FreeBSD/sys/dev/xen/blkback/blkback.c
/**
 * Cleanup all inter-domain communication mechanisms.
 *
 * \param xbb  Per-instance xbb configuration structure.
 */
Cleanup all inter-domain communication mechanisms.
\param xbb  Per-instance xbb configuration structure.
Cleanup all inter - domain communication mechanisms . \ param xbb Per - instance xbb configuration structure .
static int
xbb_disconnect(struct xbb_softc *xbb)
{
	struct gnttab_unmap_grant_ref  ops[XBB_MAX_RING_PAGES];
	struct gnttab_unmap_grant_ref *op;
	u_int			       ring_idx;
	int			       error;
	DPRINTF("\n");
	if ((xbb->flags & XBBF_RING_CONNECTED) == 0)
		return (0);
	xen_intr_unbind(&xbb->xen_intr_handle);
	mtx_unlock(&xbb->lock);
	taskqueue_drain(xbb->io_taskqueue, &xbb->io_task); 
	mtx_lock(&xbb->lock);
	if (xbb->active_request_count != 0)
		return (EAGAIN);
	for (ring_idx = 0, op = ops;
	     ring_idx < xbb->ring_config.ring_pages;
	     ring_idx++, op++) {
		op->host_addr    = xbb->ring_config.gnt_addr
			         + (ring_idx * PAGE_SIZE);
		op->dev_bus_addr = xbb->ring_config.bus_addr[ring_idx];
		op->handle	 = xbb->ring_config.handle[ring_idx];
	}
	error = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, ops,
					  xbb->ring_config.ring_pages);
	if (error != 0)
		panic("Grant table op failed (%d)", error);
	xbb_free_communication_mem(xbb);
	if (xbb->requests != NULL) {
		free(xbb->requests, M_XENBLOCKBACK);
		xbb->requests = NULL;
	}
	if (xbb->request_lists != NULL) {
		struct xbb_xen_reqlist *reqlist;
		int i;
		for (i = 0, reqlist = xbb->request_lists;
		     i < xbb->max_requests; i++, reqlist++){
#ifdef XBB_USE_BOUNCE_BUFFERS
			if (reqlist->bounce != NULL) {
				free(reqlist->bounce, M_XENBLOCKBACK);
				reqlist->bounce = NULL;
			}
#endif
			if (reqlist->gnt_handles != NULL) {
				free(reqlist->gnt_handles, M_XENBLOCKBACK);
				reqlist->gnt_handles = NULL;
			}
		}
		free(xbb->request_lists, M_XENBLOCKBACK);
		xbb->request_lists = NULL;
	}
	xbb->flags &= ~XBBF_RING_CONNECTED;
	return (0);
}
static int xbb_disconnect ( struct xbb_softc * xbb ) { struct gnttab_unmap_grant_ref ops [ XBB_MAX_RING_PAGES ] ; struct gnttab_unmap_grant_ref * op ; u_int ring_idx ; int error ; DPRINTF ( " \n " ) ; if ( ( xbb -> flags & XBBF_RING_CONNECTED ) == 0 ) return ( 0 ) ; xen_intr_unbind ( & xbb -> xen_intr_handle ) ; mtx_unlock ( & xbb -> lock ) ; taskqueue_drain ( xbb -> io_taskqueue , & xbb -> io_task ) ; mtx_lock ( & xbb -> lock ) ; if ( xbb -> active_request_count != 0 ) return ( EAGAIN ) ; for ( ring_idx = 0 , op = ops ; ring_idx < xbb -> ring_config . ring_pages ; ring_idx ++ , op ++ ) { op -> host_addr = xbb -> ring_config . gnt_addr + ( ring_idx * PAGE_SIZE ) ; op -> dev_bus_addr = xbb -> ring_config . bus_addr [ ring_idx ] ; op -> handle = xbb -> ring_config . handle [ ring_idx ] ; } error = HYPERVISOR_grant_table_op ( GNTTABOP_unmap_grant_ref , ops , xbb -> ring_config . ring_pages ) ; if ( error != 0 ) panic ( " " , error ) ; xbb_free_communication_mem ( xbb ) ; if ( xbb -> requests != NULL ) { free ( xbb -> requests , M_XENBLOCKBACK ) ; xbb -> requests = NULL ; } if ( xbb -> request_lists != NULL ) { struct xbb_xen_reqlist * reqlist ; int i ; for ( i = 0 , reqlist = xbb -> request_lists ; i < xbb -> max_requests ; i ++ , reqlist ++ ) { #ifdef XBB_USE_BOUNCE_BUFFERS if ( reqlist -> bounce != NULL ) { free ( reqlist -> bounce , M_XENBLOCKBACK ) ; reqlist -> bounce = NULL ; } #endif if ( reqlist -> gnt_handles != NULL ) { free ( reqlist -> gnt_handles , M_XENBLOCKBACK ) ; reqlist -> gnt_handles = NULL ; } } free ( xbb -> request_lists , M_XENBLOCKBACK ) ; xbb -> request_lists = NULL ; } xbb -> flags &= ~ XBBF_RING_CONNECTED ; return ( 0 ) ; }
Cleanup all inter-domain communication mechanisms.
Cleanup all inter - domain communication mechanisms .
/*
	 * No new interrupts can generate work, but we must wait
	 * for all currently active requests to drain.
	 */ /* There is one request list for ever allocated request. */