|
@@ -9,7 +9,7 @@
|
|
|
* Maintainer: Kumar Gala
|
|
|
* 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.
|
|
|
*
|
|
|
* 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);
|
|
|
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,
|
|
|
int amount_pull, struct napi_struct *napi);
|
|
|
-void gfar_halt(struct net_device *dev);
|
|
|
-static void gfar_halt_nodisable(struct net_device *dev);
|
|
|
-void gfar_start(struct net_device *dev);
|
|
|
+static void gfar_halt_nodisable(struct gfar_private *priv);
|
|
|
static void gfar_clear_exact_match(struct net_device *dev);
|
|
|
static void gfar_set_mac_for_addr(struct net_device *dev, int num,
|
|
|
const u8 *addr);
|
|
@@ -338,7 +336,6 @@ static void gfar_init_mac(struct net_device *ndev)
|
|
|
struct gfar __iomem *regs = priv->gfargrp[0].regs;
|
|
|
u32 rctrl = 0;
|
|
|
u32 tctrl = 0;
|
|
|
- u32 attrs = 0;
|
|
|
|
|
|
/* write the tx/rx base registers */
|
|
|
gfar_init_tx_rx_base(priv);
|
|
@@ -376,13 +373,6 @@ static void gfar_init_mac(struct net_device *ndev)
|
|
|
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 */
|
|
|
if (priv->hwts_rx_en) {
|
|
|
rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
|
|
@@ -409,29 +399,6 @@ static void gfar_init_mac(struct net_device *ndev)
|
|
|
}
|
|
|
|
|
|
gfar_write(®s->tctrl, tctrl);
|
|
|
-
|
|
|
- /* Set the extraction length and index */
|
|
|
- attrs = ATTRELI_EL(priv->rx_stash_size) |
|
|
|
- ATTRELI_EI(priv->rx_stash_index);
|
|
|
-
|
|
|
- gfar_write(®s->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(®s->attr, attrs);
|
|
|
-
|
|
|
- gfar_write(®s->fifo_tx_thr, priv->fifo_threshold);
|
|
|
- gfar_write(®s->fifo_tx_starve, priv->fifo_starve);
|
|
|
- gfar_write(®s->fifo_tx_starve_shutoff, priv->fifo_starve_off);
|
|
|
}
|
|
|
|
|
|
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 = {
|
|
|
#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(®s->ievent, IEVENT_INIT_CLEAR);
|
|
|
+
|
|
|
+ /* Initialize IMASK */
|
|
|
+ gfar_write(®s->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(®s->imask, IMASK_DEFAULT);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void lock_rx_qs(struct gfar_private *priv)
|
|
|
{
|
|
|
int i;
|
|
@@ -511,7 +501,43 @@ void unlock_tx_qs(struct gfar_private *priv)
|
|
|
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;
|
|
|
|
|
@@ -519,7 +545,7 @@ static void free_tx_pointers(struct gfar_private *priv)
|
|
|
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;
|
|
|
|
|
@@ -608,6 +634,30 @@ static int gfar_parse_group(struct device_node *np,
|
|
|
grp->rx_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++;
|
|
|
|
|
|
return 0;
|
|
@@ -664,7 +714,14 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
|
|
|
priv->num_tx_queues = num_tx_qs;
|
|
|
netif_set_real_num_rx_queues(dev, 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_LIST_HEAD(&priv->rx_list.list);
|
|
@@ -691,38 +748,6 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
|
|
|
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);
|
|
|
|
|
|
if (stash) {
|
|
@@ -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);
|
|
|
|
|
|
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_RMON |
|
|
|
FSL_GIANFAR_DEV_HAS_MULTI_INTR;
|
|
|
|
|
|
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_RMON |
|
|
|
FSL_GIANFAR_DEV_HAS_MULTI_INTR |
|
|
|
- FSL_GIANFAR_DEV_HAS_PADDING |
|
|
|
FSL_GIANFAR_DEV_HAS_CSUM |
|
|
|
FSL_GIANFAR_DEV_HAS_VLAN |
|
|
|
FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
|
|
@@ -784,12 +808,12 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
-rx_alloc_failed:
|
|
|
- free_rx_pointers(priv);
|
|
|
-tx_alloc_failed:
|
|
|
- free_tx_pointers(priv);
|
|
|
err_grp_init:
|
|
|
unmap_group_regs(priv);
|
|
|
+rx_alloc_failed:
|
|
|
+ gfar_free_rx_queues(priv);
|
|
|
+tx_alloc_failed:
|
|
|
+ gfar_free_tx_queues(priv);
|
|
|
free_gfar_dev(priv);
|
|
|
return err;
|
|
|
}
|
|
@@ -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);
|
|
|
}
|
|
|
|
|
|
-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,
|
|
|
u32 class)
|
|
|
{
|
|
@@ -1005,43 +1016,10 @@ static void gfar_detect_errata(struct gfar_private *priv)
|
|
|
priv->errata);
|
|
|
}
|
|
|
|
|
|
-/* Set up the ethernet device structure, private data,
|
|
|
- * and anything else we need before we start
|
|
|
- */
|
|
|
-static int gfar_probe(struct platform_device *ofdev)
|
|
|
+static void gfar_hw_init(struct gfar_private *priv)
|
|
|
{
|
|
|
- u32 tempval;
|
|
|
- struct net_device *dev = NULL;
|
|
|
- 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);
|
|
|
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
|
|
|
+ u32 tempval, attrs;
|
|
|
|
|
|
/* Reset MAC layer */
|
|
|
gfar_write(®s->maccfg1, MACCFG1_SOFT_RESET);
|
|
@@ -1049,15 +1027,10 @@ static int gfar_probe(struct platform_device *ofdev)
|
|
|
/* We need to delay at least 3 TX clocks */
|
|
|
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
|
|
|
* clear it before resuming normal operation
|
|
|
*/
|
|
|
- gfar_write(®s->maccfg1, tempval);
|
|
|
+ gfar_write(®s->maccfg1, 0);
|
|
|
|
|
|
/* Initialize MACCFG2. */
|
|
|
tempval = MACCFG2_INIT_SETTINGS;
|
|
@@ -1068,36 +1041,38 @@ static int gfar_probe(struct platform_device *ofdev)
|
|
|
/* Initialize ECNTRL */
|
|
|
gfar_write(®s->ecntrl, ECNTRL_INIT_SETTINGS);
|
|
|
|
|
|
- /* Set the dev->base_addr to the gfar reg region */
|
|
|
- dev->base_addr = (unsigned long) regs;
|
|
|
+ /* Set the extraction length and index */
|
|
|
+ attrs = ATTRELI_EL(priv->rx_stash_size) |
|
|
|
+ ATTRELI_EI(priv->rx_stash_index);
|
|
|
|
|
|
- /* 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;
|
|
|
+ gfar_write(®s->attreli, attrs);
|
|
|
|
|
|
- /* 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);
|
|
|
+ /* Start with defaults, and add stashing
|
|
|
+ * depending on driver parameters
|
|
|
+ */
|
|
|
+ attrs = ATTR_INIT_SETTINGS;
|
|
|
|
|
|
- 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;
|
|
|
- }
|
|
|
+ if (priv->bd_stash_en)
|
|
|
+ attrs |= ATTR_BDSTASH;
|
|
|
|
|
|
- if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
|
|
|
- dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX |
|
|
|
- NETIF_F_HW_VLAN_CTAG_RX;
|
|
|
- dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
|
|
|
- }
|
|
|
+ if (priv->rx_stash_size != 0)
|
|
|
+ attrs |= ATTR_BUFSTASH;
|
|
|
+
|
|
|
+ gfar_write(®s->attr, attrs);
|
|
|
+
|
|
|
+ /* FIFO configs */
|
|
|
+ gfar_write(®s->fifo_tx_thr, DEFAULT_FIFO_TX_THR);
|
|
|
+ gfar_write(®s->fifo_tx_starve, DEFAULT_FIFO_TX_STARVE);
|
|
|
+ gfar_write(®s->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) {
|
|
|
priv->extended_hash = 1;
|
|
@@ -1133,68 +1108,82 @@ static int gfar_probe(struct platform_device *ofdev)
|
|
|
priv->hash_regs[6] = ®s->gaddr6;
|
|
|
priv->hash_regs[7] = ®s->gaddr7;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- if (priv->device_flags & FSL_GIANFAR_DEV_HAS_PADDING)
|
|
|
- priv->padding = DEFAULT_PADDING;
|
|
|
- else
|
|
|
- priv->padding = 0;
|
|
|
+/* Set up the ethernet device structure, private data,
|
|
|
+ * and anything else we need before we start
|
|
|
+ */
|
|
|
+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 ||
|
|
|
- priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
|
|
|
- dev->needed_headroom = GMAC_FCB_LEN;
|
|
|
+ err = gfar_of_init(ofdev, &dev);
|
|
|
|
|
|
- /* Program the isrg regs only if number of grps > 1 */
|
|
|
- if (priv->num_grps > 1) {
|
|
|
- baddr = ®s->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;
|
|
|
- }
|
|
|
- }
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
|
|
|
- /* Need to reverse the bit maps as bit_map's MSB is q0
|
|
|
- * but, for_each_set_bit parses from right to left, which
|
|
|
- * basically reverses the queue numbers
|
|
|
+ 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);
|
|
|
+
|
|
|
+ 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++) {
|
|
|
- priv->gfargrp[i].tx_bit_map =
|
|
|
- reverse_bitmap(priv->gfargrp[i].tx_bit_map, MAX_TX_QS);
|
|
|
- priv->gfargrp[i].rx_bit_map =
|
|
|
- reverse_bitmap(priv->gfargrp[i].rx_bit_map, MAX_RX_QS);
|
|
|
+ gfar_halt(priv);
|
|
|
+
|
|
|
+ gfar_hw_init(priv);
|
|
|
+
|
|
|
+ /* 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,
|
|
|
- * also assign queues to groups
|
|
|
- */
|
|
|
- for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) {
|
|
|
- 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;
|
|
|
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
|
|
|
+ dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX |
|
|
|
+ NETIF_F_HW_VLAN_CTAG_RX;
|
|
|
+ dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
|
|
|
}
|
|
|
|
|
|
- gfar_write(®s->rqueue, rqueue);
|
|
|
- gfar_write(®s->tqueue, tqueue);
|
|
|
+ gfar_init_addr_hash_table(priv);
|
|
|
+
|
|
|
+ /* 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;
|
|
|
|
|
@@ -1251,9 +1240,6 @@ static int gfar_probe(struct platform_device *ofdev)
|
|
|
/* Initialize the filer table */
|
|
|
gfar_init_filer_table(priv);
|
|
|
|
|
|
- /* Create all the sysfs files */
|
|
|
- gfar_init_sysfs(dev);
|
|
|
-
|
|
|
/* Print out the device info */
|
|
|
netdev_info(dev, "mac: %pM\n", dev->dev_addr);
|
|
|
|
|
@@ -1272,8 +1258,8 @@ static int gfar_probe(struct platform_device *ofdev)
|
|
|
|
|
|
register_fail:
|
|
|
unmap_group_regs(priv);
|
|
|
- free_tx_pointers(priv);
|
|
|
- free_rx_pointers(priv);
|
|
|
+ gfar_free_rx_queues(priv);
|
|
|
+ gfar_free_tx_queues(priv);
|
|
|
if (priv->phy_node)
|
|
|
of_node_put(priv->phy_node);
|
|
|
if (priv->tbi_node)
|
|
@@ -1293,6 +1279,8 @@ static int gfar_remove(struct platform_device *ofdev)
|
|
|
|
|
|
unregister_netdev(priv->ndev);
|
|
|
unmap_group_regs(priv);
|
|
|
+ gfar_free_rx_queues(priv);
|
|
|
+ gfar_free_tx_queues(priv);
|
|
|
free_gfar_dev(priv);
|
|
|
|
|
|
return 0;
|
|
@@ -1320,7 +1308,7 @@ static int gfar_suspend(struct device *dev)
|
|
|
lock_tx_qs(priv);
|
|
|
lock_rx_qs(priv);
|
|
|
|
|
|
- gfar_halt_nodisable(ndev);
|
|
|
+ gfar_halt_nodisable(priv);
|
|
|
|
|
|
/* Disable Tx, and Rx if wake-on-LAN is disabled. */
|
|
|
tempval = gfar_read(®s->maccfg1);
|
|
@@ -1384,7 +1372,7 @@ static int gfar_resume(struct device *dev)
|
|
|
tempval &= ~MACCFG2_MPEN;
|
|
|
gfar_write(®s->maccfg2, tempval);
|
|
|
|
|
|
- gfar_start(ndev);
|
|
|
+ gfar_start(priv);
|
|
|
|
|
|
unlock_rx_qs(priv);
|
|
|
unlock_tx_qs(priv);
|
|
@@ -1416,7 +1404,7 @@ static int gfar_restore(struct device *dev)
|
|
|
init_registers(ndev);
|
|
|
gfar_set_mac_address(ndev);
|
|
|
gfar_init_mac(ndev);
|
|
|
- gfar_start(ndev);
|
|
|
+ gfar_start(priv);
|
|
|
|
|
|
priv->oldlink = 0;
|
|
|
priv->oldspeed = 0;
|
|
@@ -1577,19 +1565,10 @@ static void gfar_configure_serdes(struct net_device *dev)
|
|
|
static void init_registers(struct net_device *dev)
|
|
|
{
|
|
|
struct gfar_private *priv = netdev_priv(dev);
|
|
|
- struct gfar __iomem *regs = NULL;
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 0; i < priv->num_grps; i++) {
|
|
|
- regs = priv->gfargrp[i].regs;
|
|
|
- /* Clear IEVENT */
|
|
|
- gfar_write(®s->ievent, IEVENT_INIT_CLEAR);
|
|
|
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
|
|
|
|
|
|
- /* Initialize IMASK */
|
|
|
- gfar_write(®s->imask, IMASK_INIT_CLEAR);
|
|
|
- }
|
|
|
+ gfar_ints_disable(priv);
|
|
|
|
|
|
- regs = priv->gfargrp[0].regs;
|
|
|
/* Init hash registers to zero */
|
|
|
gfar_write(®s->igaddr0, 0);
|
|
|
gfar_write(®s->igaddr1, 0);
|
|
@@ -1648,23 +1627,13 @@ static int __gfar_is_rx_idle(struct gfar_private *priv)
|
|
|
}
|
|
|
|
|
|
/* 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 = NULL;
|
|
|
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
|
|
|
u32 tempval;
|
|
|
- int i;
|
|
|
|
|
|
- for (i = 0; i < priv->num_grps; i++) {
|
|
|
- regs = priv->gfargrp[i].regs;
|
|
|
- /* Mask all interrupts */
|
|
|
- gfar_write(®s->imask, IMASK_INIT_CLEAR);
|
|
|
-
|
|
|
- /* Clear all interrupts */
|
|
|
- gfar_write(®s->ievent, IEVENT_INIT_CLEAR);
|
|
|
- }
|
|
|
+ gfar_ints_disable(priv);
|
|
|
|
|
|
- regs = priv->gfargrp[0].regs;
|
|
|
/* Stop the DMA, and wait for it to stop */
|
|
|
tempval = gfar_read(®s->dmactrl);
|
|
|
if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) !=
|
|
@@ -1685,15 +1654,20 @@ static void gfar_halt_nodisable(struct net_device *dev)
|
|
|
}
|
|
|
|
|
|
/* 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;
|
|
|
u32 tempval;
|
|
|
|
|
|
- gfar_halt_nodisable(dev);
|
|
|
+ /* Dissable the Rx/Tx hw queues */
|
|
|
+ gfar_write(®s->rqueue, 0);
|
|
|
+ gfar_write(®s->tqueue, 0);
|
|
|
+
|
|
|
+ mdelay(10);
|
|
|
|
|
|
- /* Disable Rx and Tx */
|
|
|
+ gfar_halt_nodisable(priv);
|
|
|
+
|
|
|
+ /* Disable Rx/Tx DMA */
|
|
|
tempval = gfar_read(®s->maccfg1);
|
|
|
tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
|
|
|
gfar_write(®s->maccfg1, tempval);
|
|
@@ -1720,7 +1694,7 @@ void stop_gfar(struct net_device *dev)
|
|
|
lock_tx_qs(priv);
|
|
|
lock_rx_qs(priv);
|
|
|
|
|
|
- gfar_halt(dev);
|
|
|
+ gfar_halt(priv);
|
|
|
|
|
|
unlock_rx_qs(priv);
|
|
|
unlock_tx_qs(priv);
|
|
@@ -1825,17 +1799,15 @@ static void free_skb_resources(struct gfar_private *priv)
|
|
|
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;
|
|
|
u32 tempval;
|
|
|
int i = 0;
|
|
|
|
|
|
- /* Enable Rx and Tx in MACCFG1 */
|
|
|
- tempval = gfar_read(®s->maccfg1);
|
|
|
- tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
|
|
|
- gfar_write(®s->maccfg1, tempval);
|
|
|
+ /* Enable Rx/Tx hw queues */
|
|
|
+ gfar_write(®s->rqueue, priv->rqueue);
|
|
|
+ gfar_write(®s->tqueue, priv->tqueue);
|
|
|
|
|
|
/* Initialize DMACTRL to have WWR and WOP */
|
|
|
tempval = gfar_read(®s->dmactrl);
|
|
@@ -1852,11 +1824,16 @@ void gfar_start(struct net_device *dev)
|
|
|
/* Clear THLT/RHLT, so that the DMA starts polling now */
|
|
|
gfar_write(®s->tstat, priv->gfargrp[i].tstat);
|
|
|
gfar_write(®s->rstat, priv->gfargrp[i].rstat);
|
|
|
- /* Unmask the interrupts we look for */
|
|
|
- gfar_write(®s->imask, IMASK_DEFAULT);
|
|
|
}
|
|
|
|
|
|
- dev->trans_start = jiffies; /* prevent tx timeout */
|
|
|
+ /* Enable Rx/Tx DMA */
|
|
|
+ tempval = gfar_read(®s->maccfg1);
|
|
|
+ tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
|
|
|
+ gfar_write(®s->maccfg1, tempval);
|
|
|
+
|
|
|
+ gfar_ints_enable(priv);
|
|
|
+
|
|
|
+ priv->ndev->trans_start = jiffies; /* prevent tx timeout */
|
|
|
}
|
|
|
|
|
|
static void gfar_configure_coalescing(struct gfar_private *priv,
|
|
@@ -1960,15 +1937,10 @@ err_irq_fail:
|
|
|
int startup_gfar(struct net_device *ndev)
|
|
|
{
|
|
|
struct gfar_private *priv = netdev_priv(ndev);
|
|
|
- struct gfar __iomem *regs = NULL;
|
|
|
int err, i, j;
|
|
|
|
|
|
- for (i = 0; i < priv->num_grps; i++) {
|
|
|
- regs= priv->gfargrp[i].regs;
|
|
|
- gfar_write(®s->imask, IMASK_INIT_CLEAR);
|
|
|
- }
|
|
|
+ gfar_ints_disable(priv);
|
|
|
|
|
|
- regs= priv->gfargrp[0].regs;
|
|
|
err = gfar_alloc_skb_resources(ndev);
|
|
|
if (err)
|
|
|
return err;
|
|
@@ -1985,7 +1957,7 @@ int startup_gfar(struct net_device *ndev)
|
|
|
}
|
|
|
|
|
|
/* Start the controller */
|
|
|
- gfar_start(ndev);
|
|
|
+ gfar_start(priv);
|
|
|
|
|
|
phy_start(priv->phydev);
|
|
|
|