Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d2db9eea authored by Jan-Bernd Themann's avatar Jan-Bernd Themann Committed by Jeff Garzik
Browse files

ehea: Fixed error recovery



Error recovery for QP errors: Reset QPs and dump error information

Signed-off-by: default avatarJan-Bernd Themann <themann@de.ibm.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent eaefd5fb
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@
#include <asm/io.h>

#define DRV_NAME	"ehea"
#define DRV_VERSION	"EHEA_0045"
#define DRV_VERSION	"EHEA_0046"

#define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
	| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
+7 −1
Original line number Diff line number Diff line
@@ -555,6 +555,7 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
{
	struct ehea_port *port = param;
	struct ehea_eqe *eqe;
	struct ehea_qp *qp;
	u32 qp_token;

	eqe = ehea_poll_eq(port->qp_eq);
@@ -563,9 +564,14 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
		qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry);
		ehea_error("QP aff_err: entry=0x%lx, token=0x%x",
			   eqe->entry, qp_token);

		qp = port->port_res[qp_token].qp;
		ehea_error_data(port->adapter, qp->fw_handle);
		eqe = ehea_poll_eq(port->qp_eq);
	}

	queue_work(port->adapter->ehea_wq, &port->reset_task);

	return IRQ_HANDLED;
}

+10 −0
Original line number Diff line number Diff line
@@ -612,3 +612,13 @@ u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle,
				       event_mask,		/* R6 */
				       0, 0, 0, 0);		/* R7-R12 */
}

u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle,
		      void *rblock)
{
	return ehea_plpar_hcall_norets(H_ERROR_DATA,
				       adapter_handle,          /* R4 */
				       ressource_handle,        /* R5 */
				       virt_to_abs(rblock),     /* R6 */
				       0, 0, 0, 0);             /* R7-R12 */
}
+3 −0
Original line number Diff line number Diff line
@@ -454,4 +454,7 @@ u64 ehea_h_reg_dereg_bcmc(const u64 adapter_handle, const u16 port_num,
u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle,
			const u64 event_mask);

u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle,
		      void *rblock);

#endif	/* __EHEA_PHYP_H__ */
+42 −0
Original line number Diff line number Diff line
@@ -486,6 +486,7 @@ int ehea_destroy_qp(struct ehea_qp *qp)
	if (!qp)
		return 0;

	ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
	hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle);
	if (hret != H_SUCCESS) {
		ehea_error("destroy_qp failed");
@@ -581,4 +582,45 @@ out:
	return ret;
}

void print_error_data(u64 *data)
{
	int length;
	u64 type = EHEA_BMASK_GET(ERROR_DATA_TYPE, data[2]);
	u64 resource = data[1];

	length = EHEA_BMASK_GET(ERROR_DATA_LENGTH, data[0]);

	if (length > EHEA_PAGESIZE)
		length = EHEA_PAGESIZE;

	if (type == 0x8) /* Queue Pair */
		ehea_error("QP (resource=%lX) state: AER=0x%lX, AERR=0x%lX, "
			   "port=%lX", resource, data[6], data[12], data[22]);

	ehea_dump(data, length, "error data");
}

void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle)
{
	unsigned long ret;
	u64 *rblock;

	rblock = kzalloc(PAGE_SIZE, GFP_KERNEL);
	if (!rblock) {
		ehea_error("Cannot allocate rblock memory.");
		return;
	}

	ret = ehea_h_error_data(adapter->handle,
				res_handle,
				rblock);

	if (ret == H_R_STATE)
		ehea_error("No error data is available: %lX.", res_handle);
	else if (ret == H_SUCCESS)
		print_error_data(rblock);
	else
		ehea_error("Error data could not be fetched: %lX", res_handle);

	kfree(rblock);
}
Loading