[SK_BUFF]: Introduce skb_reset_mac_header(skb)
[deliverable/linux.git] / drivers / infiniband / ulp / ipoib / ipoib_cm.c
index 4d59682f7d4a39084e61361925c6b7dc0041047c..c722e5c141b3be697e69557ed6e7047d8404c409 100644 (file)
@@ -65,14 +65,14 @@ struct ipoib_cm_id {
 static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
                               struct ib_cm_event *event);
 
-static void ipoib_cm_dma_unmap_rx(struct ipoib_dev_priv *priv,
+static void ipoib_cm_dma_unmap_rx(struct ipoib_dev_priv *priv, int frags,
                                  u64 mapping[IPOIB_CM_RX_SG])
 {
        int i;
 
        ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
 
-       for (i = 0; i < IPOIB_CM_RX_SG - 1; ++i)
+       for (i = 0; i < frags; ++i)
                ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
 }
 
@@ -90,7 +90,8 @@ static int ipoib_cm_post_receive(struct net_device *dev, int id)
        ret = ib_post_srq_recv(priv->cm.srq, &priv->cm.rx_wr, &bad_wr);
        if (unlikely(ret)) {
                ipoib_warn(priv, "post srq failed for buf %d (%d)\n", id, ret);
-               ipoib_cm_dma_unmap_rx(priv, priv->cm.srq_ring[id].mapping);
+               ipoib_cm_dma_unmap_rx(priv, IPOIB_CM_RX_SG - 1,
+                                     priv->cm.srq_ring[id].mapping);
                dev_kfree_skb_any(priv->cm.srq_ring[id].skb);
                priv->cm.srq_ring[id].skb = NULL;
        }
@@ -98,8 +99,8 @@ static int ipoib_cm_post_receive(struct net_device *dev, int id)
        return ret;
 }
 
-static int ipoib_cm_alloc_rx_skb(struct net_device *dev, int id,
-                                u64 mapping[IPOIB_CM_RX_SG])
+static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev, int id, int frags,
+                                            u64 mapping[IPOIB_CM_RX_SG])
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct sk_buff *skb;
@@ -107,7 +108,7 @@ static int ipoib_cm_alloc_rx_skb(struct net_device *dev, int id,
 
        skb = dev_alloc_skb(IPOIB_CM_HEAD_SIZE + 12);
        if (unlikely(!skb))
-               return -ENOMEM;
+               return NULL;
 
        /*
         * IPoIB adds a 4 byte header. So we need 12 more bytes to align the
@@ -119,10 +120,10 @@ static int ipoib_cm_alloc_rx_skb(struct net_device *dev, int id,
                                       DMA_FROM_DEVICE);
        if (unlikely(ib_dma_mapping_error(priv->ca, mapping[0]))) {
                dev_kfree_skb_any(skb);
-               return -EIO;
+               return NULL;
        }
 
-       for (i = 0; i < IPOIB_CM_RX_SG - 1; i++) {
+       for (i = 0; i < frags; i++) {
                struct page *page = alloc_page(GFP_ATOMIC);
 
                if (!page)
@@ -130,13 +131,13 @@ static int ipoib_cm_alloc_rx_skb(struct net_device *dev, int id,
                skb_fill_page_desc(skb, i, page, 0, PAGE_SIZE);
 
                mapping[i + 1] = ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[i].page,
-                                                0, PAGE_SIZE, DMA_TO_DEVICE);
+                                                0, PAGE_SIZE, DMA_FROM_DEVICE);
                if (unlikely(ib_dma_mapping_error(priv->ca, mapping[i + 1])))
                        goto partial_error;
        }
 
        priv->cm.srq_ring[id].skb = skb;
-       return 0;
+       return skb;
 
 partial_error:
 
@@ -146,7 +147,7 @@ partial_error:
                ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
 
        dev_kfree_skb_any(skb);
-       return -ENOMEM;
+       return NULL;
 }
 
 static struct ib_qp *ipoib_cm_create_rx_qp(struct net_device *dev,
@@ -309,7 +310,7 @@ static int ipoib_cm_rx_handler(struct ib_cm_id *cm_id,
 }
 /* Adjust length of skb with fragments to match received data */
 static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space,
-                         unsigned int length)
+                         unsigned int length, struct sk_buff *toskb)
 {
        int i, num_frags;
        unsigned int size;
@@ -326,7 +327,7 @@ static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space,
 
                if (length == 0) {
                        /* don't need this page */
-                       __free_page(frag->page);
+                       skb_fill_page_desc(toskb, i, frag->page, 0, PAGE_SIZE);
                        --skb_shinfo(skb)->nr_frags;
                } else {
                        size = min(length, (unsigned) PAGE_SIZE);
@@ -344,10 +345,11 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        unsigned int wr_id = wc->wr_id & ~IPOIB_CM_OP_SRQ;
-       struct sk_buff *skb;
+       struct sk_buff *skb, *newskb;
        struct ipoib_cm_rx *p;
        unsigned long flags;
        u64 mapping[IPOIB_CM_RX_SG];
+       int frags;
 
        ipoib_dbg_data(priv, "cm recv completion: id %d, op %d, status: %d\n",
                       wr_id, wc->opcode, wc->status);
@@ -383,7 +385,11 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
                }
        }
 
