diff options
-rw-r--r-- | drivers/net/ehea/ehea.h | 2 | ||||
-rw-r--r-- | drivers/net/ehea/ehea_main.c | 8 | ||||
-rw-r--r-- | drivers/net/ehea/ehea_phyp.c | 10 | ||||
-rw-r--r-- | drivers/net/ehea/ehea_phyp.h | 3 | ||||
-rw-r--r-- | drivers/net/ehea/ehea_qmr.c | 42 | ||||
-rw-r--r-- | drivers/net/ehea/ehea_qmr.h | 5 |
6 files changed, 68 insertions, 2 deletions
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 272e1ec51aa2..42295d61ecd8 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h | |||
@@ -39,7 +39,7 @@ | |||
39 | #include <asm/io.h> | 39 | #include <asm/io.h> |
40 | 40 | ||
41 | #define DRV_NAME "ehea" | 41 | #define DRV_NAME "ehea" |
42 | #define DRV_VERSION "EHEA_0045" | 42 | #define DRV_VERSION "EHEA_0046" |
43 | 43 | ||
44 | #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \ | 44 | #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \ |
45 | | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) | 45 | | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) |
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 9de2d38a5321..1ef3846a5ea0 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
@@ -76,7 +76,7 @@ void ehea_dump(void *adr, int len, char *msg) { | |||
76 | int x; | 76 | int x; |
77 | unsigned char *deb = adr; | 77 | unsigned char *deb = adr; |
78 | for (x = 0; x < len; x += 16) { | 78 | for (x = 0; x < len; x += 16) { |
79 | printk(DRV_NAME "%s adr=%p ofs=%04x %016lx %016lx\n", msg, | 79 | printk(DRV_NAME " %s adr=%p ofs=%04x %016lx %016lx\n", msg, |
80 | deb, x, *((u64*)&deb[0]), *((u64*)&deb[8])); | 80 | deb, x, *((u64*)&deb[0]), *((u64*)&deb[8])); |
81 | deb += 16; | 81 | deb += 16; |
82 | } | 82 | } |
@@ -555,6 +555,7 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param) | |||
555 | { | 555 | { |
556 | struct ehea_port *port = param; | 556 | struct ehea_port *port = param; |
557 | struct ehea_eqe *eqe; | 557 | struct ehea_eqe *eqe; |
558 | struct ehea_qp *qp; | ||
558 | u32 qp_token; | 559 | u32 qp_token; |
559 | 560 | ||
560 | eqe = ehea_poll_eq(port->qp_eq); | 561 | eqe = ehea_poll_eq(port->qp_eq); |
@@ -563,9 +564,14 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param) | |||
563 | qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry); | 564 | qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry); |
564 | ehea_error("QP aff_err: entry=0x%lx, token=0x%x", | 565 | ehea_error("QP aff_err: entry=0x%lx, token=0x%x", |
565 | eqe->entry, qp_token); | 566 | eqe->entry, qp_token); |
567 | |||
568 | qp = port->port_res[qp_token].qp; | ||
569 | ehea_error_data(port->adapter, qp->fw_handle); | ||
566 | eqe = ehea_poll_eq(port->qp_eq); | 570 | eqe = ehea_poll_eq(port->qp_eq); |
567 | } | 571 | } |
568 | 572 | ||
573 | queue_work(port->adapter->ehea_wq, &port->reset_task); | ||
574 | |||
569 | return IRQ_HANDLED; | 575 | return IRQ_HANDLED; |
570 | } | 576 | } |
571 | 577 | ||
diff --git a/drivers/net/ehea/ehea_phyp.c b/drivers/net/ehea/ehea_phyp.c index 37716e05e808..bc3c00547264 100644 --- a/drivers/net/ehea/ehea_phyp.c +++ b/drivers/net/ehea/ehea_phyp.c | |||
@@ -612,3 +612,13 @@ u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle, | |||
612 | event_mask, /* R6 */ | 612 | event_mask, /* R6 */ |
613 | 0, 0, 0, 0); /* R7-R12 */ | 613 | 0, 0, 0, 0); /* R7-R12 */ |
614 | } | 614 | } |
615 | |||
616 | u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle, | ||
617 | void *rblock) | ||
618 | { | ||
619 | return ehea_plpar_hcall_norets(H_ERROR_DATA, | ||
620 | adapter_handle, /* R4 */ | ||
621 | ressource_handle, /* R5 */ | ||
622 | virt_to_abs(rblock), /* R6 */ | ||
623 | 0, 0, 0, 0); /* R7-R12 */ | ||
624 | } | ||
diff --git a/drivers/net/ehea/ehea_phyp.h b/drivers/net/ehea/ehea_phyp.h index 919f94b75933..90acddb068a1 100644 --- a/drivers/net/ehea/ehea_phyp.h +++ b/drivers/net/ehea/ehea_phyp.h | |||
@@ -454,4 +454,7 @@ u64 ehea_h_reg_dereg_bcmc(const u64 adapter_handle, const u16 port_num, | |||
454 | u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle, | 454 | u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle, |
455 | const u64 event_mask); | 455 | const u64 event_mask); |
456 | 456 | ||
457 | u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle, | ||
458 | void *rblock); | ||
459 | |||
457 | #endif /* __EHEA_PHYP_H__ */ | 460 | #endif /* __EHEA_PHYP_H__ */ |
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index f143e13b229d..96ff3b679996 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c | |||
@@ -486,6 +486,7 @@ int ehea_destroy_qp(struct ehea_qp *qp) | |||
486 | if (!qp) | 486 | if (!qp) |
487 | return 0; | 487 | return 0; |
488 | 488 | ||
489 | ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle); | ||
489 | hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle); | 490 | hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle); |
490 | if (hret != H_SUCCESS) { | 491 | if (hret != H_SUCCESS) { |
491 | ehea_error("destroy_qp failed"); | 492 | ehea_error("destroy_qp failed"); |
@@ -581,4 +582,45 @@ out: | |||
581 | return ret; | 582 | return ret; |
582 | } | 583 | } |
583 | 584 | ||
585 | void print_error_data(u64 *data) | ||
586 | { | ||
587 | int length; | ||
588 | u64 type = EHEA_BMASK_GET(ERROR_DATA_TYPE, data[2]); | ||
589 | u64 resource = data[1]; | ||
590 | |||
591 | length = EHEA_BMASK_GET(ERROR_DATA_LENGTH, data[0]); | ||
592 | |||
593 | if (length > EHEA_PAGESIZE) | ||
594 | length = EHEA_PAGESIZE; | ||
595 | |||
596 | if (type == 0x8) /* Queue Pair */ | ||
597 | ehea_error("QP (resource=%lX) state: AER=0x%lX, AERR=0x%lX, " | ||
598 | "port=%lX", resource, data[6], data[12], data[22]); | ||
599 | |||
600 | ehea_dump(data, length, "error data"); | ||
601 | } | ||
602 | |||
603 | void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle) | ||
604 | { | ||
605 | unsigned long ret; | ||
606 | u64 *rblock; | ||
607 | |||
608 | rblock = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
609 | if (!rblock) { | ||
610 | ehea_error("Cannot allocate rblock memory."); | ||
611 | return; | ||
612 | } | ||
584 | 613 | ||
614 | ret = ehea_h_error_data(adapter->handle, | ||
615 | res_handle, | ||
616 | rblock); | ||
617 | |||
618 | if (ret == H_R_STATE) | ||
619 | ehea_error("No error data is available: %lX.", res_handle); | ||
620 | else if (ret == H_SUCCESS) | ||
621 | print_error_data(rblock); | ||
622 | else | ||
623 | ehea_error("Error data could not be fetched: %lX", res_handle); | ||
624 | |||
625 | kfree(rblock); | ||
626 | } | ||
diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h index 7efdc96919ca..1ff60983504d 100644 --- a/drivers/net/ehea/ehea_qmr.h +++ b/drivers/net/ehea/ehea_qmr.h | |||
@@ -180,6 +180,9 @@ struct ehea_eqe { | |||
180 | u64 entry; | 180 | u64 entry; |
181 | }; | 181 | }; |
182 | 182 | ||
183 | #define ERROR_DATA_LENGTH EHEA_BMASK_IBM(52,63) | ||
184 | #define ERROR_DATA_TYPE EHEA_BMASK_IBM(0,7) | ||
185 | |||
183 | static inline void *hw_qeit_calc(struct hw_queue *queue, u64 q_offset) | 186 | static inline void *hw_qeit_calc(struct hw_queue *queue, u64 q_offset) |
184 | { | 187 | { |
185 | struct ehea_page *current_page; | 188 | struct ehea_page *current_page; |
@@ -355,4 +358,6 @@ int ehea_destroy_qp(struct ehea_qp *qp); | |||
355 | 358 | ||
356 | int ehea_reg_mr_adapter(struct ehea_adapter *adapter); | 359 | int ehea_reg_mr_adapter(struct ehea_adapter *adapter); |
357 | 360 | ||
361 | void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle); | ||
362 | |||
358 | #endif /* __EHEA_QMR_H__ */ | 363 | #endif /* __EHEA_QMR_H__ */ |