// SPDX-License-Identifier: GPL-2.0+
/******************************************************************************
* usbatm.c - Generic USB xDSL driver core
*
* Copyright (C) 2001, Alcatel
* Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas
* Copyright (C) 2004, David Woodhouse, Roman Kagan
******************************************************************************/
/*
* Written by Johan Verrept, Duncan Sands (duncan.sands@free.fr) and David Woodhouse
*
* 1.7+: - See the check-in logs
*
* 1.6: - No longer opens a connection if the firmware is not loaded
* - Added support for the speedtouch 330
* - Removed the limit on the number of devices
* - Module now autoloads on device plugin
* - Merged relevant parts of sarlib
* - Replaced the kernel thread with a tasklet
* - New packet transmission code
* - Changed proc file contents
* - Fixed all known SMP races
* - Many fixes and cleanups
* - Various fixes by Oliver Neukum (oliver@neukum.name)
*
* 1.5A: - Version for inclusion in 2.5 series kernel
* - Modifications by Richard Purdie (rpurdie@rpsys.net)
* - made compatible with kernel 2.5.6 onwards by changing
* usbatm_usb_send_data_context->urb to a pointer and adding code
* to alloc and free it
* - remove_wait_queue() added to usbatm_atm_processqueue_thread()
*
* 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL.
* (reported by stephen.robinson@zen.co.uk)
*
* 1.4: - changed the spin_lock() under interrupt to spin_lock_irqsave()
* - unlink all active send urbs of a vcc that is being closed.
*
* 1.3.1: - added the version number
*
* 1.3: - Added multiple send urb support
* - fixed memory leak and vcc->tx_inuse starvation bug
* when not enough memory left in vcc.
*
* 1.2: - Fixed race condition in usbatm_usb_send_data()
* 1.1: - Turned off packet debugging
*
*/
#include "usbatm.h"
#include <linux/uaccess.h>
#include <linux/crc32.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
#include <linux/sched/signal.h>
#include <linux/signal.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/timer.h>
#include <linux/wait.h>
#include <linux/kthread.h>
#include <linux/ratelimit.h>
#ifdef VERBOSE_DEBUG
static int usbatm_print_packet(struct usbatm_data *instance, const unsigned char *data, int len);
#define PACKETDEBUG(arg...) usbatm_print_packet(arg)
#define vdbg(arg...) dev_dbg(arg)
#else
#define PACKETDEBUG(arg...)
#define vdbg(arg...)
#endif
#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
#define DRIVER_DESC "Generic USB ATM/DSL I/O"
static const char usbatm_driver_name[] = "usbatm";
#define UDSL_MAX_RCV_URBS 16
#define UDSL_MAX_SND_URBS 16
#define UDSL_MAX_BUF_SIZE 65536
#define UDSL_DEFAULT_RCV_URBS 4
#define UDSL_DEFAULT_SND_URBS 4
#define UDSL_DEFAULT_RCV_BUF_SIZE 3392 /* 64 * ATM_CELL_SIZE */
#define UDSL_DEFAULT_SND_BUF_SIZE 3392 /* 64 * ATM_CELL_SIZE */
#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
#define THROTTLE_MSECS 100 /* delay to recover processing after urb submission fails */
static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS;
static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS;
static unsigned int rcv_buf_bytes = UDSL_DEFAULT_RCV_BUF_SIZE;
static unsigned int snd_buf_bytes = UDSL_DEFAULT_SND_BUF_SIZE;
module_param(num_rcv_urbs, uint, S_IRUGO);
MODULE_PARM_DESC(num_rcv_urbs,
"Number of urbs used for reception (range: 0-"
__MODULE_STRING(UDSL_MAX_RCV_URBS) ", default: "
__MODULE_STRING(UDSL_DEFAULT_RCV_URBS) ")");
module_param(num_snd_urbs, uint, S_IRUGO);
MODULE_PARM_DESC(num_snd_urbs,
"Number of urbs used for transmission (range: 0-"
__MODULE_STRING(UDSL_MAX_SND_URBS) ", default: "
__MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")");
module_param(rcv_buf_bytes, uint, S_IRUGO);
MODULE_PARM_DESC(rcv_buf_bytes,
"Size of the buffers used for reception, in bytes (range: 1-"
__MODULE_STRING(UDSL_MAX_BUF_SIZE) ", default: "
__MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")");
module_param