1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun #ifndef S390_ISM_H
3*4882a593Smuzhiyun #define S390_ISM_H
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #include <linux/spinlock.h>
6*4882a593Smuzhiyun #include <linux/types.h>
7*4882a593Smuzhiyun #include <linux/pci.h>
8*4882a593Smuzhiyun #include <net/smc.h>
9*4882a593Smuzhiyun #include <asm/pci_insn.h>
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #define UTIL_STR_LEN 16
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun /*
14*4882a593Smuzhiyun * Do not use the first word of the DMB bits to ensure 8 byte aligned access.
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun #define ISM_DMB_WORD_OFFSET 1
17*4882a593Smuzhiyun #define ISM_DMB_BIT_OFFSET (ISM_DMB_WORD_OFFSET * 32)
18*4882a593Smuzhiyun #define ISM_NR_DMBS 1920
19*4882a593Smuzhiyun #define ISM_IDENT_MASK 0x00FFFF
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #define ISM_REG_SBA 0x1
22*4882a593Smuzhiyun #define ISM_REG_IEQ 0x2
23*4882a593Smuzhiyun #define ISM_READ_GID 0x3
24*4882a593Smuzhiyun #define ISM_ADD_VLAN_ID 0x4
25*4882a593Smuzhiyun #define ISM_DEL_VLAN_ID 0x5
26*4882a593Smuzhiyun #define ISM_SET_VLAN 0x6
27*4882a593Smuzhiyun #define ISM_RESET_VLAN 0x7
28*4882a593Smuzhiyun #define ISM_QUERY_INFO 0x8
29*4882a593Smuzhiyun #define ISM_QUERY_RGID 0x9
30*4882a593Smuzhiyun #define ISM_REG_DMB 0xA
31*4882a593Smuzhiyun #define ISM_UNREG_DMB 0xB
32*4882a593Smuzhiyun #define ISM_SIGNAL_IEQ 0xE
33*4882a593Smuzhiyun #define ISM_UNREG_SBA 0x11
34*4882a593Smuzhiyun #define ISM_UNREG_IEQ 0x12
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun struct ism_req_hdr {
37*4882a593Smuzhiyun u32 cmd;
38*4882a593Smuzhiyun u16 : 16;
39*4882a593Smuzhiyun u16 len;
40*4882a593Smuzhiyun };
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun struct ism_resp_hdr {
43*4882a593Smuzhiyun u32 cmd;
44*4882a593Smuzhiyun u16 ret;
45*4882a593Smuzhiyun u16 len;
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun union ism_reg_sba {
49*4882a593Smuzhiyun struct {
50*4882a593Smuzhiyun struct ism_req_hdr hdr;
51*4882a593Smuzhiyun u64 sba;
52*4882a593Smuzhiyun } request;
53*4882a593Smuzhiyun struct {
54*4882a593Smuzhiyun struct ism_resp_hdr hdr;
55*4882a593Smuzhiyun } response;
56*4882a593Smuzhiyun } __aligned(16);
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun union ism_reg_ieq {
59*4882a593Smuzhiyun struct {
60*4882a593Smuzhiyun struct ism_req_hdr hdr;
61*4882a593Smuzhiyun u64 ieq;
62*4882a593Smuzhiyun u64 len;
63*4882a593Smuzhiyun } request;
64*4882a593Smuzhiyun struct {
65*4882a593Smuzhiyun struct ism_resp_hdr hdr;
66*4882a593Smuzhiyun } response;
67*4882a593Smuzhiyun } __aligned(16);
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun union ism_read_gid {
70*4882a593Smuzhiyun struct {
71*4882a593Smuzhiyun struct ism_req_hdr hdr;
72*4882a593Smuzhiyun } request;
73*4882a593Smuzhiyun struct {
74*4882a593Smuzhiyun struct ism_resp_hdr hdr;
75*4882a593Smuzhiyun u64 gid;
76*4882a593Smuzhiyun } response;
77*4882a593Smuzhiyun } __aligned(16);
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun union ism_qi {
80*4882a593Smuzhiyun struct {
81*4882a593Smuzhiyun struct ism_req_hdr hdr;
82*4882a593Smuzhiyun } request;
83*4882a593Smuzhiyun struct {
84*4882a593Smuzhiyun struct ism_resp_hdr hdr;
85*4882a593Smuzhiyun u32 version;
86*4882a593Smuzhiyun u32 max_len;
87*4882a593Smuzhiyun u64 ism_state;
88*4882a593Smuzhiyun u64 my_gid;
89*4882a593Smuzhiyun u64 sba;
90*4882a593Smuzhiyun u64 ieq;
91*4882a593Smuzhiyun u32 ieq_len;
92*4882a593Smuzhiyun u32 : 32;
93*4882a593Smuzhiyun u32 dmbs_owned;
94*4882a593Smuzhiyun u32 dmbs_used;
95*4882a593Smuzhiyun u32 vlan_required;
96*4882a593Smuzhiyun u32 vlan_nr_ids;
97*4882a593Smuzhiyun u16 vlan_id[64];
98*4882a593Smuzhiyun } response;
99*4882a593Smuzhiyun } __aligned(64);
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun union ism_query_rgid {
102*4882a593Smuzhiyun struct {
103*4882a593Smuzhiyun struct ism_req_hdr hdr;
104*4882a593Smuzhiyun u64 rgid;
105*4882a593Smuzhiyun u32 vlan_valid;
106*4882a593Smuzhiyun u32 vlan_id;
107*4882a593Smuzhiyun } request;
108*4882a593Smuzhiyun struct {
109*4882a593Smuzhiyun struct ism_resp_hdr hdr;
110*4882a593Smuzhiyun } response;
111*4882a593Smuzhiyun } __aligned(16);
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun union ism_reg_dmb {
114*4882a593Smuzhiyun struct {
115*4882a593Smuzhiyun struct ism_req_hdr hdr;
116*4882a593Smuzhiyun u64 dmb;
117*4882a593Smuzhiyun u32 dmb_len;
118*4882a593Smuzhiyun u32 sba_idx;
119*4882a593Smuzhiyun u32 vlan_valid;
120*4882a593Smuzhiyun u32 vlan_id;
121*4882a593Smuzhiyun u64 rgid;
122*4882a593Smuzhiyun } request;
123*4882a593Smuzhiyun struct {
124*4882a593Smuzhiyun struct ism_resp_hdr hdr;
125*4882a593Smuzhiyun u64 dmb_tok;
126*4882a593Smuzhiyun } response;
127*4882a593Smuzhiyun } __aligned(32);
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun union ism_sig_ieq {
130*4882a593Smuzhiyun struct {
131*4882a593Smuzhiyun struct ism_req_hdr hdr;
132*4882a593Smuzhiyun u64 rgid;
133*4882a593Smuzhiyun u32 trigger_irq;
134*4882a593Smuzhiyun u32 event_code;
135*4882a593Smuzhiyun u64 info;
136*4882a593Smuzhiyun } request;
137*4882a593Smuzhiyun struct {
138*4882a593Smuzhiyun struct ism_resp_hdr hdr;
139*4882a593Smuzhiyun } response;
140*4882a593Smuzhiyun } __aligned(32);
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun union ism_unreg_dmb {
143*4882a593Smuzhiyun struct {
144*4882a593Smuzhiyun struct ism_req_hdr hdr;
145*4882a593Smuzhiyun u64 dmb_tok;
146*4882a593Smuzhiyun } request;
147*4882a593Smuzhiyun struct {
148*4882a593Smuzhiyun struct ism_resp_hdr hdr;
149*4882a593Smuzhiyun } response;
150*4882a593Smuzhiyun } __aligned(16);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun union ism_cmd_simple {
153*4882a593Smuzhiyun struct {
154*4882a593Smuzhiyun struct ism_req_hdr hdr;
155*4882a593Smuzhiyun } request;
156*4882a593Smuzhiyun struct {
157*4882a593Smuzhiyun struct ism_resp_hdr hdr;
158*4882a593Smuzhiyun } response;
159*4882a593Smuzhiyun } __aligned(8);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun union ism_set_vlan_id {
162*4882a593Smuzhiyun struct {
163*4882a593Smuzhiyun struct ism_req_hdr hdr;
164*4882a593Smuzhiyun u64 vlan_id;
165*4882a593Smuzhiyun } request;
166*4882a593Smuzhiyun struct {
167*4882a593Smuzhiyun struct ism_resp_hdr hdr;
168*4882a593Smuzhiyun } response;
169*4882a593Smuzhiyun } __aligned(16);
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun struct ism_eq_header {
172*4882a593Smuzhiyun u64 idx;
173*4882a593Smuzhiyun u64 ieq_len;
174*4882a593Smuzhiyun u64 entry_len;
175*4882a593Smuzhiyun u64 : 64;
176*4882a593Smuzhiyun };
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun struct ism_eq {
179*4882a593Smuzhiyun struct ism_eq_header header;
180*4882a593Smuzhiyun struct smcd_event entry[15];
181*4882a593Smuzhiyun };
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun struct ism_sba {
184*4882a593Smuzhiyun u32 s : 1; /* summary bit */
185*4882a593Smuzhiyun u32 e : 1; /* event bit */
186*4882a593Smuzhiyun u32 : 30;
187*4882a593Smuzhiyun u32 dmb_bits[ISM_NR_DMBS / 32];
188*4882a593Smuzhiyun u32 reserved[3];
189*4882a593Smuzhiyun u16 dmbe_mask[ISM_NR_DMBS];
190*4882a593Smuzhiyun };
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun struct ism_dev {
193*4882a593Smuzhiyun spinlock_t lock;
194*4882a593Smuzhiyun struct pci_dev *pdev;
195*4882a593Smuzhiyun struct smcd_dev *smcd;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun struct ism_sba *sba;
198*4882a593Smuzhiyun dma_addr_t sba_dma_addr;
199*4882a593Smuzhiyun DECLARE_BITMAP(sba_bitmap, ISM_NR_DMBS);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun struct ism_eq *ieq;
202*4882a593Smuzhiyun dma_addr_t ieq_dma_addr;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun int ieq_idx;
205*4882a593Smuzhiyun };
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun #define ISM_CREATE_REQ(dmb, idx, sf, offset) \
208*4882a593Smuzhiyun ((dmb) | (idx) << 24 | (sf) << 23 | (offset))
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun struct ism_systemeid {
211*4882a593Smuzhiyun u8 seid_string[24];
212*4882a593Smuzhiyun u8 serial_number[4];
213*4882a593Smuzhiyun u8 type[4];
214*4882a593Smuzhiyun };
215*4882a593Smuzhiyun
__ism_read_cmd(struct ism_dev * ism,void * data,unsigned long offset,unsigned long len)216*4882a593Smuzhiyun static inline void __ism_read_cmd(struct ism_dev *ism, void *data,
217*4882a593Smuzhiyun unsigned long offset, unsigned long len)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun struct zpci_dev *zdev = to_zpci(ism->pdev);
220*4882a593Smuzhiyun u64 req = ZPCI_CREATE_REQ(zdev->fh, 2, 8);
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun while (len > 0) {
223*4882a593Smuzhiyun __zpci_load(data, req, offset);
224*4882a593Smuzhiyun offset += 8;
225*4882a593Smuzhiyun data += 8;
226*4882a593Smuzhiyun len -= 8;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
__ism_write_cmd(struct ism_dev * ism,void * data,unsigned long offset,unsigned long len)230*4882a593Smuzhiyun static inline void __ism_write_cmd(struct ism_dev *ism, void *data,
231*4882a593Smuzhiyun unsigned long offset, unsigned long len)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun struct zpci_dev *zdev = to_zpci(ism->pdev);
234*4882a593Smuzhiyun u64 req = ZPCI_CREATE_REQ(zdev->fh, 2, len);
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun if (len)
237*4882a593Smuzhiyun __zpci_store_block(data, req, offset);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
__ism_move(struct ism_dev * ism,u64 dmb_req,void * data,unsigned int size)240*4882a593Smuzhiyun static inline int __ism_move(struct ism_dev *ism, u64 dmb_req, void *data,
241*4882a593Smuzhiyun unsigned int size)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun struct zpci_dev *zdev = to_zpci(ism->pdev);
244*4882a593Smuzhiyun u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, size);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun return __zpci_store_block(data, req, dmb_req);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun #endif /* S390_ISM_H */
250