Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 362786
b: refs/heads/master
c: 863fc84
h: refs/heads/master
v: v3
  • Loading branch information
Sebastian Ott authored and Martin Schwidefsky committed Apr 17, 2013
1 parent 53faa61 commit f10176d
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 109 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c135ad1caffe2b35d6316758a605a2b63ca22bb3
refs/heads/master: 863fc8492734822b95671780db803cd9a4b7d923
111 changes: 34 additions & 77 deletions trunk/drivers/s390/cio/cio.c
Original file line number Diff line number Diff line change
Expand Up @@ -540,13 +540,9 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
memset(sch, 0, sizeof(struct subchannel));

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;
}
err = cio_create_sch_lock(sch);
if (err)
goto out;
mutex_init(&sch->reg_mutex);

/*
Expand Down Expand Up @@ -580,8 +576,7 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
sch->schid.ssid, sch->schid.sch_no, sch->st);
return 0;
out:
if (!cio_is_console(schid))
kfree(sch->lock);
kfree(sch->lock);
sch->lock = NULL;
return err;
}
Expand Down Expand Up @@ -650,9 +645,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
}

#ifdef CONFIG_CCW_CONSOLE
static struct subchannel console_subchannel;
static struct io_subchannel_private console_priv;
static int console_subchannel_in_use;
static struct subchannel *console_sch;

/*
* Use cio_tsch to update the subchannel status and call the interrupt handler
Expand Down Expand Up @@ -685,119 +678,83 @@ void cio_tsch(struct subchannel *sch)
}
}

void *cio_get_console_priv(void)
static int cio_test_for_console(struct subchannel_id schid, void *data)
{
return &console_priv;
}
struct schib schib;

static int
cio_test_for_console(struct subchannel_id schid, void *data)
{
if (stsch_err(schid, &console_subchannel.schib) != 0)
if (stsch_err(schid, &schib) != 0)
return -ENXIO;
if ((console_subchannel.schib.pmcw.st == SUBCHANNEL_TYPE_IO) &&
console_subchannel.schib.pmcw.dnv &&
(console_subchannel.schib.pmcw.dev == console_devno)) {
if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv &&
(schib.pmcw.dev == console_devno)) {
console_irq = schid.sch_no;
return 1; /* found */
}
return 0;
}


static int
cio_get_console_sch_no(void)
static int cio_get_console_sch_no(void)
{
struct subchannel_id schid;

struct schib schib;

init_subchannel_id(&schid);
if (console_irq != -1) {
/* VM provided us with the irq number of the console. */
schid.sch_no = console_irq;
if (stsch_err(schid, &console_subchannel.schib) != 0 ||
(console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) ||
!console_subchannel.schib.pmcw.dnv)
if (stsch_err(schid, &schib) != 0 ||
(schib.pmcw.st != SUBCHANNEL_TYPE_IO) || !schib.pmcw.dnv)
return -1;
console_devno = console_subchannel.schib.pmcw.dev;
console_devno = schib.pmcw.dev;
} else if (console_devno != -1) {
/* At least the console device number is known. */
for_each_subchannel(cio_test_for_console, NULL);
if (console_irq == -1)
return -1;
} else {
/* unlike in 2.4, we cannot autoprobe here, since
* the channel subsystem is not fully initialized.
* With some luck, the HWC console can take over */
return -1;
}
return console_irq;
}

struct subchannel *
cio_probe_console(void)
struct subchannel *cio_probe_console(void)
{
int sch_no, ret;
struct subchannel_id schid;
struct subchannel *sch;
int sch_no, ret;

if (xchg(&console_subchannel_in_use, 1) != 0)
return ERR_PTR(-EBUSY);
sch_no = cio_get_console_sch_no();
if (sch_no == -1) {
console_subchannel_in_use = 0;
pr_warning("No CCW console was found\n");
return ERR_PTR(-ENODEV);
}
memset(&console_subchannel, 0, sizeof(struct subchannel));
init_subchannel_id(&schid);
schid.sch_no = sch_no;
ret = cio_validate_subchannel(&console_subchannel, schid);
if (ret) {
console_subchannel_in_use = 0;
return ERR_PTR(-ENODEV);
}
sch = css_alloc_subchannel(schid);
if (IS_ERR(sch))
return sch;

/*
* enable console I/O-interrupt subclass
*/
isc_register(CONSOLE_ISC);
console_subchannel.config.isc = CONSOLE_ISC;
console_subchannel.config.intparm = (u32)(addr_t)&console_subchannel;
ret = cio_commit_config(&console_subchannel);
sch->config.isc = CONSOLE_ISC;
sch->config.intparm = (u32)(addr_t)sch;
ret = cio_commit_config(sch);
if (ret) {
isc_unregister(CONSOLE_ISC);
console_subchannel_in_use = 0;
put_device(&sch->dev);
return ERR_PTR(ret);
}
return &console_subchannel;
}

