rtl8150.c 20 KB
Newer Older
Petko Manolov's avatar
USB  
Petko Manolov committed
1
/*
Petko Manolov's avatar
Petko Manolov committed
2
 *  Copyright (c) 2002 Petko Manolov (petkan@users.sourceforge.net)
Petko Manolov's avatar
USB  
Petko Manolov committed
3
 *
Petko Manolov's avatar
Petko Manolov committed
4 5 6
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
Petko Manolov's avatar
USB  
Petko Manolov committed
7 8 9 10
 */

#include <linux/config.h>
#include <linux/sched.h>
Petko Manolov's avatar
Petko Manolov committed
11
#include <linux/init.h>
Petko Manolov's avatar
USB  
Petko Manolov committed
12 13 14 15 16 17 18 19 20 21 22
#include <linux/signal.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/usb.h>
#include <asm/uaccess.h>

/* Version Information */
Petko Manolov's avatar
Petko Manolov committed
23
#define DRIVER_VERSION "v0.5.7 (2002/12/31)"
Petko Manolov's avatar
USB  
Petko Manolov committed
24 25 26
#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
#define DRIVER_DESC "rtl8150 based usb-ethernet driver"

Petko Manolov's avatar
Petko Manolov committed
27
#define	IDR			0x0120
Petko Manolov's avatar
USB  
Petko Manolov committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
#define	MAR			0x0126
#define	CR			0x012e
#define	TCR			0x012f
#define	RCR			0x0130
#define	TSR			0x0132
#define	RSR			0x0133
#define	CON0			0x0135
#define	CON1			0x0136
#define	MSR			0x0137
#define	PHYADD			0x0138
#define	PHYDAT			0x0139
#define	PHYCNT			0x013b
#define	GPPC			0x013d
#define	BMCR			0x0140
#define	BMSR			0x0142
#define	ANAR			0x0144
#define	ANLP			0x0146
#define	AER			0x0148

Petko Manolov's avatar
Petko Manolov committed
47 48
#define	IDR_EEPROM		0x1202

Petko Manolov's avatar
USB  
Petko Manolov committed
49 50 51 52
#define	PHY_READ		0
#define	PHY_WRITE		0x20
#define	PHY_GO			0x40

Petko Manolov's avatar
Petko Manolov committed
53 54
#define	MII_TIMEOUT		10

Petko Manolov's avatar
USB  
Petko Manolov committed
55 56 57 58 59
#define	RTL8150_REQT_READ	0xc0
#define	RTL8150_REQT_WRITE	0x40
#define	RTL8150_REQ_GET_REGS	0x05
#define	RTL8150_REQ_SET_REGS	0x05

Petko Manolov's avatar
Petko Manolov committed
60
#define	RTL8150_MTU		1540
Petko Manolov's avatar
USB  
Petko Manolov committed
61
#define	RTL8150_TX_TIMEOUT	(HZ)
Petko Manolov's avatar
Petko Manolov committed
62
#define	RX_SKB_POOL_SIZE	4
Petko Manolov's avatar
USB  
Petko Manolov committed
63 64

/* rtl8150 flags */
Petko Manolov's avatar
Petko Manolov committed
65
#define	RTL8150_HW_CRC		0
Petko Manolov's avatar
USB  
Petko Manolov committed
66
#define	RX_REG_SET		1
Petko Manolov's avatar
Petko Manolov committed
67
#define	RTL8150_UNPLUG		2
68
#define	RX_URB_FAIL		3
Petko Manolov's avatar
USB  
Petko Manolov committed
69 70 71

/* Define these values to match your device */
#define VENDOR_ID_REALTEK		0x0bda
Petko Manolov's avatar
Petko Manolov committed
72 73
#define	VENDOR_ID_MELCO			0x0411

Petko Manolov's avatar
USB  
Petko Manolov committed
74
#define PRODUCT_ID_RTL8150		0x8150
Petko Manolov's avatar
Petko Manolov committed
75
#define	PRODUCT_ID_LUAKTX		0x0012
Petko Manolov's avatar
USB  
Petko Manolov committed
76

Petko Manolov's avatar
Petko Manolov committed
77 78
#undef	EEPROM_WRITE

Petko Manolov's avatar
USB  
Petko Manolov committed
79
/* table of devices that work with this driver */
Petko Manolov's avatar
Petko Manolov committed
80 81
static struct usb_device_id rtl8150_table[] = {
	{USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8150)},
Petko Manolov's avatar
Petko Manolov committed
82
	{USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)},
Petko Manolov's avatar
Petko Manolov committed
83
	{}
Petko Manolov's avatar
USB  
Petko Manolov committed
84 85
};

Petko Manolov's avatar
Petko Manolov committed
86
MODULE_DEVICE_TABLE(usb, rtl8150_table);
Petko Manolov's avatar
USB  
Petko Manolov committed
87 88

struct rtl8150 {
Petko Manolov's avatar
Petko Manolov committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
	unsigned long flags;
	struct usb_device *udev;
	struct semaphore sem;
	struct tasklet_struct tl;
	struct net_device_stats stats;
	struct net_device *netdev;
	struct urb *rx_urb, *tx_urb, *intr_urb, *ctrl_urb;
	struct sk_buff *tx_skb, *rx_skb;
	struct sk_buff *rx_skb_pool[RX_SKB_POOL_SIZE];
	spinlock_t rx_pool_lock;
	struct usb_ctrlrequest dr;
	int intr_interval;
	u16 rx_creg;
	u8 intr_buff[8];
	u8 phy;
Petko Manolov's avatar
USB  
Petko Manolov committed
104 105
};

Petko Manolov's avatar
Petko Manolov committed
106
typedef struct rtl8150 rtl8150_t;
Petko Manolov's avatar
USB  
Petko Manolov committed
107 108 109

unsigned long multicast_filter_limit = 32;

