diff options
202 files changed, 3229 insertions, 1230 deletions
diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.txt b/Documentation/devicetree/bindings/net/dsa/qca8k.txt index bbcb255c3150..93a7469e70d4 100644 --- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt +++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt | |||
| @@ -12,10 +12,15 @@ Required properties: | |||
| 12 | Subnodes: | 12 | Subnodes: |
| 13 | 13 | ||
| 14 | The integrated switch subnode should be specified according to the binding | 14 | The integrated switch subnode should be specified according to the binding |
| 15 | described in dsa/dsa.txt. As the QCA8K switches do not have a N:N mapping of | 15 | described in dsa/dsa.txt. If the QCA8K switch is connect to a SoC's external |
| 16 | port and PHY id, each subnode describing a port needs to have a valid phandle | 16 | mdio-bus each subnode describing a port needs to have a valid phandle |
| 17 | referencing the internal PHY connected to it. The CPU port of this switch is | 17 | referencing the internal PHY it is connected to. This is because there's no |
| 18 | always port 0. | 18 | N:N mapping of port and PHY id. |
| 19 | |||
| 20 | Don't use mixed external and internal mdio-bus configurations, as this is | ||
| 21 | not supported by the hardware. | ||
| 22 | |||
| 23 | The CPU port of this switch is always port 0. | ||
| 19 | 24 | ||
| 20 | A CPU port node has the following optional node: | 25 | A CPU port node has the following optional node: |
| 21 | 26 | ||
| @@ -31,8 +36,9 @@ For QCA8K the 'fixed-link' sub-node supports only the following properties: | |||
| 31 | - 'full-duplex' (boolean, optional), to indicate that full duplex is | 36 | - 'full-duplex' (boolean, optional), to indicate that full duplex is |
| 32 | used. When absent, half duplex is assumed. | 37 | used. When absent, half duplex is assumed. |
| 33 | 38 | ||
| 34 | Example: | 39 | Examples: |
| 35 | 40 | ||
| 41 | for the external mdio-bus configuration: | ||
| 36 | 42 | ||
| 37 | &mdio0 { | 43 | &mdio0 { |
| 38 | phy_port1: phy@0 { | 44 | phy_port1: phy@0 { |
| @@ -55,12 +61,12 @@ Example: | |||
| 55 | reg = <4>; | 61 | reg = <4>; |
| 56 | }; | 62 | }; |
| 57 | 63 | ||
| 58 | switch0@0 { | 64 | switch@10 { |
| 59 | compatible = "qca,qca8337"; | 65 | compatible = "qca,qca8337"; |
| 60 | #address-cells = <1>; | 66 | #address-cells = <1>; |
| 61 | #size-cells = <0>; | 67 | #size-cells = <0>; |
| 62 | 68 | ||
| 63 | reg = <0>; | 69 | reg = <0x10>; |
| 64 | 70 | ||
| 65 | ports { | 71 | ports { |
| 66 | #address-cells = <1>; | 72 | #address-cells = <1>; |
| @@ -108,3 +114,56 @@ Example: | |||
| 108 | }; | 114 | }; |
| 109 | }; | 115 | }; |
| 110 | }; | 116 | }; |
| 117 | |||
| 118 | for the internal master mdio-bus configuration: | ||
| 119 | |||
| 120 | &mdio0 { | ||
| 121 | switch@10 { | ||
| 122 | compatible = "qca,qca8337"; | ||
| 123 | #address-cells = <1>; | ||
| 124 | #size-cells = <0>; | ||
| 125 | |||
| 126 | reg = <0x10>; | ||
| 127 | |||
| 128 | ports { | ||
| 129 | #address-cells = <1>; | ||
| 130 | #size-cells = <0>; | ||
| 131 | |||
| 132 | port@0 { | ||
| 133 | reg = <0>; | ||
| 134 | label = "cpu"; | ||
| 135 | ethernet = <&gmac1>; | ||
| 136 | phy-mode = "rgmii"; | ||
| 137 | fixed-link { | ||
| 138 | speed = 1000; | ||
| 139 | full-duplex; | ||
| 140 | }; | ||
| 141 | }; | ||
| 142 | |||
| 143 | port@1 { | ||
| 144 | reg = <1>; | ||
| 145 | label = "lan1"; | ||
| 146 | }; | ||
| 147 | |||
| 148 | port@2 { | ||
| 149 | reg = <2>; | ||
| 150 | label = "lan2"; | ||
| 151 | }; | ||
| 152 | |||
| 153 | port@3 { | ||
| 154 | reg = <3>; | ||
| 155 | label = "lan3"; | ||
| 156 | }; | ||
| 157 | |||
| 158 | port@4 { | ||
| 159 | reg = <4>; | ||
| 160 | label = "lan4"; | ||
| 161 | }; | ||
| 162 | |||
| 163 | port@5 { | ||
| 164 | reg = <5>; | ||
| 165 | label = "wan"; | ||
| 166 | }; | ||
| 167 | }; | ||
| 168 | }; | ||
| 169 | }; | ||
diff --git a/Documentation/networking/msg_zerocopy.rst b/Documentation/networking/msg_zerocopy.rst index 18c1415e7bfa..ace56204dd03 100644 --- a/Documentation/networking/msg_zerocopy.rst +++ b/Documentation/networking/msg_zerocopy.rst | |||
| @@ -50,7 +50,7 @@ the excellent reporting over at LWN.net or read the original code. | |||
| 50 | 50 | ||
| 51 | patchset | 51 | patchset |
| 52 | [PATCH net-next v4 0/9] socket sendmsg MSG_ZEROCOPY | 52 | [PATCH net-next v4 0/9] socket sendmsg MSG_ZEROCOPY |
| 53 | http://lkml.kernel.org/r/20170803202945.70750-1-willemdebruijn.kernel@gmail.com | 53 | https://lkml.kernel.org/netdev/20170803202945.70750-1-willemdebruijn.kernel@gmail.com |
| 54 | 54 | ||
| 55 | 55 | ||
| 56 | Interface | 56 | Interface |
diff --git a/Documentation/networking/netdev-FAQ.rst b/Documentation/networking/netdev-FAQ.rst index 0ac5fa77f501..8c7a713cf657 100644 --- a/Documentation/networking/netdev-FAQ.rst +++ b/Documentation/networking/netdev-FAQ.rst | |||
| @@ -131,6 +131,19 @@ it to the maintainer to figure out what is the most recent and current | |||
| 131 | version that should be applied. If there is any doubt, the maintainer | 131 | version that should be applied. If there is any doubt, the maintainer |
| 132 | will reply and ask what should be done. | 132 | will reply and ask what should be done. |
| 133 | 133 | ||
| 134 | Q: I made changes to only a few patches in a patch series should I resend only those changed? | ||
| 135 | -------------------------------------------------------------------------------------------- | ||
| 136 | A: No, please resend the entire patch series and make sure you do number your | ||
| 137 | patches such that it is clear this is the latest and greatest set of patches | ||
| 138 | that can be applied. | ||
| 139 | |||
| 140 | Q: I submitted multiple versions of a patch series and it looks like a version other than the last one has been accepted, what should I do? | ||
| 141 | ------------------------------------------------------------------------------------------------------------------------------------------- | ||
| 142 | A: There is no revert possible, once it is pushed out, it stays like that. | ||
| 143 | Please send incremental versions on top of what has been merged in order to fix | ||
| 144 | the patches the way they would look like if your latest patch series was to be | ||
| 145 | merged. | ||
| 146 | |||
| 134 | Q: How can I tell what patches are queued up for backporting to the various stable releases? | 147 | Q: How can I tell what patches are queued up for backporting to the various stable releases? |
| 135 | -------------------------------------------------------------------------------------------- | 148 | -------------------------------------------------------------------------------------------- |
| 136 | A: Normally Greg Kroah-Hartman collects stable commits himself, but for | 149 | A: Normally Greg Kroah-Hartman collects stable commits himself, but for |
diff --git a/Documentation/networking/nf_flowtable.txt b/Documentation/networking/nf_flowtable.txt index 54128c50d508..ca2136c76042 100644 --- a/Documentation/networking/nf_flowtable.txt +++ b/Documentation/networking/nf_flowtable.txt | |||
| @@ -44,10 +44,10 @@ including the Netfilter hooks and the flowtable fastpath bypass. | |||
| 44 | / \ / \ |Routing | / \ | 44 | / \ / \ |Routing | / \ |
| 45 | --> ingress ---> prerouting ---> |decision| | postrouting |--> neigh_xmit | 45 | --> ingress ---> prerouting ---> |decision| | postrouting |--> neigh_xmit |
| 46 | \_________/ \__________/ ---------- \____________/ ^ | 46 | \_________/ \__________/ ---------- \____________/ ^ |
| 47 | | ^ | | ^ | | 47 | | ^ | ^ | |
| 48 | flowtable | | ____\/___ | | | 48 | flowtable | ____\/___ | | |
| 49 | | | | / \ | | | 49 | | | / \ | | |
| 50 | __\/___ | --------->| forward |------------ | | 50 | __\/___ | | forward |------------ | |
| 51 | |-----| | \_________/ | | 51 | |-----| | \_________/ | |
| 52 | |-----| | 'flow offload' rule | | 52 | |-----| | 'flow offload' rule | |
| 53 | |-----| | adds entry to | | 53 | |-----| | adds entry to | |
diff --git a/Documentation/networking/snmp_counter.rst b/Documentation/networking/snmp_counter.rst index 52b026be028f..38a4edc4522b 100644 --- a/Documentation/networking/snmp_counter.rst +++ b/Documentation/networking/snmp_counter.rst | |||
| @@ -413,7 +413,7 @@ algorithm. | |||
| 413 | .. _F-RTO: https://tools.ietf.org/html/rfc5682 | 413 | .. _F-RTO: https://tools.ietf.org/html/rfc5682 |
| 414 | 414 | ||
| 415 | TCP Fast Path | 415 | TCP Fast Path |
| 416 | ============ | 416 | ============= |
| 417 | When kernel receives a TCP packet, it has two paths to handler the | 417 | When kernel receives a TCP packet, it has two paths to handler the |
| 418 | packet, one is fast path, another is slow path. The comment in kernel | 418 | packet, one is fast path, another is slow path. The comment in kernel |
| 419 | code provides a good explanation of them, I pasted them below:: | 419 | code provides a good explanation of them, I pasted them below:: |
| @@ -681,6 +681,7 @@ The TCP stack receives an out of order duplicate packet, so it sends a | |||
| 681 | DSACK to the sender. | 681 | DSACK to the sender. |
| 682 | 682 | ||
| 683 | * TcpExtTCPDSACKRecv | 683 | * TcpExtTCPDSACKRecv |
| 684 | |||
| 684 | The TCP stack receives a DSACK, which indicates an acknowledged | 685 | The TCP stack receives a DSACK, which indicates an acknowledged |
| 685 | duplicate packet is received. | 686 | duplicate packet is received. |
| 686 | 687 | ||
| @@ -690,7 +691,7 @@ The TCP stack receives a DSACK, which indicate an out of order | |||
| 690 | duplicate packet is received. | 691 | duplicate packet is received. |
| 691 | 692 | ||
| 692 | invalid SACK and DSACK | 693 | invalid SACK and DSACK |
| 693 | ==================== | 694 | ====================== |
| 694 | When a SACK (or DSACK) block is invalid, a corresponding counter would | 695 | When a SACK (or DSACK) block is invalid, a corresponding counter would |
| 695 | be updated. The validation method is base on the start/end sequence | 696 | be updated. The validation method is base on the start/end sequence |
| 696 | number of the SACK block. For more details, please refer the comment | 697 | number of the SACK block. For more details, please refer the comment |
| @@ -704,11 +705,13 @@ explaination: | |||
| 704 | .. _Add counters for discarded SACK blocks: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=18f02545a9a16c9a89778b91a162ad16d510bb32 | 705 | .. _Add counters for discarded SACK blocks: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=18f02545a9a16c9a89778b91a162ad16d510bb32 |
| 705 | 706 | ||
| 706 | * TcpExtTCPSACKDiscard | 707 | * TcpExtTCPSACKDiscard |
| 708 | |||
| 707 | This counter indicates how many SACK blocks are invalid. If the invalid | 709 | This counter indicates how many SACK blocks are invalid. If the invalid |
| 708 | SACK block is caused by ACK recording, the TCP stack will only ignore | 710 | SACK block is caused by ACK recording, the TCP stack will only ignore |
| 709 | it and won't update this counter. | 711 | it and won't update this counter. |
| 710 | 712 | ||
| 711 | * TcpExtTCPDSACKIgnoredOld and TcpExtTCPDSACKIgnoredNoUndo | 713 | * TcpExtTCPDSACKIgnoredOld and TcpExtTCPDSACKIgnoredNoUndo |
| 714 | |||
| 712 | When a DSACK block is invalid, one of these two counters would be | 715 | When a DSACK block is invalid, one of these two counters would be |
| 713 | updated. Which counter will be updated depends on the undo_marker flag | 716 | updated. Which counter will be updated depends on the undo_marker flag |
| 714 | of the TCP socket. If the undo_marker is not set, the TCP stack isn't | 717 | of the TCP socket. If the undo_marker is not set, the TCP stack isn't |
| @@ -719,7 +722,7 @@ will be updated. If the undo_marker is set, TcpExtTCPDSACKIgnoredOld | |||
| 719 | will be updated. As implied in its name, it might be an old packet. | 722 | will be updated. As implied in its name, it might be an old packet. |
| 720 | 723 | ||
| 721 | SACK shift | 724 | SACK shift |
| 722 | ========= | 725 | ========== |
| 723 | The linux networking stack stores data in sk_buff struct (skb for | 726 | The linux networking stack stores data in sk_buff struct (skb for |
| 724 | short). If a SACK block acrosses multiple skb, the TCP stack will try | 727 | short). If a SACK block acrosses multiple skb, the TCP stack will try |
| 725 | to re-arrange data in these skb. E.g. if a SACK block acknowledges seq | 728 | to re-arrange data in these skb. E.g. if a SACK block acknowledges seq |
| @@ -730,12 +733,15 @@ seq 14 to 20. All data in skb2 will be moved to skb1, and skb2 will be | |||
| 730 | discard, this operation is 'merge'. | 733 | discard, this operation is 'merge'. |
| 731 | 734 | ||
| 732 | * TcpExtTCPSackShifted | 735 | * TcpExtTCPSackShifted |
| 736 | |||
| 733 | A skb is shifted | 737 | A skb is shifted |
| 734 | 738 | ||
| 735 | * TcpExtTCPSackMerged | 739 | * TcpExtTCPSackMerged |
| 740 | |||
| 736 | A skb is merged | 741 | A skb is merged |
| 737 | 742 | ||
| 738 | * TcpExtTCPSackShiftFallback | 743 | * TcpExtTCPSackShiftFallback |
| 744 | |||
| 739 | A skb should be shifted or merged, but the TCP stack doesn't do it for | 745 | A skb should be shifted or merged, but the TCP stack doesn't do it for |
| 740 | some reasons. | 746 | some reasons. |
| 741 | 747 | ||
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index c5698a523bb1..23f7ed796f38 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h | |||
| @@ -302,6 +302,7 @@ | |||
| 302 | /* Misc instructions for BPF compiler */ | 302 | /* Misc instructions for BPF compiler */ |
| 303 | #define PPC_INST_LBZ 0x88000000 | 303 | #define PPC_INST_LBZ 0x88000000 |
| 304 | #define PPC_INST_LD 0xe8000000 | 304 | #define PPC_INST_LD 0xe8000000 |
| 305 | #define PPC_INST_LDX 0x7c00002a | ||
| 305 | #define PPC_INST_LHZ 0xa0000000 | 306 | #define PPC_INST_LHZ 0xa0000000 |
| 306 | #define PPC_INST_LWZ 0x80000000 | 307 | #define PPC_INST_LWZ 0x80000000 |
| 307 | #define PPC_INST_LHBRX 0x7c00062c | 308 | #define PPC_INST_LHBRX 0x7c00062c |
| @@ -309,6 +310,7 @@ | |||
| 309 | #define PPC_INST_STB 0x98000000 | 310 | #define PPC_INST_STB 0x98000000 |
| 310 | #define PPC_INST_STH 0xb0000000 | 311 | #define PPC_INST_STH 0xb0000000 |
| 311 | #define PPC_INST_STD 0xf8000000 | 312 | #define PPC_INST_STD 0xf8000000 |
| 313 | #define PPC_INST_STDX 0x7c00012a | ||
| 312 | #define PPC_INST_STDU 0xf8000001 | 314 | #define PPC_INST_STDU 0xf8000001 |
| 313 | #define PPC_INST_STW 0x90000000 | 315 | #define PPC_INST_STW 0x90000000 |
| 314 | #define PPC_INST_STWU 0x94000000 | 316 | #define PPC_INST_STWU 0x94000000 |
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h index 549e9490ff2a..dcac37745b05 100644 --- a/arch/powerpc/net/bpf_jit.h +++ b/arch/powerpc/net/bpf_jit.h | |||
| @@ -51,6 +51,8 @@ | |||
| 51 | #define PPC_LIS(r, i) PPC_ADDIS(r, 0, i) | 51 | #define PPC_LIS(r, i) PPC_ADDIS(r, 0, i) |
| 52 | #define PPC_STD(r, base, i) EMIT(PPC_INST_STD | ___PPC_RS(r) | \ | 52 | #define PPC_STD(r, base, i) EMIT(PPC_INST_STD | ___PPC_RS(r) | \ |
| 53 | ___PPC_RA(base) | ((i) & 0xfffc)) | 53 | ___PPC_RA(base) | ((i) & 0xfffc)) |
| 54 | #define PPC_STDX(r, base, b) EMIT(PPC_INST_STDX | ___PPC_RS(r) | \ | ||
| 55 | ___PPC_RA(base) | ___PPC_RB(b)) | ||
| 54 | #define PPC_STDU(r, base, i) EMIT(PPC_INST_STDU | ___PPC_RS(r) | \ | 56 | #define PPC_STDU(r, base, i) EMIT(PPC_INST_STDU | ___PPC_RS(r) | \ |
| 55 | ___PPC_RA(base) | ((i) & 0xfffc)) | 57 | ___PPC_RA(base) | ((i) & 0xfffc)) |
| 56 | #define PPC_STW(r, base, i) EMIT(PPC_INST_STW | ___PPC_RS(r) | \ | 58 | #define PPC_STW(r, base, i) EMIT(PPC_INST_STW | ___PPC_RS(r) | \ |
| @@ -65,7 +67,9 @@ | |||
| 65 | #define PPC_LBZ(r, base, i) EMIT(PPC_INST_LBZ | ___PPC_RT(r) | \ | 67 | #define PPC_LBZ(r, base, i) EMIT(PPC_INST_LBZ | ___PPC_RT(r) | \ |
| 66 | ___PPC_RA(base) | IMM_L(i)) | 68 | ___PPC_RA(base) | IMM_L(i)) |
| 67 | #define PPC_LD(r, base, i) EMIT(PPC_INST_LD | ___PPC_RT(r) | \ | 69 | #define PPC_LD(r, base, i) EMIT(PPC_INST_LD | ___PPC_RT(r) | \ |
| 68 | ___PPC_RA(base) | IMM_L(i)) | 70 | ___PPC_RA(base) | ((i) & 0xfffc)) |
| 71 | #define PPC_LDX(r, base, b) EMIT(PPC_INST_LDX | ___PPC_RT(r) | \ | ||
| 72 | ___PPC_RA(base) | ___PPC_RB(b)) | ||
| 69 | #define PPC_LWZ(r, base, i) EMIT(PPC_INST_LWZ | ___PPC_RT(r) | \ | 73 | #define PPC_LWZ(r, base, i) EMIT(PPC_INST_LWZ | ___PPC_RT(r) | \ |
| 70 | ___PPC_RA(base) | IMM_L(i)) | 74 | ___PPC_RA(base) | IMM_L(i)) |
| 71 | #define PPC_LHZ(r, base, i) EMIT(PPC_INST_LHZ | ___PPC_RT(r) | \ | 75 | #define PPC_LHZ(r, base, i) EMIT(PPC_INST_LHZ | ___PPC_RT(r) | \ |
| @@ -85,17 +89,6 @@ | |||
| 85 | ___PPC_RA(a) | ___PPC_RB(b)) | 89 | ___PPC_RA(a) | ___PPC_RB(b)) |
| 86 | #define PPC_BPF_STDCX(s, a, b) EMIT(PPC_INST_STDCX | ___PPC_RS(s) | \ | 90 | #define PPC_BPF_STDCX(s, a, b) EMIT(PPC_INST_STDCX | ___PPC_RS(s) | \ |
| 87 | ___PPC_RA(a) | ___PPC_RB(b)) | 91 | ___PPC_RA(a) | ___PPC_RB(b)) |
| 88 | |||
| 89 | #ifdef CONFIG_PPC64 | ||
| 90 | #define PPC_BPF_LL(r, base, i) do { PPC_LD(r, base, i); } while(0) | ||
| 91 | #define PPC_BPF_STL(r, base, i) do { PPC_STD(r, base, i); } while(0) | ||
| 92 | #define PPC_BPF_STLU(r, base, i) do { PPC_STDU(r, base, i); } while(0) | ||
| 93 | #else | ||
| 94 | #define PPC_BPF_LL(r, base, i) do { PPC_LWZ(r, base, i); } while(0) | ||
| 95 | #define PPC_BPF_STL(r, base, i) do { PPC_STW(r, base, i); } while(0) | ||
| 96 | #define PPC_BPF_STLU(r, base, i) do { PPC_STWU(r, base, i); } while(0) | ||
| 97 | #endif | ||
| 98 | |||
| 99 | #define PPC_CMPWI(a, i) EMIT(PPC_INST_CMPWI | ___PPC_RA(a) | IMM_L(i)) | 92 | #define PPC_CMPWI(a, i) EMIT(PPC_INST_CMPWI | ___PPC_RA(a) | IMM_L(i)) |
| 100 | #define PPC_CMPDI(a, i) EMIT(PPC_INST_CMPDI | ___PPC_RA(a) | IMM_L(i)) | 93 | #define PPC_CMPDI(a, i) EMIT(PPC_INST_CMPDI | ___PPC_RA(a) | IMM_L(i)) |
| 101 | #define PPC_CMPW(a, b) EMIT(PPC_INST_CMPW | ___PPC_RA(a) | \ | 94 | #define PPC_CMPW(a, b) EMIT(PPC_INST_CMPW | ___PPC_RA(a) | \ |
diff --git a/arch/powerpc/net/bpf_jit32.h b/arch/powerpc/net/bpf_jit32.h index dc50a8d4b3b9..21744d8aa053 100644 --- a/arch/powerpc/net/bpf_jit32.h +++ b/arch/powerpc/net/bpf_jit32.h | |||
| @@ -122,6 +122,10 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh); | |||
| 122 | #define PPC_NTOHS_OFFS(r, base, i) PPC_LHZ_OFFS(r, base, i) | 122 | #define PPC_NTOHS_OFFS(r, base, i) PPC_LHZ_OFFS(r, base, i) |
| 123 | #endif | 123 | #endif |
| 124 | 124 | ||
| 125 | #define PPC_BPF_LL(r, base, i) do { PPC_LWZ(r, base, i); } while(0) | ||
| 126 | #define PPC_BPF_STL(r, base, i) do { PPC_STW(r, base, i); } while(0) | ||
| 127 | #define PPC_BPF_STLU(r, base, i) do { PPC_STWU(r, base, i); } while(0) | ||
| 128 | |||
| 125 | #define SEEN_DATAREF 0x10000 /* might call external helpers */ | 129 | #define SEEN_DATAREF 0x10000 /* might call external helpers */ |
| 126 | #define SEEN_XREG 0x20000 /* X reg is used */ | 130 | #define SEEN_XREG 0x20000 /* X reg is used */ |
| 127 | #define SEEN_MEM 0x40000 /* SEEN_MEM+(1<<n) = use mem[n] for temporary | 131 | #define SEEN_MEM 0x40000 /* SEEN_MEM+(1<<n) = use mem[n] for temporary |
diff --git a/arch/powerpc/net/bpf_jit64.h b/arch/powerpc/net/bpf_jit64.h index 3609be4692b3..47f441f351a6 100644 --- a/arch/powerpc/net/bpf_jit64.h +++ b/arch/powerpc/net/bpf_jit64.h | |||
| @@ -68,6 +68,26 @@ static const int b2p[] = { | |||
| 68 | /* PPC NVR range -- update this if we ever use NVRs below r27 */ | 68 | /* PPC NVR range -- update this if we ever use NVRs below r27 */ |
| 69 | #define BPF_PPC_NVR_MIN 27 | 69 | #define BPF_PPC_NVR_MIN 27 |
| 70 | 70 | ||
| 71 | /* | ||
| 72 | * WARNING: These can use TMP_REG_2 if the offset is not at word boundary, | ||
| 73 | * so ensure that it isn't in use already. | ||
| 74 | */ | ||
| 75 | #define PPC_BPF_LL(r, base, i) do { \ | ||
| 76 | if ((i) % 4) { \ | ||
| 77 | PPC_LI(b2p[TMP_REG_2], (i)); \ | ||
| 78 | PPC_LDX(r, base, b2p[TMP_REG_2]); \ | ||
| 79 | } else \ | ||
| 80 | PPC_LD(r, base, i); \ | ||
| 81 | } while(0) | ||
| 82 | #define PPC_BPF_STL(r, base, i) do { \ | ||
| 83 | if ((i) % 4) { \ | ||
| 84 | PPC_LI(b2p[TMP_REG_2], (i)); \ | ||
| 85 | PPC_STDX(r, base, b2p[TMP_REG_2]); \ | ||
| 86 | } else \ | ||
| 87 | PPC_STD(r, base, i); \ | ||
| 88 | } while(0) | ||
| 89 | #define PPC_BPF_STLU(r, base, i) do { PPC_STDU(r, base, i); } while(0) | ||
| 90 | |||
| 71 | #define SEEN_FUNC 0x1000 /* might call external helpers */ | 91 | #define SEEN_FUNC 0x1000 /* might call external helpers */ |
| 72 | #define SEEN_STACK 0x2000 /* uses BPF stack */ | 92 | #define SEEN_STACK 0x2000 /* uses BPF stack */ |
| 73 | #define SEEN_TAILCALL 0x4000 /* uses tail calls */ | 93 | #define SEEN_TAILCALL 0x4000 /* uses tail calls */ |
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index 4194d3cfb60c..21a1dcd4b156 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c | |||
| @@ -252,7 +252,7 @@ static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 | |||
| 252 | * if (tail_call_cnt > MAX_TAIL_CALL_CNT) | 252 | * if (tail_call_cnt > MAX_TAIL_CALL_CNT) |
| 253 | * goto out; | 253 | * goto out; |
| 254 | */ | 254 | */ |
| 255 | PPC_LD(b2p[TMP_REG_1], 1, bpf_jit_stack_tailcallcnt(ctx)); | 255 | PPC_BPF_LL(b2p[TMP_REG_1], 1, bpf_jit_stack_tailcallcnt(ctx)); |
| 256 | PPC_CMPLWI(b2p[TMP_REG_1], MAX_TAIL_CALL_CNT); | 256 | PPC_CMPLWI(b2p[TMP_REG_1], MAX_TAIL_CALL_CNT); |
| 257 | PPC_BCC(COND_GT, out); | 257 | PPC_BCC(COND_GT, out); |
| 258 | 258 | ||
| @@ -265,7 +265,7 @@ static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 | |||
| 265 | /* prog = array->ptrs[index]; */ | 265 | /* prog = array->ptrs[index]; */ |
| 266 | PPC_MULI(b2p[TMP_REG_1], b2p_index, 8); | 266 | PPC_MULI(b2p[TMP_REG_1], b2p_index, 8); |
| 267 | PPC_ADD(b2p[TMP_REG_1], b2p[TMP_REG_1], b2p_bpf_array); | 267 | PPC_ADD(b2p[TMP_REG_1], b2p[TMP_REG_1], b2p_bpf_array); |
| 268 | PPC_LD(b2p[TMP_REG_1], b2p[TMP_REG_1], offsetof(struct bpf_array, ptrs)); | 268 | PPC_BPF_LL(b2p[TMP_REG_1], b2p[TMP_REG_1], offsetof(struct bpf_array, ptrs)); |
| 269 | 269 | ||
| 270 | /* | 270 | /* |
| 271 | * if (prog == NULL) | 271 | * if (prog == NULL) |
| @@ -275,7 +275,7 @@ static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 | |||
| 275 | PPC_BCC(COND_EQ, out); | 275 | PPC_BCC(COND_EQ, out); |
| 276 | 276 | ||
| 277 | /* goto *(prog->bpf_func + prologue_size); */ | 277 | /* goto *(prog->bpf_func + prologue_size); */ |
| 278 | PPC_LD(b2p[TMP_REG_1], b2p[TMP_REG_1], offsetof(struct bpf_prog, bpf_func)); | 278 | PPC_BPF_LL(b2p[TMP_REG_1], b2p[TMP_REG_1], offsetof(struct bpf_prog, bpf_func)); |
| 279 | #ifdef PPC64_ELF_ABI_v1 | 279 | #ifdef PPC64_ELF_ABI_v1 |
| 280 | /* skip past the function descriptor */ | 280 | /* skip past the function descriptor */ |
| 281 | PPC_ADDI(b2p[TMP_REG_1], b2p[TMP_REG_1], | 281 | PPC_ADDI(b2p[TMP_REG_1], b2p[TMP_REG_1], |
| @@ -606,7 +606,7 @@ bpf_alu32_trunc: | |||
| 606 | * the instructions generated will remain the | 606 | * the instructions generated will remain the |
| 607 | * same across all passes | 607 | * same across all passes |
| 608 | */ | 608 | */ |
| 609 | PPC_STD(dst_reg, 1, bpf_jit_stack_local(ctx)); | 609 | PPC_BPF_STL(dst_reg, 1, bpf_jit_stack_local(ctx)); |
| 610 | PPC_ADDI(b2p[TMP_REG_1], 1, bpf_jit_stack_local(ctx)); | 610 | PPC_ADDI(b2p[TMP_REG_1], 1, bpf_jit_stack_local(ctx)); |
| 611 | PPC_LDBRX(dst_reg, 0, b2p[TMP_REG_1]); | 611 | PPC_LDBRX(dst_reg, 0, b2p[TMP_REG_1]); |
| 612 | break; | 612 | break; |
| @@ -662,7 +662,7 @@ emit_clear: | |||
| 662 | PPC_LI32(b2p[TMP_REG_1], imm); | 662 | PPC_LI32(b2p[TMP_REG_1], imm); |
| 663 | src_reg = b2p[TMP_REG_1]; | 663 | src_reg = b2p[TMP_REG_1]; |
| 664 | } | 664 | } |
| 665 | PPC_STD(src_reg, dst_reg, off); | 665 | PPC_BPF_STL(src_reg, dst_reg, off); |
| 666 | break; | 666 | break; |
| 667 | 667 | ||
| 668 | /* | 668 | /* |
| @@ -709,7 +709,7 @@ emit_clear: | |||
| 709 | break; | 709 | break; |
| 710 | /* dst = *(u64 *)(ul) (src + off) */ | 710 | /* dst = *(u64 *)(ul) (src + off) */ |
| 711 | case BPF_LDX | BPF_MEM | BPF_DW: | 711 | case BPF_LDX | BPF_MEM | BPF_DW: |
| 712 | PPC_LD(dst_reg, src_reg, off); | 712 | PPC_BPF_LL(dst_reg, src_reg, off); |
| 713 | break; | 713 | break; |
| 714 | 714 | ||
| 715 | /* | 715 | /* |
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 4d85645c87f7..0928fd1f0e0c 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c | |||
| @@ -4365,7 +4365,8 @@ setup_pci(struct hfc_multi *hc, struct pci_dev *pdev, | |||
| 4365 | if (m->clock2) | 4365 | if (m->clock2) |
| 4366 | test_and_set_bit(HFC_CHIP_CLOCK2, &hc->chip); | 4366 | test_and_set_bit(HFC_CHIP_CLOCK2, &hc->chip); |
| 4367 | 4367 | ||
| 4368 | if (ent->device == 0xB410) { | 4368 | if (ent->vendor == PCI_VENDOR_ID_DIGIUM && |
| 4369 | ent->device == PCI_DEVICE_ID_DIGIUM_HFC4S) { | ||
| 4369 | test_and_set_bit(HFC_CHIP_B410P, &hc->chip); | 4370 | test_and_set_bit(HFC_CHIP_B410P, &hc->chip); |
| 4370 | test_and_set_bit(HFC_CHIP_PCM_MASTER, &hc->chip); | 4371 | test_and_set_bit(HFC_CHIP_PCM_MASTER, &hc->chip); |
| 4371 | test_and_clear_bit(HFC_CHIP_PCM_SLAVE, &hc->chip); | 4372 | test_and_clear_bit(HFC_CHIP_PCM_SLAVE, &hc->chip); |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5e4ca082cfcd..7a96d168efc4 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
| @@ -216,8 +216,8 @@ config GENEVE | |||
| 216 | 216 | ||
| 217 | config GTP | 217 | config GTP |
| 218 | tristate "GPRS Tunneling Protocol datapath (GTP-U)" | 218 | tristate "GPRS Tunneling Protocol datapath (GTP-U)" |
| 219 | depends on INET && NET_UDP_TUNNEL | 219 | depends on INET |
| 220 | select NET_IP_TUNNEL | 220 | select NET_UDP_TUNNEL |
| 221 | ---help--- | 221 | ---help--- |
| 222 | This allows one to create gtp virtual interfaces that provide | 222 | This allows one to create gtp virtual interfaces that provide |
| 223 | the GPRS Tunneling Protocol datapath (GTP-U). This tunneling protocol | 223 | the GPRS Tunneling Protocol datapath (GTP-U). This tunneling protocol |
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c index 576b37d12a63..c4fa400efdcc 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c | |||
| @@ -481,6 +481,155 @@ qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable) | |||
| 481 | qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask); | 481 | qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask); |
| 482 | } | 482 | } |
| 483 | 483 | ||
| 484 | static u32 | ||
| 485 | qca8k_port_to_phy(int port) | ||
| 486 | { | ||
| 487 | /* From Andrew Lunn: | ||
| 488 | * Port 0 has no internal phy. | ||
| 489 | * Port 1 has an internal PHY at MDIO address 0. | ||
| 490 | * Port 2 has an internal PHY at MDIO address 1. | ||
| 491 | * ... | ||
| 492 | * Port 5 has an internal PHY at MDIO address 4. | ||
| 493 | * Port 6 has no internal PHY. | ||
| 494 | */ | ||
| 495 | |||
| 496 | return port - 1; | ||
| 497 | } | ||
| 498 | |||
| 499 | static int | ||
| 500 | qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data) | ||
| 501 | { | ||
| 502 | u32 phy, val; | ||
| 503 | |||
| 504 | if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) | ||
| 505 | return -EINVAL; | ||
| 506 | |||
| 507 | /* callee is responsible for not passing bad ports, | ||
| 508 | * but we still would like to make spills impossible. | ||
| 509 | */ | ||
| 510 | phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR; | ||
| 511 | val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN | | ||
| 512 | QCA8K_MDIO_MASTER_WRITE | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | | ||
| 513 | QCA8K_MDIO_MASTER_REG_ADDR(regnum) | | ||
| 514 | QCA8K_MDIO_MASTER_DATA(data); | ||
| 515 | |||
| 516 | qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); | ||
| 517 | |||
| 518 | return qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, | ||
| 519 | QCA8K_MDIO_MASTER_BUSY); | ||
| 520 | } | ||
| 521 | |||
| 522 | static int | ||
| 523 | qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum) | ||
| 524 | { | ||
| 525 | u32 phy, val; | ||
| 526 | |||
| 527 | if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) | ||
| 528 | return -EINVAL; | ||
| 529 | |||
| 530 | /* callee is responsible for not passing bad ports, | ||
| 531 | * but we still would like to make spills impossible. | ||
| 532 | */ | ||
| 533 | phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR; | ||
| 534 | val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN | | ||
| 535 | QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | | ||
| 536 | QCA8K_MDIO_MASTER_REG_ADDR(regnum); | ||
| 537 | |||
| 538 | qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); | ||
| 539 | |||
| 540 | if (qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, | ||
| 541 | QCA8K_MDIO_MASTER_BUSY)) | ||
| 542 | return -ETIMEDOUT; | ||
| 543 | |||
| 544 | val = (qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL) & | ||
| 545 | QCA8K_MDIO_MASTER_DATA_MASK); | ||
| 546 | |||
| 547 | return val; | ||
| 548 | } | ||
| 549 | |||
| 550 | static int | ||
| 551 | qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data) | ||
| 552 | { | ||
| 553 | struct qca8k_priv *priv = ds->priv; | ||
| 554 | |||
| 555 | return qca8k_mdio_write(priv, port, regnum, data); | ||
| 556 | } | ||
| 557 | |||
| 558 | static int | ||
| 559 | qca8k_phy_read(struct dsa_switch *ds, int port, int regnum) | ||
| 560 | { | ||
| 561 | struct qca8k_priv *priv = ds->priv; | ||
| 562 | int ret; | ||
| 563 | |||
| 564 | ret = qca8k_mdio_read(priv, port, regnum); | ||
| 565 | |||
| 566 | if (ret < 0) | ||
| 567 | return 0xffff; | ||
| 568 | |||
| 569 | return ret; | ||
| 570 | } | ||
| 571 | |||
| 572 | static int | ||
| 573 | qca8k_setup_mdio_bus(struct qca8k_priv *priv) | ||
| 574 | { | ||
| 575 | u32 internal_mdio_mask = 0, external_mdio_mask = 0, reg; | ||
| 576 | struct device_node *ports, *port; | ||
| 577 | int err; | ||
| 578 | |||
| 579 | ports = of_get_child_by_name(priv->dev->of_node, "ports"); | ||
| 580 | if (!ports) | ||
| 581 | return -EINVAL; | ||
| 582 | |||
| 583 | for_each_available_child_of_node(ports, port) { | ||
| 584 | err = of_property_read_u32(port, "reg", ®); | ||
| 585 | if (err) | ||
| 586 | return err; | ||
| 587 | |||
| 588 | if (!dsa_is_user_port(priv->ds, reg)) | ||
| 589 | continue; | ||
| 590 | |||
| 591 | if (of_property_read_bool(port, "phy-handle")) | ||
| 592 | external_mdio_mask |= BIT(reg); | ||
| 593 | else | ||
| 594 | internal_mdio_mask |= BIT(reg); | ||
| 595 | } | ||
| 596 | |||
| 597 | if (!external_mdio_mask && !internal_mdio_mask) { | ||
| 598 | dev_err(priv->dev, "no PHYs are defined.\n"); | ||
| 599 | return -EINVAL; | ||
| 600 | } | ||
| 601 | |||
| 602 | /* The QCA8K_MDIO_MASTER_EN Bit, which grants access to PHYs through | ||
| 603 | * the MDIO_MASTER register also _disconnects_ the external MDC | ||
| 604 | * passthrough to the internal PHYs. It's not possible to use both | ||
| 605 | * configurations at the same time! | ||
| 606 | * | ||
| 607 | * Because this came up during the review process: | ||
| 608 | * If the external mdio-bus driver is capable magically disabling | ||
| 609 | * the QCA8K_MDIO_MASTER_EN and mutex/spin-locking out the qca8k's | ||
| 610 | * accessors for the time being, it would be possible to pull this | ||
| 611 | * off. | ||
| 612 | */ | ||
| 613 | if (!!external_mdio_mask && !!internal_mdio_mask) { | ||
| 614 | dev_err(priv->dev, "either internal or external mdio bus configuration is supported.\n"); | ||
| 615 | return -EINVAL; | ||
| 616 | } | ||
| 617 | |||
| 618 | if (external_mdio_mask) { | ||
| 619 | /* Make sure to disable the internal mdio bus in cases | ||
| 620 | * a dt-overlay and driver reload changed the configuration | ||
| 621 | */ | ||
| 622 | |||
| 623 | qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, | ||
| 624 | QCA8K_MDIO_MASTER_EN); | ||
| 625 | return 0; | ||
| 626 | } | ||
| 627 | |||
| 628 | priv->ops.phy_read = qca8k_phy_read; | ||
| 629 | priv->ops.phy_write = qca8k_phy_write; | ||
| 630 | return 0; | ||
| 631 | } | ||
| 632 | |||
| 484 | static int | 633 | static int |
| 485 | qca8k_setup(struct dsa_switch *ds) | 634 | qca8k_setup(struct dsa_switch *ds) |
| 486 | { | 635 | { |
| @@ -502,6 +651,10 @@ qca8k_setup(struct dsa_switch *ds) | |||
| 502 | if (IS_ERR(priv->regmap)) | 651 | if (IS_ERR(priv->regmap)) |
| 503 | pr_warn("regmap initialization failed"); | 652 | pr_warn("regmap initialization failed"); |
| 504 | 653 | ||
| 654 | ret = qca8k_setup_mdio_bus(priv); | ||
| 655 | if (ret) | ||
| 656 | return ret; | ||
| 657 | |||
| 505 | /* Initialize CPU port pad mode (xMII type, delays...) */ | 658 | /* Initialize CPU port pad mode (xMII type, delays...) */ |
| 506 | phy_mode = of_get_phy_mode(ds->ports[QCA8K_CPU_PORT].dn); | 659 | phy_mode = of_get_phy_mode(ds->ports[QCA8K_CPU_PORT].dn); |
| 507 | if (phy_mode < 0) { | 660 | if (phy_mode < 0) { |
| @@ -624,22 +777,6 @@ qca8k_adjust_link(struct dsa_switch *ds, int port, struct phy_device *phy) | |||
| 624 | qca8k_port_set_status(priv, port, 1); | 777 | qca8k_port_set_status(priv, port, 1); |
| 625 | } | 778 | } |
| 626 | 779 | ||
| 627 | static int | ||
| 628 | qca8k_phy_read(struct dsa_switch *ds, int phy, int regnum) | ||
| 629 | { | ||
| 630 | struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; | ||
| 631 | |||
| 632 | return mdiobus_read(priv->bus, phy, regnum); | ||
| 633 | } | ||
| 634 | |||
| 635 | static int | ||
| 636 | qca8k_phy_write(struct dsa_switch *ds, int phy, int regnum, u16 val) | ||
| 637 | { | ||
| 638 | struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; | ||
| 639 | |||
| 640 | return mdiobus_write(priv->bus, phy, regnum, val); | ||
| 641 | } | ||
| 642 | |||
| 643 | static void | 780 | static void |
| 644 | qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data) | 781 | qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data) |
| 645 | { | 782 | { |
| @@ -879,8 +1016,6 @@ static const struct dsa_switch_ops qca8k_switch_ops = { | |||
| 879 | .setup = qca8k_setup, | 1016 | .setup = qca8k_setup, |
| 880 | .adjust_link = qca8k_adjust_link, | 1017 | .adjust_link = qca8k_adjust_link, |
| 881 | .get_strings = qca8k_get_strings, | 1018 | .get_strings = qca8k_get_strings, |
| 882 | .phy_read = qca8k_phy_read, | ||
| 883 | .phy_write = qca8k_phy_write, | ||
| 884 | .get_ethtool_stats = qca8k_get_ethtool_stats, | 1019 | .get_ethtool_stats = qca8k_get_ethtool_stats, |
| 885 | .get_sset_count = qca8k_get_sset_count, | 1020 | .get_sset_count = qca8k_get_sset_count, |
| 886 | .get_mac_eee = qca8k_get_mac_eee, | 1021 | .get_mac_eee = qca8k_get_mac_eee, |
| @@ -923,7 +1058,8 @@ qca8k_sw_probe(struct mdio_device *mdiodev) | |||
| 923 | return -ENOMEM; | 1058 | return -ENOMEM; |
| 924 | 1059 | ||
| 925 | priv->ds->priv = priv; | 1060 | priv->ds->priv = priv; |
| 926 | priv->ds->ops = &qca8k_switch_ops; | 1061 | priv->ops = qca8k_switch_ops; |
| 1062 | priv->ds->ops = &priv->ops; | ||
| 927 | mutex_init(&priv->reg_mutex); | 1063 | mutex_init(&priv->reg_mutex); |
| 928 | dev_set_drvdata(&mdiodev->dev, priv); | 1064 | dev_set_drvdata(&mdiodev->dev, priv); |
| 929 | 1065 | ||
diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h index d146e54c8a6c..249fd62268e5 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h | |||
| @@ -49,6 +49,18 @@ | |||
| 49 | #define QCA8K_MIB_FLUSH BIT(24) | 49 | #define QCA8K_MIB_FLUSH BIT(24) |
| 50 | #define QCA8K_MIB_CPU_KEEP BIT(20) | 50 | #define QCA8K_MIB_CPU_KEEP BIT(20) |
| 51 | #define QCA8K_MIB_BUSY BIT(17) | 51 | #define QCA8K_MIB_BUSY BIT(17) |
| 52 | #define QCA8K_MDIO_MASTER_CTRL 0x3c | ||
| 53 | #define QCA8K_MDIO_MASTER_BUSY BIT(31) | ||
| 54 | #define QCA8K_MDIO_MASTER_EN BIT(30) | ||
| 55 | #define QCA8K_MDIO_MASTER_READ BIT(27) | ||
| 56 | #define QCA8K_MDIO_MASTER_WRITE 0 | ||
| 57 | #define QCA8K_MDIO_MASTER_SUP_PRE BIT(26) | ||
| 58 | #define QCA8K_MDIO_MASTER_PHY_ADDR(x) ((x) << 21) | ||
| 59 | #define QCA8K_MDIO_MASTER_REG_ADDR(x) ((x) << 16) | ||
| 60 | #define QCA8K_MDIO_MASTER_DATA(x) (x) | ||
| 61 | #define QCA8K_MDIO_MASTER_DATA_MASK GENMASK(15, 0) | ||
| 62 | #define QCA8K_MDIO_MASTER_MAX_PORTS 5 | ||
| 63 | #define QCA8K_MDIO_MASTER_MAX_REG 32 | ||
| 52 | #define QCA8K_GOL_MAC_ADDR0 0x60 | 64 | #define QCA8K_GOL_MAC_ADDR0 0x60 |
| 53 | #define QCA8K_GOL_MAC_ADDR1 0x64 | 65 | #define QCA8K_GOL_MAC_ADDR1 0x64 |
| 54 | #define QCA8K_REG_PORT_STATUS(_i) (0x07c + (_i) * 4) | 66 | #define QCA8K_REG_PORT_STATUS(_i) (0x07c + (_i) * 4) |
| @@ -169,6 +181,7 @@ struct qca8k_priv { | |||
| 169 | struct dsa_switch *ds; | 181 | struct dsa_switch *ds; |
| 170 | struct mutex reg_mutex; | 182 | struct mutex reg_mutex; |
| 171 | struct device *dev; | 183 | struct device *dev; |
| 184 | struct dsa_switch_ops ops; | ||
| 172 | }; | 185 | }; |
| 173 | 186 | ||
| 174 | struct qca8k_mib_desc { | 187 | struct qca8k_mib_desc { |
diff --git a/drivers/net/ethernet/3com/3c515.c b/drivers/net/ethernet/3com/3c515.c index 808abb6b3671..b15752267c8d 100644 --- a/drivers/net/ethernet/3com/3c515.c +++ b/drivers/net/ethernet/3com/3c515.c | |||
| @@ -1521,7 +1521,7 @@ static void update_stats(int ioaddr, struct net_device *dev) | |||
| 1521 | static void set_rx_mode(struct net_device *dev) | 1521 | static void set_rx_mode(struct net_device *dev) |
| 1522 | { | 1522 | { |
| 1523 | int ioaddr = dev->base_addr; | 1523 | int ioaddr = dev->base_addr; |
| 1524 | short new_mode; | 1524 | unsigned short new_mode; |
| 1525 | 1525 | ||
| 1526 | if (dev->flags & IFF_PROMISC) { | 1526 | if (dev->flags & IFF_PROMISC) { |
| 1527 | if (corkscrew_debug > 3) | 1527 | if (corkscrew_debug > 3) |
diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c index 342ae08ec3c2..d60a86aa8aa8 100644 --- a/drivers/net/ethernet/8390/mac8390.c +++ b/drivers/net/ethernet/8390/mac8390.c | |||
| @@ -153,8 +153,6 @@ static void dayna_block_input(struct net_device *dev, int count, | |||
| 153 | static void dayna_block_output(struct net_device *dev, int count, | 153 | static void dayna_block_output(struct net_device *dev, int count, |
| 154 | const unsigned char *buf, int start_page); | 154 | const unsigned char *buf, int start_page); |
| 155 | 155 | ||
| 156 | #define memcmp_withio(a, b, c) memcmp((a), (void *)(b), (c)) | ||
| 157 | |||
| 158 | /* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */ | 156 | /* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */ |
| 159 | static void slow_sane_get_8390_hdr(struct net_device *dev, | 157 | static void slow_sane_get_8390_hdr(struct net_device *dev, |
| 160 | struct e8390_pkt_hdr *hdr, int ring_page); | 158 | struct e8390_pkt_hdr *hdr, int ring_page); |
| @@ -233,19 +231,26 @@ static enum mac8390_type mac8390_ident(struct nubus_rsrc *fres) | |||
| 233 | 231 | ||
| 234 | static enum mac8390_access mac8390_testio(unsigned long membase) | 232 | static enum mac8390_access mac8390_testio(unsigned long membase) |
| 235 | { | 233 | { |
| 236 | unsigned long outdata = 0xA5A0B5B0; | 234 | u32 outdata = 0xA5A0B5B0; |
| 237 | unsigned long indata = 0x00000000; | 235 | u32 indata = 0; |
| 236 | |||
| 238 | /* Try writing 32 bits */ | 237 | /* Try writing 32 bits */ |
| 239 | memcpy_toio((void __iomem *)membase, &outdata, 4); | 238 | nubus_writel(outdata, membase); |
| 240 | /* Now compare them */ | 239 | /* Now read it back */ |
| 241 | if (memcmp_withio(&outdata, membase, 4) == 0) | 240 | indata = nubus_readl(membase); |
| 241 | if (outdata == indata) | ||
| 242 | return ACCESS_32; | 242 | return ACCESS_32; |
| 243 | |||
| 244 | outdata = 0xC5C0D5D0; | ||
| 245 | indata = 0; | ||
| 246 | |||
| 243 | /* Write 16 bit output */ | 247 | /* Write 16 bit output */ |
| 244 | word_memcpy_tocard(membase, &outdata, 4); | 248 | word_memcpy_tocard(membase, &outdata, 4); |
| 245 | /* Now read it back */ | 249 | /* Now read it back */ |
| 246 | word_memcpy_fromcard(&indata, membase, 4); | 250 | word_memcpy_fromcard(&indata, membase, 4); |
| 247 | if (outdata == indata) | 251 | if (outdata == indata) |
| 248 | return ACCESS_16; | 252 | return ACCESS_16; |
| 253 | |||
| 249 | return ACCESS_UNKNOWN; | 254 | return ACCESS_UNKNOWN; |
| 250 | } | 255 | } |
| 251 | 256 | ||
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c index 74550ccc7a20..e2ffb159cbe2 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c | |||
| @@ -186,11 +186,12 @@ static void aq_rx_checksum(struct aq_ring_s *self, | |||
| 186 | } | 186 | } |
| 187 | if (buff->is_ip_cso) { | 187 | if (buff->is_ip_cso) { |
| 188 | __skb_incr_checksum_unnecessary(skb); | 188 | __skb_incr_checksum_unnecessary(skb); |
| 189 | if (buff->is_udp_cso || buff->is_tcp_cso) | ||
| 190 | __skb_incr_checksum_unnecessary(skb); | ||
| 191 | } else { | 189 | } else { |
| 192 | skb->ip_summed = CHECKSUM_NONE; | 190 | skb->ip_summed = CHECKSUM_NONE; |
| 193 | } | 191 | } |
| 192 | |||
| 193 | if (buff->is_udp_cso || buff->is_tcp_cso) | ||
| 194 | __skb_incr_checksum_unnecessary(skb); | ||
| 194 | } | 195 | } |
| 195 | 196 | ||
| 196 | #define AQ_SKB_ALIGN SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) | 197 | #define AQ_SKB_ALIGN SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) |
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index ad099fd01b45..1522aee81884 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c | |||
| @@ -3370,14 +3370,20 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk, | |||
| 3370 | *hclk = devm_clk_get(&pdev->dev, "hclk"); | 3370 | *hclk = devm_clk_get(&pdev->dev, "hclk"); |
| 3371 | } | 3371 | } |
| 3372 | 3372 | ||
| 3373 | if (IS_ERR(*pclk)) { | 3373 | if (IS_ERR_OR_NULL(*pclk)) { |
| 3374 | err = PTR_ERR(*pclk); | 3374 | err = PTR_ERR(*pclk); |
| 3375 | if (!err) | ||
| 3376 | err = -ENODEV; | ||
| 3377 | |||
| 3375 | dev_err(&pdev->dev, "failed to get macb_clk (%u)\n", err); | 3378 | dev_err(&pdev->dev, "failed to get macb_clk (%u)\n", err); |
| 3376 | return err; | 3379 | return err; |
| 3377 | } | 3380 | } |
| 3378 | 3381 | ||
| 3379 | if (IS_ERR(*hclk)) { | 3382 | if (IS_ERR_OR_NULL(*hclk)) { |
| 3380 | err = PTR_ERR(*hclk); | 3383 | err = PTR_ERR(*hclk); |
| 3384 | if (!err) | ||
| 3385 | err = -ENODEV; | ||
| 3386 | |||
| 3381 | dev_err(&pdev->dev, "failed to get hclk (%u)\n", err); | 3387 | dev_err(&pdev->dev, "failed to get hclk (%u)\n", err); |
| 3382 | return err; | 3388 | return err; |
| 3383 | } | 3389 | } |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c index 3130b43bba52..02959035ed3f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c | |||
| @@ -2620,7 +2620,7 @@ static inline struct port_info *ethqset2pinfo(struct adapter *adap, int qset) | |||
| 2620 | } | 2620 | } |
| 2621 | 2621 | ||
| 2622 | /* should never happen! */ | 2622 | /* should never happen! */ |
| 2623 | BUG_ON(1); | 2623 | BUG(); |
| 2624 | return NULL; | 2624 | return NULL; |
| 2625 | } | 2625 | } |
| 2626 | 2626 | ||
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 88773ca58e6b..b3da81e90132 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c | |||
| @@ -476,7 +476,7 @@ static inline int get_buf_size(struct adapter *adapter, | |||
| 476 | break; | 476 | break; |
| 477 | 477 | ||
| 478 | default: | 478 | default: |
| 479 | BUG_ON(1); | 479 | BUG(); |
| 480 | } | 480 | } |
| 481 | 481 | ||
| 482 | return buf_size; | 482 | return buf_size; |
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index 2ba49e959c3f..dc339dc1adb2 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | |||
| @@ -815,6 +815,14 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev) | |||
| 815 | */ | 815 | */ |
| 816 | queue_mapping = skb_get_queue_mapping(skb); | 816 | queue_mapping = skb_get_queue_mapping(skb); |
| 817 | fq = &priv->fq[queue_mapping]; | 817 | fq = &priv->fq[queue_mapping]; |
| 818 | |||
| 819 | fd_len = dpaa2_fd_get_len(&fd); | ||
| 820 | nq = netdev_get_tx_queue(net_dev, queue_mapping); | ||
| 821 | netdev_tx_sent_queue(nq, fd_len); | ||
| 822 | |||
| 823 | /* Everything that happens after this enqueues might race with | ||
| 824 | * the Tx confirmation callback for this frame | ||
| 825 | */ | ||
| 818 | for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) { | 826 | for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) { |
| 819 | err = priv->enqueue(priv, fq, &fd, 0); | 827 | err = priv->enqueue(priv, fq, &fd, 0); |
| 820 | if (err != -EBUSY) | 828 | if (err != -EBUSY) |
| @@ -825,13 +833,10 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev) | |||
| 825 | percpu_stats->tx_errors++; | 833 | percpu_stats->tx_errors++; |
| 826 | /* Clean up everything, including freeing the skb */ | 834 | /* Clean up everything, including freeing the skb */ |
| 827 | free_tx_fd(priv, fq, &fd, false); | 835 | free_tx_fd(priv, fq, &fd, false); |
| 836 | netdev_tx_completed_queue(nq, 1, fd_len); | ||
| 828 | } else { | 837 | } else { |
| 829 | fd_len = dpaa2_fd_get_len(&fd); | ||
| 830 | percpu_stats->tx_packets++; | 838 | percpu_stats->tx_packets++; |
| 831 | percpu_stats->tx_bytes += fd_len; | 839 | percpu_stats->tx_bytes += fd_len; |
| 832 | |||
| 833 | nq = netdev_get_tx_queue(net_dev, queue_mapping); | ||
| 834 | netdev_tx_sent_queue(nq, fd_len); | ||
| 835 | } | 840 | } |
| 836 | 841 | ||
| 837 | return NETDEV_TX_OK; | 842 | return NETDEV_TX_OK; |
| @@ -1817,7 +1822,7 @@ static int dpaa2_eth_xdp_xmit_frame(struct net_device *net_dev, | |||
| 1817 | dpaa2_fd_set_format(&fd, dpaa2_fd_single); | 1822 | dpaa2_fd_set_format(&fd, dpaa2_fd_single); |
| 1818 | dpaa2_fd_set_ctrl(&fd, FD_CTRL_PTA); | 1823 | dpaa2_fd_set_ctrl(&fd, FD_CTRL_PTA); |
| 1819 | 1824 | ||
| 1820 | fq = &priv->fq[smp_processor_id()]; | 1825 | fq = &priv->fq[smp_processor_id() % dpaa2_eth_queue_count(priv)]; |
| 1821 | for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) { | 1826 | for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) { |
| 1822 | err = priv->enqueue(priv, fq, &fd, 0); | 1827 | err = priv->enqueue(priv, fq, &fd, 0); |
| 1823 | if (err != -EBUSY) | 1828 | if (err != -EBUSY) |
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 1c1f17ec6be2..162cb9afa0e7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include "hns3_enet.h" | 22 | #include "hns3_enet.h" |
| 23 | 23 | ||
| 24 | #define hns3_set_field(origin, shift, val) ((origin) |= ((val) << (shift))) | 24 | #define hns3_set_field(origin, shift, val) ((origin) |= ((val) << (shift))) |
| 25 | #define hns3_tx_bd_count(S) DIV_ROUND_UP(S, HNS3_MAX_BD_SIZE) | ||
| 25 | 26 | ||
| 26 | static void hns3_clear_all_ring(struct hnae3_handle *h); | 27 | static void hns3_clear_all_ring(struct hnae3_handle *h); |
| 27 | static void hns3_force_clear_all_rx_ring(struct hnae3_handle *h); | 28 | static void hns3_force_clear_all_rx_ring(struct hnae3_handle *h); |
| @@ -1079,7 +1080,7 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, | |||
| 1079 | 1080 | ||
| 1080 | desc_cb->length = size; | 1081 | desc_cb->length = size; |
| 1081 | 1082 | ||
| 1082 | frag_buf_num = (size + HNS3_MAX_BD_SIZE - 1) >> HNS3_MAX_BD_SIZE_OFFSET; | 1083 | frag_buf_num = hns3_tx_bd_count(size); |
| 1083 | sizeoflast = size & HNS3_TX_LAST_SIZE_M; | 1084 | sizeoflast = size & HNS3_TX_LAST_SIZE_M; |
| 1084 | sizeoflast = sizeoflast ? sizeoflast : HNS3_MAX_BD_SIZE; | 1085 | sizeoflast = sizeoflast ? sizeoflast : HNS3_MAX_BD_SIZE; |
| 1085 | 1086 | ||
| @@ -1124,14 +1125,13 @@ static int hns3_nic_maybe_stop_tso(struct sk_buff **out_skb, int *bnum, | |||
| 1124 | int i; | 1125 | int i; |
| 1125 | 1126 | ||
| 1126 | size = skb_headlen(skb); | 1127 | size = skb_headlen(skb); |
| 1127 | buf_num = (size + HNS3_MAX_BD_SIZE - 1) >> HNS3_MAX_BD_SIZE_OFFSET; | 1128 | buf_num = hns3_tx_bd_count(size); |
| 1128 | 1129 | ||
| 1129 | frag_num = skb_shinfo(skb)->nr_frags; | 1130 | frag_num = skb_shinfo(skb)->nr_frags; |
| 1130 | for (i = 0; i < frag_num; i++) { | 1131 | for (i = 0; i < frag_num; i++) { |
| 1131 | frag = &skb_shinfo(skb)->frags[i]; | 1132 | frag = &skb_shinfo(skb)->frags[i]; |
| 1132 | size = skb_frag_size(frag); | 1133 | size = skb_frag_size(frag); |
| 1133 | bdnum_for_frag = (size + HNS3_MAX_BD_SIZE - 1) >> | 1134 | bdnum_for_frag = hns3_tx_bd_count(size); |
| 1134 | HNS3_MAX_BD_SIZE_OFFSET; | ||
| 1135 | if (unlikely(bdnum_for_frag > HNS3_MAX_BD_PER_FRAG)) | 1135 | if (unlikely(bdnum_for_frag > HNS3_MAX_BD_PER_FRAG)) |
| 1136 | return -ENOMEM; | 1136 | return -ENOMEM; |
| 1137 | 1137 | ||
| @@ -1139,8 +1139,7 @@ static int hns3_nic_maybe_stop_tso(struct sk_buff **out_skb, int *bnum, | |||
| 1139 | } | 1139 | } |
| 1140 | 1140 | ||
| 1141 | if (unlikely(buf_num > HNS3_MAX_BD_PER_FRAG)) { | 1141 | if (unlikely(buf_num > HNS3_MAX_BD_PER_FRAG)) { |
| 1142 | buf_num = (skb->len + HNS3_MAX_BD_SIZE - 1) >> | 1142 | buf_num = hns3_tx_bd_count(skb->len); |
| 1143 | HNS3_MAX_BD_SIZE_OFFSET; | ||
| 1144 | if (ring_space(ring) < buf_num) | 1143 | if (ring_space(ring) < buf_num) |
| 1145 | return -EBUSY; | 1144 | return -EBUSY; |
| 1146 | /* manual split the send packet */ | 1145 | /* manual split the send packet */ |
| @@ -1169,7 +1168,7 @@ static int hns3_nic_maybe_stop_tx(struct sk_buff **out_skb, int *bnum, | |||
| 1169 | buf_num = skb_shinfo(skb)->nr_frags + 1; | 1168 | buf_num = skb_shinfo(skb)->nr_frags + 1; |
| 1170 | 1169 | ||
| 1171 | if (unlikely(buf_num > HNS3_MAX_BD_PER_FRAG)) { | 1170 | if (unlikely(buf_num > HNS3_MAX_BD_PER_FRAG)) { |
| 1172 | buf_num = (skb->len + HNS3_MAX_BD_SIZE - 1) / HNS3_MAX_BD_SIZE; | 1171 | buf_num = hns3_tx_bd_count(skb->len); |
| 1173 | if (ring_space(ring) < buf_num) | 1172 | if (ring_space(ring) < buf_num) |
| 1174 | return -EBUSY; | 1173 | return -EBUSY; |
| 1175 | /* manual split the send packet */ | 1174 | /* manual split the send packet */ |
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 1db0bd41d209..75669cd0c311 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | |||
| @@ -193,7 +193,6 @@ enum hns3_nic_state { | |||
| 193 | #define HNS3_VECTOR_INITED 1 | 193 | #define HNS3_VECTOR_INITED 1 |
| 194 | 194 | ||
| 195 | #define HNS3_MAX_BD_SIZE 65535 | 195 | #define HNS3_MAX_BD_SIZE 65535 |
| 196 | #define HNS3_MAX_BD_SIZE_OFFSET 16 | ||
| 197 | #define HNS3_MAX_BD_PER_FRAG 8 | 196 | #define HNS3_MAX_BD_PER_FRAG 8 |
| 198 | #define HNS3_MAX_BD_PER_PKT MAX_SKB_FRAGS | 197 | #define HNS3_MAX_BD_PER_PKT MAX_SKB_FRAGS |
| 199 | 198 | ||
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 3baabdc89726..90b62c1412c8 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c | |||
| @@ -3160,6 +3160,7 @@ static ssize_t ehea_probe_port(struct device *dev, | |||
| 3160 | 3160 | ||
| 3161 | if (ehea_add_adapter_mr(adapter)) { | 3161 | if (ehea_add_adapter_mr(adapter)) { |
| 3162 | pr_err("creating MR failed\n"); | 3162 | pr_err("creating MR failed\n"); |
| 3163 | of_node_put(eth_dn); | ||
| 3163 | return -EIO; | 3164 | return -EIO; |
| 3164 | } | 3165 | } |
| 3165 | 3166 | ||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c index 7a15e932ed2f..c1c1965d7acc 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c | |||
| @@ -113,7 +113,7 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, | |||
| 113 | return 0; | 113 | return 0; |
| 114 | default: | 114 | default: |
| 115 | /* Do not consider thresholds for zero temperature. */ | 115 | /* Do not consider thresholds for zero temperature. */ |
| 116 | if (!MLXSW_REG_MTMP_TEMP_TO_MC(module_temp)) { | 116 | if (MLXSW_REG_MTMP_TEMP_TO_MC(module_temp) == 0) { |
| 117 | *temp = 0; | 117 | *temp = 0; |
| 118 | return 0; | 118 | return 0; |
| 119 | } | 119 | } |
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index bd6e9014bc74..7849119d407a 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c | |||
| @@ -142,6 +142,12 @@ struct ks8851_net { | |||
| 142 | 142 | ||
| 143 | static int msg_enable; | 143 | static int msg_enable; |
| 144 | 144 | ||
| 145 | /* SPI frame opcodes */ | ||
| 146 | #define KS_SPIOP_RD (0x00) | ||
| 147 | #define KS_SPIOP_WR (0x40) | ||
| 148 | #define KS_SPIOP_RXFIFO (0x80) | ||
| 149 | #define KS_SPIOP_TXFIFO (0xC0) | ||
| 150 | |||
| 145 | /* shift for byte-enable data */ | 151 | /* shift for byte-enable data */ |
| 146 | #define BYTE_EN(_x) ((_x) << 2) | 152 | #define BYTE_EN(_x) ((_x) << 2) |
| 147 | 153 | ||
| @@ -535,9 +541,8 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) | |||
| 535 | /* set dma read address */ | 541 | /* set dma read address */ |
| 536 | ks8851_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI | 0x00); | 542 | ks8851_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI | 0x00); |
| 537 | 543 | ||
| 538 | /* start the packet dma process, and set auto-dequeue rx */ | 544 | /* start DMA access */ |
| 539 | ks8851_wrreg16(ks, KS_RXQCR, | 545 | ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA); |
| 540 | ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE); | ||
| 541 | 546 | ||
| 542 | if (rxlen > 4) { | 547 | if (rxlen > 4) { |
| 543 | unsigned int rxalign; | 548 | unsigned int rxalign; |
| @@ -568,7 +573,8 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) | |||
| 568 | } | 573 | } |
| 569 | } | 574 | } |
| 570 | 575 | ||
| 571 | ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); | 576 | /* end DMA access and dequeue packet */ |
| 577 | ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_RRXEF); | ||
| 572 | } | 578 | } |
| 573 | } | 579 | } |
| 574 | 580 | ||
| @@ -785,6 +791,15 @@ static void ks8851_tx_work(struct work_struct *work) | |||
| 785 | static int ks8851_net_open(struct net_device *dev) | 791 | static int ks8851_net_open(struct net_device *dev) |
| 786 | { | 792 | { |
| 787 | struct ks8851_net *ks = netdev_priv(dev); | 793 | struct ks8851_net *ks = netdev_priv(dev); |
| 794 | int ret; | ||
| 795 | |||
| 796 | ret = request_threaded_irq(dev->irq, NULL, ks8851_irq, | ||
| 797 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
| 798 | dev->name, ks); | ||
| 799 | if (ret < 0) { | ||
| 800 | netdev_err(dev, "failed to get irq\n"); | ||
| 801 | return ret; | ||
| 802 | } | ||
| 788 | 803 | ||
| 789 | /* lock the card, even if we may not actually be doing anything | 804 | /* lock the card, even if we may not actually be doing anything |
| 790 | * else at the moment */ | 805 | * else at the moment */ |
| @@ -849,6 +864,7 @@ static int ks8851_net_open(struct net_device *dev) | |||
| 849 | netif_dbg(ks, ifup, ks->netdev, "network device up\n"); | 864 | netif_dbg(ks, ifup, ks->netdev, "network device up\n"); |
| 850 | 865 | ||
| 851 | mutex_unlock(&ks->lock); | 866 | mutex_unlock(&ks->lock); |
| 867 | mii_check_link(&ks->mii); | ||
| 852 | return 0; | 868 | return 0; |
| 853 | } | 869 | } |
| 854 | 870 | ||
| @@ -899,6 +915,8 @@ static int ks8851_net_stop(struct net_device *dev) | |||
| 899 | dev_kfree_skb(txb); | 915 | dev_kfree_skb(txb); |
| 900 | } | 916 | } |
| 901 | 917 | ||
| 918 | free_irq(dev->irq, ks); | ||
| 919 | |||
| 902 | return 0; | 920 | return 0; |
| 903 | } | 921 | } |
| 904 | 922 | ||
| @@ -1508,6 +1526,7 @@ static int ks8851_probe(struct spi_device *spi) | |||
| 1508 | 1526 | ||
| 1509 | spi_set_drvdata(spi, ks); | 1527 | spi_set_drvdata(spi, ks); |
| 1510 | 1528 | ||
| 1529 | netif_carrier_off(ks->netdev); | ||
| 1511 | ndev->if_port = IF_PORT_100BASET; | 1530 | ndev->if_port = IF_PORT_100BASET; |
| 1512 | ndev->netdev_ops = &ks8851_netdev_ops; | 1531 | ndev->netdev_ops = &ks8851_netdev_ops; |
| 1513 | ndev->irq = spi->irq; | 1532 | ndev->irq = spi->irq; |
| @@ -1529,14 +1548,6 @@ static int ks8851_probe(struct spi_device *spi) | |||
| 1529 | ks8851_read_selftest(ks); | 1548 | ks8851_read_selftest(ks); |
| 1530 | ks8851_init_mac(ks); | 1549 | ks8851_init_mac(ks); |
| 1531 | 1550 | ||
| 1532 | ret = request_threaded_irq(spi->irq, NULL, ks8851_irq, | ||
| 1533 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
| 1534 | ndev->name, ks); | ||
| 1535 | if (ret < 0) { | ||
| 1536 | dev_err(&spi->dev, "failed to get irq\n"); | ||
| 1537 | goto err_irq; | ||
| 1538 | } | ||
| 1539 | |||
| 1540 | ret = register_netdev(ndev); | 1551 | ret = register_netdev(ndev); |
| 1541 | if (ret) { | 1552 | if (ret) { |
| 1542 | dev_err(&spi->dev, "failed to register network device\n"); | 1553 | dev_err(&spi->dev, "failed to register network device\n"); |
| @@ -1549,14 +1560,10 @@ static int ks8851_probe(struct spi_device *spi) | |||
| 1549 | 1560 | ||
| 1550 | return 0; | 1561 | return 0; |
| 1551 | 1562 | ||
| 1552 | |||
| 1553 | err_netdev: | 1563 | err_netdev: |
| 1554 | free_irq(ndev->irq, ks); | 1564 | err_id: |
| 1555 | |||
| 1556 | err_irq: | ||
| 1557 | if (gpio_is_valid(gpio)) | 1565 | if (gpio_is_valid(gpio)) |
| 1558 | gpio_set_value(gpio, 0); | 1566 | gpio_set_value(gpio, 0); |
| 1559 | err_id: | ||
| 1560 | regulator_disable(ks->vdd_reg); | 1567 | regulator_disable(ks->vdd_reg); |
| 1561 | err_reg: | 1568 | err_reg: |
| 1562 | regulator_disable(ks->vdd_io); | 1569 | regulator_disable(ks->vdd_io); |
| @@ -1574,7 +1581,6 @@ static int ks8851_remove(struct spi_device *spi) | |||
| 1574 | dev_info(&spi->dev, "remove\n"); | 1581 | dev_info(&spi->dev, "remove\n"); |
| 1575 | 1582 | ||
| 1576 | unregister_netdev(priv->netdev); | 1583 | unregister_netdev(priv->netdev); |
| 1577 | free_irq(spi->irq, priv); | ||
| 1578 | if (gpio_is_valid(priv->gpio)) | 1584 | if (gpio_is_valid(priv->gpio)) |
| 1579 | gpio_set_value(priv->gpio, 0); | 1585 | gpio_set_value(priv->gpio, 0); |
| 1580 | regulator_disable(priv->vdd_reg); | 1586 | regulator_disable(priv->vdd_reg); |
diff --git a/drivers/net/ethernet/micrel/ks8851.h b/drivers/net/ethernet/micrel/ks8851.h index 852256ef1f22..23da1e3ee429 100644 --- a/drivers/net/ethernet/micrel/ks8851.h +++ b/drivers/net/ethernet/micrel/ks8851.h | |||
| @@ -11,9 +11,15 @@ | |||
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #define KS_CCR 0x08 | 13 | #define KS_CCR 0x08 |
| 14 | #define CCR_LE (1 << 10) /* KSZ8851-16MLL */ | ||
| 14 | #define CCR_EEPROM (1 << 9) | 15 | #define CCR_EEPROM (1 << 9) |
| 15 | #define CCR_SPI (1 << 8) | 16 | #define CCR_SPI (1 << 8) /* KSZ8851SNL */ |
| 16 | #define CCR_32PIN (1 << 0) | 17 | #define CCR_8BIT (1 << 7) /* KSZ8851-16MLL */ |
| 18 | #define CCR_16BIT (1 << 6) /* KSZ8851-16MLL */ | ||
| 19 | #define CCR_32BIT (1 << 5) /* KSZ8851-16MLL */ | ||
| 20 | #define CCR_SHARED (1 << 4) /* KSZ8851-16MLL */ | ||
| 21 | #define CCR_48PIN (1 << 1) /* KSZ8851-16MLL */ | ||
| 22 | #define CCR_32PIN (1 << 0) /* KSZ8851SNL */ | ||
| 17 | 23 | ||
| 18 | /* MAC address registers */ | 24 | /* MAC address registers */ |
| 19 | #define KS_MAR(_m) (0x15 - (_m)) | 25 | #define KS_MAR(_m) (0x15 - (_m)) |
| @@ -112,13 +118,13 @@ | |||
| 112 | #define RXCR1_RXE (1 << 0) | 118 | #define RXCR1_RXE (1 << 0) |
| 113 | 119 | ||
| 114 | #define KS_RXCR2 0x76 | 120 | #define KS_RXCR2 0x76 |
| 115 | #define RXCR2_SRDBL_MASK (0x7 << 5) | 121 | #define RXCR2_SRDBL_MASK (0x7 << 5) /* KSZ8851SNL */ |
| 116 | #define RXCR2_SRDBL_SHIFT (5) | 122 | #define RXCR2_SRDBL_SHIFT (5) /* KSZ8851SNL */ |
| 117 | #define RXCR2_SRDBL_4B (0x0 << 5) | 123 | #define RXCR2_SRDBL_4B (0x0 << 5) /* KSZ8851SNL */ |
| 118 | #define RXCR2_SRDBL_8B (0x1 << 5) | 124 | #define RXCR2_SRDBL_8B (0x1 << 5) /* KSZ8851SNL */ |
| 119 | #define RXCR2_SRDBL_16B (0x2 << 5) | 125 | #define RXCR2_SRDBL_16B (0x2 << 5) /* KSZ8851SNL */ |
| 120 | #define RXCR2_SRDBL_32B (0x3 << 5) | 126 | #define RXCR2_SRDBL_32B (0x3 << 5) /* KSZ8851SNL */ |
| 121 | #define RXCR2_SRDBL_FRAME (0x4 << 5) | 127 | #define RXCR2_SRDBL_FRAME (0x4 << 5) /* KSZ8851SNL */ |
| 122 | #define RXCR2_IUFFP (1 << 4) | 128 | #define RXCR2_IUFFP (1 << 4) |
| 123 | #define RXCR2_RXIUFCEZ (1 << 3) | 129 | #define RXCR2_RXIUFCEZ (1 << 3) |
| 124 | #define RXCR2_UDPLFE (1 << 2) | 130 | #define RXCR2_UDPLFE (1 << 2) |
| @@ -143,8 +149,10 @@ | |||
| 143 | #define RXFSHR_RXCE (1 << 0) | 149 | #define RXFSHR_RXCE (1 << 0) |
| 144 | 150 | ||
| 145 | #define KS_RXFHBCR 0x7E | 151 | #define KS_RXFHBCR 0x7E |
| 152 | #define RXFHBCR_CNT_MASK (0xfff << 0) | ||
| 153 | |||
| 146 | #define KS_TXQCR 0x80 | 154 | #define KS_TXQCR 0x80 |
| 147 | #define TXQCR_AETFE (1 << 2) | 155 | #define TXQCR_AETFE (1 << 2) /* KSZ8851SNL */ |
| 148 | #define TXQCR_TXQMAM (1 << 1) | 156 | #define TXQCR_TXQMAM (1 << 1) |
| 149 | #define TXQCR_METFE (1 << 0) | 157 | #define TXQCR_METFE (1 << 0) |
| 150 | 158 | ||
| @@ -167,6 +175,10 @@ | |||
| 167 | 175 | ||
| 168 | #define KS_RXFDPR 0x86 | 176 | #define KS_RXFDPR 0x86 |
| 169 | #define RXFDPR_RXFPAI (1 << 14) | 177 | #define RXFDPR_RXFPAI (1 << 14) |
| 178 | #define RXFDPR_WST (1 << 12) /* KSZ8851-16MLL */ | ||
| 179 | #define RXFDPR_EMS (1 << 11) /* KSZ8851-16MLL */ | ||
| 180 | #define RXFDPR_RXFP_MASK (0x7ff << 0) | ||
| 181 | #define RXFDPR_RXFP_SHIFT (0) | ||
| 170 | 182 | ||
| 171 | #define KS_RXDTTR 0x8C | 183 | #define KS_RXDTTR 0x8C |
| 172 | #define KS_RXDBCTR 0x8E | 184 | #define KS_RXDBCTR 0x8E |
| @@ -184,7 +196,7 @@ | |||
| 184 | #define IRQ_RXMPDI (1 << 4) | 196 | #define IRQ_RXMPDI (1 << 4) |
| 185 | #define IRQ_LDI (1 << 3) | 197 | #define IRQ_LDI (1 << 3) |
| 186 | #define IRQ_EDI (1 << 2) | 198 | #define IRQ_EDI (1 << 2) |
| 187 | #define IRQ_SPIBEI (1 << 1) | 199 | #define IRQ_SPIBEI (1 << 1) /* KSZ8851SNL */ |
| 188 | #define IRQ_DEDI (1 << 0) | 200 | #define IRQ_DEDI (1 << 0) |
| 189 | 201 | ||
| 190 | #define KS_RXFCTR 0x9C | 202 | #define KS_RXFCTR 0x9C |
| @@ -257,42 +269,37 @@ | |||
| 257 | #define KS_P1ANLPR 0xEE | 269 | #define KS_P1ANLPR 0xEE |
| 258 | 270 | ||
| 259 | #define KS_P1SCLMD 0xF4 | 271 | #define KS_P1SCLMD 0xF4 |
| 260 | #define P1SCLMD_LEDOFF (1 << 15) | ||
| 261 | #define P1SCLMD_TXIDS (1 << 14) | ||
| 262 | #define P1SCLMD_RESTARTAN (1 << 13) | ||
| 263 | #define P1SCLMD_DISAUTOMDIX (1 << 10) | ||
| 264 | #define P1SCLMD_FORCEMDIX (1 << 9) | ||
| 265 | #define P1SCLMD_AUTONEGEN (1 << 7) | ||
| 266 | #define P1SCLMD_FORCE100 (1 << 6) | ||
| 267 | #define P1SCLMD_FORCEFDX (1 << 5) | ||
| 268 | #define P1SCLMD_ADV_FLOW (1 << 4) | ||
| 269 | #define P1SCLMD_ADV_100BT_FDX (1 << 3) | ||
| 270 | #define P1SCLMD_ADV_100BT_HDX (1 << 2) | ||
| 271 | #define P1SCLMD_ADV_10BT_FDX (1 << 1) | ||
| 272 | #define P1SCLMD_ADV_10BT_HDX (1 << 0) | ||
| 273 | 272 | ||
| 274 | #define KS_P1CR 0xF6 | 273 | #define KS_P1CR 0xF6 |
| 275 | #define P1CR_HP_MDIX (1 << 15) | 274 | #define P1CR_LEDOFF (1 << 15) |
| 276 | #define P1CR_REV_POL (1 << 13) | 275 | #define P1CR_TXIDS (1 << 14) |
| 277 | #define P1CR_OP_100M (1 << 10) | 276 | #define P1CR_RESTARTAN (1 << 13) |
| 278 | #define P1CR_OP_FDX (1 << 9) | 277 | #define P1CR_DISAUTOMDIX (1 << 10) |
| 279 | #define P1CR_OP_MDI (1 << 7) | 278 | #define P1CR_FORCEMDIX (1 << 9) |
| 280 | #define P1CR_AN_DONE (1 << 6) | 279 | #define P1CR_AUTONEGEN (1 << 7) |
| 281 | #define P1CR_LINK_GOOD (1 << 5) | 280 | #define P1CR_FORCE100 (1 << 6) |
| 282 | #define P1CR_PNTR_FLOW (1 << 4) | 281 | #define P1CR_FORCEFDX (1 << 5) |
| 283 | #define P1CR_PNTR_100BT_FDX (1 << 3) | 282 | #define P1CR_ADV_FLOW (1 << 4) |
| 284 | #define P1CR_PNTR_100BT_HDX (1 << 2) | 283 | #define P1CR_ADV_100BT_FDX (1 << 3) |
| 285 | #define P1CR_PNTR_10BT_FDX (1 << 1) | 284 | #define P1CR_ADV_100BT_HDX (1 << 2) |
| 286 | #define P1CR_PNTR_10BT_HDX (1 << 0) | 285 | #define P1CR_ADV_10BT_FDX (1 << 1) |
| 286 | #define P1CR_ADV_10BT_HDX (1 << 0) | ||
| 287 | |||
| 288 | #define KS_P1SR 0xF8 | ||
| 289 | #define P1SR_HP_MDIX (1 << 15) | ||
| 290 | #define P1SR_REV_POL (1 << 13) | ||
| 291 | #define P1SR_OP_100M (1 << 10) | ||
| 292 | #define P1SR_OP_FDX (1 << 9) | ||
| 293 | #define P1SR_OP_MDI (1 << 7) | ||
| 294 | #define P1SR_AN_DONE (1 << 6) | ||
| 295 | #define P1SR_LINK_GOOD (1 << 5) | ||
| 296 | #define P1SR_PNTR_FLOW (1 << 4) | ||
| 297 | #define P1SR_PNTR_100BT_FDX (1 << 3) | ||
| 298 | #define P1SR_PNTR_100BT_HDX (1 << 2) | ||
| 299 | #define P1SR_PNTR_10BT_FDX (1 << 1) | ||
| 300 | #define P1SR_PNTR_10BT_HDX (1 << 0) | ||
| 287 | 301 | ||
| 288 | /* TX Frame control */ | 302 | /* TX Frame control */ |
| 289 | |||
| 290 | #define TXFR_TXIC (1 << 15) | 303 | #define TXFR_TXIC (1 << 15) |
| 291 | #define TXFR_TXFID_MASK (0x3f << 0) | 304 | #define TXFR_TXFID_MASK (0x3f << 0) |
| 292 | #define TXFR_TXFID_SHIFT (0) | 305 | #define TXFR_TXFID_SHIFT (0) |
| 293 | |||
| 294 | /* SPI frame opcodes */ | ||
| 295 | #define KS_SPIOP_RD (0x00) | ||
| 296 | #define KS_SPIOP_WR (0x40) | ||
| 297 | #define KS_SPIOP_RXFIFO (0x80) | ||
| 298 | #define KS_SPIOP_TXFIFO (0xC0) | ||
diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c index 35f8c9ef204d..c946841c0a06 100644 --- a/drivers/net/ethernet/micrel/ks8851_mll.c +++ b/drivers/net/ethernet/micrel/ks8851_mll.c | |||
| @@ -40,6 +40,8 @@ | |||
| 40 | #include <linux/of_device.h> | 40 | #include <linux/of_device.h> |
| 41 | #include <linux/of_net.h> | 41 | #include <linux/of_net.h> |
| 42 | 42 | ||
| 43 | #include "ks8851.h" | ||
| 44 | |||
| 43 | #define DRV_NAME "ks8851_mll" | 45 | #define DRV_NAME "ks8851_mll" |
| 44 | 46 | ||
| 45 | static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x86, 0x95, 0x11 }; | 47 | static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x86, 0x95, 0x11 }; |
| @@ -48,319 +50,10 @@ static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x86, 0x95, 0x11 }; | |||
| 48 | #define TX_BUF_SIZE 2000 | 50 | #define TX_BUF_SIZE 2000 |
| 49 | #define RX_BUF_SIZE 2000 | 51 | #define RX_BUF_SIZE 2000 |
| 50 | 52 | ||
| 51 | #define KS_CCR 0x08 | ||
| 52 | #define CCR_EEPROM (1 << 9) | ||
| 53 | #define CCR_SPI (1 << 8) | ||
| 54 | #define CCR_8BIT (1 << 7) | ||
| 55 | #define CCR_16BIT (1 << 6) | ||
| 56 | #define CCR_32BIT (1 << 5) | ||
| 57 | #define CCR_SHARED (1 << 4) | ||
| 58 | #define CCR_32PIN (1 << 0) | ||
| 59 | |||
| 60 | /* MAC address registers */ | ||
| 61 | #define KS_MARL 0x10 | ||
| 62 | #define KS_MARM 0x12 | ||
| 63 | #define KS_MARH 0x14 | ||
| 64 | |||
| 65 | #define KS_OBCR 0x20 | ||
| 66 | #define OBCR_ODS_16MA (1 << 6) | ||
| 67 | |||
| 68 | #define KS_EEPCR 0x22 | ||
| 69 | #define EEPCR_EESA (1 << 4) | ||
| 70 | #define EEPCR_EESB (1 << 3) | ||
| 71 | #define EEPCR_EEDO (1 << 2) | ||
| 72 | #define EEPCR_EESCK (1 << 1) | ||
| 73 | #define EEPCR_EECS (1 << 0) | ||
| 74 | |||
| 75 | #define KS_MBIR 0x24 | ||
| 76 | #define MBIR_TXMBF (1 << 12) | ||
| 77 | #define MBIR_TXMBFA (1 << 11) | ||
| 78 | #define MBIR_RXMBF (1 << 4) | ||
| 79 | #define MBIR_RXMBFA (1 << 3) | ||
| 80 | |||
| 81 | #define KS_GRR 0x26 | ||
| 82 | #define GRR_QMU (1 << 1) | ||
| 83 | #define GRR_GSR (1 << 0) | ||
| 84 | |||
| 85 | #define KS_WFCR 0x2A | ||
| 86 | #define WFCR_MPRXE (1 << 7) | ||
| 87 | #define WFCR_WF3E (1 << 3) | ||
| 88 | #define WFCR_WF2E (1 << 2) | ||
| 89 | #define WFCR_WF1E (1 << 1) | ||
| 90 | #define WFCR_WF0E (1 << 0) | ||
| 91 | |||
| 92 | #define KS_WF0CRC0 0x30 | ||
| 93 | #define KS_WF0CRC1 0x32 | ||
| 94 | #define KS_WF0BM0 0x34 | ||
| 95 | #define KS_WF0BM1 0x36 | ||
| 96 | #define KS_WF0BM2 0x38 | ||
| 97 | #define KS_WF0BM3 0x3A | ||
| 98 | |||
| 99 | #define KS_WF1CRC0 0x40 | ||
| 100 | #define KS_WF1CRC1 0x42 | ||
| 101 | #define KS_WF1BM0 0x44 | ||
| 102 | #define KS_WF1BM1 0x46 | ||
| 103 | #define KS_WF1BM2 0x48 | ||
| 104 | #define KS_WF1BM3 0x4A | ||
| 105 | |||
| 106 | #define KS_WF2CRC0 0x50 | ||
| 107 | #define KS_WF2CRC1 0x52 | ||
| 108 | #define KS_WF2BM0 0x54 | ||
| 109 | #define KS_WF2BM1 0x56 | ||
| 110 | #define KS_WF2BM2 0x58 | ||
| 111 | #define KS_WF2BM3 0x5A | ||
| 112 | |||
| 113 | #define KS_WF3CRC0 0x60 | ||
| 114 | #define KS_WF3CRC1 0x62 | ||
| 115 | #define KS_WF3BM0 0x64 | ||
| 116 | #define KS_WF3BM1 0x66 | ||
| 117 | #define KS_WF3BM2 0x68 | ||
| 118 | #define KS_WF3BM3 0x6A | ||
| 119 | |||
| 120 | #define KS_TXCR 0x70 | ||
| 121 | #define TXCR_TCGICMP (1 << 8) | ||
| 122 | #define TXCR_TCGUDP (1 << 7) | ||
| 123 | #define TXCR_TCGTCP (1 << 6) | ||
| 124 | #define TXCR_TCGIP (1 << 5) | ||
| 125 | #define TXCR_FTXQ (1 << 4) | ||
| 126 | #define TXCR_TXFCE (1 << 3) | ||
| 127 | #define TXCR_TXPE (1 << 2) | ||
| 128 | #define TXCR_TXCRC (1 << 1) | ||
| 129 | #define TXCR_TXE (1 << 0) | ||
| 130 | |||
| 131 | #define KS_TXSR 0x72 | ||
| 132 | #define TXSR_TXLC (1 << 13) | ||
| 133 | #define TXSR_TXMC (1 << 12) | ||
| 134 | #define TXSR_TXFID_MASK (0x3f << 0) | ||
| 135 | #define TXSR_TXFID_SHIFT (0) | ||
| 136 | #define TXSR_TXFID_GET(_v) (((_v) >> 0) & 0x3f) | ||
| 137 | |||
| 138 | |||
| 139 | #define KS_RXCR1 0x74 | ||
| 140 | #define RXCR1_FRXQ (1 << 15) | ||
| 141 | #define RXCR1_RXUDPFCC (1 << 14) | ||
| 142 | #define RXCR1_RXTCPFCC (1 << 13) | ||
| 143 | #define RXCR1_RXIPFCC (1 << 12) | ||
| 144 | #define RXCR1_RXPAFMA (1 << 11) | ||
| 145 | #define RXCR1_RXFCE (1 << 10) | ||
| 146 | #define RXCR1_RXEFE (1 << 9) | ||
| 147 | #define RXCR1_RXMAFMA (1 << 8) | ||
| 148 | #define RXCR1_RXBE (1 << 7) | ||
| 149 | #define RXCR1_RXME (1 << 6) | ||
| 150 | #define RXCR1_RXUE (1 << 5) | ||
| 151 | #define RXCR1_RXAE (1 << 4) | ||
| 152 | #define RXCR1_RXINVF (1 << 1) | ||
| 153 | #define RXCR1_RXE (1 << 0) | ||
| 154 | #define RXCR1_FILTER_MASK (RXCR1_RXINVF | RXCR1_RXAE | \ | 53 | #define RXCR1_FILTER_MASK (RXCR1_RXINVF | RXCR1_RXAE | \ |
| 155 | RXCR1_RXMAFMA | RXCR1_RXPAFMA) | 54 | RXCR1_RXMAFMA | RXCR1_RXPAFMA) |
| 156 | |||
| 157 | #define KS_RXCR2 0x76 | ||
| 158 | #define RXCR2_SRDBL_MASK (0x7 << 5) | ||
| 159 | #define RXCR2_SRDBL_SHIFT (5) | ||
| 160 | #define RXCR2_SRDBL_4B (0x0 << 5) | ||
| 161 | #define RXCR2_SRDBL_8B (0x1 << 5) | ||
| 162 | #define RXCR2_SRDBL_16B (0x2 << 5) | ||
| 163 | #define RXCR2_SRDBL_32B (0x3 << 5) | ||
| 164 | /* #define RXCR2_SRDBL_FRAME (0x4 << 5) */ | ||
| 165 | #define RXCR2_IUFFP (1 << 4) | ||
| 166 | #define RXCR2_RXIUFCEZ (1 << 3) | ||
| 167 | #define RXCR2_UDPLFE (1 << 2) | ||
| 168 | #define RXCR2_RXICMPFCC (1 << 1) | ||
| 169 | #define RXCR2_RXSAF (1 << 0) | ||
| 170 | |||
| 171 | #define KS_TXMIR 0x78 | ||
| 172 | |||
| 173 | #define KS_RXFHSR 0x7C | ||
| 174 | #define RXFSHR_RXFV (1 << 15) | ||
| 175 | #define RXFSHR_RXICMPFCS (1 << 13) | ||
| 176 | #define RXFSHR_RXIPFCS (1 << 12) | ||
| 177 | #define RXFSHR_RXTCPFCS (1 << 11) | ||
| 178 | #define RXFSHR_RXUDPFCS (1 << 10) | ||
| 179 | #define RXFSHR_RXBF (1 << 7) | ||
| 180 | #define RXFSHR_RXMF (1 << 6) | ||
| 181 | #define RXFSHR_RXUF (1 << 5) | ||
| 182 | #define RXFSHR_RXMR (1 << 4) | ||
| 183 | #define RXFSHR_RXFT (1 << 3) | ||
| 184 | #define RXFSHR_RXFTL (1 << 2) | ||
| 185 | #define RXFSHR_RXRF (1 << 1) | ||
| 186 | #define RXFSHR_RXCE (1 << 0) | ||
| 187 | #define RXFSHR_ERR (RXFSHR_RXCE | RXFSHR_RXRF |\ | ||
| 188 | RXFSHR_RXFTL | RXFSHR_RXMR |\ | ||
| 189 | RXFSHR_RXICMPFCS | RXFSHR_RXIPFCS |\ | ||
| 190 | RXFSHR_RXTCPFCS) | ||
| 191 | #define KS_RXFHBCR 0x7E | ||
| 192 | #define RXFHBCR_CNT_MASK 0x0FFF | ||
| 193 | |||
| 194 | #define KS_TXQCR 0x80 | ||
| 195 | #define TXQCR_AETFE (1 << 2) | ||
| 196 | #define TXQCR_TXQMAM (1 << 1) | ||
| 197 | #define TXQCR_METFE (1 << 0) | ||
| 198 | |||
| 199 | #define KS_RXQCR 0x82 | ||
| 200 | #define RXQCR_RXDTTS (1 << 12) | ||
| 201 | #define RXQCR_RXDBCTS (1 << 11) | ||
| 202 | #define RXQCR_RXFCTS (1 << 10) | ||
| 203 | #define RXQCR_RXIPHTOE (1 << 9) | ||
| 204 | #define RXQCR_RXDTTE (1 << 7) | ||
| 205 | #define RXQCR_RXDBCTE (1 << 6) | ||
| 206 | #define RXQCR_RXFCTE (1 << 5) | ||
| 207 | #define RXQCR_ADRFE (1 << 4) | ||
| 208 | #define RXQCR_SDA (1 << 3) | ||
| 209 | #define RXQCR_RRXEF (1 << 0) | ||
| 210 | #define RXQCR_CMD_CNTL (RXQCR_RXFCTE|RXQCR_ADRFE) | 55 | #define RXQCR_CMD_CNTL (RXQCR_RXFCTE|RXQCR_ADRFE) |
| 211 | 56 | ||
| 212 | #define KS_TXFDPR 0x84 | ||
| 213 | #define TXFDPR_TXFPAI (1 << 14) | ||
| 214 | #define TXFDPR_TXFP_MASK (0x7ff << 0) | ||
| 215 | #define TXFDPR_TXFP_SHIFT (0) | ||
| 216 | |||
| 217 | #define KS_RXFDPR 0x86 | ||
| 218 | #define RXFDPR_RXFPAI (1 << 14) | ||
| 219 | |||
| 220 | #define KS_RXDTTR 0x8C | ||
| 221 | #define KS_RXDBCTR 0x8E | ||
| 222 | |||
| 223 | #define KS_IER 0x90 | ||
| 224 | #define KS_ISR 0x92 | ||
| 225 | #define IRQ_LCI (1 << 15) | ||
| 226 | #define IRQ_TXI (1 << 14) | ||
| 227 | #define IRQ_RXI (1 << 13) | ||
| 228 | #define IRQ_RXOI (1 << 11) | ||
| 229 | #define IRQ_TXPSI (1 << 9) | ||
| 230 | #define IRQ_RXPSI (1 << 8) | ||
| 231 | #define IRQ_TXSAI (1 << 6) | ||
| 232 | #define IRQ_RXWFDI (1 << 5) | ||
| 233 | #define IRQ_RXMPDI (1 << 4) | ||
| 234 | #define IRQ_LDI (1 << 3) | ||
| 235 | #define IRQ_EDI (1 << 2) | ||
| 236 | #define IRQ_SPIBEI (1 << 1) | ||
| 237 | #define IRQ_DEDI (1 << 0) | ||
| 238 | |||
| 239 | #define KS_RXFCTR 0x9C | ||
| 240 | #define RXFCTR_THRESHOLD_MASK 0x00FF | ||
| 241 | |||
| 242 | #define KS_RXFC 0x9D | ||
| 243 | #define RXFCTR_RXFC_MASK (0xff << 8) | ||
| 244 | #define RXFCTR_RXFC_SHIFT (8) | ||
| 245 | #define RXFCTR_RXFC_GET(_v) (((_v) >> 8) & 0xff) | ||
| 246 | #define RXFCTR_RXFCT_MASK (0xff << 0) | ||
| 247 | #define RXFCTR_RXFCT_SHIFT (0) | ||
| 248 | |||
| 249 | #define KS_TXNTFSR 0x9E | ||
| 250 | |||
| 251 | #define KS_MAHTR0 0xA0 | ||
| 252 | #define KS_MAHTR1 0xA2 | ||
| 253 | #define KS_MAHTR2 0xA4 | ||
| 254 | #define KS_MAHTR3 0xA6 | ||
| 255 | |||
| 256 | #define KS_FCLWR 0xB0 | ||
| 257 | #define KS_FCHWR 0xB2 | ||
| 258 | #define KS_FCOWR 0xB4 | ||
| 259 | |||
| 260 | #define KS_CIDER 0xC0 | ||
| 261 | #define CIDER_ID 0x8870 | ||
| 262 | #define CIDER_REV_MASK (0x7 << 1) | ||
| 263 | #define CIDER_REV_SHIFT (1) | ||
| 264 | #define CIDER_REV_GET(_v) (((_v) >> 1) & 0x7) | ||
| 265 | |||
| 266 | #define KS_CGCR 0xC6 | ||
| 267 | #define KS_IACR 0xC8 | ||
| 268 | #define IACR_RDEN (1 << 12) | ||
| 269 | #define IACR_TSEL_MASK (0x3 << 10) | ||
| 270 | #define IACR_TSEL_SHIFT (10) | ||
| 271 | #define IACR_TSEL_MIB (0x3 << 10) | ||
| 272 | #define IACR_ADDR_MASK (0x1f << 0) | ||
| 273 | #define IACR_ADDR_SHIFT (0) | ||
| 274 | |||
| 275 | #define KS_IADLR 0xD0 | ||
| 276 | #define KS_IAHDR 0xD2 | ||
| 277 | |||
| 278 | #define KS_PMECR 0xD4 | ||
| 279 | #define PMECR_PME_DELAY (1 << 14) | ||
| 280 | #define PMECR_PME_POL (1 << 12) | ||
| 281 | #define PMECR_WOL_WAKEUP (1 << 11) | ||
| 282 | #define PMECR_WOL_MAGICPKT (1 << 10) | ||
| 283 | #define PMECR_WOL_LINKUP (1 << 9) | ||
| 284 | #define PMECR_WOL_ENERGY (1 << 8) | ||
| 285 | #define PMECR_AUTO_WAKE_EN (1 << 7) | ||
| 286 | #define PMECR_WAKEUP_NORMAL (1 << 6) | ||
| 287 | #define PMECR_WKEVT_MASK (0xf << 2) | ||
| 288 | #define PMECR_WKEVT_SHIFT (2) | ||
| 289 | #define PMECR_WKEVT_GET(_v) (((_v) >> 2) & 0xf) | ||
| 290 | #define PMECR_WKEVT_ENERGY (0x1 << 2) | ||
| 291 | #define PMECR_WKEVT_LINK (0x2 << 2) | ||
| 292 | #define PMECR_WKEVT_MAGICPKT (0x4 << 2) | ||
| 293 | #define PMECR_WKEVT_FRAME (0x8 << 2) | ||
| 294 | #define PMECR_PM_MASK (0x3 << 0) | ||
| 295 | #define PMECR_PM_SHIFT (0) | ||
| 296 | #define PMECR_PM_NORMAL (0x0 << 0) | ||
| 297 | #define PMECR_PM_ENERGY (0x1 << 0) | ||
| 298 | #define PMECR_PM_SOFTDOWN (0x2 << 0) | ||
| 299 | #define PMECR_PM_POWERSAVE (0x3 << 0) | ||
| 300 | |||
| 301 | /* Standard MII PHY data */ | ||
| 302 | #define KS_P1MBCR 0xE4 | ||
| 303 | #define P1MBCR_FORCE_FDX (1 << 8) | ||
| 304 | |||
| 305 | #define KS_P1MBSR 0xE6 | ||
| 306 | #define P1MBSR_AN_COMPLETE (1 << 5) | ||
| 307 | #define P1MBSR_AN_CAPABLE (1 << 3) | ||
| 308 | #define P1MBSR_LINK_UP (1 << 2) | ||
| 309 | |||
| 310 | #define KS_PHY1ILR 0xE8 | ||
| 311 | #define KS_PHY1IHR 0xEA | ||
| 312 | #define KS_P1ANAR 0xEC | ||
| 313 | #define KS_P1ANLPR 0xEE | ||
| 314 | |||
| 315 | #define KS_P1SCLMD 0xF4 | ||
| 316 | #define P1SCLMD_LEDOFF (1 << 15) | ||
| 317 | #define P1SCLMD_TXIDS (1 << 14) | ||
| 318 | #define P1SCLMD_RESTARTAN (1 << 13) | ||
| 319 | #define P1SCLMD_DISAUTOMDIX (1 << 10) | ||
| 320 | #define P1SCLMD_FORCEMDIX (1 << 9) | ||
| 321 | #define P1SCLMD_AUTONEGEN (1 << 7) | ||
| 322 | #define P1SCLMD_FORCE100 (1 << 6) | ||
| 323 | #define P1SCLMD_FORCEFDX (1 << 5) | ||
| 324 | #define P1SCLMD_ADV_FLOW (1 << 4) | ||
| 325 | #define P1SCLMD_ADV_100BT_FDX (1 << 3) | ||
| 326 | #define P1SCLMD_ADV_100BT_HDX (1 << 2) | ||
| 327 | #define P1SCLMD_ADV_10BT_FDX (1 << 1) | ||
| 328 | #define P1SCLMD_ADV_10BT_HDX (1 << 0) | ||
| 329 | |||
| 330 | #define KS_P1CR 0xF6 | ||
| 331 | #define P1CR_HP_MDIX (1 << 15) | ||
| 332 | #define P1CR_REV_POL (1 << 13) | ||
| 333 | #define P1CR_OP_100M (1 << 10) | ||
| 334 | #define P1CR_OP_FDX (1 << 9) | ||
| 335 | #define P1CR_OP_MDI (1 << 7) | ||
| 336 | #define P1CR_AN_DONE (1 << 6) | ||
| 337 | #define P1CR_LINK_GOOD (1 << 5) | ||
| 338 | #define P1CR_PNTR_FLOW (1 << 4) | ||
| 339 | #define P1CR_PNTR_100BT_FDX (1 << 3) | ||
| 340 | #define P1CR_PNTR_100BT_HDX (1 << 2) | ||
| 341 | #define P1CR_PNTR_10BT_FDX (1 << 1) | ||
| 342 | #define P1CR_PNTR_10BT_HDX (1 << 0) | ||
| 343 | |||
| 344 | /* TX Frame control */ | ||
| 345 | |||
| 346 | #define TXFR_TXIC (1 << 15) | ||
| 347 | #define TXFR_TXFID_MASK (0x3f << 0) | ||
| 348 | #define TXFR_TXFID_SHIFT (0) | ||
| 349 | |||
| 350 | #define KS_P1SR 0xF8 | ||
| 351 | #define P1SR_HP_MDIX (1 << 15) | ||
| 352 | #define P1SR_REV_POL (1 << 13) | ||
| 353 | #define P1SR_OP_100M (1 << 10) | ||
| 354 | #define P1SR_OP_FDX (1 << 9) | ||
| 355 | #define P1SR_OP_MDI (1 << 7) | ||
| 356 | #define P1SR_AN_DONE (1 << 6) | ||
| 357 | #define P1SR_LINK_GOOD (1 << 5) | ||
| 358 | #define P1SR_PNTR_FLOW (1 << 4) | ||
| 359 | #define P1SR_PNTR_100BT_FDX (1 << 3) | ||
| 360 | #define P1SR_PNTR_100BT_HDX (1 << 2) | ||
| 361 | #define P1SR_PNTR_10BT_FDX (1 << 1) | ||
| 362 | #define P1SR_PNTR_10BT_HDX (1 << 0) | ||
| 363 | |||
| 364 | #define ENUM_BUS_NONE 0 | 57 | #define ENUM_BUS_NONE 0 |
| 365 | #define ENUM_BUS_8BIT 1 | 58 | #define ENUM_BUS_8BIT 1 |
| 366 | #define ENUM_BUS_16BIT 2 | 59 | #define ENUM_BUS_16BIT 2 |
| @@ -1475,7 +1168,7 @@ static void ks_setup(struct ks_net *ks) | |||
| 1475 | ks_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI); | 1168 | ks_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI); |
| 1476 | 1169 | ||
| 1477 | /* Setup Receive Frame Threshold - 1 frame (RXFCTFC) */ | 1170 | /* Setup Receive Frame Threshold - 1 frame (RXFCTFC) */ |
| 1478 | ks_wrreg16(ks, KS_RXFCTR, 1 & RXFCTR_THRESHOLD_MASK); | 1171 | ks_wrreg16(ks, KS_RXFCTR, 1 & RXFCTR_RXFCT_MASK); |
| 1479 | 1172 | ||
| 1480 | /* Setup RxQ Command Control (RXQCR) */ | 1173 | /* Setup RxQ Command Control (RXQCR) */ |
| 1481 | ks->rc_rxqcr = RXQCR_CMD_CNTL; | 1174 | ks->rc_rxqcr = RXQCR_CMD_CNTL; |
| @@ -1488,7 +1181,7 @@ static void ks_setup(struct ks_net *ks) | |||
| 1488 | */ | 1181 | */ |
| 1489 | 1182 | ||
| 1490 | w = ks_rdreg16(ks, KS_P1MBCR); | 1183 | w = ks_rdreg16(ks, KS_P1MBCR); |
| 1491 | w &= ~P1MBCR_FORCE_FDX; | 1184 | w &= ~BMCR_FULLDPLX; |
| 1492 | ks_wrreg16(ks, KS_P1MBCR, w); | 1185 | ks_wrreg16(ks, KS_P1MBCR, w); |
| 1493 | 1186 | ||
| 1494 | w = TXCR_TXFCE | TXCR_TXPE | TXCR_TXCRC | TXCR_TCGIP; | 1187 | w = TXCR_TXFCE | TXCR_TXPE | TXCR_TXCRC | TXCR_TCGIP; |
| @@ -1629,7 +1322,7 @@ static int ks8851_probe(struct platform_device *pdev) | |||
| 1629 | ks_setup_int(ks); | 1322 | ks_setup_int(ks); |
| 1630 | 1323 | ||
| 1631 | data = ks_rdreg16(ks, KS_OBCR); | 1324 | data = ks_rdreg16(ks, KS_OBCR); |
| 1632 | ks_wrreg16(ks, KS_OBCR, data | OBCR_ODS_16MA); | 1325 | ks_wrreg16(ks, KS_OBCR, data | OBCR_ODS_16mA); |
| 1633 | 1326 | ||
| 1634 | /* overwriting the default MAC address */ | 1327 | /* overwriting the default MAC address */ |
| 1635 | if (pdev->dev.of_node) { | 1328 | if (pdev->dev.of_node) { |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 3b0adda7cc9c..a4cd6f2cfb86 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | |||
| @@ -1048,6 +1048,8 @@ int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) | |||
| 1048 | 1048 | ||
| 1049 | for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) { | 1049 | for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) { |
| 1050 | skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE); | 1050 | skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE); |
| 1051 | if (!skb) | ||
| 1052 | break; | ||
| 1051 | qlcnic_create_loopback_buff(skb->data, adapter->mac_addr); | 1053 | qlcnic_create_loopback_buff(skb->data, adapter->mac_addr); |
| 1052 | skb_put(skb, QLCNIC_ILB_PKT_SIZE); | 1054 | skb_put(skb, QLCNIC_ILB_PKT_SIZE); |
| 1053 | adapter->ahw->diag_cnt = 0; | 1055 | adapter->ahw->diag_cnt = 0; |
diff --git a/drivers/net/ethernet/realtek/atp.c b/drivers/net/ethernet/realtek/atp.c index cfb67b746595..58e0ca9093d3 100644 --- a/drivers/net/ethernet/realtek/atp.c +++ b/drivers/net/ethernet/realtek/atp.c | |||
| @@ -482,7 +482,7 @@ static void hardware_init(struct net_device *dev) | |||
| 482 | write_reg_high(ioaddr, IMR, ISRh_RxErr); | 482 | write_reg_high(ioaddr, IMR, ISRh_RxErr); |
| 483 | 483 | ||
| 484 | lp->tx_unit_busy = 0; | 484 | lp->tx_unit_busy = 0; |
| 485 | lp->pac_cnt_in_tx_buf = 0; | 485 | lp->pac_cnt_in_tx_buf = 0; |
| 486 | lp->saved_tx_size = 0; | 486 | lp->saved_tx_size = 0; |
| 487 | } | 487 | } |
| 488 | 488 | ||
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index c29dde064078..7562ccbbb39a 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c | |||
| @@ -678,6 +678,7 @@ struct rtl8169_private { | |||
| 678 | struct work_struct work; | 678 | struct work_struct work; |
| 679 | } wk; | 679 | } wk; |
| 680 | 680 | ||
| 681 | unsigned irq_enabled:1; | ||
| 681 | unsigned supports_gmii:1; | 682 | unsigned supports_gmii:1; |
| 682 | dma_addr_t counters_phys_addr; | 683 | dma_addr_t counters_phys_addr; |
| 683 | struct rtl8169_counters *counters; | 684 | struct rtl8169_counters *counters; |
| @@ -1293,6 +1294,7 @@ static void rtl_ack_events(struct rtl8169_private *tp, u16 bits) | |||
| 1293 | static void rtl_irq_disable(struct rtl8169_private *tp) | 1294 | static void rtl_irq_disable(struct rtl8169_private *tp) |
| 1294 | { | 1295 | { |
| 1295 | RTL_W16(tp, IntrMask, 0); | 1296 | RTL_W16(tp, IntrMask, 0); |
| 1297 | tp->irq_enabled = 0; | ||
| 1296 | } | 1298 | } |
| 1297 | 1299 | ||
| 1298 | #define RTL_EVENT_NAPI_RX (RxOK | RxErr) | 1300 | #define RTL_EVENT_NAPI_RX (RxOK | RxErr) |
| @@ -1301,6 +1303,7 @@ static void rtl_irq_disable(struct rtl8169_private *tp) | |||
| 1301 | 1303 | ||
| 1302 | static void rtl_irq_enable(struct rtl8169_private *tp) | 1304 | static void rtl_irq_enable(struct rtl8169_private *tp) |
| 1303 | { | 1305 | { |
| 1306 | tp->irq_enabled = 1; | ||
| 1304 | RTL_W16(tp, IntrMask, tp->irq_mask); | 1307 | RTL_W16(tp, IntrMask, tp->irq_mask); |
| 1305 | } | 1308 | } |
| 1306 | 1309 | ||
| @@ -6520,9 +6523,8 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) | |||
| 6520 | { | 6523 | { |
| 6521 | struct rtl8169_private *tp = dev_instance; | 6524 | struct rtl8169_private *tp = dev_instance; |
| 6522 | u16 status = RTL_R16(tp, IntrStatus); | 6525 | u16 status = RTL_R16(tp, IntrStatus); |
| 6523 | u16 irq_mask = RTL_R16(tp, IntrMask); | ||
| 6524 | 6526 | ||
| 6525 | if (status == 0xffff || !(status & irq_mask)) | 6527 | if (!tp->irq_enabled || status == 0xffff || !(status & tp->irq_mask)) |
| 6526 | return IRQ_NONE; | 6528 | return IRQ_NONE; |
| 6527 | 6529 | ||
| 6528 | if (unlikely(status & SYSErr)) { | 6530 | if (unlikely(status & SYSErr)) { |
| @@ -6540,7 +6542,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) | |||
| 6540 | set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags); | 6542 | set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags); |
| 6541 | } | 6543 | } |
| 6542 | 6544 | ||
| 6543 | if (status & RTL_EVENT_NAPI) { | 6545 | if (status & (RTL_EVENT_NAPI | LinkChg)) { |
| 6544 | rtl_irq_disable(tp); | 6546 | rtl_irq_disable(tp); |
| 6545 | napi_schedule_irqoff(&tp->napi); | 6547 | napi_schedule_irqoff(&tp->napi); |
| 6546 | } | 6548 | } |
diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index 6073387511f8..67f9bb6e941b 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c | |||
| @@ -730,10 +730,10 @@ static u16 sis900_default_phy(struct net_device * net_dev) | |||
| 730 | status = mdio_read(net_dev, phy->phy_addr, MII_STATUS); | 730 | status = mdio_read(net_dev, phy->phy_addr, MII_STATUS); |
| 731 | 731 | ||
| 732 | /* Link ON & Not select default PHY & not ghost PHY */ | 732 | /* Link ON & Not select default PHY & not ghost PHY */ |
| 733 | if ((status & MII_STAT_LINK) && !default_phy && | 733 | if ((status & MII_STAT_LINK) && !default_phy && |
| 734 | (phy->phy_types != UNKNOWN)) | 734 | (phy->phy_types != UNKNOWN)) { |
| 735 | default_phy = phy; | 735 | default_phy = phy; |
| 736 | else { | 736 | } else { |
| 737 | status = mdio_read(net_dev, phy->phy_addr, MII_CONTROL); | 737 | status = mdio_read(net_dev, phy->phy_addr, MII_CONTROL); |
| 738 | mdio_write(net_dev, phy->phy_addr, MII_CONTROL, | 738 | mdio_write(net_dev, phy->phy_addr, MII_CONTROL, |
| 739 | status | MII_CNTL_AUTO | MII_CNTL_ISOLATE); | 739 | status | MII_CNTL_AUTO | MII_CNTL_ISOLATE); |
| @@ -741,7 +741,7 @@ static u16 sis900_default_phy(struct net_device * net_dev) | |||
| 741 | phy_home = phy; | 741 | phy_home = phy; |
| 742 | else if(phy->phy_types == LAN) | 742 | else if(phy->phy_types == LAN) |
| 743 | phy_lan = phy; | 743 | phy_lan = phy; |
| 744 | } | 744 | } |
| 745 | } | 745 | } |
| 746 | 746 | ||
| 747 | if (!default_phy && phy_home) | 747 | if (!default_phy && phy_home) |
diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c index d8c5bc412219..4d9bcb4d0378 100644 --- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c +++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c | |||
| @@ -59,7 +59,7 @@ static int jumbo_frm(void *p, struct sk_buff *skb, int csum) | |||
| 59 | 59 | ||
| 60 | desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB); | 60 | desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB); |
| 61 | stmmac_prepare_tx_desc(priv, desc, 1, bmax, csum, | 61 | stmmac_prepare_tx_desc(priv, desc, 1, bmax, csum, |
| 62 | STMMAC_RING_MODE, 1, false, skb->len); | 62 | STMMAC_RING_MODE, 0, false, skb->len); |
| 63 | tx_q->tx_skbuff[entry] = NULL; | 63 | tx_q->tx_skbuff[entry] = NULL; |
| 64 | entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); | 64 | entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); |
| 65 | 65 | ||
| @@ -79,7 +79,8 @@ static int jumbo_frm(void *p, struct sk_buff *skb, int csum) | |||
| 79 | 79 | ||
| 80 | desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB); | 80 | desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB); |
| 81 | stmmac_prepare_tx_desc(priv, desc, 0, len, csum, | 81 | stmmac_prepare_tx_desc(priv, desc, 0, len, csum, |
| 82 | STMMAC_RING_MODE, 1, true, skb->len); | 82 | STMMAC_RING_MODE, 1, !skb_is_nonlinear(skb), |
| 83 | skb->len); | ||
| 83 | } else { | 84 | } else { |
| 84 | des2 = dma_map_single(priv->device, skb->data, | 85 | des2 = dma_map_single(priv->device, skb->data, |
| 85 | nopaged_len, DMA_TO_DEVICE); | 86 | nopaged_len, DMA_TO_DEVICE); |
| @@ -91,7 +92,8 @@ static int jumbo_frm(void *p, struct sk_buff *skb, int csum) | |||
| 91 | tx_q->tx_skbuff_dma[entry].is_jumbo = true; | 92 | tx_q->tx_skbuff_dma[entry].is_jumbo = true; |
| 92 | desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB); | 93 | desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB); |
| 93 | stmmac_prepare_tx_desc(priv, desc, 1, nopaged_len, csum, | 94 | stmmac_prepare_tx_desc(priv, desc, 1, nopaged_len, csum, |
| 94 | STMMAC_RING_MODE, 1, true, skb->len); | 95 | STMMAC_RING_MODE, 0, !skb_is_nonlinear(skb), |
| 96 | skb->len); | ||
| 95 | } | 97 | } |
| 96 | 98 | ||
| 97 | tx_q->cur_tx = entry; | 99 | tx_q->cur_tx = entry; |
| @@ -111,10 +113,11 @@ static unsigned int is_jumbo_frm(int len, int enh_desc) | |||
| 111 | 113 | ||
| 112 | static void refill_desc3(void *priv_ptr, struct dma_desc *p) | 114 | static void refill_desc3(void *priv_ptr, struct dma_desc *p) |
| 113 | { | 115 | { |
| 114 | struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr; | 116 | struct stmmac_rx_queue *rx_q = priv_ptr; |
| 117 | struct stmmac_priv *priv = rx_q->priv_data; | ||
| 115 | 118 | ||
| 116 | /* Fill DES3 in case of RING mode */ | 119 | /* Fill DES3 in case of RING mode */ |
| 117 | if (priv->dma_buf_sz >= BUF_SIZE_8KiB) | 120 | if (priv->dma_buf_sz == BUF_SIZE_16KiB) |
| 118 | p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + BUF_SIZE_8KiB); | 121 | p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + BUF_SIZE_8KiB); |
| 119 | } | 122 | } |
| 120 | 123 | ||
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 97c5e1aad88f..6a2e1031a62a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | |||
| @@ -3216,14 +3216,16 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 3216 | stmmac_prepare_tx_desc(priv, first, 1, nopaged_len, | 3216 | stmmac_prepare_tx_desc(priv, first, 1, nopaged_len, |
| 3217 | csum_insertion, priv->mode, 1, last_segment, | 3217 | csum_insertion, priv->mode, 1, last_segment, |
| 3218 | skb->len); | 3218 | skb->len); |
| 3219 | 3219 | } else { | |
| 3220 | /* The own bit must be the latest setting done when prepare the | 3220 | stmmac_set_tx_owner(priv, first); |
| 3221 | * descriptor and then barrier is needed to make sure that | ||
| 3222 | * all is coherent before granting the DMA engine. | ||
| 3223 | */ | ||
| 3224 | wmb(); | ||
| 3225 | } | 3221 | } |
| 3226 | 3222 | ||
| 3223 | /* The own bit must be the latest setting done when prepare the | ||
| 3224 | * descriptor and then barrier is needed to make sure that | ||
| 3225 | * all is coherent before granting the DMA engine. | ||
| 3226 | */ | ||
| 3227 | wmb(); | ||
| 3228 | |||
| 3227 | netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len); | 3229 | netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len); |
| 3228 | 3230 | ||
| 3229 | stmmac_enable_dma_transmission(priv, priv->ioaddr); | 3231 | stmmac_enable_dma_transmission(priv, priv->ioaddr); |
diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 5174d318901e..0a920c5936b2 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c | |||
| @@ -3657,12 +3657,16 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, | |||
| 3657 | 3657 | ||
| 3658 | ret = netcp_txpipe_init(&gbe_dev->tx_pipe, netcp_device, | 3658 | ret = netcp_txpipe_init(&gbe_dev->tx_pipe, netcp_device, |
| 3659 | gbe_dev->dma_chan_name, gbe_dev->tx_queue_id); | 3659 | gbe_dev->dma_chan_name, gbe_dev->tx_queue_id); |
| 3660 | if (ret) | 3660 | if (ret) { |
| 3661 | of_node_put(interfaces); | ||
| 3661 | return ret; | 3662 | return ret; |
| 3663 | } | ||
| 3662 | 3664 | ||
| 3663 | ret = netcp_txpipe_open(&gbe_dev->tx_pipe); | 3665 | ret = netcp_txpipe_open(&gbe_dev->tx_pipe); |
| 3664 | if (ret) | 3666 | if (ret) { |
| 3667 | of_node_put(interfaces); | ||
| 3665 | return ret; | 3668 | return ret; |
| 3669 | } | ||
| 3666 | 3670 | ||
| 3667 | /* Create network interfaces */ | 3671 | /* Create network interfaces */ |
| 3668 | INIT_LIST_HEAD(&gbe_dev->gbe_intf_head); | 3672 | INIT_LIST_HEAD(&gbe_dev->gbe_intf_head); |
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index ec7e7ec24ff9..4041c75997ba 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c | |||
| @@ -1575,12 +1575,14 @@ static int axienet_probe(struct platform_device *pdev) | |||
| 1575 | ret = of_address_to_resource(np, 0, &dmares); | 1575 | ret = of_address_to_resource(np, 0, &dmares); |
| 1576 | if (ret) { | 1576 | if (ret) { |
| 1577 | dev_err(&pdev->dev, "unable to get DMA resource\n"); | 1577 | dev_err(&pdev->dev, "unable to get DMA resource\n"); |
| 1578 | of_node_put(np); | ||
| 1578 | goto free_netdev; | 1579 | goto free_netdev; |
| 1579 | } | 1580 | } |
| 1580 | lp->dma_regs = devm_ioremap_resource(&pdev->dev, &dmares); | 1581 | lp->dma_regs = devm_ioremap_resource(&pdev->dev, &dmares); |
| 1581 | if (IS_ERR(lp->dma_regs)) { | 1582 | if (IS_ERR(lp->dma_regs)) { |
| 1582 | dev_err(&pdev->dev, "could not map DMA regs\n"); | 1583 | dev_err(&pdev->dev, "could not map DMA regs\n"); |
| 1583 | ret = PTR_ERR(lp->dma_regs); | 1584 | ret = PTR_ERR(lp->dma_regs); |
| 1585 | of_node_put(np); | ||
| 1584 | goto free_netdev; | 1586 | goto free_netdev; |
| 1585 | } | 1587 | } |
| 1586 | lp->rx_irq = irq_of_parse_and_map(np, 1); | 1588 | lp->rx_irq = irq_of_parse_and_map(np, 1); |
diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c index cd1d8faccca5..cd6b95e673a5 100644 --- a/drivers/net/ieee802154/adf7242.c +++ b/drivers/net/ieee802154/adf7242.c | |||
| @@ -1268,6 +1268,10 @@ static int adf7242_probe(struct spi_device *spi) | |||
| 1268 | INIT_DELAYED_WORK(&lp->work, adf7242_rx_cal_work); | 1268 | INIT_DELAYED_WORK(&lp->work, adf7242_rx_cal_work); |
| 1269 | lp->wqueue = alloc_ordered_workqueue(dev_name(&spi->dev), | 1269 | lp->wqueue = alloc_ordered_workqueue(dev_name(&spi->dev), |
| 1270 | WQ_MEM_RECLAIM); | 1270 | WQ_MEM_RECLAIM); |
| 1271 | if (unlikely(!lp->wqueue)) { | ||
| 1272 | ret = -ENOMEM; | ||
| 1273 | goto err_hw_init; | ||
| 1274 | } | ||
| 1271 | 1275 | ||
| 1272 | ret = adf7242_hw_init(lp); | 1276 | ret = adf7242_hw_init(lp); |
| 1273 | if (ret) | 1277 | if (ret) |
diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c index b6743f03dce0..3b88846de31b 100644 --- a/drivers/net/ieee802154/mac802154_hwsim.c +++ b/drivers/net/ieee802154/mac802154_hwsim.c | |||
| @@ -324,7 +324,7 @@ static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info) | |||
| 324 | goto out_err; | 324 | goto out_err; |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | genlmsg_reply(skb, info); | 327 | res = genlmsg_reply(skb, info); |
| 328 | break; | 328 | break; |
| 329 | } | 329 | } |
| 330 | 330 | ||
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 071869db44cf..520657945b82 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig | |||
| @@ -7,6 +7,8 @@ menuconfig MDIO_DEVICE | |||
| 7 | help | 7 | help |
| 8 | MDIO devices and driver infrastructure code. | 8 | MDIO devices and driver infrastructure code. |
| 9 | 9 | ||
| 10 | if MDIO_DEVICE | ||
| 11 | |||
| 10 | config MDIO_BUS | 12 | config MDIO_BUS |
| 11 | tristate | 13 | tristate |
| 12 | default m if PHYLIB=m | 14 | default m if PHYLIB=m |
| @@ -179,6 +181,7 @@ config MDIO_XGENE | |||
| 179 | APM X-Gene SoC's. | 181 | APM X-Gene SoC's. |
| 180 | 182 | ||
| 181 | endif | 183 | endif |
| 184 | endif | ||
| 182 | 185 | ||
| 183 | config PHYLINK | 186 | config PHYLINK |
| 184 | tristate | 187 | tristate |
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 9605d4fe540b..cb86a3e90c7d 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c | |||
| @@ -323,6 +323,19 @@ static int bcm54xx_config_init(struct phy_device *phydev) | |||
| 323 | 323 | ||
| 324 | bcm54xx_phydsp_config(phydev); | 324 | bcm54xx_phydsp_config(phydev); |
| 325 | 325 | ||
| 326 | /* Encode link speed into LED1 and LED3 pair (green/amber). | ||
| 327 | * Also flash these two LEDs on activity. This means configuring | ||
| 328 | * them for MULTICOLOR and encoding link/activity into them. | ||
| 329 | */ | ||
| 330 | val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) | | ||
| 331 | BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1); | ||
| 332 | bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val); | ||
| 333 | |||
| 334 | val = BCM_LED_MULTICOLOR_IN_PHASE | | ||
| 335 | BCM5482_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) | | ||
| 336 | BCM5482_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT); | ||
| 337 | bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val); | ||
| 338 | |||
| 326 | return 0; | 339 | return 0; |
| 327 | } | 340 | } |
| 328 | 341 | ||
diff --git a/drivers/net/phy/dp83822.c b/drivers/net/phy/dp83822.c index bbd8c22067f3..97d45bd5b38e 100644 --- a/drivers/net/phy/dp83822.c +++ b/drivers/net/phy/dp83822.c | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
| 16 | 16 | ||
| 17 | #define DP83822_PHY_ID 0x2000a240 | 17 | #define DP83822_PHY_ID 0x2000a240 |
| 18 | #define DP83825I_PHY_ID 0x2000a150 | ||
| 19 | |||
| 18 | #define DP83822_DEVADDR 0x1f | 20 | #define DP83822_DEVADDR 0x1f |
| 19 | 21 | ||
| 20 | #define MII_DP83822_PHYSCR 0x11 | 22 | #define MII_DP83822_PHYSCR 0x11 |
| @@ -304,26 +306,30 @@ static int dp83822_resume(struct phy_device *phydev) | |||
| 304 | return 0; | 306 | return 0; |
| 305 | } | 307 | } |
| 306 | 308 | ||
| 309 | #define DP83822_PHY_DRIVER(_id, _name) \ | ||
| 310 | { \ | ||
| 311 | PHY_ID_MATCH_MODEL(_id), \ | ||
| 312 | .name = (_name), \ | ||
| 313 | .features = PHY_BASIC_FEATURES, \ | ||
| 314 | .soft_reset = dp83822_phy_reset, \ | ||
| 315 | .config_init = dp83822_config_init, \ | ||
| 316 | .get_wol = dp83822_get_wol, \ | ||
| 317 | .set_wol = dp83822_set_wol, \ | ||
| 318 | .ack_interrupt = dp83822_ack_interrupt, \ | ||
| 319 | .config_intr = dp83822_config_intr, \ | ||
| 320 | .suspend = dp83822_suspend, \ | ||
| 321 | .resume = dp83822_resume, \ | ||
| 322 | } | ||
| 323 | |||
| 307 | static struct phy_driver dp83822_driver[] = { | 324 | static struct phy_driver dp83822_driver[] = { |
| 308 | { | 325 | DP83822_PHY_DRIVER(DP83822_PHY_ID, "TI DP83822"), |
| 309 | .phy_id = DP83822_PHY_ID, | 326 | DP83822_PHY_DRIVER(DP83825I_PHY_ID, "TI DP83825I"), |
| 310 | .phy_id_mask = 0xfffffff0, | ||
| 311 | .name = "TI DP83822", | ||
| 312 | .features = PHY_BASIC_FEATURES, | ||
| 313 | .config_init = dp83822_config_init, | ||
| 314 | .soft_reset = dp83822_phy_reset, | ||
| 315 | .get_wol = dp83822_get_wol, | ||
| 316 | .set_wol = dp83822_set_wol, | ||
| 317 | .ack_interrupt = dp83822_ack_interrupt, | ||
| 318 | .config_intr = dp83822_config_intr, | ||
| 319 | .suspend = dp83822_suspend, | ||
| 320 | .resume = dp83822_resume, | ||
| 321 | }, | ||
| 322 | }; | 327 | }; |
| 323 | module_phy_driver(dp83822_driver); | 328 | module_phy_driver(dp83822_driver); |
| 324 | 329 | ||
| 325 | static struct mdio_device_id __maybe_unused dp83822_tbl[] = { | 330 | static struct mdio_device_id __maybe_unused dp83822_tbl[] = { |
| 326 | { DP83822_PHY_ID, 0xfffffff0 }, | 331 | { DP83822_PHY_ID, 0xfffffff0 }, |
| 332 | { DP83825I_PHY_ID, 0xfffffff0 }, | ||
| 327 | { }, | 333 | { }, |
| 328 | }; | 334 | }; |
| 329 | MODULE_DEVICE_TABLE(mdio, dp83822_tbl); | 335 | MODULE_DEVICE_TABLE(mdio, dp83822_tbl); |
diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c index a238388eb1a5..0eec2913c289 100644 --- a/drivers/net/phy/meson-gxl.c +++ b/drivers/net/phy/meson-gxl.c | |||
| @@ -201,6 +201,7 @@ static int meson_gxl_ack_interrupt(struct phy_device *phydev) | |||
| 201 | static int meson_gxl_config_intr(struct phy_device *phydev) | 201 | static int meson_gxl_config_intr(struct phy_device *phydev) |
| 202 | { | 202 | { |
| 203 | u16 val; | 203 | u16 val; |
| 204 | int ret; | ||
| 204 | 205 | ||
| 205 | if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { | 206 | if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { |
| 206 | val = INTSRC_ANEG_PR | 207 | val = INTSRC_ANEG_PR |
| @@ -213,6 +214,11 @@ static int meson_gxl_config_intr(struct phy_device *phydev) | |||
| 213 | val = 0; | 214 | val = 0; |
| 214 | } | 215 | } |
| 215 | 216 | ||
| 217 | /* Ack any pending IRQ */ | ||
| 218 | ret = meson_gxl_ack_interrupt(phydev); | ||
| 219 | if (ret) | ||
| 220 | return ret; | ||
| 221 | |||
| 216 | return phy_write(phydev, INTSRC_MASK, val); | 222 | return phy_write(phydev, INTSRC_MASK, val); |
| 217 | } | 223 | } |
| 218 | 224 | ||
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 49fdd1ee798e..77068c545de0 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
| @@ -1831,7 +1831,7 @@ int genphy_soft_reset(struct phy_device *phydev) | |||
| 1831 | { | 1831 | { |
| 1832 | int ret; | 1832 | int ret; |
| 1833 | 1833 | ||
| 1834 | ret = phy_write(phydev, MII_BMCR, BMCR_RESET); | 1834 | ret = phy_set_bits(phydev, MII_BMCR, BMCR_RESET); |
| 1835 | if (ret < 0) | 1835 | if (ret < 0) |
| 1836 | return ret; | 1836 | return ret; |
| 1837 | 1837 | ||
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 1d68921723dc..e9ca1c088d0b 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
| @@ -1763,9 +1763,6 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
| 1763 | int skb_xdp = 1; | 1763 | int skb_xdp = 1; |
| 1764 | bool frags = tun_napi_frags_enabled(tfile); | 1764 | bool frags = tun_napi_frags_enabled(tfile); |
| 1765 | 1765 | ||
| 1766 | if (!(tun->dev->flags & IFF_UP)) | ||
| 1767 | return -EIO; | ||
| 1768 | |||
| 1769 | if (!(tun->flags & IFF_NO_PI)) { | 1766 | if (!(tun->flags & IFF_NO_PI)) { |
| 1770 | if (len < sizeof(pi)) | 1767 | if (len < sizeof(pi)) |
| 1771 | return -EINVAL; | 1768 | return -EINVAL; |
| @@ -1867,6 +1864,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
| 1867 | err = skb_copy_datagram_from_iter(skb, 0, from, len); | 1864 | err = skb_copy_datagram_from_iter(skb, 0, from, len); |
| 1868 | 1865 | ||
| 1869 | if (err) { | 1866 | if (err) { |
| 1867 | err = -EFAULT; | ||
| 1868 | drop: | ||
| 1870 | this_cpu_inc(tun->pcpu_stats->rx_dropped); | 1869 | this_cpu_inc(tun->pcpu_stats->rx_dropped); |
| 1871 | kfree_skb(skb); | 1870 | kfree_skb(skb); |
| 1872 | if (frags) { | 1871 | if (frags) { |
| @@ -1874,7 +1873,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
| 1874 | mutex_unlock(&tfile->napi_mutex); | 1873 | mutex_unlock(&tfile->napi_mutex); |
| 1875 | } | 1874 | } |
| 1876 | 1875 | ||
| 1877 | return -EFAULT; | 1876 | return err; |
| 1878 | } | 1877 | } |
| 1879 | } | 1878 | } |
| 1880 | 1879 | ||
| @@ -1958,6 +1957,13 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
| 1958 | !tfile->detached) | 1957 | !tfile->detached) |
| 1959 | rxhash = __skb_get_hash_symmetric(skb); | 1958 | rxhash = __skb_get_hash_symmetric(skb); |
| 1960 | 1959 | ||
| 1960 | rcu_read_lock(); | ||
| 1961 | if (unlikely(!(tun->dev->flags & IFF_UP))) { | ||
| 1962 | err = -EIO; | ||
| 1963 | rcu_read_unlock(); | ||
| 1964 | goto drop; | ||
| 1965 | } | ||
| 1966 | |||
| 1961 | if (frags) { | 1967 | if (frags) { |
| 1962 | /* Exercise flow dissector code path. */ | 1968 | /* Exercise flow dissector code path. */ |
| 1963 | u32 headlen = eth_get_headlen(skb->data, skb_headlen(skb)); | 1969 | u32 headlen = eth_get_headlen(skb->data, skb_headlen(skb)); |
| @@ -1965,6 +1971,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
| 1965 | if (unlikely(headlen > skb_headlen(skb))) { | 1971 | if (unlikely(headlen > skb_headlen(skb))) { |
| 1966 | this_cpu_inc(tun->pcpu_stats->rx_dropped); | 1972 | this_cpu_inc(tun->pcpu_stats->rx_dropped); |
| 1967 | napi_free_frags(&tfile->napi); | 1973 | napi_free_frags(&tfile->napi); |
| 1974 | rcu_read_unlock(); | ||
| 1968 | mutex_unlock(&tfile->napi_mutex); | 1975 | mutex_unlock(&tfile->napi_mutex); |
| 1969 | WARN_ON(1); | 1976 | WARN_ON(1); |
| 1970 | return -ENOMEM; | 1977 | return -ENOMEM; |
| @@ -1992,6 +1999,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
| 1992 | } else { | 1999 | } else { |
| 1993 | netif_rx_ni(skb); | 2000 | netif_rx_ni(skb); |
| 1994 | } | 2001 | } |
| 2002 | rcu_read_unlock(); | ||
| 1995 | 2003 | ||
| 1996 | stats = get_cpu_ptr(tun->pcpu_stats); | 2004 | stats = get_cpu_ptr(tun->pcpu_stats); |
| 1997 | u64_stats_update_begin(&stats->syncp); | 2005 | u64_stats_update_begin(&stats->syncp); |
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c index 820a2fe7d027..aff995be2a31 100644 --- a/drivers/net/usb/aqc111.c +++ b/drivers/net/usb/aqc111.c | |||
| @@ -1301,6 +1301,20 @@ static const struct driver_info trendnet_info = { | |||
| 1301 | .tx_fixup = aqc111_tx_fixup, | 1301 | .tx_fixup = aqc111_tx_fixup, |
| 1302 | }; | 1302 | }; |
| 1303 | 1303 | ||
| 1304 | static const struct driver_info qnap_info = { | ||
| 1305 | .description = "QNAP QNA-UC5G1T USB to 5GbE Adapter", | ||
| 1306 | .bind = aqc111_bind, | ||
| 1307 | .unbind = aqc111_unbind, | ||
| 1308 | .status = aqc111_status, | ||
| 1309 | .link_reset = aqc111_link_reset, | ||
| 1310 | .reset = aqc111_reset, | ||
| 1311 | .stop = aqc111_stop, | ||
| 1312 | .flags = FLAG_ETHER | FLAG_FRAMING_AX | | ||
| 1313 | FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET, | ||
| 1314 | .rx_fixup = aqc111_rx_fixup, | ||
| 1315 | .tx_fixup = aqc111_tx_fixup, | ||
| 1316 | }; | ||
| 1317 | |||
| 1304 | static int aqc111_suspend(struct usb_interface *intf, pm_message_t message) | 1318 | static int aqc111_suspend(struct usb_interface *intf, pm_message_t message) |
| 1305 | { | 1319 | { |
| 1306 | struct usbnet *dev = usb_get_intfdata(intf); | 1320 | struct usbnet *dev = usb_get_intfdata(intf); |
| @@ -1455,6 +1469,7 @@ static const struct usb_device_id products[] = { | |||
| 1455 | {AQC111_USB_ETH_DEV(0x0b95, 0x2790, asix111_info)}, | 1469 | {AQC111_USB_ETH_DEV(0x0b95, 0x2790, asix111_info)}, |
| 1456 | {AQC111_USB_ETH_DEV(0x0b95, 0x2791, asix112_info)}, | 1470 | {AQC111_USB_ETH_DEV(0x0b95, 0x2791, asix112_info)}, |
| 1457 | {AQC111_USB_ETH_DEV(0x20f4, 0xe05a, trendnet_info)}, | 1471 | {AQC111_USB_ETH_DEV(0x20f4, 0xe05a, trendnet_info)}, |
| 1472 | {AQC111_USB_ETH_DEV(0x1c04, 0x0015, qnap_info)}, | ||
| 1458 | { },/* END */ | 1473 | { },/* END */ |
| 1459 | }; | 1474 | }; |
| 1460 | MODULE_DEVICE_TABLE(usb, products); | 1475 | MODULE_DEVICE_TABLE(usb, products); |
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 5512a1038721..3e9b2c319e45 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c | |||
| @@ -851,6 +851,14 @@ static const struct usb_device_id products[] = { | |||
| 851 | .driver_info = 0, | 851 | .driver_info = 0, |
| 852 | }, | 852 | }, |
| 853 | 853 | ||
| 854 | /* QNAP QNA-UC5G1T USB to 5GbE Adapter (based on AQC111U) */ | ||
| 855 | { | ||
| 856 | USB_DEVICE_AND_INTERFACE_INFO(0x1c04, 0x0015, USB_CLASS_COMM, | ||
| 857 | USB_CDC_SUBCLASS_ETHERNET, | ||
| 858 | USB_CDC_PROTO_NONE), | ||
| 859 | .driver_info = 0, | ||
| 860 | }, | ||
| 861 | |||
| 854 | /* WHITELIST!!! | 862 | /* WHITELIST!!! |
| 855 | * | 863 | * |
| 856 | * CDC Ether uses two interfaces, not necessarily consecutive. | 864 | * CDC Ether uses two interfaces, not necessarily consecutive. |
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 077f1b9f2761..d76dfed8d9bb 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
| @@ -4335,10 +4335,8 @@ static void vxlan_destroy_tunnels(struct net *net, struct list_head *head) | |||
| 4335 | /* If vxlan->dev is in the same netns, it has already been added | 4335 | /* If vxlan->dev is in the same netns, it has already been added |
| 4336 | * to the list by the previous loop. | 4336 | * to the list by the previous loop. |
| 4337 | */ | 4337 | */ |
| 4338 | if (!net_eq(dev_net(vxlan->dev), net)) { | 4338 | if (!net_eq(dev_net(vxlan->dev), net)) |
| 4339 | gro_cells_destroy(&vxlan->gro_cells); | ||
| 4340 | unregister_netdevice_queue(vxlan->dev, head); | 4339 | unregister_netdevice_queue(vxlan->dev, head); |
| 4341 | } | ||
| 4342 | } | 4340 | } |
| 4343 | 4341 | ||
| 4344 | for (h = 0; h < PORT_HASH_SIZE; ++h) | 4342 | for (h = 0; h < PORT_HASH_SIZE; ++h) |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index e9822a3ec373..94132cfd1f56 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c | |||
| @@ -460,9 +460,7 @@ static int iwl_mvm_ftm_range_resp_valid(struct iwl_mvm *mvm, u8 request_id, | |||
| 460 | static void iwl_mvm_debug_range_resp(struct iwl_mvm *mvm, u8 index, | 460 | static void iwl_mvm_debug_range_resp(struct iwl_mvm *mvm, u8 index, |
| 461 | struct cfg80211_pmsr_result *res) | 461 | struct cfg80211_pmsr_result *res) |
| 462 | { | 462 | { |
| 463 | s64 rtt_avg = res->ftm.rtt_avg * 100; | 463 | s64 rtt_avg = div_s64(res->ftm.rtt_avg * 100, 6666); |
| 464 | |||
| 465 | do_div(rtt_avg, 6666); | ||
| 466 | 464 | ||
| 467 | IWL_DEBUG_INFO(mvm, "entry %d\n", index); | 465 | IWL_DEBUG_INFO(mvm, "entry %d\n", index); |
| 468 | IWL_DEBUG_INFO(mvm, "\tstatus: %d\n", res->status); | 466 | IWL_DEBUG_INFO(mvm, "\tstatus: %d\n", res->status); |
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 6eedc0ec7661..76629b98c78d 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c | |||
| @@ -130,6 +130,8 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx, | |||
| 130 | static void | 130 | static void |
| 131 | mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) | 131 | mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) |
| 132 | { | 132 | { |
| 133 | iowrite32(q->desc_dma, &q->regs->desc_base); | ||
| 134 | iowrite32(q->ndesc, &q->regs->ring_size); | ||
| 133 | q->head = ioread32(&q->regs->dma_idx); | 135 | q->head = ioread32(&q->regs->dma_idx); |
| 134 | q->tail = q->head; | 136 | q->tail = q->head; |
| 135 | iowrite32(q->head, &q->regs->cpu_idx); | 137 | iowrite32(q->head, &q->regs->cpu_idx); |
| @@ -180,7 +182,10 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush) | |||
| 180 | else | 182 | else |
| 181 | mt76_dma_sync_idx(dev, q); | 183 | mt76_dma_sync_idx(dev, q); |
| 182 | 184 | ||
| 183 | wake = wake && qid < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8; | 185 | wake = wake && q->stopped && |
| 186 | qid < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8; | ||
| 187 | if (wake) | ||
| 188 | q->stopped = false; | ||
| 184 | 189 | ||
| 185 | if (!q->queued) | 190 | if (!q->queued) |
| 186 | wake_up(&dev->tx_wait); | 191 | wake_up(&dev->tx_wait); |
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index a033745adb2f..316167404729 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c | |||
| @@ -679,19 +679,15 @@ out: | |||
| 679 | return ret; | 679 | return ret; |
| 680 | } | 680 | } |
| 681 | 681 | ||
| 682 | static void | 682 | void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, |
| 683 | mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, | 683 | struct ieee80211_sta *sta) |
| 684 | struct ieee80211_sta *sta) | ||
| 685 | { | 684 | { |
| 686 | struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; | 685 | struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; |
| 687 | int idx = wcid->idx; | 686 | int i, idx = wcid->idx; |
| 688 | int i; | ||
| 689 | 687 | ||
| 690 | rcu_assign_pointer(dev->wcid[idx], NULL); | 688 | rcu_assign_pointer(dev->wcid[idx], NULL); |
| 691 | synchronize_rcu(); | 689 | synchronize_rcu(); |
| 692 | 690 | ||
| 693 | mutex_lock(&dev->mutex); | ||
| 694 | |||
| 695 | if (dev->drv->sta_remove) | 691 | if (dev->drv->sta_remove) |
| 696 | dev->drv->sta_remove(dev, vif, sta); | 692 | dev->drv->sta_remove(dev, vif, sta); |
| 697 | 693 | ||
| @@ -699,7 +695,15 @@ mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, | |||
| 699 | for (i = 0; i < ARRAY_SIZE(sta->txq); i++) | 695 | for (i = 0; i < ARRAY_SIZE(sta->txq); i++) |
| 700 | mt76_txq_remove(dev, sta->txq[i]); | 696 | mt76_txq_remove(dev, sta->txq[i]); |
| 701 | mt76_wcid_free(dev->wcid_mask, idx); | 697 | mt76_wcid_free(dev->wcid_mask, idx); |
| 698 | } | ||
| 699 | EXPORT_SYMBOL_GPL(__mt76_sta_remove); | ||
| 702 | 700 | ||
| 701 | static void | ||
| 702 | mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, | ||
| 703 | struct ieee80211_sta *sta) | ||
| 704 | { | ||
| 705 | mutex_lock(&dev->mutex); | ||
| 706 | __mt76_sta_remove(dev, vif, sta); | ||
| 703 | mutex_unlock(&dev->mutex); | 707 | mutex_unlock(&dev->mutex); |
| 704 | } | 708 | } |
| 705 | 709 | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 5dfb0601f101..bcbfd3c4a44b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h | |||
| @@ -126,6 +126,7 @@ struct mt76_queue { | |||
| 126 | int ndesc; | 126 | int ndesc; |
| 127 | int queued; | 127 | int queued; |
| 128 | int buf_size; | 128 | int buf_size; |
| 129 | bool stopped; | ||
| 129 | 130 | ||
| 130 | u8 buf_offset; | 131 | u8 buf_offset; |
| 131 | u8 hw_idx; | 132 | u8 hw_idx; |
| @@ -143,6 +144,7 @@ struct mt76_mcu_ops { | |||
| 143 | const struct mt76_reg_pair *rp, int len); | 144 | const struct mt76_reg_pair *rp, int len); |
| 144 | int (*mcu_rd_rp)(struct mt76_dev *dev, u32 base, | 145 | int (*mcu_rd_rp)(struct mt76_dev *dev, u32 base, |
| 145 | struct mt76_reg_pair *rp, int len); | 146 | struct mt76_reg_pair *rp, int len); |
| 147 | int (*mcu_restart)(struct mt76_dev *dev); | ||
| 146 | }; | 148 | }; |
| 147 | 149 | ||
| 148 | struct mt76_queue_ops { | 150 | struct mt76_queue_ops { |
| @@ -693,6 +695,8 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
| 693 | struct ieee80211_sta *sta, | 695 | struct ieee80211_sta *sta, |
| 694 | enum ieee80211_sta_state old_state, | 696 | enum ieee80211_sta_state old_state, |
| 695 | enum ieee80211_sta_state new_state); | 697 | enum ieee80211_sta_state new_state); |
| 698 | void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, | ||
| 699 | struct ieee80211_sta *sta); | ||
| 696 | 700 | ||
| 697 | struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb); | 701 | struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb); |
| 698 | 702 | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c index afcd86f735b4..4dcb465095d1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c | |||
| @@ -135,8 +135,7 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg) | |||
| 135 | 135 | ||
| 136 | out: | 136 | out: |
| 137 | mt76_queue_tx_cleanup(dev, MT_TXQ_BEACON, false); | 137 | mt76_queue_tx_cleanup(dev, MT_TXQ_BEACON, false); |
| 138 | if (dev->mt76.q_tx[MT_TXQ_BEACON].queued > | 138 | if (dev->mt76.q_tx[MT_TXQ_BEACON].queued > hweight8(dev->beacon_mask)) |
| 139 | __sw_hweight8(dev->beacon_mask)) | ||
| 140 | dev->beacon_check++; | 139 | dev->beacon_check++; |
| 141 | } | 140 | } |
| 142 | 141 | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index d69e82c66ab2..b3ae0aaea62a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c | |||
| @@ -27,12 +27,16 @@ static void | |||
| 27 | mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) | 27 | mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) |
| 28 | { | 28 | { |
| 29 | __le32 *txd = (__le32 *)skb->data; | 29 | __le32 *txd = (__le32 *)skb->data; |
| 30 | struct ieee80211_hdr *hdr; | ||
| 31 | struct ieee80211_sta *sta; | ||
| 30 | struct mt7603_sta *msta; | 32 | struct mt7603_sta *msta; |
| 31 | struct mt76_wcid *wcid; | 33 | struct mt76_wcid *wcid; |
| 34 | void *priv; | ||
| 32 | int idx; | 35 | int idx; |
| 33 | u32 val; | 36 | u32 val; |
| 37 | u8 tid; | ||
| 34 | 38 | ||
| 35 | if (skb->len < sizeof(MT_TXD_SIZE) + sizeof(struct ieee80211_hdr)) | 39 | if (skb->len < MT_TXD_SIZE + sizeof(struct ieee80211_hdr)) |
| 36 | goto free; | 40 | goto free; |
| 37 | 41 | ||
| 38 | val = le32_to_cpu(txd[1]); | 42 | val = le32_to_cpu(txd[1]); |
| @@ -46,10 +50,19 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) | |||
| 46 | if (!wcid) | 50 | if (!wcid) |
| 47 | goto free; | 51 | goto free; |
| 48 | 52 | ||
| 49 | msta = container_of(wcid, struct mt7603_sta, wcid); | 53 | priv = msta = container_of(wcid, struct mt7603_sta, wcid); |
| 50 | val = le32_to_cpu(txd[0]); | 54 | val = le32_to_cpu(txd[0]); |
| 51 | skb_set_queue_mapping(skb, FIELD_GET(MT_TXD0_Q_IDX, val)); | 55 | skb_set_queue_mapping(skb, FIELD_GET(MT_TXD0_Q_IDX, val)); |
| 52 | 56 | ||
| 57 | val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX); | ||
| 58 | val |= FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_HW_QUEUE_MGMT); | ||
| 59 | txd[0] = cpu_to_le32(val); | ||
| 60 | |||
| 61 | sta = container_of(priv, struct ieee80211_sta, drv_priv); | ||
| 62 | hdr = (struct ieee80211_hdr *) &skb->data[MT_TXD_SIZE]; | ||
| 63 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | ||
| 64 | ieee80211_sta_set_buffered(sta, tid, true); | ||
| 65 | |||
| 53 | spin_lock_bh(&dev->ps_lock); | 66 | spin_lock_bh(&dev->ps_lock); |
| 54 | __skb_queue_tail(&msta->psq, skb); | 67 | __skb_queue_tail(&msta->psq, skb); |
| 55 | if (skb_queue_len(&msta->psq) >= 64) { | 68 | if (skb_queue_len(&msta->psq) >= 64) { |
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 15cc8f33b34d..d54dda67d036 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c | |||
| @@ -112,7 +112,7 @@ static void | |||
| 112 | mt7603_phy_init(struct mt7603_dev *dev) | 112 | mt7603_phy_init(struct mt7603_dev *dev) |
| 113 | { | 113 | { |
| 114 | int rx_chains = dev->mt76.antenna_mask; | 114 | int rx_chains = dev->mt76.antenna_mask; |
| 115 | int tx_chains = __sw_hweight8(rx_chains) - 1; | 115 | int tx_chains = hweight8(rx_chains) - 1; |
| 116 | 116 | ||
| 117 | mt76_rmw(dev, MT_WF_RMAC_RMCR, | 117 | mt76_rmw(dev, MT_WF_RMAC_RMCR, |
| 118 | (MT_WF_RMAC_RMCR_SMPS_MODE | | 118 | (MT_WF_RMAC_RMCR_SMPS_MODE | |
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 0a0115861b51..5e31d7da96fc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c | |||
| @@ -1072,7 +1072,7 @@ out: | |||
| 1072 | case MT_PHY_TYPE_HT: | 1072 | case MT_PHY_TYPE_HT: |
| 1073 | final_rate_flags |= IEEE80211_TX_RC_MCS; | 1073 | final_rate_flags |= IEEE80211_TX_RC_MCS; |
| 1074 | final_rate &= GENMASK(5, 0); | 1074 | final_rate &= GENMASK(5, 0); |
| 1075 | if (i > 15) | 1075 | if (final_rate > 15) |
| 1076 | return false; | 1076 | return false; |
| 1077 | break; | 1077 | break; |
| 1078 | default: | 1078 | default: |
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index b10775ed92e6..cc0fe0933b2d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <linux/pci.h> | 5 | #include <linux/pci.h> |
| 6 | #include <linux/module.h> | 6 | #include <linux/module.h> |
| 7 | #include "mt7603.h" | 7 | #include "mt7603.h" |
| 8 | #include "mac.h" | ||
| 8 | #include "eeprom.h" | 9 | #include "eeprom.h" |
| 9 | 10 | ||
| 10 | static int | 11 | static int |
| @@ -386,6 +387,15 @@ mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) | |||
| 386 | } | 387 | } |
| 387 | 388 | ||
| 388 | static void | 389 | static void |
| 390 | mt7603_ps_set_more_data(struct sk_buff *skb) | ||
| 391 | { | ||
| 392 | struct ieee80211_hdr *hdr; | ||
| 393 | |||
| 394 | hdr = (struct ieee80211_hdr *) &skb->data[MT_TXD_SIZE]; | ||
| 395 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
| 396 | } | ||
| 397 | |||
| 398 | static void | ||
| 389 | mt7603_release_buffered_frames(struct ieee80211_hw *hw, | 399 | mt7603_release_buffered_frames(struct ieee80211_hw *hw, |
| 390 | struct ieee80211_sta *sta, | 400 | struct ieee80211_sta *sta, |
| 391 | u16 tids, int nframes, | 401 | u16 tids, int nframes, |
| @@ -399,6 +409,8 @@ mt7603_release_buffered_frames(struct ieee80211_hw *hw, | |||
| 399 | 409 | ||
| 400 | __skb_queue_head_init(&list); | 410 | __skb_queue_head_init(&list); |
| 401 | 411 | ||
| 412 | mt7603_wtbl_set_ps(dev, msta, false); | ||
| 413 | |||
| 402 | spin_lock_bh(&dev->ps_lock); | 414 | spin_lock_bh(&dev->ps_lock); |
| 403 | skb_queue_walk_safe(&msta->psq, skb, tmp) { | 415 | skb_queue_walk_safe(&msta->psq, skb, tmp) { |
| 404 | if (!nframes) | 416 | if (!nframes) |
| @@ -409,11 +421,15 @@ mt7603_release_buffered_frames(struct ieee80211_hw *hw, | |||
| 409 | 421 | ||
| 410 | skb_set_queue_mapping(skb, MT_TXQ_PSD); | 422 | skb_set_queue_mapping(skb, MT_TXQ_PSD); |
| 411 | __skb_unlink(skb, &msta->psq); | 423 | __skb_unlink(skb, &msta->psq); |
| 424 | mt7603_ps_set_more_data(skb); | ||
| 412 | __skb_queue_tail(&list, skb); | 425 | __skb_queue_tail(&list, skb); |
| 413 | nframes--; | 426 | nframes--; |
| 414 | } | 427 | } |
| 415 | spin_unlock_bh(&dev->ps_lock); | 428 | spin_unlock_bh(&dev->ps_lock); |
| 416 | 429 | ||
| 430 | if (!skb_queue_empty(&list)) | ||
| 431 | ieee80211_sta_eosp(sta); | ||
| 432 | |||
| 417 | mt7603_ps_tx_list(dev, &list); | 433 | mt7603_ps_tx_list(dev, &list); |
| 418 | 434 | ||
| 419 | if (nframes) | 435 | if (nframes) |
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c index 4b0713f1fd5e..d06905ea8cc6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c | |||
| @@ -433,7 +433,7 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev) | |||
| 433 | { | 433 | { |
| 434 | struct cfg80211_chan_def *chandef = &dev->mt76.chandef; | 434 | struct cfg80211_chan_def *chandef = &dev->mt76.chandef; |
| 435 | struct ieee80211_hw *hw = mt76_hw(dev); | 435 | struct ieee80211_hw *hw = mt76_hw(dev); |
| 436 | int n_chains = __sw_hweight8(dev->mt76.antenna_mask); | 436 | int n_chains = hweight8(dev->mt76.antenna_mask); |
| 437 | struct { | 437 | struct { |
| 438 | u8 control_chan; | 438 | u8 control_chan; |
| 439 | u8 center_chan; | 439 | u8 center_chan; |
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c index e13fea80d970..b920be1f5718 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c | |||
| @@ -23,9 +23,9 @@ mt76_wmac_probe(struct platform_device *pdev) | |||
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | mem_base = devm_ioremap_resource(&pdev->dev, res); | 25 | mem_base = devm_ioremap_resource(&pdev->dev, res); |
| 26 | if (!mem_base) { | 26 | if (IS_ERR(mem_base)) { |
| 27 | dev_err(&pdev->dev, "Failed to get memory resource\n"); | 27 | dev_err(&pdev->dev, "Failed to get memory resource\n"); |
| 28 | return -EINVAL; | 28 | return PTR_ERR(mem_base); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops, | 31 | mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops, |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h b/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h index 0290ba5869a5..736f81752b5b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h | |||
| @@ -46,7 +46,7 @@ static const struct mt76_reg_pair common_mac_reg_table[] = { | |||
| 46 | { MT_MM20_PROT_CFG, 0x01742004 }, | 46 | { MT_MM20_PROT_CFG, 0x01742004 }, |
| 47 | { MT_MM40_PROT_CFG, 0x03f42084 }, | 47 | { MT_MM40_PROT_CFG, 0x03f42084 }, |
| 48 | { MT_TXOP_CTRL_CFG, 0x0000583f }, | 48 | { MT_TXOP_CTRL_CFG, 0x0000583f }, |
| 49 | { MT_TX_RTS_CFG, 0x00092b20 }, | 49 | { MT_TX_RTS_CFG, 0x00ffff20 }, |
| 50 | { MT_EXP_ACK_TIME, 0x002400ca }, | 50 | { MT_EXP_ACK_TIME, 0x002400ca }, |
| 51 | { MT_TXOP_HLDR_ET, 0x00000002 }, | 51 | { MT_TXOP_HLDR_ET, 0x00000002 }, |
| 52 | { MT_XIFS_TIME_CFG, 0x33a41010 }, | 52 | { MT_XIFS_TIME_CFG, 0x33a41010 }, |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 91718647da02..e5a06f74a6f7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | |||
| @@ -229,7 +229,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, | |||
| 229 | struct usb_device *usb_dev = interface_to_usbdev(usb_intf); | 229 | struct usb_device *usb_dev = interface_to_usbdev(usb_intf); |
| 230 | struct mt76x02_dev *dev; | 230 | struct mt76x02_dev *dev; |
| 231 | struct mt76_dev *mdev; | 231 | struct mt76_dev *mdev; |
| 232 | u32 asic_rev, mac_rev; | 232 | u32 mac_rev; |
| 233 | int ret; | 233 | int ret; |
| 234 | 234 | ||
| 235 | mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), &mt76x0u_ops, | 235 | mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), &mt76x0u_ops, |
| @@ -262,10 +262,14 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, | |||
| 262 | goto err; | 262 | goto err; |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | asic_rev = mt76_rr(dev, MT_ASIC_VERSION); | 265 | mdev->rev = mt76_rr(dev, MT_ASIC_VERSION); |
| 266 | mac_rev = mt76_rr(dev, MT_MAC_CSR0); | 266 | mac_rev = mt76_rr(dev, MT_MAC_CSR0); |
| 267 | dev_info(mdev->dev, "ASIC revision: %08x MAC revision: %08x\n", | 267 | dev_info(mdev->dev, "ASIC revision: %08x MAC revision: %08x\n", |
| 268 | asic_rev, mac_rev); | 268 | mdev->rev, mac_rev); |
| 269 | if (!is_mt76x0(dev)) { | ||
| 270 | ret = -ENODEV; | ||
| 271 | goto err; | ||
| 272 | } | ||
| 269 | 273 | ||
| 270 | /* Note: vendor driver skips this check for MT76X0U */ | 274 | /* Note: vendor driver skips this check for MT76X0U */ |
| 271 | if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL)) | 275 | if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL)) |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 6915cce5def9..07061eb4d1e1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h | |||
| @@ -51,6 +51,7 @@ struct mt76x02_calibration { | |||
| 51 | u16 false_cca; | 51 | u16 false_cca; |
| 52 | s8 avg_rssi_all; | 52 | s8 avg_rssi_all; |
| 53 | s8 agc_gain_adjust; | 53 | s8 agc_gain_adjust; |
| 54 | s8 agc_lowest_gain; | ||
| 54 | s8 low_gain; | 55 | s8 low_gain; |
| 55 | 56 | ||
| 56 | s8 temp_vco; | 57 | s8 temp_vco; |
| @@ -114,8 +115,11 @@ struct mt76x02_dev { | |||
| 114 | struct mt76x02_dfs_pattern_detector dfs_pd; | 115 | struct mt76x02_dfs_pattern_detector dfs_pd; |
| 115 | 116 | ||
| 116 | /* edcca monitor */ | 117 | /* edcca monitor */ |
| 118 | unsigned long ed_trigger_timeout; | ||
| 117 | bool ed_tx_blocked; | 119 | bool ed_tx_blocked; |
| 118 | bool ed_monitor; | 120 | bool ed_monitor; |
| 121 | u8 ed_monitor_enabled; | ||
| 122 | u8 ed_monitor_learning; | ||
| 119 | u8 ed_trigger; | 123 | u8 ed_trigger; |
| 120 | u8 ed_silent; | 124 | u8 ed_silent; |
| 121 | ktime_t ed_time; | 125 | ktime_t ed_time; |
| @@ -188,6 +192,13 @@ void mt76x02_mac_start(struct mt76x02_dev *dev); | |||
| 188 | 192 | ||
| 189 | void mt76x02_init_debugfs(struct mt76x02_dev *dev); | 193 | void mt76x02_init_debugfs(struct mt76x02_dev *dev); |
| 190 | 194 | ||
| 195 | static inline bool is_mt76x0(struct mt76x02_dev *dev) | ||
| 196 | { | ||
| 197 | return mt76_chip(&dev->mt76) == 0x7610 || | ||
| 198 | mt76_chip(&dev->mt76) == 0x7630 || | ||
| 199 | mt76_chip(&dev->mt76) == 0x7650; | ||
| 200 | } | ||
| 201 | |||
| 191 | static inline bool is_mt76x2(struct mt76x02_dev *dev) | 202 | static inline bool is_mt76x2(struct mt76x02_dev *dev) |
| 192 | { | 203 | { |
| 193 | return mt76_chip(&dev->mt76) == 0x7612 || | 204 | return mt76_chip(&dev->mt76) == 0x7612 || |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c index 7580c5c986ff..b1d6fd4861e3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c | |||
| @@ -116,6 +116,32 @@ static int read_agc(struct seq_file *file, void *data) | |||
| 116 | return 0; | 116 | return 0; |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | static int | ||
| 120 | mt76_edcca_set(void *data, u64 val) | ||
| 121 | { | ||
| 122 | struct mt76x02_dev *dev = data; | ||
| 123 | enum nl80211_dfs_regions region = dev->dfs_pd.region; | ||
| 124 | |||
| 125 | dev->ed_monitor_enabled = !!val; | ||
| 126 | dev->ed_monitor = dev->ed_monitor_enabled && | ||
| 127 | region == NL80211_DFS_ETSI; | ||
| 128 | mt76x02_edcca_init(dev, true); | ||
| 129 | |||
| 130 | return 0; | ||
| 131 | } | ||
| 132 | |||
| 133 | static int | ||
| 134 | mt76_edcca_get(void *data, u64 *val) | ||
| 135 | { | ||
| 136 | struct mt76x02_dev *dev = data; | ||
| 137 | |||
| 138 | *val = dev->ed_monitor_enabled; | ||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | DEFINE_DEBUGFS_ATTRIBUTE(fops_edcca, mt76_edcca_get, mt76_edcca_set, | ||
| 143 | "%lld\n"); | ||
| 144 | |||
| 119 | void mt76x02_init_debugfs(struct mt76x02_dev *dev) | 145 | void mt76x02_init_debugfs(struct mt76x02_dev *dev) |
| 120 | { | 146 | { |
| 121 | struct dentry *dir; | 147 | struct dentry *dir; |
| @@ -127,6 +153,7 @@ void mt76x02_init_debugfs(struct mt76x02_dev *dev) | |||
| 127 | debugfs_create_u8("temperature", 0400, dir, &dev->cal.temp); | 153 | debugfs_create_u8("temperature", 0400, dir, &dev->cal.temp); |
| 128 | debugfs_create_bool("tpc", 0600, dir, &dev->enable_tpc); | 154 | debugfs_create_bool("tpc", 0600, dir, &dev->enable_tpc); |
| 129 | 155 | ||
| 156 | debugfs_create_file("edcca", 0400, dir, dev, &fops_edcca); | ||
| 130 | debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat); | 157 | debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat); |
| 131 | debugfs_create_file("dfs_stats", 0400, dir, dev, &fops_dfs_stat); | 158 | debugfs_create_file("dfs_stats", 0400, dir, dev, &fops_dfs_stat); |
| 132 | debugfs_create_devm_seqfile(dev->mt76.dev, "txpower", dir, | 159 | debugfs_create_devm_seqfile(dev->mt76.dev, "txpower", dir, |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index e4649103efd4..17d12d212d1b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c | |||
| @@ -885,7 +885,8 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev, | |||
| 885 | if (dfs_pd->region != region) { | 885 | if (dfs_pd->region != region) { |
| 886 | tasklet_disable(&dfs_pd->dfs_tasklet); | 886 | tasklet_disable(&dfs_pd->dfs_tasklet); |
| 887 | 887 | ||
| 888 | dev->ed_monitor = region == NL80211_DFS_ETSI; | 888 | dev->ed_monitor = dev->ed_monitor_enabled && |
| 889 | region == NL80211_DFS_ETSI; | ||
| 889 | mt76x02_edcca_init(dev, true); | 890 | mt76x02_edcca_init(dev, true); |
| 890 | 891 | ||
| 891 | dfs_pd->region = region; | 892 | dfs_pd->region = region; |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 91ff6598eccf..9ed231abe916 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | |||
| @@ -67,12 +67,39 @@ int mt76x02_mac_shared_key_setup(struct mt76x02_dev *dev, u8 vif_idx, | |||
| 67 | } | 67 | } |
| 68 | EXPORT_SYMBOL_GPL(mt76x02_mac_shared_key_setup); | 68 | EXPORT_SYMBOL_GPL(mt76x02_mac_shared_key_setup); |
| 69 | 69 | ||
| 70 | void mt76x02_mac_wcid_sync_pn(struct mt76x02_dev *dev, u8 idx, | ||
| 71 | struct ieee80211_key_conf *key) | ||
| 72 | { | ||
| 73 | enum mt76x02_cipher_type cipher; | ||
| 74 | u8 key_data[32]; | ||
| 75 | u32 iv, eiv; | ||
| 76 | u64 pn; | ||
| 77 | |||
| 78 | cipher = mt76x02_mac_get_key_info(key, key_data); | ||
| 79 | iv = mt76_rr(dev, MT_WCID_IV(idx)); | ||
| 80 | eiv = mt76_rr(dev, MT_WCID_IV(idx) + 4); | ||
| 81 | |||
| 82 | pn = (u64)eiv << 16; | ||
| 83 | if (cipher == MT_CIPHER_TKIP) { | ||
| 84 | pn |= (iv >> 16) & 0xff; | ||
| 85 | pn |= (iv & 0xff) << 8; | ||
| 86 | } else if (cipher >= MT_CIPHER_AES_CCMP) { | ||
| 87 | pn |= iv & 0xffff; | ||
| 88 | } else { | ||
| 89 | return; | ||
| 90 | } | ||
| 91 | |||
| 92 | atomic64_set(&key->tx_pn, pn); | ||
| 93 | } | ||
| 94 | |||
| 95 | |||
| 70 | int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx, | 96 | int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx, |
| 71 | struct ieee80211_key_conf *key) | 97 | struct ieee80211_key_conf *key) |
| 72 | { | 98 | { |
| 73 | enum mt76x02_cipher_type cipher; | 99 | enum mt76x02_cipher_type cipher; |
| 74 | u8 key_data[32]; | 100 | u8 key_data[32]; |
| 75 | u8 iv_data[8]; | 101 | u8 iv_data[8]; |
| 102 | u64 pn; | ||
| 76 | 103 | ||
| 77 | cipher = mt76x02_mac_get_key_info(key, key_data); | 104 | cipher = mt76x02_mac_get_key_info(key, key_data); |
| 78 | if (cipher == MT_CIPHER_NONE && key) | 105 | if (cipher == MT_CIPHER_NONE && key) |
| @@ -85,9 +112,22 @@ int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx, | |||
| 85 | if (key) { | 112 | if (key) { |
| 86 | mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PAIRWISE, | 113 | mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PAIRWISE, |
| 87 | !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); | 114 | !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); |
| 115 | |||
| 116 | pn = atomic64_read(&key->tx_pn); | ||
| 117 | |||
| 88 | iv_data[3] = key->keyidx << 6; | 118 | iv_data[3] = key->keyidx << 6; |
| 89 | if (cipher >= MT_CIPHER_TKIP) | 119 | if (cipher >= MT_CIPHER_TKIP) { |
| 90 | iv_data[3] |= 0x20; | 120 | iv_data[3] |= 0x20; |
| 121 | put_unaligned_le32(pn >> 16, &iv_data[4]); | ||
| 122 | } | ||
| 123 | |||
| 124 | if (cipher == MT_CIPHER_TKIP) { | ||
| 125 | iv_data[0] = (pn >> 8) & 0xff; | ||
| 126 | iv_data[1] = (iv_data[0] | 0x20) & 0x7f; | ||
| 127 | iv_data[2] = pn & 0xff; | ||
| 128 | } else if (cipher >= MT_CIPHER_AES_CCMP) { | ||
| 129 | put_unaligned_le16((pn & 0xffff), &iv_data[0]); | ||
| 130 | } | ||
| 91 | } | 131 | } |
| 92 | 132 | ||
| 93 | mt76_wr_copy(dev, MT_WCID_IV(idx), iv_data, sizeof(iv_data)); | 133 | mt76_wr_copy(dev, MT_WCID_IV(idx), iv_data, sizeof(iv_data)); |
| @@ -920,6 +960,7 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable) | |||
| 920 | } | 960 | } |
| 921 | } | 961 | } |
| 922 | mt76x02_edcca_tx_enable(dev, true); | 962 | mt76x02_edcca_tx_enable(dev, true); |
| 963 | dev->ed_monitor_learning = true; | ||
| 923 | 964 | ||
| 924 | /* clear previous CCA timer value */ | 965 | /* clear previous CCA timer value */ |
| 925 | mt76_rr(dev, MT_ED_CCA_TIMER); | 966 | mt76_rr(dev, MT_ED_CCA_TIMER); |
| @@ -929,6 +970,10 @@ EXPORT_SYMBOL_GPL(mt76x02_edcca_init); | |||
| 929 | 970 | ||
| 930 | #define MT_EDCCA_TH 92 | 971 | #define MT_EDCCA_TH 92 |
| 931 | #define MT_EDCCA_BLOCK_TH 2 | 972 | #define MT_EDCCA_BLOCK_TH 2 |
| 973 | #define MT_EDCCA_LEARN_TH 50 | ||
| 974 | #define MT_EDCCA_LEARN_CCA 180 | ||
| 975 | #define MT_EDCCA_LEARN_TIMEOUT (20 * HZ) | ||
| 976 | |||
| 932 | static void mt76x02_edcca_check(struct mt76x02_dev *dev) | 977 | static void mt76x02_edcca_check(struct mt76x02_dev *dev) |
| 933 | { | 978 | { |
| 934 | ktime_t cur_time; | 979 | ktime_t cur_time; |
| @@ -951,11 +996,23 @@ static void mt76x02_edcca_check(struct mt76x02_dev *dev) | |||
| 951 | dev->ed_trigger = 0; | 996 | dev->ed_trigger = 0; |
| 952 | } | 997 | } |
| 953 | 998 | ||
| 954 | if (dev->ed_trigger > MT_EDCCA_BLOCK_TH && | 999 | if (dev->cal.agc_lowest_gain && |
| 955 | !dev->ed_tx_blocked) | 1000 | dev->cal.false_cca > MT_EDCCA_LEARN_CCA && |
| 1001 | dev->ed_trigger > MT_EDCCA_LEARN_TH) { | ||
| 1002 | dev->ed_monitor_learning = false; | ||
| 1003 | dev->ed_trigger_timeout = jiffies + 20 * HZ; | ||
| 1004 | } else if (!dev->ed_monitor_learning && | ||
| 1005 | time_is_after_jiffies(dev->ed_trigger_timeout)) { | ||
| 1006 | dev->ed_monitor_learning = true; | ||
| 1007 | mt76x02_edcca_tx_enable(dev, true); | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | if (dev->ed_monitor_learning) | ||
| 1011 | return; | ||
| 1012 | |||
| 1013 | if (dev->ed_trigger > MT_EDCCA_BLOCK_TH && !dev->ed_tx_blocked) | ||
| 956 | mt76x02_edcca_tx_enable(dev, false); | 1014 | mt76x02_edcca_tx_enable(dev, false); |
| 957 | else if (dev->ed_silent > MT_EDCCA_BLOCK_TH && | 1015 | else if (dev->ed_silent > MT_EDCCA_BLOCK_TH && dev->ed_tx_blocked) |
| 958 | dev->ed_tx_blocked) | ||
| 959 | mt76x02_edcca_tx_enable(dev, true); | 1016 | mt76x02_edcca_tx_enable(dev, true); |
| 960 | } | 1017 | } |
| 961 | 1018 | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 6b1f25d2f64c..caeeef96c42f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h | |||
| @@ -177,6 +177,8 @@ int mt76x02_mac_shared_key_setup(struct mt76x02_dev *dev, u8 vif_idx, | |||
| 177 | u8 key_idx, struct ieee80211_key_conf *key); | 177 | u8 key_idx, struct ieee80211_key_conf *key); |
| 178 | int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx, | 178 | int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx, |
| 179 | struct ieee80211_key_conf *key); | 179 | struct ieee80211_key_conf *key); |
| 180 | void mt76x02_mac_wcid_sync_pn(struct mt76x02_dev *dev, u8 idx, | ||
| 181 | struct ieee80211_key_conf *key); | ||
| 180 | void mt76x02_mac_wcid_setup(struct mt76x02_dev *dev, u8 idx, u8 vif_idx, | 182 | void mt76x02_mac_wcid_setup(struct mt76x02_dev *dev, u8 idx, u8 vif_idx, |
| 181 | u8 *mac); | 183 | u8 *mac); |
| 182 | void mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop); | 184 | void mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop); |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 1229f19f2b02..daaed1220147 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
| 20 | 20 | ||
| 21 | #include "mt76x02.h" | 21 | #include "mt76x02.h" |
| 22 | #include "mt76x02_mcu.h" | ||
| 22 | #include "mt76x02_trace.h" | 23 | #include "mt76x02_trace.h" |
| 23 | 24 | ||
| 24 | struct beacon_bc_data { | 25 | struct beacon_bc_data { |
| @@ -418,9 +419,66 @@ static bool mt76x02_tx_hang(struct mt76x02_dev *dev) | |||
| 418 | return i < 4; | 419 | return i < 4; |
| 419 | } | 420 | } |
| 420 | 421 | ||
| 422 | static void mt76x02_key_sync(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
| 423 | struct ieee80211_sta *sta, | ||
| 424 | struct ieee80211_key_conf *key, void *data) | ||
| 425 | { | ||
| 426 | struct mt76x02_dev *dev = hw->priv; | ||
| 427 | struct mt76_wcid *wcid; | ||
| 428 | |||
| 429 | if (!sta) | ||
| 430 | return; | ||
| 431 | |||
| 432 | wcid = (struct mt76_wcid *) sta->drv_priv; | ||
| 433 | |||
| 434 | if (wcid->hw_key_idx != key->keyidx || wcid->sw_iv) | ||
| 435 | return; | ||
| 436 | |||
| 437 | mt76x02_mac_wcid_sync_pn(dev, wcid->idx, key); | ||
| 438 | } | ||
| 439 | |||
| 440 | static void mt76x02_reset_state(struct mt76x02_dev *dev) | ||
| 441 | { | ||
| 442 | int i; | ||
| 443 | |||
| 444 | lockdep_assert_held(&dev->mt76.mutex); | ||
| 445 | |||
| 446 | clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); | ||
| 447 | |||
| 448 | rcu_read_lock(); | ||
| 449 | ieee80211_iter_keys_rcu(dev->mt76.hw, NULL, mt76x02_key_sync, NULL); | ||
| 450 | rcu_read_unlock(); | ||
| 451 | |||
| 452 | for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid); i++) { | ||
| 453 | struct ieee80211_sta *sta; | ||
| 454 | struct ieee80211_vif *vif; | ||
| 455 | struct mt76x02_sta *msta; | ||
| 456 | struct mt76_wcid *wcid; | ||
| 457 | void *priv; | ||
| 458 | |||
| 459 | wcid = rcu_dereference_protected(dev->mt76.wcid[i], | ||
| 460 | lockdep_is_held(&dev->mt76.mutex)); | ||
| 461 | if (!wcid) | ||
| 462 | continue; | ||
| 463 | |||
| 464 | priv = msta = container_of(wcid, struct mt76x02_sta, wcid); | ||
| 465 | sta = container_of(priv, struct ieee80211_sta, drv_priv); | ||
| 466 | |||
| 467 | priv = msta->vif; | ||
| 468 | vif = container_of(priv, struct ieee80211_vif, drv_priv); | ||
| 469 | |||
| 470 | __mt76_sta_remove(&dev->mt76, vif, sta); | ||
| 471 | memset(msta, 0, sizeof(*msta)); | ||
| 472 | } | ||
| 473 | |||
| 474 | dev->vif_mask = 0; | ||
| 475 | dev->beacon_mask = 0; | ||
| 476 | } | ||
| 477 | |||
| 421 | static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) | 478 | static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) |
| 422 | { | 479 | { |
| 423 | u32 mask = dev->mt76.mmio.irqmask; | 480 | u32 mask = dev->mt76.mmio.irqmask; |
| 481 | bool restart = dev->mt76.mcu_ops->mcu_restart; | ||
| 424 | int i; | 482 | int i; |
| 425 | 483 | ||
| 426 | ieee80211_stop_queues(dev->mt76.hw); | 484 | ieee80211_stop_queues(dev->mt76.hw); |
| @@ -434,6 +492,9 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) | |||
| 434 | 492 | ||
| 435 | mutex_lock(&dev->mt76.mutex); | 493 | mutex_lock(&dev->mt76.mutex); |
| 436 | 494 | ||
| 495 | if (restart) | ||
| 496 | mt76x02_reset_state(dev); | ||
| 497 | |||
| 437 | if (dev->beacon_mask) | 498 | if (dev->beacon_mask) |
| 438 | mt76_clear(dev, MT_BEACON_TIME_CFG, | 499 | mt76_clear(dev, MT_BEACON_TIME_CFG, |
| 439 | MT_BEACON_TIME_CFG_BEACON_TX | | 500 | MT_BEACON_TIME_CFG_BEACON_TX | |
| @@ -452,20 +513,21 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) | |||
| 452 | /* let fw reset DMA */ | 513 | /* let fw reset DMA */ |
| 453 | mt76_set(dev, 0x734, 0x3); | 514 | mt76_set(dev, 0x734, 0x3); |
| 454 | 515 | ||
| 516 | if (restart) | ||
| 517 | dev->mt76.mcu_ops->mcu_restart(&dev->mt76); | ||
| 518 | |||
| 455 | for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++) | 519 | for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++) |
| 456 | mt76_queue_tx_cleanup(dev, i, true); | 520 | mt76_queue_tx_cleanup(dev, i, true); |
| 457 | 521 | ||
| 458 | for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) | 522 | for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) |
| 459 | mt76_queue_rx_reset(dev, i); | 523 | mt76_queue_rx_reset(dev, i); |
| 460 | 524 | ||
| 461 | mt76_wr(dev, MT_MAC_SYS_CTRL, | 525 | mt76x02_mac_start(dev); |
| 462 | MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX); | 526 | |
| 463 | mt76_set(dev, MT_WPDMA_GLO_CFG, | ||
| 464 | MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_EN); | ||
| 465 | if (dev->ed_monitor) | 527 | if (dev->ed_monitor) |
| 466 | mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); | 528 | mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); |
| 467 | 529 | ||
| 468 | if (dev->beacon_mask) | 530 | if (dev->beacon_mask && !restart) |
| 469 | mt76_set(dev, MT_BEACON_TIME_CFG, | 531 | mt76_set(dev, MT_BEACON_TIME_CFG, |
| 470 | MT_BEACON_TIME_CFG_BEACON_TX | | 532 | MT_BEACON_TIME_CFG_BEACON_TX | |
| 471 | MT_BEACON_TIME_CFG_TBTT_EN); | 533 | MT_BEACON_TIME_CFG_TBTT_EN); |
| @@ -486,9 +548,13 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) | |||
| 486 | napi_schedule(&dev->mt76.napi[i]); | 548 | napi_schedule(&dev->mt76.napi[i]); |
| 487 | } | 549 | } |
| 488 | 550 | ||
| 489 | ieee80211_wake_queues(dev->mt76.hw); | 551 | if (restart) { |
| 490 | 552 | mt76x02_mcu_function_select(dev, Q_SELECT, 1); | |
| 491 | mt76_txq_schedule_all(&dev->mt76); | 553 | ieee80211_restart_hw(dev->mt76.hw); |
| 554 | } else { | ||
| 555 | ieee80211_wake_queues(dev->mt76.hw); | ||
| 556 | mt76_txq_schedule_all(&dev->mt76); | ||
| 557 | } | ||
| 492 | } | 558 | } |
| 493 | 559 | ||
| 494 | static void mt76x02_check_tx_hang(struct mt76x02_dev *dev) | 560 | static void mt76x02_check_tx_hang(struct mt76x02_dev *dev) |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c index a020c757ba5c..a54b63a96eae 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c | |||
| @@ -194,6 +194,8 @@ bool mt76x02_phy_adjust_vga_gain(struct mt76x02_dev *dev) | |||
| 194 | ret = true; | 194 | ret = true; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | dev->cal.agc_lowest_gain = dev->cal.agc_gain_adjust >= limit; | ||
| 198 | |||
| 197 | return ret; | 199 | return ret; |
| 198 | } | 200 | } |
| 199 | EXPORT_SYMBOL_GPL(mt76x02_phy_adjust_vga_gain); | 201 | EXPORT_SYMBOL_GPL(mt76x02_phy_adjust_vga_gain); |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 43f07461c8d3..6fb52b596d42 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | |||
| @@ -85,8 +85,9 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, | |||
| 85 | 85 | ||
| 86 | mt76x02_insert_hdr_pad(skb); | 86 | mt76x02_insert_hdr_pad(skb); |
| 87 | 87 | ||
| 88 | txwi = skb_push(skb, sizeof(struct mt76x02_txwi)); | 88 | txwi = (struct mt76x02_txwi *)(skb->data - sizeof(struct mt76x02_txwi)); |
| 89 | mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len); | 89 | mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len); |
| 90 | skb_push(skb, sizeof(struct mt76x02_txwi)); | ||
| 90 | 91 | ||
| 91 | pid = mt76_tx_status_skb_add(mdev, wcid, skb); | 92 | pid = mt76_tx_status_skb_add(mdev, wcid, skb); |
| 92 | txwi->pktid = pid; | 93 | txwi->pktid = pid; |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index a48c261b0c63..cd072ac614f7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c | |||
| @@ -237,6 +237,8 @@ int mt76x02_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, | |||
| 237 | struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; | 237 | struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; |
| 238 | int idx = 0; | 238 | int idx = 0; |
| 239 | 239 | ||
| 240 | memset(msta, 0, sizeof(*msta)); | ||
| 241 | |||
| 240 | idx = mt76_wcid_alloc(dev->mt76.wcid_mask, ARRAY_SIZE(dev->mt76.wcid)); | 242 | idx = mt76_wcid_alloc(dev->mt76.wcid_mask, ARRAY_SIZE(dev->mt76.wcid)); |
| 241 | if (idx < 0) | 243 | if (idx < 0) |
| 242 | return -ENOSPC; | 244 | return -ENOSPC; |
| @@ -274,6 +276,8 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, | |||
| 274 | struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; | 276 | struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; |
| 275 | struct mt76_txq *mtxq; | 277 | struct mt76_txq *mtxq; |
| 276 | 278 | ||
| 279 | memset(mvif, 0, sizeof(*mvif)); | ||
| 280 | |||
| 277 | mvif->idx = idx; | 281 | mvif->idx = idx; |
| 278 | mvif->group_wcid.idx = MT_VIF_WCID(idx); | 282 | mvif->group_wcid.idx = MT_VIF_WCID(idx); |
| 279 | mvif->group_wcid.hw_key_idx = -1; | 283 | mvif->group_wcid.hw_key_idx = -1; |
| @@ -289,6 +293,12 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
| 289 | struct mt76x02_dev *dev = hw->priv; | 293 | struct mt76x02_dev *dev = hw->priv; |
| 290 | unsigned int idx = 0; | 294 | unsigned int idx = 0; |
| 291 | 295 | ||
| 296 | /* Allow to change address in HW if we create first interface. */ | ||
| 297 | if (!dev->vif_mask && | ||
| 298 | (((vif->addr[0] ^ dev->mt76.macaddr[0]) & ~GENMASK(4, 1)) || | ||
| 299 | memcmp(vif->addr + 1, dev->mt76.macaddr + 1, ETH_ALEN - 1))) | ||
| 300 | mt76x02_mac_setaddr(dev, vif->addr); | ||
| 301 | |||
| 292 | if (vif->addr[0] & BIT(1)) | 302 | if (vif->addr[0] & BIT(1)) |
| 293 | idx = 1 + (((dev->mt76.macaddr[0] ^ vif->addr[0]) >> 2) & 7); | 303 | idx = 1 + (((dev->mt76.macaddr[0] ^ vif->addr[0]) >> 2) & 7); |
| 294 | 304 | ||
| @@ -311,10 +321,6 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
| 311 | if (dev->vif_mask & BIT(idx)) | 321 | if (dev->vif_mask & BIT(idx)) |
| 312 | return -EBUSY; | 322 | return -EBUSY; |
| 313 | 323 | ||
| 314 | /* Allow to change address in HW if we create first interface. */ | ||
| 315 | if (!dev->vif_mask && !ether_addr_equal(dev->mt76.macaddr, vif->addr)) | ||
| 316 | mt76x02_mac_setaddr(dev, vif->addr); | ||
| 317 | |||
| 318 | dev->vif_mask |= BIT(idx); | 324 | dev->vif_mask |= BIT(idx); |
| 319 | 325 | ||
| 320 | mt76x02_vif_init(dev, vif, idx); | 326 | mt76x02_vif_init(dev, vif, idx); |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c index f8534362e2c8..a30ef2c5a9db 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c | |||
| @@ -106,7 +106,7 @@ void mt76_write_mac_initvals(struct mt76x02_dev *dev) | |||
| 106 | { MT_TX_SW_CFG1, 0x00010000 }, | 106 | { MT_TX_SW_CFG1, 0x00010000 }, |
| 107 | { MT_TX_SW_CFG2, 0x00000000 }, | 107 | { MT_TX_SW_CFG2, 0x00000000 }, |
| 108 | { MT_TXOP_CTRL_CFG, 0x0400583f }, | 108 | { MT_TXOP_CTRL_CFG, 0x0400583f }, |
| 109 | { MT_TX_RTS_CFG, 0x00100020 }, | 109 | { MT_TX_RTS_CFG, 0x00ffff20 }, |
| 110 | { MT_TX_TIMEOUT_CFG, 0x000a2290 }, | 110 | { MT_TX_TIMEOUT_CFG, 0x000a2290 }, |
| 111 | { MT_TX_RETRY_CFG, 0x47f01f0f }, | 111 | { MT_TX_RETRY_CFG, 0x47f01f0f }, |
| 112 | { MT_EXP_ACK_TIME, 0x002c00dc }, | 112 | { MT_EXP_ACK_TIME, 0x002c00dc }, |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h index 6c619f1c65c9..d7abe3d73bad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h | |||
| @@ -71,6 +71,7 @@ int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level, | |||
| 71 | 71 | ||
| 72 | void mt76x2_cleanup(struct mt76x02_dev *dev); | 72 | void mt76x2_cleanup(struct mt76x02_dev *dev); |
| 73 | 73 | ||
| 74 | int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard); | ||
| 74 | void mt76x2_reset_wlan(struct mt76x02_dev *dev, bool enable); | 75 | void mt76x2_reset_wlan(struct mt76x02_dev *dev, bool enable); |
| 75 | void mt76x2_init_txpower(struct mt76x02_dev *dev, | 76 | void mt76x2_init_txpower(struct mt76x02_dev *dev, |
| 76 | struct ieee80211_supported_band *sband); | 77 | struct ieee80211_supported_band *sband); |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 984d9c4c2e1a..d3927a13e92e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c | |||
| @@ -77,7 +77,7 @@ mt76x2_fixup_xtal(struct mt76x02_dev *dev) | |||
| 77 | } | 77 | } |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) | 80 | int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) |
| 81 | { | 81 | { |
| 82 | const u8 *macaddr = dev->mt76.macaddr; | 82 | const u8 *macaddr = dev->mt76.macaddr; |
| 83 | u32 val; | 83 | u32 val; |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c index 03e24ae7f66c..605dc66ae83b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c | |||
| @@ -165,9 +165,30 @@ error: | |||
| 165 | return -ENOENT; | 165 | return -ENOENT; |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | static int | ||
| 169 | mt76pci_mcu_restart(struct mt76_dev *mdev) | ||
| 170 | { | ||
| 171 | struct mt76x02_dev *dev; | ||
| 172 | int ret; | ||
| 173 | |||
| 174 | dev = container_of(mdev, struct mt76x02_dev, mt76); | ||
| 175 | |||
| 176 | mt76x02_mcu_cleanup(dev); | ||
| 177 | mt76x2_mac_reset(dev, true); | ||
| 178 | |||
| 179 | ret = mt76pci_load_firmware(dev); | ||
| 180 | if (ret) | ||
| 181 | return ret; | ||
| 182 | |||
| 183 | mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); | ||
| 184 | |||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 168 | int mt76x2_mcu_init(struct mt76x02_dev *dev) | 188 | int mt76x2_mcu_init(struct mt76x02_dev *dev) |
| 169 | { | 189 | { |
| 170 | static const struct mt76_mcu_ops mt76x2_mcu_ops = { | 190 | static const struct mt76_mcu_ops mt76x2_mcu_ops = { |
| 191 | .mcu_restart = mt76pci_mcu_restart, | ||
| 171 | .mcu_send_msg = mt76x02_mcu_msg_send, | 192 | .mcu_send_msg = mt76x02_mcu_msg_send, |
| 172 | }; | 193 | }; |
| 173 | int ret; | 194 | int ret; |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index 1848e8ab2e21..769a9b972044 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c | |||
| @@ -260,10 +260,15 @@ mt76x2_phy_set_gain_val(struct mt76x02_dev *dev) | |||
| 260 | gain_val[0] = dev->cal.agc_gain_cur[0] - dev->cal.agc_gain_adjust; | 260 | gain_val[0] = dev->cal.agc_gain_cur[0] - dev->cal.agc_gain_adjust; |
| 261 | gain_val[1] = dev->cal.agc_gain_cur[1] - dev->cal.agc_gain_adjust; | 261 | gain_val[1] = dev->cal.agc_gain_cur[1] - dev->cal.agc_gain_adjust; |
| 262 | 262 | ||
| 263 | if (dev->mt76.chandef.width >= NL80211_CHAN_WIDTH_40) | 263 | val = 0x1836 << 16; |
| 264 | if (!mt76x2_has_ext_lna(dev) && | ||
| 265 | dev->mt76.chandef.width >= NL80211_CHAN_WIDTH_40) | ||
| 264 | val = 0x1e42 << 16; | 266 | val = 0x1e42 << 16; |
| 265 | else | 267 | |
| 266 | val = 0x1836 << 16; | 268 | if (mt76x2_has_ext_lna(dev) && |
| 269 | dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ && | ||
| 270 | dev->mt76.chandef.width < NL80211_CHAN_WIDTH_40) | ||
| 271 | val = 0x0f36 << 16; | ||
| 267 | 272 | ||
| 268 | val |= 0xf8; | 273 | val |= 0xf8; |
| 269 | 274 | ||
| @@ -280,6 +285,7 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) | |||
| 280 | { | 285 | { |
| 281 | u8 *gain = dev->cal.agc_gain_init; | 286 | u8 *gain = dev->cal.agc_gain_init; |
| 282 | u8 low_gain_delta, gain_delta; | 287 | u8 low_gain_delta, gain_delta; |
| 288 | u32 agc_35, agc_37; | ||
| 283 | bool gain_change; | 289 | bool gain_change; |
| 284 | int low_gain; | 290 | int low_gain; |
| 285 | u32 val; | 291 | u32 val; |
| @@ -318,6 +324,16 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) | |||
| 318 | else | 324 | else |
| 319 | low_gain_delta = 14; | 325 | low_gain_delta = 14; |
| 320 | 326 | ||
| 327 | agc_37 = 0x2121262c; | ||
| 328 | if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ) | ||
| 329 | agc_35 = 0x11111516; | ||
| 330 | else if (low_gain == 2) | ||
| 331 | agc_35 = agc_37 = 0x08080808; | ||
| 332 | else if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80) | ||
| 333 | agc_35 = 0x10101014; | ||
| 334 | else | ||
| 335 | agc_35 = 0x11111116; | ||
| 336 | |||
| 321 | if (low_gain == 2) { | 337 | if (low_gain == 2) { |
| 322 | mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a990); | 338 | mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a990); |
| 323 | mt76_wr(dev, MT_BBP(AGC, 35), 0x08080808); | 339 | mt76_wr(dev, MT_BBP(AGC, 35), 0x08080808); |
| @@ -326,15 +342,13 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) | |||
| 326 | dev->cal.agc_gain_adjust = 0; | 342 | dev->cal.agc_gain_adjust = 0; |
| 327 | } else { | 343 | } else { |
| 328 | mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a991); | 344 | mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a991); |
| 329 | if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80) | ||
| 330 | mt76_wr(dev, MT_BBP(AGC, 35), 0x10101014); | ||
| 331 | else | ||
| 332 | mt76_wr(dev, MT_BBP(AGC, 35), 0x11111116); | ||
| 333 | mt76_wr(dev, MT_BBP(AGC, 37), 0x2121262C); | ||
| 334 | gain_delta = 0; | 345 | gain_delta = 0; |
| 335 | dev->cal.agc_gain_adjust = low_gain_delta; | 346 | dev->cal.agc_gain_adjust = low_gain_delta; |
| 336 | } | 347 | } |
| 337 | 348 | ||
| 349 | mt76_wr(dev, MT_BBP(AGC, 35), agc_35); | ||
| 350 | mt76_wr(dev, MT_BBP(AGC, 37), agc_37); | ||
| 351 | |||
| 338 | dev->cal.agc_gain_cur[0] = gain[0] - gain_delta; | 352 | dev->cal.agc_gain_cur[0] = gain[0] - gain_delta; |
| 339 | dev->cal.agc_gain_cur[1] = gain[1] - gain_delta; | 353 | dev->cal.agc_gain_cur[1] = gain[1] - gain_delta; |
| 340 | mt76x2_phy_set_gain_val(dev); | 354 | mt76x2_phy_set_gain_val(dev); |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index ddb6b2c48e01..ac0f13d46299 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | |||
| @@ -21,11 +21,10 @@ | |||
| 21 | #include "mt76x2u.h" | 21 | #include "mt76x2u.h" |
| 22 | 22 | ||
| 23 | static const struct usb_device_id mt76x2u_device_table[] = { | 23 | static const struct usb_device_id mt76x2u_device_table[] = { |
| 24 | { USB_DEVICE(0x0e8d, 0x7612) }, /* Alfa AWUS036ACM */ | ||
| 25 | { USB_DEVICE(0x0b05, 0x1833) }, /* Asus USB-AC54 */ | 24 | { USB_DEVICE(0x0b05, 0x1833) }, /* Asus USB-AC54 */ |
| 26 | { USB_DEVICE(0x0b05, 0x17eb) }, /* Asus USB-AC55 */ | 25 | { USB_DEVICE(0x0b05, 0x17eb) }, /* Asus USB-AC55 */ |
| 27 | { USB_DEVICE(0x0b05, 0x180b) }, /* Asus USB-N53 B1 */ | 26 | { USB_DEVICE(0x0b05, 0x180b) }, /* Asus USB-N53 B1 */ |
| 28 | { USB_DEVICE(0x0e8d, 0x7612) }, /* Aukey USB-AC1200 */ | 27 | { USB_DEVICE(0x0e8d, 0x7612) }, /* Aukey USBAC1200 - Alfa AWUS036ACM */ |
| 29 | { USB_DEVICE(0x057c, 0x8503) }, /* Avm FRITZ!WLAN AC860 */ | 28 | { USB_DEVICE(0x057c, 0x8503) }, /* Avm FRITZ!WLAN AC860 */ |
| 30 | { USB_DEVICE(0x7392, 0xb711) }, /* Edimax EW 7722 UAC */ | 29 | { USB_DEVICE(0x7392, 0xb711) }, /* Edimax EW 7722 UAC */ |
| 31 | { USB_DEVICE(0x0846, 0x9053) }, /* Netgear A6210 */ | 30 | { USB_DEVICE(0x0846, 0x9053) }, /* Netgear A6210 */ |
| @@ -66,6 +65,10 @@ static int mt76x2u_probe(struct usb_interface *intf, | |||
| 66 | 65 | ||
| 67 | mdev->rev = mt76_rr(dev, MT_ASIC_VERSION); | 66 | mdev->rev = mt76_rr(dev, MT_ASIC_VERSION); |
| 68 | dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev); | 67 | dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev); |
| 68 | if (!is_mt76x2(dev)) { | ||
| 69 | err = -ENODEV; | ||
| 70 | goto err; | ||
| 71 | } | ||
| 69 | 72 | ||
| 70 | err = mt76x2u_register_device(dev); | 73 | err = mt76x2u_register_device(dev); |
| 71 | if (err < 0) | 74 | if (err < 0) |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c index 5e84b4535cb1..3b82345756ea 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c | |||
| @@ -93,7 +93,6 @@ int mt76x2u_mac_reset(struct mt76x02_dev *dev) | |||
| 93 | mt76_wr(dev, MT_TX_LINK_CFG, 0x1020); | 93 | mt76_wr(dev, MT_TX_LINK_CFG, 0x1020); |
| 94 | mt76_wr(dev, MT_AUTO_RSP_CFG, 0x13); | 94 | mt76_wr(dev, MT_AUTO_RSP_CFG, 0x13); |
| 95 | mt76_wr(dev, MT_MAX_LEN_CFG, 0x2f00); | 95 | mt76_wr(dev, MT_MAX_LEN_CFG, 0x2f00); |
| 96 | mt76_wr(dev, MT_TX_RTS_CFG, 0x92b20); | ||
| 97 | 96 | ||
| 98 | mt76_wr(dev, MT_WMM_AIFSN, 0x2273); | 97 | mt76_wr(dev, MT_WMM_AIFSN, 0x2273); |
| 99 | mt76_wr(dev, MT_WMM_CWMIN, 0x2344); | 98 | mt76_wr(dev, MT_WMM_CWMIN, 0x2344); |
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 5a349fe3e576..2585df512335 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c | |||
| @@ -289,8 +289,11 @@ mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, | |||
| 289 | dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta); | 289 | dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta); |
| 290 | dev->queue_ops->kick(dev, q); | 290 | dev->queue_ops->kick(dev, q); |
| 291 | 291 | ||
| 292 | if (q->queued > q->ndesc - 8) | 292 | if (q->queued > q->ndesc - 8 && !q->stopped) { |
| 293 | ieee80211_stop_queue(dev->hw, skb_get_queue_mapping(skb)); | 293 | ieee80211_stop_queue(dev->hw, skb_get_queue_mapping(skb)); |
| 294 | q->stopped = true; | ||
| 295 | } | ||
| 296 | |||
| 294 | spin_unlock_bh(&q->lock); | 297 | spin_unlock_bh(&q->lock); |
| 295 | } | 298 | } |
| 296 | EXPORT_SYMBOL_GPL(mt76_tx); | 299 | EXPORT_SYMBOL_GPL(mt76_tx); |
| @@ -374,7 +377,10 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | |||
| 374 | if (last_skb) { | 377 | if (last_skb) { |
| 375 | mt76_queue_ps_skb(dev, sta, last_skb, true); | 378 | mt76_queue_ps_skb(dev, sta, last_skb, true); |
| 376 | dev->queue_ops->kick(dev, hwq); | 379 | dev->queue_ops->kick(dev, hwq); |
| 380 | } else { | ||
| 381 | ieee80211_sta_eosp(sta); | ||
| 377 | } | 382 | } |
| 383 | |||
| 378 | spin_unlock_bh(&hwq->lock); | 384 | spin_unlock_bh(&hwq->lock); |
| 379 | } | 385 | } |
| 380 | EXPORT_SYMBOL_GPL(mt76_release_buffered_frames); | 386 | EXPORT_SYMBOL_GPL(mt76_release_buffered_frames); |
| @@ -577,6 +583,9 @@ void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq) | |||
| 577 | struct mt76_txq *mtxq = (struct mt76_txq *) txq->drv_priv; | 583 | struct mt76_txq *mtxq = (struct mt76_txq *) txq->drv_priv; |
| 578 | struct mt76_queue *hwq = mtxq->hwq; | 584 | struct mt76_queue *hwq = mtxq->hwq; |
| 579 | 585 | ||
| 586 | if (!test_bit(MT76_STATE_RUNNING, &dev->state)) | ||
| 587 | return; | ||
| 588 | |||
| 580 | spin_lock_bh(&hwq->lock); | 589 | spin_lock_bh(&hwq->lock); |
| 581 | if (list_empty(&mtxq->list)) | 590 | if (list_empty(&mtxq->list)) |
| 582 | list_add_tail(&mtxq->list, &hwq->swq); | 591 | list_add_tail(&mtxq->list, &hwq->swq); |
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index ae6ada370597..4c1abd492405 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c | |||
| @@ -655,7 +655,11 @@ static void mt76u_tx_tasklet(unsigned long data) | |||
| 655 | spin_lock_bh(&q->lock); | 655 | spin_lock_bh(&q->lock); |
| 656 | } | 656 | } |
| 657 | mt76_txq_schedule(dev, q); | 657 | mt76_txq_schedule(dev, q); |
| 658 | wake = i < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8; | 658 | |
| 659 | wake = q->stopped && q->queued < q->ndesc - 8; | ||
| 660 | if (wake) | ||
| 661 | q->stopped = false; | ||
| 662 | |||
| 659 | if (!q->queued) | 663 | if (!q->queued) |
| 660 | wake_up(&dev->tx_wait); | 664 | wake_up(&dev->tx_wait); |
| 661 | 665 | ||
diff --git a/drivers/net/wireless/mediatek/mt7601u/usb.c b/drivers/net/wireless/mediatek/mt7601u/usb.c index d8b7863f7926..6ae7f14dc9bf 100644 --- a/drivers/net/wireless/mediatek/mt7601u/usb.c +++ b/drivers/net/wireless/mediatek/mt7601u/usb.c | |||
| @@ -303,6 +303,10 @@ static int mt7601u_probe(struct usb_interface *usb_intf, | |||
| 303 | mac_rev = mt7601u_rr(dev, MT_MAC_CSR0); | 303 | mac_rev = mt7601u_rr(dev, MT_MAC_CSR0); |
| 304 | dev_info(dev->dev, "ASIC revision: %08x MAC revision: %08x\n", | 304 | dev_info(dev->dev, "ASIC revision: %08x MAC revision: %08x\n", |
| 305 | asic_rev, mac_rev); | 305 | asic_rev, mac_rev); |
| 306 | if ((asic_rev >> 16) != 0x7601) { | ||
| 307 | ret = -ENODEV; | ||
| 308 | goto err; | ||
| 309 | } | ||
| 306 | 310 | ||
| 307 | /* Note: vendor driver skips this check for MT7601U */ | 311 | /* Note: vendor driver skips this check for MT7601U */ |
| 308 | if (!(mt7601u_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL)) | 312 | if (!(mt7601u_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL)) |
diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c index 56dd83a45e55..5484a46dafda 100644 --- a/drivers/parport/daisy.c +++ b/drivers/parport/daisy.c | |||
| @@ -213,12 +213,10 @@ void parport_daisy_fini(struct parport *port) | |||
| 213 | struct pardevice *parport_open(int devnum, const char *name) | 213 | struct pardevice *parport_open(int devnum, const char *name) |
| 214 | { | 214 | { |
| 215 | struct daisydev *p = topology; | 215 | struct daisydev *p = topology; |
| 216 | struct pardev_cb par_cb; | ||
| 217 | struct parport *port; | 216 | struct parport *port; |
| 218 | struct pardevice *dev; | 217 | struct pardevice *dev; |
| 219 | int daisy; | 218 | int daisy; |
| 220 | 219 | ||
| 221 | memset(&par_cb, 0, sizeof(par_cb)); | ||
| 222 | spin_lock(&topology_lock); | 220 | spin_lock(&topology_lock); |
| 223 | while (p && p->devnum != devnum) | 221 | while (p && p->devnum != devnum) |
| 224 | p = p->next; | 222 | p = p->next; |
| @@ -232,7 +230,7 @@ struct pardevice *parport_open(int devnum, const char *name) | |||
| 232 | port = parport_get_port(p->port); | 230 | port = parport_get_port(p->port); |
| 233 | spin_unlock(&topology_lock); | 231 | spin_unlock(&topology_lock); |
| 234 | 232 | ||
| 235 | dev = parport_register_dev_model(port, name, &par_cb, devnum); | 233 | dev = parport_register_device(port, name, NULL, NULL, NULL, 0, NULL); |
| 236 | parport_put_port(port); | 234 | parport_put_port(port); |
| 237 | if (!dev) | 235 | if (!dev) |
| 238 | return NULL; | 236 | return NULL; |
| @@ -482,31 +480,3 @@ static int assign_addrs(struct parport *port) | |||
| 482 | kfree(deviceid); | 480 | kfree(deviceid); |
| 483 | return detected; | 481 | return detected; |
| 484 | } | 482 | } |
| 485 | |||
| 486 | static int daisy_drv_probe(struct pardevice *par_dev) | ||
| 487 | { | ||
| 488 | struct device_driver *drv = par_dev->dev.driver; | ||
| 489 | |||
| 490 | if (strcmp(drv->name, "daisy_drv")) | ||
| 491 | return -ENODEV; | ||
| 492 | if (strcmp(par_dev->name, daisy_dev_name)) | ||
| 493 | return -ENODEV; | ||
| 494 | |||
| 495 | return 0; | ||
| 496 | } | ||
| 497 | |||
| 498 | static struct parport_driver daisy_driver = { | ||
| 499 | .name = "daisy_drv", | ||
| 500 | .probe = daisy_drv_probe, | ||
| 501 | .devmodel = true, | ||
| 502 | }; | ||
| 503 | |||
| 504 | int daisy_drv_init(void) | ||
| 505 | { | ||
| 506 | return parport_register_driver(&daisy_driver); | ||
| 507 | } | ||
| 508 | |||
| 509 | void daisy_drv_exit(void) | ||
| 510 | { | ||
| 511 | parport_unregister_driver(&daisy_driver); | ||
| 512 | } | ||
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c index e5e6a463a941..e035174ba205 100644 --- a/drivers/parport/probe.c +++ b/drivers/parport/probe.c | |||
| @@ -257,7 +257,7 @@ static ssize_t parport_read_device_id (struct parport *port, char *buffer, | |||
| 257 | ssize_t parport_device_id (int devnum, char *buffer, size_t count) | 257 | ssize_t parport_device_id (int devnum, char *buffer, size_t count) |
| 258 | { | 258 | { |
| 259 | ssize_t retval = -ENXIO; | 259 | ssize_t retval = -ENXIO; |
| 260 | struct pardevice *dev = parport_open(devnum, daisy_dev_name); | 260 | struct pardevice *dev = parport_open (devnum, "Device ID probe"); |
| 261 | if (!dev) | 261 | if (!dev) |
| 262 | return -ENXIO; | 262 | return -ENXIO; |
| 263 | 263 | ||
diff --git a/drivers/parport/share.c b/drivers/parport/share.c index 0171b8dbcdcd..5dc53d420ca8 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c | |||
| @@ -137,19 +137,11 @@ static struct bus_type parport_bus_type = { | |||
| 137 | 137 | ||
| 138 | int parport_bus_init(void) | 138 | int parport_bus_init(void) |
| 139 | { | 139 | { |
| 140 | int retval; | 140 | return bus_register(&parport_bus_type); |
| 141 | |||
| 142 | retval = bus_register(&parport_bus_type); | ||
| 143 | if (retval) | ||
| 144 | return retval; | ||
| 145 | daisy_drv_init(); | ||
| 146 | |||
| 147 | return 0; | ||
| 148 | } | 141 | } |
| 149 | 142 | ||
| 150 | void parport_bus_exit(void) | 143 | void parport_bus_exit(void) |
| 151 | { | 144 | { |
| 152 | daisy_drv_exit(); | ||
| 153 | bus_unregister(&parport_bus_type); | 145 | bus_unregister(&parport_bus_type); |
| 154 | } | 146 | } |
| 155 | 147 | ||
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 197b0f5b63e7..44bd6f04c145 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
| @@ -1150,13 +1150,16 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *q, | |||
| 1150 | 1150 | ||
| 1151 | static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf) | 1151 | static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf) |
| 1152 | { | 1152 | { |
| 1153 | struct sk_buff *skb; | ||
| 1154 | |||
| 1153 | /* release may never happen from within CQ tasklet scope */ | 1155 | /* release may never happen from within CQ tasklet scope */ |
| 1154 | WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ); | 1156 | WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ); |
| 1155 | 1157 | ||
| 1156 | if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING) | 1158 | if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING) |
| 1157 | qeth_notify_skbs(buf->q, buf, TX_NOTIFY_GENERALERROR); | 1159 | qeth_notify_skbs(buf->q, buf, TX_NOTIFY_GENERALERROR); |
| 1158 | 1160 | ||
| 1159 | __skb_queue_purge(&buf->skb_list); | 1161 | while ((skb = __skb_dequeue(&buf->skb_list)) != NULL) |
| 1162 | consume_skb(skb); | ||
| 1160 | } | 1163 | } |
| 1161 | 1164 | ||
| 1162 | static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, | 1165 | static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, |
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 8efb2e8ff8f4..c3067fd3bd9e 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c | |||
| @@ -629,8 +629,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, | |||
| 629 | } /* else fall through */ | 629 | } /* else fall through */ |
| 630 | 630 | ||
| 631 | QETH_TXQ_STAT_INC(queue, tx_dropped); | 631 | QETH_TXQ_STAT_INC(queue, tx_dropped); |
| 632 | QETH_TXQ_STAT_INC(queue, tx_errors); | 632 | kfree_skb(skb); |
| 633 | dev_kfree_skb_any(skb); | ||
| 634 | netif_wake_queue(dev); | 633 | netif_wake_queue(dev); |
| 635 | return NETDEV_TX_OK; | 634 | return NETDEV_TX_OK; |
| 636 | } | 635 | } |
| @@ -645,6 +644,8 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev) | |||
| 645 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 644 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
| 646 | int rc; | 645 | int rc; |
| 647 | 646 | ||
| 647 | qeth_l2_vnicc_set_defaults(card); | ||
| 648 | |||
| 648 | if (gdev->dev.type == &qeth_generic_devtype) { | 649 | if (gdev->dev.type == &qeth_generic_devtype) { |
| 649 | rc = qeth_l2_create_device_attributes(&gdev->dev); | 650 | rc = qeth_l2_create_device_attributes(&gdev->dev); |
| 650 | if (rc) | 651 | if (rc) |
| @@ -652,8 +653,6 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev) | |||
| 652 | } | 653 | } |
| 653 | 654 | ||
| 654 | hash_init(card->mac_htable); | 655 | hash_init(card->mac_htable); |
| 655 | card->info.hwtrap = 0; | ||
| 656 | qeth_l2_vnicc_set_defaults(card); | ||
| 657 | return 0; | 656 | return 0; |
| 658 | } | 657 | } |
| 659 | 658 | ||
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 7e68d9d16859..53712cf26406 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
| @@ -2096,8 +2096,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, | |||
| 2096 | 2096 | ||
| 2097 | tx_drop: | 2097 | tx_drop: |
| 2098 | QETH_TXQ_STAT_INC(queue, tx_dropped); | 2098 | QETH_TXQ_STAT_INC(queue, tx_dropped); |
| 2099 | QETH_TXQ_STAT_INC(queue, tx_errors); | 2099 | kfree_skb(skb); |
| 2100 | dev_kfree_skb_any(skb); | ||
| 2101 | netif_wake_queue(dev); | 2100 | netif_wake_queue(dev); |
| 2102 | return NETDEV_TX_OK; | 2101 | return NETDEV_TX_OK; |
| 2103 | } | 2102 | } |
| @@ -2253,14 +2252,15 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev) | |||
| 2253 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 2252 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
| 2254 | int rc; | 2253 | int rc; |
| 2255 | 2254 | ||
| 2255 | hash_init(card->ip_htable); | ||
| 2256 | |||
| 2256 | if (gdev->dev.type == &qeth_generic_devtype) { | 2257 | if (gdev->dev.type == &qeth_generic_devtype) { |
| 2257 | rc = qeth_l3_create_device_attributes(&gdev->dev); | 2258 | rc = qeth_l3_create_device_attributes(&gdev->dev); |
| 2258 | if (rc) | 2259 | if (rc) |
| 2259 | return rc; | 2260 | return rc; |
| 2260 | } | 2261 | } |
| 2261 | hash_init(card->ip_htable); | 2262 | |
| 2262 | hash_init(card->ip_mc_htable); | 2263 | hash_init(card->ip_mc_htable); |
| 2263 | card->info.hwtrap = 0; | ||
| 2264 | return 0; | 2264 | return 0; |
| 2265 | } | 2265 | } |
| 2266 | 2266 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 1d49694e6ae3..c5880329ae37 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -6174,7 +6174,7 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info, | |||
| 6174 | * | 6174 | * |
| 6175 | * This is overestimating in most cases. | 6175 | * This is overestimating in most cases. |
| 6176 | */ | 6176 | */ |
| 6177 | qgroup_rsv_size = outstanding_extents * fs_info->nodesize; | 6177 | qgroup_rsv_size = (u64)outstanding_extents * fs_info->nodesize; |
| 6178 | 6178 | ||
| 6179 | spin_lock(&block_rsv->lock); | 6179 | spin_lock(&block_rsv->lock); |
| 6180 | block_rsv->size = reserve_size; | 6180 | block_rsv->size = reserve_size; |
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index eb680b715dd6..e659d9d61107 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
| @@ -1922,8 +1922,8 @@ static int qgroup_trace_new_subtree_blocks(struct btrfs_trans_handle* trans, | |||
| 1922 | int i; | 1922 | int i; |
| 1923 | 1923 | ||
| 1924 | /* Level sanity check */ | 1924 | /* Level sanity check */ |
| 1925 | if (cur_level < 0 || cur_level >= BTRFS_MAX_LEVEL || | 1925 | if (cur_level < 0 || cur_level >= BTRFS_MAX_LEVEL - 1 || |
| 1926 | root_level < 0 || root_level >= BTRFS_MAX_LEVEL || | 1926 | root_level < 0 || root_level >= BTRFS_MAX_LEVEL - 1 || |
| 1927 | root_level < cur_level) { | 1927 | root_level < cur_level) { |
| 1928 | btrfs_err_rl(fs_info, | 1928 | btrfs_err_rl(fs_info, |
| 1929 | "%s: bad levels, cur_level=%d root_level=%d", | 1929 | "%s: bad levels, cur_level=%d root_level=%d", |
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index 1869ba8e5981..67a6f7d47402 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c | |||
| @@ -2430,8 +2430,9 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio, | |||
| 2430 | bitmap_clear(rbio->dbitmap, pagenr, 1); | 2430 | bitmap_clear(rbio->dbitmap, pagenr, 1); |
| 2431 | kunmap(p); | 2431 | kunmap(p); |
| 2432 | 2432 | ||
| 2433 | for (stripe = 0; stripe < rbio->real_stripes; stripe++) | 2433 | for (stripe = 0; stripe < nr_data; stripe++) |
| 2434 | kunmap(page_in_rbio(rbio, stripe, pagenr, 0)); | 2434 | kunmap(page_in_rbio(rbio, stripe, pagenr, 0)); |
| 2435 | kunmap(p_page); | ||
| 2435 | } | 2436 | } |
| 2436 | 2437 | ||
| 2437 | __free_page(p_page); | 2438 | __free_page(p_page); |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index acdad6d658f5..e4e665f422fc 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -1886,8 +1886,10 @@ static void btrfs_cleanup_pending_block_groups(struct btrfs_trans_handle *trans) | |||
| 1886 | } | 1886 | } |
| 1887 | } | 1887 | } |
| 1888 | 1888 | ||
| 1889 | static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info) | 1889 | static inline int btrfs_start_delalloc_flush(struct btrfs_trans_handle *trans) |
| 1890 | { | 1890 | { |
| 1891 | struct btrfs_fs_info *fs_info = trans->fs_info; | ||
| 1892 | |||
| 1891 | /* | 1893 | /* |
| 1892 | * We use writeback_inodes_sb here because if we used | 1894 | * We use writeback_inodes_sb here because if we used |
| 1893 | * btrfs_start_delalloc_roots we would deadlock with fs freeze. | 1895 | * btrfs_start_delalloc_roots we would deadlock with fs freeze. |
| @@ -1897,15 +1899,50 @@ static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info) | |||
| 1897 | * from already being in a transaction and our join_transaction doesn't | 1899 | * from already being in a transaction and our join_transaction doesn't |
| 1898 | * have to re-take the fs freeze lock. | 1900 | * have to re-take the fs freeze lock. |
| 1899 | */ | 1901 | */ |
| 1900 | if (btrfs_test_opt(fs_info, FLUSHONCOMMIT)) | 1902 | if (btrfs_test_opt(fs_info, FLUSHONCOMMIT)) { |
| 1901 | writeback_inodes_sb(fs_info->sb, WB_REASON_SYNC); | 1903 | writeback_inodes_sb(fs_info->sb, WB_REASON_SYNC); |
| 1904 | } else { | ||
| 1905 | struct btrfs_pending_snapshot *pending; | ||
| 1906 | struct list_head *head = &trans->transaction->pending_snapshots; | ||
| 1907 | |||
| 1908 | /* | ||
| 1909 | * Flush dellaloc for any root that is going to be snapshotted. | ||
| 1910 | * This is done to avoid a corrupted version of files, in the | ||
| 1911 | * snapshots, that had both buffered and direct IO writes (even | ||
| 1912 | * if they were done sequentially) due to an unordered update of | ||
| 1913 | * the inode's size on disk. | ||
| 1914 | */ | ||
| 1915 | list_for_each_entry(pending, head, list) { | ||
| 1916 | int ret; | ||
| 1917 | |||
| 1918 | ret = btrfs_start_delalloc_snapshot(pending->root); | ||
| 1919 | if (ret) | ||
| 1920 | return ret; | ||
| 1921 | } | ||
| 1922 | } | ||
| 1902 | return 0; | 1923 | return 0; |
| 1903 | } | 1924 | } |
| 1904 | 1925 | ||
| 1905 | static inline void btrfs_wait_delalloc_flush(struct btrfs_fs_info *fs_info) | 1926 | static inline void btrfs_wait_delalloc_flush(struct btrfs_trans_handle *trans) |
| 1906 | { | 1927 | { |
| 1907 | if (btrfs_test_opt(fs_info, FLUSHONCOMMIT)) | 1928 | struct btrfs_fs_info *fs_info = trans->fs_info; |
| 1929 | |||
| 1930 | if (btrfs_test_opt(fs_info, FLUSHONCOMMIT)) { | ||
| 1908 | btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1); | 1931 | btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1); |
| 1932 | } else { | ||
| 1933 | struct btrfs_pending_snapshot *pending; | ||
| 1934 | struct list_head *head = &trans->transaction->pending_snapshots; | ||
| 1935 | |||
| 1936 | /* | ||
| 1937 | * Wait for any dellaloc that we started previously for the roots | ||
| 1938 | * that are going to be snapshotted. This is to avoid a corrupted | ||
| 1939 | * version of files in the snapshots that had both buffered and | ||
| 1940 | * direct IO writes (even if they were done sequentially). | ||
| 1941 | */ | ||
| 1942 | list_for_each_entry(pending, head, list) | ||
| 1943 | btrfs_wait_ordered_extents(pending->root, | ||
| 1944 | U64_MAX, 0, U64_MAX); | ||
| 1945 | } | ||
| 1909 | } | 1946 | } |
| 1910 | 1947 | ||
| 1911 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans) | 1948 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans) |
| @@ -2023,7 +2060,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) | |||
| 2023 | 2060 | ||
| 2024 | extwriter_counter_dec(cur_trans, trans->type); | 2061 | extwriter_counter_dec(cur_trans, trans->type); |
| 2025 | 2062 | ||
| 2026 | ret = btrfs_start_delalloc_flush(fs_info); | 2063 | ret = btrfs_start_delalloc_flush(trans); |
| 2027 | if (ret) | 2064 | if (ret) |
| 2028 | goto cleanup_transaction; | 2065 | goto cleanup_transaction; |
| 2029 | 2066 | ||
| @@ -2039,7 +2076,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) | |||
| 2039 | if (ret) | 2076 | if (ret) |
| 2040 | goto cleanup_transaction; | 2077 | goto cleanup_transaction; |
| 2041 | 2078 | ||
| 2042 | btrfs_wait_delalloc_flush(fs_info); | 2079 | btrfs_wait_delalloc_flush(trans); |
| 2043 | 2080 | ||
| 2044 | btrfs_scrub_pause(fs_info); | 2081 | btrfs_scrub_pause(fs_info); |
| 2045 | /* | 2082 | /* |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index f06454a55e00..561884f60d35 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -3578,9 +3578,16 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans, | |||
| 3578 | } | 3578 | } |
| 3579 | btrfs_release_path(path); | 3579 | btrfs_release_path(path); |
| 3580 | 3580 | ||
| 3581 | /* find the first key from this transaction again */ | 3581 | /* |
| 3582 | * Find the first key from this transaction again. See the note for | ||
| 3583 | * log_new_dir_dentries, if we're logging a directory recursively we | ||
| 3584 | * won't be holding its i_mutex, which means we can modify the directory | ||
| 3585 | * while we're logging it. If we remove an entry between our first | ||
| 3586 | * search and this search we'll not find the key again and can just | ||
| 3587 | * bail. | ||
| 3588 | */ | ||
| 3582 | ret = btrfs_search_slot(NULL, root, &min_key, path, 0, 0); | 3589 | ret = btrfs_search_slot(NULL, root, &min_key, path, 0, 0); |
| 3583 | if (WARN_ON(ret != 0)) | 3590 | if (ret != 0) |
| 3584 | goto done; | 3591 | goto done; |
| 3585 | 3592 | ||
| 3586 | /* | 3593 | /* |
| @@ -4544,6 +4551,19 @@ static int logged_inode_size(struct btrfs_root *log, struct btrfs_inode *inode, | |||
| 4544 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], | 4551 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], |
| 4545 | struct btrfs_inode_item); | 4552 | struct btrfs_inode_item); |
| 4546 | *size_ret = btrfs_inode_size(path->nodes[0], item); | 4553 | *size_ret = btrfs_inode_size(path->nodes[0], item); |
| 4554 | /* | ||
| 4555 | * If the in-memory inode's i_size is smaller then the inode | ||
| 4556 | * size stored in the btree, return the inode's i_size, so | ||
| 4557 | * that we get a correct inode size after replaying the log | ||
| 4558 | * when before a power failure we had a shrinking truncate | ||
| 4559 | * followed by addition of a new name (rename / new hard link). | ||
| 4560 | * Otherwise return the inode size from the btree, to avoid | ||
| 4561 | * data loss when replaying a log due to previously doing a | ||
| 4562 | * write that expands the inode's size and logging a new name | ||
| 4563 | * immediately after. | ||
| 4564 | */ | ||
| 4565 | if (*size_ret > inode->vfs_inode.i_size) | ||
| 4566 | *size_ret = inode->vfs_inode.i_size; | ||
| 4547 | } | 4567 | } |
| 4548 | 4568 | ||
| 4549 | btrfs_release_path(path); | 4569 | btrfs_release_path(path); |
| @@ -4705,15 +4725,8 @@ static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans, | |||
| 4705 | struct btrfs_file_extent_item); | 4725 | struct btrfs_file_extent_item); |
| 4706 | 4726 | ||
| 4707 | if (btrfs_file_extent_type(leaf, extent) == | 4727 | if (btrfs_file_extent_type(leaf, extent) == |
| 4708 | BTRFS_FILE_EXTENT_INLINE) { | 4728 | BTRFS_FILE_EXTENT_INLINE) |
| 4709 | len = btrfs_file_extent_ram_bytes(leaf, extent); | ||
| 4710 | ASSERT(len == i_size || | ||
| 4711 | (len == fs_info->sectorsize && | ||
| 4712 | btrfs_file_extent_compression(leaf, extent) != | ||
| 4713 | BTRFS_COMPRESS_NONE) || | ||
| 4714 | (len < i_size && i_size < fs_info->sectorsize)); | ||
| 4715 | return 0; | 4729 | return 0; |
| 4716 | } | ||
| 4717 | 4730 | ||
| 4718 | len = btrfs_file_extent_num_bytes(leaf, extent); | 4731 | len = btrfs_file_extent_num_bytes(leaf, extent); |
| 4719 | /* Last extent goes beyond i_size, no need to log a hole. */ | 4732 | /* Last extent goes beyond i_size, no need to log a hole. */ |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 9024eee889b9..db934ceae9c1 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -6407,7 +6407,7 @@ static void btrfs_end_bio(struct bio *bio) | |||
| 6407 | if (bio_op(bio) == REQ_OP_WRITE) | 6407 | if (bio_op(bio) == REQ_OP_WRITE) |
| 6408 | btrfs_dev_stat_inc_and_print(dev, | 6408 | btrfs_dev_stat_inc_and_print(dev, |
| 6409 | BTRFS_DEV_STAT_WRITE_ERRS); | 6409 | BTRFS_DEV_STAT_WRITE_ERRS); |
| 6410 | else | 6410 | else if (!(bio->bi_opf & REQ_RAHEAD)) |
| 6411 | btrfs_dev_stat_inc_and_print(dev, | 6411 | btrfs_dev_stat_inc_and_print(dev, |
| 6412 | BTRFS_DEV_STAT_READ_ERRS); | 6412 | BTRFS_DEV_STAT_READ_ERRS); |
| 6413 | if (bio->bi_opf & REQ_PREFLUSH) | 6413 | if (bio->bi_opf & REQ_PREFLUSH) |
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 93fb7cf0b92b..f0b5c987d6ae 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
| @@ -290,12 +290,11 @@ void nlmclnt_release_host(struct nlm_host *host) | |||
| 290 | 290 | ||
| 291 | WARN_ON_ONCE(host->h_server); | 291 | WARN_ON_ONCE(host->h_server); |
| 292 | 292 | ||
| 293 | if (refcount_dec_and_test(&host->h_count)) { | 293 | if (refcount_dec_and_mutex_lock(&host->h_count, &nlm_host_mutex)) { |
| 294 | WARN_ON_ONCE(!list_empty(&host->h_lockowners)); | 294 | WARN_ON_ONCE(!list_empty(&host->h_lockowners)); |
| 295 | WARN_ON_ONCE(!list_empty(&host->h_granted)); | 295 | WARN_ON_ONCE(!list_empty(&host->h_granted)); |
| 296 | WARN_ON_ONCE(!list_empty(&host->h_reclaim)); | 296 | WARN_ON_ONCE(!list_empty(&host->h_reclaim)); |
| 297 | 297 | ||
| 298 | mutex_lock(&nlm_host_mutex); | ||
| 299 | nlm_destroy_host_locked(host); | 298 | nlm_destroy_host_locked(host); |
| 300 | mutex_unlock(&nlm_host_mutex); | 299 | mutex_unlock(&nlm_host_mutex); |
| 301 | } | 300 | } |
diff --git a/fs/locks.c b/fs/locks.c index eaa1cfaf73b0..71d0c6c2aac5 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -1160,6 +1160,11 @@ static int posix_lock_inode(struct inode *inode, struct file_lock *request, | |||
| 1160 | */ | 1160 | */ |
| 1161 | error = -EDEADLK; | 1161 | error = -EDEADLK; |
| 1162 | spin_lock(&blocked_lock_lock); | 1162 | spin_lock(&blocked_lock_lock); |
| 1163 | /* | ||
| 1164 | * Ensure that we don't find any locks blocked on this | ||
| 1165 | * request during deadlock detection. | ||
| 1166 | */ | ||
| 1167 | __locks_wake_up_blocks(request); | ||
| 1163 | if (likely(!posix_locks_deadlock(request, fl))) { | 1168 | if (likely(!posix_locks_deadlock(request, fl))) { |
| 1164 | error = FILE_LOCK_DEFERRED; | 1169 | error = FILE_LOCK_DEFERRED; |
| 1165 | __locks_insert_block(fl, request, | 1170 | __locks_insert_block(fl, request, |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index fb1cf1a4bda2..90d71fda65ce 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -453,7 +453,7 @@ void nfs_init_timeout_values(struct rpc_timeout *to, int proto, | |||
| 453 | case XPRT_TRANSPORT_RDMA: | 453 | case XPRT_TRANSPORT_RDMA: |
| 454 | if (retrans == NFS_UNSPEC_RETRANS) | 454 | if (retrans == NFS_UNSPEC_RETRANS) |
| 455 | to->to_retries = NFS_DEF_TCP_RETRANS; | 455 | to->to_retries = NFS_DEF_TCP_RETRANS; |
| 456 | if (timeo == NFS_UNSPEC_TIMEO || to->to_retries == 0) | 456 | if (timeo == NFS_UNSPEC_TIMEO || to->to_initval == 0) |
| 457 | to->to_initval = NFS_DEF_TCP_TIMEO * HZ / 10; | 457 | to->to_initval = NFS_DEF_TCP_TIMEO * HZ / 10; |
| 458 | if (to->to_initval > NFS_MAX_TCP_TIMEOUT) | 458 | if (to->to_initval > NFS_MAX_TCP_TIMEOUT) |
| 459 | to->to_initval = NFS_MAX_TCP_TIMEOUT; | 459 | to->to_initval = NFS_MAX_TCP_TIMEOUT; |
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index f9264e1922a2..6673d4ff5a2a 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c | |||
| @@ -1289,6 +1289,7 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg, | |||
| 1289 | static int ff_layout_read_done_cb(struct rpc_task *task, | 1289 | static int ff_layout_read_done_cb(struct rpc_task *task, |
| 1290 | struct nfs_pgio_header *hdr) | 1290 | struct nfs_pgio_header *hdr) |
| 1291 | { | 1291 | { |
| 1292 | int new_idx = hdr->pgio_mirror_idx; | ||
| 1292 | int err; | 1293 | int err; |
| 1293 | 1294 | ||
| 1294 | trace_nfs4_pnfs_read(hdr, task->tk_status); | 1295 | trace_nfs4_pnfs_read(hdr, task->tk_status); |
| @@ -1307,7 +1308,7 @@ static int ff_layout_read_done_cb(struct rpc_task *task, | |||
| 1307 | case -NFS4ERR_RESET_TO_PNFS: | 1308 | case -NFS4ERR_RESET_TO_PNFS: |
| 1308 | if (ff_layout_choose_best_ds_for_read(hdr->lseg, | 1309 | if (ff_layout_choose_best_ds_for_read(hdr->lseg, |
| 1309 | hdr->pgio_mirror_idx + 1, | 1310 | hdr->pgio_mirror_idx + 1, |
| 1310 | &hdr->pgio_mirror_idx)) | 1311 | &new_idx)) |
| 1311 | goto out_layouterror; | 1312 | goto out_layouterror; |
| 1312 | set_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags); | 1313 | set_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags); |
| 1313 | return task->tk_status; | 1314 | return task->tk_status; |
| @@ -1320,7 +1321,9 @@ static int ff_layout_read_done_cb(struct rpc_task *task, | |||
| 1320 | 1321 | ||
| 1321 | return 0; | 1322 | return 0; |
| 1322 | out_layouterror: | 1323 | out_layouterror: |
| 1324 | ff_layout_read_record_layoutstats_done(task, hdr); | ||
| 1323 | ff_layout_send_layouterror(hdr->lseg); | 1325 | ff_layout_send_layouterror(hdr->lseg); |
| 1326 | hdr->pgio_mirror_idx = new_idx; | ||
| 1324 | out_eagain: | 1327 | out_eagain: |
| 1325 | rpc_restart_call_prepare(task); | 1328 | rpc_restart_call_prepare(task); |
| 1326 | return -EAGAIN; | 1329 | return -EAGAIN; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4dbb0ee23432..741ff8c9c6ed 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -2933,7 +2933,8 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, | |||
| 2933 | } | 2933 | } |
| 2934 | 2934 | ||
| 2935 | out: | 2935 | out: |
| 2936 | nfs4_sequence_free_slot(&opendata->o_res.seq_res); | 2936 | if (!opendata->cancelled) |
| 2937 | nfs4_sequence_free_slot(&opendata->o_res.seq_res); | ||
| 2937 | return ret; | 2938 | return ret; |
| 2938 | } | 2939 | } |
| 2939 | 2940 | ||
| @@ -6301,7 +6302,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, | |||
| 6301 | p->arg.seqid = seqid; | 6302 | p->arg.seqid = seqid; |
| 6302 | p->res.seqid = seqid; | 6303 | p->res.seqid = seqid; |
| 6303 | p->lsp = lsp; | 6304 | p->lsp = lsp; |
| 6304 | refcount_inc(&lsp->ls_count); | ||
| 6305 | /* Ensure we don't close file until we're done freeing locks! */ | 6305 | /* Ensure we don't close file until we're done freeing locks! */ |
| 6306 | p->ctx = get_nfs_open_context(ctx); | 6306 | p->ctx = get_nfs_open_context(ctx); |
| 6307 | p->l_ctx = nfs_get_lock_context(ctx); | 6307 | p->l_ctx = nfs_get_lock_context(ctx); |
| @@ -6526,7 +6526,6 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | |||
| 6526 | p->res.lock_seqid = p->arg.lock_seqid; | 6526 | p->res.lock_seqid = p->arg.lock_seqid; |
| 6527 | p->lsp = lsp; | 6527 | p->lsp = lsp; |
| 6528 | p->server = server; | 6528 | p->server = server; |
| 6529 | refcount_inc(&lsp->ls_count); | ||
| 6530 | p->ctx = get_nfs_open_context(ctx); | 6529 | p->ctx = get_nfs_open_context(ctx); |
| 6531 | locks_init_lock(&p->fl); | 6530 | locks_init_lock(&p->fl); |
| 6532 | locks_copy_lock(&p->fl, fl); | 6531 | locks_copy_lock(&p->fl, fl); |
diff --git a/include/linux/atalk.h b/include/linux/atalk.h index d5cfc0b15b76..f6034ba774be 100644 --- a/include/linux/atalk.h +++ b/include/linux/atalk.h | |||
| @@ -108,7 +108,7 @@ static __inline__ struct elapaarp *aarp_hdr(struct sk_buff *skb) | |||
| 108 | #define AARP_RESOLVE_TIME (10 * HZ) | 108 | #define AARP_RESOLVE_TIME (10 * HZ) |
| 109 | 109 | ||
| 110 | extern struct datalink_proto *ddp_dl, *aarp_dl; | 110 | extern struct datalink_proto *ddp_dl, *aarp_dl; |
| 111 | extern void aarp_proto_init(void); | 111 | extern int aarp_proto_init(void); |
| 112 | 112 | ||
| 113 | /* Inter module exports */ | 113 | /* Inter module exports */ |
| 114 | 114 | ||
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index a2132e09dc1c..f02367faa58d 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h | |||
| @@ -193,7 +193,6 @@ enum bpf_arg_type { | |||
| 193 | 193 | ||
| 194 | ARG_PTR_TO_CTX, /* pointer to context */ | 194 | ARG_PTR_TO_CTX, /* pointer to context */ |
| 195 | ARG_ANYTHING, /* any (initialized) argument is ok */ | 195 | ARG_ANYTHING, /* any (initialized) argument is ok */ |
| 196 | ARG_PTR_TO_SOCKET, /* pointer to bpf_sock */ | ||
| 197 | ARG_PTR_TO_SPIN_LOCK, /* pointer to bpf_spin_lock */ | 196 | ARG_PTR_TO_SPIN_LOCK, /* pointer to bpf_spin_lock */ |
| 198 | ARG_PTR_TO_SOCK_COMMON, /* pointer to sock_common */ | 197 | ARG_PTR_TO_SOCK_COMMON, /* pointer to sock_common */ |
| 199 | }; | 198 | }; |
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index 69f7a3449eda..7d8228d1c898 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h | |||
| @@ -66,6 +66,46 @@ struct bpf_reg_state { | |||
| 66 | * same reference to the socket, to determine proper reference freeing. | 66 | * same reference to the socket, to determine proper reference freeing. |
| 67 | */ | 67 | */ |
| 68 | u32 id; | 68 | u32 id; |
| 69 | /* PTR_TO_SOCKET and PTR_TO_TCP_SOCK could be a ptr returned | ||
| 70 | * from a pointer-cast helper, bpf_sk_fullsock() and | ||
| 71 | * bpf_tcp_sock(). | ||
| 72 | * | ||
| 73 | * Consider the following where "sk" is a reference counted | ||
| 74 | * pointer returned from "sk = bpf_sk_lookup_tcp();": | ||
| 75 | * | ||
| 76 | * 1: sk = bpf_sk_lookup_tcp(); | ||
| 77 | * 2: if (!sk) { return 0; } | ||
| 78 | * 3: fullsock = bpf_sk_fullsock(sk); | ||
| 79 | * 4: if (!fullsock) { bpf_sk_release(sk); return 0; } | ||
| 80 | * 5: tp = bpf_tcp_sock(fullsock); | ||
| 81 | * 6: if (!tp) { bpf_sk_release(sk); return 0; } | ||
| 82 | * 7: bpf_sk_release(sk); | ||
| 83 | * 8: snd_cwnd = tp->snd_cwnd; // verifier will complain | ||
| 84 | * | ||
| 85 | * After bpf_sk_release(sk) at line 7, both "fullsock" ptr and | ||
| 86 | * "tp" ptr should be invalidated also. In order to do that, | ||
| 87 | * the reg holding "fullsock" and "sk" need to remember | ||
| 88 | * the original refcounted ptr id (i.e. sk_reg->id) in ref_obj_id | ||
| 89 | * such that the verifier can reset all regs which have | ||
| 90 | * ref_obj_id matching the sk_reg->id. | ||
| 91 | * | ||
| 92 | * sk_reg->ref_obj_id is set to sk_reg->id at line 1. | ||
| 93 | * sk_reg->id will stay as NULL-marking purpose only. | ||
| 94 | * After NULL-marking is done, sk_reg->id can be reset to 0. | ||
| 95 | * | ||
| 96 | * After "fullsock = bpf_sk_fullsock(sk);" at line 3, | ||
| 97 | * fullsock_reg->ref_obj_id is set to sk_reg->ref_obj_id. | ||
| 98 | * | ||
| 99 | * After "tp = bpf_tcp_sock(fullsock);" at line 5, | ||
| 100 | * tp_reg->ref_obj_id is set to fullsock_reg->ref_obj_id | ||
| 101 | * which is the same as sk_reg->ref_obj_id. | ||
| 102 | * | ||
| 103 | * From the verifier perspective, if sk, fullsock and tp | ||
| 104 | * are not NULL, they are the same ptr with different | ||
| 105 | * reg->type. In particular, bpf_sk_release(tp) is also | ||
| 106 | * allowed and has the same effect as bpf_sk_release(sk). | ||
| 107 | */ | ||
| 108 | u32 ref_obj_id; | ||
| 69 | /* For scalar types (SCALAR_VALUE), this represents our knowledge of | 109 | /* For scalar types (SCALAR_VALUE), this represents our knowledge of |
| 70 | * the actual value. | 110 | * the actual value. |
| 71 | * For pointer types, this represents the variable part of the offset | 111 | * For pointer types, this represents the variable part of the offset |
diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h index 9cd00a37b8d3..6db2d9a6e503 100644 --- a/include/linux/brcmphy.h +++ b/include/linux/brcmphy.h | |||
| @@ -148,6 +148,22 @@ | |||
| 148 | #define BCM_LED_SRC_OFF 0xe /* Tied high */ | 148 | #define BCM_LED_SRC_OFF 0xe /* Tied high */ |
| 149 | #define BCM_LED_SRC_ON 0xf /* Tied low */ | 149 | #define BCM_LED_SRC_ON 0xf /* Tied low */ |
| 150 | 150 | ||
| 151 | /* | ||
| 152 | * Broadcom Multicolor LED configurations (expansion register 4) | ||
| 153 | */ | ||
| 154 | #define BCM_EXP_MULTICOLOR (MII_BCM54XX_EXP_SEL_ER + 0x04) | ||
| 155 | #define BCM_LED_MULTICOLOR_IN_PHASE BIT(8) | ||
| 156 | #define BCM_LED_MULTICOLOR_LINK_ACT 0x0 | ||
| 157 | #define BCM_LED_MULTICOLOR_SPEED 0x1 | ||
| 158 | #define BCM_LED_MULTICOLOR_ACT_FLASH 0x2 | ||
| 159 | #define BCM_LED_MULTICOLOR_FDX 0x3 | ||
| 160 | #define BCM_LED_MULTICOLOR_OFF 0x4 | ||
| 161 | #define BCM_LED_MULTICOLOR_ON 0x5 | ||
| 162 | #define BCM_LED_MULTICOLOR_ALT 0x6 | ||
| 163 | #define BCM_LED_MULTICOLOR_FLASH 0x7 | ||
| 164 | #define BCM_LED_MULTICOLOR_LINK 0x8 | ||
| 165 | #define BCM_LED_MULTICOLOR_ACT 0x9 | ||
| 166 | #define BCM_LED_MULTICOLOR_PROGRAM 0xa | ||
| 151 | 167 | ||
| 152 | /* | 168 | /* |
| 153 | * BCM5482: Shadow registers | 169 | * BCM5482: Shadow registers |
diff --git a/include/linux/net.h b/include/linux/net.h index 651fca72286c..c606c72311d0 100644 --- a/include/linux/net.h +++ b/include/linux/net.h | |||
| @@ -83,6 +83,12 @@ enum sock_type { | |||
| 83 | 83 | ||
| 84 | #endif /* ARCH_HAS_SOCKET_TYPES */ | 84 | #endif /* ARCH_HAS_SOCKET_TYPES */ |
| 85 | 85 | ||
| 86 | /** | ||
| 87 | * enum sock_shutdown_cmd - Shutdown types | ||
| 88 | * @SHUT_RD: shutdown receptions | ||
| 89 | * @SHUT_WR: shutdown transmissions | ||
| 90 | * @SHUT_RDWR: shutdown receptions/transmissions | ||
| 91 | */ | ||
| 86 | enum sock_shutdown_cmd { | 92 | enum sock_shutdown_cmd { |
| 87 | SHUT_RD, | 93 | SHUT_RD, |
| 88 | SHUT_WR, | 94 | SHUT_WR, |
diff --git a/include/linux/parport.h b/include/linux/parport.h index f41f1d041e2c..397607a0c0eb 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h | |||
| @@ -460,7 +460,6 @@ extern size_t parport_ieee1284_epp_read_addr (struct parport *, | |||
| 460 | void *, size_t, int); | 460 | void *, size_t, int); |
| 461 | 461 | ||
| 462 | /* IEEE1284.3 functions */ | 462 | /* IEEE1284.3 functions */ |
| 463 | #define daisy_dev_name "Device ID probe" | ||
| 464 | extern int parport_daisy_init (struct parport *port); | 463 | extern int parport_daisy_init (struct parport *port); |
| 465 | extern void parport_daisy_fini (struct parport *port); | 464 | extern void parport_daisy_fini (struct parport *port); |
| 466 | extern struct pardevice *parport_open (int devnum, const char *name); | 465 | extern struct pardevice *parport_open (int devnum, const char *name); |
| @@ -469,18 +468,6 @@ extern ssize_t parport_device_id (int devnum, char *buffer, size_t len); | |||
| 469 | extern void parport_daisy_deselect_all (struct parport *port); | 468 | extern void parport_daisy_deselect_all (struct parport *port); |
| 470 | extern int parport_daisy_select (struct parport *port, int daisy, int mode); | 469 | extern int parport_daisy_select (struct parport *port, int daisy, int mode); |
| 471 | 470 | ||
| 472 | #ifdef CONFIG_PARPORT_1284 | ||
| 473 | extern int daisy_drv_init(void); | ||
| 474 | extern void daisy_drv_exit(void); | ||
| 475 | #else | ||
| 476 | static inline int daisy_drv_init(void) | ||
| 477 | { | ||
| 478 | return 0; | ||
| 479 | } | ||
| 480 | |||
| 481 | static inline void daisy_drv_exit(void) {} | ||
| 482 | #endif | ||
| 483 | |||
| 484 | /* Lowlevel drivers _can_ call this support function to handle irqs. */ | 471 | /* Lowlevel drivers _can_ call this support function to handle irqs. */ |
| 485 | static inline void parport_generic_irq(struct parport *port) | 472 | static inline void parport_generic_irq(struct parport *port) |
| 486 | { | 473 | { |
diff --git a/include/linux/socket.h b/include/linux/socket.h index 6016daeecee4..b57cd8bf96e2 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h | |||
| @@ -26,7 +26,7 @@ typedef __kernel_sa_family_t sa_family_t; | |||
| 26 | /* | 26 | /* |
| 27 | * 1003.1g requires sa_family_t and that sa_data is char. | 27 | * 1003.1g requires sa_family_t and that sa_data is char. |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | struct sockaddr { | 30 | struct sockaddr { |
| 31 | sa_family_t sa_family; /* address family, AF_xxx */ | 31 | sa_family_t sa_family; /* address family, AF_xxx */ |
| 32 | char sa_data[14]; /* 14 bytes of protocol address */ | 32 | char sa_data[14]; /* 14 bytes of protocol address */ |
| @@ -44,7 +44,7 @@ struct linger { | |||
| 44 | * system, not 4.3. Thus msg_accrights(len) are now missing. They | 44 | * system, not 4.3. Thus msg_accrights(len) are now missing. They |
| 45 | * belong in an obscure libc emulation or the bin. | 45 | * belong in an obscure libc emulation or the bin. |
| 46 | */ | 46 | */ |
| 47 | 47 | ||
| 48 | struct msghdr { | 48 | struct msghdr { |
| 49 | void *msg_name; /* ptr to socket address structure */ | 49 | void *msg_name; /* ptr to socket address structure */ |
| 50 | int msg_namelen; /* size of socket address structure */ | 50 | int msg_namelen; /* size of socket address structure */ |
| @@ -54,7 +54,7 @@ struct msghdr { | |||
| 54 | unsigned int msg_flags; /* flags on received message */ | 54 | unsigned int msg_flags; /* flags on received message */ |
| 55 | struct kiocb *msg_iocb; /* ptr to iocb for async requests */ | 55 | struct kiocb *msg_iocb; /* ptr to iocb for async requests */ |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | struct user_msghdr { | 58 | struct user_msghdr { |
| 59 | void __user *msg_name; /* ptr to socket address structure */ | 59 | void __user *msg_name; /* ptr to socket address structure */ |
| 60 | int msg_namelen; /* size of socket address structure */ | 60 | int msg_namelen; /* size of socket address structure */ |
| @@ -122,7 +122,7 @@ struct cmsghdr { | |||
| 122 | * inside range, given by msg->msg_controllen before using | 122 | * inside range, given by msg->msg_controllen before using |
| 123 | * ancillary object DATA. --ANK (980731) | 123 | * ancillary object DATA. --ANK (980731) |
| 124 | */ | 124 | */ |
| 125 | 125 | ||
| 126 | static inline struct cmsghdr * __cmsg_nxthdr(void *__ctl, __kernel_size_t __size, | 126 | static inline struct cmsghdr * __cmsg_nxthdr(void *__ctl, __kernel_size_t __size, |
| 127 | struct cmsghdr *__cmsg) | 127 | struct cmsghdr *__cmsg) |
| 128 | { | 128 | { |
| @@ -264,10 +264,10 @@ struct ucred { | |||
| 264 | /* Maximum queue length specifiable by listen. */ | 264 | /* Maximum queue length specifiable by listen. */ |
| 265 | #define SOMAXCONN 128 | 265 | #define SOMAXCONN 128 |
| 266 | 266 | ||
| 267 | /* Flags we can use with send/ and recv. | 267 | /* Flags we can use with send/ and recv. |
| 268 | Added those for 1003.1g not all are supported yet | 268 | Added those for 1003.1g not all are supported yet |
| 269 | */ | 269 | */ |
| 270 | 270 | ||
| 271 | #define MSG_OOB 1 | 271 | #define MSG_OOB 1 |
| 272 | #define MSG_PEEK 2 | 272 | #define MSG_PEEK 2 |
| 273 | #define MSG_DONTROUTE 4 | 273 | #define MSG_DONTROUTE 4 |
diff --git a/include/net/act_api.h b/include/net/act_api.h index c745e9ccfab2..c61a1bf4e3de 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h | |||
| @@ -39,7 +39,7 @@ struct tc_action { | |||
| 39 | struct gnet_stats_basic_cpu __percpu *cpu_bstats_hw; | 39 | struct gnet_stats_basic_cpu __percpu *cpu_bstats_hw; |
| 40 | struct gnet_stats_queue __percpu *cpu_qstats; | 40 | struct gnet_stats_queue __percpu *cpu_qstats; |
| 41 | struct tc_cookie __rcu *act_cookie; | 41 | struct tc_cookie __rcu *act_cookie; |
| 42 | struct tcf_chain *goto_chain; | 42 | struct tcf_chain __rcu *goto_chain; |
| 43 | }; | 43 | }; |
| 44 | #define tcf_index common.tcfa_index | 44 | #define tcf_index common.tcfa_index |
| 45 | #define tcf_refcnt common.tcfa_refcnt | 45 | #define tcf_refcnt common.tcfa_refcnt |
| @@ -90,7 +90,7 @@ struct tc_action_ops { | |||
| 90 | int (*lookup)(struct net *net, struct tc_action **a, u32 index); | 90 | int (*lookup)(struct net *net, struct tc_action **a, u32 index); |
| 91 | int (*init)(struct net *net, struct nlattr *nla, | 91 | int (*init)(struct net *net, struct nlattr *nla, |
| 92 | struct nlattr *est, struct tc_action **act, int ovr, | 92 | struct nlattr *est, struct tc_action **act, int ovr, |
| 93 | int bind, bool rtnl_held, | 93 | int bind, bool rtnl_held, struct tcf_proto *tp, |
| 94 | struct netlink_ext_ack *extack); | 94 | struct netlink_ext_ack *extack); |
| 95 | int (*walk)(struct net *, struct sk_buff *, | 95 | int (*walk)(struct net *, struct sk_buff *, |
| 96 | struct netlink_callback *, int, | 96 | struct netlink_callback *, int, |
| @@ -181,6 +181,11 @@ int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int); | |||
| 181 | int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int); | 181 | int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int); |
| 182 | int tcf_action_copy_stats(struct sk_buff *, struct tc_action *, int); | 182 | int tcf_action_copy_stats(struct sk_buff *, struct tc_action *, int); |
| 183 | 183 | ||
| 184 | int tcf_action_check_ctrlact(int action, struct tcf_proto *tp, | ||
| 185 | struct tcf_chain **handle, | ||
| 186 | struct netlink_ext_ack *newchain); | ||
| 187 | struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action, | ||
| 188 | struct tcf_chain *newchain); | ||
| 184 | #endif /* CONFIG_NET_CLS_ACT */ | 189 | #endif /* CONFIG_NET_CLS_ACT */ |
| 185 | 190 | ||
| 186 | static inline void tcf_action_stats_update(struct tc_action *a, u64 bytes, | 191 | static inline void tcf_action_stats_update(struct tc_action *a, u64 bytes, |
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 31284c078d06..7d1a0483a17b 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
| @@ -378,6 +378,7 @@ struct tcf_chain { | |||
| 378 | bool flushing; | 378 | bool flushing; |
| 379 | const struct tcf_proto_ops *tmplt_ops; | 379 | const struct tcf_proto_ops *tmplt_ops; |
| 380 | void *tmplt_priv; | 380 | void *tmplt_priv; |
| 381 | struct rcu_head rcu; | ||
| 381 | }; | 382 | }; |
| 382 | 383 | ||
| 383 | struct tcf_block { | 384 | struct tcf_block { |
diff --git a/include/net/sctp/checksum.h b/include/net/sctp/checksum.h index 32ee65a30aff..1c6e6c0766ca 100644 --- a/include/net/sctp/checksum.h +++ b/include/net/sctp/checksum.h | |||
| @@ -61,7 +61,7 @@ static inline __wsum sctp_csum_combine(__wsum csum, __wsum csum2, | |||
| 61 | static inline __le32 sctp_compute_cksum(const struct sk_buff *skb, | 61 | static inline __le32 sctp_compute_cksum(const struct sk_buff *skb, |
| 62 | unsigned int offset) | 62 | unsigned int offset) |
| 63 | { | 63 | { |
| 64 | struct sctphdr *sh = sctp_hdr(skb); | 64 | struct sctphdr *sh = (struct sctphdr *)(skb->data + offset); |
| 65 | const struct skb_checksum_ops ops = { | 65 | const struct skb_checksum_ops ops = { |
| 66 | .update = sctp_csum_update, | 66 | .update = sctp_csum_update, |
| 67 | .combine = sctp_csum_combine, | 67 | .combine = sctp_csum_combine, |
diff --git a/include/net/sock.h b/include/net/sock.h index 328cb7cb7b0b..8de5ee258b93 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
| @@ -710,6 +710,12 @@ static inline void sk_add_node_rcu(struct sock *sk, struct hlist_head *list) | |||
| 710 | hlist_add_head_rcu(&sk->sk_node, list); | 710 | hlist_add_head_rcu(&sk->sk_node, list); |
| 711 | } | 711 | } |
| 712 | 712 | ||
| 713 | static inline void sk_add_node_tail_rcu(struct sock *sk, struct hlist_head *list) | ||
| 714 | { | ||
| 715 | sock_hold(sk); | ||
| 716 | hlist_add_tail_rcu(&sk->sk_node, list); | ||
| 717 | } | ||
| 718 | |||
| 713 | static inline void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list) | 719 | static inline void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list) |
| 714 | { | 720 | { |
| 715 | hlist_nulls_add_head_rcu(&sk->sk_nulls_node, list); | 721 | hlist_nulls_add_head_rcu(&sk->sk_nulls_node, list); |
diff --git a/include/net/tc_act/tc_gact.h b/include/net/tc_act/tc_gact.h index ee8d005f56fc..eb8f01c819e6 100644 --- a/include/net/tc_act/tc_gact.h +++ b/include/net/tc_act/tc_gact.h | |||
| @@ -56,7 +56,7 @@ static inline bool is_tcf_gact_goto_chain(const struct tc_action *a) | |||
| 56 | 56 | ||
| 57 | static inline u32 tcf_gact_goto_chain_index(const struct tc_action *a) | 57 | static inline u32 tcf_gact_goto_chain_index(const struct tc_action *a) |
| 58 | { | 58 | { |
| 59 | return a->goto_chain->index; | 59 | return READ_ONCE(a->tcfa_action) & TC_ACT_EXT_VAL_MASK; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | #endif /* __NET_TC_GACT_H */ | 62 | #endif /* __NET_TC_GACT_H */ |
diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h index 61cf7dbb6782..d074b6d60f8a 100644 --- a/include/net/xdp_sock.h +++ b/include/net/xdp_sock.h | |||
| @@ -36,7 +36,6 @@ struct xdp_umem { | |||
| 36 | u32 headroom; | 36 | u32 headroom; |
| 37 | u32 chunk_size_nohr; | 37 | u32 chunk_size_nohr; |
| 38 | struct user_struct *user; | 38 | struct user_struct *user; |
| 39 | struct pid *pid; | ||
| 40 | unsigned long address; | 39 | unsigned long address; |
| 41 | refcount_t users; | 40 | refcount_t users; |
| 42 | struct work_struct work; | 41 | struct work_struct work; |
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 3c38ac9a92a7..929c8e537a14 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h | |||
| @@ -502,16 +502,6 @@ union bpf_attr { | |||
| 502 | * Return | 502 | * Return |
| 503 | * 0 on success, or a negative error in case of failure. | 503 | * 0 on success, or a negative error in case of failure. |
| 504 | * | 504 | * |
| 505 | * int bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags) | ||
| 506 | * Description | ||
| 507 | * Push an element *value* in *map*. *flags* is one of: | ||
| 508 | * | ||
| 509 | * **BPF_EXIST** | ||
| 510 | * If the queue/stack is full, the oldest element is removed to | ||
| 511 | * make room for this. | ||
| 512 | * Return | ||
| 513 | * 0 on success, or a negative error in case of failure. | ||
| 514 | * | ||
| 515 | * int bpf_probe_read(void *dst, u32 size, const void *src) | 505 | * int bpf_probe_read(void *dst, u32 size, const void *src) |
| 516 | * Description | 506 | * Description |
| 517 | * For tracing programs, safely attempt to read *size* bytes from | 507 | * For tracing programs, safely attempt to read *size* bytes from |
| @@ -1435,14 +1425,14 @@ union bpf_attr { | |||
| 1435 | * u64 bpf_get_socket_cookie(struct bpf_sock_addr *ctx) | 1425 | * u64 bpf_get_socket_cookie(struct bpf_sock_addr *ctx) |
| 1436 | * Description | 1426 | * Description |
| 1437 | * Equivalent to bpf_get_socket_cookie() helper that accepts | 1427 | * Equivalent to bpf_get_socket_cookie() helper that accepts |
| 1438 | * *skb*, but gets socket from **struct bpf_sock_addr** contex. | 1428 | * *skb*, but gets socket from **struct bpf_sock_addr** context. |
| 1439 | * Return | 1429 | * Return |
| 1440 | * A 8-byte long non-decreasing number. | 1430 | * A 8-byte long non-decreasing number. |
| 1441 | * | 1431 | * |
| 1442 | * u64 bpf_get_socket_cookie(struct bpf_sock_ops *ctx) | 1432 | * u64 bpf_get_socket_cookie(struct bpf_sock_ops *ctx) |
| 1443 | * Description | 1433 | * Description |
| 1444 | * Equivalent to bpf_get_socket_cookie() helper that accepts | 1434 | * Equivalent to bpf_get_socket_cookie() helper that accepts |
| 1445 | * *skb*, but gets socket from **struct bpf_sock_ops** contex. | 1435 | * *skb*, but gets socket from **struct bpf_sock_ops** context. |
| 1446 | * Return | 1436 | * Return |
| 1447 | * A 8-byte long non-decreasing number. | 1437 | * A 8-byte long non-decreasing number. |
| 1448 | * | 1438 | * |
| @@ -2098,52 +2088,52 @@ union bpf_attr { | |||
| 2098 | * Return | 2088 | * Return |
| 2099 | * 0 on success, or a negative error in case of failure. | 2089 | * 0 on success, or a negative error in case of failure. |
| 2100 | * | 2090 | * |
| 2101 | * int bpf_rc_keydown(void *ctx, u32 protocol, u64 scancode, u32 toggle) | 2091 | * int bpf_rc_repeat(void *ctx) |
| 2102 | * Description | 2092 | * Description |
| 2103 | * This helper is used in programs implementing IR decoding, to | 2093 | * This helper is used in programs implementing IR decoding, to |
| 2104 | * report a successfully decoded key press with *scancode*, | 2094 | * report a successfully decoded repeat key message. This delays |
| 2105 | * *toggle* value in the given *protocol*. The scancode will be | 2095 | * the generation of a key up event for previously generated |
| 2106 | * translated to a keycode using the rc keymap, and reported as | 2096 | * key down event. |
| 2107 | * an input key down event. After a period a key up event is | ||
| 2108 | * generated. This period can be extended by calling either | ||
| 2109 | * **bpf_rc_keydown**\ () again with the same values, or calling | ||
| 2110 | * **bpf_rc_repeat**\ (). | ||
| 2111 | * | 2097 | * |
| 2112 | * Some protocols include a toggle bit, in case the button was | 2098 | * Some IR protocols like NEC have a special IR message for |
| 2113 | * released and pressed again between consecutive scancodes. | 2099 | * repeating last button, for when a button is held down. |
| 2114 | * | 2100 | * |
| 2115 | * The *ctx* should point to the lirc sample as passed into | 2101 | * The *ctx* should point to the lirc sample as passed into |
| 2116 | * the program. | 2102 | * the program. |
| 2117 | * | 2103 | * |
| 2118 | * The *protocol* is the decoded protocol number (see | ||
| 2119 | * **enum rc_proto** for some predefined values). | ||
| 2120 | * | ||
| 2121 | * This helper is only available is the kernel was compiled with | 2104 | * This helper is only available is the kernel was compiled with |
| 2122 | * the **CONFIG_BPF_LIRC_MODE2** configuration option set to | 2105 | * the **CONFIG_BPF_LIRC_MODE2** configuration option set to |
| 2123 | * "**y**". | 2106 | * "**y**". |
| 2124 | * Return | 2107 | * Return |
| 2125 | * 0 | 2108 | * 0 |
| 2126 | * | 2109 | * |
| 2127 | * int bpf_rc_repeat(void *ctx) | 2110 | * int bpf_rc_keydown(void *ctx, u32 protocol, u64 scancode, u32 toggle) |
| 2128 | * Description | 2111 | * Description |
| 2129 | * This helper is used in programs implementing IR decoding, to | 2112 | * This helper is used in programs implementing IR decoding, to |
| 2130 | * report a successfully decoded repeat key message. This delays | 2113 | * report a successfully decoded key press with *scancode*, |
| 2131 | * the generation of a key up event for previously generated | 2114 | * *toggle* value in the given *protocol*. The scancode will be |
| 2132 | * key down event. | 2115 | * translated to a keycode using the rc keymap, and reported as |
| 2116 | * an input key down event. After a period a key up event is | ||
| 2117 | * generated. This period can be extended by calling either | ||
| 2118 | * **bpf_rc_keydown**\ () again with the same values, or calling | ||
| 2119 | * **bpf_rc_repeat**\ (). | ||
| 2133 | * | 2120 | * |
| 2134 | * Some IR protocols like NEC have a special IR message for | 2121 | * Some protocols include a toggle bit, in case the button was |
| 2135 | * repeating last button, for when a button is held down. | 2122 | * released and pressed again between consecutive scancodes. |
| 2136 | * | 2123 | * |
| 2137 | * The *ctx* should point to the lirc sample as passed into | 2124 | * The *ctx* should point to the lirc sample as passed into |
| 2138 | * the program. | 2125 | * the program. |
| 2139 | * | 2126 | * |
| 2127 | * The *protocol* is the decoded protocol number (see | ||
| 2128 | * **enum rc_proto** for some predefined values). | ||
| 2129 | * | ||
| 2140 | * This helper is only available is the kernel was compiled with | 2130 | * This helper is only available is the kernel was compiled with |
| 2141 | * the **CONFIG_BPF_LIRC_MODE2** configuration option set to | 2131 | * the **CONFIG_BPF_LIRC_MODE2** configuration option set to |
| 2142 | * "**y**". | 2132 | * "**y**". |
| 2143 | * Return | 2133 | * Return |
| 2144 | * 0 | 2134 | * 0 |
| 2145 | * | 2135 | * |
| 2146 | * uint64_t bpf_skb_cgroup_id(struct sk_buff *skb) | 2136 | * u64 bpf_skb_cgroup_id(struct sk_buff *skb) |
| 2147 | * Description | 2137 | * Description |
| 2148 | * Return the cgroup v2 id of the socket associated with the *skb*. | 2138 | * Return the cgroup v2 id of the socket associated with the *skb*. |
| 2149 | * This is roughly similar to the **bpf_get_cgroup_classid**\ () | 2139 | * This is roughly similar to the **bpf_get_cgroup_classid**\ () |
| @@ -2159,30 +2149,12 @@ union bpf_attr { | |||
| 2159 | * Return | 2149 | * Return |
| 2160 | * The id is returned or 0 in case the id could not be retrieved. | 2150 | * The id is returned or 0 in case the id could not be retrieved. |
| 2161 | * | 2151 | * |
| 2162 | * u64 bpf_skb_ancestor_cgroup_id(struct sk_buff *skb, int ancestor_level) | ||
| 2163 | * Description | ||
| 2164 | * Return id of cgroup v2 that is ancestor of cgroup associated | ||
| 2165 | * with the *skb* at the *ancestor_level*. The root cgroup is at | ||
| 2166 | * *ancestor_level* zero and each step down the hierarchy | ||
| 2167 | * increments the level. If *ancestor_level* == level of cgroup | ||
| 2168 | * associated with *skb*, then return value will be same as that | ||
| 2169 | * of **bpf_skb_cgroup_id**\ (). | ||
| 2170 | * | ||
| 2171 | * The helper is useful to implement policies based on cgroups | ||
| 2172 | * that are upper in hierarchy than immediate cgroup associated | ||
| 2173 | * with *skb*. | ||
| 2174 | * | ||
| 2175 | * The format of returned id and helper limitations are same as in | ||
| 2176 | * **bpf_skb_cgroup_id**\ (). | ||
| 2177 | * Return | ||
| 2178 | * The id is returned or 0 in case the id could not be retrieved. | ||
| 2179 | * | ||
| 2180 | * u64 bpf_get_current_cgroup_id(void) | 2152 | * u64 bpf_get_current_cgroup_id(void) |
| 2181 | * Return | 2153 | * Return |
| 2182 | * A 64-bit integer containing the current cgroup id based | 2154 | * A 64-bit integer containing the current cgroup id based |
| 2183 | * on the cgroup within which the current task is running. | 2155 | * on the cgroup within which the current task is running. |
| 2184 | * | 2156 | * |
| 2185 | * void* get_local_storage(void *map, u64 flags) | 2157 | * void *bpf_get_local_storage(void *map, u64 flags) |
| 2186 | * Description | 2158 | * Description |
| 2187 | * Get the pointer to the local storage area. | 2159 | * Get the pointer to the local storage area. |
| 2188 | * The type and the size of the local storage is defined | 2160 | * The type and the size of the local storage is defined |
| @@ -2209,6 +2181,24 @@ union bpf_attr { | |||
| 2209 | * Return | 2181 | * Return |
| 2210 | * 0 on success, or a negative error in case of failure. | 2182 | * 0 on success, or a negative error in case of failure. |
| 2211 | * | 2183 | * |
| 2184 | * u64 bpf_skb_ancestor_cgroup_id(struct sk_buff *skb, int ancestor_level) | ||
| 2185 | * Description | ||
| 2186 | * Return id of cgroup v2 that is ancestor of cgroup associated | ||
| 2187 | * with the *skb* at the *ancestor_level*. The root cgroup is at | ||
| 2188 | * *ancestor_level* zero and each step down the hierarchy | ||
| 2189 | * increments the level. If *ancestor_level* == level of cgroup | ||
| 2190 | * associated with *skb*, then return value will be same as that | ||
| 2191 | * of **bpf_skb_cgroup_id**\ (). | ||
| 2192 | * | ||
| 2193 | * The helper is useful to implement policies based on cgroups | ||
| 2194 | * that are upper in hierarchy than immediate cgroup associated | ||
| 2195 | * with *skb*. | ||
| 2196 | * | ||
| 2197 | * The format of returned id and helper limitations are same as in | ||
| 2198 | * **bpf_skb_cgroup_id**\ (). | ||
| 2199 | * Return | ||
| 2200 | * The id is returned or 0 in case the id could not be retrieved. | ||
| 2201 | * | ||
| 2212 | * struct bpf_sock *bpf_sk_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags) | 2202 | * struct bpf_sock *bpf_sk_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags) |
| 2213 | * Description | 2203 | * Description |
| 2214 | * Look for TCP socket matching *tuple*, optionally in a child | 2204 | * Look for TCP socket matching *tuple*, optionally in a child |
| @@ -2289,6 +2279,16 @@ union bpf_attr { | |||
| 2289 | * Return | 2279 | * Return |
| 2290 | * 0 on success, or a negative error in case of failure. | 2280 | * 0 on success, or a negative error in case of failure. |
| 2291 | * | 2281 | * |
| 2282 | * int bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags) | ||
| 2283 | * Description | ||
| 2284 | * Push an element *value* in *map*. *flags* is one of: | ||
| 2285 | * | ||
| 2286 | * **BPF_EXIST** | ||
| 2287 | * If the queue/stack is full, the oldest element is | ||
| 2288 | * removed to make room for this. | ||
| 2289 | * Return | ||
| 2290 | * 0 on success, or a negative error in case of failure. | ||
| 2291 | * | ||
| 2292 | * int bpf_map_pop_elem(struct bpf_map *map, void *value) | 2292 | * int bpf_map_pop_elem(struct bpf_map *map, void *value) |
| 2293 | * Description | 2293 | * Description |
| 2294 | * Pop an element from *map*. | 2294 | * Pop an element from *map*. |
| @@ -2343,29 +2343,94 @@ union bpf_attr { | |||
| 2343 | * Return | 2343 | * Return |
| 2344 | * 0 | 2344 | * 0 |
| 2345 | * | 2345 | * |
| 2346 | * int bpf_spin_lock(struct bpf_spin_lock *lock) | ||
| 2347 | * Description | ||
| 2348 | * Acquire a spinlock represented by the pointer *lock*, which is | ||
| 2349 | * stored as part of a value of a map. Taking the lock allows to | ||
| 2350 | * safely update the rest of the fields in that value. The | ||
| 2351 | * spinlock can (and must) later be released with a call to | ||
| 2352 | * **bpf_spin_unlock**\ (\ *lock*\ ). | ||
| 2353 | * | ||
| 2354 | * Spinlocks in BPF programs come with a number of restrictions | ||
| 2355 | * and constraints: | ||
| 2356 | * | ||
| 2357 | * * **bpf_spin_lock** objects are only allowed inside maps of | ||
| 2358 | * types **BPF_MAP_TYPE_HASH** and **BPF_MAP_TYPE_ARRAY** (this | ||
| 2359 | * list could be extended in the future). | ||
| 2360 | * * BTF description of the map is mandatory. | ||
| 2361 | * * The BPF program can take ONE lock at a time, since taking two | ||
| 2362 | * or more could cause dead locks. | ||
| 2363 | * * Only one **struct bpf_spin_lock** is allowed per map element. | ||
| 2364 | * * When the lock is taken, calls (either BPF to BPF or helpers) | ||
| 2365 | * are not allowed. | ||
| 2366 | * * The **BPF_LD_ABS** and **BPF_LD_IND** instructions are not | ||
| 2367 | * allowed inside a spinlock-ed region. | ||
| 2368 | * * The BPF program MUST call **bpf_spin_unlock**\ () to release | ||
| 2369 | * the lock, on all execution paths, before it returns. | ||
| 2370 | * * The BPF program can access **struct bpf_spin_lock** only via | ||
| 2371 | * the **bpf_spin_lock**\ () and **bpf_spin_unlock**\ () | ||
| 2372 | * helpers. Loading or storing data into the **struct | ||
| 2373 | * bpf_spin_lock** *lock*\ **;** field of a map is not allowed. | ||
| 2374 | * * To use the **bpf_spin_lock**\ () helper, the BTF description | ||
| 2375 | * of the map value must be a struct and have **struct | ||
| 2376 | * bpf_spin_lock** *anyname*\ **;** field at the top level. | ||
| 2377 | * Nested lock inside another struct is not allowed. | ||
| 2378 | * * The **struct bpf_spin_lock** *lock* field in a map value must | ||
| 2379 | * be aligned on a multiple of 4 bytes in that value. | ||
| 2380 | * * Syscall with command **BPF_MAP_LOOKUP_ELEM** does not copy | ||
| 2381 | * the **bpf_spin_lock** field to user space. | ||
| 2382 | * * Syscall with command **BPF_MAP_UPDATE_ELEM**, or update from | ||
| 2383 | * a BPF program, do not update the **bpf_spin_lock** field. | ||
| 2384 | * * **bpf_spin_lock** cannot be on the stack or inside a | ||
| 2385 | * networking packet (it can only be inside of a map values). | ||
| 2386 | * * **bpf_spin_lock** is available to root only. | ||
| 2387 | * * Tracing programs and socket filter programs cannot use | ||
| 2388 | * **bpf_spin_lock**\ () due to insufficient preemption checks | ||
| 2389 | * (but this may change in the future). | ||
| 2390 | * * **bpf_spin_lock** is not allowed in inner maps of map-in-map. | ||
| 2391 | * Return | ||
| 2392 | * 0 | ||
| 2393 | * | ||
| 2394 | * int bpf_spin_unlock(struct bpf_spin_lock *lock) | ||
| 2395 | * Description | ||
| 2396 | * Release the *lock* previously locked by a call to | ||
| 2397 | * **bpf_spin_lock**\ (\ *lock*\ ). | ||
| 2398 | * Return | ||
| 2399 | * 0 | ||
| 2400 | * | ||
| 2346 | * struct bpf_sock *bpf_sk_fullsock(struct bpf_sock *sk) | 2401 | * struct bpf_sock *bpf_sk_fullsock(struct bpf_sock *sk) |
| 2347 | * Description | 2402 | * Description |
| 2348 | * This helper gets a **struct bpf_sock** pointer such | 2403 | * This helper gets a **struct bpf_sock** pointer such |
| 2349 | * that all the fields in bpf_sock can be accessed. | 2404 | * that all the fields in this **bpf_sock** can be accessed. |
| 2350 | * Return | 2405 | * Return |
| 2351 | * A **struct bpf_sock** pointer on success, or NULL in | 2406 | * A **struct bpf_sock** pointer on success, or **NULL** in |
| 2352 | * case of failure. | 2407 | * case of failure. |
| 2353 | * | 2408 | * |
| 2354 | * struct bpf_tcp_sock *bpf_tcp_sock(struct bpf_sock *sk) | 2409 | * struct bpf_tcp_sock *bpf_tcp_sock(struct bpf_sock *sk) |
| 2355 | * Description | 2410 | * Description |
| 2356 | * This helper gets a **struct bpf_tcp_sock** pointer from a | 2411 | * This helper gets a **struct bpf_tcp_sock** pointer from a |
| 2357 | * **struct bpf_sock** pointer. | 2412 | * **struct bpf_sock** pointer. |
| 2358 | * | ||
| 2359 | * Return | 2413 | * Return |
| 2360 | * A **struct bpf_tcp_sock** pointer on success, or NULL in | 2414 | * A **struct bpf_tcp_sock** pointer on success, or **NULL** in |
| 2361 | * case of failure. | 2415 | * case of failure. |
| 2362 | * | 2416 | * |
| 2363 | * int bpf_skb_ecn_set_ce(struct sk_buf *skb) | 2417 | * int bpf_skb_ecn_set_ce(struct sk_buf *skb) |
| 2364 | * Description | 2418 | * Description |
| 2365 | * Sets ECN of IP header to ce (congestion encountered) if | 2419 | * Set ECN (Explicit Congestion Notification) field of IP header |
| 2366 | * current value is ect (ECN capable). Works with IPv6 and IPv4. | 2420 | * to **CE** (Congestion Encountered) if current value is **ECT** |
| 2367 | * Return | 2421 | * (ECN Capable Transport). Otherwise, do nothing. Works with IPv6 |
| 2368 | * 1 if set, 0 if not set. | 2422 | * and IPv4. |
| 2423 | * Return | ||
| 2424 | * 1 if the **CE** flag is set (either by the current helper call | ||
| 2425 | * or because it was already present), 0 if it is not set. | ||
| 2426 | * | ||
| 2427 | * struct bpf_sock *bpf_get_listener_sock(struct bpf_sock *sk) | ||
| 2428 | * Description | ||
| 2429 | * Return a **struct bpf_sock** pointer in **TCP_LISTEN** state. | ||
| 2430 | * **bpf_sk_release**\ () is unnecessary and not allowed. | ||
| 2431 | * Return | ||
| 2432 | * A **struct bpf_sock** pointer on success, or **NULL** in | ||
| 2433 | * case of failure. | ||
| 2369 | */ | 2434 | */ |
| 2370 | #define __BPF_FUNC_MAPPER(FN) \ | 2435 | #define __BPF_FUNC_MAPPER(FN) \ |
| 2371 | FN(unspec), \ | 2436 | FN(unspec), \ |
| @@ -2465,7 +2530,8 @@ union bpf_attr { | |||
| 2465 | FN(spin_unlock), \ | 2530 | FN(spin_unlock), \ |
| 2466 | FN(sk_fullsock), \ | 2531 | FN(sk_fullsock), \ |
| 2467 | FN(tcp_sock), \ | 2532 | FN(tcp_sock), \ |
| 2468 | FN(skb_ecn_set_ce), | 2533 | FN(skb_ecn_set_ce), \ |
| 2534 | FN(get_listener_sock), | ||
| 2469 | 2535 | ||
| 2470 | /* integer value in 'imm' field of BPF_CALL instruction selects which helper | 2536 | /* integer value in 'imm' field of BPF_CALL instruction selects which helper |
| 2471 | * function eBPF program intends to call | 2537 | * function eBPF program intends to call |
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 62f6bced3a3c..afca36f53c49 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
| @@ -136,21 +136,29 @@ static struct bpf_map *find_and_alloc_map(union bpf_attr *attr) | |||
| 136 | 136 | ||
| 137 | void *bpf_map_area_alloc(size_t size, int numa_node) | 137 | void *bpf_map_area_alloc(size_t size, int numa_node) |
| 138 | { | 138 | { |
| 139 | /* We definitely need __GFP_NORETRY, so OOM killer doesn't | 139 | /* We really just want to fail instead of triggering OOM killer |
| 140 | * trigger under memory pressure as we really just want to | 140 | * under memory pressure, therefore we set __GFP_NORETRY to kmalloc, |
| 141 | * fail instead. | 141 | * which is used for lower order allocation requests. |
| 142 | * | ||
| 143 | * It has been observed that higher order allocation requests done by | ||
| 144 | * vmalloc with __GFP_NORETRY being set might fail due to not trying | ||
| 145 | * to reclaim memory from the page cache, thus we set | ||
| 146 | * __GFP_RETRY_MAYFAIL to avoid such situations. | ||
| 142 | */ | 147 | */ |
| 143 | const gfp_t flags = __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO; | 148 | |
| 149 | const gfp_t flags = __GFP_NOWARN | __GFP_ZERO; | ||
| 144 | void *area; | 150 | void *area; |
| 145 | 151 | ||
| 146 | if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) { | 152 | if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) { |
| 147 | area = kmalloc_node(size, GFP_USER | flags, numa_node); | 153 | area = kmalloc_node(size, GFP_USER | __GFP_NORETRY | flags, |
| 154 | numa_node); | ||
| 148 | if (area != NULL) | 155 | if (area != NULL) |
| 149 | return area; | 156 | return area; |
| 150 | } | 157 | } |
| 151 | 158 | ||
| 152 | return __vmalloc_node_flags_caller(size, numa_node, GFP_KERNEL | flags, | 159 | return __vmalloc_node_flags_caller(size, numa_node, |
| 153 | __builtin_return_address(0)); | 160 | GFP_KERNEL | __GFP_RETRY_MAYFAIL | |
| 161 | flags, __builtin_return_address(0)); | ||
| 154 | } | 162 | } |
| 155 | 163 | ||
| 156 | void bpf_map_area_free(void *area) | 164 | void bpf_map_area_free(void *area) |
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index ce166a002d16..fd502c1f71eb 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
| @@ -212,7 +212,7 @@ struct bpf_call_arg_meta { | |||
| 212 | int access_size; | 212 | int access_size; |
| 213 | s64 msize_smax_value; | 213 | s64 msize_smax_value; |
| 214 | u64 msize_umax_value; | 214 | u64 msize_umax_value; |
| 215 | int ptr_id; | 215 | int ref_obj_id; |
| 216 | int func_id; | 216 | int func_id; |
| 217 | }; | 217 | }; |
| 218 | 218 | ||
| @@ -346,35 +346,23 @@ static bool reg_type_may_be_null(enum bpf_reg_type type) | |||
| 346 | type == PTR_TO_TCP_SOCK_OR_NULL; | 346 | type == PTR_TO_TCP_SOCK_OR_NULL; |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | static bool type_is_refcounted(enum bpf_reg_type type) | ||
| 350 | { | ||
| 351 | return type == PTR_TO_SOCKET; | ||
| 352 | } | ||
| 353 | |||
| 354 | static bool type_is_refcounted_or_null(enum bpf_reg_type type) | ||
| 355 | { | ||
| 356 | return type == PTR_TO_SOCKET || type == PTR_TO_SOCKET_OR_NULL; | ||
| 357 | } | ||
| 358 | |||
| 359 | static bool reg_is_refcounted(const struct bpf_reg_state *reg) | ||
| 360 | { | ||
| 361 | return type_is_refcounted(reg->type); | ||
| 362 | } | ||
| 363 | |||
| 364 | static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg) | 349 | static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg) |
| 365 | { | 350 | { |
| 366 | return reg->type == PTR_TO_MAP_VALUE && | 351 | return reg->type == PTR_TO_MAP_VALUE && |
| 367 | map_value_has_spin_lock(reg->map_ptr); | 352 | map_value_has_spin_lock(reg->map_ptr); |
| 368 | } | 353 | } |
| 369 | 354 | ||
| 370 | static bool reg_is_refcounted_or_null(const struct bpf_reg_state *reg) | 355 | static bool reg_type_may_be_refcounted_or_null(enum bpf_reg_type type) |
| 371 | { | 356 | { |
| 372 | return type_is_refcounted_or_null(reg->type); | 357 | return type == PTR_TO_SOCKET || |
| 358 | type == PTR_TO_SOCKET_OR_NULL || | ||
| 359 | type == PTR_TO_TCP_SOCK || | ||
| 360 | type == PTR_TO_TCP_SOCK_OR_NULL; | ||
| 373 | } | 361 | } |
| 374 | 362 | ||
| 375 | static bool arg_type_is_refcounted(enum bpf_arg_type type) | 363 | static bool arg_type_may_be_refcounted(enum bpf_arg_type type) |
| 376 | { | 364 | { |
| 377 | return type == ARG_PTR_TO_SOCKET; | 365 | return type == ARG_PTR_TO_SOCK_COMMON; |
| 378 | } | 366 | } |
| 379 | 367 | ||
| 380 | /* Determine whether the function releases some resources allocated by another | 368 | /* Determine whether the function releases some resources allocated by another |
| @@ -392,6 +380,12 @@ static bool is_acquire_function(enum bpf_func_id func_id) | |||
| 392 | func_id == BPF_FUNC_sk_lookup_udp; | 380 | func_id == BPF_FUNC_sk_lookup_udp; |
| 393 | } | 381 | } |
| 394 | 382 | ||
| 383 | static bool is_ptr_cast_function(enum bpf_func_id func_id) | ||
| 384 | { | ||
| 385 | return func_id == BPF_FUNC_tcp_sock || | ||
| 386 | func_id == BPF_FUNC_sk_fullsock; | ||
| 387 | } | ||
| 388 | |||
| 395 | /* string representation of 'enum bpf_reg_type' */ | 389 | /* string representation of 'enum bpf_reg_type' */ |
| 396 | static const char * const reg_type_str[] = { | 390 | static const char * const reg_type_str[] = { |
| 397 | [NOT_INIT] = "?", | 391 | [NOT_INIT] = "?", |
| @@ -466,6 +460,8 @@ static void print_verifier_state(struct bpf_verifier_env *env, | |||
| 466 | verbose(env, ",call_%d", func(env, reg)->callsite); | 460 | verbose(env, ",call_%d", func(env, reg)->callsite); |
| 467 | } else { | 461 | } else { |
| 468 | verbose(env, "(id=%d", reg->id); | 462 | verbose(env, "(id=%d", reg->id); |
| 463 | if (reg_type_may_be_refcounted_or_null(t)) | ||
| 464 | verbose(env, ",ref_obj_id=%d", reg->ref_obj_id); | ||
| 469 | if (t != SCALAR_VALUE) | 465 | if (t != SCALAR_VALUE) |
| 470 | verbose(env, ",off=%d", reg->off); | 466 | verbose(env, ",off=%d", reg->off); |
| 471 | if (type_is_pkt_pointer(t)) | 467 | if (type_is_pkt_pointer(t)) |
| @@ -2414,16 +2410,15 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno, | |||
| 2414 | /* Any sk pointer can be ARG_PTR_TO_SOCK_COMMON */ | 2410 | /* Any sk pointer can be ARG_PTR_TO_SOCK_COMMON */ |
| 2415 | if (!type_is_sk_pointer(type)) | 2411 | if (!type_is_sk_pointer(type)) |
| 2416 | goto err_type; | 2412 | goto err_type; |
| 2417 | } else if (arg_type == ARG_PTR_TO_SOCKET) { | 2413 | if (reg->ref_obj_id) { |
| 2418 | expected_type = PTR_TO_SOCKET; | 2414 | if (meta->ref_obj_id) { |
| 2419 | if (type != expected_type) | 2415 | verbose(env, "verifier internal error: more than one arg with ref_obj_id R%d %u %u\n", |
| 2420 | goto err_type; | 2416 | regno, reg->ref_obj_id, |
| 2421 | if (meta->ptr_id || !reg->id) { | 2417 | meta->ref_obj_id); |
| 2422 | verbose(env, "verifier internal error: mismatched references meta=%d, reg=%d\n", | 2418 | return -EFAULT; |
| 2423 | meta->ptr_id, reg->id); | 2419 | } |
| 2424 | return -EFAULT; | 2420 | meta->ref_obj_id = reg->ref_obj_id; |
| 2425 | } | 2421 | } |
| 2426 | meta->ptr_id = reg->id; | ||
| 2427 | } else if (arg_type == ARG_PTR_TO_SPIN_LOCK) { | 2422 | } else if (arg_type == ARG_PTR_TO_SPIN_LOCK) { |
| 2428 | if (meta->func_id == BPF_FUNC_spin_lock) { | 2423 | if (meta->func_id == BPF_FUNC_spin_lock) { |
| 2429 | if (process_spin_lock(env, regno, true)) | 2424 | if (process_spin_lock(env, regno, true)) |
| @@ -2740,32 +2735,38 @@ static bool check_arg_pair_ok(const struct bpf_func_proto *fn) | |||
| 2740 | return true; | 2735 | return true; |
| 2741 | } | 2736 | } |
| 2742 | 2737 | ||
| 2743 | static bool check_refcount_ok(const struct bpf_func_proto *fn) | 2738 | static bool check_refcount_ok(const struct bpf_func_proto *fn, int func_id) |
| 2744 | { | 2739 | { |
| 2745 | int count = 0; | 2740 | int count = 0; |
| 2746 | 2741 | ||
| 2747 | if (arg_type_is_refcounted(fn->arg1_type)) | 2742 | if (arg_type_may_be_refcounted(fn->arg1_type)) |
| 2748 | count++; | 2743 | count++; |
| 2749 | if (arg_type_is_refcounted(fn->arg2_type)) | 2744 | if (arg_type_may_be_refcounted(fn->arg2_type)) |
| 2750 | count++; | 2745 | count++; |
| 2751 | if (arg_type_is_refcounted(fn->arg3_type)) | 2746 | if (arg_type_may_be_refcounted(fn->arg3_type)) |
| 2752 | count++; | 2747 | count++; |
| 2753 | if (arg_type_is_refcounted(fn->arg4_type)) | 2748 | if (arg_type_may_be_refcounted(fn->arg4_type)) |
| 2754 | count++; | 2749 | count++; |
| 2755 | if (arg_type_is_refcounted(fn->arg5_type)) | 2750 | if (arg_type_may_be_refcounted(fn->arg5_type)) |
| 2756 | count++; | 2751 | count++; |
| 2757 | 2752 | ||
| 2753 | /* A reference acquiring function cannot acquire | ||
| 2754 | * another refcounted ptr. | ||
| 2755 | */ | ||
| 2756 | if (is_acquire_function(func_id) && count) | ||
| 2757 | return false; | ||
| 2758 | |||
| 2758 | /* We only support one arg being unreferenced at the moment, | 2759 | /* We only support one arg being unreferenced at the moment, |
| 2759 | * which is sufficient for the helper functions we have right now. | 2760 | * which is sufficient for the helper functions we have right now. |
| 2760 | */ | 2761 | */ |
| 2761 | return count <= 1; | 2762 | return count <= 1; |
| 2762 | } | 2763 | } |
| 2763 | 2764 | ||
| 2764 | static int check_func_proto(const struct bpf_func_proto *fn) | 2765 | static int check_func_proto(const struct bpf_func_proto *fn, int func_id) |
| 2765 | { | 2766 | { |
| 2766 | return check_raw_mode_ok(fn) && | 2767 | return check_raw_mode_ok(fn) && |
| 2767 | check_arg_pair_ok(fn) && | 2768 | check_arg_pair_ok(fn) && |
| 2768 | check_refcount_ok(fn) ? 0 : -EINVAL; | 2769 | check_refcount_ok(fn, func_id) ? 0 : -EINVAL; |
| 2769 | } | 2770 | } |
| 2770 | 2771 | ||
| 2771 | /* Packet data might have moved, any old PTR_TO_PACKET[_META,_END] | 2772 | /* Packet data might have moved, any old PTR_TO_PACKET[_META,_END] |
| @@ -2799,19 +2800,20 @@ static void clear_all_pkt_pointers(struct bpf_verifier_env *env) | |||
| 2799 | } | 2800 | } |
| 2800 | 2801 | ||
| 2801 | static void release_reg_references(struct bpf_verifier_env *env, | 2802 | static void release_reg_references(struct bpf_verifier_env *env, |
| 2802 | struct bpf_func_state *state, int id) | 2803 | struct bpf_func_state *state, |
| 2804 | int ref_obj_id) | ||
| 2803 | { | 2805 | { |
| 2804 | struct bpf_reg_state *regs = state->regs, *reg; | 2806 | struct bpf_reg_state *regs = state->regs, *reg; |
| 2805 | int i; | 2807 | int i; |
| 2806 | 2808 | ||
| 2807 | for (i = 0; i < MAX_BPF_REG; i++) | 2809 | for (i = 0; i < MAX_BPF_REG; i++) |
| 2808 | if (regs[i].id == id) | 2810 | if (regs[i].ref_obj_id == ref_obj_id) |
| 2809 | mark_reg_unknown(env, regs, i); | 2811 | mark_reg_unknown(env, regs, i); |
| 2810 | 2812 | ||
| 2811 | bpf_for_each_spilled_reg(i, state, reg) { | 2813 | bpf_for_each_spilled_reg(i, state, reg) { |
| 2812 | if (!reg) | 2814 | if (!reg) |
| 2813 | continue; | 2815 | continue; |
| 2814 | if (reg_is_refcounted(reg) && reg->id == id) | 2816 | if (reg->ref_obj_id == ref_obj_id) |
| 2815 | __mark_reg_unknown(reg); | 2817 | __mark_reg_unknown(reg); |
| 2816 | } | 2818 | } |
| 2817 | } | 2819 | } |
| @@ -2820,15 +2822,20 @@ static void release_reg_references(struct bpf_verifier_env *env, | |||
| 2820 | * resources. Identify all copies of the same pointer and clear the reference. | 2822 | * resources. Identify all copies of the same pointer and clear the reference. |
| 2821 | */ | 2823 | */ |
| 2822 | static int release_reference(struct bpf_verifier_env *env, | 2824 | static int release_reference(struct bpf_verifier_env *env, |
| 2823 | struct bpf_call_arg_meta *meta) | 2825 | int ref_obj_id) |
| 2824 | { | 2826 | { |
| 2825 | struct bpf_verifier_state *vstate = env->cur_state; | 2827 | struct bpf_verifier_state *vstate = env->cur_state; |
| 2828 | int err; | ||
| 2826 | int i; | 2829 | int i; |
| 2827 | 2830 | ||
| 2831 | err = release_reference_state(cur_func(env), ref_obj_id); | ||
| 2832 | if (err) | ||
| 2833 | return err; | ||
| 2834 | |||
| 2828 | for (i = 0; i <= vstate->curframe; i++) | 2835 | for (i = 0; i <= vstate->curframe; i++) |
| 2829 | release_reg_references(env, vstate->frame[i], meta->ptr_id); | 2836 | release_reg_references(env, vstate->frame[i], ref_obj_id); |
| 2830 | 2837 | ||
| 2831 | return release_reference_state(cur_func(env), meta->ptr_id); | 2838 | return 0; |
| 2832 | } | 2839 | } |
| 2833 | 2840 | ||
| 2834 | static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn, | 2841 | static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn, |
| @@ -3047,7 +3054,7 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn | |||
| 3047 | memset(&meta, 0, sizeof(meta)); | 3054 | memset(&meta, 0, sizeof(meta)); |
| 3048 | meta.pkt_access = fn->pkt_access; | 3055 | meta.pkt_access = fn->pkt_access; |
| 3049 | 3056 | ||
| 3050 | err = check_func_proto(fn); | 3057 | err = check_func_proto(fn, func_id); |
| 3051 | if (err) { | 3058 | if (err) { |
| 3052 | verbose(env, "kernel subsystem misconfigured func %s#%d\n", | 3059 | verbose(env, "kernel subsystem misconfigured func %s#%d\n", |
| 3053 | func_id_name(func_id), func_id); | 3060 | func_id_name(func_id), func_id); |
| @@ -3093,7 +3100,7 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn | |||
| 3093 | return err; | 3100 | return err; |
| 3094 | } | 3101 | } |
| 3095 | } else if (is_release_function(func_id)) { | 3102 | } else if (is_release_function(func_id)) { |
| 3096 | err = release_reference(env, &meta); | 3103 | err = release_reference(env, meta.ref_obj_id); |
| 3097 | if (err) { | 3104 | if (err) { |
| 3098 | verbose(env, "func %s#%d reference has not been acquired before\n", | 3105 | verbose(env, "func %s#%d reference has not been acquired before\n", |
| 3099 | func_id_name(func_id), func_id); | 3106 | func_id_name(func_id), func_id); |
| @@ -3154,8 +3161,10 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn | |||
| 3154 | 3161 | ||
| 3155 | if (id < 0) | 3162 | if (id < 0) |
| 3156 | return id; | 3163 | return id; |
| 3157 | /* For release_reference() */ | 3164 | /* For mark_ptr_or_null_reg() */ |
| 3158 | regs[BPF_REG_0].id = id; | 3165 | regs[BPF_REG_0].id = id; |
| 3166 | /* For release_reference() */ | ||
| 3167 | regs[BPF_REG_0].ref_obj_id = id; | ||
| 3159 | } else { | 3168 | } else { |
| 3160 | /* For mark_ptr_or_null_reg() */ | 3169 | /* For mark_ptr_or_null_reg() */ |
| 3161 | regs[BPF_REG_0].id = ++env->id_gen; | 3170 | regs[BPF_REG_0].id = ++env->id_gen; |
| @@ -3170,6 +3179,10 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn | |||
| 3170 | return -EINVAL; | 3179 | return -EINVAL; |
| 3171 | } | 3180 | } |
| 3172 | 3181 | ||
| 3182 | if (is_ptr_cast_function(func_id)) | ||
| 3183 | /* For release_reference() */ | ||
| 3184 | regs[BPF_REG_0].ref_obj_id = meta.ref_obj_id; | ||
| 3185 | |||
| 3173 | do_refine_retval_range(regs, fn->ret_type, func_id, &meta); | 3186 | do_refine_retval_range(regs, fn->ret_type, func_id, &meta); |
| 3174 | 3187 | ||
| 3175 | err = check_map_func_compatibility(env, meta.map_ptr, func_id); | 3188 | err = check_map_func_compatibility(env, meta.map_ptr, func_id); |
| @@ -3368,7 +3381,7 @@ do_sim: | |||
| 3368 | *dst_reg = *ptr_reg; | 3381 | *dst_reg = *ptr_reg; |
| 3369 | } | 3382 | } |
| 3370 | ret = push_stack(env, env->insn_idx + 1, env->insn_idx, true); | 3383 | ret = push_stack(env, env->insn_idx + 1, env->insn_idx, true); |
| 3371 | if (!ptr_is_dst_reg) | 3384 | if (!ptr_is_dst_reg && ret) |
| 3372 | *dst_reg = tmp; | 3385 | *dst_reg = tmp; |
| 3373 | return !ret ? -EFAULT : 0; | 3386 | return !ret ? -EFAULT : 0; |
| 3374 | } | 3387 | } |
| @@ -4665,11 +4678,19 @@ static void mark_ptr_or_null_reg(struct bpf_func_state *state, | |||
| 4665 | } else if (reg->type == PTR_TO_TCP_SOCK_OR_NULL) { | 4678 | } else if (reg->type == PTR_TO_TCP_SOCK_OR_NULL) { |
| 4666 | reg->type = PTR_TO_TCP_SOCK; | 4679 | reg->type = PTR_TO_TCP_SOCK; |
| 4667 | } | 4680 | } |
| 4668 | if (is_null || !(reg_is_refcounted(reg) || | 4681 | if (is_null) { |
| 4669 | reg_may_point_to_spin_lock(reg))) { | 4682 | /* We don't need id and ref_obj_id from this point |
| 4670 | /* We don't need id from this point onwards anymore, | 4683 | * onwards anymore, thus we should better reset it, |
| 4671 | * thus we should better reset it, so that state | 4684 | * so that state pruning has chances to take effect. |
| 4672 | * pruning has chances to take effect. | 4685 | */ |
| 4686 | reg->id = 0; | ||
| 4687 | reg->ref_obj_id = 0; | ||
| 4688 | } else if (!reg_may_point_to_spin_lock(reg)) { | ||
| 4689 | /* For not-NULL ptr, reg->ref_obj_id will be reset | ||
| 4690 | * in release_reg_references(). | ||
| 4691 | * | ||
| 4692 | * reg->id is still used by spin_lock ptr. Other | ||
| 4693 | * than spin_lock ptr type, reg->id can be reset. | ||
| 4673 | */ | 4694 | */ |
| 4674 | reg->id = 0; | 4695 | reg->id = 0; |
| 4675 | } | 4696 | } |
| @@ -4684,11 +4705,16 @@ static void mark_ptr_or_null_regs(struct bpf_verifier_state *vstate, u32 regno, | |||
| 4684 | { | 4705 | { |
| 4685 | struct bpf_func_state *state = vstate->frame[vstate->curframe]; | 4706 | struct bpf_func_state *state = vstate->frame[vstate->curframe]; |
| 4686 | struct bpf_reg_state *reg, *regs = state->regs; | 4707 | struct bpf_reg_state *reg, *regs = state->regs; |
| 4708 | u32 ref_obj_id = regs[regno].ref_obj_id; | ||
| 4687 | u32 id = regs[regno].id; | 4709 | u32 id = regs[regno].id; |
| 4688 | int i, j; | 4710 | int i, j; |
| 4689 | 4711 | ||
| 4690 | if (reg_is_refcounted_or_null(®s[regno]) && is_null) | 4712 | if (ref_obj_id && ref_obj_id == id && is_null) |
| 4691 | release_reference_state(state, id); | 4713 | /* regs[regno] is in the " == NULL" branch. |
| 4714 | * No one could have freed the reference state before | ||
| 4715 | * doing the NULL check. | ||
| 4716 | */ | ||
| 4717 | WARN_ON_ONCE(release_reference_state(state, id)); | ||
| 4692 | 4718 | ||
| 4693 | for (i = 0; i < MAX_BPF_REG; i++) | 4719 | for (i = 0; i < MAX_BPF_REG; i++) |
| 4694 | mark_ptr_or_null_reg(state, ®s[i], id, is_null); | 4720 | mark_ptr_or_null_reg(state, ®s[i], id, is_null); |
| @@ -6052,15 +6078,17 @@ static int propagate_liveness(struct bpf_verifier_env *env, | |||
| 6052 | } | 6078 | } |
| 6053 | /* Propagate read liveness of registers... */ | 6079 | /* Propagate read liveness of registers... */ |
| 6054 | BUILD_BUG_ON(BPF_REG_FP + 1 != MAX_BPF_REG); | 6080 | BUILD_BUG_ON(BPF_REG_FP + 1 != MAX_BPF_REG); |
| 6055 | /* We don't need to worry about FP liveness because it's read-only */ | 6081 | for (frame = 0; frame <= vstate->curframe; frame++) { |
| 6056 | for (i = 0; i < BPF_REG_FP; i++) { | 6082 | /* We don't need to worry about FP liveness, it's read-only */ |
| 6057 | if (vparent->frame[vparent->curframe]->regs[i].live & REG_LIVE_READ) | 6083 | for (i = frame < vstate->curframe ? BPF_REG_6 : 0; i < BPF_REG_FP; i++) { |
| 6058 | continue; | 6084 | if (vparent->frame[frame]->regs[i].live & REG_LIVE_READ) |
| 6059 | if (vstate->frame[vstate->curframe]->regs[i].live & REG_LIVE_READ) { | 6085 | continue; |
| 6060 | err = mark_reg_read(env, &vstate->frame[vstate->curframe]->regs[i], | 6086 | if (vstate->frame[frame]->regs[i].live & REG_LIVE_READ) { |
| 6061 | &vparent->frame[vstate->curframe]->regs[i]); | 6087 | err = mark_reg_read(env, &vstate->frame[frame]->regs[i], |
| 6062 | if (err) | 6088 | &vparent->frame[frame]->regs[i]); |
| 6063 | return err; | 6089 | if (err) |
| 6090 | return err; | ||
| 6091 | } | ||
| 6064 | } | 6092 | } |
| 6065 | } | 6093 | } |
| 6066 | 6094 | ||
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index fa79323331b2..26c8ca9bd06b 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -1992,7 +1992,7 @@ static void print_bug_type(void) | |||
| 1992 | * modifying the code. @failed should be one of either: | 1992 | * modifying the code. @failed should be one of either: |
| 1993 | * EFAULT - if the problem happens on reading the @ip address | 1993 | * EFAULT - if the problem happens on reading the @ip address |
| 1994 | * EINVAL - if what is read at @ip is not what was expected | 1994 | * EINVAL - if what is read at @ip is not what was expected |
| 1995 | * EPERM - if the problem happens on writting to the @ip address | 1995 | * EPERM - if the problem happens on writing to the @ip address |
| 1996 | */ | 1996 | */ |
| 1997 | void ftrace_bug(int failed, struct dyn_ftrace *rec) | 1997 | void ftrace_bug(int failed, struct dyn_ftrace *rec) |
| 1998 | { | 1998 | { |
| @@ -2391,7 +2391,7 @@ __ftrace_replace_code(struct dyn_ftrace *rec, int enable) | |||
| 2391 | return ftrace_modify_call(rec, ftrace_old_addr, ftrace_addr); | 2391 | return ftrace_modify_call(rec, ftrace_old_addr, ftrace_addr); |
| 2392 | } | 2392 | } |
| 2393 | 2393 | ||
| 2394 | return -1; /* unknow ftrace bug */ | 2394 | return -1; /* unknown ftrace bug */ |
| 2395 | } | 2395 | } |
| 2396 | 2396 | ||
| 2397 | void __weak ftrace_replace_code(int mod_flags) | 2397 | void __weak ftrace_replace_code(int mod_flags) |
| @@ -3004,7 +3004,7 @@ ftrace_allocate_pages(unsigned long num_to_init) | |||
| 3004 | int cnt; | 3004 | int cnt; |
| 3005 | 3005 | ||
| 3006 | if (!num_to_init) | 3006 | if (!num_to_init) |
| 3007 | return 0; | 3007 | return NULL; |
| 3008 | 3008 | ||
| 3009 | start_pg = pg = kzalloc(sizeof(*pg), GFP_KERNEL); | 3009 | start_pg = pg = kzalloc(sizeof(*pg), GFP_KERNEL); |
| 3010 | if (!pg) | 3010 | if (!pg) |
| @@ -4755,7 +4755,7 @@ static int | |||
| 4755 | ftrace_set_addr(struct ftrace_ops *ops, unsigned long ip, int remove, | 4755 | ftrace_set_addr(struct ftrace_ops *ops, unsigned long ip, int remove, |
| 4756 | int reset, int enable) | 4756 | int reset, int enable) |
| 4757 | { | 4757 | { |
| 4758 | return ftrace_set_hash(ops, 0, 0, ip, remove, reset, enable); | 4758 | return ftrace_set_hash(ops, NULL, 0, ip, remove, reset, enable); |
| 4759 | } | 4759 | } |
| 4760 | 4760 | ||
| 4761 | /** | 4761 | /** |
| @@ -5463,7 +5463,7 @@ void ftrace_create_filter_files(struct ftrace_ops *ops, | |||
| 5463 | 5463 | ||
| 5464 | /* | 5464 | /* |
| 5465 | * The name "destroy_filter_files" is really a misnomer. Although | 5465 | * The name "destroy_filter_files" is really a misnomer. Although |
| 5466 | * in the future, it may actualy delete the files, but this is | 5466 | * in the future, it may actually delete the files, but this is |
| 5467 | * really intended to make sure the ops passed in are disabled | 5467 | * really intended to make sure the ops passed in are disabled |
| 5468 | * and that when this function returns, the caller is free to | 5468 | * and that when this function returns, the caller is free to |
| 5469 | * free the ops. | 5469 | * free the ops. |
| @@ -5786,7 +5786,7 @@ void ftrace_module_enable(struct module *mod) | |||
| 5786 | /* | 5786 | /* |
| 5787 | * If the tracing is enabled, go ahead and enable the record. | 5787 | * If the tracing is enabled, go ahead and enable the record. |
| 5788 | * | 5788 | * |
| 5789 | * The reason not to enable the record immediatelly is the | 5789 | * The reason not to enable the record immediately is the |
| 5790 | * inherent check of ftrace_make_nop/ftrace_make_call for | 5790 | * inherent check of ftrace_make_nop/ftrace_make_call for |
| 5791 | * correct previous instructions. Making first the NOP | 5791 | * correct previous instructions. Making first the NOP |
| 5792 | * conversion puts the module to the correct state, thus | 5792 | * conversion puts the module to the correct state, thus |
diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c index dd1f43588d70..fa100ed3b4de 100644 --- a/kernel/trace/trace_dynevent.c +++ b/kernel/trace/trace_dynevent.c | |||
| @@ -74,7 +74,7 @@ int dyn_event_release(int argc, char **argv, struct dyn_event_operations *type) | |||
| 74 | static int create_dyn_event(int argc, char **argv) | 74 | static int create_dyn_event(int argc, char **argv) |
| 75 | { | 75 | { |
| 76 | struct dyn_event_operations *ops; | 76 | struct dyn_event_operations *ops; |
| 77 | int ret; | 77 | int ret = -ENODEV; |
| 78 | 78 | ||
| 79 | if (argv[0][0] == '-' || argv[0][0] == '!') | 79 | if (argv[0][0] == '-' || argv[0][0] == '!') |
| 80 | return dyn_event_release(argc, argv, NULL); | 80 | return dyn_event_release(argc, argv, NULL); |
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index ca46339f3009..795aa2038377 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c | |||
| @@ -3713,7 +3713,6 @@ static void track_data_destroy(struct hist_trigger_data *hist_data, | |||
| 3713 | struct trace_event_file *file = hist_data->event_file; | 3713 | struct trace_event_file *file = hist_data->event_file; |
| 3714 | 3714 | ||
| 3715 | destroy_hist_field(data->track_data.track_var, 0); | 3715 | destroy_hist_field(data->track_data.track_var, 0); |
| 3716 | destroy_hist_field(data->track_data.var_ref, 0); | ||
| 3717 | 3716 | ||
| 3718 | if (data->action == ACTION_SNAPSHOT) { | 3717 | if (data->action == ACTION_SNAPSHOT) { |
| 3719 | struct track_data *track_data; | 3718 | struct track_data *track_data; |
diff --git a/lib/rhashtable.c b/lib/rhashtable.c index 0a105d4af166..97f59abc3e92 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c | |||
| @@ -416,8 +416,12 @@ static void rht_deferred_worker(struct work_struct *work) | |||
| 416 | else if (tbl->nest) | 416 | else if (tbl->nest) |
| 417 | err = rhashtable_rehash_alloc(ht, tbl, tbl->size); | 417 | err = rhashtable_rehash_alloc(ht, tbl, tbl->size); |
| 418 | 418 | ||
| 419 | if (!err) | 419 | if (!err || err == -EEXIST) { |
| 420 | err = rhashtable_rehash_table(ht); | 420 | int nerr; |
| 421 | |||
| 422 | nerr = rhashtable_rehash_table(ht); | ||
| 423 | err = err ?: nerr; | ||
| 424 | } | ||
| 421 | 425 | ||
| 422 | mutex_unlock(&ht->mutex); | 426 | mutex_unlock(&ht->mutex); |
| 423 | 427 | ||
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index 49a16cee2aae..420a98bf79b5 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c | |||
| @@ -879,15 +879,24 @@ static struct notifier_block aarp_notifier = { | |||
| 879 | 879 | ||
| 880 | static unsigned char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 }; | 880 | static unsigned char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 }; |
| 881 | 881 | ||
| 882 | void __init aarp_proto_init(void) | 882 | int __init aarp_proto_init(void) |
| 883 | { | 883 | { |
| 884 | int rc; | ||
| 885 | |||
| 884 | aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv); | 886 | aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv); |
| 885 | if (!aarp_dl) | 887 | if (!aarp_dl) { |
| 886 | printk(KERN_CRIT "Unable to register AARP with SNAP.\n"); | 888 | printk(KERN_CRIT "Unable to register AARP with SNAP.\n"); |
| 889 | return -ENOMEM; | ||
| 890 | } | ||
| 887 | timer_setup(&aarp_timer, aarp_expire_timeout, 0); | 891 | timer_setup(&aarp_timer, aarp_expire_timeout, 0); |
| 888 | aarp_timer.expires = jiffies + sysctl_aarp_expiry_time; | 892 | aarp_timer.expires = jiffies + sysctl_aarp_expiry_time; |
| 889 | add_timer(&aarp_timer); | 893 | add_timer(&aarp_timer); |
| 890 | register_netdevice_notifier(&aarp_notifier); | 894 | rc = register_netdevice_notifier(&aarp_notifier); |
| 895 | if (rc) { | ||
| 896 | del_timer_sync(&aarp_timer); | ||
| 897 | unregister_snap_client(aarp_dl); | ||
| 898 | } | ||
| 899 | return rc; | ||
| 891 | } | 900 | } |
| 892 | 901 | ||
| 893 | /* Remove the AARP entries associated with a device. */ | 902 | /* Remove the AARP entries associated with a device. */ |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 795fbc6c06aa..709d2542f729 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
| @@ -1904,9 +1904,6 @@ static unsigned char ddp_snap_id[] = { 0x08, 0x00, 0x07, 0x80, 0x9B }; | |||
| 1904 | EXPORT_SYMBOL(atrtr_get_dev); | 1904 | EXPORT_SYMBOL(atrtr_get_dev); |
| 1905 | EXPORT_SYMBOL(atalk_find_dev_addr); | 1905 | EXPORT_SYMBOL(atalk_find_dev_addr); |
| 1906 | 1906 | ||
| 1907 | static const char atalk_err_snap[] __initconst = | ||
| 1908 | KERN_CRIT "Unable to register DDP with SNAP.\n"; | ||
| 1909 | |||
| 1910 | /* Called by proto.c on kernel start up */ | 1907 | /* Called by proto.c on kernel start up */ |
| 1911 | static int __init atalk_init(void) | 1908 | static int __init atalk_init(void) |
| 1912 | { | 1909 | { |
| @@ -1921,17 +1918,22 @@ static int __init atalk_init(void) | |||
| 1921 | goto out_proto; | 1918 | goto out_proto; |
| 1922 | 1919 | ||
| 1923 | ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv); | 1920 | ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv); |
| 1924 | if (!ddp_dl) | 1921 | if (!ddp_dl) { |
| 1925 | printk(atalk_err_snap); | 1922 | pr_crit("Unable to register DDP with SNAP.\n"); |
| 1923 | goto out_sock; | ||
| 1924 | } | ||
| 1926 | 1925 | ||
| 1927 | dev_add_pack(<alk_packet_type); | 1926 | dev_add_pack(<alk_packet_type); |
| 1928 | dev_add_pack(&ppptalk_packet_type); | 1927 | dev_add_pack(&ppptalk_packet_type); |
| 1929 | 1928 | ||
| 1930 | rc = register_netdevice_notifier(&ddp_notifier); | 1929 | rc = register_netdevice_notifier(&ddp_notifier); |
| 1931 | if (rc) | 1930 | if (rc) |
| 1932 | goto out_sock; | 1931 | goto out_snap; |
| 1932 | |||
| 1933 | rc = aarp_proto_init(); | ||
| 1934 | if (rc) | ||
| 1935 | goto out_dev; | ||
| 1933 | 1936 | ||
| 1934 | aarp_proto_init(); | ||
| 1935 | rc = atalk_proc_init(); | 1937 | rc = atalk_proc_init(); |
| 1936 | if (rc) | 1938 | if (rc) |
| 1937 | goto out_aarp; | 1939 | goto out_aarp; |
| @@ -1945,11 +1947,13 @@ out_proc: | |||
| 1945 | atalk_proc_exit(); | 1947 | atalk_proc_exit(); |
| 1946 | out_aarp: | 1948 | out_aarp: |
| 1947 | aarp_cleanup_module(); | 1949 | aarp_cleanup_module(); |
| 1950 | out_dev: | ||
| 1948 | unregister_netdevice_notifier(&ddp_notifier); | 1951 | unregister_netdevice_notifier(&ddp_notifier); |
| 1949 | out_sock: | 1952 | out_snap: |
| 1950 | dev_remove_pack(&ppptalk_packet_type); | 1953 | dev_remove_pack(&ppptalk_packet_type); |
| 1951 | dev_remove_pack(<alk_packet_type); | 1954 | dev_remove_pack(<alk_packet_type); |
| 1952 | unregister_snap_client(ddp_dl); | 1955 | unregister_snap_client(ddp_dl); |
| 1956 | out_sock: | ||
| 1953 | sock_unregister(PF_APPLETALK); | 1957 | sock_unregister(PF_APPLETALK); |
| 1954 | out_proto: | 1958 | out_proto: |
| 1955 | proto_unregister(&ddp_proto); | 1959 | proto_unregister(&ddp_proto); |
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index 9d34de68571b..22afa566cbce 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c | |||
| @@ -502,6 +502,7 @@ static unsigned int br_nf_pre_routing(void *priv, | |||
| 502 | nf_bridge->ipv4_daddr = ip_hdr(skb)->daddr; | 502 | nf_bridge->ipv4_daddr = ip_hdr(skb)->daddr; |
| 503 | 503 | ||
| 504 | skb->protocol = htons(ETH_P_IP); | 504 | skb->protocol = htons(ETH_P_IP); |
| 505 | skb->transport_header = skb->network_header + ip_hdr(skb)->ihl * 4; | ||
| 505 | 506 | ||
| 506 | NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->net, state->sk, skb, | 507 | NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->net, state->sk, skb, |
| 507 | skb->dev, NULL, | 508 | skb->dev, NULL, |
diff --git a/net/bridge/br_netfilter_ipv6.c b/net/bridge/br_netfilter_ipv6.c index 564710f88f93..e88d6641647b 100644 --- a/net/bridge/br_netfilter_ipv6.c +++ b/net/bridge/br_netfilter_ipv6.c | |||
| @@ -235,6 +235,8 @@ unsigned int br_nf_pre_routing_ipv6(void *priv, | |||
| 235 | nf_bridge->ipv6_daddr = ipv6_hdr(skb)->daddr; | 235 | nf_bridge->ipv6_daddr = ipv6_hdr(skb)->daddr; |
| 236 | 236 | ||
| 237 | skb->protocol = htons(ETH_P_IPV6); | 237 | skb->protocol = htons(ETH_P_IPV6); |
| 238 | skb->transport_header = skb->network_header + sizeof(struct ipv6hdr); | ||
| 239 | |||
| 238 | NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, state->net, state->sk, skb, | 240 | NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, state->net, state->sk, skb, |
| 239 | skb->dev, NULL, | 241 | skb->dev, NULL, |
| 240 | br_nf_pre_routing_finish_ipv6); | 242 | br_nf_pre_routing_finish_ipv6); |
diff --git a/net/core/devlink.c b/net/core/devlink.c index 78e22cea4cc7..da0a29f30885 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c | |||
| @@ -3897,6 +3897,11 @@ static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg, | |||
| 3897 | continue; | 3897 | continue; |
| 3898 | } | 3898 | } |
| 3899 | 3899 | ||
| 3900 | if (!devlink->ops->info_get) { | ||
| 3901 | idx++; | ||
| 3902 | continue; | ||
| 3903 | } | ||
| 3904 | |||
| 3900 | mutex_lock(&devlink->lock); | 3905 | mutex_lock(&devlink->lock); |
| 3901 | err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET, | 3906 | err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET, |
| 3902 | NETLINK_CB(cb->skb).portid, | 3907 | NETLINK_CB(cb->skb).portid, |
diff --git a/net/core/filter.c b/net/core/filter.c index f274620945ff..647c63a7b25b 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
| @@ -1796,8 +1796,6 @@ static const struct bpf_func_proto bpf_skb_pull_data_proto = { | |||
| 1796 | 1796 | ||
| 1797 | BPF_CALL_1(bpf_sk_fullsock, struct sock *, sk) | 1797 | BPF_CALL_1(bpf_sk_fullsock, struct sock *, sk) |
| 1798 | { | 1798 | { |
| 1799 | sk = sk_to_full_sk(sk); | ||
| 1800 | |||
| 1801 | return sk_fullsock(sk) ? (unsigned long)sk : (unsigned long)NULL; | 1799 | return sk_fullsock(sk) ? (unsigned long)sk : (unsigned long)NULL; |
| 1802 | } | 1800 | } |
| 1803 | 1801 | ||
| @@ -5266,7 +5264,7 @@ static const struct bpf_func_proto bpf_sk_release_proto = { | |||
| 5266 | .func = bpf_sk_release, | 5264 | .func = bpf_sk_release, |
| 5267 | .gpl_only = false, | 5265 | .gpl_only = false, |
| 5268 | .ret_type = RET_INTEGER, | 5266 | .ret_type = RET_INTEGER, |
| 5269 | .arg1_type = ARG_PTR_TO_SOCKET, | 5267 | .arg1_type = ARG_PTR_TO_SOCK_COMMON, |
| 5270 | }; | 5268 | }; |
| 5271 | 5269 | ||
| 5272 | BPF_CALL_5(bpf_xdp_sk_lookup_udp, struct xdp_buff *, ctx, | 5270 | BPF_CALL_5(bpf_xdp_sk_lookup_udp, struct xdp_buff *, ctx, |
| @@ -5407,8 +5405,6 @@ u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type, | |||
| 5407 | 5405 | ||
| 5408 | BPF_CALL_1(bpf_tcp_sock, struct sock *, sk) | 5406 | BPF_CALL_1(bpf_tcp_sock, struct sock *, sk) |
| 5409 | { | 5407 | { |
| 5410 | sk = sk_to_full_sk(sk); | ||
| 5411 | |||
| 5412 | if (sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP) | 5408 | if (sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP) |
| 5413 | return (unsigned long)sk; | 5409 | return (unsigned long)sk; |
| 5414 | 5410 | ||
| @@ -5422,6 +5418,23 @@ static const struct bpf_func_proto bpf_tcp_sock_proto = { | |||
| 5422 | .arg1_type = ARG_PTR_TO_SOCK_COMMON, | 5418 | .arg1_type = ARG_PTR_TO_SOCK_COMMON, |
| 5423 | }; | 5419 | }; |
| 5424 | 5420 | ||
| 5421 | BPF_CALL_1(bpf_get_listener_sock, struct sock *, sk) | ||
| 5422 | { | ||
| 5423 | sk = sk_to_full_sk(sk); | ||
| 5424 | |||
| 5425 | if (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_RCU_FREE)) | ||
| 5426 | return (unsigned long)sk; | ||
| 5427 | |||
| 5428 | return (unsigned long)NULL; | ||
| 5429 | } | ||
| 5430 | |||
| 5431 | static const struct bpf_func_proto bpf_get_listener_sock_proto = { | ||
| 5432 | .func = bpf_get_listener_sock, | ||
| 5433 | .gpl_only = false, | ||
| 5434 | .ret_type = RET_PTR_TO_SOCKET_OR_NULL, | ||
| 5435 | .arg1_type = ARG_PTR_TO_SOCK_COMMON, | ||
| 5436 | }; | ||
| 5437 | |||
| 5425 | BPF_CALL_1(bpf_skb_ecn_set_ce, struct sk_buff *, skb) | 5438 | BPF_CALL_1(bpf_skb_ecn_set_ce, struct sk_buff *, skb) |
| 5426 | { | 5439 | { |
| 5427 | unsigned int iphdr_len; | 5440 | unsigned int iphdr_len; |
| @@ -5607,6 +5620,8 @@ cg_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) | |||
| 5607 | #ifdef CONFIG_INET | 5620 | #ifdef CONFIG_INET |
| 5608 | case BPF_FUNC_tcp_sock: | 5621 | case BPF_FUNC_tcp_sock: |
| 5609 | return &bpf_tcp_sock_proto; | 5622 | return &bpf_tcp_sock_proto; |
| 5623 | case BPF_FUNC_get_listener_sock: | ||
| 5624 | return &bpf_get_listener_sock_proto; | ||
| 5610 | case BPF_FUNC_skb_ecn_set_ce: | 5625 | case BPF_FUNC_skb_ecn_set_ce: |
| 5611 | return &bpf_skb_ecn_set_ce_proto; | 5626 | return &bpf_skb_ecn_set_ce_proto; |
| 5612 | #endif | 5627 | #endif |
| @@ -5702,6 +5717,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) | |||
| 5702 | return &bpf_sk_release_proto; | 5717 | return &bpf_sk_release_proto; |
| 5703 | case BPF_FUNC_tcp_sock: | 5718 | case BPF_FUNC_tcp_sock: |
| 5704 | return &bpf_tcp_sock_proto; | 5719 | return &bpf_tcp_sock_proto; |
| 5720 | case BPF_FUNC_get_listener_sock: | ||
| 5721 | return &bpf_get_listener_sock_proto; | ||
| 5705 | #endif | 5722 | #endif |
| 5706 | default: | 5723 | default: |
| 5707 | return bpf_base_func_proto(func_id); | 5724 | return bpf_base_func_proto(func_id); |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 4ff661f6f989..f8f94303a1f5 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
| @@ -928,6 +928,8 @@ static int rx_queue_add_kobject(struct net_device *dev, int index) | |||
| 928 | if (error) | 928 | if (error) |
| 929 | return error; | 929 | return error; |
| 930 | 930 | ||
| 931 | dev_hold(queue->dev); | ||
| 932 | |||
| 931 | if (dev->sysfs_rx_queue_group) { | 933 | if (dev->sysfs_rx_queue_group) { |
| 932 | error = sysfs_create_group(kobj, dev->sysfs_rx_queue_group); | 934 | error = sysfs_create_group(kobj, dev->sysfs_rx_queue_group); |
| 933 | if (error) { | 935 | if (error) { |
| @@ -937,7 +939,6 @@ static int rx_queue_add_kobject(struct net_device *dev, int index) | |||
| 937 | } | 939 | } |
| 938 | 940 | ||
| 939 | kobject_uevent(kobj, KOBJ_ADD); | 941 | kobject_uevent(kobj, KOBJ_ADD); |
| 940 | dev_hold(queue->dev); | ||
| 941 | 942 | ||
| 942 | return error; | 943 | return error; |
| 943 | } | 944 | } |
| @@ -1464,6 +1465,8 @@ static int netdev_queue_add_kobject(struct net_device *dev, int index) | |||
| 1464 | if (error) | 1465 | if (error) |
| 1465 | return error; | 1466 | return error; |
| 1466 | 1467 | ||
| 1468 | dev_hold(queue->dev); | ||
| 1469 | |||
| 1467 | #ifdef CONFIG_BQL | 1470 | #ifdef CONFIG_BQL |
| 1468 | error = sysfs_create_group(kobj, &dql_group); | 1471 | error = sysfs_create_group(kobj, &dql_group); |
| 1469 | if (error) { | 1472 | if (error) { |
| @@ -1473,7 +1476,6 @@ static int netdev_queue_add_kobject(struct net_device *dev, int index) | |||
| 1473 | #endif | 1476 | #endif |
| 1474 | 1477 | ||
| 1475 | kobject_uevent(kobj, KOBJ_ADD); | 1478 | kobject_uevent(kobj, KOBJ_ADD); |
| 1476 | dev_hold(queue->dev); | ||
| 1477 | 1479 | ||
| 1478 | return 0; | 1480 | return 0; |
| 1479 | } | 1481 | } |
| @@ -1745,16 +1747,20 @@ int netdev_register_kobject(struct net_device *ndev) | |||
| 1745 | 1747 | ||
| 1746 | error = device_add(dev); | 1748 | error = device_add(dev); |
| 1747 | if (error) | 1749 | if (error) |
| 1748 | return error; | 1750 | goto error_put_device; |
| 1749 | 1751 | ||
| 1750 | error = register_queue_kobjects(ndev); | 1752 | error = register_queue_kobjects(ndev); |
| 1751 | if (error) { | 1753 | if (error) |
| 1752 | device_del(dev); | 1754 | goto error_device_del; |
| 1753 | return error; | ||
| 1754 | } | ||
| 1755 | 1755 | ||
| 1756 | pm_runtime_set_memalloc_noio(dev, true); | 1756 | pm_runtime_set_memalloc_noio(dev, true); |
| 1757 | 1757 | ||
| 1758 | return 0; | ||
| 1759 | |||
| 1760 | error_device_del: | ||
| 1761 | device_del(dev); | ||
| 1762 | error_put_device: | ||
| 1763 | put_device(dev); | ||
| 1758 | return error; | 1764 | return error; |
| 1759 | } | 1765 | } |
| 1760 | 1766 | ||
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index d5740bad5b18..57d84e9b7b6f 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
| @@ -436,8 +436,8 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk, | |||
| 436 | newnp->ipv6_mc_list = NULL; | 436 | newnp->ipv6_mc_list = NULL; |
| 437 | newnp->ipv6_ac_list = NULL; | 437 | newnp->ipv6_ac_list = NULL; |
| 438 | newnp->ipv6_fl_list = NULL; | 438 | newnp->ipv6_fl_list = NULL; |
| 439 | newnp->mcast_oif = inet6_iif(skb); | 439 | newnp->mcast_oif = inet_iif(skb); |
| 440 | newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; | 440 | newnp->mcast_hops = ip_hdr(skb)->ttl; |
| 441 | 441 | ||
| 442 | /* | 442 | /* |
| 443 | * No need to charge this sock to the relevant IPv6 refcnt debug socks count | 443 | * No need to charge this sock to the relevant IPv6 refcnt debug socks count |
diff --git a/net/ipv6/netfilter/ip6t_srh.c b/net/ipv6/netfilter/ip6t_srh.c index 1059894a6f4c..4cb83fb69844 100644 --- a/net/ipv6/netfilter/ip6t_srh.c +++ b/net/ipv6/netfilter/ip6t_srh.c | |||
| @@ -210,6 +210,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 210 | psidoff = srhoff + sizeof(struct ipv6_sr_hdr) + | 210 | psidoff = srhoff + sizeof(struct ipv6_sr_hdr) + |
| 211 | ((srh->segments_left + 1) * sizeof(struct in6_addr)); | 211 | ((srh->segments_left + 1) * sizeof(struct in6_addr)); |
| 212 | psid = skb_header_pointer(skb, psidoff, sizeof(_psid), &_psid); | 212 | psid = skb_header_pointer(skb, psidoff, sizeof(_psid), &_psid); |
| 213 | if (!psid) | ||
| 214 | return false; | ||
| 213 | if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_PSID, | 215 | if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_PSID, |
| 214 | ipv6_masked_addr_cmp(psid, &srhinfo->psid_msk, | 216 | ipv6_masked_addr_cmp(psid, &srhinfo->psid_msk, |
| 215 | &srhinfo->psid_addr))) | 217 | &srhinfo->psid_addr))) |
| @@ -223,6 +225,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 223 | nsidoff = srhoff + sizeof(struct ipv6_sr_hdr) + | 225 | nsidoff = srhoff + sizeof(struct ipv6_sr_hdr) + |
| 224 | ((srh->segments_left - 1) * sizeof(struct in6_addr)); | 226 | ((srh->segments_left - 1) * sizeof(struct in6_addr)); |
| 225 | nsid = skb_header_pointer(skb, nsidoff, sizeof(_nsid), &_nsid); | 227 | nsid = skb_header_pointer(skb, nsidoff, sizeof(_nsid), &_nsid); |
| 228 | if (!nsid) | ||
| 229 | return false; | ||
| 226 | if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_NSID, | 230 | if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_NSID, |
| 227 | ipv6_masked_addr_cmp(nsid, &srhinfo->nsid_msk, | 231 | ipv6_masked_addr_cmp(nsid, &srhinfo->nsid_msk, |
| 228 | &srhinfo->nsid_addr))) | 232 | &srhinfo->nsid_addr))) |
| @@ -233,6 +237,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 233 | if (srhinfo->mt_flags & IP6T_SRH_LSID) { | 237 | if (srhinfo->mt_flags & IP6T_SRH_LSID) { |
| 234 | lsidoff = srhoff + sizeof(struct ipv6_sr_hdr); | 238 | lsidoff = srhoff + sizeof(struct ipv6_sr_hdr); |
| 235 | lsid = skb_header_pointer(skb, lsidoff, sizeof(_lsid), &_lsid); | 239 | lsid = skb_header_pointer(skb, lsidoff, sizeof(_lsid), &_lsid); |
| 240 | if (!lsid) | ||
| 241 | return false; | ||
| 236 | if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LSID, | 242 | if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LSID, |
| 237 | ipv6_masked_addr_cmp(lsid, &srhinfo->lsid_msk, | 243 | ipv6_masked_addr_cmp(lsid, &srhinfo->lsid_msk, |
| 238 | &srhinfo->lsid_addr))) | 244 | &srhinfo->lsid_addr))) |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 4ef4bbdb49d4..0302e0eb07af 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -1040,14 +1040,20 @@ static struct rt6_info *ip6_create_rt_rcu(struct fib6_info *rt) | |||
| 1040 | struct rt6_info *nrt; | 1040 | struct rt6_info *nrt; |
| 1041 | 1041 | ||
| 1042 | if (!fib6_info_hold_safe(rt)) | 1042 | if (!fib6_info_hold_safe(rt)) |
| 1043 | return NULL; | 1043 | goto fallback; |
| 1044 | 1044 | ||
| 1045 | nrt = ip6_dst_alloc(dev_net(dev), dev, flags); | 1045 | nrt = ip6_dst_alloc(dev_net(dev), dev, flags); |
| 1046 | if (nrt) | 1046 | if (!nrt) { |
| 1047 | ip6_rt_copy_init(nrt, rt); | ||
| 1048 | else | ||
| 1049 | fib6_info_release(rt); | 1047 | fib6_info_release(rt); |
| 1048 | goto fallback; | ||
| 1049 | } | ||
| 1050 | 1050 | ||
| 1051 | ip6_rt_copy_init(nrt, rt); | ||
| 1052 | return nrt; | ||
| 1053 | |||
| 1054 | fallback: | ||
| 1055 | nrt = dev_net(dev)->ipv6.ip6_null_entry; | ||
| 1056 | dst_hold(&nrt->dst); | ||
| 1051 | return nrt; | 1057 | return nrt; |
| 1052 | } | 1058 | } |
| 1053 | 1059 | ||
| @@ -1096,10 +1102,6 @@ restart: | |||
| 1096 | dst_hold(&rt->dst); | 1102 | dst_hold(&rt->dst); |
| 1097 | } else { | 1103 | } else { |
| 1098 | rt = ip6_create_rt_rcu(f6i); | 1104 | rt = ip6_create_rt_rcu(f6i); |
| 1099 | if (!rt) { | ||
| 1100 | rt = net->ipv6.ip6_null_entry; | ||
| 1101 | dst_hold(&rt->dst); | ||
| 1102 | } | ||
| 1103 | } | 1105 | } |
| 1104 | 1106 | ||
| 1105 | rcu_read_unlock(); | 1107 | rcu_read_unlock(); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 57ef69a10889..44d431849d39 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -1110,11 +1110,11 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * | |||
| 1110 | newnp->ipv6_fl_list = NULL; | 1110 | newnp->ipv6_fl_list = NULL; |
| 1111 | newnp->pktoptions = NULL; | 1111 | newnp->pktoptions = NULL; |
| 1112 | newnp->opt = NULL; | 1112 | newnp->opt = NULL; |
| 1113 | newnp->mcast_oif = tcp_v6_iif(skb); | 1113 | newnp->mcast_oif = inet_iif(skb); |
| 1114 | newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; | 1114 | newnp->mcast_hops = ip_hdr(skb)->ttl; |
| 1115 | newnp->rcv_flowinfo = ip6_flowinfo(ipv6_hdr(skb)); | 1115 | newnp->rcv_flowinfo = 0; |
| 1116 | if (np->repflow) | 1116 | if (np->repflow) |
| 1117 | newnp->flow_label = ip6_flowlabel(ipv6_hdr(skb)); | 1117 | newnp->flow_label = 0; |
| 1118 | 1118 | ||
| 1119 | /* | 1119 | /* |
| 1120 | * No need to charge this sock to the relevant IPv6 refcnt debug socks count | 1120 | * No need to charge this sock to the relevant IPv6 refcnt debug socks count |
diff --git a/net/mpls/mpls_iptunnel.c b/net/mpls/mpls_iptunnel.c index dda8930f20e7..f3a8557494d6 100644 --- a/net/mpls/mpls_iptunnel.c +++ b/net/mpls/mpls_iptunnel.c | |||
| @@ -140,9 +140,15 @@ static int mpls_xmit(struct sk_buff *skb) | |||
| 140 | if (rt) | 140 | if (rt) |
| 141 | err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gateway, | 141 | err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gateway, |
| 142 | skb); | 142 | skb); |
| 143 | else if (rt6) | 143 | else if (rt6) { |
| 144 | err = neigh_xmit(NEIGH_ND_TABLE, out_dev, &rt6->rt6i_gateway, | 144 | if (ipv6_addr_v4mapped(&rt6->rt6i_gateway)) { |
| 145 | skb); | 145 | /* 6PE (RFC 4798) */ |
| 146 | err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt6->rt6i_gateway.s6_addr32[3], | ||
| 147 | skb); | ||
| 148 | } else | ||
| 149 | err = neigh_xmit(NEIGH_ND_TABLE, out_dev, &rt6->rt6i_gateway, | ||
| 150 | skb); | ||
| 151 | } | ||
| 146 | if (err) | 152 | if (err) |
| 147 | net_dbg_ratelimited("%s: packet transmission failed: %d\n", | 153 | net_dbg_ratelimited("%s: packet transmission failed: %d\n", |
| 148 | __func__, err); | 154 | __func__, err); |
diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c index 5d782445d2fc..bad17bba8ba7 100644 --- a/net/ncsi/ncsi-netlink.c +++ b/net/ncsi/ncsi-netlink.c | |||
| @@ -251,6 +251,10 @@ static int ncsi_pkg_info_all_nl(struct sk_buff *skb, | |||
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | attr = nla_nest_start(skb, NCSI_ATTR_PACKAGE_LIST); | 253 | attr = nla_nest_start(skb, NCSI_ATTR_PACKAGE_LIST); |
| 254 | if (!attr) { | ||
| 255 | rc = -EMSGSIZE; | ||
| 256 | goto err; | ||
| 257 | } | ||
| 254 | rc = ncsi_write_package_info(skb, ndp, package->id); | 258 | rc = ncsi_write_package_info(skb, ndp, package->id); |
| 255 | if (rc) { | 259 | if (rc) { |
| 256 | nla_nest_cancel(skb, attr); | 260 | nla_nest_cancel(skb, attr); |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index d43ffb09939b..6548271209a0 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
| @@ -1007,6 +1007,7 @@ config NETFILTER_XT_TARGET_TEE | |||
| 1007 | depends on NETFILTER_ADVANCED | 1007 | depends on NETFILTER_ADVANCED |
| 1008 | depends on IPV6 || IPV6=n | 1008 | depends on IPV6 || IPV6=n |
| 1009 | depends on !NF_CONNTRACK || NF_CONNTRACK | 1009 | depends on !NF_CONNTRACK || NF_CONNTRACK |
| 1010 | depends on IP6_NF_IPTABLES || !IP6_NF_IPTABLES | ||
| 1010 | select NF_DUP_IPV4 | 1011 | select NF_DUP_IPV4 |
| 1011 | select NF_DUP_IPV6 if IP6_NF_IPTABLES | 1012 | select NF_DUP_IPV6 if IP6_NF_IPTABLES |
| 1012 | ---help--- | 1013 | ---help--- |
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index f067c6b50857..39fcc1ed18f3 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
| @@ -20,9 +20,9 @@ | |||
| 20 | #include <linux/udp.h> | 20 | #include <linux/udp.h> |
| 21 | #include <linux/tcp.h> | 21 | #include <linux/tcp.h> |
| 22 | #include <linux/netfilter.h> | 22 | #include <linux/netfilter.h> |
| 23 | #include <linux/netfilter_ipv4.h> | ||
| 24 | #include <linux/netfilter_ipv6.h> | ||
| 23 | 25 | ||
| 24 | #include <net/route.h> | ||
| 25 | #include <net/ip6_route.h> | ||
| 26 | #include <net/netfilter/nf_conntrack.h> | 26 | #include <net/netfilter/nf_conntrack.h> |
| 27 | #include <net/netfilter/nf_conntrack_core.h> | 27 | #include <net/netfilter/nf_conntrack_core.h> |
| 28 | #include <net/netfilter/nf_conntrack_expect.h> | 28 | #include <net/netfilter/nf_conntrack_expect.h> |
| @@ -871,38 +871,33 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff, | |||
| 871 | } else if (sip_external_media) { | 871 | } else if (sip_external_media) { |
| 872 | struct net_device *dev = skb_dst(skb)->dev; | 872 | struct net_device *dev = skb_dst(skb)->dev; |
| 873 | struct net *net = dev_net(dev); | 873 | struct net *net = dev_net(dev); |
| 874 | struct rtable *rt; | 874 | struct flowi fl; |
| 875 | struct flowi4 fl4 = {}; | ||
| 876 | #if IS_ENABLED(CONFIG_IPV6) | ||
| 877 | struct flowi6 fl6 = {}; | ||
| 878 | #endif | ||
| 879 | struct dst_entry *dst = NULL; | 875 | struct dst_entry *dst = NULL; |
| 880 | 876 | ||
| 877 | memset(&fl, 0, sizeof(fl)); | ||
| 878 | |||
| 881 | switch (nf_ct_l3num(ct)) { | 879 | switch (nf_ct_l3num(ct)) { |
| 882 | case NFPROTO_IPV4: | 880 | case NFPROTO_IPV4: |
| 883 | fl4.daddr = daddr->ip; | 881 | fl.u.ip4.daddr = daddr->ip; |
| 884 | rt = ip_route_output_key(net, &fl4); | 882 | nf_ip_route(net, &dst, &fl, false); |
| 885 | if (!IS_ERR(rt)) | ||
| 886 | dst = &rt->dst; | ||
| 887 | break; | 883 | break; |
| 888 | 884 | ||
| 889 | #if IS_ENABLED(CONFIG_IPV6) | ||
| 890 | case NFPROTO_IPV6: | 885 | case NFPROTO_IPV6: |
| 891 | fl6.daddr = daddr->in6; | 886 | fl.u.ip6.daddr = daddr->in6; |
| 892 | dst = ip6_route_output(net, NULL, &fl6); | 887 | nf_ip6_route(net, &dst, &fl, false); |
| 893 | if (dst->error) { | ||
| 894 | dst_release(dst); | ||
| 895 | dst = NULL; | ||
| 896 | } | ||
| 897 | break; | 888 | break; |
| 898 | #endif | ||
| 899 | } | 889 | } |
| 900 | 890 | ||
| 901 | /* Don't predict any conntracks when media endpoint is reachable | 891 | /* Don't predict any conntracks when media endpoint is reachable |
| 902 | * through the same interface as the signalling peer. | 892 | * through the same interface as the signalling peer. |
| 903 | */ | 893 | */ |
| 904 | if (dst && dst->dev == dev) | 894 | if (dst) { |
| 905 | return NF_ACCEPT; | 895 | bool external_media = (dst->dev == dev); |
| 896 | |||
| 897 | dst_release(dst); | ||
| 898 | if (external_media) | ||
| 899 | return NF_ACCEPT; | ||
| 900 | } | ||
| 906 | } | 901 | } |
| 907 | 902 | ||
| 908 | /* We need to check whether the registration exists before attempting | 903 | /* We need to check whether the registration exists before attempting |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 513f93118604..ef7772e976cc 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
| @@ -2806,8 +2806,11 @@ err2: | |||
| 2806 | nf_tables_rule_release(&ctx, rule); | 2806 | nf_tables_rule_release(&ctx, rule); |
| 2807 | err1: | 2807 | err1: |
| 2808 | for (i = 0; i < n; i++) { | 2808 | for (i = 0; i < n; i++) { |
| 2809 | if (info[i].ops != NULL) | 2809 | if (info[i].ops) { |
| 2810 | module_put(info[i].ops->type->owner); | 2810 | module_put(info[i].ops->type->owner); |
| 2811 | if (info[i].ops->type->release_ops) | ||
| 2812 | info[i].ops->type->release_ops(info[i].ops); | ||
| 2813 | } | ||
| 2811 | } | 2814 | } |
| 2812 | kvfree(info); | 2815 | kvfree(info); |
| 2813 | return err; | 2816 | return err; |
diff --git a/net/netfilter/nft_objref.c b/net/netfilter/nft_objref.c index 457a9ceb46af..8dfa798ea683 100644 --- a/net/netfilter/nft_objref.c +++ b/net/netfilter/nft_objref.c | |||
| @@ -65,21 +65,34 @@ nla_put_failure: | |||
| 65 | return -1; | 65 | return -1; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | static void nft_objref_destroy(const struct nft_ctx *ctx, | 68 | static void nft_objref_deactivate(const struct nft_ctx *ctx, |
| 69 | const struct nft_expr *expr) | 69 | const struct nft_expr *expr, |
| 70 | enum nft_trans_phase phase) | ||
| 70 | { | 71 | { |
| 71 | struct nft_object *obj = nft_objref_priv(expr); | 72 | struct nft_object *obj = nft_objref_priv(expr); |
| 72 | 73 | ||
| 74 | if (phase == NFT_TRANS_COMMIT) | ||
| 75 | return; | ||
| 76 | |||
| 73 | obj->use--; | 77 | obj->use--; |
| 74 | } | 78 | } |
| 75 | 79 | ||
| 80 | static void nft_objref_activate(const struct nft_ctx *ctx, | ||
| 81 | const struct nft_expr *expr) | ||
| 82 | { | ||
| 83 | struct nft_object *obj = nft_objref_priv(expr); | ||
| 84 | |||
| 85 | obj->use++; | ||
| 86 | } | ||
| 87 | |||
| 76 | static struct nft_expr_type nft_objref_type; | 88 | static struct nft_expr_type nft_objref_type; |
| 77 | static const struct nft_expr_ops nft_objref_ops = { | 89 | static const struct nft_expr_ops nft_objref_ops = { |
| 78 | .type = &nft_objref_type, | 90 | .type = &nft_objref_type, |
| 79 | .size = NFT_EXPR_SIZE(sizeof(struct nft_object *)), | 91 | .size = NFT_EXPR_SIZE(sizeof(struct nft_object *)), |
| 80 | .eval = nft_objref_eval, | 92 | .eval = nft_objref_eval, |
| 81 | .init = nft_objref_init, | 93 | .init = nft_objref_init, |
| 82 | .destroy = nft_objref_destroy, | 94 | .activate = nft_objref_activate, |
| 95 | .deactivate = nft_objref_deactivate, | ||
| 83 | .dump = nft_objref_dump, | 96 | .dump = nft_objref_dump, |
| 84 | }; | 97 | }; |
| 85 | 98 | ||
diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c index f8092926f704..a340cd8a751b 100644 --- a/net/netfilter/nft_redir.c +++ b/net/netfilter/nft_redir.c | |||
| @@ -233,5 +233,5 @@ module_exit(nft_redir_module_exit); | |||
| 233 | 233 | ||
| 234 | MODULE_LICENSE("GPL"); | 234 | MODULE_LICENSE("GPL"); |
| 235 | MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>"); | 235 | MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>"); |
| 236 | MODULE_ALIAS_NFT_AF_EXPR(AF_INET4, "redir"); | 236 | MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "redir"); |
| 237 | MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "redir"); | 237 | MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "redir"); |
diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c index fa61208371f8..321a0036fdf5 100644 --- a/net/netfilter/nft_set_rbtree.c +++ b/net/netfilter/nft_set_rbtree.c | |||
| @@ -308,10 +308,6 @@ static void *nft_rbtree_deactivate(const struct net *net, | |||
| 308 | else if (d > 0) | 308 | else if (d > 0) |
| 309 | parent = parent->rb_right; | 309 | parent = parent->rb_right; |
| 310 | else { | 310 | else { |
| 311 | if (!nft_set_elem_active(&rbe->ext, genmask)) { | ||
| 312 | parent = parent->rb_left; | ||
| 313 | continue; | ||
| 314 | } | ||
| 315 | if (nft_rbtree_interval_end(rbe) && | 311 | if (nft_rbtree_interval_end(rbe) && |
| 316 | !nft_rbtree_interval_end(this)) { | 312 | !nft_rbtree_interval_end(this)) { |
| 317 | parent = parent->rb_left; | 313 | parent = parent->rb_left; |
| @@ -320,6 +316,9 @@ static void *nft_rbtree_deactivate(const struct net *net, | |||
| 320 | nft_rbtree_interval_end(this)) { | 316 | nft_rbtree_interval_end(this)) { |
| 321 | parent = parent->rb_right; | 317 | parent = parent->rb_right; |
| 322 | continue; | 318 | continue; |
| 319 | } else if (!nft_set_elem_active(&rbe->ext, genmask)) { | ||
| 320 | parent = parent->rb_left; | ||
| 321 | continue; | ||
| 323 | } | 322 | } |
| 324 | nft_rbtree_flush(net, set, rbe); | 323 | nft_rbtree_flush(net, set, rbe); |
| 325 | return rbe; | 324 | return rbe; |
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 25eeb6d2a75a..f0ec068e1d02 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
| @@ -366,7 +366,7 @@ int genl_register_family(struct genl_family *family) | |||
| 366 | start, end + 1, GFP_KERNEL); | 366 | start, end + 1, GFP_KERNEL); |
| 367 | if (family->id < 0) { | 367 | if (family->id < 0) { |
| 368 | err = family->id; | 368 | err = family->id; |
| 369 | goto errout_locked; | 369 | goto errout_free; |
| 370 | } | 370 | } |
| 371 | 371 | ||
| 372 | err = genl_validate_assign_mc_groups(family); | 372 | err = genl_validate_assign_mc_groups(family); |
| @@ -385,6 +385,7 @@ int genl_register_family(struct genl_family *family) | |||
| 385 | 385 | ||
| 386 | errout_remove: | 386 | errout_remove: |
| 387 | idr_remove(&genl_fam_idr, family->id); | 387 | idr_remove(&genl_fam_idr, family->id); |
| 388 | errout_free: | ||
| 388 | kfree(family->attrbuf); | 389 | kfree(family->attrbuf); |
| 389 | errout_locked: | 390 | errout_locked: |
| 390 | genl_unlock_all(); | 391 | genl_unlock_all(); |
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index ae296273ce3d..17dcd0b5eb32 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c | |||
| @@ -726,6 +726,10 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
| 726 | llcp_sock->service_name = kmemdup(addr->service_name, | 726 | llcp_sock->service_name = kmemdup(addr->service_name, |
| 727 | llcp_sock->service_name_len, | 727 | llcp_sock->service_name_len, |
| 728 | GFP_KERNEL); | 728 | GFP_KERNEL); |
| 729 | if (!llcp_sock->service_name) { | ||
| 730 | ret = -ENOMEM; | ||
| 731 | goto sock_llcp_release; | ||
| 732 | } | ||
| 729 | 733 | ||
| 730 | nfc_llcp_sock_link(&local->connecting_sockets, sk); | 734 | nfc_llcp_sock_link(&local->connecting_sockets, sk); |
| 731 | 735 | ||
| @@ -745,10 +749,11 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
| 745 | return ret; | 749 | return ret; |
| 746 | 750 | ||
| 747 | sock_unlink: | 751 | sock_unlink: |
| 748 | nfc_llcp_put_ssap(local, llcp_sock->ssap); | ||
| 749 | |||
| 750 | nfc_llcp_sock_unlink(&local->connecting_sockets, sk); | 752 | nfc_llcp_sock_unlink(&local->connecting_sockets, sk); |
| 751 | 753 | ||
| 754 | sock_llcp_release: | ||
| 755 | nfc_llcp_put_ssap(local, llcp_sock->ssap); | ||
| 756 | |||
| 752 | put_dev: | 757 | put_dev: |
| 753 | nfc_put_device(dev); | 758 | nfc_put_device(dev); |
| 754 | 759 | ||
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 6679e96ab1dc..9dd158ab51b3 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
| @@ -448,6 +448,10 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
| 448 | 448 | ||
| 449 | upcall = genlmsg_put(user_skb, 0, 0, &dp_packet_genl_family, | 449 | upcall = genlmsg_put(user_skb, 0, 0, &dp_packet_genl_family, |
| 450 | 0, upcall_info->cmd); | 450 | 0, upcall_info->cmd); |
| 451 | if (!upcall) { | ||
| 452 | err = -EINVAL; | ||
| 453 | goto out; | ||
| 454 | } | ||
| 451 | upcall->dp_ifindex = dp_ifindex; | 455 | upcall->dp_ifindex = dp_ifindex; |
| 452 | 456 | ||
| 453 | err = ovs_nla_put_key(key, key, OVS_PACKET_ATTR_KEY, false, user_skb); | 457 | err = ovs_nla_put_key(key, key, OVS_PACKET_ATTR_KEY, false, user_skb); |
| @@ -460,6 +464,10 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
| 460 | 464 | ||
| 461 | if (upcall_info->egress_tun_info) { | 465 | if (upcall_info->egress_tun_info) { |
| 462 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY); | 466 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY); |
| 467 | if (!nla) { | ||
| 468 | err = -EMSGSIZE; | ||
| 469 | goto out; | ||
| 470 | } | ||
| 463 | err = ovs_nla_put_tunnel_info(user_skb, | 471 | err = ovs_nla_put_tunnel_info(user_skb, |
| 464 | upcall_info->egress_tun_info); | 472 | upcall_info->egress_tun_info); |
| 465 | BUG_ON(err); | 473 | BUG_ON(err); |
| @@ -468,6 +476,10 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
| 468 | 476 | ||
| 469 | if (upcall_info->actions_len) { | 477 | if (upcall_info->actions_len) { |
| 470 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_ACTIONS); | 478 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_ACTIONS); |
| 479 | if (!nla) { | ||
| 480 | err = -EMSGSIZE; | ||
| 481 | goto out; | ||
| 482 | } | ||
| 471 | err = ovs_nla_put_actions(upcall_info->actions, | 483 | err = ovs_nla_put_actions(upcall_info->actions, |
| 472 | upcall_info->actions_len, | 484 | upcall_info->actions_len, |
| 473 | user_skb); | 485 | user_skb); |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8376bc1c1508..9419c5cf4de5 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -1852,7 +1852,8 @@ oom: | |||
| 1852 | 1852 | ||
| 1853 | static void packet_parse_headers(struct sk_buff *skb, struct socket *sock) | 1853 | static void packet_parse_headers(struct sk_buff *skb, struct socket *sock) |
| 1854 | { | 1854 | { |
| 1855 | if (!skb->protocol && sock->type == SOCK_RAW) { | 1855 | if ((!skb->protocol || skb->protocol == htons(ETH_P_ALL)) && |
| 1856 | sock->type == SOCK_RAW) { | ||
| 1856 | skb_reset_mac_header(skb); | 1857 | skb_reset_mac_header(skb); |
| 1857 | skb->protocol = dev_parse_header_protocol(skb); | 1858 | skb->protocol = dev_parse_header_protocol(skb); |
| 1858 | } | 1859 | } |
| @@ -3243,7 +3244,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol, | |||
| 3243 | } | 3244 | } |
| 3244 | 3245 | ||
| 3245 | mutex_lock(&net->packet.sklist_lock); | 3246 | mutex_lock(&net->packet.sklist_lock); |
| 3246 | sk_add_node_rcu(sk, &net->packet.sklist); | 3247 | sk_add_node_tail_rcu(sk, &net->packet.sklist); |
| 3247 | mutex_unlock(&net->packet.sklist_lock); | 3248 | mutex_unlock(&net->packet.sklist_lock); |
| 3248 | 3249 | ||
| 3249 | preempt_disable(); | 3250 | preempt_disable(); |
| @@ -4209,7 +4210,7 @@ static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order) | |||
| 4209 | struct pgv *pg_vec; | 4210 | struct pgv *pg_vec; |
| 4210 | int i; | 4211 | int i; |
| 4211 | 4212 | ||
| 4212 | pg_vec = kcalloc(block_nr, sizeof(struct pgv), GFP_KERNEL); | 4213 | pg_vec = kcalloc(block_nr, sizeof(struct pgv), GFP_KERNEL | __GFP_NOWARN); |
| 4213 | if (unlikely(!pg_vec)) | 4214 | if (unlikely(!pg_vec)) |
| 4214 | goto out; | 4215 | goto out; |
| 4215 | 4216 | ||
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 7ca57741b2fb..7849f286bb93 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c | |||
| @@ -105,16 +105,17 @@ void rose_write_internal(struct sock *sk, int frametype) | |||
| 105 | struct sk_buff *skb; | 105 | struct sk_buff *skb; |
| 106 | unsigned char *dptr; | 106 | unsigned char *dptr; |
| 107 | unsigned char lci1, lci2; | 107 | unsigned char lci1, lci2; |
| 108 | char buffer[100]; | 108 | int maxfaclen = 0; |
| 109 | int len, faclen = 0; | 109 | int len, faclen; |
| 110 | int reserve; | ||
| 110 | 111 | ||
| 111 | len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 1; | 112 | reserve = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + 1; |
| 113 | len = ROSE_MIN_LEN; | ||
| 112 | 114 | ||
| 113 | switch (frametype) { | 115 | switch (frametype) { |
| 114 | case ROSE_CALL_REQUEST: | 116 | case ROSE_CALL_REQUEST: |
| 115 | len += 1 + ROSE_ADDR_LEN + ROSE_ADDR_LEN; | 117 | len += 1 + ROSE_ADDR_LEN + ROSE_ADDR_LEN; |
| 116 | faclen = rose_create_facilities(buffer, rose); | 118 | maxfaclen = 256; |
| 117 | len += faclen; | ||
| 118 | break; | 119 | break; |
| 119 | case ROSE_CALL_ACCEPTED: | 120 | case ROSE_CALL_ACCEPTED: |
| 120 | case ROSE_CLEAR_REQUEST: | 121 | case ROSE_CLEAR_REQUEST: |
| @@ -123,15 +124,16 @@ void rose_write_internal(struct sock *sk, int frametype) | |||
| 123 | break; | 124 | break; |
| 124 | } | 125 | } |
| 125 | 126 | ||
| 126 | if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL) | 127 | skb = alloc_skb(reserve + len + maxfaclen, GFP_ATOMIC); |
| 128 | if (!skb) | ||
| 127 | return; | 129 | return; |
| 128 | 130 | ||
| 129 | /* | 131 | /* |
| 130 | * Space for AX.25 header and PID. | 132 | * Space for AX.25 header and PID. |
| 131 | */ | 133 | */ |
| 132 | skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + 1); | 134 | skb_reserve(skb, reserve); |
| 133 | 135 | ||
| 134 | dptr = skb_put(skb, skb_tailroom(skb)); | 136 | dptr = skb_put(skb, len); |
| 135 | 137 | ||
| 136 | lci1 = (rose->lci >> 8) & 0x0F; | 138 | lci1 = (rose->lci >> 8) & 0x0F; |
| 137 | lci2 = (rose->lci >> 0) & 0xFF; | 139 | lci2 = (rose->lci >> 0) & 0xFF; |
| @@ -146,7 +148,8 @@ void rose_write_internal(struct sock *sk, int frametype) | |||
| 146 | dptr += ROSE_ADDR_LEN; | 148 | dptr += ROSE_ADDR_LEN; |
| 147 | memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); | 149 | memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); |
| 148 | dptr += ROSE_ADDR_LEN; | 150 | dptr += ROSE_ADDR_LEN; |
| 149 | memcpy(dptr, buffer, faclen); | 151 | faclen = rose_create_facilities(dptr, rose); |
| 152 | skb_put(skb, faclen); | ||
| 150 | dptr += faclen; | 153 | dptr += faclen; |
| 151 | break; | 154 | break; |
| 152 | 155 | ||
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c index 736aa9281100..004c762c2e8d 100644 --- a/net/rxrpc/output.c +++ b/net/rxrpc/output.c | |||
| @@ -335,7 +335,6 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb, | |||
| 335 | struct kvec iov[2]; | 335 | struct kvec iov[2]; |
| 336 | rxrpc_serial_t serial; | 336 | rxrpc_serial_t serial; |
| 337 | size_t len; | 337 | size_t len; |
| 338 | bool lost = false; | ||
| 339 | int ret, opt; | 338 | int ret, opt; |
| 340 | 339 | ||
| 341 | _enter(",{%d}", skb->len); | 340 | _enter(",{%d}", skb->len); |
| @@ -393,14 +392,14 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb, | |||
| 393 | static int lose; | 392 | static int lose; |
| 394 | if ((lose++ & 7) == 7) { | 393 | if ((lose++ & 7) == 7) { |
| 395 | ret = 0; | 394 | ret = 0; |
| 396 | lost = true; | 395 | trace_rxrpc_tx_data(call, sp->hdr.seq, serial, |
| 396 | whdr.flags, retrans, true); | ||
| 397 | goto done; | ||
| 397 | } | 398 | } |
| 398 | } | 399 | } |
| 399 | 400 | ||
| 400 | trace_rxrpc_tx_data(call, sp->hdr.seq, serial, whdr.flags, | 401 | trace_rxrpc_tx_data(call, sp->hdr.seq, serial, whdr.flags, retrans, |
| 401 | retrans, lost); | 402 | false); |
| 402 | if (lost) | ||
| 403 | goto done; | ||
| 404 | 403 | ||
| 405 | /* send the packet with the don't fragment bit set if we currently | 404 | /* send the packet with the don't fragment bit set if we currently |
| 406 | * think it's small enough */ | 405 | * think it's small enough */ |
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 1b9afdee5ba9..5c02ad97ef23 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
| @@ -358,8 +358,7 @@ config NET_SCH_PIE | |||
| 358 | help | 358 | help |
| 359 | Say Y here if you want to use the Proportional Integral controller | 359 | Say Y here if you want to use the Proportional Integral controller |
| 360 | Enhanced scheduler packet scheduling algorithm. | 360 | Enhanced scheduler packet scheduling algorithm. |
| 361 | For more information, please see | 361 | For more information, please see https://tools.ietf.org/html/rfc8033 |
| 362 | http://tools.ietf.org/html/draft-pan-tsvwg-pie-00 | ||
| 363 | 362 | ||
| 364 | To compile this driver as a module, choose M here: the module | 363 | To compile this driver as a module, choose M here: the module |
| 365 | will be called sch_pie. | 364 | will be called sch_pie. |
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index aecf1bf233c8..5a87e271d35a 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
| @@ -28,27 +28,10 @@ | |||
| 28 | #include <net/act_api.h> | 28 | #include <net/act_api.h> |
| 29 | #include <net/netlink.h> | 29 | #include <net/netlink.h> |
| 30 | 30 | ||
| 31 | static int tcf_action_goto_chain_init(struct tc_action *a, struct tcf_proto *tp) | ||
| 32 | { | ||
| 33 | u32 chain_index = a->tcfa_action & TC_ACT_EXT_VAL_MASK; | ||
| 34 | |||
| 35 | if (!tp) | ||
| 36 | return -EINVAL; | ||
| 37 | a->goto_chain = tcf_chain_get_by_act(tp->chain->block, chain_index); | ||
| 38 | if (!a->goto_chain) | ||
| 39 | return -ENOMEM; | ||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 43 | static void tcf_action_goto_chain_fini(struct tc_action *a) | ||
| 44 | { | ||
| 45 | tcf_chain_put_by_act(a->goto_chain); | ||
| 46 | } | ||
| 47 | |||
| 48 | static void tcf_action_goto_chain_exec(const struct tc_action *a, | 31 | static void tcf_action_goto_chain_exec(const struct tc_action *a, |
| 49 | struct tcf_result *res) | 32 | struct tcf_result *res) |
| 50 | { | 33 | { |
| 51 | const struct tcf_chain *chain = a->goto_chain; | 34 | const struct tcf_chain *chain = rcu_dereference_bh(a->goto_chain); |
| 52 | 35 | ||
| 53 | res->goto_tp = rcu_dereference_bh(chain->filter_chain); | 36 | res->goto_tp = rcu_dereference_bh(chain->filter_chain); |
| 54 | } | 37 | } |
| @@ -71,6 +54,51 @@ static void tcf_set_action_cookie(struct tc_cookie __rcu **old_cookie, | |||
| 71 | call_rcu(&old->rcu, tcf_free_cookie_rcu); | 54 | call_rcu(&old->rcu, tcf_free_cookie_rcu); |
| 72 | } | 55 | } |
| 73 | 56 | ||
| 57 | int tcf_action_check_ctrlact(int action, struct tcf_proto *tp, | ||
| 58 | struct tcf_chain **newchain, | ||
| 59 | struct netlink_ext_ack *extack) | ||
| 60 | { | ||
| 61 | int opcode = TC_ACT_EXT_OPCODE(action), ret = -EINVAL; | ||
| 62 | u32 chain_index; | ||
| 63 | |||
| 64 | if (!opcode) | ||
| 65 | ret = action > TC_ACT_VALUE_MAX ? -EINVAL : 0; | ||
| 66 | else if (opcode <= TC_ACT_EXT_OPCODE_MAX || action == TC_ACT_UNSPEC) | ||
| 67 | ret = 0; | ||
| 68 | if (ret) { | ||
| 69 | NL_SET_ERR_MSG(extack, "invalid control action"); | ||
| 70 | goto end; | ||
| 71 | } | ||
| 72 | |||
| 73 | if (TC_ACT_EXT_CMP(action, TC_ACT_GOTO_CHAIN)) { | ||
| 74 | chain_index = action & TC_ACT_EXT_VAL_MASK; | ||
| 75 | if (!tp || !newchain) { | ||
| 76 | ret = -EINVAL; | ||
| 77 | NL_SET_ERR_MSG(extack, | ||
| 78 | "can't goto NULL proto/chain"); | ||
| 79 | goto end; | ||
| 80 | } | ||
| 81 | *newchain = tcf_chain_get_by_act(tp->chain->block, chain_index); | ||
| 82 | if (!*newchain) { | ||
| 83 | ret = -ENOMEM; | ||
| 84 | NL_SET_ERR_MSG(extack, | ||
| 85 | "can't allocate goto_chain"); | ||
| 86 | } | ||
| 87 | } | ||
| 88 | end: | ||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | EXPORT_SYMBOL(tcf_action_check_ctrlact); | ||
| 92 | |||
| 93 | struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action, | ||
| 94 | struct tcf_chain *goto_chain) | ||
| 95 | { | ||
| 96 | a->tcfa_action = action; | ||
| 97 | rcu_swap_protected(a->goto_chain, goto_chain, 1); | ||
| 98 | return goto_chain; | ||
| 99 | } | ||
| 100 | EXPORT_SYMBOL(tcf_action_set_ctrlact); | ||
| 101 | |||
| 74 | /* XXX: For standalone actions, we don't need a RCU grace period either, because | 102 | /* XXX: For standalone actions, we don't need a RCU grace period either, because |
| 75 | * actions are always connected to filters and filters are already destroyed in | 103 | * actions are always connected to filters and filters are already destroyed in |
| 76 | * RCU callbacks, so after a RCU grace period actions are already disconnected | 104 | * RCU callbacks, so after a RCU grace period actions are already disconnected |
| @@ -78,13 +106,15 @@ static void tcf_set_action_cookie(struct tc_cookie __rcu **old_cookie, | |||
| 78 | */ | 106 | */ |
| 79 | static void free_tcf(struct tc_action *p) | 107 | static void free_tcf(struct tc_action *p) |
| 80 | { | 108 | { |
| 109 | struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1); | ||
| 110 | |||
| 81 | free_percpu(p->cpu_bstats); | 111 | free_percpu(p->cpu_bstats); |
| 82 | free_percpu(p->cpu_bstats_hw); | 112 | free_percpu(p->cpu_bstats_hw); |
| 83 | free_percpu(p->cpu_qstats); | 113 | free_percpu(p->cpu_qstats); |
| 84 | 114 | ||
| 85 | tcf_set_action_cookie(&p->act_cookie, NULL); | 115 | tcf_set_action_cookie(&p->act_cookie, NULL); |
| 86 | if (p->goto_chain) | 116 | if (chain) |
| 87 | tcf_action_goto_chain_fini(p); | 117 | tcf_chain_put_by_act(chain); |
| 88 | 118 | ||
| 89 | kfree(p); | 119 | kfree(p); |
| 90 | } | 120 | } |
| @@ -654,6 +684,10 @@ repeat: | |||
| 654 | return TC_ACT_OK; | 684 | return TC_ACT_OK; |
| 655 | } | 685 | } |
| 656 | } else if (TC_ACT_EXT_CMP(ret, TC_ACT_GOTO_CHAIN)) { | 686 | } else if (TC_ACT_EXT_CMP(ret, TC_ACT_GOTO_CHAIN)) { |
| 687 | if (unlikely(!rcu_access_pointer(a->goto_chain))) { | ||
| 688 | net_warn_ratelimited("can't go to NULL chain!\n"); | ||
| 689 | return TC_ACT_SHOT; | ||
| 690 | } | ||
| 657 | tcf_action_goto_chain_exec(a, res); | 691 | tcf_action_goto_chain_exec(a, res); |
| 658 | } | 692 | } |
| 659 | 693 | ||
| @@ -800,15 +834,6 @@ static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb) | |||
| 800 | return c; | 834 | return c; |
| 801 | } | 835 | } |
| 802 | 836 | ||
| 803 | static bool tcf_action_valid(int action) | ||
| 804 | { | ||
| 805 | int opcode = TC_ACT_EXT_OPCODE(action); | ||
| 806 | |||
| 807 | if (!opcode) | ||
| 808 | return action <= TC_ACT_VALUE_MAX; | ||
| 809 | return opcode <= TC_ACT_EXT_OPCODE_MAX || action == TC_ACT_UNSPEC; | ||
| 810 | } | ||
| 811 | |||
| 812 | struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, | 837 | struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, |
| 813 | struct nlattr *nla, struct nlattr *est, | 838 | struct nlattr *nla, struct nlattr *est, |
| 814 | char *name, int ovr, int bind, | 839 | char *name, int ovr, int bind, |
| @@ -890,10 +915,10 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, | |||
| 890 | /* backward compatibility for policer */ | 915 | /* backward compatibility for policer */ |
| 891 | if (name == NULL) | 916 | if (name == NULL) |
| 892 | err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind, | 917 | err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind, |
| 893 | rtnl_held, extack); | 918 | rtnl_held, tp, extack); |
| 894 | else | 919 | else |
| 895 | err = a_o->init(net, nla, est, &a, ovr, bind, rtnl_held, | 920 | err = a_o->init(net, nla, est, &a, ovr, bind, rtnl_held, |
| 896 | extack); | 921 | tp, extack); |
| 897 | if (err < 0) | 922 | if (err < 0) |
| 898 | goto err_mod; | 923 | goto err_mod; |
| 899 | 924 | ||
| @@ -907,18 +932,10 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, | |||
| 907 | if (err != ACT_P_CREATED) | 932 | if (err != ACT_P_CREATED) |
| 908 | module_put(a_o->owner); | 933 | module_put(a_o->owner); |
| 909 | 934 | ||
| 910 | if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN)) { | 935 | if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN) && |
| 911 | err = tcf_action_goto_chain_init(a, tp); | 936 | !rcu_access_pointer(a->goto_chain)) { |
| 912 | if (err) { | ||
| 913 | tcf_action_destroy_1(a, bind); | ||
| 914 | NL_SET_ERR_MSG(extack, "Failed to init TC action chain"); | ||
| 915 | return ERR_PTR(err); | ||
| 916 | } | ||
| 917 | } | ||
| 918 | |||
| 919 | if (!tcf_action_valid(a->tcfa_action)) { | ||
| 920 | tcf_action_destroy_1(a, bind); | 937 | tcf_action_destroy_1(a, bind); |
| 921 | NL_SET_ERR_MSG(extack, "Invalid control action value"); | 938 | NL_SET_ERR_MSG(extack, "can't use goto chain with NULL chain"); |
| 922 | return ERR_PTR(-EINVAL); | 939 | return ERR_PTR(-EINVAL); |
| 923 | } | 940 | } |
| 924 | 941 | ||
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c index aa5c38d11a30..3841156aa09f 100644 --- a/net/sched/act_bpf.c +++ b/net/sched/act_bpf.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #include <net/netlink.h> | 18 | #include <net/netlink.h> |
| 19 | #include <net/pkt_sched.h> | 19 | #include <net/pkt_sched.h> |
| 20 | #include <net/pkt_cls.h> | ||
| 20 | 21 | ||
| 21 | #include <linux/tc_act/tc_bpf.h> | 22 | #include <linux/tc_act/tc_bpf.h> |
| 22 | #include <net/tc_act/tc_bpf.h> | 23 | #include <net/tc_act/tc_bpf.h> |
| @@ -278,10 +279,11 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog, | |||
| 278 | static int tcf_bpf_init(struct net *net, struct nlattr *nla, | 279 | static int tcf_bpf_init(struct net *net, struct nlattr *nla, |
| 279 | struct nlattr *est, struct tc_action **act, | 280 | struct nlattr *est, struct tc_action **act, |
| 280 | int replace, int bind, bool rtnl_held, | 281 | int replace, int bind, bool rtnl_held, |
| 281 | struct netlink_ext_ack *extack) | 282 | struct tcf_proto *tp, struct netlink_ext_ack *extack) |
| 282 | { | 283 | { |
| 283 | struct tc_action_net *tn = net_generic(net, bpf_net_id); | 284 | struct tc_action_net *tn = net_generic(net, bpf_net_id); |
| 284 | struct nlattr *tb[TCA_ACT_BPF_MAX + 1]; | 285 | struct nlattr *tb[TCA_ACT_BPF_MAX + 1]; |
| 286 | struct tcf_chain *goto_ch = NULL; | ||
| 285 | struct tcf_bpf_cfg cfg, old; | 287 | struct tcf_bpf_cfg cfg, old; |
| 286 | struct tc_act_bpf *parm; | 288 | struct tc_act_bpf *parm; |
| 287 | struct tcf_bpf *prog; | 289 | struct tcf_bpf *prog; |
| @@ -323,12 +325,16 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
| 323 | return ret; | 325 | return ret; |
| 324 | } | 326 | } |
| 325 | 327 | ||
| 328 | ret = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 329 | if (ret < 0) | ||
| 330 | goto release_idr; | ||
| 331 | |||
| 326 | is_bpf = tb[TCA_ACT_BPF_OPS_LEN] && tb[TCA_ACT_BPF_OPS]; | 332 | is_bpf = tb[TCA_ACT_BPF_OPS_LEN] && tb[TCA_ACT_BPF_OPS]; |
| 327 | is_ebpf = tb[TCA_ACT_BPF_FD]; | 333 | is_ebpf = tb[TCA_ACT_BPF_FD]; |
| 328 | 334 | ||
| 329 | if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf)) { | 335 | if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf)) { |
| 330 | ret = -EINVAL; | 336 | ret = -EINVAL; |
| 331 | goto out; | 337 | goto put_chain; |
| 332 | } | 338 | } |
| 333 | 339 | ||
| 334 | memset(&cfg, 0, sizeof(cfg)); | 340 | memset(&cfg, 0, sizeof(cfg)); |
| @@ -336,7 +342,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
| 336 | ret = is_bpf ? tcf_bpf_init_from_ops(tb, &cfg) : | 342 | ret = is_bpf ? tcf_bpf_init_from_ops(tb, &cfg) : |
| 337 | tcf_bpf_init_from_efd(tb, &cfg); | 343 | tcf_bpf_init_from_efd(tb, &cfg); |
| 338 | if (ret < 0) | 344 | if (ret < 0) |
| 339 | goto out; | 345 | goto put_chain; |
| 340 | 346 | ||
| 341 | prog = to_bpf(*act); | 347 | prog = to_bpf(*act); |
| 342 | 348 | ||
| @@ -350,10 +356,13 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
| 350 | if (cfg.bpf_num_ops) | 356 | if (cfg.bpf_num_ops) |
| 351 | prog->bpf_num_ops = cfg.bpf_num_ops; | 357 | prog->bpf_num_ops = cfg.bpf_num_ops; |
| 352 | 358 | ||
| 353 | prog->tcf_action = parm->action; | 359 | goto_ch = tcf_action_set_ctrlact(*act, parm->action, goto_ch); |
| 354 | rcu_assign_pointer(prog->filter, cfg.filter); | 360 | rcu_assign_pointer(prog->filter, cfg.filter); |
| 355 | spin_unlock_bh(&prog->tcf_lock); | 361 | spin_unlock_bh(&prog->tcf_lock); |
| 356 | 362 | ||
| 363 | if (goto_ch) | ||
| 364 | tcf_chain_put_by_act(goto_ch); | ||
| 365 | |||
| 357 | if (res == ACT_P_CREATED) { | 366 | if (res == ACT_P_CREATED) { |
| 358 | tcf_idr_insert(tn, *act); | 367 | tcf_idr_insert(tn, *act); |
| 359 | } else { | 368 | } else { |
| @@ -363,9 +372,13 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
| 363 | } | 372 | } |
| 364 | 373 | ||
| 365 | return res; | 374 | return res; |
| 366 | out: | ||
| 367 | tcf_idr_release(*act, bind); | ||
| 368 | 375 | ||
| 376 | put_chain: | ||
| 377 | if (goto_ch) | ||
| 378 | tcf_chain_put_by_act(goto_ch); | ||
| 379 | |||
| 380 | release_idr: | ||
| 381 | tcf_idr_release(*act, bind); | ||
| 369 | return ret; | 382 | return ret; |
| 370 | } | 383 | } |
| 371 | 384 | ||
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c index 5d24993cccfe..32ae0cd6e31c 100644 --- a/net/sched/act_connmark.c +++ b/net/sched/act_connmark.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <net/netlink.h> | 21 | #include <net/netlink.h> |
| 22 | #include <net/pkt_sched.h> | 22 | #include <net/pkt_sched.h> |
| 23 | #include <net/act_api.h> | 23 | #include <net/act_api.h> |
| 24 | #include <net/pkt_cls.h> | ||
| 24 | #include <uapi/linux/tc_act/tc_connmark.h> | 25 | #include <uapi/linux/tc_act/tc_connmark.h> |
| 25 | #include <net/tc_act/tc_connmark.h> | 26 | #include <net/tc_act/tc_connmark.h> |
| 26 | 27 | ||
| @@ -97,13 +98,15 @@ static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = { | |||
| 97 | static int tcf_connmark_init(struct net *net, struct nlattr *nla, | 98 | static int tcf_connmark_init(struct net *net, struct nlattr *nla, |
| 98 | struct nlattr *est, struct tc_action **a, | 99 | struct nlattr *est, struct tc_action **a, |
| 99 | int ovr, int bind, bool rtnl_held, | 100 | int ovr, int bind, bool rtnl_held, |
| 101 | struct tcf_proto *tp, | ||
| 100 | struct netlink_ext_ack *extack) | 102 | struct netlink_ext_ack *extack) |
| 101 | { | 103 | { |
| 102 | struct tc_action_net *tn = net_generic(net, connmark_net_id); | 104 | struct tc_action_net *tn = net_generic(net, connmark_net_id); |
| 103 | struct nlattr *tb[TCA_CONNMARK_MAX + 1]; | 105 | struct nlattr *tb[TCA_CONNMARK_MAX + 1]; |
| 106 | struct tcf_chain *goto_ch = NULL; | ||
| 104 | struct tcf_connmark_info *ci; | 107 | struct tcf_connmark_info *ci; |
| 105 | struct tc_connmark *parm; | 108 | struct tc_connmark *parm; |
| 106 | int ret = 0; | 109 | int ret = 0, err; |
| 107 | 110 | ||
| 108 | if (!nla) | 111 | if (!nla) |
| 109 | return -EINVAL; | 112 | return -EINVAL; |
| @@ -128,7 +131,11 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, | |||
| 128 | } | 131 | } |
| 129 | 132 | ||
| 130 | ci = to_connmark(*a); | 133 | ci = to_connmark(*a); |
| 131 | ci->tcf_action = parm->action; | 134 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, |
| 135 | extack); | ||
| 136 | if (err < 0) | ||
| 137 | goto release_idr; | ||
| 138 | tcf_action_set_ctrlact(*a, parm->action, goto_ch); | ||
| 132 | ci->net = net; | 139 | ci->net = net; |
| 133 | ci->zone = parm->zone; | 140 | ci->zone = parm->zone; |
| 134 | 141 | ||
| @@ -142,15 +149,24 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, | |||
| 142 | tcf_idr_release(*a, bind); | 149 | tcf_idr_release(*a, bind); |
| 143 | return -EEXIST; | 150 | return -EEXIST; |
| 144 | } | 151 | } |
| 152 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, | ||
| 153 | extack); | ||
| 154 | if (err < 0) | ||
| 155 | goto release_idr; | ||
| 145 | /* replacing action and zone */ | 156 | /* replacing action and zone */ |
| 146 | spin_lock_bh(&ci->tcf_lock); | 157 | spin_lock_bh(&ci->tcf_lock); |
| 147 | ci->tcf_action = parm->action; | 158 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
| 148 | ci->zone = parm->zone; | 159 | ci->zone = parm->zone; |
| 149 | spin_unlock_bh(&ci->tcf_lock); | 160 | spin_unlock_bh(&ci->tcf_lock); |
| 161 | if (goto_ch) | ||
| 162 | tcf_chain_put_by_act(goto_ch); | ||
| 150 | ret = 0; | 163 | ret = 0; |
| 151 | } | 164 | } |
| 152 | 165 | ||
| 153 | return ret; | 166 | return ret; |
| 167 | release_idr: | ||
| 168 | tcf_idr_release(*a, bind); | ||
| 169 | return err; | ||
| 154 | } | 170 | } |
| 155 | 171 | ||
| 156 | static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, | 172 | static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, |
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c index c79aca29505e..0c77e7bdf6d5 100644 --- a/net/sched/act_csum.c +++ b/net/sched/act_csum.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <net/sctp/checksum.h> | 33 | #include <net/sctp/checksum.h> |
| 34 | 34 | ||
| 35 | #include <net/act_api.h> | 35 | #include <net/act_api.h> |
| 36 | #include <net/pkt_cls.h> | ||
| 36 | 37 | ||
| 37 | #include <linux/tc_act/tc_csum.h> | 38 | #include <linux/tc_act/tc_csum.h> |
| 38 | #include <net/tc_act/tc_csum.h> | 39 | #include <net/tc_act/tc_csum.h> |
| @@ -46,12 +47,13 @@ static struct tc_action_ops act_csum_ops; | |||
| 46 | 47 | ||
| 47 | static int tcf_csum_init(struct net *net, struct nlattr *nla, | 48 | static int tcf_csum_init(struct net *net, struct nlattr *nla, |
| 48 | struct nlattr *est, struct tc_action **a, int ovr, | 49 | struct nlattr *est, struct tc_action **a, int ovr, |
| 49 | int bind, bool rtnl_held, | 50 | int bind, bool rtnl_held, struct tcf_proto *tp, |
| 50 | struct netlink_ext_ack *extack) | 51 | struct netlink_ext_ack *extack) |
| 51 | { | 52 | { |
| 52 | struct tc_action_net *tn = net_generic(net, csum_net_id); | 53 | struct tc_action_net *tn = net_generic(net, csum_net_id); |
| 53 | struct tcf_csum_params *params_new; | 54 | struct tcf_csum_params *params_new; |
| 54 | struct nlattr *tb[TCA_CSUM_MAX + 1]; | 55 | struct nlattr *tb[TCA_CSUM_MAX + 1]; |
| 56 | struct tcf_chain *goto_ch = NULL; | ||
| 55 | struct tc_csum *parm; | 57 | struct tc_csum *parm; |
| 56 | struct tcf_csum *p; | 58 | struct tcf_csum *p; |
| 57 | int ret = 0, err; | 59 | int ret = 0, err; |
| @@ -87,21 +89,27 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla, | |||
| 87 | return err; | 89 | return err; |
| 88 | } | 90 | } |
| 89 | 91 | ||
| 92 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 93 | if (err < 0) | ||
| 94 | goto release_idr; | ||
| 95 | |||
| 90 | p = to_tcf_csum(*a); | 96 | p = to_tcf_csum(*a); |
| 91 | 97 | ||
| 92 | params_new = kzalloc(sizeof(*params_new), GFP_KERNEL); | 98 | params_new = kzalloc(sizeof(*params_new), GFP_KERNEL); |
| 93 | if (unlikely(!params_new)) { | 99 | if (unlikely(!params_new)) { |
| 94 | tcf_idr_release(*a, bind); | 100 | err = -ENOMEM; |
| 95 | return -ENOMEM; | 101 | goto put_chain; |
| 96 | } | 102 | } |
| 97 | params_new->update_flags = parm->update_flags; | 103 | params_new->update_flags = parm->update_flags; |
| 98 | 104 | ||
| 99 | spin_lock_bh(&p->tcf_lock); | 105 | spin_lock_bh(&p->tcf_lock); |
| 100 | p->tcf_action = parm->action; | 106 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
| 101 | rcu_swap_protected(p->params, params_new, | 107 | rcu_swap_protected(p->params, params_new, |
| 102 | lockdep_is_held(&p->tcf_lock)); | 108 | lockdep_is_held(&p->tcf_lock)); |
| 103 | spin_unlock_bh(&p->tcf_lock); | 109 | spin_unlock_bh(&p->tcf_lock); |
| 104 | 110 | ||
| 111 | if (goto_ch) | ||
| 112 | tcf_chain_put_by_act(goto_ch); | ||
| 105 | if (params_new) | 113 | if (params_new) |
| 106 | kfree_rcu(params_new, rcu); | 114 | kfree_rcu(params_new, rcu); |
| 107 | 115 | ||
| @@ -109,6 +117,12 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla, | |||
| 109 | tcf_idr_insert(tn, *a); | 117 | tcf_idr_insert(tn, *a); |
| 110 | 118 | ||
| 111 | return ret; | 119 | return ret; |
| 120 | put_chain: | ||
| 121 | if (goto_ch) | ||
| 122 | tcf_chain_put_by_act(goto_ch); | ||
| 123 | release_idr: | ||
| 124 | tcf_idr_release(*a, bind); | ||
| 125 | return err; | ||
| 112 | } | 126 | } |
| 113 | 127 | ||
| 114 | /** | 128 | /** |
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index 93da0004e9f4..e540e31069d7 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| 21 | #include <net/netlink.h> | 21 | #include <net/netlink.h> |
| 22 | #include <net/pkt_sched.h> | 22 | #include <net/pkt_sched.h> |
| 23 | #include <net/pkt_cls.h> | ||
| 23 | #include <linux/tc_act/tc_gact.h> | 24 | #include <linux/tc_act/tc_gact.h> |
| 24 | #include <net/tc_act/tc_gact.h> | 25 | #include <net/tc_act/tc_gact.h> |
| 25 | 26 | ||
| @@ -57,10 +58,11 @@ static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = { | |||
| 57 | static int tcf_gact_init(struct net *net, struct nlattr *nla, | 58 | static int tcf_gact_init(struct net *net, struct nlattr *nla, |
| 58 | struct nlattr *est, struct tc_action **a, | 59 | struct nlattr *est, struct tc_action **a, |
| 59 | int ovr, int bind, bool rtnl_held, | 60 | int ovr, int bind, bool rtnl_held, |
| 60 | struct netlink_ext_ack *extack) | 61 | struct tcf_proto *tp, struct netlink_ext_ack *extack) |
| 61 | { | 62 | { |
| 62 | struct tc_action_net *tn = net_generic(net, gact_net_id); | 63 | struct tc_action_net *tn = net_generic(net, gact_net_id); |
| 63 | struct nlattr *tb[TCA_GACT_MAX + 1]; | 64 | struct nlattr *tb[TCA_GACT_MAX + 1]; |
| 65 | struct tcf_chain *goto_ch = NULL; | ||
| 64 | struct tc_gact *parm; | 66 | struct tc_gact *parm; |
| 65 | struct tcf_gact *gact; | 67 | struct tcf_gact *gact; |
| 66 | int ret = 0; | 68 | int ret = 0; |
| @@ -116,10 +118,13 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, | |||
| 116 | return err; | 118 | return err; |
| 117 | } | 119 | } |
| 118 | 120 | ||
| 121 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 122 | if (err < 0) | ||
| 123 | goto release_idr; | ||
| 119 | gact = to_gact(*a); | 124 | gact = to_gact(*a); |
| 120 | 125 | ||
| 121 | spin_lock_bh(&gact->tcf_lock); | 126 | spin_lock_bh(&gact->tcf_lock); |
| 122 | gact->tcf_action = parm->action; | 127 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
| 123 | #ifdef CONFIG_GACT_PROB | 128 | #ifdef CONFIG_GACT_PROB |
| 124 | if (p_parm) { | 129 | if (p_parm) { |
| 125 | gact->tcfg_paction = p_parm->paction; | 130 | gact->tcfg_paction = p_parm->paction; |
| @@ -133,9 +138,15 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, | |||
| 133 | #endif | 138 | #endif |
| 134 | spin_unlock_bh(&gact->tcf_lock); | 139 | spin_unlock_bh(&gact->tcf_lock); |
| 135 | 140 | ||
| 141 | if (goto_ch) | ||
| 142 | tcf_chain_put_by_act(goto_ch); | ||
| 143 | |||
| 136 | if (ret == ACT_P_CREATED) | 144 | if (ret == ACT_P_CREATED) |
| 137 | tcf_idr_insert(tn, *a); | 145 | tcf_idr_insert(tn, *a); |
| 138 | return ret; | 146 | return ret; |
| 147 | release_idr: | ||
| 148 | tcf_idr_release(*a, bind); | ||
| 149 | return err; | ||
| 139 | } | 150 | } |
| 140 | 151 | ||
| 141 | static int tcf_gact_act(struct sk_buff *skb, const struct tc_action *a, | 152 | static int tcf_gact_act(struct sk_buff *skb, const struct tc_action *a, |
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c index 9b1f2b3990ee..31c6ffb6abe7 100644 --- a/net/sched/act_ife.c +++ b/net/sched/act_ife.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <net/net_namespace.h> | 29 | #include <net/net_namespace.h> |
| 30 | #include <net/netlink.h> | 30 | #include <net/netlink.h> |
| 31 | #include <net/pkt_sched.h> | 31 | #include <net/pkt_sched.h> |
| 32 | #include <net/pkt_cls.h> | ||
| 32 | #include <uapi/linux/tc_act/tc_ife.h> | 33 | #include <uapi/linux/tc_act/tc_ife.h> |
| 33 | #include <net/tc_act/tc_ife.h> | 34 | #include <net/tc_act/tc_ife.h> |
| 34 | #include <linux/etherdevice.h> | 35 | #include <linux/etherdevice.h> |
| @@ -469,11 +470,12 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb, | |||
| 469 | static int tcf_ife_init(struct net *net, struct nlattr *nla, | 470 | static int tcf_ife_init(struct net *net, struct nlattr *nla, |
| 470 | struct nlattr *est, struct tc_action **a, | 471 | struct nlattr *est, struct tc_action **a, |
| 471 | int ovr, int bind, bool rtnl_held, | 472 | int ovr, int bind, bool rtnl_held, |
| 472 | struct netlink_ext_ack *extack) | 473 | struct tcf_proto *tp, struct netlink_ext_ack *extack) |
| 473 | { | 474 | { |
| 474 | struct tc_action_net *tn = net_generic(net, ife_net_id); | 475 | struct tc_action_net *tn = net_generic(net, ife_net_id); |
| 475 | struct nlattr *tb[TCA_IFE_MAX + 1]; | 476 | struct nlattr *tb[TCA_IFE_MAX + 1]; |
| 476 | struct nlattr *tb2[IFE_META_MAX + 1]; | 477 | struct nlattr *tb2[IFE_META_MAX + 1]; |
| 478 | struct tcf_chain *goto_ch = NULL; | ||
| 477 | struct tcf_ife_params *p; | 479 | struct tcf_ife_params *p; |
| 478 | struct tcf_ife_info *ife; | 480 | struct tcf_ife_info *ife; |
| 479 | u16 ife_type = ETH_P_IFE; | 481 | u16 ife_type = ETH_P_IFE; |
| @@ -531,6 +533,10 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, | |||
| 531 | } | 533 | } |
| 532 | 534 | ||
| 533 | ife = to_ife(*a); | 535 | ife = to_ife(*a); |
| 536 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 537 | if (err < 0) | ||
| 538 | goto release_idr; | ||
| 539 | |||
| 534 | p->flags = parm->flags; | 540 | p->flags = parm->flags; |
| 535 | 541 | ||
| 536 | if (parm->flags & IFE_ENCODE) { | 542 | if (parm->flags & IFE_ENCODE) { |
| @@ -563,13 +569,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, | |||
| 563 | if (tb[TCA_IFE_METALST]) { | 569 | if (tb[TCA_IFE_METALST]) { |
| 564 | err = nla_parse_nested(tb2, IFE_META_MAX, tb[TCA_IFE_METALST], | 570 | err = nla_parse_nested(tb2, IFE_META_MAX, tb[TCA_IFE_METALST], |
| 565 | NULL, NULL); | 571 | NULL, NULL); |
| 566 | if (err) { | 572 | if (err) |
| 567 | metadata_parse_err: | 573 | goto metadata_parse_err; |
| 568 | tcf_idr_release(*a, bind); | ||
| 569 | kfree(p); | ||
| 570 | return err; | ||
| 571 | } | ||
| 572 | |||
| 573 | err = populate_metalist(ife, tb2, exists, rtnl_held); | 574 | err = populate_metalist(ife, tb2, exists, rtnl_held); |
| 574 | if (err) | 575 | if (err) |
| 575 | goto metadata_parse_err; | 576 | goto metadata_parse_err; |
| @@ -581,21 +582,20 @@ metadata_parse_err: | |||
| 581 | * going to bail out | 582 | * going to bail out |
| 582 | */ | 583 | */ |
| 583 | err = use_all_metadata(ife, exists); | 584 | err = use_all_metadata(ife, exists); |
| 584 | if (err) { | 585 | if (err) |
| 585 | tcf_idr_release(*a, bind); | 586 | goto metadata_parse_err; |
| 586 | kfree(p); | ||
| 587 | return err; | ||
| 588 | } | ||
| 589 | } | 587 | } |
| 590 | 588 | ||
| 591 | if (exists) | 589 | if (exists) |
| 592 | spin_lock_bh(&ife->tcf_lock); | 590 | spin_lock_bh(&ife->tcf_lock); |
| 593 | ife->tcf_action = parm->action; | ||
| 594 | /* protected by tcf_lock when modifying existing action */ | 591 | /* protected by tcf_lock when modifying existing action */ |
| 592 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); | ||
| 595 | rcu_swap_protected(ife->params, p, 1); | 593 | rcu_swap_protected(ife->params, p, 1); |
| 596 | 594 | ||
| 597 | if (exists) | 595 | if (exists) |
| 598 | spin_unlock_bh(&ife->tcf_lock); | 596 | spin_unlock_bh(&ife->tcf_lock); |
| 597 | if (goto_ch) | ||
| 598 | tcf_chain_put_by_act(goto_ch); | ||
| 599 | if (p) | 599 | if (p) |
| 600 | kfree_rcu(p, rcu); | 600 | kfree_rcu(p, rcu); |
| 601 | 601 | ||
| @@ -603,6 +603,13 @@ metadata_parse_err: | |||
| 603 | tcf_idr_insert(tn, *a); | 603 | tcf_idr_insert(tn, *a); |
| 604 | 604 | ||
| 605 | return ret; | 605 | return ret; |
| 606 | metadata_parse_err: | ||
| 607 | if (goto_ch) | ||
| 608 | tcf_chain_put_by_act(goto_ch); | ||
| 609 | release_idr: | ||
| 610 | kfree(p); | ||
| 611 | tcf_idr_release(*a, bind); | ||
| 612 | return err; | ||
| 606 | } | 613 | } |
| 607 | 614 | ||
| 608 | static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, | 615 | static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, |
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 98f5b6ea77b4..04a0b5c61194 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
| @@ -97,7 +97,8 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = { | |||
| 97 | 97 | ||
| 98 | static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla, | 98 | static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla, |
| 99 | struct nlattr *est, struct tc_action **a, | 99 | struct nlattr *est, struct tc_action **a, |
| 100 | const struct tc_action_ops *ops, int ovr, int bind) | 100 | const struct tc_action_ops *ops, int ovr, int bind, |
| 101 | struct tcf_proto *tp) | ||
| 101 | { | 102 | { |
| 102 | struct tc_action_net *tn = net_generic(net, id); | 103 | struct tc_action_net *tn = net_generic(net, id); |
| 103 | struct nlattr *tb[TCA_IPT_MAX + 1]; | 104 | struct nlattr *tb[TCA_IPT_MAX + 1]; |
| @@ -205,20 +206,20 @@ err1: | |||
| 205 | 206 | ||
| 206 | static int tcf_ipt_init(struct net *net, struct nlattr *nla, | 207 | static int tcf_ipt_init(struct net *net, struct nlattr *nla, |
| 207 | struct nlattr *est, struct tc_action **a, int ovr, | 208 | struct nlattr *est, struct tc_action **a, int ovr, |
| 208 | int bind, bool rtnl_held, | 209 | int bind, bool rtnl_held, struct tcf_proto *tp, |
| 209 | struct netlink_ext_ack *extack) | 210 | struct netlink_ext_ack *extack) |
| 210 | { | 211 | { |
| 211 | return __tcf_ipt_init(net, ipt_net_id, nla, est, a, &act_ipt_ops, ovr, | 212 | return __tcf_ipt_init(net, ipt_net_id, nla, est, a, &act_ipt_ops, ovr, |
| 212 | bind); | 213 | bind, tp); |
| 213 | } | 214 | } |
| 214 | 215 | ||
| 215 | static int tcf_xt_init(struct net *net, struct nlattr *nla, | 216 | static int tcf_xt_init(struct net *net, struct nlattr *nla, |
| 216 | struct nlattr *est, struct tc_action **a, int ovr, | 217 | struct nlattr *est, struct tc_action **a, int ovr, |
| 217 | int bind, bool unlocked, | 218 | int bind, bool unlocked, struct tcf_proto *tp, |
| 218 | struct netlink_ext_ack *extack) | 219 | struct netlink_ext_ack *extack) |
| 219 | { | 220 | { |
| 220 | return __tcf_ipt_init(net, xt_net_id, nla, est, a, &act_xt_ops, ovr, | 221 | return __tcf_ipt_init(net, xt_net_id, nla, est, a, &act_xt_ops, ovr, |
| 221 | bind); | 222 | bind, tp); |
| 222 | } | 223 | } |
| 223 | 224 | ||
| 224 | static int tcf_ipt_act(struct sk_buff *skb, const struct tc_action *a, | 225 | static int tcf_ipt_act(struct sk_buff *skb, const struct tc_action *a, |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 6692fd054617..17cc6bd4c57c 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
| @@ -94,10 +94,12 @@ static struct tc_action_ops act_mirred_ops; | |||
| 94 | static int tcf_mirred_init(struct net *net, struct nlattr *nla, | 94 | static int tcf_mirred_init(struct net *net, struct nlattr *nla, |
| 95 | struct nlattr *est, struct tc_action **a, | 95 | struct nlattr *est, struct tc_action **a, |
| 96 | int ovr, int bind, bool rtnl_held, | 96 | int ovr, int bind, bool rtnl_held, |
| 97 | struct tcf_proto *tp, | ||
| 97 | struct netlink_ext_ack *extack) | 98 | struct netlink_ext_ack *extack) |
| 98 | { | 99 | { |
| 99 | struct tc_action_net *tn = net_generic(net, mirred_net_id); | 100 | struct tc_action_net *tn = net_generic(net, mirred_net_id); |
| 100 | struct nlattr *tb[TCA_MIRRED_MAX + 1]; | 101 | struct nlattr *tb[TCA_MIRRED_MAX + 1]; |
| 102 | struct tcf_chain *goto_ch = NULL; | ||
| 101 | bool mac_header_xmit = false; | 103 | bool mac_header_xmit = false; |
| 102 | struct tc_mirred *parm; | 104 | struct tc_mirred *parm; |
| 103 | struct tcf_mirred *m; | 105 | struct tcf_mirred *m; |
| @@ -157,18 +159,23 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 157 | tcf_idr_release(*a, bind); | 159 | tcf_idr_release(*a, bind); |
| 158 | return -EEXIST; | 160 | return -EEXIST; |
| 159 | } | 161 | } |
| 162 | |||
| 160 | m = to_mirred(*a); | 163 | m = to_mirred(*a); |
| 164 | if (ret == ACT_P_CREATED) | ||
| 165 | INIT_LIST_HEAD(&m->tcfm_list); | ||
| 166 | |||
| 167 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 168 | if (err < 0) | ||
| 169 | goto release_idr; | ||
| 161 | 170 | ||
| 162 | spin_lock_bh(&m->tcf_lock); | 171 | spin_lock_bh(&m->tcf_lock); |
| 163 | m->tcf_action = parm->action; | ||
| 164 | m->tcfm_eaction = parm->eaction; | ||
| 165 | 172 | ||
| 166 | if (parm->ifindex) { | 173 | if (parm->ifindex) { |
| 167 | dev = dev_get_by_index(net, parm->ifindex); | 174 | dev = dev_get_by_index(net, parm->ifindex); |
| 168 | if (!dev) { | 175 | if (!dev) { |
| 169 | spin_unlock_bh(&m->tcf_lock); | 176 | spin_unlock_bh(&m->tcf_lock); |
| 170 | tcf_idr_release(*a, bind); | 177 | err = -ENODEV; |
| 171 | return -ENODEV; | 178 | goto put_chain; |
| 172 | } | 179 | } |
| 173 | mac_header_xmit = dev_is_mac_header_xmit(dev); | 180 | mac_header_xmit = dev_is_mac_header_xmit(dev); |
| 174 | rcu_swap_protected(m->tcfm_dev, dev, | 181 | rcu_swap_protected(m->tcfm_dev, dev, |
| @@ -177,7 +184,11 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 177 | dev_put(dev); | 184 | dev_put(dev); |
| 178 | m->tcfm_mac_header_xmit = mac_header_xmit; | 185 | m->tcfm_mac_header_xmit = mac_header_xmit; |
| 179 | } | 186 | } |
| 187 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); | ||
| 188 | m->tcfm_eaction = parm->eaction; | ||
| 180 | spin_unlock_bh(&m->tcf_lock); | 189 | spin_unlock_bh(&m->tcf_lock); |
| 190 | if (goto_ch) | ||
| 191 | tcf_chain_put_by_act(goto_ch); | ||
| 181 | 192 | ||
| 182 | if (ret == ACT_P_CREATED) { | 193 | if (ret == ACT_P_CREATED) { |
| 183 | spin_lock(&mirred_list_lock); | 194 | spin_lock(&mirred_list_lock); |
| @@ -188,6 +199,12 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 188 | } | 199 | } |
| 189 | 200 | ||
| 190 | return ret; | 201 | return ret; |
| 202 | put_chain: | ||
| 203 | if (goto_ch) | ||
| 204 | tcf_chain_put_by_act(goto_ch); | ||
| 205 | release_idr: | ||
| 206 | tcf_idr_release(*a, bind); | ||
| 207 | return err; | ||
| 191 | } | 208 | } |
| 192 | 209 | ||
| 193 | static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a, | 210 | static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a, |
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c index 543eab9193f1..e91bb8eb81ec 100644 --- a/net/sched/act_nat.c +++ b/net/sched/act_nat.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
| 22 | #include <linux/tc_act/tc_nat.h> | 22 | #include <linux/tc_act/tc_nat.h> |
| 23 | #include <net/act_api.h> | 23 | #include <net/act_api.h> |
| 24 | #include <net/pkt_cls.h> | ||
| 24 | #include <net/icmp.h> | 25 | #include <net/icmp.h> |
| 25 | #include <net/ip.h> | 26 | #include <net/ip.h> |
| 26 | #include <net/netlink.h> | 27 | #include <net/netlink.h> |
| @@ -38,10 +39,12 @@ static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { | |||
| 38 | 39 | ||
| 39 | static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, | 40 | static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, |
| 40 | struct tc_action **a, int ovr, int bind, | 41 | struct tc_action **a, int ovr, int bind, |
| 41 | bool rtnl_held, struct netlink_ext_ack *extack) | 42 | bool rtnl_held, struct tcf_proto *tp, |
| 43 | struct netlink_ext_ack *extack) | ||
| 42 | { | 44 | { |
| 43 | struct tc_action_net *tn = net_generic(net, nat_net_id); | 45 | struct tc_action_net *tn = net_generic(net, nat_net_id); |
| 44 | struct nlattr *tb[TCA_NAT_MAX + 1]; | 46 | struct nlattr *tb[TCA_NAT_MAX + 1]; |
| 47 | struct tcf_chain *goto_ch = NULL; | ||
| 45 | struct tc_nat *parm; | 48 | struct tc_nat *parm; |
| 46 | int ret = 0, err; | 49 | int ret = 0, err; |
| 47 | struct tcf_nat *p; | 50 | struct tcf_nat *p; |
| @@ -76,6 +79,9 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, | |||
| 76 | } else { | 79 | } else { |
| 77 | return err; | 80 | return err; |
| 78 | } | 81 | } |
| 82 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 83 | if (err < 0) | ||
| 84 | goto release_idr; | ||
| 79 | p = to_tcf_nat(*a); | 85 | p = to_tcf_nat(*a); |
| 80 | 86 | ||
| 81 | spin_lock_bh(&p->tcf_lock); | 87 | spin_lock_bh(&p->tcf_lock); |
| @@ -84,13 +90,18 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, | |||
| 84 | p->mask = parm->mask; | 90 | p->mask = parm->mask; |
| 85 | p->flags = parm->flags; | 91 | p->flags = parm->flags; |
| 86 | 92 | ||
| 87 | p->tcf_action = parm->action; | 93 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
| 88 | spin_unlock_bh(&p->tcf_lock); | 94 | spin_unlock_bh(&p->tcf_lock); |
| 95 | if (goto_ch) | ||
| 96 | tcf_chain_put_by_act(goto_ch); | ||
| 89 | 97 | ||
| 90 | if (ret == ACT_P_CREATED) | 98 | if (ret == ACT_P_CREATED) |
| 91 | tcf_idr_insert(tn, *a); | 99 | tcf_idr_insert(tn, *a); |
| 92 | 100 | ||
| 93 | return ret; | 101 | return ret; |
| 102 | release_idr: | ||
| 103 | tcf_idr_release(*a, bind); | ||
| 104 | return err; | ||
| 94 | } | 105 | } |
| 95 | 106 | ||
| 96 | static int tcf_nat_act(struct sk_buff *skb, const struct tc_action *a, | 107 | static int tcf_nat_act(struct sk_buff *skb, const struct tc_action *a, |
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index a80373878df7..287793abfaf9 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/tc_act/tc_pedit.h> | 23 | #include <linux/tc_act/tc_pedit.h> |
| 24 | #include <net/tc_act/tc_pedit.h> | 24 | #include <net/tc_act/tc_pedit.h> |
| 25 | #include <uapi/linux/tc_act/tc_pedit.h> | 25 | #include <uapi/linux/tc_act/tc_pedit.h> |
| 26 | #include <net/pkt_cls.h> | ||
| 26 | 27 | ||
| 27 | static unsigned int pedit_net_id; | 28 | static unsigned int pedit_net_id; |
| 28 | static struct tc_action_ops act_pedit_ops; | 29 | static struct tc_action_ops act_pedit_ops; |
| @@ -138,10 +139,11 @@ nla_failure: | |||
| 138 | static int tcf_pedit_init(struct net *net, struct nlattr *nla, | 139 | static int tcf_pedit_init(struct net *net, struct nlattr *nla, |
| 139 | struct nlattr *est, struct tc_action **a, | 140 | struct nlattr *est, struct tc_action **a, |
| 140 | int ovr, int bind, bool rtnl_held, | 141 | int ovr, int bind, bool rtnl_held, |
| 141 | struct netlink_ext_ack *extack) | 142 | struct tcf_proto *tp, struct netlink_ext_ack *extack) |
| 142 | { | 143 | { |
| 143 | struct tc_action_net *tn = net_generic(net, pedit_net_id); | 144 | struct tc_action_net *tn = net_generic(net, pedit_net_id); |
| 144 | struct nlattr *tb[TCA_PEDIT_MAX + 1]; | 145 | struct nlattr *tb[TCA_PEDIT_MAX + 1]; |
| 146 | struct tcf_chain *goto_ch = NULL; | ||
| 145 | struct tc_pedit_key *keys = NULL; | 147 | struct tc_pedit_key *keys = NULL; |
| 146 | struct tcf_pedit_key_ex *keys_ex; | 148 | struct tcf_pedit_key_ex *keys_ex; |
| 147 | struct tc_pedit *parm; | 149 | struct tc_pedit *parm; |
| @@ -205,6 +207,11 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, | |||
| 205 | goto out_free; | 207 | goto out_free; |
| 206 | } | 208 | } |
| 207 | 209 | ||
| 210 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 211 | if (err < 0) { | ||
| 212 | ret = err; | ||
| 213 | goto out_release; | ||
| 214 | } | ||
| 208 | p = to_pedit(*a); | 215 | p = to_pedit(*a); |
| 209 | spin_lock_bh(&p->tcf_lock); | 216 | spin_lock_bh(&p->tcf_lock); |
| 210 | 217 | ||
| @@ -214,7 +221,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, | |||
| 214 | if (!keys) { | 221 | if (!keys) { |
| 215 | spin_unlock_bh(&p->tcf_lock); | 222 | spin_unlock_bh(&p->tcf_lock); |
| 216 | ret = -ENOMEM; | 223 | ret = -ENOMEM; |
| 217 | goto out_release; | 224 | goto put_chain; |
| 218 | } | 225 | } |
| 219 | kfree(p->tcfp_keys); | 226 | kfree(p->tcfp_keys); |
| 220 | p->tcfp_keys = keys; | 227 | p->tcfp_keys = keys; |
| @@ -223,16 +230,21 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, | |||
| 223 | memcpy(p->tcfp_keys, parm->keys, ksize); | 230 | memcpy(p->tcfp_keys, parm->keys, ksize); |
| 224 | 231 | ||
| 225 | p->tcfp_flags = parm->flags; | 232 | p->tcfp_flags = parm->flags; |
| 226 | p->tcf_action = parm->action; | 233 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
| 227 | 234 | ||
| 228 | kfree(p->tcfp_keys_ex); | 235 | kfree(p->tcfp_keys_ex); |
| 229 | p->tcfp_keys_ex = keys_ex; | 236 | p->tcfp_keys_ex = keys_ex; |
| 230 | 237 | ||
| 231 | spin_unlock_bh(&p->tcf_lock); | 238 | spin_unlock_bh(&p->tcf_lock); |
| 239 | if (goto_ch) | ||
| 240 | tcf_chain_put_by_act(goto_ch); | ||
| 232 | if (ret == ACT_P_CREATED) | 241 | if (ret == ACT_P_CREATED) |
| 233 | tcf_idr_insert(tn, *a); | 242 | tcf_idr_insert(tn, *a); |
| 234 | return ret; | 243 | return ret; |
| 235 | 244 | ||
| 245 | put_chain: | ||
| 246 | if (goto_ch) | ||
| 247 | tcf_chain_put_by_act(goto_ch); | ||
| 236 | out_release: | 248 | out_release: |
| 237 | tcf_idr_release(*a, bind); | 249 | tcf_idr_release(*a, bind); |
| 238 | out_free: | 250 | out_free: |
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 8271a6263824..2b8581f6ab51 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 22 | #include <net/act_api.h> | 22 | #include <net/act_api.h> |
| 23 | #include <net/netlink.h> | 23 | #include <net/netlink.h> |
| 24 | #include <net/pkt_cls.h> | ||
| 24 | 25 | ||
| 25 | struct tcf_police_params { | 26 | struct tcf_police_params { |
| 26 | int tcfp_result; | 27 | int tcfp_result; |
| @@ -83,10 +84,12 @@ static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = { | |||
| 83 | static int tcf_police_init(struct net *net, struct nlattr *nla, | 84 | static int tcf_police_init(struct net *net, struct nlattr *nla, |
| 84 | struct nlattr *est, struct tc_action **a, | 85 | struct nlattr *est, struct tc_action **a, |
| 85 | int ovr, int bind, bool rtnl_held, | 86 | int ovr, int bind, bool rtnl_held, |
| 87 | struct tcf_proto *tp, | ||
| 86 | struct netlink_ext_ack *extack) | 88 | struct netlink_ext_ack *extack) |
| 87 | { | 89 | { |
| 88 | int ret = 0, tcfp_result = TC_ACT_OK, err, size; | 90 | int ret = 0, tcfp_result = TC_ACT_OK, err, size; |
| 89 | struct nlattr *tb[TCA_POLICE_MAX + 1]; | 91 | struct nlattr *tb[TCA_POLICE_MAX + 1]; |
| 92 | struct tcf_chain *goto_ch = NULL; | ||
| 90 | struct tc_police *parm; | 93 | struct tc_police *parm; |
| 91 | struct tcf_police *police; | 94 | struct tcf_police *police; |
| 92 | struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; | 95 | struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; |
| @@ -128,6 +131,9 @@ static int tcf_police_init(struct net *net, struct nlattr *nla, | |||
| 128 | tcf_idr_release(*a, bind); | 131 | tcf_idr_release(*a, bind); |
| 129 | return -EEXIST; | 132 | return -EEXIST; |
| 130 | } | 133 | } |
| 134 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 135 | if (err < 0) | ||
| 136 | goto release_idr; | ||
| 131 | 137 | ||
| 132 | police = to_police(*a); | 138 | police = to_police(*a); |
| 133 | if (parm->rate.rate) { | 139 | if (parm->rate.rate) { |
| @@ -213,12 +219,14 @@ static int tcf_police_init(struct net *net, struct nlattr *nla, | |||
| 213 | if (new->peak_present) | 219 | if (new->peak_present) |
| 214 | police->tcfp_ptoks = new->tcfp_mtu_ptoks; | 220 | police->tcfp_ptoks = new->tcfp_mtu_ptoks; |
| 215 | spin_unlock_bh(&police->tcfp_lock); | 221 | spin_unlock_bh(&police->tcfp_lock); |
| 216 | police->tcf_action = parm->action; | 222 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
| 217 | rcu_swap_protected(police->params, | 223 | rcu_swap_protected(police->params, |
| 218 | new, | 224 | new, |
| 219 | lockdep_is_held(&police->tcf_lock)); | 225 | lockdep_is_held(&police->tcf_lock)); |
| 220 | spin_unlock_bh(&police->tcf_lock); | 226 | spin_unlock_bh(&police->tcf_lock); |
| 221 | 227 | ||
| 228 | if (goto_ch) | ||
| 229 | tcf_chain_put_by_act(goto_ch); | ||
| 222 | if (new) | 230 | if (new) |
| 223 | kfree_rcu(new, rcu); | 231 | kfree_rcu(new, rcu); |
| 224 | 232 | ||
| @@ -229,6 +237,9 @@ static int tcf_police_init(struct net *net, struct nlattr *nla, | |||
| 229 | failure: | 237 | failure: |
| 230 | qdisc_put_rtab(P_tab); | 238 | qdisc_put_rtab(P_tab); |
| 231 | qdisc_put_rtab(R_tab); | 239 | qdisc_put_rtab(R_tab); |
| 240 | if (goto_ch) | ||
| 241 | tcf_chain_put_by_act(goto_ch); | ||
| 242 | release_idr: | ||
| 232 | tcf_idr_release(*a, bind); | 243 | tcf_idr_release(*a, bind); |
| 233 | return err; | 244 | return err; |
| 234 | } | 245 | } |
diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c index 203e399e5c85..4060b0955c97 100644 --- a/net/sched/act_sample.c +++ b/net/sched/act_sample.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/tc_act/tc_sample.h> | 22 | #include <linux/tc_act/tc_sample.h> |
| 23 | #include <net/tc_act/tc_sample.h> | 23 | #include <net/tc_act/tc_sample.h> |
| 24 | #include <net/psample.h> | 24 | #include <net/psample.h> |
| 25 | #include <net/pkt_cls.h> | ||
| 25 | 26 | ||
| 26 | #include <linux/if_arp.h> | 27 | #include <linux/if_arp.h> |
| 27 | 28 | ||
| @@ -37,12 +38,13 @@ static const struct nla_policy sample_policy[TCA_SAMPLE_MAX + 1] = { | |||
| 37 | 38 | ||
| 38 | static int tcf_sample_init(struct net *net, struct nlattr *nla, | 39 | static int tcf_sample_init(struct net *net, struct nlattr *nla, |
| 39 | struct nlattr *est, struct tc_action **a, int ovr, | 40 | struct nlattr *est, struct tc_action **a, int ovr, |
| 40 | int bind, bool rtnl_held, | 41 | int bind, bool rtnl_held, struct tcf_proto *tp, |
| 41 | struct netlink_ext_ack *extack) | 42 | struct netlink_ext_ack *extack) |
| 42 | { | 43 | { |
| 43 | struct tc_action_net *tn = net_generic(net, sample_net_id); | 44 | struct tc_action_net *tn = net_generic(net, sample_net_id); |
| 44 | struct nlattr *tb[TCA_SAMPLE_MAX + 1]; | 45 | struct nlattr *tb[TCA_SAMPLE_MAX + 1]; |
| 45 | struct psample_group *psample_group; | 46 | struct psample_group *psample_group; |
| 47 | struct tcf_chain *goto_ch = NULL; | ||
| 46 | struct tc_sample *parm; | 48 | struct tc_sample *parm; |
| 47 | u32 psample_group_num; | 49 | u32 psample_group_num; |
| 48 | struct tcf_sample *s; | 50 | struct tcf_sample *s; |
| @@ -79,18 +81,21 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, | |||
| 79 | tcf_idr_release(*a, bind); | 81 | tcf_idr_release(*a, bind); |
| 80 | return -EEXIST; | 82 | return -EEXIST; |
| 81 | } | 83 | } |
| 84 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 85 | if (err < 0) | ||
| 86 | goto release_idr; | ||
| 82 | 87 | ||
| 83 | psample_group_num = nla_get_u32(tb[TCA_SAMPLE_PSAMPLE_GROUP]); | 88 | psample_group_num = nla_get_u32(tb[TCA_SAMPLE_PSAMPLE_GROUP]); |
| 84 | psample_group = psample_group_get(net, psample_group_num); | 89 | psample_group = psample_group_get(net, psample_group_num); |
| 85 | if (!psample_group) { | 90 | if (!psample_group) { |
| 86 | tcf_idr_release(*a, bind); | 91 | err = -ENOMEM; |
| 87 | return -ENOMEM; | 92 | goto put_chain; |
| 88 | } | 93 | } |
| 89 | 94 | ||
| 90 | s = to_sample(*a); | 95 | s = to_sample(*a); |
| 91 | 96 | ||
| 92 | spin_lock_bh(&s->tcf_lock); | 97 | spin_lock_bh(&s->tcf_lock); |
| 93 | s->tcf_action = parm->action; | 98 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
| 94 | s->rate = nla_get_u32(tb[TCA_SAMPLE_RATE]); | 99 | s->rate = nla_get_u32(tb[TCA_SAMPLE_RATE]); |
| 95 | s->psample_group_num = psample_group_num; | 100 | s->psample_group_num = psample_group_num; |
| 96 | RCU_INIT_POINTER(s->psample_group, psample_group); | 101 | RCU_INIT_POINTER(s->psample_group, psample_group); |
| @@ -100,10 +105,18 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, | |||
| 100 | s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]); | 105 | s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]); |
| 101 | } | 106 | } |
| 102 | spin_unlock_bh(&s->tcf_lock); | 107 | spin_unlock_bh(&s->tcf_lock); |
| 108 | if (goto_ch) | ||
| 109 | tcf_chain_put_by_act(goto_ch); | ||
| 103 | 110 | ||
| 104 | if (ret == ACT_P_CREATED) | 111 | if (ret == ACT_P_CREATED) |
| 105 | tcf_idr_insert(tn, *a); | 112 | tcf_idr_insert(tn, *a); |
| 106 | return ret; | 113 | return ret; |
| 114 | put_chain: | ||
| 115 | if (goto_ch) | ||
| 116 | tcf_chain_put_by_act(goto_ch); | ||
| 117 | release_idr: | ||
| 118 | tcf_idr_release(*a, bind); | ||
| 119 | return err; | ||
| 107 | } | 120 | } |
| 108 | 121 | ||
| 109 | static void tcf_sample_cleanup(struct tc_action *a) | 122 | static void tcf_sample_cleanup(struct tc_action *a) |
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index d54cb608dbaf..23c8ca5615e5 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/rtnetlink.h> | 18 | #include <linux/rtnetlink.h> |
| 19 | #include <net/netlink.h> | 19 | #include <net/netlink.h> |
| 20 | #include <net/pkt_sched.h> | 20 | #include <net/pkt_sched.h> |
| 21 | #include <net/pkt_cls.h> | ||
| 21 | 22 | ||
| 22 | #include <linux/tc_act/tc_defact.h> | 23 | #include <linux/tc_act/tc_defact.h> |
| 23 | #include <net/tc_act/tc_defact.h> | 24 | #include <net/tc_act/tc_defact.h> |
| @@ -60,14 +61,26 @@ static int alloc_defdata(struct tcf_defact *d, const struct nlattr *defdata) | |||
| 60 | return 0; | 61 | return 0; |
| 61 | } | 62 | } |
| 62 | 63 | ||
| 63 | static void reset_policy(struct tcf_defact *d, const struct nlattr *defdata, | 64 | static int reset_policy(struct tc_action *a, const struct nlattr *defdata, |
| 64 | struct tc_defact *p) | 65 | struct tc_defact *p, struct tcf_proto *tp, |
| 66 | struct netlink_ext_ack *extack) | ||
| 65 | { | 67 | { |
| 68 | struct tcf_chain *goto_ch = NULL; | ||
| 69 | struct tcf_defact *d; | ||
| 70 | int err; | ||
| 71 | |||
| 72 | err = tcf_action_check_ctrlact(p->action, tp, &goto_ch, extack); | ||
| 73 | if (err < 0) | ||
| 74 | return err; | ||
| 75 | d = to_defact(a); | ||
| 66 | spin_lock_bh(&d->tcf_lock); | 76 | spin_lock_bh(&d->tcf_lock); |
| 67 | d->tcf_action = p->action; | 77 | goto_ch = tcf_action_set_ctrlact(a, p->action, goto_ch); |
| 68 | memset(d->tcfd_defdata, 0, SIMP_MAX_DATA); | 78 | memset(d->tcfd_defdata, 0, SIMP_MAX_DATA); |
| 69 | nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA); | 79 | nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA); |
| 70 | spin_unlock_bh(&d->tcf_lock); | 80 | spin_unlock_bh(&d->tcf_lock); |
| 81 | if (goto_ch) | ||
| 82 | tcf_chain_put_by_act(goto_ch); | ||
| 83 | return 0; | ||
| 71 | } | 84 | } |
| 72 | 85 | ||
| 73 | static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = { | 86 | static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = { |
| @@ -78,10 +91,11 @@ static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = { | |||
| 78 | static int tcf_simp_init(struct net *net, struct nlattr *nla, | 91 | static int tcf_simp_init(struct net *net, struct nlattr *nla, |
| 79 | struct nlattr *est, struct tc_action **a, | 92 | struct nlattr *est, struct tc_action **a, |
| 80 | int ovr, int bind, bool rtnl_held, | 93 | int ovr, int bind, bool rtnl_held, |
| 81 | struct netlink_ext_ack *extack) | 94 | struct tcf_proto *tp, struct netlink_ext_ack *extack) |
| 82 | { | 95 | { |
| 83 | struct tc_action_net *tn = net_generic(net, simp_net_id); | 96 | struct tc_action_net *tn = net_generic(net, simp_net_id); |
| 84 | struct nlattr *tb[TCA_DEF_MAX + 1]; | 97 | struct nlattr *tb[TCA_DEF_MAX + 1]; |
| 98 | struct tcf_chain *goto_ch = NULL; | ||
| 85 | struct tc_defact *parm; | 99 | struct tc_defact *parm; |
| 86 | struct tcf_defact *d; | 100 | struct tcf_defact *d; |
| 87 | bool exists = false; | 101 | bool exists = false; |
| @@ -122,27 +136,37 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, | |||
| 122 | } | 136 | } |
| 123 | 137 | ||
| 124 | d = to_defact(*a); | 138 | d = to_defact(*a); |
| 125 | ret = alloc_defdata(d, tb[TCA_DEF_DATA]); | 139 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, |
| 126 | if (ret < 0) { | 140 | extack); |
| 127 | tcf_idr_release(*a, bind); | 141 | if (err < 0) |
| 128 | return ret; | 142 | goto release_idr; |
| 129 | } | 143 | |
| 130 | d->tcf_action = parm->action; | 144 | err = alloc_defdata(d, tb[TCA_DEF_DATA]); |
| 145 | if (err < 0) | ||
| 146 | goto put_chain; | ||
| 147 | |||
| 148 | tcf_action_set_ctrlact(*a, parm->action, goto_ch); | ||
| 131 | ret = ACT_P_CREATED; | 149 | ret = ACT_P_CREATED; |
| 132 | } else { | 150 | } else { |
| 133 | d = to_defact(*a); | ||
| 134 | |||
| 135 | if (!ovr) { | 151 | if (!ovr) { |
| 136 | tcf_idr_release(*a, bind); | 152 | err = -EEXIST; |
| 137 | return -EEXIST; | 153 | goto release_idr; |
| 138 | } | 154 | } |
| 139 | 155 | ||
| 140 | reset_policy(d, tb[TCA_DEF_DATA], parm); | 156 | err = reset_policy(*a, tb[TCA_DEF_DATA], parm, tp, extack); |
| 157 | if (err) | ||
| 158 | goto release_idr; | ||
| 141 | } | 159 | } |
| 142 | 160 | ||
| 143 | if (ret == ACT_P_CREATED) | 161 | if (ret == ACT_P_CREATED) |
| 144 | tcf_idr_insert(tn, *a); | 162 | tcf_idr_insert(tn, *a); |
| 145 | return ret; | 163 | return ret; |
| 164 | put_chain: | ||
| 165 | if (goto_ch) | ||
| 166 | tcf_chain_put_by_act(goto_ch); | ||
| 167 | release_idr: | ||
| 168 | tcf_idr_release(*a, bind); | ||
| 169 | return err; | ||
| 146 | } | 170 | } |
| 147 | 171 | ||
| 148 | static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, | 172 | static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, |
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c index 65879500b688..7e1d261a31d2 100644 --- a/net/sched/act_skbedit.c +++ b/net/sched/act_skbedit.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <net/ip.h> | 26 | #include <net/ip.h> |
| 27 | #include <net/ipv6.h> | 27 | #include <net/ipv6.h> |
| 28 | #include <net/dsfield.h> | 28 | #include <net/dsfield.h> |
| 29 | #include <net/pkt_cls.h> | ||
| 29 | 30 | ||
| 30 | #include <linux/tc_act/tc_skbedit.h> | 31 | #include <linux/tc_act/tc_skbedit.h> |
| 31 | #include <net/tc_act/tc_skbedit.h> | 32 | #include <net/tc_act/tc_skbedit.h> |
| @@ -96,11 +97,13 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = { | |||
| 96 | static int tcf_skbedit_init(struct net *net, struct nlattr *nla, | 97 | static int tcf_skbedit_init(struct net *net, struct nlattr *nla, |
| 97 | struct nlattr *est, struct tc_action **a, | 98 | struct nlattr *est, struct tc_action **a, |
| 98 | int ovr, int bind, bool rtnl_held, | 99 | int ovr, int bind, bool rtnl_held, |
| 100 | struct tcf_proto *tp, | ||
| 99 | struct netlink_ext_ack *extack) | 101 | struct netlink_ext_ack *extack) |
| 100 | { | 102 | { |
| 101 | struct tc_action_net *tn = net_generic(net, skbedit_net_id); | 103 | struct tc_action_net *tn = net_generic(net, skbedit_net_id); |
| 102 | struct tcf_skbedit_params *params_new; | 104 | struct tcf_skbedit_params *params_new; |
| 103 | struct nlattr *tb[TCA_SKBEDIT_MAX + 1]; | 105 | struct nlattr *tb[TCA_SKBEDIT_MAX + 1]; |
| 106 | struct tcf_chain *goto_ch = NULL; | ||
| 104 | struct tc_skbedit *parm; | 107 | struct tc_skbedit *parm; |
| 105 | struct tcf_skbedit *d; | 108 | struct tcf_skbedit *d; |
| 106 | u32 flags = 0, *priority = NULL, *mark = NULL, *mask = NULL; | 109 | u32 flags = 0, *priority = NULL, *mark = NULL, *mask = NULL; |
| @@ -186,11 +189,14 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, | |||
| 186 | return -EEXIST; | 189 | return -EEXIST; |
| 187 | } | 190 | } |
| 188 | } | 191 | } |
| 192 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 193 | if (err < 0) | ||
| 194 | goto release_idr; | ||
| 189 | 195 | ||
| 190 | params_new = kzalloc(sizeof(*params_new), GFP_KERNEL); | 196 | params_new = kzalloc(sizeof(*params_new), GFP_KERNEL); |
| 191 | if (unlikely(!params_new)) { | 197 | if (unlikely(!params_new)) { |
| 192 | tcf_idr_release(*a, bind); | 198 | err = -ENOMEM; |
| 193 | return -ENOMEM; | 199 | goto put_chain; |
| 194 | } | 200 | } |
| 195 | 201 | ||
| 196 | params_new->flags = flags; | 202 | params_new->flags = flags; |
| @@ -208,16 +214,24 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, | |||
| 208 | params_new->mask = *mask; | 214 | params_new->mask = *mask; |
| 209 | 215 | ||
| 210 | spin_lock_bh(&d->tcf_lock); | 216 | spin_lock_bh(&d->tcf_lock); |
| 211 | d->tcf_action = parm->action; | 217 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
| 212 | rcu_swap_protected(d->params, params_new, | 218 | rcu_swap_protected(d->params, params_new, |
| 213 | lockdep_is_held(&d->tcf_lock)); | 219 | lockdep_is_held(&d->tcf_lock)); |
| 214 | spin_unlock_bh(&d->tcf_lock); | 220 | spin_unlock_bh(&d->tcf_lock); |
| 215 | if (params_new) | 221 | if (params_new) |
| 216 | kfree_rcu(params_new, rcu); | 222 | kfree_rcu(params_new, rcu); |
| 223 | if (goto_ch) | ||
| 224 | tcf_chain_put_by_act(goto_ch); | ||
| 217 | 225 | ||
| 218 | if (ret == ACT_P_CREATED) | 226 | if (ret == ACT_P_CREATED) |
| 219 | tcf_idr_insert(tn, *a); | 227 | tcf_idr_insert(tn, *a); |
| 220 | return ret; | 228 | return ret; |
| 229 | put_chain: | ||
| 230 | if (goto_ch) | ||
| 231 | tcf_chain_put_by_act(goto_ch); | ||
| 232 | release_idr: | ||
| 233 | tcf_idr_release(*a, bind); | ||
| 234 | return err; | ||
| 221 | } | 235 | } |
| 222 | 236 | ||
| 223 | static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, | 237 | static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, |
diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c index 7bac1d78e7a3..1d4c324d0a42 100644 --- a/net/sched/act_skbmod.c +++ b/net/sched/act_skbmod.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
| 17 | #include <net/netlink.h> | 17 | #include <net/netlink.h> |
| 18 | #include <net/pkt_sched.h> | 18 | #include <net/pkt_sched.h> |
| 19 | #include <net/pkt_cls.h> | ||
| 19 | 20 | ||
| 20 | #include <linux/tc_act/tc_skbmod.h> | 21 | #include <linux/tc_act/tc_skbmod.h> |
| 21 | #include <net/tc_act/tc_skbmod.h> | 22 | #include <net/tc_act/tc_skbmod.h> |
| @@ -82,11 +83,13 @@ static const struct nla_policy skbmod_policy[TCA_SKBMOD_MAX + 1] = { | |||
| 82 | static int tcf_skbmod_init(struct net *net, struct nlattr *nla, | 83 | static int tcf_skbmod_init(struct net *net, struct nlattr *nla, |
| 83 | struct nlattr *est, struct tc_action **a, | 84 | struct nlattr *est, struct tc_action **a, |
| 84 | int ovr, int bind, bool rtnl_held, | 85 | int ovr, int bind, bool rtnl_held, |
| 86 | struct tcf_proto *tp, | ||
| 85 | struct netlink_ext_ack *extack) | 87 | struct netlink_ext_ack *extack) |
| 86 | { | 88 | { |
| 87 | struct tc_action_net *tn = net_generic(net, skbmod_net_id); | 89 | struct tc_action_net *tn = net_generic(net, skbmod_net_id); |
| 88 | struct nlattr *tb[TCA_SKBMOD_MAX + 1]; | 90 | struct nlattr *tb[TCA_SKBMOD_MAX + 1]; |
| 89 | struct tcf_skbmod_params *p, *p_old; | 91 | struct tcf_skbmod_params *p, *p_old; |
| 92 | struct tcf_chain *goto_ch = NULL; | ||
| 90 | struct tc_skbmod *parm; | 93 | struct tc_skbmod *parm; |
| 91 | struct tcf_skbmod *d; | 94 | struct tcf_skbmod *d; |
| 92 | bool exists = false; | 95 | bool exists = false; |
| @@ -153,21 +156,24 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, | |||
| 153 | tcf_idr_release(*a, bind); | 156 | tcf_idr_release(*a, bind); |
| 154 | return -EEXIST; | 157 | return -EEXIST; |
| 155 | } | 158 | } |
| 159 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 160 | if (err < 0) | ||
| 161 | goto release_idr; | ||
| 156 | 162 | ||
| 157 | d = to_skbmod(*a); | 163 | d = to_skbmod(*a); |
| 158 | 164 | ||
| 159 | p = kzalloc(sizeof(struct tcf_skbmod_params), GFP_KERNEL); | 165 | p = kzalloc(sizeof(struct tcf_skbmod_params), GFP_KERNEL); |
| 160 | if (unlikely(!p)) { | 166 | if (unlikely(!p)) { |
| 161 | tcf_idr_release(*a, bind); | 167 | err = -ENOMEM; |
| 162 | return -ENOMEM; | 168 | goto put_chain; |
| 163 | } | 169 | } |
| 164 | 170 | ||
| 165 | p->flags = lflags; | 171 | p->flags = lflags; |
| 166 | d->tcf_action = parm->action; | ||
| 167 | 172 | ||
| 168 | if (ovr) | 173 | if (ovr) |
| 169 | spin_lock_bh(&d->tcf_lock); | 174 | spin_lock_bh(&d->tcf_lock); |
| 170 | /* Protected by tcf_lock if overwriting existing action. */ | 175 | /* Protected by tcf_lock if overwriting existing action. */ |
| 176 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); | ||
| 171 | p_old = rcu_dereference_protected(d->skbmod_p, 1); | 177 | p_old = rcu_dereference_protected(d->skbmod_p, 1); |
| 172 | 178 | ||
| 173 | if (lflags & SKBMOD_F_DMAC) | 179 | if (lflags & SKBMOD_F_DMAC) |
| @@ -183,10 +189,18 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, | |||
| 183 | 189 | ||
| 184 | if (p_old) | 190 | if (p_old) |
| 185 | kfree_rcu(p_old, rcu); | 191 | kfree_rcu(p_old, rcu); |
| 192 | if (goto_ch) | ||
| 193 | tcf_chain_put_by_act(goto_ch); | ||
| 186 | 194 | ||
| 187 | if (ret == ACT_P_CREATED) | 195 | if (ret == ACT_P_CREATED) |
| 188 | tcf_idr_insert(tn, *a); | 196 | tcf_idr_insert(tn, *a); |
| 189 | return ret; | 197 | return ret; |
| 198 | put_chain: | ||
| 199 | if (goto_ch) | ||
| 200 | tcf_chain_put_by_act(goto_ch); | ||
| 201 | release_idr: | ||
| 202 | tcf_idr_release(*a, bind); | ||
| 203 | return err; | ||
| 190 | } | 204 | } |
| 191 | 205 | ||
| 192 | static void tcf_skbmod_cleanup(struct tc_action *a) | 206 | static void tcf_skbmod_cleanup(struct tc_action *a) |
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c index 7c6591b991d5..d5aaf90a3971 100644 --- a/net/sched/act_tunnel_key.c +++ b/net/sched/act_tunnel_key.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <net/netlink.h> | 17 | #include <net/netlink.h> |
| 18 | #include <net/pkt_sched.h> | 18 | #include <net/pkt_sched.h> |
| 19 | #include <net/dst.h> | 19 | #include <net/dst.h> |
| 20 | #include <net/pkt_cls.h> | ||
| 20 | 21 | ||
| 21 | #include <linux/tc_act/tc_tunnel_key.h> | 22 | #include <linux/tc_act/tc_tunnel_key.h> |
| 22 | #include <net/tc_act/tc_tunnel_key.h> | 23 | #include <net/tc_act/tc_tunnel_key.h> |
| @@ -210,12 +211,14 @@ static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) | |||
| 210 | static int tunnel_key_init(struct net *net, struct nlattr *nla, | 211 | static int tunnel_key_init(struct net *net, struct nlattr *nla, |
| 211 | struct nlattr *est, struct tc_action **a, | 212 | struct nlattr *est, struct tc_action **a, |
| 212 | int ovr, int bind, bool rtnl_held, | 213 | int ovr, int bind, bool rtnl_held, |
| 214 | struct tcf_proto *tp, | ||
| 213 | struct netlink_ext_ack *extack) | 215 | struct netlink_ext_ack *extack) |
| 214 | { | 216 | { |
| 215 | struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); | 217 | struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); |
| 216 | struct nlattr *tb[TCA_TUNNEL_KEY_MAX + 1]; | 218 | struct nlattr *tb[TCA_TUNNEL_KEY_MAX + 1]; |
| 217 | struct tcf_tunnel_key_params *params_new; | 219 | struct tcf_tunnel_key_params *params_new; |
| 218 | struct metadata_dst *metadata = NULL; | 220 | struct metadata_dst *metadata = NULL; |
| 221 | struct tcf_chain *goto_ch = NULL; | ||
| 219 | struct tc_tunnel_key *parm; | 222 | struct tc_tunnel_key *parm; |
| 220 | struct tcf_tunnel_key *t; | 223 | struct tcf_tunnel_key *t; |
| 221 | bool exists = false; | 224 | bool exists = false; |
| @@ -359,6 +362,12 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, | |||
| 359 | goto release_tun_meta; | 362 | goto release_tun_meta; |
| 360 | } | 363 | } |
| 361 | 364 | ||
| 365 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 366 | if (err < 0) { | ||
| 367 | ret = err; | ||
| 368 | exists = true; | ||
| 369 | goto release_tun_meta; | ||
| 370 | } | ||
| 362 | t = to_tunnel_key(*a); | 371 | t = to_tunnel_key(*a); |
| 363 | 372 | ||
| 364 | params_new = kzalloc(sizeof(*params_new), GFP_KERNEL); | 373 | params_new = kzalloc(sizeof(*params_new), GFP_KERNEL); |
| @@ -366,23 +375,29 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, | |||
| 366 | NL_SET_ERR_MSG(extack, "Cannot allocate tunnel key parameters"); | 375 | NL_SET_ERR_MSG(extack, "Cannot allocate tunnel key parameters"); |
| 367 | ret = -ENOMEM; | 376 | ret = -ENOMEM; |
| 368 | exists = true; | 377 | exists = true; |
| 369 | goto release_tun_meta; | 378 | goto put_chain; |
| 370 | } | 379 | } |
| 371 | params_new->tcft_action = parm->t_action; | 380 | params_new->tcft_action = parm->t_action; |
| 372 | params_new->tcft_enc_metadata = metadata; | 381 | params_new->tcft_enc_metadata = metadata; |
| 373 | 382 | ||
| 374 | spin_lock_bh(&t->tcf_lock); | 383 | spin_lock_bh(&t->tcf_lock); |
| 375 | t->tcf_action = parm->action; | 384 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
| 376 | rcu_swap_protected(t->params, params_new, | 385 | rcu_swap_protected(t->params, params_new, |
| 377 | lockdep_is_held(&t->tcf_lock)); | 386 | lockdep_is_held(&t->tcf_lock)); |
| 378 | spin_unlock_bh(&t->tcf_lock); | 387 | spin_unlock_bh(&t->tcf_lock); |
| 379 | tunnel_key_release_params(params_new); | 388 | tunnel_key_release_params(params_new); |
| 389 | if (goto_ch) | ||
| 390 | tcf_chain_put_by_act(goto_ch); | ||
| 380 | 391 | ||
| 381 | if (ret == ACT_P_CREATED) | 392 | if (ret == ACT_P_CREATED) |
| 382 | tcf_idr_insert(tn, *a); | 393 | tcf_idr_insert(tn, *a); |
| 383 | 394 | ||
| 384 | return ret; | 395 | return ret; |
| 385 | 396 | ||
| 397 | put_chain: | ||
| 398 | if (goto_ch) | ||
| 399 | tcf_chain_put_by_act(goto_ch); | ||
| 400 | |||
| 386 | release_tun_meta: | 401 | release_tun_meta: |
| 387 | if (metadata) | 402 | if (metadata) |
| 388 | dst_release(&metadata->dst); | 403 | dst_release(&metadata->dst); |
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c index ac0061599225..0f40d0a74423 100644 --- a/net/sched/act_vlan.c +++ b/net/sched/act_vlan.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/if_vlan.h> | 15 | #include <linux/if_vlan.h> |
| 16 | #include <net/netlink.h> | 16 | #include <net/netlink.h> |
| 17 | #include <net/pkt_sched.h> | 17 | #include <net/pkt_sched.h> |
| 18 | #include <net/pkt_cls.h> | ||
| 18 | 19 | ||
| 19 | #include <linux/tc_act/tc_vlan.h> | 20 | #include <linux/tc_act/tc_vlan.h> |
| 20 | #include <net/tc_act/tc_vlan.h> | 21 | #include <net/tc_act/tc_vlan.h> |
| @@ -105,10 +106,11 @@ static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = { | |||
| 105 | static int tcf_vlan_init(struct net *net, struct nlattr *nla, | 106 | static int tcf_vlan_init(struct net *net, struct nlattr *nla, |
| 106 | struct nlattr *est, struct tc_action **a, | 107 | struct nlattr *est, struct tc_action **a, |
| 107 | int ovr, int bind, bool rtnl_held, | 108 | int ovr, int bind, bool rtnl_held, |
| 108 | struct netlink_ext_ack *extack) | 109 | struct tcf_proto *tp, struct netlink_ext_ack *extack) |
| 109 | { | 110 | { |
| 110 | struct tc_action_net *tn = net_generic(net, vlan_net_id); | 111 | struct tc_action_net *tn = net_generic(net, vlan_net_id); |
| 111 | struct nlattr *tb[TCA_VLAN_MAX + 1]; | 112 | struct nlattr *tb[TCA_VLAN_MAX + 1]; |
| 113 | struct tcf_chain *goto_ch = NULL; | ||
| 112 | struct tcf_vlan_params *p; | 114 | struct tcf_vlan_params *p; |
| 113 | struct tc_vlan *parm; | 115 | struct tc_vlan *parm; |
| 114 | struct tcf_vlan *v; | 116 | struct tcf_vlan *v; |
| @@ -200,12 +202,16 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, | |||
| 200 | return -EEXIST; | 202 | return -EEXIST; |
| 201 | } | 203 | } |
| 202 | 204 | ||
| 205 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 206 | if (err < 0) | ||
| 207 | goto release_idr; | ||
| 208 | |||
| 203 | v = to_vlan(*a); | 209 | v = to_vlan(*a); |
| 204 | 210 | ||
| 205 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 211 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 206 | if (!p) { | 212 | if (!p) { |
| 207 | tcf_idr_release(*a, bind); | 213 | err = -ENOMEM; |
| 208 | return -ENOMEM; | 214 | goto put_chain; |
| 209 | } | 215 | } |
| 210 | 216 | ||
| 211 | p->tcfv_action = action; | 217 | p->tcfv_action = action; |
| @@ -214,16 +220,24 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, | |||
| 214 | p->tcfv_push_proto = push_proto; | 220 | p->tcfv_push_proto = push_proto; |
| 215 | 221 | ||
| 216 | spin_lock_bh(&v->tcf_lock); | 222 | spin_lock_bh(&v->tcf_lock); |
| 217 | v->tcf_action = parm->action; | 223 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
| 218 | rcu_swap_protected(v->vlan_p, p, lockdep_is_held(&v->tcf_lock)); | 224 | rcu_swap_protected(v->vlan_p, p, lockdep_is_held(&v->tcf_lock)); |
| 219 | spin_unlock_bh(&v->tcf_lock); | 225 | spin_unlock_bh(&v->tcf_lock); |
| 220 | 226 | ||
| 227 | if (goto_ch) | ||
| 228 | tcf_chain_put_by_act(goto_ch); | ||
| 221 | if (p) | 229 | if (p) |
| 222 | kfree_rcu(p, rcu); | 230 | kfree_rcu(p, rcu); |
| 223 | 231 | ||
| 224 | if (ret == ACT_P_CREATED) | 232 | if (ret == ACT_P_CREATED) |
| 225 | tcf_idr_insert(tn, *a); | 233 | tcf_idr_insert(tn, *a); |
| 226 | return ret; | 234 | return ret; |
| 235 | put_chain: | ||
| 236 | if (goto_ch) | ||
| 237 | tcf_chain_put_by_act(goto_ch); | ||
| 238 | release_idr: | ||
| 239 | tcf_idr_release(*a, bind); | ||
| 240 | return err; | ||
| 227 | } | 241 | } |
| 228 | 242 | ||
| 229 | static void tcf_vlan_cleanup(struct tc_action *a) | 243 | static void tcf_vlan_cleanup(struct tc_action *a) |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index dc10525e90e7..99ae30c177c7 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
| @@ -367,7 +367,7 @@ static void tcf_chain_destroy(struct tcf_chain *chain, bool free_block) | |||
| 367 | struct tcf_block *block = chain->block; | 367 | struct tcf_block *block = chain->block; |
| 368 | 368 | ||
| 369 | mutex_destroy(&chain->filter_chain_lock); | 369 | mutex_destroy(&chain->filter_chain_lock); |
| 370 | kfree(chain); | 370 | kfree_rcu(chain, rcu); |
| 371 | if (free_block) | 371 | if (free_block) |
| 372 | tcf_block_destroy(block); | 372 | tcf_block_destroy(block); |
| 373 | } | 373 | } |
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c index 1d2a12132abc..acc9b9da985f 100644 --- a/net/sched/sch_cake.c +++ b/net/sched/sch_cake.c | |||
| @@ -211,6 +211,9 @@ struct cake_sched_data { | |||
| 211 | u8 ack_filter; | 211 | u8 ack_filter; |
| 212 | u8 atm_mode; | 212 | u8 atm_mode; |
| 213 | 213 | ||
| 214 | u32 fwmark_mask; | ||
| 215 | u16 fwmark_shft; | ||
| 216 | |||
| 214 | /* time_next = time_this + ((len * rate_ns) >> rate_shft) */ | 217 | /* time_next = time_this + ((len * rate_ns) >> rate_shft) */ |
| 215 | u16 rate_shft; | 218 | u16 rate_shft; |
| 216 | ktime_t time_next_packet; | 219 | ktime_t time_next_packet; |
| @@ -258,8 +261,7 @@ enum { | |||
| 258 | CAKE_FLAG_AUTORATE_INGRESS = BIT(1), | 261 | CAKE_FLAG_AUTORATE_INGRESS = BIT(1), |
| 259 | CAKE_FLAG_INGRESS = BIT(2), | 262 | CAKE_FLAG_INGRESS = BIT(2), |
| 260 | CAKE_FLAG_WASH = BIT(3), | 263 | CAKE_FLAG_WASH = BIT(3), |
| 261 | CAKE_FLAG_SPLIT_GSO = BIT(4), | 264 | CAKE_FLAG_SPLIT_GSO = BIT(4) |
| 262 | CAKE_FLAG_FWMARK = BIT(5) | ||
| 263 | }; | 265 | }; |
| 264 | 266 | ||
| 265 | /* COBALT operates the Codel and BLUE algorithms in parallel, in order to | 267 | /* COBALT operates the Codel and BLUE algorithms in parallel, in order to |
| @@ -1543,7 +1545,7 @@ static struct cake_tin_data *cake_select_tin(struct Qdisc *sch, | |||
| 1543 | struct sk_buff *skb) | 1545 | struct sk_buff *skb) |
| 1544 | { | 1546 | { |
| 1545 | struct cake_sched_data *q = qdisc_priv(sch); | 1547 | struct cake_sched_data *q = qdisc_priv(sch); |
| 1546 | u32 tin; | 1548 | u32 tin, mark; |
| 1547 | u8 dscp; | 1549 | u8 dscp; |
| 1548 | 1550 | ||
| 1549 | /* Tin selection: Default to diffserv-based selection, allow overriding | 1551 | /* Tin selection: Default to diffserv-based selection, allow overriding |
| @@ -1551,14 +1553,13 @@ static struct cake_tin_data *cake_select_tin(struct Qdisc *sch, | |||
| 1551 | */ | 1553 | */ |
| 1552 | dscp = cake_handle_diffserv(skb, | 1554 | dscp = cake_handle_diffserv(skb, |
| 1553 | q->rate_flags & CAKE_FLAG_WASH); | 1555 | q->rate_flags & CAKE_FLAG_WASH); |
| 1556 | mark = (skb->mark & q->fwmark_mask) >> q->fwmark_shft; | ||
| 1554 | 1557 | ||
| 1555 | if (q->tin_mode == CAKE_DIFFSERV_BESTEFFORT) | 1558 | if (q->tin_mode == CAKE_DIFFSERV_BESTEFFORT) |
| 1556 | tin = 0; | 1559 | tin = 0; |
| 1557 | 1560 | ||
| 1558 | else if (q->rate_flags & CAKE_FLAG_FWMARK && /* use fw mark */ | 1561 | else if (mark && mark <= q->tin_cnt) |
| 1559 | skb->mark && | 1562 | tin = q->tin_order[mark - 1]; |
| 1560 | skb->mark <= q->tin_cnt) | ||
| 1561 | tin = q->tin_order[skb->mark - 1]; | ||
| 1562 | 1563 | ||
| 1563 | else if (TC_H_MAJ(skb->priority) == sch->handle && | 1564 | else if (TC_H_MAJ(skb->priority) == sch->handle && |
| 1564 | TC_H_MIN(skb->priority) > 0 && | 1565 | TC_H_MIN(skb->priority) > 0 && |
| @@ -2172,6 +2173,7 @@ static const struct nla_policy cake_policy[TCA_CAKE_MAX + 1] = { | |||
| 2172 | [TCA_CAKE_MPU] = { .type = NLA_U32 }, | 2173 | [TCA_CAKE_MPU] = { .type = NLA_U32 }, |
| 2173 | [TCA_CAKE_INGRESS] = { .type = NLA_U32 }, | 2174 | [TCA_CAKE_INGRESS] = { .type = NLA_U32 }, |
| 2174 | [TCA_CAKE_ACK_FILTER] = { .type = NLA_U32 }, | 2175 | [TCA_CAKE_ACK_FILTER] = { .type = NLA_U32 }, |
| 2176 | [TCA_CAKE_FWMARK] = { .type = NLA_U32 }, | ||
| 2175 | }; | 2177 | }; |
| 2176 | 2178 | ||
| 2177 | static void cake_set_rate(struct cake_tin_data *b, u64 rate, u32 mtu, | 2179 | static void cake_set_rate(struct cake_tin_data *b, u64 rate, u32 mtu, |
| @@ -2619,10 +2621,8 @@ static int cake_change(struct Qdisc *sch, struct nlattr *opt, | |||
| 2619 | } | 2621 | } |
| 2620 | 2622 | ||
| 2621 | if (tb[TCA_CAKE_FWMARK]) { | 2623 | if (tb[TCA_CAKE_FWMARK]) { |
| 2622 | if (!!nla_get_u32(tb[TCA_CAKE_FWMARK])) | 2624 | q->fwmark_mask = nla_get_u32(tb[TCA_CAKE_FWMARK]); |
| 2623 | q->rate_flags |= CAKE_FLAG_FWMARK; | 2625 | q->fwmark_shft = q->fwmark_mask ? __ffs(q->fwmark_mask) : 0; |
| 2624 | else | ||
| 2625 | q->rate_flags &= ~CAKE_FLAG_FWMARK; | ||
| 2626 | } | 2626 | } |
| 2627 | 2627 | ||
| 2628 | if (q->tins) { | 2628 | if (q->tins) { |
| @@ -2784,8 +2784,7 @@ static int cake_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
| 2784 | !!(q->rate_flags & CAKE_FLAG_SPLIT_GSO))) | 2784 | !!(q->rate_flags & CAKE_FLAG_SPLIT_GSO))) |
| 2785 | goto nla_put_failure; | 2785 | goto nla_put_failure; |
| 2786 | 2786 | ||
| 2787 | if (nla_put_u32(skb, TCA_CAKE_FWMARK, | 2787 | if (nla_put_u32(skb, TCA_CAKE_FWMARK, q->fwmark_mask)) |
| 2788 | !!(q->rate_flags & CAKE_FLAG_FWMARK))) | ||
| 2789 | goto nla_put_failure; | 2788 | goto nla_put_failure; |
| 2790 | 2789 | ||
| 2791 | return nla_nest_end(skb, opts); | 2790 | return nla_nest_end(skb, opts); |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 6140471efd4b..9874e60c9b0d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -999,7 +999,7 @@ static int sctp_setsockopt_bindx(struct sock *sk, | |||
| 999 | if (unlikely(addrs_size <= 0)) | 999 | if (unlikely(addrs_size <= 0)) |
| 1000 | return -EINVAL; | 1000 | return -EINVAL; |
| 1001 | 1001 | ||
| 1002 | kaddrs = vmemdup_user(addrs, addrs_size); | 1002 | kaddrs = memdup_user(addrs, addrs_size); |
| 1003 | if (unlikely(IS_ERR(kaddrs))) | 1003 | if (unlikely(IS_ERR(kaddrs))) |
| 1004 | return PTR_ERR(kaddrs); | 1004 | return PTR_ERR(kaddrs); |
| 1005 | 1005 | ||
| @@ -1007,7 +1007,7 @@ static int sctp_setsockopt_bindx(struct sock *sk, | |||
| 1007 | addr_buf = kaddrs; | 1007 | addr_buf = kaddrs; |
| 1008 | while (walk_size < addrs_size) { | 1008 | while (walk_size < addrs_size) { |
| 1009 | if (walk_size + sizeof(sa_family_t) > addrs_size) { | 1009 | if (walk_size + sizeof(sa_family_t) > addrs_size) { |
| 1010 | kvfree(kaddrs); | 1010 | kfree(kaddrs); |
| 1011 | return -EINVAL; | 1011 | return -EINVAL; |
| 1012 | } | 1012 | } |
| 1013 | 1013 | ||
| @@ -1018,7 +1018,7 @@ static int sctp_setsockopt_bindx(struct sock *sk, | |||
| 1018 | * causes the address buffer to overflow return EINVAL. | 1018 | * causes the address buffer to overflow return EINVAL. |
| 1019 | */ | 1019 | */ |
| 1020 | if (!af || (walk_size + af->sockaddr_len) > addrs_size) { | 1020 | if (!af || (walk_size + af->sockaddr_len) > addrs_size) { |
| 1021 | kvfree(kaddrs); | 1021 | kfree(kaddrs); |
| 1022 | return -EINVAL; | 1022 | return -EINVAL; |
| 1023 | } | 1023 | } |
| 1024 | addrcnt++; | 1024 | addrcnt++; |
| @@ -1054,7 +1054,7 @@ static int sctp_setsockopt_bindx(struct sock *sk, | |||
| 1054 | } | 1054 | } |
| 1055 | 1055 | ||
| 1056 | out: | 1056 | out: |
| 1057 | kvfree(kaddrs); | 1057 | kfree(kaddrs); |
| 1058 | 1058 | ||
| 1059 | return err; | 1059 | return err; |
| 1060 | } | 1060 | } |
| @@ -1329,7 +1329,7 @@ static int __sctp_setsockopt_connectx(struct sock *sk, | |||
| 1329 | if (unlikely(addrs_size <= 0)) | 1329 | if (unlikely(addrs_size <= 0)) |
| 1330 | return -EINVAL; | 1330 | return -EINVAL; |
| 1331 | 1331 | ||
| 1332 | kaddrs = vmemdup_user(addrs, addrs_size); | 1332 | kaddrs = memdup_user(addrs, addrs_size); |
| 1333 | if (unlikely(IS_ERR(kaddrs))) | 1333 | if (unlikely(IS_ERR(kaddrs))) |
| 1334 | return PTR_ERR(kaddrs); | 1334 | return PTR_ERR(kaddrs); |
| 1335 | 1335 | ||
| @@ -1349,7 +1349,7 @@ static int __sctp_setsockopt_connectx(struct sock *sk, | |||
| 1349 | err = __sctp_connect(sk, kaddrs, addrs_size, flags, assoc_id); | 1349 | err = __sctp_connect(sk, kaddrs, addrs_size, flags, assoc_id); |
| 1350 | 1350 | ||
| 1351 | out_free: | 1351 | out_free: |
| 1352 | kvfree(kaddrs); | 1352 | kfree(kaddrs); |
| 1353 | 1353 | ||
| 1354 | return err; | 1354 | return err; |
| 1355 | } | 1355 | } |
| @@ -2920,6 +2920,9 @@ static int sctp_setsockopt_delayed_ack(struct sock *sk, | |||
| 2920 | return 0; | 2920 | return 0; |
| 2921 | } | 2921 | } |
| 2922 | 2922 | ||
| 2923 | if (sctp_style(sk, TCP)) | ||
| 2924 | params.sack_assoc_id = SCTP_FUTURE_ASSOC; | ||
| 2925 | |||
| 2923 | if (params.sack_assoc_id == SCTP_FUTURE_ASSOC || | 2926 | if (params.sack_assoc_id == SCTP_FUTURE_ASSOC || |
| 2924 | params.sack_assoc_id == SCTP_ALL_ASSOC) { | 2927 | params.sack_assoc_id == SCTP_ALL_ASSOC) { |
| 2925 | if (params.sack_delay) { | 2928 | if (params.sack_delay) { |
| @@ -3024,6 +3027,9 @@ static int sctp_setsockopt_default_send_param(struct sock *sk, | |||
| 3024 | return 0; | 3027 | return 0; |
| 3025 | } | 3028 | } |
| 3026 | 3029 | ||
| 3030 | if (sctp_style(sk, TCP)) | ||
| 3031 | info.sinfo_assoc_id = SCTP_FUTURE_ASSOC; | ||
| 3032 | |||
| 3027 | if (info.sinfo_assoc_id == SCTP_FUTURE_ASSOC || | 3033 | if (info.sinfo_assoc_id == SCTP_FUTURE_ASSOC || |
| 3028 | info.sinfo_assoc_id == SCTP_ALL_ASSOC) { | 3034 | info.sinfo_assoc_id == SCTP_ALL_ASSOC) { |
| 3029 | sp->default_stream = info.sinfo_stream; | 3035 | sp->default_stream = info.sinfo_stream; |
| @@ -3081,6 +3087,9 @@ static int sctp_setsockopt_default_sndinfo(struct sock *sk, | |||
| 3081 | return 0; | 3087 | return 0; |
| 3082 | } | 3088 | } |
| 3083 | 3089 | ||
| 3090 | if (sctp_style(sk, TCP)) | ||
| 3091 | info.snd_assoc_id = SCTP_FUTURE_ASSOC; | ||
| 3092 | |||
| 3084 | if (info.snd_assoc_id == SCTP_FUTURE_ASSOC || | 3093 | if (info.snd_assoc_id == SCTP_FUTURE_ASSOC || |
| 3085 | info.snd_assoc_id == SCTP_ALL_ASSOC) { | 3094 | info.snd_assoc_id == SCTP_ALL_ASSOC) { |
| 3086 | sp->default_stream = info.snd_sid; | 3095 | sp->default_stream = info.snd_sid; |
| @@ -3531,6 +3540,9 @@ static int sctp_setsockopt_context(struct sock *sk, char __user *optval, | |||
| 3531 | return 0; | 3540 | return 0; |
| 3532 | } | 3541 | } |
| 3533 | 3542 | ||
| 3543 | if (sctp_style(sk, TCP)) | ||
| 3544 | params.assoc_id = SCTP_FUTURE_ASSOC; | ||
| 3545 | |||
| 3534 | if (params.assoc_id == SCTP_FUTURE_ASSOC || | 3546 | if (params.assoc_id == SCTP_FUTURE_ASSOC || |
| 3535 | params.assoc_id == SCTP_ALL_ASSOC) | 3547 | params.assoc_id == SCTP_ALL_ASSOC) |
| 3536 | sp->default_rcv_context = params.assoc_value; | 3548 | sp->default_rcv_context = params.assoc_value; |
| @@ -3670,6 +3682,9 @@ static int sctp_setsockopt_maxburst(struct sock *sk, | |||
| 3670 | return 0; | 3682 | return 0; |
| 3671 | } | 3683 | } |
| 3672 | 3684 | ||
| 3685 | if (sctp_style(sk, TCP)) | ||
| 3686 | params.assoc_id = SCTP_FUTURE_ASSOC; | ||
| 3687 | |||
| 3673 | if (params.assoc_id == SCTP_FUTURE_ASSOC || | 3688 | if (params.assoc_id == SCTP_FUTURE_ASSOC || |
| 3674 | params.assoc_id == SCTP_ALL_ASSOC) | 3689 | params.assoc_id == SCTP_ALL_ASSOC) |
| 3675 | sp->max_burst = params.assoc_value; | 3690 | sp->max_burst = params.assoc_value; |
| @@ -3798,6 +3813,9 @@ static int sctp_setsockopt_auth_key(struct sock *sk, | |||
| 3798 | goto out; | 3813 | goto out; |
| 3799 | } | 3814 | } |
| 3800 | 3815 | ||
| 3816 | if (sctp_style(sk, TCP)) | ||
| 3817 | authkey->sca_assoc_id = SCTP_FUTURE_ASSOC; | ||
| 3818 | |||
| 3801 | if (authkey->sca_assoc_id == SCTP_FUTURE_ASSOC || | 3819 | if (authkey->sca_assoc_id == SCTP_FUTURE_ASSOC || |
| 3802 | authkey->sca_assoc_id == SCTP_ALL_ASSOC) { | 3820 | authkey->sca_assoc_id == SCTP_ALL_ASSOC) { |
| 3803 | ret = sctp_auth_set_key(ep, asoc, authkey); | 3821 | ret = sctp_auth_set_key(ep, asoc, authkey); |
| @@ -3853,6 +3871,9 @@ static int sctp_setsockopt_active_key(struct sock *sk, | |||
| 3853 | if (asoc) | 3871 | if (asoc) |
| 3854 | return sctp_auth_set_active_key(ep, asoc, val.scact_keynumber); | 3872 | return sctp_auth_set_active_key(ep, asoc, val.scact_keynumber); |
| 3855 | 3873 | ||
| 3874 | if (sctp_style(sk, TCP)) | ||
| 3875 | val.scact_assoc_id = SCTP_FUTURE_ASSOC; | ||
| 3876 | |||
| 3856 | if (val.scact_assoc_id == SCTP_FUTURE_ASSOC || | 3877 | if (val.scact_assoc_id == SCTP_FUTURE_ASSOC || |
| 3857 | val.scact_assoc_id == SCTP_ALL_ASSOC) { | 3878 | val.scact_assoc_id == SCTP_ALL_ASSOC) { |
| 3858 | ret = sctp_auth_set_active_key(ep, asoc, val.scact_keynumber); | 3879 | ret = sctp_auth_set_active_key(ep, asoc, val.scact_keynumber); |
| @@ -3904,6 +3925,9 @@ static int sctp_setsockopt_del_key(struct sock *sk, | |||
| 3904 | if (asoc) | 3925 | if (asoc) |
| 3905 | return sctp_auth_del_key_id(ep, asoc, val.scact_keynumber); | 3926 | return sctp_auth_del_key_id(ep, asoc, val.scact_keynumber); |
| 3906 | 3927 | ||
| 3928 | if (sctp_style(sk, TCP)) | ||
| 3929 | val.scact_assoc_id = SCTP_FUTURE_ASSOC; | ||
| 3930 | |||
| 3907 | if (val.scact_assoc_id == SCTP_FUTURE_ASSOC || | 3931 | if (val.scact_assoc_id == SCTP_FUTURE_ASSOC || |
| 3908 | val.scact_assoc_id == SCTP_ALL_ASSOC) { | 3932 | val.scact_assoc_id == SCTP_ALL_ASSOC) { |
| 3909 | ret = sctp_auth_del_key_id(ep, asoc, val.scact_keynumber); | 3933 | ret = sctp_auth_del_key_id(ep, asoc, val.scact_keynumber); |
| @@ -3954,6 +3978,9 @@ static int sctp_setsockopt_deactivate_key(struct sock *sk, char __user *optval, | |||
| 3954 | if (asoc) | 3978 | if (asoc) |
| 3955 | return sctp_auth_deact_key_id(ep, asoc, val.scact_keynumber); | 3979 | return sctp_auth_deact_key_id(ep, asoc, val.scact_keynumber); |
| 3956 | 3980 | ||
| 3981 | if (sctp_style(sk, TCP)) | ||
| 3982 | val.scact_assoc_id = SCTP_FUTURE_ASSOC; | ||
| 3983 | |||
| 3957 | if (val.scact_assoc_id == SCTP_FUTURE_ASSOC || | 3984 | if (val.scact_assoc_id == SCTP_FUTURE_ASSOC || |
| 3958 | val.scact_assoc_id == SCTP_ALL_ASSOC) { | 3985 | val.scact_assoc_id == SCTP_ALL_ASSOC) { |
| 3959 | ret = sctp_auth_deact_key_id(ep, asoc, val.scact_keynumber); | 3986 | ret = sctp_auth_deact_key_id(ep, asoc, val.scact_keynumber); |
| @@ -4169,6 +4196,9 @@ static int sctp_setsockopt_default_prinfo(struct sock *sk, | |||
| 4169 | goto out; | 4196 | goto out; |
| 4170 | } | 4197 | } |
| 4171 | 4198 | ||
| 4199 | if (sctp_style(sk, TCP)) | ||
| 4200 | info.pr_assoc_id = SCTP_FUTURE_ASSOC; | ||
| 4201 | |||
| 4172 | if (info.pr_assoc_id == SCTP_FUTURE_ASSOC || | 4202 | if (info.pr_assoc_id == SCTP_FUTURE_ASSOC || |
| 4173 | info.pr_assoc_id == SCTP_ALL_ASSOC) { | 4203 | info.pr_assoc_id == SCTP_ALL_ASSOC) { |
| 4174 | SCTP_PR_SET_POLICY(sp->default_flags, info.pr_policy); | 4204 | SCTP_PR_SET_POLICY(sp->default_flags, info.pr_policy); |
| @@ -4251,6 +4281,9 @@ static int sctp_setsockopt_enable_strreset(struct sock *sk, | |||
| 4251 | goto out; | 4281 | goto out; |
| 4252 | } | 4282 | } |
| 4253 | 4283 | ||
| 4284 | if (sctp_style(sk, TCP)) | ||
| 4285 | params.assoc_id = SCTP_FUTURE_ASSOC; | ||
| 4286 | |||
| 4254 | if (params.assoc_id == SCTP_FUTURE_ASSOC || | 4287 | if (params.assoc_id == SCTP_FUTURE_ASSOC || |
| 4255 | params.assoc_id == SCTP_ALL_ASSOC) | 4288 | params.assoc_id == SCTP_ALL_ASSOC) |
| 4256 | ep->strreset_enable = params.assoc_value; | 4289 | ep->strreset_enable = params.assoc_value; |
| @@ -4376,6 +4409,9 @@ static int sctp_setsockopt_scheduler(struct sock *sk, | |||
| 4376 | if (asoc) | 4409 | if (asoc) |
| 4377 | return sctp_sched_set_sched(asoc, params.assoc_value); | 4410 | return sctp_sched_set_sched(asoc, params.assoc_value); |
| 4378 | 4411 | ||
| 4412 | if (sctp_style(sk, TCP)) | ||
| 4413 | params.assoc_id = SCTP_FUTURE_ASSOC; | ||
| 4414 | |||
| 4379 | if (params.assoc_id == SCTP_FUTURE_ASSOC || | 4415 | if (params.assoc_id == SCTP_FUTURE_ASSOC || |
| 4380 | params.assoc_id == SCTP_ALL_ASSOC) | 4416 | params.assoc_id == SCTP_ALL_ASSOC) |
| 4381 | sp->default_ss = params.assoc_value; | 4417 | sp->default_ss = params.assoc_value; |
| @@ -4541,6 +4577,9 @@ static int sctp_setsockopt_event(struct sock *sk, char __user *optval, | |||
| 4541 | if (asoc) | 4577 | if (asoc) |
| 4542 | return sctp_assoc_ulpevent_type_set(¶m, asoc); | 4578 | return sctp_assoc_ulpevent_type_set(¶m, asoc); |
| 4543 | 4579 | ||
| 4580 | if (sctp_style(sk, TCP)) | ||
| 4581 | param.se_assoc_id = SCTP_FUTURE_ASSOC; | ||
| 4582 | |||
| 4544 | if (param.se_assoc_id == SCTP_FUTURE_ASSOC || | 4583 | if (param.se_assoc_id == SCTP_FUTURE_ASSOC || |
| 4545 | param.se_assoc_id == SCTP_ALL_ASSOC) | 4584 | param.se_assoc_id == SCTP_ALL_ASSOC) |
| 4546 | sctp_ulpevent_type_set(&sp->subscribe, | 4585 | sctp_ulpevent_type_set(&sp->subscribe, |
| @@ -9169,7 +9208,7 @@ static inline void sctp_copy_descendant(struct sock *sk_to, | |||
| 9169 | { | 9208 | { |
| 9170 | int ancestor_size = sizeof(struct inet_sock) + | 9209 | int ancestor_size = sizeof(struct inet_sock) + |
| 9171 | sizeof(struct sctp_sock) - | 9210 | sizeof(struct sctp_sock) - |
| 9172 | offsetof(struct sctp_sock, auto_asconf_list); | 9211 | offsetof(struct sctp_sock, pd_lobby); |
| 9173 | 9212 | ||
| 9174 | if (sk_from->sk_family == PF_INET6) | 9213 | if (sk_from->sk_family == PF_INET6) |
| 9175 | ancestor_size += sizeof(struct ipv6_pinfo); | 9214 | ancestor_size += sizeof(struct ipv6_pinfo); |
| @@ -9253,7 +9292,6 @@ static int sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
| 9253 | * 2) Peeling off partial delivery; keep pd_lobby in new pd_lobby. | 9292 | * 2) Peeling off partial delivery; keep pd_lobby in new pd_lobby. |
| 9254 | * 3) Peeling off non-partial delivery; move pd_lobby to receive_queue. | 9293 | * 3) Peeling off non-partial delivery; move pd_lobby to receive_queue. |
| 9255 | */ | 9294 | */ |
| 9256 | skb_queue_head_init(&newsp->pd_lobby); | ||
| 9257 | atomic_set(&sctp_sk(newsk)->pd_mode, assoc->ulpq.pd_mode); | 9295 | atomic_set(&sctp_sk(newsk)->pd_mode, assoc->ulpq.pd_mode); |
| 9258 | 9296 | ||
| 9259 | if (atomic_read(&sctp_sk(oldsk)->pd_mode)) { | 9297 | if (atomic_read(&sctp_sk(oldsk)->pd_mode)) { |
diff --git a/net/socket.c b/net/socket.c index 3c176a12fe48..8255f5bda0aa 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -384,6 +384,18 @@ static struct file_system_type sock_fs_type = { | |||
| 384 | * but we take care of internal coherence yet. | 384 | * but we take care of internal coherence yet. |
| 385 | */ | 385 | */ |
| 386 | 386 | ||
| 387 | /** | ||
| 388 | * sock_alloc_file - Bind a &socket to a &file | ||
| 389 | * @sock: socket | ||
| 390 | * @flags: file status flags | ||
| 391 | * @dname: protocol name | ||
| 392 | * | ||
| 393 | * Returns the &file bound with @sock, implicitly storing it | ||
| 394 | * in sock->file. If dname is %NULL, sets to "". | ||
| 395 | * On failure the return is a ERR pointer (see linux/err.h). | ||
| 396 | * This function uses GFP_KERNEL internally. | ||
| 397 | */ | ||
| 398 | |||
| 387 | struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) | 399 | struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) |
| 388 | { | 400 | { |
| 389 | struct file *file; | 401 | struct file *file; |
| @@ -424,6 +436,14 @@ static int sock_map_fd(struct socket *sock, int flags) | |||
| 424 | return PTR_ERR(newfile); | 436 | return PTR_ERR(newfile); |
| 425 | } | 437 | } |
| 426 | 438 | ||
| 439 | /** | ||
| 440 | * sock_from_file - Return the &socket bounded to @file. | ||
| 441 | * @file: file | ||
| 442 | * @err: pointer to an error code return | ||
| 443 | * | ||
| 444 | * On failure returns %NULL and assigns -ENOTSOCK to @err. | ||
| 445 | */ | ||
| 446 | |||
| 427 | struct socket *sock_from_file(struct file *file, int *err) | 447 | struct socket *sock_from_file(struct file *file, int *err) |
| 428 | { | 448 | { |
| 429 | if (file->f_op == &socket_file_ops) | 449 | if (file->f_op == &socket_file_ops) |
| @@ -532,11 +552,11 @@ static const struct inode_operations sockfs_inode_ops = { | |||
| 532 | }; | 552 | }; |
| 533 | 553 | ||
| 534 | /** | 554 | /** |
| 535 | * sock_alloc - allocate a socket | 555 | * sock_alloc - allocate a socket |
| 536 | * | 556 | * |
| 537 | * Allocate a new inode and socket object. The two are bound together | 557 | * Allocate a new inode and socket object. The two are bound together |
| 538 | * and initialised. The socket is then returned. If we are out of inodes | 558 | * and initialised. The socket is then returned. If we are out of inodes |
| 539 | * NULL is returned. | 559 | * NULL is returned. This functions uses GFP_KERNEL internally. |
| 540 | */ | 560 | */ |
| 541 | 561 | ||
| 542 | struct socket *sock_alloc(void) | 562 | struct socket *sock_alloc(void) |
| @@ -561,7 +581,7 @@ struct socket *sock_alloc(void) | |||
| 561 | EXPORT_SYMBOL(sock_alloc); | 581 | EXPORT_SYMBOL(sock_alloc); |
| 562 | 582 | ||
| 563 | /** | 583 | /** |
| 564 | * sock_release - close a socket | 584 | * sock_release - close a socket |
| 565 | * @sock: socket to close | 585 | * @sock: socket to close |
| 566 | * | 586 | * |
| 567 | * The socket is released from the protocol stack if it has a release | 587 | * The socket is released from the protocol stack if it has a release |
| @@ -617,6 +637,15 @@ void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags) | |||
| 617 | } | 637 | } |
| 618 | EXPORT_SYMBOL(__sock_tx_timestamp); | 638 | EXPORT_SYMBOL(__sock_tx_timestamp); |
| 619 | 639 | ||
| 640 | /** | ||
| 641 | * sock_sendmsg - send a message through @sock | ||
| 642 | * @sock: socket | ||
| 643 | * @msg: message to send | ||
| 644 | * | ||
| 645 | * Sends @msg through @sock, passing through LSM. | ||
| 646 | * Returns the number of bytes sent, or an error code. | ||
| 647 | */ | ||
| 648 | |||
| 620 | static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) | 649 | static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) |
| 621 | { | 650 | { |
| 622 | int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg)); | 651 | int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg)); |
| @@ -633,6 +662,18 @@ int sock_sendmsg(struct socket *sock, struct msghdr *msg) | |||
| 633 | } | 662 | } |
| 634 | EXPORT_SYMBOL(sock_sendmsg); | 663 | EXPORT_SYMBOL(sock_sendmsg); |
| 635 | 664 | ||
| 665 | /** | ||
| 666 | * kernel_sendmsg - send a message through @sock (kernel-space) | ||
| 667 | * @sock: socket | ||
| 668 | * @msg: message header | ||
| 669 | * @vec: kernel vec | ||
| 670 | * @num: vec array length | ||
| 671 | * @size: total message data size | ||
| 672 | * | ||
| 673 | * Builds the message data with @vec and sends it through @sock. | ||
| 674 | * Returns the number of bytes sent, or an error code. | ||
| 675 | */ | ||
| 676 | |||
| 636 | int kernel_sendmsg(struct socket *sock, struct msghdr *msg, | 677 | int kernel_sendmsg(struct socket *sock, struct msghdr *msg, |
| 637 | struct kvec *vec, size_t num, size_t size) | 678 | struct kvec *vec, size_t num, size_t size) |
| 638 | { | 679 | { |
| @@ -641,6 +682,19 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg, | |||
| 641 | } | 682 | } |
| 642 | EXPORT_SYMBOL(kernel_sendmsg); | 683 | EXPORT_SYMBOL(kernel_sendmsg); |
| 643 | 684 | ||
| 685 | /** | ||
| 686 | * kernel_sendmsg_locked - send a message through @sock (kernel-space) | ||
| 687 | * @sk: sock | ||
| 688 | * @msg: message header | ||
| 689 | * @vec: output s/g array | ||
| 690 | * @num: output s/g array length | ||
| 691 | * @size: total message data size | ||
| 692 | * | ||
| 693 | * Builds the message data with @vec and sends it through @sock. | ||
| 694 | * Returns the number of bytes sent, or an error code. | ||
| 695 | * Caller must hold @sk. | ||
| 696 | */ | ||
| 697 | |||
| 644 | int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg, | 698 | int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg, |
| 645 | struct kvec *vec, size_t num, size_t size) | 699 | struct kvec *vec, size_t num, size_t size) |
| 646 | { | 700 | { |
| @@ -811,6 +865,16 @@ void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, | |||
| 811 | } | 865 | } |
| 812 | EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); | 866 | EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); |
| 813 | 867 | ||
| 868 | /** | ||
| 869 | * sock_recvmsg - receive a message from @sock | ||
| 870 | * @sock: socket | ||
| 871 | * @msg: message to receive | ||
| 872 | * @flags: message flags | ||
| 873 | * | ||
| 874 | * Receives @msg from @sock, passing through LSM. Returns the total number | ||
| 875 | * of bytes received, or an error. | ||
| 876 | */ | ||
| 877 | |||
| 814 | static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg, | 878 | static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg, |
| 815 | int flags) | 879 | int flags) |
| 816 | { | 880 | { |
| @@ -826,20 +890,21 @@ int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags) | |||
| 826 | EXPORT_SYMBOL(sock_recvmsg); | 890 | EXPORT_SYMBOL(sock_recvmsg); |
| 827 | 891 | ||
| 828 | /** | 892 | /** |
| 829 | * kernel_recvmsg - Receive a message from a socket (kernel space) | 893 | * kernel_recvmsg - Receive a message from a socket (kernel space) |
| 830 | * @sock: The socket to receive the message from | 894 | * @sock: The socket to receive the message from |
| 831 | * @msg: Received message | 895 | * @msg: Received message |
| 832 | * @vec: Input s/g array for message data | 896 | * @vec: Input s/g array for message data |
| 833 | * @num: Size of input s/g array | 897 | * @num: Size of input s/g array |
| 834 | * @size: Number of bytes to read | 898 | * @size: Number of bytes to read |
| 835 | * @flags: Message flags (MSG_DONTWAIT, etc...) | 899 | * @flags: Message flags (MSG_DONTWAIT, etc...) |
| 836 | * | 900 | * |
| 837 | * On return the msg structure contains the scatter/gather array passed in the | 901 | * On return the msg structure contains the scatter/gather array passed in the |
| 838 | * vec argument. The array is modified so that it consists of the unfilled | 902 | * vec argument. The array is modified so that it consists of the unfilled |
| 839 | * portion of the original array. | 903 | * portion of the original array. |
| 840 | * | 904 | * |
| 841 | * The returned value is the total number of bytes received, or an error. | 905 | * The returned value is the total number of bytes received, or an error. |
| 842 | */ | 906 | */ |
| 907 | |||
| 843 | int kernel_recvmsg(struct socket *sock, struct msghdr *msg, | 908 | int kernel_recvmsg(struct socket *sock, struct msghdr *msg, |
| 844 | struct kvec *vec, size_t num, size_t size, int flags) | 909 | struct kvec *vec, size_t num, size_t size, int flags) |
| 845 | { | 910 | { |
| @@ -1005,6 +1070,13 @@ static long sock_do_ioctl(struct net *net, struct socket *sock, | |||
| 1005 | * what to do with it - that's up to the protocol still. | 1070 | * what to do with it - that's up to the protocol still. |
| 1006 | */ | 1071 | */ |
| 1007 | 1072 | ||
| 1073 | /** | ||
| 1074 | * get_net_ns - increment the refcount of the network namespace | ||
| 1075 | * @ns: common namespace (net) | ||
| 1076 | * | ||
| 1077 | * Returns the net's common namespace. | ||
| 1078 | */ | ||
| 1079 | |||
| 1008 | struct ns_common *get_net_ns(struct ns_common *ns) | 1080 | struct ns_common *get_net_ns(struct ns_common *ns) |
| 1009 | { | 1081 | { |
| 1010 | return &get_net(container_of(ns, struct net, ns))->ns; | 1082 | return &get_net(container_of(ns, struct net, ns))->ns; |
| @@ -1099,6 +1171,19 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
| 1099 | return err; | 1171 | return err; |
| 1100 | } | 1172 | } |
| 1101 | 1173 | ||
| 1174 | /** | ||
| 1175 | * sock_create_lite - creates a socket | ||
| 1176 | * @family: protocol family (AF_INET, ...) | ||
| 1177 | * @type: communication type (SOCK_STREAM, ...) | ||
| 1178 | * @protocol: protocol (0, ...) | ||
| 1179 | * @res: new socket | ||
| 1180 | * | ||
| 1181 | * Creates a new socket and assigns it to @res, passing through LSM. | ||
| 1182 | * The new socket initialization is not complete, see kernel_accept(). | ||
| 1183 | * Returns 0 or an error. On failure @res is set to %NULL. | ||
| 1184 | * This function internally uses GFP_KERNEL. | ||
| 1185 | */ | ||
| 1186 | |||
| 1102 | int sock_create_lite(int family, int type, int protocol, struct socket **res) | 1187 | int sock_create_lite(int family, int type, int protocol, struct socket **res) |
| 1103 | { | 1188 | { |
| 1104 | int err; | 1189 | int err; |
| @@ -1224,6 +1309,21 @@ call_kill: | |||
| 1224 | } | 1309 | } |
| 1225 | EXPORT_SYMBOL(sock_wake_async); | 1310 | EXPORT_SYMBOL(sock_wake_async); |
| 1226 | 1311 | ||
| 1312 | /** | ||
| 1313 | * __sock_create - creates a socket | ||
| 1314 | * @net: net namespace | ||
| 1315 | * @family: protocol family (AF_INET, ...) | ||
| 1316 | * @type: communication type (SOCK_STREAM, ...) | ||
| 1317 | * @protocol: protocol (0, ...) | ||
| 1318 | * @res: new socket | ||
| 1319 | * @kern: boolean for kernel space sockets | ||
| 1320 | * | ||
| 1321 | * Creates a new socket and assigns it to @res, passing through LSM. | ||
| 1322 | * Returns 0 or an error. On failure @res is set to %NULL. @kern must | ||
| 1323 | * be set to true if the socket resides in kernel space. | ||
| 1324 | * This function internally uses GFP_KERNEL. | ||
| 1325 | */ | ||
| 1326 | |||
| 1227 | int __sock_create(struct net *net, int family, int type, int protocol, | 1327 | int __sock_create(struct net *net, int family, int type, int protocol, |
| 1228 | struct socket **res, int kern) | 1328 | struct socket **res, int kern) |
| 1229 | { | 1329 | { |
| @@ -1333,12 +1433,35 @@ out_release: | |||
| 1333 | } | 1433 | } |
| 1334 | EXPORT_SYMBOL(__sock_create); | 1434 | EXPORT_SYMBOL(__sock_create); |
| 1335 | 1435 | ||
| 1436 | /** | ||
| 1437 | * sock_create - creates a socket | ||
| 1438 | * @family: protocol family (AF_INET, ...) | ||
| 1439 | * @type: communication type (SOCK_STREAM, ...) | ||
| 1440 | * @protocol: protocol (0, ...) | ||
| 1441 | * @res: new socket | ||
| 1442 | * | ||
| 1443 | * A wrapper around __sock_create(). | ||
| 1444 | * Returns 0 or an error. This function internally uses GFP_KERNEL. | ||
| 1445 | */ | ||
| 1446 | |||
| 1336 | int sock_create(int family, int type, int protocol, struct socket **res) | 1447 | int sock_create(int family, int type, int protocol, struct socket **res) |
| 1337 | { | 1448 | { |
| 1338 | return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0); | 1449 | return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0); |
| 1339 | } | 1450 | } |
| 1340 | EXPORT_SYMBOL(sock_create); | 1451 | EXPORT_SYMBOL(sock_create); |
| 1341 | 1452 | ||
| 1453 | /** | ||
| 1454 | * sock_create_kern - creates a socket (kernel space) | ||
| 1455 | * @net: net namespace | ||
| 1456 | * @family: protocol family (AF_INET, ...) | ||
| 1457 | * @type: communication type (SOCK_STREAM, ...) | ||
| 1458 | * @protocol: protocol (0, ...) | ||
| 1459 | * @res: new socket | ||
| 1460 | * | ||
| 1461 | * A wrapper around __sock_create(). | ||
| 1462 | * Returns 0 or an error. This function internally uses GFP_KERNEL. | ||
| 1463 | */ | ||
| 1464 | |||
| 1342 | int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res) | 1465 | int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res) |
| 1343 | { | 1466 | { |
| 1344 | return __sock_create(net, family, type, protocol, res, 1); | 1467 | return __sock_create(net, family, type, protocol, res, 1); |
| @@ -3322,18 +3445,46 @@ static long compat_sock_ioctl(struct file *file, unsigned int cmd, | |||
| 3322 | } | 3445 | } |
| 3323 | #endif | 3446 | #endif |
| 3324 | 3447 | ||
| 3448 | /** | ||
| 3449 | * kernel_bind - bind an address to a socket (kernel space) | ||
| 3450 | * @sock: socket | ||
| 3451 | * @addr: address | ||
| 3452 | * @addrlen: length of address | ||
| 3453 | * | ||
| 3454 | * Returns 0 or an error. | ||
| 3455 | */ | ||
| 3456 | |||
| 3325 | int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) | 3457 | int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) |
| 3326 | { | 3458 | { |
| 3327 | return sock->ops->bind(sock, addr, addrlen); | 3459 | return sock->ops->bind(sock, addr, addrlen); |
| 3328 | } | 3460 | } |
| 3329 | EXPORT_SYMBOL(kernel_bind); | 3461 | EXPORT_SYMBOL(kernel_bind); |
| 3330 | 3462 | ||
| 3463 | /** | ||
| 3464 | * kernel_listen - move socket to listening state (kernel space) | ||
| 3465 | * @sock: socket | ||
| 3466 | * @backlog: pending connections queue size | ||
| 3467 | * | ||
| 3468 | * Returns 0 or an error. | ||
| 3469 | */ | ||
| 3470 | |||
| 3331 | int kernel_listen(struct socket *sock, int backlog) | 3471 | int kernel_listen(struct socket *sock, int backlog) |
| 3332 | { | 3472 | { |
| 3333 | return sock->ops->listen(sock, backlog); | 3473 | return sock->ops->listen(sock, backlog); |
| 3334 | } | 3474 | } |
| 3335 | EXPORT_SYMBOL(kernel_listen); | 3475 | EXPORT_SYMBOL(kernel_listen); |
| 3336 | 3476 | ||
| 3477 | /** | ||
| 3478 | * kernel_accept - accept a connection (kernel space) | ||
| 3479 | * @sock: listening socket | ||
| 3480 | * @newsock: new connected socket | ||
| 3481 | * @flags: flags | ||
| 3482 | * | ||
| 3483 | * @flags must be SOCK_CLOEXEC, SOCK_NONBLOCK or 0. | ||
| 3484 | * If it fails, @newsock is guaranteed to be %NULL. | ||
| 3485 | * Returns 0 or an error. | ||
| 3486 | */ | ||
| 3487 | |||
| 3337 | int kernel_accept(struct socket *sock, struct socket **newsock, int flags) | 3488 | int kernel_accept(struct socket *sock, struct socket **newsock, int flags) |
| 3338 | { | 3489 | { |
| 3339 | struct sock *sk = sock->sk; | 3490 | struct sock *sk = sock->sk; |
| @@ -3359,6 +3510,19 @@ done: | |||
| 3359 | } | 3510 | } |
| 3360 | EXPORT_SYMBOL(kernel_accept); | 3511 | EXPORT_SYMBOL(kernel_accept); |
| 3361 | 3512 | ||
| 3513 | /** | ||
| 3514 | * kernel_connect - connect a socket (kernel space) | ||
| 3515 | * @sock: socket | ||
| 3516 | * @addr: address | ||
| 3517 | * @addrlen: address length | ||
| 3518 | * @flags: flags (O_NONBLOCK, ...) | ||
| 3519 | * | ||
| 3520 | * For datagram sockets, @addr is the addres to which datagrams are sent | ||
| 3521 | * by default, and the only address from which datagrams are received. | ||
| 3522 | * For stream sockets, attempts to connect to @addr. | ||
| 3523 | * Returns 0 or an error code. | ||
| 3524 | */ | ||
| 3525 | |||
| 3362 | int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, | 3526 | int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, |
| 3363 | int flags) | 3527 | int flags) |
| 3364 | { | 3528 | { |
| @@ -3366,18 +3530,48 @@ int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, | |||
| 3366 | } | 3530 | } |
| 3367 | EXPORT_SYMBOL(kernel_connect); | 3531 | EXPORT_SYMBOL(kernel_connect); |
| 3368 | 3532 | ||
| 3533 | /** | ||
| 3534 | * kernel_getsockname - get the address which the socket is bound (kernel space) | ||
| 3535 | * @sock: socket | ||
| 3536 | * @addr: address holder | ||
| 3537 | * | ||
| 3538 | * Fills the @addr pointer with the address which the socket is bound. | ||
| 3539 | * Returns 0 or an error code. | ||
| 3540 | */ | ||
| 3541 | |||
| 3369 | int kernel_getsockname(struct socket *sock, struct sockaddr *addr) | 3542 | int kernel_getsockname(struct socket *sock, struct sockaddr *addr) |
| 3370 | { | 3543 | { |
| 3371 | return sock->ops->getname(sock, addr, 0); | 3544 | return sock->ops->getname(sock, addr, 0); |
| 3372 | } | 3545 | } |
| 3373 | EXPORT_SYMBOL(kernel_getsockname); | 3546 | EXPORT_SYMBOL(kernel_getsockname); |
| 3374 | 3547 | ||
| 3548 | /** | ||
| 3549 | * kernel_peername - get the address which the socket is connected (kernel space) | ||
| 3550 | * @sock: socket | ||
| 3551 | * @addr: address holder | ||
| 3552 | * | ||
| 3553 | * Fills the @addr pointer with the address which the socket is connected. | ||
| 3554 | * Returns 0 or an error code. | ||
| 3555 | */ | ||
| 3556 | |||
| 3375 | int kernel_getpeername(struct socket *sock, struct sockaddr *addr) | 3557 | int kernel_getpeername(struct socket *sock, struct sockaddr *addr) |
| 3376 | { | 3558 | { |
| 3377 | return sock->ops->getname(sock, addr, 1); | 3559 | return sock->ops->getname(sock, addr, 1); |
| 3378 | } | 3560 | } |
| 3379 | EXPORT_SYMBOL(kernel_getpeername); | 3561 | EXPORT_SYMBOL(kernel_getpeername); |
| 3380 | 3562 | ||
| 3563 | /** | ||
| 3564 | * kernel_getsockopt - get a socket option (kernel space) | ||
| 3565 | * @sock: socket | ||
| 3566 | * @level: API level (SOL_SOCKET, ...) | ||
| 3567 | * @optname: option tag | ||
| 3568 | * @optval: option value | ||
| 3569 | * @optlen: option length | ||
| 3570 | * | ||
| 3571 | * Assigns the option length to @optlen. | ||
| 3572 | * Returns 0 or an error. | ||
| 3573 | */ | ||
| 3574 | |||
| 3381 | int kernel_getsockopt(struct socket *sock, int level, int optname, | 3575 | int kernel_getsockopt(struct socket *sock, int level, int optname, |
| 3382 | char *optval, int *optlen) | 3576 | char *optval, int *optlen) |
| 3383 | { | 3577 | { |
| @@ -3400,6 +3594,17 @@ int kernel_getsockopt(struct socket *sock, int level, int optname, | |||
| 3400 | } | 3594 | } |
| 3401 | EXPORT_SYMBOL(kernel_getsockopt); | 3595 | EXPORT_SYMBOL(kernel_getsockopt); |
| 3402 | 3596 | ||
| 3597 | /** | ||
| 3598 | * kernel_setsockopt - set a socket option (kernel space) | ||
| 3599 | * @sock: socket | ||
| 3600 | * @level: API level (SOL_SOCKET, ...) | ||
| 3601 | * @optname: option tag | ||
| 3602 | * @optval: option value | ||
| 3603 | * @optlen: option length | ||
| 3604 | * | ||
| 3605 | * Returns 0 or an error. | ||
| 3606 | */ | ||
| 3607 | |||
| 3403 | int kernel_setsockopt(struct socket *sock, int level, int optname, | 3608 | int kernel_setsockopt(struct socket *sock, int level, int optname, |
| 3404 | char *optval, unsigned int optlen) | 3609 | char *optval, unsigned int optlen) |
| 3405 | { | 3610 | { |
| @@ -3420,6 +3625,17 @@ int kernel_setsockopt(struct socket *sock, int level, int optname, | |||
| 3420 | } | 3625 | } |
| 3421 | EXPORT_SYMBOL(kernel_setsockopt); | 3626 | EXPORT_SYMBOL(kernel_setsockopt); |
| 3422 | 3627 | ||
| 3628 | /** | ||
| 3629 | * kernel_sendpage - send a &page through a socket (kernel space) | ||
| 3630 | * @sock: socket | ||
| 3631 | * @page: page | ||
| 3632 | * @offset: page offset | ||
| 3633 | * @size: total size in bytes | ||
| 3634 | * @flags: flags (MSG_DONTWAIT, ...) | ||
| 3635 | * | ||
| 3636 | * Returns the total amount sent in bytes or an error. | ||
| 3637 | */ | ||
| 3638 | |||
| 3423 | int kernel_sendpage(struct socket *sock, struct page *page, int offset, | 3639 | int kernel_sendpage(struct socket *sock, struct page *page, int offset, |
| 3424 | size_t size, int flags) | 3640 | size_t size, int flags) |
| 3425 | { | 3641 | { |
| @@ -3430,6 +3646,18 @@ int kernel_sendpage(struct socket *sock, struct page *page, int offset, | |||
| 3430 | } | 3646 | } |
| 3431 | EXPORT_SYMBOL(kernel_sendpage); | 3647 | EXPORT_SYMBOL(kernel_sendpage); |
| 3432 | 3648 | ||
| 3649 | /** | ||
| 3650 | * kernel_sendpage_locked - send a &page through the locked sock (kernel space) | ||
| 3651 | * @sk: sock | ||
| 3652 | * @page: page | ||
| 3653 | * @offset: page offset | ||
| 3654 | * @size: total size in bytes | ||
| 3655 | * @flags: flags (MSG_DONTWAIT, ...) | ||
| 3656 | * | ||
| 3657 | * Returns the total amount sent in bytes or an error. | ||
| 3658 | * Caller must hold @sk. | ||
| 3659 | */ | ||
| 3660 | |||
| 3433 | int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset, | 3661 | int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset, |
| 3434 | size_t size, int flags) | 3662 | size_t size, int flags) |
| 3435 | { | 3663 | { |
| @@ -3443,17 +3671,30 @@ int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset, | |||
| 3443 | } | 3671 | } |
| 3444 | EXPORT_SYMBOL(kernel_sendpage_locked); | 3672 | EXPORT_SYMBOL(kernel_sendpage_locked); |
| 3445 | 3673 | ||
| 3674 | /** | ||
| 3675 | * kernel_shutdown - shut down part of a full-duplex connection (kernel space) | ||
| 3676 | * @sock: socket | ||
| 3677 | * @how: connection part | ||
| 3678 | * | ||
| 3679 | * Returns 0 or an error. | ||
| 3680 | */ | ||
| 3681 | |||
| 3446 | int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) | 3682 | int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) |
| 3447 | { | 3683 | { |
| 3448 | return sock->ops->shutdown(sock, how); | 3684 | return sock->ops->shutdown(sock, how); |
| 3449 | } | 3685 | } |
| 3450 | EXPORT_SYMBOL(kernel_sock_shutdown); | 3686 | EXPORT_SYMBOL(kernel_sock_shutdown); |
| 3451 | 3687 | ||
| 3452 | /* This routine returns the IP overhead imposed by a socket i.e. | 3688 | /** |
| 3453 | * the length of the underlying IP header, depending on whether | 3689 | * kernel_sock_ip_overhead - returns the IP overhead imposed by a socket |
| 3454 | * this is an IPv4 or IPv6 socket and the length from IP options turned | 3690 | * @sk: socket |
| 3455 | * on at the socket. Assumes that the caller has a lock on the socket. | 3691 | * |
| 3692 | * This routine returns the IP overhead imposed by a socket i.e. | ||
| 3693 | * the length of the underlying IP header, depending on whether | ||
| 3694 | * this is an IPv4 or IPv6 socket and the length from IP options turned | ||
| 3695 | * on at the socket. Assumes that the caller has a lock on the socket. | ||
| 3456 | */ | 3696 | */ |
| 3697 | |||
| 3457 | u32 kernel_sock_ip_overhead(struct sock *sk) | 3698 | u32 kernel_sock_ip_overhead(struct sock *sk) |
| 3458 | { | 3699 | { |
| 3459 | struct inet_sock *inet; | 3700 | struct inet_sock *inet; |
diff --git a/net/strparser/strparser.c b/net/strparser/strparser.c index da1a676860ca..860dcfb95ee4 100644 --- a/net/strparser/strparser.c +++ b/net/strparser/strparser.c | |||
| @@ -550,6 +550,8 @@ EXPORT_SYMBOL_GPL(strp_check_rcv); | |||
| 550 | static int __init strp_mod_init(void) | 550 | static int __init strp_mod_init(void) |
| 551 | { | 551 | { |
| 552 | strp_wq = create_singlethread_workqueue("kstrp"); | 552 | strp_wq = create_singlethread_workqueue("kstrp"); |
| 553 | if (unlikely(!strp_wq)) | ||
| 554 | return -ENOMEM; | ||
| 553 | 555 | ||
| 554 | return 0; | 556 | return 0; |
| 555 | } | 557 | } |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 228970e6e52b..187d10443a15 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -2311,6 +2311,15 @@ out_exit: | |||
| 2311 | rpc_exit(task, status); | 2311 | rpc_exit(task, status); |
| 2312 | } | 2312 | } |
| 2313 | 2313 | ||
| 2314 | static bool | ||
| 2315 | rpc_check_connected(const struct rpc_rqst *req) | ||
| 2316 | { | ||
| 2317 | /* No allocated request or transport? return true */ | ||
| 2318 | if (!req || !req->rq_xprt) | ||
| 2319 | return true; | ||
| 2320 | return xprt_connected(req->rq_xprt); | ||
| 2321 | } | ||
| 2322 | |||
| 2314 | static void | 2323 | static void |
| 2315 | rpc_check_timeout(struct rpc_task *task) | 2324 | rpc_check_timeout(struct rpc_task *task) |
| 2316 | { | 2325 | { |
| @@ -2322,10 +2331,11 @@ rpc_check_timeout(struct rpc_task *task) | |||
| 2322 | dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid); | 2331 | dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid); |
| 2323 | task->tk_timeouts++; | 2332 | task->tk_timeouts++; |
| 2324 | 2333 | ||
| 2325 | if (RPC_IS_SOFTCONN(task)) { | 2334 | if (RPC_IS_SOFTCONN(task) && !rpc_check_connected(task->tk_rqstp)) { |
| 2326 | rpc_exit(task, -ETIMEDOUT); | 2335 | rpc_exit(task, -ETIMEDOUT); |
| 2327 | return; | 2336 | return; |
| 2328 | } | 2337 | } |
| 2338 | |||
| 2329 | if (RPC_IS_SOFT(task)) { | 2339 | if (RPC_IS_SOFT(task)) { |
| 2330 | if (clnt->cl_chatty) { | 2340 | if (clnt->cl_chatty) { |
| 2331 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", | 2341 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 9359539907ba..732d4b57411a 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
| @@ -495,8 +495,8 @@ xs_read_stream_request(struct sock_xprt *transport, struct msghdr *msg, | |||
| 495 | int flags, struct rpc_rqst *req) | 495 | int flags, struct rpc_rqst *req) |
| 496 | { | 496 | { |
| 497 | struct xdr_buf *buf = &req->rq_private_buf; | 497 | struct xdr_buf *buf = &req->rq_private_buf; |
| 498 | size_t want, read; | 498 | size_t want, uninitialized_var(read); |
| 499 | ssize_t ret; | 499 | ssize_t uninitialized_var(ret); |
| 500 | 500 | ||
| 501 | xs_read_header(transport, buf); | 501 | xs_read_header(transport, buf); |
| 502 | 502 | ||
diff --git a/net/tipc/group.c b/net/tipc/group.c index 06fee142f09f..63f39201e41e 100644 --- a/net/tipc/group.c +++ b/net/tipc/group.c | |||
| @@ -919,6 +919,9 @@ int tipc_group_fill_sock_diag(struct tipc_group *grp, struct sk_buff *skb) | |||
| 919 | { | 919 | { |
| 920 | struct nlattr *group = nla_nest_start(skb, TIPC_NLA_SOCK_GROUP); | 920 | struct nlattr *group = nla_nest_start(skb, TIPC_NLA_SOCK_GROUP); |
| 921 | 921 | ||
| 922 | if (!group) | ||
| 923 | return -EMSGSIZE; | ||
| 924 | |||
| 922 | if (nla_put_u32(skb, TIPC_NLA_SOCK_GROUP_ID, | 925 | if (nla_put_u32(skb, TIPC_NLA_SOCK_GROUP_ID, |
| 923 | grp->type) || | 926 | grp->type) || |
| 924 | nla_put_u32(skb, TIPC_NLA_SOCK_GROUP_INSTANCE, | 927 | nla_put_u32(skb, TIPC_NLA_SOCK_GROUP_INSTANCE, |
diff --git a/net/tipc/net.c b/net/tipc/net.c index f076edb74338..7ce1e86b024f 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
| @@ -163,12 +163,9 @@ void tipc_sched_net_finalize(struct net *net, u32 addr) | |||
| 163 | 163 | ||
| 164 | void tipc_net_stop(struct net *net) | 164 | void tipc_net_stop(struct net *net) |
| 165 | { | 165 | { |
| 166 | u32 self = tipc_own_addr(net); | 166 | if (!tipc_own_id(net)) |
| 167 | |||
| 168 | if (!self) | ||
| 169 | return; | 167 | return; |
| 170 | 168 | ||
| 171 | tipc_nametbl_withdraw(net, TIPC_CFG_SRV, self, self, self); | ||
| 172 | rtnl_lock(); | 169 | rtnl_lock(); |
| 173 | tipc_bearer_stop(net); | 170 | tipc_bearer_stop(net); |
| 174 | tipc_node_stop(net); | 171 | tipc_node_stop(net); |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 2dc4919ab23c..dd3b6dc17662 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
| @@ -817,10 +817,10 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id, | |||
| 817 | static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) | 817 | static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) |
| 818 | { | 818 | { |
| 819 | struct tipc_link_entry *le = &n->links[bearer_id]; | 819 | struct tipc_link_entry *le = &n->links[bearer_id]; |
| 820 | struct tipc_media_addr *maddr = NULL; | ||
| 820 | struct tipc_link *l = le->link; | 821 | struct tipc_link *l = le->link; |
| 821 | struct tipc_media_addr *maddr; | ||
| 822 | struct sk_buff_head xmitq; | ||
| 823 | int old_bearer_id = bearer_id; | 822 | int old_bearer_id = bearer_id; |
| 823 | struct sk_buff_head xmitq; | ||
| 824 | 824 | ||
| 825 | if (!l) | 825 | if (!l) |
| 826 | return; | 826 | return; |
| @@ -844,7 +844,8 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) | |||
| 844 | tipc_node_write_unlock(n); | 844 | tipc_node_write_unlock(n); |
| 845 | if (delete) | 845 | if (delete) |
| 846 | tipc_mon_remove_peer(n->net, n->addr, old_bearer_id); | 846 | tipc_mon_remove_peer(n->net, n->addr, old_bearer_id); |
| 847 | tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr); | 847 | if (!skb_queue_empty(&xmitq)) |
| 848 | tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr); | ||
| 848 | tipc_sk_rcv(n->net, &le->inputq); | 849 | tipc_sk_rcv(n->net, &le->inputq); |
| 849 | } | 850 | } |
| 850 | 851 | ||
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 3274ef625dba..b542f14ed444 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -2349,6 +2349,16 @@ static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) | |||
| 2349 | return 0; | 2349 | return 0; |
| 2350 | } | 2350 | } |
| 2351 | 2351 | ||
| 2352 | static bool tipc_sockaddr_is_sane(struct sockaddr_tipc *addr) | ||
| 2353 | { | ||
| 2354 | if (addr->family != AF_TIPC) | ||
| 2355 | return false; | ||
| 2356 | if (addr->addrtype == TIPC_SERVICE_RANGE) | ||
| 2357 | return (addr->addr.nameseq.lower <= addr->addr.nameseq.upper); | ||
| 2358 | return (addr->addrtype == TIPC_SERVICE_ADDR || | ||
| 2359 | addr->addrtype == TIPC_SOCKET_ADDR); | ||
| 2360 | } | ||
| 2361 | |||
| 2352 | /** | 2362 | /** |
| 2353 | * tipc_connect - establish a connection to another TIPC port | 2363 | * tipc_connect - establish a connection to another TIPC port |
| 2354 | * @sock: socket structure | 2364 | * @sock: socket structure |
| @@ -2384,18 +2394,18 @@ static int tipc_connect(struct socket *sock, struct sockaddr *dest, | |||
| 2384 | if (!tipc_sk_type_connectionless(sk)) | 2394 | if (!tipc_sk_type_connectionless(sk)) |
| 2385 | res = -EINVAL; | 2395 | res = -EINVAL; |
| 2386 | goto exit; | 2396 | goto exit; |
| 2387 | } else if (dst->family != AF_TIPC) { | ||
| 2388 | res = -EINVAL; | ||
| 2389 | } | 2397 | } |
| 2390 | if (dst->addrtype != TIPC_ADDR_ID && dst->addrtype != TIPC_ADDR_NAME) | 2398 | if (!tipc_sockaddr_is_sane(dst)) { |
| 2391 | res = -EINVAL; | 2399 | res = -EINVAL; |
| 2392 | if (res) | ||
| 2393 | goto exit; | 2400 | goto exit; |
| 2394 | 2401 | } | |
| 2395 | /* DGRAM/RDM connect(), just save the destaddr */ | 2402 | /* DGRAM/RDM connect(), just save the destaddr */ |
| 2396 | if (tipc_sk_type_connectionless(sk)) { | 2403 | if (tipc_sk_type_connectionless(sk)) { |
| 2397 | memcpy(&tsk->peer, dest, destlen); | 2404 | memcpy(&tsk->peer, dest, destlen); |
| 2398 | goto exit; | 2405 | goto exit; |
| 2406 | } else if (dst->addrtype == TIPC_SERVICE_RANGE) { | ||
| 2407 | res = -EINVAL; | ||
| 2408 | goto exit; | ||
| 2399 | } | 2409 | } |
| 2400 | 2410 | ||
| 2401 | previous = sk->sk_state; | 2411 | previous = sk->sk_state; |
| @@ -3255,6 +3265,8 @@ static int __tipc_nl_add_sk_con(struct sk_buff *skb, struct tipc_sock *tsk) | |||
| 3255 | peer_port = tsk_peer_port(tsk); | 3265 | peer_port = tsk_peer_port(tsk); |
| 3256 | 3266 | ||
| 3257 | nest = nla_nest_start(skb, TIPC_NLA_SOCK_CON); | 3267 | nest = nla_nest_start(skb, TIPC_NLA_SOCK_CON); |
| 3268 | if (!nest) | ||
| 3269 | return -EMSGSIZE; | ||
| 3258 | 3270 | ||
| 3259 | if (nla_put_u32(skb, TIPC_NLA_CON_NODE, peer_node)) | 3271 | if (nla_put_u32(skb, TIPC_NLA_CON_NODE, peer_node)) |
| 3260 | goto msg_full; | 3272 | goto msg_full; |
diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index 4a708a4e8583..b45932d78004 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c | |||
| @@ -363,6 +363,7 @@ static int tipc_conn_rcv_sub(struct tipc_topsrv *srv, | |||
| 363 | struct tipc_subscription *sub; | 363 | struct tipc_subscription *sub; |
| 364 | 364 | ||
| 365 | if (tipc_sub_read(s, filter) & TIPC_SUB_CANCEL) { | 365 | if (tipc_sub_read(s, filter) & TIPC_SUB_CANCEL) { |
| 366 | s->filter &= __constant_ntohl(~TIPC_SUB_CANCEL); | ||
| 366 | tipc_conn_delete_sub(con, s); | 367 | tipc_conn_delete_sub(con, s); |
| 367 | return 0; | 368 | return 0; |
| 368 | } | 369 | } |
diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c index 77520eacee8f..989e52386c35 100644 --- a/net/xdp/xdp_umem.c +++ b/net/xdp/xdp_umem.c | |||
| @@ -193,9 +193,6 @@ static void xdp_umem_unaccount_pages(struct xdp_umem *umem) | |||
| 193 | 193 | ||
| 194 | static void xdp_umem_release(struct xdp_umem *umem) | 194 | static void xdp_umem_release(struct xdp_umem *umem) |
| 195 | { | 195 | { |
| 196 | struct task_struct *task; | ||
| 197 | struct mm_struct *mm; | ||
| 198 | |||
| 199 | xdp_umem_clear_dev(umem); | 196 | xdp_umem_clear_dev(umem); |
| 200 | 197 | ||
| 201 | ida_simple_remove(&umem_ida, umem->id); | 198 | ida_simple_remove(&umem_ida, umem->id); |
| @@ -214,21 +211,10 @@ static void xdp_umem_release(struct xdp_umem *umem) | |||
| 214 | 211 | ||
| 215 | xdp_umem_unpin_pages(umem); | 212 | xdp_umem_unpin_pages(umem); |
| 216 | 213 | ||
| 217 | task = get_pid_task(umem->pid, PIDTYPE_PID); | ||
| 218 | put_pid(umem->pid); | ||
| 219 | if (!task) | ||
| 220 | goto out; | ||
| 221 | mm = get_task_mm(task); | ||
| 222 | put_task_struct(task); | ||
| 223 | if (!mm) | ||
| 224 | goto out; | ||
| 225 | |||
| 226 | mmput(mm); | ||
| 227 | kfree(umem->pages); | 214 | kfree(umem->pages); |
| 228 | umem->pages = NULL; | 215 | umem->pages = NULL; |
| 229 | 216 | ||
| 230 | xdp_umem_unaccount_pages(umem); | 217 | xdp_umem_unaccount_pages(umem); |
| 231 | out: | ||
| 232 | kfree(umem); | 218 | kfree(umem); |
| 233 | } | 219 | } |
| 234 | 220 | ||
| @@ -357,7 +343,6 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) | |||
| 357 | if (size_chk < 0) | 343 | if (size_chk < 0) |
| 358 | return -EINVAL; | 344 | return -EINVAL; |
| 359 | 345 | ||
| 360 | umem->pid = get_task_pid(current, PIDTYPE_PID); | ||
| 361 | umem->address = (unsigned long)addr; | 346 | umem->address = (unsigned long)addr; |
| 362 | umem->chunk_mask = ~((u64)chunk_size - 1); | 347 | umem->chunk_mask = ~((u64)chunk_size - 1); |
| 363 | umem->size = size; | 348 | umem->size = size; |
| @@ -373,7 +358,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) | |||
| 373 | 358 | ||
| 374 | err = xdp_umem_account_pages(umem); | 359 | err = xdp_umem_account_pages(umem); |
| 375 | if (err) | 360 | if (err) |
| 376 | goto out; | 361 | return err; |
| 377 | 362 | ||
| 378 | err = xdp_umem_pin_pages(umem); | 363 | err = xdp_umem_pin_pages(umem); |
| 379 | if (err) | 364 | if (err) |
| @@ -392,8 +377,6 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) | |||
| 392 | 377 | ||
| 393 | out_account: | 378 | out_account: |
| 394 | xdp_umem_unaccount_pages(umem); | 379 | xdp_umem_unaccount_pages(umem); |
| 395 | out: | ||
| 396 | put_pid(umem->pid); | ||
| 397 | return err; | 380 | return err; |
| 398 | } | 381 | } |
| 399 | 382 | ||
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 3c38ac9a92a7..929c8e537a14 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h | |||
| @@ -502,16 +502,6 @@ union bpf_attr { | |||
| 502 | * Return | 502 | * Return |
| 503 | * 0 on success, or a negative error in case of failure. | 503 | * 0 on success, or a negative error in case of failure. |
| 504 | * | 504 | * |
| 505 | * int bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags) | ||
| 506 | * Description | ||
| 507 | * Push an element *value* in *map*. *flags* is one of: | ||
| 508 | * | ||
| 509 | * **BPF_EXIST** | ||
| 510 | * If the queue/stack is full, the oldest element is removed to | ||
| 511 | * make room for this. | ||
| 512 | * Return | ||
| 513 | * 0 on success, or a negative error in case of failure. | ||
| 514 | * | ||
| 515 | * int bpf_probe_read(void *dst, u32 size, const void *src) | 505 | * int bpf_probe_read(void *dst, u32 size, const void *src) |
| 516 | * Description | 506 | * Description |
| 517 | * For tracing programs, safely attempt to read *size* bytes from | 507 | * For tracing programs, safely attempt to read *size* bytes from |
| @@ -1435,14 +1425,14 @@ union bpf_attr { | |||
| 1435 | * u64 bpf_get_socket_cookie(struct bpf_sock_addr *ctx) | 1425 | * u64 bpf_get_socket_cookie(struct bpf_sock_addr *ctx) |
| 1436 | * Description | 1426 | * Description |
| 1437 | * Equivalent to bpf_get_socket_cookie() helper that accepts | 1427 | * Equivalent to bpf_get_socket_cookie() helper that accepts |
| 1438 | * *skb*, but gets socket from **struct bpf_sock_addr** contex. | 1428 | * *skb*, but gets socket from **struct bpf_sock_addr** context. |
| 1439 | * Return | 1429 | * Return |
| 1440 | * A 8-byte long non-decreasing number. | 1430 | * A 8-byte long non-decreasing number. |
| 1441 | * | 1431 | * |
| 1442 | * u64 bpf_get_socket_cookie(struct bpf_sock_ops *ctx) | 1432 | * u64 bpf_get_socket_cookie(struct bpf_sock_ops *ctx) |
| 1443 | * Description | 1433 | * Description |
| 1444 | * Equivalent to bpf_get_socket_cookie() helper that accepts | 1434 | * Equivalent to bpf_get_socket_cookie() helper that accepts |
| 1445 | * *skb*, but gets socket from **struct bpf_sock_ops** contex. | 1435 | * *skb*, but gets socket from **struct bpf_sock_ops** context. |
| 1446 | * Return | 1436 | * Return |
| 1447 | * A 8-byte long non-decreasing number. | 1437 | * A 8-byte long non-decreasing number. |
| 1448 | * | 1438 | * |
| @@ -2098,52 +2088,52 @@ union bpf_attr { | |||
| 2098 | * Return | 2088 | * Return |
| 2099 | * 0 on success, or a negative error in case of failure. | 2089 | * 0 on success, or a negative error in case of failure. |
| 2100 | * | 2090 | * |
| 2101 | * int bpf_rc_keydown(void *ctx, u32 protocol, u64 scancode, u32 toggle) | 2091 | * int bpf_rc_repeat(void *ctx) |
| 2102 | * Description | 2092 | * Description |
| 2103 | * This helper is used in programs implementing IR decoding, to | 2093 | * This helper is used in programs implementing IR decoding, to |
| 2104 | * report a successfully decoded key press with *scancode*, | 2094 | * report a successfully decoded repeat key message. This delays |
| 2105 | * *toggle* value in the given *protocol*. The scancode will be | 2095 | * the generation of a key up event for previously generated |
| 2106 | * translated to a keycode using the rc keymap, and reported as | 2096 | * key down event. |
| 2107 | * an input key down event. After a period a key up event is | ||
| 2108 | * generated. This period can be extended by calling either | ||
| 2109 | * **bpf_rc_keydown**\ () again with the same values, or calling | ||
| 2110 | * **bpf_rc_repeat**\ (). | ||
| 2111 | * | 2097 | * |
| 2112 | * Some protocols include a toggle bit, in case the button was | 2098 | * Some IR protocols like NEC have a special IR message for |
| 2113 | * released and pressed again between consecutive scancodes. | 2099 | * repeating last button, for when a button is held down. |
| 2114 | * | 2100 | * |
| 2115 | * The *ctx* should point to the lirc sample as passed into | 2101 | * The *ctx* should point to the lirc sample as passed into |
| 2116 | * the program. | 2102 | * the program. |
| 2117 | * | 2103 | * |
| 2118 | * The *protocol* is the decoded protocol number (see | ||
| 2119 | * **enum rc_proto** for some predefined values). | ||
| 2120 | * | ||
| 2121 | * This helper is only available is the kernel was compiled with | 2104 | * This helper is only available is the kernel was compiled with |
| 2122 | * the **CONFIG_BPF_LIRC_MODE2** configuration option set to | 2105 | * the **CONFIG_BPF_LIRC_MODE2** configuration option set to |
| 2123 | * "**y**". | 2106 | * "**y**". |
| 2124 | * Return | 2107 | * Return |
| 2125 | * 0 | 2108 | * 0 |
| 2126 | * | 2109 | * |
| 2127 | * int bpf_rc_repeat(void *ctx) | 2110 | * int bpf_rc_keydown(void *ctx, u32 protocol, u64 scancode, u32 toggle) |
| 2128 | * Description | 2111 | * Description |
| 2129 | * This helper is used in programs implementing IR decoding, to | 2112 | * This helper is used in programs implementing IR decoding, to |
| 2130 | * report a successfully decoded repeat key message. This delays | 2113 | * report a successfully decoded key press with *scancode*, |
| 2131 | * the generation of a key up event for previously generated | 2114 | * *toggle* value in the given *protocol*. The scancode will be |
| 2132 | * key down event. | 2115 | * translated to a keycode using the rc keymap, and reported as |
| 2116 | * an input key down event. After a period a key up event is | ||
| 2117 | * generated. This period can be extended by calling either | ||
| 2118 | * **bpf_rc_keydown**\ () again with the same values, or calling | ||
| 2119 | * **bpf_rc_repeat**\ (). | ||
| 2133 | * | 2120 | * |
| 2134 | * Some IR protocols like NEC have a special IR message for | 2121 | * Some protocols include a toggle bit, in case the button was |
| 2135 | * repeating last button, for when a button is held down. | 2122 | * released and pressed again between consecutive scancodes. |
| 2136 | * | 2123 | * |
| 2137 | * The *ctx* should point to the lirc sample as passed into | 2124 | * The *ctx* should point to the lirc sample as passed into |
| 2138 | * the program. | 2125 | * the program. |
| 2139 | * | 2126 | * |
| 2127 | * The *protocol* is the decoded protocol number (see | ||
| 2128 | * **enum rc_proto** for some predefined values). | ||
| 2129 | * | ||
| 2140 | * This helper is only available is the kernel was compiled with | 2130 | * This helper is only available is the kernel was compiled with |
| 2141 | * the **CONFIG_BPF_LIRC_MODE2** configuration option set to | 2131 | * the **CONFIG_BPF_LIRC_MODE2** configuration option set to |
| 2142 | * "**y**". | 2132 | * "**y**". |
| 2143 | * Return | 2133 | * Return |
| 2144 | * 0 | 2134 | * 0 |
| 2145 | * | 2135 | * |
| 2146 | * uint64_t bpf_skb_cgroup_id(struct sk_buff *skb) | 2136 | * u64 bpf_skb_cgroup_id(struct sk_buff *skb) |
| 2147 | * Description | 2137 | * Description |
| 2148 | * Return the cgroup v2 id of the socket associated with the *skb*. | 2138 | * Return the cgroup v2 id of the socket associated with the *skb*. |
| 2149 | * This is roughly similar to the **bpf_get_cgroup_classid**\ () | 2139 | * This is roughly similar to the **bpf_get_cgroup_classid**\ () |
| @@ -2159,30 +2149,12 @@ union bpf_attr { | |||
| 2159 | * Return | 2149 | * Return |
| 2160 | * The id is returned or 0 in case the id could not be retrieved. | 2150 | * The id is returned or 0 in case the id could not be retrieved. |
| 2161 | * | 2151 | * |
| 2162 | * u64 bpf_skb_ancestor_cgroup_id(struct sk_buff *skb, int ancestor_level) | ||
| 2163 | * Description | ||
| 2164 | * Return id of cgroup v2 that is ancestor of cgroup associated | ||
| 2165 | * with the *skb* at the *ancestor_level*. The root cgroup is at | ||
| 2166 | * *ancestor_level* zero and each step down the hierarchy | ||
| 2167 | * increments the level. If *ancestor_level* == level of cgroup | ||
| 2168 | * associated with *skb*, then return value will be same as that | ||
| 2169 | * of **bpf_skb_cgroup_id**\ (). | ||
| 2170 | * | ||
| 2171 | * The helper is useful to implement policies based on cgroups | ||
| 2172 | * that are upper in hierarchy than immediate cgroup associated | ||
| 2173 | * with *skb*. | ||
| 2174 | * | ||
| 2175 | * The format of returned id and helper limitations are same as in | ||
| 2176 | * **bpf_skb_cgroup_id**\ (). | ||
| 2177 | * Return | ||
| 2178 | * The id is returned or 0 in case the id could not be retrieved. | ||
| 2179 | * | ||
| 2180 | * u64 bpf_get_current_cgroup_id(void) | 2152 | * u64 bpf_get_current_cgroup_id(void) |
| 2181 | * Return | 2153 | * Return |
| 2182 | * A 64-bit integer containing the current cgroup id based | 2154 | * A 64-bit integer containing the current cgroup id based |
| 2183 | * on the cgroup within which the current task is running. | 2155 | * on the cgroup within which the current task is running. |
| 2184 | * | 2156 | * |
| 2185 | * void* get_local_storage(void *map, u64 flags) | 2157 | * void *bpf_get_local_storage(void *map, u64 flags) |
| 2186 | * Description | 2158 | * Description |
| 2187 | * Get the pointer to the local storage area. | 2159 | * Get the pointer to the local storage area. |
| 2188 | * The type and the size of the local storage is defined | 2160 | * The type and the size of the local storage is defined |
| @@ -2209,6 +2181,24 @@ union bpf_attr { | |||
| 2209 | * Return | 2181 | * Return |
| 2210 | * 0 on success, or a negative error in case of failure. | 2182 | * 0 on success, or a negative error in case of failure. |
| 2211 | * | 2183 | * |
| 2184 | * u64 bpf_skb_ancestor_cgroup_id(struct sk_buff *skb, int ancestor_level) | ||
| 2185 | * Description | ||
| 2186 | * Return id of cgroup v2 that is ancestor of cgroup associated | ||
| 2187 | * with the *skb* at the *ancestor_level*. The root cgroup is at | ||
| 2188 | * *ancestor_level* zero and each step down the hierarchy | ||
| 2189 | * increments the level. If *ancestor_level* == level of cgroup | ||
| 2190 | * associated with *skb*, then return value will be same as that | ||
| 2191 | * of **bpf_skb_cgroup_id**\ (). | ||
| 2192 | * | ||
| 2193 | * The helper is useful to implement policies based on cgroups | ||
| 2194 | * that are upper in hierarchy than immediate cgroup associated | ||
| 2195 | * with *skb*. | ||
| 2196 | * | ||
| 2197 | * The format of returned id and helper limitations are same as in | ||
| 2198 | * **bpf_skb_cgroup_id**\ (). | ||
| 2199 | * Return | ||
| 2200 | * The id is returned or 0 in case the id could not be retrieved. | ||
| 2201 | * | ||
| 2212 | * struct bpf_sock *bpf_sk_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags) | 2202 | * struct bpf_sock *bpf_sk_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags) |
| 2213 | * Description | 2203 | * Description |
| 2214 | * Look for TCP socket matching *tuple*, optionally in a child | 2204 | * Look for TCP socket matching *tuple*, optionally in a child |
| @@ -2289,6 +2279,16 @@ union bpf_attr { | |||
| 2289 | * Return | 2279 | * Return |
| 2290 | * 0 on success, or a negative error in case of failure. | 2280 | * 0 on success, or a negative error in case of failure. |
| 2291 | * | 2281 | * |
| 2282 | * int bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags) | ||
| 2283 | * Description | ||
| 2284 | * Push an element *value* in *map*. *flags* is one of: | ||
| 2285 | * | ||
| 2286 | * **BPF_EXIST** | ||
| 2287 | * If the queue/stack is full, the oldest element is | ||
| 2288 | * removed to make room for this. | ||
| 2289 | * Return | ||
| 2290 | * 0 on success, or a negative error in case of failure. | ||
| 2291 | * | ||
| 2292 | * int bpf_map_pop_elem(struct bpf_map *map, void *value) | 2292 | * int bpf_map_pop_elem(struct bpf_map *map, void *value) |
| 2293 | * Description | 2293 | * Description |
| 2294 | * Pop an element from *map*. | 2294 | * Pop an element from *map*. |
| @@ -2343,29 +2343,94 @@ union bpf_attr { | |||
| 2343 | * Return | 2343 | * Return |
| 2344 | * 0 | 2344 | * 0 |
| 2345 | * | 2345 | * |
| 2346 | * int bpf_spin_lock(struct bpf_spin_lock *lock) | ||
| 2347 | * Description | ||
| 2348 | * Acquire a spinlock represented by the pointer *lock*, which is | ||
| 2349 | * stored as part of a value of a map. Taking the lock allows to | ||
| 2350 | * safely update the rest of the fields in that value. The | ||
| 2351 | * spinlock can (and must) later be released with a call to | ||
| 2352 | * **bpf_spin_unlock**\ (\ *lock*\ ). | ||
| 2353 | * | ||
| 2354 | * Spinlocks in BPF programs come with a number of restrictions | ||
| 2355 | * and constraints: | ||
| 2356 | * | ||
| 2357 | * * **bpf_spin_lock** objects are only allowed inside maps of | ||
| 2358 | * types **BPF_MAP_TYPE_HASH** and **BPF_MAP_TYPE_ARRAY** (this | ||
| 2359 | * list could be extended in the future). | ||
| 2360 | * * BTF description of the map is mandatory. | ||
| 2361 | * * The BPF program can take ONE lock at a time, since taking two | ||
| 2362 | * or more could cause dead locks. | ||
| 2363 | * * Only one **struct bpf_spin_lock** is allowed per map element. | ||
| 2364 | * * When the lock is taken, calls (either BPF to BPF or helpers) | ||
| 2365 | * are not allowed. | ||
| 2366 | * * The **BPF_LD_ABS** and **BPF_LD_IND** instructions are not | ||
| 2367 | * allowed inside a spinlock-ed region. | ||
| 2368 | * * The BPF program MUST call **bpf_spin_unlock**\ () to release | ||
| 2369 | * the lock, on all execution paths, before it returns. | ||
| 2370 | * * The BPF program can access **struct bpf_spin_lock** only via | ||
| 2371 | * the **bpf_spin_lock**\ () and **bpf_spin_unlock**\ () | ||
| 2372 | * helpers. Loading or storing data into the **struct | ||
| 2373 | * bpf_spin_lock** *lock*\ **;** field of a map is not allowed. | ||
| 2374 | * * To use the **bpf_spin_lock**\ () helper, the BTF description | ||
| 2375 | * of the map value must be a struct and have **struct | ||
| 2376 | * bpf_spin_lock** *anyname*\ **;** field at the top level. | ||
| 2377 | * Nested lock inside another struct is not allowed. | ||
| 2378 | * * The **struct bpf_spin_lock** *lock* field in a map value must | ||
| 2379 | * be aligned on a multiple of 4 bytes in that value. | ||
| 2380 | * * Syscall with command **BPF_MAP_LOOKUP_ELEM** does not copy | ||
| 2381 | * the **bpf_spin_lock** field to user space. | ||
| 2382 | * * Syscall with command **BPF_MAP_UPDATE_ELEM**, or update from | ||
| 2383 | * a BPF program, do not update the **bpf_spin_lock** field. | ||
| 2384 | * * **bpf_spin_lock** cannot be on the stack or inside a | ||
| 2385 | * networking packet (it can only be inside of a map values). | ||
| 2386 | * * **bpf_spin_lock** is available to root only. | ||
| 2387 | * * Tracing programs and socket filter programs cannot use | ||
| 2388 | * **bpf_spin_lock**\ () due to insufficient preemption checks | ||
| 2389 | * (but this may change in the future). | ||
| 2390 | * * **bpf_spin_lock** is not allowed in inner maps of map-in-map. | ||
| 2391 | * Return | ||
| 2392 | * 0 | ||
| 2393 | * | ||
| 2394 | * int bpf_spin_unlock(struct bpf_spin_lock *lock) | ||
| 2395 | * Description | ||
| 2396 | * Release the *lock* previously locked by a call to | ||
| 2397 | * **bpf_spin_lock**\ (\ *lock*\ ). | ||
| 2398 | * Return | ||
| 2399 | * 0 | ||
| 2400 | * | ||
| 2346 | * struct bpf_sock *bpf_sk_fullsock(struct bpf_sock *sk) | 2401 | * struct bpf_sock *bpf_sk_fullsock(struct bpf_sock *sk) |
| 2347 | * Description | 2402 | * Description |
| 2348 | * This helper gets a **struct bpf_sock** pointer such | 2403 | * This helper gets a **struct bpf_sock** pointer such |
| 2349 | * that all the fields in bpf_sock can be accessed. | 2404 | * that all the fields in this **bpf_sock** can be accessed. |
| 2350 | * Return | 2405 | * Return |
| 2351 | * A **struct bpf_sock** pointer on success, or NULL in | 2406 | * A **struct bpf_sock** pointer on success, or **NULL** in |
| 2352 | * case of failure. | 2407 | * case of failure. |
| 2353 | * | 2408 | * |
| 2354 | * struct bpf_tcp_sock *bpf_tcp_sock(struct bpf_sock *sk) | 2409 | * struct bpf_tcp_sock *bpf_tcp_sock(struct bpf_sock *sk) |
| 2355 | * Description | 2410 | * Description |
| 2356 | * This helper gets a **struct bpf_tcp_sock** pointer from a | 2411 | * This helper gets a **struct bpf_tcp_sock** pointer from a |
| 2357 | * **struct bpf_sock** pointer. | 2412 | * **struct bpf_sock** pointer. |
| 2358 | * | ||
| 2359 | * Return | 2413 | * Return |
| 2360 | * A **struct bpf_tcp_sock** pointer on success, or NULL in | 2414 | * A **struct bpf_tcp_sock** pointer on success, or **NULL** in |
| 2361 | * case of failure. | 2415 | * case of failure. |
| 2362 | * | 2416 | * |
| 2363 | * int bpf_skb_ecn_set_ce(struct sk_buf *skb) | 2417 | * int bpf_skb_ecn_set_ce(struct sk_buf *skb) |
| 2364 | * Description | 2418 | * Description |
| 2365 | * Sets ECN of IP header to ce (congestion encountered) if | 2419 | * Set ECN (Explicit Congestion Notification) field of IP header |
| 2366 | * current value is ect (ECN capable). Works with IPv6 and IPv4. | 2420 | * to **CE** (Congestion Encountered) if current value is **ECT** |
| 2367 | * Return | 2421 | * (ECN Capable Transport). Otherwise, do nothing. Works with IPv6 |
| 2368 | * 1 if set, 0 if not set. | 2422 | * and IPv4. |
| 2423 | * Return | ||
| 2424 | * 1 if the **CE** flag is set (either by the current helper call | ||
| 2425 | * or because it was already present), 0 if it is not set. | ||
| 2426 | * | ||
| 2427 | * struct bpf_sock *bpf_get_listener_sock(struct bpf_sock *sk) | ||
| 2428 | * Description | ||
| 2429 | * Return a **struct bpf_sock** pointer in **TCP_LISTEN** state. | ||
| 2430 | * **bpf_sk_release**\ () is unnecessary and not allowed. | ||
| 2431 | * Return | ||
| 2432 | * A **struct bpf_sock** pointer on success, or **NULL** in | ||
| 2433 | * case of failure. | ||
| 2369 | */ | 2434 | */ |
| 2370 | #define __BPF_FUNC_MAPPER(FN) \ | 2435 | #define __BPF_FUNC_MAPPER(FN) \ |
| 2371 | FN(unspec), \ | 2436 | FN(unspec), \ |
| @@ -2465,7 +2530,8 @@ union bpf_attr { | |||
| 2465 | FN(spin_unlock), \ | 2530 | FN(spin_unlock), \ |
| 2466 | FN(sk_fullsock), \ | 2531 | FN(sk_fullsock), \ |
| 2467 | FN(tcp_sock), \ | 2532 | FN(tcp_sock), \ |
| 2468 | FN(skb_ecn_set_ce), | 2533 | FN(skb_ecn_set_ce), \ |
| 2534 | FN(get_listener_sock), | ||
| 2469 | 2535 | ||
| 2470 | /* integer value in 'imm' field of BPF_CALL instruction selects which helper | 2536 | /* integer value in 'imm' field of BPF_CALL instruction selects which helper |
| 2471 | * function eBPF program intends to call | 2537 | * function eBPF program intends to call |
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile index 61aaacf0cfa1..5bf8e52c41fc 100644 --- a/tools/lib/bpf/Makefile +++ b/tools/lib/bpf/Makefile | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | BPF_VERSION = 0 | 4 | BPF_VERSION = 0 |
| 5 | BPF_PATCHLEVEL = 0 | 5 | BPF_PATCHLEVEL = 0 |
| 6 | BPF_EXTRAVERSION = 1 | 6 | BPF_EXTRAVERSION = 2 |
| 7 | 7 | ||
| 8 | MAKEFLAGS += --no-print-directory | 8 | MAKEFLAGS += --no-print-directory |
| 9 | 9 | ||
| @@ -79,8 +79,6 @@ export prefix libdir src obj | |||
| 79 | libdir_SQ = $(subst ','\'',$(libdir)) | 79 | libdir_SQ = $(subst ','\'',$(libdir)) |
| 80 | libdir_relative_SQ = $(subst ','\'',$(libdir_relative)) | 80 | libdir_relative_SQ = $(subst ','\'',$(libdir_relative)) |
| 81 | 81 | ||
| 82 | LIB_FILE = libbpf.a libbpf.so | ||
| 83 | |||
| 84 | VERSION = $(BPF_VERSION) | 82 | VERSION = $(BPF_VERSION) |
| 85 | PATCHLEVEL = $(BPF_PATCHLEVEL) | 83 | PATCHLEVEL = $(BPF_PATCHLEVEL) |
| 86 | EXTRAVERSION = $(BPF_EXTRAVERSION) | 84 | EXTRAVERSION = $(BPF_EXTRAVERSION) |
| @@ -88,7 +86,10 @@ EXTRAVERSION = $(BPF_EXTRAVERSION) | |||
| 88 | OBJ = $@ | 86 | OBJ = $@ |
| 89 | N = | 87 | N = |
| 90 | 88 | ||
| 91 | LIBBPF_VERSION = $(BPF_VERSION).$(BPF_PATCHLEVEL).$(BPF_EXTRAVERSION) | 89 | LIBBPF_VERSION = $(BPF_VERSION).$(BPF_PATCHLEVEL).$(BPF_EXTRAVERSION) |
| 90 | |||
| 91 | LIB_TARGET = libbpf.a libbpf.so.$(LIBBPF_VERSION) | ||
| 92 | LIB_FILE = libbpf.a libbpf.so* | ||
| 92 | 93 | ||
| 93 | # Set compile option CFLAGS | 94 | # Set compile option CFLAGS |
| 94 | ifdef EXTRA_CFLAGS | 95 | ifdef EXTRA_CFLAGS |
| @@ -128,16 +129,18 @@ all: | |||
| 128 | export srctree OUTPUT CC LD CFLAGS V | 129 | export srctree OUTPUT CC LD CFLAGS V |
| 129 | include $(srctree)/tools/build/Makefile.include | 130 | include $(srctree)/tools/build/Makefile.include |
| 130 | 131 | ||
| 131 | BPF_IN := $(OUTPUT)libbpf-in.o | 132 | BPF_IN := $(OUTPUT)libbpf-in.o |
| 132 | LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE)) | 133 | VERSION_SCRIPT := libbpf.map |
| 133 | VERSION_SCRIPT := libbpf.map | 134 | |
| 135 | LIB_TARGET := $(addprefix $(OUTPUT),$(LIB_TARGET)) | ||
| 136 | LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE)) | ||
| 134 | 137 | ||
| 135 | GLOBAL_SYM_COUNT = $(shell readelf -s --wide $(BPF_IN) | \ | 138 | GLOBAL_SYM_COUNT = $(shell readelf -s --wide $(BPF_IN) | \ |
| 136 | awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {s++} END{print s}') | 139 | awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {s++} END{print s}') |
| 137 | VERSIONED_SYM_COUNT = $(shell readelf -s --wide $(OUTPUT)libbpf.so | \ | 140 | VERSIONED_SYM_COUNT = $(shell readelf -s --wide $(OUTPUT)libbpf.so | \ |
| 138 | grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | sort -u | wc -l) | 141 | grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | sort -u | wc -l) |
| 139 | 142 | ||
| 140 | CMD_TARGETS = $(LIB_FILE) | 143 | CMD_TARGETS = $(LIB_TARGET) |
| 141 | 144 | ||
| 142 | CXX_TEST_TARGET = $(OUTPUT)test_libbpf | 145 | CXX_TEST_TARGET = $(OUTPUT)test_libbpf |
| 143 | 146 | ||
| @@ -170,9 +173,13 @@ $(BPF_IN): force elfdep bpfdep | |||
| 170 | echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/if_xdp.h' differs from latest version at 'include/uapi/linux/if_xdp.h'" >&2 )) || true | 173 | echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/if_xdp.h' differs from latest version at 'include/uapi/linux/if_xdp.h'" >&2 )) || true |
| 171 | $(Q)$(MAKE) $(build)=libbpf | 174 | $(Q)$(MAKE) $(build)=libbpf |
| 172 | 175 | ||
| 173 | $(OUTPUT)libbpf.so: $(BPF_IN) | 176 | $(OUTPUT)libbpf.so: $(OUTPUT)libbpf.so.$(LIBBPF_VERSION) |
| 174 | $(QUIET_LINK)$(CC) --shared -Wl,--version-script=$(VERSION_SCRIPT) \ | 177 | |
| 175 | $^ -o $@ | 178 | $(OUTPUT)libbpf.so.$(LIBBPF_VERSION): $(BPF_IN) |
| 179 | $(QUIET_LINK)$(CC) --shared -Wl,-soname,libbpf.so.$(VERSION) \ | ||
| 180 | -Wl,--version-script=$(VERSION_SCRIPT) $^ -o $@ | ||
| 181 | @ln -sf $(@F) $(OUTPUT)libbpf.so | ||
| 182 | @ln -sf $(@F) $(OUTPUT)libbpf.so.$(VERSION) | ||
| 176 | 183 | ||
| 177 | $(OUTPUT)libbpf.a: $(BPF_IN) | 184 | $(OUTPUT)libbpf.a: $(BPF_IN) |
| 178 | $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ | 185 | $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ |
| @@ -192,6 +199,12 @@ check_abi: $(OUTPUT)libbpf.so | |||
| 192 | exit 1; \ | 199 | exit 1; \ |
| 193 | fi | 200 | fi |
| 194 | 201 | ||
| 202 | define do_install_mkdir | ||
| 203 | if [ ! -d '$(DESTDIR_SQ)$1' ]; then \ | ||
| 204 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$1'; \ | ||
| 205 | fi | ||
| 206 | endef | ||
| 207 | |||
| 195 | define do_install | 208 | define do_install |
| 196 | if [ ! -d '$(DESTDIR_SQ)$2' ]; then \ | 209 | if [ ! -d '$(DESTDIR_SQ)$2' ]; then \ |
| 197 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \ | 210 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \ |
| @@ -200,8 +213,9 @@ define do_install | |||
| 200 | endef | 213 | endef |
| 201 | 214 | ||
| 202 | install_lib: all_cmd | 215 | install_lib: all_cmd |
| 203 | $(call QUIET_INSTALL, $(LIB_FILE)) \ | 216 | $(call QUIET_INSTALL, $(LIB_TARGET)) \ |
| 204 | $(call do_install,$(LIB_FILE),$(libdir_SQ)) | 217 | $(call do_install_mkdir,$(libdir_SQ)); \ |
| 218 | cp -fpR $(LIB_FILE) $(DESTDIR)$(libdir_SQ) | ||
| 205 | 219 | ||
| 206 | install_headers: | 220 | install_headers: |
| 207 | $(call QUIET_INSTALL, headers) \ | 221 | $(call QUIET_INSTALL, headers) \ |
| @@ -219,7 +233,7 @@ config-clean: | |||
| 219 | 233 | ||
| 220 | clean: | 234 | clean: |
| 221 | $(call QUIET_CLEAN, libbpf) $(RM) $(TARGETS) $(CXX_TEST_TARGET) \ | 235 | $(call QUIET_CLEAN, libbpf) $(RM) $(TARGETS) $(CXX_TEST_TARGET) \ |
| 222 | *.o *~ *.a *.so .*.d .*.cmd LIBBPF-CFLAGS | 236 | *.o *~ *.a *.so *.so.$(VERSION) .*.d .*.cmd LIBBPF-CFLAGS |
| 223 | $(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf | 237 | $(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf |
| 224 | 238 | ||
| 225 | 239 | ||
diff --git a/tools/lib/bpf/README.rst b/tools/lib/bpf/README.rst index 5788479384ca..cef7b77eab69 100644 --- a/tools/lib/bpf/README.rst +++ b/tools/lib/bpf/README.rst | |||
| @@ -111,6 +111,7 @@ starting from ``0.0.1``. | |||
| 111 | 111 | ||
| 112 | Every time ABI is being changed, e.g. because a new symbol is added or | 112 | Every time ABI is being changed, e.g. because a new symbol is added or |
| 113 | semantic of existing symbol is changed, ABI version should be bumped. | 113 | semantic of existing symbol is changed, ABI version should be bumped. |
| 114 | This bump in ABI version is at most once per kernel development cycle. | ||
| 114 | 115 | ||
| 115 | For example, if current state of ``libbpf.map`` is: | 116 | For example, if current state of ``libbpf.map`` is: |
| 116 | 117 | ||
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 1b8d8cdd3575..87e3020ac1bc 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c | |||
| @@ -1602,16 +1602,12 @@ static bool btf_equal_int(struct btf_type *t1, struct btf_type *t2) | |||
| 1602 | /* Calculate type signature hash of ENUM. */ | 1602 | /* Calculate type signature hash of ENUM. */ |
| 1603 | static __u32 btf_hash_enum(struct btf_type *t) | 1603 | static __u32 btf_hash_enum(struct btf_type *t) |
| 1604 | { | 1604 | { |
| 1605 | struct btf_enum *member = (struct btf_enum *)(t + 1); | 1605 | __u32 h; |
| 1606 | __u32 vlen = BTF_INFO_VLEN(t->info); | ||
| 1607 | __u32 h = btf_hash_common(t); | ||
| 1608 | int i; | ||
| 1609 | 1606 | ||
| 1610 | for (i = 0; i < vlen; i++) { | 1607 | /* don't hash vlen and enum members to support enum fwd resolving */ |
| 1611 | h = hash_combine(h, member->name_off); | 1608 | h = hash_combine(0, t->name_off); |
| 1612 | h = hash_combine(h, member->val); | 1609 | h = hash_combine(h, t->info & ~0xffff); |
| 1613 | member++; | 1610 | h = hash_combine(h, t->size); |
| 1614 | } | ||
| 1615 | return h; | 1611 | return h; |
| 1616 | } | 1612 | } |
| 1617 | 1613 | ||
| @@ -1637,6 +1633,22 @@ static bool btf_equal_enum(struct btf_type *t1, struct btf_type *t2) | |||
| 1637 | return true; | 1633 | return true; |
| 1638 | } | 1634 | } |
| 1639 | 1635 | ||
| 1636 | static inline bool btf_is_enum_fwd(struct btf_type *t) | ||
| 1637 | { | ||
| 1638 | return BTF_INFO_KIND(t->info) == BTF_KIND_ENUM && | ||
| 1639 | BTF_INFO_VLEN(t->info) == 0; | ||
| 1640 | } | ||
| 1641 | |||
| 1642 | static bool btf_compat_enum(struct btf_type *t1, struct btf_type *t2) | ||
| 1643 | { | ||
| 1644 | if (!btf_is_enum_fwd(t1) && !btf_is_enum_fwd(t2)) | ||
| 1645 | return btf_equal_enum(t1, t2); | ||
| 1646 | /* ignore vlen when comparing */ | ||
| 1647 | return t1->name_off == t2->name_off && | ||
| 1648 | (t1->info & ~0xffff) == (t2->info & ~0xffff) && | ||
| 1649 | t1->size == t2->size; | ||
| 1650 | } | ||
| 1651 | |||
| 1640 | /* | 1652 | /* |
| 1641 | * Calculate type signature hash of STRUCT/UNION, ignoring referenced type IDs, | 1653 | * Calculate type signature hash of STRUCT/UNION, ignoring referenced type IDs, |
| 1642 | * as referenced type IDs equivalence is established separately during type | 1654 | * as referenced type IDs equivalence is established separately during type |
| @@ -1860,6 +1872,17 @@ static int btf_dedup_prim_type(struct btf_dedup *d, __u32 type_id) | |||
| 1860 | new_id = cand_node->type_id; | 1872 | new_id = cand_node->type_id; |
| 1861 | break; | 1873 | break; |
| 1862 | } | 1874 | } |
| 1875 | if (d->opts.dont_resolve_fwds) | ||
| 1876 | continue; | ||
| 1877 | if (btf_compat_enum(t, cand)) { | ||
| 1878 | if (btf_is_enum_fwd(t)) { | ||
| 1879 | /* resolve fwd to full enum */ | ||
| 1880 | new_id = cand_node->type_id; | ||
| 1881 | break; | ||
| 1882 | } | ||
| 1883 | /* resolve canonical enum fwd to full enum */ | ||
| 1884 | d->map[cand_node->type_id] = type_id; | ||
| 1885 | } | ||
| 1863 | } | 1886 | } |
| 1864 | break; | 1887 | break; |
| 1865 | 1888 | ||
| @@ -2084,15 +2107,15 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id, | |||
| 2084 | return fwd_kind == real_kind; | 2107 | return fwd_kind == real_kind; |
| 2085 | } | 2108 | } |
| 2086 | 2109 | ||
| 2087 | if (cand_type->info != canon_type->info) | ||
| 2088 | return 0; | ||
| 2089 | |||
| 2090 | switch (cand_kind) { | 2110 | switch (cand_kind) { |
| 2091 | case BTF_KIND_INT: | 2111 | case BTF_KIND_INT: |
| 2092 | return btf_equal_int(cand_type, canon_type); | 2112 | return btf_equal_int(cand_type, canon_type); |
| 2093 | 2113 | ||
| 2094 | case BTF_KIND_ENUM: | 2114 | case BTF_KIND_ENUM: |
| 2095 | return btf_equal_enum(cand_type, canon_type); | 2115 | if (d->opts.dont_resolve_fwds) |
| 2116 | return btf_equal_enum(cand_type, canon_type); | ||
| 2117 | else | ||
| 2118 | return btf_compat_enum(cand_type, canon_type); | ||
| 2096 | 2119 | ||
| 2097 | case BTF_KIND_FWD: | 2120 | case BTF_KIND_FWD: |
| 2098 | return btf_equal_common(cand_type, canon_type); | 2121 | return btf_equal_common(cand_type, canon_type); |
| @@ -2103,6 +2126,8 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id, | |||
| 2103 | case BTF_KIND_PTR: | 2126 | case BTF_KIND_PTR: |
| 2104 | case BTF_KIND_TYPEDEF: | 2127 | case BTF_KIND_TYPEDEF: |
| 2105 | case BTF_KIND_FUNC: | 2128 | case BTF_KIND_FUNC: |
| 2129 | if (cand_type->info != canon_type->info) | ||
| 2130 | return 0; | ||
| 2106 | return btf_dedup_is_equiv(d, cand_type->type, canon_type->type); | 2131 | return btf_dedup_is_equiv(d, cand_type->type, canon_type->type); |
| 2107 | 2132 | ||
| 2108 | case BTF_KIND_ARRAY: { | 2133 | case BTF_KIND_ARRAY: { |
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index e6ad87512519..11c25d9ea431 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
| @@ -840,12 +840,19 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags) | |||
| 840 | obj->efile.maps_shndx = idx; | 840 | obj->efile.maps_shndx = idx; |
| 841 | else if (strcmp(name, BTF_ELF_SEC) == 0) { | 841 | else if (strcmp(name, BTF_ELF_SEC) == 0) { |
| 842 | obj->btf = btf__new(data->d_buf, data->d_size); | 842 | obj->btf = btf__new(data->d_buf, data->d_size); |
| 843 | if (IS_ERR(obj->btf) || btf__load(obj->btf)) { | 843 | if (IS_ERR(obj->btf)) { |
| 844 | pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n", | 844 | pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n", |
| 845 | BTF_ELF_SEC, PTR_ERR(obj->btf)); | 845 | BTF_ELF_SEC, PTR_ERR(obj->btf)); |
| 846 | if (!IS_ERR(obj->btf)) | ||
| 847 | btf__free(obj->btf); | ||
| 848 | obj->btf = NULL; | 846 | obj->btf = NULL; |
| 847 | continue; | ||
| 848 | } | ||
| 849 | err = btf__load(obj->btf); | ||
| 850 | if (err) { | ||
| 851 | pr_warning("Error loading %s into kernel: %d. Ignored and continue.\n", | ||
| 852 | BTF_ELF_SEC, err); | ||
| 853 | btf__free(obj->btf); | ||
| 854 | obj->btf = NULL; | ||
| 855 | err = 0; | ||
| 849 | } | 856 | } |
| 850 | } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) { | 857 | } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) { |
| 851 | btf_ext_data = data; | 858 | btf_ext_data = data; |
diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c index f98ac82c9aea..8d0078b65486 100644 --- a/tools/lib/bpf/xsk.c +++ b/tools/lib/bpf/xsk.c | |||
| @@ -126,8 +126,8 @@ static void xsk_set_umem_config(struct xsk_umem_config *cfg, | |||
| 126 | cfg->frame_headroom = usr_cfg->frame_headroom; | 126 | cfg->frame_headroom = usr_cfg->frame_headroom; |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | static void xsk_set_xdp_socket_config(struct xsk_socket_config *cfg, | 129 | static int xsk_set_xdp_socket_config(struct xsk_socket_config *cfg, |
| 130 | const struct xsk_socket_config *usr_cfg) | 130 | const struct xsk_socket_config *usr_cfg) |
| 131 | { | 131 | { |
| 132 | if (!usr_cfg) { | 132 | if (!usr_cfg) { |
| 133 | cfg->rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS; | 133 | cfg->rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS; |
| @@ -135,14 +135,19 @@ static void xsk_set_xdp_socket_config(struct xsk_socket_config *cfg, | |||
| 135 | cfg->libbpf_flags = 0; | 135 | cfg->libbpf_flags = 0; |
| 136 | cfg->xdp_flags = 0; | 136 | cfg->xdp_flags = 0; |
| 137 | cfg->bind_flags = 0; | 137 | cfg->bind_flags = 0; |
| 138 | return; | 138 | return 0; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | if (usr_cfg->libbpf_flags & ~XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD) | ||
| 142 | return -EINVAL; | ||
| 143 | |||
| 141 | cfg->rx_size = usr_cfg->rx_size; | 144 | cfg->rx_size = usr_cfg->rx_size; |
| 142 | cfg->tx_size = usr_cfg->tx_size; | 145 | cfg->tx_size = usr_cfg->tx_size; |
| 143 | cfg->libbpf_flags = usr_cfg->libbpf_flags; | 146 | cfg->libbpf_flags = usr_cfg->libbpf_flags; |
| 144 | cfg->xdp_flags = usr_cfg->xdp_flags; | 147 | cfg->xdp_flags = usr_cfg->xdp_flags; |
| 145 | cfg->bind_flags = usr_cfg->bind_flags; | 148 | cfg->bind_flags = usr_cfg->bind_flags; |
| 149 | |||
| 150 | return 0; | ||
| 146 | } | 151 | } |
| 147 | 152 | ||
| 148 | int xsk_umem__create(struct xsk_umem **umem_ptr, void *umem_area, __u64 size, | 153 | int xsk_umem__create(struct xsk_umem **umem_ptr, void *umem_area, __u64 size, |
| @@ -557,7 +562,9 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname, | |||
| 557 | } | 562 | } |
| 558 | strncpy(xsk->ifname, ifname, IFNAMSIZ); | 563 | strncpy(xsk->ifname, ifname, IFNAMSIZ); |
| 559 | 564 | ||
| 560 | xsk_set_xdp_socket_config(&xsk->config, usr_config); | 565 | err = xsk_set_xdp_socket_config(&xsk->config, usr_config); |
| 566 | if (err) | ||
| 567 | goto out_socket; | ||
| 561 | 568 | ||
| 562 | if (rx) { | 569 | if (rx) { |
| 563 | err = setsockopt(xsk->fd, SOL_XDP, XDP_RX_RING, | 570 | err = setsockopt(xsk->fd, SOL_XDP, XDP_RX_RING, |
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index c9433a496d54..c81fc350f7ad 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h | |||
| @@ -180,6 +180,8 @@ static struct bpf_sock *(*bpf_sk_fullsock)(struct bpf_sock *sk) = | |||
| 180 | (void *) BPF_FUNC_sk_fullsock; | 180 | (void *) BPF_FUNC_sk_fullsock; |
| 181 | static struct bpf_tcp_sock *(*bpf_tcp_sock)(struct bpf_sock *sk) = | 181 | static struct bpf_tcp_sock *(*bpf_tcp_sock)(struct bpf_sock *sk) = |
| 182 | (void *) BPF_FUNC_tcp_sock; | 182 | (void *) BPF_FUNC_tcp_sock; |
| 183 | static struct bpf_sock *(*bpf_get_listener_sock)(struct bpf_sock *sk) = | ||
| 184 | (void *) BPF_FUNC_get_listener_sock; | ||
| 183 | static int (*bpf_skb_ecn_set_ce)(void *ctx) = | 185 | static int (*bpf_skb_ecn_set_ce)(void *ctx) = |
| 184 | (void *) BPF_FUNC_skb_ecn_set_ce; | 186 | (void *) BPF_FUNC_skb_ecn_set_ce; |
| 185 | 187 | ||
diff --git a/tools/testing/selftests/bpf/prog_tests/map_lock.c b/tools/testing/selftests/bpf/prog_tests/map_lock.c index 90f8a206340a..ee99368c595c 100644 --- a/tools/testing/selftests/bpf/prog_tests/map_lock.c +++ b/tools/testing/selftests/bpf/prog_tests/map_lock.c | |||
| @@ -37,7 +37,7 @@ void test_map_lock(void) | |||
| 37 | const char *file = "./test_map_lock.o"; | 37 | const char *file = "./test_map_lock.o"; |
| 38 | int prog_fd, map_fd[2], vars[17] = {}; | 38 | int prog_fd, map_fd[2], vars[17] = {}; |
| 39 | pthread_t thread_id[6]; | 39 | pthread_t thread_id[6]; |
| 40 | struct bpf_object *obj; | 40 | struct bpf_object *obj = NULL; |
| 41 | int err = 0, key = 0, i; | 41 | int err = 0, key = 0, i; |
| 42 | void *ret; | 42 | void *ret; |
| 43 | 43 | ||
diff --git a/tools/testing/selftests/bpf/prog_tests/spinlock.c b/tools/testing/selftests/bpf/prog_tests/spinlock.c index 9a573a9675d7..114ebe6a438e 100644 --- a/tools/testing/selftests/bpf/prog_tests/spinlock.c +++ b/tools/testing/selftests/bpf/prog_tests/spinlock.c | |||
| @@ -5,7 +5,7 @@ void test_spinlock(void) | |||
| 5 | { | 5 | { |
| 6 | const char *file = "./test_spin_lock.o"; | 6 | const char *file = "./test_spin_lock.o"; |
| 7 | pthread_t thread_id[4]; | 7 | pthread_t thread_id[4]; |
| 8 | struct bpf_object *obj; | 8 | struct bpf_object *obj = NULL; |
| 9 | int prog_fd; | 9 | int prog_fd; |
| 10 | int err = 0, i; | 10 | int err = 0, i; |
| 11 | void *ret; | 11 | void *ret; |
diff --git a/tools/testing/selftests/bpf/progs/test_sock_fields_kern.c b/tools/testing/selftests/bpf/progs/test_sock_fields_kern.c index de1a43e8f610..37328f148538 100644 --- a/tools/testing/selftests/bpf/progs/test_sock_fields_kern.c +++ b/tools/testing/selftests/bpf/progs/test_sock_fields_kern.c | |||
| @@ -8,38 +8,51 @@ | |||
| 8 | #include "bpf_helpers.h" | 8 | #include "bpf_helpers.h" |
| 9 | #include "bpf_endian.h" | 9 | #include "bpf_endian.h" |
| 10 | 10 | ||
| 11 | enum bpf_array_idx { | 11 | enum bpf_addr_array_idx { |
| 12 | SRV_IDX, | 12 | ADDR_SRV_IDX, |
| 13 | CLI_IDX, | 13 | ADDR_CLI_IDX, |
| 14 | __NR_BPF_ARRAY_IDX, | 14 | __NR_BPF_ADDR_ARRAY_IDX, |
| 15 | }; | ||
| 16 | |||
| 17 | enum bpf_result_array_idx { | ||
| 18 | EGRESS_SRV_IDX, | ||
| 19 | EGRESS_CLI_IDX, | ||
| 20 | INGRESS_LISTEN_IDX, | ||
| 21 | __NR_BPF_RESULT_ARRAY_IDX, | ||
| 22 | }; | ||
| 23 | |||
| 24 | enum bpf_linum_array_idx { | ||
| 25 | EGRESS_LINUM_IDX, | ||
| 26 | INGRESS_LINUM_IDX, | ||
| 27 | __NR_BPF_LINUM_ARRAY_IDX, | ||
| 15 | }; | 28 | }; |
| 16 | 29 | ||
| 17 | struct bpf_map_def SEC("maps") addr_map = { | 30 | struct bpf_map_def SEC("maps") addr_map = { |
| 18 | .type = BPF_MAP_TYPE_ARRAY, | 31 | .type = BPF_MAP_TYPE_ARRAY, |
| 19 | .key_size = sizeof(__u32), | 32 | .key_size = sizeof(__u32), |
| 20 | .value_size = sizeof(struct sockaddr_in6), | 33 | .value_size = sizeof(struct sockaddr_in6), |
| 21 | .max_entries = __NR_BPF_ARRAY_IDX, | 34 | .max_entries = __NR_BPF_ADDR_ARRAY_IDX, |
| 22 | }; | 35 | }; |
| 23 | 36 | ||
| 24 | struct bpf_map_def SEC("maps") sock_result_map = { | 37 | struct bpf_map_def SEC("maps") sock_result_map = { |
| 25 | .type = BPF_MAP_TYPE_ARRAY, | 38 | .type = BPF_MAP_TYPE_ARRAY, |
| 26 | .key_size = sizeof(__u32), | 39 | .key_size = sizeof(__u32), |
| 27 | .value_size = sizeof(struct bpf_sock), | 40 | .value_size = sizeof(struct bpf_sock), |
| 28 | .max_entries = __NR_BPF_ARRAY_IDX, | 41 | .max_entries = __NR_BPF_RESULT_ARRAY_IDX, |
| 29 | }; | 42 | }; |
| 30 | 43 | ||
| 31 | struct bpf_map_def SEC("maps") tcp_sock_result_map = { | 44 | struct bpf_map_def SEC("maps") tcp_sock_result_map = { |
| 32 | .type = BPF_MAP_TYPE_ARRAY, | 45 | .type = BPF_MAP_TYPE_ARRAY, |
| 33 | .key_size = sizeof(__u32), | 46 | .key_size = sizeof(__u32), |
| 34 | .value_size = sizeof(struct bpf_tcp_sock), | 47 | .value_size = sizeof(struct bpf_tcp_sock), |
| 35 | .max_entries = __NR_BPF_ARRAY_IDX, | 48 | .max_entries = __NR_BPF_RESULT_ARRAY_IDX, |
| 36 | }; | 49 | }; |
| 37 | 50 | ||
| 38 | struct bpf_map_def SEC("maps") linum_map = { | 51 | struct bpf_map_def SEC("maps") linum_map = { |
| 39 | .type = BPF_MAP_TYPE_ARRAY, | 52 | .type = BPF_MAP_TYPE_ARRAY, |
| 40 | .key_size = sizeof(__u32), | 53 | .key_size = sizeof(__u32), |
| 41 | .value_size = sizeof(__u32), | 54 | .value_size = sizeof(__u32), |
| 42 | .max_entries = 1, | 55 | .max_entries = __NR_BPF_LINUM_ARRAY_IDX, |
| 43 | }; | 56 | }; |
| 44 | 57 | ||
| 45 | static bool is_loopback6(__u32 *a6) | 58 | static bool is_loopback6(__u32 *a6) |
| @@ -100,18 +113,20 @@ static void tpcpy(struct bpf_tcp_sock *dst, | |||
| 100 | 113 | ||
| 101 | #define RETURN { \ | 114 | #define RETURN { \ |
| 102 | linum = __LINE__; \ | 115 | linum = __LINE__; \ |
| 103 | bpf_map_update_elem(&linum_map, &idx0, &linum, 0); \ | 116 | bpf_map_update_elem(&linum_map, &linum_idx, &linum, 0); \ |
| 104 | return 1; \ | 117 | return 1; \ |
| 105 | } | 118 | } |
| 106 | 119 | ||
| 107 | SEC("cgroup_skb/egress") | 120 | SEC("cgroup_skb/egress") |
| 108 | int read_sock_fields(struct __sk_buff *skb) | 121 | int egress_read_sock_fields(struct __sk_buff *skb) |
| 109 | { | 122 | { |
| 110 | __u32 srv_idx = SRV_IDX, cli_idx = CLI_IDX, idx; | 123 | __u32 srv_idx = ADDR_SRV_IDX, cli_idx = ADDR_CLI_IDX, result_idx; |
| 111 | struct sockaddr_in6 *srv_sa6, *cli_sa6; | 124 | struct sockaddr_in6 *srv_sa6, *cli_sa6; |
| 112 | struct bpf_tcp_sock *tp, *tp_ret; | 125 | struct bpf_tcp_sock *tp, *tp_ret; |
| 113 | struct bpf_sock *sk, *sk_ret; | 126 | struct bpf_sock *sk, *sk_ret; |
| 114 | __u32 linum, idx0 = 0; | 127 | __u32 linum, linum_idx; |
| 128 | |||
| 129 | linum_idx = EGRESS_LINUM_IDX; | ||
| 115 | 130 | ||
| 116 | sk = skb->sk; | 131 | sk = skb->sk; |
| 117 | if (!sk || sk->state == 10) | 132 | if (!sk || sk->state == 10) |
| @@ -132,14 +147,55 @@ int read_sock_fields(struct __sk_buff *skb) | |||
| 132 | RETURN; | 147 | RETURN; |
| 133 | 148 | ||
| 134 | if (sk->src_port == bpf_ntohs(srv_sa6->sin6_port)) | 149 | if (sk->src_port == bpf_ntohs(srv_sa6->sin6_port)) |
| 135 | idx = srv_idx; | 150 | result_idx = EGRESS_SRV_IDX; |
| 136 | else if (sk->src_port == bpf_ntohs(cli_sa6->sin6_port)) | 151 | else if (sk->src_port == bpf_ntohs(cli_sa6->sin6_port)) |
| 137 | idx = cli_idx; | 152 | result_idx = EGRESS_CLI_IDX; |
| 138 | else | 153 | else |
| 139 | RETURN; | 154 | RETURN; |
| 140 | 155 | ||
| 141 | sk_ret = bpf_map_lookup_elem(&sock_result_map, &idx); | 156 | sk_ret = bpf_map_lookup_elem(&sock_result_map, &result_idx); |
| 142 | tp_ret = bpf_map_lookup_elem(&tcp_sock_result_map, &idx); | 157 | tp_ret = bpf_map_lookup_elem(&tcp_sock_result_map, &result_idx); |
| 158 | if (!sk_ret || !tp_ret) | ||
| 159 | RETURN; | ||
| 160 | |||
| 161 | skcpy(sk_ret, sk); | ||
| 162 | tpcpy(tp_ret, tp); | ||
| 163 | |||
| 164 | RETURN; | ||
| 165 | } | ||
| 166 | |||
| 167 | SEC("cgroup_skb/ingress") | ||
| 168 | int ingress_read_sock_fields(struct __sk_buff *skb) | ||
| 169 | { | ||
| 170 | __u32 srv_idx = ADDR_SRV_IDX, result_idx = INGRESS_LISTEN_IDX; | ||
| 171 | struct bpf_tcp_sock *tp, *tp_ret; | ||
| 172 | struct bpf_sock *sk, *sk_ret; | ||
| 173 | struct sockaddr_in6 *srv_sa6; | ||
| 174 | __u32 linum, linum_idx; | ||
| 175 | |||
| 176 | linum_idx = INGRESS_LINUM_IDX; | ||
| 177 | |||
| 178 | sk = skb->sk; | ||
| 179 | if (!sk || sk->family != AF_INET6 || !is_loopback6(sk->src_ip6)) | ||
| 180 | RETURN; | ||
| 181 | |||
| 182 | srv_sa6 = bpf_map_lookup_elem(&addr_map, &srv_idx); | ||
| 183 | if (!srv_sa6 || sk->src_port != bpf_ntohs(srv_sa6->sin6_port)) | ||
| 184 | RETURN; | ||
| 185 | |||
| 186 | if (sk->state != 10 && sk->state != 12) | ||
| 187 | RETURN; | ||
| 188 | |||
| 189 | sk = bpf_get_listener_sock(sk); | ||
| 190 | if (!sk) | ||
| 191 | RETURN; | ||
| 192 | |||
| 193 | tp = bpf_tcp_sock(sk); | ||
| 194 | if (!tp) | ||
| 195 | RETURN; | ||
| 196 | |||
| 197 | sk_ret = bpf_map_lookup_elem(&sock_result_map, &result_idx); | ||
| 198 | tp_ret = bpf_map_lookup_elem(&tcp_sock_result_map, &result_idx); | ||
| 143 | if (!sk_ret || !tp_ret) | 199 | if (!sk_ret || !tp_ret) |
| 144 | RETURN; | 200 | RETURN; |
| 145 | 201 | ||
diff --git a/tools/testing/selftests/bpf/test_btf.c b/tools/testing/selftests/bpf/test_btf.c index 38797aa627a7..23e3b314ca60 100644 --- a/tools/testing/selftests/bpf/test_btf.c +++ b/tools/testing/selftests/bpf/test_btf.c | |||
| @@ -5874,6 +5874,50 @@ const struct btf_dedup_test dedup_tests[] = { | |||
| 5874 | .dont_resolve_fwds = false, | 5874 | .dont_resolve_fwds = false, |
| 5875 | }, | 5875 | }, |
| 5876 | }, | 5876 | }, |
| 5877 | { | ||
| 5878 | .descr = "dedup: enum fwd resolution", | ||
| 5879 | .input = { | ||
| 5880 | .raw_types = { | ||
| 5881 | /* [1] fwd enum 'e1' before full enum */ | ||
| 5882 | BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 0), 4), | ||
| 5883 | /* [2] full enum 'e1' after fwd */ | ||
| 5884 | BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4), | ||
| 5885 | BTF_ENUM_ENC(NAME_NTH(2), 123), | ||
| 5886 | /* [3] full enum 'e2' before fwd */ | ||
| 5887 | BTF_TYPE_ENC(NAME_NTH(3), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4), | ||
| 5888 | BTF_ENUM_ENC(NAME_NTH(4), 456), | ||
| 5889 | /* [4] fwd enum 'e2' after full enum */ | ||
| 5890 | BTF_TYPE_ENC(NAME_NTH(3), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 0), 4), | ||
| 5891 | /* [5] incompatible fwd enum with different size */ | ||
| 5892 | BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 0), 1), | ||
| 5893 | /* [6] incompatible full enum with different value */ | ||
| 5894 | BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4), | ||
| 5895 | BTF_ENUM_ENC(NAME_NTH(2), 321), | ||
| 5896 | BTF_END_RAW, | ||
| 5897 | }, | ||
| 5898 | BTF_STR_SEC("\0e1\0e1_val\0e2\0e2_val"), | ||
| 5899 | }, | ||
| 5900 | .expect = { | ||
| 5901 | .raw_types = { | ||
| 5902 | /* [1] full enum 'e1' */ | ||
| 5903 | BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4), | ||
| 5904 | BTF_ENUM_ENC(NAME_NTH(2), 123), | ||
| 5905 | /* [2] full enum 'e2' */ | ||
| 5906 | BTF_TYPE_ENC(NAME_NTH(3), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4), | ||
| 5907 | BTF_ENUM_ENC(NAME_NTH(4), 456), | ||
| 5908 | /* [3] incompatible fwd enum with different size */ | ||
| 5909 | BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 0), 1), | ||
| 5910 | /* [4] incompatible full enum with different value */ | ||
| 5911 | BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4), | ||
| 5912 | BTF_ENUM_ENC(NAME_NTH(2), 321), | ||
| 5913 | BTF_END_RAW, | ||
| 5914 | }, | ||
| 5915 | BTF_STR_SEC("\0e1\0e1_val\0e2\0e2_val"), | ||
| 5916 | }, | ||
| 5917 | .opts = { | ||
| 5918 | .dont_resolve_fwds = false, | ||
| 5919 | }, | ||
| 5920 | }, | ||
| 5877 | 5921 | ||
| 5878 | }; | 5922 | }; |
| 5879 | 5923 | ||
diff --git a/tools/testing/selftests/bpf/test_sock_fields.c b/tools/testing/selftests/bpf/test_sock_fields.c index bc8943938bf5..dcae7f664dce 100644 --- a/tools/testing/selftests/bpf/test_sock_fields.c +++ b/tools/testing/selftests/bpf/test_sock_fields.c | |||
| @@ -16,10 +16,23 @@ | |||
| 16 | #include "cgroup_helpers.h" | 16 | #include "cgroup_helpers.h" |
| 17 | #include "bpf_rlimit.h" | 17 | #include "bpf_rlimit.h" |
| 18 | 18 | ||
| 19 | enum bpf_array_idx { | 19 | enum bpf_addr_array_idx { |
| 20 | SRV_IDX, | 20 | ADDR_SRV_IDX, |
| 21 | CLI_IDX, | 21 | ADDR_CLI_IDX, |
| 22 | __NR_BPF_ARRAY_IDX, | 22 | __NR_BPF_ADDR_ARRAY_IDX, |
| 23 | }; | ||
| 24 | |||
| 25 | enum bpf_result_array_idx { | ||
| 26 | EGRESS_SRV_IDX, | ||
| 27 | EGRESS_CLI_IDX, | ||
| 28 | INGRESS_LISTEN_IDX, | ||
| 29 | __NR_BPF_RESULT_ARRAY_IDX, | ||
| 30 | }; | ||
| 31 | |||
| 32 | enum bpf_linum_array_idx { | ||
| 33 | EGRESS_LINUM_IDX, | ||
| 34 | INGRESS_LINUM_IDX, | ||
| 35 | __NR_BPF_LINUM_ARRAY_IDX, | ||
| 23 | }; | 36 | }; |
| 24 | 37 | ||
| 25 | #define CHECK(condition, tag, format...) ({ \ | 38 | #define CHECK(condition, tag, format...) ({ \ |
| @@ -41,8 +54,16 @@ static int linum_map_fd; | |||
| 41 | static int addr_map_fd; | 54 | static int addr_map_fd; |
| 42 | static int tp_map_fd; | 55 | static int tp_map_fd; |
| 43 | static int sk_map_fd; | 56 | static int sk_map_fd; |
| 44 | static __u32 srv_idx = SRV_IDX; | 57 | |
| 45 | static __u32 cli_idx = CLI_IDX; | 58 | static __u32 addr_srv_idx = ADDR_SRV_IDX; |
| 59 | static __u32 addr_cli_idx = ADDR_CLI_IDX; | ||
| 60 | |||
| 61 | static __u32 egress_srv_idx = EGRESS_SRV_IDX; | ||
| 62 | static __u32 egress_cli_idx = EGRESS_CLI_IDX; | ||
| 63 | static __u32 ingress_listen_idx = INGRESS_LISTEN_IDX; | ||
| 64 | |||
| 65 | static __u32 egress_linum_idx = EGRESS_LINUM_IDX; | ||
| 66 | static __u32 ingress_linum_idx = INGRESS_LINUM_IDX; | ||
| 46 | 67 | ||
| 47 | static void init_loopback6(struct sockaddr_in6 *sa6) | 68 | static void init_loopback6(struct sockaddr_in6 *sa6) |
| 48 | { | 69 | { |
| @@ -93,29 +114,46 @@ static void print_tp(const struct bpf_tcp_sock *tp) | |||
| 93 | 114 | ||
| 94 | static void check_result(void) | 115 | static void check_result(void) |
| 95 | { | 116 | { |
| 96 | struct bpf_tcp_sock srv_tp, cli_tp; | 117 | struct bpf_tcp_sock srv_tp, cli_tp, listen_tp; |
| 97 | struct bpf_sock srv_sk, cli_sk; | 118 | struct bpf_sock srv_sk, cli_sk, listen_sk; |
| 98 | __u32 linum, idx0 = 0; | 119 | __u32 ingress_linum, egress_linum; |
| 99 | int err; | 120 | int err; |
| 100 | 121 | ||
| 101 | err = bpf_map_lookup_elem(linum_map_fd, &idx0, &linum); | 122 | err = bpf_map_lookup_elem(linum_map_fd, &egress_linum_idx, |
| 123 | &egress_linum); | ||
| 102 | CHECK(err == -1, "bpf_map_lookup_elem(linum_map_fd)", | 124 | CHECK(err == -1, "bpf_map_lookup_elem(linum_map_fd)", |
| 103 | "err:%d errno:%d", err, errno); | 125 | "err:%d errno:%d", err, errno); |
| 104 | 126 | ||
| 105 | err = bpf_map_lookup_elem(sk_map_fd, &srv_idx, &srv_sk); | 127 | err = bpf_map_lookup_elem(linum_map_fd, &ingress_linum_idx, |
| 106 | CHECK(err == -1, "bpf_map_lookup_elem(sk_map_fd, &srv_idx)", | 128 | &ingress_linum); |
| 129 | CHECK(err == -1, "bpf_map_lookup_elem(linum_map_fd)", | ||
| 130 | "err:%d errno:%d", err, errno); | ||
| 131 | |||
| 132 | err = bpf_map_lookup_elem(sk_map_fd, &egress_srv_idx, &srv_sk); | ||
| 133 | CHECK(err == -1, "bpf_map_lookup_elem(sk_map_fd, &egress_srv_idx)", | ||
| 134 | "err:%d errno:%d", err, errno); | ||
| 135 | err = bpf_map_lookup_elem(tp_map_fd, &egress_srv_idx, &srv_tp); | ||
| 136 | CHECK(err == -1, "bpf_map_lookup_elem(tp_map_fd, &egress_srv_idx)", | ||
| 137 | "err:%d errno:%d", err, errno); | ||
| 138 | |||
| 139 | err = bpf_map_lookup_elem(sk_map_fd, &egress_cli_idx, &cli_sk); | ||
| 140 | CHECK(err == -1, "bpf_map_lookup_elem(sk_map_fd, &egress_cli_idx)", | ||
| 107 | "err:%d errno:%d", err, errno); | 141 | "err:%d errno:%d", err, errno); |
| 108 | err = bpf_map_lookup_elem(tp_map_fd, &srv_idx, &srv_tp); | 142 | err = bpf_map_lookup_elem(tp_map_fd, &egress_cli_idx, &cli_tp); |
| 109 | CHECK(err == -1, "bpf_map_lookup_elem(tp_map_fd, &srv_idx)", | 143 | CHECK(err == -1, "bpf_map_lookup_elem(tp_map_fd, &egress_cli_idx)", |
| 110 | "err:%d errno:%d", err, errno); | 144 | "err:%d errno:%d", err, errno); |
| 111 | 145 | ||
| 112 | err = bpf_map_lookup_elem(sk_map_fd, &cli_idx, &cli_sk); | 146 | err = bpf_map_lookup_elem(sk_map_fd, &ingress_listen_idx, &listen_sk); |
| 113 | CHECK(err == -1, "bpf_map_lookup_elem(sk_map_fd, &cli_idx)", | 147 | CHECK(err == -1, "bpf_map_lookup_elem(sk_map_fd, &ingress_listen_idx)", |
| 114 | "err:%d errno:%d", err, errno); | 148 | "err:%d errno:%d", err, errno); |
| 115 | err = bpf_map_lookup_elem(tp_map_fd, &cli_idx, &cli_tp); | 149 | err = bpf_map_lookup_elem(tp_map_fd, &ingress_listen_idx, &listen_tp); |
| 116 | CHECK(err == -1, "bpf_map_lookup_elem(tp_map_fd, &cli_idx)", | 150 | CHECK(err == -1, "bpf_map_lookup_elem(tp_map_fd, &ingress_listen_idx)", |
| 117 | "err:%d errno:%d", err, errno); | 151 | "err:%d errno:%d", err, errno); |
| 118 | 152 | ||
| 153 | printf("listen_sk: "); | ||
| 154 | print_sk(&listen_sk); | ||
| 155 | printf("\n"); | ||
| 156 | |||
| 119 | printf("srv_sk: "); | 157 | printf("srv_sk: "); |
| 120 | print_sk(&srv_sk); | 158 | print_sk(&srv_sk); |
| 121 | printf("\n"); | 159 | printf("\n"); |
| @@ -124,6 +162,10 @@ static void check_result(void) | |||
| 124 | print_sk(&cli_sk); | 162 | print_sk(&cli_sk); |
| 125 | printf("\n"); | 163 | printf("\n"); |
| 126 | 164 | ||
| 165 | printf("listen_tp: "); | ||
| 166 | print_tp(&listen_tp); | ||
| 167 | printf("\n"); | ||
| 168 | |||
| 127 | printf("srv_tp: "); | 169 | printf("srv_tp: "); |
| 128 | print_tp(&srv_tp); | 170 | print_tp(&srv_tp); |
| 129 | printf("\n"); | 171 | printf("\n"); |
| @@ -132,6 +174,19 @@ static void check_result(void) | |||
| 132 | print_tp(&cli_tp); | 174 | print_tp(&cli_tp); |
| 133 | printf("\n"); | 175 | printf("\n"); |
| 134 | 176 | ||
| 177 | CHECK(listen_sk.state != 10 || | ||
| 178 | listen_sk.family != AF_INET6 || | ||
| 179 | listen_sk.protocol != IPPROTO_TCP || | ||
| 180 | memcmp(listen_sk.src_ip6, &in6addr_loopback, | ||
| 181 | sizeof(listen_sk.src_ip6)) || | ||
| 182 | listen_sk.dst_ip6[0] || listen_sk.dst_ip6[1] || | ||
| 183 | listen_sk.dst_ip6[2] || listen_sk.dst_ip6[3] || | ||
| 184 | listen_sk.src_port != ntohs(srv_sa6.sin6_port) || | ||
| 185 | listen_sk.dst_port, | ||
| 186 | "Unexpected listen_sk", | ||
| 187 | "Check listen_sk output. ingress_linum:%u", | ||
| 188 | ingress_linum); | ||
| 189 | |||
| 135 | CHECK(srv_sk.state == 10 || | 190 | CHECK(srv_sk.state == 10 || |
| 136 | !srv_sk.state || | 191 | !srv_sk.state || |
| 137 | srv_sk.family != AF_INET6 || | 192 | srv_sk.family != AF_INET6 || |
| @@ -142,7 +197,8 @@ static void check_result(void) | |||
| 142 | sizeof(srv_sk.dst_ip6)) || | 197 | sizeof(srv_sk.dst_ip6)) || |
| 143 | srv_sk.src_port != ntohs(srv_sa6.sin6_port) || | 198 | srv_sk.src_port != ntohs(srv_sa6.sin6_port) || |
| 144 | srv_sk.dst_port != cli_sa6.sin6_port, | 199 | srv_sk.dst_port != cli_sa6.sin6_port, |
| 145 | "Unexpected srv_sk", "Check srv_sk output. linum:%u", linum); | 200 | "Unexpected srv_sk", "Check srv_sk output. egress_linum:%u", |
| 201 | egress_linum); | ||
| 146 | 202 | ||
| 147 | CHECK(cli_sk.state == 10 || | 203 | CHECK(cli_sk.state == 10 || |
| 148 | !cli_sk.state || | 204 | !cli_sk.state || |
| @@ -154,21 +210,31 @@ static void check_result(void) | |||
| 154 | sizeof(cli_sk.dst_ip6)) || | 210 | sizeof(cli_sk.dst_ip6)) || |
| 155 | cli_sk.src_port != ntohs(cli_sa6.sin6_port) || | 211 | cli_sk.src_port != ntohs(cli_sa6.sin6_port) || |
| 156 | cli_sk.dst_port != srv_sa6.sin6_port, | 212 | cli_sk.dst_port != srv_sa6.sin6_port, |
| 157 | "Unexpected cli_sk", "Check cli_sk output. linum:%u", linum); | 213 | "Unexpected cli_sk", "Check cli_sk output. egress_linum:%u", |
| 214 | egress_linum); | ||
| 215 | |||
| 216 | CHECK(listen_tp.data_segs_out || | ||
| 217 | listen_tp.data_segs_in || | ||
| 218 | listen_tp.total_retrans || | ||
| 219 | listen_tp.bytes_acked, | ||
| 220 | "Unexpected listen_tp", "Check listen_tp output. ingress_linum:%u", | ||
| 221 | ingress_linum); | ||
| 158 | 222 | ||
| 159 | CHECK(srv_tp.data_segs_out != 1 || | 223 | CHECK(srv_tp.data_segs_out != 1 || |
| 160 | srv_tp.data_segs_in || | 224 | srv_tp.data_segs_in || |
| 161 | srv_tp.snd_cwnd != 10 || | 225 | srv_tp.snd_cwnd != 10 || |
| 162 | srv_tp.total_retrans || | 226 | srv_tp.total_retrans || |
| 163 | srv_tp.bytes_acked != DATA_LEN, | 227 | srv_tp.bytes_acked != DATA_LEN, |
| 164 | "Unexpected srv_tp", "Check srv_tp output. linum:%u", linum); | 228 | "Unexpected srv_tp", "Check srv_tp output. egress_linum:%u", |
| 229 | egress_linum); | ||
| 165 | 230 | ||
| 166 | CHECK(cli_tp.data_segs_out || | 231 | CHECK(cli_tp.data_segs_out || |
| 167 | cli_tp.data_segs_in != 1 || | 232 | cli_tp.data_segs_in != 1 || |
| 168 | cli_tp.snd_cwnd != 10 || | 233 | cli_tp.snd_cwnd != 10 || |
| 169 | cli_tp.total_retrans || | 234 | cli_tp.total_retrans || |
| 170 | cli_tp.bytes_received != DATA_LEN, | 235 | cli_tp.bytes_received != DATA_LEN, |
| 171 | "Unexpected cli_tp", "Check cli_tp output. linum:%u", linum); | 236 | "Unexpected cli_tp", "Check cli_tp output. egress_linum:%u", |
| 237 | egress_linum); | ||
| 172 | } | 238 | } |
| 173 | 239 | ||
| 174 | static void test(void) | 240 | static void test(void) |
| @@ -211,10 +277,10 @@ static void test(void) | |||
| 211 | err, errno); | 277 | err, errno); |
| 212 | 278 | ||
| 213 | /* Update addr_map with srv_sa6 and cli_sa6 */ | 279 | /* Update addr_map with srv_sa6 and cli_sa6 */ |
| 214 | err = bpf_map_update_elem(addr_map_fd, &srv_idx, &srv_sa6, 0); | 280 | err = bpf_map_update_elem(addr_map_fd, &addr_srv_idx, &srv_sa6, 0); |
| 215 | CHECK(err, "map_update", "err:%d errno:%d", err, errno); | 281 | CHECK(err, "map_update", "err:%d errno:%d", err, errno); |
| 216 | 282 | ||
| 217 | err = bpf_map_update_elem(addr_map_fd, &cli_idx, &cli_sa6, 0); | 283 | err = bpf_map_update_elem(addr_map_fd, &addr_cli_idx, &cli_sa6, 0); |
| 218 | CHECK(err, "map_update", "err:%d errno:%d", err, errno); | 284 | CHECK(err, "map_update", "err:%d errno:%d", err, errno); |
| 219 | 285 | ||
| 220 | /* Connect from cli_sa6 to srv_sa6 */ | 286 | /* Connect from cli_sa6 to srv_sa6 */ |
| @@ -273,9 +339,9 @@ int main(int argc, char **argv) | |||
| 273 | struct bpf_prog_load_attr attr = { | 339 | struct bpf_prog_load_attr attr = { |
| 274 | .file = "test_sock_fields_kern.o", | 340 | .file = "test_sock_fields_kern.o", |
| 275 | .prog_type = BPF_PROG_TYPE_CGROUP_SKB, | 341 | .prog_type = BPF_PROG_TYPE_CGROUP_SKB, |
| 276 | .expected_attach_type = BPF_CGROUP_INET_EGRESS, | ||
| 277 | }; | 342 | }; |
| 278 | int cgroup_fd, prog_fd, err; | 343 | int cgroup_fd, egress_fd, ingress_fd, err; |
| 344 | struct bpf_program *ingress_prog; | ||
| 279 | struct bpf_object *obj; | 345 | struct bpf_object *obj; |
| 280 | struct bpf_map *map; | 346 | struct bpf_map *map; |
| 281 | 347 | ||
| @@ -293,12 +359,24 @@ int main(int argc, char **argv) | |||
| 293 | err = join_cgroup(TEST_CGROUP); | 359 | err = join_cgroup(TEST_CGROUP); |
| 294 | CHECK(err, "join_cgroup", "err:%d errno:%d", err, errno); | 360 | CHECK(err, "join_cgroup", "err:%d errno:%d", err, errno); |
| 295 | 361 | ||
| 296 | err = bpf_prog_load_xattr(&attr, &obj, &prog_fd); | 362 | err = bpf_prog_load_xattr(&attr, &obj, &egress_fd); |
| 297 | CHECK(err, "bpf_prog_load_xattr()", "err:%d", err); | 363 | CHECK(err, "bpf_prog_load_xattr()", "err:%d", err); |
| 298 | 364 | ||
| 299 | err = bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_INET_EGRESS, 0); | 365 | ingress_prog = bpf_object__find_program_by_title(obj, |
| 366 | "cgroup_skb/ingress"); | ||
| 367 | CHECK(!ingress_prog, | ||
| 368 | "bpf_object__find_program_by_title(cgroup_skb/ingress)", | ||
| 369 | "not found"); | ||
| 370 | ingress_fd = bpf_program__fd(ingress_prog); | ||
| 371 | |||
| 372 | err = bpf_prog_attach(egress_fd, cgroup_fd, BPF_CGROUP_INET_EGRESS, 0); | ||
| 300 | CHECK(err == -1, "bpf_prog_attach(CPF_CGROUP_INET_EGRESS)", | 373 | CHECK(err == -1, "bpf_prog_attach(CPF_CGROUP_INET_EGRESS)", |
| 301 | "err:%d errno%d", err, errno); | 374 | "err:%d errno%d", err, errno); |
| 375 | |||
| 376 | err = bpf_prog_attach(ingress_fd, cgroup_fd, | ||
| 377 | BPF_CGROUP_INET_INGRESS, 0); | ||
| 378 | CHECK(err == -1, "bpf_prog_attach(CPF_CGROUP_INET_INGRESS)", | ||
| 379 | "err:%d errno%d", err, errno); | ||
| 302 | close(cgroup_fd); | 380 | close(cgroup_fd); |
| 303 | 381 | ||
| 304 | map = bpf_object__find_map_by_name(obj, "addr_map"); | 382 | map = bpf_object__find_map_by_name(obj, "addr_map"); |
diff --git a/tools/testing/selftests/bpf/verifier/calls.c b/tools/testing/selftests/bpf/verifier/calls.c index 4004891afa9c..f2ccae39ee66 100644 --- a/tools/testing/selftests/bpf/verifier/calls.c +++ b/tools/testing/selftests/bpf/verifier/calls.c | |||
| @@ -1940,3 +1940,28 @@ | |||
| 1940 | .errstr = "!read_ok", | 1940 | .errstr = "!read_ok", |
| 1941 | .result = REJECT, | 1941 | .result = REJECT, |
| 1942 | }, | 1942 | }, |
| 1943 | { | ||
| 1944 | "calls: cross frame pruning - liveness propagation", | ||
| 1945 | .insns = { | ||
| 1946 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32), | ||
| 1947 | BPF_MOV64_IMM(BPF_REG_8, 0), | ||
| 1948 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), | ||
| 1949 | BPF_MOV64_IMM(BPF_REG_8, 1), | ||
| 1950 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32), | ||
| 1951 | BPF_MOV64_IMM(BPF_REG_9, 0), | ||
| 1952 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), | ||
| 1953 | BPF_MOV64_IMM(BPF_REG_9, 1), | ||
| 1954 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), | ||
| 1955 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 4), | ||
| 1956 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_8, 1, 1), | ||
| 1957 | BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_2, 0), | ||
| 1958 | BPF_MOV64_IMM(BPF_REG_0, 0), | ||
| 1959 | BPF_EXIT_INSN(), | ||
| 1960 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 0), | ||
| 1961 | BPF_EXIT_INSN(), | ||
| 1962 | }, | ||
| 1963 | .prog_type = BPF_PROG_TYPE_SOCKET_FILTER, | ||
| 1964 | .errstr_unpriv = "function calls to other bpf functions are allowed for root only", | ||
| 1965 | .errstr = "!read_ok", | ||
| 1966 | .result = REJECT, | ||
| 1967 | }, | ||
diff --git a/tools/testing/selftests/bpf/verifier/ref_tracking.c b/tools/testing/selftests/bpf/verifier/ref_tracking.c index 3ed3593bd8b6..923f2110072d 100644 --- a/tools/testing/selftests/bpf/verifier/ref_tracking.c +++ b/tools/testing/selftests/bpf/verifier/ref_tracking.c | |||
| @@ -605,3 +605,171 @@ | |||
| 605 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 605 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 606 | .result = ACCEPT, | 606 | .result = ACCEPT, |
| 607 | }, | 607 | }, |
| 608 | { | ||
| 609 | "reference tracking: use ptr from bpf_tcp_sock() after release", | ||
| 610 | .insns = { | ||
| 611 | BPF_SK_LOOKUP, | ||
| 612 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), | ||
| 613 | BPF_EXIT_INSN(), | ||
| 614 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), | ||
| 615 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), | ||
| 616 | BPF_EMIT_CALL(BPF_FUNC_tcp_sock), | ||
| 617 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), | ||
| 618 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 619 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 620 | BPF_EXIT_INSN(), | ||
| 621 | BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), | ||
| 622 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 623 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 624 | BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_tcp_sock, snd_cwnd)), | ||
| 625 | BPF_EXIT_INSN(), | ||
| 626 | }, | ||
| 627 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | ||
| 628 | .result = REJECT, | ||
| 629 | .errstr = "invalid mem access", | ||
| 630 | }, | ||
| 631 | { | ||
| 632 | "reference tracking: use ptr from bpf_sk_fullsock() after release", | ||
| 633 | .insns = { | ||
| 634 | BPF_SK_LOOKUP, | ||
| 635 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), | ||
| 636 | BPF_EXIT_INSN(), | ||
| 637 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), | ||
| 638 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), | ||
| 639 | BPF_EMIT_CALL(BPF_FUNC_sk_fullsock), | ||
| 640 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), | ||
| 641 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 642 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 643 | BPF_EXIT_INSN(), | ||
| 644 | BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), | ||
| 645 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 646 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 647 | BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_sock, type)), | ||
| 648 | BPF_EXIT_INSN(), | ||
| 649 | }, | ||
| 650 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | ||
| 651 | .result = REJECT, | ||
| 652 | .errstr = "invalid mem access", | ||
| 653 | }, | ||
| 654 | { | ||
| 655 | "reference tracking: use ptr from bpf_sk_fullsock(tp) after release", | ||
| 656 | .insns = { | ||
| 657 | BPF_SK_LOOKUP, | ||
| 658 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), | ||
| 659 | BPF_EXIT_INSN(), | ||
| 660 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), | ||
| 661 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), | ||
| 662 | BPF_EMIT_CALL(BPF_FUNC_tcp_sock), | ||
| 663 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), | ||
| 664 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 665 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 666 | BPF_EXIT_INSN(), | ||
| 667 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), | ||
| 668 | BPF_EMIT_CALL(BPF_FUNC_sk_fullsock), | ||
| 669 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 670 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), | ||
| 671 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 672 | BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 1), | ||
| 673 | BPF_EXIT_INSN(), | ||
| 674 | BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)), | ||
| 675 | BPF_EXIT_INSN(), | ||
| 676 | }, | ||
| 677 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | ||
| 678 | .result = REJECT, | ||
| 679 | .errstr = "invalid mem access", | ||
| 680 | }, | ||
| 681 | { | ||
| 682 | "reference tracking: use sk after bpf_sk_release(tp)", | ||
| 683 | .insns = { | ||
| 684 | BPF_SK_LOOKUP, | ||
| 685 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), | ||
| 686 | BPF_EXIT_INSN(), | ||
| 687 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), | ||
| 688 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), | ||
| 689 | BPF_EMIT_CALL(BPF_FUNC_tcp_sock), | ||
| 690 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), | ||
| 691 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 692 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 693 | BPF_EXIT_INSN(), | ||
| 694 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), | ||
| 695 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 696 | BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)), | ||
| 697 | BPF_EXIT_INSN(), | ||
| 698 | }, | ||
| 699 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | ||
| 700 | .result = REJECT, | ||
| 701 | .errstr = "invalid mem access", | ||
| 702 | }, | ||
| 703 | { | ||
| 704 | "reference tracking: use ptr from bpf_get_listener_sock() after bpf_sk_release(sk)", | ||
| 705 | .insns = { | ||
| 706 | BPF_SK_LOOKUP, | ||
| 707 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), | ||
| 708 | BPF_EXIT_INSN(), | ||
| 709 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), | ||
| 710 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), | ||
| 711 | BPF_EMIT_CALL(BPF_FUNC_get_listener_sock), | ||
| 712 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), | ||
| 713 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 714 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 715 | BPF_EXIT_INSN(), | ||
| 716 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 717 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), | ||
| 718 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 719 | BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, src_port)), | ||
| 720 | BPF_EXIT_INSN(), | ||
| 721 | }, | ||
| 722 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | ||
| 723 | .result = ACCEPT, | ||
| 724 | }, | ||
| 725 | { | ||
| 726 | "reference tracking: bpf_sk_release(listen_sk)", | ||
| 727 | .insns = { | ||
| 728 | BPF_SK_LOOKUP, | ||
| 729 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), | ||
| 730 | BPF_EXIT_INSN(), | ||
| 731 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), | ||
| 732 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), | ||
| 733 | BPF_EMIT_CALL(BPF_FUNC_get_listener_sock), | ||
| 734 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), | ||
| 735 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 736 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 737 | BPF_EXIT_INSN(), | ||
| 738 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), | ||
| 739 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 740 | BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)), | ||
| 741 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 742 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 743 | BPF_EXIT_INSN(), | ||
| 744 | }, | ||
| 745 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | ||
| 746 | .result = REJECT, | ||
| 747 | .errstr = "reference has not been acquired before", | ||
| 748 | }, | ||
| 749 | { | ||
| 750 | /* !bpf_sk_fullsock(sk) is checked but !bpf_tcp_sock(sk) is not checked */ | ||
| 751 | "reference tracking: tp->snd_cwnd after bpf_sk_fullsock(sk) and bpf_tcp_sock(sk)", | ||
| 752 | .insns = { | ||
| 753 | BPF_SK_LOOKUP, | ||
| 754 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), | ||
| 755 | BPF_EXIT_INSN(), | ||
| 756 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), | ||
| 757 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), | ||
| 758 | BPF_EMIT_CALL(BPF_FUNC_sk_fullsock), | ||
| 759 | BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), | ||
| 760 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 761 | BPF_EMIT_CALL(BPF_FUNC_tcp_sock), | ||
| 762 | BPF_MOV64_REG(BPF_REG_8, BPF_REG_0), | ||
| 763 | BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 3), | ||
| 764 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 765 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 766 | BPF_EXIT_INSN(), | ||
| 767 | BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_8, offsetof(struct bpf_tcp_sock, snd_cwnd)), | ||
| 768 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), | ||
| 769 | BPF_EMIT_CALL(BPF_FUNC_sk_release), | ||
| 770 | BPF_EXIT_INSN(), | ||
| 771 | }, | ||
| 772 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | ||
| 773 | .result = REJECT, | ||
| 774 | .errstr = "invalid mem access", | ||
| 775 | }, | ||
diff --git a/tools/testing/selftests/bpf/verifier/sock.c b/tools/testing/selftests/bpf/verifier/sock.c index 0ddfdf76aba5..416436231fab 100644 --- a/tools/testing/selftests/bpf/verifier/sock.c +++ b/tools/testing/selftests/bpf/verifier/sock.c | |||
| @@ -342,7 +342,7 @@ | |||
| 342 | }, | 342 | }, |
| 343 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 343 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 344 | .result = REJECT, | 344 | .result = REJECT, |
| 345 | .errstr = "type=sock_common expected=sock", | 345 | .errstr = "reference has not been acquired before", |
| 346 | }, | 346 | }, |
| 347 | { | 347 | { |
| 348 | "bpf_sk_release(bpf_sk_fullsock(skb->sk))", | 348 | "bpf_sk_release(bpf_sk_fullsock(skb->sk))", |
| @@ -380,5 +380,5 @@ | |||
| 380 | }, | 380 | }, |
| 381 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 381 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 382 | .result = REJECT, | 382 | .result = REJECT, |
| 383 | .errstr = "type=tcp_sock expected=sock", | 383 | .errstr = "reference has not been acquired before", |
| 384 | }, | 384 | }, |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json b/tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json index 5970cee6d05f..b074ea9b6fe8 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json | |||
| @@ -286,5 +286,30 @@ | |||
| 286 | "teardown": [ | 286 | "teardown": [ |
| 287 | "$TC action flush action bpf" | 287 | "$TC action flush action bpf" |
| 288 | ] | 288 | ] |
| 289 | }, | ||
| 290 | { | ||
| 291 | "id": "b8a1", | ||
| 292 | "name": "Replace bpf action with invalid goto_chain control", | ||
| 293 | "category": [ | ||
| 294 | "actions", | ||
| 295 | "bpf" | ||
| 296 | ], | ||
| 297 | "setup": [ | ||
| 298 | [ | ||
| 299 | "$TC actions flush action bpf", | ||
| 300 | 0, | ||
| 301 | 1, | ||
| 302 | 255 | ||
| 303 | ], | ||
| 304 | "$TC action add action bpf bytecode '1,6 0 0 4294967295' pass index 90" | ||
| 305 | ], | ||
| 306 | "cmdUnderTest": "$TC action replace action bpf bytecode '1,6 0 0 4294967295' goto chain 42 index 90 cookie c1a0c1a0", | ||
| 307 | "expExitCode": "255", | ||
| 308 | "verifyCmd": "$TC action list action bpf", | ||
| 309 | "matchPattern": "action order [0-9]*: bpf.* default-action pass.*index 90", | ||
| 310 | "matchCount": "1", | ||
| 311 | "teardown": [ | ||
| 312 | "$TC action flush action bpf" | ||
| 313 | ] | ||
| 289 | } | 314 | } |
| 290 | ] | 315 | ] |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/connmark.json b/tools/testing/selftests/tc-testing/tc-tests/actions/connmark.json index 13147a1f5731..cadde8f41fcd 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/connmark.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/connmark.json | |||
| @@ -287,5 +287,30 @@ | |||
| 287 | "teardown": [ | 287 | "teardown": [ |
| 288 | "$TC actions flush action connmark" | 288 | "$TC actions flush action connmark" |
| 289 | ] | 289 | ] |
| 290 | }, | ||
| 291 | { | ||
| 292 | "id": "c506", | ||
| 293 | "name": "Replace connmark with invalid goto chain control", | ||
| 294 | "category": [ | ||
| 295 | "actions", | ||
| 296 | "connmark" | ||
| 297 | ], | ||
| 298 | "setup": [ | ||
| 299 | [ | ||
| 300 | "$TC actions flush action connmark", | ||
| 301 | 0, | ||
| 302 | 1, | ||
| 303 | 255 | ||
| 304 | ], | ||
| 305 | "$TC actions add action connmark pass index 90" | ||
| 306 | ], | ||
| 307 | "cmdUnderTest": "$TC actions replace action connmark goto chain 42 index 90 cookie c1a0c1a0", | ||
| 308 | "expExitCode": "255", | ||
| 309 | "verifyCmd": "$TC actions get action connmark index 90", | ||
| 310 | "matchPattern": "action order [0-9]+: connmark zone 0 pass.*index 90 ref", | ||
| 311 | "matchCount": "1", | ||
| 312 | "teardown": [ | ||
| 313 | "$TC actions flush action connmark" | ||
| 314 | ] | ||
| 290 | } | 315 | } |
| 291 | ] | 316 | ] |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/csum.json b/tools/testing/selftests/tc-testing/tc-tests/actions/csum.json index a022792d392a..ddabb2fbb7c7 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/csum.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/csum.json | |||
| @@ -500,5 +500,30 @@ | |||
| 500 | "matchPattern": "^[ \t]+index [0-9]+ ref", | 500 | "matchPattern": "^[ \t]+index [0-9]+ ref", |
| 501 | "matchCount": "0", | 501 | "matchCount": "0", |
| 502 | "teardown": [] | 502 | "teardown": [] |
| 503 | }, | ||
| 504 | { | ||
| 505 | "id": "d128", | ||
| 506 | "name": "Replace csum action with invalid goto chain control", | ||
| 507 | "category": [ | ||
| 508 | "actions", | ||
| 509 | "csum" | ||
| 510 | ], | ||
| 511 | "setup": [ | ||
| 512 | [ | ||
| 513 | "$TC actions flush action csum", | ||
| 514 | 0, | ||
| 515 | 1, | ||
| 516 | 255 | ||
| 517 | ], | ||
| 518 | "$TC actions add action csum iph index 90" | ||
| 519 | ], | ||
| 520 | "cmdUnderTest": "$TC actions replace action csum iph goto chain 42 index 90 cookie c1a0c1a0", | ||
| 521 | "expExitCode": "255", | ||
| 522 | "verifyCmd": "$TC actions get action csum index 90", | ||
| 523 | "matchPattern": "action order [0-9]*: csum \\(iph\\) action pass.*index 90 ref", | ||
| 524 | "matchCount": "1", | ||
| 525 | "teardown": [ | ||
| 526 | "$TC actions flush action csum" | ||
| 527 | ] | ||
| 503 | } | 528 | } |
| 504 | ] | 529 | ] |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json b/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json index 89189a03ce3d..814b7a8a478b 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json | |||
| @@ -560,5 +560,30 @@ | |||
| 560 | "teardown": [ | 560 | "teardown": [ |
| 561 | "$TC actions flush action gact" | 561 | "$TC actions flush action gact" |
| 562 | ] | 562 | ] |
| 563 | }, | ||
| 564 | { | ||
| 565 | "id": "ca89", | ||
| 566 | "name": "Replace gact action with invalid goto chain control", | ||
| 567 | "category": [ | ||
| 568 | "actions", | ||
| 569 | "gact" | ||
| 570 | ], | ||
| 571 | "setup": [ | ||
| 572 | [ | ||
| 573 | "$TC actions flush action gact", | ||
| 574 | 0, | ||
| 575 | 1, | ||
| 576 | 255 | ||
| 577 | ], | ||
| 578 | "$TC actions add action pass random determ drop 2 index 90" | ||
| 579 | ], | ||
| 580 | "cmdUnderTest": "$TC actions replace action goto chain 42 random determ drop 5 index 90 cookie c1a0c1a0", | ||
| 581 | "expExitCode": "255", | ||
| 582 | "verifyCmd": "$TC actions list action gact", | ||
| 583 | "matchPattern": "action order [0-9]*: gact action pass.*random type determ drop val 2.*index 90 ref", | ||
| 584 | "matchCount": "1", | ||
| 585 | "teardown": [ | ||
| 586 | "$TC actions flush action gact" | ||
| 587 | ] | ||
| 563 | } | 588 | } |
| 564 | ] | 589 | ] |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/ife.json b/tools/testing/selftests/tc-testing/tc-tests/actions/ife.json index 0da3545cabdb..c13a68b98fc7 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/ife.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/ife.json | |||
| @@ -1060,5 +1060,30 @@ | |||
| 1060 | "matchPattern": "action order [0-9]*: ife encode action pipe.*allow prio.*index 4", | 1060 | "matchPattern": "action order [0-9]*: ife encode action pipe.*allow prio.*index 4", |
| 1061 | "matchCount": "0", | 1061 | "matchCount": "0", |
| 1062 | "teardown": [] | 1062 | "teardown": [] |
| 1063 | }, | ||
| 1064 | { | ||
| 1065 | "id": "a0e2", | ||
| 1066 | "name": "Replace ife encode action with invalid goto chain control", | ||
| 1067 | "category": [ | ||
| 1068 | "actions", | ||
| 1069 | "ife" | ||
| 1070 | ], | ||
| 1071 | "setup": [ | ||
| 1072 | [ | ||
| 1073 | "$TC actions flush action ife", | ||
| 1074 | 0, | ||
| 1075 | 1, | ||
| 1076 | 255 | ||
| 1077 | ], | ||
| 1078 | "$TC actions add action ife encode allow mark pass index 90" | ||
| 1079 | ], | ||
| 1080 | "cmdUnderTest": "$TC actions replace action ife encode allow mark goto chain 42 index 90 cookie c1a0c1a0", | ||
| 1081 | "expExitCode": "255", | ||
| 1082 | "verifyCmd": "$TC actions get action ife index 90", | ||
| 1083 | "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E .*allow mark.*index 90 ref", | ||
| 1084 | "matchCount": "1", | ||
| 1085 | "teardown": [ | ||
| 1086 | "$TC actions flush action ife" | ||
| 1087 | ] | ||
| 1063 | } | 1088 | } |
| 1064 | ] | 1089 | ] |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json b/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json index db49fd0f8445..6e5fb3d25681 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json | |||
| @@ -434,5 +434,30 @@ | |||
| 434 | "teardown": [ | 434 | "teardown": [ |
| 435 | "$TC actions flush action mirred" | 435 | "$TC actions flush action mirred" |
| 436 | ] | 436 | ] |
| 437 | }, | ||
| 438 | { | ||
| 439 | "id": "2a9a", | ||
| 440 | "name": "Replace mirred action with invalid goto chain control", | ||
| 441 | "category": [ | ||
| 442 | "actions", | ||
| 443 | "mirred" | ||
| 444 | ], | ||
| 445 | "setup": [ | ||
| 446 | [ | ||
| 447 | "$TC actions flush action mirred", | ||
| 448 | 0, | ||
| 449 | 1, | ||
| 450 | 255 | ||
| 451 | ], | ||
| 452 | "$TC actions add action mirred ingress mirror dev lo drop index 90" | ||
| 453 | ], | ||
| 454 | "cmdUnderTest": "$TC actions replace action mirred ingress mirror dev lo goto chain 42 index 90 cookie c1a0c1a0", | ||
| 455 | "expExitCode": "255", | ||
| 456 | "verifyCmd": "$TC actions get action mirred index 90", | ||
| 457 | "matchPattern": "action order [0-9]*: mirred \\(Ingress Mirror to device lo\\) drop.*index 90 ref", | ||
| 458 | "matchCount": "1", | ||
| 459 | "teardown": [ | ||
| 460 | "$TC actions flush action mirred" | ||
| 461 | ] | ||
| 437 | } | 462 | } |
| 438 | ] | 463 | ] |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/nat.json b/tools/testing/selftests/tc-testing/tc-tests/actions/nat.json index 0080dc2fd41c..bc12c1ccad30 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/nat.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/nat.json | |||
| @@ -589,5 +589,30 @@ | |||
| 589 | "teardown": [ | 589 | "teardown": [ |
| 590 | "$TC actions flush action nat" | 590 | "$TC actions flush action nat" |
| 591 | ] | 591 | ] |
| 592 | }, | ||
| 593 | { | ||
| 594 | "id": "4b12", | ||
| 595 | "name": "Replace nat action with invalid goto chain control", | ||
| 596 | "category": [ | ||
| 597 | "actions", | ||
| 598 | "nat" | ||
| 599 | ], | ||
| 600 | "setup": [ | ||
| 601 | [ | ||
| 602 | "$TC actions flush action nat", | ||
| 603 | 0, | ||
| 604 | 1, | ||
| 605 | 255 | ||
| 606 | ], | ||
| 607 | "$TC actions add action nat ingress 1.18.1.1 1.18.2.2 drop index 90" | ||
| 608 | ], | ||
| 609 | "cmdUnderTest": "$TC actions replace action nat ingress 1.18.1.1 1.18.2.2 goto chain 42 index 90 cookie c1a0c1a0", | ||
| 610 | "expExitCode": "255", | ||
| 611 | "verifyCmd": "$TC actions get action nat index 90", | ||
| 612 | "matchPattern": "action order [0-9]+: nat ingress 1.18.1.1/32 1.18.2.2 drop.*index 90 ref", | ||
| 613 | "matchCount": "1", | ||
| 614 | "teardown": [ | ||
| 615 | "$TC actions flush action nat" | ||
| 616 | ] | ||
| 592 | } | 617 | } |
| 593 | ] | 618 | ] |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/pedit.json b/tools/testing/selftests/tc-testing/tc-tests/actions/pedit.json new file mode 100644 index 000000000000..b73ceb9e28b1 --- /dev/null +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/pedit.json | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | [ | ||
| 2 | { | ||
| 3 | "id": "319a", | ||
| 4 | "name": "Add pedit action that mangles IP TTL", | ||
| 5 | "category": [ | ||
| 6 | "actions", | ||
| 7 | "pedit" | ||
| 8 | ], | ||
| 9 | "setup": [ | ||
| 10 | [ | ||
| 11 | "$TC actions flush action pedit", | ||
| 12 | 0, | ||
| 13 | 1, | ||
| 14 | 255 | ||
| 15 | ] | ||
| 16 | ], | ||
| 17 | "cmdUnderTest": "$TC actions add action pedit ex munge ip ttl set 10", | ||
| 18 | "expExitCode": "0", | ||
| 19 | "verifyCmd": "$TC actions ls action pedit", | ||
| 20 | "matchPattern": "action order [0-9]+: pedit action pass keys 1.*index 1 ref.*key #0 at ipv4\\+8: val 0a000000 mask 00ffffff", | ||
| 21 | "matchCount": "1", | ||
| 22 | "teardown": [ | ||
| 23 | "$TC actions flush action pedit" | ||
| 24 | ] | ||
| 25 | }, | ||
| 26 | { | ||
| 27 | "id": "7e67", | ||
| 28 | "name": "Replace pedit action with invalid goto chain", | ||
| 29 | "category": [ | ||
| 30 | "actions", | ||
| 31 | "pedit" | ||
| 32 | ], | ||
| 33 | "setup": [ | ||
| 34 | [ | ||
| 35 | "$TC actions flush action pedit", | ||
| 36 | 0, | ||
| 37 | 1, | ||
| 38 | 255 | ||
| 39 | ], | ||
| 40 | "$TC actions add action pedit ex munge ip ttl set 10 pass index 90" | ||
| 41 | ], | ||
| 42 | "cmdUnderTest": "$TC actions replace action pedit ex munge ip ttl set 10 goto chain 42 index 90 cookie c1a0c1a0", | ||
| 43 | "expExitCode": "255", | ||
| 44 | "verifyCmd": "$TC actions ls action pedit", | ||
| 45 | "matchPattern": "action order [0-9]+: pedit action pass keys 1.*index 90 ref.*key #0 at ipv4\\+8: val 0a000000 mask 00ffffff", | ||
| 46 | "matchCount": "1", | ||
| 47 | "teardown": [ | ||
| 48 | "$TC actions flush action pedit" | ||
| 49 | ] | ||
| 50 | } | ||
| 51 | ] | ||
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/police.json b/tools/testing/selftests/tc-testing/tc-tests/actions/police.json index 4086a50a670e..b8268da5adaa 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/police.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/police.json | |||
| @@ -739,5 +739,30 @@ | |||
| 739 | "teardown": [ | 739 | "teardown": [ |
| 740 | "$TC actions flush action police" | 740 | "$TC actions flush action police" |
| 741 | ] | 741 | ] |
| 742 | }, | ||
| 743 | { | ||
| 744 | "id": "689e", | ||
| 745 | "name": "Replace police action with invalid goto chain control", | ||
| 746 | "category": [ | ||
| 747 | "actions", | ||
| 748 | "police" | ||
| 749 | ], | ||
| 750 | "setup": [ | ||
| 751 | [ | ||
| 752 | "$TC actions flush action police", | ||
| 753 | 0, | ||
| 754 | 1, | ||
| 755 | 255 | ||
| 756 | ], | ||
| 757 | "$TC actions add action police rate 3mbit burst 250k drop index 90" | ||
| 758 | ], | ||
| 759 | "cmdUnderTest": "$TC actions replace action police rate 3mbit burst 250k goto chain 42 index 90 cookie c1a0c1a0", | ||
| 760 | "expExitCode": "255", | ||
| 761 | "verifyCmd": "$TC actions get action police index 90", | ||
| 762 | "matchPattern": "action order [0-9]*: police 0x5a rate 3Mbit burst 250Kb mtu 2Kb action drop", | ||
| 763 | "matchCount": "1", | ||
| 764 | "teardown": [ | ||
| 765 | "$TC actions flush action police" | ||
| 766 | ] | ||
| 742 | } | 767 | } |
| 743 | ] | 768 | ] |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/sample.json b/tools/testing/selftests/tc-testing/tc-tests/actions/sample.json index 3aca33c00039..27f0acaed880 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/sample.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/sample.json | |||
| @@ -584,5 +584,30 @@ | |||
| 584 | "teardown": [ | 584 | "teardown": [ |
| 585 | "$TC actions flush action sample" | 585 | "$TC actions flush action sample" |
| 586 | ] | 586 | ] |
| 587 | }, | ||
| 588 | { | ||
| 589 | "id": "0a6e", | ||
| 590 | "name": "Replace sample action with invalid goto chain control", | ||
| 591 | "category": [ | ||
| 592 | "actions", | ||
| 593 | "sample" | ||
| 594 | ], | ||
| 595 | "setup": [ | ||
| 596 | [ | ||
| 597 | "$TC actions flush action sample", | ||
| 598 | 0, | ||
| 599 | 1, | ||
| 600 | 255 | ||
| 601 | ], | ||
| 602 | "$TC actions add action sample rate 1024 group 4 pass index 90" | ||
| 603 | ], | ||
| 604 | "cmdUnderTest": "$TC actions replace action sample rate 1024 group 7 goto chain 42 index 90 cookie c1a0c1a0", | ||
| 605 | "expExitCode": "255", | ||
| 606 | "verifyCmd": "$TC actions list action sample", | ||
| 607 | "matchPattern": "action order [0-9]+: sample rate 1/1024 group 4 pass.*index 90", | ||
| 608 | "matchCount": "1", | ||
| 609 | "teardown": [ | ||
| 610 | "$TC actions flush action sample" | ||
| 611 | ] | ||
| 587 | } | 612 | } |
| 588 | ] | 613 | ] |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/simple.json b/tools/testing/selftests/tc-testing/tc-tests/actions/simple.json index e89a7aa4012d..8e8c1ae12260 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/simple.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/simple.json | |||
| @@ -126,5 +126,30 @@ | |||
| 126 | "teardown": [ | 126 | "teardown": [ |
| 127 | "" | 127 | "" |
| 128 | ] | 128 | ] |
| 129 | }, | ||
| 130 | { | ||
| 131 | "id": "b776", | ||
| 132 | "name": "Replace simple action with invalid goto chain control", | ||
| 133 | "category": [ | ||
| 134 | "actions", | ||
| 135 | "simple" | ||
| 136 | ], | ||
| 137 | "setup": [ | ||
| 138 | [ | ||
| 139 | "$TC actions flush action simple", | ||
| 140 | 0, | ||
| 141 | 1, | ||
| 142 | 255 | ||
| 143 | ], | ||
| 144 | "$TC actions add action simple sdata \"hello\" pass index 90" | ||
| 145 | ], | ||
| 146 | "cmdUnderTest": "$TC actions replace action simple sdata \"world\" goto chain 42 index 90 cookie c1a0c1a0", | ||
| 147 | "expExitCode": "255", | ||
| 148 | "verifyCmd": "$TC actions list action simple", | ||
| 149 | "matchPattern": "action order [0-9]*: Simple <hello>.*index 90 ref", | ||
| 150 | "matchCount": "1", | ||
| 151 | "teardown": [ | ||
| 152 | "$TC actions flush action simple" | ||
| 153 | ] | ||
| 129 | } | 154 | } |
| 130 | ] | 155 | ] |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json b/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json index 5aaf593b914a..ecd96eda7f6a 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json | |||
| @@ -484,5 +484,30 @@ | |||
| 484 | "teardown": [ | 484 | "teardown": [ |
| 485 | "$TC actions flush action skbedit" | 485 | "$TC actions flush action skbedit" |
| 486 | ] | 486 | ] |
| 487 | }, | ||
| 488 | { | ||
| 489 | "id": "1b2b", | ||
| 490 | "name": "Replace skbedit action with invalid goto_chain control", | ||
| 491 | "category": [ | ||
| 492 | "actions", | ||
| 493 | "skbedit" | ||
| 494 | ], | ||
| 495 | "setup": [ | ||
| 496 | [ | ||
| 497 | "$TC actions flush action skbedit", | ||
| 498 | 0, | ||
| 499 | 1, | ||
| 500 | 255 | ||
| 501 | ], | ||
| 502 | "$TC actions add action skbedit ptype host pass index 90" | ||
| 503 | ], | ||
| 504 | "cmdUnderTest": "$TC actions replace action skbedit ptype host goto chain 42 index 90 cookie c1a0c1a0", | ||
| 505 | "expExitCode": "255", | ||
| 506 | "verifyCmd": "$TC actions list action skbedit", | ||
| 507 | "matchPattern": "action order [0-9]*: skbedit ptype host pass.*index 90 ref", | ||
| 508 | "matchCount": "1", | ||
| 509 | "teardown": [ | ||
| 510 | "$TC actions flush action skbedit" | ||
| 511 | ] | ||
| 487 | } | 512 | } |
| 488 | ] | 513 | ] |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json b/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json index fe3326e939c1..6eb4c4f97060 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json | |||
| @@ -392,5 +392,30 @@ | |||
| 392 | "teardown": [ | 392 | "teardown": [ |
| 393 | "$TC actions flush action skbmod" | 393 | "$TC actions flush action skbmod" |
| 394 | ] | 394 | ] |
| 395 | }, | ||
| 396 | { | ||
| 397 | "id": "b651", | ||
| 398 | "name": "Replace skbmod action with invalid goto_chain control", | ||
| 399 | "category": [ | ||
| 400 | "actions", | ||
| 401 | "skbmod" | ||
| 402 | ], | ||
| 403 | "setup": [ | ||
| 404 | [ | ||
| 405 | "$TC actions flush action skbmod", | ||
| 406 | 0, | ||
| 407 | 1, | ||
| 408 | 255 | ||
| 409 | ], | ||
| 410 | "$TC actions add action skbmod set etype 0x1111 pass index 90" | ||
| 411 | ], | ||
| 412 | "cmdUnderTest": "$TC actions replace action skbmod set etype 0x1111 goto chain 42 index 90 cookie c1a0c1a0", | ||
| 413 | "expExitCode": "255", | ||
| 414 | "verifyCmd": "$TC actions ls action skbmod", | ||
| 415 | "matchPattern": "action order [0-9]*: skbmod pass set etype 0x1111\\s+index 90 ref", | ||
| 416 | "matchCount": "1", | ||
| 417 | "teardown": [ | ||
| 418 | "$TC actions flush action skbmod" | ||
| 419 | ] | ||
| 395 | } | 420 | } |
| 396 | ] | 421 | ] |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/tunnel_key.json b/tools/testing/selftests/tc-testing/tc-tests/actions/tunnel_key.json index e7e15a7336b6..28453a445fdb 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/tunnel_key.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/tunnel_key.json | |||
| @@ -884,5 +884,30 @@ | |||
| 884 | "teardown": [ | 884 | "teardown": [ |
| 885 | "$TC actions flush action tunnel_key" | 885 | "$TC actions flush action tunnel_key" |
| 886 | ] | 886 | ] |
| 887 | }, | ||
| 888 | { | ||
| 889 | "id": "8242", | ||
| 890 | "name": "Replace tunnel_key set action with invalid goto chain", | ||
| 891 | "category": [ | ||
| 892 | "actions", | ||
| 893 | "tunnel_key" | ||
| 894 | ], | ||
| 895 | "setup": [ | ||
| 896 | [ | ||
| 897 | "$TC actions flush action tunnel_key", | ||
| 898 | 0, | ||
| 899 | 1, | ||
| 900 | 255 | ||
| 901 | ], | ||
| 902 | "$TC actions add action tunnel_key set src_ip 10.10.10.1 dst_ip 20.20.20.2 dst_port 3128 nocsum id 1 pass index 90" | ||
| 903 | ], | ||
| 904 | "cmdUnderTest": "$TC actions replace action tunnel_key set src_ip 10.10.10.2 dst_ip 20.20.20.1 dst_port 3129 id 2 csum goto chain 42 index 90 cookie c1a0c1a0", | ||
| 905 | "expExitCode": "255", | ||
| 906 | "verifyCmd": "$TC actions get action tunnel_key index 90", | ||
| 907 | "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 10.10.10.1.*dst_ip 20.20.20.2.*key_id 1.*dst_port 3128.*csum pass.*index 90 ref", | ||
| 908 | "matchCount": "1", | ||
| 909 | "teardown": [ | ||
| 910 | "$TC actions flush action tunnel_key" | ||
| 911 | ] | ||
| 887 | } | 912 | } |
| 888 | ] | 913 | ] |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json b/tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json index 69ea09eefffc..cc7c7d758008 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json | |||
| @@ -688,5 +688,30 @@ | |||
| 688 | "teardown": [ | 688 | "teardown": [ |
| 689 | "$TC actions flush action vlan" | 689 | "$TC actions flush action vlan" |
| 690 | ] | 690 | ] |
| 691 | }, | ||
| 692 | { | ||
| 693 | "id": "e394", | ||
| 694 | "name": "Replace vlan push action with invalid goto chain control", | ||
| 695 | "category": [ | ||
| 696 | "actions", | ||
| 697 | "vlan" | ||
| 698 | ], | ||
| 699 | "setup": [ | ||
| 700 | [ | ||
| 701 | "$TC actions flush action vlan", | ||
| 702 | 0, | ||
| 703 | 1, | ||
| 704 | 255 | ||
| 705 | ], | ||
| 706 | "$TC actions add action vlan push id 500 pass index 90" | ||
| 707 | ], | ||
| 708 | "cmdUnderTest": "$TC actions replace action vlan push id 500 goto chain 42 index 90 cookie c1a0c1a0", | ||
| 709 | "expExitCode": "255", | ||
| 710 | "verifyCmd": "$TC actions get action vlan index 90", | ||
| 711 | "matchPattern": "action order [0-9]+: vlan.*push id 500 protocol 802.1Q priority 0 pass.*index 90 ref", | ||
| 712 | "matchCount": "1", | ||
| 713 | "teardown": [ | ||
| 714 | "$TC actions flush action vlan" | ||
| 715 | ] | ||
| 691 | } | 716 | } |
| 692 | ] | 717 | ] |
