162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef S390_IO_SCH_H 362306a36Sopenharmony_ci#define S390_IO_SCH_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/types.h> 662306a36Sopenharmony_ci#include <asm/schid.h> 762306a36Sopenharmony_ci#include <asm/ccwdev.h> 862306a36Sopenharmony_ci#include <asm/irq.h> 962306a36Sopenharmony_ci#include "css.h" 1062306a36Sopenharmony_ci#include "orb.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cistruct io_subchannel_dma_area { 1362306a36Sopenharmony_ci struct ccw1 sense_ccw; /* static ccw for sense command */ 1462306a36Sopenharmony_ci}; 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistruct io_subchannel_private { 1762306a36Sopenharmony_ci union orb orb; /* operation request block */ 1862306a36Sopenharmony_ci struct ccw_device *cdev;/* pointer to the child ccw device */ 1962306a36Sopenharmony_ci struct { 2062306a36Sopenharmony_ci unsigned int suspend:1; /* allow suspend */ 2162306a36Sopenharmony_ci unsigned int prefetch:1;/* deny prefetch */ 2262306a36Sopenharmony_ci unsigned int inter:1; /* suppress intermediate interrupts */ 2362306a36Sopenharmony_ci } __packed options; 2462306a36Sopenharmony_ci struct io_subchannel_dma_area *dma_area; 2562306a36Sopenharmony_ci dma_addr_t dma_area_dma; 2662306a36Sopenharmony_ci} __aligned(8); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define to_io_private(n) ((struct io_subchannel_private *) \ 2962306a36Sopenharmony_ci dev_get_drvdata(&(n)->dev)) 3062306a36Sopenharmony_ci#define set_io_private(n, p) (dev_set_drvdata(&(n)->dev, p)) 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic inline struct ccw_device *sch_get_cdev(struct subchannel *sch) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci struct io_subchannel_private *priv = to_io_private(sch); 3562306a36Sopenharmony_ci return priv ? priv->cdev : NULL; 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic inline void sch_set_cdev(struct subchannel *sch, 3962306a36Sopenharmony_ci struct ccw_device *cdev) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci struct io_subchannel_private *priv = to_io_private(sch); 4262306a36Sopenharmony_ci if (priv) 4362306a36Sopenharmony_ci priv->cdev = cdev; 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define MAX_CIWS 8 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* 4962306a36Sopenharmony_ci * Possible status values for a CCW request's I/O. 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_cienum io_status { 5262306a36Sopenharmony_ci IO_DONE, 5362306a36Sopenharmony_ci IO_RUNNING, 5462306a36Sopenharmony_ci IO_STATUS_ERROR, 5562306a36Sopenharmony_ci IO_PATH_ERROR, 5662306a36Sopenharmony_ci IO_REJECTED, 5762306a36Sopenharmony_ci IO_KILLED 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/** 6162306a36Sopenharmony_ci * ccw_request - Internal CCW request. 6262306a36Sopenharmony_ci * @cp: channel program to start 6362306a36Sopenharmony_ci * @timeout: maximum allowable time in jiffies between start I/O and interrupt 6462306a36Sopenharmony_ci * @maxretries: number of retries per I/O operation and path 6562306a36Sopenharmony_ci * @lpm: mask of paths to use 6662306a36Sopenharmony_ci * @check: optional callback that determines if results are final 6762306a36Sopenharmony_ci * @filter: optional callback to adjust request status based on IRB data 6862306a36Sopenharmony_ci * @callback: final callback 6962306a36Sopenharmony_ci * @data: user-defined pointer passed to all callbacks 7062306a36Sopenharmony_ci * @singlepath: if set, use only one path from @lpm per start I/O 7162306a36Sopenharmony_ci * @cancel: non-zero if request was cancelled 7262306a36Sopenharmony_ci * @done: non-zero if request was finished 7362306a36Sopenharmony_ci * @mask: current path mask 7462306a36Sopenharmony_ci * @retries: current number of retries 7562306a36Sopenharmony_ci * @drc: delayed return code 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_cistruct ccw_request { 7862306a36Sopenharmony_ci struct ccw1 *cp; 7962306a36Sopenharmony_ci unsigned long timeout; 8062306a36Sopenharmony_ci u16 maxretries; 8162306a36Sopenharmony_ci u8 lpm; 8262306a36Sopenharmony_ci int (*check)(struct ccw_device *, void *); 8362306a36Sopenharmony_ci enum io_status (*filter)(struct ccw_device *, void *, struct irb *, 8462306a36Sopenharmony_ci enum io_status); 8562306a36Sopenharmony_ci void (*callback)(struct ccw_device *, void *, int); 8662306a36Sopenharmony_ci void *data; 8762306a36Sopenharmony_ci unsigned int singlepath:1; 8862306a36Sopenharmony_ci /* These fields are used internally. */ 8962306a36Sopenharmony_ci unsigned int cancel:1; 9062306a36Sopenharmony_ci unsigned int done:1; 9162306a36Sopenharmony_ci u16 mask; 9262306a36Sopenharmony_ci u16 retries; 9362306a36Sopenharmony_ci int drc; 9462306a36Sopenharmony_ci} __attribute__((packed)); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/* 9762306a36Sopenharmony_ci * sense-id response buffer layout 9862306a36Sopenharmony_ci */ 9962306a36Sopenharmony_cistruct senseid { 10062306a36Sopenharmony_ci /* common part */ 10162306a36Sopenharmony_ci u8 reserved; /* always 0x'FF' */ 10262306a36Sopenharmony_ci u16 cu_type; /* control unit type */ 10362306a36Sopenharmony_ci u8 cu_model; /* control unit model */ 10462306a36Sopenharmony_ci u16 dev_type; /* device type */ 10562306a36Sopenharmony_ci u8 dev_model; /* device model */ 10662306a36Sopenharmony_ci u8 unused; /* padding byte */ 10762306a36Sopenharmony_ci /* extended part */ 10862306a36Sopenharmony_ci struct ciw ciw[MAX_CIWS]; /* variable # of CIWs */ 10962306a36Sopenharmony_ci} __attribute__ ((packed, aligned(4))); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cienum cdev_todo { 11262306a36Sopenharmony_ci CDEV_TODO_NOTHING, 11362306a36Sopenharmony_ci CDEV_TODO_ENABLE_CMF, 11462306a36Sopenharmony_ci CDEV_TODO_REBIND, 11562306a36Sopenharmony_ci CDEV_TODO_REGISTER, 11662306a36Sopenharmony_ci CDEV_TODO_UNREG, 11762306a36Sopenharmony_ci CDEV_TODO_UNREG_EVAL, 11862306a36Sopenharmony_ci}; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define FAKE_CMD_IRB 1 12162306a36Sopenharmony_ci#define FAKE_TM_IRB 2 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistruct ccw_device_dma_area { 12462306a36Sopenharmony_ci struct senseid senseid; /* SenseID info */ 12562306a36Sopenharmony_ci struct ccw1 iccws[2]; /* ccws for SNID/SID/SPGID commands */ 12662306a36Sopenharmony_ci struct irb irb; /* device status */ 12762306a36Sopenharmony_ci struct pgid pgid[8]; /* path group IDs per chpid*/ 12862306a36Sopenharmony_ci}; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistruct ccw_device_private { 13162306a36Sopenharmony_ci struct ccw_device *cdev; 13262306a36Sopenharmony_ci struct subchannel *sch; 13362306a36Sopenharmony_ci int state; /* device state */ 13462306a36Sopenharmony_ci atomic_t onoff; 13562306a36Sopenharmony_ci struct ccw_dev_id dev_id; /* device id */ 13662306a36Sopenharmony_ci struct ccw_request req; /* internal I/O request */ 13762306a36Sopenharmony_ci int iretry; 13862306a36Sopenharmony_ci u8 pgid_valid_mask; /* mask of valid PGIDs */ 13962306a36Sopenharmony_ci u8 pgid_todo_mask; /* mask of PGIDs to be adjusted */ 14062306a36Sopenharmony_ci u8 pgid_reset_mask; /* mask of PGIDs which were reset */ 14162306a36Sopenharmony_ci u8 path_noirq_mask; /* mask of paths for which no irq was 14262306a36Sopenharmony_ci received */ 14362306a36Sopenharmony_ci u8 path_notoper_mask; /* mask of paths which were found 14462306a36Sopenharmony_ci not operable */ 14562306a36Sopenharmony_ci u8 path_gone_mask; /* mask of paths, that became unavailable */ 14662306a36Sopenharmony_ci u8 path_new_mask; /* mask of paths, that became available */ 14762306a36Sopenharmony_ci u8 path_broken_mask; /* mask of paths, which were found to be 14862306a36Sopenharmony_ci unusable */ 14962306a36Sopenharmony_ci struct { 15062306a36Sopenharmony_ci unsigned int fast:1; /* post with "channel end" */ 15162306a36Sopenharmony_ci unsigned int repall:1; /* report every interrupt status */ 15262306a36Sopenharmony_ci unsigned int pgroup:1; /* do path grouping */ 15362306a36Sopenharmony_ci unsigned int force:1; /* allow forced online */ 15462306a36Sopenharmony_ci unsigned int mpath:1; /* do multipathing */ 15562306a36Sopenharmony_ci } __attribute__ ((packed)) options; 15662306a36Sopenharmony_ci struct { 15762306a36Sopenharmony_ci unsigned int esid:1; /* Ext. SenseID supported by HW */ 15862306a36Sopenharmony_ci unsigned int dosense:1; /* delayed SENSE required */ 15962306a36Sopenharmony_ci unsigned int doverify:1; /* delayed path verification */ 16062306a36Sopenharmony_ci unsigned int donotify:1; /* call notify function */ 16162306a36Sopenharmony_ci unsigned int recog_done:1; /* dev. recog. complete */ 16262306a36Sopenharmony_ci unsigned int fake_irb:2; /* deliver faked irb */ 16362306a36Sopenharmony_ci unsigned int pgroup:1; /* pathgroup is set up */ 16462306a36Sopenharmony_ci unsigned int mpath:1; /* multipathing is set up */ 16562306a36Sopenharmony_ci unsigned int pgid_unknown:1;/* unknown pgid state */ 16662306a36Sopenharmony_ci unsigned int initialized:1; /* set if initial reference held */ 16762306a36Sopenharmony_ci } __attribute__((packed)) flags; 16862306a36Sopenharmony_ci unsigned long intparm; /* user interruption parameter */ 16962306a36Sopenharmony_ci struct qdio_irq *qdio_data; 17062306a36Sopenharmony_ci int async_kill_io_rc; 17162306a36Sopenharmony_ci struct work_struct todo_work; 17262306a36Sopenharmony_ci enum cdev_todo todo; 17362306a36Sopenharmony_ci wait_queue_head_t wait_q; 17462306a36Sopenharmony_ci struct timer_list timer; 17562306a36Sopenharmony_ci void *cmb; /* measurement information */ 17662306a36Sopenharmony_ci struct list_head cmb_list; /* list of measured devices */ 17762306a36Sopenharmony_ci u64 cmb_start_time; /* clock value of cmb reset */ 17862306a36Sopenharmony_ci void *cmb_wait; /* deferred cmb enable/disable */ 17962306a36Sopenharmony_ci struct gen_pool *dma_pool; 18062306a36Sopenharmony_ci struct ccw_device_dma_area *dma_area; 18162306a36Sopenharmony_ci enum interruption_class int_class; 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci#endif 185