Petko Manolov's avatar
Petko Manolov committed
110 111
static void fill_skb_pool(rtl8150_t *);
static void free_skb_pool(rtl8150_t *);
Petko Manolov's avatar
Petko Manolov committed
112
static inline struct sk_buff *pull_skb(rtl8150_t *);
113 114
static void rtl8150_disconnect(struct usb_interface *intf);
static int rtl8150_probe(struct usb_interface *intf,
Petko Manolov's avatar
Petko Manolov committed
115
			   const struct usb_device_id *id);
Petko Manolov's avatar
USB  
Petko Manolov committed
116 117

static struct usb_driver rtl8150_driver = {
118 119 120 121
	.name =		"rtl8150",
	.probe =	rtl8150_probe,
	.disconnect =	rtl8150_disconnect,
	.id_table =	rtl8150_table,
Petko Manolov's avatar
USB  
Petko Manolov committed
122 123 124 125 126 127 128
};

/*
**
**	device related part of the code
**
*/
Petko Manolov's avatar
Petko Manolov committed
129
static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
Petko Manolov's avatar
USB  
Petko Manolov committed
130
{
Petko Manolov's avatar
Petko Manolov committed
131 132 133
	return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
			       RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
			       indx, 0, data, size, HZ / 2);
Petko Manolov's avatar
USB  
Petko Manolov committed
134 135
}

Petko Manolov's avatar
Petko Manolov committed
136
static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
Petko Manolov's avatar
USB  
Petko Manolov committed
137
{
Petko Manolov's avatar
Petko Manolov committed
138 139 140
	return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
			       RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
			       indx, 0, data, size, HZ / 2);
Petko Manolov's avatar
USB  
Petko Manolov committed
141 142
}

David S. Miller's avatar
David S. Miller committed
143
static void ctrl_callback(struct urb *urb, struct pt_regs *regs)
Petko Manolov's avatar
USB  
Petko Manolov committed
144
{
Petko Manolov's avatar
Petko Manolov committed
145 146
	rtl8150_t *dev;

Petko Manolov's avatar
USB  
Petko Manolov committed
147 148 149 150 151 152 153 154 155 156 157 158 159 160
	switch (urb->status) {
	case 0:
		break;
	case -EINPROGRESS:
		break;
	case -ENOENT:
		break;
	default:
		warn("ctrl urb status %d", urb->status);
	}
	dev = urb->context;
	clear_bit(RX_REG_SET, &dev->flags);
}

161
static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size)
Petko Manolov's avatar
USB  
Petko Manolov committed
162
{
Petko Manolov's avatar
Petko Manolov committed
163
	int ret;
Petko Manolov's avatar
USB  
Petko Manolov committed
164

Petko Manolov's avatar
Petko Manolov committed
165
	if (test_bit(RX_REG_SET, &dev->flags))
Petko Manolov's avatar
USB  
Petko Manolov committed
166
		return -EAGAIN;
Petko Manolov's avatar
Petko Manolov committed
167

Petko Manolov's avatar
USB  
Petko Manolov committed
168 169 170 171 172 173
	dev->dr.bRequestType = RTL8150_REQT_WRITE;
	dev->dr.bRequest = RTL8150_REQ_SET_REGS;
	dev->dr.wValue = cpu_to_le16(indx);
	dev->dr.wIndex = 0;
	dev->dr.wLength = cpu_to_le16(size);
	dev->ctrl_urb->transfer_buffer_length = size;
174
	usb_fill_control_urb(dev->ctrl_urb, dev->udev,
Petko Manolov's avatar
Petko Manolov committed
175 176
			 usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr,
			 &dev->rx_creg, size, ctrl_callback, dev);
Petko Manolov's avatar
USB  
Petko Manolov committed
177 178 179 180 181 182 183 184
	if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC)))
		err("control request submission failed: %d", ret);
	else
		set_bit(RX_REG_SET, &dev->flags);

	return ret;
}

Petko Manolov's avatar
Petko Manolov committed
185
static int read_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 * reg)
Petko Manolov's avatar
USB  
Petko Manolov committed
186
{
Petko Manolov's avatar
Petko Manolov committed
187 188
	int i;
	u8 data[3], tmp;
Petko Manolov's avatar
USB  
Petko Manolov committed
189 190 191 192 193 194 195 196 197 198

	data[0] = phy;
	data[1] = data[2] = 0;
	tmp = indx | PHY_READ | PHY_GO;
	i = 0;

	set_registers(dev, PHYADD, sizeof(data), data);
	set_registers(dev, PHYCNT, 1, &tmp);
	do {
		get_registers(dev, PHYCNT, 1, data);
Petko Manolov's avatar
Petko Manolov committed
199
	} while ((data[0] & PHY_GO) && (i++ < MII_TIMEOUT));
Petko Manolov's avatar
USB  
Petko Manolov committed
200

Petko Manolov's avatar
Petko Manolov committed
201
	if (i < MII_TIMEOUT) {
Petko Manolov's avatar
USB  
Petko Manolov committed
202 203 204 205 206 207 208
		get_registers(dev, PHYDAT, 2, data);
		*reg = le16_to_cpup(data);
		return 0;
	} else
		return 1;
}

Petko Manolov's avatar
Petko Manolov committed
209
static int write_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 reg)
Petko Manolov's avatar
USB  
Petko Manolov committed
210
{
Petko Manolov's avatar
Petko Manolov committed
211 212
	int i;
	u8 data[3], tmp;
Petko Manolov's avatar
USB  
Petko Manolov committed
213 214 215 216 217 218 219 220 221 222

	data[0] = phy;
	*(data + 1) = cpu_to_le16p(&reg);
	tmp = indx | PHY_WRITE | PHY_GO;
	i = 0;

	set_registers(dev, PHYADD, sizeof(data), data);
	set_registers(dev, PHYCNT, 1, &tmp);
	do {
		get_registers(dev, PHYCNT, 1, data);
Petko Manolov's avatar
Petko Manolov committed
223
	} while ((data[0] & PHY_GO) && (i++ < MII_TIMEOUT));
Petko Manolov's avatar
USB  
Petko Manolov committed
224

Petko Manolov's avatar
Petko Manolov committed
225
	if (i < MII_TIMEOUT)
Petko Manolov's avatar
USB  
Petko Manolov committed
226 227 228 229 230
		return 0;
	else
		return 1;
}

