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 60a703e490SVasu Dev /* Function Prototyes */ 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 /** 139ab6b85c1SVasu Dev * fcoe_fip_recv - handle a received FIP frame. 140ab6b85c1SVasu Dev * @skb: the receive skb 141ab6b85c1SVasu Dev * @dev: associated &net_device 142ab6b85c1SVasu Dev * @ptype: the &packet_type structure which was used to register this handler. 143ab6b85c1SVasu Dev * @orig_dev: original receive &net_device, in case @dev is a bond. 144ab6b85c1SVasu Dev * 145ab6b85c1SVasu Dev * Returns: 0 for success 146ab6b85c1SVasu Dev */ 147ab6b85c1SVasu Dev static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev, 148ab6b85c1SVasu Dev struct packet_type *ptype, 149ab6b85c1SVasu Dev struct net_device *orig_dev) 150ab6b85c1SVasu Dev { 151ab6b85c1SVasu Dev struct fcoe_softc *fc; 152ab6b85c1SVasu Dev 153ab6b85c1SVasu Dev fc = container_of(ptype, struct fcoe_softc, fip_packet_type); 154ab6b85c1SVasu Dev fcoe_ctlr_recv(&fc->ctlr, skb); 155ab6b85c1SVasu Dev return 0; 156ab6b85c1SVasu Dev } 157ab6b85c1SVasu Dev 158ab6b85c1SVasu Dev /** 159ab6b85c1SVasu Dev * fcoe_fip_send() - send an Ethernet-encapsulated FIP frame. 160ab6b85c1SVasu Dev * @fip: FCoE controller. 161ab6b85c1SVasu Dev * @skb: FIP Packet. 162ab6b85c1SVasu Dev */ 163ab6b85c1SVasu Dev static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) 164ab6b85c1SVasu Dev { 165ab6b85c1SVasu Dev skb->dev = fcoe_from_ctlr(fip)->real_dev; 166ab6b85c1SVasu Dev dev_queue_xmit(skb); 167ab6b85c1SVasu Dev } 168ab6b85c1SVasu Dev 169ab6b85c1SVasu Dev /** 170ab6b85c1SVasu Dev * fcoe_update_src_mac() - Update Ethernet MAC filters. 171ab6b85c1SVasu Dev * @fip: FCoE controller. 172ab6b85c1SVasu Dev * @old: Unicast MAC address to delete if the MAC is non-zero. 173ab6b85c1SVasu Dev * @new: Unicast MAC address to add. 174ab6b85c1SVasu Dev * 175ab6b85c1SVasu Dev * Remove any previously-set unicast MAC filter. 176ab6b85c1SVasu Dev * Add secondary FCoE MAC address filter for our OUI. 177ab6b85c1SVasu Dev */ 178ab6b85c1SVasu Dev static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new) 179ab6b85c1SVasu Dev { 180ab6b85c1SVasu Dev struct fcoe_softc *fc; 181ab6b85c1SVasu Dev 182ab6b85c1SVasu Dev fc = fcoe_from_ctlr(fip); 183ab6b85c1SVasu Dev rtnl_lock(); 184ab6b85c1SVasu Dev if (!is_zero_ether_addr(old)) 185ab6b85c1SVasu Dev dev_unicast_delete(fc->real_dev, old, ETH_ALEN); 186ab6b85c1SVasu Dev dev_unicast_add(fc->real_dev, new, ETH_ALEN); 187ab6b85c1SVasu Dev rtnl_unlock(); 188ab6b85c1SVasu Dev } 189ab6b85c1SVasu Dev 190ab6b85c1SVasu Dev /** 191a703e490SVasu Dev * fcoe_lport_config() - sets up the fc_lport 192a703e490SVasu Dev * @lp: ptr to the fc_lport 193a703e490SVasu Dev * @shost: ptr to the parent scsi host 194a703e490SVasu Dev * 195a703e490SVasu Dev * Returns: 0 for success 196a703e490SVasu Dev */ 197a703e490SVasu Dev static int fcoe_lport_config(struct fc_lport *lp) 198a703e490SVasu Dev { 199a703e490SVasu Dev lp->link_up = 0; 200a703e490SVasu Dev lp->qfull = 0; 201a703e490SVasu Dev lp->max_retry_count = 3; 202a703e490SVasu Dev lp->e_d_tov = 2 * 1000; /* FC-FS default */ 203a703e490SVasu Dev lp->r_a_tov = 2 * 2 * 1000; 204a703e490SVasu Dev lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS | 205a703e490SVasu Dev FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL); 206a703e490SVasu Dev 207a703e490SVasu Dev fc_lport_init_stats(lp); 208a703e490SVasu Dev 209a703e490SVasu Dev /* lport fc_lport related configuration */ 210a703e490SVasu Dev fc_lport_config(lp); 211a703e490SVasu Dev 212a703e490SVasu Dev /* offload related configuration */ 213a703e490SVasu Dev lp->crc_offload = 0; 214a703e490SVasu Dev lp->seq_offload = 0; 215a703e490SVasu Dev lp->lro_enabled = 0; 216a703e490SVasu Dev lp->lro_xid = 0; 217a703e490SVasu Dev lp->lso_max = 0; 218a703e490SVasu Dev 219a703e490SVasu Dev return 0; 220a703e490SVasu Dev } 221a703e490SVasu Dev 222a703e490SVasu Dev /** 223ab6b85c1SVasu Dev * fcoe_netdev_cleanup() - clean up netdev configurations 224ab6b85c1SVasu Dev * @fc: ptr to the fcoe_softc 225ab6b85c1SVasu Dev */ 226ab6b85c1SVasu Dev void fcoe_netdev_cleanup(struct fcoe_softc *fc) 227ab6b85c1SVasu Dev { 228ab6b85c1SVasu Dev u8 flogi_maddr[ETH_ALEN]; 229ab6b85c1SVasu Dev 230ab6b85c1SVasu Dev /* Don't listen for Ethernet packets anymore */ 231ab6b85c1SVasu Dev dev_remove_pack(&fc->fcoe_packet_type); 232ab6b85c1SVasu Dev dev_remove_pack(&fc->fip_packet_type); 233ab6b85c1SVasu Dev 234ab6b85c1SVasu Dev /* Delete secondary MAC addresses */ 235ab6b85c1SVasu Dev rtnl_lock(); 236ab6b85c1SVasu Dev memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); 237ab6b85c1SVasu Dev dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN); 238ab6b85c1SVasu Dev if (!is_zero_ether_addr(fc->ctlr.data_src_addr)) 239ab6b85c1SVasu Dev dev_unicast_delete(fc->real_dev, 240ab6b85c1SVasu Dev fc->ctlr.data_src_addr, ETH_ALEN); 241184dd345SVasu Dev if (fc->ctlr.spma) 242184dd345SVasu Dev dev_unicast_delete(fc->real_dev, 243184dd345SVasu Dev fc->ctlr.ctl_src_addr, ETH_ALEN); 244ab6b85c1SVasu Dev dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); 245ab6b85c1SVasu Dev rtnl_unlock(); 246ab6b85c1SVasu Dev } 247ab6b85c1SVasu Dev 248ab6b85c1SVasu Dev /** 249a703e490SVasu Dev * fcoe_netdev_config() - Set up netdev for SW FCoE 250a703e490SVasu Dev * @lp : ptr to the fc_lport 251a703e490SVasu Dev * @netdev : ptr to the associated netdevice struct 252a703e490SVasu Dev * 253a703e490SVasu Dev * Must be called after fcoe_lport_config() as it will use lport mutex 254a703e490SVasu Dev * 255a703e490SVasu Dev * Returns : 0 for success 256a703e490SVasu Dev */ 257a703e490SVasu Dev static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) 258a703e490SVasu Dev { 259a703e490SVasu Dev u32 mfs; 260a703e490SVasu Dev u64 wwnn, wwpn; 261a703e490SVasu Dev struct fcoe_softc *fc; 262a703e490SVasu Dev u8 flogi_maddr[ETH_ALEN]; 263184dd345SVasu Dev struct netdev_hw_addr *ha; 264a703e490SVasu Dev 265a703e490SVasu Dev /* Setup lport private data to point to fcoe softc */ 266a703e490SVasu Dev fc = lport_priv(lp); 26797c8389dSJoe Eykholt fc->ctlr.lp = lp; 268a703e490SVasu Dev fc->real_dev = netdev; 269a703e490SVasu Dev fc->phys_dev = netdev; 270a703e490SVasu Dev 271a703e490SVasu Dev /* Require support for get_pauseparam ethtool op. */ 272a703e490SVasu Dev if (netdev->priv_flags & IFF_802_1Q_VLAN) 273a703e490SVasu Dev fc->phys_dev = vlan_dev_real_dev(netdev); 274a703e490SVasu Dev 275a703e490SVasu Dev /* Do not support for bonding device */ 276a703e490SVasu Dev if ((fc->real_dev->priv_flags & IFF_MASTER_ALB) || 277a703e490SVasu Dev (fc->real_dev->priv_flags & IFF_SLAVE_INACTIVE) || 278a703e490SVasu Dev (fc->real_dev->priv_flags & IFF_MASTER_8023AD)) { 279a703e490SVasu Dev return -EOPNOTSUPP; 280a703e490SVasu Dev } 281a703e490SVasu Dev 282a703e490SVasu Dev /* 283a703e490SVasu Dev * Determine max frame size based on underlying device and optional 284a703e490SVasu Dev * user-configured limit. If the MFS is too low, fcoe_link_ok() 285a703e490SVasu Dev * will return 0, so do this first. 286a703e490SVasu Dev */ 287a703e490SVasu Dev mfs = fc->real_dev->mtu - (sizeof(struct fcoe_hdr) + 288a703e490SVasu Dev sizeof(struct fcoe_crc_eof)); 289a703e490SVasu Dev if (fc_set_mfs(lp, mfs)) 290a703e490SVasu Dev return -EINVAL; 291a703e490SVasu Dev 292a703e490SVasu Dev /* offload features support */ 293a703e490SVasu Dev if (fc->real_dev->features & NETIF_F_SG) 294a703e490SVasu Dev lp->sg_supp = 1; 295a703e490SVasu Dev 296a703e490SVasu Dev #ifdef NETIF_F_FCOE_CRC 297a703e490SVasu Dev if (netdev->features & NETIF_F_FCOE_CRC) { 298a703e490SVasu Dev lp->crc_offload = 1; 299a703e490SVasu Dev printk(KERN_DEBUG "fcoe:%s supports FCCRC offload\n", 300a703e490SVasu Dev netdev->name); 301a703e490SVasu Dev } 302a703e490SVasu Dev #endif 303a703e490SVasu Dev #ifdef NETIF_F_FSO 304a703e490SVasu Dev if (netdev->features & NETIF_F_FSO) { 305a703e490SVasu Dev lp->seq_offload = 1; 306a703e490SVasu Dev lp->lso_max = netdev->gso_max_size; 307a703e490SVasu Dev printk(KERN_DEBUG "fcoe:%s supports LSO for max len 0x%x\n", 308a703e490SVasu Dev netdev->name, lp->lso_max); 309a703e490SVasu Dev } 310a703e490SVasu Dev #endif 311a703e490SVasu Dev if (netdev->fcoe_ddp_xid) { 312a703e490SVasu Dev lp->lro_enabled = 1; 313a703e490SVasu Dev lp->lro_xid = netdev->fcoe_ddp_xid; 314a703e490SVasu Dev printk(KERN_DEBUG "fcoe:%s supports LRO for max xid 0x%x\n", 315a703e490SVasu Dev netdev->name, lp->lro_xid); 316a703e490SVasu Dev } 317a703e490SVasu Dev skb_queue_head_init(&fc->fcoe_pending_queue); 318a703e490SVasu Dev fc->fcoe_pending_queue_active = 0; 319a703e490SVasu Dev 320184dd345SVasu Dev /* look for SAN MAC address, if multiple SAN MACs exist, only 321184dd345SVasu Dev * use the first one for SPMA */ 322184dd345SVasu Dev rcu_read_lock(); 323184dd345SVasu Dev for_each_dev_addr(netdev, ha) { 324184dd345SVasu Dev if ((ha->type == NETDEV_HW_ADDR_T_SAN) && 325184dd345SVasu Dev (is_valid_ether_addr(fc->ctlr.ctl_src_addr))) { 326184dd345SVasu Dev memcpy(fc->ctlr.ctl_src_addr, ha->addr, ETH_ALEN); 327184dd345SVasu Dev fc->ctlr.spma = 1; 328184dd345SVasu Dev break; 329184dd345SVasu Dev } 330184dd345SVasu Dev } 331184dd345SVasu Dev rcu_read_unlock(); 332184dd345SVasu Dev 333a703e490SVasu Dev /* setup Source Mac Address */ 334184dd345SVasu Dev if (!fc->ctlr.spma) 33597c8389dSJoe Eykholt memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr, 336a703e490SVasu Dev fc->real_dev->addr_len); 337a703e490SVasu Dev 338a703e490SVasu Dev wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0); 339a703e490SVasu Dev fc_set_wwnn(lp, wwnn); 340a703e490SVasu Dev /* XXX - 3rd arg needs to be vlan id */ 341a703e490SVasu Dev wwpn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 2, 0); 342a703e490SVasu Dev fc_set_wwpn(lp, wwpn); 343a703e490SVasu Dev 344a703e490SVasu Dev /* 345a703e490SVasu Dev * Add FCoE MAC address as second unicast MAC address 346a703e490SVasu Dev * or enter promiscuous mode if not capable of listening 347a703e490SVasu Dev * for multiple unicast MACs. 348a703e490SVasu Dev */ 349a703e490SVasu Dev rtnl_lock(); 350a703e490SVasu Dev memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); 351a703e490SVasu Dev dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN); 352184dd345SVasu Dev if (fc->ctlr.spma) 353184dd345SVasu Dev dev_unicast_add(fc->real_dev, fc->ctlr.ctl_src_addr, ETH_ALEN); 354a703e490SVasu Dev rtnl_unlock(); 355a703e490SVasu Dev 356a703e490SVasu Dev /* 357a703e490SVasu Dev * setup the receive function from ethernet driver 358a703e490SVasu Dev * on the ethertype for the given device 359a703e490SVasu Dev */ 360a703e490SVasu Dev fc->fcoe_packet_type.func = fcoe_rcv; 361a703e490SVasu Dev fc->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE); 362a703e490SVasu Dev fc->fcoe_packet_type.dev = fc->real_dev; 363a703e490SVasu Dev dev_add_pack(&fc->fcoe_packet_type); 364a703e490SVasu Dev 365ab6b85c1SVasu Dev fc->fip_packet_type.func = fcoe_fip_recv; 366ab6b85c1SVasu Dev fc->fip_packet_type.type = htons(ETH_P_FIP); 367ab6b85c1SVasu Dev fc->fip_packet_type.dev = fc->real_dev; 368ab6b85c1SVasu Dev dev_add_pack(&fc->fip_packet_type); 369ab6b85c1SVasu Dev 370a703e490SVasu Dev return 0; 371a703e490SVasu Dev } 372a703e490SVasu Dev 373a703e490SVasu Dev /** 374a703e490SVasu Dev * fcoe_shost_config() - Sets up fc_lport->host 375a703e490SVasu Dev * @lp : ptr to the fc_lport 376a703e490SVasu Dev * @shost : ptr to the associated scsi host 377a703e490SVasu Dev * @dev : device associated to scsi host 378a703e490SVasu Dev * 379a703e490SVasu Dev * Must be called after fcoe_lport_config() and fcoe_netdev_config() 380a703e490SVasu Dev * 381a703e490SVasu Dev * Returns : 0 for success 382a703e490SVasu Dev */ 383a703e490SVasu Dev static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, 384a703e490SVasu Dev struct device *dev) 385a703e490SVasu Dev { 386a703e490SVasu Dev int rc = 0; 387a703e490SVasu Dev 388a703e490SVasu Dev /* lport scsi host config */ 389a703e490SVasu Dev lp->host = shost; 390a703e490SVasu Dev 391a703e490SVasu Dev lp->host->max_lun = FCOE_MAX_LUN; 392a703e490SVasu Dev lp->host->max_id = FCOE_MAX_FCP_TARGET; 393a703e490SVasu Dev lp->host->max_channel = 0; 394a703e490SVasu Dev lp->host->transportt = scsi_transport_fcoe_sw; 395a703e490SVasu Dev 396a703e490SVasu Dev /* add the new host to the SCSI-ml */ 397a703e490SVasu Dev rc = scsi_add_host(lp->host, dev); 398a703e490SVasu Dev if (rc) { 399a703e490SVasu Dev FC_DBG("fcoe_shost_config:error on scsi_add_host\n"); 400a703e490SVasu Dev return rc; 401a703e490SVasu Dev } 402a703e490SVasu Dev sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s", 403a703e490SVasu Dev FCOE_NAME, FCOE_VERSION, 404a703e490SVasu Dev fcoe_netdev(lp)->name); 405a703e490SVasu Dev 406a703e490SVasu Dev return 0; 407a703e490SVasu Dev } 408a703e490SVasu Dev 409a703e490SVasu Dev /** 410a703e490SVasu Dev * fcoe_em_config() - allocates em for this lport 411a703e490SVasu Dev * @lp: the port that em is to allocated for 412a703e490SVasu Dev * 413a703e490SVasu Dev * Returns : 0 on success 414a703e490SVasu Dev */ 415a703e490SVasu Dev static inline int fcoe_em_config(struct fc_lport *lp) 416a703e490SVasu Dev { 417a703e490SVasu Dev BUG_ON(lp->emp); 418a703e490SVasu Dev 419a703e490SVasu Dev lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3, 420a703e490SVasu Dev FCOE_MIN_XID, FCOE_MAX_XID); 421a703e490SVasu Dev if (!lp->emp) 422a703e490SVasu Dev return -ENOMEM; 423a703e490SVasu Dev 424a703e490SVasu Dev return 0; 425a703e490SVasu Dev } 426a703e490SVasu Dev 427a703e490SVasu Dev /** 428a703e490SVasu Dev * fcoe_if_destroy() - FCoE software HBA tear-down function 429a703e490SVasu Dev * @netdev: ptr to the associated net_device 430a703e490SVasu Dev * 431a703e490SVasu Dev * Returns: 0 if link is OK for use by FCoE. 432a703e490SVasu Dev */ 433a703e490SVasu Dev static int fcoe_if_destroy(struct net_device *netdev) 434a703e490SVasu Dev { 435a703e490SVasu Dev struct fc_lport *lp = NULL; 436a703e490SVasu Dev struct fcoe_softc *fc; 437a703e490SVasu Dev 438a703e490SVasu Dev BUG_ON(!netdev); 439a703e490SVasu Dev 440a703e490SVasu Dev printk(KERN_DEBUG "fcoe_if_destroy:interface on %s\n", 441a703e490SVasu Dev netdev->name); 442a703e490SVasu Dev 443a703e490SVasu Dev lp = fcoe_hostlist_lookup(netdev); 444a703e490SVasu Dev if (!lp) 445a703e490SVasu Dev return -ENODEV; 446a703e490SVasu Dev 447a703e490SVasu Dev fc = lport_priv(lp); 448a703e490SVasu Dev 449a703e490SVasu Dev /* Logout of the fabric */ 450a703e490SVasu Dev fc_fabric_logoff(lp); 451a703e490SVasu Dev 452a703e490SVasu Dev /* Remove the instance from fcoe's list */ 453a703e490SVasu Dev fcoe_hostlist_remove(lp); 454a703e490SVasu Dev 455ab6b85c1SVasu Dev /* clean up netdev configurations */ 456ab6b85c1SVasu Dev fcoe_netdev_cleanup(fc); 457ab6b85c1SVasu Dev 458ab6b85c1SVasu Dev /* tear-down the FCoE controller */ 45997c8389dSJoe Eykholt fcoe_ctlr_destroy(&fc->ctlr); 460a703e490SVasu Dev 461a703e490SVasu Dev /* Cleanup the fc_lport */ 462a703e490SVasu Dev fc_lport_destroy(lp); 463a703e490SVasu Dev fc_fcp_destroy(lp); 464a703e490SVasu Dev 465a703e490SVasu Dev /* Detach from the scsi-ml */ 466a703e490SVasu Dev fc_remove_host(lp->host); 467a703e490SVasu Dev scsi_remove_host(lp->host); 468a703e490SVasu Dev 469a703e490SVasu Dev /* There are no more rports or I/O, free the EM */ 470a703e490SVasu Dev if (lp->emp) 471a703e490SVasu Dev fc_exch_mgr_free(lp->emp); 472a703e490SVasu Dev 473a703e490SVasu Dev /* Free the per-CPU revieve threads */ 474a703e490SVasu Dev fcoe_percpu_clean(lp); 475a703e490SVasu Dev 476a703e490SVasu Dev /* Free existing skbs */ 477a703e490SVasu Dev fcoe_clean_pending_queue(lp); 478a703e490SVasu Dev 479a703e490SVasu Dev /* Free memory used by statistical counters */ 480a703e490SVasu Dev fc_lport_free_stats(lp); 481a703e490SVasu Dev 482a703e490SVasu Dev /* Release the net_device and Scsi_Host */ 483a703e490SVasu Dev dev_put(fc->real_dev); 484a703e490SVasu Dev scsi_host_put(lp->host); 485a703e490SVasu Dev 486a703e490SVasu Dev return 0; 487a703e490SVasu Dev } 488a703e490SVasu Dev 489a703e490SVasu Dev /* 490a703e490SVasu Dev * fcoe_ddp_setup - calls LLD's ddp_setup through net_device 491a703e490SVasu Dev * @lp: the corresponding fc_lport 492a703e490SVasu Dev * @xid: the exchange id for this ddp transfer 493a703e490SVasu Dev * @sgl: the scatterlist describing this transfer 494a703e490SVasu Dev * @sgc: number of sg items 495a703e490SVasu Dev * 496a703e490SVasu Dev * Returns : 0 no ddp 497a703e490SVasu Dev */ 498a703e490SVasu Dev static int fcoe_ddp_setup(struct fc_lport *lp, u16 xid, 499a703e490SVasu Dev struct scatterlist *sgl, unsigned int sgc) 500a703e490SVasu Dev { 501a703e490SVasu Dev struct net_device *n = fcoe_netdev(lp); 502a703e490SVasu Dev 503a703e490SVasu Dev if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_setup) 504a703e490SVasu Dev return n->netdev_ops->ndo_fcoe_ddp_setup(n, xid, sgl, sgc); 505a703e490SVasu Dev 506a703e490SVasu Dev return 0; 507a703e490SVasu Dev } 508a703e490SVasu Dev 509a703e490SVasu Dev /* 510a703e490SVasu Dev * fcoe_ddp_done - calls LLD's ddp_done through net_device 511a703e490SVasu Dev * @lp: the corresponding fc_lport 512a703e490SVasu Dev * @xid: the exchange id for this ddp transfer 513a703e490SVasu Dev * 514a703e490SVasu Dev * Returns : the length of data that have been completed by ddp 515a703e490SVasu Dev */ 516a703e490SVasu Dev static int fcoe_ddp_done(struct fc_lport *lp, u16 xid) 517a703e490SVasu Dev { 518a703e490SVasu Dev struct net_device *n = fcoe_netdev(lp); 519a703e490SVasu Dev 520a703e490SVasu Dev if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_done) 521a703e490SVasu Dev return n->netdev_ops->ndo_fcoe_ddp_done(n, xid); 522a703e490SVasu Dev return 0; 523a703e490SVasu Dev } 524a703e490SVasu Dev 525a703e490SVasu Dev static struct libfc_function_template fcoe_libfc_fcn_templ = { 526a703e490SVasu Dev .frame_send = fcoe_xmit, 527a703e490SVasu Dev .ddp_setup = fcoe_ddp_setup, 528a703e490SVasu Dev .ddp_done = fcoe_ddp_done, 529a703e490SVasu Dev }; 530a703e490SVasu Dev 531a703e490SVasu Dev /** 532a703e490SVasu Dev * fcoe_if_create() - this function creates the fcoe interface 533a703e490SVasu Dev * @netdev: pointer the associated netdevice 534a703e490SVasu Dev * 535a703e490SVasu Dev * Creates fc_lport struct and scsi_host for lport, configures lport 536a703e490SVasu Dev * and starts fabric login. 537a703e490SVasu Dev * 538a703e490SVasu Dev * Returns : 0 on success 539a703e490SVasu Dev */ 540a703e490SVasu Dev static int fcoe_if_create(struct net_device *netdev) 541a703e490SVasu Dev { 542a703e490SVasu Dev int rc; 543a703e490SVasu Dev struct fc_lport *lp = NULL; 544a703e490SVasu Dev struct fcoe_softc *fc; 545a703e490SVasu Dev struct Scsi_Host *shost; 546a703e490SVasu Dev 547a703e490SVasu Dev BUG_ON(!netdev); 548a703e490SVasu Dev 549a703e490SVasu Dev printk(KERN_DEBUG "fcoe_if_create:interface on %s\n", 550a703e490SVasu Dev netdev->name); 551a703e490SVasu Dev 552a703e490SVasu Dev lp = fcoe_hostlist_lookup(netdev); 553a703e490SVasu Dev if (lp) 554a703e490SVasu Dev return -EEXIST; 555a703e490SVasu Dev 556a0a25da2SVasu Dev shost = libfc_host_alloc(&fcoe_shost_template, 557a703e490SVasu Dev sizeof(struct fcoe_softc)); 558a703e490SVasu Dev if (!shost) { 559a703e490SVasu Dev FC_DBG("Could not allocate host structure\n"); 560a703e490SVasu Dev return -ENOMEM; 561a703e490SVasu Dev } 562a703e490SVasu Dev lp = shost_priv(shost); 563a703e490SVasu Dev fc = lport_priv(lp); 564a703e490SVasu Dev 565a703e490SVasu Dev /* configure fc_lport, e.g., em */ 566a703e490SVasu Dev rc = fcoe_lport_config(lp); 567a703e490SVasu Dev if (rc) { 568a703e490SVasu Dev FC_DBG("Could not configure lport\n"); 569a703e490SVasu Dev goto out_host_put; 570a703e490SVasu Dev } 571a703e490SVasu Dev 57297c8389dSJoe Eykholt /* 57397c8389dSJoe Eykholt * Initialize FIP. 57497c8389dSJoe Eykholt */ 57597c8389dSJoe Eykholt fcoe_ctlr_init(&fc->ctlr); 57697c8389dSJoe Eykholt fc->ctlr.send = fcoe_fip_send; 57797c8389dSJoe Eykholt fc->ctlr.update_mac = fcoe_update_src_mac; 57897c8389dSJoe Eykholt 579ab6b85c1SVasu Dev /* configure lport network properties */ 580ab6b85c1SVasu Dev rc = fcoe_netdev_config(lp, netdev); 581ab6b85c1SVasu Dev if (rc) { 582ab6b85c1SVasu Dev FC_DBG("Could not configure netdev for the interface\n"); 583ab6b85c1SVasu Dev goto out_netdev_cleanup; 584ab6b85c1SVasu Dev } 58597c8389dSJoe Eykholt 586a703e490SVasu Dev /* configure lport scsi host properties */ 587a703e490SVasu Dev rc = fcoe_shost_config(lp, shost, &netdev->dev); 588a703e490SVasu Dev if (rc) { 589a703e490SVasu Dev FC_DBG("Could not configure shost for lport\n"); 590ab6b85c1SVasu Dev goto out_netdev_cleanup; 591a703e490SVasu Dev } 592a703e490SVasu Dev 593a703e490SVasu Dev /* lport exch manager allocation */ 594a703e490SVasu Dev rc = fcoe_em_config(lp); 595a703e490SVasu Dev if (rc) { 596a703e490SVasu Dev FC_DBG("Could not configure em for lport\n"); 597ab6b85c1SVasu Dev goto out_netdev_cleanup; 598a703e490SVasu Dev } 599a703e490SVasu Dev 600a703e490SVasu Dev /* Initialize the library */ 601a703e490SVasu Dev rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ); 602a703e490SVasu Dev if (rc) { 603a703e490SVasu Dev FC_DBG("Could not configure libfc for lport!\n"); 604a703e490SVasu Dev goto out_lp_destroy; 605a703e490SVasu Dev } 606a703e490SVasu Dev 607a703e490SVasu Dev /* add to lports list */ 608a703e490SVasu Dev fcoe_hostlist_add(lp); 609a703e490SVasu Dev 610a703e490SVasu Dev lp->boot_time = jiffies; 611a703e490SVasu Dev 612a703e490SVasu Dev fc_fabric_login(lp); 613a703e490SVasu Dev 61497c8389dSJoe Eykholt if (!fcoe_link_ok(lp)) 61597c8389dSJoe Eykholt fcoe_ctlr_link_up(&fc->ctlr); 61697c8389dSJoe Eykholt 617a703e490SVasu Dev dev_hold(netdev); 618a703e490SVasu Dev 619a703e490SVasu Dev return rc; 620a703e490SVasu Dev 621a703e490SVasu Dev out_lp_destroy: 622a703e490SVasu Dev fc_exch_mgr_free(lp->emp); /* Free the EM */ 623ab6b85c1SVasu Dev out_netdev_cleanup: 624ab6b85c1SVasu Dev fcoe_netdev_cleanup(fc); 625a703e490SVasu Dev out_host_put: 626a703e490SVasu Dev scsi_host_put(lp->host); 627a703e490SVasu Dev return rc; 628a703e490SVasu Dev } 629a703e490SVasu Dev 630a703e490SVasu Dev /** 631a703e490SVasu Dev * fcoe_if_init() - attach to scsi transport 632a703e490SVasu Dev * 633a703e490SVasu Dev * Returns : 0 on success 634a703e490SVasu Dev */ 635a703e490SVasu Dev static int __init fcoe_if_init(void) 636a703e490SVasu Dev { 637a703e490SVasu Dev /* attach to scsi transport */ 638a703e490SVasu Dev scsi_transport_fcoe_sw = 639a703e490SVasu Dev fc_attach_transport(&fcoe_transport_function); 640a703e490SVasu Dev 641a703e490SVasu Dev if (!scsi_transport_fcoe_sw) { 642a703e490SVasu Dev printk(KERN_ERR "fcoe_init:fc_attach_transport() failed\n"); 643a703e490SVasu Dev return -ENODEV; 644a703e490SVasu Dev } 645a703e490SVasu Dev 646a703e490SVasu Dev return 0; 647a703e490SVasu Dev } 648a703e490SVasu Dev 649a703e490SVasu Dev /** 650a703e490SVasu Dev * fcoe_if_exit() - detach from scsi transport 651a703e490SVasu Dev * 652a703e490SVasu Dev * Returns : 0 on success 653a703e490SVasu Dev */ 654a703e490SVasu Dev int __exit fcoe_if_exit(void) 655a703e490SVasu Dev { 656a703e490SVasu Dev fc_release_transport(scsi_transport_fcoe_sw); 657a703e490SVasu Dev return 0; 658a703e490SVasu Dev } 659a703e490SVasu Dev 660a703e490SVasu Dev /** 661a703e490SVasu Dev * fcoe_percpu_thread_create() - Create a receive thread for an online cpu 662a703e490SVasu Dev * @cpu: cpu index for the online cpu 663a703e490SVasu Dev */ 664a703e490SVasu Dev static void fcoe_percpu_thread_create(unsigned int cpu) 665a703e490SVasu Dev { 666a703e490SVasu Dev struct fcoe_percpu_s *p; 667a703e490SVasu Dev struct task_struct *thread; 668a703e490SVasu Dev 669a703e490SVasu Dev p = &per_cpu(fcoe_percpu, cpu); 670a703e490SVasu Dev 671a703e490SVasu Dev thread = kthread_create(fcoe_percpu_receive_thread, 672a703e490SVasu Dev (void *)p, "fcoethread/%d", cpu); 673a703e490SVasu Dev 674a703e490SVasu Dev if (likely(!IS_ERR(p->thread))) { 675a703e490SVasu Dev kthread_bind(thread, cpu); 676a703e490SVasu Dev wake_up_process(thread); 677a703e490SVasu Dev 678a703e490SVasu Dev spin_lock_bh(&p->fcoe_rx_list.lock); 679a703e490SVasu Dev p->thread = thread; 680a703e490SVasu Dev spin_unlock_bh(&p->fcoe_rx_list.lock); 681a703e490SVasu Dev } 682a703e490SVasu Dev } 683a703e490SVasu Dev 684a703e490SVasu Dev /** 685a703e490SVasu Dev * fcoe_percpu_thread_destroy() - removes the rx thread for the given cpu 686a703e490SVasu Dev * @cpu: cpu index the rx thread is to be removed 687a703e490SVasu Dev * 688a703e490SVasu Dev * Destroys a per-CPU Rx thread. Any pending skbs are moved to the 689a703e490SVasu Dev * current CPU's Rx thread. If the thread being destroyed is bound to 690a703e490SVasu Dev * the CPU processing this context the skbs will be freed. 691a703e490SVasu Dev */ 692a703e490SVasu Dev static void fcoe_percpu_thread_destroy(unsigned int cpu) 693a703e490SVasu Dev { 694a703e490SVasu Dev struct fcoe_percpu_s *p; 695a703e490SVasu Dev struct task_struct *thread; 696a703e490SVasu Dev struct page *crc_eof; 697a703e490SVasu Dev struct sk_buff *skb; 698a703e490SVasu Dev #ifdef CONFIG_SMP 699a703e490SVasu Dev struct fcoe_percpu_s *p0; 700a703e490SVasu Dev unsigned targ_cpu = smp_processor_id(); 701a703e490SVasu Dev #endif /* CONFIG_SMP */ 702a703e490SVasu Dev 703a703e490SVasu Dev printk(KERN_DEBUG "fcoe: Destroying receive thread for CPU %d\n", cpu); 704a703e490SVasu Dev 705a703e490SVasu Dev /* Prevent any new skbs from being queued for this CPU. */ 706a703e490SVasu Dev p = &per_cpu(fcoe_percpu, cpu); 707a703e490SVasu Dev spin_lock_bh(&p->fcoe_rx_list.lock); 708a703e490SVasu Dev thread = p->thread; 709a703e490SVasu Dev p->thread = NULL; 710a703e490SVasu Dev crc_eof = p->crc_eof_page; 711a703e490SVasu Dev p->crc_eof_page = NULL; 712a703e490SVasu Dev p->crc_eof_offset = 0; 713a703e490SVasu Dev spin_unlock_bh(&p->fcoe_rx_list.lock); 714a703e490SVasu Dev 715a703e490SVasu Dev #ifdef CONFIG_SMP 716a703e490SVasu Dev /* 717a703e490SVasu Dev * Don't bother moving the skb's if this context is running 718a703e490SVasu Dev * on the same CPU that is having its thread destroyed. This 719a703e490SVasu Dev * can easily happen when the module is removed. 720a703e490SVasu Dev */ 721a703e490SVasu Dev if (cpu != targ_cpu) { 722a703e490SVasu Dev p0 = &per_cpu(fcoe_percpu, targ_cpu); 723a703e490SVasu Dev spin_lock_bh(&p0->fcoe_rx_list.lock); 724a703e490SVasu Dev if (p0->thread) { 725a703e490SVasu Dev FC_DBG("Moving frames from CPU %d to CPU %d\n", 726a703e490SVasu Dev cpu, targ_cpu); 727a703e490SVasu Dev 728a703e490SVasu Dev while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL) 729a703e490SVasu Dev __skb_queue_tail(&p0->fcoe_rx_list, skb); 730a703e490SVasu Dev spin_unlock_bh(&p0->fcoe_rx_list.lock); 731a703e490SVasu Dev } else { 732a703e490SVasu Dev /* 733a703e490SVasu Dev * The targeted CPU is not initialized and cannot accept 734a703e490SVasu Dev * new skbs. Unlock the targeted CPU and drop the skbs 735a703e490SVasu Dev * on the CPU that is going offline. 736a703e490SVasu Dev */ 737a703e490SVasu Dev while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL) 738a703e490SVasu Dev kfree_skb(skb); 739a703e490SVasu Dev spin_unlock_bh(&p0->fcoe_rx_list.lock); 740a703e490SVasu Dev } 741a703e490SVasu Dev } else { 742a703e490SVasu Dev /* 743a703e490SVasu Dev * This scenario occurs when the module is being removed 744a703e490SVasu Dev * and all threads are being destroyed. skbs will continue 745a703e490SVasu Dev * to be shifted from the CPU thread that is being removed 746a703e490SVasu Dev * to the CPU thread associated with the CPU that is processing 747a703e490SVasu Dev * the module removal. Once there is only one CPU Rx thread it 748a703e490SVasu Dev * will reach this case and we will drop all skbs and later 749a703e490SVasu Dev * stop the thread. 750a703e490SVasu Dev */ 751a703e490SVasu Dev spin_lock_bh(&p->fcoe_rx_list.lock); 752a703e490SVasu Dev while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL) 753a703e490SVasu Dev kfree_skb(skb); 754a703e490SVasu Dev spin_unlock_bh(&p->fcoe_rx_list.lock); 755a703e490SVasu Dev } 756a703e490SVasu Dev #else 757a703e490SVasu Dev /* 758a703e490SVasu Dev * This a non-SMP scenario where the singluar Rx thread is 759a703e490SVasu Dev * being removed. Free all skbs and stop the thread. 760a703e490SVasu Dev */ 761a703e490SVasu Dev spin_lock_bh(&p->fcoe_rx_list.lock); 762a703e490SVasu Dev while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL) 763a703e490SVasu Dev kfree_skb(skb); 764a703e490SVasu Dev spin_unlock_bh(&p->fcoe_rx_list.lock); 765a703e490SVasu Dev #endif 766a703e490SVasu Dev 767a703e490SVasu Dev if (thread) 768a703e490SVasu Dev kthread_stop(thread); 769a703e490SVasu Dev 770a703e490SVasu Dev if (crc_eof) 771a703e490SVasu Dev put_page(crc_eof); 772a703e490SVasu Dev } 773a703e490SVasu Dev 774a703e490SVasu Dev /** 775a703e490SVasu Dev * fcoe_cpu_callback() - fcoe cpu hotplug event callback 776a703e490SVasu Dev * @nfb: callback data block 777a703e490SVasu Dev * @action: event triggering the callback 778a703e490SVasu Dev * @hcpu: index for the cpu of this event 779a703e490SVasu Dev * 780a703e490SVasu Dev * This creates or destroys per cpu data for fcoe 781a703e490SVasu Dev * 782a703e490SVasu Dev * Returns NOTIFY_OK always. 783a703e490SVasu Dev */ 784a703e490SVasu Dev static int fcoe_cpu_callback(struct notifier_block *nfb, 785a703e490SVasu Dev unsigned long action, void *hcpu) 786a703e490SVasu Dev { 787a703e490SVasu Dev unsigned cpu = (unsigned long)hcpu; 788a703e490SVasu Dev 789a703e490SVasu Dev switch (action) { 790a703e490SVasu Dev case CPU_ONLINE: 791a703e490SVasu Dev case CPU_ONLINE_FROZEN: 792a703e490SVasu Dev FC_DBG("CPU %x online: Create Rx thread\n", cpu); 793a703e490SVasu Dev fcoe_percpu_thread_create(cpu); 794a703e490SVasu Dev break; 795a703e490SVasu Dev case CPU_DEAD: 796a703e490SVasu Dev case CPU_DEAD_FROZEN: 797a703e490SVasu Dev FC_DBG("CPU %x offline: Remove Rx thread\n", cpu); 798a703e490SVasu Dev fcoe_percpu_thread_destroy(cpu); 799a703e490SVasu Dev break; 800a703e490SVasu Dev default: 801a703e490SVasu Dev break; 802a703e490SVasu Dev } 803a703e490SVasu Dev return NOTIFY_OK; 804a703e490SVasu Dev } 805a703e490SVasu Dev 806a703e490SVasu Dev static struct notifier_block fcoe_cpu_notifier = { 807a703e490SVasu Dev .notifier_call = fcoe_cpu_callback, 808a703e490SVasu Dev }; 809a703e490SVasu Dev 810a703e490SVasu Dev /** 811a703e490SVasu Dev * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ 812a703e490SVasu Dev * @skb: the receive skb 813a703e490SVasu Dev * @dev: associated net device 814a703e490SVasu Dev * @ptype: context 815a703e490SVasu Dev * @odldev: last device 816a703e490SVasu Dev * 817a703e490SVasu Dev * this function will receive the packet and build fc frame and pass it up 818a703e490SVasu Dev * 819a703e490SVasu Dev * Returns: 0 for success 820a703e490SVasu Dev */ 821a703e490SVasu Dev int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, 822a703e490SVasu Dev struct packet_type *ptype, struct net_device *olddev) 823a703e490SVasu Dev { 824a703e490SVasu Dev struct fc_lport *lp; 825a703e490SVasu Dev struct fcoe_rcv_info *fr; 826a703e490SVasu Dev struct fcoe_softc *fc; 827a703e490SVasu Dev struct fc_frame_header *fh; 828a703e490SVasu Dev struct fcoe_percpu_s *fps; 829a703e490SVasu Dev unsigned short oxid; 830a703e490SVasu Dev unsigned int cpu = 0; 831a703e490SVasu Dev 832a703e490SVasu Dev fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type); 83397c8389dSJoe Eykholt lp = fc->ctlr.lp; 834a703e490SVasu Dev if (unlikely(lp == NULL)) { 835a703e490SVasu Dev FC_DBG("cannot find hba structure"); 836a703e490SVasu Dev goto err2; 837a703e490SVasu Dev } 83897c8389dSJoe Eykholt if (!lp->link_up) 83997c8389dSJoe Eykholt goto err2; 840a703e490SVasu Dev 841a703e490SVasu Dev if (unlikely(debug_fcoe)) { 842a703e490SVasu Dev FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p tail:%p " 843a703e490SVasu Dev "end:%p sum:%d dev:%s", skb->len, skb->data_len, 844a703e490SVasu Dev skb->head, skb->data, skb_tail_pointer(skb), 845a703e490SVasu Dev skb_end_pointer(skb), skb->csum, 846a703e490SVasu Dev skb->dev ? skb->dev->name : "<NULL>"); 847a703e490SVasu Dev 848a703e490SVasu Dev } 849a703e490SVasu Dev 850a703e490SVasu Dev /* check for FCOE packet type */ 851a703e490SVasu Dev if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) { 852a703e490SVasu Dev FC_DBG("wrong FC type frame"); 853a703e490SVasu Dev goto err; 854a703e490SVasu Dev } 855a703e490SVasu Dev 856a703e490SVasu Dev /* 857a703e490SVasu Dev * Check for minimum frame length, and make sure required FCoE 858a703e490SVasu Dev * and FC headers are pulled into the linear data area. 859a703e490SVasu Dev */ 860a703e490SVasu Dev if (unlikely((skb->len < FCOE_MIN_FRAME) || 861a703e490SVasu Dev !pskb_may_pull(skb, FCOE_HEADER_LEN))) 862a703e490SVasu Dev goto err; 863a703e490SVasu Dev 864a703e490SVasu Dev skb_set_transport_header(skb, sizeof(struct fcoe_hdr)); 865a703e490SVasu Dev fh = (struct fc_frame_header *) skb_transport_header(skb); 866a703e490SVasu Dev 867a703e490SVasu Dev oxid = ntohs(fh->fh_ox_id); 868a703e490SVasu Dev 869a703e490SVasu Dev fr = fcoe_dev_from_skb(skb); 870a703e490SVasu Dev fr->fr_dev = lp; 871a703e490SVasu Dev fr->ptype = ptype; 872a703e490SVasu Dev 873a703e490SVasu Dev #ifdef CONFIG_SMP 874a703e490SVasu Dev /* 875a703e490SVasu Dev * The incoming frame exchange id(oxid) is ANDed with num of online 876a703e490SVasu Dev * cpu bits to get cpu and then this cpu is used for selecting 877a703e490SVasu Dev * a per cpu kernel thread from fcoe_percpu. 878a703e490SVasu Dev */ 879a703e490SVasu Dev cpu = oxid & (num_online_cpus() - 1); 880a703e490SVasu Dev #endif 881a703e490SVasu Dev 882a703e490SVasu Dev fps = &per_cpu(fcoe_percpu, cpu); 883a703e490SVasu Dev spin_lock_bh(&fps->fcoe_rx_list.lock); 884a703e490SVasu Dev if (unlikely(!fps->thread)) { 885a703e490SVasu Dev /* 886a703e490SVasu Dev * The targeted CPU is not ready, let's target 887a703e490SVasu Dev * the first CPU now. For non-SMP systems this 888a703e490SVasu Dev * will check the same CPU twice. 889a703e490SVasu Dev */ 890a703e490SVasu Dev FC_DBG("CPU is online, but no receive thread ready " 891a703e490SVasu Dev "for incoming skb- using first online CPU.\n"); 892a703e490SVasu Dev 893a703e490SVasu Dev spin_unlock_bh(&fps->fcoe_rx_list.lock); 894a703e490SVasu Dev cpu = first_cpu(cpu_online_map); 895a703e490SVasu Dev fps = &per_cpu(fcoe_percpu, cpu); 896a703e490SVasu Dev spin_lock_bh(&fps->fcoe_rx_list.lock); 897a703e490SVasu Dev if (!fps->thread) { 898a703e490SVasu Dev spin_unlock_bh(&fps->fcoe_rx_list.lock); 899a703e490SVasu Dev goto err; 900a703e490SVasu Dev } 901a703e490SVasu Dev } 902a703e490SVasu Dev 903a703e490SVasu Dev /* 904a703e490SVasu Dev * We now have a valid CPU that we're targeting for 905a703e490SVasu Dev * this skb. We also have this receive thread locked, 906a703e490SVasu Dev * so we're free to queue skbs into it's queue. 907a703e490SVasu Dev */ 908a703e490SVasu Dev __skb_queue_tail(&fps->fcoe_rx_list, skb); 909a703e490SVasu Dev if (fps->fcoe_rx_list.qlen == 1) 910a703e490SVasu Dev wake_up_process(fps->thread); 911a703e490SVasu Dev 912a703e490SVasu Dev spin_unlock_bh(&fps->fcoe_rx_list.lock); 913a703e490SVasu Dev 914a703e490SVasu Dev return 0; 915a703e490SVasu Dev err: 916a703e490SVasu Dev fc_lport_get_stats(lp)->ErrorFrames++; 917a703e490SVasu Dev 918a703e490SVasu Dev err2: 919a703e490SVasu Dev kfree_skb(skb); 920a703e490SVasu Dev return -1; 921a703e490SVasu Dev } 922a703e490SVasu Dev EXPORT_SYMBOL_GPL(fcoe_rcv); 923a703e490SVasu Dev 924a703e490SVasu Dev /** 925a703e490SVasu Dev * fcoe_start_io() - pass to netdev to start xmit for fcoe 926a703e490SVasu Dev * @skb: the skb to be xmitted 927a703e490SVasu Dev * 928a703e490SVasu Dev * Returns: 0 for success 929a703e490SVasu Dev */ 930a703e490SVasu Dev static inline int fcoe_start_io(struct sk_buff *skb) 931a703e490SVasu Dev { 932a703e490SVasu Dev int rc; 933a703e490SVasu Dev 934a703e490SVasu Dev skb_get(skb); 935a703e490SVasu Dev rc = dev_queue_xmit(skb); 936a703e490SVasu Dev if (rc != 0) 937a703e490SVasu Dev return rc; 938a703e490SVasu Dev kfree_skb(skb); 939a703e490SVasu Dev return 0; 940a703e490SVasu Dev } 941a703e490SVasu Dev 942a703e490SVasu Dev /** 943a703e490SVasu Dev * fcoe_get_paged_crc_eof() - in case we need alloc a page for crc_eof 944a703e490SVasu Dev * @skb: the skb to be xmitted 945a703e490SVasu Dev * @tlen: total len 946a703e490SVasu Dev * 947a703e490SVasu Dev * Returns: 0 for success 948a703e490SVasu Dev */ 949a703e490SVasu Dev static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) 950a703e490SVasu Dev { 951a703e490SVasu Dev struct fcoe_percpu_s *fps; 952a703e490SVasu Dev struct page *page; 953a703e490SVasu Dev 954a703e490SVasu Dev fps = &get_cpu_var(fcoe_percpu); 955a703e490SVasu Dev page = fps->crc_eof_page; 956a703e490SVasu Dev if (!page) { 957a703e490SVasu Dev page = alloc_page(GFP_ATOMIC); 958a703e490SVasu Dev if (!page) { 959a703e490SVasu Dev put_cpu_var(fcoe_percpu); 960a703e490SVasu Dev return -ENOMEM; 961a703e490SVasu Dev } 962a703e490SVasu Dev fps->crc_eof_page = page; 963a703e490SVasu Dev fps->crc_eof_offset = 0; 964a703e490SVasu Dev } 965a703e490SVasu Dev 966a703e490SVasu Dev get_page(page); 967a703e490SVasu Dev skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, 968a703e490SVasu Dev fps->crc_eof_offset, tlen); 969a703e490SVasu Dev skb->len += tlen; 970a703e490SVasu Dev skb->data_len += tlen; 971a703e490SVasu Dev skb->truesize += tlen; 972a703e490SVasu Dev fps->crc_eof_offset += sizeof(struct fcoe_crc_eof); 973a703e490SVasu Dev 974a703e490SVasu Dev if (fps->crc_eof_offset >= PAGE_SIZE) { 975a703e490SVasu Dev fps->crc_eof_page = NULL; 976a703e490SVasu Dev fps->crc_eof_offset = 0; 977a703e490SVasu Dev put_page(page); 978a703e490SVasu Dev } 979a703e490SVasu Dev put_cpu_var(fcoe_percpu); 980a703e490SVasu Dev return 0; 981a703e490SVasu Dev } 982a703e490SVasu Dev 983a703e490SVasu Dev /** 984a703e490SVasu Dev * fcoe_fc_crc() - calculates FC CRC in this fcoe skb 985a703e490SVasu Dev * @fp: the fc_frame containg data to be checksummed 986a703e490SVasu Dev * 987a703e490SVasu Dev * This uses crc32() to calculate the crc for fc frame 988a703e490SVasu Dev * Return : 32 bit crc 989a703e490SVasu Dev */ 990a703e490SVasu Dev u32 fcoe_fc_crc(struct fc_frame *fp) 991a703e490SVasu Dev { 992a703e490SVasu Dev struct sk_buff *skb = fp_skb(fp); 993a703e490SVasu Dev struct skb_frag_struct *frag; 994a703e490SVasu Dev unsigned char *data; 995a703e490SVasu Dev unsigned long off, len, clen; 996a703e490SVasu Dev u32 crc; 997a703e490SVasu Dev unsigned i; 998a703e490SVasu Dev 999a703e490SVasu Dev crc = crc32(~0, skb->data, skb_headlen(skb)); 1000a703e490SVasu Dev 1001a703e490SVasu Dev for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 1002a703e490SVasu Dev frag = &skb_shinfo(skb)->frags[i]; 1003a703e490SVasu Dev off = frag->page_offset; 1004a703e490SVasu Dev len = frag->size; 1005a703e490SVasu Dev while (len > 0) { 1006a703e490SVasu Dev clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK)); 1007a703e490SVasu Dev data = kmap_atomic(frag->page + (off >> PAGE_SHIFT), 1008a703e490SVasu Dev KM_SKB_DATA_SOFTIRQ); 1009a703e490SVasu Dev crc = crc32(crc, data + (off & ~PAGE_MASK), clen); 1010a703e490SVasu Dev kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ); 1011a703e490SVasu Dev off += clen; 1012a703e490SVasu Dev len -= clen; 1013a703e490SVasu Dev } 1014a703e490SVasu Dev } 1015a703e490SVasu Dev return crc; 1016a703e490SVasu Dev } 1017a703e490SVasu Dev 1018a703e490SVasu Dev /** 1019a703e490SVasu Dev * fcoe_xmit() - FCoE frame transmit function 1020a703e490SVasu Dev * @lp: the associated local port 1021a703e490SVasu Dev * @fp: the fc_frame to be transmitted 1022a703e490SVasu Dev * 1023a703e490SVasu Dev * Return : 0 for success 1024a703e490SVasu Dev */ 1025a703e490SVasu Dev int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) 1026a703e490SVasu Dev { 1027a703e490SVasu Dev int wlen, rc = 0; 1028a703e490SVasu Dev u32 crc; 1029a703e490SVasu Dev struct ethhdr *eh; 1030a703e490SVasu Dev struct fcoe_crc_eof *cp; 1031a703e490SVasu Dev struct sk_buff *skb; 1032a703e490SVasu Dev struct fcoe_dev_stats *stats; 1033a703e490SVasu Dev struct fc_frame_header *fh; 1034a703e490SVasu Dev unsigned int hlen; /* header length implies the version */ 1035a703e490SVasu Dev unsigned int tlen; /* trailer length */ 1036a703e490SVasu Dev unsigned int elen; /* eth header, may include vlan */ 1037a703e490SVasu Dev struct fcoe_softc *fc; 1038a703e490SVasu Dev u8 sof, eof; 1039a703e490SVasu Dev struct fcoe_hdr *hp; 1040a703e490SVasu Dev 1041a703e490SVasu Dev WARN_ON((fr_len(fp) % sizeof(u32)) != 0); 1042a703e490SVasu Dev 1043a703e490SVasu Dev fc = lport_priv(lp); 1044a703e490SVasu Dev fh = fc_frame_header_get(fp); 104597c8389dSJoe Eykholt skb = fp_skb(fp); 104697c8389dSJoe Eykholt wlen = skb->len / FCOE_WORD_TO_BYTE; 104797c8389dSJoe Eykholt 104897c8389dSJoe Eykholt if (!lp->link_up) { 104997c8389dSJoe Eykholt kfree(skb); 105097c8389dSJoe Eykholt return 0; 1051a703e490SVasu Dev } 1052a703e490SVasu Dev 105397c8389dSJoe Eykholt if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && 105497c8389dSJoe Eykholt fcoe_ctlr_els_send(&fc->ctlr, skb)) 105597c8389dSJoe Eykholt return 0; 105697c8389dSJoe Eykholt 1057a703e490SVasu Dev sof = fr_sof(fp); 1058a703e490SVasu Dev eof = fr_eof(fp); 1059a703e490SVasu Dev 1060a703e490SVasu Dev elen = (fc->real_dev->priv_flags & IFF_802_1Q_VLAN) ? 1061a703e490SVasu Dev sizeof(struct vlan_ethhdr) : sizeof(struct ethhdr); 1062a703e490SVasu Dev hlen = sizeof(struct fcoe_hdr); 1063a703e490SVasu Dev tlen = sizeof(struct fcoe_crc_eof); 1064a703e490SVasu Dev wlen = (skb->len - tlen + sizeof(crc)) / FCOE_WORD_TO_BYTE; 1065a703e490SVasu Dev 1066a703e490SVasu Dev /* crc offload */ 1067a703e490SVasu Dev if (likely(lp->crc_offload)) { 1068a703e490SVasu Dev skb->ip_summed = CHECKSUM_PARTIAL; 1069a703e490SVasu Dev skb->csum_start = skb_headroom(skb); 1070a703e490SVasu Dev skb->csum_offset = skb->len; 1071a703e490SVasu Dev crc = 0; 1072a703e490SVasu Dev } else { 1073a703e490SVasu Dev skb->ip_summed = CHECKSUM_NONE; 1074a703e490SVasu Dev crc = fcoe_fc_crc(fp); 1075a703e490SVasu Dev } 1076a703e490SVasu Dev 1077a703e490SVasu Dev /* copy fc crc and eof to the skb buff */ 1078a703e490SVasu Dev if (skb_is_nonlinear(skb)) { 1079a703e490SVasu Dev skb_frag_t *frag; 1080a703e490SVasu Dev if (fcoe_get_paged_crc_eof(skb, tlen)) { 1081a703e490SVasu Dev kfree_skb(skb); 1082a703e490SVasu Dev return -ENOMEM; 1083a703e490SVasu Dev } 1084a703e490SVasu Dev frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; 1085a703e490SVasu Dev cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ) 1086a703e490SVasu Dev + frag->page_offset; 1087a703e490SVasu Dev } else { 1088a703e490SVasu Dev cp = (struct fcoe_crc_eof *)skb_put(skb, tlen); 1089a703e490SVasu Dev } 1090a703e490SVasu Dev 1091a703e490SVasu Dev memset(cp, 0, sizeof(*cp)); 1092a703e490SVasu Dev cp->fcoe_eof = eof; 1093a703e490SVasu Dev cp->fcoe_crc32 = cpu_to_le32(~crc); 1094a703e490SVasu Dev 1095a703e490SVasu Dev if (skb_is_nonlinear(skb)) { 1096a703e490SVasu Dev kunmap_atomic(cp, KM_SKB_DATA_SOFTIRQ); 1097a703e490SVasu Dev cp = NULL; 1098a703e490SVasu Dev } 1099a703e490SVasu Dev 1100a703e490SVasu Dev /* adjust skb netowrk/transport offsets to match mac/fcoe/fc */ 1101a703e490SVasu Dev skb_push(skb, elen + hlen); 1102a703e490SVasu Dev skb_reset_mac_header(skb); 1103a703e490SVasu Dev skb_reset_network_header(skb); 1104a703e490SVasu Dev skb->mac_len = elen; 1105a703e490SVasu Dev skb->protocol = htons(ETH_P_FCOE); 1106a703e490SVasu Dev skb->dev = fc->real_dev; 1107a703e490SVasu Dev 1108a703e490SVasu Dev /* fill up mac and fcoe headers */ 1109a703e490SVasu Dev eh = eth_hdr(skb); 1110a703e490SVasu Dev eh->h_proto = htons(ETH_P_FCOE); 111197c8389dSJoe Eykholt if (fc->ctlr.map_dest) 1112a703e490SVasu Dev fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id); 1113a703e490SVasu Dev else 1114a703e490SVasu Dev /* insert GW address */ 111597c8389dSJoe Eykholt memcpy(eh->h_dest, fc->ctlr.dest_addr, ETH_ALEN); 1116a703e490SVasu Dev 111797c8389dSJoe Eykholt if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN)) 111897c8389dSJoe Eykholt memcpy(eh->h_source, fc->ctlr.ctl_src_addr, ETH_ALEN); 1119a703e490SVasu Dev else 112097c8389dSJoe Eykholt memcpy(eh->h_source, fc->ctlr.data_src_addr, ETH_ALEN); 1121a703e490SVasu Dev 1122a703e490SVasu Dev hp = (struct fcoe_hdr *)(eh + 1); 1123a703e490SVasu Dev memset(hp, 0, sizeof(*hp)); 1124a703e490SVasu Dev if (FC_FCOE_VER) 1125a703e490SVasu Dev FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER); 1126a703e490SVasu Dev hp->fcoe_sof = sof; 1127a703e490SVasu Dev 1128a703e490SVasu Dev #ifdef NETIF_F_FSO 1129a703e490SVasu Dev /* fcoe lso, mss is in max_payload which is non-zero for FCP data */ 1130a703e490SVasu Dev if (lp->seq_offload && fr_max_payload(fp)) { 1131a703e490SVasu Dev skb_shinfo(skb)->gso_type = SKB_GSO_FCOE; 1132a703e490SVasu Dev skb_shinfo(skb)->gso_size = fr_max_payload(fp); 1133a703e490SVasu Dev } else { 1134a703e490SVasu Dev skb_shinfo(skb)->gso_type = 0; 1135a703e490SVasu Dev skb_shinfo(skb)->gso_size = 0; 1136a703e490SVasu Dev } 1137a703e490SVasu Dev #endif 1138a703e490SVasu Dev /* update tx stats: regardless if LLD fails */ 1139a703e490SVasu Dev stats = fc_lport_get_stats(lp); 1140a703e490SVasu Dev stats->TxFrames++; 1141a703e490SVasu Dev stats->TxWords += wlen; 1142a703e490SVasu Dev 1143a703e490SVasu Dev /* send down to lld */ 1144a703e490SVasu Dev fr_dev(fp) = lp; 1145a703e490SVasu Dev if (fc->fcoe_pending_queue.qlen) 1146a703e490SVasu Dev rc = fcoe_check_wait_queue(lp); 1147a703e490SVasu Dev 1148a703e490SVasu Dev if (rc == 0) 1149a703e490SVasu Dev rc = fcoe_start_io(skb); 1150a703e490SVasu Dev 1151a703e490SVasu Dev if (rc) { 1152a703e490SVasu Dev spin_lock_bh(&fc->fcoe_pending_queue.lock); 1153a703e490SVasu Dev __skb_queue_tail(&fc->fcoe_pending_queue, skb); 1154a703e490SVasu Dev spin_unlock_bh(&fc->fcoe_pending_queue.lock); 1155a703e490SVasu Dev if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) 1156a703e490SVasu Dev lp->qfull = 1; 1157a703e490SVasu Dev } 1158a703e490SVasu Dev 1159a703e490SVasu Dev return 0; 1160a703e490SVasu Dev } 1161a703e490SVasu Dev EXPORT_SYMBOL_GPL(fcoe_xmit); 1162a703e490SVasu Dev 1163a703e490SVasu Dev /** 1164a703e490SVasu Dev * fcoe_percpu_receive_thread() - recv thread per cpu 1165a703e490SVasu Dev * @arg: ptr to the fcoe per cpu struct 1166a703e490SVasu Dev * 1167a703e490SVasu Dev * Return: 0 for success 1168a703e490SVasu Dev */ 1169a703e490SVasu Dev int fcoe_percpu_receive_thread(void *arg) 1170a703e490SVasu Dev { 1171a703e490SVasu Dev struct fcoe_percpu_s *p = arg; 1172a703e490SVasu Dev u32 fr_len; 1173a703e490SVasu Dev struct fc_lport *lp; 1174a703e490SVasu Dev struct fcoe_rcv_info *fr; 1175a703e490SVasu Dev struct fcoe_dev_stats *stats; 1176a703e490SVasu Dev struct fc_frame_header *fh; 1177a703e490SVasu Dev struct sk_buff *skb; 1178a703e490SVasu Dev struct fcoe_crc_eof crc_eof; 1179a703e490SVasu Dev struct fc_frame *fp; 1180a703e490SVasu Dev u8 *mac = NULL; 1181a703e490SVasu Dev struct fcoe_softc *fc; 1182a703e490SVasu Dev struct fcoe_hdr *hp; 1183a703e490SVasu Dev 1184a703e490SVasu Dev set_user_nice(current, -20); 1185a703e490SVasu Dev 1186a703e490SVasu Dev while (!kthread_should_stop()) { 1187a703e490SVasu Dev 1188a703e490SVasu Dev spin_lock_bh(&p->fcoe_rx_list.lock); 1189a703e490SVasu Dev while ((skb = __skb_dequeue(&p->fcoe_rx_list)) == NULL) { 1190a703e490SVasu Dev set_current_state(TASK_INTERRUPTIBLE); 1191a703e490SVasu Dev spin_unlock_bh(&p->fcoe_rx_list.lock); 1192a703e490SVasu Dev schedule(); 1193a703e490SVasu Dev set_current_state(TASK_RUNNING); 1194a703e490SVasu Dev if (kthread_should_stop()) 1195a703e490SVasu Dev return 0; 1196a703e490SVasu Dev spin_lock_bh(&p->fcoe_rx_list.lock); 1197a703e490SVasu Dev } 1198a703e490SVasu Dev spin_unlock_bh(&p->fcoe_rx_list.lock); 1199a703e490SVasu Dev fr = fcoe_dev_from_skb(skb); 1200a703e490SVasu Dev lp = fr->fr_dev; 1201a703e490SVasu Dev if (unlikely(lp == NULL)) { 1202a703e490SVasu Dev FC_DBG("invalid HBA Structure"); 1203a703e490SVasu Dev kfree_skb(skb); 1204a703e490SVasu Dev continue; 1205a703e490SVasu Dev } 1206a703e490SVasu Dev 1207a703e490SVasu Dev if (unlikely(debug_fcoe)) { 1208a703e490SVasu Dev FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p " 1209a703e490SVasu Dev "tail:%p end:%p sum:%d dev:%s", 1210a703e490SVasu Dev skb->len, skb->data_len, 1211a703e490SVasu Dev skb->head, skb->data, skb_tail_pointer(skb), 1212a703e490SVasu Dev skb_end_pointer(skb), skb->csum, 1213a703e490SVasu Dev skb->dev ? skb->dev->name : "<NULL>"); 1214a703e490SVasu Dev } 1215a703e490SVasu Dev 1216a703e490SVasu Dev /* 1217a703e490SVasu Dev * Save source MAC address before discarding header. 1218a703e490SVasu Dev */ 1219a703e490SVasu Dev fc = lport_priv(lp); 1220a703e490SVasu Dev if (skb_is_nonlinear(skb)) 1221a703e490SVasu Dev skb_linearize(skb); /* not ideal */ 122297c8389dSJoe Eykholt mac = eth_hdr(skb)->h_source; 1223a703e490SVasu Dev 1224a703e490SVasu Dev /* 1225a703e490SVasu Dev * Frame length checks and setting up the header pointers 1226a703e490SVasu Dev * was done in fcoe_rcv already. 1227a703e490SVasu Dev */ 1228a703e490SVasu Dev hp = (struct fcoe_hdr *) skb_network_header(skb); 1229a703e490SVasu Dev fh = (struct fc_frame_header *) skb_transport_header(skb); 1230a703e490SVasu Dev 1231a703e490SVasu Dev stats = fc_lport_get_stats(lp); 1232a703e490SVasu Dev if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) { 1233a703e490SVasu Dev if (stats->ErrorFrames < 5) 1234a703e490SVasu Dev printk(KERN_WARNING "FCoE version " 1235a703e490SVasu Dev "mismatch: The frame has " 1236a703e490SVasu Dev "version %x, but the " 1237a703e490SVasu Dev "initiator supports version " 1238a703e490SVasu Dev "%x\n", FC_FCOE_DECAPS_VER(hp), 1239a703e490SVasu Dev FC_FCOE_VER); 1240a703e490SVasu Dev stats->ErrorFrames++; 1241a703e490SVasu Dev kfree_skb(skb); 1242a703e490SVasu Dev continue; 1243a703e490SVasu Dev } 1244a703e490SVasu Dev 1245a703e490SVasu Dev skb_pull(skb, sizeof(struct fcoe_hdr)); 1246a703e490SVasu Dev fr_len = skb->len - sizeof(struct fcoe_crc_eof); 1247a703e490SVasu Dev 1248a703e490SVasu Dev stats->RxFrames++; 1249a703e490SVasu Dev stats->RxWords += fr_len / FCOE_WORD_TO_BYTE; 1250a703e490SVasu Dev 1251a703e490SVasu Dev fp = (struct fc_frame *)skb; 1252a703e490SVasu Dev fc_frame_init(fp); 1253a703e490SVasu Dev fr_dev(fp) = lp; 1254a703e490SVasu Dev fr_sof(fp) = hp->fcoe_sof; 1255a703e490SVasu Dev 1256a703e490SVasu Dev /* Copy out the CRC and EOF trailer for access */ 1257a703e490SVasu Dev if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) { 1258a703e490SVasu Dev kfree_skb(skb); 1259a703e490SVasu Dev continue; 1260a703e490SVasu Dev } 1261a703e490SVasu Dev fr_eof(fp) = crc_eof.fcoe_eof; 1262a703e490SVasu Dev fr_crc(fp) = crc_eof.fcoe_crc32; 1263a703e490SVasu Dev if (pskb_trim(skb, fr_len)) { 1264a703e490SVasu Dev kfree_skb(skb); 1265a703e490SVasu Dev continue; 1266a703e490SVasu Dev } 1267a703e490SVasu Dev 1268a703e490SVasu Dev /* 1269a703e490SVasu Dev * We only check CRC if no offload is available and if it is 1270a703e490SVasu Dev * it's solicited data, in which case, the FCP layer would 1271a703e490SVasu Dev * check it during the copy. 1272a703e490SVasu Dev */ 1273a703e490SVasu Dev if (lp->crc_offload && skb->ip_summed == CHECKSUM_UNNECESSARY) 1274a703e490SVasu Dev fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; 1275a703e490SVasu Dev else 1276a703e490SVasu Dev fr_flags(fp) |= FCPHF_CRC_UNCHECKED; 1277a703e490SVasu Dev 1278a703e490SVasu Dev fh = fc_frame_header_get(fp); 1279a703e490SVasu Dev if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && 1280a703e490SVasu Dev fh->fh_type == FC_TYPE_FCP) { 1281a703e490SVasu Dev fc_exch_recv(lp, lp->emp, fp); 1282a703e490SVasu Dev continue; 1283a703e490SVasu Dev } 1284a703e490SVasu Dev if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) { 1285a703e490SVasu Dev if (le32_to_cpu(fr_crc(fp)) != 1286a703e490SVasu Dev ~crc32(~0, skb->data, fr_len)) { 1287a703e490SVasu Dev if (debug_fcoe || stats->InvalidCRCCount < 5) 1288a703e490SVasu Dev printk(KERN_WARNING "fcoe: dropping " 1289a703e490SVasu Dev "frame with CRC error\n"); 1290a703e490SVasu Dev stats->InvalidCRCCount++; 1291a703e490SVasu Dev stats->ErrorFrames++; 1292a703e490SVasu Dev fc_frame_free(fp); 1293a703e490SVasu Dev continue; 1294a703e490SVasu Dev } 1295a703e490SVasu Dev fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; 1296a703e490SVasu Dev } 129797c8389dSJoe Eykholt if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN) && 129897c8389dSJoe Eykholt fcoe_ctlr_recv_flogi(&fc->ctlr, fp, mac)) { 129997c8389dSJoe Eykholt fc_frame_free(fp); 130097c8389dSJoe Eykholt continue; 130197c8389dSJoe Eykholt } 1302a703e490SVasu Dev fc_exch_recv(lp, lp->emp, fp); 1303a703e490SVasu Dev } 1304a703e490SVasu Dev return 0; 1305a703e490SVasu Dev } 1306a703e490SVasu Dev 1307a703e490SVasu Dev /** 1308a703e490SVasu Dev * fcoe_watchdog() - fcoe timer callback 1309a703e490SVasu Dev * @vp: 1310a703e490SVasu Dev * 1311a703e490SVasu Dev * This checks the pending queue length for fcoe and set lport qfull 1312a703e490SVasu Dev * if the FCOE_MAX_QUEUE_DEPTH is reached. This is done for all fc_lport on the 1313a703e490SVasu Dev * fcoe_hostlist. 1314a703e490SVasu Dev * 1315a703e490SVasu Dev * Returns: 0 for success 1316a703e490SVasu Dev */ 1317a703e490SVasu Dev void fcoe_watchdog(ulong vp) 1318a703e490SVasu Dev { 1319a703e490SVasu Dev struct fcoe_softc *fc; 1320a703e490SVasu Dev 1321a703e490SVasu Dev read_lock(&fcoe_hostlist_lock); 1322a703e490SVasu Dev list_for_each_entry(fc, &fcoe_hostlist, list) { 132397c8389dSJoe Eykholt if (fc->ctlr.lp) 132497c8389dSJoe Eykholt fcoe_check_wait_queue(fc->ctlr.lp); 1325a703e490SVasu Dev } 1326a703e490SVasu Dev read_unlock(&fcoe_hostlist_lock); 1327a703e490SVasu Dev 1328a703e490SVasu Dev fcoe_timer.expires = jiffies + (1 * HZ); 1329a703e490SVasu Dev add_timer(&fcoe_timer); 1330a703e490SVasu Dev } 1331a703e490SVasu Dev 1332a703e490SVasu Dev 1333a703e490SVasu Dev /** 1334a703e490SVasu Dev * fcoe_check_wait_queue() - put the skb into fcoe pending xmit queue 1335a703e490SVasu Dev * @lp: the fc_port for this skb 1336a703e490SVasu Dev * @skb: the associated skb to be xmitted 1337a703e490SVasu Dev * 1338a703e490SVasu Dev * This empties the wait_queue, dequeue the head of the wait_queue queue 1339a703e490SVasu Dev * and calls fcoe_start_io() for each packet, if all skb have been 1340a703e490SVasu Dev * transmitted, return qlen or -1 if a error occurs, then restore 1341a703e490SVasu Dev * wait_queue and try again later. 1342a703e490SVasu Dev * 1343a703e490SVasu Dev * The wait_queue is used when the skb transmit fails. skb will go 1344a703e490SVasu Dev * in the wait_queue which will be emptied by the time function OR 1345a703e490SVasu Dev * by the next skb transmit. 1346a703e490SVasu Dev * 1347a703e490SVasu Dev * Returns: 0 for success 1348a703e490SVasu Dev */ 1349a703e490SVasu Dev static int fcoe_check_wait_queue(struct fc_lport *lp) 1350a703e490SVasu Dev { 1351a703e490SVasu Dev struct fcoe_softc *fc = lport_priv(lp); 1352a703e490SVasu Dev struct sk_buff *skb; 1353a703e490SVasu Dev int rc = -1; 1354a703e490SVasu Dev 1355a703e490SVasu Dev spin_lock_bh(&fc->fcoe_pending_queue.lock); 1356a703e490SVasu Dev if (fc->fcoe_pending_queue_active) 1357a703e490SVasu Dev goto out; 1358a703e490SVasu Dev fc->fcoe_pending_queue_active = 1; 1359a703e490SVasu Dev 1360a703e490SVasu Dev while (fc->fcoe_pending_queue.qlen) { 1361a703e490SVasu Dev /* keep qlen > 0 until fcoe_start_io succeeds */ 1362a703e490SVasu Dev fc->fcoe_pending_queue.qlen++; 1363a703e490SVasu Dev skb = __skb_dequeue(&fc->fcoe_pending_queue); 1364a703e490SVasu Dev 1365a703e490SVasu Dev spin_unlock_bh(&fc->fcoe_pending_queue.lock); 1366a703e490SVasu Dev rc = fcoe_start_io(skb); 1367a703e490SVasu Dev spin_lock_bh(&fc->fcoe_pending_queue.lock); 1368a703e490SVasu Dev 1369a703e490SVasu Dev if (rc) { 1370a703e490SVasu Dev __skb_queue_head(&fc->fcoe_pending_queue, skb); 1371a703e490SVasu Dev /* undo temporary increment above */ 1372a703e490SVasu Dev fc->fcoe_pending_queue.qlen--; 1373a703e490SVasu Dev break; 1374a703e490SVasu Dev } 1375a703e490SVasu Dev /* undo temporary increment above */ 1376a703e490SVasu Dev fc->fcoe_pending_queue.qlen--; 1377a703e490SVasu Dev } 1378a703e490SVasu Dev 1379a703e490SVasu Dev if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) 1380a703e490SVasu Dev lp->qfull = 0; 1381a703e490SVasu Dev fc->fcoe_pending_queue_active = 0; 1382a703e490SVasu Dev rc = fc->fcoe_pending_queue.qlen; 1383a703e490SVasu Dev out: 1384a703e490SVasu Dev spin_unlock_bh(&fc->fcoe_pending_queue.lock); 1385a703e490SVasu Dev return rc; 1386a703e490SVasu Dev } 1387a703e490SVasu Dev 1388a703e490SVasu Dev /** 1389a703e490SVasu Dev * fcoe_dev_setup() - setup link change notification interface 1390a703e490SVasu Dev */ 1391a703e490SVasu Dev static void fcoe_dev_setup() 1392a703e490SVasu Dev { 1393a703e490SVasu Dev /* 1394a703e490SVasu Dev * here setup a interface specific wd time to 1395a703e490SVasu Dev * monitor the link state 1396a703e490SVasu Dev */ 1397a703e490SVasu Dev register_netdevice_notifier(&fcoe_notifier); 1398a703e490SVasu Dev } 1399a703e490SVasu Dev 1400a703e490SVasu Dev /** 1401a703e490SVasu Dev * fcoe_dev_setup() - cleanup link change notification interface 1402a703e490SVasu Dev */ 1403a703e490SVasu Dev static void fcoe_dev_cleanup(void) 1404a703e490SVasu Dev { 1405a703e490SVasu Dev unregister_netdevice_notifier(&fcoe_notifier); 1406a703e490SVasu Dev } 1407a703e490SVasu Dev 1408a703e490SVasu Dev /** 1409a703e490SVasu Dev * fcoe_device_notification() - netdev event notification callback 1410a703e490SVasu Dev * @notifier: context of the notification 1411a703e490SVasu Dev * @event: type of event 1412a703e490SVasu Dev * @ptr: fixed array for output parsed ifname 1413a703e490SVasu Dev * 1414a703e490SVasu Dev * This function is called by the ethernet driver in case of link change event 1415a703e490SVasu Dev * 1416a703e490SVasu Dev * Returns: 0 for success 1417a703e490SVasu Dev */ 1418a703e490SVasu Dev static int fcoe_device_notification(struct notifier_block *notifier, 1419a703e490SVasu Dev ulong event, void *ptr) 1420a703e490SVasu Dev { 1421a703e490SVasu Dev struct fc_lport *lp = NULL; 1422a703e490SVasu Dev struct net_device *real_dev = ptr; 1423a703e490SVasu Dev struct fcoe_softc *fc; 1424a703e490SVasu Dev struct fcoe_dev_stats *stats; 142597c8389dSJoe Eykholt u32 link_possible = 1; 1426a703e490SVasu Dev u32 mfs; 1427a703e490SVasu Dev int rc = NOTIFY_OK; 1428a703e490SVasu Dev 1429a703e490SVasu Dev read_lock(&fcoe_hostlist_lock); 1430a703e490SVasu Dev list_for_each_entry(fc, &fcoe_hostlist, list) { 1431a703e490SVasu Dev if (fc->real_dev == real_dev) { 143297c8389dSJoe Eykholt lp = fc->ctlr.lp; 1433a703e490SVasu Dev break; 1434a703e490SVasu Dev } 1435a703e490SVasu Dev } 1436a703e490SVasu Dev read_unlock(&fcoe_hostlist_lock); 1437a703e490SVasu Dev if (lp == NULL) { 1438a703e490SVasu Dev rc = NOTIFY_DONE; 1439a703e490SVasu Dev goto out; 1440a703e490SVasu Dev } 1441a703e490SVasu Dev 1442a703e490SVasu Dev switch (event) { 1443a703e490SVasu Dev case NETDEV_DOWN: 1444a703e490SVasu Dev case NETDEV_GOING_DOWN: 144597c8389dSJoe Eykholt link_possible = 0; 1446a703e490SVasu Dev break; 1447a703e490SVasu Dev case NETDEV_UP: 1448a703e490SVasu Dev case NETDEV_CHANGE: 1449a703e490SVasu Dev break; 1450a703e490SVasu Dev case NETDEV_CHANGEMTU: 1451a703e490SVasu Dev mfs = fc->real_dev->mtu - 1452a703e490SVasu Dev (sizeof(struct fcoe_hdr) + 1453a703e490SVasu Dev sizeof(struct fcoe_crc_eof)); 1454a703e490SVasu Dev if (mfs >= FC_MIN_MAX_FRAME) 1455a703e490SVasu Dev fc_set_mfs(lp, mfs); 1456a703e490SVasu Dev break; 1457a703e490SVasu Dev case NETDEV_REGISTER: 1458a703e490SVasu Dev break; 1459a703e490SVasu Dev default: 146097c8389dSJoe Eykholt FC_DBG("Unknown event %ld from netdev netlink\n", event); 1461a703e490SVasu Dev } 146297c8389dSJoe Eykholt if (link_possible && !fcoe_link_ok(lp)) 146397c8389dSJoe Eykholt fcoe_ctlr_link_up(&fc->ctlr); 146497c8389dSJoe Eykholt else if (fcoe_ctlr_link_down(&fc->ctlr)) { 1465a703e490SVasu Dev stats = fc_lport_get_stats(lp); 1466a703e490SVasu Dev stats->LinkFailureCount++; 1467a703e490SVasu Dev fcoe_clean_pending_queue(lp); 1468a703e490SVasu Dev } 1469a703e490SVasu Dev out: 1470a703e490SVasu Dev return rc; 1471a703e490SVasu Dev } 1472a703e490SVasu Dev 1473a703e490SVasu Dev /** 1474a703e490SVasu Dev * fcoe_if_to_netdev() - parse a name buffer to get netdev 1475a703e490SVasu Dev * @ifname: fixed array for output parsed ifname 1476a703e490SVasu Dev * @buffer: incoming buffer to be copied 1477a703e490SVasu Dev * 1478a703e490SVasu Dev * Returns: NULL or ptr to netdeive 1479a703e490SVasu Dev */ 1480a703e490SVasu Dev static struct net_device *fcoe_if_to_netdev(const char *buffer) 1481a703e490SVasu Dev { 1482a703e490SVasu Dev char *cp; 1483a703e490SVasu Dev char ifname[IFNAMSIZ + 2]; 1484a703e490SVasu Dev 1485a703e490SVasu Dev if (buffer) { 1486a703e490SVasu Dev strlcpy(ifname, buffer, IFNAMSIZ); 1487a703e490SVasu Dev cp = ifname + strlen(ifname); 1488a703e490SVasu Dev while (--cp >= ifname && *cp == '\n') 1489a703e490SVasu Dev *cp = '\0'; 1490a703e490SVasu Dev return dev_get_by_name(&init_net, ifname); 1491a703e490SVasu Dev } 1492a703e490SVasu Dev return NULL; 1493a703e490SVasu Dev } 1494a703e490SVasu Dev 1495a703e490SVasu Dev /** 1496a703e490SVasu Dev * fcoe_netdev_to_module_owner() - finds out the nic drive moddule of the netdev 1497a703e490SVasu Dev * @netdev: the target netdev 1498a703e490SVasu Dev * 1499a703e490SVasu Dev * Returns: ptr to the struct module, NULL for failure 1500a703e490SVasu Dev */ 1501a703e490SVasu Dev static struct module * 1502a703e490SVasu Dev fcoe_netdev_to_module_owner(const struct net_device *netdev) 1503a703e490SVasu Dev { 1504a703e490SVasu Dev struct device *dev; 1505a703e490SVasu Dev 1506a703e490SVasu Dev if (!netdev) 1507a703e490SVasu Dev return NULL; 1508a703e490SVasu Dev 1509a703e490SVasu Dev dev = netdev->dev.parent; 1510a703e490SVasu Dev if (!dev) 1511a703e490SVasu Dev return NULL; 1512a703e490SVasu Dev 1513a703e490SVasu Dev if (!dev->driver) 1514a703e490SVasu Dev return NULL; 1515a703e490SVasu Dev 1516a703e490SVasu Dev return dev->driver->owner; 1517a703e490SVasu Dev } 1518a703e490SVasu Dev 1519a703e490SVasu Dev /** 1520a703e490SVasu Dev * fcoe_ethdrv_get() - Hold the Ethernet driver 1521a703e490SVasu Dev * @netdev: the target netdev 1522a703e490SVasu Dev * 1523a703e490SVasu Dev * Holds the Ethernet driver module by try_module_get() for 1524a703e490SVasu Dev * the corresponding netdev. 1525a703e490SVasu Dev * 1526a703e490SVasu Dev * Returns: 0 for succsss 1527a703e490SVasu Dev */ 1528a703e490SVasu Dev static int fcoe_ethdrv_get(const struct net_device *netdev) 1529a703e490SVasu Dev { 1530a703e490SVasu Dev struct module *owner; 1531a703e490SVasu Dev 1532a703e490SVasu Dev owner = fcoe_netdev_to_module_owner(netdev); 1533a703e490SVasu Dev if (owner) { 1534a703e490SVasu Dev printk(KERN_DEBUG "fcoe:hold driver module %s for %s\n", 1535a703e490SVasu Dev module_name(owner), netdev->name); 1536a703e490SVasu Dev return try_module_get(owner); 1537a703e490SVasu Dev } 1538a703e490SVasu Dev return -ENODEV; 1539a703e490SVasu Dev } 1540a703e490SVasu Dev 1541a703e490SVasu Dev /** 1542a703e490SVasu Dev * fcoe_ethdrv_put() - Release the Ethernet driver 1543a703e490SVasu Dev * @netdev: the target netdev 1544a703e490SVasu Dev * 1545a703e490SVasu Dev * Releases the Ethernet driver module by module_put for 1546a703e490SVasu Dev * the corresponding netdev. 1547a703e490SVasu Dev * 1548a703e490SVasu Dev * Returns: 0 for succsss 1549a703e490SVasu Dev */ 1550a703e490SVasu Dev static int fcoe_ethdrv_put(const struct net_device *netdev) 1551a703e490SVasu Dev { 1552a703e490SVasu Dev struct module *owner; 1553a703e490SVasu Dev 1554a703e490SVasu Dev owner = fcoe_netdev_to_module_owner(netdev); 1555a703e490SVasu Dev if (owner) { 1556a703e490SVasu Dev printk(KERN_DEBUG "fcoe:release driver module %s for %s\n", 1557a703e490SVasu Dev module_name(owner), netdev->name); 1558a703e490SVasu Dev module_put(owner); 1559a703e490SVasu Dev return 0; 1560a703e490SVasu Dev } 1561a703e490SVasu Dev return -ENODEV; 1562a703e490SVasu Dev } 1563a703e490SVasu Dev 1564a703e490SVasu Dev /** 1565a703e490SVasu Dev * fcoe_destroy() - handles the destroy from sysfs 1566a703e490SVasu Dev * @buffer: expcted to be a eth if name 1567a703e490SVasu Dev * @kp: associated kernel param 1568a703e490SVasu Dev * 1569a703e490SVasu Dev * Returns: 0 for success 1570a703e490SVasu Dev */ 1571a703e490SVasu Dev static int fcoe_destroy(const char *buffer, struct kernel_param *kp) 1572a703e490SVasu Dev { 1573a703e490SVasu Dev int rc; 1574a703e490SVasu Dev struct net_device *netdev; 1575a703e490SVasu Dev 1576a703e490SVasu Dev netdev = fcoe_if_to_netdev(buffer); 1577a703e490SVasu Dev if (!netdev) { 1578a703e490SVasu Dev rc = -ENODEV; 1579a703e490SVasu Dev goto out_nodev; 1580a703e490SVasu Dev } 1581a703e490SVasu Dev /* look for existing lport */ 1582a703e490SVasu Dev if (!fcoe_hostlist_lookup(netdev)) { 1583a703e490SVasu Dev rc = -ENODEV; 1584a703e490SVasu Dev goto out_putdev; 1585a703e490SVasu Dev } 1586a703e490SVasu Dev rc = fcoe_if_destroy(netdev); 1587a703e490SVasu Dev if (rc) { 1588a703e490SVasu Dev printk(KERN_ERR "fcoe: fcoe_if_destroy(%s) failed\n", 1589a703e490SVasu Dev netdev->name); 1590a703e490SVasu Dev rc = -EIO; 1591a703e490SVasu Dev goto out_putdev; 1592a703e490SVasu Dev } 1593a703e490SVasu Dev fcoe_ethdrv_put(netdev); 1594a703e490SVasu Dev rc = 0; 1595a703e490SVasu Dev out_putdev: 1596a703e490SVasu Dev dev_put(netdev); 1597a703e490SVasu Dev out_nodev: 1598a703e490SVasu Dev return rc; 1599a703e490SVasu Dev } 1600a703e490SVasu Dev 1601a703e490SVasu Dev /** 1602a703e490SVasu Dev * fcoe_create() - Handles the create call from sysfs 1603a703e490SVasu Dev * @buffer: expcted to be a eth if name 1604a703e490SVasu Dev * @kp: associated kernel param 1605a703e490SVasu Dev * 1606a703e490SVasu Dev * Returns: 0 for success 1607a703e490SVasu Dev */ 1608a703e490SVasu Dev static int fcoe_create(const char *buffer, struct kernel_param *kp) 1609a703e490SVasu Dev { 1610a703e490SVasu Dev int rc; 1611a703e490SVasu Dev struct net_device *netdev; 1612a703e490SVasu Dev 1613a703e490SVasu Dev netdev = fcoe_if_to_netdev(buffer); 1614a703e490SVasu Dev if (!netdev) { 1615a703e490SVasu Dev rc = -ENODEV; 1616a703e490SVasu Dev goto out_nodev; 1617a703e490SVasu Dev } 1618a703e490SVasu Dev /* look for existing lport */ 1619a703e490SVasu Dev if (fcoe_hostlist_lookup(netdev)) { 1620a703e490SVasu Dev rc = -EEXIST; 1621a703e490SVasu Dev goto out_putdev; 1622a703e490SVasu Dev } 1623a703e490SVasu Dev fcoe_ethdrv_get(netdev); 1624a703e490SVasu Dev 1625a703e490SVasu Dev rc = fcoe_if_create(netdev); 1626a703e490SVasu Dev if (rc) { 1627a703e490SVasu Dev printk(KERN_ERR "fcoe: fcoe_if_create(%s) failed\n", 1628a703e490SVasu Dev netdev->name); 1629a703e490SVasu Dev fcoe_ethdrv_put(netdev); 1630a703e490SVasu Dev rc = -EIO; 1631a703e490SVasu Dev goto out_putdev; 1632a703e490SVasu Dev } 1633a703e490SVasu Dev rc = 0; 1634a703e490SVasu Dev out_putdev: 1635a703e490SVasu Dev dev_put(netdev); 1636a703e490SVasu Dev out_nodev: 1637a703e490SVasu Dev return rc; 1638a703e490SVasu Dev } 1639a703e490SVasu Dev 1640a703e490SVasu Dev module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR); 1641a703e490SVasu Dev __MODULE_PARM_TYPE(create, "string"); 1642a703e490SVasu Dev MODULE_PARM_DESC(create, "Create fcoe port using net device passed in."); 1643a703e490SVasu Dev module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR); 1644a703e490SVasu Dev __MODULE_PARM_TYPE(destroy, "string"); 1645a703e490SVasu Dev MODULE_PARM_DESC(destroy, "Destroy fcoe port"); 1646a703e490SVasu Dev 1647a703e490SVasu Dev /** 1648a703e490SVasu Dev * fcoe_link_ok() - Check if link is ok for the fc_lport 1649a703e490SVasu Dev * @lp: ptr to the fc_lport 1650a703e490SVasu Dev * 1651a703e490SVasu Dev * Any permanently-disqualifying conditions have been previously checked. 1652a703e490SVasu Dev * This also updates the speed setting, which may change with link for 100/1000. 1653a703e490SVasu Dev * 1654a703e490SVasu Dev * This function should probably be checking for PAUSE support at some point 1655a703e490SVasu Dev * in the future. Currently Per-priority-pause is not determinable using 1656a703e490SVasu Dev * ethtool, so we shouldn't be restrictive until that problem is resolved. 1657a703e490SVasu Dev * 1658a703e490SVasu Dev * Returns: 0 if link is OK for use by FCoE. 1659a703e490SVasu Dev * 1660a703e490SVasu Dev */ 1661a703e490SVasu Dev int fcoe_link_ok(struct fc_lport *lp) 1662a703e490SVasu Dev { 1663a703e490SVasu Dev struct fcoe_softc *fc = lport_priv(lp); 1664a703e490SVasu Dev struct net_device *dev = fc->real_dev; 1665a703e490SVasu Dev struct ethtool_cmd ecmd = { ETHTOOL_GSET }; 1666a703e490SVasu Dev int rc = 0; 1667a703e490SVasu Dev 1668a703e490SVasu Dev if ((dev->flags & IFF_UP) && netif_carrier_ok(dev)) { 1669a703e490SVasu Dev dev = fc->phys_dev; 1670a703e490SVasu Dev if (dev->ethtool_ops->get_settings) { 1671a703e490SVasu Dev dev->ethtool_ops->get_settings(dev, &ecmd); 1672a703e490SVasu Dev lp->link_supported_speeds &= 1673a703e490SVasu Dev ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); 1674a703e490SVasu Dev if (ecmd.supported & (SUPPORTED_1000baseT_Half | 1675a703e490SVasu Dev SUPPORTED_1000baseT_Full)) 1676a703e490SVasu Dev lp->link_supported_speeds |= FC_PORTSPEED_1GBIT; 1677a703e490SVasu Dev if (ecmd.supported & SUPPORTED_10000baseT_Full) 1678a703e490SVasu Dev lp->link_supported_speeds |= 1679a703e490SVasu Dev FC_PORTSPEED_10GBIT; 1680a703e490SVasu Dev if (ecmd.speed == SPEED_1000) 1681a703e490SVasu Dev lp->link_speed = FC_PORTSPEED_1GBIT; 1682a703e490SVasu Dev if (ecmd.speed == SPEED_10000) 1683a703e490SVasu Dev lp->link_speed = FC_PORTSPEED_10GBIT; 1684a703e490SVasu Dev } 1685a703e490SVasu Dev } else 1686a703e490SVasu Dev rc = -1; 1687a703e490SVasu Dev 1688a703e490SVasu Dev return rc; 1689a703e490SVasu Dev } 1690a703e490SVasu Dev EXPORT_SYMBOL_GPL(fcoe_link_ok); 1691a703e490SVasu Dev 1692a703e490SVasu Dev /** 1693a703e490SVasu Dev * fcoe_percpu_clean() - Clear the pending skbs for an lport 1694a703e490SVasu Dev * @lp: the fc_lport 1695a703e490SVasu Dev */ 1696a703e490SVasu Dev void fcoe_percpu_clean(struct fc_lport *lp) 1697a703e490SVasu Dev { 1698a703e490SVasu Dev struct fcoe_percpu_s *pp; 1699a703e490SVasu Dev struct fcoe_rcv_info *fr; 1700a703e490SVasu Dev struct sk_buff_head *list; 1701a703e490SVasu Dev struct sk_buff *skb, *next; 1702a703e490SVasu Dev struct sk_buff *head; 1703a703e490SVasu Dev unsigned int cpu; 1704a703e490SVasu Dev 1705a703e490SVasu Dev for_each_possible_cpu(cpu) { 1706a703e490SVasu Dev pp = &per_cpu(fcoe_percpu, cpu); 1707a703e490SVasu Dev spin_lock_bh(&pp->fcoe_rx_list.lock); 1708a703e490SVasu Dev list = &pp->fcoe_rx_list; 1709a703e490SVasu Dev head = list->next; 1710a703e490SVasu Dev for (skb = head; skb != (struct sk_buff *)list; 1711a703e490SVasu Dev skb = next) { 1712a703e490SVasu Dev next = skb->next; 1713a703e490SVasu Dev fr = fcoe_dev_from_skb(skb); 1714a703e490SVasu Dev if (fr->fr_dev == lp) { 1715a703e490SVasu Dev __skb_unlink(skb, list); 1716a703e490SVasu Dev kfree_skb(skb); 1717a703e490SVasu Dev } 1718a703e490SVasu Dev } 1719a703e490SVasu Dev spin_unlock_bh(&pp->fcoe_rx_list.lock); 1720a703e490SVasu Dev } 1721a703e490SVasu Dev } 1722a703e490SVasu Dev EXPORT_SYMBOL_GPL(fcoe_percpu_clean); 1723a703e490SVasu Dev 1724a703e490SVasu Dev /** 1725a703e490SVasu Dev * fcoe_clean_pending_queue() - Dequeue a skb and free it 1726a703e490SVasu Dev * @lp: the corresponding fc_lport 1727a703e490SVasu Dev * 1728a703e490SVasu Dev * Returns: none 1729a703e490SVasu Dev */ 1730a703e490SVasu Dev void fcoe_clean_pending_queue(struct fc_lport *lp) 1731a703e490SVasu Dev { 1732a703e490SVasu Dev struct fcoe_softc *fc = lport_priv(lp); 1733a703e490SVasu Dev struct sk_buff *skb; 1734a703e490SVasu Dev 1735a703e490SVasu Dev spin_lock_bh(&fc->fcoe_pending_queue.lock); 1736a703e490SVasu Dev while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) { 1737a703e490SVasu Dev spin_unlock_bh(&fc->fcoe_pending_queue.lock); 1738a703e490SVasu Dev kfree_skb(skb); 1739a703e490SVasu Dev spin_lock_bh(&fc->fcoe_pending_queue.lock); 1740a703e490SVasu Dev } 1741a703e490SVasu Dev spin_unlock_bh(&fc->fcoe_pending_queue.lock); 1742a703e490SVasu Dev } 1743a703e490SVasu Dev EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); 1744a703e490SVasu Dev 1745a703e490SVasu Dev /** 1746a703e490SVasu Dev * fcoe_reset() - Resets the fcoe 1747a703e490SVasu Dev * @shost: shost the reset is from 1748a703e490SVasu Dev * 1749a703e490SVasu Dev * Returns: always 0 1750a703e490SVasu Dev */ 1751a703e490SVasu Dev int fcoe_reset(struct Scsi_Host *shost) 1752a703e490SVasu Dev { 1753a703e490SVasu Dev struct fc_lport *lport = shost_priv(shost); 1754a703e490SVasu Dev fc_lport_reset(lport); 1755a703e490SVasu Dev return 0; 1756a703e490SVasu Dev } 1757a703e490SVasu Dev EXPORT_SYMBOL_GPL(fcoe_reset); 1758a703e490SVasu Dev 1759a703e490SVasu Dev /** 1760a703e490SVasu Dev * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device 1761a703e490SVasu Dev * @device: this is currently ptr to net_device 1762a703e490SVasu Dev * 1763a703e490SVasu Dev * Returns: NULL or the located fcoe_softc 1764a703e490SVasu Dev */ 1765a703e490SVasu Dev static struct fcoe_softc * 1766a703e490SVasu Dev fcoe_hostlist_lookup_softc(const struct net_device *dev) 1767a703e490SVasu Dev { 1768a703e490SVasu Dev struct fcoe_softc *fc; 1769a703e490SVasu Dev 1770a703e490SVasu Dev read_lock(&fcoe_hostlist_lock); 1771a703e490SVasu Dev list_for_each_entry(fc, &fcoe_hostlist, list) { 1772a703e490SVasu Dev if (fc->real_dev == dev) { 1773a703e490SVasu Dev read_unlock(&fcoe_hostlist_lock); 1774a703e490SVasu Dev return fc; 1775a703e490SVasu Dev } 1776a703e490SVasu Dev } 1777a703e490SVasu Dev read_unlock(&fcoe_hostlist_lock); 1778a703e490SVasu Dev return NULL; 1779a703e490SVasu Dev } 1780a703e490SVasu Dev 1781a703e490SVasu Dev /** 1782a703e490SVasu Dev * fcoe_hostlist_lookup() - Find the corresponding lport by netdev 1783a703e490SVasu Dev * @netdev: ptr to net_device 1784a703e490SVasu Dev * 1785a703e490SVasu Dev * Returns: 0 for success 1786a703e490SVasu Dev */ 1787a703e490SVasu Dev struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) 1788a703e490SVasu Dev { 1789a703e490SVasu Dev struct fcoe_softc *fc; 1790a703e490SVasu Dev 1791a703e490SVasu Dev fc = fcoe_hostlist_lookup_softc(netdev); 1792a703e490SVasu Dev 179397c8389dSJoe Eykholt return (fc) ? fc->ctlr.lp : NULL; 1794a703e490SVasu Dev } 1795a703e490SVasu Dev EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup); 1796a703e490SVasu Dev 1797a703e490SVasu Dev /** 1798a703e490SVasu Dev * fcoe_hostlist_add() - Add a lport to lports list 1799a703e490SVasu Dev * @lp: ptr to the fc_lport to badded 1800a703e490SVasu Dev * 1801a703e490SVasu Dev * Returns: 0 for success 1802a703e490SVasu Dev */ 1803a703e490SVasu Dev int fcoe_hostlist_add(const struct fc_lport *lp) 1804a703e490SVasu Dev { 1805a703e490SVasu Dev struct fcoe_softc *fc; 1806a703e490SVasu Dev 1807a703e490SVasu Dev fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp)); 1808a703e490SVasu Dev if (!fc) { 1809a703e490SVasu Dev fc = lport_priv(lp); 1810a703e490SVasu Dev write_lock_bh(&fcoe_hostlist_lock); 1811a703e490SVasu Dev list_add_tail(&fc->list, &fcoe_hostlist); 1812a703e490SVasu Dev write_unlock_bh(&fcoe_hostlist_lock); 1813a703e490SVasu Dev } 1814a703e490SVasu Dev return 0; 1815a703e490SVasu Dev } 1816a703e490SVasu Dev EXPORT_SYMBOL_GPL(fcoe_hostlist_add); 1817a703e490SVasu Dev 1818a703e490SVasu Dev /** 1819a703e490SVasu Dev * fcoe_hostlist_remove() - remove a lport from lports list 1820a703e490SVasu Dev * @lp: ptr to the fc_lport to badded 1821a703e490SVasu Dev * 1822a703e490SVasu Dev * Returns: 0 for success 1823a703e490SVasu Dev */ 1824a703e490SVasu Dev int fcoe_hostlist_remove(const struct fc_lport *lp) 1825a703e490SVasu Dev { 1826a703e490SVasu Dev struct fcoe_softc *fc; 1827a703e490SVasu Dev 1828a703e490SVasu Dev fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp)); 1829a703e490SVasu Dev BUG_ON(!fc); 1830a703e490SVasu Dev write_lock_bh(&fcoe_hostlist_lock); 1831a703e490SVasu Dev list_del(&fc->list); 1832a703e490SVasu Dev write_unlock_bh(&fcoe_hostlist_lock); 1833a703e490SVasu Dev 1834a703e490SVasu Dev return 0; 1835a703e490SVasu Dev } 1836a703e490SVasu Dev EXPORT_SYMBOL_GPL(fcoe_hostlist_remove); 1837a703e490SVasu Dev 1838a703e490SVasu Dev /** 1839a703e490SVasu Dev * fcoe_init() - fcoe module loading initialization 1840a703e490SVasu Dev * 1841a703e490SVasu Dev * Returns 0 on success, negative on failure 1842a703e490SVasu Dev */ 1843a703e490SVasu Dev static int __init fcoe_init(void) 1844a703e490SVasu Dev { 1845a703e490SVasu Dev unsigned int cpu; 1846a703e490SVasu Dev int rc = 0; 1847a703e490SVasu Dev struct fcoe_percpu_s *p; 1848a703e490SVasu Dev 1849a703e490SVasu Dev INIT_LIST_HEAD(&fcoe_hostlist); 1850a703e490SVasu Dev rwlock_init(&fcoe_hostlist_lock); 1851a703e490SVasu Dev 1852a703e490SVasu Dev for_each_possible_cpu(cpu) { 1853a703e490SVasu Dev p = &per_cpu(fcoe_percpu, cpu); 1854a703e490SVasu Dev skb_queue_head_init(&p->fcoe_rx_list); 1855a703e490SVasu Dev } 1856a703e490SVasu Dev 1857a703e490SVasu Dev for_each_online_cpu(cpu) 1858a703e490SVasu Dev fcoe_percpu_thread_create(cpu); 1859a703e490SVasu Dev 1860a703e490SVasu Dev /* Initialize per CPU interrupt thread */ 1861a703e490SVasu Dev rc = register_hotcpu_notifier(&fcoe_cpu_notifier); 1862a703e490SVasu Dev if (rc) 1863a703e490SVasu Dev goto out_free; 1864a703e490SVasu Dev 1865a703e490SVasu Dev /* Setup link change notification */ 1866a703e490SVasu Dev fcoe_dev_setup(); 1867a703e490SVasu Dev 1868a703e490SVasu Dev setup_timer(&fcoe_timer, fcoe_watchdog, 0); 1869a703e490SVasu Dev 1870a703e490SVasu Dev mod_timer(&fcoe_timer, jiffies + (10 * HZ)); 1871a703e490SVasu Dev 1872a703e490SVasu Dev fcoe_if_init(); 1873a703e490SVasu Dev 1874a703e490SVasu Dev return 0; 1875a703e490SVasu Dev 1876a703e490SVasu Dev out_free: 1877a703e490SVasu Dev for_each_online_cpu(cpu) { 1878a703e490SVasu Dev fcoe_percpu_thread_destroy(cpu); 1879a703e490SVasu Dev } 1880a703e490SVasu Dev 1881a703e490SVasu Dev return rc; 1882a703e490SVasu Dev } 1883a703e490SVasu Dev module_init(fcoe_init); 1884a703e490SVasu Dev 1885a703e490SVasu Dev /** 1886a703e490SVasu Dev * fcoe_exit() - fcoe module unloading cleanup 1887a703e490SVasu Dev * 1888a703e490SVasu Dev * Returns 0 on success, negative on failure 1889a703e490SVasu Dev */ 1890a703e490SVasu Dev static void __exit fcoe_exit(void) 1891a703e490SVasu Dev { 1892a703e490SVasu Dev unsigned int cpu; 1893a703e490SVasu Dev struct fcoe_softc *fc, *tmp; 1894a703e490SVasu Dev 1895a703e490SVasu Dev fcoe_dev_cleanup(); 1896a703e490SVasu Dev 1897a703e490SVasu Dev /* Stop the timer */ 1898a703e490SVasu Dev del_timer_sync(&fcoe_timer); 1899a703e490SVasu Dev 1900a703e490SVasu Dev /* releases the associated fcoe hosts */ 1901a703e490SVasu Dev list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list) 1902a703e490SVasu Dev fcoe_if_destroy(fc->real_dev); 1903a703e490SVasu Dev 1904a703e490SVasu Dev unregister_hotcpu_notifier(&fcoe_cpu_notifier); 1905a703e490SVasu Dev 1906a703e490SVasu Dev for_each_online_cpu(cpu) { 1907a703e490SVasu Dev fcoe_percpu_thread_destroy(cpu); 1908a703e490SVasu Dev } 1909a703e490SVasu Dev 1910a703e490SVasu Dev /* detach from scsi transport */ 1911a703e490SVasu Dev fcoe_if_exit(); 1912a703e490SVasu Dev } 1913a703e490SVasu Dev module_exit(fcoe_exit); 1914