diff options
| author | Jack Morgenstein <jackm@dev.mellanox.co.il> | 2012-08-03 04:40:51 -0400 |
|---|---|---|
| committer | Roland Dreier <roland@purestorage.com> | 2012-09-30 23:33:39 -0400 |
| commit | c1e7e466120b80ce49e91af0c9da1ce6dee4844a (patch) | |
| tree | fc67dbaf01fff7e0f411315ee3b5a6923cf22354 | |
| parent | 2a4fae148cf4b60e73faf0a427302697917409d9 (diff) | |
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: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: Roland Dreier <roland@purestorage.com>
| -rw-r--r-- | drivers/infiniband/hw/mlx4/Makefile | 2 | ||||
| -rw-r--r-- | drivers/infiniband/hw/mlx4/alias_GUID.c | 6 | ||||
| -rw-r--r-- | drivers/infiniband/hw/mlx4/mad.c | 9 | ||||
| -rw-r--r-- | drivers/infiniband/hw/mlx4/mcg.c | 67 | ||||
| -rw-r--r-- | drivers/infiniband/hw/mlx4/mlx4_ib.h | 43 | ||||
| -rw-r--r-- | drivers/infiniband/hw/mlx4/sysfs.c | 794 |
6 files changed, 917 insertions, 4 deletions
diff --git a/drivers/infiniband/hw/mlx4/Makefile b/drivers/infiniband/hw/mlx4/Makefile index 31d4c8aac679..f4213b3a8fe1 100644 --- a/drivers/infiniband/hw/mlx4/Makefile +++ b/drivers/infiniband/hw/mlx4/Makefile | |||
| @@ -1,3 +1,3 @@ | |||
| 1 | obj-$(CONFIG_MLX4_INFINIBAND) += mlx4_ib.o | 1 | obj-$(CONFIG_MLX4_INFINIBAND) += mlx4_ib.o |
| 2 | 2 | ||
| 3 | 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 | 3 | 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 |
diff --git a/drivers/infiniband/hw/mlx4/alias_GUID.c b/drivers/infiniband/hw/mlx4/alias_GUID.c index ef6d356927c3..0fcd5cd6f3ee 100644 --- a/drivers/infiniband/hw/mlx4/alias_GUID.c +++ b/drivers/infiniband/hw/mlx4/alias_GUID.c | |||
| @@ -113,7 +113,7 @@ static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index | |||
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | 115 | ||
| 116 | static ib_sa_comp_mask get_aguid_comp_mask_from_ix(int index) | 116 | ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index) |
| 117 | { | 117 | { |
| 118 | return IB_SA_COMP_MASK(4 + index); | 118 | return IB_SA_COMP_MASK(4 + index); |
| 119 | } | 119 | } |
| @@ -259,7 +259,7 @@ static void aliasguid_query_handler(int status, | |||
| 259 | /* Mark the record as not assigned, and let it | 259 | /* Mark the record as not assigned, and let it |
| 260 | * be sent again in the next work sched.*/ | 260 | * be sent again in the next work sched.*/ |
| 261 | rec->status = MLX4_GUID_INFO_STATUS_IDLE; | 261 | rec->status = MLX4_GUID_INFO_STATUS_IDLE; |
| 262 | rec->guid_indexes |= get_aguid_comp_mask_from_ix(i); | 262 | rec->guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i); |
| 263 | } | 263 | } |
| 264 | } else { | 264 | } else { |
| 265 | /* properly assigned record. */ | 265 | /* properly assigned record. */ |
| @@ -337,7 +337,7 @@ static void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index) | |||
| 337 | MLX4_GUID_NONE_ASSIGN == dev->sriov.alias_guid. | 337 | MLX4_GUID_NONE_ASSIGN == dev->sriov.alias_guid. |
| 338 | ports_guid[port - 1].all_rec_per_port[index].ownership) | 338 | ports_guid[port - 1].all_rec_per_port[index].ownership) |
| 339 | continue; | 339 | continue; |
| 340 | comp_mask |= get_aguid_comp_mask_from_ix(i); | 340 | comp_mask |= mlx4_ib_get_aguid_comp_mask_from_ix(i); |
| 341 | } | 341 | } |
| 342 | dev->sriov.alias_guid.ports_guid[port - 1]. | 342 | dev->sriov.alias_guid.ports_guid[port - 1]. |
| 343 | all_rec_per_port[index].guid_indexes = comp_mask; | 343 | all_rec_per_port[index].guid_indexes = comp_mask; |
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 591c2891159b..b689dbd6d8f6 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c | |||
| @@ -1963,6 +1963,11 @@ int mlx4_ib_init_sriov(struct mlx4_ib_dev *dev) | |||
| 1963 | mlx4_ib_warn(&dev->ib_dev, "Failed init alias guid process.\n"); | 1963 | mlx4_ib_warn(&dev->ib_dev, "Failed init alias guid process.\n"); |
| 1964 | goto paravirt_err; | 1964 | goto paravirt_err; |
| 1965 | } | 1965 | } |
| 1966 | err = mlx4_ib_device_register_sysfs(dev); | ||
| 1967 | if (err) { | ||
| 1968 | mlx4_ib_warn(&dev->ib_dev, "Failed to register sysfs\n"); | ||
| 1969 | goto sysfs_err; | ||
| 1970 | } | ||
| 1966 | 1971 | ||
| 1967 | mlx4_ib_warn(&dev->ib_dev, "initializing demux service for %d qp1 clients\n", | 1972 | mlx4_ib_warn(&dev->ib_dev, "initializing demux service for %d qp1 clients\n", |
| 1968 | dev->dev->caps.sqp_demux); | 1973 | dev->dev->caps.sqp_demux); |
| @@ -1989,6 +1994,9 @@ demux_err: | |||
| 1989 | mlx4_ib_free_demux_ctx(&dev->sriov.demux[i]); | 1994 | mlx4_ib_free_demux_ctx(&dev->sriov.demux[i]); |
| 1990 | --i; | 1995 | --i; |
| 1991 | } | 1996 | } |
| 1997 | mlx4_ib_device_unregister_sysfs(dev); | ||
| 1998 | |||
| 1999 | sysfs_err: | ||
| 1992 | mlx4_ib_destroy_alias_guid_service(dev); | 2000 | mlx4_ib_destroy_alias_guid_service(dev); |
| 1993 | 2001 | ||
| 1994 | paravirt_err: | 2002 | paravirt_err: |
| @@ -2019,5 +2027,6 @@ void mlx4_ib_close_sriov(struct mlx4_ib_dev *dev) | |||
| 2019 | 2027 | ||
| 2020 | mlx4_ib_cm_paravirt_clean(dev, -1); | 2028 | mlx4_ib_cm_paravirt_clean(dev, -1); |
| 2021 | mlx4_ib_destroy_alias_guid_service(dev); | 2029 | mlx4_ib_destroy_alias_guid_service(dev); |
| 2030 | mlx4_ib_device_unregister_sysfs(dev); | ||
| 2022 | } | 2031 | } |
| 2023 | } | 2032 | } |
diff --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c index 1ee2e3a3347a..3c3b54c3fdd9 100644 --- a/drivers/infiniband/hw/mlx4/mcg.c +++ b/drivers/infiniband/hw/mlx4/mcg.c | |||
| @@ -110,6 +110,7 @@ struct mcast_group { | |||
| 110 | __be64 last_req_tid; | 110 | __be64 last_req_tid; |
| 111 | 111 | ||
| 112 | char name[33]; /* MGID string */ | 112 | char name[33]; /* MGID string */ |
| 113 | struct device_attribute dentry; | ||
| 113 | 114 | ||
| 114 | /* refcount is the reference count for the following: | 115 | /* refcount is the reference count for the following: |
| 115 | 1. Each queued request | 116 | 1. Each queued request |
| @@ -445,6 +446,8 @@ static int release_group(struct mcast_group *group, int from_timeout_handler) | |||
| 445 | } | 446 | } |
| 446 | 447 | ||
| 447 | nzgroup = memcmp(&group->rec.mgid, &mgid0, sizeof mgid0); | 448 | nzgroup = memcmp(&group->rec.mgid, &mgid0, sizeof mgid0); |
| 449 | if (nzgroup) | ||
| 450 | del_sysfs_port_mcg_attr(ctx->dev, ctx->port, &group->dentry.attr); | ||
| 448 | if (!list_empty(&group->pending_list)) | 451 | if (!list_empty(&group->pending_list)) |
| 449 | mcg_warn_group(group, "releasing a group with non empty pending list\n"); | 452 | mcg_warn_group(group, "releasing a group with non empty pending list\n"); |
| 450 | if (nzgroup) | 453 | if (nzgroup) |
| @@ -769,6 +772,7 @@ static struct mcast_group *search_relocate_mgid0_group(struct mlx4_ib_demux_ctx | |||
| 769 | } | 772 | } |
| 770 | 773 | ||
| 771 | atomic_inc(&group->refcount); | 774 | atomic_inc(&group->refcount); |
| 775 | add_sysfs_port_mcg_attr(ctx->dev, ctx->port, &group->dentry.attr); | ||
| 772 | mutex_unlock(&group->lock); | 776 | mutex_unlock(&group->lock); |
| 773 | mutex_unlock(&ctx->mcg_table_lock); | 777 | mutex_unlock(&ctx->mcg_table_lock); |
| 774 | return group; | 778 | return group; |
| @@ -796,6 +800,9 @@ static struct mcast_group *search_relocate_mgid0_group(struct mlx4_ib_demux_ctx | |||
| 796 | return NULL; | 800 | return NULL; |
| 797 | } | 801 | } |
| 798 | 802 | ||
| 803 | static ssize_t sysfs_show_group(struct device *dev, | ||
| 804 | struct device_attribute *attr, char *buf); | ||
| 805 | |||
| 799 | static struct mcast_group *acquire_group(struct mlx4_ib_demux_ctx *ctx, | 806 | static struct mcast_group *acquire_group(struct mlx4_ib_demux_ctx *ctx, |
| 800 | union ib_gid *mgid, int create, | 807 | union ib_gid *mgid, int create, |
| 801 | gfp_t gfp_mask) | 808 | gfp_t gfp_mask) |
| @@ -830,6 +837,11 @@ static struct mcast_group *acquire_group(struct mlx4_ib_demux_ctx *ctx, | |||
| 830 | sprintf(group->name, "%016llx%016llx", | 837 | sprintf(group->name, "%016llx%016llx", |
| 831 | be64_to_cpu(group->rec.mgid.global.subnet_prefix), | 838 | be64_to_cpu(group->rec.mgid.global.subnet_prefix), |
| 832 | be64_to_cpu(group->rec.mgid.global.interface_id)); | 839 | be64_to_cpu(group->rec.mgid.global.interface_id)); |
| 840 | sysfs_attr_init(&group->dentry.attr); | ||
| 841 | group->dentry.show = sysfs_show_group; | ||
| 842 | group->dentry.store = NULL; | ||
| 843 | group->dentry.attr.name = group->name; | ||
| 844 | group->dentry.attr.mode = 0400; | ||
| 833 | group->state = MCAST_IDLE; | 845 | group->state = MCAST_IDLE; |
| 834 | 846 | ||
| 835 | if (is_mgid0) { | 847 | if (is_mgid0) { |
| @@ -844,6 +856,8 @@ static struct mcast_group *acquire_group(struct mlx4_ib_demux_ctx *ctx, | |||
| 844 | return ERR_PTR(-EINVAL); | 856 | return ERR_PTR(-EINVAL); |
| 845 | } | 857 | } |
| 846 | 858 | ||
| 859 | add_sysfs_port_mcg_attr(ctx->dev, ctx->port, &group->dentry.attr); | ||
| 860 | |||
| 847 | found: | 861 | found: |
| 848 | atomic_inc(&group->refcount); | 862 | atomic_inc(&group->refcount); |
| 849 | return group; | 863 | return group; |
| @@ -969,6 +983,58 @@ int mlx4_ib_mcg_multiplex_handler(struct ib_device *ibdev, int port, | |||
| 969 | } | 983 | } |
| 970 | } | 984 | } |
| 971 | 985 | ||
| 986 | static ssize_t sysfs_show_group(struct device *dev, | ||
| 987 | struct device_attribute *attr, char *buf) | ||
| 988 | { | ||
| 989 | struct mcast_group *group = | ||
| 990 | container_of(attr, struct mcast_group, dentry); | ||
| 991 | struct mcast_req *req = NULL; | ||
| 992 | char pending_str[40]; | ||
| 993 | char state_str[40]; | ||
| 994 | ssize_t len = 0; | ||
| 995 | int f; | ||
| 996 | |||
| 997 | if (group->state == MCAST_IDLE) | ||
| 998 | sprintf(state_str, "%s", get_state_string(group->state)); | ||