Petko Manolov's avatar
Petko Manolov committed
231
static inline void set_ethernet_addr(rtl8150_t * dev)
Petko Manolov's avatar
USB  
Petko Manolov committed
232
{
Petko Manolov's avatar
Petko Manolov committed
233
	u8 node_id[6];
Petko Manolov's avatar
USB  
Petko Manolov committed
234

Petko Manolov's avatar
Petko Manolov committed
235
	get_registers(dev, IDR, sizeof(node_id), node_id);
Petko Manolov's avatar
USB  
Petko Manolov committed
236 237 238
	memcpy(dev->netdev->dev_addr, node_id, sizeof(node_id));
}

Petko Manolov's avatar
Petko Manolov committed
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
static int rtl8150_set_mac_address(struct net_device *netdev, void *p)
{
	struct sockaddr *addr = p;
	rtl8150_t *dev;
	int i;

	if (netif_running(netdev))
		return -EBUSY;
	dev = netdev->priv;
	if (dev == NULL) {
		return -ENODEV;
	}
	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
	dbg("%s: Setting MAC address to ", netdev->name);
	for (i = 0; i < 5; i++)
		dbg("%02X:", netdev->dev_addr[i]);
	dbg("%02X\n", netdev->dev_addr[i]);
	/* Set the IDR registers. */
	set_registers(dev, IDR, sizeof(netdev->dev_addr), netdev->dev_addr);
#ifdef EEPROM_WRITE
	{
	u8 cr;
	/* Get the CR contents. */
	get_registers(dev, CR, 1, &cr);
	/* Set the WEPROM bit (eeprom write enable). */
	cr |= 0x20;
	set_registers(dev, CR, 1, &cr);
	/* Write the MAC address into eeprom. Eeprom writes must be word-sized,
	   so we need to split them up. */
	for (i = 0; i * 2 < netdev->addr_len; i++) {
		set_registers(dev, IDR_EEPROM + (i * 2), 2, 
		netdev->dev_addr + (i * 2));
	}
	/* Clear the WEPROM bit (preventing accidental eeprom writes). */
	cr &= 0xdf;
	set_registers(dev, CR, 1, &cr);
	}
#endif
	return 0;
}

Petko Manolov's avatar
Petko Manolov committed
280
static int rtl8150_reset(rtl8150_t * dev)
Petko Manolov's avatar
USB  
Petko Manolov committed
281
{
Petko Manolov's avatar
Petko Manolov committed
282 283
	u8 data = 0x10;
	int i = HZ;
Petko Manolov's avatar
USB  
Petko Manolov committed
284 285 286 287 288 289

	set_registers(dev, CR, 1, &data);
	do {
		get_registers(dev, CR, 1, &data);
	} while ((data & 0x10) && --i);

Petko Manolov's avatar
Petko Manolov committed
290 291
	return (i > 0) ? 1 : 0;
}
Petko Manolov's avatar
USB  
Petko Manolov committed
292

Petko Manolov's avatar
Petko Manolov committed
293
static int alloc_all_urbs(rtl8150_t * dev)
Petko Manolov's avatar
USB  
Petko Manolov committed
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
{
	dev->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->rx_urb)
		return 0;
	dev->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->tx_urb) {
		usb_free_urb(dev->rx_urb);
		return 0;
	}
	dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->intr_urb) {
		usb_free_urb(dev->rx_urb);
		usb_free_urb(dev->tx_urb);
		return 0;
	}
	dev->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->intr_urb) {
		usb_free_urb(dev->rx_urb);
		usb_free_urb(dev->tx_urb);
		usb_free_urb(dev->intr_urb);
		return 0;
	}

	return 1;
}

Petko Manolov's avatar
Petko Manolov committed
320
static void free_all_urbs(rtl8150_t * dev)
Petko Manolov's avatar
USB  
Petko Manolov committed
321 322 323 324 325 326 327
{
	usb_free_urb(dev->rx_urb);
	usb_free_urb(dev->tx_urb);
	usb_free_urb(dev->intr_urb);
	usb_free_urb(dev->ctrl_urb);
}

Petko Manolov's avatar
Petko Manolov committed
328
static void unlink_all_urbs(rtl8150_t * dev)
Petko Manolov's avatar
USB  
Petko Manolov committed
329 330 331 332 333 334 335
{
	usb_unlink_urb(dev->rx_urb);
	usb_unlink_urb(dev->tx_urb);
	usb_unlink_urb(dev->intr_urb);
	usb_unlink_urb(dev->ctrl_urb);
}

