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