]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
sdp: added /proc/net/sdpstats + packets dump
authorAmir Vadai <amirv@mellanox.co.il>
Sun, 5 Apr 2009 15:22:45 +0000 (18:22 +0300)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 6 Oct 2015 12:04:26 +0000 (05:04 -0700)
Signed-off-by: Amir Vadai <amirv@mellanox.co.il>
drivers/infiniband/ulp/sdp/Makefile
drivers/infiniband/ulp/sdp/sdp.h
drivers/infiniband/ulp/sdp/sdp_bcopy.c
drivers/infiniband/ulp/sdp/sdp_cma.c
drivers/infiniband/ulp/sdp/sdp_main.c
drivers/infiniband/ulp/sdp/sdp_proc.c [new file with mode: 0644]

index c889cce2bb42e103ab196981c04ecb4e3bb20829..5da4b7bbcd4b0d6ffdef8f86a95b276decfe7000 100644 (file)
@@ -3,4 +3,4 @@ EXTRA_CFLAGS += -ggdb
 
 obj-$(CONFIG_INFINIBAND_SDP) += ib_sdp.o
 
-ib_sdp-objs := sdp_main.o sdp_cma.o sdp_bcopy.o
+ib_sdp-objs := sdp_main.o sdp_cma.o sdp_bcopy.o sdp_proc.o
index f9c2421c1838c5a3dea3f9b3b72293bd3876bf81..e36f786d4072c9b43a4570c8d2fe5dc28434ae60 100644 (file)
@@ -7,9 +7,12 @@
 #include <net/tcp.h> /* For urgent data flags */
 #include <rdma/ib_verbs.h>
 
+#define SDPSTATS_ON
+
 #define sdp_printk(level, sk, format, arg...)                \
