Skip to content

Commit

Permalink
pcmcia: cleanup pccard_validate_cis()
Browse files Browse the repository at this point in the history
Cleanup pccard_validate_cis() and make it return an error code on
all failures, not merely on some failures.

Tested-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
  • Loading branch information
Dominik Brodowski committed Jan 17, 2010
1 parent 904e377 commit f131ddc
Showing 1 changed file with 81 additions and 74 deletions.
155 changes: 81 additions & 74 deletions drivers/pcmcia/cistpl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1577,88 +1577,95 @@ int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function,
EXPORT_SYMBOL(pccard_loop_tuple);


/*======================================================================
This tries to determine if a card has a sensible CIS. It returns
the number of tuples in the CIS, or 0 if the CIS looks bad. The
checks include making sure several critical tuples are present and
valid; seeing if the total number of tuples is reasonable; and
looking for tuples that use reserved codes.
======================================================================*/

/**
* pccard_validate_cis() - check whether card has a sensible CIS
* @s: the struct pcmcia_socket we are to check
* @info: returns the number of tuples in the (valid) CIS, or 0
*
* This tries to determine if a card has a sensible CIS. In @info, it
* returns the number of tuples in the CIS, or 0 if the CIS looks bad. The
* checks include making sure several critical tuples are present and
* valid; seeing if the total number of tuples is reasonable; and
* looking for tuples that use reserved codes.
*
* The function returns 0 on success.
*/
int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info)
{
tuple_t *tuple;
cisparse_t *p;
unsigned int count = 0;
int ret, reserved, dev_ok = 0, ident_ok = 0;
tuple_t *tuple;
cisparse_t *p;
unsigned int count = 0;
int ret, reserved, dev_ok = 0, ident_ok = 0;

if (!s)
return -EINVAL;
if (!s)
return -EINVAL;

/* We do not want to validate the CIS cache... */
destroy_cis_cache(s);
/* We do not want to validate the CIS cache... */
destroy_cis_cache(s);

tuple = kmalloc(sizeof(*tuple), GFP_KERNEL);
if (tuple == NULL) {
dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n");
return -ENOMEM;
}
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL) {
kfree(tuple);
dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n");
return -ENOMEM;
}
tuple = kmalloc(sizeof(*tuple), GFP_KERNEL);
if (tuple == NULL) {
dev_warn(&s->dev, "no memory to validate CIS\n");
return -ENOMEM;
}
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL) {
kfree(tuple);
dev_warn(&s->dev, "no memory to validate CIS\n");
return -ENOMEM;
}

count = reserved = 0;
tuple->DesiredTuple = RETURN_FIRST_TUPLE;
tuple->Attributes = TUPLE_RETURN_COMMON;
ret = pccard_get_first_tuple(s, BIND_FN_ALL, tuple);
if (ret != 0)
goto done;

/* First tuple should be DEVICE; we should really have either that
or a CFTABLE_ENTRY of some sort */
if ((tuple->TupleCode == CISTPL_DEVICE) ||
(pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY, p) == 0) ||
(pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY_CB, p) == 0))
dev_ok++;

/* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2
tuple, for card identification. Certain old D-Link and Linksys
cards have only a broken VERS_2 tuple; hence the bogus test. */
if ((pccard_read_tuple(s, BIND_FN_ALL, CISTPL_MANFID, p) == 0) ||
(pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_1, p) == 0) ||
(pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_2, p) != -ENOSPC))
ident_ok++;

if (!dev_ok && !ident_ok)
goto done;

for (count = 1; count < MAX_TUPLES; count++) {
ret = pccard_get_next_tuple(s, BIND_FN_ALL, tuple);
count = reserved = 0;
tuple->DesiredTuple = RETURN_FIRST_TUPLE;
tuple->Attributes = TUPLE_RETURN_COMMON;
ret = pccard_get_first_tuple(s, BIND_FN_ALL, tuple);
if (ret != 0)
break;
if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) ||
((tuple->TupleCode > 0x47) && (tuple->TupleCode < 0x80)) ||
((tuple->TupleCode > 0x90) && (tuple->TupleCode < 0xff)))
reserved++;
}
if ((count == MAX_TUPLES) || (reserved > 5) ||
((!dev_ok || !ident_ok) && (count > 10)))
count = 0;
goto done;

/* First tuple should be DEVICE; we should really have either that
or a CFTABLE_ENTRY of some sort */
if ((tuple->TupleCode == CISTPL_DEVICE) ||
(!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY, p)) ||
(!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY_CB, p)))
dev_ok++;

/* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2
tuple, for card identification. Certain old D-Link and Linksys
cards have only a broken VERS_2 tuple; hence the bogus test. */
if ((pccard_read_tuple(s, BIND_FN_ALL, CISTPL_MANFID, p) == 0) ||
(pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_1, p) == 0) ||
(pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_2, p) != -ENOSPC))
ident_ok++;

if (!dev_ok && !ident_ok)
goto done;

for (count = 1; count < MAX_TUPLES; count++) {
ret = pccard_get_next_tuple(s, BIND_FN_ALL, tuple);
if (ret != 0)
break;
if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) ||
((tuple->TupleCode > 0x47) && (tuple->TupleCode < 0x80)) ||
((tuple->TupleCode > 0x90) && (tuple->TupleCode < 0xff)))
reserved++;
}
if ((count == MAX_TUPLES) || (reserved > 5) ||
((!dev_ok || !ident_ok) && (count > 10)))
count = 0;

ret = 0;

done:
/* invalidate CIS cache on failure */
if (!dev_ok || !ident_ok || !count)
destroy_cis_cache(s);

if (info)
*info = count;
kfree(tuple);
kfree(p);
return 0;
/* invalidate CIS cache on failure */
if (!dev_ok || !ident_ok || !count) {
destroy_cis_cache(s);
ret = -EIO;
}

if (info)
*info = count;
kfree(tuple);
kfree(p);
return ret;
}
EXPORT_SYMBOL(pccard_validate_cis);

0 comments on commit f131ddc

Please sign in to comment.