diff options
1296 files changed, 93750 insertions, 36138 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index 8906648f962b..445289cd0e65 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -402,8 +402,9 @@ !Finclude/net/mac80211.h set_key_cmd !Finclude/net/mac80211.h ieee80211_key_conf !Finclude/net/mac80211.h ieee80211_key_flags -!Finclude/net/mac80211.h ieee80211_tkip_key_type -!Finclude/net/mac80211.h ieee80211_get_tkip_key +!Finclude/net/mac80211.h ieee80211_get_tkip_p1k +!Finclude/net/mac80211.h ieee80211_get_tkip_p1k_iv +!Finclude/net/mac80211.h ieee80211_get_tkip_p2k !Finclude/net/mac80211.h ieee80211_key_removed </chapter> diff --git a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c index 2bac9618c345..65968fbf1e49 100644 --- a/Documentation/networking/ifenslave.c +++ b/Documentation/networking/ifenslave.c @@ -260,7 +260,7 @@ int main(int argc, char *argv[]) case 'V': opt_V++; exclusive++; break; case '?': - fprintf(stderr, usage_msg); + fprintf(stderr, "%s", usage_msg); res = 2; goto out; } @@ -268,13 +268,13 @@ int main(int argc, char *argv[]) /* options check */ if (exclusive > 1) { - fprintf(stderr, usage_msg); + fprintf(stderr, "%s", usage_msg); res = 2; goto out; } if (opt_v || opt_V) { - printf(version); + printf("%s", version); if (opt_V) { res = 0; goto out; @@ -282,14 +282,14 @@ int main(int argc, char *argv[]) } if (opt_u) { - printf(usage_msg); + printf("%s", usage_msg); res = 0; goto out; } if (opt_h) { - printf(usage_msg); - printf(help_msg); + printf("%s", usage_msg); + printf("%s", help_msg); res = 0; goto out; } @@ -309,7 +309,7 @@ int main(int argc, char *argv[]) goto out; } else { /* Just show usage */ - fprintf(stderr, usage_msg); + fprintf(stderr, "%s", usage_msg); res = 2; goto out; } @@ -320,7 +320,7 @@ int main(int argc, char *argv[]) master_ifname = *spp++; if (master_ifname == NULL) { - fprintf(stderr, usage_msg); + fprintf(stderr, "%s", usage_msg); res = 2; goto out; } @@ -339,7 +339,7 @@ int main(int argc, char *argv[]) if (slave_ifname == NULL) { if (opt_d || opt_c) { - fprintf(stderr, usage_msg); + fprintf(stderr, "%s", usage_msg); res = 2; goto out; } diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index bfe924217f24..db2a4067013c 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -106,16 +106,6 @@ inet_peer_maxttl - INTEGER when the number of entries in the pool is very small). Measured in seconds. -inet_peer_gc_mintime - INTEGER - Minimum interval between garbage collection passes. This interval is - in effect under high memory pressure on the pool. - Measured in seconds. - -inet_peer_gc_maxtime - INTEGER - Minimum interval between garbage collection passes. This interval is - in effect under low (or absent) memory pressure on the pool. - Measured in seconds. - TCP variables: somaxconn - INTEGER @@ -394,7 +384,7 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max min: Minimal size of receive buffer used by TCP sockets. It is guaranteed to each TCP socket, even under moderate memory pressure. - Default: 8K + Default: 1 page default: initial size of receive buffer used by TCP sockets. This value overrides net.core.rmem_default used by other protocols. @@ -483,7 +473,7 @@ tcp_window_scaling - BOOLEAN tcp_wmem - vector of 3 INTEGERs: min, default, max min: Amount of memory reserved for send buffers for TCP sockets. Each TCP socket has rights to use it due to fact of its birth. - Default: 4K + Default: 1 page default: initial size of send buffer used by TCP sockets. This value overrides net.core.wmem_default used by other protocols. @@ -553,13 +543,13 @@ udp_rmem_min - INTEGER Minimal size of receive buffer used by UDP sockets in moderation. Each UDP socket is able to use the size for receiving data, even if total pages of UDP sockets exceed udp_mem pressure. The unit is byte. - Default: 4096 + Default: 1 page udp_wmem_min - INTEGER Minimal size of send buffer used by UDP sockets in moderation. Each UDP socket is able to use the size for sending data, even if total pages of UDP sockets exceed udp_mem pressure. The unit is byte. - Default: 4096 + Default: 1 page CIPSOv4 Variables: @@ -1465,10 +1455,17 @@ sctp_mem - vector of 3 INTEGERs: min, pressure, max Default is calculated at boot time from amount of available memory. sctp_rmem - vector of 3 INTEGERs: min, default, max - See tcp_rmem for a description. + Only the first value ("min") is used, "default" and "max" are + ignored. + + min: Minimal size of receive buffer used by SCTP socket. + It is guaranteed to each SCTP socket (but not association) even + under moderate memory pressure. + + Default: 1 page sctp_wmem - vector of 3 INTEGERs: min, default, max - See tcp_wmem for a description. + Currently this tunable has no effect. addr_scope_policy - INTEGER Control IPv4 address scoping - draft-stewart-tsvwg-sctp-ipv4-00 diff --git a/Documentation/networking/netdev-features.txt b/Documentation/networking/netdev-features.txt new file mode 100644 index 000000000000..4b1c0dcef84c --- /dev/null +++ b/Documentation/networking/netdev-features.txt @@ -0,0 +1,154 @@ +Netdev features mess and how to get out from it alive +===================================================== + +Author: + Michał Mirosław <mirq-linux@rere.qmqm.pl> + + + + Part I: Feature sets +====================== + +Long gone are the days when a network card would just take and give packets +verbatim. Today's devices add multiple features and bugs (read: offloads) +that relieve an OS of various tasks like generating and checking checksums, +splitting packets, classifying them. Those capabilities and their state +are commonly referred to as netdev features in Linux kernel world. + +There are currently three sets of features relevant to the driver, and +one used internally by network core: + + 1. netdev->hw_features set contains features whose state may possibly + be changed (enabled or disabled) for a particular device by user's + request. This set should be initialized in ndo_init callback and not + changed later. + + 2. netdev->features set contains features which are currently enabled + for a device. This should be changed only by network core or in + error paths of ndo_set_features callback. + + 3. netdev->vlan_features set contains features whose state is inherited + by child VLAN devices (limits netdev->features set). This is currently + used for all VLAN devices whether tags are stripped or inserted in + hardware or software. + + 4. netdev->wanted_features set contains feature set requested by user. + This set is filtered by ndo_fix_features callback whenever it or + some device-specific conditions change. This set is internal to + networking core and should not be referenced in drivers. + + + + Part II: Controlling enabled features +======================================= + +When current feature set (netdev->features) is to be changed, new set +is calculated and filtered by calling ndo_fix_features callback +and netdev_fix_features(). If the resulting set differs from current +set, it is passed to ndo_set_features callback and (if the callback +returns success) replaces value stored in netdev->features. +NETDEV_FEAT_CHANGE notification is issued after that whenever current +set might have changed. + +The following events trigger recalculation: + 1. device's registration, after ndo_init returned success + 2. user requested changes in features state + 3. netdev_update_features() is called + +ndo_*_features callbacks are called with rtnl_lock held. Missing callbacks +are treated as always returning success. + +A driver that wants to trigger recalculation must do so by calling +netdev_update_features() while holding rtnl_lock. This should not be done +from ndo_*_features callbacks. netdev->features should not be modified by +driver except by means of ndo_fix_features callback. + + + + Part III: Implementation hints +================================ + + * ndo_fix_features: + +All dependencies between features should be resolved here. The resulting +set can be reduced further by networking core imposed limitations (as coded +in netdev_fix_features()). For this reason it is safer to disable a feature +when its dependencies are not met instead of forcing the dependency on. + +This callback should not modify hardware nor driver state (should be +stateless). It can be called multiple times between successive +ndo_set_features calls. + +Callback must not alter features contained in NETIF_F_SOFT_FEATURES or +NETIF_F_NEVER_CHANGE sets. The exception is NETIF_F_VLAN_CHALLENGED but +care must be taken as the change won't affect already configured VLANs. + + * ndo_set_features: + +Hardware should be reconfigured to match passed feature set. The set +should not be altered unless some error condition happens that can't +be reliably detected in ndo_fix_features. In this case, the callback +should update netdev->features to match resulting hardware state. +Errors returned are not (and cannot be) propagated anywhere except dmesg. +(Note: successful return is zero, >0 means silent error.) + + + + Part IV: Features +=================== + +For current list of features, see include/linux/netdev_features.h. +This section describes semantics of some of them. + + * Transmit checksumming + +For complete description, see comments near the top of include/linux/skbuff.h. + +Note: NETIF_F_HW_CSUM is a superset of NETIF_F_IP_CSUM + NETIF_F_IPV6_CSUM. +It means that device can fill TCP/UDP-like checksum anywhere in the packets +whatever headers there might be. + + * Transmit TCP segmentation offload + +NETIF_F_TSO_ECN means that hardware can properly split packets with CWR bit +set, be it TCPv4 (when NETIF_F_TSO is enabled) or TCPv6 (NETIF_F_TSO6). + + * Transmit DMA from high memory + +On platforms where this is relevant, NETIF_F_HIGHDMA signals that +ndo_start_xmit can handle skbs with frags in high memory. + + * Transmit scatter-gather + +Those features say that ndo_start_xmit can handle fragmented skbs: +NETIF_F_SG --- paged skbs (skb_shinfo()->frags), NETIF_F_FRAGLIST --- +chained skbs (skb->next/prev list). + + * Software features + +Features contained in NETIF_F_SOFT_FEATURES are features of networking +stack. Driver should not change behaviour based on them. + + * LLTX driver (deprecated for hardware drivers) + +NETIF_F_LLTX should be set in drivers that implement their own locking in +transmit path or don't need locking at all (e.g. software tunnels). +In ndo_start_xmit, it is recommended to use a try_lock and return +NETDEV_TX_LOCKED when the spin lock fails. The locking should also properly +protect against other callbacks (the rules you need to find out). + +Don't use it for new drivers. + + * netns-local device + +NETIF_F_NETNS_LOCAL is set for devices that are not allowed to move between +network namespaces (e.g. loopback). + +Don't use it in drivers. + + * VLAN challenged + +NETIF_F_VLAN_CHALLENGED should be set for devices which can't cope with VLAN +headers. Some drivers set this because the cards can't handle the bigger MTU. +[FIXME: Those cases could be fixed in VLAN code by allowing only reduced-MTU +VLANs. This may be not useful, though.] diff --git a/Documentation/networking/nfc.txt b/Documentation/networking/nfc.txt new file mode 100644 index 000000000000..b24c29bdae27 --- /dev/null +++ b/Documentation/networking/nfc.txt @@ -0,0 +1,128 @@ +Linux NFC subsystem +=================== + +The Near Field Communication (NFC) subsystem is required to standardize the +NFC device drivers development and to create an unified userspace interface. + +This document covers the architecture overview, the device driver interface +description and the userspace interface description. + +Architecture overview +--------------------- + +The NFC subsystem is responsible for: + - NFC adapters management; + - Polling for targets; + - Low-level data exchange; + +The subsystem is divided in some parts. The 'core' is responsible for +providing the device driver interface. On the other side, it is also +responsible for providing an interface to control operations and low-level +data exchange. + +The control operations are available to userspace via generic netlink. + +The low-level data exchange interface is provided by the new socket family +PF_NFC. The NFC_SOCKPROTO_RAW performs raw communication with NFC targets. + + + +--------------------------------------+ + | USER SPACE | + +--------------------------------------+ + ^ ^ + | low-level | control + | data exchange | operations + | | + | v + | +-----------+ + | AF_NFC | netlink | + | socket +-----------+ + | raw ^ + | | + v v + +---------+ +-----------+ + | rawsock | <--------> | core | + +---------+ +-----------+ + ^ + | + v + +-----------+ + | driver | + +-----------+ + +Device Driver Interface +----------------------- + +When registering on the NFC subsystem, the device driver must inform the core +of the set of supported NFC protocols and the set of ops callbacks. The ops +callbacks that must be implemented are the following: + +* start_poll - setup the device to poll for targets +* stop_poll - stop on progress polling operation +* activate_target - select and initialize one of the targets found +* deactivate_target - deselect and deinitialize the selected target +* data_exchange - send data and receive the response (transceive operation) + +Userspace interface +-------------------- + +The userspace interface is divided in control operations and low-level data +exchange operation. + +CONTROL OPERATIONS: + +Generic netlink is used to implement the interface to the control operations. +The operations are composed by commands and events, all listed below: + +* NFC_CMD_GET_DEVICE - get specific device info or dump the device list +* NFC_CMD_START_POLL - setup a specific device to polling for targets +* NFC_CMD_STOP_POLL - stop the polling operation in a specific device +* NFC_CMD_GET_TARGET - dump the list of targets found by a specific device + +* NFC_EVENT_DEVICE_ADDED - reports an NFC device addition +* NFC_EVENT_DEVICE_REMOVED - reports an NFC device removal +* NFC_EVENT_TARGETS_FOUND - reports START_POLL results when 1 or more targets +are found + +The user must call START_POLL to poll for NFC targets, passing the desired NFC +protocols through NFC_ATTR_PROTOCOLS attribute. The device remains in polling +state until it finds any target. However, the user can stop the polling +operation by calling STOP_POLL command. In this case, it will be checked if +the requester of STOP_POLL is the same of START_POLL. + +If the polling operation finds one or more targets, the event TARGETS_FOUND is +sent (including the device id). The user must call GET_TARGET to get the list of +all targets found by such device. Each reply message has target attributes with +relevant information such as the supported NFC protocols. + +All polling operations requested through one netlink socket are stopped when +it's closed. + +LOW-LEVEL DATA EXCHANGE: + +The userspace must use PF_NFC sockets to perform any data communication with +targets. All NFC sockets use AF_NFC: + +struct sockaddr_nfc { + sa_family_t sa_family; + __u32 dev_idx; + __u32 target_idx; + __u32 nfc_protocol; +}; + +To establish a connection with one target, the user must create an +NFC_SOCKPROTO_RAW socket and call the 'connect' syscall with the sockaddr_nfc +struct correctly filled. All information comes from NFC_EVENT_TARGETS_FOUND +netlink event. As a target can support more than one NFC protocol, the user +must inform which protocol it wants to use. + +Internally, 'connect' will result in an activate_target call to the driver. +When the socket is closed, the target is deactivated. + +The data format exchanged through the sockets is NFC protocol dependent. For +instance, when communicating with MIFARE tags, the data exchanged are MIFARE +commands and their responses. + +The first received package is the response to the first sent package and so +on. In order to allow valid "empty" responses, every data received has a NULL +header of 1 byte. diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt index 80a7a3454902..57a24108b845 100644 --- a/Documentation/networking/stmmac.txt +++ b/Documentation/networking/stmmac.txt @@ -7,7 +7,7 @@ This is the driver for the MAC 10/100/1000 on-chip Ethernet controllers (Synopsys IP blocks); it has been fully tested on STLinux platforms. Currently this network device driver is for all STM embedded MAC/GMAC -(7xxx SoCs). Other platforms start using it i.e. ARM SPEAr. +(i.e. 7xxx/5xxx SoCs) and it's known working on other platforms i.e. ARM SPEAr. DWC Ether MAC 10/100/1000 Universal version 3.41a and DWC Ether MAC 10/100 Universal version 4.0 have been used for developing the first code @@ -71,7 +71,7 @@ Several performance tests on STM platforms showed this optimisation allows to sp the CPU while having the maximum throughput. 4.4) WOL -Wake up on Lan feature through Magic Frame is only supported for the GMAC +Wake up on Lan feature through Magic and Unicast frames are supported for the GMAC core. 4.5) DMA descriptors @@ -91,11 +91,15 @@ LRO is not supported. The driver is compatible with PAL to work with PHY and GPHY devices. 4.9) Platform information -Several information came from the platform; please refer to the -driver's Header file in include/linux directory. +Several driver's information can be passed through the platform +These are included in the include/linux/stmmac.h header file +and detailed below as well: -struct plat_stmmacenet_data { + struct plat_stmmacenet_data { int bus_id; + int phy_addr; + int interface; + struct stmmac_mdio_bus_data *mdio_bus_data; int pbl; int clk_csr; int has_gmac; @@ -103,67 +107,135 @@ struct plat_stmmacenet_data { int tx_coe; int bugged_jumbo; int pmt; - void (*fix_mac_speed)(void *priv, unsigned int speed); - void (*bus_setup)(unsigned long ioaddr); -#ifdef CONFIG_STM_DRIVERS - struct stm_pad_config *pad_config; -#endif - void *bsp_priv; -}; + int force_sf_dma_mode; + void (*fix_mac_speed)(void *priv, unsigned int speed); + void (*bus_setup)(void __iomem *ioaddr); + int (*init)(struct platform_device *pdev); + void (*exit)(struct platform_device *pdev); + void *bsp_priv; + }; Where: -- pbl (Programmable Burst Length) is maximum number of - beats to be transferred in one DMA transaction. - GMAC also enables the 4xPBL by default. -- fix_mac_speed and bus_setup are used to configure internal target - registers (on STM platforms); -- has_gmac: GMAC core is on board (get it at run-time in the next step); -- bus_id: bus identifier. -- tx_coe: core is able to perform the tx csum in HW. -- enh_desc: if sets the MAC will use the enhanced descriptor structure. -- clk_csr: CSR Clock range selection. -- bugged_jumbo: some HWs are not able to perform the csum in HW for - over-sized frames due to limited buffer sizes. Setting this - flag the csum will be done in SW on JUMBO frames. - -struct plat_stmmacphy_data { - int bus_id; - int phy_addr; - unsigned int phy_mask; - int interface; - int (*phy_reset)(void *priv); - void *priv; -}; + o bus_id: bus identifier. + o phy_addr: the physical address can be passed from the platform. + If it is set to -1 the driver will automatically + detect it at run-time by probing all the 32 addresses. + o interface: PHY device's interface. + o mdio_bus_data: specific platform fields for the MDIO bus. + o pbl: the Programmable Burst Length is maximum number of beats to + be transferred in one DMA transaction. + GMAC also enables the 4xPBL by default. + o clk_csr: CSR Clock range selection. + o has_gmac: uses the GMAC core. + o enh_desc: if sets the MAC will use the enhanced descriptor structure. + o tx_coe: core is able to perform the tx csum in HW. + o bugged_jumbo: some HWs are not able to perform the csum in HW for + over-sized frames due to limited buffer sizes. + Setting this flag the csum will be done in SW on + JUMBO frames. + o pmt: core has the embedded power module (optional). + o force_sf_dma_mode: force DMA to use the Store and Forward mode + instead of the Threshold. + o fix_mac_speed: this callback is used for modifying some syscfg registers + (on ST SoCs) according to the link speed negotiated by the + physical layer . + o bus_setup: perform HW setup of the bus. For example, on some ST platforms + this field is used to configure the AMBA bridge to generate more + efficient STBus traffic. + o init/exit: callbacks used for calling a custom initialisation; + this is sometime necessary on some platforms (e.g. ST boxes) + where the HW needs to have set some PIO lines or system cfg + registers. + o custom_cfg: this is a custom configuration that can be passed while + initialising the resources. + +The we have: + + struct stmmac_mdio_bus_data { + int bus_id; + int (*phy_reset)(void *priv); + unsigned int phy_mask; + int *irqs; + int probed_phy_irq; + }; Where: -- bus_id: bus identifier; -- phy_addr: physical address used for the attached phy device; - set it to -1 to get it at run-time; -- interface: physical MII interface mode; -- phy_reset: hook to reset HW function. - -SOURCES: -- Kconfig -- Makefile -- stmmac_main.c: main network device driver; -- stmmac_mdio.c: mdio functions; -- stmmac_ethtool.c: ethtool support; -- stmmac_timer.[ch]: timer code used for mitigating the driver dma interrupts - Only tested on ST40 platforms based. -- stmmac.h: private driver structure; -- common.h: common definitions and VFTs; -- descs.h: descriptor structure definitions; -- dwmac1000_core.c: GMAC core functions; -- dwmac1000_dma.c: dma functions for the GMAC chip; -- dwmac1000.h: specific header file for the GMAC; -- dwmac100_core: MAC 100 core and dma code; -- dwmac100_dma.c: dma funtions for the MAC chip; -- dwmac1000.h: specific header file for the MAC; -- dwmac_lib.c: generic DMA functions shared among chips -- enh_desc.c: functions for handling enhanced descriptors -- norm_desc.c: functions for handling normal descriptors - -TODO: -- XGMAC controller is not supported. -- Review the timer optimisation code to use an embedded device that seems to be + o bus_id: bus identifier; + o phy_reset: hook to reset the phy device attached to the bus. + o phy_mask: phy mask passed when register the MDIO bus within the driver. + o irqs: list of IRQs, one per PHY. + o probed_phy_irq: if irqs is NULL, use this for probed PHY. + +Below an example how the structures above are using on ST platforms. + + static struct plat_stmmacenet_data stxYYY_ethernet_platform_data = { + .pbl = 32, + .has_gmac = 0, + .enh_desc = 0, + .fix_mac_speed = stxYYY_ethernet_fix_mac_speed, + | + |-> to write an internal syscfg + | on this platform when the + | link speed changes from 10 to + | 100 and viceversa + .init = &stmmac_claim_resource, + | + |-> On ST SoC this calls own "PAD" + | manager framework to claim + | all the resources necessary + | (GPIO ...). The .custom_cfg field + | is used to pass a custom config. +}; + +Below the usage of the stmmac_mdio_bus_data: on this SoC, in fact, +there are two MAC cores: one MAC is for MDIO Bus/PHY emulation +with fixed_link support. + +static struct stmmac_mdio_bus_data stmmac1_mdio_bus = { + .bus_id = 1, + | + |-> phy device on the bus_id 1 + .phy_reset = phy_reset; + | + |-> function to provide the phy_reset on this board + .phy_mask = 0, +}; + +static struct fixed_phy_status stmmac0_fixed_phy_status = { + .link = 1, + .speed = 100, + .duplex = 1, +}; + +During the board's device_init we can configure the first +MAC for fixed_link by calling: + fixed_phy_add(PHY_POLL, 1, &stmmac0_fixed_phy_status));) +and the second one, with a real PHY device attached to the bus, +by using the stmmac_mdio_bus_data structure (to provide the id, the +reset procedure etc). + +4.10) List of source files: + o Kconfig + o Makefile + o stmmac_main.c: main network device driver; + o stmmac_mdio.c: mdio functions; + o stmmac_ethtool.c: ethtool support; + o stmmac_timer.[ch]: timer code used for mitigating the driver dma interrupts + Only tested on ST40 platforms based. + o stmmac.h: private driver structure; + o common.h: common definitions and VFTs; + o descs.h: descriptor structure definitions; + o dwmac1000_core.c: GMAC core functions; + o dwmac1000_dma.c: dma functions for the GMAC chip; + o dwmac1000.h: specific header file for the GMAC; + o dwmac100_core: MAC 100 core and dma code; + o dwmac100_dma.c: dma funtions for the MAC chip; + o dwmac1000.h: specific header file for the MAC; + o dwmac_lib.c: generic DMA functions shared among chips + o enh_desc.c: functions for handling enhanced descriptors + o norm_desc.c: functions for handling normal descriptors + +5) TODO: + o XGMAC is not supported. + o Review the timer optimisation code to use an embedded device that will be available in new chip generations. diff --git a/MAINTAINERS b/MAINTAINERS index 789fed662140..81cf5fb615e5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4290,8 +4290,8 @@ S: Maintained F: drivers/usb/musb/ MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE) +M: Jon Mason <mason@myri.com> M: Andrew Gallatin <gallatin@myri.com> -M: Brice Goglin <brice@myri.com> L: netdev@vger.kernel.org W: http://www.myri.com/scs/download-Myri10GE.html S: Supported diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index 606a6f27ed6c..5f5d78308873 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -20,6 +20,7 @@ #include <linux/spi/spi.h> #include <linux/spi/flash.h> +#include <asm/io.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <mach/common.h> diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 1e0f809644bb..e00d61e2efbe 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -8,6 +8,7 @@ * is licensed "as is" without any warranty of any kind, whether express * or implied. */ +#include <linux/dma-mapping.h> #include <linux/init.h> #include <linux/clk.h> #include <linux/serial_8250.h> diff --git a/arch/arm/mach-davinci/pm.c b/arch/arm/mach-davinci/pm.c index 1bd73a04be20..04c49f7543ef 100644 --- a/arch/arm/mach-davinci/pm.c +++ b/arch/arm/mach-davinci/pm.c @@ -17,6 +17,7 @@ #include <asm/cacheflush.h> #include <asm/delay.h> +#include <asm/io.h> #include <mach/da8xx.h> #include <mach/sram.h> diff --git a/arch/arm/mach-imx/dma-v1.c b/arch/arm/mach-imx/dma-v1.c index 236f1495efad..f8aa5be0eb15 100644 --- a/arch/arm/mach-imx/dma-v1.c +++ b/arch/arm/mach-imx/dma-v1.c @@ -26,6 +26,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/interrupt.h> +#include <linux/err.h> #include <linux/errno.h> #include <linux/clk.h> #include <linux/scatterlist.h> diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c index 9b982449cb52..b5ecc26d08a4 100644 --- a/arch/arm/mach-imx/mach-mx31_3ds.c +++ b/arch/arm/mach-imx/mach-mx31_3ds.c @@ -13,6 +13,7 @@ */ #include <linux/delay.h> +#include <linux/dma-mapping.h> #include <linux/types.h> #include <linux/init.h> #include <linux/clk.h> diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c index 5c147fb66a01..a5b989728b9e 100644 --- a/arch/arm/mach-iop13xx/setup.c +++ b/arch/arm/mach-iop13xx/setup.c @@ -17,6 +17,7 @@ * */ +#include <linux/dma-mapping.h> #include <linux/serial_8250.h> #include <linux/io.h> #ifdef CONFIG_MTD_PHYSMAP diff --git a/arch/arm/mach-mxs/devices/platform-auart.c b/arch/arm/mach-mxs/devices/platform-auart.c index 796606cce0ce..27608f5d2ac8 100644 --- a/arch/arm/mach-mxs/devices/platform-auart.c +++ b/arch/arm/mach-mxs/devices/platform-auart.c @@ -6,6 +6,7 @@ * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. */ +#include <linux/dma-mapping.h> #include <asm/sizes.h> #include <mach/mx23.h> #include <mach/mx28.h> diff --git a/arch/arm/mach-mxs/devices/platform-dma.c b/arch/arm/mach-mxs/devices/platform-dma.c index 295c4424d5d9..6a0202b1016c 100644 --- a/arch/arm/mach-mxs/devices/platform-dma.c +++ b/arch/arm/mach-mxs/devices/platform-dma.c @@ -6,6 +6,7 @@ * Free Software Foundation. */ #include <linux/compiler.h> +#include <linux/dma-mapping.h> #include <linux/err.h> #include <linux/init.h> diff --git a/arch/arm/mach-mxs/devices/platform-fec.c b/arch/arm/mach-mxs/devices/platform-fec.c index 9859cf283335..ae96a4fd8f14 100644 --- a/arch/arm/mach-mxs/devices/platform-fec.c +++ b/arch/arm/mach-mxs/devices/platform-fec.c @@ -6,6 +6,7 @@ * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. */ +#include <linux/dma-mapping.h> #include <asm/sizes.h> #include <mach/mx28.h> #include <mach/devices-common.h> diff --git a/arch/arm/plat-mxc/devices/platform-fec.c b/arch/arm/plat-mxc/devices/platform-fec.c index ccc789e21daa..4fc6ffc2a13e 100644 --- a/arch/arm/plat-mxc/devices/platform-fec.c +++ b/arch/arm/plat-mxc/devices/platform-fec.c @@ -6,6 +6,7 @@ * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. */ +#include <linux/dma-mapping.h> #include <asm/sizes.h> #include <mach/hardware.h> #include <mach/devices-common.h> diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c index 59c33f6e401c..23ce08e6ffd2 100644 --- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c +++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c @@ -6,6 +6,7 @@ * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. */ +#include <linux/dma-mapping.h> #include <mach/hardware.h> #include <mach/devices-common.h> diff --git a/arch/arm/plat-mxc/devices/platform-imx-fb.c b/arch/arm/plat-mxc/devices/platform-imx-fb.c index 79a1cb18a5b0..2b0b5e0aa998 100644 --- a/arch/arm/plat-mxc/devices/platform-imx-fb.c +++ b/arch/arm/plat-mxc/devices/platform-imx-fb.c @@ -6,6 +6,7 @@ * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. */ +#include <linux/dma-mapping.h> #include <mach/hardware.h> #include <mach/devices-common.h> diff --git a/arch/arm/plat-mxc/devices/platform-ipu-core.c b/arch/arm/plat-mxc/devices/platform-ipu-core.c index edf65034aea5..79d340ae0af1 100644 --- a/arch/arm/plat-mxc/devices/platform-ipu-core.c +++ b/arch/arm/plat-mxc/devices/platform-ipu-core.c @@ -6,6 +6,7 @@ * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. */ +#include <linux/dma-mapping.h> #include <mach/hardware.h> #include <mach/devices-common.h> diff --git a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c index cc488f4b6204..e1763e03e7cb 100644 --- a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c +++ b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c @@ -6,6 +6,7 @@ * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. */ +#include <linux/dma-mapping.h> #include <mach/hardware.h> #include <mach/devices-common.h> diff --git a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c index 90d762f6f93b..540d3a7d92df 100644 --- a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c +++ b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c @@ -6,6 +6,7 @@ * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. */ +#include <linux/dma-mapping.h> #include <mach/hardware.h> #include <mach/devices-common.h> diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index c44886062f8e..685c78716d95 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h @@ -10,6 +10,7 @@ #define STE_DMA40_H #include <linux/dmaengine.h> +#include <linux/scatterlist.h> #include <linux/workqueue.h> #include <linux/interrupt.h> diff --git a/arch/m68k/emu/nfeth.c b/arch/m68k/emu/nfeth.c index 8b6e201b2c20..c5748bb4ea71 100644 --- a/arch/m68k/emu/nfeth.c +++ b/arch/m68k/emu/nfeth.c @@ -16,6 +16,7 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> +#include <linux/interrupt.h> #include <linux/module.h> #include <asm/natfeat.h> #include <asm/virtconvert.h> @@ -204,7 +205,6 @@ static struct net_device * __init nfeth_probe(int unit) dev->irq = nfEtherIRQ; dev->netdev_ops = &nfeth_netdev_ops; - dev->flags |= NETIF_F_NO_CSUM; memcpy(dev->dev_addr, mac, ETH_ALEN); priv = netdev_priv(dev); diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 2729c6663d8a..cdf7a0a64406 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -134,6 +134,7 @@ config PPC select GENERIC_IRQ_SHOW_LEVEL select HAVE_RCU_TABLE_FREE if SMP select HAVE_SYSCALL_TRACEPOINTS + select HAVE_BPF_JIT if (PPC64 && NET) config EARLY_PRINTK bool diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index b7212b619c52..b94740f36b1a 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -154,7 +154,8 @@ core-y += arch/powerpc/kernel/ \ arch/powerpc/lib/ \ arch/powerpc/sysdev/ \ arch/powerpc/platforms/ \ - arch/powerpc/math-emu/ + arch/powerpc/math-emu/ \ + arch/powerpc/net/ core-$(CONFIG_XMON) += arch/powerpc/xmon/ core-$(CONFIG_KVM) += arch/powerpc/kvm/ diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index e472659d906c..e980faae4225 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -71,6 +71,42 @@ #define PPC_INST_ERATSX 0x7c000126 #define PPC_INST_ERATSX_DOT 0x7c000127 +/* Misc instructions for BPF compiler */ +#define PPC_INST_LD 0xe8000000 +#define PPC_INST_LHZ 0xa0000000 +#define PPC_INST_LWZ 0x80000000 +#define PPC_INST_STD 0xf8000000 +#define PPC_INST_STDU 0xf8000001 +#define PPC_INST_MFLR 0x7c0802a6 +#define PPC_INST_MTLR 0x7c0803a6 +#define PPC_INST_CMPWI 0x2c000000 +#define PPC_INST_CMPDI 0x2c200000 +#define PPC_INST_CMPLW 0x7c000040 +#define PPC_INST_CMPLWI 0x28000000 +#define PPC_INST_ADDI 0x38000000 +#define PPC_INST_ADDIS 0x3c000000 +#define PPC_INST_ADD 0x7c000214 +#define PPC_INST_SUB 0x7c000050 +#define PPC_INST_BLR 0x4e800020 +#define PPC_INST_BLRL 0x4e800021 +#define PPC_INST_MULLW 0x7c0001d6 +#define PPC_INST_MULHWU 0x7c000016 +#define PPC_INST_MULLI 0x1c000000 +#define PPC_INST_DIVWU 0x7c0003d6 +#define PPC_INST_RLWINM 0x54000000 +#define PPC_INST_RLDICR 0x78000004 +#define PPC_INST_SLW 0x7c000030 +#define PPC_INST_SRW 0x7c000430 +#define PPC_INST_AND 0x7c000038 +#define PPC_INST_ANDDOT 0x7c000039 +#define PPC_INST_OR 0x7c000378 +#define PPC_INST_ANDI 0x70000000 +#define PPC_INST_ORI 0x60000000 +#define PPC_INST_ORIS 0x64000000 +#define PPC_INST_NEG 0x7c0000d0 +#define PPC_INST_BRANCH 0x48000000 +#define PPC_INST_BRANCH_COND 0x40800000 + /* macros to insert fields into opcodes */ #define __PPC_RA(a) (((a) & 0x1f) << 16) #define __PPC_RB(b) (((b) & 0x1f) << 11) @@ -83,6 +119,10 @@ #define __PPC_T_TLB(t) (((t) & 0x3) << 21) #define __PPC_WC(w) (((w) & 0x3) << 21) #define __PPC_WS(w) (((w) & 0x1f) << 11) +#define __PPC_SH(s) __PPC_WS(s) +#define __PPC_MB(s) (((s) & 0x1f) << 6) +#define __PPC_ME(s) (((s) & 0x1f) << 1) +#define __PPC_BI(s) (((s) & 0x1f) << 16) /* * Only use the larx hint bit on 64bit CPUs. e500v1/v2 based CPUs will treat a diff --git a/arch/powerpc/net/Makefile b/arch/powerpc/net/Makefile new file mode 100644 index 000000000000..266b3950c3ac --- /dev/null +++ b/arch/powerpc/net/Makefile @@ -0,0 +1,4 @@ +# +# Arch-specific network modules +# +obj-$(CONFIG_BPF_JIT) += bpf_jit_64.o bpf_jit_comp.o diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h new file mode 100644 index 000000000000..af1ab5e9a691 --- /dev/null +++ b/arch/powerpc/net/bpf_jit.h @@ -0,0 +1,227 @@ +/* bpf_jit.h: BPF JIT compiler for PPC64 + * + * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation + * + * 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; version 2 + * of the License. + */ +#ifndef _BPF_JIT_H +#define _BPF_JIT_H + +#define BPF_PPC_STACK_LOCALS 32 +#define BPF_PPC_STACK_BASIC (48+64) +#define BPF_PPC_STACK_SAVE (18*8) +#define BPF_PPC_STACKFRAME (BPF_PPC_STACK_BASIC+BPF_PPC_STACK_LOCALS+ \ + BPF_PPC_STACK_SAVE) +#define BPF_PPC_SLOWPATH_FRAME (48+64) + +/* + * Generated code register usage: + * + * As normal PPC C ABI (e.g. r1=sp, r2=TOC), with: + * + * skb r3 (Entry parameter) + * A register r4 + * X register r5 + * addr param r6 + * r7-r10 scratch + * skb->data r14 + * skb headlen r15 (skb->len - skb->data_len) + * m[0] r16 + * m[...] ... + * m[15] r31 + */ +#define r_skb 3 +#define r_ret 3 +#define r_A 4 +#define r_X 5 +#define r_addr 6 +#define r_scratch1 7 +#define r_D 14 +#define r_HL 15 +#define r_M 16 + +#ifndef __ASSEMBLY__ + +/* + * Assembly helpers from arch/powerpc/net/bpf_jit.S: + */ +extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[]; + +#define FUNCTION_DESCR_SIZE 24 + +/* + * 16-bit immediate helper macros: HA() is for use with sign-extending instrs + * (e.g. LD, ADDI). If the bottom 16 bits is "-ve", add another bit into the + * top half to negate the effect (i.e. 0xffff + 1 = 0x(1)0000). + */ +#define IMM_H(i) ((uintptr_t)(i)>>16) +#define IMM_HA(i) (((uintptr_t)(i)>>16) + \ + (((uintptr_t)(i) & 0x8000) >> 15)) +#define IMM_L(i) ((uintptr_t)(i) & 0xffff) + +#define PLANT_INSTR(d, idx, instr) \ + do { if (d) { (d)[idx] = instr; } idx++; } while (0) +#define EMIT(instr) PLANT_INSTR(image, ctx->idx, instr) + +#define PPC_NOP() EMIT(PPC_INST_NOP) +#define PPC_BLR() EMIT(PPC_INST_BLR) +#define PPC_BLRL() EMIT(PPC_INST_BLRL) +#define PPC_MTLR(r) EMIT(PPC_INST_MTLR | __PPC_RT(r)) +#define PPC_ADDI(d, a, i) EMIT(PPC_INST_ADDI | __PPC_RT(d) | \ + __PPC_RA(a) | IMM_L(i)) +#define PPC_MR(d, a) PPC_OR(d, a, a) +#define PPC_LI(r, i) PPC_ADDI(r, 0, i) +#define PPC_ADDIS(d, a, i) EMIT(PPC_INST_ADDIS | \ + __PPC_RS(d) | __PPC_RA(a) | IMM_L(i)) +#define PPC_LIS(r, i) PPC_ADDIS(r, 0, i) +#define PPC_STD(r, base, i) EMIT(PPC_INST_STD | __PPC_RS(r) | \ + __PPC_RA(base) | ((i) & 0xfffc)) + +#define PPC_LD(r, base, i) EMIT(PPC_INST_LD | __PPC_RT(r) | \ + __PPC_RA(base) | IMM_L(i)) +#define PPC_LWZ(r, base, i) EMIT(PPC_INST_LWZ | __PPC_RT(r) | \ + __PPC_RA(base) | IMM_L(i)) +#define PPC_LHZ(r, base, i) EMIT(PPC_INST_LHZ | __PPC_RT(r) | \ + __PPC_RA(base) | IMM_L(i)) +/* Convenience helpers for the above with 'far' offsets: */ +#define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i); \ + else { PPC_ADDIS(r, base, IMM_HA(i)); \ + PPC_LD(r, r, IMM_L(i)); } } while(0) + +#define PPC_LWZ_OFFS(r, base, i) do { if ((i) < 32768) PPC_LWZ(r, base, i); \ + else { PPC_ADDIS(r, base, IMM_HA(i)); \ + PPC_LWZ(r, r, IMM_L(i)); } } while(0) + +#define PPC_LHZ_OFFS(r, base, i) do { if ((i) < 32768) PPC_LHZ(r, base, i); \ + else { PPC_ADDIS(r, base, IMM_HA(i)); \ + PPC_LHZ(r, r, IMM_L(i)); } } while(0) + +#define PPC_CMPWI(a, i) EMIT(PPC_INST_CMPWI | __PPC_RA(a) | IMM_L(i)) +#define PPC_CMPDI(a, i) EMIT(PPC_INST_CMPDI | __PPC_RA(a) | IMM_L(i)) +#define PPC_CMPLWI(a, i) EMIT(PPC_INST_CMPLWI | __PPC_RA(a) | IMM_L(i)) +#define PPC_CMPLW(a, b) EMIT(PPC_INST_CMPLW | __PPC_RA(a) | __PPC_RB(b)) + +#define PPC_SUB(d, a, b) EMIT(PPC_INST_SUB | __PPC_RT(d) | \ + __PPC_RB(a) | __PPC_RA(b)) +#define PPC_ADD(d, a, b) EMIT(PPC_INST_ADD | __PPC_RT(d) | \ + __PPC_RA(a) | __PPC_RB(b)) +#define PPC_MUL(d, a, b) EMIT(PPC_INST_MULLW | __PPC_RT(d) | \ + __PPC_RA(a) | __PPC_RB(b)) +#define PPC_MULHWU(d, a, b) EMIT(PPC_INST_MULHWU | __PPC_RT(d) | \ + __PPC_RA(a) | __PPC_RB(b)) +#define PPC_MULI(d, a, i) EMIT(PPC_INST_MULLI | __PPC_RT(d) | \ + __PPC_RA(a) | IMM_L(i)) +#define PPC_DIVWU(d, a, b) EMIT(PPC_INST_DIVWU | __PPC_RT(d) | \ + __PPC_RA(a) | __PPC_RB(b)) +#define PPC_AND(d, a, b) EMIT(PPC_INST_AND | __PPC_RA(d) | \ + __PPC_RS(a) | __PPC_RB(b)) +#define PPC_ANDI(d, a, i) EMIT(PPC_INST_ANDI | __PPC_RA(d) | \ + __PPC_RS(a) | IMM_L(i)) +#define PPC_AND_DOT(d, a, b) EMIT(PPC_INST_ANDDOT | __PPC_RA(d) | \ + __PPC_RS(a) | __PPC_RB(b)) +#define PPC_OR(d, a, b) EMIT(PPC_INST_OR | __PPC_RA(d) | \ + __PPC_RS(a) | __PPC_RB(b)) +#define PPC_ORI(d, a, i) EMIT(PPC_INST_ORI | __PPC_RA(d) | \ + __PPC_RS(a) | IMM_L(i)) +#define PPC_ORIS(d, a, i) EMIT(PPC_INST_ORIS | __PPC_RA(d) | \ + __PPC_RS(a) | IMM_L(i)) +#define PPC_SLW(d, a, s) EMIT(PPC_INST_SLW | __PPC_RA(d) | \ + __PPC_RS(a) | __PPC_RB(s)) +#define PPC_SRW(d, a, s) EMIT(PPC_INST_SRW | __PPC_RA(d) | \ + __PPC_RS(a) | __PPC_RB(s)) +/* slwi = rlwinm Rx, Ry, n, 0, 31-n */ +#define PPC_SLWI(d, a, i) EMIT(PPC_INST_RLWINM | __PPC_RA(d) | \ + __PPC_RS(a) | __PPC_SH(i) | \ + __PPC_MB(0) | __PPC_ME(31-(i))) +/* srwi = rlwinm Rx, Ry, 32-n, n, 31 */ +#define PPC_SRWI(d, a, i) EMIT(PPC_INST_RLWINM | __PPC_RA(d) | \ + __PPC_RS(a) | __PPC_SH(32-(i)) | \ + __PPC_MB(i) | __PPC_ME(31)) +/* sldi = rldicr Rx, Ry, n, 63-n */ +#define PPC_SLDI(d, a, i) EMIT(PPC_INST_RLDICR | __PPC_RA(d) | \ + __PPC_RS(a) | __PPC_SH(i) | \ + __PPC_MB(63-(i)) | (((i) & 0x20) >> 4)) +#define PPC_NEG(d, a) EMIT(PPC_INST_NEG | __PPC_RT(d) | __PPC_RA(a)) + +/* Long jump; (unconditional 'branch') */ +#define PPC_JMP(dest) EMIT(PPC_INST_BRANCH | \ + (((dest) - (ctx->idx * 4)) & 0x03fffffc)) +/* "cond" here covers BO:BI fields. */ +#define PPC_BCC_SHORT(cond, dest) EMIT(PPC_INST_BRANCH_COND | \ + (((cond) & 0x3ff) << 16) | \ + (((dest) - (ctx->idx * 4)) & \ + 0xfffc)) +#define PPC_LI32(d, i) do { PPC_LI(d, IMM_L(i)); \ + if ((u32)(uintptr_t)(i) >= 32768) { \ + PPC_ADDIS(d, d, IMM_HA(i)); \ + } } while(0) +#define PPC_LI64(d, i) do { \ + if (!((uintptr_t)(i) & 0xffffffff00000000ULL)) \ + PPC_LI32(d, i); \ + else { \ + PPC_LIS(d, ((uintptr_t)(i) >> 48)); \ + if ((uintptr_t)(i) & 0x0000ffff00000000ULL) \ + PPC_ORI(d, d, \ + ((uintptr_t)(i) >> 32) & 0xffff); \ + PPC_SLDI(d, d, 32); \ + if ((uintptr_t)(i) & 0x00000000ffff0000ULL) \ + PPC_ORIS(d, d, \ + ((uintptr_t)(i) >> 16) & 0xffff); \ + if ((uintptr_t)(i) & 0x000000000000ffffULL) \ + PPC_ORI(d, d, (uintptr_t)(i) & 0xffff); \ + } } while (0); + +static inline bool is_nearbranch(int offset) +{ + return (offset < 32768) && (offset >= -32768); +} + +/* + * The fly in the ointment of code size changing from pass to pass is + * avoided by padding the short branch case with a NOP. If code size differs + * with different branch reaches we will have the issue of code moving from + * one pass to the next and will need a few passes to converge on a stable + * state. + */ +#define PPC_BCC(cond, dest) do { \ + if (is_nearbranch((dest) - (ctx->idx * 4))) { \ + PPC_BCC_SHORT(cond, dest); \ + PPC_NOP(); \ + } else { \ + /* Flip the 'T or F' bit to invert comparison */ \ + PPC_BCC_SHORT(cond ^ COND_CMP_TRUE, (ctx->idx+2)*4); \ + PPC_JMP(dest); \ + } } while(0) + +/* To create a branch condition, select a bit of cr0... */ +#define CR0_LT 0 +#define CR0_GT 1 +#define CR0_EQ 2 +/* ...and modify BO[3] */ +#define COND_CMP_TRUE 0x100 +#define COND_CMP_FALSE 0x000 +/* Together, they make all required comparisons: */ +#define COND_GT (CR0_GT | COND_CMP_TRUE) +#define COND_GE (CR0_LT | COND_CMP_FALSE) +#define COND_EQ (CR0_EQ | COND_CMP_TRUE) +#define COND_NE (CR0_EQ | COND_CMP_FALSE) +#define COND_LT (CR0_LT | COND_CMP_TRUE) + +#define SEEN_DATAREF 0x10000 /* might call external helpers */ +#define SEEN_XREG 0x20000 /* X reg is used */ +#define SEEN_MEM 0x40000 /* SEEN_MEM+(1<<n) = use mem[n] for temporary + * storage */ +#define SEEN_MEM_MSK 0x0ffff + +struct codegen_context { + unsigned int seen; + unsigned int idx; + int pc_ret0; /* bpf index of first RET #0 instruction (if any) */ +}; + +#endif + +#endif diff --git a/arch/powerpc/net/bpf_jit_64.S b/arch/powerpc/net/bpf_jit_64.S new file mode 100644 index 000000000000..ff4506e85cce --- /dev/null +++ b/arch/powerpc/net/bpf_jit_64.S @@ -0,0 +1,138 @@ +/* bpf_jit.S: Packet/header access helper functions + * for PPC64 BPF compiler. + * + * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation + * + * 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; version 2 + * of the License. + */ + +#include <asm/ppc_asm.h> +#include "bpf_jit.h" + +/* + * All of these routines are called directly from generated code, + * whose register usage is: + * + * r3 skb + * r4,r5 A,X + * r6 *** address parameter to helper *** + * r7-r10 scratch + * r14 skb->data + * r15 skb headlen + * r16-31 M[] + */ + +/* + * To consider: These helpers are so small it could be better to just + * generate them inline. Inline code can do the simple headlen check + * then branch directly to slow_path_XXX if required. (In fact, could + * load a spare GPR with the address of slow_path_generic and pass size + * as an argument, making the call site a mtlr, li and bllr.) + * + * Technically, the "is addr < 0" check is unnecessary & slowing down + * the ABS path, as it's statically checked on generation. + */ + .globl sk_load_word +sk_load_word: + cmpdi r_addr, 0 + blt bpf_error + /* Are we accessing past headlen? */ + subi r_scratch1, r_HL, 4 + cmpd r_scratch1, r_addr + blt bpf_slow_path_word + /* Nope, just hitting the header. cr0 here is eq or gt! */ + lwzx r_A, r_D, r_addr + /* When big endian we don't need to byteswap. */ + blr /* Return success, cr0 != LT */ + + .globl sk_load_half +sk_load_half: + cmpdi r_addr, 0 + blt bpf_error + subi r_scratch1, r_HL, 2 + cmpd r_scratch1, r_addr + blt bpf_slow_path_half + lhzx r_A, r_D, r_addr + blr + + .globl sk_load_byte +sk_load_byte: + cmpdi r_addr, 0 + blt bpf_error + cmpd r_HL, r_addr + ble bpf_slow_path_byte + lbzx r_A, r_D, r_addr + blr + +/* + * BPF_S_LDX_B_MSH: ldxb 4*([offset]&0xf) + * r_addr is the offset value, already known positive + */ + .globl sk_load_byte_msh +sk_load_byte_msh: + cmpd r_HL, r_addr + ble bpf_slow_path_byte_msh + lbzx r_X, r_D, r_addr + rlwinm r_X, r_X, 2, 32-4-2, 31-2 + blr + +bpf_error: + /* Entered with cr0 = lt */ + li r3, 0 + /* Generated code will 'blt epilogue', returning 0. */ + blr + +/* Call out to skb_copy_bits: + * We'll need to back up our volatile regs first; we have + * local variable space at r1+(BPF_PPC_STACK_BASIC). + * Allocate a new stack frame here to remain ABI-compliant in + * stashing LR. + */ +#define bpf_slow_path_common(SIZE) \ + mflr r0; \ + std r0, 16(r1); \ + /* R3 goes in parameter space of caller's frame */ \ + std r_skb, (BPF_PPC_STACKFRAME+48)(r1); \ + std r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \ + std r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \ + addi r5, r1, BPF_PPC_STACK_BASIC+(2*8); \ + stdu r1, -BPF_PPC_SLOWPATH_FRAME(r1); \ + /* R3 = r_skb, as passed */ \ + mr r4, r_addr; \ + li r6, SIZE; \ + bl skb_copy_bits; \ + /* R3 = 0 on success */ \ + addi r1, r1, BPF_PPC_SLOWPATH_FRAME; \ + ld r0, 16(r1); \ + ld r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \ + ld r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \ + mtlr r0; \ + cmpdi r3, 0; \ + blt bpf_error; /* cr0 = LT */ \ + ld r_skb, (BPF_PPC_STACKFRAME+48)(r1); \ + /* Great success! */ + +bpf_slow_path_word: + bpf_slow_path_common(4) + /* Data value is on stack, and cr0 != LT */ + lwz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1) + blr + +bpf_slow_path_half: + bpf_slow_path_common(2) + lhz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1) + blr + +bpf_slow_path_byte: + bpf_slow_path_common(1) + lbz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1) + blr + +bpf_slow_path_byte_msh: + bpf_slow_path_common(1) + lbz r_X, BPF_PPC_STACK_BASIC+(2*8)(r1) + rlwinm r_X, r_X, 2, 32-4-2, 31-2 + blr diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c new file mode 100644 index 000000000000..73619d3aeb6c --- /dev/null +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -0,0 +1,694 @@ +/* bpf_jit_comp.c: BPF JIT compiler for PPC64 + * + * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation + * + * Based on the x86 BPF compiler, by Eric Dumazet (eric.dumazet@gmail.com) + * + * 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; version 2 + * of the License. + */ +#include <linux/moduleloader.h> +#include <asm/cacheflush.h> +#include <linux/netdevice.h> +#include <linux/filter.h> +#include "bpf_jit.h" + +#ifndef __BIG_ENDIAN +/* There are endianness assumptions herein. */ +#error "Little-endian PPC not supported in BPF compiler" +#endif + +int bpf_jit_enable __read_mostly; + + +static inline void bpf_flush_icache(void *start, void *end) +{ + smp_wmb(); + flush_icache_range((unsigned long)start, (unsigned long)end); +} + +static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image, + struct codegen_context *ctx) +{ + int i; + const struct sock_filter *filter = fp->insns; + + if (ctx->seen & (SEEN_MEM | SEEN_DATAREF)) { + /* Make stackframe */ + if (ctx->seen & SEEN_DATAREF) { + /* If we call any helpers (for loads), save LR */ + EMIT(PPC_INST_MFLR | __PPC_RT(0)); + PPC_STD(0, 1, 16); + + /* Back up non-volatile regs. */ + PPC_STD(r_D, 1, -(8*(32-r_D))); + PPC_STD(r_HL, 1, -(8*(32-r_HL))); + } + if (ctx->seen & SEEN_MEM) { + /* + * Conditionally save regs r15-r31 as some will be used + * for M[] data. + */ + for (i = r_M; i < (r_M+16); i++) { + if (ctx->seen & (1 << (i-r_M))) + PPC_STD(i, 1, -(8*(32-i))); + } + } + EMIT(PPC_INST_STDU | __PPC_RS(1) | __PPC_RA(1) | + (-BPF_PPC_STACKFRAME & 0xfffc)); + } + + if (ctx->seen & SEEN_DATAREF) { + /* + * If this filter needs to access skb data, + * prepare r_D and r_HL: + * r_HL = skb->len - skb->data_len + * r_D = skb->data + */ + PPC_LWZ_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff, + data_len)); + PPC_LWZ_OFFS(r_HL, r_skb, offsetof(struct sk_buff, len)); + PPC_SUB(r_HL, r_HL, r_scratch1); + PPC_LD_OFFS(r_D, r_skb, offsetof(struct sk_buff, data)); + } + + if (ctx->seen & SEEN_XREG) { + /* + * TODO: Could also detect whether first instr. sets X and + * avoid this (as below, with A). + */ + PPC_LI(r_X, 0); + } + + switch (filter[0].code) { + case BPF_S_RET_K: + case BPF_S_LD_W_LEN: + case BPF_S_ANC_PROTOCOL: + case BPF_S_ANC_IFINDEX: + case BPF_S_ANC_MARK: + case BPF_S_ANC_RXHASH: + case BPF_S_ANC_CPU: + case BPF_S_ANC_QUEUE: + case BPF_S_LD_W_ABS: + case BPF_S_LD_H_ABS: + case BPF_S_LD_B_ABS: + /* first instruction sets A register (or is RET 'constant') */ + break; + default: + /* make sure we dont leak kernel information to user */ + PPC_LI(r_A, 0); + } +} + +static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx) +{ + int i; + + if (ctx->seen & (SEEN_MEM | SEEN_DATAREF)) { + PPC_ADDI(1, 1, BPF_PPC_STACKFRAME); + if (ctx->seen & SEEN_DATAREF) { + PPC_LD(0, 1, 16); + PPC_MTLR(0); + PPC_LD(r_D, 1, -(8*(32-r_D))); + PPC_LD(r_HL, 1, -(8*(32-r_HL))); + } + if (ctx->seen & SEEN_MEM) { + /* Restore any saved non-vol registers */ + for (i = r_M; i < (r_M+16); i++) { + if (ctx->seen & (1 << (i-r_M))) + PPC_LD(i, 1, -(8*(32-i))); + } + } + } + /* The RETs have left a return value in R3. */ + + PPC_BLR(); +} + +/* Assemble the body code between the prologue & epilogue. */ +static int bpf_jit_build_body(struct sk_filter *fp, u32 *image, + struct codegen_context *ctx, + unsigned int *addrs) +{ + const struct sock_filter *filter = fp->insns; + int flen = fp->len; + u8 *func; + unsigned int true_cond; + int i; + + /* Start of epilogue code */ + unsigned int exit_addr = addrs[flen]; + + for (i = 0; i < flen; i++) { + unsigned int K = filter[i].k; + + /* + * addrs[] maps a BPF bytecode address into a real offset from + * the start of the body code. + */ + addrs[i] = ctx->idx * 4; + + switch (filter[i].code) { + /*** ALU ops ***/ + case BPF_S_ALU_ADD_X: /* A += X; */ + ctx->seen |= SEEN_XREG; + PPC_ADD(r_A, r_A, r_X); + break; + case BPF_S_ALU_ADD_K: /* A += K; */ + if (!K) + break; + PPC_ADDI(r_A, r_A, IMM_L(K)); + if (K >= 32768) + PPC_ADDIS(r_A, r_A, IMM_HA(K)); + break; + case BPF_S_ALU_SUB_X: /* A -= X; */ + ctx->seen |= SEEN_XREG; + PPC_SUB(r_A, r_A, r_X); + break; + case BPF_S_ALU_SUB_K: /* A -= K */ + if (!K) + break; + PPC_ADDI(r_A, r_A, IMM_L(-K)); + if (K >= 32768) + PPC_ADDIS(r_A, r_A, IMM_HA(-K)); + break; + case BPF_S_ALU_MUL_X: /* A *= X; */ + ctx->seen |= SEEN_XREG; + PPC_MUL(r_A, r_A, r_X); + break; + case BPF_S_ALU_MUL_K: /* A *= K */ + if (K < 32768) + PPC_MULI(r_A, r_A, K); + else { + PPC_LI32(r_scratch1, K); + PPC_MUL(r_A, r_A, r_scratch1); + } + break; + case BPF_S_ALU_DIV_X: /* A /= X; */ + ctx->seen |= SEEN_XREG; + PPC_CMPWI(r_X, 0); + if (ctx->pc_ret0 != -1) { + PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]); + } else { + /* + * Exit, returning 0; first pass hits here + * (longer worst-case code size). + */ + PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12); + PPC_LI(r_ret, 0); + PPC_JMP(exit_addr); + } + PPC_DIVWU(r_A, r_A, r_X); + break; + case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */ + PPC_LI32(r_scratch1, K); + /* Top 32 bits of 64bit result -> A */ + PPC_MULHWU(r_A, r_A, r_scratch1); + break; + case BPF_S_ALU_AND_X: + ctx->seen |= SEEN_XREG; + PPC_AND(r_A, r_A, r_X); + break; + case BPF_S_ALU_AND_K: + if (!IMM_H(K)) + PPC_ANDI(r_A, r_A, K); + else { + PPC_LI32(r_scratch1, K); + PPC_AND(r_A, r_A, r_scratch1); + } + break; + case BPF_S_ALU_OR_X: + ctx->seen |= SEEN_XREG; + PPC_OR(r_A, r_A, r_X); + break; + case BPF_S_ALU_OR_K: + if (IMM_L(K)) + PPC_ORI(r_A, r_A, IMM_L(K)); + if (K >= 65536) + PPC_ORIS(r_A, r_A, IMM_H(K)); + break; + case BPF_S_ALU_LSH_X: /* A <<= X; */ + ctx->seen |= SEEN_XREG; + PPC_SLW(r_A, r_A, r_X); + break; + case BPF_S_ALU_LSH_K: + if (K == 0) + break; + else + PPC_SLWI(r_A, r_A, K); + break; + case BPF_S_ALU_RSH_X: /* A >>= X; */ + ctx->seen |= SEEN_XREG; + PPC_SRW(r_A, r_A, r_X); + break; + case BPF_S_ALU_RSH_K: /* A >>= K; */ + if (K == 0) + break; + else + PPC_SRWI(r_A, r_A, K); + break; + case BPF_S_ALU_NEG: + PPC_NEG(r_A, r_A); + break; + case BPF_S_RET_K: + PPC_LI32(r_ret, K); + if (!K) { + if (ctx->pc_ret0 == -1) + ctx->pc_ret0 = i; + } + /* + * If this isn't the very last instruction, branch to + * the epilogue if we've stuff to clean up. Otherwise, + * if there's nothing to tidy, just return. If we /are/ + * the last instruction, we're about to fall through to + * the epilogue to return. + */ + if (i != flen - 1) { + /* + * Note: 'seen' is properly valid only on pass + * #2. Both parts of this conditional are the + * same instruction size though, meaning the + * first pass will still correctly determine the + * code size/addresses. + */ + if (ctx->seen) + PPC_JMP(exit_addr); + else + PPC_BLR(); + } + break; + case BPF_S_RET_A: + PPC_MR(r_ret, r_A); + if (i != flen - 1) { + if (ctx->seen) + PPC_JMP(exit_addr); + else + PPC_BLR(); + } + break; + case BPF_S_MISC_TAX: /* X = A */ + PPC_MR(r_X, r_A); + break; + case BPF_S_MISC_TXA: /* A = X */ + ctx->seen |= SEEN_XREG; + PPC_MR(r_A, r_X); + break; + + /*** Constant loads/M[] access ***/ + case BPF_S_LD_IMM: /* A = K */ + PPC_LI32(r_A, K); + break; + case BPF_S_LDX_IMM: /* X = K */ + PPC_LI32(r_X, K); + break; + case BPF_S_LD_MEM: /* A = mem[K] */ + PPC_MR(r_A, r_M + (K & 0xf)); + ctx->seen |= SEEN_MEM | (1<<(K & 0xf)); + break; + case BPF_S_LDX_MEM: /* X = mem[K] */ + PPC_MR(r_X, r_M + (K & 0xf)); + ctx->seen |= SEEN_MEM | (1<<(K & 0xf)); + break; + case BPF_S_ST: /* mem[K] = A */ + PPC_MR(r_M + (K & 0xf), r_A); + ctx->seen |= SEEN_MEM | (1<<(K & 0xf)); + break; + case BPF_S_STX: /* mem[K] = X */ + PPC_MR(r_M + (K & 0xf), r_X); + ctx->seen |= SEEN_XREG | SEEN_MEM | (1<<(K & 0xf)); + break; + case BPF_S_LD_W_LEN: /* A = skb->len; */ + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4); + PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff, len)); + break; + case BPF_S_LDX_W_LEN: /* X = skb->len; */ + PPC_LWZ_OFFS(r_X, r_skb, offsetof(struct sk_buff, len)); + break; + + /*** Ancillary info loads ***/ + + /* None of the BPF_S_ANC* codes appear to be passed by + * sk_chk_filter(). The interpreter and the x86 BPF + * compiler implement them so we do too -- they may be + * planted in future. + */ + case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */ + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, + protocol) != 2); + PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff, + protocol)); + /* ntohs is a NOP with BE loads. */ + break; + case BPF_S_ANC_IFINDEX: + PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff, + dev)); + PPC_CMPDI(r_scratch1, 0); + if (ctx->pc_ret0 != -1) { + PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]); + } else { + /* Exit, returning 0; first pass hits here. */ + PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12); + PPC_LI(r_ret, 0); + PPC_JMP(exit_addr); + } + BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, + ifindex) != 4); + PPC_LWZ_OFFS(r_A, r_scratch1, + offsetof(struct net_device, ifindex)); + break; + case BPF_S_ANC_MARK: + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4); + PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff, + mark)); + break; + case BPF_S_ANC_RXHASH: + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4); + PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff, + rxhash)); + break; + case BPF_S_ANC_QUEUE: + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, + queue_mapping) != 2); + PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff, + queue_mapping)); + break; + case BPF_S_ANC_CPU: +#ifdef CONFIG_SMP + /* + * PACA ptr is r13: + * raw_smp_processor_id() = local_paca->paca_index + */ + BUILD_BUG_ON(FIELD_SIZEOF(struct paca_struct, + paca_index) != 2); + PPC_LHZ_OFFS(r_A, 13, + offsetof(struct paca_struct, paca_index)); +#else + PPC_LI(r_A, 0); +#endif + break; + + /*** Absolute loads from packet header/data ***/ + case BPF_S_LD_W_ABS: + func = sk_load_word; + goto common_load; + case BPF_S_LD_H_ABS: + func = sk_load_half; + goto common_load; + case BPF_S_LD_B_ABS: + func = sk_load_byte; + common_load: + /* + * Load from [K]. Reference with the (negative) + * SKF_NET_OFF/SKF_LL_OFF offsets is unsupported. + */ + ctx->seen |= SEEN_DATAREF; + if ((int)K < 0) + return -ENOTSUPP; + PPC_LI64(r_scratch1, func); + PPC_MTLR(r_scratch1); + PPC_LI32(r_addr, K); + PPC_BLRL(); + /* + * Helper returns 'lt' condition on error, and an + * appropriate return value in r3 + */ + PPC_BCC(COND_LT, exit_addr); + break; + + /*** Indirect loads from packet header/data ***/ + case BPF_S_LD_W_IND: + func = sk_load_word; + goto common_load_ind; + case BPF_S_LD_H_IND: + func = sk_load_half; + goto common_load_ind; + case BPF_S_LD_B_IND: + func = sk_load_byte; + common_load_ind: + /* + * Load from [X + K]. Negative offsets are tested for + * in the helper functions, and result in a 'ret 0'. + */ + ctx->seen |= SEEN_DATAREF | SEEN_XREG; + PPC_LI64(r_scratch1, func); + PPC_MTLR(r_scratch1); + PPC_ADDI(r_addr, r_X, IMM_L(K)); + if (K >= 32768) + PPC_ADDIS(r_addr, r_addr, IMM_HA(K)); + PPC_BLRL(); + /* If error, cr0.LT set */ + PPC_BCC(COND_LT, exit_addr); + break; + + case BPF_S_LDX_B_MSH: + /* + * x86 version drops packet (RET 0) when K<0, whereas + * interpreter does allow K<0 (__load_pointer, special + * ancillary data). common_load returns ENOTSUPP if K<0, + * so we fall back to interpreter & filter works. + */ + func = sk_load_byte_msh; + goto common_load; + break; + + /*** Jump and branches ***/ + case BPF_S_JMP_JA: + if (K != 0) + PPC_JMP(addrs[i + 1 + K]); + break; + + case BPF_S_JMP_JGT_K: + case BPF_S_JMP_JGT_X: + true_cond = COND_GT; + goto cond_branch; + case BPF_S_JMP_JGE_K: + case BPF_S_JMP_JGE_X: + true_cond = COND_GE; + goto cond_branch; + case BPF_S_JMP_JEQ_K: + case BPF_S_JMP_JEQ_X: + true_cond = COND_EQ; + goto cond_branch; + case BPF_S_JMP_JSET_K: + case BPF_S_JMP_JSET_X: + true_cond = COND_NE; + /* Fall through */ + cond_branch: + /* same targets, can avoid doing the test :) */ + if (filter[i].jt == filter[i].jf) { + if (filter[i].jt > 0) + PPC_JMP(addrs[i + 1 + filter[i].jt]); + break; + } + + switch (filter[i].code) { + case BPF_S_JMP_JGT_X: + case BPF_S_JMP_JGE_X: + case BPF_S_JMP_JEQ_X: + ctx->seen |= SEEN_XREG; + PPC_CMPLW(r_A, r_X); + break; + case BPF_S_JMP_JSET_X: + ctx->seen |= SEEN_XREG; + PPC_AND_DOT(r_scratch1, r_A, r_X); + break; + case BPF_S_JMP_JEQ_K: + case BPF_S_JMP_JGT_K: + case BPF_S_JMP_JGE_K: + if (K < 32768) + PPC_CMPLWI(r_A, K); + else { + PPC_LI32(r_scratch1, K); + PPC_CMPLW(r_A, r_scratch1); + } + break; + case BPF_S_JMP_JSET_K: + if (K < 32768) + /* PPC_ANDI is /only/ dot-form */ + PPC_ANDI(r_scratch1, r_A, K); + else { + PPC_LI32(r_scratch1, K); + PPC_AND_DOT(r_scratch1, r_A, + r_scratch1); + } + break; + } + /* Sometimes branches are constructed "backward", with + * the false path being the branch and true path being + * a fallthrough to the next instruction. + */ + if (filter[i].jt == 0) + /* Swap the sense of the branch */ + PPC_BCC(true_cond ^ COND_CMP_TRUE, + addrs[i + 1 + filter[i].jf]); + else { + PPC_BCC(true_cond, addrs[i + 1 + filter[i].jt]); + if (filter[i].jf != 0) + PPC_JMP(addrs[i + 1 + filter[i].jf]); + } + break; + default: + /* The filter contains something cruel & unusual. + * We don't handle it, but also there shouldn't be + * anything missing from our list. + */ + if (printk_ratelimit()) + pr_err("BPF filter opcode %04x (@%d) unsupported\n", + filter[i].code, i); + return -ENOTSUPP; + } + + } + /* Set end-of-body-code address for exit. */ + addrs[i] = ctx->idx * 4; + + return 0; +} + +void bpf_jit_compile(struct sk_filter *fp) +{ + unsigned int proglen; + unsigned int alloclen; + u32 *image = NULL; + u32 *code_base; + unsigned int *addrs; + struct codegen_context cgctx; + int pass; + int flen = fp->len; + + if (!bpf_jit_enable) + return; + + addrs = kzalloc((flen+1) * sizeof(*addrs), GFP_KERNEL); + if (addrs == NULL) + return; + + /* + * There are multiple assembly passes as the generated code will change + * size as it settles down, figuring out the max branch offsets/exit + * paths required. + * + * The range of standard conditional branches is +/- 32Kbytes. Since + * BPF_MAXINSNS = 4096, we can only jump from (worst case) start to + * finish with 8 bytes/instruction. Not feasible, so long jumps are + * used, distinct from short branches. + * + * Current: + * + * For now, both branch types assemble to 2 words (short branches padded + * with a NOP); this is less efficient, but assembly will always complete + * after exactly 3 passes: + * + * First pass: No code buffer; Program is "faux-generated" -- no code + * emitted but maximum size of output determined (and addrs[] filled + * in). Also, we note whether we use M[], whether we use skb data, etc. + * All generation choices assumed to be 'worst-case', e.g. branches all + * far (2 instructions), return path code reduction not available, etc. + * + * Second pass: Code buffer allocated with size determined previously. + * Prologue generated to support features we have seen used. Exit paths + * determined and addrs[] is filled in again, as code may be slightly + * smaller as a result. + * + * Third pass: Code generated 'for real', and branch destinations + * determined from now-accurate addrs[] map. + * + * Ideal: + * + * If we optimise this, near branches will be shorter. On the + * first assembly pass, we should err on the side of caution and + * generate the biggest code. On subsequent passes, branches will be + * generated short or long and code size will reduce. With smaller + * code, more branches may fall into the short category, and code will + * reduce more. + * + * Finally, if we see one pass generate code the same size as the + * previous pass we have converged and should now generate code for + * real. Allocating at the end will also save the memory that would + * otherwise be wasted by the (small) current code shrinkage. + * Preferably, we should do a small number of passes (e.g. 5) and if we + * haven't converged by then, get impatient and force code to generate + * as-is, even if the odd branch would be left long. The chances of a + * long jump are tiny with all but the most enormous of BPF filter + * inputs, so we should usually converge on the third pass. + */ + + cgctx.idx = 0; + cgctx.seen = 0; + cgctx.pc_ret0 = -1; + /* Scouting faux-generate pass 0 */ + if (bpf_jit_build_body(fp, 0, &cgctx, addrs)) + /* We hit something illegal or unsupported. */ + goto out; + + /* + * Pretend to build prologue, given the features we've seen. This will + * update ctgtx.idx as it pretends to output instructions, then we can + * calculate total size from idx. + */ + bpf_jit_build_prologue(fp, 0, &cgctx); + bpf_jit_build_epilogue(0, &cgctx); + + proglen = cgctx.idx * 4; + alloclen = proglen + FUNCTION_DESCR_SIZE; + image = module_alloc(max_t(unsigned int, alloclen, + sizeof(struct work_struct))); + if (!image) + goto out; + + code_base = image + (FUNCTION_DESCR_SIZE/4); + + /* Code generation passes 1-2 */ + for (pass = 1; pass < 3; pass++) { + /* Now build the prologue, body code & epilogue for real. */ + cgctx.idx = 0; + bpf_jit_build_prologue(fp, code_base, &cgctx); + bpf_jit_build_body(fp, code_base, &cgctx, addrs); + bpf_jit_build_epilogue(code_base, &cgctx); + + if (bpf_jit_enable > 1) + pr_info("Pass %d: shrink = %d, seen = 0x%x\n", pass, + proglen - (cgctx.idx * 4), cgctx.seen); + } + + if (bpf_jit_enable > 1) + pr_info("flen=%d proglen=%u pass=%d image=%p\n", + flen, proglen, pass, image); + + if (image) { + if (bpf_jit_enable > 1) + print_hex_dump(KERN_ERR, "JIT code: ", + DUMP_PREFIX_ADDRESS, + 16, 1, code_base, + proglen, false); + + bpf_flush_icache(code_base, code_base + (proglen/4)); + /* Function descriptor nastiness: Address + TOC */ + ((u64 *)image)[0] = (u64)code_base; + ((u64 *)image)[1] = local_paca->kernel_toc; + fp->bpf_func = (void *)image; + } +out: + kfree(addrs); + return; +} + +static void jit_free_defer(struct work_struct *arg) +{ + module_free(NULL, arg); +} + +/* run from softirq, we must use a work_struct to call + * module_free() from process context + */ +void bpf_jit_free(struct sk_filter *fp) +{ + if (fp->bpf_func != sk_run_filter) { + struct work_struct *work = (struct work_struct *)fp->bpf_func; + + INIT_WORK(work, jit_free_defer); + schedule_work(work); + } +} diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index 30ac65df7d4e..e07a2fc876b9 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c @@ -36,6 +36,7 @@ #include <asm/bootparam.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> +#include <asm/swiotlb.h> #include <asm/fixmap.h> #include <asm/proto.h> #include <asm/setup.h> diff --git a/crypto/async_tx/raid6test.c b/crypto/async_tx/raid6test.c index c1321935ebcc..c88ff9e3fd30 100644 --- a/crypto/async_tx/raid6test.c +++ b/crypto/async_tx/raid6test.c @@ -21,6 +21,7 @@ */ #include <linux/async_tx.h> #include <linux/gfp.h> +#include <linux/mm.h> #include <linux/random.h> #undef pr diff --git a/drivers/Kconfig b/drivers/Kconfig index 3bb154d8c8cc..258473ce8d01 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -94,8 +94,6 @@ source "drivers/memstick/Kconfig" source "drivers/leds/Kconfig" -source "drivers/nfc/Kconfig" - source "drivers/accessibility/Kconfig" source "drivers/infiniband/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 09f3232bcdcd..1bc896571a3a 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -122,3 +122,4 @@ obj-y += ieee802154/ obj-y += clk/ obj-$(CONFIG_HWSPINLOCK) += hwspinlock/ +obj-$(CONFIG_NFC) += nfc/ diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index a5fcb1eb862f..bb3b016b6ce8 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -813,7 +813,7 @@ static void fill_rx_pool (amb_dev * dev, unsigned char pool, return; } -// top up all RX pools (can also be called as a bottom half) +// top up all RX pools static void fill_rx_pools (amb_dev * dev) { unsigned char pool; @@ -872,11 +872,7 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) { ++irq_work; if (irq_work) { -#ifdef FILL_RX_POOLS_IN_BH - schedule_work (&dev->bh); -#else fill_rx_pools (dev); -#endif PRINTD (DBG_IRQ, "work done: %u", irq_work); } else { @@ -2154,11 +2150,6 @@ static void setup_dev(amb_dev *dev, struct pci_dev *pci_dev) dev->tx_avail = ATM_OC3_PCR; dev->rx_avail = ATM_OC3_PCR; -#ifdef FILL_RX_POOLS_IN_BH - // initialise bottom half - INIT_WORK(&dev->bh, (void (*)(void *)) fill_rx_pools, dev); -#endif - // semaphore for txer/rxer modifications - we cannot use a // spinlock as the critical region needs to switch processes mutex_init(&dev->vcc_sf); diff --git a/drivers/atm/ambassador.h b/drivers/atm/ambassador.h index bd1c46a7ef49..aa9710556bd6 100644 --- a/drivers/atm/ambassador.h +++ b/drivers/atm/ambassador.h @@ -630,10 +630,6 @@ struct amb_dev { u32 iobase; u32 * membase; -#ifdef FILL_RX_POOLS_IN_BH - struct work_struct bh; -#endif - amb_cq cq; amb_txq txq; amb_rxq rxq[NUM_RX_POOLS]; diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h index e4c9525e60b3..493a6932507e 100644 --- a/drivers/atm/eni.h +++ b/drivers/atm/eni.h @@ -8,6 +8,7 @@ #include <linux/atm.h> #include <linux/atmdev.h> +#include <linux/interrupt.h> #include <linux/sonet.h> #include <linux/skbuff.h> #include <linux/time.h> diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index ef7a658312a6..7c7b571647f9 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -44,6 +44,7 @@ #include <linux/ioport.h> /* for request_region */ #include <linux/uio.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/capability.h> #include <linux/bitops.h> #include <linux/slab.h> diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index d58e3fcb9db3..287506183893 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -38,6 +38,7 @@ #include <linux/delay.h> #include <linux/uio.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/wait.h> #include <linux/slab.h> diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 1f8d724a18bf..be0dbfeb541c 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -37,6 +37,7 @@ #include <linux/atm.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/bitops.h> #include <linux/wait.h> #include <linux/jiffies.h> diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index dee4f01a64d8..957106f636ea 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -53,6 +53,7 @@ #include <linux/delay.h> #include <linux/uio.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/wait.h> #include <linux/slab.h> #include <asm/system.h> diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 4e8ba56f75d3..e828c5487493 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -1947,7 +1947,6 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai) { struct pci_dev *pci = lanai->pci; int result; - u16 w; if (pci_enable_device(pci) != 0) { printk(KERN_ERR DEV_LABEL "(itf %d): can't enable " @@ -1965,13 +1964,7 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai) "(itf %d): No suitable DMA available.\n", lanai->number); return -EBUSY; } - result = pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &w); - if (result != PCIBIOS_SUCCESSFUL) { - printk(KERN_ERR DEV_LABEL "(itf %d): can't read " - "PCI_SUBSYSTEM_ID: %d\n", lanai->number, result); - return -EINVAL; - } - result = check_board_id_and_rev("PCI", w, NULL); + result = check_board_id_and_rev("PCI", pci->subsystem_device, NULL); if (result != 0) return result; /* Set latency timer to zero as per lanai docs */ diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c index 624917902b65..7f8c5132ff32 100644 --- a/drivers/atm/zatm.c +++ b/drivers/atm/zatm.c @@ -16,6 +16,7 @@ #include <linux/delay.h> #include <linux/uio.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/dma-mapping.h> #include <linux/atm_zatm.h> #include <linux/capability.h> diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig index 353781b5b78b..ae0a02e1b808 100644 --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig @@ -13,6 +13,11 @@ config BCMA Bus driver for Broadcom specific Advanced Microcontroller Bus Architecture. +# Support for Block-I/O. SELECT this from the driver that needs it. +config BCMA_BLOCKIO + bool + depends on BCMA + config BCMA_HOST_PCI_POSSIBLE bool depends on BCMA && PCI = y @@ -22,6 +27,12 @@ config BCMA_HOST_PCI bool "Support for BCMA on PCI-host bus" depends on BCMA_HOST_PCI_POSSIBLE +config BCMA_DRIVER_PCI_HOSTMODE + bool "Driver for PCI core working in hostmode" + depends on BCMA && MIPS + help + PCI core hostmode operation (external PCI bus). + config BCMA_DEBUG bool "BCMA debugging" depends on BCMA diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile index 0d56245bcb79..a2161cceafb9 100644 --- a/drivers/bcma/Makefile +++ b/drivers/bcma/Makefile @@ -1,6 +1,7 @@ -bcma-y += main.o scan.o core.o +bcma-y += main.o scan.o core.o sprom.o bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o bcma-y += driver_pci.o +bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o obj-$(CONFIG_BCMA) += bcma.o diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 2f72e9c585fd..e02ff21835c9 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -13,16 +13,23 @@ struct bcma_bus; /* main.c */ -extern int bcma_bus_register(struct bcma_bus *bus); -extern void bcma_bus_unregister(struct bcma_bus *bus); +int bcma_bus_register(struct bcma_bus *bus); +void bcma_bus_unregister(struct bcma_bus *bus); /* scan.c */ int bcma_bus_scan(struct bcma_bus *bus); +/* sprom.c */ +int bcma_sprom_get(struct bcma_bus *bus); + #ifdef CONFIG_BCMA_HOST_PCI /* host_pci.c */ extern int __init bcma_host_pci_init(void); extern void __exit bcma_host_pci_exit(void); #endif /* CONFIG_BCMA_HOST_PCI */ +#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE +void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); +#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ + #endif diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c index ced379f7b371..1ec7d4528dd0 100644 --- a/drivers/bcma/core.c +++ b/drivers/bcma/core.c @@ -19,7 +19,7 @@ bool bcma_core_is_enabled(struct bcma_device *core) } EXPORT_SYMBOL_GPL(bcma_core_is_enabled); -static void bcma_core_disable(struct bcma_device *core, u32 flags) +void bcma_core_disable(struct bcma_device *core, u32 flags) { if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET) return; @@ -31,6 +31,7 @@ static void bcma_core_disable(struct bcma_device *core, u32 flags) bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); udelay(1); } +EXPORT_SYMBOL_GPL(bcma_core_disable); int bcma_core_enable(struct bcma_device *core, u32 flags) { diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index f44177a644c7..dd5846bef029 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -53,6 +53,7 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) max_msk = 0xFFFF; break; case 43224: + case 43225: break; default: pr_err("PMU resource config unknown for device 0x%04X\n", @@ -74,6 +75,7 @@ void bcma_pmu_swreg_init(struct bcma_drv_cc *cc) case 0x4313: case 0x4331: case 43224: + case 43225: break; default: pr_err("PMU switch/regulators init unknown for device " @@ -96,11 +98,13 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc) if (bus->chipinfo.rev == 0) { pr_err("Workarounds for 43224 rev 0 not fully " "implemented\n"); - bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); + bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0); } else { bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); } break; + case 43225: + break; default: pr_err("Workarounds unknown for device 0x%04X\n", bus->chipinfo.id); diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index e757e4e3c7e2..dc6f34ac96a0 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c @@ -157,7 +157,67 @@ static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) * Init. **************************************************/ -void bcma_core_pci_init(struct bcma_drv_pci *pc) +static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) { bcma_pcicore_serdes_workaround(pc); } + +static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) +{ + struct bcma_bus *bus = pc->core->bus; + u16 chipid_top; + + chipid_top = (bus->chipinfo.id & 0xFF00); + if (chipid_top != 0x4700 && + chipid_top != 0x5300) + return false; + + if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI) + return false; + +#if 0 + /* TODO: on BCMA we use address from EROM instead of magic formula */ + u32 tmp; + return !mips_busprobe32(tmp, (bus->mmio + + (pc->core->core_index * BCMA_CORE_SIZE))); +#endif + + return true; +} + +void bcma_core_pci_init(struct bcma_drv_pci *pc) +{ + if (bcma_core_pci_is_in_hostmode(pc)) { +#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE + bcma_core_pci_hostmode_init(pc); +#else + pr_err("Driver compiled without support for hostmode PCI\n"); +#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ + } else { + bcma_core_pci_clientmode_init(pc); + } +} + +int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, + bool enable) +{ + struct pci_dev *pdev = pc->core->bus->host_pci; + u32 coremask, tmp; + int err; + + err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); + if (err) + goto out; + + coremask = BIT(core->core_index) << 8; + if (enable) + tmp |= coremask; + else + tmp &= ~coremask; + + err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp); + +out: + return err; +} +EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl); diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c new file mode 100644 index 000000000000..eb332b75ce83 --- /dev/null +++ b/drivers/bcma/driver_pci_host.c @@ -0,0 +1,14 @@ +/* + * Broadcom specific AMBA + * PCI Core in hostmode + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "bcma_private.h" +#include <linux/bcma/bcma.h> + +void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) +{ + pr_err("No support for PCI core in hostmode yet\n"); +} diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 471a04013fe0..ac4bc626c149 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -65,6 +65,54 @@ static void bcma_host_pci_write32(struct bcma_device *core, u16 offset, iowrite32(value, core->bus->mmio + offset); } +#ifdef CONFIG_BCMA_BLOCKIO +void bcma_host_pci_block_read(struct bcma_device *core, void *buffer, + size_t count, u16 offset, u8 reg_width) +{ + void __iomem *addr = core->bus->mmio + offset; + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); + switch (reg_width) { + case sizeof(u8): + ioread8_rep(addr, buffer, count); + break; + case sizeof(u16): + WARN_ON(count & 1); + ioread16_rep(addr, buffer, count >> 1); + break; + case sizeof(u32): + WARN_ON(count & 3); + ioread32_rep(addr, buffer, count >> 2); + break; + default: + WARN_ON(1); + } +} + +void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer, + size_t count, u16 offset, u8 reg_width) +{ + void __iomem *addr = core->bus->mmio + offset; + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); + switch (reg_width) { + case sizeof(u8): + iowrite8_rep(addr, buffer, count); + break; + case sizeof(u16): + WARN_ON(count & 1); + iowrite16_rep(addr, buffer, count >> 1); + break; + case sizeof(u32): + WARN_ON(count & 3); + iowrite32_rep(addr, buffer, count >> 2); + break; + default: + WARN_ON(1); + } +} +#endif + static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset) { if (core->bus->mapped_core != core) @@ -87,6 +135,10 @@ const struct bcma_host_ops bcma_host_pci_ops = { .write8 = bcma_host_pci_write8, .write16 = bcma_host_pci_write16, .write32 = bcma_host_pci_write32, +#ifdef CONFIG_BCMA_BLOCKIO + .block_read = bcma_host_pci_block_read, + .block_write = bcma_host_pci_block_write, +#endif .aread32 = bcma_host_pci_aread32, .awrite32 = bcma_host_pci_awrite32, }; @@ -175,6 +227,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, { 0, }, }; diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index be52344ed19d..873e2e4ac55f 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -7,6 +7,7 @@ #include "bcma_private.h" #include <linux/bcma/bcma.h> +#include <linux/slab.h> MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); MODULE_LICENSE("GPL"); @@ -89,6 +90,8 @@ static int bcma_register_cores(struct bcma_bus *bus) switch (bus->hosttype) { case BCMA_HOSTTYPE_PCI: core->dev.parent = &bus->host_pci->dev; + core->dma_dev = &bus->host_pci->dev; + core->irq = bus->host_pci->irq; break; case BCMA_HOSTTYPE_NONE: case BCMA_HOSTTYPE_SDIO: @@ -144,6 +147,15 @@ int bcma_bus_register(struct bcma_bus *bus) bcma_core_pci_init(&bus->drv_pci); } + /* Try to get SPROM */ + err = bcma_sprom_get(bus); + if (err == -ENOENT) { + pr_err("No SPROM available\n"); + } else if (err) { + pr_err("Failed to get SPROM: %d\n", err); + return -ENOENT; + } + /* Register found cores */ bcma_register_cores(bus); @@ -151,13 +163,11 @@ int bcma_bus_register(struct bcma_bus *bus) return 0; } -EXPORT_SYMBOL_GPL(bcma_bus_register); void bcma_bus_unregister(struct bcma_bus *bus) { bcma_unregister_cores(bus); } -EXPORT_SYMBOL_GPL(bcma_bus_unregister); int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) { diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c new file mode 100644 index 000000000000..8e8d5cf32e12 --- /dev/null +++ b/drivers/bcma/sprom.c @@ -0,0 +1,165 @@ +/* + * Broadcom specific AMBA + * SPROM reading + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "bcma_private.h" + +#include <linux/bcma/bcma.h> +#include <linux/bcma/bcma_regs.h> +#include <linux/pci.h> +#include <linux/io.h> +#include <linux/dma-mapping.h> +#include <linux/slab.h> + +#define SPOFF(offset) ((offset) / sizeof(u16)) + +/************************************************** + * R/W ops. + **************************************************/ + +static void bcma_sprom_read(struct bcma_bus *bus, u16 *sprom) +{ + int i; + for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++) + sprom[i] = bcma_read16(bus->drv_cc.core, + BCMA_CC_SPROM + (i * 2)); +} + +/************************************************** + * Validation. + **************************************************/ + +static inline u8 bcma_crc8(u8 crc, u8 data) +{ + /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */ + static const u8 t[] = { + 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, + 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, + 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, + 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, + 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, + 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, + 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, + 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, + 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, + 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, + 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, + 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, + 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, + 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, + 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, + 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, + 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, + 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, + 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, + 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, + 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, + 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, + 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, + 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, + 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, + 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, + 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, + 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, + 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, + 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, + 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, + 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F, + }; + return t[crc ^ data]; +} + +static u8 bcma_sprom_crc(const u16 *sprom) +{ + int word; + u8 crc = 0xFF; + + for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 1; word++) { + crc = bcma_crc8(crc, sprom[word] & 0x00FF); + crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8); + } + crc = bcma_crc8(crc, sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & 0x00FF); + crc ^= 0xFF; + + return crc; +} + +static int bcma_sprom_check_crc(const u16 *sprom) +{ + u8 crc; + u8 expected_crc; + u16 tmp; + + crc = bcma_sprom_crc(sprom); + tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_CRC; + expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT; + if (crc != expected_crc) + return -EPROTO; + + return 0; +} + +static int bcma_sprom_valid(const u16 *sprom) +{ + u16 revision; + int err; + + err = bcma_sprom_check_crc(sprom); + if (err) + return err; + + revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV; + if (revision != 8) { + pr_err("Unsupported SPROM revision: %d\n", revision); + return -ENOENT; + } + + return 0; +} + +/************************************************** + * SPROM extraction. + **************************************************/ + +static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) +{ + u16 v; + int i; + + for (i = 0; i < 3; i++) { + v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; + *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); + } +} + +int bcma_sprom_get(struct bcma_bus *bus) +{ + u16 *sprom; + int err = 0; + + if (!bus->drv_cc.core) + return -EOPNOTSUPP; + + if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) + return -ENOENT; + + sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), + GFP_KERNEL); + if (!sprom) + return -ENOMEM; + + bcma_sprom_read(bus, sprom); + + err = bcma_sprom_valid(sprom); + if (err) + goto out; + + bcma_sprom_extract_r8(bus, sprom); + +out: + kfree(sprom); + return err; +} diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 6bacef368fab..a5854735bb2e 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -375,6 +375,11 @@ static int ath3k_probe(struct usb_interface *intf, /* load patch and sysconfig files for AR3012 */ if (id->driver_info & BTUSB_ATH3012) { + + /* New firmware with patch and sysconfig files already loaded */ + if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x0001) + return -ENODEV; + ret = ath3k_load_patch(udev); if (ret < 0) { BT_ERR("Loading patch file failed"); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index c2de8951e3fb..91d13a9e8c65 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -54,6 +54,7 @@ static struct usb_driver btusb_driver; #define BTUSB_BCM92035 0x10 #define BTUSB_BROKEN_ISOC 0x20 #define BTUSB_WRONG_SCO_MTU 0x40 +#define BTUSB_ATH3012 0x80 static struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ @@ -110,7 +111,7 @@ static struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, /* Atheros 3012 with sflash firmware */ - { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, @@ -914,6 +915,15 @@ static int btusb_probe(struct usb_interface *intf, if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER) return -ENODEV; + if (id->driver_info & BTUSB_ATH3012) { + struct usb_device *udev = interface_to_usbdev(intf); + + /* Old firmware would otherwise let ath3k driver load + * patch and sysconfig files */ + if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001) + return -ENODEV; + } + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; diff --git a/drivers/char/random.c b/drivers/char/random.c index d4ddeba56682..729281961f22 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1523,6 +1523,21 @@ __u32 secure_ip_id(__be32 daddr) return half_md4_transform(hash, keyptr->secret); } +__u32 secure_ipv6_id(const __be32 daddr[4]) +{ + const struct keydata *keyptr; + __u32 hash[4]; + + keyptr = get_keyptr(); + + hash[0] = (__force __u32)daddr[0]; + hash[1] = (__force __u32)daddr[1]; + hash[2] = (__force __u32)daddr[2]; + hash[3] = (__force __u32)daddr[3]; + + return half_md4_transform(hash, keyptr->secret); +} + #ifdef CONFIG_INET __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index af8c0b5ed70f..a92d95eac86b 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/kernel.h> /* printk() */ #include <linux/fs.h> /* everything... */ +#include <linux/scatterlist.h> #include <linux/slab.h> /* kmalloc() */ #include <linux/dmaengine.h> #include <linux/platform_device.h> diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 8bcb15fb959d..48694c34d96b 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -45,6 +45,7 @@ * See Documentation/dmaengine.txt for more details */ +#include <linux/dma-mapping.h> #include <linux/init.h> #include <linux/module.h> #include <linux/mm.h> diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index b4f5c32b6a47..765f5ff22304 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -8,6 +8,7 @@ * published by the Free Software Foundation. */ #include <linux/delay.h> +#include <linux/dma-mapping.h> #include <linux/dmaengine.h> #include <linux/init.h> #include <linux/kthread.h> diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index c1a125e7d1df..fd7d2b308cf2 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ +#include <linux/dma-mapping.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/err.h> diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 8f222d4db7de..29d1addbe0cf 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -6,6 +6,7 @@ * License terms: GNU General Public License (GPL) version 2 */ +#include <linux/dma-mapping.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/dmaengine.h> diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index b9762d07198d..eced1c25bf58 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -261,16 +261,16 @@ static int fwnet_header_rebuild(struct sk_buff *skb) } static int fwnet_header_cache(const struct neighbour *neigh, - struct hh_cache *hh) + struct hh_cache *hh, __be16 type) { struct net_device *net; struct fwnet_header *h; - if (hh->hh_type == cpu_to_be16(ETH_P_802_3)) + if (type == cpu_to_be16(ETH_P_802_3)) return -1; net = neigh->dev; h = (struct fwnet_header *)((u8 *)hh->hh_data + 16 - sizeof(*h)); - h->h_proto = hh->hh_type; + h->h_proto = type; memcpy(h->h_dest, neigh->ha, net->addr_len); hh->hh_len = FWNET_HLEN; diff --git a/drivers/ieee802154/Makefile b/drivers/ieee802154/Makefile index 68999137dedf..800a3894af0d 100644 --- a/drivers/ieee802154/Makefile +++ b/drivers/ieee802154/Makefile @@ -1,3 +1 @@ obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o - -ccflags-y := -DDEBUG -DCONFIG_FFD diff --git a/drivers/ieee802154/fakehard.c b/drivers/ieee802154/fakehard.c index a5a49a1baae7..eb0e2ccc79ae 100644 --- a/drivers/ieee802154/fakehard.c +++ b/drivers/ieee802154/fakehard.c @@ -370,8 +370,6 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev) return -ENOMEM; } - phy->dev.platform_data = dev; - memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef", dev->addr_len); memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 8e21d457b899..236ad9a89c0a 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -215,7 +215,7 @@ static int addr4_resolve(struct sockaddr_in *src_in, neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev); if (!neigh || !(neigh->nud_state & NUD_VALID)) { - neigh_event_send(rt->dst.neighbour, NULL); + neigh_event_send(dst_get_neighbour(&rt->dst), NULL); ret = -ENODATA; if (neigh) goto release; @@ -273,9 +273,10 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, goto put; } - neigh = dst->neighbour; + neigh = dst_get_neighbour(dst); if (!neigh || !(neigh->nud_state & NUD_VALID)) { - neigh_event_send(dst->neighbour, NULL); + if (neigh) + neigh_event_send(neigh, NULL); ret = -ENODATA; goto put; } diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c index 4a5abaf0a25c..9227f4acd79c 100644 --- a/drivers/infiniband/core/netlink.c +++ b/drivers/infiniband/core/netlink.c @@ -148,7 +148,7 @@ static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return -EINVAL; return netlink_dump_start(nls, skb, nlh, client->cb_table[op].dump, - NULL); + NULL, 0); } } diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c index 0cfc455630d0..444470a28de2 100644 --- a/drivers/infiniband/hw/amso1100/c2.c +++ b/drivers/infiniband/hw/amso1100/c2.c @@ -36,6 +36,7 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/inetdevice.h> +#include <linux/interrupt.h> #include <linux/delay.h> #include <linux/ethtool.h> #include <linux/mii.h> diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index 0a5008fbebac..17bf9d95463c 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -1328,6 +1328,7 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) struct iwch_ep *child_ep, *parent_ep = ctx; struct cpl_pass_accept_req *req = cplhdr(skb); unsigned int hwtid = GET_TID(req); + struct neighbour *neigh; struct dst_entry *dst; struct l2t_entry *l2t; struct rtable *rt; @@ -1364,7 +1365,8 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) goto reject; } dst = &rt->dst; - l2t = t3_l2t_get(tdev, dst->neighbour, dst->neighbour->dev); + neigh = dst_get_neighbour(dst); + l2t = t3_l2t_get(tdev, neigh, neigh->dev); if (!l2t) { printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", __func__); @@ -1874,10 +1876,11 @@ static int is_loopback_dst(struct iw_cm_id *cm_id) int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) { - int err = 0; struct iwch_dev *h = to_iwch_dev(cm_id->device); + struct neighbour *neigh; struct iwch_ep *ep; struct rtable *rt; + int err = 0; if (is_loopback_dst(cm_id)) { err = -ENOSYS; @@ -1933,9 +1936,10 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) } ep->dst = &rt->dst; + neigh = dst_get_neighbour(ep->dst); + /* get a l2t entry */ - ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst->neighbour, - ep->dst->neighbour->dev); + ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev); if (!ep->l2t) { printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); err = -ENOMEM; diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 31fb44085c9b..77f769d9227d 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -1325,6 +1325,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) unsigned int stid = GET_POPEN_TID(ntohl(req->tos_stid)); struct tid_info *t = dev->rdev.lldi.tids; unsigned int hwtid = GET_TID(req); + struct neighbour *neigh; struct dst_entry *dst; struct l2t_entry *l2t; struct rtable *rt; @@ -1357,11 +1358,11 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) goto reject; } dst = &rt->dst; - if (dst->neighbour->dev->flags & IFF_LOOPBACK) { + neigh = dst_get_neighbour(dst); + if (neigh->dev->flags & IFF_LOOPBACK) { pdev = ip_dev_find(&init_net, peer_ip); BUG_ON(!pdev); - l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour, - pdev, 0); + l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, pdev, 0); mtu = pdev->mtu; tx_chan = cxgb4_port_chan(pdev); smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1; @@ -1372,17 +1373,16 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) rss_qid = dev->rdev.lldi.rxq_ids[cxgb4_port_idx(pdev) * step]; dev_put(pdev); } else { - l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour, - dst->neighbour->dev, 0); + l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, neigh->dev, 0); mtu = dst_mtu(dst); - tx_chan = cxgb4_port_chan(dst->neighbour->dev); - smac_idx = (cxgb4_port_viid(dst->neighbour->dev) & 0x7F) << 1; + tx_chan = cxgb4_port_chan(neigh->dev); + smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1; step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan; - txq_idx = cxgb4_port_idx(dst->neighbour->dev) * step; - ctrlq_idx = cxgb4_port_idx(dst->neighbour->dev); + txq_idx = cxgb4_port_idx(neigh->dev) * step; + ctrlq_idx = cxgb4_port_idx(neigh->dev); step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan; rss_qid = dev->rdev.lldi.rxq_ids[ - cxgb4_port_idx(dst->neighbour->dev) * step]; + cxgb4_port_idx(neigh->dev) * step]; } if (!l2t) { printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", @@ -1847,6 +1847,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) struct c4iw_ep *ep; struct rtable *rt; struct net_device *pdev; + struct neighbour *neigh; int step; if ((conn_param->ord > c4iw_max_read_depth) || @@ -1908,14 +1909,15 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) } ep->dst = &rt->dst; + neigh = dst_get_neighbour(ep->dst); + /* get a l2t entry */ - if (ep->dst->neighbour->dev->flags & IFF_LOOPBACK) { + if (neigh->dev->flags & IFF_LOOPBACK) { PDBG("%s LOOPBACK\n", __func__); pdev = ip_dev_find(&init_net, cm_id->remote_addr.sin_addr.s_addr); ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t, - ep->dst->neighbour, - pdev, 0); + neigh, pdev, 0); ep->mtu = pdev->mtu; ep->tx_chan = cxgb4_port_chan(pdev); ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1; @@ -1930,20 +1932,18 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) dev_put(pdev); } else { ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t, - ep->dst->neighbour, - ep->dst->neighbour->dev, 0); + neigh, neigh->dev, 0); ep->mtu = dst_mtu(ep->dst); - ep->tx_chan = cxgb4_port_chan(ep->dst->neighbour->dev); - ep->smac_idx = (cxgb4_port_viid(ep->dst->neighbour->dev) & - 0x7F) << 1; + ep->tx_chan = cxgb4_port_chan(neigh->dev); + ep->smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1; step = ep->com.dev->rdev.lldi.ntxq / ep->com.dev->rdev.lldi.nchan; - ep->txq_idx = cxgb4_port_idx(ep->dst->neighbour->dev) * step; - ep->ctrlq_idx = cxgb4_port_idx(ep->dst->neighbour->dev); + ep->txq_idx = cxgb4_port_idx(neigh->dev) * step; + ep->ctrlq_idx = cxgb4_port_idx(neigh->dev); step = ep->com.dev->rdev.lldi.nrxq / ep->com.dev->rdev.lldi.nchan; ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[ - cxgb4_port_idx(ep->dst->neighbour->dev) * step]; + cxgb4_port_idx(neigh->dev) * step]; } if (!ep->l2t) { printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index e74cdf9ef471..73bc18465c9c 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1151,7 +1151,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi } if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) - neigh_event_send(rt->dst.neighbour, NULL); + neigh_event_send(dst_get_neighbour(&rt->dst), NULL); ip_rt_put(rt); return rc; diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 96fa9a4cafdf..be36cbeae630 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -2917,24 +2917,19 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) goto skip_rx_indicate0; - if ((cqe_misc & NES_NIC_CQE_TAG_VALID) && - (nesvnic->vlan_grp != NULL)) { + if (cqe_misc & NES_NIC_CQE_TAG_VALID) { vlan_tag = (u16)(le32_to_cpu( cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX]) >> 16); nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n", nesvnic->netdev->name, vlan_tag); - if (nes_use_lro) - lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb, - nesvnic->vlan_grp, vlan_tag, NULL); - else - nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag); - } else { - if (nes_use_lro) - lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL); - else - nes_netif_rx(rx_skb); + + __vlan_hwaccel_put_tag(rx_skb, vlan_tag); } + if (nes_use_lro) + lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL); + else + netif_receive_skb(rx_skb); skip_rx_indicate0: ; diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index 91594116f947..c3241479ec0e 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h @@ -1211,7 +1211,6 @@ struct nes_vnic { /* void *mem; */ struct nes_device *nesdev; struct net_device *netdev; - struct vlan_group *vlan_grp; atomic_t rx_skbs_needed; atomic_t rx_skb_timer_running; int budget; @@ -1357,7 +1356,4 @@ struct nes_terminate_hdr { #define NES_LINK_RECHECK_DELAY msecs_to_jiffies(50) #define NES_LINK_RECHECK_MAX 60 -#define nes_vlan_rx vlan_hwaccel_receive_skb -#define nes_netif_rx netif_receive_skb - #endif /* __NES_HW_H */ diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index d3a1c41cfd27..9d7ffebff213 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -1584,23 +1584,19 @@ static const struct ethtool_ops nes_ethtool_ops = { .set_pauseparam = nes_netdev_set_pauseparam, }; - -static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) +static void nes_vlan_mode(struct net_device *netdev, struct nes_device *nesdev, u32 features) { - struct nes_vnic *nesvnic = netdev_priv(netdev); - struct nes_device *nesdev = nesvnic->nesdev; struct nes_adapter *nesadapter = nesdev->nesadapter; u32 u32temp; unsigned long flags; spin_lock_irqsave(&nesadapter->phy_lock, flags); - nesvnic->vlan_grp = grp; nes_debug(NES_DBG_NETDEV, "%s: %s\n", __func__, netdev->name); /* Enable/Disable VLAN Stripping */ u32temp = nes_read_indexed(nesdev, NES_IDX_PCIX_DIAG); - if (grp) + if (features & NETIF_F_HW_VLAN_RX) u32temp &= 0xfdffffff; else u32temp |= 0x02000000; @@ -1609,17 +1605,44 @@ static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_g spin_unlock_irqrestore(&nesadapter->phy_lock, flags); } +static u32 nes_fix_features(struct net_device *netdev, u32 features) +{ + /* + * Since there is no support for separate rx/tx vlan accel + * enable/disable make sure tx flag is always in same state as rx. + */ + if (features & NETIF_F_HW_VLAN_RX) + features |= NETIF_F_HW_VLAN_TX; + else + features &= ~NETIF_F_HW_VLAN_TX; + + return features; +} + +static int nes_set_features(struct net_device *netdev, u32 features) +{ + struct nes_vnic *nesvnic = netdev_priv(netdev); + struct nes_device *nesdev = nesvnic->nesdev; + u32 changed = netdev->features ^ features; + + if (changed & NETIF_F_HW_VLAN_RX) + nes_vlan_mode(netdev, nesdev, features); + + return 0; +} + static const struct net_device_ops nes_netdev_ops = { - .ndo_open = nes_netdev_open, + .ndo_open = nes_netdev_open, .ndo_stop = nes_netdev_stop, - .ndo_start_xmit = nes_netdev_start_xmit, + .ndo_start_xmit = nes_netdev_start_xmit, .ndo_get_stats = nes_netdev_get_stats, - .ndo_tx_timeout = nes_netdev_tx_timeout, + .ndo_tx_timeout = nes_netdev_tx_timeout, .ndo_set_mac_address = nes_netdev_set_mac_address, .ndo_set_multicast_list = nes_netdev_set_multicast_list, .ndo_change_mtu = nes_netdev_change_mtu, .ndo_validate_addr = eth_validate_addr, - .ndo_vlan_rx_register = nes_netdev_vlan_rx_register, + .ndo_fix_features = nes_fix_features, + .ndo_set_features = nes_set_features, }; /** @@ -1656,7 +1679,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, netdev->ethtool_ops = &nes_ethtool_ops; netif_napi_add(netdev, &nesvnic->napi, nes_netdev_poll, 128); nes_debug(NES_DBG_INIT, "Enabling VLAN Insert/Delete.\n"); - netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + netdev->features |= NETIF_F_HW_VLAN_TX; /* Fill in the port structure */ nesvnic->netdev = netdev; @@ -1683,7 +1706,8 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, netdev->dev_addr[5] = (u8)u64temp; memcpy(netdev->perm_addr, netdev->dev_addr, 6); - netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM; + netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_HW_VLAN_RX; if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV)) netdev->hw_features |= NETIF_F_TSO; netdev->features |= netdev->hw_features; @@ -1815,6 +1839,8 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, nes_init_phy(nesdev); } + nes_vlan_mode(netdev, nesdev, netdev->features); + return netdev; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 86addca9ddf6..43f89ba0a908 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -560,9 +560,11 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_path *path; struct ipoib_neigh *neigh; + struct neighbour *n; unsigned long flags; - neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev); + n = dst_get_neighbour(skb_dst(skb)); + neigh = ipoib_neigh_alloc(n, skb->dev); if (!neigh) { ++dev->stats.tx_dropped; dev_kfree_skb_any(skb); @@ -571,9 +573,9 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&priv->lock, flags); - path = __path_find(dev, skb_dst(skb)->neighbour->ha + 4); + path = __path_find(dev, n->ha + 4); if (!path) { - path = path_rec_create(dev, skb_dst(skb)->neighbour->ha + 4); + path = path_rec_create(dev, n->ha + 4); if (!path) goto err_path; @@ -607,7 +609,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) } } else { spin_unlock_irqrestore(&priv->lock, flags); - ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha)); + ipoib_send(dev, skb, path->ah, IPOIB_QPN(n->ha)); return; } } else { @@ -637,17 +639,20 @@ err_drop: static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(skb->dev); + struct dst_entry *dst = skb_dst(skb); + struct neighbour *n; /* Look up path record for unicasts */ - if (skb_dst(skb)->neighbour->ha[4] != 0xff) { + n = dst_get_neighbour(dst); + if (n->ha[4] != 0xff) { neigh_add_path(skb, dev); return; } /* Add in the P_Key for multicasts */ - skb_dst(skb)->neighbour->ha[8] = (priv->pkey >> 8) & 0xff; - skb_dst(skb)->neighbour->ha[9] = priv->pkey & 0xff; - ipoib_mcast_send(dev, skb_dst(skb)->neighbour->ha + 4, skb); + n->ha[8] = (priv->pkey >> 8) & 0xff; + n->ha[9] = priv->pkey & 0xff; + ipoib_mcast_send(dev, n->ha + 4, skb); } static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, @@ -712,18 +717,20 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_neigh *neigh; + struct neighbour *n; unsigned long flags; - if (likely(skb_dst(skb) && skb_dst(skb)->neighbour)) { - if (unlikely(!*to_ipoib_neigh(skb_dst(skb)->neighbour))) { + n = dst_get_neighbour(skb_dst(skb)); + if (likely(skb_dst(skb) && n)) { + if (unlikely(!*to_ipoib_neigh(n))) { ipoib_path_lookup(skb, dev); return NETDEV_TX_OK; } - neigh = *to_ipoib_neigh(skb_dst(skb)->neighbour); + neigh = *to_ipoib_neigh(n); if (unlikely((memcmp(&neigh->dgid.raw, - skb_dst(skb)->neighbour->ha + 4, + n->ha + 4, sizeof(union ib_gid))) || (neigh->dev != dev))) { spin_lock_irqsave(&priv->lock, flags); @@ -749,7 +756,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } } else if (neigh->ah) { - ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha)); + ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha)); return NETDEV_TX_OK; } @@ -812,6 +819,8 @@ static int ipoib_hard_header(struct sk_buff *skb, const void *daddr, const void *saddr, unsigned len) { struct ipoib_header *header; + struct dst_entry *dst; + struct neighbour *n; header = (struct ipoib_header *) skb_push(skb, sizeof *header); @@ -823,7 +832,11 @@ static int ipoib_hard_header(struct sk_buff *skb, * destination address onto the front of the skb so we can * figure out where to send the packet later. */ - if ((!skb_dst(skb) || !skb_dst(skb)->neighbour) && daddr) { + dst = skb_dst(skb); + n = NULL; + if (dst) + n = dst_get_neighbour(dst); + if ((!dst || !n) && daddr) { struct ipoib_pseudoheader *phdr = (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 3871ac663554..ecea4fe1ed00 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -258,11 +258,15 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, netif_tx_lock_bh(dev); while (!skb_queue_empty(&mcast->pkt_queue)) { struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue); + struct dst_entry *dst = skb_dst(skb); + struct neighbour *n = NULL; + netif_tx_unlock_bh(dev); skb->dev = dev; - - if (!skb_dst(skb) || !skb_dst(skb)->neighbour) { + if (dst) + n = dst_get_neighbour(dst); + if (!dst || !n) { /* put pseudoheader back on for next time */ skb_push(skb, sizeof (struct ipoib_pseudoheader)); } @@ -715,11 +719,13 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb) out: if (mcast && mcast->ah) { - if (skb_dst(skb) && - skb_dst(skb)->neighbour && - !*to_ipoib_neigh(skb_dst(skb)->neighbour)) { - struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, - skb->dev); + struct dst_entry *dst = skb_dst(skb); + struct neighbour *n = NULL; + if (dst) + n = dst_get_neighbour(dst); + if (n && !*to_ipoib_neigh(n)) { + struct ipoib_neigh *neigh = ipoib_neigh_alloc(n, + skb->dev); if (neigh) { kref_get(&mcast->ah->ref); diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h index 2f02ab0ccc1e..342cbc1bdaae 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h @@ -45,6 +45,7 @@ #include <scsi/libiscsi.h> #include <scsi/scsi_transport_iscsi.h> +#include <linux/interrupt.h> #include <linux/wait.h> #include <linux/sched.h> #include <linux/list.h> diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c index 472a2af79446..861b6511f3ee 100644 --- a/drivers/isdn/hardware/mISDN/avmfritz.c +++ b/drivers/isdn/hardware/mISDN/avmfritz.c @@ -20,6 +20,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ +#include <linux/interrupt.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/delay.h> diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index f6f3c87cc7c2..a440d7fff0ad 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -152,6 +152,7 @@ #define HFC_MULTI_VERSION "2.03" +#include <linux/interrupt.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/pci.h> diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index b01a7be1300f..3261de18a91e 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -44,6 +44,7 @@ * */ +#include <linux/interrupt.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/delay.h> diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c index bc0529ac88a1..6218775ce87d 100644 --- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c +++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c @@ -38,6 +38,7 @@ * */ +#include <linux/interrupt.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/delay.h> diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c index 64ecc6f5ffaf..d2ffb1d9b831 100644 --- a/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/drivers/isdn/hardware/mISDN/mISDNipac.c @@ -20,6 +20,7 @@ * */ +#include <linux/irqreturn.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/mISDNhw.h> diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index db25b6b2ae39..5ef9f11ee74b 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c @@ -20,6 +20,7 @@ * */ +#include <linux/interrupt.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/delay.h> diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c index 9e07246bb9e7..4d0d41ea1228 100644 --- a/drivers/isdn/hardware/mISDN/speedfax.c +++ b/drivers/isdn/hardware/mISDN/speedfax.c @@ -22,6 +22,7 @@ * */ +#include <linux/interrupt.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/pci.h> diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index 9e84870b971c..e10e0284533c 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c @@ -21,6 +21,7 @@ * */ +#include <linux/interrupt.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/delay.h> diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index de1c669c7b13..0a5c42a3f125 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -16,6 +16,7 @@ #include <linux/slab.h> #include <linux/mm.h> #include <linux/mman.h> +#include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/timer.h> #include <linux/wait.h> diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c index 8b0a7d86b30f..478ebab54ca4 100644 --- a/drivers/isdn/hisax/hisax_fcpcipnp.c +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c @@ -25,6 +25,7 @@ #include <linux/module.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/pci.h> #include <linux/isapnp.h> #include <linux/kmod.h> diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 97988111e45a..48e9cc0369b1 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -1983,13 +1983,14 @@ isdn_net_rebuild_header(struct sk_buff *skb) return ret; } -static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh) +static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh, + __be16 type) { const struct net_device *dev = neigh->dev; isdn_net_local *lp = netdev_priv(dev); if (lp->p_encap == ISDN_NET_ENCAP_ETHER) - return eth_header_cache(neigh, hh); + return eth_header_cache(neigh, hh, type); return -1; } diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h index 9e2148a19967..437912e49824 100644 --- a/drivers/media/dvb/b2c2/flexcop-common.h +++ b/drivers/media/dvb/b2c2/flexcop-common.h @@ -6,6 +6,7 @@ #ifndef __FLEXCOP_COMMON_H__ #define __FLEXCOP_COMMON_H__ +#include <linux/interrupt.h> #include <linux/pci.h> #include <linux/mutex.h> diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index b2b0c45f32a9..55e6533f15e9 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -22,6 +22,7 @@ #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/proc_fs.h> diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 330216febd78..3d7046909009 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -22,6 +22,7 @@ #include <linux/slab.h> #include <linux/sched.h> #include <linux/interrupt.h> +#include <asm/io.h> #include "dmxdev.h" #include "dvbdev.h" diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index bd400d21b81f..49dbca145bb8 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -21,6 +21,7 @@ #ifndef __MANTIS_COMMON_H #define __MANTIS_COMMON_H +#include <linux/interrupt.h> #include <linux/mutex.h> #include <linux/workqueue.h> diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 9f73c2cfc9ea..36f2256ebb0e 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -23,6 +23,7 @@ #include <linux/signal.h> #include <linux/sched.h> #include <linux/interrupt.h> +#include <asm/io.h> #include "dmxdev.h" #include "dvbdev.h" diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 5772ebb3a69e..672cf4d2462d 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -23,6 +23,7 @@ #include <linux/sched.h> #include <linux/interrupt.h> +#include <asm/io.h> #include "dmxdev.h" #include "dvbdev.h" diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c index 479086dbb9a8..24fcdc63d6d5 100644 --- a/drivers/media/dvb/mantis/mantis_ioc.c +++ b/drivers/media/dvb/mantis/mantis_ioc.c @@ -24,6 +24,7 @@ #include <linux/signal.h> #include <linux/sched.h> #include <linux/interrupt.h> +#include <asm/io.h> #include "dmxdev.h" #include "dvbdev.h" diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index 5cb545b913f6..2f188c089666 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -23,6 +23,7 @@ #include <linux/signal.h> #include <linux/sched.h> #include <linux/interrupt.h> +#include <asm/io.h> #include "dmxdev.h" #include "dvbdev.h" diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c index f807c8ba26e4..18340dafa426 100644 --- a/drivers/media/dvb/mantis/mantis_uart.c +++ b/drivers/media/dvb/mantis/mantis_uart.c @@ -20,6 +20,7 @@ #include <linux/kernel.h> #include <linux/spinlock.h> +#include <asm/io.h> #include <linux/signal.h> #include <linux/sched.h> diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index 26bc0cbe84d4..430ae84ce528 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -21,6 +21,7 @@ #include <linux/signal.h> #include <linux/sched.h> #include <linux/interrupt.h> +#include <asm/io.h> #include "dmxdev.h" #include "dvbdev.h" diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c index 7cb79ec685f0..80fb51004461 100644 --- a/drivers/media/dvb/pluto2/pluto2.c +++ b/drivers/media/dvb/pluto2/pluto2.c @@ -26,6 +26,7 @@ #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index 2aa616dec32d..86f259cdfcbc 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c @@ -11,6 +11,7 @@ */ #include <linux/device.h> +#include <linux/dma-mapping.h> #include <linux/dmaengine.h> #include <linux/mfd/tmio.h> #include <linux/mmc/host.h> diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index b300705d41cb..1b90fd56bef1 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -22,6 +22,7 @@ * */ +#include <linux/dma-mapping.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/moduleparam.h> diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index 5b732988d493..84e68f1b9adf 100644 --- a/drivers/net/3c503.c +++ b/drivers/net/3c503.c @@ -49,6 +49,7 @@ static const char version[] = #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/ethtool.h> #include <asm/uaccess.h> diff --git a/drivers/net/7990.c b/drivers/net/7990.c index 903bcb3ef5bd..60b35fb5f524 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -594,7 +594,6 @@ static void lance_load_multicast (struct net_device *dev) volatile struct lance_init_block *ib = lp->init_block; volatile u16 *mcast_table = (u16 *)&ib->filter; struct netdev_hw_addr *ha; - char *addrs; u32 crc; /* set all multicast bits */ @@ -609,13 +608,7 @@ static void lance_load_multicast (struct net_device *dev) /* Add addresses */ netdev_for_each_mc_addr(ha, dev) { - addrs = ha->addr; - - /* multicast address? */ - if (!(*addrs & 1)) - continue; - - crc = ether_crc_le(6, addrs); + crc = ether_crc_le(6, ha->addr); crc = crc >> 26; mcast_table [crc >> 4] |= 1 << (crc & 0xf); } diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 10c45051caea..cc4c210a91f8 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -60,6 +60,7 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/pci.h> #include <linux/dma-mapping.h> #include <linux/delay.h> @@ -77,17 +78,6 @@ #include <asm/irq.h> #include <asm/uaccess.h> -/* VLAN tagging feature enable/disable */ -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -#define CP_VLAN_TAG_USED 1 -#define CP_VLAN_TX_TAG(tx_desc,vlan_tag_value) \ - do { (tx_desc)->opts2 = cpu_to_le32(vlan_tag_value); } while (0) -#else -#define CP_VLAN_TAG_USED 0 -#define CP_VLAN_TX_TAG(tx_desc,vlan_tag_value) \ - do { (tx_desc)->opts2 = 0; } while (0) -#endif - /* These identify the driver base version and may not be removed. */ static char version[] = DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; @@ -355,9 +345,6 @@ struct cp_private { unsigned rx_buf_sz; unsigned wol_enabled : 1; /* Is Wake-on-LAN enabled? */ -#if CP_VLAN_TAG_USED - struct vlan_group *vlgrp; -#endif dma_addr_t ring_dma; struct mii_if_info mii_if; @@ -422,24 +409,6 @@ static struct { }; -#if CP_VLAN_TAG_USED -static void cp_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) -{ - struct cp_private *cp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&cp->lock, flags); - cp->vlgrp = grp; - if (grp) - cp->cpcmd |= RxVlanOn; - else - cp->cpcmd &= ~RxVlanOn; - - cpw16(CpCmd, cp->cpcmd); - spin_unlock_irqrestore(&cp->lock, flags); -} -#endif /* CP_VLAN_TAG_USED */ - static inline void cp_set_rxbufsize (struct cp_private *cp) { unsigned int mtu = cp->dev->mtu; @@ -454,18 +423,17 @@ static inline void cp_set_rxbufsize (struct cp_private *cp) static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb, struct cp_desc *desc) { + u32 opts2 = le32_to_cpu(desc->opts2); + skb->protocol = eth_type_trans (skb, cp->dev); cp->dev->stats.rx_packets++; cp->dev->stats.rx_bytes += skb->len; -#if CP_VLAN_TAG_USED - if (cp->vlgrp && (desc->opts2 & cpu_to_le32(RxVlanTagged))) { - vlan_hwaccel_receive_skb(skb, cp->vlgrp, - swab16(le32_to_cpu(desc->opts2) & 0xffff)); - } else -#endif - netif_receive_skb(skb); + if (opts2 & RxVlanTagged) + __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); + + napi_gro_receive(&cp->napi, skb); } static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail, @@ -729,6 +697,12 @@ static void cp_tx (struct cp_private *cp) netif_wake_queue(cp->dev); } +static inline u32 cp_tx_vlan_tag(struct sk_buff *skb) +{ + return vlan_tx_tag_present(skb) ? + TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; +} + static netdev_tx_t cp_start_xmit (struct sk_buff *skb, struct net_device *dev) { @@ -736,9 +710,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, unsigned entry; u32 eor, flags; unsigned long intr_flags; -#if CP_VLAN_TAG_USED - u32 vlan_tag = 0; -#endif + __le32 opts2; int mss = 0; spin_lock_irqsave(&cp->lock, intr_flags); @@ -751,15 +723,12 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, return NETDEV_TX_BUSY; } -#if CP_VLAN_TAG_USED - if (vlan_tx_tag_present(skb)) - vlan_tag = TxVlanTag | swab16(vlan_tx_tag_get(skb)); -#endif - entry = cp->tx_head; eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; mss = skb_shinfo(skb)->gso_size; + opts2 = cpu_to_le32(cp_tx_vlan_tag(skb)); + if (skb_shinfo(skb)->nr_frags == 0) { struct cp_desc *txd = &cp->tx_ring[entry]; u32 len; @@ -767,7 +736,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, len = skb->len; mapping = dma_map_single(&cp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE); - CP_VLAN_TX_TAG(txd, vlan_tag); + txd->opts2 = opts2; txd->addr = cpu_to_le64(mapping); wmb(); @@ -838,7 +807,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, ctrl |= LastFrag; txd = &cp->tx_ring[entry]; - CP_VLAN_TX_TAG(txd, vlan_tag); + txd->opts2 = opts2; txd->addr = cpu_to_le64(mapping); wmb(); @@ -850,7 +819,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, } txd = &cp->tx_ring[first_entry]; - CP_VLAN_TX_TAG(txd, vlan_tag); + txd->opts2 = opts2; txd->addr = cpu_to_le64(first_mapping); wmb(); @@ -1430,6 +1399,11 @@ static int cp_set_features(struct net_device *dev, u32 features) else cp->cpcmd &= ~RxChkSum; + if (features & NETIF_F_HW_VLAN_RX) + cp->cpcmd |= RxVlanOn; + else + cp->cpcmd &= ~RxVlanOn; + cpw16_f(CpCmd, cp->cpcmd); spin_unlock_irqrestore(&cp->lock, flags); @@ -1817,9 +1791,6 @@ static const struct net_device_ops cp_netdev_ops = { .ndo_start_xmit = cp_start_xmit, .ndo_tx_timeout = cp_tx_timeout, .ndo_set_features = cp_set_features, -#if CP_VLAN_TAG_USED - .ndo_vlan_rx_register = cp_vlan_rx_register, -#endif #ifdef BROKEN .ndo_change_mtu = cp_change_mtu, #endif @@ -1948,15 +1919,16 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) dev->ethtool_ops = &cp_ethtool_ops; dev->watchdog_timeo = TX_TIMEOUT; -#if CP_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif if (pci_using_dac) dev->features |= NETIF_F_HIGHDMA; /* disabled by default until verified */ - dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; + dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_HIGHDMA; dev->irq = pdev->irq; diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index e3bad8247fd1..c2672c692d6f 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -100,6 +100,7 @@ #include <linux/compiler.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/rtnetlink.h> diff --git a/drivers/net/8390.h b/drivers/net/8390.h index 3d9e8fb4fbee..58a12e4c78f9 100644 --- a/drivers/net/8390.h +++ b/drivers/net/8390.h @@ -9,6 +9,7 @@ #include <linux/if_ether.h> #include <linux/ioport.h> +#include <linux/irqreturn.h> #include <linux/skbuff.h> #define TX_PAGES 12 /* Two Tx slots */ diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 93359fab240e..8d0314dbd946 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1934,13 +1934,6 @@ config DECLANCE DEC (now Compaq) based on the AMD Lance chipset, including the DEPCA series. (This chipset is better known via the NE2100 cards.) -config 68360_ENET - bool "Motorola 68360 ethernet controller" - depends on M68360 - help - Say Y here if you want to use the built-in ethernet controller of - the Motorola 68360 processor. - config FEC bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" depends on M523x || M527x || M5272 || M528x || M520x || M532x || \ @@ -2115,7 +2108,6 @@ config E1000 config E1000E tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support" - select CRC32 depends on PCI && (!SPARC32 || BROKEN) select CRC32 ---help--- @@ -2197,15 +2189,6 @@ config IGBVF source "drivers/net/ixp2000/Kconfig" -config MYRI_SBUS - tristate "MyriCOM Gigabit Ethernet support" - depends on SBUS - help - This driver supports MyriCOM Sbus gigabit Ethernet cards. - - To compile this driver as a module, choose M here: the module - will be called myri_sbus. This is recommended. - config NS83820 tristate "National Semiconductor DP83820 support" depends on PCI @@ -2282,7 +2265,7 @@ config SIS190 will be called sis190. This is recommended. config SKGE - tristate "New SysKonnect GigaEthernet support" + tristate "Marvell Yukon Gigabit Ethernet support" depends on PCI select CRC32 ---help--- @@ -2298,7 +2281,7 @@ config SKGE Linksys EG1032/EG1064, 3Com 3C940/3C940B, SysKonnect SK-9871/9872. It does not support the newer Yukon2 chipset: a separate driver, - sky2, is provided for Yukon2-based adapters. + sky2, is provided for these adapters. To compile this driver as a module, choose M here: the module will be called skge. This is recommended. @@ -2313,8 +2296,17 @@ config SKGE_DEBUG If unsure, say N. +config SKGE_GENESIS + bool "Support for older SysKonnect Genesis boards" + depends on SKGE + help + This enables support for the older and uncommon SysKonnect Genesis + chips, which support MII via an external transceiver, instead of + an internal one. Disabling this option will save some memory + by making code smaller. If unsure say Y. + config SKY2 - tristate "SysKonnect Yukon2 support" + tristate "Marvell Yukon 2 support" depends on PCI select CRC32 ---help--- @@ -2324,7 +2316,7 @@ config SKY2 88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21 There is companion driver for the older Marvell Yukon and - Genesis based adapters: skge. + SysKonnect Genesis based adapters: skge. To compile this driver as a module, choose M here: the module will be called sky2. This is recommended. @@ -2561,6 +2553,15 @@ config PCH_GBE ML7223 is companion chip for Intel Atom E6xx series. ML7223 is completely compatible for Intel EG20T PCH. +config FTGMAC100 + tristate "Faraday FTGMAC100 Gigabit Ethernet support" + depends on ARM + select PHYLIB + help + This driver supports the FTGMAC100 Gigabit Ethernet controller + from Faraday. It is used on Faraday A369, Andes AG102 and some + other ARM/NDS32 SoC's. + endif # NETDEV_1000 # diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 776a478e6296..b7622c3745fa 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -59,7 +59,6 @@ obj-$(CONFIG_HAPPYMEAL) += sunhme.o obj-$(CONFIG_SUNLANCE) += sunlance.o obj-$(CONFIG_SUNQE) += sunqe.o obj-$(CONFIG_SUNBMAC) += sunbmac.o -obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o obj-$(CONFIG_CASSINI) += cassini.o obj-$(CONFIG_SUNVNET) += sunvnet.o @@ -128,7 +127,6 @@ obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y) obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o endif -obj-$(CONFIG_68360_ENET) += 68360enet.o obj-$(CONFIG_WD80x3) += wd.o 8390.o obj-$(CONFIG_EL2) += 3c503.o 8390p.o obj-$(CONFIG_NE2000) += ne.o 8390p.o @@ -148,6 +146,7 @@ obj-$(CONFIG_FORCEDETH) += forcedeth.o obj-$(CONFIG_NE_H8300) += ne-h8300.o obj-$(CONFIG_AX88796) += ax88796.o obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o +obj-$(CONFIG_FTGMAC100) += ftgmac100.o obj-$(CONFIG_FTMAC100) += ftmac100.o obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index deaa8bc16cf8..e1e1b07d9b8d 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -37,6 +37,11 @@ * both 10BASE-2 (thin coax) and AUI (DB-15) connectors */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +/*#define DEBUG*/ +/*#define TEST_HITS*/ + #include <linux/errno.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> @@ -58,29 +63,22 @@ #include "a2065.h" - - /* - * Transmit/Receive Ring Definitions - */ +/* Transmit/Receive Ring Definitions */ #define LANCE_LOG_TX_BUFFERS (2) #define LANCE_LOG_RX_BUFFERS (4) -#define TX_RING_SIZE (1<<LANCE_LOG_TX_BUFFERS) -#define RX_RING_SIZE (1<<LANCE_LOG_RX_BUFFERS) +#define TX_RING_SIZE (1 << LANCE_LOG_TX_BUFFERS) +#define RX_RING_SIZE (1 << LANCE_LOG_RX_BUFFERS) -#define TX_RING_MOD_MASK (TX_RING_SIZE-1) -#define RX_RING_MOD_MASK (RX_RING_SIZE-1) +#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) +#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) #define PKT_BUF_SIZE (1544) #define RX_BUFF_SIZE PKT_BUF_SIZE #define TX_BUFF_SIZE PKT_BUF_SIZE - - /* - * Layout of the Lance's RAM Buffer - */ - +/* Layout of the Lance's RAM Buffer */ struct lance_init_block { unsigned short mode; /* Pre-set mode (reg. 15) */ @@ -97,14 +95,11 @@ struct lance_init_block { struct lance_rx_desc brx_ring[RX_RING_SIZE]; struct lance_tx_desc btx_ring[TX_RING_SIZE]; - char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE]; - char tx_buf [TX_RING_SIZE][TX_BUFF_SIZE]; + char rx_buf[RX_RING_SIZE][RX_BUFF_SIZE]; + char tx_buf[TX_RING_SIZE][TX_BUFF_SIZE]; }; - - /* - * Private Device Data - */ +/* Private Device Data */ struct lance_private { char *name; @@ -129,21 +124,14 @@ struct lance_private { struct timer_list multicast_timer; }; -#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ - lp->tx_old+lp->tx_ring_mod_mask-lp->tx_new:\ - lp->tx_old - lp->tx_new-1) - - #define LANCE_ADDR(x) ((int)(x) & ~0xff000000) /* Load the CSR registers */ -static void load_csrs (struct lance_private *lp) +static void load_csrs(struct lance_private *lp) { volatile struct lance_regs *ll = lp->ll; volatile struct lance_init_block *aib = lp->lance_init_block; - int leptr; - - leptr = LANCE_ADDR (aib); + int leptr = LANCE_ADDR(aib); ll->rap = LE_CSR1; ll->rdp = (leptr & 0xFFFF); @@ -156,19 +144,16 @@ static void load_csrs (struct lance_private *lp) ll->rap = LE_CSR0; } -#define ZERO 0 - /* Setup the Lance Rx and Tx rings */ -static void lance_init_ring (struct net_device *dev) +static void lance_init_ring(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); volatile struct lance_init_block *ib = lp->init_block; - volatile struct lance_init_block *aib; /* for LANCE_ADDR computations */ + volatile struct lance_init_block *aib = lp->lance_init_block; + /* for LANCE_ADDR computations */ int leptr; int i; - aib = lp->lance_init_block; - /* Lock out other processes while setting up hardware */ netif_stop_queue(dev); lp->rx_new = lp->tx_new = 0; @@ -179,41 +164,38 @@ static void lance_init_ring (struct net_device *dev) /* Copy the ethernet address to the lance init block * Note that on the sparc you need to swap the ethernet address. */ - ib->phys_addr [0] = dev->dev_addr [1]; - ib->phys_addr [1] = dev->dev_addr [0]; - ib->phys_addr [2] = dev->dev_addr [3]; - ib->phys_addr [3] = dev->dev_addr [2]; - ib->phys_addr [4] = dev->dev_addr [5]; - ib->phys_addr [5] = dev->dev_addr [4]; - - if (ZERO) - printk(KERN_DEBUG "TX rings:\n"); + ib->phys_addr[0] = dev->dev_addr[1]; + ib->phys_addr[1] = dev->dev_addr[0]; + ib->phys_addr[2] = dev->dev_addr[3]; + ib->phys_addr[3] = dev->dev_addr[2]; + ib->phys_addr[4] = dev->dev_addr[5]; + ib->phys_addr[5] = dev->dev_addr[4]; /* Setup the Tx ring entries */ - for (i = 0; i <= (1<<lp->lance_log_tx_bufs); i++) { + netdev_dbg(dev, "TX rings:\n"); + for (i = 0; i <= 1 << lp->lance_log_tx_bufs; i++) { leptr = LANCE_ADDR(&aib->tx_buf[i][0]); - ib->btx_ring [i].tmd0 = leptr; - ib->btx_ring [i].tmd1_hadr = leptr >> 16; - ib->btx_ring [i].tmd1_bits = 0; - ib->btx_ring [i].length = 0xf000; /* The ones required by tmd2 */ - ib->btx_ring [i].misc = 0; - if (i < 3 && ZERO) - printk(KERN_DEBUG "%d: 0x%8.8x\n", i, leptr); + ib->btx_ring[i].tmd0 = leptr; + ib->btx_ring[i].tmd1_hadr = leptr >> 16; + ib->btx_ring[i].tmd1_bits = 0; + ib->btx_ring[i].length = 0xf000; /* The ones required by tmd2 */ + ib->btx_ring[i].misc = 0; + if (i < 3) + netdev_dbg(dev, "%d: 0x%08x\n", i, leptr); } /* Setup the Rx ring entries */ - if (ZERO) - printk(KERN_DEBUG "RX rings:\n"); - for (i = 0; i < (1<<lp->lance_log_rx_bufs); i++) { + netdev_dbg(dev, "RX rings:\n"); + for (i = 0; i < 1 << lp->lance_log_rx_bufs; i++) { leptr = LANCE_ADDR(&aib->rx_buf[i][0]); - ib->brx_ring [i].rmd0 = leptr; - ib->brx_ring [i].rmd1_hadr = leptr >> 16; - ib->brx_ring [i].rmd1_bits = LE_R1_OWN; - ib->brx_ring [i].length = -RX_BUFF_SIZE | 0xf000; - ib->brx_ring [i].mblength = 0; - if (i < 3 && ZERO) - printk(KERN_DEBUG "%d: 0x%8.8x\n", i, leptr); + ib->brx_ring[i].rmd0 = leptr; + ib->brx_ring[i].rmd1_hadr = leptr >> 16; + ib->brx_ring[i].rmd1_bits = LE_R1_OWN; + ib->brx_ring[i].length = -RX_BUFF_SIZE | 0xf000; + ib->brx_ring[i].mblength = 0; + if (i < 3) + netdev_dbg(dev, "%d: 0x%08x\n", i, leptr); } /* Setup the initialization block */ @@ -222,22 +204,20 @@ static void lance_init_ring (struct net_device *dev) leptr = LANCE_ADDR(&aib->brx_ring); ib->rx_len = (lp->lance_log_rx_bufs << 13) | (leptr >> 16); ib->rx_ptr = leptr; - if (ZERO) - printk(KERN_DEBUG "RX ptr: %8.8x\n", leptr); + netdev_dbg(dev, "RX ptr: %08x\n", leptr); /* Setup tx descriptor pointer */ leptr = LANCE_ADDR(&aib->btx_ring); ib->tx_len = (lp->lance_log_tx_bufs << 13) | (leptr >> 16); ib->tx_ptr = leptr; - if (ZERO) - printk(KERN_DEBUG "TX ptr: %8.8x\n", leptr); + netdev_dbg(dev, "TX ptr: %08x\n", leptr); /* Clear the multicast filter */ - ib->filter [0] = 0; - ib->filter [1] = 0; + ib->filter[0] = 0; + ib->filter[1] = 0; } -static int init_restart_lance (struct lance_private *lp) +static int init_restart_lance(struct lance_private *lp) { volatile struct lance_regs *ll = lp->ll; int i; @@ -249,8 +229,7 @@ static int init_restart_lance (struct lance_private *lp) for (i = 0; (i < 100) && !(ll->rdp & (LE_C0_ERR | LE_C0_IDON)); i++) barrier(); if ((i == 100) || (ll->rdp & LE_C0_ERR)) { - printk(KERN_ERR "LANCE unopened after %d ticks, csr0=%4.4x.\n", - i, ll->rdp); + pr_err("unopened after %d ticks, csr0=%04x\n", i, ll->rdp); return -EIO; } @@ -261,7 +240,7 @@ static int init_restart_lance (struct lance_private *lp) return 0; } -static int lance_rx (struct net_device *dev) +static int lance_rx(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); volatile struct lance_init_block *ib = lp->init_block; @@ -271,22 +250,24 @@ static int lance_rx (struct net_device *dev) #ifdef TEST_HITS int i; - printk(KERN_DEBUG "["); + char buf[RX_RING_SIZE + 1]; + for (i = 0; i < RX_RING_SIZE; i++) { + char r1_own = ib->brx_ring[i].rmd1_bits & LE_R1_OWN; if (i == lp->rx_new) - printk ("%s", - ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "_" : "X"); + buf[i] = r1_own ? '_' : 'X'; else - printk ("%s", - ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "." : "1"); + buf[i] = r1_own ? '.' : '1'; } - printk ("]\n"); + buf[RX_RING_SIZE] = 0; + + pr_debug("RxRing TestHits: [%s]\n", buf); #endif - ll->rdp = LE_C0_RINT|LE_C0_INEA; - for (rd = &ib->brx_ring [lp->rx_new]; + ll->rdp = LE_C0_RINT | LE_C0_INEA; + for (rd = &ib->brx_ring[lp->rx_new]; !((bits = rd->rmd1_bits) & LE_R1_OWN); - rd = &ib->brx_ring [lp->rx_new]) { + rd = &ib->brx_ring[lp->rx_new]) { /* We got an incomplete frame? */ if ((bits & LE_R1_POK) != LE_R1_POK) { @@ -297,18 +278,22 @@ static int lance_rx (struct net_device *dev) /* Count only the end frame as a rx error, * not the beginning */ - if (bits & LE_R1_BUF) dev->stats.rx_fifo_errors++; - if (bits & LE_R1_CRC) dev->stats.rx_crc_errors++; - if (bits & LE_R1_OFL) dev->stats.rx_over_errors++; - if (bits & LE_R1_FRA) dev->stats.rx_frame_errors++; - if (bits & LE_R1_EOP) dev->stats.rx_errors++; + if (bits & LE_R1_BUF) + dev->stats.rx_fifo_errors++; + if (bits & LE_R1_CRC) + dev->stats.rx_crc_errors++; + if (bits & LE_R1_OFL) + dev->stats.rx_over_errors++; + if (bits & LE_R1_FRA) + dev->stats.rx_frame_errors++; + if (bits & LE_R1_EOP) + dev->stats.rx_errors++; } else { int len = (rd->mblength & 0xfff) - 4; - struct sk_buff *skb = dev_alloc_skb (len+2); + struct sk_buff *skb = dev_alloc_skb(len + 2); if (!skb) { - printk(KERN_WARNING "%s: Memory squeeze, " - "deferring packet.\n", dev->name); + netdev_warn(dev, "Memory squeeze, deferring packet\n"); dev->stats.rx_dropped++; rd->mblength = 0; rd->rmd1_bits = LE_R1_OWN; @@ -316,13 +301,13 @@ static int lance_rx (struct net_device *dev) return 0; } - skb_reserve (skb, 2); /* 16 byte align */ - skb_put (skb, len); /* make room */ + skb_reserve(skb, 2); /* 16 byte align */ + skb_put(skb, len); /* make room */ skb_copy_to_linear_data(skb, - (unsigned char *)&(ib->rx_buf [lp->rx_new][0]), - len); - skb->protocol = eth_type_trans (skb, dev); - netif_rx (skb); + (unsigned char *)&ib->rx_buf[lp->rx_new][0], + len); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); dev->stats.rx_packets++; dev->stats.rx_bytes += len; } @@ -335,7 +320,7 @@ static int lance_rx (struct net_device *dev) return 0; } -static int lance_tx (struct net_device *dev) +static int lance_tx(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); volatile struct lance_init_block *ib = lp->init_block; @@ -350,7 +335,7 @@ static int lance_tx (struct net_device *dev) j = lp->tx_old; for (i = j; i != lp->tx_new; i = j) { - td = &ib->btx_ring [i]; + td = &ib->btx_ring[i]; /* If we hit a packet not owned by us, stop */ if (td->tmd1_bits & LE_T1_OWN) @@ -360,45 +345,44 @@ static int lance_tx (struct net_device *dev) status = td->misc; dev->stats.tx_errors++; - if (status & LE_T3_RTY) dev->stats.tx_aborted_errors++; - if (status & LE_T3_LCOL) dev->stats.tx_window_errors++; + if (status & LE_T3_RTY) + dev->stats.tx_aborted_errors++; + if (status & LE_T3_LCOL) + dev->stats.tx_window_errors++; if (status & LE_T3_CLOS) { dev->stats.tx_carrier_errors++; if (lp->auto_select) { lp->tpe = 1 - lp->tpe; - printk(KERN_ERR "%s: Carrier Lost, " - "trying %s\n", dev->name, - lp->tpe?"TPE":"AUI"); + netdev_err(dev, "Carrier Lost, trying %s\n", + lp->tpe ? "TPE" : "AUI"); /* Stop the lance */ ll->rap = LE_CSR0; ll->rdp = LE_C0_STOP; - lance_init_ring (dev); - load_csrs (lp); - init_restart_lance (lp); + lance_init_ring(dev); + load_csrs(lp); + init_restart_lance(lp); return 0; } } - /* buffer errors and underflows turn off the transmitter */ - /* Restart the adapter */ - if (status & (LE_T3_BUF|LE_T3_UFL)) { + /* buffer errors and underflows turn off + * the transmitter, so restart the adapter + */ + if (status & (LE_T3_BUF | LE_T3_UFL)) { dev->stats.tx_fifo_errors++; - printk(KERN_ERR "%s: Tx: ERR_BUF|ERR_UFL, " - "restarting\n", dev->name); + netdev_err(dev, "Tx: ERR_BUF|ERR_UFL, restarting\n"); /* Stop the lance */ ll->rap = LE_CSR0; ll->rdp = LE_C0_STOP; - lance_init_ring (dev); - load_csrs (lp); - init_restart_lance (lp); + lance_init_ring(dev); + load_csrs(lp); + init_restart_lance(lp); return 0; } } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) { - /* - * So we don't count the packet more than once. - */ + /* So we don't count the packet more than once. */ td->tmd1_bits &= ~(LE_T1_POK); /* One collision before packet was sent. */ @@ -419,17 +403,19 @@ static int lance_tx (struct net_device *dev) return 0; } -static irqreturn_t lance_interrupt (int irq, void *dev_id) +static int lance_tx_buffs_avail(struct lance_private *lp) { - struct net_device *dev; - struct lance_private *lp; - volatile struct lance_regs *ll; - int csr0; - - dev = (struct net_device *) dev_id; + if (lp->tx_old <= lp->tx_new) + return lp->tx_old + lp->tx_ring_mod_mask - lp->tx_new; + return lp->tx_old - lp->tx_new - 1; +} - lp = netdev_priv(dev); - ll = lp->ll; +static irqreturn_t lance_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct lance_private *lp = netdev_priv(dev); + volatile struct lance_regs *ll = lp->ll; + int csr0; ll->rap = LE_CSR0; /* LANCE Controller Status */ csr0 = ll->rdp; @@ -438,19 +424,19 @@ static irqreturn_t lance_interrupt (int irq, void *dev_id) return IRQ_NONE; /* been generated by the Lance. */ /* Acknowledge all the interrupt sources ASAP */ - ll->rdp = csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT| + ll->rdp = csr0 & ~(LE_C0_INEA | LE_C0_TDMD | LE_C0_STOP | LE_C0_STRT | LE_C0_INIT); - if ((csr0 & LE_C0_ERR)) { + if (csr0 & LE_C0_ERR) { /* Clear the error condition */ - ll->rdp = LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA; + ll->rdp = LE_C0_BABL | LE_C0_ERR | LE_C0_MISS | LE_C0_INEA; } if (csr0 & LE_C0_RINT) - lance_rx (dev); + lance_rx(dev); if (csr0 & LE_C0_TINT) - lance_tx (dev); + lance_tx(dev); /* Log misc errors. */ if (csr0 & LE_C0_BABL) @@ -458,22 +444,22 @@ static irqreturn_t lance_interrupt (int irq, void *dev_id) if (csr0 & LE_C0_MISS) dev->stats.rx_errors++; /* Missed a Rx frame. */ if (csr0 & LE_C0_MERR) { - printk(KERN_ERR "%s: Bus master arbitration failure, status " - "%4.4x.\n", dev->name, csr0); + netdev_err(dev, "Bus master arbitration failure, status %04x\n", + csr0); /* Restart the chip. */ ll->rdp = LE_C0_STRT; } - if (netif_queue_stopped(dev) && TX_BUFFS_AVAIL > 0) + if (netif_queue_stopped(dev) && lance_tx_buffs_avail(lp) > 0) netif_wake_queue(dev); ll->rap = LE_CSR0; - ll->rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR| - LE_C0_IDON|LE_C0_INEA; + ll->rdp = (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_MERR | + LE_C0_IDON | LE_C0_INEA); return IRQ_HANDLED; } -static int lance_open (struct net_device *dev) +static int lance_open(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); volatile struct lance_regs *ll = lp->ll; @@ -486,17 +472,18 @@ static int lance_open (struct net_device *dev) /* Install the Interrupt handler */ ret = request_irq(IRQ_AMIGA_PORTS, lance_interrupt, IRQF_SHARED, dev->name, dev); - if (ret) return ret; + if (ret) + return ret; - load_csrs (lp); - lance_init_ring (dev); + load_csrs(lp); + lance_init_ring(dev); netif_start_queue(dev); - return init_restart_lance (lp); + return init_restart_lance(lp); } -static int lance_close (struct net_device *dev) +static int lance_close(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); volatile struct lance_regs *ll = lp->ll; @@ -512,7 +499,7 @@ static int lance_close (struct net_device *dev) return 0; } -static inline int lance_reset (struct net_device *dev) +static inline int lance_reset(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); volatile struct lance_regs *ll = lp->ll; @@ -522,16 +509,15 @@ static inline int lance_reset (struct net_device *dev) ll->rap = LE_CSR0; ll->rdp = LE_C0_STOP; - load_csrs (lp); + load_csrs(lp); - lance_init_ring (dev); + lance_init_ring(dev); dev->trans_start = jiffies; /* prevent tx timeout */ netif_start_queue(dev); - status = init_restart_lance (lp); -#ifdef DEBUG_DRIVER - printk(KERN_DEBUG "Lance restart=%d\n", status); -#endif + status = init_restart_lance(lp); + netdev_dbg(dev, "Lance restart=%d\n", status); + return status; } @@ -540,14 +526,13 @@ static void lance_tx_timeout(struct net_device *dev) struct lance_private *lp = netdev_priv(dev); volatile struct lance_regs *ll = lp->ll; - printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n", - dev->name, ll->rdp); + netdev_err(dev, "transmit timed out, status %04x, reset\n", ll->rdp); lance_reset(dev); netif_wake_queue(dev); } -static netdev_tx_t lance_start_xmit (struct sk_buff *skb, - struct net_device *dev) +static netdev_tx_t lance_start_xmit(struct sk_buff *skb, + struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); volatile struct lance_regs *ll = lp->ll; @@ -562,33 +547,33 @@ static netdev_tx_t lance_start_xmit (struct sk_buff *skb, local_irq_save(flags); - if (!TX_BUFFS_AVAIL){ + if (!lance_tx_buffs_avail(lp)) { local_irq_restore(flags); return NETDEV_TX_LOCKED; } -#ifdef DEBUG_DRIVER +#ifdef DEBUG /* dump the packet */ print_hex_dump(KERN_DEBUG, "skb->data: ", DUMP_PREFIX_NONE, 16, 1, skb->data, 64, true); #endif entry = lp->tx_new & lp->tx_ring_mod_mask; - ib->btx_ring [entry].length = (-skblen) | 0xf000; - ib->btx_ring [entry].misc = 0; + ib->btx_ring[entry].length = (-skblen) | 0xf000; + ib->btx_ring[entry].misc = 0; - skb_copy_from_linear_data(skb, (void *)&ib->tx_buf [entry][0], skblen); + skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen); /* Now, give the packet to the lance */ - ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN); + ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN); lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask; dev->stats.tx_bytes += skblen; - if (TX_BUFFS_AVAIL <= 0) + if (lance_tx_buffs_avail(lp) <= 0) netif_stop_queue(dev); /* Kick the lance: transmit now */ ll->rdp = LE_C0_INEA | LE_C0_TDMD; - dev_kfree_skb (skb); + dev_kfree_skb(skb); local_irq_restore(flags); @@ -596,40 +581,33 @@ static netdev_tx_t lance_start_xmit (struct sk_buff *skb, } /* taken from the depca driver */ -static void lance_load_multicast (struct net_device *dev) +static void lance_load_multicast(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); volatile struct lance_init_block *ib = lp->init_block; volatile u16 *mcast_table = (u16 *)&ib->filter; struct netdev_hw_addr *ha; - char *addrs; u32 crc; /* set all multicast bits */ - if (dev->flags & IFF_ALLMULTI){ - ib->filter [0] = 0xffffffff; - ib->filter [1] = 0xffffffff; + if (dev->flags & IFF_ALLMULTI) { + ib->filter[0] = 0xffffffff; + ib->filter[1] = 0xffffffff; return; } /* clear the multicast filter */ - ib->filter [0] = 0; - ib->filter [1] = 0; + ib->filter[0] = 0; + ib->filter[1] = 0; /* Add addresses */ netdev_for_each_mc_addr(ha, dev) { - addrs = ha->addr; - - /* multicast address? */ - if (!(*addrs & 1)) - continue; - - crc = ether_crc_le(6, addrs); + crc = ether_crc_le(6, ha->addr); crc = crc >> 26; - mcast_table [crc >> 4] |= 1 << (crc & 0xf); + mcast_table[crc >> 4] |= 1 << (crc & 0xf); } } -static void lance_set_multicast (struct net_device *dev) +static void lance_set_multicast(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); volatile struct lance_init_block *ib = lp->init_block; @@ -648,16 +626,16 @@ static void lance_set_multicast (struct net_device *dev) ll->rap = LE_CSR0; ll->rdp = LE_C0_STOP; - lance_init_ring (dev); + lance_init_ring(dev); if (dev->flags & IFF_PROMISC) { ib->mode |= LE_MO_PROM; } else { ib->mode &= ~LE_MO_PROM; - lance_load_multicast (dev); + lance_load_multicast(dev); } - load_csrs (lp); - init_restart_lance (lp); + load_csrs(lp); + init_restart_lance(lp); netif_wake_queue(dev); } @@ -697,14 +675,12 @@ static int __devinit a2065_init_one(struct zorro_dev *z, { struct net_device *dev; struct lance_private *priv; - unsigned long board, base_addr, mem_start; + unsigned long board = z->resource.start; + unsigned long base_addr = board + A2065_LANCE; + unsigned long mem_start = board + A2065_RAM; struct resource *r1, *r2; int err; - board = z->resource.start; - base_addr = board+A2065_LANCE; - mem_start = board+A2065_RAM; - r1 = request_mem_region(base_addr, sizeof(struct lance_regs), "Am7990"); if (!r1) @@ -735,12 +711,12 @@ static int __devinit a2065_init_one(struct zorro_dev *z, dev->dev_addr[1] = 0x00; dev->dev_addr[2] = 0x9f; } - dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff; - dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff; + dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff; + dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff; dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff; dev->base_addr = ZTWO_VADDR(base_addr); dev->mem_start = ZTWO_VADDR(mem_start); - dev->mem_end = dev->mem_start+A2065_RAM_SIZE; + dev->mem_end = dev->mem_start + A2065_RAM_SIZE; priv->ll = (volatile struct lance_regs *)dev->base_addr; priv->init_block = (struct lance_init_block *)dev->mem_start; @@ -760,7 +736,7 @@ static int __devinit a2065_init_one(struct zorro_dev *z, init_timer(&priv->multicast_timer); priv->multicast_timer.data = (unsigned long) dev; priv->multicast_timer.function = - (void (*)(unsigned long)) &lance_set_multicast; + (void (*)(unsigned long))lance_set_multicast; err = register_netdev(dev); if (err) { @@ -771,8 +747,8 @@ static int __devinit a2065_init_one(struct zorro_dev *z, } zorro_set_drvdata(z, dev); - printk(KERN_INFO "%s: A2065 at 0x%08lx, Ethernet Address " - "%pM\n", dev->name, board, dev->dev_addr); + netdev_info(dev, "A2065 at 0x%08lx, Ethernet Address %pM\n", + board, dev->dev_addr); return 0; } diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c index 5181e9322119..f07b2e980fbc 100644 --- a/drivers/net/ac3200.c +++ b/drivers/net/ac3200.c @@ -32,6 +32,7 @@ static const char version[] = #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <asm/system.h> #include <asm/io.h> diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index d7c1bfe4b6ec..536038b22710 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -69,10 +69,7 @@ #include <linux/firmware.h> #include <linux/slab.h> #include <linux/prefetch.h> - -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #include <linux/if_vlan.h> -#endif #ifdef SIOCETHTOOL #include <linux/ethtool.h> @@ -171,15 +168,6 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl); #define BOARD_IDX_STATIC 0 #define BOARD_IDX_OVERFLOW -1 -#if (defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)) && \ - defined(NETIF_F_HW_VLAN_RX) -#define ACENIC_DO_VLAN 1 -#define ACE_RCB_VLAN_FLAG RCB_FLG_VLAN_ASSIST -#else -#define ACENIC_DO_VLAN 0 -#define ACE_RCB_VLAN_FLAG 0 -#endif - #include "acenic.h" /* @@ -465,9 +453,6 @@ static const struct net_device_ops ace_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = ace_set_mac_addr, .ndo_change_mtu = ace_change_mtu, -#if ACENIC_DO_VLAN - .ndo_vlan_rx_register = ace_vlan_rx_register, -#endif }; static int __devinit acenic_probe_one(struct pci_dev *pdev, @@ -491,9 +476,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev, ap->name = pci_name(pdev); dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; -#if ACENIC_DO_VLAN dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif dev->watchdog_timeo = 5*HZ; @@ -1248,7 +1231,7 @@ static int __devinit ace_init(struct net_device *dev) set_aceaddr(&info->rx_std_ctrl.rngptr, ap->rx_ring_base_dma); info->rx_std_ctrl.max_len = ACE_STD_BUFSIZE; info->rx_std_ctrl.flags = - RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG; + RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST; memset(ap->rx_std_ring, 0, RX_STD_RING_ENTRIES * sizeof(struct rx_desc)); @@ -1264,7 +1247,7 @@ static int __devinit ace_init(struct net_device *dev) (sizeof(struct rx_desc) * RX_STD_RING_ENTRIES))); info->rx_jumbo_ctrl.max_len = 0; info->rx_jumbo_ctrl.flags = - RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG; + RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST; memset(ap->rx_jumbo_ring, 0, RX_JUMBO_RING_ENTRIES * sizeof(struct rx_desc)); @@ -1286,7 +1269,7 @@ static int __devinit ace_init(struct net_device *dev) RX_JUMBO_RING_ENTRIES)))); info->rx_mini_ctrl.max_len = ACE_MINI_SIZE; info->rx_mini_ctrl.flags = - RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR|ACE_RCB_VLAN_FLAG; + RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR|RCB_FLG_VLAN_ASSIST; for (i = 0; i < RX_MINI_RING_ENTRIES; i++) ap->rx_mini_ring[i].flags = @@ -1332,7 +1315,7 @@ static int __devinit ace_init(struct net_device *dev) } info->tx_ctrl.max_len = ACE_TX_RING_ENTRIES(ap); - tmp = RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG; + tmp = RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST; /* * The Tigon I does not like having the TX ring in host memory ;-( @@ -1674,7 +1657,7 @@ static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs) struct rx_desc *rd; dma_addr_t mapping; - skb = alloc_skb(ACE_STD_BUFSIZE + NET_IP_ALIGN, GFP_ATOMIC); + skb = dev_alloc_skb(ACE_STD_BUFSIZE + NET_IP_ALIGN); if (!skb) break; @@ -1735,7 +1718,7 @@ static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs) struct rx_desc *rd; dma_addr_t mapping; - skb = alloc_skb(ACE_MINI_BUFSIZE + NET_IP_ALIGN, GFP_ATOMIC); + skb = dev_alloc_skb(ACE_MINI_BUFSIZE + NET_IP_ALIGN); if (!skb) break; @@ -1791,7 +1774,7 @@ static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs) struct rx_desc *rd; dma_addr_t mapping; - skb = alloc_skb(ACE_JUMBO_BUFSIZE + NET_IP_ALIGN, GFP_ATOMIC); + skb = dev_alloc_skb(ACE_JUMBO_BUFSIZE + NET_IP_ALIGN); if (!skb) break; @@ -2038,12 +2021,9 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm) } /* send it up */ -#if ACENIC_DO_VLAN - if (ap->vlgrp && (bd_flags & BD_FLG_VLAN_TAG)) { - vlan_hwaccel_rx(skb, ap->vlgrp, retdesc->vlan); - } else -#endif - netif_rx(skb); + if ((bd_flags & BD_FLG_VLAN_TAG)) + __vlan_hwaccel_put_tag(skb, retdesc->vlan); + netif_rx(skb); dev->stats.rx_packets++; dev->stats.rx_bytes += retdesc->size; @@ -2262,24 +2242,6 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } - -#if ACENIC_DO_VLAN -static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) -{ - struct ace_private *ap = netdev_priv(dev); - unsigned long flags; - - local_irq_save(flags); - ace_mask_irq(dev); - - ap->vlgrp = grp; - - ace_unmask_irq(dev); - local_irq_restore(flags); -} -#endif /* ACENIC_DO_VLAN */ - - static int ace_open(struct net_device *dev) { struct ace_private *ap = netdev_priv(dev); @@ -2449,16 +2411,12 @@ ace_load_tx_bd(struct ace_private *ap, struct tx_desc *desc, u64 addr, writel(addr >> 32, &io->addr.addrhi); writel(addr & 0xffffffff, &io->addr.addrlo); writel(flagsize, &io->flagsize); -#if ACENIC_DO_VLAN writel(vlan_tag, &io->vlanres); -#endif } else { desc->addr.addrhi = addr >> 32; desc->addr.addrlo = addr; desc->flagsize = flagsize; -#if ACENIC_DO_VLAN desc->vlanres = vlan_tag; -#endif } } @@ -2486,12 +2444,10 @@ restart: flagsize = (skb->len << 16) | (BD_FLG_END); if (skb->ip_summed == CHECKSUM_PARTIAL) flagsize |= BD_FLG_TCP_UDP_SUM; -#if ACENIC_DO_VLAN if (vlan_tx_tag_present(skb)) { flagsize |= BD_FLG_VLAN_TAG; vlan_tag = vlan_tx_tag_get(skb); } -#endif desc = ap->tx_ring + idx; idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap); @@ -2509,12 +2465,10 @@ restart: flagsize = (skb_headlen(skb) << 16); if (skb->ip_summed == CHECKSUM_PARTIAL) flagsize |= BD_FLG_TCP_UDP_SUM; -#if ACENIC_DO_VLAN if (vlan_tx_tag_present(skb)) { flagsize |= BD_FLG_VLAN_TAG; vlan_tag = vlan_tx_tag_get(skb); } -#endif ace_load_tx_bd(ap, ap->tx_ring + idx, mapping, flagsize, vlan_tag); diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h index 0681da7e8753..f67dc9b0eb80 100644 --- a/drivers/net/acenic.h +++ b/drivers/net/acenic.h @@ -1,5 +1,6 @@ #ifndef _ACENIC_H_ #define _ACENIC_H_ +#include <linux/interrupt.h> /* @@ -664,10 +665,6 @@ struct ace_private struct rx_desc *rx_mini_ring; struct rx_desc *rx_return_ring; -#if ACENIC_DO_VLAN - struct vlan_group *vlgrp; -#endif - int tasklet_pending, jumbo; struct tasklet_struct ace_tasklet; @@ -789,8 +786,5 @@ static void ace_free_descriptors(struct net_device *dev); static void ace_init_cleanup(struct net_device *dev); static struct net_device_stats *ace_get_stats(struct net_device *dev); static int read_eeprom_byte(struct net_device *dev, unsigned long offset); -#if ACENIC_DO_VLAN -static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp); -#endif #endif /* _ACENIC_H_ */ diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 241b185e6569..78002ef9c0e5 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -75,6 +75,7 @@ Revision History: #include <linux/compiler.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/pci.h> #include <linux/netdevice.h> @@ -660,15 +661,6 @@ static void amd8111e_free_ring(struct amd8111e_priv* lp) } } -#if AMD8111E_VLAN_TAG_USED -/* -This is the receive indication function for packets with vlan tag. -*/ -static int amd8111e_vlan_rx(struct amd8111e_priv *lp, struct sk_buff *skb, u16 vlan_tag) -{ - return vlan_hwaccel_receive_skb(skb, lp->vlgrp,vlan_tag); -} -#endif /* This function will free all the transmit skbs that are actually transmitted by the device. It will check the ownership of the skb before freeing the skb. @@ -763,7 +755,7 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget) #if AMD8111E_VLAN_TAG_USED vtag = status & TT_MASK; /*MAC will strip vlan tag*/ - if(lp->vlgrp != NULL && vtag !=0) + if (vtag != 0) min_pkt_len =MIN_PKT_LEN - 4; else #endif @@ -798,12 +790,12 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget) skb->protocol = eth_type_trans(skb, dev); #if AMD8111E_VLAN_TAG_USED - if(lp->vlgrp != NULL && (vtag == TT_VLAN_TAGGED)){ - amd8111e_vlan_rx(lp, skb, - le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info)); - } else + if (vtag == TT_VLAN_TAGGED){ + u16 vlan_tag = le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info); + __vlan_hwaccel_put_tag(skb, vlan_tag); + } #endif - netif_receive_skb(skb); + netif_receive_skb(skb); /*COAL update rx coalescing parameters*/ lp->coal_conf.rx_packets++; lp->coal_conf.rx_bytes += pkt_len; @@ -1597,16 +1589,6 @@ static int amd8111e_change_mtu(struct net_device *dev, int new_mtu) return err; } -#if AMD8111E_VLAN_TAG_USED -static void amd8111e_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) -{ - struct amd8111e_priv *lp = netdev_priv(dev); - spin_lock_irq(&lp->lock); - lp->vlgrp = grp; - spin_unlock_irq(&lp->lock); -} -#endif - static int amd8111e_enable_magicpkt(struct amd8111e_priv* lp) { writel( VAL1|MPPLBA, lp->mmio + CMD3); @@ -1821,9 +1803,6 @@ static const struct net_device_ops amd8111e_netdev_ops = { .ndo_set_mac_address = amd8111e_set_mac_address, .ndo_do_ioctl = amd8111e_ioctl, .ndo_change_mtu = amd8111e_change_mtu, -#if AMD8111E_VLAN_TAG_USED - .ndo_vlan_rx_register = amd8111e_vlan_rx_register, -#endif #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = amd8111e_poll, #endif @@ -1958,7 +1937,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, IPG_CONVERGE_JIFFIES; lp->ipg_data.ipg = DEFAULT_IPG; lp->ipg_data.ipg_state = CSTATE; - }; + } /* display driver and device information */ diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h index b5926af03a7e..2ff2e7a12dd0 100644 --- a/drivers/net/amd8111e.h +++ b/drivers/net/amd8111e.h @@ -783,9 +783,6 @@ struct amd8111e_priv{ struct net_device *next; int mii; struct mii_if_info mii_if; -#if AMD8111E_VLAN_TAG_USED - struct vlan_group *vlgrp; -#endif char opened; unsigned int drv_rx_errors; struct amd8111e_coalesce_conf coal_conf; diff --git a/drivers/net/apne.c b/drivers/net/apne.c index 2fe60f168108..547737340cbb 100644 --- a/drivers/net/apne.c +++ b/drivers/net/apne.c @@ -36,6 +36,7 @@ #include <linux/delay.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> +#include <linux/interrupt.h> #include <linux/jiffies.h> #include <asm/system.h> diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c index e69eead12ec7..34ffb5422628 100644 --- a/drivers/net/appletalk/ltpc.c +++ b/drivers/net/appletalk/ltpc.c @@ -652,9 +652,9 @@ static int do_write(struct net_device *dev, void *cbuf, int cbuflen, int ret; if(i) { - qels[i].cbuf = (unsigned char *) cbuf; + qels[i].cbuf = cbuf; qels[i].cbuflen = cbuflen; - qels[i].dbuf = (unsigned char *) dbuf; + qels[i].dbuf = dbuf; qels[i].dbuflen = dbuflen; qels[i].QWrite = 1; qels[i].mailbox = i; /* this should be initted rather */ @@ -676,9 +676,9 @@ static int do_read(struct net_device *dev, void *cbuf, int cbuflen, int ret; if(i) { - qels[i].cbuf = (unsigned char *) cbuf; + qels[i].cbuf = cbuf; qels[i].cbuflen = cbuflen; - qels[i].dbuf = (unsigned char *) dbuf; + qels[i].dbuf = dbuf; qels[i].dbuflen = dbuflen; qels[i].QWrite = 0; qels[i].mailbox = i; /* this should be initted rather */ diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 9efbbbae47ca..25197b698dd6 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -32,6 +32,7 @@ #include <linux/netdevice.h> #include <linux/bootmem.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <asm/io.h> #include <linux/arcdevice.h> diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index 37272827ee55..45c61a2c5fbd 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -34,6 +34,7 @@ #include <linux/delay.h> #include <linux/netdevice.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/bootmem.h> #include <linux/arcdevice.h> #include <linux/com20020.h> diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 48a1dbf01e60..d427493997b6 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -34,6 +34,7 @@ #include <linux/errno.h> #include <linux/netdevice.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/pci.h> #include <linux/arcdevice.h> #include <linux/com20020.h> diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index c9e459400ff9..7bfb91f32857 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -33,6 +33,7 @@ #include <linux/delay.h> #include <linux/netdevice.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/arcdevice.h> #include <linux/com20020.h> diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index eb27976dab37..487d780ebbdf 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -33,6 +33,7 @@ #include <linux/netdevice.h> #include <linux/bootmem.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <asm/io.h> #include <linux/arcdevice.h> diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index f3b46f71e293..b80fbe40aa0e 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -27,6 +27,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/delay.h> #include <linux/netdevice.h> diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index b7f45cd756a2..7ed78f402042 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -34,6 +34,9 @@ * - an MC68230 Parallel Interface/Timer configured as 2 parallel ports */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +/*#define DEBUG*/ + #include <linux/module.h> #include <linux/stddef.h> #include <linux/kernel.h> @@ -54,802 +57,734 @@ #include "ariadne.h" - #ifdef ARIADNE_DEBUG int ariadne_debug = ARIADNE_DEBUG; #else int ariadne_debug = 1; #endif +/* Macros to Fix Endianness problems */ - /* - * Macros to Fix Endianness problems - */ - - /* Swap the Bytes in a WORD */ -#define swapw(x) (((x>>8)&0x00ff)|((x<<8)&0xff00)) - /* Get the Low BYTE in a WORD */ -#define lowb(x) (x&0xff) - /* Get the Swapped High WORD in a LONG */ -#define swhighw(x) ((((x)>>8)&0xff00)|(((x)>>24)&0x00ff)) - /* Get the Swapped Low WORD in a LONG */ -#define swloww(x) ((((x)<<8)&0xff00)|(((x)>>8)&0x00ff)) +/* Swap the Bytes in a WORD */ +#define swapw(x) (((x >> 8) & 0x00ff) | ((x << 8) & 0xff00)) +/* Get the Low BYTE in a WORD */ +#define lowb(x) (x & 0xff) +/* Get the Swapped High WORD in a LONG */ +#define swhighw(x) ((((x) >> 8) & 0xff00) | (((x) >> 24) & 0x00ff)) +/* Get the Swapped Low WORD in a LONG */ +#define swloww(x) ((((x) << 8) & 0xff00) | (((x) >> 8) & 0x00ff)) - - /* - * Transmit/Receive Ring Definitions - */ +/* Transmit/Receive Ring Definitions */ #define TX_RING_SIZE 5 #define RX_RING_SIZE 16 #define PKT_BUF_SIZE 1520 - - /* - * Private Device Data - */ +/* Private Device Data */ struct ariadne_private { - volatile struct TDRE *tx_ring[TX_RING_SIZE]; - volatile struct RDRE *rx_ring[RX_RING_SIZE]; - volatile u_short *tx_buff[TX_RING_SIZE]; - volatile u_short *rx_buff[RX_RING_SIZE]; - int cur_tx, cur_rx; /* The next free ring entry */ - int dirty_tx; /* The ring entries to be free()ed. */ - char tx_full; + volatile struct TDRE *tx_ring[TX_RING_SIZE]; + volatile struct RDRE *rx_ring[RX_RING_SIZE]; + volatile u_short *tx_buff[TX_RING_SIZE]; + volatile u_short *rx_buff[RX_RING_SIZE]; + int cur_tx, cur_rx; /* The next free ring entry */ + int dirty_tx; /* The ring entries to be free()ed */ + char tx_full; }; - - /* - * Structure Created in the Ariadne's RAM Buffer - */ +/* Structure Created in the Ariadne's RAM Buffer */ struct lancedata { - struct TDRE tx_ring[TX_RING_SIZE]; - struct RDRE rx_ring[RX_RING_SIZE]; - u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)]; - u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)]; + struct TDRE tx_ring[TX_RING_SIZE]; + struct RDRE rx_ring[RX_RING_SIZE]; + u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)]; + u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)]; }; -static int ariadne_open(struct net_device *dev); -static void ariadne_init_ring(struct net_device *dev); -static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb, - struct net_device *dev); -static void ariadne_tx_timeout(struct net_device *dev); -static int ariadne_rx(struct net_device *dev); -static void ariadne_reset(struct net_device *dev); -static irqreturn_t ariadne_interrupt(int irq, void *data); -static int ariadne_close(struct net_device *dev); -static struct net_device_stats *ariadne_get_stats(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); - - static void memcpyw(volatile u_short *dest, u_short *src, int len) { - while (len >= 2) { - *(dest++) = *(src++); - len -= 2; - } - if (len == 1) - *dest = (*(u_char *)src)<<8; + while (len >= 2) { + *(dest++) = *(src++); + len -= 2; + } + if (len == 1) + *dest = (*(u_char *)src) << 8; } +static void ariadne_init_ring(struct net_device *dev) +{ + struct ariadne_private *priv = netdev_priv(dev); + volatile struct lancedata *lancedata = (struct lancedata *)dev->mem_start; + int i; -static int __devinit ariadne_init_one(struct zorro_dev *z, - const struct zorro_device_id *ent); -static void __devexit ariadne_remove_one(struct zorro_dev *z); - - -static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = { - { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE }, - { 0 } -}; -MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl); + netif_stop_queue(dev); -static struct zorro_driver ariadne_driver = { - .name = "ariadne", - .id_table = ariadne_zorro_tbl, - .probe = ariadne_init_one, - .remove = __devexit_p(ariadne_remove_one), -}; + priv->tx_full = 0; + priv->cur_rx = priv->cur_tx = 0; + priv->dirty_tx = 0; + + /* Set up TX Ring */ + for (i = 0; i < TX_RING_SIZE; i++) { + volatile struct TDRE *t = &lancedata->tx_ring[i]; + t->TMD0 = swloww(ARIADNE_RAM + + offsetof(struct lancedata, tx_buff[i])); + t->TMD1 = swhighw(ARIADNE_RAM + + offsetof(struct lancedata, tx_buff[i])) | + TF_STP | TF_ENP; + t->TMD2 = swapw((u_short)-PKT_BUF_SIZE); + t->TMD3 = 0; + priv->tx_ring[i] = &lancedata->tx_ring[i]; + priv->tx_buff[i] = lancedata->tx_buff[i]; + netdev_dbg(dev, "TX Entry %2d at %p, Buf at %p\n", + i, &lancedata->tx_ring[i], lancedata->tx_buff[i]); + } -static const struct net_device_ops ariadne_netdev_ops = { - .ndo_open = ariadne_open, - .ndo_stop = ariadne_close, - .ndo_start_xmit = ariadne_start_xmit, - .ndo_tx_timeout = ariadne_tx_timeout, - .ndo_get_stats = ariadne_get_stats, - .ndo_set_multicast_list = set_multicast_list, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, -}; + /* Set up RX Ring */ + for (i = 0; i < RX_RING_SIZE; i++) { + volatile struct RDRE *r = &lancedata->rx_ring[i]; + r->RMD0 = swloww(ARIADNE_RAM + + offsetof(struct lancedata, rx_buff[i])); + r->RMD1 = swhighw(ARIADNE_RAM + + offsetof(struct lancedata, rx_buff[i])) | + RF_OWN; + r->RMD2 = swapw((u_short)-PKT_BUF_SIZE); + r->RMD3 = 0x0000; + priv->rx_ring[i] = &lancedata->rx_ring[i]; + priv->rx_buff[i] = lancedata->rx_buff[i]; + netdev_dbg(dev, "RX Entry %2d at %p, Buf at %p\n", + i, &lancedata->rx_ring[i], lancedata->rx_buff[i]); + } +} -static int __devinit ariadne_init_one(struct zorro_dev *z, - const struct zorro_device_id *ent) +static int ariadne_rx(struct net_device *dev) { - unsigned long board = z->resource.start; - unsigned long base_addr = board+ARIADNE_LANCE; - unsigned long mem_start = board+ARIADNE_RAM; - struct resource *r1, *r2; - struct net_device *dev; - struct ariadne_private *priv; - int err; - - r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960"); - if (!r1) - return -EBUSY; - r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM"); - if (!r2) { - release_mem_region(base_addr, sizeof(struct Am79C960)); - return -EBUSY; - } - - dev = alloc_etherdev(sizeof(struct ariadne_private)); - if (dev == NULL) { - release_mem_region(base_addr, sizeof(struct Am79C960)); - release_mem_region(mem_start, ARIADNE_RAM_SIZE); - return -ENOMEM; - } - - priv = netdev_priv(dev); - - r1->name = dev->name; - r2->name = dev->name; - - dev->dev_addr[0] = 0x00; - dev->dev_addr[1] = 0x60; - dev->dev_addr[2] = 0x30; - dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff; - dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff; - dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff; - dev->base_addr = ZTWO_VADDR(base_addr); - dev->mem_start = ZTWO_VADDR(mem_start); - dev->mem_end = dev->mem_start+ARIADNE_RAM_SIZE; - - dev->netdev_ops = &ariadne_netdev_ops; - dev->watchdog_timeo = 5*HZ; - - err = register_netdev(dev); - if (err) { - release_mem_region(base_addr, sizeof(struct Am79C960)); - release_mem_region(mem_start, ARIADNE_RAM_SIZE); - free_netdev(dev); - return err; - } - zorro_set_drvdata(z, dev); + struct ariadne_private *priv = netdev_priv(dev); + int entry = priv->cur_rx % RX_RING_SIZE; + int i; - printk(KERN_INFO "%s: Ariadne at 0x%08lx, Ethernet Address %pM\n", - dev->name, board, dev->dev_addr); + /* If we own the next entry, it's a new packet. Send it up */ + while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) { + int status = lowb(priv->rx_ring[entry]->RMD1); + + if (status != (RF_STP | RF_ENP)) { /* There was an error */ + /* There is a tricky error noted by + * John Murphy <murf@perftech.com> to Russ Nelson: + * Even with full-sized buffers it's possible for a + * jabber packet to use two buffers, with only the + * last correctly noting the error + */ + /* Only count a general error at the end of a packet */ + if (status & RF_ENP) + dev->stats.rx_errors++; + if (status & RF_FRAM) + dev->stats.rx_frame_errors++; + if (status & RF_OFLO) + dev->stats.rx_over_errors++; + if (status & RF_CRC) + dev->stats.rx_crc_errors++; + if (status & RF_BUFF) + dev->stats.rx_fifo_errors++; + priv->rx_ring[entry]->RMD1 &= 0xff00 | RF_STP | RF_ENP; + } else { + /* Malloc up new buffer, compatible with net-3 */ + short pkt_len = swapw(priv->rx_ring[entry]->RMD3); + struct sk_buff *skb; + + skb = dev_alloc_skb(pkt_len + 2); + if (skb == NULL) { + netdev_warn(dev, "Memory squeeze, deferring packet\n"); + for (i = 0; i < RX_RING_SIZE; i++) + if (lowb(priv->rx_ring[(entry + i) % RX_RING_SIZE]->RMD1) & RF_OWN) + break; + + if (i > RX_RING_SIZE - 2) { + dev->stats.rx_dropped++; + priv->rx_ring[entry]->RMD1 |= RF_OWN; + priv->cur_rx++; + } + break; + } + + + skb_reserve(skb, 2); /* 16 byte align */ + skb_put(skb, pkt_len); /* Make room */ + skb_copy_to_linear_data(skb, + (const void *)priv->rx_buff[entry], + pkt_len); + skb->protocol = eth_type_trans(skb, dev); + netdev_dbg(dev, "RX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n", + ((u_short *)skb->data)[6], + skb->data + 6, skb->data, + (int)skb->data, (int)skb->len); + + netif_rx(skb); + dev->stats.rx_packets++; + dev->stats.rx_bytes += pkt_len; + } - return 0; -} + priv->rx_ring[entry]->RMD1 |= RF_OWN; + entry = (++priv->cur_rx) % RX_RING_SIZE; + } + priv->cur_rx = priv->cur_rx % RX_RING_SIZE; -static int ariadne_open(struct net_device *dev) -{ - volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr; - u_short in; - u_long version; - int i; - - /* Reset the LANCE */ - in = lance->Reset; - - /* Stop the LANCE */ - lance->RAP = CSR0; /* PCnet-ISA Controller Status */ - lance->RDP = STOP; - - /* Check the LANCE version */ - lance->RAP = CSR88; /* Chip ID */ - version = swapw(lance->RDP); - lance->RAP = CSR89; /* Chip ID */ - version |= swapw(lance->RDP)<<16; - if ((version & 0x00000fff) != 0x00000003) { - printk(KERN_WARNING "ariadne_open: Couldn't find AMD Ethernet Chip\n"); - return -EAGAIN; - } - if ((version & 0x0ffff000) != 0x00003000) { - printk(KERN_WARNING "ariadne_open: Couldn't find Am79C960 (Wrong part " - "number = %ld)\n", (version & 0x0ffff000)>>12); - return -EAGAIN; - } -#if 0 - printk(KERN_DEBUG "ariadne_open: Am79C960 (PCnet-ISA) Revision %ld\n", - (version & 0xf0000000)>>28); -#endif + /* We should check that at least two ring entries are free. + * If not, we should free one and mark stats->rx_dropped++ + */ - ariadne_init_ring(dev); - - /* Miscellaneous Stuff */ - lance->RAP = CSR3; /* Interrupt Masks and Deferral Control */ - lance->RDP = 0x0000; - lance->RAP = CSR4; /* Test and Features Control */ - lance->RDP = DPOLL|APAD_XMT|MFCOM|RCVCCOM|TXSTRTM|JABM; - - /* Set the Multicast Table */ - lance->RAP = CSR8; /* Logical Address Filter, LADRF[15:0] */ - lance->RDP = 0x0000; - lance->RAP = CSR9; /* Logical Address Filter, LADRF[31:16] */ - lance->RDP = 0x0000; - lance->RAP = CSR10; /* Logical Address Filter, LADRF[47:32] */ - lance->RDP = 0x0000; - lance->RAP = CSR11; /* Logical Address Filter, LADRF[63:48] */ - lance->RDP = 0x0000; - - /* Set the Ethernet Hardware Address */ - lance->RAP = CSR12; /* Physical Address Register, PADR[15:0] */ - lance->RDP = ((u_short *)&dev->dev_addr[0])[0]; - lance->RAP = CSR13; /* Physical Address Register, PADR[31:16] */ - lance->RDP = ((u_short *)&dev->dev_addr[0])[1]; - lance->RAP = CSR14; /* Physical Address Register, PADR[47:32] */ - lance->RDP = ((u_short *)&dev->dev_addr[0])[2]; - - /* Set the Init Block Mode */ - lance->RAP = CSR15; /* Mode Register */ - lance->RDP = 0x0000; - - /* Set the Transmit Descriptor Ring Pointer */ - lance->RAP = CSR30; /* Base Address of Transmit Ring */ - lance->RDP = swloww(ARIADNE_RAM+offsetof(struct lancedata, tx_ring)); - lance->RAP = CSR31; /* Base Address of transmit Ring */ - lance->RDP = swhighw(ARIADNE_RAM+offsetof(struct lancedata, tx_ring)); - - /* Set the Receive Descriptor Ring Pointer */ - lance->RAP = CSR24; /* Base Address of Receive Ring */ - lance->RDP = swloww(ARIADNE_RAM+offsetof(struct lancedata, rx_ring)); - lance->RAP = CSR25; /* Base Address of Receive Ring */ - lance->RDP = swhighw(ARIADNE_RAM+offsetof(struct lancedata, rx_ring)); - - /* Set the Number of RX and TX Ring Entries */ - lance->RAP = CSR76; /* Receive Ring Length */ - lance->RDP = swapw(((u_short)-RX_RING_SIZE)); - lance->RAP = CSR78; /* Transmit Ring Length */ - lance->RDP = swapw(((u_short)-TX_RING_SIZE)); - - /* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */ - lance->RAP = ISACSR2; /* Miscellaneous Configuration */ - lance->IDP = ASEL; - - /* LED Control */ - lance->RAP = ISACSR5; /* LED1 Status */ - lance->IDP = PSE|XMTE; - lance->RAP = ISACSR6; /* LED2 Status */ - lance->IDP = PSE|COLE; - lance->RAP = ISACSR7; /* LED3 Status */ - lance->IDP = PSE|RCVE; - - netif_start_queue(dev); - - i = request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, IRQF_SHARED, - dev->name, dev); - if (i) return i; - - lance->RAP = CSR0; /* PCnet-ISA Controller Status */ - lance->RDP = INEA|STRT; - - return 0; + return 0; } - -static void ariadne_init_ring(struct net_device *dev) +static irqreturn_t ariadne_interrupt(int irq, void *data) { - struct ariadne_private *priv = netdev_priv(dev); - volatile struct lancedata *lancedata = (struct lancedata *)dev->mem_start; - int i; - - netif_stop_queue(dev); - - priv->tx_full = 0; - priv->cur_rx = priv->cur_tx = 0; - priv->dirty_tx = 0; - - /* Set up TX Ring */ - for (i = 0; i < TX_RING_SIZE; i++) { - volatile struct TDRE *t = &lancedata->tx_ring[i]; - t->TMD0 = swloww(ARIADNE_RAM+offsetof(struct lancedata, tx_buff[i])); - t->TMD1 = swhighw(ARIADNE_RAM+offsetof(struct lancedata, tx_buff[i])) | - TF_STP | TF_ENP; - t->TMD2 = swapw((u_short)-PKT_BUF_SIZE); - t->TMD3 = 0; - priv->tx_ring[i] = &lancedata->tx_ring[i]; - priv->tx_buff[i] = lancedata->tx_buff[i]; -#if 0 - printk(KERN_DEBUG "TX Entry %2d at %p, Buf at %p\n", i, - &lancedata->tx_ring[i], lancedata->tx_buff[i]); -#endif - } - - /* Set up RX Ring */ - for (i = 0; i < RX_RING_SIZE; i++) { - volatile struct RDRE *r = &lancedata->rx_ring[i]; - r->RMD0 = swloww(ARIADNE_RAM+offsetof(struct lancedata, rx_buff[i])); - r->RMD1 = swhighw(ARIADNE_RAM+offsetof(struct lancedata, rx_buff[i])) | - RF_OWN; - r->RMD2 = swapw((u_short)-PKT_BUF_SIZE); - r->RMD3 = 0x0000; - priv->rx_ring[i] = &lancedata->rx_ring[i]; - priv->rx_buff[i] = lancedata->rx_buff[i]; -#if 0 - printk(KERN_DEBUG "RX Entry %2d at %p, Buf at %p\n", i, - &lancedata->rx_ring[i], lancedata->rx_buff[i]); + struct net_device *dev = (struct net_device *)data; + volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr; + struct ariadne_private *priv; + int csr0, boguscnt; + int handled = 0; + + lance->RAP = CSR0; /* PCnet-ISA Controller Status */ + + if (!(lance->RDP & INTR)) /* Check if any interrupt has been */ + return IRQ_NONE; /* generated by the board */ + + priv = netdev_priv(dev); + + boguscnt = 10; + while ((csr0 = lance->RDP) & (ERR | RINT | TINT) && --boguscnt >= 0) { + /* Acknowledge all of the current interrupt sources ASAP */ + lance->RDP = csr0 & ~(INEA | TDMD | STOP | STRT | INIT); + +#ifdef DEBUG + if (ariadne_debug > 5) { + netdev_dbg(dev, "interrupt csr0=%#02x new csr=%#02x [", + csr0, lance->RDP); + if (csr0 & INTR) + pr_cont(" INTR"); + if (csr0 & INEA) + pr_cont(" INEA"); + if (csr0 & RXON) + pr_cont(" RXON"); + if (csr0 & TXON) + pr_cont(" TXON"); + if (csr0 & TDMD) + pr_cont(" TDMD"); + if (csr0 & STOP) + pr_cont(" STOP"); + if (csr0 & STRT) + pr_cont(" STRT"); + if (csr0 & INIT) + pr_cont(" INIT"); + if (csr0 & ERR) + pr_cont(" ERR"); + if (csr0 & BABL) + pr_cont(" BABL"); + if (csr0 & CERR) + pr_cont(" CERR"); + if (csr0 & MISS) + pr_cont(" MISS"); + if (csr0 & MERR) + pr_cont(" MERR"); + if (csr0 & RINT) + pr_cont(" RINT"); + if (csr0 & TINT) + pr_cont(" TINT"); + if (csr0 & IDON) + pr_cont(" IDON"); + pr_cont(" ]\n"); + } #endif - } -} + if (csr0 & RINT) { /* Rx interrupt */ + handled = 1; + ariadne_rx(dev); + } -static int ariadne_close(struct net_device *dev) -{ - volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr; + if (csr0 & TINT) { /* Tx-done interrupt */ + int dirty_tx = priv->dirty_tx; + + handled = 1; + while (dirty_tx < priv->cur_tx) { + int entry = dirty_tx % TX_RING_SIZE; + int status = lowb(priv->tx_ring[entry]->TMD1); + + if (status & TF_OWN) + break; /* It still hasn't been Txed */ + + priv->tx_ring[entry]->TMD1 &= 0xff00; + + if (status & TF_ERR) { + /* There was an major error, log it */ + int err_status = priv->tx_ring[entry]->TMD3; + dev->stats.tx_errors++; + if (err_status & EF_RTRY) + dev->stats.tx_aborted_errors++; + if (err_status & EF_LCAR) + dev->stats.tx_carrier_errors++; + if (err_status & EF_LCOL) + dev->stats.tx_window_errors++; + if (err_status & EF_UFLO) { + /* Ackk! On FIFO errors the Tx unit is turned off! */ + dev->stats.tx_fifo_errors++; + /* Remove this verbosity later! */ + netdev_err(dev, "Tx FIFO error! Status %04x\n", + csr0); + /* Restart the chip */ + lance->RDP = STRT; + } + } else { + if (status & (TF_MORE | TF_ONE)) + dev->stats.collisions++; + dev->stats.tx_packets++; + } + dirty_tx++; + } - netif_stop_queue(dev); +#ifndef final_version + if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) { + netdev_err(dev, "out-of-sync dirty pointer, %d vs. %d, full=%d\n", + dirty_tx, priv->cur_tx, + priv->tx_full); + dirty_tx += TX_RING_SIZE; + } +#endif - lance->RAP = CSR112; /* Missed Frame Count */ - dev->stats.rx_missed_errors = swapw(lance->RDP); - lance->RAP = CSR0; /* PCnet-ISA Controller Status */ + if (priv->tx_full && netif_queue_stopped(dev) && + dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) { + /* The ring is no longer full */ + priv->tx_full = 0; + netif_wake_queue(dev); + } - if (ariadne_debug > 1) { - printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, lance->RDP); - printk(KERN_DEBUG "%s: %lu packets missed\n", dev->name, - dev->stats.rx_missed_errors); - } + priv->dirty_tx = dirty_tx; + } - /* We stop the LANCE here -- it occasionally polls memory if we don't. */ - lance->RDP = STOP; + /* Log misc errors */ + if (csr0 & BABL) { + handled = 1; + dev->stats.tx_errors++; /* Tx babble */ + } + if (csr0 & MISS) { + handled = 1; + dev->stats.rx_errors++; /* Missed a Rx frame */ + } + if (csr0 & MERR) { + handled = 1; + netdev_err(dev, "Bus master arbitration failure, status %04x\n", + csr0); + /* Restart the chip */ + lance->RDP = STRT; + } + } - free_irq(IRQ_AMIGA_PORTS, dev); + /* Clear any other interrupt, and set interrupt enable */ + lance->RAP = CSR0; /* PCnet-ISA Controller Status */ + lance->RDP = INEA | BABL | CERR | MISS | MERR | IDON; - return 0; -} + if (ariadne_debug > 4) + netdev_dbg(dev, "exiting interrupt, csr%d=%#04x\n", + lance->RAP, lance->RDP); + return IRQ_RETVAL(handled); +} -static inline void ariadne_reset(struct net_device *dev) +static int ariadne_open(struct net_device *dev) { - volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr; - - lance->RAP = CSR0; /* PCnet-ISA Controller Status */ - lance->RDP = STOP; - ariadne_init_ring(dev); - lance->RDP = INEA|STRT; - netif_start_queue(dev); -} + volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr; + u_short in; + u_long version; + int i; + /* Reset the LANCE */ + in = lance->Reset; + + /* Stop the LANCE */ + lance->RAP = CSR0; /* PCnet-ISA Controller Status */ + lance->RDP = STOP; + + /* Check the LANCE version */ + lance->RAP = CSR88; /* Chip ID */ + version = swapw(lance->RDP); + lance->RAP = CSR89; /* Chip ID */ + version |= swapw(lance->RDP) << 16; + if ((version & 0x00000fff) != 0x00000003) { + pr_warn("Couldn't find AMD Ethernet Chip\n"); + return -EAGAIN; + } + if ((version & 0x0ffff000) != 0x00003000) { + pr_warn("Couldn't find Am79C960 (Wrong part number = %ld)\n", + (version & 0x0ffff000) >> 12); + return -EAGAIN; + } -static irqreturn_t ariadne_interrupt(int irq, void *data) -{ - struct net_device *dev = (struct net_device *)data; - volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr; - struct ariadne_private *priv; - int csr0, boguscnt; - int handled = 0; + netdev_dbg(dev, "Am79C960 (PCnet-ISA) Revision %ld\n", + (version & 0xf0000000) >> 28); - lance->RAP = CSR0; /* PCnet-ISA Controller Status */ + ariadne_init_ring(dev); - if (!(lance->RDP & INTR)) /* Check if any interrupt has been */ - return IRQ_NONE; /* generated by the board. */ + /* Miscellaneous Stuff */ + lance->RAP = CSR3; /* Interrupt Masks and Deferral Control */ + lance->RDP = 0x0000; + lance->RAP = CSR4; /* Test and Features Control */ + lance->RDP = DPOLL | APAD_XMT | MFCOM | RCVCCOM | TXSTRTM | JABM; - priv = netdev_priv(dev); + /* Set the Multicast Table */ + lance->RAP = CSR8; /* Logical Address Filter, LADRF[15:0] */ + lance->RDP = 0x0000; + lance->RAP = CSR9; /* Logical Address Filter, LADRF[31:16] */ + lance->RDP = 0x0000; + lance->RAP = CSR10; /* Logical Address Filter, LADRF[47:32] */ + lance->RDP = 0x0000; + lance->RAP = CSR11; /* Logical Address Filter, LADRF[63:48] */ + lance->RDP = 0x0000; - boguscnt = 10; - while ((csr0 = lance->RDP) & (ERR|RINT|TINT) && --boguscnt >= 0) { - /* Acknowledge all of the current interrupt sources ASAP. */ - lance->RDP = csr0 & ~(INEA|TDMD|STOP|STRT|INIT); + /* Set the Ethernet Hardware Address */ + lance->RAP = CSR12; /* Physical Address Register, PADR[15:0] */ + lance->RDP = ((u_short *)&dev->dev_addr[0])[0]; + lance->RAP = CSR13; /* Physical Address Register, PADR[31:16] */ + lance->RDP = ((u_short *)&dev->dev_addr[0])[1]; + lance->RAP = CSR14; /* Physical Address Register, PADR[47:32] */ + lance->RDP = ((u_short *)&dev->dev_addr[0])[2]; -#if 0 - if (ariadne_debug > 5) { - printk(KERN_DEBUG "%s: interrupt csr0=%#2.2x new csr=%#2.2x.", - dev->name, csr0, lance->RDP); - printk("["); - if (csr0 & INTR) - printk(" INTR"); - if (csr0 & INEA) - printk(" INEA"); - if (csr0 & RXON) - printk(" RXON"); - if (csr0 & TXON) - printk(" TXON"); - if (csr0 & TDMD) - printk(" TDMD"); - if (csr0 & STOP) - printk(" STOP"); - if (csr0 & STRT) - printk(" STRT"); - if (csr0 & INIT) - printk(" INIT"); - if (csr0 & ERR) - printk(" ERR"); - if (csr0 & BABL) - printk(" BABL"); - if (csr0 & CERR) - printk(" CERR"); - if (csr0 & MISS) - printk(" MISS"); - if (csr0 & MERR) - printk(" MERR"); - if (csr0 & RINT) - printk(" RINT"); - if (csr0 & TINT) - printk(" TINT"); - if (csr0 & IDON) - printk(" IDON"); - printk(" ]\n"); - } -#endif + /* Set the Init Block Mode */ + lance->RAP = CSR15; /* Mode Register */ + lance->RDP = 0x0000; - if (csr0 & RINT) { /* Rx interrupt */ - handled = 1; - ariadne_rx(dev); - } + /* Set the Transmit Descriptor Ring Pointer */ + lance->RAP = CSR30; /* Base Address of Transmit Ring */ + lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, tx_ring)); + lance->RAP = CSR31; /* Base Address of transmit Ring */ + lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, tx_ring)); + + /* Set the Receive Descriptor Ring Pointer */ + lance->RAP = CSR24; /* Base Address of Receive Ring */ + lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, rx_ring)); + lance->RAP = CSR25; /* Base Address of Receive Ring */ + lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, rx_ring)); + + /* Set the Number of RX and TX Ring Entries */ + lance->RAP = CSR76; /* Receive Ring Length */ + lance->RDP = swapw(((u_short)-RX_RING_SIZE)); + lance->RAP = CSR78; /* Transmit Ring Length */ + lance->RDP = swapw(((u_short)-TX_RING_SIZE)); + + /* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */ + lance->RAP = ISACSR2; /* Miscellaneous Configuration */ + lance->IDP = ASEL; + + /* LED Control */ + lance->RAP = ISACSR5; /* LED1 Status */ + lance->IDP = PSE|XMTE; + lance->RAP = ISACSR6; /* LED2 Status */ + lance->IDP = PSE|COLE; + lance->RAP = ISACSR7; /* LED3 Status */ + lance->IDP = PSE|RCVE; + + netif_start_queue(dev); + + i = request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, IRQF_SHARED, + dev->name, dev); + if (i) + return i; + + lance->RAP = CSR0; /* PCnet-ISA Controller Status */ + lance->RDP = INEA | STRT; + + return 0; +} - if (csr0 & TINT) { /* Tx-done interrupt */ - int dirty_tx = priv->dirty_tx; - - handled = 1; - while (dirty_tx < priv->cur_tx) { - int entry = dirty_tx % TX_RING_SIZE; - int status = lowb(priv->tx_ring[entry]->TMD1); - - if (status & TF_OWN) - break; /* It still hasn't been Txed */ - - priv->tx_ring[entry]->TMD1 &= 0xff00; - - if (status & TF_ERR) { - /* There was an major error, log it. */ - int err_status = priv->tx_ring[entry]->TMD3; - dev->stats.tx_errors++; - if (err_status & EF_RTRY) - dev->stats.tx_aborted_errors++; - if (err_status & EF_LCAR) - dev->stats.tx_carrier_errors++; - if (err_status & EF_LCOL) - dev->stats.tx_window_errors++; - if (err_status & EF_UFLO) { - /* Ackk! On FIFO errors the Tx unit is turned off! */ - dev->stats.tx_fifo_errors++; - /* Remove this verbosity later! */ - printk(KERN_ERR "%s: Tx FIFO error! Status %4.4x.\n", - dev->name, csr0); - /* Restart the chip. */ - lance->RDP = STRT; - } - } else { - if (status & (TF_MORE|TF_ONE)) - dev->stats.collisions++; - dev->stats.tx_packets++; - } - dirty_tx++; - } +static int ariadne_close(struct net_device *dev) +{ + volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr; -#ifndef final_version - if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) { - printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d, " - "full=%d.\n", dirty_tx, priv->cur_tx, priv->tx_full); - dirty_tx += TX_RING_SIZE; - } -#endif + netif_stop_queue(dev); - if (priv->tx_full && netif_queue_stopped(dev) && - dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) { - /* The ring is no longer full. */ - priv->tx_full = 0; - netif_wake_queue(dev); - } + lance->RAP = CSR112; /* Missed Frame Count */ + dev->stats.rx_missed_errors = swapw(lance->RDP); + lance->RAP = CSR0; /* PCnet-ISA Controller Status */ - priv->dirty_tx = dirty_tx; + if (ariadne_debug > 1) { + netdev_dbg(dev, "Shutting down ethercard, status was %02x\n", + lance->RDP); + netdev_dbg(dev, "%lu packets missed\n", + dev->stats.rx_missed_errors); } - /* Log misc errors. */ - if (csr0 & BABL) { - handled = 1; - dev->stats.tx_errors++; /* Tx babble. */ - } - if (csr0 & MISS) { - handled = 1; - dev->stats.rx_errors++; /* Missed a Rx frame. */ - } - if (csr0 & MERR) { - handled = 1; - printk(KERN_ERR "%s: Bus master arbitration failure, status " - "%4.4x.\n", dev->name, csr0); - /* Restart the chip. */ - lance->RDP = STRT; - } - } + /* We stop the LANCE here -- it occasionally polls memory if we don't */ + lance->RDP = STOP; - /* Clear any other interrupt, and set interrupt enable. */ - lance->RAP = CSR0; /* PCnet-ISA Controller Status */ - lance->RDP = INEA|BABL|CERR|MISS|MERR|IDON; + free_irq(IRQ_AMIGA_PORTS, dev); -#if 0 - if (ariadne_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, csr%d=%#4.4x.\n", dev->name, - lance->RAP, lance->RDP); -#endif - return IRQ_RETVAL(handled); + return 0; } +static inline void ariadne_reset(struct net_device *dev) +{ + volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr; + + lance->RAP = CSR0; /* PCnet-ISA Controller Status */ + lance->RDP = STOP; + ariadne_init_ring(dev); + lance->RDP = INEA | STRT; + netif_start_queue(dev); +} static void ariadne_tx_timeout(struct net_device *dev) { - volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr; + volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr; - printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n", - dev->name, lance->RDP); - ariadne_reset(dev); - netif_wake_queue(dev); + netdev_err(dev, "transmit timed out, status %04x, resetting\n", + lance->RDP); + ariadne_reset(dev); + netif_wake_queue(dev); } - static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ariadne_private *priv = netdev_priv(dev); - volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr; - int entry; - unsigned long flags; - int len = skb->len; - -#if 0 - if (ariadne_debug > 3) { - lance->RAP = CSR0; /* PCnet-ISA Controller Status */ - printk(KERN_DEBUG "%s: ariadne_start_xmit() called, csr0 %4.4x.\n", - dev->name, lance->RDP); - lance->RDP = 0x0000; - } -#endif - - /* FIXME: is the 79C960 new enough to do its own padding right ? */ - if (skb->len < ETH_ZLEN) - { - if (skb_padto(skb, ETH_ZLEN)) - return NETDEV_TX_OK; - len = ETH_ZLEN; - } - - /* Fill in a Tx ring entry */ + struct ariadne_private *priv = netdev_priv(dev); + volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr; + int entry; + unsigned long flags; + int len = skb->len; #if 0 -{ - printk(KERN_DEBUG "TX pkt type 0x%04x from %pM to %pM " - " data 0x%08x len %d\n", - ((u_short *)skb->data)[6], - skb->data + 6, skb->data, - (int)skb->data, (int)skb->len); -} + if (ariadne_debug > 3) { + lance->RAP = CSR0; /* PCnet-ISA Controller Status */ + netdev_dbg(dev, "%s: csr0 %04x\n", __func__, lance->RDP); + lance->RDP = 0x0000; + } #endif - local_irq_save(flags); - - entry = priv->cur_tx % TX_RING_SIZE; - - /* Caution: the write order is important here, set the base address with - the "ownership" bits last. */ - - priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len); - priv->tx_ring[entry]->TMD3 = 0x0000; - memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len); - -#if 0 - { - int i, len; - - len = skb->len > 64 ? 64 : skb->len; - len >>= 1; - for (i = 0; i < len; i += 8) { - int j; - printk(KERN_DEBUG "%04x:", i); - for (j = 0; (j < 8) && ((i+j) < len); j++) { - if (!(j & 1)) - printk(" "); - printk("%04x", priv->tx_buff[entry][i+j]); - } - printk("\n"); + /* FIXME: is the 79C960 new enough to do its own padding right ? */ + if (skb->len < ETH_ZLEN) { + if (skb_padto(skb, ETH_ZLEN)) + return NETDEV_TX_OK; + len = ETH_ZLEN; } - } -#endif - priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1&0xff00)|TF_OWN|TF_STP|TF_ENP; + /* Fill in a Tx ring entry */ - dev_kfree_skb(skb); + netdev_dbg(dev, "TX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n", + ((u_short *)skb->data)[6], + skb->data + 6, skb->data, + (int)skb->data, (int)skb->len); - priv->cur_tx++; - if ((priv->cur_tx >= TX_RING_SIZE) && (priv->dirty_tx >= TX_RING_SIZE)) { + local_irq_save(flags); -#if 0 - printk(KERN_DEBUG "*** Subtracting TX_RING_SIZE from cur_tx (%d) and " - "dirty_tx (%d)\n", priv->cur_tx, priv->dirty_tx); -#endif + entry = priv->cur_tx % TX_RING_SIZE; - priv->cur_tx -= TX_RING_SIZE; - priv->dirty_tx -= TX_RING_SIZE; - } - dev->stats.tx_bytes += len; + /* Caution: the write order is important here, set the base address with + the "ownership" bits last */ - /* Trigger an immediate send poll. */ - lance->RAP = CSR0; /* PCnet-ISA Controller Status */ - lance->RDP = INEA|TDMD; + priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len); + priv->tx_ring[entry]->TMD3 = 0x0000; + memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len); - if (lowb(priv->tx_ring[(entry+1) % TX_RING_SIZE]->TMD1) != 0) { - netif_stop_queue(dev); - priv->tx_full = 1; - } - local_irq_restore(flags); +#ifdef DEBUG + print_hex_dump(KERN_DEBUG, "tx_buff: ", DUMP_PREFIX_OFFSET, 16, 1, + (void *)priv->tx_buff[entry], + skb->len > 64 ? 64 : skb->len, true); +#endif - return NETDEV_TX_OK; -} + priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1 & 0xff00) + | TF_OWN | TF_STP | TF_ENP; + dev_kfree_skb(skb); -static int ariadne_rx(struct net_device *dev) -{ - struct ariadne_private *priv = netdev_priv(dev); - int entry = priv->cur_rx % RX_RING_SIZE; - int i; - - /* If we own the next entry, it's a new packet. Send it up. */ - while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) { - int status = lowb(priv->rx_ring[entry]->RMD1); - - if (status != (RF_STP|RF_ENP)) { /* There was an error. */ - /* There is a tricky error noted by John Murphy, - <murf@perftech.com> to Russ Nelson: Even with full-sized - buffers it's possible for a jabber packet to use two - buffers, with only the last correctly noting the error. */ - if (status & RF_ENP) - /* Only count a general error at the end of a packet.*/ - dev->stats.rx_errors++; - if (status & RF_FRAM) - dev->stats.rx_frame_errors++; - if (status & RF_OFLO) - dev->stats.rx_over_errors++; - if (status & RF_CRC) - dev->stats.rx_crc_errors++; - if (status & RF_BUFF) - dev->stats.rx_fifo_errors++; - priv->rx_ring[entry]->RMD1 &= 0xff00|RF_STP|RF_ENP; - } else { - /* Malloc up new buffer, compatible with net-3. */ - short pkt_len = swapw(priv->rx_ring[entry]->RMD3); - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len+2); - if (skb == NULL) { - printk(KERN_WARNING "%s: Memory squeeze, deferring packet.\n", - dev->name); - for (i = 0; i < RX_RING_SIZE; i++) - if (lowb(priv->rx_ring[(entry+i) % RX_RING_SIZE]->RMD1) & RF_OWN) - break; - - if (i > RX_RING_SIZE-2) { - dev->stats.rx_dropped++; - priv->rx_ring[entry]->RMD1 |= RF_OWN; - priv->cur_rx++; - } - break; - } + priv->cur_tx++; + if ((priv->cur_tx >= TX_RING_SIZE) && + (priv->dirty_tx >= TX_RING_SIZE)) { + netdev_dbg(dev, "*** Subtracting TX_RING_SIZE from cur_tx (%d) and dirty_tx (%d)\n", + priv->cur_tx, priv->dirty_tx); - skb_reserve(skb,2); /* 16 byte align */ - skb_put(skb,pkt_len); /* Make room */ - skb_copy_to_linear_data(skb, (char *)priv->rx_buff[entry], pkt_len); - skb->protocol=eth_type_trans(skb,dev); -#if 0 -{ - printk(KERN_DEBUG "RX pkt type 0x%04x from ", - ((u_short *)skb->data)[6]); - { - u_char *ptr = &((u_char *)skb->data)[6]; - printk("%pM", ptr); - } - printk(" to "); - { - u_char *ptr = (u_char *)skb->data; - printk("%pM", ptr); - } - printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len); -} -#endif - - netif_rx(skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += pkt_len; + priv->cur_tx -= TX_RING_SIZE; + priv->dirty_tx -= TX_RING_SIZE; } + dev->stats.tx_bytes += len; - priv->rx_ring[entry]->RMD1 |= RF_OWN; - entry = (++priv->cur_rx) % RX_RING_SIZE; - } + /* Trigger an immediate send poll */ + lance->RAP = CSR0; /* PCnet-ISA Controller Status */ + lance->RDP = INEA | TDMD; - priv->cur_rx = priv->cur_rx % RX_RING_SIZE; - - /* We should check that at least two ring entries are free. If not, - we should free one and mark stats->rx_dropped++. */ + if (lowb(priv->tx_ring[(entry + 1) % TX_RING_SIZE]->TMD1) != 0) { + netif_stop_queue(dev); + priv->tx_full = 1; + } + local_irq_restore(flags); - return 0; + return NETDEV_TX_OK; } - static struct net_device_stats *ariadne_get_stats(struct net_device *dev) { - volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr; - short saved_addr; - unsigned long flags; - - local_irq_save(flags); - saved_addr = lance->RAP; - lance->RAP = CSR112; /* Missed Frame Count */ - dev->stats.rx_missed_errors = swapw(lance->RDP); - lance->RAP = saved_addr; - local_irq_restore(flags); - - return &dev->stats; + volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr; + short saved_addr; + unsigned long flags; + + local_irq_save(flags); + saved_addr = lance->RAP; + lance->RAP = CSR112; /* Missed Frame Count */ + dev->stats.rx_missed_errors = swapw(lance->RDP); + lance->RAP = saved_addr; + local_irq_restore(flags); + + return &dev->stats; } - /* Set or clear the multicast filter for this adaptor. - num_addrs == -1 Promiscuous mode, receive all packets - num_addrs == 0 Normal mode, clear multicast list - num_addrs > 0 Multicast mode, receive normal and MC packets, and do - best-effort filtering. + * num_addrs == -1 Promiscuous mode, receive all packets + * num_addrs == 0 Normal mode, clear multicast list + * num_addrs > 0 Multicast mode, receive normal and MC packets, + * and do best-effort filtering. */ static void set_multicast_list(struct net_device *dev) { - volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr; + volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr; - if (!netif_running(dev)) - return; + if (!netif_running(dev)) + return; - netif_stop_queue(dev); + netif_stop_queue(dev); - /* We take the simple way out and always enable promiscuous mode. */ - lance->RAP = CSR0; /* PCnet-ISA Controller Status */ - lance->RDP = STOP; /* Temporarily stop the lance. */ - ariadne_init_ring(dev); + /* We take the simple way out and always enable promiscuous mode */ + lance->RAP = CSR0; /* PCnet-ISA Controller Status */ + lance->RDP = STOP; /* Temporarily stop the lance */ + ariadne_init_ring(dev); - if (dev->flags & IFF_PROMISC) { - lance->RAP = CSR15; /* Mode Register */ - lance->RDP = PROM; /* Set promiscuous mode */ - } else { - short multicast_table[4]; - int num_addrs = netdev_mc_count(dev); - int i; - /* We don't use the multicast table, but rely on upper-layer filtering. */ - memset(multicast_table, (num_addrs == 0) ? 0 : -1, - sizeof(multicast_table)); - for (i = 0; i < 4; i++) { - lance->RAP = CSR8+(i<<8); /* Logical Address Filter */ - lance->RDP = swapw(multicast_table[i]); + if (dev->flags & IFF_PROMISC) { + lance->RAP = CSR15; /* Mode Register */ + lance->RDP = PROM; /* Set promiscuous mode */ + } else { + short multicast_table[4]; + int num_addrs = netdev_mc_count(dev); + int i; + /* We don't use the multicast table, + * but rely on upper-layer filtering + */ + memset(multicast_table, (num_addrs == 0) ? 0 : -1, + sizeof(multicast_table)); + for (i = 0; i < 4; i++) { + lance->RAP = CSR8 + (i << 8); + /* Logical Address Filter */ + lance->RDP = swapw(multicast_table[i]); + } + lance->RAP = CSR15; /* Mode Register */ + lance->RDP = 0x0000; /* Unset promiscuous mode */ } - lance->RAP = CSR15; /* Mode Register */ - lance->RDP = 0x0000; /* Unset promiscuous mode */ - } - lance->RAP = CSR0; /* PCnet-ISA Controller Status */ - lance->RDP = INEA|STRT|IDON; /* Resume normal operation. */ + lance->RAP = CSR0; /* PCnet-ISA Controller Status */ + lance->RDP = INEA | STRT | IDON;/* Resume normal operation */ - netif_wake_queue(dev); + netif_wake_queue(dev); } static void __devexit ariadne_remove_one(struct zorro_dev *z) { - struct net_device *dev = zorro_get_drvdata(z); + struct net_device *dev = zorro_get_drvdata(z); - unregister_netdev(dev); - release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960)); - release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE); - free_netdev(dev); + unregister_netdev(dev); + release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960)); + release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE); + free_netdev(dev); } +static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = { + { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE }, + { 0 } +}; +MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl); + +static const struct net_device_ops ariadne_netdev_ops = { + .ndo_open = ariadne_open, + .ndo_stop = ariadne_close, + .ndo_start_xmit = ariadne_start_xmit, + .ndo_tx_timeout = ariadne_tx_timeout, + .ndo_get_stats = ariadne_get_stats, + .ndo_set_multicast_list = set_multicast_list, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, +}; + +static int __devinit ariadne_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent) +{ + unsigned long board = z->resource.start; + unsigned long base_addr = board + ARIADNE_LANCE; + unsigned long mem_start = board + ARIADNE_RAM; + struct resource *r1, *r2; + struct net_device *dev; + struct ariadne_private *priv; + int err; + + r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960"); + if (!r1) + return -EBUSY; + r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM"); + if (!r2) { + release_mem_region(base_addr, sizeof(struct Am79C960)); + return -EBUSY; + } + + dev = alloc_etherdev(sizeof(struct ariadne_private)); + if (dev == NULL) { + release_mem_region(base_addr, sizeof(struct Am79C960)); + release_mem_region(mem_start, ARIADNE_RAM_SIZE); + return -ENOMEM; + } + + priv = netdev_priv(dev); + + r1->name = dev->name; + r2->name = dev->name; + + dev->dev_addr[0] = 0x00; + dev->dev_addr[1] = 0x60; + dev->dev_addr[2] = 0x30; + dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff; + dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff; + dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff; + dev->base_addr = ZTWO_VADDR(base_addr); + dev->mem_start = ZTWO_VADDR(mem_start); + dev->mem_end = dev->mem_start + ARIADNE_RAM_SIZE; + + dev->netdev_ops = &ariadne_netdev_ops; + dev->watchdog_timeo = 5 * HZ; + + err = register_netdev(dev); + if (err) { + release_mem_region(base_addr, sizeof(struct Am79C960)); + release_mem_region(mem_start, ARIADNE_RAM_SIZE); + free_netdev(dev); + return err; + } + zorro_set_drvdata(z, dev); + + netdev_info(dev, "Ariadne at 0x%08lx, Ethernet Address %pM\n", + board, dev->dev_addr); + + return 0; +} + +static struct zorro_driver ariadne_driver = { + .name = "ariadne", + .id_table = ariadne_zorro_tbl, + .probe = ariadne_init_one, + .remove = __devexit_p(ariadne_remove_one), +}; + static int __init ariadne_init_module(void) { - return zorro_register_driver(&ariadne_driver); + return zorro_register_driver(&ariadne_driver); } static void __exit ariadne_cleanup_module(void) { - zorro_unregister_driver(&ariadne_driver); + zorro_unregister_driver(&ariadne_driver); } module_init(ariadne_init_module); diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 7b3e23f38913..52fe21e1e2cd 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -199,17 +199,15 @@ am79c961_ramtest(struct net_device *dev, unsigned int val) static void am79c961_mc_hash(char *addr, u16 *hash) { - if (addr[0] & 0x01) { - int idx, bit; - u32 crc; + int idx, bit; + u32 crc; - crc = ether_crc_le(ETH_ALEN, addr); + crc = ether_crc_le(ETH_ALEN, addr); - idx = crc >> 30; - bit = (crc >> 26) & 15; + idx = crc >> 30; + bit = (crc >> 26) & 15; - hash[idx] |= 1 << bit; - } + hash[idx] |= 1 << bit; } static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash) diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index e07b314ed8fd..29dc43523cec 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -19,6 +19,7 @@ #include <linux/module.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/mii.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 0b46b8ea0e80..4317af8d2f0a 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -19,6 +19,7 @@ #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/moduleparam.h> #include <linux/platform_device.h> #include <linux/delay.h> diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index a7b0caa18179..c827a6097d02 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -16,11 +16,13 @@ * Vincent Sanders <vince@simtec.co.uk> */ +#include <linux/dma-mapping.h> #include <linux/module.h> #include <linux/ioport.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/skbuff.h> #include <linux/spinlock.h> #include <linux/crc32.h> diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h index 925929d764ca..ca70e16b6e2c 100644 --- a/drivers/net/atl1c/atl1c.h +++ b/drivers/net/atl1c/atl1c.h @@ -22,8 +22,8 @@ #ifndef _ATL1C_H_ #define _ATL1C_H_ -#include <linux/version.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/module.h> @@ -555,7 +555,6 @@ struct atl1c_smb { struct atl1c_adapter { struct net_device *netdev; struct pci_dev *pdev; - struct vlan_group *vlgrp; struct napi_struct napi; struct atl1c_hw hw; struct atl1c_hw_stats hw_stats; diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 1269ba5d6e56..972244218408 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -411,29 +411,29 @@ static void atl1c_set_multi(struct net_device *netdev) } } -static void atl1c_vlan_rx_register(struct net_device *netdev, - struct vlan_group *grp) +static void __atl1c_vlan_mode(u32 features, u32 *mac_ctrl_data) +{ + if (features & NETIF_F_HW_VLAN_RX) { + /* enable VLAN tag insert/strip */ + *mac_ctrl_data |= MAC_CTRL_RMV_VLAN; + } else { + /* disable VLAN tag insert/strip */ + *mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN; + } +} + +static void atl1c_vlan_mode(struct net_device *netdev, u32 features) { struct atl1c_adapter *adapter = netdev_priv(netdev); struct pci_dev *pdev = adapter->pdev; u32 mac_ctrl_data = 0; if (netif_msg_pktdata(adapter)) - dev_dbg(&pdev->dev, "atl1c_vlan_rx_register\n"); + dev_dbg(&pdev->dev, "atl1c_vlan_mode\n"); atl1c_irq_disable(adapter); - - adapter->vlgrp = grp; AT_READ_REG(&adapter->hw, REG_MAC_CTRL, &mac_ctrl_data); - - if (grp) { - /* enable VLAN tag insert/strip */ - mac_ctrl_data |= MAC_CTRL_RMV_VLAN; - } else { - /* disable VLAN tag insert/strip */ - mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN; - } - + __atl1c_vlan_mode(features, &mac_ctrl_data); AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data); atl1c_irq_enable(adapter); } @@ -443,9 +443,10 @@ static void atl1c_restore_vlan(struct atl1c_adapter *adapter) struct pci_dev *pdev = adapter->pdev; if (netif_msg_pktdata(adapter)) - dev_dbg(&pdev->dev, "atl1c_restore_vlan !"); - atl1c_vlan_rx_register(adapter->netdev, adapter->vlgrp); + dev_dbg(&pdev->dev, "atl1c_restore_vlan\n"); + atl1c_vlan_mode(adapter->netdev, adapter->netdev->features); } + /* * atl1c_set_mac - Change the Ethernet Address of the NIC * @netdev: network interface device structure @@ -483,12 +484,31 @@ static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter, static u32 atl1c_fix_features(struct net_device *netdev, u32 features) { + /* + * Since there is no support for separate rx/tx vlan accel + * enable/disable make sure tx flag is always in same state as rx. + */ + if (features & NETIF_F_HW_VLAN_RX) + features |= NETIF_F_HW_VLAN_TX; + else + features &= ~NETIF_F_HW_VLAN_TX; + if (netdev->mtu > MAX_TSO_FRAME_SIZE) features &= ~(NETIF_F_TSO | NETIF_F_TSO6); return features; } +static int atl1c_set_features(struct net_device *netdev, u32 features) +{ + u32 changed = netdev->features ^ features; + + if (changed & NETIF_F_HW_VLAN_RX) + atl1c_vlan_mode(netdev, features); + + return 0; +} + /* * atl1c_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure @@ -1433,8 +1453,7 @@ static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter) mac_ctrl_data |= ((hw->preamble_len & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); - if (adapter->vlgrp) - mac_ctrl_data |= MAC_CTRL_RMV_VLAN; + __atl1c_vlan_mode(netdev->features, &mac_ctrl_data); mac_ctrl_data |= MAC_CTRL_BC_EN; if (netdev->flags & IFF_PROMISC) @@ -1878,14 +1897,14 @@ rrs_checked: skb_put(skb, length - ETH_FCS_LEN); skb->protocol = eth_type_trans(skb, netdev); atl1c_rx_checksum(adapter, skb, rrs); - if (unlikely(adapter->vlgrp) && rrs->word3 & RRS_VLAN_INS) { + if (rrs->word3 & RRS_VLAN_INS) { u16 vlan; AT_TAG_TO_VLAN(rrs->vlan_tag, vlan); vlan = le16_to_cpu(vlan); - vlan_hwaccel_receive_skb(skb, adapter->vlgrp, vlan); - } else - netif_receive_skb(skb); + __vlan_hwaccel_put_tag(skb, vlan); + } + netif_receive_skb(skb); (*work_done)++; count++; @@ -2507,8 +2526,7 @@ static int atl1c_suspend(struct device *dev) /* clear phy interrupt */ atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data); /* Config MAC Ctrl register */ - if (adapter->vlgrp) - mac_ctrl_data |= MAC_CTRL_RMV_VLAN; + __atl1c_vlan_mode(netdev->features, &mac_ctrl_data); /* magic packet maybe Broadcast&multicast&Unicast frame */ if (wufc & AT_WUFC_MAG) @@ -2581,14 +2599,14 @@ static const struct net_device_ops atl1c_netdev_ops = { .ndo_stop = atl1c_close, .ndo_validate_addr = eth_validate_addr, .ndo_start_xmit = atl1c_xmit_frame, - .ndo_set_mac_address = atl1c_set_mac_addr, + .ndo_set_mac_address = atl1c_set_mac_addr, .ndo_set_multicast_list = atl1c_set_multi, .ndo_change_mtu = atl1c_change_mtu, .ndo_fix_features = atl1c_fix_features, + .ndo_set_features = atl1c_set_features, .ndo_do_ioctl = atl1c_ioctl, .ndo_tx_timeout = atl1c_tx_timeout, .ndo_get_stats = atl1c_get_stats, - .ndo_vlan_rx_register = atl1c_vlan_rx_register, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = atl1c_netpoll, #endif @@ -2607,11 +2625,11 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev) /* TODO: add when ready */ netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_RX | NETIF_F_TSO | NETIF_F_TSO6; netdev->features = netdev->hw_features | - NETIF_F_HW_VLAN_RX; + NETIF_F_HW_VLAN_TX; return 0; } diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/atl1e/atl1e.h index 490d3b38e0cb..829b5ad71d0d 100644 --- a/drivers/net/atl1e/atl1e.h +++ b/drivers/net/atl1e/atl1e.h @@ -23,8 +23,8 @@ #ifndef _ATL1E_H_ #define _ATL1E_H_ -#include <linux/version.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/module.h> @@ -433,7 +433,6 @@ struct atl1e_rx_ring { struct atl1e_adapter { struct net_device *netdev; struct pci_dev *pdev; - struct vlan_group *vlgrp; struct napi_struct napi; struct mii_if_info mii; /* MII interface info */ struct atl1e_hw hw; diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 86a912283134..d8d411998fa3 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -313,8 +313,18 @@ static void atl1e_set_multi(struct net_device *netdev) } } -static void atl1e_vlan_rx_register(struct net_device *netdev, - struct vlan_group *grp) +static void __atl1e_vlan_mode(u32 features, u32 *mac_ctrl_data) +{ + if (features & NETIF_F_HW_VLAN_RX) { + /* enable VLAN tag insert/strip */ + *mac_ctrl_data |= MAC_CTRL_RMV_VLAN; + } else { + /* disable VLAN tag insert/strip */ + *mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN; + } +} + +static void atl1e_vlan_mode(struct net_device *netdev, u32 features) { struct atl1e_adapter *adapter = netdev_priv(netdev); u32 mac_ctrl_data = 0; @@ -322,18 +332,8 @@ static void atl1e_vlan_rx_register(struct net_device *netdev, netdev_dbg(adapter->netdev, "%s\n", __func__); atl1e_irq_disable(adapter); - - adapter->vlgrp = grp; mac_ctrl_data = AT_READ_REG(&adapter->hw, REG_MAC_CTRL); - - if (grp) { - /* enable VLAN tag insert/strip */ - mac_ctrl_data |= MAC_CTRL_RMV_VLAN; - } else { - /* disable VLAN tag insert/strip */ - mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN; - } - + __atl1e_vlan_mode(features, &mac_ctrl_data); AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data); atl1e_irq_enable(adapter); } @@ -341,8 +341,9 @@ static void atl1e_vlan_rx_register(struct net_device *netdev, static void atl1e_restore_vlan(struct atl1e_adapter *adapter) { netdev_dbg(adapter->netdev, "%s\n", __func__); - atl1e_vlan_rx_register(adapter->netdev, adapter->vlgrp); + atl1e_vlan_mode(adapter->netdev, adapter->netdev->features); } + /* * atl1e_set_mac - Change the Ethernet Address of the NIC * @netdev: network interface device structure @@ -369,6 +370,30 @@ static int atl1e_set_mac_addr(struct net_device *netdev, void *p) return 0; } +static u32 atl1e_fix_features(struct net_device *netdev, u32 features) +{ + /* + * Since there is no support for separate rx/tx vlan accel + * enable/disable make sure tx flag is always in same state as rx. + */ + if (features & NETIF_F_HW_VLAN_RX) + features |= NETIF_F_HW_VLAN_TX; + else + features &= ~NETIF_F_HW_VLAN_TX; + + return features; +} + +static int atl1e_set_features(struct net_device *netdev, u32 features) +{ + u32 changed = netdev->features ^ features; + + if (changed & NETIF_F_HW_VLAN_RX) + atl1e_vlan_mode(netdev, features); + + return 0; +} + /* * atl1e_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure @@ -800,8 +825,7 @@ static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter) /* Init TPD Ring */ tx_ring->dma = roundup(adapter->ring_dma, 8); offset = tx_ring->dma - adapter->ring_dma; - tx_ring->desc = (struct atl1e_tpd_desc *) - (adapter->ring_vir_addr + offset); + tx_ring->desc = adapter->ring_vir_addr + offset; size = sizeof(struct atl1e_tx_buffer) * (tx_ring->count); tx_ring->tx_buffer = kzalloc(size, GFP_KERNEL); if (tx_ring->tx_buffer == NULL) { @@ -827,7 +851,7 @@ static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter) /* Init CMB dma address */ tx_ring->cmb_dma = adapter->ring_dma + offset; - tx_ring->cmb = (u32 *)(adapter->ring_vir_addr + offset); + tx_ring->cmb = adapter->ring_vir_addr + offset; offset += sizeof(u32); for (i = 0; i < adapter->num_rx_queues; i++) { @@ -1040,8 +1064,7 @@ static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter) value |= (((u32)adapter->hw.preamble_len & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); - if (adapter->vlgrp) - value |= MAC_CTRL_RMV_VLAN; + __atl1e_vlan_mode(netdev->features, &value); value |= MAC_CTRL_BC_EN; if (netdev->flags & IFF_PROMISC) @@ -1424,19 +1447,16 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que, skb->protocol = eth_type_trans(skb, netdev); atl1e_rx_checksum(adapter, skb, prrs); - if (unlikely(adapter->vlgrp && - (prrs->pkt_flag & RRS_IS_VLAN_TAG))) { + if (prrs->pkt_flag & RRS_IS_VLAN_TAG) { u16 vlan_tag = (prrs->vtag >> 4) | ((prrs->vtag & 7) << 13) | ((prrs->vtag & 8) << 9); netdev_dbg(netdev, "RXD VLAN TAG<RRD>=0x%04x\n", prrs->vtag); - vlan_hwaccel_receive_skb(skb, adapter->vlgrp, - vlan_tag); - } else { - netif_receive_skb(skb); + __vlan_hwaccel_put_tag(skb, vlan_tag); } + netif_receive_skb(skb); skip_pkt: /* skip current packet whether it's ok or not. */ @@ -1812,7 +1832,7 @@ static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb, tpd = atl1e_get_tpd(adapter); - if (unlikely(vlan_tx_tag_present(skb))) { + if (vlan_tx_tag_present(skb)) { u16 vlan_tag = vlan_tx_tag_get(skb); u16 atl1e_vlan_tag; @@ -2094,8 +2114,7 @@ static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state) MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); - if (adapter->vlgrp) - mac_ctrl_data |= MAC_CTRL_RMV_VLAN; + __atl1e_vlan_mode(netdev->features, &mac_ctrl_data); /* magic packet maybe Broadcast&multicast&Unicast frame */ if (wufc & AT_WUFC_MAG) @@ -2196,10 +2215,11 @@ static const struct net_device_ops atl1e_netdev_ops = { .ndo_set_multicast_list = atl1e_set_multi, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = atl1e_set_mac_addr, + .ndo_fix_features = atl1e_fix_features, + .ndo_set_features = atl1e_set_features, .ndo_change_mtu = atl1e_change_mtu, .ndo_do_ioctl = atl1e_ioctl, .ndo_tx_timeout = atl1e_tx_timeout, - .ndo_vlan_rx_register = atl1e_vlan_rx_register, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = atl1e_netpoll, #endif @@ -2218,9 +2238,9 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev) atl1e_set_ethtool_ops(netdev); netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO | - NETIF_F_HW_VLAN_TX; - netdev->features = netdev->hw_features | - NETIF_F_HW_VLAN_RX | NETIF_F_LLTX; + NETIF_F_HW_VLAN_RX; + netdev->features = netdev->hw_features | NETIF_F_LLTX | + NETIF_F_HW_VLAN_TX; return 0; } diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index cd5789ff3726..6f0e9403004b 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -1285,8 +1285,7 @@ static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter) value |= (((u32) adapter->hw.preamble_len & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); /* vlan */ - if (adapter->vlgrp) - value |= MAC_CTRL_RMV_VLAN; + __atlx_vlan_mode(netdev->features, &value); /* rx checksum if (adapter->rx_csum) value |= MAC_CTRL_RX_CHKSUM_EN; @@ -2023,13 +2022,14 @@ rrd_ok: atl1_rx_checksum(adapter, rrd, skb); skb->protocol = eth_type_trans(skb, adapter->netdev); - if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) { + if (rrd->pkt_flg & PACKET_FLAG_VLAN_INS) { u16 vlan_tag = (rrd->vlan_tag >> 4) | ((rrd->vlan_tag & 7) << 13) | ((rrd->vlan_tag & 8) << 9); - vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag); - } else - netif_rx(skb); + + __vlan_hwaccel_put_tag(skb, vlan_tag); + } + netif_rx(skb); /* let protocol layer free skb */ buffer_info->skb = NULL; @@ -2783,8 +2783,7 @@ static int atl1_suspend(struct device *dev) ctrl |= MAC_CTRL_DUPLX; ctrl |= (((u32)adapter->hw.preamble_len & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); - if (adapter->vlgrp) - ctrl |= MAC_CTRL_RMV_VLAN; + __atlx_vlan_mode(netdev->features, &ctrl); if (wufc & ATLX_WUFC_MAG) ctrl |= MAC_CTRL_BC_EN; iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL); @@ -2874,9 +2873,10 @@ static const struct net_device_ops atl1_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = atl1_set_mac, .ndo_change_mtu = atl1_change_mtu, + .ndo_fix_features = atlx_fix_features, + .ndo_set_features = atlx_set_features, .ndo_do_ioctl = atlx_ioctl, .ndo_tx_timeout = atlx_tx_timeout, - .ndo_vlan_rx_register = atlx_vlan_rx_register, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = atl1_poll_controller, #endif @@ -2984,7 +2984,8 @@ static int __devinit atl1_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_SG; netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX); - netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_TSO; + netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_TSO | + NETIF_F_HW_VLAN_RX; /* is this valid? see atl1_setup_mac_ctrl() */ netdev->features |= NETIF_F_RXCSUM; diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h index 68de8cbfb3ec..109d6da8be97 100644 --- a/drivers/net/atlx/atl1.h +++ b/drivers/net/atlx/atl1.h @@ -753,7 +753,6 @@ struct atl1_adapter { struct pci_dev *pdev; struct atl1_sft_stats soft_stats; - struct vlan_group *vlgrp; u32 rx_buffer_len; u32 wol; u16 link_speed; diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index 16249e9b6b95..e0f87cf1e2ba 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c @@ -311,8 +311,7 @@ static s32 atl2_setup_ring_resources(struct atl2_adapter *adapter) adapter->txd_dma = adapter->ring_dma ; offset = (adapter->txd_dma & 0x7) ? (8 - (adapter->txd_dma & 0x7)) : 0; adapter->txd_dma += offset; - adapter->txd_ring = (struct tx_pkt_header *) (adapter->ring_vir_addr + - offset); + adapter->txd_ring = adapter->ring_vir_addr + offset; /* Init TXS Ring */ adapter->txs_dma = adapter->txd_dma + adapter->txd_ring_size; @@ -362,36 +361,59 @@ static inline void atl2_irq_disable(struct atl2_adapter *adapter) synchronize_irq(adapter->pdev->irq); } -#ifdef NETIF_F_HW_VLAN_TX -static void atl2_vlan_rx_register(struct net_device *netdev, - struct vlan_group *grp) +static void __atl2_vlan_mode(u32 features, u32 *ctrl) +{ + if (features & NETIF_F_HW_VLAN_RX) { + /* enable VLAN tag insert/strip */ + *ctrl |= MAC_CTRL_RMV_VLAN; + } else { + /* disable VLAN tag insert/strip */ + *ctrl &= ~MAC_CTRL_RMV_VLAN; + } +} + +static void atl2_vlan_mode(struct net_device *netdev, u32 features) { struct atl2_adapter *adapter = netdev_priv(netdev); u32 ctrl; atl2_irq_disable(adapter); - adapter->vlgrp = grp; - if (grp) { - /* enable VLAN tag insert/strip */ - ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL); - ctrl |= MAC_CTRL_RMV_VLAN; - ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl); - } else { - /* disable VLAN tag insert/strip */ - ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL); - ctrl &= ~MAC_CTRL_RMV_VLAN; - ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl); - } + ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL); + __atl2_vlan_mode(features, &ctrl); + ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl); atl2_irq_enable(adapter); } static void atl2_restore_vlan(struct atl2_adapter *adapter) { - atl2_vlan_rx_register(adapter->netdev, adapter->vlgrp); + atl2_vlan_mode(adapter->netdev, adapter->netdev->features); +} + +static u32 atl2_fix_features(struct net_device *netdev, u32 features) +{ + /* + * Since there is no support for separate rx/tx vlan accel + * enable/disable make sure tx flag is always in same state as rx. + */ + if (features & NETIF_F_HW_VLAN_RX) + features |= NETIF_F_HW_VLAN_TX; + else + features &= ~NETIF_F_HW_VLAN_TX; + + return features; +} + +static int atl2_set_features(struct net_device *netdev, u32 features) +{ + u32 changed = netdev->features ^ features; + + if (changed & NETIF_F_HW_VLAN_RX) + atl2_vlan_mode(netdev, features); + + return 0; } -#endif static void atl2_intr_rx(struct atl2_adapter *adapter) { @@ -425,14 +447,13 @@ static void atl2_intr_rx(struct atl2_adapter *adapter) memcpy(skb->data, rxd->packet, rx_size); skb_put(skb, rx_size); skb->protocol = eth_type_trans(skb, netdev); -#ifdef NETIF_F_HW_VLAN_TX - if (adapter->vlgrp && (rxd->status.vlan)) { + if (rxd->status.vlan) { u16 vlan_tag = (rxd->status.vtag>>4) | ((rxd->status.vtag&7) << 13) | ((rxd->status.vtag&8) << 9); - vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag); - } else -#endif + + __vlan_hwaccel_put_tag(skb, vlan_tag); + } netif_rx(skb); netdev->stats.rx_bytes += rx_size; netdev->stats.rx_packets++; @@ -705,9 +726,7 @@ static int atl2_open(struct net_device *netdev) atl2_set_multi(netdev); init_ring_ptrs(adapter); -#ifdef NETIF_F_HW_VLAN_TX atl2_restore_vlan(adapter); -#endif if (atl2_configure(adapter)) { err = -EIO; @@ -1083,9 +1102,7 @@ static int atl2_up(struct atl2_adapter *adapter) atl2_set_multi(netdev); init_ring_ptrs(adapter); -#ifdef NETIF_F_HW_VLAN_TX atl2_restore_vlan(adapter); -#endif if (atl2_configure(adapter)) { err = -EIO; @@ -1146,8 +1163,7 @@ static void atl2_setup_mac_ctrl(struct atl2_adapter *adapter) MAC_CTRL_PRMLEN_SHIFT); /* vlan */ - if (adapter->vlgrp) - value |= MAC_CTRL_RMV_VLAN; + __atl2_vlan_mode(netdev->features, &value); /* filter mode */ value |= MAC_CTRL_BC_EN; @@ -1313,9 +1329,10 @@ static const struct net_device_ops atl2_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = atl2_set_mac, .ndo_change_mtu = atl2_change_mtu, + .ndo_fix_features = atl2_fix_features, + .ndo_set_features = atl2_set_features, .ndo_do_ioctl = atl2_ioctl, .ndo_tx_timeout = atl2_tx_timeout, - .ndo_vlan_rx_register = atl2_vlan_rx_register, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = atl2_poll_controller, #endif @@ -1411,7 +1428,7 @@ static int __devinit atl2_probe(struct pci_dev *pdev, err = -EIO; - netdev->hw_features = NETIF_F_SG; + netdev->hw_features = NETIF_F_SG | NETIF_F_HW_VLAN_RX; netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX); /* Init PHY as early as possible due to power saving issue */ diff --git a/drivers/net/atlx/atl2.h b/drivers/net/atlx/atl2.h index 927e4de6474d..78344ddf4bf0 100644 --- a/drivers/net/atlx/atl2.h +++ b/drivers/net/atlx/atl2.h @@ -453,9 +453,6 @@ struct atl2_adapter { /* OS defined structs */ struct net_device *netdev; struct pci_dev *pdev; -#ifdef NETIF_F_HW_VLAN_TX - struct vlan_group *vlgrp; -#endif u32 wol; u16 link_speed; u16 link_duplex; diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c index afb7f7dd1bb1..aabcf4b5745a 100644 --- a/drivers/net/atlx/atlx.c +++ b/drivers/net/atlx/atlx.c @@ -211,8 +211,18 @@ static void atlx_link_chg_task(struct work_struct *work) spin_unlock_irqrestore(&adapter->lock, flags); } -static void atlx_vlan_rx_register(struct net_device *netdev, - struct vlan_group *grp) +static void __atlx_vlan_mode(u32 features, u32 *ctrl) +{ + if (features & NETIF_F_HW_VLAN_RX) { + /* enable VLAN tag insert/strip */ + *ctrl |= MAC_CTRL_RMV_VLAN; + } else { + /* disable VLAN tag insert/strip */ + *ctrl &= ~MAC_CTRL_RMV_VLAN; + } +} + +static void atlx_vlan_mode(struct net_device *netdev, u32 features) { struct atlx_adapter *adapter = netdev_priv(netdev); unsigned long flags; @@ -220,27 +230,40 @@ static void atlx_vlan_rx_register(struct net_device *netdev, spin_lock_irqsave(&adapter->lock, flags); /* atlx_irq_disable(adapter); FIXME: confirm/remove */ - adapter->vlgrp = grp; - - if (grp) { - /* enable VLAN tag insert/strip */ - ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL); - ctrl |= MAC_CTRL_RMV_VLAN; - iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL); - } else { - /* disable VLAN tag insert/strip */ - ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL); - ctrl &= ~MAC_CTRL_RMV_VLAN; - iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL); - } - + ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL); + __atlx_vlan_mode(features, &ctrl); + iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL); /* atlx_irq_enable(adapter); FIXME */ spin_unlock_irqrestore(&adapter->lock, flags); } static void atlx_restore_vlan(struct atlx_adapter *adapter) { - atlx_vlan_rx_register(adapter->netdev, adapter->vlgrp); + atlx_vlan_mode(adapter->netdev, adapter->netdev->features); +} + +static u32 atlx_fix_features(struct net_device *netdev, u32 features) +{ + /* + * Since there is no support for separate rx/tx vlan accel + * enable/disable make sure tx flag is always in same state as rx. + */ + if (features & NETIF_F_HW_VLAN_RX) + features |= NETIF_F_HW_VLAN_TX; + else + features &= ~NETIF_F_HW_VLAN_TX; + + return features; +} + +static int atlx_set_features(struct net_device *netdev, u32 features) +{ + u32 changed = netdev->features ^ features; + + if (changed & NETIF_F_HW_VLAN_RX) + atlx_vlan_mode(netdev, features); + + return 0; } #endif /* ATLX_C */ diff --git a/drivers/net/b44.c b/drivers/net/b44.c index a69331e06b8d..6c4ef966ca58 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -25,6 +25,7 @@ #include <linux/pci.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/dma-mapping.h> #include <linux/ssb/ssb.h> #include <linux/slab.h> @@ -38,6 +39,7 @@ #define DRV_MODULE_NAME "b44" #define DRV_MODULE_VERSION "2.0" +#define DRV_DESCRIPTION "Broadcom 44xx/47xx 10/100 PCI ethernet driver" #define B44_DEF_MSG_ENABLE \ (NETIF_MSG_DRV | \ @@ -90,11 +92,8 @@ #define B44_ETHIPV6UDP_HLEN 62 #define B44_ETHIPV4UDP_HLEN 42 -static char version[] __devinitdata = - DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION "\n"; - MODULE_AUTHOR("Felix Fietkau, Florian Schirmer, Pekka Pietikainen, David S. Miller"); -MODULE_DESCRIPTION("Broadcom 44xx/47xx 10/100 PCI ethernet driver"); +MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); @@ -609,7 +608,7 @@ static void b44_tx(struct b44 *bp) skb->len, DMA_TO_DEVICE); rp->skb = NULL; - dev_kfree_skb_irq(skb); + dev_kfree_skb(skb); } bp->tx_cons = cons; @@ -2129,16 +2128,13 @@ static const struct net_device_ops b44_netdev_ops = { static int __devinit b44_init_one(struct ssb_device *sdev, const struct ssb_device_id *ent) { - static int b44_version_printed = 0; struct net_device *dev; struct b44 *bp; int err; instance++; - if (b44_version_printed++ == 0) - pr_info("%s", version); - + pr_info_once("%s version %s\n", DRV_DESCRIPTION, DRV_MODULE_VERSION); dev = alloc_etherdev(sizeof(*bp)); if (!dev) { @@ -2224,8 +2220,7 @@ static int __devinit b44_init_one(struct ssb_device *sdev, if (b44_phy_reset(bp) < 0) bp->phy_addr = B44_PHY_ADDR_NO_PHY; - netdev_info(dev, "Broadcom 44xx/47xx 10/100BaseT Ethernet %pM\n", - dev->dev_addr); + netdev_info(dev, "%s %pM\n", DRV_DESCRIPTION, dev->dev_addr); return 0; @@ -2335,7 +2330,7 @@ static struct ssb_driver b44_ssb_driver = { .resume = b44_resume, }; -static inline int b44_pci_init(void) +static inline int __init b44_pci_init(void) { int err = 0; #ifdef CONFIG_B44_PCI @@ -2344,7 +2339,7 @@ static inline int b44_pci_init(void) return err; } -static inline void b44_pci_exit(void) +static inline void __exit b44_pci_exit(void) { #ifdef CONFIG_B44_PCI ssb_pcihost_unregister(&b44_pci_driver); diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c index f1573d492e90..4753bb9731f5 100644 --- a/drivers/net/bcm63xx_enet.c +++ b/drivers/net/bcm63xx_enet.c @@ -18,6 +18,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/module.h> #include <linux/clk.h> #include <linux/etherdevice.h> diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index a7db870d1641..c85768cd1b18 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -20,7 +20,6 @@ #include <linux/pci.h> #include <linux/etherdevice.h> -#include <linux/version.h> #include <linux/delay.h> #include <net/tcp.h> #include <net/ip.h> @@ -87,6 +86,7 @@ static inline char *nic_name(struct pci_dev *pdev) #define MAX_RSS_QS 4 /* BE limit is 4 queues/port */ #define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */ +#define MAX_TX_QS 8 #define BE_MAX_MSIX_VECTORS (MAX_RX_QS + 1)/* RX + TX */ #define BE_NAPI_WEIGHT 64 #define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ @@ -170,7 +170,6 @@ struct be_tx_stats { u32 be_tx_reqs; /* number of TX requests initiated */ u32 be_tx_stops; /* number of times TX Q was stopped */ u32 be_tx_wrbs; /* number of tx WRBs used */ - u32 be_tx_events; /* number of tx completion events */ u32 be_tx_compl; /* number of tx completion entries processed */ ulong be_tx_jiffies; u64 be_tx_bytes; @@ -184,6 +183,7 @@ struct be_tx_obj { struct be_queue_info cq; /* Remember the skbs that were transmitted */ struct sk_buff *sent_skb_list[TX_Q_LEN]; + struct be_tx_stats stats; }; /* Struct to remember the pages posted for rx frags */ @@ -199,6 +199,7 @@ struct be_rx_stats { u32 rx_polls; /* number of times NAPI called poll function */ u32 rx_events; /* number of ucast rx completion events */ u32 rx_compl; /* number of rx completion entries processed */ + ulong rx_dropped; /* number of skb allocation errors */ ulong rx_jiffies; u64 rx_bytes; u64 rx_bytes_prev; @@ -319,8 +320,8 @@ struct be_adapter { /* TX Rings */ struct be_eq_obj tx_eq; - struct be_tx_obj tx_obj; - struct be_tx_stats tx_stats; + struct be_tx_obj tx_obj[MAX_TX_QS]; + u8 num_tx_qs; u32 cache_line_break[8]; @@ -332,7 +333,6 @@ struct be_adapter { u8 eq_next_idx; struct be_drv_stats drv_stats; - struct vlan_group *vlan_grp; u16 vlans_added; u16 max_vlans; /* Number of vlans supported */ u8 vlan_tag[VLAN_N_VID]; @@ -391,7 +391,7 @@ struct be_adapter { extern const struct ethtool_ops be_ethtool_ops; #define msix_enabled(adapter) (adapter->num_msix_vec > 0) -#define tx_stats(adapter) (&adapter->tx_stats) +#define tx_stats(txo) (&txo->stats) #define rx_stats(rxo) (&rxo->stats) #define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) @@ -405,6 +405,10 @@ extern const struct ethtool_ops be_ethtool_ops; for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\ i++, rxo++) +#define for_all_tx_queues(adapter, txo, i) \ + for (i = 0, txo = &adapter->tx_obj[i]; i < adapter->num_tx_qs; \ + i++, txo++) + #define PAGE_SHIFT_4K 12 #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 81654ae16c63..054fa67bc4e3 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -106,14 +106,24 @@ static int be_mcc_compl_process(struct be_adapter *adapter, netdev_stats_update(adapter); adapter->stats_cmd_sent = false; } - } else if ((compl_status != MCC_STATUS_NOT_SUPPORTED) && - (compl->tag0 != OPCODE_COMMON_NTWK_MAC_QUERY)) { - extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & - CQE_STATUS_EXTD_MASK; - dev_warn(&adapter->pdev->dev, - "Error in cmd completion - opcode %d, compl %d, extd %d\n", - compl->tag0, compl_status, extd_status); + } else { + if (compl_status == MCC_STATUS_NOT_SUPPORTED || + compl_status == MCC_STATUS_ILLEGAL_REQUEST) + goto done; + + if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) { + dev_warn(&adapter->pdev->dev, "This domain(VM) is not " + "permitted to execute this cmd (opcode %d)\n", + compl->tag0); + } else { + extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & + CQE_STATUS_EXTD_MASK; + dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:" + "status %d, extd-status %d\n", + compl->tag0, compl_status, extd_status); + } } +done: return compl_status; } @@ -799,12 +809,12 @@ static u32 be_encoded_q_len(int q_len) return len_encoded; } -int be_cmd_mccq_create(struct be_adapter *adapter, +int be_cmd_mccq_ext_create(struct be_adapter *adapter, struct be_queue_info *mccq, struct be_queue_info *cq) { struct be_mcc_wrb *wrb; - struct be_cmd_req_mcc_create *req; + struct be_cmd_req_mcc_ext_create *req; struct be_dma_mem *q_mem = &mccq->dma_mem; void *ctxt; int status; @@ -859,6 +869,67 @@ int be_cmd_mccq_create(struct be_adapter *adapter, return status; } +int be_cmd_mccq_org_create(struct be_adapter *adapter, + struct be_queue_info *mccq, + struct be_queue_info *cq) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_mcc_create *req; + struct be_dma_mem *q_mem = &mccq->dma_mem; + void *ctxt; + int status; + + if (mutex_lock_interruptible(&adapter->mbox_lock)) + return -1; + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); + ctxt = &req->context; + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, + OPCODE_COMMON_MCC_CREATE); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_MCC_CREATE, sizeof(*req)); + + req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); + + AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1); + AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt, + be_encoded_q_len(mccq->len)); + AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id); + + be_dws_cpu_to_le(ctxt, sizeof(req->context)); + + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + + status = be_mbox_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); + mccq->id = le16_to_cpu(resp->id); + mccq->created = true; + } + + mutex_unlock(&adapter->mbox_lock); + return status; +} + +int be_cmd_mccq_create(struct be_adapter *adapter, + struct be_queue_info *mccq, + struct be_queue_info *cq) +{ + int status; + + status = be_cmd_mccq_ext_create(adapter, mccq, cq); + if (status && !lancer_chip(adapter)) { + dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 " + "or newer to avoid conflicting priorities between NIC " + "and FCoE traffic"); + status = be_cmd_mccq_org_create(adapter, mccq, cq); + } + return status; +} + int be_cmd_txq_create(struct be_adapter *adapter, struct be_queue_info *txq, struct be_queue_info *cq) @@ -913,7 +984,7 @@ int be_cmd_txq_create(struct be_adapter *adapter, return status; } -/* Uses mbox */ +/* Uses MCC */ int be_cmd_rxq_create(struct be_adapter *adapter, struct be_queue_info *rxq, u16 cq_id, u16 frag_size, u16 max_frame_size, u32 if_id, u32 rss, u8 *rss_id) @@ -923,10 +994,13 @@ int be_cmd_rxq_create(struct be_adapter *adapter, struct be_dma_mem *q_mem = &rxq->dma_mem; int status; - if (mutex_lock_interruptible(&adapter->mbox_lock)) - return -1; + spin_lock_bh(&adapter->mcc_lock); - wrb = wrb_from_mbox(adapter); + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, @@ -943,7 +1017,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter, req->max_frame_size = cpu_to_le16(max_frame_size); req->rss_queue = cpu_to_le32(rss); - status = be_mbox_notify_wait(adapter); + status = be_mcc_notify_wait(adapter); if (!status) { struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb); rxq->id = le16_to_cpu(resp->id); @@ -951,8 +1025,8 @@ int be_cmd_rxq_create(struct be_adapter *adapter, *rss_id = resp->rss_id; } - mutex_unlock(&adapter->mbox_lock); - +err: + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1007,9 +1081,40 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, req->id = cpu_to_le16(q->id); status = be_mbox_notify_wait(adapter); + if (!status) + q->created = false; mutex_unlock(&adapter->mbox_lock); + return status; +} + +/* Uses MCC */ +int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_q_destroy *req; + int status; + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + req = embedded_payload(wrb); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_ETH_RX_DESTROY); + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_DESTROY, + sizeof(*req)); + req->id = cpu_to_le16(q->id); + + status = be_mcc_notify_wait(adapter); + if (!status) + q->created = false; + +err: + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -2273,8 +2378,7 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter) status = be_mbox_notify_wait(adapter); if (!status) { - attribs = (struct mgmt_controller_attrib *)( attribs_cmd.va + - sizeof(struct be_cmd_resp_hdr)); + attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr); adapter->hba_port_num = attribs->hba_attribs.phy_port; } @@ -2286,7 +2390,7 @@ err: } /* Uses mbox */ -int be_cmd_check_native_mode(struct be_adapter *adapter) +int be_cmd_req_native_mode(struct be_adapter *adapter) { struct be_mcc_wrb *wrb; struct be_cmd_req_set_func_cap *req; diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 8148cc66cbe9..8e4d48824fe9 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -51,17 +51,12 @@ struct be_mcc_wrb { /* Completion Status */ enum { - MCC_STATUS_SUCCESS = 0x0, -/* The client does not have sufficient privileges to execute the command */ - MCC_STATUS_INSUFFICIENT_PRIVILEGES = 0x1, -/* A parameter in the command was invalid. */ - MCC_STATUS_INVALID_PARAMETER = 0x2, -/* There are insufficient chip resources to execute the command */ - MCC_STATUS_INSUFFICIENT_RESOURCES = 0x3, -/* The command is completing because the queue was getting flushed */ - MCC_STATUS_QUEUE_FLUSHING = 0x4, -/* The command is completing with a DMA error */ - MCC_STATUS_DMA_FAILED = 0x5, + MCC_STATUS_SUCCESS = 0, + MCC_STATUS_FAILED = 1, + MCC_STATUS_ILLEGAL_REQUEST = 2, + MCC_STATUS_ILLEGAL_FIELD = 3, + MCC_STATUS_INSUFFICIENT_BUFFER = 4, + MCC_STATUS_UNAUTHORIZED_REQUEST = 5, MCC_STATUS_NOT_SUPPORTED = 66 }; @@ -434,6 +429,14 @@ struct be_cmd_req_mcc_create { struct be_cmd_req_hdr hdr; u16 num_pages; u16 cq_id; + u8 context[sizeof(struct amap_mcc_context_be) / 8]; + struct phys_addr pages[8]; +} __packed; + +struct be_cmd_req_mcc_ext_create { + struct be_cmd_req_hdr hdr; + u16 num_pages; + u16 cq_id; u32 async_event_bitmap[1]; u8 context[sizeof(struct amap_mcc_context_be) / 8]; struct phys_addr pages[8]; @@ -1479,6 +1482,8 @@ extern int be_cmd_rxq_create(struct be_adapter *adapter, u32 rss, u8 *rss_id); extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, int type); +extern int be_cmd_rxq_destroy(struct be_adapter *adapter, + struct be_queue_info *q); extern int be_cmd_link_status_query(struct be_adapter *adapter, bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom); extern int be_cmd_reset(struct be_adapter *adapter); @@ -1540,7 +1545,7 @@ extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain); extern void be_detect_dump_ue(struct be_adapter *adapter); extern int be_cmd_get_die_temperature(struct be_adapter *adapter); extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter); -extern int be_cmd_check_native_mode(struct be_adapter *adapter); +extern int be_cmd_req_native_mode(struct be_adapter *adapter); extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size); extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index facfe3ca5c40..7fd8130d86ea 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -52,12 +52,7 @@ static const struct be_ethtool_stat et_stats[] = { {NETSTAT_INFO(tx_errors)}, {NETSTAT_INFO(rx_dropped)}, {NETSTAT_INFO(tx_dropped)}, - {DRVSTAT_TX_INFO(be_tx_rate)}, - {DRVSTAT_TX_INFO(be_tx_reqs)}, - {DRVSTAT_TX_INFO(be_tx_wrbs)}, - {DRVSTAT_TX_INFO(be_tx_stops)}, - {DRVSTAT_TX_INFO(be_tx_events)}, - {DRVSTAT_TX_INFO(be_tx_compl)}, + {DRVSTAT_INFO(be_tx_events)}, {DRVSTAT_INFO(rx_crc_errors)}, {DRVSTAT_INFO(rx_alignment_symbol_errors)}, {DRVSTAT_INFO(rx_pause_frames)}, @@ -107,10 +102,21 @@ static const struct be_ethtool_stat et_rx_stats[] = { {DRVSTAT_RX_INFO(rx_compl)}, {DRVSTAT_RX_INFO(rx_mcast_pkts)}, {DRVSTAT_RX_INFO(rx_post_fail)}, + {DRVSTAT_RX_INFO(rx_dropped)}, {ERXSTAT_INFO(rx_drops_no_fragments)} }; #define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats)) +/* Stats related to multi TX queues */ +static const struct be_ethtool_stat et_tx_stats[] = { + {DRVSTAT_TX_INFO(be_tx_rate)}, + {DRVSTAT_TX_INFO(be_tx_reqs)}, + {DRVSTAT_TX_INFO(be_tx_wrbs)}, + {DRVSTAT_TX_INFO(be_tx_stops)}, + {DRVSTAT_TX_INFO(be_tx_compl)} +}; +#define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats)) + static const char et_self_tests[][ETH_GSTRING_LEN] = { "MAC Loopback test", "PHY Loopback test", @@ -253,17 +259,15 @@ be_get_ethtool_stats(struct net_device *netdev, { struct be_adapter *adapter = netdev_priv(netdev); struct be_rx_obj *rxo; + struct be_tx_obj *txo; void *p = NULL; - int i, j; + int i, j, base; for (i = 0; i < ETHTOOL_STATS_NUM; i++) { switch (et_stats[i].type) { case NETSTAT: p = &netdev->stats; break; - case DRVSTAT_TX: - p = &ad |