summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/core/bus.c3
-rw-r--r--drivers/mmc/core/sdio_bus.c3
-rw-r--r--drivers/mmc/core/sdio_cis.c50
-rw-r--r--include/linux/mmc/card.h2
-rw-r--r--include/linux/mmc/sdio_func.h3
5 files changed, 60 insertions, 1 deletions
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 1cc11714916f..733ac95331c7 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -187,6 +187,9 @@ static void mmc_release_card(struct device *dev)
sdio_free_common_cis(card);
+ if (card->info)
+ kfree(card->info);
+
kfree(card);
}
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 683d91740109..0713a8c71e54 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -211,6 +211,9 @@ static void sdio_release_func(struct device *dev)
sdio_free_func_cis(func);
+ if (func->info)
+ kfree(func->info);
+
kfree(func);
}
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index 1d03f12bbb38..d5e51b1c7b3f 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -23,6 +23,54 @@
#include "sdio_cis.h"
#include "sdio_ops.h"
+static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func,
+ const unsigned char *buf, unsigned size)
+{
+ unsigned i, nr_strings;
+ char **buffer, *string;
+
+ buf += 2;
+ size -= 2;
+
+ nr_strings = 0;
+ for (i = 0; i < size; i++) {
+ if (buf[i] == 0xff)
+ break;
+ if (buf[i] == 0)
+ nr_strings++;
+ }
+
+ if (buf[i-1] != '\0') {
+ printk(KERN_WARNING "SDIO: ignoring broken CISTPL_VERS_1\n");
+ return 0;
+ }
+
+ size = i;
+
+ buffer = kzalloc(sizeof(char*) * nr_strings + size, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ string = (char*)(buffer + nr_strings);
+
+ for (i = 0; i < nr_strings; i++) {
+ buffer[i] = string;
+ strcpy(string, buf);
+ string += strlen(string) + 1;
+ buf += strlen(buf) + 1;
+ }
+
+ if (func) {
+ func->num_info = nr_strings;
+ func->info = (const char**)buffer;
+ } else {
+ card->num_info = nr_strings;
+ card->info = (const char**)buffer;
+ }
+
+ return 0;
+}
+
static int cistpl_manfid(struct mmc_card *card, struct sdio_func *func,
const unsigned char *buf, unsigned size)
{
@@ -119,7 +167,7 @@ struct cis_tpl {
};
static const struct cis_tpl cis_tpl_list[] = {
- { 0x15, 3, /* cistpl_vers_1 */ },
+ { 0x15, 3, cistpl_vers_1 },
{ 0x20, 4, cistpl_manfid },
{ 0x21, 2, /* cistpl_funcid */ },
{ 0x22, 0, cistpl_funce },
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index a444431e28bd..0d508ac17d64 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -108,6 +108,8 @@ struct mmc_card {
struct sdio_cccr cccr; /* common card info */
struct sdio_cis cis; /* common tuple info */
struct sdio_func *sdio_func[SDIO_MAX_FUNCS]; /* SDIO functions (devices) */
+ unsigned num_info; /* number of info strings */
+ const char **info; /* info strings */
struct sdio_func_tuple *tuples; /* unknown common tuples */
};
diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
index da6a96c39776..b050f4d7b41f 100644
--- a/include/linux/mmc/sdio_func.h
+++ b/include/linux/mmc/sdio_func.h
@@ -51,6 +51,9 @@ struct sdio_func {
u8 tmpbuf[4]; /* DMA:able scratch buffer */
+ unsigned num_info; /* number of info strings */
+ const char **info; /* info strings */
+
struct sdio_func_tuple *tuples;
};