linux/drivers/net/usb/usbnet.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * USB Network driver infrastructure
 * Copyright (C) 2000-2005 by David Brownell
 * Copyright (C) 2003-2005 David Hollis <[email protected]>
 */

/*
 * This is a generic "USB networking" framework that works with several
 * kinds of full and high speed networking devices:  host-to-host cables,
 * smart usb peripherals, and actual Ethernet adapters.
 *
 * These devices usually differ in terms of control protocols (if they
 * even have one!) and sometimes they define new framing to wrap or batch
 * Ethernet packets.  Otherwise, they talk to USB pretty much the same,
 * so interface (un)binding, endpoint I/O queues, fault handling, and other
 * issues can usefully be addressed by this framework.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ctype.h>
#include <linux/ethtool.h>
#include <linux/workqueue.h>
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/usb/usbnet.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/pm_runtime.h>

/*-------------------------------------------------------------------------*/

/*
 * Nineteen USB 1.1 max size bulk transactions per frame (ms), max.
 * Several dozen bytes of IPv4 data can fit in two such transactions.
 * One maximum size Ethernet packet takes twenty four of them.
 * For high speed, each frame comfortably fits almost 36 max size
 * Ethernet packets (so queues should be bigger).
 *
 * The goal is to let the USB host controller be busy for 5msec or
 * more before an irq is required, under load.  Jumbograms change
 * the equation.
 */
#define MAX_QUEUE_MEMORY
#define RX_QLEN(dev)
#define TX_QLEN(dev)

// reawaken network queue this soon after stopping; else watchdog barks
#define TX_TIMEOUT_JIFFIES

/* throttle rx/tx briefly after some faults, so hub_wq might disconnect()
 * us (it polls at HZ/4 usually) before we report too many false errors.
 */
#define THROTTLE_JIFFIES

// between wakeups
#define UNLINK_TIMEOUT_MS

/*-------------------------------------------------------------------------*/

/* use ethtool to change the level for any given device */
static int msg_level =;
module_param (msg_level, int, 0);
MODULE_PARM_DESC();

/*-------------------------------------------------------------------------*/

static const char * const usbnet_event_names[] =;

/* handles CDC Ethernet and many other network "bulk data" interfaces */
int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
{}
EXPORT_SYMBOL_GPL();

int usbnet_get_ethernet_addr(struct usbnet *dev, int iMACAddress)
{}
EXPORT_SYMBOL_GPL();

static void intr_complete (struct urb *urb)
{}

static int init_status (struct usbnet *dev, struct usb_interface *intf)
{}

/* Submit the interrupt URB if not previously submitted, increasing refcount */
int usbnet_status_start(struct usbnet *dev, gfp_t mem_flags)
{}
EXPORT_SYMBOL_GPL();

/* For resume; submit interrupt URB if previously submitted */
static int __usbnet_status_start_force(struct usbnet *dev, gfp_t mem_flags)
{}

/* Kill the interrupt URB if all submitters want it killed */
void usbnet_status_stop(struct usbnet *dev)
{}
EXPORT_SYMBOL_GPL();

/* For suspend; always kill interrupt URB */
static void __usbnet_status_stop_force(struct usbnet *dev)
{}

/* Passes this packet up the stack, updating its accounting.
 * Some link protocols batch packets, so their rx_fixup paths
 * can return clones as well as just modify the original skb.
 */
void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
{}
EXPORT_SYMBOL_GPL();

/* must be called if hard_mtu or rx_urb_size changed */
void usbnet_update_max_qlen(struct usbnet *dev)
{}
EXPORT_SYMBOL_GPL();


/*-------------------------------------------------------------------------
 *
 * Network Device Driver (peer link to "Host Device", from USB host)
 *
 *-------------------------------------------------------------------------*/

int usbnet_change_mtu (struct net_device *net, int new_mtu)
{}
EXPORT_SYMBOL_GPL();

/* The caller must hold list->lock */
static void __usbnet_queue_skb(struct sk_buff_head *list,
			struct sk_buff *newsk, enum skb_state state)
{}

