162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright(c) 2017 Intel Corporation. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#ifndef _HFI1_EXP_RCV_H 762306a36Sopenharmony_ci#define _HFI1_EXP_RCV_H 862306a36Sopenharmony_ci#include "hfi.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define EXP_TID_SET_EMPTY(set) (set.count == 0 && list_empty(&set.list)) 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define EXP_TID_TIDLEN_MASK 0x7FFULL 1362306a36Sopenharmony_ci#define EXP_TID_TIDLEN_SHIFT 0 1462306a36Sopenharmony_ci#define EXP_TID_TIDCTRL_MASK 0x3ULL 1562306a36Sopenharmony_ci#define EXP_TID_TIDCTRL_SHIFT 20 1662306a36Sopenharmony_ci#define EXP_TID_TIDIDX_MASK 0x3FFULL 1762306a36Sopenharmony_ci#define EXP_TID_TIDIDX_SHIFT 22 1862306a36Sopenharmony_ci#define EXP_TID_GET(tid, field) \ 1962306a36Sopenharmony_ci (((tid) >> EXP_TID_TID##field##_SHIFT) & EXP_TID_TID##field##_MASK) 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define EXP_TID_SET(field, value) \ 2262306a36Sopenharmony_ci (((value) & EXP_TID_TID##field##_MASK) << \ 2362306a36Sopenharmony_ci EXP_TID_TID##field##_SHIFT) 2462306a36Sopenharmony_ci#define EXP_TID_CLEAR(tid, field) ({ \ 2562306a36Sopenharmony_ci (tid) &= ~(EXP_TID_TID##field##_MASK << \ 2662306a36Sopenharmony_ci EXP_TID_TID##field##_SHIFT); \ 2762306a36Sopenharmony_ci }) 2862306a36Sopenharmony_ci#define EXP_TID_RESET(tid, field, value) do { \ 2962306a36Sopenharmony_ci EXP_TID_CLEAR(tid, field); \ 3062306a36Sopenharmony_ci (tid) |= EXP_TID_SET(field, (value)); \ 3162306a36Sopenharmony_ci } while (0) 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* 3462306a36Sopenharmony_ci * Define fields in the KDETH header so we can update the header 3562306a36Sopenharmony_ci * template. 3662306a36Sopenharmony_ci */ 3762306a36Sopenharmony_ci#define KDETH_OFFSET_SHIFT 0 3862306a36Sopenharmony_ci#define KDETH_OFFSET_MASK 0x7fff 3962306a36Sopenharmony_ci#define KDETH_OM_SHIFT 15 4062306a36Sopenharmony_ci#define KDETH_OM_MASK 0x1 4162306a36Sopenharmony_ci#define KDETH_TID_SHIFT 16 4262306a36Sopenharmony_ci#define KDETH_TID_MASK 0x3ff 4362306a36Sopenharmony_ci#define KDETH_TIDCTRL_SHIFT 26 4462306a36Sopenharmony_ci#define KDETH_TIDCTRL_MASK 0x3 4562306a36Sopenharmony_ci#define KDETH_INTR_SHIFT 28 4662306a36Sopenharmony_ci#define KDETH_INTR_MASK 0x1 4762306a36Sopenharmony_ci#define KDETH_SH_SHIFT 29 4862306a36Sopenharmony_ci#define KDETH_SH_MASK 0x1 4962306a36Sopenharmony_ci#define KDETH_KVER_SHIFT 30 5062306a36Sopenharmony_ci#define KDETH_KVER_MASK 0x3 5162306a36Sopenharmony_ci#define KDETH_JKEY_SHIFT 0x0 5262306a36Sopenharmony_ci#define KDETH_JKEY_MASK 0xff 5362306a36Sopenharmony_ci#define KDETH_HCRC_UPPER_SHIFT 16 5462306a36Sopenharmony_ci#define KDETH_HCRC_UPPER_MASK 0xff 5562306a36Sopenharmony_ci#define KDETH_HCRC_LOWER_SHIFT 24 5662306a36Sopenharmony_ci#define KDETH_HCRC_LOWER_MASK 0xff 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#define KDETH_GET(val, field) \ 5962306a36Sopenharmony_ci (((le32_to_cpu((val))) >> KDETH_##field##_SHIFT) & KDETH_##field##_MASK) 6062306a36Sopenharmony_ci#define KDETH_SET(dw, field, val) do { \ 6162306a36Sopenharmony_ci u32 dwval = le32_to_cpu(dw); \ 6262306a36Sopenharmony_ci dwval &= ~(KDETH_##field##_MASK << KDETH_##field##_SHIFT); \ 6362306a36Sopenharmony_ci dwval |= (((val) & KDETH_##field##_MASK) << \ 6462306a36Sopenharmony_ci KDETH_##field##_SHIFT); \ 6562306a36Sopenharmony_ci dw = cpu_to_le32(dwval); \ 6662306a36Sopenharmony_ci } while (0) 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci#define KDETH_RESET(dw, field, val) ({ dw = 0; KDETH_SET(dw, field, val); }) 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/* KDETH OM multipliers and switch over point */ 7162306a36Sopenharmony_ci#define KDETH_OM_SMALL 4 7262306a36Sopenharmony_ci#define KDETH_OM_SMALL_SHIFT 2 7362306a36Sopenharmony_ci#define KDETH_OM_LARGE 64 7462306a36Sopenharmony_ci#define KDETH_OM_LARGE_SHIFT 6 7562306a36Sopenharmony_ci#define KDETH_OM_MAX_SIZE (1 << ((KDETH_OM_LARGE / KDETH_OM_SMALL) + 1)) 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistruct tid_group { 7862306a36Sopenharmony_ci struct list_head list; 7962306a36Sopenharmony_ci u32 base; 8062306a36Sopenharmony_ci u8 size; 8162306a36Sopenharmony_ci u8 used; 8262306a36Sopenharmony_ci u8 map; 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci/* 8662306a36Sopenharmony_ci * Write an "empty" RcvArray entry. 8762306a36Sopenharmony_ci * This function exists so the TID registaration code can use it 8862306a36Sopenharmony_ci * to write to unused/unneeded entries and still take advantage 8962306a36Sopenharmony_ci * of the WC performance improvements. The HFI will ignore this 9062306a36Sopenharmony_ci * write to the RcvArray entry. 9162306a36Sopenharmony_ci */ 9262306a36Sopenharmony_cistatic inline void rcv_array_wc_fill(struct hfi1_devdata *dd, u32 index) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci /* 9562306a36Sopenharmony_ci * Doing the WC fill writes only makes sense if the device is 9662306a36Sopenharmony_ci * present and the RcvArray has been mapped as WC memory. 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_ci if ((dd->flags & HFI1_PRESENT) && dd->rcvarray_wc) { 9962306a36Sopenharmony_ci writeq(0, dd->rcvarray_wc + (index * 8)); 10062306a36Sopenharmony_ci if ((index & 3) == 3) 10162306a36Sopenharmony_ci flush_wc(); 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic inline void tid_group_add_tail(struct tid_group *grp, 10662306a36Sopenharmony_ci struct exp_tid_set *set) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci list_add_tail(&grp->list, &set->list); 10962306a36Sopenharmony_ci set->count++; 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic inline void tid_group_remove(struct tid_group *grp, 11362306a36Sopenharmony_ci struct exp_tid_set *set) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci list_del_init(&grp->list); 11662306a36Sopenharmony_ci set->count--; 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic inline void tid_group_move(struct tid_group *group, 12062306a36Sopenharmony_ci struct exp_tid_set *s1, 12162306a36Sopenharmony_ci struct exp_tid_set *s2) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci tid_group_remove(group, s1); 12462306a36Sopenharmony_ci tid_group_add_tail(group, s2); 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic inline struct tid_group *tid_group_pop(struct exp_tid_set *set) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci struct tid_group *grp = 13062306a36Sopenharmony_ci list_first_entry(&set->list, struct tid_group, list); 13162306a36Sopenharmony_ci list_del_init(&grp->list); 13262306a36Sopenharmony_ci set->count--; 13362306a36Sopenharmony_ci return grp; 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic inline u32 create_tid(u32 rcventry, u32 npages) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci u32 pair = rcventry & ~0x1; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci return EXP_TID_SET(IDX, pair >> 1) | 14162306a36Sopenharmony_ci EXP_TID_SET(CTRL, 1 << (rcventry - pair)) | 14262306a36Sopenharmony_ci EXP_TID_SET(LEN, npages); 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci/** 14662306a36Sopenharmony_ci * hfi1_tid_group_to_idx - convert an index to a group 14762306a36Sopenharmony_ci * @rcd - the receive context 14862306a36Sopenharmony_ci * @grp - the group pointer 14962306a36Sopenharmony_ci */ 15062306a36Sopenharmony_cistatic inline u16 15162306a36Sopenharmony_cihfi1_tid_group_to_idx(struct hfi1_ctxtdata *rcd, struct tid_group *grp) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci return grp - &rcd->groups[0]; 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci/** 15762306a36Sopenharmony_ci * hfi1_idx_to_tid_group - convert a group to an index 15862306a36Sopenharmony_ci * @rcd - the receive context 15962306a36Sopenharmony_ci * @idx - the index 16062306a36Sopenharmony_ci */ 16162306a36Sopenharmony_cistatic inline struct tid_group * 16262306a36Sopenharmony_cihfi1_idx_to_tid_group(struct hfi1_ctxtdata *rcd, u16 idx) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci return &rcd->groups[idx]; 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ciint hfi1_alloc_ctxt_rcv_groups(struct hfi1_ctxtdata *rcd); 16862306a36Sopenharmony_civoid hfi1_free_ctxt_rcv_groups(struct hfi1_ctxtdata *rcd); 16962306a36Sopenharmony_civoid hfi1_exp_tid_group_init(struct hfi1_ctxtdata *rcd); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci#endif /* _HFI1_EXP_RCV_H */ 172