You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							138 lines
						
					
					
						
							4.5 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							138 lines
						
					
					
						
							4.5 KiB
						
					
					
				| diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c | |
| index 3d5c251..152774f 100644 | |
| --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c | |
| +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c | |
| @@ -129,7 +129,10 @@ static inline dma_addr_t dmadesc_get_addr(struct bcmgenet_priv *priv, | |
|  #define GENET_VER_FMT	"%1d.%1d EPHY: 0x%04x" | |
|   | |
|  #define GENET_MSG_DEFAULT	(NETIF_MSG_DRV | NETIF_MSG_PROBE | \ | |
| -				NETIF_MSG_LINK) | |
| +				NETIF_MSG_LINK | NETIF_MSG_INTR | \ | |
| +                NETIF_MSG_RX_ERR | NETIF_MSG_RX_STATUS | \ | |
| +                NETIF_MSG_TX_ERR | NETIF_MSG_TX_DONE | \ | |
| +                NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) | |
|   | |
|  static inline u32 bcmgenet_rbuf_ctrl_get(struct bcmgenet_priv *priv) | |
|  { | |
| @@ -3255,24 +3258,58 @@ static irqreturn_t bcmgenet_isr1(int irq, void *dev_id) | |
|  	return IRQ_HANDLED; | |
|  } | |
|   | |
| +struct rbuf_ovfl_work_struct { | |
| +    struct delayed_work queue; | |
| +    struct bcmgenet_priv *priv; | |
| +} rbuf_ovfl_work; | |
| + | |
| +static void rbuf_ovfl_wq_func(struct work_struct *work) { | |
| +    struct delayed_work *dwork = to_delayed_work(work); | |
| +    struct rbuf_ovfl_work_struct *rbo_work = container_of(dwork, struct rbuf_ovfl_work_struct, queue); | |
| +    struct bcmgenet_priv *priv = rbo_work->priv; | |
| + | |
| +    unsigned int flags = dev_get_flags(priv->dev); | |
| + | |
| +    rtnl_lock(); | |
| +    netif_carrier_off(priv->dev); | |
| +    dev_change_flags(priv->dev, flags & ~IFF_UP); | |
| +    rtnl_unlock(); | |
| + | |
| +    msleep(1000); | |
| + | |
| +    rtnl_lock(); | |
| +    dev_change_flags(priv->dev, flags | IFF_UP); | |
| +    rtnl_unlock(); | |
| + | |
| +    return; | |
| +} | |
| + | |
|  /* bcmgenet_isr0: handle Rx and Tx default queues + other stuff */ | |
|  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 int status, status_unmask; | |
|  	unsigned long flags; | |
|   | |
|  	/* Read irq status */ | |
| -	status = bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_STAT) & | |
| -		~bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS); | |
| +	status_unmask = bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_STAT); | |
| +    status = status_unmask & ~bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS); | |
| + | |
| +    if (status_unmask & (UMAC_IRQ_RBUF_OVERFLOW)) { | |
| +        netdev_info(priv->dev, | |
| +            "%s: %d pkts\n", __func__, bcmgenet_rbuf_readl(priv, RBUF_OVFL_CNT_V3PLUS)); | |
| +        status |= UMAC_IRQ_RBUF_OVERFLOW; | |
| +        schedule_delayed_work(&(rbuf_ovfl_work.queue), HZ); | |
| +    } | |
|   | |
|  	/* clear interrupts */ | |
|  	bcmgenet_intrl2_0_writel(priv, status, INTRL2_CPU_CLEAR); | |
|   | |
| -	netif_dbg(priv, intr, priv->dev, | |
| -		  "IRQ=0x%x\n", status); | |
| +    if (status & ~(UMAC_IRQ_MDIO_DONE)) /* except for mdio event */ | |
| +    	netif_dbg(priv, intr, priv->dev, | |
| +	        "%s: IRQ=0x%x\n", __func__, status); | |
|   | |
|  	if (status & UMAC_IRQ_RXDMA_DONE) { | |
|  		rx_ring = &priv->rx_rings[DESC_INDEX]; | |
| @@ -3281,6 +3318,10 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id) | |
|  			rx_ring->int_disable(rx_ring); | |
|  			__napi_schedule(&rx_ring->napi); | |
|  		} | |
| +        else { | |
| +            netif_dbg(priv, intr, priv->dev,  | |
| +                "%s: rx not sched. state=0x%08lx\n", __func__, rx_ring->napi.state); | |
| +        } | |
|  	} | |
|   | |
|  	if (status & UMAC_IRQ_TXDMA_DONE) { | |
| @@ -3306,6 +3347,8 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id) | |
|  		spin_unlock_irqrestore(&priv->lock, flags); | |
|   | |
|  		schedule_work(&priv->bcmgenet_irq_work); | |
| +    	netif_dbg(priv, intr, priv->dev, | |
| +	        "%s: link event. status=0x%08x\n", __func__, status); | |
|  	} | |
|   | |
|  	return IRQ_HANDLED; | |
| @@ -3351,6 +3394,20 @@ static void bcmgenet_umac_reset(struct bcmgenet_priv *priv) | |
|  	udelay(10); | |
|  } | |
|   | |
| +static void bcmgenet_rbuf_reset(struct bcmgenet_priv *priv) | |
| +{ | |
| +	u32 reg; | |
| + | |
| +	reg = bcmgenet_rbuf_ctrl_get(priv); | |
| +	reg |= BIT(0); | |
| +	bcmgenet_rbuf_ctrl_set(priv, reg); | |
| +	udelay(100); | |
| + | |
| +	reg &= ~BIT(0); | |
| +	bcmgenet_rbuf_ctrl_set(priv, reg); | |
| +	udelay(100); | |
| +} | |
| + | |
|  static void bcmgenet_set_hw_addr(struct bcmgenet_priv *priv, | |
|  				 unsigned char *addr) | |
|  { | |
| @@ -3434,6 +3491,7 @@ static int bcmgenet_open(struct net_device *dev) | |
|   | |
|  	/* take MAC out of reset */ | |
|  	bcmgenet_umac_reset(priv); | |
| +    bcmgenet_rbuf_reset(priv); | |
|   | |
|  	ret = init_umac(priv); | |
|  	if (ret) | |
| @@ -4070,6 +4128,8 @@ static int bcmgenet_probe(struct platform_device *pdev) | |
|  	/* Always use RX_BUF_LENGTH (2KB) buffer for all chips */ | |
|  	priv->rx_buf_len = RX_BUF_LENGTH; | |
|  	INIT_WORK(&priv->bcmgenet_irq_work, bcmgenet_irq_task); | |
| +    rbuf_ovfl_work.priv = priv; | |
| +    INIT_DELAYED_WORK(&(rbuf_ovfl_work.queue), rbuf_ovfl_wq_func); | |
|   | |
|  	priv->clk_wol = devm_clk_get(&priv->pdev->dev, "sw_genetwol"); | |
|  	if (IS_ERR(priv->clk_wol)) {
 | |
| 
 |