diff options
Diffstat (limited to 'drivers/net/usb/rtl8150.c')
| -rw-r--r-- | drivers/net/usb/rtl8150.c | 293 | 
1 files changed, 117 insertions, 176 deletions
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index e85c89c6706..6e87e571004 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -6,7 +6,6 @@   * version 2 as published by the Free Software Foundation.   */ -#include <linux/init.h>  #include <linux/signal.h>  #include <linux/slab.h>  #include <linux/module.h> @@ -85,32 +84,6 @@  #define INT_CRERR_CNT		0x06  #define INT_COL_CNT		0x07 -/* Transmit status register errors */ -#define TSR_ECOL		(1<<5) -#define TSR_LCOL		(1<<4) -#define TSR_LOSS_CRS		(1<<3) -#define TSR_JBR			(1<<2) -#define TSR_ERRORS		(TSR_ECOL | TSR_LCOL | TSR_LOSS_CRS | TSR_JBR) -/* Receive status register errors */ -#define RSR_CRC			(1<<2) -#define RSR_FAE			(1<<1) -#define RSR_ERRORS		(RSR_CRC | RSR_FAE) - -/* Media status register definitions */ -#define MSR_DUPLEX		(1<<4) -#define MSR_SPEED		(1<<3) -#define MSR_LINK		(1<<2) - -/* Interrupt pipe data */ -#define INT_TSR			0x00 -#define INT_RSR			0x01 -#define INT_MSR			0x02 -#define INT_WAKSR		0x03 -#define INT_TXOK_CNT		0x04 -#define INT_RXLOST_CNT		0x05 -#define INT_CRERR_CNT		0x06 -#define INT_COL_CNT		0x07 -  #define	RTL8150_MTU		1540  #define	RTL8150_TX_TIMEOUT	(HZ) @@ -156,39 +129,25 @@ struct rtl8150 {  	struct usb_device *udev;  	struct tasklet_struct tl;  	struct net_device *netdev; -	struct urb *rx_urb, *tx_urb, *intr_urb, *ctrl_urb; +	struct urb *rx_urb, *tx_urb, *intr_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; -	__le16 rx_creg;  	u8 *intr_buff;  	u8 phy;  };  typedef struct rtl8150 rtl8150_t; -static void fill_skb_pool(rtl8150_t *); -static void free_skb_pool(rtl8150_t *); -static inline struct sk_buff *pull_skb(rtl8150_t *); -static void rtl8150_disconnect(struct usb_interface *intf); -static int rtl8150_probe(struct usb_interface *intf, -			   const struct usb_device_id *id); -static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message); -static int rtl8150_resume(struct usb_interface *intf); +struct async_req { +	struct usb_ctrlrequest dr; +	u16 rx_creg; +};  static const char driver_name [] = "rtl8150"; -static struct usb_driver rtl8150_driver = { -	.name =		driver_name, -	.probe =	rtl8150_probe, -	.disconnect =	rtl8150_disconnect, -	.id_table =	rtl8150_table, -	.suspend =	rtl8150_suspend, -	.resume =	rtl8150_resume -}; -  /*  **  **	device related part of the code @@ -208,50 +167,47 @@ static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)  			       indx, 0, data, size, 500);  } -static void ctrl_callback(struct urb *urb) +static void async_set_reg_cb(struct urb *urb)  { -	rtl8150_t *dev; +	struct async_req *req = (struct async_req *)urb->context;  	int status = urb->status; -	switch (status) { -	case 0: -		break; -	case -EINPROGRESS: -		break; -	case -ENOENT: -		break; -	default: -		if (printk_ratelimit()) -			dev_warn(&urb->dev->dev, "ctrl urb status %d\n", status); -	} -	dev = urb->context; -	clear_bit(RX_REG_SET, &dev->flags); +	if (status < 0) +		dev_dbg(&urb->dev->dev, "%s failed with %d", __func__, status); +	kfree(req); +	usb_free_urb(urb);  } -static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) +static int async_set_registers(rtl8150_t *dev, u16 indx, u16 size, u16 reg)  { -	int ret; - -	if (test_bit(RX_REG_SET, &dev->flags)) -		return -EAGAIN; +	int res = -ENOMEM; +	struct urb *async_urb; +	struct async_req *req; -	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; -	usb_fill_control_urb(dev->ctrl_urb, dev->udev, -			 usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, -			 &dev->rx_creg, size, ctrl_callback, dev); -	if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) { -		if (ret == -ENODEV) +	req = kmalloc(sizeof(struct async_req), GFP_ATOMIC); +	if (req == NULL) +		return res; +	async_urb = usb_alloc_urb(0, GFP_ATOMIC); +	if (async_urb == NULL) { +		kfree(req); +		return res; +	} +	req->rx_creg = cpu_to_le16(reg); +	req->dr.bRequestType = RTL8150_REQT_WRITE; +	req->dr.bRequest = RTL8150_REQ_SET_REGS; +	req->dr.wIndex = 0; +	req->dr.wValue = cpu_to_le16(indx); +	req->dr.wLength = cpu_to_le16(size); +	usb_fill_control_urb(async_urb, dev->udev, +	                     usb_sndctrlpipe(dev->udev, 0), (void *)&req->dr, +			     &req->rx_creg, size, async_set_reg_cb, req); +	res = usb_submit_urb(async_urb, GFP_ATOMIC); +	if (res) { +		if (res == -ENODEV)  			netif_device_detach(dev->netdev); -		err("control request submission failed: %d", ret); -	} else -		set_bit(RX_REG_SET, &dev->flags); - -	return ret; +		dev_err(&dev->udev->dev, "%s failed with %d\n", __func__, res); +	} +	return res;  }  static int read_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 * reg) @@ -318,7 +274,7 @@ static int rtl8150_set_mac_address(struct net_device *netdev, void *p)  		return -EBUSY;  	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); -	dbg("%s: Setting MAC address to %pM\n", netdev->name, netdev->dev_addr); +	netdev_dbg(netdev, "Setting MAC address to %pM\n", netdev->dev_addr);  	/* Set the IDR registers. */  	set_registers(dev, IDR, netdev->addr_len, netdev->dev_addr);  #ifdef EEPROM_WRITE @@ -333,7 +289,7 @@ static int rtl8150_set_mac_address(struct net_device *netdev, void *p)  	/* 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,  +		set_registers(dev, IDR_EEPROM + (i * 2), 2,  		netdev->dev_addr + (i * 2));  	}  	/* Clear the WEPROM bit (preventing accidental eeprom writes). */ @@ -373,13 +329,6 @@ static int alloc_all_urbs(rtl8150_t * dev)  		usb_free_urb(dev->tx_urb);  		return 0;  	} -	dev->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); -	if (!dev->ctrl_urb) { -		usb_free_urb(dev->rx_urb); -		usb_free_urb(dev->tx_urb); -		usb_free_urb(dev->intr_urb); -		return 0; -	}  	return 1;  } @@ -389,7 +338,6 @@ static void free_all_urbs(rtl8150_t * dev)  	usb_free_urb(dev->rx_urb);  	usb_free_urb(dev->tx_urb);  	usb_free_urb(dev->intr_urb); -	usb_free_urb(dev->ctrl_urb);  }  static void unlink_all_urbs(rtl8150_t * dev) @@ -397,7 +345,6 @@ static void unlink_all_urbs(rtl8150_t * dev)  	usb_kill_urb(dev->rx_urb);  	usb_kill_urb(dev->tx_urb);  	usb_kill_urb(dev->intr_urb); -	usb_kill_urb(dev->ctrl_urb);  }  static inline struct sk_buff *pull_skb(rtl8150_t *dev) @@ -490,44 +437,6 @@ resched:  	tasklet_schedule(&dev->tl);  } -static void rx_fixup(unsigned long data) -{ -	rtl8150_t *dev; -	struct sk_buff *skb; -	int status; - -	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; -	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; -	usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), -		      dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); -try_again: -	status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); -	if (status == -ENODEV) { -		netif_device_detach(dev->netdev); -	} else if (status) { -		set_bit(RX_URB_FAIL, &dev->flags); -		goto tlsched; -	} else { -		clear_bit(RX_URB_FAIL, &dev->flags); -	} - -	return; -tlsched: -	tasklet_schedule(&dev->tl); -} -  static void write_bulk_callback(struct urb *urb)  {  	rtl8150_t *dev; @@ -584,12 +493,12 @@ static void intr_callback(struct urb *urb)  	if ((d[INT_MSR] & MSR_LINK) == 0) {  		if (netif_carrier_ok(dev->netdev)) {  			netif_carrier_off(dev->netdev); -			dbg("%s: LINK LOST\n", __func__); +			netdev_dbg(dev->netdev, "%s: LINK LOST\n", __func__);  		}  	} else {  		if (!netif_carrier_ok(dev->netdev)) {  			netif_carrier_on(dev->netdev); -			dbg("%s: LINK CAME BACK\n", __func__); +			netdev_dbg(dev->netdev, "%s: LINK CAME BACK\n", __func__);  		}  	} @@ -598,9 +507,9 @@ resubmit:  	if (res == -ENODEV)  		netif_device_detach(dev->netdev);  	else if (res) -		err ("can't resubmit intr, %s-%s/input0, status %d", -				dev->udev->bus->bus_name, -				dev->udev->devpath, res); +		dev_err(&dev->udev->dev, +			"can't resubmit intr, %s-%s/input0, status %d\n", +			dev->udev->bus->bus_name, dev->udev->devpath, res);  }  static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message) @@ -665,6 +574,42 @@ static void free_skb_pool(rtl8150_t *dev)  			dev_kfree_skb(dev->rx_skb_pool[i]);  } +static void rx_fixup(unsigned long data) +{ +	struct rtl8150 *dev = (struct rtl8150 *)data; +	struct sk_buff *skb; +	int status; + +	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; +	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; +	usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), +		      dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); +try_again: +	status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); +	if (status == -ENODEV) { +		netif_device_detach(dev->netdev); +	} else if (status) { +		set_bit(RX_URB_FAIL, &dev->flags); +		goto tlsched; +	} else { +		clear_bit(RX_URB_FAIL, &dev->flags); +	} + +	return; +tlsched: +	tasklet_schedule(&dev->tl); +} +  static int enable_net_traffic(rtl8150_t * dev)  {  	u8 cr, tcr, rcr, msr; @@ -674,7 +619,6 @@ static int enable_net_traffic(rtl8150_t * dev)  	}  	/* RCR bit7=1 attach Rx info at the end;  =0 HW CRC (which is broken) */  	rcr = 0x9e; -	dev->rx_creg = cpu_to_le16(rcr);  	tcr = 0xd8;  	cr = 0x0c;  	if (!(rcr & 0x80)) @@ -707,20 +651,22 @@ static void rtl8150_tx_timeout(struct net_device *netdev)  static void rtl8150_set_multicast(struct net_device *netdev)  {  	rtl8150_t *dev = netdev_priv(netdev); +	u16 rx_creg = 0x9e; +  	netif_stop_queue(netdev);  	if (netdev->flags & IFF_PROMISC) { -		dev->rx_creg |= cpu_to_le16(0x0001); +		rx_creg |= 0x0001;  		dev_info(&netdev->dev, "%s: promiscuous mode\n", netdev->name);  	} else if (!netdev_mc_empty(netdev) ||  		   (netdev->flags & IFF_ALLMULTI)) { -		dev->rx_creg &= cpu_to_le16(0xfffe); -		dev->rx_creg |= cpu_to_le16(0x0002); +		rx_creg &= 0xfffe; +		rx_creg |= 0x0002;  		dev_info(&netdev->dev, "%s: allmulti set\n", netdev->name);  	} else {  		/* ~RX_MULTICAST, ~RX_PROMISCUOUS */ -		dev->rx_creg &= cpu_to_le16(0x00fc); +		rx_creg &= 0x00fc;  	} -	async_set_registers(dev, RCR, 2); +	async_set_registers(dev, RCR, sizeof(rx_creg), rx_creg);  	netif_wake_queue(netdev);  } @@ -778,7 +724,7 @@ static int rtl8150_open(struct net_device *netdev)  		return -ENOMEM;  	set_registers(dev, IDR, 6, netdev->dev_addr); -	 +  	usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),  		      dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);  	if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) { @@ -821,9 +767,9 @@ static void rtl8150_get_drvinfo(struct net_device *netdev, struct ethtool_drvinf  {  	rtl8150_t *dev = netdev_priv(netdev); -	strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN); -	strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); -	usb_make_path(dev->udev, info->bus_info, sizeof info->bus_info); +	strlcpy(info->driver, driver_name, sizeof(info->driver)); +	strlcpy(info->version, DRIVER_VERSION, sizeof(info->version)); +	usb_make_path(dev->udev, info->bus_info, sizeof(info->bus_info));  }  static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) @@ -843,10 +789,11 @@ static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *e  	get_registers(dev, BMCR, 2, &bmcr);  	get_registers(dev, ANLP, 2, &lpa);  	if (bmcr & BMCR_ANENABLE) { +		u32 speed = ((lpa & (LPA_100HALF | LPA_100FULL)) ? +			     SPEED_100 : SPEED_10); +		ethtool_cmd_speed_set(ecmd, speed);  		ecmd->autoneg = AUTONEG_ENABLE; -		ecmd->speed = (lpa & (LPA_100HALF | LPA_100FULL)) ? -			     SPEED_100 : SPEED_10; -		if (ecmd->speed == SPEED_100) +		if (speed == SPEED_100)  			ecmd->duplex = (lpa & LPA_100FULL) ?  			    DUPLEX_FULL : DUPLEX_HALF;  		else @@ -854,8 +801,8 @@ static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *e  			    DUPLEX_FULL : DUPLEX_HALF;  	} else {  		ecmd->autoneg = AUTONEG_DISABLE; -		ecmd->speed = (bmcr & BMCR_SPEED100) ? -		    SPEED_100 : SPEED_10; +		ethtool_cmd_speed_set(ecmd, ((bmcr & BMCR_SPEED100) ? +					     SPEED_100 : SPEED_10));  		ecmd->duplex = (bmcr & BMCR_FULLDPLX) ?  		    DUPLEX_FULL : DUPLEX_HALF;  	} @@ -897,8 +844,8 @@ static const struct net_device_ops rtl8150_netdev_ops = {  	.ndo_stop		= rtl8150_close,  	.ndo_do_ioctl		= rtl8150_ioctl,  	.ndo_start_xmit		= rtl8150_start_xmit, -	.ndo_tx_timeout 	= rtl8150_tx_timeout, -	.ndo_set_multicast_list = rtl8150_set_multicast, +	.ndo_tx_timeout		= rtl8150_tx_timeout, +	.ndo_set_rx_mode	= rtl8150_set_multicast,  	.ndo_set_mac_address	= rtl8150_set_mac_address,  	.ndo_change_mtu		= eth_change_mtu, @@ -913,10 +860,8 @@ static int rtl8150_probe(struct usb_interface *intf,  	struct net_device *netdev;  	netdev = alloc_etherdev(sizeof(rtl8150_t)); -	if (!netdev) { -		err("Out of memory"); +	if (!netdev)  		return -ENOMEM; -	}  	dev = netdev_priv(netdev); @@ -928,29 +873,29 @@ static int rtl8150_probe(struct usb_interface *intf,  	tasklet_init(&dev->tl, rx_fixup, (unsigned long)dev);  	spin_lock_init(&dev->rx_pool_lock); -	 +  	dev->udev = udev;  	dev->netdev = netdev;  	netdev->netdev_ops = &rtl8150_netdev_ops;  	netdev->watchdog_timeo = RTL8150_TX_TIMEOUT; -	SET_ETHTOOL_OPS(netdev, &ops); +	netdev->ethtool_ops = &ops;  	dev->intr_interval = 100;	/* 100ms */  	if (!alloc_all_urbs(dev)) { -		err("out of memory"); +		dev_err(&intf->dev, "out of memory\n");  		goto out;  	}  	if (!rtl8150_reset(dev)) { -		err("couldn't reset the device"); +		dev_err(&intf->dev, "couldn't reset the device\n");  		goto out1;  	}  	fill_skb_pool(dev);  	set_ethernet_addr(dev); -	 +  	usb_set_intfdata(intf, dev);  	SET_NETDEV_DEV(netdev, &intf->dev);  	if (register_netdev(netdev) != 0) { -		err("couldn't register the device"); +		dev_err(&intf->dev, "couldn't register the device\n");  		goto out2;  	} @@ -976,7 +921,6 @@ static void rtl8150_disconnect(struct usb_interface *intf)  	usb_set_intfdata(intf, NULL);  	if (dev) {  		set_bit(RTL8150_UNPLUG, &dev->flags); -		tasklet_disable(&dev->tl);  		tasklet_kill(&dev->tl);  		unregister_netdev(dev->netdev);  		unlink_all_urbs(dev); @@ -989,20 +933,17 @@ static void rtl8150_disconnect(struct usb_interface *intf)  	}  } -static int __init usb_rtl8150_init(void) -{ -	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" -	       DRIVER_DESC "\n"); -	return usb_register(&rtl8150_driver); -} - -static void __exit usb_rtl8150_exit(void) -{ -	usb_deregister(&rtl8150_driver); -} +static struct usb_driver rtl8150_driver = { +	.name		= driver_name, +	.probe		= rtl8150_probe, +	.disconnect	= rtl8150_disconnect, +	.id_table	= rtl8150_table, +	.suspend	= rtl8150_suspend, +	.resume		= rtl8150_resume, +	.disable_hub_initiated_lpm = 1, +}; -module_init(usb_rtl8150_init); -module_exit(usb_rtl8150_exit); +module_usb_driver(rtl8150_driver);  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC);  | 
