# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.604.1.7 -> 1.604.1.8
# drivers/usb/net/rtl8150.c 1.8 -> 1.9
# drivers/usb/net/pegasus.h 1.16 -> 1.17
# drivers/usb/net/pegasus.c 1.28 -> 1.29
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/07/04 [EMAIL PROTECTED] 1.604.1.8
# [PATCH] pegasus & rtl8150
#
# I chose a little bit more restrictive license for my drivers.
# Rx skb pool introduced in pegasus driver and the pool locking in rtl8150
# is refined.
# --------------------------------------------
#
diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
--- a/drivers/usb/net/pegasus.c Fri Jul 5 14:51:09 2002
+++ b/drivers/usb/net/pegasus.c Fri Jul 5 14:51:09 2002
@@ -1,46 +1,34 @@
/*
-** Pegasus: USB 10/100Mbps/HomePNA (1Mbps) Controller
-**
-** Copyright (c) 1999-2002 Petko Manolov ([EMAIL PROTECTED])
-**
-**
-** ChangeLog:
-** .... Most of the time spend reading sources & docs.
-** v0.2.x First official release for the Linux kernel.
-** v0.3.0 Beutified and structured, some bugs fixed.
-** v0.3.x URBifying bulk requests and bugfixing. First relatively
-** stable release. Still can touch device's registers only
-** from top-halves.
-** v0.4.0 Control messages remained unurbified are now URBs.
-** Now we can touch the HW at any time.
-** v0.4.9 Control urbs again use process context to wait. Argh...
-** Some long standing bugs (enable_net_traffic) fixed.
-** Also nasty trick about resubmiting control urb from
-** interrupt context used. Please let me know how it
-** behaves. Pegasus II support added since this version.
-** TODO: suppressing HCD warnings spewage on disconnect.
-** v0.4.13 Ethernet address is now set at probe(), not at open()
-** time as this seems to break dhcpd.
-** v0.5.0 branch to 2.5.x kernels
-** v0.5.1 ethtool support added
-*/
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Copyright (c) 1999-2002 Petko Manolov ([EMAIL PROTECTED])
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * 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.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * ChangeLog:
+ * .... Most of the time spent on reading sources & docs.
+ * v0.2.x First official release for the Linux kernel.
+ * v0.3.0 Beutified and structured, some bugs fixed.
+ * v0.3.x URBifying bulk requests and bugfixing. First relatively
+ * stable release. Still can touch device's registers only
+ * from top-halves.
+ * v0.4.0 Control messages remained unurbified are now URBs.
+ * Now we can touch the HW at any time.
+ * v0.4.9 Control urbs again use process context to wait. Argh...
+ * Some long standing bugs (enable_net_traffic) fixed.
+ * Also nasty trick about resubmiting control urb from
+ * interrupt context used. Please let me know how it
+ * behaves. Pegasus II support added since this version.
+ * TODO: suppressing HCD warnings spewage on disconnect.
+ * v0.4.13 Ethernet address is now set at probe(), not at open()
+ * time as this seems to break dhcpd.
+ * v0.5.0 branch to 2.5.x kernels
+ * v0.5.1 ethtool support added
+ * v0.5.5 rx socket buffers are in a pool and the their allocation
+ * is out of the interrupt routine.
*/
+
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/init.h>
@@ -58,14 +46,13 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.5.4 (2002/04/11)"
+#define DRIVER_VERSION "v0.5.6 (2002/06/23)"
#define DRIVER_AUTHOR "Petko Manolov <[EMAIL PROTECTED]>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
static const char driver_name[] = "pegasus";
-#define PEGASUS_USE_INTR
-#define PEGASUS_WRITE_EEPROM
+#undef PEGASUS_WRITE_EEPROM
#define BMSR_MEDIA (BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | \
BMSR_100FULL | BMSR_ANEGCAPABLE)
@@ -499,13 +486,57 @@
return 0;
}
+static void fill_skb_pool(pegasus_t *pegasus)
+{
+ int i;
+
+ for (i=0; i < RX_SKBS; i++) {
+ if (pegasus->rx_pool[i])
+ continue;
+ pegasus->rx_pool[i] = dev_alloc_skb(PEGASUS_MTU + 2);
+ /*
+ ** we give up if the allocation fail. the tasklet will be
+ ** rescheduled again anyway...
+ */
+ if (pegasus->rx_pool[i] == NULL)
+ return;
+ pegasus->rx_pool[i]->dev = pegasus->net;
+ skb_reserve(pegasus->rx_pool[i], 2);
+ }
+}
+
+static void free_skb_pool(pegasus_t *pegasus)
+{
+ int i;
+
+ for (i=0; i < RX_SKBS; i++) {
+ if (pegasus->rx_pool[i]) {
+ dev_kfree_skb(pegasus->rx_pool[i]);
+ pegasus->rx_pool[i] = NULL;
+ }
+ }
+}
+
+static inline struct sk_buff *pull_skb(pegasus_t *pegasus)
+{
+ int i;
+ struct sk_buff *skb;
+
+ for (i=0; i < RX_SKBS; i++) {
+ if (likely(pegasus->rx_pool[i] != NULL)) {
+ skb = pegasus->rx_pool[i];
+ pegasus->rx_pool[i] = NULL;
+ return skb;
+ }
+ }
+ return NULL;
+}
+
static void read_bulk_callback(struct urb *urb)
{
pegasus_t *pegasus = urb->context;
struct net_device *net;
- int count = urb->actual_length;
- int rx_status;
- struct sk_buff *skb;
+ int rx_status, count = urb->actual_length;
__u16 pkt_len;
if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING))
@@ -519,7 +550,7 @@
case 0:
break;
case -ETIMEDOUT:
- dbg("reset MAC");
+ dbg("%s: reset MAC", net->name);
pegasus->flags &= ~PEGASUS_RX_BUSY;
break;
case -ENOENT:
@@ -546,23 +577,24 @@
}
pkt_len = (rx_status & 0xfff) - 8;
- if (!pegasus->rx_skb)
- goto tl_sched;
-
+ if (pegasus->rx_skb == NULL)
+ printk("%s: rx_skb == NULL\n", __FUNCTION__);
+ /*
+ ** we are sure at this point pegasus->rx_skb != NULL
+ ** so we go ahead and pass up the packet.
+ */
skb_put(pegasus->rx_skb, pkt_len);
pegasus->rx_skb->protocol = eth_type_trans(pegasus->rx_skb, net);
netif_rx(pegasus->rx_skb);
-
- if (!(skb = dev_alloc_skb(PEGASUS_MTU + 2))) {
- pegasus->rx_skb = NULL;
- goto tl_sched;
- }
-
- skb->dev = net;
- skb_reserve(skb, 2);
- pegasus->rx_skb = skb;
pegasus->stats.rx_packets++;
pegasus->stats.rx_bytes += pkt_len;
+
+ spin_lock(&pegasus->rx_pool_lock);
+ pegasus->rx_skb = pull_skb(pegasus);
+ spin_unlock(&pegasus->rx_pool_lock);
+
+ if (pegasus->rx_skb == NULL)
+ goto tl_sched;
goon:
FILL_BULK_URB(pegasus->rx_urb, pegasus->usb,
usb_rcvbulkpipe(pegasus->usb, 1),
@@ -587,11 +619,19 @@
pegasus = (pegasus_t *)data;
+ spin_lock_irq(&pegasus->rx_pool_lock);
+ fill_skb_pool(pegasus);
+ spin_unlock_irq(&pegasus->rx_pool_lock);
if (pegasus->flags & PEGASUS_RX_URB_FAIL)
if (pegasus->rx_skb)
goto try_again;
-
- if (!(pegasus->rx_skb = dev_alloc_skb(PEGASUS_MTU + 2))) {
+ if (pegasus->rx_skb == NULL) {
+ spin_lock_irq(&pegasus->rx_pool_lock);
+ pegasus->rx_skb = pull_skb(pegasus);
+ spin_unlock_irq(&pegasus->rx_pool_lock);
+ }
+ if (pegasus->rx_skb == NULL) {
+ warn("wow, low on memory");
tasklet_schedule(&pegasus->rx_tl);
return;
}
@@ -625,7 +665,6 @@
netif_wake_queue(pegasus->net);
}
-#ifdef PEGASUS_USE_INTR
static void intr_callback(struct urb *urb)
{
pegasus_t *pegasus = urb->context;
@@ -662,7 +701,6 @@
}
}
}
-#endif
static void pegasus_tx_timeout(struct net_device *net)
{
@@ -748,15 +786,62 @@
}
+static void free_all_urbs(pegasus_t *pegasus)
+{
+ usb_free_urb(pegasus->intr_urb);
+ usb_free_urb(pegasus->tx_urb);
+ usb_free_urb(pegasus->rx_urb);
+ usb_free_urb(pegasus->ctrl_urb);
+}
+
+static void unlink_all_urbs(pegasus_t *pegasus)
+{
+ usb_unlink_urb(pegasus->intr_urb);
+ usb_unlink_urb(pegasus->tx_urb);
+ usb_unlink_urb(pegasus->rx_urb);
+ usb_unlink_urb(pegasus->ctrl_urb);
+}
+
+static int alloc_urbs(pegasus_t *pegasus)
+{
+ pegasus->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!pegasus->ctrl_urb) {
+ return 0;
+ }
+ pegasus->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!pegasus->rx_urb) {
+ usb_free_urb(pegasus->ctrl_urb);
+ return 0;
+ }
+ pegasus->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!pegasus->tx_urb) {
+ usb_free_urb(pegasus->rx_urb);
+ usb_free_urb(pegasus->ctrl_urb);
+ return 0;
+ }
+ pegasus->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!pegasus->intr_urb) {
+ usb_free_urb(pegasus->tx_urb);
+ usb_free_urb(pegasus->rx_urb);
+ usb_free_urb(pegasus->ctrl_urb);
+ return 0;
+ }
+
+ return 1;
+}
+
static int pegasus_open(struct net_device *net)
{
pegasus_t *pegasus = (pegasus_t *) net->priv;
int res;
- if (!(pegasus->rx_skb = dev_alloc_skb(PEGASUS_MTU + 2)))
+ if (pegasus->rx_skb == NULL)
+ pegasus->rx_skb = pull_skb(pegasus);
+ /*
+ ** Note: no point to free the pool. it is empty :-)
+ */
+ if (!pegasus->rx_skb)
return -ENOMEM;
- pegasus->rx_skb->dev = net;
- skb_reserve(pegasus->rx_skb, 2);
down(&pegasus->sem);
FILL_BULK_URB(pegasus->rx_urb, pegasus->usb,
@@ -765,19 +850,20 @@
read_bulk_callback, pegasus);
if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL)))
warn("%s: failed rx_urb %d", __FUNCTION__, res);
-#ifdef PEGASUS_USE_INTR
FILL_INT_URB(pegasus->intr_urb, pegasus->usb,
usb_rcvintpipe(pegasus->usb, 3),
pegasus->intr_buff, sizeof(pegasus->intr_buff),
intr_callback, pegasus, pegasus->intr_interval);
if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL)))
warn("%s: failed intr_urb %d", __FUNCTION__, res);
-#endif
netif_start_queue(net);
pegasus->flags |= PEGASUS_RUNNING;
if ((res = enable_net_traffic(net, pegasus->usb))) {
err("can't enable_net_traffic() - %d", res);
res = -EIO;
+ usb_unlink_urb(pegasus->rx_urb);
+ usb_unlink_urb(pegasus->intr_urb);
+ free_skb_pool(pegasus);
goto exit;
}
set_carrier(net);
@@ -797,13 +883,7 @@
netif_stop_queue(net);
if (!(pegasus->flags & PEGASUS_UNPLUG))
disable_net_traffic(pegasus);
-
- usb_unlink_urb(pegasus->rx_urb);
- usb_unlink_urb(pegasus->tx_urb);
- usb_unlink_urb(pegasus->ctrl_urb);
-#ifdef PEGASUS_USE_INTR
- usb_unlink_urb(pegasus->intr_urb);
-#endif
+ unlink_all_urbs(pegasus);
up(&pegasus->sem);
return 0;
@@ -986,38 +1066,14 @@
pegasus->dev_index = dev_index;
init_waitqueue_head(&pegasus->ctrl_wait);
- pegasus->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!pegasus->ctrl_urb) {
- kfree(pegasus);
- return NULL;
- }
- pegasus->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!pegasus->rx_urb) {
- usb_free_urb(pegasus->ctrl_urb);
- kfree(pegasus);
- return NULL;
- }
- pegasus->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!pegasus->tx_urb) {
- usb_free_urb(pegasus->rx_urb);
- usb_free_urb(pegasus->ctrl_urb);
- kfree(pegasus);
- return NULL;
- }
- pegasus->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!pegasus->intr_urb) {
- usb_free_urb(pegasus->tx_urb);
- usb_free_urb(pegasus->rx_urb);
- usb_free_urb(pegasus->ctrl_urb);
+ if (!alloc_urbs(pegasus)) {
kfree(pegasus);
return NULL;
}
net = init_etherdev(NULL, 0);
if (!net) {
- usb_free_urb(pegasus->tx_urb);
- usb_free_urb(pegasus->rx_urb);
- usb_free_urb(pegasus->ctrl_urb);
+ free_all_urbs(pegasus);
kfree(pegasus);
return NULL;
}
@@ -1039,32 +1095,26 @@
net->set_multicast_list = pegasus_set_multicast;
net->get_stats = pegasus_netdev_stats;
net->mtu = PEGASUS_MTU;
+ spin_lock_init(&pegasus->rx_pool_lock);
pegasus->features = usb_dev_id[dev_index].private;
-#ifdef PEGASUS_USE_INTR
get_interrupt_interval(pegasus);
-#endif
if (reset_mac(pegasus)) {
err("can't reset MAC");
unregister_netdev(pegasus->net);
- usb_free_urb(pegasus->tx_urb);
- usb_free_urb(pegasus->rx_urb);
- usb_free_urb(pegasus->ctrl_urb);
+ free_all_urbs(pegasus);
kfree(pegasus->net);
kfree(pegasus);
pegasus = NULL;
goto exit;
}
-
- info("%s: %s", net->name, usb_dev_id[dev_index].name);
-
set_ethernet_addr(pegasus);
-
+ fill_skb_pool(pegasus);
+ printk("%s: %s\n", net->name, usb_dev_id[dev_index].name);
if (pegasus->features & PEGASUS_II) {
info("setup Pegasus II specific registers");
setup_pegasus_II(pegasus);
}
-
pegasus->phy = mii_phy_probe(pegasus);
if (pegasus->phy == 0xff) {
warn("can't locate MII phy, using default");
@@ -1087,14 +1137,9 @@
pegasus->flags |= PEGASUS_UNPLUG;
unregister_netdev(pegasus->net);
usb_put_dev(dev);
- usb_unlink_urb(pegasus->intr_urb);
- usb_unlink_urb(pegasus->tx_urb);
- usb_unlink_urb(pegasus->rx_urb);
- usb_unlink_urb(pegasus->ctrl_urb);
- usb_free_urb(pegasus->intr_urb);
- usb_free_urb(pegasus->tx_urb);
- usb_free_urb(pegasus->rx_urb);
- usb_free_urb(pegasus->ctrl_urb);
+ unlink_all_urbs(pegasus);
+ free_all_urbs(pegasus);
+ free_skb_pool(pegasus);
if (pegasus->rx_skb)
dev_kfree_skb(pegasus->rx_skb);
kfree(pegasus->net);
diff -Nru a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
--- a/drivers/usb/net/pegasus.h Fri Jul 5 14:51:09 2002
+++ b/drivers/usb/net/pegasus.h Fri Jul 5 14:51:09 2002
@@ -2,18 +2,8 @@
* Copyright (c) 1999-2002 Petko Manolov - Petkan ([EMAIL PROTECTED])
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
*/
@@ -23,6 +13,7 @@
#define HAS_HOME_PNA 0x40000000
#define PEGASUS_MTU 1536
+#define RX_SKBS 4
#define EPROM_WRITE 0x01
#define EPROM_READ 0x02
@@ -100,10 +91,12 @@
int intr_interval;
struct tasklet_struct rx_tl;
struct urb *ctrl_urb, *rx_urb, *tx_urb, *intr_urb;
+ struct sk_buff *rx_pool[RX_SKBS];
struct sk_buff *rx_skb;
struct usb_ctrlrequest dr;
wait_queue_head_t ctrl_wait;
struct semaphore sem;
+ spinlock_t rx_pool_lock;
unsigned char intr_buff[8];
__u8 tx_buff[PEGASUS_MTU];
__u8 eth_regs[4];
diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
--- a/drivers/usb/net/rtl8150.c Fri Jul 5 14:51:09 2002
+++ b/drivers/usb/net/rtl8150.c Fri Jul 5 14:51:09 2002
@@ -1,15 +1,14 @@
/*
- * Copyright (c) 2002 Petko Manolov ([EMAIL PROTECTED])
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
+ * Copyright (c) 2002 Petko Manolov ([EMAIL PROTECTED])
*
+ * 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.
*/
#include <linux/config.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <linux/signal.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -19,7 +18,6 @@
#include <linux/ethtool.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/usb.h>
-#include <linux/init.h>
#include <asm/uaccess.h>
/* Version Information */
@@ -106,7 +104,7 @@
static void fill_skb_pool(rtl8150_t *);
static void free_skb_pool(rtl8150_t *);
-static struct sk_buff *pull_skb(rtl8150_t *);
+static inline struct sk_buff *pull_skb(rtl8150_t *);
static void rtl8150_disconnect(struct usb_device *dev, void *ptr);
static void *rtl8150_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id);
@@ -312,7 +310,7 @@
case -ENOENT:
return; /* the urb is in unlink state */
case -ETIMEDOUT:
- warn("reset needed may be?..");
+ warn("may be reset is needed?..");
goto goon;
default:
warn("Rx status %d", urb->status);
@@ -331,13 +329,13 @@
netif_rx(dev->rx_skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
-
+
+ spin_lock(&dev->rx_pool_lock);
skb = pull_skb(dev);
+ spin_unlock(&dev->rx_pool_lock);
if (!skb)
goto resched;
- skb->dev = netdev;
- skb_reserve(skb, 2);
dev->rx_skb = skb;
goon:
FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
@@ -361,11 +359,16 @@
dev = (rtl8150_t *)data;
+ spin_lock_irq(&dev->rx_pool_lock);
fill_skb_pool(dev);
+ spin_unlock_irq(&dev->rx_pool_lock);
if (test_bit(RX_URB_FAIL, &dev->flags))
if (dev->rx_skb)
goto try_again;
- if (!(skb = pull_skb(dev)))
+ spin_lock_irq(&dev->rx_pool_lock);
+ skb = pull_skb(dev);
+ spin_unlock_irq(&dev->rx_pool_lock);
+ if (skb == NULL)
goto tlsched;
dev->rx_skb = skb;
FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
@@ -426,51 +429,41 @@
{
struct sk_buff *skb;
int i;
- unsigned long flags;
- spin_lock_irqsave(&dev->rx_pool_lock, flags);
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) {
- spin_unlock_irqrestore(&dev->rx_pool_lock, flags);
return;
}
skb->dev = dev->netdev;
skb_reserve(skb, 2);
dev->rx_skb_pool[i] = skb;
}
- spin_unlock_irqrestore(&dev->rx_pool_lock, flags);
}
static void free_skb_pool(rtl8150_t *dev)
{
int i;
- spin_lock_irq(&dev->rx_pool_lock);
for (i = 0; i < RX_SKB_POOL_SIZE; i++)
if (dev->rx_skb_pool[i])
dev_kfree_skb(dev->rx_skb_pool[i]);
- spin_unlock_irq(&dev->rx_pool_lock);
}
-static struct sk_buff *pull_skb(rtl8150_t *dev)
+static inline struct sk_buff *pull_skb(rtl8150_t *dev)
{
struct sk_buff *skb;
int i;
- unsigned long flags;
- spin_lock_irqsave(&dev->rx_pool_lock, flags);
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;
- spin_unlock_irqrestore(&dev->rx_pool_lock, flags);
return skb;
}
}
- spin_unlock_irqrestore(&dev->rx_pool_lock, flags);
return NULL;
}
@@ -578,8 +571,8 @@
if (dev == NULL) {
return -ENODEV;
}
-
- dev->rx_skb = pull_skb(dev);
+ if (dev->rx_skb == NULL)
+ dev->rx_skb = pull_skb(dev);
if (!dev->rx_skb)
return -ENOMEM;
@@ -816,13 +809,13 @@
dev = NULL;
}
-static int __init usb_rtl8150_init(void)
+int __init usb_rtl8150_init(void)
{
info(DRIVER_DESC " " DRIVER_VERSION);
return usb_register(&rtl8150_driver);
}
-static void __exit usb_rtl8150_exit(void)
+void __exit usb_rtl8150_exit(void)
{
usb_deregister(&rtl8150_driver);
}
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Bringing you mounds of caffeinated joy.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel