[ofa-general] [PATCH 1/8] IB/ipath - MAD performance sampling registers support

Arthur Jones arthur.jones at qlogic.com
Tue Jan 8 13:18:00 PST 2008


From: Ralph Campbell <ralph.campbell at qlogic.com>

Add support for QLogic HCAs which have hardware performance
sampling registers for PortSamplesControl and PortSamplesResult
MADs.

Signed-off-by: Ralph Campbell <ralph.campbell at qlogic.com>
---

 drivers/infiniband/hw/ipath/ipath_kernel.h    |    9 ++
 drivers/infiniband/hw/ipath/ipath_mad.c       |  119 ++++++++++++++++---------
 drivers/infiniband/hw/ipath/ipath_registers.h |   14 +++
 drivers/infiniband/hw/ipath/ipath_verbs.c     |    1 
 drivers/infiniband/hw/ipath/ipath_verbs.h     |    2 
 5 files changed, 101 insertions(+), 44 deletions(-)

diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 977e88a..bfe84a1 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -930,6 +930,15 @@ static inline u32 ipath_read_creg32(const struct ipath_devdata *dd,
 		      (char __iomem *)dd->ipath_kregbase));
 }
 
+static inline void ipath_write_creg(const struct ipath_devdata *dd,
+				    ipath_creg regno, u64 value)
+{
+	if (dd->ipath_kregbase)
+		writeq(value, regno + (u64 __iomem *)
+		       (dd->ipath_cregbase +
+			(char __iomem *)dd->ipath_kregbase));
+}
+
 static inline void ipath_clear_rcvhdrtail(const struct ipath_portdata *pd)
 {
 	*((u64 *) pd->port_rcvhdrtail_kvaddr) = 0ULL;
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
index 1978c34..d98d5f1 100644
--- a/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -934,6 +934,7 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
 	struct ib_pma_portsamplescontrol *p =
 		(struct ib_pma_portsamplescontrol *)pmp->data;
 	struct ipath_ibdev *dev = to_idev(ibdev);
+	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
 	unsigned long flags;
 	u8 port_select = p->port_select;
 
@@ -955,7 +956,10 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
 	p->counter_width = 4;	/* 32 bit counters */
 	p->counter_mask0_9 = COUNTER_MASK0_9;
 	spin_lock_irqsave(&dev->pending_lock, flags);
-	p->sample_status = dev->pma_sample_status;
+	if (crp->cr_psstat)
+		p->sample_status = ipath_read_creg32(dev->dd, crp->cr_psstat);
+	else
+		p->sample_status = dev->pma_sample_status;
 	p->sample_start = cpu_to_be32(dev->pma_sample_start);
 	p->sample_interval = cpu_to_be32(dev->pma_sample_interval);
 	p->tag = cpu_to_be16(dev->pma_tag);
@@ -975,8 +979,9 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
 	struct ib_pma_portsamplescontrol *p =
 		(struct ib_pma_portsamplescontrol *)pmp->data;
 	struct ipath_ibdev *dev = to_idev(ibdev);
+	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
 	unsigned long flags;
-	u32 start;
+	u8 status;
 	int ret;
 
 	if (pmp->attr_mod != 0 ||
@@ -986,59 +991,67 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
 		goto bail;
 	}
 
-	start = be32_to_cpu(p->sample_start);
-	if (start != 0) {
-		spin_lock_irqsave(&dev->pending_lock, flags);
-		if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_DONE) {
-			dev->pma_sample_status =
-				IB_PMA_SAMPLE_STATUS_STARTED;
-			dev->pma_sample_start = start;
-			dev->pma_sample_interval =
-				be32_to_cpu(p->sample_interval);
-			dev->pma_tag = be16_to_cpu(p->tag);
-			if (p->counter_select[0])
-				dev->pma_counter_select[0] =
-					p->counter_select[0];
-			if (p->counter_select[1])
-				dev->pma_counter_select[1] =
-					p->counter_select[1];
-			if (p->counter_select[2])
-				dev->pma_counter_select[2] =
-					p->counter_select[2];
-			if (p->counter_select[3])
-				dev->pma_counter_select[3] =
-					p->counter_select[3];
-			if (p->counter_select[4])
-				dev->pma_counter_select[4] =
-					p->counter_select[4];
-		}
-		spin_unlock_irqrestore(&dev->pending_lock, flags);
+	spin_lock_irqsave(&dev->pending_lock, flags);
+	if (crp->cr_psstat)
+		status = ipath_read_creg32(dev->dd, crp->cr_psstat);
+	else
+		status = dev->pma_sample_status;
+	if (status == IB_PMA_SAMPLE_STATUS_DONE) {
+		dev->pma_sample_start = be32_to_cpu(p->sample_start);
+		dev->pma_sample_interval = be32_to_cpu(p->sample_interval);
+		dev->pma_tag = be16_to_cpu(p->tag);
+		dev->pma_counter_select[0] = p->counter_select[0];
+		dev->pma_counter_select[1] = p->counter_select[1];
+		dev->pma_counter_select[2] = p->counter_select[2];
+		dev->pma_counter_select[3] = p->counter_select[3];
+		dev->pma_counter_select[4] = p->counter_select[4];
+		if (crp->cr_psstat) {
+			ipath_write_creg(dev->dd, crp->cr_psinterval,
+					 dev->pma_sample_interval);
+			ipath_write_creg(dev->dd, crp->cr_psstart,
+					 dev->pma_sample_start);
+		} else
+			dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_STARTED;
 	}
+	spin_unlock_irqrestore(&dev->pending_lock, flags);
+
 	ret = recv_pma_get_portsamplescontrol(pmp, ibdev, port);
 
 bail:
 	return ret;
 }
 
