Commit 526a12c8 authored by Jason Gunthorpe's avatar Jason Gunthorpe
Browse files

RDMA/cm: Use an attribute_group on the ib_port_attribute intead of kobj's

This code is trying to attach a list of counters grouped into 4 groups to
the ib_port sysfs. Instead of creating a bunch of kobjects simply express
everything naturally as an ib_port_attribute and add a single
attribute_groups list.

Remove all the naked kobject manipulations.

Link: https://lore.kernel.org/r/0d5a7241ee0fe66622de04fcbaafaf6a791d5c7c.1623427137.git.leonro@nvidia.com


Signed-off-by: default avatarLeon Romanovsky <leonro@nvidia.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent 054239f4
Loading
Loading
Loading
Loading
+100 −127
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@

#include <rdma/ib_cache.h>
#include <rdma/ib_cm.h>
#include <rdma/ib_sysfs.h>
#include "cm_msgs.h"
#include "core_priv.h"
#include "cm_trace.h"
@@ -148,60 +149,17 @@ enum {
	CM_COUNTER_GROUPS
};

static char const counter_group_names[CM_COUNTER_GROUPS]
				     [sizeof("cm_rx_duplicates")] = {
	"cm_tx_msgs", "cm_tx_retries",
	"cm_rx_msgs", "cm_rx_duplicates"
};

struct cm_counter_group {
	struct kobject obj;
	atomic_long_t counter[CM_ATTR_COUNT];
};

struct cm_counter_attribute {
	struct attribute attr;
	int index;
};

#define CM_COUNTER_ATTR(_name, _index) \
struct cm_counter_attribute cm_##_name##_counter_attr = { \
	.attr = { .name = __stringify(_name), .mode = 0444 }, \
	.index = _index \
}

static CM_COUNTER_ATTR(req, CM_REQ_COUNTER);
static CM_COUNTER_ATTR(mra, CM_MRA_COUNTER);
static CM_COUNTER_ATTR(rej, CM_REJ_COUNTER);
static CM_COUNTER_ATTR(rep, CM_REP_COUNTER);
static CM_COUNTER_ATTR(rtu, CM_RTU_COUNTER);
static CM_COUNTER_ATTR(dreq, CM_DREQ_COUNTER);
static CM_COUNTER_ATTR(drep, CM_DREP_COUNTER);
static CM_COUNTER_ATTR(sidr_req, CM_SIDR_REQ_COUNTER);
static CM_COUNTER_ATTR(sidr_rep, CM_SIDR_REP_COUNTER);
static CM_COUNTER_ATTR(lap, CM_LAP_COUNTER);
static CM_COUNTER_ATTR(apr, CM_APR_COUNTER);

static struct attribute *cm_counter_default_attrs[] = {
	&cm_req_counter_attr.attr,
	&cm_mra_counter_attr.attr,
	&cm_rej_counter_attr.attr,
	&cm_rep_counter_attr.attr,
	&cm_rtu_counter_attr.attr,
	&cm_dreq_counter_attr.attr,
	&cm_drep_counter_attr.attr,
	&cm_sidr_req_counter_attr.attr,
	&cm_sidr_rep_counter_attr.attr,
	&cm_lap_counter_attr.attr,
	&cm_apr_counter_attr.attr,
	NULL
	struct ib_port_attribute attr;
	unsigned short group;
	unsigned short index;
};

struct cm_port {
	struct cm_device *cm_dev;
	struct ib_mad_agent *mad_agent;
	u32 port_num;
	struct cm_counter_group counter_group[CM_COUNTER_GROUPS];
	atomic_long_t counters[CM_COUNTER_GROUPS][CM_ATTR_COUNT];
};

struct cm_device {
@@ -1964,8 +1922,8 @@ static void cm_dup_req_handler(struct cm_work *work,
	struct ib_mad_send_buf *msg = NULL;
	int ret;

	atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
			counter[CM_REQ_COUNTER]);
	atomic_long_inc(
		&work->port->counters[CM_RECV_DUPLICATES][CM_REQ_COUNTER]);

	/* Quick state check to discard duplicate REQs. */
	spin_lock_irq(&cm_id_priv->lock);
@@ -2463,8 +2421,8 @@ static void cm_dup_rep_handler(struct cm_work *work)
	if (!cm_id_priv)
		return;

	atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
			counter[CM_REP_COUNTER]);
	atomic_long_inc(
		&work->port->counters[CM_RECV_DUPLICATES][CM_REP_COUNTER]);
	ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg);
	if (ret)
		goto deref;
@@ -2641,8 +2599,8 @@ static int cm_rtu_handler(struct cm_work *work)
	if (cm_id_priv->id.state != IB_CM_REP_SENT &&
	    cm_id_priv->id.state != IB_CM_MRA_REP_RCVD) {
		spin_unlock_irq(&cm_id_priv->lock);
		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
				counter[CM_RTU_COUNTER]);
		atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
						     [CM_RTU_COUNTER]);
		goto out;
	}
	cm_id_priv->id.state = IB_CM_ESTABLISHED;
@@ -2846,8 +2804,8 @@ static int cm_dreq_handler(struct cm_work *work)
		cpu_to_be32(IBA_GET(CM_DREQ_REMOTE_COMM_ID, dreq_msg)),
		cpu_to_be32(IBA_GET(CM_DREQ_LOCAL_COMM_ID, dreq_msg)));
	if (!cm_id_priv) {
		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
				counter[CM_DREQ_COUNTER]);
		atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
						     [CM_DREQ_COUNTER]);
		cm_issue_drep(work->port, work->mad_recv_wc);
		trace_icm_no_priv_err(
			IBA_GET(CM_DREQ_LOCAL_COMM_ID, dreq_msg),
@@ -2876,8 +2834,8 @@ static int cm_dreq_handler(struct cm_work *work)
	case IB_CM_MRA_REP_RCVD:
		break;
	case IB_CM_TIMEWAIT:
		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
				counter[CM_DREQ_COUNTER]);
		atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
						     [CM_DREQ_COUNTER]);
		msg = cm_alloc_response_msg_no_ah(work->port, work->mad_recv_wc);
		if (IS_ERR(msg))
			goto unlock;
@@ -2892,8 +2850,8 @@ static int cm_dreq_handler(struct cm_work *work)
			cm_free_response_msg(msg);
		goto deref;
	case IB_CM_DREQ_RCVD:
		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
				counter[CM_DREQ_COUNTER]);
		atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
						     [CM_DREQ_COUNTER]);
		goto unlock;
	default:
		trace_icm_dreq_unknown_err(&cm_id_priv->id);
@@ -3244,17 +3202,17 @@ static int cm_mra_handler(struct cm_work *work)
		    cm_id_priv->id.lap_state != IB_CM_LAP_SENT ||
		    ib_modify_mad(cm_id_priv->msg, timeout)) {
			if (cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD)
				atomic_long_inc(&work->port->
						counter_group[CM_RECV_DUPLICATES].
						counter[CM_MRA_COUNTER]);
				atomic_long_inc(
					&work->port->counters[CM_RECV_DUPLICATES]
							     [CM_MRA_COUNTER]);
			goto out;
		}
		cm_id_priv->id.lap_state = IB_CM_MRA_LAP_RCVD;
		break;
	case IB_CM_MRA_REQ_RCVD:
	case IB_CM_MRA_REP_RCVD:
		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
				counter[CM_MRA_COUNTER]);
		atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
						     [CM_MRA_COUNTER]);
		fallthrough;
	default:
		trace_icm_mra_unknown_err(&cm_id_priv->id);
@@ -3380,8 +3338,8 @@ static int cm_lap_handler(struct cm_work *work)
	case IB_CM_LAP_IDLE:
		break;
	case IB_CM_MRA_LAP_SENT:
		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
				counter[CM_LAP_COUNTER]);
		atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
						     [CM_LAP_COUNTER]);
		msg = cm_alloc_response_msg_no_ah(work->port, work->mad_recv_wc);
		if (IS_ERR(msg))
			goto unlock;
@@ -3398,8 +3356,8 @@ static int cm_lap_handler(struct cm_work *work)
			cm_free_response_msg(msg);
		goto deref;
	case IB_CM_LAP_RCVD:
		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
				counter[CM_LAP_COUNTER]);
		atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
						     [CM_LAP_COUNTER]);
		goto unlock;
	default:
		goto unlock;
