⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbnet.c

📁 omap3 linux 2.6 用nocc去除了冗余代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		entry->state = rx_cleanup;		entry->urb = urb;		urb = NULL;		break;	    // data overrun ... flush fifo?	    case -EOVERFLOW:		dev->stats.rx_over_errors++;		// FALLTHROUGH	    default:		entry->state = rx_cleanup;		dev->stats.rx_errors++;		if (netif_msg_rx_err (dev))			devdbg (dev, "rx status %d", urb_status);		break;	}	defer_bh(dev, skb, &dev->rxq);	if (urb) {		if (netif_running (dev->net)				&& !test_bit (EVENT_RX_HALT, &dev->flags)) {			rx_submit (dev, urb, GFP_ATOMIC);			return;		}		usb_free_urb (urb);	}	if (netif_msg_rx_err (dev))		devdbg (dev, "no read resubmitted");}static void intr_complete (struct urb *urb){	struct usbnet	*dev = urb->context;	int		status = urb->status;	switch (status) {	    /* success */	    case 0:		dev->driver_info->status(dev, urb);		break;	    /* software-driven interface shutdown */	    case -ENOENT:		// urb killed	    case -ESHUTDOWN:		// hardware gone		if (netif_msg_ifdown (dev))			devdbg (dev, "intr shutdown, code %d", status);		return;	    /* NOTE:  not throttling like RX/TX, since this endpoint	     * already polls infrequently	     */	    default:		devdbg (dev, "intr status %d", status);		break;	}	if (!netif_running (dev->net))		return;	memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);	status = usb_submit_urb (urb, GFP_ATOMIC);	if (status != 0 && netif_msg_timer (dev))		deverr(dev, "intr resubmit --> %d", status);}/*-------------------------------------------------------------------------*/// unlink pending rx/tx; completion handlers do all other cleanupstatic int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q){	unsigned long		flags;	struct sk_buff		*skb, *skbnext;	int			count = 0;	spin_lock_irqsave (&q->lock, flags);	for (skb = q->next; skb != (struct sk_buff *) q; skb = skbnext) {		struct skb_data		*entry;		struct urb		*urb;		int			retval;		entry = (struct skb_data *) skb->cb;		urb = entry->urb;		skbnext = skb->next;		// during some PM-driven resume scenarios,		// these (async) unlinks complete immediately		retval = usb_unlink_urb (urb);		if (retval != -EINPROGRESS && retval != 0)			devdbg (dev, "unlink urb err, %d", retval);		else			count++;	}	spin_unlock_irqrestore (&q->lock, flags);	return count;}// Flush all pending rx urbs// minidrivers may need to do this when the MTU changesvoid usbnet_unlink_rx_urbs(struct usbnet *dev){	if (netif_running(dev->net)) {		(void) unlink_urbs (dev, &dev->rxq);		tasklet_schedule(&dev->bh);	}}EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs);/*-------------------------------------------------------------------------*/// precondition: never called in_interruptstatic int usbnet_stop (struct net_device *net){	struct usbnet		*dev = netdev_priv(net);	int			temp;	DECLARE_WAIT_QUEUE_HEAD_ONSTACK (unlink_wakeup);	DECLARE_WAITQUEUE (wait, current);	netif_stop_queue (net);	if (netif_msg_ifdown (dev))		devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",			dev->stats.rx_packets, dev->stats.tx_packets,			dev->stats.rx_errors, dev->stats.tx_errors			);	// ensure there are no more active urbs	add_wait_queue (&unlink_wakeup, &wait);	dev->wait = &unlink_wakeup;	temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq);	// maybe wait for deletions to finish.	while (!skb_queue_empty(&dev->rxq) &&	       !skb_queue_empty(&dev->txq) &&	       !skb_queue_empty(&dev->done)) {		msleep(UNLINK_TIMEOUT_MS);		if (netif_msg_ifdown (dev))			devdbg (dev, "waited for %d urb completions", temp);	}	dev->wait = NULL;	remove_wait_queue (&unlink_wakeup, &wait);	usb_kill_urb(dev->interrupt);	/* deferred work (task, timer, softirq) must also stop.	 * can't flush_scheduled_work() until we drop rtnl (later),	 * else workers could deadlock; so make workers a NOP.	 */	dev->flags = 0;	del_timer_sync (&dev->delay);	tasklet_kill (&dev->bh);	return 0;}/*-------------------------------------------------------------------------*/// posts reads, and enables write queuing// precondition: never called in_interruptstatic int usbnet_open (struct net_device *net){	struct usbnet		*dev = netdev_priv(net);	int			retval = 0;	struct driver_info	*info = dev->driver_info;	// put into "known safe" state	if (info->reset && (retval = info->reset (dev)) < 0) {		if (netif_msg_ifup (dev))			devinfo (dev,				"open reset fail (%d) usbnet usb-%s-%s, %s",				retval,				dev->udev->bus->bus_name, dev->udev->devpath,			info->description);		goto done;	}	// insist peer be connected	if (info->check_connect && (retval = info->check_connect (dev)) < 0) {		if (netif_msg_ifup (dev))			devdbg (dev, "can't open; %d", retval);		goto done;	}	/* start any status interrupt transfer */	if (dev->interrupt) {		retval = usb_submit_urb (dev->interrupt, GFP_KERNEL);		if (retval < 0) {			if (netif_msg_ifup (dev))				deverr (dev, "intr submit %d", retval);			goto done;		}	}	netif_start_queue (net);	if (netif_msg_ifup (dev)) {		char	*framing;		if (dev->driver_info->flags & FLAG_FRAMING_NC)			framing = "NetChip";		else if (dev->driver_info->flags & FLAG_FRAMING_GL)			framing = "GeneSys";		else if (dev->driver_info->flags & FLAG_FRAMING_Z)			framing = "Zaurus";		else if (dev->driver_info->flags & FLAG_FRAMING_RN)			framing = "RNDIS";		else if (dev->driver_info->flags & FLAG_FRAMING_AX)			framing = "ASIX";		else			framing = "simple";		devinfo (dev, "open: enable queueing "				"(rx %d, tx %d) mtu %d %s framing",			(int)RX_QLEN (dev), (int)TX_QLEN (dev), dev->net->mtu,			framing);	}	// delay posting reads until we're fully open	tasklet_schedule (&dev->bh);done:	return retval;}/*-------------------------------------------------------------------------*//* ethtool methods; minidrivers may need to add some more, but * they'll probably want to use this base set. */#define HAVE_MIIint usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd){	struct usbnet *dev = netdev_priv(net);	if (!dev->mii.mdio_read)		return -EOPNOTSUPP;	return mii_ethtool_gset(&dev->mii, cmd);}EXPORT_SYMBOL_GPL(usbnet_get_settings);int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd){	struct usbnet *dev = netdev_priv(net);	int retval;	if (!dev->mii.mdio_write)		return -EOPNOTSUPP;	retval = mii_ethtool_sset(&dev->mii, cmd);	/* link speed/duplex might have changed */	if (dev->driver_info->link_reset)		dev->driver_info->link_reset(dev);	return retval;}EXPORT_SYMBOL_GPL(usbnet_set_settings);u32 usbnet_get_link (struct net_device *net){	struct usbnet *dev = netdev_priv(net);	/* If a check_connect is defined, return its result */	if (dev->driver_info->check_connect)		return dev->driver_info->check_connect (dev) == 0;	/* if the device has mii operations, use those */	if (dev->mii.mdio_read)		return mii_link_ok(&dev->mii);	/* Otherwise, say we're up (to avoid breaking scripts) */	return 1;}EXPORT_SYMBOL_GPL(usbnet_get_link);int usbnet_nway_reset(struct net_device *net){	struct usbnet *dev = netdev_priv(net);	if (!dev->mii.mdio_write)		return -EOPNOTSUPP;	return mii_nway_restart(&dev->mii);}EXPORT_SYMBOL_GPL(usbnet_nway_reset);void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info){	struct usbnet *dev = netdev_priv(net);	strncpy (info->driver, dev->driver_name, sizeof info->driver);	strncpy (info->version, DRIVER_VERSION, sizeof info->version);	strncpy (info->fw_version, dev->driver_info->description,		sizeof info->fw_version);	usb_make_path (dev->udev, info->bus_info, sizeof info->bus_info);}EXPORT_SYMBOL_GPL(usbnet_get_drvinfo);u32 usbnet_get_msglevel (struct net_device *net){	struct usbnet *dev = netdev_priv(net);	return dev->msg_enable;}EXPORT_SYMBOL_GPL(usbnet_get_msglevel);void usbnet_set_msglevel (struct net_device *net, u32 level){	struct usbnet *dev = netdev_priv(net);	dev->msg_enable = level;}EXPORT_SYMBOL_GPL(usbnet_set_msglevel);/* drivers may override default ethtool_ops in their bind() routine */static struct ethtool_ops usbnet_ethtool_ops = {	.get_settings		= usbnet_get_settings,	.set_settings		= usbnet_set_settings,	.get_link		= usbnet_get_link,	.nway_reset		= usbnet_nway_reset,	.get_drvinfo		= usbnet_get_drvinfo,	.get_msglevel		= usbnet_get_msglevel,	.set_msglevel		= usbnet_set_msglevel,};/*-------------------------------------------------------------------------*//* work that cannot be done in interrupt context uses keventd. * * NOTE:  with 2.5 we could do more of this using completion callbacks, * especially now that control transfers can be queued. */static voidkevent (struct work_struct *work){	struct usbnet		*dev =		container_of(work, struct usbnet, kevent);	int			status;	/* usb_clear_halt() needs a thread context */	if (test_bit (EVENT_TX_HALT, &dev->flags)) {		unlink_urbs (dev, &dev->txq);		status = usb_clear_halt (dev->udev, dev->out);		if (status < 0				&& status != -EPIPE				&& status != -ESHUTDOWN) {			if (netif_msg_tx_err (dev))				deverr (dev, "can't clear tx halt, status %d",					status);		} else {			clear_bit (EVENT_TX_HALT, &dev->flags);			if (status != -ESHUTDOWN)				netif_wake_queue (dev->net);		}	}	if (test_bit (EVENT_RX_HALT, &dev->flags)) {		unlink_urbs (dev, &dev->rxq);		status = usb_clear_halt (dev->udev, dev->in);		if (status < 0				&& status != -EPIPE				&& status != -ESHUTDOWN) {			if (netif_msg_rx_err (dev))				deverr (dev, "can't clear rx halt, status %d",					status);		} else {			clear_bit (EVENT_RX_HALT, &dev->flags);			tasklet_schedule (&dev->bh);		}	}	/* tasklet could resubmit itself forever if memory is tight */	if (test_bit (EVENT_RX_MEMORY, &dev->flags)) {		struct urb	*urb = NULL;		if (netif_running (dev->net))			urb = usb_alloc_urb (0, GFP_KERNEL);		else			clear_bit (EVENT_RX_MEMORY, &dev->flags);		if (urb != NULL) {			clear_bit (EVENT_RX_MEMORY, &dev->flags);			rx_submit (dev, urb, GFP_KERNEL);			tasklet_schedule (&dev->bh);		}	}	if (test_bit (EVENT_LINK_RESET, &dev->flags)) {		struct driver_info	*info = dev->driver_info;		int			retval = 0;		clear_bit (EVENT_LINK_RESET, &dev->flags);		if(info->link_reset && (retval = info->link_reset(dev)) < 0) {			devinfo(dev, "link reset failed (%d) usbnet usb-%s-%s, %s",				retval,				dev->udev->bus->bus_name, dev->udev->devpath,				info->description);		}	}	if (dev->flags)		devdbg (dev, "kevent done, flags = 0x%lx",			dev->flags);}/*-------------------------------------------------------------------------*/static void tx_complete (struct urb *urb){	struct sk_buff		*skb = (struct sk_buff *) urb->context;	struct skb_data		*entry = (struct skb_data *) skb->cb;	struct usbnet		*dev = entry->dev;	if (urb->status == 0) {		dev->stats.tx_packets++;		dev->stats.tx_bytes += entry->length;	} else {		dev->stats.tx_errors++;		switch (urb->status) {		case -EPIPE:			usbnet_defer_kevent (dev, EVENT_TX_HALT);			break;		/* software-driven interface shutdown */		case -ECONNRESET:		// async unlink		case -ESHUTDOWN:		// hardware gone			break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -