diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-08-23 14:12:22 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-08-23 14:12:22 +0200 |
commit | 68538bf2bce557c3b5fe8c59b034d45352500db1 (patch) | |
tree | a84b68990cadcbfc277acc7b7f2b75716750e203 /drivers/net/ethernet/freescale/fec_main.c | |
parent | a8cc20999799a94929a56393ff39b32245e33d64 (diff) | |
parent | 43bcb402f84fe459102120b4e2d28d7117f16cd0 (diff) |
Merge tag 'asoc-v3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next
ASoC: Updates for v3.12
- DAPM is now mandatory for CODEC drivers in order to avoid the repeated
regressions in the special cases for non-DAPM CODECs and make it
easier to integrate with other components on boards. All existing
drivers have had some level of DAPM support added.
- A lot of cleanups in DAPM plus support for maintaining controls in a
specific state while a DAPM widget all contributed by Lars-Peter Clausen.
- Core helpers for bitbanged AC'97 reset from Markus Pargmann.
- New drivers and support for Analog Devices ADAU1702 and ADAU1401(a),
Asahi Kasei Microdevices AK4554, Atmel AT91ASM9x5 and WM8904 based
machines, Freescale S/PDIF and SSI AC'97, Renesas R-Car SoCs, Samsung
Exynos5420 SoCs, Texas Instruments PCM1681 and PCM1792A and Wolfson
Microelectronics WM8997.
- Support for building drivers that can support it cross-platform for
compile test.
Diffstat (limited to 'drivers/net/ethernet/freescale/fec_main.c')
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index d3ad5ea711d..77ea0db0bbf 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -93,6 +93,20 @@ static void set_multicast_list(struct net_device *ndev); #define FEC_QUIRK_HAS_CSUM (1 << 5) /* Controller has hardware vlan support */ #define FEC_QUIRK_HAS_VLAN (1 << 6) +/* ENET IP errata ERR006358 + * + * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously + * detected as not set during a prior frame transmission, then the + * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs + * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in + * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously + * detected as not set during a prior frame transmission, then the + * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs + * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in + * frames not being transmitted until there is a 0-to-1 transition on + * ENET_TDAR[TDAR]. + */ +#define FEC_QUIRK_ERR006358 (1 << 7) static struct platform_device_id fec_devtype[] = { { @@ -112,7 +126,7 @@ static struct platform_device_id fec_devtype[] = { .name = "imx6q-fec", .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | - FEC_QUIRK_HAS_VLAN, + FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358, }, { .name = "mvf600-fec", .driver_data = FEC_QUIRK_ENET_MAC, @@ -275,16 +289,11 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct fec_enet_private *fep = netdev_priv(ndev); const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); - struct bufdesc *bdp; + struct bufdesc *bdp, *bdp_pre; void *bufaddr; unsigned short status; unsigned int index; - if (!fep->link) { - /* Link is down or auto-negotiation is in progress. */ - return NETDEV_TX_BUSY; - } - /* Fill in a Tx ring entry */ bdp = fep->cur_tx; @@ -370,6 +379,15 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) ebdp->cbd_esc |= BD_ENET_TX_PINS; } } + + bdp_pre = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex); + if ((id_entry->driver_data & FEC_QUIRK_ERR006358) && + !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) { + fep->delay_work.trig_tx = true; + schedule_delayed_work(&(fep->delay_work.delay_work), + msecs_to_jiffies(1)); + } + /* If this was the last BD in the ring, start at the beginning again. */ if (status & BD_ENET_TX_WRAP) bdp = fep->tx_bd_base; @@ -689,6 +707,11 @@ static void fec_enet_work(struct work_struct *work) fec_restart(fep->netdev, fep->full_duplex); netif_wake_queue(fep->netdev); } + + if (fep->delay_work.trig_tx) { + fep->delay_work.trig_tx = false; + writel(0, fep->hwp + FEC_X_DES_ACTIVE); + } } static void @@ -2279,4 +2302,5 @@ static struct platform_driver fec_driver = { module_platform_driver(fec_driver); +MODULE_ALIAS("platform:"DRIVER_NAME); MODULE_LICENSE("GPL"); |