Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 35560392 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'fec-next'



Russell King says:

====================
Freescale ethernet driver updates (part 2)

Here's the second batch of patches for the Freescale FEC ethernet driver,
based upon the previous set of patches.  One further set of 7 patches
remains.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2167cefc ef83337d
Loading
Loading
Loading
Loading
+84 −43
Original line number Diff line number Diff line
@@ -818,12 +818,13 @@ static void fec_enet_bd_init(struct net_device *dev)
	fep->dirty_tx = bdp;
}

/* This function is called to start or restart the FEC during a link
 * change.  This only happens when switching between half and full
 * duplex.
/*
 * This function is called to start or restart the FEC during a link
 * change, transmit timeout, or to reconfigure the FEC.  The network
 * packet processing for this device must be stopped before this call.
 */
static void
fec_restart(struct net_device *ndev, int duplex)
fec_restart(struct net_device *ndev)
{
	struct fec_enet_private *fep = netdev_priv(ndev);
	const struct platform_device_id *id_entry =
@@ -834,13 +835,6 @@ fec_restart(struct net_device *ndev, int duplex)
	u32 rcntl = OPT_FRAME_SIZE | 0x04;
	u32 ecntl = 0x2; /* ETHEREN */

	if (netif_running(ndev)) {
		netif_device_detach(ndev);
		napi_disable(&fep->napi);
		netif_tx_disable(ndev);
		netif_tx_lock_bh(ndev);
	}

	/* Whack a reset.  We should wait for this. */
	writel(1, fep->hwp + FEC_ECNTRL);
	udelay(10);
@@ -881,7 +875,7 @@ fec_restart(struct net_device *ndev, int duplex)
	}

	/* Enable MII mode */
	if (duplex) {
	if (fep->full_duplex == DUPLEX_FULL) {
		/* FD enable */
		writel(0x04, fep->hwp + FEC_X_CNTRL);
	} else {
@@ -890,8 +884,6 @@ fec_restart(struct net_device *ndev, int duplex)
		writel(0x0, fep->hwp + FEC_X_CNTRL);
	}

	fep->full_duplex = duplex;

	/* Set MII speed */
	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);

@@ -1009,13 +1001,6 @@ fec_restart(struct net_device *ndev, int duplex)

	/* Enable interrupts we wish to service */
	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);

	if (netif_running(ndev)) {
		netif_tx_unlock_bh(ndev);
		netif_wake_queue(ndev);
		napi_enable(&fep->napi);
		netif_device_attach(ndev);
	}
}

static void
@@ -1065,11 +1050,20 @@ static void fec_enet_work(struct work_struct *work)
		container_of(work,
			     struct fec_enet_private,
			     delay_work.delay_work.work);
	struct net_device *ndev = fep->netdev;

	if (fep->delay_work.timeout) {
		fep->delay_work.timeout = false;
		fec_restart(fep->netdev, fep->full_duplex);
		netif_wake_queue(fep->netdev);
		rtnl_lock();
		if (netif_device_present(ndev) || netif_running(ndev)) {
			napi_disable(&fep->napi);
			netif_tx_lock_bh(ndev);
			fec_restart(ndev);
			netif_wake_queue(ndev);
			netif_tx_unlock_bh(ndev);
			napi_enable(&fep->napi);
		}
		rtnl_unlock();
	}

	if (fep->delay_work.trig_tx) {
@@ -1502,14 +1496,23 @@ static void fec_enet_adjust_link(struct net_device *ndev)
		return;
	}

	if (phy_dev->link) {
	/*
	 * If the netdev is down, or is going down, we're not interested
	 * in link state events, so just mark our idea of the link as down
	 * and ignore the event.
	 */
	if (!netif_running(ndev) || !netif_device_present(ndev)) {
		fep->link = 0;
	} else if (phy_dev->link) {
		if (!fep->link) {
			fep->link = phy_dev->link;
			status_change = 1;
		}

		if (fep->full_duplex != phy_dev->duplex)
		if (fep->full_duplex != phy_dev->duplex) {
			fep->full_duplex = phy_dev->duplex;
			status_change = 1;
		}

		if (phy_dev->speed != fep->speed) {
			fep->speed = phy_dev->speed;
@@ -1517,11 +1520,21 @@ static void fec_enet_adjust_link(struct net_device *ndev)
		}

		/* if any of the above changed restart the FEC */
		if (status_change)
			fec_restart(ndev, phy_dev->duplex);
		if (status_change) {
			napi_disable(&fep->napi);
			netif_tx_lock_bh(ndev);
			fec_restart(ndev);
			netif_wake_queue(ndev);
			netif_tx_unlock_bh(ndev);
			napi_enable(&fep->napi);
		}
	} else {
		if (fep->link) {
			napi_disable(&fep->napi);
			netif_tx_lock_bh(ndev);
			fec_stop(ndev);
			netif_tx_unlock_bh(ndev);
			napi_enable(&fep->napi);
			fep->link = phy_dev->link;
			status_change = 1;
		}
@@ -1903,8 +1916,14 @@ static int fec_enet_set_pauseparam(struct net_device *ndev,
			fec_stop(ndev);
		phy_start_aneg(fep->phy_dev);
	}
	if (netif_running(ndev))
		fec_restart(ndev, fep->full_duplex);
	if (netif_running(ndev)) {
		napi_disable(&fep->napi);
		netif_tx_lock_bh(ndev);
		fec_restart(ndev);
		netif_wake_queue(ndev);
		netif_tx_unlock_bh(ndev);
		napi_enable(&fep->napi);
	}

	return 0;
}
@@ -2182,6 +2201,7 @@ fec_enet_open(struct net_device *ndev)
		return ret;
	}

	fec_restart(ndev);
	napi_enable(&fep->napi);
	phy_start(fep->phy_dev);
	netif_start_queue(ndev);
