Beispiel #1
0
/**
 *	ks8695_link_irq - Link change IRQ handler
 *	@irq: The IRQ which went off (ignored)
 *	@dev_id: The net_device for the interrupt
 *
 *	The WAN interface can generate an IRQ when the link changes,
 *	report this to the net layer and the user.
 */
static irqreturn_t
ks8695_link_irq(int irq, void *dev_id)
{
	struct net_device *ndev = (struct net_device *)dev_id;
	struct ks8695_priv *ksp = netdev_priv(ndev);
	u32 ctrl;

	ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
	if (ctrl & WMC_WLS) {
		netif_carrier_on(ndev);
		if (netif_msg_link(ksp))
			dev_info(ksp->dev,
				 "%s: Link is now up (10%sMbps/%s-duplex)\n",
				 ndev->name,
				 (ctrl & WMC_WSS) ? "0" : "",
				 (ctrl & WMC_WDS) ? "Full" : "Half");
	} else {
		netif_carrier_off(ndev);
		if (netif_msg_link(ksp))
			dev_info(ksp->dev, "%s: Link is now down.\n",
				 ndev->name);
	}

	return IRQ_HANDLED;
}
Beispiel #2
0
static int atl1c_set_settings(struct net_device *netdev,
			      struct ethtool_cmd *ecmd)
{
	struct atl1c_adapter *adapter = netdev_priv(netdev);
	struct atl1c_hw *hw = &adapter->hw;
	u16  autoneg_advertised;

	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
		msleep(1);

	if (ecmd->autoneg == AUTONEG_ENABLE) {
		autoneg_advertised = ADVERTISED_Autoneg;
	} else {
		u32 speed = ethtool_cmd_speed(ecmd);
		if (speed == SPEED_1000) {
			if (ecmd->duplex != DUPLEX_FULL) {
				if (netif_msg_link(adapter))
					dev_warn(&adapter->pdev->dev,
						"1000M half is invalid\n");
				clear_bit(__AT_RESETTING, &adapter->flags);
				return -EINVAL;
			}
			autoneg_advertised = ADVERTISED_1000baseT_Full;
		} else if (speed == SPEED_100) {
			if (ecmd->duplex == DUPLEX_FULL)
				autoneg_advertised = ADVERTISED_100baseT_Full;
			else
				autoneg_advertised = ADVERTISED_100baseT_Half;
		} else {
			if (ecmd->duplex == DUPLEX_FULL)
				autoneg_advertised = ADVERTISED_10baseT_Full;
			else
				autoneg_advertised = ADVERTISED_10baseT_Half;
		}
	}

	if (hw->autoneg_advertised != autoneg_advertised) {
		hw->autoneg_advertised = autoneg_advertised;
		if (atl1c_restart_autoneg(hw) != 0) {
			if (netif_msg_link(adapter))
				dev_warn(&adapter->pdev->dev,
					"ethtool speed/duplex setting failed\n");
			clear_bit(__AT_RESETTING, &adapter->flags);
			return -EINVAL;
		}
	}
	clear_bit(__AT_RESETTING, &adapter->flags);
	return 0;
}
Beispiel #3
0
/*-----------------------------------------------------------------------------
 *  generic link-change handler - should be sufficient for most cases
 *-----------------------------------------------------------------------------*/
