Ejemplo n.º 1
0
/*
 * Function: cio_modify
 * Issues a "Modify Subchannel" on the specified subchannel
 */
int
cio_modify (struct subchannel *sch)
{
	int ccode, retry, ret;

	ret = 0;
	for (retry = 0; retry < 5; retry++) {
		ccode = msch_err (sch->irq, &sch->schib);
		if (ccode < 0)	/* -EIO if msch gets a program check. */
			return ccode;
		switch (ccode) {
		case 0: /* successfull */
			return 0;
		case 1:	/* status pending */
			return -EBUSY;
		case 2:	/* busy */
			udelay (100);	/* allow for recovery */
			ret = -EBUSY;
			break;
		case 3:	/* not operational */
			return -ENODEV;
		}
	}
	return ret;
}
Ejemplo n.º 2
0
static int
set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address)
{
	int ret;
	int retry;
	struct subchannel *sch;
	struct schib *schib;

	sch = to_subchannel(cdev->dev.parent);
	schib = &sch->schib;
	/* msch can silently fail, so do it again if necessary */
	for (retry = 0; retry < 3; retry++) {
		/* prepare schib */
		stsch(sch->schid, schib);
		schib->pmcw.mme  = mme;
		schib->pmcw.mbfc = mbfc;
		/* address can be either a block address or a block index */
		if (mbfc)
			schib->mba = address;
		else
			schib->pmcw.mbi = address;

		/* try to submit it */
		switch(ret = msch_err(sch->schid, schib)) {
			case 0:
				break;
			case 1:
			case 2: /* in I/O or status pending */
				ret = -EBUSY;
				break;
			case 3: /* subchannel is no longer valid */
				ret = -ENODEV;
				break;
			default: /* msch caught an exception */
				ret = -EINVAL;
				break;
		}
		stsch(sch->schid, schib); /* restore the schib */

		if (ret)
			break;

		/* check if it worked */
		if (schib->pmcw.mme  == mme &&
		    schib->pmcw.mbfc == mbfc &&
		    (mbfc ? (schib->mba == address)
			  : (schib->pmcw.mbi == address)))
			return 0;

		ret = -EINVAL;
	}

	return ret;
}
Ejemplo n.º 3
0
Archivo: cio.c Proyecto: AllenDou/linux
static int
__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
{
	int retry, cc;

	cc = 0;
	for (retry=0;retry<3;retry++) {
		schib->pmcw.ena = 0;
		cc = msch_err(schid, schib);
		if (cc)
			return (cc==3?-ENODEV:-EBUSY);
		if (stsch_err(schid, schib) || !css_sch_is_valid(schib))
			return -ENODEV;
		if (!schib->pmcw.ena)
			return 0;
	}
	return -EBUSY; /* uhm... */
}
Ejemplo n.º 4
0
/*
 * cio_commit_config - apply configuration to the subchannel
 */
int cio_commit_config(struct subchannel *sch)
{
	int ccode, retry, ret = 0;
	struct schib schib;
	struct irb irb;

	if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib))
		return -ENODEV;

	for (retry = 0; retry < 5; retry++) {
		/* copy desired changes to local schib */
		cio_apply_config(sch, &schib);
		ccode = msch_err(sch->schid, &schib);
		if (ccode < 0) /* -EIO if msch gets a program check. */
			return ccode;
		switch (ccode) {
		case 0: /* successful */
			if (stsch_err(sch->schid, &schib) ||
			    !css_sch_is_valid(&schib))
				return -ENODEV;
			if (cio_check_config(sch, &schib)) {
				/* commit changes from local schib */
				memcpy(&sch->schib, &schib, sizeof(schib));
				return 0;
			}
			ret = -EAGAIN;
			break;
		case 1: /* status pending */
			ret = -EBUSY;
			if (tsch(sch->schid, &irb))
				return ret;
			break;
		case 2: /* busy */
			udelay(100); /* allow for recovery */
			ret = -EBUSY;
			break;
		case 3: /* not operational */
			return -ENODEV;
		}
	}
	return ret;
}
Ejemplo n.º 5
0
int cio_commit_config(struct subchannel *sch)
{
	struct schib schib;
	int ccode, retry, ret = 0;

	if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib))
		return -ENODEV;

	for (retry = 0; retry < 5; retry++) {
		
		cio_apply_config(sch, &schib);
		ccode = msch_err(sch->schid, &schib);
		if (ccode < 0) 
			return ccode;
		switch (ccode) {
		case 0: 
			if (stsch_err(sch->schid, &schib) ||
			    !css_sch_is_valid(&schib))
				return -ENODEV;
			if (cio_check_config(sch, &schib)) {
				
				memcpy(&sch->schib, &schib, sizeof(schib));
				return 0;
			}
			ret = -EAGAIN;
			break;
		case 1: 
			return -EBUSY;
		case 2: 
			udelay(100); 
			ret = -EBUSY;
			break;
		case 3: 
			return -ENODEV;
		}
	}
	return ret;
}