FreeBSD/sys/dev/mrsas/mrsas.c
/*
 * mrsas_detach:	De-allocates and teardown resources
 * input:			pointer to device struct
 *
 * This function is the entry point for device disconnect and detach.
 * It performs memory de-allocations, shutdown of the controller and various
 * teardown and destroy resource functions.
 */
De-allocates and teardown resources
input:                       pointer to device struct

This function is the entry point for device disconnect and detach.
It performs memory de-allocations, shutdown of the controller and various
teardown and destroy resource functions.
De - allocates and teardown resources input : pointer to device struct This function is the entry point for device disconnect and detach . It performs memory de - allocations shutdown of the controller and various teardown and destroy resource functions .
static int
mrsas_detach(device_t dev)
{
	struct mrsas_softc *sc;
	int i = 0;
	sc = device_get_softc(dev);
	sc->remove_in_progress = 1;
	if ((device_get_unit(dev) == 0) && sc->mrsas_linux_emulator_cdev)
		destroy_dev(sc->mrsas_linux_emulator_cdev);
	destroy_dev(sc->mrsas_cdev);
	for (i = 0; i < mrsas_mgmt_info.max_index; i++) {
		if (mrsas_mgmt_info.sc_ptr[i] == sc) {
			mrsas_mgmt_info.count--;
			mrsas_mgmt_info.sc_ptr[i] = NULL;
			break;
		}
	}
	if (sc->ocr_thread_active)
		wakeup(&sc->ocr_chan);
	while (sc->reset_in_progress) {
		i++;
		if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) {
			mrsas_dprint(sc, MRSAS_INFO,
			    "[%2d]waiting for OCR to be finished from %s\n", i, __func__);
		}
		pause("mr_shutdown", hz);
	}
	i = 0;
	while (sc->ocr_thread_active) {
		i++;
		if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) {
			mrsas_dprint(sc, MRSAS_INFO,
			    "[%2d]waiting for "
			    "mrsas_ocr thread to quit ocr %d\n", i,
			    sc->ocr_thread_active);
		}
		pause("mr_shutdown", hz);
	}
	mrsas_flush_cache(sc);
	mrsas_shutdown_ctlr(sc, MR_DCMD_CTRL_SHUTDOWN);
	mrsas_disable_intr(sc);
	mrsas_cam_detach(sc);
	mrsas_teardown_intr(sc);
	mrsas_free_mem(sc);
	mtx_destroy(&sc->sim_lock);
	mtx_destroy(&sc->aen_lock);
	mtx_destroy(&sc->pci_lock);
	mtx_destroy(&sc->io_lock);
	mtx_destroy(&sc->ioctl_lock);
	mtx_destroy(&sc->mpt_cmd_pool_lock);
	mtx_destroy(&sc->mfi_cmd_pool_lock);
	mtx_destroy(&sc->raidmap_lock);
	while (sema_value(&sc->ioctl_count_sema) != (MRSAS_MAX_MFI_CMDS - 5))
		pause("mr_shutdown", hz);
	sema_destroy(&sc->ioctl_count_sema);
	if (sc->reg_res) {
		bus_release_resource(sc->mrsas_dev,
		    SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res);
	}
	if (sc->sysctl_tree != NULL)
		sysctl_ctx_free(&sc->sysctl_ctx);
	return (0);
}
static int mrsas_detach ( device_t dev ) { struct mrsas_softc * sc ; int i = 0 ; sc = device_get_softc ( dev ) ; sc -> remove_in_progress = 1 ; if ( ( device_get_unit ( dev ) == 0 ) && sc -> mrsas_linux_emulator_cdev ) destroy_dev ( sc -> mrsas_linux_emulator_cdev ) ; destroy_dev ( sc -> mrsas_cdev ) ; for ( i = 0 ; i < mrsas_mgmt_info . max_index ; i ++ ) { if ( mrsas_mgmt_info . sc_ptr [ i ] == sc ) { mrsas_mgmt_info . count -- ; mrsas_mgmt_info . sc_ptr [ i ] = NULL ; break ; } } if ( sc -> ocr_thread_active ) wakeup ( & sc -> ocr_chan ) ; while ( sc -> reset_in_progress ) { i ++ ; if ( ! ( i % MRSAS_RESET_NOTICE_INTERVAL ) ) { mrsas_dprint ( sc , MRSAS_INFO , " \n " , i , __func__ ) ; } pause ( " " , hz ) ; } i = 0 ; while ( sc -> ocr_thread_active ) { i ++ ; if ( ! ( i % MRSAS_RESET_NOTICE_INTERVAL ) ) { mrsas_dprint ( sc , MRSAS_INFO , " " " \n " , i , sc -> ocr_thread_active ) ; } pause ( " " , hz ) ; } mrsas_flush_cache ( sc ) ; mrsas_shutdown_ctlr ( sc , MR_DCMD_CTRL_SHUTDOWN ) ; mrsas_disable_intr ( sc ) ; mrsas_cam_detach ( sc ) ; mrsas_teardown_intr ( sc ) ; mrsas_free_mem ( sc ) ; mtx_destroy ( & sc -> sim_lock ) ; mtx_destroy ( & sc -> aen_lock ) ; mtx_destroy ( & sc -> pci_lock ) ; mtx_destroy ( & sc -> io_lock ) ; mtx_destroy ( & sc -> ioctl_lock ) ; mtx_destroy ( & sc -> mpt_cmd_pool_lock ) ; mtx_destroy ( & sc -> mfi_cmd_pool_lock ) ; mtx_destroy ( & sc -> raidmap_lock ) ; while ( sema_value ( & sc -> ioctl_count_sema ) != ( MRSAS_MAX_MFI_CMDS - 5 ) ) pause ( " " , hz ) ; sema_destroy ( & sc -> ioctl_count_sema ) ; if ( sc -> reg_res ) { bus_release_resource ( sc -> mrsas_dev , SYS_RES_MEMORY , sc -> reg_res_id , sc -> reg_res ) ; } if ( sc -> sysctl_tree != NULL ) sysctl_ctx_free ( & sc -> sysctl_ctx ) ; return ( 0 ) ; }
mrsas_detach:        De-allocates and teardown resources
 input:                       pointer to device struct
mrsas_detach : De - allocates and teardown resources input : pointer to device struct
/* Destroy the character device so no other IOCTL will be handled */ /*
	 * Take the instance off the instance array. Note that we will not
	 * decrement the max_index. We let this array be sparse array
	 */ /* Wait for all the semaphores to be released */ /* Destroy the counting semaphore created for Ioctl */