Commit 04e5b1fb authored by Johannes Berg's avatar Johannes Berg Committed by Richard Weinberger

um: virtio: Remove device on disconnect

If the connection drops, just remove the device, we don't try
to recover from this right now.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
parent 5c1f33e2
...@@ -42,6 +42,13 @@ ...@@ -42,6 +42,13 @@
#define to_virtio_uml_device(_vdev) \ #define to_virtio_uml_device(_vdev) \
container_of(_vdev, struct virtio_uml_device, vdev) container_of(_vdev, struct virtio_uml_device, vdev)
struct virtio_uml_platform_data {
u32 virtio_device_id;
const char *socket_path;
struct work_struct conn_broken_wk;
struct platform_device *pdev;
};
struct virtio_uml_device { struct virtio_uml_device {
struct virtio_device vdev; struct virtio_device vdev;
struct platform_device *pdev; struct platform_device *pdev;
...@@ -50,6 +57,7 @@ struct virtio_uml_device { ...@@ -50,6 +57,7 @@ struct virtio_uml_device {
u64 features; u64 features;
u64 protocol_features; u64 protocol_features;
u8 status; u8 status;
u8 registered:1;
}; };
struct virtio_uml_vq_info { struct virtio_uml_vq_info {
...@@ -107,12 +115,21 @@ static int vhost_user_recv_header(int fd, struct vhost_user_msg *msg) ...@@ -107,12 +115,21 @@ static int vhost_user_recv_header(int fd, struct vhost_user_msg *msg)
return full_read(fd, msg, sizeof(msg->header)); return full_read(fd, msg, sizeof(msg->header));
} }
static int vhost_user_recv(int fd, struct vhost_user_msg *msg, static int vhost_user_recv(struct virtio_uml_device *vu_dev,
int fd, struct vhost_user_msg *msg,
size_t max_payload_size) size_t max_payload_size)
{ {
size_t size; size_t size;
int rc = vhost_user_recv_header(fd, msg); int rc = vhost_user_recv_header(fd, msg);
if (rc == -ECONNRESET && vu_dev->registered) {
struct virtio_uml_platform_data *pdata;
pdata = vu_dev->pdev->dev.platform_data;
virtio_break_device(&vu_dev->vdev);
schedule_work(&pdata->conn_broken_wk);
}
if (rc) if (rc)
return rc; return rc;
size = msg->header.size; size = msg->header.size;
...@@ -125,7 +142,7 @@ static int vhost_user_recv_resp(struct virtio_uml_device *vu_dev, ...@@ -125,7 +142,7 @@ static int vhost_user_recv_resp(struct virtio_uml_device *vu_dev,
struct vhost_user_msg *msg, struct vhost_user_msg *msg,
size_t max_payload_size) size_t max_payload_size)
{ {
int rc = vhost_user_recv(vu_dev->sock, msg, max_payload_size); int rc = vhost_user_recv(vu_dev, vu_dev->sock, msg, max_payload_size);
if (rc) if (rc)
return rc; return rc;
...@@ -155,7 +172,7 @@ static int vhost_user_recv_req(struct virtio_uml_device *vu_dev, ...@@ -155,7 +172,7 @@ static int vhost_user_recv_req(struct virtio_uml_device *vu_dev,
struct vhost_user_msg *msg, struct vhost_user_msg *msg,
size_t max_payload_size) size_t max_payload_size)
{ {
int rc = vhost_user_recv(vu_dev->req_fd, msg, max_payload_size); int rc = vhost_user_recv(vu_dev, vu_dev->req_fd, msg, max_payload_size);
if (rc) if (rc)
return rc; return rc;
...@@ -963,11 +980,6 @@ static void virtio_uml_release_dev(struct device *d) ...@@ -963,11 +980,6 @@ static void virtio_uml_release_dev(struct device *d)
/* Platform device */ /* Platform device */
struct virtio_uml_platform_data {
u32 virtio_device_id;
const char *socket_path;
};
static int virtio_uml_probe(struct platform_device *pdev) static int virtio_uml_probe(struct platform_device *pdev)
{ {
struct virtio_uml_platform_data *pdata = pdev->dev.platform_data; struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
...@@ -1005,6 +1017,7 @@ static int virtio_uml_probe(struct platform_device *pdev) ...@@ -1005,6 +1017,7 @@ static int virtio_uml_probe(struct platform_device *pdev)
rc = register_virtio_device(&vu_dev->vdev); rc = register_virtio_device(&vu_dev->vdev);
if (rc) if (rc)
put_device(&vu_dev->vdev.dev); put_device(&vu_dev->vdev.dev);
vu_dev->registered = 1;
return rc; return rc;
error_init: error_init:
...@@ -1034,13 +1047,31 @@ static struct device vu_cmdline_parent = { ...@@ -1034,13 +1047,31 @@ static struct device vu_cmdline_parent = {
static bool vu_cmdline_parent_registered; static bool vu_cmdline_parent_registered;
static int vu_cmdline_id; static int vu_cmdline_id;
static int vu_unregister_cmdline_device(struct device *dev, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
kfree(pdata->socket_path);
platform_device_unregister(pdev);
return 0;
}
static void vu_conn_broken(struct work_struct *wk)
{
struct virtio_uml_platform_data *pdata;
pdata = container_of(wk, struct virtio_uml_platform_data, conn_broken_wk);
vu_unregister_cmdline_device(&pdata->pdev->dev, NULL);
}
static int vu_cmdline_set(const char *device, const struct kernel_param *kp) static int vu_cmdline_set(const char *device, const struct kernel_param *kp)
{ {
const char *ids = strchr(device, ':'); const char *ids = strchr(device, ':');
unsigned int virtio_device_id; unsigned int virtio_device_id;
int processed, consumed, err; int processed, consumed, err;
char *socket_path; char *socket_path;
struct virtio_uml_platform_data pdata; struct virtio_uml_platform_data pdata, *ppdata;
struct platform_device *pdev; struct platform_device *pdev;
if (!ids || ids == device) if (!ids || ids == device)
...@@ -1079,6 +1110,11 @@ static int vu_cmdline_set(const char *device, const struct kernel_param *kp) ...@@ -1079,6 +1110,11 @@ static int vu_cmdline_set(const char *device, const struct kernel_param *kp)
err = PTR_ERR_OR_ZERO(pdev); err = PTR_ERR_OR_ZERO(pdev);
if (err) if (err)
goto free; goto free;
ppdata = pdev->dev.platform_data;
ppdata->pdev = pdev;
INIT_WORK(&ppdata->conn_broken_wk, vu_conn_broken);
return 0; return 0;
free: free:
...@@ -1121,16 +1157,6 @@ __uml_help(vu_cmdline_param_ops, ...@@ -1121,16 +1157,6 @@ __uml_help(vu_cmdline_param_ops,
); );
static int vu_unregister_cmdline_device(struct device *dev, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
kfree(pdata->socket_path);
platform_device_unregister(pdev);
return 0;
}
static void vu_unregister_cmdline_devices(void) static void vu_unregister_cmdline_devices(void)
{ {
if (vu_cmdline_parent_registered) { if (vu_cmdline_parent_registered) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment