struct list_head list;
int list_data;
struct mutex list_lock;
- dev_t dev;
struct cdev cdev;
- struct device *device;
+ struct device dev;
};
struct raw_data {
return retval;
}
+static void raw_dev_release(struct device *dev)
+{
+ struct gb_raw *raw = container_of(dev, struct gb_raw, dev);
+
+ ida_free(&minors, MINOR(raw->dev.devt));
+
+ kfree(raw);
+}
+
static int gb_raw_probe(struct gb_bundle *bundle,
const struct greybus_bundle_id *id)
{
if (cport_desc->protocol_id != GREYBUS_PROTOCOL_RAW)
return -ENODEV;
- raw = kzalloc_obj(*raw);
- if (!raw)
+ minor = ida_alloc(&minors, GFP_KERNEL);
+ if (minor < 0)
+ return minor;
+
+ raw = kzalloc_obj(*raw, GFP_KERNEL);
+ if (!raw) {
+ ida_free(&minors, minor);
return -ENOMEM;
+ }
+
+ device_initialize(&raw->dev);
+ raw->dev.devt = MKDEV(raw_major, minor);
+ raw->dev.class = &raw_class;
+ raw->dev.parent = &bundle->dev;
+ raw->dev.release = raw_dev_release;
+ retval = dev_set_name(&raw->dev, "gb!raw%d", minor);
+ if (retval)
+ goto error_put_device;
connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
gb_raw_request_handler);
if (IS_ERR(connection)) {
retval = PTR_ERR(connection);
- goto error_free;
+ goto error_put_device;
}
INIT_LIST_HEAD(&raw->list);
raw->connection = connection;
greybus_set_drvdata(bundle, raw);
- minor = ida_alloc(&minors, GFP_KERNEL);
- if (minor < 0) {
- retval = minor;
- goto error_connection_destroy;
- }
-
- raw->dev = MKDEV(raw_major, minor);
cdev_init(&raw->cdev, &raw_fops);
retval = gb_connection_enable(connection);
if (retval)
- goto error_remove_ida;
+ goto error_connection_destroy;
- retval = cdev_add(&raw->cdev, raw->dev, 1);
+ retval = cdev_device_add(&raw->cdev, &raw->dev);
if (retval)
goto error_connection_disable;
- raw->device = device_create(&raw_class, &connection->bundle->dev,
- raw->dev, raw, "gb!raw%d", minor);
- if (IS_ERR(raw->device)) {
- retval = PTR_ERR(raw->device);
- goto error_del_cdev;
- }
-
return 0;
-error_del_cdev:
- cdev_del(&raw->cdev);
-
error_connection_disable:
gb_connection_disable(connection);
-error_remove_ida:
- ida_free(&minors, minor);
-
error_connection_destroy:
gb_connection_destroy(connection);
-error_free:
- kfree(raw);
+error_put_device:
+ put_device(&raw->dev);
return retval;
}
struct raw_data *raw_data;
struct raw_data *temp;
- // FIXME - handle removing a connection when the char device node is open.
- device_destroy(&raw_class, raw->dev);
- cdev_del(&raw->cdev);
+ cdev_device_del(&raw->cdev, &raw->dev);
gb_connection_disable(connection);
- ida_free(&minors, MINOR(raw->dev));
gb_connection_destroy(connection);
mutex_lock(&raw->list_lock);
kfree(raw_data);
}
mutex_unlock(&raw->list_lock);
-
- kfree(raw);
+ put_device(&raw->dev);
}
/*