diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 20:53:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 20:53:36 -0400 |
commit | 39695224bd84dc4be29abad93a0ec232a16fc519 (patch) | |
tree | 2bfa5cb50788a4c8be9f2e9f4412e47a565f4508 /drivers/scsi/fcoe | |
parent | a9bbd210a44102cc50b30a5f3d111dbf5f2f9cd4 (diff) | |
parent | ea038f63ac52439e7816295fa6064fe95e6c1f51 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (209 commits)
[SCSI] fix oops during scsi scanning
[SCSI] libsrp: fix memory leak in srp_ring_free()
[SCSI] libiscsi, bnx2i: make bound ep check common
[SCSI] libiscsi: add completion function for drivers that do not need pdu processing
[SCSI] scsi_dh_rdac: changes for rdac debug logging
[SCSI] scsi_dh_rdac: changes to collect the rdac debug information during the initialization
[SCSI] scsi_dh_rdac: move the init code from rdac_activate to rdac_bus_attach
[SCSI] sg: fix oops in the error path in sg_build_indirect()
[SCSI] mptsas : Bump version to 3.04.12
[SCSI] mptsas : FW event thread and scsi mid layer deadlock in SYNCHRONIZE CACHE command
[SCSI] mptsas : Send DID_NO_CONNECT for pending IOs of removed device
[SCSI] mptsas : PAE Kernel more than 4 GB kernel panic
[SCSI] mptsas : NULL pointer on big endian systems causing Expander not to tear off
[SCSI] mptsas : Sanity check for phyinfo is added
[SCSI] scsi_dh_rdac: Add support for Sun StorageTek ST2500, ST2510 and ST2530
[SCSI] pmcraid: PMC-Sierra MaxRAID driver to support 6Gb/s SAS RAID controller
[SCSI] qla2xxx: Update version number to 8.03.01-k6.
[SCSI] qla2xxx: Properly delete rports attached to a vport.
[SCSI] qla2xxx: Correct various NPIV issues.
[SCSI] qla2xxx: Correct qla2x00_eh_wait_on_command() to wait correctly.
...
Diffstat (limited to 'drivers/scsi/fcoe')
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 1078 | ||||
-rw-r--r-- | drivers/scsi/fcoe/fcoe.h | 36 | ||||
-rw-r--r-- | drivers/scsi/fcoe/libfcoe.c | 30 |
3 files changed, 666 insertions, 478 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 0a5609bb5817..704b8e034946 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved. | 2 | * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms and conditions of the GNU General Public License, | 5 | * under the terms and conditions of the GNU General Public License, |
@@ -49,9 +49,20 @@ MODULE_AUTHOR("Open-FCoE.org"); | |||
49 | MODULE_DESCRIPTION("FCoE"); | 49 | MODULE_DESCRIPTION("FCoE"); |
50 | MODULE_LICENSE("GPL v2"); | 50 | MODULE_LICENSE("GPL v2"); |
51 | 51 | ||
52 | /* Performance tuning parameters for fcoe */ | ||
53 | static unsigned int fcoe_ddp_min; | ||
54 | module_param_named(ddp_min, fcoe_ddp_min, uint, S_IRUGO | S_IWUSR); | ||
55 | MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for " \ | ||
56 | "Direct Data Placement (DDP)."); | ||
57 | |||
58 | DEFINE_MUTEX(fcoe_config_mutex); | ||
59 | |||
60 | /* fcoe_percpu_clean completion. Waiter protected by fcoe_create_mutex */ | ||
61 | static DECLARE_COMPLETION(fcoe_flush_completion); | ||
62 | |||
52 | /* fcoe host list */ | 63 | /* fcoe host list */ |
64 | /* must only by accessed under the RTNL mutex */ | ||
53 | LIST_HEAD(fcoe_hostlist); | 65 | LIST_HEAD(fcoe_hostlist); |
54 | DEFINE_RWLOCK(fcoe_hostlist_lock); | ||
55 | DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu); | 66 | DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu); |
56 | 67 | ||
57 | /* Function Prototypes */ | 68 | /* Function Prototypes */ |
@@ -66,12 +77,13 @@ static int fcoe_link_ok(struct fc_lport *lp); | |||
66 | 77 | ||
67 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); | 78 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); |
68 | static int fcoe_hostlist_add(const struct fc_lport *); | 79 | static int fcoe_hostlist_add(const struct fc_lport *); |
69 | static int fcoe_hostlist_remove(const struct fc_lport *); | ||
70 | 80 | ||
71 | static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *); | 81 | static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *); |
72 | static int fcoe_device_notification(struct notifier_block *, ulong, void *); | 82 | static int fcoe_device_notification(struct notifier_block *, ulong, void *); |
73 | static void fcoe_dev_setup(void); | 83 | static void fcoe_dev_setup(void); |
74 | static void fcoe_dev_cleanup(void); | 84 | static void fcoe_dev_cleanup(void); |
85 | static struct fcoe_interface * | ||
86 | fcoe_hostlist_lookup_port(const struct net_device *dev); | ||
75 | 87 | ||
76 | /* notification function from net device */ | 88 | /* notification function from net device */ |
77 | static struct notifier_block fcoe_notifier = { | 89 | static struct notifier_block fcoe_notifier = { |
@@ -132,6 +144,180 @@ static struct scsi_host_template fcoe_shost_template = { | |||
132 | .max_sectors = 0xffff, | 144 | .max_sectors = 0xffff, |
133 | }; | 145 | }; |
134 | 146 | ||
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 | /** | ||
151 | * fcoe_interface_setup() | ||
152 | * @fcoe: new fcoe_interface | ||
153 | * @netdev : ptr to the associated netdevice struct | ||
154 | * | ||
155 | * Returns : 0 for success | ||
156 | * Locking: must be called with the RTNL mutex held | ||
157 | */ | ||
158 | static int fcoe_interface_setup(struct fcoe_interface *fcoe, | ||
159 | struct net_device *netdev) | ||
160 | { | ||
161 | struct fcoe_ctlr *fip = &fcoe->ctlr; | ||
162 | struct netdev_hw_addr *ha; | ||
163 | u8 flogi_maddr[ETH_ALEN]; | ||
164 | |||
165 | fcoe->netdev = netdev; | ||
166 | |||
167 | /* Do not support for bonding device */ | ||
168 | if ((netdev->priv_flags & IFF_MASTER_ALB) || | ||
169 | (netdev->priv_flags & IFF_SLAVE_INACTIVE) || | ||
170 | (netdev->priv_flags & IFF_MASTER_8023AD)) { | ||
171 | return -EOPNOTSUPP; | ||
172 | } | ||
173 | |||
174 | /* look for SAN MAC address, if multiple SAN MACs exist, only | ||
175 | * use the first one for SPMA */ | ||
176 | rcu_read_lock(); | ||
177 | for_each_dev_addr(netdev, ha) { | ||
178 | if ((ha->type == NETDEV_HW_ADDR_T_SAN) && | ||
179 | (is_valid_ether_addr(fip->ctl_src_addr))) { | ||
180 | memcpy(fip->ctl_src_addr, ha->addr, ETH_ALEN); | ||
181 | fip->spma = 1; | ||
182 | break; | ||
183 | } | ||
184 | } | ||
185 | rcu_read_unlock(); | ||
186 | |||
187 | /* setup Source Mac Address */ | ||
188 | if (!fip->spma) | ||
189 | memcpy(fip->ctl_src_addr, netdev->dev_addr, netdev->addr_len); | ||
190 | |||
191 | /* | ||
192 | * Add FCoE MAC address as second unicast MAC address | ||
193 | * or enter promiscuous mode if not capable of listening | ||
194 | * for multiple unicast MACs. | ||
195 | */ | ||
196 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); | ||
197 | dev_unicast_add(netdev, flogi_maddr); | ||
198 | if (fip->spma) | ||
199 | dev_unicast_add(netdev, fip->ctl_src_addr); | ||
200 | dev_mc_add(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); | ||
201 | |||
202 | /* | ||
203 | * setup the receive function from ethernet driver | ||
204 | * on the ethertype for the given device | ||
205 | */ | ||
206 | fcoe->fcoe_packet_type.func = fcoe_rcv; | ||
207 | fcoe->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE); | ||
208 | fcoe->fcoe_packet_type.dev = netdev; | ||
209 | dev_add_pack(&fcoe->fcoe_packet_type); | ||
210 | |||
211 | fcoe->fip_packet_type.func = fcoe_fip_recv; | ||
212 | fcoe->fip_packet_type.type = htons(ETH_P_FIP); | ||
213 | fcoe->fip_packet_type.dev = netdev; | ||
214 | dev_add_pack(&fcoe->fip_packet_type); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
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 | /** | ||
224 | * fcoe_interface_create() | ||
225 | * @netdev: network interface | ||
226 | * | ||
227 | * Returns: pointer to a struct fcoe_interface or NULL on error | ||
228 | */ | ||
229 | static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev) | ||
230 | { | ||
231 | struct fcoe_interface *fcoe; | ||
232 | |||
233 | fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL); | ||
234 | if (!fcoe) { | ||
235 | FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n"); | ||
236 | return NULL; | ||
237 | } | ||
238 | |||
239 | dev_hold(netdev); | ||
240 | kref_init(&fcoe->kref); | ||
241 | |||
242 | /* | ||
243 | * Initialize FIP. | ||
244 | */ | ||
245 | fcoe_ctlr_init(&fcoe->ctlr); | ||
246 | fcoe->ctlr.send = fcoe_fip_send; | ||
247 | fcoe->ctlr.update_mac = fcoe_update_src_mac; | ||
248 | |||
249 | fcoe_interface_setup(fcoe, netdev); | ||
250 | |||
251 | return fcoe; | ||
252 | } | ||
253 | |||
254 | /** | ||
255 | * fcoe_interface_cleanup() - clean up netdev configurations | ||
256 | * @fcoe: | ||
257 | * | ||
258 | * Caller must be holding the RTNL mutex | ||
259 | */ | ||
260 | void fcoe_interface_cleanup(struct fcoe_interface *fcoe) | ||
261 | { | ||
262 | struct net_device *netdev = fcoe->netdev; | ||
263 | struct fcoe_ctlr *fip = &fcoe->ctlr; | ||
264 | u8 flogi_maddr[ETH_ALEN]; | ||
265 | |||
266 | /* | ||
267 | * Don't listen for Ethernet packets anymore. | ||
268 | * synchronize_net() ensures that the packet handlers are not running | ||
269 | * on another CPU. dev_remove_pack() would do that, this calls the | ||
270 | * unsyncronized version __dev_remove_pack() to avoid multiple delays. | ||
271 | */ | ||
272 | __dev_remove_pack(&fcoe->fcoe_packet_type); | ||
273 | __dev_remove_pack(&fcoe->fip_packet_type); | ||
274 | synchronize_net(); | ||
275 | |||
276 | /* Delete secondary MAC addresses */ | ||
277 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); | ||
278 | 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) | ||
282 | dev_unicast_delete(netdev, fip->ctl_src_addr); | ||
283 | dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * fcoe_interface_release() - fcoe_port kref release function | ||
288 | * @kref: embedded reference count in an fcoe_interface struct | ||
289 | */ | ||
290 | static void fcoe_interface_release(struct kref *kref) | ||
291 | { | ||
292 | struct fcoe_interface *fcoe; | ||
293 | struct net_device *netdev; | ||
294 | |||
295 | fcoe = container_of(kref, struct fcoe_interface, kref); | ||
296 | netdev = fcoe->netdev; | ||
297 | /* tear-down the FCoE controller */ | ||
298 | fcoe_ctlr_destroy(&fcoe->ctlr); | ||
299 | kfree(fcoe); | ||
300 | dev_put(netdev); | ||
301 | } | ||
302 | |||
303 | /** | ||
304 | * fcoe_interface_get() | ||
305 | * @fcoe: | ||
306 | */ | ||
307 | static inline void fcoe_interface_get(struct fcoe_interface *fcoe) | ||
308 | { | ||
309 | kref_get(&fcoe->kref); | ||
310 | } | ||
311 | |||
312 | /** | ||
313 | * fcoe_interface_put() | ||
314 | * @fcoe: | ||
315 | */ | ||
316 | static inline void fcoe_interface_put(struct fcoe_interface *fcoe) | ||
317 | { | ||
318 | kref_put(&fcoe->kref, fcoe_interface_release); | ||
319 | } | ||
320 | |||
135 | /** | 321 | /** |
136 | * fcoe_fip_recv - handle a received FIP frame. | 322 | * fcoe_fip_recv - handle a received FIP frame. |
137 | * @skb: the receive skb | 323 | * @skb: the receive skb |
@@ -145,10 +331,10 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev, | |||
145 | struct packet_type *ptype, | 331 | struct packet_type *ptype, |
146 | struct net_device *orig_dev) | 332 | struct net_device *orig_dev) |
147 | { | 333 | { |
148 | struct fcoe_softc *fc; | 334 | struct fcoe_interface *fcoe; |
149 | 335 | ||
150 | fc = container_of(ptype, struct fcoe_softc, fip_packet_type); | 336 | fcoe = container_of(ptype, struct fcoe_interface, fip_packet_type); |
151 | fcoe_ctlr_recv(&fc->ctlr, skb); | 337 | fcoe_ctlr_recv(&fcoe->ctlr, skb); |
152 | return 0; | 338 | return 0; |
153 | } | 339 | } |
154 | 340 | ||
@@ -159,7 +345,7 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev, | |||
159 | */ | 345 | */ |
160 | static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | 346 | static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) |
161 | { | 347 | { |
162 | skb->dev = fcoe_from_ctlr(fip)->real_dev; | 348 | skb->dev = fcoe_from_ctlr(fip)->netdev; |
163 | dev_queue_xmit(skb); | 349 | dev_queue_xmit(skb); |
164 | } | 350 | } |
165 | 351 | ||
@@ -174,13 +360,13 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
174 | */ | 360 | */ |
175 | static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new) | 361 | static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new) |
176 | { | 362 | { |
177 | struct fcoe_softc *fc; | 363 | struct fcoe_interface *fcoe; |
178 | 364 | ||
179 | fc = fcoe_from_ctlr(fip); | 365 | fcoe = fcoe_from_ctlr(fip); |
180 | rtnl_lock(); | 366 | rtnl_lock(); |
181 | if (!is_zero_ether_addr(old)) | 367 | if (!is_zero_ether_addr(old)) |
182 | dev_unicast_delete(fc->real_dev, old); | 368 | dev_unicast_delete(fcoe->netdev, old); |
183 | dev_unicast_add(fc->real_dev, new); | 369 | dev_unicast_add(fcoe->netdev, new); |
184 | rtnl_unlock(); | 370 | rtnl_unlock(); |
185 | } | 371 | } |
186 | 372 | ||
@@ -217,30 +403,6 @@ static int fcoe_lport_config(struct fc_lport *lp) | |||
217 | } | 403 | } |
218 | 404 | ||
219 | /** | 405 | /** |
220 | * fcoe_netdev_cleanup() - clean up netdev configurations | ||
221 | * @fc: ptr to the fcoe_softc | ||
222 | */ | ||
223 | void fcoe_netdev_cleanup(struct fcoe_softc *fc) | ||
224 | { | ||
225 | u8 flogi_maddr[ETH_ALEN]; | ||
226 | |||
227 | /* Don't listen for Ethernet packets anymore */ | ||
228 | dev_remove_pack(&fc->fcoe_packet_type); | ||
229 | dev_remove_pack(&fc->fip_packet_type); | ||
230 | |||
231 | /* Delete secondary MAC addresses */ | ||
232 | rtnl_lock(); | ||
233 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); | ||
234 | dev_unicast_delete(fc->real_dev, flogi_maddr); | ||
235 | if (!is_zero_ether_addr(fc->ctlr.data_src_addr)) | ||
236 | dev_unicast_delete(fc->real_dev, fc->ctlr.data_src_addr); | ||
237 | if (fc->ctlr.spma) | ||
238 | dev_unicast_delete(fc->real_dev, fc->ctlr.ctl_src_addr); | ||
239 | dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); | ||
240 | rtnl_unlock(); | ||
241 | } | ||
242 | |||
243 | /** | ||
244 | * fcoe_queue_timer() - fcoe queue timer | 406 | * fcoe_queue_timer() - fcoe queue timer |
245 | * @lp: the fc_lport pointer | 407 | * @lp: the fc_lport pointer |
246 | * | 408 | * |
@@ -265,116 +427,53 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) | |||
265 | { | 427 | { |
266 | u32 mfs; | 428 | u32 mfs; |
267 | u64 wwnn, wwpn; | 429 | u64 wwnn, wwpn; |
268 | struct fcoe_softc *fc; | 430 | struct fcoe_interface *fcoe; |
269 | u8 flogi_maddr[ETH_ALEN]; | 431 | struct fcoe_port *port; |
270 | struct netdev_hw_addr *ha; | ||
271 | 432 | ||
272 | /* Setup lport private data to point to fcoe softc */ | 433 | /* Setup lport private data to point to fcoe softc */ |
273 | fc = lport_priv(lp); | 434 | port = lport_priv(lp); |
274 | fc->ctlr.lp = lp; | 435 | fcoe = port->fcoe; |
275 | fc->real_dev = netdev; | ||
276 | fc->phys_dev = netdev; | ||
277 | |||
278 | /* Require support for get_pauseparam ethtool op. */ | ||
279 | if (netdev->priv_flags & IFF_802_1Q_VLAN) | ||
280 | fc->phys_dev = vlan_dev_real_dev(netdev); | ||
281 | |||
282 | /* Do not support for bonding device */ | ||
283 | if ((fc->real_dev->priv_flags & IFF_MASTER_ALB) || | ||
284 | (fc->real_dev->priv_flags & IFF_SLAVE_INACTIVE) || | ||
285 | (fc->real_dev->priv_flags & IFF_MASTER_8023AD)) { | ||
286 | return -EOPNOTSUPP; | ||
287 | } | ||
288 | 436 | ||
289 | /* | 437 | /* |
290 | * Determine max frame size based on underlying device and optional | 438 | * Determine max frame size based on underlying device and optional |
291 | * user-configured limit. If the MFS is too low, fcoe_link_ok() | 439 | * user-configured limit. If the MFS is too low, fcoe_link_ok() |
292 | * will return 0, so do this first. | 440 | * will return 0, so do this first. |
293 | */ | 441 | */ |
294 | mfs = fc->real_dev->mtu - (sizeof(struct fcoe_hdr) + | 442 | mfs = netdev->mtu - (sizeof(struct fcoe_hdr) + |
295 | sizeof(struct fcoe_crc_eof)); | 443 | sizeof(struct fcoe_crc_eof)); |
296 | if (fc_set_mfs(lp, mfs)) | 444 | if (fc_set_mfs(lp, mfs)) |
297 | return -EINVAL; | 445 | return -EINVAL; |
298 | 446 | ||
299 | /* offload features support */ | 447 | /* offload features support */ |
300 | if (fc->real_dev->features & NETIF_F_SG) | 448 | if (netdev->features & NETIF_F_SG) |
301 | lp->sg_supp = 1; | 449 | lp->sg_supp = 1; |
302 | 450 | ||
303 | #ifdef NETIF_F_FCOE_CRC | ||
304 | if (netdev->features & NETIF_F_FCOE_CRC) { | 451 | if (netdev->features & NETIF_F_FCOE_CRC) { |
305 | lp->crc_offload = 1; | 452 | lp->crc_offload = 1; |
306 | FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n"); | 453 | FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n"); |
307 | } | 454 | } |
308 | #endif | ||
309 | #ifdef NETIF_F_FSO | ||
310 | if (netdev->features & NETIF_F_FSO) { | 455 | if (netdev->features & NETIF_F_FSO) { |
311 | lp->seq_offload = 1; | 456 | lp->seq_offload = 1; |
312 | lp->lso_max = netdev->gso_max_size; | 457 | lp->lso_max = netdev->gso_max_size; |
313 | FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n", | 458 | FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n", |
314 | lp->lso_max); | 459 | lp->lso_max); |
315 | } | 460 | } |
316 | #endif | ||
317 | if (netdev->fcoe_ddp_xid) { | 461 | if (netdev->fcoe_ddp_xid) { |
318 | lp->lro_enabled = 1; | 462 | lp->lro_enabled = 1; |
319 | lp->lro_xid = netdev->fcoe_ddp_xid; | 463 | lp->lro_xid = netdev->fcoe_ddp_xid; |
320 | FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n", | 464 | FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n", |
321 | lp->lro_xid); | 465 | lp->lro_xid); |
322 | } | 466 | } |
323 | skb_queue_head_init(&fc->fcoe_pending_queue); | 467 | skb_queue_head_init(&port->fcoe_pending_queue); |
324 | fc->fcoe_pending_queue_active = 0; | 468 | port->fcoe_pending_queue_active = 0; |
325 | setup_timer(&fc->timer, fcoe_queue_timer, (unsigned long)lp); | 469 | setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lp); |
326 | |||
327 | /* look for SAN MAC address, if multiple SAN MACs exist, only | ||
328 | * use the first one for SPMA */ | ||
329 | rcu_read_lock(); | ||
330 | for_each_dev_addr(netdev, ha) { | ||
331 | if ((ha->type == NETDEV_HW_ADDR_T_SAN) && | ||
332 | (is_valid_ether_addr(fc->ctlr.ctl_src_addr))) { | ||
333 | memcpy(fc->ctlr.ctl_src_addr, ha->addr, ETH_ALEN); | ||
334 | fc->ctlr.spma = 1; | ||
335 | break; | ||
336 | } | ||
337 | } | ||
338 | rcu_read_unlock(); | ||
339 | |||
340 | /* setup Source Mac Address */ | ||
341 | if (!fc->ctlr.spma) | ||
342 | memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr, | ||
343 | fc->real_dev->addr_len); | ||
344 | 470 | ||
345 | wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0); | 471 | wwnn = fcoe_wwn_from_mac(netdev->dev_addr, 1, 0); |
346 | fc_set_wwnn(lp, wwnn); | 472 | fc_set_wwnn(lp, wwnn); |
347 | /* XXX - 3rd arg needs to be vlan id */ | 473 | /* XXX - 3rd arg needs to be vlan id */ |
348 | wwpn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 2, 0); | 474 | wwpn = fcoe_wwn_from_mac(netdev->dev_addr, 2, 0); |
349 | fc_set_wwpn(lp, wwpn); | 475 | fc_set_wwpn(lp, wwpn); |
350 | 476 | ||
351 | /* | ||
352 | * Add FCoE MAC address as second unicast MAC address | ||
353 | * or enter promiscuous mode if not capable of listening | ||
354 | * for multiple unicast MACs. | ||
355 | */ | ||
356 | rtnl_lock(); | ||
357 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); | ||
358 | dev_unicast_add(fc->real_dev, flogi_maddr); | ||
359 | if (fc->ctlr.spma) | ||
360 | dev_unicast_add(fc->real_dev, fc->ctlr.ctl_src_addr); | ||
361 | dev_mc_add(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); | ||
362 | rtnl_unlock(); | ||
363 | |||
364 | /* | ||
365 | * setup the receive function from ethernet driver | ||
366 | * on the ethertype for the given device | ||
367 | */ | ||
368 | fc->fcoe_packet_type.func = fcoe_rcv; | ||
369 | fc->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE); | ||
370 | fc->fcoe_packet_type.dev = fc->real_dev; | ||
371 | dev_add_pack(&fc->fcoe_packet_type); | ||
372 | |||
373 | fc->fip_packet_type.func = fcoe_fip_recv; | ||
374 | fc->fip_packet_type.type = htons(ETH_P_FIP); | ||
375 | fc->fip_packet_type.dev = fc->real_dev; | ||
376 | dev_add_pack(&fc->fip_packet_type); | ||
377 | |||
378 | return 0; | 477 | return 0; |
379 | } | 478 | } |
380 | 479 | ||
@@ -415,86 +514,140 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, | |||
415 | return 0; | 514 | return 0; |
416 | } | 515 | } |
417 | 516 | ||
517 | /* | ||
518 | * fcoe_oem_match() - match for read types IO | ||
519 | * @fp: the fc_frame for new IO. | ||
520 | * | ||
521 | * Returns : true for read types IO, otherwise returns false. | ||
522 | */ | ||
523 | bool fcoe_oem_match(struct fc_frame *fp) | ||
524 | { | ||
525 | return fc_fcp_is_read(fr_fsp(fp)) && | ||
526 | (fr_fsp(fp)->data_len > fcoe_ddp_min); | ||
527 | } | ||
528 | |||
418 | /** | 529 | /** |
419 | * fcoe_em_config() - allocates em for this lport | 530 | * fcoe_em_config() - allocates em for this lport |
420 | * @lp: the port that em is to allocated for | 531 | * @lp: the fcoe that em is to allocated for |
421 | * | 532 | * |
422 | * Returns : 0 on success | 533 | * Returns : 0 on success |
423 | */ | 534 | */ |
424 | static inline int fcoe_em_config(struct fc_lport *lp) | 535 | static inline int fcoe_em_config(struct fc_lport *lp) |
425 | { | 536 | { |
426 | BUG_ON(lp->emp); | 537 | struct fcoe_port *port = lport_priv(lp); |
538 | struct fcoe_interface *fcoe = port->fcoe; | ||
539 | struct fcoe_interface *oldfcoe = NULL; | ||
540 | struct net_device *old_real_dev, *cur_real_dev; | ||
541 | u16 min_xid = FCOE_MIN_XID; | ||
542 | u16 max_xid = FCOE_MAX_XID; | ||
427 | 543 | ||
428 | lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3, | 544 | /* |
429 | FCOE_MIN_XID, FCOE_MAX_XID); | 545 | * Check if need to allocate an em instance for |
430 | if (!lp->emp) | 546 | * offload exchange ids to be shared across all VN_PORTs/lport. |
547 | */ | ||
548 | if (!lp->lro_enabled || !lp->lro_xid || (lp->lro_xid >= max_xid)) { | ||
549 | lp->lro_xid = 0; | ||
550 | goto skip_oem; | ||
551 | } | ||
552 | |||
553 | /* | ||
554 | * Reuse existing offload em instance in case | ||
555 | * it is already allocated on real eth device | ||
556 | */ | ||
557 | if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN) | ||
558 | cur_real_dev = vlan_dev_real_dev(fcoe->netdev); | ||
559 | else | ||
560 | cur_real_dev = fcoe->netdev; | ||
561 | |||
562 | list_for_each_entry(oldfcoe, &fcoe_hostlist, list) { | ||
563 | if (oldfcoe->netdev->priv_flags & IFF_802_1Q_VLAN) | ||
564 | old_real_dev = vlan_dev_real_dev(oldfcoe->netdev); | ||
565 | else | ||
566 | old_real_dev = oldfcoe->netdev; | ||
567 | |||
568 | if (cur_real_dev == old_real_dev) { | ||
569 | fcoe->oem = oldfcoe->oem; | ||
570 | break; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | if (fcoe->oem) { | ||
575 | if (!fc_exch_mgr_add(lp, fcoe->oem, fcoe_oem_match)) { | ||
576 | printk(KERN_ERR "fcoe_em_config: failed to add " | ||
577 | "offload em:%p on interface:%s\n", | ||
578 | fcoe->oem, fcoe->netdev->name); | ||
579 | return -ENOMEM; | ||
580 | } | ||
581 | } else { | ||
582 | fcoe->oem = fc_exch_mgr_alloc(lp, FC_CLASS_3, | ||
583 | FCOE_MIN_XID, lp->lro_xid, | ||
584 | fcoe_oem_match); | ||
585 | if (!fcoe->oem) { | ||
586 | printk(KERN_ERR "fcoe_em_config: failed to allocate " | ||
587 | "em for offload exches on interface:%s\n", | ||
588 | fcoe->netdev->name); | ||
589 | return -ENOMEM; | ||
590 | } | ||
591 | } | ||
592 | |||
593 | /* | ||
594 | * Exclude offload EM xid range from next EM xid range. | ||
595 | */ | ||
596 | min_xid += lp->lro_xid + 1; | ||
597 | |||
598 | skip_oem: | ||
599 | if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, min_xid, max_xid, NULL)) { | ||
600 | printk(KERN_ERR "fcoe_em_config: failed to " | ||
601 | "allocate em on interface %s\n", fcoe->netdev->name); | ||
431 | return -ENOMEM; | 602 | return -ENOMEM; |
603 | } | ||
432 | 604 | ||
433 | return 0; | 605 | return 0; |
434 | } | 606 | } |
435 | 607 | ||
436 | /** | 608 | /** |
437 | * fcoe_if_destroy() - FCoE software HBA tear-down function | 609 | * fcoe_if_destroy() - FCoE software HBA tear-down function |
438 | * @netdev: ptr to the associated net_device | 610 | * @lport: fc_lport to destroy |
439 | * | ||
440 | * Returns: 0 if link is OK for use by FCoE. | ||
441 | */ | 611 | */ |
442 | static int fcoe_if_destroy(struct net_device *netdev) | 612 | static void fcoe_if_destroy(struct fc_lport *lport) |
443 | { | 613 | { |
444 | struct fc_lport *lp = NULL; | 614 | struct fcoe_port *port = lport_priv(lport); |
445 | struct fcoe_softc *fc; | 615 | struct fcoe_interface *fcoe = port->fcoe; |
446 | 616 | struct net_device *netdev = fcoe->netdev; | |
447 | BUG_ON(!netdev); | ||
448 | 617 | ||
449 | FCOE_NETDEV_DBG(netdev, "Destroying interface\n"); | 618 | FCOE_NETDEV_DBG(netdev, "Destroying interface\n"); |
450 | 619 | ||
451 | lp = fcoe_hostlist_lookup(netdev); | ||
452 | if (!lp) | ||
453 | return -ENODEV; | ||
454 | |||
455 | fc = lport_priv(lp); | ||
456 | |||
457 | /* Logout of the fabric */ | 620 | /* Logout of the fabric */ |
458 | fc_fabric_logoff(lp); | 621 | fc_fabric_logoff(lport); |
459 | 622 | ||
460 | /* Remove the instance from fcoe's list */ | 623 | /* Cleanup the fc_lport */ |
461 | fcoe_hostlist_remove(lp); | 624 | fc_lport_destroy(lport); |
625 | fc_fcp_destroy(lport); | ||
462 | 626 | ||
463 | /* clean up netdev configurations */ | 627 | /* Stop the transmit retry timer */ |
464 | fcoe_netdev_cleanup(fc); | 628 | del_timer_sync(&port->timer); |
465 | 629 | ||
466 | /* tear-down the FCoE controller */ | 630 | /* Free existing transmit skbs */ |
467 | fcoe_ctlr_destroy(&fc->ctlr); | 631 | fcoe_clean_pending_queue(lport); |
468 | 632 | ||
469 | /* Cleanup the fc_lport */ | 633 | /* receives may not be stopped until after this */ |
470 | fc_lport_destroy(lp); | 634 | fcoe_interface_put(fcoe); |
471 | fc_fcp_destroy(lp); | 635 | |
636 | /* Free queued packets for the per-CPU receive threads */ | ||
637 | fcoe_percpu_clean(lport); | ||
472 | 638 | ||
473 | /* Detach from the scsi-ml */ | 639 | /* Detach from the scsi-ml */ |
474 | fc_remove_host(lp->host); | 640 | fc_remove_host(lport->host); |
475 | scsi_remove_host(lp->host); | 641 | scsi_remove_host(lport->host); |
476 | 642 | ||
477 | /* There are no more rports or I/O, free the EM */ | 643 | /* There are no more rports or I/O, free the EM */ |
478 | if (lp->emp) | 644 | fc_exch_mgr_free(lport); |
479 | fc_exch_mgr_free(lp->emp); | ||
480 | |||
481 | /* Free the per-CPU receive threads */ | ||
482 | fcoe_percpu_clean(lp); | ||
483 | |||
484 | /* Free existing skbs */ | ||
485 | fcoe_clean_pending_queue(lp); | ||
486 | |||
487 | /* Stop the timer */ | ||
488 | del_timer_sync(&fc->timer); | ||
489 | 645 | ||
490 | /* Free memory used by statistical counters */ | 646 | /* Free memory used by statistical counters */ |
491 | fc_lport_free_stats(lp); | 647 | fc_lport_free_stats(lport); |
492 | |||
493 | /* Release the net_device and Scsi_Host */ | ||
494 | dev_put(fc->real_dev); | ||
495 | scsi_host_put(lp->host); | ||
496 | 648 | ||
497 | return 0; | 649 | /* Release the Scsi_Host */ |
650 | scsi_host_put(lport->host); | ||
498 | } | 651 | } |
499 | 652 | ||
500 | /* | 653 | /* |
@@ -540,106 +693,96 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = { | |||
540 | }; | 693 | }; |
541 | 694 | ||
542 | /** | 695 | /** |
543 | * fcoe_if_create() - this function creates the fcoe interface | 696 | * fcoe_if_create() - this function creates the fcoe port |
544 | * @netdev: pointer the associated netdevice | 697 | * @fcoe: fcoe_interface structure to create an fc_lport instance on |
698 | * @parent: device pointer to be the parent in sysfs for the SCSI host | ||
545 | * | 699 | * |
546 | * Creates fc_lport struct and scsi_host for lport, configures lport | 700 | * Creates fc_lport struct and scsi_host for lport, configures lport. |
547 | * and starts fabric login. | ||
548 | * | 701 | * |
549 | * Returns : 0 on success | 702 | * Returns : The allocated fc_lport or an error pointer |
550 | */ | 703 | */ |
551 | static int fcoe_if_create(struct net_device *netdev) | 704 | static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, |
705 | struct device *parent) | ||
552 | { | 706 | { |
553 | int rc; | 707 | int rc; |
554 | struct fc_lport *lp = NULL; | 708 | struct fc_lport *lport = NULL; |
555 | struct fcoe_softc *fc; | 709 | struct fcoe_port *port; |
556 | struct Scsi_Host *shost; | 710 | struct Scsi_Host *shost; |
557 | 711 | struct net_device *netdev = fcoe->netdev; | |
558 | BUG_ON(!netdev); | ||
559 | 712 | ||
560 | FCOE_NETDEV_DBG(netdev, "Create Interface\n"); | 713 | FCOE_NETDEV_DBG(netdev, "Create Interface\n"); |
561 | 714 | ||
562 | lp = fcoe_hostlist_lookup(netdev); | ||
563 | if (lp) | ||
564 | return -EEXIST; | ||
565 | |||
566 | shost = libfc_host_alloc(&fcoe_shost_template, | 715 | shost = libfc_host_alloc(&fcoe_shost_template, |
567 | sizeof(struct fcoe_softc)); | 716 | sizeof(struct fcoe_port)); |
568 | if (!shost) { | 717 | if (!shost) { |
569 | FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n"); | 718 | FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n"); |
570 | return -ENOMEM; | 719 | rc = -ENOMEM; |
720 | goto out; | ||
571 | } | 721 | } |
572 | lp = shost_priv(shost); | 722 | lport = shost_priv(shost); |
573 | fc = lport_priv(lp); | 723 | port = lport_priv(lport); |
724 | port->lport = lport; | ||
725 | port->fcoe = fcoe; | ||
726 | INIT_WORK(&port->destroy_work, fcoe_destroy_work); | ||
574 | 727 | ||
575 | /* configure fc_lport, e.g., em */ | 728 | /* configure fc_lport, e.g., em */ |
576 | rc = fcoe_lport_config(lp); | 729 | rc = fcoe_lport_config(lport); |
577 | if (rc) { | 730 | if (rc) { |
578 | FCOE_NETDEV_DBG(netdev, "Could not configure lport for the " | 731 | FCOE_NETDEV_DBG(netdev, "Could not configure lport for the " |
579 | "interface\n"); | 732 | "interface\n"); |
580 | goto out_host_put; | 733 | goto out_host_put; |
581 | } | 734 | } |
582 | 735 | ||
583 | /* | ||
584 | * Initialize FIP. | ||
585 | */ | ||
586 | fcoe_ctlr_init(&fc->ctlr); | ||
587 | fc->ctlr.send = fcoe_fip_send; | ||
588 | fc->ctlr.update_mac = fcoe_update_src_mac; | ||
589 | |||
590 | /* configure lport network properties */ | 736 | /* configure lport network properties */ |
591 | rc = fcoe_netdev_config(lp, netdev); | 737 | rc = fcoe_netdev_config(lport, netdev); |
592 | if (rc) { | 738 | if (rc) { |
593 | FCOE_NETDEV_DBG(netdev, "Could not configure netdev for the " | 739 | FCOE_NETDEV_DBG(netdev, "Could not configure netdev for the " |
594 | "interface\n"); | 740 | "interface\n"); |
595 | goto out_netdev_cleanup; | 741 | goto out_lp_destroy; |
596 | } | 742 | } |
597 | 743 | ||
598 | /* configure lport scsi host properties */ | 744 | /* configure lport scsi host properties */ |
599 | rc = fcoe_shost_config(lp, shost, &netdev->dev); | 745 | rc = fcoe_shost_config(lport, shost, parent); |
600 | if (rc) { | 746 | if (rc) { |
601 | FCOE_NETDEV_DBG(netdev, "Could not configure shost for the " | 747 | FCOE_NETDEV_DBG(netdev, "Could not configure shost for the " |
602 | "interface\n"); | 748 | "interface\n"); |
603 | goto out_netdev_cleanup; | 749 | goto out_lp_destroy; |
604 | } | ||
605 | |||
606 | /* lport exch manager allocation */ | ||
607 | rc = fcoe_em_config(lp); | ||
608 | if (rc) { | ||
609 | FCOE_NETDEV_DBG(netdev, "Could not configure the EM for the " | ||
610 | "interface\n"); | ||
611 | goto out_netdev_cleanup; | ||
612 | } | 750 | } |
613 | 751 | ||
614 | /* Initialize the library */ | 752 | /* Initialize the library */ |
615 | rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ); | 753 | rc = fcoe_libfc_config(lport, &fcoe_libfc_fcn_templ); |
616 | if (rc) { | 754 | if (rc) { |
617 | FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the " | 755 | FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the " |
618 | "interface\n"); | 756 | "interface\n"); |
619 | goto out_lp_destroy; | 757 | goto out_lp_destroy; |
620 | } | 758 | } |
621 | 759 | ||
622 | /* add to lports list */ | 760 | /* |
623 | fcoe_hostlist_add(lp); | 761 | * fcoe_em_alloc() and fcoe_hostlist_add() both |
624 | 762 | * need to be atomic with respect to other changes to the hostlist | |
625 | lp->boot_time = jiffies; | 763 | * since fcoe_em_alloc() looks for an existing EM |
626 | 764 | * instance on host list updated by fcoe_hostlist_add(). | |
627 | fc_fabric_login(lp); | 765 | * |
628 | 766 | * This is currently handled through the fcoe_config_mutex begin held. | |
629 | if (!fcoe_link_ok(lp)) | 767 | */ |
630 | fcoe_ctlr_link_up(&fc->ctlr); | ||
631 | 768 | ||
632 | dev_hold(netdev); | 769 | /* lport exch manager allocation */ |
770 | rc = fcoe_em_config(lport); | ||
771 | if (rc) { | ||
772 | FCOE_NETDEV_DBG(netdev, "Could not configure the EM for the " | ||
773 | "interface\n"); | ||
774 | goto out_lp_destroy; | ||
775 | } | ||
633 | 776 | ||
634 | return rc; | 777 | fcoe_interface_get(fcoe); |
778 | return lport; | ||
635 | 779 | ||
636 | out_lp_destroy: | 780 | out_lp_destroy: |
637 | fc_exch_mgr_free(lp->emp); /* Free the EM */ | 781 | fc_exch_mgr_free(lport); |
638 | out_netdev_cleanup: | ||
639 | fcoe_netdev_cleanup(fc); | ||
640 | out_host_put: | 782 | out_host_put: |
641 | scsi_host_put(lp->host); | 783 | scsi_host_put(lport->host); |
642 | return rc; | 784 | out: |
785 | return ERR_PTR(rc); | ||
643 | } | 786 | } |
644 | 787 | ||
645 | /** | 788 | /** |
@@ -669,6 +812,7 @@ static int __init fcoe_if_init(void) | |||
669 | int __exit fcoe_if_exit(void) | 812 | int __exit fcoe_if_exit(void) |
670 | { | 813 | { |
671 | fc_release_transport(scsi_transport_fcoe_sw); | 814 | fc_release_transport(scsi_transport_fcoe_sw); |
815 | scsi_transport_fcoe_sw = NULL; | ||
672 | return 0; | 816 | return 0; |
673 | } | 817 | } |
674 | 818 | ||
@@ -686,7 +830,7 @@ static void fcoe_percpu_thread_create(unsigned int cpu) | |||
686 | thread = kthread_create(fcoe_percpu_receive_thread, | 830 | thread = kthread_create(fcoe_percpu_receive_thread, |
687 | (void *)p, "fcoethread/%d", cpu); | 831 | (void *)p, "fcoethread/%d", cpu); |
688 | 832 | ||
689 | if (likely(!IS_ERR(p->thread))) { | 833 | if (likely(!IS_ERR(thread))) { |
690 | kthread_bind(thread, cpu); | 834 | kthread_bind(thread, cpu); |
691 | wake_up_process(thread); | 835 | wake_up_process(thread); |
692 | 836 | ||
@@ -838,14 +982,13 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, | |||
838 | { | 982 | { |
839 | struct fc_lport *lp; | 983 | struct fc_lport *lp; |
840 | struct fcoe_rcv_info *fr; | 984 | struct fcoe_rcv_info *fr; |
841 | struct fcoe_softc *fc; | 985 | struct fcoe_interface *fcoe; |
842 | struct fc_frame_header *fh; | 986 | struct fc_frame_header *fh; |
843 | struct fcoe_percpu_s *fps; | 987 | struct fcoe_percpu_s *fps; |
844 | unsigned short oxid; | 988 | unsigned int cpu; |
845 | unsigned int cpu = 0; | ||
846 | 989 | ||
847 | fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type); | 990 | fcoe = container_of(ptype, struct fcoe_interface, fcoe_packet_type); |
848 | lp = fc->ctlr.lp; | 991 | lp = fcoe->ctlr.lp; |
849 | if (unlikely(lp == NULL)) { | 992 | if (unlikely(lp == NULL)) { |
850 | FCOE_NETDEV_DBG(dev, "Cannot find hba structure"); | 993 | FCOE_NETDEV_DBG(dev, "Cannot find hba structure"); |
851 | goto err2; | 994 | goto err2; |
@@ -876,20 +1019,20 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, | |||
876 | skb_set_transport_header(skb, sizeof(struct fcoe_hdr)); | 1019 | skb_set_transport_header(skb, sizeof(struct fcoe_hdr)); |
877 | fh = (struct fc_frame_header *) skb_transport_header(skb); | 1020 | fh = (struct fc_frame_header *) skb_transport_header(skb); |
878 | 1021 | ||
879 | oxid = ntohs(fh->fh_ox_id); | ||
880 | |||
881 | fr = fcoe_dev_from_skb(skb); | 1022 | fr = fcoe_dev_from_skb(skb); |
882 | fr->fr_dev = lp; | 1023 | fr->fr_dev = lp; |
883 | fr->ptype = ptype; | 1024 | fr->ptype = ptype; |
884 | 1025 | ||
885 | #ifdef CONFIG_SMP | ||
886 | /* | 1026 | /* |
887 | * The incoming frame exchange id(oxid) is ANDed with num of online | 1027 | * In case the incoming frame's exchange is originated from |
888 | * cpu bits to get cpu and then this cpu is used for selecting | 1028 | * the initiator, then received frame's exchange id is ANDed |
889 | * a per cpu kernel thread from fcoe_percpu. | 1029 | * with fc_cpu_mask bits to get the same cpu on which exchange |
1030 | * was originated, otherwise just use the current cpu. | ||
890 | */ | 1031 | */ |
891 | cpu = oxid & (num_online_cpus() - 1); | 1032 | if (ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX) |
892 | #endif | 1033 | cpu = ntohs(fh->fh_ox_id) & fc_cpu_mask; |
1034 | else | ||
1035 | cpu = smp_processor_id(); | ||
893 | 1036 | ||
894 | fps = &per_cpu(fcoe_percpu, cpu); | 1037 | fps = &per_cpu(fcoe_percpu, cpu); |
895 | spin_lock_bh(&fps->fcoe_rx_list.lock); | 1038 | spin_lock_bh(&fps->fcoe_rx_list.lock); |
@@ -996,7 +1139,7 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) | |||
996 | * fcoe_fc_crc() - calculates FC CRC in this fcoe skb | 1139 | * fcoe_fc_crc() - calculates FC CRC in this fcoe skb |
997 | * @fp: the fc_frame containing data to be checksummed | 1140 | * @fp: the fc_frame containing data to be checksummed |
998 | * | 1141 | * |
999 | * This uses crc32() to calculate the crc for fc frame | 1142 | * This uses crc32() to calculate the crc for port frame |
1000 | * Return : 32 bit crc | 1143 | * Return : 32 bit crc |
1001 | */ | 1144 | */ |
1002 | u32 fcoe_fc_crc(struct fc_frame *fp) | 1145 | u32 fcoe_fc_crc(struct fc_frame *fp) |
@@ -1029,7 +1172,7 @@ u32 fcoe_fc_crc(struct fc_frame *fp) | |||
1029 | 1172 | ||
1030 | /** | 1173 | /** |
1031 | * fcoe_xmit() - FCoE frame transmit function | 1174 | * fcoe_xmit() - FCoE frame transmit function |
1032 | * @lp: the associated local port | 1175 | * @lp: the associated local fcoe |
1033 | * @fp: the fc_frame to be transmitted | 1176 | * @fp: the fc_frame to be transmitted |
1034 | * | 1177 | * |
1035 | * Return : 0 for success | 1178 | * Return : 0 for success |
@@ -1046,13 +1189,13 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1046 | unsigned int hlen; /* header length implies the version */ | 1189 | unsigned int hlen; /* header length implies the version */ |
1047 | unsigned int tlen; /* trailer length */ | 1190 | unsigned int tlen; /* trailer length */ |
1048 | unsigned int elen; /* eth header, may include vlan */ | 1191 | unsigned int elen; /* eth header, may include vlan */ |
1049 | struct fcoe_softc *fc; | 1192 | struct fcoe_port *port = lport_priv(lp); |
1193 | struct fcoe_interface *fcoe = port->fcoe; | ||
1050 | u8 sof, eof; | 1194 | u8 sof, eof; |
1051 | struct fcoe_hdr *hp; | 1195 | struct fcoe_hdr *hp; |
1052 | 1196 | ||
1053 | WARN_ON((fr_len(fp) % sizeof(u32)) != 0); | 1197 | WARN_ON((fr_len(fp) % sizeof(u32)) != 0); |
1054 | 1198 | ||
1055 | fc = lport_priv(lp); | ||
1056 | fh = fc_frame_header_get(fp); | 1199 | fh = fc_frame_header_get(fp); |
1057 | skb = fp_skb(fp); | 1200 | skb = fp_skb(fp); |
1058 | wlen = skb->len / FCOE_WORD_TO_BYTE; | 1201 | wlen = skb->len / FCOE_WORD_TO_BYTE; |
@@ -1063,7 +1206,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1063 | } | 1206 | } |
1064 | 1207 | ||
1065 | if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && | 1208 | if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && |
1066 | fcoe_ctlr_els_send(&fc->ctlr, skb)) | 1209 | fcoe_ctlr_els_send(&fcoe->ctlr, skb)) |
1067 | return 0; | 1210 | return 0; |
1068 | 1211 | ||
1069 | sof = fr_sof(fp); | 1212 | sof = fr_sof(fp); |
@@ -1085,7 +1228,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1085 | crc = fcoe_fc_crc(fp); | 1228 | crc = fcoe_fc_crc(fp); |
1086 | } | 1229 | } |
1087 | 1230 | ||
1088 | /* copy fc crc and eof to the skb buff */ | 1231 | /* copy port crc and eof to the skb buff */ |
1089 | if (skb_is_nonlinear(skb)) { | 1232 | if (skb_is_nonlinear(skb)) { |
1090 | skb_frag_t *frag; | 1233 | skb_frag_t *frag; |
1091 | if (fcoe_get_paged_crc_eof(skb, tlen)) { | 1234 | if (fcoe_get_paged_crc_eof(skb, tlen)) { |
@@ -1108,27 +1251,27 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1108 | cp = NULL; | 1251 | cp = NULL; |
1109 | } | 1252 | } |
1110 | 1253 | ||
1111 | /* adjust skb network/transport offsets to match mac/fcoe/fc */ | 1254 | /* adjust skb network/transport offsets to match mac/fcoe/port */ |
1112 | skb_push(skb, elen + hlen); | 1255 | skb_push(skb, elen + hlen); |
1113 | skb_reset_mac_header(skb); | 1256 | skb_reset_mac_header(skb); |
1114 | skb_reset_network_header(skb); | 1257 | skb_reset_network_header(skb); |
1115 | skb->mac_len = elen; | 1258 | skb->mac_len = elen; |
1116 | skb->protocol = htons(ETH_P_FCOE); | 1259 | skb->protocol = htons(ETH_P_FCOE); |
1117 | skb->dev = fc->real_dev; | 1260 | skb->dev = fcoe->netdev; |
1118 | 1261 | ||
1119 | /* fill up mac and fcoe headers */ | 1262 | /* fill up mac and fcoe headers */ |
1120 | eh = eth_hdr(skb); | 1263 | eh = eth_hdr(skb); |
1121 | eh->h_proto = htons(ETH_P_FCOE); | 1264 | eh->h_proto = htons(ETH_P_FCOE); |
1122 | if (fc->ctlr.map_dest) | 1265 | if (fcoe->ctlr.map_dest) |
1123 | fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id); | 1266 | fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id); |
1124 | else | 1267 | else |
1125 | /* insert GW address */ | 1268 | /* insert GW address */ |
1126 | memcpy(eh->h_dest, fc->ctlr.dest_addr, ETH_ALEN); | 1269 | memcpy(eh->h_dest, fcoe->ctlr.dest_addr, ETH_ALEN); |
1127 | 1270 | ||
1128 | if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN)) | 1271 | if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN)) |
1129 | memcpy(eh->h_source, fc->ctlr.ctl_src_addr, ETH_ALEN); | 1272 | memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN); |
1130 | else | 1273 | else |
1131 | memcpy(eh->h_source, fc->ctlr.data_src_addr, ETH_ALEN); | 1274 | memcpy(eh->h_source, fcoe->ctlr.data_src_addr, ETH_ALEN); |
1132 | 1275 | ||
1133 | hp = (struct fcoe_hdr *)(eh + 1); | 1276 | hp = (struct fcoe_hdr *)(eh + 1); |
1134 | memset(hp, 0, sizeof(*hp)); | 1277 | memset(hp, 0, sizeof(*hp)); |
@@ -1136,7 +1279,6 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1136 | FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER); | 1279 | FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER); |
1137 | hp->fcoe_sof = sof; | 1280 | hp->fcoe_sof = sof; |
1138 | 1281 | ||
1139 | #ifdef NETIF_F_FSO | ||
1140 | /* fcoe lso, mss is in max_payload which is non-zero for FCP data */ | 1282 | /* fcoe lso, mss is in max_payload which is non-zero for FCP data */ |
1141 | if (lp->seq_offload && fr_max_payload(fp)) { | 1283 | if (lp->seq_offload && fr_max_payload(fp)) { |
1142 | skb_shinfo(skb)->gso_type = SKB_GSO_FCOE; | 1284 | skb_shinfo(skb)->gso_type = SKB_GSO_FCOE; |
@@ -1145,7 +1287,6 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1145 | skb_shinfo(skb)->gso_type = 0; | 1287 | skb_shinfo(skb)->gso_type = 0; |
1146 | skb_shinfo(skb)->gso_size = 0; | 1288 | skb_shinfo(skb)->gso_size = 0; |
1147 | } | 1289 | } |
1148 | #endif | ||
1149 | /* update tx stats: regardless if LLD fails */ | 1290 | /* update tx stats: regardless if LLD fails */ |
1150 | stats = fc_lport_get_stats(lp); | 1291 | stats = fc_lport_get_stats(lp); |
1151 | stats->TxFrames++; | 1292 | stats->TxFrames++; |
@@ -1153,7 +1294,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1153 | 1294 | ||
1154 | /* send down to lld */ | 1295 | /* send down to lld */ |
1155 | fr_dev(fp) = lp; | 1296 | fr_dev(fp) = lp; |
1156 | if (fc->fcoe_pending_queue.qlen) | 1297 | if (port->fcoe_pending_queue.qlen) |
1157 | fcoe_check_wait_queue(lp, skb); | 1298 | fcoe_check_wait_queue(lp, skb); |
1158 | else if (fcoe_start_io(skb)) | 1299 | else if (fcoe_start_io(skb)) |
1159 | fcoe_check_wait_queue(lp, skb); | 1300 | fcoe_check_wait_queue(lp, skb); |
@@ -1162,6 +1303,15 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1162 | } | 1303 | } |
1163 | 1304 | ||
1164 | /** | 1305 | /** |
1306 | * fcoe_percpu_flush_done() - Indicate percpu queue flush completion. | ||
1307 | * @skb: the skb being completed. | ||
1308 | */ | ||
1309 | static void fcoe_percpu_flush_done(struct sk_buff *skb) | ||
1310 | { | ||
1311 | complete(&fcoe_flush_completion); | ||
1312 | } | ||
1313 | |||
1314 | /** | ||
1165 | * fcoe_percpu_receive_thread() - recv thread per cpu | 1315 | * fcoe_percpu_receive_thread() - recv thread per cpu |
1166 | * @arg: ptr to the fcoe per cpu struct | 1316 | * @arg: ptr to the fcoe per cpu struct |
1167 | * | 1317 | * |
@@ -1179,7 +1329,7 @@ int fcoe_percpu_receive_thread(void *arg) | |||
1179 | struct fcoe_crc_eof crc_eof; | 1329 | struct fcoe_crc_eof crc_eof; |
1180 | struct fc_frame *fp; | 1330 | struct fc_frame *fp; |
1181 | u8 *mac = NULL; | 1331 | u8 *mac = NULL; |
1182 | struct fcoe_softc *fc; | 1332 | struct fcoe_port *port; |
1183 | struct fcoe_hdr *hp; | 1333 | struct fcoe_hdr *hp; |
1184 | 1334 | ||
1185 | set_user_nice(current, -20); | 1335 | set_user_nice(current, -20); |
@@ -1200,7 +1350,8 @@ int fcoe_percpu_receive_thread(void *arg) | |||
1200 | fr = fcoe_dev_from_skb(skb); | 1350 | fr = fcoe_dev_from_skb(skb); |
1201 | lp = fr->fr_dev; | 1351 | lp = fr->fr_dev; |
1202 | if (unlikely(lp == NULL)) { | 1352 | if (unlikely(lp == NULL)) { |
1203 | FCOE_NETDEV_DBG(skb->dev, "Invalid HBA Structure"); | 1353 | if (skb->destructor != fcoe_percpu_flush_done) |
1354 | FCOE_NETDEV_DBG(skb->dev, "NULL lport in skb"); | ||
1204 | kfree_skb(skb); | 1355 | kfree_skb(skb); |
1205 | continue; | 1356 | continue; |
1206 | } | 1357 | } |
@@ -1215,7 +1366,7 @@ int fcoe_percpu_receive_thread(void *arg) | |||
1215 | /* | 1366 | /* |
1216 | * Save source MAC address before discarding header. | 1367 | * Save source MAC address before discarding header. |
1217 | */ | 1368 | */ |
1218 | fc = lport_priv(lp); | 1369 | port = lport_priv(lp); |
1219 | if (skb_is_nonlinear(skb)) | 1370 | if (skb_is_nonlinear(skb)) |
1220 | skb_linearize(skb); /* not ideal */ | 1371 | skb_linearize(skb); /* not ideal */ |
1221 | mac = eth_hdr(skb)->h_source; | 1372 | mac = eth_hdr(skb)->h_source; |
@@ -1277,7 +1428,7 @@ int fcoe_percpu_receive_thread(void *arg) | |||
1277 | fh = fc_frame_header_get(fp); | 1428 | fh = fc_frame_header_get(fp); |
1278 | if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && | 1429 | if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && |
1279 | fh->fh_type == FC_TYPE_FCP) { | 1430 | fh->fh_type == FC_TYPE_FCP) { |
1280 | fc_exch_recv(lp, lp->emp, fp); | 1431 | fc_exch_recv(lp, fp); |
1281 | continue; | 1432 | continue; |
1282 | } | 1433 | } |
1283 | if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) { | 1434 | if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) { |
@@ -1293,12 +1444,12 @@ int fcoe_percpu_receive_thread(void *arg) | |||
1293 | } | 1444 | } |
1294 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; | 1445 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; |
1295 | } | 1446 | } |
1296 | if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN) && | 1447 | if (unlikely(port->fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN) && |
1297 | fcoe_ctlr_recv_flogi(&fc->ctlr, fp, mac)) { | 1448 | fcoe_ctlr_recv_flogi(&port->fcoe->ctlr, fp, mac)) { |
1298 | fc_frame_free(fp); | 1449 | fc_frame_free(fp); |
1299 | continue; | 1450 | continue; |
1300 | } | 1451 | } |
1301 | fc_exch_recv(lp, lp->emp, fp); | 1452 | fc_exch_recv(lp, fp); |
1302 | } | 1453 | } |
1303 | return 0; | 1454 | return 0; |
1304 | } | 1455 | } |
@@ -1318,46 +1469,46 @@ int fcoe_percpu_receive_thread(void *arg) | |||
1318 | */ | 1469 | */ |
1319 | static void fcoe_check_wait_queue(struct fc_lport *lp, struct sk_buff *skb) | 1470 | static void fcoe_check_wait_queue(struct fc_lport *lp, struct sk_buff *skb) |
1320 | { | 1471 | { |
1321 | struct fcoe_softc *fc = lport_priv(lp); | 1472 | struct fcoe_port *port = lport_priv(lp); |
1322 | int rc; | 1473 | int rc; |
1323 | 1474 | ||
1324 | spin_lock_bh(&fc->fcoe_pending_queue.lock); | 1475 | spin_lock_bh(&port->fcoe_pending_queue.lock); |
1325 | 1476 | ||
1326 | if (skb) | 1477 | if (skb) |
1327 | __skb_queue_tail(&fc->fcoe_pending_queue, skb); | 1478 | __skb_queue_tail(&port->fcoe_pending_queue, skb); |
1328 | 1479 | ||
1329 | if (fc->fcoe_pending_queue_active) | 1480 | if (port->fcoe_pending_queue_active) |
1330 | goto out; | 1481 | goto out; |
1331 | fc->fcoe_pending_queue_active = 1; | 1482 | port->fcoe_pending_queue_active = 1; |
1332 | 1483 | ||
1333 | while (fc->fcoe_pending_queue.qlen) { | 1484 | while (port->fcoe_pending_queue.qlen) { |
1334 | /* keep qlen > 0 until fcoe_start_io succeeds */ | 1485 | /* keep qlen > 0 until fcoe_start_io succeeds */ |
1335 | fc->fcoe_pending_queue.qlen++; | 1486 | port->fcoe_pending_queue.qlen++; |
1336 | skb = __skb_dequeue(&fc->fcoe_pending_queue); | 1487 | skb = __skb_dequeue(&port->fcoe_pending_queue); |
1337 | 1488 | ||
1338 | spin_unlock_bh(&fc->fcoe_pending_queue.lock); | 1489 | spin_unlock_bh(&port->fcoe_pending_queue.lock); |
1339 | rc = fcoe_start_io(skb); | 1490 | rc = fcoe_start_io(skb); |
1340 | spin_lock_bh(&fc->fcoe_pending_queue.lock); | 1491 | spin_lock_bh(&port->fcoe_pending_queue.lock); |
1341 | 1492 | ||
1342 | if (rc) { | 1493 | if (rc) { |
1343 | __skb_queue_head(&fc->fcoe_pending_queue, skb); | 1494 | __skb_queue_head(&port->fcoe_pending_queue, skb); |
1344 | /* undo temporary increment above */ | 1495 | /* undo temporary increment above */ |
1345 | fc->fcoe_pending_queue.qlen--; | 1496 | port->fcoe_pending_queue.qlen--; |
1346 | break; | 1497 | break; |
1347 | } | 1498 | } |
1348 | /* undo temporary increment above */ | 1499 | /* undo temporary increment above */ |
1349 | fc->fcoe_pending_queue.qlen--; | 1500 | port->fcoe_pending_queue.qlen--; |
1350 | } | 1501 | } |
1351 | 1502 | ||
1352 | if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) | 1503 | if (port->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) |
1353 | lp->qfull = 0; | 1504 | lp->qfull = 0; |
1354 | if (fc->fcoe_pending_queue.qlen && !timer_pending(&fc->timer)) | 1505 | if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer)) |
1355 | mod_timer(&fc->timer, jiffies + 2); | 1506 | mod_timer(&port->timer, jiffies + 2); |
1356 | fc->fcoe_pending_queue_active = 0; | 1507 | port->fcoe_pending_queue_active = 0; |
1357 | out: | 1508 | out: |
1358 | if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) | 1509 | if (port->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) |
1359 | lp->qfull = 1; | 1510 | lp->qfull = 1; |
1360 | spin_unlock_bh(&fc->fcoe_pending_queue.lock); | 1511 | spin_unlock_bh(&port->fcoe_pending_queue.lock); |
1361 | return; | 1512 | return; |
1362 | } | 1513 | } |
1363 | 1514 | ||
@@ -1391,21 +1542,20 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1391 | ulong event, void *ptr) | 1542 | ulong event, void *ptr) |
1392 | { | 1543 | { |
1393 | struct fc_lport *lp = NULL; | 1544 | struct fc_lport *lp = NULL; |
1394 | struct net_device *real_dev = ptr; | 1545 | struct net_device *netdev = ptr; |
1395 | struct fcoe_softc *fc; | 1546 | struct fcoe_interface *fcoe; |
1547 | struct fcoe_port *port; | ||
1396 | struct fcoe_dev_stats *stats; | 1548 | struct fcoe_dev_stats *stats; |
1397 | u32 link_possible = 1; | 1549 | u32 link_possible = 1; |
1398 | u32 mfs; | 1550 | u32 mfs; |
1399 | int rc = NOTIFY_OK; | 1551 | int rc = NOTIFY_OK; |
1400 | 1552 | ||
1401 | read_lock(&fcoe_hostlist_lock); | 1553 | list_for_each_entry(fcoe, &fcoe_hostlist, list) { |
1402 | list_for_each_entry(fc, &fcoe_hostlist, list) { | 1554 | if (fcoe->netdev == netdev) { |
1403 | if (fc->real_dev == real_dev) { | 1555 | lp = fcoe->ctlr.lp; |
1404 | lp = fc->ctlr.lp; | ||
1405 | break; | 1556 | break; |
1406 | } | 1557 | } |
1407 | } | 1558 | } |
1408 | read_unlock(&fcoe_hostlist_lock); | ||
1409 | if (lp == NULL) { | 1559 | if (lp == NULL) { |
1410 | rc = NOTIFY_DONE; | 1560 | rc = NOTIFY_DONE; |
1411 | goto out; | 1561 | goto out; |
@@ -1420,21 +1570,27 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1420 | case NETDEV_CHANGE: | 1570 | case NETDEV_CHANGE: |
1421 | break; | 1571 | break; |
1422 | case NETDEV_CHANGEMTU: | 1572 | case NETDEV_CHANGEMTU: |
1423 | mfs = fc->real_dev->mtu - | 1573 | mfs = netdev->mtu - (sizeof(struct fcoe_hdr) + |
1424 | (sizeof(struct fcoe_hdr) + | 1574 | sizeof(struct fcoe_crc_eof)); |
1425 | sizeof(struct fcoe_crc_eof)); | ||
1426 | if (mfs >= FC_MIN_MAX_FRAME) | 1575 | if (mfs >= FC_MIN_MAX_FRAME) |
1427 | fc_set_mfs(lp, mfs); | 1576 | fc_set_mfs(lp, mfs); |
1428 | break; | 1577 | break; |
1429 | case NETDEV_REGISTER: | 1578 | case NETDEV_REGISTER: |
1430 | break; | 1579 | break; |
1580 | case NETDEV_UNREGISTER: | ||
1581 | list_del(&fcoe->list); | ||
1582 | port = lport_priv(fcoe->ctlr.lp); | ||
1583 | fcoe_interface_cleanup(fcoe); | ||
1584 | schedule_work(&port->destroy_work); | ||
1585 | goto out; | ||
1586 | break; | ||
1431 | default: | 1587 | default: |
1432 | FCOE_NETDEV_DBG(real_dev, "Unknown event %ld " | 1588 | FCOE_NETDEV_DBG(netdev, "Unknown event %ld " |
1433 | "from netdev netlink\n", event); | 1589 | "from netdev netlink\n", event); |
1434 | } | 1590 | } |
1435 | if (link_possible && !fcoe_link_ok(lp)) | 1591 | if (link_possible && !fcoe_link_ok(lp)) |
1436 | fcoe_ctlr_link_up(&fc->ctlr); | 1592 | fcoe_ctlr_link_up(&fcoe->ctlr); |
1437 | else if (fcoe_ctlr_link_down(&fc->ctlr)) { | 1593 | else if (fcoe_ctlr_link_down(&fcoe->ctlr)) { |
1438 | stats = fc_lport_get_stats(lp); | 1594 | stats = fc_lport_get_stats(lp); |
1439 | stats->LinkFailureCount++; | 1595 | stats->LinkFailureCount++; |
1440 | fcoe_clean_pending_queue(lp); | 1596 | fcoe_clean_pending_queue(lp); |
@@ -1465,75 +1621,6 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) | |||
1465 | } | 1621 | } |
1466 | 1622 | ||
1467 | /** | 1623 | /** |
1468 | * fcoe_netdev_to_module_owner() - finds out the driver module of the netdev | ||
1469 | * @netdev: the target netdev | ||
1470 | * | ||
1471 | * Returns: ptr to the struct module, NULL for failure | ||
1472 | */ | ||
1473 | static struct module * | ||
1474 | fcoe_netdev_to_module_owner(const struct net_device *netdev) | ||
1475 | { | ||
1476 | struct device *dev; | ||
1477 | |||
1478 | if (!netdev) | ||
1479 | return NULL; | ||
1480 | |||
1481 | dev = netdev->dev.parent; | ||
1482 | if (!dev) | ||
1483 | return NULL; | ||
1484 | |||
1485 | if (!dev->driver) | ||
1486 | return NULL; | ||
1487 | |||
1488 | return dev->driver->owner; | ||
1489 | } | ||
1490 | |||
1491 | /** | ||
1492 | * fcoe_ethdrv_get() - Hold the Ethernet driver | ||
1493 | * @netdev: the target netdev | ||
1494 | * | ||
1495 | * Holds the Ethernet driver module by try_module_get() for | ||
1496 | * the corresponding netdev. | ||
1497 | * | ||
1498 | * Returns: 0 for success | ||
1499 | */ | ||
1500 | static int fcoe_ethdrv_get(const struct net_device *netdev) | ||
1501 | { | ||
1502 | struct module *owner; | ||
1503 | |||
1504 | owner = fcoe_netdev_to_module_owner(netdev); | ||
1505 | if (owner) { | ||
1506 | FCOE_NETDEV_DBG(netdev, "Hold driver module %s\n", | ||
1507 | module_name(owner)); | ||
1508 | return try_module_get(owner); | ||
1509 | } | ||
1510 | return -ENODEV; | ||
1511 | } | ||
1512 | |||
1513 | /** | ||
1514 | * fcoe_ethdrv_put() - Release the Ethernet driver | ||
1515 | * @netdev: the target netdev | ||
1516 | * | ||
1517 | * Releases the Ethernet driver module by module_put for | ||
1518 | * the corresponding netdev. | ||
1519 | * | ||
1520 | * Returns: 0 for success | ||
1521 | */ | ||
1522 | static int fcoe_ethdrv_put(const struct net_device *netdev) | ||
1523 | { | ||
1524 | struct module *owner; | ||
1525 | |||
1526 | owner = fcoe_netdev_to_module_owner(netdev); | ||
1527 | if (owner) { | ||
1528 | FCOE_NETDEV_DBG(netdev, "Release driver module %s\n", | ||
1529 | module_name(owner)); | ||
1530 | module_put(owner); | ||
1531 | return 0; | ||
1532 | } | ||
1533 | return -ENODEV; | ||
1534 | } | ||
1535 | |||
1536 | /** | ||
1537 | * fcoe_destroy() - handles the destroy from sysfs | 1624 | * fcoe_destroy() - handles the destroy from sysfs |
1538 | * @buffer: expected to be an eth if name | 1625 | * @buffer: expected to be an eth if name |
1539 | * @kp: associated kernel param | 1626 | * @kp: associated kernel param |
@@ -1542,34 +1629,57 @@ static int fcoe_ethdrv_put(const struct net_device *netdev) | |||
1542 | */ | 1629 | */ |
1543 | static int fcoe_destroy(const char *buffer, struct kernel_param *kp) | 1630 | static int fcoe_destroy(const char *buffer, struct kernel_param *kp) |
1544 | { | 1631 | { |
1545 | int rc; | 1632 | struct fcoe_interface *fcoe; |
1546 | struct net_device *netdev; | 1633 | struct net_device *netdev; |
1634 | int rc; | ||
1635 | |||
1636 | mutex_lock(&fcoe_config_mutex); | ||
1637 | #ifdef CONFIG_FCOE_MODULE | ||
1638 | /* | ||
1639 | * Make sure the module has been initialized, and is not about to be | ||
1640 | * removed. Module paramter sysfs files are writable before the | ||
1641 | * module_init function is called and after module_exit. | ||
1642 | */ | ||
1643 | if (THIS_MODULE->state != MODULE_STATE_LIVE) { | ||
1644 | rc = -ENODEV; | ||
1645 | goto out_nodev; | ||
1646 | } | ||
1647 | #endif | ||
1547 | 1648 | ||
1548 | netdev = fcoe_if_to_netdev(buffer); | 1649 | netdev = fcoe_if_to_netdev(buffer); |
1549 | if (!netdev) { | 1650 | if (!netdev) { |
1550 | rc = -ENODEV; | 1651 | rc = -ENODEV; |
1551 | goto out_nodev; | 1652 | goto out_nodev; |
1552 | } | 1653 | } |
1553 | /* look for existing lport */ | 1654 | |
1554 | if (!fcoe_hostlist_lookup(netdev)) { | 1655 | rtnl_lock(); |
1656 | fcoe = fcoe_hostlist_lookup_port(netdev); | ||
1657 | if (!fcoe) { | ||
1658 | rtnl_unlock(); | ||
1555 | rc = -ENODEV; | 1659 | rc = -ENODEV; |
1556 | goto out_putdev; | 1660 | goto out_putdev; |
1557 | } | 1661 | } |
1558 | rc = fcoe_if_destroy(netdev); | 1662 | list_del(&fcoe->list); |
1559 | if (rc) { | 1663 | fcoe_interface_cleanup(fcoe); |
1560 | printk(KERN_ERR "fcoe: Failed to destroy interface (%s)\n", | 1664 | rtnl_unlock(); |
1561 | netdev->name); | 1665 | fcoe_if_destroy(fcoe->ctlr.lp); |
1562 | rc = -EIO; | ||
1563 | goto out_putdev; | ||
1564 | } | ||
1565 | fcoe_ethdrv_put(netdev); | ||
1566 | rc = 0; | ||
1567 | out_putdev: | 1666 | out_putdev: |
1568 | dev_put(netdev); | 1667 | dev_put(netdev); |
1569 | out_nodev: | 1668 | out_nodev: |
1669 | mutex_unlock(&fcoe_config_mutex); | ||
1570 | return rc; | 1670 | return rc; |
1571 | } | 1671 | } |
1572 | 1672 | ||
1673 | static void fcoe_destroy_work(struct work_struct *work) | ||
1674 | { | ||
1675 | struct fcoe_port *port; | ||
1676 | |||
1677 | port = container_of(work, struct fcoe_port, destroy_work); | ||
1678 | mutex_lock(&fcoe_config_mutex); | ||
1679 | fcoe_if_destroy(port->lport); | ||
1680 | mutex_unlock(&fcoe_config_mutex); | ||
1681 | } | ||
1682 | |||
1573 | /** | 1683 | /** |
1574 | * fcoe_create() - Handles the create call from sysfs | 1684 | * fcoe_create() - Handles the create call from sysfs |
1575 | * @buffer: expected to be an eth if name | 1685 | * @buffer: expected to be an eth if name |
@@ -1580,41 +1690,84 @@ out_nodev: | |||
1580 | static int fcoe_create(const char *buffer, struct kernel_param *kp) | 1690 | static int fcoe_create(const char *buffer, struct kernel_param *kp) |
1581 | { | 1691 | { |
1582 | int rc; | 1692 | int rc; |
1693 | struct fcoe_interface *fcoe; | ||
1694 | struct fc_lport *lport; | ||
1583 | struct net_device *netdev; | 1695 | struct net_device *netdev; |
1584 | 1696 | ||
1697 | mutex_lock(&fcoe_config_mutex); | ||
1698 | #ifdef CONFIG_FCOE_MODULE | ||
1699 | /* | ||
1700 | * Make sure the module has been initialized, and is not about to be | ||
1701 | * removed. Module paramter sysfs files are writable before the | ||
1702 | * module_init function is called and after module_exit. | ||
1703 | */ | ||
1704 | if (THIS_MODULE->state != MODULE_STATE_LIVE) { | ||
1705 | rc = -ENODEV; | ||
1706 | goto out_nodev; | ||
1707 | } | ||
1708 | #endif | ||
1709 | |||
1710 | rtnl_lock(); | ||
1585 | netdev = fcoe_if_to_netdev(buffer); | 1711 | netdev = fcoe_if_to_netdev(buffer); |
1586 | if (!netdev) { | 1712 | if (!netdev) { |
1587 | rc = -ENODEV; | 1713 | rc = -ENODEV; |
1588 | goto out_nodev; | 1714 | goto out_nodev; |
1589 | } | 1715 | } |
1716 | |||
1590 | /* look for existing lport */ | 1717 | /* look for existing lport */ |
1591 | if (fcoe_hostlist_lookup(netdev)) { | 1718 | if (fcoe_hostlist_lookup(netdev)) { |
1592 | rc = -EEXIST; | 1719 | rc = -EEXIST; |
1593 | goto out_putdev; | 1720 | goto out_putdev; |
1594 | } | 1721 | } |
1595 | fcoe_ethdrv_get(netdev); | ||
1596 | 1722 | ||
1597 | rc = fcoe_if_create(netdev); | 1723 | fcoe = fcoe_interface_create(netdev); |
1598 | if (rc) { | 1724 | if (!fcoe) { |
1725 | rc = -ENOMEM; | ||
1726 | goto out_putdev; | ||
1727 | } | ||
1728 | |||
1729 | lport = fcoe_if_create(fcoe, &netdev->dev); | ||
1730 | if (IS_ERR(lport)) { | ||
1599 | printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", | 1731 | printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", |
1600 | netdev->name); | 1732 | netdev->name); |
1601 | fcoe_ethdrv_put(netdev); | ||
1602 | rc = -EIO; | 1733 | rc = -EIO; |
1603 | goto out_putdev; | 1734 | fcoe_interface_cleanup(fcoe); |
1735 | goto out_free; | ||
1604 | } | 1736 | } |
1737 | |||
1738 | /* Make this the "master" N_Port */ | ||
1739 | fcoe->ctlr.lp = lport; | ||
1740 | |||
1741 | /* add to lports list */ | ||
1742 | fcoe_hostlist_add(lport); | ||
1743 | |||
1744 | /* start FIP Discovery and FLOGI */ | ||
1745 | lport->boot_time = jiffies; | ||
1746 | fc_fabric_login(lport); | ||
1747 | if (!fcoe_link_ok(lport)) | ||
1748 | fcoe_ctlr_link_up(&fcoe->ctlr); | ||
1749 | |||
1605 | rc = 0; | 1750 | rc = 0; |
1751 | out_free: | ||
1752 | /* | ||
1753 | * Release from init in fcoe_interface_create(), on success lport | ||
1754 | * should be holding a reference taken in fcoe_if_create(). | ||
1755 | */ | ||
1756 | fcoe_interface_put(fcoe); | ||
1606 | out_putdev: | 1757 | out_putdev: |
1607 | dev_put(netdev); | 1758 | dev_put(netdev); |
1608 | out_nodev: | 1759 | out_nodev: |
1760 | rtnl_unlock(); | ||
1761 | mutex_unlock(&fcoe_config_mutex); | ||
1609 | return rc; | 1762 | return rc; |
1610 | } | 1763 | } |
1611 | 1764 | ||
1612 | module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR); | 1765 | module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR); |
1613 | __MODULE_PARM_TYPE(create, "string"); | 1766 | __MODULE_PARM_TYPE(create, "string"); |
1614 | MODULE_PARM_DESC(create, "Create fcoe port using net device passed in."); | 1767 | MODULE_PARM_DESC(create, "Create fcoe fcoe using net device passed in."); |
1615 | module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR); | 1768 | module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR); |
1616 | __MODULE_PARM_TYPE(destroy, "string"); | 1769 | __MODULE_PARM_TYPE(destroy, "string"); |
1617 | MODULE_PARM_DESC(destroy, "Destroy fcoe port"); | 1770 | MODULE_PARM_DESC(destroy, "Destroy fcoe fcoe"); |
1618 | 1771 | ||
1619 | /** | 1772 | /** |
1620 | * fcoe_link_ok() - Check if link is ok for the fc_lport | 1773 | * fcoe_link_ok() - Check if link is ok for the fc_lport |
@@ -1632,37 +1785,40 @@ MODULE_PARM_DESC(destroy, "Destroy fcoe port"); | |||
1632 | */ | 1785 | */ |
1633 | int fcoe_link_ok(struct fc_lport *lp) | 1786 | int fcoe_link_ok(struct fc_lport *lp) |
1634 | { | 1787 | { |
1635 | struct fcoe_softc *fc = lport_priv(lp); | 1788 | struct fcoe_port *port = lport_priv(lp); |
1636 | struct net_device *dev = fc->real_dev; | 1789 | struct net_device *dev = port->fcoe->netdev; |
1637 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; | 1790 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; |
1638 | int rc = 0; | ||
1639 | 1791 | ||
1640 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev)) { | 1792 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && |
1641 | dev = fc->phys_dev; | 1793 | (!dev_ethtool_get_settings(dev, &ecmd))) { |
1642 | if (dev->ethtool_ops->get_settings) { | 1794 | lp->link_supported_speeds &= |
1643 | dev->ethtool_ops->get_settings(dev, &ecmd); | 1795 | ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); |
1644 | lp->link_supported_speeds &= | 1796 | if (ecmd.supported & (SUPPORTED_1000baseT_Half | |
1645 | ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); | 1797 | SUPPORTED_1000baseT_Full)) |
1646 | if (ecmd.supported & (SUPPORTED_1000baseT_Half | | 1798 | lp->link_supported_speeds |= FC_PORTSPEED_1GBIT; |
1647 | SUPPORTED_1000baseT_Full)) | 1799 | if (ecmd.supported & SUPPORTED_10000baseT_Full) |
1648 | lp->link_supported_speeds |= FC_PORTSPEED_1GBIT; | 1800 | lp->link_supported_speeds |= |
1649 | if (ecmd.supported & SUPPORTED_10000baseT_Full) | 1801 | FC_PORTSPEED_10GBIT; |
1650 | lp->link_supported_speeds |= | 1802 | if (ecmd.speed == SPEED_1000) |
1651 | FC_PORTSPEED_10GBIT; | 1803 | lp->link_speed = FC_PORTSPEED_1GBIT; |
1652 | if (ecmd.speed == SPEED_1000) | 1804 | if (ecmd.speed == SPEED_10000) |
1653 | lp->link_speed = FC_PORTSPEED_1GBIT; | 1805 | lp->link_speed = FC_PORTSPEED_10GBIT; |
1654 | if (ecmd.speed == SPEED_10000) | ||
1655 | lp->link_speed = FC_PORTSPEED_10GBIT; | ||
1656 | } | ||
1657 | } else | ||
1658 | rc = -1; | ||
1659 | 1806 | ||
1660 | return rc; | 1807 | return 0; |
1808 | } | ||
1809 | return -1; | ||
1661 | } | 1810 | } |
1662 | 1811 | ||
1663 | /** | 1812 | /** |
1664 | * fcoe_percpu_clean() - Clear the pending skbs for an lport | 1813 | * fcoe_percpu_clean() - Clear the pending skbs for an lport |
1665 | * @lp: the fc_lport | 1814 | * @lp: the fc_lport |
1815 | * | ||
1816 | * Must be called with fcoe_create_mutex held to single-thread completion. | ||
1817 | * | ||
1818 | * This flushes the pending skbs by adding a new skb to each queue and | ||
1819 | * waiting until they are all freed. This assures us that not only are | ||
1820 | * there no packets that will be handled by the lport, but also that any | ||
1821 | * threads already handling packet have returned. | ||
1666 | */ | 1822 | */ |
1667 | void fcoe_percpu_clean(struct fc_lport *lp) | 1823 | void fcoe_percpu_clean(struct fc_lport *lp) |
1668 | { | 1824 | { |
@@ -1687,7 +1843,25 @@ void fcoe_percpu_clean(struct fc_lport *lp) | |||
1687 | kfree_skb(skb); | 1843 | kfree_skb(skb); |
1688 | } | 1844 | } |
1689 | } | 1845 | } |
1846 | |||
1847 | if (!pp->thread || !cpu_online(cpu)) { | ||
1848 | spin_unlock_bh(&pp->fcoe_rx_list.lock); | ||
1849 | continue; | ||
1850 | } | ||
1851 | |||
1852 | skb = dev_alloc_skb(0); | ||
1853 | if (!skb) { | ||
1854 | spin_unlock_bh(&pp->fcoe_rx_list.lock); | ||
1855 | continue; | ||
1856 | } | ||
1857 | skb->destructor = fcoe_percpu_flush_done; | ||
1858 | |||
1859 | __skb_queue_tail(&pp->fcoe_rx_list, skb); | ||
1860 | if (pp->fcoe_rx_list.qlen == 1) | ||
1861 | wake_up_process(pp->thread); | ||
1690 | spin_unlock_bh(&pp->fcoe_rx_list.lock); | 1862 | spin_unlock_bh(&pp->fcoe_rx_list.lock); |
1863 | |||
1864 | wait_for_completion(&fcoe_flush_completion); | ||
1691 | } | 1865 | } |
1692 | } | 1866 | } |
1693 | 1867 | ||
@@ -1699,16 +1873,16 @@ void fcoe_percpu_clean(struct fc_lport *lp) | |||
1699 | */ | 1873 | */ |
1700 | void fcoe_clean_pending_queue(struct fc_lport *lp) | 1874 | void fcoe_clean_pending_queue(struct fc_lport *lp) |
1701 | { | 1875 | { |
1702 | struct fcoe_softc *fc = lport_priv(lp); | 1876 | struct fcoe_port *port = lport_priv(lp); |
1703 | struct sk_buff *skb; | 1877 | struct sk_buff *skb; |
1704 | 1878 | ||
1705 | spin_lock_bh(&fc->fcoe_pending_queue.lock); | 1879 | spin_lock_bh(&port->fcoe_pending_queue.lock); |
1706 | while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) { | 1880 | while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) { |
1707 | spin_unlock_bh(&fc->fcoe_pending_queue.lock); | 1881 | spin_unlock_bh(&port->fcoe_pending_queue.lock); |
1708 | kfree_skb(skb); | 1882 | kfree_skb(skb); |
1709 | spin_lock_bh(&fc->fcoe_pending_queue.lock); | 1883 | spin_lock_bh(&port->fcoe_pending_queue.lock); |
1710 | } | 1884 | } |
1711 | spin_unlock_bh(&fc->fcoe_pending_queue.lock); | 1885 | spin_unlock_bh(&port->fcoe_pending_queue.lock); |
1712 | } | 1886 | } |
1713 | 1887 | ||
1714 | /** | 1888 | /** |
@@ -1725,24 +1899,21 @@ int fcoe_reset(struct Scsi_Host *shost) | |||
1725 | } | 1899 | } |
1726 | 1900 | ||
1727 | /** | 1901 | /** |
1728 | * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device | 1902 | * fcoe_hostlist_lookup_port() - find the corresponding lport by a given device |
1729 | * @dev: this is currently ptr to net_device | 1903 | * @dev: this is currently ptr to net_device |
1730 | * | 1904 | * |
1731 | * Returns: NULL or the located fcoe_softc | 1905 | * Returns: NULL or the located fcoe_port |
1906 | * Locking: must be called with the RNL mutex held | ||
1732 | */ | 1907 | */ |
1733 | static struct fcoe_softc * | 1908 | static struct fcoe_interface * |
1734 | fcoe_hostlist_lookup_softc(const struct net_device *dev) | 1909 | fcoe_hostlist_lookup_port(const struct net_device *dev) |
1735 | { | 1910 | { |
1736 | struct fcoe_softc *fc; | 1911 | struct fcoe_interface *fcoe; |
1737 | 1912 | ||
1738 | read_lock(&fcoe_hostlist_lock); | 1913 | list_for_each_entry(fcoe, &fcoe_hostlist, list) { |
1739 | list_for_each_entry(fc, &fcoe_hostlist, list) { | 1914 | if (fcoe->netdev == dev) |
1740 | if (fc->real_dev == dev) { | 1915 | return fcoe; |
1741 | read_unlock(&fcoe_hostlist_lock); | ||
1742 | return fc; | ||
1743 | } | ||
1744 | } | 1916 | } |
1745 | read_unlock(&fcoe_hostlist_lock); | ||
1746 | return NULL; | 1917 | return NULL; |
1747 | } | 1918 | } |
1748 | 1919 | ||
@@ -1751,14 +1922,14 @@ fcoe_hostlist_lookup_softc(const struct net_device *dev) | |||
1751 | * @netdev: ptr to net_device | 1922 | * @netdev: ptr to net_device |
1752 | * | 1923 | * |
1753 | * Returns: 0 for success | 1924 | * Returns: 0 for success |
1925 | * Locking: must be called with the RTNL mutex held | ||
1754 | */ | 1926 | */ |
1755 | struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) | 1927 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) |
1756 | { | 1928 | { |
1757 | struct fcoe_softc *fc; | 1929 | struct fcoe_interface *fcoe; |
1758 | |||
1759 | fc = fcoe_hostlist_lookup_softc(netdev); | ||
1760 | 1930 | ||
1761 | return (fc) ? fc->ctlr.lp : NULL; | 1931 | fcoe = fcoe_hostlist_lookup_port(netdev); |
1932 | return (fcoe) ? fcoe->ctlr.lp : NULL; | ||
1762 | } | 1933 | } |
1763 | 1934 | ||
1764 | /** | 1935 | /** |
@@ -1766,41 +1937,23 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) | |||
1766 | * @lp: ptr to the fc_lport to be added | 1937 | * @lp: ptr to the fc_lport to be added |
1767 | * | 1938 | * |
1768 | * Returns: 0 for success | 1939 | * Returns: 0 for success |
1940 | * Locking: must be called with the RTNL mutex held | ||
1769 | */ | 1941 | */ |
1770 | int fcoe_hostlist_add(const struct fc_lport *lp) | 1942 | static int fcoe_hostlist_add(const struct fc_lport *lport) |
1771 | { | 1943 | { |
1772 | struct fcoe_softc *fc; | 1944 | struct fcoe_interface *fcoe; |
1773 | 1945 | struct fcoe_port *port; | |
1774 | fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp)); | 1946 | |
1775 | if (!fc) { | 1947 | fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport)); |
1776 | fc = lport_priv(lp); | 1948 | if (!fcoe) { |
1777 | write_lock_bh(&fcoe_hostlist_lock); | 1949 | port = lport_priv(lport); |
1778 | list_add_tail(&fc->list, &fcoe_hostlist); | 1950 | fcoe = port->fcoe; |
1779 | write_unlock_bh(&fcoe_hostlist_lock); | 1951 | list_add_tail(&fcoe->list, &fcoe_hostlist); |
1780 | } | 1952 | } |
1781 | return 0; | 1953 | return 0; |
1782 | } | 1954 | } |
1783 | 1955 | ||
1784 | /** | 1956 | /** |
1785 | * fcoe_hostlist_remove() - remove a lport from lports list | ||
1786 | * @lp: ptr to the fc_lport to be removed | ||
1787 | * | ||
1788 | * Returns: 0 for success | ||
1789 | */ | ||
1790 | int fcoe_hostlist_remove(const struct fc_lport *lp) | ||
1791 | { | ||
1792 | struct fcoe_softc *fc; | ||
1793 | |||
1794 | fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp)); | ||
1795 | BUG_ON(!fc); | ||
1796 | write_lock_bh(&fcoe_hostlist_lock); | ||
1797 | list_del(&fc->list); | ||
1798 | write_unlock_bh(&fcoe_hostlist_lock); | ||
1799 | |||
1800 | return 0; | ||
1801 | } | ||
1802 | |||
1803 | /** | ||
1804 | * fcoe_init() - fcoe module loading initialization | 1957 | * fcoe_init() - fcoe module loading initialization |
1805 | * | 1958 | * |
1806 | * Returns 0 on success, negative on failure | 1959 | * Returns 0 on success, negative on failure |
@@ -1811,8 +1964,7 @@ static int __init fcoe_init(void) | |||
1811 | int rc = 0; | 1964 | int rc = 0; |
1812 | struct fcoe_percpu_s *p; | 1965 | struct fcoe_percpu_s *p; |
1813 | 1966 | ||
1814 | INIT_LIST_HEAD(&fcoe_hostlist); | 1967 | mutex_lock(&fcoe_config_mutex); |
1815 | rwlock_init(&fcoe_hostlist_lock); | ||
1816 | 1968 | ||
1817 | for_each_possible_cpu(cpu) { | 1969 | for_each_possible_cpu(cpu) { |
1818 | p = &per_cpu(fcoe_percpu, cpu); | 1970 | p = &per_cpu(fcoe_percpu, cpu); |
@@ -1830,15 +1982,18 @@ static int __init fcoe_init(void) | |||
1830 | /* Setup link change notification */ | 1982 | /* Setup link change notification */ |
1831 | fcoe_dev_setup(); | 1983 | fcoe_dev_setup(); |
1832 | 1984 | ||
1833 | fcoe_if_init(); | 1985 | rc = fcoe_if_init(); |
1986 | if (rc) | ||
1987 | goto out_free; | ||
1834 | 1988 | ||
1989 | mutex_unlock(&fcoe_config_mutex); | ||
1835 | return 0; | 1990 | return 0; |
1836 | 1991 | ||
1837 | out_free: | 1992 | out_free: |
1838 | for_each_online_cpu(cpu) { | 1993 | for_each_online_cpu(cpu) { |
1839 | fcoe_percpu_thread_destroy(cpu); | 1994 | fcoe_percpu_thread_destroy(cpu); |
1840 | } | 1995 | } |
1841 | 1996 | mutex_unlock(&fcoe_config_mutex); | |
1842 | return rc; | 1997 | return rc; |
1843 | } | 1998 | } |
1844 | module_init(fcoe_init); | 1999 | module_init(fcoe_init); |
@@ -1851,21 +2006,36 @@ module_init(fcoe_init); | |||
1851 | static void __exit fcoe_exit(void) | 2006 | static void __exit fcoe_exit(void) |
1852 | { | 2007 | { |
1853 | unsigned int cpu; | 2008 | unsigned int cpu; |
1854 | struct fcoe_softc *fc, *tmp; | 2009 | struct fcoe_interface *fcoe, *tmp; |
2010 | struct fcoe_port *port; | ||
2011 | |||
2012 | mutex_lock(&fcoe_config_mutex); | ||
1855 | 2013 | ||
1856 | fcoe_dev_cleanup(); | 2014 | fcoe_dev_cleanup(); |
1857 | 2015 | ||
1858 | /* releases the associated fcoe hosts */ | 2016 | /* releases the associated fcoe hosts */ |
1859 | list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list) | 2017 | rtnl_lock(); |
1860 | fcoe_if_destroy(fc->real_dev); | 2018 | list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) { |
2019 | list_del(&fcoe->list); | ||
2020 | port = lport_priv(fcoe->ctlr.lp); | ||
2021 | fcoe_interface_cleanup(fcoe); | ||
2022 | schedule_work(&port->destroy_work); | ||
2023 | } | ||
2024 | rtnl_unlock(); | ||
1861 | 2025 | ||
1862 | unregister_hotcpu_notifier(&fcoe_cpu_notifier); | 2026 | unregister_hotcpu_notifier(&fcoe_cpu_notifier); |
1863 | 2027 | ||
1864 | for_each_online_cpu(cpu) { | 2028 | for_each_online_cpu(cpu) |
1865 | fcoe_percpu_thread_destroy(cpu); | 2029 | fcoe_percpu_thread_destroy(cpu); |
1866 | } | ||
1867 | 2030 | ||
1868 | /* detach from scsi transport */ | 2031 | mutex_unlock(&fcoe_config_mutex); |
2032 | |||
2033 | /* flush any asyncronous interface destroys, | ||
2034 | * this should happen after the netdev notifier is unregistered */ | ||
2035 | flush_scheduled_work(); | ||
2036 | |||
2037 | /* detach from scsi transport | ||
2038 | * must happen after all destroys are done, therefor after the flush */ | ||
1869 | fcoe_if_exit(); | 2039 | fcoe_if_exit(); |
1870 | } | 2040 | } |
1871 | module_exit(fcoe_exit); | 2041 | module_exit(fcoe_exit); |
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h index 0d724fa0898f..ce7f60fb1bc0 100644 --- a/drivers/scsi/fcoe/fcoe.h +++ b/drivers/scsi/fcoe/fcoe.h | |||
@@ -37,8 +37,8 @@ | |||
37 | 37 | ||
38 | #define FCOE_MAX_OUTSTANDING_COMMANDS 1024 | 38 | #define FCOE_MAX_OUTSTANDING_COMMANDS 1024 |
39 | 39 | ||
40 | #define FCOE_MIN_XID 0x0001 /* 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 0x07ef /* the max xid supported by fcoe_sw */ | 41 | #define FCOE_MAX_XID 0x0FFF /* the max xid supported by fcoe_sw */ |
42 | 42 | ||
43 | unsigned int fcoe_debug_logging; | 43 | unsigned int fcoe_debug_logging; |
44 | module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR); | 44 | module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR); |
@@ -53,7 +53,7 @@ do { \ | |||
53 | do { \ | 53 | do { \ |
54 | CMD; \ | 54 | CMD; \ |
55 | } while (0); \ | 55 | } while (0); \ |
56 | } while (0); | 56 | } while (0) |
57 | 57 | ||
58 | #define FCOE_DBG(fmt, args...) \ | 58 | #define FCOE_DBG(fmt, args...) \ |
59 | FCOE_CHECK_LOGGING(FCOE_LOGGING, \ | 59 | FCOE_CHECK_LOGGING(FCOE_LOGGING, \ |
@@ -61,7 +61,7 @@ do { \ | |||
61 | 61 | ||
62 | #define FCOE_NETDEV_DBG(netdev, fmt, args...) \ | 62 | #define FCOE_NETDEV_DBG(netdev, fmt, args...) \ |
63 | FCOE_CHECK_LOGGING(FCOE_NETDEV_LOGGING, \ | 63 | FCOE_CHECK_LOGGING(FCOE_NETDEV_LOGGING, \ |
64 | printk(KERN_INFO "fcoe: %s" fmt, \ | 64 | printk(KERN_INFO "fcoe: %s: " fmt, \ |
65 | netdev->name, ##args);) | 65 | netdev->name, ##args);) |
66 | 66 | ||
67 | /* | 67 | /* |
@@ -75,26 +75,36 @@ struct fcoe_percpu_s { | |||
75 | }; | 75 | }; |
76 | 76 | ||
77 | /* | 77 | /* |
78 | * the fcoe sw transport private data | 78 | * an FCoE interface, 1:1 with netdev |
79 | */ | 79 | */ |
80 | struct fcoe_softc { | 80 | struct fcoe_interface { |
81 | struct list_head list; | 81 | struct list_head list; |
82 | struct net_device *real_dev; | 82 | struct net_device *netdev; |
83 | struct net_device *phys_dev; /* device with ethtool_ops */ | ||
84 | struct packet_type fcoe_packet_type; | 83 | struct packet_type fcoe_packet_type; |
85 | struct packet_type fip_packet_type; | 84 | struct packet_type fip_packet_type; |
85 | struct fcoe_ctlr ctlr; | ||
86 | struct fc_exch_mgr *oem; /* offload exchange manager */ | ||
87 | struct kref kref; | ||
88 | }; | ||
89 | |||
90 | /* | ||
91 | * the FCoE private structure that's allocated along with the | ||
92 | * Scsi_Host and libfc fc_lport structures | ||
93 | */ | ||
94 | struct fcoe_port { | ||
95 | struct fcoe_interface *fcoe; | ||
96 | struct fc_lport *lport; | ||
86 | struct sk_buff_head fcoe_pending_queue; | 97 | struct sk_buff_head fcoe_pending_queue; |
87 | u8 fcoe_pending_queue_active; | 98 | u8 fcoe_pending_queue_active; |
88 | struct timer_list timer; /* queue timer */ | 99 | struct timer_list timer; /* queue timer */ |
89 | struct fcoe_ctlr ctlr; | 100 | struct work_struct destroy_work; /* to prevent rtnl deadlocks */ |
90 | }; | 101 | }; |
91 | 102 | ||
92 | #define fcoe_from_ctlr(fc) container_of(fc, struct fcoe_softc, ctlr) | 103 | #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) |
93 | 104 | ||
94 | static inline struct net_device *fcoe_netdev( | 105 | static inline struct net_device *fcoe_netdev(const struct fc_lport *lp) |
95 | const struct fc_lport *lp) | ||
96 | { | 106 | { |
97 | return ((struct fcoe_softc *)lport_priv(lp))->real_dev; | 107 | return ((struct fcoe_port *)lport_priv(lp))->fcoe->netdev; |
98 | } | 108 | } |
99 | 109 | ||
100 | #endif /* _FCOE_H_ */ | 110 | #endif /* _FCOE_H_ */ |
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index f544340d318b..62a4c2026072 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c | |||
@@ -69,7 +69,7 @@ do { \ | |||
69 | do { \ | 69 | do { \ |
70 | CMD; \ | 70 | CMD; \ |
71 | } while (0); \ | 71 | } while (0); \ |
72 | } while (0); | 72 | } while (0) |
73 | 73 | ||
74 | #define LIBFCOE_DBG(fmt, args...) \ | 74 | #define LIBFCOE_DBG(fmt, args...) \ |
75 | LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING, \ | 75 | LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING, \ |
@@ -148,13 +148,17 @@ static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip) | |||
148 | */ | 148 | */ |
149 | void fcoe_ctlr_destroy(struct fcoe_ctlr *fip) | 149 | void fcoe_ctlr_destroy(struct fcoe_ctlr *fip) |
150 | { | 150 | { |
151 | flush_work(&fip->recv_work); | 151 | cancel_work_sync(&fip->recv_work); |
152 | spin_lock_bh(&fip->fip_recv_list.lock); | ||
153 | __skb_queue_purge(&fip->fip_recv_list); | ||
154 | spin_unlock_bh(&fip->fip_recv_list.lock); | ||
155 | |||
152 | spin_lock_bh(&fip->lock); | 156 | spin_lock_bh(&fip->lock); |
153 | fip->state = FIP_ST_DISABLED; | 157 | fip->state = FIP_ST_DISABLED; |
154 | fcoe_ctlr_reset_fcfs(fip); | 158 | fcoe_ctlr_reset_fcfs(fip); |
155 | spin_unlock_bh(&fip->lock); | 159 | spin_unlock_bh(&fip->lock); |
156 | del_timer_sync(&fip->timer); | 160 | del_timer_sync(&fip->timer); |
157 | flush_work(&fip->link_work); | 161 | cancel_work_sync(&fip->link_work); |
158 | } | 162 | } |
159 | EXPORT_SYMBOL(fcoe_ctlr_destroy); | 163 | EXPORT_SYMBOL(fcoe_ctlr_destroy); |
160 | 164 | ||
@@ -413,10 +417,18 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, | |||
413 | struct fip_mac_desc *mac; | 417 | struct fip_mac_desc *mac; |
414 | struct fcoe_fcf *fcf; | 418 | struct fcoe_fcf *fcf; |
415 | size_t dlen; | 419 | size_t dlen; |
420 | u16 fip_flags; | ||
416 | 421 | ||
417 | fcf = fip->sel_fcf; | 422 | fcf = fip->sel_fcf; |
418 | if (!fcf) | 423 | if (!fcf) |
419 | return -ENODEV; | 424 | return -ENODEV; |
425 | |||
426 | /* set flags according to both FCF and lport's capability on SPMA */ | ||
427 | fip_flags = fcf->flags; | ||
428 | fip_flags &= fip->spma ? FIP_FL_SPMA | FIP_FL_FPMA : FIP_FL_FPMA; | ||
429 | if (!fip_flags) | ||
430 | return -ENODEV; | ||
431 | |||
420 | dlen = sizeof(struct fip_encaps) + skb->len; /* len before push */ | 432 | dlen = sizeof(struct fip_encaps) + skb->len; /* len before push */ |
421 | cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap)); | 433 | cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap)); |
422 | 434 | ||
@@ -429,9 +441,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, | |||
429 | cap->fip.fip_op = htons(FIP_OP_LS); | 441 | cap->fip.fip_op = htons(FIP_OP_LS); |
430 | cap->fip.fip_subcode = FIP_SC_REQ; | 442 | cap->fip.fip_subcode = FIP_SC_REQ; |
431 | cap->fip.fip_dl_len = htons((dlen + sizeof(*mac)) / FIP_BPW); | 443 | cap->fip.fip_dl_len = htons((dlen + sizeof(*mac)) / FIP_BPW); |
432 | cap->fip.fip_flags = htons(FIP_FL_FPMA); | 444 | cap->fip.fip_flags = htons(fip_flags); |
433 | if (fip->spma) | ||
434 | cap->fip.fip_flags |= htons(FIP_FL_SPMA); | ||
435 | 445 | ||
436 | cap->encaps.fd_desc.fip_dtype = dtype; | 446 | cap->encaps.fd_desc.fip_dtype = dtype; |
437 | cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW; | 447 | cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW; |
@@ -879,7 +889,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
879 | stats->RxFrames++; | 889 | stats->RxFrames++; |
880 | stats->RxWords += skb->len / FIP_BPW; | 890 | stats->RxWords += skb->len / FIP_BPW; |
881 | 891 | ||
882 | fc_exch_recv(lp, lp->emp, fp); | 892 | fc_exch_recv(lp, fp); |
883 | return; | 893 | return; |
884 | 894 | ||
885 | len_err: | 895 | len_err: |
@@ -1104,7 +1114,6 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1104 | struct fcoe_fcf *sel; | 1114 | struct fcoe_fcf *sel; |
1105 | struct fcoe_fcf *fcf; | 1115 | struct fcoe_fcf *fcf; |
1106 | unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); | 1116 | unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); |
1107 | DECLARE_MAC_BUF(buf); | ||
1108 | u8 send_ctlr_ka; | 1117 | u8 send_ctlr_ka; |
1109 | u8 send_port_ka; | 1118 | u8 send_port_ka; |
1110 | 1119 | ||
@@ -1128,9 +1137,8 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1128 | fcf = sel; /* the old FCF may have been freed */ | 1137 | fcf = sel; /* the old FCF may have been freed */ |
1129 | if (sel) { | 1138 | if (sel) { |
1130 | printk(KERN_INFO "libfcoe: host%d: FIP selected " | 1139 | printk(KERN_INFO "libfcoe: host%d: FIP selected " |
1131 | "Fibre-Channel Forwarder MAC %s\n", | 1140 | "Fibre-Channel Forwarder MAC %pM\n", |
1132 | fip->lp->host->host_no, | 1141 | fip->lp->host->host_no, sel->fcf_mac); |
1133 | print_mac(buf, sel->fcf_mac)); | ||
1134 | memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN); | 1142 | memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN); |
1135 | fip->port_ka_time = jiffies + | 1143 | fip->port_ka_time = jiffies + |
1136 | msecs_to_jiffies(FIP_VN_KA_PERIOD); | 1144 | msecs_to_jiffies(FIP_VN_KA_PERIOD); |