Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d3fd742 authored by Alex Vesker's avatar Alex Vesker Committed by Doug Ledford
Browse files

IB/sa: Add cached attribute containing SM information to SA port



Added a new SA port attribute containing SM ClassPortInfo fields,
(ClassPortInfo fields: Table 126 IB Spec 1.3.). This is useful for
checking SM support for specific features. The attribute is cached
to avoid resending queries, caching is done when a successful
ClassPortInfo reply is received on the port. Invalidation of the
attribute is done on SM change events, SM re-registration events,
and SM LID change events. The fields in ClassPortInfo should not
change during SM runtime without an event.

Signed-off-by: default avatarAlex Vesker <valex@mellanox.com>
Reviewed by: Hal Rosenstock <hal@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent d1e09f30
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -65,10 +65,17 @@ struct ib_sa_sm_ah {
	u8		     src_path_mask;
};

struct ib_sa_classport_cache {
	bool valid;
	struct ib_class_port_info data;
};

struct ib_sa_port {
	struct ib_mad_agent *agent;
	struct ib_sa_sm_ah  *sm_ah;
	struct work_struct   update_task;
	struct ib_sa_classport_cache classport_info;
	spinlock_t                   classport_lock; /* protects class port info set */
	spinlock_t           ah_lock;
	u8                   port_num;
};
@@ -998,6 +1005,13 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event
		port->sm_ah = NULL;
		spin_unlock_irqrestore(&port->ah_lock, flags);

		if (event->event == IB_EVENT_SM_CHANGE ||
		    event->event == IB_EVENT_CLIENT_REREGISTER ||
		    event->event == IB_EVENT_LID_CHANGE) {
			spin_lock_irqsave(&port->classport_lock, flags);
			port->classport_info.valid = false;
			spin_unlock_irqrestore(&port->classport_lock, flags);
		}
		queue_work(ib_wq, &sa_dev->port[event->element.port_num -
					    sa_dev->start_port].update_task);
	}
@@ -1719,6 +1733,7 @@ static void ib_sa_classport_info_rec_callback(struct ib_sa_query *sa_query,
					      int status,
					      struct ib_sa_mad *mad)
{
	unsigned long flags;
	struct ib_sa_classport_info_query *query =
		container_of(sa_query, struct ib_sa_classport_info_query, sa_query);

@@ -1728,6 +1743,16 @@ static void ib_sa_classport_info_rec_callback(struct ib_sa_query *sa_query,
		ib_unpack(classport_info_rec_table,
			  ARRAY_SIZE(classport_info_rec_table),
			  mad->data, &rec);

		spin_lock_irqsave(&sa_query->port->classport_lock, flags);
		if (!status && !sa_query->port->classport_info.valid) {
			memcpy(&sa_query->port->classport_info.data, &rec,
			       sizeof(sa_query->port->classport_info.data));

			sa_query->port->classport_info.valid = true;
		}
		spin_unlock_irqrestore(&sa_query->port->classport_lock, flags);

		query->callback(status, &rec, query->context);
	} else {
		query->callback(status, NULL, query->context);
@@ -1754,7 +1779,9 @@ int ib_sa_classport_info_rec_query(struct ib_sa_client *client,
	struct ib_sa_port *port;
	struct ib_mad_agent *agent;
	struct ib_sa_mad *mad;
	struct ib_class_port_info cached_class_port_info;
	int ret;
	unsigned long flags;

	if (!sa_dev)
		return -ENODEV;
@@ -1762,6 +1789,17 @@ int ib_sa_classport_info_rec_query(struct ib_sa_client *client,
	port  = &sa_dev->port[port_num - sa_dev->start_port];
	agent = port->agent;

	/* Use cached ClassPortInfo attribute if valid instead of sending mad */
	spin_lock_irqsave(&port->classport_lock, flags);
	if (port->classport_info.valid && callback) {
		memcpy(&cached_class_port_info, &port->classport_info.data,
		       sizeof(cached_class_port_info));
		spin_unlock_irqrestore(&port->classport_lock, flags);
		callback(0, &cached_class_port_info, context);
		return 0;
	}
	spin_unlock_irqrestore(&port->classport_lock, flags);

	query = kzalloc(sizeof(*query), gfp_mask);
	if (!query)
		return -ENOMEM;
@@ -1885,6 +1923,9 @@ static void ib_sa_add_one(struct ib_device *device)
		sa_dev->port[i].sm_ah    = NULL;
		sa_dev->port[i].port_num = i + s;

		spin_lock_init(&sa_dev->port[i].classport_lock);
		sa_dev->port[i].classport_info.valid = false;

		sa_dev->port[i].agent =
			ib_register_mad_agent(device, i + s, IB_QPT_GSI,
					      NULL, 0, send_handler,