Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: drivers/net/ethernet/broadcom/genet/bcmgenet.c net/core/sock.c Conflicts were overlapping changes in bcmgenet and the lockdep handling of sockets. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -450,6 +450,22 @@ static inline void bcmgenet_rdma_ring_writel(struct bcmgenet_priv *priv,
|
||||
genet_dma_ring_regs[r]);
|
||||
}
|
||||
|
||||
static int bcmgenet_begin(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
|
||||
/* Turn on the clock */
|
||||
return clk_prepare_enable(priv->clk);
|
||||
}
|
||||
|
||||
static void bcmgenet_complete(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
|
||||
/* Turn off the clock */
|
||||
clk_disable_unprepare(priv->clk);
|
||||
}
|
||||
|
||||
static int bcmgenet_get_link_ksettings(struct net_device *dev,
|
||||
struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
@@ -778,8 +794,9 @@ static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = {
|
||||
STAT_GENET_RUNT("rx_runt_bytes", mib.rx_runt_bytes),
|
||||
/* Misc UniMAC counters */
|
||||
STAT_GENET_MISC("rbuf_ovflow_cnt", mib.rbuf_ovflow_cnt,
|
||||
UMAC_RBUF_OVFL_CNT),
|
||||
STAT_GENET_MISC("rbuf_err_cnt", mib.rbuf_err_cnt, UMAC_RBUF_ERR_CNT),
|
||||
UMAC_RBUF_OVFL_CNT_V1),
|
||||
STAT_GENET_MISC("rbuf_err_cnt", mib.rbuf_err_cnt,
|
||||
UMAC_RBUF_ERR_CNT_V1),
|
||||
STAT_GENET_MISC("mdf_err_cnt", mib.mdf_err_cnt, UMAC_MDF_ERR_CNT),
|
||||
STAT_GENET_SOFT_MIB("alloc_rx_buff_failed", mib.alloc_rx_buff_failed),
|
||||
STAT_GENET_SOFT_MIB("rx_dma_failed", mib.rx_dma_failed),
|
||||
@@ -821,6 +838,45 @@ static void bcmgenet_get_strings(struct net_device *dev, u32 stringset,
|
||||
}
|
||||
}
|
||||
|
||||
static u32 bcmgenet_update_stat_misc(struct bcmgenet_priv *priv, u16 offset)
|
||||
{
|
||||
u16 new_offset;
|
||||
u32 val;
|
||||
|
||||
switch (offset) {
|
||||
case UMAC_RBUF_OVFL_CNT_V1:
|
||||
if (GENET_IS_V2(priv))
|
||||
new_offset = RBUF_OVFL_CNT_V2;
|
||||
else
|
||||
new_offset = RBUF_OVFL_CNT_V3PLUS;
|
||||
|
||||
val = bcmgenet_rbuf_readl(priv, new_offset);
|
||||
/* clear if overflowed */
|
||||
if (val == ~0)
|
||||
bcmgenet_rbuf_writel(priv, 0, new_offset);
|
||||
break;
|
||||
case UMAC_RBUF_ERR_CNT_V1:
|
||||
if (GENET_IS_V2(priv))
|
||||
new_offset = RBUF_ERR_CNT_V2;
|
||||
else
|
||||
new_offset = RBUF_ERR_CNT_V3PLUS;
|
||||
|
||||
val = bcmgenet_rbuf_readl(priv, new_offset);
|
||||
/* clear if overflowed */
|
||||
if (val == ~0)
|
||||
bcmgenet_rbuf_writel(priv, 0, new_offset);
|
||||
break;
|
||||
default:
|
||||
val = bcmgenet_umac_readl(priv, offset);
|
||||
/* clear if overflowed */
|
||||
if (val == ~0)
|
||||
bcmgenet_umac_writel(priv, 0, offset);
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv)
|
||||
{
|
||||
int i, j = 0;
|
||||
@@ -836,19 +892,28 @@ static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv)
|
||||
case BCMGENET_STAT_NETDEV:
|
||||
case BCMGENET_STAT_SOFT:
|
||||
continue;
|
||||
case BCMGENET_STAT_MIB_RX:
|
||||
case BCMGENET_STAT_MIB_TX:
|
||||
case BCMGENET_STAT_RUNT:
|
||||
if (s->type != BCMGENET_STAT_MIB_RX)
|
||||
offset = BCMGENET_STAT_OFFSET;
|
||||
offset += BCMGENET_STAT_OFFSET;
|
||||
/* fall through */
|
||||
case BCMGENET_STAT_MIB_TX:
|
||||
offset += BCMGENET_STAT_OFFSET;
|
||||
/* fall through */
|
||||
case BCMGENET_STAT_MIB_RX:
|
||||
val = bcmgenet_umac_readl(priv,
|
||||
UMAC_MIB_START + j + offset);
|
||||
offset = 0; /* Reset Offset */
|
||||
break;
|
||||
case BCMGENET_STAT_MISC:
|
||||
val = bcmgenet_umac_readl(priv, s->reg_offset);
|
||||
/* clear if overflowed */
|
||||
if (val == ~0)
|
||||
bcmgenet_umac_writel(priv, 0, s->reg_offset);
|
||||
if (GENET_IS_V1(priv)) {
|
||||
val = bcmgenet_umac_readl(priv, s->reg_offset);
|
||||
/* clear if overflowed */
|
||||
if (val == ~0)
|
||||
bcmgenet_umac_writel(priv, 0,
|
||||
s->reg_offset);
|
||||
} else {
|
||||
val = bcmgenet_update_stat_misc(priv,
|
||||
s->reg_offset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -973,6 +1038,8 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e)
|
||||
|
||||
/* standard ethtool support functions. */
|
||||
static const struct ethtool_ops bcmgenet_ethtool_ops = {
|
||||
.begin = bcmgenet_begin,
|
||||
.complete = bcmgenet_complete,
|
||||
.get_strings = bcmgenet_get_strings,
|
||||
.get_sset_count = bcmgenet_get_sset_count,
|
||||
.get_ethtool_stats = bcmgenet_get_ethtool_stats,
|
||||
@@ -1179,7 +1246,6 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
struct enet_cb *tx_cb_ptr;
|
||||
struct netdev_queue *txq;
|
||||
unsigned int pkts_compl = 0;
|
||||
unsigned int bytes_compl = 0;
|
||||
unsigned int c_index;
|
||||
@@ -1235,13 +1301,8 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
|
||||
dev->stats.tx_packets += pkts_compl;
|
||||
dev->stats.tx_bytes += bytes_compl;
|
||||
|
||||
txq = netdev_get_tx_queue(dev, ring->queue);
|
||||
netdev_tx_completed_queue(txq, pkts_compl, bytes_compl);
|
||||
|
||||
if (ring->free_bds > (MAX_SKB_FRAGS + 1)) {
|
||||
if (netif_tx_queue_stopped(txq))
|
||||
netif_tx_wake_queue(txq);
|
||||
}
|
||||
netdev_tx_completed_queue(netdev_get_tx_queue(dev, ring->queue),
|
||||
pkts_compl, bytes_compl);
|
||||
|
||||
return txbds_processed;
|
||||
}
|
||||
@@ -1264,8 +1325,16 @@ static int bcmgenet_tx_poll(struct napi_struct *napi, int budget)
|
||||
struct bcmgenet_tx_ring *ring =
|
||||
container_of(napi, struct bcmgenet_tx_ring, napi);
|
||||
unsigned int work_done = 0;
|
||||
struct netdev_queue *txq;
|
||||
unsigned long flags;
|
||||
|
||||
work_done = bcmgenet_tx_reclaim(ring->priv->dev, ring);
|
||||
spin_lock_irqsave(&ring->lock, flags);
|
||||
work_done = __bcmgenet_tx_reclaim(ring->priv->dev, ring);
|
||||
if (ring->free_bds > (MAX_SKB_FRAGS + 1)) {
|
||||
txq = netdev_get_tx_queue(ring->priv->dev, ring->queue);
|
||||
netif_tx_wake_queue(txq);
|
||||
}
|
||||
spin_unlock_irqrestore(&ring->lock, flags);
|
||||
|
||||
if (work_done == 0) {
|
||||
napi_complete(napi);
|
||||
@@ -2481,17 +2550,28 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
|
||||
/* Interrupt bottom half */
|
||||
static void bcmgenet_irq_task(struct work_struct *work)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int status;
|
||||
struct bcmgenet_priv *priv = container_of(
|
||||
work, struct bcmgenet_priv, bcmgenet_irq_work);
|
||||
|
||||
netif_dbg(priv, intr, priv->dev, "%s\n", __func__);
|
||||
|
||||
/* Link UP/DOWN event */
|
||||
if (priv->irq0_stat & UMAC_IRQ_LINK_EVENT) {
|
||||
phy_mac_interrupt(priv->phydev,
|
||||
!!(priv->irq0_stat & UMAC_IRQ_LINK_UP));
|
||||
priv->irq0_stat &= ~UMAC_IRQ_LINK_EVENT;
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
status = priv->irq0_stat;
|
||||
priv->irq0_stat = 0;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
if (status & UMAC_IRQ_MPD_R) {
|
||||
netif_dbg(priv, wol, priv->dev,
|
||||
"magic packet detected, waking up\n");
|
||||
bcmgenet_power_up(priv, GENET_POWER_WOL_MAGIC);
|
||||
}
|
||||
|
||||
/* Link UP/DOWN event */
|
||||
if (status & UMAC_IRQ_LINK_EVENT)
|
||||
phy_mac_interrupt(priv->phydev,
|
||||
!!(status & UMAC_IRQ_LINK_UP));
|
||||
}
|
||||
|
||||
/* bcmgenet_isr1: handle Rx and Tx priority queues */
|
||||
@@ -2500,22 +2580,21 @@ static irqreturn_t bcmgenet_isr1(int irq, void *dev_id)
|
||||
struct bcmgenet_priv *priv = dev_id;
|
||||
struct bcmgenet_rx_ring *rx_ring;
|
||||
struct bcmgenet_tx_ring *tx_ring;
|
||||
unsigned int index;
|
||||
unsigned int index, status;
|
||||
|
||||
/* Save irq status for bottom-half processing. */
|
||||
priv->irq1_stat =
|
||||
bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_STAT) &
|
||||
/* Read irq status */
|
||||
status = bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_STAT) &
|
||||
~bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_MASK_STATUS);
|
||||
|
||||
/* clear interrupts */
|
||||
bcmgenet_intrl2_1_writel(priv, priv->irq1_stat, INTRL2_CPU_CLEAR);
|
||||
bcmgenet_intrl2_1_writel(priv, status, INTRL2_CPU_CLEAR);
|
||||
|
||||
netif_dbg(priv, intr, priv->dev,
|
||||
"%s: IRQ=0x%x\n", __func__, priv->irq1_stat);
|
||||
"%s: IRQ=0x%x\n", __func__, status);
|
||||
|
||||
/* Check Rx priority queue interrupts */
|
||||
for (index = 0; index < priv->hw_params->rx_queues; index++) {
|
||||
if (!(priv->irq1_stat & BIT(UMAC_IRQ1_RX_INTR_SHIFT + index)))
|
||||
if (!(status & BIT(UMAC_IRQ1_RX_INTR_SHIFT + index)))
|
||||
continue;
|
||||
|
||||
rx_ring = &priv->rx_rings[index];
|
||||
@@ -2528,7 +2607,7 @@ static irqreturn_t bcmgenet_isr1(int irq, void *dev_id)
|
||||
|
||||
/* Check Tx priority queue interrupts */
|
||||
for (index = 0; index < priv->hw_params->tx_queues; index++) {
|
||||
if (!(priv->irq1_stat & BIT(index)))
|
||||
if (!(status & BIT(index)))
|
||||
continue;
|
||||
|
||||
tx_ring = &priv->tx_rings[index];
|
||||
@@ -2548,19 +2627,20 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
|
||||
struct bcmgenet_priv *priv = dev_id;
|
||||
struct bcmgenet_rx_ring *rx_ring;
|
||||
struct bcmgenet_tx_ring *tx_ring;
|
||||
unsigned int status;
|
||||
unsigned long flags;
|
||||
|
||||
/* Save irq status for bottom-half processing. */
|
||||
priv->irq0_stat =
|
||||
bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_STAT) &
|
||||
/* Read irq status */
|
||||
status = bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_STAT) &
|
||||
~bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS);
|
||||
|
||||
/* clear interrupts */
|
||||
bcmgenet_intrl2_0_writel(priv, priv->irq0_stat, INTRL2_CPU_CLEAR);
|
||||
bcmgenet_intrl2_0_writel(priv, status, INTRL2_CPU_CLEAR);
|
||||
|
||||
netif_dbg(priv, intr, priv->dev,
|
||||
"IRQ=0x%x\n", priv->irq0_stat);
|
||||
"IRQ=0x%x\n", status);
|
||||
|
||||
if (priv->irq0_stat & UMAC_IRQ_RXDMA_DONE) {
|
||||
if (status & UMAC_IRQ_RXDMA_DONE) {
|
||||
rx_ring = &priv->rx_rings[DESC_INDEX];
|
||||
|
||||
if (likely(napi_schedule_prep(&rx_ring->napi))) {
|
||||
@@ -2569,7 +2649,7 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->irq0_stat & UMAC_IRQ_TXDMA_DONE) {
|
||||
if (status & UMAC_IRQ_TXDMA_DONE) {
|
||||
tx_ring = &priv->tx_rings[DESC_INDEX];
|
||||
|
||||
if (likely(napi_schedule_prep(&tx_ring->napi))) {
|
||||
@@ -2588,11 +2668,22 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
if ((priv->hw_params->flags & GENET_HAS_MDIO_INTR) &&
|
||||
priv->irq0_stat & (UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR)) {
|
||||
priv->irq0_stat &= ~(UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR);
|
||||
status & (UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR)) {
|
||||
wake_up(&priv->wq);
|
||||
}
|
||||
|
||||
/* all other interested interrupts handled in bottom half */
|
||||
status &= (UMAC_IRQ_LINK_EVENT |
|
||||
UMAC_IRQ_MPD_R);
|
||||
if (status) {
|
||||
/* Save irq status for bottom-half processing. */
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->irq0_stat |= status;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
schedule_work(&priv->bcmgenet_irq_work);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -2817,6 +2908,8 @@ err_irq0:
|
||||
err_fini_dma:
|
||||
bcmgenet_fini_dma(priv);
|
||||
err_clk_disable:
|
||||
if (priv->internal_phy)
|
||||
bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
return ret;
|
||||
}
|
||||
@@ -3218,16 +3311,16 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv)
|
||||
pr_warn("GENET is reporting EPHY revision: 0x%04x\n",
|
||||
gphy_rev);
|
||||
}
|
||||
/* This is reserved so should require special treatment */
|
||||
} else if (gphy_rev == 0 || gphy_rev == 0x01ff) {
|
||||
pr_warn("Invalid GPHY revision detected: 0x%04x\n", gphy_rev);
|
||||
return;
|
||||
/* This is the good old scheme, just GPHY major, no minor nor patch */
|
||||
} else if ((gphy_rev & 0xf0) != 0) {
|
||||
priv->gphy_rev = gphy_rev << 8;
|
||||
/* This is the new scheme, GPHY major rolls over with 0x10 = rev G0 */
|
||||
} else if ((gphy_rev & 0xff00) != 0) {
|
||||
priv->gphy_rev = gphy_rev;
|
||||
/* This is reserved so should require special treatment */
|
||||
} else if (gphy_rev == 0 || gphy_rev == 0x01ff) {
|
||||
pr_warn("Invalid GPHY revision detected: 0x%04x\n", gphy_rev);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PHYS_ADDR_T_64BIT
|
||||
@@ -3273,6 +3366,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
||||
const void *macaddr;
|
||||
struct resource *r;
|
||||
int err = -EIO;
|
||||
const char *phy_mode_str;
|
||||
|
||||
/* Up to GENET_MAX_MQ_CNT + 1 TX queues and RX queues */
|
||||
dev = alloc_etherdev_mqs(sizeof(*priv), GENET_MAX_MQ_CNT + 1,
|
||||
@@ -3316,6 +3410,8 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
||||
goto err;
|
||||
}
|
||||
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
SET_NETDEV_DEV(dev, &pdev->dev);
|
||||
dev_set_drvdata(&pdev->dev, dev);
|
||||
ether_addr_copy(dev->dev_addr, macaddr);
|
||||
@@ -3378,6 +3474,13 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
||||
priv->clk_eee = NULL;
|
||||
}
|
||||
|
||||
/* If this is an internal GPHY, power it on now, before UniMAC is
|
||||
* brought out of reset as absolutely no UniMAC activity is allowed
|
||||
*/
|
||||
if (dn && !of_property_read_string(dn, "phy-mode", &phy_mode_str) &&
|
||||
!strcasecmp(phy_mode_str, "internal"))
|
||||
bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
|
||||
|
||||
err = reset_umac(priv);
|
||||
if (err)
|
||||
goto err_clk_disable;
|
||||
@@ -3542,6 +3645,8 @@ static int bcmgenet_resume(struct device *d)
|
||||
return 0;
|
||||
|
||||
out_clk_disable:
|
||||
if (priv->internal_phy)
|
||||
bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
return ret;
|
||||
}
|
||||
|
@@ -214,7 +214,9 @@ struct bcmgenet_mib_counters {
|
||||
#define MDIO_REG_SHIFT 16
|
||||
#define MDIO_REG_MASK 0x1F
|
||||
|
||||
#define UMAC_RBUF_OVFL_CNT 0x61C
|
||||
#define UMAC_RBUF_OVFL_CNT_V1 0x61C
|
||||
#define RBUF_OVFL_CNT_V2 0x80
|
||||
#define RBUF_OVFL_CNT_V3PLUS 0x94
|
||||
|
||||
#define UMAC_MPD_CTRL 0x620
|
||||
#define MPD_EN (1 << 0)
|
||||
@@ -224,7 +226,9 @@ struct bcmgenet_mib_counters {
|
||||
|
||||
#define UMAC_MPD_PW_MS 0x624
|
||||
#define UMAC_MPD_PW_LS 0x628
|
||||
#define UMAC_RBUF_ERR_CNT 0x634
|
||||
#define UMAC_RBUF_ERR_CNT_V1 0x634
|
||||
#define RBUF_ERR_CNT_V2 0x84
|
||||
#define RBUF_ERR_CNT_V3PLUS 0x98
|
||||
#define UMAC_MDF_ERR_CNT 0x638
|
||||
#define UMAC_MDF_CTRL 0x650
|
||||
#define UMAC_MDF_ADDR 0x654
|
||||
@@ -627,11 +631,13 @@ struct bcmgenet_priv {
|
||||
struct work_struct bcmgenet_irq_work;
|
||||
int irq0;
|
||||
int irq1;
|
||||
unsigned int irq0_stat;
|
||||
unsigned int irq1_stat;
|
||||
int wol_irq;
|
||||
bool wol_irq_disabled;
|
||||
|
||||
/* shared status */
|
||||
spinlock_t lock;
|
||||
unsigned int irq0_stat;
|
||||
|
||||
/* HW descriptors/checksum variables */
|
||||
bool desc_64b_en;
|
||||
bool desc_rxchk_en;
|
||||
|
Reference in New Issue
Block a user