FILE
ethernet-tx.c
File preview with syntax highlighting.
linux-6.19.14/drivers/staging/octeon/ethernet-tx.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * This file is based on code from OCTEON SDK by Cavium Networks. 4 * 5 * Copyright (c) 2003-2010 Cavium Networks 6 */ 7 8#include <linux/module.h> 9#include <linux/kernel.h> 10#include <linux/netdevice.h> 11#include <linux/etherdevice.h> 12#include <linux/ip.h> 13#include <linux/ratelimit.h> 14#include <linux/string.h> 15#include <linux/interrupt.h> 16#include <net/dst.h> 17#ifdef CONFIG_XFRM 18#include <linux/xfrm.h> 19#include <net/xfrm.h> 20#endif /* CONFIG_XFRM */ 21 22#include <linux/atomic.h> 23#include <net/sch_generic.h> 24 25#include "octeon-ethernet.h" 26#include "ethernet-defines.h" 27#include "ethernet-tx.h" 28#include "ethernet-util.h" 29 30#define CVM_OCT_SKB_CB(skb) ((u64 *)((skb)->cb)) 31 32/* 33 * You can define GET_SKBUFF_QOS() to override how the skbuff output 34 * function determines which output queue is used. The default 35 * implementation always uses the base queue for the port. If, for 36 * example, you wanted to use the skb->priority field, define 37 * GET_SKBUFF_QOS as: #define GET_SKBUFF_QOS(skb) ((skb)->priority) 38 */ 39#ifndef GET_SKBUFF_QOS 40#define GET_SKBUFF_QOS(skb) 0 41#endif 42 43static void cvm_oct_tx_do_cleanup(struct tasklet_struct *clean); 44static DECLARE_TASKLET(cvm_oct_tx_cleanup_tasklet, cvm_oct_tx_do_cleanup); 45 46/* Maximum number of SKBs to try to free per xmit packet. */ 47#define MAX_SKB_TO_FREE (MAX_OUT_QUEUE_DEPTH * 2) 48 49static inline int cvm_oct_adjust_skb_to_free(int skb_to_free, int fau) 50{ 51 int undo; 52 53 undo = skb_to_free > 0 ? MAX_SKB_TO_FREE : skb_to_free + 54 MAX_SKB_TO_FREE; 55 if (undo > 0) 56 cvmx_fau_atomic_add32(fau, -undo); 57 skb_to_free = -skb_to_free > MAX_SKB_TO_FREE ? MAX_SKB_TO_FREE : 58 -skb_to_free; 59 return skb_to_free; 60} 61 62static void cvm_oct_kick_tx_poll_watchdog(void) 63{ 64 union cvmx_ciu_timx ciu_timx; 65 66 ciu_timx.u64 = 0; 67 ciu_timx.s.one_shot = 1; 68 ciu_timx.s.len = cvm_oct_tx_poll_interval; 69 cvmx_write_csr(CVMX_CIU_TIMX(1), ciu_timx.u64); 70} 71 72static void cvm_oct_free_tx_skbs(struct net_device *dev) 73{ 74 int skb_to_free; 75 int qos, queues_per_port; 76 int total_remaining = 0; 77 unsigned long flags; 78 struct octeon_ethernet *priv = netdev_priv(dev); 79 80 queues_per_port = cvmx_pko_get_num_queues(priv->port); 81 /* Drain any pending packets in the free list */ 82 for (qos = 0; qos < queues_per_port; qos++) { 83 if (skb_queue_len(&priv->tx_free_list[qos]) == 0) 84 continue; 85 skb_to_free = cvmx_fau_fetch_and_add32(priv->fau + qos * 4, 86 MAX_SKB_TO_FREE); 87 skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, 88 priv->fau + qos * 4); 89 if (skb_to_free > 0) { 90 struct sk_buff *to_free_list = NULL; 91 92 spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); 93 while (skb_to_free > 0) { 94 struct sk_buff *t; 95 96 t = __skb_dequeue(&priv->tx_free_list[qos]); 97 t->next = to_free_list; 98 to_free_list = t; 99 skb_to_free--; 100 } 101 spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, 102 flags); 103 /* Do the actual freeing outside of the lock. */ 104 while (to_free_list) { 105 struct sk_buff *t = to_free_list; 106 107 to_free_list = to_free_list->next; 108 dev_kfree_skb_any(t); 109 } 110 } 111 total_remaining += skb_queue_len(&priv->tx_free_list[qos]); 112 } 113 if (total_remaining < MAX_OUT_QUEUE_DEPTH && netif_queue_stopped(dev)) 114 netif_wake_queue(dev); 115 if (total_remaining) 116 cvm_oct_kick_tx_poll_watchdog(); 117} 118 119/** 120 * cvm_oct_xmit - transmit a packet 121 * @skb: Packet to send 122 * @dev: Device info structure 123 * 124 * Returns Always returns NETDEV_TX_OK 125 */ 126netdev_tx_t cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) 127{ 128 union cvmx_pko_command_word0 pko_command; 129 union cvmx_buf_ptr hw_buffer; 130 u64 old_scratch; 131 u64 old_scratch2; 132 int qos; 133 int i; 134 enum {QUEUE_CORE, QUEUE_HW, QUEUE_DROP} queue_type; 135 struct octeon_ethernet *priv = netdev_priv(dev); 136 struct sk_buff *to_free_list; 137 int skb_to_free; 138 int buffers_to_free; 139 u32 total_to_clean; 140 unsigned long flags; 141#if REUSE_SKBUFFS_WITHOUT_FREE 142 unsigned char *fpa_head; 143#endif 144 145 /* 146 * Prefetch the private data structure. It is larger than the 147 * one cache line. 148 */ 149 prefetch(priv); 150 151 /* 152 * The check on CVMX_PKO_QUEUES_PER_PORT_* is designed to 153 * completely remove "qos" in the event neither interface 154 * supports multiple queues per port. 155 */ 156 if ((CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 > 1) || 157 (CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 > 1)) { 158 qos = GET_SKBUFF_QOS(skb); 159 if (qos <= 0) 160 qos = 0; 161 else if (qos >= cvmx_pko_get_num_queues(priv->port)) 162 qos = 0; 163 } else { 164 qos = 0; 165 } 166 167 if (USE_ASYNC_IOBDMA) { 168 /* Save scratch in case userspace is using it */ 169 CVMX_SYNCIOBDMA; 170 old_scratch = cvmx_scratch_read64(CVMX_SCR_SCRATCH); 171 old_scratch2 = cvmx_scratch_read64(CVMX_SCR_SCRATCH + 8); 172 173 /* 174 * Fetch and increment the number of packets to be 175 * freed. 176 */ 177 cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH + 8, 178 FAU_NUM_PACKET_BUFFERS_TO_FREE, 179 0); 180 cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH, 181 priv->fau + qos * 4, 182 MAX_SKB_TO_FREE); 183 } 184 185 /* 186 * We have space for 6 segment pointers, If there will be more 187 * than that, we must linearize. 188 */ 189 if (unlikely(skb_shinfo(skb)->nr_frags > 5)) { 190 if (unlikely(__skb_linearize(skb))) { 191 queue_type = QUEUE_DROP; 192 if (USE_ASYNC_IOBDMA) { 193 /* 194 * Get the number of skbuffs in use 195 * by the hardware 196 */ 197 CVMX_SYNCIOBDMA; 198 skb_to_free = 199 cvmx_scratch_read64(CVMX_SCR_SCRATCH); 200 } else { 201 /* 202 * Get the number of skbuffs in use 203 * by the hardware 204 */ 205 skb_to_free = 206 cvmx_fau_fetch_and_add32(priv->fau + 207 qos * 4, 208 MAX_SKB_TO_FREE); 209 } 210 skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, 211 priv->fau + 212 qos * 4); 213 spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); 214 goto skip_xmit; 215 } 216 } 217 218 /* 219 * The CN3XXX series of parts has an errata (GMX-401) which 220 * causes the GMX block to hang if a collision occurs towards 221 * the end of a <68 byte packet. As a workaround for this, we 222 * pad packets to be 68 bytes whenever we are in half duplex 223 * mode. We don't handle the case of having a small packet but 224 * no room to add the padding. The kernel should always give 225 * us at least a cache line 226 */ 227 if ((skb->len < 64) && OCTEON_IS_MODEL(OCTEON_CN3XXX)) { 228 union cvmx_gmxx_prtx_cfg gmx_prt_cfg; 229 int interface = INTERFACE(priv->port); 230 int index = INDEX(priv->port); 231 232 if (interface < 2) { 233 /* We only need to pad packet in half duplex mode */ 234 gmx_prt_cfg.u64 = 235 cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); 236 if (gmx_prt_cfg.s.duplex == 0) { 237 int add_bytes = 64 - skb->len; 238 239 if ((skb_tail_pointer(skb) + add_bytes) <= 240 skb_end_pointer(skb)) 241 __skb_put_zero(skb, add_bytes); 242 } 243 } 244 } 245 246 /* Build the PKO command */ 247 pko_command.u64 = 0; 248#ifdef __LITTLE_ENDIAN 249 pko_command.s.le = 1; 250#endif 251 pko_command.s.n2 = 1; /* Don't pollute L2 with the outgoing packet */ 252 pko_command.s.segs = 1; 253 pko_command.s.total_bytes = skb->len; 254 pko_command.s.size0 = CVMX_FAU_OP_SIZE_32; 255 pko_command.s.subone0 = 1; 256 257 pko_command.s.dontfree = 1; 258 259 /* Build the PKO buffer pointer */ 260 hw_buffer.u64 = 0; 261 if (skb_shinfo(skb)->nr_frags == 0) { 262 hw_buffer.s.addr = XKPHYS_TO_PHYS((uintptr_t)skb->data); 263 hw_buffer.s.pool = 0; 264 hw_buffer.s.size = skb->len; 265 } else { 266 hw_buffer.s.addr = XKPHYS_TO_PHYS((uintptr_t)skb->data); 267 hw_buffer.s.pool = 0; 268 hw_buffer.s.size = skb_headlen(skb); 269 CVM_OCT_SKB_CB(skb)[0] = hw_buffer.u64; 270 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 271 skb_frag_t *fs = skb_shinfo(skb)->frags + i; 272 273 hw_buffer.s.addr = 274 XKPHYS_TO_PHYS((uintptr_t)skb_frag_address(fs)); 275 hw_buffer.s.size = skb_frag_size(fs); 276 CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64; 277 } 278 hw_buffer.s.addr = 279 XKPHYS_TO_PHYS((uintptr_t)CVM_OCT_SKB_CB(skb)); 280 hw_buffer.s.size = skb_shinfo(skb)->nr_frags + 1; 281 pko_command.s.segs = skb_shinfo(skb)->nr_frags + 1; 282 pko_command.s.gather = 1; 283 goto dont_put_skbuff_in_hw; 284 } 285 286 /* 287 * See if we can put this skb in the FPA pool. Any strange 288 * behavior from the Linux networking stack will most likely 289 * be caused by a bug in the following code. If some field is 290 * in use by the network stack and gets carried over when a 291 * buffer is reused, bad things may happen. If in doubt and 292 * you dont need the absolute best performance, disable the 293 * define REUSE_SKBUFFS_WITHOUT_FREE. The reuse of buffers has 294 * shown a 25% increase in performance under some loads. 295 */ 296#if REUSE_SKBUFFS_WITHOUT_FREE 297 fpa_head = skb->head + 256 - ((unsigned long)skb->head & 0x7f); 298 if (unlikely(skb->data < fpa_head)) { 299 /* TX buffer beginning can't meet FPA alignment constraints */ 300 goto dont_put_skbuff_in_hw; 301 } 302 if (unlikely 303 ((skb_end_pointer(skb) - fpa_head) < CVMX_FPA_PACKET_POOL_SIZE)) { 304 /* TX buffer isn't large enough for the FPA */ 305 goto dont_put_skbuff_in_hw; 306 } 307 if (unlikely(skb_shared(skb))) { 308 /* TX buffer sharing data with someone else */ 309 goto dont_put_skbuff_in_hw; 310 } 311 if (unlikely(skb_cloned(skb))) { 312 /* TX buffer has been cloned */ 313 goto dont_put_skbuff_in_hw; 314 } 315 if (unlikely(skb_header_cloned(skb))) { 316 /* TX buffer header has been cloned */ 317 goto dont_put_skbuff_in_hw; 318 } 319 if (unlikely(skb->destructor)) { 320 /* TX buffer has a destructor */ 321 goto dont_put_skbuff_in_hw; 322 } 323 if (unlikely(skb_shinfo(skb)->nr_frags)) { 324 /* TX buffer has fragments */ 325 goto dont_put_skbuff_in_hw; 326 } 327 if (unlikely 328 (skb->truesize != 329 sizeof(*skb) + skb_end_offset(skb))) { 330 /* TX buffer truesize has been changed */ 331 goto dont_put_skbuff_in_hw; 332 } 333 334 /* 335 * We can use this buffer in the FPA. We don't need the FAU 336 * update anymore 337 */ 338 pko_command.s.dontfree = 0; 339 340 hw_buffer.s.back = ((unsigned long)skb->data >> 7) - 341 ((unsigned long)fpa_head >> 7); 342 343 *(struct sk_buff **)(fpa_head - sizeof(void *)) = skb; 344 345 /* 346 * The skbuff will be reused without ever being freed. We must 347 * cleanup a bunch of core things. 348 */ 349 skb_dst_drop(skb); 350 skb_ext_reset(skb); 351 nf_reset_ct(skb); 352 skb_reset_redirect(skb); 353 354#ifdef CONFIG_NET_SCHED 355 skb->tc_index = 0; 356#endif /* CONFIG_NET_SCHED */ 357#endif /* REUSE_SKBUFFS_WITHOUT_FREE */ 358 359dont_put_skbuff_in_hw: 360 361 /* Check if we can use the hardware checksumming */ 362 if ((skb->protocol == htons(ETH_P_IP)) && 363 (ip_hdr(skb)->version == 4) && 364 (ip_hdr(skb)->ihl == 5) && 365 ((ip_hdr(skb)->frag_off == 0) || 366 (ip_hdr(skb)->frag_off == htons(1 << 14))) && 367 ((ip_hdr(skb)->protocol == IPPROTO_TCP) || 368 (ip_hdr(skb)->protocol == IPPROTO_UDP))) { 369 /* Use hardware checksum calc */ 370 pko_command.s.ipoffp1 = skb_network_offset(skb) + 1; 371 } 372 373 if (USE_ASYNC_IOBDMA) { 374 /* Get the number of skbuffs in use by the hardware */ 375 CVMX_SYNCIOBDMA; 376 skb_to_free = cvmx_scratch_read64(CVMX_SCR_SCRATCH); 377 buffers_to_free = cvmx_scratch_read64(CVMX_SCR_SCRATCH + 8); 378 } else { 379 /* Get the number of skbuffs in use by the hardware */ 380 skb_to_free = cvmx_fau_fetch_and_add32(priv->fau + qos * 4, 381 MAX_SKB_TO_FREE); 382 buffers_to_free = 383 cvmx_fau_fetch_and_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); 384 } 385 386 skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, 387 priv->fau + qos * 4); 388 389 /* 390 * If we're sending faster than the receive can free them then 391 * don't do the HW free. 392 */ 393 if ((buffers_to_free < -100) && !pko_command.s.dontfree) 394 pko_command.s.dontfree = 1; 395 396 if (pko_command.s.dontfree) { 397 queue_type = QUEUE_CORE; 398 pko_command.s.reg0 = priv->fau + qos * 4; 399 } else { 400 queue_type = QUEUE_HW; 401 } 402 if (USE_ASYNC_IOBDMA) 403 cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH, 404 FAU_TOTAL_TX_TO_CLEAN, 1); 405 406 spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); 407 408 /* Drop this packet if we have too many already queued to the HW */ 409 if (unlikely(skb_queue_len(&priv->tx_free_list[qos]) >= 410 MAX_OUT_QUEUE_DEPTH)) { 411 if (dev->tx_queue_len != 0) { 412 /* Drop the lock when notifying the core. */ 413 spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, 414 flags); 415 netif_stop_queue(dev); 416 spin_lock_irqsave(&priv->tx_free_list[qos].lock, 417 flags); 418 } else { 419 /* If not using normal queueing. */ 420 queue_type = QUEUE_DROP; 421 goto skip_xmit; 422 } 423 } 424 425 cvmx_pko_send_packet_prepare(priv->port, priv->queue + qos, 426 CVMX_PKO_LOCK_NONE); 427 428 /* Send the packet to the output queue */ 429 if (unlikely(cvmx_pko_send_packet_finish(priv->port, 430 priv->queue + qos, 431 pko_command, hw_buffer, 432 CVMX_PKO_LOCK_NONE))) { 433 printk_ratelimited("%s: Failed to send the packet\n", 434 dev->name); 435 queue_type = QUEUE_DROP; 436 } 437skip_xmit: 438 to_free_list = NULL; 439 440 switch (queue_type) { 441 case QUEUE_DROP: 442 skb->next = to_free_list; 443 to_free_list = skb; 444 dev->stats.tx_dropped++; 445 break; 446 case QUEUE_HW: 447 cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, -1); 448 break; 449 case QUEUE_CORE: 450 __skb_queue_tail(&priv->tx_free_list[qos], skb); 451 break; 452 default: 453 BUG(); 454 } 455 456 while (skb_to_free > 0) { 457 struct sk_buff *t = __skb_dequeue(&priv->tx_free_list[qos]); 458 459 t->next = to_free_list; 460 to_free_list = t; 461 skb_to_free--; 462 } 463 464 spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, flags); 465 466 /* Do the actual freeing outside of the lock. */ 467 while (to_free_list) { 468 struct sk_buff *t = to_free_list; 469 470 to_free_list = to_free_list->next; 471 dev_kfree_skb_any(t); 472 } 473 474 if (USE_ASYNC_IOBDMA) { 475 CVMX_SYNCIOBDMA; 476 total_to_clean = cvmx_scratch_read64(CVMX_SCR_SCRATCH); 477 /* Restore the scratch area */ 478 cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch); 479 cvmx_scratch_write64(CVMX_SCR_SCRATCH + 8, old_scratch2); 480 } else { 481 total_to_clean = 482 cvmx_fau_fetch_and_add32(FAU_TOTAL_TX_TO_CLEAN, 1); 483 } 484 485 if (total_to_clean & 0x3ff) { 486 /* 487 * Schedule the cleanup tasklet every 1024 packets for 488 * the pathological case of high traffic on one port 489 * delaying clean up of packets on a different port 490 * that is blocked waiting for the cleanup. 491 */ 492 tasklet_schedule(&cvm_oct_tx_cleanup_tasklet); 493 } 494 495 cvm_oct_kick_tx_poll_watchdog(); 496 497 return NETDEV_TX_OK; 498} 499 500/** 501 * cvm_oct_xmit_pow - transmit a packet to the POW 502 * @skb: Packet to send 503 * @dev: Device info structure 504 * Returns Always returns zero 505 */ 506netdev_tx_t cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev) 507{ 508 struct octeon_ethernet *priv = netdev_priv(dev); 509 void *packet_buffer; 510 void *copy_location; 511 512 /* Get a work queue entry */ 513 struct cvmx_wqe *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL); 514 515 if (unlikely(!work)) { 516 printk_ratelimited("%s: Failed to allocate a work queue entry\n", 517 dev->name); 518 dev->stats.tx_dropped++; 519 dev_kfree_skb_any(skb); 520 return 0; 521 } 522 523 /* Get a packet buffer */ 524 packet_buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL); 525 if (unlikely(!packet_buffer)) { 526 printk_ratelimited("%s: Failed to allocate a packet buffer\n", 527 dev->name); 528 cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 1); 529 dev->stats.tx_dropped++; 530 dev_kfree_skb_any(skb); 531 return 0; 532 } 533 534 /* 535 * Calculate where we need to copy the data to. We need to 536 * leave 8 bytes for a next pointer (unused). We also need to 537 * include any configure skip. Then we need to align the IP 538 * packet src and dest into the same 64bit word. The below 539 * calculation may add a little extra, but that doesn't 540 * hurt. 541 */ 542 copy_location = packet_buffer + sizeof(u64); 543 copy_location += ((CVMX_HELPER_FIRST_MBUFF_SKIP + 7) & 0xfff8) + 6; 544 545 /* 546 * We have to copy the packet since whoever processes this 547 * packet will free it to a hardware pool. We can't use the 548 * trick of counting outstanding packets like in 549 * cvm_oct_xmit. 550 */ 551 memcpy(copy_location, skb->data, skb->len); 552 553 /* 554 * Fill in some of the work queue fields. We may need to add 555 * more if the software at the other end needs them. 556 */ 557 if (!OCTEON_IS_MODEL(OCTEON_CN68XX)) 558 work->word0.pip.cn38xx.hw_chksum = skb->csum; 559 work->word1.len = skb->len; 560 cvmx_wqe_set_port(work, priv->port); 561 cvmx_wqe_set_qos(work, priv->port & 0x7); 562 cvmx_wqe_set_grp(work, pow_send_group); 563 work->word1.tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 564 work->word1.tag = pow_send_group; /* FIXME */ 565 /* Default to zero. Sets of zero later are commented out */ 566 work->word2.u64 = 0; 567 work->word2.s.bufs = 1; 568 work->packet_ptr.u64 = 0; 569 work->packet_ptr.s.addr = cvmx_ptr_to_phys(copy_location); 570 work->packet_ptr.s.pool = CVMX_FPA_PACKET_POOL; 571 work->packet_ptr.s.size = CVMX_FPA_PACKET_POOL_SIZE; 572 work->packet_ptr.s.back = (copy_location - packet_buffer) >> 7; 573 574 if (skb->protocol == htons(ETH_P_IP)) { 575 work->word2.s.ip_offset = 14; 576 work->word2.s.tcp_or_udp = 577 (ip_hdr(skb)->protocol == IPPROTO_TCP) || 578 (ip_hdr(skb)->protocol == IPPROTO_UDP); 579 work->word2.s.is_frag = !((ip_hdr(skb)->frag_off == 0) || 580 (ip_hdr(skb)->frag_off == 581 cpu_to_be16(1 << 14))); 582 work->word2.s.is_bcast = (skb->pkt_type == PACKET_BROADCAST); 583 work->word2.s.is_mcast = (skb->pkt_type == PACKET_MULTICAST); 584 585 /* 586 * When copying the data, include 4 bytes of the 587 * ethernet header to align the same way hardware 588 * does. 589 */ 590 memcpy(work->packet_data, skb->data + 10, 591 sizeof(work->packet_data)); 592 } else { 593 work->word2.snoip.is_rarp = skb->protocol == htons(ETH_P_RARP); 594 work->word2.snoip.is_arp = skb->protocol == htons(ETH_P_ARP); 595 work->word2.snoip.is_bcast = 596 (skb->pkt_type == PACKET_BROADCAST); 597 work->word2.snoip.is_mcast = 598 (skb->pkt_type == PACKET_MULTICAST); 599 work->word2.snoip.not_IP = 1; /* IP was done up above */ 600 memcpy(work->packet_data, skb->data, sizeof(work->packet_data)); 601 } 602 603 /* Submit the packet to the POW */ 604 cvmx_pow_work_submit(work, work->word1.tag, work->word1.tag_type, 605 cvmx_wqe_get_qos(work), cvmx_wqe_get_grp(work)); 606 dev->stats.tx_packets++; 607 dev->stats.tx_bytes += skb->len; 608 dev_consume_skb_any(skb); 609 return 0; 610} 611 612/** 613 * cvm_oct_tx_shutdown_dev - free all skb that are currently queued for TX. 614 * @dev: Device being shutdown 615 * 616 */ 617void cvm_oct_tx_shutdown_dev(struct net_device *dev) 618{ 619 struct octeon_ethernet *priv = netdev_priv(dev); 620 unsigned long flags; 621 int qos; 622 623 for (qos = 0; qos < 16; qos++) { 624 spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); 625 while (skb_queue_len(&priv->tx_free_list[qos])) 626 dev_kfree_skb_any(__skb_dequeue 627 (&priv->tx_free_list[qos])); 628 spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, flags); 629 } 630} 631 632static void cvm_oct_tx_do_cleanup(struct tasklet_struct *clean) 633{ 634 int port; 635 636 for (port = 0; port < TOTAL_NUMBER_OF_PORTS; port++) { 637 if (cvm_oct_device[port]) { 638 struct net_device *dev = cvm_oct_device[port]; 639 640 cvm_oct_free_tx_skbs(dev); 641 } 642 } 643} 644 645static irqreturn_t cvm_oct_tx_cleanup_watchdog(int cpl, void *dev_id) 646{ 647 /* Disable the interrupt. */ 648 cvmx_write_csr(CVMX_CIU_TIMX(1), 0); 649 /* Do the work in the tasklet. */ 650 tasklet_schedule(&cvm_oct_tx_cleanup_tasklet); 651 return IRQ_HANDLED; 652} 653 654void cvm_oct_tx_initialize(void) 655{ 656 int i; 657 658 /* Disable the interrupt. */ 659 cvmx_write_csr(CVMX_CIU_TIMX(1), 0); 660 /* Register an IRQ handler to receive CIU_TIMX(1) interrupts */ 661 i = request_irq(OCTEON_IRQ_TIMER1, 662 cvm_oct_tx_cleanup_watchdog, 0, 663 "Ethernet", cvm_oct_device); 664 665 if (i) 666 panic("Could not acquire Ethernet IRQ %d\n", OCTEON_IRQ_TIMER1); 667} 668 669void cvm_oct_tx_shutdown(void) 670{ 671 /* Free the interrupt handler */ 672 free_irq(OCTEON_IRQ_TIMER1, cvm_oct_device); 673}
~/
Read-only file preview.