42
42
#define to_virtio_uml_device (_vdev ) \
43
43
container_of(_vdev, struct virtio_uml_device, vdev)
44
44
45
+ struct virtio_uml_platform_data {
46
+ u32 virtio_device_id ;
47
+ const char * socket_path ;
48
+ struct work_struct conn_broken_wk ;
49
+ struct platform_device * pdev ;
50
+ };
51
+
45
52
struct virtio_uml_device {
46
53
struct virtio_device vdev ;
47
54
struct platform_device * pdev ;
@@ -50,6 +57,7 @@ struct virtio_uml_device {
50
57
u64 features ;
51
58
u64 protocol_features ;
52
59
u8 status ;
60
+ u8 registered :1 ;
53
61
};
54
62
55
63
struct virtio_uml_vq_info {
@@ -107,12 +115,21 @@ static int vhost_user_recv_header(int fd, struct vhost_user_msg *msg)
107
115
return full_read (fd , msg , sizeof (msg -> header ));
108
116
}
109
117
110
- static int vhost_user_recv (int fd , struct vhost_user_msg * msg ,
118
+ static int vhost_user_recv (struct virtio_uml_device * vu_dev ,
119
+ int fd , struct vhost_user_msg * msg ,
111
120
size_t max_payload_size )
112
121
{
113
122
size_t size ;
114
123
int rc = vhost_user_recv_header (fd , msg );
115
124
125
+ if (rc == - ECONNRESET && vu_dev -> registered ) {
126
+ struct virtio_uml_platform_data * pdata ;
127
+
128
+ pdata = vu_dev -> pdev -> dev .platform_data ;
129
+
130
+ virtio_break_device (& vu_dev -> vdev );
131
+ schedule_work (& pdata -> conn_broken_wk );
132
+ }
116
133
if (rc )
117
134
return rc ;
118
135
size = msg -> header .size ;
@@ -125,7 +142,7 @@ static int vhost_user_recv_resp(struct virtio_uml_device *vu_dev,
125
142
struct vhost_user_msg * msg ,
126
143
size_t max_payload_size )
127
144
{
128
- int rc = vhost_user_recv (vu_dev -> sock , msg , max_payload_size );
145
+ int rc = vhost_user_recv (vu_dev , vu_dev -> sock , msg , max_payload_size );
129
146
130
147
if (rc )
131
148
return rc ;
@@ -155,7 +172,7 @@ static int vhost_user_recv_req(struct virtio_uml_device *vu_dev,
155
172
struct vhost_user_msg * msg ,
156
173
size_t max_payload_size )
157
174
{
158
- int rc = vhost_user_recv (vu_dev -> req_fd , msg , max_payload_size );
175
+ int rc = vhost_user_recv (vu_dev , vu_dev -> req_fd , msg , max_payload_size );
159
176
160
177
if (rc )
161
178
return rc ;
@@ -963,11 +980,6 @@ static void virtio_uml_release_dev(struct device *d)
963
980
964
981
/* Platform device */
965
982
966
- struct virtio_uml_platform_data {
967
- u32 virtio_device_id ;
968
- const char * socket_path ;
969
- };
970
-
971
983
static int virtio_uml_probe (struct platform_device * pdev )
972
984
{
973
985
struct virtio_uml_platform_data * pdata = pdev -> dev .platform_data ;
@@ -1005,6 +1017,7 @@ static int virtio_uml_probe(struct platform_device *pdev)
1005
1017
rc = register_virtio_device (& vu_dev -> vdev );
1006
1018
if (rc )
1007
1019
put_device (& vu_dev -> vdev .dev );
1020
+ vu_dev -> registered = 1 ;
1008
1021
return rc ;
1009
1022
1010
1023
error_init :
@@ -1034,13 +1047,31 @@ static struct device vu_cmdline_parent = {
1034
1047
static bool vu_cmdline_parent_registered ;
1035
1048
static int vu_cmdline_id ;
1036
1049
1050
+ static int vu_unregister_cmdline_device (struct device * dev , void * data )
1051
+ {
1052
+ struct platform_device * pdev = to_platform_device (dev );
1053
+ struct virtio_uml_platform_data * pdata = pdev -> dev .platform_data ;
1054
+
1055
+ kfree (pdata -> socket_path );
1056
+ platform_device_unregister (pdev );
1057
+ return 0 ;
1058
+ }
1059
+
1060
+ static void vu_conn_broken (struct work_struct * wk )
1061
+ {
1062
+ struct virtio_uml_platform_data * pdata ;
1063
+
1064
+ pdata = container_of (wk , struct virtio_uml_platform_data , conn_broken_wk );
1065
+ vu_unregister_cmdline_device (& pdata -> pdev -> dev , NULL );
1066
+ }
1067
+
1037
1068
static int vu_cmdline_set (const char * device , const struct kernel_param * kp )
1038
1069
{
1039
1070
const char * ids = strchr (device , ':' );
1040
1071
unsigned int virtio_device_id ;
1041
1072
int processed , consumed , err ;
1042
1073
char * socket_path ;
1043
- struct virtio_uml_platform_data pdata ;
1074
+ struct virtio_uml_platform_data pdata , * ppdata ;
1044
1075
struct platform_device * pdev ;
1045
1076
1046
1077
if (!ids || ids == device )
@@ -1079,6 +1110,11 @@ static int vu_cmdline_set(const char *device, const struct kernel_param *kp)
1079
1110
err = PTR_ERR_OR_ZERO (pdev );
1080
1111
if (err )
1081
1112
goto free ;
1113
+
1114
+ ppdata = pdev -> dev .platform_data ;
1115
+ ppdata -> pdev = pdev ;
1116
+ INIT_WORK (& ppdata -> conn_broken_wk , vu_conn_broken );
1117
+
1082
1118
return 0 ;
1083
1119
1084
1120
free :
@@ -1121,16 +1157,6 @@ __uml_help(vu_cmdline_param_ops,
1121
1157
);
1122
1158
1123
1159
1124
- static int vu_unregister_cmdline_device (struct device * dev , void * data )
1125
- {
1126
- struct platform_device * pdev = to_platform_device (dev );
1127
- struct virtio_uml_platform_data * pdata = pdev -> dev .platform_data ;
1128
-
1129
- kfree (pdata -> socket_path );
1130
- platform_device_unregister (pdev );
1131
- return 0 ;
1132
- }
1133
-
1134
1160
static void vu_unregister_cmdline_devices (void )
1135
1161
{
1136
1162
if (vu_cmdline_parent_registered ) {
0 commit comments