David S. Miller's avatar
David S. Miller committed
336
static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
Petko Manolov's avatar
USB  
Petko Manolov committed
337
{
Petko Manolov's avatar
Petko Manolov committed
338 339 340
	rtl8150_t *dev;
	unsigned pkt_len, res;
	struct sk_buff *skb;
Petko Manolov's avatar
USB  
Petko Manolov committed
341
	struct net_device *netdev;
Petko Manolov's avatar
Petko Manolov committed
342
	u16 rx_stat;
Petko Manolov's avatar
USB  
Petko Manolov committed
343 344

	dev = urb->context;
345 346 347
	if (!dev)
		return;
	if (test_bit(RTL8150_UNPLUG, &dev->flags))
Petko Manolov's avatar
USB  
Petko Manolov committed
348 349
		return;
	netdev = dev->netdev;
350
	if (!netif_device_present(netdev))
Petko Manolov's avatar
USB  
Petko Manolov committed
351
		return;
352

Petko Manolov's avatar
USB  
Petko Manolov committed
353 354 355 356
	switch (urb->status) {
	case 0:
		break;
	case -ENOENT:
Petko Manolov's avatar
Petko Manolov committed
357
		return;	/* the urb is in unlink state */
Petko Manolov's avatar
USB  
Petko Manolov committed
358
	case -ETIMEDOUT:
Petko Manolov's avatar
Petko Manolov committed
359
		warn("may be reset is needed?..");
Petko Manolov's avatar
Petko Manolov committed
360
		goto goon;
Petko Manolov's avatar
USB  
Petko Manolov committed
361 362 363 364 365
	default:
		warn("Rx status %d", urb->status);
		goto goon;
	}

Petko Manolov's avatar
Petko Manolov committed
366 367
	if (!dev->rx_skb)
		goto resched;
Petko Manolov's avatar
Petko Manolov committed
368

Petko Manolov's avatar
Petko Manolov committed
369
	res = urb->actual_length;
Petko Manolov's avatar
Petko Manolov committed
370
	rx_stat = le16_to_cpu(*(short *)(urb->transfer_buffer + res - 4));
Petko Manolov's avatar
Petko Manolov committed
371 372
	pkt_len = res - 4;

Petko Manolov's avatar
Petko Manolov committed
373 374 375
	skb_put(dev->rx_skb, pkt_len);
	dev->rx_skb->protocol = eth_type_trans(dev->rx_skb, netdev);
	netif_rx(dev->rx_skb);
Petko Manolov's avatar
USB  
Petko Manolov committed
376 377
	dev->stats.rx_packets++;
	dev->stats.rx_bytes += pkt_len;
Petko Manolov's avatar
Petko Manolov committed
378 379

	spin_lock(&dev->rx_pool_lock);
Petko Manolov's avatar
Petko Manolov committed
380
	skb = pull_skb(dev);
Petko Manolov's avatar
Petko Manolov committed
381
	spin_unlock(&dev->rx_pool_lock);
Petko Manolov's avatar
Petko Manolov committed
382 383
	if (!skb)
		goto resched;
Petko Manolov's avatar
Petko Manolov committed
384 385

	dev->rx_skb = skb;
Petko Manolov's avatar
USB  
Petko Manolov committed
386
goon:
387
	usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
Petko Manolov's avatar
Petko Manolov committed
388
		      dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
Petko Manolov's avatar
Petko Manolov committed
389
	if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) {
390
		set_bit(RX_URB_FAIL, &dev->flags);
Petko Manolov's avatar
Petko Manolov committed
391 392
		goto resched;
	} else {
393
		clear_bit(RX_URB_FAIL, &dev->flags);
Petko Manolov's avatar
Petko Manolov committed
394 395 396 397 398
	}

	return;
resched:
	tasklet_schedule(&dev->tl);
Petko Manolov's avatar
USB  
Petko Manolov committed
399 400
}

Petko Manolov's avatar
Petko Manolov committed
401 402 403 404 405 406
static void rx_fixup(unsigned long data)
{
	rtl8150_t *dev;
	struct sk_buff *skb;

	dev = (rtl8150_t *)data;
407

Petko Manolov's avatar
Petko Manolov committed
408
	spin_lock_irq(&dev->rx_pool_lock);
Petko Manolov's avatar
Petko Manolov committed
409
	fill_skb_pool(dev);
Petko Manolov's avatar
Petko Manolov committed
410
	spin_unlock_irq(&dev->rx_pool_lock);
411
	if (test_bit(RX_URB_FAIL, &dev->flags))
Petko Manolov's avatar
Petko Manolov committed
412 413
		if (dev->rx_skb)
			goto try_again;
Petko Manolov's avatar
Petko Manolov committed
414 415 416 417
	spin_lock_irq(&dev->rx_pool_lock);
	skb = pull_skb(dev);
	spin_unlock_irq(&dev->rx_pool_lock);
	if (skb == NULL)
Petko Manolov's avatar
Petko Manolov committed
418
		goto tlsched;
Petko Manolov's avatar
Petko Manolov committed
419
	dev->rx_skb = skb;
420
	usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
Petko Manolov's avatar
Petko Manolov committed
421
		      dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
422 423 424
try_again:
	if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) {
		set_bit(RX_URB_FAIL, &dev->flags);
Petko Manolov's avatar
Petko Manolov committed
425 426
		goto tlsched;
	 } else {
427
		clear_bit(RX_URB_FAIL, &dev->flags);
Petko Manolov's avatar
Petko Manolov committed
428 429 430 431 432
	}

	return;
tlsched:
	tasklet_schedule(&dev->tl);
Petko Manolov's avatar
Petko Manolov committed
433
}
Petko Manolov's avatar
USB  
Petko Manolov committed
434

David S. Miller's avatar
David S. Miller committed
435
static void write_bulk_callback(struct urb *urb, struct pt_regs *regs)
Petko Manolov's avatar
USB  
Petko Manolov committed
436
{
Petko Manolov's avatar
Petko Manolov committed
437
	rtl8150_t *dev;
Petko Manolov's avatar
USB  
Petko Manolov committed
438 439 440 441

	dev = urb->context;
	if (!dev)
		return;
Petko Manolov's avatar
Petko Manolov committed
442
	dev_kfree_skb_irq(dev->tx_skb);
Petko Manolov's avatar
USB  
Petko Manolov committed
443 444 445 446 447 448 449 450
	if (!netif_device_present(dev->netdev))
		return;
	if (urb->status)
		info("%s: Tx status %d", dev->netdev->name, urb->status);
	dev->netdev->trans_start = jiffies;
	netif_wake_queue(dev->netdev);
}

