Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking updates from David Miller: 1) Fix flexcan build on big endian, from Arnd Bergmann 2) Correctly attach cpsw to GPIO bitbang MDIO drive, from Stefan Roese 3) udp_add_offload has to use GFP_ATOMIC since it can be invoked from non-sleepable contexts. From Or Gerlitz 4) vxlan_gro_receive() does not iterate over all possible flows properly, fix also from Or Gerlitz 5) CAN core doesn't use a proper SKB destructor when it hooks up sockets to SKBs. Fix from Oliver Hartkopp 6) ip_tunnel_xmit() can use an uninitialized route pointer, fix from Eric Dumazet 7) Fix address family assignment in IPVS, from Michal Kubecek 8) Fix ath9k build on ARM, from Sujith Manoharan 9) Make sure fail_over_mac only applies for the correct bonding modes, from Ding Tianhong 10) The udp offload code doesn't use RCU correctly, from Shlomo Pongratz 11) Handle gigabit features properly in generic PHY code, from Florian Fainelli 12) Don't blindly invoke link operations in rtnl_link_get_slave_info_data_size, they are optional. Fix from Fernando Luis Vazquez Cao 13) Add USB IDs for Netgear Aircard 340U, from Bjørn Mork 14) Handle netlink packet padding properly in openvswitch, from Thomas Graf 15) Fix oops when deleting chains in nf_tables, from Patrick McHardy 16) Fix RX stalls in xen-netback driver, from Zoltan Kiss 17) Fix deadlock in mac80211 stack, from Emmanuel Grumbach 18) inet_nlmsg_size() forgets to consider ifa_cacheinfo, fix from Geert Uytterhoeven 19) tg3_change_mtu() can deadlock, fix from Nithin Sujir 20) Fix regression in setting SCTP local source addresses on accepted sockets, caused by some generic ipv6 socket changes. Fix from Matija Glavinic Pecotic 21) IPPROTO_* must be pure defines, otherwise module aliases don't get constructed properly. Fix from Jan Moskyto 22) IPV6 netconsole setup doesn't work properly unless an explicit source address is specified, fix from Sabrina Dubroca 23) Use __GFP_NORETRY for high order skb page allocations in sock_alloc_send_pskb and skb_page_frag_refill. From Eric Dumazet 24) Fix a regression added in netconsole over bridging, from Cong Wang 25) TCP uses an artificial offset of 1ms for SRTT, but this doesn't jive well with TCP pacing which needs the SRTT to be accurate. Fix from Eric Dumazet 26) Several cases of missing header file includes from Rashika Kheria 27) Add ZTE MF667 device ID to qmi_wwan driver, from Raymond Wanyoike 28) TCP Small Queues doesn't handle nonagle properly in some corner cases, fix from Eric Dumazet 29) Remove extraneous read_unlock in bond_enslave, whoops. From Ding Tianhong 30) Fix 9p trans_virtio handling of vmalloc buffers, from Richard Yao * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (136 commits) 6lowpan: fix lockdep splats alx: add missing stats_lock spinlock init 9p/trans_virtio.c: Fix broken zero-copy on vmalloc() buffers bonding: remove unwanted bond lock for enslave processing USB2NET : SR9800 : One chip USB2.0 USB2NET SR9800 Device Driver Support tcp: tsq: fix nonagle handling bridge: Prevent possible race condition in br_fdb_change_mac_address bridge: Properly check if local fdb entry can be deleted when deleting vlan bridge: Properly check if local fdb entry can be deleted in br_fdb_delete_by_port bridge: Properly check if local fdb entry can be deleted in br_fdb_change_mac_address bridge: Fix the way to check if a local fdb entry can be deleted bridge: Change local fdb entries whenever mac address of bridge device changes bridge: Fix the way to find old local fdb entries in br_fdb_change_mac_address bridge: Fix the way to insert new local fdb entries in br_fdb_changeaddr bridge: Fix the way to find old local fdb entries in br_fdb_changeaddr tcp: correct code comment stating 3 min timeout for FIN_WAIT2, we only do 1 min net: vxge: Remove unused device pointer net: qmi_wwan: add ZTE MF667 3c59x: Remove unused pointer in vortex_eisa_cleanup() net: fix 'ip rule' iif/oif device rename ...
This commit is contained in:
commit
16e5a2ed59
@ -1,7 +1,8 @@
|
||||
* Allwinner EMAC ethernet controller
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "allwinner,sun4i-emac".
|
||||
- compatible: should be "allwinner,sun4i-a10-emac" (Deprecated:
|
||||
"allwinner,sun4i-emac")
|
||||
- reg: address and length of the register set for the device.
|
||||
- interrupts: interrupt for the device
|
||||
- phy: A phandle to a phy node defining the PHY address (as the reg
|
||||
@ -14,7 +15,7 @@ Optional properties:
|
||||
Example:
|
||||
|
||||
emac: ethernet@01c0b000 {
|
||||
compatible = "allwinner,sun4i-emac";
|
||||
compatible = "allwinner,sun4i-a10-emac";
|
||||
reg = <0x01c0b000 0x1000>;
|
||||
interrupts = <55>;
|
||||
clocks = <&ahb_gates 17>;
|
||||
|
@ -1,7 +1,8 @@
|
||||
* Allwinner A10 MDIO Ethernet Controller interface
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "allwinner,sun4i-mdio".
|
||||
- compatible: should be "allwinner,sun4i-a10-mdio"
|
||||
(Deprecated: "allwinner,sun4i-mdio").
|
||||
- reg: address and length of the register set for the device.
|
||||
|
||||
Optional properties:
|
||||
@ -9,7 +10,7 @@ Optional properties:
|
||||
|
||||
Example at the SoC level:
|
||||
mdio@01c0b080 {
|
||||
compatible = "allwinner,sun4i-mdio";
|
||||
compatible = "allwinner,sun4i-a10-mdio";
|
||||
reg = <0x01c0b080 0x14>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -117,6 +117,7 @@ static void usage(char *progname)
|
||||
" -f val adjust the ptp clock frequency by 'val' ppb\n"
|
||||
" -g get the ptp clock time\n"
|
||||
" -h prints this message\n"
|
||||
" -i val index for event/trigger\n"
|
||||
" -k val measure the time offset between system and phc clock\n"
|
||||
" for 'val' times (Maximum 25)\n"
|
||||
" -p val enable output with a period of 'val' nanoseconds\n"
|
||||
@ -154,6 +155,7 @@ int main(int argc, char *argv[])
|
||||
int capabilities = 0;
|
||||
int extts = 0;
|
||||
int gettime = 0;
|
||||
int index = 0;
|
||||
int oneshot = 0;
|
||||
int pct_offset = 0;
|
||||
int n_samples = 0;
|
||||
@ -167,7 +169,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
progname = strrchr(argv[0], '/');
|
||||
progname = progname ? 1+progname : argv[0];
|
||||
while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghk:p:P:sSt:v"))) {
|
||||
while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghi:k:p:P:sSt:v"))) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
oneshot = atoi(optarg);
|
||||
@ -190,6 +192,9 @@ int main(int argc, char *argv[])
|
||||
case 'g':
|
||||
gettime = 1;
|
||||
break;
|
||||
case 'i':
|
||||
index = atoi(optarg);
|
||||
break;
|
||||
case 'k':
|
||||
pct_offset = 1;
|
||||
n_samples = atoi(optarg);
|
||||
@ -301,7 +306,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (extts) {
|
||||
memset(&extts_request, 0, sizeof(extts_request));
|
||||
extts_request.index = 0;
|
||||
extts_request.index = index;
|
||||
extts_request.flags = PTP_ENABLE_FEATURE;
|
||||
if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) {
|
||||
perror("PTP_EXTTS_REQUEST");
|
||||
@ -375,7 +380,7 @@ int main(int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
memset(&perout_request, 0, sizeof(perout_request));
|
||||
perout_request.index = 0;
|
||||
perout_request.index = index;
|
||||
perout_request.start.sec = ts.tv_sec + 2;
|
||||
perout_request.start.nsec = 0;
|
||||
perout_request.period.sec = 0;
|
||||
|
@ -7196,7 +7196,7 @@ S: Maintained
|
||||
F: drivers/net/ethernet/rdc/r6040.c
|
||||
|
||||
RDS - RELIABLE DATAGRAM SOCKETS
|
||||
M: Venkat Venkatsubra <venkat.x.venkatsubra@oracle.com>
|
||||
M: Chien Yen <chien.yen@oracle.com>
|
||||
L: rds-devel@oss.oracle.com (moderated for non-subscribers)
|
||||
S: Supported
|
||||
F: net/rds/
|
||||
|
@ -315,7 +315,7 @@
|
||||
ranges;
|
||||
|
||||
emac: ethernet@01c0b000 {
|
||||
compatible = "allwinner,sun4i-emac";
|
||||
compatible = "allwinner,sun4i-a10-emac";
|
||||
reg = <0x01c0b000 0x1000>;
|
||||
interrupts = <55>;
|
||||
clocks = <&ahb_gates 17>;
|
||||
@ -323,7 +323,7 @@
|
||||
};
|
||||
|
||||
mdio@01c0b080 {
|
||||
compatible = "allwinner,sun4i-mdio";
|
||||
compatible = "allwinner,sun4i-a10-mdio";
|
||||
reg = <0x01c0b080 0x14>;
|
||||
status = "disabled";
|
||||
#address-cells = <1>;
|
||||
|
@ -278,7 +278,7 @@
|
||||
ranges;
|
||||
|
||||
emac: ethernet@01c0b000 {
|
||||
compatible = "allwinner,sun4i-emac";
|
||||
compatible = "allwinner,sun4i-a10-emac";
|
||||
reg = <0x01c0b000 0x1000>;
|
||||
interrupts = <55>;
|
||||
clocks = <&ahb_gates 17>;
|
||||
@ -286,7 +286,7 @@
|
||||
};
|
||||
|
||||
mdio@01c0b080 {
|
||||
compatible = "allwinner,sun4i-mdio";
|
||||
compatible = "allwinner,sun4i-a10-mdio";
|
||||
reg = <0x01c0b080 0x14>;
|
||||
status = "disabled";
|
||||
#address-cells = <1>;
|
||||
|
@ -340,7 +340,7 @@
|
||||
ranges;
|
||||
|
||||
emac: ethernet@01c0b000 {
|
||||
compatible = "allwinner,sun4i-emac";
|
||||
compatible = "allwinner,sun4i-a10-emac";
|
||||
reg = <0x01c0b000 0x1000>;
|
||||
interrupts = <0 55 4>;
|
||||
clocks = <&ahb_gates 17>;
|
||||
@ -348,7 +348,7 @@
|
||||
};
|
||||
|
||||
mdio@01c0b080 {
|
||||
compatible = "allwinner,sun4i-mdio";
|
||||
compatible = "allwinner,sun4i-a10-mdio";
|
||||
reg = <0x01c0b080 0x14>;
|
||||
status = "disabled";
|
||||
#address-cells = <1>;
|
||||
|
@ -810,7 +810,7 @@ prfeatureind(char *dest, u_char *p)
|
||||
dp += sprintf(dp, " octet 3 ");
|
||||
dp += prbits(dp, *p, 8, 8);
|
||||
*dp++ = '\n';
|
||||
if (!(*p++ & 80)) {
|
||||
if (!(*p++ & 0x80)) {
|
||||
dp += sprintf(dp, " octet 4 ");
|
||||
dp += prbits(dp, *p++, 8, 8);
|
||||
*dp++ = '\n';
|
||||
|
@ -1270,9 +1270,13 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||
|
||||
if (slave_ops->ndo_set_mac_address == NULL) {
|
||||
if (!bond_has_slaves(bond)) {
|
||||
pr_warning("%s: Warning: The first slave device specified does not support setting the MAC address. Setting fail_over_mac to active.",
|
||||
bond_dev->name);
|
||||
bond->params.fail_over_mac = BOND_FOM_ACTIVE;
|
||||
pr_warn("%s: Warning: The first slave device specified does not support setting the MAC address.\n",
|
||||
bond_dev->name);
|
||||
if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
|
||||
bond->params.fail_over_mac = BOND_FOM_ACTIVE;
|
||||
pr_warn("%s: Setting fail_over_mac to active for active-backup mode.\n",
|
||||
bond_dev->name);
|
||||
}
|
||||
} else if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) {
|
||||
pr_err("%s: Error: The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active.\n",
|
||||
bond_dev->name);
|
||||
@ -1315,7 +1319,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||
*/
|
||||
memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN);
|
||||
|
||||
if (!bond->params.fail_over_mac) {
|
||||
if (!bond->params.fail_over_mac ||
|
||||
bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
|
||||
/*
|
||||
* Set slave to master's mac address. The application already
|
||||
* set the master's mac address to that of the first slave
|
||||
@ -1505,7 +1510,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||
slave_dev->npinfo = bond->dev->npinfo;
|
||||
if (slave_dev->npinfo) {
|
||||
if (slave_enable_netpoll(new_slave)) {
|
||||
read_unlock(&bond->lock);
|
||||
pr_info("Error, %s: master_dev is using netpoll, "
|
||||
"but new slave device does not support netpoll.\n",
|
||||
bond_dev->name);
|
||||
@ -1579,7 +1583,8 @@ err_close:
|
||||
dev_close(slave_dev);
|
||||
|
||||
err_restore_mac:
|
||||
if (!bond->params.fail_over_mac) {
|
||||
if (!bond->params.fail_over_mac ||
|
||||
bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
|
||||
/* XXX TODO - fom follow mode needs to change master's
|
||||
* MAC if this slave's MAC is in use by the bond, or at
|
||||
* least print a warning.
|
||||
@ -1672,7 +1677,8 @@ static int __bond_release_one(struct net_device *bond_dev,
|
||||
|
||||
bond->current_arp_slave = NULL;
|
||||
|
||||
if (!all && !bond->params.fail_over_mac) {
|
||||
if (!all && (!bond->params.fail_over_mac ||
|
||||
bond->params.mode != BOND_MODE_ACTIVEBACKUP)) {
|
||||
if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) &&
|
||||
bond_has_slaves(bond))
|
||||
pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n",
|
||||
@ -1769,7 +1775,8 @@ static int __bond_release_one(struct net_device *bond_dev,
|
||||
/* close slave before restoring its mac address */
|
||||
dev_close(slave_dev);
|
||||
|
||||
if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) {
|
||||
if (bond->params.fail_over_mac != BOND_FOM_ACTIVE ||
|
||||
bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
|
||||
/* restore original ("permanent") mac address */
|
||||
memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
|
||||
addr.sa_family = slave_dev->type;
|
||||
@ -3431,7 +3438,8 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
|
||||
/* If fail_over_mac is enabled, do nothing and return success.
|
||||
* Returning an error causes ifenslave to fail.
|
||||
*/
|
||||
if (bond->params.fail_over_mac)
|
||||
if (bond->params.fail_over_mac &&
|
||||
bond->params.mode == BOND_MODE_ACTIVEBACKUP)
|
||||
return 0;
|
||||
|
||||
if (!is_valid_ether_addr(sa->sa_data))
|
||||
|
@ -104,7 +104,7 @@ config CAN_JANZ_ICAN3
|
||||
|
||||
config CAN_FLEXCAN
|
||||
tristate "Support for Freescale FLEXCAN based chips"
|
||||
depends on (ARM && CPU_LITTLE_ENDIAN) || PPC
|
||||
depends on ARM || PPC
|
||||
---help---
|
||||
Say Y here if you want to support for Freescale FlexCAN.
|
||||
|
||||
|
@ -323,19 +323,10 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
}
|
||||
|
||||
if (!priv->echo_skb[idx]) {
|
||||
struct sock *srcsk = skb->sk;
|
||||
|
||||
if (atomic_read(&skb->users) != 1) {
|
||||
struct sk_buff *old_skb = skb;
|
||||
|
||||
skb = skb_clone(old_skb, GFP_ATOMIC);
|
||||
kfree_skb(old_skb);
|
||||
if (!skb)
|
||||
return;
|
||||
} else
|
||||
skb_orphan(skb);
|
||||
|
||||
skb->sk = srcsk;
|
||||
skb = can_create_echo_skb(skb);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
/* make settings for echo to reduce code in irq context */
|
||||
skb->protocol = htons(ETH_P_CAN);
|
||||
|
@ -235,9 +235,12 @@ static const struct can_bittiming_const flexcan_bittiming_const = {
|
||||
};
|
||||
|
||||
/*
|
||||
* Abstract off the read/write for arm versus ppc.
|
||||
* Abstract off the read/write for arm versus ppc. This
|
||||
* assumes that PPC uses big-endian registers and everything
|
||||
* else uses little-endian registers, independent of CPU
|
||||
* endianess.
|
||||
*/
|
||||
#if defined(__BIG_ENDIAN)
|
||||
#if defined(CONFIG_PPC)
|
||||
static inline u32 flexcan_read(void __iomem *addr)
|
||||
{
|
||||
return in_be32(addr);
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/can/skb.h>
|
||||
#include <linux/can/error.h>
|
||||
|
||||
#include <linux/mfd/janz.h>
|
||||
@ -1133,20 +1134,9 @@ static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg)
|
||||
*/
|
||||
static void ican3_put_echo_skb(struct ican3_dev *mod, struct sk_buff *skb)
|
||||
{
|
||||
struct sock *srcsk = skb->sk;
|
||||
|
||||
if (atomic_read(&skb->users) != 1) {
|
||||
struct sk_buff *old_skb = skb;
|
||||
|
||||
skb = skb_clone(old_skb, GFP_ATOMIC);
|
||||
kfree_skb(old_skb);
|
||||
if (!skb)
|
||||
return;
|
||||
} else {
|
||||
skb_orphan(skb);
|
||||
}
|
||||
|
||||
skb->sk = srcsk;
|
||||
skb = can_create_echo_skb(skb);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
/* save this skb for tx interrupt echo handling */
|
||||
skb_queue_tail(&mod->echoq, skb);
|
||||
@ -1322,7 +1312,7 @@ static int ican3_napi(struct napi_struct *napi, int budget)
|
||||
|
||||
/* process all communication messages */
|
||||
while (true) {
|
||||
struct ican3_msg msg;
|
||||
struct ican3_msg uninitialized_var(msg);
|
||||
ret = ican3_recv_msg(mod, &msg);
|
||||
if (ret)
|
||||
break;
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/can/skb.h>
|
||||
#include <linux/slab.h>
|
||||
#include <net/rtnetlink.h>
|
||||
|
||||
@ -109,25 +110,23 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += cfd->len;
|
||||
}
|
||||
kfree_skb(skb);
|
||||
consume_skb(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
/* perform standard echo handling for CAN network interfaces */
|
||||
|
||||
if (loop) {
|
||||
struct sock *srcsk = skb->sk;
|
||||
|
||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
skb = can_create_echo_skb(skb);
|
||||
if (!skb)
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
/* receive with packet counting */
|
||||
skb->sk = srcsk;
|
||||
vcan_rx(skb, dev);
|
||||
} else {
|
||||
/* no looped packets => no counting */
|
||||
kfree_skb(skb);
|
||||
consume_skb(skb);
|
||||
}
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
@ -3294,7 +3294,6 @@ static int __init vortex_init(void)
|
||||
|
||||
static void __exit vortex_eisa_cleanup(void)
|
||||
{
|
||||
struct vortex_private *vp;
|
||||
void __iomem *ioaddr;
|
||||
|
||||
#ifdef CONFIG_EISA
|
||||
@ -3303,7 +3302,6 @@ static void __exit vortex_eisa_cleanup(void)
|
||||
#endif
|
||||
|
||||
if (compaq_net_device) {
|
||||
vp = netdev_priv(compaq_net_device);
|
||||
ioaddr = ioport_map(compaq_net_device->base_addr,
|
||||
VORTEX_TOTAL_SIZE);
|
||||
|
||||
|
@ -929,6 +929,9 @@ static int emac_resume(struct platform_device *dev)
|
||||
}
|
||||
|
||||
static const struct of_device_id emac_of_match[] = {
|
||||
{.compatible = "allwinner,sun4i-a10-emac",},
|
||||
|
||||
/* Deprecated */
|
||||
{.compatible = "allwinner,sun4i-emac",},
|
||||
{},
|
||||
};
|
||||
|
@ -1292,6 +1292,7 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
alx = netdev_priv(netdev);
|
||||
spin_lock_init(&alx->hw.mdio_lock);
|
||||
spin_lock_init(&alx->irq_lock);
|
||||
spin_lock_init(&alx->stats_lock);
|
||||
alx->dev = netdev;
|
||||
alx->hw.pdev = pdev;
|
||||
alx->msg_enable = NETIF_MSG_LINK | NETIF_MSG_HW | NETIF_MSG_IFUP |
|
||||
|
@ -85,7 +85,7 @@ MODULE_FIRMWARE(FW_RV2P_FILE_09_Ax);
|
||||
|
||||
static int disable_msi = 0;
|
||||
|
||||
module_param(disable_msi, int, 0);
|
||||
module_param(disable_msi, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
|
||||
|
||||
typedef enum {
|
||||
|
@ -936,7 +936,7 @@ static inline int bnx2x_func_start(struct bnx2x *bp)
|
||||
else /* CHIP_IS_E1X */
|
||||
start_params->network_cos_mode = FW_WRR;
|
||||
|
||||
start_params->gre_tunnel_mode = IPGRE_TUNNEL;
|
||||
start_params->gre_tunnel_mode = L2GRE_TUNNEL;
|
||||
start_params->gre_tunnel_rss = GRE_INNER_HEADERS_RSS;
|
||||
|
||||
return bnx2x_func_state_change(bp, &func_params);
|
||||
|
@ -95,29 +95,29 @@ MODULE_FIRMWARE(FW_FILE_NAME_E1H);
|
||||
MODULE_FIRMWARE(FW_FILE_NAME_E2);
|
||||
|
||||
int bnx2x_num_queues;
|
||||
module_param_named(num_queues, bnx2x_num_queues, int, 0);
|
||||
module_param_named(num_queues, bnx2x_num_queues, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(num_queues,
|
||||
" Set number of queues (default is as a number of CPUs)");
|
||||
|
||||
static int disable_tpa;
|
||||
module_param(disable_tpa, int, 0);
|
||||
module_param(disable_tpa, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature");
|
||||
|
||||
static int int_mode;
|
||||
module_param(int_mode, int, 0);
|
||||
module_param(int_mode, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X "
|
||||
"(1 INT#x; 2 MSI)");
|
||||
|
||||
static int dropless_fc;
|
||||
module_param(dropless_fc, int, 0);
|
||||
module_param(dropless_fc, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(dropless_fc, " Pause on exhausted host ring");
|
||||
|
||||
static int mrrs = -1;
|
||||
module_param(mrrs, int, 0);
|
||||
module_param(mrrs, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(mrrs, " Force Max Read Req Size (0..3) (for debug)");
|
||||
|
||||
static int debug;
|
||||
module_param(debug, int, 0);
|
||||
module_param(debug, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(debug, " Default debug msglevel");
|
||||
|
||||
struct workqueue_struct *bnx2x_wq;
|
||||
|
@ -1446,12 +1446,12 @@ static void bnx2x_vf_igu_reset(struct bnx2x *bp, struct bnx2x_virtf *vf)
|
||||
if (vf->cfg_flags & VF_CFG_INT_SIMD)
|
||||
val |= IGU_VF_CONF_SINGLE_ISR_EN;
|
||||
val &= ~IGU_VF_CONF_PARENT_MASK;
|
||||
val |= BP_FUNC(bp) << IGU_VF_CONF_PARENT_SHIFT; /* parent PF */
|
||||
val |= (BP_ABS_FUNC(bp) >> 1) << IGU_VF_CONF_PARENT_SHIFT;
|
||||
REG_WR(bp, IGU_REG_VF_CONFIGURATION, val);
|
||||
|
||||
DP(BNX2X_MSG_IOV,
|
||||
"value in IGU_REG_VF_CONFIGURATION of vf %d after write %x\n",
|
||||
vf->abs_vfid, REG_RD(bp, IGU_REG_VF_CONFIGURATION));
|
||||
"value in IGU_REG_VF_CONFIGURATION of vf %d after write is 0x%08x\n",
|
||||
vf->abs_vfid, val);
|
||||
|
||||
bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
|
||||
|
||||
|
@ -2609,13 +2609,14 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
|
||||
|
||||
tg3_writephy(tp, MII_CTRL1000, phy9_orig);
|
||||
|
||||
if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32)) {
|
||||
reg32 &= ~0x3000;
|
||||
tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
|
||||
} else if (!err)
|
||||
err = -EBUSY;
|
||||
err = tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return err;
|
||||
reg32 &= ~0x3000;
|
||||
tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tg3_carrier_off(struct tg3 *tp)
|
||||
@ -14113,12 +14114,12 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
|
||||
|
||||
tg3_netif_stop(tp);
|
||||
|
||||
tg3_set_mtu(dev, tp, new_mtu);
|
||||
|
||||
tg3_full_lock(tp, 1);
|
||||
|
||||
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
||||
|
||||
tg3_set_mtu(dev, tp, new_mtu);
|
||||
|
||||
/* Reset PHY, otherwise the read DMA engine will be in a mode that
|
||||
* breaks all requests to 256 bytes.
|
||||
*/
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
@ -51,6 +52,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
|
||||
#define ETH_HASH0 0x48
|
||||
#define ETH_HASH1 0x4c
|
||||
#define ETH_TXCTRL 0x50
|
||||
#define ETH_END 0x54
|
||||
|
||||
/* mode register */
|
||||
#define MODER_RXEN (1 << 0) /* receive enable */
|
||||
@ -179,6 +181,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
|
||||
* @membase: pointer to buffer memory region
|
||||
* @dma_alloc: dma allocated buffer size
|
||||
* @io_region_size: I/O memory region size
|
||||
* @num_bd: number of buffer descriptors
|
||||
* @num_tx: number of send buffers
|
||||
* @cur_tx: last send buffer written
|
||||
* @dty_tx: last buffer actually sent
|
||||
@ -199,6 +202,7 @@ struct ethoc {
|
||||
int dma_alloc;
|
||||
resource_size_t io_region_size;
|
||||
|
||||
unsigned int num_bd;
|
||||
unsigned int num_tx;
|
||||
unsigned int cur_tx;
|
||||
unsigned int dty_tx;
|
||||
@ -216,6 +220,7 @@ struct ethoc {
|
||||
|
||||
struct phy_device *phy;
|
||||
struct mii_bus *mdio;
|
||||
struct clk *clk;
|
||||
s8 phy_id;
|
||||
};
|
||||
|
||||
@ -688,6 +693,11 @@ static int ethoc_mdio_probe(struct net_device *dev)
|
||||
}
|
||||
|
||||
priv->phy = phy;
|
||||
phy->advertising &= ~(ADVERTISED_1000baseT_Full |
|
||||
ADVERTISED_1000baseT_Half);
|
||||
phy->supported &= ~(SUPPORTED_1000baseT_Full |
|
||||
SUPPORTED_1000baseT_Half);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -890,6 +900,102 @@ out:
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static int ethoc_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct ethoc *priv = netdev_priv(dev);
|
||||
struct phy_device *phydev = priv->phy;
|
||||
|
||||
if (!phydev)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return phy_ethtool_gset(phydev, cmd);
|
||||
}
|
||||
|
||||
static int ethoc_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct ethoc *priv = netdev_priv(dev);
|
||||
struct phy_device *phydev = priv->phy;
|
||||
|
||||
if (!phydev)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return phy_ethtool_sset(phydev, cmd);
|
||||
}
|
||||
|
||||
static int ethoc_get_regs_len(struct net_device *netdev)
|
||||
{
|
||||
return ETH_END;
|
||||
}
|
||||
|
||||
static void ethoc_get_regs(struct net_device *dev, struct ethtool_regs *regs,
|
||||
void *p)
|
||||
{
|
||||
struct ethoc *priv = netdev_priv(dev);
|
||||
u32 *regs_buff = p;
|
||||
unsigned i;
|
||||
|
||||
regs->version = 0;
|
||||
for (i = 0; i < ETH_END / sizeof(u32); ++i)
|
||||
regs_buff[i] = ethoc_read(priv, i * sizeof(u32));
|
||||
}
|
||||
|
||||
static void ethoc_get_ringparam(struct net_device *dev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct ethoc *priv = netdev_priv(dev);
|
||||
|
||||
ring->rx_max_pending = priv->num_bd - 1;
|
||||
ring->rx_mini_max_pending = 0;
|
||||
ring->rx_jumbo_max_pending = 0;
|
||||
ring->tx_max_pending = priv->num_bd - 1;
|
||||
|
||||
ring->rx_pending = priv->num_rx;
|
||||
ring->rx_mini_pending = 0;
|
||||
ring->rx_jumbo_pending = 0;
|
||||
ring->tx_pending = priv->num_tx;
|
||||
}
|
||||
|
||||
static int ethoc_set_ringparam(struct net_device *dev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct ethoc *priv = netdev_priv(dev);
|
||||
|
||||
if (ring->tx_pending < 1 || ring->rx_pending < 1 ||
|
||||
ring->tx_pending + ring->rx_pending > priv->num_bd)
|
||||
return -EINVAL;
|
||||
if (ring->rx_mini_pending || ring->rx_jumbo_pending)
|
||||
return -EINVAL;
|
||||
|
||||
if (netif_running(dev)) {
|
||||
netif_tx_disable(dev);
|
||||
ethoc_disable_rx_and_tx(priv);
|
||||
ethoc_disable_irq(priv, INT_MASK_TX | INT_MASK_RX);
|
||||
synchronize_irq(dev->irq);
|
||||
}
|
||||
|
||||
priv->num_tx = rounddown_pow_of_two(ring->tx_pending);
|
||||
priv->num_rx = ring->rx_pending;
|
||||
ethoc_init_ring(priv, dev->mem_start);
|
||||
|
||||
if (netif_running(dev)) {
|
||||
ethoc_enable_irq(priv, INT_MASK_TX | INT_MASK_RX);
|
||||
ethoc_enable_rx_and_tx(priv);
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ethtool_ops ethoc_ethtool_ops = {
|
||||
.get_settings = ethoc_get_settings,
|
||||
.set_settings = ethoc_set_settings,
|
||||
.get_regs_len = ethoc_get_regs_len,
|
||||
.get_regs = ethoc_get_regs,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_ringparam = ethoc_get_ringparam,
|
||||
.set_ringparam = ethoc_set_ringparam,
|
||||
.get_ts_info = ethtool_op_get_ts_info,
|
||||
};
|
||||
|
||||
static const struct net_device_ops ethoc_netdev_ops = {
|
||||
.ndo_open = ethoc_open,
|
||||
.ndo_stop = ethoc_stop,
|
||||
@ -917,6 +1023,8 @@ static int ethoc_probe(struct platform_device *pdev)
|
||||
int num_bd;
|
||||
int ret = 0;
|
||||
bool random_mac = false;
|
||||
struct ethoc_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
u32 eth_clkfreq = pdata ? pdata->eth_clkfreq : 0;
|
||||
|
||||
/* allocate networking device */
|
||||
netdev = alloc_etherdev(sizeof(struct ethoc));
|
||||
@ -1016,6 +1124,7 @@ static int ethoc_probe(struct platform_device *pdev)
|
||||
ret = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
priv->num_bd = num_bd;
|
||||
/* num_tx must be a power of two */
|
||||
priv->num_tx = rounddown_pow_of_two(num_bd >> 1);
|
||||
priv->num_rx = num_bd - priv->num_tx;
|
||||
@ -1030,8 +1139,7 @@ static int ethoc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* Allow the platform setup code to pass in a MAC address. */
|
||||
if (dev_get_platdata(&pdev->dev)) {
|
||||
struct ethoc_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
if (pdata) {
|
||||
memcpy(netdev->dev_addr, pdata->hwaddr, IFHWADDRLEN);
|
||||
priv->phy_id = pdata->phy_id;
|
||||
} else {
|
||||
@ -1069,6 +1177,27 @@ static int ethoc_probe(struct platform_device *pdev)
|
||||
if (random_mac)
|
||||
netdev->addr_assign_type = NET_ADDR_RANDOM;
|
||||
|
||||
/* Allow the platform setup code to adjust MII management bus clock. */
|
||||
if (!eth_clkfreq) {
|
||||
struct clk *clk = devm_clk_get(&pdev->dev, NULL);
|
||||
|
||||
if (!IS_ERR(clk)) {
|
||||
priv->clk = clk;
|
||||
clk_prepare_enable(clk);
|
||||
eth_clkfreq = clk_get_rate(clk);
|
||||
}
|
||||
}
|
||||
if (eth_clkfreq) {
|
||||
u32 clkdiv = MIIMODER_CLKDIV(eth_clkfreq / 2500000 + 1);
|
||||
|
||||
if (!clkdiv)
|
||||
clkdiv = 2;
|
||||
dev_dbg(&pdev->dev, "setting MII clkdiv to %u\n", clkdiv);
|
||||
ethoc_write(priv, MIIMODER,
|
||||
(ethoc_read(priv, MIIMODER) & MIIMODER_NOPRE) |
|
||||
clkdiv);
|
||||
}
|
||||
|
||||
/* register MII bus */
|
||||
priv->mdio = mdiobus_alloc();
|
||||
if (!priv->mdio) {
|
||||
@ -1111,6 +1240,7 @@ static int ethoc_probe(struct platform_device *pdev)
|
||||
netdev->netdev_ops = ðoc_netdev_ops;
|
||||
netdev->watchdog_timeo = ETHOC_TIMEOUT;
|
||||
netdev->features |= 0;
|
||||
netdev->ethtool_ops = ðoc_ethtool_ops;
|
||||
|
||||
/* setup NAPI */
|
||||
netif_napi_add(netdev, &priv->napi, ethoc_poll, 64);
|
||||
@ -1133,6 +1263,8 @@ free_mdio:
|
||||
kfree(priv->mdio->irq);
|
||||
mdiobus_free(priv->mdio);
|
||||
free:
|
||||
if (priv->clk)
|
||||
clk_disable_unprepare(priv->clk);
|
||||
free_netdev(netdev);
|
||||
out:
|
||||
return ret;
|
||||
@ -1157,6 +1289,8 @@ static int ethoc_remove(struct platform_device *pdev)
|
||||
kfree(priv->mdio->irq);
|
||||
mdiobus_free(priv->mdio);
|
||||
}
|
||||
if (priv->clk)
|
||||
clk_disable_unprepare(priv->clk);
|
||||
unregister_netdev(netdev);
|
||||
free_netdev(netdev);
|
||||
}
|
||||
|
@ -3034,7 +3034,7 @@ static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake)
|
||||
*enable_wake = false;
|
||||
}
|
||||
|
||||
pci_disable_device(pdev);
|
||||
pci_clear_master(pdev);
|
||||
}
|
||||
|
||||
static int __e100_power_off(struct pci_dev *pdev, bool wake)
|
||||
|
@ -726,9 +726,6 @@ static int vxge_learn_mac(struct vxgedev *vdev, u8 *mac_header)
|
||||
int vpath_idx = 0;
|
||||
enum vxge_hw_status status = VXGE_HW_OK;
|
||||
struct vxge_vpath *vpath = NULL;
|
||||
struct __vxge_hw_device *hldev;
|
||||
|
||||
hldev = pci_get_drvdata(vdev->pdev);
|
||||
|
||||
mac_address = (u8 *)&mac_addr;
|
||||
memcpy(mac_address, mac_header, ETH_ALEN);
|
||||
@ -2443,9 +2440,6 @@ static void vxge_rem_msix_isr(struct vxgedev *vdev)
|
||||
|
||||
static void vxge_rem_isr(struct vxgedev *vdev)
|
||||
{
|
||||
struct __vxge_hw_device *hldev;
|
||||
hldev = pci_get_drvdata(vdev->pdev);
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
if (vdev->config.intr_type == MSI_X) {
|
||||
vxge_rem_msix_isr(vdev);
|
||||
|
@ -429,7 +429,9 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
/* Transfer ownership of the skb to the final buffer */
|
||||
#ifdef EFX_USE_PIO
|
||||
finish_packet:
|
||||
#endif
|
||||
buffer->skb = skb;
|
||||
buffer->flags = EFX_TX_BUF_SKB | dma_flags;
|
||||
|
||||
|
@ -1878,8 +1878,18 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
|
||||
mdio_node = of_find_node_by_phandle(be32_to_cpup(parp));
|
||||
phyid = be32_to_cpup(parp+1);
|
||||
mdio = of_find_device_by_node(mdio_node);
|
||||
snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
|
||||
PHY_ID_FMT, mdio->name, phyid);
|
||||
|
||||
if (strncmp(mdio->name, "gpio", 4) == 0) {
|
||||
/* GPIO bitbang MDIO driver attached */
|
||||
struct mii_bus *bus = dev_get_drvdata(&mdio->dev);
|
||||
|
||||
snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
|
||||
PHY_ID_FMT, bus->id, phyid);
|
||||
} else {
|
||||
/* davinci MDIO driver attached */
|
||||
snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
|
||||
PHY_ID_FMT, mdio->name, phyid);
|
||||
}
|
||||
|
||||
mac_addr = of_get_mac_address(slave_node);
|
||||
if (mac_addr)
|
||||
|
@ -210,13 +210,6 @@ config KINGSUN_DONGLE
|
||||
To compile it as a module, choose M here: the module will be called
|
||||
kingsun-sir.
|
||||
|
||||
config EP7211_DONGLE
|
||||
tristate "Cirrus Logic clps711x I/R support"
|
||||
depends on IRTTY_SIR && ARCH_CLPS711X && IRDA
|
||||
help
|
||||
Say Y here if you want to build support for the Cirrus logic
|
||||
EP7211 chipset's infrared module.
|
||||
|
||||
config KSDAZZLE_DONGLE
|
||||
tristate "KingSun Dazzle IrDA-USB dongle"
|
||||
depends on IRDA && USB
|
||||
|
@ -35,7 +35,6 @@ obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o
|
||||
obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o
|
||||
obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o
|
||||
obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o
|
||||
obj-$(CONFIG_EP7211_DONGLE) += ep7211-sir.o
|
||||
obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o
|
||||
obj-$(CONFIG_KSDAZZLE_DONGLE) += ksdazzle-sir.o
|
||||
obj-$(CONFIG_KS959_DONGLE) += ks959-sir.o
|
||||
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* IR port driver for the Cirrus Logic CLPS711X processors
|
||||
*
|
||||
* Copyright 2001, Blue Mug Inc. All rights reserved.
|
||||
* Copyright 2007, Samuel Ortiz <samuel@sortiz.org>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include "sir-dev.h"
|
||||
|
||||
static int clps711x_dongle_open(struct sir_dev *dev)
|
||||
{
|
||||
unsigned int syscon;
|
||||
|
||||
/* Turn on the SIR encoder. */
|
||||
syscon = clps_readl(SYSCON1);
|
||||
syscon |= SYSCON1_SIREN;
|
||||
clps_writel(syscon, SYSCON1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clps711x_dongle_close(struct sir_dev *dev)
|
||||
{
|
||||
unsigned int syscon;
|
||||
|
||||
/* Turn off the SIR encoder. */
|
||||
syscon = clps_readl(SYSCON1);
|
||||
syscon &= ~SYSCON1_SIREN;
|
||||
clps_writel(syscon, SYSCON1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dongle_driver clps711x_dongle = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "EP7211 IR driver",
|
||||
.type = IRDA_EP7211_DONGLE,
|
||||
.open = clps711x_dongle_open,
|
||||
.close = clps711x_dongle_close,
|
||||
};
|
||||
|
||||
static int clps711x_sir_probe(struct platform_device *pdev)
|
||||
{
|
||||
return irda_register_dongle(&clps711x_dongle);
|
||||
}
|
||||
|
||||
static int clps711x_sir_remove(struct platform_device *pdev)
|
||||
{
|
||||
return irda_unregister_dongle(&clps711x_dongle);
|
||||
}
|
||||
|
||||
static struct platform_driver clps711x_sir_driver = {
|
||||
.driver = {
|
||||
.name = "sir-clps711x",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = clps711x_sir_probe,
|
||||
.remove = clps711x_sir_remove,
|
||||
};
|
||||
module_platform_driver(clps711x_sir_driver);
|
||||
|
||||
MODULE_AUTHOR("Samuel Ortiz <samuel@sortiz.org>");
|
||||
MODULE_DESCRIPTION("EP7211 IR dongle driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("irda-dongle-13"); /* IRDA_EP7211_DONGLE */
|
@ -437,7 +437,10 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
|
||||
if (on) {
|
||||
gpio_num = gpio_tab[EXTTS0_GPIO + index];
|
||||
evnt |= (gpio_num & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
|
||||
evnt |= EVNT_RISE;
|
||||
if (rq->extts.flags & PTP_FALLING_EDGE)
|
||||
evnt |= EVNT_FALL;
|
||||
else
|
||||
evnt |= EVNT_RISE;
|
||||
}
|
||||
ext_write(0, phydev, PAGE5, PTP_EVNT, evnt);
|
||||
return 0;
|
||||
@ -1058,6 +1061,13 @@ static void dp83640_remove(struct phy_device *phydev)
|
||||
kfree(dp83640);
|
||||
}
|
||||
|
||||
static int dp83640_config_init(struct phy_device *phydev)
|
||||
{
|
||||
enable_status_frames(phydev, true);
|
||||
ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dp83640_ack_interrupt(struct phy_device *phydev)
|
||||
{
|
||||
int err = phy_read(phydev, MII_DP83640_MISR);
|
||||
@ -1195,11 +1205,6 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
|
||||
|
||||
mutex_lock(&dp83640->clock->extreg_lock);
|
||||
|
||||
if (dp83640->hwts_tx_en || dp83640->hwts_rx_en) {
|
||||
enable_status_frames(phydev, true);
|
||||
ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE);
|
||||
}
|
||||
|
||||
ext_write(0, phydev, PAGE5, PTP_TXCFG0, txcfg0);
|
||||
ext_write(0, phydev, PAGE5, PTP_RXCFG0, rxcfg0);
|
||||
|
||||
@ -1281,6 +1286,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,
|
||||
}
|
||||
/* fall through */
|
||||
case HWTSTAMP_TX_ON:
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
||||
skb_queue_tail(&dp83640->tx_queue, skb);
|
||||
schedule_work(&dp83640->ts_work);
|
||||
break;
|
||||
@ -1330,6 +1336,7 @@ static struct phy_driver dp83640_driver = {
|
||||
.flags = PHY_HAS_INTERRUPT,
|
||||
.probe = dp83640_probe,
|
||||
.remove = dp83640_remove,
|
||||
.config_init = dp83640_config_init,
|
||||
.config_aneg = genphy_config_aneg,
|
||||
.read_status = genphy_read_status,
|
||||
.ack_interrupt = dp83640_ack_interrupt,
|
||||
|
@ -170,6 +170,9 @@ static int sun4i_mdio_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct of_device_id sun4i_mdio_dt_ids[] = {
|
||||
{ .compatible = "allwinner,sun4i-a10-mdio" },
|
||||
|
||||
/* Deprecated */
|
||||
{ .compatible = "allwinner,sun4i-mdio" },
|
||||
{ }
|
||||
};
|
||||
|
@ -719,7 +719,7 @@ int phy_resume(struct phy_device *phydev)
|
||||
static int genphy_config_advert(struct phy_device *phydev)
|
||||
{
|
||||
u32 advertise;
|
||||
int oldadv, adv;
|
||||
int oldadv, adv, bmsr;
|
||||
int err, changed = 0;
|
||||
|
||||
/* Only allow advertising what this PHY supports */
|
||||
@ -744,26 +744,36 @@ static int genphy_config_advert(struct phy_device *phydev)
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
bmsr = phy_read(phydev, MII_BMSR);
|
||||
if (bmsr < 0)
|
||||
return bmsr;
|
||||
|
||||
/* Per 802.3-2008, Section 22.2.4.2.16 Extended status all
|
||||
* 1000Mbits/sec capable PHYs shall have the BMSR_ESTATEN bit set to a
|
||||
* logical 1.
|
||||
*/
|
||||
if (!(bmsr & BMSR_ESTATEN))
|
||||
return changed;
|
||||
|
||||
/* Configure gigabit if it's supported */
|
||||
adv = phy_read(phydev, MII_CTRL1000);
|
||||
if (adv < 0)
|
||||
return adv;
|
||||
|
||||
oldadv = adv;
|
||||
adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
|
||||
|
||||
if (phydev->supported & (SUPPORTED_1000baseT_Half |
|
||||
SUPPORTED_1000baseT_Full)) {
|
||||
adv = phy_read(phydev, MII_CTRL1000);
|
||||
if (adv < 0)
|
||||
return adv;
|
||||
|
||||
oldadv = adv;
|
||||
adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
|
||||
adv |= ethtool_adv_to_mii_ctrl1000_t(advertise);
|
||||
|
||||
if (adv != oldadv) {
|
||||
err = phy_write(phydev, MII_CTRL1000, adv);
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (adv != oldadv)
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
err = phy_write(phydev, MII_CTRL1000, adv);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
@ -292,6 +292,22 @@ config USB_NET_SR9700
|
||||
This option adds support for CoreChip-sz SR9700 based USB 1.1
|
||||
10/100 Ethernet adapters.
|
||||
|
||||
config USB_NET_SR9800
|
||||
tristate "CoreChip-sz SR9800 based USB 2.0 10/100 ethernet devices"
|
||||
depends on USB_USBNET
|
||||
select CRC32
|
||||
default y
|
||||
---help---
|
||||
Say Y if you want to use one of the following 100Mbps USB Ethernet
|
||||
device based on the CoreChip-sz SR9800 chip.
|
||||
|
||||
This driver makes the adapter appear as a normal Ethernet interface,
|
||||
typically on eth0, if it is the only ethernet device, or perhaps on
|
||||
eth1, if you have a PCI or ISA ethernet card installed.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called sr9800.
|
||||
|
||||
config USB_NET_SMSC75XX
|
||||
tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices"
|
||||
depends on USB_USBNET
|
||||
|
@ -15,6 +15,7 @@ obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o r815x.o
|
||||
obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o
|
||||
obj-$(CONFIG_USB_NET_DM9601) += dm9601.o
|
||||
obj-$(CONFIG_USB_NET_SR9700) += sr9700.o
|
||||
obj-$(CONFIG_USB_NET_SR9800) += sr9800.o
|
||||
obj-$(CONFIG_USB_NET_SMSC75XX) += smsc75xx.o
|
||||
obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o
|
||||
obj-$(CONFIG_USB_NET_GL620A) += gl620a.o
|
||||
|
@ -1201,16 +1201,18 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb)
|
||||
struct hso_serial *serial = urb->context;
|
||||
int status = urb->status;
|
||||
|
||||
D4("\n--- Got serial_read_bulk callback %02x ---", status);
|
||||
|
||||
/* sanity check */
|
||||
if (!serial) {
|
||||
D1("serial == NULL");
|
||||
return;
|
||||
} else if (status) {
|
||||
}
|
||||
if (status) {
|
||||
handle_usb_error(status, __func__, serial->parent);
|
||||
return;
|
||||
}
|
||||
|
||||
D4("\n--- Got serial_read_bulk callback %02x ---", status);
|
||||
D1("Actual length = %d\n", urb->actual_length);
|
||||
DUMP1(urb->transfer_buffer, urb->actual_length);
|
||||
|
||||
@ -1218,25 +1220,13 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb)
|
||||
if (serial->port.count == 0)
|
||||
return;
|
||||
|
||||
if (status == 0) {
|
||||
if (serial->parent->port_spec & HSO_INFO_CRC_BUG)
|
||||
fix_crc_bug(urb, serial->in_endp->wMaxPacketSize);
|
||||
/* Valid data, handle RX data */
|
||||
spin_lock(&serial->serial_lock);
|
||||
serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1;
|
||||
put_rxbuf_data_and_resubmit_bulk_urb(serial);
|
||||
spin_unlock(&serial->serial_lock);
|
||||
} else if (status == -ENOENT || status == -ECONNRESET) {
|
||||
/* Unlinked - check for throttled port. */
|
||||
D2("Port %d, successfully unlinked urb", serial->minor);
|
||||
spin_lock(&serial->serial_lock);
|
||||
serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
|
||||
hso_resubmit_rx_bulk_urb(serial, urb);
|
||||
spin_unlock(&serial->serial_lock);
|
||||
} else {
|
||||
D2("Port %d, status = %d for read urb", serial->minor, status);
|
||||
return;
|
||||
}
|
||||
if (serial->parent->port_spec & HSO_INFO_CRC_BUG)
|
||||
fix_crc_bug(urb, serial->in_endp->wMaxPacketSize);
|
||||
/* Valid data, handle RX data */
|
||||
spin_lock(&serial->serial_lock);
|
||||
serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1;
|
||||
put_rxbuf_data_and_resubmit_bulk_urb(serial);
|
||||
spin_unlock(&serial->serial_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -712,6 +712,7 @@ static const struct usb_device_id products[] = {
|
||||
{QMI_FIXED_INTF(0x19d2, 0x1255, 3)},
|
||||
{QMI_FIXED_INTF(0x19d2, 0x1255, 4)},
|
||||
{QMI_FIXED_INTF(0x19d2, 0x1256, 4)},
|
||||
{QMI_FIXED_INTF(0x19d2, 0x1270, 5)}, /* ZTE MF667 */
|
||||
{QMI_FIXED_INTF(0x19d2, 0x1401, 2)},
|
||||
{QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */
|
||||
{QMI_FIXED_INTF(0x19d2, 0x1424, 2)},
|
||||
@ -723,6 +724,7 @@ static const struct usb_device_id products[] = {
|
||||
{QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */
|
||||
{QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */
|
||||
{QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */
|
||||
{QMI_FIXED_INTF(0x1199, 0x9051, 8)}, /* Netgear AirCard 340U */
|
||||
{QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
|
||||
{QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */
|
||||
{QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */
|
||||
|
@ -2273,15 +2273,6 @@ static int rtl8152_open(struct net_device *netdev)
|
||||
struct r8152 *tp = netdev_priv(netdev);
|
||||
int res = 0;
|
||||
|
||||
res = usb_submit_urb(tp->intr_urb, GFP_KERNEL);
|
||||
if (res) {
|
||||
if (res == -ENODEV)
|
||||
netif_device_detach(tp->netdev);
|
||||
netif_warn(tp, ifup, netdev, "intr_urb submit failed: %d\n",
|
||||
res);
|
||||
return res;
|
||||
}
|
||||
|
||||
rtl8152_set_speed(tp, AUTONEG_ENABLE,
|
||||
tp->mii.supports_gmii ? SPEED_1000 : SPEED_100,
|
||||
DUPLEX_FULL);
|
||||
@ -2289,6 +2280,14 @@ static int rtl8152_open(struct net_device *netdev)
|
||||
netif_carrier_off(netdev);
|
||||
netif_start_queue(netdev);
|
||||
set_bit(WORK_ENABLE, &tp->flags);
|
||||
res = usb_submit_urb(tp->intr_urb, GFP_KERNEL);
|
||||
if (res) {
|
||||
if (res == -ENODEV)
|
||||
netif_device_detach(tp->netdev);
|
||||
netif_warn(tp, ifup, netdev, "intr_urb submit failed: %d\n",
|
||||
res);
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -2298,8 +2297,8 @@ static int rtl8152_close(struct net_device *netdev)
|
||||
struct r8152 *tp = netdev_priv(netdev);
|
||||
int res = 0;
|
||||
|
||||
usb_kill_urb(tp->intr_urb);
|
||||
clear_bit(WORK_ENABLE, &tp->flags);
|
||||
usb_kill_urb(tp->intr_urb);
|
||||
cancel_delayed_work_sync(&tp->schedule);
|
||||
netif_stop_queue(netdev);
|
||||
tasklet_disable(&tp->tl);
|
||||
|
870
drivers/net/usb/sr9800.c
Normal file
870
drivers/net/usb/sr9800.c
Normal file
@ -0,0 +1,870 @@
|
||||
/* CoreChip-sz SR9800 one chip USB 2.0 Ethernet Devices
|
||||
*
|
||||
* Author : Liu Junliang <liujunliang_ljl@163.com>
|
||||
*
|
||||
* Based on asix_common.c, asix_devices.c
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/usb/usbnet.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/if_vlan.h>
|
||||
|
||||
#include "sr9800.h"
|
||||
|
||||
static int sr_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
|
||||
u16 size, void *data)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = usbnet_read_cmd(dev, cmd, SR_REQ_RD_REG, value, index,
|
||||
data, size);
|
||||
if ((err != size) && (err >= 0))
|
||||
err = -EINVAL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sr_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
|
||||
u16 size, void *data)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = usbnet_write_cmd(dev, cmd, SR_REQ_WR_REG, value, index,
|
||||
data, size);
|
||||
if ((err != size) && (err >= 0))
|
||||
err = -EINVAL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
sr_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
|
||||
u16 size, void *data)
|
||||
{
|
||||
usbnet_write_cmd_async(dev, cmd, SR_REQ_WR_REG, value, index, data,
|
||||
size);
|
||||
}
|
||||
|
||||
static int sr_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
while (offset + sizeof(u32) < skb->len) {
|
||||
struct sk_buff *sr_skb;
|
||||
u16 size;
|
||||
u32 header = get_unaligned_le32(skb->data + offset);
|
||||
|
||||
offset += sizeof(u32);
|
||||
/* get the packet length */
|
||||
size = (u16) (header & 0x7ff);
|
||||
if (size != ((~header >> 16) & 0x07ff)) {
|
||||
netdev_err(dev->net, "%s : Bad Header Length\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) ||
|
||||
(size + offset > skb->len)) {
|
||||
netdev_err(dev->net, "%s : Bad RX Length %d\n",
|
||||
__func__, size);
|
||||
return 0;
|
||||
}
|
||||
sr_skb = netdev_alloc_skb_ip_align(dev->net, size);
|
||||
if (!sr_skb)
|
||||
return 0;
|
||||
|
||||
skb_put(sr_skb, size);
|
||||
memcpy(sr_skb->data, skb->data + offset, size);
|
||||
usbnet_skb_return(dev, sr_skb);
|
||||
|
||||
offset += (size + 1) & 0xfffe;
|
||||
}
|
||||
|
||||
if (skb->len != offset) {
|
||||
netdev_err(dev->net, "%s : Bad SKB Length %d\n", __func__,
|
||||
skb->len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct sk_buff *sr_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
|
||||
gfp_t flags)
|
||||
{
|
||||
int headroom = skb_headroom(skb);
|
||||
int tailroom = skb_tailroom(skb);
|
||||
u32 padbytes = 0xffff0000;
|
||||
u32 packet_len;
|
||||
int padlen;
|
||||
|
||||
padlen = ((skb->len + 4) % (dev->maxpacket - 1)) ? 0 : 4;
|
||||
|
||||
if ((!skb_cloned(skb)) && ((headroom + tailroom) >= (4 + padlen))) {
|
||||
if ((headroom < 4) || (tailroom < padlen)) {
|
||||
skb->data = memmove(skb->head + 4, skb->data,
|
||||
skb->len);
|
||||
skb_set_tail_pointer(skb, skb->len);
|
||||
}
|
||||
} else {
|
||||
struct sk_buff *skb2;
|
||||
skb2 = skb_copy_expand(skb, 4, padlen, flags);
|
||||
dev_kfree_skb_any(skb);
|
||||
skb = skb2;
|
||||
if (!skb)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
skb_push(skb, 4);
|
||||
packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
|
||||
cpu_to_le32s(&packet_len);
|
||||
skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
|
||||
|
||||
if (padlen) {
|
||||
cpu_to_le32s(&padbytes);
|
||||
memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
|
||||
skb_put(skb, sizeof(padbytes));
|
||||
}
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static void sr_status(struct usbnet *dev, struct urb *urb)
|
||||
{
|
||||
struct sr9800_int_data *event;
|
||||
int link;
|
||||
|
||||
if (urb->actual_length < 8)
|
||||
return;
|
||||
|
||||
event = urb->transfer_buffer;
|
||||
link = event->link & 0x01;
|
||||
if (netif_carrier_ok(dev->net) != link) {
|
||||
usbnet_link_change(dev, link, 1);
|
||||
netdev_dbg(dev->net, "Link Status is: %d\n", link);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int sr_set_sw_mii(struct usbnet *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sr_write_cmd(dev, SR_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
|
||||
if (ret < 0)
|
||||
netdev_err(dev->net, "Failed to enable software MII access\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int sr_set_hw_mii(struct usbnet *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sr_write_cmd(dev, SR_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
|
||||
if (ret < 0)
|
||||
netdev_err(dev->net, "Failed to enable hardware MII access\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int sr_get_phy_addr(struct usbnet *dev)
|
||||
{
|
||||
u8 buf[2];
|
||||
int ret;
|
||||
|
||||
ret = sr_read_cmd(dev, SR_CMD_READ_PHY_ID, 0, 0, 2, buf);
|
||||
if (ret < 0) {
|
||||
netdev_err(dev->net, "%s : Error reading PHYID register:%02x\n",
|
||||
__func__, ret);
|
||||
goto out;
|
||||
}
|
||||
netdev_dbg(dev->net, "%s : returning 0x%04x\n", __func__,
|
||||
*((__le16 *)buf));
|
||||
|
||||
ret = buf[1];
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sr_sw_reset(struct usbnet *dev, u8 flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sr_write_cmd(dev, SR_CMD_SW_RESET, flags, 0, 0, NULL);
|
||||
if (ret < 0)
|
||||
netdev_err(dev->net, "Failed to send software reset:%02x\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u16 sr_read_rx_ctl(struct usbnet *dev)
|
||||
{
|
||||
__le16 v;
|
||||
int ret;
|
||||
|
||||
ret = sr_read_cmd(dev, SR_CMD_READ_RX_CTL, 0, 0, 2, &v);
|
||||
if (ret < 0) {
|
||||
netdev_err(dev->net, "Error reading RX_CTL register:%02x\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = le16_to_cpu(v);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sr_write_rx_ctl(struct usbnet *dev, u16 mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode);
|
||||
ret = sr_write_cmd(dev, SR_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
|
||||
if (ret < 0)
|
||||
netdev_err(dev->net,
|
||||
"Failed to write RX_CTL mode to 0x%04x:%02x\n",
|
||||
mode, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u16 sr_read_medium_status(struct usbnet *dev)
|
||||
{
|
||||
__le16 v;
|
||||
int ret;
|
||||
|
||||
ret = sr_read_cmd(dev, SR_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v);
|
||||
if (ret < 0) {
|
||||
netdev_err(dev->net,
|
||||
"Error reading Medium Status register:%02x\n", ret);
|
||||
return ret; /* TODO: callers not checking for error ret */
|
||||
}
|
||||
|
||||
return le16_to_cpu(v);
|
||||
}
|
||||
|
||||
static int sr_write_medium_mode(struct usbnet *dev, u16 mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode);
|
||||
ret = sr_write_cmd(dev, SR_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
|
||||
if (ret < 0)
|
||||
netdev_err(dev->net,
|
||||
"Failed to write Medium Mode mode to 0x%04x:%02x\n",
|
||||
mode, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sr_write_gpio(struct usbnet *dev, u16 value, int sleep)
|
||||
{
|
||||
int ret;
|
||||
|
||||
netdev_dbg(dev->net, "%s : value = 0x%04x\n", __func__, value);
|
||||
ret = sr_write_cmd(dev, SR_CMD_WRITE_GPIOS, value, 0, 0, NULL);
|
||||
if (ret < 0)
|
||||
netdev_err(dev->net, "Failed to write GPIO value 0x%04x:%02x\n",
|
||||
value, ret);
|
||||
if (sleep)
|
||||
msleep(sleep);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* SR9800 have a 16-bit RX_CTL value */
|
||||
static void sr_set_multicast(struct net_device *net)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
struct sr_data *data = (struct sr_data *)&dev->data;
|
||||
u16 rx_ctl = SR_DEFAULT_RX_CTL;
|
||||
|
||||
if (net->flags & IFF_PROMISC) {
|
||||
rx_ctl |= SR_RX_CTL_PRO;
|
||||
} else if (net->flags & IFF_ALLMULTI ||
|
||||
netdev_mc_count(net) > SR_MAX_MCAST) {
|
||||
rx_ctl |= SR_RX_CTL_AMALL;
|
||||
} else if (netdev_mc_empty(net)) {
|
||||
/* just broadcast and directed */
|
||||
} else {
|
||||
/* We use the 20 byte dev->data
|
||||
* for our 8 byte filter buffer
|
||||
* to avoid allocating memory that
|
||||
* is tricky to free later
|
||||
*/
|
||||
struct netdev_hw_addr *ha;
|
||||
u32 crc_bits;
|
||||
|
||||
memset(data->multi_filter, 0, SR_MCAST_FILTER_SIZE);
|
||||
|
||||
/* Build the multicast hash filter. */
|
||||
netdev_for_each_mc_addr(ha, net) {
|
||||
crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
|
||||
data->multi_filter[crc_bits >> 3] |=
|
||||
1 << (crc_bits & 7);
|
||||
}
|
||||
|
||||
sr_write_cmd_async(dev, SR_CMD_WRITE_MULTI_FILTER, 0, 0,
|
||||
SR_MCAST_FILTER_SIZE, data->multi_filter);
|
||||
|
||||
rx_ctl |= SR_RX_CTL_AM;
|
||||
}
|
||||
|
||||
sr_write_cmd_async(dev, SR_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
|
||||
}
|
||||
|
||||
static int sr_mdio_read(struct net_device *net, int phy_id, int loc)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
__le16 res;
|
||||
|
||||
mutex_lock(&dev->phy_mutex);
|
||||
sr_set_sw_mii(dev);
|
||||
sr_read_cmd(dev, SR_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, &res);
|
||||
sr_set_hw_mii(dev);
|
||||
mutex_unlock(&dev->phy_mutex);
|
||||
|
||||
netdev_dbg(dev->net,
|
||||
"%s : phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", __func__,
|
||||
phy_id, loc, le16_to_cpu(res));
|
||||
|
||||
return le16_to_cpu(res);
|
||||
}
|
||||
|
||||
static void
|
||||
sr_mdio_write(struct net_device *net, int phy_id, int loc, int val)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
__le16 res = cpu_to_le16(val);
|
||||
|
||||
netdev_dbg(dev->net,
|
||||
"%s : phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", __func__,
|
||||
phy_id, loc, val);
|
||||
mutex_lock(&dev->phy_mutex);
|
||||
sr_set_sw_mii(dev);
|
||||
sr_write_cmd(dev, SR_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res);
|
||||
sr_set_hw_mii(dev);
|
||||
mutex_unlock(&dev->phy_mutex);
|
||||
}
|
||||
|
||||
/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
|
||||
static u32 sr_get_phyid(struct usbnet *dev)
|
||||
{
|
||||
int phy_reg;
|
||||
u32 phy_id;
|
||||
int i;
|
||||
|
||||
/* Poll for the rare case the FW or phy isn't ready yet. */
|
||||
for (i = 0; i < 100; i++) {
|
||||
phy_reg = sr_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1);
|
||||
if (phy_reg != 0 && phy_reg != 0xFFFF)
|
||||
break;
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
if (phy_reg <= 0 || phy_reg == 0xFFFF)
|
||||
return 0;
|
||||
|
||||
phy_id = (phy_reg & 0xffff) << 16;
|
||||
|
||||
phy_reg = sr_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID2);
|
||||
if (phy_reg < 0)
|
||||
return 0;
|
||||
|
||||
phy_id |= (phy_reg & 0xffff);
|
||||
|
||||
return phy_id;
|
||||
}
|
||||
|
||||
static void
|
||||
sr_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
u8 opt;
|
||||
|
||||
if (sr_read_cmd(dev, SR_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
|
||||
wolinfo->supported = 0;
|
||||
wolinfo->wolopts = 0;
|
||||
return;
|
||||
}
|
||||
wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
|
||||
wolinfo->wolopts = 0;
|
||||
if (opt & SR_MONITOR_LINK)
|
||||
wolinfo->wolopts |= WAKE_PHY;
|
||||
if (opt & SR_MONITOR_MAGIC)
|
||||
wolinfo->wolopts |= WAKE_MAGIC;
|
||||
}
|
||||
|
||||
static int
|
||||
sr_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
u8 opt = 0;
|
||||
|
||||
if (wolinfo->wolopts & WAKE_PHY)
|
||||
opt |= SR_MONITOR_LINK;
|
||||
if (wolinfo->wolopts & WAKE_MAGIC)
|
||||
opt |= SR_MONITOR_MAGIC;
|
||||
|
||||
if (sr_write_cmd(dev, SR_CMD_WRITE_MONITOR_MODE,
|
||||
opt, 0, 0, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sr_get_eeprom_len(struct net_device *net)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
struct sr_data *data = (struct sr_data *)&dev->data;
|
||||
|
||||
return data->eeprom_len;
|
||||
}
|
||||
|
||||
static int sr_get_eeprom(struct net_device *net,
|
||||
struct ethtool_eeprom *eeprom, u8 *data)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
__le16 *ebuf = (__le16 *)data;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* Crude hack to ensure that we don't overwrite memory
|
||||
* if an odd length is supplied
|
||||
*/
|
||||
if (eeprom->len % 2)
|
||||
return -EINVAL;
|
||||
|
||||
eeprom->magic = SR_EEPROM_MAGIC;
|
||||
|
||||
/* sr9800 returns 2 bytes from eeprom on read */
|
||||
for (i = 0; i < eeprom->len / 2; i++) {
|
||||
ret = sr_read_cmd(dev, SR_CMD_READ_EEPROM, eeprom->offset + i,
|
||||
0, 2, &ebuf[i]);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sr_get_drvinfo(struct net_device *net,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
struct sr_data *data = (struct sr_data *)&dev->data;
|
||||
|
||||
/* Inherit standard device info */
|
||||
usbnet_get_drvinfo(net, info);
|
||||
strncpy(info->driver, DRIVER_NAME, sizeof(info->driver));
|
||||
strncpy(info->version, DRIVER_VERSION, sizeof(info->version));
|
||||
info->eedump_len = data->eeprom_len;
|
||||
}
|
||||
|
||||
static u32 sr_get_link(struct net_device *net)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
|
||||
return mii_link_ok(&dev->mii);
|
||||
}
|
||||
|
||||
static int sr_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
|
||||
return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
|
||||
}
|
||||
|
||||
static int sr_set_mac_address(struct net_device *net, void *p)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
struct sr_data *data = (struct sr_data *)&dev->data;
|
||||
struct sockaddr *addr = p;
|
||||
|
||||
if (netif_running(net))
|
||||
return -EBUSY;
|
||||
if (!is_valid_ether_addr(addr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
|
||||
|
||||
/* We use the 20 byte dev->data
|
||||
* for our 6 byte mac buffer
|
||||
* to avoid allocating memory that
|
||||
* is tricky to free later
|
||||
*/
|
||||
memcpy(data->mac_addr, addr->sa_data, ETH_ALEN);
|
||||
sr_write_cmd_async(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
|
||||
data->mac_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ethtool_ops sr9800_ethtool_ops = {
|
||||
.get_drvinfo = sr_get_drvinfo,
|
||||
.get_link = sr_get_link,
|
||||
.get_msglevel = usbnet_get_msglevel,
|
||||
.set_msglevel = usbnet_set_msglevel,
|
||||
.get_wol = sr_get_wol,
|
||||
.set_wol = sr_set_wol,
|
||||
.get_eeprom_len = sr_get_eeprom_len,
|
||||
.get_eeprom = sr_get_eeprom,
|
||||
.get_settings = usbnet_get_settings,
|
||||
.set_settings = usbnet_set_settings,
|
||||
.nway_reset = usbnet_nway_reset,
|
||||
};
|
||||
|
||||
static int sr9800_link_reset(struct usbnet *dev)
|
||||
{
|
||||
struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
|
||||
u16 mode;
|
||||
|
||||
mii_check_media(&dev->mii, 1, 1);
|
||||
mii_ethtool_gset(&dev->mii, &ecmd);
|
||||
mode = SR9800_MEDIUM_DEFAULT;
|
||||
|
||||
if (ethtool_cmd_speed(&ecmd) != SPEED_100)
|
||||
mode &= ~SR_MEDIUM_PS;
|
||||
|
||||
if (ecmd.duplex != DUPLEX_FULL)
|
||||
mode &= ~SR_MEDIUM_FD;
|
||||
|
||||
netdev_dbg(dev->net, "%s : speed: %u duplex: %d mode: 0x%04x\n",
|
||||
__func__, ethtool_cmd_speed(&ecmd), ecmd.duplex, mode);
|
||||
|
||||
sr_write_medium_mode(dev, mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int sr9800_set_default_mode(struct usbnet *dev)
|
||||
{
|
||||
u16 rx_ctl;
|
||||
int ret;
|
||||
|
||||
sr_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
|
||||
sr_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
|
||||
ADVERTISE_ALL | ADVERTISE_CSMA);
|
||||
mii_nway_restart(&dev->mii);
|
||||
|
||||
ret = sr_write_medium_mode(dev, SR9800_MEDIUM_DEFAULT);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = sr_write_cmd(dev, SR_CMD_WRITE_IPG012,
|
||||
SR9800_IPG0_DEFAULT | SR9800_IPG1_DEFAULT,
|
||||
SR9800_IPG2_DEFAULT, 0, NULL);
|
||||
if (ret < 0) {
|
||||
netdev_dbg(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
|
||||
ret = sr_write_rx_ctl(dev, SR_DEFAULT_RX_CTL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
rx_ctl = sr_read_rx_ctl(dev);
|
||||
netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n",
|
||||
rx_ctl);
|
||||
|
||||
rx_ctl = sr_read_medium_status(dev);
|
||||
netdev_dbg(dev->net, "Medium Status:0x%04x after all initializations\n",
|
||||
rx_ctl);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sr9800_reset(struct usbnet *dev)
|
||||
{
|
||||
struct sr_data *data = (struct sr_data *)&dev->data;
|
||||
int ret, embd_phy;
|
||||
u16 rx_ctl;
|
||||
|
||||
ret = sr_write_gpio(dev,
|
||||
SR_GPIO_RSE | SR_GPIO_GPO_2 | SR_GPIO_GPO2EN, 5);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
embd_phy = ((sr_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0);
|
||||
|
||||
ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL);
|
||||
if (ret < 0) {
|
||||
netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_PRL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
msleep(150);
|
||||
|
||||
ret = sr_sw_reset(dev, SR_SWRESET_CLEAR);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
msleep(150);
|
||||
|
||||
if (embd_phy) {
|
||||
ret = sr_sw_reset(dev, SR_SWRESET_IPRL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
} else {
|
||||
ret = sr_sw_reset(dev, SR_SWRESET_PRTE);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
msleep(150);
|
||||
rx_ctl = sr_read_rx_ctl(dev);
|
||||
netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl);
|
||||
ret = sr_write_rx_ctl(dev, 0x0000);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
rx_ctl = sr_read_rx_ctl(dev);
|
||||
netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
|
||||
|
||||
ret = sr_sw_reset(dev, SR_SWRESET_PRL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
msleep(150);
|
||||
|
||||
ret = sr_sw_reset(dev, SR_SWRESET_IPRL | SR_SWRESET_PRL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
msleep(150);
|
||||
|
||||
ret = sr9800_set_default_mode(dev);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* Rewrite MAC address */
|
||||
memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN);
|
||||
ret = sr_write_cmd(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
|
||||
data->mac_addr);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct net_device_ops sr9800_netdev_ops = {
|
||||
.ndo_open = usbnet_open,
|
||||
.ndo_stop = usbnet_stop,
|
||||
.ndo_start_xmit = usbnet_start_xmit,
|
||||
.ndo_tx_timeout = usbnet_tx_timeout,
|
||||
.ndo_change_mtu = usbnet_change_mtu,
|
||||
.ndo_set_mac_address = sr_set_mac_address,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_do_ioctl = sr_ioctl,
|
||||
.ndo_set_rx_mode = sr_set_multicast,
|
||||
};
|
||||
|
||||
static int sr9800_phy_powerup(struct usbnet *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* set the embedded Ethernet PHY in power-down state */
|
||||
ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_IPRL);
|
||||
if (ret < 0) {
|
||||
netdev_err(dev->net, "Failed to power down PHY : %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(20);
|
||||
|
||||
/* set the embedded Ethernet PHY in power-up state */
|
||||
ret = sr_sw_reset(dev, SR_SWRESET_IPRL);
|
||||
if (ret < 0) {
|
||||
netdev_err(dev->net, "Failed to reset PHY: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(600);
|
||||
|
||||
/* set the embedded Ethernet PHY in reset state */
|
||||
ret = sr_sw_reset(dev, SR_SWRESET_CLEAR);
|
||||
if (ret < 0) {
|
||||
netdev_err(dev->net, "Failed to power up PHY: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(20);
|
||||
|
||||
/* set the embedded Ethernet PHY in power-up state */
|
||||
ret = sr_sw_reset(dev, SR_SWRESET_IPRL);
|
||||
if (ret < 0) {
|
||||
netdev_err(dev->net, "Failed to reset PHY: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sr9800_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
{
|
||||
struct sr_data *data = (struct sr_data *)&dev->data;
|
||||
u16 led01_mux, led23_mux;
|
||||
int ret, embd_phy;
|
||||
u32 phyid;
|
||||
u16 rx_ctl;
|
||||
|
||||
data->eeprom_len = SR9800_EEPROM_LEN;
|
||||
|
||||
usbnet_get_endpoints(dev, intf);
|
||||
|
||||
/* LED Setting Rule :
|
||||
* AABB:CCDD
|
||||
* AA : MFA0(LED0)
|
||||
* BB : MFA1(LED1)
|
||||
* CC : MFA2(LED2), Reserved for SR9800
|
||||
* DD : MFA3(LED3), Reserved for SR9800
|
||||
*/
|
||||
led01_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_LINK;
|
||||
led23_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_TX_ACTIVE;
|
||||
ret = sr_write_cmd(dev, SR_CMD_LED_MUX, led01_mux, led23_mux, 0, NULL);
|
||||
if (ret < 0) {
|
||||
netdev_err(dev->net, "set LINK LED failed : %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get the MAC address */
|
||||
ret = sr_read_cmd(dev, SR_CMD_READ_NODE_ID, 0, 0, ETH_ALEN,
|
||||
dev->net->dev_addr);
|
||||
if (ret < 0) {
|
||||
netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
netdev_dbg(dev->net, "mac addr : %pM\n", dev->net->dev_addr);
|
||||
|
||||
/* Initialize MII structure */
|
||||
dev->mii.dev = dev->net;
|
||||
dev->mii.mdio_read = sr_mdio_read;
|
||||
dev->mii.mdio_write = sr_mdio_write;
|
||||
dev->mii.phy_id_mask = 0x1f;
|
||||
dev->mii.reg_num_mask = 0x1f;
|
||||
dev->mii.phy_id = sr_get_phy_addr(dev);
|
||||
|
||||
dev->net->netdev_ops = &sr9800_netdev_ops;
|
||||
dev->net->ethtool_ops = &sr9800_ethtool_ops;
|
||||
|
||||
embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0);
|
||||
/* Reset the PHY to normal operation mode */
|
||||
ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL);
|
||||
if (ret < 0) {
|
||||
netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Init PHY routine */
|
||||
ret = sr9800_phy_powerup(dev);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
rx_ctl = sr_read_rx_ctl(dev);
|
||||
netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl);
|
||||
ret = sr_write_rx_ctl(dev, 0x0000);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
rx_ctl = sr_read_rx_ctl(dev);
|
||||
netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
|
||||
|
||||
/* Read PHYID register *AFTER* the PHY was reset properly */
|
||||
phyid = sr_get_phyid(dev);
|
||||
netdev_dbg(dev->net, "PHYID=0x%08x\n", phyid);
|
||||
|
||||
/* medium mode setting */
|
||||
ret = sr9800_set_default_mode(dev);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (dev->udev->speed == USB_SPEED_HIGH) {
|
||||
ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE,
|
||||
SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].byte_cnt,
|
||||
SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].threshold,
|
||||
0, NULL);
|
||||
if (ret < 0) {
|
||||
netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
dev->rx_urb_size =
|
||||
SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].size;
|
||||
} else {
|
||||
ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE,
|
||||
SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].byte_cnt,
|
||||
SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].threshold,
|
||||
0, NULL);
|
||||
if (ret < 0) {
|
||||
netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
dev->rx_urb_size =
|
||||
SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].size;
|
||||
}
|
||||
netdev_dbg(dev->net, "%s : setting rx_urb_size with : %ld\n", __func__,
|
||||
dev->rx_urb_size);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct driver_info sr9800_driver_info = {
|
||||
.description = "CoreChip SR9800 USB 2.0 Ethernet",
|
||||
.bind = sr9800_bind,
|
||||
.status = sr_status,
|
||||
.link_reset = sr9800_link_reset,
|
||||
.reset = sr9800_reset,
|
||||
.flags = DRIVER_FLAG,
|
||||
.rx_fixup = sr_rx_fixup,
|
||||
.tx_fixup = sr_tx_fixup,
|
||||
};
|
||||
|
||||
static const struct usb_device_id products[] = {
|
||||
{
|
||||
USB_DEVICE(0x0fe6, 0x9800), /* SR9800 Device */
|
||||
.driver_info = (unsigned long) &sr9800_driver_info,
|
||||
},
|
||||
{}, /* END */
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, products);
|
||||
|
||||
static struct usb_driver sr_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = products,
|
||||
.probe = usbnet_probe,
|
||||
.suspend = usbnet_suspend,
|
||||
.resume = usbnet_resume,
|
||||
.disconnect = usbnet_disconnect,
|
||||
.supports_autosuspend = 1,
|
||||
};
|
||||
|
||||
module_usb_driver(sr_driver);
|
||||
|
||||
MODULE_AUTHOR("Liu Junliang <liujunliang_ljl@163.com");
|
||||
MODULE_VERSION(DRIVER_VERSION);
|
||||
MODULE_DESCRIPTION("SR9800 USB 2.0 USB2NET Dev : http://www.corechip-sz.com");
|
||||
MODULE_LICENSE("GPL");
|
202
drivers/net/usb/sr9800.h
Normal file
202
drivers/net/usb/sr9800.h
Normal file
@ -0,0 +1,202 @@
|
||||
/* CoreChip-sz SR9800 one chip USB 2.0 Ethernet Devices
|
||||
*
|
||||
* Author : Liu Junliang <liujunliang_ljl@163.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#ifndef _SR9800_H
|
||||
#define _SR9800_H
|
||||
|
||||
/* SR9800 spec. command table on Linux Platform */
|
||||
|
||||
/* command : Software Station Management Control Reg */
|
||||
#define SR_CMD_SET_SW_MII 0x06
|
||||
/* command : PHY Read Reg */
|
||||
#define SR_CMD_READ_MII_REG 0x07
|
||||
/* command : PHY Write Reg */
|
||||
#define SR_CMD_WRITE_MII_REG 0x08
|
||||
/* command : Hardware Station Management Control Reg */
|
||||
#define SR_CMD_SET_HW_MII 0x0a
|
||||
/* command : SROM Read Reg */
|
||||
#define SR_CMD_READ_EEPROM 0x0b
|
||||
/* command : SROM Write Reg */
|
||||
#define SR_CMD_WRITE_EEPROM 0x0c
|
||||
/* command : SROM Write Enable Reg */
|
||||
#define SR_CMD_WRITE_ENABLE 0x0d
|
||||
/* command : SROM Write Disable Reg */
|
||||
#define SR_CMD_WRITE_DISABLE 0x0e
|
||||
/* command : RX Control Read Reg */
|
||||
#define SR_CMD_READ_RX_CTL 0x0f
|
||||
#define SR_RX_CTL_PRO (1 << 0)
|
||||
#define SR_RX_CTL_AMALL (1 << 1)
|
||||
#define SR_RX_CTL_SEP (1 << 2)
|
||||
#define SR_RX_CTL_AB (1 << 3)
|
||||
#define SR_RX_CTL_AM (1 << 4)
|
||||
#define SR_RX_CTL_AP (1 << 5)
|
||||
#define SR_RX_CTL_ARP (1 << 6)
|
||||
#define SR_RX_CTL_SO (1 << 7)
|
||||
#define SR_RX_CTL_RH1M (1 << 8)
|
||||
#define SR_RX_CTL_RH2M (1 << 9)
|
||||
#define SR_RX_CTL_RH3M (1 << 10)
|
||||
/* command : RX Control Write Reg */
|
||||
#define SR_CMD_WRITE_RX_CTL 0x10
|
||||
/* command : IPG0/IPG1/IPG2 Control Read Reg */
|
||||
#define SR_CMD_READ_IPG012 0x11
|
||||
/* command : IPG0/IPG1/IPG2 Control Write Reg */
|
||||
#define SR_CMD_WRITE_IPG012 0x12
|
||||
/* command : Node ID Read Reg */
|
||||
#define SR_CMD_READ_NODE_ID 0x13
|
||||
/* command : Node ID Write Reg */
|
||||
#define SR_CMD_WRITE_NODE_ID 0x14
|
||||
/* command : Multicast Filter Array Read Reg */
|
||||
#define SR_CMD_READ_MULTI_FILTER 0x15
|
||||
/* command : Multicast Filter Array Write Reg */
|
||||
#define SR_CMD_WRITE_MULTI_FILTER 0x16
|
||||
/* command : Eth/HomePNA PHY Address Reg */
|
||||
#define SR_CMD_READ_PHY_ID 0x19
|
||||
/* command : Medium Status Read Reg */
|
||||
#define SR_CMD_READ_MEDIUM_STATUS 0x1a
|
||||
#define SR_MONITOR_LINK (1 << 1)
|
||||
#define SR_MONITOR_MAGIC (1 << 2)
|
||||
#define SR_MONITOR_HSFS (1 << 4)
|
||||
/* command : Medium Status Write Reg */
|
||||
#define SR_CMD_WRITE_MEDIUM_MODE 0x1b
|
||||
#define SR_MEDIUM_GM (1 << 0)
|
||||
#define SR_MEDIUM_FD (1 << 1)
|
||||
#define SR_MEDIUM_AC (1 << 2)
|
||||
#define SR_MEDIUM_ENCK (1 << 3)
|
||||
#define SR_MEDIUM_RFC (1 << 4)
|
||||
#define SR_MEDIUM_TFC (1 << 5)
|
||||
#define SR_MEDIUM_JFE (1 << 6)
|
||||
#define SR_MEDIUM_PF (1 << 7)
|
||||
#define SR_MEDIUM_RE (1 << 8)
|
||||
#define SR_MEDIUM_PS (1 << 9)
|
||||
#define SR_MEDIUM_RSV (1 << 10)
|
||||
#define SR_MEDIUM_SBP (1 << 11)
|
||||
#define SR_MEDIUM_SM (1 << 12)
|
||||
/* command : Monitor Mode Status Read Reg */
|
||||
#define SR_CMD_READ_MONITOR_MODE 0x1c
|
||||
/* command : Monitor Mode Status Write Reg */
|
||||
#define SR_CMD_WRITE_MONITOR_MODE 0x1d
|
||||
/* command : GPIO Status Read Reg */
|
||||
#define SR_CMD_READ_GPIOS 0x1e
|
||||
#define SR_GPIO_GPO0EN (1 << 0) /* GPIO0 Output enable */
|
||||
#define SR_GPIO_GPO_0 (1 << 1) /* GPIO0 Output value */
|
||||
#define SR_GPIO_GPO1EN (1 << 2) /* GPIO1 Output enable */
|
||||
#define SR_GPIO_GPO_1 (1 << 3) /* GPIO1 Output value */
|
||||
#define SR_GPIO_GPO2EN (1 << 4) /* GPIO2 Output enable */
|
||||
#define SR_GPIO_GPO_2 (1 << 5) /* GPIO2 Output value */
|
||||
#define SR_GPIO_RESERVED (1 << 6) /* Reserved */
|
||||
#define SR_GPIO_RSE (1 << 7) /* Reload serial EEPROM */
|
||||
/* command : GPIO Status Write Reg */
|
||||
#define SR_CMD_WRITE_GPIOS 0x1f
|
||||
/* command : Eth PHY Power and Reset Control Reg */
|
||||
#define SR_CMD_SW_RESET 0x20
|
||||
#define SR_SWRESET_CLEAR 0x00
|
||||
#define SR_SWRESET_RR (1 << 0)
|
||||
#define SR_SWRESET_RT (1 << 1)
|
||||
#define SR_SWRESET_PRTE (1 << 2)
|
||||
#define SR_SWRESET_PRL (1 << 3)
|
||||
#define SR_SWRESET_BZ (1 << 4)
|
||||
#define SR_SWRESET_IPRL (1 << 5)
|
||||
#define SR_SWRESET_IPPD (1 << 6)
|
||||
/* command : Software Interface Selection Status Read Reg */
|
||||
#define SR_CMD_SW_PHY_STATUS 0x21
|
||||
/* command : Software Interface Selection Status Write Reg */
|
||||
#define SR_CMD_SW_PHY_SELECT 0x22
|
||||
/* command : BULK in Buffer Size Reg */
|
||||
#define SR_CMD_BULKIN_SIZE 0x2A
|
||||
/* command : LED_MUX Control Reg */
|
||||
#define SR_CMD_LED_MUX 0x70
|
||||
#define SR_LED_MUX_TX_ACTIVE (1 << 0)
|
||||
#define SR_LED_MUX_RX_ACTIVE (1 << 1)
|
||||
#define SR_LED_MUX_COLLISION (1 << 2)
|
||||
#define SR_LED_MUX_DUP_COL (1 << 3)
|
||||
#define SR_LED_MUX_DUP (1 << 4)
|
||||
#define SR_LED_MUX_SPEED (1 << 5)
|
||||
#define SR_LED_MUX_LINK_ACTIVE (1 << 6)
|
||||
#define SR_LED_MUX_LINK (1 << 7)
|
||||
|
||||
/* Register Access Flags */
|
||||
#define SR_REQ_RD_REG (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
|
||||
#define SR_REQ_WR_REG (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
|
||||
|
||||
/* Multicast Filter Array size & Max Number */
|
||||
#define SR_MCAST_FILTER_SIZE 8
|
||||
#define SR_MAX_MCAST 64
|
||||
|
||||
/* IPG0/1/2 Default Value */
|
||||
#define SR9800_IPG0_DEFAULT 0x15
|
||||
#define SR9800_IPG1_DEFAULT 0x0c
|
||||
#define SR9800_IPG2_DEFAULT 0x12
|
||||
|
||||
/* Medium Status Default Mode */
|
||||
#define SR9800_MEDIUM_DEFAULT \
|
||||
(SR_MEDIUM_FD | SR_MEDIUM_RFC | \
|
||||
SR_MEDIUM_TFC | SR_MEDIUM_PS | \
|
||||
SR_MEDIUM_AC | SR_MEDIUM_RE)
|
||||
|
||||
/* RX Control Default Setting */
|
||||
#define SR_DEFAULT_RX_CTL \
|
||||
(SR_RX_CTL_SO | SR_RX_CTL_AB | SR_RX_CTL_RH1M)
|
||||
|
||||
/* EEPROM Magic Number & EEPROM Size */
|
||||
#define SR_EEPROM_MAGIC 0xdeadbeef
|
||||
#define SR9800_EEPROM_LEN 0xff
|
||||
|
||||
/* SR9800 Driver Version and Driver Name */
|
||||
#define DRIVER_VERSION "11-Nov-2013"
|
||||
#define DRIVER_NAME "CoreChips"
|
||||
#define DRIVER_FLAG \
|
||||
(FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET)
|
||||
|
||||
/* SR9800 BULKIN Buffer Size */
|
||||
#define SR9800_MAX_BULKIN_2K 0
|
||||
#define SR9800_MAX_BULKIN_4K 1
|
||||
#define SR9800_MAX_BULKIN_6K 2
|
||||
#define SR9800_MAX_BULKIN_8K 3
|
||||
#define SR9800_MAX_BULKIN_16K 4
|
||||
#define SR9800_MAX_BULKIN_20K 5
|
||||
#define SR9800_MAX_BULKIN_24K 6
|
||||
#define SR9800_MAX_BULKIN_32K 7
|
||||
|
||||
struct {unsigned short size, byte_cnt, threshold; } SR9800_BULKIN_SIZE[] = {
|
||||
/* 2k */
|
||||
{2048, 0x8000, 0x8001},
|
||||
/* 4k */
|
||||
{4096, 0x8100, 0x8147},
|
||||
/* 6k */
|
||||
{6144, 0x8200, 0x81EB},
|
||||
/* 8k */
|
||||
{8192, 0x8300, 0x83D7},
|
||||
/* 16 */
|
||||
{16384, 0x8400, 0x851E},
|
||||
/* 20k */
|
||||
{20480, 0x8500, 0x8666},
|
||||
/* 24k */
|
||||
{24576, 0x8600, 0x87AE},
|
||||
/* 32k */
|
||||
{32768, 0x8700, 0x8A3D},
|
||||
};
|
||||
|
||||
/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
|
||||
struct sr_data {
|
||||
u8 multi_filter[SR_MCAST_FILTER_SIZE];
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 phymode;
|
||||
u8 ledmode;
|
||||
u8 eeprom_len;
|
||||
};
|
||||
|
||||
struct sr9800_int_data {
|
||||
__le16 res1;
|
||||
u8 link;
|
||||
__le16 res2;
|
||||
u8 status;
|
||||
__le16 res3;
|
||||
} __packed;
|
||||
|
||||
#endif /* _SR9800_H */
|
@ -469,7 +469,6 @@ static inline struct hlist_head *vxlan_fdb_head(struct vxlan_dev *vxlan,
|
||||
/* Look up Ethernet address in forwarding table */
|
||||
static struct vxlan_fdb *__vxlan_find_mac(struct vxlan_dev *vxlan,
|
||||
const u8 *mac)
|
||||
|
||||
{
|
||||
struct hlist_head *head = vxlan_fdb_head(vxlan, mac);
|
||||
struct vxlan_fdb *f;
|
||||
@ -596,10 +595,8 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, struct sk_buff
|
||||
NAPI_GRO_CB(p)->same_flow = 0;
|
||||
continue;
|
||||
}
|
||||
goto found;
|
||||
}
|
||||
|
||||
found:
|
||||
type = eh->h_proto;
|
||||
|
||||
rcu_read_lock();
|
||||
|
@ -71,12 +71,9 @@ static int dlci_header(struct sk_buff *skb, struct net_device *dev,
|
||||
const void *saddr, unsigned len)
|
||||
{
|
||||
struct frhdr hdr;
|
||||
struct dlci_local *dlp;
|
||||
unsigned int hlen;
|
||||
char *dest;
|
||||
|
||||
dlp = netdev_priv(dev);
|
||||
|
||||
hdr.control = FRAD_I_UI;
|
||||
switch (type)
|
||||
{
|
||||
@ -107,11 +104,9 @@ static int dlci_header(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct dlci_local *dlp;
|
||||
struct frhdr *hdr;
|
||||
int process, header;
|
||||
|
||||
dlp = netdev_priv(dev);
|
||||
if (!pskb_may_pull(skb, sizeof(*hdr))) {
|
||||
netdev_notice(dev, "invalid data no header\n");
|
||||
dev->stats.rx_errors++;
|
||||
|
@ -1764,7 +1764,7 @@ static struct usb_device_id ar5523_id_table[] = {
|
||||
AR5523_DEVICE_UG(0x07d1, 0x3a07), /* D-Link / WUA-2340 rev A1 */
|
||||
AR5523_DEVICE_UG(0x1690, 0x0712), /* Gigaset / AR5523 */
|
||||
AR5523_DEVICE_UG(0x1690, 0x0710), /* Gigaset / SMCWUSBTG */
|
||||
AR5523_DEVICE_UG(0x129b, 0x160c), /* Gigaset / USB stick 108
|
||||
AR5523_DEVICE_UG(0x129b, 0x160b), /* Gigaset / USB stick 108
|
||||
(CyberTAN Technology) */
|
||||
AR5523_DEVICE_UG(0x16ab, 0x7801), /* Globalsun / AR5523_1 */
|
||||
AR5523_DEVICE_UX(0x16ab, 0x7811), /* Globalsun / AR5523_2 */
|
||||
|
@ -5065,6 +5065,10 @@ static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is2GHz && !twiceMaxEdgePower)
|
||||
twiceMaxEdgePower = 60;
|
||||
|
||||
return twiceMaxEdgePower;
|
||||
}
|
||||
|
||||
|
@ -262,6 +262,8 @@ enum tid_aggr_state {
|
||||
struct ath9k_htc_sta {
|
||||
u8 index;
|
||||
enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID];
|
||||
struct work_struct rc_update_work;
|
||||
struct ath9k_htc_priv *htc_priv;
|
||||
};
|
||||
|
||||
#define ATH9K_HTC_RXBUF 256
|
||||
|
@ -34,6 +34,10 @@ static int ath9k_htc_btcoex_enable;
|
||||
module_param_named(btcoex_enable, ath9k_htc_btcoex_enable, int, 0444);
|
||||
MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
|
||||
|
||||
static int ath9k_ps_enable;
|
||||
module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
|
||||
MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
|
||||
|
||||
#define CHAN2G(_freq, _idx) { \
|
||||
.center_freq = (_freq), \
|
||||
.hw_value = (_idx), \
|
||||
@ -725,12 +729,14 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
|
||||
IEEE80211_HW_SPECTRUM_MGMT |
|
||||
IEEE80211_HW_HAS_RATE_CONTROL |
|
||||
IEEE80211_HW_RX_INCLUDES_FCS |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_PS_NULLFUNC_STACK |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_MFP_CAPABLE |
|
||||
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
|
||||
|
||||
if (ath9k_ps_enable)
|
||||
hw->flags |= IEEE80211_HW_SUPPORTS_PS;
|
||||
|
||||
hw->wiphy->interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
|
@ -1270,18 +1270,50 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static void ath9k_htc_sta_rc_update_work(struct work_struct *work)
|
||||
{
|
||||
struct ath9k_htc_sta *ista =
|
||||
container_of(work, struct ath9k_htc_sta, rc_update_work);
|
||||
struct ieee80211_sta *sta =
|
||||
container_of((void *)ista, struct ieee80211_sta, drv_priv);
|
||||
struct ath9k_htc_priv *priv = ista->htc_priv;
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath9k_htc_target_rate trate;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
|
||||
memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));
|
||||
ath9k_htc_setup_rate(priv, sta, &trate);
|
||||
if (!ath9k_htc_send_rate_cmd(priv, &trate))
|
||||
ath_dbg(common, CONFIG,
|
||||
"Supported rates for sta: %pM updated, rate caps: 0x%X\n",
|
||||
sta->addr, be32_to_cpu(trate.capflags));
|
||||
else
|
||||
ath_dbg(common, CONFIG,
|
||||
"Unable to update supported rates for sta: %pM\n",
|
||||
sta->addr);
|
||||
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static int ath9k_htc_sta_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
ret = ath9k_htc_add_station(priv, vif, sta);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
INIT_WORK(&ista->rc_update_work, ath9k_htc_sta_rc_update_work);
|
||||
ista->htc_priv = priv;
|
||||
ath9k_htc_init_rate(priv, sta);
|
||||
}
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
@ -1293,12 +1325,13 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath9k_htc_sta *ista;
|
||||
struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
|
||||
int ret;
|
||||
|
||||
cancel_work_sync(&ista->rc_update_work);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
ista = (struct ath9k_htc_sta *) sta->drv_priv;
|
||||
htc_sta_drain(priv->htc, ista->index);
|
||||
ret = ath9k_htc_remove_station(priv, vif, sta);
|
||||
ath9k_htc_ps_restore(priv);
|
||||
@ -1311,28 +1344,12 @@ static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u32 changed)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath9k_htc_target_rate trate;
|
||||
struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED))
|
||||
return;
|
||||
|
||||
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
|
||||
memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));
|
||||
ath9k_htc_setup_rate(priv, sta, &trate);
|
||||
if (!ath9k_htc_send_rate_cmd(priv, &trate))
|
||||
ath_dbg(common, CONFIG,
|
||||
"Supported rates for sta: %pM updated, rate caps: 0x%X\n",
|
||||
sta->addr, be32_to_cpu(trate.capflags));
|
||||
else
|
||||
ath_dbg(common, CONFIG,
|
||||
"Unable to update supported rates for sta: %pM\n",
|
||||
sta->addr);
|
||||
}
|
||||
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
schedule_work(&ista->rc_update_work);
|
||||
}
|
||||
|
||||
static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
|
||||
|
@ -1316,7 +1316,7 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
|
||||
if (AR_SREV_9300_20_OR_LATER(ah))
|
||||
udelay(50);
|
||||
else if (AR_SREV_9100(ah))
|
||||
udelay(10000);
|
||||
mdelay(10);
|
||||
else
|
||||
udelay(100);
|
||||
|
||||
@ -2051,9 +2051,8 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
|
||||
|
||||
REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
|
||||
AR_RTC_FORCE_WAKE_EN);
|
||||
|
||||
if (AR_SREV_9100(ah))
|
||||
udelay(10000);
|
||||
mdelay(10);
|
||||
else
|
||||
udelay(50);
|
||||
|
||||
|
@ -57,6 +57,10 @@ static int ath9k_bt_ant_diversity;
|
||||
module_param_named(bt_ant_diversity, ath9k_bt_ant_diversity, int, 0444);
|
||||
MODULE_PARM_DESC(bt_ant_diversity, "Enable WLAN/BT RX antenna diversity");
|
||||
|
||||
static int ath9k_ps_enable;
|
||||
module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
|
||||
MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
|
||||
|
||||
bool is_ath9k_unloaded;
|
||||
/* We use the hw_value as an index into our private channel structure */
|
||||
|
||||
@ -903,13 +907,15 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
|
||||
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_PS_NULLFUNC_STACK |
|
||||
IEEE80211_HW_SPECTRUM_MGMT |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_SUPPORTS_RC_TABLE |
|
||||
IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
|
||||
|
||||
if (ath9k_ps_enable)
|
||||
hw->flags |= IEEE80211_HW_SUPPORTS_PS;
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
|
||||
hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
|
||||
|
||||
|
@ -182,6 +182,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
|
||||
for (ch_idx = 0; ch_idx < IWL_NUM_CHANNELS; ch_idx++) {
|
||||
ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
|
||||
|
||||
if (ch_idx >= NUM_2GHZ_CHANNELS &&
|
||||
!data->sku_cap_band_52GHz_enable)
|
||||
ch_flags &= ~NVM_CHANNEL_VALID;
|
||||
|
||||
if (!(ch_flags & NVM_CHANNEL_VALID)) {
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"Ch. %d Flags %x [%sGHz] - No traffic\n",
|
||||
|
@ -504,6 +504,7 @@ struct iwl_scan_offload_profile {
|
||||
* @match_notify: clients waiting for match found notification
|
||||
* @pass_match: clients waiting for the results
|
||||
* @active_clients: active clients bitmap - enum scan_framework_client
|
||||
* @any_beacon_notify: clients waiting for match notification without match
|
||||
*/
|
||||
struct iwl_scan_offload_profile_cfg {
|
||||
struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES];
|
||||
@ -512,7 +513,8 @@ struct iwl_scan_offload_profile_cfg {
|
||||
u8 match_notify;
|
||||
u8 pass_match;
|
||||
u8 active_clients;
|
||||
u8 reserved[3];
|
||||
u8 any_beacon_notify;
|
||||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
|
@ -246,7 +246,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
else
|
||||
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
||||
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) {
|
||||
if (0 && mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) {
|
||||
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
|
||||
hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
|
||||
hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
|
||||
|
@ -344,7 +344,8 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
|
||||
|
||||
iwl_mvm_scan_fill_ssids(cmd, req, basic_ssid ? 1 : 0);
|
||||
|
||||
cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL);
|
||||
cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
|
||||
TX_CMD_FLG_BT_DIS);
|
||||
cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id;
|
||||
cmd->tx_cmd.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
|
||||
cmd->tx_cmd.rate_n_flags =
|
||||
@ -807,6 +808,8 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
|
||||
profile_cfg->active_clients = SCAN_CLIENT_SCHED_SCAN;
|
||||
profile_cfg->pass_match = SCAN_CLIENT_SCHED_SCAN;
|
||||
profile_cfg->match_notify = SCAN_CLIENT_SCHED_SCAN;
|
||||
if (!req->n_match_sets || !req->match_sets[0].ssid.ssid_len)
|
||||
profile_cfg->any_beacon_notify = SCAN_CLIENT_SCHED_SCAN;
|
||||
|
||||
for (i = 0; i < req->n_match_sets; i++) {
|
||||
profile = &profile_cfg->profiles[i];
|
||||
|
@ -652,7 +652,7 @@ int iwl_mvm_send_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
static const u8 *baddr = _baddr;
|
||||
const u8 *baddr = _baddr;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
|
@ -659,8 +659,14 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
||||
rcu_read_lock();
|
||||
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
|
||||
/*
|
||||
* sta can't be NULL otherwise it'd mean that the sta has been freed in
|
||||
* the firmware while we still have packets for it in the Tx queues.
|
||||
*/
|
||||
if (WARN_ON_ONCE(!sta))
|
||||
goto out;
|
||||
|
||||
if (!IS_ERR_OR_NULL(sta)) {
|
||||
if (!IS_ERR(sta)) {
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
if (tid != IWL_TID_NON_QOS) {
|
||||
@ -675,7 +681,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
||||
spin_unlock_bh(&mvmsta->lock);
|
||||
}
|
||||
} else {
|
||||
sta = NULL;
|
||||
mvmsta = NULL;
|
||||
}
|
||||
|
||||
@ -683,42 +688,38 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
||||
* If the txq is not an AMPDU queue, there is no chance we freed
|
||||
* several skbs. Check that out...
|
||||
*/
|
||||
if (txq_id < mvm->first_agg_queue && !WARN_ON(skb_freed > 1) &&
|
||||
atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) {
|
||||
if (mvmsta) {
|
||||
/*
|
||||
* If there are no pending frames for this STA, notify
|
||||
* mac80211 that this station can go to sleep in its
|
||||
* STA table.
|
||||
*/
|
||||
if (mvmsta->vif->type == NL80211_IFTYPE_AP)
|
||||
ieee80211_sta_block_awake(mvm->hw, sta, false);
|
||||
/*
|
||||
* We might very well have taken mvmsta pointer while
|
||||
* the station was being removed. The remove flow might
|
||||
* have seen a pending_frame (because we didn't take
|
||||
* the lock) even if now the queues are drained. So make
|
||||
* really sure now that this the station is not being
|
||||
* removed. If it is, run the drain worker to remove it.
|
||||
*/
|
||||
spin_lock_bh(&mvmsta->lock);
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
|
||||
if (!sta || PTR_ERR(sta) == -EBUSY) {
|
||||
/*
|
||||
* Station disappeared in the meantime:
|
||||
* so we are draining.
|
||||
*/
|
||||
set_bit(sta_id, mvm->sta_drained);
|
||||
schedule_work(&mvm->sta_drained_wk);
|
||||
}
|
||||
spin_unlock_bh(&mvmsta->lock);
|
||||
} else if (!mvmsta && PTR_ERR(sta) == -EBUSY) {
|
||||
/* Tx response without STA, so we are draining */
|
||||
set_bit(sta_id, mvm->sta_drained);
|
||||
schedule_work(&mvm->sta_drained_wk);
|
||||
}
|
||||
if (txq_id >= mvm->first_agg_queue)
|
||||
goto out;
|
||||
|
||||
/* We can't free more than one frame at once on a shared queue */
|
||||
WARN_ON(skb_freed > 1);
|
||||
|
||||
/* If we have still frames from this STA nothing to do here */
|
||||
if (!atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id]))
|
||||
goto out;
|
||||
|
||||
if (mvmsta && mvmsta->vif->type == NL80211_IFTYPE_AP) {
|
||||
/*
|
||||
* If there are no pending frames for this STA, notify
|
||||
* mac80211 that this station can go to sleep in its
|
||||
* STA table.
|
||||
* If mvmsta is not NULL, sta is valid.
|
||||
*/
|
||||
ieee80211_sta_block_awake(mvm->hw, sta, false);
|
||||
}
|
||||
|
||||
if (PTR_ERR(sta) == -EBUSY || PTR_ERR(sta) == -ENOENT) {
|
||||
/*
|
||||
* We are draining and this was the last packet - pre_rcu_remove
|
||||
* has been called already. We might be after the
|
||||
* synchronize_net already.
|
||||
* Don't rely on iwl_mvm_rm_sta to see the empty Tx queues.
|
||||
*/
|
||||
set_bit(sta_id, mvm->sta_drained);
|
||||
schedule_work(&mvm->sta_drained_wk);
|
||||
}
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
|
@ -411,6 +411,8 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
||||
mvm->status, table.valid);
|
||||
}
|
||||
|
||||
IWL_ERR(mvm, "Loaded firmware version: %s\n", mvm->fw->fw_version);
|
||||
|
||||
trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low,
|
||||
table.data1, table.data2, table.data3,
|
||||
table.blink1, table.blink2, table.ilink1,
|
||||
|
@ -359,20 +359,25 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
|
||||
/* 7265 Series */
|
||||
{IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x5112, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x5100, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x510A, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095B, 0x5310, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095B, 0x5210, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x5012, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x5400, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x1010, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x5000, iwl7265_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)},
|
||||
|
@ -1876,6 +1876,11 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_eeprom_addr(rt2x00dev,
|
||||
EEPROM_MAC_ADDR_0));
|
||||
|
||||
/*
|
||||
* Disable powersaving as default.
|
||||
*/
|
||||
rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
||||
/*
|
||||
* Initialize hw_mode information.
|
||||
*/
|
||||
|
@ -1706,6 +1706,11 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_PS_NULLFUNC_STACK;
|
||||
|
||||
/*
|
||||
* Disable powersaving as default.
|
||||
*/
|
||||
rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
||||
SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
|
||||
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
|
||||
rt2x00_eeprom_addr(rt2x00dev,
|
||||
|
@ -7458,10 +7458,9 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* Disable powersaving as default on PCI devices.
|
||||
* Disable powersaving as default.
|
||||
*/
|
||||
if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
|
||||
rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
||||
/*
|
||||
* Initialize all hw fields.
|
||||
|
@ -107,6 +107,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
|
||||
struct rtl8180_priv *priv = dev->priv;
|
||||
unsigned int count = 32;
|
||||
u8 signal, agc, sq;
|
||||
dma_addr_t mapping;
|
||||
|
||||
while (count--) {
|
||||
struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx];
|
||||
@ -128,6 +129,17 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
|
||||
if (unlikely(!new_skb))
|
||||
goto done;
|
||||
|
||||
mapping = pci_map_single(priv->pdev,
|
||||
skb_tail_pointer(new_skb),
|
||||
MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
|
||||
|
||||
if (pci_dma_mapping_error(priv->pdev, mapping)) {
|
||||
kfree_skb(new_skb);
|
||||
dev_err(&priv->pdev->dev, "RX DMA map error\n");
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
pci_unmap_single(priv->pdev,
|
||||
*((dma_addr_t *)skb->cb),
|
||||
MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
|
||||
@ -158,9 +170,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
|
||||
|
||||
skb = new_skb;
|
||||
priv->rx_buf[priv->rx_idx] = skb;
|
||||
*((dma_addr_t *) skb->cb) =
|
||||
pci_map_single(priv->pdev, skb_tail_pointer(skb),
|
||||
MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
|
||||
*((dma_addr_t *) skb->cb) = mapping;
|
||||
}
|
||||
|
||||
done:
|
||||
@ -266,6 +276,13 @@ static void rtl8180_tx(struct ieee80211_hw *dev,
|
||||
mapping = pci_map_single(priv->pdev, skb->data,
|
||||
skb->len, PCI_DMA_TODEVICE);
|
||||
|
||||
if (pci_dma_mapping_error(priv->pdev, mapping)) {
|
||||
kfree_skb(skb);
|
||||
dev_err(&priv->pdev->dev, "TX DMA mapping error\n");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
tx_flags = RTL818X_TX_DESC_FLAG_OWN | RTL818X_TX_DESC_FLAG_FS |
|
||||
RTL818X_TX_DESC_FLAG_LS |
|
||||
(ieee80211_get_tx_rate(dev, info)->hw_value << 24) |
|
||||
|
@ -143,11 +143,7 @@ struct xenvif {
|
||||
char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */
|
||||
struct xen_netif_rx_back_ring rx;
|
||||
struct sk_buff_head rx_queue;
|
||||
bool rx_queue_stopped;
|
||||
/* Set when the RX interrupt is triggered by the frontend.
|
||||
* The worker thread may need to wake the queue.
|
||||
*/
|
||||
bool rx_event;
|
||||
RING_IDX rx_last_skb_slots;
|
||||
|
||||
/* This array is allocated seperately as it is large */
|
||||
struct gnttab_copy *grant_copy_op;
|
||||
|
@ -100,7 +100,6 @@ static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct xenvif *vif = dev_id;
|
||||
|
||||
vif->rx_event = true;
|
||||
xenvif_kick_thread(vif);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -476,7 +476,6 @@ static void xenvif_rx_action(struct xenvif *vif)
|
||||
unsigned long offset;
|
||||
struct skb_cb_overlay *sco;
|
||||
bool need_to_notify = false;
|
||||
bool ring_full = false;
|
||||
|
||||
struct netrx_pending_operations npo = {
|
||||
.copy = vif->grant_copy_op,
|
||||
@ -486,7 +485,7 @@ static void xenvif_rx_action(struct xenvif *vif)
|
||||
skb_queue_head_init(&rxq);
|
||||
|
||||
while ((skb = skb_dequeue(&vif->rx_queue)) != NULL) {
|
||||
int max_slots_needed;
|
||||
RING_IDX max_slots_needed;
|
||||
int i;
|
||||
|
||||
/* We need a cheap worse case estimate for the number of
|
||||
@ -509,9 +508,10 @@ static void xenvif_rx_action(struct xenvif *vif)
|
||||
if (!xenvif_rx_ring_slots_available(vif, max_slots_needed)) {
|
||||
skb_queue_head(&vif->rx_queue, skb);
|
||||
need_to_notify = true;
|
||||
ring_full = true;
|
||||
vif->rx_last_skb_slots = max_slots_needed;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
vif->rx_last_skb_slots = 0;
|
||||
|
||||
sco = (struct skb_cb_overlay *)skb->cb;
|
||||
sco->meta_slots_used = xenvif_gop_skb(skb, &npo);
|
||||
@ -522,8 +522,6 @@ static void xenvif_rx_action(struct xenvif *vif)
|
||||
|
||||
BUG_ON(npo.meta_prod > ARRAY_SIZE(vif->meta));
|
||||
|
||||
vif->rx_queue_stopped = !npo.copy_prod && ring_full;
|
||||
|
||||
if (!npo.copy_prod)
|
||||
goto done;
|
||||
|
||||
@ -1473,8 +1471,8 @@ static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif,
|
||||
|
||||
static inline int rx_work_todo(struct xenvif *vif)
|
||||
{
|
||||
return (!skb_queue_empty(&vif->rx_queue) && !vif->rx_queue_stopped) ||
|
||||
vif->rx_event;
|
||||
return !skb_queue_empty(&vif->rx_queue) &&
|
||||
xenvif_rx_ring_slots_available(vif, vif->rx_last_skb_slots);
|
||||
}
|
||||
|
||||
static inline int tx_work_todo(struct xenvif *vif)
|
||||
@ -1560,8 +1558,6 @@ int xenvif_kthread(void *data)
|
||||
if (!skb_queue_empty(&vif->rx_queue))
|
||||
xenvif_rx_action(vif);
|
||||
|
||||
vif->rx_event = false;
|
||||
|
||||
if (skb_queue_empty(&vif->rx_queue) &&
|
||||
netif_queue_stopped(vif->dev))
|
||||
xenvif_start_queue(vif);
|
||||
|
@ -1832,7 +1832,6 @@ static void netback_changed(struct xenbus_device *dev,
|
||||
case XenbusStateReconfiguring:
|
||||
case XenbusStateReconfigured:
|
||||
case XenbusStateUnknown:
|
||||
case XenbusStateClosed:
|
||||
break;
|
||||
|
||||
case XenbusStateInitWait:
|
||||
@ -1847,6 +1846,10 @@ static void netback_changed(struct xenbus_device *dev,
|
||||
netdev_notify_peers(netdev);
|
||||
break;
|
||||
|
||||
case XenbusStateClosed:
|
||||
if (dev->state == XenbusStateClosed)
|
||||
break;
|
||||
/* Missed the backend's CLOSING state -- fallthrough */
|
||||
case XenbusStateClosing:
|
||||
xenbus_frontend_closed(dev);
|
||||
break;
|
||||
|
@ -11,7 +11,9 @@
|
||||
#define CAN_SKB_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/can.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
/*
|
||||
* The struct can_skb_priv is used to transport additional information along
|
||||
@ -42,4 +44,40 @@ static inline void can_skb_reserve(struct sk_buff *skb)
|
||||
skb_reserve(skb, sizeof(struct can_skb_priv));
|
||||
}
|
||||
|
||||
static inline void can_skb_destructor(struct sk_buff *skb)
|
||||
{
|
||||
sock_put(skb->sk);
|
||||
}
|
||||
|
||||
static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk)
|
||||
{
|
||||
if (sk) {
|
||||
sock_hold(sk);
|
||||
skb->destructor = can_skb_destructor;
|
||||
skb->sk = sk;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* returns an unshared skb owned by the original sock to be echo'ed back
|
||||
*/
|
||||
static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
|
||||
{
|
||||
if (skb_shared(skb)) {
|
||||
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
|
||||
|
||||
if (likely(nskb)) {
|
||||
can_skb_set_owner(nskb, skb->sk);
|
||||
consume_skb(skb);
|
||||
return nskb;
|
||||
} else {
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* we can assume to have an unshared skb with proper owner */
|
||||
return skb;
|
||||
}
|
||||
|
||||
#endif /* CAN_SKB_H */
|
||||
|
@ -15,4 +15,6 @@ struct datalink_proto {
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct datalink_proto *make_EII_client(void);
|
||||
void destroy_EII_client(struct datalink_proto *dl);
|
||||
#endif
|
||||
|
@ -200,6 +200,8 @@ static inline void dn_sk_ports_copy(struct flowidn *fld, struct dn_scp *scp)
|
||||
}
|
||||
|
||||
unsigned int dn_mss_from_pmtu(struct net_device *dev, int mtu);
|
||||
void dn_register_sysctl(void);
|
||||
void dn_unregister_sysctl(void);
|
||||
|
||||
#define DN_MENUVER_ACC 0x01
|
||||
#define DN_MENUVER_USR 0x02
|
||||
|
@ -20,6 +20,8 @@ int dn_route_output_sock(struct dst_entry __rcu **pprt, struct flowidn *,
|
||||
struct sock *sk, int flags);
|
||||
int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
|
||||
void dn_rt_cache_flush(int delay);
|
||||
int dn_route_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
struct packet_type *pt, struct net_device *orig_dev);
|
||||
|
||||
/* Masks for flags field */
|
||||
#define DN_RT_F_PID 0x07 /* Mask for packet type */
|
||||
|
@ -16,6 +16,7 @@
|
||||
struct ethoc_platform_data {
|
||||
u8 hwaddr[IFHWADDRLEN];
|
||||
s8 phy_id;
|
||||
u32 eth_clkfreq;
|
||||
};
|
||||
|
||||
#endif /* !LINUX_NET_ETHOC_H */
|
||||
|
@ -140,6 +140,17 @@ static __inline__ void ipxitf_hold(struct ipx_interface *intrfc)
|
||||
}
|
||||
|
||||
void ipxitf_down(struct ipx_interface *intrfc);
|
||||
struct ipx_interface *ipxitf_find_using_net(__be32 net);
|
||||
int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node);
|
||||
__be16 ipx_cksum(struct ipxhdr *packet, int length);
|
||||
int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc,
|
||||
unsigned char *node);
|
||||
void ipxrtr_del_routes(struct ipx_interface *intrfc);
|
||||
int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
|
||||
struct iovec *iov, size_t len, int noblock);
|
||||
int ipxrtr_route_skb(struct sk_buff *skb);
|
||||
struct ipx_route *ipxrtr_lookup(__be32 net);
|
||||
int ipxrtr_ioctl(unsigned int cmd, void __user *arg);
|
||||
|
||||
static __inline__ void ipxitf_put(struct ipx_interface *intrfc)
|
||||
{
|
||||
|
@ -162,6 +162,14 @@ extern struct list_head net_namespace_list;
|
||||
struct net *get_net_ns_by_pid(pid_t pid);
|
||||
struct net *get_net_ns_by_fd(int pid);
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
void ipx_register_sysctl(void);
|
||||
void ipx_unregister_sysctl(void);
|
||||
#else
|
||||
#define ipx_register_sysctl()
|
||||
#define ipx_unregister_sysctl()
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_NS
|
||||
void __put_net(struct net *net);
|
||||
|
||||
|
@ -284,6 +284,8 @@ extern unsigned int nf_conntrack_max;
|
||||
extern unsigned int nf_conntrack_hash_rnd;
|
||||
void init_nf_conntrack_hash_rnd(void);
|
||||
|
||||
void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl);
|
||||
|
||||
#define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count)
|
||||
#define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count)
|
||||
|
||||
|
@ -252,6 +252,7 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
|
||||
* @owner: module reference
|
||||
* @policy: netlink attribute policy
|
||||
* @maxattr: highest netlink attribute number
|
||||
* @family: address family for AF-specific types
|
||||
*/
|
||||
struct nft_expr_type {
|
||||
const struct nft_expr_ops *(*select_ops)(const struct nft_ctx *,
|
||||
@ -262,6 +263,7 @@ struct nft_expr_type {
|
||||
struct module *owner;
|
||||
const struct nla_policy *policy;
|
||||
unsigned int maxattr;
|
||||
u8 family;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -320,7 +322,6 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
|
||||
* struct nft_rule - nf_tables rule
|
||||
*
|
||||
* @list: used internally
|
||||
* @rcu_head: used internally for rcu
|
||||
* @handle: rule handle
|
||||
* @genmask: generation mask
|
||||
* @dlen: length of expression data
|
||||
@ -328,7 +329,6 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
|
||||
*/
|
||||
struct nft_rule {
|
||||
struct list_head list;
|
||||
struct rcu_head rcu_head;
|
||||
u64 handle:46,
|
||||
genmask:2,
|
||||
dlen:16;
|
||||
@ -389,7 +389,6 @@ enum nft_chain_flags {
|
||||
*
|
||||
* @rules: list of rules in the chain
|
||||
* @list: used internally
|
||||
* @rcu_head: used internally
|
||||
* @net: net namespace that this chain belongs to
|
||||
* @table: table that this chain belongs to
|
||||
* @handle: chain handle
|
||||
@ -401,7 +400,6 @@ enum nft_chain_flags {
|
||||
struct nft_chain {
|
||||
struct list_head rules;
|
||||
struct list_head list;
|
||||
struct rcu_head rcu_head;
|
||||
struct net *net;
|
||||
struct nft_table *table;
|
||||
u64 handle;
|
||||
@ -529,6 +527,9 @@ void nft_unregister_expr(struct nft_expr_type *);
|
||||
#define MODULE_ALIAS_NFT_CHAIN(family, name) \
|
||||
MODULE_ALIAS("nft-chain-" __stringify(family) "-" name)
|
||||
|
||||
#define MODULE_ALIAS_NFT_AF_EXPR(family, name) \
|
||||
MODULE_ALIAS("nft-expr-" __stringify(family) "-" name)
|
||||
|
||||
#define MODULE_ALIAS_NFT_EXPR(name) \
|
||||
MODULE_ALIAS("nft-expr-" name)
|
||||
|
||||
|
25
include/net/netfilter/nft_reject.h
Normal file
25
include/net/netfilter/nft_reject.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef _NFT_REJECT_H_
|
||||
#define _NFT_REJECT_H_
|
||||
|
||||
struct nft_reject {
|
||||
enum nft_reject_types type:8;
|
||||
u8 icmp_code;
|
||||
};
|
||||
|
||||
extern const struct nla_policy nft_reject_policy[];
|
||||
|
||||
int nft_reject_init(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr,
|
||||
const struct nlattr * const tb[]);
|
||||
|
||||
int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr);
|
||||
|
||||
void nft_reject_ipv4_eval(const struct nft_expr *expr,
|
||||
struct nft_data data[NFT_REG_MAX + 1],
|
||||
const struct nft_pktinfo *pkt);
|
||||
|
||||
void nft_reject_ipv6_eval(const struct nft_expr *expr,
|
||||
struct nft_data data[NFT_REG_MAX + 1],
|
||||
const struct nft_pktinfo *pkt);
|
||||
|
||||
#endif
|
@ -128,22 +128,13 @@ struct in6_flowlabel_req {
|
||||
* IPV6 extension headers
|
||||
*/
|
||||
#if __UAPI_DEF_IPPROTO_V6
|
||||
enum {
|
||||
IPPROTO_HOPOPTS = 0, /* IPv6 hop-by-hop options */
|
||||
#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
|
||||
IPPROTO_ROUTING = 43, /* IPv6 routing header */
|
||||
#define IPPROTO_ROUTING IPPROTO_ROUTING
|
||||
IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header */
|
||||
#define IPPROTO_FRAGMENT IPPROTO_FRAGMENT
|
||||
IPPROTO_ICMPV6 = 58, /* ICMPv6 */
|
||||
#define IPPROTO_ICMPV6 IPPROTO_ICMPV6
|
||||
IPPROTO_NONE = 59, /* IPv6 no next header */
|
||||
#define IPPROTO_NONE IPPROTO_NONE
|
||||
IPPROTO_DSTOPTS = 60, /* IPv6 destination options */
|
||||
#define IPPROTO_DSTOPTS IPPROTO_DSTOPTS
|
||||
IPPROTO_MH = 135, /* IPv6 mobility header */
|
||||
#define IPPROTO_MH IPPROTO_MH
|
||||
};
|
||||
#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */
|
||||
#define IPPROTO_ROUTING 43 /* IPv6 routing header */
|
||||
#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */
|
||||
#define IPPROTO_ICMPV6 58 /* ICMPv6 */
|
||||
#define IPPROTO_NONE 59 /* IPv6 no next header */
|
||||
#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */
|
||||
#define IPPROTO_MH 135 /* IPv6 mobility header */
|
||||
#endif /* __UAPI_DEF_IPPROTO_V6 */
|
||||
|
||||
/*
|
||||
|
@ -204,7 +204,7 @@ free_and_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct p9_fcall *p9_fcall_alloc(int alloc_msize)
|
||||
static struct p9_fcall *p9_fcall_alloc(int alloc_msize)
|
||||
{
|
||||
struct p9_fcall *fc;
|
||||
fc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, GFP_NOFS);
|
||||
|
@ -340,7 +340,10 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
|
||||
int count = nr_pages;
|
||||
while (nr_pages) {
|
||||
s = rest_of_page(data);
|
||||
pages[index++] = kmap_to_page(data);
|
||||
if (is_vmalloc_addr(data))
|
||||
pages[index++] = vmalloc_to_page(data);
|
||||
else
|
||||
pages[index++] = kmap_to_page(data);
|
||||
data += s;
|
||||
nr_pages--;
|
||||
}
|
||||
|
@ -187,8 +187,7 @@ static int br_set_mac_address(struct net_device *dev, void *p)
|
||||
|
||||
spin_lock_bh(&br->lock);
|
||||
if (!ether_addr_equal(dev->dev_addr, addr->sa_data)) {
|
||||
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
|
||||
br_fdb_change_mac_address(br, addr->sa_data);
|
||||
/* Mac address will be changed in br_stp_change_bridge_id(). */
|
||||
br_stp_change_bridge_id(br, addr->sa_data);
|
||||
}
|
||||
spin_unlock_bh(&br->lock);
|
||||
@ -226,37 +225,11 @@ static void br_netpoll_cleanup(struct net_device *dev)
|
||||
br_netpoll_disable(p);
|
||||
}
|
||||
|
||||
static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni,
|
||||
gfp_t gfp)
|
||||
{
|
||||
struct net_bridge *br = netdev_priv(dev);
|
||||
struct net_bridge_port *p;
|
||||
int err = 0;
|
||||
|
||||
list_for_each_entry(p, &br->port_list, list) {
|
||||
if (!p->dev)
|
||||
continue;
|
||||
err = br_netpoll_enable(p, gfp);
|
||||
if (err)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
out:
|
||||
return err;
|
||||
|
||||
fail:
|
||||
br_netpoll_cleanup(dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp)
|
||||
static int __br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp)
|
||||
{
|
||||
struct netpoll *np;
|
||||
int err;
|
||||
|
||||
if (!p->br->dev->npinfo)
|
||||
return 0;
|
||||
|
||||
np = kzalloc(sizeof(*p->np), gfp);
|
||||
if (!np)
|
||||
return -ENOMEM;
|
||||
@ -271,6 +244,37 @@ int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp)
|
||||
return err;
|
||||
}
|
||||
|
||||
int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp)
|
||||
{
|
||||
if (!p->br->dev->npinfo)
|
||||
return 0;
|
||||
|
||||
return __br_netpoll_enable(p, gfp);
|
||||
}
|
||||
|
||||
static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni,
|
||||
gfp_t gfp)
|
||||
{
|
||||
struct net_bridge *br = netdev_priv(dev);
|
||||
struct net_bridge_port *p;
|
||||
int err = 0;
|
||||
|
||||
list_for_each_entry(p, &br->port_list, list) {
|
||||
if (!p->dev)
|
||||
continue;
|
||||
err = __br_netpoll_enable(p, gfp);
|
||||
if (err)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
out:
|
||||
return err;
|
||||
|
||||
fail:
|
||||
br_netpoll_cleanup(dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
void br_netpoll_disable(struct net_bridge_port *p)
|
||||
{
|
||||
struct netpoll *np = p->np;
|
||||
|
@ -27,6 +27,9 @@
|
||||
#include "br_private.h"
|
||||
|
||||
static struct kmem_cache *br_fdb_cache __read_mostly;
|
||||
static struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head,
|
||||
const unsigned char *addr,
|
||||
__u16 vid);
|
||||
static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
|
||||
const unsigned char *addr, u16 vid);
|
||||
static void fdb_notify(struct net_bridge *br,
|
||||
@ -89,11 +92,57 @@ static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
|
||||
call_rcu(&f->rcu, fdb_rcu_free);
|
||||
}
|
||||
|
||||
/* Delete a local entry if no other port had the same address. */
|
||||
static void fdb_delete_local(struct net_bridge *br,
|
||||
const struct net_bridge_port *p,
|
||||
struct net_bridge_fdb_entry *f)
|
||||
{
|
||||
const unsigned char *addr = f->addr.addr;
|
||||
u16 vid = f->vlan_id;
|
||||
struct net_bridge_port *op;
|
||||
|
||||
/* Maybe another port has same hw addr? */
|
||||
list_for_each_entry(op, &br->port_list, list) {
|
||||
if (op != p && ether_addr_equal(op->dev->dev_addr, addr) &&
|
||||
(!vid || nbp_vlan_find(op, vid))) {
|
||||
f->dst = op;
|
||||
f->added_by_user = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Maybe bridge device has same hw addr? */
|
||||
if (p && ether_addr_equal(br->dev->dev_addr, addr) &&
|
||||
(!vid || br_vlan_find(br, vid))) {
|
||||
f->dst = NULL;
|
||||
f->added_by_user = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
fdb_delete(br, f);
|
||||
}
|
||||
|
||||
void br_fdb_find_delete_local(struct net_bridge *br,
|
||||
const struct net_bridge_port *p,
|
||||
const unsigned char *addr, u16 vid)
|
||||
{
|
||||
struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
|
||||
struct net_bridge_fdb_entry *f;
|
||||
|
||||
spin_lock_bh(&br->hash_lock);
|
||||
f = fdb_find(head, addr, vid);
|
||||
if (f && f->is_local && !f->added_by_user && f->dst == p)
|
||||
fdb_delete_local(br, p, f);
|
||||
spin_unlock_bh(&br->hash_lock);
|
||||
}
|
||||
|
||||
void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
|
||||
{
|
||||
struct net_bridge *br = p->br;
|
||||
bool no_vlan = (nbp_get_vlan_info(p) == NULL) ? true : false;
|
||||
struct net_port_vlans *pv = nbp_get_vlan_info(p);
|
||||
bool no_vlan = !pv;
|
||||
int i;
|
||||
u16 vid;
|
||||
|
||||
spin_lock_bh(&br->hash_lock);
|
||||
|
||||
@ -104,38 +153,34 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
|
||||
struct net_bridge_fdb_entry *f;
|
||||
|
||||
f = hlist_entry(h, struct net_bridge_fdb_entry, hlist);
|
||||
if (f->dst == p && f->is_local) {
|
||||
/* maybe another port has same hw addr? */
|
||||
struct net_bridge_port *op;
|
||||
u16 vid = f->vlan_id;
|
||||
list_for_each_entry(op, &br->port_list, list) {
|
||||
if (op != p &&
|
||||
ether_addr_equal(op->dev->dev_addr,
|
||||
f->addr.addr) &&
|
||||
nbp_vlan_find(op, vid)) {
|
||||
f->dst = op;
|
||||
goto insert;
|
||||
}
|
||||
}
|
||||
|
||||
if (f->dst == p && f->is_local && !f->added_by_user) {
|
||||
/* delete old one */
|
||||
fdb_delete(br, f);
|
||||
insert:
|
||||
/* insert new address, may fail if invalid
|
||||
* address or dup.
|
||||
*/
|
||||
fdb_insert(br, p, newaddr, vid);
|
||||
fdb_delete_local(br, p, f);
|
||||
|
||||
/* if this port has no vlan information
|
||||
* configured, we can safely be done at
|
||||
* this point.
|
||||
*/
|
||||
if (no_vlan)
|
||||
goto done;
|
||||
goto insert;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
insert:
|
||||
/* insert new address, may fail if invalid address or dup. */
|
||||
fdb_insert(br, p, newaddr, 0);
|
||||
|
||||
if (no_vlan)
|
||||
goto done;
|
||||
|
||||
/* Now add entries for every VLAN configured on the port.
|
||||
* This function runs under RTNL so the bitmap will not change
|
||||
* from under us.
|
||||
*/
|
||||
for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID)
|
||||
fdb_insert(br, p, newaddr, vid);
|
||||
|
||||
done:
|
||||
spin_unlock_bh(&br->hash_lock);
|
||||
}
|
||||
@ -146,10 +191,12 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
|
||||
struct net_port_vlans *pv;
|
||||
u16 vid = 0;
|
||||
|
||||
spin_lock_bh(&br->hash_lock);
|
||||
|
||||
/* If old entry was unassociated with any port, then delete it. */
|
||||
f = __br_fdb_get(br, br->dev->dev_addr, 0);
|
||||
if (f && f->is_local && !f->dst)
|
||||
fdb_delete(br, f);
|
||||
fdb_delete_local(br, NULL, f);
|
||||
|
||||
fdb_insert(br, NULL, newaddr, 0);
|
||||
|
||||
@ -159,14 +206,16 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
|
||||
*/
|
||||
pv = br_get_vlan_info(br);
|
||||
if (!pv)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
for_each_set_bit_from(vid, pv->vlan_bitmap, VLAN_N_VID) {
|
||||
f = __br_fdb_get(br, br->dev->dev_addr, vid);
|
||||
if (f && f->is_local && !f->dst)
|
||||
fdb_delete(br, f);
|
||||
fdb_delete_local(br, NULL, f);
|
||||
fdb_insert(br, NULL, newaddr, vid);
|
||||
}
|
||||
out:
|
||||
spin_unlock_bh(&br->hash_lock);
|
||||
}
|
||||
|
||||
void br_fdb_cleanup(unsigned long _data)
|
||||
@ -235,25 +284,11 @@ void br_fdb_delete_by_port(struct net_bridge *br,
|
||||
|
||||
if (f->is_static && !do_all)
|
||||
continue;
|
||||
/*
|
||||
* if multiple ports all have the same device address
|
||||
* then when one port is deleted, assign
|
||||
* the local entry to other port
|
||||
*/
|
||||
if (f->is_local) {
|
||||
struct net_bridge_port *op;
|
||||
list_for_each_entry(op, &br->port_list, list) {
|
||||
if (op != p &&
|
||||
ether_addr_equal(op->dev->dev_addr,
|
||||
f->addr.addr)) {
|
||||
f->dst = op;
|
||||
goto skip_delete;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fdb_delete(br, f);
|
||||
skip_delete: ;
|
||||
if (f->is_local)
|
||||
fdb_delete_local(br, p, f);
|
||||
else
|
||||
fdb_delete(br, f);
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&br->hash_lock);
|
||||
@ -397,6 +432,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
|
||||
fdb->vlan_id = vid;
|
||||
fdb->is_local = 0;
|
||||
fdb->is_static = 0;
|
||||
fdb->added_by_user = 0;
|
||||
fdb->updated = fdb->used = jiffies;
|
||||
hlist_add_head_rcu(&fdb->hlist, head);
|
||||
}
|
||||
@ -447,7 +483,7 @@ int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
|
||||
}
|
||||
|
||||
void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
|
||||
const unsigned char *addr, u16 vid)
|
||||
const unsigned char *addr, u16 vid, bool added_by_user)
|
||||
{
|
||||
struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
|
||||
struct net_bridge_fdb_entry *fdb;
|
||||
@ -473,13 +509,18 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
|
||||
/* fastpath: update of existing entry */
|
||||
fdb->dst = source;
|
||||
fdb->updated = jiffies;
|
||||
if (unlikely(added_by_user))
|
||||
fdb->added_by_user = 1;
|
||||
}
|
||||
} else {
|
||||
spin_lock(&br->hash_lock);
|
||||
if (likely(!fdb_find(head, addr, vid))) {
|
||||
fdb = fdb_create(head, source, addr, vid);
|
||||
if (fdb)
|
||||
if (fdb) {
|
||||
if (unlikely(added_by_user))
|
||||
fdb->added_by_user = 1;
|
||||
fdb_notify(br, fdb, RTM_NEWNEIGH);
|
||||
}
|
||||
}
|
||||
/* else we lose race and someone else inserts
|
||||
* it first, don't bother updating
|
||||
@ -647,6 +688,7 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr,
|
||||
|
||||
modified = true;
|
||||
}
|
||||
fdb->added_by_user = 1;
|
||||
|
||||
fdb->used = jiffies;
|
||||
if (modified) {
|
||||
@ -664,7 +706,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge_port *p,
|
||||
|
||||
if (ndm->ndm_flags & NTF_USE) {
|
||||
rcu_read_lock();
|
||||
br_fdb_update(p->br, p, addr, vid);
|
||||
br_fdb_update(p->br, p, addr, vid, true);
|
||||
rcu_read_unlock();
|
||||
} else {
|
||||
spin_lock_bh(&p->br->hash_lock);
|
||||
@ -749,8 +791,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr,
|
||||
u16 vlan)
|
||||
static int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr, u16 vlan)
|
||||
{
|
||||
struct hlist_head *head = &br->hash[br_mac_hash(addr, vlan)];
|
||||
struct net_bridge_fdb_entry *fdb;
|
||||
|
@ -389,6 +389,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
|
||||
if (br->dev->needed_headroom < dev->needed_headroom)
|
||||
br->dev->needed_headroom = dev->needed_headroom;
|
||||
|
||||
if (br_fdb_insert(br, p, dev->dev_addr, 0))
|
||||
netdev_err(dev, "failed insert local address bridge forwarding table\n");
|
||||
|
||||
spin_lock_bh(&br->lock);
|
||||
changed_addr = br_stp_recalculate_bridge_id(br);
|
||||
|
||||
@ -404,9 +407,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
|
||||
|
||||
dev_set_mtu(br->dev, br_min_mtu(br));
|
||||
|
||||
if (br_fdb_insert(br, p, dev->dev_addr, 0))
|
||||
netdev_err(dev, "failed insert local address bridge forwarding table\n");
|
||||
|
||||
kobject_uevent(&p->kobj, KOBJ_ADD);
|
||||
|
||||
return 0;
|
||||
|
@ -77,7 +77,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
|
||||
/* insert into forwarding database after filtering to avoid spoofing */
|
||||
br = p->br;
|
||||
if (p->flags & BR_LEARNING)
|
||||
br_fdb_update(br, p, eth_hdr(skb)->h_source, vid);
|
||||
br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false);
|
||||
|
||||
if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) &&
|
||||
br_multicast_rcv(br, p, skb, vid))
|
||||
@ -148,7 +148,7 @@ static int br_handle_local_finish(struct sk_buff *skb)
|
||||
|
||||
br_vlan_get_tag(skb, &vid);
|
||||
if (p->flags & BR_LEARNING)
|
||||
br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid);
|
||||
br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false);
|
||||
return 0; /* process further */
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,7 @@ struct net_bridge_fdb_entry
|
||||
mac_addr addr;
|
||||
unsigned char is_local;
|
||||
unsigned char is_static;
|
||||
unsigned char added_by_user;
|
||||
__u16 vlan_id;
|
||||
};
|
||||
|
||||
@ -370,6 +371,9 @@ static inline void br_netpoll_disable(struct net_bridge_port *p)
|
||||
int br_fdb_init(void);
|
||||
void br_fdb_fini(void);
|
||||
void br_fdb_flush(struct net_bridge *br);
|
||||
void br_fdb_find_delete_local(struct net_bridge *br,
|
||||
const struct net_bridge_port *p,
|
||||
const unsigned char *addr, u16 vid);
|
||||
void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr);
|
||||
void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr);
|
||||
void br_fdb_cleanup(unsigned long arg);
|
||||
@ -383,8 +387,7 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, unsigned long count,
|
||||
int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
|
||||
const unsigned char *addr, u16 vid);
|
||||
void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
|
||||
const unsigned char *addr, u16 vid);
|
||||
int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr, u16 vid);
|
||||
const unsigned char *addr, u16 vid, bool added_by_user);
|
||||
|
||||
int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
|
||||
struct net_device *dev, const unsigned char *addr);
|
||||
@ -584,6 +587,7 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
|
||||
int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags);
|
||||
int br_vlan_delete(struct net_bridge *br, u16 vid);
|
||||
void br_vlan_flush(struct net_bridge *br);
|
||||
bool br_vlan_find(struct net_bridge *br, u16 vid);
|
||||
int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
|
||||
int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags);
|
||||
int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
|
||||
@ -665,6 +669,11 @@ static inline void br_vlan_flush(struct net_bridge *br)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool br_vlan_find(struct net_bridge *br, u16 vid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -194,6 +194,8 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
|
||||
|
||||
wasroot = br_is_root_bridge(br);
|
||||
|
||||
br_fdb_change_mac_address(br, addr);
|
||||
|
||||
memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN);
|
||||
memcpy(br->bridge_id.addr, addr, ETH_ALEN);
|
||||
memcpy(br->dev->dev_addr, addr, ETH_ALEN);
|
||||
|
@ -275,9 +275,7 @@ int br_vlan_delete(struct net_bridge *br, u16 vid)
|
||||
if (!pv)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_bh(&br->hash_lock);
|
||||
fdb_delete_by_addr(br, br->dev->dev_addr, vid);
|
||||
spin_unlock_bh(&br->hash_lock);
|
||||
br_fdb_find_delete_local(br, NULL, br->dev->dev_addr, vid);
|
||||
|
||||
__vlan_del(pv, vid);
|
||||
return 0;
|
||||
@ -295,6 +293,25 @@ void br_vlan_flush(struct net_bridge *br)
|
||||
__vlan_flush(pv);
|
||||
}
|
||||
|
||||
bool br_vlan_find(struct net_bridge *br, u16 vid)
|
||||
{
|
||||
struct net_port_vlans *pv;
|
||||
bool found = false;
|
||||
|
||||
rcu_read_lock();
|
||||
pv = rcu_dereference(br->vlan_info);
|
||||
|
||||
if (!pv)
|
||||
goto out;
|
||||
|
||||
if (test_bit(vid, pv->vlan_bitmap))
|
||||
found = true;
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return found;
|
||||
}
|
||||
|
||||
int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
|
||||
{
|
||||
if (!rtnl_trylock())
|
||||
@ -359,9 +376,7 @@ int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
|
||||
if (!pv)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_bh(&port->br->hash_lock);
|
||||
fdb_delete_by_addr(port->br, port->dev->dev_addr, vid);
|
||||
spin_unlock_bh(&port->br->hash_lock);
|
||||
br_fdb_find_delete_local(port->br, port, port->dev->dev_addr, vid);
|
||||
|
||||
return __vlan_del(pv, vid);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/caif/caif_device.h>
|
||||
#include <net/caif/caif_layer.h>
|
||||
#include <net/caif/caif_dev.h>
|
||||
#include <net/caif/cfpkt.h>
|
||||
#include <net/caif/cfcnfg.h>
|
||||
#include <net/caif/cfserl.h>
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <net/caif/caif_layer.h>
|
||||
#include <net/caif/cfsrvl.h>
|
||||
#include <net/caif/cfpkt.h>
|
||||
#include <net/caif/caif_dev.h>
|
||||
|
||||
#define SRVL_CTRL_PKT_SIZE 1
|
||||
#define SRVL_FLOW_OFF 0x81
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/can/core.h>
|
||||
#include <linux/can/skb.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/sock.h>
|
||||
@ -290,7 +291,7 @@ int can_send(struct sk_buff *skb, int loop)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
newskb->sk = skb->sk;
|
||||
can_skb_set_owner(newskb, skb->sk);
|
||||
newskb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
newskb->pkt_type = PACKET_BROADCAST;
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ static void bcm_can_tx(struct bcm_op *op)
|
||||
|
||||
/* send with loopback */
|
||||
skb->dev = dev;
|
||||
skb->sk = op->sk;
|
||||
can_skb_set_owner(skb, op->sk);
|
||||
can_send(skb, 1);
|
||||
|
||||
/* update statistics */
|
||||
@ -1223,7 +1223,7 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk)
|
||||
|
||||
can_skb_prv(skb)->ifindex = dev->ifindex;
|
||||
skb->dev = dev;
|
||||
skb->sk = sk;
|
||||
can_skb_set_owner(skb, sk);
|
||||
err = can_send(skb, 1); /* send with loopback */
|
||||
dev_put(dev);
|
||||
|
||||
|
@ -715,6 +715,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||
|
||||
skb->dev = dev;
|
||||
skb->sk = sk;
|
||||
skb->priority = sk->sk_priority;
|
||||
|
||||
err = can_send(skb, ro->loopback);
|
||||
|
||||
|
@ -2803,7 +2803,7 @@ EXPORT_SYMBOL(dev_loopback_xmit);
|
||||
* the BH enable code must have IRQs enabled so that it will not deadlock.
|
||||
* --BLG
|
||||
*/
|
||||
int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
|
||||
static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
struct netdev_queue *txq;
|
||||
@ -4637,7 +4637,7 @@ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu);
|
||||
|
||||
int netdev_adjacent_sysfs_add(struct net_device *dev,
|
||||
static int netdev_adjacent_sysfs_add(struct net_device *dev,
|
||||
struct net_device *adj_dev,
|
||||
struct list_head *dev_list)
|
||||
{
|
||||
@ -4647,7 +4647,7 @@ int netdev_adjacent_sysfs_add(struct net_device *dev,
|
||||
return sysfs_create_link(&(dev->dev.kobj), &(adj_dev->dev.kobj),
|
||||
linkname);
|
||||
}
|
||||
void netdev_adjacent_sysfs_del(struct net_device *dev,
|
||||
static void netdev_adjacent_sysfs_del(struct net_device *dev,
|
||||
char *name,
|
||||
struct list_head *dev_list)
|
||||
{
|
||||
|
@ -745,6 +745,13 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event,
|
||||
attach_rules(&ops->rules_list, dev);
|
||||
break;
|
||||
|
||||
case NETDEV_CHANGENAME:
|
||||
list_for_each_entry(ops, &net->rules_ops, list) {
|
||||
detach_rules(&ops->rules_list, dev);
|
||||
attach_rules(&ops->rules_list, dev);
|
||||
}
|
||||
break;
|
||||
|
||||
case NETDEV_UNREGISTER:
|
||||
list_for_each_entry(ops, &net->rules_ops, list)
|
||||
detach_rules(&ops->rules_list, dev);
|
||||
|
@ -948,6 +948,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
|
||||
{
|
||||
char *cur=opt, *delim;
|
||||
int ipv6;
|
||||
bool ipversion_set = false;
|
||||
|
||||
if (*cur != '@') {
|
||||
if ((delim = strchr(cur, '@')) == NULL)
|
||||
@ -960,6 +961,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
|
||||
cur++;
|
||||
|
||||
if (*cur != '/') {
|
||||
ipversion_set = true;
|
||||
if ((delim = strchr(cur, '/')) == NULL)
|
||||
goto parse_failed;
|
||||
*delim = 0;
|
||||
@ -1002,7 +1004,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
|
||||
ipv6 = netpoll_parse_ip_addr(cur, &np->remote_ip);
|
||||
if (ipv6 < 0)
|
||||
goto parse_failed;
|
||||
else if (np->ipv6 != (bool)ipv6)
|
||||
else if (ipversion_set && np->ipv6 != (bool)ipv6)
|
||||
goto parse_failed;
|
||||
else
|
||||
np->ipv6 = (bool)ipv6;
|
||||
|
@ -374,7 +374,7 @@ static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev)
|
||||
if (!master_dev)
|
||||
return 0;
|
||||
ops = master_dev->rtnl_link_ops;
|
||||
if (!ops->get_slave_size)
|
||||
if (!ops || !ops->get_slave_size)
|
||||
return 0;
|
||||
/* IFLA_INFO_SLAVE_DATA + nested data */
|
||||
return nla_total_size(sizeof(struct nlattr)) +
|
||||
|
@ -1775,7 +1775,9 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
|
||||
while (order) {
|
||||
if (npages >= 1 << order) {
|
||||
page = alloc_pages(sk->sk_allocation |
|
||||
__GFP_COMP | __GFP_NOWARN,
|
||||
__GFP_COMP |
|
||||
__GFP_NOWARN |
|
||||
__GFP_NORETRY,
|
||||
order);
|
||||
if (page)
|
||||
goto fill_page;
|
||||
@ -1845,7 +1847,7 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio)
|
||||
gfp_t gfp = prio;
|
||||
|
||||
if (order)
|
||||
gfp |= __GFP_COMP | __GFP_NOWARN;
|
||||
gfp |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY;
|
||||
pfrag->page = alloc_pages(gfp, order);
|
||||
if (likely(pfrag->page)) {
|
||||
pfrag->offset = 0;
|
||||
|
@ -2104,8 +2104,6 @@ static struct notifier_block dn_dev_notifier = {
|
||||
.notifier_call = dn_device_event,
|
||||
};
|
||||
|
||||
extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
|
||||
|
||||
static struct packet_type dn_dix_packet_type __read_mostly = {
|
||||
.type = cpu_to_be16(ETH_P_DNA_RT),
|
||||
.func = dn_route_rcv,
|
||||
@ -2353,9 +2351,6 @@ static const struct proto_ops dn_proto_ops = {
|
||||
.sendpage = sock_no_sendpage,
|
||||
};
|
||||
|
||||
void dn_register_sysctl(void);
|
||||
void dn_unregister_sysctl(void);
|
||||
|
||||
MODULE_DESCRIPTION("The Linux DECnet Network Protocol");
|
||||
MODULE_AUTHOR("Linux DECnet Project Team");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -106,7 +106,6 @@ static int lowpan_header_create(struct sk_buff *skb,
|
||||
unsigned short type, const void *_daddr,
|
||||
const void *_saddr, unsigned int len)
|
||||
{
|
||||
struct ipv6hdr *hdr;
|
||||
const u8 *saddr = _saddr;
|
||||
const u8 *daddr = _daddr;
|
||||
struct ieee802154_addr sa, da;
|
||||
@ -117,8 +116,6 @@ static int lowpan_header_create(struct sk_buff *skb,
|
||||
if (type != ETH_P_IPV6)
|
||||
return 0;
|
||||
|
||||
hdr = ipv6_hdr(skb);
|
||||
|
||||
if (!saddr)
|
||||
saddr = dev->dev_addr;
|
||||
|
||||
@ -533,7 +530,27 @@ static struct header_ops lowpan_header_ops = {
|
||||
.create = lowpan_header_create,
|
||||
};
|
||||
|
||||
static struct lock_class_key lowpan_tx_busylock;
|
||||
static struct lock_class_key lowpan_netdev_xmit_lock_key;
|
||||
|
||||
static void lowpan_set_lockdep_class_one(struct net_device *dev,
|
||||
struct netdev_queue *txq,
|
||||
void *_unused)
|
||||
{
|
||||
lockdep_set_class(&txq->_xmit_lock,
|
||||
&lowpan_netdev_xmit_lock_key);
|
||||
}
|
||||
|
||||
|
||||
static int lowpan_dev_init(struct net_device *dev)
|
||||
{
|
||||
netdev_for_each_tx_queue(dev, lowpan_set_lockdep_class_one, NULL);
|
||||
dev->qdisc_tx_busylock = &lowpan_tx_busylock;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct net_device_ops lowpan_netdev_ops = {
|
||||
.ndo_init = lowpan_dev_init,
|
||||
.ndo_start_xmit = lowpan_xmit,
|
||||
.ndo_set_mac_address = lowpan_set_address,
|
||||
};
|
||||
|
@ -1443,7 +1443,8 @@ static size_t inet_nlmsg_size(void)
|
||||
+ nla_total_size(4) /* IFA_LOCAL */
|
||||
+ nla_total_size(4) /* IFA_BROADCAST */
|
||||
+ nla_total_size(IFNAMSIZ) /* IFA_LABEL */
|
||||
+ nla_total_size(4); /* IFA_FLAGS */
|
||||
+ nla_total_size(4) /* IFA_FLAGS */
|
||||
+ nla_total_size(sizeof(struct ifa_cacheinfo)); /* IFA_CACHEINFO */
|
||||
}
|
||||
|
||||
static inline u32 cstamp_delta(unsigned long cstamp)
|
||||
|
@ -101,28 +101,22 @@ static void tunnel_dst_reset_all(struct ip_tunnel *t)
|
||||
__tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL);
|
||||
}
|
||||
|
||||
static struct dst_entry *tunnel_dst_get(struct ip_tunnel *t)
|
||||
static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie)
|
||||
{
|
||||
struct dst_entry *dst;
|
||||
|
||||
rcu_read_lock();
|
||||
dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst);
|
||||
if (dst)
|
||||
if (dst) {
|
||||
if (dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
|
||||
rcu_read_unlock();
|
||||
tunnel_dst_reset(t);
|
||||
return NULL;
|
||||
}
|
||||
dst_hold(dst);
|
||||
rcu_read_unlock();
|
||||
return dst;
|
||||
}
|
||||
|
||||
static struct dst_entry *tunnel_dst_check(struct ip_tunnel *t, u32 cookie)
|
||||
{
|
||||
struct dst_entry *dst = tunnel_dst_get(t);
|
||||
|
||||
if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
|
||||
tunnel_dst_reset(t);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dst;
|
||||
rcu_read_unlock();
|
||||
return (struct rtable *)dst;
|
||||
}
|
||||
|
||||
/* Often modified stats are per cpu, other are shared (netdev->stats) */
|
||||
@ -584,7 +578,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||
struct flowi4 fl4;
|
||||
u8 tos, ttl;
|
||||
__be16 df;
|
||||
struct rtable *rt = NULL; /* Route to the other host */
|
||||
struct rtable *rt; /* Route to the other host */
|
||||
unsigned int max_headroom; /* The extra header space needed */
|
||||
__be32 dst;
|
||||
int err;
|
||||
@ -657,8 +651,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||
init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr,
|
||||
tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link);
|
||||
|
||||
if (connected)
|
||||
rt = (struct rtable *)tunnel_dst_check(tunnel, 0);
|
||||
rt = connected ? tunnel_rtable_get(tunnel, 0) : NULL;
|
||||
|
||||
if (!rt) {
|
||||
rt = ip_route_output_key(tunnel->net, &fl4);
|
||||
|
@ -61,6 +61,11 @@ config NFT_CHAIN_NAT_IPV4
|
||||
packet transformations such as the source, destination address and
|
||||
source and destination ports.
|
||||
|
||||
config NFT_REJECT_IPV4
|
||||
depends on NF_TABLES_IPV4
|
||||
default NFT_REJECT
|
||||
tristate
|
||||
|
||||
config NF_TABLES_ARP
|
||||
depends on NF_TABLES
|
||||
tristate "ARP nf_tables support"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user