Example #1
0
/*
 * vdds_match_niu_node -- callback function to verify a node is the
 *	NIU Hybrid node.
 */
static int
vdds_match_niu_node(dev_info_t *dip, void *arg)
{
	vdds_cb_arg_t	*warg = (vdds_cb_arg_t *)arg;
	char		*name;
	vdds_reg_t	*reg_p;
	uint_t		reglen;
	int		rv;
	uint32_t	addr_hi;

	name = ddi_node_name(dip);
	if (strcmp(name, "network")  != 0) {
		return (DDI_WALK_CONTINUE);
	}
	rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
	    DDI_PROP_DONTPASS, "reg", (int **)&reg_p, &reglen);
	if (rv != DDI_PROP_SUCCESS) {
		DWARN(NULL, "Failed to get reg property dip=0x%p", dip);
		return (DDI_WALK_CONTINUE);
	}

	addr_hi = reg_p->addr_hi;
	DBG1(NULL, "addr_hi = 0x%x dip=0x%p", addr_hi, dip);
	ddi_prop_free(reg_p);
	if (addr_hi == HVCOOKIE(warg->cookie)) {
		warg->dip = dip;
		if (!e_ddi_branch_held(dip))
			e_ddi_branch_hold(dip);
		DBG1(NULL, "Found dip = 0x%p", dip);
		return (DDI_WALK_TERMINATE);
	}
	return (DDI_WALK_CONTINUE);
}
Example #2
0
static int
dr_check_io_refs(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum)
{
	register int	i, reftotal = 0;
	static fn_t	f = "dr_check_io_refs";

	for (i = 0; i < devnum; i++) {
		dr_io_unit_t	*ip = (dr_io_unit_t *)devlist[i];
		dev_info_t	*dip;
		int		ref;
		sbd_error_t	*err;

		err = drmach_get_dip(ip->sbi_cm.sbdev_id, &dip);
		if (err)
			DRERR_SET_C(&ip->sbi_cm.sbdev_error, &err);
		else if (dip != NULL) {
			ref = 0;
			ASSERT(e_ddi_branch_held(dip));
			dr_check_devices(dip, &ref, hp, NULL, NULL, 0);
			hp->h_err = NULL;
			if (ref) {
				dr_dev_err(CE_WARN, &ip->sbi_cm, ESBD_BUSY);
			}
			PR_IO("%s: dip(%s) ref = %d\n",
				f, ddi_get_name(dip), ref);
			reftotal += ref;
		} else {
			PR_IO("%s: NO dip for id (0x%x)\n",
				f, (uint_t)(uintptr_t)ip->sbi_cm.sbdev_id);
		}
	}

	return (reftotal);
}
void
sbdp_check_devices(dev_info_t *dip, int *refcount, sbd_error_t *sep)
{
	sbdp_ref_t sbr;

	sbr.refcount = refcount;
	sbr.sep = sep;

	ASSERT(e_ddi_branch_held(dip));

	(void) e_ddi_branch_referenced(dip, sbdp_check_dip, &sbr);
}
Example #4
0
/*ARGSUSED*/
void
sbd_attach_io(sbd_handle_t *hp, sbderror_t *ep, dev_info_t *dip, int unit)
{
	sbd_board_t	*sbp = SBDH2BD(hp->h_sbd);

	ASSERT(e_ddi_branch_held(dip));

	(void) e_ddi_branch_configure(dip, NULL, 0);

	ASSERT(sbp->sb_iopath[unit] != NULL);

	(void) ddi_pathname(dip, sbp->sb_iopath[unit]);
}
Example #5
0
/*ARGSUSED*/
void
dr_check_devices(dev_info_t *dip, int *refcount, dr_handle_t *handle,
    uint64_t *arr, int *idx, int len)
{
	struct dr_ref bref = {0};

	if (dip == NULL)
		return;

	bref.refcount = refcount;
	bref.arr = arr;
	bref.idx = idx;
	bref.len = len;

	ASSERT(e_ddi_branch_held(dip));
	(void) e_ddi_branch_referenced(dip, dr_check_dip, &bref);
}
Example #6
0
/*
 * vdds_destroy_niu_node -- Destroy the NIU node.
 */
