aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2010-01-07 14:05:05 -0500
committerRalf Baechle <ralf@linux-mips.org>2010-02-27 06:53:08 -0500
commit924cc2680fbe181066ec138d369691d28d913ea2 (patch)
tree009d3b28ddf2ebc9466b882fd8170ea97e6d8a73 /drivers
parent3368c784bcf77124aaf39372e627016c36bd4472 (diff)
Staging: Octeon Ethernet: Enable scatter-gather.
Octeon ethernet hardware can handle NETIF_F_SG, so we enable it. A gather list of up to six fragments will fit in the SKB's CB structure, so no extra memory is required. If a SKB has more than six fragments, we must linearize it. Signed-off-by: David Daney <ddaney@caviumnetworks.com> To: linux-mips@linux-mips.org To: gregkh@suse.de Patchwork: http://patchwork.linux-mips.org/patch/838/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/octeon/ethernet-tx.c57
-rw-r--r--drivers/staging/octeon/ethernet.c7
2 files changed, 55 insertions, 9 deletions
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index 05b58f8b58fd..bc67e416e421 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -53,6 +53,8 @@
53 53
54#include "cvmx-gmxx-defs.h" 54#include "cvmx-gmxx-defs.h"
55 55
56#define CVM_OCT_SKB_CB(skb) ((u64 *)((skb)->cb))
57
56/* 58/*
57 * You can define GET_SKBUFF_QOS() to override how the skbuff output 59 * You can define GET_SKBUFF_QOS() to override how the skbuff output
58 * function determines which output queue is used. The default 60 * function determines which output queue is used. The default
@@ -121,6 +123,7 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
121 uint64_t old_scratch; 123 uint64_t old_scratch;
122 uint64_t old_scratch2; 124 uint64_t old_scratch2;
123 int qos; 125 int qos;
126 int i;
124 enum {QUEUE_CORE, QUEUE_HW, QUEUE_DROP} queue_type; 127 enum {QUEUE_CORE, QUEUE_HW, QUEUE_DROP} queue_type;
125 struct octeon_ethernet *priv = netdev_priv(dev); 128 struct octeon_ethernet *priv = netdev_priv(dev);
126 struct sk_buff *to_free_list; 129 struct sk_buff *to_free_list;
@@ -171,6 +174,28 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
171 } 174 }
172 175
173 /* 176 /*
177 * We have space for 6 segment pointers, If there will be more
178 * than that, we must linearize.
179 */
180 if (unlikely(skb_shinfo(skb)->nr_frags > 5)) {
181 if (unlikely(__skb_linearize(skb))) {
182 queue_type = QUEUE_DROP;
183 if (USE_ASYNC_IOBDMA) {
184 /* Get the number of skbuffs in use by the hardware */
185 CVMX_SYNCIOBDMA;
186 skb_to_free = cvmx_scratch_read64(CVMX_SCR_SCRATCH);
187 } else {
188 /* Get the number of skbuffs in use by the hardware */
189 skb_to_free = cvmx_fau_fetch_and_add32(priv->fau + qos * 4,
190 MAX_SKB_TO_FREE);
191 }
192 skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, priv->fau + qos * 4);
193 spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags);
194 goto skip_xmit;
195 }
196 }
197
198 /*
174 * The CN3XXX series of parts has an errata (GMX-401) which 199 * The CN3XXX series of parts has an errata (GMX-401) which
175 * causes the GMX block to hang if a collision occurs towards 200 * causes the GMX block to hang if a collision occurs towards
176 * the end of a <68 byte packet. As a workaround for this, we 201 * the end of a <68 byte packet. As a workaround for this, we
@@ -198,13 +223,6 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
198 } 223 }
199 } 224 }
200 225
201 /* Build the PKO buffer pointer */
202 hw_buffer.u64 = 0;
203 hw_buffer.s.addr = cvmx_ptr_to_phys(skb->data);
204 hw_buffer.s.pool = 0;
205 hw_buffer.s.size =
206 (unsigned long)skb_end_pointer(skb) - (unsigned long)skb->head;
207
208 /* Build the PKO command */ 226 /* Build the PKO command */
209 pko_command.u64 = 0; 227 pko_command.u64 = 0;
210 pko_command.s.n2 = 1; /* Don't pollute L2 with the outgoing packet */ 228 pko_command.s.n2 = 1; /* Don't pollute L2 with the outgoing packet */
@@ -215,6 +233,31 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
215 233
216 pko_command.s.dontfree = 1; 234 pko_command.s.dontfree = 1;
217 pko_command.s.reg0 = priv->fau + qos * 4; 235 pko_command.s.reg0 = priv->fau + qos * 4;
236
237 /* Build the PKO buffer pointer */
238 hw_buffer.u64 = 0;
239 if (skb_shinfo(skb)->nr_frags == 0) {
240 hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)skb->data);
241 hw_buffer.s.pool = 0;
242 hw_buffer.s.size = skb->len;
243 } else {
244 hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)skb->data);
245 hw_buffer.s.pool = 0;
246 hw_buffer.s.size = skb_headlen(skb);
247 CVM_OCT_SKB_CB(skb)[0] = hw_buffer.u64;
248 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
249 struct skb_frag_struct *fs = skb_shinfo(skb)->frags + i;
250 hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)(page_address(fs->page) + fs->page_offset));
251 hw_buffer.s.size = fs->size;
252 CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64;
253 }
254 hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)CVM_OCT_SKB_CB(skb));
255 hw_buffer.s.size = skb_shinfo(skb)->nr_frags + 1;
256 pko_command.s.segs = skb_shinfo(skb)->nr_frags + 1;
257 pko_command.s.gather = 1;
258 goto dont_put_skbuff_in_hw;
259 }
260
218 /* 261 /*
219 * See if we can put this skb in the FPA pool. Any strange 262 * See if we can put this skb in the FPA pool. Any strange
220 * behavior from the Linux networking stack will most likely 263 * behavior from the Linux networking stack will most likely
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index 9f5b7419e777..9d632020b9ee 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -484,8 +484,11 @@ int cvm_oct_common_init(struct net_device *dev)
484 && (always_use_pow || strstr(pow_send_list, dev->name))) 484 && (always_use_pow || strstr(pow_send_list, dev->name)))
485 priv->queue = -1; 485 priv->queue = -1;
486 486
487 if (priv->queue != -1 && USE_HW_TCPUDP_CHECKSUM) 487 if (priv->queue != -1) {
488 dev->features |= NETIF_F_IP_CSUM; 488 dev->features |= NETIF_F_SG;
489 if (USE_HW_TCPUDP_CHECKSUM)
490 dev->features |= NETIF_F_IP_CSUM;
491 }
489 492
490 /* We do our own locking, Linux doesn't need to */ 493 /* We do our own locking, Linux doesn't need to */
491 dev->features |= NETIF_F_LLTX; 494 dev->features |= NETIF_F_LLTX;