Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ec22984 authored by Cornelia Huck's avatar Cornelia Huck Committed by Martin Schwidefsky
Browse files

[S390] subchannel lock conversion.



Convert the subchannel lock to a pointer to a lock.  Needed for the dynamic
subchannel mapping patch.

Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 7674da77
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -183,7 +183,7 @@ css_get_ssd_info(struct subchannel *sch)
	page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
	if (!page)
		return -ENOMEM;
	spin_lock_irq(&sch->lock);
	spin_lock_irq(sch->lock);
	ret = chsc_get_sch_desc_irq(sch, page);
	if (ret) {
		static int cio_chsc_err_msg;
@@ -197,7 +197,7 @@ css_get_ssd_info(struct subchannel *sch)
			cio_chsc_err_msg = 1;
		}
	}
	spin_unlock_irq(&sch->lock);
	spin_unlock_irq(sch->lock);
	free_page((unsigned long)page);
	if (!ret) {
		int j, chpid, mask;
@@ -233,7 +233,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
	if (j >= 8)
		return 0;

	spin_lock_irq(&sch->lock);
	spin_lock_irq(sch->lock);

	stsch(sch->schid, &schib);
	if (!schib.pmcw.dnv)
@@ -265,10 +265,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
	else if (sch->lpm == mask)
		goto out_unreg;
out_unlock:
	spin_unlock_irq(&sch->lock);
	spin_unlock_irq(sch->lock);
	return 0;
out_unreg:
	spin_unlock_irq(&sch->lock);
	spin_unlock_irq(sch->lock);
	sch->lpm = 0;
	if (css_enqueue_subchannel_slow(sch->schid)) {
		css_clear_subchannel_slow_list();
@@ -378,12 +378,12 @@ __s390_process_res_acc(struct subchannel_id schid, void *data)
		/* Check if a subchannel is newly available. */
		return s390_process_res_acc_new_sch(schid);

	spin_lock_irq(&sch->lock);
	spin_lock_irq(sch->lock);

	chp_mask = s390_process_res_acc_sch(res_data, sch);

	if (chp_mask == 0) {
		spin_unlock_irq(&sch->lock);
		spin_unlock_irq(sch->lock);
		put_device(&sch->dev);
		return 0;
	}
@@ -397,7 +397,7 @@ __s390_process_res_acc(struct subchannel_id schid, void *data)
	else if (sch->driver && sch->driver->verify)
		sch->driver->verify(&sch->dev);

	spin_unlock_irq(&sch->lock);
	spin_unlock_irq(sch->lock);
	put_device(&sch->dev);
	return 0;
}
@@ -635,21 +635,21 @@ __chp_add(struct subchannel_id schid, void *data)
	if (!sch)
		/* Check if the subchannel is now available. */
		return __chp_add_new_sch(schid);
	spin_lock_irq(&sch->lock);
	spin_lock_irq(sch->lock);
	for (i=0; i<8; i++) {
		mask = 0x80 >> i;
		if ((sch->schib.pmcw.pim & mask) &&
		    (sch->schib.pmcw.chpid[i] == chp->id)) {
			if (stsch(sch->schid, &sch->schib) != 0) {
				/* Endgame. */
				spin_unlock_irq(&sch->lock);
				spin_unlock_irq(sch->lock);
				return -ENXIO;
			}
			break;
		}
	}
	if (i==8) {
		spin_unlock_irq(&sch->lock);
		spin_unlock_irq(sch->lock);
		return 0;
	}
	sch->lpm = ((sch->schib.pmcw.pim &
@@ -660,7 +660,7 @@ __chp_add(struct subchannel_id schid, void *data)
	if (sch->driver && sch->driver->verify)
		sch->driver->verify(&sch->dev);

	spin_unlock_irq(&sch->lock);
	spin_unlock_irq(sch->lock);
	put_device(&sch->dev);
	return 0;
}
@@ -750,7 +750,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
	if (!sch->ssd_info.valid)
		return;
	
	spin_lock_irqsave(&sch->lock, flags);
	spin_lock_irqsave(sch->lock, flags);
	old_lpm = sch->lpm;
	for (chp = 0; chp < 8; chp++) {
		if (sch->ssd_info.chpid[chp] != chpid)
@@ -785,7 +785,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
			sch->driver->verify(&sch->dev);
		break;
	}
	spin_unlock_irqrestore(&sch->lock, flags);
	spin_unlock_irqrestore(sch->lock, flags);
}

static int
+41 −17
Original line number Diff line number Diff line
@@ -143,11 +143,11 @@ cio_tpi(void)
		return 1;
	local_bh_disable();
	irq_enter ();
	spin_lock(&sch->lock);
	spin_lock(sch->lock);
	memcpy (&sch->schib.scsw, &irb->scsw, sizeof (struct scsw));
	if (sch->driver && sch->driver->irq)
		sch->driver->irq(&sch->dev);
	spin_unlock(&sch->lock);
	spin_unlock(sch->lock);
	irq_exit ();
	_local_bh_enable();
	return 1;
@@ -496,6 +496,15 @@ cio_disable_subchannel (struct subchannel *sch)
	return ret;
}