static void generic_adjust_link(struct  net_device *dev)
{
	struct fs_enet_private *fep = netdev_priv(dev);
	struct phy_device *phydev = fep->phydev;
	int new_state = 0;

	if (phydev->link) {
		/* adjust to duplex mode */
		if (phydev->duplex != fep->oldduplex) {
			new_state = 1;
			fep->oldduplex = phydev->duplex;
		}

		if (phydev->speed != fep->oldspeed) {
			new_state = 1;
			fep->oldspeed = phydev->speed;
		}

		if (!fep->oldlink) {
			new_state = 1;
			fep->oldlink = 1;
		}

		if (new_state)
			fep->ops->restart(dev);
	} else if (fep->oldlink) {
		new_state = 1;
		fep->oldlink = 0;
		fep->oldspeed = 0;
		fep->oldduplex = -1;
	}

	if (new_state && netif_msg_link(fep))
		phy_print_status(phydev);
}
static int netx_eth_open(struct net_device *ndev)
{
	struct netx_eth_priv *priv = netdev_priv(ndev);

	if (request_irq
	    (ndev->irq, netx_eth_interrupt, IRQF_SHARED, ndev->name, ndev))
		return -EAGAIN;

	writel(ndev->dev_addr[0] |
	       ndev->dev_addr[1]<<8 |
	       ndev->dev_addr[2]<<16 |
	       ndev->dev_addr[3]<<24,
	       priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_4321);
	writel(ndev->dev_addr[4] |
	       ndev->dev_addr[5]<<8,
	       priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_65);

	writel(LOCAL_CONFIG_LINK_STATUS_IRQ_EN |
		LOCAL_CONFIG_CON_LO_IRQ_EN |
		LOCAL_CONFIG_CON_HI_IRQ_EN |
		LOCAL_CONFIG_IND_LO_IRQ_EN |
		LOCAL_CONFIG_IND_HI_IRQ_EN,
		priv->xpec_base + NETX_XPEC_RAM_START_OFS +
		ETH_MAC_LOCAL_CONFIG);

	mii_check_media(&priv->mii, netif_msg_link(priv), 1);
	netif_start_queue(ndev);

	return 0;
}
static irqreturn_t
netx_eth_interrupt(int irq, void *dev_id)
{
	struct net_device *ndev = dev_id;
	struct netx_eth_priv *priv = netdev_priv(ndev);
	int status;
	unsigned long flags;

	spin_lock_irqsave(&priv->lock, flags);

	status = readl(NETX_PFIFO_XPEC_ISR(priv->id));
	while (status) {
		int fill_level;
		writel(status, NETX_PFIFO_XPEC_ISR(priv->id));

		if ((status & ISR_CON_HI) || (status & ISR_IND_HI))
			printk("%s: unexpected status: 0x%08x\n",
			    __func__, status);

		fill_level =
		    readl(NETX_PFIFO_FILL_LEVEL(IND_FIFO_PORT_LO(priv->id)));
		while (fill_level--)
			netx_eth_receive(ndev);

		if (status & ISR_CON_LO)
			netif_wake_queue(ndev);

		if (status & ISR_LINK_STATUS_CHANGE)
			mii_check_media(&priv->mii, netif_msg_link(priv), 1);

		status = readl(NETX_PFIFO_XPEC_ISR(priv->id));
	}
	spin_unlock_irqrestore(&priv->lock, flags);
	return IRQ_HANDLED;
}
Beispiel #6
0
static int cp_open (struct net_device *dev)
{
	struct cp_private *cp = netdev_priv(dev);
	int rc;

	if (netif_msg_ifup(cp))
		printk(KERN_DEBUG "%s: enabling interface\n", dev->name);

	rc = cp_alloc_rings(cp);
	if (rc)
		return rc;

	cp_init_hw(cp);

	rc = request_irq(dev->irq, cp_interrupt, SA_SHIRQ, dev->name, dev);
	if (rc)
		goto err_out_hw;

	netif_carrier_off(dev);
	mii_check_media(&cp->mii_if, netif_msg_link(cp), TRUE);
	netif_start_queue(dev);

	return 0;

err_out_hw:
	cp_stop_hw(cp);
	cp_free_rings(cp);
	return rc;
}
Beispiel #7
0
static inline void nc_dump_ttl(struct usbnet *dev, u16 ttl)
{
	if (netif_msg_link(dev))
		devdbg(dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d",
			dev->udev->bus->bus_name, dev->udev->devpath,
			ttl, TTL_THIS(ttl), TTL_OTHER(ttl));
}
Beispiel #8
0
static inline void nc_dump_status(struct usbnet *dev, u16 status)
{
	if (!netif_msg_link(dev))
		return;
	devdbg(dev, "net1080 %s-%s status 0x%x:"
			" this (%c) PKT=%d%s%s%s;"
			" other PKT=%d%s%s%s; unspec 0x%x",
		dev->udev->bus->bus_name, dev->udev->devpath,
		status,

		// XXX the packet counts don't seem right
		// (1 at reset, not 0); maybe UNSPEC too

		(status & STATUS_PORT_A) ? 'A' : 'B',
		STATUS_PACKETS_THIS(status),
		(status & STATUS_CONN_THIS) ? " CON" : "",
		(status & STATUS_SUSPEND_THIS) ? " SUS" : "",
		(status & STATUS_MAILBOX_THIS) ? " MBOX" : "",

		STATUS_PACKETS_OTHER(status),
		(status & STATUS_CONN_OTHER) ? " CON" : "",
		(status & STATUS_SUSPEND_OTHER) ? " SUS" : "",
		(status & STATUS_MAILBOX_OTHER) ? " MBOX" : "",

		status & STATUS_UNSPEC_MASK
		);
}
Beispiel #9
0
static void usbnet_bh (unsigned long param)
{
	struct usbnet		*dev = (struct usbnet *) param;
	struct sk_buff		*skb;
	struct skb_data		*entry;

	while ((skb = skb_dequeue (&dev->done))) {
		entry = (struct skb_data *) skb->cb;
		switch (entry->state) {
		    case rx_done:
			entry->state = rx_cleanup;
			rx_process (dev, skb);
			continue;
		    case tx_done:
		    case rx_cleanup:
			usb_free_urb (entry->urb);
			dev_kfree_skb (skb);
			continue;
		    default:
			devdbg (dev, "bogus skb state %d", entry->state);
		}
	}

	// waiting for all pending urbs to complete?
	if (dev->wait) {
		if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) {
			wake_up (dev->wait);
		}

	// or are we maybe short a few urbs?
	} else if (netif_running (dev->net)
			&& netif_device_present (dev->net)
			&& !timer_pending (&dev->delay)
			&& !test_bit (EVENT_RX_HALT, &dev->flags)) {
		int	temp = dev->rxq.qlen;
		int	qlen = RX_QLEN (dev);

		if (temp < qlen) {
			struct urb	*urb;
			int		i;

			// don't refill the queue all at once
			for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) {
				urb = usb_alloc_urb (0, GFP_ATOMIC);
				if (urb != NULL)
					rx_submit (dev, urb, GFP_ATOMIC);
			}
			if (temp != dev->rxq.qlen && netif_msg_link (dev))
				devdbg (dev, "rxqlen %d --> %d",
						temp, dev->rxq.qlen);
			if (dev->rxq.qlen < qlen)
				tasklet_schedule (&dev->bh);
		}
		if (dev->txq.qlen < TX_QLEN (dev))
			netif_wake_queue (dev->net);
	}
}
Beispiel #10
0
static irqreturn_t
cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
{
	struct net_device *dev = dev_instance;
	struct cp_private *cp;
	u16 status;

	if (unlikely(dev == NULL))
		return IRQ_NONE;
	cp = netdev_priv(dev);

	status = cpr16(IntrStatus);
	if (!status || (status == 0xFFFF))
		return IRQ_NONE;

	if (netif_msg_intr(cp))
		printk(KERN_DEBUG "%s: intr, status %04x cmd %02x cpcmd %04x\n",
		        dev->name, status, cpr8(Cmd), cpr16(CpCmd));

	cpw16(IntrStatus, status & ~cp_rx_intr_mask);

	spin_lock(&cp->lock);

	/* close possible race's with dev_close */
	if (unlikely(!netif_running(dev))) {
		cpw16(IntrMask, 0);
		spin_unlock(&cp->lock);
		return IRQ_HANDLED;
	}

	if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
		if (netif_rx_schedule_prep(dev)) {
			cpw16_f(IntrMask, cp_norx_intr_mask);
			__netif_rx_schedule(dev);
		}

	if (status & (TxOK | TxErr | TxEmpty | SWInt))
		cp_tx(cp);
	if (status & LinkChg)
		mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);

	spin_unlock(&cp->lock);

	if (status & PciErr) {
		u16 pci_status;

		pci_read_config_word(cp->pdev, PCI_STATUS, &pci_status);
		pci_write_config_word(cp->pdev, PCI_STATUS, pci_status);
		printk(KERN_ERR "%s: PCI bus error, status=%04x, PCI status=%04x\n",
		       dev->name, status, pci_status);

		/* TODO: reset hardware */
	}

	return IRQ_HANDLED;
}
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->net->stats.tx_packets++;
		dev->net->stats.tx_bytes += entry->length;
	} else {
		dev->net->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;

		// like rx, tx gets controller i/o faults during khubd delays
		// and so it uses the same throttling mechanism.
		case -EPROTO:
		case -ETIME:
		case -EILSEQ:
#if defined(CONFIG_ERICSSON_F3307_ENABLE)
			usb_mark_last_busy(dev->udev);
#endif
			if (!timer_pending (&dev->delay)) {
				mod_timer (&dev->delay,
					jiffies + THROTTLE_JIFFIES);
				if (netif_msg_link (dev))
					devdbg (dev, "tx throttle %d",
							urb->status);
			}
			netif_stop_queue (dev->net);
			break;
		default:
			if (netif_msg_tx_err (dev))
				devdbg (dev, "tx err %d", entry->urb->status);
			break;
		}
	}
#if defined(CONFIG_ERICSSON_F3307_ENABLE)
	usb_autopm_put_interface_async(dev->intf);
#endif
	urb->dev = NULL;
	entry->state = tx_done;
	defer_bh(dev, skb, &dev->txq);
}
Beispiel #12
0
static int net1080_reset(struct usbnet *dev)
{
	u16		usbctl, status, ttl;
	u16		*vp = kmalloc(sizeof (u16), GFP_KERNEL);
	int		retval;

	if (!vp)
		return -ENOMEM;

	// nc_dump_registers(dev);

	if ((retval = nc_register_read(dev, REG_STATUS, vp)) < 0) {
		dbg("can't read %s-%s status: %d",
			dev->udev->bus->bus_name, dev->udev->devpath, retval);
		goto done;
	}
	status = *vp;
	nc_dump_status(dev, status);

	if ((retval = nc_register_read(dev, REG_USBCTL, vp)) < 0) {
		dbg("can't read USBCTL, %d", retval);
		goto done;
	}
	usbctl = *vp;
	nc_dump_usbctl(dev, usbctl);

	nc_register_write(dev, REG_USBCTL,
			USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);

	if ((retval = nc_register_read(dev, REG_TTL, vp)) < 0) {
		dbg("can't read TTL, %d", retval);
		goto done;
	}
	ttl = *vp;
	// nc_dump_ttl(dev, ttl);

	nc_register_write(dev, REG_TTL,
			MK_TTL(NC_READ_TTL_MS, TTL_OTHER(ttl)) );
	dbg("%s: assigned TTL, %d ms", dev->net->name, NC_READ_TTL_MS);

	if (netif_msg_link(dev))
		devinfo(dev, "port %c, peer %sconnected",
			(status & STATUS_PORT_A) ? 'A' : 'B',
			(status & STATUS_CONN_OTHER) ? "" : "dis"
			);
	retval = 0;

done:
	kfree(vp);
	return retval;
}
Beispiel #13
0
/* Start or stop link monitoring. If we want to be interrupted for a link
   state change, then we call this routine just once when turning on
   interrupt monitoring. For polling, this routine is called periodically
   every HX_LINK_TIMEOUT seconds and the one-shot timer is set for the next
   period. */
