IB/ipath: MAD performance sampling registers support
authorRalph Campbell <ralph.campbell@qlogic.com>
Mon, 7 Jan 2008 05:02:33 +0000 (21:02 -0800)
committerRoland Dreier <rolandd@cisco.com>
Fri, 25 Jan 2008 22:15:38 +0000 (14:15 -0800)
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>
drivers/infiniband/hw/ipath/ipath_kernel.h
drivers/infiniband/hw/ipath/ipath_mad.c
drivers/infiniband/hw/ipath/ipath_registers.h
drivers/infiniband/hw/ipath/ipath_verbs.c
drivers/infiniband/hw/ipath/ipath_verbs.h

index 7bb0d08..a59c069 100644 (file)
@@ -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;
index 1978c34..d98d5f1 100644 (file)
@@ -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;
index d7181d4..156ef14 100644 (file)
@@ -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 */
index c4c9984..a2baa61 100644 (file)
@@ -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
index 6ccb54f..1c89850 100644 (file)
@@ -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)