277 lines
5.1 KiB
C
277 lines
5.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef S390_ISM_H
|
|
#define S390_ISM_H
|
|
|
|
#include <linux/spinlock.h>
|
|
#include <linux/types.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/dibs.h>
|
|
#include <asm/pci_insn.h>
|
|
|
|
#define UTIL_STR_LEN 16
|
|
#define ISM_ERROR 0xFFFF
|
|
|
|
#define ISM_NR_DMBS 1920
|
|
|
|
/*
|
|
* 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_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
|
|
|
|
enum ism_event_type {
|
|
ISM_EVENT_BUF = 0x00,
|
|
ISM_EVENT_DEV = 0x01,
|
|
ISM_EVENT_SWR = 0x02
|
|
};
|
|
|
|
enum ism_event_code {
|
|
ISM_BUF_DMB_UNREGISTERED = 0x04,
|
|
ISM_BUF_USING_ISM_DEV_DISABLED = 0x08,
|
|
ISM_BUF_OWNING_ISM_DEV_IN_ERR_STATE = 0x02,
|
|
ISM_BUF_USING_ISM_DEV_IN_ERR_STATE = 0x03,
|
|
ISM_BUF_VLAN_MISMATCH_WITH_OWNER = 0x05,
|
|
ISM_BUF_VLAN_MISMATCH_WITH_USER = 0x06,
|
|
ISM_DEV_GID_DISABLED = 0x07,
|
|
ISM_DEV_GID_ERR_STATE = 0x01
|
|
};
|
|
|
|
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);
|
|
|
|
/* ISM-vPCI devices provide 64 Bit GIDs
|
|
* Map them to ISM UUID GIDs like this:
|
|
* _________________________________________
|
|
* | 64 Bit ISM-vPCI GID | 00000000_00000000 |
|
|
* -----------------------------------------
|
|
* This will be interpreted as a UIID variant, that is reserved
|
|
* for NCS backward compatibility. So it will not collide with
|
|
* proper UUIDs.
|
|
*/
|
|
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_event {
|
|
u32 type;
|
|
u32 code;
|
|
u64 tok;
|
|
u64 time;
|
|
u64 info;
|
|
};
|
|
|
|
struct ism_eq {
|
|
struct ism_eq_header header;
|
|
struct ism_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 cmd_lock; /* serializes cmds */
|
|
struct dibs_dev *dibs;
|
|
struct pci_dev *pdev;
|
|
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 */
|