Commit 81206ebc authored by David S. Miller's avatar David S. Miller

Merge branch 'gianfar'

Claudiu Manoil says:

====================
gianfar: Device configuration fixes

This patchset represents the first part of an effort
to solve some old device configuration issues in gianfar,
especially run-time reset and re-configuration problems.
I'm referring to "on-the-fly" configuration of registers
against HW specification, concurrency issues during device
reset / re-configuration operations, and implementing HW
advisories for these operations.

There's also a good deal of code cleanup and refactoring,
and some other (minor) fixes as well.

v2: Remove sysfs stubs w/o replacing them with module
    params (patch 2).
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c85fde83 7cca336a
The Gianfar Ethernet Driver The Gianfar Ethernet Driver
Sysfs File description
Author: Andy Fleming <afleming@freescale.com> Author: Andy Fleming <afleming@freescale.com>
Updated: 2005-07-28 Updated: 2005-07-28
SYSFS
Several of the features of the gianfar driver are controlled
through sysfs files. These are:
bd_stash:
To stash RX Buffer Descriptors in the L2, echo 'on' or '1' to
bd_stash, echo 'off' or '0' to disable
rx_stash_len:
To stash the first n bytes of the packet in L2, echo the number
of bytes to buf_stash_len. echo 0 to disable.
WARNING: You could really screw these up if you set them too low or high!
fifo_threshold:
To change the number of bytes the controller needs in the
fifo before it starts transmission, echo the number of bytes to
fifo_thresh. Range should be 0-511.
fifo_starve:
When the FIFO has less than this many bytes during a transmit, it
enters starve mode, and increases the priority of TX memory
transactions. To change, echo the number of bytes to
fifo_starve. Range should be 0-511.
fifo_starve_off:
Once in starve mode, the FIFO remains there until it has this
many bytes. To change, echo the number of bytes to
fifo_starve_off. Range should be 0-511.
CHECKSUM OFFLOADING CHECKSUM OFFLOADING
......
...@@ -14,7 +14,6 @@ obj-$(CONFIG_FSL_XGMAC_MDIO) += xgmac_mdio.o ...@@ -14,7 +14,6 @@ obj-$(CONFIG_FSL_XGMAC_MDIO) += xgmac_mdio.o
obj-$(CONFIG_GIANFAR) += gianfar_driver.o obj-$(CONFIG_GIANFAR) += gianfar_driver.o
obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o
gianfar_driver-objs := gianfar.o \ gianfar_driver-objs := gianfar.o \
gianfar_ethtool.o \ gianfar_ethtool.o
gianfar_sysfs.o
obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Maintainer: Kumar Gala * Maintainer: Kumar Gala
* Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com> * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
* *
* Copyright 2002-2009, 2011 Freescale Semiconductor, Inc. * Copyright 2002-2009, 2011-2013 Freescale Semiconductor, Inc.
* Copyright 2007 MontaVista Software, Inc. * Copyright 2007 MontaVista Software, Inc.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
...@@ -138,9 +138,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit); ...@@ -138,9 +138,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit);
static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue); static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue);
static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb, static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
int amount_pull, struct napi_struct *napi); int amount_pull, struct napi_struct *napi);
void gfar_halt(struct net_device *dev); static void gfar_halt_nodisable(struct gfar_private *priv);
static void gfar_halt_nodisable(struct net_device *dev);
void gfar_start(struct net_device *dev);
static void gfar_clear_exact_match(struct net_device *dev); static void gfar_clear_exact_match(struct net_device *dev);
static void gfar_set_mac_for_addr(struct net_device *dev, int num, static void gfar_set_mac_for_addr(struct net_device *dev, int num,
const u8 *addr); const u8 *addr);
...@@ -338,7 +336,6 @@ static void gfar_init_mac(struct net_device *ndev) ...@@ -338,7 +336,6 @@ static void gfar_init_mac(struct net_device *ndev)
struct gfar __iomem *regs = priv->gfargrp[0].regs; struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 rctrl = 0; u32 rctrl = 0;
u32 tctrl = 0; u32 tctrl = 0;
u32 attrs = 0;
/* write the tx/rx base registers */ /* write the tx/rx base registers */
gfar_init_tx_rx_base(priv); gfar_init_tx_rx_base(priv);
...@@ -376,13 +373,6 @@ static void gfar_init_mac(struct net_device *ndev) ...@@ -376,13 +373,6 @@ static void gfar_init_mac(struct net_device *ndev)
rctrl |= RCTRL_PADDING(priv->padding); rctrl |= RCTRL_PADDING(priv->padding);
} }
/* Insert receive time stamps into padding alignment bytes */
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) {
rctrl &= ~RCTRL_PAL_MASK;
rctrl |= RCTRL_PADDING(8);
priv->padding = 8;
}
/* Enable HW time stamping if requested from user space */ /* Enable HW time stamping if requested from user space */
if (priv->hwts_rx_en) { if (priv->hwts_rx_en) {
rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE; rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
...@@ -409,29 +399,6 @@ static void gfar_init_mac(struct net_device *ndev) ...@@ -409,29 +399,6 @@ static void gfar_init_mac(struct net_device *ndev)
} }
gfar_write(&regs->tctrl, tctrl); gfar_write(&regs->tctrl, tctrl);
/* Set the extraction length and index */
attrs = ATTRELI_EL(priv->rx_stash_size) |
ATTRELI_EI(priv->rx_stash_index);
gfar_write(&regs->attreli, attrs);
/* Start with defaults, and add stashing or locking
* depending on the approprate variables
*/
attrs = ATTR_INIT_SETTINGS;
if (priv->bd_stash_en)
attrs |= ATTR_BDSTASH;
if (priv->rx_stash_size != 0)
attrs |= ATTR_BUFSTASH;
gfar_write(&regs->attr, attrs);
gfar_write(&regs->fifo_tx_thr, priv->fifo_threshold);
gfar_write(&regs->fifo_tx_starve, priv->fifo_starve);
gfar_write(&regs->fifo_tx_starve_shutoff, priv->fifo_starve_off);
} }
static struct net_device_stats *gfar_get_stats(struct net_device *dev) static struct net_device_stats *gfar_get_stats(struct net_device *dev)
...@@ -479,6 +446,29 @@ static const struct net_device_ops gfar_netdev_ops = { ...@@ -479,6 +446,29 @@ static const struct net_device_ops gfar_netdev_ops = {
#endif #endif
}; };
static void gfar_ints_disable(struct gfar_private *priv)
{
int i;
for (i = 0; i < priv->num_grps; i++) {
struct gfar __iomem *regs = priv->gfargrp[i].regs;
/* Clear IEVENT */
gfar_write(&regs->ievent, IEVENT_INIT_CLEAR);
/* Initialize IMASK */
gfar_write(&regs->imask, IMASK_INIT_CLEAR);
}
}
static void gfar_ints_enable(struct gfar_private *priv)
{
int i;
for (i = 0; i < priv->num_grps; i++) {
struct gfar __iomem *regs = priv->gfargrp[i].regs;
/* Unmask the interrupts we look for */
gfar_write(&regs->imask, IMASK_DEFAULT);
}
}
void lock_rx_qs(struct gfar_private *priv) void lock_rx_qs(struct gfar_private *priv)
{ {
int i; int i;
...@@ -511,7 +501,43 @@ void unlock_tx_qs(struct gfar_private *priv) ...@@ -511,7 +501,43 @@ void unlock_tx_qs(struct gfar_private *priv)
spin_unlock(&priv->tx_queue[i]->txlock); spin_unlock(&priv->tx_queue[i]->txlock);
} }
static void free_tx_pointers(struct gfar_private *priv) static int gfar_alloc_tx_queues(struct gfar_private *priv)
{
int i;
for (i = 0; i < priv->num_tx_queues; i++) {
priv->tx_queue[i] = kzalloc(sizeof(struct gfar_priv_tx_q),
GFP_KERNEL);
if (!priv->tx_queue[i])
return -ENOMEM;
priv->tx_queue[i]->tx_skbuff = NULL;
priv->tx_queue[i]->qindex = i;
priv->tx_queue[i]->dev = priv->ndev;
spin_lock_init(&(priv->tx_queue[i]->txlock));
}
return 0;
}
static int gfar_alloc_rx_queues(struct gfar_private *priv)
{
int i;
for (i = 0; i < priv->num_rx_queues; i++) {
priv->rx_queue[i] = kzalloc(sizeof(struct gfar_priv_rx_q),
GFP_KERNEL);
if (!priv->rx_queue[i])
return -ENOMEM;
priv->rx_queue[i]->rx_skbuff = NULL;
priv->rx_queue[i]->qindex = i;
priv->rx_queue[i]->dev = priv->ndev;
spin_lock_init(&(priv->rx_queue[i]->rxlock));
}
return 0;
}
static void gfar_free_tx_queues(struct gfar_private *priv)
{ {
int i; int i;
...@@ -519,7 +545,7 @@ static void free_tx_pointers(struct gfar_private *priv) ...@@ -519,7 +545,7 @@ static void free_tx_pointers(struct gfar_private *priv)
kfree(priv->tx_queue[i]); kfree(priv->tx_queue[i]);
} }
static void free_rx_pointers(struct gfar_private *priv) static void gfar_free_rx_queues(struct gfar_private *priv)
{ {
int i; int i;
...@@ -608,6 +634,30 @@ static int gfar_parse_group(struct device_node *np, ...@@ -608,6 +634,30 @@ static int gfar_parse_group(struct device_node *np,
grp->rx_bit_map = 0xFF; grp->rx_bit_map = 0xFF;
grp->tx_bit_map = 0xFF; grp->tx_bit_map = 0xFF;
} }
/* bit_map's MSB is q0 (from q0 to q7) but, for_each_set_bit parses
* right to left, so we need to revert the 8 bits to get the q index
*/
grp->rx_bit_map = bitrev8(grp->rx_bit_map);
grp->tx_bit_map = bitrev8(grp->tx_bit_map);
/* Calculate RSTAT, TSTAT, RQUEUE and TQUEUE values,
* also assign queues to groups
*/
for_each_set_bit(i, &grp->rx_bit_map, priv->num_rx_queues) {
grp->num_rx_queues++;
grp->rstat |= (RSTAT_CLEAR_RHALT >> i);
priv->rqueue |= ((RQUEUE_EN0 | RQUEUE_EX0) >> i);
priv->rx_queue[i]->grp = grp;
}
for_each_set_bit(i, &grp->tx_bit_map, priv->num_tx_queues) {
grp->num_tx_queues++;
grp->tstat |= (TSTAT_CLEAR_THALT >> i);
priv->tqueue |= (TQUEUE_EN0 >> i);
priv->tx_queue[i]->grp = grp;
}
priv->num_grps++; priv->num_grps++;
return 0; return 0;
...@@ -664,7 +714,14 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) ...@@ -664,7 +714,14 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
priv->num_tx_queues = num_tx_qs; priv->num_tx_queues = num_tx_qs;
netif_set_real_num_rx_queues(dev, num_rx_qs); netif_set_real_num_rx_queues(dev, num_rx_qs);
priv->num_rx_queues = num_rx_qs; priv->num_rx_queues = num_rx_qs;
priv->num_grps = 0x0;
err = gfar_alloc_tx_queues(priv);
if (err)
goto tx_alloc_failed;
err = gfar_alloc_rx_queues(priv);
if (err)
goto rx_alloc_failed;
/* Init Rx queue filer rule set linked list */ /* Init Rx queue filer rule set linked list */
INIT_LIST_HEAD(&priv->rx_list.list); INIT_LIST_HEAD(&priv->rx_list.list);
...@@ -691,38 +748,6 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) ...@@ -691,38 +748,6 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
goto err_grp_init; goto err_grp_init;
} }
for (i = 0; i < priv->num_tx_queues; i++)
priv->tx_queue[i] = NULL;
for (i = 0; i < priv->num_rx_queues; i++)
priv->rx_queue[i] = NULL;
for (i = 0; i < priv->num_tx_queues; i++) {
priv->tx_queue[i] = kzalloc(sizeof(struct gfar_priv_tx_q),
GFP_KERNEL);
if (!priv->tx_queue[i]) {
err = -ENOMEM;
goto tx_alloc_failed;
}
priv->tx_queue[i]->tx_skbuff = NULL;
priv->tx_queue[i]->qindex = i;
priv->tx_queue[i]->dev = dev;
spin_lock_init(&(priv->tx_queue[i]->txlock));
}
for (i = 0; i < priv->num_rx_queues; i++) {
priv->rx_queue[i] = kzalloc(sizeof(struct gfar_priv_rx_q),
GFP_KERNEL);
if (!priv->rx_queue[i]) {
err = -ENOMEM;
goto rx_alloc_failed;
}
priv->rx_queue[i]->rx_skbuff = NULL;
priv->rx_queue[i]->qindex = i;
priv->rx_queue[i]->dev = dev;
spin_lock_init(&(priv->rx_queue[i]->rxlock));
}
stash = of_get_property(np, "bd-stash", NULL); stash = of_get_property(np, "bd-stash", NULL);
if (stash) { if (stash) {
...@@ -749,17 +774,16 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) ...@@ -749,17 +774,16 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
memcpy(dev->dev_addr, mac_addr, ETH_ALEN); memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
if (model && !strcasecmp(model, "TSEC")) if (model && !strcasecmp(model, "TSEC"))
priv->device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT | priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_COALESCE |
FSL_GIANFAR_DEV_HAS_RMON | FSL_GIANFAR_DEV_HAS_RMON |
FSL_GIANFAR_DEV_HAS_MULTI_INTR; FSL_GIANFAR_DEV_HAS_MULTI_INTR;
if (model && !strcasecmp(model, "eTSEC")) if (model && !strcasecmp(model, "eTSEC"))
priv->device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT | priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_COALESCE |
FSL_GIANFAR_DEV_HAS_RMON | FSL_GIANFAR_DEV_HAS_RMON |
FSL_GIANFAR_DEV_HAS_MULTI_INTR | FSL_GIANFAR_DEV_HAS_MULTI_INTR |
FSL_GIANFAR_DEV_HAS_PADDING |
FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_CSUM |
FSL_GIANFAR_DEV_HAS_VLAN | FSL_GIANFAR_DEV_HAS_VLAN |
FSL_GIANFAR_DEV_HAS_MAGIC_PACKET | FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
...@@ -784,12 +808,12 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) ...@@ -784,12 +808,12 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
return 0; return 0;
rx_alloc_failed:
free_rx_pointers(priv);
tx_alloc_failed:
free_tx_pointers(priv);
err_grp_init: err_grp_init:
unmap_group_regs(priv); unmap_group_regs(priv);
rx_alloc_failed:
gfar_free_rx_queues(priv);
tx_alloc_failed:
gfar_free_tx_queues(priv);
free_gfar_dev(priv); free_gfar_dev(priv);
return err; return err;
} }
...@@ -875,19 +899,6 @@ static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -875,19 +899,6 @@ static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return phy_mii_ioctl(priv->phydev, rq, cmd); return phy_mii_ioctl(priv->phydev, rq, cmd);
} }
static unsigned int reverse_bitmap(unsigned int bit_map, unsigned int max_qs)
{
unsigned int new_bit_map = 0x0;
int mask = 0x1 << (max_qs - 1), i;
for (i = 0; i < max_qs; i++) {
if (bit_map & mask)
new_bit_map = new_bit_map + (1 << i);
mask = mask >> 0x1;
}
return new_bit_map;
}
static u32 cluster_entry_per_class(struct gfar_private *priv, u32 rqfar, static u32 cluster_entry_per_class(struct gfar_private *priv, u32 rqfar,
u32 class) u32 class)
{ {
...@@ -1005,43 +1016,10 @@ static void gfar_detect_errata(struct gfar_private *priv) ...@@ -1005,43 +1016,10 @@ static void gfar_detect_errata(struct gfar_private *priv)
priv->errata); priv->errata);
} }
/* Set up the ethernet device structure, private data, static void gfar_hw_init(struct gfar_private *priv)
* and anything else we need before we start
*/
static int gfar_probe(struct platform_device *ofdev)
{ {
u32 tempval; struct gfar __iomem *regs = priv->gfargrp[0].regs;
struct net_device *dev = NULL; u32 tempval, attrs;
struct gfar_private *priv = NULL;
struct gfar __iomem *regs = NULL;
int err = 0, i, grp_idx = 0;
u32 rstat = 0, tstat = 0, rqueue = 0, tqueue = 0;
u32 isrg = 0;
u32 __iomem *baddr;
err = gfar_of_init(ofdev, &dev);
if (err)
return err;
priv = netdev_priv(dev);
priv->ndev = dev;
priv->ofdev = ofdev;
priv->dev = &ofdev->dev;
SET_NETDEV_DEV(dev, &ofdev->dev);
spin_lock_init(&priv->bflock);
INIT_WORK(&priv->reset_task, gfar_reset_task);
platform_set_drvdata(ofdev, priv);
regs = priv->gfargrp[0].regs;
gfar_detect_errata(priv);
/* Stop the DMA engine now, in case it was running before
* (The firmware could have used it, and left it running).
*/
gfar_halt(dev);
/* Reset MAC layer */ /* Reset MAC layer */
gfar_write(&regs->maccfg1, MACCFG1_SOFT_RESET); gfar_write(&regs->maccfg1, MACCFG1_SOFT_RESET);
...@@ -1049,15 +1027,10 @@ static int gfar_probe(struct platform_device *ofdev) ...@@ -1049,15 +1027,10 @@ static int gfar_probe(struct platform_device *ofdev)
/* We need to delay at least 3 TX clocks */ /* We need to delay at least 3 TX clocks */
udelay(2); udelay(2);
tempval = 0;
if (!priv->pause_aneg_en && priv->tx_pause_en)
tempval |= MACCFG1_TX_FLOW;
if (!priv->pause_aneg_en && priv->rx_pause_en)
tempval |= MACCFG1_RX_FLOW;
/* the soft reset bit is not self-resetting, so we need to /* the soft reset bit is not self-resetting, so we need to
* clear it before resuming normal operation * clear it before resuming normal operation
*/ */
gfar_write(&regs->maccfg1, tempval); gfar_write(&regs->maccfg1, 0);
/* Initialize MACCFG2. */ /* Initialize MACCFG2. */
tempval = MACCFG2_INIT_SETTINGS; tempval = MACCFG2_INIT_SETTINGS;
...@@ -1068,36 +1041,38 @@ static int gfar_probe(struct platform_device *ofdev) ...@@ -1068,36 +1041,38 @@ static int gfar_probe(struct platform_device *ofdev)
/* Initialize ECNTRL */ /* Initialize ECNTRL */
gfar_write(&regs->ecntrl, ECNTRL_INIT_SETTINGS); gfar_write(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
/* Set the dev->base_addr to the gfar reg region */ /* Set the extraction length and index */
dev->base_addr = (unsigned long) regs; attrs = ATTRELI_EL(priv->rx_stash_size) |
ATTRELI_EI(priv->rx_stash_index);
/* Fill in the dev structure */ gfar_write(&regs->attreli, attrs);
dev->watchdog_timeo = TX_TIMEOUT;
dev->mtu = 1500;
dev->netdev_ops = &gfar_netdev_ops;
dev->ethtool_ops = &gfar_ethtool_ops;
/* Register for napi ...We are registering NAPI for each grp */ /* Start with defaults, and add stashing
if (priv->mode == SQ_SG_MODE) * depending on driver parameters
netif_napi_add(dev, &priv->gfargrp[0].napi, gfar_poll_sq, */
GFAR_DEV_WEIGHT); attrs = ATTR_INIT_SETTINGS;
else
for (i = 0; i < priv->num_grps; i++)
netif_napi_add(dev, &priv->gfargrp[i].napi, gfar_poll,
GFAR_DEV_WEIGHT);
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { if (priv->bd_stash_en)
dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | attrs |= ATTR_BDSTASH;
NETIF_F_RXCSUM;
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG |
NETIF_F_RXCSUM | NETIF_F_HIGHDMA;
}
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { if (priv->rx_stash_size != 0)
dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | attrs |= ATTR_BUFSTASH;
NETIF_F_HW_VLAN_CTAG_RX;
dev->features |= NETIF_F_HW_VLAN_CTAG_RX; gfar_write(&regs->attr, attrs);
}
/* FIFO configs */
gfar_write(&regs->fifo_tx_thr, DEFAULT_FIFO_TX_THR);
gfar_write(&regs->fifo_tx_starve, DEFAULT_FIFO_TX_STARVE);
gfar_write(&regs->fifo_tx_starve_shutoff, DEFAULT_FIFO_TX_STARVE_OFF);
/* Program the interrupt steering regs, only for MG devices */
if (priv->num_grps > 1)
gfar_write_isrg(priv);
}
static void __init gfar_init_addr_hash_table(struct gfar_private *priv)
{
struct gfar __iomem *regs = priv->gfargrp[0].regs;
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) { if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) {
priv->extended_hash = 1; priv->extended_hash = 1;
...@@ -1133,68 +1108,82 @@ static int gfar_probe(struct platform_device *ofdev) ...@@ -1133,68 +1108,82 @@ static int gfar_probe(struct platform_device *ofdev)
priv->hash_regs[6] = &regs->gaddr6; priv->hash_regs[6] = &regs->gaddr6;
priv->hash_regs[7] = &regs->gaddr7; priv->hash_regs[7] = &regs->gaddr7;
} }
}
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_PADDING) /* Set up the ethernet device structure, private data,
priv->padding = DEFAULT_PADDING; * and anything else we need before we start
else */
priv->padding = 0; static int gfar_probe(struct platform_device *ofdev)
{
struct net_device *dev = NULL;
struct gfar_private *priv = NULL;
int err = 0, i;
if (dev->features & NETIF_F_IP_CSUM || err = gfar_of_init(ofdev, &dev);
priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
dev->needed_headroom = GMAC_FCB_LEN;
/* Program the isrg regs only if number of grps > 1 */ if (err)
if (priv->num_grps > 1) { return err;
baddr = &regs->isrg0;
for (i = 0; i < priv->num_grps; i++) {
isrg |= (priv->gfargrp[i].rx_bit_map << ISRG_SHIFT_RX);
isrg |= (priv->gfargrp[i].tx_bit_map << ISRG_SHIFT_TX);
gfar_write(baddr, isrg);
baddr++;
isrg = 0x0;
}
}
/* Need to reverse the bit maps as bit_map's MSB is q0 priv = netdev_priv(dev);
* but, for_each_set_bit parses from right to left, which priv->ndev = dev;
* basically reverses the queue numbers priv->ofdev = ofdev;
priv->dev = &ofdev->dev;
SET_NETDEV_DEV(dev, &ofdev->dev);
spin_lock_init(&priv->bflock);
INIT_WORK(&priv->reset_task, gfar_reset_task);
platform_set_drvdata(ofdev, priv);
gfar_detect_errata(priv);
/* Stop the DMA engine now, in case it was running before
* (The firmware could have used it, and left it running).
*/ */
for (i = 0; i< priv->num_grps; i++) { gfar_halt(priv);
priv->gfargrp[i].tx_bit_map =
reverse_bitmap(priv->gfargrp[i].tx_bit_map, MAX_TX_QS); gfar_hw_init(priv);
priv->gfargrp[i].rx_bit_map =
reverse_bitmap(priv->gfargrp[i].rx_bit_map, MAX_RX_QS); /* Set the dev->base_addr to the gfar reg region */
dev->base_addr = (unsigned long) priv->gfargrp[0].regs;
/* Fill in the dev structure */
dev->watchdog_timeo = TX_TIMEOUT;
dev->mtu = 1500;
dev->netdev_ops = &gfar_netdev_ops;
dev->ethtool_ops = &gfar_ethtool_ops;
/* Register for napi ...We are registering NAPI for each grp */
if (priv->mode == SQ_SG_MODE)
netif_napi_add(dev, &priv->gfargrp[0].napi, gfar_poll_sq,
GFAR_DEV_WEIGHT);
else
for (i = 0; i < priv->num_grps; i++)
netif_napi_add(dev, &priv->gfargrp[i].napi, gfar_poll,
GFAR_DEV_WEIGHT);
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
NETIF_F_RXCSUM;
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG |
NETIF_F_RXCSUM | NETIF_F_HIGHDMA;
} }
/* Calculate RSTAT, TSTAT, RQUEUE and TQUEUE values, if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
* also assign queues to groups dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX |
*/ NETIF_F_HW_VLAN_CTAG_RX;
for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) { dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
priv->gfargrp[grp_idx].num_rx_queues = 0x0;
for_each_set_bit(i, &priv->gfargrp[grp_idx].rx_bit_map,
priv->num_rx_queues) {
priv->gfargrp[grp_idx].num_rx_queues++;
priv->rx_queue[i]->grp = &priv->gfargrp[grp_idx];
rstat = rstat | (RSTAT_CLEAR_RHALT >> i);
rqueue = rqueue | ((RQUEUE_EN0 | RQUEUE_EX0) >> i);
}
priv->gfargrp[grp_idx].num_tx_queues = 0x0;
for_each_set_bit(i, &priv->gfargrp[grp_idx].tx_bit_map,
priv->num_tx_queues) {
priv->gfargrp[grp_idx].num_tx_queues++;
priv->tx_queue[i]->grp = &priv->gfargrp[grp_idx];
tstat = tstat | (TSTAT_CLEAR_THALT >> i);
tqueue = tqueue | (TQUEUE_EN0 >> i);
}
priv->gfargrp[grp_idx].rstat = rstat;
priv->gfargrp[grp_idx].tstat = tstat;
rstat = tstat =0;
} }
gfar_write(&regs->rqueue, rqueue); gfar_init_addr_hash_table(priv);
gfar_write(&regs->tqueue, tqueue);
/* Insert receive time stamps into padding alignment bytes */
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
priv->padding = 8;
if (dev->features & NETIF_F_IP_CSUM ||
priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
dev->needed_headroom = GMAC_FCB_LEN;
priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE; priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
...@@ -1251,9 +1240,6 @@ static int gfar_probe(struct platform_device *ofdev) ...@@ -1251,9 +1240,6 @@ static int gfar_probe(struct platform_device *ofdev)
/* Initialize the filer table */ /* Initialize the filer table */
gfar_init_filer_table(priv); gfar_init_filer_table(priv);
/* Create all the sysfs files */
gfar_init_sysfs(dev);
/* Print out the device info */ /* Print out the device info */
netdev_info(dev, "mac: %pM\n", dev->dev_addr); netdev_info(dev, "mac: %pM\n", dev->dev_addr);
...@@ -1272,8 +1258,8 @@ static int gfar_probe(struct platform_device *ofdev) ...@@ -1272,8 +1258,8 @@ static int gfar_probe(struct platform_device *ofdev)
register_fail: register_fail:
unmap_group_regs(priv); unmap_group_regs(priv);
free_tx_pointers(priv); gfar_free_rx_queues(priv);
free_rx_pointers(priv); gfar_free_tx_queues(priv);
if (priv->phy_node) if (priv->phy_node)
of_node_put(priv->phy_node); of_node_put(priv->phy_node);
if (priv->tbi_node) if (priv->tbi_node)
...@@ -1293,6 +1279,8 @@ static int gfar_remove(struct platform_device *ofdev) ...@@ -1293,6 +1279,8 @@ static int gfar_remove(struct platform_device *ofdev)
unregister_netdev(priv->ndev); unregister_netdev(priv->ndev);
unmap_group_regs(priv); unmap_group_regs(priv);
gfar_free_rx_queues(priv);
gfar_free_tx_queues(priv);
free_gfar_dev(priv); free_gfar_dev(priv);
return 0; return 0;
...@@ -1320,7 +1308,7 @@ static int gfar_suspend(struct device *dev) ...@@ -1320,7 +1308,7 @@ static int gfar_suspend(struct device *dev)
lock_tx_qs(priv); lock_tx_qs(priv);
lock_rx_qs(priv); lock_rx_qs(priv);
gfar_halt_nodisable(ndev); gfar_halt_nodisable(priv);
/* Disable Tx, and Rx if wake-on-LAN is disabled. */ /* Disable Tx, and Rx if wake-on-LAN is disabled. */
tempval = gfar_read(&regs->maccfg1); tempval = gfar_read(&regs->maccfg1);
...@@ -1384,7 +1372,7 @@ static int gfar_resume(struct device *dev) ...@@ -1384,7 +1372,7 @@ static int gfar_resume(struct device *dev)
tempval &= ~MACCFG2_MPEN; tempval &= ~MACCFG2_MPEN;
gfar_write(&regs->maccfg2, tempval); gfar_write(&regs->maccfg2, tempval);
gfar_start(ndev); gfar_start(priv);
unlock_rx_qs(priv); unlock_rx_qs(priv);
unlock_tx_qs(priv); unlock_tx_qs(priv);
...@@ -1416,7 +1404,7 @@ static int gfar_restore(struct device *dev) ...@@ -1416,7 +1404,7 @@ static int gfar_restore(struct device *dev)
init_registers(ndev); init_registers(ndev);
gfar_set_mac_address(ndev); gfar_set_mac_address(ndev);
gfar_init_mac(ndev); gfar_init_mac(ndev);
gfar_start(ndev); gfar_start(priv);
priv->oldlink = 0; priv->oldlink = 0;
priv->oldspeed = 0; priv->oldspeed = 0;
...@@ -1577,19 +1565,10 @@ static void gfar_configure_serdes(struct net_device *dev) ...@@ -1577,19 +1565,10 @@ static void gfar_configure_serdes(struct net_device *dev)
static void init_registers(struct net_device *dev) static void init_registers(struct net_device *dev)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = NULL; struct gfar __iomem *regs = priv->gfargrp[0].regs;
int i;
for (i = 0; i < priv->num_grps; i++) {
regs = priv->gfargrp[i].regs;
/* Clear IEVENT */
gfar_write(&regs->ievent, IEVENT_INIT_CLEAR);
/* Initialize IMASK */ gfar_ints_disable(priv);
gfar_write(&regs->imask, IMASK_INIT_CLEAR);
}
regs = priv->gfargrp[0].regs;
/* Init hash registers to zero */ /* Init hash registers to zero */
gfar_write(&regs->igaddr0, 0); gfar_write(&regs->igaddr0, 0);
gfar_write(&regs->igaddr1, 0); gfar_write(&regs->igaddr1, 0);
...@@ -1648,23 +1627,13 @@ static int __gfar_is_rx_idle(struct gfar_private *priv) ...@@ -1648,23 +1627,13 @@ static int __gfar_is_rx_idle(struct gfar_private *priv)
} }
/* Halt the receive and transmit queues */ /* Halt the receive and transmit queues */
static void gfar_halt_nodisable(struct net_device *dev) static void gfar_halt_nodisable(struct gfar_private *priv)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar __iomem *regs = priv->gfargrp[0].regs;
struct gfar __iomem *regs = NULL;
u32 tempval; u32 tempval;
int i;
for (i = 0; i < priv->num_grps; i++) { gfar_ints_disable(priv);
regs = priv->gfargrp[i].regs;
/* Mask all interrupts */
gfar_write(&regs->imask, IMASK_INIT_CLEAR);
/* Clear all interrupts */
gfar_write(&regs->ievent, IEVENT_INIT_CLEAR);
}
regs = priv->gfargrp[0].regs;
/* Stop the DMA, and wait for it to stop */ /* Stop the DMA, and wait for it to stop */
tempval = gfar_read(&regs->dmactrl); tempval = gfar_read(&regs->dmactrl);
if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) != if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) !=
...@@ -1685,15 +1654,20 @@ static void gfar_halt_nodisable(struct net_device *dev) ...@@ -1685,15 +1654,20 @@ static void gfar_halt_nodisable(struct net_device *dev)
} }
/* Halt the receive and transmit queues */ /* Halt the receive and transmit queues */
void gfar_halt(struct net_device *dev) void gfar_halt(struct gfar_private *priv)
{ {
struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->gfargrp[0].regs; struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 tempval; u32 tempval;
gfar_halt_nodisable(dev); /* Dissable the Rx/Tx hw queues */
gfar_write(&regs->rqueue, 0);
gfar_write(&regs->tqueue, 0);
mdelay(10);
/* Disable Rx and Tx */ gfar_halt_nodisable(priv);
/* Disable Rx/Tx DMA */
tempval = gfar_read(&regs->maccfg1); tempval = gfar_read(&regs->maccfg1);
tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
gfar_write(&regs->maccfg1, tempval); gfar_write(&regs->maccfg1, tempval);
...@@ -1720,7 +1694,7 @@ void stop_gfar(struct net_device *dev) ...@@ -1720,7 +1694,7 @@ void stop_gfar(struct net_device *dev)
lock_tx_qs(priv); lock_tx_qs(priv);
lock_rx_qs(priv); lock_rx_qs(priv);
gfar_halt(dev); gfar_halt(priv);
unlock_rx_qs(priv); unlock_rx_qs(priv);
unlock_tx_qs(priv); unlock_tx_qs(priv);
...@@ -1825,17 +1799,15 @@ static void free_skb_resources(struct gfar_private *priv) ...@@ -1825,17 +1799,15 @@ static void free_skb_resources(struct gfar_private *priv)
priv->tx_queue[0]->tx_bd_dma_base); priv->tx_queue[0]->tx_bd_dma_base);
} }
void gfar_start(struct net_device *dev) void gfar_start(struct gfar_private *priv)
{ {
struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->gfargrp[0].regs; struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 tempval; u32 tempval;
int i = 0; int i = 0;
/* Enable Rx and Tx in MACCFG1 */ /* Enable Rx/Tx hw queues */
tempval = gfar_read(&regs->maccfg1); gfar_write(&regs->rqueue, priv->rqueue);
tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN); gfar_write(&regs->tqueue, priv->tqueue);
gfar_write(&regs->maccfg1, tempval);
/* Initialize DMACTRL to have WWR and WOP */ /* Initialize DMACTRL to have WWR and WOP */
tempval = gfar_read(&regs->dmactrl); tempval = gfar_read(&regs->dmactrl);
...@@ -1852,11 +1824,16 @@ void gfar_start(struct net_device *dev) ...@@ -1852,11 +1824,16 @@ void gfar_start(struct net_device *dev)
/* Clear THLT/RHLT, so that the DMA starts polling now */ /* Clear THLT/RHLT, so that the DMA starts polling now */
gfar_write(&regs->tstat, priv->gfargrp[i].tstat); gfar_write(&regs->tstat, priv->gfargrp[i].tstat);
gfar_write(&regs->rstat, priv->gfargrp[i].rstat); gfar_write(&regs->rstat, priv->gfargrp[i].rstat);
/* Unmask the interrupts we look for */
gfar_write(&regs->imask, IMASK_DEFAULT);
} }
dev->trans_start = jiffies; /* prevent tx timeout */ /* Enable Rx/Tx DMA */
tempval = gfar_read(&regs->maccfg1);
tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
gfar_write(&regs->maccfg1, tempval);
gfar_ints_enable(priv);
priv->ndev->trans_start = jiffies; /* prevent tx timeout */
} }
static void gfar_configure_coalescing(struct gfar_private *priv, static void gfar_configure_coalescing(struct gfar_private *priv,
...@@ -1960,15 +1937,10 @@ static int register_grp_irqs(struct gfar_priv_grp *grp) ...@@ -1960,15 +1937,10 @@ static int register_grp_irqs(struct gfar_priv_grp *grp)
int startup_gfar(struct net_device *ndev) int startup_gfar(struct net_device *ndev)
{ {
struct gfar_private *priv = netdev_priv(ndev); struct gfar_private *priv = netdev_priv(ndev);
struct gfar __iomem *regs = NULL;
int err, i, j; int err, i, j;
for (i = 0; i < priv->num_grps; i++) { gfar_ints_disable(priv);
regs= priv->gfargrp[i].regs;
gfar_write(&regs->imask, IMASK_INIT_CLEAR);
}
regs= priv->gfargrp[0].regs;
err = gfar_alloc_skb_resources(ndev); err = gfar_alloc_skb_resources(ndev);
if (err) if (err)
return err; return err;
...@@ -1985,7 +1957,7 @@ int startup_gfar(struct net_device *ndev) ...@@ -1985,7 +1957,7 @@ int startup_gfar(struct net_device *ndev)
} }
/* Start the controller */ /* Start the controller */
gfar_start(ndev); gfar_start(priv);
phy_start(priv->phydev); phy_start(priv->phydev);
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Maintainer: Kumar Gala * Maintainer: Kumar Gala
* Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com> * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
* *
* Copyright 2002-2009, 2011 Freescale Semiconductor, Inc. * Copyright 2002-2009, 2011-2013 Freescale Semiconductor, Inc.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
...@@ -880,7 +880,6 @@ struct gfar { ...@@ -880,7 +880,6 @@ struct gfar {
#define FSL_GIANFAR_DEV_HAS_CSUM 0x00000010 #define FSL_GIANFAR_DEV_HAS_CSUM 0x00000010
#define FSL_GIANFAR_DEV_HAS_VLAN 0x00000020 #define FSL_GIANFAR_DEV_HAS_VLAN 0x00000020
#define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH 0x00000040 #define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH 0x00000040
#define FSL_GIANFAR_DEV_HAS_PADDING 0x00000080
#define FSL_GIANFAR_DEV_HAS_MAGIC_PACKET 0x00000100 #define FSL_GIANFAR_DEV_HAS_MAGIC_PACKET 0x00000100
#define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200 #define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200
#define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400 #define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400
...@@ -892,8 +891,8 @@ struct gfar { ...@@ -892,8 +891,8 @@ struct gfar {
#define DEFAULT_MAPPING 0xFF #define DEFAULT_MAPPING 0xFF
#endif #endif
#define ISRG_SHIFT_TX 0x10 #define ISRG_RR0 0x80000000
#define ISRG_SHIFT_RX 0x18 #define ISRG_TR0 0x00800000
/* The same driver can operate in two modes */ /* The same driver can operate in two modes */
/* SQ_SG_MODE: Single Queue Single Group Mode /* SQ_SG_MODE: Single Queue Single Group Mode
...@@ -1113,6 +1112,9 @@ struct gfar_private { ...@@ -1113,6 +1112,9 @@ struct gfar_private {
unsigned int total_tx_ring_size; unsigned int total_tx_ring_size;
unsigned int total_rx_ring_size; unsigned int total_rx_ring_size;
u32 rqueue;
u32 tqueue;
/* RX per device parameters */ /* RX per device parameters */
unsigned int rx_stash_size; unsigned int rx_stash_size;
unsigned int rx_stash_index; unsigned int rx_stash_index;
...@@ -1127,11 +1129,6 @@ struct gfar_private { ...@@ -1127,11 +1129,6 @@ struct gfar_private {
u32 __iomem *hash_regs[16]; u32 __iomem *hash_regs[16];
int hash_width; int hash_width;
/* global parameters */
unsigned int fifo_threshold;
unsigned int fifo_starve;
unsigned int fifo_starve_off;
/*Filer table*/ /*Filer table*/
unsigned int ftp_rqfpr[MAX_FILER_IDX + 1]; unsigned int ftp_rqfpr[MAX_FILER_IDX + 1];
unsigned int ftp_rqfcr[MAX_FILER_IDX + 1]; unsigned int ftp_rqfcr[MAX_FILER_IDX + 1];
...@@ -1176,6 +1173,31 @@ static inline void gfar_read_filer(struct gfar_private *priv, ...@@ -1176,6 +1173,31 @@ static inline void gfar_read_filer(struct gfar_private *priv,
*fpr = gfar_read(&regs->rqfpr); *fpr = gfar_read(&regs->rqfpr);
} }
static inline void gfar_write_isrg(struct gfar_private *priv)
{
struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 __iomem *baddr = &regs->isrg0;
u32 isrg = 0;
int grp_idx, i;
for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) {
struct gfar_priv_grp *grp = &priv->gfargrp[grp_idx];
for_each_set_bit(i, &grp->rx_bit_map, priv->num_rx_queues) {
isrg |= (ISRG_RR0 >> i);
}
for_each_set_bit(i, &grp->tx_bit_map, priv->num_tx_queues) {
isrg |= (ISRG_TR0 >> i);
}
gfar_write(baddr, isrg);
baddr++;
isrg = 0;
}
}
void lock_rx_qs(struct gfar_private *priv); void lock_rx_qs(struct gfar_private *priv);
void lock_tx_qs(struct gfar_private *priv); void lock_tx_qs(struct gfar_private *priv);
void unlock_rx_qs(struct gfar_private *priv); void unlock_rx_qs(struct gfar_private *priv);
...@@ -1183,11 +1205,11 @@ void unlock_tx_qs(struct gfar_private *priv); ...@@ -1183,11 +1205,11 @@ void unlock_tx_qs(struct gfar_private *priv);
irqreturn_t gfar_receive(int irq, void *dev_id); irqreturn_t gfar_receive(int irq, void *dev_id);
int startup_gfar(struct net_device *dev); int startup_gfar(struct net_device *dev);
void stop_gfar(struct net_device *dev); void stop_gfar(struct net_device *dev);
void gfar_halt(struct net_device *dev); void gfar_halt(struct gfar_private *priv);
void gfar_start(struct gfar_private *priv);
void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, int enable, void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, int enable,
u32 regnum, u32 read); u32 regnum, u32 read);
void gfar_configure_coalescing_all(struct gfar_private *priv); void gfar_configure_coalescing_all(struct gfar_private *priv);
void gfar_init_sysfs(struct net_device *dev);
int gfar_set_features(struct net_device *dev, netdev_features_t features); int gfar_set_features(struct net_device *dev, netdev_features_t features);
void gfar_check_rx_parser_mode(struct gfar_private *priv); void gfar_check_rx_parser_mode(struct gfar_private *priv);
void gfar_vlan_mode(struct net_device *dev, netdev_features_t features); void gfar_vlan_mode(struct net_device *dev, netdev_features_t features);
......
...@@ -44,10 +44,6 @@ ...@@ -44,10 +44,6 @@
#include "gianfar.h" #include "gianfar.h"
extern void gfar_start(struct net_device *dev);
extern int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue,
int rx_work_limit);
#define GFAR_MAX_COAL_USECS 0xffff #define GFAR_MAX_COAL_USECS 0xffff
#define GFAR_MAX_COAL_FRAMES 0xff #define GFAR_MAX_COAL_FRAMES 0xff
static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
...@@ -467,15 +463,13 @@ static void gfar_gringparam(struct net_device *dev, ...@@ -467,15 +463,13 @@ static void gfar_gringparam(struct net_device *dev,
} }
/* Change the current ring parameters, stopping the controller if /* Change the current ring parameters, stopping the controller if
* necessary so that we don't mess things up while we're in * necessary so that we don't mess things up while we're in motion.
* motion. We wait for the ring to be clean before reallocating
* the rings.
*/ */
static int gfar_sringparam(struct net_device *dev, static int gfar_sringparam(struct net_device *dev,
struct ethtool_ringparam *rvals) struct ethtool_ringparam *rvals)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
int err = 0, i = 0; int err = 0, i;
if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE) if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE)
return -EINVAL; return -EINVAL;
...@@ -493,38 +487,15 @@ static int gfar_sringparam(struct net_device *dev, ...@@ -493,38 +487,15 @@ static int gfar_sringparam(struct net_device *dev,
return -EINVAL; return -EINVAL;
} }
if (dev->flags & IFF_UP)
if (dev->flags & IFF_UP) {
unsigned long flags;
/* Halt TX and RX, and process the frames which
* have already been received
*/
local_irq_save(flags);
lock_tx_qs(priv);
lock_rx_qs(priv);
gfar_halt(dev);
unlock_rx_qs(priv);
unlock_tx_qs(priv);
local_irq_restore(flags);
for (i = 0; i < priv->num_rx_queues; i++)
gfar_clean_rx_ring(priv->rx_queue[i],
priv->rx_queue[i]->rx_ring_size);
/* Now we take down the rings to rebuild them */
stop_gfar(dev); stop_gfar(dev);
}
/* Change the size */ /* Change the sizes */
for (i = 0; i < priv->num_rx_queues; i++) { for (i = 0; i < priv->num_rx_queues; i++)
priv->rx_queue[i]->rx_ring_size = rvals->rx_pending; priv->rx_queue[i]->rx_ring_size = rvals->rx_pending;
for (i = 0; i < priv->num_tx_queues; i++)
priv->tx_queue[i]->tx_ring_size = rvals->tx_pending; priv->tx_queue[i]->tx_ring_size = rvals->tx_pending;
priv->tx_queue[i]->num_txbdfree =
priv->tx_queue[i]->tx_ring_size;
}
/* Rebuild the rings with the new size */ /* Rebuild the rings with the new size */
if (dev->flags & IFF_UP) { if (dev->flags & IFF_UP) {
...@@ -608,10 +579,8 @@ static int gfar_spauseparam(struct net_device *dev, ...@@ -608,10 +579,8 @@ static int gfar_spauseparam(struct net_device *dev,
int gfar_set_features(struct net_device *dev, netdev_features_t features) int gfar_set_features(struct net_device *dev, netdev_features_t features)
{ {
struct gfar_private *priv = netdev_priv(dev);
unsigned long flags;
int err = 0, i = 0;
netdev_features_t changed = dev->features ^ features; netdev_features_t changed = dev->features ^ features;
int err = 0;
if (changed & (NETIF_F_HW_VLAN_CTAG_TX|NETIF_F_HW_VLAN_CTAG_RX)) if (changed & (NETIF_F_HW_VLAN_CTAG_TX|NETIF_F_HW_VLAN_CTAG_RX))
gfar_vlan_mode(dev, features); gfar_vlan_mode(dev, features);
...@@ -620,23 +589,6 @@ int gfar_set_features(struct net_device *dev, netdev_features_t features) ...@@ -620,23 +589,6 @@ int gfar_set_features(struct net_device *dev, netdev_features_t features)
return 0; return 0;
if (dev->flags & IFF_UP) { if (dev->flags & IFF_UP) {
/* Halt TX and RX, and process the frames which
* have already been received
*/
local_irq_save(flags);
lock_tx_qs(priv);
lock_rx_qs(priv);
gfar_halt(dev);
unlock_tx_qs(priv);
unlock_rx_qs(priv);
local_irq_restore(flags);
for (i = 0; i < priv->num_rx_queues; i++)
gfar_clean_rx_ring(priv->rx_queue[i],
priv->rx_queue[i]->rx_ring_size);
/* Now we take down the rings to rebuild them */ /* Now we take down the rings to rebuild them */
stop_gfar(dev); stop_gfar(dev);
......
/*
* drivers/net/ethernet/freescale/gianfar_sysfs.c
*
* Gianfar Ethernet Driver
* This driver is designed for the non-CPM ethernet controllers
* on the 85xx and 83xx family of integrated processors
* Based on 8260_io/fcc_enet.c
*
* Author: Andy Fleming
* Maintainer: Kumar Gala (galak@kernel.crashing.org)
* Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
*
* Copyright 2002-2009 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* Sysfs file creation and management
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/unistd.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <linux/module.h>
#include "gianfar.h"
static ssize_t gfar_show_bd_stash(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct gfar_private *priv = netdev_priv(to_net_dev(dev));
return sprintf(buf, "%s\n", priv->bd_stash_en ? "on" : "off");
}
static ssize_t gfar_set_bd_stash(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar __iomem *regs = priv->gfargrp[0].regs;
int new_setting = 0;
u32 temp;
unsigned long flags;
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING))
return count;
/* Find out the new setting */
if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
new_setting = 1;
else if (!strncmp("off", buf, count - 1) ||
!strncmp("0", buf, count - 1))
new_setting = 0;
else
return count;
local_irq_save(flags);
lock_rx_qs(priv);
/* Set the new stashing value */
priv->bd_stash_en = new_setting;
temp = gfar_read(&regs->attr);
if (new_setting)
temp |= ATTR_BDSTASH;
else
temp &= ~(ATTR_BDSTASH);
gfar_write(&regs->attr, temp);
unlock_rx_qs(priv);
local_irq_restore(flags);
return count;
}
static DEVICE_ATTR(bd_stash, 0644, gfar_show_bd_stash, gfar_set_bd_stash);
static ssize_t gfar_show_rx_stash_size(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct gfar_private *priv = netdev_priv(to_net_dev(dev));
return sprintf(buf, "%d\n", priv->rx_stash_size);
}
static ssize_t gfar_set_rx_stash_size(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar __iomem *regs = priv->gfargrp[0].regs;
unsigned int length = simple_strtoul(buf, NULL, 0);
u32 temp;
unsigned long flags;
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
return count;
local_irq_save(flags);
lock_rx_qs(priv);
if (length > priv->rx_buffer_size)
goto out;
if (length == priv->rx_stash_size)
goto out;
priv->rx_stash_size = length;
temp = gfar_read(&regs->attreli);
temp &= ~ATTRELI_EL_MASK;
temp |= ATTRELI_EL(length);
gfar_write(&regs->attreli, temp);
/* Turn stashing on/off as appropriate */
temp = gfar_read(&regs->attr);
if (length)
temp |= ATTR_BUFSTASH;
else
temp &= ~(ATTR_BUFSTASH);
gfar_write(&regs->attr, temp);
out:
unlock_rx_qs(priv);
local_irq_restore(flags);
return count;
}
static DEVICE_ATTR(rx_stash_size, 0644, gfar_show_rx_stash_size,
gfar_set_rx_stash_size);
/* Stashing will only be enabled when rx_stash_size != 0 */
static ssize_t gfar_show_rx_stash_index(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct gfar_private *priv = netdev_priv(to_net_dev(dev));
return sprintf(buf, "%d\n", priv->rx_stash_index);
}
static ssize_t gfar_set_rx_stash_index(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar __iomem *regs = priv->gfargrp[0].regs;
unsigned short index = simple_strtoul(buf, NULL, 0);
u32 temp;
unsigned long flags;
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
return count;
local_irq_save(flags);
lock_rx_qs(priv);
if (index > priv->rx_stash_size)
goto out;
if (index == priv->rx_stash_index)
goto out;
priv->rx_stash_index = index;
temp = gfar_read(&regs->attreli);
temp &= ~ATTRELI_EI_MASK;
temp |= ATTRELI_EI(index);
gfar_write(&regs->attreli, temp);
out:
unlock_rx_qs(priv);
local_irq_restore(flags);
return count;
}
static DEVICE_ATTR(rx_stash_index, 0644, gfar_show_rx_stash_index,
gfar_set_rx_stash_index);
static ssize_t gfar_show_fifo_threshold(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct gfar_private *priv = netdev_priv(to_net_dev(dev));
return sprintf(buf, "%d\n", priv->fifo_threshold);
}
static ssize_t gfar_set_fifo_threshold(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar __iomem *regs = priv->gfargrp[0].regs;
unsigned int length = simple_strtoul(buf, NULL, 0);
u32 temp;
unsigned long flags;
if (length > GFAR_MAX_FIFO_THRESHOLD)
return count;
local_irq_save(flags);
lock_tx_qs(priv);
priv->fifo_threshold = length;
temp = gfar_read(&regs->fifo_tx_thr);
temp &= ~FIFO_TX_THR_MASK;
temp |= length;
gfar_write(&regs->fifo_tx_thr, temp);
unlock_tx_qs(priv);
local_irq_restore(flags);
return count;
}
static DEVICE_ATTR(fifo_threshold, 0644, gfar_show_fifo_threshold,
gfar_set_fifo_threshold);
static ssize_t gfar_show_fifo_starve(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct gfar_private *priv = netdev_priv(to_net_dev(dev));
return sprintf(buf, "%d\n", priv->fifo_starve);
}
static ssize_t gfar_set_fifo_starve(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar __iomem *regs = priv->gfargrp[0].regs;
unsigned int num = simple_strtoul(buf, NULL, 0);
u32 temp;
unsigned long flags;
if (num > GFAR_MAX_FIFO_STARVE)
return count;
local_irq_save(flags);
lock_tx_qs(priv);
priv->fifo_starve = num;
temp = gfar_read(&regs->fifo_tx_starve);
temp &= ~FIFO_TX_STARVE_MASK;
temp |= num;
gfar_write(&regs->fifo_tx_starve, temp);
unlock_tx_qs(priv);
local_irq_restore(flags);
return count;
}
static DEVICE_ATTR(fifo_starve, 0644, gfar_show_fifo_starve,
gfar_set_fifo_starve);
static ssize_t gfar_show_fifo_starve_off(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct gfar_private *priv = netdev_priv(to_net_dev(dev));
return sprintf(buf, "%d\n", priv->fifo_starve_off);
}
static ssize_t gfar_set_fifo_starve_off(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar __iomem *regs = priv->gfargrp[0].regs;
unsigned int num = simple_strtoul(buf, NULL, 0);
u32 temp;
unsigned long flags;
if (num > GFAR_MAX_FIFO_STARVE_OFF)
return count;
local_irq_save(flags);
lock_tx_qs(priv);
priv->fifo_starve_off = num;
temp = gfar_read(&regs->fifo_tx_starve_shutoff);
temp &= ~FIFO_TX_STARVE_OFF_MASK;
temp |= num;
gfar_write(&regs->fifo_tx_starve_shutoff, temp);
unlock_tx_qs(priv);
local_irq_restore(flags);
return count;
}
static DEVICE_ATTR(fifo_starve_off, 0644, gfar_show_fifo_starve_off,
gfar_set_fifo_starve_off);
void gfar_init_sysfs(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
int rc;
/* Initialize the default values */
priv->fifo_threshold = DEFAULT_FIFO_TX_THR;
priv->fifo_starve = DEFAULT_FIFO_TX_STARVE;
priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF;
/* Create our sysfs files */
rc = device_create_file(&dev->dev, &dev_attr_bd_stash);
rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_size);
rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_index);
rc |= device_create_file(&dev->dev, &dev_attr_fifo_threshold);
rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve);
rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve_off);
if (rc)
dev_err(&dev->dev, "Error creating gianfar sysfs files\n");
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment