diff options
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/cistpl.c | 155 |
1 files changed, 81 insertions, 74 deletions
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 41ec7729eddc..04bf1ba607f7 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c | |||
@@ -1577,88 +1577,95 @@ next_entry: | |||
1577 | EXPORT_SYMBOL(pccard_loop_tuple); | 1577 | EXPORT_SYMBOL(pccard_loop_tuple); |
1578 | 1578 | ||
1579 | 1579 | ||
1580 | /*====================================================================== | 1580 | /** |
1581 | 1581 | * pccard_validate_cis() - check whether card has a sensible CIS | |
1582 | This tries to determine if a card has a sensible CIS. It returns | 1582 | * @s: the struct pcmcia_socket we are to check |
1583 | the number of tuples in the CIS, or 0 if the CIS looks bad. The | 1583 | * @info: returns the number of tuples in the (valid) CIS, or 0 |
1584 | checks include making sure several critical tuples are present and | 1584 | * |
1585 | valid; seeing if the total number of tuples is reasonable; and | 1585 | * This tries to determine if a card has a sensible CIS. In @info, it |
1586 | looking for tuples that use reserved codes. | 1586 | * returns the number of tuples in the CIS, or 0 if the CIS looks bad. The |
1587 | 1587 | * checks include making sure several critical tuples are present and | |
1588 | ======================================================================*/ | 1588 | * valid; seeing if the total number of tuples is reasonable; and |
1589 | 1589 | * looking for tuples that use reserved codes. | |
1590 | * | ||
1591 | * The function returns 0 on success. | ||
1592 | */ | ||
1590 | int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info) | 1593 | int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info) |
1591 | { | 1594 | { |
1592 | tuple_t *tuple; | 1595 | tuple_t *tuple; |
1593 | cisparse_t *p; | 1596 | cisparse_t *p; |
1594 | unsigned int count = 0; | 1597 | unsigned int count = 0; |
1595 | int ret, reserved, dev_ok = 0, ident_ok = 0; | 1598 | int ret, reserved, dev_ok = 0, ident_ok = 0; |
1596 | 1599 | ||
1597 | if (!s) | 1600 | if (!s) |
1598 | return -EINVAL; | 1601 | return -EINVAL; |
1599 | 1602 | ||
1600 | /* We do not want to validate the CIS cache... */ | 1603 | /* We do not want to validate the CIS cache... */ |
1601 | destroy_cis_cache(s); | 1604 | destroy_cis_cache(s); |
1602 | 1605 | ||
1603 | tuple = kmalloc(sizeof(*tuple), GFP_KERNEL); | 1606 | tuple = kmalloc(sizeof(*tuple), GFP_KERNEL); |
1604 | if (tuple == NULL) { | 1607 | if (tuple == NULL) { |
1605 | dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n"); | 1608 | dev_warn(&s->dev, "no memory to validate CIS\n"); |
1606 | return -ENOMEM; | 1609 | return -ENOMEM; |
1607 | } | 1610 | } |
1608 | p = kmalloc(sizeof(*p), GFP_KERNEL); | 1611 | p = kmalloc(sizeof(*p), GFP_KERNEL); |
1609 | if (p == NULL) { | 1612 | if (p == NULL) { |
1610 | kfree(tuple); | 1613 | kfree(tuple); |
1611 | dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n"); | 1614 | dev_warn(&s->dev, "no memory to validate CIS\n"); |
1612 | return -ENOMEM; | 1615 | return -ENOMEM; |
1613 | } | 1616 | } |
1614 | 1617 | ||
1615 | count = reserved = 0; | 1618 | count = reserved = 0; |
1616 | tuple->DesiredTuple = RETURN_FIRST_TUPLE; | 1619 | tuple->DesiredTuple = RETURN_FIRST_TUPLE; |
1617 | tuple->Attributes = TUPLE_RETURN_COMMON; | 1620 | tuple->Attributes = TUPLE_RETURN_COMMON; |
1618 | ret = pccard_get_first_tuple(s, BIND_FN_ALL, tuple); | 1621 | ret = pccard_get_first_tuple(s, BIND_FN_ALL, tuple); |
1619 | if (ret != 0) | ||
1620 | goto done; | ||
1621 | |||
1622 | /* First tuple should be DEVICE; we should really have either that | ||
1623 | or a CFTABLE_ENTRY of some sort */ | ||
1624 | if ((tuple->TupleCode == CISTPL_DEVICE) || | ||
1625 | (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY, p) == 0) || | ||
1626 | (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY_CB, p) == 0)) | ||
1627 | dev_ok++; | ||
1628 | |||
1629 | /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2 | ||
1630 | tuple, for card identification. Certain old D-Link and Linksys | ||
1631 | cards have only a broken VERS_2 tuple; hence the bogus test. */ | ||
1632 | if ((pccard_read_tuple(s, BIND_FN_ALL, CISTPL_MANFID, p) == 0) || | ||
1633 | (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_1, p) == 0) || | ||
1634 | (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_2, p) != -ENOSPC)) | ||
1635 | ident_ok++; | ||
1636 | |||
1637 | if (!dev_ok && !ident_ok) | ||
1638 | goto done; | ||
1639 | |||
1640 | for (count = 1; count < MAX_TUPLES; count++) { | ||
1641 | ret = pccard_get_next_tuple(s, BIND_FN_ALL, tuple); | ||
1642 | if (ret != 0) | 1622 | if (ret != 0) |
1643 | break; | 1623 | goto done; |
1644 | if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) || | 1624 | |
1645 | ((tuple->TupleCode > 0x47) && (tuple->TupleCode < 0x80)) || | 1625 | /* First tuple should be DEVICE; we should really have either that |
1646 | ((tuple->TupleCode > 0x90) && (tuple->TupleCode < 0xff))) | 1626 | or a CFTABLE_ENTRY of some sort */ |
1647 | reserved++; | 1627 | if ((tuple->TupleCode == CISTPL_DEVICE) || |
1648 | } | 1628 | (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY, p)) || |
1649 | if ((count == MAX_TUPLES) || (reserved > 5) || | 1629 | (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY_CB, p))) |
1650 | ((!dev_ok || !ident_ok) && (count > 10))) | 1630 | dev_ok++; |
1651 | count = 0; | 1631 | |
1632 | /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2 | ||
1633 | tuple, for card identification. Certain old D-Link and Linksys | ||
1634 | cards have only a broken VERS_2 tuple; hence the bogus test. */ | ||
1635 | if ((pccard_read_tuple(s, BIND_FN_ALL, CISTPL_MANFID, p) == 0) || | ||
1636 | (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_1, p) == 0) || | ||
1637 | (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_2, p) != -ENOSPC)) | ||
1638 | ident_ok++; | ||
1639 | |||
1640 | if (!dev_ok && !ident_ok) | ||
1641 | goto done; | ||
1642 | |||
1643 | for (count = 1; count < MAX_TUPLES; count++) { | ||
1644 | ret = pccard_get_next_tuple(s, BIND_FN_ALL, tuple); | ||
1645 | if (ret != 0) | ||
1646 | break; | ||
1647 | if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) || | ||
1648 | ((tuple->TupleCode > 0x47) && (tuple->TupleCode < 0x80)) || | ||
1649 | ((tuple->TupleCode > 0x90) && (tuple->TupleCode < 0xff))) | ||
1650 | reserved++; | ||
1651 | } | ||
1652 | if ((count == MAX_TUPLES) || (reserved > 5) || | ||
1653 | ((!dev_ok || !ident_ok) && (count > 10))) | ||
1654 | count = 0; | ||
1655 | |||
1656 | ret = 0; | ||
1652 | 1657 | ||
1653 | done: | 1658 | done: |
1654 | /* invalidate CIS cache on failure */ | 1659 | /* invalidate CIS cache on failure */ |
1655 | if (!dev_ok || !ident_ok || !count) | 1660 | if (!dev_ok || !ident_ok || !count) { |
1656 | destroy_cis_cache(s); | 1661 | destroy_cis_cache(s); |
1657 | 1662 | ret = -EIO; | |
1658 | if (info) | 1663 | } |
1659 | *info = count; | 1664 | |
1660 | kfree(tuple); | 1665 | if (info) |
1661 | kfree(p); | 1666 | *info = count; |
1662 | return 0; | 1667 | kfree(tuple); |
1668 | kfree(p); | ||
1669 | return ret; | ||
1663 | } | 1670 | } |
1664 | EXPORT_SYMBOL(pccard_validate_cis); | 1671 | EXPORT_SYMBOL(pccard_validate_cis); |