David S. Miller's avatar
David S. Miller committed
451
void intr_callback(struct urb *urb, struct pt_regs *regs)
Petko Manolov's avatar
USB  
Petko Manolov committed
452
{
Petko Manolov's avatar
Petko Manolov committed
453
	rtl8150_t *dev;
454
	int status;
Petko Manolov's avatar
USB  
Petko Manolov committed
455 456 457 458 459

	dev = urb->context;
	if (!dev)
		return;
	switch (urb->status) {
460
	case 0:			/* success */
Petko Manolov's avatar
Petko Manolov committed
461
		break;
462
	case -ECONNRESET:	/* unlink */
Petko Manolov's avatar
Petko Manolov committed
463
	case -ENOENT:
464
	case -ESHUTDOWN:
Petko Manolov's avatar
Petko Manolov committed
465
		return;
466
	/* -EPIPE:  should clear the halt */
Petko Manolov's avatar
Petko Manolov committed
467 468
	default:
		info("%s: intr status %d", dev->netdev->name, urb->status);
469
		goto resubmit;
Petko Manolov's avatar
USB  
Petko Manolov committed
470
	}
471 472 473 474 475 476 477 478 479

	/* FIXME if this doesn't do anything, don't submit the urb! */

resubmit:
	status = usb_submit_urb (urb, SLAB_ATOMIC);
	if (status)
		err ("can't resubmit intr, %s-%s/input0, status %d",
				dev->udev->bus->bus_name,
				dev->udev->devpath, status);
Petko Manolov's avatar
USB  
Petko Manolov committed
480 481 482 483 484 485 486 487
}

/*
**
**	network related part of the code
**
*/

Petko Manolov's avatar
Petko Manolov committed
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
static void fill_skb_pool(rtl8150_t *dev)
{
	struct sk_buff *skb;
	int i;

	for (i = 0; i < RX_SKB_POOL_SIZE; i++) {
		if (dev->rx_skb_pool[i])
			continue;
		skb = dev_alloc_skb(RTL8150_MTU + 2);
		if (!skb) {
			return;
		}
		skb->dev = dev->netdev;
		skb_reserve(skb, 2);
		dev->rx_skb_pool[i] = skb;
	}
}

static void free_skb_pool(rtl8150_t *dev)
{
	int i;

	for (i = 0; i < RX_SKB_POOL_SIZE; i++)
		if (dev->rx_skb_pool[i])
			dev_kfree_skb(dev->rx_skb_pool[i]);
}

Petko Manolov's avatar
Petko Manolov committed
515
static inline struct sk_buff *pull_skb(rtl8150_t *dev)
Petko Manolov's avatar
Petko Manolov committed
516 517 518 519 520 521 522 523 524 525 526 527 528
{
	struct sk_buff *skb;
	int i;

	for (i = 0; i < RX_SKB_POOL_SIZE; i++) {
		if (dev->rx_skb_pool[i]) {
			skb = dev->rx_skb_pool[i];
			dev->rx_skb_pool[i] = NULL;
			return skb;
		}
	}
	return NULL;
}
Petko Manolov's avatar
USB  
Petko Manolov committed
529

Petko Manolov's avatar
Petko Manolov committed
530
static int enable_net_traffic(rtl8150_t * dev)
Petko Manolov's avatar
USB  
Petko Manolov committed
531
{
Petko Manolov's avatar
Petko Manolov committed
532
	u8 cr, tcr, rcr, msr;
Petko Manolov's avatar
USB  
Petko Manolov committed
533

Petko Manolov's avatar
Petko Manolov committed
534
	if (!rtl8150_reset(dev)) {
Petko Manolov's avatar
USB  
Petko Manolov committed
535 536
		warn("%s - device reset failed", __FUNCTION__);
	}
Petko Manolov's avatar
Petko Manolov committed
537
	/* RCR bit7=1 attach Rx info at the end;  =0 HW CRC (which is broken) */
538 539
	rcr = 0x9e;	/* bit7=1 attach Rx info at the end */
	dev->rx_creg = cpu_to_le16(rcr);
Petko Manolov's avatar
Petko Manolov committed
540
	tcr = 0xd8;
Petko Manolov's avatar
USB  
Petko Manolov committed
541
	cr = 0x0c;
Petko Manolov's avatar
Petko Manolov committed
542 543
	if (!(rcr & 0x80))
		set_bit(RTL8150_HW_CRC, &dev->flags);
Petko Manolov's avatar
USB  
Petko Manolov committed
544 545 546 547 548 549 550 551
	set_registers(dev, RCR, 1, &rcr);
	set_registers(dev, TCR, 1, &tcr);
	set_registers(dev, CR, 1, &cr);
	get_registers(dev, MSR, 1, &msr);

	return 0;
}

Petko Manolov's avatar
Petko Manolov committed
552
static void disable_net_traffic(rtl8150_t * dev)
Petko Manolov's avatar
USB  
Petko Manolov committed
553
{
Petko Manolov's avatar
Petko Manolov committed
554
	u8 cr;
Petko Manolov's avatar
USB  
Petko Manolov committed
555 556 557 558 559 560 561 562

	get_registers(dev, CR, 1, &cr);
	cr &= 0xf3;
	set_registers(dev, CR, 1, &cr);
}

static struct net_device_stats *rtl8150_netdev_stats(struct net_device *dev)
{
Petko Manolov's avatar
Petko Manolov committed
563
	return &((rtl8150_t *) dev->priv)->stats;
Petko Manolov's avatar
USB  
Petko Manolov committed
564 565 566 567
}

static void rtl8150_tx_timeout(struct net_device *netdev)
{
Petko Manolov's avatar
Petko Manolov committed
568
	rtl8150_t *dev;
Petko Manolov's avatar
USB  
Petko Manolov committed
569 570 571 572

	dev = netdev->priv;
	if (!dev)
		return;
Petko Manolov's avatar
Petko Manolov committed
573
	warn("%s: Tx timeout.", netdev->name);
574
	dev->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
Petko Manolov's avatar
USB  
Petko Manolov committed
575 576 577 578 579 580
	usb_unlink_urb(dev->tx_urb);
	dev->stats.tx_errors++;
}

