15a2cc190SJeff Kirsher /* 25a2cc190SJeff Kirsher * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. 35a2cc190SJeff Kirsher * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved. 45a2cc190SJeff Kirsher * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved. 55a2cc190SJeff Kirsher * 65a2cc190SJeff Kirsher * This software is available to you under a choice of one of two 75a2cc190SJeff Kirsher * licenses. You may choose to be licensed under the terms of the GNU 85a2cc190SJeff Kirsher * General Public License (GPL) Version 2, available from the file 95a2cc190SJeff Kirsher * COPYING in the main directory of this source tree, or the 105a2cc190SJeff Kirsher * OpenIB.org BSD license below: 115a2cc190SJeff Kirsher * 125a2cc190SJeff Kirsher * Redistribution and use in source and binary forms, with or 135a2cc190SJeff Kirsher * without modification, are permitted provided that the following 145a2cc190SJeff Kirsher * conditions are met: 155a2cc190SJeff Kirsher * 165a2cc190SJeff Kirsher * - Redistributions of source code must retain the above 175a2cc190SJeff Kirsher * copyright notice, this list of conditions and the following 185a2cc190SJeff Kirsher * disclaimer. 195a2cc190SJeff Kirsher * 205a2cc190SJeff Kirsher * - Redistributions in binary form must reproduce the above 215a2cc190SJeff Kirsher * copyright notice, this list of conditions and the following 225a2cc190SJeff Kirsher * disclaimer in the documentation and/or other materials 235a2cc190SJeff Kirsher * provided with the distribution. 245a2cc190SJeff Kirsher * 255a2cc190SJeff Kirsher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 265a2cc190SJeff Kirsher * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 275a2cc190SJeff Kirsher * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 285a2cc190SJeff Kirsher * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 295a2cc190SJeff Kirsher * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 305a2cc190SJeff Kirsher * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 315a2cc190SJeff Kirsher * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 325a2cc190SJeff Kirsher * SOFTWARE. 335a2cc190SJeff Kirsher */ 345a2cc190SJeff Kirsher 355cc914f1SMarcel Apfelbaum #include <linux/etherdevice.h> 365a2cc190SJeff Kirsher #include <linux/mlx4/cmd.h> 379d9779e7SPaul Gortmaker #include <linux/module.h> 385a2cc190SJeff Kirsher #include <linux/cache.h> 395a2cc190SJeff Kirsher 405a2cc190SJeff Kirsher #include "fw.h" 415a2cc190SJeff Kirsher #include "icm.h" 425a2cc190SJeff Kirsher 435a2cc190SJeff Kirsher enum { 445a2cc190SJeff Kirsher MLX4_COMMAND_INTERFACE_MIN_REV = 2, 455a2cc190SJeff Kirsher MLX4_COMMAND_INTERFACE_MAX_REV = 3, 465a2cc190SJeff Kirsher MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS = 3, 475a2cc190SJeff Kirsher }; 485a2cc190SJeff Kirsher 495a2cc190SJeff Kirsher extern void __buggy_use_of_MLX4_GET(void); 505a2cc190SJeff Kirsher extern void __buggy_use_of_MLX4_PUT(void); 515a2cc190SJeff Kirsher 52eb939922SRusty Russell static bool enable_qos; 535a2cc190SJeff Kirsher module_param(enable_qos, bool, 0444); 545a2cc190SJeff Kirsher MODULE_PARM_DESC(enable_qos, "Enable Quality of Service support in the HCA (default: off)"); 555a2cc190SJeff Kirsher 565a2cc190SJeff Kirsher #define MLX4_GET(dest, source, offset) \ 575a2cc190SJeff Kirsher do { \ 585a2cc190SJeff Kirsher void *__p = (char *) (source) + (offset); \ 595a2cc190SJeff Kirsher switch (sizeof (dest)) { \ 605a2cc190SJeff Kirsher case 1: (dest) = *(u8 *) __p; break; \ 615a2cc190SJeff Kirsher case 2: (dest) = be16_to_cpup(__p); break; \ 625a2cc190SJeff Kirsher case 4: (dest) = be32_to_cpup(__p); break; \ 635a2cc190SJeff Kirsher case 8: (dest) = be64_to_cpup(__p); break; \ 645a2cc190SJeff Kirsher default: __buggy_use_of_MLX4_GET(); \ 655a2cc190SJeff Kirsher } \ 665a2cc190SJeff Kirsher } while (0) 675a2cc190SJeff Kirsher 685a2cc190SJeff Kirsher #define MLX4_PUT(dest, source, offset) \ 695a2cc190SJeff Kirsher do { \ 705a2cc190SJeff Kirsher void *__d = ((char *) (dest) + (offset)); \ 715a2cc190SJeff Kirsher switch (sizeof(source)) { \ 725a2cc190SJeff Kirsher case 1: *(u8 *) __d = (source); break; \ 735a2cc190SJeff Kirsher case 2: *(__be16 *) __d = cpu_to_be16(source); break; \ 745a2cc190SJeff Kirsher case 4: *(__be32 *) __d = cpu_to_be32(source); break; \ 755a2cc190SJeff Kirsher case 8: *(__be64 *) __d = cpu_to_be64(source); break; \ 765a2cc190SJeff Kirsher default: __buggy_use_of_MLX4_PUT(); \ 775a2cc190SJeff Kirsher } \ 785a2cc190SJeff Kirsher } while (0) 795a2cc190SJeff Kirsher 805a2cc190SJeff Kirsher static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags) 815a2cc190SJeff Kirsher { 825a2cc190SJeff Kirsher static const char *fname[] = { 835a2cc190SJeff Kirsher [ 0] = "RC transport", 845a2cc190SJeff Kirsher [ 1] = "UC transport", 855a2cc190SJeff Kirsher [ 2] = "UD transport", 865a2cc190SJeff Kirsher [ 3] = "XRC transport", 875a2cc190SJeff Kirsher [ 4] = "reliable multicast", 885a2cc190SJeff Kirsher [ 5] = "FCoIB support", 895a2cc190SJeff Kirsher [ 6] = "SRQ support", 905a2cc190SJeff Kirsher [ 7] = "IPoIB checksum offload", 915a2cc190SJeff Kirsher [ 8] = "P_Key violation counter", 925a2cc190SJeff Kirsher [ 9] = "Q_Key violation counter", 935a2cc190SJeff Kirsher [10] = "VMM", 944d531aa8SOr Gerlitz [12] = "Dual Port Different Protocol (DPDP) support", 955a2cc190SJeff Kirsher [15] = "Big LSO headers", 965a2cc190SJeff Kirsher [16] = "MW support", 975a2cc190SJeff Kirsher [17] = "APM support", 985a2cc190SJeff Kirsher [18] = "Atomic ops support", 995a2cc190SJeff Kirsher [19] = "Raw multicast support", 1005a2cc190SJeff Kirsher [20] = "Address vector port checking support", 1015a2cc190SJeff Kirsher [21] = "UD multicast support", 1025a2cc190SJeff Kirsher [24] = "Demand paging support", 1035a2cc190SJeff Kirsher [25] = "Router support", 1045a2cc190SJeff Kirsher [30] = "IBoE support", 1055a2cc190SJeff Kirsher [32] = "Unicast loopback support", 106f3a9d1f2SYevgeny Petrilin [34] = "FCS header control", 1075a2cc190SJeff Kirsher [38] = "Wake On LAN support", 1085a2cc190SJeff Kirsher [40] = "UDP RSS support", 1095a2cc190SJeff Kirsher [41] = "Unicast VEP steering support", 1105a2cc190SJeff Kirsher [42] = "Multicast VEP steering support", 1115a2cc190SJeff Kirsher [48] = "Counters support", 112540b3a39SOr Gerlitz [53] = "Port ETS Scheduler support", 1134d531aa8SOr Gerlitz [55] = "Port link type sensing support", 11400f5ce99SJack Morgenstein [59] = "Port management change event support", 11508ff3235SOr Gerlitz [61] = "64 byte EQE support", 11608ff3235SOr Gerlitz [62] = "64 byte CQE support", 1175a2cc190SJeff Kirsher }; 1185a2cc190SJeff Kirsher int i; 1195a2cc190SJeff Kirsher 1205a2cc190SJeff Kirsher mlx4_dbg(dev, "DEV_CAP flags:\n"); 1215a2cc190SJeff Kirsher for (i = 0; i < ARRAY_SIZE(fname); ++i) 1225a2cc190SJeff Kirsher if (fname[i] && (flags & (1LL << i))) 1235a2cc190SJeff Kirsher mlx4_dbg(dev, " %s\n", fname[i]); 1245a2cc190SJeff Kirsher } 1255a2cc190SJeff Kirsher 126b3416f44SShlomo Pongratz static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) 127b3416f44SShlomo Pongratz { 128b3416f44SShlomo Pongratz static const char * const fname[] = { 129b3416f44SShlomo Pongratz [0] = "RSS support", 130b3416f44SShlomo Pongratz [1] = "RSS Toeplitz Hash Function support", 1310ff1fb65SHadar Hen Zion [2] = "RSS XOR Hash Function support", 13256cb4567SOr Gerlitz [3] = "Device managed flow steering support", 133d998735fSEugenia Emantayev [4] = "Automatic MAC reassignment support", 1344e8cf5b8SOr Gerlitz [5] = "Time stamping support", 1354e8cf5b8SOr Gerlitz [6] = "VST (control vlan insertion/stripping) support", 136b01978caSJack Morgenstein [7] = "FSM (MAC anti-spoofing) support", 1377ffdf726SOr Gerlitz [8] = "Dynamic QP updates support", 13856cb4567SOr Gerlitz [9] = "Device managed flow steering IPoIB support", 139114840c3SJack Morgenstein [10] = "TCP/IP offloads/flow-steering for VXLAN support", 14077507aa2SIdo Shamay [11] = "MAD DEMUX (Secure-Host) support", 14177507aa2SIdo Shamay [12] = "Large cache line (>64B) CQE stride support", 142adbc7ac5SSaeed Mahameed [13] = "Large cache line (>64B) EQE stride support", 143a53e3e8cSSaeed Mahameed [14] = "Ethernet protocol control support", 144d475c95bSMatan Barak [15] = "Ethernet Backplane autoneg support", 1457ae0e400SMatan Barak [16] = "CONFIG DEV support", 146de966c59SMatan Barak [17] = "Asymmetric EQs support", 1477d077cd3SMatan Barak [18] = "More than 80 VFs support", 148*be6a6b43SJack Morgenstein [19] = "Performance optimized for limited rule configuration flow steering support", 149*be6a6b43SJack Morgenstein [20] = "Recoverable error events support" 150b3416f44SShlomo Pongratz }; 151b3416f44SShlomo Pongratz int i; 152b3416f44SShlomo Pongratz 153b3416f44SShlomo Pongratz for (i = 0; i < ARRAY_SIZE(fname); ++i) 154b3416f44SShlomo Pongratz if (fname[i] && (flags & (1LL << i))) 155b3416f44SShlomo Pongratz mlx4_dbg(dev, " %s\n", fname[i]); 156b3416f44SShlomo Pongratz } 157b3416f44SShlomo Pongratz 1585a2cc190SJeff Kirsher int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg) 1595a2cc190SJeff Kirsher { 1605a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 1615a2cc190SJeff Kirsher u32 *inbox; 1625a2cc190SJeff Kirsher int err = 0; 1635a2cc190SJeff Kirsher 1645a2cc190SJeff Kirsher #define MOD_STAT_CFG_IN_SIZE 0x100 1655a2cc190SJeff Kirsher 1665a2cc190SJeff Kirsher #define MOD_STAT_CFG_PG_SZ_M_OFFSET 0x002 1675a2cc190SJeff Kirsher #define MOD_STAT_CFG_PG_SZ_OFFSET 0x003 1685a2cc190SJeff Kirsher 1695a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 1705a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 1715a2cc190SJeff Kirsher return PTR_ERR(mailbox); 1725a2cc190SJeff Kirsher inbox = mailbox->buf; 1735a2cc190SJeff Kirsher 1745a2cc190SJeff Kirsher MLX4_PUT(inbox, cfg->log_pg_sz, MOD_STAT_CFG_PG_SZ_OFFSET); 1755a2cc190SJeff Kirsher MLX4_PUT(inbox, cfg->log_pg_sz_m, MOD_STAT_CFG_PG_SZ_M_OFFSET); 1765a2cc190SJeff Kirsher 1775a2cc190SJeff Kirsher err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_MOD_STAT_CFG, 178f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 1795a2cc190SJeff Kirsher 1805a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 1815a2cc190SJeff Kirsher return err; 1825a2cc190SJeff Kirsher } 1835a2cc190SJeff Kirsher 184e8c4265bSMatan Barak int mlx4_QUERY_FUNC(struct mlx4_dev *dev, struct mlx4_func *func, int slave) 185e8c4265bSMatan Barak { 186e8c4265bSMatan Barak struct mlx4_cmd_mailbox *mailbox; 187e8c4265bSMatan Barak u32 *outbox; 188e8c4265bSMatan Barak u8 in_modifier; 189e8c4265bSMatan Barak u8 field; 190e8c4265bSMatan Barak u16 field16; 191e8c4265bSMatan Barak int err; 192e8c4265bSMatan Barak 193e8c4265bSMatan Barak #define QUERY_FUNC_BUS_OFFSET 0x00 194e8c4265bSMatan Barak #define QUERY_FUNC_DEVICE_OFFSET 0x01 195e8c4265bSMatan Barak #define QUERY_FUNC_FUNCTION_OFFSET 0x01 196e8c4265bSMatan Barak #define QUERY_FUNC_PHYSICAL_FUNCTION_OFFSET 0x03 197e8c4265bSMatan Barak #define QUERY_FUNC_RSVD_EQS_OFFSET 0x04 198e8c4265bSMatan Barak #define QUERY_FUNC_MAX_EQ_OFFSET 0x06 199e8c4265bSMatan Barak #define QUERY_FUNC_RSVD_UARS_OFFSET 0x0b 200e8c4265bSMatan Barak 201e8c4265bSMatan Barak mailbox = mlx4_alloc_cmd_mailbox(dev); 202e8c4265bSMatan Barak if (IS_ERR(mailbox)) 203e8c4265bSMatan Barak return PTR_ERR(mailbox); 204e8c4265bSMatan Barak outbox = mailbox->buf; 205e8c4265bSMatan Barak 206e8c4265bSMatan Barak in_modifier = slave; 207e8c4265bSMatan Barak 208e8c4265bSMatan Barak err = mlx4_cmd_box(dev, 0, mailbox->dma, in_modifier, 0, 209e8c4265bSMatan Barak MLX4_CMD_QUERY_FUNC, 210e8c4265bSMatan Barak MLX4_CMD_TIME_CLASS_A, 211e8c4265bSMatan Barak MLX4_CMD_NATIVE); 212e8c4265bSMatan Barak if (err) 213e8c4265bSMatan Barak goto out; 214e8c4265bSMatan Barak 215e8c4265bSMatan Barak MLX4_GET(field, outbox, QUERY_FUNC_BUS_OFFSET); 216e8c4265bSMatan Barak func->bus = field & 0xf; 217e8c4265bSMatan Barak MLX4_GET(field, outbox, QUERY_FUNC_DEVICE_OFFSET); 218e8c4265bSMatan Barak func->device = field & 0xf1; 219e8c4265bSMatan Barak MLX4_GET(field, outbox, QUERY_FUNC_FUNCTION_OFFSET); 220e8c4265bSMatan Barak func->function = field & 0x7; 221e8c4265bSMatan Barak MLX4_GET(field, outbox, QUERY_FUNC_PHYSICAL_FUNCTION_OFFSET); 222e8c4265bSMatan Barak func->physical_function = field & 0xf; 223e8c4265bSMatan Barak MLX4_GET(field16, outbox, QUERY_FUNC_RSVD_EQS_OFFSET); 224e8c4265bSMatan Barak func->rsvd_eqs = field16 & 0xffff; 225e8c4265bSMatan Barak MLX4_GET(field16, outbox, QUERY_FUNC_MAX_EQ_OFFSET); 226e8c4265bSMatan Barak func->max_eq = field16 & 0xffff; 227e8c4265bSMatan Barak MLX4_GET(field, outbox, QUERY_FUNC_RSVD_UARS_OFFSET); 228e8c4265bSMatan Barak func->rsvd_uars = field & 0x0f; 229e8c4265bSMatan Barak 230e8c4265bSMatan Barak mlx4_dbg(dev, "Bus: %d, Device: %d, Function: %d, Physical function: %d, Max EQs: %d, Reserved EQs: %d, Reserved UARs: %d\n", 231e8c4265bSMatan Barak func->bus, func->device, func->function, func->physical_function, 232e8c4265bSMatan Barak func->max_eq, func->rsvd_eqs, func->rsvd_uars); 233e8c4265bSMatan Barak 234e8c4265bSMatan Barak out: 235e8c4265bSMatan Barak mlx4_free_cmd_mailbox(dev, mailbox); 236e8c4265bSMatan Barak return err; 237e8c4265bSMatan Barak } 238e8c4265bSMatan Barak 2395cc914f1SMarcel Apfelbaum int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, 2405cc914f1SMarcel Apfelbaum struct mlx4_vhcr *vhcr, 2415cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *inbox, 2425cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *outbox, 2435cc914f1SMarcel Apfelbaum struct mlx4_cmd_info *cmd) 2445cc914f1SMarcel Apfelbaum { 2455a0d0a61SJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 24699ec41d0SJack Morgenstein u8 field, port; 24799ec41d0SJack Morgenstein u32 size, proxy_qp, qkey; 2485cc914f1SMarcel Apfelbaum int err = 0; 2497ae0e400SMatan Barak struct mlx4_func func; 2505cc914f1SMarcel Apfelbaum 2515cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_FLAGS_OFFSET 0x0 2525cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_NUM_PORTS_OFFSET 0x1 2535cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_PF_BHVR_OFFSET 0x4 254105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FMR_OFFSET 0x8 255eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP 0x10 256eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP 0x14 257eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP 0x18 258eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP 0x20 259eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP 0x24 260eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP 0x28 2615cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_MAX_EQ_OFFSET 0x2c 26269612b9fSRoland Dreier #define QUERY_FUNC_CAP_RESERVED_EQ_OFFSET 0x30 2635cc914f1SMarcel Apfelbaum 264eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x50 265eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x54 266eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET 0x58 267eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET 0x60 268eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET 0x64 269eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET 0x68 270eb456a68SJack Morgenstein 271ddae0349SEugenia Emantayev #define QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET 0x6c 272ddae0349SEugenia Emantayev 273105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FMR_FLAG 0x80 274105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FLAG_RDMA 0x40 275105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FLAG_ETH 0x80 276eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_FLAG_QUOTAS 0x10 277ddae0349SEugenia Emantayev #define QUERY_FUNC_CAP_FLAG_VALID_MAILBOX 0x04 278ddae0349SEugenia Emantayev 279ddae0349SEugenia Emantayev #define QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG (1UL << 31) 280d57febe1SMatan Barak #define QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG (1UL << 30) 281105c320fSJack Morgenstein 282105c320fSJack Morgenstein /* when opcode modifier = 1 */ 2835cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3 28499ec41d0SJack Morgenstein #define QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET 0x4 28573e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS0_OFFSET 0x8 28673e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_OFFSET 0xc 2875cc914f1SMarcel Apfelbaum 28847605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP0_TUNNEL 0x10 28947605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP0_PROXY 0x14 29047605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP1_TUNNEL 0x18 29147605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP1_PROXY 0x1c 2928e1a28e8SHadar Hen Zion #define QUERY_FUNC_CAP_PHYS_PORT_ID 0x28 29347605df9SJack Morgenstein 29473e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_FORCE_MAC 0x40 29573e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_FORCE_VLAN 0x80 296eb17711bSHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_NIC_INFO 0x10 29799ec41d0SJack Morgenstein #define QUERY_FUNC_CAP_VF_ENABLE_QP0 0x08 298105c320fSJack Morgenstein 29973e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID 0x80 3007ae0e400SMatan Barak #define QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS (1 << 31) 301105c320fSJack Morgenstein 3025cc914f1SMarcel Apfelbaum if (vhcr->op_modifier == 1) { 303449fc488SMatan Barak struct mlx4_active_ports actv_ports = 304449fc488SMatan Barak mlx4_get_active_ports(dev, slave); 305449fc488SMatan Barak int converted_port = mlx4_slave_convert_port( 306449fc488SMatan Barak dev, slave, vhcr->in_modifier); 307449fc488SMatan Barak 308449fc488SMatan Barak if (converted_port < 0) 309449fc488SMatan Barak return -EINVAL; 310449fc488SMatan Barak 311449fc488SMatan Barak vhcr->in_modifier = converted_port; 312449fc488SMatan Barak /* phys-port = logical-port */ 313449fc488SMatan Barak field = vhcr->in_modifier - 314449fc488SMatan Barak find_first_bit(actv_ports.ports, dev->caps.num_ports); 31547605df9SJack Morgenstein MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_PHYS_PORT_OFFSET); 31647605df9SJack Morgenstein 31799ec41d0SJack Morgenstein port = vhcr->in_modifier; 31899ec41d0SJack Morgenstein proxy_qp = dev->phys_caps.base_proxy_sqpn + 8 * slave + port - 1; 31999ec41d0SJack Morgenstein 32099ec41d0SJack Morgenstein /* Set nic_info bit to mark new fields support */ 32199ec41d0SJack Morgenstein field = QUERY_FUNC_CAP_FLAGS1_NIC_INFO; 32299ec41d0SJack Morgenstein 32399ec41d0SJack Morgenstein if (mlx4_vf_smi_enabled(dev, slave, port) && 32499ec41d0SJack Morgenstein !mlx4_get_parav_qkey(dev, proxy_qp, &qkey)) { 32599ec41d0SJack Morgenstein field |= QUERY_FUNC_CAP_VF_ENABLE_QP0; 32699ec41d0SJack Morgenstein MLX4_PUT(outbox->buf, qkey, 32799ec41d0SJack Morgenstein QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET); 32899ec41d0SJack Morgenstein } 32999ec41d0SJack Morgenstein MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS1_OFFSET); 33099ec41d0SJack Morgenstein 33147605df9SJack Morgenstein /* size is now the QP number */ 33299ec41d0SJack Morgenstein size = dev->phys_caps.base_tunnel_sqpn + 8 * slave + port - 1; 33347605df9SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP0_TUNNEL); 33447605df9SJack Morgenstein 33547605df9SJack Morgenstein size += 2; 33647605df9SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_TUNNEL); 33747605df9SJack Morgenstein 33899ec41d0SJack Morgenstein MLX4_PUT(outbox->buf, proxy_qp, QUERY_FUNC_CAP_QP0_PROXY); 33999ec41d0SJack Morgenstein proxy_qp += 2; 34099ec41d0SJack Morgenstein MLX4_PUT(outbox->buf, proxy_qp, QUERY_FUNC_CAP_QP1_PROXY); 34147605df9SJack Morgenstein 3428e1a28e8SHadar Hen Zion MLX4_PUT(outbox->buf, dev->caps.phys_port_id[vhcr->in_modifier], 3438e1a28e8SHadar Hen Zion QUERY_FUNC_CAP_PHYS_PORT_ID); 3448e1a28e8SHadar Hen Zion 3455cc914f1SMarcel Apfelbaum } else if (vhcr->op_modifier == 0) { 346449fc488SMatan Barak struct mlx4_active_ports actv_ports = 347449fc488SMatan Barak mlx4_get_active_ports(dev, slave); 348eb456a68SJack Morgenstein /* enable rdma and ethernet interfaces, and new quota locations */ 349eb456a68SJack Morgenstein field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA | 350ddae0349SEugenia Emantayev QUERY_FUNC_CAP_FLAG_QUOTAS | QUERY_FUNC_CAP_FLAG_VALID_MAILBOX); 3515cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET); 3525cc914f1SMarcel Apfelbaum 353449fc488SMatan Barak field = min( 354449fc488SMatan Barak bitmap_weight(actv_ports.ports, dev->caps.num_ports), 355449fc488SMatan Barak dev->caps.num_ports); 3565cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); 3575cc914f1SMarcel Apfelbaum 35808ff3235SOr Gerlitz size = dev->caps.function_caps; /* set PF behaviours */ 3595cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_PF_BHVR_OFFSET); 3605cc914f1SMarcel Apfelbaum 361105c320fSJack Morgenstein field = 0; /* protected FMR support not available as yet */ 362105c320fSJack Morgenstein MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FMR_OFFSET); 363105c320fSJack Morgenstein 3645a0d0a61SJack Morgenstein size = priv->mfunc.master.res_tracker.res_alloc[RES_QP].quota[slave]; 3655cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET); 366eb456a68SJack Morgenstein size = dev->caps.num_qps; 367eb456a68SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP); 3685cc914f1SMarcel Apfelbaum 3695a0d0a61SJack Morgenstein size = priv->mfunc.master.res_tracker.res_alloc[RES_SRQ].quota[slave]; 3705cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET); 371eb456a68SJack Morgenstein size = dev->caps.num_srqs; 372eb456a68SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP); 3735cc914f1SMarcel Apfelbaum 3745a0d0a61SJack Morgenstein size = priv->mfunc.master.res_tracker.res_alloc[RES_CQ].quota[slave]; 3755cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET); 376eb456a68SJack Morgenstein size = dev->caps.num_cqs; 377eb456a68SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP); 3785cc914f1SMarcel Apfelbaum 3797ae0e400SMatan Barak if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS) || 3807ae0e400SMatan Barak mlx4_QUERY_FUNC(dev, &func, slave)) { 3817ae0e400SMatan Barak size = vhcr->in_modifier & 3827ae0e400SMatan Barak QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS ? 3837ae0e400SMatan Barak dev->caps.num_eqs : 3847ae0e400SMatan Barak rounddown_pow_of_two(dev->caps.num_eqs); 3855cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET); 3865cc914f1SMarcel Apfelbaum size = dev->caps.reserved_eqs; 3875cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); 3887ae0e400SMatan Barak } else { 3897ae0e400SMatan Barak size = vhcr->in_modifier & 3907ae0e400SMatan Barak QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS ? 3917ae0e400SMatan Barak func.max_eq : 3927ae0e400SMatan Barak rounddown_pow_of_two(func.max_eq); 3937ae0e400SMatan Barak MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET); 3947ae0e400SMatan Barak size = func.rsvd_eqs; 3957ae0e400SMatan Barak MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); 3967ae0e400SMatan Barak } 3975cc914f1SMarcel Apfelbaum 3985a0d0a61SJack Morgenstein size = priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[slave]; 3995cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET); 400eb456a68SJack Morgenstein size = dev->caps.num_mpts; 401eb456a68SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP); 4025cc914f1SMarcel Apfelbaum 4035a0d0a61SJack Morgenstein size = priv->mfunc.master.res_tracker.res_alloc[RES_MTT].quota[slave]; 4045cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET); 405eb456a68SJack Morgenstein size = dev->caps.num_mtts; 406eb456a68SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP); 4075cc914f1SMarcel Apfelbaum 4085cc914f1SMarcel Apfelbaum size = dev->caps.num_mgms + dev->caps.num_amgms; 4095cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); 410eb456a68SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP); 4115cc914f1SMarcel Apfelbaum 412d57febe1SMatan Barak size = QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG | 413d57febe1SMatan Barak QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG; 414ddae0349SEugenia Emantayev MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET); 4155cc914f1SMarcel Apfelbaum } else 4165cc914f1SMarcel Apfelbaum err = -EINVAL; 4175cc914f1SMarcel Apfelbaum 4185cc914f1SMarcel Apfelbaum return err; 4195cc914f1SMarcel Apfelbaum } 4205cc914f1SMarcel Apfelbaum 421225c6c8cSMatan Barak int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port, 42247605df9SJack Morgenstein struct mlx4_func_cap *func_cap) 4235cc914f1SMarcel Apfelbaum { 4245cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *mailbox; 4255cc914f1SMarcel Apfelbaum u32 *outbox; 42647605df9SJack Morgenstein u8 field, op_modifier; 42799ec41d0SJack Morgenstein u32 size, qkey; 428eb456a68SJack Morgenstein int err = 0, quotas = 0; 4297ae0e400SMatan Barak u32 in_modifier; 4305cc914f1SMarcel Apfelbaum 43147605df9SJack Morgenstein op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */ 4327ae0e400SMatan Barak in_modifier = op_modifier ? gen_or_port : 4337ae0e400SMatan Barak QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS; 4345cc914f1SMarcel Apfelbaum 4355cc914f1SMarcel Apfelbaum mailbox = mlx4_alloc_cmd_mailbox(dev); 4365cc914f1SMarcel Apfelbaum if (IS_ERR(mailbox)) 4375cc914f1SMarcel Apfelbaum return PTR_ERR(mailbox); 4385cc914f1SMarcel Apfelbaum 4397ae0e400SMatan Barak err = mlx4_cmd_box(dev, 0, mailbox->dma, in_modifier, op_modifier, 44047605df9SJack Morgenstein MLX4_CMD_QUERY_FUNC_CAP, 4415cc914f1SMarcel Apfelbaum MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 4425cc914f1SMarcel Apfelbaum if (err) 4435cc914f1SMarcel Apfelbaum goto out; 4445cc914f1SMarcel Apfelbaum 4455cc914f1SMarcel Apfelbaum outbox = mailbox->buf; 4465cc914f1SMarcel Apfelbaum 44747605df9SJack Morgenstein if (!op_modifier) { 4485cc914f1SMarcel Apfelbaum MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS_OFFSET); 449105c320fSJack Morgenstein if (!(field & (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA))) { 450105c320fSJack Morgenstein mlx4_err(dev, "The host supports neither eth nor rdma interfaces\n"); 4515cc914f1SMarcel Apfelbaum err = -EPROTONOSUPPORT; 4525cc914f1SMarcel Apfelbaum goto out; 4535cc914f1SMarcel Apfelbaum } 454105c320fSJack Morgenstein func_cap->flags = field; 455eb456a68SJack Morgenstein quotas = !!(func_cap->flags & QUERY_FUNC_CAP_FLAG_QUOTAS); 4565cc914f1SMarcel Apfelbaum 4575cc914f1SMarcel Apfelbaum MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); 4585cc914f1SMarcel Apfelbaum func_cap->num_ports = field; 4595cc914f1SMarcel Apfelbaum 4605cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_PF_BHVR_OFFSET); 4615cc914f1SMarcel Apfelbaum func_cap->pf_context_behaviour = size; 4625cc914f1SMarcel Apfelbaum 463eb456a68SJack Morgenstein if (quotas) { 4645cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET); 4655cc914f1SMarcel Apfelbaum func_cap->qp_quota = size & 0xFFFFFF; 4665cc914f1SMarcel Apfelbaum 4675cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET); 4685cc914f1SMarcel Apfelbaum func_cap->srq_quota = size & 0xFFFFFF; 4695cc914f1SMarcel Apfelbaum 4705cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET); 4715cc914f1SMarcel Apfelbaum func_cap->cq_quota = size & 0xFFFFFF; 4725cc914f1SMarcel Apfelbaum 4735cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET); 4745cc914f1SMarcel Apfelbaum func_cap->mpt_quota = size & 0xFFFFFF; 4755cc914f1SMarcel Apfelbaum 4765cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET); 4775cc914f1SMarcel Apfelbaum func_cap->mtt_quota = size & 0xFFFFFF; 4785cc914f1SMarcel Apfelbaum 4795cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); 4805cc914f1SMarcel Apfelbaum func_cap->mcg_quota = size & 0xFFFFFF; 481eb456a68SJack Morgenstein 482eb456a68SJack Morgenstein } else { 483eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP); 484eb456a68SJack Morgenstein func_cap->qp_quota = size & 0xFFFFFF; 485eb456a68SJack Morgenstein 486eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP); 487eb456a68SJack Morgenstein func_cap->srq_quota = size & 0xFFFFFF; 488eb456a68SJack Morgenstein 489eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP); 490eb456a68SJack Morgenstein func_cap->cq_quota = size & 0xFFFFFF; 491eb456a68SJack Morgenstein 492eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP); 493eb456a68SJack Morgenstein func_cap->mpt_quota = size & 0xFFFFFF; 494eb456a68SJack Morgenstein 495eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP); 496eb456a68SJack Morgenstein func_cap->mtt_quota = size & 0xFFFFFF; 497eb456a68SJack Morgenstein 498eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP); 499eb456a68SJack Morgenstein func_cap->mcg_quota = size & 0xFFFFFF; 500eb456a68SJack Morgenstein } 501eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_MAX_EQ_OFFSET); 502eb456a68SJack Morgenstein func_cap->max_eq = size & 0xFFFFFF; 503eb456a68SJack Morgenstein 504eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); 505eb456a68SJack Morgenstein func_cap->reserved_eq = size & 0xFFFFFF; 506eb456a68SJack Morgenstein 507ddae0349SEugenia Emantayev func_cap->extra_flags = 0; 508ddae0349SEugenia Emantayev 509ddae0349SEugenia Emantayev /* Mailbox data from 0x6c and onward should only be treated if 510ddae0349SEugenia Emantayev * QUERY_FUNC_CAP_FLAG_VALID_MAILBOX is set in func_cap->flags 511ddae0349SEugenia Emantayev */ 512ddae0349SEugenia Emantayev if (func_cap->flags & QUERY_FUNC_CAP_FLAG_VALID_MAILBOX) { 513ddae0349SEugenia Emantayev MLX4_GET(size, outbox, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET); 514ddae0349SEugenia Emantayev if (size & QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG) 515ddae0349SEugenia Emantayev func_cap->extra_flags |= MLX4_QUERY_FUNC_FLAGS_BF_RES_QP; 516d57febe1SMatan Barak if (size & QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG) 517d57febe1SMatan Barak func_cap->extra_flags |= MLX4_QUERY_FUNC_FLAGS_A0_RES_QP; 518ddae0349SEugenia Emantayev } 519ddae0349SEugenia Emantayev 5205cc914f1SMarcel Apfelbaum goto out; 52147605df9SJack Morgenstein } 5225cc914f1SMarcel Apfelbaum 52347605df9SJack Morgenstein /* logical port query */ 52447605df9SJack Morgenstein if (gen_or_port > dev->caps.num_ports) { 52547605df9SJack Morgenstein err = -EINVAL; 52647605df9SJack Morgenstein goto out; 52747605df9SJack Morgenstein } 52847605df9SJack Morgenstein 529eb17711bSHadar Hen Zion MLX4_GET(func_cap->flags1, outbox, QUERY_FUNC_CAP_FLAGS1_OFFSET); 53047605df9SJack Morgenstein if (dev->caps.port_type[gen_or_port] == MLX4_PORT_TYPE_ETH) { 531bc82878bSJack Morgenstein if (func_cap->flags1 & QUERY_FUNC_CAP_FLAGS1_FORCE_VLAN) { 5325cc914f1SMarcel Apfelbaum mlx4_err(dev, "VLAN is enforced on this port\n"); 5335cc914f1SMarcel Apfelbaum err = -EPROTONOSUPPORT; 5345cc914f1SMarcel Apfelbaum goto out; 5355cc914f1SMarcel Apfelbaum } 5365cc914f1SMarcel Apfelbaum 537eb17711bSHadar Hen Zion if (func_cap->flags1 & QUERY_FUNC_CAP_FLAGS1_FORCE_MAC) { 5385cc914f1SMarcel Apfelbaum mlx4_err(dev, "Force mac is enabled on this port\n"); 5395cc914f1SMarcel Apfelbaum err = -EPROTONOSUPPORT; 5405cc914f1SMarcel Apfelbaum goto out; 5415cc914f1SMarcel Apfelbaum } 54247605df9SJack Morgenstein } else if (dev->caps.port_type[gen_or_port] == MLX4_PORT_TYPE_IB) { 54373e74ab4SHadar Hen Zion MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS0_OFFSET); 54473e74ab4SHadar Hen Zion if (field & QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID) { 5451a91de28SJoe Perches mlx4_err(dev, "phy_wqe_gid is enforced on this ib port\n"); 546105c320fSJack Morgenstein err = -EPROTONOSUPPORT; 547105c320fSJack Morgenstein goto out; 548105c320fSJack Morgenstein } 549105c320fSJack Morgenstein } 5505cc914f1SMarcel Apfelbaum 5515cc914f1SMarcel Apfelbaum MLX4_GET(field, outbox, QUERY_FUNC_CAP_PHYS_PORT_OFFSET); 55247605df9SJack Morgenstein func_cap->physical_port = field; 55347605df9SJack Morgenstein if (func_cap->physical_port != gen_or_port) { 55447605df9SJack Morgenstein err = -ENOSYS; 55547605df9SJack Morgenstein goto out; 5565cc914f1SMarcel Apfelbaum } 5575cc914f1SMarcel Apfelbaum 55899ec41d0SJack Morgenstein if (func_cap->flags1 & QUERY_FUNC_CAP_VF_ENABLE_QP0) { 55999ec41d0SJack Morgenstein MLX4_GET(qkey, outbox, QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET); 56099ec41d0SJack Morgenstein func_cap->qp0_qkey = qkey; 56199ec41d0SJack Morgenstein } else { 56299ec41d0SJack Morgenstein func_cap->qp0_qkey = 0; 56399ec41d0SJack Morgenstein } 56499ec41d0SJack Morgenstein 56547605df9SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_TUNNEL); 56647605df9SJack Morgenstein func_cap->qp0_tunnel_qpn = size & 0xFFFFFF; 56747605df9SJack Morgenstein 56847605df9SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_PROXY); 56947605df9SJack Morgenstein func_cap->qp0_proxy_qpn = size & 0xFFFFFF; 57047605df9SJack Morgenstein 57147605df9SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP1_TUNNEL); 57247605df9SJack Morgenstein func_cap->qp1_tunnel_qpn = size & 0xFFFFFF; 57347605df9SJack Morgenstein 57447605df9SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP1_PROXY); 57547605df9SJack Morgenstein func_cap->qp1_proxy_qpn = size & 0xFFFFFF; 57647605df9SJack Morgenstein 5778e1a28e8SHadar Hen Zion if (func_cap->flags1 & QUERY_FUNC_CAP_FLAGS1_NIC_INFO) 5788e1a28e8SHadar Hen Zion MLX4_GET(func_cap->phys_port_id, outbox, 5798e1a28e8SHadar Hen Zion QUERY_FUNC_CAP_PHYS_PORT_ID); 5808e1a28e8SHadar Hen Zion 5815cc914f1SMarcel Apfelbaum /* All other resources are allocated by the master, but we still report 5825cc914f1SMarcel Apfelbaum * 'num' and 'reserved' capabilities as follows: 5835cc914f1SMarcel Apfelbaum * - num remains the maximum resource index 5845cc914f1SMarcel Apfelbaum * - 'num - reserved' is the total available objects of a resource, but 5855cc914f1SMarcel Apfelbaum * resource indices may be less than 'reserved' 5865cc914f1SMarcel Apfelbaum * TODO: set per-resource quotas */ 5875cc914f1SMarcel Apfelbaum 5885cc914f1SMarcel Apfelbaum out: 5895cc914f1SMarcel Apfelbaum mlx4_free_cmd_mailbox(dev, mailbox); 5905cc914f1SMarcel Apfelbaum 5915cc914f1SMarcel Apfelbaum return err; 5925cc914f1SMarcel Apfelbaum } 5935cc914f1SMarcel Apfelbaum 5945a2cc190SJeff Kirsher int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) 5955a2cc190SJeff Kirsher { 5965a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 5975a2cc190SJeff Kirsher u32 *outbox; 5985a2cc190SJeff Kirsher u8 field; 5995a2cc190SJeff Kirsher u32 field32, flags, ext_flags; 6005a2cc190SJeff Kirsher u16 size; 6015a2cc190SJeff Kirsher u16 stat_rate; 6025a2cc190SJeff Kirsher int err; 6035a2cc190SJeff Kirsher int i; 6045a2cc190SJeff Kirsher 6055a2cc190SJeff Kirsher #define QUERY_DEV_CAP_OUT_SIZE 0x100 6065a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET 0x10 6075a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_QP_SZ_OFFSET 0x11 6085a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_QP_OFFSET 0x12 6095a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_QP_OFFSET 0x13 6105a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_SRQ_OFFSET 0x14 6115a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SRQ_OFFSET 0x15 6125a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_EEC_OFFSET 0x16 6135a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_EEC_OFFSET 0x17 6145a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET 0x19 6155a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_CQ_OFFSET 0x1a 6165a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_CQ_OFFSET 0x1b 6175a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MPT_OFFSET 0x1d 6185a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_EQ_OFFSET 0x1e 6195a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_EQ_OFFSET 0x1f 6205a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_MTT_OFFSET 0x20 6215a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET 0x21 6225a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_MRW_OFFSET 0x22 6235a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET 0x23 6247ae0e400SMatan Barak #define QUERY_DEV_CAP_NUM_SYS_EQ_OFFSET 0x26 6255a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_AV_OFFSET 0x27 6265a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET 0x29 6275a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_RES_QP_OFFSET 0x2b 6285a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_GSO_OFFSET 0x2d 629b3416f44SShlomo Pongratz #define QUERY_DEV_CAP_RSS_OFFSET 0x2e 6305a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_RDMA_OFFSET 0x2f 6315a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSZ_SRQ_OFFSET 0x33 6325a2cc190SJeff Kirsher #define QUERY_DEV_CAP_ACK_DELAY_OFFSET 0x35 6335a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MTU_WIDTH_OFFSET 0x36 6345a2cc190SJeff Kirsher #define QUERY_DEV_CAP_VL_PORT_OFFSET 0x37 6355a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET 0x38 6365a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b 6375a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c 638d998735fSEugenia Emantayev #define QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET 0x3e 6395a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f 6405a2cc190SJeff Kirsher #define QUERY_DEV_CAP_EXT_FLAGS_OFFSET 0x40 6415a2cc190SJeff Kirsher #define QUERY_DEV_CAP_FLAGS_OFFSET 0x44 6425a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48 6435a2cc190SJeff Kirsher #define QUERY_DEV_CAP_UAR_SZ_OFFSET 0x49 6445a2cc190SJeff Kirsher #define QUERY_DEV_CAP_PAGE_SZ_OFFSET 0x4b 6455a2cc190SJeff Kirsher #define QUERY_DEV_CAP_BF_OFFSET 0x4c 6465a2cc190SJeff Kirsher #define QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET 0x4d 6475a2cc190SJeff Kirsher #define QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET 0x4e 6485a2cc190SJeff Kirsher #define QUERY_DEV_CAP_LOG_MAX_BF_PAGES_OFFSET 0x4f 6495a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SG_SQ_OFFSET 0x51 6505a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET 0x52 6515a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SG_RQ_OFFSET 0x55 6525a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET 0x56 6535a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_QP_MCG_OFFSET 0x61 6545a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_MCG_OFFSET 0x62 6555a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MCG_OFFSET 0x63 6565a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_PD_OFFSET 0x64 6575a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_PD_OFFSET 0x65 658f470f8d4SLinus Torvalds #define QUERY_DEV_CAP_RSVD_XRC_OFFSET 0x66 659f470f8d4SLinus Torvalds #define QUERY_DEV_CAP_MAX_XRC_OFFSET 0x67 6605a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET 0x68 6613f7fb021SRony Efraim #define QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET 0x70 6624de65803SMatan Barak #define QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET 0x74 6630ff1fb65SHadar Hen Zion #define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET 0x76 6640ff1fb65SHadar Hen Zion #define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET 0x77 66577507aa2SIdo Shamay #define QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE 0x7a 666adbc7ac5SSaeed Mahameed #define QUERY_DEV_CAP_ETH_PROT_CTRL_OFFSET 0x7a 6675a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80 6685a2cc190SJeff Kirsher #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82 6695a2cc190SJeff Kirsher #define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84 6705a2cc190SJeff Kirsher #define QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET 0x86 6715a2cc190SJeff Kirsher #define QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET 0x88 6725a2cc190SJeff Kirsher #define QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET 0x8a 6735a2cc190SJeff Kirsher #define QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET 0x8c 6745a2cc190SJeff Kirsher #define QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET 0x8e 6755a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET 0x90 6765a2cc190SJeff Kirsher #define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET 0x92 6775a2cc190SJeff Kirsher #define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x94 678d475c95bSMatan Barak #define QUERY_DEV_CAP_CONFIG_DEV_OFFSET 0x94 6795a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98 6805a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0 681a53e3e8cSSaeed Mahameed #define QUERY_DEV_CAP_ETH_BACKPL_OFFSET 0x9c 682955154faSMatan Barak #define QUERY_DEV_CAP_FW_REASSIGN_MAC 0x9d 6837ffdf726SOr Gerlitz #define QUERY_DEV_CAP_VXLAN 0x9e 684114840c3SJack Morgenstein #define QUERY_DEV_CAP_MAD_DEMUX_OFFSET 0xb0 6857d077cd3SMatan Barak #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET 0xa8 6867d077cd3SMatan Barak #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET 0xac 6875a2cc190SJeff Kirsher 688b3416f44SShlomo Pongratz dev_cap->flags2 = 0; 6895a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 6905a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 6915a2cc190SJeff Kirsher return PTR_ERR(mailbox); 6925a2cc190SJeff Kirsher outbox = mailbox->buf; 6935a2cc190SJeff Kirsher 6945a2cc190SJeff Kirsher err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, 695401453a3SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 6965a2cc190SJeff Kirsher if (err) 6975a2cc190SJeff Kirsher goto out; 6985a2cc190SJeff Kirsher 6995a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_QP_OFFSET); 7005a2cc190SJeff Kirsher dev_cap->reserved_qps = 1 << (field & 0xf); 7015a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_OFFSET); 7025a2cc190SJeff Kirsher dev_cap->max_qps = 1 << (field & 0x1f); 7035a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_SRQ_OFFSET); 7045a2cc190SJeff Kirsher dev_cap->reserved_srqs = 1 << (field >> 4); 7055a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_OFFSET); 7065a2cc190SJeff Kirsher dev_cap->max_srqs = 1 << (field & 0x1f); 7075a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET); 7085a2cc190SJeff Kirsher dev_cap->max_cq_sz = 1 << field; 7095a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_CQ_OFFSET); 7105a2cc190SJeff Kirsher dev_cap->reserved_cqs = 1 << (field & 0xf); 7115a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_OFFSET); 7125a2cc190SJeff Kirsher dev_cap->max_cqs = 1 << (field & 0x1f); 7135a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MPT_OFFSET); 7145a2cc190SJeff Kirsher dev_cap->max_mpts = 1 << (field & 0x3f); 7155a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_EQ_OFFSET); 7167c68dd43SMatan Barak dev_cap->reserved_eqs = 1 << (field & 0xf); 7175a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_EQ_OFFSET); 7185a2cc190SJeff Kirsher dev_cap->max_eqs = 1 << (field & 0xf); 7195a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MTT_OFFSET); 7205a2cc190SJeff Kirsher dev_cap->reserved_mtts = 1 << (field >> 4); 7215a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET); 7225a2cc190SJeff Kirsher dev_cap->max_mrw_sz = 1 << field; 7235a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MRW_OFFSET); 7245a2cc190SJeff Kirsher dev_cap->reserved_mrws = 1 << (field & 0xf); 7255a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET); 7265a2cc190SJeff Kirsher dev_cap->max_mtt_seg = 1 << (field & 0x3f); 7277ae0e400SMatan Barak MLX4_GET(size, outbox, QUERY_DEV_CAP_NUM_SYS_EQ_OFFSET); 7287ae0e400SMatan Barak dev_cap->num_sys_eqs = size & 0xfff; 7295a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_REQ_QP_OFFSET); 7305a2cc190SJeff Kirsher dev_cap->max_requester_per_qp = 1 << (field & 0x3f); 7315a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RES_QP_OFFSET); 7325a2cc190SJeff Kirsher dev_cap->max_responder_per_qp = 1 << (field & 0x3f); 7335a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GSO_OFFSET); 7345a2cc190SJeff Kirsher field &= 0x1f; 7355a2cc190SJeff Kirsher if (!field) 7365a2cc190SJeff Kirsher dev_cap->max_gso_sz = 0; 7375a2cc190SJeff Kirsher else 7385a2cc190SJeff Kirsher dev_cap->max_gso_sz = 1 << field; 7395a2cc190SJeff Kirsher 740b3416f44SShlomo Pongratz MLX4_GET(field, outbox, QUERY_DEV_CAP_RSS_OFFSET); 741b3416f44SShlomo Pongratz if (field & 0x20) 742b3416f44SShlomo Pongratz dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_XOR; 743b3416f44SShlomo Pongratz if (field & 0x10) 744b3416f44SShlomo Pongratz dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_TOP; 745b3416f44SShlomo Pongratz field &= 0xf; 746b3416f44SShlomo Pongratz if (field) { 747b3416f44SShlomo Pongratz dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS; 748b3416f44SShlomo Pongratz dev_cap->max_rss_tbl_sz = 1 << field; 749b3416f44SShlomo Pongratz } else 750b3416f44SShlomo Pongratz dev_cap->max_rss_tbl_sz = 0; 7515a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RDMA_OFFSET); 7525a2cc190SJeff Kirsher dev_cap->max_rdma_global = 1 << (field & 0x3f); 7535a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET); 7545a2cc190SJeff Kirsher dev_cap->local_ca_ack_delay = field & 0x1f; 7555a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); 7565a2cc190SJeff Kirsher dev_cap->num_ports = field & 0xf; 7575a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET); 7585a2cc190SJeff Kirsher dev_cap->max_msg_sz = 1 << (field & 0x1f); 7590ff1fb65SHadar Hen Zion MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET); 7600ff1fb65SHadar Hen Zion if (field & 0x80) 7610ff1fb65SHadar Hen Zion dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FS_EN; 7620ff1fb65SHadar Hen Zion dev_cap->fs_log_max_ucast_qp_range_size = field & 0x1f; 7634de65803SMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET); 7644de65803SMatan Barak if (field & 0x80) 7654de65803SMatan Barak dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DMFS_IPOIB; 7660ff1fb65SHadar Hen Zion MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET); 7670ff1fb65SHadar Hen Zion dev_cap->fs_max_num_qp_per_entry = field; 7685a2cc190SJeff Kirsher MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); 7695a2cc190SJeff Kirsher dev_cap->stat_rate_support = stat_rate; 770d998735fSEugenia Emantayev MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET); 771d998735fSEugenia Emantayev if (field & 0x80) 772d998735fSEugenia Emantayev dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_TS; 7735a2cc190SJeff Kirsher MLX4_GET(ext_flags, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET); 7745a2cc190SJeff Kirsher MLX4_GET(flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET); 7755a2cc190SJeff Kirsher dev_cap->flags = flags | (u64)ext_flags << 32; 7765a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET); 7775a2cc190SJeff Kirsher dev_cap->reserved_uars = field >> 4; 7785a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_UAR_SZ_OFFSET); 7795a2cc190SJeff Kirsher dev_cap->uar_size = 1 << ((field & 0x3f) + 20); 7805a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_PAGE_SZ_OFFSET); 7815a2cc190SJeff Kirsher dev_cap->min_page_sz = 1 << field; 7825a2cc190SJeff Kirsher 7835a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_BF_OFFSET); 7845a2cc190SJeff Kirsher if (field & 0x80) { 7855a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET); 7865a2cc190SJeff Kirsher dev_cap->bf_reg_size = 1 << (field & 0x1f); 7875a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET); 7885a2cc190SJeff Kirsher if ((1 << (field & 0x3f)) > (PAGE_SIZE / dev_cap->bf_reg_size)) 7895a2cc190SJeff Kirsher field = 3; 7905a2cc190SJeff Kirsher dev_cap->bf_regs_per_page = 1 << (field & 0x3f); 7915a2cc190SJeff Kirsher } else { 7925a2cc190SJeff Kirsher dev_cap->bf_reg_size = 0; 7935a2cc190SJeff Kirsher } 7945a2cc190SJeff Kirsher 7955a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_SQ_OFFSET); 7965a2cc190SJeff Kirsher dev_cap->max_sq_sg = field; 7975a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET); 7985a2cc190SJeff Kirsher dev_cap->max_sq_desc_sz = size; 7995a2cc190SJeff Kirsher 8005a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_MCG_OFFSET); 8015a2cc190SJeff Kirsher dev_cap->max_qp_per_mcg = 1 << field; 8025a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MCG_OFFSET); 8035a2cc190SJeff Kirsher dev_cap->reserved_mgms = field & 0xf; 8045a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MCG_OFFSET); 8055a2cc190SJeff Kirsher dev_cap->max_mcgs = 1 << field; 8065a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_PD_OFFSET); 8075a2cc190SJeff Kirsher dev_cap->reserved_pds = field >> 4; 8085a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET); 8095a2cc190SJeff Kirsher dev_cap->max_pds = 1 << (field & 0x3f); 810f470f8d4SLinus Torvalds MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_XRC_OFFSET); 811f470f8d4SLinus Torvalds dev_cap->reserved_xrcds = field >> 4; 812426dd00dSDotan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_XRC_OFFSET); 813f470f8d4SLinus Torvalds dev_cap->max_xrcds = 1 << (field & 0x1f); 8145a2cc190SJeff Kirsher 8155a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET); 8165a2cc190SJeff Kirsher dev_cap->rdmarc_entry_sz = size; 8175a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET); 8185a2cc190SJeff Kirsher dev_cap->qpc_entry_sz = size; 8195a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET); 8205a2cc190SJeff Kirsher dev_cap->aux_entry_sz = size; 8215a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET); 8225a2cc190SJeff Kirsher dev_cap->altc_entry_sz = size; 8235a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET); 8245a2cc190SJeff Kirsher dev_cap->eqc_entry_sz = size; 8255a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET); 8265a2cc190SJeff Kirsher dev_cap->cqc_entry_sz = size; 8275a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET); 8285a2cc190SJeff Kirsher dev_cap->srq_entry_sz = size; 8295a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET); 8305a2cc190SJeff Kirsher dev_cap->cmpt_entry_sz = size; 8315a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET); 8325a2cc190SJeff Kirsher dev_cap->mtt_entry_sz = size; 8335a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET); 8345a2cc190SJeff Kirsher dev_cap->dmpt_entry_sz = size; 8355a2cc190SJeff Kirsher 8365a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET); 8375a2cc190SJeff Kirsher dev_cap->max_srq_sz = 1 << field; 8385a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_SZ_OFFSET); 8395a2cc190SJeff Kirsher dev_cap->max_qp_sz = 1 << field; 8405a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSZ_SRQ_OFFSET); 8415a2cc190SJeff Kirsher dev_cap->resize_srq = field & 1; 8425a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_RQ_OFFSET); 8435a2cc190SJeff Kirsher dev_cap->max_rq_sg = field; 8445a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET); 8455a2cc190SJeff Kirsher dev_cap->max_rq_desc_sz = size; 84677507aa2SIdo Shamay MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE); 847adbc7ac5SSaeed Mahameed if (field & (1 << 5)) 848adbc7ac5SSaeed Mahameed dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETH_PROT_CTRL; 84977507aa2SIdo Shamay if (field & (1 << 6)) 85077507aa2SIdo Shamay dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_CQE_STRIDE; 85177507aa2SIdo Shamay if (field & (1 << 7)) 85277507aa2SIdo Shamay dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_EQE_STRIDE; 8535a2cc190SJeff Kirsher MLX4_GET(dev_cap->bmme_flags, outbox, 8545a2cc190SJeff Kirsher QUERY_DEV_CAP_BMME_FLAGS_OFFSET); 855d475c95bSMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_CONFIG_DEV_OFFSET); 856d475c95bSMatan Barak if (field & 0x20) 857d475c95bSMatan Barak dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_CONFIG_DEV; 8585a2cc190SJeff Kirsher MLX4_GET(dev_cap->reserved_lkey, outbox, 8595a2cc190SJeff Kirsher QUERY_DEV_CAP_RSVD_LKEY_OFFSET); 860a53e3e8cSSaeed Mahameed MLX4_GET(field32, outbox, QUERY_DEV_CAP_ETH_BACKPL_OFFSET); 861a53e3e8cSSaeed Mahameed if (field32 & (1 << 0)) 862a53e3e8cSSaeed Mahameed dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP; 863*be6a6b43SJack Morgenstein if (field32 & (1 << 7)) 864*be6a6b43SJack Morgenstein dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT; 865955154faSMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_FW_REASSIGN_MAC); 866955154faSMatan Barak if (field & 1<<6) 8675930e8d0SOr Gerlitz dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_REASSIGN_MAC_EN; 8687ffdf726SOr Gerlitz MLX4_GET(field, outbox, QUERY_DEV_CAP_VXLAN); 8697ffdf726SOr Gerlitz if (field & 1<<3) 8707ffdf726SOr Gerlitz dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS; 8715a2cc190SJeff Kirsher MLX4_GET(dev_cap->max_icm_sz, outbox, 8725a2cc190SJeff Kirsher QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET); 8735a2cc190SJeff Kirsher if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS) 8745a2cc190SJeff Kirsher MLX4_GET(dev_cap->max_counters, outbox, 8755a2cc190SJeff Kirsher QUERY_DEV_CAP_MAX_COUNTERS_OFFSET); 8765a2cc190SJeff Kirsher 877114840c3SJack Morgenstein MLX4_GET(field32, outbox, 878114840c3SJack Morgenstein QUERY_DEV_CAP_MAD_DEMUX_OFFSET); 879114840c3SJack Morgenstein if (field32 & (1 << 0)) 880114840c3SJack Morgenstein dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_MAD_DEMUX; 881114840c3SJack Morgenstein 8827d077cd3SMatan Barak MLX4_GET(dev_cap->dmfs_high_rate_qpn_base, outbox, 8837d077cd3SMatan Barak QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET); 8847d077cd3SMatan Barak dev_cap->dmfs_high_rate_qpn_base &= MGM_QPN_MASK; 8857d077cd3SMatan Barak MLX4_GET(dev_cap->dmfs_high_rate_qpn_range, outbox, 8867d077cd3SMatan Barak QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET); 8877d077cd3SMatan Barak dev_cap->dmfs_high_rate_qpn_range &= MGM_QPN_MASK; 8887d077cd3SMatan Barak 8893f7fb021SRony Efraim MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); 890b01978caSJack Morgenstein if (field32 & (1 << 16)) 891b01978caSJack Morgenstein dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP; 8923f7fb021SRony Efraim if (field32 & (1 << 26)) 8933f7fb021SRony Efraim dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VLAN_CONTROL; 894e6b6a231SRony Efraim if (field32 & (1 << 20)) 895e6b6a231SRony Efraim dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FSM; 896de966c59SMatan Barak if (field32 & (1 << 21)) 897de966c59SMatan Barak dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_80_VFS; 8983f7fb021SRony Efraim 899431df8c7SMatan Barak for (i = 1; i <= dev_cap->num_ports; i++) { 900431df8c7SMatan Barak err = mlx4_QUERY_PORT(dev, i, dev_cap->port_cap + i); 9015a2cc190SJeff Kirsher if (err) 9025a2cc190SJeff Kirsher goto out; 9035a2cc190SJeff Kirsher } 9045a2cc190SJeff Kirsher 9055a2cc190SJeff Kirsher /* 9065a2cc190SJeff Kirsher * Each UAR has 4 EQ doorbells; so if a UAR is reserved, then 9075a2cc190SJeff Kirsher * we can't use any EQs whose doorbell falls on that page, 9085a2cc190SJeff Kirsher * even if the EQ itself isn't reserved. 9095a2cc190SJeff Kirsher */ 9107ae0e400SMatan Barak if (dev_cap->num_sys_eqs == 0) 9115a2cc190SJeff Kirsher dev_cap->reserved_eqs = max(dev_cap->reserved_uars * 4, 9125a2cc190SJeff Kirsher dev_cap->reserved_eqs); 9137ae0e400SMatan Barak else 9147ae0e400SMatan Barak dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SYS_EQS; 9155a2cc190SJeff Kirsher 916c78e25edSOr Gerlitz out: 917c78e25edSOr Gerlitz mlx4_free_cmd_mailbox(dev, mailbox); 918c78e25edSOr Gerlitz return err; 919c78e25edSOr Gerlitz } 920c78e25edSOr Gerlitz 921c78e25edSOr Gerlitz void mlx4_dev_cap_dump(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) 922c78e25edSOr Gerlitz { 923c78e25edSOr Gerlitz if (dev_cap->bf_reg_size > 0) 924c78e25edSOr Gerlitz mlx4_dbg(dev, "BlueFlame available (reg size %d, regs/page %d)\n", 925c78e25edSOr Gerlitz dev_cap->bf_reg_size, dev_cap->bf_regs_per_page); 926c78e25edSOr Gerlitz else 927c78e25edSOr Gerlitz mlx4_dbg(dev, "BlueFlame not available\n"); 928c78e25edSOr Gerlitz 929c78e25edSOr Gerlitz mlx4_dbg(dev, "Base MM extensions: flags %08x, rsvd L_Key %08x\n", 930c78e25edSOr Gerlitz dev_cap->bmme_flags, dev_cap->reserved_lkey); 9315a2cc190SJeff Kirsher mlx4_dbg(dev, "Max ICM size %lld MB\n", 9325a2cc190SJeff Kirsher (unsigned long long) dev_cap->max_icm_sz >> 20); 9335a2cc190SJeff Kirsher mlx4_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n", 9345a2cc190SJeff Kirsher dev_cap->max_qps, dev_cap->reserved_qps, dev_cap->qpc_entry_sz); 9355a2cc190SJeff Kirsher mlx4_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n", 9365a2cc190SJeff Kirsher dev_cap->max_srqs, dev_cap->reserved_srqs, dev_cap->srq_entry_sz); 9375a2cc190SJeff Kirsher mlx4_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n", 9385a2cc190SJeff Kirsher dev_cap->max_cqs, dev_cap->reserved_cqs, dev_cap->cqc_entry_sz); 9397ae0e400SMatan Barak mlx4_dbg(dev, "Num sys EQs: %d, max EQs: %d, reserved EQs: %d, entry size: %d\n", 9407ae0e400SMatan Barak dev_cap->num_sys_eqs, dev_cap->max_eqs, dev_cap->reserved_eqs, 9417ae0e400SMatan Barak dev_cap->eqc_entry_sz); 9425a2cc190SJeff Kirsher mlx4_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n", 9435a2cc190SJeff Kirsher dev_cap->reserved_mrws, dev_cap->reserved_mtts); 9445a2cc190SJeff Kirsher mlx4_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n", 9455a2cc190SJeff Kirsher dev_cap->max_pds, dev_cap->reserved_pds, dev_cap->reserved_uars); 9465a2cc190SJeff Kirsher mlx4_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n", 9475a2cc190SJeff Kirsher dev_cap->max_pds, dev_cap->reserved_mgms); 9485a2cc190SJeff Kirsher mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", 9495a2cc190SJeff Kirsher dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz); 9505a2cc190SJeff Kirsher mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n", 951431df8c7SMatan Barak dev_cap->local_ca_ack_delay, 128 << dev_cap->port_cap[1].ib_mtu, 952431df8c7SMatan Barak dev_cap->port_cap[1].max_port_width); 9535a2cc190SJeff Kirsher mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n", 9545a2cc190SJeff Kirsher dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg); 9555a2cc190SJeff Kirsher mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n", 9565a2cc190SJeff Kirsher dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg); 9575a2cc190SJeff Kirsher mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz); 9585a2cc190SJeff Kirsher mlx4_dbg(dev, "Max counters: %d\n", dev_cap->max_counters); 959b3416f44SShlomo Pongratz mlx4_dbg(dev, "Max RSS Table size: %d\n", dev_cap->max_rss_tbl_sz); 9607d077cd3SMatan Barak mlx4_dbg(dev, "DMFS high rate steer QPn base: %d\n", 9617d077cd3SMatan Barak dev_cap->dmfs_high_rate_qpn_base); 9627d077cd3SMatan Barak mlx4_dbg(dev, "DMFS high rate steer QPn range: %d\n", 9637d077cd3SMatan Barak dev_cap->dmfs_high_rate_qpn_range); 9645a2cc190SJeff Kirsher dump_dev_cap_flags(dev, dev_cap->flags); 965b3416f44SShlomo Pongratz dump_dev_cap_flags2(dev, dev_cap->flags2); 9665a2cc190SJeff Kirsher } 9675a2cc190SJeff Kirsher 968431df8c7SMatan Barak int mlx4_QUERY_PORT(struct mlx4_dev *dev, int port, struct mlx4_port_cap *port_cap) 969431df8c7SMatan Barak { 970431df8c7SMatan Barak struct mlx4_cmd_mailbox *mailbox; 971431df8c7SMatan Barak u32 *outbox; 972431df8c7SMatan Barak u8 field; 973431df8c7SMatan Barak u32 field32; 974431df8c7SMatan Barak int err; 975431df8c7SMatan Barak 976431df8c7SMatan Barak mailbox = mlx4_alloc_cmd_mailbox(dev); 977431df8c7SMatan Barak if (IS_ERR(mailbox)) 978431df8c7SMatan Barak return PTR_ERR(mailbox); 979431df8c7SMatan Barak outbox = mailbox->buf; 980431df8c7SMatan Barak 981431df8c7SMatan Barak if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 982431df8c7SMatan Barak err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, 983431df8c7SMatan Barak MLX4_CMD_TIME_CLASS_A, 984431df8c7SMatan Barak MLX4_CMD_NATIVE); 985431df8c7SMatan Barak 986431df8c7SMatan Barak if (err) 987431df8c7SMatan Barak goto out; 988431df8c7SMatan Barak 989431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); 990431df8c7SMatan Barak port_cap->max_vl = field >> 4; 991431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET); 992431df8c7SMatan Barak port_cap->ib_mtu = field >> 4; 993431df8c7SMatan Barak port_cap->max_port_width = field & 0xf; 994431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET); 995431df8c7SMatan Barak port_cap->max_gids = 1 << (field & 0xf); 996431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET); 997431df8c7SMatan Barak port_cap->max_pkeys = 1 << (field & 0xf); 998431df8c7SMatan Barak } else { 999431df8c7SMatan Barak #define QUERY_PORT_SUPPORTED_TYPE_OFFSET 0x00 1000431df8c7SMatan Barak #define QUERY_PORT_MTU_OFFSET 0x01 1001431df8c7SMatan Barak #define QUERY_PORT_ETH_MTU_OFFSET 0x02 1002431df8c7SMatan Barak #define QUERY_PORT_WIDTH_OFFSET 0x06 1003431df8c7SMatan Barak #define QUERY_PORT_MAX_GID_PKEY_OFFSET 0x07 1004431df8c7SMatan Barak #define QUERY_PORT_MAX_MACVLAN_OFFSET 0x0a 1005431df8c7SMatan Barak #define QUERY_PORT_MAX_VL_OFFSET 0x0b 1006431df8c7SMatan Barak #define QUERY_PORT_MAC_OFFSET 0x10 1007431df8c7SMatan Barak #define QUERY_PORT_TRANS_VENDOR_OFFSET 0x18 1008431df8c7SMatan Barak #define QUERY_PORT_WAVELENGTH_OFFSET 0x1c 1009431df8c7SMatan Barak #define QUERY_PORT_TRANS_CODE_OFFSET 0x20 1010431df8c7SMatan Barak 1011431df8c7SMatan Barak err = mlx4_cmd_box(dev, 0, mailbox->dma, port, 0, MLX4_CMD_QUERY_PORT, 1012431df8c7SMatan Barak MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 1013431df8c7SMatan Barak if (err) 1014431df8c7SMatan Barak goto out; 1015431df8c7SMatan Barak 1016431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_PORT_SUPPORTED_TYPE_OFFSET); 1017431df8c7SMatan Barak port_cap->supported_port_types = field & 3; 1018431df8c7SMatan Barak port_cap->suggested_type = (field >> 3) & 1; 1019431df8c7SMatan Barak port_cap->default_sense = (field >> 4) & 1; 10207d077cd3SMatan Barak port_cap->dmfs_optimized_state = (field >> 5) & 1; 1021431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET); 1022431df8c7SMatan Barak port_cap->ib_mtu = field & 0xf; 1023431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET); 1024431df8c7SMatan Barak port_cap->max_port_width = field & 0xf; 1025431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET); 1026431df8c7SMatan Barak port_cap->max_gids = 1 << (field >> 4); 1027431df8c7SMatan Barak port_cap->max_pkeys = 1 << (field & 0xf); 1028431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET); 1029431df8c7SMatan Barak port_cap->max_vl = field & 0xf; 1030431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_PORT_MAX_MACVLAN_OFFSET); 1031431df8c7SMatan Barak port_cap->log_max_macs = field & 0xf; 1032431df8c7SMatan Barak port_cap->log_max_vlans = field >> 4; 1033431df8c7SMatan Barak MLX4_GET(port_cap->eth_mtu, outbox, QUERY_PORT_ETH_MTU_OFFSET); 1034431df8c7SMatan Barak MLX4_GET(port_cap->def_mac, outbox, QUERY_PORT_MAC_OFFSET); 1035431df8c7SMatan Barak MLX4_GET(field32, outbox, QUERY_PORT_TRANS_VENDOR_OFFSET); 1036431df8c7SMatan Barak port_cap->trans_type = field32 >> 24; 1037431df8c7SMatan Barak port_cap->vendor_oui = field32 & 0xffffff; 1038431df8c7SMatan Barak MLX4_GET(port_cap->wavelength, outbox, QUERY_PORT_WAVELENGTH_OFFSET); 1039431df8c7SMatan Barak MLX4_GET(port_cap->trans_code, outbox, QUERY_PORT_TRANS_CODE_OFFSET); 1040431df8c7SMatan Barak } 1041431df8c7SMatan Barak 1042431df8c7SMatan Barak out: 1043431df8c7SMatan Barak mlx4_free_cmd_mailbox(dev, mailbox); 1044431df8c7SMatan Barak return err; 1045431df8c7SMatan Barak } 1046431df8c7SMatan Barak 1047383677daSOr Gerlitz #define DEV_CAP_EXT_2_FLAG_VLAN_CONTROL (1 << 26) 1048383677daSOr Gerlitz #define DEV_CAP_EXT_2_FLAG_80_VFS (1 << 21) 1049383677daSOr Gerlitz #define DEV_CAP_EXT_2_FLAG_FSM (1 << 20) 1050383677daSOr Gerlitz 1051b91cb3ebSJack Morgenstein int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, 1052b91cb3ebSJack Morgenstein struct mlx4_vhcr *vhcr, 1053b91cb3ebSJack Morgenstein struct mlx4_cmd_mailbox *inbox, 1054b91cb3ebSJack Morgenstein struct mlx4_cmd_mailbox *outbox, 1055b91cb3ebSJack Morgenstein struct mlx4_cmd_info *cmd) 1056b91cb3ebSJack Morgenstein { 10572a4fae14SJack Morgenstein u64 flags; 1058b91cb3ebSJack Morgenstein int err = 0; 1059b91cb3ebSJack Morgenstein u8 field; 1060383677daSOr Gerlitz u32 bmme_flags, field32; 1061449fc488SMatan Barak int real_port; 1062449fc488SMatan Barak int slave_port; 1063449fc488SMatan Barak int first_port; 1064449fc488SMatan Barak struct mlx4_active_ports actv_ports; 1065b91cb3ebSJack Morgenstein 1066b91cb3ebSJack Morgenstein err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, 1067b91cb3ebSJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 1068b91cb3ebSJack Morgenstein if (err) 1069b91cb3ebSJack Morgenstein return err; 1070b91cb3ebSJack Morgenstein 1071cc1ade94SShani Michaeli /* add port mng change event capability and disable mw type 1 1072cc1ade94SShani Michaeli * unconditionally to slaves 1073cc1ade94SShani Michaeli */ 10742a4fae14SJack Morgenstein MLX4_GET(flags, outbox->buf, QUERY_DEV_CAP_EXT_FLAGS_OFFSET); 10752a4fae14SJack Morgenstein flags |= MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV; 1076cc1ade94SShani Michaeli flags &= ~MLX4_DEV_CAP_FLAG_MEM_WINDOW; 1077449fc488SMatan Barak actv_ports = mlx4_get_active_ports(dev, slave); 1078449fc488SMatan Barak first_port = find_first_bit(actv_ports.ports, dev->caps.num_ports); 1079449fc488SMatan Barak for (slave_port = 0, real_port = first_port; 1080449fc488SMatan Barak real_port < first_port + 1081449fc488SMatan Barak bitmap_weight(actv_ports.ports, dev->caps.num_ports); 1082449fc488SMatan Barak ++real_port, ++slave_port) { 1083449fc488SMatan Barak if (flags & (MLX4_DEV_CAP_FLAG_WOL_PORT1 << real_port)) 1084449fc488SMatan Barak flags |= MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port; 1085449fc488SMatan Barak else 1086449fc488SMatan Barak flags &= ~(MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port); 1087449fc488SMatan Barak } 1088449fc488SMatan Barak for (; slave_port < dev->caps.num_ports; ++slave_port) 1089449fc488SMatan Barak flags &= ~(MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port); 10902a4fae14SJack Morgenstein MLX4_PUT(outbox->buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET); 10912a4fae14SJack Morgenstein 1092449fc488SMatan Barak MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_VL_PORT_OFFSET); 1093449fc488SMatan Barak field &= ~0x0F; 1094449fc488SMatan Barak field |= bitmap_weight(actv_ports.ports, dev->caps.num_ports) & 0x0F; 1095449fc488SMatan Barak MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_VL_PORT_OFFSET); 1096449fc488SMatan Barak 109730b40c31SAmir Vadai /* For guests, disable timestamp */ 109830b40c31SAmir Vadai MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET); 109930b40c31SAmir Vadai field &= 0x7f; 110030b40c31SAmir Vadai MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET); 110130b40c31SAmir Vadai 11027ffdf726SOr Gerlitz /* For guests, disable vxlan tunneling */ 110357352ef4SAmir Vadai MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_VXLAN); 11047ffdf726SOr Gerlitz field &= 0xf7; 11057ffdf726SOr Gerlitz MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_VXLAN); 11067ffdf726SOr Gerlitz 1107b91cb3ebSJack Morgenstein /* For guests, report Blueflame disabled */ 1108b91cb3ebSJack Morgenstein MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_BF_OFFSET); 1109b91cb3ebSJack Morgenstein field &= 0x7f; 1110b91cb3ebSJack Morgenstein MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_BF_OFFSET); 1111b91cb3ebSJack Morgenstein 1112cc1ade94SShani Michaeli /* For guests, disable mw type 2 */ 111357352ef4SAmir Vadai MLX4_GET(bmme_flags, outbox->buf, QUERY_DEV_CAP_BMME_FLAGS_OFFSET); 1114cc1ade94SShani Michaeli bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN; 1115cc1ade94SShani Michaeli MLX4_PUT(outbox->buf, bmme_flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET); 1116cc1ade94SShani Michaeli 11170081c8f3SJack Morgenstein /* turn off device-managed steering capability if not enabled */ 11180081c8f3SJack Morgenstein if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) { 11190081c8f3SJack Morgenstein MLX4_GET(field, outbox->buf, 11200081c8f3SJack Morgenstein QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET); 11210081c8f3SJack Morgenstein field &= 0x7f; 11220081c8f3SJack Morgenstein MLX4_PUT(outbox->buf, field, 11230081c8f3SJack Morgenstein QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET); 11240081c8f3SJack Morgenstein } 11254de65803SMatan Barak 11264de65803SMatan Barak /* turn off ipoib managed steering for guests */ 112757352ef4SAmir Vadai MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET); 11284de65803SMatan Barak field &= ~0x80; 11294de65803SMatan Barak MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET); 11304de65803SMatan Barak 1131383677daSOr Gerlitz /* turn off host side virt features (VST, FSM, etc) for guests */ 1132383677daSOr Gerlitz MLX4_GET(field32, outbox->buf, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); 1133383677daSOr Gerlitz field32 &= ~(DEV_CAP_EXT_2_FLAG_VLAN_CONTROL | DEV_CAP_EXT_2_FLAG_80_VFS | 1134383677daSOr Gerlitz DEV_CAP_EXT_2_FLAG_FSM); 1135383677daSOr Gerlitz MLX4_PUT(outbox->buf, field32, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); 1136383677daSOr Gerlitz 1137b91cb3ebSJack Morgenstein return 0; 1138b91cb3ebSJack Morgenstein } 1139b91cb3ebSJack Morgenstein 11405cc914f1SMarcel Apfelbaum int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, 11415cc914f1SMarcel Apfelbaum struct mlx4_vhcr *vhcr, 11425cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *inbox, 11435cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *outbox, 11445cc914f1SMarcel Apfelbaum struct mlx4_cmd_info *cmd) 11455cc914f1SMarcel Apfelbaum { 11460eb62b93SRony Efraim struct mlx4_priv *priv = mlx4_priv(dev); 11475cc914f1SMarcel Apfelbaum u64 def_mac; 11485cc914f1SMarcel Apfelbaum u8 port_type; 11496634961cSJack Morgenstein u16 short_field; 11505cc914f1SMarcel Apfelbaum int err; 1151948e306dSRony Efraim int admin_link_state; 1152449fc488SMatan Barak int port = mlx4_slave_convert_port(dev, slave, 1153449fc488SMatan Barak vhcr->in_modifier & 0xFF); 11545cc914f1SMarcel Apfelbaum 1155105c320fSJack Morgenstein #define MLX4_VF_PORT_NO_LINK_SENSE_MASK 0xE0 1156948e306dSRony Efraim #define MLX4_PORT_LINK_UP_MASK 0x80 11576634961cSJack Morgenstein #define QUERY_PORT_CUR_MAX_PKEY_OFFSET 0x0c 11586634961cSJack Morgenstein #define QUERY_PORT_CUR_MAX_GID_OFFSET 0x0e 115995f56e7aSYevgeny Petrilin 1160449fc488SMatan Barak if (port < 0) 1161449fc488SMatan Barak return -EINVAL; 1162449fc488SMatan Barak 1163a7401b9cSJack Morgenstein /* Protect against untrusted guests: enforce that this is the 1164a7401b9cSJack Morgenstein * QUERY_PORT general query. 1165a7401b9cSJack Morgenstein */ 1166a7401b9cSJack Morgenstein if (vhcr->op_modifier || vhcr->in_modifier & ~0xFF) 1167a7401b9cSJack Morgenstein return -EINVAL; 1168a7401b9cSJack Morgenstein 1169a7401b9cSJack Morgenstein vhcr->in_modifier = port; 1170449fc488SMatan Barak 11715cc914f1SMarcel Apfelbaum err = mlx4_cmd_box(dev, 0, outbox->dma, vhcr->in_modifier, 0, 11725cc914f1SMarcel Apfelbaum MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, 11735cc914f1SMarcel Apfelbaum MLX4_CMD_NATIVE); 11745cc914f1SMarcel Apfelbaum 11755cc914f1SMarcel Apfelbaum if (!err && dev->caps.function != slave) { 11760eb62b93SRony Efraim def_mac = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac; 11775cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, def_mac, QUERY_PORT_MAC_OFFSET); 11785cc914f1SMarcel Apfelbaum 11795cc914f1SMarcel Apfelbaum /* get port type - currently only eth is enabled */ 11805cc914f1SMarcel Apfelbaum MLX4_GET(port_type, outbox->buf, 11815cc914f1SMarcel Apfelbaum QUERY_PORT_SUPPORTED_TYPE_OFFSET); 11825cc914f1SMarcel Apfelbaum 1183105c320fSJack Morgenstein /* No link sensing allowed */ 1184105c320fSJack Morgenstein port_type &= MLX4_VF_PORT_NO_LINK_SENSE_MASK; 1185105c320fSJack Morgenstein /* set port type to currently operating port type */ 1186105c320fSJack Morgenstein port_type |= (dev->caps.port_type[vhcr->in_modifier] & 0x3); 11875cc914f1SMarcel Apfelbaum 1188948e306dSRony Efraim admin_link_state = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.link_state; 1189948e306dSRony Efraim if (IFLA_VF_LINK_STATE_ENABLE == admin_link_state) 1190948e306dSRony Efraim port_type |= MLX4_PORT_LINK_UP_MASK; 1191948e306dSRony Efraim else if (IFLA_VF_LINK_STATE_DISABLE == admin_link_state) 1192948e306dSRony Efraim port_type &= ~MLX4_PORT_LINK_UP_MASK; 1193948e306dSRony Efraim 11945cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, port_type, 11955cc914f1SMarcel Apfelbaum QUERY_PORT_SUPPORTED_TYPE_OFFSET); 11966634961cSJack Morgenstein 1197b6ffaeffSJack Morgenstein if (dev->caps.port_type[vhcr->in_modifier] == MLX4_PORT_TYPE_ETH) 1198449fc488SMatan Barak short_field = mlx4_get_slave_num_gids(dev, slave, port); 1199b6ffaeffSJack Morgenstein else 12006634961cSJack Morgenstein short_field = 1; /* slave max gids */ 12016634961cSJack Morgenstein MLX4_PUT(outbox->buf, short_field, 12026634961cSJack Morgenstein QUERY_PORT_CUR_MAX_GID_OFFSET); 12036634961cSJack Morgenstein 12046634961cSJack Morgenstein short_field = dev->caps.pkey_table_len[vhcr->in_modifier]; 12056634961cSJack Morgenstein MLX4_PUT(outbox->buf, short_field, 12066634961cSJack Morgenstein QUERY_PORT_CUR_MAX_PKEY_OFFSET); 12075cc914f1SMarcel Apfelbaum } 12085cc914f1SMarcel Apfelbaum 12095cc914f1SMarcel Apfelbaum return err; 12105cc914f1SMarcel Apfelbaum } 12115cc914f1SMarcel Apfelbaum 12126634961cSJack Morgenstein int mlx4_get_slave_pkey_gid_tbl_len(struct mlx4_dev *dev, u8 port, 12136634961cSJack Morgenstein int *gid_tbl_len, int *pkey_tbl_len) 12146634961cSJack Morgenstein { 12156634961cSJack Morgenstein struct mlx4_cmd_mailbox *mailbox; 12166634961cSJack Morgenstein u32 *outbox; 12176634961cSJack Morgenstein u16 field; 12186634961cSJack Morgenstein int err; 12196634961cSJack Morgenstein 12206634961cSJack Morgenstein mailbox = mlx4_alloc_cmd_mailbox(dev); 12216634961cSJack Morgenstein if (IS_ERR(mailbox)) 12226634961cSJack Morgenstein return PTR_ERR(mailbox); 12236634961cSJack Morgenstein 12246634961cSJack Morgenstein err = mlx4_cmd_box(dev, 0, mailbox->dma, port, 0, 12256634961cSJack Morgenstein MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, 12266634961cSJack Morgenstein MLX4_CMD_WRAPPED); 12276634961cSJack Morgenstein if (err) 12286634961cSJack Morgenstein goto out; 12296634961cSJack Morgenstein 12306634961cSJack Morgenstein outbox = mailbox->buf; 12316634961cSJack Morgenstein 12326634961cSJack Morgenstein MLX4_GET(field, outbox, QUERY_PORT_CUR_MAX_GID_OFFSET); 12336634961cSJack Morgenstein *gid_tbl_len = field; 12346634961cSJack Morgenstein 12356634961cSJack Morgenstein MLX4_GET(field, outbox, QUERY_PORT_CUR_MAX_PKEY_OFFSET); 12366634961cSJack Morgenstein *pkey_tbl_len = field; 12376634961cSJack Morgenstein 12386634961cSJack Morgenstein out: 12396634961cSJack Morgenstein mlx4_free_cmd_mailbox(dev, mailbox); 12406634961cSJack Morgenstein return err; 12416634961cSJack Morgenstein } 12426634961cSJack Morgenstein EXPORT_SYMBOL(mlx4_get_slave_pkey_gid_tbl_len); 12436634961cSJack Morgenstein 12445a2cc190SJeff Kirsher int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt) 12455a2cc190SJeff Kirsher { 12465a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 12475a2cc190SJeff Kirsher struct mlx4_icm_iter iter; 12485a2cc190SJeff Kirsher __be64 *pages; 12495a2cc190SJeff Kirsher int lg; 12505a2cc190SJeff Kirsher int nent = 0; 12515a2cc190SJeff Kirsher int i; 12525a2cc190SJeff Kirsher int err = 0; 12535a2cc190SJeff Kirsher int ts = 0, tc = 0; 12545a2cc190SJeff Kirsher 12555a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 12565a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 12575a2cc190SJeff Kirsher return PTR_ERR(mailbox); 12585a2cc190SJeff Kirsher pages = mailbox->buf; 12595a2cc190SJeff Kirsher 12605a2cc190SJeff Kirsher for (mlx4_icm_first(icm, &iter); 12615a2cc190SJeff Kirsher !mlx4_icm_last(&iter); 12625a2cc190SJeff Kirsher mlx4_icm_next(&iter)) { 12635a2cc190SJeff Kirsher /* 12645a2cc190SJeff Kirsher * We have to pass pages that are aligned to their 12655a2cc190SJeff Kirsher * size, so find the least significant 1 in the 12665a2cc190SJeff Kirsher * address or size and use that as our log2 size. 12675a2cc190SJeff Kirsher */ 12685a2cc190SJeff Kirsher lg = ffs(mlx4_icm_addr(&iter) | mlx4_icm_size(&iter)) - 1; 12695a2cc190SJeff Kirsher if (lg < MLX4_ICM_PAGE_SHIFT) { 12701a91de28SJoe Perches mlx4_warn(dev, "Got FW area not aligned to %d (%llx/%lx)\n", 12715a2cc190SJeff Kirsher MLX4_ICM_PAGE_SIZE, 12725a2cc190SJeff Kirsher (unsigned long long) mlx4_icm_addr(&iter), 12735a2cc190SJeff Kirsher mlx4_icm_size(&iter)); 12745a2cc190SJeff Kirsher err = -EINVAL; 12755a2cc190SJeff Kirsher goto out; 12765a2cc190SJeff Kirsher } 12775a2cc190SJeff Kirsher 12785a2cc190SJeff Kirsher for (i = 0; i < mlx4_icm_size(&iter) >> lg; ++i) { 12795a2cc190SJeff Kirsher if (virt != -1) { 12805a2cc190SJeff Kirsher pages[nent * 2] = cpu_to_be64(virt); 12815a2cc190SJeff Kirsher virt += 1 << lg; 12825a2cc190SJeff Kirsher } 12835a2cc190SJeff Kirsher 12845a2cc190SJeff Kirsher pages[nent * 2 + 1] = 12855a2cc190SJeff Kirsher cpu_to_be64((mlx4_icm_addr(&iter) + (i << lg)) | 12865a2cc190SJeff Kirsher (lg - MLX4_ICM_PAGE_SHIFT)); 12875a2cc190SJeff Kirsher ts += 1 << (lg - 10); 12885a2cc190SJeff Kirsher ++tc; 12895a2cc190SJeff Kirsher 12905a2cc190SJeff Kirsher if (++nent == MLX4_MAILBOX_SIZE / 16) { 12915a2cc190SJeff Kirsher err = mlx4_cmd(dev, mailbox->dma, nent, 0, op, 1292f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_B, 1293f9baff50SJack Morgenstein MLX4_CMD_NATIVE); 12945a2cc190SJeff Kirsher if (err) 12955a2cc190SJeff Kirsher goto out; 12965a2cc190SJeff Kirsher nent = 0; 12975a2cc190SJeff Kirsher } 12985a2cc190SJeff Kirsher } 12995a2cc190SJeff Kirsher } 13005a2cc190SJeff Kirsher 13015a2cc190SJeff Kirsher if (nent) 1302f9baff50SJack Morgenstein err = mlx4_cmd(dev, mailbox->dma, nent, 0, op, 1303f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 13045a2cc190SJeff Kirsher if (err) 13055a2cc190SJeff Kirsher goto out; 13065a2cc190SJeff Kirsher 13075a2cc190SJeff Kirsher switch (op) { 13085a2cc190SJeff Kirsher case MLX4_CMD_MAP_FA: 13091a91de28SJoe Perches mlx4_dbg(dev, "Mapped %d chunks/%d KB for FW\n", tc, ts); 13105a2cc190SJeff Kirsher break; 13115a2cc190SJeff Kirsher case MLX4_CMD_MAP_ICM_AUX: 13121a91de28SJoe Perches mlx4_dbg(dev, "Mapped %d chunks/%d KB for ICM aux\n", tc, ts); 13135a2cc190SJeff Kirsher break; 13145a2cc190SJeff Kirsher case MLX4_CMD_MAP_ICM: 13151a91de28SJoe Perches mlx4_dbg(dev, "Mapped %d chunks/%d KB at %llx for ICM\n", 13165a2cc190SJeff Kirsher tc, ts, (unsigned long long) virt - (ts << 10)); 13175a2cc190SJeff Kirsher break; 13185a2cc190SJeff Kirsher } 13195a2cc190SJeff Kirsher 13205a2cc190SJeff Kirsher out: 13215a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 13225a2cc190SJeff Kirsher return err; 13235a2cc190SJeff Kirsher } 13245a2cc190SJeff Kirsher 13255a2cc190SJeff Kirsher int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm) 13265a2cc190SJeff Kirsher { 13275a2cc190SJeff Kirsher return mlx4_map_cmd(dev, MLX4_CMD_MAP_FA, icm, -1); 13285a2cc190SJeff Kirsher } 13295a2cc190SJeff Kirsher 13305a2cc190SJeff Kirsher int mlx4_UNMAP_FA(struct mlx4_dev *dev) 13315a2cc190SJeff Kirsher { 1332f9baff50SJack Morgenstein return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_FA, 1333f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 13345a2cc190SJeff Kirsher } 13355a2cc190SJeff Kirsher 13365a2cc190SJeff Kirsher 13375a2cc190SJeff Kirsher int mlx4_RUN_FW(struct mlx4_dev *dev) 13385a2cc190SJeff Kirsher { 1339f9baff50SJack Morgenstein return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_RUN_FW, 1340f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 13415a2cc190SJeff Kirsher } 13425a2cc190SJeff Kirsher 13435a2cc190SJeff Kirsher int mlx4_QUERY_FW(struct mlx4_dev *dev) 13445a2cc190SJeff Kirsher { 13455a2cc190SJeff Kirsher struct mlx4_fw *fw = &mlx4_priv(dev)->fw; 13465a2cc190SJeff Kirsher struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; 13475a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 13485a2cc190SJeff Kirsher u32 *outbox; 13495a2cc190SJeff Kirsher int err = 0; 13505a2cc190SJeff Kirsher u64 fw_ver; 13515a2cc190SJeff Kirsher u16 cmd_if_rev; 13525a2cc190SJeff Kirsher u8 lg; 13535a2cc190SJeff Kirsher 13545a2cc190SJeff Kirsher #define QUERY_FW_OUT_SIZE 0x100 13555a2cc190SJeff Kirsher #define QUERY_FW_VER_OFFSET 0x00 13565cc914f1SMarcel Apfelbaum #define QUERY_FW_PPF_ID 0x09 13575a2cc190SJeff Kirsher #define QUERY_FW_CMD_IF_REV_OFFSET 0x0a 13585a2cc190SJeff Kirsher #define QUERY_FW_MAX_CMD_OFFSET 0x0f 13595a2cc190SJeff Kirsher #define QUERY_FW_ERR_START_OFFSET 0x30 13605a2cc190SJeff Kirsher #define QUERY_FW_ERR_SIZE_OFFSET 0x38 13615a2cc190SJeff Kirsher #define QUERY_FW_ERR_BAR_OFFSET 0x3c 13625a2cc190SJeff Kirsher 13635a2cc190SJeff Kirsher #define QUERY_FW_SIZE_OFFSET 0x00 13645a2cc190SJeff Kirsher #define QUERY_FW_CLR_INT_BASE_OFFSET 0x20 13655a2cc190SJeff Kirsher #define QUERY_FW_CLR_INT_BAR_OFFSET 0x28 13665a2cc190SJeff Kirsher 13675cc914f1SMarcel Apfelbaum #define QUERY_FW_COMM_BASE_OFFSET 0x40 13685cc914f1SMarcel Apfelbaum #define QUERY_FW_COMM_BAR_OFFSET 0x48 13695cc914f1SMarcel Apfelbaum 1370ddd8a6c1SEugenia Emantayev #define QUERY_FW_CLOCK_OFFSET 0x50 1371ddd8a6c1SEugenia Emantayev #define QUERY_FW_CLOCK_BAR 0x58 1372ddd8a6c1SEugenia Emantayev 13735a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 13745a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 13755a2cc190SJeff Kirsher return PTR_ERR(mailbox); 13765a2cc190SJeff Kirsher outbox = mailbox->buf; 13775a2cc190SJeff Kirsher 13785a2cc190SJeff Kirsher err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_FW, 1379f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 13805a2cc190SJeff Kirsher if (err) 13815a2cc190SJeff Kirsher goto out; 13825a2cc190SJeff Kirsher 13835a2cc190SJeff Kirsher MLX4_GET(fw_ver, outbox, QUERY_FW_VER_OFFSET); 13845a2cc190SJeff Kirsher /* 13855a2cc190SJeff Kirsher * FW subminor version is at more significant bits than minor 13865a2cc190SJeff Kirsher * version, so swap here. 13875a2cc190SJeff Kirsher */ 13885a2cc190SJeff Kirsher dev->caps.fw_ver = (fw_ver & 0xffff00000000ull) | 13895a2cc190SJeff Kirsher ((fw_ver & 0xffff0000ull) >> 16) | 13905a2cc190SJeff Kirsher ((fw_ver & 0x0000ffffull) << 16); 13915a2cc190SJeff Kirsher 1392752a50caSJack Morgenstein MLX4_GET(lg, outbox, QUERY_FW_PPF_ID); 1393752a50caSJack Morgenstein dev->caps.function = lg; 1394752a50caSJack Morgenstein 1395b91cb3ebSJack Morgenstein if (mlx4_is_slave(dev)) 1396b91cb3ebSJack Morgenstein goto out; 1397b91cb3ebSJack Morgenstein 13985cc914f1SMarcel Apfelbaum 13995a2cc190SJeff Kirsher MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET); 14005a2cc190SJeff Kirsher if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV || 14015a2cc190SJeff Kirsher cmd_if_rev > MLX4_COMMAND_INTERFACE_MAX_REV) { 14021a91de28SJoe Perches mlx4_err(dev, "Installed FW has unsupported command interface revision %d\n", 14035a2cc190SJeff Kirsher cmd_if_rev); 14045a2cc190SJeff Kirsher mlx4_err(dev, "(Installed FW version is %d.%d.%03d)\n", 14055a2cc190SJeff Kirsher (int) (dev->caps.fw_ver >> 32), 14065a2cc190SJeff Kirsher (int) (dev->caps.fw_ver >> 16) & 0xffff, 14075a2cc190SJeff Kirsher (int) dev->caps.fw_ver & 0xffff); 14081a91de28SJoe Perches mlx4_err(dev, "This driver version supports only revisions %d to %d\n", 14095a2cc190SJeff Kirsher MLX4_COMMAND_INTERFACE_MIN_REV, MLX4_COMMAND_INTERFACE_MAX_REV); 14105a2cc190SJeff Kirsher err = -ENODEV; 14115a2cc190SJeff Kirsher goto out; 14125a2cc190SJeff Kirsher } 14135a2cc190SJeff Kirsher 14145a2cc190SJeff Kirsher if (cmd_if_rev < MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS) 14155a2cc190SJeff Kirsher dev->flags |= MLX4_FLAG_OLD_PORT_CMDS; 14165a2cc190SJeff Kirsher 14175a2cc190SJeff Kirsher MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET); 14185a2cc190SJeff Kirsher cmd->max_cmds = 1 << lg; 14195a2cc190SJeff Kirsher 14205a2cc190SJeff Kirsher mlx4_dbg(dev, "FW version %d.%d.%03d (cmd intf rev %d), max commands %d\n", 14215a2cc190SJeff Kirsher (int) (dev->caps.fw_ver >> 32), 14225a2cc190SJeff Kirsher (int) (dev->caps.fw_ver >> 16) & 0xffff, 14235a2cc190SJeff Kirsher (int) dev->caps.fw_ver & 0xffff, 14245a2cc190SJeff Kirsher cmd_if_rev, cmd->max_cmds); 14255a2cc190SJeff Kirsher 14265a2cc190SJeff Kirsher MLX4_GET(fw->catas_offset, outbox, QUERY_FW_ERR_START_OFFSET); 14275a2cc190SJeff Kirsher MLX4_GET(fw->catas_size, outbox, QUERY_FW_ERR_SIZE_OFFSET); 14285a2cc190SJeff Kirsher MLX4_GET(fw->catas_bar, outbox, QUERY_FW_ERR_BAR_OFFSET); 14295a2cc190SJeff Kirsher fw->catas_bar = (fw->catas_bar >> 6) * 2; 14305a2cc190SJeff Kirsher 14315a2cc190SJeff Kirsher mlx4_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x, BAR %d\n", 14325a2cc190SJeff Kirsher (unsigned long long) fw->catas_offset, fw->catas_size, fw->catas_bar); 14335a2cc190SJeff Kirsher 14345a2cc190SJeff Kirsher MLX4_GET(fw->fw_pages, outbox, QUERY_FW_SIZE_OFFSET); 14355a2cc190SJeff Kirsher MLX4_GET(fw->clr_int_base, outbox, QUERY_FW_CLR_INT_BASE_OFFSET); 14365a2cc190SJeff Kirsher MLX4_GET(fw->clr_int_bar, outbox, QUERY_FW_CLR_INT_BAR_OFFSET); 14375a2cc190SJeff Kirsher fw->clr_int_bar = (fw->clr_int_bar >> 6) * 2; 14385a2cc190SJeff Kirsher 14395cc914f1SMarcel Apfelbaum MLX4_GET(fw->comm_base, outbox, QUERY_FW_COMM_BASE_OFFSET); 14405cc914f1SMarcel Apfelbaum MLX4_GET(fw->comm_bar, outbox, QUERY_FW_COMM_BAR_OFFSET); 14415cc914f1SMarcel Apfelbaum fw->comm_bar = (fw->comm_bar >> 6) * 2; 14425cc914f1SMarcel Apfelbaum mlx4_dbg(dev, "Communication vector bar:%d offset:0x%llx\n", 14435cc914f1SMarcel Apfelbaum fw->comm_bar, fw->comm_base); 14445a2cc190SJeff Kirsher mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2); 14455a2cc190SJeff Kirsher 1446ddd8a6c1SEugenia Emantayev MLX4_GET(fw->clock_offset, outbox, QUERY_FW_CLOCK_OFFSET); 1447ddd8a6c1SEugenia Emantayev MLX4_GET(fw->clock_bar, outbox, QUERY_FW_CLOCK_BAR); 1448ddd8a6c1SEugenia Emantayev fw->clock_bar = (fw->clock_bar >> 6) * 2; 1449ddd8a6c1SEugenia Emantayev mlx4_dbg(dev, "Internal clock bar:%d offset:0x%llx\n", 1450ddd8a6c1SEugenia Emantayev fw->clock_bar, fw->clock_offset); 1451ddd8a6c1SEugenia Emantayev 14525a2cc190SJeff Kirsher /* 14535a2cc190SJeff Kirsher * Round up number of system pages needed in case 14545a2cc190SJeff Kirsher * MLX4_ICM_PAGE_SIZE < PAGE_SIZE. 14555a2cc190SJeff Kirsher */ 14565a2cc190SJeff Kirsher fw->fw_pages = 14575a2cc190SJeff Kirsher ALIGN(fw->fw_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >> 14585a2cc190SJeff Kirsher (PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT); 14595a2cc190SJeff Kirsher 14605a2cc190SJeff Kirsher mlx4_dbg(dev, "Clear int @ %llx, BAR %d\n", 14615a2cc190SJeff Kirsher (unsigned long long) fw->clr_int_base, fw->clr_int_bar); 14625a2cc190SJeff Kirsher 14635a2cc190SJeff Kirsher out: 14645a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 14655a2cc190SJeff Kirsher return err; 14665a2cc190SJeff Kirsher } 14675a2cc190SJeff Kirsher 1468b91cb3ebSJack Morgenstein int mlx4_QUERY_FW_wrapper(struct mlx4_dev *dev, int slave, 1469b91cb3ebSJack Morgenstein struct mlx4_vhcr *vhcr, 1470b91cb3ebSJack Morgenstein struct mlx4_cmd_mailbox *inbox, 1471b91cb3ebSJack Morgenstein struct mlx4_cmd_mailbox *outbox, 1472b91cb3ebSJack Morgenstein struct mlx4_cmd_info *cmd) 1473b91cb3ebSJack Morgenstein { 1474b91cb3ebSJack Morgenstein u8 *outbuf; 1475b91cb3ebSJack Morgenstein int err; 1476b91cb3ebSJack Morgenstein 1477b91cb3ebSJack Morgenstein outbuf = outbox->buf; 1478b91cb3ebSJack Morgenstein err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_FW, 1479b91cb3ebSJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 1480b91cb3ebSJack Morgenstein if (err) 1481b91cb3ebSJack Morgenstein return err; 1482b91cb3ebSJack Morgenstein 1483752a50caSJack Morgenstein /* for slaves, set pci PPF ID to invalid and zero out everything 1484752a50caSJack Morgenstein * else except FW version */ 1485b91cb3ebSJack Morgenstein outbuf[0] = outbuf[1] = 0; 1486b91cb3ebSJack Morgenstein memset(&outbuf[8], 0, QUERY_FW_OUT_SIZE - 8); 1487752a50caSJack Morgenstein outbuf[QUERY_FW_PPF_ID] = MLX4_INVALID_SLAVE_ID; 1488752a50caSJack Morgenstein 1489b91cb3ebSJack Morgenstein return 0; 1490b91cb3ebSJack Morgenstein } 1491b91cb3ebSJack Morgenstein 14925a2cc190SJeff Kirsher static void get_board_id(void *vsd, char *board_id) 14935a2cc190SJeff Kirsher { 14945a2cc190SJeff Kirsher int i; 14955a2cc190SJeff Kirsher 14965a2cc190SJeff Kirsher #define VSD_OFFSET_SIG1 0x00 14975a2cc190SJeff Kirsher #define VSD_OFFSET_SIG2 0xde 14985a2cc190SJeff Kirsher #define VSD_OFFSET_MLX_BOARD_ID 0xd0 14995a2cc190SJeff Kirsher #define VSD_OFFSET_TS_BOARD_ID 0x20 15005a2cc190SJeff Kirsher 15015a2cc190SJeff Kirsher #define VSD_SIGNATURE_TOPSPIN 0x5ad 15025a2cc190SJeff Kirsher 15035a2cc190SJeff Kirsher memset(board_id, 0, MLX4_BOARD_ID_LEN); 15045a2cc190SJeff Kirsher 15055a2cc190SJeff Kirsher if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN && 15065a2cc190SJeff Kirsher be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) { 15075a2cc190SJeff Kirsher strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MLX4_BOARD_ID_LEN); 15085a2cc190SJeff Kirsher } else { 15095a2cc190SJeff Kirsher /* 15105a2cc190SJeff Kirsher * The board ID is a string but the firmware byte 15115a2cc190SJeff Kirsher * swaps each 4-byte word before passing it back to 15125a2cc190SJeff Kirsher * us. Therefore we need to swab it before printing. 15135a2cc190SJeff Kirsher */ 15145a2cc190SJeff Kirsher for (i = 0; i < 4; ++i) 15155a2cc190SJeff Kirsher ((u32 *) board_id)[i] = 15165a2cc190SJeff Kirsher swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4)); 15175a2cc190SJeff Kirsher } 15185a2cc190SJeff Kirsher } 15195a2cc190SJeff Kirsher 15205a2cc190SJeff Kirsher int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter) 15215a2cc190SJeff Kirsher { 15225a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 15235a2cc190SJeff Kirsher u32 *outbox; 15245a2cc190SJeff Kirsher int err; 15255a2cc190SJeff Kirsher 15265a2cc190SJeff Kirsher #define QUERY_ADAPTER_OUT_SIZE 0x100 15275a2cc190SJeff Kirsher #define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10 15285a2cc190SJeff Kirsher #define QUERY_ADAPTER_VSD_OFFSET 0x20 15295a2cc190SJeff Kirsher 15305a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 15315a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 15325a2cc190SJeff Kirsher return PTR_ERR(mailbox); 15335a2cc190SJeff Kirsher outbox = mailbox->buf; 15345a2cc190SJeff Kirsher 15355a2cc190SJeff Kirsher err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_ADAPTER, 1536f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 15375a2cc190SJeff Kirsher if (err) 15385a2cc190SJeff Kirsher goto out; 15395a2cc190SJeff Kirsher 15405a2cc190SJeff Kirsher MLX4_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET); 15415a2cc190SJeff Kirsher 15425a2cc190SJeff Kirsher get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4, 15435a2cc190SJeff Kirsher adapter->board_id); 15445a2cc190SJeff Kirsher 15455a2cc190SJeff Kirsher out: 15465a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 15475a2cc190SJeff Kirsher return err; 15485a2cc190SJeff Kirsher } 15495a2cc190SJeff Kirsher 15505a2cc190SJeff Kirsher int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) 15515a2cc190SJeff Kirsher { 15525a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 15535a2cc190SJeff Kirsher __be32 *inbox; 15545a2cc190SJeff Kirsher int err; 15557d077cd3SMatan Barak static const u8 a0_dmfs_hw_steering[] = { 15567d077cd3SMatan Barak [MLX4_STEERING_DMFS_A0_DEFAULT] = 0, 15577d077cd3SMatan Barak [MLX4_STEERING_DMFS_A0_DYNAMIC] = 1, 15587d077cd3SMatan Barak [MLX4_STEERING_DMFS_A0_STATIC] = 2, 15597d077cd3SMatan Barak [MLX4_STEERING_DMFS_A0_DISABLE] = 3 15607d077cd3SMatan Barak }; 15615a2cc190SJeff Kirsher 15625a2cc190SJeff Kirsher #define INIT_HCA_IN_SIZE 0x200 15635a2cc190SJeff Kirsher #define INIT_HCA_VERSION_OFFSET 0x000 15645a2cc190SJeff Kirsher #define INIT_HCA_VERSION 2 15657ffdf726SOr Gerlitz #define INIT_HCA_VXLAN_OFFSET 0x0c 15665a2cc190SJeff Kirsher #define INIT_HCA_CACHELINE_SZ_OFFSET 0x0e 15675a2cc190SJeff Kirsher #define INIT_HCA_FLAGS_OFFSET 0x014 1568*be6a6b43SJack Morgenstein #define INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET 0x018 15695a2cc190SJeff Kirsher #define INIT_HCA_QPC_OFFSET 0x020 15705a2cc190SJeff Kirsher #define INIT_HCA_QPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x10) 15715a2cc190SJeff Kirsher #define INIT_HCA_LOG_QP_OFFSET (INIT_HCA_QPC_OFFSET + 0x17) 15725a2cc190SJeff Kirsher #define INIT_HCA_SRQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x28) 15735a2cc190SJeff Kirsher #define INIT_HCA_LOG_SRQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x2f) 15745a2cc190SJeff Kirsher #define INIT_HCA_CQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x30) 15755a2cc190SJeff Kirsher #define INIT_HCA_LOG_CQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x37) 15765cc914f1SMarcel Apfelbaum #define INIT_HCA_EQE_CQE_OFFSETS (INIT_HCA_QPC_OFFSET + 0x38) 157777507aa2SIdo Shamay #define INIT_HCA_EQE_CQE_STRIDE_OFFSET (INIT_HCA_QPC_OFFSET + 0x3b) 15785a2cc190SJeff Kirsher #define INIT_HCA_ALTC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x40) 15795a2cc190SJeff Kirsher #define INIT_HCA_AUXC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x50) 15805a2cc190SJeff Kirsher #define INIT_HCA_EQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x60) 15815a2cc190SJeff Kirsher #define INIT_HCA_LOG_EQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x67) 15827ae0e400SMatan Barak #define INIT_HCA_NUM_SYS_EQS_OFFSET (INIT_HCA_QPC_OFFSET + 0x6a) 15835a2cc190SJeff Kirsher #define INIT_HCA_RDMARC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x70) 15845a2cc190SJeff Kirsher #define INIT_HCA_LOG_RD_OFFSET (INIT_HCA_QPC_OFFSET + 0x77) 15855a2cc190SJeff Kirsher #define INIT_HCA_MCAST_OFFSET 0x0c0 15865a2cc190SJeff Kirsher #define INIT_HCA_MC_BASE_OFFSET (INIT_HCA_MCAST_OFFSET + 0x00) 15875a2cc190SJeff Kirsher #define INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12) 15885a2cc190SJeff Kirsher #define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16) 15895a2cc190SJeff Kirsher #define INIT_HCA_UC_STEERING_OFFSET (INIT_HCA_MCAST_OFFSET + 0x18) 15905a2cc190SJeff Kirsher #define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b) 15910ff1fb65SHadar Hen Zion #define INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN 0x6 15920ff1fb65SHadar Hen Zion #define INIT_HCA_FS_PARAM_OFFSET 0x1d0 15930ff1fb65SHadar Hen Zion #define INIT_HCA_FS_BASE_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x00) 15940ff1fb65SHadar Hen Zion #define INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x12) 15957d077cd3SMatan Barak #define INIT_HCA_FS_A0_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x18) 15960ff1fb65SHadar Hen Zion #define INIT_HCA_FS_LOG_TABLE_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x1b) 15970ff1fb65SHadar Hen Zion #define INIT_HCA_FS_ETH_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x21) 15980ff1fb65SHadar Hen Zion #define INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x22) 15990ff1fb65SHadar Hen Zion #define INIT_HCA_FS_IB_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x25) 16000ff1fb65SHadar Hen Zion #define INIT_HCA_FS_IB_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x26) 16015a2cc190SJeff Kirsher #define INIT_HCA_TPT_OFFSET 0x0f0 16025a2cc190SJeff Kirsher #define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00) 1603e448834eSShani Michaeli #define INIT_HCA_TPT_MW_OFFSET (INIT_HCA_TPT_OFFSET + 0x08) 16045a2cc190SJeff Kirsher #define INIT_HCA_LOG_MPT_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x0b) 16055a2cc190SJeff Kirsher #define INIT_HCA_MTT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x10) 16065a2cc190SJeff Kirsher #define INIT_HCA_CMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x18) 16075a2cc190SJeff Kirsher #define INIT_HCA_UAR_OFFSET 0x120 16085a2cc190SJeff Kirsher #define INIT_HCA_LOG_UAR_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0a) 16095a2cc190SJeff Kirsher #define INIT_HCA_UAR_PAGE_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0b) 16105a2cc190SJeff Kirsher 16115a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 16125a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 16135a2cc190SJeff Kirsher return PTR_ERR(mailbox); 16145a2cc190SJeff Kirsher inbox = mailbox->buf; 16155a2cc190SJeff Kirsher 16165a2cc190SJeff Kirsher *((u8 *) mailbox->buf + INIT_HCA_VERSION_OFFSET) = INIT_HCA_VERSION; 16175a2cc190SJeff Kirsher 16185a2cc190SJeff Kirsher *((u8 *) mailbox->buf + INIT_HCA_CACHELINE_SZ_OFFSET) = 16195a2cc190SJeff Kirsher (ilog2(cache_line_size()) - 4) << 5; 16205a2cc190SJeff Kirsher 16215a2cc190SJeff Kirsher #if defined(__LITTLE_ENDIAN) 16225a2cc190SJeff Kirsher *(inbox + INIT_HCA_FLAGS_OFFSET / 4) &= ~cpu_to_be32(1 << 1); 16235a2cc190SJeff Kirsher #elif defined(__BIG_ENDIAN) 16245a2cc190SJeff Kirsher *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 1); 16255a2cc190SJeff Kirsher #else 16265a2cc190SJeff Kirsher #error Host endianness not defined 16275a2cc190SJeff Kirsher #endif 16285a2cc190SJeff Kirsher /* Check port for UD address vector: */ 16295a2cc190SJeff Kirsher *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1); 16305a2cc190SJeff Kirsher 16315a2cc190SJeff Kirsher /* Enable IPoIB checksumming if we can: */ 16325a2cc190SJeff Kirsher if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM) 16335a2cc190SJeff Kirsher *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 3); 16345a2cc190SJeff Kirsher 16355a2cc190SJeff Kirsher /* Enable QoS support if module parameter set */ 16365a2cc190SJeff Kirsher if (enable_qos) 16375a2cc190SJeff Kirsher *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 2); 16385a2cc190SJeff Kirsher 16395a2cc190SJeff Kirsher /* enable counters */ 16405a2cc190SJeff Kirsher if (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS) 16415a2cc190SJeff Kirsher *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 4); 16425a2cc190SJeff Kirsher 164308ff3235SOr Gerlitz /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */ 164408ff3235SOr Gerlitz if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_EQE) { 164508ff3235SOr Gerlitz *(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 29); 164608ff3235SOr Gerlitz dev->caps.eqe_size = 64; 164708ff3235SOr Gerlitz dev->caps.eqe_factor = 1; 164808ff3235SOr Gerlitz } else { 164908ff3235SOr Gerlitz dev->caps.eqe_size = 32; 165008ff3235SOr Gerlitz dev->caps.eqe_factor = 0; 165108ff3235SOr Gerlitz } 165208ff3235SOr Gerlitz 165308ff3235SOr Gerlitz if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_CQE) { 165408ff3235SOr Gerlitz *(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 30); 165508ff3235SOr Gerlitz dev->caps.cqe_size = 64; 165677507aa2SIdo Shamay dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE; 165708ff3235SOr Gerlitz } else { 165808ff3235SOr Gerlitz dev->caps.cqe_size = 32; 165908ff3235SOr Gerlitz } 166008ff3235SOr Gerlitz 166177507aa2SIdo Shamay /* CX3 is capable of extending CQEs\EQEs to strides larger than 64B */ 166277507aa2SIdo Shamay if ((dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_EQE_STRIDE) && 166377507aa2SIdo Shamay (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_CQE_STRIDE)) { 166477507aa2SIdo Shamay dev->caps.eqe_size = cache_line_size(); 166577507aa2SIdo Shamay dev->caps.cqe_size = cache_line_size(); 166677507aa2SIdo Shamay dev->caps.eqe_factor = 0; 166777507aa2SIdo Shamay MLX4_PUT(inbox, (u8)((ilog2(dev->caps.eqe_size) - 5) << 4 | 166877507aa2SIdo Shamay (ilog2(dev->caps.eqe_size) - 5)), 166977507aa2SIdo Shamay INIT_HCA_EQE_CQE_STRIDE_OFFSET); 167077507aa2SIdo Shamay 167177507aa2SIdo Shamay /* User still need to know to support CQE > 32B */ 167277507aa2SIdo Shamay dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE; 167377507aa2SIdo Shamay } 167477507aa2SIdo Shamay 1675*be6a6b43SJack Morgenstein if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT) 1676*be6a6b43SJack Morgenstein *(inbox + INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET / 4) |= cpu_to_be32(1 << 31); 1677*be6a6b43SJack Morgenstein 16785a2cc190SJeff Kirsher /* QPC/EEC/CQC/EQC/RDMARC attributes */ 16795a2cc190SJeff Kirsher 16805a2cc190SJeff Kirsher MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET); 16815a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_num_qps, INIT_HCA_LOG_QP_OFFSET); 16825a2cc190SJeff Kirsher MLX4_PUT(inbox, param->srqc_base, INIT_HCA_SRQC_BASE_OFFSET); 16835a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_num_srqs, INIT_HCA_LOG_SRQ_OFFSET); 16845a2cc190SJeff Kirsher MLX4_PUT(inbox, param->cqc_base, INIT_HCA_CQC_BASE_OFFSET); 16855a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_num_cqs, INIT_HCA_LOG_CQ_OFFSET); 16865a2cc190SJeff Kirsher MLX4_PUT(inbox, param->altc_base, INIT_HCA_ALTC_BASE_OFFSET); 16875a2cc190SJeff Kirsher MLX4_PUT(inbox, param->auxc_base, INIT_HCA_AUXC_BASE_OFFSET); 16885a2cc190SJeff Kirsher MLX4_PUT(inbox, param->eqc_base, INIT_HCA_EQC_BASE_OFFSET); 16895a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_num_eqs, INIT_HCA_LOG_EQ_OFFSET); 16907ae0e400SMatan Barak MLX4_PUT(inbox, param->num_sys_eqs, INIT_HCA_NUM_SYS_EQS_OFFSET); 16915a2cc190SJeff Kirsher MLX4_PUT(inbox, param->rdmarc_base, INIT_HCA_RDMARC_BASE_OFFSET); 16925a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_rd_per_qp, INIT_HCA_LOG_RD_OFFSET); 16935a2cc190SJeff Kirsher 16940ff1fb65SHadar Hen Zion /* steering attributes */ 16950ff1fb65SHadar Hen Zion if (dev->caps.steering_mode == 16960ff1fb65SHadar Hen Zion MLX4_STEERING_MODE_DEVICE_MANAGED) { 16970ff1fb65SHadar Hen Zion *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= 16980ff1fb65SHadar Hen Zion cpu_to_be32(1 << 16990ff1fb65SHadar Hen Zion INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN); 17005a2cc190SJeff Kirsher 17010ff1fb65SHadar Hen Zion MLX4_PUT(inbox, param->mc_base, INIT_HCA_FS_BASE_OFFSET); 17020ff1fb65SHadar Hen Zion MLX4_PUT(inbox, param->log_mc_entry_sz, 17030ff1fb65SHadar Hen Zion INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); 17040ff1fb65SHadar Hen Zion MLX4_PUT(inbox, param->log_mc_table_sz, 17050ff1fb65SHadar Hen Zion INIT_HCA_FS_LOG_TABLE_SZ_OFFSET); 17060ff1fb65SHadar Hen Zion /* Enable Ethernet flow steering 17070ff1fb65SHadar Hen Zion * with udp unicast and tcp unicast 17080ff1fb65SHadar Hen Zion */ 17097d077cd3SMatan Barak if (dev->caps.dmfs_high_steer_mode != 17107d077cd3SMatan Barak MLX4_STEERING_DMFS_A0_STATIC) 17117d077cd3SMatan Barak MLX4_PUT(inbox, 17127d077cd3SMatan Barak (u8)(MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN), 17130ff1fb65SHadar Hen Zion INIT_HCA_FS_ETH_BITS_OFFSET); 17140ff1fb65SHadar Hen Zion MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, 17150ff1fb65SHadar Hen Zion INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET); 17160ff1fb65SHadar Hen Zion /* Enable IPoIB flow steering 17170ff1fb65SHadar Hen Zion * with udp unicast and tcp unicast 17180ff1fb65SHadar Hen Zion */ 171923537b73SHadar Hen Zion MLX4_PUT(inbox, (u8) (MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN), 17200ff1fb65SHadar Hen Zion INIT_HCA_FS_IB_BITS_OFFSET); 17210ff1fb65SHadar Hen Zion MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, 17220ff1fb65SHadar Hen Zion INIT_HCA_FS_IB_NUM_ADDRS_OFFSET); 17237d077cd3SMatan Barak 17247d077cd3SMatan Barak if (dev->caps.dmfs_high_steer_mode != 17257d077cd3SMatan Barak MLX4_STEERING_DMFS_A0_NOT_SUPPORTED) 17267d077cd3SMatan Barak MLX4_PUT(inbox, 17277d077cd3SMatan Barak ((u8)(a0_dmfs_hw_steering[dev->caps.dmfs_high_steer_mode] 17287d077cd3SMatan Barak << 6)), 17297d077cd3SMatan Barak INIT_HCA_FS_A0_OFFSET); 17300ff1fb65SHadar Hen Zion } else { 17315a2cc190SJeff Kirsher MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET); 17320ff1fb65SHadar Hen Zion MLX4_PUT(inbox, param->log_mc_entry_sz, 17330ff1fb65SHadar Hen Zion INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); 17340ff1fb65SHadar Hen Zion MLX4_PUT(inbox, param->log_mc_hash_sz, 17350ff1fb65SHadar Hen Zion INIT_HCA_LOG_MC_HASH_SZ_OFFSET); 17360ff1fb65SHadar Hen Zion MLX4_PUT(inbox, param->log_mc_table_sz, 17370ff1fb65SHadar Hen Zion INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); 1738c96d97f4SHadar Hen Zion if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0) 17390ff1fb65SHadar Hen Zion MLX4_PUT(inbox, (u8) (1 << 3), 17400ff1fb65SHadar Hen Zion INIT_HCA_UC_STEERING_OFFSET); 17410ff1fb65SHadar Hen Zion } 17425a2cc190SJeff Kirsher 17435a2cc190SJeff Kirsher /* TPT attributes */ 17445a2cc190SJeff Kirsher 17455a2cc190SJeff Kirsher MLX4_PUT(inbox, param->dmpt_base, INIT_HCA_DMPT_BASE_OFFSET); 1746e448834eSShani Michaeli MLX4_PUT(inbox, param->mw_enabled, INIT_HCA_TPT_MW_OFFSET); 17475a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_mpt_sz, INIT_HCA_LOG_MPT_SZ_OFFSET); 17485a2cc190SJeff Kirsher MLX4_PUT(inbox, param->mtt_base, INIT_HCA_MTT_BASE_OFFSET); 17495a2cc190SJeff Kirsher MLX4_PUT(inbox, param->cmpt_base, INIT_HCA_CMPT_BASE_OFFSET); 17505a2cc190SJeff Kirsher 17515a2cc190SJeff Kirsher /* UAR attributes */ 17525a2cc190SJeff Kirsher 1753ab9c17a0SJack Morgenstein MLX4_PUT(inbox, param->uar_page_sz, INIT_HCA_UAR_PAGE_SZ_OFFSET); 17545a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_uar_sz, INIT_HCA_LOG_UAR_SZ_OFFSET); 17555a2cc190SJeff Kirsher 17567ffdf726SOr Gerlitz /* set parser VXLAN attributes */ 17577ffdf726SOr Gerlitz if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS) { 17587ffdf726SOr Gerlitz u8 parser_params = 0; 17597ffdf726SOr Gerlitz MLX4_PUT(inbox, parser_params, INIT_HCA_VXLAN_OFFSET); 17607ffdf726SOr Gerlitz } 17617ffdf726SOr Gerlitz 1762f9baff50SJack Morgenstein err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA, 10000, 1763f9baff50SJack Morgenstein MLX4_CMD_NATIVE); 17645a2cc190SJeff Kirsher 17655a2cc190SJeff Kirsher if (err) 17665a2cc190SJeff Kirsher mlx4_err(dev, "INIT_HCA returns %d\n", err); 17675a2cc190SJeff Kirsher 17685a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 17695a2cc190SJeff Kirsher return err; 17705a2cc190SJeff Kirsher } 17715a2cc190SJeff Kirsher 1772ab9c17a0SJack Morgenstein int mlx4_QUERY_HCA(struct mlx4_dev *dev, 1773ab9c17a0SJack Morgenstein struct mlx4_init_hca_param *param) 1774ab9c17a0SJack Morgenstein { 1775ab9c17a0SJack Morgenstein struct mlx4_cmd_mailbox *mailbox; 1776ab9c17a0SJack Morgenstein __be32 *outbox; 17777b8157beSJack Morgenstein u32 dword_field; 1778ab9c17a0SJack Morgenstein int err; 177908ff3235SOr Gerlitz u8 byte_field; 17807d077cd3SMatan Barak static const u8 a0_dmfs_query_hw_steering[] = { 17817d077cd3SMatan Barak [0] = MLX4_STEERING_DMFS_A0_DEFAULT, 17827d077cd3SMatan Barak [1] = MLX4_STEERING_DMFS_A0_DYNAMIC, 17837d077cd3SMatan Barak [2] = MLX4_STEERING_DMFS_A0_STATIC, 17847d077cd3SMatan Barak [3] = MLX4_STEERING_DMFS_A0_DISABLE 17857d077cd3SMatan Barak }; 1786ab9c17a0SJack Morgenstein 1787ab9c17a0SJack Morgenstein #define QUERY_HCA_GLOBAL_CAPS_OFFSET 0x04 1788ddd8a6c1SEugenia Emantayev #define QUERY_HCA_CORE_CLOCK_OFFSET 0x0c 1789ab9c17a0SJack Morgenstein 1790ab9c17a0SJack Morgenstein mailbox = mlx4_alloc_cmd_mailbox(dev); 1791ab9c17a0SJack Morgenstein if (IS_ERR(mailbox)) 1792ab9c17a0SJack Morgenstein return PTR_ERR(mailbox); 1793ab9c17a0SJack Morgenstein outbox = mailbox->buf; 1794ab9c17a0SJack Morgenstein 1795ab9c17a0SJack Morgenstein err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, 1796ab9c17a0SJack Morgenstein MLX4_CMD_QUERY_HCA, 1797ab9c17a0SJack Morgenstein MLX4_CMD_TIME_CLASS_B, 1798ab9c17a0SJack Morgenstein !mlx4_is_slave(dev)); 1799ab9c17a0SJack Morgenstein if (err) 1800ab9c17a0SJack Morgenstein goto out; 1801ab9c17a0SJack Morgenstein 1802ab9c17a0SJack Morgenstein MLX4_GET(param->global_caps, outbox, QUERY_HCA_GLOBAL_CAPS_OFFSET); 1803ddd8a6c1SEugenia Emantayev MLX4_GET(param->hca_core_clock, outbox, QUERY_HCA_CORE_CLOCK_OFFSET); 1804ab9c17a0SJack Morgenstein 1805ab9c17a0SJack Morgenstein /* QPC/EEC/CQC/EQC/RDMARC attributes */ 1806ab9c17a0SJack Morgenstein 1807ab9c17a0SJack Morgenstein MLX4_GET(param->qpc_base, outbox, INIT_HCA_QPC_BASE_OFFSET); 1808ab9c17a0SJack Morgenstein MLX4_GET(param->log_num_qps, outbox, INIT_HCA_LOG_QP_OFFSET); 1809ab9c17a0SJack Morgenstein MLX4_GET(param->srqc_base, outbox, INIT_HCA_SRQC_BASE_OFFSET); 1810ab9c17a0SJack Morgenstein MLX4_GET(param->log_num_srqs, outbox, INIT_HCA_LOG_SRQ_OFFSET); 1811ab9c17a0SJack Morgenstein MLX4_GET(param->cqc_base, outbox, INIT_HCA_CQC_BASE_OFFSET); 1812ab9c17a0SJack Morgenstein MLX4_GET(param->log_num_cqs, outbox, INIT_HCA_LOG_CQ_OFFSET); 1813ab9c17a0SJack Morgenstein MLX4_GET(param->altc_base, outbox, INIT_HCA_ALTC_BASE_OFFSET); 1814ab9c17a0SJack Morgenstein MLX4_GET(param->auxc_base, outbox, INIT_HCA_AUXC_BASE_OFFSET); 1815ab9c17a0SJack Morgenstein MLX4_GET(param->eqc_base, outbox, INIT_HCA_EQC_BASE_OFFSET); 1816ab9c17a0SJack Morgenstein MLX4_GET(param->log_num_eqs, outbox, INIT_HCA_LOG_EQ_OFFSET); 18177ae0e400SMatan Barak MLX4_GET(param->num_sys_eqs, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET); 1818ab9c17a0SJack Morgenstein MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET); 1819ab9c17a0SJack Morgenstein MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET); 1820ab9c17a0SJack Morgenstein 18217b8157beSJack Morgenstein MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET); 18227b8157beSJack Morgenstein if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) { 18237b8157beSJack Morgenstein param->steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; 18247b8157beSJack Morgenstein } else { 18257b8157beSJack Morgenstein MLX4_GET(byte_field, outbox, INIT_HCA_UC_STEERING_OFFSET); 18267b8157beSJack Morgenstein if (byte_field & 0x8) 18277b8157beSJack Morgenstein param->steering_mode = MLX4_STEERING_MODE_B0; 18287b8157beSJack Morgenstein else 18297b8157beSJack Morgenstein param->steering_mode = MLX4_STEERING_MODE_A0; 18307b8157beSJack Morgenstein } 18310ff1fb65SHadar Hen Zion /* steering attributes */ 18327b8157beSJack Morgenstein if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { 18330ff1fb65SHadar Hen Zion MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET); 18340ff1fb65SHadar Hen Zion MLX4_GET(param->log_mc_entry_sz, outbox, 18350ff1fb65SHadar Hen Zion INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); 18360ff1fb65SHadar Hen Zion MLX4_GET(param->log_mc_table_sz, outbox, 18370ff1fb65SHadar Hen Zion INIT_HCA_FS_LOG_TABLE_SZ_OFFSET); 18387d077cd3SMatan Barak MLX4_GET(byte_field, outbox, 18397d077cd3SMatan Barak INIT_HCA_FS_A0_OFFSET); 18407d077cd3SMatan Barak param->dmfs_high_steer_mode = 18417d077cd3SMatan Barak a0_dmfs_query_hw_steering[(byte_field >> 6) & 3]; 18420ff1fb65SHadar Hen Zion } else { 1843ab9c17a0SJack Morgenstein MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET); 1844ab9c17a0SJack Morgenstein MLX4_GET(param->log_mc_entry_sz, outbox, 1845ab9c17a0SJack Morgenstein INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); 1846ab9c17a0SJack Morgenstein MLX4_GET(param->log_mc_hash_sz, outbox, 1847ab9c17a0SJack Morgenstein INIT_HCA_LOG_MC_HASH_SZ_OFFSET); 1848ab9c17a0SJack Morgenstein MLX4_GET(param->log_mc_table_sz, outbox, 1849ab9c17a0SJack Morgenstein INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); 18500ff1fb65SHadar Hen Zion } 1851ab9c17a0SJack Morgenstein 185208ff3235SOr Gerlitz /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */ 185308ff3235SOr Gerlitz MLX4_GET(byte_field, outbox, INIT_HCA_EQE_CQE_OFFSETS); 185408ff3235SOr Gerlitz if (byte_field & 0x20) /* 64-bytes eqe enabled */ 185508ff3235SOr Gerlitz param->dev_cap_enabled |= MLX4_DEV_CAP_64B_EQE_ENABLED; 185608ff3235SOr Gerlitz if (byte_field & 0x40) /* 64-bytes cqe enabled */ 185708ff3235SOr Gerlitz param->dev_cap_enabled |= MLX4_DEV_CAP_64B_CQE_ENABLED; 185808ff3235SOr Gerlitz 185977507aa2SIdo Shamay /* CX3 is capable of extending CQEs\EQEs to strides larger than 64B */ 186077507aa2SIdo Shamay MLX4_GET(byte_field, outbox, INIT_HCA_EQE_CQE_STRIDE_OFFSET); 186177507aa2SIdo Shamay if (byte_field) { 1862c3f2511fSIdo Shamay param->dev_cap_enabled |= MLX4_DEV_CAP_EQE_STRIDE_ENABLED; 1863c3f2511fSIdo Shamay param->dev_cap_enabled |= MLX4_DEV_CAP_CQE_STRIDE_ENABLED; 186477507aa2SIdo Shamay param->cqe_size = 1 << ((byte_field & 186577507aa2SIdo Shamay MLX4_CQE_SIZE_MASK_STRIDE) + 5); 186677507aa2SIdo Shamay param->eqe_size = 1 << (((byte_field & 186777507aa2SIdo Shamay MLX4_EQE_SIZE_MASK_STRIDE) >> 4) + 5); 186877507aa2SIdo Shamay } 186977507aa2SIdo Shamay 1870ab9c17a0SJack Morgenstein /* TPT attributes */ 1871ab9c17a0SJack Morgenstein 1872ab9c17a0SJack Morgenstein MLX4_GET(param->dmpt_base, outbox, INIT_HCA_DMPT_BASE_OFFSET); 1873e448834eSShani Michaeli MLX4_GET(param->mw_enabled, outbox, INIT_HCA_TPT_MW_OFFSET); 1874ab9c17a0SJack Morgenstein MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET); 1875ab9c17a0SJack Morgenstein MLX4_GET(param->mtt_base, outbox, INIT_HCA_MTT_BASE_OFFSET); 1876ab9c17a0SJack Morgenstein MLX4_GET(param->cmpt_base, outbox, INIT_HCA_CMPT_BASE_OFFSET); 1877ab9c17a0SJack Morgenstein 1878ab9c17a0SJack Morgenstein /* UAR attributes */ 1879ab9c17a0SJack Morgenstein 1880ab9c17a0SJack Morgenstein MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET); 1881ab9c17a0SJack Morgenstein MLX4_GET(param->log_uar_sz, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET); 1882ab9c17a0SJack Morgenstein 1883ab9c17a0SJack Morgenstein out: 1884ab9c17a0SJack Morgenstein mlx4_free_cmd_mailbox(dev, mailbox); 1885ab9c17a0SJack Morgenstein 1886ab9c17a0SJack Morgenstein return err; 1887ab9c17a0SJack Morgenstein } 1888ab9c17a0SJack Morgenstein 1889980e9001SJack Morgenstein /* for IB-type ports only in SRIOV mode. Checks that both proxy QP0 1890980e9001SJack Morgenstein * and real QP0 are active, so that the paravirtualized QP0 is ready 1891980e9001SJack Morgenstein * to operate */ 1892980e9001SJack Morgenstein static int check_qp0_state(struct mlx4_dev *dev, int function, int port) 1893980e9001SJack Morgenstein { 1894980e9001SJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 1895980e9001SJack Morgenstein /* irrelevant if not infiniband */ 1896980e9001SJack Morgenstein if (priv->mfunc.master.qp0_state[port].proxy_qp0_active && 1897980e9001SJack Morgenstein priv->mfunc.master.qp0_state[port].qp0_active) 1898980e9001SJack Morgenstein return 1; 1899980e9001SJack Morgenstein return 0; 1900980e9001SJack Morgenstein } 1901980e9001SJack Morgenstein 19025cc914f1SMarcel Apfelbaum int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave, 19035cc914f1SMarcel Apfelbaum struct mlx4_vhcr *vhcr, 19045cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *inbox, 19055cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *outbox, 19065cc914f1SMarcel Apfelbaum struct mlx4_cmd_info *cmd) 19075cc914f1SMarcel Apfelbaum { 19085cc914f1SMarcel Apfelbaum struct mlx4_priv *priv = mlx4_priv(dev); 1909449fc488SMatan Barak int port = mlx4_slave_convert_port(dev, slave, vhcr->in_modifier); 19105cc914f1SMarcel Apfelbaum int err; 19115cc914f1SMarcel Apfelbaum 1912449fc488SMatan Barak if (port < 0) 1913449fc488SMatan Barak return -EINVAL; 1914449fc488SMatan Barak 19155cc914f1SMarcel Apfelbaum if (priv->mfunc.master.slave_state[slave].init_port_mask & (1 << port)) 19165cc914f1SMarcel Apfelbaum return 0; 19175cc914f1SMarcel Apfelbaum 1918980e9001SJack Morgenstein if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB) { 19195cc914f1SMarcel Apfelbaum /* Enable port only if it was previously disabled */ 19205cc914f1SMarcel Apfelbaum if (!priv->mfunc.master.init_port_ref[port]) { 19215cc914f1SMarcel Apfelbaum err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT, 19225cc914f1SMarcel Apfelbaum MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 19235cc914f1SMarcel Apfelbaum if (err) 19245cc914f1SMarcel Apfelbaum return err; 19255cc914f1SMarcel Apfelbaum } 19268bac9edeSJack Morgenstein priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port); 1927980e9001SJack Morgenstein } else { 1928980e9001SJack Morgenstein if (slave == mlx4_master_func_num(dev)) { 1929980e9001SJack Morgenstein if (check_qp0_state(dev, slave, port) && 1930980e9001SJack Morgenstein !priv->mfunc.master.qp0_state[port].port_active) { 1931980e9001SJack Morgenstein err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT, 1932980e9001SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 1933980e9001SJack Morgenstein if (err) 1934980e9001SJack Morgenstein return err; 1935980e9001SJack Morgenstein priv->mfunc.master.qp0_state[port].port_active = 1; 1936980e9001SJack Morgenstein priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port); 1937980e9001SJack Morgenstein } 1938980e9001SJack Morgenstein } else 1939980e9001SJack Morgenstein priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port); 1940980e9001SJack Morgenstein } 19415cc914f1SMarcel Apfelbaum ++priv->mfunc.master.init_port_ref[port]; 19425cc914f1SMarcel Apfelbaum return 0; 19435cc914f1SMarcel Apfelbaum } 19445cc914f1SMarcel Apfelbaum 19455a2cc190SJeff Kirsher int mlx4_INIT_PORT(struct mlx4_dev *dev, int port) 19465a2cc190SJeff Kirsher { 19475a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 19485a2cc190SJeff Kirsher u32 *inbox; 19495a2cc190SJeff Kirsher int err; 19505a2cc190SJeff Kirsher u32 flags; 19515a2cc190SJeff Kirsher u16 field; 19525a2cc190SJeff Kirsher 19535a2cc190SJeff Kirsher if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 19545a2cc190SJeff Kirsher #define INIT_PORT_IN_SIZE 256 19555a2cc190SJeff Kirsher #define INIT_PORT_FLAGS_OFFSET 0x00 19565a2cc190SJeff Kirsher #define INIT_PORT_FLAG_SIG (1 << 18) 19575a2cc190SJeff Kirsher #define INIT_PORT_FLAG_NG (1 << 17) 19585a2cc190SJeff Kirsher #define INIT_PORT_FLAG_G0 (1 << 16) 19595a2cc190SJeff Kirsher #define INIT_PORT_VL_SHIFT 4 19605a2cc190SJeff Kirsher #define INIT_PORT_PORT_WIDTH_SHIFT 8 19615a2cc190SJeff Kirsher #define INIT_PORT_MTU_OFFSET 0x04 19625a2cc190SJeff Kirsher #define INIT_PORT_MAX_GID_OFFSET 0x06 19635a2cc190SJeff Kirsher #define INIT_PORT_MAX_PKEY_OFFSET 0x0a 19645a2cc190SJeff Kirsher #define INIT_PORT_GUID0_OFFSET 0x10 19655a2cc190SJeff Kirsher #define INIT_PORT_NODE_GUID_OFFSET 0x18 19665a2cc190SJeff Kirsher #define INIT_PORT_SI_GUID_OFFSET 0x20 19675a2cc190SJeff Kirsher 19685a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 19695a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 19705a2cc190SJeff Kirsher return PTR_ERR(mailbox); 19715a2cc190SJeff Kirsher inbox = mailbox->buf; 19725a2cc190SJeff Kirsher 19735a2cc190SJeff Kirsher flags = 0; 19745a2cc190SJeff Kirsher flags |= (dev->caps.vl_cap[port] & 0xf) << INIT_PORT_VL_SHIFT; 19755a2cc190SJeff Kirsher flags |= (dev->caps.port_width_cap[port] & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT; 19765a2cc190SJeff Kirsher MLX4_PUT(inbox, flags, INIT_PORT_FLAGS_OFFSET); 19775a2cc190SJeff Kirsher 19785a2cc190SJeff Kirsher field = 128 << dev->caps.ib_mtu_cap[port]; 19795a2cc190SJeff Kirsher MLX4_PUT(inbox, field, INIT_PORT_MTU_OFFSET); 19805a2cc190SJeff Kirsher field = dev->caps.gid_table_len[port]; 19815a2cc190SJeff Kirsher MLX4_PUT(inbox, field, INIT_PORT_MAX_GID_OFFSET); 19825a2cc190SJeff Kirsher field = dev->caps.pkey_table_len[port]; 19835a2cc190SJeff Kirsher MLX4_PUT(inbox, field, INIT_PORT_MAX_PKEY_OFFSET); 19845a2cc190SJeff Kirsher 19855a2cc190SJeff Kirsher err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT, 1986f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 19875a2cc190SJeff Kirsher 19885a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 19895a2cc190SJeff Kirsher } else 19905a2cc190SJeff Kirsher err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT, 1991f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 19925a2cc190SJeff Kirsher 19935a2cc190SJeff Kirsher return err; 19945a2cc190SJeff Kirsher } 19955a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_INIT_PORT); 19965a2cc190SJeff Kirsher 19975cc914f1SMarcel Apfelbaum int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave, 19985cc914f1SMarcel Apfelbaum struct mlx4_vhcr *vhcr, 19995cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *inbox, 20005cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *outbox, 20015cc914f1SMarcel Apfelbaum struct mlx4_cmd_info *cmd) 20025cc914f1SMarcel Apfelbaum { 20035cc914f1SMarcel Apfelbaum struct mlx4_priv *priv = mlx4_priv(dev); 2004449fc488SMatan Barak int port = mlx4_slave_convert_port(dev, slave, vhcr->in_modifier); 20055cc914f1SMarcel Apfelbaum int err; 20065cc914f1SMarcel Apfelbaum 2007449fc488SMatan Barak if (port < 0) 2008449fc488SMatan Barak return -EINVAL; 2009449fc488SMatan Barak 20105cc914f1SMarcel Apfelbaum if (!(priv->mfunc.master.slave_state[slave].init_port_mask & 20115cc914f1SMarcel Apfelbaum (1 << port))) 20125cc914f1SMarcel Apfelbaum return 0; 20135cc914f1SMarcel Apfelbaum 2014980e9001SJack Morgenstein if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB) { 20155cc914f1SMarcel Apfelbaum if (priv->mfunc.master.init_port_ref[port] == 1) { 2016980e9001SJack Morgenstein err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 2017980e9001SJack Morgenstein 1000, MLX4_CMD_NATIVE); 20185cc914f1SMarcel Apfelbaum if (err) 20195cc914f1SMarcel Apfelbaum return err; 20205cc914f1SMarcel Apfelbaum } 20215cc914f1SMarcel Apfelbaum priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port); 2022980e9001SJack Morgenstein } else { 2023980e9001SJack Morgenstein /* infiniband port */ 2024980e9001SJack Morgenstein if (slave == mlx4_master_func_num(dev)) { 2025980e9001SJack Morgenstein if (!priv->mfunc.master.qp0_state[port].qp0_active && 2026980e9001SJack Morgenstein priv->mfunc.master.qp0_state[port].port_active) { 2027980e9001SJack Morgenstein err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 2028980e9001SJack Morgenstein 1000, MLX4_CMD_NATIVE); 2029980e9001SJack Morgenstein if (err) 2030980e9001SJack Morgenstein return err; 2031980e9001SJack Morgenstein priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port); 2032980e9001SJack Morgenstein priv->mfunc.master.qp0_state[port].port_active = 0; 2033980e9001SJack Morgenstein } 2034980e9001SJack Morgenstein } else 2035980e9001SJack Morgenstein priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port); 2036980e9001SJack Morgenstein } 20375cc914f1SMarcel Apfelbaum --priv->mfunc.master.init_port_ref[port]; 20385cc914f1SMarcel Apfelbaum return 0; 20395cc914f1SMarcel Apfelbaum } 20405cc914f1SMarcel Apfelbaum 20415a2cc190SJeff Kirsher int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port) 20425a2cc190SJeff Kirsher { 2043f9baff50SJack Morgenstein return mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000, 2044f9baff50SJack Morgenstein MLX4_CMD_WRAPPED); 20455a2cc190SJeff Kirsher } 20465a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_CLOSE_PORT); 20475a2cc190SJeff Kirsher 20485a2cc190SJeff Kirsher int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic) 20495a2cc190SJeff Kirsher { 2050f9baff50SJack Morgenstein return mlx4_cmd(dev, 0, 0, panic, MLX4_CMD_CLOSE_HCA, 1000, 2051f9baff50SJack Morgenstein MLX4_CMD_NATIVE); 20525a2cc190SJeff Kirsher } 20535a2cc190SJeff Kirsher 2054d18f141aSOr Gerlitz struct mlx4_config_dev { 2055d18f141aSOr Gerlitz __be32 update_flags; 2056d475c95bSMatan Barak __be32 rsvd1[3]; 2057d18f141aSOr Gerlitz __be16 vxlan_udp_dport; 2058d18f141aSOr Gerlitz __be16 rsvd2; 2059d475c95bSMatan Barak __be32 rsvd3[27]; 2060d475c95bSMatan Barak __be16 rsvd4; 2061d475c95bSMatan Barak u8 rsvd5; 2062d475c95bSMatan Barak u8 rx_checksum_val; 2063d18f141aSOr Gerlitz }; 2064d18f141aSOr Gerlitz 2065d18f141aSOr Gerlitz #define MLX4_VXLAN_UDP_DPORT (1 << 0) 2066d18f141aSOr Gerlitz 2067d475c95bSMatan Barak static int mlx4_CONFIG_DEV_set(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev) 2068d18f141aSOr Gerlitz { 2069d18f141aSOr Gerlitz int err; 2070d18f141aSOr Gerlitz struct mlx4_cmd_mailbox *mailbox; 2071d18f141aSOr Gerlitz 2072d18f141aSOr Gerlitz mailbox = mlx4_alloc_cmd_mailbox(dev); 2073d18f141aSOr Gerlitz if (IS_ERR(mailbox)) 2074d18f141aSOr Gerlitz return PTR_ERR(mailbox); 2075d18f141aSOr Gerlitz 2076d18f141aSOr Gerlitz memcpy(mailbox->buf, config_dev, sizeof(*config_dev)); 2077d18f141aSOr Gerlitz 2078d18f141aSOr Gerlitz err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_CONFIG_DEV, 2079d18f141aSOr Gerlitz MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 2080d18f141aSOr Gerlitz 2081d18f141aSOr Gerlitz mlx4_free_cmd_mailbox(dev, mailbox); 2082d18f141aSOr Gerlitz return err; 2083d18f141aSOr Gerlitz } 2084d18f141aSOr Gerlitz 2085d475c95bSMatan Barak static int mlx4_CONFIG_DEV_get(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev) 2086d475c95bSMatan Barak { 2087d475c95bSMatan Barak int err; 2088d475c95bSMatan Barak struct mlx4_cmd_mailbox *mailbox; 2089d475c95bSMatan Barak 2090d475c95bSMatan Barak mailbox = mlx4_alloc_cmd_mailbox(dev); 2091d475c95bSMatan Barak if (IS_ERR(mailbox)) 2092d475c95bSMatan Barak return PTR_ERR(mailbox); 2093d475c95bSMatan Barak 2094d475c95bSMatan Barak err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 1, MLX4_CMD_CONFIG_DEV, 2095d475c95bSMatan Barak MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 2096d475c95bSMatan Barak 2097d475c95bSMatan Barak if (!err) 2098d475c95bSMatan Barak memcpy(config_dev, mailbox->buf, sizeof(*config_dev)); 2099d475c95bSMatan Barak 2100d475c95bSMatan Barak mlx4_free_cmd_mailbox(dev, mailbox); 2101d475c95bSMatan Barak return err; 2102d475c95bSMatan Barak } 2103d475c95bSMatan Barak 2104d475c95bSMatan Barak /* Conversion between the HW values and the actual functionality. 2105d475c95bSMatan Barak * The value represented by the array index, 2106d475c95bSMatan Barak * and the functionality determined by the flags. 2107d475c95bSMatan Barak */ 2108d475c95bSMatan Barak static const u8 config_dev_csum_flags[] = { 2109d475c95bSMatan Barak [0] = 0, 2110d475c95bSMatan Barak [1] = MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP, 2111d475c95bSMatan Barak [2] = MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP | 2112d475c95bSMatan Barak MLX4_RX_CSUM_MODE_L4, 2113d475c95bSMatan Barak [3] = MLX4_RX_CSUM_MODE_L4 | 2114d475c95bSMatan Barak MLX4_RX_CSUM_MODE_IP_OK_IP_NON_TCP_UDP | 2115d475c95bSMatan Barak MLX4_RX_CSUM_MODE_MULTI_VLAN 2116d475c95bSMatan Barak }; 2117d475c95bSMatan Barak 2118d475c95bSMatan Barak int mlx4_config_dev_retrieval(struct mlx4_dev *dev, 2119d475c95bSMatan Barak struct mlx4_config_dev_params *params) 2120d475c95bSMatan Barak { 2121d475c95bSMatan Barak struct mlx4_config_dev config_dev; 2122d475c95bSMatan Barak int err; 2123d475c95bSMatan Barak u8 csum_mask; 2124d475c95bSMatan Barak 2125d475c95bSMatan Barak #define CONFIG_DEV_RX_CSUM_MODE_MASK 0x7 2126d475c95bSMatan Barak #define CONFIG_DEV_RX_CSUM_MODE_PORT1_BIT_OFFSET 0 2127d475c95bSMatan Barak #define CONFIG_DEV_RX_CSUM_MODE_PORT2_BIT_OFFSET 4 2128d475c95bSMatan Barak 2129d475c95bSMatan Barak if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_CONFIG_DEV)) 2130d475c95bSMatan Barak return -ENOTSUPP; 2131d475c95bSMatan Barak 2132d475c95bSMatan Barak err = mlx4_CONFIG_DEV_get(dev, &config_dev); 2133d475c95bSMatan Barak if (err) 2134d475c95bSMatan Barak return err; 2135d475c95bSMatan Barak 2136d475c95bSMatan Barak csum_mask = (config_dev.rx_checksum_val >> CONFIG_DEV_RX_CSUM_MODE_PORT1_BIT_OFFSET) & 2137d475c95bSMatan Barak CONFIG_DEV_RX_CSUM_MODE_MASK; 2138d475c95bSMatan Barak 2139d475c95bSMatan Barak if (csum_mask >= sizeof(config_dev_csum_flags)/sizeof(config_dev_csum_flags[0])) 2140d475c95bSMatan Barak return -EINVAL; 2141d475c95bSMatan Barak params->rx_csum_flags_port_1 = config_dev_csum_flags[csum_mask]; 2142d475c95bSMatan Barak 2143d475c95bSMatan Barak csum_mask = (config_dev.rx_checksum_val >> CONFIG_DEV_RX_CSUM_MODE_PORT2_BIT_OFFSET) & 2144d475c95bSMatan Barak CONFIG_DEV_RX_CSUM_MODE_MASK; 2145d475c95bSMatan Barak 2146d475c95bSMatan Barak if (csum_mask >= sizeof(config_dev_csum_flags)/sizeof(config_dev_csum_flags[0])) 2147d475c95bSMatan Barak return -EINVAL; 2148d475c95bSMatan Barak params->rx_csum_flags_port_2 = config_dev_csum_flags[csum_mask]; 2149d475c95bSMatan Barak 2150d475c95bSMatan Barak params->vxlan_udp_dport = be16_to_cpu(config_dev.vxlan_udp_dport); 2151d475c95bSMatan Barak 2152d475c95bSMatan Barak return 0; 2153d475c95bSMatan Barak } 2154d475c95bSMatan Barak EXPORT_SYMBOL_GPL(mlx4_config_dev_retrieval); 2155d475c95bSMatan Barak 2156d18f141aSOr Gerlitz int mlx4_config_vxlan_port(struct mlx4_dev *dev, __be16 udp_port) 2157d18f141aSOr Gerlitz { 2158d18f141aSOr Gerlitz struct mlx4_config_dev config_dev; 2159d18f141aSOr Gerlitz 2160d18f141aSOr Gerlitz memset(&config_dev, 0, sizeof(config_dev)); 2161d18f141aSOr Gerlitz config_dev.update_flags = cpu_to_be32(MLX4_VXLAN_UDP_DPORT); 2162d18f141aSOr Gerlitz config_dev.vxlan_udp_dport = udp_port; 2163d18f141aSOr Gerlitz 2164d475c95bSMatan Barak return mlx4_CONFIG_DEV_set(dev, &config_dev); 2165d18f141aSOr Gerlitz } 2166d18f141aSOr Gerlitz EXPORT_SYMBOL_GPL(mlx4_config_vxlan_port); 2167d18f141aSOr Gerlitz 2168d18f141aSOr Gerlitz 21695a2cc190SJeff Kirsher int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages) 21705a2cc190SJeff Kirsher { 21715a2cc190SJeff Kirsher int ret = mlx4_cmd_imm(dev, icm_size, aux_pages, 0, 0, 21725a2cc190SJeff Kirsher MLX4_CMD_SET_ICM_SIZE, 2173f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 21745a2cc190SJeff Kirsher if (ret) 21755a2cc190SJeff Kirsher return ret; 21765a2cc190SJeff Kirsher 21775a2cc190SJeff Kirsher /* 21785a2cc190SJeff Kirsher * Round up number of system pages needed in case 21795a2cc190SJeff Kirsher * MLX4_ICM_PAGE_SIZE < PAGE_SIZE. 21805a2cc190SJeff Kirsher */ 21815a2cc190SJeff Kirsher *aux_pages = ALIGN(*aux_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >> 21825a2cc190SJeff Kirsher (PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT); 21835a2cc190SJeff Kirsher 21845a2cc190SJeff Kirsher return 0; 21855a2cc190SJeff Kirsher } 21865a2cc190SJeff Kirsher 21875a2cc190SJeff Kirsher int mlx4_NOP(struct mlx4_dev *dev) 21885a2cc190SJeff Kirsher { 21895a2cc190SJeff Kirsher /* Input modifier of 0x1f means "finish as soon as possible." */ 2190f9baff50SJack Morgenstein return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100, MLX4_CMD_NATIVE); 21915a2cc190SJeff Kirsher } 21925a2cc190SJeff Kirsher 21938e1a28e8SHadar Hen Zion int mlx4_get_phys_port_id(struct mlx4_dev *dev) 21948e1a28e8SHadar Hen Zion { 21958e1a28e8SHadar Hen Zion u8 port; 21968e1a28e8SHadar Hen Zion u32 *outbox; 21978e1a28e8SHadar Hen Zion struct mlx4_cmd_mailbox *mailbox; 21988e1a28e8SHadar Hen Zion u32 in_mod; 21998e1a28e8SHadar Hen Zion u32 guid_hi, guid_lo; 22008e1a28e8SHadar Hen Zion int err, ret = 0; 22018e1a28e8SHadar Hen Zion #define MOD_STAT_CFG_PORT_OFFSET 8 22028e1a28e8SHadar Hen Zion #define MOD_STAT_CFG_GUID_H 0X14 22038e1a28e8SHadar Hen Zion #define MOD_STAT_CFG_GUID_L 0X1c 22048e1a28e8SHadar Hen Zion 22058e1a28e8SHadar Hen Zion mailbox = mlx4_alloc_cmd_mailbox(dev); 22068e1a28e8SHadar Hen Zion if (IS_ERR(mailbox)) 22078e1a28e8SHadar Hen Zion return PTR_ERR(mailbox); 22088e1a28e8SHadar Hen Zion outbox = mailbox->buf; 22098e1a28e8SHadar Hen Zion 22108e1a28e8SHadar Hen Zion for (port = 1; port <= dev->caps.num_ports; port++) { 22118e1a28e8SHadar Hen Zion in_mod = port << MOD_STAT_CFG_PORT_OFFSET; 22128e1a28e8SHadar Hen Zion err = mlx4_cmd_box(dev, 0, mailbox->dma, in_mod, 0x2, 22138e1a28e8SHadar Hen Zion MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A, 22148e1a28e8SHadar Hen Zion MLX4_CMD_NATIVE); 22158e1a28e8SHadar Hen Zion if (err) { 22168e1a28e8SHadar Hen Zion mlx4_err(dev, "Fail to get port %d uplink guid\n", 22178e1a28e8SHadar Hen Zion port); 22188e1a28e8SHadar Hen Zion ret = err; 22198e1a28e8SHadar Hen Zion } else { 22208e1a28e8SHadar Hen Zion MLX4_GET(guid_hi, outbox, MOD_STAT_CFG_GUID_H); 22218e1a28e8SHadar Hen Zion MLX4_GET(guid_lo, outbox, MOD_STAT_CFG_GUID_L); 22228e1a28e8SHadar Hen Zion dev->caps.phys_port_id[port] = (u64)guid_lo | 22238e1a28e8SHadar Hen Zion (u64)guid_hi << 32; 22248e1a28e8SHadar Hen Zion } 22258e1a28e8SHadar Hen Zion } 22268e1a28e8SHadar Hen Zion mlx4_free_cmd_mailbox(dev, mailbox); 22278e1a28e8SHadar Hen Zion return ret; 22288e1a28e8SHadar Hen Zion } 22298e1a28e8SHadar Hen Zion 22305a2cc190SJeff Kirsher #define MLX4_WOL_SETUP_MODE (5 << 28) 22315a2cc190SJeff Kirsher int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port) 22325a2cc190SJeff Kirsher { 22335a2cc190SJeff Kirsher u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8; 22345a2cc190SJeff Kirsher 22355a2cc190SJeff Kirsher return mlx4_cmd_imm(dev, 0, config, in_mod, 0x3, 2236f9baff50SJack Morgenstein MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A, 2237f9baff50SJack Morgenstein MLX4_CMD_NATIVE); 22385a2cc190SJeff Kirsher } 22395a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_wol_read); 22405a2cc190SJeff Kirsher 22415a2cc190SJeff Kirsher int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port) 22425a2cc190SJeff Kirsher { 22435a2cc190SJeff Kirsher u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8; 22445a2cc190SJeff Kirsher 22455a2cc190SJeff Kirsher return mlx4_cmd(dev, config, in_mod, 0x1, MLX4_CMD_MOD_STAT_CFG, 2246f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 22475a2cc190SJeff Kirsher } 22485a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_wol_write); 2249fe6f700dSYevgeny Petrilin 2250fe6f700dSYevgeny Petrilin enum { 2251fe6f700dSYevgeny Petrilin ADD_TO_MCG = 0x26, 2252fe6f700dSYevgeny Petrilin }; 2253fe6f700dSYevgeny Petrilin 2254fe6f700dSYevgeny Petrilin 2255fe6f700dSYevgeny Petrilin void mlx4_opreq_action(struct work_struct *work) 2256fe6f700dSYevgeny Petrilin { 2257fe6f700dSYevgeny Petrilin struct mlx4_priv *priv = container_of(work, struct mlx4_priv, 2258fe6f700dSYevgeny Petrilin opreq_task); 2259fe6f700dSYevgeny Petrilin struct mlx4_dev *dev = &priv->dev; 2260fe6f700dSYevgeny Petrilin int num_tasks = atomic_read(&priv->opreq_count); 2261fe6f700dSYevgeny Petrilin struct mlx4_cmd_mailbox *mailbox; 2262fe6f700dSYevgeny Petrilin struct mlx4_mgm *mgm; 2263fe6f700dSYevgeny Petrilin u32 *outbox; 2264fe6f700dSYevgeny Petrilin u32 modifier; 2265fe6f700dSYevgeny Petrilin u16 token; 2266fe6f700dSYevgeny Petrilin u16 type; 2267fe6f700dSYevgeny Petrilin int err; 2268fe6f700dSYevgeny Petrilin u32 num_qps; 2269fe6f700dSYevgeny Petrilin struct mlx4_qp qp; 2270fe6f700dSYevgeny Petrilin int i; 2271fe6f700dSYevgeny Petrilin u8 rem_mcg; 2272fe6f700dSYevgeny Petrilin u8 prot; 2273fe6f700dSYevgeny Petrilin 2274fe6f700dSYevgeny Petrilin #define GET_OP_REQ_MODIFIER_OFFSET 0x08 2275fe6f700dSYevgeny Petrilin #define GET_OP_REQ_TOKEN_OFFSET 0x14 2276fe6f700dSYevgeny Petrilin #define GET_OP_REQ_TYPE_OFFSET 0x1a 2277fe6f700dSYevgeny Petrilin #define GET_OP_REQ_DATA_OFFSET 0x20 2278fe6f700dSYevgeny Petrilin 2279fe6f700dSYevgeny Petrilin mailbox = mlx4_alloc_cmd_mailbox(dev); 2280fe6f700dSYevgeny Petrilin if (IS_ERR(mailbox)) { 2281fe6f700dSYevgeny Petrilin mlx4_err(dev, "Failed to allocate mailbox for GET_OP_REQ\n"); 2282fe6f700dSYevgeny Petrilin return; 2283fe6f700dSYevgeny Petrilin } 2284fe6f700dSYevgeny Petrilin outbox = mailbox->buf; 2285fe6f700dSYevgeny Petrilin 2286fe6f700dSYevgeny Petrilin while (num_tasks) { 2287fe6f700dSYevgeny Petrilin err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, 2288fe6f700dSYevgeny Petrilin MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A, 2289fe6f700dSYevgeny Petrilin MLX4_CMD_NATIVE); 2290fe6f700dSYevgeny Petrilin if (err) { 22916d3be300SMasanari Iida mlx4_err(dev, "Failed to retrieve required operation: %d\n", 2292fe6f700dSYevgeny Petrilin err); 2293fe6f700dSYevgeny Petrilin return; 2294fe6f700dSYevgeny Petrilin } 2295fe6f700dSYevgeny Petrilin MLX4_GET(modifier, outbox, GET_OP_REQ_MODIFIER_OFFSET); 2296fe6f700dSYevgeny Petrilin MLX4_GET(token, outbox, GET_OP_REQ_TOKEN_OFFSET); 2297fe6f700dSYevgeny Petrilin MLX4_GET(type, outbox, GET_OP_REQ_TYPE_OFFSET); 2298fe6f700dSYevgeny Petrilin type &= 0xfff; 2299fe6f700dSYevgeny Petrilin 2300fe6f700dSYevgeny Petrilin switch (type) { 2301fe6f700dSYevgeny Petrilin case ADD_TO_MCG: 2302fe6f700dSYevgeny Petrilin if (dev->caps.steering_mode == 2303fe6f700dSYevgeny Petrilin MLX4_STEERING_MODE_DEVICE_MANAGED) { 2304fe6f700dSYevgeny Petrilin mlx4_warn(dev, "ADD MCG operation is not supported in DEVICE_MANAGED steering mode\n"); 2305fe6f700dSYevgeny Petrilin err = EPERM; 2306fe6f700dSYevgeny Petrilin break; 2307fe6f700dSYevgeny Petrilin } 2308fe6f700dSYevgeny Petrilin mgm = (struct mlx4_mgm *)((u8 *)(outbox) + 2309fe6f700dSYevgeny Petrilin GET_OP_REQ_DATA_OFFSET); 2310fe6f700dSYevgeny Petrilin num_qps = be32_to_cpu(mgm->members_count) & 2311fe6f700dSYevgeny Petrilin MGM_QPN_MASK; 2312fe6f700dSYevgeny Petrilin rem_mcg = ((u8 *)(&mgm->members_count))[0] & 1; 2313fe6f700dSYevgeny Petrilin prot = ((u8 *)(&mgm->members_count))[0] >> 6; 2314fe6f700dSYevgeny Petrilin 2315fe6f700dSYevgeny Petrilin for (i = 0; i < num_qps; i++) { 2316fe6f700dSYevgeny Petrilin qp.qpn = be32_to_cpu(mgm->qp[i]); 2317fe6f700dSYevgeny Petrilin if (rem_mcg) 2318fe6f700dSYevgeny Petrilin err = mlx4_multicast_detach(dev, &qp, 2319fe6f700dSYevgeny Petrilin mgm->gid, 2320fe6f700dSYevgeny Petrilin prot, 0); 2321fe6f700dSYevgeny Petrilin else 2322fe6f700dSYevgeny Petrilin err = mlx4_multicast_attach(dev, &qp, 2323fe6f700dSYevgeny Petrilin mgm->gid, 2324fe6f700dSYevgeny Petrilin mgm->gid[5] 2325fe6f700dSYevgeny Petrilin , 0, prot, 2326fe6f700dSYevgeny Petrilin NULL); 2327fe6f700dSYevgeny Petrilin if (err) 2328fe6f700dSYevgeny Petrilin break; 2329fe6f700dSYevgeny Petrilin } 2330fe6f700dSYevgeny Petrilin break; 2331fe6f700dSYevgeny Petrilin default: 2332fe6f700dSYevgeny Petrilin mlx4_warn(dev, "Bad type for required operation\n"); 2333fe6f700dSYevgeny Petrilin err = EINVAL; 2334fe6f700dSYevgeny Petrilin break; 2335fe6f700dSYevgeny Petrilin } 233628d222bbSEyal Perry err = mlx4_cmd(dev, 0, ((u32) err | 233728d222bbSEyal Perry (__force u32)cpu_to_be32(token) << 16), 2338fe6f700dSYevgeny Petrilin 1, MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A, 2339fe6f700dSYevgeny Petrilin MLX4_CMD_NATIVE); 2340fe6f700dSYevgeny Petrilin if (err) { 2341fe6f700dSYevgeny Petrilin mlx4_err(dev, "Failed to acknowledge required request: %d\n", 2342fe6f700dSYevgeny Petrilin err); 2343fe6f700dSYevgeny Petrilin goto out; 2344fe6f700dSYevgeny Petrilin } 2345fe6f700dSYevgeny Petrilin memset(outbox, 0, 0xffc); 2346fe6f700dSYevgeny Petrilin num_tasks = atomic_dec_return(&priv->opreq_count); 2347fe6f700dSYevgeny Petrilin } 2348fe6f700dSYevgeny Petrilin 2349fe6f700dSYevgeny Petrilin out: 2350fe6f700dSYevgeny Petrilin mlx4_free_cmd_mailbox(dev, mailbox); 2351fe6f700dSYevgeny Petrilin } 2352114840c3SJack Morgenstein 2353114840c3SJack Morgenstein static int mlx4_check_smp_firewall_active(struct mlx4_dev *dev, 2354114840c3SJack Morgenstein struct mlx4_cmd_mailbox *mailbox) 2355114840c3SJack Morgenstein { 2356114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET 0x10 2357114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET 0x20 2358114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET 0x40 2359114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET 0x70 2360114840c3SJack Morgenstein 2361114840c3SJack Morgenstein u32 set_attr_mask, getresp_attr_mask; 2362114840c3SJack Morgenstein u32 trap_attr_mask, traprepress_attr_mask; 2363114840c3SJack Morgenstein 2364114840c3SJack Morgenstein MLX4_GET(set_attr_mask, mailbox->buf, 2365114840c3SJack Morgenstein MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET); 2366114840c3SJack Morgenstein mlx4_dbg(dev, "SMP firewall set_attribute_mask = 0x%x\n", 2367114840c3SJack Morgenstein set_attr_mask); 2368114840c3SJack Morgenstein 2369114840c3SJack Morgenstein MLX4_GET(getresp_attr_mask, mailbox->buf, 2370114840c3SJack Morgenstein MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET); 2371114840c3SJack Morgenstein mlx4_dbg(dev, "SMP firewall getresp_attribute_mask = 0x%x\n", 2372114840c3SJack Morgenstein getresp_attr_mask); 2373114840c3SJack Morgenstein 2374114840c3SJack Morgenstein MLX4_GET(trap_attr_mask, mailbox->buf, 2375114840c3SJack Morgenstein MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET); 2376114840c3SJack Morgenstein mlx4_dbg(dev, "SMP firewall trap_attribute_mask = 0x%x\n", 2377114840c3SJack Morgenstein trap_attr_mask); 2378114840c3SJack Morgenstein 2379114840c3SJack Morgenstein MLX4_GET(traprepress_attr_mask, mailbox->buf, 2380114840c3SJack Morgenstein MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET); 2381114840c3SJack Morgenstein mlx4_dbg(dev, "SMP firewall traprepress_attribute_mask = 0x%x\n", 2382114840c3SJack Morgenstein traprepress_attr_mask); 2383114840c3SJack Morgenstein 2384114840c3SJack Morgenstein if (set_attr_mask && getresp_attr_mask && trap_attr_mask && 2385114840c3SJack Morgenstein traprepress_attr_mask) 2386114840c3SJack Morgenstein return 1; 2387114840c3SJack Morgenstein 2388114840c3SJack Morgenstein return 0; 2389114840c3SJack Morgenstein } 2390114840c3SJack Morgenstein 2391114840c3SJack Morgenstein int mlx4_config_mad_demux(struct mlx4_dev *dev) 2392114840c3SJack Morgenstein { 2393114840c3SJack Morgenstein struct mlx4_cmd_mailbox *mailbox; 2394114840c3SJack Morgenstein int secure_host_active; 2395114840c3SJack Morgenstein int err; 2396114840c3SJack Morgenstein 2397114840c3SJack Morgenstein /* Check if mad_demux is supported */ 2398114840c3SJack Morgenstein if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_MAD_DEMUX)) 2399114840c3SJack Morgenstein return 0; 2400114840c3SJack Morgenstein 2401114840c3SJack Morgenstein mailbox = mlx4_alloc_cmd_mailbox(dev); 2402114840c3SJack Morgenstein if (IS_ERR(mailbox)) { 2403114840c3SJack Morgenstein mlx4_warn(dev, "Failed to allocate mailbox for cmd MAD_DEMUX"); 2404114840c3SJack Morgenstein return -ENOMEM; 2405114840c3SJack Morgenstein } 2406114840c3SJack Morgenstein 2407114840c3SJack Morgenstein /* Query mad_demux to find out which MADs are handled by internal sma */ 2408114840c3SJack Morgenstein err = mlx4_cmd_box(dev, 0, mailbox->dma, 0x01 /* subn mgmt class */, 2409114840c3SJack Morgenstein MLX4_CMD_MAD_DEMUX_QUERY_RESTR, MLX4_CMD_MAD_DEMUX, 2410114840c3SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 2411114840c3SJack Morgenstein if (err) { 2412114840c3SJack Morgenstein mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: query restrictions failed (%d)\n", 2413114840c3SJack Morgenstein err); 2414114840c3SJack Morgenstein goto out; 2415114840c3SJack Morgenstein } 2416114840c3SJack Morgenstein 2417114840c3SJack Morgenstein secure_host_active = mlx4_check_smp_firewall_active(dev, mailbox); 2418114840c3SJack Morgenstein 2419114840c3SJack Morgenstein /* Config mad_demux to handle all MADs returned by the query above */ 2420114840c3SJack Morgenstein err = mlx4_cmd(dev, mailbox->dma, 0x01 /* subn mgmt class */, 2421114840c3SJack Morgenstein MLX4_CMD_MAD_DEMUX_CONFIG, MLX4_CMD_MAD_DEMUX, 2422114840c3SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 2423114840c3SJack Morgenstein if (err) { 2424114840c3SJack Morgenstein mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: configure failed (%d)\n", err); 2425114840c3SJack Morgenstein goto out; 2426114840c3SJack Morgenstein } 2427114840c3SJack Morgenstein 2428114840c3SJack Morgenstein if (secure_host_active) 2429114840c3SJack Morgenstein mlx4_warn(dev, "HCA operating in secure-host mode. SMP firewall activated.\n"); 2430114840c3SJack Morgenstein out: 2431114840c3SJack Morgenstein mlx4_free_cmd_mailbox(dev, mailbox); 2432114840c3SJack Morgenstein return err; 2433114840c3SJack Morgenstein } 2434adbc7ac5SSaeed Mahameed 2435adbc7ac5SSaeed Mahameed /* Access Reg commands */ 2436adbc7ac5SSaeed Mahameed enum mlx4_access_reg_masks { 2437adbc7ac5SSaeed Mahameed MLX4_ACCESS_REG_STATUS_MASK = 0x7f, 2438adbc7ac5SSaeed Mahameed MLX4_ACCESS_REG_METHOD_MASK = 0x7f, 2439adbc7ac5SSaeed Mahameed MLX4_ACCESS_REG_LEN_MASK = 0x7ff 2440adbc7ac5SSaeed Mahameed }; 2441adbc7ac5SSaeed Mahameed 2442adbc7ac5SSaeed Mahameed struct mlx4_access_reg { 2443adbc7ac5SSaeed Mahameed __be16 constant1; 2444adbc7ac5SSaeed Mahameed u8 status; 2445adbc7ac5SSaeed Mahameed u8 resrvd1; 2446adbc7ac5SSaeed Mahameed __be16 reg_id; 2447adbc7ac5SSaeed Mahameed u8 method; 2448adbc7ac5SSaeed Mahameed u8 constant2; 2449adbc7ac5SSaeed Mahameed __be32 resrvd2[2]; 2450adbc7ac5SSaeed Mahameed __be16 len_const; 2451adbc7ac5SSaeed Mahameed __be16 resrvd3; 2452adbc7ac5SSaeed Mahameed #define MLX4_ACCESS_REG_HEADER_SIZE (20) 2453adbc7ac5SSaeed Mahameed u8 reg_data[MLX4_MAILBOX_SIZE-MLX4_ACCESS_REG_HEADER_SIZE]; 2454adbc7ac5SSaeed Mahameed } __attribute__((__packed__)); 2455adbc7ac5SSaeed Mahameed 2456adbc7ac5SSaeed Mahameed /** 2457adbc7ac5SSaeed Mahameed * mlx4_ACCESS_REG - Generic access reg command. 2458adbc7ac5SSaeed Mahameed * @dev: mlx4_dev. 2459adbc7ac5SSaeed Mahameed * @reg_id: register ID to access. 2460adbc7ac5SSaeed Mahameed * @method: Access method Read/Write. 2461adbc7ac5SSaeed Mahameed * @reg_len: register length to Read/Write in bytes. 2462adbc7ac5SSaeed Mahameed * @reg_data: reg_data pointer to Read/Write From/To. 2463adbc7ac5SSaeed Mahameed * 2464adbc7ac5SSaeed Mahameed * Access ConnectX registers FW command. 2465adbc7ac5SSaeed Mahameed * Returns 0 on success and copies outbox mlx4_access_reg data 2466adbc7ac5SSaeed Mahameed * field into reg_data or a negative error code. 2467adbc7ac5SSaeed Mahameed */ 2468adbc7ac5SSaeed Mahameed static int mlx4_ACCESS_REG(struct mlx4_dev *dev, u16 reg_id, 2469adbc7ac5SSaeed Mahameed enum mlx4_access_reg_method method, 2470adbc7ac5SSaeed Mahameed u16 reg_len, void *reg_data) 2471adbc7ac5SSaeed Mahameed { 2472adbc7ac5SSaeed Mahameed struct mlx4_cmd_mailbox *inbox, *outbox; 2473adbc7ac5SSaeed Mahameed struct mlx4_access_reg *inbuf, *outbuf; 2474adbc7ac5SSaeed Mahameed int err; 2475adbc7ac5SSaeed Mahameed 2476adbc7ac5SSaeed Mahameed inbox = mlx4_alloc_cmd_mailbox(dev); 2477adbc7ac5SSaeed Mahameed if (IS_ERR(inbox)) 2478adbc7ac5SSaeed Mahameed return PTR_ERR(inbox); 2479adbc7ac5SSaeed Mahameed 2480adbc7ac5SSaeed Mahameed outbox = mlx4_alloc_cmd_mailbox(dev); 2481adbc7ac5SSaeed Mahameed if (IS_ERR(outbox)) { 2482adbc7ac5SSaeed Mahameed mlx4_free_cmd_mailbox(dev, inbox); 2483adbc7ac5SSaeed Mahameed return PTR_ERR(outbox); 2484adbc7ac5SSaeed Mahameed } 2485adbc7ac5SSaeed Mahameed 2486adbc7ac5SSaeed Mahameed inbuf = inbox->buf; 2487adbc7ac5SSaeed Mahameed outbuf = outbox->buf; 2488adbc7ac5SSaeed Mahameed 2489adbc7ac5SSaeed Mahameed inbuf->constant1 = cpu_to_be16(0x1<<11 | 0x4); 2490adbc7ac5SSaeed Mahameed inbuf->constant2 = 0x1; 2491adbc7ac5SSaeed Mahameed inbuf->reg_id = cpu_to_be16(reg_id); 2492adbc7ac5SSaeed Mahameed inbuf->method = method & MLX4_ACCESS_REG_METHOD_MASK; 2493adbc7ac5SSaeed Mahameed 2494adbc7ac5SSaeed Mahameed reg_len = min(reg_len, (u16)(sizeof(inbuf->reg_data))); 2495adbc7ac5SSaeed Mahameed inbuf->len_const = 2496adbc7ac5SSaeed Mahameed cpu_to_be16(((reg_len/4 + 1) & MLX4_ACCESS_REG_LEN_MASK) | 2497adbc7ac5SSaeed Mahameed ((0x3) << 12)); 2498adbc7ac5SSaeed Mahameed 2499adbc7ac5SSaeed Mahameed memcpy(inbuf->reg_data, reg_data, reg_len); 2500adbc7ac5SSaeed Mahameed err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, 0, 0, 2501adbc7ac5SSaeed Mahameed MLX4_CMD_ACCESS_REG, MLX4_CMD_TIME_CLASS_C, 25026e806699SSaeed Mahameed MLX4_CMD_WRAPPED); 2503adbc7ac5SSaeed Mahameed if (err) 2504adbc7ac5SSaeed Mahameed goto out; 2505adbc7ac5SSaeed Mahameed 2506adbc7ac5SSaeed Mahameed if (outbuf->status & MLX4_ACCESS_REG_STATUS_MASK) { 2507adbc7ac5SSaeed Mahameed err = outbuf->status & MLX4_ACCESS_REG_STATUS_MASK; 2508adbc7ac5SSaeed Mahameed mlx4_err(dev, 2509adbc7ac5SSaeed Mahameed "MLX4_CMD_ACCESS_REG(%x) returned REG status (%x)\n", 2510adbc7ac5SSaeed Mahameed reg_id, err); 2511adbc7ac5SSaeed Mahameed goto out; 2512adbc7ac5SSaeed Mahameed } 2513adbc7ac5SSaeed Mahameed 2514adbc7ac5SSaeed Mahameed memcpy(reg_data, outbuf->reg_data, reg_len); 2515adbc7ac5SSaeed Mahameed out: 2516adbc7ac5SSaeed Mahameed mlx4_free_cmd_mailbox(dev, inbox); 2517adbc7ac5SSaeed Mahameed mlx4_free_cmd_mailbox(dev, outbox); 2518adbc7ac5SSaeed Mahameed return err; 2519adbc7ac5SSaeed Mahameed } 2520adbc7ac5SSaeed Mahameed 2521adbc7ac5SSaeed Mahameed /* ConnectX registers IDs */ 2522adbc7ac5SSaeed Mahameed enum mlx4_reg_id { 2523adbc7ac5SSaeed Mahameed MLX4_REG_ID_PTYS = 0x5004, 2524adbc7ac5SSaeed Mahameed }; 2525adbc7ac5SSaeed Mahameed 2526adbc7ac5SSaeed Mahameed /** 2527adbc7ac5SSaeed Mahameed * mlx4_ACCESS_PTYS_REG - Access PTYs (Port Type and Speed) 2528adbc7ac5SSaeed Mahameed * register 2529adbc7ac5SSaeed Mahameed * @dev: mlx4_dev. 2530adbc7ac5SSaeed Mahameed * @method: Access method Read/Write. 2531adbc7ac5SSaeed Mahameed * @ptys_reg: PTYS register data pointer. 2532adbc7ac5SSaeed Mahameed * 2533adbc7ac5SSaeed Mahameed * Access ConnectX PTYS register, to Read/Write Port Type/Speed 2534adbc7ac5SSaeed Mahameed * configuration 2535adbc7ac5SSaeed Mahameed * Returns 0 on success or a negative error code. 2536adbc7ac5SSaeed Mahameed */ 2537adbc7ac5SSaeed Mahameed int mlx4_ACCESS_PTYS_REG(struct mlx4_dev *dev, 2538adbc7ac5SSaeed Mahameed enum mlx4_access_reg_method method, 2539adbc7ac5SSaeed Mahameed struct mlx4_ptys_reg *ptys_reg) 2540adbc7ac5SSaeed Mahameed { 2541adbc7ac5SSaeed Mahameed return mlx4_ACCESS_REG(dev, MLX4_REG_ID_PTYS, 2542adbc7ac5SSaeed Mahameed method, sizeof(*ptys_reg), ptys_reg); 2543adbc7ac5SSaeed Mahameed } 2544adbc7ac5SSaeed Mahameed EXPORT_SYMBOL_GPL(mlx4_ACCESS_PTYS_REG); 25456e806699SSaeed Mahameed 25466e806699SSaeed Mahameed int mlx4_ACCESS_REG_wrapper(struct mlx4_dev *dev, int slave, 25476e806699SSaeed Mahameed struct mlx4_vhcr *vhcr, 25486e806699SSaeed Mahameed struct mlx4_cmd_mailbox *inbox, 25496e806699SSaeed Mahameed struct mlx4_cmd_mailbox *outbox, 25506e806699SSaeed Mahameed struct mlx4_cmd_info *cmd) 25516e806699SSaeed Mahameed { 25526e806699SSaeed Mahameed struct mlx4_access_reg *inbuf = inbox->buf; 25536e806699SSaeed Mahameed u8 method = inbuf->method & MLX4_ACCESS_REG_METHOD_MASK; 25546e806699SSaeed Mahameed u16 reg_id = be16_to_cpu(inbuf->reg_id); 25556e806699SSaeed Mahameed 25566e806699SSaeed Mahameed if (slave != mlx4_master_func_num(dev) && 25576e806699SSaeed Mahameed method == MLX4_ACCESS_REG_WRITE) 25586e806699SSaeed Mahameed return -EPERM; 25596e806699SSaeed Mahameed 25606e806699SSaeed Mahameed if (reg_id == MLX4_REG_ID_PTYS) { 25616e806699SSaeed Mahameed struct mlx4_ptys_reg *ptys_reg = 25626e806699SSaeed Mahameed (struct mlx4_ptys_reg *)inbuf->reg_data; 25636e806699SSaeed Mahameed 25646e806699SSaeed Mahameed ptys_reg->local_port = 25656e806699SSaeed Mahameed mlx4_slave_convert_port(dev, slave, 25666e806699SSaeed Mahameed ptys_reg->local_port); 25676e806699SSaeed Mahameed } 25686e806699SSaeed Mahameed 25696e806699SSaeed Mahameed return mlx4_cmd_box(dev, inbox->dma, outbox->dma, vhcr->in_modifier, 25706e806699SSaeed Mahameed 0, MLX4_CMD_ACCESS_REG, MLX4_CMD_TIME_CLASS_C, 25716e806699SSaeed Mahameed MLX4_CMD_NATIVE); 25726e806699SSaeed Mahameed } 2573