static int cio_create_sch_lock(struct subchannel *sch)
{
	sch->lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
	if (!sch->lock)
		return -ENOMEM;
	spin_lock_init(sch->lock);
	return 0;
}

/*
 * cio_validate_subchannel()
 *
@@ -513,6 +522,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
{
	char dbf_txt[15];
	int ccode;
	int err;

	sprintf (dbf_txt, "valsch%x", schid.sch_no);
	CIO_TRACE_EVENT (4, dbf_txt);
@@ -520,9 +530,15 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
	/* Nuke all fields. */
	memset(sch, 0, sizeof(struct subchannel));

	spin_lock_init(&sch->lock);
	sch->schid = schid;
	if (cio_is_console(schid)) {
		sch->lock = cio_get_console_lock();
	} else {
		err = cio_create_sch_lock(sch);
		if (err)
			goto out;
	}
	mutex_init(&sch->reg_mutex);

	/* Set a name for the subchannel */
	snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
		  schid.sch_no);
@@ -534,10 +550,10 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
	 *  is not valid.
	 */
	ccode = stsch_err (schid, &sch->schib);
	if (ccode)
		return (ccode == 3) ? -ENXIO : ccode;

	sch->schid = schid;
	if (ccode) {
		err = (ccode == 3) ? -ENXIO : ccode;
		goto out;
	}
	/* Copy subchannel type from path management control word. */
	sch->st = sch->schib.pmcw.st;

@@ -550,14 +566,16 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
			  "non-I/O subchannel type %04X\n",
			  sch->schid.ssid, sch->schid.sch_no, sch->st);
		/* We stop here for non-io subchannels. */
		return sch->st;
		err = sch->st;
		goto out;
	}

	/* Initialization for io subchannels. */
	if (!sch->schib.pmcw.dnv)
	if (!sch->schib.pmcw.dnv) {
		/* io subchannel but device number is invalid. */
		return -ENODEV;

		err = -ENODEV;
		goto out;
	}
	/* Devno is valid. */
	if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) {
		/*
@@ -567,7 +585,8 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
		CIO_MSG_EVENT(0, "Blacklisted device detected "
			      "at devno %04X, subchannel set %x\n",
			      sch->schib.pmcw.dev, sch->schid.ssid);
		return -ENODEV;
		err = -ENODEV;
		goto out;
	}
	sch->opm = 0xff;
	if (!cio_is_console(sch->schid))
@@ -595,6 +614,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
	if ((sch->lpm & (sch->lpm - 1)) != 0)
		sch->schib.pmcw.mp = 1;	/* multipath mode */
	return 0;
out:
	if (!cio_is_console(schid))
		kfree(sch->lock);
	sch->lock = NULL;
	return err;
}

/*
@@ -637,7 +661,7 @@ do_IRQ (struct pt_regs *regs)
		}
		sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
		if (sch)
			spin_lock(&sch->lock);
			spin_lock(sch->lock);
		/* Store interrupt response block to lowcore. */
		if (tsch (tpi_info->schid, irb) == 0 && sch) {
			/* Keep subchannel information word up to date. */
@@ -648,7 +672,7 @@ do_IRQ (struct pt_regs *regs)
				sch->driver->irq(&sch->dev);
		}
		if (sch)
			spin_unlock(&sch->lock);
			spin_unlock(sch->lock);
		/*
		 * Are more interrupts pending?
		 * If so, the tpi instruction will update the lowcore
@@ -687,10 +711,10 @@ wait_cons_dev (void)
	__ctl_load (cr6, 6, 6);

	do {
		spin_unlock(&console_subchannel.lock);
		spin_unlock(console_subchannel.lock);
		if (!cio_tpi())
			cpu_relax();
		spin_lock(&console_subchannel.lock);
		spin_lock(console_subchannel.lock);
	} while (console_subchannel.schib.scsw.actl != 0);
	/*
	 * restore previous isc value
+3 −1
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ struct orb {
/* subchannel data structure used by I/O subroutines */
struct subchannel {
	struct subchannel_id schid;
	spinlock_t lock;	/* subchannel lock */
	spinlock_t *lock;	/* subchannel lock */
	struct mutex reg_mutex;
	enum {
		SUBCHANNEL_TYPE_IO = 0,
@@ -137,9 +137,11 @@ extern struct subchannel *cio_probe_console(void);
extern void cio_release_console(void);
extern int cio_is_console(struct subchannel_id);
extern struct subchannel *cio_get_console_subchannel(void);
extern spinlock_t * cio_get_console_lock(void);
#else
#define cio_is_console(schid) 0
#define cio_get_console_subchannel() NULL
#define cio_get_console_lock() NULL;
#endif

extern int cio_show_msg;
+12 −10
Original line number Diff line number Diff line
@@ -91,9 +91,9 @@ css_free_subchannel(struct subchannel *sch)
		/* Reset intparm to zeroes. */
		sch->schib.pmcw.intparm = 0;
		cio_modify(sch);
		kfree(sch->lock);
		kfree(sch);
	}
	
}

