|
|
|
@ -279,10 +279,59 @@ void host1x_bus_exit(void) |
|
|
|
|
bus_unregister(&host1x_bus_type); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void __host1x_device_del(struct host1x_device *device) |
|
|
|
|
{ |
|
|
|
|
struct host1x_subdev *subdev, *sd; |
|
|
|
|
struct host1x_client *client, *cl; |
|
|
|
|
|
|
|
|
|
mutex_lock(&device->subdevs_lock); |
|
|
|
|
|
|
|
|
|
/* unregister subdevices */ |
|
|
|
|
list_for_each_entry_safe(subdev, sd, &device->active, list) { |
|
|
|
|
/*
|
|
|
|
|
* host1x_subdev_unregister() will remove the client from |
|
|
|
|
* any lists, so we'll need to manually add it back to the |
|
|
|
|
* list of idle clients. |
|
|
|
|
* |
|
|
|
|
* XXX: Alternatively, perhaps don't remove the client from |
|
|
|
|
* any lists in host1x_subdev_unregister() and instead do |
|
|
|
|
* that explicitly from host1x_unregister_client()? |
|
|
|
|
*/ |
|
|
|
|
client = subdev->client; |
|
|
|
|
|
|
|
|
|
__host1x_subdev_unregister(device, subdev); |
|
|
|
|
|
|
|
|
|
/* add the client to the list of idle clients */ |
|
|
|
|
mutex_lock(&clients_lock); |
|
|
|
|
list_add_tail(&client->list, &clients); |
|
|
|
|
mutex_unlock(&clients_lock); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* remove subdevices */ |
|
|
|
|
list_for_each_entry_safe(subdev, sd, &device->subdevs, list) |
|
|
|
|
host1x_subdev_del(subdev); |
|
|
|
|
|
|
|
|
|
mutex_unlock(&device->subdevs_lock); |
|
|
|
|
|
|
|
|
|
/* move clients to idle list */ |
|
|
|
|
mutex_lock(&clients_lock); |
|
|
|
|
mutex_lock(&device->clients_lock); |
|
|
|
|
|
|
|
|
|
list_for_each_entry_safe(client, cl, &device->clients, list) |
|
|
|
|
list_move_tail(&client->list, &clients); |
|
|
|
|
|
|
|
|
|
mutex_unlock(&device->clients_lock); |
|
|
|
|
mutex_unlock(&clients_lock); |
|
|
|
|
|
|
|
|
|
/* finally remove the device */ |
|
|
|
|
list_del_init(&device->list); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void host1x_device_release(struct device *dev) |
|
|
|
|
{ |
|
|
|
|
struct host1x_device *device = to_host1x_device(dev); |
|
|
|
|
|
|
|
|
|
__host1x_device_del(device); |
|
|
|
|
kfree(device); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -350,50 +399,6 @@ static int host1x_device_add(struct host1x *host1x, |
|
|
|
|
static void host1x_device_del(struct host1x *host1x, |
|
|
|
|
struct host1x_device *device) |
|
|
|
|
{ |
|
|
|
|
struct host1x_subdev *subdev, *sd; |
|
|
|
|
struct host1x_client *client, *cl; |
|
|
|
|
|
|
|
|
|
mutex_lock(&device->subdevs_lock); |
|
|
|
|
|
|
|
|
|
/* unregister subdevices */ |
|
|
|
|
list_for_each_entry_safe(subdev, sd, &device->active, list) { |
|
|
|
|
/*
|
|
|
|
|
* host1x_subdev_unregister() will remove the client from |
|
|
|
|
* any lists, so we'll need to manually add it back to the |
|
|
|
|
* list of idle clients. |
|
|
|
|
* |
|
|
|
|
* XXX: Alternatively, perhaps don't remove the client from |
|
|
|
|
* any lists in host1x_subdev_unregister() and instead do |
|
|
|
|
* that explicitly from host1x_unregister_client()? |
|
|
|
|
*/ |
|
|
|
|
client = subdev->client; |
|
|
|
|
|
|
|
|
|
__host1x_subdev_unregister(device, subdev); |
|
|
|
|
|
|
|
|
|
/* add the client to the list of idle clients */ |
|
|
|
|
mutex_lock(&clients_lock); |
|
|
|
|
list_add_tail(&client->list, &clients); |
|
|
|
|
mutex_unlock(&clients_lock); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* remove subdevices */ |
|
|
|
|
list_for_each_entry_safe(subdev, sd, &device->subdevs, list) |
|
|
|
|
host1x_subdev_del(subdev); |
|
|
|
|
|
|
|
|
|
mutex_unlock(&device->subdevs_lock); |
|
|
|
|
|
|
|
|
|
/* move clients to idle list */ |
|
|
|
|
mutex_lock(&clients_lock); |
|
|
|
|
mutex_lock(&device->clients_lock); |
|
|
|
|
|
|
|
|
|
list_for_each_entry_safe(client, cl, &device->clients, list) |
|
|
|
|
list_move_tail(&client->list, &clients); |
|
|
|
|
|
|
|
|
|
mutex_unlock(&device->clients_lock); |
|
|
|
|
mutex_unlock(&clients_lock); |
|
|
|
|
|
|
|
|
|
/* finally remove the device */ |
|
|
|
|
list_del_init(&device->list); |
|
|
|
|
device_unregister(&device->dev); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|