• Elad Kanfi's avatar
    net: nps_enet: Tx handler synchronization · e5df49d5
    Elad Kanfi authored
    Below is a description of a possible problematic
    sequence. CPU-A is sending a frame and CPU-B handles
    the interrupt that indicates the frame was sent. CPU-B
    reads an invalid value of tx_packet_sent.
    
    	CPU-A				CPU-B
    	-----				-----
    	nps_enet_send_frame
    	.
    	.
    	tx_skb = skb
    	tx_packet_sent = true
    	order HW to start tx
    	.
    	.
    	HW complete tx
    			    ------> 	get tx complete interrupt
    					.
    					.
    					if(tx_packet_sent == true)
    						handle tx_skb
    
    	end memory transaction
    	(tx_packet_sent actually
    	 written)
    
    Furthermore there is a dependency between tx_skb and tx_packet_sent.
    There is no assurance that tx_skb contains a valid pointer at CPU B
    when it sees tx_packet_sent == true.
    
    Solution:
    
    Initialize tx_skb to NULL and use it to indicate that packet was sent,
    in this way tx_packet_sent can be removed.
    Add a write memory barrier after setting tx_skb in order to make sure
    that it is valid before HW is informed and IRQ is fired.
    
    Fixed sequence will be:
    
           CPU-A                           CPU-B
           -----                           -----
    
    	tx_skb = skb
    	wmb()
    	.
    	.
    	order HW to start tx
    	.
    	.
    	HW complete tx
    			------>		get tx complete interrupt
    					.
    					.
    					if(tx_skb != NULL)
    						handle tx_skb
    
    					tx_skb = NULL
    Signed-off-by: default avatarElad Kanfi <eladkan@mellanox.com>
    Acked-by: default avatarNoam Camus <noamca@mellanox.com>
    Acked-by: default avatarGilad Ben-Yossef <giladby@mellanox.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    e5df49d5
nps_enet.h 6.46 KB