int
vdds_destroy_niu_node(dev_info_t *niu_dip, uint64_t cookie)
{
	int rv;
	dev_info_t *fdip = NULL;
	dev_info_t *nexus_dip = ddi_get_parent(niu_dip);


	DBG1(NULL, "Called");
	ASSERT(nexus_dip != NULL);
	mutex_enter(&vdds_dev_lock);

	if (!e_ddi_branch_held(niu_dip))
		e_ddi_branch_hold(niu_dip);
	/*
	 * As we are destroying now, release the
	 * hold that was done in during the creation.
	 */
	ddi_release_devi(niu_dip);
	rv = e_ddi_branch_destroy(niu_dip, &fdip, 0);
	if (rv != 0) {
		DERR(NULL, "Failed to destroy niumx/network node dip=0x%p",
		    niu_dip);
		if (fdip != NULL) {
			ddi_release_devi(fdip);
		}
		rv = EBUSY;
		goto dest_exit;
	}
	/*
	 * Cleanup the parent's ranges property set
	 * for this Hybrid device.
	 */
	vdds_release_range_prop(nexus_dip, cookie);

dest_exit:
	mutex_exit(&vdds_dev_lock);
	DBG1(NULL, "returning rv=%d", rv);
	return (rv);
}
Example #7
0
/*
 * vdds_match_niu_nexus -- callback function to verify a node is the
 *	NIU nexus node.
 */
static int
vdds_match_niu_nexus(dev_info_t *dip, void *arg)
{
	vdds_cb_arg_t	*warg = (vdds_cb_arg_t *)arg;
	vdds_reg_t	*reg_p;
	char		*name;
	uint64_t	hdl;
	uint_t		reglen;
	int		rv;

	if (dip == ddi_root_node()) {
		return (DDI_WALK_CONTINUE);
	}

	name = ddi_node_name(dip);
	if (strcmp(name, "niu")  != 0) {
		return (DDI_WALK_CONTINUE);
	}
	rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
	    DDI_PROP_DONTPASS, "reg", (int **)&reg_p, &reglen);
	if (rv != DDI_PROP_SUCCESS) {
		DWARN(NULL, "Failed to get reg property dip=0x%p", dip);
		return (DDI_WALK_CONTINUE);
	}

	hdl =  reg_p->addr_hi & 0x0FFFFFFF;
	ddi_prop_free(reg_p);

	DBG2(NULL, "Handle = 0x%lx dip=0x%p", hdl, dip);
	if (hdl == NIUCFGHDL(warg->cookie)) {
		/* Hold before returning */
		if (!e_ddi_branch_held(dip))
			e_ddi_branch_hold(dip);
		warg->dip = dip;
		DBG2(NULL, "Found dip = 0x%p", dip);
		return (DDI_WALK_TERMINATE);
	}
	return (DDI_WALK_CONTINUE);
}
Example #8
0
/*ARGSUSED*/
void
sbd_detach_io(sbd_handle_t *hp, sbderror_t *ep, dev_info_t *dip, int unit)
{
	int rv;
	dev_info_t *fdip = NULL;
	sbd_board_t *sbp = SBDH2BD(hp->h_sbd);

	ASSERT(e_ddi_branch_held(dip));
	mutex_enter(&sbp->sb_slock);
	rv = e_ddi_branch_unconfigure(dip, &fdip, DEVI_BRANCH_EVENT);
	mutex_exit(&sbp->sb_slock);
	if (rv) {
		/*
		 * If non-NULL, fdip is returned held and must be released.
		 */
		if (fdip != NULL) {
			sbd_errno_decode(rv, ep, fdip);
			ddi_release_devi(fdip);
		} else {
			sbd_errno_decode(rv, ep, dip);
		}
	}
}
Example #9
0
/*
 * vdds_create_niu_node -- Create NIU Hybrid node. The NIU nexus
 *	node also created if it doesn't exist already.
 */
