cregit-Linux how code gets into the kernel

Release 4.11 net/irda/irlan/irlan_eth.c

Directory: net/irda/irlan
/*********************************************************************
 *
 * Filename:      irlan_eth.c
 * Version:
 * Description:
 * Status:        Experimental.
 * Author:        Dag Brattli <dagb@cs.uit.no>
 * Created at:    Thu Oct 15 08:37:58 1998
 * Modified at:   Tue Mar 21 09:06:41 2000
 * Modified by:   Dag Brattli <dagb@cs.uit.no>
 * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
 *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
 *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
 *
 *     Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
 *
 *     This program is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU General Public License as
 *     published by the Free Software Foundation; either version 2 of
 *     the License, or (at your option) any later version.
 *
 *     Neither Dag Brattli nor University of Tromsø admit liability nor
 *     provide warranty for any of this software. This material is
 *     provided "AS-IS" and at no charge.
 *
 ********************************************************************/

#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/inetdevice.h>
#include <linux/if_arp.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <net/arp.h>

#include <net/irda/irda.h>
#include <net/irda/irmod.h>
#include <net/irda/irlan_common.h>
#include <net/irda/irlan_client.h>
#include <net/irda/irlan_event.h>
#include <net/irda/irlan_eth.h>

static int  irlan_eth_open(struct net_device *dev);
static int  irlan_eth_close(struct net_device *dev);
static netdev_tx_t  irlan_eth_xmit(struct sk_buff *skb,
					 struct net_device *dev);
static void irlan_eth_set_multicast_list(struct net_device *dev);


static const struct net_device_ops irlan_eth_netdev_ops = {
	.ndo_open		= irlan_eth_open,
	.ndo_stop		= irlan_eth_close,
	.ndo_start_xmit		= irlan_eth_xmit,
	.ndo_set_rx_mode	= irlan_eth_set_multicast_list,
	.ndo_validate_addr	= eth_validate_addr,
};

/*
 * Function irlan_eth_setup (dev)
 *
 *    The network device initialization function.
 *
 */

static void irlan_eth_setup(struct net_device *dev) { ether_setup(dev); dev->netdev_ops = &irlan_eth_netdev_ops; dev->destructor = free_netdev; dev->min_mtu = 0; dev->max_mtu = ETH_MAX_MTU; /* * Lets do all queueing in IrTTP instead of this device driver. * Queueing here as well can introduce some strange latency * problems, which we will avoid by setting the queue size to 0. */ /* * The bugs in IrTTP and IrLAN that created this latency issue * have now been fixed, and we can propagate flow control properly * to the network layer. However, this requires a minimal queue of * packets for the device. * Without flow control, the Tx Queue is 14 (ttp) + 0 (dev) = 14 * With flow control, the Tx Queue is 7 (ttp) + 4 (dev) = 11 * See irlan_eth_flow_indication()... * Note : this number was randomly selected and would need to * be adjusted. * Jean II */ dev->tx_queue_len = 4; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)1836.73%225.00%
Stephen Hemminger1326.53%225.00%
Jarod Wilson1224.49%112.50%
Jean Tourrilhes48.16%112.50%
Hideaki Yoshifuji / 吉藤英明12.04%112.50%
Al Viro12.04%112.50%
Total49100.00%8100.00%

/* * Function alloc_irlandev * * Allocate network device and control block * */
struct net_device *alloc_irlandev(const char *name) { return alloc_netdev(sizeof(struct irlan_cb), name, NET_NAME_UNKNOWN, irlan_eth_setup); }

Contributors

PersonTokensPropCommitsCommitProp
Jean Tourrilhes2071.43%125.00%
Linus Torvalds (pre-git)621.43%250.00%
Tom Gundersen27.14%125.00%
Total28100.00%4100.00%

