From: Amir Vadai Date: Tue, 16 Feb 2010 15:36:00 +0000 (+0200) Subject: sdp: Fix bugs in huge paged HW's X-Git-Tag: v4.1.12-92~264^2~5^2~218 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=e35c32ade60e06e579b1e4de409e9ffa44480231;p=users%2Fjedix%2Flinux-maple.git sdp: Fix bugs in huge paged HW's * Protect some constants that are based on PAGE_SIZE: - FMR size - xmit_goal * renamed SDP_HEAD_SIZE => SDP_SKB_HEAD_SIZE * removed unneeded special IA64 code due to changes here Signed-off-by: Amir Vadai --- diff --git a/drivers/infiniband/ulp/sdp/sdp.h b/drivers/infiniband/ulp/sdp/sdp.h index dc5332c2d6a3d..893e33f974cba 100644 --- a/drivers/infiniband/ulp/sdp/sdp.h +++ b/drivers/infiniband/ulp/sdp/sdp.h @@ -30,7 +30,7 @@ #define SDP_TX_SIZE 0x40 #define SDP_RX_SIZE 0x40 -#define SDP_FMR_SIZE (PAGE_SIZE / sizeof(u64)) +#define SDP_FMR_SIZE (MIN(0x1000, PAGE_SIZE) / sizeof(u64)) #define SDP_FMR_POOL_SIZE 1024 #define SDP_FMR_DIRTY_SIZE ( SDP_FMR_POOL_SIZE / 4 ) @@ -39,10 +39,15 @@ #define SDP_MAX_RECV_SKB_FRAGS (PAGE_SIZE > 0x8000 ? 1 : 0x8000 / PAGE_SIZE) #define SDP_MAX_SEND_SKB_FRAGS (SDP_MAX_RECV_SKB_FRAGS + 1) -/* payload len - rest will be rx'ed into frags */ -#define SDP_HEAD_SIZE (PAGE_SIZE / 2 + sizeof(struct sdp_bsdh)) +/* skb inlined data len - rest will be rx'ed into frags */ +#define SDP_SKB_HEAD_SIZE (0x500 + sizeof(struct sdp_bsdh)) + +/* limit tx payload len, if the sink supports bigger buffers than the source + * can handle. + * or rx fragment size (limited by sge->length size) */ +#define SDP_MAX_PAYLOAD ((1 << 16) - SDP_SKB_HEAD_SIZE) + #define SDP_NUM_WC 4 -#define SDP_MAX_PAYLOAD ((1 << 16) - SDP_HEAD_SIZE) #define SDP_DEF_ZCOPY_THRESH 64*1024 #define SDP_MIN_ZCOPY_THRESH PAGE_SIZE diff --git a/drivers/infiniband/ulp/sdp/sdp_main.c b/drivers/infiniband/ulp/sdp/sdp_main.c index be77cdf94aa06..a7e050c07ce9c 100644 --- a/drivers/infiniband/ulp/sdp/sdp_main.c +++ b/drivers/infiniband/ulp/sdp/sdp_main.c @@ -1914,6 +1914,13 @@ new_segment: skb_entail(sk, ssk, skb); copy = size_goal; + + sdp_dbg_data(sk, "created new skb: %p" + " len = %d, sk_send_head: %p " + "copy: %d size_goal: %d\n", + skb, skb->len, sk->sk_send_head, copy, size_goal); + + } else { sdp_dbg_data(sk, "adding to existing skb: %p" " len = %d, sk_send_head: %p " diff --git a/drivers/infiniband/ulp/sdp/sdp_rx.c b/drivers/infiniband/ulp/sdp/sdp_rx.c index f869f96b4b7f2..44d9f1a2e5a84 100644 --- a/drivers/infiniband/ulp/sdp/sdp_rx.c +++ b/drivers/infiniband/ulp/sdp/sdp_rx.c @@ -164,11 +164,11 @@ static int sdp_post_recv(struct sdp_sock *ssk) /* TODO: allocate from cache */ if (unlikely(ssk->isk.sk.sk_allocation)) { - skb = sdp_stream_alloc_skb(&ssk->isk.sk, SDP_HEAD_SIZE, + skb = sdp_stream_alloc_skb(&ssk->isk.sk, SDP_SKB_HEAD_SIZE, ssk->isk.sk.sk_allocation); gfp_page = ssk->isk.sk.sk_allocation | __GFP_HIGHMEM; } else { - skb = sdp_stream_alloc_skb(&ssk->isk.sk, SDP_HEAD_SIZE, + skb = sdp_stream_alloc_skb(&ssk->isk.sk, SDP_SKB_HEAD_SIZE, GFP_KERNEL); gfp_page = GFP_HIGHUSER; } @@ -193,14 +193,14 @@ static int sdp_post_recv(struct sdp_sock *ssk) rx_req = ssk->rx_ring.buffer + (id & (SDP_RX_SIZE - 1)); rx_req->skb = skb; dev = ssk->ib_device; - addr = ib_dma_map_single(dev, h, SDP_HEAD_SIZE, DMA_FROM_DEVICE); + addr = ib_dma_map_single(dev, h, SDP_SKB_HEAD_SIZE, DMA_FROM_DEVICE); BUG_ON(ib_dma_mapping_error(dev, addr)); rx_req->mapping[0] = addr; /* TODO: proper error handling */ sge->addr = (u64)addr; - sge->length = SDP_HEAD_SIZE; + sge->length = SDP_SKB_HEAD_SIZE; sge->lkey = ssk->sdp_dev->mr->lkey; frags = skb_shinfo(skb)->nr_frags; for (i = 0; i < frags; ++i) { @@ -242,7 +242,7 @@ static inline int sdp_post_recvs_needed(struct sdp_sock *ssk) { struct sock *sk = &ssk->isk.sk; int scale = ssk->rcvbuf_scale; - int buffer_size = SDP_HEAD_SIZE + ssk->recv_frags * PAGE_SIZE; + int buffer_size = SDP_SKB_HEAD_SIZE + ssk->recv_frags * PAGE_SIZE; unsigned long max_bytes; if (!ssk->qp_active) @@ -344,7 +344,7 @@ static inline struct sk_buff *sdp_sock_queue_rcv_skb(struct sock *sk, int sdp_init_buffers(struct sdp_sock *ssk, u32 new_size) { - ssk->recv_frags = PAGE_ALIGN(new_size - SDP_HEAD_SIZE) / PAGE_SIZE; + ssk->recv_frags = PAGE_ALIGN(new_size - SDP_SKB_HEAD_SIZE) / PAGE_SIZE; if (ssk->recv_frags > SDP_MAX_RECV_SKB_FRAGS) ssk->recv_frags = SDP_MAX_RECV_SKB_FRAGS; ssk->rcvbuf_scale = rcvbuf_scale; @@ -356,22 +356,13 @@ int sdp_init_buffers(struct sdp_sock *ssk, u32 new_size) int sdp_resize_buffers(struct sdp_sock *ssk, u32 new_size) { - u32 curr_size = SDP_HEAD_SIZE + ssk->recv_frags * PAGE_SIZE; -#if defined(__ia64__) - /* for huge PAGE_SIZE systems, aka IA64, limit buffers size - [re-]negotiation to a known+working size that will not - trigger a HW error/rc to be interpreted as a IB_WC_LOC_LEN_ERR */ - u32 max_size = (SDP_HEAD_SIZE + SDP_MAX_RECV_SKB_FRAGS * PAGE_SIZE) <= - 32784 ? - (SDP_HEAD_SIZE + SDP_MAX_RECV_SKB_FRAGS * PAGE_SIZE) : 32784; -#else - u32 max_size = SDP_HEAD_SIZE + SDP_MAX_RECV_SKB_FRAGS * PAGE_SIZE; -#endif + u32 curr_size = SDP_SKB_HEAD_SIZE + ssk->recv_frags * PAGE_SIZE; + u32 max_size = SDP_SKB_HEAD_SIZE + SDP_MAX_RECV_SKB_FRAGS * PAGE_SIZE; if (new_size > curr_size && new_size <= max_size && sdp_get_large_socket(ssk)) { ssk->rcvbuf_scale = rcvbuf_scale; - ssk->recv_frags = PAGE_ALIGN(new_size - SDP_HEAD_SIZE) / + ssk->recv_frags = PAGE_ALIGN(new_size - SDP_SKB_HEAD_SIZE) / PAGE_SIZE; if (ssk->recv_frags > SDP_MAX_RECV_SKB_FRAGS) ssk->recv_frags = SDP_MAX_RECV_SKB_FRAGS; @@ -434,7 +425,7 @@ static struct sk_buff *sdp_recv_completion(struct sdp_sock *ssk, int id) dev = ssk->ib_device; rx_req = &ssk->rx_ring.buffer[id & (SDP_RX_SIZE - 1)]; skb = rx_req->skb; - ib_dma_unmap_single(dev, rx_req->mapping[0], SDP_HEAD_SIZE, + ib_dma_unmap_single(dev, rx_req->mapping[0], SDP_SKB_HEAD_SIZE, DMA_FROM_DEVICE); frags = skb_shinfo(skb)->nr_frags; for (i = 0; i < frags; ++i) @@ -642,8 +633,8 @@ static struct sk_buff *sdp_process_rx_wc(struct sdp_sock *ssk, h = (struct sdp_bsdh *)skb->data; - if (likely(wc->byte_len > SDP_HEAD_SIZE)) - skb->data_len = wc->byte_len - SDP_HEAD_SIZE; + if (likely(wc->byte_len > SDP_SKB_HEAD_SIZE)) + skb->data_len = wc->byte_len - SDP_SKB_HEAD_SIZE; else skb->data_len = 0;