-       printk(level "%s:%d sdp_sock(%d:%d): " format,             \
+       printk(level "%s:%d sdp_sock(%d %d:%d): " format,             \
               __func__, __LINE__, \
+              current->pid, \
               (sk) ? inet_sk(sk)->num : -1,                 \
               (sk) ? ntohs(inet_sk(sk)->dport) : -1, ## arg)
 #define sdp_warn(sk, format, arg...)                         \
@@ -50,15 +53,72 @@ extern int sdp_debug_level;
 #endif /* CONFIG_INFINIBAND_SDP_DEBUG */
 
 #ifdef CONFIG_INFINIBAND_SDP_DEBUG_DATA
+
 extern int sdp_data_debug_level;
 #define sdp_dbg_data(sk, format, arg...)                     \
        do {                                                 \
-               if (sdp_data_debug_level > 0)                \
+               if (sdp_data_debug_level & 0x2)                \
                sdp_printk(KERN_DEBUG, sk, format , ## arg); \
        } while (0)
+#define SDP_DUMP_PACKET(sk, str, skb, h)                     \
+       do {                                                 \
+               if (sdp_data_debug_level & 0x1)                \
+                       dump_packet(sk, str, skb, h); \
+       } while (0)
 #else
-#define sdp_dbg_data(priv, format, arg...)                   \
-       do { (void) (priv); } while (0)
+#define sdp_dbg_data(priv, format, arg...)
+//     do { (void) (priv); } while (0)
+#define SDP_DUMP_PACKET(sk, str, skb, h)
+#endif
+
+#ifdef SDPSTATS_ON
+
+struct sdpstats {
+       u32 post_send[256];
+       u32 sendmsg_bcopy_segment;
+       u32 sendmsg_bzcopy_segment;
+       u32 sendmsg;
+       u32 post_send_credits;
+       u32 sendmsg_nagle_skip;
+       u32 sendmsg_seglen[25];
+       u32 send_size[25];
+       u32 post_recv;
+       u32 rx_int_count;
+       u32 tx_int_count;
+       u32 bzcopy_poll_miss;
+       u32 send_wait_for_mem;
+       u32 send_miss_no_credits;
+       u32 rx_poll_miss;
+       u32 tx_poll_miss;
+       u32 memcpy_count;
+       u32 credits_before_update[64];
+       u32 send_interval[25];
+};
+extern struct sdpstats sdpstats;
+
+static inline void sdpstats_hist(u32 *h, u32 val, u32 maxidx, int is_log)
+{
+       int idx = is_log ? ilog2(val) : val;
+       if (idx > maxidx)
+               idx = maxidx;
+
+       h[idx]++;
+}
+
+#define SDPSTATS_COUNTER_INC(stat) do {sdpstats.stat++;} while (0)
+#define SDPSTATS_COUNTER_ADD(stat, val) do {sdpstats.stat+=val;} while (0)
+#define SDPSTATS_COUNTER_MID_INC(stat, mid) do {sdpstats.stat[mid]++;} while (0)
+#define SDPSTATS_HIST(stat, size) \
+       sdpstats_hist(sdpstats.stat, size, ARRAY_SIZE(sdpstats.stat) - 1, 1)
+
+#define SDPSTATS_HIST_LINEAR(stat, size) \
+       sdpstats_hist(sdpstats.stat, size, ARRAY_SIZE(sdpstats.stat) - 1, 0)
+
+#else
+#define SDPSTATS_COUNTER_INC(stat)
+#define SDPSTATS_COUNTER_ADD(stat, val)
+#define SDPSTATS_COUNTER_MID_INC(stat, mid)
+#define SDPSTATS_HIST(stat, size)
 #endif
 
 #define SOCK_REF_RESET "RESET"
@@ -92,6 +152,9 @@ extern int sdp_data_debug_level;
 #define SDP_OP_RECV 0x800000000LL
 #define SDP_OP_SEND 0x400000000LL
 
+extern struct list_head sock_list;
+extern spinlock_t sock_list_lock;
+
 enum sdp_mid {
        SDP_MID_HELLO = 0x0,
        SDP_MID_HELLO_ACK = 0x1,
@@ -129,6 +192,38 @@ struct sdp_bsdh {
        __u32 mseq_ack;
 };
 
+union cma_ip_addr {
+        struct in6_addr ip6;
+        struct {
+                __u32 pad[3];
+                __u32 addr;
+        } ip4;
+};
+
+/* TODO: too much? Can I avoid having the src/dst and port here? */
+struct sdp_hh {
+       struct sdp_bsdh bsdh;
+       u8 majv_minv;
+       u8 ipv_cap;
+       u8 rsvd1;
+       u8 max_adverts;
+       __u32 desremrcvsz;
+       __u32 localrcvsz;
+       __u16 port;
+       __u16 rsvd2;
+       union cma_ip_addr src_addr;
+       union cma_ip_addr dst_addr;
+};
+
+struct sdp_hah {
+       struct sdp_bsdh bsdh;
+       u8 majv_minv;
+       u8 ipv_cap;
+       u8 rsvd1;
+       u8 ext_max_adverts;
+       __u32 actrcvsz;
+};
+
 struct sdp_buf {
         struct sk_buff *skb;
         u64             mapping[SDP_MAX_SEND_SKB_FRAGS + 1];
@@ -329,6 +424,9 @@ static inline void sdp_set_error(struct sock *sk, int err)
 
 extern struct workqueue_struct *sdp_workqueue;
 
+#ifdef CONFIG_INFINIBAND_SDP_DEBUG_DATA
+void dump_packet(struct sock *sk, char *str, struct sk_buff *skb, const struct sdp_bsdh *h);
+#endif
 int sdp_cma_handler(struct rdma_cm_id *, struct rdma_cm_event *);
 void sdp_reset(struct sock *sk);
 void sdp_reset_sk(struct sock *sk, int rc);
@@ -354,6 +452,8 @@ void sdp_post_keepalive(struct sdp_sock *ssk);
 void sdp_start_keepalive_timer(struct sock *sk);
 void sdp_bzcopy_write_space(struct sdp_sock *ssk);
 int sdp_init_sock(struct sock *sk);
+int __init sdp_proc_init(void);
+void sdp_proc_unregister(void);
 
 static inline struct sk_buff *sdp_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp)
 {
index 475d7c362991552076e82922f60695d68dc144f2..7c7271c861747d7ad72505d7dcaf236c9306a587 100644 (file)
@@ -186,6 +186,64 @@ void sdp_post_keepalive(struct sdp_sock *ssk)
        sdp_cnt(sdp_keepalive_probes_sent);
 }
 
+#ifdef CONFIG_INFINIBAND_SDP_DEBUG_DATA
+void dump_packet(struct sock *sk, char *str, struct sk_buff *skb, const struct sdp_bsdh *h)
+{
+       int len = 0;
+       char buf[256];
+#define ENUM2STR(e) [e] = #e
+       static char *mid2str[] = {
+               ENUM2STR(SDP_MID_HELLO),
+               ENUM2STR(SDP_MID_HELLO_ACK),
+               ENUM2STR(SDP_MID_DISCONN),
+               ENUM2STR(SDP_MID_CHRCVBUF),
+               ENUM2STR(SDP_MID_CHRCVBUF_ACK),
+               ENUM2STR(SDP_MID_DATA),
+       };
+       len += snprintf(buf, 255-len, "skb: %p mid: %2x:%-20s flags: 0x%x bufs: %d "
+               "len: %d mseq: %d mseq_ack: %d",
+               skb, h->mid, mid2str[h->mid], h->flags,
+               ntohs(h->bufs), ntohl(h->len),ntohl(h->mseq),
+               ntohl(h->mseq_ack));
+
+       switch (h->mid) {
+               case SDP_MID_HELLO:
+                       {
+                               const struct sdp_hh *hh = (struct sdp_hh *)h;
+                               len += snprintf(buf + len, 255-len,
+                                       " | max_adverts: %d  majv_minv: %d localrcvsz: %d "
+                                       "desremrcvsz: %d |",
+                                       hh->max_adverts,
+                                       hh->majv_minv,
+                                       ntohl(hh->localrcvsz),
+                                       ntohl(hh->desremrcvsz));
+                       }
+                       break;
+               case SDP_MID_HELLO_ACK:
+                       {
+                               const struct sdp_hah *hah = (struct sdp_hah *)h;
+                               len += snprintf(buf + len, 255-len, " | actrcvz: %d |",
+                                               ntohl(hah->actrcvsz));
+                       }
+                       break;
+               case SDP_MID_CHRCVBUF:
+               case SDP_MID_CHRCVBUF_ACK:
+                       {
+                               struct sdp_chrecvbuf *req_size = (struct sdp_chrecvbuf *)(h+1);
+                               len += snprintf(buf + len, 255-len,
+                                       " | req_size: %d |", ntohl(req_size->size));
+                       }
+                       break;
+               case SDP_MID_DATA:
+                       len += snprintf(buf + len, 255-len, " | data_len: %ld |", ntohl(h->len) - sizeof(struct sdp_bsdh));
+               default:
+                       break;
+       }
+       buf[len] = 0;
+       sdp_warn(sk, "%s: %s\n", str, buf);
+}
+#endif
+
 void sdp_post_send(struct sdp_sock *ssk, struct sk_buff *skb, u8 mid)
 {
        struct sdp_buf *tx_req;
@@ -197,6 +255,9 @@ void sdp_post_send(struct sdp_sock *ssk, struct sk_buff *skb, u8 mid)
        struct ib_sge *sge;
        struct ib_send_wr *bad_wr;
 
+       SDPSTATS_COUNTER_MID_INC(post_send, mid);
+       SDPSTATS_HIST(send_size, skb->len);
+
        h->mid = mid;
        if (unlikely(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_URG))
                h->flags = SDP_OOB_PRES | SDP_OOB_PEND;
@@ -208,6 +269,7 @@ void sdp_post_send(struct sdp_sock *ssk, struct sk_buff *skb, u8 mid)
        h->mseq = htonl(mseq);
        h->mseq_ack = htonl(ssk->mseq_ack);
 
+       SDP_DUMP_PACKET(&ssk->isk.sk, "TX", skb, h);
        tx_req = &ssk->tx_ring[mseq & (SDP_TX_SIZE - 1)];
        tx_req->skb = skb;
        dev = ssk->ib_device;
@@ -244,6 +306,16 @@ void sdp_post_send(struct sdp_sock *ssk, struct sk_buff *skb, u8 mid)
        ssk->tx_wr.send_flags = IB_SEND_SIGNALED;
        if (unlikely(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_URG))
                ssk->tx_wr.send_flags |= IB_SEND_SOLICITED;
+       
+       {
+               static unsigned long last_send = 0;
+               int delta = jiffies - last_send;
+               
+               if (likely(last_send)) 
+                       SDPSTATS_HIST(send_interval, delta);
+
+               last_send = jiffies;
+       }
        rc = ib_post_send(ssk->qp, &ssk->tx_wr, &bad_wr);
        ++ssk->tx_head;
        --ssk->bufs;
@@ -292,7 +364,6 @@ struct sk_buff *sdp_send_completion(struct sdp_sock *ssk, int mseq)
        return skb;
 }
 
-
 static void sdp_post_recv(struct sdp_sock *ssk)
 {
        struct sdp_buf *rx_req;
@@ -375,6 +446,7 @@ static void sdp_post_recv(struct sdp_sock *ssk)
        ssk->rx_wr.sg_list = ssk->ibsge;
        ssk->rx_wr.num_sge = frags + 1;
        rc = ib_post_recv(ssk->qp, &ssk->rx_wr, &bad_wr);
+       SDPSTATS_COUNTER_INC(post_recv);
        ++ssk->rx_head;
        if (unlikely(rc)) {
                sdp_dbg(&ssk->isk.sk, "ib_post_recv failed with status %d\n", rc);
@@ -583,6 +655,7 @@ void sdp_post_sends(struct sdp_sock *ssk, int nonagle)
                                          GFP_KERNEL);
                /* FIXME */
                BUG_ON(!skb);
+               SDPSTATS_COUNTER_INC(post_send_credits);
                sdp_post_send(ssk, skb, SDP_MID_DATA);
        }
 
@@ -701,11 +774,14 @@ static int sdp_handle_recv_comp(struct sdp_sock *ssk, struct ib_wc *wc)
        skb->tail = skb->head + skb_headlen(skb);
 #endif
        h = (struct sdp_bsdh *)skb->data;
+       SDP_DUMP_PACKET(&ssk->isk.sk, "RX", skb, h);
        skb_reset_transport_header(skb);
        ssk->mseq_ack = ntohl(h->mseq);
        if (ssk->mseq_ack != (int)wc->wr_id)
                printk(KERN_WARNING "SDP BUG! mseq %d != wrid %d\n",
                                ssk->mseq_ack, (int)wc->wr_id);
+
+       SDPSTATS_HIST_LINEAR(credits_before_update, ssk->bufs);
        ssk->bufs = ntohl(h->mseq_ack) - ssk->tx_head + 1 +
                ntohs(h->bufs);
 
@@ -782,7 +858,7 @@ static int sdp_handle_send_comp(struct sdp_sock *ssk, struct ib_wc *wc)
        if (unlikely(wc->status)) {
                if (wc->status != IB_WC_WR_FLUSH_ERR) {
                        struct sock *sk = &ssk->isk.sk;
-                       sdp_dbg(sk, "Send completion with error. "
+                       sdp_warn(sk, "Send completion with error. "
                                "Status %d\n", wc->status);
                        sdp_set_error(sk, -ECONNRESET);
                        wake_up(&ssk->wq);
index 96d65bdfb90722b184eb3be04fd36778e142681c..b6bc4e5f35c6b8128c91cd2dc2e4f8ae06fe9542 100644 (file)
 #include "sdp_socket.h"
 #include "sdp.h"
 
-union cma_ip_addr {
-        struct in6_addr ip6;
-        struct {
-                __u32 pad[3];
-                __u32 addr;
-        } ip4;
-};
-
 #define SDP_MAJV_MINV 0x22
 
-/* TODO: too much? Can I avoid having the src/dst and port here? */
-struct sdp_hh {
-       struct sdp_bsdh bsdh;
-       u8 majv_minv;
-       u8 ipv_cap;
-       u8 rsvd1;
-       u8 max_adverts;
-       __u32 desremrcvsz;
-       __u32 localrcvsz;
-       __u16 port;
-       __u16 rsvd2;
-       union cma_ip_addr src_addr;
-       union cma_ip_addr dst_addr;
-};
-
-struct sdp_hah {
-       struct sdp_bsdh bsdh;
-       u8 majv_minv;
-       u8 ipv_cap;
-       u8 rsvd1;
-       u8 ext_max_adverts;
-       __u32 actrcvsz;
-};
-
 enum {
        SDP_HH_SIZE = 76,
        SDP_HAH_SIZE = 180,
@@ -206,6 +174,7 @@ static int sdp_connect_handler(struct sock *sk, struct rdma_cm_id *id,
        sdp_dbg(sk, "%s %p -> %p\n", __func__, sdp_sk(sk)->id, id);
 
        h = event->param.conn.private_data;
+       SDP_DUMP_PACKET(sk, "RX", NULL, &h->bsdh);
 
        if (!h->max_adverts)
                return -EINVAL;
@@ -277,6 +246,7 @@ static int sdp_response_handler(struct sock *sk, struct rdma_cm_id *id,
                return 0;
 
        h = event->param.conn.private_data;
+       SDP_DUMP_PACKET(sk, "RX", NULL, &h->bsdh);
        sdp_sk(sk)->max_bufs = sdp_sk(sk)->bufs = ntohs(h->bsdh.bufs);
        sdp_sk(sk)->min_bufs = sdp_sk(sk)->bufs / 4;
        sdp_sk(sk)->xmit_size_goal = ntohl(h->actrcvsz) -
@@ -428,6 +398,7 @@ int sdp_cma_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
                conn_param.responder_resources = 4 /* TODO */;
                conn_param.initiator_depth = 4 /* TODO */;
                conn_param.retry_count = SDP_RETRY_COUNT;
+               SDP_DUMP_PACKET(NULL, "TX", NULL, &hh.bsdh);
                rc = rdma_connect(id, &conn_param);
                break;
        case RDMA_CM_EVENT_ROUTE_ERROR:
@@ -458,6 +429,7 @@ int sdp_cma_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
                conn_param.responder_resources = 4 /* TODO */;
                conn_param.initiator_depth = 4 /* TODO */;
                conn_param.retry_count = SDP_RETRY_COUNT;
+               SDP_DUMP_PACKET(sk, "TX", NULL, &hah.bsdh);
                rc = rdma_accept(id, &conn_param);
                if (rc) {
                        sdp_sk(child)->id = NULL;
index 7a38c47f0fa011cd4e4542368d7a334bbd49fd7b..c9b5ba2b6907061fe0941e5b083517cac16f893d 100644 (file)
@@ -67,7 +67,6 @@ unsigned int csum_partial_copy_from_user_new (const char *src, char *dst,
 #include <linux/socket.h>
 #include <net/protocol.h>
 #include <net/inet_common.h>
-#include <linux/proc_fs.h>
 #include <rdma/rdma_cm.h>
 #include <rdma/ib_verbs.h>
 /* TODO: remove when sdp_socket.h becomes part of include/linux/socket.h */
@@ -138,8 +137,8 @@ MODULE_PARM_DESC(sdp_zcopy_thresh, "Zero copy send threshold; 0=0ff.");
 
 struct workqueue_struct *sdp_workqueue;
 
-static struct list_head sock_list;
-static spinlock_t sock_list_lock;
+struct list_head sock_list;
+spinlock_t sock_list_lock;
 
 static DEFINE_RWLOCK(device_removal_lock);
 
@@ -1288,6 +1287,8 @@ static inline struct bzcopy_state *sdp_bz_cleanup(struct bzcopy_state *bz)
 
                        if (!bz->busy)
                                break;
+
+                       SDPSTATS_COUNTER_INC(bzcopy_poll_miss);
                }
 
                if (bz->busy)
@@ -1319,11 +1320,14 @@ static struct bzcopy_state *sdp_bz_setup(struct sdp_sock *ssk,
        int thresh;
        mm_segment_t cur_fs;
 
-       cur_fs = get_fs();
-
        thresh = ssk->zcopy_thresh ? : sdp_zcopy_thresh;
-       if (thresh == 0 || len < thresh || !capable(CAP_IPC_LOCK))
+       if (thresh == 0 || len < thresh || !capable(CAP_IPC_LOCK)) {
+               SDPSTATS_COUNTER_INC(sendmsg_bcopy_segment);
                return NULL;
+       }
+       SDPSTATS_COUNTER_INC(sendmsg_bzcopy_segment);
+
+       cur_fs = get_fs();
 
        /*
         *   Since we use the TCP segmentation fields of the skb to map user
@@ -1445,6 +1449,8 @@ static inline int sdp_bcopy_get(struct sock *sk, struct sk_buff *skb,
 
                /* Time to copy data. We are close to
                 * the end! */
+               SDPSTATS_COUNTER_ADD(memcpy_count, copy);
+               sdp_dbg_data(sk, "Copying from: %p offset: %d size: %d\n", from, off, copy);
                err = skb_copy_to_page(sk, from, skb, page,
                                       off, copy);
                if (err) {
@@ -1463,6 +1469,8 @@ static inline int sdp_bcopy_get(struct sock *sk, struct sk_buff *skb,
                        skb_shinfo(skb)->frags[i - 1].size +=
                                                        copy;
                } else {
+                       sdp_dbg_data(sk, "Adding to frage %d: page: %p off: %d size: %d\n",
+                               i, page, off, copy);
                        skb_fill_page_desc(skb, i, page, off, copy);
                        if (TCP_PAGE(sk)) {
                                get_page(page);
@@ -1651,7 +1659,7 @@ static int sdp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        int err, copied;
        long timeo;
        struct bzcopy_state *bz = NULL;
-
+       SDPSTATS_COUNTER_INC(sendmsg);
        lock_sock(sk);
        sdp_dbg_data(sk, "%s\n", __func__);
 
@@ -1688,6 +1696,8 @@ static int sdp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                if (size_goal > SDP_MAX_PAYLOAD)
                        size_goal = SDP_MAX_PAYLOAD;
 
+               SDPSTATS_HIST(sendmsg_seglen, seglen);
+
                if (bz)
                        sdp_bz_cleanup(bz);
                bz = sdp_bz_setup(ssk, from, seglen, size_goal);
@@ -1737,8 +1747,14 @@ new_segment:
                                     NETIF_F_HW_CSUM))
                                        skb->ip_summed = CHECKSUM_PARTIAL;
 
+                               sdp_dbg_data(sk, "entail new skb: %p len = %d\n", skb, skb->len);
                                skb_entail(sk, ssk, skb);
                                copy = size_goal;
+                       } else {
+                               sdp_dbg_data(sk, "adding to existing skb: %p"
+                                       " len = %d, sk_send_head: %p copy: %d\n",
+                                       skb, skb->len, sk->sk_send_head, copy);
+                       
                        }
 
                        /* Try to append data to the end of skb. */
@@ -1791,6 +1807,7 @@ new_segment:
 wait_for_sndbuf:
                        set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
 wait_for_memory:
+                       SDPSTATS_COUNTER_INC(send_wait_for_mem);
                        if (copied)
                                sdp_push(sk, ssk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
 
@@ -2266,192 +2283,6 @@ static int sdp_create_socket(struct net *net, struct socket *sock, int protocol)
        return 0;
 }
 
-#ifdef CONFIG_PROC_FS
-
-static void *sdp_get_idx(struct seq_file *seq, loff_t pos)
-{
-       int i = 0;
-       struct sdp_sock *ssk;
-
-       if (!list_empty(&sock_list))
-               list_for_each_entry(ssk, &sock_list, sock_list) {
-                       if (i == pos)
-                               return ssk;
-                       i++;
-               }
-
-       return NULL;
-}
-
-static void *sdp_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       void *start = NULL;
-       struct sdp_iter_state* st = seq->private;
-
-       st->num = 0;
-
-       if (!*pos)
-               return SEQ_START_TOKEN;
-
-       spin_lock_irq(&sock_list_lock);
-       start = sdp_get_idx(seq, *pos - 1);
-       if (start)
-               sock_hold((struct sock *)start, SOCK_REF_SEQ);
-       spin_unlock_irq(&sock_list_lock);
-
-       return start;
-}
-
-static void *sdp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-       struct sdp_iter_state* st = seq->private;
-       void *next = NULL;
-
-       spin_lock_irq(&sock_list_lock);
-       if (v == SEQ_START_TOKEN)
-               next = sdp_get_idx(seq, 0);
-       else
-               next = sdp_get_idx(seq, *pos);
-       if (next)
-               sock_hold((struct sock *)next, SOCK_REF_SEQ);
-       spin_unlock_irq(&sock_list_lock);
-
-       *pos += 1;
-       st->num++;
-
-       return next;
-}
-
-static void sdp_seq_stop(struct seq_file *seq, void *v)
-{
-}
-
-#define TMPSZ 150
-
-static int sdp_seq_show(struct seq_file *seq, void *v)
-{
-       struct sdp_iter_state* st;
-       struct sock *sk = v;
-       char tmpbuf[TMPSZ + 1];
-       unsigned int dest;
-       unsigned int src;
-       int uid;
-       unsigned long inode;
-       __u16 destp;
-       __u16 srcp;
-       __u32 rx_queue, tx_queue;
-
-       if (v == SEQ_START_TOKEN) {
-               seq_printf(seq, "%-*s\n", TMPSZ - 1,
-                               "  sl  local_address rem_address        uid inode"
-                               "   rx_queue tx_queue state");
-               goto out;
-       }
-
-       st = seq->private;
-
-       dest = inet_sk(sk)->daddr;
-       src = inet_sk(sk)->rcv_saddr;
-       destp = ntohs(inet_sk(sk)->dport);
-       srcp = ntohs(inet_sk(sk)->sport);
-       uid = sock_i_uid(sk);
-       inode = sock_i_ino(sk);
-       rx_queue = sdp_sk(sk)->rcv_nxt - sdp_sk(sk)->copied_seq;
-       tx_queue = sdp_sk(sk)->write_seq - sdp_sk(sk)->snd_una;
-
-       sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %5d %lu       %08X:%08X %X",
-               st->num, src, srcp, dest, destp, uid, inode,
-               rx_queue, tx_queue, sk->sk_state);
-
-       seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf);
-
-       sock_put(sk, SOCK_REF_SEQ);
-out:
-       return 0;
-}
-
-static int sdp_seq_open(struct inode *inode, struct file *file)
-{
-       struct sdp_seq_afinfo *afinfo = PDE(inode)->data;
-       struct seq_file *seq;
-       struct sdp_iter_state *s;
-       int rc;
-
-       if (unlikely(afinfo == NULL))
-               return -EINVAL;
-
-       s = kzalloc(sizeof(*s), GFP_KERNEL);
-       if (!s)
-               return -ENOMEM;
-       s->family               = afinfo->family;
-       s->seq_ops.start        = sdp_seq_start;
-       s->seq_ops.next         = sdp_seq_next;
-       s->seq_ops.show         = afinfo->seq_show;
-       s->seq_ops.stop         = sdp_seq_stop;
-
-       rc = seq_open(file, &s->seq_ops);
-       if (rc)
-               goto out_kfree;
-       seq          = file->private_data;
-       seq->private = s;
-out:
-       return rc;
-out_kfree:
-       kfree(s);
-       goto out;
-}
-
-
-static struct file_operations sdp_seq_fops;
-static struct sdp_seq_afinfo sdp_seq_afinfo = {
-       .owner          = THIS_MODULE,
-       .name           = "sdp",
-       .family         = AF_INET_SDP,
-       .seq_show       = sdp_seq_show,
-       .seq_fops       = &sdp_seq_fops,
-};
-
-
-static int __init sdp_proc_init(void)
-{
-       int rc = 0;
-       struct proc_dir_entry *p;
-
-       sdp_seq_afinfo.seq_fops->owner         = sdp_seq_afinfo.owner;
-       sdp_seq_afinfo.seq_fops->open          = sdp_seq_open;
-       sdp_seq_afinfo.seq_fops->read          = seq_read;
-       sdp_seq_afinfo.seq_fops->llseek        = seq_lseek;
-       sdp_seq_afinfo.seq_fops->release       = seq_release_private;
-
-       p = proc_net_fops_create(&init_net, sdp_seq_afinfo.name, S_IRUGO,
-                                sdp_seq_afinfo.seq_fops);
-       if (p)
-               p->data = &sdp_seq_afinfo;
-       else
-               rc = -ENOMEM;
-
-       return rc;
-}
-
-static void sdp_proc_unregister(void)
-{
-       proc_net_remove(&init_net, sdp_seq_afinfo.name);
-       memset(sdp_seq_afinfo.seq_fops, 0, sizeof(*sdp_seq_afinfo.seq_fops));
-}
-
-#else /* CONFIG_PROC_FS */
-
-static int __init sdp_proc_init(void)
-{
-       return 0;
-}
-
-static void sdp_proc_unregister(void)
-{
-
-}
-#endif /* CONFIG_PROC_FS */
-
 static void sdp_add_device(struct ib_device *device)
 {
 }
diff --git a/drivers/infiniband/ulp/sdp/sdp_proc.c b/drivers/infiniband/ulp/sdp/sdp_proc.c
new file mode 100644 (file)
index 0000000..8971517
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2008 Mellanox Technologies Ltd.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/proc_fs.h>
+#include "sdp_socket.h"
+#include "sdp.h"
+
+#ifdef CONFIG_PROC_FS
+
+#define PROC_SDP_STATS "sdpstats"
+
+static void *sdp_get_idx(struct seq_file *seq, loff_t pos)
+{
+       int i = 0;
+       struct sdp_sock *ssk;
+
+       if (!list_empty(&sock_list))
+               list_for_each_entry(ssk, &sock_list, sock_list) {
+                       if (i == pos)
+                               return ssk;
+                       i++;
+               }
+
+       return NULL;
+}
+
+static void *sdp_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       void *start = NULL;
+       struct sdp_iter_state* st = seq->private;
+
+       st->num = 0;
+
+       if (!*pos)
+               return SEQ_START_TOKEN;
+
+       spin_lock_irq(&sock_list_lock);
+       start = sdp_get_idx(seq, *pos - 1);
+       if (start)
+               sock_hold((struct sock *)start, SOCK_REF_SEQ);
+       spin_unlock_irq(&sock_list_lock);
+
+       return start;
+}
+
+static void *sdp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       struct sdp_iter_state* st = seq->private;
+       void *next = NULL;
+
+       spin_lock_irq(&sock_list_lock);
+       if (v == SEQ_START_TOKEN)
+               next = sdp_get_idx(seq, 0);
+       else
+               next = sdp_get_idx(seq, *pos);
+       if (next)
+               sock_hold((struct sock *)next, SOCK_REF_SEQ);
+       spin_unlock_irq(&sock_list_lock);
+
+       *pos += 1;
+       st->num++;
+
+       return next;
+}
+
+static void sdp_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+#define TMPSZ 150
+
+static int sdp_seq_show(struct seq_file *seq, void *v)
+{
+       struct sdp_iter_state* st;
+       struct sock *sk = v;
+       char tmpbuf[TMPSZ + 1];
+       unsigned int dest;
+       unsigned int src;
+       int uid;
+       unsigned long inode;
+       __u16 destp;
+       __u16 srcp;
+       __u32 rx_queue, tx_queue;
+
+       if (v == SEQ_START_TOKEN) {
+               seq_printf(seq, "%-*s\n", TMPSZ - 1,
+                               "  sl  local_address rem_address        uid inode"
+                               "   rx_queue tx_queue state");
+               goto out;
+       }
+
+       st = seq->private;
+
+       dest = inet_sk(sk)->daddr;
+       src = inet_sk(sk)->rcv_saddr;
+       destp = ntohs(inet_sk(sk)->dport);
+       srcp = ntohs(inet_sk(sk)->sport);
+       uid = sock_i_uid(sk);
+       inode = sock_i_ino(sk);
+       rx_queue = sdp_sk(sk)->rcv_nxt - sdp_sk(sk)->copied_seq;
+       tx_queue = sdp_sk(sk)->write_seq - sdp_sk(sk)->snd_una;
+
+       sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %5d %lu       %08X:%08X %X",
+               st->num, src, srcp, dest, destp, uid, inode,
+               rx_queue, tx_queue, sk->sk_state);
+
+       seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf);
+
+       sock_put(sk, SOCK_REF_SEQ);
+out:
+       return 0;
+}
+
+static int sdp_seq_open(struct inode *inode, struct file *file)
+{
+       struct sdp_seq_afinfo *afinfo = PDE(inode)->data;
+       struct seq_file *seq;
+       struct sdp_iter_state *s;
+       int rc;
+
+       if (unlikely(afinfo == NULL))
+               return -EINVAL;
+
+       s = kzalloc(sizeof(*s), GFP_KERNEL);
+       if (!s)
+               return -ENOMEM;
+       s->family               = afinfo->family;
+       s->seq_ops.start        = sdp_seq_start;
+       s->seq_ops.next         = sdp_seq_next;
+       s->seq_ops.show         = afinfo->seq_show;
+       s->seq_ops.stop         = sdp_seq_stop;
+
+       rc = seq_open(file, &s->seq_ops);
+       if (rc)
+               goto out_kfree;
+       seq          = file->private_data;
+       seq->private = s;
+out:
+       return rc;
+out_kfree:
+       kfree(s);
+       goto out;
+}
+
+
+static struct file_operations sdp_seq_fops;
+static struct sdp_seq_afinfo sdp_seq_afinfo = {
+       .owner          = THIS_MODULE,
+       .name           = "sdp",
+       .family         = AF_INET_SDP,
+       .seq_show       = sdp_seq_show,
+       .seq_fops       = &sdp_seq_fops,
+};
+
+#ifdef SDPSTATS_ON
+struct sdpstats sdpstats = { { 0 } };
+
+static void sdpstats_seq_hist(struct seq_file *seq, char *str, u32 *h, int n, int is_log)
+{
+       int i;
+       u32 max = 0;
+
+       seq_printf(seq, "%s:\n", str);
+
+       for (i = 0; i < n; i++) {
+               if (h[i] > max)
+                       max = h[i];
+       }
+
+       if (max == 0) {
+               seq_printf(seq, " - all values are 0\n");
+               return;
+       }
+
+       for (i = 0; i < n; i++) {
+               char s[51];
+               int j = 50 * h[i] / max;
+               int val = is_log ? (i == n-1 ? 0 : 1<<i) : i;
+               memset(s, '*', j);
+               s[j] = '\0';
+
+               seq_printf(seq, "%10d | %-50s - %d\n", val, s, h[i]);
+       }
+}
+
+static int sdpstats_seq_show(struct seq_file *seq, void *v)
+{
+#define ENUM2STR(e) [e] = #e
+       static char *mid2str[] = {
+               ENUM2STR(SDP_MID_HELLO),
+               ENUM2STR(SDP_MID_HELLO_ACK),
+               ENUM2STR(SDP_MID_DISCONN),
+               ENUM2STR(SDP_MID_CHRCVBUF),
+               ENUM2STR(SDP_MID_CHRCVBUF_ACK),
+               ENUM2STR(SDP_MID_DATA),
+       };
+       int i;
+
+       seq_printf(seq, "SDP statistics:\n");
+
+       sdpstats_seq_hist(seq, "sendmsg_seglen", sdpstats.sendmsg_seglen,
+               ARRAY_SIZE(sdpstats.sendmsg_seglen), 1);
+
+       sdpstats_seq_hist(seq, "send_size", sdpstats.send_size,
+               ARRAY_SIZE(sdpstats.send_size), 1);
+
+       sdpstats_seq_hist(seq, "credits_before_update", sdpstats.credits_before_update,
+               ARRAY_SIZE(sdpstats.credits_before_update), 0);
+
+//     sdpstats_seq_hist(seq, "send_interval", sdpstats.send_interval,
+//             ARRAY_SIZE(sdpstats.send_interval));
+
+       seq_printf(seq, "sdp_sendmsg() calls\t\t: %d\n", sdpstats.sendmsg);
+       seq_printf(seq, "bcopy segments     \t\t: %d\n", sdpstats.sendmsg_bcopy_segment);
+       seq_printf(seq, "bzcopy segments    \t\t: %d\n", sdpstats.sendmsg_bzcopy_segment);
+       seq_printf(seq, "post_send_credits  \t\t: %d\n", sdpstats.post_send_credits);
+       seq_printf(seq, "memcpy_count       \t\t: %u\n", sdpstats.memcpy_count);
+
+       for (i = 0; i < ARRAY_SIZE(sdpstats.post_send); i++) {
+               if (mid2str[i]) {
+                       seq_printf(seq, "post_send %-20s\t: %d\n",
+                                       mid2str[i], sdpstats.post_send[i]);
+               }
+       }
+
+       seq_printf(seq, "\n");
+       seq_printf(seq, "post_recv         \t\t: %d\n", sdpstats.post_recv);
+       seq_printf(seq, "BZCopy poll miss  \t\t: %d\n", sdpstats.bzcopy_poll_miss);
+       seq_printf(seq, "send_wait_for_mem \t\t: %d\n", sdpstats.send_wait_for_mem);
+       seq_printf(seq, "send_miss_no_credits\t\t: %d\n", sdpstats.send_miss_no_credits);
+
+       seq_printf(seq, "rx_poll_miss      \t\t: %d\n", sdpstats.rx_poll_miss);
+       seq_printf(seq, "tx_poll_miss      \t\t: %d\n", sdpstats.tx_poll_miss);
+
+       seq_printf(seq, "CQ stats:\n");
+       seq_printf(seq, "- RX interrupts\t\t: %d\n", sdpstats.rx_int_count);
+       seq_printf(seq, "- TX interrupts\t\t: %d\n", sdpstats.tx_int_count);
+       return 0;
+}
+
+static ssize_t sdpstats_write(struct file *file, const char __user *buf,
+                           size_t count, loff_t *offs)
+{
+       memset(&sdpstats, 0, sizeof(sdpstats));
+       printk("Cleared sdp statistics\n");
+
+       return count;
+}
+
+static const struct seq_operations sdpstats_seq_ops = {
+       .show   = sdpstats_seq_show,
+};
+
+static int sdpstats_seq_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, sdpstats_seq_show, NULL);
+}
+
+static struct file_operations sdpstats_fops = {
+       .owner          = THIS_MODULE,
+       .open           = sdpstats_seq_open,
+       .read           = seq_read,
+       .write          = sdpstats_write,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+#endif
+
+int __init sdp_proc_init(void)
+{
+       struct proc_dir_entry *p = NULL;
+       struct proc_dir_entry *sdpstats = NULL;
+
+       sdp_seq_afinfo.seq_fops->owner         = sdp_seq_afinfo.owner;
+       sdp_seq_afinfo.seq_fops->open          = sdp_seq_open;
+       sdp_seq_afinfo.seq_fops->read          = seq_read;
+       sdp_seq_afinfo.seq_fops->llseek        = seq_lseek;
+       sdp_seq_afinfo.seq_fops->release       = seq_release_private;
+
+       p = proc_net_fops_create(sdp_seq_afinfo.name, S_IRUGO,
+                                sdp_seq_afinfo.seq_fops);
+       if (p)
+               p->data = &sdp_seq_afinfo;
+       else
+               goto no_mem;;
+
+#ifdef SDPSTATS_ON
+
+       sdpstats = proc_net_fops_create(PROC_SDP_STATS,
+                       S_IRUGO | S_IWUGO, &sdpstats_fops); 
+       if (!sdpstats)
+               goto no_mem;;
+
+       return 0;
+#endif
+
+no_mem:
+       if (sdpstats)
+               proc_net_remove(PROC_SDP_STATS);
+
+       if (p)
+               proc_net_remove(sdp_seq_afinfo.name);
+
+       return -ENOMEM;
+}
+
+void sdp_proc_unregister(void)
+{
+       proc_net_remove(sdp_seq_afinfo.name);
+       memset(sdp_seq_afinfo.seq_fops, 0, sizeof(*sdp_seq_afinfo.seq_fops));
+
+#ifdef SDPSTATS_ON
+       proc_net_remove(PROC_SDP_STATS);
+#endif
+}
+
+#else /* CONFIG_PROC_FS */
+
+int __init sdp_proc_init(void)
+{
+       return 0;
+}
+
+void sdp_proc_unregister(void)
+{
+
+}
+#endif /* CONFIG_PROC_FS */