/* * Function irlan_eth_open (dev) * * Network device has been opened by user * */
static int irlan_eth_open(struct net_device *dev) { struct irlan_cb *self = netdev_priv(dev); /* Ready to play! */ netif_stop_queue(dev); /* Wait until data link is ready */ /* We are now open, so time to do some work */ self->disconnect_reason = 0; irlan_client_wakeup(self, self->saddr, self->daddr); /* Make sure we have a hardware address before we return, so DHCP clients gets happy */ return wait_event_interruptible(self->open_wait, !self->tsap_data->connected); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)4875.00%350.00%
Jean Tourrilhes1523.44%233.33%
Hideaki Yoshifuji / 吉藤英明11.56%116.67%
Total64100.00%6100.00%

/* * Function irlan_eth_close (dev) * * Stop the ether network device, his function will usually be called by * ifconfig down. We should now disconnect the link, We start the * close timer, so that the instance will be removed if we are unable * to discover the remote device after the disconnect. */
static int irlan_eth_close(struct net_device *dev) { struct irlan_cb *self = netdev_priv(dev); /* Stop device */ netif_stop_queue(dev); irlan_close_data_channel(self); irlan_close_tsaps(self); irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL); irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL); /* Remove frames queued on the control channel */ skb_queue_purge(&self->client.txq); self->client.tx_busy = 0; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)7293.51%480.00%
Jean Tourrilhes56.49%120.00%
Total77100.00%5100.00%

/* * Function irlan_eth_tx (skb) * * Transmits ethernet frames over IrDA link. * */
static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb, struct net_device *dev) { struct irlan_cb *self = netdev_priv(dev); int ret; unsigned int len; /* skb headroom large enough to contain all IrDA-headers? */ if ((skb_headroom(skb) < self->max_header_size) || (skb_shared(skb))) { struct sk_buff *new_skb = skb_realloc_headroom(skb, self->max_header_size); /* We have to free the original skb anyway */ dev_kfree_skb(skb); /* Did the realloc succeed? */ if (new_skb == NULL) return NETDEV_TX_OK; /* Use the new skb instead */ skb = new_skb; } netif_trans_update(dev); len = skb->len; /* Now queue the packet in the transport layer */ if (self->use_udata) ret = irttp_udata_request(self->tsap_data, skb); else ret = irttp_data_request(self->tsap_data, skb); if (ret < 0) { /* * IrTTPs tx queue is full, so we just have to * drop the frame! You might think that we should * just return -1 and don't deallocate the frame, * but that is dangerous since it's possible that * we have replaced the original skb with a new * one with larger headroom, and that would really * confuse do_dev_queue_xmit() in dev.c! I have * tried :-) DB */ /* irttp_data_request already free the packet */ dev->stats.tx_dropped++; } else { dev->stats.tx_packets++; dev->stats.tx_bytes += len; } return NETDEV_TX_OK; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)14384.12%538.46%
Eric Dumazet137.65%215.38%
Jean Tourrilhes74.12%215.38%
Florian Westphal31.76%17.69%
Patrick McHardy21.18%17.69%
Hideaki Yoshifuji / 吉藤英明10.59%17.69%
Stephen Hemminger10.59%17.69%
Total170100.00%13100.00%

/* * Function irlan_eth_receive (handle, skb) * * This function gets the data that is received on the data channel * */
int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb) { struct irlan_cb *self = instance; struct net_device *dev = self->dev; if (skb == NULL) { dev->stats.rx_dropped++; return 0; } if (skb->len < ETH_HLEN) { pr_debug("%s() : IrLAN frame too short (%d)\n", __func__, skb->len); dev->stats.rx_dropped++; dev_kfree_skb(skb); return 0; } /* * Adopt this frame! Important to set all these fields since they * might have been previously set by the low level IrDA network * device driver */ skb->protocol = eth_type_trans(skb, dev); /* Remove eth header */ dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; netif_rx(skb); /* Eat it! */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)7760.63%440.00%
Jean Tourrilhes3225.20%220.00%
Eric Dumazet1511.81%110.00%
Harvey Harrison10.79%110.00%
Hideaki Yoshifuji / 吉藤英明10.79%110.00%
Joe Perches10.79%110.00%
Total127100.00%10100.00%