-static u64 get_counter(struct ipath_ibdev *dev, __be16 sel)
+static u64 get_counter(struct ipath_ibdev *dev,
+		       struct ipath_cregs const *crp,
+		       __be16 sel)
 {
 	u64 ret;
 
 	switch (sel) {
 	case IB_PMA_PORT_XMIT_DATA:
-		ret = dev->ipath_sword;
+		ret = (crp->cr_psxmitdatacount) ?
+			ipath_read_creg32(dev->dd, crp->cr_psxmitdatacount) :
+			dev->ipath_sword;
 		break;
 	case IB_PMA_PORT_RCV_DATA:
-		ret = dev->ipath_rword;
+		ret = (crp->cr_psrcvdatacount) ?
+			ipath_read_creg32(dev->dd, crp->cr_psrcvdatacount) :
+			dev->ipath_rword;
 		break;
 	case IB_PMA_PORT_XMIT_PKTS:
-		ret = dev->ipath_spkts;
+		ret = (crp->cr_psxmitpktscount) ?
+			ipath_read_creg32(dev->dd, crp->cr_psxmitpktscount) :
+			dev->ipath_spkts;
 		break;
 	case IB_PMA_PORT_RCV_PKTS:
-		ret = dev->ipath_rpkts;
+		ret = (crp->cr_psrcvpktscount) ?
+			ipath_read_creg32(dev->dd, crp->cr_psrcvpktscount) :
+			dev->ipath_rpkts;
 		break;
 	case IB_PMA_PORT_XMIT_WAIT:
-		ret = dev->ipath_xmit_wait;
+		ret = (crp->cr_psxmitwaitcount) ?
+			ipath_read_creg32(dev->dd, crp->cr_psxmitwaitcount) :
+			dev->ipath_xmit_wait;
 		break;
 	default:
 		ret = 0;
@@ -1053,14 +1066,21 @@ static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
 	struct ib_pma_portsamplesresult *p =
 		(struct ib_pma_portsamplesresult *)pmp->data;
 	struct ipath_ibdev *dev = to_idev(ibdev);
+	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
+	u8 status;
 	int i;
 
 	memset(pmp->data, 0, sizeof(pmp->data));
 	p->tag = cpu_to_be16(dev->pma_tag);
-	p->sample_status = cpu_to_be16(dev->pma_sample_status);
+	if (crp->cr_psstat)
+		status = ipath_read_creg32(dev->dd, crp->cr_psstat);
+	else
+		status = dev->pma_sample_status;
+	p->sample_status = cpu_to_be16(status);
 	for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
-		p->counter[i] = cpu_to_be32(
-			get_counter(dev, dev->pma_counter_select[i]));
+		p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 :
+		    cpu_to_be32(
+			get_counter(dev, crp, dev->pma_counter_select[i]));
 
 	return reply((struct ib_smp *) pmp);
 }
@@ -1071,16 +1091,23 @@ static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
 	struct ib_pma_portsamplesresult_ext *p =
 		(struct ib_pma_portsamplesresult_ext *)pmp->data;
 	struct ipath_ibdev *dev = to_idev(ibdev);
+	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
+	u8 status;
 	int i;
 
 	memset(pmp->data, 0, sizeof(pmp->data));
 	p->tag = cpu_to_be16(dev->pma_tag);
-	p->sample_status = cpu_to_be16(dev->pma_sample_status);
+	if (crp->cr_psstat)
+		status = ipath_read_creg32(dev->dd, crp->cr_psstat);
+	else
+		status = dev->pma_sample_status;
+	p->sample_status = cpu_to_be16(status);
 	/* 64 bits */
 	p->extended_width = __constant_cpu_to_be32(0x80000000);
 	for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
-		p->counter[i] = cpu_to_be64(
-			get_counter(dev, dev->pma_counter_select[i]));
+		p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 :
+		    cpu_to_be64(
+			get_counter(dev, crp, dev->pma_counter_select[i]));
 
 	return reply((struct ib_smp *) pmp);
 }