/*-------------------------------------------------------------------------*/

/* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from
 * completion callbacks.  2.5 should have fixed those bugs...
 */

static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
		struct sk_buff_head *list, enum skb_state state)
{}

/* some work can't be done in tasklets, so we use keventd
 *
 * NOTE:  annoying asymmetry:  if it's active, schedule_work() fails,
 * but tasklet_schedule() doesn't.  hope the failure is rare.
 */
void usbnet_defer_kevent (struct usbnet *dev, int work)
{}
EXPORT_SYMBOL_GPL();

/*-------------------------------------------------------------------------*/

static void rx_complete (struct urb *urb);

static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
{}


/*-------------------------------------------------------------------------*/

static inline int rx_process(struct usbnet *dev, struct sk_buff *skb)
{}

/*-------------------------------------------------------------------------*/

static void rx_complete (struct urb *urb)
{}

/*-------------------------------------------------------------------------*/
void usbnet_pause_rx(struct usbnet *dev)
{}
EXPORT_SYMBOL_GPL();

void usbnet_resume_rx(struct usbnet *dev)
{}
EXPORT_SYMBOL_GPL();

void usbnet_purge_paused_rxq(struct usbnet *dev)
{}
EXPORT_SYMBOL_GPL();

/*-------------------------------------------------------------------------*/

// unlink pending rx/tx; completion handlers do all other cleanup

static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
{}

// Flush all pending rx urbs
// minidrivers may need to do this when the MTU changes

void usbnet_unlink_rx_urbs(struct usbnet *dev)
{}
EXPORT_SYMBOL_GPL();

/*-------------------------------------------------------------------------*/

static void wait_skb_queue_empty(struct sk_buff_head *q)
{}

// precondition: never called in_interrupt
static void usbnet_terminate_urbs(struct usbnet *dev)
{}

int usbnet_stop (struct net_device *net)
{}
EXPORT_SYMBOL_GPL();

/*-------------------------------------------------------------------------*/

// posts reads, and enables write queuing

// precondition: never called in_interrupt

int usbnet_open (struct net_device *net)
{}
EXPORT_SYMBOL_GPL();

/*-------------------------------------------------------------------------*/

/* ethtool methods; minidrivers may need to add some more, but
 * they'll probably want to use this base set.
 */

/* These methods are written on the assumption that the device
 * uses MII
 */
int usbnet_get_link_ksettings_mii(struct net_device *net,
			      struct ethtool_link_ksettings *cmd)
{}
EXPORT_SYMBOL_GPL();

int usbnet_get_link_ksettings_internal(struct net_device *net,
					struct ethtool_link_ksettings *cmd)
{}
EXPORT_SYMBOL_GPL();

int usbnet_set_link_ksettings_mii(struct net_device *net,
			      const struct ethtool_link_ksettings *cmd)
{}
EXPORT_SYMBOL_GPL();

u32 usbnet_get_link (struct net_device *net)
{}
EXPORT_SYMBOL_GPL();

int usbnet_nway_reset(struct net_device *net)
{}
EXPORT_SYMBOL_GPL();

void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
{}
EXPORT_SYMBOL_GPL();

u32 usbnet_get_msglevel (struct net_device *net)
{}
EXPORT_SYMBOL_GPL();

void usbnet_set_msglevel (struct net_device *net, u32 level)
{}
EXPORT_SYMBOL_GPL();

/* drivers may override default ethtool_ops in their bind() routine */
static const struct ethtool_ops usbnet_ethtool_ops =;

/*-------------------------------------------------------------------------*/

static void __handle_link_change(struct usbnet *dev)
{}

void usbnet_set_rx_mode(struct net_device *net)
{}
EXPORT_SYMBOL_GPL();

static void __handle_set_rx_mode(struct usbnet *dev)
{}

/* work that cannot be done in interrupt context uses keventd.
 *
 * NOTE:  with 2.5 we could do more of this using completion callbacks,
 * especially now that control transfers can be queued.
 */
