aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ehca/ehca_irq.c
diff options
context:
space:
mode:
authorJoachim Fenkes <fenkes@de.ibm.com>2007-07-09 09:32:22 -0400
committerRoland Dreier <rolandd@cisco.com>2007-07-09 23:12:27 -0400
commit8705ce5b90118be93eb8b0ed6f49ca5ff377df24 (patch)
treea7d273e77e01a4be09882aae2a8285e31e02aebf /drivers/infiniband/hw/ehca/ehca_irq.c
parentb1cfe43d4b24144596d277133e0e5b715eea1347 (diff)
IB/ehca: Notify consumers of LID/PKEY/SM changes after nondisruptive events
When firmware reports a nondisruptive port configuration change event, previous versions of the eHCA driver didn't forward the event to consumers like IPoIB. Add code that determines the type of configuration change by comparing old and new port attributes and reports it. Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ehca/ehca_irq.c')
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.c89
1 files changed, 58 insertions, 31 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 02b73c84c49b..96eba3830754 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -61,6 +61,7 @@
61#define NEQE_EVENT_CODE EHCA_BMASK_IBM(2,7) 61#define NEQE_EVENT_CODE EHCA_BMASK_IBM(2,7)
62#define NEQE_PORT_NUMBER EHCA_BMASK_IBM(8,15) 62#define NEQE_PORT_NUMBER EHCA_BMASK_IBM(8,15)
63#define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16,16) 63#define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16,16)
64#define NEQE_DISRUPTIVE EHCA_BMASK_IBM(16,16)
64 65
65#define ERROR_DATA_LENGTH EHCA_BMASK_IBM(52,63) 66#define ERROR_DATA_LENGTH EHCA_BMASK_IBM(52,63)
66#define ERROR_DATA_TYPE EHCA_BMASK_IBM(0,7) 67#define ERROR_DATA_TYPE EHCA_BMASK_IBM(0,7)
@@ -286,30 +287,61 @@ static void parse_identifier(struct ehca_shca *shca, u64 eqe)
286 return; 287 return;
287} 288}
288 289
289static void parse_ec(struct ehca_shca *shca, u64 eqe) 290static void dispatch_port_event(struct ehca_shca *shca, int port_num,
291 enum ib_event_type type, const char *msg)
290{ 292{
291 struct ib_event event; 293 struct ib_event event;
294
295 ehca_info(&shca->ib_device, "port %d %s.", port_num, msg);
296 event.device = &shca->ib_device;
297 event.event = type;
298 event.element.port_num = port_num;
299 ib_dispatch_event(&event);
300}
301
302static void notify_port_conf_change(struct ehca_shca *shca, int port_num)
303{
304 struct ehca_sma_attr new_attr;
305 struct ehca_sma_attr *old_attr = &shca->sport[port_num - 1].saved_attr;
306
307 ehca_query_sma_attr(shca, port_num, &new_attr);
308
309 if (new_attr.sm_sl != old_attr->sm_sl ||
310 new_attr.sm_lid != old_attr->sm_lid)
311 dispatch_port_event(shca, port_num, IB_EVENT_SM_CHANGE,
312 "SM changed");
313
314 if (new_attr.lid != old_attr->lid ||
315 new_attr.lmc != old_attr->lmc)
316 dispatch_port_event(shca, port_num, IB_EVENT_LID_CHANGE,
317 "LID changed");
318
319 if (new_attr.pkey_tbl_len != old_attr->pkey_tbl_len ||
320 memcmp(new_attr.pkeys, old_attr->pkeys,
321 sizeof(u16) * new_attr.pkey_tbl_len))
322 dispatch_port_event(shca, port_num, IB_EVENT_PKEY_CHANGE,
323 "P_Key changed");
324
325 *old_attr = new_attr;
326}
327
328static void parse_ec(struct ehca_shca *shca, u64 eqe)
329{
292 u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); 330 u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
293 u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); 331 u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
294 332
295 switch (ec) { 333 switch (ec) {
296 case 0x30: /* port availability change */ 334 case 0x30: /* port availability change */
297 if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { 335 if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
298 ehca_info(&shca->ib_device,
299 "port %x is active.", port);
300 event.device = &shca->ib_device;
301 event.event = IB_EVENT_PORT_ACTIVE;
302 event.element.port_num = port;
303 shca->sport[port - 1].port_state = IB_PORT_ACTIVE; 336 shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
304 ib_dispatch_event(&event); 337 dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
338 "is active");
339 ehca_query_sma_attr(shca, port,
340 &shca->sport[port - 1].saved_attr);
305 } else { 341 } else {
306 ehca_info(&shca->ib_device,
307 "port %x is inactive.", port);
308 event.device = &shca->ib_device;
309 event.event = IB_EVENT_PORT_ERR;
310 event.element.port_num = port;
311 shca->sport[port - 1].port_state = IB_PORT_DOWN; 342 shca->sport[port - 1].port_state = IB_PORT_DOWN;
312 ib_dispatch_event(&event); 343 dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
344 "is inactive");
313 } 345 }
314 break; 346 break;
315 case 0x31: 347 case 0x31:
@@ -317,24 +349,19 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
317 * disruptive change is caused by 349 * disruptive change is caused by
318 * LID, PKEY or SM change 350 * LID, PKEY or SM change
319 */ 351 */
320 ehca_warn(&shca->ib_device, 352 if (EHCA_BMASK_GET(NEQE_DISRUPTIVE, eqe)) {
321 "disruptive port %x configuration change", port); 353 ehca_warn(&shca->ib_device, "disruptive port "
322 354 "%d configuration change", port);
323 ehca_info(&shca->ib_device, 355
324 "port %x is inactive.", port); 356 shca->sport[port - 1].port_state = IB_PORT_DOWN;
325 event.device = &shca->ib_device; 357 dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
326 event.event = IB_EVENT_PORT_ERR; 358 "is inactive");
327 event.element.port_num = port; 359
328 shca->sport[port - 1].port_state = IB_PORT_DOWN; 360 shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
329 ib_dispatch_event(&event); 361 dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
330 362 "is active");
331 ehca_info(&shca->ib_device, 363 } else
332 "port %x is active.", port); 364 notify_port_conf_change(shca, port);
333 event.device = &shca->ib_device;
334 event.event = IB_EVENT_PORT_ACTIVE;
335 event.element.port_num = port;
336 shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
337 ib_dispatch_event(&event);
338 break; 365 break;
339 case 0x32: /* adapter malfunction */ 366 case 0x32: /* adapter malfunction */
340 ehca_err(&shca->ib_device, "Adapter malfunction."); 367 ehca_err(&shca->ib_device, "Adapter malfunction.");