X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Finfiniband%2Fulp%2Fipoib%2Fipoib_main.c;h=c3b5f79d11681e2bd43cacad1bbdb73da88203a3;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=cb078a7d0bf5b86551adf812fbc93724883616f8;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index cb078a7d0..c3b5f79d1 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -41,7 +41,6 @@ #include #include #include -#include #include /* For ARPHRD_xxx */ @@ -54,14 +53,6 @@ MODULE_AUTHOR("Roland Dreier"); MODULE_DESCRIPTION("IP-over-InfiniBand net driver"); MODULE_LICENSE("Dual BSD/GPL"); -int ipoib_sendq_size __read_mostly = IPOIB_TX_RING_SIZE; -int ipoib_recvq_size __read_mostly = IPOIB_RX_RING_SIZE; - -module_param_named(send_queue_size, ipoib_sendq_size, int, 0444); -MODULE_PARM_DESC(send_queue_size, "Number of descriptors in send queue"); -module_param_named(recv_queue_size, ipoib_recvq_size, int, 0444); -MODULE_PARM_DESC(recv_queue_size, "Number of descriptors in receive queue"); - #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG int ipoib_debug_level; @@ -142,13 +133,7 @@ static int ipoib_stop(struct net_device *dev) netif_stop_queue(dev); - /* - * Now flush workqueue to make sure a scheduled task doesn't - * bring our internal state back up. - */ - flush_workqueue(ipoib_workqueue); - - ipoib_ib_dev_down(dev, 1); + ipoib_ib_dev_down(dev); ipoib_ib_dev_stop(dev); if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { @@ -261,8 +246,9 @@ static void path_free(struct net_device *dev, struct ipoib_path *path) */ if (neigh->ah) ipoib_put_ah(neigh->ah); - - ipoib_neigh_free(neigh); + *to_ipoib_neigh(neigh->neighbour) = NULL; + neigh->neighbour->ops->destructor = NULL; + kfree(neigh); } spin_unlock_irqrestore(&priv->lock, flags); @@ -336,8 +322,9 @@ void ipoib_flush_paths(struct net_device *dev) struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_path *path, *tp; LIST_HEAD(remove_list); + unsigned long flags; - spin_lock_irq(&priv->lock); + spin_lock_irqsave(&priv->lock, flags); list_splice(&priv->path_list, &remove_list); INIT_LIST_HEAD(&priv->path_list); @@ -345,15 +332,14 @@ void ipoib_flush_paths(struct net_device *dev) list_for_each_entry(path, &remove_list, list) rb_erase(&path->rb_node, &priv->path_tree); + spin_unlock_irqrestore(&priv->lock, flags); + list_for_each_entry_safe(path, tp, &remove_list, list) { if (path->query) ib_sa_cancel_query(path->query_id, path->query); - spin_unlock_irq(&priv->lock); wait_for_completion(&path->done); path_free(dev, path); - spin_lock_irq(&priv->lock); } - spin_unlock_irq(&priv->lock); } static void path_rec_completion(int status, @@ -382,9 +368,16 @@ static void path_rec_completion(int status, struct ib_ah_attr av = { .dlid = be16_to_cpu(pathrec->dlid), .sl = pathrec->sl, - .port_num = priv->port, - .static_rate = pathrec->rate + .port_num = priv->port }; + int path_rate = ib_sa_rate_enum_to_int(pathrec->rate); + + if (path_rate > 0 && priv->local_rate > path_rate) + av.static_rate = (priv->local_rate - 1) / path_rate; + + ipoib_dbg(priv, "static_rate %d for local port %dX, path %dX\n", + av.static_rate, priv->local_rate, + ib_sa_rate_enum_to_int(pathrec->rate)); ah = ipoib_create_ah(dev, priv->pd, &av); } @@ -483,7 +476,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) struct ipoib_path *path; struct ipoib_neigh *neigh; - neigh = ipoib_neigh_alloc(skb->dst->neighbour); + neigh = kmalloc(sizeof *neigh, GFP_ATOMIC); if (!neigh) { ++priv->stats.tx_dropped; dev_kfree_skb_any(skb); @@ -491,6 +484,8 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) } skb_queue_head_init(&neigh->queue); + neigh->neighbour = skb->dst->neighbour; + *to_ipoib_neigh(skb->dst->neighbour) = neigh; /* * We can only be called from ipoib_start_xmit, so we're @@ -503,7 +498,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) path = path_rec_create(dev, (union ib_gid *) (skb->dst->neighbour->ha + 4)); if (!path) - goto err_path; + goto err; __path_add(dev, path); } @@ -518,20 +513,26 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) be32_to_cpup((__be32 *) skb->dst->neighbour->ha)); } else { neigh->ah = NULL; - __skb_queue_tail(&neigh->queue, skb); + if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { + __skb_queue_tail(&neigh->queue, skb); + } else { + ++priv->stats.tx_dropped; + dev_kfree_skb_any(skb); + } if (!path->query && path_rec_start(dev, path)) - goto err_list; + goto err; } spin_unlock(&priv->lock); return; -err_list: +err: + *to_ipoib_neigh(skb->dst->neighbour) = NULL; list_del(&neigh->list); + neigh->neighbour->ops->destructor = NULL; + kfree(neigh); -err_path: - ipoib_neigh_free(neigh); ++priv->stats.tx_dropped; dev_kfree_skb_any(skb); @@ -723,7 +724,7 @@ static int ipoib_hard_header(struct sk_buff *skb, * destination address onto the front of the skb so we can * figure out where to send the packet later. */ - if ((!skb->dst || !skb->dst->neighbour) && daddr) { + if (!skb->dst || !skb->dst->neighbour) { struct ipoib_pseudoheader *phdr = (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); @@ -736,11 +737,6 @@ static void ipoib_set_mcast_list(struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(dev); - if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) { - ipoib_dbg(priv, "IPOIB_FLAG_OPER_UP not set"); - return; - } - queue_work(ipoib_workqueue, &priv->restart_task); } @@ -763,7 +759,8 @@ static void ipoib_neigh_destructor(struct neighbour *n) if (neigh->ah) ah = neigh->ah; list_del(&neigh->list); - ipoib_neigh_free(neigh); + *to_ipoib_neigh(n) = NULL; + kfree(neigh); } spin_unlock_irqrestore(&priv->lock, flags); @@ -772,29 +769,21 @@ static void ipoib_neigh_destructor(struct neighbour *n) ipoib_put_ah(ah); } -struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour) +static int ipoib_neigh_setup(struct neighbour *neigh) { - struct ipoib_neigh *neigh; - - neigh = kmalloc(sizeof *neigh, GFP_ATOMIC); - if (!neigh) - return NULL; - - neigh->neighbour = neighbour; - *to_ipoib_neigh(neighbour) = neigh; - - return neigh; -} + /* + * Is this kosher? I can't find anybody in the kernel that + * sets neigh->destructor, so we should be able to set it here + * without trouble. + */ + neigh->ops->destructor = ipoib_neigh_destructor; -void ipoib_neigh_free(struct ipoib_neigh *neigh) -{ - *to_ipoib_neigh(neigh->neighbour) = NULL; - kfree(neigh); + return 0; } static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms) { - parms->neigh_destructor = ipoib_neigh_destructor; + parms->neigh_setup = ipoib_neigh_setup; return 0; } @@ -804,19 +793,20 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) struct ipoib_dev_priv *priv = netdev_priv(dev); /* Allocate RX/TX "rings" to hold queued skbs */ - priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring, + + priv->rx_ring = kzalloc(IPOIB_RX_RING_SIZE * sizeof (struct ipoib_rx_buf), GFP_KERNEL); if (!priv->rx_ring) { printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n", - ca->name, ipoib_recvq_size); + ca->name, IPOIB_RX_RING_SIZE); goto out; } - priv->tx_ring = kzalloc(ipoib_sendq_size * sizeof *priv->tx_ring, + priv->tx_ring = kzalloc(IPOIB_TX_RING_SIZE * sizeof (struct ipoib_tx_buf), GFP_KERNEL); if (!priv->tx_ring) { printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", - ca->name, ipoib_sendq_size); + ca->name, IPOIB_TX_RING_SIZE); goto out_rx_ring_cleanup; } @@ -884,7 +874,7 @@ static void ipoib_setup(struct net_device *dev) dev->hard_header_len = IPOIB_ENCAP_LEN + INFINIBAND_ALEN; dev->addr_len = INFINIBAND_ALEN; dev->type = ARPHRD_INFINIBAND; - dev->tx_queue_len = ipoib_sendq_size * 2; + dev->tx_queue_len = IPOIB_TX_RING_SIZE * 2; dev->features = NETIF_F_VLAN_CHALLENGED | NETIF_F_LLTX; /* MTU will be reset when mcast join happens */ @@ -1136,14 +1126,6 @@ static int __init ipoib_init_module(void) { int ret; - ipoib_recvq_size = roundup_pow_of_two(ipoib_recvq_size); - ipoib_recvq_size = min(ipoib_recvq_size, IPOIB_MAX_QUEUE_SIZE); - ipoib_recvq_size = max(ipoib_recvq_size, IPOIB_MIN_QUEUE_SIZE); - - ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size); - ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE); - ipoib_sendq_size = max(ipoib_sendq_size, IPOIB_MIN_QUEUE_SIZE); - ret = ipoib_register_debugfs(); if (ret) return ret;