@@ -3617,8 +3575,8 @@ static int cm_sidr_req_handler(struct cm_work *work)
	listen_cm_id_priv = cm_insert_remote_sidr(cm_id_priv);
	if (listen_cm_id_priv) {
		spin_unlock_irq(&cm.lock);
		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
				counter[CM_SIDR_REQ_COUNTER]);
		atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
						     [CM_SIDR_REQ_COUNTER]);
		goto out; /* Duplicate message. */
	}
	cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
@@ -3867,12 +3825,10 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent,
	if (!cm_id_priv && (attr_index != CM_REJ_COUNTER))
		msg->retries = 1;

	atomic_long_add(1 + msg->retries,
			&port->counter_group[CM_XMIT].counter[attr_index]);
	atomic_long_add(1 + msg->retries, &port->counters[CM_XMIT][attr_index]);
	if (msg->retries)
		atomic_long_add(msg->retries,
				&port->counter_group[CM_XMIT_RETRIES].
				counter[attr_index]);
				&port->counters[CM_XMIT_RETRIES][attr_index]);

	if (cm_id_priv)
		cm_process_send_error(cm_id_priv, msg, state,
@@ -4093,8 +4049,7 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent,
	}

	attr_id = be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id);
	atomic_long_inc(&port->counter_group[CM_RECV].
			counter[attr_id - CM_ATTR_ID_OFFSET]);
	atomic_long_inc(&port->counters[CM_RECV][attr_id - CM_ATTR_ID_OFFSET]);

	work = kmalloc(struct_size(work, path, paths), GFP_KERNEL);
	if (!work) {
@@ -4296,60 +4251,75 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
}
EXPORT_SYMBOL(ib_cm_init_qp_attr);

static ssize_t cm_show_counter(struct kobject *obj, struct attribute *attr,
			       char *buf)
static ssize_t cm_show_counter(struct ib_device *ibdev, u32 port_num,
			       struct ib_port_attribute *attr, char *buf)
{
	struct cm_counter_group *group;
	struct cm_counter_attribute *cm_attr;
	struct cm_counter_attribute *cm_attr =
		container_of(attr, struct cm_counter_attribute, attr);
	struct cm_device *cm_dev = ib_get_client_data(ibdev, &cm_client);

	group = container_of(obj, struct cm_counter_group, obj);
	cm_attr = container_of(attr, struct cm_counter_attribute, attr);

	return sysfs_emit(buf, "%ld\n",
			  atomic_long_read(&group->counter[cm_attr->index]));
}
	if (WARN_ON(!cm_dev))
		return -EINVAL;

static const struct sysfs_ops cm_counter_ops = {
	.show = cm_show_counter
	return sysfs_emit(
		buf, "%ld\n",
		atomic_long_read(
			&cm_dev->port[port_num - 1]
				 ->counters[cm_attr->group][cm_attr->index]));
}

#define CM_COUNTER_ATTR(_name, _group, _index)                                 \
	{                                                                      \
		.attr = __ATTR(_name, 0444, cm_show_counter, NULL),            \
		.group = _group, .index = _index                               \
	}

