diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 1cc11714916f99c79e5fef1919f216319bfd0f02..733ac95331c733ce10e2ae27944d43375accc533 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 683d91740109ebfe9a5b6bd22b2d96b7287cfab8..0713a8c71e54b2980d88127644e14cd9ed87f748 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 1d03f12bbb38824002d90dee04533d916b0eecba..d5e51b1c7b3fb715ebc81dcad5468c572748d42e 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 a444431e28bd3cf489878e2362655255c08b209f..0d508ac17d6452b5a35429fd38704c8de2c13de4 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 da6a96c39776e022726dd01810bf3787d489db6c..b050f4d7b41f05af47bf98c342c0b4528d110e19 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; };