162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright(c) 2015-2017 Intel Corporation. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#ifndef _PIO_H 762306a36Sopenharmony_ci#define _PIO_H 862306a36Sopenharmony_ci/* send context types */ 962306a36Sopenharmony_ci#define SC_KERNEL 0 1062306a36Sopenharmony_ci#define SC_VL15 1 1162306a36Sopenharmony_ci#define SC_ACK 2 1262306a36Sopenharmony_ci#define SC_USER 3 /* must be the last one: it may take all left */ 1362306a36Sopenharmony_ci#define SC_MAX 4 /* count of send context types */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* invalid send context index */ 1662306a36Sopenharmony_ci#define INVALID_SCI 0xff 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* PIO buffer release callback function */ 1962306a36Sopenharmony_citypedef void (*pio_release_cb)(void *arg, int code); 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* PIO release codes - in bits, as there could more than one that apply */ 2262306a36Sopenharmony_ci#define PRC_OK 0 /* no known error */ 2362306a36Sopenharmony_ci#define PRC_STATUS_ERR 0x01 /* credit return due to status error */ 2462306a36Sopenharmony_ci#define PRC_PBC 0x02 /* credit return due to PBC */ 2562306a36Sopenharmony_ci#define PRC_THRESHOLD 0x04 /* credit return due to threshold */ 2662306a36Sopenharmony_ci#define PRC_FILL_ERR 0x08 /* credit return due fill error */ 2762306a36Sopenharmony_ci#define PRC_FORCE 0x10 /* credit return due credit force */ 2862306a36Sopenharmony_ci#define PRC_SC_DISABLE 0x20 /* clean-up after a context disable */ 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* byte helper */ 3162306a36Sopenharmony_ciunion mix { 3262306a36Sopenharmony_ci u64 val64; 3362306a36Sopenharmony_ci u32 val32[2]; 3462306a36Sopenharmony_ci u8 val8[8]; 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* an allocated PIO buffer */ 3862306a36Sopenharmony_cistruct pio_buf { 3962306a36Sopenharmony_ci struct send_context *sc;/* back pointer to owning send context */ 4062306a36Sopenharmony_ci pio_release_cb cb; /* called when the buffer is released */ 4162306a36Sopenharmony_ci void *arg; /* argument for cb */ 4262306a36Sopenharmony_ci void __iomem *start; /* buffer start address */ 4362306a36Sopenharmony_ci void __iomem *end; /* context end address */ 4462306a36Sopenharmony_ci unsigned long sent_at; /* buffer is sent when <= free */ 4562306a36Sopenharmony_ci union mix carry; /* pending unwritten bytes */ 4662306a36Sopenharmony_ci u16 qw_written; /* QW written so far */ 4762306a36Sopenharmony_ci u8 carry_bytes; /* number of valid bytes in carry */ 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* cache line aligned pio buffer array */ 5162306a36Sopenharmony_ciunion pio_shadow_ring { 5262306a36Sopenharmony_ci struct pio_buf pbuf; 5362306a36Sopenharmony_ci} ____cacheline_aligned; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* per-NUMA send context */ 5662306a36Sopenharmony_cistruct send_context { 5762306a36Sopenharmony_ci /* read-only after init */ 5862306a36Sopenharmony_ci struct hfi1_devdata *dd; /* device */ 5962306a36Sopenharmony_ci union pio_shadow_ring *sr; /* shadow ring */ 6062306a36Sopenharmony_ci void __iomem *base_addr; /* start of PIO memory */ 6162306a36Sopenharmony_ci u32 __percpu *buffers_allocated;/* count of buffers allocated */ 6262306a36Sopenharmony_ci u32 size; /* context size, in bytes */ 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci int node; /* context home node */ 6562306a36Sopenharmony_ci u32 sr_size; /* size of the shadow ring */ 6662306a36Sopenharmony_ci u16 flags; /* flags */ 6762306a36Sopenharmony_ci u8 type; /* context type */ 6862306a36Sopenharmony_ci u8 sw_index; /* software index number */ 6962306a36Sopenharmony_ci u8 hw_context; /* hardware context number */ 7062306a36Sopenharmony_ci u8 group; /* credit return group */ 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* allocator fields */ 7362306a36Sopenharmony_ci spinlock_t alloc_lock ____cacheline_aligned_in_smp; 7462306a36Sopenharmony_ci u32 sr_head; /* shadow ring head */ 7562306a36Sopenharmony_ci unsigned long fill; /* official alloc count */ 7662306a36Sopenharmony_ci unsigned long alloc_free; /* copy of free (less cache thrash) */ 7762306a36Sopenharmony_ci u32 fill_wrap; /* tracks fill within ring */ 7862306a36Sopenharmony_ci u32 credits; /* number of blocks in context */ 7962306a36Sopenharmony_ci /* adding a new field here would make it part of this cacheline */ 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci /* releaser fields */ 8262306a36Sopenharmony_ci spinlock_t release_lock ____cacheline_aligned_in_smp; 8362306a36Sopenharmony_ci u32 sr_tail; /* shadow ring tail */ 8462306a36Sopenharmony_ci unsigned long free; /* official free count */ 8562306a36Sopenharmony_ci volatile __le64 *hw_free; /* HW free counter */ 8662306a36Sopenharmony_ci /* list for PIO waiters */ 8762306a36Sopenharmony_ci struct list_head piowait ____cacheline_aligned_in_smp; 8862306a36Sopenharmony_ci seqlock_t waitlock; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci spinlock_t credit_ctrl_lock ____cacheline_aligned_in_smp; 9162306a36Sopenharmony_ci u32 credit_intr_count; /* count of credit intr users */ 9262306a36Sopenharmony_ci u64 credit_ctrl; /* cache for credit control */ 9362306a36Sopenharmony_ci wait_queue_head_t halt_wait; /* wait until kernel sees interrupt */ 9462306a36Sopenharmony_ci struct work_struct halt_work; /* halted context work queue entry */ 9562306a36Sopenharmony_ci}; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/* send context flags */ 9862306a36Sopenharmony_ci#define SCF_ENABLED 0x01 9962306a36Sopenharmony_ci#define SCF_IN_FREE 0x02 10062306a36Sopenharmony_ci#define SCF_HALTED 0x04 10162306a36Sopenharmony_ci#define SCF_FROZEN 0x08 10262306a36Sopenharmony_ci#define SCF_LINK_DOWN 0x10 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistruct send_context_info { 10562306a36Sopenharmony_ci struct send_context *sc; /* allocated working context */ 10662306a36Sopenharmony_ci u16 allocated; /* has this been allocated? */ 10762306a36Sopenharmony_ci u16 type; /* context type */ 10862306a36Sopenharmony_ci u16 base; /* base in PIO array */ 10962306a36Sopenharmony_ci u16 credits; /* size in PIO array */ 11062306a36Sopenharmony_ci}; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci/* DMA credit return, index is always (context & 0x7) */ 11362306a36Sopenharmony_cistruct credit_return { 11462306a36Sopenharmony_ci volatile __le64 cr[8]; 11562306a36Sopenharmony_ci}; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* NUMA indexed credit return array */ 11862306a36Sopenharmony_cistruct credit_return_base { 11962306a36Sopenharmony_ci struct credit_return *va; 12062306a36Sopenharmony_ci dma_addr_t dma; 12162306a36Sopenharmony_ci}; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci/* send context configuration sizes (one per type) */ 12462306a36Sopenharmony_cistruct sc_config_sizes { 12562306a36Sopenharmony_ci short int size; 12662306a36Sopenharmony_ci short int count; 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/* 13062306a36Sopenharmony_ci * The diagram below details the relationship of the mapping structures 13162306a36Sopenharmony_ci * 13262306a36Sopenharmony_ci * Since the mapping now allows for non-uniform send contexts per vl, the 13362306a36Sopenharmony_ci * number of send contexts for a vl is either the vl_scontexts[vl] or 13462306a36Sopenharmony_ci * a computation based on num_kernel_send_contexts/num_vls: 13562306a36Sopenharmony_ci * 13662306a36Sopenharmony_ci * For example: 13762306a36Sopenharmony_ci * nactual = vl_scontexts ? vl_scontexts[vl] : num_kernel_send_contexts/num_vls 13862306a36Sopenharmony_ci * 13962306a36Sopenharmony_ci * n = roundup to next highest power of 2 using nactual 14062306a36Sopenharmony_ci * 14162306a36Sopenharmony_ci * In the case where there are num_kernel_send_contexts/num_vls doesn't divide 14262306a36Sopenharmony_ci * evenly, the extras are added from the last vl downward. 14362306a36Sopenharmony_ci * 14462306a36Sopenharmony_ci * For the case where n > nactual, the send contexts are assigned 14562306a36Sopenharmony_ci * in a round robin fashion wrapping back to the first send context 14662306a36Sopenharmony_ci * for a particular vl. 14762306a36Sopenharmony_ci * 14862306a36Sopenharmony_ci * dd->pio_map 14962306a36Sopenharmony_ci * | pio_map_elem[0] 15062306a36Sopenharmony_ci * | +--------------------+ 15162306a36Sopenharmony_ci * v | mask | 15262306a36Sopenharmony_ci * pio_vl_map |--------------------| 15362306a36Sopenharmony_ci * +--------------------------+ | ksc[0] -> sc 1 | 15462306a36Sopenharmony_ci * | list (RCU) | |--------------------| 15562306a36Sopenharmony_ci * |--------------------------| ->| ksc[1] -> sc 2 | 15662306a36Sopenharmony_ci * | mask | --/ |--------------------| 15762306a36Sopenharmony_ci * |--------------------------| -/ | * | 15862306a36Sopenharmony_ci * | actual_vls (max 8) | -/ |--------------------| 15962306a36Sopenharmony_ci * |--------------------------| --/ | ksc[n-1] -> sc n | 16062306a36Sopenharmony_ci * | vls (max 8) | -/ +--------------------+ 16162306a36Sopenharmony_ci * |--------------------------| --/ 16262306a36Sopenharmony_ci * | map[0] |-/ 16362306a36Sopenharmony_ci * |--------------------------| +--------------------+ 16462306a36Sopenharmony_ci * | map[1] |--- | mask | 16562306a36Sopenharmony_ci * |--------------------------| \---- |--------------------| 16662306a36Sopenharmony_ci * | * | \-- | ksc[0] -> sc 1+n | 16762306a36Sopenharmony_ci * | * | \---- |--------------------| 16862306a36Sopenharmony_ci * | * | \->| ksc[1] -> sc 2+n | 16962306a36Sopenharmony_ci * |--------------------------| |--------------------| 17062306a36Sopenharmony_ci * | map[vls - 1] |- | * | 17162306a36Sopenharmony_ci * +--------------------------+ \- |--------------------| 17262306a36Sopenharmony_ci * \- | ksc[m-1] -> sc m+n | 17362306a36Sopenharmony_ci * \ +--------------------+ 17462306a36Sopenharmony_ci * \- 17562306a36Sopenharmony_ci * \ 17662306a36Sopenharmony_ci * \- +----------------------+ 17762306a36Sopenharmony_ci * \- | mask | 17862306a36Sopenharmony_ci * \ |----------------------| 17962306a36Sopenharmony_ci * \- | ksc[0] -> sc 1+m+n | 18062306a36Sopenharmony_ci * \- |----------------------| 18162306a36Sopenharmony_ci * >| ksc[1] -> sc 2+m+n | 18262306a36Sopenharmony_ci * |----------------------| 18362306a36Sopenharmony_ci * | * | 18462306a36Sopenharmony_ci * |----------------------| 18562306a36Sopenharmony_ci * | ksc[o-1] -> sc o+m+n | 18662306a36Sopenharmony_ci * +----------------------+ 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci */ 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci/* Initial number of send contexts per VL */ 19162306a36Sopenharmony_ci#define INIT_SC_PER_VL 2 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci/* 19462306a36Sopenharmony_ci * struct pio_map_elem - mapping for a vl 19562306a36Sopenharmony_ci * @mask - selector mask 19662306a36Sopenharmony_ci * @ksc - array of kernel send contexts for this vl 19762306a36Sopenharmony_ci * 19862306a36Sopenharmony_ci * The mask is used to "mod" the selector to 19962306a36Sopenharmony_ci * produce index into the trailing array of 20062306a36Sopenharmony_ci * kscs 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_cistruct pio_map_elem { 20362306a36Sopenharmony_ci u32 mask; 20462306a36Sopenharmony_ci struct send_context *ksc[]; 20562306a36Sopenharmony_ci}; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci/* 20862306a36Sopenharmony_ci * struct pio_vl_map - mapping for a vl 20962306a36Sopenharmony_ci * @list - rcu head for free callback 21062306a36Sopenharmony_ci * @mask - vl mask to "mod" the vl to produce an index to map array 21162306a36Sopenharmony_ci * @actual_vls - number of vls 21262306a36Sopenharmony_ci * @vls - numbers of vls rounded to next power of 2 21362306a36Sopenharmony_ci * @map - array of pio_map_elem entries 21462306a36Sopenharmony_ci * 21562306a36Sopenharmony_ci * This is the parent mapping structure. The trailing members of the 21662306a36Sopenharmony_ci * struct point to pio_map_elem entries, which in turn point to an 21762306a36Sopenharmony_ci * array of kscs for that vl. 21862306a36Sopenharmony_ci */ 21962306a36Sopenharmony_cistruct pio_vl_map { 22062306a36Sopenharmony_ci struct rcu_head list; 22162306a36Sopenharmony_ci u32 mask; 22262306a36Sopenharmony_ci u8 actual_vls; 22362306a36Sopenharmony_ci u8 vls; 22462306a36Sopenharmony_ci struct pio_map_elem *map[]; 22562306a36Sopenharmony_ci}; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ciint pio_map_init(struct hfi1_devdata *dd, u8 port, u8 num_vls, 22862306a36Sopenharmony_ci u8 *vl_scontexts); 22962306a36Sopenharmony_civoid free_pio_map(struct hfi1_devdata *dd); 23062306a36Sopenharmony_cistruct send_context *pio_select_send_context_vl(struct hfi1_devdata *dd, 23162306a36Sopenharmony_ci u32 selector, u8 vl); 23262306a36Sopenharmony_cistruct send_context *pio_select_send_context_sc(struct hfi1_devdata *dd, 23362306a36Sopenharmony_ci u32 selector, u8 sc5); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci/* send context functions */ 23662306a36Sopenharmony_ciint init_credit_return(struct hfi1_devdata *dd); 23762306a36Sopenharmony_civoid free_credit_return(struct hfi1_devdata *dd); 23862306a36Sopenharmony_ciint init_sc_pools_and_sizes(struct hfi1_devdata *dd); 23962306a36Sopenharmony_ciint init_send_contexts(struct hfi1_devdata *dd); 24062306a36Sopenharmony_ciint init_pervl_scs(struct hfi1_devdata *dd); 24162306a36Sopenharmony_cistruct send_context *sc_alloc(struct hfi1_devdata *dd, int type, 24262306a36Sopenharmony_ci uint hdrqentsize, int numa); 24362306a36Sopenharmony_civoid sc_free(struct send_context *sc); 24462306a36Sopenharmony_ciint sc_enable(struct send_context *sc); 24562306a36Sopenharmony_civoid sc_disable(struct send_context *sc); 24662306a36Sopenharmony_ciint sc_restart(struct send_context *sc); 24762306a36Sopenharmony_civoid sc_return_credits(struct send_context *sc); 24862306a36Sopenharmony_civoid sc_flush(struct send_context *sc); 24962306a36Sopenharmony_civoid sc_drop(struct send_context *sc); 25062306a36Sopenharmony_civoid sc_stop(struct send_context *sc, int bit); 25162306a36Sopenharmony_cistruct pio_buf *sc_buffer_alloc(struct send_context *sc, u32 dw_len, 25262306a36Sopenharmony_ci pio_release_cb cb, void *arg); 25362306a36Sopenharmony_civoid sc_release_update(struct send_context *sc); 25462306a36Sopenharmony_civoid sc_group_release_update(struct hfi1_devdata *dd, u32 hw_context); 25562306a36Sopenharmony_civoid sc_add_credit_return_intr(struct send_context *sc); 25662306a36Sopenharmony_civoid sc_del_credit_return_intr(struct send_context *sc); 25762306a36Sopenharmony_civoid sc_set_cr_threshold(struct send_context *sc, u32 new_threshold); 25862306a36Sopenharmony_ciu32 sc_percent_to_threshold(struct send_context *sc, u32 percent); 25962306a36Sopenharmony_ciu32 sc_mtu_to_threshold(struct send_context *sc, u32 mtu, u32 hdrqentsize); 26062306a36Sopenharmony_civoid hfi1_sc_wantpiobuf_intr(struct send_context *sc, u32 needint); 26162306a36Sopenharmony_civoid sc_wait(struct hfi1_devdata *dd); 26262306a36Sopenharmony_civoid set_pio_integrity(struct send_context *sc); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci/* support functions */ 26562306a36Sopenharmony_civoid pio_reset_all(struct hfi1_devdata *dd); 26662306a36Sopenharmony_civoid pio_freeze(struct hfi1_devdata *dd); 26762306a36Sopenharmony_civoid pio_kernel_unfreeze(struct hfi1_devdata *dd); 26862306a36Sopenharmony_civoid pio_kernel_linkup(struct hfi1_devdata *dd); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci/* global PIO send control operations */ 27162306a36Sopenharmony_ci#define PSC_GLOBAL_ENABLE 0 27262306a36Sopenharmony_ci#define PSC_GLOBAL_DISABLE 1 27362306a36Sopenharmony_ci#define PSC_GLOBAL_VLARB_ENABLE 2 27462306a36Sopenharmony_ci#define PSC_GLOBAL_VLARB_DISABLE 3 27562306a36Sopenharmony_ci#define PSC_CM_RESET 4 27662306a36Sopenharmony_ci#define PSC_DATA_VL_ENABLE 5 27762306a36Sopenharmony_ci#define PSC_DATA_VL_DISABLE 6 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_civoid __cm_reset(struct hfi1_devdata *dd, u64 sendctrl); 28062306a36Sopenharmony_civoid pio_send_control(struct hfi1_devdata *dd, int op); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci/* PIO copy routines */ 28362306a36Sopenharmony_civoid pio_copy(struct hfi1_devdata *dd, struct pio_buf *pbuf, u64 pbc, 28462306a36Sopenharmony_ci const void *from, size_t count); 28562306a36Sopenharmony_civoid seg_pio_copy_start(struct pio_buf *pbuf, u64 pbc, 28662306a36Sopenharmony_ci const void *from, size_t nbytes); 28762306a36Sopenharmony_civoid seg_pio_copy_mid(struct pio_buf *pbuf, const void *from, size_t nbytes); 28862306a36Sopenharmony_civoid seg_pio_copy_end(struct pio_buf *pbuf); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_civoid seqfile_dump_sci(struct seq_file *s, u32 i, 29162306a36Sopenharmony_ci struct send_context_info *sci); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci#endif /* _PIO_H */ 294