static int hxge_link_monitor(struct hxge_adapter *hxgep, int cmd)
{
	if (netif_msg_link(hxgep)) {
		HXGE_DBG(hxgep, "hxge_link_monitor: cmd = %d",cmd);
		if (hxgep->link_monitor_state == LINK_MONITOR_DISABLED) {
			HXGE_DBG(hxgep, "hxge_link_monitor: Link monitoring disabled");
		}
		else {
			HXGE_DBG(hxgep, "hxge_link_monitor: Link monitoring enabled");
		}
	}

	hxgep->statsp->link_monitor_cnt++;
	switch (cmd) {
		case LINK_MONITOR_START:
		   /* Assert an interrupt when link state changes. */
		   if (hxgep->link_mode == LINK_MODE_INTR) {
			if (hxge_link_intr(hxgep, cmd))
				goto fail;
		    /* Periodically poll for for state change */
		    } else if (hxgep->link_monitor_state == LINK_MONITOR_DISABLED) {
			hxgep->link_monitor_state = LINK_MONITOR_ENABLED;
			mod_timer (&hxgep->wd_timer, jiffies + HXGE_LINK_TIMEOUT);
		    }
		    HXGE_DBG(hxgep, "hxge_link_monitor: Link monitoring started");
		    break;
		case LINK_MONITOR_STOP:
		   if (hxgep->link_mode == LINK_MODE_INTR) {
			if (hxge_link_intr(hxgep, cmd))
				goto fail;
		   } else if (hxgep->link_monitor_state == LINK_MONITOR_ENABLED)
		   {
			hxgep->link_monitor_state = LINK_MONITOR_DISABLED;
			del_timer_sync(&hxgep->wd_timer);
		   }
		    HXGE_DBG(hxgep, "hxge_link_monitor: Link monitoring stopped");
		   break;
		default:
		   HXGE_ERR(hxgep, "hxge_link_monitor: Unknown command");
		   break;
	}
	return 0;

fail:
	HXGE_ERR(hxgep, "hxge_link_monitor: failed");
	return -1;
}
Beispiel #14
0
static void smc_phy_check_media(struct net_device *dev, int init)
{
	struct smc_local *lp = netdev_priv(dev);
	void __iomem *ioaddr = lp->base;

	if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) {
		
		if (lp->mii.full_duplex) {
			lp->tcr_cur_mode |= TCR_SWFDUP;
		} else {
			lp->tcr_cur_mode &= ~TCR_SWFDUP;
		}

		SMC_SELECT_BANK(lp, 0);
		SMC_SET_TCR(lp, lp->tcr_cur_mode);
	}
}
Beispiel #15
0
static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl)
{
	if (!netif_msg_link(dev))
		return;
	devdbg(dev, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;"
			" this%s%s;"
			" other%s%s; r/o 0x%x",
		dev->udev->bus->bus_name, dev->udev->devpath,
		usbctl,
		(usbctl & USBCTL_ENABLE_LANG) ? " lang" : "",
		(usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "",
		(usbctl & USBCTL_ENABLE_PROD) ? " prod" : "",
		(usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "",
		(usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "",

		(usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "",
		(usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "",
		(usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "",
		(usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "",
		usbctl & ~USBCTL_WRITABLE_MASK
		);
}
Beispiel #16
0
static void xgbe_phy_adjust_link(struct xgbe_prv_data *pdata)
{
	int new_state = 0;

	if (pdata->phy.link) {
		/* Flow control support */
		pdata->pause_autoneg = pdata->phy.pause_autoneg;

		if (pdata->tx_pause != pdata->phy.tx_pause) {
			new_state = 1;
			pdata->hw_if.config_tx_flow_control(pdata);
			pdata->tx_pause = pdata->phy.tx_pause;
		}

		if (pdata->rx_pause != pdata->phy.rx_pause) {
			new_state = 1;
			pdata->hw_if.config_rx_flow_control(pdata);
			pdata->rx_pause = pdata->phy.rx_pause;
		}

		/* Speed support */
		if (pdata->phy_speed != pdata->phy.speed) {
			new_state = 1;
			pdata->phy_speed = pdata->phy.speed;
		}

		if (pdata->phy_link != pdata->phy.link) {
			new_state = 1;
			pdata->phy_link = pdata->phy.link;
		}
	} else if (pdata->phy_link) {
		new_state = 1;
		pdata->phy_link = 0;
		pdata->phy_speed = SPEED_UNKNOWN;
	}

	if (new_state && netif_msg_link(pdata))
		xgbe_phy_print_status(pdata);
}
Beispiel #17
0
static INT bcm_open(struct net_device *dev)
{
	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);

	if (Adapter->fw_download_done == false) {
		pr_notice(PFX "%s: link up failed (download in progress)\n",
			  dev->name);
		return -EBUSY;
	}

	if (netif_msg_ifup(Adapter))
		pr_info(PFX "%s: enabling interface\n", dev->name);

	if (Adapter->LinkUpStatus) {
		if (netif_msg_link(Adapter))
			pr_info(PFX "%s: link up\n", dev->name);

		netif_carrier_on(Adapter->dev);
		netif_start_queue(Adapter->dev);
	}

	return 0;
}
Beispiel #18
0
static void smc_10bt_check_media(struct net_device *dev, int init)
{
	struct smc_local *lp = netdev_priv(dev);
	void __iomem *ioaddr = lp->base;
	unsigned int old_carrier, new_carrier;

	old_carrier = netif_carrier_ok(dev) ? 1 : 0;

	SMC_SELECT_BANK(lp, 0);
	new_carrier = (SMC_GET_EPH_STATUS(lp) & ES_LINK_OK) ? 1 : 0;
	SMC_SELECT_BANK(lp, 2);

	if (init || (old_carrier != new_carrier)) {
		if (!new_carrier) {
			netif_carrier_off(dev);
		} else {
			netif_carrier_on(dev);
		}
		if (netif_msg_link(lp))
			printk(KERN_INFO "%s: link %s\n", dev->name,
			       new_carrier ? "up" : "down");
	}
}
Beispiel #19
0
/* PHY state control function */
static void sh_eth_adjust_link(struct net_device *ndev)
{
	struct sh_eth_private *mdp = netdev_priv(ndev);
	struct phy_device *phydev = mdp->phydev;
	int new_state = 0;

	if (phydev->link != PHY_DOWN) {
		if (phydev->duplex != mdp->duplex) {
			new_state = 1;
			mdp->duplex = phydev->duplex;
			if (mdp->cd->set_duplex)
				mdp->cd->set_duplex(ndev);
		}

		if (phydev->speed != mdp->speed) {
			new_state = 1;
			mdp->speed = phydev->speed;
			if (mdp->cd->set_rate)
				mdp->cd->set_rate(ndev);
		}
		if (mdp->link == PHY_DOWN) {
			sh_eth_write(ndev,
				(sh_eth_read(ndev, ECMR) & ~ECMR_TXF), ECMR);
			new_state = 1;
			mdp->link = phydev->link;
		}
	} else if (mdp->link) {
		new_state = 1;
		mdp->link = PHY_DOWN;
		mdp->speed = 0;
		mdp->duplex = -1;
	}

	if (new_state && netif_msg_link(mdp))
		phy_print_status(phydev);
}
Beispiel #20
0
static int mpodp_clean_tx_unlocked(struct mpodp_if_priv *priv,
				   struct mpodp_txq *txq,  unsigned budget)
{
	struct net_device *netdev = priv->netdev;
	struct mpodp_tx *tx;
	unsigned int packets_completed = 0;
	unsigned int bytes_completed = 0;
	unsigned int worked = 0;
	union mppa_timestamp ts;
	uint32_t tx_done, first_tx_done, last_tx_done, tx_submitted,
		tx_size, tx_head;

	tx_submitted = atomic_read(&txq->submitted);
	tx_done = atomic_read(&txq->done);
	first_tx_done = tx_done;
	last_tx_done = first_tx_done;

	tx_size = txq->size;
	tx_head = atomic_read(&txq->head);

	if (!tx_head) {
		/* No carrier yet. Check if there are any buffers yet */
		tx_head = readl(txq->head_addr);
		if (tx_head) {
			/* We now have buffers */
			atomic_set(&txq->head, tx_head);

			if (netif_msg_link(priv))
				netdev_info(netdev,"txq[%d]  now has Tx (%u).\n",
					    txq->id, tx_head);
		}
		return 0;
	}

	/* TX: 2nd step: update TX tail (DMA transfer completed) */
	while (tx_done != tx_submitted && worked < budget) {
		if (!mpodp_tx_is_done(priv, txq, tx_done)) {
			/* DMA transfer not completed */
			break;
		}

		if (netif_msg_tx_done(priv))
			netdev_info(netdev,
				    "txq[%d] tx[%d]: transfer done (head: %d submitted: %d done: %d)\n",
				    txq->id, tx_done, atomic_read(&txq->head),
				    tx_submitted, tx_done);

		/* get TX slot */
		tx = &(txq->ring[tx_done]);

		/* free ressources */
		unmap_skb(&priv->pdev->dev, tx->skb, tx);
		consume_skb(tx->skb);

		worked++;

		tx_done += 1;
		if (tx_done == tx_size)
			tx_done = 0;
		last_tx_done = tx_done;

	}
	/* write new TX tail */
	atomic_set(&txq->done, tx_done);

	/* TX: 3rd step: free finished TX slot */
	while (first_tx_done != last_tx_done) {
		if (netif_msg_tx_done(priv))
			netdev_info(netdev,
				    "txq[%d] tx[%d]: done (head: %d submitted: %d done: %d)\n",
				    txq->id, first_tx_done, atomic_read(&txq->head),
				    tx_submitted, tx_done);

		/* get TX slot */
		tx = &(txq->ring[first_tx_done]);
		mppa_pcie_time_get(priv->tx_time, &ts);
		mppa_pcie_time_update(priv->tx_time, &tx->time, &ts);

		/* get stats */
		packets_completed++;
		bytes_completed += tx->len;

		first_tx_done += 1;
		if (first_tx_done == tx_size)
			first_tx_done = 0;
	}

	if (!packets_completed) {
		goto out;
	}

	/* update stats */
	netdev->stats.tx_bytes += bytes_completed;
	netdev->stats.tx_packets += packets_completed;

	netdev_tx_completed_queue(txq->txq, packets_completed, bytes_completed);
	netif_tx_wake_queue(txq->txq);
      out:
	return worked;
}
Beispiel #21
0
static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
{
	struct sk_buff		*skb;
	struct skb_data		*entry;
	int			retval = 0;
	unsigned long		lockflags;
	size_t			size = dev->rx_urb_size;

#if defined(CONFIG_RA_HW_NAT_PCI) && (defined(CONFIG_RA_HW_NAT) || defined(CONFIG_RA_HW_NAT_MODULE))
	if ((skb = alloc_skb (size + NET_IP_ALIGN + FOE_INFO_LEN, flags)) == NULL) {
#else
	if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) {
#endif
		if (netif_msg_rx_err (dev))
			devdbg (dev, "no rx skb");
		usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
		usb_free_urb (urb);
		return;
	}
#if defined(CONFIG_RA_HW_NAT_PCI) && (defined(CONFIG_RA_HW_NAT) || defined(CONFIG_RA_HW_NAT_MODULE))
	skb_reserve (skb, NET_IP_ALIGN + FOE_INFO_LEN);
#else
	skb_reserve (skb, NET_IP_ALIGN);
#endif
	entry = (struct skb_data *) skb->cb;
	entry->urb = urb;
	entry->dev = dev;
	entry->length = 0;

	usb_fill_bulk_urb (urb, dev->udev, dev->in,
		skb->data, size, rx_complete, skb);

	spin_lock_irqsave (&dev->rxq.lock, lockflags);

	if (netif_running (dev->net)
			&& netif_device_present (dev->net)
			&& !test_bit (EVENT_RX_HALT, &dev->flags)) {
		switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
		case -EPIPE:
			usbnet_defer_kevent (dev, EVENT_RX_HALT);
			break;
		case -ENOMEM:
			usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
			break;
		case -ENODEV:
			if (netif_msg_ifdown (dev))
				devdbg (dev, "device gone");
			netif_device_detach (dev->net);
			break;
		default:
			if (netif_msg_rx_err (dev))
				devdbg (dev, "rx submit, %d", retval);
			tasklet_schedule (&dev->bh);
			break;
		case 0:
			__usbnet_queue_skb(&dev->rxq, skb, rx_start);
		}
	} else {
		if (netif_msg_ifdown (dev))
			devdbg (dev, "rx: stopped");
		retval = -ENOLINK;
	}
	spin_unlock_irqrestore (&dev->rxq.lock, lockflags);
	if (retval) {
		dev_kfree_skb_any (skb);
		usb_free_urb (urb);
	}
}


/*-------------------------------------------------------------------------*/

static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
{
	if (dev->driver_info->rx_fixup
			&& !dev->driver_info->rx_fixup (dev, skb))
		goto error;
	// else network stack removes extra byte if we forced a short packet

	if (skb->len)
		usbnet_skb_return (dev, skb);
	else {
		if (netif_msg_rx_err (dev))
			devdbg (dev, "drop");
error:
		dev->stats.rx_errors++;
		skb_queue_tail (&dev->done, skb);
	}
}

/*-------------------------------------------------------------------------*/

static void rx_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;
	int			urb_status = urb->status;
	enum skb_state		state;

	skb_put (skb, urb->actual_length);
	state = rx_done;
	entry->urb = NULL;

	switch (urb_status) {
	    // success
	    case 0:
		if (skb->len < dev->net->hard_header_len) {
			state = rx_cleanup;
			dev->stats.rx_errors++;
			dev->stats.rx_length_errors++;
			if (netif_msg_rx_err (dev))
				devdbg (dev, "rx length %d", skb->len);
		}
		break;

	    // stalls need manual reset. this is rare ... except that
	    // when going through USB 2.0 TTs, unplug appears this way.
	    // we avoid the highspeed version of the ETIMEOUT/EILSEQ
	    // storm, recovering as needed.
	    case -EPIPE:
		dev->stats.rx_errors++;
		usbnet_defer_kevent (dev, EVENT_RX_HALT);
		// FALLTHROUGH

	    // software-driven interface shutdown
	    case -ECONNRESET:		// async unlink
	    case -ESHUTDOWN:		// hardware gone
		if (netif_msg_ifdown (dev))
			devdbg (dev, "rx shutdown, code %d", urb_status);
		goto block;

	    // we get controller i/o faults during khubd disconnect() delays.
	    // throttle down resubmits, to avoid log floods; just temporarily,
	    // so we still recover when the fault isn't a khubd delay.
	    case -EPROTO:
	    case -ETIME:
	    case -EILSEQ:
		dev->stats.rx_errors++;
		if (!timer_pending (&dev->delay)) {
			mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
			if (netif_msg_link (dev))
				devdbg (dev, "rx throttle %d", urb_status);
		}
block:
		state = rx_cleanup;
		entry->urb = urb;
		urb = NULL;
		break;

	    // data overrun ... flush fifo?
	    case -EOVERFLOW:
		dev->stats.rx_over_errors++;
		// FALLTHROUGH

	    default:
		state = rx_cleanup;
		dev->stats.rx_errors++;
		if (netif_msg_rx_err (dev))
			devdbg (dev, "rx status %d", urb_status);
		break;
	}

	state = defer_bh(dev, skb, &dev->rxq, state);

	if (urb) {
		if (netif_running (dev->net)
		    && !test_bit (EVENT_RX_HALT, &dev->flags) &&
		    state != unlink_start) {
			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;
	}

	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 cleanup

static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
{
	unsigned long		flags;
	struct sk_buff		*skb;
	int			count = 0;

	spin_lock_irqsave (&q->lock, flags);
	while (!skb_queue_empty(q)) {
		struct skb_data		*entry;
		struct urb		*urb;
		int			retval;

		skb_queue_walk(q, skb) {
		entry = (struct skb_data *) skb->cb;
			if (entry->state != unlink_start)
				goto found;
		}
		break;
found:
		entry->state = unlink_start;
		urb = entry->urb;

		/*
		 * Get reference count of the URB to avoid it to be
		 * freed during usb_unlink_urb, which may trigger
		 * use-after-free problem inside usb_unlink_urb since
		 * usb_unlink_urb is always racing with .complete
		 * handler(include defer_bh).
		 */
		usb_get_urb(urb);
		spin_unlock_irqrestore(&q->lock, flags);
		// 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++;
		usb_put_urb(urb);
		spin_lock_irqsave(&q->lock, flags);
	}
Beispiel #22
0
static void kevent(void *data)
{
	struct usbnet *dev = (struct usbnet *)data;
#else
static void kevent(struct work_struct *work)
{
	struct usbnet		*dev =
		container_of(work, struct usbnet, kevent);
#endif
	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);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
			urb->transfer_flags |= URB_ASYNC_UNLINK;
#endif
			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);
			if (retval < 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);
}

/*-------------------------------------------------------------------------*/

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
static void tx_complete(struct urb *urb, struct pt_regs *regs)
#else
static void tx_complete(struct urb *urb)
#endif
{
	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:
			axusbnet_defer_kevent(dev, EVENT_TX_HALT);
			break;

		/* software-driven interface shutdown */
		case -ECONNRESET:		/* async unlink */
		case -ESHUTDOWN:		/* hardware gone */
			break;

		/* like rx, tx gets controller i/o faults during khubd delays */
		/* and so it uses the same throttling mechanism. */
		case -EPROTO:
		case -ETIME:
		case -EILSEQ:
			if (!timer_pending(&dev->delay)) {
				mod_timer(&dev->delay,
					  jiffies + THROTTLE_JIFFIES);
				if (netif_msg_link(dev))
					devdbg(dev, "tx throttle %d",
					       urb->status);
			}
			netif_stop_queue(dev->net);
			break;
		default:
			if (netif_msg_tx_err(dev))
				devdbg(dev, "tx err %d", entry->urb->status);
			break;
		}
	}

	urb->dev = NULL;
	entry->state = tx_done;
	defer_bh(dev, skb, &dev->txq);
}

/*-------------------------------------------------------------------------*/

static
void axusbnet_tx_timeout(struct net_device *net)
{
	struct usbnet *dev = netdev_priv(net);

	unlink_urbs(dev, &dev->txq);
	tasklet_schedule(&dev->bh);

	/* FIXME: device recovery -- reset? */
}

/*-------------------------------------------------------------------------*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
static int
#else
static netdev_tx_t
#endif
axusbnet_start_xmit(struct sk_buff *skb, struct net_device *net)
{
	struct usbnet		*dev = netdev_priv(net);
	int			length;
	struct urb		*urb = NULL;
	struct skb_data		*entry;
	struct driver_info	*info = dev->driver_info;
	unsigned long		flags;
	int retval;

	/* some devices want funky USB-level framing, for */
	/* win32 driver (usually) and/or hardware quirks */
	if (info->tx_fixup) {
		skb = info->tx_fixup(dev, skb, GFP_ATOMIC);
		if (!skb) {
			if (netif_msg_tx_err(dev))
				devdbg(dev, "can't tx_fixup skb");
			goto drop;
		}
	}
	length = skb->len;

	urb = usb_alloc_urb(0, GFP_ATOMIC);
	if (!urb) {
		if (netif_msg_tx_err(dev))
			devdbg(dev, "no urb");
		goto drop;
	}

	entry = (struct skb_data *) skb->cb;
	entry->urb = urb;
	entry->dev = dev;
	entry->state = tx_start;
	entry->length = length;

	usb_fill_bulk_urb(urb, dev->udev, dev->out, skb->data,
			  skb->len, tx_complete, skb);

	/* don't assume the hardware handles USB_ZERO_PACKET
	 * NOTE:  strictly conforming cdc-ether devices should expect
	 * the ZLP here, but ignore the one-byte packet.
	 */
	if (!(info->flags & FLAG_SEND_ZLP) && (length % dev->maxpacket) == 0) {
		urb->transfer_buffer_length++;
		if (skb_tailroom(skb)) {
			skb->data[skb->len] = 0;
			__skb_put(skb, 1);
		}
	}

	spin_lock_irqsave(&dev->txq.lock, flags);

	switch ((retval = usb_submit_urb(urb, GFP_ATOMIC))) {
	case -EPIPE:
		netif_stop_queue(net);
		axusbnet_defer_kevent(dev, EVENT_TX_HALT);
		break;
	default:
		if (netif_msg_tx_err(dev))
			devdbg(dev, "tx: submit urb err %d", retval);
		break;
	case 0:
		net->trans_start = jiffies;
		__skb_queue_tail(&dev->txq, skb);
		if (dev->txq.qlen >= TX_QLEN(dev))
			netif_stop_queue(net);
	}
	spin_unlock_irqrestore(&dev->txq.lock, flags);

	if (retval) {
		if (netif_msg_tx_err(dev))
			devdbg(dev, "drop, code %d", retval);
drop:
		dev->stats.tx_dropped++;
		if (skb)
			dev_kfree_skb_any(skb);
		usb_free_urb(urb);
	} else if (netif_msg_tx_queued(dev)) {
		devdbg(dev, "> tx, len %d, type 0x%x",
		       length, skb->protocol);
	}
	return NETDEV_TX_OK;
}

/*-------------------------------------------------------------------------*/

/* tasklet (work deferred from completions, in_irq) or timer */

static void axusbnet_bh(unsigned long param)
{
	struct usbnet		*dev = (struct usbnet *) param;
	struct sk_buff		*skb;
	struct skb_data		*entry;

	while ((skb = skb_dequeue(&dev->done))) {
		entry = (struct skb_data *) skb->cb;
		switch (entry->state) {
		case rx_done:
			entry->state = rx_cleanup;
			rx_process(dev, skb);
			continue;
		case tx_done:
		case rx_cleanup:
			usb_free_urb(entry->urb);
			dev_kfree_skb(skb);
			continue;
		default:
			devdbg(dev, "bogus skb state %d", entry->state);
		}
	}

	/* waiting for all pending urbs to complete? */
	if (dev->wait) {
		if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0)
			wake_up(dev->wait);

	/* or are we maybe short a few urbs? */
	} else if (netif_running(dev->net)
			&& netif_device_present(dev->net)
			&& !timer_pending(&dev->delay)
			&& !test_bit(EVENT_RX_HALT, &dev->flags)) {
		int	temp = dev->rxq.qlen;
		int	qlen = RX_QLEN(dev);

		if (temp < qlen) {
			struct urb	*urb;
			int		i;

			/* don't refill the queue all at once */
			for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) {
				urb = usb_alloc_urb(0, GFP_ATOMIC);
				if (urb != NULL) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
					urb->transfer_flags |= URB_ASYNC_UNLINK;
#endif
					rx_submit(dev, urb, GFP_ATOMIC);
				}
			}
			if (temp != dev->rxq.qlen && netif_msg_link(dev))
				devdbg(dev, "rxqlen %d --> %d",
				       temp, dev->rxq.qlen);
			if (dev->rxq.qlen < qlen)
				tasklet_schedule(&dev->bh);
		}
		if (dev->txq.qlen < TX_QLEN(dev))
			netif_wake_queue(dev->net);
	}
}


