From: Greg KH To: torvalds@transmeta.com Cc: linux-usb-devel@lists.sourceforge.net, pmanolov@lnxw.com Subject: [PATCH 09 of 16] USB pegasus driver change and bugfix Hi, Here's a patch against 2.5.3-pre3 for the USB pegasus driver that converts it to dynamically allocate its urbs, fixes two memory leaks, and adds support for two new devices. Portions of this patch were written by Petko Manolov. thanks, greg k-h diff -Nru a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c --- a/drivers/usb/pegasus.c Tue Jan 22 12:54:24 2002 +++ b/drivers/usb/pegasus.c Tue Jan 22 12:54:24 2002 @@ -147,9 +147,9 @@ pegasus->dr.wValue = cpu_to_le16 (0); pegasus->dr.wIndex = cpu_to_le16p(&indx); pegasus->dr.wLength = cpu_to_le16p(&size); - pegasus->ctrl_urb.transfer_buffer_length = size; + pegasus->ctrl_urb->transfer_buffer_length = size; - FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb, + FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb, usb_rcvctrlpipe(pegasus->usb,0), (char *)&pegasus->dr, buffer, size, ctrl_callback, pegasus ); @@ -157,7 +157,7 @@ add_wait_queue( &pegasus->ctrl_wait, &wait ); set_current_state( TASK_UNINTERRUPTIBLE ); - if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { + if ( (ret = usb_submit_urb( pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRLs %d", ret); goto out; } @@ -197,9 +197,9 @@ pegasus->dr.wValue = cpu_to_le16 (0); pegasus->dr.wIndex = cpu_to_le16p( &indx ); pegasus->dr.wLength = cpu_to_le16p( &size ); - pegasus->ctrl_urb.transfer_buffer_length = size; + pegasus->ctrl_urb->transfer_buffer_length = size; - FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb, + FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb, usb_sndctrlpipe(pegasus->usb,0), (char *)&pegasus->dr, buffer, size, ctrl_callback, pegasus ); @@ -207,7 +207,7 @@ add_wait_queue( &pegasus->ctrl_wait, &wait ); set_current_state( TASK_UNINTERRUPTIBLE ); - if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { + if ( (ret = usb_submit_urb( pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRL %d", ret); goto out; } @@ -247,9 +247,9 @@ pegasus->dr.wValue = cpu_to_le16p( &dat); pegasus->dr.wIndex = cpu_to_le16p( &indx ); pegasus->dr.wLength = cpu_to_le16( 1 ); - pegasus->ctrl_urb.transfer_buffer_length = 1; + pegasus->ctrl_urb->transfer_buffer_length = 1; - FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb, + FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb, usb_sndctrlpipe(pegasus->usb,0), (char *)&pegasus->dr, buffer, 1, ctrl_callback, pegasus ); @@ -257,7 +257,7 @@ add_wait_queue( &pegasus->ctrl_wait, &wait ); set_current_state( TASK_UNINTERRUPTIBLE ); - if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { + if ( (ret = usb_submit_urb( pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRL %d", ret); goto out; } @@ -280,14 +280,14 @@ pegasus->dr.wValue = 0; pegasus->dr.wIndex = cpu_to_le16(EthCtrl0); pegasus->dr.wLength = cpu_to_le16(3); - pegasus->ctrl_urb.transfer_buffer_length = 3; + pegasus->ctrl_urb->transfer_buffer_length = 3; - FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb, + FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb, usb_sndctrlpipe(pegasus->usb,0), (char *)&pegasus->dr, pegasus->eth_regs, 3, ctrl_callback, pegasus ); - if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) + if ( (ret = usb_submit_urb( pegasus->ctrl_urb )) ) err( __FUNCTION__ " BAD CTRL %d, flags %x",ret,pegasus->flags ); return ret; @@ -569,11 +569,11 @@ pegasus->stats.rx_bytes += pkt_len; goon: - FILL_BULK_URB( &pegasus->rx_urb, pegasus->usb, + FILL_BULK_URB( pegasus->rx_urb, pegasus->usb, usb_rcvbulkpipe(pegasus->usb, 1), pegasus->rx_buff, PEGASUS_MAX_MTU, read_bulk_callback, pegasus ); - if ( (res = usb_submit_urb(&pegasus->rx_urb)) ) + if ( (res = usb_submit_urb(pegasus->rx_urb)) ) warn( __FUNCTION__ " failed submint rx_urb %d", res); pegasus->flags &= ~PEGASUS_RX_BUSY; } @@ -639,8 +639,8 @@ return; warn("%s: Tx timed out.", net->name); - pegasus->tx_urb.transfer_flags |= USB_ASYNC_UNLINK; - usb_unlink_urb( &pegasus->tx_urb ); + pegasus->tx_urb->transfer_flags |= USB_ASYNC_UNLINK; + usb_unlink_urb( pegasus->tx_urb ); pegasus->stats.tx_errors++; } @@ -656,12 +656,12 @@ ((__u16 *)pegasus->tx_buff)[0] = cpu_to_le16( l16 ); memcpy(pegasus->tx_buff+2, skb->data, skb->len); - FILL_BULK_URB( &pegasus->tx_urb, pegasus->usb, + FILL_BULK_URB( pegasus->tx_urb, pegasus->usb, usb_sndbulkpipe(pegasus->usb, 2), pegasus->tx_buff, PEGASUS_MAX_MTU, write_bulk_callback, pegasus ); - pegasus->tx_urb.transfer_buffer_length = count; - if ((res = usb_submit_urb(&pegasus->tx_urb))) { + pegasus->tx_urb->transfer_buffer_length = count; + if ((res = usb_submit_urb(pegasus->tx_urb))) { warn("failed tx_urb %d", res); pegasus->stats.tx_errors++; netif_start_queue( net ); @@ -717,18 +717,18 @@ err("can't enable_net_traffic() - %d", res); return -EIO; } - FILL_BULK_URB( &pegasus->rx_urb, pegasus->usb, + FILL_BULK_URB( pegasus->rx_urb, pegasus->usb, usb_rcvbulkpipe(pegasus->usb, 1), pegasus->rx_buff, PEGASUS_MAX_MTU, read_bulk_callback, pegasus ); - if ( (res = usb_submit_urb(&pegasus->rx_urb)) ) + if ( (res = usb_submit_urb(pegasus->rx_urb)) ) warn( __FUNCTION__ " failed rx_urb %d", res ); #ifdef PEGASUS_USE_INTR - FILL_INT_URB( &pegasus->intr_urb, pegasus->usb, + 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)) ) + if ( (res = usb_submit_urb(pegasus->intr_urb)) ) warn( __FUNCTION__ " failed intr_urb %d", res); #endif netif_start_queue( net ); @@ -747,11 +747,11 @@ 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 ); + 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 ); + usb_unlink_urb( pegasus->intr_urb ); #endif return 0; @@ -800,7 +800,7 @@ } pegasus->flags |= ETH_REGS_CHANGE; - ctrl_callback( &pegasus->ctrl_urb ); + ctrl_callback( pegasus->ctrl_urb ); netif_wake_queue(net); } @@ -856,6 +856,33 @@ pegasus->dev_index = dev_index; init_waitqueue_head( &pegasus->ctrl_wait ); + pegasus->ctrl_urb = usb_alloc_urb(0); + if (!pegasus->ctrl_urb) { + kfree (pegasus); + return NULL; + } + pegasus->rx_urb = usb_alloc_urb(0); + if (!pegasus->rx_urb) { + usb_free_urb (pegasus->ctrl_urb); + kfree (pegasus); + return NULL; + } + pegasus->tx_urb = usb_alloc_urb(0); + 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); + if (!pegasus->intr_urb) { + usb_free_urb (pegasus->tx_urb); + usb_free_urb (pegasus->rx_urb); + usb_free_urb (pegasus->ctrl_urb); + kfree (pegasus); + return NULL; + } + net = init_etherdev( NULL, 0 ); if ( !net ) { kfree( pegasus ); @@ -883,6 +910,7 @@ if ( reset_mac(pegasus) ) { err("can't reset MAC"); unregister_netdev( pegasus->net ); + kfree(pegasus->net); kfree(pegasus); pegasus = NULL; return NULL; @@ -919,6 +947,11 @@ pegasus->flags |= PEGASUS_UNPLUG; unregister_netdev( pegasus->net ); usb_dec_dev_use( dev ); + usb_free_urb (pegasus->intr_urb); + usb_free_urb (pegasus->tx_urb); + usb_free_urb (pegasus->rx_urb); + usb_free_urb (pegasus->ctrl_urb); + kfree( pegasus->net ); kfree( pegasus ); pegasus = NULL; } diff -Nru a/drivers/usb/pegasus.h b/drivers/usb/pegasus.h --- a/drivers/usb/pegasus.h Tue Jan 22 12:54:25 2002 +++ b/drivers/usb/pegasus.h Tue Jan 22 12:54:25 2002 @@ -107,7 +107,7 @@ unsigned features; int dev_index; int intr_interval; - struct urb ctrl_urb, rx_urb, tx_urb, intr_urb; + struct urb *ctrl_urb, *rx_urb, *tx_urb, *intr_urb; struct usb_ctrlrequest dr; wait_queue_head_t ctrl_wait; struct semaphore ctrl_sem; @@ -145,6 +145,7 @@ #define VENDOR_SMARTBRIDGES 0x08d1 #define VENDOR_SMC 0x0707 #define VENDOR_SOHOWARE 0x15e8 +#define VENDOR_SIEMENS 0x067c #else /* PEGASUS_DEV */ @@ -173,6 +174,8 @@ DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046, DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046, + DEFAULT_GPIO_RESET ) PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet", VENDOR_ADMTEK, 0x8511, DEFAULT_GPIO_RESET | PEGASUS_II ) @@ -244,6 +247,8 @@ PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001, DEFAULT_GPIO_RESET )