Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Feb 1997 15:23:45 +1030 (CST)
From:      Michael Smith <msmith@atrad.adelaide.edu.au>
To:        Shimon@i-Connect.Net (Simon Shapiro)
Cc:        freebsd-scsi@freebsd.org, freebsd-hackers@freebsd.org
Subject:   Re: Contigious (spelling?) allocation in kernel
Message-ID:  <199702060453.PAA00702@genesis.atrad.adelaide.edu.au>
In-Reply-To: <XFMail.970205205354.Shimon@i-Connect.Net> from Simon Shapiro at "Feb 5, 97 07:33:54 pm"

next in thread | previous in thread | raw e-mail | index | archive | help
Simon Shapiro stands accused of saying:
> I need to allocate a contigious (one piece :-) block of memory for a DMA
> scatter/gather list.  The HBA knows how to do scatter gather, but wants a
> single pointer to a single block of memory that hoslds the entire list.

That's a bit icky 8)

> The SG structure is very plain, 32bits for length and 32bits for physical
> address; 8 bytes.  The thing is capable of up to 8192 entries, which give
> us a possible list of 64KB per request list.

You might want to check on the s/g limit for block I/O for FreeBSD; it's
quite possible that something like that is far beyond anything that
it's likely to do.  In most cases, I/O is likely to be in page-sized
(4K) chunks, with a limit of 64K (MAXPHYS).

You'd have to ask Bruce or possibly Justin about that; I don't know where
to look to confirm such a limit.

> As each HBA can have up to 256 concurrent requests, with who knows how
> many more in the driver's queue, the list can grow quite impressively.
> Since most requests are smaller, it seems very wasteful to allocate all
> this memory upfront.  So malloc is in order, but what are the options?

I'd start with a small pool of permanently-allocated (get them at
driver startup time) S/G lists of some empirically determined
"adequate" size.  Keep enough of these around so that you can cover
the maximum number of concurrent outstanding transactions (or possibly
just grow your pool as required).  Use the BSD queue macros to
efficiently manage your buffer lists.  If you get a request bigger
than will fit in your "normal" S/G block, allocate one temporarily,
and throw it away when you're done.

As far as actually allocating the suckers goes, contigmalloc() is
probably what you're after; call it contigmalloc(size, M_DEVBUF,
M_NOWAIT, low, high, align), where low and high are the lowest and
highest legal physical addresses, and align is the alignment size for
the structure.  It sounds like you're talking to a PCI device, so 0,
ULONG_MAX and sizeof(u_long) respectively should do the trick.

> Simon

-- 
]] Mike Smith, Software Engineer        msmith@gsoft.com.au             [[
]] Genesis Software                     genesis@gsoft.com.au            [[
]] High-speed data acquisition and      (GSM mobile)     0411-222-496   [[
]] realtime instrument control.         (ph)          +61-8-8267-3493   [[
]] Unix hardware collector.             "Where are your PEZ?" The Tick  [[



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199702060453.PAA00702>