コード例 #1
0
ファイル: ghd.c プロジェクト: MatiasNAmendola/AuroraUX-SunOS
int
ghd_tran_reset_bus(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status)
{
	int	rc;

	mutex_enter(&cccp->ccc_hba_mutex);
	ghd_doneq_pollmode_enter(cccp);

	/* send out the bus reset request */
	ghd_timer_newstate(cccp, NULL, gtgtp, GACTION_RESET_BUS, GHD_TGTREQ);

	/*
	 * Wait for all active requests on this HBA to complete
	 */
	rc = ghd_poll(cccp, GHD_POLL_ALL, ghd_tran_reset_bus_timeout,
	    NULL, NULL, intr_status);


	ghd_doneq_pollmode_exit(cccp);

	mutex_enter(&cccp->ccc_waitq_mutex);
	ghd_waitq_process_and_mutex_exit(cccp);

	return (rc);
}
コード例 #2
0
ファイル: ghd.c プロジェクト: MatiasNAmendola/AuroraUX-SunOS
int
ghd_tran_abort_lun(ccc_t *cccp,	gtgt_t *gtgtp, void *intr_status)
{
	int	 rc;

	/*
	 * call the HBA driver's abort_device function
	 */

	mutex_enter(&cccp->ccc_hba_mutex);
	ghd_doneq_pollmode_enter(cccp);

	/* send out the abort device request */
	ghd_timer_newstate(cccp, NULL, gtgtp, GACTION_ABORT_DEV, GHD_TGTREQ);

	/* wait for the device to go idle */
	rc = ghd_poll(cccp, GHD_POLL_DEVICE, ghd_tran_abort_lun_timeout,
	    NULL, gtgtp, intr_status);

	ghd_doneq_pollmode_exit(cccp);

	mutex_enter(&cccp->ccc_waitq_mutex);
	ghd_waitq_process_and_mutex_exit(cccp);

	return (rc);
}
コード例 #3
0
/*ARGSUSED*/
void
ghd_target_free(dev_info_t	*hba_dip,
		dev_info_t	*tgt_dip,
		ccc_t		*cccp,
		gtgt_t		*gtgtp)
{
	_NOTE(ARGUNUSED(hba_dip,tgt_dip))

	gdev_t	*gdevp = gtgtp->gt_gdevp;

	GDBG_WAITQ(("ghd_target_free(%d,%d) gdevp-0x%p gtgtp 0x%p\n",
	    gtgtp->gt_target, gtgtp->gt_lun, (void *)gdevp, (void *)gtgtp));

	/*
	 * grab both mutexes so the queue structures
	 * stay stable while deleting this instance
	 */
	mutex_enter(&cccp->ccc_hba_mutex);
	mutex_enter(&cccp->ccc_waitq_mutex);

	ASSERT(gdevp->gd_ninstances > 0);

	/*
	 * remove this per-instance structure from the device list and
	 * free the memory
	 */
	GTGT_DEATTACH(gtgtp, gdevp);
	kmem_free((caddr_t)gtgtp, gtgtp->gt_size);

	if (gdevp->gd_ninstances == 1) {
		GDBG_WAITQ(("ghd_target_free: N=1 gdevp 0x%p\n",
		    (void *)gdevp));
		/*
		 * If there's now just one instance left attached to this
		 * device then reset the queue's max active value
		 * from that instance's saved value.
		 */
		gtgtp = GDEVP2GTGTP(gdevp);
		GDEV_MAXACTIVE(gdevp) = gtgtp->gt_maxactive;

	} else if (gdevp->gd_ninstances == 0) {
		/* else no instances left */
		GDBG_WAITQ(("ghd_target_free: N=0 gdevp 0x%p\n",
		    (void *)gdevp));

		/* detach this per-dev-structure from the HBA's dev list */
		GDEV_QDETACH(gdevp, cccp);
		kmem_free(gdevp, sizeof (*gdevp));

	}
#if defined(GHD_DEBUG) || defined(__lint)
	else {
		/* leave maxactive set to 1 */
		GDBG_WAITQ(("ghd_target_free: N>1 gdevp 0x%p\n",
		    (void *)gdevp));
	}
#endif

	ghd_waitq_process_and_mutex_exit(cccp);
}
コード例 #4
0
ファイル: ghd.c プロジェクト: MatiasNAmendola/AuroraUX-SunOS
int
ghd_tran_abort(ccc_t *cccp, gcmd_t *gcmdp, gtgt_t *gtgtp, void *intr_status)
{
	gact_t	 action;
	int	 rc;

	/*
	 * call the driver's abort_cmd function
	 */

	mutex_enter(&cccp->ccc_hba_mutex);
	ghd_doneq_pollmode_enter(cccp);

	switch (gcmdp->cmd_state) {
	case GCMD_STATE_WAITQ:
		/* not yet started */
		action = GACTION_EARLY_ABORT;
		break;

	case GCMD_STATE_ACTIVE:
		/* in progress */
		action = GACTION_ABORT_CMD;
		break;

	default:
		/* everything else, probably already being aborted */
		rc = FALSE;
		goto exit;
	}

	/* stop the timer and remove it from the active list */
	GHD_TIMER_STOP(cccp, gcmdp);

	/* start a new timer and send out the abort command */
	ghd_timer_newstate(cccp, gcmdp, gtgtp, action, GHD_TGTREQ);

	/* wait for the abort to complete */
	if (rc = ghd_poll(cccp, GHD_POLL_REQUEST, ghd_tran_abort_timeout,
	    gcmdp, gtgtp, intr_status)) {
		gcmdp->cmd_state = GCMD_STATE_DONEQ;
		GHD_DONEQ_PUT_TAIL(cccp, gcmdp);
	}

exit:
	ghd_doneq_pollmode_exit(cccp);

	mutex_enter(&cccp->ccc_waitq_mutex);
	ghd_waitq_process_and_mutex_exit(cccp);

	return (rc);
}
コード例 #5
0
ファイル: ghd.c プロジェクト: MatiasNAmendola/AuroraUX-SunOS
int
ghd_tran_reset_target(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status)
{
	int rc = TRUE;


	mutex_enter(&cccp->ccc_hba_mutex);
	ghd_doneq_pollmode_enter(cccp);

	/* send out the device reset request */
	ghd_timer_newstate(cccp, NULL, gtgtp, GACTION_RESET_TARGET, GHD_TGTREQ);

	/* wait for the device to reset */
	rc = ghd_poll(cccp, GHD_POLL_DEVICE, ghd_tran_reset_target_timeout,
	    NULL, gtgtp, intr_status);

	ghd_doneq_pollmode_exit(cccp);

	mutex_enter(&cccp->ccc_waitq_mutex);
	ghd_waitq_process_and_mutex_exit(cccp);

	return (rc);
}
コード例 #6
0
ファイル: ghd.c プロジェクト: MatiasNAmendola/AuroraUX-SunOS
int
ghd_transport(ccc_t	*cccp,
		gcmd_t	*gcmdp,
		gtgt_t	*gtgtp,
		ulong_t	 timeout,
		int	 polled,
		void	*intr_status)
{
	gdev_t	*gdevp = gtgtp->gt_gdevp;

	ASSERT(!mutex_owned(&cccp->ccc_hba_mutex));
	ASSERT(!mutex_owned(&cccp->ccc_waitq_mutex));

	if (polled) {
		/*
		 * Grab the HBA mutex so no other requests are started
		 * until after this one completes.
		 */
		mutex_enter(&cccp->ccc_hba_mutex);

		GDBG_START(("ghd_transport: polled"
		    " cccp 0x%p gdevp 0x%p gtgtp 0x%p gcmdp 0x%p\n",
		    (void *)cccp, (void *)gdevp, (void *)gtgtp, (void *)gcmdp));

		/*
		 * Lock the doneq so no other thread flushes the Q.
		 */
		ghd_doneq_pollmode_enter(cccp);
	}
#if defined(GHD_DEBUG) || defined(__lint)
	else {
		GDBG_START(("ghd_transport: non-polled"
		    " cccp 0x%p gdevp 0x%p gtgtp 0x%p gcmdp 0x%p\n",
		    (void *)cccp, (void *)gdevp, (void *)gtgtp, (void *)gcmdp));
	}
#endif
	/*
	 * add this request to the tail of the waitq
	 */
	gcmdp->cmd_waitq_level = 1;
	mutex_enter(&cccp->ccc_waitq_mutex);
	L2_add(&GDEV_QHEAD(gdevp), &gcmdp->cmd_q, gcmdp);

	/*
	 * Add this request to the packet timer active list and start its
	 * abort timer.
	 */
	gcmdp->cmd_state = GCMD_STATE_WAITQ;
	ghd_timer_start(cccp, gcmdp, timeout);


	/*
	 * Check the device wait queue throttle and perhaps move
	 * some requests to the end of the HBA wait queue.
	 */
	ghd_waitq_shuffle_up(cccp, gdevp);

	if (!polled) {
		/*
		 * See if the HBA mutex is available but use the
		 * tryenter so I don't deadlock.
		 */
		if (!mutex_tryenter(&cccp->ccc_hba_mutex)) {
			/* The HBA mutex isn't available */
			GDBG_START(("ghd_transport: !mutex cccp 0x%p\n",
			    (void *)cccp));
			mutex_exit(&cccp->ccc_waitq_mutex);
			return (TRAN_ACCEPT);
		}
		GDBG_START(("ghd_transport: got mutex cccp 0x%p\n",
		    (void *)cccp));

		/*
		 * start as many requests as possible from the head
		 * of the HBA wait queue
		 */

		ghd_waitq_process_and_mutex_exit(cccp);

		ASSERT(!mutex_owned(&cccp->ccc_hba_mutex));
		ASSERT(!mutex_owned(&cccp->ccc_waitq_mutex));

		return (TRAN_ACCEPT);
	}


	/*
	 * If polled mode (FLAG_NOINTR specified in scsi_pkt flags),
	 * then ghd_poll() waits until the request completes or times out
	 * before returning.
	 */

	mutex_exit(&cccp->ccc_waitq_mutex);
	(void) ghd_poll(cccp, GHD_POLL_REQUEST, 0, gcmdp, gtgtp, intr_status);
	ghd_doneq_pollmode_exit(cccp);

	mutex_enter(&cccp->ccc_waitq_mutex);
	ghd_waitq_process_and_mutex_exit(cccp);

	/* call HBA's completion function but don't do callback to target */
	(*cccp->ccc_hba_complete)(cccp->ccc_hba_handle, gcmdp, FALSE);

	GDBG_START(("ghd_transport: polled done cccp 0x%p\n", (void *)cccp));
	return (TRAN_ACCEPT);
}
コード例 #7
0
ファイル: ghd_waitq.c プロジェクト: andreiw/polaris
/*ARGSUSED*/
gtgt_t *
ghd_target_init(dev_info_t	*hba_dip,
		dev_info_t	*tgt_dip,
		ccc_t		*cccp,
		size_t		 tgt_private_size,
		void		*hba_private,
		ushort_t	 target,
		uchar_t		 lun)
{
	_NOTE(ARGUNUSED(hba_dip))
	gtgt_t	*gtgtp;
	size_t	 size = sizeof (*gtgtp) + tgt_private_size;
	gdev_t	*gdevp;
	ulong_t	 maxactive;

	gtgtp = kmem_zalloc(size, KM_SLEEP);

	/*
	 * initialize the per instance structure
	 */

	gtgtp->gt_tgt_private = (void *)(gtgtp + 1);
	gtgtp->gt_size = size;
	gtgtp->gt_hba_private = hba_private;
	gtgtp->gt_target = target;
	gtgtp->gt_lun = lun;
	gtgtp->gt_ccc = cccp;

	/*
	 * set the queue's maxactive to 1 if
	 * property not specified on target or hba devinfo node
	 */
	maxactive = ddi_getprop(DDI_DEV_T_ANY, tgt_dip, 0, "ghd-maxactive", 1);
	gtgtp->gt_maxactive = maxactive;

	/* initialize the linked list pointers */
	GTGT_INIT(gtgtp);

	/*
	 * grab both mutexes so the queue structures
	 * stay stable while adding this instance to the linked lists
	 */
	mutex_enter(&cccp->ccc_hba_mutex);
	mutex_enter(&cccp->ccc_waitq_mutex);

	/*
	 * Search the HBA's linked list of device structures.
	 *
	 * If this device is already attached then link this instance
	 * to the existing per-device-structure on the ccc_devs list.
	 *
	 */
	gdevp = CCCP2GDEVP(cccp);
	while (gdevp != NULL) {
		if (gdevp->gd_target == target && gdevp->gd_lun == lun) {
			GDBG_WAITQ(("ghd_target_init(%d,%d) found gdevp 0x%p"
				" gtgtp 0x%p max %lu\n",
					target, lun, gdevp, gtgtp, maxactive));

			goto foundit;
		}
		gdevp = GDEV_NEXTP(gdevp);
	}

	/*
	 * Not found. This is the first instance for this device.
	 */


	/* allocate the per-device-structure */

	gdevp = kmem_zalloc(sizeof (*gdevp), KM_SLEEP);
	gdevp->gd_target = target;
	gdevp->gd_lun = lun;

	/*
	 * link this second level queue to the HBA's first
	 * level queue
	 */
	GDEV_QATTACH(gdevp, cccp, maxactive);

	GDBG_WAITQ(("ghd_target_init(%d,%d) new gdevp 0x%p gtgtp 0x%p"
		    " max %lu\n", target, lun, gdevp, gtgtp, maxactive));

foundit:

	/* save the ptr to the per device structure */
	gtgtp->gt_gdevp = gdevp;

	/* Add the per instance structure to the per device list  */
	GTGT_ATTACH(gtgtp, gdevp);

	ghd_waitq_process_and_mutex_exit(cccp);

	return (gtgtp);
}