/*-------------------------------------------------------------------------
 *
 * USB Device Driver support
 *
 *-------------------------------------------------------------------------*/

/* precondition: never called in_interrupt */

static
void axusbnet_disconnect(struct usb_interface *intf)
{
	struct usbnet		*dev;
	struct usb_device	*xdev;
	struct net_device	*net;

	dev = usb_get_intfdata(intf);
	usb_set_intfdata(intf, NULL);
	if (!dev)
		return;

	xdev = interface_to_usbdev(intf);

	if (netif_msg_probe(dev))
		devinfo(dev, "unregister '%s' usb-%s-%s, %s",
			intf->dev.driver->name,
			xdev->bus->bus_name, xdev->devpath,
			dev->driver_info->description);

	net = dev->net;
	unregister_netdev(net);

	/* we don't hold rtnl here ... */
	flush_scheduled_work();

	if (dev->driver_info->unbind)
		dev->driver_info->unbind(dev, intf);

	free_netdev(net);
	usb_put_dev(xdev);
}

/*-------------------------------------------------------------------------*/

/* precondition: never called in_interrupt */

static int
axusbnet_probe(struct usb_interface *udev, const struct usb_device_id *prod)
{
	struct usbnet			*dev;
	struct net_device		*net;
	struct usb_host_interface	*interface;
	struct driver_info		*info;
	struct usb_device		*xdev;
	int				status;
	const char			*name;

	name = udev->dev.driver->name;
	info = (struct driver_info *) prod->driver_info;
	if (!info) {
		printk(KERN_ERR "blacklisted by %s\n", name);
		return -ENODEV;
	}
	xdev = interface_to_usbdev(udev);
	interface = udev->cur_altsetting;

	usb_get_dev(xdev);

	status = -ENOMEM;

	/* set up our own records */
	net = alloc_etherdev(sizeof(*dev));
	if (!net) {
		printk(KERN_ERR "can't kmalloc dev");
		goto out;
	}

	dev = netdev_priv(net);
	dev->udev = xdev;
	dev->intf = udev;
	dev->driver_info = info;
	dev->driver_name = name;
	dev->msg_enable = netif_msg_init(msg_level, NETIF_MSG_DRV |
					 NETIF_MSG_PROBE | NETIF_MSG_LINK);
	skb_queue_head_init(&dev->rxq);
	skb_queue_head_init(&dev->txq);
	skb_queue_head_init(&dev->done);
	dev->bh.func = axusbnet_bh;
	dev->bh.data = (unsigned long) dev;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
	INIT_WORK(&dev->kevent, kevent, dev);
#else
	INIT_WORK(&dev->kevent, kevent);
#endif

	dev->delay.function = axusbnet_bh;
	dev->delay.data = (unsigned long) dev;
	init_timer(&dev->delay);
	/* mutex_init(&dev->phy_mutex); */

	dev->net = net;

	/* rx and tx sides can use different message sizes;
	 * bind() should set rx_urb_size in that case.
	 */
	dev->hard_mtu = net->mtu + net->hard_header_len;

#if 0
	/* dma_supported() is deeply broken on almost all architectures */
	/* possible with some EHCI controllers */
	if (dma_supported(&udev->dev, DMA_BIT_MASK(64)))
		net->features |= NETIF_F_HIGHDMA;
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
	net->open		= axusbnet_open,
	net->stop		= axusbnet_stop,
	net->hard_start_xmit	= axusbnet_start_xmit,
	net->tx_timeout	= axusbnet_tx_timeout,
	net->get_stats = axusbnet_get_stats;
#endif

	net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
	net->ethtool_ops = &axusbnet_ethtool_ops;

	/* allow device-specific bind/init procedures */
	/* NOTE net->name still not usable ... */
	status = info->bind(dev, udev);
	if (status < 0) {
		deverr(dev, "Binding device failed: %d", status);
		goto out1;
	}

	/* maybe the remote can't receive an Ethernet MTU */
	if (net->mtu > (dev->hard_mtu - net->hard_header_len))
		net->mtu = dev->hard_mtu - net->hard_header_len;

	status = init_status(dev, udev);
	if (status < 0)
		goto out3;

	if (!dev->rx_urb_size)
		dev->rx_urb_size = dev->hard_mtu;
	dev->maxpacket = usb_maxpacket(dev->udev, dev->out, 1);

	SET_NETDEV_DEV(net, &udev->dev);
	status = register_netdev(net);
	if (status) {
		deverr(dev, "net device registration failed: %d", status);
		goto out3;
	}

	if (netif_msg_probe(dev))
		devinfo(dev, "register '%s' at usb-%s-%s, %s, %pM",
			udev->dev.driver->name,
			xdev->bus->bus_name, xdev->devpath,
			dev->driver_info->description,
			net->dev_addr);

	/* ok, it's ready to go. */
	usb_set_intfdata(udev, dev);

	/* start as if the link is up */
	netif_device_attach(net);

	return 0;

out3:
	if (info->unbind)
		info->unbind(dev, udev);
out1:
	free_netdev(net);
out:
	usb_put_dev(xdev);
	return status;
}

