| 
				
			 | 
			
			
				
				@@ -161,6 +161,9 @@ void netdev_rx_unfreeze ( struct net_device *netdev ) { 
			 | 
		
		
	
		
			
			| 
				161
			 | 
			
				161
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				162
			 | 
			
				162
			 | 
			
			
				
				 void netdev_link_err ( struct net_device *netdev, int rc ) { 
			 | 
		
		
	
		
			
			| 
				163
			 | 
			
				163
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				164
			 | 
			
			
				
				+	/* Stop link block timer */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				165
			 | 
			
			
				
				+	stop_timer ( &netdev->link_block ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				166
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				164
			 | 
			
				167
			 | 
			
			
				
				 	/* Record link state */ 
			 | 
		
		
	
		
			
			| 
				165
			 | 
			
				168
			 | 
			
			
				
				 	netdev->link_rc = rc; 
			 | 
		
		
	
		
			
			| 
				166
			 | 
			
				169
			 | 
			
			
				
				 	if ( netdev->link_rc == 0 ) { 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -190,6 +193,50 @@ void netdev_link_down ( struct net_device *netdev ) { 
			 | 
		
		
	
		
			
			| 
				190
			 | 
			
				193
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				191
			 | 
			
				194
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				192
			 | 
			
				195
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				196
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				197
			 | 
			
			
				
				+ * Mark network device link as being blocked 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				198
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				199
			 | 
			
			
				
				+ * @v netdev		Network device 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				200
			 | 
			
			
				
				+ * @v timeout		Timeout (in ticks) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				201
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				202
			 | 
			
			
				
				+void netdev_link_block ( struct net_device *netdev, unsigned long timeout ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				203
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				204
			 | 
			
			
				
				+	/* Start link block timer */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				205
			 | 
			
			
				
				+	if ( ! netdev_link_blocked ( netdev ) ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				206
			 | 
			
			
				
				+		DBGC ( netdev, "NETDEV %s link blocked for %ld ticks\n", 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				207
			 | 
			
			
				
				+		       netdev->name, timeout ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				208
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				209
			 | 
			
			
				
				+	start_timer_fixed ( &netdev->link_block, timeout ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				210
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				211
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				212
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				213
			 | 
			
			
				
				+ * Mark network device link as being unblocked 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				214
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				215
			 | 
			
			
				
				+ * @v netdev		Network device 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				216
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				217
			 | 
			
			
				
				+void netdev_link_unblock ( struct net_device *netdev ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				218
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				219
			 | 
			
			
				
				+	/* Stop link block timer */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				220
			 | 
			
			
				
				+	if ( netdev_link_blocked ( netdev ) ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				221
			 | 
			
			
				
				+		DBGC ( netdev, "NETDEV %s link unblocked\n", netdev->name ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				222
			 | 
			
			
				
				+	stop_timer ( &netdev->link_block ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				223
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				224
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				225
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				226
			 | 
			
			
				
				+ * Handle network device link block timer expiry 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				227
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				228
			 | 
			
			
				
				+ * @v timer		Link block timer 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				229
			 | 
			
			
				
				+ * @v fail		Failure indicator 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				230
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				231
			 | 
			
			
				
				+static void netdev_link_block_expired ( struct retry_timer *timer, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				232
			 | 
			
			
				
				+					int fail __unused ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				233
			 | 
			
			
				
				+	struct net_device *netdev = 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				234
			 | 
			
			
				
				+		container_of ( timer, struct net_device, link_block ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				235
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				236
			 | 
			
			
				
				+	/* Assume link is no longer blocked */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				237
			 | 
			
			
				
				+	DBGC ( netdev, "NETDEV %s link block expired\n", netdev->name ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				238
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				239
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				193
			 | 
			
				240
			 | 
			
			
				
				 /** 
			 | 
		
		
	
		
			
			| 
				194
			 | 
			
				241
			 | 
			
			
				
				  * Record network device statistic 
			 | 
		
		
	
		
			
			| 
				195
			 | 
			
				242
			 | 
			
			
				
				  * 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -545,7 +592,8 @@ static struct interface_descriptor netdev_config_desc = 
			 | 
		
		
	
		
			
			| 
				545
			 | 
			
				592
			 | 
			
			
				
				 static void free_netdev ( struct refcnt *refcnt ) { 
			 | 
		
		
	
		
			
			| 
				546
			 | 
			
				593
			 | 
			
			
				
				 	struct net_device *netdev = 
			 | 
		
		
	
		
			
			| 
				547
			 | 
			
				594
			 | 
			
			
				
				 		container_of ( refcnt, struct net_device, refcnt ); 
			 | 
		
		
	
		
			
			| 
				548
			 | 
			
				
			 | 
			
			
				
				-	 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				595
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				596
			 | 
			
			
				
				+	stop_timer ( &netdev->link_block ); 
			 | 
		
		
	
		
			
			| 
				549
			 | 
			
				597
			 | 
			
			
				
				 	netdev_tx_flush ( netdev ); 
			 | 
		
		
	
		
			
			| 
				550
			 | 
			
				598
			 | 
			
			
				
				 	netdev_rx_flush ( netdev ); 
			 | 
		
		
	
		
			
			| 
				551
			 | 
			
				599
			 | 
			
			
				
				 	clear_settings ( netdev_settings ( netdev ) ); 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -575,6 +623,8 @@ struct net_device * alloc_netdev ( size_t priv_len ) { 
			 | 
		
		
	
		
			
			| 
				575
			 | 
			
				623
			 | 
			
			
				
				 	if ( netdev ) { 
			 | 
		
		
	
		
			
			| 
				576
			 | 
			
				624
			 | 
			
			
				
				 		ref_init ( &netdev->refcnt, free_netdev ); 
			 | 
		
		
	
		
			
			| 
				577
			 | 
			
				625
			 | 
			
			
				
				 		netdev->link_rc = -EUNKNOWN_LINK_STATUS; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				626
			 | 
			
			
				
				+		timer_init ( &netdev->link_block, netdev_link_block_expired, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				627
			 | 
			
			
				
				+			     &netdev->refcnt ); 
			 | 
		
		
	
		
			
			| 
				578
			 | 
			
				628
			 | 
			
			
				
				 		INIT_LIST_HEAD ( &netdev->tx_queue ); 
			 | 
		
		
	
		
			
			| 
				579
			 | 
			
				629
			 | 
			
			
				
				 		INIT_LIST_HEAD ( &netdev->tx_deferred ); 
			 | 
		
		
	
		
			
			| 
				580
			 | 
			
				630
			 | 
			
			
				
				 		INIT_LIST_HEAD ( &netdev->rx_queue ); 
			 |