@@ -1113,6 +1140,8 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
 		dev->z_local_link_integrity_errors;
 	cntrs.excessive_buffer_overrun_errors -=
 		dev->z_excessive_buffer_overrun_errors;
+	cntrs.vl15_dropped -= dev->z_vl15_dropped;
+	cntrs.vl15_dropped += dev->n_vl15_dropped;
 
 	memset(pmp->data, 0, sizeof(pmp->data));
 
@@ -1156,10 +1185,10 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
 		cntrs.excessive_buffer_overrun_errors = 0xFUL;
 	p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
 		cntrs.excessive_buffer_overrun_errors;
-	if (dev->n_vl15_dropped > 0xFFFFUL)
+	if (cntrs.vl15_dropped > 0xFFFFUL)
 		p->vl15_dropped = __constant_cpu_to_be16(0xFFFF);
 	else
-		p->vl15_dropped = cpu_to_be16((u16)dev->n_vl15_dropped);
+		p->vl15_dropped = cpu_to_be16((u16)cntrs.vl15_dropped);
 	if (cntrs.port_xmit_data > 0xFFFFFFFFUL)
 		p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF);
 	else
@@ -1262,8 +1291,10 @@ static int recv_pma_set_portcounters(struct ib_perf *pmp,
 		dev->z_excessive_buffer_overrun_errors =
 			cntrs.excessive_buffer_overrun_errors;
 
-	if (p->counter_select & IB_PMA_SEL_PORT_VL15_DROPPED)
+	if (p->counter_select & IB_PMA_SEL_PORT_VL15_DROPPED) {
 		dev->n_vl15_dropped = 0;
+		dev->z_vl15_dropped = cntrs.vl15_dropped;
+	}
 
 	if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA)
 		dev->z_port_xmit_data = cntrs.port_xmit_data;
diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h
index d7181d4..156ef14 100644
--- a/drivers/infiniband/hw/ipath/ipath_registers.h
+++ b/drivers/infiniband/hw/ipath/ipath_registers.h
@@ -469,6 +469,20 @@ struct ipath_cregs {
 	ipath_creg cr_unsupvlcnt;
 	ipath_creg cr_wordrcvcnt;
 	ipath_creg cr_wordsendcnt;
+	ipath_creg cr_vl15droppedpktcnt;
+	ipath_creg cr_rxotherlocalphyerrcnt;
+	ipath_creg cr_excessbufferovflcnt;
+	ipath_creg cr_locallinkintegrityerrcnt;
+	ipath_creg cr_rxvlerrcnt;
+	ipath_creg cr_rxdlidfltrcnt;
+	ipath_creg cr_psstat;
+	ipath_creg cr_psstart;
+	ipath_creg cr_psinterval;
+	ipath_creg cr_psrcvdatacount;
+	ipath_creg cr_psrcvpktscount;
+	ipath_creg cr_psxmitdatacount;
+	ipath_creg cr_psxmitpktscount;
+	ipath_creg cr_psxmitwaitcount;
 };
 
 #endif				/* _IPATH_REGISTERS_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index c4c9984..a2baa61 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -1641,6 +1641,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
 		cntrs.local_link_integrity_errors;
 	idev->z_excessive_buffer_overrun_errors =
 		cntrs.excessive_buffer_overrun_errors;
+	idev->z_vl15_dropped = cntrs.vl15_dropped;
 
 	/*
 	 * The system image GUID is supposed to be the same for all
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
index 6ccb54f..1c89850 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.h
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
@@ -554,6 +554,7 @@ struct ipath_ibdev {
 	u32 z_pkey_violations;			/* starting count for PMA */
 	u32 z_local_link_integrity_errors;	/* starting count for PMA */
 	u32 z_excessive_buffer_overrun_errors;	/* starting count for PMA */
+	u32 z_vl15_dropped;			/* starting count for PMA */
 	u32 n_rc_resends;
 	u32 n_rc_acks;
 	u32 n_rc_qacks;
@@ -598,6 +599,7 @@ struct ipath_verbs_counters {
 	u64 port_rcv_packets;
 	u32 local_link_integrity_errors;
 	u32 excessive_buffer_overrun_errors;
+	u32 vl15_dropped;
 };
 
 static inline struct ipath_mr *to_imr(struct ib_mr *ibmr)




More information about the general mailing list