@@ -2195,10 +2215,11 @@ fec_enet_close(struct net_device *ndev)

	phy_stop(fep->phy_dev);

	/* Don't know what to do yet. */
	if (netif_device_present(ndev)) {
		napi_disable(&fep->napi);
		netif_tx_disable(ndev);
		fec_stop(ndev);
	}

	phy_disconnect(fep->phy_dev);
	fep->phy_dev = NULL;
@@ -2329,12 +2350,21 @@ static void fec_poll_controller(struct net_device *dev)
}
#endif

#define FEATURES_NEED_QUIESCE NETIF_F_RXCSUM

static int fec_set_features(struct net_device *netdev,
	netdev_features_t features)
{
	struct fec_enet_private *fep = netdev_priv(netdev);
	netdev_features_t changed = features ^ netdev->features;

	/* Quiesce the device if necessary */
	if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) {
		napi_disable(&fep->napi);
		netif_tx_lock_bh(netdev);
		fec_stop(netdev);
	}

	netdev->features = features;

	/* Receive checksum has been changed */
@@ -2343,14 +2373,14 @@ static int fec_set_features(struct net_device *netdev,
			fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
		else
			fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED;
	}

		if (netif_running(netdev)) {
			fec_stop(netdev);
			fec_restart(netdev, fep->phy_dev->duplex);
	/* Resume the device after updates */
	if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) {
		fec_restart(netdev);
		netif_wake_queue(netdev);
		} else {
			fec_restart(netdev, fep->phy_dev->duplex);
		}
		netif_tx_unlock_bh(netdev);
		napi_enable(&fep->napi);
	}

	return 0;
@@ -2451,7 +2481,7 @@ static int fec_enet_init(struct net_device *ndev)

	ndev->hw_features = ndev->features;

	fec_restart(ndev, 0);
	fec_restart(ndev);

	return 0;
}
@@ -2680,11 +2710,17 @@ fec_suspend(struct device *dev)
	struct net_device *ndev = dev_get_drvdata(dev);
	struct fec_enet_private *fep = netdev_priv(ndev);

	rtnl_lock();
	if (netif_running(ndev)) {
		phy_stop(fep->phy_dev);
		fec_stop(ndev);
		napi_disable(&fep->napi);
		netif_tx_lock_bh(ndev);
		netif_device_detach(ndev);
		netif_tx_unlock_bh(ndev);
		fec_stop(ndev);
	}
	rtnl_unlock();

	fec_enet_clk_enable(ndev, false);
	pinctrl_pm_select_sleep_state(&fep->pdev->dev);

@@ -2712,11 +2748,16 @@ fec_resume(struct device *dev)
	if (ret)
		goto failed_clk;

	rtnl_lock();
	if (netif_running(ndev)) {
		fec_restart(ndev, fep->full_duplex);
		fec_restart(ndev);
		netif_tx_lock_bh(ndev);
		netif_device_attach(ndev);
		netif_tx_unlock_bh(ndev);
		napi_enable(&fep->napi);
		phy_start(fep->phy_dev);
	}
	rtnl_unlock();

	return 0;