diff options
Diffstat (limited to 'drivers/infiniband/hw/ehca/ehca_irq.c')
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_irq.c | 89 |
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 | ||
289 | static void parse_ec(struct ehca_shca *shca, u64 eqe) | 290 | static 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 | |||
302 | static 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 | |||
328 | static 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."); |