|
@@ -62,6 +62,55 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
62
|
62
|
******************************************************************************
|
63
|
63
|
*/
|
64
|
64
|
|
|
65
|
+/**
|
|
66
|
+ * Reset device
|
|
67
|
+ *
|
|
68
|
+ * @v netfront Netfront device
|
|
69
|
+ * @ret rc Return status code
|
|
70
|
+ */
|
|
71
|
+static int netfront_reset ( struct netfront_nic *netfront ) {
|
|
72
|
+ struct xen_device *xendev = netfront->xendev;
|
|
73
|
+ int state;
|
|
74
|
+ int rc;
|
|
75
|
+
|
|
76
|
+ /* Get current backend state */
|
|
77
|
+ if ( ( state = xenbus_backend_state ( xendev ) ) < 0 ) {
|
|
78
|
+ rc = state;
|
|
79
|
+ DBGC ( netfront, "NETFRONT %s could not read backend state: "
|
|
80
|
+ "%s\n", xendev->key, strerror ( rc ) );
|
|
81
|
+ return rc;
|
|
82
|
+ }
|
|
83
|
+
|
|
84
|
+ /* If the backend is not already in InitWait, then mark
|
|
85
|
+ * frontend as Closed to shut down the backend.
|
|
86
|
+ */
|
|
87
|
+ if ( state != XenbusStateInitWait ) {
|
|
88
|
+
|
|
89
|
+ /* Set state to Closed */
|
|
90
|
+ xenbus_set_state ( xendev, XenbusStateClosed );
|
|
91
|
+
|
|
92
|
+ /* Wait for backend to reach Closed */
|
|
93
|
+ if ( ( rc = xenbus_backend_wait ( xendev,
|
|
94
|
+ XenbusStateClosed ) ) != 0 ) {
|
|
95
|
+ DBGC ( netfront, "NETFRONT %s backend did not reach "
|
|
96
|
+ "Closed: %s\n", xendev->key, strerror ( rc ) );
|
|
97
|
+ return rc;
|
|
98
|
+ }
|
|
99
|
+ }
|
|
100
|
+
|
|
101
|
+ /* Reset state to Initialising */
|
|
102
|
+ xenbus_set_state ( xendev, XenbusStateInitialising );
|
|
103
|
+
|
|
104
|
+ /* Wait for backend to reach InitWait */
|
|
105
|
+ if ( ( rc = xenbus_backend_wait ( xendev, XenbusStateInitWait ) ) != 0){
|
|
106
|
+ DBGC ( netfront, "NETFRONT %s backend did not reach InitWait: "
|
|
107
|
+ "%s\n", xendev->key, strerror ( rc ) );
|
|
108
|
+ return rc;
|
|
109
|
+ }
|
|
110
|
+
|
|
111
|
+ return 0;
|
|
112
|
+}
|
|
113
|
+
|
65
|
114
|
/**
|
66
|
115
|
* Fetch MAC address
|
67
|
116
|
*
|
|
@@ -510,6 +559,10 @@ static int netfront_open ( struct net_device *netdev ) {
|
510
|
559
|
struct xen_device *xendev = netfront->xendev;
|
511
|
560
|
int rc;
|
512
|
561
|
|
|
562
|
+ /* Ensure device is in a suitable initial state */
|
|
563
|
+ if ( ( rc = netfront_reset ( netfront ) ) != 0 )
|
|
564
|
+ goto err_reset;
|
|
565
|
+
|
513
|
566
|
/* Create transmit descriptor ring */
|
514
|
567
|
if ( ( rc = netfront_create_ring ( netfront, &netfront->tx ) ) != 0 )
|
515
|
568
|
goto err_create_tx;
|
|
@@ -563,7 +616,7 @@ static int netfront_open ( struct net_device *netdev ) {
|
563
|
616
|
return 0;
|
564
|
617
|
|
565
|
618
|
err_backend_wait:
|
566
|
|
- xenbus_set_state ( xendev, XenbusStateInitialising );
|
|
619
|
+ netfront_reset ( netfront );
|
567
|
620
|
err_set_state:
|
568
|
621
|
netfront_rm ( netfront, "feature-no-csum-offload" );
|
569
|
622
|
err_feature_no_csum_offload:
|
|
@@ -575,6 +628,7 @@ static int netfront_open ( struct net_device *netdev ) {
|
575
|
628
|
err_create_rx:
|
576
|
629
|
netfront_destroy_ring ( netfront, &netfront->tx, NULL );
|
577
|
630
|
err_create_tx:
|
|
631
|
+ err_reset:
|
578
|
632
|
return rc;
|
579
|
633
|
}
|
580
|
634
|
|
|
@@ -588,13 +642,10 @@ static void netfront_close ( struct net_device *netdev ) {
|
588
|
642
|
struct xen_device *xendev = netfront->xendev;
|
589
|
643
|
int rc;
|
590
|
644
|
|
591
|
|
- /* Set state to Closed */
|
592
|
|
- xenbus_set_state ( xendev, XenbusStateClosed );
|
593
|
|
-
|
594
|
|
- /* Wait for backend to close, thereby ensuring that grant
|
595
|
|
- * references are no longer in use, etc.
|
|
645
|
+ /* Reset devic, thereby ensuring that grant references are no
|
|
646
|
+ * longer in use, etc.
|
596
|
647
|
*/
|
597
|
|
- if ( ( rc = xenbus_backend_wait ( xendev, XenbusStateClosed ) ) != 0 ) {
|
|
648
|
+ if ( ( rc = netfront_reset ( netfront ) ) != 0 ) {
|
598
|
649
|
DBGC ( netfront, "NETFRONT %s could not disconnect from "
|
599
|
650
|
"backend: %s\n", xendev->key, strerror ( rc ) );
|
600
|
651
|
/* Things will probably go _very_ badly wrong if this
|
|
@@ -609,9 +660,6 @@ static void netfront_close ( struct net_device *netdev ) {
|
609
|
660
|
netdev_link_down ( netdev );
|
610
|
661
|
}
|
611
|
662
|
|
612
|
|
- /* Reset state to Initialising */
|
613
|
|
- xenbus_set_state ( xendev, XenbusStateInitialising );
|
614
|
|
-
|
615
|
663
|
/* Delete flags */
|
616
|
664
|
netfront_rm ( netfront, "feature-no-csum-offload" );
|
617
|
665
|
netfront_rm ( netfront, "request-rx-copy" );
|
|
@@ -835,6 +883,12 @@ static int netfront_probe ( struct xen_device *xendev ) {
|
835
|
883
|
if ( ( rc = netfront_read_mac ( netfront, netdev->hw_addr ) ) != 0 )
|
836
|
884
|
goto err_read_mac;
|
837
|
885
|
|
|
886
|
+ /* Reset device. Ignore failures; allow the device to be
|
|
887
|
+ * registered so that reset errors can be observed by the user
|
|
888
|
+ * when attempting to open the device.
|
|
889
|
+ */
|
|
890
|
+ netfront_reset ( netfront );
|
|
891
|
+
|
838
|
892
|
/* Register network device */
|
839
|
893
|
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
840
|
894
|
goto err_register_netdev;
|