Example #1
0
/**
 * arc_emac_stop - Close the network device.
 * @ndev:	Pointer to the network device.
 *
 * This function stops the Tx queue, disables interrupts and frees the IRQ for
 * the EMAC device.
 * It also disconnects the PHY device associated with the EMAC device.
 */
static int arc_emac_stop(struct net_device *ndev)
{
	struct arc_emac_priv *priv = netdev_priv(ndev);

	napi_disable(&priv->napi);
	netif_stop_queue(ndev);

	/* Disable interrupts */
	arc_reg_clr(priv, R_ENABLE, RXINT_MASK | ERR_MASK);

	/* Disable EMAC */
	arc_reg_clr(priv, R_CTRL, EN_MASK);

	return 0;
}
Example #2
0
/**
 * arc_emac_set_rx_mode - Change the receive filtering mode.
 * @ndev:	Pointer to the network device.
 *
 * This function enables/disables promiscuous or all-multicast mode
 * and updates the multicast filtering list of the network device.
 */
static void arc_emac_set_rx_mode(struct net_device *ndev)
{
	struct arc_emac_priv *priv = netdev_priv(ndev);

	if (ndev->flags & IFF_PROMISC) {
		arc_reg_or(priv, R_CTRL, PROM_MASK);
	} else {
		arc_reg_clr(priv, R_CTRL, PROM_MASK);

		if (ndev->flags & IFF_ALLMULTI) {
			arc_reg_set(priv, R_LAFL, ~0);
			arc_reg_set(priv, R_LAFH, ~0);
		} else if (ndev->flags & IFF_MULTICAST) {
			struct netdev_hw_addr *ha;
			unsigned int filter[2] = { 0, 0 };
			int bit;

			netdev_for_each_mc_addr(ha, ndev) {
				bit = ether_crc_le(ETH_ALEN, ha->addr) >> 26;
				filter[bit >> 5] |= 1 << (bit & 31);
			}

			arc_reg_set(priv, R_LAFL, filter[0]);
			arc_reg_set(priv, R_LAFH, filter[1]);
		} else {
Example #3
0
static void arc_emac_halt(struct eth_device *edev)
{
	struct arc_emac_priv *priv = edev->priv;

	/* Disable EMAC */
	arc_reg_clr(priv, R_CTRL, EN_MASK);
}
Example #4
0
/**
 * arc_emac_intr - Global interrupt handler for EMAC.
 * @irq:		irq number.
 * @dev_instance:	device instance.
 *
 * returns: IRQ_HANDLED for all cases.
 *
 * ARC EMAC has only 1 interrupt line, and depending on bits raised in
 * STATUS register we may tell what is a reason for interrupt to fire.
 */
static irqreturn_t arc_emac_intr(int irq, void *dev_instance)
{
	struct net_device *ndev = dev_instance;
	struct arc_emac_priv *priv = netdev_priv(ndev);
	struct net_device_stats *stats = &ndev->stats;
	unsigned int status;

	status = arc_reg_get(priv, R_STATUS);
	status &= ~MDIO_MASK;

	/* Reset all flags except "MDIO complete" */
	arc_reg_set(priv, R_STATUS, status);

	if (status & (RXINT_MASK | TXINT_MASK)) {
		if (likely(napi_schedule_prep(&priv->napi))) {
			arc_reg_clr(priv, R_ENABLE, RXINT_MASK | TXINT_MASK);
			__napi_schedule(&priv->napi);
		}
	}

	if (status & ERR_MASK) {
		/* MSER/RXCR/RXFR/RXFL interrupt fires on corresponding
		 * 8-bit error counter overrun.
		 */

		if (status & MSER_MASK) {
			stats->rx_missed_errors += 0x100;
			stats->rx_errors += 0x100;
			priv->rx_missed_errors += 0x100;
			napi_schedule(&priv->napi);
		}

		if (status & RXCR_MASK) {
			stats->rx_crc_errors += 0x100;
			stats->rx_errors += 0x100;
		}

		if (status & RXFR_MASK) {
			stats->rx_frame_errors += 0x100;
			stats->rx_errors += 0x100;
		}

		if (status & RXFL_MASK) {
			stats->rx_over_errors += 0x100;
			stats->rx_errors += 0x100;
		}
	}

	return IRQ_HANDLED;
}