static void rtl8150_set_multicast(struct net_device *netdev)
{
Petko Manolov's avatar
Petko Manolov committed
581
	rtl8150_t *dev;
Petko Manolov's avatar
USB  
Petko Manolov committed
582 583 584 585

	dev = netdev->priv;
	netif_stop_queue(netdev);
	if (netdev->flags & IFF_PROMISC) {
586
		dev->rx_creg |= cpu_to_le16(0x0001);
Petko Manolov's avatar
USB  
Petko Manolov committed
587 588
		info("%s: promiscuous mode", netdev->name);
	} else if ((netdev->mc_count > multicast_filter_limit) ||
Petko Manolov's avatar
Petko Manolov committed
589
		   (netdev->flags & IFF_ALLMULTI)) {
590 591
		dev->rx_creg &= cpu_to_le16(0xfffe);
		dev->rx_creg |= cpu_to_le16(0x0002);
Petko Manolov's avatar
USB  
Petko Manolov committed
592 593 594
		info("%s: allmulti set", netdev->name);
	} else {
		/* ~RX_MULTICAST, ~RX_PROMISCUOUS */
595
		dev->rx_creg &= cpu_to_le16(0x00fc);
Petko Manolov's avatar
USB  
Petko Manolov committed
596
	}
597
	async_set_registers(dev, RCR, 2);
Petko Manolov's avatar
USB  
Petko Manolov committed
598 599 600 601 602
	netif_wake_queue(netdev);
}

static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{
Petko Manolov's avatar
Petko Manolov committed
603 604
	rtl8150_t *dev;
	int count, res;
Petko Manolov's avatar
USB  
Petko Manolov committed
605 606 607

	netif_stop_queue(netdev);
	dev = netdev->priv;
Petko Manolov's avatar
Petko Manolov committed
608 609
	count = (skb->len < 60) ? 60 : skb->len;
	count = (count & 0x3f) ? count : count + 1;
Petko Manolov's avatar
Petko Manolov committed
610
	dev->tx_skb = skb;
611
	usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2),
Petko Manolov's avatar
Petko Manolov committed
612
		      skb->data, count, write_bulk_callback, dev);
613
	if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) {
Petko Manolov's avatar
USB  
Petko Manolov committed
614 615 616 617 618 619 620 621 622 623 624 625 626 627
		warn("failed tx_urb %d\n", res);
		dev->stats.tx_errors++;
		netif_start_queue(netdev);
	} else {
		dev->stats.tx_packets++;
		dev->stats.tx_bytes += skb->len;
		netdev->trans_start = jiffies;
	}

	return 0;
}

static int rtl8150_open(struct net_device *netdev)
{
Petko Manolov's avatar
Petko Manolov committed
628 629 630
	rtl8150_t *dev;
	int res;

Petko Manolov's avatar
USB  
Petko Manolov committed
631 632 633 634
	dev = netdev->priv;
	if (dev == NULL) {
		return -ENODEV;
	}
Petko Manolov's avatar
Petko Manolov committed
635 636
	if (dev->rx_skb == NULL)
		dev->rx_skb = pull_skb(dev);
Petko Manolov's avatar
Petko Manolov committed
637 638 639
	if (!dev->rx_skb)
		return -ENOMEM;

Petko Manolov's avatar
Petko Manolov committed
640
	down(&dev->sem);
Petko Manolov's avatar
Petko Manolov committed
641 642 643

	set_registers(dev, IDR, 6, netdev->dev_addr);
	
644
	usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
Petko Manolov's avatar
Petko Manolov committed
645 646
		      dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
	if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL)))
Petko Manolov's avatar
USB  
Petko Manolov committed
647
		warn("%s: rx_urb submit failed: %d", __FUNCTION__, res);
648
	usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3),
Petko Manolov's avatar
Petko Manolov committed
649 650 651
		     dev->intr_buff, sizeof(dev->intr_buff), intr_callback,
		     dev, dev->intr_interval);
	if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL)))
Petko Manolov's avatar
USB  
Petko Manolov committed
652 653 654
		warn("%s: intr_urb submit failed: %d", __FUNCTION__, res);
	netif_start_queue(netdev);
	enable_net_traffic(dev);
Petko Manolov's avatar
Petko Manolov committed
655
	up(&dev->sem);
Petko Manolov's avatar
USB  
Petko Manolov committed
656 657 658 659 660 661 662 663 664 665 666 667 668

	return res;
}

static int rtl8150_close(struct net_device *netdev)
{
	rtl8150_t *dev;
	int res = 0;

	dev = netdev->priv;
	if (!dev)
		return -ENODEV;

Petko Manolov's avatar
Petko Manolov committed
669
	down(&dev->sem);
670
	netif_stop_queue(netdev);
Petko Manolov's avatar
Petko Manolov committed
671 672
	if (!test_bit(RTL8150_UNPLUG, &dev->flags))
		disable_net_traffic(dev);
Petko Manolov's avatar
USB  
Petko Manolov committed
673
	unlink_all_urbs(dev);
Petko Manolov's avatar
Petko Manolov committed
674
	up(&dev->sem);
Petko Manolov's avatar
USB  
Petko Manolov committed
675 676 677 678 679 680

	return res;
}