dev_info_t *
vdds_create_niu_node(uint64_t cookie, uint64_t macaddr, uint32_t max_frame_size)
{
	dev_info_t *nexus_dip;
	dev_info_t *niu_dip;
	vdds_cb_arg_t cba;

	DBG1(NULL, "Called");

	if (vdds_hv_hio_capable == B_FALSE) {
		return (NULL);
	}
	mutex_enter(&vdds_dev_lock);
	/* Check if the nexus node exists already */
	nexus_dip = vdds_find_node(cookie, ddi_root_node(),
	    vdds_match_niu_nexus);
	if (nexus_dip == NULL) {
		/*
		 * NIU nexus node not found, so create it now.
		 */
		cba.dip = NULL;
		cba.cookie = cookie;
		cba.macaddr = macaddr;
		cba.max_frame_size = max_frame_size;
		nexus_dip = vdds_create_new_node(&cba, NULL,
		    vdds_new_nexus_node);
		if (nexus_dip == NULL) {
			mutex_exit(&vdds_dev_lock);
			return (NULL);
		}
	}
	DBG2(NULL, "nexus_dip = 0x%p", nexus_dip);

	/* Check if NIU node exists already before creating one */
	niu_dip = vdds_find_node(cookie, nexus_dip,
	    vdds_match_niu_node);
	if (niu_dip == NULL) {
		cba.dip = NULL;
		cba.cookie = cookie;
		cba.macaddr = macaddr;
		cba.max_frame_size = max_frame_size;
		niu_dip = vdds_create_new_node(&cba, nexus_dip,
		    vdds_new_niu_node);
		/*
		 * Hold the niu_dip to prevent it from
		 * detaching.
		 */
		if (niu_dip != NULL) {
			e_ddi_hold_devi(niu_dip);
		} else {
			DWARN(NULL, "niumx/network node creation failed");
		}
	} else {
		DWARN(NULL, "niumx/network node already exists(dip=0x%p)",
		    niu_dip);
	}
	/* release the hold that was done in find/create */
	if ((niu_dip != NULL) && (e_ddi_branch_held(niu_dip)))
		e_ddi_branch_rele(niu_dip);
	if (e_ddi_branch_held(nexus_dip))
		e_ddi_branch_rele(nexus_dip);
	mutex_exit(&vdds_dev_lock);
	DBG1(NULL, "returning niu_dip=0x%p", niu_dip);
	return (niu_dip);
}
Example #10
0
int
dr_io_status(dr_handle_t *hp, dr_devset_t devset, sbd_dev_stat_t *dsp)
{
	int		i, ix;
	dr_board_t	*bp;
	sbd_io_stat_t	*isp;
	dr_io_unit_t	*ip;

	bp = hp->h_bd;

	/*
	 * Only look for requested devices that are actually present.
	 */
	devset &= DR_DEVS_PRESENT(bp);

	for (i = ix = 0; i < MAX_IO_UNITS_PER_BOARD; i++) {
		drmachid_t	 id;
		dev_info_t	*dip;
		sbd_error_t	*err;
		drmach_status_t	 pstat;

		if (DEVSET_IN_SET(devset, SBD_COMP_IO, i) == 0)
			continue;

		ip = dr_get_io_unit(bp, i);

		if (ip->sbi_cm.sbdev_state == DR_STATE_EMPTY) {
			/* present, but not fully initialized */
			continue;
		}

		id = ip->sbi_cm.sbdev_id;
		if (id == (drmachid_t)0)
			continue;

		err = drmach_status(ip->sbi_cm.sbdev_id, &pstat);
		if (err) {
			DRERR_SET_C(&ip->sbi_cm.sbdev_error, &err);
			return (-1);
		}

		dip = NULL;
		err = drmach_get_dip(id, &dip);
		if (err) {
			/* catch this in debug kernels */
			ASSERT(0);

			sbd_err_clear(&err);
			continue;
		}

		isp = &dsp->d_io;
		bzero((caddr_t)isp, sizeof (*isp));

		isp->is_cm.c_id.c_type = ip->sbi_cm.sbdev_type;
		isp->is_cm.c_id.c_unit = ip->sbi_cm.sbdev_unum;
		strncpy(isp->is_cm.c_id.c_name, pstat.type,
			sizeof (isp->is_cm.c_id.c_name));

		dr_get_comp_cond(ip, dip);
		isp->is_cm.c_cond = ip->sbi_cm.sbdev_cond;
		isp->is_cm.c_busy = ip->sbi_cm.sbdev_busy | pstat.busy;
		isp->is_cm.c_time = ip->sbi_cm.sbdev_time;
		isp->is_cm.c_ostate = ip->sbi_cm.sbdev_ostate;
		isp->is_cm.c_sflags = 0;

		if (dip == NULL) {
			isp->is_pathname[0] = '\0';
			isp->is_referenced = 0;
			isp->is_unsafe_count = 0;
		} else {
			int		refcount = 0, idx = 0;
			uint64_t	unsafe_devs[SBD_MAX_UNSAFE];

			ASSERT(e_ddi_branch_held(dip));
			(void) ddi_pathname(dip, isp->is_pathname);

			/* check reference and unsafe counts on devices */
			isp->is_unsafe_count = 0;
			dr_check_devices(dip, &refcount, hp, unsafe_devs,
				&idx, SBD_MAX_UNSAFE);
			while (idx > 0) {
				isp->is_unsafe_list[idx-1] = unsafe_devs[idx-1];
				--idx;
			}

			isp->is_referenced = (refcount == 0) ? 0 : 1;

			hp->h_err = NULL;
		}
		ix++;
		dsp++;
	}

	return (ix);
}