aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ehca/ehca_irq.c
diff options
context:
space:
mode:
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.");