Commit 46ceb60c authored by Sandeep Gopalpet's avatar Sandeep Gopalpet Committed by David S. Miller

gianfar: Add Multiple group Support

This patch introduces multiple group support for etsec2.0
devices.

Multiple group support is provided by mapping the set of enabled
queues to different groups and then programming the per group
regsiters imask, ievent, rstat, tstat.

The queues corresponding to a group are indicated by programming
isrg (interrupt steering) registers.
Signed-off-by: default avatarSandeep Gopalpet <Sandeep.Kumar@freescale.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2e0246c7
This diff is collapsed.
...@@ -79,6 +79,9 @@ extern const char gfar_driver_version[]; ...@@ -79,6 +79,9 @@ extern const char gfar_driver_version[];
#define MAX_TX_QS 0x8 #define MAX_TX_QS 0x8
#define MAX_RX_QS 0x8 #define MAX_RX_QS 0x8
/* MAXIMUM NUMBER OF GROUPS SUPPORTED */
#define MAXGROUPS 0x2
/* These need to be powers of 2 for this driver */ /* These need to be powers of 2 for this driver */
#define DEFAULT_TX_RING_SIZE 256 #define DEFAULT_TX_RING_SIZE 256
#define DEFAULT_RX_RING_SIZE 256 #define DEFAULT_RX_RING_SIZE 256
...@@ -795,7 +798,24 @@ struct gfar { ...@@ -795,7 +798,24 @@ struct gfar {
#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
#if (MAXGROUPS == 2)
#define DEFAULT_MAPPING 0xAA
#else
#define DEFAULT_MAPPING 0xFF #define DEFAULT_MAPPING 0xFF
#endif
#define ISRG_SHIFT_TX 0x10
#define ISRG_SHIFT_RX 0x18
/* The same driver can operate in two modes */
/* SQ_SG_MODE: Single Queue Single Group Mode
* (Backward compatible mode)
* MQ_MG_MODE: Multi Queue Multi Group mode
*/
enum {
SQ_SG_MODE = 0,
MQ_MG_MODE
};
/** /**
* struct gfar_priv_tx_q - per tx queue structure * struct gfar_priv_tx_q - per tx queue structure
...@@ -825,6 +845,7 @@ struct gfar_priv_tx_q { ...@@ -825,6 +845,7 @@ struct gfar_priv_tx_q {
struct txbd8 *cur_tx; struct txbd8 *cur_tx;
struct txbd8 *dirty_tx; struct txbd8 *dirty_tx;
struct net_device *dev; struct net_device *dev;
struct gfar_priv_grp *grp;
u16 skb_curtx; u16 skb_curtx;
u16 skb_dirtytx; u16 skb_dirtytx;
u16 qindex; u16 qindex;
...@@ -858,6 +879,7 @@ struct gfar_priv_rx_q { ...@@ -858,6 +879,7 @@ struct gfar_priv_rx_q {
struct rxbd8 *rx_bd_base; struct rxbd8 *rx_bd_base;
struct rxbd8 *cur_rx; struct rxbd8 *cur_rx;
struct net_device *dev; struct net_device *dev;
struct gfar_priv_grp *grp;
u16 skb_currx; u16 skb_currx;
u16 qindex; u16 qindex;
unsigned int rx_ring_size; unsigned int rx_ring_size;
...@@ -885,6 +907,7 @@ struct gfar_priv_grp { ...@@ -885,6 +907,7 @@ struct gfar_priv_grp {
struct napi_struct napi; struct napi_struct napi;
struct gfar_private *priv; struct gfar_private *priv;
struct gfar __iomem *regs; struct gfar __iomem *regs;
unsigned int grp_id;
unsigned int rx_bit_map; unsigned int rx_bit_map;
unsigned int tx_bit_map; unsigned int tx_bit_map;
unsigned int num_tx_queues; unsigned int num_tx_queues;
...@@ -916,6 +939,8 @@ struct gfar_private { ...@@ -916,6 +939,8 @@ struct gfar_private {
/* Indicates how many tx, rx queues are enabled */ /* Indicates how many tx, rx queues are enabled */
unsigned int num_tx_queues; unsigned int num_tx_queues;
unsigned int num_rx_queues; unsigned int num_rx_queues;
unsigned int num_grps;
unsigned int mode;
/* The total tx and rx ring size for the enabled queues */ /* The total tx and rx ring size for the enabled queues */
unsigned int total_tx_ring_size; unsigned int total_tx_ring_size;
...@@ -925,7 +950,7 @@ struct gfar_private { ...@@ -925,7 +950,7 @@ struct gfar_private {
struct net_device *ndev; struct net_device *ndev;
struct of_device *ofdev; struct of_device *ofdev;
struct gfar_priv_grp gfargrp; struct gfar_priv_grp gfargrp[MAXGROUPS];
struct gfar_priv_tx_q *tx_queue[MAX_TX_QS]; struct gfar_priv_tx_q *tx_queue[MAX_TX_QS];
struct gfar_priv_rx_q *rx_queue[MAX_RX_QS]; struct gfar_priv_rx_q *rx_queue[MAX_RX_QS];
...@@ -999,6 +1024,8 @@ extern void stop_gfar(struct net_device *dev); ...@@ -999,6 +1024,8 @@ extern void stop_gfar(struct net_device *dev);
extern void gfar_halt(struct net_device *dev); extern void gfar_halt(struct net_device *dev);
extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
int enable, u32 regnum, u32 read); int enable, u32 regnum, u32 read);
extern void gfar_configure_coalescing(struct gfar_private *priv,
unsigned int tx_mask, unsigned int rx_mask);
void gfar_init_sysfs(struct net_device *dev); void gfar_init_sysfs(struct net_device *dev);
extern const struct ethtool_ops gfar_ethtool_ops; extern const struct ethtool_ops gfar_ethtool_ops;
......
...@@ -137,7 +137,7 @@ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, ...@@ -137,7 +137,7 @@ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
{ {
int i; int i;
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar __iomem *regs = priv->gfargrp[0].regs;
u64 *extra = (u64 *) & priv->extra_stats; u64 *extra = (u64 *) & priv->extra_stats;
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
...@@ -226,7 +226,7 @@ static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, voi ...@@ -226,7 +226,7 @@ static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, voi
{ {
int i; int i;
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
u32 __iomem *theregs = (u32 __iomem *) priv->gfargrp.regs; u32 __iomem *theregs = (u32 __iomem *) priv->gfargrp[0].regs;
u32 *buf = (u32 *) regbuf; u32 *buf = (u32 *) regbuf;
for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++) for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++)
...@@ -352,22 +352,23 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals ...@@ -352,22 +352,23 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->gfargrp.regs; int i = 0;
struct gfar_priv_tx_q *tx_queue = NULL;
struct gfar_priv_rx_q *rx_queue = NULL;
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
return -EOPNOTSUPP; return -EOPNOTSUPP;
tx_queue = priv->tx_queue[0];
rx_queue = priv->rx_queue[0];
/* Set up rx coalescing */ /* Set up rx coalescing */
/* As of now, we will enable/disable coalescing for all
* queues together in case of eTSEC2, this will be modified
* along with the ethtool interface */
if ((cvals->rx_coalesce_usecs == 0) || if ((cvals->rx_coalesce_usecs == 0) ||
(cvals->rx_max_coalesced_frames == 0)) (cvals->rx_max_coalesced_frames == 0)) {
rx_queue->rxcoalescing = 0; for (i = 0; i < priv->num_rx_queues; i++)
else priv->rx_queue[i]->rxcoalescing = 0;
rx_queue->rxcoalescing = 1; } else {
for (i = 0; i < priv->num_rx_queues; i++)
priv->rx_queue[i]->rxcoalescing = 1;
}
if (NULL == priv->phydev) if (NULL == priv->phydev)
return -ENODEV; return -ENODEV;
...@@ -385,15 +386,21 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals ...@@ -385,15 +386,21 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
return -EINVAL; return -EINVAL;
} }
rx_queue->rxic = mk_ic_value(cvals->rx_max_coalesced_frames, for (i = 0; i < priv->num_rx_queues; i++) {
priv->rx_queue[i]->rxic = mk_ic_value(
cvals->rx_max_coalesced_frames,
gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs)); gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs));
}
/* Set up tx coalescing */ /* Set up tx coalescing */
if ((cvals->tx_coalesce_usecs == 0) || if ((cvals->tx_coalesce_usecs == 0) ||
(cvals->tx_max_coalesced_frames == 0)) (cvals->tx_max_coalesced_frames == 0)) {
tx_queue->txcoalescing = 0; for (i = 0; i < priv->num_tx_queues; i++)
else priv->tx_queue[i]->txcoalescing = 0;
tx_queue->txcoalescing = 1; } else {
for (i = 0; i < priv->num_tx_queues; i++)
priv->tx_queue[i]->txcoalescing = 1;
}
/* Check the bounds of the values */ /* Check the bounds of the values */
if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) { if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
...@@ -408,16 +415,13 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals ...@@ -408,16 +415,13 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
return -EINVAL; return -EINVAL;
} }
tx_queue->txic = mk_ic_value(cvals->tx_max_coalesced_frames, for (i = 0; i < priv->num_tx_queues; i++) {
priv->tx_queue[i]->txic = mk_ic_value(
cvals->tx_max_coalesced_frames,
gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs)); gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs));
}
gfar_write(&regs->rxic, 0); gfar_configure_coalescing(priv, 0xFF, 0xFF);
if (rx_queue->rxcoalescing)
gfar_write(&regs->rxic, rx_queue->rxic);
gfar_write(&regs->txic, 0);
if (tx_queue->txcoalescing)
gfar_write(&regs->txic, tx_queue->txic);
return 0; return 0;
} }
......
...@@ -50,7 +50,7 @@ static ssize_t gfar_set_bd_stash(struct device *dev, ...@@ -50,7 +50,7 @@ static ssize_t gfar_set_bd_stash(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar __iomem *regs = priv->gfargrp[0].regs;
int new_setting = 0; int new_setting = 0;
u32 temp; u32 temp;
unsigned long flags; unsigned long flags;
...@@ -105,7 +105,7 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev, ...@@ -105,7 +105,7 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar __iomem *regs = priv->gfargrp[0].regs;
unsigned int length = simple_strtoul(buf, NULL, 0); unsigned int length = simple_strtoul(buf, NULL, 0);
u32 temp; u32 temp;
unsigned long flags; unsigned long flags;
...@@ -164,7 +164,7 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev, ...@@ -164,7 +164,7 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar __iomem *regs = priv->gfargrp[0].regs;
unsigned short index = simple_strtoul(buf, NULL, 0); unsigned short index = simple_strtoul(buf, NULL, 0);
u32 temp; u32 temp;
unsigned long flags; unsigned long flags;
...@@ -212,7 +212,7 @@ static ssize_t gfar_set_fifo_threshold(struct device *dev, ...@@ -212,7 +212,7 @@ static ssize_t gfar_set_fifo_threshold(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar __iomem *regs = priv->gfargrp[0].regs;
unsigned int length = simple_strtoul(buf, NULL, 0); unsigned int length = simple_strtoul(buf, NULL, 0);
u32 temp; u32 temp;
unsigned long flags; unsigned long flags;
...@@ -252,7 +252,7 @@ static ssize_t gfar_set_fifo_starve(struct device *dev, ...@@ -252,7 +252,7 @@ static ssize_t gfar_set_fifo_starve(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar __iomem *regs = priv->gfargrp[0].regs;
unsigned int num = simple_strtoul(buf, NULL, 0); unsigned int num = simple_strtoul(buf, NULL, 0);
u32 temp; u32 temp;
unsigned long flags; unsigned long flags;
...@@ -293,7 +293,7 @@ static ssize_t gfar_set_fifo_starve_off(struct device *dev, ...@@ -293,7 +293,7 @@ static ssize_t gfar_set_fifo_starve_off(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar __iomem *regs = priv->gfargrp[0].regs;
unsigned int num = simple_strtoul(buf, NULL, 0); unsigned int num = simple_strtoul(buf, NULL, 0);
u32 temp; u32 temp;
unsigned long flags; unsigned long flags;
......
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