Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a218ceb authored by Carlos Chinea's avatar Carlos Chinea
Browse files

HSI: hsi: Rework hsi_controller release



Use the proper release mechanism for hsi_controller and
hsi_ports structures. Free the structures through their
associated device release callbacks.

Signed-off-by: default avatarCarlos Chinea <carlos.chinea@nokia.com>
Acked-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 66f75a5d
Loading
Loading
Loading
Loading
+66 −42
Original line number Diff line number Diff line
@@ -140,12 +140,17 @@ static int hsi_remove_port(struct device *dev, void *data __maybe_unused)
	return 0;
}

static void hsi_controller_release(struct device *dev __maybe_unused)
static void hsi_controller_release(struct device *dev)
{
	struct hsi_controller *hsi = to_hsi_controller(dev);

	kfree(hsi->port);
	kfree(hsi);
}

static void hsi_port_release(struct device *dev __maybe_unused)
static void hsi_port_release(struct device *dev)
{
	kfree(to_hsi_port(dev));
}

/**
@@ -172,18 +177,14 @@ int hsi_register_controller(struct hsi_controller *hsi)

	hsi->device.type = &hsi_ctrl;
	hsi->device.bus = &hsi_bus_type;
	hsi->device.release = hsi_controller_release;
	err = device_register(&hsi->device);
	err = device_add(&hsi->device);
	if (err < 0)
		return err;
	for (i = 0; i < hsi->num_ports; i++) {
		hsi->port[i].device.parent = &hsi->device;
		hsi->port[i].device.bus = &hsi_bus_type;
		hsi->port[i].device.release = hsi_port_release;
		hsi->port[i].device.type = &hsi_port;
		INIT_LIST_HEAD(&hsi->port[i].clients);
		spin_lock_init(&hsi->port[i].clock);
		err = device_register(&hsi->port[i].device);
		hsi->port[i]->device.parent = &hsi->device;
		hsi->port[i]->device.bus = &hsi_bus_type;
		hsi->port[i]->device.type = &hsi_port;
		err = device_add(&hsi->port[i]->device);
		if (err < 0)
			goto out;
	}
@@ -192,7 +193,9 @@ int hsi_register_controller(struct hsi_controller *hsi)

	return 0;
out:
	hsi_unregister_controller(hsi);
	while (i-- > 0)
		device_del(&hsi->port[i]->device);
	device_del(&hsi->device);

	return err;
}
@@ -222,6 +225,29 @@ static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)
	return 0;
}

/**
 * hsi_put_controller - Free an HSI controller
 *
 * @hsi: Pointer to the HSI controller to freed
 *
 * HSI controller drivers should only use this function if they need
 * to free their allocated hsi_controller structures before a successful
 * call to hsi_register_controller. Other use is not allowed.
 */
void hsi_put_controller(struct hsi_controller *hsi)
{
	unsigned int i;

	if (!hsi)
		return;

	for (i = 0; i < hsi->num_ports; i++)
		if (hsi->port && hsi->port[i])
			put_device(&hsi->port[i]->device);
	put_device(&hsi->device);
}
EXPORT_SYMBOL_GPL(hsi_put_controller);

/**
 * hsi_alloc_controller - Allocate an HSI controller and its ports
 * @n_ports: Number of ports on the HSI controller
@@ -232,54 +258,52 @@ static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)
struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags)
{
	struct hsi_controller	*hsi;
	struct hsi_port		*port;
	struct hsi_port		**port;
	unsigned int		i;

	if (!n_ports)
		return NULL;

	port = kzalloc(sizeof(*port)*n_ports, flags);
	if (!port)
		return NULL;
	hsi = kzalloc(sizeof(*hsi), flags);
	if (!hsi)
		goto out;
	for (i = 0; i < n_ports; i++) {
		dev_set_name(&port[i].device, "port%d", i);
		port[i].num = i;
		port[i].async = hsi_dummy_msg;
		port[i].setup = hsi_dummy_cl;
		port[i].flush = hsi_dummy_cl;
		port[i].start_tx = hsi_dummy_cl;
		port[i].stop_tx = hsi_dummy_cl;
		port[i].release = hsi_dummy_cl;
		mutex_init(&port[i].lock);
		return NULL;
	port = kzalloc(sizeof(*port)*n_ports, flags);
	if (!port) {
		kfree(hsi);
		return NULL;
	}
	hsi->num_ports = n_ports;
	hsi->port = port;
	hsi->device.release = hsi_controller_release;
	device_initialize(&hsi->device);

	for (i = 0; i < n_ports; i++) {
		port[i] = kzalloc(sizeof(**port), flags);
		if (port[i] == NULL)
			goto out;
		port[i]->num = i;
		port[i]->async = hsi_dummy_msg;
		port[i]->setup = hsi_dummy_cl;
		port[i]->flush = hsi_dummy_cl;
		port[i]->start_tx = hsi_dummy_cl;
		port[i]->stop_tx = hsi_dummy_cl;
		port[i]->release = hsi_dummy_cl;
		mutex_init(&port[i]->lock);
		INIT_LIST_HEAD(&hsi->port[i]->clients);
		spin_lock_init(&hsi->port[i]->clock);
		dev_set_name(&port[i]->device, "port%d", i);
		hsi->port[i]->device.release = hsi_port_release;
		device_initialize(&hsi->port[i]->device);
	}

	return hsi;
out:
	kfree(port);
	hsi_put_controller(hsi);

	return NULL;
}
EXPORT_SYMBOL_GPL(hsi_alloc_controller);

/**
 * hsi_free_controller - Free an HSI controller
 * @hsi: Pointer to HSI controller
 */
void hsi_free_controller(struct hsi_controller *hsi)
{
	if (!hsi)
		return;

	kfree(hsi->port);
	kfree(hsi);
}
EXPORT_SYMBOL_GPL(hsi_free_controller);

/**
 * hsi_free_msg - Free an HSI message
 * @msg: Pointer to the HSI message
+3 −3
Original line number Diff line number Diff line
@@ -270,13 +270,13 @@ struct hsi_controller {
	struct module		*owner;
	unsigned int		id;
	unsigned int		num_ports;
	struct hsi_port		*port;
	struct hsi_port		**port;
};

#define to_hsi_controller(dev) container_of(dev, struct hsi_controller, device)

struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags);
void hsi_free_controller(struct hsi_controller *hsi);
void hsi_put_controller(struct hsi_controller *hsi);
int hsi_register_controller(struct hsi_controller *hsi);
void hsi_unregister_controller(struct hsi_controller *hsi);

@@ -294,7 +294,7 @@ static inline void *hsi_controller_drvdata(struct hsi_controller *hsi)
static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi,
							unsigned int num)
{
	return (num < hsi->num_ports) ? &hsi->port[num] : NULL;
	return (num < hsi->num_ports) ? hsi->port[num] : NULL;
}

/*