1a703e490SVasu Dev /* 2a703e490SVasu Dev * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved. 3a703e490SVasu Dev * 4a703e490SVasu Dev * This program is free software; you can redistribute it and/or modify it 5a703e490SVasu Dev * under the terms and conditions of the GNU General Public License, 6a703e490SVasu Dev * version 2, as published by the Free Software Foundation. 7a703e490SVasu Dev * 8a703e490SVasu Dev * This program is distributed in the hope it will be useful, but WITHOUT 9a703e490SVasu Dev * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10a703e490SVasu Dev * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11a703e490SVasu Dev * more details. 12a703e490SVasu Dev * 13a703e490SVasu Dev * You should have received a copy of the GNU General Public License along with 14a703e490SVasu Dev * this program; if not, write to the Free Software Foundation, Inc., 15a703e490SVasu Dev * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16a703e490SVasu Dev * 17a703e490SVasu Dev * Maintained at www.Open-FCoE.org 18a703e490SVasu Dev */ 19a703e490SVasu Dev 20a703e490SVasu Dev #include <linux/module.h> 21a703e490SVasu Dev #include <linux/version.h> 22a703e490SVasu Dev #include <linux/spinlock.h> 23a703e490SVasu Dev #include <linux/netdevice.h> 24a703e490SVasu Dev #include <linux/etherdevice.h> 25a703e490SVasu Dev #include <linux/ethtool.h> 26a703e490SVasu Dev #include <linux/if_ether.h> 27a703e490SVasu Dev #include <linux/if_vlan.h> 28a703e490SVasu Dev #include <linux/crc32.h> 29a703e490SVasu Dev #include <linux/cpu.h> 30a703e490SVasu Dev #include <linux/fs.h> 31a703e490SVasu Dev #include <linux/sysfs.h> 32a703e490SVasu Dev #include <linux/ctype.h> 33a703e490SVasu Dev #include <scsi/scsi_tcq.h> 34a703e490SVasu Dev #include <scsi/scsicam.h> 35a703e490SVasu Dev #include <scsi/scsi_transport.h> 36a703e490SVasu Dev #include <scsi/scsi_transport_fc.h> 37a703e490SVasu Dev #include <net/rtnetlink.h> 38a703e490SVasu Dev 39a703e490SVasu Dev #include <scsi/fc/fc_encaps.h> 4097c8389dSJoe Eykholt #include <scsi/fc/fc_fip.h> 41a703e490SVasu Dev 42a703e490SVasu Dev #include <scsi/libfc.h> 43a703e490SVasu Dev #include <scsi/fc_frame.h> 44a703e490SVasu Dev #include <scsi/libfcoe.h> 45a703e490SVasu Dev 46fdd78027SVasu Dev #include "fcoe.h" 47fdd78027SVasu Dev 48a703e490SVasu Dev static int debug_fcoe; 49a703e490SVasu Dev 50a703e490SVasu Dev MODULE_AUTHOR("Open-FCoE.org"); 51a703e490SVasu Dev MODULE_DESCRIPTION("FCoE"); 529b34ecffSVasu Dev MODULE_LICENSE("GPL v2"); 53a703e490SVasu Dev 54a703e490SVasu Dev /* fcoe host list */ 55a703e490SVasu Dev LIST_HEAD(fcoe_hostlist); 56a703e490SVasu Dev DEFINE_RWLOCK(fcoe_hostlist_lock); 57a703e490SVasu Dev DEFINE_TIMER(fcoe_timer, NULL, 0, 0); 58a703e490SVasu Dev DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu); 59a703e490SVasu Dev 60dd3fd72eSChris Leech /* Function Prototypes */ 61fdd78027SVasu Dev static int fcoe_reset(struct Scsi_Host *shost); 62fdd78027SVasu Dev static int fcoe_xmit(struct fc_lport *, struct fc_frame *); 63fdd78027SVasu Dev static int fcoe_rcv(struct sk_buff *, struct net_device *, 64fdd78027SVasu Dev struct packet_type *, struct net_device *); 65fdd78027SVasu Dev static int fcoe_percpu_receive_thread(void *arg); 66fdd78027SVasu Dev static void fcoe_clean_pending_queue(struct fc_lport *lp); 67fdd78027SVasu Dev static void fcoe_percpu_clean(struct fc_lport *lp); 68fdd78027SVasu Dev static int fcoe_link_ok(struct fc_lport *lp); 69fdd78027SVasu Dev 70fdd78027SVasu Dev static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); 71fdd78027SVasu Dev static int fcoe_hostlist_add(const struct fc_lport *); 72fdd78027SVasu Dev static int fcoe_hostlist_remove(const struct fc_lport *); 73fdd78027SVasu Dev 74a703e490SVasu Dev static int fcoe_check_wait_queue(struct fc_lport *); 75a703e490SVasu Dev static int fcoe_device_notification(struct notifier_block *, ulong, void *); 76a703e490SVasu Dev static void fcoe_dev_setup(void); 77a703e490SVasu Dev static void fcoe_dev_cleanup(void); 78a703e490SVasu Dev 79a703e490SVasu Dev /* notification function from net device */ 80a703e490SVasu Dev static struct notifier_block fcoe_notifier = { 81a703e490SVasu Dev .notifier_call = fcoe_device_notification, 82a703e490SVasu Dev }; 83a703e490SVasu Dev 84a703e490SVasu Dev static struct scsi_transport_template *scsi_transport_fcoe_sw; 85a703e490SVasu Dev 86a703e490SVasu Dev struct fc_function_template fcoe_transport_function = { 87a703e490SVasu Dev .show_host_node_name = 1, 88a703e490SVasu Dev .show_host_port_name = 1, 89a703e490SVasu Dev .show_host_supported_classes = 1, 90a703e490SVasu Dev .show_host_supported_fc4s = 1, 91a703e490SVasu Dev .show_host_active_fc4s = 1, 92a703e490SVasu Dev .show_host_maxframe_size = 1, 93a703e490SVasu Dev 94a703e490SVasu Dev .show_host_port_id = 1, 95a703e490SVasu Dev .show_host_supported_speeds = 1, 96a703e490SVasu Dev .get_host_speed = fc_get_host_speed, 97a703e490SVasu Dev .show_host_speed = 1, 98a703e490SVasu Dev .show_host_port_type = 1, 99a703e490SVasu Dev .get_host_port_state = fc_get_host_port_state, 100a703e490SVasu Dev .show_host_port_state = 1, 101a703e490SVasu Dev .show_host_symbolic_name = 1, 102a703e490SVasu Dev 103a703e490SVasu Dev .dd_fcrport_size = sizeof(struct fc_rport_libfc_priv), 104a703e490SVasu Dev .show_rport_maxframe_size = 1, 105a703e490SVasu Dev .show_rport_supported_classes = 1, 106a703e490SVasu Dev 107a703e490SVasu Dev .show_host_fabric_name = 1, 108a703e490SVasu Dev .show_starget_node_name = 1, 109a703e490SVasu Dev .show_starget_port_name = 1, 110a703e490SVasu Dev .show_starget_port_id = 1, 111a703e490SVasu Dev .set_rport_dev_loss_tmo = fc_set_rport_loss_tmo, 112a703e490SVasu Dev .show_rport_dev_loss_tmo = 1, 113a703e490SVasu Dev .get_fc_host_stats = fc_get_host_stats, 114a703e490SVasu Dev .issue_fc_host_lip = fcoe_reset, 115a703e490SVasu Dev 116a703e490SVasu Dev .terminate_rport_io = fc_rport_terminate_io, 117a703e490SVasu Dev }; 118a703e490SVasu Dev 119a703e490SVasu Dev static struct scsi_host_template fcoe_shost_template = { 120a703e490SVasu Dev .module = THIS_MODULE, 121a703e490SVasu Dev .name = "FCoE Driver", 122a703e490SVasu Dev .proc_name = FCOE_NAME, 123a703e490SVasu Dev .queuecommand = fc_queuecommand, 124a703e490SVasu Dev .eh_abort_handler = fc_eh_abort, 125a703e490SVasu Dev .eh_device_reset_handler = fc_eh_device_reset, 126a703e490SVasu Dev .eh_host_reset_handler = fc_eh_host_reset, 127a703e490SVasu Dev .slave_alloc = fc_slave_alloc, 128a703e490SVasu Dev .change_queue_depth = fc_change_queue_depth, 129a703e490SVasu Dev .change_queue_type = fc_change_queue_type, 130a703e490SVasu Dev .this_id = -1, 131a703e490SVasu Dev .cmd_per_lun = 32, 132a703e490SVasu Dev .can_queue = FCOE_MAX_OUTSTANDING_COMMANDS, 133a703e490SVasu Dev .use_clustering = ENABLE_CLUSTERING, 134a703e490SVasu Dev .sg_tablesize = SG_ALL, 135a703e490SVasu Dev .max_sectors = 0xffff, 136a703e490SVasu Dev }; 137a703e490SVasu Dev 138a703e490SVasu Dev /** 139a703e490SVasu Dev * fcoe_lport_config() - sets up the fc_lport 140a703e490SVasu Dev * @lp: ptr to the fc_lport 141a703e490SVasu Dev * 142a703e490SVasu Dev * Returns: 0 for success 143a703e490SVasu Dev */ 144a703e490SVasu Dev static int fcoe_lport_config(struct fc_lport *lp) 145a703e490SVasu Dev { 146a703e490SVasu Dev lp->link_up = 0; 147a703e490SVasu Dev lp->qfull = 0; 148a703e490SVasu Dev lp->max_retry_count = 3; 149a3666955SAbhijeet Joglekar lp->max_rport_retry_count = 3; 150a703e490SVasu Dev lp->e_d_tov = 2 * 1000; /* FC-FS default */ 151a703e490SVasu Dev lp->r_a_tov = 2 * 2 * 1000; 152a703e490SVasu Dev lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS | 153a703e490SVasu Dev FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL); 154a703e490SVasu Dev 155a703e490SVasu Dev fc_lport_init_stats(lp); 156a703e490SVasu Dev 157a703e490SVasu Dev /* lport fc_lport related configuration */ 158a703e490SVasu Dev fc_lport_config(lp); 159a703e490SVasu Dev 160a703e490SVasu Dev /* offload related configuration */ 161a703e490SVasu Dev lp->crc_offload = 0; 162a703e490SVasu Dev lp->seq_offload = 0; 163a703e490SVasu Dev lp->lro_enabled = 0; 164a703e490SVasu Dev lp->lro_xid = 0; 165a703e490SVasu Dev lp->lso_max = 0; 166a703e490SVasu Dev 167a703e490SVasu Dev return 0; 168a703e490SVasu Dev } 169a703e490SVasu Dev 170a703e490SVasu Dev /** 171a703e490SVasu Dev * fcoe_netdev_config() - Set up netdev for SW FCoE 172a703e490SVasu Dev * @lp : ptr to the fc_lport 173a703e490SVasu Dev * @netdev : ptr to the associated netdevice struct 174a703e490SVasu Dev * 175a703e490SVasu Dev * Must be called after fcoe_lport_config() as it will use lport mutex 176a703e490SVasu Dev * 177a703e490SVasu Dev * Returns : 0 for success 178a703e490SVasu Dev */ 179a703e490SVasu Dev static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) 180a703e490SVasu Dev { 181a703e490SVasu Dev u32 mfs; 182a703e490SVasu Dev u64 wwnn, wwpn; 183a703e490SVasu Dev struct fcoe_softc *fc; 184a703e490SVasu Dev u8 flogi_maddr[ETH_ALEN]; 185a703e490SVasu Dev 186a703e490SVasu Dev /* Setup lport private data to point to fcoe softc */ 187a703e490SVasu Dev fc = lport_priv(lp); 18897c8389dSJoe Eykholt fc->ctlr.lp = lp; 189a703e490SVasu Dev fc->real_dev = netdev; 190a703e490SVasu Dev fc->phys_dev = netdev; 191a703e490SVasu Dev 192a703e490SVasu Dev /* Require support for get_pauseparam ethtool op. */ 193a703e490SVasu Dev if (netdev->priv_flags & IFF_802_1Q_VLAN) 194a703e490SVasu Dev fc->phys_dev = vlan_dev_real_dev(netdev); 195a703e490SVasu Dev 196a703e490SVasu Dev /* Do not support for bonding device */ 197a703e490SVasu Dev if ((fc->real_dev->priv_flags & IFF_MASTER_ALB) || 198a703e490SVasu Dev (fc->real_dev->priv_flags & IFF_SLAVE_INACTIVE) || 199a703e490SVasu Dev (fc->real_dev->priv_flags & IFF_MASTER_8023AD)) { 200a703e490SVasu Dev return -EOPNOTSUPP; 201a703e490SVasu Dev } 202a703e490SVasu Dev 203a703e490SVasu Dev /* 204a703e490SVasu Dev * Determine max frame size based on underlying device and optional 205a703e490SVasu Dev * user-configured limit. If the MFS is too low, fcoe_link_ok() 206a703e490SVasu Dev * will return 0, so do this first. 207a703e490SVasu Dev */ 208a703e490SVasu Dev mfs = fc->real_dev->mtu - (sizeof(struct fcoe_hdr) + 209a703e490SVasu Dev sizeof(struct fcoe_crc_eof)); 210a703e490SVasu Dev if (fc_set_mfs(lp, mfs)) 211a703e490SVasu Dev return -EINVAL; 212a703e490SVasu Dev 213a703e490SVasu Dev /* offload features support */ 214a703e490SVasu Dev if (fc->real_dev->features & NETIF_F_SG) 215a703e490SVasu Dev lp->sg_supp = 1; 216a703e490SVasu Dev 217a703e490SVasu Dev #ifdef NETIF_F_FCOE_CRC 218a703e490SVasu Dev if (netdev->features & NETIF_F_FCOE_CRC) { 219a703e490SVasu Dev lp->crc_offload = 1; 220a703e490SVasu Dev printk(KERN_DEBUG "fcoe:%s supports FCCRC offload\n", 221a703e490SVasu Dev netdev->name); 222a703e490SVasu Dev } 223a703e490SVasu Dev #endif 224a703e490SVasu Dev #ifdef NETIF_F_FSO 225a703e490SVasu Dev if (netdev->features & NETIF_F_FSO) { 226a703e490SVasu Dev lp->seq_offload = 1; 227a703e490SVasu Dev lp->lso_max = netdev->gso_max_size; 228a703e490SVasu Dev printk(KERN_DEBUG "fcoe:%s supports LSO for max len 0x%x\n", 229a703e490SVasu Dev netdev->name, lp->lso_max); 230a703e490SVasu Dev } 231a703e490SVasu Dev #endif 232a703e490SVasu Dev if (netdev->fcoe_ddp_xid) { 233a703e490SVasu Dev lp->lro_enabled = 1; 234a703e490SVasu Dev lp->lro_xid = netdev->fcoe_ddp_xid; 235a703e490SVasu Dev printk(KERN_DEBUG "fcoe:%s supports LRO for max xid 0x%x\n", 236a703e490SVasu Dev netdev->name, lp->lro_xid); 237a703e490SVasu Dev } 238a703e490SVasu Dev skb_queue_head_init(&fc->fcoe_pending_queue); 239a703e490SVasu Dev fc->fcoe_pending_queue_active = 0; 240a703e490SVasu Dev 241a703e490SVasu Dev /* setup Source Mac Address */ 24297c8389dSJoe Eykholt memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr, 243a703e490SVasu Dev fc->real_dev->addr_len); 244a703e490SVasu Dev 245a703e490SVasu Dev wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0); 246a703e490SVasu Dev fc_set_wwnn(lp, wwnn); 247a703e490SVasu Dev /* XXX - 3rd arg needs to be vlan id */ 248a703e490SVasu Dev wwpn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 2, 0); 249a703e490SVasu Dev fc_set_wwpn(lp, wwpn); 250a703e490SVasu Dev 251a703e490SVasu Dev /* 252a703e490SVasu Dev * Add FCoE MAC address as second unicast MAC address 253a703e490SVasu Dev * or enter promiscuous mode if not capable of listening 254a703e490SVasu Dev * for multiple unicast MACs. 255a703e490SVasu Dev */ 256a703e490SVasu Dev rtnl_lock(); 257a703e490SVasu Dev memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); 258a703e490SVasu Dev dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN); 2596401bdcaSJoe Eykholt dev_mc_add(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); 260a703e490SVasu Dev rtnl_unlock(); 261a703e490SVasu Dev 262a703e490SVasu Dev /* 263a703e490SVasu Dev * setup the receive function from ethernet driver 264a703e490SVasu Dev * on the ethertype for the given device 265a703e490SVasu Dev */ 266a703e490SVasu Dev fc->fcoe_packet_type.func = fcoe_rcv; 267a703e490SVasu Dev fc->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE); 268a703e490SVasu Dev fc->fcoe_packet_type.dev = fc->real_dev; 269a703e490SVasu Dev dev_add_pack(&fc->fcoe_packet_type); 270a703e490SVasu Dev 271a703e490SVasu Dev return 0; 272a703e490SVasu Dev } 273a703e490SVasu Dev 274a703e490SVasu Dev /** 275a703e490SVasu Dev * fcoe_shost_config() - Sets up fc_lport->host 276a703e490SVasu Dev * @lp : ptr to the fc_lport 277a703e490SVasu Dev * @shost : ptr to the associated scsi host 278a703e490SVasu Dev * @dev : device associated to scsi host 279a703e490SVasu Dev * 280a703e490SVasu Dev * Must be called after fcoe_lport_config() and fcoe_netdev_config() 281a703e490SVasu Dev * 282a703e490SVasu Dev * Returns : 0 for success 283a703e490SVasu Dev */ 284a703e490SVasu Dev static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, 285a703e490SVasu Dev struct device *dev) 286a703e490SVasu Dev { 287a703e490SVasu Dev int rc = 0; 288a703e490SVasu Dev 289a703e490SVasu Dev /* lport scsi host config */ 290a703e490SVasu Dev lp->host = shost; 291a703e490SVasu Dev 292a703e490SVasu Dev lp->host->max_lun = FCOE_MAX_LUN; 293a703e490SVasu Dev lp->host->max_id = FCOE_MAX_FCP_TARGET; 294a703e490SVasu Dev lp->host->max_channel = 0; 295a703e490SVasu Dev lp->host->transportt = scsi_transport_fcoe_sw; 296a703e490SVasu Dev 297a703e490SVasu Dev /* add the new host to the SCSI-ml */ 298a703e490SVasu Dev rc = scsi_add_host(lp->host, dev); 299a703e490SVasu Dev if (rc) { 300a703e490SVasu Dev FC_DBG("fcoe_shost_config:error on scsi_add_host\n"); 301a703e490SVasu Dev return rc; 302a703e490SVasu Dev } 303a703e490SVasu Dev sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s", 304a703e490SVasu Dev FCOE_NAME, FCOE_VERSION, 305a703e490SVasu Dev fcoe_netdev(lp)->name); 306a703e490SVasu Dev 307a703e490SVasu Dev return 0; 308a703e490SVasu Dev } 309a703e490SVasu Dev 310a703e490SVasu Dev /** 311a703e490SVasu Dev * fcoe_em_config() - allocates em for this lport 312a703e490SVasu Dev * @lp: the port that em is to allocated for 313a703e490SVasu Dev * 314a703e490SVasu Dev * Returns : 0 on success 315a703e490SVasu Dev */ 316a703e490SVasu Dev static inline int fcoe_em_config(struct fc_lport *lp) 317a703e490SVasu Dev { 318a703e490SVasu Dev BUG_ON(lp->emp); 319a703e490SVasu Dev 320a703e490SVasu Dev lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3, 321a703e490SVasu Dev FCOE_MIN_XID, FCOE_MAX_XID); 322a703e490SVasu Dev if (!lp->emp) 323a703e490SVasu Dev return -ENOMEM; 324a703e490SVasu Dev 325a703e490SVasu Dev return 0; 326a703e490SVasu Dev } 327a703e490SVasu Dev 328a703e490SVasu Dev /** 329a703e490SVasu Dev * fcoe_if_destroy() - FCoE software HBA tear-down function 330a703e490SVasu Dev * @netdev: ptr to the associated net_device 331a703e490SVasu Dev * 332a703e490SVasu Dev * Returns: 0 if link is OK for use by FCoE. 333a703e490SVasu Dev */ 334a703e490SVasu Dev static int fcoe_if_destroy(struct net_device *netdev) 335a703e490SVasu Dev { 336a703e490SVasu Dev struct fc_lport *lp = NULL; 337a703e490SVasu Dev struct fcoe_softc *fc; 338a703e490SVasu Dev u8 flogi_maddr[ETH_ALEN]; 339a703e490SVasu Dev 340a703e490SVasu Dev BUG_ON(!netdev); 341a703e490SVasu Dev 342a703e490SVasu Dev printk(KERN_DEBUG "fcoe_if_destroy:interface on %s\n", 343a703e490SVasu Dev netdev->name); 344a703e490SVasu Dev 345a703e490SVasu Dev lp = fcoe_hostlist_lookup(netdev); 346a703e490SVasu Dev if (!lp) 347a703e490SVasu Dev return -ENODEV; 348a703e490SVasu Dev 349a703e490SVasu Dev fc = lport_priv(lp); 350a703e490SVasu Dev 351a703e490SVasu Dev /* Logout of the fabric */ 352a703e490SVasu Dev fc_fabric_logoff(lp); 353a703e490SVasu Dev 354a703e490SVasu Dev /* Remove the instance from fcoe's list */ 355a703e490SVasu Dev fcoe_hostlist_remove(lp); 356a703e490SVasu Dev 357a703e490SVasu Dev /* Don't listen for Ethernet packets anymore */ 358a703e490SVasu Dev dev_remove_pack(&fc->fcoe_packet_type); 35997c8389dSJoe Eykholt dev_remove_pack(&fc->fip_packet_type); 36097c8389dSJoe Eykholt fcoe_ctlr_destroy(&fc->ctlr); 361a703e490SVasu Dev 362a703e490SVasu Dev /* Cleanup the fc_lport */ 363a703e490SVasu Dev fc_lport_destroy(lp); 364a703e490SVasu Dev fc_fcp_destroy(lp); 365a703e490SVasu Dev 366a703e490SVasu Dev /* Detach from the scsi-ml */ 367a703e490SVasu Dev fc_remove_host(lp->host); 368a703e490SVasu Dev scsi_remove_host(lp->host); 369a703e490SVasu Dev 370a703e490SVasu Dev /* There are no more rports or I/O, free the EM */ 371a703e490SVasu Dev if (lp->emp) 372a703e490SVasu Dev fc_exch_mgr_free(lp->emp); 373a703e490SVasu Dev 374a703e490SVasu Dev /* Delete secondary MAC addresses */ 375a703e490SVasu Dev rtnl_lock(); 376a703e490SVasu Dev memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); 377a703e490SVasu Dev dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN); 37897c8389dSJoe Eykholt if (!is_zero_ether_addr(fc->ctlr.data_src_addr)) 37997c8389dSJoe Eykholt dev_unicast_delete(fc->real_dev, 38097c8389dSJoe Eykholt fc->ctlr.data_src_addr, ETH_ALEN); 38197c8389dSJoe Eykholt dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); 382a703e490SVasu Dev rtnl_unlock(); 383a703e490SVasu Dev 384dd3fd72eSChris Leech /* Free the per-CPU receive threads */ 385a703e490SVasu Dev fcoe_percpu_clean(lp); 386a703e490SVasu Dev 387a703e490SVasu Dev /* Free existing skbs */ 388a703e490SVasu Dev fcoe_clean_pending_queue(lp); 389a703e490SVasu Dev 390a703e490SVasu Dev /* Free memory used by statistical counters */ 391a703e490SVasu Dev fc_lport_free_stats(lp); 392a703e490SVasu Dev 393a703e490SVasu Dev /* Release the net_device and Scsi_Host */ 394a703e490SVasu Dev dev_put(fc->real_dev); 395a703e490SVasu Dev scsi_host_put(lp->host); 396a703e490SVasu Dev 397a703e490SVasu Dev return 0; 398a703e490SVasu Dev } 399a703e490SVasu Dev 400a703e490SVasu Dev /* 401a703e490SVasu Dev * fcoe_ddp_setup - calls LLD's ddp_setup through net_device 402a703e490SVasu Dev * @lp: the corresponding fc_lport 403a703e490SVasu Dev * @xid: the exchange id for this ddp transfer 404a703e490SVasu Dev * @sgl: the scatterlist describing this transfer 405a703e490SVasu Dev * @sgc: number of sg items 406a703e490SVasu Dev * 407a703e490SVasu Dev * Returns : 0 no ddp 408a703e490SVasu Dev */ 409a703e490SVasu Dev static int fcoe_ddp_setup(struct fc_lport *lp, u16 xid, 410a703e490SVasu Dev struct scatterlist *sgl, unsigned int sgc) 411a703e490SVasu Dev { 412a703e490SVasu Dev struct net_device *n = fcoe_netdev(lp); 413a703e490SVasu Dev 414a703e490SVasu Dev if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_setup) 415a703e490SVasu Dev return n->netdev_ops->ndo_fcoe_ddp_setup(n, xid, sgl, sgc); 416a703e490SVasu Dev 417a703e490SVasu Dev return 0; 418a703e490SVasu Dev } 419a703e490SVasu Dev 420a703e490SVasu Dev /* 421a703e490SVasu Dev * fcoe_ddp_done - calls LLD's ddp_done through net_device 422a703e490SVasu Dev * @lp: the corresponding fc_lport 423a703e490SVasu Dev * @xid: the exchange id for this ddp transfer 424a703e490SVasu Dev * 425a703e490SVasu Dev * Returns : the length of data that have been completed by ddp 426a703e490SVasu Dev */ 427a703e490SVasu Dev static int fcoe_ddp_done(struct fc_lport *lp, u16 xid) 428a703e490SVasu Dev { 429a703e490SVasu Dev struct net_device *n = fcoe_netdev(lp); 430a703e490SVasu Dev 431a703e490SVasu Dev if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_done) 432a703e490SVasu Dev return n->netdev_ops->ndo_fcoe_ddp_done(n, xid); 433a703e490SVasu Dev return 0; 434a703e490SVasu Dev } 435a703e490SVasu Dev 436a703e490SVasu Dev static struct libfc_function_template fcoe_libfc_fcn_templ = { 437a703e490SVasu Dev .frame_send = fcoe_xmit, 438a703e490SVasu Dev .ddp_setup = fcoe_ddp_setup, 439a703e490SVasu Dev .ddp_done = fcoe_ddp_done, 440a703e490SVasu Dev }; 441a703e490SVasu Dev 442a703e490SVasu Dev /** 44397c8389dSJoe Eykholt * fcoe_fip_recv - handle a received FIP frame. 44497c8389dSJoe Eykholt * @skb: the receive skb 44597c8389dSJoe Eykholt * @dev: associated &net_device 44697c8389dSJoe Eykholt * @ptype: the &packet_type structure which was used to register this handler. 44797c8389dSJoe Eykholt * @orig_dev: original receive &net_device, in case @dev is a bond. 44897c8389dSJoe Eykholt * 44997c8389dSJoe Eykholt * Returns: 0 for success 45097c8389dSJoe Eykholt */ 45197c8389dSJoe Eykholt static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev, 45297c8389dSJoe Eykholt struct packet_type *ptype, 45397c8389dSJoe Eykholt struct net_device *orig_dev) 45497c8389dSJoe Eykholt { 45597c8389dSJoe Eykholt struct fcoe_softc *fc; 45697c8389dSJoe Eykholt 45797c8389dSJoe Eykholt fc = container_of(ptype, struct fcoe_softc, fip_packet_type); 45897c8389dSJoe Eykholt fcoe_ctlr_recv(&fc->ctlr, skb); 45997c8389dSJoe Eykholt return 0; 46097c8389dSJoe Eykholt } 46197c8389dSJoe Eykholt 46297c8389dSJoe Eykholt /** 46397c8389dSJoe Eykholt * fcoe_fip_send() - send an Ethernet-encapsulated FIP frame. 46497c8389dSJoe Eykholt * @fip: FCoE controller. 46597c8389dSJoe Eykholt * @skb: FIP Packet. 46697c8389dSJoe Eykholt */ 46797c8389dSJoe Eykholt static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) 46897c8389dSJoe Eykholt { 46997c8389dSJoe Eykholt skb->dev = fcoe_from_ctlr(fip)->real_dev; 47097c8389dSJoe Eykholt dev_queue_xmit(skb); 47197c8389dSJoe Eykholt } 47297c8389dSJoe Eykholt 47397c8389dSJoe Eykholt /** 47497c8389dSJoe Eykholt * fcoe_update_src_mac() - Update Ethernet MAC filters. 47597c8389dSJoe Eykholt * @fip: FCoE controller. 47697c8389dSJoe Eykholt * @old: Unicast MAC address to delete if the MAC is non-zero. 47797c8389dSJoe Eykholt * @new: Unicast MAC address to add. 47897c8389dSJoe Eykholt * 47997c8389dSJoe Eykholt * Remove any previously-set unicast MAC filter. 48097c8389dSJoe Eykholt * Add secondary FCoE MAC address filter for our OUI. 48197c8389dSJoe Eykholt */ 48297c8389dSJoe Eykholt static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new) 48397c8389dSJoe Eykholt { 48497c8389dSJoe Eykholt struct fcoe_softc *fc; 48597c8389dSJoe Eykholt 48697c8389dSJoe Eykholt fc = fcoe_from_ctlr(fip); 48797c8389dSJoe Eykholt rtnl_lock(); 48897c8389dSJoe Eykholt if (!is_zero_ether_addr(old)) 48997c8389dSJoe Eykholt dev_unicast_delete(fc->real_dev, old, ETH_ALEN); 49097c8389dSJoe Eykholt dev_unicast_add(fc->real_dev, new, ETH_ALEN); 49197c8389dSJoe Eykholt rtnl_unlock(); 49297c8389dSJoe Eykholt } 49397c8389dSJoe Eykholt 49497c8389dSJoe Eykholt /** 495a703e490SVasu Dev * fcoe_if_create() - this function creates the fcoe interface 496a703e490SVasu Dev * @netdev: pointer the associated netdevice 497a703e490SVasu Dev * 498a703e490SVasu Dev * Creates fc_lport struct and scsi_host for lport, configures lport 499a703e490SVasu Dev * and starts fabric login. 500a703e490SVasu Dev * 501a703e490SVasu Dev * Returns : 0 on success 502a703e490SVasu Dev */ 503a703e490SVasu Dev static int fcoe_if_create(struct net_device *netdev) 504a703e490SVasu Dev { 505a703e490SVasu Dev int rc; 506a703e490SVasu Dev struct fc_lport *lp = NULL; 507a703e490SVasu Dev struct fcoe_softc *fc; 508a703e490SVasu Dev struct Scsi_Host *shost; 509a703e490SVasu Dev 510a703e490SVasu Dev BUG_ON(!netdev); 511a703e490SVasu Dev 512a703e490SVasu Dev printk(KERN_DEBUG "fcoe_if_create:interface on %s\n", 513a703e490SVasu Dev netdev->name); 514a703e490SVasu Dev 515a703e490SVasu Dev lp = fcoe_hostlist_lookup(netdev); 516a703e490SVasu Dev if (lp) 517a703e490SVasu Dev return -EEXIST; 518a703e490SVasu Dev 519a0a25da2SVasu Dev shost = libfc_host_alloc(&fcoe_shost_template, 520a703e490SVasu Dev sizeof(struct fcoe_softc)); 521a703e490SVasu Dev if (!shost) { 522a703e490SVasu Dev FC_DBG("Could not allocate host structure\n"); 523a703e490SVasu Dev return -ENOMEM; 524a703e490SVasu Dev } 525a703e490SVasu Dev lp = shost_priv(shost); 526a703e490SVasu Dev fc = lport_priv(lp); 527a703e490SVasu Dev 528a703e490SVasu Dev /* configure fc_lport, e.g., em */ 529a703e490SVasu Dev rc = fcoe_lport_config(lp); 530a703e490SVasu Dev if (rc) { 531a703e490SVasu Dev FC_DBG("Could not configure lport\n"); 532a703e490SVasu Dev goto out_host_put; 533a703e490SVasu Dev } 534a703e490SVasu Dev 535a703e490SVasu Dev /* configure lport network properties */ 536a703e490SVasu Dev rc = fcoe_netdev_config(lp, netdev); 537a703e490SVasu Dev if (rc) { 538a703e490SVasu Dev FC_DBG("Could not configure netdev for lport\n"); 539a703e490SVasu Dev goto out_host_put; 540a703e490SVasu Dev } 541a703e490SVasu Dev 54297c8389dSJoe Eykholt /* 54397c8389dSJoe Eykholt * Initialize FIP. 54497c8389dSJoe Eykholt */ 54597c8389dSJoe Eykholt fcoe_ctlr_init(&fc->ctlr); 54697c8389dSJoe Eykholt fc->ctlr.send = fcoe_fip_send; 54797c8389dSJoe Eykholt fc->ctlr.update_mac = fcoe_update_src_mac; 54897c8389dSJoe Eykholt 54997c8389dSJoe Eykholt fc->fip_packet_type.func = fcoe_fip_recv; 55097c8389dSJoe Eykholt fc->fip_packet_type.type = htons(ETH_P_FIP); 55197c8389dSJoe Eykholt fc->fip_packet_type.dev = fc->real_dev; 55297c8389dSJoe Eykholt dev_add_pack(&fc->fip_packet_type); 55397c8389dSJoe Eykholt 554a703e490SVasu Dev /* configure lport scsi host properties */ 555a703e490SVasu Dev rc = fcoe_shost_config(lp, shost, &netdev->dev); 556a703e490SVasu Dev if (rc) { 557a703e490SVasu Dev FC_DBG("Could not configure shost for lport\n"); 558a703e490SVasu Dev goto out_host_put; 559a703e490SVasu Dev } 560a703e490SVasu Dev 561a703e490SVasu Dev /* lport exch manager allocation */ 562a703e490SVasu Dev rc = fcoe_em_config(lp); 563a703e490SVasu Dev if (rc) { 564a703e490SVasu Dev FC_DBG("Could not configure em for lport\n"); 565a703e490SVasu Dev goto out_host_put; 566a703e490SVasu Dev } 567a703e490SVasu Dev 568a703e490SVasu Dev /* Initialize the library */ 569a703e490SVasu Dev rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ); 570a703e490SVasu Dev if (rc) { 571a703e490SVasu Dev FC_DBG("Could not configure libfc for lport!\n"); 572a703e490SVasu Dev goto out_lp_destroy; 573a703e490SVasu Dev } 574a703e490SVasu Dev 575a703e490SVasu Dev /* add to lports list */ 576a703e490SVasu Dev fcoe_hostlist_add(lp); 577a703e490SVasu Dev 578a703e490SVasu Dev lp->boot_time = jiffies; 579a703e490SVasu Dev 580a703e490SVasu Dev fc_fabric_login(lp); 581a703e490SVasu Dev 58297c8389dSJoe Eykholt if (!fcoe_link_ok(lp)) 58397c8389dSJoe Eykholt fcoe_ctlr_link_up(&fc->ctlr); 58497c8389dSJoe Eykholt 585a703e490SVasu Dev dev_hold(netdev); 586a703e490SVasu Dev 587a703e490SVasu Dev return rc; 588a703e490SVasu Dev 589a703e490SVasu Dev out_lp_destroy: 590a703e490SVasu Dev fc_exch_mgr_free(lp->emp); /* Free the EM */ 591a703e490SVasu Dev out_host_put: 592a703e490SVasu Dev scsi_host_put(lp->host); 593a703e490SVasu Dev return rc; 594a703e490SVasu Dev } 595a703e490SVasu Dev 596a703e490SVasu Dev /** 597a703e490SVasu Dev * fcoe_if_init() - attach to scsi transport 598a703e490SVasu Dev * 599a703e490SVasu Dev * Returns : 0 on success 600a703e490SVasu Dev */ 601a703e490SVasu Dev static int __init fcoe_if_init(void) 602a703e490SVasu Dev { 603a703e490SVasu Dev /* attach to scsi transport */ 604a703e490SVasu Dev scsi_transport_fcoe_sw = 605a703e490SVasu Dev fc_attach_transport(&fcoe_transport_function); 606a703e490SVasu Dev 607a703e490SVasu Dev if (!scsi_transport_fcoe_sw) { 608a703e490SVasu Dev printk(KERN_ERR "fcoe_init:fc_attach_transport() failed\n"); 609a703e490SVasu Dev return -ENODEV; 610a703e490SVasu Dev } 611a703e490SVasu Dev 612a703e490SVasu Dev return 0; 613a703e490SVasu Dev } 614a703e490SVasu Dev 615a703e490SVasu Dev /** 616a703e490SVasu Dev * fcoe_if_exit() - detach from scsi transport 617a703e490SVasu Dev * 618a703e490SVasu Dev * Returns : 0 on success 619a703e490SVasu Dev */ 620a703e490SVasu Dev int __exit fcoe_if_exit(void) 621a703e490SVasu Dev { 622a703e490SVasu Dev fc_release_transport(scsi_transport_fcoe_sw); 623a703e490SVasu Dev return 0; 624a703e490SVasu Dev } 625a703e490SVasu Dev 626a703e490SVasu Dev /** 627a703e490SVasu Dev * fcoe_percpu_thread_create() - Create a receive thread for an online cpu 628a703e490SVasu Dev * @cpu: cpu index for the online cpu 629a703e490SVasu Dev */ 630a703e490SVasu Dev static void fcoe_percpu_thread_create(unsigned int cpu) 631a703e490SVasu Dev { 632a703e490SVasu Dev struct fcoe_percpu_s *p; 633a703e490SVasu Dev struct task_struct *thread; 634a703e490SVasu Dev 635a703e490SVasu Dev p = &per_cpu(fcoe_percpu, cpu); 636a703e490SVasu Dev 637a703e490SVasu Dev thread = kthread_create(fcoe_percpu_receive_thread, 638a703e490SVasu Dev (void *)p, "fcoethread/%d", cpu); 639a703e490SVasu Dev 640a703e490SVasu Dev if (likely(!IS_ERR(p->thread))) { 641a703e490SVasu Dev kthread_bind(thread, cpu); 642a703e490SVasu Dev wake_up_process(thread); 643a703e490SVasu Dev 644a703e490SVasu Dev spin_lock_bh(&p->fcoe_rx_list.lock); 645a703e490SVasu Dev p->thread = thread; 646a703e490SVasu Dev spin_unlock_bh(&p->fcoe_rx_list.lock); 647a703e490SVasu Dev } 648a703e490SVasu Dev } 649a703e490SVasu Dev 650a703e490SVasu Dev /** 651a703e490SVasu Dev * fcoe_percpu_thread_destroy() - removes the rx thread for the given cpu 652a703e490SVasu Dev * @cpu: cpu index the rx thread is to be removed 653a703e490SVasu Dev * 654a703e490SVasu Dev * Destroys a per-CPU Rx thread. Any pending skbs are moved to the 655a703e490SVasu Dev * current CPU's Rx thread. If the thread being destroyed is bound to 656a703e490SVasu Dev * the CPU processing this context the skbs will be freed. 657a703e490SVasu Dev */ 658a703e490SVasu Dev static void fcoe_percpu_thread_destroy(unsigned int cpu) 659a703e490SVasu Dev { 660a703e490SVasu Dev struct fcoe_percpu_s *p; 661a703e490SVasu Dev struct task_struct *thread; 662a703e490SVasu Dev struct page *crc_eof; 663a703e490SVasu Dev struct sk_buff *skb; 664a703e490SVasu Dev #ifdef CONFIG_SMP 665a703e490SVasu Dev struct fcoe_percpu_s *p0; 666a703e490SVasu Dev unsigned targ_cpu = smp_processor_id(); 667a703e490SVasu Dev #endif /* CONFIG_SMP */ 668a703e490SVasu Dev 669a703e490SVasu Dev printk(KERN_DEBUG "fcoe: Destroying receive thread for CPU %d\n", cpu); 670a703e490SVasu Dev 671a703e490SVasu Dev /* Prevent any new skbs from being queued for this CPU. */ 672a703e490SVasu Dev p = &per_cpu(fcoe_percpu, cpu); 673a703e490SVasu Dev spin_lock_bh(&p->fcoe_rx_list.lock); 674a703e490SVasu Dev thread = p->thread; 675a703e490SVasu Dev p->thread = NULL; 676a703e490SVasu Dev crc_eof = p->crc_eof_page; 677a703e490SVasu Dev p->crc_eof_page = NULL; 678a703e490SVasu Dev p->crc_eof_offset = 0; 679a703e490SVasu Dev spin_unlock_bh(&p->fcoe_rx_list.lock); 680a703e490SVasu Dev 681a703e490SVasu Dev #ifdef CONFIG_SMP 682a703e490SVasu Dev /* 683a703e490SVasu Dev * Don't bother moving the skb's if this context is running 684a703e490SVasu Dev * on the same CPU that is having its thread destroyed. This 685a703e490SVasu Dev * can easily happen when the module is removed. 686a703e490SVasu Dev */ 687a703e490SVasu Dev if (cpu != targ_cpu) { 688a703e490SVasu Dev p0 = &per_cpu(fcoe_percpu, targ_cpu); 689a703e490SVasu Dev spin_lock_bh(&p0->fcoe_rx_list.lock); 690a703e490SVasu Dev if (p0->thread) { 691a703e490SVasu Dev FC_DBG("Moving frames from CPU %d to CPU %d\n", 692a703e490SVasu Dev cpu, targ_cpu); 693a703e490SVasu Dev 694a703e490SVasu Dev while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL) 695a703e490SVasu Dev __skb_queue_tail(&p0->fcoe_rx_list, skb); 696a703e490SVasu Dev spin_unlock_bh(&p0->fcoe_rx_list.lock); 697a703e490SVasu Dev } else { 698a703e490SVasu Dev /* 699a703e490SVasu Dev * The targeted CPU is not initialized and cannot accept 700a703e490SVasu Dev * new skbs. Unlock the targeted CPU and drop the skbs 701a703e490SVasu Dev * on the CPU that is going offline. 702a703e490SVasu Dev */ 703a703e490SVasu Dev while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL) 704a703e490SVasu Dev kfree_skb(skb); 705a703e490SVasu Dev spin_unlock_bh(&p0->fcoe_rx_list.lock); 706a703e490SVasu Dev } 707a703e490SVasu Dev } else { 708a703e490SVasu Dev /* 709a703e490SVasu Dev * This scenario occurs when the module is being removed 710a703e490SVasu Dev * and all threads are being destroyed. skbs will continue 711a703e490SVasu Dev * to be shifted from the CPU thread that is being removed 712a703e490SVasu Dev * to the CPU thread associated with the CPU that is processing 713a703e490SVasu Dev * the module removal. Once there is only one CPU Rx thread it 714a703e490SVasu Dev * will reach this case and we will drop all skbs and later 715a703e490SVasu Dev * stop the thread. 716a703e490SVasu Dev */ 717a703e490SVasu Dev spin_lock_bh(&p->fcoe_rx_list.lock); 718a703e490SVasu Dev while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL) 719a703e490SVasu Dev kfree_skb(skb); 720a703e490SVasu Dev spin_unlock_bh(&p->fcoe_rx_list.lock); 721a703e490SVasu Dev } 722a703e490SVasu Dev #else 723a703e490SVasu Dev /* 724dd3fd72eSChris Leech * This a non-SMP scenario where the singular Rx thread is 725a703e490SVasu Dev * being removed. Free all skbs and stop the thread. 726a703e490SVasu Dev */ 727a703e490SVasu Dev spin_lock_bh(&p->fcoe_rx_list.lock); 728a703e490SVasu Dev while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL) 729a703e490SVasu Dev kfree_skb(skb); 730a703e490SVasu Dev spin_unlock_bh(&p->fcoe_rx_list.lock); 731a703e490SVasu Dev #endif 732a703e490SVasu Dev 733a703e490SVasu Dev if (thread) 734a703e490SVasu Dev kthread_stop(thread); 735a703e490SVasu Dev 736a703e490SVasu Dev if (crc_eof) 737a703e490SVasu Dev put_page(crc_eof); 738a703e490SVasu Dev } 739a703e490SVasu Dev 740a703e490SVasu Dev /** 741a703e490SVasu Dev * fcoe_cpu_callback() - fcoe cpu hotplug event callback 742a703e490SVasu Dev * @nfb: callback data block 743a703e490SVasu Dev * @action: event triggering the callback 744a703e490SVasu Dev * @hcpu: index for the cpu of this event 745a703e490SVasu Dev * 746a703e490SVasu Dev * This creates or destroys per cpu data for fcoe 747a703e490SVasu Dev * 748a703e490SVasu Dev * Returns NOTIFY_OK always. 749a703e490SVasu Dev */ 750a703e490SVasu Dev static int fcoe_cpu_callback(struct notifier_block *nfb, 751a703e490SVasu Dev unsigned long action, void *hcpu) 752a703e490SVasu Dev { 753a703e490SVasu Dev unsigned cpu = (unsigned long)hcpu; 754a703e490SVasu Dev 755a703e490SVasu Dev switch (action) { 756a703e490SVasu Dev case CPU_ONLINE: 757a703e490SVasu Dev case CPU_ONLINE_FROZEN: 758a703e490SVasu Dev FC_DBG("CPU %x online: Create Rx thread\n", cpu); 759a703e490SVasu Dev fcoe_percpu_thread_create(cpu); 760a703e490SVasu Dev break; 761a703e490SVasu Dev case CPU_DEAD: 762a703e490SVasu Dev case CPU_DEAD_FROZEN: 763a703e490SVasu Dev FC_DBG("CPU %x offline: Remove Rx thread\n", cpu); 764a703e490SVasu Dev fcoe_percpu_thread_destroy(cpu); 765a703e490SVasu Dev break; 766a703e490SVasu Dev default: 767a703e490SVasu Dev break; 768a703e490SVasu Dev } 769a703e490SVasu Dev return NOTIFY_OK; 770a703e490SVasu Dev } 771a703e490SVasu Dev 772a703e490SVasu Dev static struct notifier_block fcoe_cpu_notifier = { 773a703e490SVasu Dev .notifier_call = fcoe_cpu_callback, 774a703e490SVasu Dev }; 775a703e490SVasu Dev 776a703e490SVasu Dev /** 777a703e490SVasu Dev * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ 778a703e490SVasu Dev * @skb: the receive skb 779a703e490SVasu Dev * @dev: associated net device 780a703e490SVasu Dev * @ptype: context 781dd3fd72eSChris Leech * @olddev: last device 782a703e490SVasu Dev * 783a703e490SVasu Dev * this function will receive the packet and build fc frame and pass it up 784a703e490SVasu Dev * 785a703e490SVasu Dev * Returns: 0 for success 786a703e490SVasu Dev */ 787a703e490SVasu Dev int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, 788a703e490SVasu Dev struct packet_type *ptype, struct net_device *olddev) 789a703e490SVasu Dev { 790a703e490SVasu Dev struct fc_lport *lp; 791a703e490SVasu Dev struct fcoe_rcv_info *fr; 792a703e490SVasu Dev struct fcoe_softc *fc; 793a703e490SVasu Dev struct fc_frame_header *fh; 794a703e490SVasu Dev struct fcoe_percpu_s *fps; 795a703e490SVasu Dev unsigned short oxid; 796a703e490SVasu Dev unsigned int cpu = 0; 797a703e490SVasu Dev 798a703e490SVasu Dev fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type); 79997c8389dSJoe Eykholt lp = fc->ctlr.lp; 800a703e490SVasu Dev if (unlikely(lp == NULL)) { 801a703e490SVasu Dev FC_DBG("cannot find hba structure"); 802a703e490SVasu Dev goto err2; 803a703e490SVasu Dev } 80497c8389dSJoe Eykholt if (!lp->link_up) 80597c8389dSJoe Eykholt goto err2; 806a703e490SVasu Dev 807a703e490SVasu Dev if (unlikely(debug_fcoe)) { 808a703e490SVasu Dev FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p tail:%p " 809a703e490SVasu Dev "end:%p sum:%d dev:%s", skb->len, skb->data_len, 810a703e490SVasu Dev skb->head, skb->data, skb_tail_pointer(skb), 811a703e490SVasu Dev skb_end_pointer(skb), skb->csum, 812a703e490SVasu Dev skb->dev ? skb->dev->name : "<NULL>"); 813a703e490SVasu Dev 814a703e490SVasu Dev } 815a703e490SVasu Dev 816a703e490SVasu Dev /* check for FCOE packet type */ 817a703e490SVasu Dev if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) { 818a703e490SVasu Dev FC_DBG("wrong FC type frame"); 819a703e490SVasu Dev goto err; 820a703e490SVasu Dev } 821a703e490SVasu Dev 822a703e490SVasu Dev /* 823a703e490SVasu Dev * Check for minimum frame length, and make sure required FCoE 824a703e490SVasu Dev * and FC headers are pulled into the linear data area. 825a703e490SVasu Dev */ 826a703e490SVasu Dev if (unlikely((skb->len < FCOE_MIN_FRAME) || 827a703e490SVasu Dev !pskb_may_pull(skb, FCOE_HEADER_LEN))) 828a703e490SVasu Dev goto err; 829a703e490SVasu Dev 830a703e490SVasu Dev skb_set_transport_header(skb, sizeof(struct fcoe_hdr)); 831a703e490SVasu Dev fh = (struct fc_frame_header *) skb_transport_header(skb); 832a703e490SVasu Dev 833a703e490SVasu Dev oxid = ntohs(fh->fh_ox_id); 834a703e490SVasu Dev 835a703e490SVasu Dev fr = fcoe_dev_from_skb(skb); 836a703e490SVasu Dev fr->fr_dev = lp; 837a703e490SVasu Dev fr->ptype = ptype; 838a703e490SVasu Dev 839a703e490SVasu Dev #ifdef CONFIG_SMP 840a703e490SVasu Dev /* 841a703e490SVasu Dev * The incoming frame exchange id(oxid) is ANDed with num of online 842a703e490SVasu Dev * cpu bits to get cpu and then this cpu is used for selecting 843a703e490SVasu Dev * a per cpu kernel thread from fcoe_percpu. 844a703e490SVasu Dev */ 845a703e490SVasu Dev cpu = oxid & (num_online_cpus() - 1); 846a703e490SVasu Dev #endif 847a703e490SVasu Dev 848a703e490SVasu Dev fps = &per_cpu(fcoe_percpu, cpu); 849a703e490SVasu Dev spin_lock_bh(&fps->fcoe_rx_list.lock); 850a703e490SVasu Dev if (unlikely(!fps->thread)) { 851a703e490SVasu Dev /* 852a703e490SVasu Dev * The targeted CPU is not ready, let's target 853a703e490SVasu Dev * the first CPU now. For non-SMP systems this 854a703e490SVasu Dev * will check the same CPU twice. 855a703e490SVasu Dev */ 856a703e490SVasu Dev FC_DBG("CPU is online, but no receive thread ready " 857a703e490SVasu Dev "for incoming skb- using first online CPU.\n"); 858a703e490SVasu Dev 859a703e490SVasu Dev spin_unlock_bh(&fps->fcoe_rx_list.lock); 860a703e490SVasu Dev cpu = first_cpu(cpu_online_map); 861a703e490SVasu Dev fps = &per_cpu(fcoe_percpu, cpu); 862a703e490SVasu Dev spin_lock_bh(&fps->fcoe_rx_list.lock); 863a703e490SVasu Dev if (!fps->thread) { 864a703e490SVasu Dev spin_unlock_bh(&fps->fcoe_rx_list.lock); 865a703e490SVasu Dev goto err; 866a703e490SVasu Dev } 867a703e490SVasu Dev } 868a703e490SVasu Dev 869a703e490SVasu Dev /* 870a703e490SVasu Dev * We now have a valid CPU that we're targeting for 871a703e490SVasu Dev * this skb. We also have this receive thread locked, 872a703e490SVasu Dev * so we're free to queue skbs into it's queue. 873a703e490SVasu Dev */ 874a703e490SVasu Dev __skb_queue_tail(&fps->fcoe_rx_list, skb); 875a703e490SVasu Dev if (fps->fcoe_rx_list.qlen == 1) 876a703e490SVasu Dev wake_up_process(fps->thread); 877a703e490SVasu Dev 878a703e490SVasu Dev spin_unlock_bh(&fps->fcoe_rx_list.lock); 879a703e490SVasu Dev 880a703e490SVasu Dev return 0; 881a703e490SVasu Dev err: 882a703e490SVasu Dev fc_lport_get_stats(lp)->ErrorFrames++; 883a703e490SVasu Dev 884a703e490SVasu Dev err2: 885a703e490SVasu Dev kfree_skb(skb); 886a703e490SVasu Dev return -1; 887a703e490SVasu Dev } 888a703e490SVasu Dev 889a703e490SVasu Dev /** 890a703e490SVasu Dev * fcoe_start_io() - pass to netdev to start xmit for fcoe 891a703e490SVasu Dev * @skb: the skb to be xmitted 892a703e490SVasu Dev * 893a703e490SVasu Dev * Returns: 0 for success 894a703e490SVasu Dev */ 895a703e490SVasu Dev static inline int fcoe_start_io(struct sk_buff *skb) 896a703e490SVasu Dev { 897a703e490SVasu Dev int rc; 898a703e490SVasu Dev 899a703e490SVasu Dev skb_get(skb); 900a703e490SVasu Dev rc = dev_queue_xmit(skb); 901a703e490SVasu Dev if (rc != 0) 902a703e490SVasu Dev return rc; 903a703e490SVasu Dev kfree_skb(skb); 904a703e490SVasu Dev return 0; 905a703e490SVasu Dev } 906a703e490SVasu Dev 907a703e490SVasu Dev /** 908dd3fd72eSChris Leech * fcoe_get_paged_crc_eof() - in case we need to alloc a page for crc_eof 909a703e490SVasu Dev * @skb: the skb to be xmitted 910a703e490SVasu Dev * @tlen: total len 911a703e490SVasu Dev * 912a703e490SVasu Dev * Returns: 0 for success 913a703e490SVasu Dev */ 914a703e490SVasu Dev static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) 915a703e490SVasu Dev { 916a703e490SVasu Dev struct fcoe_percpu_s *fps; 917a703e490SVasu Dev struct page *page; 918a703e490SVasu Dev 919a703e490SVasu Dev fps = &get_cpu_var(fcoe_percpu); 920a703e490SVasu Dev page = fps->crc_eof_page; 921a703e490SVasu Dev if (!page) { 922a703e490SVasu Dev page = alloc_page(GFP_ATOMIC); 923a703e490SVasu Dev if (!page) { 924a703e490SVasu Dev put_cpu_var(fcoe_percpu); 925a703e490SVasu Dev return -ENOMEM; 926a703e490SVasu Dev } 927a703e490SVasu Dev fps->crc_eof_page = page; 928a703e490SVasu Dev fps->crc_eof_offset = 0; 929a703e490SVasu Dev } 930a703e490SVasu Dev 931a703e490SVasu Dev get_page(page); 932a703e490SVasu Dev skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, 933a703e490SVasu Dev fps->crc_eof_offset, tlen); 934a703e490SVasu Dev skb->len += tlen; 935a703e490SVasu Dev skb->data_len += tlen; 936a703e490SVasu Dev skb->truesize += tlen; 937a703e490SVasu Dev fps->crc_eof_offset += sizeof(struct fcoe_crc_eof); 938a703e490SVasu Dev 939a703e490SVasu Dev if (fps->crc_eof_offset >= PAGE_SIZE) { 940a703e490SVasu Dev fps->crc_eof_page = NULL; 941a703e490SVasu Dev fps->crc_eof_offset = 0; 942a703e490SVasu Dev put_page(page); 943a703e490SVasu Dev } 944a703e490SVasu Dev put_cpu_var(fcoe_percpu); 945a703e490SVasu Dev return 0; 946a703e490SVasu Dev } 947a703e490SVasu Dev 948a703e490SVasu Dev /** 949a703e490SVasu Dev * fcoe_fc_crc() - calculates FC CRC in this fcoe skb 950dd3fd72eSChris Leech * @fp: the fc_frame containing data to be checksummed 951a703e490SVasu Dev * 952a703e490SVasu Dev * This uses crc32() to calculate the crc for fc frame 953a703e490SVasu Dev * Return : 32 bit crc 954a703e490SVasu Dev */ 955a703e490SVasu Dev u32 fcoe_fc_crc(struct fc_frame *fp) 956a703e490SVasu Dev { 957a703e490SVasu Dev struct sk_buff *skb = fp_skb(fp); 958a703e490SVasu Dev struct skb_frag_struct *frag; 959a703e490SVasu Dev unsigned char *data; 960a703e490SVasu Dev unsigned long off, len, clen; 961a703e490SVasu Dev u32 crc; 962a703e490SVasu Dev unsigned i; 963a703e490SVasu Dev 964a703e490SVasu Dev crc = crc32(~0, skb->data, skb_headlen(skb)); 965a703e490SVasu Dev 966a703e490SVasu Dev for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 967a703e490SVasu Dev frag = &skb_shinfo(skb)->frags[i]; 968a703e490SVasu Dev off = frag->page_offset; 969a703e490SVasu Dev len = frag->size; 970a703e490SVasu Dev while (len > 0) { 971a703e490SVasu Dev clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK)); 972a703e490SVasu Dev data = kmap_atomic(frag->page + (off >> PAGE_SHIFT), 973a703e490SVasu Dev KM_SKB_DATA_SOFTIRQ); 974a703e490SVasu Dev crc = crc32(crc, data + (off & ~PAGE_MASK), clen); 975a703e490SVasu Dev kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ); 976a703e490SVasu Dev off += clen; 977a703e490SVasu Dev len -= clen; 978a703e490SVasu Dev } 979a703e490SVasu Dev } 980a703e490SVasu Dev return crc; 981a703e490SVasu Dev } 982a703e490SVasu Dev 983a703e490SVasu Dev /** 984a703e490SVasu Dev * fcoe_xmit() - FCoE frame transmit function 985a703e490SVasu Dev * @lp: the associated local port 986a703e490SVasu Dev * @fp: the fc_frame to be transmitted 987a703e490SVasu Dev * 988a703e490SVasu Dev * Return : 0 for success 989a703e490SVasu Dev */ 990a703e490SVasu Dev int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) 991a703e490SVasu Dev { 992a703e490SVasu Dev int wlen, rc = 0; 993a703e490SVasu Dev u32 crc; 994a703e490SVasu Dev struct ethhdr *eh; 995a703e490SVasu Dev struct fcoe_crc_eof *cp; 996a703e490SVasu Dev struct sk_buff *skb; 997a703e490SVasu Dev struct fcoe_dev_stats *stats; 998a703e490SVasu Dev struct fc_frame_header *fh; 999a703e490SVasu Dev unsigned int hlen; /* header length implies the version */ 1000a703e490SVasu Dev unsigned int tlen; /* trailer length */ 1001a703e490SVasu Dev unsigned int elen; /* eth header, may include vlan */ 1002a703e490SVasu Dev struct fcoe_softc *fc; 1003a703e490SVasu Dev u8 sof, eof; 1004a703e490SVasu Dev struct fcoe_hdr *hp; 1005a703e490SVasu Dev 1006a703e490SVasu Dev WARN_ON((fr_len(fp) % sizeof(u32)) != 0); 1007a703e490SVasu Dev 1008a703e490SVasu Dev fc = lport_priv(lp); 1009a703e490SVasu Dev fh = fc_frame_header_get(fp); 101097c8389dSJoe Eykholt skb = fp_skb(fp); 101197c8389dSJoe Eykholt wlen = skb->len / FCOE_WORD_TO_BYTE; 101297c8389dSJoe Eykholt 101397c8389dSJoe Eykholt if (!lp->link_up) { 10143caf02eeSDan Carpenter kfree_skb(skb); 101597c8389dSJoe Eykholt return 0; 1016a703e490SVasu Dev } 1017a703e490SVasu Dev 101897c8389dSJoe Eykholt if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && 101997c8389dSJoe Eykholt fcoe_ctlr_els_send(&fc->ctlr, skb)) 102097c8389dSJoe Eykholt return 0; 102197c8389dSJoe Eykholt 1022a703e490SVasu Dev sof = fr_sof(fp); 1023a703e490SVasu Dev eof = fr_eof(fp); 1024a703e490SVasu Dev 1025a703e490SVasu Dev elen = (fc->real_dev->priv_flags & IFF_802_1Q_VLAN) ? 1026a703e490SVasu Dev sizeof(struct vlan_ethhdr) : sizeof(struct ethhdr); 1027a703e490SVasu Dev hlen = sizeof(struct fcoe_hdr); 1028a703e490SVasu Dev tlen = sizeof(struct fcoe_crc_eof); 1029a703e490SVasu Dev wlen = (skb->len - tlen + sizeof(crc)) / FCOE_WORD_TO_BYTE; 1030a703e490SVasu Dev 1031a703e490SVasu Dev /* crc offload */ 1032a703e490SVasu Dev if (likely(lp->crc_offload)) { 1033a703e490SVasu Dev skb->ip_summed = CHECKSUM_PARTIAL; 1034a703e490SVasu Dev skb->csum_start = skb_headroom(skb); 1035a703e490SVasu Dev skb->csum_offset = skb->len; 1036a703e490SVasu Dev crc = 0; 1037a703e490SVasu Dev } else { 1038a703e490SVasu Dev skb->ip_summed = CHECKSUM_NONE; 1039a703e490SVasu Dev crc = fcoe_fc_crc(fp); 1040a703e490SVasu Dev } 1041a703e490SVasu Dev 1042a703e490SVasu Dev /* copy fc crc and eof to the skb buff */ 1043a703e490SVasu Dev if (skb_is_nonlinear(skb)) { 1044a703e490SVasu Dev skb_frag_t *frag; 1045a703e490SVasu Dev if (fcoe_get_paged_crc_eof(skb, tlen)) { 1046a703e490SVasu Dev kfree_skb(skb); 1047a703e490SVasu Dev return -ENOMEM; 1048a703e490SVasu Dev } 1049a703e490SVasu Dev frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; 1050a703e490SVasu Dev cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ) 1051a703e490SVasu Dev + frag->page_offset; 1052a703e490SVasu Dev } else { 1053a703e490SVasu Dev cp = (struct fcoe_crc_eof *)skb_put(skb, tlen); 1054a703e490SVasu Dev } 1055a703e490SVasu Dev 1056a703e490SVasu Dev memset(cp, 0, sizeof(*cp)); 1057a703e490SVasu Dev cp->fcoe_eof = eof; 1058a703e490SVasu Dev cp->fcoe_crc32 = cpu_to_le32(~crc); 1059a703e490SVasu Dev 1060a703e490SVasu Dev if (skb_is_nonlinear(skb)) { 1061a703e490SVasu Dev kunmap_atomic(cp, KM_SKB_DATA_SOFTIRQ); 1062a703e490SVasu Dev cp = NULL; 1063a703e490SVasu Dev } 1064a703e490SVasu Dev 1065dd3fd72eSChris Leech /* adjust skb network/transport offsets to match mac/fcoe/fc */ 1066a703e490SVasu Dev skb_push(skb, elen + hlen); 1067a703e490SVasu Dev skb_reset_mac_header(skb); 1068a703e490SVasu Dev skb_reset_network_header(skb); 1069a703e490SVasu Dev skb->mac_len = elen; 1070a703e490SVasu Dev skb->protocol = htons(ETH_P_FCOE); 1071a703e490SVasu Dev skb->dev = fc->real_dev; 1072a703e490SVasu Dev 1073a703e490SVasu Dev /* fill up mac and fcoe headers */ 1074a703e490SVasu Dev eh = eth_hdr(skb); 1075a703e490SVasu Dev eh->h_proto = htons(ETH_P_FCOE); 107697c8389dSJoe Eykholt if (fc->ctlr.map_dest) 1077a703e490SVasu Dev fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id); 1078a703e490SVasu Dev else 1079a703e490SVasu Dev /* insert GW address */ 108097c8389dSJoe Eykholt memcpy(eh->h_dest, fc->ctlr.dest_addr, ETH_ALEN); 1081a703e490SVasu Dev 108297c8389dSJoe Eykholt if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN)) 108397c8389dSJoe Eykholt memcpy(eh->h_source, fc->ctlr.ctl_src_addr, ETH_ALEN); 1084a703e490SVasu Dev else 108597c8389dSJoe Eykholt memcpy(eh->h_source, fc->ctlr.data_src_addr, ETH_ALEN); 1086a703e490SVasu Dev 1087a703e490SVasu Dev hp = (struct fcoe_hdr *)(eh + 1); 1088a703e490SVasu Dev memset(hp, 0, sizeof(*hp)); 1089a703e490SVasu Dev if (FC_FCOE_VER) 1090a703e490SVasu Dev FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER); 1091a703e490SVasu Dev hp->fcoe_sof = sof; 1092a703e490SVasu Dev 1093a703e490SVasu Dev #ifdef NETIF_F_FSO 1094a703e490SVasu Dev /* fcoe lso, mss is in max_payload which is non-zero for FCP data */ 1095a703e490SVasu Dev if (lp->seq_offload && fr_max_payload(fp)) { 1096a703e490SVasu Dev skb_shinfo(skb)->gso_type = SKB_GSO_FCOE; 1097a703e490SVasu Dev skb_shinfo(skb)->gso_size = fr_max_payload(fp); 1098a703e490SVasu Dev } else { 1099a703e490SVasu Dev skb_shinfo(skb)->gso_type = 0; 1100a703e490SVasu Dev skb_shinfo(skb)->gso_size = 0; 1101a703e490SVasu Dev } 1102a703e490SVasu Dev #endif 1103a703e490SVasu Dev /* update tx stats: regardless if LLD fails */ 1104a703e490SVasu Dev stats = fc_lport_get_stats(lp); 1105a703e490SVasu Dev stats->TxFrames++; 1106a703e490SVasu Dev stats->TxWords += wlen; 1107a703e490SVasu Dev 1108a703e490SVasu Dev /* send down to lld */ 1109a703e490SVasu Dev fr_dev(fp) = lp; 1110a703e490SVasu Dev if (fc->fcoe_pending_queue.qlen) 1111a703e490SVasu Dev rc = fcoe_check_wait_queue(lp); 1112a703e490SVasu Dev 1113a703e490SVasu Dev if (rc == 0) 1114a703e490SVasu Dev rc = fcoe_start_io(skb); 1115a703e490SVasu Dev 1116a703e490SVasu Dev if (rc) { 1117a703e490SVasu Dev spin_lock_bh(&fc->fcoe_pending_queue.lock); 1118a703e490SVasu Dev __skb_queue_tail(&fc->fcoe_pending_queue, skb); 1119a703e490SVasu Dev spin_unlock_bh(&fc->fcoe_pending_queue.lock); 1120a703e490SVasu Dev if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) 1121a703e490SVasu Dev lp->qfull = 1; 1122a703e490SVasu Dev } 1123a703e490SVasu Dev 1124a703e490SVasu Dev return 0; 1125a703e490SVasu Dev } 1126a703e490SVasu Dev 1127a703e490SVasu Dev /** 1128a703e490SVasu Dev * fcoe_percpu_receive_thread() - recv thread per cpu 1129a703e490SVasu Dev * @arg: ptr to the fcoe per cpu struct 1130a703e490SVasu Dev * 1131a703e490SVasu Dev * Return: 0 for success 1132a703e490SVasu Dev */ 1133a703e490SVasu Dev int fcoe_percpu_receive_thread(void *arg) 1134a703e490SVasu Dev { 1135a703e490SVasu Dev struct fcoe_percpu_s *p = arg; 1136a703e490SVasu Dev u32 fr_len; 1137a703e490SVasu Dev struct fc_lport *lp; 1138a703e490SVasu Dev struct fcoe_rcv_info *fr; 1139a703e490SVasu Dev struct fcoe_dev_stats *stats; 1140a703e490SVasu Dev struct fc_frame_header *fh; 1141a703e490SVasu Dev struct sk_buff *skb; 1142a703e490SVasu Dev struct fcoe_crc_eof crc_eof; 1143a703e490SVasu Dev struct fc_frame *fp; 1144a703e490SVasu Dev u8 *mac = NULL; 1145a703e490SVasu Dev struct fcoe_softc *fc; 1146a703e490SVasu Dev struct fcoe_hdr *hp; 1147a703e490SVasu Dev 1148a703e490SVasu Dev set_user_nice(current, -20); 1149a703e490SVasu Dev 1150a703e490SVasu Dev while (!kthread_should_stop()) { 1151a703e490SVasu Dev 1152a703e490SVasu Dev spin_lock_bh(&p->fcoe_rx_list.lock); 1153a703e490SVasu Dev while ((skb = __skb_dequeue(&p->fcoe_rx_list)) == NULL) { 1154a703e490SVasu Dev set_current_state(TASK_INTERRUPTIBLE); 1155a703e490SVasu Dev spin_unlock_bh(&p->fcoe_rx_list.lock); 1156a703e490SVasu Dev schedule(); 1157a703e490SVasu Dev set_current_state(TASK_RUNNING); 1158a703e490SVasu Dev if (kthread_should_stop()) 1159a703e490SVasu Dev return 0; 1160a703e490SVasu Dev spin_lock_bh(&p->fcoe_rx_list.lock); 1161a703e490SVasu Dev } 1162a703e490SVasu Dev spin_unlock_bh(&p->fcoe_rx_list.lock); 1163a703e490SVasu Dev fr = fcoe_dev_from_skb(skb); 1164a703e490SVasu Dev lp = fr->fr_dev; 1165a703e490SVasu Dev if (unlikely(lp == NULL)) { 1166a703e490SVasu Dev FC_DBG("invalid HBA Structure"); 1167a703e490SVasu Dev kfree_skb(skb); 1168a703e490SVasu Dev continue; 1169a703e490SVasu Dev } 1170a703e490SVasu Dev 1171a703e490SVasu Dev if (unlikely(debug_fcoe)) { 1172a703e490SVasu Dev FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p " 1173a703e490SVasu Dev "tail:%p end:%p sum:%d dev:%s", 1174a703e490SVasu Dev skb->len, skb->data_len, 1175a703e490SVasu Dev skb->head, skb->data, skb_tail_pointer(skb), 1176a703e490SVasu Dev skb_end_pointer(skb), skb->csum, 1177a703e490SVasu Dev skb->dev ? skb->dev->name : "<NULL>"); 1178a703e490SVasu Dev } 1179a703e490SVasu Dev 1180a703e490SVasu Dev /* 1181a703e490SVasu Dev * Save source MAC address before discarding header. 1182a703e490SVasu Dev */ 1183a703e490SVasu Dev fc = lport_priv(lp); 1184a703e490SVasu Dev if (skb_is_nonlinear(skb)) 1185a703e490SVasu Dev skb_linearize(skb); /* not ideal */ 118697c8389dSJoe Eykholt mac = eth_hdr(skb)->h_source; 1187a703e490SVasu Dev 1188a703e490SVasu Dev /* 1189a703e490SVasu Dev * Frame length checks and setting up the header pointers 1190a703e490SVasu Dev * was done in fcoe_rcv already. 1191a703e490SVasu Dev */ 1192a703e490SVasu Dev hp = (struct fcoe_hdr *) skb_network_header(skb); 1193a703e490SVasu Dev fh = (struct fc_frame_header *) skb_transport_header(skb); 1194a703e490SVasu Dev 1195a703e490SVasu Dev stats = fc_lport_get_stats(lp); 1196a703e490SVasu Dev if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) { 1197a703e490SVasu Dev if (stats->ErrorFrames < 5) 1198a703e490SVasu Dev printk(KERN_WARNING "FCoE version " 1199a703e490SVasu Dev "mismatch: The frame has " 1200a703e490SVasu Dev "version %x, but the " 1201a703e490SVasu Dev "initiator supports version " 1202a703e490SVasu Dev "%x\n", FC_FCOE_DECAPS_VER(hp), 1203a703e490SVasu Dev FC_FCOE_VER); 1204a703e490SVasu Dev stats->ErrorFrames++; 1205a703e490SVasu Dev kfree_skb(skb); 1206a703e490SVasu Dev continue; 1207a703e490SVasu Dev } 1208a703e490SVasu Dev 1209a703e490SVasu Dev skb_pull(skb, sizeof(struct fcoe_hdr)); 1210a703e490SVasu Dev fr_len = skb->len - sizeof(struct fcoe_crc_eof); 1211a703e490SVasu Dev 1212a703e490SVasu Dev stats->RxFrames++; 1213a703e490SVasu Dev stats->RxWords += fr_len / FCOE_WORD_TO_BYTE; 1214a703e490SVasu Dev 1215a703e490SVasu Dev fp = (struct fc_frame *)skb; 1216a703e490SVasu Dev fc_frame_init(fp); 1217a703e490SVasu Dev fr_dev(fp) = lp; 1218a703e490SVasu Dev fr_sof(fp) = hp->fcoe_sof; 1219a703e490SVasu Dev 1220a703e490SVasu Dev /* Copy out the CRC and EOF trailer for access */ 1221a703e490SVasu Dev if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) { 1222a703e490SVasu Dev kfree_skb(skb); 1223a703e490SVasu Dev continue; 1224a703e490SVasu Dev } 1225a703e490SVasu Dev fr_eof(fp) = crc_eof.fcoe_eof; 1226a703e490SVasu Dev fr_crc(fp) = crc_eof.fcoe_crc32; 1227a703e490SVasu Dev if (pskb_trim(skb, fr_len)) { 1228a703e490SVasu Dev kfree_skb(skb); 1229a703e490SVasu Dev continue; 1230a703e490SVasu Dev } 1231a703e490SVasu Dev 1232a703e490SVasu Dev /* 1233a703e490SVasu Dev * We only check CRC if no offload is available and if it is 1234a703e490SVasu Dev * it's solicited data, in which case, the FCP layer would 1235a703e490SVasu Dev * check it during the copy. 1236a703e490SVasu Dev */ 1237a703e490SVasu Dev if (lp->crc_offload && skb->ip_summed == CHECKSUM_UNNECESSARY) 1238a703e490SVasu Dev fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; 1239a703e490SVasu Dev else 1240a703e490SVasu Dev fr_flags(fp) |= FCPHF_CRC_UNCHECKED; 1241a703e490SVasu Dev 1242a703e490SVasu Dev fh = fc_frame_header_get(fp); 1243a703e490SVasu Dev if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && 1244a703e490SVasu Dev fh->fh_type == FC_TYPE_FCP) { 1245a703e490SVasu Dev fc_exch_recv(lp, lp->emp, fp); 1246a703e490SVasu Dev continue; 1247a703e490SVasu Dev } 1248a703e490SVasu Dev if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) { 1249a703e490SVasu Dev if (le32_to_cpu(fr_crc(fp)) != 1250a703e490SVasu Dev ~crc32(~0, skb->data, fr_len)) { 1251a703e490SVasu Dev if (debug_fcoe || stats->InvalidCRCCount < 5) 1252a703e490SVasu Dev printk(KERN_WARNING "fcoe: dropping " 1253a703e490SVasu Dev "frame with CRC error\n"); 1254a703e490SVasu Dev stats->InvalidCRCCount++; 1255a703e490SVasu Dev stats->ErrorFrames++; 1256a703e490SVasu Dev fc_frame_free(fp); 1257a703e490SVasu Dev continue; 1258a703e490SVasu Dev } 1259a703e490SVasu Dev fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; 1260a703e490SVasu Dev } 126197c8389dSJoe Eykholt if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN) && 126297c8389dSJoe Eykholt fcoe_ctlr_recv_flogi(&fc->ctlr, fp, mac)) { 126397c8389dSJoe Eykholt fc_frame_free(fp); 126497c8389dSJoe Eykholt continue; 126597c8389dSJoe Eykholt } 1266a703e490SVasu Dev fc_exch_recv(lp, lp->emp, fp); 1267a703e490SVasu Dev } 1268a703e490SVasu Dev return 0; 1269a703e490SVasu Dev } 1270a703e490SVasu Dev 1271a703e490SVasu Dev /** 1272a703e490SVasu Dev * fcoe_watchdog() - fcoe timer callback 1273a703e490SVasu Dev * @vp: 1274a703e490SVasu Dev * 1275a703e490SVasu Dev * This checks the pending queue length for fcoe and set lport qfull 1276a703e490SVasu Dev * if the FCOE_MAX_QUEUE_DEPTH is reached. This is done for all fc_lport on the 1277a703e490SVasu Dev * fcoe_hostlist. 1278a703e490SVasu Dev * 1279a703e490SVasu Dev * Returns: 0 for success 1280a703e490SVasu Dev */ 1281a703e490SVasu Dev void fcoe_watchdog(ulong vp) 1282a703e490SVasu Dev { 1283a703e490SVasu Dev struct fcoe_softc *fc; 1284a703e490SVasu Dev 1285a703e490SVasu Dev read_lock(&fcoe_hostlist_lock); 1286a703e490SVasu Dev list_for_each_entry(fc, &fcoe_hostlist, list) { 128797c8389dSJoe Eykholt if (fc->ctlr.lp) 128897c8389dSJoe Eykholt fcoe_check_wait_queue(fc->ctlr.lp); 1289a703e490SVasu Dev } 1290a703e490SVasu Dev read_unlock(&fcoe_hostlist_lock); 1291a703e490SVasu Dev 1292a703e490SVasu Dev fcoe_timer.expires = jiffies + (1 * HZ); 1293a703e490SVasu Dev add_timer(&fcoe_timer); 1294a703e490SVasu Dev } 1295a703e490SVasu Dev 1296a703e490SVasu Dev 1297a703e490SVasu Dev /** 1298dd3fd72eSChris Leech * fcoe_check_wait_queue() - attempt to clear the transmit backlog 1299dd3fd72eSChris Leech * @lp: the fc_lport 1300a703e490SVasu Dev * 1301a703e490SVasu Dev * This empties the wait_queue, dequeue the head of the wait_queue queue 1302a703e490SVasu Dev * and calls fcoe_start_io() for each packet, if all skb have been 1303a703e490SVasu Dev * transmitted, return qlen or -1 if a error occurs, then restore 1304a703e490SVasu Dev * wait_queue and try again later. 1305a703e490SVasu Dev * 1306a703e490SVasu Dev * The wait_queue is used when the skb transmit fails. skb will go 1307dd3fd72eSChris Leech * in the wait_queue which will be emptied by the timer function or 1308a703e490SVasu Dev * by the next skb transmit. 1309a703e490SVasu Dev * 1310a703e490SVasu Dev * Returns: 0 for success 1311a703e490SVasu Dev */ 1312a703e490SVasu Dev static int fcoe_check_wait_queue(struct fc_lport *lp) 1313a703e490SVasu Dev { 1314a703e490SVasu Dev struct fcoe_softc *fc = lport_priv(lp); 1315a703e490SVasu Dev struct sk_buff *skb; 1316a703e490SVasu Dev int rc = -1; 1317a703e490SVasu Dev 1318a703e490SVasu Dev spin_lock_bh(&fc->fcoe_pending_queue.lock); 1319a703e490SVasu Dev if (fc->fcoe_pending_queue_active) 1320a703e490SVasu Dev goto out; 1321a703e490SVasu Dev fc->fcoe_pending_queue_active = 1; 1322a703e490SVasu Dev 1323a703e490SVasu Dev while (fc->fcoe_pending_queue.qlen) { 1324a703e490SVasu Dev /* keep qlen > 0 until fcoe_start_io succeeds */ 1325a703e490SVasu Dev fc->fcoe_pending_queue.qlen++; 1326a703e490SVasu Dev skb = __skb_dequeue(&fc->fcoe_pending_queue); 1327a703e490SVasu Dev 1328a703e490SVasu Dev spin_unlock_bh(&fc->fcoe_pending_queue.lock); 1329a703e490SVasu Dev rc = fcoe_start_io(skb); 1330a703e490SVasu Dev spin_lock_bh(&fc->fcoe_pending_queue.lock); 1331a703e490SVasu Dev 1332a703e490SVasu Dev if (rc) { 1333a703e490SVasu Dev __skb_queue_head(&fc->fcoe_pending_queue, skb); 1334a703e490SVasu Dev /* undo temporary increment above */ 1335a703e490SVasu Dev fc->fcoe_pending_queue.qlen--; 1336a703e490SVasu Dev break; 1337a703e490SVasu Dev } 1338a703e490SVasu Dev /* undo temporary increment above */ 1339a703e490SVasu Dev fc->fcoe_pending_queue.qlen--; 1340a703e490SVasu Dev } 1341a703e490SVasu Dev 1342a703e490SVasu Dev if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) 1343a703e490SVasu Dev lp->qfull = 0; 1344a703e490SVasu Dev fc->fcoe_pending_queue_active = 0; 1345a703e490SVasu Dev rc = fc->fcoe_pending_queue.qlen; 1346a703e490SVasu Dev out: 1347a703e490SVasu Dev spin_unlock_bh(&fc->fcoe_pending_queue.lock); 1348a703e490SVasu Dev return rc; 1349a703e490SVasu Dev } 1350a703e490SVasu Dev 1351a703e490SVasu Dev /** 1352a703e490SVasu Dev * fcoe_dev_setup() - setup link change notification interface 1353a703e490SVasu Dev */ 1354b0d428adSRandy Dunlap static void fcoe_dev_setup(void) 1355a703e490SVasu Dev { 1356a703e490SVasu Dev register_netdevice_notifier(&fcoe_notifier); 1357a703e490SVasu Dev } 1358a703e490SVasu Dev 1359a703e490SVasu Dev /** 1360b0d428adSRandy Dunlap * fcoe_dev_cleanup() - cleanup link change notification interface 1361a703e490SVasu Dev */ 1362a703e490SVasu Dev static void fcoe_dev_cleanup(void) 1363a703e490SVasu Dev { 1364a703e490SVasu Dev unregister_netdevice_notifier(&fcoe_notifier); 1365a703e490SVasu Dev } 1366a703e490SVasu Dev 1367a703e490SVasu Dev /** 1368a703e490SVasu Dev * fcoe_device_notification() - netdev event notification callback 1369a703e490SVasu Dev * @notifier: context of the notification 1370a703e490SVasu Dev * @event: type of event 1371a703e490SVasu Dev * @ptr: fixed array for output parsed ifname 1372a703e490SVasu Dev * 1373a703e490SVasu Dev * This function is called by the ethernet driver in case of link change event 1374a703e490SVasu Dev * 1375a703e490SVasu Dev * Returns: 0 for success 1376a703e490SVasu Dev */ 1377a703e490SVasu Dev static int fcoe_device_notification(struct notifier_block *notifier, 1378a703e490SVasu Dev ulong event, void *ptr) 1379a703e490SVasu Dev { 1380a703e490SVasu Dev struct fc_lport *lp = NULL; 1381a703e490SVasu Dev struct net_device *real_dev = ptr; 1382a703e490SVasu Dev struct fcoe_softc *fc; 1383a703e490SVasu Dev struct fcoe_dev_stats *stats; 138497c8389dSJoe Eykholt u32 link_possible = 1; 1385a703e490SVasu Dev u32 mfs; 1386a703e490SVasu Dev int rc = NOTIFY_OK; 1387a703e490SVasu Dev 1388a703e490SVasu Dev read_lock(&fcoe_hostlist_lock); 1389a703e490SVasu Dev list_for_each_entry(fc, &fcoe_hostlist, list) { 1390a703e490SVasu Dev if (fc->real_dev == real_dev) { 139197c8389dSJoe Eykholt lp = fc->ctlr.lp; 1392a703e490SVasu Dev break; 1393a703e490SVasu Dev } 1394a703e490SVasu Dev } 1395a703e490SVasu Dev read_unlock(&fcoe_hostlist_lock); 1396a703e490SVasu Dev if (lp == NULL) { 1397a703e490SVasu Dev rc = NOTIFY_DONE; 1398a703e490SVasu Dev goto out; 1399a703e490SVasu Dev } 1400a703e490SVasu Dev 1401a703e490SVasu Dev switch (event) { 1402a703e490SVasu Dev case NETDEV_DOWN: 1403a703e490SVasu Dev case NETDEV_GOING_DOWN: 140497c8389dSJoe Eykholt link_possible = 0; 1405a703e490SVasu Dev break; 1406a703e490SVasu Dev case NETDEV_UP: 1407a703e490SVasu Dev case NETDEV_CHANGE: 1408a703e490SVasu Dev break; 1409a703e490SVasu Dev case NETDEV_CHANGEMTU: 1410a703e490SVasu Dev mfs = fc->real_dev->mtu - 1411a703e490SVasu Dev (sizeof(struct fcoe_hdr) + 1412a703e490SVasu Dev sizeof(struct fcoe_crc_eof)); 1413a703e490SVasu Dev if (mfs >= FC_MIN_MAX_FRAME) 1414a703e490SVasu Dev fc_set_mfs(lp, mfs); 1415a703e490SVasu Dev break; 1416a703e490SVasu Dev case NETDEV_REGISTER: 1417a703e490SVasu Dev break; 1418a703e490SVasu Dev default: 141997c8389dSJoe Eykholt FC_DBG("Unknown event %ld from netdev netlink\n", event); 1420a703e490SVasu Dev } 142197c8389dSJoe Eykholt if (link_possible && !fcoe_link_ok(lp)) 142297c8389dSJoe Eykholt fcoe_ctlr_link_up(&fc->ctlr); 142397c8389dSJoe Eykholt else if (fcoe_ctlr_link_down(&fc->ctlr)) { 1424a703e490SVasu Dev stats = fc_lport_get_stats(lp); 1425a703e490SVasu Dev stats->LinkFailureCount++; 1426a703e490SVasu Dev fcoe_clean_pending_queue(lp); 1427a703e490SVasu Dev } 1428a703e490SVasu Dev out: 1429a703e490SVasu Dev return rc; 1430a703e490SVasu Dev } 1431a703e490SVasu Dev 1432a703e490SVasu Dev /** 1433a703e490SVasu Dev * fcoe_if_to_netdev() - parse a name buffer to get netdev 1434a703e490SVasu Dev * @buffer: incoming buffer to be copied 1435a703e490SVasu Dev * 1436dd3fd72eSChris Leech * Returns: NULL or ptr to net_device 1437a703e490SVasu Dev */ 1438a703e490SVasu Dev static struct net_device *fcoe_if_to_netdev(const char *buffer) 1439a703e490SVasu Dev { 1440a703e490SVasu Dev char *cp; 1441a703e490SVasu Dev char ifname[IFNAMSIZ + 2]; 1442a703e490SVasu Dev 1443a703e490SVasu Dev if (buffer) { 1444a703e490SVasu Dev strlcpy(ifname, buffer, IFNAMSIZ); 1445a703e490SVasu Dev cp = ifname + strlen(ifname); 1446a703e490SVasu Dev while (--cp >= ifname && *cp == '\n') 1447a703e490SVasu Dev *cp = '\0'; 1448a703e490SVasu Dev return dev_get_by_name(&init_net, ifname); 1449a703e490SVasu Dev } 1450a703e490SVasu Dev return NULL; 1451a703e490SVasu Dev } 1452a703e490SVasu Dev 1453a703e490SVasu Dev /** 1454dd3fd72eSChris Leech * fcoe_netdev_to_module_owner() - finds out the driver module of the netdev 1455a703e490SVasu Dev * @netdev: the target netdev 1456a703e490SVasu Dev * 1457a703e490SVasu Dev * Returns: ptr to the struct module, NULL for failure 1458a703e490SVasu Dev */ 1459a703e490SVasu Dev static struct module * 1460a703e490SVasu Dev fcoe_netdev_to_module_owner(const struct net_device *netdev) 1461a703e490SVasu Dev { 1462a703e490SVasu Dev struct device *dev; 1463a703e490SVasu Dev 1464a703e490SVasu Dev if (!netdev) 1465a703e490SVasu Dev return NULL; 1466a703e490SVasu Dev 1467a703e490SVasu Dev dev = netdev->dev.parent; 1468a703e490SVasu Dev if (!dev) 1469a703e490SVasu Dev return NULL; 1470a703e490SVasu Dev 1471a703e490SVasu Dev if (!dev->driver) 1472a703e490SVasu Dev return NULL; 1473a703e490SVasu Dev 1474a703e490SVasu Dev return dev->driver->owner; 1475a703e490SVasu Dev } 1476a703e490SVasu Dev 1477a703e490SVasu Dev /** 1478a703e490SVasu Dev * fcoe_ethdrv_get() - Hold the Ethernet driver 1479a703e490SVasu Dev * @netdev: the target netdev 1480a703e490SVasu Dev * 1481a703e490SVasu Dev * Holds the Ethernet driver module by try_module_get() for 1482a703e490SVasu Dev * the corresponding netdev. 1483a703e490SVasu Dev * 1484dd3fd72eSChris Leech * Returns: 0 for success 1485a703e490SVasu Dev */ 1486a703e490SVasu Dev static int fcoe_ethdrv_get(const struct net_device *netdev) 1487a703e490SVasu Dev { 1488a703e490SVasu Dev struct module *owner; 1489a703e490SVasu Dev 1490a703e490SVasu Dev owner = fcoe_netdev_to_module_owner(netdev); 1491a703e490SVasu Dev if (owner) { 1492a703e490SVasu Dev printk(KERN_DEBUG "fcoe:hold driver module %s for %s\n", 1493a703e490SVasu Dev module_name(owner), netdev->name); 1494a703e490SVasu Dev return try_module_get(owner); 1495a703e490SVasu Dev } 1496a703e490SVasu Dev return -ENODEV; 1497a703e490SVasu Dev } 1498a703e490SVasu Dev 1499a703e490SVasu Dev /** 1500a703e490SVasu Dev * fcoe_ethdrv_put() - Release the Ethernet driver 1501a703e490SVasu Dev * @netdev: the target netdev 1502a703e490SVasu Dev * 1503a703e490SVasu Dev * Releases the Ethernet driver module by module_put for 1504a703e490SVasu Dev * the corresponding netdev. 1505a703e490SVasu Dev * 1506dd3fd72eSChris Leech * Returns: 0 for success 1507a703e490SVasu Dev */ 1508a703e490SVasu Dev static int fcoe_ethdrv_put(const struct net_device *netdev) 1509a703e490SVasu Dev { 1510a703e490SVasu Dev struct module *owner; 1511a703e490SVasu Dev 1512a703e490SVasu Dev owner = fcoe_netdev_to_module_owner(netdev); 1513a703e490SVasu Dev if (owner) { 1514a703e490SVasu Dev printk(KERN_DEBUG "fcoe:release driver module %s for %s\n", 1515a703e490SVasu Dev module_name(owner), netdev->name); 1516a703e490SVasu Dev module_put(owner); 1517a703e490SVasu Dev return 0; 1518a703e490SVasu Dev } 1519a703e490SVasu Dev return -ENODEV; 1520a703e490SVasu Dev } 1521a703e490SVasu Dev 1522a703e490SVasu Dev /** 1523a703e490SVasu Dev * fcoe_destroy() - handles the destroy from sysfs 1524dd3fd72eSChris Leech * @buffer: expected to be an eth if name 1525a703e490SVasu Dev * @kp: associated kernel param 1526a703e490SVasu Dev * 1527a703e490SVasu Dev * Returns: 0 for success 1528a703e490SVasu Dev */ 1529a703e490SVasu Dev static int fcoe_destroy(const char *buffer, struct kernel_param *kp) 1530a703e490SVasu Dev { 1531a703e490SVasu Dev int rc; 1532a703e490SVasu Dev struct net_device *netdev; 1533a703e490SVasu Dev 1534a703e490SVasu Dev netdev = fcoe_if_to_netdev(buffer); 1535a703e490SVasu Dev if (!netdev) { 1536a703e490SVasu Dev rc = -ENODEV; 1537a703e490SVasu Dev goto out_nodev; 1538a703e490SVasu Dev } 1539a703e490SVasu Dev /* look for existing lport */ 1540a703e490SVasu Dev if (!fcoe_hostlist_lookup(netdev)) { 1541a703e490SVasu Dev rc = -ENODEV; 1542a703e490SVasu Dev goto out_putdev; 1543a703e490SVasu Dev } 1544a703e490SVasu Dev rc = fcoe_if_destroy(netdev); 1545a703e490SVasu Dev if (rc) { 1546a703e490SVasu Dev printk(KERN_ERR "fcoe: fcoe_if_destroy(%s) failed\n", 1547a703e490SVasu Dev netdev->name); 1548a703e490SVasu Dev rc = -EIO; 1549a703e490SVasu Dev goto out_putdev; 1550a703e490SVasu Dev } 1551a703e490SVasu Dev fcoe_ethdrv_put(netdev); 1552a703e490SVasu Dev rc = 0; 1553a703e490SVasu Dev out_putdev: 1554a703e490SVasu Dev dev_put(netdev); 1555a703e490SVasu Dev out_nodev: 1556a703e490SVasu Dev return rc; 1557a703e490SVasu Dev } 1558a703e490SVasu Dev 1559a703e490SVasu Dev /** 1560a703e490SVasu Dev * fcoe_create() - Handles the create call from sysfs 1561dd3fd72eSChris Leech * @buffer: expected to be an eth if name 1562a703e490SVasu Dev * @kp: associated kernel param 1563a703e490SVasu Dev * 1564a703e490SVasu Dev * Returns: 0 for success 1565a703e490SVasu Dev */ 1566a703e490SVasu Dev static int fcoe_create(const char *buffer, struct kernel_param *kp) 1567a703e490SVasu Dev { 1568a703e490SVasu Dev int rc; 1569a703e490SVasu Dev struct net_device *netdev; 1570a703e490SVasu Dev 1571a703e490SVasu Dev netdev = fcoe_if_to_netdev(buffer); 1572a703e490SVasu Dev if (!netdev) { 1573a703e490SVasu Dev rc = -ENODEV; 1574a703e490SVasu Dev goto out_nodev; 1575a703e490SVasu Dev } 1576a703e490SVasu Dev /* look for existing lport */ 1577a703e490SVasu Dev if (fcoe_hostlist_lookup(netdev)) { 1578a703e490SVasu Dev rc = -EEXIST; 1579a703e490SVasu Dev goto out_putdev; 1580a703e490SVasu Dev } 1581a703e490SVasu Dev fcoe_ethdrv_get(netdev); 1582a703e490SVasu Dev 1583a703e490SVasu Dev rc = fcoe_if_create(netdev); 1584a703e490SVasu Dev if (rc) { 1585a703e490SVasu Dev printk(KERN_ERR "fcoe: fcoe_if_create(%s) failed\n", 1586a703e490SVasu Dev netdev->name); 1587a703e490SVasu Dev fcoe_ethdrv_put(netdev); 1588a703e490SVasu Dev rc = -EIO; 1589a703e490SVasu Dev goto out_putdev; 1590a703e490SVasu Dev } 1591a703e490SVasu Dev rc = 0; 1592a703e490SVasu Dev out_putdev: 1593a703e490SVasu Dev dev_put(netdev); 1594a703e490SVasu Dev out_nodev: 1595a703e490SVasu Dev return rc; 1596a703e490SVasu Dev } 1597a703e490SVasu Dev 1598a703e490SVasu Dev module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR); 1599a703e490SVasu Dev __MODULE_PARM_TYPE(create, "string"); 1600a703e490SVasu Dev MODULE_PARM_DESC(create, "Create fcoe port using net device passed in."); 1601a703e490SVasu Dev module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR); 1602a703e490SVasu Dev __MODULE_PARM_TYPE(destroy, "string"); 1603a703e490SVasu Dev MODULE_PARM_DESC(destroy, "Destroy fcoe port"); 1604a703e490SVasu Dev 1605a703e490SVasu Dev /** 1606a703e490SVasu Dev * fcoe_link_ok() - Check if link is ok for the fc_lport 1607a703e490SVasu Dev * @lp: ptr to the fc_lport 1608a703e490SVasu Dev * 1609a703e490SVasu Dev * Any permanently-disqualifying conditions have been previously checked. 1610a703e490SVasu Dev * This also updates the speed setting, which may change with link for 100/1000. 1611a703e490SVasu Dev * 1612a703e490SVasu Dev * This function should probably be checking for PAUSE support at some point 1613a703e490SVasu Dev * in the future. Currently Per-priority-pause is not determinable using 1614a703e490SVasu Dev * ethtool, so we shouldn't be restrictive until that problem is resolved. 1615a703e490SVasu Dev * 1616a703e490SVasu Dev * Returns: 0 if link is OK for use by FCoE. 1617a703e490SVasu Dev * 1618a703e490SVasu Dev */ 1619a703e490SVasu Dev int fcoe_link_ok(struct fc_lport *lp) 1620a703e490SVasu Dev { 1621a703e490SVasu Dev struct fcoe_softc *fc = lport_priv(lp); 1622a703e490SVasu Dev struct net_device *dev = fc->real_dev; 1623a703e490SVasu Dev struct ethtool_cmd ecmd = { ETHTOOL_GSET }; 1624a703e490SVasu Dev int rc = 0; 1625a703e490SVasu Dev 1626a703e490SVasu Dev if ((dev->flags & IFF_UP) && netif_carrier_ok(dev)) { 1627a703e490SVasu Dev dev = fc->phys_dev; 1628a703e490SVasu Dev if (dev->ethtool_ops->get_settings) { 1629a703e490SVasu Dev dev->ethtool_ops->get_settings(dev, &ecmd); 1630a703e490SVasu Dev lp->link_supported_speeds &= 1631a703e490SVasu Dev ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); 1632a703e490SVasu Dev if (ecmd.supported & (SUPPORTED_1000baseT_Half | 1633a703e490SVasu Dev SUPPORTED_1000baseT_Full)) 1634a703e490SVasu Dev lp->link_supported_speeds |= FC_PORTSPEED_1GBIT; 1635a703e490SVasu Dev if (ecmd.supported & SUPPORTED_10000baseT_Full) 1636a703e490SVasu Dev lp->link_supported_speeds |= 1637a703e490SVasu Dev FC_PORTSPEED_10GBIT; 1638a703e490SVasu Dev if (ecmd.speed == SPEED_1000) 1639a703e490SVasu Dev lp->link_speed = FC_PORTSPEED_1GBIT; 1640a703e490SVasu Dev if (ecmd.speed == SPEED_10000) 1641a703e490SVasu Dev lp->link_speed = FC_PORTSPEED_10GBIT; 1642a703e490SVasu Dev } 1643a703e490SVasu Dev } else 1644a703e490SVasu Dev rc = -1; 1645a703e490SVasu Dev 1646a703e490SVasu Dev return rc; 1647a703e490SVasu Dev } 1648a703e490SVasu Dev 1649a703e490SVasu Dev /** 1650a703e490SVasu Dev * fcoe_percpu_clean() - Clear the pending skbs for an lport 1651a703e490SVasu Dev * @lp: the fc_lport 1652a703e490SVasu Dev */ 1653a703e490SVasu Dev void fcoe_percpu_clean(struct fc_lport *lp) 1654a703e490SVasu Dev { 1655a703e490SVasu Dev struct fcoe_percpu_s *pp; 1656a703e490SVasu Dev struct fcoe_rcv_info *fr; 1657a703e490SVasu Dev struct sk_buff_head *list; 1658a703e490SVasu Dev struct sk_buff *skb, *next; 1659a703e490SVasu Dev struct sk_buff *head; 1660a703e490SVasu Dev unsigned int cpu; 1661a703e490SVasu Dev 1662a703e490SVasu Dev for_each_possible_cpu(cpu) { 1663a703e490SVasu Dev pp = &per_cpu(fcoe_percpu, cpu); 1664a703e490SVasu Dev spin_lock_bh(&pp->fcoe_rx_list.lock); 1665a703e490SVasu Dev list = &pp->fcoe_rx_list; 1666a703e490SVasu Dev head = list->next; 1667a703e490SVasu Dev for (skb = head; skb != (struct sk_buff *)list; 1668a703e490SVasu Dev skb = next) { 1669a703e490SVasu Dev next = skb->next; 1670a703e490SVasu Dev fr = fcoe_dev_from_skb(skb); 1671a703e490SVasu Dev if (fr->fr_dev == lp) { 1672a703e490SVasu Dev __skb_unlink(skb, list); 1673a703e490SVasu Dev kfree_skb(skb); 1674a703e490SVasu Dev } 1675a703e490SVasu Dev } 1676a703e490SVasu Dev spin_unlock_bh(&pp->fcoe_rx_list.lock); 1677a703e490SVasu Dev } 1678a703e490SVasu Dev } 1679a703e490SVasu Dev 1680a703e490SVasu Dev /** 1681a703e490SVasu Dev * fcoe_clean_pending_queue() - Dequeue a skb and free it 1682a703e490SVasu Dev * @lp: the corresponding fc_lport 1683a703e490SVasu Dev * 1684a703e490SVasu Dev * Returns: none 1685a703e490SVasu Dev */ 1686a703e490SVasu Dev void fcoe_clean_pending_queue(struct fc_lport *lp) 1687a703e490SVasu Dev { 1688a703e490SVasu Dev struct fcoe_softc *fc = lport_priv(lp); 1689a703e490SVasu Dev struct sk_buff *skb; 1690a703e490SVasu Dev 1691a703e490SVasu Dev spin_lock_bh(&fc->fcoe_pending_queue.lock); 1692a703e490SVasu Dev while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) { 1693a703e490SVasu Dev spin_unlock_bh(&fc->fcoe_pending_queue.lock); 1694a703e490SVasu Dev kfree_skb(skb); 1695a703e490SVasu Dev spin_lock_bh(&fc->fcoe_pending_queue.lock); 1696a703e490SVasu Dev } 1697a703e490SVasu Dev spin_unlock_bh(&fc->fcoe_pending_queue.lock); 1698a703e490SVasu Dev } 1699a703e490SVasu Dev 1700a703e490SVasu Dev /** 1701a703e490SVasu Dev * fcoe_reset() - Resets the fcoe 1702a703e490SVasu Dev * @shost: shost the reset is from 1703a703e490SVasu Dev * 1704a703e490SVasu Dev * Returns: always 0 1705a703e490SVasu Dev */ 1706a703e490SVasu Dev int fcoe_reset(struct Scsi_Host *shost) 1707a703e490SVasu Dev { 1708a703e490SVasu Dev struct fc_lport *lport = shost_priv(shost); 1709a703e490SVasu Dev fc_lport_reset(lport); 1710a703e490SVasu Dev return 0; 1711a703e490SVasu Dev } 1712a703e490SVasu Dev 1713a703e490SVasu Dev /** 1714a703e490SVasu Dev * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device 1715dd3fd72eSChris Leech * @dev: this is currently ptr to net_device 1716a703e490SVasu Dev * 1717a703e490SVasu Dev * Returns: NULL or the located fcoe_softc 1718a703e490SVasu Dev */ 1719a703e490SVasu Dev static struct fcoe_softc * 1720a703e490SVasu Dev fcoe_hostlist_lookup_softc(const struct net_device *dev) 1721a703e490SVasu Dev { 1722a703e490SVasu Dev struct fcoe_softc *fc; 1723a703e490SVasu Dev 1724a703e490SVasu Dev read_lock(&fcoe_hostlist_lock); 1725a703e490SVasu Dev list_for_each_entry(fc, &fcoe_hostlist, list) { 1726a703e490SVasu Dev if (fc->real_dev == dev) { 1727a703e490SVasu Dev read_unlock(&fcoe_hostlist_lock); 1728a703e490SVasu Dev return fc; 1729a703e490SVasu Dev } 1730a703e490SVasu Dev } 1731a703e490SVasu Dev read_unlock(&fcoe_hostlist_lock); 1732a703e490SVasu Dev return NULL; 1733a703e490SVasu Dev } 1734a703e490SVasu Dev 1735a703e490SVasu Dev /** 1736a703e490SVasu Dev * fcoe_hostlist_lookup() - Find the corresponding lport by netdev 1737a703e490SVasu Dev * @netdev: ptr to net_device 1738a703e490SVasu Dev * 1739a703e490SVasu Dev * Returns: 0 for success 1740a703e490SVasu Dev */ 1741a703e490SVasu Dev struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) 1742a703e490SVasu Dev { 1743a703e490SVasu Dev struct fcoe_softc *fc; 1744a703e490SVasu Dev 1745a703e490SVasu Dev fc = fcoe_hostlist_lookup_softc(netdev); 1746a703e490SVasu Dev 174797c8389dSJoe Eykholt return (fc) ? fc->ctlr.lp : NULL; 1748a703e490SVasu Dev } 1749a703e490SVasu Dev 1750a703e490SVasu Dev /** 1751a703e490SVasu Dev * fcoe_hostlist_add() - Add a lport to lports list 1752dd3fd72eSChris Leech * @lp: ptr to the fc_lport to be added 1753a703e490SVasu Dev * 1754a703e490SVasu Dev * Returns: 0 for success 1755a703e490SVasu Dev */ 1756a703e490SVasu Dev int fcoe_hostlist_add(const struct fc_lport *lp) 1757a703e490SVasu Dev { 1758a703e490SVasu Dev struct fcoe_softc *fc; 1759a703e490SVasu Dev 1760a703e490SVasu Dev fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp)); 1761a703e490SVasu Dev if (!fc) { 1762a703e490SVasu Dev fc = lport_priv(lp); 1763a703e490SVasu Dev write_lock_bh(&fcoe_hostlist_lock); 1764a703e490SVasu Dev list_add_tail(&fc->list, &fcoe_hostlist); 1765a703e490SVasu Dev write_unlock_bh(&fcoe_hostlist_lock); 1766a703e490SVasu Dev } 1767a703e490SVasu Dev return 0; 1768a703e490SVasu Dev } 1769a703e490SVasu Dev 1770a703e490SVasu Dev /** 1771a703e490SVasu Dev * fcoe_hostlist_remove() - remove a lport from lports list 1772dd3fd72eSChris Leech * @lp: ptr to the fc_lport to be removed 1773a703e490SVasu Dev * 1774a703e490SVasu Dev * Returns: 0 for success 1775a703e490SVasu Dev */ 1776a703e490SVasu Dev int fcoe_hostlist_remove(const struct fc_lport *lp) 1777a703e490SVasu Dev { 1778a703e490SVasu Dev struct fcoe_softc *fc; 1779a703e490SVasu Dev 1780a703e490SVasu Dev fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp)); 1781a703e490SVasu Dev BUG_ON(!fc); 1782a703e490SVasu Dev write_lock_bh(&fcoe_hostlist_lock); 1783a703e490SVasu Dev list_del(&fc->list); 1784a703e490SVasu Dev write_unlock_bh(&fcoe_hostlist_lock); 1785a703e490SVasu Dev 1786a703e490SVasu Dev return 0; 1787a703e490SVasu Dev } 1788a703e490SVasu Dev 1789a703e490SVasu Dev /** 1790a703e490SVasu Dev * fcoe_init() - fcoe module loading initialization 1791a703e490SVasu Dev * 1792a703e490SVasu Dev * Returns 0 on success, negative on failure 1793a703e490SVasu Dev */ 1794a703e490SVasu Dev static int __init fcoe_init(void) 1795a703e490SVasu Dev { 1796a703e490SVasu Dev unsigned int cpu; 1797a703e490SVasu Dev int rc = 0; 1798a703e490SVasu Dev struct fcoe_percpu_s *p; 1799a703e490SVasu Dev 1800a703e490SVasu Dev INIT_LIST_HEAD(&fcoe_hostlist); 1801a703e490SVasu Dev rwlock_init(&fcoe_hostlist_lock); 1802a703e490SVasu Dev 1803a703e490SVasu Dev for_each_possible_cpu(cpu) { 1804a703e490SVasu Dev p = &per_cpu(fcoe_percpu, cpu); 1805a703e490SVasu Dev skb_queue_head_init(&p->fcoe_rx_list); 1806a703e490SVasu Dev } 1807a703e490SVasu Dev 1808a703e490SVasu Dev for_each_online_cpu(cpu) 1809a703e490SVasu Dev fcoe_percpu_thread_create(cpu); 1810a703e490SVasu Dev 1811a703e490SVasu Dev /* Initialize per CPU interrupt thread */ 1812a703e490SVasu Dev rc = register_hotcpu_notifier(&fcoe_cpu_notifier); 1813a703e490SVasu Dev if (rc) 1814a703e490SVasu Dev goto out_free; 1815a703e490SVasu Dev 1816a703e490SVasu Dev /* Setup link change notification */ 1817a703e490SVasu Dev fcoe_dev_setup(); 1818a703e490SVasu Dev 1819a703e490SVasu Dev setup_timer(&fcoe_timer, fcoe_watchdog, 0); 1820a703e490SVasu Dev 1821a703e490SVasu Dev mod_timer(&fcoe_timer, jiffies + (10 * HZ)); 1822a703e490SVasu Dev 1823a703e490SVasu Dev fcoe_if_init(); 1824a703e490SVasu Dev 1825a703e490SVasu Dev return 0; 1826a703e490SVasu Dev 1827a703e490SVasu Dev out_free: 1828a703e490SVasu Dev for_each_online_cpu(cpu) { 1829a703e490SVasu Dev fcoe_percpu_thread_destroy(cpu); 1830a703e490SVasu Dev } 1831a703e490SVasu Dev 1832a703e490SVasu Dev return rc; 1833a703e490SVasu Dev } 1834a703e490SVasu Dev module_init(fcoe_init); 1835a703e490SVasu Dev 1836a703e490SVasu Dev /** 1837a703e490SVasu Dev * fcoe_exit() - fcoe module unloading cleanup 1838a703e490SVasu Dev * 1839a703e490SVasu Dev * Returns 0 on success, negative on failure 1840a703e490SVasu Dev */ 1841a703e490SVasu Dev static void __exit fcoe_exit(void) 1842a703e490SVasu Dev { 1843a703e490SVasu Dev unsigned int cpu; 1844a703e490SVasu Dev struct fcoe_softc *fc, *tmp; 1845a703e490SVasu Dev 1846a703e490SVasu Dev fcoe_dev_cleanup(); 1847a703e490SVasu Dev 1848a703e490SVasu Dev /* Stop the timer */ 1849a703e490SVasu Dev del_timer_sync(&fcoe_timer); 1850a703e490SVasu Dev 1851a703e490SVasu Dev /* releases the associated fcoe hosts */ 1852a703e490SVasu Dev list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list) 1853a703e490SVasu Dev fcoe_if_destroy(fc->real_dev); 1854a703e490SVasu Dev 1855a703e490SVasu Dev unregister_hotcpu_notifier(&fcoe_cpu_notifier); 1856a703e490SVasu Dev 1857a703e490SVasu Dev for_each_online_cpu(cpu) { 1858a703e490SVasu Dev fcoe_percpu_thread_destroy(cpu); 1859a703e490SVasu Dev } 1860a703e490SVasu Dev 1861a703e490SVasu Dev /* detach from scsi transport */ 1862a703e490SVasu Dev fcoe_if_exit(); 1863a703e490SVasu Dev } 1864a703e490SVasu Dev module_exit(fcoe_exit); 1865