net: fec: restart the FEC when PHY speed changes
Proviously we would only restart the FEC when PHY link or duplex state changed. PHY does not always bring down the link for speed changes, in which case we would not detect any change and keep FEC running. Switching link speed without restarting the FEC results in the FEC being stuck in an indefinite state, generating error conditions for every packet. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
					parent
					
						
							
								cca7af3889
							
						
					
				
			
			
				commit
				
					
						d97e749769
					
				
			
		
					 2 changed files with 16 additions and 11 deletions
				
			
		|  | @ -934,24 +934,28 @@ static void fec_enet_adjust_link(struct net_device *ndev) | |||
| 		goto spin_unlock; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Duplex link change */ | ||||
| 	if (phy_dev->link) { | ||||
| 		if (fep->full_duplex != phy_dev->duplex) { | ||||
| 			fec_restart(ndev, phy_dev->duplex); | ||||
| 			/* prevent unnecessary second fec_restart() below */ | ||||
| 		if (!fep->link) { | ||||
| 			fep->link = phy_dev->link; | ||||
| 			status_change = 1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Link on or off change */ | ||||
| 	if (phy_dev->link != fep->link) { | ||||
| 		fep->link = phy_dev->link; | ||||
| 		if (phy_dev->link) | ||||
| 		if (fep->full_duplex != phy_dev->duplex) | ||||
| 			status_change = 1; | ||||
| 
 | ||||
| 		if (phy_dev->speed != fep->speed) { | ||||
| 			fep->speed = phy_dev->speed; | ||||
| 			status_change = 1; | ||||
| 		} | ||||
| 
 | ||||
| 		/* if any of the above changed restart the FEC */ | ||||
| 		if (status_change) | ||||
| 			fec_restart(ndev, phy_dev->duplex); | ||||
| 		else | ||||
| 	} else { | ||||
| 		if (fep->link) { | ||||
| 			fec_stop(ndev); | ||||
| 		status_change = 1; | ||||
| 			status_change = 1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| spin_unlock: | ||||
|  |  | |||
|  | @ -240,6 +240,7 @@ struct fec_enet_private { | |||
| 	phy_interface_t	phy_interface; | ||||
| 	int	link; | ||||
| 	int	full_duplex; | ||||
| 	int	speed; | ||||
| 	struct	completion mdio_done; | ||||
| 	int	irq[FEC_IRQ_NUM]; | ||||
| 	int	bufdesc_ex; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lucas Stach
				Lucas Stach