sunvnet: fix a memory leak in vnet_handle_offloads
[deliverable/linux.git] / drivers / net / ethernet / sun / sunvnet.c
index 90c86cd3be1443bc72d5d1d4469882950a4be4e8..d2835bf7b4fbef1744bf2bd6d840acfe47863a39 100644 (file)
@@ -466,23 +466,6 @@ static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr,
        return err;
 }
 
-static u32 next_idx(u32 idx, struct vio_dring_state *dr)
-{
-       if (++idx == dr->num_entries)
-               idx = 0;
-       return idx;
-}
-
-static u32 prev_idx(u32 idx, struct vio_dring_state *dr)
-{
-       if (idx == 0)
-               idx = dr->num_entries - 1;
-       else
-               idx--;
-
-       return idx;
-}
-
 static struct vio_net_desc *get_rx_desc(struct vnet_port *port,
                                        struct vio_dring_state *dr,
                                        u32 index)
@@ -556,7 +539,8 @@ static int vnet_walk_rx(struct vnet_port *port, struct vio_dring_state *dr,
        int ack_start = -1, ack_end = -1;
        bool send_ack = true;
 
-       end = (end == (u32) -1) ? prev_idx(start, dr) : next_idx(end, dr);
+       end = (end == (u32) -1) ? vio_dring_prev(dr, start)
+                               : vio_dring_next(dr, end);
 
        viodbg(DATA, "vnet_walk_rx start[%08x] end[%08x]\n", start, end);
 
@@ -570,7 +554,7 @@ static int vnet_walk_rx(struct vnet_port *port, struct vio_dring_state *dr,
                if (ack_start == -1)
                        ack_start = start;
                ack_end = start;
-               start = next_idx(start, dr);
+               start = vio_dring_next(dr, start);
                if (ack && start != end) {
                        err = vnet_send_ack(port, dr, ack_start, ack_end,
                                            VIO_DRING_ACTIVE);
@@ -584,7 +568,7 @@ static int vnet_walk_rx(struct vnet_port *port, struct vio_dring_state *dr,
                }
        }
        if (unlikely(ack_start == -1))
-               ack_start = ack_end = prev_idx(start, dr);
+               ack_start = ack_end = vio_dring_prev(dr, start);
        if (send_ack) {
                port->napi_resume = false;
                return vnet_send_ack(port, dr, ack_start, ack_end,
@@ -633,7 +617,7 @@ static int idx_is_pending(struct vio_dring_state *dr, u32 end)
                        found = 1;
                        break;
                }
-               idx = next_idx(idx, dr);
+               idx = vio_dring_next(dr, idx);
        }
        return found;
 }
@@ -663,7 +647,7 @@ static int vnet_ack(struct vnet_port *port, void *msgbuf)
        /* sync for race conditions with vnet_start_xmit() and tell xmit it
         * is time to send a trigger.
         */
-       dr->cons = next_idx(end, dr);
+       dr->cons = vio_dring_next(dr, end);
        desc = vio_dring_entry(dr, dr->cons);
        if (desc->hdr.state == VIO_DESC_READY && !port->start_cons) {
                /* vnet_start_xmit() just populated this dring but missed
@@ -784,7 +768,7 @@ ldc_ctrl:
                        pkt->tag.stype = VIO_SUBTYPE_INFO;
                        pkt->tag.stype_env = VIO_DRING_DATA;
                        pkt->seq = dr->rcv_nxt;
-                       pkt->start_idx = next_idx(port->napi_stop_idx, dr);
+                       pkt->start_idx = vio_dring_next(dr, port->napi_stop_idx);
                        pkt->end_idx = -1;
                        goto napi_resume;
                }
@@ -1217,6 +1201,7 @@ static int vnet_handle_offloads(struct vnet_port *port, struct sk_buff *skb)
                segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO);
        if (IS_ERR(segs)) {
                dev->stats.tx_dropped++;
+               dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
 
This page took 0.026786 seconds and 5 git commands to generate.