Loading Documentation/networking/fib_trie.txt 0 → 100644 +145 −0 Original line number Diff line number Diff line LC-trie implementation notes. Node types ---------- leaf An end node with data. This has a copy of the relevant key, along with 'hlist' with routing table entries sorted by prefix length. See struct leaf and struct leaf_info. trie node or tnode An internal node, holding an array of child (leaf or tnode) pointers, indexed through a subset of the key. See Level Compression. A few concepts explained ------------------------ Bits (tnode) The number of bits in the key segment used for indexing into the child array - the "child index". See Level Compression. Pos (tnode) The position (in the key) of the key segment used for indexing into the child array. See Path Compression. Path Compression / skipped bits Any given tnode is linked to from the child array of its parent, using a segment of the key specified by the parent's "pos" and "bits" In certain cases, this tnode's own "pos" will not be immediately adjacent to the parent (pos+bits), but there will be some bits in the key skipped over because they represent a single path with no deviations. These "skipped bits" constitute Path Compression. Note that the search algorithm will simply skip over these bits when searching, making it necessary to save the keys in the leaves to verify that they actually do match the key we are searching for. Level Compression / child arrays the trie is kept level balanced moving, under certain conditions, the children of a full child (see "full_children") up one level, so that instead of a pure binary tree, each internal node ("tnode") may contain an arbitrarily large array of links to several children. Conversely, a tnode with a mostly empty child array (see empty_children) may be "halved", having some of its children moved downwards one level, in order to avoid ever-increasing child arrays. empty_children the number of positions in the child array of a given tnode that are NULL. full_children the number of children of a given tnode that aren't path compressed. (in other words, they aren't NULL or leaves and their "pos" is equal to this tnode's "pos"+"bits"). (The word "full" here is used more in the sense of "complete" than as the opposite of "empty", which might be a tad confusing.) Comments --------- We have tried to keep the structure of the code as close to fib_hash as possible to allow verification and help up reviewing. fib_find_node() A good start for understanding this code. This function implements a straightforward trie lookup. fib_insert_node() Inserts a new leaf node in the trie. This is bit more complicated than fib_find_node(). Inserting a new node means we might have to run the level compression algorithm on part of the trie. trie_leaf_remove() Looks up a key, deletes it and runs the level compression algorithm. trie_rebalance() The key function for the dynamic trie after any change in the trie it is run to optimize and reorganize. Tt will walk the trie upwards towards the root from a given tnode, doing a resize() at each step to implement level compression. resize() Analyzes a tnode and optimizes the child array size by either inflating or shrinking it repeatedly until it fullfills the criteria for optimal level compression. This part follows the original paper pretty closely and there may be some room for experimentation here. inflate() Doubles the size of the child array within a tnode. Used by resize(). halve() Halves the size of the child array within a tnode - the inverse of inflate(). Used by resize(); fn_trie_insert(), fn_trie_delete(), fn_trie_select_default() The route manipulation functions. Should conform pretty closely to the corresponding functions in fib_hash. fn_trie_flush() This walks the full trie (using nextleaf()) and searches for empty leaves which have to be removed. fn_trie_dump() Dumps the routing table ordered by prefix length. This is somewhat slower than the corresponding fib_hash function, as we have to walk the entire trie for each prefix length. In comparison, fib_hash is organized as one "zone"/hash per prefix length. Locking ------- fib_lock is used for an RW-lock in the same way that this is done in fib_hash. However, the functions are somewhat separated for other possible locking scenarios. It might conceivably be possible to run trie_rebalance via RCU to avoid read_lock in the fn_trie_lookup() function. Main lookup mechanism --------------------- fn_trie_lookup() is the main lookup function. The lookup is in its simplest form just like fib_find_node(). We descend the trie, key segment by key segment, until we find a leaf. check_leaf() does the fib_semantic_match in the leaf's sorted prefix hlist. If we find a match, we are done. If we don't find a match, we enter prefix matching mode. The prefix length, starting out at the same as the key length, is reduced one step at a time, and we backtrack upwards through the trie trying to find a longest matching prefix. The goal is always to reach a leaf and get a positive result from the fib_semantic_match mechanism. Inside each tnode, the search for longest matching prefix consists of searching through the child array, chopping off (zeroing) the least significant "1" of the child index until we find a match or the child index consists of nothing but zeros. At this point we backtrack (t->stats.backtrack++) up the trie, continuing to chop off part of the key in order to find the longest matching prefix. At this point we will repeatedly descend subtries to look for a match, and there are some optimizations available that can provide us with "shortcuts" to avoid descending into dead ends. Look for "HL_OPTIMIZE" sections in the code. To alleviate any doubts about the correctness of the route selection process, a new netlink operation has been added. Look for NETLINK_FIB_LOOKUP, which gives userland access to fib_lookup(). drivers/net/shaper.c +16 −26 Original line number Diff line number Diff line Loading @@ -136,9 +136,7 @@ static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev) struct shaper *shaper = dev->priv; struct sk_buff *ptr; if (down_trylock(&shaper->sem)) return -1; spin_lock(&shaper->lock); ptr=shaper->sendq.prev; /* Loading Loading @@ -232,7 +230,7 @@ static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev) shaper->stats.collisions++; } shaper_kick(shaper); up(&shaper->sem); spin_unlock(&shaper->lock); return 0; } Loading Loading @@ -271,11 +269,9 @@ static void shaper_timer(unsigned long data) { struct shaper *shaper = (struct shaper *)data; if (!down_trylock(&shaper->sem)) { spin_lock(&shaper->lock); shaper_kick(shaper); up(&shaper->sem); } else mod_timer(&shaper->timer, jiffies); spin_unlock(&shaper->lock); } /* Loading Loading @@ -331,21 +327,6 @@ static void shaper_kick(struct shaper *shaper) } /* * Flush the shaper queues on a closedown */ static void shaper_flush(struct shaper *shaper) { struct sk_buff *skb; down(&shaper->sem); while((skb=skb_dequeue(&shaper->sendq))!=NULL) dev_kfree_skb(skb); shaper_kick(shaper); up(&shaper->sem); } /* * Bring the interface up. We just disallow this until a * bind. Loading Loading @@ -375,7 +356,15 @@ static int shaper_open(struct net_device *dev) static int shaper_close(struct net_device *dev) { struct shaper *shaper=dev->priv; shaper_flush(shaper); struct sk_buff *skb; while ((skb = skb_dequeue(&shaper->sendq)) != NULL) dev_kfree_skb(skb); spin_lock_bh(&shaper->lock); shaper_kick(shaper); spin_unlock_bh(&shaper->lock); del_timer_sync(&shaper->timer); return 0; } Loading Loading @@ -576,6 +565,7 @@ static void shaper_init_priv(struct net_device *dev) init_timer(&sh->timer); sh->timer.function=shaper_timer; sh->timer.data=(unsigned long)sh; spin_lock_init(&sh->lock); } /* Loading drivers/net/skge.h +1 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ /* PCI config registers */ #define PCI_DEV_REG1 0x40 #define PCI_DEV_REG2 0x44 #define PCI_REV_DESC 0x4 #define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \ PCI_STATUS_SIG_SYSTEM_ERROR | \ Loading drivers/net/tg3.c +65 −4 Original line number Diff line number Diff line Loading @@ -66,8 +66,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " #define DRV_MODULE_VERSION "3.32" #define DRV_MODULE_RELDATE "June 24, 2005" #define DRV_MODULE_VERSION "3.33" #define DRV_MODULE_RELDATE "July 5, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 Loading Loading @@ -5117,7 +5117,7 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr, } static void __tg3_set_rx_mode(struct net_device *); static void tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) { tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs); tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs); Loading Loading @@ -5460,7 +5460,7 @@ static int tg3_reset_hw(struct tg3 *tp) udelay(10); } tg3_set_coalesce(tp, &tp->coal); __tg3_set_coalesce(tp, &tp->coal); /* set status block DMA address */ tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, Loading Loading @@ -7821,6 +7821,60 @@ static int tg3_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) return 0; } static int tg3_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) { struct tg3 *tp = netdev_priv(dev); u32 max_rxcoal_tick_int = 0, max_txcoal_tick_int = 0; u32 max_stat_coal_ticks = 0, min_stat_coal_ticks = 0; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { max_rxcoal_tick_int = MAX_RXCOAL_TICK_INT; max_txcoal_tick_int = MAX_TXCOAL_TICK_INT; max_stat_coal_ticks = MAX_STAT_COAL_TICKS; min_stat_coal_ticks = MIN_STAT_COAL_TICKS; } if ((ec->rx_coalesce_usecs > MAX_RXCOL_TICKS) || (ec->tx_coalesce_usecs > MAX_TXCOL_TICKS) || (ec->rx_max_coalesced_frames > MAX_RXMAX_FRAMES) || (ec->tx_max_coalesced_frames > MAX_TXMAX_FRAMES) || (ec->rx_coalesce_usecs_irq > max_rxcoal_tick_int) || (ec->tx_coalesce_usecs_irq > max_txcoal_tick_int) || (ec->rx_max_coalesced_frames_irq > MAX_RXCOAL_MAXF_INT) || (ec->tx_max_coalesced_frames_irq > MAX_TXCOAL_MAXF_INT) || (ec->stats_block_coalesce_usecs > max_stat_coal_ticks) || (ec->stats_block_coalesce_usecs < min_stat_coal_ticks)) return -EINVAL; /* No rx interrupts will be generated if both are zero */ if ((ec->rx_coalesce_usecs == 0) && (ec->rx_max_coalesced_frames == 0)) return -EINVAL; /* No tx interrupts will be generated if both are zero */ if ((ec->tx_coalesce_usecs == 0) && (ec->tx_max_coalesced_frames == 0)) return -EINVAL; /* Only copy relevant parameters, ignore all others. */ tp->coal.rx_coalesce_usecs = ec->rx_coalesce_usecs; tp->coal.tx_coalesce_usecs = ec->tx_coalesce_usecs; tp->coal.rx_max_coalesced_frames = ec->rx_max_coalesced_frames; tp->coal.tx_max_coalesced_frames = ec->tx_max_coalesced_frames; tp->coal.rx_coalesce_usecs_irq = ec->rx_coalesce_usecs_irq; tp->coal.tx_coalesce_usecs_irq = ec->tx_coalesce_usecs_irq; tp->coal.rx_max_coalesced_frames_irq = ec->rx_max_coalesced_frames_irq; tp->coal.tx_max_coalesced_frames_irq = ec->tx_max_coalesced_frames_irq; tp->coal.stats_block_coalesce_usecs = ec->stats_block_coalesce_usecs; if (netif_running(dev)) { tg3_full_lock(tp, 0); __tg3_set_coalesce(tp, &tp->coal); tg3_full_unlock(tp); } return 0; } static struct ethtool_ops tg3_ethtool_ops = { .get_settings = tg3_get_settings, .set_settings = tg3_set_settings, Loading Loading @@ -7856,6 +7910,7 @@ static struct ethtool_ops tg3_ethtool_ops = { .get_stats_count = tg3_get_stats_count, .get_ethtool_stats = tg3_get_ethtool_stats, .get_coalesce = tg3_get_coalesce, .set_coalesce = tg3_set_coalesce, }; static void __devinit tg3_get_eeprom_size(struct tg3 *tp) Loading Loading @@ -9800,6 +9855,12 @@ static void __devinit tg3_init_coal(struct tg3 *tp) ec->tx_coalesce_usecs = LOW_TXCOL_TICKS_CLRTCKS; ec->tx_coalesce_usecs_irq = DEFAULT_TXCOAL_TICK_INT_CLRTCKS; } if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { ec->rx_coalesce_usecs_irq = 0; ec->tx_coalesce_usecs_irq = 0; ec->stats_block_coalesce_usecs = 0; } } static int __devinit tg3_init_one(struct pci_dev *pdev, Loading drivers/net/tg3.h +10 −0 Original line number Diff line number Diff line Loading @@ -879,31 +879,41 @@ #define LOW_RXCOL_TICKS_CLRTCKS 0x00000014 #define DEFAULT_RXCOL_TICKS 0x00000048 #define HIGH_RXCOL_TICKS 0x00000096 #define MAX_RXCOL_TICKS 0x000003ff #define HOSTCC_TXCOL_TICKS 0x00003c0c #define LOW_TXCOL_TICKS 0x00000096 #define LOW_TXCOL_TICKS_CLRTCKS 0x00000048 #define DEFAULT_TXCOL_TICKS 0x0000012c #define HIGH_TXCOL_TICKS 0x00000145 #define MAX_TXCOL_TICKS 0x000003ff #define HOSTCC_RXMAX_FRAMES 0x00003c10 #define LOW_RXMAX_FRAMES 0x00000005 #define DEFAULT_RXMAX_FRAMES 0x00000008 #define HIGH_RXMAX_FRAMES 0x00000012 #define MAX_RXMAX_FRAMES 0x000000ff #define HOSTCC_TXMAX_FRAMES 0x00003c14 #define LOW_TXMAX_FRAMES 0x00000035 #define DEFAULT_TXMAX_FRAMES 0x0000004b #define HIGH_TXMAX_FRAMES 0x00000052 #define MAX_TXMAX_FRAMES 0x000000ff #define HOSTCC_RXCOAL_TICK_INT 0x00003c18 #define DEFAULT_RXCOAL_TICK_INT 0x00000019 #define DEFAULT_RXCOAL_TICK_INT_CLRTCKS 0x00000014 #define MAX_RXCOAL_TICK_INT 0x000003ff #define HOSTCC_TXCOAL_TICK_INT 0x00003c1c #define DEFAULT_TXCOAL_TICK_INT 0x00000019 #define DEFAULT_TXCOAL_TICK_INT_CLRTCKS 0x00000014 #define MAX_TXCOAL_TICK_INT 0x000003ff #define HOSTCC_RXCOAL_MAXF_INT 0x00003c20 #define DEFAULT_RXCOAL_MAXF_INT 0x00000005 #define MAX_RXCOAL_MAXF_INT 0x000000ff #define HOSTCC_TXCOAL_MAXF_INT 0x00003c24 #define DEFAULT_TXCOAL_MAXF_INT 0x00000005 #define MAX_TXCOAL_MAXF_INT 0x000000ff #define HOSTCC_STAT_COAL_TICKS 0x00003c28 #define DEFAULT_STAT_COAL_TICKS 0x000f4240 #define MAX_STAT_COAL_TICKS 0xd693d400 #define MIN_STAT_COAL_TICKS 0x00000064 /* 0x3c2c --> 0x3c30 unused */ #define HOSTCC_STATS_BLK_HOST_ADDR 0x00003c30 /* 64-bit */ #define HOSTCC_STATUS_BLK_HOST_ADDR 0x00003c38 /* 64-bit */ Loading Loading
Documentation/networking/fib_trie.txt 0 → 100644 +145 −0 Original line number Diff line number Diff line LC-trie implementation notes. Node types ---------- leaf An end node with data. This has a copy of the relevant key, along with 'hlist' with routing table entries sorted by prefix length. See struct leaf and struct leaf_info. trie node or tnode An internal node, holding an array of child (leaf or tnode) pointers, indexed through a subset of the key. See Level Compression. A few concepts explained ------------------------ Bits (tnode) The number of bits in the key segment used for indexing into the child array - the "child index". See Level Compression. Pos (tnode) The position (in the key) of the key segment used for indexing into the child array. See Path Compression. Path Compression / skipped bits Any given tnode is linked to from the child array of its parent, using a segment of the key specified by the parent's "pos" and "bits" In certain cases, this tnode's own "pos" will not be immediately adjacent to the parent (pos+bits), but there will be some bits in the key skipped over because they represent a single path with no deviations. These "skipped bits" constitute Path Compression. Note that the search algorithm will simply skip over these bits when searching, making it necessary to save the keys in the leaves to verify that they actually do match the key we are searching for. Level Compression / child arrays the trie is kept level balanced moving, under certain conditions, the children of a full child (see "full_children") up one level, so that instead of a pure binary tree, each internal node ("tnode") may contain an arbitrarily large array of links to several children. Conversely, a tnode with a mostly empty child array (see empty_children) may be "halved", having some of its children moved downwards one level, in order to avoid ever-increasing child arrays. empty_children the number of positions in the child array of a given tnode that are NULL. full_children the number of children of a given tnode that aren't path compressed. (in other words, they aren't NULL or leaves and their "pos" is equal to this tnode's "pos"+"bits"). (The word "full" here is used more in the sense of "complete" than as the opposite of "empty", which might be a tad confusing.) Comments --------- We have tried to keep the structure of the code as close to fib_hash as possible to allow verification and help up reviewing. fib_find_node() A good start for understanding this code. This function implements a straightforward trie lookup. fib_insert_node() Inserts a new leaf node in the trie. This is bit more complicated than fib_find_node(). Inserting a new node means we might have to run the level compression algorithm on part of the trie. trie_leaf_remove() Looks up a key, deletes it and runs the level compression algorithm. trie_rebalance() The key function for the dynamic trie after any change in the trie it is run to optimize and reorganize. Tt will walk the trie upwards towards the root from a given tnode, doing a resize() at each step to implement level compression. resize() Analyzes a tnode and optimizes the child array size by either inflating or shrinking it repeatedly until it fullfills the criteria for optimal level compression. This part follows the original paper pretty closely and there may be some room for experimentation here. inflate() Doubles the size of the child array within a tnode. Used by resize(). halve() Halves the size of the child array within a tnode - the inverse of inflate(). Used by resize(); fn_trie_insert(), fn_trie_delete(), fn_trie_select_default() The route manipulation functions. Should conform pretty closely to the corresponding functions in fib_hash. fn_trie_flush() This walks the full trie (using nextleaf()) and searches for empty leaves which have to be removed. fn_trie_dump() Dumps the routing table ordered by prefix length. This is somewhat slower than the corresponding fib_hash function, as we have to walk the entire trie for each prefix length. In comparison, fib_hash is organized as one "zone"/hash per prefix length. Locking ------- fib_lock is used for an RW-lock in the same way that this is done in fib_hash. However, the functions are somewhat separated for other possible locking scenarios. It might conceivably be possible to run trie_rebalance via RCU to avoid read_lock in the fn_trie_lookup() function. Main lookup mechanism --------------------- fn_trie_lookup() is the main lookup function. The lookup is in its simplest form just like fib_find_node(). We descend the trie, key segment by key segment, until we find a leaf. check_leaf() does the fib_semantic_match in the leaf's sorted prefix hlist. If we find a match, we are done. If we don't find a match, we enter prefix matching mode. The prefix length, starting out at the same as the key length, is reduced one step at a time, and we backtrack upwards through the trie trying to find a longest matching prefix. The goal is always to reach a leaf and get a positive result from the fib_semantic_match mechanism. Inside each tnode, the search for longest matching prefix consists of searching through the child array, chopping off (zeroing) the least significant "1" of the child index until we find a match or the child index consists of nothing but zeros. At this point we backtrack (t->stats.backtrack++) up the trie, continuing to chop off part of the key in order to find the longest matching prefix. At this point we will repeatedly descend subtries to look for a match, and there are some optimizations available that can provide us with "shortcuts" to avoid descending into dead ends. Look for "HL_OPTIMIZE" sections in the code. To alleviate any doubts about the correctness of the route selection process, a new netlink operation has been added. Look for NETLINK_FIB_LOOKUP, which gives userland access to fib_lookup().
drivers/net/shaper.c +16 −26 Original line number Diff line number Diff line Loading @@ -136,9 +136,7 @@ static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev) struct shaper *shaper = dev->priv; struct sk_buff *ptr; if (down_trylock(&shaper->sem)) return -1; spin_lock(&shaper->lock); ptr=shaper->sendq.prev; /* Loading Loading @@ -232,7 +230,7 @@ static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev) shaper->stats.collisions++; } shaper_kick(shaper); up(&shaper->sem); spin_unlock(&shaper->lock); return 0; } Loading Loading @@ -271,11 +269,9 @@ static void shaper_timer(unsigned long data) { struct shaper *shaper = (struct shaper *)data; if (!down_trylock(&shaper->sem)) { spin_lock(&shaper->lock); shaper_kick(shaper); up(&shaper->sem); } else mod_timer(&shaper->timer, jiffies); spin_unlock(&shaper->lock); } /* Loading Loading @@ -331,21 +327,6 @@ static void shaper_kick(struct shaper *shaper) } /* * Flush the shaper queues on a closedown */ static void shaper_flush(struct shaper *shaper) { struct sk_buff *skb; down(&shaper->sem); while((skb=skb_dequeue(&shaper->sendq))!=NULL) dev_kfree_skb(skb); shaper_kick(shaper); up(&shaper->sem); } /* * Bring the interface up. We just disallow this until a * bind. Loading Loading @@ -375,7 +356,15 @@ static int shaper_open(struct net_device *dev) static int shaper_close(struct net_device *dev) { struct shaper *shaper=dev->priv; shaper_flush(shaper); struct sk_buff *skb; while ((skb = skb_dequeue(&shaper->sendq)) != NULL) dev_kfree_skb(skb); spin_lock_bh(&shaper->lock); shaper_kick(shaper); spin_unlock_bh(&shaper->lock); del_timer_sync(&shaper->timer); return 0; } Loading Loading @@ -576,6 +565,7 @@ static void shaper_init_priv(struct net_device *dev) init_timer(&sh->timer); sh->timer.function=shaper_timer; sh->timer.data=(unsigned long)sh; spin_lock_init(&sh->lock); } /* Loading
drivers/net/skge.h +1 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ /* PCI config registers */ #define PCI_DEV_REG1 0x40 #define PCI_DEV_REG2 0x44 #define PCI_REV_DESC 0x4 #define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \ PCI_STATUS_SIG_SYSTEM_ERROR | \ Loading
drivers/net/tg3.c +65 −4 Original line number Diff line number Diff line Loading @@ -66,8 +66,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " #define DRV_MODULE_VERSION "3.32" #define DRV_MODULE_RELDATE "June 24, 2005" #define DRV_MODULE_VERSION "3.33" #define DRV_MODULE_RELDATE "July 5, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 Loading Loading @@ -5117,7 +5117,7 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr, } static void __tg3_set_rx_mode(struct net_device *); static void tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) { tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs); tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs); Loading Loading @@ -5460,7 +5460,7 @@ static int tg3_reset_hw(struct tg3 *tp) udelay(10); } tg3_set_coalesce(tp, &tp->coal); __tg3_set_coalesce(tp, &tp->coal); /* set status block DMA address */ tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, Loading Loading @@ -7821,6 +7821,60 @@ static int tg3_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) return 0; } static int tg3_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) { struct tg3 *tp = netdev_priv(dev); u32 max_rxcoal_tick_int = 0, max_txcoal_tick_int = 0; u32 max_stat_coal_ticks = 0, min_stat_coal_ticks = 0; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { max_rxcoal_tick_int = MAX_RXCOAL_TICK_INT; max_txcoal_tick_int = MAX_TXCOAL_TICK_INT; max_stat_coal_ticks = MAX_STAT_COAL_TICKS; min_stat_coal_ticks = MIN_STAT_COAL_TICKS; } if ((ec->rx_coalesce_usecs > MAX_RXCOL_TICKS) || (ec->tx_coalesce_usecs > MAX_TXCOL_TICKS) || (ec->rx_max_coalesced_frames > MAX_RXMAX_FRAMES) || (ec->tx_max_coalesced_frames > MAX_TXMAX_FRAMES) || (ec->rx_coalesce_usecs_irq > max_rxcoal_tick_int) || (ec->tx_coalesce_usecs_irq > max_txcoal_tick_int) || (ec->rx_max_coalesced_frames_irq > MAX_RXCOAL_MAXF_INT) || (ec->tx_max_coalesced_frames_irq > MAX_TXCOAL_MAXF_INT) || (ec->stats_block_coalesce_usecs > max_stat_coal_ticks) || (ec->stats_block_coalesce_usecs < min_stat_coal_ticks)) return -EINVAL; /* No rx interrupts will be generated if both are zero */ if ((ec->rx_coalesce_usecs == 0) && (ec->rx_max_coalesced_frames == 0)) return -EINVAL; /* No tx interrupts will be generated if both are zero */ if ((ec->tx_coalesce_usecs == 0) && (ec->tx_max_coalesced_frames == 0)) return -EINVAL; /* Only copy relevant parameters, ignore all others. */ tp->coal.rx_coalesce_usecs = ec->rx_coalesce_usecs; tp->coal.tx_coalesce_usecs = ec->tx_coalesce_usecs; tp->coal.rx_max_coalesced_frames = ec->rx_max_coalesced_frames; tp->coal.tx_max_coalesced_frames = ec->tx_max_coalesced_frames; tp->coal.rx_coalesce_usecs_irq = ec->rx_coalesce_usecs_irq; tp->coal.tx_coalesce_usecs_irq = ec->tx_coalesce_usecs_irq; tp->coal.rx_max_coalesced_frames_irq = ec->rx_max_coalesced_frames_irq; tp->coal.tx_max_coalesced_frames_irq = ec->tx_max_coalesced_frames_irq; tp->coal.stats_block_coalesce_usecs = ec->stats_block_coalesce_usecs; if (netif_running(dev)) { tg3_full_lock(tp, 0); __tg3_set_coalesce(tp, &tp->coal); tg3_full_unlock(tp); } return 0; } static struct ethtool_ops tg3_ethtool_ops = { .get_settings = tg3_get_settings, .set_settings = tg3_set_settings, Loading Loading @@ -7856,6 +7910,7 @@ static struct ethtool_ops tg3_ethtool_ops = { .get_stats_count = tg3_get_stats_count, .get_ethtool_stats = tg3_get_ethtool_stats, .get_coalesce = tg3_get_coalesce, .set_coalesce = tg3_set_coalesce, }; static void __devinit tg3_get_eeprom_size(struct tg3 *tp) Loading Loading @@ -9800,6 +9855,12 @@ static void __devinit tg3_init_coal(struct tg3 *tp) ec->tx_coalesce_usecs = LOW_TXCOL_TICKS_CLRTCKS; ec->tx_coalesce_usecs_irq = DEFAULT_TXCOAL_TICK_INT_CLRTCKS; } if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { ec->rx_coalesce_usecs_irq = 0; ec->tx_coalesce_usecs_irq = 0; ec->stats_block_coalesce_usecs = 0; } } static int __devinit tg3_init_one(struct pci_dev *pdev, Loading
drivers/net/tg3.h +10 −0 Original line number Diff line number Diff line Loading @@ -879,31 +879,41 @@ #define LOW_RXCOL_TICKS_CLRTCKS 0x00000014 #define DEFAULT_RXCOL_TICKS 0x00000048 #define HIGH_RXCOL_TICKS 0x00000096 #define MAX_RXCOL_TICKS 0x000003ff #define HOSTCC_TXCOL_TICKS 0x00003c0c #define LOW_TXCOL_TICKS 0x00000096 #define LOW_TXCOL_TICKS_CLRTCKS 0x00000048 #define DEFAULT_TXCOL_TICKS 0x0000012c #define HIGH_TXCOL_TICKS 0x00000145 #define MAX_TXCOL_TICKS 0x000003ff #define HOSTCC_RXMAX_FRAMES 0x00003c10 #define LOW_RXMAX_FRAMES 0x00000005 #define DEFAULT_RXMAX_FRAMES 0x00000008 #define HIGH_RXMAX_FRAMES 0x00000012 #define MAX_RXMAX_FRAMES 0x000000ff #define HOSTCC_TXMAX_FRAMES 0x00003c14 #define LOW_TXMAX_FRAMES 0x00000035 #define DEFAULT_TXMAX_FRAMES 0x0000004b #define HIGH_TXMAX_FRAMES 0x00000052 #define MAX_TXMAX_FRAMES 0x000000ff #define HOSTCC_RXCOAL_TICK_INT 0x00003c18 #define DEFAULT_RXCOAL_TICK_INT 0x00000019 #define DEFAULT_RXCOAL_TICK_INT_CLRTCKS 0x00000014 #define MAX_RXCOAL_TICK_INT 0x000003ff #define HOSTCC_TXCOAL_TICK_INT 0x00003c1c #define DEFAULT_TXCOAL_TICK_INT 0x00000019 #define DEFAULT_TXCOAL_TICK_INT_CLRTCKS 0x00000014 #define MAX_TXCOAL_TICK_INT 0x000003ff #define HOSTCC_RXCOAL_MAXF_INT 0x00003c20 #define DEFAULT_RXCOAL_MAXF_INT 0x00000005 #define MAX_RXCOAL_MAXF_INT 0x000000ff #define HOSTCC_TXCOAL_MAXF_INT 0x00003c24 #define DEFAULT_TXCOAL_MAXF_INT 0x00000005 #define MAX_TXCOAL_MAXF_INT 0x000000ff #define HOSTCC_STAT_COAL_TICKS 0x00003c28 #define DEFAULT_STAT_COAL_TICKS 0x000f4240 #define MAX_STAT_COAL_TICKS 0xd693d400 #define MIN_STAT_COAL_TICKS 0x00000064 /* 0x3c2c --> 0x3c30 unused */ #define HOSTCC_STATS_BLK_HOST_ADDR 0x00003c30 /* 64-bit */ #define HOSTCC_STATUS_BLK_HOST_ADDR 0x00003c38 /* 64-bit */ Loading