mmc: core: convert slot functions to managed allocation
This prepares for the addition of further slot functions. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:
committed by
Chris Ball
parent
befe4048d8
commit
a7d1a1ebd8
@@ -32,6 +32,7 @@
|
|||||||
static void mmc_host_classdev_release(struct device *dev)
|
static void mmc_host_classdev_release(struct device *dev)
|
||||||
{
|
{
|
||||||
struct mmc_host *host = cls_dev_to_mmc_host(dev);
|
struct mmc_host *host = cls_dev_to_mmc_host(dev);
|
||||||
|
mutex_destroy(&host->slot.lock);
|
||||||
kfree(host);
|
kfree(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,6 +328,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
|
|||||||
|
|
||||||
mmc_host_clk_init(host);
|
mmc_host_clk_init(host);
|
||||||
|
|
||||||
|
mutex_init(&host->slot.lock);
|
||||||
host->slot.cd_irq = -EINVAL;
|
host->slot.cd_irq = -EINVAL;
|
||||||
|
|
||||||
spin_lock_init(&host->lock);
|
spin_lock_init(&host->lock);
|
||||||
|
@@ -29,6 +29,34 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
|
|||||||
return IRQ_HANDLED;
|
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)
|
int mmc_gpio_get_cd(struct mmc_host *host)
|
||||||
{
|
{
|
||||||
struct mmc_gpio *ctx = host->slot.handler_priv;
|
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)
|
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;
|
struct mmc_gpio *ctx;
|
||||||
int irq = gpio_to_irq(gpio);
|
int irq = gpio_to_irq(gpio);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ctx = kmalloc(sizeof(*ctx) + len, GFP_KERNEL);
|
ret = mmc_gpio_alloc(host);
|
||||||
if (!ctx)
|
if (ret < 0)
|
||||||
return -ENOMEM;
|
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);
|
ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label);
|
||||||
if (ret < 0)
|
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
|
* 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;
|
host->caps |= MMC_CAP_NEEDS_POLL;
|
||||||
|
|
||||||
ctx->cd_gpio = gpio;
|
ctx->cd_gpio = gpio;
|
||||||
host->slot.handler_priv = ctx;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
egpioreq:
|
|
||||||
kfree(ctx);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mmc_gpio_request_cd);
|
EXPORT_SYMBOL(mmc_gpio_request_cd);
|
||||||
|
|
||||||
@@ -107,7 +134,5 @@ void mmc_gpio_free_cd(struct mmc_host *host)
|
|||||||
ctx->cd_gpio = -EINVAL;
|
ctx->cd_gpio = -EINVAL;
|
||||||
|
|
||||||
gpio_free(gpio);
|
gpio_free(gpio);
|
||||||
host->slot.handler_priv = NULL;
|
|
||||||
kfree(ctx);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mmc_gpio_free_cd);
|
EXPORT_SYMBOL(mmc_gpio_free_cd);
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#define LINUX_MMC_HOST_H
|
#define LINUX_MMC_HOST_H
|
||||||
|
|
||||||
#include <linux/leds.h>
|
#include <linux/leds.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/fault-inject.h>
|
#include <linux/fault-inject.h>
|
||||||
@@ -154,6 +155,7 @@ struct mmc_async_req {
|
|||||||
* struct mmc_slot - MMC slot functions
|
* struct mmc_slot - MMC slot functions
|
||||||
*
|
*
|
||||||
* @cd_irq: MMC/SD-card slot hotplug detection IRQ or -EINVAL
|
* @cd_irq: MMC/SD-card slot hotplug detection IRQ or -EINVAL
|
||||||
|
* @lock: protect the @handler_priv pointer
|
||||||
* @handler_priv: MMC/SD-card slot context
|
* @handler_priv: MMC/SD-card slot context
|
||||||
*
|
*
|
||||||
* Some MMC/SD host controllers implement slot-functions like card and
|
* Some MMC/SD host controllers implement slot-functions like card and
|
||||||
@@ -163,6 +165,7 @@ struct mmc_async_req {
|
|||||||
*/
|
*/
|
||||||
struct mmc_slot {
|
struct mmc_slot {
|
||||||
int cd_irq;
|
int cd_irq;
|
||||||
|
struct mutex lock;
|
||||||
void *handler_priv;
|
void *handler_priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user