Skip to content

Commit

Permalink
[S390] Support for disconnected devices reappearing on another subcha…
Browse files Browse the repository at this point in the history
…nnel.

- create a 'pseudo_subchannel' per channel subsystem (the 'orphanage')
- use the orphanage as a shelter for ccw_devices that can't remain on the same
  subchannel

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Cornelia Huck authored and Martin Schwidefsky committed Dec 8, 2006
1 parent 2ec2298 commit d7b5a4c
Show file tree
Hide file tree
Showing 7 changed files with 296 additions and 59 deletions.
6 changes: 5 additions & 1 deletion drivers/s390/cio/cio.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,8 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
CIO_TRACE_EVENT (2, "ensch");
CIO_TRACE_EVENT (2, sch->dev.bus_id);

if (sch_is_pseudo_sch(sch))
return -EINVAL;
ccode = stsch (sch->schid, &sch->schib);
if (ccode)
return -ENODEV;
Expand Down Expand Up @@ -462,6 +464,8 @@ cio_disable_subchannel (struct subchannel *sch)
CIO_TRACE_EVENT (2, "dissch");
CIO_TRACE_EVENT (2, sch->dev.bus_id);

if (sch_is_pseudo_sch(sch))
return 0;
ccode = stsch (sch->schid, &sch->schib);
if (ccode == 3) /* Not operational. */
return -ENODEV;
Expand Down Expand Up @@ -496,7 +500,7 @@ cio_disable_subchannel (struct subchannel *sch)
return ret;
}

static int cio_create_sch_lock(struct subchannel *sch)
int cio_create_sch_lock(struct subchannel *sch)
{
sch->lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
if (!sch->lock)
Expand Down
2 changes: 2 additions & 0 deletions drivers/s390/cio/cio.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ extern int cio_set_options (struct subchannel *, int);
extern int cio_get_options (struct subchannel *);
extern int cio_modify (struct subchannel *);

int cio_create_sch_lock(struct subchannel *);

/* Use with care. */
#ifdef CONFIG_CCW_CONSOLE
extern struct subchannel *cio_probe_console(void);
Expand Down
37 changes: 33 additions & 4 deletions drivers/s390/cio/css.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,19 +580,32 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,

static DEVICE_ATTR(cm_enable, 0644, css_cm_enable_show, css_cm_enable_store);

static inline void __init
setup_css(int nr)
static inline int __init setup_css(int nr)
{
u32 tod_high;
int ret;

memset(css[nr], 0, sizeof(struct channel_subsystem));
css[nr]->pseudo_subchannel =
kzalloc(sizeof(*css[nr]->pseudo_subchannel), GFP_KERNEL);
if (!css[nr]->pseudo_subchannel)
return -ENOMEM;
css[nr]->pseudo_subchannel->dev.parent = &css[nr]->device;
css[nr]->pseudo_subchannel->dev.release = css_subchannel_release;
sprintf(css[nr]->pseudo_subchannel->dev.bus_id, "defunct");
ret = cio_create_sch_lock(css[nr]->pseudo_subchannel);
if (ret) {
kfree(css[nr]->pseudo_subchannel);
return ret;
}
mutex_init(&css[nr]->mutex);
css[nr]->valid = 1;
css[nr]->cssid = nr;
sprintf(css[nr]->device.bus_id, "css%x", nr);
css[nr]->device.release = channel_subsystem_release;
tod_high = (u32) (get_clock() >> 32);
css_generate_pgid(css[nr], tod_high);
return 0;
}

/*
Expand Down Expand Up @@ -629,31 +642,42 @@ init_channel_subsystem (void)
ret = -ENOMEM;
goto out_unregister;
}
setup_css(i);
ret = device_register(&css[i]->device);
ret = setup_css(i);
if (ret)
goto out_free;
ret = device_register(&css[i]->device);
if (ret)
goto out_free_all;
if (css_characteristics_avail &&
css_chsc_characteristics.secm) {
ret = device_create_file(&css[i]->device,
&dev_attr_cm_enable);
if (ret)
goto out_device;
}
ret = device_register(&css[i]->pseudo_subchannel->dev);
if (ret)
goto out_file;
}
css_init_done = 1;

ctl_set_bit(6, 28);

for_each_subchannel(__init_channel_subsystem, NULL);
return 0;
out_file:
device_remove_file(&css[i]->device, &dev_attr_cm_enable);
out_device:
device_unregister(&css[i]->device);
out_free_all:
kfree(css[i]->pseudo_subchannel->lock);
kfree(css[i]->pseudo_subchannel);
out_free:
kfree(css[i]);
out_unregister:
while (i > 0) {
i--;
device_unregister(&css[i]->pseudo_subchannel->dev);
if (css_characteristics_avail && css_chsc_characteristics.secm)
device_remove_file(&css[i]->device,
&dev_attr_cm_enable);
Expand All @@ -665,6 +689,11 @@ init_channel_subsystem (void)
return ret;
}

int sch_is_pseudo_sch(struct subchannel *sch)
{
return sch == to_css(sch->dev.parent)->pseudo_subchannel;
}

/*
* find a driver for a subchannel. They identify by the subchannel
* type with the exception that the console subchannel driver has its own
Expand Down
4 changes: 4 additions & 0 deletions drivers/s390/cio/css.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ struct channel_subsystem {
int cm_enabled;
void *cub_addr1;
void *cub_addr2;
/* for orphaned ccw devices */
struct subchannel *pseudo_subchannel;
};
#define to_css(dev) container_of(dev, struct channel_subsystem, device)

Expand Down Expand Up @@ -187,6 +189,8 @@ void css_clear_subchannel_slow_list(void);
int css_slow_subchannels_exist(void);
extern int need_rescan;

int sch_is_pseudo_sch(struct subchannel *);

extern struct workqueue_struct *slow_path_wq;
extern struct work_struct slow_path_work;

Expand Down
Loading

0 comments on commit d7b5a4c

Please sign in to comment.