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

Commit a7d1a1eb authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Chris Ball
Browse files

mmc: core: convert slot functions to managed allocation



This prepares for the addition of further slot functions.

Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent befe4048
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
static void mmc_host_classdev_release(struct device *dev)
{
	struct mmc_host *host = cls_dev_to_mmc_host(dev);
	mutex_destroy(&host->slot.lock);
	kfree(host);
}

@@ -327,6 +328,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)

	mmc_host_clk_init(host);

	mutex_init(&host->slot.lock);
	host->slot.cd_irq = -EINVAL;

	spin_lock_init(&host->lock);
+38 −13
Original line number Diff line number Diff line
@@ -29,6 +29,34 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
	return IRQ_HANDLED;
}

static int mmc_gpio_alloc(struct mmc_host *host)
{
	size_t len = strlen(dev_name(host->parent)) + 4;
	struct mmc_gpio *ctx;

	mutex_lock(&host->slot.lock);

	ctx = host->slot.handler_priv;
	if (!ctx) {
		/*
		 * devm_kzalloc() can be called after device_initialize(), even
		 * before device_add(), i.e., between mmc_alloc_host() and
		 * mmc_add_host()
		 */
		ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + len,
				   GFP_KERNEL);
		if (ctx) {
			snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
			ctx->cd_gpio = -EINVAL;
			host->slot.handler_priv = ctx;
		}
	}

	mutex_unlock(&host->slot.lock);

	return ctx ? 0 : -ENOMEM;
}

int mmc_gpio_get_cd(struct mmc_host *host)
{
	struct mmc_gpio *ctx = host->slot.handler_priv;
@@ -43,20 +71,24 @@ EXPORT_SYMBOL(mmc_gpio_get_cd);

int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
{
	size_t len = strlen(dev_name(host->parent)) + 4;
	struct mmc_gpio *ctx;
	int irq = gpio_to_irq(gpio);
	int ret;

	ctx = kmalloc(sizeof(*ctx) + len, GFP_KERNEL);
	if (!ctx)
		return -ENOMEM;
	ret = mmc_gpio_alloc(host);
	if (ret < 0)
		return ret;

	snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
	ctx = host->slot.handler_priv;

	ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label);
	if (ret < 0)
		goto egpioreq;
		/*
		 * don't bother freeing memory. It might still get used by other
		 * slot functions, in any case it will be freed, when the device
		 * is destroyed.
		 */
		return ret;

	/*
	 * Even if gpio_to_irq() returns a valid IRQ number, the platform might
@@ -80,13 +112,8 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
		host->caps |= MMC_CAP_NEEDS_POLL;

	ctx->cd_gpio = gpio;
	host->slot.handler_priv = ctx;

	return 0;

egpioreq:
	kfree(ctx);
	return ret;
}
EXPORT_SYMBOL(mmc_gpio_request_cd);

@@ -107,7 +134,5 @@ void mmc_gpio_free_cd(struct mmc_host *host)
	ctx->cd_gpio = -EINVAL;

	gpio_free(gpio);
	host->slot.handler_priv = NULL;
	kfree(ctx);
}
EXPORT_SYMBOL(mmc_gpio_free_cd);
+3 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#define LINUX_MMC_HOST_H

#include <linux/leds.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/device.h>
#include <linux/fault-inject.h>
@@ -154,6 +155,7 @@ struct mmc_async_req {
 * struct mmc_slot - MMC slot functions
 *
 * @cd_irq:		MMC/SD-card slot hotplug detection IRQ or -EINVAL
 * @lock:		protect the @handler_priv pointer
 * @handler_priv:	MMC/SD-card slot context
 *
 * Some MMC/SD host controllers implement slot-functions like card and
@@ -163,6 +165,7 @@ struct mmc_async_req {
 */
struct mmc_slot {
	int cd_irq;
	struct mutex lock;
	void *handler_priv;
};