xref: /kernel/linux/linux-6.6/drivers/s390/cio/css.h (revision 62306a36)
162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _CSS_H
362306a36Sopenharmony_ci#define _CSS_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/mutex.h>
662306a36Sopenharmony_ci#include <linux/wait.h>
762306a36Sopenharmony_ci#include <linux/workqueue.h>
862306a36Sopenharmony_ci#include <linux/device.h>
962306a36Sopenharmony_ci#include <linux/types.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <asm/cio.h>
1262306a36Sopenharmony_ci#include <asm/chpid.h>
1362306a36Sopenharmony_ci#include <asm/schid.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include "cio.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/*
1862306a36Sopenharmony_ci * path grouping stuff
1962306a36Sopenharmony_ci */
2062306a36Sopenharmony_ci#define SPID_FUNC_SINGLE_PATH	   0x00
2162306a36Sopenharmony_ci#define SPID_FUNC_MULTI_PATH	   0x80
2262306a36Sopenharmony_ci#define SPID_FUNC_ESTABLISH	   0x00
2362306a36Sopenharmony_ci#define SPID_FUNC_RESIGN	   0x40
2462306a36Sopenharmony_ci#define SPID_FUNC_DISBAND	   0x20
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define SNID_STATE1_RESET	   0
2762306a36Sopenharmony_ci#define SNID_STATE1_UNGROUPED	   2
2862306a36Sopenharmony_ci#define SNID_STATE1_GROUPED	   3
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define SNID_STATE2_NOT_RESVD	   0
3162306a36Sopenharmony_ci#define SNID_STATE2_RESVD_ELSE	   2
3262306a36Sopenharmony_ci#define SNID_STATE2_RESVD_SELF	   3
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define SNID_STATE3_MULTI_PATH	   1
3562306a36Sopenharmony_ci#define SNID_STATE3_SINGLE_PATH	   0
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/*
3862306a36Sopenharmony_ci * Conditions used to specify which subchannels need evaluation
3962306a36Sopenharmony_ci */
4062306a36Sopenharmony_cienum css_eval_cond {
4162306a36Sopenharmony_ci	CSS_EVAL_NO_PATH,		/* Subchannels with no operational paths */
4262306a36Sopenharmony_ci	CSS_EVAL_NOT_ONLINE	/* sch without an online-device */
4362306a36Sopenharmony_ci};
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistruct path_state {
4662306a36Sopenharmony_ci	__u8  state1 : 2;	/* path state value 1 */
4762306a36Sopenharmony_ci	__u8  state2 : 2;	/* path state value 2 */
4862306a36Sopenharmony_ci	__u8  state3 : 1;	/* path state value 3 */
4962306a36Sopenharmony_ci	__u8  resvd  : 3;	/* reserved */
5062306a36Sopenharmony_ci} __attribute__ ((packed));
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistruct extended_cssid {
5362306a36Sopenharmony_ci	u8 version;
5462306a36Sopenharmony_ci	u8 cssid;
5562306a36Sopenharmony_ci} __attribute__ ((packed));
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistruct pgid {
5862306a36Sopenharmony_ci	union {
5962306a36Sopenharmony_ci		__u8 fc;   	/* SPID function code */
6062306a36Sopenharmony_ci		struct path_state ps;	/* SNID path state */
6162306a36Sopenharmony_ci	} __attribute__ ((packed)) inf;
6262306a36Sopenharmony_ci	union {
6362306a36Sopenharmony_ci		__u32 cpu_addr	: 16;	/* CPU address */
6462306a36Sopenharmony_ci		struct extended_cssid ext_cssid;
6562306a36Sopenharmony_ci	} __attribute__ ((packed)) pgid_high;
6662306a36Sopenharmony_ci	__u32 cpu_id	: 24;	/* CPU identification */
6762306a36Sopenharmony_ci	__u32 cpu_model : 16;	/* CPU model */
6862306a36Sopenharmony_ci	__u32 tod_high;		/* high word TOD clock */
6962306a36Sopenharmony_ci} __attribute__ ((packed));
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistruct subchannel;
7262306a36Sopenharmony_cistruct chp_link;
7362306a36Sopenharmony_ci/**
7462306a36Sopenharmony_ci * struct css_driver - device driver for subchannels
7562306a36Sopenharmony_ci * @subchannel_type: subchannel type supported by this driver
7662306a36Sopenharmony_ci * @drv: embedded device driver structure
7762306a36Sopenharmony_ci * @irq: called on interrupts
7862306a36Sopenharmony_ci * @chp_event: called for events affecting a channel path
7962306a36Sopenharmony_ci * @sch_event: called for events affecting the subchannel
8062306a36Sopenharmony_ci * @probe: function called on probe
8162306a36Sopenharmony_ci * @remove: function called on remove
8262306a36Sopenharmony_ci * @shutdown: called at device shutdown
8362306a36Sopenharmony_ci * @settle: wait for asynchronous work to finish
8462306a36Sopenharmony_ci */
8562306a36Sopenharmony_cistruct css_driver {
8662306a36Sopenharmony_ci	struct css_device_id *subchannel_type;
8762306a36Sopenharmony_ci	struct device_driver drv;
8862306a36Sopenharmony_ci	void (*irq)(struct subchannel *);
8962306a36Sopenharmony_ci	int (*chp_event)(struct subchannel *, struct chp_link *, int);
9062306a36Sopenharmony_ci	int (*sch_event)(struct subchannel *, int);
9162306a36Sopenharmony_ci	int (*probe)(struct subchannel *);
9262306a36Sopenharmony_ci	void (*remove)(struct subchannel *);
9362306a36Sopenharmony_ci	void (*shutdown)(struct subchannel *);
9462306a36Sopenharmony_ci	int (*settle)(void);
9562306a36Sopenharmony_ci};
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci#define to_cssdriver(n) container_of(n, struct css_driver, drv)
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ciextern int css_driver_register(struct css_driver *);
10062306a36Sopenharmony_ciextern void css_driver_unregister(struct css_driver *);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ciextern void css_sch_device_unregister(struct subchannel *);
10362306a36Sopenharmony_ciextern int css_register_subchannel(struct subchannel *);
10462306a36Sopenharmony_ciextern struct subchannel *css_alloc_subchannel(struct subchannel_id,
10562306a36Sopenharmony_ci					       struct schib *schib);
10662306a36Sopenharmony_ciextern struct subchannel *get_subchannel_by_schid(struct subchannel_id);
10762306a36Sopenharmony_ciextern int css_init_done;
10862306a36Sopenharmony_ciextern int max_ssid;
10962306a36Sopenharmony_ciint for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *),
11062306a36Sopenharmony_ci			       int (*fn_unknown)(struct subchannel_id,
11162306a36Sopenharmony_ci			       void *), void *data);
11262306a36Sopenharmony_ciextern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
11362306a36Sopenharmony_civoid css_update_ssd_info(struct subchannel *sch);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistruct channel_subsystem {
11662306a36Sopenharmony_ci	u8 cssid;
11762306a36Sopenharmony_ci	u8 iid;
11862306a36Sopenharmony_ci	bool id_valid; /* cssid,iid */
11962306a36Sopenharmony_ci	struct channel_path *chps[__MAX_CHPID + 1];
12062306a36Sopenharmony_ci	struct device device;
12162306a36Sopenharmony_ci	struct pgid global_pgid;
12262306a36Sopenharmony_ci	struct mutex mutex;
12362306a36Sopenharmony_ci	/* channel measurement related */
12462306a36Sopenharmony_ci	int cm_enabled;
12562306a36Sopenharmony_ci	void *cub_addr1;
12662306a36Sopenharmony_ci	void *cub_addr2;
12762306a36Sopenharmony_ci	/* for orphaned ccw devices */
12862306a36Sopenharmony_ci	struct subchannel *pseudo_subchannel;
12962306a36Sopenharmony_ci};
13062306a36Sopenharmony_ci#define to_css(dev) container_of(dev, struct channel_subsystem, device)
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ciextern struct channel_subsystem *channel_subsystems[];
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci/* Dummy helper which needs to change once we support more than one css. */
13562306a36Sopenharmony_cistatic inline struct channel_subsystem *css_by_id(u8 cssid)
13662306a36Sopenharmony_ci{
13762306a36Sopenharmony_ci	return channel_subsystems[0];
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci/* Dummy iterator which needs to change once we support more than one css. */
14162306a36Sopenharmony_ci#define for_each_css(css)						\
14262306a36Sopenharmony_ci	for ((css) = channel_subsystems[0]; (css); (css) = NULL)
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci/* Helper functions to build lists for the slow path. */
14562306a36Sopenharmony_civoid css_schedule_eval(struct subchannel_id schid);
14662306a36Sopenharmony_civoid css_schedule_eval_all(void);
14762306a36Sopenharmony_civoid css_schedule_eval_cond(enum css_eval_cond, unsigned long delay);
14862306a36Sopenharmony_ciint css_complete_work(void);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ciint sch_is_pseudo_sch(struct subchannel *);
15162306a36Sopenharmony_cistruct schib;
15262306a36Sopenharmony_ciint css_sch_is_valid(struct schib *);
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ciextern struct workqueue_struct *cio_work_q;
15562306a36Sopenharmony_civoid css_wait_for_slow_path(void);
15662306a36Sopenharmony_civoid css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo);
15762306a36Sopenharmony_ci#endif
158