File Index
Files and directories
Sign in
FILE

fcoe_transport.c

File preview with syntax highlighting.

linux-6.19.14/drivers/scsi/fcoe/fcoe_transport.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
   4 *
   5 * Maintained at www.Open-FCoE.org
   6 */
   7
   8#include <linux/types.h>
   9#include <linux/module.h>
  10#include <linux/kernel.h>
  11#include <linux/list.h>
  12#include <linux/netdevice.h>
  13#include <linux/ethtool.h>
  14#include <linux/errno.h>
  15#include <linux/crc32.h>
  16#include <scsi/libfcoe.h>
  17
  18#include "libfcoe.h"
  19
  20MODULE_AUTHOR("Open-FCoE.org");
  21MODULE_DESCRIPTION("FIP discovery protocol and FCoE transport for FCoE HBAs");
  22MODULE_LICENSE("GPL v2");
  23
  24static int fcoe_transport_create(const char *, const struct kernel_param *);
  25static int fcoe_transport_destroy(const char *, const struct kernel_param *);
  26static int fcoe_transport_show(char *buffer, const struct kernel_param *kp);
  27static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device);
  28static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device);
  29static int fcoe_transport_enable(const char *, const struct kernel_param *);
  30static int fcoe_transport_disable(const char *, const struct kernel_param *);
  31static int libfcoe_device_notification(struct notifier_block *notifier,
  32				    ulong event, void *ptr);
  33
  34static LIST_HEAD(fcoe_transports);
  35static DEFINE_MUTEX(ft_mutex);
  36static LIST_HEAD(fcoe_netdevs);
  37static DEFINE_MUTEX(fn_mutex);
  38
  39unsigned int libfcoe_debug_logging;
  40module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR);
  41MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
  42
  43module_param_call(show, NULL, fcoe_transport_show, NULL, S_IRUSR);
  44__MODULE_PARM_TYPE(show, "string");
  45MODULE_PARM_DESC(show, " Show attached FCoE transports");
  46
  47module_param_call(create, fcoe_transport_create, NULL,
  48		  (void *)FIP_MODE_FABRIC, S_IWUSR);
  49__MODULE_PARM_TYPE(create, "string");
  50MODULE_PARM_DESC(create, " Creates fcoe instance on an ethernet interface");
  51
  52module_param_call(create_vn2vn, fcoe_transport_create, NULL,
  53		  (void *)FIP_MODE_VN2VN, S_IWUSR);
  54__MODULE_PARM_TYPE(create_vn2vn, "string");
  55MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance "
  56		 "on an Ethernet interface");
  57
  58module_param_call(destroy, fcoe_transport_destroy, NULL, NULL, S_IWUSR);
  59__MODULE_PARM_TYPE(destroy, "string");
  60MODULE_PARM_DESC(destroy, " Destroys fcoe instance on an ethernet interface");
  61
  62module_param_call(enable, fcoe_transport_enable, NULL, NULL, S_IWUSR);
  63__MODULE_PARM_TYPE(enable, "string");
  64MODULE_PARM_DESC(enable, " Enables fcoe on an ethernet interface.");
  65
  66module_param_call(disable, fcoe_transport_disable, NULL, NULL, S_IWUSR);
  67__MODULE_PARM_TYPE(disable, "string");
  68MODULE_PARM_DESC(disable, " Disables fcoe on an ethernet interface.");
  69
  70/* notification function for packets from net device */
  71static struct notifier_block libfcoe_notifier = {
  72	.notifier_call = libfcoe_device_notification,
  73};
  74
  75static const struct {
  76	u32 fc_port_speed;
  77#define SPEED_2000	2000
  78#define SPEED_4000	4000
  79#define SPEED_8000	8000
  80#define SPEED_16000	16000
  81#define SPEED_32000	32000
  82	u32 eth_port_speed;
  83} fcoe_port_speed_mapping[] = {
  84	{ FC_PORTSPEED_1GBIT,   SPEED_1000   },
  85	{ FC_PORTSPEED_2GBIT,   SPEED_2000   },
  86	{ FC_PORTSPEED_4GBIT,   SPEED_4000   },
  87	{ FC_PORTSPEED_8GBIT,   SPEED_8000   },
  88	{ FC_PORTSPEED_10GBIT,  SPEED_10000  },
  89	{ FC_PORTSPEED_16GBIT,  SPEED_16000  },
  90	{ FC_PORTSPEED_20GBIT,  SPEED_20000  },
  91	{ FC_PORTSPEED_25GBIT,  SPEED_25000  },
  92	{ FC_PORTSPEED_32GBIT,  SPEED_32000  },
  93	{ FC_PORTSPEED_40GBIT,  SPEED_40000  },
  94	{ FC_PORTSPEED_50GBIT,  SPEED_50000  },
  95	{ FC_PORTSPEED_100GBIT, SPEED_100000 },
  96};
  97
  98static inline u32 eth2fc_speed(u32 eth_port_speed)
  99{
 100	int i;
 101
 102	for (i = 0; i < ARRAY_SIZE(fcoe_port_speed_mapping); i++) {
 103		if (fcoe_port_speed_mapping[i].eth_port_speed == eth_port_speed)
 104			return fcoe_port_speed_mapping[i].fc_port_speed;
 105	}
 106
 107	return FC_PORTSPEED_UNKNOWN;
 108}
 109
 110/**
 111 * fcoe_link_speed_update() - Update the supported and actual link speeds
 112 * @lport: The local port to update speeds for
 113 *
 114 * Returns: 0 if the ethtool query was successful
 115 *          -1 if the ethtool query failed
 116 */
 117int fcoe_link_speed_update(struct fc_lport *lport)
 118{
 119	struct net_device *netdev = fcoe_get_netdev(lport);
 120	struct ethtool_link_ksettings ecmd;
 121
 122	if (!__ethtool_get_link_ksettings(netdev, &ecmd)) {
 123		lport->link_supported_speeds &= ~(FC_PORTSPEED_1GBIT  |
 124		                                  FC_PORTSPEED_10GBIT |
 125		                                  FC_PORTSPEED_20GBIT |
 126		                                  FC_PORTSPEED_40GBIT);
 127
 128		if (ecmd.link_modes.supported[0] & (
 129			    SUPPORTED_1000baseT_Half |
 130			    SUPPORTED_1000baseT_Full |
 131			    SUPPORTED_1000baseKX_Full))
 132			lport->link_supported_speeds |= FC_PORTSPEED_1GBIT;
 133
 134		if (ecmd.link_modes.supported[0] & (
 135			    SUPPORTED_10000baseT_Full   |
 136			    SUPPORTED_10000baseKX4_Full |
 137			    SUPPORTED_10000baseKR_Full  |
 138			    SUPPORTED_10000baseR_FEC))
 139			lport->link_supported_speeds |= FC_PORTSPEED_10GBIT;
 140
 141		if (ecmd.link_modes.supported[0] & (
 142			    SUPPORTED_20000baseMLD2_Full |
 143			    SUPPORTED_20000baseKR2_Full))
 144			lport->link_supported_speeds |= FC_PORTSPEED_20GBIT;
 145
 146		if (ecmd.link_modes.supported[0] & (
 147			    SUPPORTED_40000baseKR4_Full |
 148			    SUPPORTED_40000baseCR4_Full |
 149			    SUPPORTED_40000baseSR4_Full |
 150			    SUPPORTED_40000baseLR4_Full))
 151			lport->link_supported_speeds |= FC_PORTSPEED_40GBIT;
 152
 153		lport->link_speed = eth2fc_speed(ecmd.base.speed);
 154		return 0;
 155	}
 156	return -1;
 157}
 158EXPORT_SYMBOL_GPL(fcoe_link_speed_update);
 159
 160/**
 161 * __fcoe_get_lesb() - Get the Link Error Status Block (LESB) for a given lport
 162 * @lport: The local port to update speeds for
 163 * @fc_lesb: Pointer to the LESB to be filled up
 164 * @netdev: Pointer to the netdev that is associated with the lport
 165 *
 166 * Note, the Link Error Status Block (LESB) for FCoE is defined in FC-BB-6
 167 * Clause 7.11 in v1.04.
 168 */
 169void __fcoe_get_lesb(struct fc_lport *lport,
 170		     struct fc_els_lesb *fc_lesb,
 171		     struct net_device *netdev)
 172{
 173	unsigned int cpu;
 174	u32 lfc, vlfc, mdac;
 175	struct fc_stats *stats;
 176	struct fcoe_fc_els_lesb *lesb;
 177	struct rtnl_link_stats64 temp;
 178
 179	lfc = 0;
 180	vlfc = 0;
 181	mdac = 0;
 182	lesb = (struct fcoe_fc_els_lesb *)fc_lesb;
 183	memset(lesb, 0, sizeof(*lesb));
 184	for_each_possible_cpu(cpu) {
 185		stats = per_cpu_ptr(lport->stats, cpu);
 186		lfc += READ_ONCE(stats->LinkFailureCount);
 187		vlfc += READ_ONCE(stats->VLinkFailureCount);
 188		mdac += READ_ONCE(stats->MissDiscAdvCount);
 189	}
 190	lesb->lesb_link_fail = htonl(lfc);
 191	lesb->lesb_vlink_fail = htonl(vlfc);
 192	lesb->lesb_miss_fka = htonl(mdac);
 193	lesb->lesb_fcs_error =
 194			htonl(dev_get_stats(netdev, &temp)->rx_crc_errors);
 195}
 196EXPORT_SYMBOL_GPL(__fcoe_get_lesb);
 197
 198/**
 199 * fcoe_get_lesb() - Fill the FCoE Link Error Status Block
 200 * @lport: the local port
 201 * @fc_lesb: the link error status block
 202 */
 203void fcoe_get_lesb(struct fc_lport *lport,
 204			 struct fc_els_lesb *fc_lesb)
 205{
 206	struct net_device *netdev = fcoe_get_netdev(lport);
 207
 208	__fcoe_get_lesb(lport, fc_lesb, netdev);
 209}
 210EXPORT_SYMBOL_GPL(fcoe_get_lesb);
 211
 212/**
 213 * fcoe_ctlr_get_lesb() - Get the Link Error Status Block (LESB) for a given
 214 * fcoe controller device
 215 * @ctlr_dev: The given fcoe controller device
 216 *
 217 */
 218void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev)
 219{
 220	struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
 221	struct net_device *netdev = fcoe_get_netdev(fip->lp);
 222	struct fc_els_lesb *fc_lesb;
 223
 224	fc_lesb = (struct fc_els_lesb *)(&ctlr_dev->lesb);
 225	__fcoe_get_lesb(fip->lp, fc_lesb, netdev);
 226}
 227EXPORT_SYMBOL_GPL(fcoe_ctlr_get_lesb);
 228
 229void fcoe_wwn_to_str(u64 wwn, char *buf, int len)
 230{
 231	u8 wwpn[8];
 232
 233	u64_to_wwn(wwn, wwpn);
 234	snprintf(buf, len, "%02x%02x%02x%02x%02x%02x%02x%02x",
 235		 wwpn[0], wwpn[1], wwpn[2], wwpn[3],
 236		 wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
 237}
 238EXPORT_SYMBOL_GPL(fcoe_wwn_to_str);
 239
 240/**
 241 * fcoe_validate_vport_create() - Validate a vport before creating it
 242 * @vport: NPIV port to be created
 243 *
 244 * This routine is meant to add validation for a vport before creating it
 245 * via fcoe_vport_create().
 246 * Current validations are:
 247 *      - WWPN supplied is unique for given lport
 248 */
 249int fcoe_validate_vport_create(struct fc_vport *vport)
 250{
 251	struct Scsi_Host *shost = vport_to_shost(vport);
 252	struct fc_lport *n_port = shost_priv(shost);
 253	struct fc_lport *vn_port;
 254	int rc = 0;
 255	char buf[32];
 256
 257	mutex_lock(&n_port->lp_mutex);
 258
 259	fcoe_wwn_to_str(vport->port_name, buf, sizeof(buf));
 260	/* Check if the wwpn is not same as that of the lport */
 261	if (!memcmp(&n_port->wwpn, &vport->port_name, sizeof(u64))) {
 262		LIBFCOE_TRANSPORT_DBG("vport WWPN 0x%s is same as that of the "
 263				      "base port WWPN\n", buf);
 264		rc = -EINVAL;
 265		goto out;
 266	}
 267
 268	/* Check if there is any existing vport with same wwpn */
 269	list_for_each_entry(vn_port, &n_port->vports, list) {
 270		if (!memcmp(&vn_port->wwpn, &vport->port_name, sizeof(u64))) {
 271			LIBFCOE_TRANSPORT_DBG("vport with given WWPN 0x%s "
 272					      "already exists\n", buf);
 273			rc = -EINVAL;
 274			break;
 275		}
 276	}
 277out:
 278	mutex_unlock(&n_port->lp_mutex);
 279	return rc;
 280}
 281EXPORT_SYMBOL_GPL(fcoe_validate_vport_create);
 282
 283/**
 284 * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
 285 * @netdev: the associated net device
 286 * @wwn: the output WWN
 287 * @type: the type of WWN (WWPN or WWNN)
 288 *
 289 * Returns: 0 for success
 290 */
 291int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
 292{
 293	const struct net_device_ops *ops = netdev->netdev_ops;
 294
 295	if (ops->ndo_fcoe_get_wwn)
 296		return ops->ndo_fcoe_get_wwn(netdev, wwn, type);
 297	return -EINVAL;
 298}
 299EXPORT_SYMBOL_GPL(fcoe_get_wwn);
 300
 301/**
 302 * fcoe_fc_crc() - Calculates the CRC for a given frame
 303 * @fp: The frame to be checksumed
 304 *
 305 * This uses crc32() routine to calculate the CRC for a frame
 306 *
 307 * Return: The 32 bit CRC value
 308 */
 309u32 fcoe_fc_crc(struct fc_frame *fp)
 310{
 311	struct sk_buff *skb = fp_skb(fp);
 312	skb_frag_t *frag;
 313	unsigned char *data;
 314	unsigned long off, len, clen;
 315	u32 crc;
 316	unsigned i;
 317
 318	crc = crc32(~0, skb->data, skb_headlen(skb));
 319
 320	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 321		frag = &skb_shinfo(skb)->frags[i];
 322		off = skb_frag_off(frag);
 323		len = skb_frag_size(frag);
 324		while (len > 0) {
 325			clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
 326			data = kmap_atomic(
 327				skb_frag_page(frag) + (off >> PAGE_SHIFT));
 328			crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
 329			kunmap_atomic(data);
 330			off += clen;
 331			len -= clen;
 332		}
 333	}
 334	return crc;
 335}
 336EXPORT_SYMBOL_GPL(fcoe_fc_crc);
 337
 338/**
 339 * fcoe_start_io() - Start FCoE I/O
 340 * @skb: The packet to be transmitted
 341 *
 342 * This routine is called from the net device to start transmitting
 343 * FCoE packets.
 344 *
 345 * Returns: 0 for success
 346 */
 347int fcoe_start_io(struct sk_buff *skb)
 348{
 349	struct sk_buff *nskb;
 350	int rc;
 351
 352	nskb = skb_clone(skb, GFP_ATOMIC);
 353	if (!nskb)
 354		return -ENOMEM;
 355	rc = dev_queue_xmit(nskb);
 356	if (rc != 0)
 357		return rc;
 358	kfree_skb(skb);
 359	return 0;
 360}
 361EXPORT_SYMBOL_GPL(fcoe_start_io);
 362
 363
 364/**
 365 * fcoe_clean_pending_queue() - Dequeue a skb and free it
 366 * @lport: The local port to dequeue a skb on
 367 */
 368void fcoe_clean_pending_queue(struct fc_lport *lport)
 369{
 370	struct fcoe_port  *port = lport_priv(lport);
 371	struct sk_buff *skb;
 372
 373	spin_lock_bh(&port->fcoe_pending_queue.lock);
 374	while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) {
 375		spin_unlock_bh(&port->fcoe_pending_queue.lock);
 376		kfree_skb(skb);
 377		spin_lock_bh(&port->fcoe_pending_queue.lock);
 378	}
 379	spin_unlock_bh(&port->fcoe_pending_queue.lock);
 380}
 381EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
 382
 383/**
 384 * fcoe_check_wait_queue() - Attempt to clear the transmit backlog
 385 * @lport: The local port whose backlog is to be cleared
 386 * @skb: The received FIP packet
 387 *
 388 * This empties the wait_queue, dequeues the head of the wait_queue queue
 389 * and calls fcoe_start_io() for each packet. If all skb have been
 390 * transmitted it returns the qlen. If an error occurs it restores
 391 * wait_queue (to try again later) and returns -1.
 392 *
 393 * The wait_queue is used when the skb transmit fails. The failed skb
 394 * will go in the wait_queue which will be emptied by the timer function or
 395 * by the next skb transmit.
 396 */
 397void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb)
 398{
 399	struct fcoe_port *port = lport_priv(lport);
 400	int rc;
 401
 402	spin_lock_bh(&port->fcoe_pending_queue.lock);
 403
 404	if (skb)
 405		__skb_queue_tail(&port->fcoe_pending_queue, skb);
 406
 407	if (port->fcoe_pending_queue_active)
 408		goto out;
 409	port->fcoe_pending_queue_active = 1;
 410
 411	while (port->fcoe_pending_queue.qlen) {
 412		/* keep qlen > 0 until fcoe_start_io succeeds */
 413		port->fcoe_pending_queue.qlen++;
 414		skb = __skb_dequeue(&port->fcoe_pending_queue);
 415
 416		spin_unlock_bh(&port->fcoe_pending_queue.lock);
 417		rc = fcoe_start_io(skb);
 418		spin_lock_bh(&port->fcoe_pending_queue.lock);
 419
 420		if (rc) {
 421			__skb_queue_head(&port->fcoe_pending_queue, skb);
 422			/* undo temporary increment above */
 423			port->fcoe_pending_queue.qlen--;
 424			break;
 425		}
 426		/* undo temporary increment above */
 427		port->fcoe_pending_queue.qlen--;
 428	}
 429
 430	if (port->fcoe_pending_queue.qlen < port->min_queue_depth)
 431		lport->qfull = 0;
 432	if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer))
 433		mod_timer(&port->timer, jiffies + 2);
 434	port->fcoe_pending_queue_active = 0;
 435out:
 436	if (port->fcoe_pending_queue.qlen > port->max_queue_depth)
 437		lport->qfull = 1;
 438	spin_unlock_bh(&port->fcoe_pending_queue.lock);
 439}
 440EXPORT_SYMBOL_GPL(fcoe_check_wait_queue);
 441
 442/**
 443 * fcoe_queue_timer() - The fcoe queue timer
 444 * @t: Timer context use to obtain the FCoE port
 445 *
 446 * Calls fcoe_check_wait_queue on timeout
 447 */
 448void fcoe_queue_timer(struct timer_list *t)
 449{
 450	struct fcoe_port *port = timer_container_of(port, t, timer);
 451
 452	fcoe_check_wait_queue(port->lport, NULL);
 453}
 454EXPORT_SYMBOL_GPL(fcoe_queue_timer);
 455
 456/**
 457 * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC
 458 * @skb:  The packet to be transmitted
 459 * @tlen: The total length of the trailer
 460 * @fps:  The fcoe context
 461 *
 462 * This routine allocates a page for frame trailers. The page is re-used if
 463 * there is enough room left on it for the current trailer. If there isn't
 464 * enough buffer left a new page is allocated for the trailer. Reference to
 465 * the page from this function as well as the skbs using the page fragments
 466 * ensure that the page is freed at the appropriate time.
 467 *
 468 * Returns: 0 for success
 469 */
 470int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen,
 471			   struct fcoe_percpu_s *fps)
 472{
 473	struct page *page;
 474
 475	page = fps->crc_eof_page;
 476	if (!page) {
 477		page = alloc_page(GFP_ATOMIC);
 478		if (!page)
 479			return -ENOMEM;
 480
 481		fps->crc_eof_page = page;
 482		fps->crc_eof_offset = 0;
 483	}
 484
 485	get_page(page);
 486	skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
 487			   fps->crc_eof_offset, tlen);
 488	skb->len += tlen;
 489	skb->data_len += tlen;
 490	skb->truesize += tlen;
 491	fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
 492
 493	if (fps->crc_eof_offset >= PAGE_SIZE) {
 494		fps->crc_eof_page = NULL;
 495		fps->crc_eof_offset = 0;
 496		put_page(page);
 497	}
 498
 499	return 0;
 500}
 501EXPORT_SYMBOL_GPL(fcoe_get_paged_crc_eof);
 502
 503/**
 504 * fcoe_transport_lookup - find an fcoe transport that matches a netdev
 505 * @netdev: The netdev to look for from all attached transports
 506 *
 507 * Returns : ptr to the fcoe transport that supports this netdev or NULL
 508 * if not found.
 509 *
 510 * The ft_mutex should be held when this is called
 511 */
 512static struct fcoe_transport *fcoe_transport_lookup(struct net_device *netdev)
 513{
 514	struct fcoe_transport *ft = NULL;
 515
 516	list_for_each_entry(ft, &fcoe_transports, list)
 517		if (ft->match && ft->match(netdev))
 518			return ft;
 519	return NULL;
 520}
 521
 522/**
 523 * fcoe_transport_attach - Attaches an FCoE transport
 524 * @ft: The fcoe transport to be attached
 525 *
 526 * Returns : 0 for success
 527 */
 528int fcoe_transport_attach(struct fcoe_transport *ft)
 529{
 530	int rc = 0;
 531
 532	mutex_lock(&ft_mutex);
 533	if (ft->attached) {
 534		LIBFCOE_TRANSPORT_DBG("transport %s already attached\n",
 535				       ft->name);
 536		rc = -EEXIST;
 537		goto out_attach;
 538	}
 539
 540	/* Add default transport to the tail */
 541	if (strcmp(ft->name, FCOE_TRANSPORT_DEFAULT))
 542		list_add(&ft->list, &fcoe_transports);
 543	else
 544		list_add_tail(&ft->list, &fcoe_transports);
 545
 546	ft->attached = true;
 547	LIBFCOE_TRANSPORT_DBG("attaching transport %s\n", ft->name);
 548
 549out_attach:
 550	mutex_unlock(&ft_mutex);
 551	return rc;
 552}
 553EXPORT_SYMBOL(fcoe_transport_attach);
 554
 555/**
 556 * fcoe_transport_detach - Detaches an FCoE transport
 557 * @ft: The fcoe transport to be attached
 558 *
 559 * Returns : 0 for success
 560 */
 561int fcoe_transport_detach(struct fcoe_transport *ft)
 562{
 563	int rc = 0;
 564	struct fcoe_netdev_mapping *nm = NULL, *tmp;
 565
 566	mutex_lock(&ft_mutex);
 567	if (!ft->attached) {
 568		LIBFCOE_TRANSPORT_DBG("transport %s already detached\n",
 569			ft->name);
 570		rc = -ENODEV;
 571		goto out_attach;
 572	}
 573
 574	/* remove netdev mapping for this transport as it is going away */
 575	mutex_lock(&fn_mutex);
 576	list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
 577		if (nm->ft == ft) {
 578			LIBFCOE_TRANSPORT_DBG("transport %s going away, "
 579				"remove its netdev mapping for %s\n",
 580				ft->name, nm->netdev->name);
 581			list_del(&nm->list);
 582			kfree(nm);
 583		}
 584	}
 585	mutex_unlock(&fn_mutex);
 586
 587	list_del(&ft->list);
 588	ft->attached = false;
 589	LIBFCOE_TRANSPORT_DBG("detaching transport %s\n", ft->name);
 590
 591out_attach:
 592	mutex_unlock(&ft_mutex);
 593	return rc;
 594
 595}
 596EXPORT_SYMBOL(fcoe_transport_detach);
 597
 598static int fcoe_transport_show(char *buffer, const struct kernel_param *kp)
 599{
 600	int i, j;
 601	struct fcoe_transport *ft = NULL;
 602
 603	i = j = sprintf(buffer, "Attached FCoE transports:");
 604	mutex_lock(&ft_mutex);
 605	list_for_each_entry(ft, &fcoe_transports, list) {
 606		if (i >= PAGE_SIZE - IFNAMSIZ)
 607			break;
 608		i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name);
 609	}
 610	mutex_unlock(&ft_mutex);
 611	if (i == j)
 612		i += snprintf(&buffer[i], IFNAMSIZ, "none");
 613	return i;
 614}
 615
 616static int __init fcoe_transport_init(void)
 617{
 618	register_netdevice_notifier(&libfcoe_notifier);
 619	return 0;
 620}
 621
 622static int fcoe_transport_exit(void)
 623{
 624	struct fcoe_transport *ft;
 625
 626	unregister_netdevice_notifier(&libfcoe_notifier);
 627	mutex_lock(&ft_mutex);
 628	list_for_each_entry(ft, &fcoe_transports, list)
 629		printk(KERN_ERR "FCoE transport %s is still attached!\n",
 630		      ft->name);
 631	mutex_unlock(&ft_mutex);
 632	return 0;
 633}
 634
 635
 636static int fcoe_add_netdev_mapping(struct net_device *netdev,
 637					struct fcoe_transport *ft)
 638{
 639	struct fcoe_netdev_mapping *nm;
 640
 641	nm = kmalloc(sizeof(*nm), GFP_KERNEL);
 642	if (!nm) {
 643		printk(KERN_ERR "Unable to allocate netdev_mapping");
 644		return -ENOMEM;
 645	}
 646
 647	nm->netdev = netdev;
 648	nm->ft = ft;
 649
 650	mutex_lock(&fn_mutex);
 651	list_add(&nm->list, &fcoe_netdevs);
 652	mutex_unlock(&fn_mutex);
 653	return 0;
 654}
 655
 656
 657static void fcoe_del_netdev_mapping(struct net_device *netdev)
 658{
 659	struct fcoe_netdev_mapping *nm = NULL, *tmp;
 660
 661	mutex_lock(&fn_mutex);
 662	list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
 663		if (nm->netdev == netdev) {
 664			list_del(&nm->list);
 665			kfree(nm);
 666			mutex_unlock(&fn_mutex);
 667			return;
 668		}
 669	}
 670	mutex_unlock(&fn_mutex);
 671}
 672
 673
 674/**
 675 * fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on which
 676 * it was created
 677 * @netdev: The net device that the FCoE interface is on
 678 *
 679 * Returns : ptr to the fcoe transport that supports this netdev or NULL
 680 * if not found.
 681 *
 682 * The ft_mutex should be held when this is called
 683 */
 684static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *netdev)
 685{
 686	struct fcoe_transport *ft = NULL;
 687	struct fcoe_netdev_mapping *nm;
 688
 689	mutex_lock(&fn_mutex);
 690	list_for_each_entry(nm, &fcoe_netdevs, list) {
 691		if (netdev == nm->netdev) {
 692			ft = nm->ft;
 693			mutex_unlock(&fn_mutex);
 694			return ft;
 695		}
 696	}
 697
 698	mutex_unlock(&fn_mutex);
 699	return NULL;
 700}
 701
 702/**
 703 * fcoe_if_to_netdev() - Parse a name buffer to get a net device
 704 * @buffer: The name of the net device
 705 *
 706 * Returns: NULL or a ptr to net_device
 707 */
 708static struct net_device *fcoe_if_to_netdev(const char *buffer)
 709{
 710	char *cp;
 711	char ifname[IFNAMSIZ + 2];
 712
 713	if (buffer) {
 714		strscpy(ifname, buffer, IFNAMSIZ);
 715		cp = ifname + strlen(ifname);
 716		while (--cp >= ifname && *cp == '\n')
 717			*cp = '\0';
 718		return dev_get_by_name(&init_net, ifname);
 719	}
 720	return NULL;
 721}
 722
 723/**
 724 * libfcoe_device_notification() - Handler for net device events
 725 * @notifier: The context of the notification
 726 * @event:    The type of event
 727 * @ptr:      The net device that the event was on
 728 *
 729 * This function is called by the Ethernet driver in case of link change event.
 730 *
 731 * Returns: 0 for success
 732 */
 733static int libfcoe_device_notification(struct notifier_block *notifier,
 734				    ulong event, void *ptr)
 735{
 736	struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
 737
 738	switch (event) {
 739	case NETDEV_UNREGISTER:
 740		LIBFCOE_TRANSPORT_DBG("NETDEV_UNREGISTER %s\n",
 741				      netdev->name);
 742		fcoe_del_netdev_mapping(netdev);
 743		break;
 744	}
 745	return NOTIFY_OK;
 746}
 747
 748ssize_t fcoe_ctlr_create_store(const char *buf, size_t count)
 749{
 750	struct net_device *netdev = NULL;
 751	struct fcoe_transport *ft = NULL;
 752	int rc = 0;
 753	int err;
 754
 755	mutex_lock(&ft_mutex);
 756
 757	netdev = fcoe_if_to_netdev(buf);
 758	if (!netdev) {
 759		LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buf);
 760		rc = -ENODEV;
 761		goto out_nodev;
 762	}
 763
 764	ft = fcoe_netdev_map_lookup(netdev);
 765	if (ft) {
 766		LIBFCOE_TRANSPORT_DBG("transport %s already has existing "
 767				      "FCoE instance on %s.\n",
 768				      ft->name, netdev->name);
 769		rc = -EEXIST;
 770		goto out_putdev;
 771	}
 772
 773	ft = fcoe_transport_lookup(netdev);
 774	if (!ft) {
 775		LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
 776				      netdev->name);
 777		rc = -ENODEV;
 778		goto out_putdev;
 779	}
 780
 781	/* pass to transport create */
 782	err = ft->alloc ? ft->alloc(netdev) : -ENODEV;
 783	if (err) {
 784		fcoe_del_netdev_mapping(netdev);
 785		rc = -ENOMEM;
 786		goto out_putdev;
 787	}
 788
 789	err = fcoe_add_netdev_mapping(netdev, ft);
 790	if (err) {
 791		LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping "
 792				      "for FCoE transport %s for %s.\n",
 793				      ft->name, netdev->name);
 794		rc = -ENODEV;
 795		goto out_putdev;
 796	}
 797
 798	LIBFCOE_TRANSPORT_DBG("transport %s succeeded to create fcoe on %s.\n",
 799			      ft->name, netdev->name);
 800
 801out_putdev:
 802	dev_put(netdev);
 803out_nodev:
 804	mutex_unlock(&ft_mutex);
 805	if (rc)
 806		return rc;
 807	return count;
 808}
 809
 810ssize_t fcoe_ctlr_destroy_store(const char *buf, size_t count)
 811{
 812	int rc = -ENODEV;
 813	struct net_device *netdev = NULL;
 814	struct fcoe_transport *ft = NULL;
 815
 816	mutex_lock(&ft_mutex);
 817
 818	netdev = fcoe_if_to_netdev(buf);
 819	if (!netdev) {
 820		LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buf);
 821		goto out_nodev;
 822	}
 823
 824	ft = fcoe_netdev_map_lookup(netdev);
 825	if (!ft) {
 826		LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
 827				      netdev->name);
 828		goto out_putdev;
 829	}
 830
 831	/* pass to transport destroy */
 832	rc = ft->destroy(netdev);
 833	if (rc)
 834		goto out_putdev;
 835
 836	fcoe_del_netdev_mapping(netdev);
 837	LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n",
 838			      ft->name, (rc) ? "failed" : "succeeded",
 839			      netdev->name);
 840	rc = count; /* required for successful return */
 841out_putdev:
 842	dev_put(netdev);
 843out_nodev:
 844	mutex_unlock(&ft_mutex);
 845	return rc;
 846}
 847
 848/**
 849 * fcoe_transport_create() - Create a fcoe interface
 850 * @buffer: The name of the Ethernet interface to create on
 851 * @kp:	    The associated kernel param
 852 *
 853 * Called from sysfs. This holds the ft_mutex while calling the
 854 * registered fcoe transport's create function.
 855 *
 856 * Returns: 0 for success
 857 */
 858static int fcoe_transport_create(const char *buffer,
 859				 const struct kernel_param *kp)
 860{
 861	int rc = -ENODEV;
 862	struct net_device *netdev = NULL;
 863	struct fcoe_transport *ft = NULL;
 864	enum fip_mode fip_mode = (enum fip_mode)(uintptr_t)kp->arg;
 865
 866	mutex_lock(&ft_mutex);
 867
 868	netdev = fcoe_if_to_netdev(buffer);
 869	if (!netdev) {
 870		LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buffer);
 871		goto out_nodev;
 872	}
 873
 874	ft = fcoe_netdev_map_lookup(netdev);
 875	if (ft) {
 876		LIBFCOE_TRANSPORT_DBG("transport %s already has existing "
 877				      "FCoE instance on %s.\n",
 878				      ft->name, netdev->name);
 879		rc = -EEXIST;
 880		goto out_putdev;
 881	}
 882
 883	ft = fcoe_transport_lookup(netdev);
 884	if (!ft) {
 885		LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
 886				      netdev->name);
 887		goto out_putdev;
 888	}
 889
 890	rc = fcoe_add_netdev_mapping(netdev, ft);
 891	if (rc) {
 892		LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping "
 893				      "for FCoE transport %s for %s.\n",
 894				      ft->name, netdev->name);
 895		goto out_putdev;
 896	}
 897
 898	/* pass to transport create */
 899	rc = ft->create ? ft->create(netdev, fip_mode) : -ENODEV;
 900	if (rc)
 901		fcoe_del_netdev_mapping(netdev);
 902
 903	LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n",
 904			      ft->name, (rc) ? "failed" : "succeeded",
 905			      netdev->name);
 906
 907out_putdev:
 908	dev_put(netdev);
 909out_nodev:
 910	mutex_unlock(&ft_mutex);
 911	return rc;
 912}
 913
 914/**
 915 * fcoe_transport_destroy() - Destroy a FCoE interface
 916 * @buffer: The name of the Ethernet interface to be destroyed
 917 * @kp:	    The associated kernel parameter
 918 *
 919 * Called from sysfs. This holds the ft_mutex while calling the
 920 * registered fcoe transport's destroy function.
 921 *
 922 * Returns: 0 for success
 923 */
 924static int fcoe_transport_destroy(const char *buffer,
 925				  const struct kernel_param *kp)
 926{
 927	int rc = -ENODEV;
 928	struct net_device *netdev = NULL;
 929	struct fcoe_transport *ft = NULL;
 930
 931	mutex_lock(&ft_mutex);
 932
 933	netdev = fcoe_if_to_netdev(buffer);
 934	if (!netdev) {
 935		LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buffer);
 936		goto out_nodev;
 937	}
 938
 939	ft = fcoe_netdev_map_lookup(netdev);
 940	if (!ft) {
 941		LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
 942				      netdev->name);
 943		goto out_putdev;
 944	}
 945
 946	/* pass to transport destroy */
 947	rc = ft->destroy ? ft->destroy(netdev) : -ENODEV;
 948	fcoe_del_netdev_mapping(netdev);
 949	LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n",
 950			      ft->name, (rc) ? "failed" : "succeeded",
 951			      netdev->name);
 952
 953out_putdev:
 954	dev_put(netdev);
 955out_nodev:
 956	mutex_unlock(&ft_mutex);
 957	return rc;
 958}
 959
 960/**
 961 * fcoe_transport_disable() - Disables a FCoE interface
 962 * @buffer: The name of the Ethernet interface to be disabled
 963 * @kp:	    The associated kernel parameter
 964 *
 965 * Called from sysfs.
 966 *
 967 * Returns: 0 for success
 968 */
 969static int fcoe_transport_disable(const char *buffer,
 970				  const struct kernel_param *kp)
 971{
 972	int rc = -ENODEV;
 973	struct net_device *netdev = NULL;
 974	struct fcoe_transport *ft = NULL;
 975
 976	mutex_lock(&ft_mutex);
 977
 978	netdev = fcoe_if_to_netdev(buffer);
 979	if (!netdev)
 980		goto out_nodev;
 981
 982	ft = fcoe_netdev_map_lookup(netdev);
 983	if (!ft)
 984		goto out_putdev;
 985
 986	rc = ft->disable ? ft->disable(netdev) : -ENODEV;
 987
 988out_putdev:
 989	dev_put(netdev);
 990out_nodev:
 991	mutex_unlock(&ft_mutex);
 992	return rc;
 993}
 994
 995/**
 996 * fcoe_transport_enable() - Enables a FCoE interface
 997 * @buffer: The name of the Ethernet interface to be enabled
 998 * @kp:     The associated kernel parameter
 999 *
1000 * Called from sysfs.
1001 *
1002 * Returns: 0 for success
1003 */
1004static int fcoe_transport_enable(const char *buffer,
1005				 const struct kernel_param *kp)
1006{
1007	int rc = -ENODEV;
1008	struct net_device *netdev = NULL;
1009	struct fcoe_transport *ft = NULL;
1010
1011	mutex_lock(&ft_mutex);
1012
1013	netdev = fcoe_if_to_netdev(buffer);
1014	if (!netdev)
1015		goto out_nodev;
1016
1017	ft = fcoe_netdev_map_lookup(netdev);
1018	if (!ft)
1019		goto out_putdev;
1020
1021	rc = ft->enable ? ft->enable(netdev) : -ENODEV;
1022
1023out_putdev:
1024	dev_put(netdev);
1025out_nodev:
1026	mutex_unlock(&ft_mutex);
1027	return rc;
1028}
1029
1030/**
1031 * libfcoe_init() - Initialization routine for libfcoe.ko
1032 */
1033static int __init libfcoe_init(void)
1034{
1035	int rc = 0;
1036
1037	rc = fcoe_transport_init();
1038	if (rc)
1039		return rc;
1040
1041	rc = fcoe_sysfs_setup();
1042	if (rc)
1043		fcoe_transport_exit();
1044
1045	return rc;
1046}
1047module_init(libfcoe_init);
1048
1049/**
1050 * libfcoe_exit() - Tear down libfcoe.ko
1051 */
1052static void __exit libfcoe_exit(void)
1053{
1054	fcoe_sysfs_teardown();
1055	fcoe_transport_exit();
1056}
1057module_exit(libfcoe_exit);
~/ Read-only file preview.