Skip to content

Commit

Permalink
IB/ipath: MAD performance sampling registers support
Browse files Browse the repository at this point in the history
Add support for QLogic HCAs which have hardware performance sampling
registers for PortSamplesControl and PortSamplesResult MADs.

Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
  • Loading branch information
Ralph Campbell authored and Roland Dreier committed Jan 25, 2008
1 parent 7aa54bd commit 6c719ca
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 44 deletions.
9 changes: 9 additions & 0 deletions drivers/infiniband/hw/ipath/ipath_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
119 changes: 75 additions & 44 deletions drivers/infiniband/hw/ipath/ipath_mad.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
Expand All @@ -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 ||
Expand All @@ -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;
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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));

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
14 changes: 14 additions & 0 deletions drivers/infiniband/hw/ipath/ipath_registers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 change: 1 addition & 0 deletions drivers/infiniband/hw/ipath/ipath_verbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions drivers/infiniband/hw/ipath/ipath_verbs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 6c719ca

Please sign in to comment.