aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2014-09-20 19:50:03 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2014-09-23 06:59:18 -0400
commitb101c9626477b1f9d30f31d11442a9cc80c98d7c (patch)
treecb9bf9d2994c65e6011bec82fa596187cb617c67 /drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
parent3abaae42e1bf686bf5c43063a00b0f4ddbb14373 (diff)
fm10k: Add transmit and receive fastpath and interrupt handlers
This change adds the transmit and receive fastpath and interrupt handlers. With this code in place the network device is now able to send and receive frames over the network interface using a single queue. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> CC: Rick Jones <rick.jones2@hp.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/fm10k/fm10k_netdev.c')
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_netdev.c94
1 files changed, 92 insertions, 2 deletions
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index 52673d78de8e..46df65856156 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -451,8 +451,66 @@ int fm10k_close(struct net_device *netdev)
451 451
452static netdev_tx_t fm10k_xmit_frame(struct sk_buff *skb, struct net_device *dev) 452static netdev_tx_t fm10k_xmit_frame(struct sk_buff *skb, struct net_device *dev)
453{ 453{
454 dev_kfree_skb_any(skb); 454 struct fm10k_intfc *interface = netdev_priv(dev);
455 return NETDEV_TX_OK; 455 unsigned int r_idx = 0;
456 int err;
457
458 if ((skb->protocol == htons(ETH_P_8021Q)) &&
459 !vlan_tx_tag_present(skb)) {
460 /* FM10K only supports hardware tagging, any tags in frame
461 * are considered 2nd level or "outer" tags
462 */
463 struct vlan_hdr *vhdr;
464 __be16 proto;
465
466 /* make sure skb is not shared */
467 skb = skb_share_check(skb, GFP_ATOMIC);
468 if (!skb)
469 return NETDEV_TX_OK;
470
471 /* make sure there is enough room to move the ethernet header */
472 if (unlikely(!pskb_may_pull(skb, VLAN_ETH_HLEN)))
473 return NETDEV_TX_OK;
474
475 /* verify the skb head is not shared */
476 err = skb_cow_head(skb, 0);
477 if (err)
478 return NETDEV_TX_OK;
479
480 /* locate vlan header */
481 vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN);
482
483 /* pull the 2 key pieces of data out of it */
484 __vlan_hwaccel_put_tag(skb,
485 htons(ETH_P_8021Q),
486 ntohs(vhdr->h_vlan_TCI));
487 proto = vhdr->h_vlan_encapsulated_proto;
488 skb->protocol = (ntohs(proto) >= 1536) ? proto :
489 htons(ETH_P_802_2);
490
491 /* squash it by moving the ethernet addresses up 4 bytes */
492 memmove(skb->data + VLAN_HLEN, skb->data, 12);
493 __skb_pull(skb, VLAN_HLEN);
494 skb_reset_mac_header(skb);
495 }
496
497 /* The minimum packet size for a single buffer is 17B so pad the skb
498 * in order to meet this minimum size requirement.
499 */
500 if (unlikely(skb->len < 17)) {
501 int pad_len = 17 - skb->len;
502
503 if (skb_pad(skb, pad_len))
504 return NETDEV_TX_OK;
505 __skb_put(skb, pad_len);
506 }
507
508 if (r_idx >= interface->num_tx_queues)
509 r_idx %= interface->num_tx_queues;
510
511 err = fm10k_xmit_frame_ring(skb, interface->tx_ring[r_idx]);
512
513 return err;
456} 514}
457 515
458static int fm10k_change_mtu(struct net_device *dev, int new_mtu) 516static int fm10k_change_mtu(struct net_device *dev, int new_mtu)
@@ -465,6 +523,37 @@ static int fm10k_change_mtu(struct net_device *dev, int new_mtu)
465 return 0; 523 return 0;
466} 524}
467 525
526/**
527 * fm10k_tx_timeout - Respond to a Tx Hang
528 * @netdev: network interface device structure
529 **/
530static void fm10k_tx_timeout(struct net_device *netdev)
531{
532 struct fm10k_intfc *interface = netdev_priv(netdev);
533 bool real_tx_hang = false;
534 int i;
535
536#define TX_TIMEO_LIMIT 16000
537 for (i = 0; i < interface->num_tx_queues; i++) {
538 struct fm10k_ring *tx_ring = interface->tx_ring[i];
539
540 if (check_for_tx_hang(tx_ring) && fm10k_check_tx_hang(tx_ring))
541 real_tx_hang = true;
542 }
543
544 if (real_tx_hang) {
545 fm10k_tx_timeout_reset(interface);
546 } else {
547 netif_info(interface, drv, netdev,
548 "Fake Tx hang detected with timeout of %d seconds\n",
549 netdev->watchdog_timeo/HZ);
550
551 /* fake Tx hang - increase the kernel timeout */
552 if (netdev->watchdog_timeo < TX_TIMEO_LIMIT)
553 netdev->watchdog_timeo *= 2;
554 }
555}
556
468static int fm10k_uc_vlan_unsync(struct net_device *netdev, 557static int fm10k_uc_vlan_unsync(struct net_device *netdev,
469 const unsigned char *uc_addr) 558 const unsigned char *uc_addr)
470{ 559{
@@ -891,6 +980,7 @@ static const struct net_device_ops fm10k_netdev_ops = {
891 .ndo_start_xmit = fm10k_xmit_frame, 980 .ndo_start_xmit = fm10k_xmit_frame,
892 .ndo_set_mac_address = fm10k_set_mac, 981 .ndo_set_mac_address = fm10k_set_mac,
893 .ndo_change_mtu = fm10k_change_mtu, 982 .ndo_change_mtu = fm10k_change_mtu,
983 .ndo_tx_timeout = fm10k_tx_timeout,
894 .ndo_vlan_rx_add_vid = fm10k_vlan_rx_add_vid, 984 .ndo_vlan_rx_add_vid = fm10k_vlan_rx_add_vid,
895 .ndo_vlan_rx_kill_vid = fm10k_vlan_rx_kill_vid, 985 .ndo_vlan_rx_kill_vid = fm10k_vlan_rx_kill_vid,
896 .ndo_set_rx_mode = fm10k_set_rx_mode, 986 .ndo_set_rx_mode = fm10k_set_rx_mode,