diff options
Diffstat (limited to 'drivers')
23 files changed, 293 insertions, 116 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index fc63992ab0e0..c99dc59d729b 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -4289,7 +4289,7 @@ static int bond_check_params(struct bond_params *params) | |||
4289 | int bond_mode = BOND_MODE_ROUNDROBIN; | 4289 | int bond_mode = BOND_MODE_ROUNDROBIN; |
4290 | int xmit_hashtype = BOND_XMIT_POLICY_LAYER2; | 4290 | int xmit_hashtype = BOND_XMIT_POLICY_LAYER2; |
4291 | int lacp_fast = 0; | 4291 | int lacp_fast = 0; |
4292 | int tlb_dynamic_lb = 0; | 4292 | int tlb_dynamic_lb; |
4293 | 4293 | ||
4294 | /* Convert string parameters. */ | 4294 | /* Convert string parameters. */ |
4295 | if (mode) { | 4295 | if (mode) { |
@@ -4601,16 +4601,13 @@ static int bond_check_params(struct bond_params *params) | |||
4601 | } | 4601 | } |
4602 | ad_user_port_key = valptr->value; | 4602 | ad_user_port_key = valptr->value; |
4603 | 4603 | ||
4604 | if ((bond_mode == BOND_MODE_TLB) || (bond_mode == BOND_MODE_ALB)) { | 4604 | bond_opt_initstr(&newval, "default"); |
4605 | bond_opt_initstr(&newval, "default"); | 4605 | valptr = bond_opt_parse(bond_opt_get(BOND_OPT_TLB_DYNAMIC_LB), &newval); |
4606 | valptr = bond_opt_parse(bond_opt_get(BOND_OPT_TLB_DYNAMIC_LB), | 4606 | if (!valptr) { |
4607 | &newval); | 4607 | pr_err("Error: No tlb_dynamic_lb default value"); |
4608 | if (!valptr) { | 4608 | return -EINVAL; |
4609 | pr_err("Error: No tlb_dynamic_lb default value"); | ||
4610 | return -EINVAL; | ||
4611 | } | ||
4612 | tlb_dynamic_lb = valptr->value; | ||
4613 | } | 4609 | } |
4610 | tlb_dynamic_lb = valptr->value; | ||
4614 | 4611 | ||
4615 | if (lp_interval == 0) { | 4612 | if (lp_interval == 0) { |
4616 | pr_warn("Warning: ip_interval must be between 1 and %d, so it was reset to %d\n", | 4613 | pr_warn("Warning: ip_interval must be between 1 and %d, so it was reset to %d\n", |
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index a12d603d41c6..5931aa2fe997 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c | |||
@@ -754,6 +754,9 @@ static int bond_option_mode_set(struct bonding *bond, | |||
754 | bond->params.miimon); | 754 | bond->params.miimon); |
755 | } | 755 | } |
756 | 756 | ||
757 | if (newval->value == BOND_MODE_ALB) | ||
758 | bond->params.tlb_dynamic_lb = 1; | ||
759 | |||
757 | /* don't cache arp_validate between modes */ | 760 | /* don't cache arp_validate between modes */ |
758 | bond->params.arp_validate = BOND_ARP_VALIDATE_NONE; | 761 | bond->params.arp_validate = BOND_ARP_VALIDATE_NONE; |
759 | bond->params.mode = newval->value; | 762 | bond->params.mode = newval->value; |
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index a6572b51435a..c3c53f6cd9e6 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c | |||
@@ -1735,11 +1735,8 @@ static void bcm_sysport_get_stats64(struct net_device *dev, | |||
1735 | stats->tx_packets += tx_packets; | 1735 | stats->tx_packets += tx_packets; |
1736 | } | 1736 | } |
1737 | 1737 | ||
1738 | /* lockless update tx_bytes and tx_packets */ | ||
1739 | u64_stats_update_begin(&priv->syncp); | ||
1740 | stats64->tx_bytes = stats->tx_bytes; | 1738 | stats64->tx_bytes = stats->tx_bytes; |
1741 | stats64->tx_packets = stats->tx_packets; | 1739 | stats64->tx_packets = stats->tx_packets; |
1742 | u64_stats_update_end(&priv->syncp); | ||
1743 | 1740 | ||
1744 | do { | 1741 | do { |
1745 | start = u64_stats_fetch_begin_irq(&priv->syncp); | 1742 | start = u64_stats_fetch_begin_irq(&priv->syncp); |
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index af33dc15c55f..656e6af70f0a 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
@@ -11536,11 +11536,11 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq, | |||
11536 | tg3_napi_enable(tp); | 11536 | tg3_napi_enable(tp); |
11537 | 11537 | ||
11538 | for (i = 0; i < tp->irq_cnt; i++) { | 11538 | for (i = 0; i < tp->irq_cnt; i++) { |
11539 | struct tg3_napi *tnapi = &tp->napi[i]; | ||
11540 | err = tg3_request_irq(tp, i); | 11539 | err = tg3_request_irq(tp, i); |
11541 | if (err) { | 11540 | if (err) { |
11542 | for (i--; i >= 0; i--) { | 11541 | for (i--; i >= 0; i--) { |
11543 | tnapi = &tp->napi[i]; | 11542 | struct tg3_napi *tnapi = &tp->napi[i]; |
11543 | |||
11544 | free_irq(tnapi->irq_vec, tnapi); | 11544 | free_irq(tnapi->irq_vec, tnapi); |
11545 | } | 11545 | } |
11546 | goto out_napi_fini; | 11546 | goto out_napi_fini; |
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 674cf9d13b98..8984c4938881 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h | |||
@@ -930,6 +930,14 @@ static inline bool is_ipv4_pkt(struct sk_buff *skb) | |||
930 | return skb->protocol == htons(ETH_P_IP) && ip_hdr(skb)->version == 4; | 930 | return skb->protocol == htons(ETH_P_IP) && ip_hdr(skb)->version == 4; |
931 | } | 931 | } |
932 | 932 | ||
933 | static inline bool is_ipv6_ext_hdr(struct sk_buff *skb) | ||
934 | { | ||
935 | if (ip_hdr(skb)->version == 6) | ||
936 | return ipv6_ext_hdr(ipv6_hdr(skb)->nexthdr); | ||
937 | else | ||
938 | return false; | ||
939 | } | ||
940 | |||
933 | #define be_error_recovering(adapter) \ | 941 | #define be_error_recovering(adapter) \ |
934 | (adapter->flags & BE_FLAGS_TRY_RECOVERY) | 942 | (adapter->flags & BE_FLAGS_TRY_RECOVERY) |
935 | 943 | ||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 319eee36649b..0e3d9f39a807 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -5089,6 +5089,20 @@ static netdev_features_t be_features_check(struct sk_buff *skb, | |||
5089 | struct be_adapter *adapter = netdev_priv(dev); | 5089 | struct be_adapter *adapter = netdev_priv(dev); |
5090 | u8 l4_hdr = 0; | 5090 | u8 l4_hdr = 0; |
5091 | 5091 | ||
5092 | if (skb_is_gso(skb)) { | ||
5093 | /* IPv6 TSO requests with extension hdrs are a problem | ||
5094 | * to Lancer and BE3 HW. Disable TSO6 feature. | ||
5095 | */ | ||
5096 | if (!skyhawk_chip(adapter) && is_ipv6_ext_hdr(skb)) | ||
5097 | features &= ~NETIF_F_TSO6; | ||
5098 | |||
5099 | /* Lancer cannot handle the packet with MSS less than 256. | ||
5100 | * Disable the GSO support in such cases | ||
5101 | */ | ||
5102 | if (lancer_chip(adapter) && skb_shinfo(skb)->gso_size < 256) | ||
5103 | features &= ~NETIF_F_GSO_MASK; | ||
5104 | } | ||
5105 | |||
5092 | /* The code below restricts offload features for some tunneled and | 5106 | /* The code below restricts offload features for some tunneled and |
5093 | * Q-in-Q packets. | 5107 | * Q-in-Q packets. |
5094 | * Offload features for normal (non tunnel) packets are unchanged. | 5108 | * Offload features for normal (non tunnel) packets are unchanged. |
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index ed7cd6c48019..696b99e65a5a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c | |||
@@ -575,15 +575,14 @@ static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp, | |||
575 | } | 575 | } |
576 | 576 | ||
577 | static struct mlxsw_sp_span_entry * | 577 | static struct mlxsw_sp_span_entry * |
578 | mlxsw_sp_span_entry_find(struct mlxsw_sp_port *port) | 578 | mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port) |
579 | { | 579 | { |
580 | struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp; | ||
581 | int i; | 580 | int i; |
582 | 581 | ||
583 | for (i = 0; i < mlxsw_sp->span.entries_count; i++) { | 582 | for (i = 0; i < mlxsw_sp->span.entries_count; i++) { |
584 | struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i]; | 583 | struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i]; |
585 | 584 | ||
586 | if (curr->used && curr->local_port == port->local_port) | 585 | if (curr->used && curr->local_port == local_port) |
587 | return curr; | 586 | return curr; |
588 | } | 587 | } |
589 | return NULL; | 588 | return NULL; |
@@ -594,7 +593,8 @@ static struct mlxsw_sp_span_entry | |||
594 | { | 593 | { |
595 | struct mlxsw_sp_span_entry *span_entry; | 594 | struct mlxsw_sp_span_entry *span_entry; |
596 | 595 | ||
597 | span_entry = mlxsw_sp_span_entry_find(port); | 596 | span_entry = mlxsw_sp_span_entry_find(port->mlxsw_sp, |
597 | port->local_port); | ||
598 | if (span_entry) { | 598 | if (span_entry) { |
599 | /* Already exists, just take a reference */ | 599 | /* Already exists, just take a reference */ |
600 | span_entry->ref_count++; | 600 | span_entry->ref_count++; |
@@ -783,12 +783,13 @@ err_port_bind: | |||
783 | } | 783 | } |
784 | 784 | ||
785 | static void mlxsw_sp_span_mirror_remove(struct mlxsw_sp_port *from, | 785 | static void mlxsw_sp_span_mirror_remove(struct mlxsw_sp_port *from, |
786 | struct mlxsw_sp_port *to, | 786 | u8 destination_port, |
787 | enum mlxsw_sp_span_type type) | 787 | enum mlxsw_sp_span_type type) |
788 | { | 788 | { |
789 | struct mlxsw_sp_span_entry *span_entry; | 789 | struct mlxsw_sp_span_entry *span_entry; |
790 | 790 | ||
791 | span_entry = mlxsw_sp_span_entry_find(to); | 791 | span_entry = mlxsw_sp_span_entry_find(from->mlxsw_sp, |
792 | destination_port); | ||
792 | if (!span_entry) { | 793 | if (!span_entry) { |
793 | netdev_err(from->dev, "no span entry found\n"); | 794 | netdev_err(from->dev, "no span entry found\n"); |
794 | return; | 795 | return; |
@@ -1563,14 +1564,12 @@ static void | |||
1563 | mlxsw_sp_port_del_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port, | 1564 | mlxsw_sp_port_del_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port, |
1564 | struct mlxsw_sp_port_mall_mirror_tc_entry *mirror) | 1565 | struct mlxsw_sp_port_mall_mirror_tc_entry *mirror) |
1565 | { | 1566 | { |
1566 | struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; | ||
1567 | enum mlxsw_sp_span_type span_type; | 1567 | enum mlxsw_sp_span_type span_type; |
1568 | struct mlxsw_sp_port *to_port; | ||
1569 | 1568 | ||
1570 | to_port = mlxsw_sp->ports[mirror->to_local_port]; | ||
1571 | span_type = mirror->ingress ? | 1569 | span_type = mirror->ingress ? |
1572 | MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS; | 1570 | MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS; |
1573 | mlxsw_sp_span_mirror_remove(mlxsw_sp_port, to_port, span_type); | 1571 | mlxsw_sp_span_mirror_remove(mlxsw_sp_port, mirror->to_local_port, |
1572 | span_type); | ||
1574 | } | 1573 | } |
1575 | 1574 | ||
1576 | static int | 1575 | static int |
@@ -2545,7 +2544,9 @@ out: | |||
2545 | return err; | 2544 | return err; |
2546 | } | 2545 | } |
2547 | 2546 | ||
2548 | #define MLXSW_SP_QSFP_I2C_ADDR 0x50 | 2547 | #define MLXSW_SP_I2C_ADDR_LOW 0x50 |
2548 | #define MLXSW_SP_I2C_ADDR_HIGH 0x51 | ||
2549 | #define MLXSW_SP_EEPROM_PAGE_LENGTH 256 | ||
2549 | 2550 | ||
2550 | static int mlxsw_sp_query_module_eeprom(struct mlxsw_sp_port *mlxsw_sp_port, | 2551 | static int mlxsw_sp_query_module_eeprom(struct mlxsw_sp_port *mlxsw_sp_port, |
2551 | u16 offset, u16 size, void *data, | 2552 | u16 offset, u16 size, void *data, |
@@ -2554,12 +2555,25 @@ static int mlxsw_sp_query_module_eeprom(struct mlxsw_sp_port *mlxsw_sp_port, | |||
2554 | struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; | 2555 | struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; |
2555 | char eeprom_tmp[MLXSW_SP_REG_MCIA_EEPROM_SIZE]; | 2556 | char eeprom_tmp[MLXSW_SP_REG_MCIA_EEPROM_SIZE]; |
2556 | char mcia_pl[MLXSW_REG_MCIA_LEN]; | 2557 | char mcia_pl[MLXSW_REG_MCIA_LEN]; |
2558 | u16 i2c_addr; | ||
2557 | int status; | 2559 | int status; |
2558 | int err; | 2560 | int err; |
2559 | 2561 | ||
2560 | size = min_t(u16, size, MLXSW_SP_REG_MCIA_EEPROM_SIZE); | 2562 | size = min_t(u16, size, MLXSW_SP_REG_MCIA_EEPROM_SIZE); |
2563 | |||
2564 | if (offset < MLXSW_SP_EEPROM_PAGE_LENGTH && | ||
2565 | offset + size > MLXSW_SP_EEPROM_PAGE_LENGTH) | ||
2566 | /* Cross pages read, read until offset 256 in low page */ | ||
2567 | size = MLXSW_SP_EEPROM_PAGE_LENGTH - offset; | ||
2568 | |||
2569 | i2c_addr = MLXSW_SP_I2C_ADDR_LOW; | ||
2570 | if (offset >= MLXSW_SP_EEPROM_PAGE_LENGTH) { | ||
2571 | i2c_addr = MLXSW_SP_I2C_ADDR_HIGH; | ||
2572 | offset -= MLXSW_SP_EEPROM_PAGE_LENGTH; | ||
2573 | } | ||
2574 | |||
2561 | mlxsw_reg_mcia_pack(mcia_pl, mlxsw_sp_port->mapping.module, | 2575 | mlxsw_reg_mcia_pack(mcia_pl, mlxsw_sp_port->mapping.module, |
2562 | 0, 0, offset, size, MLXSW_SP_QSFP_I2C_ADDR); | 2576 | 0, 0, offset, size, i2c_addr); |
2563 | 2577 | ||
2564 | err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mcia), mcia_pl); | 2578 | err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mcia), mcia_pl); |
2565 | if (err) | 2579 | if (err) |
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index f0fb898533fb..2cfb3f5d092d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | |||
@@ -4868,7 +4868,8 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb, | |||
4868 | struct fib_notifier_info *info = ptr; | 4868 | struct fib_notifier_info *info = ptr; |
4869 | struct mlxsw_sp_router *router; | 4869 | struct mlxsw_sp_router *router; |
4870 | 4870 | ||
4871 | if (!net_eq(info->net, &init_net)) | 4871 | if (!net_eq(info->net, &init_net) || |
4872 | (info->family != AF_INET && info->family != AF_INET6)) | ||
4872 | return NOTIFY_DONE; | 4873 | return NOTIFY_DONE; |
4873 | 4874 | ||
4874 | fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC); | 4875 | fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC); |
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index d396183108f7..a18b4d2b1d3e 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c | |||
@@ -44,6 +44,16 @@ | |||
44 | #include "../nfp_net.h" | 44 | #include "../nfp_net.h" |
45 | #include "../nfp_port.h" | 45 | #include "../nfp_port.h" |
46 | 46 | ||
47 | #define NFP_FLOWER_WHITELIST_DISSECTOR \ | ||
48 | (BIT(FLOW_DISSECTOR_KEY_CONTROL) | \ | ||
49 | BIT(FLOW_DISSECTOR_KEY_BASIC) | \ | ||
50 | BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | \ | ||
51 | BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | \ | ||
52 | BIT(FLOW_DISSECTOR_KEY_PORTS) | \ | ||
53 | BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | \ | ||
54 | BIT(FLOW_DISSECTOR_KEY_VLAN) | \ | ||
55 | BIT(FLOW_DISSECTOR_KEY_IP)) | ||
56 | |||
47 | static int | 57 | static int |
48 | nfp_flower_xmit_flow(struct net_device *netdev, | 58 | nfp_flower_xmit_flow(struct net_device *netdev, |
49 | struct nfp_fl_payload *nfp_flow, u8 mtype) | 59 | struct nfp_fl_payload *nfp_flow, u8 mtype) |
@@ -112,6 +122,9 @@ nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls, | |||
112 | u8 key_layer; | 122 | u8 key_layer; |
113 | int key_size; | 123 | int key_size; |
114 | 124 | ||
125 | if (flow->dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR) | ||
126 | return -EOPNOTSUPP; | ||
127 | |||
115 | if (dissector_uses_key(flow->dissector, | 128 | if (dissector_uses_key(flow->dissector, |
116 | FLOW_DISSECTOR_KEY_ENC_CONTROL)) { | 129 | FLOW_DISSECTOR_KEY_ENC_CONTROL)) { |
117 | struct flow_dissector_key_control *mask_enc_ctl = | 130 | struct flow_dissector_key_control *mask_enc_ctl = |
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.c b/drivers/net/ethernet/netronome/nfp/nfp_main.c index f055b1774d65..f8fa63b66739 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_main.c | |||
@@ -74,6 +74,45 @@ static const struct pci_device_id nfp_pci_device_ids[] = { | |||
74 | }; | 74 | }; |
75 | MODULE_DEVICE_TABLE(pci, nfp_pci_device_ids); | 75 | MODULE_DEVICE_TABLE(pci, nfp_pci_device_ids); |
76 | 76 | ||
77 | static bool nfp_board_ready(struct nfp_pf *pf) | ||
78 | { | ||
79 | const char *cp; | ||
80 | long state; | ||
81 | int err; | ||
82 | |||
83 | cp = nfp_hwinfo_lookup(pf->hwinfo, "board.state"); | ||
84 | if (!cp) | ||
85 | return false; | ||
86 | |||
87 | err = kstrtol(cp, 0, &state); | ||
88 | if (err < 0) | ||
89 | return false; | ||
90 | |||
91 | return state == 15; | ||
92 | } | ||
93 | |||
94 | static int nfp_pf_board_state_wait(struct nfp_pf *pf) | ||
95 | { | ||
96 | const unsigned long wait_until = jiffies + 10 * HZ; | ||
97 | |||
98 | while (!nfp_board_ready(pf)) { | ||
99 | if (time_is_before_eq_jiffies(wait_until)) { | ||
100 | nfp_err(pf->cpp, "NFP board initialization timeout\n"); | ||
101 | return -EINVAL; | ||
102 | } | ||
103 | |||
104 | nfp_info(pf->cpp, "waiting for board initialization\n"); | ||
105 | if (msleep_interruptible(500)) | ||
106 | return -ERESTARTSYS; | ||
107 | |||
108 | /* Refresh cached information */ | ||
109 | kfree(pf->hwinfo); | ||
110 | pf->hwinfo = nfp_hwinfo_read(pf->cpp); | ||
111 | } | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
77 | static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf) | 116 | static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf) |
78 | { | 117 | { |
79 | int err; | 118 | int err; |
@@ -312,6 +351,10 @@ static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf) | |||
312 | struct nfp_nsp *nsp; | 351 | struct nfp_nsp *nsp; |
313 | int err; | 352 | int err; |
314 | 353 | ||
354 | err = nfp_resource_wait(pf->cpp, NFP_RESOURCE_NSP, 30); | ||
355 | if (err) | ||
356 | return err; | ||
357 | |||
315 | nsp = nfp_nsp_open(pf->cpp); | 358 | nsp = nfp_nsp_open(pf->cpp); |
316 | if (IS_ERR(nsp)) { | 359 | if (IS_ERR(nsp)) { |
317 | err = PTR_ERR(nsp); | 360 | err = PTR_ERR(nsp); |
@@ -425,6 +468,10 @@ static int nfp_pci_probe(struct pci_dev *pdev, | |||
425 | nfp_hwinfo_lookup(pf->hwinfo, "assembly.revision"), | 468 | nfp_hwinfo_lookup(pf->hwinfo, "assembly.revision"), |
426 | nfp_hwinfo_lookup(pf->hwinfo, "cpld.version")); | 469 | nfp_hwinfo_lookup(pf->hwinfo, "cpld.version")); |
427 | 470 | ||
471 | err = nfp_pf_board_state_wait(pf); | ||
472 | if (err) | ||
473 | goto err_hwinfo_free; | ||
474 | |||
428 | err = devlink_register(devlink, &pdev->dev); | 475 | err = devlink_register(devlink, &pdev->dev); |
429 | if (err) | 476 | if (err) |
430 | goto err_hwinfo_free; | 477 | goto err_hwinfo_free; |
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c index 5abb9ba31e7d..ff373acd28f3 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c | |||
@@ -64,23 +64,6 @@ | |||
64 | 64 | ||
65 | #define NFP_PF_CSR_SLICE_SIZE (32 * 1024) | 65 | #define NFP_PF_CSR_SLICE_SIZE (32 * 1024) |
66 | 66 | ||
67 | static int nfp_is_ready(struct nfp_pf *pf) | ||
68 | { | ||
69 | const char *cp; | ||
70 | long state; | ||
71 | int err; | ||
72 | |||
73 | cp = nfp_hwinfo_lookup(pf->hwinfo, "board.state"); | ||
74 | if (!cp) | ||
75 | return 0; | ||
76 | |||
77 | err = kstrtol(cp, 0, &state); | ||
78 | if (err < 0) | ||
79 | return 0; | ||
80 | |||
81 | return state == 15; | ||
82 | } | ||
83 | |||
84 | /** | 67 | /** |
85 | * nfp_net_get_mac_addr() - Get the MAC address. | 68 | * nfp_net_get_mac_addr() - Get the MAC address. |
86 | * @pf: NFP PF handle | 69 | * @pf: NFP PF handle |
@@ -725,12 +708,6 @@ int nfp_net_pci_probe(struct nfp_pf *pf) | |||
725 | 708 | ||
726 | INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_vnics); | 709 | INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_vnics); |
727 | 710 | ||
728 | /* Verify that the board has completed initialization */ | ||
729 | if (!nfp_is_ready(pf)) { | ||
730 | nfp_err(pf->cpp, "NFP is not ready for NIC operation.\n"); | ||
731 | return -EINVAL; | ||
732 | } | ||
733 | |||
734 | if (!pf->rtbl) { | 711 | if (!pf->rtbl) { |
735 | nfp_err(pf->cpp, "No %s, giving up.\n", | 712 | nfp_err(pf->cpp, "No %s, giving up.\n", |
736 | pf->fw_loaded ? "symbol table" : "firmware found"); | 713 | pf->fw_loaded ? "symbol table" : "firmware found"); |
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp.h index 1a8d04a1e113..3ce51f03126f 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp.h +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp.h | |||
@@ -97,6 +97,8 @@ nfp_resource_acquire(struct nfp_cpp *cpp, const char *name); | |||
97 | 97 | ||
98 | void nfp_resource_release(struct nfp_resource *res); | 98 | void nfp_resource_release(struct nfp_resource *res); |
99 | 99 | ||
100 | int nfp_resource_wait(struct nfp_cpp *cpp, const char *name, unsigned int secs); | ||
101 | |||
100 | u32 nfp_resource_cpp_id(struct nfp_resource *res); | 102 | u32 nfp_resource_cpp_id(struct nfp_resource *res); |
101 | 103 | ||
102 | const char *nfp_resource_name(struct nfp_resource *res); | 104 | const char *nfp_resource_name(struct nfp_resource *res); |
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c index 072612263dab..b1dd13ff282b 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c | |||
@@ -250,6 +250,51 @@ void nfp_resource_release(struct nfp_resource *res) | |||
250 | } | 250 | } |
251 | 251 | ||
252 | /** | 252 | /** |
253 | * nfp_resource_wait() - Wait for resource to appear | ||
254 | * @cpp: NFP CPP handle | ||
255 | * @name: Name of the resource | ||
256 | * @secs: Number of seconds to wait | ||
257 | * | ||
258 | * Wait for resource to appear in the resource table, grab and release | ||
259 | * its lock. The wait is jiffies-based, don't expect fine granularity. | ||
260 | * | ||
261 | * Return: 0 on success, errno otherwise. | ||
262 | */ | ||
263 | int nfp_resource_wait(struct nfp_cpp *cpp, const char *name, unsigned int secs) | ||
264 | { | ||
265 | unsigned long warn_at = jiffies + NFP_MUTEX_WAIT_FIRST_WARN * HZ; | ||
266 | unsigned long err_at = jiffies + secs * HZ; | ||
267 | struct nfp_resource *res; | ||
268 | |||
269 | while (true) { | ||
270 | res = nfp_resource_acquire(cpp, name); | ||
271 | if (!IS_ERR(res)) { | ||
272 | nfp_resource_release(res); | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | if (PTR_ERR(res) != -ENOENT) { | ||
277 | nfp_err(cpp, "error waiting for resource %s: %ld\n", | ||
278 | name, PTR_ERR(res)); | ||
279 | return PTR_ERR(res); | ||
280 | } | ||
281 | if (time_is_before_eq_jiffies(err_at)) { | ||
282 | nfp_err(cpp, "timeout waiting for resource %s\n", name); | ||
283 | return -ETIMEDOUT; | ||
284 | } | ||
285 | if (time_is_before_eq_jiffies(warn_at)) { | ||
286 | warn_at = jiffies + NFP_MUTEX_WAIT_NEXT_WARN * HZ; | ||
287 | nfp_info(cpp, "waiting for NFP resource %s\n", name); | ||
288 | } | ||
289 | if (msleep_interruptible(10)) { | ||
290 | nfp_err(cpp, "wait for resource %s interrupted\n", | ||
291 | name); | ||
292 | return -ERESTARTSYS; | ||
293 | } | ||
294 | } | ||
295 | } | ||
296 | |||
297 | /** | ||
253 | * nfp_resource_cpp_id() - Return the cpp_id of a resource handle | 298 | * nfp_resource_cpp_id() - Return the cpp_id of a resource handle |
254 | * @res: NFP Resource handle | 299 | * @res: NFP Resource handle |
255 | * | 300 | * |
diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c index 89ab786da25f..4a67c55aa9f1 100644 --- a/drivers/net/ethernet/nuvoton/w90p910_ether.c +++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/interrupt.h> | ||
14 | #include <linux/mii.h> | 15 | #include <linux/mii.h> |
15 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
16 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c index eaca4578435d..8f6ccc0c39e5 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c | |||
@@ -1244,7 +1244,6 @@ int qed_dcbx_get_config_params(struct qed_hwfn *p_hwfn, | |||
1244 | if (!dcbx_info) | 1244 | if (!dcbx_info) |
1245 | return -ENOMEM; | 1245 | return -ENOMEM; |
1246 | 1246 | ||
1247 | memset(dcbx_info, 0, sizeof(*dcbx_info)); | ||
1248 | rc = qed_dcbx_query_params(p_hwfn, dcbx_info, QED_DCBX_OPERATIONAL_MIB); | 1247 | rc = qed_dcbx_query_params(p_hwfn, dcbx_info, QED_DCBX_OPERATIONAL_MIB); |
1249 | if (rc) { | 1248 | if (rc) { |
1250 | kfree(dcbx_info); | 1249 | kfree(dcbx_info); |
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c index 557c9bf1a469..86b8c758f94e 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c | |||
@@ -84,6 +84,10 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb) | |||
84 | if (((int)skb->len - (int)packet_len) < 0) | 84 | if (((int)skb->len - (int)packet_len) < 0) |
85 | return NULL; | 85 | return NULL; |
86 | 86 | ||
87 | /* Some hardware can send us empty frames. Catch them */ | ||
88 | if (ntohs(maph->pkt_len) == 0) | ||
89 | return NULL; | ||
90 | |||
87 | skbn = alloc_skb(packet_len + RMNET_MAP_DEAGGR_SPACING, GFP_ATOMIC); | 91 | skbn = alloc_skb(packet_len + RMNET_MAP_DEAGGR_SPACING, GFP_ATOMIC); |
88 | if (!skbn) | 92 | if (!skbn) |
89 | return NULL; | 93 | return NULL; |
@@ -94,11 +98,5 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb) | |||
94 | memcpy(skbn->data, skb->data, packet_len); | 98 | memcpy(skbn->data, skb->data, packet_len); |
95 | skb_pull(skb, packet_len); | 99 | skb_pull(skb, packet_len); |
96 | 100 | ||
97 | /* Some hardware can send us empty frames. Catch them */ | ||
98 | if (ntohs(maph->pkt_len) == 0) { | ||
99 | kfree_skb(skb); | ||
100 | return NULL; | ||
101 | } | ||
102 | |||
103 | return skbn; | 101 | return skbn; |
104 | } | 102 | } |
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 0b6a39b003a4..012fb66eed8d 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c | |||
@@ -2595,6 +2595,11 @@ static int smsc911x_suspend(struct device *dev) | |||
2595 | struct net_device *ndev = dev_get_drvdata(dev); | 2595 | struct net_device *ndev = dev_get_drvdata(dev); |
2596 | struct smsc911x_data *pdata = netdev_priv(ndev); | 2596 | struct smsc911x_data *pdata = netdev_priv(ndev); |
2597 | 2597 | ||
2598 | if (netif_running(ndev)) { | ||
2599 | netif_stop_queue(ndev); | ||
2600 | netif_device_detach(ndev); | ||
2601 | } | ||
2602 | |||
2598 | /* enable wake on LAN, energy detection and the external PME | 2603 | /* enable wake on LAN, energy detection and the external PME |
2599 | * signal. */ | 2604 | * signal. */ |
2600 | smsc911x_reg_write(pdata, PMT_CTRL, | 2605 | smsc911x_reg_write(pdata, PMT_CTRL, |
@@ -2628,7 +2633,15 @@ static int smsc911x_resume(struct device *dev) | |||
2628 | while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to) | 2633 | while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to) |
2629 | udelay(1000); | 2634 | udelay(1000); |
2630 | 2635 | ||
2631 | return (to == 0) ? -EIO : 0; | 2636 | if (to == 0) |
2637 | return -EIO; | ||
2638 | |||
2639 | if (netif_running(ndev)) { | ||
2640 | netif_device_attach(ndev); | ||
2641 | netif_start_queue(ndev); | ||
2642 | } | ||
2643 | |||
2644 | return 0; | ||
2632 | } | 2645 | } |
2633 | 2646 | ||
2634 | static const struct dev_pm_ops smsc911x_pm_ops = { | 2647 | static const struct dev_pm_ops smsc911x_pm_ops = { |
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index ec546da86683..d98cdfb1536b 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h | |||
@@ -204,6 +204,8 @@ int netvsc_recv_callback(struct net_device *net, | |||
204 | const struct ndis_pkt_8021q_info *vlan); | 204 | const struct ndis_pkt_8021q_info *vlan); |
205 | void netvsc_channel_cb(void *context); | 205 | void netvsc_channel_cb(void *context); |
206 | int netvsc_poll(struct napi_struct *napi, int budget); | 206 | int netvsc_poll(struct napi_struct *napi, int budget); |
207 | |||
208 | void rndis_set_subchannel(struct work_struct *w); | ||
207 | bool rndis_filter_opened(const struct netvsc_device *nvdev); | 209 | bool rndis_filter_opened(const struct netvsc_device *nvdev); |
208 | int rndis_filter_open(struct netvsc_device *nvdev); | 210 | int rndis_filter_open(struct netvsc_device *nvdev); |
209 | int rndis_filter_close(struct netvsc_device *nvdev); | 211 | int rndis_filter_close(struct netvsc_device *nvdev); |
@@ -782,6 +784,7 @@ struct netvsc_device { | |||
782 | u32 num_chn; | 784 | u32 num_chn; |
783 | 785 | ||
784 | atomic_t open_chn; | 786 | atomic_t open_chn; |
787 | struct work_struct subchan_work; | ||
785 | wait_queue_head_t subchan_open; | 788 | wait_queue_head_t subchan_open; |
786 | 789 | ||
787 | struct rndis_device *extension; | 790 | struct rndis_device *extension; |
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 0062b802676f..a5511b7326af 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c | |||
@@ -81,6 +81,7 @@ static struct netvsc_device *alloc_net_device(void) | |||
81 | 81 | ||
82 | init_completion(&net_device->channel_init_wait); | 82 | init_completion(&net_device->channel_init_wait); |
83 | init_waitqueue_head(&net_device->subchan_open); | 83 | init_waitqueue_head(&net_device->subchan_open); |
84 | INIT_WORK(&net_device->subchan_work, rndis_set_subchannel); | ||
84 | 85 | ||
85 | return net_device; | 86 | return net_device; |
86 | } | 87 | } |
@@ -557,6 +558,8 @@ void netvsc_device_remove(struct hv_device *device) | |||
557 | = rtnl_dereference(net_device_ctx->nvdev); | 558 | = rtnl_dereference(net_device_ctx->nvdev); |
558 | int i; | 559 | int i; |
559 | 560 | ||
561 | cancel_work_sync(&net_device->subchan_work); | ||
562 | |||
560 | netvsc_disconnect_vsp(device); | 563 | netvsc_disconnect_vsp(device); |
561 | 564 | ||
562 | RCU_INIT_POINTER(net_device_ctx->nvdev, NULL); | 565 | RCU_INIT_POINTER(net_device_ctx->nvdev, NULL); |
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 165ba4b3b423..d4902ee5f260 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c | |||
@@ -49,7 +49,7 @@ | |||
49 | #define NETVSC_MIN_TX_SECTIONS 10 | 49 | #define NETVSC_MIN_TX_SECTIONS 10 |
50 | #define NETVSC_DEFAULT_TX 192 /* ~1M */ | 50 | #define NETVSC_DEFAULT_TX 192 /* ~1M */ |
51 | #define NETVSC_MIN_RX_SECTIONS 10 /* ~64K */ | 51 | #define NETVSC_MIN_RX_SECTIONS 10 /* ~64K */ |
52 | #define NETVSC_DEFAULT_RX 2048 /* ~4M */ | 52 | #define NETVSC_DEFAULT_RX 10485 /* Max ~16M */ |
53 | 53 | ||
54 | #define LINKCHANGE_INT (2 * HZ) | 54 | #define LINKCHANGE_INT (2 * HZ) |
55 | #define VF_TAKEOVER_INT (HZ / 10) | 55 | #define VF_TAKEOVER_INT (HZ / 10) |
@@ -853,10 +853,7 @@ static int netvsc_set_channels(struct net_device *net, | |||
853 | rndis_filter_device_remove(dev, nvdev); | 853 | rndis_filter_device_remove(dev, nvdev); |
854 | 854 | ||
855 | nvdev = rndis_filter_device_add(dev, &device_info); | 855 | nvdev = rndis_filter_device_add(dev, &device_info); |
856 | if (!IS_ERR(nvdev)) { | 856 | if (IS_ERR(nvdev)) { |
857 | netif_set_real_num_tx_queues(net, nvdev->num_chn); | ||
858 | netif_set_real_num_rx_queues(net, nvdev->num_chn); | ||
859 | } else { | ||
860 | ret = PTR_ERR(nvdev); | 857 | ret = PTR_ERR(nvdev); |
861 | device_info.num_chn = orig; | 858 | device_info.num_chn = orig; |
862 | nvdev = rndis_filter_device_add(dev, &device_info); | 859 | nvdev = rndis_filter_device_add(dev, &device_info); |
@@ -1954,9 +1951,6 @@ static int netvsc_probe(struct hv_device *dev, | |||
1954 | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; | 1951 | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; |
1955 | net->vlan_features = net->features; | 1952 | net->vlan_features = net->features; |
1956 | 1953 | ||
1957 | netif_set_real_num_tx_queues(net, nvdev->num_chn); | ||
1958 | netif_set_real_num_rx_queues(net, nvdev->num_chn); | ||
1959 | |||
1960 | netdev_lockdep_set_classes(net); | 1954 | netdev_lockdep_set_classes(net); |
1961 | 1955 | ||
1962 | /* MTU range: 68 - 1500 or 65521 */ | 1956 | /* MTU range: 68 - 1500 or 65521 */ |
@@ -2012,9 +2006,10 @@ static int netvsc_remove(struct hv_device *dev) | |||
2012 | if (vf_netdev) | 2006 | if (vf_netdev) |
2013 | netvsc_unregister_vf(vf_netdev); | 2007 | netvsc_unregister_vf(vf_netdev); |
2014 | 2008 | ||
2009 | unregister_netdevice(net); | ||
2010 | |||
2015 | rndis_filter_device_remove(dev, | 2011 | rndis_filter_device_remove(dev, |
2016 | rtnl_dereference(ndev_ctx->nvdev)); | 2012 | rtnl_dereference(ndev_ctx->nvdev)); |
2017 | unregister_netdevice(net); | ||
2018 | rtnl_unlock(); | 2013 | rtnl_unlock(); |
2019 | 2014 | ||
2020 | hv_set_drvdata(dev, NULL); | 2015 | hv_set_drvdata(dev, NULL); |
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 69c40b8fccc3..065b204d8e17 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c | |||
@@ -1039,8 +1039,6 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) | |||
1039 | 1039 | ||
1040 | /* Set the channel before opening.*/ | 1040 | /* Set the channel before opening.*/ |
1041 | nvchan->channel = new_sc; | 1041 | nvchan->channel = new_sc; |
1042 | netif_napi_add(ndev, &nvchan->napi, | ||
1043 | netvsc_poll, NAPI_POLL_WEIGHT); | ||
1044 | 1042 | ||
1045 | ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE, | 1043 | ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE, |
1046 | nvscdev->ring_size * PAGE_SIZE, NULL, 0, | 1044 | nvscdev->ring_size * PAGE_SIZE, NULL, 0, |
@@ -1048,10 +1046,86 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) | |||
1048 | if (ret == 0) | 1046 | if (ret == 0) |
1049 | napi_enable(&nvchan->napi); | 1047 | napi_enable(&nvchan->napi); |
1050 | else | 1048 | else |
1051 | netif_napi_del(&nvchan->napi); | 1049 | netdev_notice(ndev, "sub channel open failed: %d\n", ret); |
1052 | 1050 | ||
1053 | atomic_inc(&nvscdev->open_chn); | 1051 | if (atomic_inc_return(&nvscdev->open_chn) == nvscdev->num_chn) |
1054 | wake_up(&nvscdev->subchan_open); | 1052 | wake_up(&nvscdev->subchan_open); |
1053 | } | ||
1054 | |||
1055 | /* Open sub-channels after completing the handling of the device probe. | ||
1056 | * This breaks overlap of processing the host message for the | ||
1057 | * new primary channel with the initialization of sub-channels. | ||
1058 | */ | ||
1059 | void rndis_set_subchannel(struct work_struct *w) | ||
1060 | { | ||
1061 | struct netvsc_device *nvdev | ||
1062 | = container_of(w, struct netvsc_device, subchan_work); | ||
1063 | struct nvsp_message *init_packet = &nvdev->channel_init_pkt; | ||
1064 | struct net_device_context *ndev_ctx; | ||
1065 | struct rndis_device *rdev; | ||
1066 | struct net_device *ndev; | ||
1067 | struct hv_device *hv_dev; | ||
1068 | int i, ret; | ||
1069 | |||
1070 | if (!rtnl_trylock()) { | ||
1071 | schedule_work(w); | ||
1072 | return; | ||
1073 | } | ||
1074 | |||
1075 | rdev = nvdev->extension; | ||
1076 | if (!rdev) | ||
1077 | goto unlock; /* device was removed */ | ||
1078 | |||
1079 | ndev = rdev->ndev; | ||
1080 | ndev_ctx = netdev_priv(ndev); | ||
1081 | hv_dev = ndev_ctx->device_ctx; | ||
1082 | |||
1083 | memset(init_packet, 0, sizeof(struct nvsp_message)); | ||
1084 | init_packet->hdr.msg_type = NVSP_MSG5_TYPE_SUBCHANNEL; | ||
1085 | init_packet->msg.v5_msg.subchn_req.op = NVSP_SUBCHANNEL_ALLOCATE; | ||
1086 | init_packet->msg.v5_msg.subchn_req.num_subchannels = | ||
1087 | nvdev->num_chn - 1; | ||
1088 | ret = vmbus_sendpacket(hv_dev->channel, init_packet, | ||
1089 | sizeof(struct nvsp_message), | ||
1090 | (unsigned long)init_packet, | ||
1091 | VM_PKT_DATA_INBAND, | ||
1092 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | ||
1093 | if (ret) { | ||
1094 | netdev_err(ndev, "sub channel allocate send failed: %d\n", ret); | ||
1095 | goto failed; | ||
1096 | } | ||
1097 | |||
1098 | wait_for_completion(&nvdev->channel_init_wait); | ||
1099 | if (init_packet->msg.v5_msg.subchn_comp.status != NVSP_STAT_SUCCESS) { | ||
1100 | netdev_err(ndev, "sub channel request failed\n"); | ||
1101 | goto failed; | ||
1102 | } | ||
1103 | |||
1104 | nvdev->num_chn = 1 + | ||
1105 | init_packet->msg.v5_msg.subchn_comp.num_subchannels; | ||
1106 | |||
1107 | /* wait for all sub channels to open */ | ||
1108 | wait_event(nvdev->subchan_open, | ||
1109 | atomic_read(&nvdev->open_chn) == nvdev->num_chn); | ||
1110 | |||
1111 | /* ignore failues from setting rss parameters, still have channels */ | ||
1112 | rndis_filter_set_rss_param(rdev, netvsc_hash_key); | ||
1113 | |||
1114 | netif_set_real_num_tx_queues(ndev, nvdev->num_chn); | ||
1115 | netif_set_real_num_rx_queues(ndev, nvdev->num_chn); | ||
1116 | |||
1117 | rtnl_unlock(); | ||
1118 | return; | ||
1119 | |||
1120 | failed: | ||
1121 | /* fallback to only primary channel */ | ||
1122 | for (i = 1; i < nvdev->num_chn; i++) | ||
1123 | netif_napi_del(&nvdev->chan_table[i].napi); | ||
1124 | |||
1125 | nvdev->max_chn = 1; | ||
1126 | nvdev->num_chn = 1; | ||
1127 | unlock: | ||
1128 | rtnl_unlock(); | ||
1055 | } | 1129 | } |
1056 | 1130 | ||
1057 | struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, | 1131 | struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, |
@@ -1063,7 +1137,6 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, | |||
1063 | struct rndis_device *rndis_device; | 1137 | struct rndis_device *rndis_device; |
1064 | struct ndis_offload hwcaps; | 1138 | struct ndis_offload hwcaps; |
1065 | struct ndis_offload_params offloads; | 1139 | struct ndis_offload_params offloads; |
1066 | struct nvsp_message *init_packet; | ||
1067 | struct ndis_recv_scale_cap rsscap; | 1140 | struct ndis_recv_scale_cap rsscap; |
1068 | u32 rsscap_size = sizeof(struct ndis_recv_scale_cap); | 1141 | u32 rsscap_size = sizeof(struct ndis_recv_scale_cap); |
1069 | unsigned int gso_max_size = GSO_MAX_SIZE; | 1142 | unsigned int gso_max_size = GSO_MAX_SIZE; |
@@ -1215,9 +1288,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, | |||
1215 | net_device->num_chn); | 1288 | net_device->num_chn); |
1216 | 1289 | ||
1217 | atomic_set(&net_device->open_chn, 1); | 1290 | atomic_set(&net_device->open_chn, 1); |
1218 | 1291 | vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open); | |
1219 | if (net_device->num_chn == 1) | ||
1220 | return net_device; | ||
1221 | 1292 | ||
1222 | for (i = 1; i < net_device->num_chn; i++) { | 1293 | for (i = 1; i < net_device->num_chn; i++) { |
1223 | ret = netvsc_alloc_recv_comp_ring(net_device, i); | 1294 | ret = netvsc_alloc_recv_comp_ring(net_device, i); |
@@ -1228,38 +1299,15 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, | |||
1228 | } | 1299 | } |
1229 | } | 1300 | } |
1230 | 1301 | ||
1231 | vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open); | 1302 | for (i = 1; i < net_device->num_chn; i++) |
1303 | netif_napi_add(net, &net_device->chan_table[i].napi, | ||
1304 | netvsc_poll, NAPI_POLL_WEIGHT); | ||
1232 | 1305 | ||
1233 | init_packet = &net_device->channel_init_pkt; | 1306 | if (net_device->num_chn > 1) |
1234 | memset(init_packet, 0, sizeof(struct nvsp_message)); | 1307 | schedule_work(&net_device->subchan_work); |
1235 | init_packet->hdr.msg_type = NVSP_MSG5_TYPE_SUBCHANNEL; | ||
1236 | init_packet->msg.v5_msg.subchn_req.op = NVSP_SUBCHANNEL_ALLOCATE; | ||
1237 | init_packet->msg.v5_msg.subchn_req.num_subchannels = | ||
1238 | net_device->num_chn - 1; | ||
1239 | ret = vmbus_sendpacket(dev->channel, init_packet, | ||
1240 | sizeof(struct nvsp_message), | ||
1241 | (unsigned long)init_packet, | ||
1242 | VM_PKT_DATA_INBAND, | ||
1243 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | ||
1244 | if (ret) | ||
1245 | goto out; | ||
1246 | |||
1247 | wait_for_completion(&net_device->channel_init_wait); | ||
1248 | if (init_packet->msg.v5_msg.subchn_comp.status != NVSP_STAT_SUCCESS) { | ||
1249 | ret = -ENODEV; | ||
1250 | goto out; | ||
1251 | } | ||
1252 | 1308 | ||
1253 | net_device->num_chn = 1 + | ||
1254 | init_packet->msg.v5_msg.subchn_comp.num_subchannels; | ||
1255 | |||
1256 | /* wait for all sub channels to open */ | ||
1257 | wait_event(net_device->subchan_open, | ||
1258 | atomic_read(&net_device->open_chn) == net_device->num_chn); | ||
1259 | |||
1260 | /* ignore failues from setting rss parameters, still have channels */ | ||
1261 | rndis_filter_set_rss_param(rndis_device, netvsc_hash_key); | ||
1262 | out: | 1309 | out: |
1310 | /* if unavailable, just proceed with one queue */ | ||
1263 | if (ret) { | 1311 | if (ret) { |
1264 | net_device->max_chn = 1; | 1312 | net_device->max_chn = 1; |
1265 | net_device->num_chn = 1; | 1313 | net_device->num_chn = 1; |
@@ -1280,10 +1328,10 @@ void rndis_filter_device_remove(struct hv_device *dev, | |||
1280 | /* Halt and release the rndis device */ | 1328 | /* Halt and release the rndis device */ |
1281 | rndis_filter_halt_device(rndis_dev); | 1329 | rndis_filter_halt_device(rndis_dev); |
1282 | 1330 | ||
1283 | kfree(rndis_dev); | ||
1284 | net_dev->extension = NULL; | 1331 | net_dev->extension = NULL; |
1285 | 1332 | ||
1286 | netvsc_device_remove(dev); | 1333 | netvsc_device_remove(dev); |
1334 | kfree(rndis_dev); | ||
1287 | } | 1335 | } |
1288 | 1336 | ||
1289 | int rndis_filter_open(struct netvsc_device *nvdev) | 1337 | int rndis_filter_open(struct netvsc_device *nvdev) |
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 340c13484e5c..309b88acd3d0 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c | |||
@@ -526,7 +526,7 @@ static void smsc95xx_set_multicast(struct net_device *netdev) | |||
526 | static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex, | 526 | static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex, |
527 | u16 lcladv, u16 rmtadv) | 527 | u16 lcladv, u16 rmtadv) |
528 | { | 528 | { |
529 | u32 flow, afc_cfg = 0; | 529 | u32 flow = 0, afc_cfg; |
530 | 530 | ||
531 | int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg); | 531 | int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg); |
532 | if (ret < 0) | 532 | if (ret < 0) |
@@ -537,20 +537,19 @@ static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex, | |||
537 | 537 | ||
538 | if (cap & FLOW_CTRL_RX) | 538 | if (cap & FLOW_CTRL_RX) |
539 | flow = 0xFFFF0002; | 539 | flow = 0xFFFF0002; |
540 | else | ||
541 | flow = 0; | ||
542 | 540 | ||
543 | if (cap & FLOW_CTRL_TX) | 541 | if (cap & FLOW_CTRL_TX) { |
544 | afc_cfg |= 0xF; | 542 | afc_cfg |= 0xF; |
545 | else | 543 | flow |= 0xFFFF0000; |
544 | } else { | ||
546 | afc_cfg &= ~0xF; | 545 | afc_cfg &= ~0xF; |
546 | } | ||
547 | 547 | ||
548 | netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s\n", | 548 | netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s\n", |
549 | cap & FLOW_CTRL_RX ? "enabled" : "disabled", | 549 | cap & FLOW_CTRL_RX ? "enabled" : "disabled", |
550 | cap & FLOW_CTRL_TX ? "enabled" : "disabled"); | 550 | cap & FLOW_CTRL_TX ? "enabled" : "disabled"); |
551 | } else { | 551 | } else { |
552 | netif_dbg(dev, link, dev->net, "half duplex\n"); | 552 | netif_dbg(dev, link, dev->net, "half duplex\n"); |
553 | flow = 0; | ||
554 | afc_cfg |= 0xF; | 553 | afc_cfg |= 0xF; |
555 | } | 554 | } |
556 | 555 | ||
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 7e19051f3230..9b243e6f3008 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c | |||
@@ -957,12 +957,12 @@ static void vrf_ip6_input_dst(struct sk_buff *skb, struct net_device *vrf_dev, | |||
957 | { | 957 | { |
958 | const struct ipv6hdr *iph = ipv6_hdr(skb); | 958 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
959 | struct flowi6 fl6 = { | 959 | struct flowi6 fl6 = { |
960 | .flowi6_iif = ifindex, | ||
961 | .flowi6_mark = skb->mark, | ||
962 | .flowi6_proto = iph->nexthdr, | ||
960 | .daddr = iph->daddr, | 963 | .daddr = iph->daddr, |
961 | .saddr = iph->saddr, | 964 | .saddr = iph->saddr, |
962 | .flowlabel = ip6_flowinfo(iph), | 965 | .flowlabel = ip6_flowinfo(iph), |
963 | .flowi6_mark = skb->mark, | ||
964 | .flowi6_proto = iph->nexthdr, | ||
965 | .flowi6_iif = ifindex, | ||
966 | }; | 966 | }; |
967 | struct net *net = dev_net(vrf_dev); | 967 | struct net *net = dev_net(vrf_dev); |
968 | struct rt6_info *rt6; | 968 | struct rt6_info *rt6; |