diff options
Diffstat (limited to 'drivers/pcmcia/cistpl.c')
-rw-r--r-- | drivers/pcmcia/cistpl.c | 134 |
1 files changed, 18 insertions, 116 deletions
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index f230f6543bff..8844bc3e3118 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c | |||
@@ -129,6 +129,8 @@ static void __iomem *set_cis_map(struct pcmcia_socket *s, | |||
129 | 129 | ||
130 | /** | 130 | /** |
131 | * pcmcia_read_cis_mem() - low-level function to read CIS memory | 131 | * pcmcia_read_cis_mem() - low-level function to read CIS memory |
132 | * | ||
133 | * must be called with ops_mutex held | ||
132 | */ | 134 | */ |
133 | int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | 135 | int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, |
134 | u_int len, void *ptr) | 136 | u_int len, void *ptr) |
@@ -138,7 +140,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
138 | 140 | ||
139 | dev_dbg(&s->dev, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len); | 141 | dev_dbg(&s->dev, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len); |
140 | 142 | ||
141 | mutex_lock(&s->ops_mutex); | ||
142 | if (attr & IS_INDIRECT) { | 143 | if (attr & IS_INDIRECT) { |
143 | /* Indirect accesses use a bunch of special registers at fixed | 144 | /* Indirect accesses use a bunch of special registers at fixed |
144 | locations in common memory */ | 145 | locations in common memory */ |
@@ -153,7 +154,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
153 | if (!sys) { | 154 | if (!sys) { |
154 | dev_dbg(&s->dev, "could not map memory\n"); | 155 | dev_dbg(&s->dev, "could not map memory\n"); |
155 | memset(ptr, 0xff, len); | 156 | memset(ptr, 0xff, len); |
156 | mutex_unlock(&s->ops_mutex); | ||
157 | return -1; | 157 | return -1; |
158 | } | 158 | } |
159 | 159 | ||
@@ -184,7 +184,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
184 | if (!sys) { | 184 | if (!sys) { |
185 | dev_dbg(&s->dev, "could not map memory\n"); | 185 | dev_dbg(&s->dev, "could not map memory\n"); |
186 | memset(ptr, 0xff, len); | 186 | memset(ptr, 0xff, len); |
187 | mutex_unlock(&s->ops_mutex); | ||
188 | return -1; | 187 | return -1; |
189 | } | 188 | } |
190 | end = sys + s->map_size; | 189 | end = sys + s->map_size; |
@@ -198,7 +197,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
198 | addr = 0; | 197 | addr = 0; |
199 | } | 198 | } |
200 | } | 199 | } |
201 | mutex_unlock(&s->ops_mutex); | ||
202 | dev_dbg(&s->dev, " %#2.2x %#2.2x %#2.2x %#2.2x ...\n", | 200 | dev_dbg(&s->dev, " %#2.2x %#2.2x %#2.2x %#2.2x ...\n", |
203 | *(u_char *)(ptr+0), *(u_char *)(ptr+1), | 201 | *(u_char *)(ptr+0), *(u_char *)(ptr+1), |
204 | *(u_char *)(ptr+2), *(u_char *)(ptr+3)); | 202 | *(u_char *)(ptr+2), *(u_char *)(ptr+3)); |
@@ -209,7 +207,8 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
209 | /** | 207 | /** |
210 | * pcmcia_write_cis_mem() - low-level function to write CIS memory | 208 | * pcmcia_write_cis_mem() - low-level function to write CIS memory |
211 | * | 209 | * |
212 | * Probably only useful for writing one-byte registers. | 210 | * Probably only useful for writing one-byte registers. Must be called |
211 | * with ops_mutex held. | ||
213 | */ | 212 | */ |
214 | void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | 213 | void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, |
215 | u_int len, void *ptr) | 214 | u_int len, void *ptr) |
@@ -220,7 +219,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
220 | dev_dbg(&s->dev, | 219 | dev_dbg(&s->dev, |
221 | "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len); | 220 | "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len); |
222 | 221 | ||
223 | mutex_lock(&s->ops_mutex); | ||
224 | if (attr & IS_INDIRECT) { | 222 | if (attr & IS_INDIRECT) { |
225 | /* Indirect accesses use a bunch of special registers at fixed | 223 | /* Indirect accesses use a bunch of special registers at fixed |
226 | locations in common memory */ | 224 | locations in common memory */ |
@@ -234,7 +232,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
234 | ((cis_width) ? MAP_16BIT : 0)); | 232 | ((cis_width) ? MAP_16BIT : 0)); |
235 | if (!sys) { | 233 | if (!sys) { |
236 | dev_dbg(&s->dev, "could not map memory\n"); | 234 | dev_dbg(&s->dev, "could not map memory\n"); |
237 | mutex_unlock(&s->ops_mutex); | ||
238 | return; /* FIXME: Error */ | 235 | return; /* FIXME: Error */ |
239 | } | 236 | } |
240 | 237 | ||
@@ -260,7 +257,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
260 | sys = set_cis_map(s, card_offset, flags); | 257 | sys = set_cis_map(s, card_offset, flags); |
261 | if (!sys) { | 258 | if (!sys) { |
262 | dev_dbg(&s->dev, "could not map memory\n"); | 259 | dev_dbg(&s->dev, "could not map memory\n"); |
263 | mutex_unlock(&s->ops_mutex); | ||
264 | return; /* FIXME: error */ | 260 | return; /* FIXME: error */ |
265 | } | 261 | } |
266 | 262 | ||
@@ -275,7 +271,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
275 | addr = 0; | 271 | addr = 0; |
276 | } | 272 | } |
277 | } | 273 | } |
278 | mutex_unlock(&s->ops_mutex); | ||
279 | } | 274 | } |
280 | 275 | ||
281 | 276 | ||
@@ -314,7 +309,6 @@ static int read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, | |||
314 | return 0; | 309 | return 0; |
315 | } | 310 | } |
316 | } | 311 | } |
317 | mutex_unlock(&s->ops_mutex); | ||
318 | 312 | ||
319 | ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr); | 313 | ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr); |
320 | 314 | ||
@@ -326,11 +320,11 @@ static int read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, | |||
326 | cis->len = len; | 320 | cis->len = len; |
327 | cis->attr = attr; | 321 | cis->attr = attr; |
328 | memcpy(cis->cache, ptr, len); | 322 | memcpy(cis->cache, ptr, len); |
329 | mutex_lock(&s->ops_mutex); | ||
330 | list_add(&cis->node, &s->cis_cache); | 323 | list_add(&cis->node, &s->cis_cache); |
331 | mutex_unlock(&s->ops_mutex); | ||
332 | } | 324 | } |
333 | } | 325 | } |
326 | mutex_unlock(&s->ops_mutex); | ||
327 | |||
334 | return ret; | 328 | return ret; |
335 | } | 329 | } |
336 | 330 | ||
@@ -386,6 +380,7 @@ int verify_cis_cache(struct pcmcia_socket *s) | |||
386 | "no memory for verifying CIS\n"); | 380 | "no memory for verifying CIS\n"); |
387 | return -ENOMEM; | 381 | return -ENOMEM; |
388 | } | 382 | } |
383 | mutex_lock(&s->ops_mutex); | ||
389 | list_for_each_entry(cis, &s->cis_cache, node) { | 384 | list_for_each_entry(cis, &s->cis_cache, node) { |
390 | int len = cis->len; | 385 | int len = cis->len; |
391 | 386 | ||
@@ -395,10 +390,12 @@ int verify_cis_cache(struct pcmcia_socket *s) | |||
395 | ret = pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf); | 390 | ret = pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf); |
396 | if (ret || memcmp(buf, cis->cache, len) != 0) { | 391 | if (ret || memcmp(buf, cis->cache, len) != 0) { |
397 | kfree(buf); | 392 | kfree(buf); |
393 | mutex_unlock(&s->ops_mutex); | ||
398 | return -1; | 394 | return -1; |
399 | } | 395 | } |
400 | } | 396 | } |
401 | kfree(buf); | 397 | kfree(buf); |
398 | mutex_unlock(&s->ops_mutex); | ||
402 | return 0; | 399 | return 0; |
403 | } | 400 | } |
404 | 401 | ||
@@ -1362,106 +1359,6 @@ EXPORT_SYMBOL(pcmcia_parse_tuple); | |||
1362 | 1359 | ||
1363 | 1360 | ||
1364 | /** | 1361 | /** |
1365 | * pccard_read_tuple() - internal CIS tuple access | ||
1366 | * @s: the struct pcmcia_socket where the card is inserted | ||
1367 | * @function: the device function we loop for | ||
1368 | * @code: which CIS code shall we look for? | ||
1369 | * @parse: buffer where the tuple shall be parsed (or NULL, if no parse) | ||
1370 | * | ||
1371 | * pccard_read_tuple() reads out one tuple and attempts to parse it | ||
1372 | */ | ||
1373 | int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, | ||
1374 | cisdata_t code, void *parse) | ||
1375 | { | ||
1376 | tuple_t tuple; | ||
1377 | cisdata_t *buf; | ||
1378 | int ret; | ||
1379 | |||
1380 | buf = kmalloc(256, GFP_KERNEL); | ||
1381 | if (buf == NULL) { | ||
1382 | dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n"); | ||
1383 | return -ENOMEM; | ||
1384 | } | ||
1385 | tuple.DesiredTuple = code; | ||
1386 | tuple.Attributes = 0; | ||
1387 | if (function == BIND_FN_ALL) | ||
1388 | tuple.Attributes = TUPLE_RETURN_COMMON; | ||
1389 | ret = pccard_get_first_tuple(s, function, &tuple); | ||
1390 | if (ret != 0) | ||
1391 | goto done; | ||
1392 | tuple.TupleData = buf; | ||
1393 | tuple.TupleOffset = 0; | ||
1394 | tuple.TupleDataMax = 255; | ||
1395 | ret = pccard_get_tuple_data(s, &tuple); | ||
1396 | if (ret != 0) | ||
1397 | goto done; | ||
1398 | ret = pcmcia_parse_tuple(&tuple, parse); | ||
1399 | done: | ||
1400 | kfree(buf); | ||
1401 | return ret; | ||
1402 | } | ||
1403 | |||
1404 | |||
1405 | /** | ||
1406 | * pccard_loop_tuple() - loop over tuples in the CIS | ||
1407 | * @s: the struct pcmcia_socket where the card is inserted | ||
1408 | * @function: the device function we loop for | ||
1409 | * @code: which CIS code shall we look for? | ||
1410 | * @parse: buffer where the tuple shall be parsed (or NULL, if no parse) | ||
1411 | * @priv_data: private data to be passed to the loop_tuple function. | ||
1412 | * @loop_tuple: function to call for each CIS entry of type @function. IT | ||
1413 | * gets passed the raw tuple, the paresed tuple (if @parse is | ||
1414 | * set) and @priv_data. | ||
1415 | * | ||
1416 | * pccard_loop_tuple() loops over all CIS entries of type @function, and | ||
1417 | * calls the @loop_tuple function for each entry. If the call to @loop_tuple | ||
1418 | * returns 0, the loop exits. Returns 0 on success or errorcode otherwise. | ||
1419 | */ | ||
1420 | int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function, | ||
1421 | cisdata_t code, cisparse_t *parse, void *priv_data, | ||
1422 | int (*loop_tuple) (tuple_t *tuple, | ||
1423 | cisparse_t *parse, | ||
1424 | void *priv_data)) | ||
1425 | { | ||
1426 | tuple_t tuple; | ||
1427 | cisdata_t *buf; | ||
1428 | int ret; | ||
1429 | |||
1430 | buf = kzalloc(256, GFP_KERNEL); | ||
1431 | if (buf == NULL) { | ||
1432 | dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n"); | ||
1433 | return -ENOMEM; | ||
1434 | } | ||
1435 | |||
1436 | tuple.TupleData = buf; | ||
1437 | tuple.TupleDataMax = 255; | ||
1438 | tuple.TupleOffset = 0; | ||
1439 | tuple.DesiredTuple = code; | ||
1440 | tuple.Attributes = 0; | ||
1441 | |||
1442 | ret = pccard_get_first_tuple(s, function, &tuple); | ||
1443 | while (!ret) { | ||
1444 | if (pccard_get_tuple_data(s, &tuple)) | ||
1445 | goto next_entry; | ||
1446 | |||
1447 | if (parse) | ||
1448 | if (pcmcia_parse_tuple(&tuple, parse)) | ||
1449 | goto next_entry; | ||
1450 | |||
1451 | ret = loop_tuple(&tuple, parse, priv_data); | ||
1452 | if (!ret) | ||
1453 | break; | ||
1454 | |||
1455 | next_entry: | ||
1456 | ret = pccard_get_next_tuple(s, function, &tuple); | ||
1457 | } | ||
1458 | |||
1459 | kfree(buf); | ||
1460 | return ret; | ||
1461 | } | ||
1462 | |||
1463 | |||
1464 | /** | ||
1465 | * pccard_validate_cis() - check whether card has a sensible CIS | 1362 | * pccard_validate_cis() - check whether card has a sensible CIS |
1466 | * @s: the struct pcmcia_socket we are to check | 1363 | * @s: the struct pcmcia_socket we are to check |
1467 | * @info: returns the number of tuples in the (valid) CIS, or 0 | 1364 | * @info: returns the number of tuples in the (valid) CIS, or 0 |
@@ -1484,6 +1381,11 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info) | |||
1484 | if (!s) | 1381 | if (!s) |
1485 | return -EINVAL; | 1382 | return -EINVAL; |
1486 | 1383 | ||
1384 | if (s->functions) { | ||
1385 | WARN_ON(1); | ||
1386 | return -EINVAL; | ||
1387 | } | ||
1388 | |||
1487 | /* We do not want to validate the CIS cache... */ | 1389 | /* We do not want to validate the CIS cache... */ |
1488 | mutex_lock(&s->ops_mutex); | 1390 | mutex_lock(&s->ops_mutex); |
1489 | destroy_cis_cache(s); | 1391 | destroy_cis_cache(s); |
@@ -1629,7 +1531,7 @@ static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, | |||
1629 | } | 1531 | } |
1630 | 1532 | ||
1631 | 1533 | ||
1632 | static ssize_t pccard_show_cis(struct kobject *kobj, | 1534 | static ssize_t pccard_show_cis(struct file *filp, struct kobject *kobj, |
1633 | struct bin_attribute *bin_attr, | 1535 | struct bin_attribute *bin_attr, |
1634 | char *buf, loff_t off, size_t count) | 1536 | char *buf, loff_t off, size_t count) |
1635 | { | 1537 | { |
@@ -1639,7 +1541,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, | |||
1639 | count = 0; | 1541 | count = 0; |
1640 | else { | 1542 | else { |
1641 | struct pcmcia_socket *s; | 1543 | struct pcmcia_socket *s; |
1642 | unsigned int chains; | 1544 | unsigned int chains = 1; |
1643 | 1545 | ||
1644 | if (off + count > size) | 1546 | if (off + count > size) |
1645 | count = size - off; | 1547 | count = size - off; |
@@ -1648,7 +1550,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, | |||
1648 | 1550 | ||
1649 | if (!(s->state & SOCKET_PRESENT)) | 1551 | if (!(s->state & SOCKET_PRESENT)) |
1650 | return -ENODEV; | 1552 | return -ENODEV; |
1651 | if (pccard_validate_cis(s, &chains)) | 1553 | if (!s->functions && pccard_validate_cis(s, &chains)) |
1652 | return -EIO; | 1554 | return -EIO; |
1653 | if (!chains) | 1555 | if (!chains) |
1654 | return -ENODATA; | 1556 | return -ENODATA; |
@@ -1660,7 +1562,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, | |||
1660 | } | 1562 | } |
1661 | 1563 | ||
1662 | 1564 | ||
1663 | static ssize_t pccard_store_cis(struct kobject *kobj, | 1565 | static ssize_t pccard_store_cis(struct file *filp, struct kobject *kobj, |
1664 | struct bin_attribute *bin_attr, | 1566 | struct bin_attribute *bin_attr, |
1665 | char *buf, loff_t off, size_t count) | 1567 | char *buf, loff_t off, size_t count) |
1666 | { | 1568 | { |