aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r--drivers/mmc/core/debugfs.c2
-rw-r--r--drivers/mmc/core/sdio_cis.c72
2 files changed, 53 insertions, 21 deletions
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 610dbd1fcc82..96d10f40fb23 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -240,7 +240,7 @@ static int mmc_ext_csd_release(struct inode *inode, struct file *file)
240 return 0; 240 return 0;
241} 241}
242 242
243static struct file_operations mmc_dbg_ext_csd_fops = { 243static const struct file_operations mmc_dbg_ext_csd_fops = {
244 .open = mmc_ext_csd_open, 244 .open = mmc_ext_csd_open,
245 .read = mmc_ext_csd_read, 245 .read = mmc_ext_csd_read,
246 .release = mmc_ext_csd_release, 246 .release = mmc_ext_csd_release,
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index 6636354b48ce..f85dcd536508 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -29,6 +29,8 @@ static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func,
29 unsigned i, nr_strings; 29 unsigned i, nr_strings;
30 char **buffer, *string; 30 char **buffer, *string;
31 31
32 /* Find all null-terminated (including zero length) strings in
33 the TPLLV1_INFO field. Trailing garbage is ignored. */
32 buf += 2; 34 buf += 2;
33 size -= 2; 35 size -= 2;
34 36
@@ -39,11 +41,8 @@ static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func,
39 if (buf[i] == 0) 41 if (buf[i] == 0)
40 nr_strings++; 42 nr_strings++;
41 } 43 }
42 44 if (nr_strings == 0)
43 if (nr_strings < 4) {
44 printk(KERN_WARNING "SDIO: ignoring broken CISTPL_VERS_1\n");
45 return 0; 45 return 0;
46 }
47 46
48 size = i; 47 size = i;
49 48
@@ -98,6 +97,22 @@ static const unsigned char speed_val[16] =
98static const unsigned int speed_unit[8] = 97static const unsigned int speed_unit[8] =
99 { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 }; 98 { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 };
100 99
100/* FUNCE tuples with these types get passed to SDIO drivers */
101static const unsigned char funce_type_whitelist[] = {
102 4 /* CISTPL_FUNCE_LAN_NODE_ID used in Broadcom cards */
103};
104
105static int cistpl_funce_whitelisted(unsigned char type)
106{
107 int i;
108
109 for (i = 0; i < ARRAY_SIZE(funce_type_whitelist); i++) {
110 if (funce_type_whitelist[i] == type)
111 return 1;
112 }
113 return 0;
114}
115
101static int cistpl_funce_common(struct mmc_card *card, 116static int cistpl_funce_common(struct mmc_card *card,
102 const unsigned char *buf, unsigned size) 117 const unsigned char *buf, unsigned size)
103{ 118{
@@ -120,6 +135,10 @@ static int cistpl_funce_func(struct sdio_func *func,
120 unsigned vsn; 135 unsigned vsn;
121 unsigned min_size; 136 unsigned min_size;
122 137
138 /* let SDIO drivers take care of whitelisted FUNCE tuples */
139 if (cistpl_funce_whitelisted(buf[0]))
140 return -EILSEQ;
141
123 vsn = func->card->cccr.sdio_vsn; 142 vsn = func->card->cccr.sdio_vsn;
124 min_size = (vsn == SDIO_SDIO_REV_1_00) ? 28 : 42; 143 min_size = (vsn == SDIO_SDIO_REV_1_00) ? 28 : 42;
125 144
@@ -154,13 +173,12 @@ static int cistpl_funce(struct mmc_card *card, struct sdio_func *func,
154 else 173 else
155 ret = cistpl_funce_common(card, buf, size); 174 ret = cistpl_funce_common(card, buf, size);
156 175
157 if (ret) { 176 if (ret && ret != -EILSEQ) {
158 printk(KERN_ERR "%s: bad CISTPL_FUNCE size %u " 177 printk(KERN_ERR "%s: bad CISTPL_FUNCE size %u "
159 "type %u\n", mmc_hostname(card->host), size, buf[0]); 178 "type %u\n", mmc_hostname(card->host), size, buf[0]);
160 return ret;
161 } 179 }
162 180
163 return 0; 181 return ret;
164} 182}
165 183
166typedef int (tpl_parse_t)(struct mmc_card *, struct sdio_func *, 184typedef int (tpl_parse_t)(struct mmc_card *, struct sdio_func *,
@@ -253,21 +271,12 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
253 for (i = 0; i < ARRAY_SIZE(cis_tpl_list); i++) 271 for (i = 0; i < ARRAY_SIZE(cis_tpl_list); i++)
254 if (cis_tpl_list[i].code == tpl_code) 272 if (cis_tpl_list[i].code == tpl_code)
255 break; 273 break;
256 if (i >= ARRAY_SIZE(cis_tpl_list)) { 274 if (i < ARRAY_SIZE(cis_tpl_list)) {
257 /* this tuple is unknown to the core */
258 this->next = NULL;
259 this->code = tpl_code;
260 this->size = tpl_link;
261 *prev = this;
262 prev = &this->next;
263 printk(KERN_DEBUG
264 "%s: queuing CIS tuple 0x%02x length %u\n",
265 mmc_hostname(card->host), tpl_code, tpl_link);
266 } else {
267 const struct cis_tpl *tpl = cis_tpl_list + i; 275 const struct cis_tpl *tpl = cis_tpl_list + i;
268 if (tpl_link < tpl->min_size) { 276 if (tpl_link < tpl->min_size) {
269 printk(KERN_ERR 277 printk(KERN_ERR
270 "%s: bad CIS tuple 0x%02x (length = %u, expected >= %u)\n", 278 "%s: bad CIS tuple 0x%02x"
279 " (length = %u, expected >= %u)\n",
271 mmc_hostname(card->host), 280 mmc_hostname(card->host),
272 tpl_code, tpl_link, tpl->min_size); 281 tpl_code, tpl_link, tpl->min_size);
273 ret = -EINVAL; 282 ret = -EINVAL;
@@ -275,7 +284,30 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
275 ret = tpl->parse(card, func, 284 ret = tpl->parse(card, func,
276 this->data, tpl_link); 285 this->data, tpl_link);
277 } 286 }
278 kfree(this); 287 /*
288 * We don't need the tuple anymore if it was
289 * successfully parsed by the SDIO core or if it is
290 * not going to be parsed by SDIO drivers.
291 */
292 if (!ret || ret != -EILSEQ)
293 kfree(this);
294 } else {
295 /* unknown tuple */
296 ret = -EILSEQ;
297 }
298
299 if (ret == -EILSEQ) {
300 /* this tuple is unknown to the core or whitelisted */
301 this->next = NULL;
302 this->code = tpl_code;
303 this->size = tpl_link;
304 *prev = this;
305 prev = &this->next;
306 printk(KERN_DEBUG
307 "%s: queuing CIS tuple 0x%02x length %u\n",
308 mmc_hostname(card->host), tpl_code, tpl_link);
309 /* keep on analyzing tuples */
310 ret = 0;
279 } 311 }
280 312
281 ptr += tpl_link; 313 ptr += tpl_link;