18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _CSS_H
38c2ecf20Sopenharmony_ci#define _CSS_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/mutex.h>
68c2ecf20Sopenharmony_ci#include <linux/wait.h>
78c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
88c2ecf20Sopenharmony_ci#include <linux/device.h>
98c2ecf20Sopenharmony_ci#include <linux/types.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <asm/cio.h>
128c2ecf20Sopenharmony_ci#include <asm/chpid.h>
138c2ecf20Sopenharmony_ci#include <asm/schid.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include "cio.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/*
188c2ecf20Sopenharmony_ci * path grouping stuff
198c2ecf20Sopenharmony_ci */
208c2ecf20Sopenharmony_ci#define SPID_FUNC_SINGLE_PATH	   0x00
218c2ecf20Sopenharmony_ci#define SPID_FUNC_MULTI_PATH	   0x80
228c2ecf20Sopenharmony_ci#define SPID_FUNC_ESTABLISH	   0x00
238c2ecf20Sopenharmony_ci#define SPID_FUNC_RESIGN	   0x40
248c2ecf20Sopenharmony_ci#define SPID_FUNC_DISBAND	   0x20
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define SNID_STATE1_RESET	   0
278c2ecf20Sopenharmony_ci#define SNID_STATE1_UNGROUPED	   2
288c2ecf20Sopenharmony_ci#define SNID_STATE1_GROUPED	   3
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define SNID_STATE2_NOT_RESVD	   0
318c2ecf20Sopenharmony_ci#define SNID_STATE2_RESVD_ELSE	   2
328c2ecf20Sopenharmony_ci#define SNID_STATE2_RESVD_SELF	   3
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#define SNID_STATE3_MULTI_PATH	   1
358c2ecf20Sopenharmony_ci#define SNID_STATE3_SINGLE_PATH	   0
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistruct path_state {
388c2ecf20Sopenharmony_ci	__u8  state1 : 2;	/* path state value 1 */
398c2ecf20Sopenharmony_ci	__u8  state2 : 2;	/* path state value 2 */
408c2ecf20Sopenharmony_ci	__u8  state3 : 1;	/* path state value 3 */
418c2ecf20Sopenharmony_ci	__u8  resvd  : 3;	/* reserved */
428c2ecf20Sopenharmony_ci} __attribute__ ((packed));
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistruct extended_cssid {
458c2ecf20Sopenharmony_ci	u8 version;
468c2ecf20Sopenharmony_ci	u8 cssid;
478c2ecf20Sopenharmony_ci} __attribute__ ((packed));
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistruct pgid {
508c2ecf20Sopenharmony_ci	union {
518c2ecf20Sopenharmony_ci		__u8 fc;   	/* SPID function code */
528c2ecf20Sopenharmony_ci		struct path_state ps;	/* SNID path state */
538c2ecf20Sopenharmony_ci	} __attribute__ ((packed)) inf;
548c2ecf20Sopenharmony_ci	union {
558c2ecf20Sopenharmony_ci		__u32 cpu_addr	: 16;	/* CPU address */
568c2ecf20Sopenharmony_ci		struct extended_cssid ext_cssid;
578c2ecf20Sopenharmony_ci	} __attribute__ ((packed)) pgid_high;
588c2ecf20Sopenharmony_ci	__u32 cpu_id	: 24;	/* CPU identification */
598c2ecf20Sopenharmony_ci	__u32 cpu_model : 16;	/* CPU model */
608c2ecf20Sopenharmony_ci	__u32 tod_high;		/* high word TOD clock */
618c2ecf20Sopenharmony_ci} __attribute__ ((packed));
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistruct subchannel;
648c2ecf20Sopenharmony_cistruct chp_link;
658c2ecf20Sopenharmony_ci/**
668c2ecf20Sopenharmony_ci * struct css_driver - device driver for subchannels
678c2ecf20Sopenharmony_ci * @subchannel_type: subchannel type supported by this driver
688c2ecf20Sopenharmony_ci * @drv: embedded device driver structure
698c2ecf20Sopenharmony_ci * @irq: called on interrupts
708c2ecf20Sopenharmony_ci * @chp_event: called for events affecting a channel path
718c2ecf20Sopenharmony_ci * @sch_event: called for events affecting the subchannel
728c2ecf20Sopenharmony_ci * @probe: function called on probe
738c2ecf20Sopenharmony_ci * @remove: function called on remove
748c2ecf20Sopenharmony_ci * @shutdown: called at device shutdown
758c2ecf20Sopenharmony_ci * @prepare: prepare for pm state transition
768c2ecf20Sopenharmony_ci * @complete: undo work done in @prepare
778c2ecf20Sopenharmony_ci * @freeze: callback for freezing during hibernation snapshotting
788c2ecf20Sopenharmony_ci * @thaw: undo work done in @freeze
798c2ecf20Sopenharmony_ci * @restore: callback for restoring after hibernation
808c2ecf20Sopenharmony_ci * @settle: wait for asynchronous work to finish
818c2ecf20Sopenharmony_ci */
828c2ecf20Sopenharmony_cistruct css_driver {
838c2ecf20Sopenharmony_ci	struct css_device_id *subchannel_type;
848c2ecf20Sopenharmony_ci	struct device_driver drv;
858c2ecf20Sopenharmony_ci	void (*irq)(struct subchannel *);
868c2ecf20Sopenharmony_ci	int (*chp_event)(struct subchannel *, struct chp_link *, int);
878c2ecf20Sopenharmony_ci	int (*sch_event)(struct subchannel *, int);
888c2ecf20Sopenharmony_ci	int (*probe)(struct subchannel *);
898c2ecf20Sopenharmony_ci	int (*remove)(struct subchannel *);
908c2ecf20Sopenharmony_ci	void (*shutdown)(struct subchannel *);
918c2ecf20Sopenharmony_ci	int (*prepare) (struct subchannel *);
928c2ecf20Sopenharmony_ci	void (*complete) (struct subchannel *);
938c2ecf20Sopenharmony_ci	int (*freeze)(struct subchannel *);
948c2ecf20Sopenharmony_ci	int (*thaw) (struct subchannel *);
958c2ecf20Sopenharmony_ci	int (*restore)(struct subchannel *);
968c2ecf20Sopenharmony_ci	int (*settle)(void);
978c2ecf20Sopenharmony_ci};
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci#define to_cssdriver(n) container_of(n, struct css_driver, drv)
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ciextern int css_driver_register(struct css_driver *);
1028c2ecf20Sopenharmony_ciextern void css_driver_unregister(struct css_driver *);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ciextern void css_sch_device_unregister(struct subchannel *);
1058c2ecf20Sopenharmony_ciextern int css_register_subchannel(struct subchannel *);
1068c2ecf20Sopenharmony_ciextern struct subchannel *css_alloc_subchannel(struct subchannel_id,
1078c2ecf20Sopenharmony_ci					       struct schib *schib);
1088c2ecf20Sopenharmony_ciextern struct subchannel *get_subchannel_by_schid(struct subchannel_id);
1098c2ecf20Sopenharmony_ciextern int css_init_done;
1108c2ecf20Sopenharmony_ciextern int max_ssid;
1118c2ecf20Sopenharmony_ciint for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *),
1128c2ecf20Sopenharmony_ci			       int (*fn_unknown)(struct subchannel_id,
1138c2ecf20Sopenharmony_ci			       void *), void *data);
1148c2ecf20Sopenharmony_ciextern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
1158c2ecf20Sopenharmony_civoid css_update_ssd_info(struct subchannel *sch);
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cistruct channel_subsystem {
1188c2ecf20Sopenharmony_ci	u8 cssid;
1198c2ecf20Sopenharmony_ci	u8 iid;
1208c2ecf20Sopenharmony_ci	bool id_valid; /* cssid,iid */
1218c2ecf20Sopenharmony_ci	struct channel_path *chps[__MAX_CHPID + 1];
1228c2ecf20Sopenharmony_ci	struct device device;
1238c2ecf20Sopenharmony_ci	struct pgid global_pgid;
1248c2ecf20Sopenharmony_ci	struct mutex mutex;
1258c2ecf20Sopenharmony_ci	/* channel measurement related */
1268c2ecf20Sopenharmony_ci	int cm_enabled;
1278c2ecf20Sopenharmony_ci	void *cub_addr1;
1288c2ecf20Sopenharmony_ci	void *cub_addr2;
1298c2ecf20Sopenharmony_ci	/* for orphaned ccw devices */
1308c2ecf20Sopenharmony_ci	struct subchannel *pseudo_subchannel;
1318c2ecf20Sopenharmony_ci};
1328c2ecf20Sopenharmony_ci#define to_css(dev) container_of(dev, struct channel_subsystem, device)
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ciextern struct channel_subsystem *channel_subsystems[];
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci/* Dummy helper which needs to change once we support more than one css. */
1378c2ecf20Sopenharmony_cistatic inline struct channel_subsystem *css_by_id(u8 cssid)
1388c2ecf20Sopenharmony_ci{
1398c2ecf20Sopenharmony_ci	return channel_subsystems[0];
1408c2ecf20Sopenharmony_ci}
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci/* Dummy iterator which needs to change once we support more than one css. */
1438c2ecf20Sopenharmony_ci#define for_each_css(css)						\
1448c2ecf20Sopenharmony_ci	for ((css) = channel_subsystems[0]; (css); (css) = NULL)
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci/* Helper functions to build lists for the slow path. */
1478c2ecf20Sopenharmony_civoid css_schedule_eval(struct subchannel_id schid);
1488c2ecf20Sopenharmony_civoid css_schedule_eval_all(void);
1498c2ecf20Sopenharmony_civoid css_schedule_eval_all_unreg(unsigned long delay);
1508c2ecf20Sopenharmony_ciint css_complete_work(void);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ciint sch_is_pseudo_sch(struct subchannel *);
1538c2ecf20Sopenharmony_cistruct schib;
1548c2ecf20Sopenharmony_ciint css_sch_is_valid(struct schib *);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ciextern struct workqueue_struct *cio_work_q;
1578c2ecf20Sopenharmony_civoid css_wait_for_slow_path(void);
1588c2ecf20Sopenharmony_civoid css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo);
1598c2ecf20Sopenharmony_ci#endif
160