/* SPDX-License-Identifier: GPL-2.0 */ #ifndef S390_ISM_H #define S390_ISM_H #include #include #include #include #include #define UTIL_STR_LEN 16 /* * Do not use the first word of the DMB bits to ensure 8 byte aligned access. */ #define ISM_DMB_WORD_OFFSET 1 #define ISM_DMB_BIT_OFFSET (ISM_DMB_WORD_OFFSET * 32) #define ISM_NR_DMBS 1920 #define ISM_REG_SBA 0x1 #define ISM_REG_IEQ 0x2 #define ISM_READ_GID 0x3 #define ISM_ADD_VLAN_ID 0x4 #define ISM_DEL_VLAN_ID 0x5 #define ISM_SET_VLAN 0x6 #define ISM_RESET_VLAN 0x7 #define ISM_QUERY_INFO 0x8 #define ISM_QUERY_RGID 0x9 #define ISM_REG_DMB 0xA #define ISM_UNREG_DMB 0xB #define ISM_SIGNAL_IEQ 0xE #define ISM_UNREG_SBA 0x11 #define ISM_UNREG_IEQ 0x12 struct ism_req_hdr { u32 cmd; u16 : 16; u16 len; }; struct ism_resp_hdr { u32 cmd; u16 ret; u16 len; }; union ism_reg_sba { struct { struct ism_req_hdr hdr; u64 sba; } request; struct { struct ism_resp_hdr hdr; } response; } __aligned(16); union ism_reg_ieq { struct { struct ism_req_hdr hdr; u64 ieq; u64 len; } request; struct { struct ism_resp_hdr hdr; } response; } __aligned(16); union ism_read_gid { struct { struct ism_req_hdr hdr; } request; struct { struct ism_resp_hdr hdr; u64 gid; } response; } __aligned(16); union ism_qi { struct { struct ism_req_hdr hdr; } request; struct { struct ism_resp_hdr hdr; u32 version; u32 max_len; u64 ism_state; u64 my_gid; u64 sba; u64 ieq; u32 ieq_len; u32 : 32; u32 dmbs_owned; u32 dmbs_used; u32 vlan_required; u32 vlan_nr_ids; u16 vlan_id[64]; } response; } __aligned(64); union ism_query_rgid { struct { struct ism_req_hdr hdr; u64 rgid; u32 vlan_valid; u32 vlan_id; } request; struct { struct ism_resp_hdr hdr; } response; } __aligned(16); union ism_reg_dmb { struct { struct ism_req_hdr hdr; u64 dmb; u32 dmb_len; u32 sba_idx; u32 vlan_valid; u32 vlan_id; u64 rgid; } request; struct { struct ism_resp_hdr hdr; u64 dmb_tok; } response; } __aligned(32); union ism_sig_ieq { struct { struct ism_req_hdr hdr; u64 rgid; u32 trigger_irq; u32 event_code; u64 info; } request; struct { struct ism_resp_hdr hdr; } response; } __aligned(32); union ism_unreg_dmb { struct { struct ism_req_hdr hdr; u64 dmb_tok; } request; struct { struct ism_resp_hdr hdr; } response; } __aligned(16); union ism_cmd_simple { struct { struct ism_req_hdr hdr; } request; struct { struct ism_resp_hdr hdr; } response; } __aligned(8); union ism_set_vlan_id { struct { struct ism_req_hdr hdr; u64 vlan_id; } request; struct { struct ism_resp_hdr hdr; } response; } __aligned(16); struct ism_eq_header { u64 idx; u64 ieq_len; u64 entry_len; u64 : 64; }; struct ism_eq { struct ism_eq_header header; struct smcd_event entry[15]; }; struct ism_sba { u32 s : 1; /* summary bit */ u32 e : 1; /* event bit */ u32 : 30; u32 dmb_bits[ISM_NR_DMBS / 32]; u32 reserved[3]; u16 dmbe_mask[ISM_NR_DMBS]; }; struct ism_dev { spinlock_t lock; struct pci_dev *pdev; struct smcd_dev *smcd; struct ism_sba *sba; dma_addr_t sba_dma_addr; DECLARE_BITMAP(sba_bitmap, ISM_NR_DMBS); struct ism_eq *ieq; dma_addr_t ieq_dma_addr; int ieq_idx; }; #define ISM_CREATE_REQ(dmb, idx, sf, offset) \ ((dmb) | (idx) << 24 | (sf) << 23 | (offset)) static inline void __ism_read_cmd(struct ism_dev *ism, void *data, unsigned long offset, unsigned long len) { struct zpci_dev *zdev = to_zpci(ism->pdev); u64 req = ZPCI_CREATE_REQ(zdev->fh, 2, 8); while (len > 0) { __zpci_load(data, req, offset); offset += 8; data += 8; len -= 8; } } static inline void __ism_write_cmd(struct ism_dev *ism, void *data, unsigned long offset, unsigned long len) { struct zpci_dev *zdev = to_zpci(ism->pdev); u64 req = ZPCI_CREATE_REQ(zdev->fh, 2, len); if (len) __zpci_store_block(data, req, offset); } static inline int __ism_move(struct ism_dev *ism, u64 dmb_req, void *data, unsigned int size) { struct zpci_dev *zdev = to_zpci(ism->pdev); u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, size); return __zpci_store_block(data, req, dmb_req); } #endif /* S390_ISM_H */