/*-------------------------------------------------------------------------*/

/*
 * suspend the whole driver as soon as the first interface is suspended
 * resume only when the last interface is resumed
 */

static int axusbnet_suspend(struct usb_interface *intf,
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
pm_message_t message)
#else
u32 message)
#endif
{
	struct usbnet *dev = usb_get_intfdata(intf);

	if (!dev->suspend_count++) {
		/*
		 * accelerate emptying of the rx and queues, to avoid
		 * having everything error out.
		 */
		netif_device_detach(dev->net);
		(void) unlink_urbs(dev, &dev->rxq);
		(void) unlink_urbs(dev, &dev->txq);
		usb_kill_urb(dev->interrupt);
		/*
		 * reattach so runtime management can use and
		 * wake the device
		 */
		netif_device_attach(dev->net);
	}
	return 0;
}

static int
axusbnet_resume(struct usb_interface *intf)
{
	struct usbnet	*dev = usb_get_intfdata(intf);
	int	retval = 0;

	if (!--dev->suspend_count)
		tasklet_schedule(&dev->bh);

	retval = init_status(dev, intf);
	if (retval < 0)
		return retval;

	if (dev->interrupt) {
		retval = usb_submit_urb(dev->interrupt, GFP_KERNEL);
		if (retval < 0 && netif_msg_ifup(dev))
			deverr(dev, "intr submit %d", retval);
	}

	return retval;
}
Beispiel #23
0
static void rx_complete(struct urb *urb)
#endif
{
	struct sk_buff		*skb = (struct sk_buff *) urb->context;
	struct skb_data		*entry = (struct skb_data *) skb->cb;
	struct usbnet		*dev = entry->dev;
	int			urb_status = urb->status;

	skb_put(skb, urb->actual_length);
	entry->state = rx_done;
	entry->urb = NULL;

	switch (urb_status) {
	/* success */
	case 0:
		if (skb->len < dev->net->hard_header_len) {
			entry->state = rx_cleanup;
			dev->stats.rx_errors++;
			dev->stats.rx_length_errors++;
			if (netif_msg_rx_err(dev))
				devdbg(dev, "rx length %d", skb->len);
		}
		break;

	/* stalls need manual reset. this is rare ... except that
	 * when going through USB 2.0 TTs, unplug appears this way.
	 * we avoid the highspeed version of the ETIMEDOUT/EILSEQ
	 * storm, recovering as needed.
	 */
	case -EPIPE:
		dev->stats.rx_errors++;
		axusbnet_defer_kevent(dev, EVENT_RX_HALT);
		/* FALLTHROUGH */

	/* software-driven interface shutdown */
	case -ECONNRESET:		/* async unlink */
	case -ESHUTDOWN:		/* hardware gone */
		if (netif_msg_ifdown(dev))
			devdbg(dev, "rx shutdown, code %d", urb_status);
		goto block;

	/* we get controller i/o faults during khubd disconnect() delays.
	 * throttle down resubmits, to avoid log floods; just temporarily,
	 * so we still recover when the fault isn't a khubd delay.
	 */
	case -EPROTO:
	case -ETIME:
	case -EILSEQ:
		dev->stats.rx_errors++;
		if (!timer_pending(&dev->delay)) {
			mod_timer(&dev->delay, jiffies + THROTTLE_JIFFIES);
			if (netif_msg_link(dev))
				devdbg(dev, "rx throttle %d", urb_status);
		}
block:
		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");
}
Beispiel #24
0
static void ag71xx_phy_link_update(struct ag71xx *ag)
{
	u32 cfg2;
	u32 ifctl;
	u32 pll;
	u32 fifo5;
	u32 mii_speed;

	if (!ag->link) {
		netif_carrier_off(ag->dev);
		if (netif_msg_link(ag))
			printk(KERN_INFO "%s: link down\n", ag->dev->name);
		return;
	}

	cfg2 = ag71xx_rr(ag, AG71XX_REG_MAC_CFG2);
	cfg2 &= ~(MAC_CFG2_IF_1000 | MAC_CFG2_IF_10_100 | MAC_CFG2_FDX);
	cfg2 |= (ag->duplex) ? MAC_CFG2_FDX : 0;

	ifctl = ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL);
	ifctl &= ~(MAC_IFCTL_SPEED);

	fifo5 = ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5);
	fifo5 &= ~FIFO_CFG5_BYTE_PER_CLK;

	switch (ag->speed) {
	case SPEED_1000:
		mii_speed =  MII_CTRL_SPEED_1000;
		cfg2 |= MAC_CFG2_IF_1000;
		pll = PLL_VAL_1000;
		fifo5 |= FIFO_CFG5_BYTE_PER_CLK;
		break;
	case SPEED_100:
		mii_speed = MII_CTRL_SPEED_100;
		cfg2 |= MAC_CFG2_IF_10_100;
		ifctl |= MAC_IFCTL_SPEED;
		pll = PLL_VAL_100;
		break;
	case SPEED_10:
		mii_speed = MII_CTRL_SPEED_10;
		cfg2 |= MAC_CFG2_IF_10_100;
		pll = PLL_VAL_10;
		break;
	default:
		BUG();
		return;
	}

	ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x008001ff);
	ag71xx_set_pll(ag, pll);
	ag71xx_mii_ctrl_set_speed(ag, mii_speed);

	ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2);
	ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, fifo5);
	ag71xx_wr(ag, AG71XX_REG_MAC_IFCTL, ifctl);

	netif_carrier_on(ag->dev);
	if (netif_msg_link(ag))
		printk(KERN_INFO "%s: link up (%sMbps/%s duplex)\n",
			ag->dev->name,
			ag71xx_speed_str(ag),
			(DUPLEX_FULL == ag->duplex) ? "Full" : "Half");

	DBG("%s: fifo1=%#x, fifo2=%#x, fifo3=%#x, fifo4=%#x, fifo5=%#x\n",
		ag->dev->name,
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG1),
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG2),
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG3),
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG4),
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5));

	DBG("%s: mac_cfg2=%#x, ifctl=%#x, mii_ctrl=%#x\n",
		ag->dev->name,
		ag71xx_rr(ag, AG71XX_REG_MAC_CFG2),
		ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL),
		ag71xx_mii_ctrl_rr(ag));
}
Beispiel #25
0
/**
 * stmmac_adjust_link
 * @dev: net device structure
 * Description: it adjusts the link parameters.
 */