static int rtl8150_ethtool_ioctl(struct net_device *netdev, void *uaddr)
{
Petko Manolov's avatar
Petko Manolov committed
681 682
	rtl8150_t *dev;
	int cmd;
Petko Manolov's avatar
USB  
Petko Manolov committed
683 684

	dev = netdev->priv;
Petko Manolov's avatar
Petko Manolov committed
685
	if (get_user(cmd, (int *) uaddr))
Petko Manolov's avatar
USB  
Petko Manolov committed
686 687 688
		return -EFAULT;

	switch (cmd) {
Petko Manolov's avatar
Petko Manolov committed
689 690 691
	case ETHTOOL_GDRVINFO:{
		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };

Petko Manolov's avatar
USB  
Petko Manolov committed
692 693
		strncpy(info.driver, DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
		strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
Petko Manolov's avatar
Petko Manolov committed
694
		usb_make_path(dev->udev, info.bus_info, sizeof info.bus_info);
Petko Manolov's avatar
USB  
Petko Manolov committed
695 696 697
		if (copy_to_user(uaddr, &info, sizeof(info)))
			return -EFAULT;
		return 0;
Petko Manolov's avatar
Petko Manolov committed
698 699
		}
	case ETHTOOL_GSET:{
Petko Manolov's avatar
USB  
Petko Manolov committed
700
		struct ethtool_cmd ecmd;
Petko Manolov's avatar
Petko Manolov committed
701
		short lpa, bmcr;
Petko Manolov's avatar
USB  
Petko Manolov committed
702 703 704 705

		if (copy_from_user(&ecmd, uaddr, sizeof(ecmd)))
			return -EFAULT;
		ecmd.supported = (SUPPORTED_10baseT_Half |
Petko Manolov's avatar
Petko Manolov committed
706 707 708 709 710
				  SUPPORTED_10baseT_Full |
				  SUPPORTED_100baseT_Half |
				  SUPPORTED_100baseT_Full |
				  SUPPORTED_Autoneg |
				  SUPPORTED_TP | SUPPORTED_MII);
Petko Manolov's avatar
USB  
Petko Manolov committed
711 712 713 714 715 716 717 718 719 720 721
		ecmd.port = PORT_TP;
		ecmd.transceiver = XCVR_INTERNAL;
		ecmd.phy_address = dev->phy;
		get_registers(dev, BMCR, 2, &bmcr);
		get_registers(dev, ANLP, 2, &lpa);
		if (bmcr & BMCR_ANENABLE) {
			ecmd.autoneg = AUTONEG_ENABLE;
			ecmd.speed = (lpa & (LPA_100HALF | LPA_100FULL)) ?
			             SPEED_100 : SPEED_10;
			if (ecmd.speed == SPEED_100)
				ecmd.duplex = (lpa & LPA_100FULL) ?
Petko Manolov's avatar
Petko Manolov committed
722
				    DUPLEX_FULL : DUPLEX_HALF;
Petko Manolov's avatar
USB  
Petko Manolov committed
723 724
			else
				ecmd.duplex = (lpa & LPA_10FULL) ?
Petko Manolov's avatar
Petko Manolov committed
725
				    DUPLEX_FULL : DUPLEX_HALF;
Petko Manolov's avatar
USB  
Petko Manolov committed
726 727 728
		} else {
			ecmd.autoneg = AUTONEG_DISABLE;
			ecmd.speed = (bmcr & BMCR_SPEED100) ?
Petko Manolov's avatar
Petko Manolov committed
729
			    SPEED_100 : SPEED_10;
Petko Manolov's avatar
USB  
Petko Manolov committed
730
			ecmd.duplex = (bmcr & BMCR_FULLDPLX) ?
Petko Manolov's avatar
Petko Manolov committed
731
			    DUPLEX_FULL : DUPLEX_HALF;
Petko Manolov's avatar
USB  
Petko Manolov committed
732 733 734 735
		}
		if (copy_to_user(uaddr, &ecmd, sizeof(ecmd)))
			return -EFAULT;
		return 0;
Petko Manolov's avatar
Petko Manolov committed
736
		}
Petko Manolov's avatar
USB  
Petko Manolov committed
737 738
	case ETHTOOL_SSET:
		return -ENOTSUPP;
Petko Manolov's avatar
Petko Manolov committed
739 740
	case ETHTOOL_GLINK:{
		struct ethtool_value edata = { ETHTOOL_GLINK };
Petko Manolov's avatar
USB  
Petko Manolov committed
741 742 743 744 745

		edata.data = netif_carrier_ok(netdev);
		if (copy_to_user(uaddr, &edata, sizeof(edata)))
			return -EFAULT;
		return 0;
Petko Manolov's avatar
Petko Manolov committed
746
		}
Petko Manolov's avatar
USB  
Petko Manolov committed
747 748 749 750 751
	default:
		return -EOPNOTSUPP;
	}
}

Petko Manolov's avatar
Petko Manolov committed
752
static int rtl8150_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
Petko Manolov's avatar
USB  
Petko Manolov committed
753 754
{
	rtl8150_t *dev;
Petko Manolov's avatar
Petko Manolov committed
755 756
	u16 *data;
	int res;
Petko Manolov's avatar
USB  
Petko Manolov committed
757 758

	dev = netdev->priv;
Petko Manolov's avatar
Petko Manolov committed
759
	data = (u16 *) & rq->ifr_data;
Petko Manolov's avatar
Petko Manolov committed
760
	res = 0;
Petko Manolov's avatar
USB  
Petko Manolov committed
761

Petko Manolov's avatar
Petko Manolov committed
762
	down(&dev->sem);
Petko Manolov's avatar
USB  
Petko Manolov committed
763 764
	switch (cmd) {
	case SIOCETHTOOL:
Petko Manolov's avatar
Petko Manolov committed
765 766
		res = rtl8150_ethtool_ioctl(netdev, rq->ifr_data);
		break;
Petko Manolov's avatar
USB  
Petko Manolov committed
767 768
	case SIOCDEVPRIVATE:
		data[0] = dev->phy;
Petko Manolov's avatar
Petko Manolov committed
769
	case SIOCDEVPRIVATE + 1:
Petko Manolov's avatar
USB  
Petko Manolov committed
770
		read_mii_word(dev, dev->phy, (data[1] & 0x1f), &data[3]);
Petko Manolov's avatar
Petko Manolov committed
771
		break;
Petko Manolov's avatar
Petko Manolov committed
772
	case SIOCDEVPRIVATE + 2:
Petko Manolov's avatar
Petko Manolov committed
773 774
		if (!capable(CAP_NET_ADMIN)) {
			up(&dev->sem);
Petko Manolov's avatar
USB  
Petko Manolov committed
775
			return -EPERM;
Petko Manolov's avatar
Petko Manolov committed
776
		}
Petko Manolov's avatar
USB  
Petko Manolov committed
777
		write_mii_word(dev, dev->phy, (data[1] & 0x1f), data[2]);
Petko Manolov's avatar
Petko Manolov committed
778
		break;
Petko Manolov's avatar
USB  
Petko Manolov committed
779
	default:
Petko Manolov's avatar
Petko Manolov committed
780
		res = -EOPNOTSUPP;
Petko Manolov's avatar
USB  
Petko Manolov committed
781
	}
Petko Manolov's avatar
Petko Manolov committed
782 783
	up(&dev->sem);
	return res;
Petko Manolov's avatar
USB  
Petko Manolov committed
784 785
}

