Beispiel #1
0
static void __lpc_handle_xmit(struct net_device *ndev)
{
	struct netdata_local *pldat = netdev_priv(ndev);
	struct sk_buff *skb;
	u32 txcidx, *ptxstat, txstat;

	txcidx = readl(LPC_ENET_TXCONSUMEINDEX(pldat->net_base));
	while (pldat->last_tx_idx != txcidx) {
		skb = pldat->skb[pldat->last_tx_idx];

		/* A buffer is available, get buffer status */
		ptxstat = &pldat->tx_stat_v[pldat->last_tx_idx];
		txstat = *ptxstat;

		/* Next buffer and decrement used buffer counter */
		pldat->num_used_tx_buffs--;
		pldat->last_tx_idx++;
		if (pldat->last_tx_idx >= ENET_TX_DESC)
			pldat->last_tx_idx = 0;

		/* Update collision counter */
		ndev->stats.collisions += TXSTATUS_COLLISIONS_GET(txstat);

		/* Any errors occurred? */
		if (txstat & TXSTATUS_ERROR) {
			if (txstat & TXSTATUS_UNDERRUN) {
				/* FIFO underrun */
				ndev->stats.tx_fifo_errors++;
			}
			if (txstat & TXSTATUS_LATECOLL) {
				/* Late collision */
				ndev->stats.tx_aborted_errors++;
			}
			if (txstat & TXSTATUS_EXCESSCOLL) {
				/* Excessive collision */
				ndev->stats.tx_aborted_errors++;
			}
			if (txstat & TXSTATUS_EXCESSDEFER) {
				/* Defer limit */
				ndev->stats.tx_aborted_errors++;
			}
			ndev->stats.tx_errors++;
		} else {
			/* Update stats */
			ndev->stats.tx_packets++;
			ndev->stats.tx_bytes += skb->len;

			/* Free buffer */
			dev_kfree_skb_irq(skb);
		}

		txcidx = readl(LPC_ENET_TXCONSUMEINDEX(pldat->net_base));
	}

	if (netif_queue_stopped(ndev))
		netif_wake_queue(ndev);
}
Beispiel #2
0
static void __lpc_eth_init(struct netdata_local *pldat)
{
	u32 tmp;

	/* Disable controller and reset */
	tmp = readl(LPC_ENET_COMMAND(pldat->net_base));
	tmp &= ~LPC_COMMAND_RXENABLE | LPC_COMMAND_TXENABLE;
	writel(tmp, LPC_ENET_COMMAND(pldat->net_base));
	tmp = readl(LPC_ENET_MAC1(pldat->net_base));
	tmp &= ~LPC_MAC1_RECV_ENABLE;
	writel(tmp, LPC_ENET_MAC1(pldat->net_base));

	/* Initial MAC setup */
	writel(LPC_MAC1_PASS_ALL_RX_FRAMES, LPC_ENET_MAC1(pldat->net_base));
	writel((LPC_MAC2_PAD_CRC_ENABLE | LPC_MAC2_CRC_ENABLE),
	       LPC_ENET_MAC2(pldat->net_base));
	writel(ENET_MAXF_SIZE, LPC_ENET_MAXF(pldat->net_base));

	/* Collision window, gap */
	writel((LPC_CLRT_LOAD_RETRY_MAX(0xF) |
		LPC_CLRT_LOAD_COLLISION_WINDOW(0x37)),
	       LPC_ENET_CLRT(pldat->net_base));
	writel(LPC_IPGR_LOAD_PART2(0x12), LPC_ENET_IPGR(pldat->net_base));

	if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII)
		writel(LPC_COMMAND_PASSRUNTFRAME,
		       LPC_ENET_COMMAND(pldat->net_base));
	else {
		writel((LPC_COMMAND_PASSRUNTFRAME | LPC_COMMAND_RMII),
		       LPC_ENET_COMMAND(pldat->net_base));
		writel(LPC_SUPP_RESET_RMII, LPC_ENET_SUPP(pldat->net_base));
	}

	__lpc_params_setup(pldat);

	/* Setup TX and RX descriptors */
	__lpc_txrx_desc_setup(pldat);

	/* Setup packet filtering */
	writel((LPC_RXFLTRW_ACCEPTUBROADCAST | LPC_RXFLTRW_ACCEPTPERFECT),
	       LPC_ENET_RXFILTER_CTRL(pldat->net_base));

	/* Get the next TX buffer output index */
	pldat->num_used_tx_buffs = 0;
	pldat->last_tx_idx =
		readl(LPC_ENET_TXCONSUMEINDEX(pldat->net_base));

	/* Clear and enable interrupts */
	writel(0xFFFF, LPC_ENET_INTCLEAR(pldat->net_base));
	smp_wmb();
	lpc_eth_enable_int(pldat->net_base);

	/* Enable controller */
	tmp = readl(LPC_ENET_COMMAND(pldat->net_base));
	tmp |= LPC_COMMAND_RXENABLE | LPC_COMMAND_TXENABLE;
	writel(tmp, LPC_ENET_COMMAND(pldat->net_base));
	tmp = readl(LPC_ENET_MAC1(pldat->net_base));
	tmp |= LPC_MAC1_RECV_ENABLE;
	writel(tmp, LPC_ENET_MAC1(pldat->net_base));
}