static void stmmac_adjust_link(struct net_device *dev)
{
	struct stmmac_priv *priv = netdev_priv(dev);
	struct phy_device *phydev = priv->phydev;
	unsigned long flags;
	int new_state = 0;
	unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;

	if (phydev == NULL)
		return;

	DBG(probe, DEBUG, "stmmac_adjust_link: called.  address %d link %d\n",
	    phydev->addr, phydev->link);

	spin_lock_irqsave(&priv->lock, flags);
	if (phydev->link) {
		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);

		/* Now we make sure that we can be in full duplex mode.
		 * If not, we operate in half-duplex mode. */
		if (phydev->duplex != priv->oldduplex) {
			new_state = 1;
			if (!(phydev->duplex))
				ctrl &= ~priv->hw->link.duplex;
			else
				ctrl |= priv->hw->link.duplex;
			priv->oldduplex = phydev->duplex;
		}
		/* Flow Control operation */
		if (phydev->pause)
			priv->hw->mac->flow_ctrl(priv->ioaddr, phydev->duplex,
						 fc, pause_time);

		if (phydev->speed != priv->speed) {
			new_state = 1;
			switch (phydev->speed) {
			case 1000:
				if (likely(priv->plat->has_gmac))
					ctrl &= ~priv->hw->link.port;
				stmmac_hw_fix_mac_speed(priv);
				break;
			case 100:
			case 10:
				if (priv->plat->has_gmac) {
					ctrl |= priv->hw->link.port;
					if (phydev->speed == SPEED_100) {
						ctrl |= priv->hw->link.speed;
					} else {
						ctrl &= ~(priv->hw->link.speed);
					}
				} else {
					ctrl &= ~priv->hw->link.port;
				}
				stmmac_hw_fix_mac_speed(priv);
				break;
			default:
				if (netif_msg_link(priv))
					pr_warning("%s: Speed (%d) is not 10"
				       " or 100!\n", dev->name, phydev->speed);
				break;
			}

			priv->speed = phydev->speed;
		}

		writel(ctrl, priv->ioaddr + MAC_CTRL_REG);

		if (!priv->oldlink) {
			new_state = 1;
			priv->oldlink = 1;
		}
	} else if (priv->oldlink) {
		new_state = 1;
		priv->oldlink = 0;
		priv->speed = 0;
		priv->oldduplex = -1;
	}

	if (new_state && netif_msg_link(priv))
		phy_print_status(phydev);

	spin_unlock_irqrestore(&priv->lock, flags);

	DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n");
}
Beispiel #26
0
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;

#ifdef TX_URB_MONITOR
	unsigned char b_usb_if_num = 0;
    int iRet = get_usb_interface(urb, &b_usb_if_num);
#endif //#ifdef TX_URB_MONITOR

   if (urb->status == 0)
   {
      if (!(dev->driver_info->flags & FLAG_MULTI_PACKET))
         dev->net->stats.tx_packets++;
      dev->net->stats.tx_bytes += entry->length;
   }
   else
   {
      dev->net->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;
       
         // like rx, tx gets controller i/o faults during khubd delays
         // and so it uses the same throttling mechanism.
         case -EPROTO:
         case -ETIME:
         case -EILSEQ:
            if (!timer_pending (&dev->delay)) {
             mod_timer (&dev->delay,
             jiffies + THROTTLE_JIFFIES);
            if (netif_msg_link (dev))
            #if (LINUX_VERSION_CODE != KERNEL_VERSION( 3,0,6 ))
               devdbg (dev, "tx throttle %d",
                            urb->status);
            #else
			         	netif_dbg(dev, link, dev->net,
				                  	  "tx throttle %d\n", urb->status);
            #endif
            }
            netif_stop_queue (dev->net);
            break;
         default:
            if (netif_msg_tx_err (dev))
            #if (LINUX_VERSION_CODE != KERNEL_VERSION( 3,0,6 ))
               devdbg (dev, "tx err %d", entry->urb->status);
            #else
			          netif_dbg(dev, tx_err, dev->net,
				                       "tx err %d\n", entry->urb->status);
            #endif
            break;
    		}
  	}

   usb_autopm_put_interface_async(dev->intf);
   urb->dev = NULL;
   entry->state = tx_done;
   defer_bh(dev, skb, &dev->txq);