static void
usbnet_deferred_kevent (struct work_struct *work)
{}

/*-------------------------------------------------------------------------*/

static void tx_complete (struct urb *urb)
{}

/*-------------------------------------------------------------------------*/

void usbnet_tx_timeout (struct net_device *net, unsigned int txqueue)
{}
EXPORT_SYMBOL_GPL();

/*-------------------------------------------------------------------------*/

static int build_dma_sg(const struct sk_buff *skb, struct urb *urb)
{}

netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
				     struct net_device *net)
{}
EXPORT_SYMBOL_GPL();

static int rx_alloc_submit(struct usbnet *dev, gfp_t flags)
{}

static inline void usb_free_skb(struct sk_buff *skb)
{}

/*-------------------------------------------------------------------------*/

// tasklet (work deferred from completions, in_irq) or timer

static void usbnet_bh (struct timer_list *t)
{}

static void usbnet_bh_tasklet(struct tasklet_struct *t)
{}


/*-------------------------------------------------------------------------
 *
 * USB Device Driver support
 *
 *-------------------------------------------------------------------------*/

// precondition: never called in_interrupt

void usbnet_disconnect (struct usb_interface *intf)
{}
EXPORT_SYMBOL_GPL();

static const struct net_device_ops usbnet_netdev_ops =;

/*-------------------------------------------------------------------------*/

// precondition: never called in_interrupt

static const struct device_type wlan_type =;

static const struct device_type wwan_type =;

int
usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
{}
EXPORT_SYMBOL_GPL();

/*-------------------------------------------------------------------------*/

/*
 * suspend the whole driver as soon as the first interface is suspended
 * resume only when the last interface is resumed
 */

int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
{}
EXPORT_SYMBOL_GPL();

int usbnet_resume (struct usb_interface *intf)
{}
EXPORT_SYMBOL_GPL();

/*
 * Either a subdriver implements manage_power, then it is assumed to always
 * be ready to be suspended or it reports the readiness to be suspended
 * explicitly
 */
void usbnet_device_suggests_idle(struct usbnet *dev)
{}
EXPORT_SYMBOL();

/*
 * For devices that can do without special commands
 */
int usbnet_manage_power(struct usbnet *dev, int on)
{}
EXPORT_SYMBOL();

void usbnet_link_change(struct usbnet *dev, bool link, bool need_reset)
{}
EXPORT_SYMBOL();

/*-------------------------------------------------------------------------*/
static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
			     u16 value, u16 index, void *data, u16 size)
{}

static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
			      u16 value, u16 index, const void *data,
			      u16 size)
{}

/*
 * The function can't be called inside suspend/resume callback,
 * otherwise deadlock will be caused.
 */
int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
		    u16 value, u16 index, void *data, u16 size)
{}
EXPORT_SYMBOL_GPL();

/*
 * The function can't be called inside suspend/resume callback,
 * otherwise deadlock will be caused.
 */
int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
		     u16 value, u16 index, const void *data, u16 size)
{}
EXPORT_SYMBOL_GPL();

/*
 * The function can be called inside suspend/resume callback safely
 * and should only be called by suspend/resume callback generally.
 */
int usbnet_read_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
			  u16 value, u16 index, void *data, u16 size)
{}
EXPORT_SYMBOL_GPL();

/*
 * The function can be called inside suspend/resume callback safely
 * and should only be called by suspend/resume callback generally.
 */
int usbnet_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
			  u16 value, u16 index, const void *data,
			  u16 size)
{}
EXPORT_SYMBOL_GPL();

static void usbnet_async_cmd_cb(struct urb *urb)
{}

/*
 * The caller must make sure that device can't be put into suspend
 * state until the control URB completes.
 */
int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
			   u16 value, u16 index, const void *data, u16 size)
{}
EXPORT_SYMBOL_GPL();
/*-------------------------------------------------------------------------*/

static int __init usbnet_init(void)
{}
module_init();

static void __exit usbnet_exit(void)
{}
module_exit(usbnet_exit);

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();