summaryrefslogtreecommitdiffstats
path: root/drivers/usb/pegasus.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-08-28 22:00:09 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-08-28 22:00:09 +0000
commit1a1d77dd589de5a567fa95e36aa6999c704ceca4 (patch)
tree141e31f89f18b9fe0831f31852e0435ceaccafc5 /drivers/usb/pegasus.c
parentfb9c690a18b3d66925a65b17441c37fa14d4370b (diff)
Merge with 2.4.0-test7.
Diffstat (limited to 'drivers/usb/pegasus.c')
-rw-r--r--drivers/usb/pegasus.c385
1 files changed, 230 insertions, 155 deletions
diff --git a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c
index 0a264faaf..96a28da5e 100644
--- a/drivers/usb/pegasus.c
+++ b/drivers/usb/pegasus.c
@@ -1,7 +1,7 @@
/*
** Pegasus: USB 10/100Mbps/HomePNA (1Mbps) Controller
**
-** Copyright (c) 1999,2000 Petko Manolov - Petkan (petkan@spct.net)
+** Copyright (c) 1999,2000 Petko Manolov - Petkan (petkan@dce.bg)
**
**
** ChangeLog:
@@ -42,16 +42,26 @@
#include <linux/usb.h>
-static const char *version = __FILE__ ": v0.4.0 2000/06/15 (C) 1999-2000 Petko Manolov (petkan@spct.net)\n";
+static const char *version = __FILE__ ": v0.4.3 2000/08/22 (C) 1999-2000 Petko Manolov (petkan@dce.bg)\n";
+
+
+#define PEGASUS_USE_WAITQ
#define PEGASUS_MTU 1500
#define PEGASUS_MAX_MTU 1536
-#define SROM_WRITE 0x01
-#define SROM_READ 0x02
-#define PEGASUS_TX_TIMEOUT (HZ*5)
-#define PEGASUS_CTRL_TIMEOUT 1000
-#define PEGASUS_RESET 1
+#define EPROM_WRITE 0x01
+#define EPROM_READ 0x02
+#define PEGASUS_TX_TIMEOUT (HZ*10)
+#define PEGASUS_CTRL_TIMEOUT (HZ*5)
+#define PEGASUS_CTRL_WAIT (1<<31)
+#define PEGASUS_RUNNING 1
+#define PEGASUS_REQT_READ 0xc0
+#define PEGASUS_REQT_WRITE 0x40
+#define PEGASUS_REQ_GET_REGS 0xf0
+#define PEGASUS_REQ_SET_REGS 0xf1
+#define PEGASUS_REQ_SET_REG PEGASUS_REQ_SET_REGS
+#define NUM_CTRL_URBS 0x10
#define ALIGN(x) x __attribute__((aligned(L1_CACHE_BYTES)))
@@ -75,16 +85,26 @@ enum pegasus_registers {
};
+struct pegasus;
+struct ctrl_urb_pool {
+ struct pegasus *pegasus;
+ struct urb urb;
+ devrequest dr;
+ __u8 busy;
+};
+
+
struct pegasus {
struct usb_device *usb;
struct net_device *net;
struct net_device_stats stats;
int flags;
- spinlock_t pegasus_lock, ctrl_lock;
- struct urb rx_urb, tx_urb, intr_urb, ctrl_urb;
- devrequest dr;
- unsigned char ALIGN(rx_buff[PEGASUS_MAX_MTU]);
- unsigned char ALIGN(tx_buff[PEGASUS_MAX_MTU]);
+ struct urb rx_urb, tx_urb, intr_urb;
+ struct ctrl_urb_pool ALIGN(ctrl[NUM_CTRL_URBS]);
+ wait_queue_head_t ctrl_wait;
+ struct semaphore ctrl_sem;
+ unsigned char ALIGN(rx_buff[PEGASUS_MAX_MTU]);
+ unsigned char ALIGN(tx_buff[PEGASUS_MAX_MTU]);
unsigned char ALIGN(intr_buff[8]);
};
@@ -100,10 +120,11 @@ static int loopback = 0;
static int multicast_filter_limit = 32;
-MODULE_AUTHOR("Petko Manolov <petkan@spct.net>");
+MODULE_AUTHOR("Petko Manolov <petkan@dce.bg>");
MODULE_DESCRIPTION("ADMtek AN986 Pegasus USB Ethernet driver");
MODULE_PARM(loopback, "i");
-MODULE_PARM_DESC(loopback, "Enable loopback mode (Bit 0) and ??? (Bit 1)");
+MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
+
static struct usb_eth_dev usb_dev_id[] = {
{"Billionton USB-100", 0x08dd, 0x0986, NULL},
@@ -112,8 +133,10 @@ static struct usb_eth_dev usb_dev_id[] = {
{"D-Link DSB-650TX", 0x2001, 0x4001, NULL},
{"D-Link DSB-650TX", 0x2001, 0x4002, NULL},
{"D-Link DSB-650TX(PNA)", 0x2001, 0x4003, NULL},
+ {"D-Link DSB-650", 0x2001, 0xabc1, NULL},
{"D-Link DU-E10", 0x07b8, 0xabc1, NULL},
{"D-Link DU-E100", 0x07b8, 0x4002, NULL},
+ {"Linksys USB10TX", 0x066b, 0x2202, NULL},
{"Linksys USB100TX", 0x066b, 0x2203, NULL},
{"Linksys USB100TX", 0x066b, 0x2204, NULL},
{"Linksys USB Ethernet Adapter", 0x066b, 0x2206, NULL},
@@ -122,112 +145,149 @@ static struct usb_eth_dev usb_dev_id[] = {
{"Accton USB 10/100 Ethernet Adapter", 0x083a, 0x1046, NULL},
{"IO DATA USB ET/TX", 0x04bb, 0x0904, NULL},
{"LANEED USB Ethernet LD-USB/TX", 0x056e, 0x4002, NULL},
+ {"SOHOware NUB100 Ethernet", 0x15e8, 0x9100, NULL},
{NULL, 0, 0, NULL}
};
-
-static void pegasus_ctrl_end( urb_t *urb )
+static void pegasus_unlink_ctrl_urbs( struct pegasus *pegasus )
{
- if ( urb->status )
- warn("ctrl_urb end status %d", urb->status);
+ int i;
+
+ for ( i=0; i < NUM_CTRL_URBS; i++ ) {
+ if ( pegasus->ctrl[i].urb.status == -EINPROGRESS )
+ usb_unlink_urb( &pegasus->ctrl[i].urb );
+ }
}
-static int pegasus_ctrl_timeout( urb_t *ctrl_urb )
+static int pegasus_find_ctrl_urb( struct pegasus *pegasus )
{
- int timeout=0;
-
- while ( ctrl_urb->status == -EINPROGRESS ) {
- if ( timeout++ < PEGASUS_CTRL_TIMEOUT ) {
- udelay(100);
- continue;
- }
- err("ctrl urb busy %d", ctrl_urb->status);
- usb_unlink_urb( ctrl_urb );
- return ctrl_urb->status;
- }
- return 0;
+ int i=0;
+
+ while( i < NUM_CTRL_URBS && (pegasus->ctrl[i].busy == 1 ||
+ (pegasus->ctrl[i].urb.status == -EINPROGRESS)) )
+ i++;
+
+ return i;
}
-static int pegasus_get_registers( struct pegasus *pegasus, __u16 indx, __u16 size, void *data )
+static void pegasus_ctrl_end( urb_t *urb )
{
- int ret;
+ struct ctrl_urb_pool *ctrl = urb->context;
+ struct pegasus *pegasus = ctrl->pegasus;
- spin_lock( &pegasus->ctrl_lock );
- pegasus->dr.requesttype = 0xc0;
- pegasus->dr.request = 0xf0;
- pegasus->dr.value = 0x0;
- pegasus->dr.index = indx;
- pegasus->dr.length = pegasus->ctrl_urb.transfer_buffer_length = size;
+ if ( !pegasus )
+ return;
- FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
- usb_rcvctrlpipe(pegasus->usb,0), (char *)&pegasus->dr,
- data, size, pegasus_ctrl_end, pegasus );
+ if ( urb->status )
+ warn("ctrl_urb end status %d", urb->status);
+ ctrl->busy = 0;
+#ifdef PEGASUS_USE_WAITQ
+ wake_up_interruptible( &pegasus->ctrl_wait );
+#endif
+}
- if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) )
- err("BAD CTRLs %d", ret);
- else
- ret = pegasus_ctrl_timeout( &pegasus->ctrl_urb );
- spin_unlock( &pegasus->ctrl_lock );
+static int pegasus_get_registers( struct pegasus *pegasus, __u16 indx, __u16 size, void *data )
+{
+ int ret, i;
+ struct ctrl_urb_pool *ctrl;
+
+ if ( (i = pegasus_find_ctrl_urb( pegasus )) == NUM_CTRL_URBS ) {
+ return -1;
+ }
+ ctrl = &pegasus->ctrl[i];
+ ctrl->busy = 1;
+ ctrl->pegasus = pegasus;
+
+ ctrl->dr.requesttype = PEGASUS_REQT_READ;
+ ctrl->dr.request = PEGASUS_REQ_GET_REGS;
+ ctrl->dr.value = 0;
+ ctrl->dr.index = cpu_to_le16p(&indx);
+ ctrl->dr.length =
+ ctrl->urb.transfer_buffer_length = cpu_to_le16p(&size);
+
+ FILL_CONTROL_URB( &ctrl->urb, pegasus->usb,
+ usb_rcvctrlpipe(pegasus->usb,0),
+ (char *)&ctrl->dr,
+ data, size, pegasus_ctrl_end, ctrl );
+
+ if ( (ret = usb_submit_urb( &ctrl->urb )) )
+ err( __FUNCTION__ " BAD CTRLs %d", ret);
+#ifdef PEGASUS_USE_WAITQ
+ interruptible_sleep_on( &pegasus->ctrl_wait );
+#endif
return ret;
}
static int pegasus_set_registers( struct pegasus *pegasus, __u16 indx, __u16 size, void *data )
{
- int ret;
-
-
- spin_lock( &pegasus->ctrl_lock );
- pegasus->dr.requesttype = 0x40;
- pegasus->dr.request = 0xf1;
- pegasus->dr.value = 0x0;
- pegasus->dr.index = indx;
- pegasus->dr.length = pegasus->ctrl_urb.transfer_buffer_length = size;
-
- FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
- usb_sndctrlpipe(pegasus->usb,0), (char *)&pegasus->dr,
- data, size, pegasus_ctrl_end, pegasus );
-
- if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) )
- err("BAD CTRL %d", ret);
- else
- ret = pegasus_ctrl_timeout( &pegasus->ctrl_urb );
-
- spin_unlock( &pegasus->ctrl_lock );
+ int ret, i;
+ struct ctrl_urb_pool *ctrl;
+
+ if ( (i = pegasus_find_ctrl_urb( pegasus )) == NUM_CTRL_URBS ) {
+ return -1;
+ }
+ ctrl = &pegasus->ctrl[i];
+ ctrl->busy = 1;
+ ctrl->pegasus = pegasus;
+
+ ctrl->dr.requesttype = PEGASUS_REQT_WRITE;
+ ctrl->dr.request = PEGASUS_REQ_SET_REGS;
+ ctrl->dr.value = 0;
+ ctrl->dr.index = cpu_to_le16p( &indx );
+ ctrl->dr.length =
+ ctrl->urb.transfer_buffer_length = cpu_to_le16p( &size );
+
+ FILL_CONTROL_URB( &ctrl->urb, pegasus->usb,
+ usb_sndctrlpipe(pegasus->usb,0),
+ (char *)&ctrl->dr,
+ data, size, pegasus_ctrl_end, ctrl );
+
+ if ( (ret = usb_submit_urb( &ctrl->urb )) )
+ err( __FUNCTION__ " BAD CTRL %d", ret);
+#ifdef PEGASUS_USE_WAITQ
+ interruptible_sleep_on( &pegasus->ctrl_wait );
+#endif
return ret;
}
static int pegasus_set_register( struct pegasus *pegasus, __u16 indx,__u8 data )
{
- int ret;
-
-
- spin_lock( &pegasus->ctrl_lock );
- pegasus->dr.requesttype = 0x40;
- pegasus->dr.request = 0xf1;
- pegasus->dr.value = data;
- pegasus->dr.index = indx;
- pegasus->dr.length = pegasus->ctrl_urb.transfer_buffer_length = 1;
-
- FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
- usb_sndctrlpipe(pegasus->usb,0), (char *)&pegasus->dr,
- &data, 1, pegasus_ctrl_end, pegasus );
-
- if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) )
- err("BAD CTRL %d", ret);
- else
- ret = pegasus_ctrl_timeout( &pegasus->ctrl_urb );
-
- spin_unlock( &pegasus->ctrl_lock );
+ int ret, i;
+ struct ctrl_urb_pool *ctrl;
+
+ if ( (i = pegasus_find_ctrl_urb( pegasus )) == NUM_CTRL_URBS ) {
+ return -1;
+ }
+ ctrl = &pegasus->ctrl[i];
+ ctrl->busy = 1;
+ ctrl->pegasus = pegasus;
+
+ ctrl->dr.requesttype = PEGASUS_REQT_WRITE;
+ ctrl->dr.request = PEGASUS_REQ_SET_REG;
+ ctrl->dr.value = cpu_to_le16p( &data );
+ ctrl->dr.index = cpu_to_le16p( &indx );
+ ctrl->dr.length = ctrl->urb.transfer_buffer_length = 1;
+
+ FILL_CONTROL_URB( &ctrl->urb, pegasus->usb,
+ usb_sndctrlpipe(pegasus->usb,0),
+ (char *)&ctrl->dr,
+ &data, 1, pegasus_ctrl_end, ctrl );
+
+ if ( (ret = usb_submit_urb( &ctrl->urb )) )
+ err( __FUNCTION__ " BAD CTRL %d", ret);
+#ifdef PEGASUS_USE_WAITQ
+ interruptible_sleep_on( &pegasus->ctrl_wait );
+#endif
return ret;
}
@@ -244,10 +304,9 @@ static int pegasus_read_phy_word(struct pegasus *pegasus, __u8 index, __u16 *reg
*regdata = *(__u16 *)(data);
return 0;
}
- udelay(100);
}
-
warn("read_phy_word() failed");
+
return 1;
}
@@ -262,10 +321,9 @@ static int pegasus_write_phy_word(struct pegasus *pegasus, __u8 index, __u16 reg
pegasus_get_registers(pegasus, PhyCtrl, 1, data);
if (data[0] & 0x80)
return 0;
- udelay(100);
}
-
warn("write_phy_word() failed");
+
return 1;
}
@@ -284,8 +342,8 @@ static int pegasus_rw_eprom_word(struct pegasus *pegasus, __u8 index, __u16 *ret
return 0;
}
}
-
warn("pegasus_rw_eprom_word() failed");
+
return 1;
}
@@ -294,7 +352,7 @@ static int pegasus_get_node_id(struct pegasus *pegasus, __u8 *id)
{
int i;
for (i = 0; i < 3; i++)
- if (pegasus_rw_eprom_word(pegasus,i,(__u16 *)&id[i*2],SROM_READ))
+ if (pegasus_rw_eprom_word(pegasus, i, (__u16 *)&id[i*2], EPROM_READ))
return 1;
return 0;
}
@@ -311,8 +369,6 @@ static int pegasus_reset_mac(struct pegasus *pegasus)
if (~data & 0x08) {
if (loopback & 1)
return 0;
- if (loopback & 2)
- pegasus_write_phy_word(pegasus, 0, 0x4000);
pegasus_set_register(pegasus, Gpio0, 0x24);
pegasus_set_register(pegasus, Gpio0, 0x27);
return 0;
@@ -348,7 +404,6 @@ static int pegasus_start_net(struct net_device *dev, struct usb_device *usb)
if ((partmedia & 0x1f) != 1) {
warn("party FAIL %x", partmedia);
- /* return 5; FIXME */
}
data[0] = 0xc9;
@@ -361,15 +416,21 @@ static int pegasus_start_net(struct net_device *dev, struct usb_device *usb)
}
-static void pegasus_read_bulk(struct urb *urb)
+static void pegasus_read_bulk_callback( struct urb *urb )
{
struct pegasus *pegasus = urb->context;
- struct net_device *net = pegasus->net;
+ struct net_device *net; /* = pegasus->net;*/
int count = urb->actual_length, res;
- int rx_status = *(int *)(pegasus->rx_buff + count - 4);
+ int rx_status; /*= *(int *)(pegasus->rx_buff + count - 4);*/
struct sk_buff *skb;
__u16 pkt_len;
+ if ( !pegasus || !(pegasus->flags & PEGASUS_RUNNING) )
+ return;
+
+ net = pegasus->net;
+ rx_status = *(int *)(pegasus->rx_buff + count - 4);
+
if (urb->status) {
dbg("%s: RX status %d", net->name, urb->status);
goto goon;
@@ -408,31 +469,30 @@ static void pegasus_read_bulk(struct urb *urb)
pegasus->stats.rx_bytes += pkt_len;
goon:
- if ((res = usb_submit_urb(&pegasus->rx_urb)))
+ if ( (res = usb_submit_urb(&pegasus->rx_urb)) )
warn("(prb)failed rx_urb %d", res);
}
-static void pegasus_irq(urb_t *urb)
+static void pegasus_irq_callback( urb_t *urb )
{
__u8 *d = urb->transfer_buffer;
-
+
+
if ( d[0] )
dbg("txst0=0x%2x", d[0]);
}
-static void pegasus_write_bulk(struct urb *urb)
+static void pegasus_write_bulk_callback(struct urb *urb)
{
struct pegasus *pegasus = urb->context;
+ if ( !pegasus )
+ return;
if (urb->status)
info("%s: TX status %d", pegasus->net->name, urb->status);
-#if 1 /* Should be fixed */
- if (urb->status == -ETIMEDOUT)
- pegasus_reset_mac(pegasus);
-#endif
netif_wake_queue(pegasus->net);
}
@@ -440,10 +500,11 @@ static void pegasus_tx_timeout(struct net_device *net)
{
struct pegasus *pegasus = net->priv;
+ if ( !pegasus )
+ return;
usb_unlink_urb(&pegasus->tx_urb);
- warn("%s: Tx timed out. Reseting...", net->name);
- pegasus_reset_mac( pegasus );
+ warn("%s: Tx timed out.", net->name);
pegasus->stats.tx_errors++;
net->trans_start = jiffies;
@@ -457,13 +518,14 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
int count = ((skb->len+2) & 0x3f) ? skb->len+2 : skb->len+3;
int res;
- spin_lock(&pegasus->pegasus_lock);
-
netif_stop_queue(net);
+ if ( !(pegasus->flags & PEGASUS_RUNNING) )
+ return 0;
((__u16 *)pegasus->tx_buff)[0] = skb->len;
memcpy(pegasus->tx_buff+2, skb->data, skb->len);
- (&pegasus->tx_urb)->transfer_buffer_length = count;
+ pegasus->tx_urb.transfer_buffer_length = count;
+ pegasus->tx_urb.transfer_flags |= USB_ASYNC_UNLINK;
if ((res = usb_submit_urb(&pegasus->tx_urb))) {
warn("failed tx_urb %d", res);
@@ -477,8 +539,6 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
dev_kfree_skb(skb);
- spin_unlock(&pegasus->pegasus_lock);
-
return 0;
}
@@ -489,6 +549,15 @@ static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
}
+static inline void pegasus_stop_net( struct pegasus *pegasus )
+{
+ int tmp;
+
+ pegasus_get_registers( pegasus, EthCtrl0, 1, &tmp );
+ pegasus_set_register( pegasus, EthCtrl0, tmp & 0x3f );
+}
+
+
static int pegasus_open(struct net_device *net)
{
struct pegasus *pegasus = (struct pegasus *)net->priv;
@@ -506,8 +575,7 @@ static int pegasus_open(struct net_device *net)
warn("(open)failed intr_urb %d", res);
netif_start_queue(net);
-
- MOD_INC_USE_COUNT;
+ pegasus->flags |= PEGASUS_RUNNING;
return 0;
}
@@ -517,18 +585,15 @@ static int pegasus_close(struct net_device *net)
{
struct pegasus *pegasus = net->priv;
+ pegasus->flags &= ~PEGASUS_RUNNING;
+ pegasus_stop_net( pegasus );
+
netif_stop_queue(net);
- if ( pegasus->ctrl_urb.status == -EINPROGRESS )
- usb_unlink_urb(&pegasus->ctrl_urb);
- if ( pegasus->rx_urb.status == -EINPROGRESS )
- usb_unlink_urb(&pegasus->rx_urb);
- if ( pegasus->tx_urb.status == -EINPROGRESS )
- usb_unlink_urb(&pegasus->tx_urb);
- if ( pegasus->intr_urb.status == -EINPROGRESS )
- usb_unlink_urb(&pegasus->intr_urb);
-
- MOD_DEC_USE_COUNT;
+ usb_unlink_urb(&pegasus->rx_urb);
+ usb_unlink_urb(&pegasus->tx_urb);
+ usb_unlink_urb(&pegasus->intr_urb);
+ pegasus_unlink_ctrl_urbs( pegasus );
return 0;
}
@@ -558,24 +623,32 @@ static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
static void pegasus_set_rx_mode(struct net_device *net)
{
+#ifndef PEGASUS_USE_WAITQ
struct pegasus *pegasus = net->priv;
__u8 tmp;
+#endif
netif_stop_queue(net);
if (net->flags & IFF_PROMISC) {
- info("%s: Promiscuous mode enabled", net->name);
+#ifndef PEGASUS_USE_WAITQ
pegasus_get_registers(pegasus, EthCtrl2, 1, &tmp);
- pegasus_set_register(pegasus, EthCtrl2, tmp | 4);
+ pegasus_set_register(pegasus, EthCtrl2, tmp | 4);
+#endif
+ info("%s: Promiscuous mode enabled", net->name);
} else if ((net->mc_count > multicast_filter_limit) ||
(net->flags & IFF_ALLMULTI)) {
+#ifndef PEGASUS_USE_WAITQ
pegasus_set_register(pegasus, EthCtrl0, 0xfa);
pegasus_set_register(pegasus, EthCtrl2, 0);
+#endif
info("%s set allmulti", net->name);
} else {
- info("%s: set Rx mode", net->name);
+#ifndef PEGASUS_USE_WAITQ
pegasus_get_registers(pegasus, EthCtrl2, 1, &tmp);
- pegasus_set_register(pegasus, EthCtrl2, tmp & ~4);
+ pegasus_set_register(pegasus, EthCtrl2, tmp & ~4);
+#endif
+ info("%s: set Rx mode", net->name);
}
netif_wake_queue(net);
@@ -629,27 +702,32 @@ static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum)
net->get_stats = pegasus_netdev_stats;
net->mtu = PEGASUS_MTU;
+ init_MUTEX( &pegasus-> ctrl_sem );
+ init_waitqueue_head( &pegasus->ctrl_wait );
+
pegasus->usb = dev;
pegasus->net = net;
- pegasus->pegasus_lock = SPIN_LOCK_UNLOCKED;
- pegasus->ctrl_lock = SPIN_LOCK_UNLOCKED;
-
- FILL_BULK_URB(&pegasus->rx_urb, dev, usb_rcvbulkpipe(dev, 1),
- pegasus->rx_buff, PEGASUS_MAX_MTU, pegasus_read_bulk,
- pegasus);
- FILL_BULK_URB(&pegasus->tx_urb, dev, usb_sndbulkpipe(dev, 2),
- pegasus->tx_buff, PEGASUS_MAX_MTU, pegasus_write_bulk,
- pegasus);
- FILL_INT_URB(&pegasus->intr_urb, dev, usb_rcvintpipe(dev, 3),
- pegasus->intr_buff, 8, pegasus_irq, pegasus, 500);
+
+ FILL_BULK_URB( &pegasus->rx_urb, dev, usb_rcvbulkpipe(dev, 1),
+ pegasus->rx_buff, PEGASUS_MAX_MTU,
+ pegasus_read_bulk_callback, pegasus );
+ FILL_BULK_URB( &pegasus->tx_urb, dev, usb_sndbulkpipe(dev, 2),
+ pegasus->tx_buff, PEGASUS_MAX_MTU,
+ pegasus_write_bulk_callback, pegasus );
+ FILL_INT_URB( &pegasus->intr_urb, dev, usb_rcvintpipe(dev, 3),
+ pegasus->intr_buff, 8, pegasus_irq_callback,
+ pegasus, 128 );
if (pegasus_reset_mac(pegasus)) {
err("can't reset MAC");
kfree(pegasus);
+ pegasus = NULL;
return NULL;
}
- printk(KERN_INFO "%s: %s\n", net->name, usb_dev_id[dev_indx].name);
+ info( "%s: %s\n", net->name, usb_dev_id[dev_indx].name );
+
+ MOD_INC_USE_COUNT;
return pegasus;
}
@@ -664,21 +742,18 @@ static void pegasus_disconnect(struct usb_device *dev, void *ptr)
return;
}
- if (pegasus->net->flags & IFF_UP)
- dev_close(pegasus->net);
-
+ pegasus->flags &= ~PEGASUS_RUNNING;
unregister_netdev(pegasus->net);
-
- if ( pegasus->ctrl_urb.status == -EINPROGRESS )
- usb_unlink_urb(&pegasus->ctrl_urb);
- if ( pegasus->rx_urb.status == -EINPROGRESS )
- usb_unlink_urb(&pegasus->rx_urb);
- if ( pegasus->tx_urb.status == -EINPROGRESS )
- usb_unlink_urb(&pegasus->tx_urb);
- if ( pegasus->intr_urb.status == -EINPROGRESS )
- usb_unlink_urb(&pegasus->intr_urb);
+
+ usb_unlink_urb(&pegasus->rx_urb);
+ usb_unlink_urb(&pegasus->tx_urb);
+ usb_unlink_urb(&pegasus->intr_urb);
+ pegasus_unlink_ctrl_urbs( pegasus );
kfree(pegasus);
+ pegasus = NULL;
+
+ MOD_DEC_USE_COUNT;
}
@@ -690,7 +765,7 @@ static struct usb_driver pegasus_driver = {
int __init pegasus_init(void)
{
- printk( version );
+ info( "%s", version );
return usb_register(&pegasus_driver);
}