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

Commit 6c719cae authored by Ralph Campbell's avatar Ralph Campbell Committed by Roland Dreier
Browse files

IB/ipath: MAD performance sampling registers support



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

Signed-off-by: default avatarRalph Campbell <ralph.campbell@qlogic.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 7aa54bd7
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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;
+75 −44
Original line number Diff line number Diff line
@@ -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,6 +956,9 @@ 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);
	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);
@@ -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);
	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);
			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];
		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;
+14 −0
Original line number Diff line number Diff line
@@ -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 */
+1 −0
Original line number Diff line number Diff line
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -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)