diff options
author | msmith <msmith@FreeBSD.org> | 2000-05-06 08:54:33 +0000 |
---|---|---|
committer | msmith <msmith@FreeBSD.org> | 2000-05-06 08:54:33 +0000 |
commit | 9cfdfa9434715d06f368749139a813e66ee2ca7a (patch) | |
tree | 9b255a84e28773bacb3fb95666ea6b73036aae9b /sys/dev | |
parent | 4b77d307471bc8c1eac6d2856702374846fb9a38 (diff) | |
download | FreeBSD-src-9cfdfa9434715d06f368749139a813e66ee2ca7a.zip FreeBSD-src-9cfdfa9434715d06f368749139a813e66ee2ca7a.tar.gz |
Change the way that scatter/gather list tables are allocated so that we
can use all of the s/g entries available on smaller cards. This is
necessary if we want to be able to handle a non-page-aligned 64k transfer
on 2.x and 3.x firmware.
Fix a missing splx() that may have left us at splbio() for longer than
desired.
Reduce shadowing of controller-supplied parameters a little.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/mlx/mlx.c | 70 | ||||
-rw-r--r-- | sys/dev/mlx/mlx_disk.c | 10 | ||||
-rw-r--r-- | sys/dev/mlx/mlx_pci.c | 2 | ||||
-rw-r--r-- | sys/dev/mlx/mlxvar.h | 15 |
4 files changed, 58 insertions, 39 deletions
diff --git a/sys/dev/mlx/mlx.c b/sys/dev/mlx/mlx.c index 942bebb..9bb87ca 100644 --- a/sys/dev/mlx/mlx.c +++ b/sys/dev/mlx/mlx.c @@ -227,7 +227,7 @@ static int mlx_sglist_map(struct mlx_softc *sc) { size_t segsize; - int error; + int error, ncmd; debug_called(1); @@ -239,9 +239,16 @@ mlx_sglist_map(struct mlx_softc *sc) /* * Create a single tag describing a region large enough to hold all of - * the s/g lists we will need. + * the s/g lists we will need. If we're called early on, we don't know how + * many commands we're going to be asked to support, so only allocate enough + * for a couple. */ - segsize = sizeof(struct mlx_sgentry) * sc->mlx_sg_nseg * sc->mlx_maxiop; + if (sc->mlx_enq2 == NULL) { + ncmd = 2; + } else { + ncmd = sc->mlx_enq2->me_max_commands; + } + segsize = sizeof(struct mlx_sgentry) * MLX_NSEG * ncmd; error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */ 1, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ @@ -301,21 +308,18 @@ mlx_attach(struct mlx_softc *sc) sc->mlx_findcomplete = mlx_v3_findcomplete; sc->mlx_intaction = mlx_v3_intaction; sc->mlx_fw_handshake = mlx_v3_fw_handshake; - sc->mlx_sg_nseg = MLX_NSEG_OLD; break; case MLX_IFTYPE_4: sc->mlx_tryqueue = mlx_v4_tryqueue; sc->mlx_findcomplete = mlx_v4_findcomplete; sc->mlx_intaction = mlx_v4_intaction; sc->mlx_fw_handshake = mlx_v4_fw_handshake; - sc->mlx_sg_nseg = MLX_NSEG_NEW; break; case MLX_IFTYPE_5: sc->mlx_tryqueue = mlx_v5_tryqueue; sc->mlx_findcomplete = mlx_v5_findcomplete; sc->mlx_intaction = mlx_v5_intaction; sc->mlx_fw_handshake = mlx_v5_fw_handshake; - sc->mlx_sg_nseg = MLX_NSEG_NEW; break; default: mlx_free(sc); @@ -376,7 +380,7 @@ mlx_attach(struct mlx_softc *sc) BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ - MAXBSIZE, sc->mlx_sg_nseg, /* maxsize, nsegments */ + MAXBSIZE, MLX_NSEG, /* maxsize, nsegments */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 0, /* flags */ &sc->mlx_buffer_dmat); @@ -387,9 +391,8 @@ mlx_attach(struct mlx_softc *sc) } /* - * Create an initial set of s/g mappings. + * Create some initial scatter/gather mappings so we can run the probe commands. */ - sc->mlx_maxiop = 8; error = mlx_sglist_map(sc); if (error != 0) { device_printf(sc->mlx_dev, "can't make initial s/g list mapping\n"); @@ -397,7 +400,14 @@ mlx_attach(struct mlx_softc *sc) return(error); } - /* send an ENQUIRY2 to the controller */ + /* + * We don't (yet) know where the event log is up to. + */ + sc->mlx_currevent = -1; + + /* + * Obtain controller feature information + */ if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) { device_printf(sc->mlx_dev, "ENQUIRY2 failed\n"); mlx_free(sc); @@ -405,11 +415,6 @@ mlx_attach(struct mlx_softc *sc) } /* - * We don't (yet) know where the event log is up to. - */ - sc->mlx_currevent = -1; - - /* * Do quirk/feature related things. */ fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff; @@ -456,13 +461,11 @@ mlx_attach(struct mlx_softc *sc) } /* - * Create the final set of s/g mappings now that we know how many commands - * the controller actually supports. + * Create the final scatter/gather mappings now that we have characterised the controller. */ - sc->mlx_maxiop = sc->mlx_enq2->me_max_commands; error = mlx_sglist_map(sc); if (error != 0) { - device_printf(sc->mlx_dev, "can't make permanent s/g list mapping\n"); + device_printf(sc->mlx_dev, "can't make final s/g list mapping\n"); mlx_free(sc); return(error); } @@ -1953,13 +1956,19 @@ static int mlx_getslot(struct mlx_command *mc) { struct mlx_softc *sc = mc->mc_sc; - int s, slot; + int s, slot, limit; debug_called(1); - /* enforce slot-usage limit */ - if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? - sc->mlx_maxiop : sc->mlx_maxiop - 4)) + /* + * Enforce slot-usage limit, if we have the required information. + */ + if (sc->mlx_enq2 != NULL) { + limit = sc->mlx_enq2->me_max_commands; + } else { + limit = 2; + } + if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? limit : limit - 4)) return(EBUSY); /* @@ -1968,19 +1977,19 @@ mlx_getslot(struct mlx_command *mc) * XXX linear search is slow */ s = splbio(); - for (slot = 0; slot < sc->mlx_maxiop; slot++) { + for (slot = 0; slot < limit; slot++) { debug(2, "try slot %d", slot); if (sc->mlx_busycmd[slot] == NULL) break; } - if (slot < sc->mlx_maxiop) { + if (slot < limit) { sc->mlx_busycmd[slot] = mc; sc->mlx_busycmds++; } splx(s); /* out of slots? */ - if (slot >= sc->mlx_maxiop) + if (slot >= limit) return(EBUSY); debug(2, "got slot %d", slot); @@ -2001,12 +2010,16 @@ mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error) debug_called(1); + /* XXX should be unnecessary */ + if (sc->mlx_enq2 && (nsegments > sc->mlx_enq2->me_max_sg)) + panic("MLX: too many s/g segments (%d, max %d)", nsegments, sc->mlx_enq2->me_max_sg); + /* get base address of s/g table */ - sg = sc->mlx_sgtable + (mc->mc_slot * sc->mlx_sg_nseg); + sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG); /* save s/g table information in command */ mc->mc_nsgent = nsegments; - mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * sc->mlx_sg_nseg * sizeof(struct mlx_sgentry)); + mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * MLX_NSEG * sizeof(struct mlx_sgentry)); mc->mc_dataphys = segs[0].ds_addr; /* populate s/g table */ @@ -2146,6 +2159,7 @@ mlx_done(struct mlx_softc *sc) break; } } + splx(s); /* if we've completed any commands, try posting some more */ if (result) diff --git a/sys/dev/mlx/mlx_disk.c b/sys/dev/mlx/mlx_disk.c index 190f7a7..5584749 100644 --- a/sys/dev/mlx/mlx_disk.c +++ b/sys/dev/mlx/mlx_disk.c @@ -236,6 +236,7 @@ mlxd_attach(device_t dev) device_t parent; char *state; dev_t dsk; + int s1, s2; debug_called(1); @@ -272,8 +273,13 @@ mlxd_attach(device_t dev) dsk->si_drv1 = sc; sc->mlxd_dev_t = dsk; - /* set maximum I/O size */ - dsk->si_iosize_max = sc->mlxd_controller->mlx_enq2->me_maxblk * MLX_BLKSIZE; + /* + * Set maximum I/O size to the lesser of the recommended maximum and the practical + * maximum. + */ + s1 = sc->mlxd_controller->mlx_enq2->me_maxblk * MLX_BLKSIZE; + s2 = (sc->mlxd_controller->mlx_enq2->me_max_sg - 1) * PAGE_SIZE; + dsk->si_iosize_max = imin(s1, s2); return (0); } diff --git a/sys/dev/mlx/mlx_pci.c b/sys/dev/mlx/mlx_pci.c index 9a5a658..118e495 100644 --- a/sys/dev/mlx/mlx_pci.c +++ b/sys/dev/mlx/mlx_pci.c @@ -185,7 +185,7 @@ mlx_pci_attach(device_t dev) BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ - MAXBSIZE, MLX_NSEG_NEW, /* maxsize, nsegments */ + MAXBSIZE, MLX_NSEG, /* maxsize, nsegments */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ BUS_DMA_ALLOCNOW, /* flags */ &sc->mlx_parent_dmat); diff --git a/sys/dev/mlx/mlxvar.h b/sys/dev/mlx/mlxvar.h index 51500bd..edb1a85 100644 --- a/sys/dev/mlx/mlxvar.h +++ b/sys/dev/mlx/mlxvar.h @@ -40,14 +40,15 @@ #define debug_called(level) #endif - /* - * We could actually use all 17/33 segments, but using only 16/32 means that - * each scatter/gather map is 128/256 bytes in size, and thus we don't have to worry about - * maps crossing page boundaries. + * Regardless of the actual capacity of the controller, we will allocate space + * for 64 s/g entries. Typically controllers support 17 or 33 entries (64k or + * 128k maximum transfer assuming 4k page size and non-optimal alignment), but + * making that fit cleanly without crossing page boundaries requires rounding up + * to the next power of two. */ -#define MLX_NSEG_OLD 16 /* max scatter/gather segments we use 3.x and earlier */ -#define MLX_NSEG_NEW 32 /* max scatter/gather segments we use 4.x and later */ +#define MLX_NSEG 64 + #define MLX_NSLOTS 256 /* max number of command slots */ #define MLX_MAXDRIVES 32 /* max number of system drives */ @@ -120,11 +121,9 @@ struct mlx_softc u_int32_t mlx_sgbusaddr; /* s/g table base address in bus space */ bus_dma_tag_t mlx_sg_dmat; /* s/g buffer DMA tag */ bus_dmamap_t mlx_sg_dmamap; /* map for s/g buffers */ - int mlx_sg_nseg; /* max number of s/g entries */ /* controller limits and features */ struct mlx_enquiry2 *mlx_enq2; - int mlx_maxiop; /* hard maximum number of commands */ int mlx_feature; /* controller features/quirks */ #define MLX_FEAT_PAUSEWORKS (1<<0) /* channel pause works as expected */ |