/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * (C) Copyright 2020 Hewlett Packard Enterprise Development LP * Copyright (C) 1999-2009 Silicon Graphics, Inc. All rights reserved. */ /* * Cross Partition Network Interface (XPNET) support * * XPNET provides a virtual network layered on top of the Cross * Partition communication layer. * * XPNET provides direct point-to-point and broadcast-like support * for an ethernet-like device. The ethernet broadcast medium is * replaced with a point-to-point message structure which passes * pointers to a DMA-capable block that a remote partition should * retrieve and pass to the upper level networking layer. * */ #include <linux/slab.h> #include <linux/module.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include "xp.h" /* * The message payload transferred by XPC. * * buf_pa is the physical address where the DMA should pull from. * * NOTE: for performance reasons, buf_pa should _ALWAYS_ begin on a * cacheline boundary. To accomplish this, we record the number of * bytes from the beginning of the first cacheline to the first useful * byte of the skb (leadin_ignore) and the number of bytes from the * last useful byte of the skb to the end of the last cacheline * (tailout_ignore). * * size is the number of bytes to transfer which includes the skb->len * (useful bytes of the senders skb) plus the leadin and tailout */ struct xpnet_message { … }; /* * Determine the size of our message, the cacheline aligned size, * and then the number of message will request from XPC. * * XPC expects each message to exist in an individual cacheline. */ #define XPNET_MSG_SIZE … #define XPNET_MSG_DATA_MAX … #define XPNET_MSG_NENTRIES … #define XPNET_MAX_KTHREADS … #define XPNET_MAX_IDLE_KTHREADS … /* * Version number of XPNET implementation. XPNET can always talk to versions * with same major #, and never talk to versions with a different version. */ #define _XPNET_VERSION(_major, _minor) … #define XPNET_VERSION_MAJOR(_v) … #define XPNET_VERSION_MINOR(_v) … #define XPNET_VERSION … #define XPNET_VERSION_EMBED … #define XPNET_MAGIC … #define XPNET_VALID_MSG(_m) … #define XPNET_DEVICE_NAME … /* * When messages are queued with xpc_send_notify, a kmalloc'd buffer * of the following type is passed as a notification cookie. When the * notification function is called, we use the cookie to decide * whether all outstanding message sends have completed. The skb can * then be released. */ struct xpnet_pending_msg { … }; static struct net_device *xpnet_device; /* * When we are notified of other partitions activating, we add them to * our bitmask of partitions to which we broadcast. */ static unsigned long *xpnet_broadcast_partitions; /* protect above */ static DEFINE_SPINLOCK(xpnet_broadcast_lock); /* * Since the Block Transfer Engine (BTE) is being used for the transfer * and it relies upon cache-line size transfers, we need to reserve at * least one cache-line for head and tail alignment. The BTE is * limited to 8MB transfers. * * Testing has shown that changing MTU to greater than 64KB has no effect * on TCP as the two sides negotiate a Max Segment Size that is limited * to 64K. Other protocols May use packets greater than this, but for * now, the default is 64KB. */ #define XPNET_MAX_MTU … /* 68 comes from min TCP+IP+MAC header */ #define XPNET_MIN_MTU … /* 32KB has been determined to be the ideal */ #define XPNET_DEF_MTU … /* * The partid is encapsulated in the MAC address beginning in the following * octet and it consists of two octets. */ #define XPNET_PARTID_OCTET … /* Define the XPNET debug device structures to be used with dev_dbg() et al */ static struct device_driver xpnet_dbg_name = …; static struct device xpnet_dbg_subname = …; static struct device *xpnet = …; /* * Packet was recevied by XPC and forwarded to us. */ static void xpnet_receive(short partid, int channel, struct xpnet_message *msg) { … } /* * This is the handler which XPC calls during any sort of change in * state or message reception on a connection. */ static void xpnet_connection_activity(enum xp_retval reason, short partid, int channel, void *data, void *key) { … } static int xpnet_dev_open(struct net_device *dev) { … } static int xpnet_dev_stop(struct net_device *dev) { … } /* * Notification that the other end has received the message and * DMA'd the skb information. At this point, they are done with * our side. When all recipients are done processing, we * release the skb and then release our pending message structure. */ static void xpnet_send_completed(enum xp_retval reason, short partid, int channel, void *__qm) { … } static void xpnet_send(struct sk_buff *skb, struct xpnet_pending_msg *queued_msg, u64 start_addr, u64 end_addr, u16 embedded_bytes, int dest_partid) { … } /* * Network layer has formatted a packet (skb) and is ready to place it * "on the wire". Prepare and send an xpnet_message to all partitions * which have connected with us and are targets of this packet. * * MAC-NOTE: For the XPNET driver, the MAC address contains the * destination partid. If the destination partid octets are 0xffff, * this packet is to be broadcast to all connected partitions. */ static netdev_tx_t xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { … } /* * Deal with transmit timeouts coming from the network layer. */ static void xpnet_dev_tx_timeout(struct net_device *dev, unsigned int txqueue) { … } static const struct net_device_ops xpnet_netdev_ops = …; static int __init xpnet_init(void) { … } module_init(…) …; static void __exit xpnet_exit(void) { … } module_exit(xpnet_exit); MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …;