diff options
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r-- | drivers/mmc/core/debugfs.c | 2 | ||||
-rw-r--r-- | drivers/mmc/core/sdio_cis.c | 72 |
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 | ||
243 | static struct file_operations mmc_dbg_ext_csd_fops = { | 243 | static 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] = | |||
98 | static const unsigned int speed_unit[8] = | 97 | static 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 */ | ||
101 | static const unsigned char funce_type_whitelist[] = { | ||
102 | 4 /* CISTPL_FUNCE_LAN_NODE_ID used in Broadcom cards */ | ||
103 | }; | ||
104 | |||
105 | static 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 | |||
101 | static int cistpl_funce_common(struct mmc_card *card, | 116 | static 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 | ||
166 | typedef int (tpl_parse_t)(struct mmc_card *, struct sdio_func *, | 184 | typedef 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; |