Up until now, the free SCB pool received only a small initial allocation,

and new SCBs were allocated on demand later if needed.  This has two
problems.  First, allocating SCBs involves allocating contiguous memory,
and if memory is exhausted then the VM will try to page out to satisfy
the request, leading to recursion and deadlock.  The second problem is
that it can cause lock order reversals due to parts of the VM still being
under Giant.

Fix the problem be allocating the full pool at driver attach, when it is
safe to do so.
This commit is contained in:
Scott Long 2007-04-19 18:53:52 +00:00
parent 58b0b144e8
commit 7628acd8ee
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=168873
5 changed files with 24 additions and 18 deletions

View File

@ -5693,7 +5693,8 @@ ahd_init_scbdata(struct ahd_softc *ahd)
scb_data->init_level++;
/* Perform initial CCB allocation */
ahd_alloc_scbs(ahd);
while (ahd_alloc_scbs(ahd) != 0)
;
if (scb_data->numscbs == 0) {
printf("%s: ahd_init_scbdata - "
@ -5940,7 +5941,8 @@ ahd_get_scb(struct ahd_softc *ahd, u_int col_idx)
if (tries++ != 0)
return (NULL);
ahd_alloc_scbs(ahd);
if (ahd_alloc_scbs(ahd) == 0)
return (NULL);
goto look_again;
}
LIST_REMOVE(scb, links.le);
@ -6011,7 +6013,7 @@ ahd_free_scb(struct ahd_softc *ahd, struct scb *scb)
aic_platform_scb_free(ahd, scb);
}
void
int
ahd_alloc_scbs(struct ahd_softc *ahd)
{
struct scb_data *scb_data;
@ -6031,7 +6033,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
scb_data = &ahd->scb_data;
if (scb_data->numscbs >= AHD_SCB_MAX_ALLOC)
/* Can't allocate any more */
return;
return (0);
if (scb_data->scbs_left != 0) {
int offset;
@ -6044,14 +6046,14 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
hscb_map = malloc(sizeof(*hscb_map), M_DEVBUF, M_NOWAIT);
if (hscb_map == NULL)
return;
return (0);
/* Allocate the next batch of hardware SCBs */
if (aic_dmamem_alloc(ahd, scb_data->hscb_dmat,
(void **)&hscb_map->vaddr,
BUS_DMA_NOWAIT, &hscb_map->dmamap) != 0) {
free(hscb_map, M_DEVBUF);
return;
return (0);
}
SLIST_INSERT_HEAD(&scb_data->hscb_maps, hscb_map, links);
@ -6077,14 +6079,14 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
if (sg_map == NULL)
return;
return (0);
/* Allocate the next batch of S/G lists */
if (aic_dmamem_alloc(ahd, scb_data->sg_dmat,
(void **)&sg_map->vaddr,
BUS_DMA_NOWAIT, &sg_map->dmamap) != 0) {
free(sg_map, M_DEVBUF);
return;
return (0);
}
SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links);
@ -6114,14 +6116,14 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
sense_map = malloc(sizeof(*sense_map), M_DEVBUF, M_NOWAIT);
if (sense_map == NULL)
return;
return (0);
/* Allocate the next batch of sense buffers */
if (aic_dmamem_alloc(ahd, scb_data->sense_dmat,
(void **)&sense_map->vaddr,
BUS_DMA_NOWAIT, &sense_map->dmamap) != 0) {
free(sense_map, M_DEVBUF);
return;
return (0);
}
SLIST_INSERT_HEAD(&scb_data->sense_maps, sense_map, links);
@ -6210,6 +6212,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
sense_busaddr += AHD_SENSE_BUFSIZE;
scb_data->numscbs++;
}
return (i);
}
void

View File

@ -1402,7 +1402,7 @@ void ahd_set_unit(struct ahd_softc *, int);
void ahd_set_name(struct ahd_softc *, char *);
struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx);
void ahd_free_scb(struct ahd_softc *ahd, struct scb *scb);
void ahd_alloc_scbs(struct ahd_softc *ahd);
int ahd_alloc_scbs(struct ahd_softc *ahd);
void ahd_free(struct ahd_softc *ahd);
int ahd_reset(struct ahd_softc *ahd, int reinit);
void ahd_shutdown(void *arg);

View File

@ -4444,7 +4444,8 @@ ahc_init_scbdata(struct ahc_softc *ahc)
/* Perform initial CCB allocation */
memset(scb_data->hscbs, 0,
AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb));
ahc_alloc_scbs(ahc);
while (ahc_alloc_scbs(ahc) != 0)
;
if (scb_data->numscbs == 0) {
printf("%s: ahc_init_scbdata - "
@ -4522,7 +4523,7 @@ ahc_fini_scbdata(struct ahc_softc *ahc)
free(scb_data->scbarray, M_DEVBUF);
}
void
int
ahc_alloc_scbs(struct ahc_softc *ahc)
{
struct scb_data *scb_data;
@ -4536,21 +4537,21 @@ ahc_alloc_scbs(struct ahc_softc *ahc)
scb_data = ahc->scb_data;
if (scb_data->numscbs >= AHC_SCB_MAX_ALLOC)
/* Can't allocate any more */
return;
return (0);
next_scb = &scb_data->scbarray[scb_data->numscbs];
sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
if (sg_map == NULL)
return;
return (0);
/* Allocate S/G space for the next batch of SCBS */
if (aic_dmamem_alloc(ahc, scb_data->sg_dmat,
(void **)&sg_map->sg_vaddr,
BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) {
free(sg_map, M_DEVBUF);
return;
return (0);
}
SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links);
@ -4599,6 +4600,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc)
next_scb++;
ahc->scb_data->numscbs++;
}
return (i);
}
void

View File

@ -1227,7 +1227,7 @@ int ahc_resume(struct ahc_softc *ahc);
void ahc_softc_insert(struct ahc_softc *);
void ahc_set_unit(struct ahc_softc *, int);
void ahc_set_name(struct ahc_softc *, char *);
void ahc_alloc_scbs(struct ahc_softc *ahc);
int ahc_alloc_scbs(struct ahc_softc *ahc);
void ahc_free(struct ahc_softc *ahc);
int ahc_reset(struct ahc_softc *ahc, int reinit);
void ahc_shutdown(void *arg);

View File

@ -363,7 +363,8 @@ ahc_get_scb(struct ahc_softc *ahc)
struct scb *scb;
if ((scb = SLIST_FIRST(&ahc->scb_data->free_scbs)) == NULL) {
ahc_alloc_scbs(ahc);
if (ahc_alloc_scbs(ahc) == 0)
return (NULL);
scb = SLIST_FIRST(&ahc->scb_data->free_scbs);
if (scb == NULL)
return (NULL);