#define CM_COUNTER_GROUP(_group, _name)                                        \
	static struct cm_counter_attribute cm_counter_attr_##_group[] = {      \
		CM_COUNTER_ATTR(req, _group, CM_REQ_COUNTER),                  \
		CM_COUNTER_ATTR(mra, _group, CM_MRA_COUNTER),                  \
		CM_COUNTER_ATTR(rej, _group, CM_REJ_COUNTER),                  \
		CM_COUNTER_ATTR(rep, _group, CM_REP_COUNTER),                  \
		CM_COUNTER_ATTR(rtu, _group, CM_RTU_COUNTER),                  \
		CM_COUNTER_ATTR(dreq, _group, CM_DREQ_COUNTER),                \
		CM_COUNTER_ATTR(drep, _group, CM_DREP_COUNTER),                \
		CM_COUNTER_ATTR(sidr_req, _group, CM_SIDR_REQ_COUNTER),        \
		CM_COUNTER_ATTR(sidr_rep, _group, CM_SIDR_REP_COUNTER),        \
		CM_COUNTER_ATTR(lap, _group, CM_LAP_COUNTER),                  \
		CM_COUNTER_ATTR(apr, _group, CM_APR_COUNTER),                  \
	};                                                                     \
	static struct attribute *cm_counter_attrs_##_group[] = {               \
		&cm_counter_attr_##_group[0].attr.attr,                        \
		&cm_counter_attr_##_group[1].attr.attr,                        \
		&cm_counter_attr_##_group[2].attr.attr,                        \
		&cm_counter_attr_##_group[3].attr.attr,                        \
		&cm_counter_attr_##_group[4].attr.attr,                        \
		&cm_counter_attr_##_group[5].attr.attr,                        \
		&cm_counter_attr_##_group[6].attr.attr,                        \
		&cm_counter_attr_##_group[7].attr.attr,                        \
		&cm_counter_attr_##_group[8].attr.attr,                        \
		&cm_counter_attr_##_group[9].attr.attr,                        \
		&cm_counter_attr_##_group[10].attr.attr,                       \
		NULL,                                                          \
	};                                                                     \
	static const struct attribute_group cm_counter_group_##_group = {      \
		.name = _name,                                                 \
		.attrs = cm_counter_attrs_##_group,                            \
	};

static struct kobj_type cm_counter_obj_type = {
	.sysfs_ops = &cm_counter_ops,
	.default_attrs = cm_counter_default_attrs
CM_COUNTER_GROUP(CM_XMIT, "cm_tx_msgs")
CM_COUNTER_GROUP(CM_XMIT_RETRIES, "cm_tx_retries")
CM_COUNTER_GROUP(CM_RECV, "cm_rx_msgs")
CM_COUNTER_GROUP(CM_RECV_DUPLICATES, "cm_rx_duplicates")

static const struct attribute_group *cm_counter_groups[] = {
	&cm_counter_group_CM_XMIT,
	&cm_counter_group_CM_XMIT_RETRIES,
	&cm_counter_group_CM_RECV,
	&cm_counter_group_CM_RECV_DUPLICATES,
	NULL,
};

static int cm_create_port_fs(struct cm_port *port)
{
	int i, ret;

	for (i = 0; i < CM_COUNTER_GROUPS; i++) {
		ret = ib_port_register_module_stat(port->cm_dev->ib_device,
						   port->port_num,
						   &port->counter_group[i].obj,
						   &cm_counter_obj_type,
						   counter_group_names[i]);
		if (ret)
			goto error;
	}

	return 0;

error:
	while (i--)
		ib_port_unregister_module_stat(&port->counter_group[i].obj);
	return ret;

}

static void cm_remove_port_fs(struct cm_port *port)
{
	int i;

	for (i = 0; i < CM_COUNTER_GROUPS; i++)
		ib_port_unregister_module_stat(&port->counter_group[i].obj);

}

static int cm_add_one(struct ib_device *ib_device)
{
	struct cm_device *cm_dev;
@@ -4377,6 +4347,8 @@ static int cm_add_one(struct ib_device *ib_device)
	cm_dev->ack_delay = ib_device->attrs.local_ca_ack_delay;
	cm_dev->going_down = 0;

	ib_set_client_data(ib_device, &cm_client, cm_dev);

	set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
	rdma_for_each_port (ib_device, i) {
		if (!rdma_cap_ib_cm(ib_device, i))
@@ -4392,7 +4364,8 @@ static int cm_add_one(struct ib_device *ib_device)
		port->cm_dev = cm_dev;
		port->port_num = i;

		ret = cm_create_port_fs(port);
		ret = ib_port_register_client_groups(ib_device, i,
						     cm_counter_groups);
		if (ret)
			goto error1;

@@ -4421,8 +4394,6 @@ static int cm_add_one(struct ib_device *ib_device)
		goto free;
	}

	ib_set_client_data(ib_device, &cm_client, cm_dev);

	write_lock_irqsave(&cm.device_lock, flags);
	list_add_tail(&cm_dev->list, &cm.device_list);
	write_unlock_irqrestore(&cm.device_lock, flags);
@@ -4431,7 +4402,7 @@ static int cm_add_one(struct ib_device *ib_device)
error3:
	ib_unregister_mad_agent(port->mad_agent);
error2:
	cm_remove_port_fs(port);
	ib_port_unregister_client_groups(ib_device, i, cm_counter_groups);
error1:
	port_modify.set_port_cap_mask = 0;
	port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
@@ -4442,7 +4413,8 @@ static int cm_add_one(struct ib_device *ib_device)
		port = cm_dev->port[i-1];
		ib_modify_port(ib_device, port->port_num, 0, &port_modify);
		ib_unregister_mad_agent(port->mad_agent);
		cm_remove_port_fs(port);
		ib_port_unregister_client_groups(ib_device, i,
						 cm_counter_groups);
	}
free:
	cm_device_put(cm_dev);
@@ -4490,7 +4462,8 @@ static void cm_remove_one(struct ib_device *ib_device, void *client_data)
		port->mad_agent = NULL;
		spin_unlock(&cm_dev->mad_agent_lock);
		ib_unregister_mad_agent(mad_agent);
		cm_remove_port_fs(port);
		ib_port_unregister_client_groups(ib_device, i,
						 cm_counter_groups);
	}

	cm_device_put(cm_dev);
