172 lines · c
1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */2/*3 * Copyright(c) 2017 Intel Corporation.4 */5 6#ifndef _HFI1_EXP_RCV_H7#define _HFI1_EXP_RCV_H8#include "hfi.h"9 10#define EXP_TID_SET_EMPTY(set) (set.count == 0 && list_empty(&set.list))11 12#define EXP_TID_TIDLEN_MASK 0x7FFULL13#define EXP_TID_TIDLEN_SHIFT 014#define EXP_TID_TIDCTRL_MASK 0x3ULL15#define EXP_TID_TIDCTRL_SHIFT 2016#define EXP_TID_TIDIDX_MASK 0x3FFULL17#define EXP_TID_TIDIDX_SHIFT 2218#define EXP_TID_GET(tid, field) \19 (((tid) >> EXP_TID_TID##field##_SHIFT) & EXP_TID_TID##field##_MASK)20 21#define EXP_TID_SET(field, value) \22 (((value) & EXP_TID_TID##field##_MASK) << \23 EXP_TID_TID##field##_SHIFT)24#define EXP_TID_CLEAR(tid, field) ({ \25 (tid) &= ~(EXP_TID_TID##field##_MASK << \26 EXP_TID_TID##field##_SHIFT); \27 })28#define EXP_TID_RESET(tid, field, value) do { \29 EXP_TID_CLEAR(tid, field); \30 (tid) |= EXP_TID_SET(field, (value)); \31 } while (0)32 33/*34 * Define fields in the KDETH header so we can update the header35 * template.36 */37#define KDETH_OFFSET_SHIFT 038#define KDETH_OFFSET_MASK 0x7fff39#define KDETH_OM_SHIFT 1540#define KDETH_OM_MASK 0x141#define KDETH_TID_SHIFT 1642#define KDETH_TID_MASK 0x3ff43#define KDETH_TIDCTRL_SHIFT 2644#define KDETH_TIDCTRL_MASK 0x345#define KDETH_INTR_SHIFT 2846#define KDETH_INTR_MASK 0x147#define KDETH_SH_SHIFT 2948#define KDETH_SH_MASK 0x149#define KDETH_KVER_SHIFT 3050#define KDETH_KVER_MASK 0x351#define KDETH_JKEY_SHIFT 0x052#define KDETH_JKEY_MASK 0xff53#define KDETH_HCRC_UPPER_SHIFT 1654#define KDETH_HCRC_UPPER_MASK 0xff55#define KDETH_HCRC_LOWER_SHIFT 2456#define KDETH_HCRC_LOWER_MASK 0xff57 58#define KDETH_GET(val, field) \59 (((le32_to_cpu((val))) >> KDETH_##field##_SHIFT) & KDETH_##field##_MASK)60#define KDETH_SET(dw, field, val) do { \61 u32 dwval = le32_to_cpu(dw); \62 dwval &= ~(KDETH_##field##_MASK << KDETH_##field##_SHIFT); \63 dwval |= (((val) & KDETH_##field##_MASK) << \64 KDETH_##field##_SHIFT); \65 dw = cpu_to_le32(dwval); \66 } while (0)67 68#define KDETH_RESET(dw, field, val) ({ dw = 0; KDETH_SET(dw, field, val); })69 70/* KDETH OM multipliers and switch over point */71#define KDETH_OM_SMALL 472#define KDETH_OM_SMALL_SHIFT 273#define KDETH_OM_LARGE 6474#define KDETH_OM_LARGE_SHIFT 675#define KDETH_OM_MAX_SIZE (1 << ((KDETH_OM_LARGE / KDETH_OM_SMALL) + 1))76 77struct tid_group {78 struct list_head list;79 u32 base;80 u8 size;81 u8 used;82 u8 map;83};84 85/*86 * Write an "empty" RcvArray entry.87 * This function exists so the TID registaration code can use it88 * to write to unused/unneeded entries and still take advantage89 * of the WC performance improvements. The HFI will ignore this90 * write to the RcvArray entry.91 */92static inline void rcv_array_wc_fill(struct hfi1_devdata *dd, u32 index)93{94 /*95 * Doing the WC fill writes only makes sense if the device is96 * present and the RcvArray has been mapped as WC memory.97 */98 if ((dd->flags & HFI1_PRESENT) && dd->rcvarray_wc) {99 writeq(0, dd->rcvarray_wc + (index * 8));100 if ((index & 3) == 3)101 flush_wc();102 }103}104 105static inline void tid_group_add_tail(struct tid_group *grp,106 struct exp_tid_set *set)107{108 list_add_tail(&grp->list, &set->list);109 set->count++;110}111 112static inline void tid_group_remove(struct tid_group *grp,113 struct exp_tid_set *set)114{115 list_del_init(&grp->list);116 set->count--;117}118 119static inline void tid_group_move(struct tid_group *group,120 struct exp_tid_set *s1,121 struct exp_tid_set *s2)122{123 tid_group_remove(group, s1);124 tid_group_add_tail(group, s2);125}126 127static inline struct tid_group *tid_group_pop(struct exp_tid_set *set)128{129 struct tid_group *grp =130 list_first_entry(&set->list, struct tid_group, list);131 list_del_init(&grp->list);132 set->count--;133 return grp;134}135 136static inline u32 create_tid(u32 rcventry, u32 npages)137{138 u32 pair = rcventry & ~0x1;139 140 return EXP_TID_SET(IDX, pair >> 1) |141 EXP_TID_SET(CTRL, 1 << (rcventry - pair)) |142 EXP_TID_SET(LEN, npages);143}144 145/**146 * hfi1_tid_group_to_idx - convert an index to a group147 * @rcd - the receive context148 * @grp - the group pointer149 */150static inline u16151hfi1_tid_group_to_idx(struct hfi1_ctxtdata *rcd, struct tid_group *grp)152{153 return grp - &rcd->groups[0];154}155 156/**157 * hfi1_idx_to_tid_group - convert a group to an index158 * @rcd - the receive context159 * @idx - the index160 */161static inline struct tid_group *162hfi1_idx_to_tid_group(struct hfi1_ctxtdata *rcd, u16 idx)163{164 return &rcd->groups[idx];165}166 167int hfi1_alloc_ctxt_rcv_groups(struct hfi1_ctxtdata *rcd);168void hfi1_free_ctxt_rcv_groups(struct hfi1_ctxtdata *rcd);169void hfi1_exp_tid_group_init(struct hfi1_ctxtdata *rcd);170 171#endif /* _HFI1_EXP_RCV_H */172