-       if (unlikely(ipoib_cm_alloc_rx_skb(dev, wr_id, mapping))) {
+       frags = PAGE_ALIGN(wc->byte_len - min(wc->byte_len,
+                                             (unsigned)IPOIB_CM_HEAD_SIZE)) / PAGE_SIZE;
+
+       newskb = ipoib_cm_alloc_rx_skb(dev, wr_id, frags, mapping);
+       if (unlikely(!newskb)) {
                /*
                 * If we can't allocate a new RX buffer, dump
                 * this packet and reuse the old buffer.
@@ -393,16 +399,16 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
                goto repost;
        }
 
-       ipoib_cm_dma_unmap_rx(priv, priv->cm.srq_ring[wr_id].mapping);
-       memcpy(priv->cm.srq_ring[wr_id].mapping, mapping, sizeof mapping);
+       ipoib_cm_dma_unmap_rx(priv, frags, priv->cm.srq_ring[wr_id].mapping);
+       memcpy(priv->cm.srq_ring[wr_id].mapping, mapping, (frags + 1) * sizeof *mapping);
 
        ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n",
                       wc->byte_len, wc->slid);
 
-       skb_put_frags(skb, IPOIB_CM_HEAD_SIZE, wc->byte_len);
+       skb_put_frags(skb, IPOIB_CM_HEAD_SIZE, wc->byte_len, newskb);
 
        skb->protocol = ((struct ipoib_header *) skb->data)->proto;
-       skb->mac.raw = skb->data;
+       skb_reset_mac_header(skb);
        skb_pull(skb, IPOIB_ENCAP_LEN);
 
        dev->last_rx = jiffies;
@@ -446,7 +452,7 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
                           skb->len, tx->mtu);
                ++priv->stats.tx_dropped;
                ++priv->stats.tx_errors;
-               ipoib_cm_skb_too_long(dev, skb, tx->mtu - INFINIBAND_ALEN);
+               ipoib_cm_skb_too_long(dev, skb, tx->mtu - IPOIB_ENCAP_LEN);
                return;
        }
 
@@ -1089,7 +1095,7 @@ static void ipoib_cm_stale_task(struct work_struct *work)
                /* List if sorted by LRU, start from tail,
                 * stop when we see a recently used entry */
                p = list_entry(priv->cm.passive_ids.prev, typeof(*p), list);
-               if (time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_TIMEOUT))
+               if (time_before_eq(jiffies, p->jiffies + IPOIB_CM_RX_TIMEOUT))
                        break;
                list_del_init(&p->list);
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -1193,7 +1199,8 @@ int ipoib_cm_dev_init(struct net_device *dev)
        priv->cm.rx_wr.num_sge = IPOIB_CM_RX_SG;
 
        for (i = 0; i < ipoib_recvq_size; ++i) {
-               if (ipoib_cm_alloc_rx_skb(dev, i, priv->cm.srq_ring[i].mapping)) {
+               if (!ipoib_cm_alloc_rx_skb(dev, i, IPOIB_CM_RX_SG - 1,
+                                          priv->cm.srq_ring[i].mapping)) {
                        ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
                        ipoib_cm_dev_cleanup(dev);
                        return -ENOMEM;
@@ -1228,7 +1235,8 @@ void ipoib_cm_dev_cleanup(struct net_device *dev)
                return;
        for (i = 0; i < ipoib_recvq_size; ++i)
                if (priv->cm.srq_ring[i].skb) {
-                       ipoib_cm_dma_unmap_rx(priv, priv->cm.srq_ring[i].mapping);
+                       ipoib_cm_dma_unmap_rx(priv, IPOIB_CM_RX_SG - 1,
+                                             priv->cm.srq_ring[i].mapping);
                        dev_kfree_skb_any(priv->cm.srq_ring[i].skb);
                        priv->cm.srq_ring[i].skb = NULL;
                }
This page took 0.027626 seconds and 5 git commands to generate.