1f48ad614SDennis Dalessandro #ifndef _HFI1_SDMA_H 2f48ad614SDennis Dalessandro #define _HFI1_SDMA_H 3f48ad614SDennis Dalessandro /* 4f48ad614SDennis Dalessandro * Copyright(c) 2015, 2016 Intel Corporation. 5f48ad614SDennis Dalessandro * 6f48ad614SDennis Dalessandro * This file is provided under a dual BSD/GPLv2 license. When using or 7f48ad614SDennis Dalessandro * redistributing this file, you may do so under either license. 8f48ad614SDennis Dalessandro * 9f48ad614SDennis Dalessandro * GPL LICENSE SUMMARY 10f48ad614SDennis Dalessandro * 11f48ad614SDennis Dalessandro * This program is free software; you can redistribute it and/or modify 12f48ad614SDennis Dalessandro * it under the terms of version 2 of the GNU General Public License as 13f48ad614SDennis Dalessandro * published by the Free Software Foundation. 14f48ad614SDennis Dalessandro * 15f48ad614SDennis Dalessandro * This program is distributed in the hope that it will be useful, but 16f48ad614SDennis Dalessandro * WITHOUT ANY WARRANTY; without even the implied warranty of 17f48ad614SDennis Dalessandro * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18f48ad614SDennis Dalessandro * General Public License for more details. 19f48ad614SDennis Dalessandro * 20f48ad614SDennis Dalessandro * BSD LICENSE 21f48ad614SDennis Dalessandro * 22f48ad614SDennis Dalessandro * Redistribution and use in source and binary forms, with or without 23f48ad614SDennis Dalessandro * modification, are permitted provided that the following conditions 24f48ad614SDennis Dalessandro * are met: 25f48ad614SDennis Dalessandro * 26f48ad614SDennis Dalessandro * - Redistributions of source code must retain the above copyright 27f48ad614SDennis Dalessandro * notice, this list of conditions and the following disclaimer. 28f48ad614SDennis Dalessandro * - Redistributions in binary form must reproduce the above copyright 29f48ad614SDennis Dalessandro * notice, this list of conditions and the following disclaimer in 30f48ad614SDennis Dalessandro * the documentation and/or other materials provided with the 31f48ad614SDennis Dalessandro * distribution. 32f48ad614SDennis Dalessandro * - Neither the name of Intel Corporation nor the names of its 33f48ad614SDennis Dalessandro * contributors may be used to endorse or promote products derived 34f48ad614SDennis Dalessandro * from this software without specific prior written permission. 35f48ad614SDennis Dalessandro * 36f48ad614SDennis Dalessandro * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 37f48ad614SDennis Dalessandro * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 38f48ad614SDennis Dalessandro * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 39f48ad614SDennis Dalessandro * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 40f48ad614SDennis Dalessandro * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41f48ad614SDennis Dalessandro * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 42f48ad614SDennis Dalessandro * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 43f48ad614SDennis Dalessandro * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 44f48ad614SDennis Dalessandro * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 45f48ad614SDennis Dalessandro * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 46f48ad614SDennis Dalessandro * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 47f48ad614SDennis Dalessandro * 48f48ad614SDennis Dalessandro */ 49f48ad614SDennis Dalessandro 50f48ad614SDennis Dalessandro #include <linux/types.h> 51f48ad614SDennis Dalessandro #include <linux/list.h> 52f48ad614SDennis Dalessandro #include <asm/byteorder.h> 53f48ad614SDennis Dalessandro #include <linux/workqueue.h> 54f48ad614SDennis Dalessandro #include <linux/rculist.h> 55f48ad614SDennis Dalessandro 56f48ad614SDennis Dalessandro #include "hfi.h" 57f48ad614SDennis Dalessandro #include "verbs.h" 58f48ad614SDennis Dalessandro #include "sdma_txreq.h" 59f48ad614SDennis Dalessandro 60f48ad614SDennis Dalessandro /* Hardware limit */ 61f48ad614SDennis Dalessandro #define MAX_DESC 64 62f48ad614SDennis Dalessandro /* Hardware limit for SDMA packet size */ 63f48ad614SDennis Dalessandro #define MAX_SDMA_PKT_SIZE ((16 * 1024) - 1) 64f48ad614SDennis Dalessandro 65f48ad614SDennis Dalessandro #define SDMA_MAP_NONE 0 66f48ad614SDennis Dalessandro #define SDMA_MAP_SINGLE 1 67f48ad614SDennis Dalessandro #define SDMA_MAP_PAGE 2 68f48ad614SDennis Dalessandro 69f48ad614SDennis Dalessandro #define SDMA_AHG_VALUE_MASK 0xffff 70f48ad614SDennis Dalessandro #define SDMA_AHG_VALUE_SHIFT 0 71f48ad614SDennis Dalessandro #define SDMA_AHG_INDEX_MASK 0xf 72f48ad614SDennis Dalessandro #define SDMA_AHG_INDEX_SHIFT 16 73f48ad614SDennis Dalessandro #define SDMA_AHG_FIELD_LEN_MASK 0xf 74f48ad614SDennis Dalessandro #define SDMA_AHG_FIELD_LEN_SHIFT 20 75f48ad614SDennis Dalessandro #define SDMA_AHG_FIELD_START_MASK 0x1f 76f48ad614SDennis Dalessandro #define SDMA_AHG_FIELD_START_SHIFT 24 77f48ad614SDennis Dalessandro #define SDMA_AHG_UPDATE_ENABLE_MASK 0x1 78f48ad614SDennis Dalessandro #define SDMA_AHG_UPDATE_ENABLE_SHIFT 31 79f48ad614SDennis Dalessandro 80f48ad614SDennis Dalessandro /* AHG modes */ 81f48ad614SDennis Dalessandro 82f48ad614SDennis Dalessandro /* 83f48ad614SDennis Dalessandro * Be aware the ordering and values 84f48ad614SDennis Dalessandro * for SDMA_AHG_APPLY_UPDATE[123] 85f48ad614SDennis Dalessandro * are assumed in generating a skip 86f48ad614SDennis Dalessandro * count in submit_tx() in sdma.c 87f48ad614SDennis Dalessandro */ 88f48ad614SDennis Dalessandro #define SDMA_AHG_NO_AHG 0 89f48ad614SDennis Dalessandro #define SDMA_AHG_COPY 1 90f48ad614SDennis Dalessandro #define SDMA_AHG_APPLY_UPDATE1 2 91f48ad614SDennis Dalessandro #define SDMA_AHG_APPLY_UPDATE2 3 92f48ad614SDennis Dalessandro #define SDMA_AHG_APPLY_UPDATE3 4 93f48ad614SDennis Dalessandro 94f48ad614SDennis Dalessandro /* 95f48ad614SDennis Dalessandro * Bits defined in the send DMA descriptor. 96f48ad614SDennis Dalessandro */ 97f48ad614SDennis Dalessandro #define SDMA_DESC0_FIRST_DESC_FLAG BIT_ULL(63) 98f48ad614SDennis Dalessandro #define SDMA_DESC0_LAST_DESC_FLAG BIT_ULL(62) 99f48ad614SDennis Dalessandro #define SDMA_DESC0_BYTE_COUNT_SHIFT 48 100f48ad614SDennis Dalessandro #define SDMA_DESC0_BYTE_COUNT_WIDTH 14 101f48ad614SDennis Dalessandro #define SDMA_DESC0_BYTE_COUNT_MASK \ 102f48ad614SDennis Dalessandro ((1ULL << SDMA_DESC0_BYTE_COUNT_WIDTH) - 1) 103f48ad614SDennis Dalessandro #define SDMA_DESC0_BYTE_COUNT_SMASK \ 104f48ad614SDennis Dalessandro (SDMA_DESC0_BYTE_COUNT_MASK << SDMA_DESC0_BYTE_COUNT_SHIFT) 105f48ad614SDennis Dalessandro #define SDMA_DESC0_PHY_ADDR_SHIFT 0 106f48ad614SDennis Dalessandro #define SDMA_DESC0_PHY_ADDR_WIDTH 48 107f48ad614SDennis Dalessandro #define SDMA_DESC0_PHY_ADDR_MASK \ 108f48ad614SDennis Dalessandro ((1ULL << SDMA_DESC0_PHY_ADDR_WIDTH) - 1) 109f48ad614SDennis Dalessandro #define SDMA_DESC0_PHY_ADDR_SMASK \ 110f48ad614SDennis Dalessandro (SDMA_DESC0_PHY_ADDR_MASK << SDMA_DESC0_PHY_ADDR_SHIFT) 111f48ad614SDennis Dalessandro 112f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_UPDATE1_SHIFT 32 113f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_UPDATE1_WIDTH 32 114f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_UPDATE1_MASK \ 115f48ad614SDennis Dalessandro ((1ULL << SDMA_DESC1_HEADER_UPDATE1_WIDTH) - 1) 116f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_UPDATE1_SMASK \ 117f48ad614SDennis Dalessandro (SDMA_DESC1_HEADER_UPDATE1_MASK << SDMA_DESC1_HEADER_UPDATE1_SHIFT) 118f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_MODE_SHIFT 13 119f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_MODE_WIDTH 3 120f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_MODE_MASK \ 121f48ad614SDennis Dalessandro ((1ULL << SDMA_DESC1_HEADER_MODE_WIDTH) - 1) 122f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_MODE_SMASK \ 123f48ad614SDennis Dalessandro (SDMA_DESC1_HEADER_MODE_MASK << SDMA_DESC1_HEADER_MODE_SHIFT) 124f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_INDEX_SHIFT 8 125f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_INDEX_WIDTH 5 126f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_INDEX_MASK \ 127f48ad614SDennis Dalessandro ((1ULL << SDMA_DESC1_HEADER_INDEX_WIDTH) - 1) 128f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_INDEX_SMASK \ 129f48ad614SDennis Dalessandro (SDMA_DESC1_HEADER_INDEX_MASK << SDMA_DESC1_HEADER_INDEX_SHIFT) 130f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_DWS_SHIFT 4 131f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_DWS_WIDTH 4 132f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_DWS_MASK \ 133f48ad614SDennis Dalessandro ((1ULL << SDMA_DESC1_HEADER_DWS_WIDTH) - 1) 134f48ad614SDennis Dalessandro #define SDMA_DESC1_HEADER_DWS_SMASK \ 135f48ad614SDennis Dalessandro (SDMA_DESC1_HEADER_DWS_MASK << SDMA_DESC1_HEADER_DWS_SHIFT) 136f48ad614SDennis Dalessandro #define SDMA_DESC1_GENERATION_SHIFT 2 137f48ad614SDennis Dalessandro #define SDMA_DESC1_GENERATION_WIDTH 2 138f48ad614SDennis Dalessandro #define SDMA_DESC1_GENERATION_MASK \ 139f48ad614SDennis Dalessandro ((1ULL << SDMA_DESC1_GENERATION_WIDTH) - 1) 140f48ad614SDennis Dalessandro #define SDMA_DESC1_GENERATION_SMASK \ 141f48ad614SDennis Dalessandro (SDMA_DESC1_GENERATION_MASK << SDMA_DESC1_GENERATION_SHIFT) 142f48ad614SDennis Dalessandro #define SDMA_DESC1_INT_REQ_FLAG BIT_ULL(1) 143f48ad614SDennis Dalessandro #define SDMA_DESC1_HEAD_TO_HOST_FLAG BIT_ULL(0) 144f48ad614SDennis Dalessandro 145f48ad614SDennis Dalessandro enum sdma_states { 146f48ad614SDennis Dalessandro sdma_state_s00_hw_down, 147f48ad614SDennis Dalessandro sdma_state_s10_hw_start_up_halt_wait, 148f48ad614SDennis Dalessandro sdma_state_s15_hw_start_up_clean_wait, 149f48ad614SDennis Dalessandro sdma_state_s20_idle, 150f48ad614SDennis Dalessandro sdma_state_s30_sw_clean_up_wait, 151f48ad614SDennis Dalessandro sdma_state_s40_hw_clean_up_wait, 152f48ad614SDennis Dalessandro sdma_state_s50_hw_halt_wait, 153f48ad614SDennis Dalessandro sdma_state_s60_idle_halt_wait, 154f48ad614SDennis Dalessandro sdma_state_s80_hw_freeze, 155f48ad614SDennis Dalessandro sdma_state_s82_freeze_sw_clean, 156f48ad614SDennis Dalessandro sdma_state_s99_running, 157f48ad614SDennis Dalessandro }; 158f48ad614SDennis Dalessandro 159f48ad614SDennis Dalessandro enum sdma_events { 160f48ad614SDennis Dalessandro sdma_event_e00_go_hw_down, 161f48ad614SDennis Dalessandro sdma_event_e10_go_hw_start, 162f48ad614SDennis Dalessandro sdma_event_e15_hw_halt_done, 163f48ad614SDennis Dalessandro sdma_event_e25_hw_clean_up_done, 164f48ad614SDennis Dalessandro sdma_event_e30_go_running, 165f48ad614SDennis Dalessandro sdma_event_e40_sw_cleaned, 166f48ad614SDennis Dalessandro sdma_event_e50_hw_cleaned, 167f48ad614SDennis Dalessandro sdma_event_e60_hw_halted, 168f48ad614SDennis Dalessandro sdma_event_e70_go_idle, 169f48ad614SDennis Dalessandro sdma_event_e80_hw_freeze, 170f48ad614SDennis Dalessandro sdma_event_e81_hw_frozen, 171f48ad614SDennis Dalessandro sdma_event_e82_hw_unfreeze, 172f48ad614SDennis Dalessandro sdma_event_e85_link_down, 173f48ad614SDennis Dalessandro sdma_event_e90_sw_halted, 174f48ad614SDennis Dalessandro }; 175f48ad614SDennis Dalessandro 176f48ad614SDennis Dalessandro struct sdma_set_state_action { 177f48ad614SDennis Dalessandro unsigned op_enable:1; 178f48ad614SDennis Dalessandro unsigned op_intenable:1; 179f48ad614SDennis Dalessandro unsigned op_halt:1; 180f48ad614SDennis Dalessandro unsigned op_cleanup:1; 181f48ad614SDennis Dalessandro unsigned go_s99_running_tofalse:1; 182f48ad614SDennis Dalessandro unsigned go_s99_running_totrue:1; 183f48ad614SDennis Dalessandro }; 184f48ad614SDennis Dalessandro 185f48ad614SDennis Dalessandro struct sdma_state { 186f48ad614SDennis Dalessandro struct kref kref; 187f48ad614SDennis Dalessandro struct completion comp; 188f48ad614SDennis Dalessandro enum sdma_states current_state; 189f48ad614SDennis Dalessandro unsigned current_op; 190f48ad614SDennis Dalessandro unsigned go_s99_running; 191f48ad614SDennis Dalessandro /* debugging/development */ 192f48ad614SDennis Dalessandro enum sdma_states previous_state; 193f48ad614SDennis Dalessandro unsigned previous_op; 194f48ad614SDennis Dalessandro enum sdma_events last_event; 195f48ad614SDennis Dalessandro }; 196f48ad614SDennis Dalessandro 197f48ad614SDennis Dalessandro /** 198f48ad614SDennis Dalessandro * DOC: sdma exported routines 199f48ad614SDennis Dalessandro * 200f48ad614SDennis Dalessandro * These sdma routines fit into three categories: 201f48ad614SDennis Dalessandro * - The SDMA API for building and submitting packets 202f48ad614SDennis Dalessandro * to the ring 203f48ad614SDennis Dalessandro * 204f48ad614SDennis Dalessandro * - Initialization and tear down routines to buildup 205f48ad614SDennis Dalessandro * and tear down SDMA 206f48ad614SDennis Dalessandro * 207f48ad614SDennis Dalessandro * - ISR entrances to handle interrupts, state changes 208f48ad614SDennis Dalessandro * and errors 209f48ad614SDennis Dalessandro */ 210f48ad614SDennis Dalessandro 211f48ad614SDennis Dalessandro /** 212f48ad614SDennis Dalessandro * DOC: sdma PSM/verbs API 213f48ad614SDennis Dalessandro * 214f48ad614SDennis Dalessandro * The sdma API is designed to be used by both PSM 215f48ad614SDennis Dalessandro * and verbs to supply packets to the SDMA ring. 216f48ad614SDennis Dalessandro * 217f48ad614SDennis Dalessandro * The usage of the API is as follows: 218f48ad614SDennis Dalessandro * 219f48ad614SDennis Dalessandro * Embed a struct iowait in the QP or 220f48ad614SDennis Dalessandro * PQ. The iowait should be initialized with a 221f48ad614SDennis Dalessandro * call to iowait_init(). 222f48ad614SDennis Dalessandro * 223f48ad614SDennis Dalessandro * The user of the API should create an allocation method 224f48ad614SDennis Dalessandro * for their version of the txreq. slabs, pre-allocated lists, 225f48ad614SDennis Dalessandro * and dma pools can be used. Once the user's overload of 226f48ad614SDennis Dalessandro * the sdma_txreq has been allocated, the sdma_txreq member 227f48ad614SDennis Dalessandro * must be initialized with sdma_txinit() or sdma_txinit_ahg(). 228f48ad614SDennis Dalessandro * 229f48ad614SDennis Dalessandro * The txreq must be declared with the sdma_txreq first. 230f48ad614SDennis Dalessandro * 231f48ad614SDennis Dalessandro * The tx request, once initialized, is manipulated with calls to 232f48ad614SDennis Dalessandro * sdma_txadd_daddr(), sdma_txadd_page(), or sdma_txadd_kvaddr() 233f48ad614SDennis Dalessandro * for each disjoint memory location. It is the user's responsibility 234f48ad614SDennis Dalessandro * to understand the packet boundaries and page boundaries to do the 235f48ad614SDennis Dalessandro * appropriate number of sdma_txadd_* calls.. The user 236f48ad614SDennis Dalessandro * must be prepared to deal with failures from these routines due to 237f48ad614SDennis Dalessandro * either memory allocation or dma_mapping failures. 238f48ad614SDennis Dalessandro * 239f48ad614SDennis Dalessandro * The mapping specifics for each memory location are recorded 240f48ad614SDennis Dalessandro * in the tx. Memory locations added with sdma_txadd_page() 241f48ad614SDennis Dalessandro * and sdma_txadd_kvaddr() are automatically mapped when added 242f48ad614SDennis Dalessandro * to the tx and nmapped as part of the progress processing in the 243f48ad614SDennis Dalessandro * SDMA interrupt handling. 244f48ad614SDennis Dalessandro * 245f48ad614SDennis Dalessandro * sdma_txadd_daddr() is used to add an dma_addr_t memory to the 246f48ad614SDennis Dalessandro * tx. An example of a use case would be a pre-allocated 247f48ad614SDennis Dalessandro * set of headers allocated via dma_pool_alloc() or 248f48ad614SDennis Dalessandro * dma_alloc_coherent(). For these memory locations, it 249f48ad614SDennis Dalessandro * is the responsibility of the user to handle that unmapping. 250f48ad614SDennis Dalessandro * (This would usually be at an unload or job termination.) 251f48ad614SDennis Dalessandro * 252f48ad614SDennis Dalessandro * The routine sdma_send_txreq() is used to submit 253f48ad614SDennis Dalessandro * a tx to the ring after the appropriate number of 254f48ad614SDennis Dalessandro * sdma_txadd_* have been done. 255f48ad614SDennis Dalessandro * 256f48ad614SDennis Dalessandro * If it is desired to send a burst of sdma_txreqs, sdma_send_txlist() 257f48ad614SDennis Dalessandro * can be used to submit a list of packets. 258f48ad614SDennis Dalessandro * 259f48ad614SDennis Dalessandro * The user is free to use the link overhead in the struct sdma_txreq as 260f48ad614SDennis Dalessandro * long as the tx isn't in flight. 261f48ad614SDennis Dalessandro * 262f48ad614SDennis Dalessandro * The extreme degenerate case of the number of descriptors 263f48ad614SDennis Dalessandro * exceeding the ring size is automatically handled as 264f48ad614SDennis Dalessandro * memory locations are added. An overflow of the descriptor 265f48ad614SDennis Dalessandro * array that is part of the sdma_txreq is also automatically 266f48ad614SDennis Dalessandro * handled. 267f48ad614SDennis Dalessandro * 268f48ad614SDennis Dalessandro */ 269f48ad614SDennis Dalessandro 270f48ad614SDennis Dalessandro /** 271f48ad614SDennis Dalessandro * DOC: Infrastructure calls 272f48ad614SDennis Dalessandro * 273f48ad614SDennis Dalessandro * sdma_init() is used to initialize data structures and 274f48ad614SDennis Dalessandro * CSRs for the desired number of SDMA engines. 275f48ad614SDennis Dalessandro * 276f48ad614SDennis Dalessandro * sdma_start() is used to kick the SDMA engines initialized 277f48ad614SDennis Dalessandro * with sdma_init(). Interrupts must be enabled at this 278f48ad614SDennis Dalessandro * point since aspects of the state machine are interrupt 279f48ad614SDennis Dalessandro * driven. 280f48ad614SDennis Dalessandro * 281f48ad614SDennis Dalessandro * sdma_engine_error() and sdma_engine_interrupt() are 282f48ad614SDennis Dalessandro * entrances for interrupts. 283f48ad614SDennis Dalessandro * 284f48ad614SDennis Dalessandro * sdma_map_init() is for the management of the mapping 285f48ad614SDennis Dalessandro * table when the number of vls is changed. 286f48ad614SDennis Dalessandro * 287f48ad614SDennis Dalessandro */ 288f48ad614SDennis Dalessandro 289f48ad614SDennis Dalessandro /* 290f48ad614SDennis Dalessandro * struct hw_sdma_desc - raw 128 bit SDMA descriptor 291f48ad614SDennis Dalessandro * 292f48ad614SDennis Dalessandro * This is the raw descriptor in the SDMA ring 293f48ad614SDennis Dalessandro */ 294f48ad614SDennis Dalessandro struct hw_sdma_desc { 295f48ad614SDennis Dalessandro /* private: don't use directly */ 296f48ad614SDennis Dalessandro __le64 qw[2]; 297f48ad614SDennis Dalessandro }; 298f48ad614SDennis Dalessandro 299f48ad614SDennis Dalessandro /** 300f48ad614SDennis Dalessandro * struct sdma_engine - Data pertaining to each SDMA engine. 301f48ad614SDennis Dalessandro * @dd: a back-pointer to the device data 302f48ad614SDennis Dalessandro * @ppd: per port back-pointer 303f48ad614SDennis Dalessandro * @imask: mask for irq manipulation 304f48ad614SDennis Dalessandro * @idle_mask: mask for determining if an interrupt is due to sdma_idle 305f48ad614SDennis Dalessandro * 306f48ad614SDennis Dalessandro * This structure has the state for each sdma_engine. 307f48ad614SDennis Dalessandro * 308f48ad614SDennis Dalessandro * Accessing to non public fields are not supported 309f48ad614SDennis Dalessandro * since the private members are subject to change. 310f48ad614SDennis Dalessandro */ 311f48ad614SDennis Dalessandro struct sdma_engine { 312f48ad614SDennis Dalessandro /* read mostly */ 313f48ad614SDennis Dalessandro struct hfi1_devdata *dd; 314f48ad614SDennis Dalessandro struct hfi1_pportdata *ppd; 315f48ad614SDennis Dalessandro /* private: */ 316f48ad614SDennis Dalessandro void __iomem *tail_csr; 317f48ad614SDennis Dalessandro u64 imask; /* clear interrupt mask */ 318f48ad614SDennis Dalessandro u64 idle_mask; 319f48ad614SDennis Dalessandro u64 progress_mask; 320f48ad614SDennis Dalessandro u64 int_mask; 321f48ad614SDennis Dalessandro /* private: */ 322f48ad614SDennis Dalessandro volatile __le64 *head_dma; /* DMA'ed by chip */ 323f48ad614SDennis Dalessandro /* private: */ 324f48ad614SDennis Dalessandro dma_addr_t head_phys; 325f48ad614SDennis Dalessandro /* private: */ 326f48ad614SDennis Dalessandro struct hw_sdma_desc *descq; 327f48ad614SDennis Dalessandro /* private: */ 328f48ad614SDennis Dalessandro unsigned descq_full_count; 329f48ad614SDennis Dalessandro struct sdma_txreq **tx_ring; 330f48ad614SDennis Dalessandro /* private: */ 331f48ad614SDennis Dalessandro dma_addr_t descq_phys; 332f48ad614SDennis Dalessandro /* private */ 333f48ad614SDennis Dalessandro u32 sdma_mask; 334f48ad614SDennis Dalessandro /* private */ 335f48ad614SDennis Dalessandro struct sdma_state state; 336f48ad614SDennis Dalessandro /* private */ 337f48ad614SDennis Dalessandro int cpu; 338f48ad614SDennis Dalessandro /* private: */ 339f48ad614SDennis Dalessandro u8 sdma_shift; 340f48ad614SDennis Dalessandro /* private: */ 341f48ad614SDennis Dalessandro u8 this_idx; /* zero relative engine */ 342f48ad614SDennis Dalessandro /* protect changes to senddmactrl shadow */ 343f48ad614SDennis Dalessandro spinlock_t senddmactrl_lock; 344f48ad614SDennis Dalessandro /* private: */ 345f48ad614SDennis Dalessandro u64 p_senddmactrl; /* shadow per-engine SendDmaCtrl */ 346f48ad614SDennis Dalessandro 347f48ad614SDennis Dalessandro /* read/write using tail_lock */ 348f48ad614SDennis Dalessandro spinlock_t tail_lock ____cacheline_aligned_in_smp; 349f48ad614SDennis Dalessandro #ifdef CONFIG_HFI1_DEBUG_SDMA_ORDER 350f48ad614SDennis Dalessandro /* private: */ 351f48ad614SDennis Dalessandro u64 tail_sn; 352f48ad614SDennis Dalessandro #endif 353f48ad614SDennis Dalessandro /* private: */ 354f48ad614SDennis Dalessandro u32 descq_tail; 355f48ad614SDennis Dalessandro /* private: */ 356f48ad614SDennis Dalessandro unsigned long ahg_bits; 357f48ad614SDennis Dalessandro /* private: */ 358f48ad614SDennis Dalessandro u16 desc_avail; 359f48ad614SDennis Dalessandro /* private: */ 360f48ad614SDennis Dalessandro u16 tx_tail; 361f48ad614SDennis Dalessandro /* private: */ 362f48ad614SDennis Dalessandro u16 descq_cnt; 363f48ad614SDennis Dalessandro 364f48ad614SDennis Dalessandro /* read/write using head_lock */ 365f48ad614SDennis Dalessandro /* private: */ 366f48ad614SDennis Dalessandro seqlock_t head_lock ____cacheline_aligned_in_smp; 367f48ad614SDennis Dalessandro #ifdef CONFIG_HFI1_DEBUG_SDMA_ORDER 368f48ad614SDennis Dalessandro /* private: */ 369f48ad614SDennis Dalessandro u64 head_sn; 370f48ad614SDennis Dalessandro #endif 371f48ad614SDennis Dalessandro /* private: */ 372f48ad614SDennis Dalessandro u32 descq_head; 373f48ad614SDennis Dalessandro /* private: */ 374f48ad614SDennis Dalessandro u16 tx_head; 375f48ad614SDennis Dalessandro /* private: */ 376f48ad614SDennis Dalessandro u64 last_status; 377f48ad614SDennis Dalessandro /* private */ 378f48ad614SDennis Dalessandro u64 err_cnt; 379f48ad614SDennis Dalessandro /* private */ 380f48ad614SDennis Dalessandro u64 sdma_int_cnt; 381f48ad614SDennis Dalessandro u64 idle_int_cnt; 382f48ad614SDennis Dalessandro u64 progress_int_cnt; 383f48ad614SDennis Dalessandro 384f48ad614SDennis Dalessandro /* private: */ 385f48ad614SDennis Dalessandro struct list_head dmawait; 386f48ad614SDennis Dalessandro 387f48ad614SDennis Dalessandro /* CONFIG SDMA for now, just blindly duplicate */ 388f48ad614SDennis Dalessandro /* private: */ 389f48ad614SDennis Dalessandro struct tasklet_struct sdma_hw_clean_up_task 390f48ad614SDennis Dalessandro ____cacheline_aligned_in_smp; 391f48ad614SDennis Dalessandro 392f48ad614SDennis Dalessandro /* private: */ 393f48ad614SDennis Dalessandro struct tasklet_struct sdma_sw_clean_up_task 394f48ad614SDennis Dalessandro ____cacheline_aligned_in_smp; 395f48ad614SDennis Dalessandro /* private: */ 396f48ad614SDennis Dalessandro struct work_struct err_halt_worker; 397f48ad614SDennis Dalessandro /* private */ 398f48ad614SDennis Dalessandro struct timer_list err_progress_check_timer; 399f48ad614SDennis Dalessandro u32 progress_check_head; 400f48ad614SDennis Dalessandro /* private: */ 401f48ad614SDennis Dalessandro struct work_struct flush_worker; 402f48ad614SDennis Dalessandro /* protect flush list */ 403f48ad614SDennis Dalessandro spinlock_t flushlist_lock; 404f48ad614SDennis Dalessandro /* private: */ 405f48ad614SDennis Dalessandro struct list_head flushlist; 4060cb2aa69STadeusz Struk struct cpumask cpu_mask; 4070cb2aa69STadeusz Struk struct kobject kobj; 408*6eb4eb10SMichael J. Ruhl u32 msix_intr; 409f48ad614SDennis Dalessandro }; 410f48ad614SDennis Dalessandro 411f48ad614SDennis Dalessandro int sdma_init(struct hfi1_devdata *dd, u8 port); 412f48ad614SDennis Dalessandro void sdma_start(struct hfi1_devdata *dd); 413f48ad614SDennis Dalessandro void sdma_exit(struct hfi1_devdata *dd); 414473291b3SAlex Estrin void sdma_clean(struct hfi1_devdata *dd, size_t num_engines); 415f48ad614SDennis Dalessandro void sdma_all_running(struct hfi1_devdata *dd); 416f48ad614SDennis Dalessandro void sdma_all_idle(struct hfi1_devdata *dd); 417f48ad614SDennis Dalessandro void sdma_freeze_notify(struct hfi1_devdata *dd, int go_idle); 418f48ad614SDennis Dalessandro void sdma_freeze(struct hfi1_devdata *dd); 419f48ad614SDennis Dalessandro void sdma_unfreeze(struct hfi1_devdata *dd); 420f48ad614SDennis Dalessandro void sdma_wait(struct hfi1_devdata *dd); 421f48ad614SDennis Dalessandro 422f48ad614SDennis Dalessandro /** 423f48ad614SDennis Dalessandro * sdma_empty() - idle engine test 424f48ad614SDennis Dalessandro * @engine: sdma engine 425f48ad614SDennis Dalessandro * 426f48ad614SDennis Dalessandro * Currently used by verbs as a latency optimization. 427f48ad614SDennis Dalessandro * 428f48ad614SDennis Dalessandro * Return: 429f48ad614SDennis Dalessandro * 1 - empty, 0 - non-empty 430f48ad614SDennis Dalessandro */ 431f48ad614SDennis Dalessandro static inline int sdma_empty(struct sdma_engine *sde) 432f48ad614SDennis Dalessandro { 433f48ad614SDennis Dalessandro return sde->descq_tail == sde->descq_head; 434f48ad614SDennis Dalessandro } 435f48ad614SDennis Dalessandro 436f48ad614SDennis Dalessandro static inline u16 sdma_descq_freecnt(struct sdma_engine *sde) 437f48ad614SDennis Dalessandro { 438f48ad614SDennis Dalessandro return sde->descq_cnt - 439f48ad614SDennis Dalessandro (sde->descq_tail - 4406aa7de05SMark Rutland READ_ONCE(sde->descq_head)) - 1; 441f48ad614SDennis Dalessandro } 442f48ad614SDennis Dalessandro 443f48ad614SDennis Dalessandro static inline u16 sdma_descq_inprocess(struct sdma_engine *sde) 444f48ad614SDennis Dalessandro { 445f48ad614SDennis Dalessandro return sde->descq_cnt - sdma_descq_freecnt(sde); 446f48ad614SDennis Dalessandro } 447f48ad614SDennis Dalessandro 448f48ad614SDennis Dalessandro /* 449f48ad614SDennis Dalessandro * Either head_lock or tail lock required to see 450f48ad614SDennis Dalessandro * a steady state. 451f48ad614SDennis Dalessandro */ 452f48ad614SDennis Dalessandro static inline int __sdma_running(struct sdma_engine *engine) 453f48ad614SDennis Dalessandro { 454f48ad614SDennis Dalessandro return engine->state.current_state == sdma_state_s99_running; 455f48ad614SDennis Dalessandro } 456f48ad614SDennis Dalessandro 457f48ad614SDennis Dalessandro /** 458f48ad614SDennis Dalessandro * sdma_running() - state suitability test 459f48ad614SDennis Dalessandro * @engine: sdma engine 460f48ad614SDennis Dalessandro * 461f48ad614SDennis Dalessandro * sdma_running probes the internal state to determine if it is suitable 462f48ad614SDennis Dalessandro * for submitting packets. 463f48ad614SDennis Dalessandro * 464f48ad614SDennis Dalessandro * Return: 465f48ad614SDennis Dalessandro * 1 - ok to submit, 0 - not ok to submit 466f48ad614SDennis Dalessandro * 467f48ad614SDennis Dalessandro */ 468f48ad614SDennis Dalessandro static inline int sdma_running(struct sdma_engine *engine) 469f48ad614SDennis Dalessandro { 470f48ad614SDennis Dalessandro unsigned long flags; 471f48ad614SDennis Dalessandro int ret; 472f48ad614SDennis Dalessandro 473f48ad614SDennis Dalessandro spin_lock_irqsave(&engine->tail_lock, flags); 474f48ad614SDennis Dalessandro ret = __sdma_running(engine); 475f48ad614SDennis Dalessandro spin_unlock_irqrestore(&engine->tail_lock, flags); 476f48ad614SDennis Dalessandro return ret; 477f48ad614SDennis Dalessandro } 478f48ad614SDennis Dalessandro 479f48ad614SDennis Dalessandro void _sdma_txreq_ahgadd( 480f48ad614SDennis Dalessandro struct sdma_txreq *tx, 481f48ad614SDennis Dalessandro u8 num_ahg, 482f48ad614SDennis Dalessandro u8 ahg_entry, 483f48ad614SDennis Dalessandro u32 *ahg, 484f48ad614SDennis Dalessandro u8 ahg_hlen); 485f48ad614SDennis Dalessandro 486f48ad614SDennis Dalessandro /** 487f48ad614SDennis Dalessandro * sdma_txinit_ahg() - initialize an sdma_txreq struct with AHG 488f48ad614SDennis Dalessandro * @tx: tx request to initialize 489f48ad614SDennis Dalessandro * @flags: flags to key last descriptor additions 490f48ad614SDennis Dalessandro * @tlen: total packet length (pbc + headers + data) 491f48ad614SDennis Dalessandro * @ahg_entry: ahg entry to use (0 - 31) 492f48ad614SDennis Dalessandro * @num_ahg: ahg descriptor for first descriptor (0 - 9) 493f48ad614SDennis Dalessandro * @ahg: array of AHG descriptors (up to 9 entries) 494f48ad614SDennis Dalessandro * @ahg_hlen: number of bytes from ASIC entry to use 495f48ad614SDennis Dalessandro * @cb: callback 496f48ad614SDennis Dalessandro * 497f48ad614SDennis Dalessandro * The allocation of the sdma_txreq and it enclosing structure is user 498f48ad614SDennis Dalessandro * dependent. This routine must be called to initialize the user independent 499f48ad614SDennis Dalessandro * fields. 500f48ad614SDennis Dalessandro * 501f48ad614SDennis Dalessandro * The currently supported flags are SDMA_TXREQ_F_URGENT, 502f48ad614SDennis Dalessandro * SDMA_TXREQ_F_AHG_COPY, and SDMA_TXREQ_F_USE_AHG. 503f48ad614SDennis Dalessandro * 504f48ad614SDennis Dalessandro * SDMA_TXREQ_F_URGENT is used for latency sensitive situations where the 505f48ad614SDennis Dalessandro * completion is desired as soon as possible. 506f48ad614SDennis Dalessandro * 507f48ad614SDennis Dalessandro * SDMA_TXREQ_F_AHG_COPY causes the header in the first descriptor to be 508f48ad614SDennis Dalessandro * copied to chip entry. SDMA_TXREQ_F_USE_AHG causes the code to add in 509f48ad614SDennis Dalessandro * the AHG descriptors into the first 1 to 3 descriptors. 510f48ad614SDennis Dalessandro * 511f48ad614SDennis Dalessandro * Completions of submitted requests can be gotten on selected 512f48ad614SDennis Dalessandro * txreqs by giving a completion routine callback to sdma_txinit() or 513f48ad614SDennis Dalessandro * sdma_txinit_ahg(). The environment in which the callback runs 514f48ad614SDennis Dalessandro * can be from an ISR, a tasklet, or a thread, so no sleeping 515f48ad614SDennis Dalessandro * kernel routines can be used. Aspects of the sdma ring may 516f48ad614SDennis Dalessandro * be locked so care should be taken with locking. 517f48ad614SDennis Dalessandro * 518f48ad614SDennis Dalessandro * The callback pointer can be NULL to avoid any callback for the packet 519f48ad614SDennis Dalessandro * being submitted. The callback will be provided this tx, a status, and a flag. 520f48ad614SDennis Dalessandro * 521f48ad614SDennis Dalessandro * The status will be one of SDMA_TXREQ_S_OK, SDMA_TXREQ_S_SENDERROR, 522f48ad614SDennis Dalessandro * SDMA_TXREQ_S_ABORTED, or SDMA_TXREQ_S_SHUTDOWN. 523f48ad614SDennis Dalessandro * 524f48ad614SDennis Dalessandro * The flag, if the is the iowait had been used, indicates the iowait 525f48ad614SDennis Dalessandro * sdma_busy count has reached zero. 526f48ad614SDennis Dalessandro * 527f48ad614SDennis Dalessandro * user data portion of tlen should be precise. The sdma_txadd_* entrances 528f48ad614SDennis Dalessandro * will pad with a descriptor references 1 - 3 bytes when the number of bytes 529f48ad614SDennis Dalessandro * specified in tlen have been supplied to the sdma_txreq. 530f48ad614SDennis Dalessandro * 531f48ad614SDennis Dalessandro * ahg_hlen is used to determine the number of on-chip entry bytes to 532f48ad614SDennis Dalessandro * use as the header. This is for cases where the stored header is 533f48ad614SDennis Dalessandro * larger than the header to be used in a packet. This is typical 534f48ad614SDennis Dalessandro * for verbs where an RDMA_WRITE_FIRST is larger than the packet in 535f48ad614SDennis Dalessandro * and RDMA_WRITE_MIDDLE. 536f48ad614SDennis Dalessandro * 537f48ad614SDennis Dalessandro */ 538f48ad614SDennis Dalessandro static inline int sdma_txinit_ahg( 539f48ad614SDennis Dalessandro struct sdma_txreq *tx, 540f48ad614SDennis Dalessandro u16 flags, 541f48ad614SDennis Dalessandro u16 tlen, 542f48ad614SDennis Dalessandro u8 ahg_entry, 543f48ad614SDennis Dalessandro u8 num_ahg, 544f48ad614SDennis Dalessandro u32 *ahg, 545f48ad614SDennis Dalessandro u8 ahg_hlen, 546f48ad614SDennis Dalessandro void (*cb)(struct sdma_txreq *, int)) 547f48ad614SDennis Dalessandro { 548f48ad614SDennis Dalessandro if (tlen == 0) 549f48ad614SDennis Dalessandro return -ENODATA; 550f48ad614SDennis Dalessandro if (tlen > MAX_SDMA_PKT_SIZE) 551f48ad614SDennis Dalessandro return -EMSGSIZE; 552f48ad614SDennis Dalessandro tx->desc_limit = ARRAY_SIZE(tx->descs); 553f48ad614SDennis Dalessandro tx->descp = &tx->descs[0]; 554f48ad614SDennis Dalessandro INIT_LIST_HEAD(&tx->list); 555f48ad614SDennis Dalessandro tx->num_desc = 0; 556f48ad614SDennis Dalessandro tx->flags = flags; 557f48ad614SDennis Dalessandro tx->complete = cb; 558f48ad614SDennis Dalessandro tx->coalesce_buf = NULL; 559f48ad614SDennis Dalessandro tx->wait = NULL; 560f48ad614SDennis Dalessandro tx->packet_len = tlen; 561f48ad614SDennis Dalessandro tx->tlen = tx->packet_len; 562f48ad614SDennis Dalessandro tx->descs[0].qw[0] = SDMA_DESC0_FIRST_DESC_FLAG; 563f48ad614SDennis Dalessandro tx->descs[0].qw[1] = 0; 564f48ad614SDennis Dalessandro if (flags & SDMA_TXREQ_F_AHG_COPY) 565f48ad614SDennis Dalessandro tx->descs[0].qw[1] |= 566f48ad614SDennis Dalessandro (((u64)ahg_entry & SDMA_DESC1_HEADER_INDEX_MASK) 567f48ad614SDennis Dalessandro << SDMA_DESC1_HEADER_INDEX_SHIFT) | 568f48ad614SDennis Dalessandro (((u64)SDMA_AHG_COPY & SDMA_DESC1_HEADER_MODE_MASK) 569f48ad614SDennis Dalessandro << SDMA_DESC1_HEADER_MODE_SHIFT); 570f48ad614SDennis Dalessandro else if (flags & SDMA_TXREQ_F_USE_AHG && num_ahg) 571f48ad614SDennis Dalessandro _sdma_txreq_ahgadd(tx, num_ahg, ahg_entry, ahg, ahg_hlen); 572f48ad614SDennis Dalessandro return 0; 573f48ad614SDennis Dalessandro } 574f48ad614SDennis Dalessandro 575f48ad614SDennis Dalessandro /** 576f48ad614SDennis Dalessandro * sdma_txinit() - initialize an sdma_txreq struct (no AHG) 577f48ad614SDennis Dalessandro * @tx: tx request to initialize 578f48ad614SDennis Dalessandro * @flags: flags to key last descriptor additions 579f48ad614SDennis Dalessandro * @tlen: total packet length (pbc + headers + data) 580f48ad614SDennis Dalessandro * @cb: callback pointer 581f48ad614SDennis Dalessandro * 582f48ad614SDennis Dalessandro * The allocation of the sdma_txreq and it enclosing structure is user 583f48ad614SDennis Dalessandro * dependent. This routine must be called to initialize the user 584f48ad614SDennis Dalessandro * independent fields. 585f48ad614SDennis Dalessandro * 586f48ad614SDennis Dalessandro * The currently supported flags is SDMA_TXREQ_F_URGENT. 587f48ad614SDennis Dalessandro * 588f48ad614SDennis Dalessandro * SDMA_TXREQ_F_URGENT is used for latency sensitive situations where the 589f48ad614SDennis Dalessandro * completion is desired as soon as possible. 590f48ad614SDennis Dalessandro * 591f48ad614SDennis Dalessandro * Completions of submitted requests can be gotten on selected 592f48ad614SDennis Dalessandro * txreqs by giving a completion routine callback to sdma_txinit() or 593f48ad614SDennis Dalessandro * sdma_txinit_ahg(). The environment in which the callback runs 594f48ad614SDennis Dalessandro * can be from an ISR, a tasklet, or a thread, so no sleeping 595f48ad614SDennis Dalessandro * kernel routines can be used. The head size of the sdma ring may 596f48ad614SDennis Dalessandro * be locked so care should be taken with locking. 597f48ad614SDennis Dalessandro * 598f48ad614SDennis Dalessandro * The callback pointer can be NULL to avoid any callback for the packet 599f48ad614SDennis Dalessandro * being submitted. 600f48ad614SDennis Dalessandro * 601f48ad614SDennis Dalessandro * The callback, if non-NULL, will be provided this tx and a status. The 602f48ad614SDennis Dalessandro * status will be one of SDMA_TXREQ_S_OK, SDMA_TXREQ_S_SENDERROR, 603f48ad614SDennis Dalessandro * SDMA_TXREQ_S_ABORTED, or SDMA_TXREQ_S_SHUTDOWN. 604f48ad614SDennis Dalessandro * 605f48ad614SDennis Dalessandro */ 606f48ad614SDennis Dalessandro static inline int sdma_txinit( 607f48ad614SDennis Dalessandro struct sdma_txreq *tx, 608f48ad614SDennis Dalessandro u16 flags, 609f48ad614SDennis Dalessandro u16 tlen, 610f48ad614SDennis Dalessandro void (*cb)(struct sdma_txreq *, int)) 611f48ad614SDennis Dalessandro { 612f48ad614SDennis Dalessandro return sdma_txinit_ahg(tx, flags, tlen, 0, 0, NULL, 0, cb); 613f48ad614SDennis Dalessandro } 614f48ad614SDennis Dalessandro 615f48ad614SDennis Dalessandro /* helpers - don't use */ 616f48ad614SDennis Dalessandro static inline int sdma_mapping_type(struct sdma_desc *d) 617f48ad614SDennis Dalessandro { 618f48ad614SDennis Dalessandro return (d->qw[1] & SDMA_DESC1_GENERATION_SMASK) 619f48ad614SDennis Dalessandro >> SDMA_DESC1_GENERATION_SHIFT; 620f48ad614SDennis Dalessandro } 621f48ad614SDennis Dalessandro 622f48ad614SDennis Dalessandro static inline size_t sdma_mapping_len(struct sdma_desc *d) 623f48ad614SDennis Dalessandro { 624f48ad614SDennis Dalessandro return (d->qw[0] & SDMA_DESC0_BYTE_COUNT_SMASK) 625f48ad614SDennis Dalessandro >> SDMA_DESC0_BYTE_COUNT_SHIFT; 626f48ad614SDennis Dalessandro } 627f48ad614SDennis Dalessandro 628f48ad614SDennis Dalessandro static inline dma_addr_t sdma_mapping_addr(struct sdma_desc *d) 629f48ad614SDennis Dalessandro { 630f48ad614SDennis Dalessandro return (d->qw[0] & SDMA_DESC0_PHY_ADDR_SMASK) 631f48ad614SDennis Dalessandro >> SDMA_DESC0_PHY_ADDR_SHIFT; 632f48ad614SDennis Dalessandro } 633f48ad614SDennis Dalessandro 634f48ad614SDennis Dalessandro static inline void make_tx_sdma_desc( 635f48ad614SDennis Dalessandro struct sdma_txreq *tx, 636f48ad614SDennis Dalessandro int type, 637f48ad614SDennis Dalessandro dma_addr_t addr, 638f48ad614SDennis Dalessandro size_t len) 639f48ad614SDennis Dalessandro { 640f48ad614SDennis Dalessandro struct sdma_desc *desc = &tx->descp[tx->num_desc]; 641f48ad614SDennis Dalessandro 642f48ad614SDennis Dalessandro if (!tx->num_desc) { 643f48ad614SDennis Dalessandro /* qw[0] zero; qw[1] first, ahg mode already in from init */ 644f48ad614SDennis Dalessandro desc->qw[1] |= ((u64)type & SDMA_DESC1_GENERATION_MASK) 645f48ad614SDennis Dalessandro << SDMA_DESC1_GENERATION_SHIFT; 646f48ad614SDennis Dalessandro } else { 647f48ad614SDennis Dalessandro desc->qw[0] = 0; 648f48ad614SDennis Dalessandro desc->qw[1] = ((u64)type & SDMA_DESC1_GENERATION_MASK) 649f48ad614SDennis Dalessandro << SDMA_DESC1_GENERATION_SHIFT; 650f48ad614SDennis Dalessandro } 651f48ad614SDennis Dalessandro desc->qw[0] |= (((u64)addr & SDMA_DESC0_PHY_ADDR_MASK) 652f48ad614SDennis Dalessandro << SDMA_DESC0_PHY_ADDR_SHIFT) | 653f48ad614SDennis Dalessandro (((u64)len & SDMA_DESC0_BYTE_COUNT_MASK) 654f48ad614SDennis Dalessandro << SDMA_DESC0_BYTE_COUNT_SHIFT); 655f48ad614SDennis Dalessandro } 656f48ad614SDennis Dalessandro 657f48ad614SDennis Dalessandro /* helper to extend txreq */ 658f48ad614SDennis Dalessandro int ext_coal_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx, 659f48ad614SDennis Dalessandro int type, void *kvaddr, struct page *page, 660f48ad614SDennis Dalessandro unsigned long offset, u16 len); 661f48ad614SDennis Dalessandro int _pad_sdma_tx_descs(struct hfi1_devdata *, struct sdma_txreq *); 66263df8e09SMike Marciniszyn void __sdma_txclean(struct hfi1_devdata *, struct sdma_txreq *); 66363df8e09SMike Marciniszyn 66463df8e09SMike Marciniszyn static inline void sdma_txclean(struct hfi1_devdata *dd, struct sdma_txreq *tx) 66563df8e09SMike Marciniszyn { 66663df8e09SMike Marciniszyn if (tx->num_desc) 66763df8e09SMike Marciniszyn __sdma_txclean(dd, tx); 66863df8e09SMike Marciniszyn } 669f48ad614SDennis Dalessandro 670f48ad614SDennis Dalessandro /* helpers used by public routines */ 671f48ad614SDennis Dalessandro static inline void _sdma_close_tx(struct hfi1_devdata *dd, 672f48ad614SDennis Dalessandro struct sdma_txreq *tx) 673f48ad614SDennis Dalessandro { 674f48ad614SDennis Dalessandro tx->descp[tx->num_desc].qw[0] |= 675f48ad614SDennis Dalessandro SDMA_DESC0_LAST_DESC_FLAG; 676f48ad614SDennis Dalessandro tx->descp[tx->num_desc].qw[1] |= 677f48ad614SDennis Dalessandro dd->default_desc1; 678f48ad614SDennis Dalessandro if (tx->flags & SDMA_TXREQ_F_URGENT) 679f48ad614SDennis Dalessandro tx->descp[tx->num_desc].qw[1] |= 680f48ad614SDennis Dalessandro (SDMA_DESC1_HEAD_TO_HOST_FLAG | 681f48ad614SDennis Dalessandro SDMA_DESC1_INT_REQ_FLAG); 682f48ad614SDennis Dalessandro } 683f48ad614SDennis Dalessandro 684f48ad614SDennis Dalessandro static inline int _sdma_txadd_daddr( 685f48ad614SDennis Dalessandro struct hfi1_devdata *dd, 686f48ad614SDennis Dalessandro int type, 687f48ad614SDennis Dalessandro struct sdma_txreq *tx, 688f48ad614SDennis Dalessandro dma_addr_t addr, 689f48ad614SDennis Dalessandro u16 len) 690f48ad614SDennis Dalessandro { 691f48ad614SDennis Dalessandro int rval = 0; 692f48ad614SDennis Dalessandro 693f48ad614SDennis Dalessandro make_tx_sdma_desc( 694f48ad614SDennis Dalessandro tx, 695f48ad614SDennis Dalessandro type, 696f48ad614SDennis Dalessandro addr, len); 697f48ad614SDennis Dalessandro WARN_ON(len > tx->tlen); 698f48ad614SDennis Dalessandro tx->tlen -= len; 699f48ad614SDennis Dalessandro /* special cases for last */ 700f48ad614SDennis Dalessandro if (!tx->tlen) { 701f48ad614SDennis Dalessandro if (tx->packet_len & (sizeof(u32) - 1)) { 702f48ad614SDennis Dalessandro rval = _pad_sdma_tx_descs(dd, tx); 703f48ad614SDennis Dalessandro if (rval) 704f48ad614SDennis Dalessandro return rval; 705f48ad614SDennis Dalessandro } else { 706f48ad614SDennis Dalessandro _sdma_close_tx(dd, tx); 707f48ad614SDennis Dalessandro } 708f48ad614SDennis Dalessandro } 709f48ad614SDennis Dalessandro tx->num_desc++; 710f48ad614SDennis Dalessandro return rval; 711f48ad614SDennis Dalessandro } 712f48ad614SDennis Dalessandro 713f48ad614SDennis Dalessandro /** 714f48ad614SDennis Dalessandro * sdma_txadd_page() - add a page to the sdma_txreq 715f48ad614SDennis Dalessandro * @dd: the device to use for mapping 716f48ad614SDennis Dalessandro * @tx: tx request to which the page is added 717f48ad614SDennis Dalessandro * @page: page to map 718f48ad614SDennis Dalessandro * @offset: offset within the page 719f48ad614SDennis Dalessandro * @len: length in bytes 720f48ad614SDennis Dalessandro * 721f48ad614SDennis Dalessandro * This is used to add a page/offset/length descriptor. 722f48ad614SDennis Dalessandro * 723f48ad614SDennis Dalessandro * The mapping/unmapping of the page/offset/len is automatically handled. 724f48ad614SDennis Dalessandro * 725f48ad614SDennis Dalessandro * Return: 726f48ad614SDennis Dalessandro * 0 - success, -ENOSPC - mapping fail, -ENOMEM - couldn't 727f48ad614SDennis Dalessandro * extend/coalesce descriptor array 728f48ad614SDennis Dalessandro */ 729f48ad614SDennis Dalessandro static inline int sdma_txadd_page( 730f48ad614SDennis Dalessandro struct hfi1_devdata *dd, 731f48ad614SDennis Dalessandro struct sdma_txreq *tx, 732f48ad614SDennis Dalessandro struct page *page, 733f48ad614SDennis Dalessandro unsigned long offset, 734f48ad614SDennis Dalessandro u16 len) 735f48ad614SDennis Dalessandro { 736f48ad614SDennis Dalessandro dma_addr_t addr; 737f48ad614SDennis Dalessandro int rval; 738f48ad614SDennis Dalessandro 739f48ad614SDennis Dalessandro if ((unlikely(tx->num_desc == tx->desc_limit))) { 740f48ad614SDennis Dalessandro rval = ext_coal_sdma_tx_descs(dd, tx, SDMA_MAP_PAGE, 741f48ad614SDennis Dalessandro NULL, page, offset, len); 742f48ad614SDennis Dalessandro if (rval <= 0) 743f48ad614SDennis Dalessandro return rval; 744f48ad614SDennis Dalessandro } 745f48ad614SDennis Dalessandro 746f48ad614SDennis Dalessandro addr = dma_map_page( 747f48ad614SDennis Dalessandro &dd->pcidev->dev, 748f48ad614SDennis Dalessandro page, 749f48ad614SDennis Dalessandro offset, 750f48ad614SDennis Dalessandro len, 751f48ad614SDennis Dalessandro DMA_TO_DEVICE); 752f48ad614SDennis Dalessandro 753f48ad614SDennis Dalessandro if (unlikely(dma_mapping_error(&dd->pcidev->dev, addr))) { 75463df8e09SMike Marciniszyn __sdma_txclean(dd, tx); 755f48ad614SDennis Dalessandro return -ENOSPC; 756f48ad614SDennis Dalessandro } 757f48ad614SDennis Dalessandro 758f48ad614SDennis Dalessandro return _sdma_txadd_daddr( 759f48ad614SDennis Dalessandro dd, SDMA_MAP_PAGE, tx, addr, len); 760f48ad614SDennis Dalessandro } 761f48ad614SDennis Dalessandro 762f48ad614SDennis Dalessandro /** 763f48ad614SDennis Dalessandro * sdma_txadd_daddr() - add a dma address to the sdma_txreq 764f48ad614SDennis Dalessandro * @dd: the device to use for mapping 765f48ad614SDennis Dalessandro * @tx: sdma_txreq to which the page is added 766f48ad614SDennis Dalessandro * @addr: dma address mapped by caller 767f48ad614SDennis Dalessandro * @len: length in bytes 768f48ad614SDennis Dalessandro * 769f48ad614SDennis Dalessandro * This is used to add a descriptor for memory that is already dma mapped. 770f48ad614SDennis Dalessandro * 771f48ad614SDennis Dalessandro * In this case, there is no unmapping as part of the progress processing for 772f48ad614SDennis Dalessandro * this memory location. 773f48ad614SDennis Dalessandro * 774f48ad614SDennis Dalessandro * Return: 775f48ad614SDennis Dalessandro * 0 - success, -ENOMEM - couldn't extend descriptor array 776f48ad614SDennis Dalessandro */ 777f48ad614SDennis Dalessandro 778f48ad614SDennis Dalessandro static inline int sdma_txadd_daddr( 779f48ad614SDennis Dalessandro struct hfi1_devdata *dd, 780f48ad614SDennis Dalessandro struct sdma_txreq *tx, 781f48ad614SDennis Dalessandro dma_addr_t addr, 782f48ad614SDennis Dalessandro u16 len) 783f48ad614SDennis Dalessandro { 784f48ad614SDennis Dalessandro int rval; 785f48ad614SDennis Dalessandro 786f48ad614SDennis Dalessandro if ((unlikely(tx->num_desc == tx->desc_limit))) { 787f48ad614SDennis Dalessandro rval = ext_coal_sdma_tx_descs(dd, tx, SDMA_MAP_NONE, 788f48ad614SDennis Dalessandro NULL, NULL, 0, 0); 789f48ad614SDennis Dalessandro if (rval <= 0) 790f48ad614SDennis Dalessandro return rval; 791f48ad614SDennis Dalessandro } 792f48ad614SDennis Dalessandro 793f48ad614SDennis Dalessandro return _sdma_txadd_daddr(dd, SDMA_MAP_NONE, tx, addr, len); 794f48ad614SDennis Dalessandro } 795f48ad614SDennis Dalessandro 796f48ad614SDennis Dalessandro /** 797f48ad614SDennis Dalessandro * sdma_txadd_kvaddr() - add a kernel virtual address to sdma_txreq 798f48ad614SDennis Dalessandro * @dd: the device to use for mapping 799f48ad614SDennis Dalessandro * @tx: sdma_txreq to which the page is added 800f48ad614SDennis Dalessandro * @kvaddr: the kernel virtual address 801f48ad614SDennis Dalessandro * @len: length in bytes 802f48ad614SDennis Dalessandro * 803f48ad614SDennis Dalessandro * This is used to add a descriptor referenced by the indicated kvaddr and 804f48ad614SDennis Dalessandro * len. 805f48ad614SDennis Dalessandro * 806f48ad614SDennis Dalessandro * The mapping/unmapping of the kvaddr and len is automatically handled. 807f48ad614SDennis Dalessandro * 808f48ad614SDennis Dalessandro * Return: 809f48ad614SDennis Dalessandro * 0 - success, -ENOSPC - mapping fail, -ENOMEM - couldn't extend/coalesce 810f48ad614SDennis Dalessandro * descriptor array 811f48ad614SDennis Dalessandro */ 812f48ad614SDennis Dalessandro static inline int sdma_txadd_kvaddr( 813f48ad614SDennis Dalessandro struct hfi1_devdata *dd, 814f48ad614SDennis Dalessandro struct sdma_txreq *tx, 815f48ad614SDennis Dalessandro void *kvaddr, 816f48ad614SDennis Dalessandro u16 len) 817f48ad614SDennis Dalessandro { 818f48ad614SDennis Dalessandro dma_addr_t addr; 819f48ad614SDennis Dalessandro int rval; 820f48ad614SDennis Dalessandro 821f48ad614SDennis Dalessandro if ((unlikely(tx->num_desc == tx->desc_limit))) { 822f48ad614SDennis Dalessandro rval = ext_coal_sdma_tx_descs(dd, tx, SDMA_MAP_SINGLE, 823f48ad614SDennis Dalessandro kvaddr, NULL, 0, len); 824f48ad614SDennis Dalessandro if (rval <= 0) 825f48ad614SDennis Dalessandro return rval; 826f48ad614SDennis Dalessandro } 827f48ad614SDennis Dalessandro 828f48ad614SDennis Dalessandro addr = dma_map_single( 829f48ad614SDennis Dalessandro &dd->pcidev->dev, 830f48ad614SDennis Dalessandro kvaddr, 831f48ad614SDennis Dalessandro len, 832f48ad614SDennis Dalessandro DMA_TO_DEVICE); 833f48ad614SDennis Dalessandro 834f48ad614SDennis Dalessandro if (unlikely(dma_mapping_error(&dd->pcidev->dev, addr))) { 83563df8e09SMike Marciniszyn __sdma_txclean(dd, tx); 836f48ad614SDennis Dalessandro return -ENOSPC; 837f48ad614SDennis Dalessandro } 838f48ad614SDennis Dalessandro 839f48ad614SDennis Dalessandro return _sdma_txadd_daddr( 840f48ad614SDennis Dalessandro dd, SDMA_MAP_SINGLE, tx, addr, len); 841f48ad614SDennis Dalessandro } 842f48ad614SDennis Dalessandro 843f48ad614SDennis Dalessandro struct iowait; 844f48ad614SDennis Dalessandro 845f48ad614SDennis Dalessandro int sdma_send_txreq(struct sdma_engine *sde, 846f48ad614SDennis Dalessandro struct iowait *wait, 847bcad2913SKaike Wan struct sdma_txreq *tx, 848bcad2913SKaike Wan bool pkts_sent); 849f48ad614SDennis Dalessandro int sdma_send_txlist(struct sdma_engine *sde, 850f48ad614SDennis Dalessandro struct iowait *wait, 8510b115ef1SHarish Chegondi struct list_head *tx_list, 8520b115ef1SHarish Chegondi u32 *count); 853f48ad614SDennis Dalessandro 854f48ad614SDennis Dalessandro int sdma_ahg_alloc(struct sdma_engine *sde); 855f48ad614SDennis Dalessandro void sdma_ahg_free(struct sdma_engine *sde, int ahg_index); 856f48ad614SDennis Dalessandro 857f48ad614SDennis Dalessandro /** 858f48ad614SDennis Dalessandro * sdma_build_ahg - build ahg descriptor 859f48ad614SDennis Dalessandro * @data 860f48ad614SDennis Dalessandro * @dwindex 861f48ad614SDennis Dalessandro * @startbit 862f48ad614SDennis Dalessandro * @bits 863f48ad614SDennis Dalessandro * 864f48ad614SDennis Dalessandro * Build and return a 32 bit descriptor. 865f48ad614SDennis Dalessandro */ 866f48ad614SDennis Dalessandro static inline u32 sdma_build_ahg_descriptor( 867f48ad614SDennis Dalessandro u16 data, 868f48ad614SDennis Dalessandro u8 dwindex, 869f48ad614SDennis Dalessandro u8 startbit, 870f48ad614SDennis Dalessandro u8 bits) 871f48ad614SDennis Dalessandro { 872f48ad614SDennis Dalessandro return (u32)(1UL << SDMA_AHG_UPDATE_ENABLE_SHIFT | 873f48ad614SDennis Dalessandro ((startbit & SDMA_AHG_FIELD_START_MASK) << 874f48ad614SDennis Dalessandro SDMA_AHG_FIELD_START_SHIFT) | 875f48ad614SDennis Dalessandro ((bits & SDMA_AHG_FIELD_LEN_MASK) << 876f48ad614SDennis Dalessandro SDMA_AHG_FIELD_LEN_SHIFT) | 877f48ad614SDennis Dalessandro ((dwindex & SDMA_AHG_INDEX_MASK) << 878f48ad614SDennis Dalessandro SDMA_AHG_INDEX_SHIFT) | 879f48ad614SDennis Dalessandro ((data & SDMA_AHG_VALUE_MASK) << 880f48ad614SDennis Dalessandro SDMA_AHG_VALUE_SHIFT)); 881f48ad614SDennis Dalessandro } 882f48ad614SDennis Dalessandro 883f48ad614SDennis Dalessandro /** 884f48ad614SDennis Dalessandro * sdma_progress - use seq number of detect head progress 885f48ad614SDennis Dalessandro * @sde: sdma_engine to check 886f48ad614SDennis Dalessandro * @seq: base seq count 887f48ad614SDennis Dalessandro * @tx: txreq for which we need to check descriptor availability 888f48ad614SDennis Dalessandro * 889f48ad614SDennis Dalessandro * This is used in the appropriate spot in the sleep routine 890f48ad614SDennis Dalessandro * to check for potential ring progress. This routine gets the 891f48ad614SDennis Dalessandro * seqcount before queuing the iowait structure for progress. 892f48ad614SDennis Dalessandro * 893f48ad614SDennis Dalessandro * If the seqcount indicates that progress needs to be checked, 894f48ad614SDennis Dalessandro * re-submission is detected by checking whether the descriptor 895f48ad614SDennis Dalessandro * queue has enough descriptor for the txreq. 896f48ad614SDennis Dalessandro */ 897f48ad614SDennis Dalessandro static inline unsigned sdma_progress(struct sdma_engine *sde, unsigned seq, 898f48ad614SDennis Dalessandro struct sdma_txreq *tx) 899f48ad614SDennis Dalessandro { 900f48ad614SDennis Dalessandro if (read_seqretry(&sde->head_lock, seq)) { 901f48ad614SDennis Dalessandro sde->desc_avail = sdma_descq_freecnt(sde); 902f48ad614SDennis Dalessandro if (tx->num_desc > sde->desc_avail) 903f48ad614SDennis Dalessandro return 0; 904f48ad614SDennis Dalessandro return 1; 905f48ad614SDennis Dalessandro } 906f48ad614SDennis Dalessandro return 0; 907f48ad614SDennis Dalessandro } 908f48ad614SDennis Dalessandro 909f48ad614SDennis Dalessandro /** 910f48ad614SDennis Dalessandro * sdma_iowait_schedule() - initialize wait structure 911f48ad614SDennis Dalessandro * @sde: sdma_engine to schedule 912f48ad614SDennis Dalessandro * @wait: wait struct to schedule 913f48ad614SDennis Dalessandro * 914f48ad614SDennis Dalessandro * This function initializes the iowait 915f48ad614SDennis Dalessandro * structure embedded in the QP or PQ. 916f48ad614SDennis Dalessandro * 917f48ad614SDennis Dalessandro */ 918f48ad614SDennis Dalessandro static inline void sdma_iowait_schedule( 919f48ad614SDennis Dalessandro struct sdma_engine *sde, 920f48ad614SDennis Dalessandro struct iowait *wait) 921f48ad614SDennis Dalessandro { 922f48ad614SDennis Dalessandro struct hfi1_pportdata *ppd = sde->dd->pport; 923f48ad614SDennis Dalessandro 924f48ad614SDennis Dalessandro iowait_schedule(wait, ppd->hfi1_wq, sde->cpu); 925f48ad614SDennis Dalessandro } 926f48ad614SDennis Dalessandro 927f48ad614SDennis Dalessandro /* for use by interrupt handling */ 928f48ad614SDennis Dalessandro void sdma_engine_error(struct sdma_engine *sde, u64 status); 929f48ad614SDennis Dalessandro void sdma_engine_interrupt(struct sdma_engine *sde, u64 status); 930f48ad614SDennis Dalessandro 931f48ad614SDennis Dalessandro /* 932f48ad614SDennis Dalessandro * 933f48ad614SDennis Dalessandro * The diagram below details the relationship of the mapping structures 934f48ad614SDennis Dalessandro * 935f48ad614SDennis Dalessandro * Since the mapping now allows for non-uniform engines per vl, the 936f48ad614SDennis Dalessandro * number of engines for a vl is either the vl_engines[vl] or 937f48ad614SDennis Dalessandro * a computation based on num_sdma/num_vls: 938f48ad614SDennis Dalessandro * 939f48ad614SDennis Dalessandro * For example: 940f48ad614SDennis Dalessandro * nactual = vl_engines ? vl_engines[vl] : num_sdma/num_vls 941f48ad614SDennis Dalessandro * 942f48ad614SDennis Dalessandro * n = roundup to next highest power of 2 using nactual 943f48ad614SDennis Dalessandro * 944f48ad614SDennis Dalessandro * In the case where there are num_sdma/num_vls doesn't divide 945f48ad614SDennis Dalessandro * evenly, the extras are added from the last vl downward. 946f48ad614SDennis Dalessandro * 947f48ad614SDennis Dalessandro * For the case where n > nactual, the engines are assigned 948f48ad614SDennis Dalessandro * in a round robin fashion wrapping back to the first engine 949f48ad614SDennis Dalessandro * for a particular vl. 950f48ad614SDennis Dalessandro * 951f48ad614SDennis Dalessandro * dd->sdma_map 952f48ad614SDennis Dalessandro * | sdma_map_elem[0] 953f48ad614SDennis Dalessandro * | +--------------------+ 954f48ad614SDennis Dalessandro * v | mask | 955f48ad614SDennis Dalessandro * sdma_vl_map |--------------------| 956f48ad614SDennis Dalessandro * +--------------------------+ | sde[0] -> eng 1 | 957f48ad614SDennis Dalessandro * | list (RCU) | |--------------------| 958f48ad614SDennis Dalessandro * |--------------------------| ->| sde[1] -> eng 2 | 959f48ad614SDennis Dalessandro * | mask | --/ |--------------------| 960f48ad614SDennis Dalessandro * |--------------------------| -/ | * | 961f48ad614SDennis Dalessandro * | actual_vls (max 8) | -/ |--------------------| 962e8ea95afSIra Weiny * |--------------------------| --/ | sde[n-1] -> eng n | 963f48ad614SDennis Dalessandro * | vls (max 8) | -/ +--------------------+ 964f48ad614SDennis Dalessandro * |--------------------------| --/ 965f48ad614SDennis Dalessandro * | map[0] |-/ 966e8ea95afSIra Weiny * |--------------------------| +---------------------+ 967f48ad614SDennis Dalessandro * | map[1] |--- | mask | 968e8ea95afSIra Weiny * |--------------------------| \---- |---------------------| 969f48ad614SDennis Dalessandro * | * | \-- | sde[0] -> eng 1+n | 970e8ea95afSIra Weiny * | * | \---- |---------------------| 971f48ad614SDennis Dalessandro * | * | \->| sde[1] -> eng 2+n | 972e8ea95afSIra Weiny * |--------------------------| |---------------------| 973f48ad614SDennis Dalessandro * | map[vls - 1] |- | * | 974e8ea95afSIra Weiny * +--------------------------+ \- |---------------------| 975e8ea95afSIra Weiny * \- | sde[m-1] -> eng m+n | 976e8ea95afSIra Weiny * \ +---------------------+ 977f48ad614SDennis Dalessandro * \- 978f48ad614SDennis Dalessandro * \ 979e8ea95afSIra Weiny * \- +----------------------+ 980f48ad614SDennis Dalessandro * \- | mask | 981e8ea95afSIra Weiny * \ |----------------------| 982f48ad614SDennis Dalessandro * \- | sde[0] -> eng 1+m+n | 983e8ea95afSIra Weiny * \- |----------------------| 984f48ad614SDennis Dalessandro * >| sde[1] -> eng 2+m+n | 985e8ea95afSIra Weiny * |----------------------| 986f48ad614SDennis Dalessandro * | * | 987e8ea95afSIra Weiny * |----------------------| 988e8ea95afSIra Weiny * | sde[o-1] -> eng o+m+n| 989e8ea95afSIra Weiny * +----------------------+ 990f48ad614SDennis Dalessandro * 991f48ad614SDennis Dalessandro */ 992f48ad614SDennis Dalessandro 993f48ad614SDennis Dalessandro /** 994f48ad614SDennis Dalessandro * struct sdma_map_elem - mapping for a vl 995f48ad614SDennis Dalessandro * @mask - selector mask 996f48ad614SDennis Dalessandro * @sde - array of engines for this vl 997f48ad614SDennis Dalessandro * 998f48ad614SDennis Dalessandro * The mask is used to "mod" the selector 999f48ad614SDennis Dalessandro * to produce index into the trailing 1000f48ad614SDennis Dalessandro * array of sdes. 1001f48ad614SDennis Dalessandro */ 1002f48ad614SDennis Dalessandro struct sdma_map_elem { 1003f48ad614SDennis Dalessandro u32 mask; 1004f48ad614SDennis Dalessandro struct sdma_engine *sde[0]; 1005f48ad614SDennis Dalessandro }; 1006f48ad614SDennis Dalessandro 1007f48ad614SDennis Dalessandro /** 1008f48ad614SDennis Dalessandro * struct sdma_map_el - mapping for a vl 1009f48ad614SDennis Dalessandro * @engine_to_vl - map of an engine to a vl 1010f48ad614SDennis Dalessandro * @list - rcu head for free callback 1011f48ad614SDennis Dalessandro * @mask - vl mask to "mod" the vl to produce an index to map array 1012f48ad614SDennis Dalessandro * @actual_vls - number of vls 1013f48ad614SDennis Dalessandro * @vls - number of vls rounded to next power of 2 1014f48ad614SDennis Dalessandro * @map - array of sdma_map_elem entries 1015f48ad614SDennis Dalessandro * 1016f48ad614SDennis Dalessandro * This is the parent mapping structure. The trailing 1017f48ad614SDennis Dalessandro * members of the struct point to sdma_map_elem entries, which 1018f48ad614SDennis Dalessandro * in turn point to an array of sde's for that vl. 1019f48ad614SDennis Dalessandro */ 1020f48ad614SDennis Dalessandro struct sdma_vl_map { 1021f48ad614SDennis Dalessandro s8 engine_to_vl[TXE_NUM_SDMA_ENGINES]; 1022f48ad614SDennis Dalessandro struct rcu_head list; 1023f48ad614SDennis Dalessandro u32 mask; 1024f48ad614SDennis Dalessandro u8 actual_vls; 1025f48ad614SDennis Dalessandro u8 vls; 1026f48ad614SDennis Dalessandro struct sdma_map_elem *map[0]; 1027f48ad614SDennis Dalessandro }; 1028f48ad614SDennis Dalessandro 1029f48ad614SDennis Dalessandro int sdma_map_init( 1030f48ad614SDennis Dalessandro struct hfi1_devdata *dd, 1031f48ad614SDennis Dalessandro u8 port, 1032f48ad614SDennis Dalessandro u8 num_vls, 1033f48ad614SDennis Dalessandro u8 *vl_engines); 1034f48ad614SDennis Dalessandro 1035f48ad614SDennis Dalessandro /* slow path */ 1036f48ad614SDennis Dalessandro void _sdma_engine_progress_schedule(struct sdma_engine *sde); 1037f48ad614SDennis Dalessandro 1038f48ad614SDennis Dalessandro /** 1039f48ad614SDennis Dalessandro * sdma_engine_progress_schedule() - schedule progress on engine 1040f48ad614SDennis Dalessandro * @sde: sdma_engine to schedule progress 1041f48ad614SDennis Dalessandro * 1042f48ad614SDennis Dalessandro * This is the fast path. 1043f48ad614SDennis Dalessandro * 1044f48ad614SDennis Dalessandro */ 1045f48ad614SDennis Dalessandro static inline void sdma_engine_progress_schedule( 1046f48ad614SDennis Dalessandro struct sdma_engine *sde) 1047f48ad614SDennis Dalessandro { 1048f48ad614SDennis Dalessandro if (!sde || sdma_descq_inprocess(sde) < (sde->descq_cnt / 8)) 1049f48ad614SDennis Dalessandro return; 1050f48ad614SDennis Dalessandro _sdma_engine_progress_schedule(sde); 1051f48ad614SDennis Dalessandro } 1052f48ad614SDennis Dalessandro 1053f48ad614SDennis Dalessandro struct sdma_engine *sdma_select_engine_sc( 1054f48ad614SDennis Dalessandro struct hfi1_devdata *dd, 1055f48ad614SDennis Dalessandro u32 selector, 1056f48ad614SDennis Dalessandro u8 sc5); 1057f48ad614SDennis Dalessandro 1058f48ad614SDennis Dalessandro struct sdma_engine *sdma_select_engine_vl( 1059f48ad614SDennis Dalessandro struct hfi1_devdata *dd, 1060f48ad614SDennis Dalessandro u32 selector, 1061f48ad614SDennis Dalessandro u8 vl); 1062f48ad614SDennis Dalessandro 10630cb2aa69STadeusz Struk struct sdma_engine *sdma_select_user_engine(struct hfi1_devdata *dd, 10640cb2aa69STadeusz Struk u32 selector, u8 vl); 10650cb2aa69STadeusz Struk ssize_t sdma_get_cpu_to_sde_map(struct sdma_engine *sde, char *buf); 10660cb2aa69STadeusz Struk ssize_t sdma_set_cpu_to_sde_map(struct sdma_engine *sde, const char *buf, 10670cb2aa69STadeusz Struk size_t count); 10680cb2aa69STadeusz Struk int sdma_engine_get_vl(struct sdma_engine *sde); 1069f48ad614SDennis Dalessandro void sdma_seqfile_dump_sde(struct seq_file *s, struct sdma_engine *); 1070af3674d6STadeusz Struk void sdma_seqfile_dump_cpu_list(struct seq_file *s, struct hfi1_devdata *dd, 1071af3674d6STadeusz Struk unsigned long cpuid); 1072f48ad614SDennis Dalessandro 1073f48ad614SDennis Dalessandro #ifdef CONFIG_SDMA_VERBOSITY 1074f48ad614SDennis Dalessandro void sdma_dumpstate(struct sdma_engine *); 1075f48ad614SDennis Dalessandro #endif 1076f48ad614SDennis Dalessandro static inline char *slashstrip(char *s) 1077f48ad614SDennis Dalessandro { 1078f48ad614SDennis Dalessandro char *r = s; 1079f48ad614SDennis Dalessandro 1080f48ad614SDennis Dalessandro while (*s) 1081f48ad614SDennis Dalessandro if (*s++ == '/') 1082f48ad614SDennis Dalessandro r = s; 1083f48ad614SDennis Dalessandro return r; 1084f48ad614SDennis Dalessandro } 1085f48ad614SDennis Dalessandro 1086f48ad614SDennis Dalessandro u16 sdma_get_descq_cnt(void); 1087f48ad614SDennis Dalessandro 1088f48ad614SDennis Dalessandro extern uint mod_num_sdma; 1089f48ad614SDennis Dalessandro 1090f48ad614SDennis Dalessandro void sdma_update_lmc(struct hfi1_devdata *dd, u64 mask, u32 lid); 1091f48ad614SDennis Dalessandro 1092f48ad614SDennis Dalessandro #endif 1093