void
cio_release_console(void)
{
console_subchannel.config.intparm = 0;
cio_commit_config(&console_subchannel);
isc_unregister(CONSOLE_ISC);
console_subchannel_in_use = 0;
console_sch = sch;
return sch;
}

/* Bah... hack to catch console special sausages. */
int
cio_is_console(struct subchannel_id schid)
int cio_is_console(struct subchannel_id schid)
{
if (!console_subchannel_in_use)
if (!console_sch)
return 0;
return schid_equal(&schid, &console_subchannel.schid);
return schid_equal(&schid, &console_sch->schid);
}

struct subchannel *
cio_get_console_subchannel(void)
struct subchannel *cio_get_console_subchannel(void)
{
if (!console_subchannel_in_use)
return NULL;
return &console_subchannel;
return console_sch;
}
#endif /* CONFIG_CCW_CONSOLE */

#endif
static int
__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
{
Expand Down
5 changes: 0 additions & 5 deletions trunk/drivers/s390/cio/cio.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,12 @@ void do_IRQ(struct pt_regs *);
/* Use with care. */
#ifdef CONFIG_CCW_CONSOLE
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);
extern void *cio_get_console_priv(void);
extern void cio_tsch(struct subchannel *sch);
#else
#define cio_is_console(schid) 0
#define cio_get_console_subchannel() NULL
#define cio_get_console_lock() NULL
#define cio_get_console_priv() NULL
#endif

#endif
23 changes: 9 additions & 14 deletions trunk/drivers/s390/cio/css.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,15 @@ static void css_sch_todo(struct work_struct *work);

static void css_subchannel_release(struct device *dev)
{
struct subchannel *sch;
struct subchannel *sch = to_subchannel(dev);

sch = to_subchannel(dev);
if (!cio_is_console(sch->schid)) {
/* Reset intparm to zeroes. */
sch->config.intparm = 0;
cio_commit_config(sch);
kfree(sch->lock);
kfree(sch);
}
sch->config.intparm = 0;
cio_commit_config(sch);
kfree(sch->lock);
kfree(sch);
}

static struct subchannel *css_alloc_subchannel(struct subchannel_id schid)
struct subchannel *css_alloc_subchannel(struct subchannel_id schid)
{
struct subchannel *sch;
int ret;
Expand Down Expand Up @@ -326,10 +322,9 @@ int css_probe_device(struct subchannel_id schid)
return PTR_ERR(sch);
}
ret = css_register_subchannel(sch);
if (ret) {
if (!cio_is_console(schid))
put_device(&sch->dev);
}
if (ret)
put_device(&sch->dev);

return ret;
}

Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/s390/cio/css.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ extern void css_driver_unregister(struct css_driver *);

extern void css_sch_device_unregister(struct subchannel *);
extern int css_probe_device(struct subchannel_id);
extern struct subchannel *css_alloc_subchannel(struct subchannel_id);
extern struct subchannel *get_subchannel_by_schid(struct subchannel_id);
extern int css_init_done;
extern int max_ssid;
Expand Down
24 changes: 12 additions & 12 deletions trunk/drivers/s390/cio/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -1585,22 +1585,11 @@ 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)
{
struct io_subchannel_private *io_priv = cio_get_console_priv();
int rc;

/* Attach subchannel private data. */
memset(io_priv, 0, sizeof(*io_priv));
set_io_private(sch, io_priv);
io_subchannel_init_fields(sch);
rc = cio_commit_config(sch);
if (rc)
Expand Down Expand Up @@ -1633,6 +1622,7 @@ static int ccw_device_console_enable(struct ccw_device *cdev,
struct ccw_device *
ccw_device_probe_console(void)
{
struct io_subchannel_private *io_priv;
struct subchannel *sch;
int ret;

Expand All @@ -1648,10 +1638,20 @@ ccw_device_probe_console(void)
console_cdev.private = &console_private;
console_private.cdev = &console_cdev;
console_private.int_class = IRQIO_CIO;

io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA);
if (!io_priv) {
put_device(&sch->dev);
return ERR_PTR(-ENOMEM);
}
set_io_private(sch, io_priv);

ret = ccw_device_console_enable(&console_cdev, sch);
if (ret) {
cio_release_console();
console_cdev_in_use = 0;
set_io_private(sch, NULL);
put_device(&sch->dev);
kfree(io_priv);
return ERR_PTR(ret);
}
console_cdev.online = 1;
Expand Down

0 comments on commit f10176d

Please sign in to comment.