+4 −4
Original line number Diff line number Diff line
@@ -382,10 +382,10 @@ int ib_setup_device_attrs(struct ib_device *ibdev);

int rdma_compatdev_set(u8 enable);

int ib_port_register_module_stat(struct ib_device *device, u32 port_num,
				 struct kobject *kobj, struct kobj_type *ktype,
				 const char *name);
void ib_port_unregister_module_stat(struct kobject *kobj);
int ib_port_register_client_groups(struct ib_device *ibdev, u32 port_num,
				   const struct attribute_group **groups);
void ib_port_unregister_client_groups(struct ib_device *ibdev, u32 port_num,
				     const struct attribute_group **groups);

int ib_device_set_netns_put(struct sk_buff *skb,
			    struct ib_device *dev, u32 ns_fd);
+15 −35
Original line number Diff line number Diff line
@@ -1448,46 +1448,26 @@ int ib_setup_port_attrs(struct ib_core_device *coredev)
}

/**
 * ib_port_register_module_stat - add module counters under relevant port
 *  of IB device.
 * ib_port_register_client_groups - Add an ib_client's attributes to the port
 *
 * @device: IB device to add counters
 * @ibdev: IB device to add counters
 * @port_num: valid port number
 * @kobj: pointer to the kobject to initialize
 * @ktype: pointer to the ktype for this kobject.
 * @name: the name of the kobject
 * @groups: Group list of attributes
 *
 * Do not use. Only for legacy sysfs compatibility.
 */
int ib_port_register_module_stat(struct ib_device *device, u32 port_num,
				 struct kobject *kobj, struct kobj_type *ktype,
				 const char *name)
int ib_port_register_client_groups(struct ib_device *ibdev, u32 port_num,
				   const struct attribute_group **groups)
{
	struct kobject *p, *t;
	int ret;

	list_for_each_entry_safe(p, t, &device->coredev.port_list, entry) {
		struct ib_port *port = container_of(p, struct ib_port, kobj);

		if (port->port_num != port_num)
			continue;

		ret = kobject_init_and_add(kobj, ktype, &port->kobj, "%s",
					   name);
		if (ret) {
			kobject_put(kobj);
			return ret;
		}
	}

	return 0;
	return sysfs_create_groups(&ibdev->port_data[port_num].sysfs->kobj,
				   groups);
}
EXPORT_SYMBOL(ib_port_register_module_stat);
EXPORT_SYMBOL(ib_port_register_client_groups);

/**
 * ib_port_unregister_module_stat - release module counters
 * @kobj: pointer to the kobject to release
 */
void ib_port_unregister_module_stat(struct kobject *kobj)
void ib_port_unregister_client_groups(struct ib_device *ibdev, u32 port_num,
				      const struct attribute_group **groups)
{
	kobject_put(kobj);
	return sysfs_remove_groups(&ibdev->port_data[port_num].sysfs->kobj,
				   groups);
}
EXPORT_SYMBOL(ib_port_unregister_module_stat);
EXPORT_SYMBOL(ib_port_unregister_client_groups);