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

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
...@@ -65,10 +65,17 @@ struct ib_sa_sm_ah { ...@@ -65,10 +65,17 @@ struct ib_sa_sm_ah {
u8 src_path_mask; u8 src_path_mask;
}; };
struct ib_sa_classport_cache {
bool valid;
struct ib_class_port_info data;
};
struct ib_sa_port { struct ib_sa_port {
struct ib_mad_agent *agent; struct ib_mad_agent *agent;
struct ib_sa_sm_ah *sm_ah; struct ib_sa_sm_ah *sm_ah;
struct work_struct update_task; 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; spinlock_t ah_lock;
u8 port_num; u8 port_num;
}; };
...@@ -998,6 +1005,13 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event ...@@ -998,6 +1005,13 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event
port->sm_ah = NULL; port->sm_ah = NULL;
spin_unlock_irqrestore(&port->ah_lock, flags); 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 - queue_work(ib_wq, &sa_dev->port[event->element.port_num -
sa_dev->start_port].update_task); sa_dev->start_port].update_task);
} }
...@@ -1719,6 +1733,7 @@ static void ib_sa_classport_info_rec_callback(struct ib_sa_query *sa_query, ...@@ -1719,6 +1733,7 @@ static void ib_sa_classport_info_rec_callback(struct ib_sa_query *sa_query,
int status, int status,
struct ib_sa_mad *mad) struct ib_sa_mad *mad)
{ {
unsigned long flags;
struct ib_sa_classport_info_query *query = struct ib_sa_classport_info_query *query =
container_of(sa_query, struct ib_sa_classport_info_query, sa_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, ...@@ -1728,6 +1743,16 @@ static void ib_sa_classport_info_rec_callback(struct ib_sa_query *sa_query,
ib_unpack(classport_info_rec_table, ib_unpack(classport_info_rec_table,
ARRAY_SIZE(classport_info_rec_table), ARRAY_SIZE(classport_info_rec_table),
mad->data, &rec); 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); query->callback(status, &rec, query->context);
} else { } else {
query->callback(status, NULL, query->context); query->callback(status, NULL, query->context);
...@@ -1754,7 +1779,9 @@ int ib_sa_classport_info_rec_query(struct ib_sa_client *client, ...@@ -1754,7 +1779,9 @@ int ib_sa_classport_info_rec_query(struct ib_sa_client *client,
struct ib_sa_port *port; struct ib_sa_port *port;
struct ib_mad_agent *agent; struct ib_mad_agent *agent;
struct ib_sa_mad *mad; struct ib_sa_mad *mad;
struct ib_class_port_info cached_class_port_info;
int ret; int ret;
unsigned long flags;
if (!sa_dev) if (!sa_dev)
return -ENODEV; return -ENODEV;
...@@ -1762,6 +1789,17 @@ int ib_sa_classport_info_rec_query(struct ib_sa_client *client, ...@@ -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]; port = &sa_dev->port[port_num - sa_dev->start_port];
agent = port->agent; 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); query = kzalloc(sizeof(*query), gfp_mask);
if (!query) if (!query)
return -ENOMEM; return -ENOMEM;
...@@ -1885,6 +1923,9 @@ static void ib_sa_add_one(struct ib_device *device) ...@@ -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].sm_ah = NULL;
sa_dev->port[i].port_num = i + s; 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 = sa_dev->port[i].agent =
ib_register_mad_agent(device, i + s, IB_QPT_GSI, ib_register_mad_agent(device, i + s, IB_QPT_GSI,
NULL, 0, send_handler, NULL, 0, send_handler,
......
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