static void
@@ -102,9 +102,11 @@ css_subchannel_release(struct device *dev)
	struct subchannel *sch;

	sch = to_subchannel(dev);
	if (!cio_is_console(sch->schid))
	if (!cio_is_console(sch->schid)) {
		kfree(sch->lock);
		kfree(sch);
	}
}

extern int css_get_ssd_info(struct subchannel *sch);

@@ -206,18 +208,18 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
	unsigned long flags;
	enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE } action;

	spin_lock_irqsave(&sch->lock, flags);
	spin_lock_irqsave(sch->lock, flags);
	disc = device_is_disconnected(sch);
	if (disc && slow) {
		/* Disconnected devices are evaluated directly only.*/
		spin_unlock_irqrestore(&sch->lock, flags);
		spin_unlock_irqrestore(sch->lock, flags);
		return 0;
	}
	/* No interrupt after machine check - kill pending timers. */
	device_kill_pending_timer(sch);
	if (!disc && !slow) {
		/* Non-disconnected devices are evaluated on the slow path. */
		spin_unlock_irqrestore(&sch->lock, flags);
		spin_unlock_irqrestore(sch->lock, flags);
		return -EAGAIN;
	}
	event = css_get_subchannel_status(sch);
@@ -242,9 +244,9 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
		/* Ask driver what to do with device. */
		action = UNREGISTER;
		if (sch->driver && sch->driver->notify) {
			spin_unlock_irqrestore(&sch->lock, flags);
			spin_unlock_irqrestore(sch->lock, flags);
			ret = sch->driver->notify(&sch->dev, event);
			spin_lock_irqsave(&sch->lock, flags);
			spin_lock_irqsave(sch->lock, flags);
			if (ret)
				action = NONE;
		}
@@ -269,9 +271,9 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
	case UNREGISTER:
	case UNREGISTER_PROBE:
		/* Unregister device (will use subchannel lock). */
		spin_unlock_irqrestore(&sch->lock, flags);
		spin_unlock_irqrestore(sch->lock, flags);
		css_sch_device_unregister(sch);
		spin_lock_irqsave(&sch->lock, flags);
		spin_lock_irqsave(sch->lock, flags);

		/* Reset intparm to zeroes. */
		sch->schib.pmcw.intparm = 0;
@@ -283,7 +285,7 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
	default:
		break;
	}
	spin_unlock_irqrestore(&sch->lock, flags);
	spin_unlock_irqrestore(sch->lock, flags);
	/* Probe if necessary. */
	if (action == UNREGISTER_PROBE)
		ret = css_probe_device(sch->schid);
+14 −7
Original line number Diff line number Diff line
@@ -774,9 +774,9 @@ io_subchannel_register(struct work_struct *work)
		printk (KERN_WARNING "%s: could not register %s\n",
			__func__, cdev->dev.bus_id);
		put_device(&cdev->dev);
		spin_lock_irqsave(&sch->lock, flags);
		spin_lock_irqsave(sch->lock, flags);
		sch->dev.driver_data = NULL;
		spin_unlock_irqrestore(&sch->lock, flags);
		spin_unlock_irqrestore(sch->lock, flags);
		kfree (cdev->private);
		kfree (cdev);
		put_device(&sch->dev);
@@ -860,7 +860,7 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)

	sch->dev.driver_data = cdev;
	sch->driver = &io_subchannel_driver;
	cdev->ccwlock = &sch->lock;
	cdev->ccwlock = sch->lock;

	/* Init private data. */
	priv = cdev->private;
@@ -880,9 +880,9 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
	atomic_inc(&ccw_device_init_count);

	/* Start async. device sensing. */
	spin_lock_irq(&sch->lock);
	spin_lock_irq(sch->lock);
	rc = ccw_device_recognition(cdev);
	spin_unlock_irq(&sch->lock);
	spin_unlock_irq(sch->lock);
	if (rc) {
		if (atomic_dec_and_test(&ccw_device_init_count))
			wake_up(&ccw_device_init_wq);
@@ -924,9 +924,9 @@ io_subchannel_probe (struct subchannel *sch)

	rc = io_subchannel_recog(cdev, sch);
	if (rc) {
		spin_lock_irqsave(&sch->lock, flags);
		spin_lock_irqsave(sch->lock, flags);
		sch->dev.driver_data = NULL;
		spin_unlock_irqrestore(&sch->lock, flags);
		spin_unlock_irqrestore(sch->lock, flags);
		if (cdev->dev.release)
			cdev->dev.release(&cdev->dev);
	}
@@ -1036,6 +1036,13 @@ static struct ccw_device console_cdev;
static struct ccw_device_private console_private;
static int console_cdev_in_use;

static DEFINE_SPINLOCK(ccw_console_lock);

spinlock_t * cio_get_console_lock(void)
{
	return &ccw_console_lock;
}

static int
ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch)
{
Loading