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

Commit a28c6944 authored by Cornelia Huck's avatar Cornelia Huck Committed by Linus Torvalds
Browse files

[PATCH] s390: introduce struct channel_subsystem



struct channel_subsystem encapsulates several per channel subsystem
properties, like status of chpids or the global path group id.

Signed-off-by: default avatarCornelia Huck <cohuck@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f97a56fb
Loading
Loading
Loading
Loading
+19 −13
Original line number Diff line number Diff line
@@ -24,8 +24,6 @@
#include "ioasm.h"
#include "chsc.h"

static struct channel_path *chps[NR_CHPIDS];

static void *sei_page;

static int new_channel_path(int chpid);
@@ -33,13 +31,13 @@ static int new_channel_path(int chpid);
static inline void
set_chp_logically_online(int chp, int onoff)
{
	chps[chp]->state = onoff;
	css[0]->chps[chp]->state = onoff;
}

static int
get_chp_status(int chp)
{
	return (chps[chp] ? chps[chp]->state : -ENODEV);
	return (css[0]->chps[chp] ? css[0]->chps[chp]->state : -ENODEV);
}

void
@@ -219,13 +217,13 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
	int j;
	int mask;
	struct subchannel *sch;
	__u8 *chpid;
	struct channel_path *chpid;
	struct schib schib;

	sch = to_subchannel(dev);
	chpid = data;
	for (j = 0; j < 8; j++)
		if (sch->schib.pmcw.chpid[j] == *chpid)
		if (sch->schib.pmcw.chpid[j] == chpid->id)
			break;
	if (j >= 8)
		return 0;
@@ -296,18 +294,20 @@ static inline void
s390_set_chpid_offline( __u8 chpid)
{
	char dbf_txt[15];
	struct device *dev;

	sprintf(dbf_txt, "chpr%x", chpid);
	CIO_TRACE_EVENT(2, dbf_txt);

	if (get_chp_status(chpid) <= 0)
		return;

	bus_for_each_dev(&css_bus_type, NULL, &chpid,
	dev = get_device(&css[0]->chps[chpid]->dev);
	bus_for_each_dev(&css_bus_type, NULL, to_channelpath(dev),
			 s390_subchannel_remove_chpid);

	if (need_rescan || css_slow_subchannels_exist())
		queue_work(slow_path_wq, &slow_path_work);
	put_device(dev);
}

struct res_acc_data {
@@ -511,6 +511,7 @@ chsc_process_crw(void)
	ret = 0;
	do {
		int ccode, status;
		struct device *dev;
		memset(sei_area, 0, sizeof(*sei_area));
		memset(&res_data, 0, sizeof(struct res_acc_data));
		sei_area->request = (struct chsc_header) {
@@ -586,7 +587,8 @@ chsc_process_crw(void)
				new_channel_path(sei_area->rsid);
			else if (!status)
				break;
			res_data.chp = chps[sei_area->rsid];
			dev = get_device(&css[0]->chps[sei_area->rsid]->dev);
			res_data.chp = to_channelpath(dev);
			pr_debug("chpid: %x", sei_area->rsid);
			if ((sei_area->vf & 0xc0) != 0) {
				res_data.fla = sei_area->fla;
@@ -602,6 +604,7 @@ chsc_process_crw(void)
			}
			ret = s390_process_res_acc(&res_data);
			pr_debug("\n\n");
			put_device(dev);
			break;
			
		default: /* other stuff */
@@ -678,6 +681,7 @@ chp_add(int chpid)
{
	int rc;
	char dbf_txt[15];
	struct device *dev;

	if (!get_chp_status(chpid))
		return 0; /* no need to do the rest */
@@ -685,11 +689,13 @@ chp_add(int chpid)
	sprintf(dbf_txt, "cadd%x", chpid);
	CIO_TRACE_EVENT(2, dbf_txt);

	rc = for_each_subchannel(__chp_add, chps[chpid]);
	dev = get_device(&css[0]->chps[chpid]->dev);
	rc = for_each_subchannel(__chp_add, to_channelpath(dev));
	if (css_slow_subchannels_exist())
		rc = -EAGAIN;
	if (rc != -EAGAIN)
		rc = 0;
	put_device(dev);
	return rc;
}

@@ -1016,7 +1022,7 @@ new_channel_path(int chpid)
	chp->id = chpid;
	chp->state = 1;
	chp->dev = (struct device) {
		.parent  = &css_bus_device,
		.parent  = &css[0]->device,
		.release = chp_release,
	};
	snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid);
@@ -1038,7 +1044,7 @@ new_channel_path(int chpid)
		device_unregister(&chp->dev);
		goto out_free;
	} else
		chps[chpid] = chp;
		css[0]->chps[chpid] = chp;
	return ret;
out_free:
	kfree(chp);
@@ -1051,7 +1057,7 @@ chsc_get_chp_desc(struct subchannel *sch, int chp_no)
	struct channel_path *chp;
	struct channel_path_desc *desc;

	chp = chps[sch->schib.pmcw.chpid[chp_no]];
	chp = css[0]->chps[sch->schib.pmcw.chpid[chp_no]];
	if (!chp)
		return NULL;
	desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL);
+3 −2
Original line number Diff line number Diff line
#ifndef S390_CHSC_H
#define S390_CHSC_H

#define NR_CHPIDS 256

#define CHSC_SEI_ACC_CHPID        1
#define CHSC_SEI_ACC_LINKADDR     2
#define CHSC_SEI_ACC_FULLLINKADDR 3
@@ -65,4 +63,7 @@ extern int chsc_determine_css_characteristics(void);
extern int css_characteristics_avail;

extern void *chsc_get_chp_desc(struct subchannel*, int);

#define to_channelpath(dev) container_of(dev, struct channel_path, dev)

#endif
+46 −21
Original line number Diff line number Diff line
@@ -24,12 +24,9 @@
int need_rescan = 0;
int css_init_done = 0;

struct pgid global_pgid;
int css_characteristics_avail = 0;
struct channel_subsystem *css[__MAX_CSSID + 1];

struct device css_bus_device = {
	.bus_id = "css0",
};
int css_characteristics_avail = 0;

inline int
for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
@@ -112,7 +109,7 @@ css_register_subchannel(struct subchannel *sch)
	int ret;

	/* Initialize the subchannel structure */
	sch->dev.parent = &css_bus_device;
	sch->dev.parent = &css[0]->device;
	sch->dev.bus = &css_bus_type;
	sch->dev.release = &css_subchannel_release;
	
@@ -421,21 +418,35 @@ __init_channel_subsystem(struct subchannel_id schid, void *data)
}

