diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2012-05-01 10:51:38 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2012-07-21 00:02:17 -0400 |
commit | a7d1a1ebd8f5858a812ac3d5fbbc178b4959a63b (patch) | |
tree | b96e8522469e2b228a265db89a9d2bc8f0b5e390 /drivers | |
parent | befe4048d8d20483a62636e20f3dbffebf85a1c1 (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/core/host.c | 2 | ||||
-rw-r--r-- | drivers/mmc/core/slot-gpio.c | 51 |
2 files changed, 40 insertions, 13 deletions
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index b8c5290571f1..74cf29a504f4 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c | |||
@@ -32,6 +32,7 @@ | |||
32 | static void mmc_host_classdev_release(struct device *dev) | 32 | static void mmc_host_classdev_release(struct device *dev) |
33 | { | 33 | { |
34 | struct mmc_host *host = cls_dev_to_mmc_host(dev); | 34 | struct mmc_host *host = cls_dev_to_mmc_host(dev); |
35 | mutex_destroy(&host->slot.lock); | ||
35 | kfree(host); | 36 | kfree(host); |
36 | } | 37 | } |
37 | 38 | ||
@@ -327,6 +328,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) | |||
327 | 328 | ||
328 | mmc_host_clk_init(host); | 329 | mmc_host_clk_init(host); |
329 | 330 | ||
331 | mutex_init(&host->slot.lock); | ||
330 | host->slot.cd_irq = -EINVAL; | 332 | host->slot.cd_irq = -EINVAL; |
331 | 333 | ||
332 | spin_lock_init(&host->lock); | 334 | spin_lock_init(&host->lock); |
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 92cba02c04be..41689da14b8d 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c | |||
@@ -29,6 +29,34 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) | |||
29 | return IRQ_HANDLED; | 29 | return IRQ_HANDLED; |
30 | } | 30 | } |
31 | 31 | ||
32 | static int mmc_gpio_alloc(struct mmc_host *host) | ||
33 | { | ||
34 | size_t len = strlen(dev_name(host->parent)) + 4; | ||
35 | struct mmc_gpio *ctx; | ||
36 | |||
37 | mutex_lock(&host->slot.lock); | ||
38 | |||
39 | ctx = host->slot.handler_priv; | ||
40 | if (!ctx) { | ||
41 | /* | ||
42 | * devm_kzalloc() can be called after device_initialize(), even | ||
43 | * before device_add(), i.e., between mmc_alloc_host() and | ||
44 | * mmc_add_host() | ||
45 | */ | ||
46 | ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + len, | ||
47 | GFP_KERNEL); | ||
48 | if (ctx) { | ||
49 | snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); | ||
50 | ctx->cd_gpio = -EINVAL; | ||
51 | host->slot.handler_priv = ctx; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | mutex_unlock(&host->slot.lock); | ||
56 | |||
57 | return ctx ? 0 : -ENOMEM; | ||
58 | } | ||
59 | |||
32 | int mmc_gpio_get_cd(struct mmc_host *host) | 60 | int mmc_gpio_get_cd(struct mmc_host *host) |
33 | { | 61 | { |
34 | struct mmc_gpio *ctx = host->slot.handler_priv; | 62 | struct mmc_gpio *ctx = host->slot.handler_priv; |
@@ -43,20 +71,24 @@ EXPORT_SYMBOL(mmc_gpio_get_cd); | |||
43 | 71 | ||
44 | int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) | 72 | int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) |
45 | { | 73 | { |
46 | size_t len = strlen(dev_name(host->parent)) + 4; | ||
47 | struct mmc_gpio *ctx; | 74 | struct mmc_gpio *ctx; |
48 | int irq = gpio_to_irq(gpio); | 75 | int irq = gpio_to_irq(gpio); |
49 | int ret; | 76 | int ret; |
50 | 77 | ||
51 | ctx = kmalloc(sizeof(*ctx) + len, GFP_KERNEL); | 78 | ret = mmc_gpio_alloc(host); |
52 | if (!ctx) | 79 | if (ret < 0) |
53 | return -ENOMEM; | 80 | return ret; |
54 | 81 | ||
55 | snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); | 82 | ctx = host->slot.handler_priv; |
56 | 83 | ||
57 | ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label); | 84 | ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label); |
58 | if (ret < 0) | 85 | if (ret < 0) |
59 | goto egpioreq; | 86 | /* |
87 | * don't bother freeing memory. It might still get used by other | ||
88 | * slot functions, in any case it will be freed, when the device | ||
89 | * is destroyed. | ||
90 | */ | ||
91 | return ret; | ||
60 | 92 | ||
61 | /* | 93 | /* |
62 | * Even if gpio_to_irq() returns a valid IRQ number, the platform might | 94 | * 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) | |||
80 | host->caps |= MMC_CAP_NEEDS_POLL; | 112 | host->caps |= MMC_CAP_NEEDS_POLL; |
81 | 113 | ||
82 | ctx->cd_gpio = gpio; | 114 | ctx->cd_gpio = gpio; |
83 | host->slot.handler_priv = ctx; | ||
84 | 115 | ||
85 | return 0; | 116 | return 0; |
86 | |||
87 | egpioreq: | ||
88 | kfree(ctx); | ||
89 | return ret; | ||
90 | } | 117 | } |
91 | EXPORT_SYMBOL(mmc_gpio_request_cd); | 118 | EXPORT_SYMBOL(mmc_gpio_request_cd); |
92 | 119 | ||
@@ -107,7 +134,5 @@ void mmc_gpio_free_cd(struct mmc_host *host) | |||
107 | ctx->cd_gpio = -EINVAL; | 134 | ctx->cd_gpio = -EINVAL; |
108 | 135 | ||
109 | gpio_free(gpio); | 136 | gpio_free(gpio); |
110 | host->slot.handler_priv = NULL; | ||
111 | kfree(ctx); | ||
112 | } | 137 | } |
113 | EXPORT_SYMBOL(mmc_gpio_free_cd); | 138 | EXPORT_SYMBOL(mmc_gpio_free_cd); |