/* * Function irlan_eth_flow (status) * * Do flow control between IP/Ethernet and IrLAN/IrTTP. This is done by * controlling the queue stop/start. * * The IrDA link layer has the advantage to have flow control, and * IrTTP now properly handles that. Flow controlling the higher layers * prevent us to drop Tx packets in here (up to 15% for a TCP socket, * more for UDP socket). * Also, this allow us to reduce the overall transmit queue, which means * less latency in case of mixed traffic. * Jean II */
void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow) { struct irlan_cb *self; struct net_device *dev; self = instance; IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); dev = self->dev; IRDA_ASSERT(dev != NULL, return;); pr_debug("%s() : flow %s ; running %d\n", __func__, flow == FLOW_STOP ? "FLOW_STOP" : "FLOW_START", netif_running(dev)); switch (flow) { case FLOW_STOP: /* IrTTP is full, stop higher layers */ netif_stop_queue(dev); break; case FLOW_START: default: /* Tell upper layers that its time to transmit frames again */ /* Schedule network layer */ netif_wake_queue(dev); break; } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)8076.19%450.00%
Jean Tourrilhes2321.90%225.00%
Joe Perches10.95%112.50%
Harvey Harrison10.95%112.50%
Total105100.00%8100.00%

/* * Function set_multicast_list (dev) * * Configure the filtering of the device * */ #define HW_MAX_ADDRS 4 /* Must query to get it! */
static void irlan_eth_set_multicast_list(struct net_device *dev) { struct irlan_cb *self = netdev_priv(dev); /* Check if data channel has been connected yet */ if (self->client.state != IRLAN_DATA) { pr_debug("%s(), delaying!\n", __func__); return; } if (dev->flags & IFF_PROMISC) { /* Enable promiscuous mode */ net_warn_ratelimited("Promiscuous mode not implemented by IrLAN!\n"); } else if ((dev->flags & IFF_ALLMULTI) || netdev_mc_count(dev) > HW_MAX_ADDRS) { /* Disable promiscuous mode, use normal mode. */ pr_debug("%s(), Setting multicast filter\n", __func__); /* hardware_set_filter(NULL); */ irlan_set_multicast_filter(self, TRUE); } else if (!netdev_mc_empty(dev)) { pr_debug("%s(), Setting multicast filter\n", __func__); /* Walk the address list, and load the filter */ /* hardware_set_filter(dev->mc_list); */ irlan_set_multicast_filter(self, TRUE); } else { pr_debug("%s(), Clearing multicast filter\n", __func__); irlan_set_multicast_filter(self, FALSE); } if (dev->flags & IFF_BROADCAST) irlan_set_broadcast_filter(self, TRUE); else irlan_set_broadcast_filter(self, FALSE); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)13080.75%330.00%
Jean Tourrilhes148.70%220.00%
Jiri Pirko74.35%110.00%
Joe Perches63.73%330.00%
Harvey Harrison42.48%110.00%
Total161100.00%10100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)61667.54%926.47%
Jean Tourrilhes16618.20%514.71%
Stephen Hemminger475.15%38.82%
Eric Dumazet283.07%25.88%
Jarod Wilson121.32%12.94%
Jiri Pirko80.88%25.88%
Joe Perches80.88%38.82%
Hideaki Yoshifuji / 吉藤英明60.66%12.94%
Harvey Harrison60.66%12.94%
Florian Westphal30.33%12.94%
Rusty Russell30.33%12.94%
Alexey Dobriyan30.33%12.94%
Tom Gundersen20.22%12.94%
Patrick McHardy20.22%12.94%
Al Viro10.11%12.94%
Jan Engelhardt10.11%12.94%
Total912100.00%34100.00%
Directory: net/irda/irlan
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.