786 787
static int rtl8150_probe(struct usb_interface *intf,
			 const struct usb_device_id *id)
Petko Manolov's avatar
USB  
Petko Manolov committed
788
{
789
	struct usb_device *udev = interface_to_usbdev(intf);
Petko Manolov's avatar
USB  
Petko Manolov committed
790 791 792 793 794
	rtl8150_t *dev;
	struct net_device *netdev;

	dev = kmalloc(sizeof(rtl8150_t), GFP_KERNEL);
	if (!dev) {
Petko Manolov's avatar
Petko Manolov committed
795
		err("Out of memory");
796
		return -ENOMEM;
Petko Manolov's avatar
USB  
Petko Manolov committed
797 798 799 800 801 802 803
	} else
		memset(dev, 0, sizeof(rtl8150_t));

	netdev = init_etherdev(NULL, 0);
	if (!netdev) {
		kfree(dev);
		err("Oh boy, out of memory again?!?");
804
		return -ENOMEM;
Petko Manolov's avatar
USB  
Petko Manolov committed
805
	}
Petko Manolov's avatar
Petko Manolov committed
806

Petko Manolov's avatar
USB  
Petko Manolov committed
807
	init_MUTEX(&dev->sem);
Petko Manolov's avatar
Petko Manolov committed
808 809 810 811
	tasklet_init(&dev->tl, rx_fixup, (unsigned long)dev);
	spin_lock_init(&dev->rx_pool_lock);
	
	down(&dev->sem);
Petko Manolov's avatar
USB  
Petko Manolov committed
812 813 814 815 816 817 818 819 820 821 822
	dev->udev = udev;
	dev->netdev = netdev;
	SET_MODULE_OWNER(netdev);
	netdev->priv = dev;
	netdev->open = rtl8150_open;
	netdev->stop = rtl8150_close;
	netdev->do_ioctl = rtl8150_ioctl;
	netdev->watchdog_timeo = RTL8150_TX_TIMEOUT;
	netdev->tx_timeout = rtl8150_tx_timeout;
	netdev->hard_start_xmit = rtl8150_start_xmit;
	netdev->set_multicast_list = rtl8150_set_multicast;
Petko Manolov's avatar
Petko Manolov committed
823
	netdev->set_mac_address = rtl8150_set_mac_address;
Petko Manolov's avatar
USB  
Petko Manolov committed
824 825 826 827
	netdev->get_stats = rtl8150_netdev_stats;
	netdev->mtu = RTL8150_MTU;
	dev->intr_interval = 100;	/* 100ms */

Petko Manolov's avatar
Petko Manolov committed
828 829 830 831 832
	if (!alloc_all_urbs(dev)) {
		err("out of memory");
		goto err;
	}
	if (!rtl8150_reset(dev)) {
Petko Manolov's avatar
USB  
Petko Manolov committed
833 834
		err("couldn't reset the device");
		free_all_urbs(dev);
Petko Manolov's avatar
Petko Manolov committed
835
		goto err;
Petko Manolov's avatar
USB  
Petko Manolov committed
836
	}
Petko Manolov's avatar
Petko Manolov committed
837
	fill_skb_pool(dev);
Petko Manolov's avatar
USB  
Petko Manolov committed
838
	set_ethernet_addr(dev);
Petko Manolov's avatar
Petko Manolov committed
839
	info("%s: rtl8150 is detected", netdev->name);
Petko Manolov's avatar
Petko Manolov committed
840 841
	
	up(&dev->sem);
842
	usb_set_intfdata(intf, dev);
843
	return 0;
Petko Manolov's avatar
Petko Manolov committed
844 845 846 847 848
err:
	unregister_netdev(dev->netdev);
	up(&dev->sem);
	kfree(netdev);
	kfree(dev);
849
	return -EIO;
Petko Manolov's avatar
USB  
Petko Manolov committed
850 851
}

852
static void rtl8150_disconnect(struct usb_interface *intf)
Petko Manolov's avatar
USB  
Petko Manolov committed
853
{
854
	rtl8150_t *dev = usb_get_intfdata(intf);
855

856
	usb_set_intfdata(intf, NULL);
857 858 859 860 861 862 863 864 865 866 867 868 869
	if (dev) {
		set_bit(RTL8150_UNPLUG, &dev->flags);
		unregister_netdev(dev->netdev);
		unlink_all_urbs(dev);
		free_all_urbs(dev);
		free_skb_pool(dev);
		if (dev->rx_skb)
			dev_kfree_skb(dev->rx_skb);
		kfree(dev->netdev);
		kfree(dev);
		dev->netdev = NULL;
		dev = NULL;
	}
Petko Manolov's avatar
USB  
Petko Manolov committed
870 871
}

Petko Manolov's avatar
Petko Manolov committed
872
int __init usb_rtl8150_init(void)
Petko Manolov's avatar
USB  
Petko Manolov committed
873 874 875 876 877
{
	info(DRIVER_DESC " " DRIVER_VERSION);
	return usb_register(&rtl8150_driver);
}

Petko Manolov's avatar
Petko Manolov committed
878
void __exit usb_rtl8150_exit(void)
Petko Manolov's avatar
USB  
Petko Manolov committed
879 880 881 882 883 884 885 886 887 888
{
	usb_deregister(&rtl8150_driver);
}

module_init(usb_rtl8150_init);
module_exit(usb_rtl8150_exit);

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");