Pull networking fixes from David Miller: 1) Off by one in mt76 airtime calculation, from Dan Carpenter. 2) Fix TLV fragment allocation loop condition in iwlwifi, from Luca Coelho. 3) Don't confirm neigh entries when doing ipsec pmtu updates, from Xu Wang. 4) More checks to make sure we only send TSO packets to lan78xx chips that they can actually handle. From James Hughes. 5) Fix ip_tunnel namespace move, from William Dauchy. 6) Fix unintended packet reordering due to cooperation between listification done by GRO and non-GRO paths. From Maxim Mikityanskiy. 7) Add Jakub Kicincki formally as networking co-maintainer. 8) Info leak in airo ioctls, from Michael Ellerman. 9) IFLA_MTU attribute needs validation during rtnl_create_link(), from Eric Dumazet. 10) Use after free during reload in mlxsw, from Ido Schimmel. 11) Dangling pointers are possible in tp->highest_sack, fix from Eric Dumazet. 12) Missing *pos++ in various networking seq_next handlers, from Vasily Averin. 13) CHELSIO_GET_MEM operation neds CAP_NET_ADMIN check, from Michael Ellerman. * git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (109 commits) firestream: fix memory leaks net: cxgb3_main: Add CAP_NET_ADMIN check to CHELSIO_GET_MEM net: bcmgenet: Use netif_tx_napi_add() for TX NAPI tipc: change maintainer email address net: stmmac: platform: fix probe for ACPI devices net/mlx5e: kTLS, Do not send decrypted-marked SKBs via non-accel path net/mlx5e: kTLS, Remove redundant posts in TX resync flow net/mlx5e: kTLS, Fix corner-case checks in TX resync flow net/mlx5e: Clear VF config when switching modes net/mlx5: DR, use non preemptible call to get the current cpu number net/mlx5: E-Switch, Prevent ingress rate configuration of uplink rep net/mlx5: DR, Enable counter on non-fwd-dest objects net/mlx5: Update the list of the PCI supported devices net/mlx5: Fix lowest FDB pool size net: Fix skb->csum update in inet_proto_csum_replace16(). netfilter: nf_tables: autoload modules from the abort path netfilter: nf_tables: add __nft_chain_type_get() netfilter: nf_tables_offload: fix check the chain offload flag netfilter: conntrack: sctp: use distinct states for new SCTP connections ipv6_route_seq_next should increase position index ...
Unified · Split
| @@ -403,6 +403,19 @@ PROPERTIES · 402 unmodified lines | ||
| 403 | 403 | The settings and programming routines for internal/external |
| 404 | 404 | MDIO are different. Must be included for internal MDIO. |
| 405 | 405 | |
| 406 | +- fsl,erratum-a011043 | |
| 407 | + Usage: optional | |
| 408 | + Value type: <boolean> | |
| 409 | + Definition: Indicates the presence of the A011043 erratum | |
| 410 | + describing that the MDIO_CFG[MDIO_RD_ER] bit may be falsely | |
| 411 | + set when reading internal PCS registers. MDIO reads to | |
| 412 | + internal PCS registers may result in having the | |
| 413 | + MDIO_CFG[MDIO_RD_ER] bit set, even when there is no error and | |
| 414 | + read data (MDIO_DATA[MDIO_DATA]) is correct. | |
| 415 | + Software may get false read error when reading internal | |
| 416 | + PCS registers through MDIO. As a workaround, all internal | |
| 417 | + MDIO accesses should ignore the MDIO_CFG[MDIO_RD_ER] bit. | |
| 418 | + | |
| 406 | 419 | For internal PHY device on internal mdio bus, a PHY node should be created. |
| 407 | 420 | See the definition of the PHY node in booting-without-of.txt for an |
| 408 | 421 | example of how to define a PHY (Internal PHY has no interrupt line). |
| @@ -6197,6 +6197,7 @@ ETHERNET PHY LIBRARY · 6196 unmodified lines | ||
| 6197 | 6197 | M: Andrew Lunn <andrew@lunn.ch> |
| 6198 | 6198 | M: Florian Fainelli <f.fainelli@gmail.com> |
| 6199 | 6199 | M: Heiner Kallweit <hkallweit1@gmail.com> |
| 6200 | +R: Russell King <linux@armlinux.org.uk> | |
| 6200 | 6201 | L: netdev@vger.kernel.org |
| 6201 | 6202 | S: Maintained |
| 6202 | 6203 | F: Documentation/ABI/testing/sysfs-class-net-phydev |
| @@ -8569,7 +8570,7 @@ S: Maintained · 2366 unmodified lines | ||
| 8569 | 8570 | F: drivers/platform/x86/intel-vbtn.c |
| 8570 | 8571 | |
| 8571 | 8572 | INTEL WIRELESS 3945ABG/BG, 4965AGN (iwlegacy) |
| 8572 | −M: Stanislaw Gruszka <sgruszka@redhat.com> | |
| 8573 | +M: Stanislaw Gruszka <stf_xl@wp.pl> | |
| 8573 | 8574 | L: linux-wireless@vger.kernel.org |
| 8574 | 8575 | S: Supported |
| 8575 | 8576 | F: drivers/net/wireless/intel/iwlegacy/ |
| @@ -11499,6 +11500,7 @@ F: drivers/net/dsa/ · 2923 unmodified lines | ||
| 11499 | 11500 | |
| 11500 | 11501 | NETWORKING [GENERAL] |
| 11501 | 11502 | M: "David S. Miller" <davem@davemloft.net> |
| 11503 | +M: Jakub Kicinski <kuba@kernel.org> | |
| 11502 | 11504 | L: netdev@vger.kernel.org |
| 11503 | 11505 | W: http://www.linuxfoundation.org/en/Net |
| 11504 | 11506 | Q: http://patchwork.ozlabs.org/project/netdev/list/ |
| @@ -13820,7 +13822,7 @@ S: Maintained · 2315 unmodified lines | ||
| 13820 | 13822 | F: arch/mips/ralink |
| 13821 | 13823 | |
| 13822 | 13824 | RALINK RT2X00 WIRELESS LAN DRIVER |
| 13823 | −M: Stanislaw Gruszka <sgruszka@redhat.com> | |
| 13825 | +M: Stanislaw Gruszka <stf_xl@wp.pl> | |
| 13824 | 13826 | M: Helmut Schaa <helmut.schaa@googlemail.com> |
| 13825 | 13827 | L: linux-wireless@vger.kernel.org |
| 13826 | 13828 | S: Maintained |
| @@ -16601,7 +16603,7 @@ F: kernel/time/ntp.c · 2774 unmodified lines | ||
| 16601 | 16603 | F: tools/testing/selftests/timers/ |
| 16602 | 16604 | |
| 16603 | 16605 | TIPC NETWORK LAYER |
| 16604 | −M: Jon Maloy <jon.maloy@ericsson.com> | |
| 16606 | +M: Jon Maloy <jmaloy@redhat.com> | |
| 16605 | 16607 | M: Ying Xue <ying.xue@windriver.com> |
| 16606 | 16608 | L: netdev@vger.kernel.org (core kernel code) |
| 16607 | 16609 | L: tipc-discussion@lists.sourceforge.net (user apps, general discussion) |
| @@ -63,6 +63,7 @@ fman@400000 { · 62 unmodified lines | ||
| 63 | 63 | #size-cells = <0>; |
| 64 | 64 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 65 | 65 | reg = <0xe1000 0x1000>; |
| 66 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 66 | 67 | |
| 67 | 68 | pcsphy0: ethernet-phy@0 { |
| 68 | 69 | reg = <0x0>; |
| @@ -60,6 +60,7 @@ fman@400000 { · 59 unmodified lines | ||
| 60 | 60 | #size-cells = <0>; |
| 61 | 61 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 62 | 62 | reg = <0xf1000 0x1000>; |
| 63 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 63 | 64 | |
| 64 | 65 | pcsphy6: ethernet-phy@0 { |
| 65 | 66 | reg = <0x0>; |
| @@ -63,6 +63,7 @@ fman@400000 { · 62 unmodified lines | ||
| 63 | 63 | #size-cells = <0>; |
| 64 | 64 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 65 | 65 | reg = <0xe3000 0x1000>; |
| 66 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 66 | 67 | |
| 67 | 68 | pcsphy1: ethernet-phy@0 { |
| 68 | 69 | reg = <0x0>; |
| @@ -60,6 +60,7 @@ fman@400000 { · 59 unmodified lines | ||
| 60 | 60 | #size-cells = <0>; |
| 61 | 61 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 62 | 62 | reg = <0xf3000 0x1000>; |
| 63 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 63 | 64 | |
| 64 | 65 | pcsphy7: ethernet-phy@0 { |
| 65 | 66 | reg = <0x0>; |
| @@ -59,6 +59,7 @@ fman@400000 { · 58 unmodified lines | ||
| 59 | 59 | #size-cells = <0>; |
| 60 | 60 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 61 | 61 | reg = <0xe1000 0x1000>; |
| 62 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 62 | 63 | |
| 63 | 64 | pcsphy0: ethernet-phy@0 { |
| 64 | 65 | reg = <0x0>; |
| @@ -59,6 +59,7 @@ fman@400000 { · 58 unmodified lines | ||
| 59 | 59 | #size-cells = <0>; |
| 60 | 60 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 61 | 61 | reg = <0xe3000 0x1000>; |
| 62 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 62 | 63 | |
| 63 | 64 | pcsphy1: ethernet-phy@0 { |
| 64 | 65 | reg = <0x0>; |
| @@ -59,6 +59,7 @@ fman@400000 { · 58 unmodified lines | ||
| 59 | 59 | #size-cells = <0>; |
| 60 | 60 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 61 | 61 | reg = <0xe5000 0x1000>; |
| 62 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 62 | 63 | |
| 63 | 64 | pcsphy2: ethernet-phy@0 { |
| 64 | 65 | reg = <0x0>; |
| @@ -59,6 +59,7 @@ fman@400000 { · 58 unmodified lines | ||
| 59 | 59 | #size-cells = <0>; |
| 60 | 60 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 61 | 61 | reg = <0xe7000 0x1000>; |
| 62 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 62 | 63 | |
| 63 | 64 | pcsphy3: ethernet-phy@0 { |
| 64 | 65 | reg = <0x0>; |
| @@ -59,6 +59,7 @@ fman@400000 { · 58 unmodified lines | ||
| 59 | 59 | #size-cells = <0>; |
| 60 | 60 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 61 | 61 | reg = <0xe9000 0x1000>; |
| 62 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 62 | 63 | |
| 63 | 64 | pcsphy4: ethernet-phy@0 { |
| 64 | 65 | reg = <0x0>; |
| @@ -59,6 +59,7 @@ fman@400000 { · 58 unmodified lines | ||
| 59 | 59 | #size-cells = <0>; |
| 60 | 60 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 61 | 61 | reg = <0xeb000 0x1000>; |
| 62 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 62 | 63 | |
| 63 | 64 | pcsphy5: ethernet-phy@0 { |
| 64 | 65 | reg = <0x0>; |
| @@ -60,6 +60,7 @@ fman@500000 { · 59 unmodified lines | ||
| 60 | 60 | #size-cells = <0>; |
| 61 | 61 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 62 | 62 | reg = <0xf1000 0x1000>; |
| 63 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 63 | 64 | |
| 64 | 65 | pcsphy14: ethernet-phy@0 { |
| 65 | 66 | reg = <0x0>; |
| @@ -60,6 +60,7 @@ fman@500000 { · 59 unmodified lines | ||
| 60 | 60 | #size-cells = <0>; |
| 61 | 61 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 62 | 62 | reg = <0xf3000 0x1000>; |
| 63 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 63 | 64 | |
| 64 | 65 | pcsphy15: ethernet-phy@0 { |
| 65 | 66 | reg = <0x0>; |
| @@ -59,6 +59,7 @@ fman@500000 { · 58 unmodified lines | ||
| 59 | 59 | #size-cells = <0>; |
| 60 | 60 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 61 | 61 | reg = <0xe1000 0x1000>; |
| 62 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 62 | 63 | |
| 63 | 64 | pcsphy8: ethernet-phy@0 { |
| 64 | 65 | reg = <0x0>; |
| @@ -59,6 +59,7 @@ fman@500000 { · 58 unmodified lines | ||
| 59 | 59 | #size-cells = <0>; |
| 60 | 60 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 61 | 61 | reg = <0xe3000 0x1000>; |
| 62 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 62 | 63 | |
| 63 | 64 | pcsphy9: ethernet-phy@0 { |
| 64 | 65 | reg = <0x0>; |
| @@ -59,6 +59,7 @@ fman@500000 { · 58 unmodified lines | ||
| 59 | 59 | #size-cells = <0>; |
| 60 | 60 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 61 | 61 | reg = <0xe5000 0x1000>; |
| 62 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 62 | 63 | |
| 63 | 64 | pcsphy10: ethernet-phy@0 { |
| 64 | 65 | reg = <0x0>; |
| @@ -59,6 +59,7 @@ fman@500000 { · 58 unmodified lines | ||
| 59 | 59 | #size-cells = <0>; |
| 60 | 60 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 61 | 61 | reg = <0xe7000 0x1000>; |
| 62 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 62 | 63 | |
| 63 | 64 | pcsphy11: ethernet-phy@0 { |
| 64 | 65 | reg = <0x0>; |
| @@ -59,6 +59,7 @@ fman@500000 { · 58 unmodified lines | ||
| 59 | 59 | #size-cells = <0>; |
| 60 | 60 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 61 | 61 | reg = <0xe9000 0x1000>; |
| 62 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 62 | 63 | |
| 63 | 64 | pcsphy12: ethernet-phy@0 { |
| 64 | 65 | reg = <0x0>; |
| @@ -59,6 +59,7 @@ fman@500000 { · 58 unmodified lines | ||
| 59 | 59 | #size-cells = <0>; |
| 60 | 60 | compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; |
| 61 | 61 | reg = <0xeb000 0x1000>; |
| 62 | + fsl,erratum-a011043; /* must ignore read errors */ | |
| 62 | 63 | |
| 63 | 64 | pcsphy13: ethernet-phy@0 { |
| 64 | 65 | reg = <0x0>; |
| @@ -912,6 +912,7 @@ static int fs_open(struct atm_vcc *atm_vcc) · 911 unmodified lines | ||
| 912 | 912 | } |
| 913 | 913 | if (!to) { |
| 914 | 914 | printk ("No more free channels for FS50..\n"); |
| 915 | + kfree(vcc); | |
| 915 | 916 | return -EBUSY; |
| 916 | 917 | } |
| 917 | 918 | vcc->channo = dev->channo; |
| @@ -922,6 +923,7 @@ static int fs_open(struct atm_vcc *atm_vcc) · 4 unmodified lines | ||
| 922 | 923 | if (((DO_DIRECTION(rxtp) && dev->atm_vccs[vcc->channo])) || |
| 923 | 924 | ( DO_DIRECTION(txtp) && test_bit (vcc->channo, dev->tx_inuse))) { |
| 924 | 925 | printk ("Channel is in use for FS155.\n"); |
| 926 | + kfree(vcc); | |
| 925 | 927 | return -EBUSY; |
| 926 | 928 | } |
| 927 | 929 | } |
| @@ -935,6 +937,7 @@ static int fs_open(struct atm_vcc *atm_vcc) · 7 unmodified lines | ||
| 935 | 937 | tc, sizeof (struct fs_transmit_config)); |
| 936 | 938 | if (!tc) { |
| 937 | 939 | fs_dprintk (FS_DEBUG_OPEN, "fs: can't alloc transmit_config.\n"); |
| 940 | + kfree(vcc); | |
| 938 | 941 | return -ENOMEM; |
| 939 | 942 | } |
| 940 | 943 | |
| @@ -344,9 +344,16 @@ static void slcan_transmit(struct work_struct *work) · 343 unmodified lines | ||
| 344 | 344 | */ |
| 345 | 345 | static void slcan_write_wakeup(struct tty_struct *tty) |
| 346 | 346 | { |
| 347 | − struct slcan *sl = tty->disc_data; | |
| 347 | + struct slcan *sl; | |
| 348 | + | |
| 349 | + rcu_read_lock(); | |
| 350 | + sl = rcu_dereference(tty->disc_data); | |
| 351 | + if (!sl) | |
| 352 | + goto out; | |
| 348 | 353 | |
| 349 | 354 | schedule_work(&sl->tx_work); |
| 355 | +out: | |
| 356 | + rcu_read_unlock(); | |
| 350 | 357 | } |
| 351 | 358 | |
| 352 | 359 | /* Send a can_frame to a TTY queue. */ |
| @@ -644,10 +651,11 @@ static void slcan_close(struct tty_struct *tty) · 291 unmodified lines | ||
| 644 | 651 | return; |
| 645 | 652 | |
| 646 | 653 | spin_lock_bh(&sl->lock); |
| 647 | − tty->disc_data = NULL; | |
| 654 | + rcu_assign_pointer(tty->disc_data, NULL); | |
| 648 | 655 | sl->tty = NULL; |
| 649 | 656 | spin_unlock_bh(&sl->lock); |
| 650 | 657 | |
| 658 | + synchronize_rcu(); | |
| 651 | 659 | flush_work(&sl->tx_work); |
| 652 | 660 | |
| 653 | 661 | /* Flush network side */ |
| @@ -2164,8 +2164,8 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv, · 2163 unmodified lines | ||
| 2164 | 2164 | DMA_END_ADDR); |
| 2165 | 2165 | |
| 2166 | 2166 | /* Initialize Tx NAPI */ |
| 2167 | − netif_napi_add(priv->dev, &ring->napi, bcmgenet_tx_poll, | |
| 2168 | − NAPI_POLL_WEIGHT); | |
| 2167 | + netif_tx_napi_add(priv->dev, &ring->napi, bcmgenet_tx_poll, | |
| 2168 | + NAPI_POLL_WEIGHT); | |
| 2169 | 2169 | } |
| 2170 | 2170 | |
| 2171 | 2171 | /* Initialize a RDMA ring */ |
| @@ -2448,6 +2448,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) · 2447 unmodified lines | ||
| 2448 | 2448 | |
| 2449 | 2449 | if (!is_offload(adapter)) |
| 2450 | 2450 | return -EOPNOTSUPP; |
| 2451 | + if (!capable(CAP_NET_ADMIN)) | |
| 2452 | + return -EPERM; | |
| 2451 | 2453 | if (!(adapter->flags & FULL_INIT_DONE)) |
| 2452 | 2454 | return -EIO; /* need the memory controllers */ |
| 2453 | 2455 | if (copy_from_user(&t, useraddr, sizeof(t))) |
| @@ -70,8 +70,7 @@ static void *seq_tab_start(struct seq_file *seq, loff_t *pos) · 69 unmodified lines | ||
| 70 | 70 | static void *seq_tab_next(struct seq_file *seq, void *v, loff_t *pos) |
| 71 | 71 | { |
| 72 | 72 | v = seq_tab_get_idx(seq->private, *pos + 1); |
| 73 | − if (v) | |
| 74 | − ++*pos; | |
| 73 | + ++(*pos); | |
| 75 | 74 | return v; |
| 76 | 75 | } |
| 77 | 76 | |
| @@ -678,8 +678,7 @@ static void *l2t_seq_start(struct seq_file *seq, loff_t *pos) · 677 unmodified lines | ||
| 678 | 678 | static void *l2t_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
| 679 | 679 | { |
| 680 | 680 | v = l2t_get_idx(seq, *pos); |
| 681 | − if (v) | |
| 682 | − ++*pos; | |
| 681 | + ++(*pos); | |
| 683 | 682 | return v; |
| 684 | 683 | } |
| 685 | 684 | |
| @@ -110,7 +110,7 @@ do { \ · 109 unmodified lines | ||
| 110 | 110 | /* Interface Mode Register (IF_MODE) */ |
| 111 | 111 | |
| 112 | 112 | #define IF_MODE_MASK 0x00000003 /* 30-31 Mask on i/f mode bits */ |
| 113 | −#define IF_MODE_XGMII 0x00000000 /* 30-31 XGMII (10G) interface */ | |
| 113 | +#define IF_MODE_10G 0x00000000 /* 30-31 10G interface */ | |
| 114 | 114 | #define IF_MODE_GMII 0x00000002 /* 30-31 GMII (1G) interface */ |
| 115 | 115 | #define IF_MODE_RGMII 0x00000004 |
| 116 | 116 | #define IF_MODE_RGMII_AUTO 0x00008000 |
| @@ -440,7 +440,7 @@ static int init(struct memac_regs __iomem *regs, struct memac_cfg *cfg, · 323 unmodified lines | ||
| 440 | 440 | tmp = 0; |
| 441 | 441 | switch (phy_if) { |
| 442 | 442 | case PHY_INTERFACE_MODE_XGMII: |
| 443 | − tmp |= IF_MODE_XGMII; | |
| 443 | + tmp |= IF_MODE_10G; | |
| 444 | 444 | break; |
| 445 | 445 | default: |
| 446 | 446 | tmp |= IF_MODE_GMII; |
| @@ -49,6 +49,7 @@ struct tgec_mdio_controller { · 48 unmodified lines | ||
| 49 | 49 | struct mdio_fsl_priv { |
| 50 | 50 | struct tgec_mdio_controller __iomem *mdio_base; |
| 51 | 51 | bool is_little_endian; |
| 52 | + bool has_a011043; | |
| 52 | 53 | }; |
| 53 | 54 | |
| 54 | 55 | static u32 xgmac_read32(void __iomem *regs, |
| @@ -226,7 +227,8 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum) · 171 unmodified lines | ||
| 226 | 227 | return ret; |
| 227 | 228 | |
| 228 | 229 | /* Return all Fs if nothing was there */ |
| 229 | − if (xgmac_read32(®s->mdio_stat, endian) & MDIO_STAT_RD_ER) { | |
| 230 | + if ((xgmac_read32(®s->mdio_stat, endian) & MDIO_STAT_RD_ER) && | |
| 231 | + !priv->has_a011043) { | |
| 230 | 232 | dev_err(&bus->dev, |
| 231 | 233 | "Error while reading PHY%d reg at %d.%hhu\n", |
| 232 | 234 | phy_id, dev_addr, regnum); |
| @@ -274,6 +276,9 @@ static int xgmac_mdio_probe(struct platform_device *pdev) · 41 unmodified lines | ||
| 274 | 276 | priv->is_little_endian = of_property_read_bool(pdev->dev.of_node, |
| 275 | 277 | "little-endian"); |
| 276 | 278 | |
| 279 | + priv->has_a011043 = of_property_read_bool(pdev->dev.of_node, | |
| 280 | + "fsl,erratum-a011043"); | |
| 281 | + | |
| 277 | 282 | ret = of_mdiobus_register(bus, np); |
| 278 | 283 | if (ret) { |
| 279 | 284 | dev_err(&pdev->dev, "cannot register MDIO bus\n"); |
| @@ -1113,7 +1113,7 @@ i40e_status i40e_read_pba_string(struct i40e_hw *hw, u8 *pba_num, · 1112 unmodified lines | ||
| 1113 | 1113 | */ |
| 1114 | 1114 | pba_size--; |
| 1115 | 1115 | if (pba_num_size < (((u32)pba_size * 2) + 1)) { |
| 1116 | − hw_dbg(hw, "Buffer to small for PBA data.\n"); | |
| 1116 | + hw_dbg(hw, "Buffer too small for PBA data.\n"); | |
| 1117 | 1117 | return I40E_ERR_PARAM; |
| 1118 | 1118 | } |
| 1119 | 1119 | |
| @@ -180,7 +180,7 @@ mlx5e_ktls_tx_post_param_wqes(struct mlx5e_txqsq *sq, · 179 unmodified lines | ||
| 180 | 180 | |
| 181 | 181 | struct tx_sync_info { |
| 182 | 182 | u64 rcd_sn; |
| 183 | − s32 sync_len; | |
| 183 | + u32 sync_len; | |
| 184 | 184 | int nr_frags; |
| 185 | 185 | skb_frag_t frags[MAX_SKB_FRAGS]; |
| 186 | 186 | }; |
| @@ -193,13 +193,14 @@ enum mlx5e_ktls_sync_retval { · 6 unmodified lines | ||
| 193 | 193 | |
| 194 | 194 | static enum mlx5e_ktls_sync_retval |
| 195 | 195 | tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx, |
| 196 | − u32 tcp_seq, struct tx_sync_info *info) | |
| 196 | + u32 tcp_seq, int datalen, struct tx_sync_info *info) | |
| 197 | 197 | { |
| 198 | 198 | struct tls_offload_context_tx *tx_ctx = priv_tx->tx_ctx; |
| 199 | 199 | enum mlx5e_ktls_sync_retval ret = MLX5E_KTLS_SYNC_DONE; |
| 200 | 200 | struct tls_record_info *record; |
| 201 | 201 | int remaining, i = 0; |
| 202 | 202 | unsigned long flags; |
| 203 | + bool ends_before; | |
| 203 | 204 | |
| 204 | 205 | spin_lock_irqsave(&tx_ctx->lock, flags); |
| 205 | 206 | record = tls_get_record(tx_ctx, tcp_seq, &info->rcd_sn); |
| @@ -209,9 +210,21 @@ tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx, · 3 unmodified lines | ||
| 209 | 210 | goto out; |
| 210 | 211 | } |
| 211 | 212 | |
| 212 | − if (unlikely(tcp_seq < tls_record_start_seq(record))) { | |
| 213 | − ret = tls_record_is_start_marker(record) ? | |
| 214 | − MLX5E_KTLS_SYNC_SKIP_NO_DATA : MLX5E_KTLS_SYNC_FAIL; | |
| 213 | + /* There are the following cases: | |
| 214 | + * 1. packet ends before start marker: bypass offload. | |
| 215 | + * 2. packet starts before start marker and ends after it: drop, | |
| 216 | + * not supported, breaks contract with kernel. | |
| 217 | + * 3. packet ends before tls record info starts: drop, | |
| 218 | + * this packet was already acknowledged and its record info | |
| 219 | + * was released. | |
| 220 | + */ | |
| 221 | + ends_before = before(tcp_seq + datalen, tls_record_start_seq(record)); | |
| 222 | + | |
| 223 | + if (unlikely(tls_record_is_start_marker(record))) { | |
| 224 | + ret = ends_before ? MLX5E_KTLS_SYNC_SKIP_NO_DATA : MLX5E_KTLS_SYNC_FAIL; | |
| 225 | + goto out; | |
| 226 | + } else if (ends_before) { | |
| 227 | + ret = MLX5E_KTLS_SYNC_FAIL; | |
| 215 | 228 | goto out; |
| 216 | 229 | } |
| 217 | 230 | |
| @@ -337,7 +350,7 @@ mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx, · 119 unmodified lines | ||
| 337 | 350 | u8 num_wqebbs; |
| 338 | 351 | int i = 0; |
| 339 | 352 | |
| 340 | − ret = tx_sync_info_get(priv_tx, seq, &info); | |
| 353 | + ret = tx_sync_info_get(priv_tx, seq, datalen, &info); | |
| 341 | 354 | if (unlikely(ret != MLX5E_KTLS_SYNC_DONE)) { |
| 342 | 355 | if (ret == MLX5E_KTLS_SYNC_SKIP_NO_DATA) { |
| 343 | 356 | stats->tls_skip_no_sync_data++; |
| @@ -351,14 +364,6 @@ mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx, · 7 unmodified lines | ||
| 351 | 364 | goto err_out; |
| 352 | 365 | } |
| 353 | 366 | |
| 354 | − if (unlikely(info.sync_len < 0)) { | |
| 355 | − if (likely(datalen <= -info.sync_len)) | |
| 356 | − return MLX5E_KTLS_SYNC_DONE; | |
| 357 | − | |
| 358 | − stats->tls_drop_bypass_req++; | |
| 359 | − goto err_out; | |
| 360 | − } | |
| 361 | − | |
| 362 | 367 | stats->tls_ooo++; |
| 363 | 368 | |
| 364 | 369 | tx_post_resync_params(sq, priv_tx, info.rcd_sn); |
| @@ -378,8 +383,6 @@ mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx, · 13 unmodified lines | ||
| 378 | 383 | if (unlikely(contig_wqebbs_room < num_wqebbs)) |
| 379 | 384 | mlx5e_fill_sq_frag_edge(sq, wq, pi, contig_wqebbs_room); |
| 380 | 385 | |
| 381 | − tx_post_resync_params(sq, priv_tx, info.rcd_sn); | |
| 382 | − | |
| 383 | 386 | for (; i < info.nr_frags; i++) { |
| 384 | 387 | unsigned int orig_fsz, frag_offset = 0, n = 0; |
| 385 | 388 | skb_frag_t *f = &info.frags[i]; |
| @@ -455,12 +458,18 @@ struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev, · 69 unmodified lines | ||
| 455 | 458 | enum mlx5e_ktls_sync_retval ret = |
| 456 | 459 | mlx5e_ktls_tx_handle_ooo(priv_tx, sq, datalen, seq); |
| 457 | 460 | |
| 458 | − if (likely(ret == MLX5E_KTLS_SYNC_DONE)) | |
| 461 | + switch (ret) { | |
| 462 | + case MLX5E_KTLS_SYNC_DONE: | |
| 459 | 463 | *wqe = mlx5e_sq_fetch_wqe(sq, sizeof(**wqe), pi); |
| 460 | − else if (ret == MLX5E_KTLS_SYNC_FAIL) | |
| 464 | + break; | |
| 465 | + case MLX5E_KTLS_SYNC_SKIP_NO_DATA: | |
| 466 | + if (likely(!skb->decrypted)) | |
| 467 | + goto out; | |
| 468 | + WARN_ON_ONCE(1); | |
| 469 | + /* fall-through */ | |
| 470 | + default: /* MLX5E_KTLS_SYNC_FAIL */ | |
| 461 | 471 | goto err_out; |
| 462 | − else /* ret == MLX5E_KTLS_SYNC_SKIP_NO_DATA */ | |
| 463 | − goto out; | |
| 472 | + } | |
| 464 | 473 | } |
| 465 | 474 | |
| 466 | 475 | priv_tx->expected_seq = seq + datalen; |
| @@ -4036,6 +4036,13 @@ static int apply_police_params(struct mlx5e_priv *priv, u32 rate, · 4035 unmodified lines | ||
| 4036 | 4036 | u32 rate_mbps; |
| 4037 | 4037 | int err; |
| 4038 | 4038 | |
| 4039 | + vport_num = rpriv->rep->vport; | |
| 4040 | + if (vport_num >= MLX5_VPORT_ECPF) { | |
| 4041 | + NL_SET_ERR_MSG_MOD(extack, | |
| 4042 | + "Ingress rate limit is supported only for Eswitch ports connected to VFs"); | |
| 4043 | + return -EOPNOTSUPP; | |
| 4044 | + } | |
| 4045 | + | |
| 4039 | 4046 | esw = priv->mdev->priv.eswitch; |
| 4040 | 4047 | /* rate is given in bytes/sec. |
| 4041 | 4048 | * First convert to bits/sec and then round to the nearest mbit/secs. |
| @@ -4044,8 +4051,6 @@ static int apply_police_params(struct mlx5e_priv *priv, u32 rate, · 2 unmodified lines | ||
| 4044 | 4051 | * 1 mbit/sec. |
| 4045 | 4052 | */ |
| 4046 | 4053 | rate_mbps = rate ? max_t(u32, (rate * 8 + 500000) / 1000000, 1) : 0; |
| 4047 | − vport_num = rpriv->rep->vport; | |
| 4048 | − | |
| 4049 | 4054 | err = mlx5_esw_modify_vport_rate(esw, vport_num, rate_mbps); |
| 4050 | 4055 | if (err) |
| 4051 | 4056 | NL_SET_ERR_MSG_MOD(extack, "failed applying action to hardware"); |
| @@ -1928,8 +1928,10 @@ static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw) · 1927 unmodified lines | ||
| 1928 | 1928 | struct mlx5_vport *vport; |
| 1929 | 1929 | int i; |
| 1930 | 1930 | |
| 1931 | − mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) | |
| 1931 | + mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) { | |
| 1932 | 1932 | memset(&vport->info, 0, sizeof(vport->info)); |
| 1933 | + vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; | |
| 1934 | + } | |
| 1933 | 1935 | } |
| 1934 | 1936 | |
| 1935 | 1937 | /* Public E-Switch API */ |
| @@ -866,7 +866,7 @@ out: · 865 unmodified lines | ||
| 866 | 866 | */ |
| 867 | 867 | #define ESW_SIZE (16 * 1024 * 1024) |
| 868 | 868 | const unsigned int ESW_POOLS[4] = { 4 * 1024 * 1024, 1 * 1024 * 1024, |
| 869 | − 64 * 1024, 4 * 1024 }; | |
| 869 | + 64 * 1024, 128 }; | |
| 870 | 870 | |
| 871 | 871 | static int |
| 872 | 872 | get_sz_from_pool(struct mlx5_eswitch *esw) |
| @@ -1377,7 +1377,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw, · 504 unmodified lines | ||
| 1377 | 1377 | return -EINVAL; |
| 1378 | 1378 | } |
| 1379 | 1379 | |
| 1380 | − mlx5_eswitch_disable(esw, false); | |
| 1380 | + mlx5_eswitch_disable(esw, true); | |
| 1381 | 1381 | mlx5_eswitch_update_num_of_vfs(esw, esw->dev->priv.sriov.num_vfs); |
| 1382 | 1382 | err = mlx5_eswitch_enable(esw, MLX5_ESWITCH_OFFLOADS); |
| 1383 | 1383 | if (err) { |
| @@ -2220,7 +2220,8 @@ int mlx5_esw_funcs_changed_handler(struct notifier_block *nb, unsigned long type · 836 unmodified lines | ||
| 2220 | 2220 | |
| 2221 | 2221 | int esw_offloads_enable(struct mlx5_eswitch *esw) |
| 2222 | 2222 | { |
| 2223 | − int err; | |
| 2223 | + struct mlx5_vport *vport; | |
| 2224 | + int err, i; | |
| 2224 | 2225 | |
| 2225 | 2226 | if (MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat) && |
| 2226 | 2227 | MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, decap)) |
| @@ -2237,6 +2238,10 @@ int esw_offloads_enable(struct mlx5_eswitch *esw) · 10 unmodified lines | ||
| 2237 | 2238 | if (err) |
| 2238 | 2239 | goto err_vport_metadata; |
| 2239 | 2240 | |
| 2241 | + /* Representor will control the vport link state */ | |
| 2242 | + mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) | |
| 2243 | + vport->info.link_state = MLX5_VPORT_ADMIN_STATE_DOWN; | |
| 2244 | + | |
| 2240 | 2245 | err = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_VPORT_UC_ADDR_CHANGE); |
| 2241 | 2246 | if (err) |
| 2242 | 2247 | goto err_vports; |
| @@ -2266,7 +2271,7 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw, · 23 unmodified lines | ||
| 2266 | 2271 | { |
| 2267 | 2272 | int err, err1; |
| 2268 | 2273 | |
| 2269 | − mlx5_eswitch_disable(esw, false); | |
| 2274 | + mlx5_eswitch_disable(esw, true); | |
| 2270 | 2275 | err = mlx5_eswitch_enable(esw, MLX5_ESWITCH_LEGACY); |
| 2271 | 2276 | if (err) { |
| 2272 | 2277 | NL_SET_ERR_MSG_MOD(extack, "Failed setting eswitch to legacy"); |
| @@ -1563,6 +1563,7 @@ static const struct pci_device_id mlx5_core_pci_table[] = { · 1562 unmodified lines | ||
| 1563 | 1563 | { PCI_VDEVICE(MELLANOX, 0x101d) }, /* ConnectX-6 Dx */ |
| 1564 | 1564 | { PCI_VDEVICE(MELLANOX, 0x101e), MLX5_PCI_DEV_IS_VF}, /* ConnectX Family mlx5Gen Virtual Function */ |
| 1565 | 1565 | { PCI_VDEVICE(MELLANOX, 0x101f) }, /* ConnectX-6 LX */ |
| 1566 | + { PCI_VDEVICE(MELLANOX, 0x1021) }, /* ConnectX-7 */ | |
| 1566 | 1567 | { PCI_VDEVICE(MELLANOX, 0xa2d2) }, /* BlueField integrated ConnectX-5 network controller */ |
| 1567 | 1568 | { PCI_VDEVICE(MELLANOX, 0xa2d3), MLX5_PCI_DEV_IS_VF}, /* BlueField integrated ConnectX-5 network controller VF */ |
| 1568 | 1569 | { PCI_VDEVICE(MELLANOX, 0xa2d6) }, /* BlueField-2 integrated ConnectX-6 Dx network controller */ |
| @@ -1,6 +1,7 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB |
| 2 | 2 | /* Copyright (c) 2019 Mellanox Technologies. */ |
| 3 | 3 | |
| 4 | +#include <linux/smp.h> | |
| 4 | 5 | #include "dr_types.h" |
| 5 | 6 | |
| 6 | 7 | #define QUEUE_SIZE 128 |
| @@ -729,7 +730,7 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev, · 722 unmodified lines | ||
| 729 | 730 | if (!in) |
| 730 | 731 | goto err_cqwq; |
| 731 | 732 | |
| 732 | − vector = smp_processor_id() % mlx5_comp_vectors_count(mdev); | |
| 733 | + vector = raw_smp_processor_id() % mlx5_comp_vectors_count(mdev); | |
| 733 | 734 | err = mlx5_vector2eqn(mdev, vector, &eqn, &irqn); |
| 734 | 735 | if (err) { |
| 735 | 736 | kvfree(in); |
| @@ -352,26 +352,16 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, · 351 unmodified lines | ||
| 352 | 352 | if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { |
| 353 | 353 | list_for_each_entry(dst, &fte->node.children, node.list) { |
| 354 | 354 | enum mlx5_flow_destination_type type = dst->dest_attr.type; |
| 355 | − u32 id; | |
| 356 | 355 | |
| 357 | 356 | if (num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX) { |
| 358 | 357 | err = -ENOSPC; |
| 359 | 358 | goto free_actions; |
| 360 | 359 | } |
| 361 | 360 | |
| 362 | − switch (type) { | |
| 363 | − case MLX5_FLOW_DESTINATION_TYPE_COUNTER: | |
| 364 | − id = dst->dest_attr.counter_id; | |
| 361 | + if (type == MLX5_FLOW_DESTINATION_TYPE_COUNTER) | |
| 362 | + continue; | |
| 365 | 363 | |
| 366 | − tmp_action = | |
| 367 | − mlx5dr_action_create_flow_counter(id); | |
| 368 | − if (!tmp_action) { | |
| 369 | − err = -ENOMEM; | |
| 370 | − goto free_actions; | |
| 371 | − } | |
| 372 | − fs_dr_actions[fs_dr_num_actions++] = tmp_action; | |
| 373 | − actions[num_actions++] = tmp_action; | |
| 374 | − break; | |
| 364 | + switch (type) { | |
| 375 | 365 | case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE: |
| 376 | 366 | tmp_action = create_ft_action(dev, dst); |
| 377 | 367 | if (!tmp_action) { |
| @@ -397,6 +387,32 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, · 19 unmodified lines | ||
| 397 | 387 | } |
| 398 | 388 | } |
| 399 | 389 | |
| 390 | + if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { | |
| 391 | + list_for_each_entry(dst, &fte->node.children, node.list) { | |
| 392 | + u32 id; | |
| 393 | + | |
| 394 | + if (dst->dest_attr.type != | |
| 395 | + MLX5_FLOW_DESTINATION_TYPE_COUNTER) | |
| 396 | + continue; | |
| 397 | + | |
| 398 | + if (num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX) { | |
| 399 | + err = -ENOSPC; | |
| 400 | + goto free_actions; | |
| 401 | + } | |
| 402 | + | |
| 403 | + id = dst->dest_attr.counter_id; | |
| 404 | + tmp_action = | |
| 405 | + mlx5dr_action_create_flow_counter(id); | |
| 406 | + if (!tmp_action) { | |
| 407 | + err = -ENOMEM; | |
| 408 | + goto free_actions; | |
| 409 | + } | |
| 410 | + | |
| 411 | + fs_dr_actions[fs_dr_num_actions++] = tmp_action; | |
| 412 | + actions[num_actions++] = tmp_action; | |
| 413 | + } | |
| 414 | + } | |
| 415 | + | |
| 400 | 416 | params.match_sz = match_sz; |
| 401 | 417 | params.match_buf = (u64 *)fte->val; |
| 402 | 418 | |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <linux/string.h> |
| 9 | 9 | #include <linux/rhashtable.h> |
| 10 | 10 | #include <linux/netdevice.h> |
| 11 | +#include <linux/mutex.h> | |
| 11 | 12 | #include <net/net_namespace.h> |
| 12 | 13 | #include <net/tc_act/tc_vlan.h> |
| 13 | 14 | |
| @@ -25,6 +26,7 @@ struct mlxsw_sp_acl { · 11 unmodified lines | ||
| 25 | 26 | struct mlxsw_sp_fid *dummy_fid; |
| 26 | 27 | struct rhashtable ruleset_ht; |
| 27 | 28 | struct list_head rules; |
| 29 | + struct mutex rules_lock; /* Protects rules list */ | |
| 28 | 30 | struct { |
| 29 | 31 | struct delayed_work dw; |
| 30 | 32 | unsigned long interval; /* ms */ |
| @@ -701,7 +703,9 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp, · 670 unmodified lines | ||
| 701 | 703 | goto err_ruleset_block_bind; |
| 702 | 704 | } |
| 703 | 705 | |
| 706 | + mutex_lock(&mlxsw_sp->acl->rules_lock); | |
| 704 | 707 | list_add_tail(&rule->list, &mlxsw_sp->acl->rules); |
| 708 | + mutex_unlock(&mlxsw_sp->acl->rules_lock); | |
| 705 | 709 | block->rule_count++; |
| 706 | 710 | block->egress_blocker_rule_count += rule->rulei->egress_bind_blocker; |
| 707 | 711 | return 0; |
| @@ -723,7 +727,9 @@ void mlxsw_sp_acl_rule_del(struct mlxsw_sp *mlxsw_sp, · 15 unmodified lines | ||
| 723 | 727 | |
| 724 | 728 | block->egress_blocker_rule_count -= rule->rulei->egress_bind_blocker; |
| 725 | 729 | ruleset->ht_key.block->rule_count--; |
| 730 | + mutex_lock(&mlxsw_sp->acl->rules_lock); | |
| 726 | 731 | list_del(&rule->list); |
| 732 | + mutex_unlock(&mlxsw_sp->acl->rules_lock); | |
| 727 | 733 | if (!ruleset->ht_key.chain_index && |
| 728 | 734 | mlxsw_sp_acl_ruleset_is_singular(ruleset)) |
| 729 | 735 | mlxsw_sp_acl_ruleset_block_unbind(mlxsw_sp, ruleset, |
| @@ -783,19 +789,18 @@ static int mlxsw_sp_acl_rules_activity_update(struct mlxsw_sp_acl *acl) · 53 unmodified lines | ||
| 783 | 789 | struct mlxsw_sp_acl_rule *rule; |
| 784 | 790 | int err; |
| 785 | 791 | |
| 786 | − /* Protect internal structures from changes */ | |
| 787 | − rtnl_lock(); | |
| 792 | + mutex_lock(&acl->rules_lock); | |
| 788 | 793 | list_for_each_entry(rule, &acl->rules, list) { |
| 789 | 794 | err = mlxsw_sp_acl_rule_activity_update(acl->mlxsw_sp, |
| 790 | 795 | rule); |
| 791 | 796 | if (err) |
| 792 | 797 | goto err_rule_update; |
| 793 | 798 | } |
| 794 | − rtnl_unlock(); | |
| 799 | + mutex_unlock(&acl->rules_lock); | |
| 795 | 800 | return 0; |
| 796 | 801 | |
| 797 | 802 | err_rule_update: |
| 798 | − rtnl_unlock(); | |
| 803 | + mutex_unlock(&acl->rules_lock); | |
| 799 | 804 | return err; |
| 800 | 805 | } |
| 801 | 806 | |
| @@ -880,6 +885,7 @@ int mlxsw_sp_acl_init(struct mlxsw_sp *mlxsw_sp) · 78 unmodified lines | ||
| 880 | 885 | acl->dummy_fid = fid; |
| 881 | 886 | |
| 882 | 887 | INIT_LIST_HEAD(&acl->rules); |
| 888 | + mutex_init(&acl->rules_lock); | |
| 883 | 889 | err = mlxsw_sp_acl_tcam_init(mlxsw_sp, &acl->tcam); |
| 884 | 890 | if (err) |
| 885 | 891 | goto err_acl_ops_init; |
| @@ -892,6 +898,7 @@ int mlxsw_sp_acl_init(struct mlxsw_sp *mlxsw_sp) · 6 unmodified lines | ||
| 892 | 898 | return 0; |
| 893 | 899 | |
| 894 | 900 | err_acl_ops_init: |
| 901 | + mutex_destroy(&acl->rules_lock); | |
| 895 | 902 | mlxsw_sp_fid_put(fid); |
| 896 | 903 | err_fid_get: |
| 897 | 904 | rhashtable_destroy(&acl->ruleset_ht); |
| @@ -908,6 +915,7 @@ void mlxsw_sp_acl_fini(struct mlxsw_sp *mlxsw_sp) · 10 unmodified lines | ||
| 908 | 915 | |
| 909 | 916 | cancel_delayed_work_sync(&mlxsw_sp->acl->rule_activity_update.dw); |
| 910 | 917 | mlxsw_sp_acl_tcam_fini(mlxsw_sp, &acl->tcam); |
| 918 | + mutex_destroy(&acl->rules_lock); | |
| 911 | 919 | WARN_ON(!list_empty(&acl->rules)); |
| 912 | 920 | mlxsw_sp_fid_put(acl->dummy_fid); |
| 913 | 921 | rhashtable_destroy(&acl->ruleset_ht); |
| @@ -64,6 +64,8 @@ static int sonic_open(struct net_device *dev) · 63 unmodified lines | ||
| 64 | 64 | |
| 65 | 65 | netif_dbg(lp, ifup, dev, "%s: initializing sonic driver\n", __func__); |
| 66 | 66 | |
| 67 | + spin_lock_init(&lp->lock); | |
| 68 | + | |
| 67 | 69 | for (i = 0; i < SONIC_NUM_RRS; i++) { |
| 68 | 70 | struct sk_buff *skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2); |
| 69 | 71 | if (skb == NULL) { |
| @@ -114,6 +116,24 @@ static int sonic_open(struct net_device *dev) · 44 unmodified lines | ||
| 114 | 116 | return 0; |
| 115 | 117 | } |
| 116 | 118 | |
| 119 | +/* Wait for the SONIC to become idle. */ | |
| 120 | +static void sonic_quiesce(struct net_device *dev, u16 mask) | |
| 121 | +{ | |
| 122 | + struct sonic_local * __maybe_unused lp = netdev_priv(dev); | |
| 123 | + int i; | |
| 124 | + u16 bits; | |
| 125 | + | |
| 126 | + for (i = 0; i < 1000; ++i) { | |
| 127 | + bits = SONIC_READ(SONIC_CMD) & mask; | |
| 128 | + if (!bits) | |
| 129 | + return; | |
| 130 | + if (irqs_disabled() || in_interrupt()) | |
| 131 | + udelay(20); | |
| 132 | + else | |
| 133 | + usleep_range(100, 200); | |
| 134 | + } | |
| 135 | + WARN_ONCE(1, "command deadline expired! 0x%04x\n", bits); | |
| 136 | +} | |
| 117 | 137 | |
| 118 | 138 | /* |
| 119 | 139 | * Close the SONIC device |
| @@ -130,6 +150,9 @@ static int sonic_close(struct net_device *dev) · 10 unmodified lines | ||
| 130 | 150 | /* |
| 131 | 151 | * stop the SONIC, disable interrupts |
| 132 | 152 | */ |
| 153 | + SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS); | |
| 154 | + sonic_quiesce(dev, SONIC_CR_ALL); | |
| 155 | + | |
| 133 | 156 | SONIC_WRITE(SONIC_IMR, 0); |
| 134 | 157 | SONIC_WRITE(SONIC_ISR, 0x7fff); |
| 135 | 158 | SONIC_WRITE(SONIC_CMD, SONIC_CR_RST); |
| @@ -169,6 +192,9 @@ static void sonic_tx_timeout(struct net_device *dev) · 33 unmodified lines | ||
| 169 | 192 | * put the Sonic into software-reset mode and |
| 170 | 193 | * disable all interrupts before releasing DMA buffers |
| 171 | 194 | */ |
| 195 | + SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS); | |
| 196 | + sonic_quiesce(dev, SONIC_CR_ALL); | |
| 197 | + | |
| 172 | 198 | SONIC_WRITE(SONIC_IMR, 0); |
| 173 | 199 | SONIC_WRITE(SONIC_ISR, 0x7fff); |
| 174 | 200 | SONIC_WRITE(SONIC_CMD, SONIC_CR_RST); |
| @@ -206,8 +232,6 @@ static void sonic_tx_timeout(struct net_device *dev) · 31 unmodified lines | ||
| 206 | 232 | * wake the tx queue |
| 207 | 233 | * Concurrently with all of this, the SONIC is potentially writing to |
| 208 | 234 | * the status flags of the TDs. |
| 209 | − * Until some mutual exclusion is added, this code will not work with SMP. However, | |
| 210 | − * MIPS Jazz machines and m68k Macs were all uni-processor machines. | |
| 211 | 235 | */ |
| 212 | 236 | |
| 213 | 237 | static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) |
| @@ -215,7 +239,8 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) · 1 unmodified line | ||
| 215 | 239 | struct sonic_local *lp = netdev_priv(dev); |
| 216 | 240 | dma_addr_t laddr; |
| 217 | 241 | int length; |
| 218 | − int entry = lp->next_tx; | |
| 242 | + int entry; | |
| 243 | + unsigned long flags; | |
| 219 | 244 | |
| 220 | 245 | netif_dbg(lp, tx_queued, dev, "%s: skb=%p\n", __func__, skb); |
| 221 | 246 | |
| @@ -237,6 +262,10 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) · 15 unmodified lines | ||
| 237 | 262 | return NETDEV_TX_OK; |
| 238 | 263 | } |
| 239 | 264 | |
| 265 | + spin_lock_irqsave(&lp->lock, flags); | |
| 266 | + | |
| 267 | + entry = lp->next_tx; | |
| 268 | + | |
| 240 | 269 | sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */ |
| 241 | 270 | sonic_tda_put(dev, entry, SONIC_TD_FRAG_COUNT, 1); /* single fragment */ |
| 242 | 271 | sonic_tda_put(dev, entry, SONIC_TD_PKTSIZE, length); /* length of packet */ |
| @@ -246,10 +275,6 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) · 3 unmodified lines | ||
| 246 | 275 | sonic_tda_put(dev, entry, SONIC_TD_LINK, |
| 247 | 276 | sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL); |
| 248 | 277 | |
| 249 | − /* | |
| 250 | − * Must set tx_skb[entry] only after clearing status, and | |
| 251 | − * before clearing EOL and before stopping queue | |
| 252 | − */ | |
| 253 | 278 | wmb(); |
| 254 | 279 | lp->tx_len[entry] = length; |
| 255 | 280 | lp->tx_laddr[entry] = laddr; |
| @@ -272,6 +297,8 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) · 16 unmodified lines | ||
| 272 | 297 | |
| 273 | 298 | SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP); |
| 274 | 299 | |
| 300 | + spin_unlock_irqrestore(&lp->lock, flags); | |
| 301 | + | |
| 275 | 302 | return NETDEV_TX_OK; |
| 276 | 303 | } |
| 277 | 304 | |
| @@ -284,15 +311,28 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) · 6 unmodified lines | ||
| 284 | 311 | struct net_device *dev = dev_id; |
| 285 | 312 | struct sonic_local *lp = netdev_priv(dev); |
| 286 | 313 | int status; |
| 314 | + unsigned long flags; | |
| 315 | + | |
| 316 | + /* The lock has two purposes. Firstly, it synchronizes sonic_interrupt() | |
| 317 | + * with sonic_send_packet() so that the two functions can share state. | |
| 318 | + * Secondly, it makes sonic_interrupt() re-entrant, as that is required | |
| 319 | + * by macsonic which must use two IRQs with different priority levels. | |
| 320 | + */ | |
| 321 | + spin_lock_irqsave(&lp->lock, flags); | |
| 322 | + | |
| 323 | + status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT; | |
| 324 | + if (!status) { | |
| 325 | + spin_unlock_irqrestore(&lp->lock, flags); | |
| 287 | 326 | |
| 288 | − if (!(status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT)) | |
| 289 | 327 | return IRQ_NONE; |
| 328 | + } | |
| 290 | 329 | |
| 291 | 330 | do { |
| 331 | + SONIC_WRITE(SONIC_ISR, status); /* clear the interrupt(s) */ | |
| 332 | + | |
| 292 | 333 | if (status & SONIC_INT_PKTRX) { |
| 293 | 334 | netif_dbg(lp, intr, dev, "%s: packet rx\n", __func__); |
| 294 | 335 | sonic_rx(dev); /* got packet(s) */ |
| 295 | − SONIC_WRITE(SONIC_ISR, SONIC_INT_PKTRX); /* clear the interrupt */ | |
| 296 | 336 | } |
| 297 | 337 | |
| 298 | 338 | if (status & SONIC_INT_TXDN) { |
| @@ -300,11 +340,12 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) · 1 unmodified line | ||
| 300 | 340 | int td_status; |
| 301 | 341 | int freed_some = 0; |
| 302 | 342 | |
| 303 | − /* At this point, cur_tx is the index of a TD that is one of: | |
| 304 | − * unallocated/freed (status set & tx_skb[entry] clear) | |
| 305 | − * allocated and sent (status set & tx_skb[entry] set ) | |
| 306 | − * allocated and not yet sent (status clear & tx_skb[entry] set ) | |
| 307 | − * still being allocated by sonic_send_packet (status clear & tx_skb[entry] clear) | |
| 343 | + /* The state of a Transmit Descriptor may be inferred | |
| 344 | + * from { tx_skb[entry], td_status } as follows. | |
| 345 | + * { clear, clear } => the TD has never been used | |
| 346 | + * { set, clear } => the TD was handed to SONIC | |
| 347 | + * { set, set } => the TD was handed back | |
| 348 | + * { clear, set } => the TD is available for re-use | |
| 308 | 349 | */ |
| 309 | 350 | |
| 310 | 351 | netif_dbg(lp, intr, dev, "%s: tx done\n", __func__); |
| @@ -313,18 +354,19 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) · 2 unmodified lines | ||
| 313 | 354 | if ((td_status = sonic_tda_get(dev, entry, SONIC_TD_STATUS)) == 0) |
| 314 | 355 | break; |
| 315 | 356 | |
| 316 | − if (td_status & 0x0001) { | |
| 357 | + if (td_status & SONIC_TCR_PTX) { | |
| 317 | 358 | lp->stats.tx_packets++; |
| 318 | 359 | lp->stats.tx_bytes += sonic_tda_get(dev, entry, SONIC_TD_PKTSIZE); |
| 319 | 360 | } else { |
| 320 | − lp->stats.tx_errors++; | |
| 321 | − if (td_status & 0x0642) | |
| 361 | + if (td_status & (SONIC_TCR_EXD | | |
| 362 | + SONIC_TCR_EXC | SONIC_TCR_BCM)) | |
| 322 | 363 | lp->stats.tx_aborted_errors++; |
| 323 | − if (td_status & 0x0180) | |
| 364 | + if (td_status & | |
| 365 | + (SONIC_TCR_NCRS | SONIC_TCR_CRLS)) | |
| 324 | 366 | lp->stats.tx_carrier_errors++; |
| 325 | − if (td_status & 0x0020) | |
| 367 | + if (td_status & SONIC_TCR_OWC) | |
| 326 | 368 | lp->stats.tx_window_errors++; |
| 327 | − if (td_status & 0x0004) | |
| 369 | + if (td_status & SONIC_TCR_FU) | |
| 328 | 370 | lp->stats.tx_fifo_errors++; |
| 329 | 371 | } |
| 330 | 372 | |
| @@ -346,7 +388,6 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) · 15 unmodified lines | ||
| 346 | 388 | if (freed_some || lp->tx_skb[entry] == NULL) |
| 347 | 389 | netif_wake_queue(dev); /* The ring is no longer full */ |
| 348 | 390 | lp->cur_tx = entry; |
| 349 | − SONIC_WRITE(SONIC_ISR, SONIC_INT_TXDN); /* clear the interrupt */ | |
| 350 | 391 | } |
| 351 | 392 | |
| 352 | 393 | /* |
| @@ -355,42 +396,37 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) · 2 unmodified lines | ||
| 355 | 396 | if (status & SONIC_INT_RFO) { |
| 356 | 397 | netif_dbg(lp, rx_err, dev, "%s: rx fifo overrun\n", |
| 357 | 398 | __func__); |
| 358 | − lp->stats.rx_fifo_errors++; | |
| 359 | − SONIC_WRITE(SONIC_ISR, SONIC_INT_RFO); /* clear the interrupt */ | |
| 360 | 399 | } |
| 361 | 400 | if (status & SONIC_INT_RDE) { |
| 362 | 401 | netif_dbg(lp, rx_err, dev, "%s: rx descriptors exhausted\n", |
| 363 | 402 | __func__); |
| 364 | − lp->stats.rx_dropped++; | |
| 365 | − SONIC_WRITE(SONIC_ISR, SONIC_INT_RDE); /* clear the interrupt */ | |
| 366 | 403 | } |
| 367 | 404 | if (status & SONIC_INT_RBAE) { |
| 368 | 405 | netif_dbg(lp, rx_err, dev, "%s: rx buffer area exceeded\n", |
| 369 | 406 | __func__); |
| 370 | − lp->stats.rx_dropped++; | |
| 371 | − SONIC_WRITE(SONIC_ISR, SONIC_INT_RBAE); /* clear the interrupt */ | |
| 372 | 407 | } |
| 373 | 408 | |
| 374 | 409 | /* counter overruns; all counters are 16bit wide */ |
| 375 | − if (status & SONIC_INT_FAE) { | |
| 410 | + if (status & SONIC_INT_FAE) | |
| 376 | 411 | lp->stats.rx_frame_errors += 65536; |
| 377 | − SONIC_WRITE(SONIC_ISR, SONIC_INT_FAE); /* clear the interrupt */ | |
| 378 | − } | |
| 379 | − if (status & SONIC_INT_CRC) { | |
| 412 | + if (status & SONIC_INT_CRC) | |
| 380 | 413 | lp->stats.rx_crc_errors += 65536; |
| 381 | − SONIC_WRITE(SONIC_ISR, SONIC_INT_CRC); /* clear the interrupt */ | |
| 382 | − } | |
| 383 | − if (status & SONIC_INT_MP) { | |
| 414 | + if (status & SONIC_INT_MP) | |
| 384 | 415 | lp->stats.rx_missed_errors += 65536; |
| 385 | − SONIC_WRITE(SONIC_ISR, SONIC_INT_MP); /* clear the interrupt */ | |
| 386 | − } | |
| 387 | 416 | |
| 388 | 417 | /* transmit error */ |
| 389 | 418 | if (status & SONIC_INT_TXER) { |
| 390 | − if (SONIC_READ(SONIC_TCR) & SONIC_TCR_FU) | |
| 391 | − netif_dbg(lp, tx_err, dev, "%s: tx fifo underrun\n", | |
| 392 | − __func__); | |
| 393 | − SONIC_WRITE(SONIC_ISR, SONIC_INT_TXER); /* clear the interrupt */ | |
| 419 | + u16 tcr = SONIC_READ(SONIC_TCR); | |
| 420 | + | |
| 421 | + netif_dbg(lp, tx_err, dev, "%s: TXER intr, TCR %04x\n", | |
| 422 | + __func__, tcr); | |
| 423 | + | |
| 424 | + if (tcr & (SONIC_TCR_EXD | SONIC_TCR_EXC | | |
| 425 | + SONIC_TCR_FU | SONIC_TCR_BCM)) { | |
| 426 | + /* Aborted transmission. Try again. */ | |
| 427 | + netif_stop_queue(dev); | |
| 428 | + SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP); | |
| 429 | + } | |
| 394 | 430 | } |
| 395 | 431 | |
| 396 | 432 | /* bus retry */ |
| @@ -400,107 +436,164 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) · 3 unmodified lines | ||
| 400 | 436 | /* ... to help debug DMA problems causing endless interrupts. */ |
| 401 | 437 | /* Bounce the eth interface to turn on the interrupt again. */ |
| 402 | 438 | SONIC_WRITE(SONIC_IMR, 0); |
| 403 | − SONIC_WRITE(SONIC_ISR, SONIC_INT_BR); /* clear the interrupt */ | |
| 404 | 439 | } |
| 405 | 440 | |
| 406 | − /* load CAM done */ | |
| 407 | − if (status & SONIC_INT_LCD) | |
| 408 | − SONIC_WRITE(SONIC_ISR, SONIC_INT_LCD); /* clear the interrupt */ | |
| 409 | − } while((status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT)); | |
| 441 | + status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT; | |
| 442 | + } while (status); | |
| 443 | + | |
| 444 | + spin_unlock_irqrestore(&lp->lock, flags); | |
| 445 | + | |
| 410 | 446 | return IRQ_HANDLED; |
| 411 | 447 | } |
| 412 | 448 | |
| 449 | +/* Return the array index corresponding to a given Receive Buffer pointer. */ | |
| 450 | +static int index_from_addr(struct sonic_local *lp, dma_addr_t addr, | |
| 451 | + unsigned int last) | |
| 452 | +{ | |
| 453 | + unsigned int i = last; | |
| 454 | + | |
| 455 | + do { | |
| 456 | + i = (i + 1) & SONIC_RRS_MASK; | |
| 457 | + if (addr == lp->rx_laddr[i]) | |
| 458 | + return i; | |
| 459 | + } while (i != last); | |
| 460 | + | |
| 461 | + return -ENOENT; | |
| 462 | +} | |
| 463 | + | |
| 464 | +/* Allocate and map a new skb to be used as a receive buffer. */ | |
| 465 | +static bool sonic_alloc_rb(struct net_device *dev, struct sonic_local *lp, | |
| 466 | + struct sk_buff **new_skb, dma_addr_t *new_addr) | |
| 467 | +{ | |
| 468 | + *new_skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2); | |
| 469 | + if (!*new_skb) | |
| 470 | + return false; | |
| 471 | + | |
| 472 | + if (SONIC_BUS_SCALE(lp->dma_bitmode) == 2) | |
| 473 | + skb_reserve(*new_skb, 2); | |
| 474 | + | |
| 475 | + *new_addr = dma_map_single(lp->device, skb_put(*new_skb, SONIC_RBSIZE), | |
| 476 | + SONIC_RBSIZE, DMA_FROM_DEVICE); | |
| 477 | + if (!*new_addr) { | |
| 478 | + dev_kfree_skb(*new_skb); | |
| 479 | + *new_skb = NULL; | |
| 480 | + return false; | |
| 481 | + } | |
| 482 | + | |
| 483 | + return true; | |
| 484 | +} | |
| 485 | + | |
| 486 | +/* Place a new receive resource in the Receive Resource Area and update RWP. */ | |
| 487 | +static void sonic_update_rra(struct net_device *dev, struct sonic_local *lp, | |
| 488 | + dma_addr_t old_addr, dma_addr_t new_addr) | |
| 489 | +{ | |
| 490 | + unsigned int entry = sonic_rr_entry(dev, SONIC_READ(SONIC_RWP)); | |
| 491 | + unsigned int end = sonic_rr_entry(dev, SONIC_READ(SONIC_RRP)); | |
| 492 | + u32 buf; | |
| 493 | + | |
| 494 | + /* The resources in the range [RRP, RWP) belong to the SONIC. This loop | |
| 495 | + * scans the other resources in the RRA, those in the range [RWP, RRP). | |
| 496 | + */ | |
| 497 | + do { | |
| 498 | + buf = (sonic_rra_get(dev, entry, SONIC_RR_BUFADR_H) << 16) | | |
| 499 | + sonic_rra_get(dev, entry, SONIC_RR_BUFADR_L); | |
| 500 | + | |
| 501 | + if (buf == old_addr) | |
| 502 | + break; | |
| 503 | + | |
| 504 | + entry = (entry + 1) & SONIC_RRS_MASK; | |
| 505 | + } while (entry != end); | |
| 506 | + | |
| 507 | + WARN_ONCE(buf != old_addr, "failed to find resource!\n"); | |
| 508 | + | |
| 509 | + sonic_rra_put(dev, entry, SONIC_RR_BUFADR_H, new_addr >> 16); | |
| 510 | + sonic_rra_put(dev, entry, SONIC_RR_BUFADR_L, new_addr & 0xffff); | |
| 511 | + | |
| 512 | + entry = (entry + 1) & SONIC_RRS_MASK; | |
| 513 | + | |
| 514 | + SONIC_WRITE(SONIC_RWP, sonic_rr_addr(dev, entry)); | |
| 515 | +} | |
| 516 | + | |
| 413 | 517 | /* |
| 414 | 518 | * We have a good packet(s), pass it/them up the network stack. |
| 415 | 519 | */ |
| 416 | 520 | static void sonic_rx(struct net_device *dev) |
| 417 | 521 | { |
| 418 | 522 | struct sonic_local *lp = netdev_priv(dev); |
| 419 | − int status; | |
| 420 | 523 | int entry = lp->cur_rx; |
| 524 | + int prev_entry = lp->eol_rx; | |
| 525 | + bool rbe = false; | |
| 421 | 526 | |
| 422 | 527 | while (sonic_rda_get(dev, entry, SONIC_RD_IN_USE) == 0) { |
| 423 | − struct sk_buff *used_skb; | |
| 424 | − struct sk_buff *new_skb; | |
| 425 | − dma_addr_t new_laddr; | |
| 426 | − u16 bufadr_l; | |
| 427 | − u16 bufadr_h; | |
| 428 | − int pkt_len; | |
| 429 | − | |
| 430 | − status = sonic_rda_get(dev, entry, SONIC_RD_STATUS); | |
| 431 | − if (status & SONIC_RCR_PRX) { | |
| 432 | − /* Malloc up new buffer. */ | |
| 433 | − new_skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2); | |
| 434 | − if (new_skb == NULL) { | |
| 435 | − lp->stats.rx_dropped++; | |
| 528 | + u16 status = sonic_rda_get(dev, entry, SONIC_RD_STATUS); | |
| 529 | + | |
| 530 | + /* If the RD has LPKT set, the chip has finished with the RB */ | |
| 531 | + if ((status & SONIC_RCR_PRX) && (status & SONIC_RCR_LPKT)) { | |
| 532 | + struct sk_buff *new_skb; | |
| 533 | + dma_addr_t new_laddr; | |
| 534 | + u32 addr = (sonic_rda_get(dev, entry, | |
| 535 | + SONIC_RD_PKTPTR_H) << 16) | | |
| 536 | + sonic_rda_get(dev, entry, SONIC_RD_PKTPTR_L); | |
| 537 | + int i = index_from_addr(lp, addr, entry); | |
| 538 | + | |
| 539 | + if (i < 0) { | |
| 540 | + WARN_ONCE(1, "failed to find buffer!\n"); | |
| 436 | 541 | break; |
| 437 | 542 | } |
| 438 | − /* provide 16 byte IP header alignment unless DMA requires otherwise */ | |
| 439 | − if(SONIC_BUS_SCALE(lp->dma_bitmode) == 2) | |
| 440 | − skb_reserve(new_skb, 2); | |
| 441 | − | |
| 442 | − new_laddr = dma_map_single(lp->device, skb_put(new_skb, SONIC_RBSIZE), | |
| 443 | − SONIC_RBSIZE, DMA_FROM_DEVICE); | |
| 444 | − if (!new_laddr) { | |
| 445 | − dev_kfree_skb(new_skb); | |
| 446 | − printk(KERN_ERR "%s: Failed to map rx buffer, dropping packet.\n", dev->name); | |
| 543 | + | |
| 544 | + if (sonic_alloc_rb(dev, lp, &new_skb, &new_laddr)) { | |
| 545 | + struct sk_buff *used_skb = lp->rx_skb[i]; | |
| 546 | + int pkt_len; | |
| 547 | + | |
| 548 | + /* Pass the used buffer up the stack */ | |
| 549 | + dma_unmap_single(lp->device, addr, SONIC_RBSIZE, | |
| 550 | + DMA_FROM_DEVICE); | |
| 551 | + | |
| 552 | + pkt_len = sonic_rda_get(dev, entry, | |
| 553 | + SONIC_RD_PKTLEN); | |
| 554 | + skb_trim(used_skb, pkt_len); | |
| 555 | + used_skb->protocol = eth_type_trans(used_skb, | |
| 556 | + dev); | |
| 557 | + netif_rx(used_skb); | |
| 558 | + lp->stats.rx_packets++; | |
| 559 | + lp->stats.rx_bytes += pkt_len; | |
| 560 | + | |
| 561 | + lp->rx_skb[i] = new_skb; | |
| 562 | + lp->rx_laddr[i] = new_laddr; | |
| 563 | + } else { | |
| 564 | + /* Failed to obtain a new buffer so re-use it */ | |
| 565 | + new_laddr = addr; | |
| 447 | 566 | lp->stats.rx_dropped++; |
| 448 | − break; | |
| 449 | 567 | } |
| 450 | − | |
| 451 | − /* now we have a new skb to replace it, pass the used one up the stack */ | |
| 452 | − dma_unmap_single(lp->device, lp->rx_laddr[entry], SONIC_RBSIZE, DMA_FROM_DEVICE); | |
| 453 | − used_skb = lp->rx_skb[entry]; | |
| 454 | − pkt_len = sonic_rda_get(dev, entry, SONIC_RD_PKTLEN); | |
| 455 | − skb_trim(used_skb, pkt_len); | |
| 456 | − used_skb->protocol = eth_type_trans(used_skb, dev); | |
| 457 | − netif_rx(used_skb); | |
| 458 | − lp->stats.rx_packets++; | |
| 459 | − lp->stats.rx_bytes += pkt_len; | |
| 460 | − | |
| 461 | − /* and insert the new skb */ | |
| 462 | − lp->rx_laddr[entry] = new_laddr; | |
| 463 | − lp->rx_skb[entry] = new_skb; | |
| 464 | − | |
| 465 | − bufadr_l = (unsigned long)new_laddr & 0xffff; | |
| 466 | − bufadr_h = (unsigned long)new_laddr >> 16; | |
| 467 | − sonic_rra_put(dev, entry, SONIC_RR_BUFADR_L, bufadr_l); | |
| 468 | − sonic_rra_put(dev, entry, SONIC_RR_BUFADR_H, bufadr_h); | |
| 469 | − } else { | |
| 470 | − /* This should only happen, if we enable accepting broken packets. */ | |
| 471 | − lp->stats.rx_errors++; | |
| 472 | − if (status & SONIC_RCR_FAER) | |
| 473 | − lp->stats.rx_frame_errors++; | |
| 474 | − if (status & SONIC_RCR_CRCR) | |
| 475 | − lp->stats.rx_crc_errors++; | |
| 476 | − } | |
| 477 | − if (status & SONIC_RCR_LPKT) { | |
| 478 | − /* | |
| 479 | − * this was the last packet out of the current receive buffer | |
| 480 | − * give the buffer back to the SONIC | |
| 568 | + /* If RBE is already asserted when RWP advances then | |
| 569 | + * it's safe to clear RBE after processing this packet. | |
| 481 | 570 | */ |
| 482 | − lp->cur_rwp += SIZEOF_SONIC_RR * SONIC_BUS_SCALE(lp->dma_bitmode); | |
| 483 | − if (lp->cur_rwp >= lp->rra_end) lp->cur_rwp = lp->rra_laddr & 0xffff; | |
| 484 | − SONIC_WRITE(SONIC_RWP, lp->cur_rwp); | |
| 485 | − if (SONIC_READ(SONIC_ISR) & SONIC_INT_RBE) { | |
| 486 | − netif_dbg(lp, rx_err, dev, "%s: rx buffer exhausted\n", | |
| 487 | − __func__); | |
| 488 | − SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE); /* clear the flag */ | |
| 489 | − } | |
| 490 | − } else | |
| 491 | − printk(KERN_ERR "%s: rx desc without RCR_LPKT. Shouldn't happen !?\n", | |
| 492 | − dev->name); | |
| 571 | + rbe = rbe || SONIC_READ(SONIC_ISR) & SONIC_INT_RBE; | |
| 572 | + sonic_update_rra(dev, lp, addr, new_laddr); | |
| 573 | + } | |
| 493 | 574 | /* |
| 494 | 575 | * give back the descriptor |
| 495 | 576 | */ |
| 496 | − sonic_rda_put(dev, entry, SONIC_RD_LINK, | |
| 497 | − sonic_rda_get(dev, entry, SONIC_RD_LINK) | SONIC_EOL); | |
| 577 | + sonic_rda_put(dev, entry, SONIC_RD_STATUS, 0); | |
| 498 | 578 | sonic_rda_put(dev, entry, SONIC_RD_IN_USE, 1); |
| 499 | − sonic_rda_put(dev, lp->eol_rx, SONIC_RD_LINK, | |
| 500 | − sonic_rda_get(dev, lp->eol_rx, SONIC_RD_LINK) & ~SONIC_EOL); | |
| 501 | − lp->eol_rx = entry; | |
| 502 | − lp->cur_rx = entry = (entry + 1) & SONIC_RDS_MASK; | |
| 579 | + | |
| 580 | + prev_entry = entry; | |
| 581 | + entry = (entry + 1) & SONIC_RDS_MASK; | |
| 582 | + } | |
| 583 | + | |
| 584 | + lp->cur_rx = entry; | |
| 585 | + | |
| 586 | + if (prev_entry != lp->eol_rx) { | |
| 587 | + /* Advance the EOL flag to put descriptors back into service */ | |
| 588 | + sonic_rda_put(dev, prev_entry, SONIC_RD_LINK, SONIC_EOL | | |
| 589 | + sonic_rda_get(dev, prev_entry, SONIC_RD_LINK)); | |
| 590 | + sonic_rda_put(dev, lp->eol_rx, SONIC_RD_LINK, ~SONIC_EOL & | |
| 591 | + sonic_rda_get(dev, lp->eol_rx, SONIC_RD_LINK)); | |
| 592 | + lp->eol_rx = prev_entry; | |
| 503 | 593 | } |
| 594 | + | |
| 595 | + if (rbe) | |
| 596 | + SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE); | |
| 504 | 597 | /* |
| 505 | 598 | * If any worth-while packets have been received, netif_rx() |
| 506 | 599 | * has done a mark_bh(NET_BH) for us and will work on them |
| @@ -550,6 +643,8 @@ static void sonic_multicast_list(struct net_device *dev) · 43 unmodified lines | ||
| 550 | 643 | (netdev_mc_count(dev) > 15)) { |
| 551 | 644 | rcr |= SONIC_RCR_AMC; |
| 552 | 645 | } else { |
| 646 | + unsigned long flags; | |
| 647 | + | |
| 553 | 648 | netif_dbg(lp, ifup, dev, "%s: mc_count %d\n", __func__, |
| 554 | 649 | netdev_mc_count(dev)); |
| 555 | 650 | sonic_set_cam_enable(dev, 1); /* always enable our own address */ |
| @@ -563,9 +658,14 @@ static void sonic_multicast_list(struct net_device *dev) · 7 unmodified lines | ||
| 563 | 658 | i++; |
| 564 | 659 | } |
| 565 | 660 | SONIC_WRITE(SONIC_CDC, 16); |
| 566 | − /* issue Load CAM command */ | |
| 567 | 661 | SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff); |
| 662 | + | |
| 663 | + /* LCAM and TXP commands can't be used simultaneously */ | |
| 664 | + spin_lock_irqsave(&lp->lock, flags); | |
| 665 | + sonic_quiesce(dev, SONIC_CR_TXP); | |
| 568 | 666 | SONIC_WRITE(SONIC_CMD, SONIC_CR_LCAM); |
| 667 | + sonic_quiesce(dev, SONIC_CR_LCAM); | |
| 668 | + spin_unlock_irqrestore(&lp->lock, flags); | |
| 569 | 669 | } |
| 570 | 670 | } |
| 571 | 671 | |
| @@ -580,7 +680,6 @@ static void sonic_multicast_list(struct net_device *dev) · 8 unmodified lines | ||
| 580 | 680 | */ |
| 581 | 681 | static int sonic_init(struct net_device *dev) |
| 582 | 682 | { |
| 583 | − unsigned int cmd; | |
| 584 | 683 | struct sonic_local *lp = netdev_priv(dev); |
| 585 | 684 | int i; |
| 586 | 685 | |
| @@ -592,12 +691,16 @@ static int sonic_init(struct net_device *dev) · 5 unmodified lines | ||
| 592 | 691 | SONIC_WRITE(SONIC_ISR, 0x7fff); |
| 593 | 692 | SONIC_WRITE(SONIC_CMD, SONIC_CR_RST); |
| 594 | 693 | |
| 694 | + /* While in reset mode, clear CAM Enable register */ | |
| 695 | + SONIC_WRITE(SONIC_CE, 0); | |
| 696 | + | |
| 595 | 697 | /* |
| 596 | 698 | * clear software reset flag, disable receiver, clear and |
| 597 | 699 | * enable interrupts, then completely initialize the SONIC |
| 598 | 700 | */ |
| 599 | 701 | SONIC_WRITE(SONIC_CMD, 0); |
| 600 | − SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS); | |
| 702 | + SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS | SONIC_CR_STP); | |
| 703 | + sonic_quiesce(dev, SONIC_CR_ALL); | |
| 601 | 704 | |
| 602 | 705 | /* |
| 603 | 706 | * initialize the receive resource area |
| @@ -615,15 +718,10 @@ static int sonic_init(struct net_device *dev) · 11 unmodified lines | ||
| 615 | 718 | } |
| 616 | 719 | |
| 617 | 720 | /* initialize all RRA registers */ |
| 618 | − lp->rra_end = (lp->rra_laddr + SONIC_NUM_RRS * SIZEOF_SONIC_RR * | |
| 619 | − SONIC_BUS_SCALE(lp->dma_bitmode)) & 0xffff; | |
| 620 | − lp->cur_rwp = (lp->rra_laddr + (SONIC_NUM_RRS - 1) * SIZEOF_SONIC_RR * | |
| 621 | − SONIC_BUS_SCALE(lp->dma_bitmode)) & 0xffff; | |
| 622 | − | |
| 623 | − SONIC_WRITE(SONIC_RSA, lp->rra_laddr & 0xffff); | |
| 624 | − SONIC_WRITE(SONIC_REA, lp->rra_end); | |
| 625 | − SONIC_WRITE(SONIC_RRP, lp->rra_laddr & 0xffff); | |
| 626 | − SONIC_WRITE(SONIC_RWP, lp->cur_rwp); | |
| 721 | + SONIC_WRITE(SONIC_RSA, sonic_rr_addr(dev, 0)); | |
| 722 | + SONIC_WRITE(SONIC_REA, sonic_rr_addr(dev, SONIC_NUM_RRS)); | |
| 723 | + SONIC_WRITE(SONIC_RRP, sonic_rr_addr(dev, 0)); | |
| 724 | + SONIC_WRITE(SONIC_RWP, sonic_rr_addr(dev, SONIC_NUM_RRS - 1)); | |
| 627 | 725 | SONIC_WRITE(SONIC_URRA, lp->rra_laddr >> 16); |
| 628 | 726 | SONIC_WRITE(SONIC_EOBC, (SONIC_RBSIZE >> 1) - (lp->dma_bitmode ? 2 : 1)); |
| 629 | 727 | |
| @@ -631,14 +729,7 @@ static int sonic_init(struct net_device *dev) · 1 unmodified line | ||
| 631 | 729 | netif_dbg(lp, ifup, dev, "%s: issuing RRRA command\n", __func__); |
| 632 | 730 | |
| 633 | 731 | SONIC_WRITE(SONIC_CMD, SONIC_CR_RRRA); |
| 634 | − i = 0; | |
| 635 | − while (i++ < 100) { | |
| 636 | − if (SONIC_READ(SONIC_CMD) & SONIC_CR_RRRA) | |
| 637 | − break; | |
| 638 | − } | |
| 639 | − | |
| 640 | − netif_dbg(lp, ifup, dev, "%s: status=%x, i=%d\n", __func__, | |
| 641 | − SONIC_READ(SONIC_CMD), i); | |
| 732 | + sonic_quiesce(dev, SONIC_CR_RRRA); | |
| 642 | 733 | |
| 643 | 734 | /* |
| 644 | 735 | * Initialize the receive descriptors so that they |
| @@ -713,28 +804,17 @@ static int sonic_init(struct net_device *dev) · 68 unmodified lines | ||
| 713 | 804 | * load the CAM |
| 714 | 805 | */ |
| 715 | 806 | SONIC_WRITE(SONIC_CMD, SONIC_CR_LCAM); |
| 716 | − | |
| 717 | − i = 0; | |
| 718 | − while (i++ < 100) { | |
| 719 | − if (SONIC_READ(SONIC_ISR) & SONIC_INT_LCD) | |
| 720 | − break; | |
| 721 | − } | |
| 722 | − netif_dbg(lp, ifup, dev, "%s: CMD=%x, ISR=%x, i=%d\n", __func__, | |
| 723 | − SONIC_READ(SONIC_CMD), SONIC_READ(SONIC_ISR), i); | |
| 807 | + sonic_quiesce(dev, SONIC_CR_LCAM); | |
| 724 | 808 | |
| 725 | 809 | /* |
| 726 | 810 | * enable receiver, disable loopback |
| 727 | 811 | * and enable all interrupts |
| 728 | 812 | */ |
| 729 | − SONIC_WRITE(SONIC_CMD, SONIC_CR_RXEN | SONIC_CR_STP); | |
| 730 | 813 | SONIC_WRITE(SONIC_RCR, SONIC_RCR_DEFAULT); |
| 731 | 814 | SONIC_WRITE(SONIC_TCR, SONIC_TCR_DEFAULT); |
| 732 | 815 | SONIC_WRITE(SONIC_ISR, 0x7fff); |
| 733 | 816 | SONIC_WRITE(SONIC_IMR, SONIC_IMR_DEFAULT); |
| 734 | − | |
| 735 | − cmd = SONIC_READ(SONIC_CMD); | |
| 736 | − if ((cmd & SONIC_CR_RXEN) == 0 || (cmd & SONIC_CR_STP) == 0) | |
| 737 | − printk(KERN_ERR "sonic_init: failed, status=%x\n", cmd); | |
| 817 | + SONIC_WRITE(SONIC_CMD, SONIC_CR_RXEN); | |
| 738 | 818 | |
| 739 | 819 | netif_dbg(lp, ifup, dev, "%s: new status=%x\n", __func__, |
| 740 | 820 | SONIC_READ(SONIC_CMD)); |
| @@ -110,6 +110,9 @@ · 109 unmodified lines | ||
| 110 | 110 | #define SONIC_CR_TXP 0x0002 |
| 111 | 111 | #define SONIC_CR_HTX 0x0001 |
| 112 | 112 | |
| 113 | +#define SONIC_CR_ALL (SONIC_CR_LCAM | SONIC_CR_RRRA | \ | |
| 114 | + SONIC_CR_RXEN | SONIC_CR_TXP) | |
| 115 | + | |
| 113 | 116 | /* |
| 114 | 117 | * SONIC data configuration bits |
| 115 | 118 | */ |
| @@ -175,6 +178,7 @@ · 59 unmodified lines | ||
| 175 | 178 | #define SONIC_TCR_NCRS 0x0100 |
| 176 | 179 | #define SONIC_TCR_CRLS 0x0080 |
| 177 | 180 | #define SONIC_TCR_EXC 0x0040 |
| 181 | +#define SONIC_TCR_OWC 0x0020 | |
| 178 | 182 | #define SONIC_TCR_PMB 0x0008 |
| 179 | 183 | #define SONIC_TCR_FU 0x0004 |
| 180 | 184 | #define SONIC_TCR_BCM 0x0002 |
| @@ -274,8 +278,9 @@ · 93 unmodified lines | ||
| 274 | 278 | #define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */ |
| 275 | 279 | #define SONIC_NUM_TDS 16 /* number of transmit descriptors */ |
| 276 | 280 | |
| 277 | −#define SONIC_RDS_MASK (SONIC_NUM_RDS-1) | |
| 278 | −#define SONIC_TDS_MASK (SONIC_NUM_TDS-1) | |
| 281 | +#define SONIC_RRS_MASK (SONIC_NUM_RRS - 1) | |
| 282 | +#define SONIC_RDS_MASK (SONIC_NUM_RDS - 1) | |
| 283 | +#define SONIC_TDS_MASK (SONIC_NUM_TDS - 1) | |
| 279 | 284 | |
| 280 | 285 | #define SONIC_RBSIZE 1520 /* size of one resource buffer */ |
| 281 | 286 | |
| @@ -312,8 +317,6 @@ struct sonic_local { · 30 unmodified lines | ||
| 312 | 317 | u32 rda_laddr; /* logical DMA address of RDA */ |
| 313 | 318 | dma_addr_t rx_laddr[SONIC_NUM_RRS]; /* logical DMA addresses of rx skbuffs */ |
| 314 | 319 | dma_addr_t tx_laddr[SONIC_NUM_TDS]; /* logical DMA addresses of tx skbuffs */ |
| 315 | − unsigned int rra_end; | |
| 316 | − unsigned int cur_rwp; | |
| 317 | 320 | unsigned int cur_rx; |
| 318 | 321 | unsigned int cur_tx; /* first unacked transmit packet */ |
| 319 | 322 | unsigned int eol_rx; |
| @@ -322,6 +325,7 @@ struct sonic_local { · 2 unmodified lines | ||
| 322 | 325 | int msg_enable; |
| 323 | 326 | struct device *device; /* generic device */ |
| 324 | 327 | struct net_device_stats stats; |
| 328 | + spinlock_t lock; | |
| 325 | 329 | }; |
| 326 | 330 | |
| 327 | 331 | #define TX_TIMEOUT (3 * HZ) |
| @@ -344,30 +348,30 @@ static void sonic_msg_init(struct net_device *dev); · 16 unmodified lines | ||
| 344 | 348 | as far as we can tell. */ |
| 345 | 349 | /* OpenBSD calls this "SWO". I'd like to think that sonic_buf_put() |
| 346 | 350 | is a much better name. */ |
| 347 | −static inline void sonic_buf_put(void* base, int bitmode, | |
| 351 | +static inline void sonic_buf_put(u16 *base, int bitmode, | |
| 348 | 352 | int offset, __u16 val) |
| 349 | 353 | { |
| 350 | 354 | if (bitmode) |
| 351 | 355 | #ifdef __BIG_ENDIAN |
| 352 | − ((__u16 *) base + (offset*2))[1] = val; | |
| 356 | + __raw_writew(val, base + (offset * 2) + 1); | |
| 353 | 357 | #else |
| 354 | − ((__u16 *) base + (offset*2))[0] = val; | |
| 358 | + __raw_writew(val, base + (offset * 2) + 0); | |
| 355 | 359 | #endif |
| 356 | 360 | else |
| 357 | − ((__u16 *) base)[offset] = val; | |
| 361 | + __raw_writew(val, base + (offset * 1) + 0); | |
| 358 | 362 | } |
| 359 | 363 | |
| 360 | −static inline __u16 sonic_buf_get(void* base, int bitmode, | |
| 364 | +static inline __u16 sonic_buf_get(u16 *base, int bitmode, | |
| 361 | 365 | int offset) |
| 362 | 366 | { |
| 363 | 367 | if (bitmode) |
| 364 | 368 | #ifdef __BIG_ENDIAN |
| 365 | − return ((volatile __u16 *) base + (offset*2))[1]; | |
| 369 | + return __raw_readw(base + (offset * 2) + 1); | |
| 366 | 370 | #else |
| 367 | − return ((volatile __u16 *) base + (offset*2))[0]; | |
| 371 | + return __raw_readw(base + (offset * 2) + 0); | |
| 368 | 372 | #endif |
| 369 | 373 | else |
| 370 | − return ((volatile __u16 *) base)[offset]; | |
| 374 | + return __raw_readw(base + (offset * 1) + 0); | |
| 371 | 375 | } |
| 372 | 376 | |
| 373 | 377 | /* Inlines that you should actually use for reading/writing DMA buffers */ |
| @@ -447,6 +451,22 @@ static inline __u16 sonic_rra_get(struct net_device* dev, int entry, · 73 unmodified lines | ||
| 447 | 451 | (entry * SIZEOF_SONIC_RR) + offset); |
| 448 | 452 | } |
| 449 | 453 | |
| 454 | +static inline u16 sonic_rr_addr(struct net_device *dev, int entry) | |
| 455 | +{ | |
| 456 | + struct sonic_local *lp = netdev_priv(dev); | |
| 457 | + | |
| 458 | + return lp->rra_laddr + | |
| 459 | + entry * SIZEOF_SONIC_RR * SONIC_BUS_SCALE(lp->dma_bitmode); | |
| 460 | +} | |
| 461 | + | |
| 462 | +static inline u16 sonic_rr_entry(struct net_device *dev, u16 addr) | |
| 463 | +{ | |
| 464 | + struct sonic_local *lp = netdev_priv(dev); | |
| 465 | + | |
| 466 | + return (addr - (u16)lp->rra_laddr) / (SIZEOF_SONIC_RR * | |
| 467 | + SONIC_BUS_SCALE(lp->dma_bitmode)); | |
| 468 | +} | |
| 469 | + | |
| 450 | 470 | static const char version[] = |
| 451 | 471 | "sonic.c:v0.92 20.9.98 tsbogend@alpha.franken.de\n"; |
| 452 | 472 | |
| @@ -2043,6 +2043,7 @@ static void qlcnic_83xx_exec_template_cmd(struct qlcnic_adapter *p_dev, · 2042 unmodified lines | ||
| 2043 | 2043 | break; |
| 2044 | 2044 | } |
| 2045 | 2045 | entry += p_hdr->size; |
| 2046 | + cond_resched(); | |
| 2046 | 2047 | } |
| 2047 | 2048 | p_dev->ahw->reset.seq_index = index; |
| 2048 | 2049 | } |
| @@ -703,6 +703,7 @@ static u32 qlcnic_read_memory_test_agent(struct qlcnic_adapter *adapter, · 702 unmodified lines | ||
| 703 | 703 | addr += 16; |
| 704 | 704 | reg_read -= 16; |
| 705 | 705 | ret += 16; |
| 706 | + cond_resched(); | |
| 706 | 707 | } |
| 707 | 708 | out: |
| 708 | 709 | mutex_unlock(&adapter->ahw->mem_lock); |
| @@ -1383,6 +1384,7 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) · 674 unmodified lines | ||
| 1383 | 1384 | buf_offset += entry->hdr.cap_size; |
| 1384 | 1385 | entry_offset += entry->hdr.offset; |
| 1385 | 1386 | buffer = fw_dump->data + buf_offset; |
| 1387 | + cond_resched(); | |
| 1386 | 1388 | } |
| 1387 | 1389 | |
| 1388 | 1390 | fw_dump->clr = 1; |
| @@ -412,9 +412,9 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) · 411 unmodified lines | ||
| 412 | 412 | *mac = NULL; |
| 413 | 413 | } |
| 414 | 414 | |
| 415 | − rc = of_get_phy_mode(np, &plat->phy_interface); | |
| 416 | − if (rc) | |
| 417 | − return ERR_PTR(rc); | |
| 415 | + plat->phy_interface = device_get_phy_mode(&pdev->dev); | |
| 416 | + if (plat->phy_interface < 0) | |
| 417 | + return ERR_PTR(plat->phy_interface); | |
| 418 | 418 | |
| 419 | 419 | plat->interface = stmmac_of_get_mac_mode(np); |
| 420 | 420 | if (plat->interface < 0) |
| @@ -804,19 +804,21 @@ static struct sock *gtp_encap_enable_socket(int fd, int type, · 803 unmodified lines | ||
| 804 | 804 | return NULL; |
| 805 | 805 | } |
| 806 | 806 | |
| 807 | − if (sock->sk->sk_protocol != IPPROTO_UDP) { | |
| 807 | + sk = sock->sk; | |
| 808 | + if (sk->sk_protocol != IPPROTO_UDP || | |
| 809 | + sk->sk_type != SOCK_DGRAM || | |
| 810 | + (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)) { | |
| 808 | 811 | pr_debug("socket fd=%d not UDP\n", fd); |
| 809 | 812 | sk = ERR_PTR(-EINVAL); |
| 810 | 813 | goto out_sock; |
| 811 | 814 | } |
| 812 | 815 | |
| 813 | − lock_sock(sock->sk); | |
| 814 | − if (sock->sk->sk_user_data) { | |
| 816 | + lock_sock(sk); | |
| 817 | + if (sk->sk_user_data) { | |
| 815 | 818 | sk = ERR_PTR(-EBUSY); |
| 816 | 819 | goto out_rel_sock; |
| 817 | 820 | } |
| 818 | 821 | |
| 819 | − sk = sock->sk; | |
| 820 | 822 | sock_hold(sk); |
| 821 | 823 | |
| 822 | 824 | tuncfg.sk_user_data = gtp; |
| @@ -452,9 +452,16 @@ static void slip_transmit(struct work_struct *work) · 451 unmodified lines | ||
| 452 | 452 | */ |
| 453 | 453 | static void slip_write_wakeup(struct tty_struct *tty) |
| 454 | 454 | { |
| 455 | − struct slip *sl = tty->disc_data; | |
| 455 | + struct slip *sl; | |
| 456 | + | |
| 457 | + rcu_read_lock(); | |
| 458 | + sl = rcu_dereference(tty->disc_data); | |
| 459 | + if (!sl) | |
| 460 | + goto out; | |
| 456 | 461 | |
| 457 | 462 | schedule_work(&sl->tx_work); |
| 463 | +out: | |
| 464 | + rcu_read_unlock(); | |
| 458 | 465 | } |
| 459 | 466 | |
| 460 | 467 | static void sl_tx_timeout(struct net_device *dev) |
| @@ -882,10 +889,11 @@ static void slip_close(struct tty_struct *tty) · 421 unmodified lines | ||
| 882 | 889 | return; |
| 883 | 890 | |
| 884 | 891 | spin_lock_bh(&sl->lock); |
| 885 | − tty->disc_data = NULL; | |
| 892 | + rcu_assign_pointer(tty->disc_data, NULL); | |
| 886 | 893 | sl->tty = NULL; |
| 887 | 894 | spin_unlock_bh(&sl->lock); |
| 888 | 895 | |
| 896 | + synchronize_rcu(); | |
| 889 | 897 | flush_work(&sl->tx_work); |
| 890 | 898 | |
| 891 | 899 | /* VSV = very important to remove timers */ |
| @@ -1936,6 +1936,10 @@ drop: · 1935 unmodified lines | ||
| 1936 | 1936 | if (ret != XDP_PASS) { |
| 1937 | 1937 | rcu_read_unlock(); |
| 1938 | 1938 | local_bh_enable(); |
| 1939 | + if (frags) { | |
| 1940 | + tfile->napi.skb = NULL; | |
| 1941 | + mutex_unlock(&tfile->napi_mutex); | |
| 1942 | + } | |
| 1939 | 1943 | return total_len; |
| 1940 | 1944 | } |
| 1941 | 1945 | } |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/mdio.h> |
| 21 | 21 | #include <linux/phy.h> |
| 22 | 22 | #include <net/ip6_checksum.h> |
| 23 | +#include <net/vxlan.h> | |
| 23 | 24 | #include <linux/interrupt.h> |
| 24 | 25 | #include <linux/irqdomain.h> |
| 25 | 26 | #include <linux/irq.h> |
| @@ -3668,6 +3669,19 @@ static void lan78xx_tx_timeout(struct net_device *net) · 3642 unmodified lines | ||
| 3668 | 3669 | tasklet_schedule(&dev->bh); |
| 3669 | 3670 | } |
| 3670 | 3671 | |
| 3672 | +static netdev_features_t lan78xx_features_check(struct sk_buff *skb, | |
| 3673 | + struct net_device *netdev, | |
| 3674 | + netdev_features_t features) | |
| 3675 | +{ | |
| 3676 | + if (skb->len + TX_OVERHEAD > MAX_SINGLE_PACKET_SIZE) | |
| 3677 | + features &= ~NETIF_F_GSO_MASK; | |
| 3678 | + | |
| 3679 | + features = vlan_features_check(skb, features); | |
| 3680 | + features = vxlan_features_check(skb, features); | |
| 3681 | + | |
| 3682 | + return features; | |
| 3683 | +} | |
| 3684 | + | |
| 3671 | 3685 | static const struct net_device_ops lan78xx_netdev_ops = { |
| 3672 | 3686 | .ndo_open = lan78xx_open, |
| 3673 | 3687 | .ndo_stop = lan78xx_stop, |
| @@ -3681,6 +3695,7 @@ static const struct net_device_ops lan78xx_netdev_ops = { · 7 unmodified lines | ||
| 3681 | 3695 | .ndo_set_features = lan78xx_set_features, |
| 3682 | 3696 | .ndo_vlan_rx_add_vid = lan78xx_vlan_rx_add_vid, |
| 3683 | 3697 | .ndo_vlan_rx_kill_vid = lan78xx_vlan_rx_kill_vid, |
| 3698 | + .ndo_features_check = lan78xx_features_check, | |
| 3684 | 3699 | }; |
| 3685 | 3700 | |
| 3686 | 3701 | static void lan78xx_stat_monitor(struct timer_list *t) |
| @@ -31,7 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | #define NETNEXT_VERSION "11" |
| 32 | 32 | |
| 33 | 33 | /* Information for net */ |
| 34 | −#define NET_VERSION "10" | |
| 34 | +#define NET_VERSION "11" | |
| 35 | 35 | |
| 36 | 36 | #define DRIVER_VERSION "v1." NETNEXT_VERSION "." NET_VERSION |
| 37 | 37 | #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" |
| @@ -68,6 +68,7 @@ · 30 unmodified lines | ||
| 68 | 68 | #define PLA_LED_FEATURE 0xdd92 |
| 69 | 69 | #define PLA_PHYAR 0xde00 |
| 70 | 70 | #define PLA_BOOT_CTRL 0xe004 |
| 71 | +#define PLA_LWAKE_CTRL_REG 0xe007 | |
| 71 | 72 | #define PLA_GPHY_INTR_IMR 0xe022 |
| 72 | 73 | #define PLA_EEE_CR 0xe040 |
| 73 | 74 | #define PLA_EEEP_CR 0xe080 |
| @@ -95,6 +96,7 @@ · 21 unmodified lines | ||
| 95 | 96 | #define PLA_TALLYCNT 0xe890 |
| 96 | 97 | #define PLA_SFF_STS_7 0xe8de |
| 97 | 98 | #define PLA_PHYSTATUS 0xe908 |
| 99 | +#define PLA_CONFIG6 0xe90a /* CONFIG6 */ | |
| 98 | 100 | #define PLA_BP_BA 0xfc26 |
| 99 | 101 | #define PLA_BP_0 0xfc28 |
| 100 | 102 | #define PLA_BP_1 0xfc2a |
| @@ -107,6 +109,7 @@ · 6 unmodified lines | ||
| 107 | 109 | #define PLA_BP_EN 0xfc38 |
| 108 | 110 | |
| 109 | 111 | #define USB_USB2PHY 0xb41e |
| 112 | +#define USB_SSPHYLINK1 0xb426 | |
| 110 | 113 | #define USB_SSPHYLINK2 0xb428 |
| 111 | 114 | #define USB_U2P3_CTRL 0xb460 |
| 112 | 115 | #define USB_CSR_DUMMY1 0xb464 |
| @@ -300,6 +303,9 @@ · 187 unmodified lines | ||
| 300 | 303 | #define LINK_ON_WAKE_EN 0x0010 |
| 301 | 304 | #define LINK_OFF_WAKE_EN 0x0008 |
| 302 | 305 | |
| 306 | +/* PLA_CONFIG6 */ | |
| 307 | +#define LANWAKE_CLR_EN BIT(0) | |
| 308 | + | |
| 303 | 309 | /* PLA_CONFIG5 */ |
| 304 | 310 | #define BWF_EN 0x0040 |
| 305 | 311 | #define MWF_EN 0x0020 |
| @@ -312,6 +318,7 @@ · 6 unmodified lines | ||
| 312 | 318 | /* PLA_PHY_PWR */ |
| 313 | 319 | #define TX_10M_IDLE_EN 0x0080 |
| 314 | 320 | #define PFM_PWM_SWITCH 0x0040 |
| 321 | +#define TEST_IO_OFF BIT(4) | |
| 315 | 322 | |
| 316 | 323 | /* PLA_MAC_PWR_CTRL */ |
| 317 | 324 | #define D3_CLK_GATED_EN 0x00004000 |
| @@ -324,6 +331,7 @@ · 6 unmodified lines | ||
| 324 | 331 | #define MAC_CLK_SPDWN_EN BIT(15) |
| 325 | 332 | |
| 326 | 333 | /* PLA_MAC_PWR_CTRL3 */ |
| 334 | +#define PLA_MCU_SPDWN_EN BIT(14) | |
| 327 | 335 | #define PKT_AVAIL_SPDWN_EN 0x0100 |
| 328 | 336 | #define SUSPEND_SPDWN_EN 0x0004 |
| 329 | 337 | #define U1U2_SPDWN_EN 0x0002 |
| @@ -354,6 +362,9 @@ · 24 unmodified lines | ||
| 354 | 362 | /* PLA_BOOT_CTRL */ |
| 355 | 363 | #define AUTOLOAD_DONE 0x0002 |
| 356 | 364 | |
| 365 | +/* PLA_LWAKE_CTRL_REG */ | |
| 366 | +#define LANWAKE_PIN BIT(7) | |
| 367 | + | |
| 357 | 368 | /* PLA_SUSPEND_FLAG */ |
| 358 | 369 | #define LINK_CHG_EVENT BIT(0) |
| 359 | 370 | |
| @@ -365,13 +376,18 @@ · 5 unmodified lines | ||
| 365 | 376 | #define DEBUG_LTSSM 0x0082 |
| 366 | 377 | |
| 367 | 378 | /* PLA_EXTRA_STATUS */ |
| 379 | +#define CUR_LINK_OK BIT(15) | |
| 368 | 380 | #define U3P3_CHECK_EN BIT(7) /* RTL_VER_05 only */ |
| 369 | 381 | #define LINK_CHANGE_FLAG BIT(8) |
| 382 | +#define POLL_LINK_CHG BIT(0) | |
| 370 | 383 | |
| 371 | 384 | /* USB_USB2PHY */ |
| 372 | 385 | #define USB2PHY_SUSPEND 0x0001 |
| 373 | 386 | #define USB2PHY_L1 0x0002 |
| 374 | 387 | |
| 388 | +/* USB_SSPHYLINK1 */ | |
| 389 | +#define DELAY_PHY_PWR_CHG BIT(1) | |
| 390 | + | |
| 375 | 391 | /* USB_SSPHYLINK2 */ |
| 376 | 392 | #define pwd_dn_scale_mask 0x3ffe |
| 377 | 393 | #define pwd_dn_scale(x) ((x) << 1) |
| @@ -2863,6 +2879,17 @@ static int rtl8153_enable(struct r8152 *tp) · 2485 unmodified lines | ||
| 2863 | 2879 | r8153_set_rx_early_timeout(tp); |
| 2864 | 2880 | r8153_set_rx_early_size(tp); |
| 2865 | 2881 | |
| 2882 | + if (tp->version == RTL_VER_09) { | |
| 2883 | + u32 ocp_data; | |
| 2884 | + | |
| 2885 | + ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK); | |
| 2886 | + ocp_data &= ~FC_PATCH_TASK; | |
| 2887 | + ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); | |
| 2888 | + usleep_range(1000, 2000); | |
| 2889 | + ocp_data |= FC_PATCH_TASK; | |
| 2890 | + ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); | |
| 2891 | + } | |
| 2892 | + | |
| 2866 | 2893 | return rtl_enable(tp); |
| 2867 | 2894 | } |
| 2868 | 2895 | |
| @@ -3376,8 +3403,8 @@ static void rtl8153b_runtime_enable(struct r8152 *tp, bool enable) · 507 unmodified lines | ||
| 3376 | 3403 | r8153b_ups_en(tp, false); |
| 3377 | 3404 | r8153_queue_wake(tp, false); |
| 3378 | 3405 | rtl_runtime_suspend_enable(tp, false); |
| 3379 | − r8153_u2p3en(tp, true); | |
| 3380 | − r8153b_u1u2en(tp, true); | |
| 3406 | + if (tp->udev->speed != USB_SPEED_HIGH) | |
| 3407 | + r8153b_u1u2en(tp, true); | |
| 3381 | 3408 | } |
| 3382 | 3409 | } |
| 3383 | 3410 | |
| @@ -4675,7 +4702,6 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) · 1291 unmodified lines | ||
| 4675 | 4702 | |
| 4676 | 4703 | r8153_aldps_en(tp, true); |
| 4677 | 4704 | r8152b_enable_fc(tp); |
| 4678 | − r8153_u2p3en(tp, true); | |
| 4679 | 4705 | |
| 4680 | 4706 | set_bit(PHY_RESET, &tp->flags); |
| 4681 | 4707 | } |
| @@ -4954,6 +4980,8 @@ static void rtl8152_down(struct r8152 *tp) · 272 unmodified lines | ||
| 4954 | 4980 | |
| 4955 | 4981 | static void rtl8153_up(struct r8152 *tp) |
| 4956 | 4982 | { |
| 4983 | + u32 ocp_data; | |
| 4984 | + | |
| 4957 | 4985 | if (test_bit(RTL8152_UNPLUG, &tp->flags)) |
| 4958 | 4986 | return; |
| 4959 | 4987 | |
| @@ -4961,6 +4989,19 @@ static void rtl8153_up(struct r8152 *tp) · 1 unmodified line | ||
| 4961 | 4989 | r8153_u2p3en(tp, false); |
| 4962 | 4990 | r8153_aldps_en(tp, false); |
| 4963 | 4991 | r8153_first_init(tp); |
| 4992 | + | |
| 4993 | + ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6); | |
| 4994 | + ocp_data |= LANWAKE_CLR_EN; | |
| 4995 | + ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6, ocp_data); | |
| 4996 | + | |
| 4997 | + ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG); | |
| 4998 | + ocp_data &= ~LANWAKE_PIN; | |
| 4999 | + ocp_write_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG, ocp_data); | |
| 5000 | + | |
| 5001 | + ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SSPHYLINK1); | |
| 5002 | + ocp_data &= ~DELAY_PHY_PWR_CHG; | |
| 5003 | + ocp_write_word(tp, MCU_TYPE_USB, USB_SSPHYLINK1, ocp_data); | |
| 5004 | + | |
| 4964 | 5005 | r8153_aldps_en(tp, true); |
| 4965 | 5006 | |
| 4966 | 5007 | switch (tp->version) { |
| @@ -4979,11 +5020,17 @@ static void rtl8153_up(struct r8152 *tp) · 12 unmodified lines | ||
| 4979 | 5020 | |
| 4980 | 5021 | static void rtl8153_down(struct r8152 *tp) |
| 4981 | 5022 | { |
| 5023 | + u32 ocp_data; | |
| 5024 | + | |
| 4982 | 5025 | if (test_bit(RTL8152_UNPLUG, &tp->flags)) { |
| 4983 | 5026 | rtl_drop_queued_tx(tp); |
| 4984 | 5027 | return; |
| 4985 | 5028 | } |
| 4986 | 5029 | |
| 5030 | + ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6); | |
| 5031 | + ocp_data &= ~LANWAKE_CLR_EN; | |
| 5032 | + ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6, ocp_data); | |
| 5033 | + | |
| 4987 | 5034 | r8153_u1u2en(tp, false); |
| 4988 | 5035 | r8153_u2p3en(tp, false); |
| 4989 | 5036 | r8153_power_cut_en(tp, false); |
| @@ -4994,6 +5041,8 @@ static void rtl8153_down(struct r8152 *tp) · 4 unmodified lines | ||
| 4994 | 5041 | |
| 4995 | 5042 | static void rtl8153b_up(struct r8152 *tp) |
| 4996 | 5043 | { |
| 5044 | + u32 ocp_data; | |
| 5045 | + | |
| 4997 | 5046 | if (test_bit(RTL8152_UNPLUG, &tp->flags)) |
| 4998 | 5047 | return; |
| 4999 | 5048 | |
| @@ -5004,18 +5053,29 @@ static void rtl8153b_up(struct r8152 *tp) · 4 unmodified lines | ||
| 5004 | 5053 | r8153_first_init(tp); |
| 5005 | 5054 | ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_B); |
| 5006 | 5055 | |
| 5056 | + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); | |
| 5057 | + ocp_data &= ~PLA_MCU_SPDWN_EN; | |
| 5058 | + ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); | |
| 5059 | + | |
| 5007 | 5060 | r8153_aldps_en(tp, true); |
| 5008 | − r8153_u2p3en(tp, true); | |
| 5009 | − r8153b_u1u2en(tp, true); | |
| 5061 | + | |
| 5062 | + if (tp->udev->speed != USB_SPEED_HIGH) | |
| 5063 | + r8153b_u1u2en(tp, true); | |
| 5010 | 5064 | } |
| 5011 | 5065 | |
| 5012 | 5066 | static void rtl8153b_down(struct r8152 *tp) |
| 5013 | 5067 | { |
| 5068 | + u32 ocp_data; | |
| 5069 | + | |
| 5014 | 5070 | if (test_bit(RTL8152_UNPLUG, &tp->flags)) { |
| 5015 | 5071 | rtl_drop_queued_tx(tp); |
| 5016 | 5072 | return; |
| 5017 | 5073 | } |
| 5018 | 5074 | |
| 5075 | + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); | |
| 5076 | + ocp_data |= PLA_MCU_SPDWN_EN; | |
| 5077 | + ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); | |
| 5078 | + | |
| 5019 | 5079 | r8153b_u1u2en(tp, false); |
| 5020 | 5080 | r8153_u2p3en(tp, false); |
| 5021 | 5081 | r8153b_power_cut_en(tp, false); |
| @@ -5387,6 +5447,16 @@ static void r8153_init(struct r8152 *tp) · 365 unmodified lines | ||
| 5387 | 5447 | else |
| 5388 | 5448 | ocp_data |= DYNAMIC_BURST; |
| 5389 | 5449 | ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1, ocp_data); |
| 5450 | + | |
| 5451 | + r8153_queue_wake(tp, false); | |
| 5452 | + | |
| 5453 | + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS); | |
| 5454 | + if (rtl8152_get_speed(tp) & LINK_STATUS) | |
| 5455 | + ocp_data |= CUR_LINK_OK; | |
| 5456 | + else | |
| 5457 | + ocp_data &= ~CUR_LINK_OK; | |
| 5458 | + ocp_data |= POLL_LINK_CHG; | |
| 5459 | + ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); | |
| 5390 | 5460 | } |
| 5391 | 5461 | |
| 5392 | 5462 | ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2); |
| @@ -5416,10 +5486,19 @@ static void r8153_init(struct r8152 *tp) · 23 unmodified lines | ||
| 5416 | 5486 | ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001); |
| 5417 | 5487 | |
| 5418 | 5488 | r8153_power_cut_en(tp, false); |
| 5489 | + rtl_runtime_suspend_enable(tp, false); | |
| 5419 | 5490 | r8153_u1u2en(tp, true); |
| 5420 | 5491 | r8153_mac_clk_spd(tp, false); |
| 5421 | 5492 | usb_enable_lpm(tp->udev); |
| 5422 | 5493 | |
| 5494 | + ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6); | |
| 5495 | + ocp_data |= LANWAKE_CLR_EN; | |
| 5496 | + ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6, ocp_data); | |
| 5497 | + | |
| 5498 | + ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG); | |
| 5499 | + ocp_data &= ~LANWAKE_PIN; | |
| 5500 | + ocp_write_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG, ocp_data); | |
| 5501 | + | |
| 5423 | 5502 | /* rx aggregation */ |
| 5424 | 5503 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); |
| 5425 | 5504 | ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); |
| @@ -5484,7 +5563,17 @@ static void r8153b_init(struct r8152 *tp) · 58 unmodified lines | ||
| 5484 | 5563 | r8153b_ups_en(tp, false); |
| 5485 | 5564 | r8153_queue_wake(tp, false); |
| 5486 | 5565 | rtl_runtime_suspend_enable(tp, false); |
| 5487 | − r8153b_u1u2en(tp, true); | |
| 5566 | + | |
| 5567 | + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS); | |
| 5568 | + if (rtl8152_get_speed(tp) & LINK_STATUS) | |
| 5569 | + ocp_data |= CUR_LINK_OK; | |
| 5570 | + else | |
| 5571 | + ocp_data &= ~CUR_LINK_OK; | |
| 5572 | + ocp_data |= POLL_LINK_CHG; | |
| 5573 | + ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); | |
| 5574 | + | |
| 5575 | + if (tp->udev->speed != USB_SPEED_HIGH) | |
| 5576 | + r8153b_u1u2en(tp, true); | |
| 5488 | 5577 | usb_enable_lpm(tp->udev); |
| 5489 | 5578 | |
| 5490 | 5579 | /* MAC clock speed down */ |
| @@ -5492,6 +5581,19 @@ static void r8153b_init(struct r8152 *tp) · 1 unmodified line | ||
| 5492 | 5581 | ocp_data |= MAC_CLK_SPDWN_EN; |
| 5493 | 5582 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); |
| 5494 | 5583 | |
| 5584 | + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); | |
| 5585 | + ocp_data &= ~PLA_MCU_SPDWN_EN; | |
| 5586 | + ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); | |
| 5587 | + | |
| 5588 | + if (tp->version == RTL_VER_09) { | |
| 5589 | + /* Disable Test IO for 32QFN */ | |
| 5590 | + if (ocp_read_byte(tp, MCU_TYPE_PLA, 0xdc00) & BIT(5)) { | |
| 5591 | + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR); | |
| 5592 | + ocp_data |= TEST_IO_OFF; | |
| 5593 | + ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); | |
| 5594 | + } | |
| 5595 | + } | |
| 5596 | + | |
| 5495 | 5597 | set_bit(GREEN_ETHERNET, &tp->flags); |
| 5496 | 5598 | |
| 5497 | 5599 | /* rx aggregation */ |
| @@ -6707,6 +6809,11 @@ static int rtl8152_probe(struct usb_interface *intf, · 1209 unmodified lines | ||
| 6707 | 6809 | |
| 6708 | 6810 | intf->needs_remote_wakeup = 1; |
| 6709 | 6811 | |
| 6812 | + if (!rtl_can_wakeup(tp)) | |
| 6813 | + __rtl_set_wol(tp, 0); | |
| 6814 | + else | |
| 6815 | + tp->saved_wolopts = __rtl_get_wol(tp); | |
| 6816 | + | |
| 6710 | 6817 | tp->rtl_ops.init(tp); |
| 6711 | 6818 | #if IS_BUILTIN(CONFIG_USB_RTL8152) |
| 6712 | 6819 | /* Retry in case request_firmware() is not ready yet. */ |
| @@ -6724,10 +6831,6 @@ static int rtl8152_probe(struct usb_interface *intf, · 11 unmodified lines | ||
| 6724 | 6831 | goto out1; |
| 6725 | 6832 | } |
| 6726 | 6833 | |
| 6727 | − if (!rtl_can_wakeup(tp)) | |
| 6728 | − __rtl_set_wol(tp, 0); | |
| 6729 | − | |
| 6730 | − tp->saved_wolopts = __rtl_get_wol(tp); | |
| 6731 | 6834 | if (tp->saved_wolopts) |
| 6732 | 6835 | device_set_wakeup_enable(&udev->dev, true); |
| 6733 | 6836 | else |
| @@ -7790,16 +7790,8 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { · 7789 unmodified lines | ||
| 7790 | 7790 | case AIROGVLIST: ridcode = RID_APLIST; break; |
| 7791 | 7791 | case AIROGDRVNAM: ridcode = RID_DRVNAME; break; |
| 7792 | 7792 | case AIROGEHTENC: ridcode = RID_ETHERENCAP; break; |
| 7793 | − case AIROGWEPKTMP: ridcode = RID_WEP_TEMP; | |
| 7794 | − /* Only super-user can read WEP keys */ | |
| 7795 | − if (!capable(CAP_NET_ADMIN)) | |
| 7796 | − return -EPERM; | |
| 7797 | − break; | |
| 7798 | − case AIROGWEPKNV: ridcode = RID_WEP_PERM; | |
| 7799 | − /* Only super-user can read WEP keys */ | |
| 7800 | − if (!capable(CAP_NET_ADMIN)) | |
| 7801 | − return -EPERM; | |
| 7802 | − break; | |
| 7793 | + case AIROGWEPKTMP: ridcode = RID_WEP_TEMP; break; | |
| 7794 | + case AIROGWEPKNV: ridcode = RID_WEP_PERM; break; | |
| 7803 | 7795 | case AIROGSTAT: ridcode = RID_STATUS; break; |
| 7804 | 7796 | case AIROGSTATSD32: ridcode = RID_STATSDELTA; break; |
| 7805 | 7797 | case AIROGSTATSC32: ridcode = RID_STATS; break; |
| @@ -7813,7 +7805,13 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { · 7 unmodified lines | ||
| 7813 | 7805 | return -EINVAL; |
| 7814 | 7806 | } |
| 7815 | 7807 | |
| 7816 | − if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL) | |
| 7808 | + if (ridcode == RID_WEP_TEMP || ridcode == RID_WEP_PERM) { | |
| 7809 | + /* Only super-user can read WEP keys */ | |
| 7810 | + if (!capable(CAP_NET_ADMIN)) | |
| 7811 | + return -EPERM; | |
| 7812 | + } | |
| 7813 | + | |
| 7814 | + if ((iobuf = kzalloc(RIDSIZE, GFP_KERNEL)) == NULL) | |
| 7817 | 7815 | return -ENOMEM; |
| 7818 | 7816 | |
| 7819 | 7817 | PC4500_readrid(ai,ridcode,iobuf,RIDSIZE, 1); |
| @@ -267,7 +267,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, · 266 unmodified lines | ||
| 267 | 267 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 268 | 268 | struct iwl_station_priv *sta_priv = NULL; |
| 269 | 269 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
| 270 | − struct iwl_device_cmd *dev_cmd; | |
| 270 | + struct iwl_device_tx_cmd *dev_cmd; | |
| 271 | 271 | struct iwl_tx_cmd *tx_cmd; |
| 272 | 272 | __le16 fc; |
| 273 | 273 | u8 hdr_len; |
| @@ -348,7 +348,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, · 74 unmodified lines | ||
| 348 | 348 | if (unlikely(!dev_cmd)) |
| 349 | 349 | goto drop_unlock_priv; |
| 350 | 350 | |
| 351 | − memset(dev_cmd, 0, sizeof(*dev_cmd)); | |
| 352 | 351 | dev_cmd->hdr.cmd = REPLY_TX; |
| 353 | 352 | tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload; |
| 354 | 353 | |
| @@ -357,8 +357,8 @@ int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt) · 356 unmodified lines | ||
| 357 | 357 | { |
| 358 | 358 | union acpi_object *wifi_pkg, *data; |
| 359 | 359 | bool enabled; |
| 360 | − int i, n_profiles, tbl_rev; | |
| 361 | − int ret = 0; | |
| 360 | + int i, n_profiles, tbl_rev, pos; | |
| 361 | + int ret = 0; | |
| 362 | 362 | |
| 363 | 363 | data = iwl_acpi_get_object(fwrt->dev, ACPI_EWRD_METHOD); |
| 364 | 364 | if (IS_ERR(data)) |
| @@ -390,10 +390,10 @@ int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt) · 25 unmodified lines | ||
| 390 | 390 | goto out_free; |
| 391 | 391 | } |
| 392 | 392 | |
| 393 | − for (i = 0; i < n_profiles; i++) { | |
| 394 | − /* the tables start at element 3 */ | |
| 395 | − int pos = 3; | |
| 393 | + /* the tables start at element 3 */ | |
| 394 | + pos = 3; | |
| 396 | 395 | |
| 396 | + for (i = 0; i < n_profiles; i++) { | |
| 397 | 397 | /* The EWRD profiles officially go from 2 to 4, but we |
| 398 | 398 | * save them in sar_profiles[1-3] (because we don't |
| 399 | 399 | * have profile 0). So in the array we start from 1. |
| @@ -2669,12 +2669,7 @@ int iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt, · 2668 unmodified lines | ||
| 2669 | 2669 | { |
| 2670 | 2670 | int ret = 0; |
| 2671 | 2671 | |
| 2672 | − /* if the FW crashed or not debug monitor cfg was given, there is | |
| 2673 | − * no point in changing the recording state | |
| 2674 | − */ | |
| 2675 | − if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status) || | |
| 2676 | − (!fwrt->trans->dbg.dest_tlv && | |
| 2677 | − fwrt->trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID)) | |
| 2672 | + if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) | |
| 2678 | 2673 | return 0; |
| 2679 | 2674 | |
| 2680 | 2675 | if (fw_has_capa(&fwrt->fw->ucode_capa, |
| @@ -379,7 +379,7 @@ enum { · 378 unmodified lines | ||
| 379 | 379 | |
| 380 | 380 | |
| 381 | 381 | /* CSR GIO */ |
| 382 | −#define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002) | |
| 382 | +#define CSR_GIO_REG_VAL_L0S_DISABLED (0x00000002) | |
| 383 | 383 | |
| 384 | 384 | /* |
| 385 | 385 | * UCODE-DRIVER GP (general purpose) mailbox register 1 |
| @@ -480,7 +480,14 @@ static int iwl_dbg_tlv_alloc_fragment(struct iwl_fw_runtime *fwrt, · 479 unmodified lines | ||
| 480 | 480 | if (!frag || frag->size || !pages) |
| 481 | 481 | return -EIO; |
| 482 | 482 | |
| 483 | − while (pages) { | |
| 483 | + /* | |
| 484 | + * We try to allocate as many pages as we can, starting with | |
| 485 | + * the requested amount and going down until we can allocate | |
| 486 | + * something. Because of DIV_ROUND_UP(), pages will never go | |
| 487 | + * down to 0 and stop the loop, so stop when pages reaches 1, | |
| 488 | + * which is too small anyway. | |
| 489 | + */ | |
| 490 | + while (pages > 1) { | |
| 484 | 491 | block = dma_alloc_coherent(fwrt->dev, pages * PAGE_SIZE, |
| 485 | 492 | &physical, |
| 486 | 493 | GFP_KERNEL | __GFP_NOWARN); |
| @@ -1817,9 +1817,6 @@ MODULE_PARM_DESC(antenna_coupling, · 1816 unmodified lines | ||
| 1817 | 1817 | module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, 0444); |
| 1818 | 1818 | MODULE_PARM_DESC(nvm_file, "NVM file name"); |
| 1819 | 1819 | |
| 1820 | −module_param_named(lar_disable, iwlwifi_mod_params.lar_disable, bool, 0444); | |
| 1821 | −MODULE_PARM_DESC(lar_disable, "disable LAR functionality (default: N)"); | |
| 1822 | − | |
| 1823 | 1820 | module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable, uint, 0644); |
| 1824 | 1821 | MODULE_PARM_DESC(uapsd_disable, |
| 1825 | 1822 | "disable U-APSD functionality bitmap 1: BSS 2: P2P Client (default: 3)"); |
| @@ -115,7 +115,6 @@ enum iwl_uapsd_disable { · 114 unmodified lines | ||
| 115 | 115 | * @nvm_file: specifies a external NVM file |
| 116 | 116 | * @uapsd_disable: disable U-APSD, see &enum iwl_uapsd_disable, default = |
| 117 | 117 | * IWL_DISABLE_UAPSD_BSS | IWL_DISABLE_UAPSD_P2P_CLIENT |
| 118 | − * @lar_disable: disable LAR (regulatory), default = 0 | |
| 119 | 118 | * @fw_monitor: allow to use firmware monitor |
| 120 | 119 | * @disable_11ac: disable VHT capabilities, default = false. |
| 121 | 120 | * @remove_when_gone: remove an inaccessible device from the PCIe bus. |
| @@ -136,7 +135,6 @@ struct iwl_mod_params { · 14 unmodified lines | ||
| 136 | 135 | int antenna_coupling; |
| 137 | 136 | char *nvm_file; |
| 138 | 137 | u32 uapsd_disable; |
| 139 | − bool lar_disable; | |
| 140 | 138 | bool fw_monitor; |
| 141 | 139 | bool disable_11ac; |
| 142 | 140 | /** |
| @@ -224,6 +224,34 @@ enum iwl_nvm_channel_flags { · 223 unmodified lines | ||
| 224 | 224 | NVM_CHANNEL_DC_HIGH = BIT(12), |
| 225 | 225 | }; |
| 226 | 226 | |
| 227 | +/** | |
| 228 | + * enum iwl_reg_capa_flags - global flags applied for the whole regulatory | |
| 229 | + * domain. | |
| 230 | + * @REG_CAPA_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the | |
| 231 | + * 2.4Ghz band is allowed. | |
| 232 | + * @REG_CAPA_BF_CCD_HIGH_BAND: Beam-forming or Cyclic Delay Diversity in the | |
| 233 | + * 5Ghz band is allowed. | |
| 234 | + * @REG_CAPA_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed | |
| 235 | + * for this regulatory domain (valid only in 5Ghz). | |
| 236 | + * @REG_CAPA_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed | |
| 237 | + * for this regulatory domain (valid only in 5Ghz). | |
| 238 | + * @REG_CAPA_MCS_8_ALLOWED: 11ac with MCS 8 is allowed. | |
| 239 | + * @REG_CAPA_MCS_9_ALLOWED: 11ac with MCS 9 is allowed. | |
| 240 | + * @REG_CAPA_40MHZ_FORBIDDEN: 11n channel with a width of 40Mhz is forbidden | |
| 241 | + * for this regulatory domain (valid only in 5Ghz). | |
| 242 | + * @REG_CAPA_DC_HIGH_ENABLED: DC HIGH allowed. | |
| 243 | + */ | |
| 244 | +enum iwl_reg_capa_flags { | |
| 245 | + REG_CAPA_BF_CCD_LOW_BAND = BIT(0), | |
| 246 | + REG_CAPA_BF_CCD_HIGH_BAND = BIT(1), | |
| 247 | + REG_CAPA_160MHZ_ALLOWED = BIT(2), | |
| 248 | + REG_CAPA_80MHZ_ALLOWED = BIT(3), | |
| 249 | + REG_CAPA_MCS_8_ALLOWED = BIT(4), | |
| 250 | + REG_CAPA_MCS_9_ALLOWED = BIT(5), | |
| 251 | + REG_CAPA_40MHZ_FORBIDDEN = BIT(7), | |
| 252 | + REG_CAPA_DC_HIGH_ENABLED = BIT(9), | |
| 253 | +}; | |
| 254 | + | |
| 227 | 255 | static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level, |
| 228 | 256 | int chan, u32 flags) |
| 229 | 257 | { |
| @@ -939,10 +967,11 @@ iwl_nvm_no_wide_in_5ghz(struct iwl_trans *trans, const struct iwl_cfg *cfg, · 709 unmodified lines | ||
| 939 | 967 | |
| 940 | 968 | struct iwl_nvm_data * |
| 941 | 969 | iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, |
| 970 | + const struct iwl_fw *fw, | |
| 942 | 971 | const __be16 *nvm_hw, const __le16 *nvm_sw, |
| 943 | 972 | const __le16 *nvm_calib, const __le16 *regulatory, |
| 944 | 973 | const __le16 *mac_override, const __le16 *phy_sku, |
| 945 | − u8 tx_chains, u8 rx_chains, bool lar_fw_supported) | |
| 974 | + u8 tx_chains, u8 rx_chains) | |
| 946 | 975 | { |
| 947 | 976 | struct iwl_nvm_data *data; |
| 948 | 977 | bool lar_enabled; |
| @@ -1022,7 +1051,8 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, · 73 unmodified lines | ||
| 1022 | 1051 | return NULL; |
| 1023 | 1052 | } |
| 1024 | 1053 | |
| 1025 | − if (lar_fw_supported && lar_enabled) | |
| 1054 | + if (lar_enabled && | |
| 1055 | + fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_LAR_SUPPORT)) | |
| 1026 | 1056 | sbands_flags |= IWL_NVM_SBANDS_FLAGS_LAR; |
| 1027 | 1057 | |
| 1028 | 1058 | if (iwl_nvm_no_wide_in_5ghz(trans, cfg, nvm_hw)) |
| @@ -1038,6 +1068,7 @@ IWL_EXPORT_SYMBOL(iwl_parse_nvm_data); · 9 unmodified lines | ||
| 1038 | 1068 | |
| 1039 | 1069 | static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan, |
| 1040 | 1070 | int ch_idx, u16 nvm_flags, |
| 1071 | + u16 cap_flags, | |
| 1041 | 1072 | const struct iwl_cfg *cfg) |
| 1042 | 1073 | { |
| 1043 | 1074 | u32 flags = NL80211_RRF_NO_HT40; |
| @@ -1076,13 +1107,27 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan, · 32 unmodified lines | ||
| 1076 | 1107 | (flags & NL80211_RRF_NO_IR)) |
| 1077 | 1108 | flags |= NL80211_RRF_GO_CONCURRENT; |
| 1078 | 1109 | |
| 1110 | + /* | |
| 1111 | + * cap_flags is per regulatory domain so apply it for every channel | |
| 1112 | + */ | |
| 1113 | + if (ch_idx >= NUM_2GHZ_CHANNELS) { | |
| 1114 | + if (cap_flags & REG_CAPA_40MHZ_FORBIDDEN) | |
| 1115 | + flags |= NL80211_RRF_NO_HT40; | |
| 1116 | + | |
| 1117 | + if (!(cap_flags & REG_CAPA_80MHZ_ALLOWED)) | |
| 1118 | + flags |= NL80211_RRF_NO_80MHZ; | |
| 1119 | + | |
| 1120 | + if (!(cap_flags & REG_CAPA_160MHZ_ALLOWED)) | |
| 1121 | + flags |= NL80211_RRF_NO_160MHZ; | |
| 1122 | + } | |
| 1123 | + | |
| 1079 | 1124 | return flags; |
| 1080 | 1125 | } |
| 1081 | 1126 | |
| 1082 | 1127 | struct ieee80211_regdomain * |
| 1083 | 1128 | iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, |
| 1084 | 1129 | int num_of_ch, __le32 *channels, u16 fw_mcc, |
| 1085 | − u16 geo_info) | |
| 1130 | + u16 geo_info, u16 cap) | |
| 1086 | 1131 | { |
| 1087 | 1132 | int ch_idx; |
| 1088 | 1133 | u16 ch_flags; |
| @@ -1140,7 +1185,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, · 51 unmodified lines | ||
| 1140 | 1185 | } |
| 1141 | 1186 | |
| 1142 | 1187 | reg_rule_flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx, |
| 1143 | − ch_flags, cfg); | |
| 1188 | + ch_flags, cap, | |
| 1189 | + cfg); | |
| 1144 | 1190 | |
| 1145 | 1191 | /* we can't continue the same rule */ |
| 1146 | 1192 | if (ch_idx == 0 || prev_reg_rule_flags != reg_rule_flags || |
| @@ -1405,9 +1451,6 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, · 258 unmodified lines | ||
| 1405 | 1451 | .id = WIDE_ID(REGULATORY_AND_NVM_GROUP, NVM_GET_INFO) |
| 1406 | 1452 | }; |
| 1407 | 1453 | int ret; |
| 1408 | − bool lar_fw_supported = !iwlwifi_mod_params.lar_disable && | |
| 1409 | − fw_has_capa(&fw->ucode_capa, | |
| 1410 | − IWL_UCODE_TLV_CAPA_LAR_SUPPORT); | |
| 1411 | 1454 | bool empty_otp; |
| 1412 | 1455 | u32 mac_flags; |
| 1413 | 1456 | u32 sbands_flags = 0; |
| @@ -1485,7 +1528,9 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, · 71 unmodified lines | ||
| 1485 | 1528 | nvm->valid_tx_ant = (u8)le32_to_cpu(rsp->phy_sku.tx_chains); |
| 1486 | 1529 | nvm->valid_rx_ant = (u8)le32_to_cpu(rsp->phy_sku.rx_chains); |
| 1487 | 1530 | |
| 1488 | − if (le32_to_cpu(rsp->regulatory.lar_enabled) && lar_fw_supported) { | |
| 1531 | + if (le32_to_cpu(rsp->regulatory.lar_enabled) && | |
| 1532 | + fw_has_capa(&fw->ucode_capa, | |
| 1533 | + IWL_UCODE_TLV_CAPA_LAR_SUPPORT)) { | |
| 1489 | 1534 | nvm->lar_enabled = true; |
| 1490 | 1535 | sbands_flags |= IWL_NVM_SBANDS_FLAGS_LAR; |
| 1491 | 1536 | } |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | * |
| 8 | 8 | * Copyright(c) 2008 - 2015 Intel Corporation. All rights reserved. |
| 9 | 9 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 10 | − * Copyright(c) 2018 Intel Corporation | |
| 10 | + * Copyright(c) 2018 - 2019 Intel Corporation | |
| 11 | 11 | * |
| 12 | 12 | * This program is free software; you can redistribute it and/or modify |
| 13 | 13 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -29,7 +29,7 @@ · 15 unmodified lines | ||
| 29 | 29 | * |
| 30 | 30 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 31 | 31 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 32 | − * Copyright(c) 2018 Intel Corporation | |
| 32 | + * Copyright(c) 2018 - 2019 Intel Corporation | |
| 33 | 33 | * All rights reserved. |
| 34 | 34 | * |
| 35 | 35 | * Redistribution and use in source and binary forms, with or without |
| @@ -85,10 +85,11 @@ enum iwl_nvm_sbands_flags { · 49 unmodified lines | ||
| 85 | 85 | */ |
| 86 | 86 | struct iwl_nvm_data * |
| 87 | 87 | iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, |
| 88 | + const struct iwl_fw *fw, | |
| 88 | 89 | const __be16 *nvm_hw, const __le16 *nvm_sw, |
| 89 | 90 | const __le16 *nvm_calib, const __le16 *regulatory, |
| 90 | 91 | const __le16 *mac_override, const __le16 *phy_sku, |
| 91 | − u8 tx_chains, u8 rx_chains, bool lar_fw_supported); | |
| 92 | + u8 tx_chains, u8 rx_chains); | |
| 92 | 93 | |
| 93 | 94 | /** |
| 94 | 95 | * iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW |
| @@ -103,7 +104,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, · 8 unmodified lines | ||
| 103 | 104 | struct ieee80211_regdomain * |
| 104 | 105 | iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, |
| 105 | 106 | int num_of_ch, __le32 *channels, u16 fw_mcc, |
| 106 | − u16 geo_info); | |
| 107 | + u16 geo_info, u16 cap); | |
| 107 | 108 | |
| 108 | 109 | /** |
| 109 | 110 | * struct iwl_nvm_section - describes an NVM section in memory. |
| @@ -66,7 +66,9 @@ · 65 unmodified lines | ||
| 66 | 66 | |
| 67 | 67 | struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, |
| 68 | 68 | struct device *dev, |
| 69 | − const struct iwl_trans_ops *ops) | |
| 69 | + const struct iwl_trans_ops *ops, | |
| 70 | + unsigned int cmd_pool_size, | |
| 71 | + unsigned int cmd_pool_align) | |
| 70 | 72 | { |
| 71 | 73 | struct iwl_trans *trans; |
| 72 | 74 | #ifdef CONFIG_LOCKDEP |
| @@ -90,10 +92,8 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, · 17 unmodified lines | ||
| 90 | 92 | "iwl_cmd_pool:%s", dev_name(trans->dev)); |
| 91 | 93 | trans->dev_cmd_pool = |
| 92 | 94 | kmem_cache_create(trans->dev_cmd_pool_name, |
| 93 | − sizeof(struct iwl_device_cmd), | |
| 94 | − sizeof(void *), | |
| 95 | − SLAB_HWCACHE_ALIGN, | |
| 96 | − NULL); | |
| 95 | + cmd_pool_size, cmd_pool_align, | |
| 96 | + SLAB_HWCACHE_ALIGN, NULL); | |
| 97 | 97 | if (!trans->dev_cmd_pool) |
| 98 | 98 | return NULL; |
| 99 | 99 | |
| @@ -193,6 +193,18 @@ struct iwl_device_cmd { · 192 unmodified lines | ||
| 193 | 193 | }; |
| 194 | 194 | } __packed; |
| 195 | 195 | |
| 196 | +/** | |
| 197 | + * struct iwl_device_tx_cmd - buffer for TX command | |
| 198 | + * @hdr: the header | |
| 199 | + * @payload: the payload placeholder | |
| 200 | + * | |
| 201 | + * The actual structure is sized dynamically according to need. | |
| 202 | + */ | |
| 203 | +struct iwl_device_tx_cmd { | |
| 204 | + struct iwl_cmd_header hdr; | |
| 205 | + u8 payload[]; | |
| 206 | +} __packed; | |
| 207 | + | |
| 196 | 208 | #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) |
| 197 | 209 | |
| 198 | 210 | /* |
| @@ -544,7 +556,7 @@ struct iwl_trans_ops { · 345 unmodified lines | ||
| 544 | 556 | int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); |
| 545 | 557 | |
| 546 | 558 | int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, |
| 547 | − struct iwl_device_cmd *dev_cmd, int queue); | |
| 559 | + struct iwl_device_tx_cmd *dev_cmd, int queue); | |
| 548 | 560 | void (*reclaim)(struct iwl_trans *trans, int queue, int ssn, |
| 549 | 561 | struct sk_buff_head *skbs); |
| 550 | 562 | |
| @@ -948,22 +960,22 @@ iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask) · 397 unmodified lines | ||
| 948 | 960 | return trans->ops->dump_data(trans, dump_mask); |
| 949 | 961 | } |
| 950 | 962 | |
| 951 | −static inline struct iwl_device_cmd * | |
| 963 | +static inline struct iwl_device_tx_cmd * | |
| 952 | 964 | iwl_trans_alloc_tx_cmd(struct iwl_trans *trans) |
| 953 | 965 | { |
| 954 | − return kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC); | |
| 966 | + return kmem_cache_zalloc(trans->dev_cmd_pool, GFP_ATOMIC); | |
| 955 | 967 | } |
| 956 | 968 | |
| 957 | 969 | int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); |
| 958 | 970 | |
| 959 | 971 | static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans, |
| 960 | − struct iwl_device_cmd *dev_cmd) | |
| 972 | + struct iwl_device_tx_cmd *dev_cmd) | |
| 961 | 973 | { |
| 962 | 974 | kmem_cache_free(trans->dev_cmd_pool, dev_cmd); |
| 963 | 975 | } |
| 964 | 976 | |
| 965 | 977 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, |
| 966 | − struct iwl_device_cmd *dev_cmd, int queue) | |
| 978 | + struct iwl_device_tx_cmd *dev_cmd, int queue) | |
| 967 | 979 | { |
| 968 | 980 | if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) |
| 969 | 981 | return -EIO; |
| @@ -1271,7 +1283,9 @@ static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans) · 301 unmodified lines | ||
| 1271 | 1283 | *****************************************************/ |
| 1272 | 1284 | struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, |
| 1273 | 1285 | struct device *dev, |
| 1274 | − const struct iwl_trans_ops *ops); | |
| 1286 | + const struct iwl_trans_ops *ops, | |
| 1287 | + unsigned int cmd_pool_size, | |
| 1288 | + unsigned int cmd_pool_align); | |
| 1275 | 1289 | void iwl_trans_free(struct iwl_trans *trans); |
| 1276 | 1290 | |
| 1277 | 1291 | /***************************************************** |
| @@ -154,5 +154,6 @@ · 153 unmodified lines | ||
| 154 | 154 | #define IWL_MVM_D3_DEBUG false |
| 155 | 155 | #define IWL_MVM_USE_TWT false |
| 156 | 156 | #define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 10 |
| 157 | +#define IWL_MVM_USE_NSSN_SYNC 0 | |
| 157 | 158 | |
| 158 | 159 | #endif /* __MVM_CONSTANTS_H */ |
| @@ -841,9 +841,13 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) · 840 unmodified lines | ||
| 841 | 841 | return 0; |
| 842 | 842 | } |
| 843 | 843 | |
| 844 | + if (!mvm->fwrt.ppag_table.enabled) { | |
| 845 | + IWL_DEBUG_RADIO(mvm, | |
| 846 | + "PPAG not enabled, command not sent.\n"); | |
| 847 | + return 0; | |
| 848 | + } | |
| 849 | + | |
| 844 | 850 | IWL_DEBUG_RADIO(mvm, "Sending PER_PLATFORM_ANT_GAIN_CMD\n"); |
| 845 | − IWL_DEBUG_RADIO(mvm, "PPAG is %s\n", | |
| 846 | − mvm->fwrt.ppag_table.enabled ? "enabled" : "disabled"); | |
| 847 | 851 | |
| 848 | 852 | for (i = 0; i < ACPI_PPAG_NUM_CHAINS; i++) { |
| 849 | 853 | for (j = 0; j < ACPI_PPAG_NUM_SUB_BANDS; j++) { |
| @@ -256,7 +256,8 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, · 255 unmodified lines | ||
| 256 | 256 | __le32_to_cpu(resp->n_channels), |
| 257 | 257 | resp->channels, |
| 258 | 258 | __le16_to_cpu(resp->mcc), |
| 259 | − __le16_to_cpu(resp->geo_info)); | |
| 259 | + __le16_to_cpu(resp->geo_info), | |
| 260 | + __le16_to_cpu(resp->cap)); | |
| 260 | 261 | /* Store the return source id */ |
| 261 | 262 | src_id = resp->source_id; |
| 262 | 263 | kfree(resp); |
| @@ -754,6 +755,20 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) · 491 unmodified lines | ||
| 754 | 755 | return ret; |
| 755 | 756 | } |
| 756 | 757 | |
| 758 | +static void iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |
| 759 | + struct ieee80211_sta *sta) | |
| 760 | +{ | |
| 761 | + if (likely(sta)) { | |
| 762 | + if (likely(iwl_mvm_tx_skb_sta(mvm, skb, sta) == 0)) | |
| 763 | + return; | |
| 764 | + } else { | |
| 765 | + if (likely(iwl_mvm_tx_skb_non_sta(mvm, skb) == 0)) | |
| 766 | + return; | |
| 767 | + } | |
| 768 | + | |
| 769 | + ieee80211_free_txskb(mvm->hw, skb); | |
| 770 | +} | |
| 771 | + | |
| 757 | 772 | static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, |
| 758 | 773 | struct ieee80211_tx_control *control, |
| 759 | 774 | struct sk_buff *skb) |
| @@ -797,14 +812,7 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, · 37 unmodified lines | ||
| 797 | 812 | } |
| 798 | 813 | } |
| 799 | 814 | |
| 800 | − if (sta) { | |
| 801 | − if (iwl_mvm_tx_skb(mvm, skb, sta)) | |
| 802 | − goto drop; | |
| 803 | − return; | |
| 804 | − } | |
| 805 | − | |
| 806 | − if (iwl_mvm_tx_skb_non_sta(mvm, skb)) | |
| 807 | − goto drop; | |
| 815 | + iwl_mvm_tx_skb(mvm, skb, sta); | |
| 808 | 816 | return; |
| 809 | 817 | drop: |
| 810 | 818 | ieee80211_free_txskb(hw, skb); |
| @@ -854,10 +862,7 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq) · 43 unmodified lines | ||
| 854 | 862 | break; |
| 855 | 863 | } |
| 856 | 864 | |
| 857 | − if (!txq->sta) | |
| 858 | − iwl_mvm_tx_skb_non_sta(mvm, skb); | |
| 859 | − else | |
| 860 | − iwl_mvm_tx_skb(mvm, skb, txq->sta); | |
| 865 | + iwl_mvm_tx_skb(mvm, skb, txq->sta); | |
| 861 | 866 | } |
| 862 | 867 | } while (atomic_dec_return(&mvmtxq->tx_request)); |
| 863 | 868 | rcu_read_unlock(); |
| @@ -4771,6 +4776,125 @@ static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx, · 3907 unmodified lines | ||
| 4771 | 4776 | return ret; |
| 4772 | 4777 | } |
| 4773 | 4778 | |
| 4779 | +static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo) | |
| 4780 | +{ | |
| 4781 | + switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { | |
| 4782 | + case RATE_MCS_CHAN_WIDTH_20: | |
| 4783 | + rinfo->bw = RATE_INFO_BW_20; | |
| 4784 | + break; | |
| 4785 | + case RATE_MCS_CHAN_WIDTH_40: | |
| 4786 | + rinfo->bw = RATE_INFO_BW_40; | |
| 4787 | + break; | |
| 4788 | + case RATE_MCS_CHAN_WIDTH_80: | |
| 4789 | + rinfo->bw = RATE_INFO_BW_80; | |
| 4790 | + break; | |
| 4791 | + case RATE_MCS_CHAN_WIDTH_160: | |
| 4792 | + rinfo->bw = RATE_INFO_BW_160; | |
| 4793 | + break; | |
| 4794 | + } | |
| 4795 | + | |
| 4796 | + if (rate_n_flags & RATE_MCS_HT_MSK) { | |
| 4797 | + rinfo->flags |= RATE_INFO_FLAGS_MCS; | |
| 4798 | + rinfo->mcs = u32_get_bits(rate_n_flags, RATE_HT_MCS_INDEX_MSK); | |
| 4799 | + rinfo->nss = u32_get_bits(rate_n_flags, | |
| 4800 | + RATE_HT_MCS_NSS_MSK) + 1; | |
| 4801 | + if (rate_n_flags & RATE_MCS_SGI_MSK) | |
| 4802 | + rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | |
| 4803 | + } else if (rate_n_flags & RATE_MCS_VHT_MSK) { | |
| 4804 | + rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS; | |
| 4805 | + rinfo->mcs = u32_get_bits(rate_n_flags, | |
| 4806 | + RATE_VHT_MCS_RATE_CODE_MSK); | |
| 4807 | + rinfo->nss = u32_get_bits(rate_n_flags, | |
| 4808 | + RATE_VHT_MCS_NSS_MSK) + 1; | |
| 4809 | + if (rate_n_flags & RATE_MCS_SGI_MSK) | |
| 4810 | + rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | |
| 4811 | + } else if (rate_n_flags & RATE_MCS_HE_MSK) { | |
| 4812 | + u32 gi_ltf = u32_get_bits(rate_n_flags, | |
| 4813 | + RATE_MCS_HE_GI_LTF_MSK); | |
| 4814 | + | |
| 4815 | + rinfo->flags |= RATE_INFO_FLAGS_HE_MCS; | |
| 4816 | + rinfo->mcs = u32_get_bits(rate_n_flags, | |
| 4817 | + RATE_VHT_MCS_RATE_CODE_MSK); | |
| 4818 | + rinfo->nss = u32_get_bits(rate_n_flags, | |
| 4819 | + RATE_VHT_MCS_NSS_MSK) + 1; | |
| 4820 | + | |
| 4821 | + if (rate_n_flags & RATE_MCS_HE_106T_MSK) { | |
| 4822 | + rinfo->bw = RATE_INFO_BW_HE_RU; | |
| 4823 | + rinfo->he_ru_alloc = NL80211_RATE_INFO_HE_RU_ALLOC_106; | |
| 4824 | + } | |
| 4825 | + | |
| 4826 | + switch (rate_n_flags & RATE_MCS_HE_TYPE_MSK) { | |
| 4827 | + case RATE_MCS_HE_TYPE_SU: | |
| 4828 | + case RATE_MCS_HE_TYPE_EXT_SU: | |
| 4829 | + if (gi_ltf == 0 || gi_ltf == 1) | |
| 4830 | + rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8; | |
| 4831 | + else if (gi_ltf == 2) | |
| 4832 | + rinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6; | |
| 4833 | + else if (rate_n_flags & RATE_MCS_SGI_MSK) | |
| 4834 | + rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8; | |
| 4835 | + else | |
| 4836 | + rinfo->he_gi = NL80211_RATE_INFO_HE_GI_3_2; | |
| 4837 | + break; | |
| 4838 | + case RATE_MCS_HE_TYPE_MU: | |
| 4839 | + if (gi_ltf == 0 || gi_ltf == 1) | |
| 4840 | + rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8; | |
| 4841 | + else if (gi_ltf == 2) | |
| 4842 | + rinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6; | |
| 4843 | + else | |
| 4844 | + rinfo->he_gi = NL80211_RATE_INFO_HE_GI_3_2; | |
| 4845 | + break; | |
| 4846 | + case RATE_MCS_HE_TYPE_TRIG: | |
| 4847 | + if (gi_ltf == 0 || gi_ltf == 1) | |
| 4848 | + rinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6; | |
| 4849 | + else | |
| 4850 | + rinfo->he_gi = NL80211_RATE_INFO_HE_GI_3_2; | |
| 4851 | + break; | |
| 4852 | + } | |
| 4853 | + | |
| 4854 | + if (rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK) | |
| 4855 | + rinfo->he_dcm = 1; | |
| 4856 | + } else { | |
| 4857 | + switch (u32_get_bits(rate_n_flags, RATE_LEGACY_RATE_MSK)) { | |
| 4858 | + case IWL_RATE_1M_PLCP: | |
| 4859 | + rinfo->legacy = 10; | |
| 4860 | + break; | |
| 4861 | + case IWL_RATE_2M_PLCP: | |
| 4862 | + rinfo->legacy = 20; | |
| 4863 | + break; | |
| 4864 | + case IWL_RATE_5M_PLCP: | |
| 4865 | + rinfo->legacy = 55; | |
| 4866 | + break; | |
| 4867 | + case IWL_RATE_11M_PLCP: | |
| 4868 | + rinfo->legacy = 110; | |
| 4869 | + break; | |
| 4870 | + case IWL_RATE_6M_PLCP: | |
| 4871 | + rinfo->legacy = 60; | |
| 4872 | + break; | |
| 4873 | + case IWL_RATE_9M_PLCP: | |
| 4874 | + rinfo->legacy = 90; | |
| 4875 | + break; | |
| 4876 | + case IWL_RATE_12M_PLCP: | |
| 4877 | + rinfo->legacy = 120; | |
| 4878 | + break; | |
| 4879 | + case IWL_RATE_18M_PLCP: | |
| 4880 | + rinfo->legacy = 180; | |
| 4881 | + break; | |
| 4882 | + case IWL_RATE_24M_PLCP: | |
| 4883 | + rinfo->legacy = 240; | |
| 4884 | + break; | |
| 4885 | + case IWL_RATE_36M_PLCP: | |
| 4886 | + rinfo->legacy = 360; | |
| 4887 | + break; | |
| 4888 | + case IWL_RATE_48M_PLCP: | |
| 4889 | + rinfo->legacy = 480; | |
| 4890 | + break; | |
| 4891 | + case IWL_RATE_54M_PLCP: | |
| 4892 | + rinfo->legacy = 540; | |
| 4893 | + break; | |
| 4894 | + } | |
| 4895 | + } | |
| 4896 | +} | |
| 4897 | + | |
| 4774 | 4898 | static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw, |
| 4775 | 4899 | struct ieee80211_vif *vif, |
| 4776 | 4900 | struct ieee80211_sta *sta, |
| @@ -4785,6 +4909,13 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw, · 8 unmodified lines | ||
| 4785 | 4909 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG); |
| 4786 | 4910 | } |
| 4787 | 4911 | |
| 4912 | + if (iwl_mvm_has_tlc_offload(mvm)) { | |
| 4913 | + struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw; | |
| 4914 | + | |
| 4915 | + iwl_mvm_set_sta_rate(lq_sta->last_rate_n_flags, &sinfo->txrate); | |
| 4916 | + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); | |
| 4917 | + } | |
| 4918 | + | |
| 4788 | 4919 | /* if beacon filtering isn't on mac80211 does it anyway */ |
| 4789 | 4920 | if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER)) |
| 4790 | 4921 | return; |
| @@ -1298,9 +1298,6 @@ static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm) · 1297 unmodified lines | ||
| 1298 | 1298 | bool tlv_lar = fw_has_capa(&mvm->fw->ucode_capa, |
| 1299 | 1299 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT); |
| 1300 | 1300 | |
| 1301 | − if (iwlwifi_mod_params.lar_disable) | |
| 1302 | − return false; | |
| 1303 | − | |
| 1304 | 1301 | /* |
| 1305 | 1302 | * Enable LAR only if it is supported by the FW (TLV) && |
| 1306 | 1303 | * enabled in the NVM |
| @@ -1508,8 +1505,8 @@ int __must_check iwl_mvm_send_cmd_status(struct iwl_mvm *mvm, · 201 unmodified lines | ||
| 1508 | 1505 | int __must_check iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u32 id, |
| 1509 | 1506 | u16 len, const void *data, |
| 1510 | 1507 | u32 *status); |
| 1511 | −int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |
| 1512 | − struct ieee80211_sta *sta); | |
| 1508 | +int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb, | |
| 1509 | + struct ieee80211_sta *sta); | |
| 1513 | 1510 | int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb); |
| 1514 | 1511 | void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, |
| 1515 | 1512 | struct iwl_tx_cmd *tx_cmd, |
| @@ -277,11 +277,10 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) · 276 unmodified lines | ||
| 277 | 277 | struct iwl_nvm_section *sections = mvm->nvm_sections; |
| 278 | 278 | const __be16 *hw; |
| 279 | 279 | const __le16 *sw, *calib, *regulatory, *mac_override, *phy_sku; |
| 280 | − bool lar_enabled; | |
| 281 | 280 | int regulatory_type; |
| 282 | 281 | |
| 283 | 282 | /* Checking for required sections */ |
| 284 | − if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT) { | |
| 283 | + if (mvm->trans->cfg->nvm_type == IWL_NVM) { | |
| 285 | 284 | if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || |
| 286 | 285 | !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) { |
| 287 | 286 | IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n"); |
| @@ -327,14 +326,9 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) · 39 unmodified lines | ||
| 327 | 326 | (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY_SDP].data : |
| 328 | 327 | (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data; |
| 329 | 328 | |
| 330 | − lar_enabled = !iwlwifi_mod_params.lar_disable && | |
| 331 | − fw_has_capa(&mvm->fw->ucode_capa, | |
| 332 | − IWL_UCODE_TLV_CAPA_LAR_SUPPORT); | |
| 333 | − | |
| 334 | − return iwl_parse_nvm_data(mvm->trans, mvm->cfg, hw, sw, calib, | |
| 329 | + return iwl_parse_nvm_data(mvm->trans, mvm->cfg, mvm->fw, hw, sw, calib, | |
| 335 | 330 | regulatory, mac_override, phy_sku, |
| 336 | − mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant, | |
| 337 | − lar_enabled); | |
| 331 | + mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant); | |
| 338 | 332 | } |
| 339 | 333 | |
| 340 | 334 | /* Loads the NVM data stored in mvm->nvm_sections into the NIC */ |
| @@ -514,14 +514,17 @@ static bool iwl_mvm_is_sn_less(u16 sn1, u16 sn2, u16 buffer_size) · 513 unmodified lines | ||
| 514 | 514 | |
| 515 | 515 | static void iwl_mvm_sync_nssn(struct iwl_mvm *mvm, u8 baid, u16 nssn) |
| 516 | 516 | { |
| 517 | − struct iwl_mvm_rss_sync_notif notif = { | |
| 518 | − .metadata.type = IWL_MVM_RXQ_NSSN_SYNC, | |
| 519 | − .metadata.sync = 0, | |
| 520 | − .nssn_sync.baid = baid, | |
| 521 | − .nssn_sync.nssn = nssn, | |
| 522 | − }; | |
| 523 | − | |
| 524 | − iwl_mvm_sync_rx_queues_internal(mvm, (void *)¬if, sizeof(notif)); | |
| 517 | + if (IWL_MVM_USE_NSSN_SYNC) { | |
| 518 | + struct iwl_mvm_rss_sync_notif notif = { | |
| 519 | + .metadata.type = IWL_MVM_RXQ_NSSN_SYNC, | |
| 520 | + .metadata.sync = 0, | |
| 521 | + .nssn_sync.baid = baid, | |
| 522 | + .nssn_sync.nssn = nssn, | |
| 523 | + }; | |
| 524 | + | |
| 525 | + iwl_mvm_sync_rx_queues_internal(mvm, (void *)¬if, | |
| 526 | + sizeof(notif)); | |
| 527 | + } | |
| 525 | 528 | } |
| 526 | 529 | |
| 527 | 530 | #define RX_REORDER_BUF_TIMEOUT_MQ (HZ / 10) |
| @@ -1213,7 +1213,7 @@ static int iwl_mvm_legacy_config_scan(struct iwl_mvm *mvm) · 1212 unmodified lines | ||
| 1213 | 1213 | cmd_size = sizeof(struct iwl_scan_config_v2); |
| 1214 | 1214 | else |
| 1215 | 1215 | cmd_size = sizeof(struct iwl_scan_config_v1); |
| 1216 | − cmd_size += num_channels; | |
| 1216 | + cmd_size += mvm->fw->ucode_capa.n_scan_channels; | |
| 1217 | 1217 | |
| 1218 | 1218 | cfg = kzalloc(cmd_size, GFP_KERNEL); |
| 1219 | 1219 | if (!cfg) |
| @@ -490,13 +490,13 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm, · 489 unmodified lines | ||
| 490 | 490 | /* |
| 491 | 491 | * Allocates and sets the Tx cmd the driver data pointers in the skb |
| 492 | 492 | */ |
| 493 | −static struct iwl_device_cmd * | |
| 493 | +static struct iwl_device_tx_cmd * | |
| 494 | 494 | iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, |
| 495 | 495 | struct ieee80211_tx_info *info, int hdrlen, |
| 496 | 496 | struct ieee80211_sta *sta, u8 sta_id) |
| 497 | 497 | { |
| 498 | 498 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| 499 | − struct iwl_device_cmd *dev_cmd; | |
| 499 | + struct iwl_device_tx_cmd *dev_cmd; | |
| 500 | 500 | struct iwl_tx_cmd *tx_cmd; |
| 501 | 501 | |
| 502 | 502 | dev_cmd = iwl_trans_alloc_tx_cmd(mvm->trans); |
| @@ -504,11 +504,6 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, · 1 unmodified line | ||
| 504 | 504 | if (unlikely(!dev_cmd)) |
| 505 | 505 | return NULL; |
| 506 | 506 | |
| 507 | − /* Make sure we zero enough of dev_cmd */ | |
| 508 | − BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen2) > sizeof(*tx_cmd)); | |
| 509 | − BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen3) > sizeof(*tx_cmd)); | |
| 510 | − | |
| 511 | − memset(dev_cmd, 0, sizeof(dev_cmd->hdr) + sizeof(*tx_cmd)); | |
| 512 | 507 | dev_cmd->hdr.cmd = TX_CMD; |
| 513 | 508 | |
| 514 | 509 | if (iwl_mvm_has_new_tx_api(mvm)) { |
| @@ -597,7 +592,7 @@ out: · 82 unmodified lines | ||
| 597 | 592 | } |
| 598 | 593 | |
| 599 | 594 | static void iwl_mvm_skb_prepare_status(struct sk_buff *skb, |
| 600 | − struct iwl_device_cmd *cmd) | |
| 595 | + struct iwl_device_tx_cmd *cmd) | |
| 601 | 596 | { |
| 602 | 597 | struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb); |
| 603 | 598 | |
| @@ -716,7 +711,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) · 112 unmodified lines | ||
| 716 | 711 | { |
| 717 | 712 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| 718 | 713 | struct ieee80211_tx_info info; |
| 719 | − struct iwl_device_cmd *dev_cmd; | |
| 714 | + struct iwl_device_tx_cmd *dev_cmd; | |
| 720 | 715 | u8 sta_id; |
| 721 | 716 | int hdrlen = ieee80211_hdrlen(hdr->frame_control); |
| 722 | 717 | __le16 fc = hdr->frame_control; |
| @@ -1078,7 +1073,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, · 355 unmodified lines | ||
| 1078 | 1073 | { |
| 1079 | 1074 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| 1080 | 1075 | struct iwl_mvm_sta *mvmsta; |
| 1081 | − struct iwl_device_cmd *dev_cmd; | |
| 1076 | + struct iwl_device_tx_cmd *dev_cmd; | |
| 1082 | 1077 | __le16 fc; |
| 1083 | 1078 | u16 seq_number = 0; |
| 1084 | 1079 | u8 tid = IWL_MAX_TID_COUNT; |
| @@ -1154,7 +1149,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, · 69 unmodified lines | ||
| 1154 | 1149 | if (WARN_ONCE(txq_id == IWL_MVM_INVALID_QUEUE, "Invalid TXQ id")) { |
| 1155 | 1150 | iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); |
| 1156 | 1151 | spin_unlock(&mvmsta->lock); |
| 1157 | − return 0; | |
| 1152 | + return -1; | |
| 1158 | 1153 | } |
| 1159 | 1154 | |
| 1160 | 1155 | if (!iwl_mvm_has_new_tx_api(mvm)) { |
| @@ -1206,8 +1201,8 @@ drop: · 45 unmodified lines | ||
| 1206 | 1201 | return -1; |
| 1207 | 1202 | } |
| 1208 | 1203 | |
| 1209 | −int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |
| 1210 | − struct ieee80211_sta *sta) | |
| 1204 | +int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb, | |
| 1205 | + struct ieee80211_sta *sta) | |
| 1211 | 1206 | { |
| 1212 | 1207 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
| 1213 | 1208 | struct ieee80211_tx_info info; |
| @@ -57,6 +57,42 @@ · 56 unmodified lines | ||
| 57 | 57 | #include "internal.h" |
| 58 | 58 | #include "iwl-prph.h" |
| 59 | 59 | |
| 60 | +static void *_iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, | |
| 61 | + size_t size, | |
| 62 | + dma_addr_t *phys, | |
| 63 | + int depth) | |
| 64 | +{ | |
| 65 | + void *result; | |
| 66 | + | |
| 67 | + if (WARN(depth > 2, | |
| 68 | + "failed to allocate DMA memory not crossing 2^32 boundary")) | |
| 69 | + return NULL; | |
| 70 | + | |
| 71 | + result = dma_alloc_coherent(trans->dev, size, phys, GFP_KERNEL); | |
| 72 | + | |
| 73 | + if (!result) | |
| 74 | + return NULL; | |
| 75 | + | |
| 76 | + if (unlikely(iwl_pcie_crosses_4g_boundary(*phys, size))) { | |
| 77 | + void *old = result; | |
| 78 | + dma_addr_t oldphys = *phys; | |
| 79 | + | |
| 80 | + result = _iwl_pcie_ctxt_info_dma_alloc_coherent(trans, size, | |
| 81 | + phys, | |
| 82 | + depth + 1); | |
| 83 | + dma_free_coherent(trans->dev, size, old, oldphys); | |
| 84 | + } | |
| 85 | + | |
| 86 | + return result; | |
| 87 | +} | |
| 88 | + | |
| 89 | +static void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, | |
| 90 | + size_t size, | |
| 91 | + dma_addr_t *phys) | |
| 92 | +{ | |
| 93 | + return _iwl_pcie_ctxt_info_dma_alloc_coherent(trans, size, phys, 0); | |
| 94 | +} | |
| 95 | + | |
| 60 | 96 | void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans) |
| 61 | 97 | { |
| 62 | 98 | struct iwl_self_init_dram *dram = &trans->init_dram; |
| @@ -161,14 +197,17 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, · 98 unmodified lines | ||
| 161 | 197 | struct iwl_context_info *ctxt_info; |
| 162 | 198 | struct iwl_context_info_rbd_cfg *rx_cfg; |
| 163 | 199 | u32 control_flags = 0, rb_size; |
| 200 | + dma_addr_t phys; | |
| 164 | 201 | int ret; |
| 165 | 202 | |
| 166 | − ctxt_info = dma_alloc_coherent(trans->dev, sizeof(*ctxt_info), | |
| 167 | − &trans_pcie->ctxt_info_dma_addr, | |
| 168 | − GFP_KERNEL); | |
| 203 | + ctxt_info = iwl_pcie_ctxt_info_dma_alloc_coherent(trans, | |
| 204 | + sizeof(*ctxt_info), | |
| 205 | + &phys); | |
| 169 | 206 | if (!ctxt_info) |
| 170 | 207 | return -ENOMEM; |
| 171 | 208 | |
| 209 | + trans_pcie->ctxt_info_dma_addr = phys; | |
| 210 | + | |
| 172 | 211 | ctxt_info->version.version = 0; |
| 173 | 212 | ctxt_info->version.mac_id = |
| 174 | 213 | cpu_to_le16((u16)iwl_read32(trans, CSR_HW_REV)); |
| @@ -305,7 +305,7 @@ struct iwl_cmd_meta { · 304 unmodified lines | ||
| 305 | 305 | #define IWL_FIRST_TB_SIZE_ALIGN ALIGN(IWL_FIRST_TB_SIZE, 64) |
| 306 | 306 | |
| 307 | 307 | struct iwl_pcie_txq_entry { |
| 308 | − struct iwl_device_cmd *cmd; | |
| 308 | + void *cmd; | |
| 309 | 309 | struct sk_buff *skb; |
| 310 | 310 | /* buffer to free after command completes */ |
| 311 | 311 | const void *free_buf; |
| @@ -672,6 +672,16 @@ void iwl_pcie_disable_ict(struct iwl_trans *trans); · 360 unmodified lines | ||
| 672 | 672 | /***************************************************** |
| 673 | 673 | * TX / HCMD |
| 674 | 674 | ******************************************************/ |
| 675 | +/* | |
| 676 | + * We need this inline in case dma_addr_t is only 32-bits - since the | |
| 677 | + * hardware is always 64-bit, the issue can still occur in that case, | |
| 678 | + * so use u64 for 'phys' here to force the addition in 64-bit. | |
| 679 | + */ | |
| 680 | +static inline bool iwl_pcie_crosses_4g_boundary(u64 phys, u16 len) | |
| 681 | +{ | |
| 682 | + return upper_32_bits(phys) != upper_32_bits(phys + len); | |
| 683 | +} | |
| 684 | + | |
| 675 | 685 | int iwl_pcie_tx_init(struct iwl_trans *trans); |
| 676 | 686 | int iwl_pcie_gen2_tx_init(struct iwl_trans *trans, int txq_id, |
| 677 | 687 | int queue_size); |
| @@ -688,7 +698,7 @@ void iwl_trans_pcie_txq_set_shared_mode(struct iwl_trans *trans, u32 txq_id, · 10 unmodified lines | ||
| 688 | 698 | void iwl_trans_pcie_log_scd_error(struct iwl_trans *trans, |
| 689 | 699 | struct iwl_txq *txq); |
| 690 | 700 | int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, |
| 691 | − struct iwl_device_cmd *dev_cmd, int txq_id); | |
| 701 | + struct iwl_device_tx_cmd *dev_cmd, int txq_id); | |
| 692 | 702 | void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans); |
| 693 | 703 | int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); |
| 694 | 704 | void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx); |
| @@ -1082,7 +1092,8 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans); · 387 unmodified lines | ||
| 1082 | 1092 | void iwl_pcie_free_tso_page(struct iwl_trans_pcie *trans_pcie, |
| 1083 | 1093 | struct sk_buff *skb); |
| 1084 | 1094 | #ifdef CONFIG_INET |
| 1085 | −struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len); | |
| 1095 | +struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len, | |
| 1096 | + struct sk_buff *skb); | |
| 1086 | 1097 | #endif |
| 1087 | 1098 | |
| 1088 | 1099 | /* common functions that are used by gen3 transport */ |
| @@ -1106,7 +1117,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans, · 17 unmodified lines | ||
| 1106 | 1117 | unsigned int timeout); |
| 1107 | 1118 | void iwl_trans_pcie_dyn_txq_free(struct iwl_trans *trans, int queue); |
| 1108 | 1119 | int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, |
| 1109 | − struct iwl_device_cmd *dev_cmd, int txq_id); | |
| 1120 | + struct iwl_device_tx_cmd *dev_cmd, int txq_id); | |
| 1110 | 1121 | int iwl_trans_pcie_gen2_send_hcmd(struct iwl_trans *trans, |
| 1111 | 1122 | struct iwl_host_cmd *cmd); |
| 1112 | 1123 | void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans); |
| @@ -1529,13 +1529,13 @@ out: · 1528 unmodified lines | ||
| 1529 | 1529 | |
| 1530 | 1530 | napi = &rxq->napi; |
| 1531 | 1531 | if (napi->poll) { |
| 1532 | + napi_gro_flush(napi, false); | |
| 1533 | + | |
| 1532 | 1534 | if (napi->rx_count) { |
| 1533 | 1535 | netif_receive_skb_list(&napi->rx_list); |
| 1534 | 1536 | INIT_LIST_HEAD(&napi->rx_list); |
| 1535 | 1537 | napi->rx_count = 0; |
| 1536 | 1538 | } |
| 1537 | − | |
| 1538 | − napi_gro_flush(napi, false); | |
| 1539 | 1539 | } |
| 1540 | 1540 | |
| 1541 | 1541 | iwl_pcie_rxq_restock(trans, rxq); |
| @@ -79,6 +79,7 @@ · 78 unmodified lines | ||
| 79 | 79 | #include "iwl-agn-hw.h" |
| 80 | 80 | #include "fw/error-dump.h" |
| 81 | 81 | #include "fw/dbg.h" |
| 82 | +#include "fw/api/tx.h" | |
| 82 | 83 | #include "internal.h" |
| 83 | 84 | #include "iwl-fh.h" |
| 84 | 85 | |
| @@ -301,18 +302,13 @@ void iwl_pcie_apm_config(struct iwl_trans *trans) · 216 unmodified lines | ||
| 301 | 302 | u16 cap; |
| 302 | 303 | |
| 303 | 304 | /* |
| 304 | − * HW bug W/A for instability in PCIe bus L0S->L1 transition. | |
| 305 | − * Check if BIOS (or OS) enabled L1-ASPM on this device. | |
| 306 | − * If so (likely), disable L0S, so device moves directly L0->L1; | |
| 307 | − * costs negligible amount of power savings. | |
| 308 | − * If not (unlikely), enable L0S, so there is at least some | |
| 309 | − * power savings, even without L1. | |
| 305 | + * L0S states have been found to be unstable with our devices | |
| 306 | + * and in newer hardware they are not officially supported at | |
| 307 | + * all, so we must always set the L0S_DISABLED bit. | |
| 310 | 308 | */ |
| 309 | + iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_DISABLED); | |
| 310 | + | |
| 311 | 311 | pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl); |
| 312 | − if (lctl & PCI_EXP_LNKCTL_ASPM_L1) | |
| 313 | − iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | |
| 314 | − else | |
| 315 | − iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | |
| 316 | 312 | trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S); |
| 317 | 313 | |
| 318 | 314 | pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_DEVCTL2, &cap); |
| @@ -3460,19 +3456,34 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, · 3141 unmodified lines | ||
| 3460 | 3456 | { |
| 3461 | 3457 | struct iwl_trans_pcie *trans_pcie; |
| 3462 | 3458 | struct iwl_trans *trans; |
| 3463 | − int ret, addr_size; | |
| 3459 | + int ret, addr_size, txcmd_size, txcmd_align; | |
| 3460 | + const struct iwl_trans_ops *ops = &trans_ops_pcie_gen2; | |
| 3461 | + | |
| 3462 | + if (!cfg_trans->gen2) { | |
| 3463 | + ops = &trans_ops_pcie; | |
| 3464 | + txcmd_size = sizeof(struct iwl_tx_cmd); | |
| 3465 | + txcmd_align = sizeof(void *); | |
| 3466 | + } else if (cfg_trans->device_family < IWL_DEVICE_FAMILY_AX210) { | |
| 3467 | + txcmd_size = sizeof(struct iwl_tx_cmd_gen2); | |
| 3468 | + txcmd_align = 64; | |
| 3469 | + } else { | |
| 3470 | + txcmd_size = sizeof(struct iwl_tx_cmd_gen3); | |
| 3471 | + txcmd_align = 128; | |
| 3472 | + } | |
| 3473 | + | |
| 3474 | + txcmd_size += sizeof(struct iwl_cmd_header); | |
| 3475 | + txcmd_size += 36; /* biggest possible 802.11 header */ | |
| 3476 | + | |
| 3477 | + /* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */ | |
| 3478 | + if (WARN_ON(cfg_trans->gen2 && txcmd_size >= txcmd_align)) | |
| 3479 | + return ERR_PTR(-EINVAL); | |
| 3464 | 3480 | |
| 3465 | 3481 | ret = pcim_enable_device(pdev); |
| 3466 | 3482 | if (ret) |
| 3467 | 3483 | return ERR_PTR(ret); |
| 3468 | 3484 | |
| 3469 | − if (cfg_trans->gen2) | |
| 3470 | − trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), | |
| 3471 | − &pdev->dev, &trans_ops_pcie_gen2); | |
| 3472 | − else | |
| 3473 | − trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), | |
| 3474 | − &pdev->dev, &trans_ops_pcie); | |
| 3475 | − | |
| 3485 | + trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), &pdev->dev, ops, | |
| 3486 | + txcmd_size, txcmd_align); | |
| 3476 | 3487 | if (!trans) |
| 3477 | 3488 | return ERR_PTR(-ENOMEM); |
| 3478 | 3489 | |
| @@ -221,6 +221,17 @@ static int iwl_pcie_gen2_set_tb(struct iwl_trans *trans, · 220 unmodified lines | ||
| 221 | 221 | int idx = iwl_pcie_gen2_get_num_tbs(trans, tfd); |
| 222 | 222 | struct iwl_tfh_tb *tb; |
| 223 | 223 | |
| 224 | + /* | |
| 225 | + * Only WARN here so we know about the issue, but we mess up our | |
| 226 | + * unmap path because not every place currently checks for errors | |
| 227 | + * returned from this function - it can only return an error if | |
| 228 | + * there's no more space, and so when we know there is enough we | |
| 229 | + * don't always check ... | |
| 230 | + */ | |
| 231 | + WARN(iwl_pcie_crosses_4g_boundary(addr, len), | |
| 232 | + "possible DMA problem with iova:0x%llx, len:%d\n", | |
| 233 | + (unsigned long long)addr, len); | |
| 234 | + | |
| 224 | 235 | if (WARN_ON(idx >= IWL_TFH_NUM_TBS)) |
| 225 | 236 | return -EINVAL; |
| 226 | 237 | tb = &tfd->tbs[idx]; |
| @@ -240,13 +251,114 @@ static int iwl_pcie_gen2_set_tb(struct iwl_trans *trans, · 13 unmodified lines | ||
| 240 | 251 | return idx; |
| 241 | 252 | } |
| 242 | 253 | |
| 254 | +static struct page *get_workaround_page(struct iwl_trans *trans, | |
| 255 | + struct sk_buff *skb) | |
| 256 | +{ | |
| 257 | + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | |
| 258 | + struct page **page_ptr; | |
| 259 | + struct page *ret; | |
| 260 | + | |
| 261 | + page_ptr = (void *)((u8 *)skb->cb + trans_pcie->page_offs); | |
| 262 | + | |
| 263 | + ret = alloc_page(GFP_ATOMIC); | |
| 264 | + if (!ret) | |
| 265 | + return NULL; | |
| 266 | + | |
| 267 | + /* set the chaining pointer to the previous page if there */ | |
| 268 | + *(void **)(page_address(ret) + PAGE_SIZE - sizeof(void *)) = *page_ptr; | |
| 269 | + *page_ptr = ret; | |
| 270 | + | |
| 271 | + return ret; | |
| 272 | +} | |
| 273 | + | |
| 274 | +/* | |
| 275 | + * Add a TB and if needed apply the FH HW bug workaround; | |
| 276 | + * meta != NULL indicates that it's a page mapping and we | |
| 277 | + * need to dma_unmap_page() and set the meta->tbs bit in | |
| 278 | + * this case. | |
| 279 | + */ | |
| 280 | +static int iwl_pcie_gen2_set_tb_with_wa(struct iwl_trans *trans, | |
| 281 | + struct sk_buff *skb, | |
| 282 | + struct iwl_tfh_tfd *tfd, | |
| 283 | + dma_addr_t phys, void *virt, | |
| 284 | + u16 len, struct iwl_cmd_meta *meta) | |
| 285 | +{ | |
| 286 | + dma_addr_t oldphys = phys; | |
| 287 | + struct page *page; | |
| 288 | + int ret; | |
| 289 | + | |
| 290 | + if (unlikely(dma_mapping_error(trans->dev, phys))) | |
| 291 | + return -ENOMEM; | |
| 292 | + | |
| 293 | + if (likely(!iwl_pcie_crosses_4g_boundary(phys, len))) { | |
| 294 | + ret = iwl_pcie_gen2_set_tb(trans, tfd, phys, len); | |
| 295 | + | |
| 296 | + if (ret < 0) | |
| 297 | + goto unmap; | |
| 298 | + | |
| 299 | + if (meta) | |
| 300 | + meta->tbs |= BIT(ret); | |
| 301 | + | |
| 302 | + ret = 0; | |
| 303 | + goto trace; | |
| 304 | + } | |
| 305 | + | |
| 306 | + /* | |
| 307 | + * Work around a hardware bug. If (as expressed in the | |
| 308 | + * condition above) the TB ends on a 32-bit boundary, | |
| 309 | + * then the next TB may be accessed with the wrong | |
| 310 | + * address. | |
| 311 | + * To work around it, copy the data elsewhere and make | |
| 312 | + * a new mapping for it so the device will not fail. | |
| 313 | + */ | |
| 314 | + | |
| 315 | + if (WARN_ON(len > PAGE_SIZE - sizeof(void *))) { | |
| 316 | + ret = -ENOBUFS; | |
| 317 | + goto unmap; | |
| 318 | + } | |
| 319 | + | |
| 320 | + page = get_workaround_page(trans, skb); | |
| 321 | + if (!page) { | |
| 322 | + ret = -ENOMEM; | |
| 323 | + goto unmap; | |
| 324 | + } | |
| 325 | + | |
| 326 | + memcpy(page_address(page), virt, len); | |
| 327 | + | |
| 328 | + phys = dma_map_single(trans->dev, page_address(page), len, | |
| 329 | + DMA_TO_DEVICE); | |
| 330 | + if (unlikely(dma_mapping_error(trans->dev, phys))) | |
| 331 | + return -ENOMEM; | |
| 332 | + ret = iwl_pcie_gen2_set_tb(trans, tfd, phys, len); | |
| 333 | + if (ret < 0) { | |
| 334 | + /* unmap the new allocation as single */ | |
| 335 | + oldphys = phys; | |
| 336 | + meta = NULL; | |
| 337 | + goto unmap; | |
| 338 | + } | |
| 339 | + IWL_WARN(trans, | |
| 340 | + "TB bug workaround: copied %d bytes from 0x%llx to 0x%llx\n", | |
| 341 | + len, (unsigned long long)oldphys, (unsigned long long)phys); | |
| 342 | + | |
| 343 | + ret = 0; | |
| 344 | +unmap: | |
| 345 | + if (meta) | |
| 346 | + dma_unmap_page(trans->dev, oldphys, len, DMA_TO_DEVICE); | |
| 347 | + else | |
| 348 | + dma_unmap_single(trans->dev, oldphys, len, DMA_TO_DEVICE); | |
| 349 | +trace: | |
| 350 | + trace_iwlwifi_dev_tx_tb(trans->dev, skb, virt, phys, len); | |
| 351 | + | |
| 352 | + return ret; | |
| 353 | +} | |
| 354 | + | |
| 243 | 355 | static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans, |
| 244 | 356 | struct sk_buff *skb, |
| 245 | 357 | struct iwl_tfh_tfd *tfd, int start_len, |
| 246 | − u8 hdr_len, struct iwl_device_cmd *dev_cmd) | |
| 358 | + u8 hdr_len, | |
| 359 | + struct iwl_device_tx_cmd *dev_cmd) | |
| 247 | 360 | { |
| 248 | 361 | #ifdef CONFIG_INET |
| 249 | − struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | |
| 250 | 362 | struct iwl_tx_cmd_gen2 *tx_cmd = (void *)dev_cmd->payload; |
| 251 | 363 | struct ieee80211_hdr *hdr = (void *)skb->data; |
| 252 | 364 | unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room; |
| @@ -254,7 +366,6 @@ static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans, · 1 unmodified line | ||
| 254 | 366 | u16 length, amsdu_pad; |
| 255 | 367 | u8 *start_hdr; |
| 256 | 368 | struct iwl_tso_hdr_page *hdr_page; |
| 257 | − struct page **page_ptr; | |
| 258 | 369 | struct tso_t tso; |
| 259 | 370 | |
| 260 | 371 | trace_iwlwifi_dev_tx(trans->dev, skb, tfd, sizeof(*tfd), |
| @@ -270,14 +381,11 @@ static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans, · 9 unmodified lines | ||
| 270 | 381 | (3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr)); |
| 271 | 382 | |
| 272 | 383 | /* Our device supports 9 segments at most, it will fit in 1 page */ |
| 273 | − hdr_page = get_page_hdr(trans, hdr_room); | |
| 384 | + hdr_page = get_page_hdr(trans, hdr_room, skb); | |
| 274 | 385 | if (!hdr_page) |
| 275 | 386 | return -ENOMEM; |
| 276 | 387 | |
| 277 | − get_page(hdr_page->page); | |
| 278 | 388 | start_hdr = hdr_page->pos; |
| 279 | − page_ptr = (void *)((u8 *)skb->cb + trans_pcie->page_offs); | |
| 280 | − *page_ptr = hdr_page->page; | |
| 281 | 389 | |
| 282 | 390 | /* |
| 283 | 391 | * Pull the ieee80211 header to be able to use TSO core, |
| @@ -332,6 +440,11 @@ static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans, · 48 unmodified lines | ||
| 332 | 440 | dev_kfree_skb(csum_skb); |
| 333 | 441 | goto out_err; |
| 334 | 442 | } |
| 443 | + /* | |
| 444 | + * No need for _with_wa, this is from the TSO page and | |
| 445 | + * we leave some space at the end of it so can't hit | |
| 446 | + * the buggy scenario. | |
| 447 | + */ | |
| 335 | 448 | iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb_len); |
| 336 | 449 | trace_iwlwifi_dev_tx_tb(trans->dev, skb, start_hdr, |
| 337 | 450 | tb_phys, tb_len); |
| @@ -343,16 +456,18 @@ static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans, · 5 unmodified lines | ||
| 343 | 456 | |
| 344 | 457 | /* put the payload */ |
| 345 | 458 | while (data_left) { |
| 459 | + int ret; | |
| 460 | + | |
| 346 | 461 | tb_len = min_t(unsigned int, tso.size, data_left); |
| 347 | 462 | tb_phys = dma_map_single(trans->dev, tso.data, |
| 348 | 463 | tb_len, DMA_TO_DEVICE); |
| 349 | − if (unlikely(dma_mapping_error(trans->dev, tb_phys))) { | |
| 464 | + ret = iwl_pcie_gen2_set_tb_with_wa(trans, skb, tfd, | |
| 465 | + tb_phys, tso.data, | |
| 466 | + tb_len, NULL); | |
| 467 | + if (ret) { | |
| 350 | 468 | dev_kfree_skb(csum_skb); |
| 351 | 469 | goto out_err; |
| 352 | 470 | } |
| 353 | − iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb_len); | |
| 354 | − trace_iwlwifi_dev_tx_tb(trans->dev, skb, tso.data, | |
| 355 | − tb_phys, tb_len); | |
| 356 | 471 | |
| 357 | 472 | data_left -= tb_len; |
| 358 | 473 | tso_build_data(skb, &tso, tb_len); |
| @@ -372,7 +487,7 @@ out_err: · 13 unmodified lines | ||
| 372 | 487 | static struct |
| 373 | 488 | iwl_tfh_tfd *iwl_pcie_gen2_build_tx_amsdu(struct iwl_trans *trans, |
| 374 | 489 | struct iwl_txq *txq, |
| 375 | − struct iwl_device_cmd *dev_cmd, | |
| 490 | + struct iwl_device_tx_cmd *dev_cmd, | |
| 376 | 491 | struct sk_buff *skb, |
| 377 | 492 | struct iwl_cmd_meta *out_meta, |
| 378 | 493 | int hdr_len, |
| @@ -386,6 +501,11 @@ iwl_tfh_tfd *iwl_pcie_gen2_build_tx_amsdu(struct iwl_trans *trans, · 7 unmodified lines | ||
| 386 | 501 | |
| 387 | 502 | tb_phys = iwl_pcie_get_first_tb_dma(txq, idx); |
| 388 | 503 | |
| 504 | + /* | |
| 505 | + * No need for _with_wa, the first TB allocation is aligned up | |
| 506 | + * to a 64-byte boundary and thus can't be at the end or cross | |
| 507 | + * a page boundary (much less a 2^32 boundary). | |
| 508 | + */ | |
| 389 | 509 | iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, IWL_FIRST_TB_SIZE); |
| 390 | 510 | |
| 391 | 511 | /* |
| @@ -404,6 +524,10 @@ iwl_tfh_tfd *iwl_pcie_gen2_build_tx_amsdu(struct iwl_trans *trans, · 12 unmodified lines | ||
| 404 | 524 | tb_phys = dma_map_single(trans->dev, tb1_addr, len, DMA_TO_DEVICE); |
| 405 | 525 | if (unlikely(dma_mapping_error(trans->dev, tb_phys))) |
| 406 | 526 | goto out_err; |
| 527 | + /* | |
| 528 | + * No need for _with_wa(), we ensure (via alignment) that the data | |
| 529 | + * here can never cross or end at a page boundary. | |
| 530 | + */ | |
| 407 | 531 | iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, len); |
| 408 | 532 | |
| 409 | 533 | if (iwl_pcie_gen2_build_amsdu(trans, skb, tfd, |
| @@ -430,24 +554,19 @@ static int iwl_pcie_gen2_tx_add_frags(struct iwl_trans *trans, · 20 unmodified lines | ||
| 430 | 554 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
| 431 | 555 | const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; |
| 432 | 556 | dma_addr_t tb_phys; |
| 433 | − int tb_idx; | |
| 557 | + unsigned int fragsz = skb_frag_size(frag); | |
| 558 | + int ret; | |
| 434 | 559 | |
| 435 | − if (!skb_frag_size(frag)) | |
| 560 | + if (!fragsz) | |
| 436 | 561 | continue; |
| 437 | 562 | |
| 438 | 563 | tb_phys = skb_frag_dma_map(trans->dev, frag, 0, |
| 439 | − skb_frag_size(frag), DMA_TO_DEVICE); | |
| 440 | − | |
| 441 | − if (unlikely(dma_mapping_error(trans->dev, tb_phys))) | |
| 442 | − return -ENOMEM; | |
| 443 | − tb_idx = iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, | |
| 444 | − skb_frag_size(frag)); | |
| 445 | − trace_iwlwifi_dev_tx_tb(trans->dev, skb, skb_frag_address(frag), | |
| 446 | − tb_phys, skb_frag_size(frag)); | |
| 447 | − if (tb_idx < 0) | |
| 448 | − return tb_idx; | |
| 449 | − | |
| 450 | − out_meta->tbs |= BIT(tb_idx); | |
| 564 | + fragsz, DMA_TO_DEVICE); | |
| 565 | + ret = iwl_pcie_gen2_set_tb_with_wa(trans, skb, tfd, tb_phys, | |
| 566 | + skb_frag_address(frag), | |
| 567 | + fragsz, out_meta); | |
| 568 | + if (ret) | |
| 569 | + return ret; | |
| 451 | 570 | } |
| 452 | 571 | |
| 453 | 572 | return 0; |
| @@ -456,7 +575,7 @@ static int iwl_pcie_gen2_tx_add_frags(struct iwl_trans *trans, · 2 unmodified lines | ||
| 456 | 575 | static struct |
| 457 | 576 | iwl_tfh_tfd *iwl_pcie_gen2_build_tx(struct iwl_trans *trans, |
| 458 | 577 | struct iwl_txq *txq, |
| 459 | − struct iwl_device_cmd *dev_cmd, | |
| 578 | + struct iwl_device_tx_cmd *dev_cmd, | |
| 460 | 579 | struct sk_buff *skb, |
| 461 | 580 | struct iwl_cmd_meta *out_meta, |
| 462 | 581 | int hdr_len, |
| @@ -475,6 +594,11 @@ iwl_tfh_tfd *iwl_pcie_gen2_build_tx(struct iwl_trans *trans, · 12 unmodified lines | ||
| 475 | 594 | /* The first TB points to bi-directional DMA data */ |
| 476 | 595 | memcpy(&txq->first_tb_bufs[idx], dev_cmd, IWL_FIRST_TB_SIZE); |
| 477 | 596 | |
| 597 | + /* | |
| 598 | + * No need for _with_wa, the first TB allocation is aligned up | |
| 599 | + * to a 64-byte boundary and thus can't be at the end or cross | |
| 600 | + * a page boundary (much less a 2^32 boundary). | |
| 601 | + */ | |
| 478 | 602 | iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, IWL_FIRST_TB_SIZE); |
| 479 | 603 | |
| 480 | 604 | /* |
| @@ -496,6 +620,10 @@ iwl_tfh_tfd *iwl_pcie_gen2_build_tx(struct iwl_trans *trans, · 15 unmodified lines | ||
| 496 | 620 | tb_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE); |
| 497 | 621 | if (unlikely(dma_mapping_error(trans->dev, tb_phys))) |
| 498 | 622 | goto out_err; |
| 623 | + /* | |
| 624 | + * No need for _with_wa(), we ensure (via alignment) that the data | |
| 625 | + * here can never cross or end at a page boundary. | |
| 626 | + */ | |
| 499 | 627 | iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb1_len); |
| 500 | 628 | trace_iwlwifi_dev_tx(trans->dev, skb, tfd, sizeof(*tfd), &dev_cmd->hdr, |
| 501 | 629 | IWL_FIRST_TB_SIZE + tb1_len, hdr_len); |
| @@ -504,26 +632,30 @@ iwl_tfh_tfd *iwl_pcie_gen2_build_tx(struct iwl_trans *trans, · 2 unmodified lines | ||
| 504 | 632 | tb2_len = skb_headlen(skb) - hdr_len; |
| 505 | 633 | |
| 506 | 634 | if (tb2_len > 0) { |
| 635 | + int ret; | |
| 636 | + | |
| 507 | 637 | tb_phys = dma_map_single(trans->dev, skb->data + hdr_len, |
| 508 | 638 | tb2_len, DMA_TO_DEVICE); |
| 509 | − if (unlikely(dma_mapping_error(trans->dev, tb_phys))) | |
| 639 | + ret = iwl_pcie_gen2_set_tb_with_wa(trans, skb, tfd, tb_phys, | |
| 640 | + skb->data + hdr_len, tb2_len, | |
| 641 | + NULL); | |
| 642 | + if (ret) | |
| 510 | 643 | goto out_err; |
| 511 | − iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb2_len); | |
| 512 | − trace_iwlwifi_dev_tx_tb(trans->dev, skb, skb->data + hdr_len, | |
| 513 | − tb_phys, tb2_len); | |
| 514 | 644 | } |
| 515 | 645 | |
| 516 | 646 | if (iwl_pcie_gen2_tx_add_frags(trans, skb, tfd, out_meta)) |
| 517 | 647 | goto out_err; |
| 518 | 648 | |
| 519 | 649 | skb_walk_frags(skb, frag) { |
| 650 | + int ret; | |
| 651 | + | |
| 520 | 652 | tb_phys = dma_map_single(trans->dev, frag->data, |
| 521 | 653 | skb_headlen(frag), DMA_TO_DEVICE); |
| 522 | − if (unlikely(dma_mapping_error(trans->dev, tb_phys))) | |
| 654 | + ret = iwl_pcie_gen2_set_tb_with_wa(trans, skb, tfd, tb_phys, | |
| 655 | + frag->data, | |
| 656 | + skb_headlen(frag), NULL); | |
| 657 | + if (ret) | |
| 523 | 658 | goto out_err; |
| 524 | − iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, skb_headlen(frag)); | |
| 525 | − trace_iwlwifi_dev_tx_tb(trans->dev, skb, frag->data, | |
| 526 | − tb_phys, skb_headlen(frag)); | |
| 527 | 659 | if (iwl_pcie_gen2_tx_add_frags(trans, frag, tfd, out_meta)) |
| 528 | 660 | goto out_err; |
| 529 | 661 | } |
| @@ -538,7 +670,7 @@ out_err: · 8 unmodified lines | ||
| 538 | 670 | static |
| 539 | 671 | struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans, |
| 540 | 672 | struct iwl_txq *txq, |
| 541 | − struct iwl_device_cmd *dev_cmd, | |
| 673 | + struct iwl_device_tx_cmd *dev_cmd, | |
| 542 | 674 | struct sk_buff *skb, |
| 543 | 675 | struct iwl_cmd_meta *out_meta) |
| 544 | 676 | { |
| @@ -578,7 +710,7 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans, · 33 unmodified lines | ||
| 578 | 710 | } |
| 579 | 711 | |
| 580 | 712 | int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, |
| 581 | − struct iwl_device_cmd *dev_cmd, int txq_id) | |
| 713 | + struct iwl_device_tx_cmd *dev_cmd, int txq_id) | |
| 582 | 714 | { |
| 583 | 715 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 584 | 716 | struct iwl_cmd_meta *out_meta; |
| @@ -603,7 +735,7 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, · 18 unmodified lines | ||
| 603 | 735 | |
| 604 | 736 | /* don't put the packet on the ring, if there is no room */ |
| 605 | 737 | if (unlikely(iwl_queue_space(trans, txq) < 3)) { |
| 606 | − struct iwl_device_cmd **dev_cmd_ptr; | |
| 738 | + struct iwl_device_tx_cmd **dev_cmd_ptr; | |
| 607 | 739 | |
| 608 | 740 | dev_cmd_ptr = (void *)((u8 *)skb->cb + |
| 609 | 741 | trans_pcie->dev_cmd_offs); |
| @@ -213,8 +213,8 @@ static void iwl_pcie_txq_update_byte_cnt_tbl(struct iwl_trans *trans, · 212 unmodified lines | ||
| 213 | 213 | u8 sec_ctl = 0; |
| 214 | 214 | u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; |
| 215 | 215 | __le16 bc_ent; |
| 216 | − struct iwl_tx_cmd *tx_cmd = | |
| 217 | − (void *)txq->entries[txq->write_ptr].cmd->payload; | |
| 216 | + struct iwl_device_tx_cmd *dev_cmd = txq->entries[txq->write_ptr].cmd; | |
| 217 | + struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload; | |
| 218 | 218 | u8 sta_id = tx_cmd->sta_id; |
| 219 | 219 | |
| 220 | 220 | scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; |
| @@ -257,8 +257,8 @@ static void iwl_pcie_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, · 36 unmodified lines | ||
| 257 | 257 | int read_ptr = txq->read_ptr; |
| 258 | 258 | u8 sta_id = 0; |
| 259 | 259 | __le16 bc_ent; |
| 260 | − struct iwl_tx_cmd *tx_cmd = | |
| 261 | − (void *)txq->entries[read_ptr].cmd->payload; | |
| 260 | + struct iwl_device_tx_cmd *dev_cmd = txq->entries[read_ptr].cmd; | |
| 261 | + struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload; | |
| 262 | 262 | |
| 263 | 263 | WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); |
| 264 | 264 | |
| @@ -624,12 +624,18 @@ void iwl_pcie_free_tso_page(struct iwl_trans_pcie *trans_pcie, · 359 unmodified lines | ||
| 624 | 624 | struct sk_buff *skb) |
| 625 | 625 | { |
| 626 | 626 | struct page **page_ptr; |
| 627 | + struct page *next; | |
| 627 | 628 | |
| 628 | 629 | page_ptr = (void *)((u8 *)skb->cb + trans_pcie->page_offs); |
| 630 | + next = *page_ptr; | |
| 631 | + *page_ptr = NULL; | |
| 629 | 632 | |
| 630 | − if (*page_ptr) { | |
| 631 | − __free_page(*page_ptr); | |
| 632 | − *page_ptr = NULL; | |
| 633 | + while (next) { | |
| 634 | + struct page *tmp = next; | |
| 635 | + | |
| 636 | + next = *(void **)(page_address(next) + PAGE_SIZE - | |
| 637 | + sizeof(void *)); | |
| 638 | + __free_page(tmp); | |
| 633 | 639 | } |
| 634 | 640 | } |
| 635 | 641 | |
| @@ -1196,7 +1202,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, · 560 unmodified lines | ||
| 1196 | 1202 | |
| 1197 | 1203 | while (!skb_queue_empty(&overflow_skbs)) { |
| 1198 | 1204 | struct sk_buff *skb = __skb_dequeue(&overflow_skbs); |
| 1199 | − struct iwl_device_cmd *dev_cmd_ptr; | |
| 1205 | + struct iwl_device_tx_cmd *dev_cmd_ptr; | |
| 1200 | 1206 | |
| 1201 | 1207 | dev_cmd_ptr = *(void **)((u8 *)skb->cb + |
| 1202 | 1208 | trans_pcie->dev_cmd_offs); |
| @@ -2052,17 +2058,34 @@ static int iwl_fill_data_tbs(struct iwl_trans *trans, struct sk_buff *skb, · 849 unmodified lines | ||
| 2052 | 2058 | } |
| 2053 | 2059 | |
| 2054 | 2060 | #ifdef CONFIG_INET |
| 2055 | −struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len) | |
| 2061 | +struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len, | |
| 2062 | + struct sk_buff *skb) | |
| 2056 | 2063 | { |
| 2057 | 2064 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 2058 | 2065 | struct iwl_tso_hdr_page *p = this_cpu_ptr(trans_pcie->tso_hdr_page); |
| 2066 | + struct page **page_ptr; | |
| 2067 | + | |
| 2068 | + page_ptr = (void *)((u8 *)skb->cb + trans_pcie->page_offs); | |
| 2069 | + | |
| 2070 | + if (WARN_ON(*page_ptr)) | |
| 2071 | + return NULL; | |
| 2059 | 2072 | |
| 2060 | 2073 | if (!p->page) |
| 2061 | 2074 | goto alloc; |
| 2062 | 2075 | |
| 2063 | − /* enough room on this page */ | |
| 2064 | − if (p->pos + len < (u8 *)page_address(p->page) + PAGE_SIZE) | |
| 2065 | − return p; | |
| 2076 | + /* | |
| 2077 | + * Check if there's enough room on this page | |
| 2078 | + * | |
| 2079 | + * Note that we put a page chaining pointer *last* in the | |
| 2080 | + * page - we need it somewhere, and if it's there then we | |
| 2081 | + * avoid DMA mapping the last bits of the page which may | |
| 2082 | + * trigger the 32-bit boundary hardware bug. | |
| 2083 | + * | |
| 2084 | + * (see also get_workaround_page() in tx-gen2.c) | |
| 2085 | + */ | |
| 2086 | + if (p->pos + len < (u8 *)page_address(p->page) + PAGE_SIZE - | |
| 2087 | + sizeof(void *)) | |
| 2088 | + goto out; | |
| 2066 | 2089 | |
| 2067 | 2090 | /* We don't have enough room on this page, get a new one. */ |
| 2068 | 2091 | __free_page(p->page); |
| @@ -2072,6 +2095,11 @@ alloc: · 3 unmodified lines | ||
| 2072 | 2095 | if (!p->page) |
| 2073 | 2096 | return NULL; |
| 2074 | 2097 | p->pos = page_address(p->page); |
| 2098 | + /* set the chaining pointer to NULL */ | |
| 2099 | + *(void **)(page_address(p->page) + PAGE_SIZE - sizeof(void *)) = NULL; | |
| 2100 | +out: | |
| 2101 | + *page_ptr = p->page; | |
| 2102 | + get_page(p->page); | |
| 2075 | 2103 | return p; |
| 2076 | 2104 | } |
| 2077 | 2105 | |
| @@ -2097,7 +2125,8 @@ static void iwl_compute_pseudo_hdr_csum(void *iph, struct tcphdr *tcph, · 19 unmodified lines | ||
| 2097 | 2125 | static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, |
| 2098 | 2126 | struct iwl_txq *txq, u8 hdr_len, |
| 2099 | 2127 | struct iwl_cmd_meta *out_meta, |
| 2100 | − struct iwl_device_cmd *dev_cmd, u16 tb1_len) | |
| 2128 | + struct iwl_device_tx_cmd *dev_cmd, | |
| 2129 | + u16 tb1_len) | |
| 2101 | 2130 | { |
| 2102 | 2131 | struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload; |
| 2103 | 2132 | struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; |
| @@ -2107,7 +2136,6 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, · 3 unmodified lines | ||
| 2107 | 2136 | u16 length, iv_len, amsdu_pad; |
| 2108 | 2137 | u8 *start_hdr; |
| 2109 | 2138 | struct iwl_tso_hdr_page *hdr_page; |
| 2110 | − struct page **page_ptr; | |
| 2111 | 2139 | struct tso_t tso; |
| 2112 | 2140 | |
| 2113 | 2141 | /* if the packet is protected, then it must be CCMP or GCMP */ |
| @@ -2130,14 +2158,11 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, · 16 unmodified lines | ||
| 2130 | 2158 | (3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr)) + iv_len; |
| 2131 | 2159 | |
| 2132 | 2160 | /* Our device supports 9 segments at most, it will fit in 1 page */ |
| 2133 | − hdr_page = get_page_hdr(trans, hdr_room); | |
| 2161 | + hdr_page = get_page_hdr(trans, hdr_room, skb); | |
| 2134 | 2162 | if (!hdr_page) |
| 2135 | 2163 | return -ENOMEM; |
| 2136 | 2164 | |
| 2137 | − get_page(hdr_page->page); | |
| 2138 | 2165 | start_hdr = hdr_page->pos; |
| 2139 | − page_ptr = (void *)((u8 *)skb->cb + trans_pcie->page_offs); | |
| 2140 | − *page_ptr = hdr_page->page; | |
| 2141 | 2166 | memcpy(hdr_page->pos, skb->data + hdr_len, iv_len); |
| 2142 | 2167 | hdr_page->pos += iv_len; |
| 2143 | 2168 | |
| @@ -2279,7 +2304,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, · 135 unmodified lines | ||
| 2279 | 2304 | static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, |
| 2280 | 2305 | struct iwl_txq *txq, u8 hdr_len, |
| 2281 | 2306 | struct iwl_cmd_meta *out_meta, |
| 2282 | − struct iwl_device_cmd *dev_cmd, u16 tb1_len) | |
| 2307 | + struct iwl_device_tx_cmd *dev_cmd, | |
| 2308 | + u16 tb1_len) | |
| 2283 | 2309 | { |
| 2284 | 2310 | /* No A-MSDU without CONFIG_INET */ |
| 2285 | 2311 | WARN_ON(1); |
| @@ -2289,7 +2315,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, · 3 unmodified lines | ||
| 2289 | 2315 | #endif /* CONFIG_INET */ |
| 2290 | 2316 | |
| 2291 | 2317 | int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, |
| 2292 | − struct iwl_device_cmd *dev_cmd, int txq_id) | |
| 2318 | + struct iwl_device_tx_cmd *dev_cmd, int txq_id) | |
| 2293 | 2319 | { |
| 2294 | 2320 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 2295 | 2321 | struct ieee80211_hdr *hdr; |
| @@ -2346,7 +2372,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, · 50 unmodified lines | ||
| 2346 | 2372 | |
| 2347 | 2373 | /* don't put the packet on the ring, if there is no room */ |
| 2348 | 2374 | if (unlikely(iwl_queue_space(trans, txq) < 3)) { |
| 2349 | − struct iwl_device_cmd **dev_cmd_ptr; | |
| 2375 | + struct iwl_device_tx_cmd **dev_cmd_ptr; | |
| 2350 | 2376 | |
| 2351 | 2377 | dev_cmd_ptr = (void *)((u8 *)skb->cb + |
| 2352 | 2378 | trans_pcie->dev_cmd_offs); |
| @@ -273,6 +273,10 @@ add_ie_rates(u8 *tlv, const u8 *ie, int *nrates) · 272 unmodified lines | ||
| 273 | 273 | int hw, ap, ap_max = ie[1]; |
| 274 | 274 | u8 hw_rate; |
| 275 | 275 | |
| 276 | + if (ap_max > MAX_RATES) { | |
| 277 | + lbs_deb_assoc("invalid rates\n"); | |
| 278 | + return tlv; | |
| 279 | + } | |
| 276 | 280 | /* Advance past IE header */ |
| 277 | 281 | ie += 2; |
| 278 | 282 | |
| @@ -1717,6 +1721,9 @@ static int lbs_ibss_join_existing(struct lbs_private *priv, · 1438 unmodified lines | ||
| 1717 | 1721 | struct cmd_ds_802_11_ad_hoc_join cmd; |
| 1718 | 1722 | u8 preamble = RADIO_PREAMBLE_SHORT; |
| 1719 | 1723 | int ret = 0; |
| 1724 | + int hw, i; | |
| 1725 | + u8 rates_max; | |
| 1726 | + u8 *rates; | |
| 1720 | 1727 | |
| 1721 | 1728 | /* TODO: set preamble based on scan result */ |
| 1722 | 1729 | ret = lbs_set_radio(priv, preamble, 1); |
| @@ -1775,9 +1782,12 @@ static int lbs_ibss_join_existing(struct lbs_private *priv, · 52 unmodified lines | ||
| 1775 | 1782 | if (!rates_eid) { |
| 1776 | 1783 | lbs_add_rates(cmd.bss.rates); |
| 1777 | 1784 | } else { |
| 1778 | − int hw, i; | |
| 1779 | − u8 rates_max = rates_eid[1]; | |
| 1780 | − u8 *rates = cmd.bss.rates; | |
| 1785 | + rates_max = rates_eid[1]; | |
| 1786 | + if (rates_max > MAX_RATES) { | |
| 1787 | + lbs_deb_join("invalid rates"); | |
| 1788 | + goto out; | |
| 1789 | + } | |
| 1790 | + rates = cmd.bss.rates; | |
| 1781 | 1791 | for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) { |
| 1782 | 1792 | u8 hw_rate = lbs_rates[hw].bitrate / 5; |
| 1783 | 1793 | for (i = 0; i < rates_max; i++) { |
| @@ -242,7 +242,7 @@ u32 mt76_calc_rx_airtime(struct mt76_dev *dev, struct mt76_rx_status *status, · 241 unmodified lines | ||
| 242 | 242 | return 0; |
| 243 | 243 | |
| 244 | 244 | sband = dev->hw->wiphy->bands[status->band]; |
| 245 | − if (!sband || status->rate_idx > sband->n_bitrates) | |
| 245 | + if (!sband || status->rate_idx >= sband->n_bitrates) | |
| 246 | 246 | return 0; |
| 247 | 247 | |
| 248 | 248 | rate = &sband->bitrates[status->rate_idx]; |
| @@ -378,7 +378,8 @@ void mt76_unregister_device(struct mt76_dev *dev) · 377 unmodified lines | ||
| 378 | 378 | { |
| 379 | 379 | struct ieee80211_hw *hw = dev->hw; |
| 380 | 380 | |
| 381 | − mt76_led_cleanup(dev); | |
| 381 | + if (IS_ENABLED(CONFIG_MT76_LEDS)) | |
| 382 | + mt76_led_cleanup(dev); | |
| 382 | 383 | mt76_tx_status_check(dev, NULL, true); |
| 383 | 384 | ieee80211_unregister_hw(hw); |
| 384 | 385 | } |
| @@ -3698,6 +3698,8 @@ int dev_set_alias(struct net_device *, const char *, size_t); · 3697 unmodified lines | ||
| 3698 | 3698 | int dev_get_alias(const struct net_device *, char *, size_t); |
| 3699 | 3699 | int dev_change_net_namespace(struct net_device *, struct net *, const char *); |
| 3700 | 3700 | int __dev_set_mtu(struct net_device *, int); |
| 3701 | +int dev_validate_mtu(struct net_device *dev, int mtu, | |
| 3702 | + struct netlink_ext_ack *extack); | |
| 3701 | 3703 | int dev_set_mtu_ext(struct net_device *dev, int mtu, |
| 3702 | 3704 | struct netlink_ext_ack *extack); |
| 3703 | 3705 | int dev_set_mtu(struct net_device *, int); |
| @@ -426,13 +426,6 @@ ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr) · 425 unmodified lines | ||
| 426 | 426 | sizeof(*addr)); |
| 427 | 427 | } |
| 428 | 428 | |
| 429 | −/* Calculate the bytes required to store the inclusive range of a-b */ | |
| 430 | −static inline int | |
| 431 | −bitmap_bytes(u32 a, u32 b) | |
| 432 | −{ | |
| 433 | − return 4 * ((((b - a + 8) / 8) + 3) / 4); | |
| 434 | −} | |
| 435 | − | |
| 436 | 429 | /* How often should the gc be run by default */ |
| 437 | 430 | #define IPSET_GC_TIME (3 * 60) |
| 438 | 431 | |
| @@ -31,7 +31,7 @@ struct nfnetlink_subsystem { · 30 unmodified lines | ||
| 31 | 31 | const struct nfnl_callback *cb; /* callback for individual types */ |
| 32 | 32 | struct module *owner; |
| 33 | 33 | int (*commit)(struct net *net, struct sk_buff *skb); |
| 34 | − int (*abort)(struct net *net, struct sk_buff *skb); | |
| 34 | + int (*abort)(struct net *net, struct sk_buff *skb, bool autoload); | |
| 35 | 35 | void (*cleanup)(struct net *net); |
| 36 | 36 | bool (*valid_genid)(struct net *net, u32 genid); |
| 37 | 37 | }; |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | struct netns_nftables { |
| 8 | 8 | struct list_head tables; |
| 9 | 9 | struct list_head commit_list; |
| 10 | + struct list_head module_list; | |
| 10 | 11 | struct mutex commit_mutex; |
| 11 | 12 | unsigned int base_seq; |
| 12 | 13 | u8 gencursor; |
| @@ -134,8 +134,7 @@ static void vcc_seq_stop(struct seq_file *seq, void *v) · 133 unmodified lines | ||
| 134 | 134 | static void *vcc_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
| 135 | 135 | { |
| 136 | 136 | v = vcc_walk(seq, 1); |
| 137 | − if (v) | |
| 138 | − (*pos)++; | |
| 137 | + (*pos)++; | |
| 139 | 138 | return v; |
| 140 | 139 | } |
| 141 | 140 | |
| @@ -62,7 +62,7 @@ static int cfusbl_transmit(struct cflayer *layr, struct cfpkt *pkt) · 61 unmodified lines | ||
| 62 | 62 | hpad = (info->hdr_len + CFUSB_PAD_DESCR_SZ) & (CFUSB_ALIGNMENT - 1); |
| 63 | 63 | |
| 64 | 64 | if (skb_headroom(skb) < ETH_HLEN + CFUSB_PAD_DESCR_SZ + hpad) { |
| 65 | − pr_warn("Headroom to small\n"); | |
| 65 | + pr_warn("Headroom too small\n"); | |
| 66 | 66 | kfree_skb(skb); |
| 67 | 67 | return -EIO; |
| 68 | 68 | } |
| @@ -5491,9 +5491,29 @@ static void flush_all_backlogs(void) · 5490 unmodified lines | ||
| 5491 | 5491 | put_online_cpus(); |
| 5492 | 5492 | } |
| 5493 | 5493 | |
| 5494 | +/* Pass the currently batched GRO_NORMAL SKBs up to the stack. */ | |
| 5495 | +static void gro_normal_list(struct napi_struct *napi) | |
| 5496 | +{ | |
| 5497 | + if (!napi->rx_count) | |
| 5498 | + return; | |
| 5499 | + netif_receive_skb_list_internal(&napi->rx_list); | |
| 5500 | + INIT_LIST_HEAD(&napi->rx_list); | |
| 5501 | + napi->rx_count = 0; | |
| 5502 | +} | |
| 5503 | + | |
| 5504 | +/* Queue one GRO_NORMAL SKB up for list processing. If batch size exceeded, | |
| 5505 | + * pass the whole batch up to the stack. | |
| 5506 | + */ | |
| 5507 | +static void gro_normal_one(struct napi_struct *napi, struct sk_buff *skb) | |
| 5508 | +{ | |
| 5509 | + list_add_tail(&skb->list, &napi->rx_list); | |
| 5510 | + if (++napi->rx_count >= gro_normal_batch) | |
| 5511 | + gro_normal_list(napi); | |
| 5512 | +} | |
| 5513 | + | |
| 5494 | 5514 | INDIRECT_CALLABLE_DECLARE(int inet_gro_complete(struct sk_buff *, int)); |
| 5495 | 5515 | INDIRECT_CALLABLE_DECLARE(int ipv6_gro_complete(struct sk_buff *, int)); |
| 5496 | −static int napi_gro_complete(struct sk_buff *skb) | |
| 5516 | +static int napi_gro_complete(struct napi_struct *napi, struct sk_buff *skb) | |
| 5497 | 5517 | { |
| 5498 | 5518 | struct packet_offload *ptype; |
| 5499 | 5519 | __be16 type = skb->protocol; |
| @@ -5526,7 +5546,8 @@ static int napi_gro_complete(struct sk_buff *skb) · 26 unmodified lines | ||
| 5526 | 5546 | } |
| 5527 | 5547 | |
| 5528 | 5548 | out: |
| 5529 | − return netif_receive_skb_internal(skb); | |
| 5549 | + gro_normal_one(napi, skb); | |
| 5550 | + return NET_RX_SUCCESS; | |
| 5530 | 5551 | } |
| 5531 | 5552 | |
| 5532 | 5553 | static void __napi_gro_flush_chain(struct napi_struct *napi, u32 index, |
| @@ -5539,7 +5560,7 @@ static void __napi_gro_flush_chain(struct napi_struct *napi, u32 index, · 6 unmodified lines | ||
| 5539 | 5560 | if (flush_old && NAPI_GRO_CB(skb)->age == jiffies) |
| 5540 | 5561 | return; |
| 5541 | 5562 | skb_list_del_init(skb); |
| 5542 | − napi_gro_complete(skb); | |
| 5563 | + napi_gro_complete(napi, skb); | |
| 5543 | 5564 | napi->gro_hash[index].count--; |
| 5544 | 5565 | } |
| 5545 | 5566 | |
| @@ -5641,7 +5662,7 @@ static void gro_pull_from_frag0(struct sk_buff *skb, int grow) · 95 unmodified lines | ||
| 5641 | 5662 | } |
| 5642 | 5663 | } |
| 5643 | 5664 | |
| 5644 | −static void gro_flush_oldest(struct list_head *head) | |
| 5665 | +static void gro_flush_oldest(struct napi_struct *napi, struct list_head *head) | |
| 5645 | 5666 | { |
| 5646 | 5667 | struct sk_buff *oldest; |
| 5647 | 5668 | |
| @@ -5657,7 +5678,7 @@ static void gro_flush_oldest(struct list_head *head) · 9 unmodified lines | ||
| 5657 | 5678 | * SKB to the chain. |
| 5658 | 5679 | */ |
| 5659 | 5680 | skb_list_del_init(oldest); |
| 5660 | − napi_gro_complete(oldest); | |
| 5681 | + napi_gro_complete(napi, oldest); | |
| 5661 | 5682 | } |
| 5662 | 5683 | |
| 5663 | 5684 | INDIRECT_CALLABLE_DECLARE(struct sk_buff *inet_gro_receive(struct list_head *, |
| @@ -5733,7 +5754,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff · 69 unmodified lines | ||
| 5733 | 5754 | |
| 5734 | 5755 | if (pp) { |
| 5735 | 5756 | skb_list_del_init(pp); |
| 5736 | − napi_gro_complete(pp); | |
| 5757 | + napi_gro_complete(napi, pp); | |
| 5737 | 5758 | napi->gro_hash[hash].count--; |
| 5738 | 5759 | } |
| 5739 | 5760 | |
| @@ -5744,7 +5765,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff · 4 unmodified lines | ||
| 5744 | 5765 | goto normal; |
| 5745 | 5766 | |
| 5746 | 5767 | if (unlikely(napi->gro_hash[hash].count >= MAX_GRO_SKBS)) { |
| 5747 | − gro_flush_oldest(gro_head); | |
| 5768 | + gro_flush_oldest(napi, gro_head); | |
| 5748 | 5769 | } else { |
| 5749 | 5770 | napi->gro_hash[hash].count++; |
| 5750 | 5771 | } |
| @@ -5802,26 +5823,6 @@ struct packet_offload *gro_find_complete_by_type(__be16 type) · 51 unmodified lines | ||
| 5802 | 5823 | } |
| 5803 | 5824 | EXPORT_SYMBOL(gro_find_complete_by_type); |
| 5804 | 5825 | |
| 5805 | −/* Pass the currently batched GRO_NORMAL SKBs up to the stack. */ | |
| 5806 | −static void gro_normal_list(struct napi_struct *napi) | |
| 5807 | −{ | |
| 5808 | − if (!napi->rx_count) | |
| 5809 | − return; | |
| 5810 | − netif_receive_skb_list_internal(&napi->rx_list); | |
| 5811 | − INIT_LIST_HEAD(&napi->rx_list); | |
| 5812 | − napi->rx_count = 0; | |
| 5813 | −} | |
| 5814 | − | |
| 5815 | −/* Queue one GRO_NORMAL SKB up for list processing. If batch size exceeded, | |
| 5816 | − * pass the whole batch up to the stack. | |
| 5817 | − */ | |
| 5818 | −static void gro_normal_one(struct napi_struct *napi, struct sk_buff *skb) | |
| 5819 | −{ | |
| 5820 | − list_add_tail(&skb->list, &napi->rx_list); | |
| 5821 | − if (++napi->rx_count >= gro_normal_batch) | |
| 5822 | − gro_normal_list(napi); | |
| 5823 | −} | |
| 5824 | − | |
| 5825 | 5826 | static void napi_skb_free_stolen_head(struct sk_buff *skb) |
| 5826 | 5827 | { |
| 5827 | 5828 | skb_dst_drop(skb); |
| @@ -6200,8 +6201,6 @@ bool napi_complete_done(struct napi_struct *n, int work_done) · 372 unmodified lines | ||
| 6200 | 6201 | NAPIF_STATE_IN_BUSY_POLL))) |
| 6201 | 6202 | return false; |
| 6202 | 6203 | |
| 6203 | − gro_normal_list(n); | |
| 6204 | − | |
| 6205 | 6204 | if (n->gro_bitmask) { |
| 6206 | 6205 | unsigned long timeout = 0; |
| 6207 | 6206 | |
| @@ -6217,6 +6216,9 @@ bool napi_complete_done(struct napi_struct *n, int work_done) · 9 unmodified lines | ||
| 6217 | 6216 | hrtimer_start(&n->timer, ns_to_ktime(timeout), |
| 6218 | 6217 | HRTIMER_MODE_REL_PINNED); |
| 6219 | 6218 | } |
| 6219 | + | |
| 6220 | + gro_normal_list(n); | |
| 6221 | + | |
| 6220 | 6222 | if (unlikely(!list_empty(&n->poll_list))) { |
| 6221 | 6223 | /* If n->poll_list is not empty, we need to mask irqs */ |
| 6222 | 6224 | local_irq_save(flags); |
| @@ -6548,8 +6550,6 @@ static int napi_poll(struct napi_struct *n, struct list_head *repoll) · 325 unmodified lines | ||
| 6548 | 6550 | goto out_unlock; |
| 6549 | 6551 | } |
| 6550 | 6552 | |
| 6551 | − gro_normal_list(n); | |
| 6552 | − | |
| 6553 | 6553 | if (n->gro_bitmask) { |
| 6554 | 6554 | /* flush too old packets |
| 6555 | 6555 | * If HZ < 1000, flush all packets. |
| @@ -6557,6 +6557,8 @@ static int napi_poll(struct napi_struct *n, struct list_head *repoll) · 1 unmodified line | ||
| 6557 | 6557 | napi_gro_flush(n, HZ >= 1000); |
| 6558 | 6558 | } |
| 6559 | 6559 | |
| 6560 | + gro_normal_list(n); | |
| 6561 | + | |
| 6560 | 6562 | /* Some drivers may have called napi_schedule |
| 6561 | 6563 | * prior to exhausting their budget. |
| 6562 | 6564 | */ |
| @@ -8194,6 +8196,22 @@ int __dev_set_mtu(struct net_device *dev, int new_mtu) · 1631 unmodified lines | ||
| 8194 | 8196 | } |
| 8195 | 8197 | EXPORT_SYMBOL(__dev_set_mtu); |
| 8196 | 8198 | |
| 8199 | +int dev_validate_mtu(struct net_device *dev, int new_mtu, | |
| 8200 | + struct netlink_ext_ack *extack) | |
| 8201 | +{ | |
| 8202 | + /* MTU must be positive, and in range */ | |
| 8203 | + if (new_mtu < 0 || new_mtu < dev->min_mtu) { | |
| 8204 | + NL_SET_ERR_MSG(extack, "mtu less than device minimum"); | |
| 8205 | + return -EINVAL; | |
| 8206 | + } | |
| 8207 | + | |
| 8208 | + if (dev->max_mtu > 0 && new_mtu > dev->max_mtu) { | |
| 8209 | + NL_SET_ERR_MSG(extack, "mtu greater than device maximum"); | |
| 8210 | + return -EINVAL; | |
| 8211 | + } | |
| 8212 | + return 0; | |
| 8213 | +} | |
| 8214 | + | |
| 8197 | 8215 | /** |
| 8198 | 8216 | * dev_set_mtu_ext - Change maximum transfer unit |
| 8199 | 8217 | * @dev: device |
| @@ -8210,16 +8228,9 @@ int dev_set_mtu_ext(struct net_device *dev, int new_mtu, · 10 unmodified lines | ||
| 8210 | 8228 | if (new_mtu == dev->mtu) |
| 8211 | 8229 | return 0; |
| 8212 | 8230 | |
| 8213 | − /* MTU must be positive, and in range */ | |
| 8214 | − if (new_mtu < 0 || new_mtu < dev->min_mtu) { | |
| 8215 | − NL_SET_ERR_MSG(extack, "mtu less than device minimum"); | |
| 8216 | − return -EINVAL; | |
| 8217 | − } | |
| 8218 | − | |
| 8219 | − if (dev->max_mtu > 0 && new_mtu > dev->max_mtu) { | |
| 8220 | − NL_SET_ERR_MSG(extack, "mtu greater than device maximum"); | |
| 8221 | − return -EINVAL; | |
| 8222 | − } | |
| 8231 | + err = dev_validate_mtu(dev, new_mtu, extack); | |
| 8232 | + if (err) | |
| 8233 | + return err; | |
| 8223 | 8234 | |
| 8224 | 8235 | if (!netif_device_present(dev)) |
| 8225 | 8236 | return -ENODEV; |
| @@ -9302,8 +9313,10 @@ int register_netdevice(struct net_device *dev) · 1076 unmodified lines | ||
| 9302 | 9313 | goto err_uninit; |
| 9303 | 9314 | |
| 9304 | 9315 | ret = netdev_register_kobject(dev); |
| 9305 | − if (ret) | |
| 9316 | + if (ret) { | |
| 9317 | + dev->reg_state = NETREG_UNREGISTERED; | |
| 9306 | 9318 | goto err_uninit; |
| 9319 | + } | |
| 9307 | 9320 | dev->reg_state = NETREG_REGISTERED; |
| 9308 | 9321 | |
| 9309 | 9322 | __netdev_update_features(dev); |
| @@ -3290,6 +3290,7 @@ static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos) · 3289 unmodified lines | ||
| 3290 | 3290 | *pos = cpu+1; |
| 3291 | 3291 | return per_cpu_ptr(tbl->stats, cpu); |
| 3292 | 3292 | } |
| 3293 | + (*pos)++; | |
| 3293 | 3294 | return NULL; |
| 3294 | 3295 | } |
| 3295 | 3296 | |
| @@ -3048,8 +3048,17 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname, · 3047 unmodified lines | ||
| 3048 | 3048 | dev->rtnl_link_ops = ops; |
| 3049 | 3049 | dev->rtnl_link_state = RTNL_LINK_INITIALIZING; |
| 3050 | 3050 | |
| 3051 | − if (tb[IFLA_MTU]) | |
| 3052 | − dev->mtu = nla_get_u32(tb[IFLA_MTU]); | |
| 3051 | + if (tb[IFLA_MTU]) { | |
| 3052 | + u32 mtu = nla_get_u32(tb[IFLA_MTU]); | |
| 3053 | + int err; | |
| 3054 | + | |
| 3055 | + err = dev_validate_mtu(dev, mtu, extack); | |
| 3056 | + if (err) { | |
| 3057 | + free_netdev(dev); | |
| 3058 | + return ERR_PTR(err); | |
| 3059 | + } | |
| 3060 | + dev->mtu = mtu; | |
| 3061 | + } | |
| 3053 | 3062 | if (tb[IFLA_ADDRESS]) { |
| 3054 | 3063 | memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]), |
| 3055 | 3064 | nla_len(tb[IFLA_ADDRESS])); |
| @@ -594,8 +594,6 @@ EXPORT_SYMBOL_GPL(sk_psock_destroy); · 593 unmodified lines | ||
| 594 | 594 | |
| 595 | 595 | void sk_psock_drop(struct sock *sk, struct sk_psock *psock) |
| 596 | 596 | { |
| 597 | − sock_owned_by_me(sk); | |
| 598 | − | |
| 599 | 597 | sk_psock_cork_free(psock); |
| 600 | 598 | sk_psock_zap_ingress(psock); |
| 601 | 599 | |
| @@ -438,6 +438,23 @@ void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, · 437 unmodified lines | ||
| 438 | 438 | } |
| 439 | 439 | EXPORT_SYMBOL(inet_proto_csum_replace4); |
| 440 | 440 | |
| 441 | +/** | |
| 442 | + * inet_proto_csum_replace16 - update layer 4 header checksum field | |
| 443 | + * @sum: Layer 4 header checksum field | |
| 444 | + * @skb: sk_buff for the packet | |
| 445 | + * @from: old IPv6 address | |
| 446 | + * @to: new IPv6 address | |
| 447 | + * @pseudohdr: True if layer 4 header checksum includes pseudoheader | |
| 448 | + * | |
| 449 | + * Update layer 4 header as per the update in IPv6 src/dst address. | |
| 450 | + * | |
| 451 | + * There is no need to update skb->csum in this function, because update in two | |
| 452 | + * fields a.) IPv6 src/dst address and b.) L4 header checksum cancels each other | |
| 453 | + * for skb->csum calculation. Whereas inet_proto_csum_replace4 function needs to | |
| 454 | + * update skb->csum, because update in 3 fields a.) IPv4 src/dst address, | |
| 455 | + * b.) IPv4 Header checksum and c.) L4 header checksum results in same diff as | |
| 456 | + * L4 Header checksum for skb->csum calculation. | |
| 457 | + */ | |
| 441 | 458 | void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, |
| 442 | 459 | const __be32 *from, const __be32 *to, |
| 443 | 460 | bool pseudohdr) |
| @@ -449,9 +466,6 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, · 5 unmodified lines | ||
| 449 | 466 | if (skb->ip_summed != CHECKSUM_PARTIAL) { |
| 450 | 467 | *sum = csum_fold(csum_partial(diff, sizeof(diff), |
| 451 | 468 | ~csum_unfold(*sum))); |
| 452 | − if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) | |
| 453 | − skb->csum = ~csum_partial(diff, sizeof(diff), | |
| 454 | − ~skb->csum); | |
| 455 | 469 | } else if (pseudohdr) |
| 456 | 470 | *sum = ~csum_fold(csum_partial(diff, sizeof(diff), |
| 457 | 471 | csum_unfold(*sum))); |
| @@ -191,7 +191,7 @@ void hsr_debugfs_term(struct hsr_priv *priv); · 190 unmodified lines | ||
| 191 | 191 | void hsr_debugfs_create_root(void); |
| 192 | 192 | void hsr_debugfs_remove_root(void); |
| 193 | 193 | #else |
| 194 | −static inline void void hsr_debugfs_rename(struct net_device *dev) | |
| 194 | +static inline void hsr_debugfs_rename(struct net_device *dev) | |
| 195 | 195 | { |
| 196 | 196 | } |
| 197 | 197 | static inline void hsr_debugfs_init(struct hsr_priv *priv, |
| @@ -57,6 +57,8 @@ static struct sk_buff *esp4_gro_receive(struct list_head *head, · 56 unmodified lines | ||
| 57 | 57 | if (!x) |
| 58 | 58 | goto out_reset; |
| 59 | 59 | |
| 60 | + skb->mark = xfrm_smark_get(skb->mark, x); | |
| 61 | + | |
| 60 | 62 | sp->xvec[sp->len++] = x; |
| 61 | 63 | sp->olen++; |
| 62 | 64 | |
| @@ -662,8 +662,8 @@ static const struct nla_policy fou_nl_policy[FOU_ATTR_MAX + 1] = { · 661 unmodified lines | ||
| 662 | 662 | [FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG, }, |
| 663 | 663 | [FOU_ATTR_LOCAL_V4] = { .type = NLA_U32, }, |
| 664 | 664 | [FOU_ATTR_PEER_V4] = { .type = NLA_U32, }, |
| 665 | − [FOU_ATTR_LOCAL_V6] = { .type = sizeof(struct in6_addr), }, | |
| 666 | − [FOU_ATTR_PEER_V6] = { .type = sizeof(struct in6_addr), }, | |
| 665 | + [FOU_ATTR_LOCAL_V6] = { .len = sizeof(struct in6_addr), }, | |
| 666 | + [FOU_ATTR_PEER_V6] = { .len = sizeof(struct in6_addr), }, | |
| 667 | 667 | [FOU_ATTR_PEER_PORT] = { .type = NLA_U16, }, |
| 668 | 668 | [FOU_ATTR_IFINDEX] = { .type = NLA_S32, }, |
| 669 | 669 | }; |
| @@ -1236,10 +1236,8 @@ int ip_tunnel_init(struct net_device *dev) · 1235 unmodified lines | ||
| 1236 | 1236 | iph->version = 4; |
| 1237 | 1237 | iph->ihl = 5; |
| 1238 | 1238 | |
| 1239 | − if (tunnel->collect_md) { | |
| 1240 | − dev->features |= NETIF_F_NETNS_LOCAL; | |
| 1239 | + if (tunnel->collect_md) | |
| 1241 | 1240 | netif_keep_dst(dev); |
| 1242 | − } | |
| 1243 | 1241 | return 0; |
| 1244 | 1242 | } |
| 1245 | 1243 | EXPORT_SYMBOL_GPL(ip_tunnel_init); |
| @@ -187,8 +187,17 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, · 186 unmodified lines | ||
| 187 | 187 | int mtu; |
| 188 | 188 | |
| 189 | 189 | if (!dst) { |
| 190 | − dev->stats.tx_carrier_errors++; | |
| 191 | − goto tx_error_icmp; | |
| 190 | + struct rtable *rt; | |
| 191 | + | |
| 192 | + fl->u.ip4.flowi4_oif = dev->ifindex; | |
| 193 | + fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC; | |
| 194 | + rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4); | |
| 195 | + if (IS_ERR(rt)) { | |
| 196 | + dev->stats.tx_carrier_errors++; | |
| 197 | + goto tx_error_icmp; | |
| 198 | + } | |
| 199 | + dst = &rt->dst; | |
| 200 | + skb_dst_set(skb, dst); | |
| 192 | 201 | } |
| 193 | 202 | |
| 194 | 203 | dst_hold(dst); |
| @@ -271,6 +271,7 @@ static void *rt_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) · 270 unmodified lines | ||
| 271 | 271 | *pos = cpu+1; |
| 272 | 272 | return &per_cpu(rt_cache_stat, cpu); |
| 273 | 273 | } |
| 274 | + (*pos)++; | |
| 274 | 275 | return NULL; |
| 275 | 276 | |
| 276 | 277 | } |
| @@ -2524,6 +2524,7 @@ static void tcp_rtx_queue_purge(struct sock *sk) · 2523 unmodified lines | ||
| 2524 | 2524 | { |
| 2525 | 2525 | struct rb_node *p = rb_first(&sk->tcp_rtx_queue); |
| 2526 | 2526 | |
| 2527 | + tcp_sk(sk)->highest_sack = NULL; | |
| 2527 | 2528 | while (p) { |
| 2528 | 2529 | struct sk_buff *skb = rb_to_skb(p); |
| 2529 | 2530 | |
| @@ -2614,7 +2615,6 @@ int tcp_disconnect(struct sock *sk, int flags) · 84 unmodified lines | ||
| 2614 | 2615 | WRITE_ONCE(tp->write_seq, seq); |
| 2615 | 2616 | |
| 2616 | 2617 | icsk->icsk_backoff = 0; |
| 2617 | − tp->snd_cwnd = 2; | |
| 2618 | 2618 | icsk->icsk_probes_out = 0; |
| 2619 | 2619 | icsk->icsk_rto = TCP_TIMEOUT_INIT; |
| 2620 | 2620 | tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; |
| @@ -779,8 +779,7 @@ static void bbr_update_bw(struct sock *sk, const struct rate_sample *rs) · 778 unmodified lines | ||
| 779 | 779 | * bandwidth sample. Delivered is in packets and interval_us in uS and |
| 780 | 780 | * ratio will be <<1 for most connections. So delivered is first scaled. |
| 781 | 781 | */ |
| 782 | − bw = (u64)rs->delivered * BW_UNIT; | |
| 783 | − do_div(bw, rs->interval_us); | |
| 782 | + bw = div64_long((u64)rs->delivered * BW_UNIT, rs->interval_us); | |
| 784 | 783 | |
| 785 | 784 | /* If this sample is application-limited, it is likely to have a very |
| 786 | 785 | * low delivered count that represents application behavior rather than |
| @@ -3164,6 +3164,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, u32 prior_fack, · 3163 unmodified lines | ||
| 3164 | 3164 | tp->retransmit_skb_hint = NULL; |
| 3165 | 3165 | if (unlikely(skb == tp->lost_skb_hint)) |
| 3166 | 3166 | tp->lost_skb_hint = NULL; |
| 3167 | + tcp_highest_sack_replace(sk, skb, next); | |
| 3167 | 3168 | tcp_rtx_queue_unlink_and_free(skb, sk); |
| 3168 | 3169 | } |
| 3169 | 3170 | |
| @@ -3232,6 +3232,7 @@ int tcp_send_synack(struct sock *sk) · 3231 unmodified lines | ||
| 3232 | 3232 | if (!nskb) |
| 3233 | 3233 | return -ENOMEM; |
| 3234 | 3234 | INIT_LIST_HEAD(&nskb->tcp_tsorted_anchor); |
| 3235 | + tcp_highest_sack_replace(sk, skb, nskb); | |
| 3235 | 3236 | tcp_rtx_queue_unlink_and_free(skb, sk); |
| 3236 | 3237 | __skb_header_release(nskb); |
| 3237 | 3238 | tcp_rbtree_insert(&sk->tcp_rtx_queue, nskb); |
| @@ -1368,7 +1368,8 @@ static void udp_rmem_release(struct sock *sk, int size, int partial, · 1367 unmodified lines | ||
| 1368 | 1368 | if (likely(partial)) { |
| 1369 | 1369 | up->forward_deficit += size; |
| 1370 | 1370 | size = up->forward_deficit; |
| 1371 | − if (size < (sk->sk_rcvbuf >> 2)) | |
| 1371 | + if (size < (sk->sk_rcvbuf >> 2) && | |
| 1372 | + !skb_queue_empty(&up->reader_queue)) | |
| 1372 | 1373 | return; |
| 1373 | 1374 | } else { |
| 1374 | 1375 | size += up->forward_deficit; |
| @@ -79,6 +79,8 @@ static struct sk_buff *esp6_gro_receive(struct list_head *head, · 78 unmodified lines | ||
| 79 | 79 | if (!x) |
| 80 | 80 | goto out_reset; |
| 81 | 81 | |
| 82 | + skb->mark = xfrm_smark_get(skb->mark, x); | |
| 83 | + | |
| 82 | 84 | sp->xvec[sp->len++] = x; |
| 83 | 85 | sp->olen++; |
| 84 | 86 | |
| @@ -2495,14 +2495,13 @@ static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos) · 2494 unmodified lines | ||
| 2495 | 2495 | struct net *net = seq_file_net(seq); |
| 2496 | 2496 | struct ipv6_route_iter *iter = seq->private; |
| 2497 | 2497 | |
| 2498 | + ++(*pos); | |
| 2498 | 2499 | if (!v) |
| 2499 | 2500 | goto iter_table; |
| 2500 | 2501 | |
| 2501 | 2502 | n = rcu_dereference_bh(((struct fib6_info *)v)->fib6_next); |
| 2502 | − if (n) { | |
| 2503 | − ++*pos; | |
| 2503 | + if (n) | |
| 2504 | 2504 | return n; |
| 2505 | − } | |
| 2506 | 2505 | |
| 2507 | 2506 | iter_table: |
| 2508 | 2507 | ipv6_route_check_sernum(iter); |
| @@ -2510,8 +2509,6 @@ iter_table: · 1 unmodified line | ||
| 2510 | 2509 | r = fib6_walk_continue(&iter->w); |
| 2511 | 2510 | spin_unlock_bh(&iter->tbl->tb6_lock); |
| 2512 | 2511 | if (r > 0) { |
| 2513 | − if (v) | |
| 2514 | − ++*pos; | |
| 2515 | 2512 | return iter->w.leaf; |
| 2516 | 2513 | } else if (r < 0) { |
| 2517 | 2514 | fib6_walker_unlink(net, &iter->w); |
| @@ -1466,7 +1466,6 @@ static int ip6gre_tunnel_init_common(struct net_device *dev) · 1465 unmodified lines | ||
| 1466 | 1466 | dev->mtu -= 8; |
| 1467 | 1467 | |
| 1468 | 1468 | if (tunnel->parms.collect_md) { |
| 1469 | − dev->features |= NETIF_F_NETNS_LOCAL; | |
| 1470 | 1469 | netif_keep_dst(dev); |
| 1471 | 1470 | } |
| 1472 | 1471 | ip6gre_tnl_init_features(dev); |
| @@ -1894,7 +1893,6 @@ static void ip6gre_tap_setup(struct net_device *dev) · 421 unmodified lines | ||
| 1894 | 1893 | dev->needs_free_netdev = true; |
| 1895 | 1894 | dev->priv_destructor = ip6gre_dev_free; |
| 1896 | 1895 | |
| 1897 | − dev->features |= NETIF_F_NETNS_LOCAL; | |
| 1898 | 1896 | dev->priv_flags &= ~IFF_TX_SKB_SHARING; |
| 1899 | 1897 | dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; |
| 1900 | 1898 | netif_keep_dst(dev); |
| @@ -2197,7 +2195,6 @@ static void ip6erspan_tap_setup(struct net_device *dev) · 296 unmodified lines | ||
| 2197 | 2195 | dev->needs_free_netdev = true; |
| 2198 | 2196 | dev->priv_destructor = ip6gre_dev_free; |
| 2199 | 2197 | |
| 2200 | − dev->features |= NETIF_F_NETNS_LOCAL; | |
| 2201 | 2198 | dev->priv_flags &= ~IFF_TX_SKB_SHARING; |
| 2202 | 2199 | dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; |
| 2203 | 2200 | netif_keep_dst(dev); |
| @@ -1877,10 +1877,8 @@ static int ip6_tnl_dev_init(struct net_device *dev) · 1876 unmodified lines | ||
| 1877 | 1877 | if (err) |
| 1878 | 1878 | return err; |
| 1879 | 1879 | ip6_tnl_link_config(t); |
| 1880 | − if (t->parms.collect_md) { | |
| 1881 | − dev->features |= NETIF_F_NETNS_LOCAL; | |
| 1880 | + if (t->parms.collect_md) | |
| 1882 | 1881 | netif_keep_dst(dev); |
| 1883 | − } | |
| 1884 | 1882 | return 0; |
| 1885 | 1883 | } |
| 1886 | 1884 | |
| @@ -449,8 +449,17 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) · 448 unmodified lines | ||
| 449 | 449 | int err = -1; |
| 450 | 450 | int mtu; |
| 451 | 451 | |
| 452 | − if (!dst) | |
| 453 | − goto tx_err_link_failure; | |
| 452 | + if (!dst) { | |
| 453 | + fl->u.ip6.flowi6_oif = dev->ifindex; | |
| 454 | + fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC; | |
| 455 | + dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6); | |
| 456 | + if (dst->error) { | |
| 457 | + dst_release(dst); | |
| 458 | + dst = NULL; | |
| 459 | + goto tx_err_link_failure; | |
| 460 | + } | |
| 461 | + skb_dst_set(skb, dst); | |
| 462 | + } | |
| 454 | 463 | |
| 455 | 464 | dst_hold(dst); |
| 456 | 465 | dst = xfrm_lookup(t->net, dst, fl, NULL, 0); |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <net/addrconf.h> |
| 24 | 24 | #include <net/ip6_route.h> |
| 25 | 25 | #include <net/dst_cache.h> |
| 26 | +#include <net/ip_tunnels.h> | |
| 26 | 27 | #ifdef CONFIG_IPV6_SEG6_HMAC |
| 27 | 28 | #include <net/seg6_hmac.h> |
| 28 | 29 | #endif |
| @@ -135,7 +136,8 @@ static bool decap_and_validate(struct sk_buff *skb, int proto) · 106 unmodified lines | ||
| 135 | 136 | |
| 136 | 137 | skb_reset_network_header(skb); |
| 137 | 138 | skb_reset_transport_header(skb); |
| 138 | − skb->encapsulation = 0; | |
| 139 | + if (iptunnel_pull_offloads(skb)) | |
| 140 | + return false; | |
| 139 | 141 | |
| 140 | 142 | return true; |
| 141 | 143 | } |
| @@ -75,7 +75,7 @@ mtype_flush(struct ip_set *set) · 74 unmodified lines | ||
| 75 | 75 | |
| 76 | 76 | if (set->extensions & IPSET_EXT_DESTROY) |
| 77 | 77 | mtype_ext_cleanup(set); |
| 78 | − memset(map->members, 0, map->memsize); | |
| 78 | + bitmap_zero(map->members, map->elements); | |
| 79 | 79 | set->elements = 0; |
| 80 | 80 | set->ext_size = 0; |
| 81 | 81 | } |
| @@ -37,7 +37,7 @@ MODULE_ALIAS("ip_set_bitmap:ip"); · 36 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | /* Type structure */ |
| 39 | 39 | struct bitmap_ip { |
| 40 | − void *members; /* the set members */ | |
| 40 | + unsigned long *members; /* the set members */ | |
| 41 | 41 | u32 first_ip; /* host byte order, included in range */ |
| 42 | 42 | u32 last_ip; /* host byte order, included in range */ |
| 43 | 43 | u32 elements; /* number of max elements in the set */ |
| @@ -220,7 +220,7 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map, · 176 unmodified lines | ||
| 220 | 220 | u32 first_ip, u32 last_ip, |
| 221 | 221 | u32 elements, u32 hosts, u8 netmask) |
| 222 | 222 | { |
| 223 | − map->members = ip_set_alloc(map->memsize); | |
| 223 | + map->members = bitmap_zalloc(elements, GFP_KERNEL | __GFP_NOWARN); | |
| 224 | 224 | if (!map->members) |
| 225 | 225 | return false; |
| 226 | 226 | map->first_ip = first_ip; |
| @@ -322,7 +322,7 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[], · 95 unmodified lines | ||
| 322 | 322 | if (!map) |
| 323 | 323 | return -ENOMEM; |
| 324 | 324 | |
| 325 | − map->memsize = bitmap_bytes(0, elements - 1); | |
| 325 | + map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long); | |
| 326 | 326 | set->variant = &bitmap_ip; |
| 327 | 327 | if (!init_map_ip(set, map, first_ip, last_ip, |
| 328 | 328 | elements, hosts, netmask)) { |
| @@ -42,7 +42,7 @@ enum { · 41 unmodified lines | ||
| 42 | 42 | |
| 43 | 43 | /* Type structure */ |
| 44 | 44 | struct bitmap_ipmac { |
| 45 | − void *members; /* the set members */ | |
| 45 | + unsigned long *members; /* the set members */ | |
| 46 | 46 | u32 first_ip; /* host byte order, included in range */ |
| 47 | 47 | u32 last_ip; /* host byte order, included in range */ |
| 48 | 48 | u32 elements; /* number of max elements in the set */ |
| @@ -299,7 +299,7 @@ static bool · 250 unmodified lines | ||
| 299 | 299 | init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map, |
| 300 | 300 | u32 first_ip, u32 last_ip, u32 elements) |
| 301 | 301 | { |
| 302 | − map->members = ip_set_alloc(map->memsize); | |
| 302 | + map->members = bitmap_zalloc(elements, GFP_KERNEL | __GFP_NOWARN); | |
| 303 | 303 | if (!map->members) |
| 304 | 304 | return false; |
| 305 | 305 | map->first_ip = first_ip; |
| @@ -360,7 +360,7 @@ bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[], · 54 unmodified lines | ||
| 360 | 360 | if (!map) |
| 361 | 361 | return -ENOMEM; |
| 362 | 362 | |
| 363 | − map->memsize = bitmap_bytes(0, elements - 1); | |
| 363 | + map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long); | |
| 364 | 364 | set->variant = &bitmap_ipmac; |
| 365 | 365 | if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) { |
| 366 | 366 | kfree(map); |
| @@ -30,7 +30,7 @@ MODULE_ALIAS("ip_set_bitmap:port"); · 29 unmodified lines | ||
| 30 | 30 | |
| 31 | 31 | /* Type structure */ |
| 32 | 32 | struct bitmap_port { |
| 33 | − void *members; /* the set members */ | |
| 33 | + unsigned long *members; /* the set members */ | |
| 34 | 34 | u16 first_port; /* host byte order, included in range */ |
| 35 | 35 | u16 last_port; /* host byte order, included in range */ |
| 36 | 36 | u32 elements; /* number of max elements in the set */ |
| @@ -231,7 +231,7 @@ static bool · 194 unmodified lines | ||
| 231 | 231 | init_map_port(struct ip_set *set, struct bitmap_port *map, |
| 232 | 232 | u16 first_port, u16 last_port) |
| 233 | 233 | { |
| 234 | − map->members = ip_set_alloc(map->memsize); | |
| 234 | + map->members = bitmap_zalloc(map->elements, GFP_KERNEL | __GFP_NOWARN); | |
| 235 | 235 | if (!map->members) |
| 236 | 236 | return false; |
| 237 | 237 | map->first_port = first_port; |
| @@ -271,7 +271,7 @@ bitmap_port_create(struct net *net, struct ip_set *set, struct nlattr *tb[], · 33 unmodified lines | ||
| 271 | 271 | return -ENOMEM; |
| 272 | 272 | |
| 273 | 273 | map->elements = elements; |
| 274 | − map->memsize = bitmap_bytes(0, map->elements); | |
| 274 | + map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long); | |
| 275 | 275 | set->variant = &bitmap_port; |
| 276 | 276 | if (!init_map_port(set, map, first_port, last_port)) { |
| 277 | 277 | kfree(map); |
| @@ -1239,7 +1239,7 @@ static void ip_vs_process_message(struct netns_ipvs *ipvs, __u8 *buffer, · 1238 unmodified lines | ||
| 1239 | 1239 | |
| 1240 | 1240 | p = msg_end; |
| 1241 | 1241 | if (p + sizeof(s->v4) > buffer+buflen) { |
| 1242 | − IP_VS_ERR_RL("BACKUP, Dropping buffer, to small\n"); | |
| 1242 | + IP_VS_ERR_RL("BACKUP, Dropping buffer, too small\n"); | |
| 1243 | 1243 | return; |
| 1244 | 1244 | } |
| 1245 | 1245 | s = (union ip_vs_sync_conn *)p; |
| @@ -114,7 +114,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { · 113 unmodified lines | ||
| 114 | 114 | { |
| 115 | 115 | /* ORIGINAL */ |
| 116 | 116 | /* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA */ |
| 117 | −/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA, sCW, sHA}, | |
| 117 | +/* init */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCW, sHA}, | |
| 118 | 118 | /* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL, sHA}, |
| 119 | 119 | /* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, |
| 120 | 120 | /* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA, sCL, sSS}, |
| @@ -130,7 +130,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { · 9 unmodified lines | ||
| 130 | 130 | /* REPLY */ |
| 131 | 131 | /* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA */ |
| 132 | 132 | /* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV, sHA},/* INIT in sCL Big TODO */ |
| 133 | −/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV, sHA}, | |
| 133 | +/* init_ack */ {sIV, sCW, sCW, sCE, sES, sSS, sSR, sSA, sIV, sHA}, | |
| 134 | 134 | /* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV, sCL}, |
| 135 | 135 | /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV, sSR}, |
| 136 | 136 | /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV, sHA}, |
| @@ -316,7 +316,7 @@ sctp_new(struct nf_conn *ct, const struct sk_buff *skb, · 179 unmodified lines | ||
| 316 | 316 | ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag; |
| 317 | 317 | } |
| 318 | 318 | |
| 319 | − ct->proto.sctp.state = new_state; | |
| 319 | + ct->proto.sctp.state = SCTP_CONNTRACK_NONE; | |
| 320 | 320 | } |
| 321 | 321 | |
| 322 | 322 | return true; |
| @@ -552,48 +552,71 @@ static inline u64 nf_tables_alloc_handle(struct nft_table *table) · 551 unmodified lines | ||
| 552 | 552 | |
| 553 | 553 | static const struct nft_chain_type *chain_type[NFPROTO_NUMPROTO][NFT_CHAIN_T_MAX]; |
| 554 | 554 | |
| 555 | +static const struct nft_chain_type * | |
| 556 | +__nft_chain_type_get(u8 family, enum nft_chain_types type) | |
| 557 | +{ | |
| 558 | + if (family >= NFPROTO_NUMPROTO || | |
| 559 | + type >= NFT_CHAIN_T_MAX) | |
| 560 | + return NULL; | |
| 561 | + | |
| 562 | + return chain_type[family][type]; | |
| 563 | +} | |
| 564 | + | |
| 555 | 565 | static const struct nft_chain_type * |
| 556 | 566 | __nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family) |
| 557 | 567 | { |
| 568 | + const struct nft_chain_type *type; | |
| 558 | 569 | int i; |
| 559 | 570 | |
| 560 | 571 | for (i = 0; i < NFT_CHAIN_T_MAX; i++) { |
| 561 | − if (chain_type[family][i] != NULL && | |
| 562 | − !nla_strcmp(nla, chain_type[family][i]->name)) | |
| 563 | − return chain_type[family][i]; | |
| 572 | + type = __nft_chain_type_get(family, i); | |
| 573 | + if (!type) | |
| 574 | + continue; | |
| 575 | + if (!nla_strcmp(nla, type->name)) | |
| 576 | + return type; | |
| 564 | 577 | } |
| 565 | 578 | return NULL; |
| 566 | 579 | } |
| 567 | 580 | |
| 568 | −/* | |
| 569 | − * Loading a module requires dropping mutex that guards the transaction. | |
| 570 | − * A different client might race to start a new transaction meanwhile. Zap the | |
| 571 | − * list of pending transaction and then restore it once the mutex is grabbed | |
| 572 | − * again. Users of this function return EAGAIN which implicitly triggers the | |
| 573 | − * transaction abort path to clean up the list of pending transactions. | |
| 574 | − */ | |
| 581 | +struct nft_module_request { | |
| 582 | + struct list_head list; | |
| 583 | + char module[MODULE_NAME_LEN]; | |
| 584 | + bool done; | |
| 585 | +}; | |
| 586 | + | |
| 575 | 587 | #ifdef CONFIG_MODULES |
| 576 | −static void nft_request_module(struct net *net, const char *fmt, ...) | |
| 588 | +static int nft_request_module(struct net *net, const char *fmt, ...) | |
| 577 | 589 | { |
| 578 | 590 | char module_name[MODULE_NAME_LEN]; |
| 579 | − LIST_HEAD(commit_list); | |
| 591 | + struct nft_module_request *req; | |
| 580 | 592 | va_list args; |
| 581 | 593 | int ret; |
| 582 | 594 | |
| 583 | − list_splice_init(&net->nft.commit_list, &commit_list); | |
| 584 | − | |
| 585 | 595 | va_start(args, fmt); |
| 586 | 596 | ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args); |
| 587 | 597 | va_end(args); |
| 588 | 598 | if (ret >= MODULE_NAME_LEN) |
| 589 | − return; | |
| 599 | + return 0; | |
| 590 | 600 | |
| 591 | − mutex_unlock(&net->nft.commit_mutex); | |
| 592 | − request_module("%s", module_name); | |
| 593 | − mutex_lock(&net->nft.commit_mutex); | |
| 601 | + list_for_each_entry(req, &net->nft.module_list, list) { | |
| 602 | + if (!strcmp(req->module, module_name)) { | |
| 603 | + if (req->done) | |
| 604 | + return 0; | |
| 594 | 605 | |
| 595 | − WARN_ON_ONCE(!list_empty(&net->nft.commit_list)); | |
| 596 | − list_splice(&commit_list, &net->nft.commit_list); | |
| 606 | + /* A request to load this module already exists. */ | |
| 607 | + return -EAGAIN; | |
| 608 | + } | |
| 609 | + } | |
| 610 | + | |
| 611 | + req = kmalloc(sizeof(*req), GFP_KERNEL); | |
| 612 | + if (!req) | |
| 613 | + return -ENOMEM; | |
| 614 | + | |
| 615 | + req->done = false; | |
| 616 | + strlcpy(req->module, module_name, MODULE_NAME_LEN); | |
| 617 | + list_add_tail(&req->list, &net->nft.module_list); | |
| 618 | + | |
| 619 | + return -EAGAIN; | |
| 597 | 620 | } |
| 598 | 621 | #endif |
| 599 | 622 | |
| @@ -617,10 +640,9 @@ nf_tables_chain_type_lookup(struct net *net, const struct nlattr *nla, · 17 unmodified lines | ||
| 617 | 640 | lockdep_nfnl_nft_mutex_not_held(); |
| 618 | 641 | #ifdef CONFIG_MODULES |
| 619 | 642 | if (autoload) { |
| 620 | − nft_request_module(net, "nft-chain-%u-%.*s", family, | |
| 621 | − nla_len(nla), (const char *)nla_data(nla)); | |
| 622 | − type = __nf_tables_chain_type_lookup(nla, family); | |
| 623 | − if (type != NULL) | |
| 643 | + if (nft_request_module(net, "nft-chain-%u-%.*s", family, | |
| 644 | + nla_len(nla), | |
| 645 | + (const char *)nla_data(nla)) == -EAGAIN) | |
| 624 | 646 | return ERR_PTR(-EAGAIN); |
| 625 | 647 | } |
| 626 | 648 | #endif |
| @@ -1162,11 +1184,8 @@ static void nf_tables_table_destroy(struct nft_ctx *ctx) · 535 unmodified lines | ||
| 1162 | 1184 | |
| 1163 | 1185 | void nft_register_chain_type(const struct nft_chain_type *ctype) |
| 1164 | 1186 | { |
| 1165 | − if (WARN_ON(ctype->family >= NFPROTO_NUMPROTO)) | |
| 1166 | − return; | |
| 1167 | − | |
| 1168 | 1187 | nfnl_lock(NFNL_SUBSYS_NFTABLES); |
| 1169 | − if (WARN_ON(chain_type[ctype->family][ctype->type] != NULL)) { | |
| 1188 | + if (WARN_ON(__nft_chain_type_get(ctype->family, ctype->type))) { | |
| 1170 | 1189 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); |
| 1171 | 1190 | return; |
| 1172 | 1191 | } |
| @@ -1768,7 +1787,10 @@ static int nft_chain_parse_hook(struct net *net, · 595 unmodified lines | ||
| 1768 | 1787 | hook->num = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM])); |
| 1769 | 1788 | hook->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY])); |
| 1770 | 1789 | |
| 1771 | − type = chain_type[family][NFT_CHAIN_T_DEFAULT]; | |
| 1790 | + type = __nft_chain_type_get(family, NFT_CHAIN_T_DEFAULT); | |
| 1791 | + if (!type) | |
| 1792 | + return -EOPNOTSUPP; | |
| 1793 | + | |
| 1772 | 1794 | if (nla[NFTA_CHAIN_TYPE]) { |
| 1773 | 1795 | type = nf_tables_chain_type_lookup(net, nla[NFTA_CHAIN_TYPE], |
| 1774 | 1796 | family, autoload); |
| @@ -2328,9 +2350,8 @@ static const struct nft_expr_type *__nft_expr_type_get(u8 family, · 553 unmodified lines | ||
| 2328 | 2350 | static int nft_expr_type_request_module(struct net *net, u8 family, |
| 2329 | 2351 | struct nlattr *nla) |
| 2330 | 2352 | { |
| 2331 | − nft_request_module(net, "nft-expr-%u-%.*s", family, | |
| 2332 | − nla_len(nla), (char *)nla_data(nla)); | |
| 2333 | − if (__nft_expr_type_get(family, nla)) | |
| 2353 | + if (nft_request_module(net, "nft-expr-%u-%.*s", family, | |
| 2354 | + nla_len(nla), (char *)nla_data(nla)) == -EAGAIN) | |
| 2334 | 2355 | return -EAGAIN; |
| 2335 | 2356 | |
| 2336 | 2357 | return 0; |
| @@ -2356,9 +2377,9 @@ static const struct nft_expr_type *nft_expr_type_get(struct net *net, · 19 unmodified lines | ||
| 2356 | 2377 | if (nft_expr_type_request_module(net, family, nla) == -EAGAIN) |
| 2357 | 2378 | return ERR_PTR(-EAGAIN); |
| 2358 | 2379 | |
| 2359 | − nft_request_module(net, "nft-expr-%.*s", | |
| 2360 | − nla_len(nla), (char *)nla_data(nla)); | |
| 2361 | − if (__nft_expr_type_get(family, nla)) | |
| 2380 | + if (nft_request_module(net, "nft-expr-%.*s", | |
| 2381 | + nla_len(nla), | |
| 2382 | + (char *)nla_data(nla)) == -EAGAIN) | |
| 2362 | 2383 | return ERR_PTR(-EAGAIN); |
| 2363 | 2384 | } |
| 2364 | 2385 | #endif |
| @@ -2449,9 +2470,10 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx, · 84 unmodified lines | ||
| 2449 | 2470 | err = PTR_ERR(ops); |
| 2450 | 2471 | #ifdef CONFIG_MODULES |
| 2451 | 2472 | if (err == -EAGAIN) |
| 2452 | − nft_expr_type_request_module(ctx->net, | |
| 2453 | − ctx->family, | |
| 2454 | − tb[NFTA_EXPR_NAME]); | |
| 2473 | + if (nft_expr_type_request_module(ctx->net, | |
| 2474 | + ctx->family, | |
| 2475 | + tb[NFTA_EXPR_NAME]) != -EAGAIN) | |
| 2476 | + err = -ENOENT; | |
| 2455 | 2477 | #endif |
| 2456 | 2478 | goto err1; |
| 2457 | 2479 | } |
| @@ -3288,8 +3310,7 @@ nft_select_set_ops(const struct nft_ctx *ctx, · 830 unmodified lines | ||
| 3288 | 3310 | lockdep_nfnl_nft_mutex_not_held(); |
| 3289 | 3311 | #ifdef CONFIG_MODULES |
| 3290 | 3312 | if (list_empty(&nf_tables_set_types)) { |
| 3291 | − nft_request_module(ctx->net, "nft-set"); | |
| 3292 | − if (!list_empty(&nf_tables_set_types)) | |
| 3313 | + if (nft_request_module(ctx->net, "nft-set") == -EAGAIN) | |
| 3293 | 3314 | return ERR_PTR(-EAGAIN); |
| 3294 | 3315 | } |
| 3295 | 3316 | #endif |
| @@ -5415,8 +5436,7 @@ nft_obj_type_get(struct net *net, u32 objtype) · 2119 unmodified lines | ||
| 5415 | 5436 | lockdep_nfnl_nft_mutex_not_held(); |
| 5416 | 5437 | #ifdef CONFIG_MODULES |
| 5417 | 5438 | if (type == NULL) { |
| 5418 | − nft_request_module(net, "nft-obj-%u", objtype); | |
| 5419 | − if (__nft_obj_type_get(objtype)) | |
| 5439 | + if (nft_request_module(net, "nft-obj-%u", objtype) == -EAGAIN) | |
| 5420 | 5440 | return ERR_PTR(-EAGAIN); |
| 5421 | 5441 | } |
| 5422 | 5442 | #endif |
| @@ -5989,8 +6009,7 @@ nft_flowtable_type_get(struct net *net, u8 family) · 566 unmodified lines | ||
| 5989 | 6009 | lockdep_nfnl_nft_mutex_not_held(); |
| 5990 | 6010 | #ifdef CONFIG_MODULES |
| 5991 | 6011 | if (type == NULL) { |
| 5992 | − nft_request_module(net, "nf-flowtable-%u", family); | |
| 5993 | − if (__nft_flowtable_type_get(family)) | |
| 6012 | + if (nft_request_module(net, "nf-flowtable-%u", family) == -EAGAIN) | |
| 5994 | 6013 | return ERR_PTR(-EAGAIN); |
| 5995 | 6014 | } |
| 5996 | 6015 | #endif |
| @@ -6992,6 +7011,18 @@ static void nft_chain_del(struct nft_chain *chain) · 995 unmodified lines | ||
| 6992 | 7011 | list_del_rcu(&chain->list); |
| 6993 | 7012 | } |
| 6994 | 7013 | |
| 7014 | +static void nf_tables_module_autoload_cleanup(struct net *net) | |
| 7015 | +{ | |
| 7016 | + struct nft_module_request *req, *next; | |
| 7017 | + | |
| 7018 | + WARN_ON_ONCE(!list_empty(&net->nft.commit_list)); | |
| 7019 | + list_for_each_entry_safe(req, next, &net->nft.module_list, list) { | |
| 7020 | + WARN_ON_ONCE(!req->done); | |
| 7021 | + list_del(&req->list); | |
| 7022 | + kfree(req); | |
| 7023 | + } | |
| 7024 | +} | |
| 7025 | + | |
| 6995 | 7026 | static void nf_tables_commit_release(struct net *net) |
| 6996 | 7027 | { |
| 6997 | 7028 | struct nft_trans *trans; |
| @@ -7004,6 +7035,7 @@ static void nf_tables_commit_release(struct net *net) · 6 unmodified lines | ||
| 7004 | 7035 | * to prevent expensive synchronize_rcu() in commit phase. |
| 7005 | 7036 | */ |
| 7006 | 7037 | if (list_empty(&net->nft.commit_list)) { |
| 7038 | + nf_tables_module_autoload_cleanup(net); | |
| 7007 | 7039 | mutex_unlock(&net->nft.commit_mutex); |
| 7008 | 7040 | return; |
| 7009 | 7041 | } |
| @@ -7018,6 +7050,7 @@ static void nf_tables_commit_release(struct net *net) · 8 unmodified lines | ||
| 7018 | 7050 | list_splice_tail_init(&net->nft.commit_list, &nf_tables_destroy_list); |
| 7019 | 7051 | spin_unlock(&nf_tables_destroy_list_lock); |
| 7020 | 7052 | |
| 7053 | + nf_tables_module_autoload_cleanup(net); | |
| 7021 | 7054 | mutex_unlock(&net->nft.commit_mutex); |
| 7022 | 7055 | |
| 7023 | 7056 | schedule_work(&trans_destroy_work); |
| @@ -7209,6 +7242,26 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) · 185 unmodified lines | ||
| 7209 | 7242 | return 0; |
| 7210 | 7243 | } |
| 7211 | 7244 | |
| 7245 | +static void nf_tables_module_autoload(struct net *net) | |
| 7246 | +{ | |
| 7247 | + struct nft_module_request *req, *next; | |
| 7248 | + LIST_HEAD(module_list); | |
| 7249 | + | |
| 7250 | + list_splice_init(&net->nft.module_list, &module_list); | |
| 7251 | + mutex_unlock(&net->nft.commit_mutex); | |
| 7252 | + list_for_each_entry_safe(req, next, &module_list, list) { | |
| 7253 | + if (req->done) { | |
| 7254 | + list_del(&req->list); | |
| 7255 | + kfree(req); | |
| 7256 | + } else { | |
| 7257 | + request_module("%s", req->module); | |
| 7258 | + req->done = true; | |
| 7259 | + } | |
| 7260 | + } | |
| 7261 | + mutex_lock(&net->nft.commit_mutex); | |
| 7262 | + list_splice(&module_list, &net->nft.module_list); | |
| 7263 | +} | |
| 7264 | + | |
| 7212 | 7265 | static void nf_tables_abort_release(struct nft_trans *trans) |
| 7213 | 7266 | { |
| 7214 | 7267 | switch (trans->msg_type) { |
| @@ -7238,7 +7291,7 @@ static void nf_tables_abort_release(struct nft_trans *trans) · 23 unmodified lines | ||
| 7238 | 7291 | kfree(trans); |
| 7239 | 7292 | } |
| 7240 | 7293 | |
| 7241 | −static int __nf_tables_abort(struct net *net) | |
| 7294 | +static int __nf_tables_abort(struct net *net, bool autoload) | |
| 7242 | 7295 | { |
| 7243 | 7296 | struct nft_trans *trans, *next; |
| 7244 | 7297 | struct nft_trans_elem *te; |
| @@ -7360,6 +7413,11 @@ static int __nf_tables_abort(struct net *net) · 115 unmodified lines | ||
| 7360 | 7413 | nf_tables_abort_release(trans); |
| 7361 | 7414 | } |
| 7362 | 7415 | |
| 7416 | + if (autoload) | |
| 7417 | + nf_tables_module_autoload(net); | |
| 7418 | + else | |
| 7419 | + nf_tables_module_autoload_cleanup(net); | |
| 7420 | + | |
| 7363 | 7421 | return 0; |
| 7364 | 7422 | } |
| 7365 | 7423 | |
| @@ -7368,9 +7426,9 @@ static void nf_tables_cleanup(struct net *net) · 2 unmodified lines | ||
| 7368 | 7426 | nft_validate_state_update(net, NFT_VALIDATE_SKIP); |
| 7369 | 7427 | } |
| 7370 | 7428 | |
| 7371 | −static int nf_tables_abort(struct net *net, struct sk_buff *skb) | |
| 7429 | +static int nf_tables_abort(struct net *net, struct sk_buff *skb, bool autoload) | |
| 7372 | 7430 | { |
| 7373 | − int ret = __nf_tables_abort(net); | |
| 7431 | + int ret = __nf_tables_abort(net, autoload); | |
| 7374 | 7432 | |
| 7375 | 7433 | mutex_unlock(&net->nft.commit_mutex); |
| 7376 | 7434 | |
| @@ -7965,6 +8023,7 @@ static int __net_init nf_tables_init_net(struct net *net) · 588 unmodified lines | ||
| 7965 | 8023 | { |
| 7966 | 8024 | INIT_LIST_HEAD(&net->nft.tables); |
| 7967 | 8025 | INIT_LIST_HEAD(&net->nft.commit_list); |
| 8026 | + INIT_LIST_HEAD(&net->nft.module_list); | |
| 7968 | 8027 | mutex_init(&net->nft.commit_mutex); |
| 7969 | 8028 | net->nft.base_seq = 1; |
| 7970 | 8029 | net->nft.validate_state = NFT_VALIDATE_SKIP; |
| @@ -7976,7 +8035,7 @@ static void __net_exit nf_tables_exit_net(struct net *net) · 5 unmodified lines | ||
| 7976 | 8035 | { |
| 7977 | 8036 | mutex_lock(&net->nft.commit_mutex); |
| 7978 | 8037 | if (!list_empty(&net->nft.commit_list)) |
| 7979 | − __nf_tables_abort(net); | |
| 8038 | + __nf_tables_abort(net, false); | |
| 7980 | 8039 | __nft_release_tables(net); |
| 7981 | 8040 | mutex_unlock(&net->nft.commit_mutex); |
| 7982 | 8041 | WARN_ON_ONCE(!list_empty(&net->nft.tables)); |
| @@ -564,7 +564,7 @@ static void nft_indr_block_cb(struct net_device *dev, · 563 unmodified lines | ||
| 564 | 564 | |
| 565 | 565 | mutex_lock(&net->nft.commit_mutex); |
| 566 | 566 | chain = __nft_offload_get_chain(dev); |
| 567 | − if (chain) { | |
| 567 | + if (chain && chain->flags & NFT_CHAIN_HW_OFFLOAD) { | |
| 568 | 568 | struct nft_base_chain *basechain; |
| 569 | 569 | |
| 570 | 570 | basechain = nft_base_chain(chain); |
| @@ -476,7 +476,7 @@ ack: · 475 unmodified lines | ||
| 476 | 476 | } |
| 477 | 477 | done: |
| 478 | 478 | if (status & NFNL_BATCH_REPLAY) { |
| 479 | − ss->abort(net, oskb); | |
| 479 | + ss->abort(net, oskb, true); | |
| 480 | 480 | nfnl_err_reset(&err_list); |
| 481 | 481 | kfree_skb(skb); |
| 482 | 482 | module_put(ss->owner); |
| @@ -487,11 +487,11 @@ done: · 4 unmodified lines | ||
| 487 | 487 | status |= NFNL_BATCH_REPLAY; |
| 488 | 488 | goto done; |
| 489 | 489 | } else if (err) { |
| 490 | − ss->abort(net, oskb); | |
| 490 | + ss->abort(net, oskb, false); | |
| 491 | 491 | netlink_ack(oskb, nlmsg_hdr(oskb), err, NULL); |
| 492 | 492 | } |
| 493 | 493 | } else { |
| 494 | − ss->abort(net, oskb); | |
| 494 | + ss->abort(net, oskb, false); | |
| 495 | 495 | } |
| 496 | 496 | if (ss->cleanup) |
| 497 | 497 | ss->cleanup(net); |
| @@ -61,6 +61,9 @@ static int nft_osf_init(const struct nft_ctx *ctx, · 60 unmodified lines | ||
| 61 | 61 | int err; |
| 62 | 62 | u8 ttl; |
| 63 | 63 | |
| 64 | + if (!tb[NFTA_OSF_DREG]) | |
| 65 | + return -EINVAL; | |
| 66 | + | |
| 64 | 67 | if (tb[NFTA_OSF_TTL]) { |
| 65 | 68 | ttl = nla_get_u8(tb[NFTA_OSF_TTL]); |
| 66 | 69 | if (ttl > 2) |
| @@ -1475,7 +1475,7 @@ static int __init rose_proto_init(void) · 1474 unmodified lines | ||
| 1475 | 1475 | int rc; |
| 1476 | 1476 | |
| 1477 | 1477 | if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) { |
| 1478 | − printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter to large\n"); | |
| 1478 | + printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter too large\n"); | |
| 1479 | 1479 | rc = -EINVAL; |
| 1480 | 1480 | goto out; |
| 1481 | 1481 | } |
| @@ -2055,9 +2055,8 @@ replay: · 2054 unmodified lines | ||
| 2055 | 2055 | &chain_info)); |
| 2056 | 2056 | |
| 2057 | 2057 | mutex_unlock(&chain->filter_chain_lock); |
| 2058 | − tp_new = tcf_proto_create(nla_data(tca[TCA_KIND]), | |
| 2059 | − protocol, prio, chain, rtnl_held, | |
| 2060 | − extack); | |
| 2058 | + tp_new = tcf_proto_create(name, protocol, prio, chain, | |
| 2059 | + rtnl_held, extack); | |
| 2061 | 2060 | if (IS_ERR(tp_new)) { |
| 2062 | 2061 | err = PTR_ERR(tp_new); |
| 2063 | 2062 | goto errout_tp; |
| @@ -263,12 +263,12 @@ static int tcf_em_validate(struct tcf_proto *tp, · 262 unmodified lines | ||
| 263 | 263 | } |
| 264 | 264 | em->data = (unsigned long) v; |
| 265 | 265 | } |
| 266 | + em->datalen = data_len; | |
| 266 | 267 | } |
| 267 | 268 | } |
| 268 | 269 | |
| 269 | 270 | em->matchid = em_hdr->matchid; |
| 270 | 271 | em->flags = em_hdr->flags; |
| 271 | − em->datalen = data_len; | |
| 272 | 272 | em->net = net; |
| 273 | 273 | |
| 274 | 274 | err = 0; |
| @@ -268,9 +268,6 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) · 267 unmodified lines | ||
| 268 | 268 | int err = -1; |
| 269 | 269 | int mtu; |
| 270 | 270 | |
| 271 | − if (!dst) | |
| 272 | − goto tx_err_link_failure; | |
| 273 | − | |
| 274 | 271 | dst_hold(dst); |
| 275 | 272 | dst = xfrm_lookup_with_ifid(xi->net, dst, fl, NULL, 0, xi->p.if_id); |
| 276 | 273 | if (IS_ERR(dst)) { |
| @@ -297,7 +294,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) · 20 unmodified lines | ||
| 297 | 294 | |
| 298 | 295 | mtu = dst_mtu(dst); |
| 299 | 296 | if (!skb->ignore_df && skb->len > mtu) { |
| 300 | − skb_dst_update_pmtu(skb, mtu); | |
| 297 | + skb_dst_update_pmtu_no_confirm(skb, mtu); | |
| 301 | 298 | |
| 302 | 299 | if (skb->protocol == htons(ETH_P_IPV6)) { |
| 303 | 300 | if (mtu < IPV6_MIN_MTU) |
| @@ -343,6 +340,7 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev) · 39 unmodified lines | ||
| 343 | 340 | { |
| 344 | 341 | struct xfrm_if *xi = netdev_priv(dev); |
| 345 | 342 | struct net_device_stats *stats = &xi->dev->stats; |
| 343 | + struct dst_entry *dst = skb_dst(skb); | |
| 346 | 344 | struct flowi fl; |
| 347 | 345 | int ret; |
| 348 | 346 | |
| @@ -352,10 +350,33 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev) · 3 unmodified lines | ||
| 352 | 350 | case htons(ETH_P_IPV6): |
| 353 | 351 | xfrm_decode_session(skb, &fl, AF_INET6); |
| 354 | 352 | memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); |
| 353 | + if (!dst) { | |
| 354 | + fl.u.ip6.flowi6_oif = dev->ifindex; | |
| 355 | + fl.u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC; | |
| 356 | + dst = ip6_route_output(dev_net(dev), NULL, &fl.u.ip6); | |
| 357 | + if (dst->error) { | |
| 358 | + dst_release(dst); | |
| 359 | + stats->tx_carrier_errors++; | |
| 360 | + goto tx_err; | |
| 361 | + } | |
| 362 | + skb_dst_set(skb, dst); | |
| 363 | + } | |
| 355 | 364 | break; |
| 356 | 365 | case htons(ETH_P_IP): |
| 357 | 366 | xfrm_decode_session(skb, &fl, AF_INET); |
| 358 | 367 | memset(IPCB(skb), 0, sizeof(*IPCB(skb))); |
| 368 | + if (!dst) { | |
| 369 | + struct rtable *rt; | |
| 370 | + | |
| 371 | + fl.u.ip4.flowi4_oif = dev->ifindex; | |
| 372 | + fl.u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC; | |
| 373 | + rt = __ip_route_output_key(dev_net(dev), &fl.u.ip4); | |
| 374 | + if (IS_ERR(rt)) { | |
| 375 | + stats->tx_carrier_errors++; | |
| 376 | + goto tx_err; | |
| 377 | + } | |
| 378 | + skb_dst_set(skb, &rt->dst); | |
| 379 | + } | |
| 359 | 380 | break; |
| 360 | 381 | default: |
| 361 | 382 | goto tx_err; |
| @@ -563,12 +584,9 @@ static void xfrmi_dev_setup(struct net_device *dev) · 201 unmodified lines | ||
| 563 | 584 | { |
| 564 | 585 | dev->netdev_ops = &xfrmi_netdev_ops; |
| 565 | 586 | dev->type = ARPHRD_NONE; |
| 566 | − dev->hard_header_len = ETH_HLEN; | |
| 567 | − dev->min_header_len = ETH_HLEN; | |
| 568 | 587 | dev->mtu = ETH_DATA_LEN; |
| 569 | 588 | dev->min_mtu = ETH_MIN_MTU; |
| 570 | − dev->max_mtu = ETH_DATA_LEN; | |
| 571 | − dev->addr_len = ETH_ALEN; | |
| 589 | + dev->max_mtu = IP_MAX_MTU; | |
| 572 | 590 | dev->flags = IFF_NOARP; |
| 573 | 591 | dev->needs_free_netdev = true; |
| 574 | 592 | dev->priv_destructor = xfrmi_dev_free; |