1*33ec1ccbSHans Petter Selasky /* 2*33ec1ccbSHans Petter Selasky * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. 3*33ec1ccbSHans Petter Selasky * Copyright (c) 2005 Mellanox Technologies. All rights reserved. 4*33ec1ccbSHans Petter Selasky * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. 5*33ec1ccbSHans Petter Selasky * 6*33ec1ccbSHans Petter Selasky * This software is available to you under a choice of one of two 7*33ec1ccbSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU 8*33ec1ccbSHans Petter Selasky * General Public License (GPL) Version 2, available from the file 9*33ec1ccbSHans Petter Selasky * COPYING in the main directory of this source tree, or the 10*33ec1ccbSHans Petter Selasky * OpenIB.org BSD license below: 11*33ec1ccbSHans Petter Selasky * 12*33ec1ccbSHans Petter Selasky * Redistribution and use in source and binary forms, with or 13*33ec1ccbSHans Petter Selasky * without modification, are permitted provided that the following 14*33ec1ccbSHans Petter Selasky * conditions are met: 15*33ec1ccbSHans Petter Selasky * 16*33ec1ccbSHans Petter Selasky * - Redistributions of source code must retain the above 17*33ec1ccbSHans Petter Selasky * copyright notice, this list of conditions and the following 18*33ec1ccbSHans Petter Selasky * disclaimer. 19*33ec1ccbSHans Petter Selasky * 20*33ec1ccbSHans Petter Selasky * - Redistributions in binary form must reproduce the above 21*33ec1ccbSHans Petter Selasky * copyright notice, this list of conditions and the following 22*33ec1ccbSHans Petter Selasky * disclaimer in the documentation and/or other materials 23*33ec1ccbSHans Petter Selasky * provided with the distribution. 24*33ec1ccbSHans Petter Selasky * 25*33ec1ccbSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26*33ec1ccbSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27*33ec1ccbSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28*33ec1ccbSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29*33ec1ccbSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30*33ec1ccbSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31*33ec1ccbSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32*33ec1ccbSHans Petter Selasky * SOFTWARE. 33*33ec1ccbSHans Petter Selasky */ 34*33ec1ccbSHans Petter Selasky 35*33ec1ccbSHans Petter Selasky #define LINUXKPI_PARAM_PREFIX mthca_ 36*33ec1ccbSHans Petter Selasky 37*33ec1ccbSHans Petter Selasky #include <linux/completion.h> 38*33ec1ccbSHans Petter Selasky #include <linux/pci.h> 39*33ec1ccbSHans Petter Selasky #include <linux/errno.h> 40*33ec1ccbSHans Petter Selasky #include <linux/sched.h> 41*33ec1ccbSHans Petter Selasky #include <linux/module.h> 42*33ec1ccbSHans Petter Selasky #include <linux/slab.h> 43*33ec1ccbSHans Petter Selasky #include <linux/page.h> 44*33ec1ccbSHans Petter Selasky #include <asm/io.h> 45*33ec1ccbSHans Petter Selasky #include <rdma/ib_mad.h> 46*33ec1ccbSHans Petter Selasky 47*33ec1ccbSHans Petter Selasky #include "mthca_dev.h" 48*33ec1ccbSHans Petter Selasky #include "mthca_config_reg.h" 49*33ec1ccbSHans Petter Selasky #include "mthca_cmd.h" 50*33ec1ccbSHans Petter Selasky #include "mthca_memfree.h" 51*33ec1ccbSHans Petter Selasky 52*33ec1ccbSHans Petter Selasky #define CMD_POLL_TOKEN 0xffff 53*33ec1ccbSHans Petter Selasky 54*33ec1ccbSHans Petter Selasky enum { 55*33ec1ccbSHans Petter Selasky HCR_IN_PARAM_OFFSET = 0x00, 56*33ec1ccbSHans Petter Selasky HCR_IN_MODIFIER_OFFSET = 0x08, 57*33ec1ccbSHans Petter Selasky HCR_OUT_PARAM_OFFSET = 0x0c, 58*33ec1ccbSHans Petter Selasky HCR_TOKEN_OFFSET = 0x14, 59*33ec1ccbSHans Petter Selasky HCR_STATUS_OFFSET = 0x18, 60*33ec1ccbSHans Petter Selasky 61*33ec1ccbSHans Petter Selasky HCR_OPMOD_SHIFT = 12, 62*33ec1ccbSHans Petter Selasky HCA_E_BIT = 22, 63*33ec1ccbSHans Petter Selasky HCR_GO_BIT = 23 64*33ec1ccbSHans Petter Selasky }; 65*33ec1ccbSHans Petter Selasky 66*33ec1ccbSHans Petter Selasky enum { 67*33ec1ccbSHans Petter Selasky /* initialization and general commands */ 68*33ec1ccbSHans Petter Selasky CMD_SYS_EN = 0x1, 69*33ec1ccbSHans Petter Selasky CMD_SYS_DIS = 0x2, 70*33ec1ccbSHans Petter Selasky CMD_MAP_FA = 0xfff, 71*33ec1ccbSHans Petter Selasky CMD_UNMAP_FA = 0xffe, 72*33ec1ccbSHans Petter Selasky CMD_RUN_FW = 0xff6, 73*33ec1ccbSHans Petter Selasky CMD_MOD_STAT_CFG = 0x34, 74*33ec1ccbSHans Petter Selasky CMD_QUERY_DEV_LIM = 0x3, 75*33ec1ccbSHans Petter Selasky CMD_QUERY_FW = 0x4, 76*33ec1ccbSHans Petter Selasky CMD_ENABLE_LAM = 0xff8, 77*33ec1ccbSHans Petter Selasky CMD_DISABLE_LAM = 0xff7, 78*33ec1ccbSHans Petter Selasky CMD_QUERY_DDR = 0x5, 79*33ec1ccbSHans Petter Selasky CMD_QUERY_ADAPTER = 0x6, 80*33ec1ccbSHans Petter Selasky CMD_INIT_HCA = 0x7, 81*33ec1ccbSHans Petter Selasky CMD_CLOSE_HCA = 0x8, 82*33ec1ccbSHans Petter Selasky CMD_INIT_IB = 0x9, 83*33ec1ccbSHans Petter Selasky CMD_CLOSE_IB = 0xa, 84*33ec1ccbSHans Petter Selasky CMD_QUERY_HCA = 0xb, 85*33ec1ccbSHans Petter Selasky CMD_SET_IB = 0xc, 86*33ec1ccbSHans Petter Selasky CMD_ACCESS_DDR = 0x2e, 87*33ec1ccbSHans Petter Selasky CMD_MAP_ICM = 0xffa, 88*33ec1ccbSHans Petter Selasky CMD_UNMAP_ICM = 0xff9, 89*33ec1ccbSHans Petter Selasky CMD_MAP_ICM_AUX = 0xffc, 90*33ec1ccbSHans Petter Selasky CMD_UNMAP_ICM_AUX = 0xffb, 91*33ec1ccbSHans Petter Selasky CMD_SET_ICM_SIZE = 0xffd, 92*33ec1ccbSHans Petter Selasky 93*33ec1ccbSHans Petter Selasky /* TPT commands */ 94*33ec1ccbSHans Petter Selasky CMD_SW2HW_MPT = 0xd, 95*33ec1ccbSHans Petter Selasky CMD_QUERY_MPT = 0xe, 96*33ec1ccbSHans Petter Selasky CMD_HW2SW_MPT = 0xf, 97*33ec1ccbSHans Petter Selasky CMD_READ_MTT = 0x10, 98*33ec1ccbSHans Petter Selasky CMD_WRITE_MTT = 0x11, 99*33ec1ccbSHans Petter Selasky CMD_SYNC_TPT = 0x2f, 100*33ec1ccbSHans Petter Selasky 101*33ec1ccbSHans Petter Selasky /* EQ commands */ 102*33ec1ccbSHans Petter Selasky CMD_MAP_EQ = 0x12, 103*33ec1ccbSHans Petter Selasky CMD_SW2HW_EQ = 0x13, 104*33ec1ccbSHans Petter Selasky CMD_HW2SW_EQ = 0x14, 105*33ec1ccbSHans Petter Selasky CMD_QUERY_EQ = 0x15, 106*33ec1ccbSHans Petter Selasky 107*33ec1ccbSHans Petter Selasky /* CQ commands */ 108*33ec1ccbSHans Petter Selasky CMD_SW2HW_CQ = 0x16, 109*33ec1ccbSHans Petter Selasky CMD_HW2SW_CQ = 0x17, 110*33ec1ccbSHans Petter Selasky CMD_QUERY_CQ = 0x18, 111*33ec1ccbSHans Petter Selasky CMD_RESIZE_CQ = 0x2c, 112*33ec1ccbSHans Petter Selasky 113*33ec1ccbSHans Petter Selasky /* SRQ commands */ 114*33ec1ccbSHans Petter Selasky CMD_SW2HW_SRQ = 0x35, 115*33ec1ccbSHans Petter Selasky CMD_HW2SW_SRQ = 0x36, 116*33ec1ccbSHans Petter Selasky CMD_QUERY_SRQ = 0x37, 117*33ec1ccbSHans Petter Selasky CMD_ARM_SRQ = 0x40, 118*33ec1ccbSHans Petter Selasky 119*33ec1ccbSHans Petter Selasky /* QP/EE commands */ 120*33ec1ccbSHans Petter Selasky CMD_RST2INIT_QPEE = 0x19, 121*33ec1ccbSHans Petter Selasky CMD_INIT2RTR_QPEE = 0x1a, 122*33ec1ccbSHans Petter Selasky CMD_RTR2RTS_QPEE = 0x1b, 123*33ec1ccbSHans Petter Selasky CMD_RTS2RTS_QPEE = 0x1c, 124*33ec1ccbSHans Petter Selasky CMD_SQERR2RTS_QPEE = 0x1d, 125*33ec1ccbSHans Petter Selasky CMD_2ERR_QPEE = 0x1e, 126*33ec1ccbSHans Petter Selasky CMD_RTS2SQD_QPEE = 0x1f, 127*33ec1ccbSHans Petter Selasky CMD_SQD2SQD_QPEE = 0x38, 128*33ec1ccbSHans Petter Selasky CMD_SQD2RTS_QPEE = 0x20, 129*33ec1ccbSHans Petter Selasky CMD_ERR2RST_QPEE = 0x21, 130*33ec1ccbSHans Petter Selasky CMD_QUERY_QPEE = 0x22, 131*33ec1ccbSHans Petter Selasky CMD_INIT2INIT_QPEE = 0x2d, 132*33ec1ccbSHans Petter Selasky CMD_SUSPEND_QPEE = 0x32, 133*33ec1ccbSHans Petter Selasky CMD_UNSUSPEND_QPEE = 0x33, 134*33ec1ccbSHans Petter Selasky /* special QPs and management commands */ 135*33ec1ccbSHans Petter Selasky CMD_CONF_SPECIAL_QP = 0x23, 136*33ec1ccbSHans Petter Selasky CMD_MAD_IFC = 0x24, 137*33ec1ccbSHans Petter Selasky 138*33ec1ccbSHans Petter Selasky /* multicast commands */ 139*33ec1ccbSHans Petter Selasky CMD_READ_MGM = 0x25, 140*33ec1ccbSHans Petter Selasky CMD_WRITE_MGM = 0x26, 141*33ec1ccbSHans Petter Selasky CMD_MGID_HASH = 0x27, 142*33ec1ccbSHans Petter Selasky 143*33ec1ccbSHans Petter Selasky /* miscellaneous commands */ 144*33ec1ccbSHans Petter Selasky CMD_DIAG_RPRT = 0x30, 145*33ec1ccbSHans Petter Selasky CMD_NOP = 0x31, 146*33ec1ccbSHans Petter Selasky 147*33ec1ccbSHans Petter Selasky /* debug commands */ 148*33ec1ccbSHans Petter Selasky CMD_QUERY_DEBUG_MSG = 0x2a, 149*33ec1ccbSHans Petter Selasky CMD_SET_DEBUG_MSG = 0x2b, 150*33ec1ccbSHans Petter Selasky }; 151*33ec1ccbSHans Petter Selasky 152*33ec1ccbSHans Petter Selasky /* 153*33ec1ccbSHans Petter Selasky * According to Mellanox code, FW may be starved and never complete 154*33ec1ccbSHans Petter Selasky * commands. So we can't use strict timeouts described in PRM -- we 155*33ec1ccbSHans Petter Selasky * just arbitrarily select 60 seconds for now. 156*33ec1ccbSHans Petter Selasky */ 157*33ec1ccbSHans Petter Selasky #if 0 158*33ec1ccbSHans Petter Selasky /* 159*33ec1ccbSHans Petter Selasky * Round up and add 1 to make sure we get the full wait time (since we 160*33ec1ccbSHans Petter Selasky * will be starting in the middle of a jiffy) 161*33ec1ccbSHans Petter Selasky */ 162*33ec1ccbSHans Petter Selasky enum { 163*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A = (HZ + 999) / 1000 + 1, 164*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_B = (HZ + 99) / 100 + 1, 165*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_C = (HZ + 9) / 10 + 1, 166*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_D = 60 * HZ 167*33ec1ccbSHans Petter Selasky }; 168*33ec1ccbSHans Petter Selasky #else 169*33ec1ccbSHans Petter Selasky #define CMD_TIME_CLASS_A (60 * HZ) 170*33ec1ccbSHans Petter Selasky #define CMD_TIME_CLASS_B (60 * HZ) 171*33ec1ccbSHans Petter Selasky #define CMD_TIME_CLASS_C (60 * HZ) 172*33ec1ccbSHans Petter Selasky #define CMD_TIME_CLASS_D (60 * HZ) 173*33ec1ccbSHans Petter Selasky #endif 174*33ec1ccbSHans Petter Selasky 175*33ec1ccbSHans Petter Selasky #define GO_BIT_TIMEOUT (HZ * 10) 176*33ec1ccbSHans Petter Selasky 177*33ec1ccbSHans Petter Selasky struct mthca_cmd_context { 178*33ec1ccbSHans Petter Selasky struct completion done; 179*33ec1ccbSHans Petter Selasky int result; 180*33ec1ccbSHans Petter Selasky int next; 181*33ec1ccbSHans Petter Selasky u64 out_param; 182*33ec1ccbSHans Petter Selasky u16 token; 183*33ec1ccbSHans Petter Selasky u8 status; 184*33ec1ccbSHans Petter Selasky }; 185*33ec1ccbSHans Petter Selasky 186*33ec1ccbSHans Petter Selasky static int fw_cmd_doorbell = 0; 187*33ec1ccbSHans Petter Selasky module_param(fw_cmd_doorbell, int, 0644); 188*33ec1ccbSHans Petter Selasky MODULE_PARM_DESC(fw_cmd_doorbell, "post FW commands through doorbell page if nonzero " 189*33ec1ccbSHans Petter Selasky "(and supported by FW)"); 190*33ec1ccbSHans Petter Selasky 191*33ec1ccbSHans Petter Selasky static inline int go_bit(struct mthca_dev *dev) 192*33ec1ccbSHans Petter Selasky { 193*33ec1ccbSHans Petter Selasky return readl(dev->hcr + HCR_STATUS_OFFSET) & 194*33ec1ccbSHans Petter Selasky swab32(1 << HCR_GO_BIT); 195*33ec1ccbSHans Petter Selasky } 196*33ec1ccbSHans Petter Selasky 197*33ec1ccbSHans Petter Selasky static void mthca_cmd_post_dbell(struct mthca_dev *dev, 198*33ec1ccbSHans Petter Selasky u64 in_param, 199*33ec1ccbSHans Petter Selasky u64 out_param, 200*33ec1ccbSHans Petter Selasky u32 in_modifier, 201*33ec1ccbSHans Petter Selasky u8 op_modifier, 202*33ec1ccbSHans Petter Selasky u16 op, 203*33ec1ccbSHans Petter Selasky u16 token) 204*33ec1ccbSHans Petter Selasky { 205*33ec1ccbSHans Petter Selasky void __iomem *ptr = dev->cmd.dbell_map; 206*33ec1ccbSHans Petter Selasky u16 *offs = dev->cmd.dbell_offsets; 207*33ec1ccbSHans Petter Selasky 208*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32(in_param >> 32), ptr + offs[0]); 209*33ec1ccbSHans Petter Selasky wmb(); 210*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful), ptr + offs[1]); 211*33ec1ccbSHans Petter Selasky wmb(); 212*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32(in_modifier), ptr + offs[2]); 213*33ec1ccbSHans Petter Selasky wmb(); 214*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32(out_param >> 32), ptr + offs[3]); 215*33ec1ccbSHans Petter Selasky wmb(); 216*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), ptr + offs[4]); 217*33ec1ccbSHans Petter Selasky wmb(); 218*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32(token << 16), ptr + offs[5]); 219*33ec1ccbSHans Petter Selasky wmb(); 220*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) | 221*33ec1ccbSHans Petter Selasky (1 << HCA_E_BIT) | 222*33ec1ccbSHans Petter Selasky (op_modifier << HCR_OPMOD_SHIFT) | 223*33ec1ccbSHans Petter Selasky op), ptr + offs[6]); 224*33ec1ccbSHans Petter Selasky wmb(); 225*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) 0, ptr + offs[7]); 226*33ec1ccbSHans Petter Selasky wmb(); 227*33ec1ccbSHans Petter Selasky } 228*33ec1ccbSHans Petter Selasky 229*33ec1ccbSHans Petter Selasky static int mthca_cmd_post_hcr(struct mthca_dev *dev, 230*33ec1ccbSHans Petter Selasky u64 in_param, 231*33ec1ccbSHans Petter Selasky u64 out_param, 232*33ec1ccbSHans Petter Selasky u32 in_modifier, 233*33ec1ccbSHans Petter Selasky u8 op_modifier, 234*33ec1ccbSHans Petter Selasky u16 op, 235*33ec1ccbSHans Petter Selasky u16 token, 236*33ec1ccbSHans Petter Selasky int event) 237*33ec1ccbSHans Petter Selasky { 238*33ec1ccbSHans Petter Selasky if (event) { 239*33ec1ccbSHans Petter Selasky unsigned long end = jiffies + GO_BIT_TIMEOUT; 240*33ec1ccbSHans Petter Selasky 241*33ec1ccbSHans Petter Selasky while (go_bit(dev) && time_before(jiffies, end)) { 242*33ec1ccbSHans Petter Selasky set_current_state(TASK_RUNNING); 243*33ec1ccbSHans Petter Selasky schedule(); 244*33ec1ccbSHans Petter Selasky } 245*33ec1ccbSHans Petter Selasky } 246*33ec1ccbSHans Petter Selasky 247*33ec1ccbSHans Petter Selasky if (go_bit(dev)) 248*33ec1ccbSHans Petter Selasky return -EAGAIN; 249*33ec1ccbSHans Petter Selasky 250*33ec1ccbSHans Petter Selasky /* 251*33ec1ccbSHans Petter Selasky * We use writel (instead of something like memcpy_toio) 252*33ec1ccbSHans Petter Selasky * because writes of less than 32 bits to the HCR don't work 253*33ec1ccbSHans Petter Selasky * (and some architectures such as ia64 implement memcpy_toio 254*33ec1ccbSHans Petter Selasky * in terms of writeb). 255*33ec1ccbSHans Petter Selasky */ 256*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32(in_param >> 32), dev->hcr + 0 * 4); 257*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful), dev->hcr + 1 * 4); 258*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32(in_modifier), dev->hcr + 2 * 4); 259*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32(out_param >> 32), dev->hcr + 3 * 4); 260*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), dev->hcr + 4 * 4); 261*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32(token << 16), dev->hcr + 5 * 4); 262*33ec1ccbSHans Petter Selasky 263*33ec1ccbSHans Petter Selasky /* __raw_writel may not order writes. */ 264*33ec1ccbSHans Petter Selasky wmb(); 265*33ec1ccbSHans Petter Selasky 266*33ec1ccbSHans Petter Selasky __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) | 267*33ec1ccbSHans Petter Selasky (event ? (1 << HCA_E_BIT) : 0) | 268*33ec1ccbSHans Petter Selasky (op_modifier << HCR_OPMOD_SHIFT) | 269*33ec1ccbSHans Petter Selasky op), dev->hcr + 6 * 4); 270*33ec1ccbSHans Petter Selasky 271*33ec1ccbSHans Petter Selasky return 0; 272*33ec1ccbSHans Petter Selasky } 273*33ec1ccbSHans Petter Selasky 274*33ec1ccbSHans Petter Selasky static int mthca_cmd_post(struct mthca_dev *dev, 275*33ec1ccbSHans Petter Selasky u64 in_param, 276*33ec1ccbSHans Petter Selasky u64 out_param, 277*33ec1ccbSHans Petter Selasky u32 in_modifier, 278*33ec1ccbSHans Petter Selasky u8 op_modifier, 279*33ec1ccbSHans Petter Selasky u16 op, 280*33ec1ccbSHans Petter Selasky u16 token, 281*33ec1ccbSHans Petter Selasky int event) 282*33ec1ccbSHans Petter Selasky { 283*33ec1ccbSHans Petter Selasky int err = 0; 284*33ec1ccbSHans Petter Selasky 285*33ec1ccbSHans Petter Selasky mutex_lock(&dev->cmd.hcr_mutex); 286*33ec1ccbSHans Petter Selasky 287*33ec1ccbSHans Petter Selasky if (event && dev->cmd.flags & MTHCA_CMD_POST_DOORBELLS && fw_cmd_doorbell) 288*33ec1ccbSHans Petter Selasky mthca_cmd_post_dbell(dev, in_param, out_param, in_modifier, 289*33ec1ccbSHans Petter Selasky op_modifier, op, token); 290*33ec1ccbSHans Petter Selasky else 291*33ec1ccbSHans Petter Selasky err = mthca_cmd_post_hcr(dev, in_param, out_param, in_modifier, 292*33ec1ccbSHans Petter Selasky op_modifier, op, token, event); 293*33ec1ccbSHans Petter Selasky 294*33ec1ccbSHans Petter Selasky /* 295*33ec1ccbSHans Petter Selasky * Make sure that our HCR writes don't get mixed in with 296*33ec1ccbSHans Petter Selasky * writes from another CPU starting a FW command. 297*33ec1ccbSHans Petter Selasky */ 298*33ec1ccbSHans Petter Selasky mmiowb(); 299*33ec1ccbSHans Petter Selasky 300*33ec1ccbSHans Petter Selasky mutex_unlock(&dev->cmd.hcr_mutex); 301*33ec1ccbSHans Petter Selasky return err; 302*33ec1ccbSHans Petter Selasky } 303*33ec1ccbSHans Petter Selasky 304*33ec1ccbSHans Petter Selasky 305*33ec1ccbSHans Petter Selasky static int mthca_status_to_errno(u8 status) 306*33ec1ccbSHans Petter Selasky { 307*33ec1ccbSHans Petter Selasky static const int trans_table[] = { 308*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_INTERNAL_ERR] = -EIO, 309*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_BAD_OP] = -EPERM, 310*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_BAD_PARAM] = -EINVAL, 311*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_BAD_SYS_STATE] = -ENXIO, 312*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_BAD_RESOURCE] = -EBADF, 313*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_RESOURCE_BUSY] = -EBUSY, 314*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_DDR_MEM_ERR] = -ENOMEM, 315*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_EXCEED_LIM] = -ENOMEM, 316*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_BAD_RES_STATE] = -EBADF, 317*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_BAD_INDEX] = -EBADF, 318*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_BAD_NVMEM] = -EFAULT, 319*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_BAD_QPEE_STATE] = -EINVAL, 320*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_BAD_SEG_PARAM] = -EFAULT, 321*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_REG_BOUND] = -EBUSY, 322*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_LAM_NOT_PRE] = -EAGAIN, 323*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_BAD_PKT] = -EBADMSG, 324*33ec1ccbSHans Petter Selasky [MTHCA_CMD_STAT_BAD_SIZE] = -ENOMEM, 325*33ec1ccbSHans Petter Selasky }; 326*33ec1ccbSHans Petter Selasky 327*33ec1ccbSHans Petter Selasky if (status >= ARRAY_SIZE(trans_table) || 328*33ec1ccbSHans Petter Selasky (status != MTHCA_CMD_STAT_OK 329*33ec1ccbSHans Petter Selasky && trans_table[status] == 0)) 330*33ec1ccbSHans Petter Selasky return -EINVAL; 331*33ec1ccbSHans Petter Selasky 332*33ec1ccbSHans Petter Selasky return trans_table[status]; 333*33ec1ccbSHans Petter Selasky } 334*33ec1ccbSHans Petter Selasky 335*33ec1ccbSHans Petter Selasky 336*33ec1ccbSHans Petter Selasky static int mthca_cmd_poll(struct mthca_dev *dev, 337*33ec1ccbSHans Petter Selasky u64 in_param, 338*33ec1ccbSHans Petter Selasky u64 *out_param, 339*33ec1ccbSHans Petter Selasky int out_is_imm, 340*33ec1ccbSHans Petter Selasky u32 in_modifier, 341*33ec1ccbSHans Petter Selasky u8 op_modifier, 342*33ec1ccbSHans Petter Selasky u16 op, 343*33ec1ccbSHans Petter Selasky unsigned long timeout) 344*33ec1ccbSHans Petter Selasky { 345*33ec1ccbSHans Petter Selasky int err = 0; 346*33ec1ccbSHans Petter Selasky unsigned long end; 347*33ec1ccbSHans Petter Selasky u8 status; 348*33ec1ccbSHans Petter Selasky 349*33ec1ccbSHans Petter Selasky down(&dev->cmd.poll_sem); 350*33ec1ccbSHans Petter Selasky 351*33ec1ccbSHans Petter Selasky err = mthca_cmd_post(dev, in_param, 352*33ec1ccbSHans Petter Selasky out_param ? *out_param : 0, 353*33ec1ccbSHans Petter Selasky in_modifier, op_modifier, 354*33ec1ccbSHans Petter Selasky op, CMD_POLL_TOKEN, 0); 355*33ec1ccbSHans Petter Selasky if (err) 356*33ec1ccbSHans Petter Selasky goto out; 357*33ec1ccbSHans Petter Selasky 358*33ec1ccbSHans Petter Selasky end = timeout + jiffies; 359*33ec1ccbSHans Petter Selasky while (go_bit(dev) && time_before(jiffies, end)) { 360*33ec1ccbSHans Petter Selasky set_current_state(TASK_RUNNING); 361*33ec1ccbSHans Petter Selasky schedule(); 362*33ec1ccbSHans Petter Selasky } 363*33ec1ccbSHans Petter Selasky 364*33ec1ccbSHans Petter Selasky if (go_bit(dev)) { 365*33ec1ccbSHans Petter Selasky err = -EBUSY; 366*33ec1ccbSHans Petter Selasky goto out; 367*33ec1ccbSHans Petter Selasky } 368*33ec1ccbSHans Petter Selasky 369*33ec1ccbSHans Petter Selasky if (out_is_imm) 370*33ec1ccbSHans Petter Selasky *out_param = 371*33ec1ccbSHans Petter Selasky (u64) be32_to_cpu((__force __be32) 372*33ec1ccbSHans Petter Selasky __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET)) << 32 | 373*33ec1ccbSHans Petter Selasky (u64) be32_to_cpu((__force __be32) 374*33ec1ccbSHans Petter Selasky __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET + 4)); 375*33ec1ccbSHans Petter Selasky 376*33ec1ccbSHans Petter Selasky status = be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24; 377*33ec1ccbSHans Petter Selasky if (status) { 378*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Command %02x completed with status %02x\n", 379*33ec1ccbSHans Petter Selasky op, status); 380*33ec1ccbSHans Petter Selasky err = mthca_status_to_errno(status); 381*33ec1ccbSHans Petter Selasky } 382*33ec1ccbSHans Petter Selasky 383*33ec1ccbSHans Petter Selasky out: 384*33ec1ccbSHans Petter Selasky up(&dev->cmd.poll_sem); 385*33ec1ccbSHans Petter Selasky return err; 386*33ec1ccbSHans Petter Selasky } 387*33ec1ccbSHans Petter Selasky 388*33ec1ccbSHans Petter Selasky void mthca_cmd_event(struct mthca_dev *dev, 389*33ec1ccbSHans Petter Selasky u16 token, 390*33ec1ccbSHans Petter Selasky u8 status, 391*33ec1ccbSHans Petter Selasky u64 out_param) 392*33ec1ccbSHans Petter Selasky { 393*33ec1ccbSHans Petter Selasky struct mthca_cmd_context *context = 394*33ec1ccbSHans Petter Selasky &dev->cmd.context[token & dev->cmd.token_mask]; 395*33ec1ccbSHans Petter Selasky 396*33ec1ccbSHans Petter Selasky /* previously timed out command completing at long last */ 397*33ec1ccbSHans Petter Selasky if (token != context->token) 398*33ec1ccbSHans Petter Selasky return; 399*33ec1ccbSHans Petter Selasky 400*33ec1ccbSHans Petter Selasky context->result = 0; 401*33ec1ccbSHans Petter Selasky context->status = status; 402*33ec1ccbSHans Petter Selasky context->out_param = out_param; 403*33ec1ccbSHans Petter Selasky 404*33ec1ccbSHans Petter Selasky complete(&context->done); 405*33ec1ccbSHans Petter Selasky } 406*33ec1ccbSHans Petter Selasky 407*33ec1ccbSHans Petter Selasky static int mthca_cmd_wait(struct mthca_dev *dev, 408*33ec1ccbSHans Petter Selasky u64 in_param, 409*33ec1ccbSHans Petter Selasky u64 *out_param, 410*33ec1ccbSHans Petter Selasky int out_is_imm, 411*33ec1ccbSHans Petter Selasky u32 in_modifier, 412*33ec1ccbSHans Petter Selasky u8 op_modifier, 413*33ec1ccbSHans Petter Selasky u16 op, 414*33ec1ccbSHans Petter Selasky unsigned long timeout) 415*33ec1ccbSHans Petter Selasky { 416*33ec1ccbSHans Petter Selasky int err = 0; 417*33ec1ccbSHans Petter Selasky struct mthca_cmd_context *context; 418*33ec1ccbSHans Petter Selasky 419*33ec1ccbSHans Petter Selasky down(&dev->cmd.event_sem); 420*33ec1ccbSHans Petter Selasky 421*33ec1ccbSHans Petter Selasky spin_lock(&dev->cmd.context_lock); 422*33ec1ccbSHans Petter Selasky BUG_ON(dev->cmd.free_head < 0); 423*33ec1ccbSHans Petter Selasky context = &dev->cmd.context[dev->cmd.free_head]; 424*33ec1ccbSHans Petter Selasky context->token += dev->cmd.token_mask + 1; 425*33ec1ccbSHans Petter Selasky dev->cmd.free_head = context->next; 426*33ec1ccbSHans Petter Selasky spin_unlock(&dev->cmd.context_lock); 427*33ec1ccbSHans Petter Selasky 428*33ec1ccbSHans Petter Selasky init_completion(&context->done); 429*33ec1ccbSHans Petter Selasky 430*33ec1ccbSHans Petter Selasky err = mthca_cmd_post(dev, in_param, 431*33ec1ccbSHans Petter Selasky out_param ? *out_param : 0, 432*33ec1ccbSHans Petter Selasky in_modifier, op_modifier, 433*33ec1ccbSHans Petter Selasky op, context->token, 1); 434*33ec1ccbSHans Petter Selasky if (err) 435*33ec1ccbSHans Petter Selasky goto out; 436*33ec1ccbSHans Petter Selasky 437*33ec1ccbSHans Petter Selasky if (!wait_for_completion_timeout(&context->done, timeout)) { 438*33ec1ccbSHans Petter Selasky err = -EBUSY; 439*33ec1ccbSHans Petter Selasky goto out; 440*33ec1ccbSHans Petter Selasky } 441*33ec1ccbSHans Petter Selasky 442*33ec1ccbSHans Petter Selasky err = context->result; 443*33ec1ccbSHans Petter Selasky if (err) 444*33ec1ccbSHans Petter Selasky goto out; 445*33ec1ccbSHans Petter Selasky 446*33ec1ccbSHans Petter Selasky if (context->status) { 447*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Command %02x completed with status %02x\n", 448*33ec1ccbSHans Petter Selasky op, context->status); 449*33ec1ccbSHans Petter Selasky err = mthca_status_to_errno(context->status); 450*33ec1ccbSHans Petter Selasky } 451*33ec1ccbSHans Petter Selasky 452*33ec1ccbSHans Petter Selasky if (out_is_imm) 453*33ec1ccbSHans Petter Selasky *out_param = context->out_param; 454*33ec1ccbSHans Petter Selasky 455*33ec1ccbSHans Petter Selasky out: 456*33ec1ccbSHans Petter Selasky spin_lock(&dev->cmd.context_lock); 457*33ec1ccbSHans Petter Selasky context->next = dev->cmd.free_head; 458*33ec1ccbSHans Petter Selasky dev->cmd.free_head = context - dev->cmd.context; 459*33ec1ccbSHans Petter Selasky spin_unlock(&dev->cmd.context_lock); 460*33ec1ccbSHans Petter Selasky 461*33ec1ccbSHans Petter Selasky up(&dev->cmd.event_sem); 462*33ec1ccbSHans Petter Selasky return err; 463*33ec1ccbSHans Petter Selasky } 464*33ec1ccbSHans Petter Selasky 465*33ec1ccbSHans Petter Selasky /* Invoke a command with an output mailbox */ 466*33ec1ccbSHans Petter Selasky static int mthca_cmd_box(struct mthca_dev *dev, 467*33ec1ccbSHans Petter Selasky u64 in_param, 468*33ec1ccbSHans Petter Selasky u64 out_param, 469*33ec1ccbSHans Petter Selasky u32 in_modifier, 470*33ec1ccbSHans Petter Selasky u8 op_modifier, 471*33ec1ccbSHans Petter Selasky u16 op, 472*33ec1ccbSHans Petter Selasky unsigned long timeout) 473*33ec1ccbSHans Petter Selasky { 474*33ec1ccbSHans Petter Selasky if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS) 475*33ec1ccbSHans Petter Selasky return mthca_cmd_wait(dev, in_param, &out_param, 0, 476*33ec1ccbSHans Petter Selasky in_modifier, op_modifier, op, 477*33ec1ccbSHans Petter Selasky timeout); 478*33ec1ccbSHans Petter Selasky else 479*33ec1ccbSHans Petter Selasky return mthca_cmd_poll(dev, in_param, &out_param, 0, 480*33ec1ccbSHans Petter Selasky in_modifier, op_modifier, op, 481*33ec1ccbSHans Petter Selasky timeout); 482*33ec1ccbSHans Petter Selasky } 483*33ec1ccbSHans Petter Selasky 484*33ec1ccbSHans Petter Selasky /* Invoke a command with no output parameter */ 485*33ec1ccbSHans Petter Selasky static int mthca_cmd(struct mthca_dev *dev, 486*33ec1ccbSHans Petter Selasky u64 in_param, 487*33ec1ccbSHans Petter Selasky u32 in_modifier, 488*33ec1ccbSHans Petter Selasky u8 op_modifier, 489*33ec1ccbSHans Petter Selasky u16 op, 490*33ec1ccbSHans Petter Selasky unsigned long timeout) 491*33ec1ccbSHans Petter Selasky { 492*33ec1ccbSHans Petter Selasky return mthca_cmd_box(dev, in_param, 0, in_modifier, 493*33ec1ccbSHans Petter Selasky op_modifier, op, timeout); 494*33ec1ccbSHans Petter Selasky } 495*33ec1ccbSHans Petter Selasky 496*33ec1ccbSHans Petter Selasky /* 497*33ec1ccbSHans Petter Selasky * Invoke a command with an immediate output parameter (and copy the 498*33ec1ccbSHans Petter Selasky * output into the caller's out_param pointer after the command 499*33ec1ccbSHans Petter Selasky * executes). 500*33ec1ccbSHans Petter Selasky */ 501*33ec1ccbSHans Petter Selasky static int mthca_cmd_imm(struct mthca_dev *dev, 502*33ec1ccbSHans Petter Selasky u64 in_param, 503*33ec1ccbSHans Petter Selasky u64 *out_param, 504*33ec1ccbSHans Petter Selasky u32 in_modifier, 505*33ec1ccbSHans Petter Selasky u8 op_modifier, 506*33ec1ccbSHans Petter Selasky u16 op, 507*33ec1ccbSHans Petter Selasky unsigned long timeout) 508*33ec1ccbSHans Petter Selasky { 509*33ec1ccbSHans Petter Selasky if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS) 510*33ec1ccbSHans Petter Selasky return mthca_cmd_wait(dev, in_param, out_param, 1, 511*33ec1ccbSHans Petter Selasky in_modifier, op_modifier, op, 512*33ec1ccbSHans Petter Selasky timeout); 513*33ec1ccbSHans Petter Selasky else 514*33ec1ccbSHans Petter Selasky return mthca_cmd_poll(dev, in_param, out_param, 1, 515*33ec1ccbSHans Petter Selasky in_modifier, op_modifier, op, 516*33ec1ccbSHans Petter Selasky timeout); 517*33ec1ccbSHans Petter Selasky } 518*33ec1ccbSHans Petter Selasky 519*33ec1ccbSHans Petter Selasky int mthca_cmd_init(struct mthca_dev *dev) 520*33ec1ccbSHans Petter Selasky { 521*33ec1ccbSHans Petter Selasky mutex_init(&dev->cmd.hcr_mutex); 522*33ec1ccbSHans Petter Selasky sema_init(&dev->cmd.poll_sem, 1); 523*33ec1ccbSHans Petter Selasky dev->cmd.flags = 0; 524*33ec1ccbSHans Petter Selasky 525*33ec1ccbSHans Petter Selasky dev->hcr = ioremap(pci_resource_start(dev->pdev, 0) + MTHCA_HCR_BASE, 526*33ec1ccbSHans Petter Selasky MTHCA_HCR_SIZE); 527*33ec1ccbSHans Petter Selasky if (!dev->hcr) { 528*33ec1ccbSHans Petter Selasky mthca_err(dev, "Couldn't map command register."); 529*33ec1ccbSHans Petter Selasky return -ENOMEM; 530*33ec1ccbSHans Petter Selasky } 531*33ec1ccbSHans Petter Selasky 532*33ec1ccbSHans Petter Selasky dev->cmd.pool = pci_pool_create("mthca_cmd", dev->pdev, 533*33ec1ccbSHans Petter Selasky MTHCA_MAILBOX_SIZE, 534*33ec1ccbSHans Petter Selasky MTHCA_MAILBOX_SIZE, 0); 535*33ec1ccbSHans Petter Selasky if (!dev->cmd.pool) { 536*33ec1ccbSHans Petter Selasky iounmap(dev->hcr); 537*33ec1ccbSHans Petter Selasky return -ENOMEM; 538*33ec1ccbSHans Petter Selasky } 539*33ec1ccbSHans Petter Selasky 540*33ec1ccbSHans Petter Selasky return 0; 541*33ec1ccbSHans Petter Selasky } 542*33ec1ccbSHans Petter Selasky 543*33ec1ccbSHans Petter Selasky void mthca_cmd_cleanup(struct mthca_dev *dev) 544*33ec1ccbSHans Petter Selasky { 545*33ec1ccbSHans Petter Selasky pci_pool_destroy(dev->cmd.pool); 546*33ec1ccbSHans Petter Selasky iounmap(dev->hcr); 547*33ec1ccbSHans Petter Selasky if (dev->cmd.flags & MTHCA_CMD_POST_DOORBELLS) 548*33ec1ccbSHans Petter Selasky iounmap(dev->cmd.dbell_map); 549*33ec1ccbSHans Petter Selasky } 550*33ec1ccbSHans Petter Selasky 551*33ec1ccbSHans Petter Selasky /* 552*33ec1ccbSHans Petter Selasky * Switch to using events to issue FW commands (should be called after 553*33ec1ccbSHans Petter Selasky * event queue to command events has been initialized). 554*33ec1ccbSHans Petter Selasky */ 555*33ec1ccbSHans Petter Selasky int mthca_cmd_use_events(struct mthca_dev *dev) 556*33ec1ccbSHans Petter Selasky { 557*33ec1ccbSHans Petter Selasky int i; 558*33ec1ccbSHans Petter Selasky 559*33ec1ccbSHans Petter Selasky dev->cmd.context = kmalloc(dev->cmd.max_cmds * 560*33ec1ccbSHans Petter Selasky sizeof (struct mthca_cmd_context), 561*33ec1ccbSHans Petter Selasky GFP_KERNEL); 562*33ec1ccbSHans Petter Selasky if (!dev->cmd.context) 563*33ec1ccbSHans Petter Selasky return -ENOMEM; 564*33ec1ccbSHans Petter Selasky 565*33ec1ccbSHans Petter Selasky for (i = 0; i < dev->cmd.max_cmds; ++i) { 566*33ec1ccbSHans Petter Selasky dev->cmd.context[i].token = i; 567*33ec1ccbSHans Petter Selasky dev->cmd.context[i].next = i + 1; 568*33ec1ccbSHans Petter Selasky } 569*33ec1ccbSHans Petter Selasky 570*33ec1ccbSHans Petter Selasky dev->cmd.context[dev->cmd.max_cmds - 1].next = -1; 571*33ec1ccbSHans Petter Selasky dev->cmd.free_head = 0; 572*33ec1ccbSHans Petter Selasky 573*33ec1ccbSHans Petter Selasky sema_init(&dev->cmd.event_sem, dev->cmd.max_cmds); 574*33ec1ccbSHans Petter Selasky spin_lock_init(&dev->cmd.context_lock); 575*33ec1ccbSHans Petter Selasky 576*33ec1ccbSHans Petter Selasky for (dev->cmd.token_mask = 1; 577*33ec1ccbSHans Petter Selasky dev->cmd.token_mask < dev->cmd.max_cmds; 578*33ec1ccbSHans Petter Selasky dev->cmd.token_mask <<= 1) 579*33ec1ccbSHans Petter Selasky ; /* nothing */ 580*33ec1ccbSHans Petter Selasky --dev->cmd.token_mask; 581*33ec1ccbSHans Petter Selasky 582*33ec1ccbSHans Petter Selasky dev->cmd.flags |= MTHCA_CMD_USE_EVENTS; 583*33ec1ccbSHans Petter Selasky 584*33ec1ccbSHans Petter Selasky down(&dev->cmd.poll_sem); 585*33ec1ccbSHans Petter Selasky 586*33ec1ccbSHans Petter Selasky return 0; 587*33ec1ccbSHans Petter Selasky } 588*33ec1ccbSHans Petter Selasky 589*33ec1ccbSHans Petter Selasky /* 590*33ec1ccbSHans Petter Selasky * Switch back to polling (used when shutting down the device) 591*33ec1ccbSHans Petter Selasky */ 592*33ec1ccbSHans Petter Selasky void mthca_cmd_use_polling(struct mthca_dev *dev) 593*33ec1ccbSHans Petter Selasky { 594*33ec1ccbSHans Petter Selasky int i; 595*33ec1ccbSHans Petter Selasky 596*33ec1ccbSHans Petter Selasky dev->cmd.flags &= ~MTHCA_CMD_USE_EVENTS; 597*33ec1ccbSHans Petter Selasky 598*33ec1ccbSHans Petter Selasky for (i = 0; i < dev->cmd.max_cmds; ++i) 599*33ec1ccbSHans Petter Selasky down(&dev->cmd.event_sem); 600*33ec1ccbSHans Petter Selasky 601*33ec1ccbSHans Petter Selasky kfree(dev->cmd.context); 602*33ec1ccbSHans Petter Selasky 603*33ec1ccbSHans Petter Selasky up(&dev->cmd.poll_sem); 604*33ec1ccbSHans Petter Selasky } 605*33ec1ccbSHans Petter Selasky 606*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev, 607*33ec1ccbSHans Petter Selasky gfp_t gfp_mask) 608*33ec1ccbSHans Petter Selasky { 609*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox; 610*33ec1ccbSHans Petter Selasky 611*33ec1ccbSHans Petter Selasky mailbox = kmalloc(sizeof *mailbox, gfp_mask); 612*33ec1ccbSHans Petter Selasky if (!mailbox) 613*33ec1ccbSHans Petter Selasky return ERR_PTR(-ENOMEM); 614*33ec1ccbSHans Petter Selasky 615*33ec1ccbSHans Petter Selasky mailbox->buf = pci_pool_alloc(dev->cmd.pool, gfp_mask, &mailbox->dma); 616*33ec1ccbSHans Petter Selasky if (!mailbox->buf) { 617*33ec1ccbSHans Petter Selasky kfree(mailbox); 618*33ec1ccbSHans Petter Selasky return ERR_PTR(-ENOMEM); 619*33ec1ccbSHans Petter Selasky } 620*33ec1ccbSHans Petter Selasky 621*33ec1ccbSHans Petter Selasky return mailbox; 622*33ec1ccbSHans Petter Selasky } 623*33ec1ccbSHans Petter Selasky 624*33ec1ccbSHans Petter Selasky void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox) 625*33ec1ccbSHans Petter Selasky { 626*33ec1ccbSHans Petter Selasky if (!mailbox) 627*33ec1ccbSHans Petter Selasky return; 628*33ec1ccbSHans Petter Selasky 629*33ec1ccbSHans Petter Selasky pci_pool_free(dev->cmd.pool, mailbox->buf, mailbox->dma); 630*33ec1ccbSHans Petter Selasky kfree(mailbox); 631*33ec1ccbSHans Petter Selasky } 632*33ec1ccbSHans Petter Selasky 633*33ec1ccbSHans Petter Selasky int mthca_SYS_EN(struct mthca_dev *dev) 634*33ec1ccbSHans Petter Selasky { 635*33ec1ccbSHans Petter Selasky u64 out; 636*33ec1ccbSHans Petter Selasky int ret; 637*33ec1ccbSHans Petter Selasky 638*33ec1ccbSHans Petter Selasky ret = mthca_cmd_imm(dev, 0, &out, 0, 0, CMD_SYS_EN, CMD_TIME_CLASS_D); 639*33ec1ccbSHans Petter Selasky 640*33ec1ccbSHans Petter Selasky if (ret == -ENOMEM) 641*33ec1ccbSHans Petter Selasky mthca_warn(dev, "SYS_EN DDR error: syn=%x, sock=%d, " 642*33ec1ccbSHans Petter Selasky "sladdr=%d, SPD source=%s\n", 643*33ec1ccbSHans Petter Selasky (int) (out >> 6) & 0xf, (int) (out >> 4) & 3, 644*33ec1ccbSHans Petter Selasky (int) (out >> 1) & 7, (int) out & 1 ? "NVMEM" : "DIMM"); 645*33ec1ccbSHans Petter Selasky 646*33ec1ccbSHans Petter Selasky return ret; 647*33ec1ccbSHans Petter Selasky } 648*33ec1ccbSHans Petter Selasky 649*33ec1ccbSHans Petter Selasky int mthca_SYS_DIS(struct mthca_dev *dev) 650*33ec1ccbSHans Petter Selasky { 651*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C); 652*33ec1ccbSHans Petter Selasky } 653*33ec1ccbSHans Petter Selasky 654*33ec1ccbSHans Petter Selasky static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, 655*33ec1ccbSHans Petter Selasky u64 virt) 656*33ec1ccbSHans Petter Selasky { 657*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox; 658*33ec1ccbSHans Petter Selasky struct mthca_icm_iter iter; 659*33ec1ccbSHans Petter Selasky __be64 *pages; 660*33ec1ccbSHans Petter Selasky int lg; 661*33ec1ccbSHans Petter Selasky int nent = 0; 662*33ec1ccbSHans Petter Selasky int i; 663*33ec1ccbSHans Petter Selasky int err = 0; 664*33ec1ccbSHans Petter Selasky int ts = 0, tc = 0; 665*33ec1ccbSHans Petter Selasky 666*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 667*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox)) 668*33ec1ccbSHans Petter Selasky return PTR_ERR(mailbox); 669*33ec1ccbSHans Petter Selasky memset(mailbox->buf, 0, MTHCA_MAILBOX_SIZE); 670*33ec1ccbSHans Petter Selasky pages = mailbox->buf; 671*33ec1ccbSHans Petter Selasky 672*33ec1ccbSHans Petter Selasky for (mthca_icm_first(icm, &iter); 673*33ec1ccbSHans Petter Selasky !mthca_icm_last(&iter); 674*33ec1ccbSHans Petter Selasky mthca_icm_next(&iter)) { 675*33ec1ccbSHans Petter Selasky /* 676*33ec1ccbSHans Petter Selasky * We have to pass pages that are aligned to their 677*33ec1ccbSHans Petter Selasky * size, so find the least significant 1 in the 678*33ec1ccbSHans Petter Selasky * address or size and use that as our log2 size. 679*33ec1ccbSHans Petter Selasky */ 680*33ec1ccbSHans Petter Selasky lg = ffs(mthca_icm_addr(&iter) | mthca_icm_size(&iter)) - 1; 681*33ec1ccbSHans Petter Selasky if (lg < MTHCA_ICM_PAGE_SHIFT) { 682*33ec1ccbSHans Petter Selasky mthca_warn(dev, "Got FW area not aligned to %d (%llx/%lx).\n", 683*33ec1ccbSHans Petter Selasky MTHCA_ICM_PAGE_SIZE, 684*33ec1ccbSHans Petter Selasky (unsigned long long) mthca_icm_addr(&iter), 685*33ec1ccbSHans Petter Selasky mthca_icm_size(&iter)); 686*33ec1ccbSHans Petter Selasky err = -EINVAL; 687*33ec1ccbSHans Petter Selasky goto out; 688*33ec1ccbSHans Petter Selasky } 689*33ec1ccbSHans Petter Selasky for (i = 0; i < mthca_icm_size(&iter) >> lg; ++i) { 690*33ec1ccbSHans Petter Selasky if (virt != -1) { 691*33ec1ccbSHans Petter Selasky pages[nent * 2] = cpu_to_be64(virt); 692*33ec1ccbSHans Petter Selasky virt += 1 << lg; 693*33ec1ccbSHans Petter Selasky } 694*33ec1ccbSHans Petter Selasky 695*33ec1ccbSHans Petter Selasky pages[nent * 2 + 1] = 696*33ec1ccbSHans Petter Selasky cpu_to_be64((mthca_icm_addr(&iter) + (i << lg)) | 697*33ec1ccbSHans Petter Selasky (lg - MTHCA_ICM_PAGE_SHIFT)); 698*33ec1ccbSHans Petter Selasky ts += 1 << (lg - 10); 699*33ec1ccbSHans Petter Selasky ++tc; 700*33ec1ccbSHans Petter Selasky 701*33ec1ccbSHans Petter Selasky if (++nent == MTHCA_MAILBOX_SIZE / 16) { 702*33ec1ccbSHans Petter Selasky err = mthca_cmd(dev, mailbox->dma, nent, 0, op, 703*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_B); 704*33ec1ccbSHans Petter Selasky if (err) 705*33ec1ccbSHans Petter Selasky goto out; 706*33ec1ccbSHans Petter Selasky nent = 0; 707*33ec1ccbSHans Petter Selasky } 708*33ec1ccbSHans Petter Selasky } 709*33ec1ccbSHans Petter Selasky } 710*33ec1ccbSHans Petter Selasky 711*33ec1ccbSHans Petter Selasky if (nent) 712*33ec1ccbSHans Petter Selasky err = mthca_cmd(dev, mailbox->dma, nent, 0, op, 713*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_B); 714*33ec1ccbSHans Petter Selasky 715*33ec1ccbSHans Petter Selasky switch (op) { 716*33ec1ccbSHans Petter Selasky case CMD_MAP_FA: 717*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Mapped %d chunks/%d KB for FW.\n", tc, ts); 718*33ec1ccbSHans Petter Selasky break; 719*33ec1ccbSHans Petter Selasky case CMD_MAP_ICM_AUX: 720*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Mapped %d chunks/%d KB for ICM aux.\n", tc, ts); 721*33ec1ccbSHans Petter Selasky break; 722*33ec1ccbSHans Petter Selasky case CMD_MAP_ICM: 723*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Mapped %d chunks/%d KB at %llx for ICM.\n", 724*33ec1ccbSHans Petter Selasky tc, ts, (unsigned long long) virt - (ts << 10)); 725*33ec1ccbSHans Petter Selasky break; 726*33ec1ccbSHans Petter Selasky } 727*33ec1ccbSHans Petter Selasky 728*33ec1ccbSHans Petter Selasky out: 729*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox); 730*33ec1ccbSHans Petter Selasky return err; 731*33ec1ccbSHans Petter Selasky } 732*33ec1ccbSHans Petter Selasky 733*33ec1ccbSHans Petter Selasky int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm) 734*33ec1ccbSHans Petter Selasky { 735*33ec1ccbSHans Petter Selasky return mthca_map_cmd(dev, CMD_MAP_FA, icm, -1); 736*33ec1ccbSHans Petter Selasky } 737*33ec1ccbSHans Petter Selasky 738*33ec1ccbSHans Petter Selasky int mthca_UNMAP_FA(struct mthca_dev *dev) 739*33ec1ccbSHans Petter Selasky { 740*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_FA, CMD_TIME_CLASS_B); 741*33ec1ccbSHans Petter Selasky } 742*33ec1ccbSHans Petter Selasky 743*33ec1ccbSHans Petter Selasky int mthca_RUN_FW(struct mthca_dev *dev) 744*33ec1ccbSHans Petter Selasky { 745*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, 0, 0, 0, CMD_RUN_FW, CMD_TIME_CLASS_A); 746*33ec1ccbSHans Petter Selasky } 747*33ec1ccbSHans Petter Selasky 748*33ec1ccbSHans Petter Selasky static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base) 749*33ec1ccbSHans Petter Selasky { 750*33ec1ccbSHans Petter Selasky phys_addr_t addr; 751*33ec1ccbSHans Petter Selasky u16 max_off = 0; 752*33ec1ccbSHans Petter Selasky int i; 753*33ec1ccbSHans Petter Selasky 754*33ec1ccbSHans Petter Selasky for (i = 0; i < 8; ++i) 755*33ec1ccbSHans Petter Selasky max_off = max(max_off, dev->cmd.dbell_offsets[i]); 756*33ec1ccbSHans Petter Selasky 757*33ec1ccbSHans Petter Selasky if ((base & PAGE_MASK) != ((base + max_off) & PAGE_MASK)) { 758*33ec1ccbSHans Petter Selasky mthca_warn(dev, "Firmware doorbell region at 0x%016llx, " 759*33ec1ccbSHans Petter Selasky "length 0x%x crosses a page boundary\n", 760*33ec1ccbSHans Petter Selasky (unsigned long long) base, max_off); 761*33ec1ccbSHans Petter Selasky return; 762*33ec1ccbSHans Petter Selasky } 763*33ec1ccbSHans Petter Selasky 764*33ec1ccbSHans Petter Selasky addr = pci_resource_start(dev->pdev, 2) + 765*33ec1ccbSHans Petter Selasky ((pci_resource_len(dev->pdev, 2) - 1) & base); 766*33ec1ccbSHans Petter Selasky dev->cmd.dbell_map = ioremap(addr, max_off + sizeof(u32)); 767*33ec1ccbSHans Petter Selasky if (!dev->cmd.dbell_map) 768*33ec1ccbSHans Petter Selasky return; 769*33ec1ccbSHans Petter Selasky 770*33ec1ccbSHans Petter Selasky dev->cmd.flags |= MTHCA_CMD_POST_DOORBELLS; 771*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Mapped doorbell page for posting FW commands\n"); 772*33ec1ccbSHans Petter Selasky } 773*33ec1ccbSHans Petter Selasky 774*33ec1ccbSHans Petter Selasky int mthca_QUERY_FW(struct mthca_dev *dev) 775*33ec1ccbSHans Petter Selasky { 776*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox; 777*33ec1ccbSHans Petter Selasky u32 *outbox; 778*33ec1ccbSHans Petter Selasky u64 base; 779*33ec1ccbSHans Petter Selasky u32 tmp; 780*33ec1ccbSHans Petter Selasky int err = 0; 781*33ec1ccbSHans Petter Selasky u8 lg; 782*33ec1ccbSHans Petter Selasky int i; 783*33ec1ccbSHans Petter Selasky 784*33ec1ccbSHans Petter Selasky #define QUERY_FW_OUT_SIZE 0x100 785*33ec1ccbSHans Petter Selasky #define QUERY_FW_VER_OFFSET 0x00 786*33ec1ccbSHans Petter Selasky #define QUERY_FW_MAX_CMD_OFFSET 0x0f 787*33ec1ccbSHans Petter Selasky #define QUERY_FW_ERR_START_OFFSET 0x30 788*33ec1ccbSHans Petter Selasky #define QUERY_FW_ERR_SIZE_OFFSET 0x38 789*33ec1ccbSHans Petter Selasky 790*33ec1ccbSHans Petter Selasky #define QUERY_FW_CMD_DB_EN_OFFSET 0x10 791*33ec1ccbSHans Petter Selasky #define QUERY_FW_CMD_DB_OFFSET 0x50 792*33ec1ccbSHans Petter Selasky #define QUERY_FW_CMD_DB_BASE 0x60 793*33ec1ccbSHans Petter Selasky 794*33ec1ccbSHans Petter Selasky #define QUERY_FW_START_OFFSET 0x20 795*33ec1ccbSHans Petter Selasky #define QUERY_FW_END_OFFSET 0x28 796*33ec1ccbSHans Petter Selasky 797*33ec1ccbSHans Petter Selasky #define QUERY_FW_SIZE_OFFSET 0x00 798*33ec1ccbSHans Petter Selasky #define QUERY_FW_CLR_INT_BASE_OFFSET 0x20 799*33ec1ccbSHans Petter Selasky #define QUERY_FW_EQ_ARM_BASE_OFFSET 0x40 800*33ec1ccbSHans Petter Selasky #define QUERY_FW_EQ_SET_CI_BASE_OFFSET 0x48 801*33ec1ccbSHans Petter Selasky 802*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 803*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox)) 804*33ec1ccbSHans Petter Selasky return PTR_ERR(mailbox); 805*33ec1ccbSHans Petter Selasky outbox = mailbox->buf; 806*33ec1ccbSHans Petter Selasky 807*33ec1ccbSHans Petter Selasky err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_FW, 808*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A); 809*33ec1ccbSHans Petter Selasky 810*33ec1ccbSHans Petter Selasky if (err) 811*33ec1ccbSHans Petter Selasky goto out; 812*33ec1ccbSHans Petter Selasky 813*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->fw_ver, outbox, QUERY_FW_VER_OFFSET); 814*33ec1ccbSHans Petter Selasky /* 815*33ec1ccbSHans Petter Selasky * FW subminor version is at more significant bits than minor 816*33ec1ccbSHans Petter Selasky * version, so swap here. 817*33ec1ccbSHans Petter Selasky */ 818*33ec1ccbSHans Petter Selasky dev->fw_ver = (dev->fw_ver & 0xffff00000000ull) | 819*33ec1ccbSHans Petter Selasky ((dev->fw_ver & 0xffff0000ull) >> 16) | 820*33ec1ccbSHans Petter Selasky ((dev->fw_ver & 0x0000ffffull) << 16); 821*33ec1ccbSHans Petter Selasky 822*33ec1ccbSHans Petter Selasky MTHCA_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET); 823*33ec1ccbSHans Petter Selasky dev->cmd.max_cmds = 1 << lg; 824*33ec1ccbSHans Petter Selasky 825*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "FW version %012llx, max commands %d\n", 826*33ec1ccbSHans Petter Selasky (unsigned long long) dev->fw_ver, dev->cmd.max_cmds); 827*33ec1ccbSHans Petter Selasky 828*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->catas_err.addr, outbox, QUERY_FW_ERR_START_OFFSET); 829*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->catas_err.size, outbox, QUERY_FW_ERR_SIZE_OFFSET); 830*33ec1ccbSHans Petter Selasky 831*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x\n", 832*33ec1ccbSHans Petter Selasky (unsigned long long) dev->catas_err.addr, dev->catas_err.size); 833*33ec1ccbSHans Petter Selasky 834*33ec1ccbSHans Petter Selasky MTHCA_GET(tmp, outbox, QUERY_FW_CMD_DB_EN_OFFSET); 835*33ec1ccbSHans Petter Selasky if (tmp & 0x1) { 836*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "FW supports commands through doorbells\n"); 837*33ec1ccbSHans Petter Selasky 838*33ec1ccbSHans Petter Selasky MTHCA_GET(base, outbox, QUERY_FW_CMD_DB_BASE); 839*33ec1ccbSHans Petter Selasky for (i = 0; i < MTHCA_CMD_NUM_DBELL_DWORDS; ++i) 840*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->cmd.dbell_offsets[i], outbox, 841*33ec1ccbSHans Petter Selasky QUERY_FW_CMD_DB_OFFSET + (i << 1)); 842*33ec1ccbSHans Petter Selasky 843*33ec1ccbSHans Petter Selasky mthca_setup_cmd_doorbells(dev, base); 844*33ec1ccbSHans Petter Selasky } 845*33ec1ccbSHans Petter Selasky 846*33ec1ccbSHans Petter Selasky if (mthca_is_memfree(dev)) { 847*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->fw.arbel.fw_pages, outbox, QUERY_FW_SIZE_OFFSET); 848*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->fw.arbel.clr_int_base, outbox, QUERY_FW_CLR_INT_BASE_OFFSET); 849*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->fw.arbel.eq_arm_base, outbox, QUERY_FW_EQ_ARM_BASE_OFFSET); 850*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->fw.arbel.eq_set_ci_base, outbox, QUERY_FW_EQ_SET_CI_BASE_OFFSET); 851*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "FW size %d KB\n", dev->fw.arbel.fw_pages << 2); 852*33ec1ccbSHans Petter Selasky 853*33ec1ccbSHans Petter Selasky /* 854*33ec1ccbSHans Petter Selasky * Round up number of system pages needed in case 855*33ec1ccbSHans Petter Selasky * MTHCA_ICM_PAGE_SIZE < PAGE_SIZE. 856*33ec1ccbSHans Petter Selasky */ 857*33ec1ccbSHans Petter Selasky dev->fw.arbel.fw_pages = 858*33ec1ccbSHans Petter Selasky ALIGN(dev->fw.arbel.fw_pages, PAGE_SIZE / MTHCA_ICM_PAGE_SIZE) >> 859*33ec1ccbSHans Petter Selasky (PAGE_SHIFT - MTHCA_ICM_PAGE_SHIFT); 860*33ec1ccbSHans Petter Selasky 861*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n", 862*33ec1ccbSHans Petter Selasky (unsigned long long) dev->fw.arbel.clr_int_base, 863*33ec1ccbSHans Petter Selasky (unsigned long long) dev->fw.arbel.eq_arm_base, 864*33ec1ccbSHans Petter Selasky (unsigned long long) dev->fw.arbel.eq_set_ci_base); 865*33ec1ccbSHans Petter Selasky } else { 866*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->fw.tavor.fw_start, outbox, QUERY_FW_START_OFFSET); 867*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->fw.tavor.fw_end, outbox, QUERY_FW_END_OFFSET); 868*33ec1ccbSHans Petter Selasky 869*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "FW size %d KB (start %llx, end %llx)\n", 870*33ec1ccbSHans Petter Selasky (int) ((dev->fw.tavor.fw_end - dev->fw.tavor.fw_start) >> 10), 871*33ec1ccbSHans Petter Selasky (unsigned long long) dev->fw.tavor.fw_start, 872*33ec1ccbSHans Petter Selasky (unsigned long long) dev->fw.tavor.fw_end); 873*33ec1ccbSHans Petter Selasky } 874*33ec1ccbSHans Petter Selasky 875*33ec1ccbSHans Petter Selasky out: 876*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox); 877*33ec1ccbSHans Petter Selasky return err; 878*33ec1ccbSHans Petter Selasky } 879*33ec1ccbSHans Petter Selasky 880*33ec1ccbSHans Petter Selasky int mthca_ENABLE_LAM(struct mthca_dev *dev) 881*33ec1ccbSHans Petter Selasky { 882*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox; 883*33ec1ccbSHans Petter Selasky u8 info; 884*33ec1ccbSHans Petter Selasky u32 *outbox; 885*33ec1ccbSHans Petter Selasky int err = 0; 886*33ec1ccbSHans Petter Selasky 887*33ec1ccbSHans Petter Selasky #define ENABLE_LAM_OUT_SIZE 0x100 888*33ec1ccbSHans Petter Selasky #define ENABLE_LAM_START_OFFSET 0x00 889*33ec1ccbSHans Petter Selasky #define ENABLE_LAM_END_OFFSET 0x08 890*33ec1ccbSHans Petter Selasky #define ENABLE_LAM_INFO_OFFSET 0x13 891*33ec1ccbSHans Petter Selasky 892*33ec1ccbSHans Petter Selasky #define ENABLE_LAM_INFO_HIDDEN_FLAG (1 << 4) 893*33ec1ccbSHans Petter Selasky #define ENABLE_LAM_INFO_ECC_MASK 0x3 894*33ec1ccbSHans Petter Selasky 895*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 896*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox)) 897*33ec1ccbSHans Petter Selasky return PTR_ERR(mailbox); 898*33ec1ccbSHans Petter Selasky outbox = mailbox->buf; 899*33ec1ccbSHans Petter Selasky 900*33ec1ccbSHans Petter Selasky err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_ENABLE_LAM, 901*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_C); 902*33ec1ccbSHans Petter Selasky 903*33ec1ccbSHans Petter Selasky if (err) 904*33ec1ccbSHans Petter Selasky goto out; 905*33ec1ccbSHans Petter Selasky 906*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->ddr_start, outbox, ENABLE_LAM_START_OFFSET); 907*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->ddr_end, outbox, ENABLE_LAM_END_OFFSET); 908*33ec1ccbSHans Petter Selasky MTHCA_GET(info, outbox, ENABLE_LAM_INFO_OFFSET); 909*33ec1ccbSHans Petter Selasky 910*33ec1ccbSHans Petter Selasky if (!!(info & ENABLE_LAM_INFO_HIDDEN_FLAG) != 911*33ec1ccbSHans Petter Selasky !!(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) { 912*33ec1ccbSHans Petter Selasky mthca_info(dev, "FW reports that HCA-attached memory " 913*33ec1ccbSHans Petter Selasky "is %s hidden; does not match PCI config\n", 914*33ec1ccbSHans Petter Selasky (info & ENABLE_LAM_INFO_HIDDEN_FLAG) ? 915*33ec1ccbSHans Petter Selasky "" : "not"); 916*33ec1ccbSHans Petter Selasky } 917*33ec1ccbSHans Petter Selasky if (info & ENABLE_LAM_INFO_HIDDEN_FLAG) 918*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "HCA-attached memory is hidden.\n"); 919*33ec1ccbSHans Petter Selasky 920*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "HCA memory size %d KB (start %llx, end %llx)\n", 921*33ec1ccbSHans Petter Selasky (int) ((dev->ddr_end - dev->ddr_start) >> 10), 922*33ec1ccbSHans Petter Selasky (unsigned long long) dev->ddr_start, 923*33ec1ccbSHans Petter Selasky (unsigned long long) dev->ddr_end); 924*33ec1ccbSHans Petter Selasky 925*33ec1ccbSHans Petter Selasky out: 926*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox); 927*33ec1ccbSHans Petter Selasky return err; 928*33ec1ccbSHans Petter Selasky } 929*33ec1ccbSHans Petter Selasky 930*33ec1ccbSHans Petter Selasky int mthca_DISABLE_LAM(struct mthca_dev *dev) 931*33ec1ccbSHans Petter Selasky { 932*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C); 933*33ec1ccbSHans Petter Selasky } 934*33ec1ccbSHans Petter Selasky 935*33ec1ccbSHans Petter Selasky int mthca_QUERY_DDR(struct mthca_dev *dev) 936*33ec1ccbSHans Petter Selasky { 937*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox; 938*33ec1ccbSHans Petter Selasky u8 info; 939*33ec1ccbSHans Petter Selasky u32 *outbox; 940*33ec1ccbSHans Petter Selasky int err = 0; 941*33ec1ccbSHans Petter Selasky 942*33ec1ccbSHans Petter Selasky #define QUERY_DDR_OUT_SIZE 0x100 943*33ec1ccbSHans Petter Selasky #define QUERY_DDR_START_OFFSET 0x00 944*33ec1ccbSHans Petter Selasky #define QUERY_DDR_END_OFFSET 0x08 945*33ec1ccbSHans Petter Selasky #define QUERY_DDR_INFO_OFFSET 0x13 946*33ec1ccbSHans Petter Selasky 947*33ec1ccbSHans Petter Selasky #define QUERY_DDR_INFO_HIDDEN_FLAG (1 << 4) 948*33ec1ccbSHans Petter Selasky #define QUERY_DDR_INFO_ECC_MASK 0x3 949*33ec1ccbSHans Petter Selasky 950*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 951*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox)) 952*33ec1ccbSHans Petter Selasky return PTR_ERR(mailbox); 953*33ec1ccbSHans Petter Selasky outbox = mailbox->buf; 954*33ec1ccbSHans Petter Selasky 955*33ec1ccbSHans Petter Selasky err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DDR, 956*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A); 957*33ec1ccbSHans Petter Selasky 958*33ec1ccbSHans Petter Selasky if (err) 959*33ec1ccbSHans Petter Selasky goto out; 960*33ec1ccbSHans Petter Selasky 961*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->ddr_start, outbox, QUERY_DDR_START_OFFSET); 962*33ec1ccbSHans Petter Selasky MTHCA_GET(dev->ddr_end, outbox, QUERY_DDR_END_OFFSET); 963*33ec1ccbSHans Petter Selasky MTHCA_GET(info, outbox, QUERY_DDR_INFO_OFFSET); 964*33ec1ccbSHans Petter Selasky 965*33ec1ccbSHans Petter Selasky if (!!(info & QUERY_DDR_INFO_HIDDEN_FLAG) != 966*33ec1ccbSHans Petter Selasky !!(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) { 967*33ec1ccbSHans Petter Selasky mthca_info(dev, "FW reports that HCA-attached memory " 968*33ec1ccbSHans Petter Selasky "is %s hidden; does not match PCI config\n", 969*33ec1ccbSHans Petter Selasky (info & QUERY_DDR_INFO_HIDDEN_FLAG) ? 970*33ec1ccbSHans Petter Selasky "" : "not"); 971*33ec1ccbSHans Petter Selasky } 972*33ec1ccbSHans Petter Selasky if (info & QUERY_DDR_INFO_HIDDEN_FLAG) 973*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "HCA-attached memory is hidden.\n"); 974*33ec1ccbSHans Petter Selasky 975*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "HCA memory size %d KB (start %llx, end %llx)\n", 976*33ec1ccbSHans Petter Selasky (int) ((dev->ddr_end - dev->ddr_start) >> 10), 977*33ec1ccbSHans Petter Selasky (unsigned long long) dev->ddr_start, 978*33ec1ccbSHans Petter Selasky (unsigned long long) dev->ddr_end); 979*33ec1ccbSHans Petter Selasky 980*33ec1ccbSHans Petter Selasky out: 981*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox); 982*33ec1ccbSHans Petter Selasky return err; 983*33ec1ccbSHans Petter Selasky } 984*33ec1ccbSHans Petter Selasky 985*33ec1ccbSHans Petter Selasky int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, 986*33ec1ccbSHans Petter Selasky struct mthca_dev_lim *dev_lim) 987*33ec1ccbSHans Petter Selasky { 988*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox; 989*33ec1ccbSHans Petter Selasky u32 *outbox; 990*33ec1ccbSHans Petter Selasky u8 field; 991*33ec1ccbSHans Petter Selasky u16 size; 992*33ec1ccbSHans Petter Selasky u16 stat_rate; 993*33ec1ccbSHans Petter Selasky int err; 994*33ec1ccbSHans Petter Selasky 995*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_OUT_SIZE 0x100 996*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET 0x10 997*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_QP_SZ_OFFSET 0x11 998*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RSVD_QP_OFFSET 0x12 999*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_QP_OFFSET 0x13 1000*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RSVD_SRQ_OFFSET 0x14 1001*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_SRQ_OFFSET 0x15 1002*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RSVD_EEC_OFFSET 0x16 1003*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_EEC_OFFSET 0x17 1004*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_CQ_SZ_OFFSET 0x19 1005*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RSVD_CQ_OFFSET 0x1a 1006*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_CQ_OFFSET 0x1b 1007*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_MPT_OFFSET 0x1d 1008*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RSVD_EQ_OFFSET 0x1e 1009*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_EQ_OFFSET 0x1f 1010*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RSVD_MTT_OFFSET 0x20 1011*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_MRW_SZ_OFFSET 0x21 1012*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RSVD_MRW_OFFSET 0x22 1013*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_MTT_SEG_OFFSET 0x23 1014*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_AV_OFFSET 0x27 1015*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_REQ_QP_OFFSET 0x29 1016*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_RES_QP_OFFSET 0x2b 1017*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_RDMA_OFFSET 0x2f 1018*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RSZ_SRQ_OFFSET 0x33 1019*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_ACK_DELAY_OFFSET 0x35 1020*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MTU_WIDTH_OFFSET 0x36 1021*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_VL_PORT_OFFSET 0x37 1022*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_GID_OFFSET 0x3b 1023*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RATE_SUPPORT_OFFSET 0x3c 1024*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_PKEY_OFFSET 0x3f 1025*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_FLAGS_OFFSET 0x44 1026*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RSVD_UAR_OFFSET 0x48 1027*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_UAR_SZ_OFFSET 0x49 1028*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_PAGE_SZ_OFFSET 0x4b 1029*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_SG_OFFSET 0x51 1030*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_DESC_SZ_OFFSET 0x52 1031*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_SG_RQ_OFFSET 0x55 1032*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_DESC_SZ_RQ_OFFSET 0x56 1033*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_QP_MCG_OFFSET 0x61 1034*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RSVD_MCG_OFFSET 0x62 1035*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_MCG_OFFSET 0x63 1036*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RSVD_PD_OFFSET 0x64 1037*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_PD_OFFSET 0x65 1038*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RSVD_RDD_OFFSET 0x66 1039*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_RDD_OFFSET 0x67 1040*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_EEC_ENTRY_SZ_OFFSET 0x80 1041*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_QPC_ENTRY_SZ_OFFSET 0x82 1042*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_EEEC_ENTRY_SZ_OFFSET 0x84 1043*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_EQPC_ENTRY_SZ_OFFSET 0x86 1044*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_EQC_ENTRY_SZ_OFFSET 0x88 1045*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_CQC_ENTRY_SZ_OFFSET 0x8a 1046*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_SRQ_ENTRY_SZ_OFFSET 0x8c 1047*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_UAR_ENTRY_SZ_OFFSET 0x8e 1048*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MTT_ENTRY_SZ_OFFSET 0x90 1049*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MPT_ENTRY_SZ_OFFSET 0x92 1050*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_PBL_SZ_OFFSET 0x96 1051*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_BMME_FLAGS_OFFSET 0x97 1052*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_RSVD_LKEY_OFFSET 0x98 1053*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_LAMR_OFFSET 0x9f 1054*33ec1ccbSHans Petter Selasky #define QUERY_DEV_LIM_MAX_ICM_SZ_OFFSET 0xa0 1055*33ec1ccbSHans Petter Selasky 1056*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 1057*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox)) 1058*33ec1ccbSHans Petter Selasky return PTR_ERR(mailbox); 1059*33ec1ccbSHans Petter Selasky outbox = mailbox->buf; 1060*33ec1ccbSHans Petter Selasky 1061*33ec1ccbSHans Petter Selasky err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DEV_LIM, 1062*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A); 1063*33ec1ccbSHans Petter Selasky 1064*33ec1ccbSHans Petter Selasky if (err) 1065*33ec1ccbSHans Petter Selasky goto out; 1066*33ec1ccbSHans Petter Selasky 1067*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_QP_OFFSET); 1068*33ec1ccbSHans Petter Selasky dev_lim->reserved_qps = 1 << (field & 0xf); 1069*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_OFFSET); 1070*33ec1ccbSHans Petter Selasky dev_lim->max_qps = 1 << (field & 0x1f); 1071*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_SRQ_OFFSET); 1072*33ec1ccbSHans Petter Selasky dev_lim->reserved_srqs = 1 << (field >> 4); 1073*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_OFFSET); 1074*33ec1ccbSHans Petter Selasky dev_lim->max_srqs = 1 << (field & 0x1f); 1075*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_EEC_OFFSET); 1076*33ec1ccbSHans Petter Selasky dev_lim->reserved_eecs = 1 << (field & 0xf); 1077*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_EEC_OFFSET); 1078*33ec1ccbSHans Petter Selasky dev_lim->max_eecs = 1 << (field & 0x1f); 1079*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_CQ_SZ_OFFSET); 1080*33ec1ccbSHans Petter Selasky dev_lim->max_cq_sz = 1 << field; 1081*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_CQ_OFFSET); 1082*33ec1ccbSHans Petter Selasky dev_lim->reserved_cqs = 1 << (field & 0xf); 1083*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_CQ_OFFSET); 1084*33ec1ccbSHans Petter Selasky dev_lim->max_cqs = 1 << (field & 0x1f); 1085*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_MPT_OFFSET); 1086*33ec1ccbSHans Petter Selasky dev_lim->max_mpts = 1 << (field & 0x3f); 1087*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_EQ_OFFSET); 1088*33ec1ccbSHans Petter Selasky dev_lim->reserved_eqs = 1 << (field & 0xf); 1089*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_EQ_OFFSET); 1090*33ec1ccbSHans Petter Selasky dev_lim->max_eqs = 1 << (field & 0x7); 1091*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_MTT_OFFSET); 1092*33ec1ccbSHans Petter Selasky if (mthca_is_memfree(dev)) 1093*33ec1ccbSHans Petter Selasky dev_lim->reserved_mtts = ALIGN((1 << (field >> 4)) * sizeof(u64), 1094*33ec1ccbSHans Petter Selasky dev->limits.mtt_seg_size) / dev->limits.mtt_seg_size; 1095*33ec1ccbSHans Petter Selasky else 1096*33ec1ccbSHans Petter Selasky dev_lim->reserved_mtts = 1 << (field >> 4); 1097*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_MRW_SZ_OFFSET); 1098*33ec1ccbSHans Petter Selasky dev_lim->max_mrw_sz = 1 << field; 1099*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_MRW_OFFSET); 1100*33ec1ccbSHans Petter Selasky dev_lim->reserved_mrws = 1 << (field & 0xf); 1101*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_MTT_SEG_OFFSET); 1102*33ec1ccbSHans Petter Selasky dev_lim->max_mtt_seg = 1 << (field & 0x3f); 1103*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_REQ_QP_OFFSET); 1104*33ec1ccbSHans Petter Selasky dev_lim->max_requester_per_qp = 1 << (field & 0x3f); 1105*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_RES_QP_OFFSET); 1106*33ec1ccbSHans Petter Selasky dev_lim->max_responder_per_qp = 1 << (field & 0x3f); 1107*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_RDMA_OFFSET); 1108*33ec1ccbSHans Petter Selasky dev_lim->max_rdma_global = 1 << (field & 0x3f); 1109*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_ACK_DELAY_OFFSET); 1110*33ec1ccbSHans Petter Selasky dev_lim->local_ca_ack_delay = field & 0x1f; 1111*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MTU_WIDTH_OFFSET); 1112*33ec1ccbSHans Petter Selasky dev_lim->max_mtu = field >> 4; 1113*33ec1ccbSHans Petter Selasky dev_lim->max_port_width = field & 0xf; 1114*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_VL_PORT_OFFSET); 1115*33ec1ccbSHans Petter Selasky dev_lim->max_vl = field >> 4; 1116*33ec1ccbSHans Petter Selasky dev_lim->num_ports = field & 0xf; 1117*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_GID_OFFSET); 1118*33ec1ccbSHans Petter Selasky dev_lim->max_gids = 1 << (field & 0xf); 1119*33ec1ccbSHans Petter Selasky MTHCA_GET(stat_rate, outbox, QUERY_DEV_LIM_RATE_SUPPORT_OFFSET); 1120*33ec1ccbSHans Petter Selasky dev_lim->stat_rate_support = stat_rate; 1121*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_PKEY_OFFSET); 1122*33ec1ccbSHans Petter Selasky dev_lim->max_pkeys = 1 << (field & 0xf); 1123*33ec1ccbSHans Petter Selasky MTHCA_GET(dev_lim->flags, outbox, QUERY_DEV_LIM_FLAGS_OFFSET); 1124*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_UAR_OFFSET); 1125*33ec1ccbSHans Petter Selasky dev_lim->reserved_uars = field >> 4; 1126*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_UAR_SZ_OFFSET); 1127*33ec1ccbSHans Petter Selasky dev_lim->uar_size = 1 << ((field & 0x3f) + 20); 1128*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_PAGE_SZ_OFFSET); 1129*33ec1ccbSHans Petter Selasky dev_lim->min_page_sz = 1 << field; 1130*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_OFFSET); 1131*33ec1ccbSHans Petter Selasky dev_lim->max_sg = field; 1132*33ec1ccbSHans Petter Selasky 1133*33ec1ccbSHans Petter Selasky MTHCA_GET(size, outbox, QUERY_DEV_LIM_MAX_DESC_SZ_OFFSET); 1134*33ec1ccbSHans Petter Selasky dev_lim->max_desc_sz = size; 1135*33ec1ccbSHans Petter Selasky 1136*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_MCG_OFFSET); 1137*33ec1ccbSHans Petter Selasky dev_lim->max_qp_per_mcg = 1 << field; 1138*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_MCG_OFFSET); 1139*33ec1ccbSHans Petter Selasky dev_lim->reserved_mgms = field & 0xf; 1140*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_MCG_OFFSET); 1141*33ec1ccbSHans Petter Selasky dev_lim->max_mcgs = 1 << field; 1142*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_PD_OFFSET); 1143*33ec1ccbSHans Petter Selasky dev_lim->reserved_pds = field >> 4; 1144*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_PD_OFFSET); 1145*33ec1ccbSHans Petter Selasky dev_lim->max_pds = 1 << (field & 0x3f); 1146*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_RDD_OFFSET); 1147*33ec1ccbSHans Petter Selasky dev_lim->reserved_rdds = field >> 4; 1148*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_RDD_OFFSET); 1149*33ec1ccbSHans Petter Selasky dev_lim->max_rdds = 1 << (field & 0x3f); 1150*33ec1ccbSHans Petter Selasky 1151*33ec1ccbSHans Petter Selasky MTHCA_GET(size, outbox, QUERY_DEV_LIM_EEC_ENTRY_SZ_OFFSET); 1152*33ec1ccbSHans Petter Selasky dev_lim->eec_entry_sz = size; 1153*33ec1ccbSHans Petter Selasky MTHCA_GET(size, outbox, QUERY_DEV_LIM_QPC_ENTRY_SZ_OFFSET); 1154*33ec1ccbSHans Petter Selasky dev_lim->qpc_entry_sz = size; 1155*33ec1ccbSHans Petter Selasky MTHCA_GET(size, outbox, QUERY_DEV_LIM_EEEC_ENTRY_SZ_OFFSET); 1156*33ec1ccbSHans Petter Selasky dev_lim->eeec_entry_sz = size; 1157*33ec1ccbSHans Petter Selasky MTHCA_GET(size, outbox, QUERY_DEV_LIM_EQPC_ENTRY_SZ_OFFSET); 1158*33ec1ccbSHans Petter Selasky dev_lim->eqpc_entry_sz = size; 1159*33ec1ccbSHans Petter Selasky MTHCA_GET(size, outbox, QUERY_DEV_LIM_EQC_ENTRY_SZ_OFFSET); 1160*33ec1ccbSHans Petter Selasky dev_lim->eqc_entry_sz = size; 1161*33ec1ccbSHans Petter Selasky MTHCA_GET(size, outbox, QUERY_DEV_LIM_CQC_ENTRY_SZ_OFFSET); 1162*33ec1ccbSHans Petter Selasky dev_lim->cqc_entry_sz = size; 1163*33ec1ccbSHans Petter Selasky MTHCA_GET(size, outbox, QUERY_DEV_LIM_SRQ_ENTRY_SZ_OFFSET); 1164*33ec1ccbSHans Petter Selasky dev_lim->srq_entry_sz = size; 1165*33ec1ccbSHans Petter Selasky MTHCA_GET(size, outbox, QUERY_DEV_LIM_UAR_ENTRY_SZ_OFFSET); 1166*33ec1ccbSHans Petter Selasky dev_lim->uar_scratch_entry_sz = size; 1167*33ec1ccbSHans Petter Selasky 1168*33ec1ccbSHans Petter Selasky if (mthca_is_memfree(dev)) { 1169*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET); 1170*33ec1ccbSHans Petter Selasky dev_lim->max_srq_sz = 1 << field; 1171*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET); 1172*33ec1ccbSHans Petter Selasky dev_lim->max_qp_sz = 1 << field; 1173*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSZ_SRQ_OFFSET); 1174*33ec1ccbSHans Petter Selasky dev_lim->hca.arbel.resize_srq = field & 1; 1175*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_RQ_OFFSET); 1176*33ec1ccbSHans Petter Selasky dev_lim->max_sg = min_t(int, field, dev_lim->max_sg); 1177*33ec1ccbSHans Petter Selasky MTHCA_GET(size, outbox, QUERY_DEV_LIM_MAX_DESC_SZ_RQ_OFFSET); 1178*33ec1ccbSHans Petter Selasky dev_lim->max_desc_sz = min_t(int, size, dev_lim->max_desc_sz); 1179*33ec1ccbSHans Petter Selasky MTHCA_GET(size, outbox, QUERY_DEV_LIM_MPT_ENTRY_SZ_OFFSET); 1180*33ec1ccbSHans Petter Selasky dev_lim->mpt_entry_sz = size; 1181*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_PBL_SZ_OFFSET); 1182*33ec1ccbSHans Petter Selasky dev_lim->hca.arbel.max_pbl_sz = 1 << (field & 0x3f); 1183*33ec1ccbSHans Petter Selasky MTHCA_GET(dev_lim->hca.arbel.bmme_flags, outbox, 1184*33ec1ccbSHans Petter Selasky QUERY_DEV_LIM_BMME_FLAGS_OFFSET); 1185*33ec1ccbSHans Petter Selasky MTHCA_GET(dev_lim->hca.arbel.reserved_lkey, outbox, 1186*33ec1ccbSHans Petter Selasky QUERY_DEV_LIM_RSVD_LKEY_OFFSET); 1187*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_LAMR_OFFSET); 1188*33ec1ccbSHans Petter Selasky dev_lim->hca.arbel.lam_required = field & 1; 1189*33ec1ccbSHans Petter Selasky MTHCA_GET(dev_lim->hca.arbel.max_icm_sz, outbox, 1190*33ec1ccbSHans Petter Selasky QUERY_DEV_LIM_MAX_ICM_SZ_OFFSET); 1191*33ec1ccbSHans Petter Selasky 1192*33ec1ccbSHans Petter Selasky if (dev_lim->hca.arbel.bmme_flags & 1) 1193*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Base MM extensions: yes " 1194*33ec1ccbSHans Petter Selasky "(flags %d, max PBL %d, rsvd L_Key %08x)\n", 1195*33ec1ccbSHans Petter Selasky dev_lim->hca.arbel.bmme_flags, 1196*33ec1ccbSHans Petter Selasky dev_lim->hca.arbel.max_pbl_sz, 1197*33ec1ccbSHans Petter Selasky dev_lim->hca.arbel.reserved_lkey); 1198*33ec1ccbSHans Petter Selasky else 1199*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Base MM extensions: no\n"); 1200*33ec1ccbSHans Petter Selasky 1201*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Max ICM size %lld MB\n", 1202*33ec1ccbSHans Petter Selasky (unsigned long long) dev_lim->hca.arbel.max_icm_sz >> 20); 1203*33ec1ccbSHans Petter Selasky } else { 1204*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET); 1205*33ec1ccbSHans Petter Selasky dev_lim->max_srq_sz = (1 << field) - 1; 1206*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET); 1207*33ec1ccbSHans Petter Selasky dev_lim->max_qp_sz = (1 << field) - 1; 1208*33ec1ccbSHans Petter Selasky MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_AV_OFFSET); 1209*33ec1ccbSHans Petter Selasky dev_lim->hca.tavor.max_avs = 1 << (field & 0x3f); 1210*33ec1ccbSHans Petter Selasky dev_lim->mpt_entry_sz = MTHCA_MPT_ENTRY_SIZE; 1211*33ec1ccbSHans Petter Selasky } 1212*33ec1ccbSHans Petter Selasky 1213*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n", 1214*33ec1ccbSHans Petter Selasky dev_lim->max_qps, dev_lim->reserved_qps, dev_lim->qpc_entry_sz); 1215*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n", 1216*33ec1ccbSHans Petter Selasky dev_lim->max_srqs, dev_lim->reserved_srqs, dev_lim->srq_entry_sz); 1217*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n", 1218*33ec1ccbSHans Petter Selasky dev_lim->max_cqs, dev_lim->reserved_cqs, dev_lim->cqc_entry_sz); 1219*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n", 1220*33ec1ccbSHans Petter Selasky dev_lim->max_eqs, dev_lim->reserved_eqs, dev_lim->eqc_entry_sz); 1221*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n", 1222*33ec1ccbSHans Petter Selasky dev_lim->reserved_mrws, dev_lim->reserved_mtts); 1223*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n", 1224*33ec1ccbSHans Petter Selasky dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars); 1225*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n", 1226*33ec1ccbSHans Petter Selasky dev_lim->max_pds, dev_lim->reserved_mgms); 1227*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", 1228*33ec1ccbSHans Petter Selasky dev_lim->max_cq_sz, dev_lim->max_qp_sz, dev_lim->max_srq_sz); 1229*33ec1ccbSHans Petter Selasky 1230*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags); 1231*33ec1ccbSHans Petter Selasky 1232*33ec1ccbSHans Petter Selasky out: 1233*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox); 1234*33ec1ccbSHans Petter Selasky return err; 1235*33ec1ccbSHans Petter Selasky } 1236*33ec1ccbSHans Petter Selasky 1237*33ec1ccbSHans Petter Selasky static void get_board_id(void *vsd, char *board_id) 1238*33ec1ccbSHans Petter Selasky { 1239*33ec1ccbSHans Petter Selasky int i; 1240*33ec1ccbSHans Petter Selasky 1241*33ec1ccbSHans Petter Selasky #define VSD_OFFSET_SIG1 0x00 1242*33ec1ccbSHans Petter Selasky #define VSD_OFFSET_SIG2 0xde 1243*33ec1ccbSHans Petter Selasky #define VSD_OFFSET_MLX_BOARD_ID 0xd0 1244*33ec1ccbSHans Petter Selasky #define VSD_OFFSET_TS_BOARD_ID 0x20 1245*33ec1ccbSHans Petter Selasky 1246*33ec1ccbSHans Petter Selasky #define VSD_SIGNATURE_TOPSPIN 0x5ad 1247*33ec1ccbSHans Petter Selasky 1248*33ec1ccbSHans Petter Selasky memset(board_id, 0, MTHCA_BOARD_ID_LEN); 1249*33ec1ccbSHans Petter Selasky 1250*33ec1ccbSHans Petter Selasky if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN && 1251*33ec1ccbSHans Petter Selasky be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) { 1252*33ec1ccbSHans Petter Selasky strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MTHCA_BOARD_ID_LEN); 1253*33ec1ccbSHans Petter Selasky } else { 1254*33ec1ccbSHans Petter Selasky /* 1255*33ec1ccbSHans Petter Selasky * The board ID is a string but the firmware byte 1256*33ec1ccbSHans Petter Selasky * swaps each 4-byte word before passing it back to 1257*33ec1ccbSHans Petter Selasky * us. Therefore we need to swab it before printing. 1258*33ec1ccbSHans Petter Selasky */ 1259*33ec1ccbSHans Petter Selasky for (i = 0; i < 4; ++i) 1260*33ec1ccbSHans Petter Selasky ((u32 *) board_id)[i] = 1261*33ec1ccbSHans Petter Selasky swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4)); 1262*33ec1ccbSHans Petter Selasky } 1263*33ec1ccbSHans Petter Selasky } 1264*33ec1ccbSHans Petter Selasky 1265*33ec1ccbSHans Petter Selasky int mthca_QUERY_ADAPTER(struct mthca_dev *dev, 1266*33ec1ccbSHans Petter Selasky struct mthca_adapter *adapter) 1267*33ec1ccbSHans Petter Selasky { 1268*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox; 1269*33ec1ccbSHans Petter Selasky u32 *outbox; 1270*33ec1ccbSHans Petter Selasky int err; 1271*33ec1ccbSHans Petter Selasky 1272*33ec1ccbSHans Petter Selasky #define QUERY_ADAPTER_OUT_SIZE 0x100 1273*33ec1ccbSHans Petter Selasky #define QUERY_ADAPTER_VENDOR_ID_OFFSET 0x00 1274*33ec1ccbSHans Petter Selasky #define QUERY_ADAPTER_DEVICE_ID_OFFSET 0x04 1275*33ec1ccbSHans Petter Selasky #define QUERY_ADAPTER_REVISION_ID_OFFSET 0x08 1276*33ec1ccbSHans Petter Selasky #define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10 1277*33ec1ccbSHans Petter Selasky #define QUERY_ADAPTER_VSD_OFFSET 0x20 1278*33ec1ccbSHans Petter Selasky 1279*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 1280*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox)) 1281*33ec1ccbSHans Petter Selasky return PTR_ERR(mailbox); 1282*33ec1ccbSHans Petter Selasky outbox = mailbox->buf; 1283*33ec1ccbSHans Petter Selasky 1284*33ec1ccbSHans Petter Selasky err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_ADAPTER, 1285*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A); 1286*33ec1ccbSHans Petter Selasky 1287*33ec1ccbSHans Petter Selasky if (err) 1288*33ec1ccbSHans Petter Selasky goto out; 1289*33ec1ccbSHans Petter Selasky 1290*33ec1ccbSHans Petter Selasky if (!mthca_is_memfree(dev)) { 1291*33ec1ccbSHans Petter Selasky MTHCA_GET(adapter->vendor_id, outbox, 1292*33ec1ccbSHans Petter Selasky QUERY_ADAPTER_VENDOR_ID_OFFSET); 1293*33ec1ccbSHans Petter Selasky MTHCA_GET(adapter->device_id, outbox, 1294*33ec1ccbSHans Petter Selasky QUERY_ADAPTER_DEVICE_ID_OFFSET); 1295*33ec1ccbSHans Petter Selasky MTHCA_GET(adapter->revision_id, outbox, 1296*33ec1ccbSHans Petter Selasky QUERY_ADAPTER_REVISION_ID_OFFSET); 1297*33ec1ccbSHans Petter Selasky } 1298*33ec1ccbSHans Petter Selasky MTHCA_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET); 1299*33ec1ccbSHans Petter Selasky 1300*33ec1ccbSHans Petter Selasky get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4, 1301*33ec1ccbSHans Petter Selasky adapter->board_id); 1302*33ec1ccbSHans Petter Selasky 1303*33ec1ccbSHans Petter Selasky out: 1304*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox); 1305*33ec1ccbSHans Petter Selasky return err; 1306*33ec1ccbSHans Petter Selasky } 1307*33ec1ccbSHans Petter Selasky 1308*33ec1ccbSHans Petter Selasky int mthca_INIT_HCA(struct mthca_dev *dev, 1309*33ec1ccbSHans Petter Selasky struct mthca_init_hca_param *param) 1310*33ec1ccbSHans Petter Selasky { 1311*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox; 1312*33ec1ccbSHans Petter Selasky __be32 *inbox; 1313*33ec1ccbSHans Petter Selasky int err; 1314*33ec1ccbSHans Petter Selasky 1315*33ec1ccbSHans Petter Selasky #define INIT_HCA_IN_SIZE 0x200 1316*33ec1ccbSHans Petter Selasky #define INIT_HCA_FLAGS1_OFFSET 0x00c 1317*33ec1ccbSHans Petter Selasky #define INIT_HCA_FLAGS2_OFFSET 0x014 1318*33ec1ccbSHans Petter Selasky #define INIT_HCA_QPC_OFFSET 0x020 1319*33ec1ccbSHans Petter Selasky #define INIT_HCA_QPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x10) 1320*33ec1ccbSHans Petter Selasky #define INIT_HCA_LOG_QP_OFFSET (INIT_HCA_QPC_OFFSET + 0x17) 1321*33ec1ccbSHans Petter Selasky #define INIT_HCA_EEC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x20) 1322*33ec1ccbSHans Petter Selasky #define INIT_HCA_LOG_EEC_OFFSET (INIT_HCA_QPC_OFFSET + 0x27) 1323*33ec1ccbSHans Petter Selasky #define INIT_HCA_SRQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x28) 1324*33ec1ccbSHans Petter Selasky #define INIT_HCA_LOG_SRQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x2f) 1325*33ec1ccbSHans Petter Selasky #define INIT_HCA_CQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x30) 1326*33ec1ccbSHans Petter Selasky #define INIT_HCA_LOG_CQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x37) 1327*33ec1ccbSHans Petter Selasky #define INIT_HCA_EQPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x40) 1328*33ec1ccbSHans Petter Selasky #define INIT_HCA_EEEC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x50) 1329*33ec1ccbSHans Petter Selasky #define INIT_HCA_EQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x60) 1330*33ec1ccbSHans Petter Selasky #define INIT_HCA_LOG_EQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x67) 1331*33ec1ccbSHans Petter Selasky #define INIT_HCA_RDB_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x70) 1332*33ec1ccbSHans Petter Selasky #define INIT_HCA_UDAV_OFFSET 0x0b0 1333*33ec1ccbSHans Petter Selasky #define INIT_HCA_UDAV_LKEY_OFFSET (INIT_HCA_UDAV_OFFSET + 0x0) 1334*33ec1ccbSHans Petter Selasky #define INIT_HCA_UDAV_PD_OFFSET (INIT_HCA_UDAV_OFFSET + 0x4) 1335*33ec1ccbSHans Petter Selasky #define INIT_HCA_MCAST_OFFSET 0x0c0 1336*33ec1ccbSHans Petter Selasky #define INIT_HCA_MC_BASE_OFFSET (INIT_HCA_MCAST_OFFSET + 0x00) 1337*33ec1ccbSHans Petter Selasky #define INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12) 1338*33ec1ccbSHans Petter Selasky #define INIT_HCA_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16) 1339*33ec1ccbSHans Petter Selasky #define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b) 1340*33ec1ccbSHans Petter Selasky #define INIT_HCA_TPT_OFFSET 0x0f0 1341*33ec1ccbSHans Petter Selasky #define INIT_HCA_MPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00) 1342*33ec1ccbSHans Petter Selasky #define INIT_HCA_MTT_SEG_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x09) 1343*33ec1ccbSHans Petter Selasky #define INIT_HCA_LOG_MPT_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x0b) 1344*33ec1ccbSHans Petter Selasky #define INIT_HCA_MTT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x10) 1345*33ec1ccbSHans Petter Selasky #define INIT_HCA_UAR_OFFSET 0x120 1346*33ec1ccbSHans Petter Selasky #define INIT_HCA_UAR_BASE_OFFSET (INIT_HCA_UAR_OFFSET + 0x00) 1347*33ec1ccbSHans Petter Selasky #define INIT_HCA_UARC_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x09) 1348*33ec1ccbSHans Petter Selasky #define INIT_HCA_LOG_UAR_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0a) 1349*33ec1ccbSHans Petter Selasky #define INIT_HCA_UAR_PAGE_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0b) 1350*33ec1ccbSHans Petter Selasky #define INIT_HCA_UAR_SCATCH_BASE_OFFSET (INIT_HCA_UAR_OFFSET + 0x10) 1351*33ec1ccbSHans Petter Selasky #define INIT_HCA_UAR_CTX_BASE_OFFSET (INIT_HCA_UAR_OFFSET + 0x18) 1352*33ec1ccbSHans Petter Selasky 1353*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 1354*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox)) 1355*33ec1ccbSHans Petter Selasky return PTR_ERR(mailbox); 1356*33ec1ccbSHans Petter Selasky inbox = mailbox->buf; 1357*33ec1ccbSHans Petter Selasky 1358*33ec1ccbSHans Petter Selasky memset(inbox, 0, INIT_HCA_IN_SIZE); 1359*33ec1ccbSHans Petter Selasky 1360*33ec1ccbSHans Petter Selasky if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT) 1361*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, 0x1, INIT_HCA_FLAGS1_OFFSET); 1362*33ec1ccbSHans Petter Selasky 1363*33ec1ccbSHans Petter Selasky #if defined(__LITTLE_ENDIAN) 1364*33ec1ccbSHans Petter Selasky *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) &= ~cpu_to_be32(1 << 1); 1365*33ec1ccbSHans Petter Selasky #elif defined(__BIG_ENDIAN) 1366*33ec1ccbSHans Petter Selasky *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(1 << 1); 1367*33ec1ccbSHans Petter Selasky #else 1368*33ec1ccbSHans Petter Selasky #error Host endianness not defined 1369*33ec1ccbSHans Petter Selasky #endif 1370*33ec1ccbSHans Petter Selasky /* Check port for UD address vector: */ 1371*33ec1ccbSHans Petter Selasky *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(1); 1372*33ec1ccbSHans Petter Selasky 1373*33ec1ccbSHans Petter Selasky /* Enable IPoIB checksumming if we can: */ 1374*33ec1ccbSHans Petter Selasky if (dev->device_cap_flags & IB_DEVICE_UD_IP_CSUM) 1375*33ec1ccbSHans Petter Selasky *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(7 << 3); 1376*33ec1ccbSHans Petter Selasky 1377*33ec1ccbSHans Petter Selasky /* We leave wqe_quota, responder_exu, etc as 0 (default) */ 1378*33ec1ccbSHans Petter Selasky 1379*33ec1ccbSHans Petter Selasky /* QPC/EEC/CQC/EQC/RDB attributes */ 1380*33ec1ccbSHans Petter Selasky 1381*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET); 1382*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->log_num_qps, INIT_HCA_LOG_QP_OFFSET); 1383*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->eec_base, INIT_HCA_EEC_BASE_OFFSET); 1384*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->log_num_eecs, INIT_HCA_LOG_EEC_OFFSET); 1385*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->srqc_base, INIT_HCA_SRQC_BASE_OFFSET); 1386*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->log_num_srqs, INIT_HCA_LOG_SRQ_OFFSET); 1387*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->cqc_base, INIT_HCA_CQC_BASE_OFFSET); 1388*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->log_num_cqs, INIT_HCA_LOG_CQ_OFFSET); 1389*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->eqpc_base, INIT_HCA_EQPC_BASE_OFFSET); 1390*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->eeec_base, INIT_HCA_EEEC_BASE_OFFSET); 1391*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->eqc_base, INIT_HCA_EQC_BASE_OFFSET); 1392*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->log_num_eqs, INIT_HCA_LOG_EQ_OFFSET); 1393*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->rdb_base, INIT_HCA_RDB_BASE_OFFSET); 1394*33ec1ccbSHans Petter Selasky 1395*33ec1ccbSHans Petter Selasky /* UD AV attributes */ 1396*33ec1ccbSHans Petter Selasky 1397*33ec1ccbSHans Petter Selasky /* multicast attributes */ 1398*33ec1ccbSHans Petter Selasky 1399*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET); 1400*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); 1401*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->mc_hash_sz, INIT_HCA_MC_HASH_SZ_OFFSET); 1402*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); 1403*33ec1ccbSHans Petter Selasky 1404*33ec1ccbSHans Petter Selasky /* TPT attributes */ 1405*33ec1ccbSHans Petter Selasky 1406*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->mpt_base, INIT_HCA_MPT_BASE_OFFSET); 1407*33ec1ccbSHans Petter Selasky if (!mthca_is_memfree(dev)) 1408*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->mtt_seg_sz, INIT_HCA_MTT_SEG_SZ_OFFSET); 1409*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->log_mpt_sz, INIT_HCA_LOG_MPT_SZ_OFFSET); 1410*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->mtt_base, INIT_HCA_MTT_BASE_OFFSET); 1411*33ec1ccbSHans Petter Selasky 1412*33ec1ccbSHans Petter Selasky /* UAR attributes */ 1413*33ec1ccbSHans Petter Selasky { 1414*33ec1ccbSHans Petter Selasky u8 uar_page_sz = PAGE_SHIFT - 12; 1415*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, uar_page_sz, INIT_HCA_UAR_PAGE_SZ_OFFSET); 1416*33ec1ccbSHans Petter Selasky } 1417*33ec1ccbSHans Petter Selasky 1418*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->uar_scratch_base, INIT_HCA_UAR_SCATCH_BASE_OFFSET); 1419*33ec1ccbSHans Petter Selasky 1420*33ec1ccbSHans Petter Selasky if (mthca_is_memfree(dev)) { 1421*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->log_uarc_sz, INIT_HCA_UARC_SZ_OFFSET); 1422*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->log_uar_sz, INIT_HCA_LOG_UAR_SZ_OFFSET); 1423*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->uarc_base, INIT_HCA_UAR_CTX_BASE_OFFSET); 1424*33ec1ccbSHans Petter Selasky } 1425*33ec1ccbSHans Petter Selasky 1426*33ec1ccbSHans Petter Selasky err = mthca_cmd(dev, mailbox->dma, 0, 0, 1427*33ec1ccbSHans Petter Selasky CMD_INIT_HCA, CMD_TIME_CLASS_D); 1428*33ec1ccbSHans Petter Selasky 1429*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox); 1430*33ec1ccbSHans Petter Selasky return err; 1431*33ec1ccbSHans Petter Selasky } 1432*33ec1ccbSHans Petter Selasky 1433*33ec1ccbSHans Petter Selasky int mthca_INIT_IB(struct mthca_dev *dev, 1434*33ec1ccbSHans Petter Selasky struct mthca_init_ib_param *param, 1435*33ec1ccbSHans Petter Selasky int port) 1436*33ec1ccbSHans Petter Selasky { 1437*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox; 1438*33ec1ccbSHans Petter Selasky u32 *inbox; 1439*33ec1ccbSHans Petter Selasky int err; 1440*33ec1ccbSHans Petter Selasky u32 flags; 1441*33ec1ccbSHans Petter Selasky 1442*33ec1ccbSHans Petter Selasky #define INIT_IB_IN_SIZE 56 1443*33ec1ccbSHans Petter Selasky #define INIT_IB_FLAGS_OFFSET 0x00 1444*33ec1ccbSHans Petter Selasky #define INIT_IB_FLAG_SIG (1 << 18) 1445*33ec1ccbSHans Petter Selasky #define INIT_IB_FLAG_NG (1 << 17) 1446*33ec1ccbSHans Petter Selasky #define INIT_IB_FLAG_G0 (1 << 16) 1447*33ec1ccbSHans Petter Selasky #define INIT_IB_VL_SHIFT 4 1448*33ec1ccbSHans Petter Selasky #define INIT_IB_PORT_WIDTH_SHIFT 8 1449*33ec1ccbSHans Petter Selasky #define INIT_IB_MTU_SHIFT 12 1450*33ec1ccbSHans Petter Selasky #define INIT_IB_MAX_GID_OFFSET 0x06 1451*33ec1ccbSHans Petter Selasky #define INIT_IB_MAX_PKEY_OFFSET 0x0a 1452*33ec1ccbSHans Petter Selasky #define INIT_IB_GUID0_OFFSET 0x10 1453*33ec1ccbSHans Petter Selasky #define INIT_IB_NODE_GUID_OFFSET 0x18 1454*33ec1ccbSHans Petter Selasky #define INIT_IB_SI_GUID_OFFSET 0x20 1455*33ec1ccbSHans Petter Selasky 1456*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 1457*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox)) 1458*33ec1ccbSHans Petter Selasky return PTR_ERR(mailbox); 1459*33ec1ccbSHans Petter Selasky inbox = mailbox->buf; 1460*33ec1ccbSHans Petter Selasky 1461*33ec1ccbSHans Petter Selasky memset(inbox, 0, INIT_IB_IN_SIZE); 1462*33ec1ccbSHans Petter Selasky 1463*33ec1ccbSHans Petter Selasky flags = 0; 1464*33ec1ccbSHans Petter Selasky flags |= param->set_guid0 ? INIT_IB_FLAG_G0 : 0; 1465*33ec1ccbSHans Petter Selasky flags |= param->set_node_guid ? INIT_IB_FLAG_NG : 0; 1466*33ec1ccbSHans Petter Selasky flags |= param->set_si_guid ? INIT_IB_FLAG_SIG : 0; 1467*33ec1ccbSHans Petter Selasky flags |= param->vl_cap << INIT_IB_VL_SHIFT; 1468*33ec1ccbSHans Petter Selasky flags |= param->port_width << INIT_IB_PORT_WIDTH_SHIFT; 1469*33ec1ccbSHans Petter Selasky flags |= param->mtu_cap << INIT_IB_MTU_SHIFT; 1470*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, flags, INIT_IB_FLAGS_OFFSET); 1471*33ec1ccbSHans Petter Selasky 1472*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->gid_cap, INIT_IB_MAX_GID_OFFSET); 1473*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->pkey_cap, INIT_IB_MAX_PKEY_OFFSET); 1474*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->guid0, INIT_IB_GUID0_OFFSET); 1475*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->node_guid, INIT_IB_NODE_GUID_OFFSET); 1476*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->si_guid, INIT_IB_SI_GUID_OFFSET); 1477*33ec1ccbSHans Petter Selasky 1478*33ec1ccbSHans Petter Selasky err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_INIT_IB, 1479*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A); 1480*33ec1ccbSHans Petter Selasky 1481*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox); 1482*33ec1ccbSHans Petter Selasky return err; 1483*33ec1ccbSHans Petter Selasky } 1484*33ec1ccbSHans Petter Selasky 1485*33ec1ccbSHans Petter Selasky int mthca_CLOSE_IB(struct mthca_dev *dev, int port) 1486*33ec1ccbSHans Petter Selasky { 1487*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, 0, port, 0, CMD_CLOSE_IB, CMD_TIME_CLASS_A); 1488*33ec1ccbSHans Petter Selasky } 1489*33ec1ccbSHans Petter Selasky 1490*33ec1ccbSHans Petter Selasky int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic) 1491*33ec1ccbSHans Petter Selasky { 1492*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, 0, 0, panic, CMD_CLOSE_HCA, CMD_TIME_CLASS_C); 1493*33ec1ccbSHans Petter Selasky } 1494*33ec1ccbSHans Petter Selasky 1495*33ec1ccbSHans Petter Selasky int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param, 1496*33ec1ccbSHans Petter Selasky int port) 1497*33ec1ccbSHans Petter Selasky { 1498*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox; 1499*33ec1ccbSHans Petter Selasky u32 *inbox; 1500*33ec1ccbSHans Petter Selasky int err; 1501*33ec1ccbSHans Petter Selasky u32 flags = 0; 1502*33ec1ccbSHans Petter Selasky 1503*33ec1ccbSHans Petter Selasky #define SET_IB_IN_SIZE 0x40 1504*33ec1ccbSHans Petter Selasky #define SET_IB_FLAGS_OFFSET 0x00 1505*33ec1ccbSHans Petter Selasky #define SET_IB_FLAG_SIG (1 << 18) 1506*33ec1ccbSHans Petter Selasky #define SET_IB_FLAG_RQK (1 << 0) 1507*33ec1ccbSHans Petter Selasky #define SET_IB_CAP_MASK_OFFSET 0x04 1508*33ec1ccbSHans Petter Selasky #define SET_IB_SI_GUID_OFFSET 0x08 1509*33ec1ccbSHans Petter Selasky 1510*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 1511*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox)) 1512*33ec1ccbSHans Petter Selasky return PTR_ERR(mailbox); 1513*33ec1ccbSHans Petter Selasky inbox = mailbox->buf; 1514*33ec1ccbSHans Petter Selasky 1515*33ec1ccbSHans Petter Selasky memset(inbox, 0, SET_IB_IN_SIZE); 1516*33ec1ccbSHans Petter Selasky 1517*33ec1ccbSHans Petter Selasky flags |= param->set_si_guid ? SET_IB_FLAG_SIG : 0; 1518*33ec1ccbSHans Petter Selasky flags |= param->reset_qkey_viol ? SET_IB_FLAG_RQK : 0; 1519*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, flags, SET_IB_FLAGS_OFFSET); 1520*33ec1ccbSHans Petter Selasky 1521*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->cap_mask, SET_IB_CAP_MASK_OFFSET); 1522*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, param->si_guid, SET_IB_SI_GUID_OFFSET); 1523*33ec1ccbSHans Petter Selasky 1524*33ec1ccbSHans Petter Selasky err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_SET_IB, 1525*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_B); 1526*33ec1ccbSHans Petter Selasky 1527*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox); 1528*33ec1ccbSHans Petter Selasky return err; 1529*33ec1ccbSHans Petter Selasky } 1530*33ec1ccbSHans Petter Selasky 1531*33ec1ccbSHans Petter Selasky int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt) 1532*33ec1ccbSHans Petter Selasky { 1533*33ec1ccbSHans Petter Selasky return mthca_map_cmd(dev, CMD_MAP_ICM, icm, virt); 1534*33ec1ccbSHans Petter Selasky } 1535*33ec1ccbSHans Petter Selasky 1536*33ec1ccbSHans Petter Selasky int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt) 1537*33ec1ccbSHans Petter Selasky { 1538*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox; 1539*33ec1ccbSHans Petter Selasky __be64 *inbox; 1540*33ec1ccbSHans Petter Selasky int err; 1541*33ec1ccbSHans Petter Selasky 1542*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 1543*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox)) 1544*33ec1ccbSHans Petter Selasky return PTR_ERR(mailbox); 1545*33ec1ccbSHans Petter Selasky inbox = mailbox->buf; 1546*33ec1ccbSHans Petter Selasky 1547*33ec1ccbSHans Petter Selasky inbox[0] = cpu_to_be64(virt); 1548*33ec1ccbSHans Petter Selasky inbox[1] = cpu_to_be64(dma_addr); 1549*33ec1ccbSHans Petter Selasky 1550*33ec1ccbSHans Petter Selasky err = mthca_cmd(dev, mailbox->dma, 1, 0, CMD_MAP_ICM, 1551*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_B); 1552*33ec1ccbSHans Petter Selasky 1553*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox); 1554*33ec1ccbSHans Petter Selasky 1555*33ec1ccbSHans Petter Selasky if (!err) 1556*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Mapped page at %llx to %llx for ICM.\n", 1557*33ec1ccbSHans Petter Selasky (unsigned long long) dma_addr, (unsigned long long) virt); 1558*33ec1ccbSHans Petter Selasky 1559*33ec1ccbSHans Petter Selasky return err; 1560*33ec1ccbSHans Petter Selasky } 1561*33ec1ccbSHans Petter Selasky 1562*33ec1ccbSHans Petter Selasky int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count) 1563*33ec1ccbSHans Petter Selasky { 1564*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Unmapping %d pages at %llx from ICM.\n", 1565*33ec1ccbSHans Petter Selasky page_count, (unsigned long long) virt); 1566*33ec1ccbSHans Petter Selasky 1567*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, virt, page_count, 0, 1568*33ec1ccbSHans Petter Selasky CMD_UNMAP_ICM, CMD_TIME_CLASS_B); 1569*33ec1ccbSHans Petter Selasky } 1570*33ec1ccbSHans Petter Selasky 1571*33ec1ccbSHans Petter Selasky int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm) 1572*33ec1ccbSHans Petter Selasky { 1573*33ec1ccbSHans Petter Selasky return mthca_map_cmd(dev, CMD_MAP_ICM_AUX, icm, -1); 1574*33ec1ccbSHans Petter Selasky } 1575*33ec1ccbSHans Petter Selasky 1576*33ec1ccbSHans Petter Selasky int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev) 1577*33ec1ccbSHans Petter Selasky { 1578*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_ICM_AUX, CMD_TIME_CLASS_B); 1579*33ec1ccbSHans Petter Selasky } 1580*33ec1ccbSHans Petter Selasky 1581*33ec1ccbSHans Petter Selasky int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages) 1582*33ec1ccbSHans Petter Selasky { 1583*33ec1ccbSHans Petter Selasky int ret = mthca_cmd_imm(dev, icm_size, aux_pages, 0, 1584*33ec1ccbSHans Petter Selasky 0, CMD_SET_ICM_SIZE, CMD_TIME_CLASS_A); 1585*33ec1ccbSHans Petter Selasky 1586*33ec1ccbSHans Petter Selasky if (ret) 1587*33ec1ccbSHans Petter Selasky return ret; 1588*33ec1ccbSHans Petter Selasky 1589*33ec1ccbSHans Petter Selasky /* 1590*33ec1ccbSHans Petter Selasky * Round up number of system pages needed in case 1591*33ec1ccbSHans Petter Selasky * MTHCA_ICM_PAGE_SIZE < PAGE_SIZE. 1592*33ec1ccbSHans Petter Selasky */ 1593*33ec1ccbSHans Petter Selasky *aux_pages = ALIGN(*aux_pages, PAGE_SIZE / MTHCA_ICM_PAGE_SIZE) >> 1594*33ec1ccbSHans Petter Selasky (PAGE_SHIFT - MTHCA_ICM_PAGE_SHIFT); 1595*33ec1ccbSHans Petter Selasky 1596*33ec1ccbSHans Petter Selasky return 0; 1597*33ec1ccbSHans Petter Selasky } 1598*33ec1ccbSHans Petter Selasky 1599*33ec1ccbSHans Petter Selasky int mthca_SW2HW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox, 1600*33ec1ccbSHans Petter Selasky int mpt_index) 1601*33ec1ccbSHans Petter Selasky { 1602*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, mailbox->dma, mpt_index, 0, CMD_SW2HW_MPT, 1603*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_B); 1604*33ec1ccbSHans Petter Selasky } 1605*33ec1ccbSHans Petter Selasky 1606*33ec1ccbSHans Petter Selasky int mthca_HW2SW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox, 1607*33ec1ccbSHans Petter Selasky int mpt_index) 1608*33ec1ccbSHans Petter Selasky { 1609*33ec1ccbSHans Petter Selasky return mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, mpt_index, 1610*33ec1ccbSHans Petter Selasky !mailbox, CMD_HW2SW_MPT, 1611*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_B); 1612*33ec1ccbSHans Petter Selasky } 1613*33ec1ccbSHans Petter Selasky 1614*33ec1ccbSHans Petter Selasky int mthca_WRITE_MTT(struct mthca_dev *dev, struct mthca_mailbox *mailbox, 1615*33ec1ccbSHans Petter Selasky int num_mtt) 1616*33ec1ccbSHans Petter Selasky { 1617*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, mailbox->dma, num_mtt, 0, CMD_WRITE_MTT, 1618*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_B); 1619*33ec1ccbSHans Petter Selasky } 1620*33ec1ccbSHans Petter Selasky 1621*33ec1ccbSHans Petter Selasky int mthca_SYNC_TPT(struct mthca_dev *dev) 1622*33ec1ccbSHans Petter Selasky { 1623*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, 0, 0, 0, CMD_SYNC_TPT, CMD_TIME_CLASS_B); 1624*33ec1ccbSHans Petter Selasky } 1625*33ec1ccbSHans Petter Selasky 1626*33ec1ccbSHans Petter Selasky int mthca_MAP_EQ(struct mthca_dev *dev, u64 event_mask, int unmap, 1627*33ec1ccbSHans Petter Selasky int eq_num) 1628*33ec1ccbSHans Petter Selasky { 1629*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "%s mask %016llx for eqn %d\n", 1630*33ec1ccbSHans Petter Selasky unmap ? "Clearing" : "Setting", 1631*33ec1ccbSHans Petter Selasky (unsigned long long) event_mask, eq_num); 1632*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, event_mask, (unmap << 31) | eq_num, 1633*33ec1ccbSHans Petter Selasky 0, CMD_MAP_EQ, CMD_TIME_CLASS_B); 1634*33ec1ccbSHans Petter Selasky } 1635*33ec1ccbSHans Petter Selasky 1636*33ec1ccbSHans Petter Selasky int mthca_SW2HW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, 1637*33ec1ccbSHans Petter Selasky int eq_num) 1638*33ec1ccbSHans Petter Selasky { 1639*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, mailbox->dma, eq_num, 0, CMD_SW2HW_EQ, 1640*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A); 1641*33ec1ccbSHans Petter Selasky } 1642*33ec1ccbSHans Petter Selasky 1643*33ec1ccbSHans Petter Selasky int mthca_HW2SW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, 1644*33ec1ccbSHans Petter Selasky int eq_num) 1645*33ec1ccbSHans Petter Selasky { 1646*33ec1ccbSHans Petter Selasky return mthca_cmd_box(dev, 0, mailbox->dma, eq_num, 0, 1647*33ec1ccbSHans Petter Selasky CMD_HW2SW_EQ, 1648*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A); 1649*33ec1ccbSHans Petter Selasky } 1650*33ec1ccbSHans Petter Selasky 1651*33ec1ccbSHans Petter Selasky int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, 1652*33ec1ccbSHans Petter Selasky int cq_num) 1653*33ec1ccbSHans Petter Selasky { 1654*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, mailbox->dma, cq_num, 0, CMD_SW2HW_CQ, 1655*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A); 1656*33ec1ccbSHans Petter Selasky } 1657*33ec1ccbSHans Petter Selasky 1658*33ec1ccbSHans Petter Selasky int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, 1659*33ec1ccbSHans Petter Selasky int cq_num) 1660*33ec1ccbSHans Petter Selasky { 1661*33ec1ccbSHans Petter Selasky return mthca_cmd_box(dev, 0, mailbox->dma, cq_num, 0, 1662*33ec1ccbSHans Petter Selasky CMD_HW2SW_CQ, 1663*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A); 1664*33ec1ccbSHans Petter Selasky } 1665*33ec1ccbSHans Petter Selasky 1666*33ec1ccbSHans Petter Selasky int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size) 1667*33ec1ccbSHans Petter Selasky { 1668*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox; 1669*33ec1ccbSHans Petter Selasky __be32 *inbox; 1670*33ec1ccbSHans Petter Selasky int err; 1671*33ec1ccbSHans Petter Selasky 1672*33ec1ccbSHans Petter Selasky #define RESIZE_CQ_IN_SIZE 0x40 1673*33ec1ccbSHans Petter Selasky #define RESIZE_CQ_LOG_SIZE_OFFSET 0x0c 1674*33ec1ccbSHans Petter Selasky #define RESIZE_CQ_LKEY_OFFSET 0x1c 1675*33ec1ccbSHans Petter Selasky 1676*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 1677*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox)) 1678*33ec1ccbSHans Petter Selasky return PTR_ERR(mailbox); 1679*33ec1ccbSHans Petter Selasky inbox = mailbox->buf; 1680*33ec1ccbSHans Petter Selasky 1681*33ec1ccbSHans Petter Selasky memset(inbox, 0, RESIZE_CQ_IN_SIZE); 1682*33ec1ccbSHans Petter Selasky /* 1683*33ec1ccbSHans Petter Selasky * Leave start address fields zeroed out -- mthca assumes that 1684*33ec1ccbSHans Petter Selasky * MRs for CQs always start at virtual address 0. 1685*33ec1ccbSHans Petter Selasky */ 1686*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, log_size, RESIZE_CQ_LOG_SIZE_OFFSET); 1687*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, lkey, RESIZE_CQ_LKEY_OFFSET); 1688*33ec1ccbSHans Petter Selasky 1689*33ec1ccbSHans Petter Selasky err = mthca_cmd(dev, mailbox->dma, cq_num, 1, CMD_RESIZE_CQ, 1690*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_B); 1691*33ec1ccbSHans Petter Selasky 1692*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox); 1693*33ec1ccbSHans Petter Selasky return err; 1694*33ec1ccbSHans Petter Selasky } 1695*33ec1ccbSHans Petter Selasky 1696*33ec1ccbSHans Petter Selasky int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, 1697*33ec1ccbSHans Petter Selasky int srq_num) 1698*33ec1ccbSHans Petter Selasky { 1699*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, mailbox->dma, srq_num, 0, CMD_SW2HW_SRQ, 1700*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A); 1701*33ec1ccbSHans Petter Selasky } 1702*33ec1ccbSHans Petter Selasky 1703*33ec1ccbSHans Petter Selasky int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, 1704*33ec1ccbSHans Petter Selasky int srq_num) 1705*33ec1ccbSHans Petter Selasky { 1706*33ec1ccbSHans Petter Selasky return mthca_cmd_box(dev, 0, mailbox->dma, srq_num, 0, 1707*33ec1ccbSHans Petter Selasky CMD_HW2SW_SRQ, 1708*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A); 1709*33ec1ccbSHans Petter Selasky } 1710*33ec1ccbSHans Petter Selasky 1711*33ec1ccbSHans Petter Selasky int mthca_QUERY_SRQ(struct mthca_dev *dev, u32 num, 1712*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox) 1713*33ec1ccbSHans Petter Selasky { 1714*33ec1ccbSHans Petter Selasky return mthca_cmd_box(dev, 0, mailbox->dma, num, 0, 1715*33ec1ccbSHans Petter Selasky CMD_QUERY_SRQ, CMD_TIME_CLASS_A); 1716*33ec1ccbSHans Petter Selasky } 1717*33ec1ccbSHans Petter Selasky 1718*33ec1ccbSHans Petter Selasky int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit) 1719*33ec1ccbSHans Petter Selasky { 1720*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, limit, srq_num, 0, CMD_ARM_SRQ, 1721*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_B); 1722*33ec1ccbSHans Petter Selasky } 1723*33ec1ccbSHans Petter Selasky 1724*33ec1ccbSHans Petter Selasky int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur, 1725*33ec1ccbSHans Petter Selasky enum ib_qp_state next, u32 num, int is_ee, 1726*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox, u32 optmask) 1727*33ec1ccbSHans Petter Selasky { 1728*33ec1ccbSHans Petter Selasky static const u16 op[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { 1729*33ec1ccbSHans Petter Selasky [IB_QPS_RESET] = { 1730*33ec1ccbSHans Petter Selasky [IB_QPS_RESET] = CMD_ERR2RST_QPEE, 1731*33ec1ccbSHans Petter Selasky [IB_QPS_ERR] = CMD_2ERR_QPEE, 1732*33ec1ccbSHans Petter Selasky [IB_QPS_INIT] = CMD_RST2INIT_QPEE, 1733*33ec1ccbSHans Petter Selasky }, 1734*33ec1ccbSHans Petter Selasky [IB_QPS_INIT] = { 1735*33ec1ccbSHans Petter Selasky [IB_QPS_RESET] = CMD_ERR2RST_QPEE, 1736*33ec1ccbSHans Petter Selasky [IB_QPS_ERR] = CMD_2ERR_QPEE, 1737*33ec1ccbSHans Petter Selasky [IB_QPS_INIT] = CMD_INIT2INIT_QPEE, 1738*33ec1ccbSHans Petter Selasky [IB_QPS_RTR] = CMD_INIT2RTR_QPEE, 1739*33ec1ccbSHans Petter Selasky }, 1740*33ec1ccbSHans Petter Selasky [IB_QPS_RTR] = { 1741*33ec1ccbSHans Petter Selasky [IB_QPS_RESET] = CMD_ERR2RST_QPEE, 1742*33ec1ccbSHans Petter Selasky [IB_QPS_ERR] = CMD_2ERR_QPEE, 1743*33ec1ccbSHans Petter Selasky [IB_QPS_RTS] = CMD_RTR2RTS_QPEE, 1744*33ec1ccbSHans Petter Selasky }, 1745*33ec1ccbSHans Petter Selasky [IB_QPS_RTS] = { 1746*33ec1ccbSHans Petter Selasky [IB_QPS_RESET] = CMD_ERR2RST_QPEE, 1747*33ec1ccbSHans Petter Selasky [IB_QPS_ERR] = CMD_2ERR_QPEE, 1748*33ec1ccbSHans Petter Selasky [IB_QPS_RTS] = CMD_RTS2RTS_QPEE, 1749*33ec1ccbSHans Petter Selasky [IB_QPS_SQD] = CMD_RTS2SQD_QPEE, 1750*33ec1ccbSHans Petter Selasky }, 1751*33ec1ccbSHans Petter Selasky [IB_QPS_SQD] = { 1752*33ec1ccbSHans Petter Selasky [IB_QPS_RESET] = CMD_ERR2RST_QPEE, 1753*33ec1ccbSHans Petter Selasky [IB_QPS_ERR] = CMD_2ERR_QPEE, 1754*33ec1ccbSHans Petter Selasky [IB_QPS_RTS] = CMD_SQD2RTS_QPEE, 1755*33ec1ccbSHans Petter Selasky [IB_QPS_SQD] = CMD_SQD2SQD_QPEE, 1756*33ec1ccbSHans Petter Selasky }, 1757*33ec1ccbSHans Petter Selasky [IB_QPS_SQE] = { 1758*33ec1ccbSHans Petter Selasky [IB_QPS_RESET] = CMD_ERR2RST_QPEE, 1759*33ec1ccbSHans Petter Selasky [IB_QPS_ERR] = CMD_2ERR_QPEE, 1760*33ec1ccbSHans Petter Selasky [IB_QPS_RTS] = CMD_SQERR2RTS_QPEE, 1761*33ec1ccbSHans Petter Selasky }, 1762*33ec1ccbSHans Petter Selasky [IB_QPS_ERR] = { 1763*33ec1ccbSHans Petter Selasky [IB_QPS_RESET] = CMD_ERR2RST_QPEE, 1764*33ec1ccbSHans Petter Selasky [IB_QPS_ERR] = CMD_2ERR_QPEE, 1765*33ec1ccbSHans Petter Selasky } 1766*33ec1ccbSHans Petter Selasky }; 1767*33ec1ccbSHans Petter Selasky 1768*33ec1ccbSHans Petter Selasky u8 op_mod = 0; 1769*33ec1ccbSHans Petter Selasky int my_mailbox = 0; 1770*33ec1ccbSHans Petter Selasky int err; 1771*33ec1ccbSHans Petter Selasky 1772*33ec1ccbSHans Petter Selasky if (op[cur][next] == CMD_ERR2RST_QPEE) { 1773*33ec1ccbSHans Petter Selasky op_mod = 3; /* don't write outbox, any->reset */ 1774*33ec1ccbSHans Petter Selasky 1775*33ec1ccbSHans Petter Selasky /* For debugging */ 1776*33ec1ccbSHans Petter Selasky if (!mailbox) { 1777*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 1778*33ec1ccbSHans Petter Selasky if (!IS_ERR(mailbox)) { 1779*33ec1ccbSHans Petter Selasky my_mailbox = 1; 1780*33ec1ccbSHans Petter Selasky op_mod = 2; /* write outbox, any->reset */ 1781*33ec1ccbSHans Petter Selasky } else 1782*33ec1ccbSHans Petter Selasky mailbox = NULL; 1783*33ec1ccbSHans Petter Selasky } 1784*33ec1ccbSHans Petter Selasky 1785*33ec1ccbSHans Petter Selasky err = mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, 1786*33ec1ccbSHans Petter Selasky (!!is_ee << 24) | num, op_mod, 1787*33ec1ccbSHans Petter Selasky op[cur][next], CMD_TIME_CLASS_C); 1788*33ec1ccbSHans Petter Selasky 1789*33ec1ccbSHans Petter Selasky if (0 && mailbox) { 1790*33ec1ccbSHans Petter Selasky int i; 1791*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Dumping QP context:\n"); 1792*33ec1ccbSHans Petter Selasky printk(" %08x\n", be32_to_cpup(mailbox->buf)); 1793*33ec1ccbSHans Petter Selasky for (i = 0; i < 0x100 / 4; ++i) { 1794*33ec1ccbSHans Petter Selasky if (i % 8 == 0) 1795*33ec1ccbSHans Petter Selasky printk("[%02x] ", i * 4); 1796*33ec1ccbSHans Petter Selasky printk(" %08x", 1797*33ec1ccbSHans Petter Selasky be32_to_cpu(((__be32 *) mailbox->buf)[i + 2])); 1798*33ec1ccbSHans Petter Selasky if ((i + 1) % 8 == 0) 1799*33ec1ccbSHans Petter Selasky printk("\n"); 1800*33ec1ccbSHans Petter Selasky } 1801*33ec1ccbSHans Petter Selasky } 1802*33ec1ccbSHans Petter Selasky 1803*33ec1ccbSHans Petter Selasky if (my_mailbox) 1804*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox); 1805*33ec1ccbSHans Petter Selasky } else { 1806*33ec1ccbSHans Petter Selasky if (0) { 1807*33ec1ccbSHans Petter Selasky int i; 1808*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Dumping QP context:\n"); 1809*33ec1ccbSHans Petter Selasky printk(" opt param mask: %08x\n", be32_to_cpup(mailbox->buf)); 1810*33ec1ccbSHans Petter Selasky for (i = 0; i < 0x100 / 4; ++i) { 1811*33ec1ccbSHans Petter Selasky if (i % 8 == 0) 1812*33ec1ccbSHans Petter Selasky printk(" [%02x] ", i * 4); 1813*33ec1ccbSHans Petter Selasky printk(" %08x", 1814*33ec1ccbSHans Petter Selasky be32_to_cpu(((__be32 *) mailbox->buf)[i + 2])); 1815*33ec1ccbSHans Petter Selasky if ((i + 1) % 8 == 0) 1816*33ec1ccbSHans Petter Selasky printk("\n"); 1817*33ec1ccbSHans Petter Selasky } 1818*33ec1ccbSHans Petter Selasky } 1819*33ec1ccbSHans Petter Selasky 1820*33ec1ccbSHans Petter Selasky err = mthca_cmd(dev, mailbox->dma, optmask | (!!is_ee << 24) | num, 1821*33ec1ccbSHans Petter Selasky op_mod, op[cur][next], CMD_TIME_CLASS_C); 1822*33ec1ccbSHans Petter Selasky } 1823*33ec1ccbSHans Petter Selasky 1824*33ec1ccbSHans Petter Selasky return err; 1825*33ec1ccbSHans Petter Selasky } 1826*33ec1ccbSHans Petter Selasky 1827*33ec1ccbSHans Petter Selasky int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee, 1828*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox) 1829*33ec1ccbSHans Petter Selasky { 1830*33ec1ccbSHans Petter Selasky return mthca_cmd_box(dev, 0, mailbox->dma, (!!is_ee << 24) | num, 0, 1831*33ec1ccbSHans Petter Selasky CMD_QUERY_QPEE, CMD_TIME_CLASS_A); 1832*33ec1ccbSHans Petter Selasky } 1833*33ec1ccbSHans Petter Selasky 1834*33ec1ccbSHans Petter Selasky int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn) 1835*33ec1ccbSHans Petter Selasky { 1836*33ec1ccbSHans Petter Selasky u8 op_mod; 1837*33ec1ccbSHans Petter Selasky 1838*33ec1ccbSHans Petter Selasky switch (type) { 1839*33ec1ccbSHans Petter Selasky case IB_QPT_SMI: 1840*33ec1ccbSHans Petter Selasky op_mod = 0; 1841*33ec1ccbSHans Petter Selasky break; 1842*33ec1ccbSHans Petter Selasky case IB_QPT_GSI: 1843*33ec1ccbSHans Petter Selasky op_mod = 1; 1844*33ec1ccbSHans Petter Selasky break; 1845*33ec1ccbSHans Petter Selasky case IB_QPT_RAW_IPV6: 1846*33ec1ccbSHans Petter Selasky op_mod = 2; 1847*33ec1ccbSHans Petter Selasky break; 1848*33ec1ccbSHans Petter Selasky case IB_QPT_RAW_ETHERTYPE: 1849*33ec1ccbSHans Petter Selasky op_mod = 3; 1850*33ec1ccbSHans Petter Selasky break; 1851*33ec1ccbSHans Petter Selasky default: 1852*33ec1ccbSHans Petter Selasky return -EINVAL; 1853*33ec1ccbSHans Petter Selasky } 1854*33ec1ccbSHans Petter Selasky 1855*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, 0, qpn, op_mod, CMD_CONF_SPECIAL_QP, 1856*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_B); 1857*33ec1ccbSHans Petter Selasky } 1858*33ec1ccbSHans Petter Selasky 1859*33ec1ccbSHans Petter Selasky int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, 1860*33ec1ccbSHans Petter Selasky int port, const struct ib_wc *in_wc, const struct ib_grh *in_grh, 1861*33ec1ccbSHans Petter Selasky const void *in_mad, void *response_mad) 1862*33ec1ccbSHans Petter Selasky { 1863*33ec1ccbSHans Petter Selasky struct mthca_mailbox *inmailbox, *outmailbox; 1864*33ec1ccbSHans Petter Selasky void *inbox; 1865*33ec1ccbSHans Petter Selasky int err; 1866*33ec1ccbSHans Petter Selasky u32 in_modifier = port; 1867*33ec1ccbSHans Petter Selasky u8 op_modifier = 0; 1868*33ec1ccbSHans Petter Selasky 1869*33ec1ccbSHans Petter Selasky #define MAD_IFC_BOX_SIZE 0x400 1870*33ec1ccbSHans Petter Selasky #define MAD_IFC_MY_QPN_OFFSET 0x100 1871*33ec1ccbSHans Petter Selasky #define MAD_IFC_RQPN_OFFSET 0x108 1872*33ec1ccbSHans Petter Selasky #define MAD_IFC_SL_OFFSET 0x10c 1873*33ec1ccbSHans Petter Selasky #define MAD_IFC_G_PATH_OFFSET 0x10d 1874*33ec1ccbSHans Petter Selasky #define MAD_IFC_RLID_OFFSET 0x10e 1875*33ec1ccbSHans Petter Selasky #define MAD_IFC_PKEY_OFFSET 0x112 1876*33ec1ccbSHans Petter Selasky #define MAD_IFC_GRH_OFFSET 0x140 1877*33ec1ccbSHans Petter Selasky 1878*33ec1ccbSHans Petter Selasky inmailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 1879*33ec1ccbSHans Petter Selasky if (IS_ERR(inmailbox)) 1880*33ec1ccbSHans Petter Selasky return PTR_ERR(inmailbox); 1881*33ec1ccbSHans Petter Selasky inbox = inmailbox->buf; 1882*33ec1ccbSHans Petter Selasky 1883*33ec1ccbSHans Petter Selasky outmailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 1884*33ec1ccbSHans Petter Selasky if (IS_ERR(outmailbox)) { 1885*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, inmailbox); 1886*33ec1ccbSHans Petter Selasky return PTR_ERR(outmailbox); 1887*33ec1ccbSHans Petter Selasky } 1888*33ec1ccbSHans Petter Selasky 1889*33ec1ccbSHans Petter Selasky memcpy(inbox, in_mad, 256); 1890*33ec1ccbSHans Petter Selasky 1891*33ec1ccbSHans Petter Selasky /* 1892*33ec1ccbSHans Petter Selasky * Key check traps can't be generated unless we have in_wc to 1893*33ec1ccbSHans Petter Selasky * tell us where to send the trap. 1894*33ec1ccbSHans Petter Selasky */ 1895*33ec1ccbSHans Petter Selasky if (ignore_mkey || !in_wc) 1896*33ec1ccbSHans Petter Selasky op_modifier |= 0x1; 1897*33ec1ccbSHans Petter Selasky if (ignore_bkey || !in_wc) 1898*33ec1ccbSHans Petter Selasky op_modifier |= 0x2; 1899*33ec1ccbSHans Petter Selasky 1900*33ec1ccbSHans Petter Selasky if (in_wc) { 1901*33ec1ccbSHans Petter Selasky u8 val; 1902*33ec1ccbSHans Petter Selasky 1903*33ec1ccbSHans Petter Selasky memset(inbox + 256, 0, 256); 1904*33ec1ccbSHans Petter Selasky 1905*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, in_wc->qp->qp_num, MAD_IFC_MY_QPN_OFFSET); 1906*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, in_wc->src_qp, MAD_IFC_RQPN_OFFSET); 1907*33ec1ccbSHans Petter Selasky 1908*33ec1ccbSHans Petter Selasky val = in_wc->sl << 4; 1909*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, val, MAD_IFC_SL_OFFSET); 1910*33ec1ccbSHans Petter Selasky 1911*33ec1ccbSHans Petter Selasky val = in_wc->dlid_path_bits | 1912*33ec1ccbSHans Petter Selasky (in_wc->wc_flags & IB_WC_GRH ? 0x80 : 0); 1913*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, val, MAD_IFC_G_PATH_OFFSET); 1914*33ec1ccbSHans Petter Selasky 1915*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, in_wc->slid, MAD_IFC_RLID_OFFSET); 1916*33ec1ccbSHans Petter Selasky MTHCA_PUT(inbox, in_wc->pkey_index, MAD_IFC_PKEY_OFFSET); 1917*33ec1ccbSHans Petter Selasky 1918*33ec1ccbSHans Petter Selasky if (in_grh) 1919*33ec1ccbSHans Petter Selasky memcpy(inbox + MAD_IFC_GRH_OFFSET, in_grh, 40); 1920*33ec1ccbSHans Petter Selasky 1921*33ec1ccbSHans Petter Selasky op_modifier |= 0x4; 1922*33ec1ccbSHans Petter Selasky 1923*33ec1ccbSHans Petter Selasky in_modifier |= in_wc->slid << 16; 1924*33ec1ccbSHans Petter Selasky } 1925*33ec1ccbSHans Petter Selasky 1926*33ec1ccbSHans Petter Selasky err = mthca_cmd_box(dev, inmailbox->dma, outmailbox->dma, 1927*33ec1ccbSHans Petter Selasky in_modifier, op_modifier, 1928*33ec1ccbSHans Petter Selasky CMD_MAD_IFC, CMD_TIME_CLASS_C); 1929*33ec1ccbSHans Petter Selasky 1930*33ec1ccbSHans Petter Selasky if (!err) 1931*33ec1ccbSHans Petter Selasky memcpy(response_mad, outmailbox->buf, 256); 1932*33ec1ccbSHans Petter Selasky 1933*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, inmailbox); 1934*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, outmailbox); 1935*33ec1ccbSHans Petter Selasky return err; 1936*33ec1ccbSHans Petter Selasky } 1937*33ec1ccbSHans Petter Selasky 1938*33ec1ccbSHans Petter Selasky int mthca_READ_MGM(struct mthca_dev *dev, int index, 1939*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox) 1940*33ec1ccbSHans Petter Selasky { 1941*33ec1ccbSHans Petter Selasky return mthca_cmd_box(dev, 0, mailbox->dma, index, 0, 1942*33ec1ccbSHans Petter Selasky CMD_READ_MGM, CMD_TIME_CLASS_A); 1943*33ec1ccbSHans Petter Selasky } 1944*33ec1ccbSHans Petter Selasky 1945*33ec1ccbSHans Petter Selasky int mthca_WRITE_MGM(struct mthca_dev *dev, int index, 1946*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox) 1947*33ec1ccbSHans Petter Selasky { 1948*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, mailbox->dma, index, 0, CMD_WRITE_MGM, 1949*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A); 1950*33ec1ccbSHans Petter Selasky } 1951*33ec1ccbSHans Petter Selasky 1952*33ec1ccbSHans Petter Selasky int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox, 1953*33ec1ccbSHans Petter Selasky u16 *hash) 1954*33ec1ccbSHans Petter Selasky { 1955*33ec1ccbSHans Petter Selasky u64 imm; 1956*33ec1ccbSHans Petter Selasky int err; 1957*33ec1ccbSHans Petter Selasky 1958*33ec1ccbSHans Petter Selasky err = mthca_cmd_imm(dev, mailbox->dma, &imm, 0, 0, CMD_MGID_HASH, 1959*33ec1ccbSHans Petter Selasky CMD_TIME_CLASS_A); 1960*33ec1ccbSHans Petter Selasky 1961*33ec1ccbSHans Petter Selasky *hash = imm; 1962*33ec1ccbSHans Petter Selasky return err; 1963*33ec1ccbSHans Petter Selasky } 1964*33ec1ccbSHans Petter Selasky 1965*33ec1ccbSHans Petter Selasky int mthca_NOP(struct mthca_dev *dev) 1966*33ec1ccbSHans Petter Selasky { 1967*33ec1ccbSHans Petter Selasky return mthca_cmd(dev, 0, 0x1f, 0, CMD_NOP, msecs_to_jiffies(100)); 1968*33ec1ccbSHans Petter Selasky } 1969