Fix multi-function card memory problems:
- centralize pcmcia function allocation and free'ing. - free the cfe too, not just the pf in the multifunction card case. - don't free pointers while walking the list, because free() will fill the memory with deadbeef, thus killing list walking.
This commit is contained in:
parent
bbe21e45f5
commit
4251568ad8
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pcmcia_cis.c,v 1.30 2002/06/01 23:51:02 lukem Exp $ */
|
||||
/* $NetBSD: pcmcia_cis.c,v 1.31 2002/08/15 10:37:02 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Marc Horowitz. All rights reserved.
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: pcmcia_cis.c,v 1.30 2002/06/01 23:51:02 lukem Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pcmcia_cis.c,v 1.31 2002/08/15 10:37:02 christos Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -61,8 +61,45 @@ struct cis_state {
|
|||
|
||||
int pcmcia_parse_cis_tuple __P((struct pcmcia_tuple *, void *));
|
||||
static int decode_funce __P((struct pcmcia_tuple *, struct pcmcia_function *));
|
||||
static void create_pf __P((struct cis_state *));
|
||||
|
||||
|
||||
static void
|
||||
create_pf(struct cis_state *state)
|
||||
{
|
||||
state->pf = malloc(sizeof(*state->pf), M_DEVBUF, M_NOWAIT|M_ZERO);
|
||||
state->pf->number = state->count++;
|
||||
state->pf->last_config_index = -1;
|
||||
SIMPLEQ_INIT(&state->pf->cfe_head);
|
||||
SIMPLEQ_INSERT_TAIL(&state->card->pf_head, state->pf, pf_list);
|
||||
}
|
||||
|
||||
void
|
||||
pcmcia_free_pf(struct pcmcia_function_head *pfhead)
|
||||
{
|
||||
struct pcmcia_function *pf, *opf = NULL;
|
||||
struct pcmcia_config_entry *cfe, *ocfe = NULL;
|
||||
|
||||
SIMPLEQ_FOREACH(pf, pfhead, pf_list) {
|
||||
SIMPLEQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
|
||||
if (ocfe)
|
||||
free(ocfe, M_DEVBUF);
|
||||
ocfe = cfe;
|
||||
}
|
||||
if (ocfe) {
|
||||
free(ocfe, M_DEVBUF);
|
||||
ocfe = NULL;
|
||||
}
|
||||
if (opf)
|
||||
free(opf, M_DEVBUF);
|
||||
opf = pf;
|
||||
}
|
||||
if (opf)
|
||||
free(opf, M_DEVBUF);
|
||||
|
||||
SIMPLEQ_INIT(pfhead);
|
||||
}
|
||||
|
||||
void
|
||||
pcmcia_read_cis(sc)
|
||||
struct pcmcia_softc *sc;
|
||||
|
@ -690,17 +727,11 @@ pcmcia_parse_cis_tuple(tuple, arg)
|
|||
* rather not change it.
|
||||
*/
|
||||
if (state->gotmfc == 1) {
|
||||
struct pcmcia_function *pf;
|
||||
|
||||
SIMPLEQ_FOREACH(pf, &state->card->pf_head, pf_list) {
|
||||
free(pf, M_DEVBUF);
|
||||
}
|
||||
|
||||
SIMPLEQ_INIT(&state->card->pf_head);
|
||||
|
||||
state->count = 0;
|
||||
state->gotmfc = 2;
|
||||
state->count = 0;
|
||||
state->pf = NULL;
|
||||
|
||||
pcmcia_free_pf(&state->card->pf_head);
|
||||
}
|
||||
break;
|
||||
case PCMCIA_CISTPL_LONGLINK_MFC:
|
||||
|
@ -710,7 +741,11 @@ pcmcia_parse_cis_tuple(tuple, arg)
|
|||
* functions declared before the MFC link can be cleaned
|
||||
* up.
|
||||
*/
|
||||
state->gotmfc = 1;
|
||||
if (state->gotmfc == 0) {
|
||||
state->gotmfc = 1;
|
||||
} else {
|
||||
DPRINTF(("got LONGLINK_MFC again!"));
|
||||
}
|
||||
break;
|
||||
#ifdef PCMCIACISDEBUG
|
||||
case PCMCIA_CISTPL_DEVICE:
|
||||
|
@ -849,16 +884,8 @@ pcmcia_parse_cis_tuple(tuple, arg)
|
|||
state->pf = NULL;
|
||||
}
|
||||
}
|
||||
if (state->pf == NULL) {
|
||||
state->pf = malloc(sizeof(*state->pf), M_DEVBUF,
|
||||
M_NOWAIT|M_ZERO);
|
||||
state->pf->number = state->count++;
|
||||
state->pf->last_config_index = -1;
|
||||
SIMPLEQ_INIT(&state->pf->cfe_head);
|
||||
|
||||
SIMPLEQ_INSERT_TAIL(&state->card->pf_head, state->pf,
|
||||
pf_list);
|
||||
}
|
||||
if (state->pf == NULL)
|
||||
create_pf(state);
|
||||
state->pf->function = pcmcia_tuple_read_1(tuple, 0);
|
||||
|
||||
DPRINTF(("CISTPL_FUNCID\n"));
|
||||
|
@ -897,15 +924,7 @@ pcmcia_parse_cis_tuple(tuple, arg)
|
|||
break;
|
||||
}
|
||||
if (state->pf == NULL) {
|
||||
state->pf = malloc(sizeof(*state->pf),
|
||||
M_DEVBUF, M_NOWAIT|M_ZERO);
|
||||
state->pf->number = state->count++;
|
||||
state->pf->last_config_index = -1;
|
||||
SIMPLEQ_INIT(&state->pf->cfe_head);
|
||||
|
||||
SIMPLEQ_INSERT_TAIL(&state->card->pf_head,
|
||||
state->pf, pf_list);
|
||||
|
||||
create_pf(state);
|
||||
state->pf->function = PCMCIA_FUNCTION_UNSPEC;
|
||||
}
|
||||
state->pf->last_config_index =
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pcmcia_cis_quirks.c,v 1.19 2002/06/01 23:51:02 lukem Exp $ */
|
||||
/* $NetBSD: pcmcia_cis_quirks.c,v 1.20 2002/08/15 10:37:02 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Marc Horowitz. All rights reserved.
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: pcmcia_cis_quirks.c,v 1.19 2002/06/01 23:51:02 lukem Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pcmcia_cis_quirks.c,v 1.20 2002/08/15 10:37:02 christos Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -284,17 +284,7 @@ void pcmcia_check_cis_quirks(sc)
|
|||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
SIMPLEQ_FOREACH(pf, &sc->card.pf_head,
|
||||
pf_list) {
|
||||
SIMPLEQ_FOREACH(cfe, &pf->cfe_head,
|
||||
cfe_list) {
|
||||
free(cfe, M_DEVBUF);
|
||||
}
|
||||
free(pf, M_DEVBUF);
|
||||
}
|
||||
|
||||
SIMPLEQ_INIT(&sc->card.pf_head);
|
||||
pcmcia_free_pf(&sc->card.pf_head);
|
||||
wiped = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pcmciavar.h,v 1.16 2002/06/01 23:51:02 lukem Exp $ */
|
||||
/* $NetBSD: pcmciavar.h,v 1.17 2002/08/15 10:37:02 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Marc Horowitz. All rights reserved.
|
||||
|
@ -155,6 +155,8 @@ struct pcmcia_function {
|
|||
/* pf_flags */
|
||||
#define PFF_ENABLED 0x0001 /* function is enabled */
|
||||
|
||||
SIMPLEQ_HEAD(pcmcia_function_head, pcmcia_function);
|
||||
|
||||
struct pcmcia_card {
|
||||
int cis1_major;
|
||||
int cis1_minor;
|
||||
|
@ -172,7 +174,7 @@ struct pcmcia_card {
|
|||
#define PCMCIA_PRODUCT_INVALID -1
|
||||
u_int16_t error;
|
||||
#define PCMCIA_CIS_INVALID { NULL, NULL, NULL, NULL }
|
||||
SIMPLEQ_HEAD(, pcmcia_function) pf_head;
|
||||
struct pcmcia_function_head pf_head;
|
||||
};
|
||||
|
||||
struct pcmcia_softc {
|
||||
|
@ -297,6 +299,8 @@ int pcmcia_io_map __P((struct pcmcia_function *, int, bus_addr_t,
|
|||
bus_size_t, struct pcmcia_io_handle *, int *));
|
||||
void pcmcia_io_unmap __P((struct pcmcia_function *, int));
|
||||
|
||||
void pcmcia_free_pf __P((struct pcmcia_function_head *));
|
||||
|
||||
#define pcmcia_mem_alloc(pf, size, pcmhp) \
|
||||
(pcmcia_chip_mem_alloc((pf)->sc->pct, (pf)->sc->pch, (size), (pcmhp)))
|
||||
|
||||
|
|
Loading…
Reference in New Issue