static void __init
css_generate_pgid(void)
css_generate_pgid(struct channel_subsystem *css, u32 tod_high)
{
	/* Let's build our path group ID here. */
	if (css_characteristics_avail && css_general_characteristics.mcss)
		global_pgid.cpu_addr = 0x8000;
	else {
	if (css_characteristics_avail && css_general_characteristics.mcss) {
		css->global_pgid.pgid_high.ext_cssid.version = 0x80;
		css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid;
	} else {
#ifdef CONFIG_SMP
		global_pgid.cpu_addr = hard_smp_processor_id();
		css->global_pgid.pgid_high.cpu_addr = hard_smp_processor_id();
#else
		global_pgid.cpu_addr = 0;
		css->global_pgid.pgid_high.cpu_addr = 0;
#endif
	}
	global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident;
	global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine;
	global_pgid.tod_high = (__u32) (get_clock() >> 32);
	css->global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident;
	css->global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine;
	css->global_pgid.tod_high = tod_high;

}

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

	memset(css[nr], 0, sizeof(struct channel_subsystem));
	css[nr]->valid = 1;
	css[nr]->cssid = nr;
	sprintf(css[nr]->device.bus_id, "css%x", nr);
	tod_high = (u32) (get_clock() >> 32);
	css_generate_pgid(css[nr], tod_high);
}

/*
@@ -446,25 +457,39 @@ css_generate_pgid(void)
static int __init
init_channel_subsystem (void)
{
	int ret;
	int ret, i;

	if (chsc_determine_css_characteristics() == 0)
		css_characteristics_avail = 1;

	css_generate_pgid();

	if ((ret = bus_register(&css_bus_type)))
		goto out;
	if ((ret = device_register (&css_bus_device)))
		goto out_bus;

	/* Setup css structure. */
	for (i = 0; i <= __MAX_CSSID; i++) {
		css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL);
		if (!css[i]) {
			ret = -ENOMEM;
			goto out_bus;
		}
		setup_css(i);
		ret = device_register(&css[i]->device);
		if (ret)
			goto out_free;
	}
	css_init_done = 1;

	ctl_set_bit(6, 28);

	for_each_subchannel(__init_channel_subsystem, NULL);
	return 0;
out_free:
	kfree(css[i]);
out_bus:
	while (i > 0) {
		i--;
		device_unregister(&css[i]->device);
	}
	bus_unregister(&css_bus_type);
out:
	return ret;
+21 −4
Original line number Diff line number Diff line
@@ -35,19 +35,25 @@ struct path_state {
	__u8  resvd  : 3;	/* reserved */
} __attribute__ ((packed));

struct extended_cssid {
	u8 version;
	u8 cssid;
} __attribute__ ((packed));

struct pgid {
	union {
		__u8 fc;   	/* SPID function code */
		struct path_state ps;	/* SNID path state */
	} inf;
	union {
		__u32 cpu_addr	: 16;	/* CPU address */
		struct extended_cssid ext_cssid;
	} pgid_high;
	__u32 cpu_id	: 24;	/* CPU identification */
	__u32 cpu_model : 16;	/* CPU model */
	__u32 tod_high;		/* high word TOD clock */
} __attribute__ ((packed));

extern struct pgid global_pgid;

#define MAX_CIWS 8

/*
@@ -129,9 +135,20 @@ extern int css_init_done;
extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);

#define __MAX_SUBCHANNEL 65535
#define __MAX_CHPID 255
#define __MAX_CSSID 0

struct channel_subsystem {
	u8 cssid;
	int valid;
	struct channel_path *chps[__MAX_CHPID];
	struct device device;
	struct pgid global_pgid;
};
#define to_css(dev) container_of(dev, struct channel_subsystem, device)

extern struct bus_type css_bus_type;
extern struct device css_bus_device;
extern struct channel_subsystem *css[];

/* Some helper functions for disconnected state. */
int device_is_disconnected(struct subchannel *);
+0 −4
Original line number Diff line number Diff line
@@ -986,10 +986,6 @@ ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch)
	cdev->dev = (struct device) {
		.parent = &sch->dev,
	};
	/* Initialize the subchannel structure */
	sch->dev.parent = &css_bus_device;
	sch->dev.bus = &css_bus_type;

	rc = io_subchannel_recog(cdev, sch);
	if (rc)
		return rc;
Loading