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", 148be6a6b43SJack Morgenstein [19] = "Performance optimized for limited rule configuration flow steering support", 149be6a6b43SJack 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 263*f0ce0615SJack Morgenstein #define QUERY_FUNC_CAP_QP_RESD_LKEY_OFFSET 0x48 2645cc914f1SMarcel Apfelbaum 265eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x50 266eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x54 267eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET 0x58 268eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET 0x60 269eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET 0x64 270eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET 0x68 271eb456a68SJack Morgenstein 272ddae0349SEugenia Emantayev #define QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET 0x6c 273ddae0349SEugenia Emantayev 274105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FMR_FLAG 0x80 275105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FLAG_RDMA 0x40 276105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FLAG_ETH 0x80 277eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_FLAG_QUOTAS 0x10 278*f0ce0615SJack Morgenstein #define QUERY_FUNC_CAP_FLAG_RESD_LKEY 0x08 279ddae0349SEugenia Emantayev #define QUERY_FUNC_CAP_FLAG_VALID_MAILBOX 0x04 280ddae0349SEugenia Emantayev 281ddae0349SEugenia Emantayev #define QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG (1UL << 31) 282d57febe1SMatan Barak #define QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG (1UL << 30) 283105c320fSJack Morgenstein 284105c320fSJack Morgenstein /* when opcode modifier = 1 */ 2855cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3 28699ec41d0SJack Morgenstein #define QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET 0x4 28773e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS0_OFFSET 0x8 28873e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_OFFSET 0xc 2895cc914f1SMarcel Apfelbaum 29047605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP0_TUNNEL 0x10 29147605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP0_PROXY 0x14 29247605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP1_TUNNEL 0x18 29347605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP1_PROXY 0x1c 2948e1a28e8SHadar Hen Zion #define QUERY_FUNC_CAP_PHYS_PORT_ID 0x28 29547605df9SJack Morgenstein 29673e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_FORCE_MAC 0x40 29773e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_FORCE_VLAN 0x80 298eb17711bSHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_NIC_INFO 0x10 29999ec41d0SJack Morgenstein #define QUERY_FUNC_CAP_VF_ENABLE_QP0 0x08 300105c320fSJack Morgenstein 30173e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID 0x80 3027ae0e400SMatan Barak #define QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS (1 << 31) 303105c320fSJack Morgenstein 3045cc914f1SMarcel Apfelbaum if (vhcr->op_modifier == 1) { 305449fc488SMatan Barak struct mlx4_active_ports actv_ports = 306449fc488SMatan Barak mlx4_get_active_ports(dev, slave); 307449fc488SMatan Barak int converted_port = mlx4_slave_convert_port( 308449fc488SMatan Barak dev, slave, vhcr->in_modifier); 309449fc488SMatan Barak 310449fc488SMatan Barak if (converted_port < 0) 311449fc488SMatan Barak return -EINVAL; 312449fc488SMatan Barak 313449fc488SMatan Barak vhcr->in_modifier = converted_port; 314449fc488SMatan Barak /* phys-port = logical-port */ 315449fc488SMatan Barak field = vhcr->in_modifier - 316449fc488SMatan Barak find_first_bit(actv_ports.ports, dev->caps.num_ports); 31747605df9SJack Morgenstein MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_PHYS_PORT_OFFSET); 31847605df9SJack Morgenstein 31999ec41d0SJack Morgenstein port = vhcr->in_modifier; 32099ec41d0SJack Morgenstein proxy_qp = dev->phys_caps.base_proxy_sqpn + 8 * slave + port - 1; 32199ec41d0SJack Morgenstein 32299ec41d0SJack Morgenstein /* Set nic_info bit to mark new fields support */ 32399ec41d0SJack Morgenstein field = QUERY_FUNC_CAP_FLAGS1_NIC_INFO; 32499ec41d0SJack Morgenstein 32599ec41d0SJack Morgenstein if (mlx4_vf_smi_enabled(dev, slave, port) && 32699ec41d0SJack Morgenstein !mlx4_get_parav_qkey(dev, proxy_qp, &qkey)) { 32799ec41d0SJack Morgenstein field |= QUERY_FUNC_CAP_VF_ENABLE_QP0; 32899ec41d0SJack Morgenstein MLX4_PUT(outbox->buf, qkey, 32999ec41d0SJack Morgenstein QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET); 33099ec41d0SJack Morgenstein } 33199ec41d0SJack Morgenstein MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS1_OFFSET); 33299ec41d0SJack Morgenstein 33347605df9SJack Morgenstein /* size is now the QP number */ 33499ec41d0SJack Morgenstein size = dev->phys_caps.base_tunnel_sqpn + 8 * slave + port - 1; 33547605df9SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP0_TUNNEL); 33647605df9SJack Morgenstein 33747605df9SJack Morgenstein size += 2; 33847605df9SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_TUNNEL); 33947605df9SJack Morgenstein 34099ec41d0SJack Morgenstein MLX4_PUT(outbox->buf, proxy_qp, QUERY_FUNC_CAP_QP0_PROXY); 34199ec41d0SJack Morgenstein proxy_qp += 2; 34299ec41d0SJack Morgenstein MLX4_PUT(outbox->buf, proxy_qp, QUERY_FUNC_CAP_QP1_PROXY); 34347605df9SJack Morgenstein 3448e1a28e8SHadar Hen Zion MLX4_PUT(outbox->buf, dev->caps.phys_port_id[vhcr->in_modifier], 3458e1a28e8SHadar Hen Zion QUERY_FUNC_CAP_PHYS_PORT_ID); 3468e1a28e8SHadar Hen Zion 3475cc914f1SMarcel Apfelbaum } else if (vhcr->op_modifier == 0) { 348449fc488SMatan Barak struct mlx4_active_ports actv_ports = 349449fc488SMatan Barak mlx4_get_active_ports(dev, slave); 350*f0ce0615SJack Morgenstein /* enable rdma and ethernet interfaces, new quota locations, 351*f0ce0615SJack Morgenstein * and reserved lkey 352*f0ce0615SJack Morgenstein */ 353eb456a68SJack Morgenstein field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA | 354*f0ce0615SJack Morgenstein QUERY_FUNC_CAP_FLAG_QUOTAS | QUERY_FUNC_CAP_FLAG_VALID_MAILBOX | 355*f0ce0615SJack Morgenstein QUERY_FUNC_CAP_FLAG_RESD_LKEY); 3565cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET); 3575cc914f1SMarcel Apfelbaum 358449fc488SMatan Barak field = min( 359449fc488SMatan Barak bitmap_weight(actv_ports.ports, dev->caps.num_ports), 360449fc488SMatan Barak dev->caps.num_ports); 3615cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); 3625cc914f1SMarcel Apfelbaum 36308ff3235SOr Gerlitz size = dev->caps.function_caps; /* set PF behaviours */ 3645cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_PF_BHVR_OFFSET); 3655cc914f1SMarcel Apfelbaum 366105c320fSJack Morgenstein field = 0; /* protected FMR support not available as yet */ 367105c320fSJack Morgenstein MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FMR_OFFSET); 368105c320fSJack Morgenstein 3695a0d0a61SJack Morgenstein size = priv->mfunc.master.res_tracker.res_alloc[RES_QP].quota[slave]; 3705cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET); 371eb456a68SJack Morgenstein size = dev->caps.num_qps; 372eb456a68SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP); 3735cc914f1SMarcel Apfelbaum 3745a0d0a61SJack Morgenstein size = priv->mfunc.master.res_tracker.res_alloc[RES_SRQ].quota[slave]; 3755cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET); 376eb456a68SJack Morgenstein size = dev->caps.num_srqs; 377eb456a68SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP); 3785cc914f1SMarcel Apfelbaum 3795a0d0a61SJack Morgenstein size = priv->mfunc.master.res_tracker.res_alloc[RES_CQ].quota[slave]; 3805cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET); 381eb456a68SJack Morgenstein size = dev->caps.num_cqs; 382eb456a68SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP); 3835cc914f1SMarcel Apfelbaum 3847ae0e400SMatan Barak if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS) || 3857ae0e400SMatan Barak mlx4_QUERY_FUNC(dev, &func, slave)) { 3867ae0e400SMatan Barak size = vhcr->in_modifier & 3877ae0e400SMatan Barak QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS ? 3887ae0e400SMatan Barak dev->caps.num_eqs : 3897ae0e400SMatan Barak rounddown_pow_of_two(dev->caps.num_eqs); 3905cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET); 3915cc914f1SMarcel Apfelbaum size = dev->caps.reserved_eqs; 3925cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); 3937ae0e400SMatan Barak } else { 3947ae0e400SMatan Barak size = vhcr->in_modifier & 3957ae0e400SMatan Barak QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS ? 3967ae0e400SMatan Barak func.max_eq : 3977ae0e400SMatan Barak rounddown_pow_of_two(func.max_eq); 3987ae0e400SMatan Barak MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET); 3997ae0e400SMatan Barak size = func.rsvd_eqs; 4007ae0e400SMatan Barak MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); 4017ae0e400SMatan Barak } 4025cc914f1SMarcel Apfelbaum 4035a0d0a61SJack Morgenstein size = priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[slave]; 4045cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET); 405eb456a68SJack Morgenstein size = dev->caps.num_mpts; 406eb456a68SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP); 4075cc914f1SMarcel Apfelbaum 4085a0d0a61SJack Morgenstein size = priv->mfunc.master.res_tracker.res_alloc[RES_MTT].quota[slave]; 4095cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET); 410eb456a68SJack Morgenstein size = dev->caps.num_mtts; 411eb456a68SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP); 4125cc914f1SMarcel Apfelbaum 4135cc914f1SMarcel Apfelbaum size = dev->caps.num_mgms + dev->caps.num_amgms; 4145cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); 415eb456a68SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP); 4165cc914f1SMarcel Apfelbaum 417d57febe1SMatan Barak size = QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG | 418d57febe1SMatan Barak QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG; 419ddae0349SEugenia Emantayev MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET); 420*f0ce0615SJack Morgenstein 421*f0ce0615SJack Morgenstein size = dev->caps.reserved_lkey + ((slave << 8) & 0xFF00); 422*f0ce0615SJack Morgenstein MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_RESD_LKEY_OFFSET); 4235cc914f1SMarcel Apfelbaum } else 4245cc914f1SMarcel Apfelbaum err = -EINVAL; 4255cc914f1SMarcel Apfelbaum 4265cc914f1SMarcel Apfelbaum return err; 4275cc914f1SMarcel Apfelbaum } 4285cc914f1SMarcel Apfelbaum 429225c6c8cSMatan Barak int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port, 43047605df9SJack Morgenstein struct mlx4_func_cap *func_cap) 4315cc914f1SMarcel Apfelbaum { 4325cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *mailbox; 4335cc914f1SMarcel Apfelbaum u32 *outbox; 43447605df9SJack Morgenstein u8 field, op_modifier; 43599ec41d0SJack Morgenstein u32 size, qkey; 436eb456a68SJack Morgenstein int err = 0, quotas = 0; 4377ae0e400SMatan Barak u32 in_modifier; 4385cc914f1SMarcel Apfelbaum 43947605df9SJack Morgenstein op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */ 4407ae0e400SMatan Barak in_modifier = op_modifier ? gen_or_port : 4417ae0e400SMatan Barak QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS; 4425cc914f1SMarcel Apfelbaum 4435cc914f1SMarcel Apfelbaum mailbox = mlx4_alloc_cmd_mailbox(dev); 4445cc914f1SMarcel Apfelbaum if (IS_ERR(mailbox)) 4455cc914f1SMarcel Apfelbaum return PTR_ERR(mailbox); 4465cc914f1SMarcel Apfelbaum 4477ae0e400SMatan Barak err = mlx4_cmd_box(dev, 0, mailbox->dma, in_modifier, op_modifier, 44847605df9SJack Morgenstein MLX4_CMD_QUERY_FUNC_CAP, 4495cc914f1SMarcel Apfelbaum MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 4505cc914f1SMarcel Apfelbaum if (err) 4515cc914f1SMarcel Apfelbaum goto out; 4525cc914f1SMarcel Apfelbaum 4535cc914f1SMarcel Apfelbaum outbox = mailbox->buf; 4545cc914f1SMarcel Apfelbaum 45547605df9SJack Morgenstein if (!op_modifier) { 4565cc914f1SMarcel Apfelbaum MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS_OFFSET); 457105c320fSJack Morgenstein if (!(field & (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA))) { 458105c320fSJack Morgenstein mlx4_err(dev, "The host supports neither eth nor rdma interfaces\n"); 4595cc914f1SMarcel Apfelbaum err = -EPROTONOSUPPORT; 4605cc914f1SMarcel Apfelbaum goto out; 4615cc914f1SMarcel Apfelbaum } 462105c320fSJack Morgenstein func_cap->flags = field; 463eb456a68SJack Morgenstein quotas = !!(func_cap->flags & QUERY_FUNC_CAP_FLAG_QUOTAS); 4645cc914f1SMarcel Apfelbaum 4655cc914f1SMarcel Apfelbaum MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); 4665cc914f1SMarcel Apfelbaum func_cap->num_ports = field; 4675cc914f1SMarcel Apfelbaum 4685cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_PF_BHVR_OFFSET); 4695cc914f1SMarcel Apfelbaum func_cap->pf_context_behaviour = size; 4705cc914f1SMarcel Apfelbaum 471eb456a68SJack Morgenstein if (quotas) { 4725cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET); 4735cc914f1SMarcel Apfelbaum func_cap->qp_quota = size & 0xFFFFFF; 4745cc914f1SMarcel Apfelbaum 4755cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET); 4765cc914f1SMarcel Apfelbaum func_cap->srq_quota = size & 0xFFFFFF; 4775cc914f1SMarcel Apfelbaum 4785cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET); 4795cc914f1SMarcel Apfelbaum func_cap->cq_quota = size & 0xFFFFFF; 4805cc914f1SMarcel Apfelbaum 4815cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET); 4825cc914f1SMarcel Apfelbaum func_cap->mpt_quota = size & 0xFFFFFF; 4835cc914f1SMarcel Apfelbaum 4845cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET); 4855cc914f1SMarcel Apfelbaum func_cap->mtt_quota = size & 0xFFFFFF; 4865cc914f1SMarcel Apfelbaum 4875cc914f1SMarcel Apfelbaum MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); 4885cc914f1SMarcel Apfelbaum func_cap->mcg_quota = size & 0xFFFFFF; 489eb456a68SJack Morgenstein 490eb456a68SJack Morgenstein } else { 491eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP); 492eb456a68SJack Morgenstein func_cap->qp_quota = size & 0xFFFFFF; 493eb456a68SJack Morgenstein 494eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP); 495eb456a68SJack Morgenstein func_cap->srq_quota = size & 0xFFFFFF; 496eb456a68SJack Morgenstein 497eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP); 498eb456a68SJack Morgenstein func_cap->cq_quota = size & 0xFFFFFF; 499eb456a68SJack Morgenstein 500eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP); 501eb456a68SJack Morgenstein func_cap->mpt_quota = size & 0xFFFFFF; 502eb456a68SJack Morgenstein 503eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP); 504eb456a68SJack Morgenstein func_cap->mtt_quota = size & 0xFFFFFF; 505eb456a68SJack Morgenstein 506eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP); 507eb456a68SJack Morgenstein func_cap->mcg_quota = size & 0xFFFFFF; 508eb456a68SJack Morgenstein } 509eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_MAX_EQ_OFFSET); 510eb456a68SJack Morgenstein func_cap->max_eq = size & 0xFFFFFF; 511eb456a68SJack Morgenstein 512eb456a68SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); 513eb456a68SJack Morgenstein func_cap->reserved_eq = size & 0xFFFFFF; 514eb456a68SJack Morgenstein 515*f0ce0615SJack Morgenstein if (func_cap->flags & QUERY_FUNC_CAP_FLAG_RESD_LKEY) { 516*f0ce0615SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_RESD_LKEY_OFFSET); 517*f0ce0615SJack Morgenstein func_cap->reserved_lkey = size; 518*f0ce0615SJack Morgenstein } else { 519*f0ce0615SJack Morgenstein func_cap->reserved_lkey = 0; 520*f0ce0615SJack Morgenstein } 521*f0ce0615SJack Morgenstein 522ddae0349SEugenia Emantayev func_cap->extra_flags = 0; 523ddae0349SEugenia Emantayev 524ddae0349SEugenia Emantayev /* Mailbox data from 0x6c and onward should only be treated if 525ddae0349SEugenia Emantayev * QUERY_FUNC_CAP_FLAG_VALID_MAILBOX is set in func_cap->flags 526ddae0349SEugenia Emantayev */ 527ddae0349SEugenia Emantayev if (func_cap->flags & QUERY_FUNC_CAP_FLAG_VALID_MAILBOX) { 528ddae0349SEugenia Emantayev MLX4_GET(size, outbox, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET); 529ddae0349SEugenia Emantayev if (size & QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG) 530ddae0349SEugenia Emantayev func_cap->extra_flags |= MLX4_QUERY_FUNC_FLAGS_BF_RES_QP; 531d57febe1SMatan Barak if (size & QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG) 532d57febe1SMatan Barak func_cap->extra_flags |= MLX4_QUERY_FUNC_FLAGS_A0_RES_QP; 533ddae0349SEugenia Emantayev } 534ddae0349SEugenia Emantayev 5355cc914f1SMarcel Apfelbaum goto out; 53647605df9SJack Morgenstein } 5375cc914f1SMarcel Apfelbaum 53847605df9SJack Morgenstein /* logical port query */ 53947605df9SJack Morgenstein if (gen_or_port > dev->caps.num_ports) { 54047605df9SJack Morgenstein err = -EINVAL; 54147605df9SJack Morgenstein goto out; 54247605df9SJack Morgenstein } 54347605df9SJack Morgenstein 544eb17711bSHadar Hen Zion MLX4_GET(func_cap->flags1, outbox, QUERY_FUNC_CAP_FLAGS1_OFFSET); 54547605df9SJack Morgenstein if (dev->caps.port_type[gen_or_port] == MLX4_PORT_TYPE_ETH) { 546bc82878bSJack Morgenstein if (func_cap->flags1 & QUERY_FUNC_CAP_FLAGS1_FORCE_VLAN) { 5475cc914f1SMarcel Apfelbaum mlx4_err(dev, "VLAN is enforced on this port\n"); 5485cc914f1SMarcel Apfelbaum err = -EPROTONOSUPPORT; 5495cc914f1SMarcel Apfelbaum goto out; 5505cc914f1SMarcel Apfelbaum } 5515cc914f1SMarcel Apfelbaum 552eb17711bSHadar Hen Zion if (func_cap->flags1 & QUERY_FUNC_CAP_FLAGS1_FORCE_MAC) { 5535cc914f1SMarcel Apfelbaum mlx4_err(dev, "Force mac is enabled on this port\n"); 5545cc914f1SMarcel Apfelbaum err = -EPROTONOSUPPORT; 5555cc914f1SMarcel Apfelbaum goto out; 5565cc914f1SMarcel Apfelbaum } 55747605df9SJack Morgenstein } else if (dev->caps.port_type[gen_or_port] == MLX4_PORT_TYPE_IB) { 55873e74ab4SHadar Hen Zion MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS0_OFFSET); 55973e74ab4SHadar Hen Zion if (field & QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID) { 5601a91de28SJoe Perches mlx4_err(dev, "phy_wqe_gid is enforced on this ib port\n"); 561105c320fSJack Morgenstein err = -EPROTONOSUPPORT; 562105c320fSJack Morgenstein goto out; 563105c320fSJack Morgenstein } 564105c320fSJack Morgenstein } 5655cc914f1SMarcel Apfelbaum 5665cc914f1SMarcel Apfelbaum MLX4_GET(field, outbox, QUERY_FUNC_CAP_PHYS_PORT_OFFSET); 56747605df9SJack Morgenstein func_cap->physical_port = field; 56847605df9SJack Morgenstein if (func_cap->physical_port != gen_or_port) { 56947605df9SJack Morgenstein err = -ENOSYS; 57047605df9SJack Morgenstein goto out; 5715cc914f1SMarcel Apfelbaum } 5725cc914f1SMarcel Apfelbaum 57399ec41d0SJack Morgenstein if (func_cap->flags1 & QUERY_FUNC_CAP_VF_ENABLE_QP0) { 57499ec41d0SJack Morgenstein MLX4_GET(qkey, outbox, QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET); 57599ec41d0SJack Morgenstein func_cap->qp0_qkey = qkey; 57699ec41d0SJack Morgenstein } else { 57799ec41d0SJack Morgenstein func_cap->qp0_qkey = 0; 57899ec41d0SJack Morgenstein } 57999ec41d0SJack Morgenstein 58047605df9SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_TUNNEL); 58147605df9SJack Morgenstein func_cap->qp0_tunnel_qpn = size & 0xFFFFFF; 58247605df9SJack Morgenstein 58347605df9SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_PROXY); 58447605df9SJack Morgenstein func_cap->qp0_proxy_qpn = size & 0xFFFFFF; 58547605df9SJack Morgenstein 58647605df9SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP1_TUNNEL); 58747605df9SJack Morgenstein func_cap->qp1_tunnel_qpn = size & 0xFFFFFF; 58847605df9SJack Morgenstein 58947605df9SJack Morgenstein MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP1_PROXY); 59047605df9SJack Morgenstein func_cap->qp1_proxy_qpn = size & 0xFFFFFF; 59147605df9SJack Morgenstein 5928e1a28e8SHadar Hen Zion if (func_cap->flags1 & QUERY_FUNC_CAP_FLAGS1_NIC_INFO) 5938e1a28e8SHadar Hen Zion MLX4_GET(func_cap->phys_port_id, outbox, 5948e1a28e8SHadar Hen Zion QUERY_FUNC_CAP_PHYS_PORT_ID); 5958e1a28e8SHadar Hen Zion 5965cc914f1SMarcel Apfelbaum /* All other resources are allocated by the master, but we still report 5975cc914f1SMarcel Apfelbaum * 'num' and 'reserved' capabilities as follows: 5985cc914f1SMarcel Apfelbaum * - num remains the maximum resource index 5995cc914f1SMarcel Apfelbaum * - 'num - reserved' is the total available objects of a resource, but 6005cc914f1SMarcel Apfelbaum * resource indices may be less than 'reserved' 6015cc914f1SMarcel Apfelbaum * TODO: set per-resource quotas */ 6025cc914f1SMarcel Apfelbaum 6035cc914f1SMarcel Apfelbaum out: 6045cc914f1SMarcel Apfelbaum mlx4_free_cmd_mailbox(dev, mailbox); 6055cc914f1SMarcel Apfelbaum 6065cc914f1SMarcel Apfelbaum return err; 6075cc914f1SMarcel Apfelbaum } 6085cc914f1SMarcel Apfelbaum 6095a2cc190SJeff Kirsher int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) 6105a2cc190SJeff Kirsher { 6115a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 6125a2cc190SJeff Kirsher u32 *outbox; 6135a2cc190SJeff Kirsher u8 field; 6145a2cc190SJeff Kirsher u32 field32, flags, ext_flags; 6155a2cc190SJeff Kirsher u16 size; 6165a2cc190SJeff Kirsher u16 stat_rate; 6175a2cc190SJeff Kirsher int err; 6185a2cc190SJeff Kirsher int i; 6195a2cc190SJeff Kirsher 6205a2cc190SJeff Kirsher #define QUERY_DEV_CAP_OUT_SIZE 0x100 6215a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET 0x10 6225a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_QP_SZ_OFFSET 0x11 6235a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_QP_OFFSET 0x12 6245a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_QP_OFFSET 0x13 6255a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_SRQ_OFFSET 0x14 6265a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SRQ_OFFSET 0x15 6275a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_EEC_OFFSET 0x16 6285a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_EEC_OFFSET 0x17 6295a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET 0x19 6305a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_CQ_OFFSET 0x1a 6315a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_CQ_OFFSET 0x1b 6325a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MPT_OFFSET 0x1d 6335a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_EQ_OFFSET 0x1e 6345a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_EQ_OFFSET 0x1f 6355a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_MTT_OFFSET 0x20 6365a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET 0x21 6375a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_MRW_OFFSET 0x22 6385a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET 0x23 6397ae0e400SMatan Barak #define QUERY_DEV_CAP_NUM_SYS_EQ_OFFSET 0x26 6405a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_AV_OFFSET 0x27 6415a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET 0x29 6425a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_RES_QP_OFFSET 0x2b 6435a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_GSO_OFFSET 0x2d 644b3416f44SShlomo Pongratz #define QUERY_DEV_CAP_RSS_OFFSET 0x2e 6455a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_RDMA_OFFSET 0x2f 6465a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSZ_SRQ_OFFSET 0x33 6475a2cc190SJeff Kirsher #define QUERY_DEV_CAP_ACK_DELAY_OFFSET 0x35 6485a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MTU_WIDTH_OFFSET 0x36 6495a2cc190SJeff Kirsher #define QUERY_DEV_CAP_VL_PORT_OFFSET 0x37 6505a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET 0x38 6515a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b 6525a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c 653d998735fSEugenia Emantayev #define QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET 0x3e 6545a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f 6555a2cc190SJeff Kirsher #define QUERY_DEV_CAP_EXT_FLAGS_OFFSET 0x40 6565a2cc190SJeff Kirsher #define QUERY_DEV_CAP_FLAGS_OFFSET 0x44 6575a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48 6585a2cc190SJeff Kirsher #define QUERY_DEV_CAP_UAR_SZ_OFFSET 0x49 6595a2cc190SJeff Kirsher #define QUERY_DEV_CAP_PAGE_SZ_OFFSET 0x4b 6605a2cc190SJeff Kirsher #define QUERY_DEV_CAP_BF_OFFSET 0x4c 6615a2cc190SJeff Kirsher #define QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET 0x4d 6625a2cc190SJeff Kirsher #define QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET 0x4e 6635a2cc190SJeff Kirsher #define QUERY_DEV_CAP_LOG_MAX_BF_PAGES_OFFSET 0x4f 6645a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SG_SQ_OFFSET 0x51 6655a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET 0x52 6665a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SG_RQ_OFFSET 0x55 6675a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET 0x56 6685a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_QP_MCG_OFFSET 0x61 6695a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_MCG_OFFSET 0x62 6705a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MCG_OFFSET 0x63 6715a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_PD_OFFSET 0x64 6725a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_PD_OFFSET 0x65 673f470f8d4SLinus Torvalds #define QUERY_DEV_CAP_RSVD_XRC_OFFSET 0x66 674f470f8d4SLinus Torvalds #define QUERY_DEV_CAP_MAX_XRC_OFFSET 0x67 6755a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET 0x68 6763f7fb021SRony Efraim #define QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET 0x70 6774de65803SMatan Barak #define QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET 0x74 6780ff1fb65SHadar Hen Zion #define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET 0x76 6790ff1fb65SHadar Hen Zion #define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET 0x77 68077507aa2SIdo Shamay #define QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE 0x7a 681adbc7ac5SSaeed Mahameed #define QUERY_DEV_CAP_ETH_PROT_CTRL_OFFSET 0x7a 6825a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80 6835a2cc190SJeff Kirsher #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82 6845a2cc190SJeff Kirsher #define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84 6855a2cc190SJeff Kirsher #define QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET 0x86 6865a2cc190SJeff Kirsher #define QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET 0x88 6875a2cc190SJeff Kirsher #define QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET 0x8a 6885a2cc190SJeff Kirsher #define QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET 0x8c 6895a2cc190SJeff Kirsher #define QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET 0x8e 6905a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET 0x90 6915a2cc190SJeff Kirsher #define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET 0x92 6925a2cc190SJeff Kirsher #define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x94 693d475c95bSMatan Barak #define QUERY_DEV_CAP_CONFIG_DEV_OFFSET 0x94 6945a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98 6955a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0 696a53e3e8cSSaeed Mahameed #define QUERY_DEV_CAP_ETH_BACKPL_OFFSET 0x9c 697955154faSMatan Barak #define QUERY_DEV_CAP_FW_REASSIGN_MAC 0x9d 6987ffdf726SOr Gerlitz #define QUERY_DEV_CAP_VXLAN 0x9e 699114840c3SJack Morgenstein #define QUERY_DEV_CAP_MAD_DEMUX_OFFSET 0xb0 7007d077cd3SMatan Barak #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET 0xa8 7017d077cd3SMatan Barak #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET 0xac 7025a2cc190SJeff Kirsher 703b3416f44SShlomo Pongratz dev_cap->flags2 = 0; 7045a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 7055a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 7065a2cc190SJeff Kirsher return PTR_ERR(mailbox); 7075a2cc190SJeff Kirsher outbox = mailbox->buf; 7085a2cc190SJeff Kirsher 7095a2cc190SJeff Kirsher err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, 710401453a3SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 7115a2cc190SJeff Kirsher if (err) 7125a2cc190SJeff Kirsher goto out; 7135a2cc190SJeff Kirsher 7145a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_QP_OFFSET); 7155a2cc190SJeff Kirsher dev_cap->reserved_qps = 1 << (field & 0xf); 7165a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_OFFSET); 7175a2cc190SJeff Kirsher dev_cap->max_qps = 1 << (field & 0x1f); 7185a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_SRQ_OFFSET); 7195a2cc190SJeff Kirsher dev_cap->reserved_srqs = 1 << (field >> 4); 7205a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_OFFSET); 7215a2cc190SJeff Kirsher dev_cap->max_srqs = 1 << (field & 0x1f); 7225a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET); 7235a2cc190SJeff Kirsher dev_cap->max_cq_sz = 1 << field; 7245a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_CQ_OFFSET); 7255a2cc190SJeff Kirsher dev_cap->reserved_cqs = 1 << (field & 0xf); 7265a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_OFFSET); 7275a2cc190SJeff Kirsher dev_cap->max_cqs = 1 << (field & 0x1f); 7285a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MPT_OFFSET); 7295a2cc190SJeff Kirsher dev_cap->max_mpts = 1 << (field & 0x3f); 7305a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_EQ_OFFSET); 7317c68dd43SMatan Barak dev_cap->reserved_eqs = 1 << (field & 0xf); 7325a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_EQ_OFFSET); 7335a2cc190SJeff Kirsher dev_cap->max_eqs = 1 << (field & 0xf); 7345a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MTT_OFFSET); 7355a2cc190SJeff Kirsher dev_cap->reserved_mtts = 1 << (field >> 4); 7365a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET); 7375a2cc190SJeff Kirsher dev_cap->max_mrw_sz = 1 << field; 7385a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MRW_OFFSET); 7395a2cc190SJeff Kirsher dev_cap->reserved_mrws = 1 << (field & 0xf); 7405a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET); 7415a2cc190SJeff Kirsher dev_cap->max_mtt_seg = 1 << (field & 0x3f); 7427ae0e400SMatan Barak MLX4_GET(size, outbox, QUERY_DEV_CAP_NUM_SYS_EQ_OFFSET); 7437ae0e400SMatan Barak dev_cap->num_sys_eqs = size & 0xfff; 7445a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_REQ_QP_OFFSET); 7455a2cc190SJeff Kirsher dev_cap->max_requester_per_qp = 1 << (field & 0x3f); 7465a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RES_QP_OFFSET); 7475a2cc190SJeff Kirsher dev_cap->max_responder_per_qp = 1 << (field & 0x3f); 7485a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GSO_OFFSET); 7495a2cc190SJeff Kirsher field &= 0x1f; 7505a2cc190SJeff Kirsher if (!field) 7515a2cc190SJeff Kirsher dev_cap->max_gso_sz = 0; 7525a2cc190SJeff Kirsher else 7535a2cc190SJeff Kirsher dev_cap->max_gso_sz = 1 << field; 7545a2cc190SJeff Kirsher 755b3416f44SShlomo Pongratz MLX4_GET(field, outbox, QUERY_DEV_CAP_RSS_OFFSET); 756b3416f44SShlomo Pongratz if (field & 0x20) 757b3416f44SShlomo Pongratz dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_XOR; 758b3416f44SShlomo Pongratz if (field & 0x10) 759b3416f44SShlomo Pongratz dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_TOP; 760b3416f44SShlomo Pongratz field &= 0xf; 761b3416f44SShlomo Pongratz if (field) { 762b3416f44SShlomo Pongratz dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS; 763b3416f44SShlomo Pongratz dev_cap->max_rss_tbl_sz = 1 << field; 764b3416f44SShlomo Pongratz } else 765b3416f44SShlomo Pongratz dev_cap->max_rss_tbl_sz = 0; 7665a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RDMA_OFFSET); 7675a2cc190SJeff Kirsher dev_cap->max_rdma_global = 1 << (field & 0x3f); 7685a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET); 7695a2cc190SJeff Kirsher dev_cap->local_ca_ack_delay = field & 0x1f; 7705a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); 7715a2cc190SJeff Kirsher dev_cap->num_ports = field & 0xf; 7725a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET); 7735a2cc190SJeff Kirsher dev_cap->max_msg_sz = 1 << (field & 0x1f); 7740ff1fb65SHadar Hen Zion MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET); 7750ff1fb65SHadar Hen Zion if (field & 0x80) 7760ff1fb65SHadar Hen Zion dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FS_EN; 7770ff1fb65SHadar Hen Zion dev_cap->fs_log_max_ucast_qp_range_size = field & 0x1f; 7784de65803SMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET); 7794de65803SMatan Barak if (field & 0x80) 7804de65803SMatan Barak dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DMFS_IPOIB; 7810ff1fb65SHadar Hen Zion MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET); 7820ff1fb65SHadar Hen Zion dev_cap->fs_max_num_qp_per_entry = field; 7835a2cc190SJeff Kirsher MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); 7845a2cc190SJeff Kirsher dev_cap->stat_rate_support = stat_rate; 785d998735fSEugenia Emantayev MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET); 786d998735fSEugenia Emantayev if (field & 0x80) 787d998735fSEugenia Emantayev dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_TS; 7885a2cc190SJeff Kirsher MLX4_GET(ext_flags, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET); 7895a2cc190SJeff Kirsher MLX4_GET(flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET); 7905a2cc190SJeff Kirsher dev_cap->flags = flags | (u64)ext_flags << 32; 7915a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET); 7925a2cc190SJeff Kirsher dev_cap->reserved_uars = field >> 4; 7935a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_UAR_SZ_OFFSET); 7945a2cc190SJeff Kirsher dev_cap->uar_size = 1 << ((field & 0x3f) + 20); 7955a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_PAGE_SZ_OFFSET); 7965a2cc190SJeff Kirsher dev_cap->min_page_sz = 1 << field; 7975a2cc190SJeff Kirsher 7985a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_BF_OFFSET); 7995a2cc190SJeff Kirsher if (field & 0x80) { 8005a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET); 8015a2cc190SJeff Kirsher dev_cap->bf_reg_size = 1 << (field & 0x1f); 8025a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET); 8035a2cc190SJeff Kirsher if ((1 << (field & 0x3f)) > (PAGE_SIZE / dev_cap->bf_reg_size)) 8045a2cc190SJeff Kirsher field = 3; 8055a2cc190SJeff Kirsher dev_cap->bf_regs_per_page = 1 << (field & 0x3f); 8065a2cc190SJeff Kirsher } else { 8075a2cc190SJeff Kirsher dev_cap->bf_reg_size = 0; 8085a2cc190SJeff Kirsher } 8095a2cc190SJeff Kirsher 8105a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_SQ_OFFSET); 8115a2cc190SJeff Kirsher dev_cap->max_sq_sg = field; 8125a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET); 8135a2cc190SJeff Kirsher dev_cap->max_sq_desc_sz = size; 8145a2cc190SJeff Kirsher 8155a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_MCG_OFFSET); 8165a2cc190SJeff Kirsher dev_cap->max_qp_per_mcg = 1 << field; 8175a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MCG_OFFSET); 8185a2cc190SJeff Kirsher dev_cap->reserved_mgms = field & 0xf; 8195a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MCG_OFFSET); 8205a2cc190SJeff Kirsher dev_cap->max_mcgs = 1 << field; 8215a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_PD_OFFSET); 8225a2cc190SJeff Kirsher dev_cap->reserved_pds = field >> 4; 8235a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET); 8245a2cc190SJeff Kirsher dev_cap->max_pds = 1 << (field & 0x3f); 825f470f8d4SLinus Torvalds MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_XRC_OFFSET); 826f470f8d4SLinus Torvalds dev_cap->reserved_xrcds = field >> 4; 827426dd00dSDotan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_XRC_OFFSET); 828f470f8d4SLinus Torvalds dev_cap->max_xrcds = 1 << (field & 0x1f); 8295a2cc190SJeff Kirsher 8305a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET); 8315a2cc190SJeff Kirsher dev_cap->rdmarc_entry_sz = size; 8325a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET); 8335a2cc190SJeff Kirsher dev_cap->qpc_entry_sz = size; 8345a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET); 8355a2cc190SJeff Kirsher dev_cap->aux_entry_sz = size; 8365a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET); 8375a2cc190SJeff Kirsher dev_cap->altc_entry_sz = size; 8385a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET); 8395a2cc190SJeff Kirsher dev_cap->eqc_entry_sz = size; 8405a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET); 8415a2cc190SJeff Kirsher dev_cap->cqc_entry_sz = size; 8425a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET); 8435a2cc190SJeff Kirsher dev_cap->srq_entry_sz = size; 8445a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET); 8455a2cc190SJeff Kirsher dev_cap->cmpt_entry_sz = size; 8465a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET); 8475a2cc190SJeff Kirsher dev_cap->mtt_entry_sz = size; 8485a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET); 8495a2cc190SJeff Kirsher dev_cap->dmpt_entry_sz = size; 8505a2cc190SJeff Kirsher 8515a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET); 8525a2cc190SJeff Kirsher dev_cap->max_srq_sz = 1 << field; 8535a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_SZ_OFFSET); 8545a2cc190SJeff Kirsher dev_cap->max_qp_sz = 1 << field; 8555a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_RSZ_SRQ_OFFSET); 8565a2cc190SJeff Kirsher dev_cap->resize_srq = field & 1; 8575a2cc190SJeff Kirsher MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_RQ_OFFSET); 8585a2cc190SJeff Kirsher dev_cap->max_rq_sg = field; 8595a2cc190SJeff Kirsher MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET); 8605a2cc190SJeff Kirsher dev_cap->max_rq_desc_sz = size; 86177507aa2SIdo Shamay MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE); 862adbc7ac5SSaeed Mahameed if (field & (1 << 5)) 863adbc7ac5SSaeed Mahameed dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETH_PROT_CTRL; 86477507aa2SIdo Shamay if (field & (1 << 6)) 86577507aa2SIdo Shamay dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_CQE_STRIDE; 86677507aa2SIdo Shamay if (field & (1 << 7)) 86777507aa2SIdo Shamay dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_EQE_STRIDE; 8685a2cc190SJeff Kirsher MLX4_GET(dev_cap->bmme_flags, outbox, 8695a2cc190SJeff Kirsher QUERY_DEV_CAP_BMME_FLAGS_OFFSET); 870d475c95bSMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_CONFIG_DEV_OFFSET); 871d475c95bSMatan Barak if (field & 0x20) 872d475c95bSMatan Barak dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_CONFIG_DEV; 8735a2cc190SJeff Kirsher MLX4_GET(dev_cap->reserved_lkey, outbox, 8745a2cc190SJeff Kirsher QUERY_DEV_CAP_RSVD_LKEY_OFFSET); 875a53e3e8cSSaeed Mahameed MLX4_GET(field32, outbox, QUERY_DEV_CAP_ETH_BACKPL_OFFSET); 876a53e3e8cSSaeed Mahameed if (field32 & (1 << 0)) 877a53e3e8cSSaeed Mahameed dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP; 878be6a6b43SJack Morgenstein if (field32 & (1 << 7)) 879be6a6b43SJack Morgenstein dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT; 880955154faSMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_FW_REASSIGN_MAC); 881955154faSMatan Barak if (field & 1<<6) 8825930e8d0SOr Gerlitz dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_REASSIGN_MAC_EN; 8837ffdf726SOr Gerlitz MLX4_GET(field, outbox, QUERY_DEV_CAP_VXLAN); 8847ffdf726SOr Gerlitz if (field & 1<<3) 8857ffdf726SOr Gerlitz dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS; 8865a2cc190SJeff Kirsher MLX4_GET(dev_cap->max_icm_sz, outbox, 8875a2cc190SJeff Kirsher QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET); 8885a2cc190SJeff Kirsher if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS) 8895a2cc190SJeff Kirsher MLX4_GET(dev_cap->max_counters, outbox, 8905a2cc190SJeff Kirsher QUERY_DEV_CAP_MAX_COUNTERS_OFFSET); 8915a2cc190SJeff Kirsher 892114840c3SJack Morgenstein MLX4_GET(field32, outbox, 893114840c3SJack Morgenstein QUERY_DEV_CAP_MAD_DEMUX_OFFSET); 894114840c3SJack Morgenstein if (field32 & (1 << 0)) 895114840c3SJack Morgenstein dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_MAD_DEMUX; 896114840c3SJack Morgenstein 8977d077cd3SMatan Barak MLX4_GET(dev_cap->dmfs_high_rate_qpn_base, outbox, 8987d077cd3SMatan Barak QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET); 8997d077cd3SMatan Barak dev_cap->dmfs_high_rate_qpn_base &= MGM_QPN_MASK; 9007d077cd3SMatan Barak MLX4_GET(dev_cap->dmfs_high_rate_qpn_range, outbox, 9017d077cd3SMatan Barak QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET); 9027d077cd3SMatan Barak dev_cap->dmfs_high_rate_qpn_range &= MGM_QPN_MASK; 9037d077cd3SMatan Barak 9043f7fb021SRony Efraim MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); 905b01978caSJack Morgenstein if (field32 & (1 << 16)) 906b01978caSJack Morgenstein dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP; 9073f7fb021SRony Efraim if (field32 & (1 << 26)) 9083f7fb021SRony Efraim dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VLAN_CONTROL; 909e6b6a231SRony Efraim if (field32 & (1 << 20)) 910e6b6a231SRony Efraim dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FSM; 911de966c59SMatan Barak if (field32 & (1 << 21)) 912de966c59SMatan Barak dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_80_VFS; 9133f7fb021SRony Efraim 914431df8c7SMatan Barak for (i = 1; i <= dev_cap->num_ports; i++) { 915431df8c7SMatan Barak err = mlx4_QUERY_PORT(dev, i, dev_cap->port_cap + i); 9165a2cc190SJeff Kirsher if (err) 9175a2cc190SJeff Kirsher goto out; 9185a2cc190SJeff Kirsher } 9195a2cc190SJeff Kirsher 9205a2cc190SJeff Kirsher /* 9215a2cc190SJeff Kirsher * Each UAR has 4 EQ doorbells; so if a UAR is reserved, then 9225a2cc190SJeff Kirsher * we can't use any EQs whose doorbell falls on that page, 9235a2cc190SJeff Kirsher * even if the EQ itself isn't reserved. 9245a2cc190SJeff Kirsher */ 9257ae0e400SMatan Barak if (dev_cap->num_sys_eqs == 0) 9265a2cc190SJeff Kirsher dev_cap->reserved_eqs = max(dev_cap->reserved_uars * 4, 9275a2cc190SJeff Kirsher dev_cap->reserved_eqs); 9287ae0e400SMatan Barak else 9297ae0e400SMatan Barak dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SYS_EQS; 9305a2cc190SJeff Kirsher 931c78e25edSOr Gerlitz out: 932c78e25edSOr Gerlitz mlx4_free_cmd_mailbox(dev, mailbox); 933c78e25edSOr Gerlitz return err; 934c78e25edSOr Gerlitz } 935c78e25edSOr Gerlitz 936c78e25edSOr Gerlitz void mlx4_dev_cap_dump(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) 937c78e25edSOr Gerlitz { 938c78e25edSOr Gerlitz if (dev_cap->bf_reg_size > 0) 939c78e25edSOr Gerlitz mlx4_dbg(dev, "BlueFlame available (reg size %d, regs/page %d)\n", 940c78e25edSOr Gerlitz dev_cap->bf_reg_size, dev_cap->bf_regs_per_page); 941c78e25edSOr Gerlitz else 942c78e25edSOr Gerlitz mlx4_dbg(dev, "BlueFlame not available\n"); 943c78e25edSOr Gerlitz 944c78e25edSOr Gerlitz mlx4_dbg(dev, "Base MM extensions: flags %08x, rsvd L_Key %08x\n", 945c78e25edSOr Gerlitz dev_cap->bmme_flags, dev_cap->reserved_lkey); 9465a2cc190SJeff Kirsher mlx4_dbg(dev, "Max ICM size %lld MB\n", 9475a2cc190SJeff Kirsher (unsigned long long) dev_cap->max_icm_sz >> 20); 9485a2cc190SJeff Kirsher mlx4_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n", 9495a2cc190SJeff Kirsher dev_cap->max_qps, dev_cap->reserved_qps, dev_cap->qpc_entry_sz); 9505a2cc190SJeff Kirsher mlx4_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n", 9515a2cc190SJeff Kirsher dev_cap->max_srqs, dev_cap->reserved_srqs, dev_cap->srq_entry_sz); 9525a2cc190SJeff Kirsher mlx4_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n", 9535a2cc190SJeff Kirsher dev_cap->max_cqs, dev_cap->reserved_cqs, dev_cap->cqc_entry_sz); 9547ae0e400SMatan Barak mlx4_dbg(dev, "Num sys EQs: %d, max EQs: %d, reserved EQs: %d, entry size: %d\n", 9557ae0e400SMatan Barak dev_cap->num_sys_eqs, dev_cap->max_eqs, dev_cap->reserved_eqs, 9567ae0e400SMatan Barak dev_cap->eqc_entry_sz); 9575a2cc190SJeff Kirsher mlx4_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n", 9585a2cc190SJeff Kirsher dev_cap->reserved_mrws, dev_cap->reserved_mtts); 9595a2cc190SJeff Kirsher mlx4_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n", 9605a2cc190SJeff Kirsher dev_cap->max_pds, dev_cap->reserved_pds, dev_cap->reserved_uars); 9615a2cc190SJeff Kirsher mlx4_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n", 9625a2cc190SJeff Kirsher dev_cap->max_pds, dev_cap->reserved_mgms); 9635a2cc190SJeff Kirsher mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", 9645a2cc190SJeff Kirsher dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz); 9655a2cc190SJeff Kirsher mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n", 966431df8c7SMatan Barak dev_cap->local_ca_ack_delay, 128 << dev_cap->port_cap[1].ib_mtu, 967431df8c7SMatan Barak dev_cap->port_cap[1].max_port_width); 9685a2cc190SJeff Kirsher mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n", 9695a2cc190SJeff Kirsher dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg); 9705a2cc190SJeff Kirsher mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n", 9715a2cc190SJeff Kirsher dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg); 9725a2cc190SJeff Kirsher mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz); 9735a2cc190SJeff Kirsher mlx4_dbg(dev, "Max counters: %d\n", dev_cap->max_counters); 974b3416f44SShlomo Pongratz mlx4_dbg(dev, "Max RSS Table size: %d\n", dev_cap->max_rss_tbl_sz); 9757d077cd3SMatan Barak mlx4_dbg(dev, "DMFS high rate steer QPn base: %d\n", 9767d077cd3SMatan Barak dev_cap->dmfs_high_rate_qpn_base); 9777d077cd3SMatan Barak mlx4_dbg(dev, "DMFS high rate steer QPn range: %d\n", 9787d077cd3SMatan Barak dev_cap->dmfs_high_rate_qpn_range); 9795a2cc190SJeff Kirsher dump_dev_cap_flags(dev, dev_cap->flags); 980b3416f44SShlomo Pongratz dump_dev_cap_flags2(dev, dev_cap->flags2); 9815a2cc190SJeff Kirsher } 9825a2cc190SJeff Kirsher 983431df8c7SMatan Barak int mlx4_QUERY_PORT(struct mlx4_dev *dev, int port, struct mlx4_port_cap *port_cap) 984431df8c7SMatan Barak { 985431df8c7SMatan Barak struct mlx4_cmd_mailbox *mailbox; 986431df8c7SMatan Barak u32 *outbox; 987431df8c7SMatan Barak u8 field; 988431df8c7SMatan Barak u32 field32; 989431df8c7SMatan Barak int err; 990431df8c7SMatan Barak 991431df8c7SMatan Barak mailbox = mlx4_alloc_cmd_mailbox(dev); 992431df8c7SMatan Barak if (IS_ERR(mailbox)) 993431df8c7SMatan Barak return PTR_ERR(mailbox); 994431df8c7SMatan Barak outbox = mailbox->buf; 995431df8c7SMatan Barak 996431df8c7SMatan Barak if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 997431df8c7SMatan Barak err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, 998431df8c7SMatan Barak MLX4_CMD_TIME_CLASS_A, 999431df8c7SMatan Barak MLX4_CMD_NATIVE); 1000431df8c7SMatan Barak 1001431df8c7SMatan Barak if (err) 1002431df8c7SMatan Barak goto out; 1003431df8c7SMatan Barak 1004431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); 1005431df8c7SMatan Barak port_cap->max_vl = field >> 4; 1006431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET); 1007431df8c7SMatan Barak port_cap->ib_mtu = field >> 4; 1008431df8c7SMatan Barak port_cap->max_port_width = field & 0xf; 1009431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET); 1010431df8c7SMatan Barak port_cap->max_gids = 1 << (field & 0xf); 1011431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET); 1012431df8c7SMatan Barak port_cap->max_pkeys = 1 << (field & 0xf); 1013431df8c7SMatan Barak } else { 1014431df8c7SMatan Barak #define QUERY_PORT_SUPPORTED_TYPE_OFFSET 0x00 1015431df8c7SMatan Barak #define QUERY_PORT_MTU_OFFSET 0x01 1016431df8c7SMatan Barak #define QUERY_PORT_ETH_MTU_OFFSET 0x02 1017431df8c7SMatan Barak #define QUERY_PORT_WIDTH_OFFSET 0x06 1018431df8c7SMatan Barak #define QUERY_PORT_MAX_GID_PKEY_OFFSET 0x07 1019431df8c7SMatan Barak #define QUERY_PORT_MAX_MACVLAN_OFFSET 0x0a 1020431df8c7SMatan Barak #define QUERY_PORT_MAX_VL_OFFSET 0x0b 1021431df8c7SMatan Barak #define QUERY_PORT_MAC_OFFSET 0x10 1022431df8c7SMatan Barak #define QUERY_PORT_TRANS_VENDOR_OFFSET 0x18 1023431df8c7SMatan Barak #define QUERY_PORT_WAVELENGTH_OFFSET 0x1c 1024431df8c7SMatan Barak #define QUERY_PORT_TRANS_CODE_OFFSET 0x20 1025431df8c7SMatan Barak 1026431df8c7SMatan Barak err = mlx4_cmd_box(dev, 0, mailbox->dma, port, 0, MLX4_CMD_QUERY_PORT, 1027431df8c7SMatan Barak MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 1028431df8c7SMatan Barak if (err) 1029431df8c7SMatan Barak goto out; 1030431df8c7SMatan Barak 1031431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_PORT_SUPPORTED_TYPE_OFFSET); 1032431df8c7SMatan Barak port_cap->supported_port_types = field & 3; 1033431df8c7SMatan Barak port_cap->suggested_type = (field >> 3) & 1; 1034431df8c7SMatan Barak port_cap->default_sense = (field >> 4) & 1; 10357d077cd3SMatan Barak port_cap->dmfs_optimized_state = (field >> 5) & 1; 1036431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET); 1037431df8c7SMatan Barak port_cap->ib_mtu = field & 0xf; 1038431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET); 1039431df8c7SMatan Barak port_cap->max_port_width = field & 0xf; 1040431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET); 1041431df8c7SMatan Barak port_cap->max_gids = 1 << (field >> 4); 1042431df8c7SMatan Barak port_cap->max_pkeys = 1 << (field & 0xf); 1043431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET); 1044431df8c7SMatan Barak port_cap->max_vl = field & 0xf; 1045431df8c7SMatan Barak MLX4_GET(field, outbox, QUERY_PORT_MAX_MACVLAN_OFFSET); 1046431df8c7SMatan Barak port_cap->log_max_macs = field & 0xf; 1047431df8c7SMatan Barak port_cap->log_max_vlans = field >> 4; 1048431df8c7SMatan Barak MLX4_GET(port_cap->eth_mtu, outbox, QUERY_PORT_ETH_MTU_OFFSET); 1049431df8c7SMatan Barak MLX4_GET(port_cap->def_mac, outbox, QUERY_PORT_MAC_OFFSET); 1050431df8c7SMatan Barak MLX4_GET(field32, outbox, QUERY_PORT_TRANS_VENDOR_OFFSET); 1051431df8c7SMatan Barak port_cap->trans_type = field32 >> 24; 1052431df8c7SMatan Barak port_cap->vendor_oui = field32 & 0xffffff; 1053431df8c7SMatan Barak MLX4_GET(port_cap->wavelength, outbox, QUERY_PORT_WAVELENGTH_OFFSET); 1054431df8c7SMatan Barak MLX4_GET(port_cap->trans_code, outbox, QUERY_PORT_TRANS_CODE_OFFSET); 1055431df8c7SMatan Barak } 1056431df8c7SMatan Barak 1057431df8c7SMatan Barak out: 1058431df8c7SMatan Barak mlx4_free_cmd_mailbox(dev, mailbox); 1059431df8c7SMatan Barak return err; 1060431df8c7SMatan Barak } 1061431df8c7SMatan Barak 1062383677daSOr Gerlitz #define DEV_CAP_EXT_2_FLAG_VLAN_CONTROL (1 << 26) 1063383677daSOr Gerlitz #define DEV_CAP_EXT_2_FLAG_80_VFS (1 << 21) 1064383677daSOr Gerlitz #define DEV_CAP_EXT_2_FLAG_FSM (1 << 20) 1065383677daSOr Gerlitz 1066b91cb3ebSJack Morgenstein int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, 1067b91cb3ebSJack Morgenstein struct mlx4_vhcr *vhcr, 1068b91cb3ebSJack Morgenstein struct mlx4_cmd_mailbox *inbox, 1069b91cb3ebSJack Morgenstein struct mlx4_cmd_mailbox *outbox, 1070b91cb3ebSJack Morgenstein struct mlx4_cmd_info *cmd) 1071b91cb3ebSJack Morgenstein { 10722a4fae14SJack Morgenstein u64 flags; 1073b91cb3ebSJack Morgenstein int err = 0; 1074b91cb3ebSJack Morgenstein u8 field; 1075383677daSOr Gerlitz u32 bmme_flags, field32; 1076449fc488SMatan Barak int real_port; 1077449fc488SMatan Barak int slave_port; 1078449fc488SMatan Barak int first_port; 1079449fc488SMatan Barak struct mlx4_active_ports actv_ports; 1080b91cb3ebSJack Morgenstein 1081b91cb3ebSJack Morgenstein err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, 1082b91cb3ebSJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 1083b91cb3ebSJack Morgenstein if (err) 1084b91cb3ebSJack Morgenstein return err; 1085b91cb3ebSJack Morgenstein 1086cc1ade94SShani Michaeli /* add port mng change event capability and disable mw type 1 1087cc1ade94SShani Michaeli * unconditionally to slaves 1088cc1ade94SShani Michaeli */ 10892a4fae14SJack Morgenstein MLX4_GET(flags, outbox->buf, QUERY_DEV_CAP_EXT_FLAGS_OFFSET); 10902a4fae14SJack Morgenstein flags |= MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV; 1091cc1ade94SShani Michaeli flags &= ~MLX4_DEV_CAP_FLAG_MEM_WINDOW; 1092449fc488SMatan Barak actv_ports = mlx4_get_active_ports(dev, slave); 1093449fc488SMatan Barak first_port = find_first_bit(actv_ports.ports, dev->caps.num_ports); 1094449fc488SMatan Barak for (slave_port = 0, real_port = first_port; 1095449fc488SMatan Barak real_port < first_port + 1096449fc488SMatan Barak bitmap_weight(actv_ports.ports, dev->caps.num_ports); 1097449fc488SMatan Barak ++real_port, ++slave_port) { 1098449fc488SMatan Barak if (flags & (MLX4_DEV_CAP_FLAG_WOL_PORT1 << real_port)) 1099449fc488SMatan Barak flags |= MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port; 1100449fc488SMatan Barak else 1101449fc488SMatan Barak flags &= ~(MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port); 1102449fc488SMatan Barak } 1103449fc488SMatan Barak for (; slave_port < dev->caps.num_ports; ++slave_port) 1104449fc488SMatan Barak flags &= ~(MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port); 11052a4fae14SJack Morgenstein MLX4_PUT(outbox->buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET); 11062a4fae14SJack Morgenstein 1107449fc488SMatan Barak MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_VL_PORT_OFFSET); 1108449fc488SMatan Barak field &= ~0x0F; 1109449fc488SMatan Barak field |= bitmap_weight(actv_ports.ports, dev->caps.num_ports) & 0x0F; 1110449fc488SMatan Barak MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_VL_PORT_OFFSET); 1111449fc488SMatan Barak 111230b40c31SAmir Vadai /* For guests, disable timestamp */ 111330b40c31SAmir Vadai MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET); 111430b40c31SAmir Vadai field &= 0x7f; 111530b40c31SAmir Vadai MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET); 111630b40c31SAmir Vadai 11177ffdf726SOr Gerlitz /* For guests, disable vxlan tunneling */ 111857352ef4SAmir Vadai MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_VXLAN); 11197ffdf726SOr Gerlitz field &= 0xf7; 11207ffdf726SOr Gerlitz MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_VXLAN); 11217ffdf726SOr Gerlitz 1122b91cb3ebSJack Morgenstein /* For guests, report Blueflame disabled */ 1123b91cb3ebSJack Morgenstein MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_BF_OFFSET); 1124b91cb3ebSJack Morgenstein field &= 0x7f; 1125b91cb3ebSJack Morgenstein MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_BF_OFFSET); 1126b91cb3ebSJack Morgenstein 1127cc1ade94SShani Michaeli /* For guests, disable mw type 2 */ 112857352ef4SAmir Vadai MLX4_GET(bmme_flags, outbox->buf, QUERY_DEV_CAP_BMME_FLAGS_OFFSET); 1129cc1ade94SShani Michaeli bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN; 1130cc1ade94SShani Michaeli MLX4_PUT(outbox->buf, bmme_flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET); 1131cc1ade94SShani Michaeli 11320081c8f3SJack Morgenstein /* turn off device-managed steering capability if not enabled */ 11330081c8f3SJack Morgenstein if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) { 11340081c8f3SJack Morgenstein MLX4_GET(field, outbox->buf, 11350081c8f3SJack Morgenstein QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET); 11360081c8f3SJack Morgenstein field &= 0x7f; 11370081c8f3SJack Morgenstein MLX4_PUT(outbox->buf, field, 11380081c8f3SJack Morgenstein QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET); 11390081c8f3SJack Morgenstein } 11404de65803SMatan Barak 11414de65803SMatan Barak /* turn off ipoib managed steering for guests */ 114257352ef4SAmir Vadai MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET); 11434de65803SMatan Barak field &= ~0x80; 11444de65803SMatan Barak MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET); 11454de65803SMatan Barak 1146383677daSOr Gerlitz /* turn off host side virt features (VST, FSM, etc) for guests */ 1147383677daSOr Gerlitz MLX4_GET(field32, outbox->buf, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); 1148383677daSOr Gerlitz field32 &= ~(DEV_CAP_EXT_2_FLAG_VLAN_CONTROL | DEV_CAP_EXT_2_FLAG_80_VFS | 1149383677daSOr Gerlitz DEV_CAP_EXT_2_FLAG_FSM); 1150383677daSOr Gerlitz MLX4_PUT(outbox->buf, field32, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); 1151383677daSOr Gerlitz 1152b91cb3ebSJack Morgenstein return 0; 1153b91cb3ebSJack Morgenstein } 1154b91cb3ebSJack Morgenstein 11555cc914f1SMarcel Apfelbaum int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, 11565cc914f1SMarcel Apfelbaum struct mlx4_vhcr *vhcr, 11575cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *inbox, 11585cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *outbox, 11595cc914f1SMarcel Apfelbaum struct mlx4_cmd_info *cmd) 11605cc914f1SMarcel Apfelbaum { 11610eb62b93SRony Efraim struct mlx4_priv *priv = mlx4_priv(dev); 11625cc914f1SMarcel Apfelbaum u64 def_mac; 11635cc914f1SMarcel Apfelbaum u8 port_type; 11646634961cSJack Morgenstein u16 short_field; 11655cc914f1SMarcel Apfelbaum int err; 1166948e306dSRony Efraim int admin_link_state; 1167449fc488SMatan Barak int port = mlx4_slave_convert_port(dev, slave, 1168449fc488SMatan Barak vhcr->in_modifier & 0xFF); 11695cc914f1SMarcel Apfelbaum 1170105c320fSJack Morgenstein #define MLX4_VF_PORT_NO_LINK_SENSE_MASK 0xE0 1171948e306dSRony Efraim #define MLX4_PORT_LINK_UP_MASK 0x80 11726634961cSJack Morgenstein #define QUERY_PORT_CUR_MAX_PKEY_OFFSET 0x0c 11736634961cSJack Morgenstein #define QUERY_PORT_CUR_MAX_GID_OFFSET 0x0e 117495f56e7aSYevgeny Petrilin 1175449fc488SMatan Barak if (port < 0) 1176449fc488SMatan Barak return -EINVAL; 1177449fc488SMatan Barak 1178a7401b9cSJack Morgenstein /* Protect against untrusted guests: enforce that this is the 1179a7401b9cSJack Morgenstein * QUERY_PORT general query. 1180a7401b9cSJack Morgenstein */ 1181a7401b9cSJack Morgenstein if (vhcr->op_modifier || vhcr->in_modifier & ~0xFF) 1182a7401b9cSJack Morgenstein return -EINVAL; 1183a7401b9cSJack Morgenstein 1184a7401b9cSJack Morgenstein vhcr->in_modifier = port; 1185449fc488SMatan Barak 11865cc914f1SMarcel Apfelbaum err = mlx4_cmd_box(dev, 0, outbox->dma, vhcr->in_modifier, 0, 11875cc914f1SMarcel Apfelbaum MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, 11885cc914f1SMarcel Apfelbaum MLX4_CMD_NATIVE); 11895cc914f1SMarcel Apfelbaum 11905cc914f1SMarcel Apfelbaum if (!err && dev->caps.function != slave) { 11910eb62b93SRony Efraim def_mac = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac; 11925cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, def_mac, QUERY_PORT_MAC_OFFSET); 11935cc914f1SMarcel Apfelbaum 11945cc914f1SMarcel Apfelbaum /* get port type - currently only eth is enabled */ 11955cc914f1SMarcel Apfelbaum MLX4_GET(port_type, outbox->buf, 11965cc914f1SMarcel Apfelbaum QUERY_PORT_SUPPORTED_TYPE_OFFSET); 11975cc914f1SMarcel Apfelbaum 1198105c320fSJack Morgenstein /* No link sensing allowed */ 1199105c320fSJack Morgenstein port_type &= MLX4_VF_PORT_NO_LINK_SENSE_MASK; 1200105c320fSJack Morgenstein /* set port type to currently operating port type */ 1201105c320fSJack Morgenstein port_type |= (dev->caps.port_type[vhcr->in_modifier] & 0x3); 12025cc914f1SMarcel Apfelbaum 1203948e306dSRony Efraim admin_link_state = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.link_state; 1204948e306dSRony Efraim if (IFLA_VF_LINK_STATE_ENABLE == admin_link_state) 1205948e306dSRony Efraim port_type |= MLX4_PORT_LINK_UP_MASK; 1206948e306dSRony Efraim else if (IFLA_VF_LINK_STATE_DISABLE == admin_link_state) 1207948e306dSRony Efraim port_type &= ~MLX4_PORT_LINK_UP_MASK; 1208948e306dSRony Efraim 12095cc914f1SMarcel Apfelbaum MLX4_PUT(outbox->buf, port_type, 12105cc914f1SMarcel Apfelbaum QUERY_PORT_SUPPORTED_TYPE_OFFSET); 12116634961cSJack Morgenstein 1212b6ffaeffSJack Morgenstein if (dev->caps.port_type[vhcr->in_modifier] == MLX4_PORT_TYPE_ETH) 1213449fc488SMatan Barak short_field = mlx4_get_slave_num_gids(dev, slave, port); 1214b6ffaeffSJack Morgenstein else 12156634961cSJack Morgenstein short_field = 1; /* slave max gids */ 12166634961cSJack Morgenstein MLX4_PUT(outbox->buf, short_field, 12176634961cSJack Morgenstein QUERY_PORT_CUR_MAX_GID_OFFSET); 12186634961cSJack Morgenstein 12196634961cSJack Morgenstein short_field = dev->caps.pkey_table_len[vhcr->in_modifier]; 12206634961cSJack Morgenstein MLX4_PUT(outbox->buf, short_field, 12216634961cSJack Morgenstein QUERY_PORT_CUR_MAX_PKEY_OFFSET); 12225cc914f1SMarcel Apfelbaum } 12235cc914f1SMarcel Apfelbaum 12245cc914f1SMarcel Apfelbaum return err; 12255cc914f1SMarcel Apfelbaum } 12265cc914f1SMarcel Apfelbaum 12276634961cSJack Morgenstein int mlx4_get_slave_pkey_gid_tbl_len(struct mlx4_dev *dev, u8 port, 12286634961cSJack Morgenstein int *gid_tbl_len, int *pkey_tbl_len) 12296634961cSJack Morgenstein { 12306634961cSJack Morgenstein struct mlx4_cmd_mailbox *mailbox; 12316634961cSJack Morgenstein u32 *outbox; 12326634961cSJack Morgenstein u16 field; 12336634961cSJack Morgenstein int err; 12346634961cSJack Morgenstein 12356634961cSJack Morgenstein mailbox = mlx4_alloc_cmd_mailbox(dev); 12366634961cSJack Morgenstein if (IS_ERR(mailbox)) 12376634961cSJack Morgenstein return PTR_ERR(mailbox); 12386634961cSJack Morgenstein 12396634961cSJack Morgenstein err = mlx4_cmd_box(dev, 0, mailbox->dma, port, 0, 12406634961cSJack Morgenstein MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, 12416634961cSJack Morgenstein MLX4_CMD_WRAPPED); 12426634961cSJack Morgenstein if (err) 12436634961cSJack Morgenstein goto out; 12446634961cSJack Morgenstein 12456634961cSJack Morgenstein outbox = mailbox->buf; 12466634961cSJack Morgenstein 12476634961cSJack Morgenstein MLX4_GET(field, outbox, QUERY_PORT_CUR_MAX_GID_OFFSET); 12486634961cSJack Morgenstein *gid_tbl_len = field; 12496634961cSJack Morgenstein 12506634961cSJack Morgenstein MLX4_GET(field, outbox, QUERY_PORT_CUR_MAX_PKEY_OFFSET); 12516634961cSJack Morgenstein *pkey_tbl_len = field; 12526634961cSJack Morgenstein 12536634961cSJack Morgenstein out: 12546634961cSJack Morgenstein mlx4_free_cmd_mailbox(dev, mailbox); 12556634961cSJack Morgenstein return err; 12566634961cSJack Morgenstein } 12576634961cSJack Morgenstein EXPORT_SYMBOL(mlx4_get_slave_pkey_gid_tbl_len); 12586634961cSJack Morgenstein 12595a2cc190SJeff Kirsher int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt) 12605a2cc190SJeff Kirsher { 12615a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 12625a2cc190SJeff Kirsher struct mlx4_icm_iter iter; 12635a2cc190SJeff Kirsher __be64 *pages; 12645a2cc190SJeff Kirsher int lg; 12655a2cc190SJeff Kirsher int nent = 0; 12665a2cc190SJeff Kirsher int i; 12675a2cc190SJeff Kirsher int err = 0; 12685a2cc190SJeff Kirsher int ts = 0, tc = 0; 12695a2cc190SJeff Kirsher 12705a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 12715a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 12725a2cc190SJeff Kirsher return PTR_ERR(mailbox); 12735a2cc190SJeff Kirsher pages = mailbox->buf; 12745a2cc190SJeff Kirsher 12755a2cc190SJeff Kirsher for (mlx4_icm_first(icm, &iter); 12765a2cc190SJeff Kirsher !mlx4_icm_last(&iter); 12775a2cc190SJeff Kirsher mlx4_icm_next(&iter)) { 12785a2cc190SJeff Kirsher /* 12795a2cc190SJeff Kirsher * We have to pass pages that are aligned to their 12805a2cc190SJeff Kirsher * size, so find the least significant 1 in the 12815a2cc190SJeff Kirsher * address or size and use that as our log2 size. 12825a2cc190SJeff Kirsher */ 12835a2cc190SJeff Kirsher lg = ffs(mlx4_icm_addr(&iter) | mlx4_icm_size(&iter)) - 1; 12845a2cc190SJeff Kirsher if (lg < MLX4_ICM_PAGE_SHIFT) { 12851a91de28SJoe Perches mlx4_warn(dev, "Got FW area not aligned to %d (%llx/%lx)\n", 12865a2cc190SJeff Kirsher MLX4_ICM_PAGE_SIZE, 12875a2cc190SJeff Kirsher (unsigned long long) mlx4_icm_addr(&iter), 12885a2cc190SJeff Kirsher mlx4_icm_size(&iter)); 12895a2cc190SJeff Kirsher err = -EINVAL; 12905a2cc190SJeff Kirsher goto out; 12915a2cc190SJeff Kirsher } 12925a2cc190SJeff Kirsher 12935a2cc190SJeff Kirsher for (i = 0; i < mlx4_icm_size(&iter) >> lg; ++i) { 12945a2cc190SJeff Kirsher if (virt != -1) { 12955a2cc190SJeff Kirsher pages[nent * 2] = cpu_to_be64(virt); 12965a2cc190SJeff Kirsher virt += 1 << lg; 12975a2cc190SJeff Kirsher } 12985a2cc190SJeff Kirsher 12995a2cc190SJeff Kirsher pages[nent * 2 + 1] = 13005a2cc190SJeff Kirsher cpu_to_be64((mlx4_icm_addr(&iter) + (i << lg)) | 13015a2cc190SJeff Kirsher (lg - MLX4_ICM_PAGE_SHIFT)); 13025a2cc190SJeff Kirsher ts += 1 << (lg - 10); 13035a2cc190SJeff Kirsher ++tc; 13045a2cc190SJeff Kirsher 13055a2cc190SJeff Kirsher if (++nent == MLX4_MAILBOX_SIZE / 16) { 13065a2cc190SJeff Kirsher err = mlx4_cmd(dev, mailbox->dma, nent, 0, op, 1307f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_B, 1308f9baff50SJack Morgenstein MLX4_CMD_NATIVE); 13095a2cc190SJeff Kirsher if (err) 13105a2cc190SJeff Kirsher goto out; 13115a2cc190SJeff Kirsher nent = 0; 13125a2cc190SJeff Kirsher } 13135a2cc190SJeff Kirsher } 13145a2cc190SJeff Kirsher } 13155a2cc190SJeff Kirsher 13165a2cc190SJeff Kirsher if (nent) 1317f9baff50SJack Morgenstein err = mlx4_cmd(dev, mailbox->dma, nent, 0, op, 1318f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 13195a2cc190SJeff Kirsher if (err) 13205a2cc190SJeff Kirsher goto out; 13215a2cc190SJeff Kirsher 13225a2cc190SJeff Kirsher switch (op) { 13235a2cc190SJeff Kirsher case MLX4_CMD_MAP_FA: 13241a91de28SJoe Perches mlx4_dbg(dev, "Mapped %d chunks/%d KB for FW\n", tc, ts); 13255a2cc190SJeff Kirsher break; 13265a2cc190SJeff Kirsher case MLX4_CMD_MAP_ICM_AUX: 13271a91de28SJoe Perches mlx4_dbg(dev, "Mapped %d chunks/%d KB for ICM aux\n", tc, ts); 13285a2cc190SJeff Kirsher break; 13295a2cc190SJeff Kirsher case MLX4_CMD_MAP_ICM: 13301a91de28SJoe Perches mlx4_dbg(dev, "Mapped %d chunks/%d KB at %llx for ICM\n", 13315a2cc190SJeff Kirsher tc, ts, (unsigned long long) virt - (ts << 10)); 13325a2cc190SJeff Kirsher break; 13335a2cc190SJeff Kirsher } 13345a2cc190SJeff Kirsher 13355a2cc190SJeff Kirsher out: 13365a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 13375a2cc190SJeff Kirsher return err; 13385a2cc190SJeff Kirsher } 13395a2cc190SJeff Kirsher 13405a2cc190SJeff Kirsher int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm) 13415a2cc190SJeff Kirsher { 13425a2cc190SJeff Kirsher return mlx4_map_cmd(dev, MLX4_CMD_MAP_FA, icm, -1); 13435a2cc190SJeff Kirsher } 13445a2cc190SJeff Kirsher 13455a2cc190SJeff Kirsher int mlx4_UNMAP_FA(struct mlx4_dev *dev) 13465a2cc190SJeff Kirsher { 1347f9baff50SJack Morgenstein return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_FA, 1348f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 13495a2cc190SJeff Kirsher } 13505a2cc190SJeff Kirsher 13515a2cc190SJeff Kirsher 13525a2cc190SJeff Kirsher int mlx4_RUN_FW(struct mlx4_dev *dev) 13535a2cc190SJeff Kirsher { 1354f9baff50SJack Morgenstein return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_RUN_FW, 1355f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 13565a2cc190SJeff Kirsher } 13575a2cc190SJeff Kirsher 13585a2cc190SJeff Kirsher int mlx4_QUERY_FW(struct mlx4_dev *dev) 13595a2cc190SJeff Kirsher { 13605a2cc190SJeff Kirsher struct mlx4_fw *fw = &mlx4_priv(dev)->fw; 13615a2cc190SJeff Kirsher struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; 13625a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 13635a2cc190SJeff Kirsher u32 *outbox; 13645a2cc190SJeff Kirsher int err = 0; 13655a2cc190SJeff Kirsher u64 fw_ver; 13665a2cc190SJeff Kirsher u16 cmd_if_rev; 13675a2cc190SJeff Kirsher u8 lg; 13685a2cc190SJeff Kirsher 13695a2cc190SJeff Kirsher #define QUERY_FW_OUT_SIZE 0x100 13705a2cc190SJeff Kirsher #define QUERY_FW_VER_OFFSET 0x00 13715cc914f1SMarcel Apfelbaum #define QUERY_FW_PPF_ID 0x09 13725a2cc190SJeff Kirsher #define QUERY_FW_CMD_IF_REV_OFFSET 0x0a 13735a2cc190SJeff Kirsher #define QUERY_FW_MAX_CMD_OFFSET 0x0f 13745a2cc190SJeff Kirsher #define QUERY_FW_ERR_START_OFFSET 0x30 13755a2cc190SJeff Kirsher #define QUERY_FW_ERR_SIZE_OFFSET 0x38 13765a2cc190SJeff Kirsher #define QUERY_FW_ERR_BAR_OFFSET 0x3c 13775a2cc190SJeff Kirsher 13785a2cc190SJeff Kirsher #define QUERY_FW_SIZE_OFFSET 0x00 13795a2cc190SJeff Kirsher #define QUERY_FW_CLR_INT_BASE_OFFSET 0x20 13805a2cc190SJeff Kirsher #define QUERY_FW_CLR_INT_BAR_OFFSET 0x28 13815a2cc190SJeff Kirsher 13825cc914f1SMarcel Apfelbaum #define QUERY_FW_COMM_BASE_OFFSET 0x40 13835cc914f1SMarcel Apfelbaum #define QUERY_FW_COMM_BAR_OFFSET 0x48 13845cc914f1SMarcel Apfelbaum 1385ddd8a6c1SEugenia Emantayev #define QUERY_FW_CLOCK_OFFSET 0x50 1386ddd8a6c1SEugenia Emantayev #define QUERY_FW_CLOCK_BAR 0x58 1387ddd8a6c1SEugenia Emantayev 13885a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 13895a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 13905a2cc190SJeff Kirsher return PTR_ERR(mailbox); 13915a2cc190SJeff Kirsher outbox = mailbox->buf; 13925a2cc190SJeff Kirsher 13935a2cc190SJeff Kirsher err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_FW, 1394f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 13955a2cc190SJeff Kirsher if (err) 13965a2cc190SJeff Kirsher goto out; 13975a2cc190SJeff Kirsher 13985a2cc190SJeff Kirsher MLX4_GET(fw_ver, outbox, QUERY_FW_VER_OFFSET); 13995a2cc190SJeff Kirsher /* 14005a2cc190SJeff Kirsher * FW subminor version is at more significant bits than minor 14015a2cc190SJeff Kirsher * version, so swap here. 14025a2cc190SJeff Kirsher */ 14035a2cc190SJeff Kirsher dev->caps.fw_ver = (fw_ver & 0xffff00000000ull) | 14045a2cc190SJeff Kirsher ((fw_ver & 0xffff0000ull) >> 16) | 14055a2cc190SJeff Kirsher ((fw_ver & 0x0000ffffull) << 16); 14065a2cc190SJeff Kirsher 1407752a50caSJack Morgenstein MLX4_GET(lg, outbox, QUERY_FW_PPF_ID); 1408752a50caSJack Morgenstein dev->caps.function = lg; 1409752a50caSJack Morgenstein 1410b91cb3ebSJack Morgenstein if (mlx4_is_slave(dev)) 1411b91cb3ebSJack Morgenstein goto out; 1412b91cb3ebSJack Morgenstein 14135cc914f1SMarcel Apfelbaum 14145a2cc190SJeff Kirsher MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET); 14155a2cc190SJeff Kirsher if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV || 14165a2cc190SJeff Kirsher cmd_if_rev > MLX4_COMMAND_INTERFACE_MAX_REV) { 14171a91de28SJoe Perches mlx4_err(dev, "Installed FW has unsupported command interface revision %d\n", 14185a2cc190SJeff Kirsher cmd_if_rev); 14195a2cc190SJeff Kirsher mlx4_err(dev, "(Installed FW version is %d.%d.%03d)\n", 14205a2cc190SJeff Kirsher (int) (dev->caps.fw_ver >> 32), 14215a2cc190SJeff Kirsher (int) (dev->caps.fw_ver >> 16) & 0xffff, 14225a2cc190SJeff Kirsher (int) dev->caps.fw_ver & 0xffff); 14231a91de28SJoe Perches mlx4_err(dev, "This driver version supports only revisions %d to %d\n", 14245a2cc190SJeff Kirsher MLX4_COMMAND_INTERFACE_MIN_REV, MLX4_COMMAND_INTERFACE_MAX_REV); 14255a2cc190SJeff Kirsher err = -ENODEV; 14265a2cc190SJeff Kirsher goto out; 14275a2cc190SJeff Kirsher } 14285a2cc190SJeff Kirsher 14295a2cc190SJeff Kirsher if (cmd_if_rev < MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS) 14305a2cc190SJeff Kirsher dev->flags |= MLX4_FLAG_OLD_PORT_CMDS; 14315a2cc190SJeff Kirsher 14325a2cc190SJeff Kirsher MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET); 14335a2cc190SJeff Kirsher cmd->max_cmds = 1 << lg; 14345a2cc190SJeff Kirsher 14355a2cc190SJeff Kirsher mlx4_dbg(dev, "FW version %d.%d.%03d (cmd intf rev %d), max commands %d\n", 14365a2cc190SJeff Kirsher (int) (dev->caps.fw_ver >> 32), 14375a2cc190SJeff Kirsher (int) (dev->caps.fw_ver >> 16) & 0xffff, 14385a2cc190SJeff Kirsher (int) dev->caps.fw_ver & 0xffff, 14395a2cc190SJeff Kirsher cmd_if_rev, cmd->max_cmds); 14405a2cc190SJeff Kirsher 14415a2cc190SJeff Kirsher MLX4_GET(fw->catas_offset, outbox, QUERY_FW_ERR_START_OFFSET); 14425a2cc190SJeff Kirsher MLX4_GET(fw->catas_size, outbox, QUERY_FW_ERR_SIZE_OFFSET); 14435a2cc190SJeff Kirsher MLX4_GET(fw->catas_bar, outbox, QUERY_FW_ERR_BAR_OFFSET); 14445a2cc190SJeff Kirsher fw->catas_bar = (fw->catas_bar >> 6) * 2; 14455a2cc190SJeff Kirsher 14465a2cc190SJeff Kirsher mlx4_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x, BAR %d\n", 14475a2cc190SJeff Kirsher (unsigned long long) fw->catas_offset, fw->catas_size, fw->catas_bar); 14485a2cc190SJeff Kirsher 14495a2cc190SJeff Kirsher MLX4_GET(fw->fw_pages, outbox, QUERY_FW_SIZE_OFFSET); 14505a2cc190SJeff Kirsher MLX4_GET(fw->clr_int_base, outbox, QUERY_FW_CLR_INT_BASE_OFFSET); 14515a2cc190SJeff Kirsher MLX4_GET(fw->clr_int_bar, outbox, QUERY_FW_CLR_INT_BAR_OFFSET); 14525a2cc190SJeff Kirsher fw->clr_int_bar = (fw->clr_int_bar >> 6) * 2; 14535a2cc190SJeff Kirsher 14545cc914f1SMarcel Apfelbaum MLX4_GET(fw->comm_base, outbox, QUERY_FW_COMM_BASE_OFFSET); 14555cc914f1SMarcel Apfelbaum MLX4_GET(fw->comm_bar, outbox, QUERY_FW_COMM_BAR_OFFSET); 14565cc914f1SMarcel Apfelbaum fw->comm_bar = (fw->comm_bar >> 6) * 2; 14575cc914f1SMarcel Apfelbaum mlx4_dbg(dev, "Communication vector bar:%d offset:0x%llx\n", 14585cc914f1SMarcel Apfelbaum fw->comm_bar, fw->comm_base); 14595a2cc190SJeff Kirsher mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2); 14605a2cc190SJeff Kirsher 1461ddd8a6c1SEugenia Emantayev MLX4_GET(fw->clock_offset, outbox, QUERY_FW_CLOCK_OFFSET); 1462ddd8a6c1SEugenia Emantayev MLX4_GET(fw->clock_bar, outbox, QUERY_FW_CLOCK_BAR); 1463ddd8a6c1SEugenia Emantayev fw->clock_bar = (fw->clock_bar >> 6) * 2; 1464ddd8a6c1SEugenia Emantayev mlx4_dbg(dev, "Internal clock bar:%d offset:0x%llx\n", 1465ddd8a6c1SEugenia Emantayev fw->clock_bar, fw->clock_offset); 1466ddd8a6c1SEugenia Emantayev 14675a2cc190SJeff Kirsher /* 14685a2cc190SJeff Kirsher * Round up number of system pages needed in case 14695a2cc190SJeff Kirsher * MLX4_ICM_PAGE_SIZE < PAGE_SIZE. 14705a2cc190SJeff Kirsher */ 14715a2cc190SJeff Kirsher fw->fw_pages = 14725a2cc190SJeff Kirsher ALIGN(fw->fw_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >> 14735a2cc190SJeff Kirsher (PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT); 14745a2cc190SJeff Kirsher 14755a2cc190SJeff Kirsher mlx4_dbg(dev, "Clear int @ %llx, BAR %d\n", 14765a2cc190SJeff Kirsher (unsigned long long) fw->clr_int_base, fw->clr_int_bar); 14775a2cc190SJeff Kirsher 14785a2cc190SJeff Kirsher out: 14795a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 14805a2cc190SJeff Kirsher return err; 14815a2cc190SJeff Kirsher } 14825a2cc190SJeff Kirsher 1483b91cb3ebSJack Morgenstein int mlx4_QUERY_FW_wrapper(struct mlx4_dev *dev, int slave, 1484b91cb3ebSJack Morgenstein struct mlx4_vhcr *vhcr, 1485b91cb3ebSJack Morgenstein struct mlx4_cmd_mailbox *inbox, 1486b91cb3ebSJack Morgenstein struct mlx4_cmd_mailbox *outbox, 1487b91cb3ebSJack Morgenstein struct mlx4_cmd_info *cmd) 1488b91cb3ebSJack Morgenstein { 1489b91cb3ebSJack Morgenstein u8 *outbuf; 1490b91cb3ebSJack Morgenstein int err; 1491b91cb3ebSJack Morgenstein 1492b91cb3ebSJack Morgenstein outbuf = outbox->buf; 1493b91cb3ebSJack Morgenstein err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_FW, 1494b91cb3ebSJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 1495b91cb3ebSJack Morgenstein if (err) 1496b91cb3ebSJack Morgenstein return err; 1497b91cb3ebSJack Morgenstein 1498752a50caSJack Morgenstein /* for slaves, set pci PPF ID to invalid and zero out everything 1499752a50caSJack Morgenstein * else except FW version */ 1500b91cb3ebSJack Morgenstein outbuf[0] = outbuf[1] = 0; 1501b91cb3ebSJack Morgenstein memset(&outbuf[8], 0, QUERY_FW_OUT_SIZE - 8); 1502752a50caSJack Morgenstein outbuf[QUERY_FW_PPF_ID] = MLX4_INVALID_SLAVE_ID; 1503752a50caSJack Morgenstein 1504b91cb3ebSJack Morgenstein return 0; 1505b91cb3ebSJack Morgenstein } 1506b91cb3ebSJack Morgenstein 15075a2cc190SJeff Kirsher static void get_board_id(void *vsd, char *board_id) 15085a2cc190SJeff Kirsher { 15095a2cc190SJeff Kirsher int i; 15105a2cc190SJeff Kirsher 15115a2cc190SJeff Kirsher #define VSD_OFFSET_SIG1 0x00 15125a2cc190SJeff Kirsher #define VSD_OFFSET_SIG2 0xde 15135a2cc190SJeff Kirsher #define VSD_OFFSET_MLX_BOARD_ID 0xd0 15145a2cc190SJeff Kirsher #define VSD_OFFSET_TS_BOARD_ID 0x20 15155a2cc190SJeff Kirsher 15165a2cc190SJeff Kirsher #define VSD_SIGNATURE_TOPSPIN 0x5ad 15175a2cc190SJeff Kirsher 15185a2cc190SJeff Kirsher memset(board_id, 0, MLX4_BOARD_ID_LEN); 15195a2cc190SJeff Kirsher 15205a2cc190SJeff Kirsher if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN && 15215a2cc190SJeff Kirsher be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) { 15225a2cc190SJeff Kirsher strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MLX4_BOARD_ID_LEN); 15235a2cc190SJeff Kirsher } else { 15245a2cc190SJeff Kirsher /* 15255a2cc190SJeff Kirsher * The board ID is a string but the firmware byte 15265a2cc190SJeff Kirsher * swaps each 4-byte word before passing it back to 15275a2cc190SJeff Kirsher * us. Therefore we need to swab it before printing. 15285a2cc190SJeff Kirsher */ 15295a2cc190SJeff Kirsher for (i = 0; i < 4; ++i) 15305a2cc190SJeff Kirsher ((u32 *) board_id)[i] = 15315a2cc190SJeff Kirsher swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4)); 15325a2cc190SJeff Kirsher } 15335a2cc190SJeff Kirsher } 15345a2cc190SJeff Kirsher 15355a2cc190SJeff Kirsher int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter) 15365a2cc190SJeff Kirsher { 15375a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 15385a2cc190SJeff Kirsher u32 *outbox; 15395a2cc190SJeff Kirsher int err; 15405a2cc190SJeff Kirsher 15415a2cc190SJeff Kirsher #define QUERY_ADAPTER_OUT_SIZE 0x100 15425a2cc190SJeff Kirsher #define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10 15435a2cc190SJeff Kirsher #define QUERY_ADAPTER_VSD_OFFSET 0x20 15445a2cc190SJeff Kirsher 15455a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 15465a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 15475a2cc190SJeff Kirsher return PTR_ERR(mailbox); 15485a2cc190SJeff Kirsher outbox = mailbox->buf; 15495a2cc190SJeff Kirsher 15505a2cc190SJeff Kirsher err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_ADAPTER, 1551f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 15525a2cc190SJeff Kirsher if (err) 15535a2cc190SJeff Kirsher goto out; 15545a2cc190SJeff Kirsher 15555a2cc190SJeff Kirsher MLX4_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET); 15565a2cc190SJeff Kirsher 15575a2cc190SJeff Kirsher get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4, 15585a2cc190SJeff Kirsher adapter->board_id); 15595a2cc190SJeff Kirsher 15605a2cc190SJeff Kirsher out: 15615a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 15625a2cc190SJeff Kirsher return err; 15635a2cc190SJeff Kirsher } 15645a2cc190SJeff Kirsher 15655a2cc190SJeff Kirsher int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) 15665a2cc190SJeff Kirsher { 15675a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 15685a2cc190SJeff Kirsher __be32 *inbox; 15695a2cc190SJeff Kirsher int err; 15707d077cd3SMatan Barak static const u8 a0_dmfs_hw_steering[] = { 15717d077cd3SMatan Barak [MLX4_STEERING_DMFS_A0_DEFAULT] = 0, 15727d077cd3SMatan Barak [MLX4_STEERING_DMFS_A0_DYNAMIC] = 1, 15737d077cd3SMatan Barak [MLX4_STEERING_DMFS_A0_STATIC] = 2, 15747d077cd3SMatan Barak [MLX4_STEERING_DMFS_A0_DISABLE] = 3 15757d077cd3SMatan Barak }; 15765a2cc190SJeff Kirsher 15775a2cc190SJeff Kirsher #define INIT_HCA_IN_SIZE 0x200 15785a2cc190SJeff Kirsher #define INIT_HCA_VERSION_OFFSET 0x000 15795a2cc190SJeff Kirsher #define INIT_HCA_VERSION 2 15807ffdf726SOr Gerlitz #define INIT_HCA_VXLAN_OFFSET 0x0c 15815a2cc190SJeff Kirsher #define INIT_HCA_CACHELINE_SZ_OFFSET 0x0e 15825a2cc190SJeff Kirsher #define INIT_HCA_FLAGS_OFFSET 0x014 1583be6a6b43SJack Morgenstein #define INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET 0x018 15845a2cc190SJeff Kirsher #define INIT_HCA_QPC_OFFSET 0x020 15855a2cc190SJeff Kirsher #define INIT_HCA_QPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x10) 15865a2cc190SJeff Kirsher #define INIT_HCA_LOG_QP_OFFSET (INIT_HCA_QPC_OFFSET + 0x17) 15875a2cc190SJeff Kirsher #define INIT_HCA_SRQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x28) 15885a2cc190SJeff Kirsher #define INIT_HCA_LOG_SRQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x2f) 15895a2cc190SJeff Kirsher #define INIT_HCA_CQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x30) 15905a2cc190SJeff Kirsher #define INIT_HCA_LOG_CQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x37) 15915cc914f1SMarcel Apfelbaum #define INIT_HCA_EQE_CQE_OFFSETS (INIT_HCA_QPC_OFFSET + 0x38) 159277507aa2SIdo Shamay #define INIT_HCA_EQE_CQE_STRIDE_OFFSET (INIT_HCA_QPC_OFFSET + 0x3b) 15935a2cc190SJeff Kirsher #define INIT_HCA_ALTC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x40) 15945a2cc190SJeff Kirsher #define INIT_HCA_AUXC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x50) 15955a2cc190SJeff Kirsher #define INIT_HCA_EQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x60) 15965a2cc190SJeff Kirsher #define INIT_HCA_LOG_EQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x67) 15977ae0e400SMatan Barak #define INIT_HCA_NUM_SYS_EQS_OFFSET (INIT_HCA_QPC_OFFSET + 0x6a) 15985a2cc190SJeff Kirsher #define INIT_HCA_RDMARC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x70) 15995a2cc190SJeff Kirsher #define INIT_HCA_LOG_RD_OFFSET (INIT_HCA_QPC_OFFSET + 0x77) 16005a2cc190SJeff Kirsher #define INIT_HCA_MCAST_OFFSET 0x0c0 16015a2cc190SJeff Kirsher #define INIT_HCA_MC_BASE_OFFSET (INIT_HCA_MCAST_OFFSET + 0x00) 16025a2cc190SJeff Kirsher #define INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12) 16035a2cc190SJeff Kirsher #define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16) 16045a2cc190SJeff Kirsher #define INIT_HCA_UC_STEERING_OFFSET (INIT_HCA_MCAST_OFFSET + 0x18) 16055a2cc190SJeff Kirsher #define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b) 16060ff1fb65SHadar Hen Zion #define INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN 0x6 16070ff1fb65SHadar Hen Zion #define INIT_HCA_FS_PARAM_OFFSET 0x1d0 16080ff1fb65SHadar Hen Zion #define INIT_HCA_FS_BASE_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x00) 16090ff1fb65SHadar Hen Zion #define INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x12) 16107d077cd3SMatan Barak #define INIT_HCA_FS_A0_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x18) 16110ff1fb65SHadar Hen Zion #define INIT_HCA_FS_LOG_TABLE_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x1b) 16120ff1fb65SHadar Hen Zion #define INIT_HCA_FS_ETH_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x21) 16130ff1fb65SHadar Hen Zion #define INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x22) 16140ff1fb65SHadar Hen Zion #define INIT_HCA_FS_IB_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x25) 16150ff1fb65SHadar Hen Zion #define INIT_HCA_FS_IB_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x26) 16165a2cc190SJeff Kirsher #define INIT_HCA_TPT_OFFSET 0x0f0 16175a2cc190SJeff Kirsher #define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00) 1618e448834eSShani Michaeli #define INIT_HCA_TPT_MW_OFFSET (INIT_HCA_TPT_OFFSET + 0x08) 16195a2cc190SJeff Kirsher #define INIT_HCA_LOG_MPT_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x0b) 16205a2cc190SJeff Kirsher #define INIT_HCA_MTT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x10) 16215a2cc190SJeff Kirsher #define INIT_HCA_CMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x18) 16225a2cc190SJeff Kirsher #define INIT_HCA_UAR_OFFSET 0x120 16235a2cc190SJeff Kirsher #define INIT_HCA_LOG_UAR_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0a) 16245a2cc190SJeff Kirsher #define INIT_HCA_UAR_PAGE_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0b) 16255a2cc190SJeff Kirsher 16265a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 16275a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 16285a2cc190SJeff Kirsher return PTR_ERR(mailbox); 16295a2cc190SJeff Kirsher inbox = mailbox->buf; 16305a2cc190SJeff Kirsher 16315a2cc190SJeff Kirsher *((u8 *) mailbox->buf + INIT_HCA_VERSION_OFFSET) = INIT_HCA_VERSION; 16325a2cc190SJeff Kirsher 16335a2cc190SJeff Kirsher *((u8 *) mailbox->buf + INIT_HCA_CACHELINE_SZ_OFFSET) = 16345a2cc190SJeff Kirsher (ilog2(cache_line_size()) - 4) << 5; 16355a2cc190SJeff Kirsher 16365a2cc190SJeff Kirsher #if defined(__LITTLE_ENDIAN) 16375a2cc190SJeff Kirsher *(inbox + INIT_HCA_FLAGS_OFFSET / 4) &= ~cpu_to_be32(1 << 1); 16385a2cc190SJeff Kirsher #elif defined(__BIG_ENDIAN) 16395a2cc190SJeff Kirsher *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 1); 16405a2cc190SJeff Kirsher #else 16415a2cc190SJeff Kirsher #error Host endianness not defined 16425a2cc190SJeff Kirsher #endif 16435a2cc190SJeff Kirsher /* Check port for UD address vector: */ 16445a2cc190SJeff Kirsher *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1); 16455a2cc190SJeff Kirsher 16465a2cc190SJeff Kirsher /* Enable IPoIB checksumming if we can: */ 16475a2cc190SJeff Kirsher if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM) 16485a2cc190SJeff Kirsher *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 3); 16495a2cc190SJeff Kirsher 16505a2cc190SJeff Kirsher /* Enable QoS support if module parameter set */ 16515a2cc190SJeff Kirsher if (enable_qos) 16525a2cc190SJeff Kirsher *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 2); 16535a2cc190SJeff Kirsher 16545a2cc190SJeff Kirsher /* enable counters */ 16555a2cc190SJeff Kirsher if (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS) 16565a2cc190SJeff Kirsher *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 4); 16575a2cc190SJeff Kirsher 165808ff3235SOr Gerlitz /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */ 165908ff3235SOr Gerlitz if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_EQE) { 166008ff3235SOr Gerlitz *(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 29); 166108ff3235SOr Gerlitz dev->caps.eqe_size = 64; 166208ff3235SOr Gerlitz dev->caps.eqe_factor = 1; 166308ff3235SOr Gerlitz } else { 166408ff3235SOr Gerlitz dev->caps.eqe_size = 32; 166508ff3235SOr Gerlitz dev->caps.eqe_factor = 0; 166608ff3235SOr Gerlitz } 166708ff3235SOr Gerlitz 166808ff3235SOr Gerlitz if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_CQE) { 166908ff3235SOr Gerlitz *(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 30); 167008ff3235SOr Gerlitz dev->caps.cqe_size = 64; 167177507aa2SIdo Shamay dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE; 167208ff3235SOr Gerlitz } else { 167308ff3235SOr Gerlitz dev->caps.cqe_size = 32; 167408ff3235SOr Gerlitz } 167508ff3235SOr Gerlitz 167677507aa2SIdo Shamay /* CX3 is capable of extending CQEs\EQEs to strides larger than 64B */ 167777507aa2SIdo Shamay if ((dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_EQE_STRIDE) && 167877507aa2SIdo Shamay (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_CQE_STRIDE)) { 167977507aa2SIdo Shamay dev->caps.eqe_size = cache_line_size(); 168077507aa2SIdo Shamay dev->caps.cqe_size = cache_line_size(); 168177507aa2SIdo Shamay dev->caps.eqe_factor = 0; 168277507aa2SIdo Shamay MLX4_PUT(inbox, (u8)((ilog2(dev->caps.eqe_size) - 5) << 4 | 168377507aa2SIdo Shamay (ilog2(dev->caps.eqe_size) - 5)), 168477507aa2SIdo Shamay INIT_HCA_EQE_CQE_STRIDE_OFFSET); 168577507aa2SIdo Shamay 168677507aa2SIdo Shamay /* User still need to know to support CQE > 32B */ 168777507aa2SIdo Shamay dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE; 168877507aa2SIdo Shamay } 168977507aa2SIdo Shamay 1690be6a6b43SJack Morgenstein if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT) 1691be6a6b43SJack Morgenstein *(inbox + INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET / 4) |= cpu_to_be32(1 << 31); 1692be6a6b43SJack Morgenstein 16935a2cc190SJeff Kirsher /* QPC/EEC/CQC/EQC/RDMARC attributes */ 16945a2cc190SJeff Kirsher 16955a2cc190SJeff Kirsher MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET); 16965a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_num_qps, INIT_HCA_LOG_QP_OFFSET); 16975a2cc190SJeff Kirsher MLX4_PUT(inbox, param->srqc_base, INIT_HCA_SRQC_BASE_OFFSET); 16985a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_num_srqs, INIT_HCA_LOG_SRQ_OFFSET); 16995a2cc190SJeff Kirsher MLX4_PUT(inbox, param->cqc_base, INIT_HCA_CQC_BASE_OFFSET); 17005a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_num_cqs, INIT_HCA_LOG_CQ_OFFSET); 17015a2cc190SJeff Kirsher MLX4_PUT(inbox, param->altc_base, INIT_HCA_ALTC_BASE_OFFSET); 17025a2cc190SJeff Kirsher MLX4_PUT(inbox, param->auxc_base, INIT_HCA_AUXC_BASE_OFFSET); 17035a2cc190SJeff Kirsher MLX4_PUT(inbox, param->eqc_base, INIT_HCA_EQC_BASE_OFFSET); 17045a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_num_eqs, INIT_HCA_LOG_EQ_OFFSET); 17057ae0e400SMatan Barak MLX4_PUT(inbox, param->num_sys_eqs, INIT_HCA_NUM_SYS_EQS_OFFSET); 17065a2cc190SJeff Kirsher MLX4_PUT(inbox, param->rdmarc_base, INIT_HCA_RDMARC_BASE_OFFSET); 17075a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_rd_per_qp, INIT_HCA_LOG_RD_OFFSET); 17085a2cc190SJeff Kirsher 17090ff1fb65SHadar Hen Zion /* steering attributes */ 17100ff1fb65SHadar Hen Zion if (dev->caps.steering_mode == 17110ff1fb65SHadar Hen Zion MLX4_STEERING_MODE_DEVICE_MANAGED) { 17120ff1fb65SHadar Hen Zion *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= 17130ff1fb65SHadar Hen Zion cpu_to_be32(1 << 17140ff1fb65SHadar Hen Zion INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN); 17155a2cc190SJeff Kirsher 17160ff1fb65SHadar Hen Zion MLX4_PUT(inbox, param->mc_base, INIT_HCA_FS_BASE_OFFSET); 17170ff1fb65SHadar Hen Zion MLX4_PUT(inbox, param->log_mc_entry_sz, 17180ff1fb65SHadar Hen Zion INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); 17190ff1fb65SHadar Hen Zion MLX4_PUT(inbox, param->log_mc_table_sz, 17200ff1fb65SHadar Hen Zion INIT_HCA_FS_LOG_TABLE_SZ_OFFSET); 17210ff1fb65SHadar Hen Zion /* Enable Ethernet flow steering 17220ff1fb65SHadar Hen Zion * with udp unicast and tcp unicast 17230ff1fb65SHadar Hen Zion */ 17247d077cd3SMatan Barak if (dev->caps.dmfs_high_steer_mode != 17257d077cd3SMatan Barak MLX4_STEERING_DMFS_A0_STATIC) 17267d077cd3SMatan Barak MLX4_PUT(inbox, 17277d077cd3SMatan Barak (u8)(MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN), 17280ff1fb65SHadar Hen Zion INIT_HCA_FS_ETH_BITS_OFFSET); 17290ff1fb65SHadar Hen Zion MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, 17300ff1fb65SHadar Hen Zion INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET); 17310ff1fb65SHadar Hen Zion /* Enable IPoIB flow steering 17320ff1fb65SHadar Hen Zion * with udp unicast and tcp unicast 17330ff1fb65SHadar Hen Zion */ 173423537b73SHadar Hen Zion MLX4_PUT(inbox, (u8) (MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN), 17350ff1fb65SHadar Hen Zion INIT_HCA_FS_IB_BITS_OFFSET); 17360ff1fb65SHadar Hen Zion MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, 17370ff1fb65SHadar Hen Zion INIT_HCA_FS_IB_NUM_ADDRS_OFFSET); 17387d077cd3SMatan Barak 17397d077cd3SMatan Barak if (dev->caps.dmfs_high_steer_mode != 17407d077cd3SMatan Barak MLX4_STEERING_DMFS_A0_NOT_SUPPORTED) 17417d077cd3SMatan Barak MLX4_PUT(inbox, 17427d077cd3SMatan Barak ((u8)(a0_dmfs_hw_steering[dev->caps.dmfs_high_steer_mode] 17437d077cd3SMatan Barak << 6)), 17447d077cd3SMatan Barak INIT_HCA_FS_A0_OFFSET); 17450ff1fb65SHadar Hen Zion } else { 17465a2cc190SJeff Kirsher MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET); 17470ff1fb65SHadar Hen Zion MLX4_PUT(inbox, param->log_mc_entry_sz, 17480ff1fb65SHadar Hen Zion INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); 17490ff1fb65SHadar Hen Zion MLX4_PUT(inbox, param->log_mc_hash_sz, 17500ff1fb65SHadar Hen Zion INIT_HCA_LOG_MC_HASH_SZ_OFFSET); 17510ff1fb65SHadar Hen Zion MLX4_PUT(inbox, param->log_mc_table_sz, 17520ff1fb65SHadar Hen Zion INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); 1753c96d97f4SHadar Hen Zion if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0) 17540ff1fb65SHadar Hen Zion MLX4_PUT(inbox, (u8) (1 << 3), 17550ff1fb65SHadar Hen Zion INIT_HCA_UC_STEERING_OFFSET); 17560ff1fb65SHadar Hen Zion } 17575a2cc190SJeff Kirsher 17585a2cc190SJeff Kirsher /* TPT attributes */ 17595a2cc190SJeff Kirsher 17605a2cc190SJeff Kirsher MLX4_PUT(inbox, param->dmpt_base, INIT_HCA_DMPT_BASE_OFFSET); 1761e448834eSShani Michaeli MLX4_PUT(inbox, param->mw_enabled, INIT_HCA_TPT_MW_OFFSET); 17625a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_mpt_sz, INIT_HCA_LOG_MPT_SZ_OFFSET); 17635a2cc190SJeff Kirsher MLX4_PUT(inbox, param->mtt_base, INIT_HCA_MTT_BASE_OFFSET); 17645a2cc190SJeff Kirsher MLX4_PUT(inbox, param->cmpt_base, INIT_HCA_CMPT_BASE_OFFSET); 17655a2cc190SJeff Kirsher 17665a2cc190SJeff Kirsher /* UAR attributes */ 17675a2cc190SJeff Kirsher 1768ab9c17a0SJack Morgenstein MLX4_PUT(inbox, param->uar_page_sz, INIT_HCA_UAR_PAGE_SZ_OFFSET); 17695a2cc190SJeff Kirsher MLX4_PUT(inbox, param->log_uar_sz, INIT_HCA_LOG_UAR_SZ_OFFSET); 17705a2cc190SJeff Kirsher 17717ffdf726SOr Gerlitz /* set parser VXLAN attributes */ 17727ffdf726SOr Gerlitz if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS) { 17737ffdf726SOr Gerlitz u8 parser_params = 0; 17747ffdf726SOr Gerlitz MLX4_PUT(inbox, parser_params, INIT_HCA_VXLAN_OFFSET); 17757ffdf726SOr Gerlitz } 17767ffdf726SOr Gerlitz 1777f9baff50SJack Morgenstein err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA, 10000, 1778f9baff50SJack Morgenstein MLX4_CMD_NATIVE); 17795a2cc190SJeff Kirsher 17805a2cc190SJeff Kirsher if (err) 17815a2cc190SJeff Kirsher mlx4_err(dev, "INIT_HCA returns %d\n", err); 17825a2cc190SJeff Kirsher 17835a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 17845a2cc190SJeff Kirsher return err; 17855a2cc190SJeff Kirsher } 17865a2cc190SJeff Kirsher 1787ab9c17a0SJack Morgenstein int mlx4_QUERY_HCA(struct mlx4_dev *dev, 1788ab9c17a0SJack Morgenstein struct mlx4_init_hca_param *param) 1789ab9c17a0SJack Morgenstein { 1790ab9c17a0SJack Morgenstein struct mlx4_cmd_mailbox *mailbox; 1791ab9c17a0SJack Morgenstein __be32 *outbox; 17927b8157beSJack Morgenstein u32 dword_field; 1793ab9c17a0SJack Morgenstein int err; 179408ff3235SOr Gerlitz u8 byte_field; 17957d077cd3SMatan Barak static const u8 a0_dmfs_query_hw_steering[] = { 17967d077cd3SMatan Barak [0] = MLX4_STEERING_DMFS_A0_DEFAULT, 17977d077cd3SMatan Barak [1] = MLX4_STEERING_DMFS_A0_DYNAMIC, 17987d077cd3SMatan Barak [2] = MLX4_STEERING_DMFS_A0_STATIC, 17997d077cd3SMatan Barak [3] = MLX4_STEERING_DMFS_A0_DISABLE 18007d077cd3SMatan Barak }; 1801ab9c17a0SJack Morgenstein 1802ab9c17a0SJack Morgenstein #define QUERY_HCA_GLOBAL_CAPS_OFFSET 0x04 1803ddd8a6c1SEugenia Emantayev #define QUERY_HCA_CORE_CLOCK_OFFSET 0x0c 1804ab9c17a0SJack Morgenstein 1805ab9c17a0SJack Morgenstein mailbox = mlx4_alloc_cmd_mailbox(dev); 1806ab9c17a0SJack Morgenstein if (IS_ERR(mailbox)) 1807ab9c17a0SJack Morgenstein return PTR_ERR(mailbox); 1808ab9c17a0SJack Morgenstein outbox = mailbox->buf; 1809ab9c17a0SJack Morgenstein 1810ab9c17a0SJack Morgenstein err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, 1811ab9c17a0SJack Morgenstein MLX4_CMD_QUERY_HCA, 1812ab9c17a0SJack Morgenstein MLX4_CMD_TIME_CLASS_B, 1813ab9c17a0SJack Morgenstein !mlx4_is_slave(dev)); 1814ab9c17a0SJack Morgenstein if (err) 1815ab9c17a0SJack Morgenstein goto out; 1816ab9c17a0SJack Morgenstein 1817ab9c17a0SJack Morgenstein MLX4_GET(param->global_caps, outbox, QUERY_HCA_GLOBAL_CAPS_OFFSET); 1818ddd8a6c1SEugenia Emantayev MLX4_GET(param->hca_core_clock, outbox, QUERY_HCA_CORE_CLOCK_OFFSET); 1819ab9c17a0SJack Morgenstein 1820ab9c17a0SJack Morgenstein /* QPC/EEC/CQC/EQC/RDMARC attributes */ 1821ab9c17a0SJack Morgenstein 1822ab9c17a0SJack Morgenstein MLX4_GET(param->qpc_base, outbox, INIT_HCA_QPC_BASE_OFFSET); 1823ab9c17a0SJack Morgenstein MLX4_GET(param->log_num_qps, outbox, INIT_HCA_LOG_QP_OFFSET); 1824ab9c17a0SJack Morgenstein MLX4_GET(param->srqc_base, outbox, INIT_HCA_SRQC_BASE_OFFSET); 1825ab9c17a0SJack Morgenstein MLX4_GET(param->log_num_srqs, outbox, INIT_HCA_LOG_SRQ_OFFSET); 1826ab9c17a0SJack Morgenstein MLX4_GET(param->cqc_base, outbox, INIT_HCA_CQC_BASE_OFFSET); 1827ab9c17a0SJack Morgenstein MLX4_GET(param->log_num_cqs, outbox, INIT_HCA_LOG_CQ_OFFSET); 1828ab9c17a0SJack Morgenstein MLX4_GET(param->altc_base, outbox, INIT_HCA_ALTC_BASE_OFFSET); 1829ab9c17a0SJack Morgenstein MLX4_GET(param->auxc_base, outbox, INIT_HCA_AUXC_BASE_OFFSET); 1830ab9c17a0SJack Morgenstein MLX4_GET(param->eqc_base, outbox, INIT_HCA_EQC_BASE_OFFSET); 1831ab9c17a0SJack Morgenstein MLX4_GET(param->log_num_eqs, outbox, INIT_HCA_LOG_EQ_OFFSET); 18327ae0e400SMatan Barak MLX4_GET(param->num_sys_eqs, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET); 1833ab9c17a0SJack Morgenstein MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET); 1834ab9c17a0SJack Morgenstein MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET); 1835ab9c17a0SJack Morgenstein 18367b8157beSJack Morgenstein MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET); 18377b8157beSJack Morgenstein if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) { 18387b8157beSJack Morgenstein param->steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; 18397b8157beSJack Morgenstein } else { 18407b8157beSJack Morgenstein MLX4_GET(byte_field, outbox, INIT_HCA_UC_STEERING_OFFSET); 18417b8157beSJack Morgenstein if (byte_field & 0x8) 18427b8157beSJack Morgenstein param->steering_mode = MLX4_STEERING_MODE_B0; 18437b8157beSJack Morgenstein else 18447b8157beSJack Morgenstein param->steering_mode = MLX4_STEERING_MODE_A0; 18457b8157beSJack Morgenstein } 18460ff1fb65SHadar Hen Zion /* steering attributes */ 18477b8157beSJack Morgenstein if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { 18480ff1fb65SHadar Hen Zion MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET); 18490ff1fb65SHadar Hen Zion MLX4_GET(param->log_mc_entry_sz, outbox, 18500ff1fb65SHadar Hen Zion INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); 18510ff1fb65SHadar Hen Zion MLX4_GET(param->log_mc_table_sz, outbox, 18520ff1fb65SHadar Hen Zion INIT_HCA_FS_LOG_TABLE_SZ_OFFSET); 18537d077cd3SMatan Barak MLX4_GET(byte_field, outbox, 18547d077cd3SMatan Barak INIT_HCA_FS_A0_OFFSET); 18557d077cd3SMatan Barak param->dmfs_high_steer_mode = 18567d077cd3SMatan Barak a0_dmfs_query_hw_steering[(byte_field >> 6) & 3]; 18570ff1fb65SHadar Hen Zion } else { 1858ab9c17a0SJack Morgenstein MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET); 1859ab9c17a0SJack Morgenstein MLX4_GET(param->log_mc_entry_sz, outbox, 1860ab9c17a0SJack Morgenstein INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); 1861ab9c17a0SJack Morgenstein MLX4_GET(param->log_mc_hash_sz, outbox, 1862ab9c17a0SJack Morgenstein INIT_HCA_LOG_MC_HASH_SZ_OFFSET); 1863ab9c17a0SJack Morgenstein MLX4_GET(param->log_mc_table_sz, outbox, 1864ab9c17a0SJack Morgenstein INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); 18650ff1fb65SHadar Hen Zion } 1866ab9c17a0SJack Morgenstein 186708ff3235SOr Gerlitz /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */ 186808ff3235SOr Gerlitz MLX4_GET(byte_field, outbox, INIT_HCA_EQE_CQE_OFFSETS); 186908ff3235SOr Gerlitz if (byte_field & 0x20) /* 64-bytes eqe enabled */ 187008ff3235SOr Gerlitz param->dev_cap_enabled |= MLX4_DEV_CAP_64B_EQE_ENABLED; 187108ff3235SOr Gerlitz if (byte_field & 0x40) /* 64-bytes cqe enabled */ 187208ff3235SOr Gerlitz param->dev_cap_enabled |= MLX4_DEV_CAP_64B_CQE_ENABLED; 187308ff3235SOr Gerlitz 187477507aa2SIdo Shamay /* CX3 is capable of extending CQEs\EQEs to strides larger than 64B */ 187577507aa2SIdo Shamay MLX4_GET(byte_field, outbox, INIT_HCA_EQE_CQE_STRIDE_OFFSET); 187677507aa2SIdo Shamay if (byte_field) { 1877c3f2511fSIdo Shamay param->dev_cap_enabled |= MLX4_DEV_CAP_EQE_STRIDE_ENABLED; 1878c3f2511fSIdo Shamay param->dev_cap_enabled |= MLX4_DEV_CAP_CQE_STRIDE_ENABLED; 187977507aa2SIdo Shamay param->cqe_size = 1 << ((byte_field & 188077507aa2SIdo Shamay MLX4_CQE_SIZE_MASK_STRIDE) + 5); 188177507aa2SIdo Shamay param->eqe_size = 1 << (((byte_field & 188277507aa2SIdo Shamay MLX4_EQE_SIZE_MASK_STRIDE) >> 4) + 5); 188377507aa2SIdo Shamay } 188477507aa2SIdo Shamay 1885ab9c17a0SJack Morgenstein /* TPT attributes */ 1886ab9c17a0SJack Morgenstein 1887ab9c17a0SJack Morgenstein MLX4_GET(param->dmpt_base, outbox, INIT_HCA_DMPT_BASE_OFFSET); 1888e448834eSShani Michaeli MLX4_GET(param->mw_enabled, outbox, INIT_HCA_TPT_MW_OFFSET); 1889ab9c17a0SJack Morgenstein MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET); 1890ab9c17a0SJack Morgenstein MLX4_GET(param->mtt_base, outbox, INIT_HCA_MTT_BASE_OFFSET); 1891ab9c17a0SJack Morgenstein MLX4_GET(param->cmpt_base, outbox, INIT_HCA_CMPT_BASE_OFFSET); 1892ab9c17a0SJack Morgenstein 1893ab9c17a0SJack Morgenstein /* UAR attributes */ 1894ab9c17a0SJack Morgenstein 1895ab9c17a0SJack Morgenstein MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET); 1896ab9c17a0SJack Morgenstein MLX4_GET(param->log_uar_sz, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET); 1897ab9c17a0SJack Morgenstein 1898ab9c17a0SJack Morgenstein out: 1899ab9c17a0SJack Morgenstein mlx4_free_cmd_mailbox(dev, mailbox); 1900ab9c17a0SJack Morgenstein 1901ab9c17a0SJack Morgenstein return err; 1902ab9c17a0SJack Morgenstein } 1903ab9c17a0SJack Morgenstein 1904980e9001SJack Morgenstein /* for IB-type ports only in SRIOV mode. Checks that both proxy QP0 1905980e9001SJack Morgenstein * and real QP0 are active, so that the paravirtualized QP0 is ready 1906980e9001SJack Morgenstein * to operate */ 1907980e9001SJack Morgenstein static int check_qp0_state(struct mlx4_dev *dev, int function, int port) 1908980e9001SJack Morgenstein { 1909980e9001SJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 1910980e9001SJack Morgenstein /* irrelevant if not infiniband */ 1911980e9001SJack Morgenstein if (priv->mfunc.master.qp0_state[port].proxy_qp0_active && 1912980e9001SJack Morgenstein priv->mfunc.master.qp0_state[port].qp0_active) 1913980e9001SJack Morgenstein return 1; 1914980e9001SJack Morgenstein return 0; 1915980e9001SJack Morgenstein } 1916980e9001SJack Morgenstein 19175cc914f1SMarcel Apfelbaum int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave, 19185cc914f1SMarcel Apfelbaum struct mlx4_vhcr *vhcr, 19195cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *inbox, 19205cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *outbox, 19215cc914f1SMarcel Apfelbaum struct mlx4_cmd_info *cmd) 19225cc914f1SMarcel Apfelbaum { 19235cc914f1SMarcel Apfelbaum struct mlx4_priv *priv = mlx4_priv(dev); 1924449fc488SMatan Barak int port = mlx4_slave_convert_port(dev, slave, vhcr->in_modifier); 19255cc914f1SMarcel Apfelbaum int err; 19265cc914f1SMarcel Apfelbaum 1927449fc488SMatan Barak if (port < 0) 1928449fc488SMatan Barak return -EINVAL; 1929449fc488SMatan Barak 19305cc914f1SMarcel Apfelbaum if (priv->mfunc.master.slave_state[slave].init_port_mask & (1 << port)) 19315cc914f1SMarcel Apfelbaum return 0; 19325cc914f1SMarcel Apfelbaum 1933980e9001SJack Morgenstein if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB) { 19345cc914f1SMarcel Apfelbaum /* Enable port only if it was previously disabled */ 19355cc914f1SMarcel Apfelbaum if (!priv->mfunc.master.init_port_ref[port]) { 19365cc914f1SMarcel Apfelbaum err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT, 19375cc914f1SMarcel Apfelbaum MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 19385cc914f1SMarcel Apfelbaum if (err) 19395cc914f1SMarcel Apfelbaum return err; 19405cc914f1SMarcel Apfelbaum } 19418bac9edeSJack Morgenstein priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port); 1942980e9001SJack Morgenstein } else { 1943980e9001SJack Morgenstein if (slave == mlx4_master_func_num(dev)) { 1944980e9001SJack Morgenstein if (check_qp0_state(dev, slave, port) && 1945980e9001SJack Morgenstein !priv->mfunc.master.qp0_state[port].port_active) { 1946980e9001SJack Morgenstein err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT, 1947980e9001SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 1948980e9001SJack Morgenstein if (err) 1949980e9001SJack Morgenstein return err; 1950980e9001SJack Morgenstein priv->mfunc.master.qp0_state[port].port_active = 1; 1951980e9001SJack Morgenstein priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port); 1952980e9001SJack Morgenstein } 1953980e9001SJack Morgenstein } else 1954980e9001SJack Morgenstein priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port); 1955980e9001SJack Morgenstein } 19565cc914f1SMarcel Apfelbaum ++priv->mfunc.master.init_port_ref[port]; 19575cc914f1SMarcel Apfelbaum return 0; 19585cc914f1SMarcel Apfelbaum } 19595cc914f1SMarcel Apfelbaum 19605a2cc190SJeff Kirsher int mlx4_INIT_PORT(struct mlx4_dev *dev, int port) 19615a2cc190SJeff Kirsher { 19625a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 19635a2cc190SJeff Kirsher u32 *inbox; 19645a2cc190SJeff Kirsher int err; 19655a2cc190SJeff Kirsher u32 flags; 19665a2cc190SJeff Kirsher u16 field; 19675a2cc190SJeff Kirsher 19685a2cc190SJeff Kirsher if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 19695a2cc190SJeff Kirsher #define INIT_PORT_IN_SIZE 256 19705a2cc190SJeff Kirsher #define INIT_PORT_FLAGS_OFFSET 0x00 19715a2cc190SJeff Kirsher #define INIT_PORT_FLAG_SIG (1 << 18) 19725a2cc190SJeff Kirsher #define INIT_PORT_FLAG_NG (1 << 17) 19735a2cc190SJeff Kirsher #define INIT_PORT_FLAG_G0 (1 << 16) 19745a2cc190SJeff Kirsher #define INIT_PORT_VL_SHIFT 4 19755a2cc190SJeff Kirsher #define INIT_PORT_PORT_WIDTH_SHIFT 8 19765a2cc190SJeff Kirsher #define INIT_PORT_MTU_OFFSET 0x04 19775a2cc190SJeff Kirsher #define INIT_PORT_MAX_GID_OFFSET 0x06 19785a2cc190SJeff Kirsher #define INIT_PORT_MAX_PKEY_OFFSET 0x0a 19795a2cc190SJeff Kirsher #define INIT_PORT_GUID0_OFFSET 0x10 19805a2cc190SJeff Kirsher #define INIT_PORT_NODE_GUID_OFFSET 0x18 19815a2cc190SJeff Kirsher #define INIT_PORT_SI_GUID_OFFSET 0x20 19825a2cc190SJeff Kirsher 19835a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 19845a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 19855a2cc190SJeff Kirsher return PTR_ERR(mailbox); 19865a2cc190SJeff Kirsher inbox = mailbox->buf; 19875a2cc190SJeff Kirsher 19885a2cc190SJeff Kirsher flags = 0; 19895a2cc190SJeff Kirsher flags |= (dev->caps.vl_cap[port] & 0xf) << INIT_PORT_VL_SHIFT; 19905a2cc190SJeff Kirsher flags |= (dev->caps.port_width_cap[port] & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT; 19915a2cc190SJeff Kirsher MLX4_PUT(inbox, flags, INIT_PORT_FLAGS_OFFSET); 19925a2cc190SJeff Kirsher 19935a2cc190SJeff Kirsher field = 128 << dev->caps.ib_mtu_cap[port]; 19945a2cc190SJeff Kirsher MLX4_PUT(inbox, field, INIT_PORT_MTU_OFFSET); 19955a2cc190SJeff Kirsher field = dev->caps.gid_table_len[port]; 19965a2cc190SJeff Kirsher MLX4_PUT(inbox, field, INIT_PORT_MAX_GID_OFFSET); 19975a2cc190SJeff Kirsher field = dev->caps.pkey_table_len[port]; 19985a2cc190SJeff Kirsher MLX4_PUT(inbox, field, INIT_PORT_MAX_PKEY_OFFSET); 19995a2cc190SJeff Kirsher 20005a2cc190SJeff Kirsher err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT, 2001f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 20025a2cc190SJeff Kirsher 20035a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 20045a2cc190SJeff Kirsher } else 20055a2cc190SJeff Kirsher err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT, 2006f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 20075a2cc190SJeff Kirsher 20085a2cc190SJeff Kirsher return err; 20095a2cc190SJeff Kirsher } 20105a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_INIT_PORT); 20115a2cc190SJeff Kirsher 20125cc914f1SMarcel Apfelbaum int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave, 20135cc914f1SMarcel Apfelbaum struct mlx4_vhcr *vhcr, 20145cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *inbox, 20155cc914f1SMarcel Apfelbaum struct mlx4_cmd_mailbox *outbox, 20165cc914f1SMarcel Apfelbaum struct mlx4_cmd_info *cmd) 20175cc914f1SMarcel Apfelbaum { 20185cc914f1SMarcel Apfelbaum struct mlx4_priv *priv = mlx4_priv(dev); 2019449fc488SMatan Barak int port = mlx4_slave_convert_port(dev, slave, vhcr->in_modifier); 20205cc914f1SMarcel Apfelbaum int err; 20215cc914f1SMarcel Apfelbaum 2022449fc488SMatan Barak if (port < 0) 2023449fc488SMatan Barak return -EINVAL; 2024449fc488SMatan Barak 20255cc914f1SMarcel Apfelbaum if (!(priv->mfunc.master.slave_state[slave].init_port_mask & 20265cc914f1SMarcel Apfelbaum (1 << port))) 20275cc914f1SMarcel Apfelbaum return 0; 20285cc914f1SMarcel Apfelbaum 2029980e9001SJack Morgenstein if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB) { 20305cc914f1SMarcel Apfelbaum if (priv->mfunc.master.init_port_ref[port] == 1) { 2031980e9001SJack Morgenstein err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 2032980e9001SJack Morgenstein 1000, MLX4_CMD_NATIVE); 20335cc914f1SMarcel Apfelbaum if (err) 20345cc914f1SMarcel Apfelbaum return err; 20355cc914f1SMarcel Apfelbaum } 20365cc914f1SMarcel Apfelbaum priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port); 2037980e9001SJack Morgenstein } else { 2038980e9001SJack Morgenstein /* infiniband port */ 2039980e9001SJack Morgenstein if (slave == mlx4_master_func_num(dev)) { 2040980e9001SJack Morgenstein if (!priv->mfunc.master.qp0_state[port].qp0_active && 2041980e9001SJack Morgenstein priv->mfunc.master.qp0_state[port].port_active) { 2042980e9001SJack Morgenstein err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 2043980e9001SJack Morgenstein 1000, MLX4_CMD_NATIVE); 2044980e9001SJack Morgenstein if (err) 2045980e9001SJack Morgenstein return err; 2046980e9001SJack Morgenstein priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port); 2047980e9001SJack Morgenstein priv->mfunc.master.qp0_state[port].port_active = 0; 2048980e9001SJack Morgenstein } 2049980e9001SJack Morgenstein } else 2050980e9001SJack Morgenstein priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port); 2051980e9001SJack Morgenstein } 20525cc914f1SMarcel Apfelbaum --priv->mfunc.master.init_port_ref[port]; 20535cc914f1SMarcel Apfelbaum return 0; 20545cc914f1SMarcel Apfelbaum } 20555cc914f1SMarcel Apfelbaum 20565a2cc190SJeff Kirsher int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port) 20575a2cc190SJeff Kirsher { 2058f9baff50SJack Morgenstein return mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000, 2059f9baff50SJack Morgenstein MLX4_CMD_WRAPPED); 20605a2cc190SJeff Kirsher } 20615a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_CLOSE_PORT); 20625a2cc190SJeff Kirsher 20635a2cc190SJeff Kirsher int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic) 20645a2cc190SJeff Kirsher { 2065f9baff50SJack Morgenstein return mlx4_cmd(dev, 0, 0, panic, MLX4_CMD_CLOSE_HCA, 1000, 2066f9baff50SJack Morgenstein MLX4_CMD_NATIVE); 20675a2cc190SJeff Kirsher } 20685a2cc190SJeff Kirsher 2069d18f141aSOr Gerlitz struct mlx4_config_dev { 2070d18f141aSOr Gerlitz __be32 update_flags; 2071d475c95bSMatan Barak __be32 rsvd1[3]; 2072d18f141aSOr Gerlitz __be16 vxlan_udp_dport; 2073d18f141aSOr Gerlitz __be16 rsvd2; 2074d475c95bSMatan Barak __be32 rsvd3[27]; 2075d475c95bSMatan Barak __be16 rsvd4; 2076d475c95bSMatan Barak u8 rsvd5; 2077d475c95bSMatan Barak u8 rx_checksum_val; 2078d18f141aSOr Gerlitz }; 2079d18f141aSOr Gerlitz 2080d18f141aSOr Gerlitz #define MLX4_VXLAN_UDP_DPORT (1 << 0) 2081d18f141aSOr Gerlitz 2082d475c95bSMatan Barak static int mlx4_CONFIG_DEV_set(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev) 2083d18f141aSOr Gerlitz { 2084d18f141aSOr Gerlitz int err; 2085d18f141aSOr Gerlitz struct mlx4_cmd_mailbox *mailbox; 2086d18f141aSOr Gerlitz 2087d18f141aSOr Gerlitz mailbox = mlx4_alloc_cmd_mailbox(dev); 2088d18f141aSOr Gerlitz if (IS_ERR(mailbox)) 2089d18f141aSOr Gerlitz return PTR_ERR(mailbox); 2090d18f141aSOr Gerlitz 2091d18f141aSOr Gerlitz memcpy(mailbox->buf, config_dev, sizeof(*config_dev)); 2092d18f141aSOr Gerlitz 2093d18f141aSOr Gerlitz err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_CONFIG_DEV, 2094d18f141aSOr Gerlitz MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 2095d18f141aSOr Gerlitz 2096d18f141aSOr Gerlitz mlx4_free_cmd_mailbox(dev, mailbox); 2097d18f141aSOr Gerlitz return err; 2098d18f141aSOr Gerlitz } 2099d18f141aSOr Gerlitz 2100d475c95bSMatan Barak static int mlx4_CONFIG_DEV_get(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev) 2101d475c95bSMatan Barak { 2102d475c95bSMatan Barak int err; 2103d475c95bSMatan Barak struct mlx4_cmd_mailbox *mailbox; 2104d475c95bSMatan Barak 2105d475c95bSMatan Barak mailbox = mlx4_alloc_cmd_mailbox(dev); 2106d475c95bSMatan Barak if (IS_ERR(mailbox)) 2107d475c95bSMatan Barak return PTR_ERR(mailbox); 2108d475c95bSMatan Barak 2109d475c95bSMatan Barak err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 1, MLX4_CMD_CONFIG_DEV, 2110d475c95bSMatan Barak MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 2111d475c95bSMatan Barak 2112d475c95bSMatan Barak if (!err) 2113d475c95bSMatan Barak memcpy(config_dev, mailbox->buf, sizeof(*config_dev)); 2114d475c95bSMatan Barak 2115d475c95bSMatan Barak mlx4_free_cmd_mailbox(dev, mailbox); 2116d475c95bSMatan Barak return err; 2117d475c95bSMatan Barak } 2118d475c95bSMatan Barak 2119d475c95bSMatan Barak /* Conversion between the HW values and the actual functionality. 2120d475c95bSMatan Barak * The value represented by the array index, 2121d475c95bSMatan Barak * and the functionality determined by the flags. 2122d475c95bSMatan Barak */ 2123d475c95bSMatan Barak static const u8 config_dev_csum_flags[] = { 2124d475c95bSMatan Barak [0] = 0, 2125d475c95bSMatan Barak [1] = MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP, 2126d475c95bSMatan Barak [2] = MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP | 2127d475c95bSMatan Barak MLX4_RX_CSUM_MODE_L4, 2128d475c95bSMatan Barak [3] = MLX4_RX_CSUM_MODE_L4 | 2129d475c95bSMatan Barak MLX4_RX_CSUM_MODE_IP_OK_IP_NON_TCP_UDP | 2130d475c95bSMatan Barak MLX4_RX_CSUM_MODE_MULTI_VLAN 2131d475c95bSMatan Barak }; 2132d475c95bSMatan Barak 2133d475c95bSMatan Barak int mlx4_config_dev_retrieval(struct mlx4_dev *dev, 2134d475c95bSMatan Barak struct mlx4_config_dev_params *params) 2135d475c95bSMatan Barak { 2136d475c95bSMatan Barak struct mlx4_config_dev config_dev; 2137d475c95bSMatan Barak int err; 2138d475c95bSMatan Barak u8 csum_mask; 2139d475c95bSMatan Barak 2140d475c95bSMatan Barak #define CONFIG_DEV_RX_CSUM_MODE_MASK 0x7 2141d475c95bSMatan Barak #define CONFIG_DEV_RX_CSUM_MODE_PORT1_BIT_OFFSET 0 2142d475c95bSMatan Barak #define CONFIG_DEV_RX_CSUM_MODE_PORT2_BIT_OFFSET 4 2143d475c95bSMatan Barak 2144d475c95bSMatan Barak if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_CONFIG_DEV)) 2145d475c95bSMatan Barak return -ENOTSUPP; 2146d475c95bSMatan Barak 2147d475c95bSMatan Barak err = mlx4_CONFIG_DEV_get(dev, &config_dev); 2148d475c95bSMatan Barak if (err) 2149d475c95bSMatan Barak return err; 2150d475c95bSMatan Barak 2151d475c95bSMatan Barak csum_mask = (config_dev.rx_checksum_val >> CONFIG_DEV_RX_CSUM_MODE_PORT1_BIT_OFFSET) & 2152d475c95bSMatan Barak CONFIG_DEV_RX_CSUM_MODE_MASK; 2153d475c95bSMatan Barak 2154d475c95bSMatan Barak if (csum_mask >= sizeof(config_dev_csum_flags)/sizeof(config_dev_csum_flags[0])) 2155d475c95bSMatan Barak return -EINVAL; 2156d475c95bSMatan Barak params->rx_csum_flags_port_1 = config_dev_csum_flags[csum_mask]; 2157d475c95bSMatan Barak 2158d475c95bSMatan Barak csum_mask = (config_dev.rx_checksum_val >> CONFIG_DEV_RX_CSUM_MODE_PORT2_BIT_OFFSET) & 2159d475c95bSMatan Barak CONFIG_DEV_RX_CSUM_MODE_MASK; 2160d475c95bSMatan Barak 2161d475c95bSMatan Barak if (csum_mask >= sizeof(config_dev_csum_flags)/sizeof(config_dev_csum_flags[0])) 2162d475c95bSMatan Barak return -EINVAL; 2163d475c95bSMatan Barak params->rx_csum_flags_port_2 = config_dev_csum_flags[csum_mask]; 2164d475c95bSMatan Barak 2165d475c95bSMatan Barak params->vxlan_udp_dport = be16_to_cpu(config_dev.vxlan_udp_dport); 2166d475c95bSMatan Barak 2167d475c95bSMatan Barak return 0; 2168d475c95bSMatan Barak } 2169d475c95bSMatan Barak EXPORT_SYMBOL_GPL(mlx4_config_dev_retrieval); 2170d475c95bSMatan Barak 2171d18f141aSOr Gerlitz int mlx4_config_vxlan_port(struct mlx4_dev *dev, __be16 udp_port) 2172d18f141aSOr Gerlitz { 2173d18f141aSOr Gerlitz struct mlx4_config_dev config_dev; 2174d18f141aSOr Gerlitz 2175d18f141aSOr Gerlitz memset(&config_dev, 0, sizeof(config_dev)); 2176d18f141aSOr Gerlitz config_dev.update_flags = cpu_to_be32(MLX4_VXLAN_UDP_DPORT); 2177d18f141aSOr Gerlitz config_dev.vxlan_udp_dport = udp_port; 2178d18f141aSOr Gerlitz 2179d475c95bSMatan Barak return mlx4_CONFIG_DEV_set(dev, &config_dev); 2180d18f141aSOr Gerlitz } 2181d18f141aSOr Gerlitz EXPORT_SYMBOL_GPL(mlx4_config_vxlan_port); 2182d18f141aSOr Gerlitz 2183d18f141aSOr Gerlitz 21845a2cc190SJeff Kirsher int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages) 21855a2cc190SJeff Kirsher { 21865a2cc190SJeff Kirsher int ret = mlx4_cmd_imm(dev, icm_size, aux_pages, 0, 0, 21875a2cc190SJeff Kirsher MLX4_CMD_SET_ICM_SIZE, 2188f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 21895a2cc190SJeff Kirsher if (ret) 21905a2cc190SJeff Kirsher return ret; 21915a2cc190SJeff Kirsher 21925a2cc190SJeff Kirsher /* 21935a2cc190SJeff Kirsher * Round up number of system pages needed in case 21945a2cc190SJeff Kirsher * MLX4_ICM_PAGE_SIZE < PAGE_SIZE. 21955a2cc190SJeff Kirsher */ 21965a2cc190SJeff Kirsher *aux_pages = ALIGN(*aux_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >> 21975a2cc190SJeff Kirsher (PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT); 21985a2cc190SJeff Kirsher 21995a2cc190SJeff Kirsher return 0; 22005a2cc190SJeff Kirsher } 22015a2cc190SJeff Kirsher 22025a2cc190SJeff Kirsher int mlx4_NOP(struct mlx4_dev *dev) 22035a2cc190SJeff Kirsher { 22045a2cc190SJeff Kirsher /* Input modifier of 0x1f means "finish as soon as possible." */ 2205f9baff50SJack Morgenstein return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100, MLX4_CMD_NATIVE); 22065a2cc190SJeff Kirsher } 22075a2cc190SJeff Kirsher 22088e1a28e8SHadar Hen Zion int mlx4_get_phys_port_id(struct mlx4_dev *dev) 22098e1a28e8SHadar Hen Zion { 22108e1a28e8SHadar Hen Zion u8 port; 22118e1a28e8SHadar Hen Zion u32 *outbox; 22128e1a28e8SHadar Hen Zion struct mlx4_cmd_mailbox *mailbox; 22138e1a28e8SHadar Hen Zion u32 in_mod; 22148e1a28e8SHadar Hen Zion u32 guid_hi, guid_lo; 22158e1a28e8SHadar Hen Zion int err, ret = 0; 22168e1a28e8SHadar Hen Zion #define MOD_STAT_CFG_PORT_OFFSET 8 22178e1a28e8SHadar Hen Zion #define MOD_STAT_CFG_GUID_H 0X14 22188e1a28e8SHadar Hen Zion #define MOD_STAT_CFG_GUID_L 0X1c 22198e1a28e8SHadar Hen Zion 22208e1a28e8SHadar Hen Zion mailbox = mlx4_alloc_cmd_mailbox(dev); 22218e1a28e8SHadar Hen Zion if (IS_ERR(mailbox)) 22228e1a28e8SHadar Hen Zion return PTR_ERR(mailbox); 22238e1a28e8SHadar Hen Zion outbox = mailbox->buf; 22248e1a28e8SHadar Hen Zion 22258e1a28e8SHadar Hen Zion for (port = 1; port <= dev->caps.num_ports; port++) { 22268e1a28e8SHadar Hen Zion in_mod = port << MOD_STAT_CFG_PORT_OFFSET; 22278e1a28e8SHadar Hen Zion err = mlx4_cmd_box(dev, 0, mailbox->dma, in_mod, 0x2, 22288e1a28e8SHadar Hen Zion MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A, 22298e1a28e8SHadar Hen Zion MLX4_CMD_NATIVE); 22308e1a28e8SHadar Hen Zion if (err) { 22318e1a28e8SHadar Hen Zion mlx4_err(dev, "Fail to get port %d uplink guid\n", 22328e1a28e8SHadar Hen Zion port); 22338e1a28e8SHadar Hen Zion ret = err; 22348e1a28e8SHadar Hen Zion } else { 22358e1a28e8SHadar Hen Zion MLX4_GET(guid_hi, outbox, MOD_STAT_CFG_GUID_H); 22368e1a28e8SHadar Hen Zion MLX4_GET(guid_lo, outbox, MOD_STAT_CFG_GUID_L); 22378e1a28e8SHadar Hen Zion dev->caps.phys_port_id[port] = (u64)guid_lo | 22388e1a28e8SHadar Hen Zion (u64)guid_hi << 32; 22398e1a28e8SHadar Hen Zion } 22408e1a28e8SHadar Hen Zion } 22418e1a28e8SHadar Hen Zion mlx4_free_cmd_mailbox(dev, mailbox); 22428e1a28e8SHadar Hen Zion return ret; 22438e1a28e8SHadar Hen Zion } 22448e1a28e8SHadar Hen Zion 22455a2cc190SJeff Kirsher #define MLX4_WOL_SETUP_MODE (5 << 28) 22465a2cc190SJeff Kirsher int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port) 22475a2cc190SJeff Kirsher { 22485a2cc190SJeff Kirsher u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8; 22495a2cc190SJeff Kirsher 22505a2cc190SJeff Kirsher return mlx4_cmd_imm(dev, 0, config, in_mod, 0x3, 2251f9baff50SJack Morgenstein MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A, 2252f9baff50SJack Morgenstein MLX4_CMD_NATIVE); 22535a2cc190SJeff Kirsher } 22545a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_wol_read); 22555a2cc190SJeff Kirsher 22565a2cc190SJeff Kirsher int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port) 22575a2cc190SJeff Kirsher { 22585a2cc190SJeff Kirsher u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8; 22595a2cc190SJeff Kirsher 22605a2cc190SJeff Kirsher return mlx4_cmd(dev, config, in_mod, 0x1, MLX4_CMD_MOD_STAT_CFG, 2261f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 22625a2cc190SJeff Kirsher } 22635a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_wol_write); 2264fe6f700dSYevgeny Petrilin 2265fe6f700dSYevgeny Petrilin enum { 2266fe6f700dSYevgeny Petrilin ADD_TO_MCG = 0x26, 2267fe6f700dSYevgeny Petrilin }; 2268fe6f700dSYevgeny Petrilin 2269fe6f700dSYevgeny Petrilin 2270fe6f700dSYevgeny Petrilin void mlx4_opreq_action(struct work_struct *work) 2271fe6f700dSYevgeny Petrilin { 2272fe6f700dSYevgeny Petrilin struct mlx4_priv *priv = container_of(work, struct mlx4_priv, 2273fe6f700dSYevgeny Petrilin opreq_task); 2274fe6f700dSYevgeny Petrilin struct mlx4_dev *dev = &priv->dev; 2275fe6f700dSYevgeny Petrilin int num_tasks = atomic_read(&priv->opreq_count); 2276fe6f700dSYevgeny Petrilin struct mlx4_cmd_mailbox *mailbox; 2277fe6f700dSYevgeny Petrilin struct mlx4_mgm *mgm; 2278fe6f700dSYevgeny Petrilin u32 *outbox; 2279fe6f700dSYevgeny Petrilin u32 modifier; 2280fe6f700dSYevgeny Petrilin u16 token; 2281fe6f700dSYevgeny Petrilin u16 type; 2282fe6f700dSYevgeny Petrilin int err; 2283fe6f700dSYevgeny Petrilin u32 num_qps; 2284fe6f700dSYevgeny Petrilin struct mlx4_qp qp; 2285fe6f700dSYevgeny Petrilin int i; 2286fe6f700dSYevgeny Petrilin u8 rem_mcg; 2287fe6f700dSYevgeny Petrilin u8 prot; 2288fe6f700dSYevgeny Petrilin 2289fe6f700dSYevgeny Petrilin #define GET_OP_REQ_MODIFIER_OFFSET 0x08 2290fe6f700dSYevgeny Petrilin #define GET_OP_REQ_TOKEN_OFFSET 0x14 2291fe6f700dSYevgeny Petrilin #define GET_OP_REQ_TYPE_OFFSET 0x1a 2292fe6f700dSYevgeny Petrilin #define GET_OP_REQ_DATA_OFFSET 0x20 2293fe6f700dSYevgeny Petrilin 2294fe6f700dSYevgeny Petrilin mailbox = mlx4_alloc_cmd_mailbox(dev); 2295fe6f700dSYevgeny Petrilin if (IS_ERR(mailbox)) { 2296fe6f700dSYevgeny Petrilin mlx4_err(dev, "Failed to allocate mailbox for GET_OP_REQ\n"); 2297fe6f700dSYevgeny Petrilin return; 2298fe6f700dSYevgeny Petrilin } 2299fe6f700dSYevgeny Petrilin outbox = mailbox->buf; 2300fe6f700dSYevgeny Petrilin 2301fe6f700dSYevgeny Petrilin while (num_tasks) { 2302fe6f700dSYevgeny Petrilin err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, 2303fe6f700dSYevgeny Petrilin MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A, 2304fe6f700dSYevgeny Petrilin MLX4_CMD_NATIVE); 2305fe6f700dSYevgeny Petrilin if (err) { 23066d3be300SMasanari Iida mlx4_err(dev, "Failed to retrieve required operation: %d\n", 2307fe6f700dSYevgeny Petrilin err); 2308fe6f700dSYevgeny Petrilin return; 2309fe6f700dSYevgeny Petrilin } 2310fe6f700dSYevgeny Petrilin MLX4_GET(modifier, outbox, GET_OP_REQ_MODIFIER_OFFSET); 2311fe6f700dSYevgeny Petrilin MLX4_GET(token, outbox, GET_OP_REQ_TOKEN_OFFSET); 2312fe6f700dSYevgeny Petrilin MLX4_GET(type, outbox, GET_OP_REQ_TYPE_OFFSET); 2313fe6f700dSYevgeny Petrilin type &= 0xfff; 2314fe6f700dSYevgeny Petrilin 2315fe6f700dSYevgeny Petrilin switch (type) { 2316fe6f700dSYevgeny Petrilin case ADD_TO_MCG: 2317fe6f700dSYevgeny Petrilin if (dev->caps.steering_mode == 2318fe6f700dSYevgeny Petrilin MLX4_STEERING_MODE_DEVICE_MANAGED) { 2319fe6f700dSYevgeny Petrilin mlx4_warn(dev, "ADD MCG operation is not supported in DEVICE_MANAGED steering mode\n"); 2320fe6f700dSYevgeny Petrilin err = EPERM; 2321fe6f700dSYevgeny Petrilin break; 2322fe6f700dSYevgeny Petrilin } 2323fe6f700dSYevgeny Petrilin mgm = (struct mlx4_mgm *)((u8 *)(outbox) + 2324fe6f700dSYevgeny Petrilin GET_OP_REQ_DATA_OFFSET); 2325fe6f700dSYevgeny Petrilin num_qps = be32_to_cpu(mgm->members_count) & 2326fe6f700dSYevgeny Petrilin MGM_QPN_MASK; 2327fe6f700dSYevgeny Petrilin rem_mcg = ((u8 *)(&mgm->members_count))[0] & 1; 2328fe6f700dSYevgeny Petrilin prot = ((u8 *)(&mgm->members_count))[0] >> 6; 2329fe6f700dSYevgeny Petrilin 2330fe6f700dSYevgeny Petrilin for (i = 0; i < num_qps; i++) { 2331fe6f700dSYevgeny Petrilin qp.qpn = be32_to_cpu(mgm->qp[i]); 2332fe6f700dSYevgeny Petrilin if (rem_mcg) 2333fe6f700dSYevgeny Petrilin err = mlx4_multicast_detach(dev, &qp, 2334fe6f700dSYevgeny Petrilin mgm->gid, 2335fe6f700dSYevgeny Petrilin prot, 0); 2336fe6f700dSYevgeny Petrilin else 2337fe6f700dSYevgeny Petrilin err = mlx4_multicast_attach(dev, &qp, 2338fe6f700dSYevgeny Petrilin mgm->gid, 2339fe6f700dSYevgeny Petrilin mgm->gid[5] 2340fe6f700dSYevgeny Petrilin , 0, prot, 2341fe6f700dSYevgeny Petrilin NULL); 2342fe6f700dSYevgeny Petrilin if (err) 2343fe6f700dSYevgeny Petrilin break; 2344fe6f700dSYevgeny Petrilin } 2345fe6f700dSYevgeny Petrilin break; 2346fe6f700dSYevgeny Petrilin default: 2347fe6f700dSYevgeny Petrilin mlx4_warn(dev, "Bad type for required operation\n"); 2348fe6f700dSYevgeny Petrilin err = EINVAL; 2349fe6f700dSYevgeny Petrilin break; 2350fe6f700dSYevgeny Petrilin } 235128d222bbSEyal Perry err = mlx4_cmd(dev, 0, ((u32) err | 235228d222bbSEyal Perry (__force u32)cpu_to_be32(token) << 16), 2353fe6f700dSYevgeny Petrilin 1, MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A, 2354fe6f700dSYevgeny Petrilin MLX4_CMD_NATIVE); 2355fe6f700dSYevgeny Petrilin if (err) { 2356fe6f700dSYevgeny Petrilin mlx4_err(dev, "Failed to acknowledge required request: %d\n", 2357fe6f700dSYevgeny Petrilin err); 2358fe6f700dSYevgeny Petrilin goto out; 2359fe6f700dSYevgeny Petrilin } 2360fe6f700dSYevgeny Petrilin memset(outbox, 0, 0xffc); 2361fe6f700dSYevgeny Petrilin num_tasks = atomic_dec_return(&priv->opreq_count); 2362fe6f700dSYevgeny Petrilin } 2363fe6f700dSYevgeny Petrilin 2364fe6f700dSYevgeny Petrilin out: 2365fe6f700dSYevgeny Petrilin mlx4_free_cmd_mailbox(dev, mailbox); 2366fe6f700dSYevgeny Petrilin } 2367114840c3SJack Morgenstein 2368114840c3SJack Morgenstein static int mlx4_check_smp_firewall_active(struct mlx4_dev *dev, 2369114840c3SJack Morgenstein struct mlx4_cmd_mailbox *mailbox) 2370114840c3SJack Morgenstein { 2371114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET 0x10 2372114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET 0x20 2373114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET 0x40 2374114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET 0x70 2375114840c3SJack Morgenstein 2376114840c3SJack Morgenstein u32 set_attr_mask, getresp_attr_mask; 2377114840c3SJack Morgenstein u32 trap_attr_mask, traprepress_attr_mask; 2378114840c3SJack Morgenstein 2379114840c3SJack Morgenstein MLX4_GET(set_attr_mask, mailbox->buf, 2380114840c3SJack Morgenstein MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET); 2381114840c3SJack Morgenstein mlx4_dbg(dev, "SMP firewall set_attribute_mask = 0x%x\n", 2382114840c3SJack Morgenstein set_attr_mask); 2383114840c3SJack Morgenstein 2384114840c3SJack Morgenstein MLX4_GET(getresp_attr_mask, mailbox->buf, 2385114840c3SJack Morgenstein MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET); 2386114840c3SJack Morgenstein mlx4_dbg(dev, "SMP firewall getresp_attribute_mask = 0x%x\n", 2387114840c3SJack Morgenstein getresp_attr_mask); 2388114840c3SJack Morgenstein 2389114840c3SJack Morgenstein MLX4_GET(trap_attr_mask, mailbox->buf, 2390114840c3SJack Morgenstein MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET); 2391114840c3SJack Morgenstein mlx4_dbg(dev, "SMP firewall trap_attribute_mask = 0x%x\n", 2392114840c3SJack Morgenstein trap_attr_mask); 2393114840c3SJack Morgenstein 2394114840c3SJack Morgenstein MLX4_GET(traprepress_attr_mask, mailbox->buf, 2395114840c3SJack Morgenstein MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET); 2396114840c3SJack Morgenstein mlx4_dbg(dev, "SMP firewall traprepress_attribute_mask = 0x%x\n", 2397114840c3SJack Morgenstein traprepress_attr_mask); 2398114840c3SJack Morgenstein 2399114840c3SJack Morgenstein if (set_attr_mask && getresp_attr_mask && trap_attr_mask && 2400114840c3SJack Morgenstein traprepress_attr_mask) 2401114840c3SJack Morgenstein return 1; 2402114840c3SJack Morgenstein 2403114840c3SJack Morgenstein return 0; 2404114840c3SJack Morgenstein } 2405114840c3SJack Morgenstein 2406114840c3SJack Morgenstein int mlx4_config_mad_demux(struct mlx4_dev *dev) 2407114840c3SJack Morgenstein { 2408114840c3SJack Morgenstein struct mlx4_cmd_mailbox *mailbox; 2409114840c3SJack Morgenstein int secure_host_active; 2410114840c3SJack Morgenstein int err; 2411114840c3SJack Morgenstein 2412114840c3SJack Morgenstein /* Check if mad_demux is supported */ 2413114840c3SJack Morgenstein if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_MAD_DEMUX)) 2414114840c3SJack Morgenstein return 0; 2415114840c3SJack Morgenstein 2416114840c3SJack Morgenstein mailbox = mlx4_alloc_cmd_mailbox(dev); 2417114840c3SJack Morgenstein if (IS_ERR(mailbox)) { 2418114840c3SJack Morgenstein mlx4_warn(dev, "Failed to allocate mailbox for cmd MAD_DEMUX"); 2419114840c3SJack Morgenstein return -ENOMEM; 2420114840c3SJack Morgenstein } 2421114840c3SJack Morgenstein 2422114840c3SJack Morgenstein /* Query mad_demux to find out which MADs are handled by internal sma */ 2423114840c3SJack Morgenstein err = mlx4_cmd_box(dev, 0, mailbox->dma, 0x01 /* subn mgmt class */, 2424114840c3SJack Morgenstein MLX4_CMD_MAD_DEMUX_QUERY_RESTR, MLX4_CMD_MAD_DEMUX, 2425114840c3SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 2426114840c3SJack Morgenstein if (err) { 2427114840c3SJack Morgenstein mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: query restrictions failed (%d)\n", 2428114840c3SJack Morgenstein err); 2429114840c3SJack Morgenstein goto out; 2430114840c3SJack Morgenstein } 2431114840c3SJack Morgenstein 2432114840c3SJack Morgenstein secure_host_active = mlx4_check_smp_firewall_active(dev, mailbox); 2433114840c3SJack Morgenstein 2434114840c3SJack Morgenstein /* Config mad_demux to handle all MADs returned by the query above */ 2435114840c3SJack Morgenstein err = mlx4_cmd(dev, mailbox->dma, 0x01 /* subn mgmt class */, 2436114840c3SJack Morgenstein MLX4_CMD_MAD_DEMUX_CONFIG, MLX4_CMD_MAD_DEMUX, 2437114840c3SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 2438114840c3SJack Morgenstein if (err) { 2439114840c3SJack Morgenstein mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: configure failed (%d)\n", err); 2440114840c3SJack Morgenstein goto out; 2441114840c3SJack Morgenstein } 2442114840c3SJack Morgenstein 2443114840c3SJack Morgenstein if (secure_host_active) 2444114840c3SJack Morgenstein mlx4_warn(dev, "HCA operating in secure-host mode. SMP firewall activated.\n"); 2445114840c3SJack Morgenstein out: 2446114840c3SJack Morgenstein mlx4_free_cmd_mailbox(dev, mailbox); 2447114840c3SJack Morgenstein return err; 2448114840c3SJack Morgenstein } 2449adbc7ac5SSaeed Mahameed 2450adbc7ac5SSaeed Mahameed /* Access Reg commands */ 2451adbc7ac5SSaeed Mahameed enum mlx4_access_reg_masks { 2452adbc7ac5SSaeed Mahameed MLX4_ACCESS_REG_STATUS_MASK = 0x7f, 2453adbc7ac5SSaeed Mahameed MLX4_ACCESS_REG_METHOD_MASK = 0x7f, 2454adbc7ac5SSaeed Mahameed MLX4_ACCESS_REG_LEN_MASK = 0x7ff 2455adbc7ac5SSaeed Mahameed }; 2456adbc7ac5SSaeed Mahameed 2457adbc7ac5SSaeed Mahameed struct mlx4_access_reg { 2458adbc7ac5SSaeed Mahameed __be16 constant1; 2459adbc7ac5SSaeed Mahameed u8 status; 2460adbc7ac5SSaeed Mahameed u8 resrvd1; 2461adbc7ac5SSaeed Mahameed __be16 reg_id; 2462adbc7ac5SSaeed Mahameed u8 method; 2463adbc7ac5SSaeed Mahameed u8 constant2; 2464adbc7ac5SSaeed Mahameed __be32 resrvd2[2]; 2465adbc7ac5SSaeed Mahameed __be16 len_const; 2466adbc7ac5SSaeed Mahameed __be16 resrvd3; 2467adbc7ac5SSaeed Mahameed #define MLX4_ACCESS_REG_HEADER_SIZE (20) 2468adbc7ac5SSaeed Mahameed u8 reg_data[MLX4_MAILBOX_SIZE-MLX4_ACCESS_REG_HEADER_SIZE]; 2469adbc7ac5SSaeed Mahameed } __attribute__((__packed__)); 2470adbc7ac5SSaeed Mahameed 2471adbc7ac5SSaeed Mahameed /** 2472adbc7ac5SSaeed Mahameed * mlx4_ACCESS_REG - Generic access reg command. 2473adbc7ac5SSaeed Mahameed * @dev: mlx4_dev. 2474adbc7ac5SSaeed Mahameed * @reg_id: register ID to access. 2475adbc7ac5SSaeed Mahameed * @method: Access method Read/Write. 2476adbc7ac5SSaeed Mahameed * @reg_len: register length to Read/Write in bytes. 2477adbc7ac5SSaeed Mahameed * @reg_data: reg_data pointer to Read/Write From/To. 2478adbc7ac5SSaeed Mahameed * 2479adbc7ac5SSaeed Mahameed * Access ConnectX registers FW command. 2480adbc7ac5SSaeed Mahameed * Returns 0 on success and copies outbox mlx4_access_reg data 2481adbc7ac5SSaeed Mahameed * field into reg_data or a negative error code. 2482adbc7ac5SSaeed Mahameed */ 2483adbc7ac5SSaeed Mahameed static int mlx4_ACCESS_REG(struct mlx4_dev *dev, u16 reg_id, 2484adbc7ac5SSaeed Mahameed enum mlx4_access_reg_method method, 2485adbc7ac5SSaeed Mahameed u16 reg_len, void *reg_data) 2486adbc7ac5SSaeed Mahameed { 2487adbc7ac5SSaeed Mahameed struct mlx4_cmd_mailbox *inbox, *outbox; 2488adbc7ac5SSaeed Mahameed struct mlx4_access_reg *inbuf, *outbuf; 2489adbc7ac5SSaeed Mahameed int err; 2490adbc7ac5SSaeed Mahameed 2491adbc7ac5SSaeed Mahameed inbox = mlx4_alloc_cmd_mailbox(dev); 2492adbc7ac5SSaeed Mahameed if (IS_ERR(inbox)) 2493adbc7ac5SSaeed Mahameed return PTR_ERR(inbox); 2494adbc7ac5SSaeed Mahameed 2495adbc7ac5SSaeed Mahameed outbox = mlx4_alloc_cmd_mailbox(dev); 2496adbc7ac5SSaeed Mahameed if (IS_ERR(outbox)) { 2497adbc7ac5SSaeed Mahameed mlx4_free_cmd_mailbox(dev, inbox); 2498adbc7ac5SSaeed Mahameed return PTR_ERR(outbox); 2499adbc7ac5SSaeed Mahameed } 2500adbc7ac5SSaeed Mahameed 2501adbc7ac5SSaeed Mahameed inbuf = inbox->buf; 2502adbc7ac5SSaeed Mahameed outbuf = outbox->buf; 2503adbc7ac5SSaeed Mahameed 2504adbc7ac5SSaeed Mahameed inbuf->constant1 = cpu_to_be16(0x1<<11 | 0x4); 2505adbc7ac5SSaeed Mahameed inbuf->constant2 = 0x1; 2506adbc7ac5SSaeed Mahameed inbuf->reg_id = cpu_to_be16(reg_id); 2507adbc7ac5SSaeed Mahameed inbuf->method = method & MLX4_ACCESS_REG_METHOD_MASK; 2508adbc7ac5SSaeed Mahameed 2509adbc7ac5SSaeed Mahameed reg_len = min(reg_len, (u16)(sizeof(inbuf->reg_data))); 2510adbc7ac5SSaeed Mahameed inbuf->len_const = 2511adbc7ac5SSaeed Mahameed cpu_to_be16(((reg_len/4 + 1) & MLX4_ACCESS_REG_LEN_MASK) | 2512adbc7ac5SSaeed Mahameed ((0x3) << 12)); 2513adbc7ac5SSaeed Mahameed 2514adbc7ac5SSaeed Mahameed memcpy(inbuf->reg_data, reg_data, reg_len); 2515adbc7ac5SSaeed Mahameed err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, 0, 0, 2516adbc7ac5SSaeed Mahameed MLX4_CMD_ACCESS_REG, MLX4_CMD_TIME_CLASS_C, 25176e806699SSaeed Mahameed MLX4_CMD_WRAPPED); 2518adbc7ac5SSaeed Mahameed if (err) 2519adbc7ac5SSaeed Mahameed goto out; 2520adbc7ac5SSaeed Mahameed 2521adbc7ac5SSaeed Mahameed if (outbuf->status & MLX4_ACCESS_REG_STATUS_MASK) { 2522adbc7ac5SSaeed Mahameed err = outbuf->status & MLX4_ACCESS_REG_STATUS_MASK; 2523adbc7ac5SSaeed Mahameed mlx4_err(dev, 2524adbc7ac5SSaeed Mahameed "MLX4_CMD_ACCESS_REG(%x) returned REG status (%x)\n", 2525adbc7ac5SSaeed Mahameed reg_id, err); 2526adbc7ac5SSaeed Mahameed goto out; 2527adbc7ac5SSaeed Mahameed } 2528adbc7ac5SSaeed Mahameed 2529adbc7ac5SSaeed Mahameed memcpy(reg_data, outbuf->reg_data, reg_len); 2530adbc7ac5SSaeed Mahameed out: 2531adbc7ac5SSaeed Mahameed mlx4_free_cmd_mailbox(dev, inbox); 2532adbc7ac5SSaeed Mahameed mlx4_free_cmd_mailbox(dev, outbox); 2533adbc7ac5SSaeed Mahameed return err; 2534adbc7ac5SSaeed Mahameed } 2535adbc7ac5SSaeed Mahameed 2536adbc7ac5SSaeed Mahameed /* ConnectX registers IDs */ 2537adbc7ac5SSaeed Mahameed enum mlx4_reg_id { 2538adbc7ac5SSaeed Mahameed MLX4_REG_ID_PTYS = 0x5004, 2539adbc7ac5SSaeed Mahameed }; 2540adbc7ac5SSaeed Mahameed 2541adbc7ac5SSaeed Mahameed /** 2542adbc7ac5SSaeed Mahameed * mlx4_ACCESS_PTYS_REG - Access PTYs (Port Type and Speed) 2543adbc7ac5SSaeed Mahameed * register 2544adbc7ac5SSaeed Mahameed * @dev: mlx4_dev. 2545adbc7ac5SSaeed Mahameed * @method: Access method Read/Write. 2546adbc7ac5SSaeed Mahameed * @ptys_reg: PTYS register data pointer. 2547adbc7ac5SSaeed Mahameed * 2548adbc7ac5SSaeed Mahameed * Access ConnectX PTYS register, to Read/Write Port Type/Speed 2549adbc7ac5SSaeed Mahameed * configuration 2550adbc7ac5SSaeed Mahameed * Returns 0 on success or a negative error code. 2551adbc7ac5SSaeed Mahameed */ 2552adbc7ac5SSaeed Mahameed int mlx4_ACCESS_PTYS_REG(struct mlx4_dev *dev, 2553adbc7ac5SSaeed Mahameed enum mlx4_access_reg_method method, 2554adbc7ac5SSaeed Mahameed struct mlx4_ptys_reg *ptys_reg) 2555adbc7ac5SSaeed Mahameed { 2556adbc7ac5SSaeed Mahameed return mlx4_ACCESS_REG(dev, MLX4_REG_ID_PTYS, 2557adbc7ac5SSaeed Mahameed method, sizeof(*ptys_reg), ptys_reg); 2558adbc7ac5SSaeed Mahameed } 2559adbc7ac5SSaeed Mahameed EXPORT_SYMBOL_GPL(mlx4_ACCESS_PTYS_REG); 25606e806699SSaeed Mahameed 25616e806699SSaeed Mahameed int mlx4_ACCESS_REG_wrapper(struct mlx4_dev *dev, int slave, 25626e806699SSaeed Mahameed struct mlx4_vhcr *vhcr, 25636e806699SSaeed Mahameed struct mlx4_cmd_mailbox *inbox, 25646e806699SSaeed Mahameed struct mlx4_cmd_mailbox *outbox, 25656e806699SSaeed Mahameed struct mlx4_cmd_info *cmd) 25666e806699SSaeed Mahameed { 25676e806699SSaeed Mahameed struct mlx4_access_reg *inbuf = inbox->buf; 25686e806699SSaeed Mahameed u8 method = inbuf->method & MLX4_ACCESS_REG_METHOD_MASK; 25696e806699SSaeed Mahameed u16 reg_id = be16_to_cpu(inbuf->reg_id); 25706e806699SSaeed Mahameed 25716e806699SSaeed Mahameed if (slave != mlx4_master_func_num(dev) && 25726e806699SSaeed Mahameed method == MLX4_ACCESS_REG_WRITE) 25736e806699SSaeed Mahameed return -EPERM; 25746e806699SSaeed Mahameed 25756e806699SSaeed Mahameed if (reg_id == MLX4_REG_ID_PTYS) { 25766e806699SSaeed Mahameed struct mlx4_ptys_reg *ptys_reg = 25776e806699SSaeed Mahameed (struct mlx4_ptys_reg *)inbuf->reg_data; 25786e806699SSaeed Mahameed 25796e806699SSaeed Mahameed ptys_reg->local_port = 25806e806699SSaeed Mahameed mlx4_slave_convert_port(dev, slave, 25816e806699SSaeed Mahameed ptys_reg->local_port); 25826e806699SSaeed Mahameed } 25836e806699SSaeed Mahameed 25846e806699SSaeed Mahameed return mlx4_cmd_box(dev, inbox->dma, outbox->dma, vhcr->in_modifier, 25856e806699SSaeed Mahameed 0, MLX4_CMD_ACCESS_REG, MLX4_CMD_TIME_CLASS_C, 25866e806699SSaeed Mahameed MLX4_CMD_NATIVE); 25876e806699SSaeed Mahameed } 2588