// SPDX-License-Identifier: GPL-2.0-or-later /* * NET3 Protocol independent device support routines. * * Derived from the non IP parts of dev.c 1.0.19 * Authors: Ross Biro * Fred N. van Kempen, * Mark Evans, * * Additional Authors: * Florian la Roche * Alan Cox * David Hinds * Alexey Kuznetsov * Adam Sulmicki * Pekka Riikonen * * Changes: * D.J. Barrow : Fixed bug where dev->refcnt gets set * to 2 if register_netdev gets called * before net_dev_init & also removed a * few lines of code in the process. * Alan Cox : device private ioctl copies fields back. * Alan Cox : Transmit queue code does relevant * stunts to keep the queue safe. * Alan Cox : Fixed double lock. * Alan Cox : Fixed promisc NULL pointer trap * ???????? : Support the full private ioctl range * Alan Cox : Moved ioctl permission check into * drivers * Tim Kordas : SIOCADDMULTI/SIOCDELMULTI * Alan Cox : 100 backlog just doesn't cut it when * you start doing multicast video 8) * Alan Cox : Rewrote net_bh and list manager. * Alan Cox : Fix ETH_P_ALL echoback lengths. * Alan Cox : Took out transmit every packet pass * Saved a few bytes in the ioctl handler * Alan Cox : Network driver sets packet type before * calling netif_rx. Saves a function * call a packet. * Alan Cox : Hashed net_bh() * Richard Kooijman: Timestamp fixes. * Alan Cox : Wrong field in SIOCGIFDSTADDR * Alan Cox : Device lock protection. * Alan Cox : Fixed nasty side effect of device close * changes. * Rudi Cilibrasi : Pass the right thing to * set_mac_address() * Dave Miller : 32bit quantity for the device lock to * make it work out on a Sparc. * Bjorn Ekwall : Added KERNELD hack. * Alan Cox : Cleaned up the backlog initialise. * Craig Metz : SIOCGIFCONF fix if space for under * 1 device. * Thomas Bogendoerfer : Return ENODEV for dev_open, if there * is no device open function. * Andi Kleen : Fix error reporting for SIOCGIFCONF * Michael Chastain : Fix signed/unsigned for SIOCGIFCONF * Cyrus Durgin : Cleaned for KMOD * Adam Sulmicki : Bug Fix : Network Device Unload * A network device unload needs to purge * the backlog queue. * Paul Rusty Russell : SIOCSIFNAME * Pekka Riikonen : Netdev boot-time settings code * Andrew Morton : Make unregister_netdevice wait * indefinitely on dev->refcnt * J Hadi Salim : - Backlog queue sampling * - netif_rx() feedback */ #include #include #include #include #include #include #include #include void *vzalloc(int size); #include #include #include /** * dev_close - shutdown an interface. * @dev: device to shutdown * * This function moves an active device into down state. A * %NETDEV_GOING_DOWN is sent to the netdev notifier chain. The device * is then deactivated and finally a %NETDEV_DOWN is sent to the notifier * chain. */ int dev_close(struct net_device *dev) { #ifdef MAC80211_TODO if (dev->flags & IFF_UP) { LIST_HEAD(single); list_add(&dev->close_list, &single); dev_close_many(&single, true); list_del(&single); } return 0; #else (void)dev; printk("TODO: %s\n", __FUNCTION__); return 0; #endif /*MAC80211_TODO*/ } EXPORT_SYMBOL(dev_close); void netif_wake_subqueue(struct net_device *dev, u16 queue_index) { #ifdef MAC80211_TODO struct netdev_queue *txq = netdev_get_tx_queue(dev, queue_index); if (test_and_clear_bit(__QUEUE_STATE_DRV_XOFF, &txq->state)) { struct Qdisc *q; rcu_read_lock(); q = rcu_dereference(txq->qdisc); __netif_schedule(q); rcu_read_unlock(); } #else (void)dev; (void)queue_index; UMAC_TODOMSG("TODO: %s\n", __FUNCTION__); #endif /*MAC80211_TODO*/ } EXPORT_SYMBOL(netif_wake_subqueue); int dev_queue_xmit_sk(struct sk_buff *skb) { #ifdef MAC80211_TODO #else wlan_data_xmit_skb(skb->data, (skb->tail - skb->data), skb->dev); kfree_skb(skb); return 0; #endif /*MAC80211_TODO*/ } EXPORT_SYMBOL(dev_queue_xmit_sk); /** * register_netdevice - register a network device * @dev: device to register * * Take a completed network device structure and add it to the kernel * interfaces. A %NETDEV_REGISTER message is sent to the netdev notifier * chain. 0 is returned on success. A negative errno code is returned * on a failure to set up the device, or if the name is a duplicate. * * Callers must hold the rtnl semaphore. You may want * register_netdev() instead of this. * * BUGS: * The locking appears insufficient to guarantee two parallel registers * will not get the same name. */ int cfg80211_netdev_notifier_call(struct notifier_block *nb, unsigned long state, void *ptr); int register_netdevice(struct net_device *dev) { static int ifindex_l = 0; struct netdev_notifier_info info; info.dev = dev; cfg80211_netdev_notifier_call(NULL, NETDEV_REGISTER, (void *) &info); if(++ifindex_l < 0) ifindex_l = 1; dev->ifindex = ifindex_l; spin_lock_init(&dev->addr_list_lock); return 0; } EXPORT_SYMBOL(register_netdevice); void netdev_set_default_ethtool_ops(struct net_device *dev, const struct ethtool_ops *ops) { #ifdef MAC80211_TODO if (dev->ethtool_ops == &default_ethtool_ops) dev->ethtool_ops = ops; #else (void)dev; (void)ops; printk("TODO: %s\n", __FUNCTION__); #endif /*MAC80211_TODO*/ } /** * alloc_netdev_mqs - allocate network device * @sizeof_priv: size of private data to allocate space for * @name: device name format string * @name_assign_type: origin of device name * @setup: callback to initialize device * @txqs: the number of TX subqueues to allocate * @rxqs: the number of RX subqueues to allocate * * Allocates a struct net_device with private data area for driver use * and performs basic initialization. Also allocates subqueue structs * for each queue on the device. */ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, unsigned char name_assign_type, void (*setup)(struct net_device *), unsigned int txqs, unsigned int rxqs) { (void)name_assign_type; (void)setup; (void)rxqs; struct net_device *dev; size_t alloc_size; struct net_device *p; BUG_ON(strlen(name) >= sizeof(dev->name)); if (txqs < 1) { pr_err("alloc_netdev: Unable to allocate device with zero queues\n"); return NULL; } #ifdef CONFIG_SYSFS if (rxqs < 1) { pr_err("alloc_netdev: Unable to allocate device with zero RX queues\n"); return NULL; } #endif alloc_size = sizeof(struct net_device); if (sizeof_priv) { /* ensure 32-byte alignment of private area */ alloc_size = ALIGN(alloc_size, NETDEV_ALIGN); alloc_size += sizeof_priv; } /* ensure 32-byte alignment of whole construct */ alloc_size += NETDEV_ALIGN - 1; p = kzalloc(alloc_size, 0xFFFF); if (!p) return NULL; dev = PTR_ALIGN(p, NETDEV_ALIGN); strcpy(dev->name, name); return dev; } EXPORT_SYMBOL(alloc_netdev_mqs); /** * free_netdev - free network device * @dev: device * * This function does the last stage of destroying an allocated device * interface. The reference to the device object is released. * If this is the last reference then it will be freed. */ void free_netdev(struct net_device *dev) { #ifdef MAC80211_TODO netif_free_tx_queues(dev); #ifdef CONFIG_SYSFS kvfree(dev->_rx); #endif kfree(rcu_dereference_protected(dev->ingress_queue, 1)); /* Flush device addresses */ dev_addr_flush(dev); free_percpu(dev->pcpu_refcnt); dev->pcpu_refcnt = NULL; /* Compatibility with error handling in drivers */ if (dev->reg_state == NETREG_UNINITIALIZED) { netdev_freemem(dev); return; } BUG_ON(dev->reg_state != NETREG_UNREGISTERED); dev->reg_state = NETREG_RELEASED; /* will free via device release */ put_device(&dev->dev); #else (void)dev; printk("TODO: %s\n", __FUNCTION__); #endif /* MAC80211_TODO */ } EXPORT_SYMBOL(free_netdev); /** * synchronize_net - Synchronize with packet receive processing * * Wait for packets currently being received to be done. * Does not block later packets from starting. */ void synchronize_net(void) { } EXPORT_SYMBOL(synchronize_net); /** * unregister_netdevice_queue - remove device from the kernel * @dev: device * @head: list * * This function shuts down a device interface and removes it * from the kernel tables. * If head not NULL, device is queued to be unregistered later. * * Callers must hold the rtnl semaphore. You may want * unregister_netdev() instead of this. */ void unregister_netdevice_queue(struct net_device *dev, DQ_T *head) { #ifdef MAC80211_TODO ASSERT_RTNL(); if (head) { list_move_tail(&dev->unreg_list, head); } else { rollback_registered(dev); /* Finish processing unregister after unlock */ net_set_todo(dev); } #else (void)dev; (void)head; printk("TODO: %s\n", __FUNCTION__); #endif /* MAC80211_TODO */ } EXPORT_SYMBOL(unregister_netdevice_queue); /** * unregister_netdevice_many - unregister many devices * @head: list of devices * * Note: As most callers use a stack allocated list_head, * we force a list_del() to make sure stack wont be corrupted later. */ void unregister_netdevice_many(DQ_T *head) { #ifdef MAC80211_TODO struct net_device *dev; if (!list_empty(head)) { rollback_registered_many(head); list_for_each_entry(dev, head, unreg_list) net_set_todo(dev); list_del(head); } #else (void)head; printk("TODO: %s\n", __FUNCTION__); #endif /* MAC80211_TODO */ } EXPORT_SYMBOL(unregister_netdevice_many);