I/O consolidation and direct-to-DMA plans

Matthew Dillon dillon at apollo.backplane.com
Mon Dec 20 12:11:30 PST 2004


    Hiten and I have come up with a roadmap for the I/O path cleanup and
    direct-to-dma plans (avoiding having to map KVA buffers).

    We've looked at all existing structures... msf_buf's, sfbufs, struct buf,
    XIO's, UIO's, and BUSDMA (bounce_page and bus_dmamap).  Each of these
    structures represents a piece of the larger 'integrated I/O' puzzle.

    The primary issue is that we need a structure which covers both ends of
    the equation... we need the capability in higher layers to specify either
    a KVA mapped buffer or a page list, and we need the capability in lower
    layers to require either a KVA mapped buffer or a page list, depending on
    the requirements of the layer.   For example, in some instances CAM 
    may supply a buffer pointer to simple SCSI request structures while in
    others CAM might want to pass data from a struct BUF or UIO that it has
    a page list for.  In some cases a driver will have access to a DMA
    engine and require a page list, while in others a driver might need a
    mapped buffer, or might need to create bounce pages.

    What we are going to do is extend the msf_buf abstraction to cover these
    needs and provide a set of API calls that allows upper layers to supply
    data in any form and lower level layers to request data in any form,
    including with address restrictions.  msf_buf's already have a page-list
    (XIO) and KVA mapping abstraction.  We are going to add a bounce-buffer
    abstraction and then work on a bunch of new API calls for msf_bufs to
    cover the needs of various subsystems.

    As a starter we'll have these functions:


    msf_init(struct msf_buf *msf)

	Initialize an msf_buf for use (i.e. zero its fields).

    struct msf_buf *
    msf_create_from_buf(struct msf_buf *opt_msf, void *buf, size_t bytes)

	Populate an existing msf_buf or allocate a new one and install the
	supplied KVA buffer pointer and size.

    struct msf_buf *
    msf_create_from_xio(struct msf_buf *opt_msf, struct xio *xio)

	Populate an existing msf_buf or allocate a new one and install the
	supplied XIO (page list).

    int
    msf_require_buf(struct msf_buf *msf)

	Require that an msf_buf have a mapped KVA buffer.  If the msf_buf
	already has a mapped KVA buffer this is a NOP.  If the msf_buf
	contains a page list a KVA buffer will be allocated and mapped
	based on the page list.

    int
    msf_require_xio(struct msf_buf *msf)

	Require that an mfs_buf have a page list.  If the msf_buf already
	has a page list this is a NOP.  Otherwise a page list is constructed
	from the msf_buf's KVA buffer.

    void
    msf_release(struct msf_buf *msf)

	Release an msf_buf, freeing any resources that were created as side
	effects to the above API calls and zeroing out any resources
	that were originally supplied.


    The plan is to start embedding msf_buf's in various system layers
    (struct buf, busdma, etc...) as independant entities to begin with.  As
    more of this work is accomplished the various layers using msf_buf's 
    will start to become adjacent to each other and we will be able to then
    have one layer pass its msf_buf directly to another without having to
    re-create this.

    Along the way all the various disparate I/O related structures will
    be consolidated.

    Eventually this will allow e.g. the buffer cache to pass an msf_buf
    all the way down to BUSDMA without having to KVA map the buffer, thus
    achieving our goal.

					-Matt
					Matthew Dillon 
					<dillon at xxxxxxxxxxxxx>





More information about the Kernel mailing list