Changes:
sys/dev/xen/netfront/netfront.c:
- Added a DMA tag in each rx and tx queue.
- Added DMA tag creation in setup_rxqs() and setup_txqs().
- Added new functions xn_get_rx_map(), xn_unpool_rx_map(),
xn_repool_rx_map(), xn_unpool_tx_map(), xn_repool_tx_map(),
xn_get_map_gref() as helpers for using the dma maps with the netfront
implementation.
- Updated xn_rebuild_rx_bufs(), setup_rxqs(), and xn_assemble_tx_request
to use dma loads instead of gnttab_grant_foreign_access_ref().
- Updated xn_release_rx_bufs(), xn_get_responses(), xn_release_tx_bufs()
and xn_txeof() to use dma unloads instead of
gnttab_end_foreign_access_ref().
- Updated disconnect_rxq() to use bus_dmamap_destroy() instead of
gnttab_free_grant_references().
- Created a generic DMA load callback xn_dma_cb() that any function
using loads can use if they don't want to do anything there.
Reasoning:
- My aim was to stay as close to the tried and tested code as
possible, so most of the code I wrote parallels the functionality
previously present.
- Since netfront maintains a pool of grant references, I thought it
would be best to keep doing that. This had a challenge: the busdma
implementation can't work with pools of grant refs that can be
claimed/released as and when needed. I worked around it by creating a
"pool" of dma maps. Each map corresponds to 1 grant reference, and I
maintain a pool of dma maps for each queue. Whenever a grant ref is
needed, a map is removed from the pool. Whenever the grant reference is
released, the corresponding map is added back to the pool. The functions
xn_unpool_rx/tx_map() andxn_repool_rx/tx_map() do this.
- The calls to xn_unpool_rx/tx_map() are equivalent to
gnttab_claim_grant_reference() and the calls to xn_repool_rx/tx_map()
are equivalent to gnttab_release_grant_reference().
- The calls to bus_dmamap_load() are equivalent to
gnttab_grant_foreign_access_ref().
- The calls to bus_dmamap_unload() are equivalent to
gnttab_end_foreign_access_ref().
- The calls to bus_dmamap_destroy() are equivalent to
gnttab_free_grant_references()
- I create a DMA tag for each rx/tx queue. There are two reasons for
that:
- Since all loads on a single tag must be serialized, there might be a loss in performance with a single tag because the synchronization can lead to a bottleneck.
- Trying to synchronize access to the tag proved to be difficult, because of my lack of familiarity with the locking expectations on netfront_info's sc_lock.
This driver uses the Xen-specific bus_dma(9) implementation. It is
located in sys/xen/busdma_xen.h and sys/x86/xen/busdma_xen.c