Commit c1e7e466 authored by Jack Morgenstein's avatar Jack Morgenstein Committed by Roland Dreier

IB/mlx4: Add iov directory in sysfs under the ib device

This directory is added only for the master -- slaves do not have it.

The sysfs iov directory is used to manage and examine the port P_Key
and guid paravirtualization.

Under iov/ports, the administrator may examine the gid and P_Key tables
as they are present in the device (and as are seen in the "network
view" presented to the SM).

Under the iov/<pci slot number> directories, the admin may map the
index numbers in the physical tables (as under iov/ports) to the
paravirtualized index numbers that guests see.

For example, if the administrator, for port 1 on guest 2 maps physical
pkey index 10 to virtual index 1, then that guest, whenever it uses
its pkey index 1, will actually be using the real pkey index 10.

Based on patch from Erez Shitrit <erezsh@mellanox.com>
Signed-off-by: default avatarJack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 2a4fae14
obj-$(CONFIG_MLX4_INFINIBAND) += mlx4_ib.o
mlx4_ib-y := ah.o cq.o doorbell.o mad.o main.o mr.o qp.o srq.o mcg.o cm.o alias_GUID.o
mlx4_ib-y := ah.o cq.o doorbell.o mad.o main.o mr.o qp.o srq.o mcg.o cm.o alias_GUID.o sysfs.o
......@@ -113,7 +113,7 @@ static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index
}
static ib_sa_comp_mask get_aguid_comp_mask_from_ix(int index)
ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index)
{
return IB_SA_COMP_MASK(4 + index);
}
......@@ -259,7 +259,7 @@ static void aliasguid_query_handler(int status,
/* Mark the record as not assigned, and let it
* be sent again in the next work sched.*/
rec->status = MLX4_GUID_INFO_STATUS_IDLE;
rec->guid_indexes |= get_aguid_comp_mask_from_ix(i);
rec->guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
}
} else {
/* properly assigned record. */
......@@ -337,7 +337,7 @@ static void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index)
MLX4_GUID_NONE_ASSIGN == dev->sriov.alias_guid.
ports_guid[port - 1].all_rec_per_port[index].ownership)
continue;
comp_mask |= get_aguid_comp_mask_from_ix(i);
comp_mask |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
}
dev->sriov.alias_guid.ports_guid[port - 1].
all_rec_per_port[index].guid_indexes = comp_mask;
......
......@@ -1963,6 +1963,11 @@ int mlx4_ib_init_sriov(struct mlx4_ib_dev *dev)
mlx4_ib_warn(&dev->ib_dev, "Failed init alias guid process.\n");
goto paravirt_err;
}
err = mlx4_ib_device_register_sysfs(dev);
if (err) {
mlx4_ib_warn(&dev->ib_dev, "Failed to register sysfs\n");
goto sysfs_err;
}
mlx4_ib_warn(&dev->ib_dev, "initializing demux service for %d qp1 clients\n",
dev->dev->caps.sqp_demux);
......@@ -1989,6 +1994,9 @@ int mlx4_ib_init_sriov(struct mlx4_ib_dev *dev)
mlx4_ib_free_demux_ctx(&dev->sriov.demux[i]);
--i;
}
mlx4_ib_device_unregister_sysfs(dev);
sysfs_err:
mlx4_ib_destroy_alias_guid_service(dev);
paravirt_err:
......@@ -2019,5 +2027,6 @@ void mlx4_ib_close_sriov(struct mlx4_ib_dev *dev)
mlx4_ib_cm_paravirt_clean(dev, -1);
mlx4_ib_destroy_alias_guid_service(dev);
mlx4_ib_device_unregister_sysfs(dev);
}
}
......@@ -110,6 +110,7 @@ struct mcast_group {
__be64 last_req_tid;
char name[33]; /* MGID string */
struct device_attribute dentry;
/* refcount is the reference count for the following:
1. Each queued request
......@@ -445,6 +446,8 @@ static int release_group(struct mcast_group *group, int from_timeout_handler)
}
nzgroup = memcmp(&group->rec.mgid, &mgid0, sizeof mgid0);
if (nzgroup)
del_sysfs_port_mcg_attr(ctx->dev, ctx->port, &group->dentry.attr);
if (!list_empty(&group->pending_list))
mcg_warn_group(group, "releasing a group with non empty pending list\n");
if (nzgroup)
......@@ -769,6 +772,7 @@ static struct mcast_group *search_relocate_mgid0_group(struct mlx4_ib_demux_ctx
}
atomic_inc(&group->refcount);
add_sysfs_port_mcg_attr(ctx->dev, ctx->port, &group->dentry.attr);
mutex_unlock(&group->lock);
mutex_unlock(&ctx->mcg_table_lock);
return group;
......@@ -796,6 +800,9 @@ static struct mcast_group *search_relocate_mgid0_group(struct mlx4_ib_demux_ctx
return NULL;
}
static ssize_t sysfs_show_group(struct device *dev,
struct device_attribute *attr, char *buf);
static struct mcast_group *acquire_group(struct mlx4_ib_demux_ctx *ctx,
union ib_gid *mgid, int create,
gfp_t gfp_mask)
......@@ -830,6 +837,11 @@ static struct mcast_group *acquire_group(struct mlx4_ib_demux_ctx *ctx,
sprintf(group->name, "%016llx%016llx",
be64_to_cpu(group->rec.mgid.global.subnet_prefix),
be64_to_cpu(group->rec.mgid.global.interface_id));
sysfs_attr_init(&group->dentry.attr);
group->dentry.show = sysfs_show_group;
group->dentry.store = NULL;
group->dentry.attr.name = group->name;
group->dentry.attr.mode = 0400;
group->state = MCAST_IDLE;
if (is_mgid0) {
......@@ -844,6 +856,8 @@ static struct mcast_group *acquire_group(struct mlx4_ib_demux_ctx *ctx,
return ERR_PTR(-EINVAL);
}
add_sysfs_port_mcg_attr(ctx->dev, ctx->port, &group->dentry.attr);
found:
atomic_inc(&group->refcount);
return group;
......@@ -969,6 +983,58 @@ int mlx4_ib_mcg_multiplex_handler(struct ib_device *ibdev, int port,
}
}
static ssize_t sysfs_show_group(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct mcast_group *group =
container_of(attr, struct mcast_group, dentry);
struct mcast_req *req = NULL;
char pending_str[40];
char state_str[40];
ssize_t len = 0;
int f;
if (group->state == MCAST_IDLE)
sprintf(state_str, "%s", get_state_string(group->state));
else
sprintf(state_str, "%s(TID=0x%llx)",
get_state_string(group->state),
be64_to_cpu(group->last_req_tid));
if (list_empty(&group->pending_list)) {
sprintf(pending_str, "No");
} else {
req = list_first_entry(&group->pending_list, struct mcast_req, group_list);
sprintf(pending_str, "Yes(TID=0x%llx)",
be64_to_cpu(req->sa_mad.mad_hdr.tid));
}
len += sprintf(buf + len, "%1d [%02d,%02d,%02d] %4d %4s %5s ",
group->rec.scope_join_state & 0xf,
group->members[2], group->members[1], group->members[0],
atomic_read(&group->refcount),
pending_str,
state_str);
for (f = 0; f < MAX_VFS; ++f)
if (group->func[f].state == MCAST_MEMBER)
len += sprintf(buf + len, "%d[%1x] ",
f, group->func[f].join_state);
len += sprintf(buf + len, "\t\t(%4hx %4x %2x %2x %2x %2x %2x "
"%4x %4x %2x %2x)\n",
be16_to_cpu(group->rec.pkey),
be32_to_cpu(group->rec.qkey),
(group->rec.mtusel_mtu & 0xc0) >> 6,
group->rec.mtusel_mtu & 0x3f,
group->rec.tclass,
(group->rec.ratesel_rate & 0xc0) >> 6,
group->rec.ratesel_rate & 0x3f,
(be32_to_cpu(group->rec.sl_flowlabel_hoplimit) & 0xf0000000) >> 28,
(be32_to_cpu(group->rec.sl_flowlabel_hoplimit) & 0x0fffff00) >> 8,
be32_to_cpu(group->rec.sl_flowlabel_hoplimit) & 0x000000ff,
group->rec.proxy_join);
return len;
}
int mlx4_ib_mcg_port_init(struct mlx4_ib_demux_ctx *ctx)
{
char name[20];
......@@ -995,6 +1061,7 @@ static void force_clean_group(struct mcast_group *group)
list_del(&req->group_list);
kfree(req);
}
del_sysfs_port_mcg_attr(group->demux->dev, group->demux->port, &group->dentry.attr);
rb_erase(&group->node, &group->demux->mcg_table);
kfree(group);
}
......
......@@ -427,6 +427,35 @@ struct pkey_mgt {
struct kobject *device_parent[MLX4_MFUNC_MAX];
};
struct mlx4_ib_iov_sysfs_attr {
void *ctx;
struct kobject *kobj;
unsigned long data;
u32 entry_num;
char name[15];
struct device_attribute dentry;
struct device *dev;
};
struct mlx4_ib_iov_sysfs_attr_ar {
struct mlx4_ib_iov_sysfs_attr dentries[3 * NUM_ALIAS_GUID_PER_PORT + 1];
};
struct mlx4_ib_iov_port {
char name[100];
u8 num;
struct mlx4_ib_dev *dev;
struct list_head list;
struct mlx4_ib_iov_sysfs_attr_ar *dentr_ar;
struct ib_port_attr attr;
struct kobject *cur_port;
struct kobject *admin_alias_parent;
struct kobject *gids_parent;
struct kobject *pkeys_parent;
struct kobject *mcgs_parent;
struct mlx4_ib_iov_sysfs_attr mcg_dentry;
};
struct mlx4_ib_dev {
struct ib_device ib_dev;
struct mlx4_dev *dev;
......@@ -448,6 +477,10 @@ struct mlx4_ib_dev {
int counters[MLX4_MAX_PORTS];
int *eq_table;
int eq_added;
struct kobject *iov_parent;
struct kobject *ports_parent;
struct kobject *dev_ports_parent[MLX4_MFUNC_MAX];
struct mlx4_ib_iov_port iov_ports[MLX4_MAX_PORTS];
struct pkey_mgt pkeys;
};
......@@ -680,4 +713,14 @@ void mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev *dev,
int block_num, u8 port_num,
u8 *p_data);
int add_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
struct attribute *attr);
void del_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
struct attribute *attr);
ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index);
int mlx4_ib_device_register_sysfs(struct mlx4_ib_dev *device) ;
void mlx4_ib_device_unregister_sysfs(struct mlx4_ib_dev *device);
#endif /* MLX4_IB_H */
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment