diff options
Diffstat (limited to 'drivers/scsi/fcoe/fcoe.c')
| -rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 146 |
1 files changed, 52 insertions, 94 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index cd19be3f3405..c8c5dfb3ba9a 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1,19 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * * Maintained at www.Open-FCoE.org */ @@ -272,7 +260,7 @@ static struct fc_function_template fcoe_vport_fc_functions = { .bsg_request = fc_lport_bsg_request, }; -static struct scsi_host_template fcoe_shost_template = { +static const struct scsi_host_template fcoe_shost_template = { .module = THIS_MODULE, .name = "FCoE Driver", .proc_name = FCOE_NAME, @@ -281,7 +269,7 @@ static struct scsi_host_template fcoe_shost_template = { .eh_abort_handler = fc_eh_abort, .eh_device_reset_handler = fc_eh_device_reset, .eh_host_reset_handler = fc_eh_host_reset, - .slave_alloc = fc_slave_alloc, + .sdev_init = fc_sdev_init, .change_queue_depth = scsi_change_queue_depth, .this_id = -1, .cmd_per_lun = 3, @@ -289,6 +277,7 @@ static struct scsi_host_template fcoe_shost_template = { .sg_tablesize = SG_ALL, .max_sectors = 0xffff, .track_queue_depth = 1, + .cmd_size = sizeof(struct libfc_cmd_priv), }; /** @@ -305,7 +294,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); struct netdev_hw_addr *ha; struct net_device *real_dev; - u8 flogi_maddr[ETH_ALEN]; + static const u8 flogi_maddr[ETH_ALEN] = FC_FCOE_FLOGI_MAC; const struct net_device_ops *ops; fcoe->netdev = netdev; @@ -319,7 +308,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, } /* Do not support for bonding device */ - if (netdev->priv_flags & IFF_BONDING && netdev->flags & IFF_MASTER) { + if (netif_is_bond_master(netdev)) { FCOE_NETDEV_DBG(netdev, "Bonded interfaces not supported\n"); return -EOPNOTSUPP; } @@ -348,7 +337,6 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, * or enter promiscuous mode if not capable of listening * for multiple unicast MACs. */ - memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); dev_uc_add(netdev, flogi_maddr); if (fip->spma) dev_uc_add(netdev, fip->ctl_src_addr); @@ -389,7 +377,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, * Returns: pointer to a struct fcoe_interface or NULL on error */ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, - enum fip_state fip_mode) + enum fip_mode fip_mode) { struct fcoe_ctlr_device *ctlr_dev; struct fcoe_ctlr *ctlr; @@ -454,7 +442,7 @@ static void fcoe_interface_remove(struct fcoe_interface *fcoe) { struct net_device *netdev = fcoe->netdev; struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); - u8 flogi_maddr[ETH_ALEN]; + static const u8 flogi_maddr[ETH_ALEN] = FC_FCOE_FLOGI_MAC; const struct net_device_ops *ops; /* @@ -470,7 +458,6 @@ static void fcoe_interface_remove(struct fcoe_interface *fcoe) synchronize_net(); /* Delete secondary MAC addresses */ - memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); dev_uc_del(netdev, flogi_maddr); if (fip->spma) dev_uc_del(netdev, fip->ctl_src_addr); @@ -657,7 +644,7 @@ static int fcoe_lport_config(struct fc_lport *lport) return 0; } -/** +/* * fcoe_netdev_features_change - Updates the lport's offload flags based * on the LLD netdev's FCoE feature flags */ @@ -680,7 +667,7 @@ static void fcoe_netdev_features_change(struct fc_lport *lport, if (netdev->features & NETIF_F_FSO) { lport->seq_offload = 1; - lport->lso_max = netdev->gso_max_size; + lport->lso_max = min(netdev->gso_max_size, GSO_LEGACY_MAX_SIZE); FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n", lport->lso_max); } else { @@ -735,7 +722,7 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) * will return 0, so do this first. */ mfs = netdev->mtu; - if (netdev->features & NETIF_F_FCOE_MTU) { + if (netdev->fcoe_mtu) { mfs = FCOE_MTU; FCOE_NETDEV_DBG(netdev, "Supports FCOE_MTU of %d bytes\n", mfs); } @@ -1026,7 +1013,7 @@ static void fcoe_if_destroy(struct fc_lport *lport) fc_lport_destroy(lport); /* Stop the transmit retry timer */ - del_timer_sync(&port->timer); + timer_delete_sync(&port->timer); /* Free existing transmit skbs */ fcoe_clean_pending_queue(lport); @@ -1262,15 +1249,21 @@ static int __init fcoe_if_init(void) /* attach to scsi transport */ fcoe_nport_scsi_transport = fc_attach_transport(&fcoe_nport_fc_functions); + if (!fcoe_nport_scsi_transport) + goto err; + fcoe_vport_scsi_transport = fc_attach_transport(&fcoe_vport_fc_functions); - - if (!fcoe_nport_scsi_transport) { - printk(KERN_ERR "fcoe: Failed to attach to the FC transport\n"); - return -ENODEV; - } + if (!fcoe_vport_scsi_transport) + goto err_vport; return 0; + +err_vport: + fc_release_transport(fcoe_nport_scsi_transport); +err: + printk(KERN_ERR "fcoe: Failed to attach to the FC transport\n"); + return -ENODEV; } /** @@ -1307,26 +1300,6 @@ static void fcoe_thread_cleanup_local(unsigned int cpu) } /** - * fcoe_select_cpu() - Selects CPU to handle post-processing of incoming - * command. - * - * This routine selects next CPU based on cpumask to distribute - * incoming requests in round robin. - * - * Returns: int CPU number - */ -static inline unsigned int fcoe_select_cpu(void) -{ - static unsigned int selected_cpu; - - selected_cpu = cpumask_next(selected_cpu, cpu_online_mask); - if (selected_cpu >= nr_cpu_ids) - selected_cpu = cpumask_first(cpu_online_mask); - - return selected_cpu; -} - -/** * fcoe_rcv() - Receive packets from a net device * @skb: The received packet * @netdev: The net device that the packet was received on @@ -1412,7 +1385,7 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, cpu = ntohs(fh->fh_ox_id) & fc_cpu_mask; else { if (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN) - cpu = fcoe_select_cpu(); + cpu = skb->alloc_cpu; else cpu = ntohs(fh->fh_rx_id) & fc_cpu_mask; } @@ -1441,8 +1414,7 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, return NET_RX_SUCCESS; err: - per_cpu_ptr(lport->stats, get_cpu())->ErrorFrames++; - put_cpu(); + this_cpu_inc(lport->stats->ErrorFrames); err2: kfree_skb(skb); return NET_RX_DROP; @@ -1460,9 +1432,10 @@ static int fcoe_alloc_paged_crc_eof(struct sk_buff *skb, int tlen) struct fcoe_percpu_s *fps; int rc; - fps = &get_cpu_var(fcoe_percpu); + local_lock(&fcoe_percpu.lock); + fps = this_cpu_ptr(&fcoe_percpu); rc = fcoe_get_paged_crc_eof(skb, tlen, fps); - put_cpu_var(fcoe_percpu); + local_unlock(&fcoe_percpu.lock); return rc; } @@ -1481,7 +1454,6 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) struct ethhdr *eh; struct fcoe_crc_eof *cp; struct sk_buff *skb; - struct fc_stats *stats; struct fc_frame_header *fh; unsigned int hlen; /* header length implies the version */ unsigned int tlen; /* trailer length */ @@ -1496,7 +1468,6 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) fh = fc_frame_header_get(fp); skb = fp_skb(fp); - wlen = skb->len / FCOE_WORD_TO_BYTE; if (!lport->link_up) { kfree_skb(skb); @@ -1534,8 +1505,7 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) return -ENOMEM; } frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; - cp = kmap_atomic(skb_frag_page(frag)) - + frag->page_offset; + cp = kmap_atomic(skb_frag_page(frag)) + skb_frag_off(frag); } else { cp = skb_put(skb, tlen); } @@ -1593,10 +1563,8 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) skb_shinfo(skb)->gso_size = 0; } /* update tx stats: regardless if LLD fails */ - stats = per_cpu_ptr(lport->stats, get_cpu()); - stats->TxFrames++; - stats->TxWords += wlen; - put_cpu(); + this_cpu_inc(lport->stats->TxFrames); + this_cpu_add(lport->stats->TxWords, wlen); /* send down to lld */ fr_dev(fp) = lport; @@ -1618,7 +1586,6 @@ static inline int fcoe_filter_frames(struct fc_lport *lport, struct fcoe_interface *fcoe; struct fc_frame_header *fh; struct sk_buff *skb = (struct sk_buff *)fp; - struct fc_stats *stats; /* * We only check CRC if no offload is available and if it is @@ -1630,7 +1597,6 @@ static inline int fcoe_filter_frames(struct fc_lport *lport, else fr_flags(fp) |= FCPHF_CRC_UNCHECKED; - fh = (struct fc_frame_header *) skb_transport_header(skb); fh = fc_frame_header_get(fp); if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && fh->fh_type == FC_TYPE_FCP) return 0; @@ -1649,11 +1615,8 @@ static inline int fcoe_filter_frames(struct fc_lport *lport, return 0; } - stats = per_cpu_ptr(lport->stats, get_cpu()); - stats->InvalidCRCCount++; - if (stats->InvalidCRCCount < 5) + if (this_cpu_inc_return(lport->stats->InvalidCRCCount) < 5) printk(KERN_WARNING "fcoe: dropping frame with CRC error\n"); - put_cpu(); return -EINVAL; } @@ -1666,7 +1629,6 @@ static void fcoe_recv_frame(struct sk_buff *skb) u32 fr_len; struct fc_lport *lport; struct fcoe_rcv_info *fr; - struct fc_stats *stats; struct fcoe_crc_eof crc_eof; struct fc_frame *fp; struct fcoe_hdr *hp; @@ -1694,9 +1656,11 @@ static void fcoe_recv_frame(struct sk_buff *skb) */ hp = (struct fcoe_hdr *) skb_network_header(skb); - stats = per_cpu_ptr(lport->stats, get_cpu()); if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) { - if (stats->ErrorFrames < 5) + struct fc_stats *stats; + + stats = per_cpu_ptr(lport->stats, raw_smp_processor_id()); + if (READ_ONCE(stats->ErrorFrames) < 5) printk(KERN_WARNING "fcoe: FCoE version " "mismatch: The frame has " "version %x, but the " @@ -1709,8 +1673,8 @@ static void fcoe_recv_frame(struct sk_buff *skb) skb_pull(skb, sizeof(struct fcoe_hdr)); fr_len = skb->len - sizeof(struct fcoe_crc_eof); - stats->RxFrames++; - stats->RxWords += fr_len / FCOE_WORD_TO_BYTE; + this_cpu_inc(lport->stats->RxFrames); + this_cpu_add(lport->stats->RxWords, fr_len / FCOE_WORD_TO_BYTE); fp = (struct fc_frame *)skb; fc_frame_init(fp); @@ -1726,13 +1690,11 @@ static void fcoe_recv_frame(struct sk_buff *skb) goto drop; if (!fcoe_filter_frames(lport, fp)) { - put_cpu(); fc_exch_recv(lport, fp); return; } drop: - stats->ErrorFrames++; - put_cpu(); + this_cpu_inc(lport->stats->ErrorFrames); kfree_skb(skb); } @@ -1856,7 +1818,6 @@ static int fcoe_device_notification(struct notifier_block *notifier, struct net_device *netdev = netdev_notifier_info_to_dev(ptr); struct fcoe_ctlr *ctlr; struct fcoe_interface *fcoe; - struct fc_stats *stats; u32 link_possible = 1; u32 mfs; int rc = NOTIFY_OK; @@ -1882,7 +1843,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, case NETDEV_CHANGE: break; case NETDEV_CHANGEMTU: - if (netdev->features & NETIF_F_FCOE_MTU) + if (netdev->fcoe_mtu) break; mfs = netdev->mtu - (sizeof(struct fcoe_hdr) + sizeof(struct fcoe_crc_eof)); @@ -1902,7 +1863,6 @@ static int fcoe_device_notification(struct notifier_block *notifier, mutex_unlock(&fcoe_config_mutex); fcoe_ctlr_device_delete(fcoe_ctlr_to_ctlr_dev(ctlr)); goto out; - break; case NETDEV_FEAT_CHANGE: fcoe_netdev_features_change(lport, netdev); break; @@ -1923,7 +1883,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, case FCOE_CTLR_ENABLED: case FCOE_CTLR_UNUSED: fcoe_ctlr_link_up(ctlr); - }; + } } else if (fcoe_ctlr_link_down(ctlr)) { switch (cdev->enabled) { case FCOE_CTLR_DISABLED: @@ -1931,11 +1891,9 @@ static int fcoe_device_notification(struct notifier_block *notifier, break; case FCOE_CTLR_ENABLED: case FCOE_CTLR_UNUSED: - stats = per_cpu_ptr(lport->stats, get_cpu()); - stats->LinkFailureCount++; - put_cpu(); + this_cpu_inc(lport->stats->LinkFailureCount); fcoe_clean_pending_queue(lport); - }; + } } out: return rc; @@ -2032,12 +1990,12 @@ static int fcoe_ctlr_enabled(struct fcoe_ctlr_device *cdev) case FCOE_CTLR_UNUSED: default: return -ENOTSUPP; - }; + } } /** * fcoe_ctlr_mode() - Switch FIP mode - * @cdev: The FCoE Controller that is being modified + * @ctlr_dev: The FCoE Controller that is being modified * * When the FIP mode has been changed we need to update * the multicast addresses to ensure we get the correct @@ -2144,9 +2102,7 @@ static bool fcoe_match(struct net_device *netdev) /** * fcoe_dcb_create() - Initialize DCB attributes and hooks - * @netdev: The net_device object of the L2 link that should be queried - * @port: The fcoe_port to bind FCoE APP priority with - * @ + * @fcoe: The new FCoE interface */ static void fcoe_dcb_create(struct fcoe_interface *fcoe) { @@ -2482,7 +2438,7 @@ static int __init fcoe_init(void) unsigned int cpu; int rc = 0; - fcoe_wq = alloc_workqueue("fcoe", 0, 0); + fcoe_wq = alloc_workqueue("fcoe", WQ_PERCPU, 0); if (!fcoe_wq) return -ENOMEM; @@ -2500,6 +2456,7 @@ static int __init fcoe_init(void) p = per_cpu_ptr(&fcoe_percpu, cpu); INIT_WORK(&p->work, fcoe_receive_work); skb_queue_head_init(&p->fcoe_rx_list); + local_lock_init(&p->lock); } /* Setup link change notification */ @@ -2514,6 +2471,7 @@ static int __init fcoe_init(void) out_free: mutex_unlock(&fcoe_config_mutex); + fcoe_transport_detach(&fcoe_sw_transport); out_destroy: destroy_workqueue(fcoe_wq); return rc; @@ -2592,7 +2550,7 @@ static void fcoe_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) /* pre-FIP */ if (is_zero_ether_addr(mac)) fcoe_ctlr_recv_flogi(fip, lport, fp); - if (!is_zero_ether_addr(mac)) + else fcoe_update_src_mac(lport, mac); done: fc_lport_flogi_resp(seq, fp, lport); @@ -2617,7 +2575,7 @@ static void fcoe_logo_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) fc_lport_logo_resp(seq, fp, lport); } -/** +/* * fcoe_elsct_send - FCoE specific ELS handler * * This does special case handling of FIP encapsualted ELS exchanges for FCoE, @@ -2782,7 +2740,7 @@ static int fcoe_vport_disable(struct fc_vport *vport, bool disable) } /** - * fcoe_vport_set_symbolic_name() - append vport string to symbolic name + * fcoe_set_vport_symbolic_name() - append vport string to symbolic name * @vport: fc_vport with a new symbolic name string * * After generating a new symbolic name string, a new RSPN_ID request is |
