/*
*
*
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <linux/mlx4/cmd.h>
#include <linux/cache.h>
#include "fw.h"
#include "icm.h"
enum {
MLX4_COMMAND_INTERFACE_MIN_REV = 2,
MLX4_COMMAND_INTERFACE_MAX_REV = 3,
MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS = 3,
};
extern void __buggy_use_of_MLX4_GET(void);
extern void __buggy_use_of_MLX4_PUT(void);
static int enable_qos;
module_param(enable_qos, bool, 0444);
MODULE_PARM_DESC(enable_qos, "Enable Quality of Service support in the HCA (default: off)");
#define MLX4_GET(dest, source, offset) \
do { \
void *__p = (char *) (source) + (offset); \
switch (sizeof (dest)) { \
case 1: (dest) = *(u8 *) __p; break; \
case 2: (dest) = be16_to_cpup(__p); break; \
case 4: (dest) = be32_to_cpup(__p); break; \
case 8: (dest) = be64_to_cpup(__p); break; \
default: __buggy_use_of_MLX4_GET(); \
} \
} while (0)
#define MLX4_PUT(dest, source, offset) \
do { \
void *__d = ((char *) (dest) + (offset)); \
switch (sizeof(source)) { \
case 1: *(u8 *) __d = (source); break; \
case 2: *(__be16 *) __d = cpu_to_be16(source); break; \
case 4: *(__be32 *) __d = cpu_to_be32(source); break; \
case 8: *(__be64 *) __d = cpu_to_be64(source); break; \
default: __buggy_use_of_MLX4_PUT(); \
} \
} while (0)
static void dump_dev_cap_flags(struct mlx4_dev *dev, u32 flags)
{
static const char *fname[] = {
[ 0] = "RC transport",
[ 1] = "UC transport",
[ 2] = "UD transport",
[ 3] = "XRC transport",
[ 4] = "reliable multicast",
[ 5] = "FCoIB support",
[ 6] = "SRQ support",
[ 7] = "IPoIB checksum offload",
[ 8] = "P_Key violation counter",
[ 9] = "Q_Key violation counter",
[10] = "VMM",
[12] = "DPDP",
[15] = "Big LSO headers",
[16] = "MW support",
[17] = "APM support",
[18] = "Atomic ops support",
[19] = "Raw multicast support",
[20] = "Address vector port checking support",
[21] = "UD multicast support",
[24] = "Demand paging support",
[25] = "Router support",
[30] = "IBoE support"
};
int i;
mlx4_dbg(dev, "DEV_CAP flags:\n");
for (i = 0; i < ARRAY_SIZE(fname); ++i)
if (fname[i] && (flags & (1 << i)))
mlx4_dbg(dev, " %s\n", fname[i]);
}
int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg)
{
struct mlx4_cmd_mailbox *mailbox;
u32 *inbox;
int err = 0;
#define MOD_STAT_CFG_IN_SIZE 0x100
#define MOD_STAT_CFG_PG_SZ_M_OFFSET 0x002
#define MOD_STAT_CFG_PG_SZ_OFFSET 0x003
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
inbox = mailbox->buf;
memset(inbox, 0, MOD_STAT_CFG_IN_SIZE);
MLX4_PUT(inbox, cfg->log_pg_sz, MOD_STAT_CFG_PG_SZ_OFFSET);
MLX4_PUT(inbox, cfg->log_pg_sz_m, MOD_STAT_CFG_PG_SZ_M_OFFSET);
err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_MOD_STAT_CFG,
MLX4_CMD_TIME_CLASS_A);
mlx4_free_cmd_mailbox(dev, mailbox);
return err;
}
int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
{
struct mlx4_cmd_mailbox *mailbox;
u32 *outbox;
u8 field;
u32 field32;
u16 size;
u16 stat_rate;
int err;
int i;
#define QUERY_DEV_CAP_OUT_SIZE 0x100
#define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET 0x10
#define QUERY_DEV_CAP_MAX_QP_SZ_OFFSET 0x11
#define QUERY_DEV_CAP_RSVD_QP_OFFSET 0x12
#define QUERY_DEV_CAP_MAX_QP_OFFSET 0x13
#define QUERY_DEV_CAP_RSVD_SRQ_OFFSET 0x14
#define QUERY_DEV_CAP_MAX_SRQ_OFFSET 0x15
#define QUERY_DEV_CAP_RSVD_EEC_OFFSET 0x16
#define QUERY_DEV_CAP_MAX_EEC_OFFSET 0x17
#define QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET 0x19
#define QUERY_DEV_CAP_RSVD_CQ_OFFSET 0x1a
#define QUERY_DEV_CAP_MAX_CQ_OFFSET 0x1b
#define QUERY_DEV_CAP_MAX_MPT_OFFSET 0x1d
#define QUERY_DEV_CAP_RSVD_EQ_OFFSET 0x1e
#define QUERY_DEV_CAP_MAX_EQ_OFFSET 0x1f
#define QUERY_DEV_CAP_RSVD_MTT_OFFSET 0x20
#define QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET 0x21
#define QUERY_DEV_CAP_RSVD_MRW_OFFSET 0x22
#define QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET 0x23
#define QUERY_DEV_CAP_MAX_AV_OFFSET 0x27
#define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET 0x29
#define QUERY_DEV_CAP_MAX_RES_QP_OFFSET 0x2b
#define QUERY_DEV_CAP_MAX_GSO_OFFSET 0x2d
#define QUERY_DEV_CAP_MAX_RDMA_OFFSET 0x2f
#define QUERY_DEV_CAP_RSZ_SRQ_OFFSET 0x33
#define QUERY_DEV_CAP_ACK_DELAY_OFFSET 0x35
#define QUERY_DEV_CAP_MTU_WIDTH_OFFSET 0x36
#define QUERY_DEV_CAP_VL_PORT_OFFSET 0x37
#define QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET 0x38
#define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b
#define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c
#define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f
#define QUERY_DEV_CAP_UDP_RSS_OFFSET 0x42
#define QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET 0x43
#define QUERY_DEV_CAP_FLAGS_OFFSET 0x44
#define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48
#define QUERY_DEV_CAP_UAR_SZ_OFFSET 0x49
#define QUERY_DEV_CAP_PAGE_SZ_OFFSET 0x4b
#define QUERY_DEV_CAP_BF_OFFSET 0x4c
#define QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET 0x4d
#define QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET 0x4e
#define QUERY_DEV_CAP_LOG_MAX_BF_PAGES_OFFSET 0x4f
#define QUERY_DEV_CAP_MAX_SG_SQ_OFFSET 0x51
#define QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET 0x52
#define QUERY_DEV_CAP_MAX_SG_RQ_OFFSET 0x55
#define QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET 0x56
#define QUERY_DEV_CAP_MAX_QP_MCG_OFFSET 0x61
#define QUERY_DEV_CAP_RSVD_MCG_OFFSET 0x62
#define QUERY_DEV_CAP_MAX_MCG_OFFSET 0x63
#define QUERY_DEV_CAP_RSVD_PD_OFFSET 0x64
#define QUERY_DEV_CAP_MAX_PD_OFFSET 0x65
#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80
#define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82
#define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84
#define QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET 0x86
#define QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET 0x88
#define QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET 0x8a
#define QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET 0x8c
#define QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET 0x8e
#define QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET 0x90
#define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET 0x92
#define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x94
#define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98
#define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
outbox = mailbox->buf;
err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
MLX4_CMD_TIME_CLASS_A);
if (err)
goto out;
MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_QP_OFFSET);
dev_cap->reserved_qps = 1 << (field & 0xf);
MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_OFFSET);
dev_cap->max_qps = 1 << (field & 0x1f);
MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_SRQ_OFFSET);
dev_cap->reserved_srqs = 1 << (field >> 4);
MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX