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

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
...@@ -930,6 +930,15 @@ static inline u32 ipath_read_creg32(const struct ipath_devdata *dd, ...@@ -930,6 +930,15 @@ static inline u32 ipath_read_creg32(const struct ipath_devdata *dd,
(char __iomem *)dd->ipath_kregbase)); (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) static inline void ipath_clear_rcvhdrtail(const struct ipath_portdata *pd)
{ {
*((u64 *) pd->port_rcvhdrtail_kvaddr) = 0ULL; *((u64 *) pd->port_rcvhdrtail_kvaddr) = 0ULL;
......
...@@ -934,6 +934,7 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp, ...@@ -934,6 +934,7 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
struct ib_pma_portsamplescontrol *p = struct ib_pma_portsamplescontrol *p =
(struct ib_pma_portsamplescontrol *)pmp->data; (struct ib_pma_portsamplescontrol *)pmp->data;
struct ipath_ibdev *dev = to_idev(ibdev); struct ipath_ibdev *dev = to_idev(ibdev);
struct ipath_cregs const *crp = dev->dd->ipath_cregs;
unsigned long flags; unsigned long flags;
u8 port_select = p->port_select; u8 port_select = p->port_select;
...@@ -955,6 +956,9 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp, ...@@ -955,6 +956,9 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
p->counter_width = 4; /* 32 bit counters */ p->counter_width = 4; /* 32 bit counters */
p->counter_mask0_9 = COUNTER_MASK0_9; p->counter_mask0_9 = COUNTER_MASK0_9;
spin_lock_irqsave(&dev->pending_lock, flags); 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_status = dev->pma_sample_status;
p->sample_start = cpu_to_be32(dev->pma_sample_start); p->sample_start = cpu_to_be32(dev->pma_sample_start);
p->sample_interval = cpu_to_be32(dev->pma_sample_interval); p->sample_interval = cpu_to_be32(dev->pma_sample_interval);
...@@ -975,8 +979,9 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp, ...@@ -975,8 +979,9 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
struct ib_pma_portsamplescontrol *p = struct ib_pma_portsamplescontrol *p =
(struct ib_pma_portsamplescontrol *)pmp->data; (struct ib_pma_portsamplescontrol *)pmp->data;
struct ipath_ibdev *dev = to_idev(ibdev); struct ipath_ibdev *dev = to_idev(ibdev);
struct ipath_cregs const *crp = dev->dd->ipath_cregs;
unsigned long flags; unsigned long flags;
u32 start; u8 status;
int ret; int ret;
if (pmp->attr_mod != 0 || if (pmp->attr_mod != 0 ||
...@@ -986,59 +991,67 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp, ...@@ -986,59 +991,67 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
goto bail; goto bail;
} }
start = be32_to_cpu(p->sample_start);
if (start != 0) {
spin_lock_irqsave(&dev->pending_lock, flags); spin_lock_irqsave(&dev->pending_lock, flags);
if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_DONE) { if (crp->cr_psstat)
dev->pma_sample_status = status = ipath_read_creg32(dev->dd, crp->cr_psstat);
IB_PMA_SAMPLE_STATUS_STARTED; else
dev->pma_sample_start = start; status = dev->pma_sample_status;
dev->pma_sample_interval = if (status == IB_PMA_SAMPLE_STATUS_DONE) {
be32_to_cpu(p->sample_interval); 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_tag = be16_to_cpu(p->tag);
if (p->counter_select[0]) dev->pma_counter_select[0] = p->counter_select[0];
dev->pma_counter_select[0] = dev->pma_counter_select[1] = p->counter_select[1];
p->counter_select[0]; dev->pma_counter_select[2] = p->counter_select[2];
if (p->counter_select[1]) dev->pma_counter_select[3] = p->counter_select[3];
dev->pma_counter_select[1] = dev->pma_counter_select[4] = p->counter_select[4];
p->counter_select[1]; if (crp->cr_psstat) {
if (p->counter_select[2]) ipath_write_creg(dev->dd, crp->cr_psinterval,
dev->pma_counter_select[2] = dev->pma_sample_interval);
p->counter_select[2]; ipath_write_creg(dev->dd, crp->cr_psstart,
if (p->counter_select[3]) dev->pma_sample_start);
dev->pma_counter_select[3] = } else
p->counter_select[3]; dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_STARTED;
if (p->counter_select[4])
dev->pma_counter_select[4] =
p->counter_select[4];
} }
spin_unlock_irqrestore(&dev->pending_lock, flags); spin_unlock_irqrestore(&dev->pending_lock, flags);
}
ret = recv_pma_get_portsamplescontrol(pmp, ibdev, port); ret = recv_pma_get_portsamplescontrol(pmp, ibdev, port);
bail: bail:
return ret; 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; u64 ret;
switch (sel) { switch (sel) {
case IB_PMA_PORT_XMIT_DATA: 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; break;
case IB_PMA_PORT_RCV_DATA: 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; break;
case IB_PMA_PORT_XMIT_PKTS: 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; break;
case IB_PMA_PORT_RCV_PKTS: 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; break;
case IB_PMA_PORT_XMIT_WAIT: 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; break;
default: default:
ret = 0; ret = 0;
...@@ -1053,14 +1066,21 @@ static int recv_pma_get_portsamplesresult(struct ib_perf *pmp, ...@@ -1053,14 +1066,21 @@ static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
struct ib_pma_portsamplesresult *p = struct ib_pma_portsamplesresult *p =
(struct ib_pma_portsamplesresult *)pmp->data; (struct ib_pma_portsamplesresult *)pmp->data;
struct ipath_ibdev *dev = to_idev(ibdev); struct ipath_ibdev *dev = to_idev(ibdev);
struct ipath_cregs const *crp = dev->dd->ipath_cregs;
u8 status;
int i; int i;
memset(pmp->data, 0, sizeof(pmp->data)); memset(pmp->data, 0, sizeof(pmp->data));
p->tag = cpu_to_be16(dev->pma_tag); 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++) for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
p->counter[i] = cpu_to_be32( p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 :
get_counter(dev, dev->pma_counter_select[i])); cpu_to_be32(
get_counter(dev, crp, dev->pma_counter_select[i]));
return reply((struct ib_smp *) pmp); return reply((struct ib_smp *) pmp);
} }
...@@ -1071,16 +1091,23 @@ static int recv_pma_get_portsamplesresult_ext(struct ib_perf *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 *p =
(struct ib_pma_portsamplesresult_ext *)pmp->data; (struct ib_pma_portsamplesresult_ext *)pmp->data;
struct ipath_ibdev *dev = to_idev(ibdev); struct ipath_ibdev *dev = to_idev(ibdev);
struct ipath_cregs const *crp = dev->dd->ipath_cregs;
u8 status;
int i; int i;
memset(pmp->data, 0, sizeof(pmp->data)); memset(pmp->data, 0, sizeof(pmp->data));
p->tag = cpu_to_be16(dev->pma_tag); 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 */ /* 64 bits */
p->extended_width = __constant_cpu_to_be32(0x80000000); p->extended_width = __constant_cpu_to_be32(0x80000000);
for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++) for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
p->counter[i] = cpu_to_be64( p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 :
get_counter(dev, dev->pma_counter_select[i])); cpu_to_be64(
get_counter(dev, crp, dev->pma_counter_select[i]));
return reply((struct ib_smp *) pmp); return reply((struct ib_smp *) pmp);
} }
...@@ -1113,6 +1140,8 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp, ...@@ -1113,6 +1140,8 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
dev->z_local_link_integrity_errors; dev->z_local_link_integrity_errors;
cntrs.excessive_buffer_overrun_errors -= cntrs.excessive_buffer_overrun_errors -=
dev->z_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)); memset(pmp->data, 0, sizeof(pmp->data));
...@@ -1156,10 +1185,10 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp, ...@@ -1156,10 +1185,10 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
cntrs.excessive_buffer_overrun_errors = 0xFUL; cntrs.excessive_buffer_overrun_errors = 0xFUL;
p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) | p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
cntrs.excessive_buffer_overrun_errors; cntrs.excessive_buffer_overrun_errors;
if (dev->n_vl15_dropped > 0xFFFFUL) if (cntrs.vl15_dropped > 0xFFFFUL)
p->vl15_dropped = __constant_cpu_to_be16(0xFFFF); p->vl15_dropped = __constant_cpu_to_be16(0xFFFF);
else 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) if (cntrs.port_xmit_data > 0xFFFFFFFFUL)
p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF); p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF);
else else
...@@ -1262,8 +1291,10 @@ static int recv_pma_set_portcounters(struct ib_perf *pmp, ...@@ -1262,8 +1291,10 @@ static int recv_pma_set_portcounters(struct ib_perf *pmp,
dev->z_excessive_buffer_overrun_errors = dev->z_excessive_buffer_overrun_errors =
cntrs.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->n_vl15_dropped = 0;
dev->z_vl15_dropped = cntrs.vl15_dropped;
}
if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA) if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA)
dev->z_port_xmit_data = cntrs.port_xmit_data; dev->z_port_xmit_data = cntrs.port_xmit_data;
......
...@@ -469,6 +469,20 @@ struct ipath_cregs { ...@@ -469,6 +469,20 @@ struct ipath_cregs {
ipath_creg cr_unsupvlcnt; ipath_creg cr_unsupvlcnt;
ipath_creg cr_wordrcvcnt; ipath_creg cr_wordrcvcnt;
ipath_creg cr_wordsendcnt; 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 */ #endif /* _IPATH_REGISTERS_H */
...@@ -1641,6 +1641,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd) ...@@ -1641,6 +1641,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
cntrs.local_link_integrity_errors; cntrs.local_link_integrity_errors;
idev->z_excessive_buffer_overrun_errors = idev->z_excessive_buffer_overrun_errors =
cntrs.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 * The system image GUID is supposed to be the same for all
......
...@@ -554,6 +554,7 @@ struct ipath_ibdev { ...@@ -554,6 +554,7 @@ struct ipath_ibdev {
u32 z_pkey_violations; /* starting count for PMA */ u32 z_pkey_violations; /* starting count for PMA */
u32 z_local_link_integrity_errors; /* 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_excessive_buffer_overrun_errors; /* starting count for PMA */
u32 z_vl15_dropped; /* starting count for PMA */
u32 n_rc_resends; u32 n_rc_resends;
u32 n_rc_acks; u32 n_rc_acks;
u32 n_rc_qacks; u32 n_rc_qacks;
...@@ -598,6 +599,7 @@ struct ipath_verbs_counters { ...@@ -598,6 +599,7 @@ struct ipath_verbs_counters {
u64 port_rcv_packets; u64 port_rcv_packets;
u32 local_link_integrity_errors; u32 local_link_integrity_errors;
u32 excessive_buffer_overrun_errors; u32 excessive_buffer_overrun_errors;
u32 vl15_dropped;
}; };
static inline struct ipath_mr *to_imr(struct ib_mr *ibmr) static inline struct ipath_mr *to_imr(struct ib_mr *ibmr)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment