|
@@ -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 );
|