#ifdef TX_URB_MONITOR
   if ((URB_monitor) && (0==iRet))
   {
       URB_monitor(false, b_usb_if_num);
   }
#endif //#ifdef TX_URB_MONITOR

}
Beispiel #27
0
void ag71xx_link_adjust(struct ag71xx *ag)
{
	struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag);
	u32 cfg2;
	u32 ifctl;
	u32 fifo5;
	u32 mii_speed;

	if (!ag->link) {
		netif_carrier_off(ag->dev);
		if (netif_msg_link(ag))
			printk(KERN_INFO "%s: link down\n", ag->dev->name);
		return;
	}

	cfg2 = ag71xx_rr(ag, AG71XX_REG_MAC_CFG2);
	cfg2 &= ~(MAC_CFG2_IF_1000 | MAC_CFG2_IF_10_100 | MAC_CFG2_FDX);
	cfg2 |= (ag->duplex) ? MAC_CFG2_FDX : 0;

	ifctl = ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL);
	ifctl &= ~(MAC_IFCTL_SPEED);

	fifo5 = ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5);
	fifo5 &= ~FIFO_CFG5_BM;

	switch (ag->speed) {
	case SPEED_1000:
		mii_speed =  MII_CTRL_SPEED_1000;
		cfg2 |= MAC_CFG2_IF_1000;
		fifo5 |= FIFO_CFG5_BM;
		break;
	case SPEED_100:
		mii_speed = MII_CTRL_SPEED_100;
		cfg2 |= MAC_CFG2_IF_10_100;
		ifctl |= MAC_IFCTL_SPEED;
		break;
	case SPEED_10:
		mii_speed = MII_CTRL_SPEED_10;
		cfg2 |= MAC_CFG2_IF_10_100;
		break;
	default:
		BUG();
		return;
	}

	if (pdata->is_ar91xx)
		ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x00780fff);
	else if (pdata->is_ar724x)
		ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, pdata->fifo_cfg3);
	else
		ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x008001ff);

	if (pdata->set_pll)
		pdata->set_pll(ag->speed);

	ag71xx_mii_ctrl_set_speed(ag, mii_speed);

	ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2);
	ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, fifo5);
	ag71xx_wr(ag, AG71XX_REG_MAC_IFCTL, ifctl);

	netif_carrier_on(ag->dev);
	if (netif_msg_link(ag))
		printk(KERN_INFO "%s: link up (%sMbps/%s duplex)\n",
			ag->dev->name,
			ag71xx_speed_str(ag),
			(DUPLEX_FULL == ag->duplex) ? "Full" : "Half");

	DBG("%s: fifo_cfg0=%#x, fifo_cfg1=%#x, fifo_cfg2=%#x\n",
		ag->dev->name,
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG0),
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG1),
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG2));

	DBG("%s: fifo_cfg3=%#x, fifo_cfg4=%#x, fifo_cfg5=%#x\n",
		ag->dev->name,
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG3),
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG4),
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5));

	DBG("%s: mac_cfg2=%#x, mac_ifctl=%#x, mii_ctrl=%#x\n",
		ag->dev->name,
		ag71xx_rr(ag, AG71XX_REG_MAC_CFG2),
		ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL),
		ag71xx_mii_ctrl_rr(ag));
}
Beispiel #28
0
static void tc_handle_link_change(struct net_device *dev)
{
	struct tc35815_local *lp = netdev_priv(dev);
	struct phy_device *phydev = dev->phydev;
	unsigned long flags;
	int status_change = 0;

	spin_lock_irqsave(&lp->lock, flags);
	if (phydev->link &&
	    (lp->speed != phydev->speed || lp->duplex != phydev->duplex)) {
		struct tc35815_regs __iomem *tr =
			(struct tc35815_regs __iomem *)dev->base_addr;
		u32 reg;

		reg = tc_readl(&tr->MAC_Ctl);
		reg |= MAC_HaltReq;
		tc_writel(reg, &tr->MAC_Ctl);
		if (phydev->duplex == DUPLEX_FULL)
			reg |= MAC_FullDup;
		else
			reg &= ~MAC_FullDup;
		tc_writel(reg, &tr->MAC_Ctl);
		reg &= ~MAC_HaltReq;
		tc_writel(reg, &tr->MAC_Ctl);

		/*
		 * TX4939 PCFG.SPEEDn bit will be changed on
		 * NETDEV_CHANGE event.
		 */
		/*
		 * WORKAROUND: enable LostCrS only if half duplex
		 * operation.
		 * (TX4939 does not have EnLCarr)
		 */
		if (phydev->duplex == DUPLEX_HALF &&
		    lp->chiptype != TC35815_TX4939)
			tc_writel(tc_readl(&tr->Tx_Ctl) | Tx_EnLCarr,
				  &tr->Tx_Ctl);

		lp->speed = phydev->speed;
		lp->duplex = phydev->duplex;
		status_change = 1;
	}

	if (phydev->link != lp->link) {
		if (phydev->link) {
			/* delayed promiscuous enabling */
			if (dev->flags & IFF_PROMISC)
				tc35815_set_multicast_list(dev);
		} else {
			lp->speed = 0;
			lp->duplex = -1;
		}
		lp->link = phydev->link;

		status_change = 1;
	}
	spin_unlock_irqrestore(&lp->lock, flags);

	if (status_change && netif_msg_link(lp)) {
		phy_print_status(phydev);
		pr_debug("%s: MII BMCR %04x BMSR %04x LPA %04x\n",
			 dev->name,
			 phy_read(phydev, MII_BMCR),
			 phy_read(phydev, MII_BMSR),
			 phy_read(phydev, MII_LPA));
	}
}