net/mlx4_en: Fix mixed PFC and Global pause user control requests
[pandora-kernel.git] / drivers / net / rionet.c
index 7145714..66cd4ce 100644 (file)
@@ -79,6 +79,7 @@ static int rionet_capable = 1;
  * on system trade-offs.
  */
 static struct rio_dev **rionet_active;
+static int nact;       /* total number of active rionet peers */
 
 #define is_rionet_capable(src_ops, dst_ops)                    \
                        ((src_ops & RIO_SRC_OPS_DATA_MSG) &&    \
@@ -175,6 +176,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        struct ethhdr *eth = (struct ethhdr *)skb->data;
        u16 destid;
        unsigned long flags;
+       int add_num = 1;
 
        local_irq_save(flags);
        if (!spin_trylock(&rnet->tx_lock)) {
@@ -182,7 +184,10 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                return NETDEV_TX_LOCKED;
        }
 
-       if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) {
+       if (is_multicast_ether_addr(eth->h_dest))
+               add_num = nact;
+
+       if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) {
                netif_stop_queue(ndev);
                spin_unlock_irqrestore(&rnet->tx_lock, flags);
                printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
@@ -191,11 +196,16 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        }
 
        if (is_multicast_ether_addr(eth->h_dest)) {
+               int count = 0;
                for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size);
                                i++)
-                       if (rionet_active[i])
+                       if (rionet_active[i]) {
                                rionet_queue_tx_msg(skb, ndev,
                                                    rionet_active[i]);
+                               if (count)
+                                       atomic_inc(&skb->users);
+                               count++;
+                       }
        } else if (RIONET_MAC_MATCH(eth->h_dest)) {
                destid = RIONET_GET_DESTID(eth->h_dest);
                if (rionet_active[destid])
@@ -220,14 +230,17 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u
        if (info == RIONET_DOORBELL_JOIN) {
                if (!rionet_active[sid]) {
                        list_for_each_entry(peer, &rionet_peers, node) {
-                               if (peer->rdev->destid == sid)
+                               if (peer->rdev->destid == sid) {
                                        rionet_active[sid] = peer->rdev;
+                                       nact++;
+                               }
                        }
                        rio_mport_send_doorbell(mport, sid,
                                                RIONET_DOORBELL_JOIN);
                }
        } else if (info == RIONET_DOORBELL_LEAVE) {
                rionet_active[sid] = NULL;
+               nact--;
        } else {
                if (netif_msg_intr(rnet))
                        printk(KERN_WARNING "%s: unhandled doorbell\n",
@@ -256,7 +269,7 @@ static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbo
        struct net_device *ndev = dev_id;
        struct rionet_private *rnet = netdev_priv(ndev);
 
-       spin_lock(&rnet->lock);
+       spin_lock(&rnet->tx_lock);
 
        if (netif_msg_intr(rnet))
                printk(KERN_INFO
@@ -275,7 +288,7 @@ static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbo
        if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
                netif_wake_queue(ndev);
 
-       spin_unlock(&rnet->lock);
+       spin_unlock(&rnet->tx_lock);
 }
 
 static int rionet_open(struct net_device *ndev)
@@ -524,6 +537,7 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
 
                rc = rionet_setup_netdev(rdev->net->hport, ndev);
                rionet_check = 1;
+               nact = 0;
        }
 
        /*