diff options
100 files changed, 1086 insertions, 612 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index c776906f67a9..c45c02bc6082 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3216,7 +3216,6 @@ F: drivers/platform/chrome/ | |||
3216 | 3216 | ||
3217 | CISCO VIC ETHERNET NIC DRIVER | 3217 | CISCO VIC ETHERNET NIC DRIVER |
3218 | M: Christian Benvenuti <benve@cisco.com> | 3218 | M: Christian Benvenuti <benve@cisco.com> |
3219 | M: Sujith Sankar <ssujith@cisco.com> | ||
3220 | M: Govindarajulu Varadarajan <_govind@gmx.com> | 3219 | M: Govindarajulu Varadarajan <_govind@gmx.com> |
3221 | M: Neel Patel <neepatel@cisco.com> | 3220 | M: Neel Patel <neepatel@cisco.com> |
3222 | S: Supported | 3221 | S: Supported |
@@ -7774,13 +7773,6 @@ F: include/net/mac80211.h | |||
7774 | F: net/mac80211/ | 7773 | F: net/mac80211/ |
7775 | F: drivers/net/wireless/mac80211_hwsim.[ch] | 7774 | F: drivers/net/wireless/mac80211_hwsim.[ch] |
7776 | 7775 | ||
7777 | MACVLAN DRIVER | ||
7778 | M: Patrick McHardy <kaber@trash.net> | ||
7779 | L: netdev@vger.kernel.org | ||
7780 | S: Maintained | ||
7781 | F: drivers/net/macvlan.c | ||
7782 | F: include/linux/if_macvlan.h | ||
7783 | |||
7784 | MAILBOX API | 7776 | MAILBOX API |
7785 | M: Jassi Brar <jassisinghbrar@gmail.com> | 7777 | M: Jassi Brar <jassisinghbrar@gmail.com> |
7786 | L: linux-kernel@vger.kernel.org | 7778 | L: linux-kernel@vger.kernel.org |
@@ -7853,6 +7845,8 @@ F: drivers/net/ethernet/marvell/mvneta.* | |||
7853 | MARVELL MWIFIEX WIRELESS DRIVER | 7845 | MARVELL MWIFIEX WIRELESS DRIVER |
7854 | M: Amitkumar Karwar <akarwar@marvell.com> | 7846 | M: Amitkumar Karwar <akarwar@marvell.com> |
7855 | M: Nishant Sarmukadam <nishants@marvell.com> | 7847 | M: Nishant Sarmukadam <nishants@marvell.com> |
7848 | M: Ganapathi Bhat <gbhat@marvell.com> | ||
7849 | M: Xinming Hu <huxm@marvell.com> | ||
7856 | L: linux-wireless@vger.kernel.org | 7850 | L: linux-wireless@vger.kernel.org |
7857 | S: Maintained | 7851 | S: Maintained |
7858 | F: drivers/net/wireless/marvell/mwifiex/ | 7852 | F: drivers/net/wireless/marvell/mwifiex/ |
@@ -13383,14 +13377,6 @@ W: https://linuxtv.org | |||
13383 | S: Maintained | 13377 | S: Maintained |
13384 | F: drivers/media/platform/vivid/* | 13378 | F: drivers/media/platform/vivid/* |
13385 | 13379 | ||
13386 | VLAN (802.1Q) | ||
13387 | M: Patrick McHardy <kaber@trash.net> | ||
13388 | L: netdev@vger.kernel.org | ||
13389 | S: Maintained | ||
13390 | F: drivers/net/macvlan.c | ||
13391 | F: include/linux/if_*vlan.h | ||
13392 | F: net/8021q/ | ||
13393 | |||
13394 | VLYNQ BUS | 13380 | VLYNQ BUS |
13395 | M: Florian Fainelli <f.fainelli@gmail.com> | 13381 | M: Florian Fainelli <f.fainelli@gmail.com> |
13396 | L: openwrt-devel@lists.openwrt.org (subscribers-only) | 13382 | L: openwrt-devel@lists.openwrt.org (subscribers-only) |
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index c2c14a12713b..08e054507d0b 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig | |||
@@ -344,7 +344,8 @@ config BT_WILINK | |||
344 | 344 | ||
345 | config BT_QCOMSMD | 345 | config BT_QCOMSMD |
346 | tristate "Qualcomm SMD based HCI support" | 346 | tristate "Qualcomm SMD based HCI support" |
347 | depends on (QCOM_SMD && QCOM_WCNSS_CTRL) || COMPILE_TEST | 347 | depends on QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n) |
348 | depends on QCOM_WCNSS_CTRL || (COMPILE_TEST && QCOM_WCNSS_CTRL=n) | ||
348 | select BT_QCA | 349 | select BT_QCA |
349 | help | 350 | help |
350 | Qualcomm SMD based HCI driver. | 351 | Qualcomm SMD based HCI driver. |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index 8a280e7d66bd..127adbeefb10 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h | |||
@@ -984,29 +984,29 @@ | |||
984 | #define XP_ECC_CNT1_DESC_DED_WIDTH 8 | 984 | #define XP_ECC_CNT1_DESC_DED_WIDTH 8 |
985 | #define XP_ECC_CNT1_DESC_SEC_INDEX 0 | 985 | #define XP_ECC_CNT1_DESC_SEC_INDEX 0 |
986 | #define XP_ECC_CNT1_DESC_SEC_WIDTH 8 | 986 | #define XP_ECC_CNT1_DESC_SEC_WIDTH 8 |
987 | #define XP_ECC_IER_DESC_DED_INDEX 0 | 987 | #define XP_ECC_IER_DESC_DED_INDEX 5 |
988 | #define XP_ECC_IER_DESC_DED_WIDTH 1 | 988 | #define XP_ECC_IER_DESC_DED_WIDTH 1 |
989 | #define XP_ECC_IER_DESC_SEC_INDEX 1 | 989 | #define XP_ECC_IER_DESC_SEC_INDEX 4 |
990 | #define XP_ECC_IER_DESC_SEC_WIDTH 1 | 990 | #define XP_ECC_IER_DESC_SEC_WIDTH 1 |
991 | #define XP_ECC_IER_RX_DED_INDEX 2 | 991 | #define XP_ECC_IER_RX_DED_INDEX 3 |
992 | #define XP_ECC_IER_RX_DED_WIDTH 1 | 992 | #define XP_ECC_IER_RX_DED_WIDTH 1 |
993 | #define XP_ECC_IER_RX_SEC_INDEX 3 | 993 | #define XP_ECC_IER_RX_SEC_INDEX 2 |
994 | #define XP_ECC_IER_RX_SEC_WIDTH 1 | 994 | #define XP_ECC_IER_RX_SEC_WIDTH 1 |
995 | #define XP_ECC_IER_TX_DED_INDEX 4 | 995 | #define XP_ECC_IER_TX_DED_INDEX 1 |
996 | #define XP_ECC_IER_TX_DED_WIDTH 1 | 996 | #define XP_ECC_IER_TX_DED_WIDTH 1 |
997 | #define XP_ECC_IER_TX_SEC_INDEX 5 | 997 | #define XP_ECC_IER_TX_SEC_INDEX 0 |
998 | #define XP_ECC_IER_TX_SEC_WIDTH 1 | 998 | #define XP_ECC_IER_TX_SEC_WIDTH 1 |
999 | #define XP_ECC_ISR_DESC_DED_INDEX 0 | 999 | #define XP_ECC_ISR_DESC_DED_INDEX 5 |
1000 | #define XP_ECC_ISR_DESC_DED_WIDTH 1 | 1000 | #define XP_ECC_ISR_DESC_DED_WIDTH 1 |
1001 | #define XP_ECC_ISR_DESC_SEC_INDEX 1 | 1001 | #define XP_ECC_ISR_DESC_SEC_INDEX 4 |
1002 | #define XP_ECC_ISR_DESC_SEC_WIDTH 1 | 1002 | #define XP_ECC_ISR_DESC_SEC_WIDTH 1 |
1003 | #define XP_ECC_ISR_RX_DED_INDEX 2 | 1003 | #define XP_ECC_ISR_RX_DED_INDEX 3 |
1004 | #define XP_ECC_ISR_RX_DED_WIDTH 1 | 1004 | #define XP_ECC_ISR_RX_DED_WIDTH 1 |
1005 | #define XP_ECC_ISR_RX_SEC_INDEX 3 | 1005 | #define XP_ECC_ISR_RX_SEC_INDEX 2 |
1006 | #define XP_ECC_ISR_RX_SEC_WIDTH 1 | 1006 | #define XP_ECC_ISR_RX_SEC_WIDTH 1 |
1007 | #define XP_ECC_ISR_TX_DED_INDEX 4 | 1007 | #define XP_ECC_ISR_TX_DED_INDEX 1 |
1008 | #define XP_ECC_ISR_TX_DED_WIDTH 1 | 1008 | #define XP_ECC_ISR_TX_DED_WIDTH 1 |
1009 | #define XP_ECC_ISR_TX_SEC_INDEX 5 | 1009 | #define XP_ECC_ISR_TX_SEC_INDEX 0 |
1010 | #define XP_ECC_ISR_TX_SEC_WIDTH 1 | 1010 | #define XP_ECC_ISR_TX_SEC_WIDTH 1 |
1011 | #define XP_I2C_MUTEX_BUSY_INDEX 31 | 1011 | #define XP_I2C_MUTEX_BUSY_INDEX 31 |
1012 | #define XP_I2C_MUTEX_BUSY_WIDTH 1 | 1012 | #define XP_I2C_MUTEX_BUSY_WIDTH 1 |
@@ -1148,8 +1148,8 @@ | |||
1148 | #define RX_PACKET_ATTRIBUTES_CSUM_DONE_WIDTH 1 | 1148 | #define RX_PACKET_ATTRIBUTES_CSUM_DONE_WIDTH 1 |
1149 | #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX 1 | 1149 | #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX 1 |
1150 | #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH 1 | 1150 | #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH 1 |
1151 | #define RX_PACKET_ATTRIBUTES_INCOMPLETE_INDEX 2 | 1151 | #define RX_PACKET_ATTRIBUTES_LAST_INDEX 2 |
1152 | #define RX_PACKET_ATTRIBUTES_INCOMPLETE_WIDTH 1 | 1152 | #define RX_PACKET_ATTRIBUTES_LAST_WIDTH 1 |
1153 | #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_INDEX 3 | 1153 | #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_INDEX 3 |
1154 | #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_WIDTH 1 | 1154 | #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_WIDTH 1 |
1155 | #define RX_PACKET_ATTRIBUTES_CONTEXT_INDEX 4 | 1155 | #define RX_PACKET_ATTRIBUTES_CONTEXT_INDEX 4 |
@@ -1158,6 +1158,8 @@ | |||
1158 | #define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH 1 | 1158 | #define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH 1 |
1159 | #define RX_PACKET_ATTRIBUTES_RSS_HASH_INDEX 6 | 1159 | #define RX_PACKET_ATTRIBUTES_RSS_HASH_INDEX 6 |
1160 | #define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH 1 | 1160 | #define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH 1 |
1161 | #define RX_PACKET_ATTRIBUTES_FIRST_INDEX 7 | ||
1162 | #define RX_PACKET_ATTRIBUTES_FIRST_WIDTH 1 | ||
1161 | 1163 | ||
1162 | #define RX_NORMAL_DESC0_OVT_INDEX 0 | 1164 | #define RX_NORMAL_DESC0_OVT_INDEX 0 |
1163 | #define RX_NORMAL_DESC0_OVT_WIDTH 16 | 1165 | #define RX_NORMAL_DESC0_OVT_WIDTH 16 |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 937f37a5dcb2..24a687ce4388 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c | |||
@@ -1896,10 +1896,15 @@ static int xgbe_dev_read(struct xgbe_channel *channel) | |||
1896 | 1896 | ||
1897 | /* Get the header length */ | 1897 | /* Get the header length */ |
1898 | if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD)) { | 1898 | if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD)) { |
1899 | XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, | ||
1900 | FIRST, 1); | ||
1899 | rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2, | 1901 | rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2, |
1900 | RX_NORMAL_DESC2, HL); | 1902 | RX_NORMAL_DESC2, HL); |
1901 | if (rdata->rx.hdr_len) | 1903 | if (rdata->rx.hdr_len) |
1902 | pdata->ext_stats.rx_split_header_packets++; | 1904 | pdata->ext_stats.rx_split_header_packets++; |
1905 | } else { | ||
1906 | XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, | ||
1907 | FIRST, 0); | ||
1903 | } | 1908 | } |
1904 | 1909 | ||
1905 | /* Get the RSS hash */ | 1910 | /* Get the RSS hash */ |
@@ -1922,19 +1927,16 @@ static int xgbe_dev_read(struct xgbe_channel *channel) | |||
1922 | } | 1927 | } |
1923 | } | 1928 | } |
1924 | 1929 | ||
1925 | /* Get the packet length */ | 1930 | /* Not all the data has been transferred for this packet */ |
1926 | rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); | 1931 | if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) |
1927 | |||
1928 | if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) { | ||
1929 | /* Not all the data has been transferred for this packet */ | ||
1930 | XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, | ||
1931 | INCOMPLETE, 1); | ||
1932 | return 0; | 1932 | return 0; |
1933 | } | ||
1934 | 1933 | ||
1935 | /* This is the last of the data for this packet */ | 1934 | /* This is the last of the data for this packet */ |
1936 | XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, | 1935 | XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, |
1937 | INCOMPLETE, 0); | 1936 | LAST, 1); |
1937 | |||
1938 | /* Get the packet length */ | ||
1939 | rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); | ||
1938 | 1940 | ||
1939 | /* Set checksum done indicator as appropriate */ | 1941 | /* Set checksum done indicator as appropriate */ |
1940 | if (netdev->features & NETIF_F_RXCSUM) | 1942 | if (netdev->features & NETIF_F_RXCSUM) |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index ffea9859f5a7..a713abd9d03e 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c | |||
@@ -1971,13 +1971,12 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata, | |||
1971 | { | 1971 | { |
1972 | struct sk_buff *skb; | 1972 | struct sk_buff *skb; |
1973 | u8 *packet; | 1973 | u8 *packet; |
1974 | unsigned int copy_len; | ||
1975 | 1974 | ||
1976 | skb = napi_alloc_skb(napi, rdata->rx.hdr.dma_len); | 1975 | skb = napi_alloc_skb(napi, rdata->rx.hdr.dma_len); |
1977 | if (!skb) | 1976 | if (!skb) |
1978 | return NULL; | 1977 | return NULL; |
1979 | 1978 | ||
1980 | /* Start with the header buffer which may contain just the header | 1979 | /* Pull in the header buffer which may contain just the header |
1981 | * or the header plus data | 1980 | * or the header plus data |
1982 | */ | 1981 | */ |
1983 | dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.hdr.dma_base, | 1982 | dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.hdr.dma_base, |
@@ -1986,30 +1985,49 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata, | |||
1986 | 1985 | ||
1987 | packet = page_address(rdata->rx.hdr.pa.pages) + | 1986 | packet = page_address(rdata->rx.hdr.pa.pages) + |
1988 | rdata->rx.hdr.pa.pages_offset; | 1987 | rdata->rx.hdr.pa.pages_offset; |
1989 | copy_len = (rdata->rx.hdr_len) ? rdata->rx.hdr_len : len; | 1988 | skb_copy_to_linear_data(skb, packet, len); |
1990 | copy_len = min(rdata->rx.hdr.dma_len, copy_len); | 1989 | skb_put(skb, len); |
1991 | skb_copy_to_linear_data(skb, packet, copy_len); | ||
1992 | skb_put(skb, copy_len); | ||
1993 | |||
1994 | len -= copy_len; | ||
1995 | if (len) { | ||
1996 | /* Add the remaining data as a frag */ | ||
1997 | dma_sync_single_range_for_cpu(pdata->dev, | ||
1998 | rdata->rx.buf.dma_base, | ||
1999 | rdata->rx.buf.dma_off, | ||
2000 | rdata->rx.buf.dma_len, | ||
2001 | DMA_FROM_DEVICE); | ||
2002 | |||
2003 | skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, | ||
2004 | rdata->rx.buf.pa.pages, | ||
2005 | rdata->rx.buf.pa.pages_offset, | ||
2006 | len, rdata->rx.buf.dma_len); | ||
2007 | rdata->rx.buf.pa.pages = NULL; | ||
2008 | } | ||
2009 | 1990 | ||
2010 | return skb; | 1991 | return skb; |
2011 | } | 1992 | } |
2012 | 1993 | ||
1994 | static unsigned int xgbe_rx_buf1_len(struct xgbe_ring_data *rdata, | ||
1995 | struct xgbe_packet_data *packet) | ||
1996 | { | ||
1997 | /* Always zero if not the first descriptor */ | ||
1998 | if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, FIRST)) | ||
1999 | return 0; | ||
2000 | |||
2001 | /* First descriptor with split header, return header length */ | ||
2002 | if (rdata->rx.hdr_len) | ||
2003 | return rdata->rx.hdr_len; | ||
2004 | |||
2005 | /* First descriptor but not the last descriptor and no split header, | ||
2006 | * so the full buffer was used | ||
2007 | */ | ||
2008 | if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST)) | ||
2009 | return rdata->rx.hdr.dma_len; | ||
2010 | |||
2011 | /* First descriptor and last descriptor and no split header, so | ||
2012 | * calculate how much of the buffer was used | ||
2013 | */ | ||
2014 | return min_t(unsigned int, rdata->rx.hdr.dma_len, rdata->rx.len); | ||
2015 | } | ||
2016 | |||
2017 | static unsigned int xgbe_rx_buf2_len(struct xgbe_ring_data *rdata, | ||
2018 | struct xgbe_packet_data *packet, | ||
2019 | unsigned int len) | ||
2020 | { | ||
2021 | /* Always the full buffer if not the last descriptor */ | ||
2022 | if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST)) | ||
2023 | return rdata->rx.buf.dma_len; | ||
2024 | |||
2025 | /* Last descriptor so calculate how much of the buffer was used | ||
2026 | * for the last bit of data | ||
2027 | */ | ||
2028 | return rdata->rx.len - len; | ||
2029 | } | ||
2030 | |||
2013 | static int xgbe_tx_poll(struct xgbe_channel *channel) | 2031 | static int xgbe_tx_poll(struct xgbe_channel *channel) |
2014 | { | 2032 | { |
2015 | struct xgbe_prv_data *pdata = channel->pdata; | 2033 | struct xgbe_prv_data *pdata = channel->pdata; |
@@ -2092,8 +2110,8 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) | |||
2092 | struct napi_struct *napi; | 2110 | struct napi_struct *napi; |
2093 | struct sk_buff *skb; | 2111 | struct sk_buff *skb; |
2094 | struct skb_shared_hwtstamps *hwtstamps; | 2112 | struct skb_shared_hwtstamps *hwtstamps; |
2095 | unsigned int incomplete, error, context_next, context; | 2113 | unsigned int last, error, context_next, context; |
2096 | unsigned int len, rdesc_len, max_len; | 2114 | unsigned int len, buf1_len, buf2_len, max_len; |
2097 | unsigned int received = 0; | 2115 | unsigned int received = 0; |
2098 | int packet_count = 0; | 2116 | int packet_count = 0; |
2099 | 2117 | ||
@@ -2103,7 +2121,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) | |||
2103 | if (!ring) | 2121 | if (!ring) |
2104 | return 0; | 2122 | return 0; |
2105 | 2123 | ||
2106 | incomplete = 0; | 2124 | last = 0; |
2107 | context_next = 0; | 2125 | context_next = 0; |
2108 | 2126 | ||
2109 | napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; | 2127 | napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; |
@@ -2137,9 +2155,8 @@ read_again: | |||
2137 | received++; | 2155 | received++; |
2138 | ring->cur++; | 2156 | ring->cur++; |
2139 | 2157 | ||
2140 | incomplete = XGMAC_GET_BITS(packet->attributes, | 2158 | last = XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, |
2141 | RX_PACKET_ATTRIBUTES, | 2159 | LAST); |
2142 | INCOMPLETE); | ||
2143 | context_next = XGMAC_GET_BITS(packet->attributes, | 2160 | context_next = XGMAC_GET_BITS(packet->attributes, |
2144 | RX_PACKET_ATTRIBUTES, | 2161 | RX_PACKET_ATTRIBUTES, |
2145 | CONTEXT_NEXT); | 2162 | CONTEXT_NEXT); |
@@ -2148,7 +2165,7 @@ read_again: | |||
2148 | CONTEXT); | 2165 | CONTEXT); |
2149 | 2166 | ||
2150 | /* Earlier error, just drain the remaining data */ | 2167 | /* Earlier error, just drain the remaining data */ |
2151 | if ((incomplete || context_next) && error) | 2168 | if ((!last || context_next) && error) |
2152 | goto read_again; | 2169 | goto read_again; |
2153 | 2170 | ||
2154 | if (error || packet->errors) { | 2171 | if (error || packet->errors) { |
@@ -2160,16 +2177,22 @@ read_again: | |||
2160 | } | 2177 | } |
2161 | 2178 | ||
2162 | if (!context) { | 2179 | if (!context) { |
2163 | /* Length is cumulative, get this descriptor's length */ | 2180 | /* Get the data length in the descriptor buffers */ |
2164 | rdesc_len = rdata->rx.len - len; | 2181 | buf1_len = xgbe_rx_buf1_len(rdata, packet); |
2165 | len += rdesc_len; | 2182 | len += buf1_len; |
2183 | buf2_len = xgbe_rx_buf2_len(rdata, packet, len); | ||
2184 | len += buf2_len; | ||
2166 | 2185 | ||
2167 | if (rdesc_len && !skb) { | 2186 | if (!skb) { |
2168 | skb = xgbe_create_skb(pdata, napi, rdata, | 2187 | skb = xgbe_create_skb(pdata, napi, rdata, |
2169 | rdesc_len); | 2188 | buf1_len); |
2170 | if (!skb) | 2189 | if (!skb) { |
2171 | error = 1; | 2190 | error = 1; |
2172 | } else if (rdesc_len) { | 2191 | goto skip_data; |
2192 | } | ||
2193 | } | ||
2194 | |||
2195 | if (buf2_len) { | ||
2173 | dma_sync_single_range_for_cpu(pdata->dev, | 2196 | dma_sync_single_range_for_cpu(pdata->dev, |
2174 | rdata->rx.buf.dma_base, | 2197 | rdata->rx.buf.dma_base, |
2175 | rdata->rx.buf.dma_off, | 2198 | rdata->rx.buf.dma_off, |
@@ -2179,13 +2202,14 @@ read_again: | |||
2179 | skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, | 2202 | skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, |
2180 | rdata->rx.buf.pa.pages, | 2203 | rdata->rx.buf.pa.pages, |
2181 | rdata->rx.buf.pa.pages_offset, | 2204 | rdata->rx.buf.pa.pages_offset, |
2182 | rdesc_len, | 2205 | buf2_len, |
2183 | rdata->rx.buf.dma_len); | 2206 | rdata->rx.buf.dma_len); |
2184 | rdata->rx.buf.pa.pages = NULL; | 2207 | rdata->rx.buf.pa.pages = NULL; |
2185 | } | 2208 | } |
2186 | } | 2209 | } |
2187 | 2210 | ||
2188 | if (incomplete || context_next) | 2211 | skip_data: |
2212 | if (!last || context_next) | ||
2189 | goto read_again; | 2213 | goto read_again; |
2190 | 2214 | ||
2191 | if (!skb) | 2215 | if (!skb) |
@@ -2243,7 +2267,7 @@ next_packet: | |||
2243 | } | 2267 | } |
2244 | 2268 | ||
2245 | /* Check if we need to save state before leaving */ | 2269 | /* Check if we need to save state before leaving */ |
2246 | if (received && (incomplete || context_next)) { | 2270 | if (received && (!last || context_next)) { |
2247 | rdata = XGBE_GET_DESC_DATA(ring, ring->cur); | 2271 | rdata = XGBE_GET_DESC_DATA(ring, ring->cur); |
2248 | rdata->state_saved = 1; | 2272 | rdata->state_saved = 1; |
2249 | rdata->state.skb = skb; | 2273 | rdata->state.skb = skb; |
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c index dad63623be6a..d05fbfdce5e5 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c | |||
@@ -98,6 +98,7 @@ static int aq_ndev_change_mtu(struct net_device *ndev, int new_mtu) | |||
98 | 98 | ||
99 | if (err < 0) | 99 | if (err < 0) |
100 | goto err_exit; | 100 | goto err_exit; |
101 | ndev->mtu = new_mtu; | ||
101 | 102 | ||
102 | if (netif_running(ndev)) { | 103 | if (netif_running(ndev)) { |
103 | aq_ndev_close(ndev); | 104 | aq_ndev_close(ndev); |
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h index 1093ea18823a..0592a0330cf0 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h | |||
@@ -137,6 +137,7 @@ static struct aq_hw_caps_s hw_atl_a0_hw_caps_ = { | |||
137 | .tx_rings = HW_ATL_A0_TX_RINGS, | 137 | .tx_rings = HW_ATL_A0_TX_RINGS, |
138 | .rx_rings = HW_ATL_A0_RX_RINGS, | 138 | .rx_rings = HW_ATL_A0_RX_RINGS, |
139 | .hw_features = NETIF_F_HW_CSUM | | 139 | .hw_features = NETIF_F_HW_CSUM | |
140 | NETIF_F_RXCSUM | | ||
140 | NETIF_F_RXHASH | | 141 | NETIF_F_RXHASH | |
141 | NETIF_F_SG | | 142 | NETIF_F_SG | |
142 | NETIF_F_TSO, | 143 | NETIF_F_TSO, |
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h index 8bdee3ddd5a0..f3957e930340 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h | |||
@@ -188,6 +188,7 @@ static struct aq_hw_caps_s hw_atl_b0_hw_caps_ = { | |||
188 | .tx_rings = HW_ATL_B0_TX_RINGS, | 188 | .tx_rings = HW_ATL_B0_TX_RINGS, |
189 | .rx_rings = HW_ATL_B0_RX_RINGS, | 189 | .rx_rings = HW_ATL_B0_RX_RINGS, |
190 | .hw_features = NETIF_F_HW_CSUM | | 190 | .hw_features = NETIF_F_HW_CSUM | |
191 | NETIF_F_RXCSUM | | ||
191 | NETIF_F_RXHASH | | 192 | NETIF_F_RXHASH | |
192 | NETIF_F_SG | | 193 | NETIF_F_SG | |
193 | NETIF_F_TSO | | 194 | NETIF_F_TSO | |
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 69015fa50f20..365895ed3c3e 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c | |||
@@ -3481,7 +3481,8 @@ static int bcmgenet_suspend(struct device *d) | |||
3481 | 3481 | ||
3482 | bcmgenet_netif_stop(dev); | 3482 | bcmgenet_netif_stop(dev); |
3483 | 3483 | ||
3484 | phy_suspend(priv->phydev); | 3484 | if (!device_may_wakeup(d)) |
3485 | phy_suspend(priv->phydev); | ||
3485 | 3486 | ||
3486 | netif_device_detach(dev); | 3487 | netif_device_detach(dev); |
3487 | 3488 | ||
@@ -3578,7 +3579,8 @@ static int bcmgenet_resume(struct device *d) | |||
3578 | 3579 | ||
3579 | netif_device_attach(dev); | 3580 | netif_device_attach(dev); |
3580 | 3581 | ||
3581 | phy_resume(priv->phydev); | 3582 | if (!device_may_wakeup(d)) |
3583 | phy_resume(priv->phydev); | ||
3582 | 3584 | ||
3583 | if (priv->eee.eee_enabled) | 3585 | if (priv->eee.eee_enabled) |
3584 | bcmgenet_eee_enable_set(dev, true); | 3586 | bcmgenet_eee_enable_set(dev, true); |
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index e87607621e62..2f9281936f0e 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c | |||
@@ -220,20 +220,6 @@ void bcmgenet_phy_power_set(struct net_device *dev, bool enable) | |||
220 | udelay(60); | 220 | udelay(60); |
221 | } | 221 | } |
222 | 222 | ||
223 | static void bcmgenet_internal_phy_setup(struct net_device *dev) | ||
224 | { | ||
225 | struct bcmgenet_priv *priv = netdev_priv(dev); | ||
226 | u32 reg; | ||
227 | |||
228 | /* Power up PHY */ | ||
229 | bcmgenet_phy_power_set(dev, true); | ||
230 | /* enable APD */ | ||
231 | reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT); | ||
232 | reg |= EXT_PWR_DN_EN_LD; | ||
233 | bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT); | ||
234 | bcmgenet_mii_reset(dev); | ||
235 | } | ||
236 | |||
237 | static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv) | 223 | static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv) |
238 | { | 224 | { |
239 | u32 reg; | 225 | u32 reg; |
@@ -281,7 +267,6 @@ int bcmgenet_mii_config(struct net_device *dev) | |||
281 | 267 | ||
282 | if (priv->internal_phy) { | 268 | if (priv->internal_phy) { |
283 | phy_name = "internal PHY"; | 269 | phy_name = "internal PHY"; |
284 | bcmgenet_internal_phy_setup(dev); | ||
285 | } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) { | 270 | } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) { |
286 | phy_name = "MoCA"; | 271 | phy_name = "MoCA"; |
287 | bcmgenet_moca_phy_setup(priv); | 272 | bcmgenet_moca_phy_setup(priv); |
diff --git a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c index 05c1c1dd7751..cebfe3bd086e 100644 --- a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c +++ b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c | |||
@@ -325,7 +325,7 @@ bnad_debugfs_write_regrd(struct file *file, const char __user *buf, | |||
325 | return PTR_ERR(kern_buf); | 325 | return PTR_ERR(kern_buf); |
326 | 326 | ||
327 | rc = sscanf(kern_buf, "%x:%x", &addr, &len); | 327 | rc = sscanf(kern_buf, "%x:%x", &addr, &len); |
328 | if (rc < 2) { | 328 | if (rc < 2 || len > UINT_MAX >> 2) { |
329 | netdev_warn(bnad->netdev, "failed to read user buffer\n"); | 329 | netdev_warn(bnad->netdev, "failed to read user buffer\n"); |
330 | kfree(kern_buf); | 330 | kfree(kern_buf); |
331 | return -EINVAL; | 331 | return -EINVAL; |
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 5f11b4dc95d2..b23d6545f835 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c | |||
@@ -1257,6 +1257,7 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter) | |||
1257 | release_sub_crq_queue(adapter, | 1257 | release_sub_crq_queue(adapter, |
1258 | adapter->tx_scrq[i]); | 1258 | adapter->tx_scrq[i]); |
1259 | } | 1259 | } |
1260 | kfree(adapter->tx_scrq); | ||
1260 | adapter->tx_scrq = NULL; | 1261 | adapter->tx_scrq = NULL; |
1261 | } | 1262 | } |
1262 | 1263 | ||
@@ -1269,6 +1270,7 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter) | |||
1269 | release_sub_crq_queue(adapter, | 1270 | release_sub_crq_queue(adapter, |
1270 | adapter->rx_scrq[i]); | 1271 | adapter->rx_scrq[i]); |
1271 | } | 1272 | } |
1273 | kfree(adapter->rx_scrq); | ||
1272 | adapter->rx_scrq = NULL; | 1274 | adapter->rx_scrq = NULL; |
1273 | } | 1275 | } |
1274 | } | 1276 | } |
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index e8c105164931..0e0fa7030565 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c | |||
@@ -2305,6 +2305,17 @@ static int sync_toggles(struct mlx4_dev *dev) | |||
2305 | rd_toggle = swab32(readl(&priv->mfunc.comm->slave_read)); | 2305 | rd_toggle = swab32(readl(&priv->mfunc.comm->slave_read)); |
2306 | if (wr_toggle == 0xffffffff || rd_toggle == 0xffffffff) { | 2306 | if (wr_toggle == 0xffffffff || rd_toggle == 0xffffffff) { |
2307 | /* PCI might be offline */ | 2307 | /* PCI might be offline */ |
2308 | |||
2309 | /* If device removal has been requested, | ||
2310 | * do not continue retrying. | ||
2311 | */ | ||
2312 | if (dev->persist->interface_state & | ||
2313 | MLX4_INTERFACE_STATE_NOWAIT) { | ||
2314 | mlx4_warn(dev, | ||
2315 | "communication channel is offline\n"); | ||
2316 | return -EIO; | ||
2317 | } | ||
2318 | |||
2308 | msleep(100); | 2319 | msleep(100); |
2309 | wr_toggle = swab32(readl(&priv->mfunc.comm-> | 2320 | wr_toggle = swab32(readl(&priv->mfunc.comm-> |
2310 | slave_write)); | 2321 | slave_write)); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 21377c315083..703205475524 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -1940,6 +1940,14 @@ static int mlx4_comm_check_offline(struct mlx4_dev *dev) | |||
1940 | (u32)(1 << COMM_CHAN_OFFLINE_OFFSET)); | 1940 | (u32)(1 << COMM_CHAN_OFFLINE_OFFSET)); |
1941 | if (!offline_bit) | 1941 | if (!offline_bit) |
1942 | return 0; | 1942 | return 0; |
1943 | |||
1944 | /* If device removal has been requested, | ||
1945 | * do not continue retrying. | ||
1946 | */ | ||
1947 | if (dev->persist->interface_state & | ||
1948 | MLX4_INTERFACE_STATE_NOWAIT) | ||
1949 | break; | ||
1950 | |||
1943 | /* There are cases as part of AER/Reset flow that PF needs | 1951 | /* There are cases as part of AER/Reset flow that PF needs |
1944 | * around 100 msec to load. We therefore sleep for 100 msec | 1952 | * around 100 msec to load. We therefore sleep for 100 msec |
1945 | * to allow other tasks to make use of that CPU during this | 1953 | * to allow other tasks to make use of that CPU during this |
@@ -3955,6 +3963,9 @@ static void mlx4_remove_one(struct pci_dev *pdev) | |||
3955 | struct devlink *devlink = priv_to_devlink(priv); | 3963 | struct devlink *devlink = priv_to_devlink(priv); |
3956 | int active_vfs = 0; | 3964 | int active_vfs = 0; |
3957 | 3965 | ||
3966 | if (mlx4_is_slave(dev)) | ||
3967 | persist->interface_state |= MLX4_INTERFACE_STATE_NOWAIT; | ||
3968 | |||
3958 | mutex_lock(&persist->interface_state_mutex); | 3969 | mutex_lock(&persist->interface_state_mutex); |
3959 | persist->interface_state |= MLX4_INTERFACE_STATE_DELETION; | 3970 | persist->interface_state |= MLX4_INTERFACE_STATE_DELETION; |
3960 | mutex_unlock(&persist->interface_state_mutex); | 3971 | mutex_unlock(&persist->interface_state_mutex); |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index caa837e5e2b9..a380353a78c2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c | |||
@@ -361,6 +361,8 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, | |||
361 | case MLX5_CMD_OP_QUERY_VPORT_COUNTER: | 361 | case MLX5_CMD_OP_QUERY_VPORT_COUNTER: |
362 | case MLX5_CMD_OP_ALLOC_Q_COUNTER: | 362 | case MLX5_CMD_OP_ALLOC_Q_COUNTER: |
363 | case MLX5_CMD_OP_QUERY_Q_COUNTER: | 363 | case MLX5_CMD_OP_QUERY_Q_COUNTER: |
364 | case MLX5_CMD_OP_SET_RATE_LIMIT: | ||
365 | case MLX5_CMD_OP_QUERY_RATE_LIMIT: | ||
364 | case MLX5_CMD_OP_ALLOC_PD: | 366 | case MLX5_CMD_OP_ALLOC_PD: |
365 | case MLX5_CMD_OP_ALLOC_UAR: | 367 | case MLX5_CMD_OP_ALLOC_UAR: |
366 | case MLX5_CMD_OP_CONFIG_INT_MODERATION: | 368 | case MLX5_CMD_OP_CONFIG_INT_MODERATION: |
@@ -497,6 +499,8 @@ const char *mlx5_command_str(int command) | |||
497 | MLX5_COMMAND_STR_CASE(ALLOC_Q_COUNTER); | 499 | MLX5_COMMAND_STR_CASE(ALLOC_Q_COUNTER); |
498 | MLX5_COMMAND_STR_CASE(DEALLOC_Q_COUNTER); | 500 | MLX5_COMMAND_STR_CASE(DEALLOC_Q_COUNTER); |
499 | MLX5_COMMAND_STR_CASE(QUERY_Q_COUNTER); | 501 | MLX5_COMMAND_STR_CASE(QUERY_Q_COUNTER); |
502 | MLX5_COMMAND_STR_CASE(SET_RATE_LIMIT); | ||
503 | MLX5_COMMAND_STR_CASE(QUERY_RATE_LIMIT); | ||
500 | MLX5_COMMAND_STR_CASE(ALLOC_PD); | 504 | MLX5_COMMAND_STR_CASE(ALLOC_PD); |
501 | MLX5_COMMAND_STR_CASE(DEALLOC_PD); | 505 | MLX5_COMMAND_STR_CASE(DEALLOC_PD); |
502 | MLX5_COMMAND_STR_CASE(ALLOC_UAR); | 506 | MLX5_COMMAND_STR_CASE(ALLOC_UAR); |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index f6a6ded204f6..dc52053128bc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h | |||
@@ -928,10 +928,6 @@ void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, struct mlx5e_priv *priv); | |||
928 | int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev); | 928 | int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev); |
929 | void mlx5e_detach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev); | 929 | void mlx5e_detach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev); |
930 | u32 mlx5e_choose_lro_timeout(struct mlx5_core_dev *mdev, u32 wanted_timeout); | 930 | u32 mlx5e_choose_lro_timeout(struct mlx5_core_dev *mdev, u32 wanted_timeout); |
931 | void mlx5e_add_vxlan_port(struct net_device *netdev, | ||
932 | struct udp_tunnel_info *ti); | ||
933 | void mlx5e_del_vxlan_port(struct net_device *netdev, | ||
934 | struct udp_tunnel_info *ti); | ||
935 | 931 | ||
936 | int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev, | 932 | int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev, |
937 | void *sp); | 933 | void *sp); |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 8ef64c4db2c2..66c133757a5e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c | |||
@@ -3100,8 +3100,8 @@ static int mlx5e_get_vf_stats(struct net_device *dev, | |||
3100 | vf_stats); | 3100 | vf_stats); |
3101 | } | 3101 | } |
3102 | 3102 | ||
3103 | void mlx5e_add_vxlan_port(struct net_device *netdev, | 3103 | static void mlx5e_add_vxlan_port(struct net_device *netdev, |
3104 | struct udp_tunnel_info *ti) | 3104 | struct udp_tunnel_info *ti) |
3105 | { | 3105 | { |
3106 | struct mlx5e_priv *priv = netdev_priv(netdev); | 3106 | struct mlx5e_priv *priv = netdev_priv(netdev); |
3107 | 3107 | ||
@@ -3114,8 +3114,8 @@ void mlx5e_add_vxlan_port(struct net_device *netdev, | |||
3114 | mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 1); | 3114 | mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 1); |
3115 | } | 3115 | } |
3116 | 3116 | ||
3117 | void mlx5e_del_vxlan_port(struct net_device *netdev, | 3117 | static void mlx5e_del_vxlan_port(struct net_device *netdev, |
3118 | struct udp_tunnel_info *ti) | 3118 | struct udp_tunnel_info *ti) |
3119 | { | 3119 | { |
3120 | struct mlx5e_priv *priv = netdev_priv(netdev); | 3120 | struct mlx5e_priv *priv = netdev_priv(netdev); |
3121 | 3121 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 2c864574a9d5..f621373bd7a5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | |||
@@ -393,8 +393,6 @@ static const struct net_device_ops mlx5e_netdev_ops_rep = { | |||
393 | .ndo_get_phys_port_name = mlx5e_rep_get_phys_port_name, | 393 | .ndo_get_phys_port_name = mlx5e_rep_get_phys_port_name, |
394 | .ndo_setup_tc = mlx5e_rep_ndo_setup_tc, | 394 | .ndo_setup_tc = mlx5e_rep_ndo_setup_tc, |
395 | .ndo_get_stats64 = mlx5e_rep_get_stats, | 395 | .ndo_get_stats64 = mlx5e_rep_get_stats, |
396 | .ndo_udp_tunnel_add = mlx5e_add_vxlan_port, | ||
397 | .ndo_udp_tunnel_del = mlx5e_del_vxlan_port, | ||
398 | .ndo_has_offload_stats = mlx5e_has_offload_stats, | 396 | .ndo_has_offload_stats = mlx5e_has_offload_stats, |
399 | .ndo_get_offload_stats = mlx5e_get_offload_stats, | 397 | .ndo_get_offload_stats = mlx5e_get_offload_stats, |
400 | }; | 398 | }; |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 3d371688fbbb..bafcb349a50c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | |||
@@ -601,6 +601,10 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe, | |||
601 | if (lro_num_seg > 1) { | 601 | if (lro_num_seg > 1) { |
602 | mlx5e_lro_update_hdr(skb, cqe, cqe_bcnt); | 602 | mlx5e_lro_update_hdr(skb, cqe, cqe_bcnt); |
603 | skb_shinfo(skb)->gso_size = DIV_ROUND_UP(cqe_bcnt, lro_num_seg); | 603 | skb_shinfo(skb)->gso_size = DIV_ROUND_UP(cqe_bcnt, lro_num_seg); |
604 | /* Subtract one since we already counted this as one | ||
605 | * "regular" packet in mlx5e_complete_rx_cqe() | ||
606 | */ | ||
607 | rq->stats.packets += lro_num_seg - 1; | ||
604 | rq->stats.lro_packets++; | 608 | rq->stats.lro_packets++; |
605 | rq->stats.lro_bytes += cqe_bcnt; | 609 | rq->stats.lro_bytes += cqe_bcnt; |
606 | } | 610 | } |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 79481f4cf264..fade7233dac5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | |||
@@ -133,6 +133,23 @@ err_create_ft: | |||
133 | return rule; | 133 | return rule; |
134 | } | 134 | } |
135 | 135 | ||
136 | static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv, | ||
137 | struct mlx5e_tc_flow *flow) | ||
138 | { | ||
139 | struct mlx5_fc *counter = NULL; | ||
140 | |||
141 | if (!IS_ERR(flow->rule)) { | ||
142 | counter = mlx5_flow_rule_counter(flow->rule); | ||
143 | mlx5_del_flow_rules(flow->rule); | ||
144 | mlx5_fc_destroy(priv->mdev, counter); | ||
145 | } | ||
146 | |||
147 | if (!mlx5e_tc_num_filters(priv) && (priv->fs.tc.t)) { | ||
148 | mlx5_destroy_flow_table(priv->fs.tc.t); | ||
149 | priv->fs.tc.t = NULL; | ||
150 | } | ||
151 | } | ||
152 | |||
136 | static struct mlx5_flow_handle * | 153 | static struct mlx5_flow_handle * |
137 | mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, | 154 | mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, |
138 | struct mlx5_flow_spec *spec, | 155 | struct mlx5_flow_spec *spec, |
@@ -149,7 +166,24 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, | |||
149 | } | 166 | } |
150 | 167 | ||
151 | static void mlx5e_detach_encap(struct mlx5e_priv *priv, | 168 | static void mlx5e_detach_encap(struct mlx5e_priv *priv, |
152 | struct mlx5e_tc_flow *flow) { | 169 | struct mlx5e_tc_flow *flow); |
170 | |||
171 | static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, | ||
172 | struct mlx5e_tc_flow *flow) | ||
173 | { | ||
174 | struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; | ||
175 | |||
176 | mlx5_eswitch_del_offloaded_rule(esw, flow->rule, flow->attr); | ||
177 | |||
178 | mlx5_eswitch_del_vlan_action(esw, flow->attr); | ||
179 | |||
180 | if (flow->attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP) | ||
181 | mlx5e_detach_encap(priv, flow); | ||
182 | } | ||
183 | |||
184 | static void mlx5e_detach_encap(struct mlx5e_priv *priv, | ||
185 | struct mlx5e_tc_flow *flow) | ||
186 | { | ||
153 | struct list_head *next = flow->encap.next; | 187 | struct list_head *next = flow->encap.next; |
154 | 188 | ||
155 | list_del(&flow->encap); | 189 | list_del(&flow->encap); |
@@ -173,25 +207,10 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv, | |||
173 | static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, | 207 | static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, |
174 | struct mlx5e_tc_flow *flow) | 208 | struct mlx5e_tc_flow *flow) |
175 | { | 209 | { |
176 | struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; | 210 | if (flow->flags & MLX5E_TC_FLOW_ESWITCH) |
177 | struct mlx5_fc *counter = NULL; | 211 | mlx5e_tc_del_fdb_flow(priv, flow); |
178 | 212 | else | |
179 | if (!IS_ERR(flow->rule)) { | 213 | mlx5e_tc_del_nic_flow(priv, flow); |
180 | counter = mlx5_flow_rule_counter(flow->rule); | ||
181 | mlx5_del_flow_rules(flow->rule); | ||
182 | mlx5_fc_destroy(priv->mdev, counter); | ||
183 | } | ||
184 | |||
185 | if (flow->flags & MLX5E_TC_FLOW_ESWITCH) { | ||
186 | mlx5_eswitch_del_vlan_action(esw, flow->attr); | ||
187 | if (flow->attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP) | ||
188 | mlx5e_detach_encap(priv, flow); | ||
189 | } | ||
190 | |||
191 | if (!mlx5e_tc_num_filters(priv) && (priv->fs.tc.t)) { | ||
192 | mlx5_destroy_flow_table(priv->fs.tc.t); | ||
193 | priv->fs.tc.t = NULL; | ||
194 | } | ||
195 | } | 214 | } |
196 | 215 | ||
197 | static void parse_vxlan_attr(struct mlx5_flow_spec *spec, | 216 | static void parse_vxlan_attr(struct mlx5_flow_spec *spec, |
@@ -248,12 +267,15 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv, | |||
248 | skb_flow_dissector_target(f->dissector, | 267 | skb_flow_dissector_target(f->dissector, |
249 | FLOW_DISSECTOR_KEY_ENC_PORTS, | 268 | FLOW_DISSECTOR_KEY_ENC_PORTS, |
250 | f->mask); | 269 | f->mask); |
270 | struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; | ||
271 | struct net_device *up_dev = mlx5_eswitch_get_uplink_netdev(esw); | ||
272 | struct mlx5e_priv *up_priv = netdev_priv(up_dev); | ||
251 | 273 | ||
252 | /* Full udp dst port must be given */ | 274 | /* Full udp dst port must be given */ |
253 | if (memchr_inv(&mask->dst, 0xff, sizeof(mask->dst))) | 275 | if (memchr_inv(&mask->dst, 0xff, sizeof(mask->dst))) |
254 | goto vxlan_match_offload_err; | 276 | goto vxlan_match_offload_err; |
255 | 277 | ||
256 | if (mlx5e_vxlan_lookup_port(priv, be16_to_cpu(key->dst)) && | 278 | if (mlx5e_vxlan_lookup_port(up_priv, be16_to_cpu(key->dst)) && |
257 | MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap)) | 279 | MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap)) |
258 | parse_vxlan_attr(spec, f); | 280 | parse_vxlan_attr(spec, f); |
259 | else { | 281 | else { |
@@ -976,6 +998,8 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, | |||
976 | struct mlx5_esw_flow_attr *attr) | 998 | struct mlx5_esw_flow_attr *attr) |
977 | { | 999 | { |
978 | struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; | 1000 | struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; |
1001 | struct net_device *up_dev = mlx5_eswitch_get_uplink_netdev(esw); | ||
1002 | struct mlx5e_priv *up_priv = netdev_priv(up_dev); | ||
979 | unsigned short family = ip_tunnel_info_af(tun_info); | 1003 | unsigned short family = ip_tunnel_info_af(tun_info); |
980 | struct ip_tunnel_key *key = &tun_info->key; | 1004 | struct ip_tunnel_key *key = &tun_info->key; |
981 | struct mlx5_encap_entry *e; | 1005 | struct mlx5_encap_entry *e; |
@@ -996,7 +1020,7 @@ vxlan_encap_offload_err: | |||
996 | return -EOPNOTSUPP; | 1020 | return -EOPNOTSUPP; |
997 | } | 1021 | } |
998 | 1022 | ||
999 | if (mlx5e_vxlan_lookup_port(priv, be16_to_cpu(key->tp_dst)) && | 1023 | if (mlx5e_vxlan_lookup_port(up_priv, be16_to_cpu(key->tp_dst)) && |
1000 | MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap)) { | 1024 | MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap)) { |
1001 | tunnel_type = MLX5_HEADER_TYPE_VXLAN; | 1025 | tunnel_type = MLX5_HEADER_TYPE_VXLAN; |
1002 | } else { | 1026 | } else { |
@@ -1112,14 +1136,16 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, | |||
1112 | } | 1136 | } |
1113 | 1137 | ||
1114 | if (is_tcf_vlan(a)) { | 1138 | if (is_tcf_vlan(a)) { |
1115 | if (tcf_vlan_action(a) == VLAN_F_POP) { | 1139 | if (tcf_vlan_action(a) == TCA_VLAN_ACT_POP) { |
1116 | attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP; | 1140 | attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP; |
1117 | } else if (tcf_vlan_action(a) == VLAN_F_PUSH) { | 1141 | } else if (tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) { |
1118 | if (tcf_vlan_push_proto(a) != htons(ETH_P_8021Q)) | 1142 | if (tcf_vlan_push_proto(a) != htons(ETH_P_8021Q)) |
1119 | return -EOPNOTSUPP; | 1143 | return -EOPNOTSUPP; |
1120 | 1144 | ||
1121 | attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH; | 1145 | attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH; |
1122 | attr->vlan = tcf_vlan_push_vid(a); | 1146 | attr->vlan = tcf_vlan_push_vid(a); |
1147 | } else { /* action is TCA_VLAN_ACT_MODIFY */ | ||
1148 | return -EOPNOTSUPP; | ||
1123 | } | 1149 | } |
1124 | continue; | 1150 | continue; |
1125 | } | 1151 | } |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index f193128bac4b..57f5e2d7ebd1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | |||
@@ -274,15 +274,18 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb) | |||
274 | sq->stats.tso_bytes += skb->len - ihs; | 274 | sq->stats.tso_bytes += skb->len - ihs; |
275 | } | 275 | } |
276 | 276 | ||
277 | sq->stats.packets += skb_shinfo(skb)->gso_segs; | ||
277 | num_bytes = skb->len + (skb_shinfo(skb)->gso_segs - 1) * ihs; | 278 | num_bytes = skb->len + (skb_shinfo(skb)->gso_segs - 1) * ihs; |
278 | } else { | 279 | } else { |
279 | bf = sq->bf_budget && | 280 | bf = sq->bf_budget && |
280 | !skb->xmit_more && | 281 | !skb->xmit_more && |
281 | !skb_shinfo(skb)->nr_frags; | 282 | !skb_shinfo(skb)->nr_frags; |
282 | ihs = mlx5e_get_inline_hdr_size(sq, skb, bf); | 283 | ihs = mlx5e_get_inline_hdr_size(sq, skb, bf); |
284 | sq->stats.packets++; | ||
283 | num_bytes = max_t(unsigned int, skb->len, ETH_ZLEN); | 285 | num_bytes = max_t(unsigned int, skb->len, ETH_ZLEN); |
284 | } | 286 | } |
285 | 287 | ||
288 | sq->stats.bytes += num_bytes; | ||
286 | wi->num_bytes = num_bytes; | 289 | wi->num_bytes = num_bytes; |
287 | 290 | ||
288 | ds_cnt = sizeof(*wqe) / MLX5_SEND_WQE_DS; | 291 | ds_cnt = sizeof(*wqe) / MLX5_SEND_WQE_DS; |
@@ -381,8 +384,6 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb) | |||
381 | if (bf) | 384 | if (bf) |
382 | sq->bf_budget--; | 385 | sq->bf_budget--; |
383 | 386 | ||
384 | sq->stats.packets++; | ||
385 | sq->stats.bytes += num_bytes; | ||
386 | return NETDEV_TX_OK; | 387 | return NETDEV_TX_OK; |
387 | 388 | ||
388 | dma_unmap_wqe_err: | 389 | dma_unmap_wqe_err: |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 5b78883d5654..ad329b1680b4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | |||
@@ -209,6 +209,7 @@ struct mlx5_esw_offload { | |||
209 | struct mlx5_eswitch_rep *vport_reps; | 209 | struct mlx5_eswitch_rep *vport_reps; |
210 | DECLARE_HASHTABLE(encap_tbl, 8); | 210 | DECLARE_HASHTABLE(encap_tbl, 8); |
211 | u8 inline_mode; | 211 | u8 inline_mode; |
212 | u64 num_flows; | ||
212 | }; | 213 | }; |
213 | 214 | ||
214 | struct mlx5_eswitch { | 215 | struct mlx5_eswitch { |
@@ -271,6 +272,11 @@ struct mlx5_flow_handle * | |||
271 | mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, | 272 | mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, |
272 | struct mlx5_flow_spec *spec, | 273 | struct mlx5_flow_spec *spec, |
273 | struct mlx5_esw_flow_attr *attr); | 274 | struct mlx5_esw_flow_attr *attr); |
275 | void | ||
276 | mlx5_eswitch_del_offloaded_rule(struct mlx5_eswitch *esw, | ||
277 | struct mlx5_flow_handle *rule, | ||
278 | struct mlx5_esw_flow_attr *attr); | ||
279 | |||
274 | struct mlx5_flow_handle * | 280 | struct mlx5_flow_handle * |
275 | mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn); | 281 | mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn); |
276 | 282 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 4f5b0d47d5f3..307ec6c5fd3b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | |||
@@ -93,10 +93,27 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, | |||
93 | spec, &flow_act, dest, i); | 93 | spec, &flow_act, dest, i); |
94 | if (IS_ERR(rule)) | 94 | if (IS_ERR(rule)) |
95 | mlx5_fc_destroy(esw->dev, counter); | 95 | mlx5_fc_destroy(esw->dev, counter); |
96 | else | ||
97 | esw->offloads.num_flows++; | ||
96 | 98 | ||
97 | return rule; | 99 | return rule; |
98 | } | 100 | } |
99 | 101 | ||
102 | void | ||
103 | mlx5_eswitch_del_offloaded_rule(struct mlx5_eswitch *esw, | ||
104 | struct mlx5_flow_handle *rule, | ||
105 | struct mlx5_esw_flow_attr *attr) | ||
106 | { | ||
107 | struct mlx5_fc *counter = NULL; | ||
108 | |||
109 | if (!IS_ERR(rule)) { | ||
110 | counter = mlx5_flow_rule_counter(rule); | ||
111 | mlx5_del_flow_rules(rule); | ||
112 | mlx5_fc_destroy(esw->dev, counter); | ||
113 | esw->offloads.num_flows--; | ||
114 | } | ||
115 | } | ||
116 | |||
100 | static int esw_set_global_vlan_pop(struct mlx5_eswitch *esw, u8 val) | 117 | static int esw_set_global_vlan_pop(struct mlx5_eswitch *esw, u8 val) |
101 | { | 118 | { |
102 | struct mlx5_eswitch_rep *rep; | 119 | struct mlx5_eswitch_rep *rep; |
@@ -908,6 +925,11 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode) | |||
908 | MLX5_CAP_INLINE_MODE_VPORT_CONTEXT) | 925 | MLX5_CAP_INLINE_MODE_VPORT_CONTEXT) |
909 | return -EOPNOTSUPP; | 926 | return -EOPNOTSUPP; |
910 | 927 | ||
928 | if (esw->offloads.num_flows > 0) { | ||
929 | esw_warn(dev, "Can't set inline mode when flows are configured\n"); | ||
930 | return -EOPNOTSUPP; | ||
931 | } | ||
932 | |||
911 | err = esw_inline_mode_from_devlink(mode, &mlx5_mode); | 933 | err = esw_inline_mode_from_devlink(mode, &mlx5_mode); |
912 | if (err) | 934 | if (err) |
913 | goto out; | 935 | goto out; |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index e2bd600d19de..60154a175bd3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c | |||
@@ -87,7 +87,7 @@ static struct mlx5_profile profile[] = { | |||
87 | [2] = { | 87 | [2] = { |
88 | .mask = MLX5_PROF_MASK_QP_SIZE | | 88 | .mask = MLX5_PROF_MASK_QP_SIZE | |
89 | MLX5_PROF_MASK_MR_CACHE, | 89 | MLX5_PROF_MASK_MR_CACHE, |
90 | .log_max_qp = 17, | 90 | .log_max_qp = 18, |
91 | .mr_cache[0] = { | 91 | .mr_cache[0] = { |
92 | .size = 500, | 92 | .size = 500, |
93 | .limit = 250 | 93 | .limit = 250 |
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 334bcc6df6b2..50d28261b6b9 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c | |||
@@ -2404,7 +2404,7 @@ static void efx_udp_tunnel_del(struct net_device *dev, struct udp_tunnel_info *t | |||
2404 | tnl.type = (u16)efx_tunnel_type; | 2404 | tnl.type = (u16)efx_tunnel_type; |
2405 | tnl.port = ti->port; | 2405 | tnl.port = ti->port; |
2406 | 2406 | ||
2407 | if (efx->type->udp_tnl_add_port) | 2407 | if (efx->type->udp_tnl_del_port) |
2408 | (void)efx->type->udp_tnl_del_port(efx, tnl); | 2408 | (void)efx->type->udp_tnl_del_port(efx, tnl); |
2409 | } | 2409 | } |
2410 | 2410 | ||
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig index 296c8efd0038..9e631952b86f 100644 --- a/drivers/net/ethernet/ti/Kconfig +++ b/drivers/net/ethernet/ti/Kconfig | |||
@@ -74,15 +74,21 @@ config TI_CPSW | |||
74 | will be called cpsw. | 74 | will be called cpsw. |
75 | 75 | ||
76 | config TI_CPTS | 76 | config TI_CPTS |
77 | tristate "TI Common Platform Time Sync (CPTS) Support" | 77 | bool "TI Common Platform Time Sync (CPTS) Support" |
78 | depends on TI_CPSW || TI_KEYSTONE_NETCP | 78 | depends on TI_CPSW || TI_KEYSTONE_NETCP |
79 | imply PTP_1588_CLOCK | 79 | depends on PTP_1588_CLOCK |
80 | ---help--- | 80 | ---help--- |
81 | This driver supports the Common Platform Time Sync unit of | 81 | This driver supports the Common Platform Time Sync unit of |
82 | the CPSW Ethernet Switch and Keystone 2 1g/10g Switch Subsystem. | 82 | the CPSW Ethernet Switch and Keystone 2 1g/10g Switch Subsystem. |
83 | The unit can time stamp PTP UDP/IPv4 and Layer 2 packets, and the | 83 | The unit can time stamp PTP UDP/IPv4 and Layer 2 packets, and the |
84 | driver offers a PTP Hardware Clock. | 84 | driver offers a PTP Hardware Clock. |
85 | 85 | ||
86 | config TI_CPTS_MOD | ||
87 | tristate | ||
88 | depends on TI_CPTS | ||
89 | default y if TI_CPSW=y || TI_KEYSTONE_NETCP=y | ||
90 | default m | ||
91 | |||
86 | config TI_KEYSTONE_NETCP | 92 | config TI_KEYSTONE_NETCP |
87 | tristate "TI Keystone NETCP Core Support" | 93 | tristate "TI Keystone NETCP Core Support" |
88 | select TI_CPSW_ALE | 94 | select TI_CPSW_ALE |
diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile index 1e7c10bf8713..10e6b0ce51ba 100644 --- a/drivers/net/ethernet/ti/Makefile +++ b/drivers/net/ethernet/ti/Makefile | |||
@@ -12,7 +12,7 @@ obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o | |||
12 | obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o | 12 | obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o |
13 | obj-$(CONFIG_TI_CPSW_PHY_SEL) += cpsw-phy-sel.o | 13 | obj-$(CONFIG_TI_CPSW_PHY_SEL) += cpsw-phy-sel.o |
14 | obj-$(CONFIG_TI_CPSW_ALE) += cpsw_ale.o | 14 | obj-$(CONFIG_TI_CPSW_ALE) += cpsw_ale.o |
15 | obj-$(CONFIG_TI_CPTS) += cpts.o | 15 | obj-$(CONFIG_TI_CPTS_MOD) += cpts.o |
16 | obj-$(CONFIG_TI_CPSW) += ti_cpsw.o | 16 | obj-$(CONFIG_TI_CPSW) += ti_cpsw.o |
17 | ti_cpsw-y := cpsw.o | 17 | ti_cpsw-y := cpsw.o |
18 | 18 | ||
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index b75d9cdcfb0c..ae48c809bac9 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c | |||
@@ -45,6 +45,8 @@ MODULE_DESCRIPTION("FUJITSU Extended Socket Network Device Driver"); | |||
45 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
46 | MODULE_VERSION(DRV_VERSION); | 46 | MODULE_VERSION(DRV_VERSION); |
47 | 47 | ||
48 | #define ACPI_MOTHERBOARD_RESOURCE_HID "PNP0C02" | ||
49 | |||
48 | static int fjes_request_irq(struct fjes_adapter *); | 50 | static int fjes_request_irq(struct fjes_adapter *); |
49 | static void fjes_free_irq(struct fjes_adapter *); | 51 | static void fjes_free_irq(struct fjes_adapter *); |
50 | 52 | ||
@@ -78,7 +80,7 @@ static void fjes_rx_irq(struct fjes_adapter *, int); | |||
78 | static int fjes_poll(struct napi_struct *, int); | 80 | static int fjes_poll(struct napi_struct *, int); |
79 | 81 | ||
80 | static const struct acpi_device_id fjes_acpi_ids[] = { | 82 | static const struct acpi_device_id fjes_acpi_ids[] = { |
81 | {"PNP0C02", 0}, | 83 | {ACPI_MOTHERBOARD_RESOURCE_HID, 0}, |
82 | {"", 0}, | 84 | {"", 0}, |
83 | }; | 85 | }; |
84 | MODULE_DEVICE_TABLE(acpi, fjes_acpi_ids); | 86 | MODULE_DEVICE_TABLE(acpi, fjes_acpi_ids); |
@@ -115,18 +117,17 @@ static struct resource fjes_resource[] = { | |||
115 | }, | 117 | }, |
116 | }; | 118 | }; |
117 | 119 | ||
118 | static int fjes_acpi_add(struct acpi_device *device) | 120 | static bool is_extended_socket_device(struct acpi_device *device) |
119 | { | 121 | { |
120 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; | 122 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; |
121 | char str_buf[sizeof(FJES_ACPI_SYMBOL) + 1]; | 123 | char str_buf[sizeof(FJES_ACPI_SYMBOL) + 1]; |
122 | struct platform_device *plat_dev; | ||
123 | union acpi_object *str; | 124 | union acpi_object *str; |
124 | acpi_status status; | 125 | acpi_status status; |
125 | int result; | 126 | int result; |
126 | 127 | ||
127 | status = acpi_evaluate_object(device->handle, "_STR", NULL, &buffer); | 128 | status = acpi_evaluate_object(device->handle, "_STR", NULL, &buffer); |
128 | if (ACPI_FAILURE(status)) | 129 | if (ACPI_FAILURE(status)) |
129 | return -ENODEV; | 130 | return false; |
130 | 131 | ||
131 | str = buffer.pointer; | 132 | str = buffer.pointer; |
132 | result = utf16s_to_utf8s((wchar_t *)str->string.pointer, | 133 | result = utf16s_to_utf8s((wchar_t *)str->string.pointer, |
@@ -136,10 +137,42 @@ static int fjes_acpi_add(struct acpi_device *device) | |||
136 | 137 | ||
137 | if (strncmp(FJES_ACPI_SYMBOL, str_buf, strlen(FJES_ACPI_SYMBOL)) != 0) { | 138 | if (strncmp(FJES_ACPI_SYMBOL, str_buf, strlen(FJES_ACPI_SYMBOL)) != 0) { |
138 | kfree(buffer.pointer); | 139 | kfree(buffer.pointer); |
139 | return -ENODEV; | 140 | return false; |
140 | } | 141 | } |
141 | kfree(buffer.pointer); | 142 | kfree(buffer.pointer); |
142 | 143 | ||
144 | return true; | ||
145 | } | ||
146 | |||
147 | static int acpi_check_extended_socket_status(struct acpi_device *device) | ||
148 | { | ||
149 | unsigned long long sta; | ||
150 | acpi_status status; | ||
151 | |||
152 | status = acpi_evaluate_integer(device->handle, "_STA", NULL, &sta); | ||
153 | if (ACPI_FAILURE(status)) | ||
154 | return -ENODEV; | ||
155 | |||
156 | if (!((sta & ACPI_STA_DEVICE_PRESENT) && | ||
157 | (sta & ACPI_STA_DEVICE_ENABLED) && | ||
158 | (sta & ACPI_STA_DEVICE_UI) && | ||
159 | (sta & ACPI_STA_DEVICE_FUNCTIONING))) | ||
160 | return -ENODEV; | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int fjes_acpi_add(struct acpi_device *device) | ||
166 | { | ||
167 | struct platform_device *plat_dev; | ||
168 | acpi_status status; | ||
169 | |||
170 | if (!is_extended_socket_device(device)) | ||
171 | return -ENODEV; | ||
172 | |||
173 | if (acpi_check_extended_socket_status(device)) | ||
174 | return -ENODEV; | ||
175 | |||
143 | status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, | 176 | status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, |
144 | fjes_get_acpi_resource, fjes_resource); | 177 | fjes_get_acpi_resource, fjes_resource); |
145 | if (ACPI_FAILURE(status)) | 178 | if (ACPI_FAILURE(status)) |
@@ -1316,7 +1349,7 @@ static void fjes_netdev_setup(struct net_device *netdev) | |||
1316 | netdev->min_mtu = fjes_support_mtu[0]; | 1349 | netdev->min_mtu = fjes_support_mtu[0]; |
1317 | netdev->max_mtu = fjes_support_mtu[3]; | 1350 | netdev->max_mtu = fjes_support_mtu[3]; |
1318 | netdev->flags |= IFF_BROADCAST; | 1351 | netdev->flags |= IFF_BROADCAST; |
1319 | netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER; | 1352 | netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; |
1320 | } | 1353 | } |
1321 | 1354 | ||
1322 | static void fjes_irq_watch_task(struct work_struct *work) | 1355 | static void fjes_irq_watch_task(struct work_struct *work) |
@@ -1473,11 +1506,44 @@ static void fjes_watch_unshare_task(struct work_struct *work) | |||
1473 | } | 1506 | } |
1474 | } | 1507 | } |
1475 | 1508 | ||
1509 | static acpi_status | ||
1510 | acpi_find_extended_socket_device(acpi_handle obj_handle, u32 level, | ||
1511 | void *context, void **return_value) | ||
1512 | { | ||
1513 | struct acpi_device *device; | ||
1514 | bool *found = context; | ||
1515 | int result; | ||
1516 | |||
1517 | result = acpi_bus_get_device(obj_handle, &device); | ||
1518 | if (result) | ||
1519 | return AE_OK; | ||
1520 | |||
1521 | if (strcmp(acpi_device_hid(device), ACPI_MOTHERBOARD_RESOURCE_HID)) | ||
1522 | return AE_OK; | ||
1523 | |||
1524 | if (!is_extended_socket_device(device)) | ||
1525 | return AE_OK; | ||
1526 | |||
1527 | if (acpi_check_extended_socket_status(device)) | ||
1528 | return AE_OK; | ||
1529 | |||
1530 | *found = true; | ||
1531 | return AE_CTRL_TERMINATE; | ||
1532 | } | ||
1533 | |||
1476 | /* fjes_init_module - Driver Registration Routine */ | 1534 | /* fjes_init_module - Driver Registration Routine */ |
1477 | static int __init fjes_init_module(void) | 1535 | static int __init fjes_init_module(void) |
1478 | { | 1536 | { |
1537 | bool found = false; | ||
1479 | int result; | 1538 | int result; |
1480 | 1539 | ||
1540 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, | ||
1541 | acpi_find_extended_socket_device, NULL, &found, | ||
1542 | NULL); | ||
1543 | |||
1544 | if (!found) | ||
1545 | return -ENODEV; | ||
1546 | |||
1481 | pr_info("%s - version %s - %s\n", | 1547 | pr_info("%s - version %s - %s\n", |
1482 | fjes_driver_string, fjes_driver_version, fjes_copyright); | 1548 | fjes_driver_string, fjes_driver_version, fjes_copyright); |
1483 | 1549 | ||
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 4c1d8cca247b..8dd0b8770328 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c | |||
@@ -1231,8 +1231,11 @@ void netvsc_channel_cb(void *context) | |||
1231 | return; | 1231 | return; |
1232 | 1232 | ||
1233 | net_device = net_device_to_netvsc_device(ndev); | 1233 | net_device = net_device_to_netvsc_device(ndev); |
1234 | if (unlikely(net_device->destroy) && | 1234 | if (unlikely(!net_device)) |
1235 | netvsc_channel_idle(net_device, q_idx)) | 1235 | return; |
1236 | |||
1237 | if (unlikely(net_device->destroy && | ||
1238 | netvsc_channel_idle(net_device, q_idx))) | ||
1236 | return; | 1239 | return; |
1237 | 1240 | ||
1238 | /* commit_rd_index() -> hv_signal_on_read() needs this. */ | 1241 | /* commit_rd_index() -> hv_signal_on_read() needs this. */ |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 34cc3c590aa5..cc88cd7856f5 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -1931,6 +1931,8 @@ static int set_offload(struct tun_struct *tun, unsigned long arg) | |||
1931 | return -EINVAL; | 1931 | return -EINVAL; |
1932 | 1932 | ||
1933 | tun->set_features = features; | 1933 | tun->set_features = features; |
1934 | tun->dev->wanted_features &= ~TUN_USER_FEATURES; | ||
1935 | tun->dev->wanted_features |= features; | ||
1934 | netdev_update_features(tun->dev); | 1936 | netdev_update_features(tun->dev); |
1935 | 1937 | ||
1936 | return 0; | 1938 | return 0; |
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 805674550683..156f7f85e486 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c | |||
@@ -580,6 +580,10 @@ static const struct usb_device_id products[] = { | |||
580 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x69), | 580 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x69), |
581 | .driver_info = (unsigned long)&qmi_wwan_info, | 581 | .driver_info = (unsigned long)&qmi_wwan_info, |
582 | }, | 582 | }, |
583 | { /* Motorola Mapphone devices with MDM6600 */ | ||
584 | USB_VENDOR_AND_INTERFACE_INFO(0x22b8, USB_CLASS_VENDOR_SPEC, 0xfb, 0xff), | ||
585 | .driver_info = (unsigned long)&qmi_wwan_info, | ||
586 | }, | ||
583 | 587 | ||
584 | /* 2. Combined interface devices matching on class+protocol */ | 588 | /* 2. Combined interface devices matching on class+protocol */ |
585 | { /* Huawei E367 and possibly others in "Windows mode" */ | 589 | { /* Huawei E367 and possibly others in "Windows mode" */ |
@@ -925,6 +929,8 @@ static const struct usb_device_id products[] = { | |||
925 | {QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ | 929 | {QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ |
926 | {QMI_FIXED_INTF(0x413c, 0x81b1, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */ | 930 | {QMI_FIXED_INTF(0x413c, 0x81b1, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */ |
927 | {QMI_FIXED_INTF(0x413c, 0x81b3, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */ | 931 | {QMI_FIXED_INTF(0x413c, 0x81b3, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */ |
932 | {QMI_FIXED_INTF(0x413c, 0x81b6, 8)}, /* Dell Wireless 5811e */ | ||
933 | {QMI_FIXED_INTF(0x413c, 0x81b6, 10)}, /* Dell Wireless 5811e */ | ||
928 | {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ | 934 | {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ |
929 | {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */ | 935 | {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */ |
930 | {QMI_FIXED_INTF(0x1e0e, 0x9001, 5)}, /* SIMCom 7230E */ | 936 | {QMI_FIXED_INTF(0x1e0e, 0x9001, 5)}, /* SIMCom 7230E */ |
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 986243c932cc..0b1b9188625d 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #define NETNEXT_VERSION "08" | 32 | #define NETNEXT_VERSION "08" |
33 | 33 | ||
34 | /* Information for net */ | 34 | /* Information for net */ |
35 | #define NET_VERSION "8" | 35 | #define NET_VERSION "9" |
36 | 36 | ||
37 | #define DRIVER_VERSION "v1." NETNEXT_VERSION "." NET_VERSION | 37 | #define DRIVER_VERSION "v1." NETNEXT_VERSION "." NET_VERSION |
38 | #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" | 38 | #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" |
@@ -501,6 +501,8 @@ enum rtl_register_content { | |||
501 | #define RTL8153_RMS RTL8153_MAX_PACKET | 501 | #define RTL8153_RMS RTL8153_MAX_PACKET |
502 | #define RTL8152_TX_TIMEOUT (5 * HZ) | 502 | #define RTL8152_TX_TIMEOUT (5 * HZ) |
503 | #define RTL8152_NAPI_WEIGHT 64 | 503 | #define RTL8152_NAPI_WEIGHT 64 |
504 | #define rx_reserved_size(x) ((x) + VLAN_ETH_HLEN + CRC_SIZE + \ | ||
505 | sizeof(struct rx_desc) + RX_ALIGN) | ||
504 | 506 | ||
505 | /* rtl8152 flags */ | 507 | /* rtl8152 flags */ |
506 | enum rtl8152_flags { | 508 | enum rtl8152_flags { |
@@ -1362,6 +1364,7 @@ static int alloc_all_mem(struct r8152 *tp) | |||
1362 | spin_lock_init(&tp->rx_lock); | 1364 | spin_lock_init(&tp->rx_lock); |
1363 | spin_lock_init(&tp->tx_lock); | 1365 | spin_lock_init(&tp->tx_lock); |
1364 | INIT_LIST_HEAD(&tp->tx_free); | 1366 | INIT_LIST_HEAD(&tp->tx_free); |
1367 | INIT_LIST_HEAD(&tp->rx_done); | ||
1365 | skb_queue_head_init(&tp->tx_queue); | 1368 | skb_queue_head_init(&tp->tx_queue); |
1366 | skb_queue_head_init(&tp->rx_queue); | 1369 | skb_queue_head_init(&tp->rx_queue); |
1367 | 1370 | ||
@@ -2252,8 +2255,7 @@ static void r8153_set_rx_early_timeout(struct r8152 *tp) | |||
2252 | 2255 | ||
2253 | static void r8153_set_rx_early_size(struct r8152 *tp) | 2256 | static void r8153_set_rx_early_size(struct r8152 *tp) |
2254 | { | 2257 | { |
2255 | u32 mtu = tp->netdev->mtu; | 2258 | u32 ocp_data = (agg_buf_sz - rx_reserved_size(tp->netdev->mtu)) / 4; |
2256 | u32 ocp_data = (agg_buf_sz - mtu - VLAN_ETH_HLEN - VLAN_HLEN) / 8; | ||
2257 | 2259 | ||
2258 | ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, ocp_data); | 2260 | ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, ocp_data); |
2259 | } | 2261 | } |
@@ -2898,7 +2900,8 @@ static void r8153_first_init(struct r8152 *tp) | |||
2898 | 2900 | ||
2899 | rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX); | 2901 | rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX); |
2900 | 2902 | ||
2901 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8153_RMS); | 2903 | ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + CRC_SIZE; |
2904 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data); | ||
2902 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO); | 2905 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO); |
2903 | 2906 | ||
2904 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0); | 2907 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0); |
@@ -2950,7 +2953,8 @@ static void r8153_enter_oob(struct r8152 *tp) | |||
2950 | usleep_range(1000, 2000); | 2953 | usleep_range(1000, 2000); |
2951 | } | 2954 | } |
2952 | 2955 | ||
2953 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8153_RMS); | 2956 | ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + CRC_SIZE; |
2957 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data); | ||
2954 | 2958 | ||
2955 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG); | 2959 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG); |
2956 | ocp_data &= ~TEREDO_WAKE_MASK; | 2960 | ocp_data &= ~TEREDO_WAKE_MASK; |
@@ -4200,8 +4204,14 @@ static int rtl8152_change_mtu(struct net_device *dev, int new_mtu) | |||
4200 | 4204 | ||
4201 | dev->mtu = new_mtu; | 4205 | dev->mtu = new_mtu; |
4202 | 4206 | ||
4203 | if (netif_running(dev) && netif_carrier_ok(dev)) | 4207 | if (netif_running(dev)) { |
4204 | r8153_set_rx_early_size(tp); | 4208 | u32 rms = new_mtu + VLAN_ETH_HLEN + CRC_SIZE; |
4209 | |||
4210 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, rms); | ||
4211 | |||
4212 | if (netif_carrier_ok(dev)) | ||
4213 | r8153_set_rx_early_size(tp); | ||
4214 | } | ||
4205 | 4215 | ||
4206 | mutex_unlock(&tp->control); | 4216 | mutex_unlock(&tp->control); |
4207 | 4217 | ||
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index fea687f35b5a..d6988db1930d 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c | |||
@@ -462,8 +462,10 @@ static void vrf_rt6_release(struct net_device *dev, struct net_vrf *vrf) | |||
462 | } | 462 | } |
463 | 463 | ||
464 | if (rt6_local) { | 464 | if (rt6_local) { |
465 | if (rt6_local->rt6i_idev) | 465 | if (rt6_local->rt6i_idev) { |
466 | in6_dev_put(rt6_local->rt6i_idev); | 466 | in6_dev_put(rt6_local->rt6i_idev); |
467 | rt6_local->rt6i_idev = NULL; | ||
468 | } | ||
467 | 469 | ||
468 | dst = &rt6_local->dst; | 470 | dst = &rt6_local->dst; |
469 | dev_put(dst->dev); | 471 | dev_put(dst->dev); |
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 33fb26833cd0..d9f37ee4bfdd 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c | |||
@@ -51,7 +51,7 @@ const struct ath10k_hw_regs qca6174_regs = { | |||
51 | .rtc_soc_base_address = 0x00000800, | 51 | .rtc_soc_base_address = 0x00000800, |
52 | .rtc_wmac_base_address = 0x00001000, | 52 | .rtc_wmac_base_address = 0x00001000, |
53 | .soc_core_base_address = 0x0003a000, | 53 | .soc_core_base_address = 0x0003a000, |
54 | .wlan_mac_base_address = 0x00020000, | 54 | .wlan_mac_base_address = 0x00010000, |
55 | .ce_wrapper_base_address = 0x00034000, | 55 | .ce_wrapper_base_address = 0x00034000, |
56 | .ce0_base_address = 0x00034400, | 56 | .ce0_base_address = 0x00034400, |
57 | .ce1_base_address = 0x00034800, | 57 | .ce1_base_address = 0x00034800, |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index d37b1695c64e..6927caecd48e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | |||
@@ -2319,7 +2319,7 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw, | |||
2319 | { | 2319 | { |
2320 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 2320 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
2321 | 2321 | ||
2322 | /* Called when we need to transmit (a) frame(s) from agg queue */ | 2322 | /* Called when we need to transmit (a) frame(s) from agg or dqa queue */ |
2323 | 2323 | ||
2324 | iwl_mvm_sta_modify_sleep_tx_count(mvm, sta, reason, num_frames, | 2324 | iwl_mvm_sta_modify_sleep_tx_count(mvm, sta, reason, num_frames, |
2325 | tids, more_data, true); | 2325 | tids, more_data, true); |
@@ -2338,7 +2338,8 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, | |||
2338 | for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) { | 2338 | for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) { |
2339 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; | 2339 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; |
2340 | 2340 | ||
2341 | if (tid_data->state != IWL_AGG_ON && | 2341 | if (!iwl_mvm_is_dqa_supported(mvm) && |
2342 | tid_data->state != IWL_AGG_ON && | ||
2342 | tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA) | 2343 | tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA) |
2343 | continue; | 2344 | continue; |
2344 | 2345 | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index bd1dcc863d8f..b51a2853cc80 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c | |||
@@ -3135,7 +3135,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, | |||
3135 | struct ieee80211_sta *sta, | 3135 | struct ieee80211_sta *sta, |
3136 | enum ieee80211_frame_release_type reason, | 3136 | enum ieee80211_frame_release_type reason, |
3137 | u16 cnt, u16 tids, bool more_data, | 3137 | u16 cnt, u16 tids, bool more_data, |
3138 | bool agg) | 3138 | bool single_sta_queue) |
3139 | { | 3139 | { |
3140 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 3140 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
3141 | struct iwl_mvm_add_sta_cmd cmd = { | 3141 | struct iwl_mvm_add_sta_cmd cmd = { |
@@ -3155,14 +3155,14 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, | |||
3155 | for_each_set_bit(tid, &_tids, IWL_MAX_TID_COUNT) | 3155 | for_each_set_bit(tid, &_tids, IWL_MAX_TID_COUNT) |
3156 | cmd.awake_acs |= BIT(tid_to_ucode_ac[tid]); | 3156 | cmd.awake_acs |= BIT(tid_to_ucode_ac[tid]); |
3157 | 3157 | ||
3158 | /* If we're releasing frames from aggregation queues then check if the | 3158 | /* If we're releasing frames from aggregation or dqa queues then check |
3159 | * all queues combined that we're releasing frames from have | 3159 | * if all the queues that we're releasing frames from, combined, have: |
3160 | * - more frames than the service period, in which case more_data | 3160 | * - more frames than the service period, in which case more_data |
3161 | * needs to be set | 3161 | * needs to be set |
3162 | * - fewer than 'cnt' frames, in which case we need to adjust the | 3162 | * - fewer than 'cnt' frames, in which case we need to adjust the |
3163 | * firmware command (but do that unconditionally) | 3163 | * firmware command (but do that unconditionally) |
3164 | */ | 3164 | */ |
3165 | if (agg) { | 3165 | if (single_sta_queue) { |
3166 | int remaining = cnt; | 3166 | int remaining = cnt; |
3167 | int sleep_tx_count; | 3167 | int sleep_tx_count; |
3168 | 3168 | ||
@@ -3172,7 +3172,8 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, | |||
3172 | u16 n_queued; | 3172 | u16 n_queued; |
3173 | 3173 | ||
3174 | tid_data = &mvmsta->tid_data[tid]; | 3174 | tid_data = &mvmsta->tid_data[tid]; |
3175 | if (WARN(tid_data->state != IWL_AGG_ON && | 3175 | if (WARN(!iwl_mvm_is_dqa_supported(mvm) && |
3176 | tid_data->state != IWL_AGG_ON && | ||
3176 | tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA, | 3177 | tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA, |
3177 | "TID %d state is %d\n", | 3178 | "TID %d state is %d\n", |
3178 | tid, tid_data->state)) { | 3179 | tid, tid_data->state)) { |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index 4be34f902278..1927ce607798 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h | |||
@@ -547,7 +547,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, | |||
547 | struct ieee80211_sta *sta, | 547 | struct ieee80211_sta *sta, |
548 | enum ieee80211_frame_release_type reason, | 548 | enum ieee80211_frame_release_type reason, |
549 | u16 cnt, u16 tids, bool more_data, | 549 | u16 cnt, u16 tids, bool more_data, |
550 | bool agg); | 550 | bool single_sta_queue); |
551 | int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, | 551 | int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, |
552 | bool drain); | 552 | bool drain); |
553 | void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm, | 553 | void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm, |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index dd2b4a300819..3f37075f4cde 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2016 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
13 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
@@ -34,6 +34,7 @@ | |||
34 | * | 34 | * |
35 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 35 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
36 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 36 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
37 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | ||
37 | * All rights reserved. | 38 | * All rights reserved. |
38 | * | 39 | * |
39 | * Redistribution and use in source and binary forms, with or without | 40 | * Redistribution and use in source and binary forms, with or without |
@@ -628,8 +629,10 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) | |||
628 | * values. | 629 | * values. |
629 | * Note that we don't need to make sure it isn't agg'd, since we're | 630 | * Note that we don't need to make sure it isn't agg'd, since we're |
630 | * TXing non-sta | 631 | * TXing non-sta |
632 | * For DQA mode - we shouldn't increase it though | ||
631 | */ | 633 | */ |
632 | atomic_inc(&mvm->pending_frames[sta_id]); | 634 | if (!iwl_mvm_is_dqa_supported(mvm)) |
635 | atomic_inc(&mvm->pending_frames[sta_id]); | ||
633 | 636 | ||
634 | return 0; | 637 | return 0; |
635 | } | 638 | } |
@@ -1005,11 +1008,8 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
1005 | 1008 | ||
1006 | spin_unlock(&mvmsta->lock); | 1009 | spin_unlock(&mvmsta->lock); |
1007 | 1010 | ||
1008 | /* Increase pending frames count if this isn't AMPDU */ | 1011 | /* Increase pending frames count if this isn't AMPDU or DQA queue */ |
1009 | if ((iwl_mvm_is_dqa_supported(mvm) && | 1012 | if (!iwl_mvm_is_dqa_supported(mvm) && !is_ampdu) |
1010 | mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_ON && | ||
1011 | mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_STARTING) || | ||
1012 | (!iwl_mvm_is_dqa_supported(mvm) && !is_ampdu)) | ||
1013 | atomic_inc(&mvm->pending_frames[mvmsta->sta_id]); | 1013 | atomic_inc(&mvm->pending_frames[mvmsta->sta_id]); |
1014 | 1014 | ||
1015 | return 0; | 1015 | return 0; |
@@ -1079,12 +1079,13 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm, | |||
1079 | lockdep_assert_held(&mvmsta->lock); | 1079 | lockdep_assert_held(&mvmsta->lock); |
1080 | 1080 | ||
1081 | if ((tid_data->state == IWL_AGG_ON || | 1081 | if ((tid_data->state == IWL_AGG_ON || |
1082 | tid_data->state == IWL_EMPTYING_HW_QUEUE_DELBA) && | 1082 | tid_data->state == IWL_EMPTYING_HW_QUEUE_DELBA || |
1083 | iwl_mvm_is_dqa_supported(mvm)) && | ||
1083 | iwl_mvm_tid_queued(tid_data) == 0) { | 1084 | iwl_mvm_tid_queued(tid_data) == 0) { |
1084 | /* | 1085 | /* |
1085 | * Now that this aggregation queue is empty tell mac80211 so it | 1086 | * Now that this aggregation or DQA queue is empty tell |
1086 | * knows we no longer have frames buffered for the station on | 1087 | * mac80211 so it knows we no longer have frames buffered for |
1087 | * this TID (for the TIM bitmap calculation.) | 1088 | * the station on this TID (for the TIM bitmap calculation.) |
1088 | */ | 1089 | */ |
1089 | ieee80211_sta_set_buffered(sta, tid, false); | 1090 | ieee80211_sta_set_buffered(sta, tid, false); |
1090 | } | 1091 | } |
@@ -1257,7 +1258,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
1257 | u8 skb_freed = 0; | 1258 | u8 skb_freed = 0; |
1258 | u16 next_reclaimed, seq_ctl; | 1259 | u16 next_reclaimed, seq_ctl; |
1259 | bool is_ndp = false; | 1260 | bool is_ndp = false; |
1260 | bool txq_agg = false; /* Is this TXQ aggregated */ | ||
1261 | 1261 | ||
1262 | __skb_queue_head_init(&skbs); | 1262 | __skb_queue_head_init(&skbs); |
1263 | 1263 | ||
@@ -1283,6 +1283,10 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
1283 | info->flags |= IEEE80211_TX_STAT_ACK; | 1283 | info->flags |= IEEE80211_TX_STAT_ACK; |
1284 | break; | 1284 | break; |
1285 | case TX_STATUS_FAIL_DEST_PS: | 1285 | case TX_STATUS_FAIL_DEST_PS: |
1286 | /* In DQA, the FW should have stopped the queue and not | ||
1287 | * return this status | ||
1288 | */ | ||
1289 | WARN_ON(iwl_mvm_is_dqa_supported(mvm)); | ||
1286 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 1290 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
1287 | break; | 1291 | break; |
1288 | default: | 1292 | default: |
@@ -1387,15 +1391,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
1387 | bool send_eosp_ndp = false; | 1391 | bool send_eosp_ndp = false; |
1388 | 1392 | ||
1389 | spin_lock_bh(&mvmsta->lock); | 1393 | spin_lock_bh(&mvmsta->lock); |
1390 | if (iwl_mvm_is_dqa_supported(mvm)) { | ||
1391 | enum iwl_mvm_agg_state state; | ||
1392 | |||
1393 | state = mvmsta->tid_data[tid].state; | ||
1394 | txq_agg = (state == IWL_AGG_ON || | ||
1395 | state == IWL_EMPTYING_HW_QUEUE_DELBA); | ||
1396 | } else { | ||
1397 | txq_agg = txq_id >= mvm->first_agg_queue; | ||
1398 | } | ||
1399 | 1394 | ||
1400 | if (!is_ndp) { | 1395 | if (!is_ndp) { |
1401 | tid_data->next_reclaimed = next_reclaimed; | 1396 | tid_data->next_reclaimed = next_reclaimed; |
@@ -1452,11 +1447,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
1452 | * If the txq is not an AMPDU queue, there is no chance we freed | 1447 | * If the txq is not an AMPDU queue, there is no chance we freed |
1453 | * several skbs. Check that out... | 1448 | * several skbs. Check that out... |
1454 | */ | 1449 | */ |
1455 | if (txq_agg) | 1450 | if (iwl_mvm_is_dqa_supported(mvm) || txq_id >= mvm->first_agg_queue) |
1456 | goto out; | 1451 | goto out; |
1457 | 1452 | ||
1458 | /* We can't free more than one frame at once on a shared queue */ | 1453 | /* We can't free more than one frame at once on a shared queue */ |
1459 | WARN_ON(!iwl_mvm_is_dqa_supported(mvm) && (skb_freed > 1)); | 1454 | WARN_ON(skb_freed > 1); |
1460 | 1455 | ||
1461 | /* If we have still frames for this STA nothing to do here */ | 1456 | /* If we have still frames for this STA nothing to do here */ |
1462 | if (!atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) | 1457 | if (!atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) |
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index 5ebca1d0cfc7..b62e03d11c2e 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c | |||
@@ -57,8 +57,8 @@ MODULE_PARM_DESC(mfg_mode, "manufacturing mode enable:1, disable:0"); | |||
57 | * In case of any errors during inittialization, this function also ensures | 57 | * In case of any errors during inittialization, this function also ensures |
58 | * proper cleanup before exiting. | 58 | * proper cleanup before exiting. |
59 | */ | 59 | */ |
60 | static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, | 60 | static int mwifiex_register(void *card, struct device *dev, |
61 | void **padapter) | 61 | struct mwifiex_if_ops *if_ops, void **padapter) |
62 | { | 62 | { |
63 | struct mwifiex_adapter *adapter; | 63 | struct mwifiex_adapter *adapter; |
64 | int i; | 64 | int i; |
@@ -68,6 +68,7 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, | |||
68 | return -ENOMEM; | 68 | return -ENOMEM; |
69 | 69 | ||
70 | *padapter = adapter; | 70 | *padapter = adapter; |
71 | adapter->dev = dev; | ||
71 | adapter->card = card; | 72 | adapter->card = card; |
72 | 73 | ||
73 | /* Save interface specific operations in adapter */ | 74 | /* Save interface specific operations in adapter */ |
@@ -1568,12 +1569,11 @@ mwifiex_add_card(void *card, struct completion *fw_done, | |||
1568 | { | 1569 | { |
1569 | struct mwifiex_adapter *adapter; | 1570 | struct mwifiex_adapter *adapter; |
1570 | 1571 | ||
1571 | if (mwifiex_register(card, if_ops, (void **)&adapter)) { | 1572 | if (mwifiex_register(card, dev, if_ops, (void **)&adapter)) { |
1572 | pr_err("%s: software init failed\n", __func__); | 1573 | pr_err("%s: software init failed\n", __func__); |
1573 | goto err_init_sw; | 1574 | goto err_init_sw; |
1574 | } | 1575 | } |
1575 | 1576 | ||
1576 | adapter->dev = dev; | ||
1577 | mwifiex_probe_of(adapter); | 1577 | mwifiex_probe_of(adapter); |
1578 | 1578 | ||
1579 | adapter->iface_type = iface_type; | 1579 | adapter->iface_type = iface_type; |
@@ -1718,6 +1718,9 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter) | |||
1718 | wiphy_unregister(adapter->wiphy); | 1718 | wiphy_unregister(adapter->wiphy); |
1719 | wiphy_free(adapter->wiphy); | 1719 | wiphy_free(adapter->wiphy); |
1720 | 1720 | ||
1721 | if (adapter->irq_wakeup >= 0) | ||
1722 | device_init_wakeup(adapter->dev, false); | ||
1723 | |||
1721 | /* Unregister device */ | 1724 | /* Unregister device */ |
1722 | mwifiex_dbg(adapter, INFO, | 1725 | mwifiex_dbg(adapter, INFO, |
1723 | "info: unregister device\n"); | 1726 | "info: unregister device\n"); |
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index a0d918094889..b8c990d10d6e 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c | |||
@@ -2739,6 +2739,21 @@ static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter) | |||
2739 | schedule_work(&card->work); | 2739 | schedule_work(&card->work); |
2740 | } | 2740 | } |
2741 | 2741 | ||
2742 | static void mwifiex_pcie_free_buffers(struct mwifiex_adapter *adapter) | ||
2743 | { | ||
2744 | struct pcie_service_card *card = adapter->card; | ||
2745 | const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; | ||
2746 | |||
2747 | if (reg->sleep_cookie) | ||
2748 | mwifiex_pcie_delete_sleep_cookie_buf(adapter); | ||
2749 | |||
2750 | mwifiex_pcie_delete_cmdrsp_buf(adapter); | ||
2751 | mwifiex_pcie_delete_evtbd_ring(adapter); | ||
2752 | mwifiex_pcie_delete_rxbd_ring(adapter); | ||
2753 | mwifiex_pcie_delete_txbd_ring(adapter); | ||
2754 | card->cmdrsp_buf = NULL; | ||
2755 | } | ||
2756 | |||
2742 | /* | 2757 | /* |
2743 | * This function initializes the PCI-E host memory space, WCB rings, etc. | 2758 | * This function initializes the PCI-E host memory space, WCB rings, etc. |
2744 | * | 2759 | * |
@@ -2850,13 +2865,6 @@ err_enable_dev: | |||
2850 | 2865 | ||
2851 | /* | 2866 | /* |
2852 | * This function cleans up the allocated card buffers. | 2867 | * This function cleans up the allocated card buffers. |
2853 | * | ||
2854 | * The following are freed by this function - | ||
2855 | * - TXBD ring buffers | ||
2856 | * - RXBD ring buffers | ||
2857 | * - Event BD ring buffers | ||
2858 | * - Command response ring buffer | ||
2859 | * - Sleep cookie buffer | ||
2860 | */ | 2868 | */ |
2861 | static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter) | 2869 | static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter) |
2862 | { | 2870 | { |
@@ -2875,6 +2883,8 @@ static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter) | |||
2875 | "Failed to write driver not-ready signature\n"); | 2883 | "Failed to write driver not-ready signature\n"); |
2876 | } | 2884 | } |
2877 | 2885 | ||
2886 | mwifiex_pcie_free_buffers(adapter); | ||
2887 | |||
2878 | if (pdev) { | 2888 | if (pdev) { |
2879 | pci_iounmap(pdev, card->pci_mmap); | 2889 | pci_iounmap(pdev, card->pci_mmap); |
2880 | pci_iounmap(pdev, card->pci_mmap1); | 2890 | pci_iounmap(pdev, card->pci_mmap1); |
@@ -3126,10 +3136,7 @@ err_cre_txbd: | |||
3126 | pci_iounmap(pdev, card->pci_mmap1); | 3136 | pci_iounmap(pdev, card->pci_mmap1); |
3127 | } | 3137 | } |
3128 | 3138 | ||
3129 | /* This function cleans up the PCI-E host memory space. | 3139 | /* This function cleans up the PCI-E host memory space. */ |
3130 | * Some code is extracted from mwifiex_unregister_dev() | ||
3131 | * | ||
3132 | */ | ||
3133 | static void mwifiex_pcie_down_dev(struct mwifiex_adapter *adapter) | 3140 | static void mwifiex_pcie_down_dev(struct mwifiex_adapter *adapter) |
3134 | { | 3141 | { |
3135 | struct pcie_service_card *card = adapter->card; | 3142 | struct pcie_service_card *card = adapter->card; |
@@ -3140,14 +3147,7 @@ static void mwifiex_pcie_down_dev(struct mwifiex_adapter *adapter) | |||
3140 | 3147 | ||
3141 | adapter->seq_num = 0; | 3148 | adapter->seq_num = 0; |
3142 | 3149 | ||
3143 | if (reg->sleep_cookie) | 3150 | mwifiex_pcie_free_buffers(adapter); |
3144 | mwifiex_pcie_delete_sleep_cookie_buf(adapter); | ||
3145 | |||
3146 | mwifiex_pcie_delete_cmdrsp_buf(adapter); | ||
3147 | mwifiex_pcie_delete_evtbd_ring(adapter); | ||
3148 | mwifiex_pcie_delete_rxbd_ring(adapter); | ||
3149 | mwifiex_pcie_delete_txbd_ring(adapter); | ||
3150 | card->cmdrsp_buf = NULL; | ||
3151 | } | 3151 | } |
3152 | 3152 | ||
3153 | static struct mwifiex_if_ops pcie_ops = { | 3153 | static struct mwifiex_if_ops pcie_ops = { |
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index ce5e63d2c66a..44eed8eb0725 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c | |||
@@ -223,6 +223,46 @@ vhost_transport_send_pkt(struct virtio_vsock_pkt *pkt) | |||
223 | return len; | 223 | return len; |
224 | } | 224 | } |
225 | 225 | ||
226 | static int | ||
227 | vhost_transport_cancel_pkt(struct vsock_sock *vsk) | ||
228 | { | ||
229 | struct vhost_vsock *vsock; | ||
230 | struct virtio_vsock_pkt *pkt, *n; | ||
231 | int cnt = 0; | ||
232 | LIST_HEAD(freeme); | ||
233 | |||
234 | /* Find the vhost_vsock according to guest context id */ | ||
235 | vsock = vhost_vsock_get(vsk->remote_addr.svm_cid); | ||
236 | if (!vsock) | ||
237 | return -ENODEV; | ||
238 | |||
239 | spin_lock_bh(&vsock->send_pkt_list_lock); | ||
240 | list_for_each_entry_safe(pkt, n, &vsock->send_pkt_list, list) { | ||
241 | if (pkt->vsk != vsk) | ||
242 | continue; | ||
243 | list_move(&pkt->list, &freeme); | ||
244 | } | ||
245 | spin_unlock_bh(&vsock->send_pkt_list_lock); | ||
246 | |||
247 | list_for_each_entry_safe(pkt, n, &freeme, list) { | ||
248 | if (pkt->reply) | ||
249 | cnt++; | ||
250 | list_del(&pkt->list); | ||
251 | virtio_transport_free_pkt(pkt); | ||
252 | } | ||
253 | |||
254 | if (cnt) { | ||
255 | struct vhost_virtqueue *tx_vq = &vsock->vqs[VSOCK_VQ_TX]; | ||
256 | int new_cnt; | ||
257 | |||
258 | new_cnt = atomic_sub_return(cnt, &vsock->queued_replies); | ||
259 | if (new_cnt + cnt >= tx_vq->num && new_cnt < tx_vq->num) | ||
260 | vhost_poll_queue(&tx_vq->poll); | ||
261 | } | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
226 | static struct virtio_vsock_pkt * | 266 | static struct virtio_vsock_pkt * |
227 | vhost_vsock_alloc_pkt(struct vhost_virtqueue *vq, | 267 | vhost_vsock_alloc_pkt(struct vhost_virtqueue *vq, |
228 | unsigned int out, unsigned int in) | 268 | unsigned int out, unsigned int in) |
@@ -675,6 +715,7 @@ static struct virtio_transport vhost_transport = { | |||
675 | .release = virtio_transport_release, | 715 | .release = virtio_transport_release, |
676 | .connect = virtio_transport_connect, | 716 | .connect = virtio_transport_connect, |
677 | .shutdown = virtio_transport_shutdown, | 717 | .shutdown = virtio_transport_shutdown, |
718 | .cancel_pkt = vhost_transport_cancel_pkt, | ||
678 | 719 | ||
679 | .dgram_enqueue = virtio_transport_dgram_enqueue, | 720 | .dgram_enqueue = virtio_transport_dgram_enqueue, |
680 | .dgram_dequeue = virtio_transport_dgram_dequeue, | 721 | .dgram_dequeue = virtio_transport_dgram_dequeue, |
diff --git a/include/linux/errqueue.h b/include/linux/errqueue.h index 9ca23fcfb5d7..6fdfc884fdeb 100644 --- a/include/linux/errqueue.h +++ b/include/linux/errqueue.h | |||
@@ -20,6 +20,8 @@ struct sock_exterr_skb { | |||
20 | struct sock_extended_err ee; | 20 | struct sock_extended_err ee; |
21 | u16 addr_offset; | 21 | u16 addr_offset; |
22 | __be16 port; | 22 | __be16 port; |
23 | u8 opt_stats:1, | ||
24 | unused:7; | ||
23 | }; | 25 | }; |
24 | 26 | ||
25 | #endif | 27 | #endif |
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 7e66e4f62858..1beb1ec2fbdf 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h | |||
@@ -476,6 +476,7 @@ enum { | |||
476 | enum { | 476 | enum { |
477 | MLX4_INTERFACE_STATE_UP = 1 << 0, | 477 | MLX4_INTERFACE_STATE_UP = 1 << 0, |
478 | MLX4_INTERFACE_STATE_DELETION = 1 << 1, | 478 | MLX4_INTERFACE_STATE_DELETION = 1 << 1, |
479 | MLX4_INTERFACE_STATE_NOWAIT = 1 << 2, | ||
479 | }; | 480 | }; |
480 | 481 | ||
481 | #define MSTR_SM_CHANGE_MASK (MLX4_EQ_PORT_INFO_MSTR_SM_SL_CHANGE_MASK | \ | 482 | #define MSTR_SM_CHANGE_MASK (MLX4_EQ_PORT_INFO_MSTR_SM_SL_CHANGE_MASK | \ |
diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h index 9638bfeb0d1f..584f9a647ad4 100644 --- a/include/linux/virtio_vsock.h +++ b/include/linux/virtio_vsock.h | |||
@@ -48,6 +48,8 @@ struct virtio_vsock_pkt { | |||
48 | struct virtio_vsock_hdr hdr; | 48 | struct virtio_vsock_hdr hdr; |
49 | struct work_struct work; | 49 | struct work_struct work; |
50 | struct list_head list; | 50 | struct list_head list; |
51 | /* socket refcnt not held, only use for cancellation */ | ||
52 | struct vsock_sock *vsk; | ||
51 | void *buf; | 53 | void *buf; |
52 | u32 len; | 54 | u32 len; |
53 | u32 off; | 55 | u32 off; |
@@ -56,6 +58,7 @@ struct virtio_vsock_pkt { | |||
56 | 58 | ||
57 | struct virtio_vsock_pkt_info { | 59 | struct virtio_vsock_pkt_info { |
58 | u32 remote_cid, remote_port; | 60 | u32 remote_cid, remote_port; |
61 | struct vsock_sock *vsk; | ||
59 | struct msghdr *msg; | 62 | struct msghdr *msg; |
60 | u32 pkt_len; | 63 | u32 pkt_len; |
61 | u16 type; | 64 | u16 type; |
diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h index f2758964ce6f..f32ed9ac181a 100644 --- a/include/net/af_vsock.h +++ b/include/net/af_vsock.h | |||
@@ -100,6 +100,9 @@ struct vsock_transport { | |||
100 | void (*destruct)(struct vsock_sock *); | 100 | void (*destruct)(struct vsock_sock *); |
101 | void (*release)(struct vsock_sock *); | 101 | void (*release)(struct vsock_sock *); |
102 | 102 | ||
103 | /* Cancel all pending packets sent on vsock. */ | ||
104 | int (*cancel_pkt)(struct vsock_sock *vsk); | ||
105 | |||
103 | /* Connections. */ | 106 | /* Connections. */ |
104 | int (*connect)(struct vsock_sock *); | 107 | int (*connect)(struct vsock_sock *); |
105 | 108 | ||
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index f540f9ad2af4..19605878da47 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
@@ -244,7 +244,7 @@ extern s32 (*nf_ct_nat_offset)(const struct nf_conn *ct, | |||
244 | u32 seq); | 244 | u32 seq); |
245 | 245 | ||
246 | /* Fake conntrack entry for untracked connections */ | 246 | /* Fake conntrack entry for untracked connections */ |
247 | DECLARE_PER_CPU(struct nf_conn, nf_conntrack_untracked); | 247 | DECLARE_PER_CPU_ALIGNED(struct nf_conn, nf_conntrack_untracked); |
248 | static inline struct nf_conn *nf_ct_untracked_get(void) | 248 | static inline struct nf_conn *nf_ct_untracked_get(void) |
249 | { | 249 | { |
250 | return raw_cpu_ptr(&nf_conntrack_untracked); | 250 | return raw_cpu_ptr(&nf_conntrack_untracked); |
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 2aa8a9d80fbe..0136028652bd 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h | |||
@@ -103,6 +103,35 @@ struct nft_regs { | |||
103 | }; | 103 | }; |
104 | }; | 104 | }; |
105 | 105 | ||
106 | /* Store/load an u16 or u8 integer to/from the u32 data register. | ||
107 | * | ||
108 | * Note, when using concatenations, register allocation happens at 32-bit | ||
109 | * level. So for store instruction, pad the rest part with zero to avoid | ||
110 | * garbage values. | ||
111 | */ | ||
112 | |||
113 | static inline void nft_reg_store16(u32 *dreg, u16 val) | ||
114 | { | ||
115 | *dreg = 0; | ||
116 | *(u16 *)dreg = val; | ||
117 | } | ||
118 | |||
119 | static inline void nft_reg_store8(u32 *dreg, u8 val) | ||
120 | { | ||
121 | *dreg = 0; | ||
122 | *(u8 *)dreg = val; | ||
123 | } | ||
124 | |||
125 | static inline u16 nft_reg_load16(u32 *sreg) | ||
126 | { | ||
127 | return *(u16 *)sreg; | ||
128 | } | ||
129 | |||
130 | static inline u8 nft_reg_load8(u32 *sreg) | ||
131 | { | ||
132 | return *(u8 *)sreg; | ||
133 | } | ||
134 | |||
106 | static inline void nft_data_copy(u32 *dst, const struct nft_data *src, | 135 | static inline void nft_data_copy(u32 *dst, const struct nft_data *src, |
107 | unsigned int len) | 136 | unsigned int len) |
108 | { | 137 | { |
@@ -203,7 +232,6 @@ struct nft_set_elem { | |||
203 | struct nft_set; | 232 | struct nft_set; |
204 | struct nft_set_iter { | 233 | struct nft_set_iter { |
205 | u8 genmask; | 234 | u8 genmask; |
206 | bool flush; | ||
207 | unsigned int count; | 235 | unsigned int count; |
208 | unsigned int skip; | 236 | unsigned int skip; |
209 | int err; | 237 | int err; |
diff --git a/include/net/netfilter/nf_tables_ipv6.h b/include/net/netfilter/nf_tables_ipv6.h index d150b5066201..97983d1c05e4 100644 --- a/include/net/netfilter/nf_tables_ipv6.h +++ b/include/net/netfilter/nf_tables_ipv6.h | |||
@@ -9,12 +9,13 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, | |||
9 | struct sk_buff *skb, | 9 | struct sk_buff *skb, |
10 | const struct nf_hook_state *state) | 10 | const struct nf_hook_state *state) |
11 | { | 11 | { |
12 | unsigned int flags = IP6_FH_F_AUTH; | ||
12 | int protohdr, thoff = 0; | 13 | int protohdr, thoff = 0; |
13 | unsigned short frag_off; | 14 | unsigned short frag_off; |
14 | 15 | ||
15 | nft_set_pktinfo(pkt, skb, state); | 16 | nft_set_pktinfo(pkt, skb, state); |
16 | 17 | ||
17 | protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, NULL); | 18 | protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags); |
18 | if (protohdr < 0) { | 19 | if (protohdr < 0) { |
19 | nft_set_pktinfo_proto_unspec(pkt, skb); | 20 | nft_set_pktinfo_proto_unspec(pkt, skb); |
20 | return; | 21 | return; |
@@ -32,6 +33,7 @@ __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, | |||
32 | const struct nf_hook_state *state) | 33 | const struct nf_hook_state *state) |
33 | { | 34 | { |
34 | #if IS_ENABLED(CONFIG_IPV6) | 35 | #if IS_ENABLED(CONFIG_IPV6) |
36 | unsigned int flags = IP6_FH_F_AUTH; | ||
35 | struct ipv6hdr *ip6h, _ip6h; | 37 | struct ipv6hdr *ip6h, _ip6h; |
36 | unsigned int thoff = 0; | 38 | unsigned int thoff = 0; |
37 | unsigned short frag_off; | 39 | unsigned short frag_off; |
@@ -50,7 +52,7 @@ __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, | |||
50 | if (pkt_len + sizeof(*ip6h) > skb->len) | 52 | if (pkt_len + sizeof(*ip6h) > skb->len) |
51 | return -1; | 53 | return -1; |
52 | 54 | ||
53 | protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, NULL); | 55 | protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags); |
54 | if (protohdr < 0) | 56 | if (protohdr < 0) |
55 | return -1; | 57 | return -1; |
56 | 58 | ||
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 07a0b128625a..592decebac75 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -83,6 +83,7 @@ struct sctp_bind_addr; | |||
83 | struct sctp_ulpq; | 83 | struct sctp_ulpq; |
84 | struct sctp_ep_common; | 84 | struct sctp_ep_common; |
85 | struct crypto_shash; | 85 | struct crypto_shash; |
86 | struct sctp_stream; | ||
86 | 87 | ||
87 | 88 | ||
88 | #include <net/sctp/tsnmap.h> | 89 | #include <net/sctp/tsnmap.h> |
@@ -753,6 +754,8 @@ struct sctp_transport { | |||
753 | /* Is the Path MTU update pending on this tranport */ | 754 | /* Is the Path MTU update pending on this tranport */ |
754 | pmtu_pending:1, | 755 | pmtu_pending:1, |
755 | 756 | ||
757 | dst_pending_confirm:1, /* need to confirm neighbour */ | ||
758 | |||
756 | /* Has this transport moved the ctsn since we last sacked */ | 759 | /* Has this transport moved the ctsn since we last sacked */ |
757 | sack_generation:1; | 760 | sack_generation:1; |
758 | u32 dst_cookie; | 761 | u32 dst_cookie; |
@@ -806,8 +809,6 @@ struct sctp_transport { | |||
806 | 809 | ||
807 | __u32 burst_limited; /* Holds old cwnd when max.burst is applied */ | 810 | __u32 burst_limited; /* Holds old cwnd when max.burst is applied */ |
808 | 811 | ||
809 | __u32 dst_pending_confirm; /* need to confirm neighbour */ | ||
810 | |||
811 | /* Destination */ | 812 | /* Destination */ |
812 | struct dst_entry *dst; | 813 | struct dst_entry *dst; |
813 | /* Source address. */ | 814 | /* Source address. */ |
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index afe5bab376c9..361a69dfe543 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c | |||
@@ -30,18 +30,12 @@ struct bpf_htab { | |||
30 | struct pcpu_freelist freelist; | 30 | struct pcpu_freelist freelist; |
31 | struct bpf_lru lru; | 31 | struct bpf_lru lru; |
32 | }; | 32 | }; |
33 | void __percpu *extra_elems; | 33 | struct htab_elem *__percpu *extra_elems; |
34 | atomic_t count; /* number of elements in this hashtable */ | 34 | atomic_t count; /* number of elements in this hashtable */ |
35 | u32 n_buckets; /* number of hash buckets */ | 35 | u32 n_buckets; /* number of hash buckets */ |
36 | u32 elem_size; /* size of each element in bytes */ | 36 | u32 elem_size; /* size of each element in bytes */ |
37 | }; | 37 | }; |
38 | 38 | ||
39 | enum extra_elem_state { | ||
40 | HTAB_NOT_AN_EXTRA_ELEM = 0, | ||
41 | HTAB_EXTRA_ELEM_FREE, | ||
42 | HTAB_EXTRA_ELEM_USED | ||
43 | }; | ||
44 | |||
45 | /* each htab element is struct htab_elem + key + value */ | 39 | /* each htab element is struct htab_elem + key + value */ |
46 | struct htab_elem { | 40 | struct htab_elem { |
47 | union { | 41 | union { |
@@ -56,7 +50,6 @@ struct htab_elem { | |||
56 | }; | 50 | }; |
57 | union { | 51 | union { |
58 | struct rcu_head rcu; | 52 | struct rcu_head rcu; |
59 | enum extra_elem_state state; | ||
60 | struct bpf_lru_node lru_node; | 53 | struct bpf_lru_node lru_node; |
61 | }; | 54 | }; |
62 | u32 hash; | 55 | u32 hash; |
@@ -77,6 +70,11 @@ static bool htab_is_percpu(const struct bpf_htab *htab) | |||
77 | htab->map.map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH; | 70 | htab->map.map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH; |
78 | } | 71 | } |
79 | 72 | ||
73 | static bool htab_is_prealloc(const struct bpf_htab *htab) | ||
74 | { | ||
75 | return !(htab->map.map_flags & BPF_F_NO_PREALLOC); | ||
76 | } | ||
77 | |||
80 | static inline void htab_elem_set_ptr(struct htab_elem *l, u32 key_size, | 78 | static inline void htab_elem_set_ptr(struct htab_elem *l, u32 key_size, |
81 | void __percpu *pptr) | 79 | void __percpu *pptr) |
82 | { | 80 | { |
@@ -128,17 +126,20 @@ static struct htab_elem *prealloc_lru_pop(struct bpf_htab *htab, void *key, | |||
128 | 126 | ||
129 | static int prealloc_init(struct bpf_htab *htab) | 127 | static int prealloc_init(struct bpf_htab *htab) |
130 | { | 128 | { |
129 | u32 num_entries = htab->map.max_entries; | ||
131 | int err = -ENOMEM, i; | 130 | int err = -ENOMEM, i; |
132 | 131 | ||
133 | htab->elems = bpf_map_area_alloc(htab->elem_size * | 132 | if (!htab_is_percpu(htab) && !htab_is_lru(htab)) |
134 | htab->map.max_entries); | 133 | num_entries += num_possible_cpus(); |
134 | |||
135 | htab->elems = bpf_map_area_alloc(htab->elem_size * num_entries); | ||
135 | if (!htab->elems) | 136 | if (!htab->elems) |
136 | return -ENOMEM; | 137 | return -ENOMEM; |
137 | 138 | ||
138 | if (!htab_is_percpu(htab)) | 139 | if (!htab_is_percpu(htab)) |
139 | goto skip_percpu_elems; | 140 | goto skip_percpu_elems; |
140 | 141 | ||
141 | for (i = 0; i < htab->map.max_entries; i++) { | 142 | for (i = 0; i < num_entries; i++) { |
142 | u32 size = round_up(htab->map.value_size, 8); | 143 | u32 size = round_up(htab->map.value_size, 8); |
143 | void __percpu *pptr; | 144 | void __percpu *pptr; |
144 | 145 | ||
@@ -166,11 +167,11 @@ skip_percpu_elems: | |||
166 | if (htab_is_lru(htab)) | 167 | if (htab_is_lru(htab)) |
167 | bpf_lru_populate(&htab->lru, htab->elems, | 168 | bpf_lru_populate(&htab->lru, htab->elems, |
168 | offsetof(struct htab_elem, lru_node), | 169 | offsetof(struct htab_elem, lru_node), |
169 | htab->elem_size, htab->map.max_entries); | 170 | htab->elem_size, num_entries); |
170 | else | 171 | else |
171 | pcpu_freelist_populate(&htab->freelist, | 172 | pcpu_freelist_populate(&htab->freelist, |
172 | htab->elems + offsetof(struct htab_elem, fnode), | 173 | htab->elems + offsetof(struct htab_elem, fnode), |
173 | htab->elem_size, htab->map.max_entries); | 174 | htab->elem_size, num_entries); |
174 | 175 | ||
175 | return 0; | 176 | return 0; |
176 | 177 | ||
@@ -191,16 +192,22 @@ static void prealloc_destroy(struct bpf_htab *htab) | |||
191 | 192 | ||
192 | static int alloc_extra_elems(struct bpf_htab *htab) | 193 | static int alloc_extra_elems(struct bpf_htab *htab) |
193 | { | 194 | { |
194 | void __percpu *pptr; | 195 | struct htab_elem *__percpu *pptr, *l_new; |
196 | struct pcpu_freelist_node *l; | ||
195 | int cpu; | 197 | int cpu; |
196 | 198 | ||
197 | pptr = __alloc_percpu_gfp(htab->elem_size, 8, GFP_USER | __GFP_NOWARN); | 199 | pptr = __alloc_percpu_gfp(sizeof(struct htab_elem *), 8, |
200 | GFP_USER | __GFP_NOWARN); | ||
198 | if (!pptr) | 201 | if (!pptr) |
199 | return -ENOMEM; | 202 | return -ENOMEM; |
200 | 203 | ||
201 | for_each_possible_cpu(cpu) { | 204 | for_each_possible_cpu(cpu) { |
202 | ((struct htab_elem *)per_cpu_ptr(pptr, cpu))->state = | 205 | l = pcpu_freelist_pop(&htab->freelist); |
203 | HTAB_EXTRA_ELEM_FREE; | 206 | /* pop will succeed, since prealloc_init() |
207 | * preallocated extra num_possible_cpus elements | ||
208 | */ | ||
209 | l_new = container_of(l, struct htab_elem, fnode); | ||
210 | *per_cpu_ptr(pptr, cpu) = l_new; | ||
204 | } | 211 | } |
205 | htab->extra_elems = pptr; | 212 | htab->extra_elems = pptr; |
206 | return 0; | 213 | return 0; |
@@ -342,25 +349,25 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr) | |||
342 | raw_spin_lock_init(&htab->buckets[i].lock); | 349 | raw_spin_lock_init(&htab->buckets[i].lock); |
343 | } | 350 | } |
344 | 351 | ||
345 | if (!percpu && !lru) { | ||
346 | /* lru itself can remove the least used element, so | ||
347 | * there is no need for an extra elem during map_update. | ||
348 | */ | ||
349 | err = alloc_extra_elems(htab); | ||
350 | if (err) | ||
351 | goto free_buckets; | ||
352 | } | ||
353 | |||
354 | if (prealloc) { | 352 | if (prealloc) { |
355 | err = prealloc_init(htab); | 353 | err = prealloc_init(htab); |
356 | if (err) | 354 | if (err) |
357 | goto free_extra_elems; | 355 | goto free_buckets; |
356 | |||
357 | if (!percpu && !lru) { | ||
358 | /* lru itself can remove the least used element, so | ||
359 | * there is no need for an extra elem during map_update. | ||
360 | */ | ||
361 | err = alloc_extra_elems(htab); | ||
362 | if (err) | ||
363 | goto free_prealloc; | ||
364 | } | ||
358 | } | 365 | } |
359 | 366 | ||
360 | return &htab->map; | 367 | return &htab->map; |
361 | 368 | ||
362 | free_extra_elems: | 369 | free_prealloc: |
363 | free_percpu(htab->extra_elems); | 370 | prealloc_destroy(htab); |
364 | free_buckets: | 371 | free_buckets: |
365 | bpf_map_area_free(htab->buckets); | 372 | bpf_map_area_free(htab->buckets); |
366 | free_htab: | 373 | free_htab: |
@@ -575,12 +582,7 @@ static void htab_elem_free_rcu(struct rcu_head *head) | |||
575 | 582 | ||
576 | static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l) | 583 | static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l) |
577 | { | 584 | { |
578 | if (l->state == HTAB_EXTRA_ELEM_USED) { | 585 | if (htab_is_prealloc(htab)) { |
579 | l->state = HTAB_EXTRA_ELEM_FREE; | ||
580 | return; | ||
581 | } | ||
582 | |||
583 | if (!(htab->map.map_flags & BPF_F_NO_PREALLOC)) { | ||
584 | pcpu_freelist_push(&htab->freelist, &l->fnode); | 586 | pcpu_freelist_push(&htab->freelist, &l->fnode); |
585 | } else { | 587 | } else { |
586 | atomic_dec(&htab->count); | 588 | atomic_dec(&htab->count); |
@@ -610,47 +612,43 @@ static void pcpu_copy_value(struct bpf_htab *htab, void __percpu *pptr, | |||
610 | static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key, | 612 | static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key, |
611 | void *value, u32 key_size, u32 hash, | 613 | void *value, u32 key_size, u32 hash, |
612 | bool percpu, bool onallcpus, | 614 | bool percpu, bool onallcpus, |
613 | bool old_elem_exists) | 615 | struct htab_elem *old_elem) |
614 | { | 616 | { |
615 | u32 size = htab->map.value_size; | 617 | u32 size = htab->map.value_size; |
616 | bool prealloc = !(htab->map.map_flags & BPF_F_NO_PREALLOC); | 618 | bool prealloc = htab_is_prealloc(htab); |
617 | struct htab_elem *l_new; | 619 | struct htab_elem *l_new, **pl_new; |
618 | void __percpu *pptr; | 620 | void __percpu *pptr; |
619 | int err = 0; | ||
620 | 621 | ||
621 | if (prealloc) { | 622 | if (prealloc) { |
622 | struct pcpu_freelist_node *l; | 623 | if (old_elem) { |
624 | /* if we're updating the existing element, | ||
625 | * use per-cpu extra elems to avoid freelist_pop/push | ||
626 | */ | ||
627 | pl_new = this_cpu_ptr(htab->extra_elems); | ||
628 | l_new = *pl_new; | ||
629 | *pl_new = old_elem; | ||
630 | } else { | ||
631 | struct pcpu_freelist_node *l; | ||
623 | 632 | ||
624 | l = pcpu_freelist_pop(&htab->freelist); | 633 | l = pcpu_freelist_pop(&htab->freelist); |
625 | if (!l) | 634 | if (!l) |
626 | err = -E2BIG; | 635 | return ERR_PTR(-E2BIG); |
627 | else | ||
628 | l_new = container_of(l, struct htab_elem, fnode); | 636 | l_new = container_of(l, struct htab_elem, fnode); |
629 | } else { | ||
630 | if (atomic_inc_return(&htab->count) > htab->map.max_entries) { | ||
631 | atomic_dec(&htab->count); | ||
632 | err = -E2BIG; | ||
633 | } else { | ||
634 | l_new = kmalloc(htab->elem_size, | ||
635 | GFP_ATOMIC | __GFP_NOWARN); | ||
636 | if (!l_new) | ||
637 | return ERR_PTR(-ENOMEM); | ||
638 | } | 637 | } |
639 | } | ||
640 | |||
641 | if (err) { | ||
642 | if (!old_elem_exists) | ||
643 | return ERR_PTR(err); | ||
644 | |||
645 | /* if we're updating the existing element and the hash table | ||
646 | * is full, use per-cpu extra elems | ||
647 | */ | ||
648 | l_new = this_cpu_ptr(htab->extra_elems); | ||
649 | if (l_new->state != HTAB_EXTRA_ELEM_FREE) | ||
650 | return ERR_PTR(-E2BIG); | ||
651 | l_new->state = HTAB_EXTRA_ELEM_USED; | ||
652 | } else { | 638 | } else { |
653 | l_new->state = HTAB_NOT_AN_EXTRA_ELEM; | 639 | if (atomic_inc_return(&htab->count) > htab->map.max_entries) |
640 | if (!old_elem) { | ||
641 | /* when map is full and update() is replacing | ||
642 | * old element, it's ok to allocate, since | ||
643 | * old element will be freed immediately. | ||
644 | * Otherwise return an error | ||
645 | */ | ||
646 | atomic_dec(&htab->count); | ||
647 | return ERR_PTR(-E2BIG); | ||
648 | } | ||
649 | l_new = kmalloc(htab->elem_size, GFP_ATOMIC | __GFP_NOWARN); | ||
650 | if (!l_new) | ||
651 | return ERR_PTR(-ENOMEM); | ||
654 | } | 652 | } |
655 | 653 | ||
656 | memcpy(l_new->key, key, key_size); | 654 | memcpy(l_new->key, key, key_size); |
@@ -731,7 +729,7 @@ static int htab_map_update_elem(struct bpf_map *map, void *key, void *value, | |||
731 | goto err; | 729 | goto err; |
732 | 730 | ||
733 | l_new = alloc_htab_elem(htab, key, value, key_size, hash, false, false, | 731 | l_new = alloc_htab_elem(htab, key, value, key_size, hash, false, false, |
734 | !!l_old); | 732 | l_old); |
735 | if (IS_ERR(l_new)) { | 733 | if (IS_ERR(l_new)) { |
736 | /* all pre-allocated elements are in use or memory exhausted */ | 734 | /* all pre-allocated elements are in use or memory exhausted */ |
737 | ret = PTR_ERR(l_new); | 735 | ret = PTR_ERR(l_new); |
@@ -744,7 +742,8 @@ static int htab_map_update_elem(struct bpf_map *map, void *key, void *value, | |||
744 | hlist_nulls_add_head_rcu(&l_new->hash_node, head); | 742 | hlist_nulls_add_head_rcu(&l_new->hash_node, head); |
745 | if (l_old) { | 743 | if (l_old) { |
746 | hlist_nulls_del_rcu(&l_old->hash_node); | 744 | hlist_nulls_del_rcu(&l_old->hash_node); |
747 | free_htab_elem(htab, l_old); | 745 | if (!htab_is_prealloc(htab)) |
746 | free_htab_elem(htab, l_old); | ||
748 | } | 747 | } |
749 | ret = 0; | 748 | ret = 0; |
750 | err: | 749 | err: |
@@ -856,7 +855,7 @@ static int __htab_percpu_map_update_elem(struct bpf_map *map, void *key, | |||
856 | value, onallcpus); | 855 | value, onallcpus); |
857 | } else { | 856 | } else { |
858 | l_new = alloc_htab_elem(htab, key, value, key_size, | 857 | l_new = alloc_htab_elem(htab, key, value, key_size, |
859 | hash, true, onallcpus, false); | 858 | hash, true, onallcpus, NULL); |
860 | if (IS_ERR(l_new)) { | 859 | if (IS_ERR(l_new)) { |
861 | ret = PTR_ERR(l_new); | 860 | ret = PTR_ERR(l_new); |
862 | goto err; | 861 | goto err; |
@@ -1024,8 +1023,7 @@ static void delete_all_elements(struct bpf_htab *htab) | |||
1024 | 1023 | ||
1025 | hlist_nulls_for_each_entry_safe(l, n, head, hash_node) { | 1024 | hlist_nulls_for_each_entry_safe(l, n, head, hash_node) { |
1026 | hlist_nulls_del_rcu(&l->hash_node); | 1025 | hlist_nulls_del_rcu(&l->hash_node); |
1027 | if (l->state != HTAB_EXTRA_ELEM_USED) | 1026 | htab_elem_free(htab, l); |
1028 | htab_elem_free(htab, l); | ||
1029 | } | 1027 | } |
1030 | } | 1028 | } |
1031 | } | 1029 | } |
@@ -1045,7 +1043,7 @@ static void htab_map_free(struct bpf_map *map) | |||
1045 | * not have executed. Wait for them. | 1043 | * not have executed. Wait for them. |
1046 | */ | 1044 | */ |
1047 | rcu_barrier(); | 1045 | rcu_barrier(); |
1048 | if (htab->map.map_flags & BPF_F_NO_PREALLOC) | 1046 | if (!htab_is_prealloc(htab)) |
1049 | delete_all_elements(htab); | 1047 | delete_all_elements(htab); |
1050 | else | 1048 | else |
1051 | prealloc_destroy(htab); | 1049 | prealloc_destroy(htab); |
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 7c3d994e90d8..71343d0fec94 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
@@ -2477,6 +2477,16 @@ static void batadv_iv_iface_activate(struct batadv_hard_iface *hard_iface) | |||
2477 | batadv_iv_ogm_schedule(hard_iface); | 2477 | batadv_iv_ogm_schedule(hard_iface); |
2478 | } | 2478 | } |
2479 | 2479 | ||
2480 | /** | ||
2481 | * batadv_iv_init_sel_class - initialize GW selection class | ||
2482 | * @bat_priv: the bat priv with all the soft interface information | ||
2483 | */ | ||
2484 | static void batadv_iv_init_sel_class(struct batadv_priv *bat_priv) | ||
2485 | { | ||
2486 | /* set default TQ difference threshold to 20 */ | ||
2487 | atomic_set(&bat_priv->gw.sel_class, 20); | ||
2488 | } | ||
2489 | |||
2480 | static struct batadv_gw_node * | 2490 | static struct batadv_gw_node * |
2481 | batadv_iv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | 2491 | batadv_iv_gw_get_best_gw_node(struct batadv_priv *bat_priv) |
2482 | { | 2492 | { |
@@ -2823,6 +2833,7 @@ static struct batadv_algo_ops batadv_batman_iv __read_mostly = { | |||
2823 | .del_if = batadv_iv_ogm_orig_del_if, | 2833 | .del_if = batadv_iv_ogm_orig_del_if, |
2824 | }, | 2834 | }, |
2825 | .gw = { | 2835 | .gw = { |
2836 | .init_sel_class = batadv_iv_init_sel_class, | ||
2826 | .get_best_gw_node = batadv_iv_gw_get_best_gw_node, | 2837 | .get_best_gw_node = batadv_iv_gw_get_best_gw_node, |
2827 | .is_eligible = batadv_iv_gw_is_eligible, | 2838 | .is_eligible = batadv_iv_gw_is_eligible, |
2828 | #ifdef CONFIG_BATMAN_ADV_DEBUGFS | 2839 | #ifdef CONFIG_BATMAN_ADV_DEBUGFS |
diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c index 0acd081dd286..a36c8e7291d6 100644 --- a/net/batman-adv/bat_v.c +++ b/net/batman-adv/bat_v.c | |||
@@ -668,6 +668,16 @@ err_ifinfo1: | |||
668 | return ret; | 668 | return ret; |
669 | } | 669 | } |
670 | 670 | ||
671 | /** | ||
672 | * batadv_v_init_sel_class - initialize GW selection class | ||
673 | * @bat_priv: the bat priv with all the soft interface information | ||
674 | */ | ||
675 | static void batadv_v_init_sel_class(struct batadv_priv *bat_priv) | ||
676 | { | ||
677 | /* set default throughput difference threshold to 5Mbps */ | ||
678 | atomic_set(&bat_priv->gw.sel_class, 50); | ||
679 | } | ||
680 | |||
671 | static ssize_t batadv_v_store_sel_class(struct batadv_priv *bat_priv, | 681 | static ssize_t batadv_v_store_sel_class(struct batadv_priv *bat_priv, |
672 | char *buff, size_t count) | 682 | char *buff, size_t count) |
673 | { | 683 | { |
@@ -1052,6 +1062,7 @@ static struct batadv_algo_ops batadv_batman_v __read_mostly = { | |||
1052 | .dump = batadv_v_orig_dump, | 1062 | .dump = batadv_v_orig_dump, |
1053 | }, | 1063 | }, |
1054 | .gw = { | 1064 | .gw = { |
1065 | .init_sel_class = batadv_v_init_sel_class, | ||
1055 | .store_sel_class = batadv_v_store_sel_class, | 1066 | .store_sel_class = batadv_v_store_sel_class, |
1056 | .show_sel_class = batadv_v_show_sel_class, | 1067 | .show_sel_class = batadv_v_show_sel_class, |
1057 | .get_best_gw_node = batadv_v_gw_get_best_gw_node, | 1068 | .get_best_gw_node = batadv_v_gw_get_best_gw_node, |
@@ -1092,9 +1103,6 @@ int batadv_v_mesh_init(struct batadv_priv *bat_priv) | |||
1092 | if (ret < 0) | 1103 | if (ret < 0) |
1093 | return ret; | 1104 | return ret; |
1094 | 1105 | ||
1095 | /* set default throughput difference threshold to 5Mbps */ | ||
1096 | atomic_set(&bat_priv->gw.sel_class, 50); | ||
1097 | |||
1098 | return 0; | 1106 | return 0; |
1099 | } | 1107 | } |
1100 | 1108 | ||
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index 11a23fd6e1a0..8f964beaac28 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c | |||
@@ -404,7 +404,7 @@ out: | |||
404 | * batadv_frag_create - create a fragment from skb | 404 | * batadv_frag_create - create a fragment from skb |
405 | * @skb: skb to create fragment from | 405 | * @skb: skb to create fragment from |
406 | * @frag_head: header to use in new fragment | 406 | * @frag_head: header to use in new fragment |
407 | * @mtu: size of new fragment | 407 | * @fragment_size: size of new fragment |
408 | * | 408 | * |
409 | * Split the passed skb into two fragments: A new one with size matching the | 409 | * Split the passed skb into two fragments: A new one with size matching the |
410 | * passed mtu and the old one with the rest. The new skb contains data from the | 410 | * passed mtu and the old one with the rest. The new skb contains data from the |
@@ -414,11 +414,11 @@ out: | |||
414 | */ | 414 | */ |
415 | static struct sk_buff *batadv_frag_create(struct sk_buff *skb, | 415 | static struct sk_buff *batadv_frag_create(struct sk_buff *skb, |
416 | struct batadv_frag_packet *frag_head, | 416 | struct batadv_frag_packet *frag_head, |
417 | unsigned int mtu) | 417 | unsigned int fragment_size) |
418 | { | 418 | { |
419 | struct sk_buff *skb_fragment; | 419 | struct sk_buff *skb_fragment; |
420 | unsigned int header_size = sizeof(*frag_head); | 420 | unsigned int header_size = sizeof(*frag_head); |
421 | unsigned int fragment_size = mtu - header_size; | 421 | unsigned int mtu = fragment_size + header_size; |
422 | 422 | ||
423 | skb_fragment = netdev_alloc_skb(NULL, mtu + ETH_HLEN); | 423 | skb_fragment = netdev_alloc_skb(NULL, mtu + ETH_HLEN); |
424 | if (!skb_fragment) | 424 | if (!skb_fragment) |
@@ -456,7 +456,7 @@ int batadv_frag_send_packet(struct sk_buff *skb, | |||
456 | struct sk_buff *skb_fragment; | 456 | struct sk_buff *skb_fragment; |
457 | unsigned int mtu = neigh_node->if_incoming->net_dev->mtu; | 457 | unsigned int mtu = neigh_node->if_incoming->net_dev->mtu; |
458 | unsigned int header_size = sizeof(frag_header); | 458 | unsigned int header_size = sizeof(frag_header); |
459 | unsigned int max_fragment_size, max_packet_size; | 459 | unsigned int max_fragment_size, num_fragments; |
460 | int ret; | 460 | int ret; |
461 | 461 | ||
462 | /* To avoid merge and refragmentation at next-hops we never send | 462 | /* To avoid merge and refragmentation at next-hops we never send |
@@ -464,10 +464,15 @@ int batadv_frag_send_packet(struct sk_buff *skb, | |||
464 | */ | 464 | */ |
465 | mtu = min_t(unsigned int, mtu, BATADV_FRAG_MAX_FRAG_SIZE); | 465 | mtu = min_t(unsigned int, mtu, BATADV_FRAG_MAX_FRAG_SIZE); |
466 | max_fragment_size = mtu - header_size; | 466 | max_fragment_size = mtu - header_size; |
467 | max_packet_size = max_fragment_size * BATADV_FRAG_MAX_FRAGMENTS; | 467 | |
468 | if (skb->len == 0 || max_fragment_size == 0) | ||
469 | return -EINVAL; | ||
470 | |||
471 | num_fragments = (skb->len - 1) / max_fragment_size + 1; | ||
472 | max_fragment_size = (skb->len - 1) / num_fragments + 1; | ||
468 | 473 | ||
469 | /* Don't even try to fragment, if we need more than 16 fragments */ | 474 | /* Don't even try to fragment, if we need more than 16 fragments */ |
470 | if (skb->len > max_packet_size) { | 475 | if (num_fragments > BATADV_FRAG_MAX_FRAGMENTS) { |
471 | ret = -EAGAIN; | 476 | ret = -EAGAIN; |
472 | goto free_skb; | 477 | goto free_skb; |
473 | } | 478 | } |
@@ -507,7 +512,8 @@ int batadv_frag_send_packet(struct sk_buff *skb, | |||
507 | goto put_primary_if; | 512 | goto put_primary_if; |
508 | } | 513 | } |
509 | 514 | ||
510 | skb_fragment = batadv_frag_create(skb, &frag_header, mtu); | 515 | skb_fragment = batadv_frag_create(skb, &frag_header, |
516 | max_fragment_size); | ||
511 | if (!skb_fragment) { | 517 | if (!skb_fragment) { |
512 | ret = -ENOMEM; | 518 | ret = -ENOMEM; |
513 | goto put_primary_if; | 519 | goto put_primary_if; |
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c index 5db2e43e3775..33940c5c74a8 100644 --- a/net/batman-adv/gateway_common.c +++ b/net/batman-adv/gateway_common.c | |||
@@ -253,6 +253,11 @@ static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, | |||
253 | */ | 253 | */ |
254 | void batadv_gw_init(struct batadv_priv *bat_priv) | 254 | void batadv_gw_init(struct batadv_priv *bat_priv) |
255 | { | 255 | { |
256 | if (bat_priv->algo_ops->gw.init_sel_class) | ||
257 | bat_priv->algo_ops->gw.init_sel_class(bat_priv); | ||
258 | else | ||
259 | atomic_set(&bat_priv->gw.sel_class, 1); | ||
260 | |||
256 | batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1, | 261 | batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1, |
257 | NULL, BATADV_TVLV_GW, 1, | 262 | NULL, BATADV_TVLV_GW, 1, |
258 | BATADV_TVLV_HANDLER_OGM_CIFNOTFND); | 263 | BATADV_TVLV_HANDLER_OGM_CIFNOTFND); |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 5d099b2e6cfc..d042c99af028 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -819,7 +819,6 @@ static int batadv_softif_init_late(struct net_device *dev) | |||
819 | atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0); | 819 | atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0); |
820 | #endif | 820 | #endif |
821 | atomic_set(&bat_priv->gw.mode, BATADV_GW_MODE_OFF); | 821 | atomic_set(&bat_priv->gw.mode, BATADV_GW_MODE_OFF); |
822 | atomic_set(&bat_priv->gw.sel_class, 20); | ||
823 | atomic_set(&bat_priv->gw.bandwidth_down, 100); | 822 | atomic_set(&bat_priv->gw.bandwidth_down, 100); |
824 | atomic_set(&bat_priv->gw.bandwidth_up, 20); | 823 | atomic_set(&bat_priv->gw.bandwidth_up, 20); |
825 | atomic_set(&bat_priv->orig_interval, 1000); | 824 | atomic_set(&bat_priv->orig_interval, 1000); |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 66b25e410a41..246f21b4973b 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -1489,6 +1489,7 @@ struct batadv_algo_orig_ops { | |||
1489 | 1489 | ||
1490 | /** | 1490 | /** |
1491 | * struct batadv_algo_gw_ops - mesh algorithm callbacks (GW specific) | 1491 | * struct batadv_algo_gw_ops - mesh algorithm callbacks (GW specific) |
1492 | * @init_sel_class: initialize GW selection class (optional) | ||
1492 | * @store_sel_class: parse and stores a new GW selection class (optional) | 1493 | * @store_sel_class: parse and stores a new GW selection class (optional) |
1493 | * @show_sel_class: prints the current GW selection class (optional) | 1494 | * @show_sel_class: prints the current GW selection class (optional) |
1494 | * @get_best_gw_node: select the best GW from the list of available nodes | 1495 | * @get_best_gw_node: select the best GW from the list of available nodes |
@@ -1499,6 +1500,7 @@ struct batadv_algo_orig_ops { | |||
1499 | * @dump: dump gateways to a netlink socket (optional) | 1500 | * @dump: dump gateways to a netlink socket (optional) |
1500 | */ | 1501 | */ |
1501 | struct batadv_algo_gw_ops { | 1502 | struct batadv_algo_gw_ops { |
1503 | void (*init_sel_class)(struct batadv_priv *bat_priv); | ||
1502 | ssize_t (*store_sel_class)(struct batadv_priv *bat_priv, char *buff, | 1504 | ssize_t (*store_sel_class)(struct batadv_priv *bat_priv, char *buff, |
1503 | size_t count); | 1505 | size_t count); |
1504 | ssize_t (*show_sel_class)(struct batadv_priv *bat_priv, char *buff); | 1506 | ssize_t (*show_sel_class)(struct batadv_priv *bat_priv, char *buff); |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 4f598dc2d916..6e08b7199dd7 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -106,7 +106,7 @@ static struct net_bridge_fdb_entry *br_fdb_find(struct net_bridge *br, | |||
106 | struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)]; | 106 | struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)]; |
107 | struct net_bridge_fdb_entry *fdb; | 107 | struct net_bridge_fdb_entry *fdb; |
108 | 108 | ||
109 | WARN_ON_ONCE(!br_hash_lock_held(br)); | 109 | lockdep_assert_held_once(&br->hash_lock); |
110 | 110 | ||
111 | rcu_read_lock(); | 111 | rcu_read_lock(); |
112 | fdb = fdb_find_rcu(head, addr, vid); | 112 | fdb = fdb_find_rcu(head, addr, vid); |
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index fa87fbd62bb7..1f1e62095464 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c | |||
@@ -706,18 +706,20 @@ static unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb) | |||
706 | 706 | ||
707 | static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) | 707 | static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) |
708 | { | 708 | { |
709 | struct nf_bridge_info *nf_bridge; | 709 | struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); |
710 | unsigned int mtu_reserved; | 710 | unsigned int mtu, mtu_reserved; |
711 | 711 | ||
712 | mtu_reserved = nf_bridge_mtu_reduction(skb); | 712 | mtu_reserved = nf_bridge_mtu_reduction(skb); |
713 | mtu = skb->dev->mtu; | ||
714 | |||
715 | if (nf_bridge->frag_max_size && nf_bridge->frag_max_size < mtu) | ||
716 | mtu = nf_bridge->frag_max_size; | ||
713 | 717 | ||
714 | if (skb_is_gso(skb) || skb->len + mtu_reserved <= skb->dev->mtu) { | 718 | if (skb_is_gso(skb) || skb->len + mtu_reserved <= mtu) { |
715 | nf_bridge_info_free(skb); | 719 | nf_bridge_info_free(skb); |
716 | return br_dev_queue_push_xmit(net, sk, skb); | 720 | return br_dev_queue_push_xmit(net, sk, skb); |
717 | } | 721 | } |
718 | 722 | ||
719 | nf_bridge = nf_bridge_info_get(skb); | ||
720 | |||
721 | /* This is wrong! We should preserve the original fragment | 723 | /* This is wrong! We should preserve the original fragment |
722 | * boundaries by preserving frag_list rather than refragmenting. | 724 | * boundaries by preserving frag_list rather than refragmenting. |
723 | */ | 725 | */ |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 2288fca7756c..61368186edea 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -531,15 +531,6 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p, | |||
531 | int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p, | 531 | int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p, |
532 | const unsigned char *addr, u16 vid); | 532 | const unsigned char *addr, u16 vid); |
533 | 533 | ||
534 | static inline bool br_hash_lock_held(struct net_bridge *br) | ||
535 | { | ||
536 | #ifdef CONFIG_LOCKDEP | ||
537 | return lockdep_is_held(&br->hash_lock); | ||
538 | #else | ||
539 | return true; | ||
540 | #endif | ||
541 | } | ||
542 | |||
543 | /* br_forward.c */ | 534 | /* br_forward.c */ |
544 | enum br_pkt_type { | 535 | enum br_pkt_type { |
545 | BR_PKT_UNICAST, | 536 | BR_PKT_UNICAST, |
diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c index 6ae56037bb13..029a61ac6cdd 100644 --- a/net/core/netclassid_cgroup.c +++ b/net/core/netclassid_cgroup.c | |||
@@ -71,27 +71,17 @@ static int update_classid_sock(const void *v, struct file *file, unsigned n) | |||
71 | return 0; | 71 | return 0; |
72 | } | 72 | } |
73 | 73 | ||
74 | static void update_classid(struct cgroup_subsys_state *css, void *v) | 74 | static void cgrp_attach(struct cgroup_taskset *tset) |
75 | { | 75 | { |
76 | struct css_task_iter it; | 76 | struct cgroup_subsys_state *css; |
77 | struct task_struct *p; | 77 | struct task_struct *p; |
78 | 78 | ||
79 | css_task_iter_start(css, &it); | 79 | cgroup_taskset_for_each(p, css, tset) { |
80 | while ((p = css_task_iter_next(&it))) { | ||
81 | task_lock(p); | 80 | task_lock(p); |
82 | iterate_fd(p->files, 0, update_classid_sock, v); | 81 | iterate_fd(p->files, 0, update_classid_sock, |
82 | (void *)(unsigned long)css_cls_state(css)->classid); | ||
83 | task_unlock(p); | 83 | task_unlock(p); |
84 | } | 84 | } |
85 | css_task_iter_end(&it); | ||
86 | } | ||
87 | |||
88 | static void cgrp_attach(struct cgroup_taskset *tset) | ||
89 | { | ||
90 | struct cgroup_subsys_state *css; | ||
91 | |||
92 | cgroup_taskset_first(tset, &css); | ||
93 | update_classid(css, | ||
94 | (void *)(unsigned long)css_cls_state(css)->classid); | ||
95 | } | 85 | } |
96 | 86 | ||
97 | static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft) | 87 | static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft) |
@@ -103,12 +93,22 @@ static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft, | |||
103 | u64 value) | 93 | u64 value) |
104 | { | 94 | { |
105 | struct cgroup_cls_state *cs = css_cls_state(css); | 95 | struct cgroup_cls_state *cs = css_cls_state(css); |
96 | struct css_task_iter it; | ||
97 | struct task_struct *p; | ||
106 | 98 | ||
107 | cgroup_sk_alloc_disable(); | 99 | cgroup_sk_alloc_disable(); |
108 | 100 | ||
109 | cs->classid = (u32)value; | 101 | cs->classid = (u32)value; |
110 | 102 | ||
111 | update_classid(css, (void *)(unsigned long)cs->classid); | 103 | css_task_iter_start(css, &it); |
104 | while ((p = css_task_iter_next(&it))) { | ||
105 | task_lock(p); | ||
106 | iterate_fd(p->files, 0, update_classid_sock, | ||
107 | (void *)(unsigned long)cs->classid); | ||
108 | task_unlock(p); | ||
109 | } | ||
110 | css_task_iter_end(&it); | ||
111 | |||
112 | return 0; | 112 | return 0; |
113 | } | 113 | } |
114 | 114 | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index cd4ba8c6b609..9f781092fda9 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -3694,6 +3694,15 @@ static void sock_rmem_free(struct sk_buff *skb) | |||
3694 | atomic_sub(skb->truesize, &sk->sk_rmem_alloc); | 3694 | atomic_sub(skb->truesize, &sk->sk_rmem_alloc); |
3695 | } | 3695 | } |
3696 | 3696 | ||
3697 | static void skb_set_err_queue(struct sk_buff *skb) | ||
3698 | { | ||
3699 | /* pkt_type of skbs received on local sockets is never PACKET_OUTGOING. | ||
3700 | * So, it is safe to (mis)use it to mark skbs on the error queue. | ||
3701 | */ | ||
3702 | skb->pkt_type = PACKET_OUTGOING; | ||
3703 | BUILD_BUG_ON(PACKET_OUTGOING == 0); | ||
3704 | } | ||
3705 | |||
3697 | /* | 3706 | /* |
3698 | * Note: We dont mem charge error packets (no sk_forward_alloc changes) | 3707 | * Note: We dont mem charge error packets (no sk_forward_alloc changes) |
3699 | */ | 3708 | */ |
@@ -3707,6 +3716,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) | |||
3707 | skb->sk = sk; | 3716 | skb->sk = sk; |
3708 | skb->destructor = sock_rmem_free; | 3717 | skb->destructor = sock_rmem_free; |
3709 | atomic_add(skb->truesize, &sk->sk_rmem_alloc); | 3718 | atomic_add(skb->truesize, &sk->sk_rmem_alloc); |
3719 | skb_set_err_queue(skb); | ||
3710 | 3720 | ||
3711 | /* before exiting rcu section, make sure dst is refcounted */ | 3721 | /* before exiting rcu section, make sure dst is refcounted */ |
3712 | skb_dst_force(skb); | 3722 | skb_dst_force(skb); |
@@ -3783,16 +3793,20 @@ EXPORT_SYMBOL(skb_clone_sk); | |||
3783 | 3793 | ||
3784 | static void __skb_complete_tx_timestamp(struct sk_buff *skb, | 3794 | static void __skb_complete_tx_timestamp(struct sk_buff *skb, |
3785 | struct sock *sk, | 3795 | struct sock *sk, |
3786 | int tstype) | 3796 | int tstype, |
3797 | bool opt_stats) | ||
3787 | { | 3798 | { |
3788 | struct sock_exterr_skb *serr; | 3799 | struct sock_exterr_skb *serr; |
3789 | int err; | 3800 | int err; |
3790 | 3801 | ||
3802 | BUILD_BUG_ON(sizeof(struct sock_exterr_skb) > sizeof(skb->cb)); | ||
3803 | |||
3791 | serr = SKB_EXT_ERR(skb); | 3804 | serr = SKB_EXT_ERR(skb); |
3792 | memset(serr, 0, sizeof(*serr)); | 3805 | memset(serr, 0, sizeof(*serr)); |
3793 | serr->ee.ee_errno = ENOMSG; | 3806 | serr->ee.ee_errno = ENOMSG; |
3794 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; | 3807 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; |
3795 | serr->ee.ee_info = tstype; | 3808 | serr->ee.ee_info = tstype; |
3809 | serr->opt_stats = opt_stats; | ||
3796 | if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) { | 3810 | if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) { |
3797 | serr->ee.ee_data = skb_shinfo(skb)->tskey; | 3811 | serr->ee.ee_data = skb_shinfo(skb)->tskey; |
3798 | if (sk->sk_protocol == IPPROTO_TCP && | 3812 | if (sk->sk_protocol == IPPROTO_TCP && |
@@ -3833,7 +3847,7 @@ void skb_complete_tx_timestamp(struct sk_buff *skb, | |||
3833 | */ | 3847 | */ |
3834 | if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) { | 3848 | if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) { |
3835 | *skb_hwtstamps(skb) = *hwtstamps; | 3849 | *skb_hwtstamps(skb) = *hwtstamps; |
3836 | __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND); | 3850 | __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND, false); |
3837 | sock_put(sk); | 3851 | sock_put(sk); |
3838 | } | 3852 | } |
3839 | } | 3853 | } |
@@ -3844,7 +3858,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb, | |||
3844 | struct sock *sk, int tstype) | 3858 | struct sock *sk, int tstype) |
3845 | { | 3859 | { |
3846 | struct sk_buff *skb; | 3860 | struct sk_buff *skb; |
3847 | bool tsonly; | 3861 | bool tsonly, opt_stats = false; |
3848 | 3862 | ||
3849 | if (!sk) | 3863 | if (!sk) |
3850 | return; | 3864 | return; |
@@ -3857,9 +3871,10 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb, | |||
3857 | #ifdef CONFIG_INET | 3871 | #ifdef CONFIG_INET |
3858 | if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) && | 3872 | if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) && |
3859 | sk->sk_protocol == IPPROTO_TCP && | 3873 | sk->sk_protocol == IPPROTO_TCP && |
3860 | sk->sk_type == SOCK_STREAM) | 3874 | sk->sk_type == SOCK_STREAM) { |
3861 | skb = tcp_get_timestamping_opt_stats(sk); | 3875 | skb = tcp_get_timestamping_opt_stats(sk); |
3862 | else | 3876 | opt_stats = true; |
3877 | } else | ||
3863 | #endif | 3878 | #endif |
3864 | skb = alloc_skb(0, GFP_ATOMIC); | 3879 | skb = alloc_skb(0, GFP_ATOMIC); |
3865 | } else { | 3880 | } else { |
@@ -3878,7 +3893,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb, | |||
3878 | else | 3893 | else |
3879 | skb->tstamp = ktime_get_real(); | 3894 | skb->tstamp = ktime_get_real(); |
3880 | 3895 | ||
3881 | __skb_complete_tx_timestamp(skb, sk, tstype); | 3896 | __skb_complete_tx_timestamp(skb, sk, tstype, opt_stats); |
3882 | } | 3897 | } |
3883 | EXPORT_SYMBOL_GPL(__skb_tstamp_tx); | 3898 | EXPORT_SYMBOL_GPL(__skb_tstamp_tx); |
3884 | 3899 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index a96d5f7a5734..2c4f574168fb 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1442,6 +1442,11 @@ static void __sk_destruct(struct rcu_head *head) | |||
1442 | pr_debug("%s: optmem leakage (%d bytes) detected\n", | 1442 | pr_debug("%s: optmem leakage (%d bytes) detected\n", |
1443 | __func__, atomic_read(&sk->sk_omem_alloc)); | 1443 | __func__, atomic_read(&sk->sk_omem_alloc)); |
1444 | 1444 | ||
1445 | if (sk->sk_frag.page) { | ||
1446 | put_page(sk->sk_frag.page); | ||
1447 | sk->sk_frag.page = NULL; | ||
1448 | } | ||
1449 | |||
1445 | if (sk->sk_peer_cred) | 1450 | if (sk->sk_peer_cred) |
1446 | put_cred(sk->sk_peer_cred); | 1451 | put_cred(sk->sk_peer_cred); |
1447 | put_pid(sk->sk_peer_pid); | 1452 | put_pid(sk->sk_peer_pid); |
@@ -1539,6 +1544,12 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) | |||
1539 | is_charged = sk_filter_charge(newsk, filter); | 1544 | is_charged = sk_filter_charge(newsk, filter); |
1540 | 1545 | ||
1541 | if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk, sk))) { | 1546 | if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk, sk))) { |
1547 | /* We need to make sure that we don't uncharge the new | ||
1548 | * socket if we couldn't charge it in the first place | ||
1549 | * as otherwise we uncharge the parent's filter. | ||
1550 | */ | ||
1551 | if (!is_charged) | ||
1552 | RCU_INIT_POINTER(newsk->sk_filter, NULL); | ||
1542 | sk_free_unlock_clone(newsk); | 1553 | sk_free_unlock_clone(newsk); |
1543 | newsk = NULL; | 1554 | newsk = NULL; |
1544 | goto out; | 1555 | goto out; |
@@ -2787,11 +2798,6 @@ void sk_common_release(struct sock *sk) | |||
2787 | 2798 | ||
2788 | sk_refcnt_debug_release(sk); | 2799 | sk_refcnt_debug_release(sk); |
2789 | 2800 | ||
2790 | if (sk->sk_frag.page) { | ||
2791 | put_page(sk->sk_frag.page); | ||
2792 | sk->sk_frag.page = NULL; | ||
2793 | } | ||
2794 | |||
2795 | sock_put(sk); | 2801 | sock_put(sk); |
2796 | } | 2802 | } |
2797 | EXPORT_SYMBOL(sk_common_release); | 2803 | EXPORT_SYMBOL(sk_common_release); |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 42bfd08109dd..8f2133ffc2ff 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -1083,7 +1083,8 @@ static void nl_fib_input(struct sk_buff *skb) | |||
1083 | 1083 | ||
1084 | net = sock_net(skb->sk); | 1084 | net = sock_net(skb->sk); |
1085 | nlh = nlmsg_hdr(skb); | 1085 | nlh = nlmsg_hdr(skb); |
1086 | if (skb->len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len || | 1086 | if (skb->len < nlmsg_total_size(sizeof(*frn)) || |
1087 | skb->len < nlh->nlmsg_len || | ||
1087 | nlmsg_len(nlh) < sizeof(*frn)) | 1088 | nlmsg_len(nlh) < sizeof(*frn)) |
1088 | return; | 1089 | return; |
1089 | 1090 | ||
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index bbe7f72db9c1..b3cdeec85f1f 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -198,6 +198,7 @@ static void ip_expire(unsigned long arg) | |||
198 | qp = container_of((struct inet_frag_queue *) arg, struct ipq, q); | 198 | qp = container_of((struct inet_frag_queue *) arg, struct ipq, q); |
199 | net = container_of(qp->q.net, struct net, ipv4.frags); | 199 | net = container_of(qp->q.net, struct net, ipv4.frags); |
200 | 200 | ||
201 | rcu_read_lock(); | ||
201 | spin_lock(&qp->q.lock); | 202 | spin_lock(&qp->q.lock); |
202 | 203 | ||
203 | if (qp->q.flags & INET_FRAG_COMPLETE) | 204 | if (qp->q.flags & INET_FRAG_COMPLETE) |
@@ -207,7 +208,7 @@ static void ip_expire(unsigned long arg) | |||
207 | __IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS); | 208 | __IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS); |
208 | 209 | ||
209 | if (!inet_frag_evicting(&qp->q)) { | 210 | if (!inet_frag_evicting(&qp->q)) { |
210 | struct sk_buff *head = qp->q.fragments; | 211 | struct sk_buff *clone, *head = qp->q.fragments; |
211 | const struct iphdr *iph; | 212 | const struct iphdr *iph; |
212 | int err; | 213 | int err; |
213 | 214 | ||
@@ -216,32 +217,40 @@ static void ip_expire(unsigned long arg) | |||
216 | if (!(qp->q.flags & INET_FRAG_FIRST_IN) || !qp->q.fragments) | 217 | if (!(qp->q.flags & INET_FRAG_FIRST_IN) || !qp->q.fragments) |
217 | goto out; | 218 | goto out; |
218 | 219 | ||
219 | rcu_read_lock(); | ||
220 | head->dev = dev_get_by_index_rcu(net, qp->iif); | 220 | head->dev = dev_get_by_index_rcu(net, qp->iif); |
221 | if (!head->dev) | 221 | if (!head->dev) |
222 | goto out_rcu_unlock; | 222 | goto out; |
223 | |||
223 | 224 | ||
224 | /* skb has no dst, perform route lookup again */ | 225 | /* skb has no dst, perform route lookup again */ |
225 | iph = ip_hdr(head); | 226 | iph = ip_hdr(head); |
226 | err = ip_route_input_noref(head, iph->daddr, iph->saddr, | 227 | err = ip_route_input_noref(head, iph->daddr, iph->saddr, |
227 | iph->tos, head->dev); | 228 | iph->tos, head->dev); |
228 | if (err) | 229 | if (err) |
229 | goto out_rcu_unlock; | 230 | goto out; |
230 | 231 | ||
231 | /* Only an end host needs to send an ICMP | 232 | /* Only an end host needs to send an ICMP |
232 | * "Fragment Reassembly Timeout" message, per RFC792. | 233 | * "Fragment Reassembly Timeout" message, per RFC792. |
233 | */ | 234 | */ |
234 | if (frag_expire_skip_icmp(qp->user) && | 235 | if (frag_expire_skip_icmp(qp->user) && |
235 | (skb_rtable(head)->rt_type != RTN_LOCAL)) | 236 | (skb_rtable(head)->rt_type != RTN_LOCAL)) |
236 | goto out_rcu_unlock; | 237 | goto out; |
238 | |||
239 | clone = skb_clone(head, GFP_ATOMIC); | ||
237 | 240 | ||
238 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ | 241 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ |
239 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); | 242 | if (clone) { |
240 | out_rcu_unlock: | 243 | spin_unlock(&qp->q.lock); |
241 | rcu_read_unlock(); | 244 | icmp_send(clone, ICMP_TIME_EXCEEDED, |
245 | ICMP_EXC_FRAGTIME, 0); | ||
246 | consume_skb(clone); | ||
247 | goto out_rcu_unlock; | ||
248 | } | ||
242 | } | 249 | } |
243 | out: | 250 | out: |
244 | spin_unlock(&qp->q.lock); | 251 | spin_unlock(&qp->q.lock); |
252 | out_rcu_unlock: | ||
253 | rcu_read_unlock(); | ||
245 | ipq_put(qp); | 254 | ipq_put(qp); |
246 | } | 255 | } |
247 | 256 | ||
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index bc1486f2c064..2e14ed11a35c 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -165,6 +165,10 @@ static unsigned int ipv4_conntrack_local(void *priv, | |||
165 | if (skb->len < sizeof(struct iphdr) || | 165 | if (skb->len < sizeof(struct iphdr) || |
166 | ip_hdrlen(skb) < sizeof(struct iphdr)) | 166 | ip_hdrlen(skb) < sizeof(struct iphdr)) |
167 | return NF_ACCEPT; | 167 | return NF_ACCEPT; |
168 | |||
169 | if (ip_is_fragment(ip_hdr(skb))) /* IP_NODEFRAG setsockopt set */ | ||
170 | return NF_ACCEPT; | ||
171 | |||
168 | return nf_conntrack_in(state->net, PF_INET, state->hook, skb); | 172 | return nf_conntrack_in(state->net, PF_INET, state->hook, skb); |
169 | } | 173 | } |
170 | 174 | ||
diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c index f8aad03d674b..6f5e8d01b876 100644 --- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | |||
@@ -255,11 +255,6 @@ nf_nat_ipv4_fn(void *priv, struct sk_buff *skb, | |||
255 | /* maniptype == SRC for postrouting. */ | 255 | /* maniptype == SRC for postrouting. */ |
256 | enum nf_nat_manip_type maniptype = HOOK2MANIP(state->hook); | 256 | enum nf_nat_manip_type maniptype = HOOK2MANIP(state->hook); |
257 | 257 | ||
258 | /* We never see fragments: conntrack defrags on pre-routing | ||
259 | * and local-out, and nf_nat_out protects post-routing. | ||
260 | */ | ||
261 | NF_CT_ASSERT(!ip_is_fragment(ip_hdr(skb))); | ||
262 | |||
263 | ct = nf_ct_get(skb, &ctinfo); | 258 | ct = nf_ct_get(skb, &ctinfo); |
264 | /* Can't track? It's not due to stress, or conntrack would | 259 | /* Can't track? It's not due to stress, or conntrack would |
265 | * have dropped it. Hence it's the user's responsibilty to | 260 | * have dropped it. Hence it's the user's responsibilty to |
diff --git a/net/ipv4/netfilter/nft_masq_ipv4.c b/net/ipv4/netfilter/nft_masq_ipv4.c index a0ea8aad1bf1..f18677277119 100644 --- a/net/ipv4/netfilter/nft_masq_ipv4.c +++ b/net/ipv4/netfilter/nft_masq_ipv4.c | |||
@@ -26,10 +26,10 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr, | |||
26 | memset(&range, 0, sizeof(range)); | 26 | memset(&range, 0, sizeof(range)); |
27 | range.flags = priv->flags; | 27 | range.flags = priv->flags; |
28 | if (priv->sreg_proto_min) { | 28 | if (priv->sreg_proto_min) { |
29 | range.min_proto.all = | 29 | range.min_proto.all = (__force __be16)nft_reg_load16( |
30 | *(__be16 *)®s->data[priv->sreg_proto_min]; | 30 | ®s->data[priv->sreg_proto_min]); |
31 | range.max_proto.all = | 31 | range.max_proto.all = (__force __be16)nft_reg_load16( |
32 | *(__be16 *)®s->data[priv->sreg_proto_max]; | 32 | ®s->data[priv->sreg_proto_max]); |
33 | } | 33 | } |
34 | regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, nft_hook(pkt), | 34 | regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, nft_hook(pkt), |
35 | &range, nft_out(pkt)); | 35 | &range, nft_out(pkt)); |
diff --git a/net/ipv4/netfilter/nft_redir_ipv4.c b/net/ipv4/netfilter/nft_redir_ipv4.c index 1650ed23c15d..5120be1d3118 100644 --- a/net/ipv4/netfilter/nft_redir_ipv4.c +++ b/net/ipv4/netfilter/nft_redir_ipv4.c | |||
@@ -26,10 +26,10 @@ static void nft_redir_ipv4_eval(const struct nft_expr *expr, | |||
26 | 26 | ||
27 | memset(&mr, 0, sizeof(mr)); | 27 | memset(&mr, 0, sizeof(mr)); |
28 | if (priv->sreg_proto_min) { | 28 | if (priv->sreg_proto_min) { |
29 | mr.range[0].min.all = | 29 | mr.range[0].min.all = (__force __be16)nft_reg_load16( |
30 | *(__be16 *)®s->data[priv->sreg_proto_min]; | 30 | ®s->data[priv->sreg_proto_min]); |
31 | mr.range[0].max.all = | 31 | mr.range[0].max.all = (__force __be16)nft_reg_load16( |
32 | *(__be16 *)®s->data[priv->sreg_proto_max]; | 32 | ®s->data[priv->sreg_proto_max]); |
33 | mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; | 33 | mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
34 | } | 34 | } |
35 | 35 | ||
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index cf4555581282..1e319a525d51 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2770,7 +2770,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) | |||
2770 | { | 2770 | { |
2771 | const struct tcp_sock *tp = tcp_sk(sk); /* iff sk_type == SOCK_STREAM */ | 2771 | const struct tcp_sock *tp = tcp_sk(sk); /* iff sk_type == SOCK_STREAM */ |
2772 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2772 | const struct inet_connection_sock *icsk = inet_csk(sk); |
2773 | u32 now = tcp_time_stamp, intv; | 2773 | u32 now, intv; |
2774 | u64 rate64; | 2774 | u64 rate64; |
2775 | bool slow; | 2775 | bool slow; |
2776 | u32 rate; | 2776 | u32 rate; |
@@ -2839,6 +2839,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) | |||
2839 | info->tcpi_retrans = tp->retrans_out; | 2839 | info->tcpi_retrans = tp->retrans_out; |
2840 | info->tcpi_fackets = tp->fackets_out; | 2840 | info->tcpi_fackets = tp->fackets_out; |
2841 | 2841 | ||
2842 | now = tcp_time_stamp; | ||
2842 | info->tcpi_last_data_sent = jiffies_to_msecs(now - tp->lsndtime); | 2843 | info->tcpi_last_data_sent = jiffies_to_msecs(now - tp->lsndtime); |
2843 | info->tcpi_last_data_recv = jiffies_to_msecs(now - icsk->icsk_ack.lrcvtime); | 2844 | info->tcpi_last_data_recv = jiffies_to_msecs(now - icsk->icsk_ack.lrcvtime); |
2844 | info->tcpi_last_ack_recv = jiffies_to_msecs(now - tp->rcv_tstamp); | 2845 | info->tcpi_last_ack_recv = jiffies_to_msecs(now - tp->rcv_tstamp); |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 39c393cc0fd3..c43119726a62 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -5541,6 +5541,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb) | |||
5541 | struct inet_connection_sock *icsk = inet_csk(sk); | 5541 | struct inet_connection_sock *icsk = inet_csk(sk); |
5542 | 5542 | ||
5543 | tcp_set_state(sk, TCP_ESTABLISHED); | 5543 | tcp_set_state(sk, TCP_ESTABLISHED); |
5544 | icsk->icsk_ack.lrcvtime = tcp_time_stamp; | ||
5544 | 5545 | ||
5545 | if (skb) { | 5546 | if (skb) { |
5546 | icsk->icsk_af_ops->sk_rx_dst_set(sk, skb); | 5547 | icsk->icsk_af_ops->sk_rx_dst_set(sk, skb); |
@@ -5759,7 +5760,6 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, | |||
5759 | * to stand against the temptation 8) --ANK | 5760 | * to stand against the temptation 8) --ANK |
5760 | */ | 5761 | */ |
5761 | inet_csk_schedule_ack(sk); | 5762 | inet_csk_schedule_ack(sk); |
5762 | icsk->icsk_ack.lrcvtime = tcp_time_stamp; | ||
5763 | tcp_enter_quickack_mode(sk); | 5763 | tcp_enter_quickack_mode(sk); |
5764 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, | 5764 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, |
5765 | TCP_DELACK_MAX, TCP_RTO_MAX); | 5765 | TCP_DELACK_MAX, TCP_RTO_MAX); |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 7e16243cdb58..65c0f3d13eca 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -460,6 +460,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, | |||
460 | newtp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT); | 460 | newtp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT); |
461 | minmax_reset(&newtp->rtt_min, tcp_time_stamp, ~0U); | 461 | minmax_reset(&newtp->rtt_min, tcp_time_stamp, ~0U); |
462 | newicsk->icsk_rto = TCP_TIMEOUT_INIT; | 462 | newicsk->icsk_rto = TCP_TIMEOUT_INIT; |
463 | newicsk->icsk_ack.lrcvtime = tcp_time_stamp; | ||
463 | 464 | ||
464 | newtp->packets_out = 0; | 465 | newtp->packets_out = 0; |
465 | newtp->retrans_out = 0; | 466 | newtp->retrans_out = 0; |
diff --git a/net/ipv6/netfilter/nft_masq_ipv6.c b/net/ipv6/netfilter/nft_masq_ipv6.c index 6c5b5b1830a7..4146536e9c15 100644 --- a/net/ipv6/netfilter/nft_masq_ipv6.c +++ b/net/ipv6/netfilter/nft_masq_ipv6.c | |||
@@ -27,10 +27,10 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr, | |||
27 | memset(&range, 0, sizeof(range)); | 27 | memset(&range, 0, sizeof(range)); |
28 | range.flags = priv->flags; | 28 | range.flags = priv->flags; |
29 | if (priv->sreg_proto_min) { | 29 | if (priv->sreg_proto_min) { |
30 | range.min_proto.all = | 30 | range.min_proto.all = (__force __be16)nft_reg_load16( |
31 | *(__be16 *)®s->data[priv->sreg_proto_min]; | 31 | ®s->data[priv->sreg_proto_min]); |
32 | range.max_proto.all = | 32 | range.max_proto.all = (__force __be16)nft_reg_load16( |
33 | *(__be16 *)®s->data[priv->sreg_proto_max]; | 33 | ®s->data[priv->sreg_proto_max]); |
34 | } | 34 | } |
35 | regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range, | 35 | regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range, |
36 | nft_out(pkt)); | 36 | nft_out(pkt)); |
diff --git a/net/ipv6/netfilter/nft_redir_ipv6.c b/net/ipv6/netfilter/nft_redir_ipv6.c index f5ac080fc084..a27e424f690d 100644 --- a/net/ipv6/netfilter/nft_redir_ipv6.c +++ b/net/ipv6/netfilter/nft_redir_ipv6.c | |||
@@ -26,10 +26,10 @@ static void nft_redir_ipv6_eval(const struct nft_expr *expr, | |||
26 | 26 | ||
27 | memset(&range, 0, sizeof(range)); | 27 | memset(&range, 0, sizeof(range)); |
28 | if (priv->sreg_proto_min) { | 28 | if (priv->sreg_proto_min) { |
29 | range.min_proto.all = | 29 | range.min_proto.all = (__force __be16)nft_reg_load16( |
30 | *(__be16 *)®s->data[priv->sreg_proto_min], | 30 | ®s->data[priv->sreg_proto_min]); |
31 | range.max_proto.all = | 31 | range.max_proto.all = (__force __be16)nft_reg_load16( |
32 | *(__be16 *)®s->data[priv->sreg_proto_max], | 32 | ®s->data[priv->sreg_proto_max]); |
33 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; | 33 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
34 | } | 34 | } |
35 | 35 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 35c58b669ebd..9db1418993f2 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -3423,6 +3423,8 @@ static int rt6_fill_node(struct net *net, | |||
3423 | } | 3423 | } |
3424 | else if (rt->rt6i_flags & RTF_LOCAL) | 3424 | else if (rt->rt6i_flags & RTF_LOCAL) |
3425 | rtm->rtm_type = RTN_LOCAL; | 3425 | rtm->rtm_type = RTN_LOCAL; |
3426 | else if (rt->rt6i_flags & RTF_ANYCAST) | ||
3427 | rtm->rtm_type = RTN_ANYCAST; | ||
3426 | else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK)) | 3428 | else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK)) |
3427 | rtm->rtm_type = RTN_LOCAL; | 3429 | rtm->rtm_type = RTN_LOCAL; |
3428 | else | 3430 | else |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 4e4c401e3bc6..e28082f0a307 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -1035,6 +1035,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
1035 | ipc6.hlimit = -1; | 1035 | ipc6.hlimit = -1; |
1036 | ipc6.tclass = -1; | 1036 | ipc6.tclass = -1; |
1037 | ipc6.dontfrag = -1; | 1037 | ipc6.dontfrag = -1; |
1038 | sockc.tsflags = sk->sk_tsflags; | ||
1038 | 1039 | ||
1039 | /* destination address check */ | 1040 | /* destination address check */ |
1040 | if (sin6) { | 1041 | if (sin6) { |
@@ -1159,7 +1160,6 @@ do_udp_sendmsg: | |||
1159 | 1160 | ||
1160 | fl6.flowi6_mark = sk->sk_mark; | 1161 | fl6.flowi6_mark = sk->sk_mark; |
1161 | fl6.flowi6_uid = sk->sk_uid; | 1162 | fl6.flowi6_uid = sk->sk_uid; |
1162 | sockc.tsflags = sk->sk_tsflags; | ||
1163 | 1163 | ||
1164 | if (msg->msg_controllen) { | 1164 | if (msg->msg_controllen) { |
1165 | opt = &opt_space; | 1165 | opt = &opt_space; |
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index 33211f9a2656..6414079aa729 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c | |||
@@ -1269,6 +1269,8 @@ static void mpls_ifdown(struct net_device *dev, int event) | |||
1269 | { | 1269 | { |
1270 | struct mpls_route __rcu **platform_label; | 1270 | struct mpls_route __rcu **platform_label; |
1271 | struct net *net = dev_net(dev); | 1271 | struct net *net = dev_net(dev); |
1272 | unsigned int nh_flags = RTNH_F_DEAD | RTNH_F_LINKDOWN; | ||
1273 | unsigned int alive; | ||
1272 | unsigned index; | 1274 | unsigned index; |
1273 | 1275 | ||
1274 | platform_label = rtnl_dereference(net->mpls.platform_label); | 1276 | platform_label = rtnl_dereference(net->mpls.platform_label); |
@@ -1278,9 +1280,11 @@ static void mpls_ifdown(struct net_device *dev, int event) | |||
1278 | if (!rt) | 1280 | if (!rt) |
1279 | continue; | 1281 | continue; |
1280 | 1282 | ||
1283 | alive = 0; | ||
1281 | change_nexthops(rt) { | 1284 | change_nexthops(rt) { |
1282 | if (rtnl_dereference(nh->nh_dev) != dev) | 1285 | if (rtnl_dereference(nh->nh_dev) != dev) |
1283 | continue; | 1286 | goto next; |
1287 | |||
1284 | switch (event) { | 1288 | switch (event) { |
1285 | case NETDEV_DOWN: | 1289 | case NETDEV_DOWN: |
1286 | case NETDEV_UNREGISTER: | 1290 | case NETDEV_UNREGISTER: |
@@ -1288,13 +1292,16 @@ static void mpls_ifdown(struct net_device *dev, int event) | |||
1288 | /* fall through */ | 1292 | /* fall through */ |
1289 | case NETDEV_CHANGE: | 1293 | case NETDEV_CHANGE: |
1290 | nh->nh_flags |= RTNH_F_LINKDOWN; | 1294 | nh->nh_flags |= RTNH_F_LINKDOWN; |
1291 | if (event != NETDEV_UNREGISTER) | ||
1292 | ACCESS_ONCE(rt->rt_nhn_alive) = rt->rt_nhn_alive - 1; | ||
1293 | break; | 1295 | break; |
1294 | } | 1296 | } |
1295 | if (event == NETDEV_UNREGISTER) | 1297 | if (event == NETDEV_UNREGISTER) |
1296 | RCU_INIT_POINTER(nh->nh_dev, NULL); | 1298 | RCU_INIT_POINTER(nh->nh_dev, NULL); |
1299 | next: | ||
1300 | if (!(nh->nh_flags & nh_flags)) | ||
1301 | alive++; | ||
1297 | } endfor_nexthops(rt); | 1302 | } endfor_nexthops(rt); |
1303 | |||
1304 | WRITE_ONCE(rt->rt_nhn_alive, alive); | ||
1298 | } | 1305 | } |
1299 | } | 1306 | } |
1300 | 1307 | ||
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 071b97fcbefb..ffb78e5f7b70 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -181,7 +181,11 @@ EXPORT_SYMBOL_GPL(nf_conntrack_htable_size); | |||
181 | unsigned int nf_conntrack_max __read_mostly; | 181 | unsigned int nf_conntrack_max __read_mostly; |
182 | seqcount_t nf_conntrack_generation __read_mostly; | 182 | seqcount_t nf_conntrack_generation __read_mostly; |
183 | 183 | ||
184 | DEFINE_PER_CPU(struct nf_conn, nf_conntrack_untracked); | 184 | /* nf_conn must be 8 bytes aligned, as the 3 LSB bits are used |
185 | * for the nfctinfo. We cheat by (ab)using the PER CPU cache line | ||
186 | * alignment to enforce this. | ||
187 | */ | ||
188 | DEFINE_PER_CPU_ALIGNED(struct nf_conn, nf_conntrack_untracked); | ||
185 | EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked); | 189 | EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked); |
186 | 190 | ||
187 | static unsigned int nf_conntrack_hash_rnd __read_mostly; | 191 | static unsigned int nf_conntrack_hash_rnd __read_mostly; |
diff --git a/net/netfilter/nf_nat_proto_sctp.c b/net/netfilter/nf_nat_proto_sctp.c index 31d358691af0..804e8a0ab36e 100644 --- a/net/netfilter/nf_nat_proto_sctp.c +++ b/net/netfilter/nf_nat_proto_sctp.c | |||
@@ -33,8 +33,16 @@ sctp_manip_pkt(struct sk_buff *skb, | |||
33 | enum nf_nat_manip_type maniptype) | 33 | enum nf_nat_manip_type maniptype) |
34 | { | 34 | { |
35 | sctp_sctphdr_t *hdr; | 35 | sctp_sctphdr_t *hdr; |
36 | int hdrsize = 8; | ||
36 | 37 | ||
37 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) | 38 | /* This could be an inner header returned in imcp packet; in such |
39 | * cases we cannot update the checksum field since it is outside | ||
40 | * of the 8 bytes of transport layer headers we are guaranteed. | ||
41 | */ | ||
42 | if (skb->len >= hdroff + sizeof(*hdr)) | ||
43 | hdrsize = sizeof(*hdr); | ||
44 | |||
45 | if (!skb_make_writable(skb, hdroff + hdrsize)) | ||
38 | return false; | 46 | return false; |
39 | 47 | ||
40 | hdr = (struct sctphdr *)(skb->data + hdroff); | 48 | hdr = (struct sctphdr *)(skb->data + hdroff); |
@@ -47,6 +55,9 @@ sctp_manip_pkt(struct sk_buff *skb, | |||
47 | hdr->dest = tuple->dst.u.sctp.port; | 55 | hdr->dest = tuple->dst.u.sctp.port; |
48 | } | 56 | } |
49 | 57 | ||
58 | if (hdrsize < sizeof(*hdr)) | ||
59 | return true; | ||
60 | |||
50 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | 61 | if (skb->ip_summed != CHECKSUM_PARTIAL) { |
51 | hdr->checksum = sctp_compute_cksum(skb, hdroff); | 62 | hdr->checksum = sctp_compute_cksum(skb, hdroff); |
52 | skb->ip_summed = CHECKSUM_NONE; | 63 | skb->ip_summed = CHECKSUM_NONE; |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 5e0ccfd5bb37..434c739dfeca 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -3145,7 +3145,6 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set, | |||
3145 | iter.count = 0; | 3145 | iter.count = 0; |
3146 | iter.err = 0; | 3146 | iter.err = 0; |
3147 | iter.fn = nf_tables_bind_check_setelem; | 3147 | iter.fn = nf_tables_bind_check_setelem; |
3148 | iter.flush = false; | ||
3149 | 3148 | ||
3150 | set->ops->walk(ctx, set, &iter); | 3149 | set->ops->walk(ctx, set, &iter); |
3151 | if (iter.err < 0) | 3150 | if (iter.err < 0) |
@@ -3399,7 +3398,6 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) | |||
3399 | args.iter.count = 0; | 3398 | args.iter.count = 0; |
3400 | args.iter.err = 0; | 3399 | args.iter.err = 0; |
3401 | args.iter.fn = nf_tables_dump_setelem; | 3400 | args.iter.fn = nf_tables_dump_setelem; |
3402 | args.iter.flush = false; | ||
3403 | set->ops->walk(&ctx, set, &args.iter); | 3401 | set->ops->walk(&ctx, set, &args.iter); |
3404 | 3402 | ||
3405 | nla_nest_end(skb, nest); | 3403 | nla_nest_end(skb, nest); |
@@ -3963,7 +3961,6 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk, | |||
3963 | struct nft_set_iter iter = { | 3961 | struct nft_set_iter iter = { |
3964 | .genmask = genmask, | 3962 | .genmask = genmask, |
3965 | .fn = nft_flush_set, | 3963 | .fn = nft_flush_set, |
3966 | .flush = true, | ||
3967 | }; | 3964 | }; |
3968 | set->ops->walk(&ctx, set, &iter); | 3965 | set->ops->walk(&ctx, set, &iter); |
3969 | 3966 | ||
@@ -5114,7 +5111,6 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx, | |||
5114 | iter.count = 0; | 5111 | iter.count = 0; |
5115 | iter.err = 0; | 5112 | iter.err = 0; |
5116 | iter.fn = nf_tables_loop_check_setelem; | 5113 | iter.fn = nf_tables_loop_check_setelem; |
5117 | iter.flush = false; | ||
5118 | 5114 | ||
5119 | set->ops->walk(ctx, set, &iter); | 5115 | set->ops->walk(ctx, set, &iter); |
5120 | if (iter.err < 0) | 5116 | if (iter.err < 0) |
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index bf548a7a71ec..0264258c46fe 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c | |||
@@ -83,7 +83,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr, | |||
83 | 83 | ||
84 | switch (priv->key) { | 84 | switch (priv->key) { |
85 | case NFT_CT_DIRECTION: | 85 | case NFT_CT_DIRECTION: |
86 | *dest = CTINFO2DIR(ctinfo); | 86 | nft_reg_store8(dest, CTINFO2DIR(ctinfo)); |
87 | return; | 87 | return; |
88 | case NFT_CT_STATUS: | 88 | case NFT_CT_STATUS: |
89 | *dest = ct->status; | 89 | *dest = ct->status; |
@@ -151,20 +151,22 @@ static void nft_ct_get_eval(const struct nft_expr *expr, | |||
151 | return; | 151 | return; |
152 | } | 152 | } |
153 | case NFT_CT_L3PROTOCOL: | 153 | case NFT_CT_L3PROTOCOL: |
154 | *dest = nf_ct_l3num(ct); | 154 | nft_reg_store8(dest, nf_ct_l3num(ct)); |
155 | return; | 155 | return; |
156 | case NFT_CT_PROTOCOL: | 156 | case NFT_CT_PROTOCOL: |
157 | *dest = nf_ct_protonum(ct); | 157 | nft_reg_store8(dest, nf_ct_protonum(ct)); |
158 | return; | 158 | return; |
159 | #ifdef CONFIG_NF_CONNTRACK_ZONES | 159 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
160 | case NFT_CT_ZONE: { | 160 | case NFT_CT_ZONE: { |
161 | const struct nf_conntrack_zone *zone = nf_ct_zone(ct); | 161 | const struct nf_conntrack_zone *zone = nf_ct_zone(ct); |
162 | u16 zoneid; | ||
162 | 163 | ||
163 | if (priv->dir < IP_CT_DIR_MAX) | 164 | if (priv->dir < IP_CT_DIR_MAX) |
164 | *dest = nf_ct_zone_id(zone, priv->dir); | 165 | zoneid = nf_ct_zone_id(zone, priv->dir); |
165 | else | 166 | else |
166 | *dest = zone->id; | 167 | zoneid = zone->id; |
167 | 168 | ||
169 | nft_reg_store16(dest, zoneid); | ||
168 | return; | 170 | return; |
169 | } | 171 | } |
170 | #endif | 172 | #endif |
@@ -183,10 +185,10 @@ static void nft_ct_get_eval(const struct nft_expr *expr, | |||
183 | nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16); | 185 | nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16); |
184 | return; | 186 | return; |
185 | case NFT_CT_PROTO_SRC: | 187 | case NFT_CT_PROTO_SRC: |
186 | *dest = (__force __u16)tuple->src.u.all; | 188 | nft_reg_store16(dest, (__force u16)tuple->src.u.all); |
187 | return; | 189 | return; |
188 | case NFT_CT_PROTO_DST: | 190 | case NFT_CT_PROTO_DST: |
189 | *dest = (__force __u16)tuple->dst.u.all; | 191 | nft_reg_store16(dest, (__force u16)tuple->dst.u.all); |
190 | return; | 192 | return; |
191 | default: | 193 | default: |
192 | break; | 194 | break; |
@@ -205,7 +207,7 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr, | |||
205 | const struct nft_ct *priv = nft_expr_priv(expr); | 207 | const struct nft_ct *priv = nft_expr_priv(expr); |
206 | struct sk_buff *skb = pkt->skb; | 208 | struct sk_buff *skb = pkt->skb; |
207 | enum ip_conntrack_info ctinfo; | 209 | enum ip_conntrack_info ctinfo; |
208 | u16 value = regs->data[priv->sreg]; | 210 | u16 value = nft_reg_load16(®s->data[priv->sreg]); |
209 | struct nf_conn *ct; | 211 | struct nf_conn *ct; |
210 | 212 | ||
211 | ct = nf_ct_get(skb, &ctinfo); | 213 | ct = nf_ct_get(skb, &ctinfo); |
@@ -542,7 +544,8 @@ static int nft_ct_set_init(const struct nft_ctx *ctx, | |||
542 | case IP_CT_DIR_REPLY: | 544 | case IP_CT_DIR_REPLY: |
543 | break; | 545 | break; |
544 | default: | 546 | default: |
545 | return -EINVAL; | 547 | err = -EINVAL; |
548 | goto err1; | ||
546 | } | 549 | } |
547 | } | 550 | } |
548 | 551 | ||
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index e1f5ca9b423b..7b60e01f38ff 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c | |||
@@ -45,16 +45,15 @@ void nft_meta_get_eval(const struct nft_expr *expr, | |||
45 | *dest = skb->len; | 45 | *dest = skb->len; |
46 | break; | 46 | break; |
47 | case NFT_META_PROTOCOL: | 47 | case NFT_META_PROTOCOL: |
48 | *dest = 0; | 48 | nft_reg_store16(dest, (__force u16)skb->protocol); |
49 | *(__be16 *)dest = skb->protocol; | ||
50 | break; | 49 | break; |
51 | case NFT_META_NFPROTO: | 50 | case NFT_META_NFPROTO: |
52 | *dest = nft_pf(pkt); | 51 | nft_reg_store8(dest, nft_pf(pkt)); |
53 | break; | 52 | break; |
54 | case NFT_META_L4PROTO: | 53 | case NFT_META_L4PROTO: |
55 | if (!pkt->tprot_set) | 54 | if (!pkt->tprot_set) |
56 | goto err; | 55 | goto err; |
57 | *dest = pkt->tprot; | 56 | nft_reg_store8(dest, pkt->tprot); |
58 | break; | 57 | break; |
59 | case NFT_META_PRIORITY: | 58 | case NFT_META_PRIORITY: |
60 | *dest = skb->priority; | 59 | *dest = skb->priority; |
@@ -85,14 +84,12 @@ void nft_meta_get_eval(const struct nft_expr *expr, | |||
85 | case NFT_META_IIFTYPE: | 84 | case NFT_META_IIFTYPE: |
86 | if (in == NULL) | 85 | if (in == NULL) |
87 | goto err; | 86 | goto err; |
88 | *dest = 0; | 87 | nft_reg_store16(dest, in->type); |
89 | *(u16 *)dest = in->type; | ||
90 | break; | 88 | break; |
91 | case NFT_META_OIFTYPE: | 89 | case NFT_META_OIFTYPE: |
92 | if (out == NULL) | 90 | if (out == NULL) |
93 | goto err; | 91 | goto err; |
94 | *dest = 0; | 92 | nft_reg_store16(dest, out->type); |
95 | *(u16 *)dest = out->type; | ||
96 | break; | 93 | break; |
97 | case NFT_META_SKUID: | 94 | case NFT_META_SKUID: |
98 | sk = skb_to_full_sk(skb); | 95 | sk = skb_to_full_sk(skb); |
@@ -142,19 +139,19 @@ void nft_meta_get_eval(const struct nft_expr *expr, | |||
142 | #endif | 139 | #endif |
143 | case NFT_META_PKTTYPE: | 140 | case NFT_META_PKTTYPE: |
144 | if (skb->pkt_type != PACKET_LOOPBACK) { | 141 | if (skb->pkt_type != PACKET_LOOPBACK) { |
145 | *dest = skb->pkt_type; | 142 | nft_reg_store8(dest, skb->pkt_type); |
146 | break; | 143 | break; |
147 | } | 144 | } |
148 | 145 | ||
149 | switch (nft_pf(pkt)) { | 146 | switch (nft_pf(pkt)) { |
150 | case NFPROTO_IPV4: | 147 | case NFPROTO_IPV4: |
151 | if (ipv4_is_multicast(ip_hdr(skb)->daddr)) | 148 | if (ipv4_is_multicast(ip_hdr(skb)->daddr)) |
152 | *dest = PACKET_MULTICAST; | 149 | nft_reg_store8(dest, PACKET_MULTICAST); |
153 | else | 150 | else |
154 | *dest = PACKET_BROADCAST; | 151 | nft_reg_store8(dest, PACKET_BROADCAST); |
155 | break; | 152 | break; |
156 | case NFPROTO_IPV6: | 153 | case NFPROTO_IPV6: |
157 | *dest = PACKET_MULTICAST; | 154 | nft_reg_store8(dest, PACKET_MULTICAST); |
158 | break; | 155 | break; |
159 | case NFPROTO_NETDEV: | 156 | case NFPROTO_NETDEV: |
160 | switch (skb->protocol) { | 157 | switch (skb->protocol) { |
@@ -168,14 +165,14 @@ void nft_meta_get_eval(const struct nft_expr *expr, | |||
168 | goto err; | 165 | goto err; |
169 | 166 | ||
170 | if (ipv4_is_multicast(iph->daddr)) | 167 | if (ipv4_is_multicast(iph->daddr)) |
171 | *dest = PACKET_MULTICAST; | 168 | nft_reg_store8(dest, PACKET_MULTICAST); |
172 | else | 169 | else |
173 | *dest = PACKET_BROADCAST; | 170 | nft_reg_store8(dest, PACKET_BROADCAST); |
174 | 171 | ||
175 | break; | 172 | break; |
176 | } | 173 | } |
177 | case htons(ETH_P_IPV6): | 174 | case htons(ETH_P_IPV6): |
178 | *dest = PACKET_MULTICAST; | 175 | nft_reg_store8(dest, PACKET_MULTICAST); |
179 | break; | 176 | break; |
180 | default: | 177 | default: |
181 | WARN_ON_ONCE(1); | 178 | WARN_ON_ONCE(1); |
@@ -230,7 +227,9 @@ void nft_meta_set_eval(const struct nft_expr *expr, | |||
230 | { | 227 | { |
231 | const struct nft_meta *meta = nft_expr_priv(expr); | 228 | const struct nft_meta *meta = nft_expr_priv(expr); |
232 | struct sk_buff *skb = pkt->skb; | 229 | struct sk_buff *skb = pkt->skb; |
233 | u32 value = regs->data[meta->sreg]; | 230 | u32 *sreg = ®s->data[meta->sreg]; |
231 | u32 value = *sreg; | ||
232 | u8 pkt_type; | ||
234 | 233 | ||
235 | switch (meta->key) { | 234 | switch (meta->key) { |
236 | case NFT_META_MARK: | 235 | case NFT_META_MARK: |
@@ -240,9 +239,12 @@ void nft_meta_set_eval(const struct nft_expr *expr, | |||
240 | skb->priority = value; | 239 | skb->priority = value; |
241 | break; | 240 | break; |
242 | case NFT_META_PKTTYPE: | 241 | case NFT_META_PKTTYPE: |
243 | if (skb->pkt_type != value && | 242 | pkt_type = nft_reg_load8(sreg); |
244 | skb_pkt_type_ok(value) && skb_pkt_type_ok(skb->pkt_type)) | 243 | |
245 | skb->pkt_type = value; | 244 | if (skb->pkt_type != pkt_type && |
245 | skb_pkt_type_ok(pkt_type) && | ||
246 | skb_pkt_type_ok(skb->pkt_type)) | ||
247 | skb->pkt_type = pkt_type; | ||
246 | break; | 248 | break; |
247 | case NFT_META_NFTRACE: | 249 | case NFT_META_NFTRACE: |
248 | skb->nf_trace = !!value; | 250 | skb->nf_trace = !!value; |
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c index 19a7bf3236f9..439e0bd152a0 100644 --- a/net/netfilter/nft_nat.c +++ b/net/netfilter/nft_nat.c | |||
@@ -65,10 +65,10 @@ static void nft_nat_eval(const struct nft_expr *expr, | |||
65 | } | 65 | } |
66 | 66 | ||
67 | if (priv->sreg_proto_min) { | 67 | if (priv->sreg_proto_min) { |
68 | range.min_proto.all = | 68 | range.min_proto.all = (__force __be16)nft_reg_load16( |
69 | *(__be16 *)®s->data[priv->sreg_proto_min]; | 69 | ®s->data[priv->sreg_proto_min]); |
70 | range.max_proto.all = | 70 | range.max_proto.all = (__force __be16)nft_reg_load16( |
71 | *(__be16 *)®s->data[priv->sreg_proto_max]; | 71 | ®s->data[priv->sreg_proto_max]); |
72 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; | 72 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
73 | } | 73 | } |
74 | 74 | ||
diff --git a/net/netfilter/nft_set_bitmap.c b/net/netfilter/nft_set_bitmap.c index 152d226552c1..8ebbc2940f4c 100644 --- a/net/netfilter/nft_set_bitmap.c +++ b/net/netfilter/nft_set_bitmap.c | |||
@@ -15,6 +15,11 @@ | |||
15 | #include <linux/netfilter/nf_tables.h> | 15 | #include <linux/netfilter/nf_tables.h> |
16 | #include <net/netfilter/nf_tables.h> | 16 | #include <net/netfilter/nf_tables.h> |
17 | 17 | ||
18 | struct nft_bitmap_elem { | ||
19 | struct list_head head; | ||
20 | struct nft_set_ext ext; | ||
21 | }; | ||
22 | |||
18 | /* This bitmap uses two bits to represent one element. These two bits determine | 23 | /* This bitmap uses two bits to represent one element. These two bits determine |
19 | * the element state in the current and the future generation. | 24 | * the element state in the current and the future generation. |
20 | * | 25 | * |
@@ -41,13 +46,22 @@ | |||
41 | * restore its previous state. | 46 | * restore its previous state. |
42 | */ | 47 | */ |
43 | struct nft_bitmap { | 48 | struct nft_bitmap { |
44 | u16 bitmap_size; | 49 | struct list_head list; |
45 | u8 bitmap[]; | 50 | u16 bitmap_size; |
51 | u8 bitmap[]; | ||
46 | }; | 52 | }; |
47 | 53 | ||
48 | static inline void nft_bitmap_location(u32 key, u32 *idx, u32 *off) | 54 | static inline void nft_bitmap_location(const struct nft_set *set, |
55 | const void *key, | ||
56 | u32 *idx, u32 *off) | ||
49 | { | 57 | { |
50 | u32 k = (key << 1); | 58 | u32 k; |
59 | |||
60 | if (set->klen == 2) | ||
61 | k = *(u16 *)key; | ||
62 | else | ||
63 | k = *(u8 *)key; | ||
64 | k <<= 1; | ||
51 | 65 | ||
52 | *idx = k / BITS_PER_BYTE; | 66 | *idx = k / BITS_PER_BYTE; |
53 | *off = k % BITS_PER_BYTE; | 67 | *off = k % BITS_PER_BYTE; |
@@ -69,26 +83,48 @@ static bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set, | |||
69 | u8 genmask = nft_genmask_cur(net); | 83 | u8 genmask = nft_genmask_cur(net); |
70 | u32 idx, off; | 84 | u32 idx, off; |
71 | 85 | ||
72 | nft_bitmap_location(*key, &idx, &off); | 86 | nft_bitmap_location(set, key, &idx, &off); |
73 | 87 | ||
74 | return nft_bitmap_active(priv->bitmap, idx, off, genmask); | 88 | return nft_bitmap_active(priv->bitmap, idx, off, genmask); |
75 | } | 89 | } |
76 | 90 | ||
91 | static struct nft_bitmap_elem * | ||
92 | nft_bitmap_elem_find(const struct nft_set *set, struct nft_bitmap_elem *this, | ||
93 | u8 genmask) | ||
94 | { | ||
95 | const struct nft_bitmap *priv = nft_set_priv(set); | ||
96 | struct nft_bitmap_elem *be; | ||
97 | |||
98 | list_for_each_entry_rcu(be, &priv->list, head) { | ||
99 | if (memcmp(nft_set_ext_key(&be->ext), | ||
100 | nft_set_ext_key(&this->ext), set->klen) || | ||
101 | !nft_set_elem_active(&be->ext, genmask)) | ||
102 | continue; | ||
103 | |||
104 | return be; | ||
105 | } | ||
106 | return NULL; | ||
107 | } | ||
108 | |||
77 | static int nft_bitmap_insert(const struct net *net, const struct nft_set *set, | 109 | static int nft_bitmap_insert(const struct net *net, const struct nft_set *set, |
78 | const struct nft_set_elem *elem, | 110 | const struct nft_set_elem *elem, |
79 | struct nft_set_ext **_ext) | 111 | struct nft_set_ext **ext) |
80 | { | 112 | { |
81 | struct nft_bitmap *priv = nft_set_priv(set); | 113 | struct nft_bitmap *priv = nft_set_priv(set); |
82 | struct nft_set_ext *ext = elem->priv; | 114 | struct nft_bitmap_elem *new = elem->priv, *be; |
83 | u8 genmask = nft_genmask_next(net); | 115 | u8 genmask = nft_genmask_next(net); |
84 | u32 idx, off; | 116 | u32 idx, off; |
85 | 117 | ||
86 | nft_bitmap_location(nft_set_ext_key(ext)->data[0], &idx, &off); | 118 | be = nft_bitmap_elem_find(set, new, genmask); |
87 | if (nft_bitmap_active(priv->bitmap, idx, off, genmask)) | 119 | if (be) { |
120 | *ext = &be->ext; | ||
88 | return -EEXIST; | 121 | return -EEXIST; |
122 | } | ||
89 | 123 | ||
124 | nft_bitmap_location(set, nft_set_ext_key(&new->ext), &idx, &off); | ||
90 | /* Enter 01 state. */ | 125 | /* Enter 01 state. */ |
91 | priv->bitmap[idx] |= (genmask << off); | 126 | priv->bitmap[idx] |= (genmask << off); |
127 | list_add_tail_rcu(&new->head, &priv->list); | ||
92 | 128 | ||
93 | return 0; | 129 | return 0; |
94 | } | 130 | } |
@@ -98,13 +134,14 @@ static void nft_bitmap_remove(const struct net *net, | |||
98 | const struct nft_set_elem *elem) | 134 | const struct nft_set_elem *elem) |
99 | { | 135 | { |
100 | struct nft_bitmap *priv = nft_set_priv(set); | 136 | struct nft_bitmap *priv = nft_set_priv(set); |
101 | struct nft_set_ext *ext = elem->priv; | 137 | struct nft_bitmap_elem *be = elem->priv; |
102 | u8 genmask = nft_genmask_next(net); | 138 | u8 genmask = nft_genmask_next(net); |
103 | u32 idx, off; | 139 | u32 idx, off; |
104 | 140 | ||
105 | nft_bitmap_location(nft_set_ext_key(ext)->data[0], &idx, &off); | 141 | nft_bitmap_location(set, nft_set_ext_key(&be->ext), &idx, &off); |
106 | /* Enter 00 state. */ | 142 | /* Enter 00 state. */ |
107 | priv->bitmap[idx] &= ~(genmask << off); | 143 | priv->bitmap[idx] &= ~(genmask << off); |
144 | list_del_rcu(&be->head); | ||
108 | } | 145 | } |
109 | 146 | ||
110 | static void nft_bitmap_activate(const struct net *net, | 147 | static void nft_bitmap_activate(const struct net *net, |
@@ -112,74 +149,52 @@ static void nft_bitmap_activate(const struct net *net, | |||
112 | const struct nft_set_elem *elem) | 149 | const struct nft_set_elem *elem) |
113 | { | 150 | { |
114 | struct nft_bitmap *priv = nft_set_priv(set); | 151 | struct nft_bitmap *priv = nft_set_priv(set); |
115 | struct nft_set_ext *ext = elem->priv; | 152 | struct nft_bitmap_elem *be = elem->priv; |
116 | u8 genmask = nft_genmask_next(net); | 153 | u8 genmask = nft_genmask_next(net); |
117 | u32 idx, off; | 154 | u32 idx, off; |
118 | 155 | ||
119 | nft_bitmap_location(nft_set_ext_key(ext)->data[0], &idx, &off); | 156 | nft_bitmap_location(set, nft_set_ext_key(&be->ext), &idx, &off); |
120 | /* Enter 11 state. */ | 157 | /* Enter 11 state. */ |
121 | priv->bitmap[idx] |= (genmask << off); | 158 | priv->bitmap[idx] |= (genmask << off); |
159 | nft_set_elem_change_active(net, set, &be->ext); | ||
122 | } | 160 | } |
123 | 161 | ||
124 | static bool nft_bitmap_flush(const struct net *net, | 162 | static bool nft_bitmap_flush(const struct net *net, |
125 | const struct nft_set *set, void *ext) | 163 | const struct nft_set *set, void *_be) |
126 | { | 164 | { |
127 | struct nft_bitmap *priv = nft_set_priv(set); | 165 | struct nft_bitmap *priv = nft_set_priv(set); |
128 | u8 genmask = nft_genmask_next(net); | 166 | u8 genmask = nft_genmask_next(net); |
167 | struct nft_bitmap_elem *be = _be; | ||
129 | u32 idx, off; | 168 | u32 idx, off; |
130 | 169 | ||
131 | nft_bitmap_location(nft_set_ext_key(ext)->data[0], &idx, &off); | 170 | nft_bitmap_location(set, nft_set_ext_key(&be->ext), &idx, &off); |
132 | /* Enter 10 state, similar to deactivation. */ | 171 | /* Enter 10 state, similar to deactivation. */ |
133 | priv->bitmap[idx] &= ~(genmask << off); | 172 | priv->bitmap[idx] &= ~(genmask << off); |
173 | nft_set_elem_change_active(net, set, &be->ext); | ||
134 | 174 | ||
135 | return true; | 175 | return true; |
136 | } | 176 | } |
137 | 177 | ||
138 | static struct nft_set_ext *nft_bitmap_ext_alloc(const struct nft_set *set, | ||
139 | const struct nft_set_elem *elem) | ||
140 | { | ||
141 | struct nft_set_ext_tmpl tmpl; | ||
142 | struct nft_set_ext *ext; | ||
143 | |||
144 | nft_set_ext_prepare(&tmpl); | ||
145 | nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, set->klen); | ||
146 | |||
147 | ext = kzalloc(tmpl.len, GFP_KERNEL); | ||
148 | if (!ext) | ||
149 | return NULL; | ||
150 | |||
151 | nft_set_ext_init(ext, &tmpl); | ||
152 | memcpy(nft_set_ext_key(ext), elem->key.val.data, set->klen); | ||
153 | |||
154 | return ext; | ||
155 | } | ||
156 | |||
157 | static void *nft_bitmap_deactivate(const struct net *net, | 178 | static void *nft_bitmap_deactivate(const struct net *net, |
158 | const struct nft_set *set, | 179 | const struct nft_set *set, |
159 | const struct nft_set_elem *elem) | 180 | const struct nft_set_elem *elem) |
160 | { | 181 | { |
161 | struct nft_bitmap *priv = nft_set_priv(set); | 182 | struct nft_bitmap *priv = nft_set_priv(set); |
183 | struct nft_bitmap_elem *this = elem->priv, *be; | ||
162 | u8 genmask = nft_genmask_next(net); | 184 | u8 genmask = nft_genmask_next(net); |
163 | struct nft_set_ext *ext; | 185 | u32 idx, off; |
164 | u32 idx, off, key = 0; | ||
165 | |||
166 | memcpy(&key, elem->key.val.data, set->klen); | ||
167 | nft_bitmap_location(key, &idx, &off); | ||
168 | 186 | ||
169 | if (!nft_bitmap_active(priv->bitmap, idx, off, genmask)) | 187 | nft_bitmap_location(set, elem->key.val.data, &idx, &off); |
170 | return NULL; | ||
171 | 188 | ||
172 | /* We have no real set extension since this is a bitmap, allocate this | 189 | be = nft_bitmap_elem_find(set, this, genmask); |
173 | * dummy object that is released from the commit/abort path. | 190 | if (!be) |
174 | */ | ||
175 | ext = nft_bitmap_ext_alloc(set, elem); | ||
176 | if (!ext) | ||
177 | return NULL; | 191 | return NULL; |
178 | 192 | ||
179 | /* Enter 10 state. */ | 193 | /* Enter 10 state. */ |
180 | priv->bitmap[idx] &= ~(genmask << off); | 194 | priv->bitmap[idx] &= ~(genmask << off); |
195 | nft_set_elem_change_active(net, set, &be->ext); | ||
181 | 196 | ||
182 | return ext; | 197 | return be; |
183 | } | 198 | } |
184 | 199 | ||
185 | static void nft_bitmap_walk(const struct nft_ctx *ctx, | 200 | static void nft_bitmap_walk(const struct nft_ctx *ctx, |
@@ -187,47 +202,23 @@ static void nft_bitmap_walk(const struct nft_ctx *ctx, | |||
187 | struct nft_set_iter *iter) | 202 | struct nft_set_iter *iter) |
188 | { | 203 | { |
189 | const struct nft_bitmap *priv = nft_set_priv(set); | 204 | const struct nft_bitmap *priv = nft_set_priv(set); |
190 | struct nft_set_ext_tmpl tmpl; | 205 | struct nft_bitmap_elem *be; |
191 | struct nft_set_elem elem; | 206 | struct nft_set_elem elem; |
192 | struct nft_set_ext *ext; | 207 | |
193 | int idx, off; | 208 | list_for_each_entry_rcu(be, &priv->list, head) { |
194 | u16 key; | 209 | if (iter->count < iter->skip) |
195 | 210 | goto cont; | |
196 | nft_set_ext_prepare(&tmpl); | 211 | if (!nft_set_elem_active(&be->ext, iter->genmask)) |
197 | nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, set->klen); | 212 | goto cont; |
198 | 213 | ||
199 | for (idx = 0; idx < priv->bitmap_size; idx++) { | 214 | elem.priv = be; |
200 | for (off = 0; off < BITS_PER_BYTE; off += 2) { | 215 | |
201 | if (iter->count < iter->skip) | 216 | iter->err = iter->fn(ctx, set, iter, &elem); |
202 | goto cont; | 217 | |
203 | 218 | if (iter->err < 0) | |
204 | if (!nft_bitmap_active(priv->bitmap, idx, off, | 219 | return; |
205 | iter->genmask)) | ||
206 | goto cont; | ||
207 | |||
208 | ext = kzalloc(tmpl.len, GFP_KERNEL); | ||
209 | if (!ext) { | ||
210 | iter->err = -ENOMEM; | ||
211 | return; | ||
212 | } | ||
213 | nft_set_ext_init(ext, &tmpl); | ||
214 | key = ((idx * BITS_PER_BYTE) + off) >> 1; | ||
215 | memcpy(nft_set_ext_key(ext), &key, set->klen); | ||
216 | |||
217 | elem.priv = ext; | ||
218 | iter->err = iter->fn(ctx, set, iter, &elem); | ||
219 | |||
220 | /* On set flush, this dummy extension object is released | ||
221 | * from the commit/abort path. | ||
222 | */ | ||
223 | if (!iter->flush) | ||
224 | kfree(ext); | ||
225 | |||
226 | if (iter->err < 0) | ||
227 | return; | ||
228 | cont: | 220 | cont: |
229 | iter->count++; | 221 | iter->count++; |
230 | } | ||
231 | } | 222 | } |
232 | } | 223 | } |
233 | 224 | ||
@@ -258,6 +249,7 @@ static int nft_bitmap_init(const struct nft_set *set, | |||
258 | { | 249 | { |
259 | struct nft_bitmap *priv = nft_set_priv(set); | 250 | struct nft_bitmap *priv = nft_set_priv(set); |
260 | 251 | ||
252 | INIT_LIST_HEAD(&priv->list); | ||
261 | priv->bitmap_size = nft_bitmap_size(set->klen); | 253 | priv->bitmap_size = nft_bitmap_size(set->klen); |
262 | 254 | ||
263 | return 0; | 255 | return 0; |
@@ -283,6 +275,7 @@ static bool nft_bitmap_estimate(const struct nft_set_desc *desc, u32 features, | |||
283 | 275 | ||
284 | static struct nft_set_ops nft_bitmap_ops __read_mostly = { | 276 | static struct nft_set_ops nft_bitmap_ops __read_mostly = { |
285 | .privsize = nft_bitmap_privsize, | 277 | .privsize = nft_bitmap_privsize, |
278 | .elemsize = offsetof(struct nft_bitmap_elem, ext), | ||
286 | .estimate = nft_bitmap_estimate, | 279 | .estimate = nft_bitmap_estimate, |
287 | .init = nft_bitmap_init, | 280 | .init = nft_bitmap_init, |
288 | .destroy = nft_bitmap_destroy, | 281 | .destroy = nft_bitmap_destroy, |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 7b73c7c161a9..596eaff66649 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -96,6 +96,44 @@ EXPORT_SYMBOL_GPL(nl_table); | |||
96 | 96 | ||
97 | static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait); | 97 | static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait); |
98 | 98 | ||
99 | static struct lock_class_key nlk_cb_mutex_keys[MAX_LINKS]; | ||
100 | |||
101 | static const char *const nlk_cb_mutex_key_strings[MAX_LINKS + 1] = { | ||
102 | "nlk_cb_mutex-ROUTE", | ||
103 | "nlk_cb_mutex-1", | ||
104 | "nlk_cb_mutex-USERSOCK", | ||
105 | "nlk_cb_mutex-FIREWALL", | ||
106 | "nlk_cb_mutex-SOCK_DIAG", | ||
107 | "nlk_cb_mutex-NFLOG", | ||
108 | "nlk_cb_mutex-XFRM", | ||
109 | "nlk_cb_mutex-SELINUX", | ||
110 | "nlk_cb_mutex-ISCSI", | ||
111 | "nlk_cb_mutex-AUDIT", | ||
112 | "nlk_cb_mutex-FIB_LOOKUP", | ||
113 | "nlk_cb_mutex-CONNECTOR", | ||
114 | "nlk_cb_mutex-NETFILTER", | ||
115 | "nlk_cb_mutex-IP6_FW", | ||
116 | "nlk_cb_mutex-DNRTMSG", | ||
117 | "nlk_cb_mutex-KOBJECT_UEVENT", | ||
118 | "nlk_cb_mutex-GENERIC", | ||
119 | "nlk_cb_mutex-17", | ||
120 | "nlk_cb_mutex-SCSITRANSPORT", | ||
121 | "nlk_cb_mutex-ECRYPTFS", | ||
122 | "nlk_cb_mutex-RDMA", | ||
123 | "nlk_cb_mutex-CRYPTO", | ||
124 | "nlk_cb_mutex-SMC", | ||
125 | "nlk_cb_mutex-23", | ||
126 | "nlk_cb_mutex-24", | ||
127 | "nlk_cb_mutex-25", | ||
128 | "nlk_cb_mutex-26", | ||
129 | "nlk_cb_mutex-27", | ||
130 | "nlk_cb_mutex-28", | ||
131 | "nlk_cb_mutex-29", | ||
132 | "nlk_cb_mutex-30", | ||
133 | "nlk_cb_mutex-31", | ||
134 | "nlk_cb_mutex-MAX_LINKS" | ||
135 | }; | ||
136 | |||
99 | static int netlink_dump(struct sock *sk); | 137 | static int netlink_dump(struct sock *sk); |
100 | static void netlink_skb_destructor(struct sk_buff *skb); | 138 | static void netlink_skb_destructor(struct sk_buff *skb); |
101 | 139 | ||
@@ -585,6 +623,9 @@ static int __netlink_create(struct net *net, struct socket *sock, | |||
585 | } else { | 623 | } else { |
586 | nlk->cb_mutex = &nlk->cb_def_mutex; | 624 | nlk->cb_mutex = &nlk->cb_def_mutex; |
587 | mutex_init(nlk->cb_mutex); | 625 | mutex_init(nlk->cb_mutex); |
626 | lockdep_set_class_and_name(nlk->cb_mutex, | ||
627 | nlk_cb_mutex_keys + protocol, | ||
628 | nlk_cb_mutex_key_strings[protocol]); | ||
588 | } | 629 | } |
589 | init_waitqueue_head(&nlk->wait); | 630 | init_waitqueue_head(&nlk->wait); |
590 | 631 | ||
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index fb6e10fdb217..92e0981f7404 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -783,8 +783,10 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) | |||
783 | 783 | ||
784 | if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).portid, | 784 | if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).portid, |
785 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 785 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
786 | skb, CTRL_CMD_NEWFAMILY) < 0) | 786 | skb, CTRL_CMD_NEWFAMILY) < 0) { |
787 | n--; | ||
787 | break; | 788 | break; |
789 | } | ||
788 | } | 790 | } |
789 | 791 | ||
790 | cb->args[0] = n; | 792 | cb->args[0] = n; |
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 6f5fa50f716d..1105a838bab8 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
@@ -604,7 +604,7 @@ static int ip_tun_from_nlattr(const struct nlattr *attr, | |||
604 | ipv4 = true; | 604 | ipv4 = true; |
605 | break; | 605 | break; |
606 | case OVS_TUNNEL_KEY_ATTR_IPV6_SRC: | 606 | case OVS_TUNNEL_KEY_ATTR_IPV6_SRC: |
607 | SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.dst, | 607 | SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.src, |
608 | nla_get_in6_addr(a), is_mask); | 608 | nla_get_in6_addr(a), is_mask); |
609 | ipv6 = true; | 609 | ipv6 = true; |
610 | break; | 610 | break; |
@@ -665,6 +665,8 @@ static int ip_tun_from_nlattr(const struct nlattr *attr, | |||
665 | tun_flags |= TUNNEL_VXLAN_OPT; | 665 | tun_flags |= TUNNEL_VXLAN_OPT; |
666 | opts_type = type; | 666 | opts_type = type; |
667 | break; | 667 | break; |
668 | case OVS_TUNNEL_KEY_ATTR_PAD: | ||
669 | break; | ||
668 | default: | 670 | default: |
669 | OVS_NLERR(log, "Unknown IP tunnel attribute %d", | 671 | OVS_NLERR(log, "Unknown IP tunnel attribute %d", |
670 | type); | 672 | type); |
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c index 3f9d8d7ec632..b099b64366f3 100644 --- a/net/rxrpc/conn_event.c +++ b/net/rxrpc/conn_event.c | |||
@@ -275,6 +275,10 @@ static int rxrpc_process_event(struct rxrpc_connection *conn, | |||
275 | rxrpc_conn_retransmit_call(conn, skb); | 275 | rxrpc_conn_retransmit_call(conn, skb); |
276 | return 0; | 276 | return 0; |
277 | 277 | ||
278 | case RXRPC_PACKET_TYPE_BUSY: | ||
279 | /* Just ignore BUSY packets for now. */ | ||
280 | return 0; | ||
281 | |||
278 | case RXRPC_PACKET_TYPE_ABORT: | 282 | case RXRPC_PACKET_TYPE_ABORT: |
279 | if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), | 283 | if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), |
280 | &wtmp, sizeof(wtmp)) < 0) | 284 | &wtmp, sizeof(wtmp)) < 0) |
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 802ac7c2e5e8..5334e309f17f 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c | |||
@@ -201,9 +201,13 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch, | |||
201 | pr_debug("%s(skb %p,sch %p,[qdisc %p])\n", __func__, skb, sch, p); | 201 | pr_debug("%s(skb %p,sch %p,[qdisc %p])\n", __func__, skb, sch, p); |
202 | 202 | ||
203 | if (p->set_tc_index) { | 203 | if (p->set_tc_index) { |
204 | int wlen = skb_network_offset(skb); | ||
205 | |||
204 | switch (tc_skb_protocol(skb)) { | 206 | switch (tc_skb_protocol(skb)) { |
205 | case htons(ETH_P_IP): | 207 | case htons(ETH_P_IP): |
206 | if (skb_cow_head(skb, sizeof(struct iphdr))) | 208 | wlen += sizeof(struct iphdr); |
209 | if (!pskb_may_pull(skb, wlen) || | ||
210 | skb_try_make_writable(skb, wlen)) | ||
207 | goto drop; | 211 | goto drop; |
208 | 212 | ||
209 | skb->tc_index = ipv4_get_dsfield(ip_hdr(skb)) | 213 | skb->tc_index = ipv4_get_dsfield(ip_hdr(skb)) |
@@ -211,7 +215,9 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch, | |||
211 | break; | 215 | break; |
212 | 216 | ||
213 | case htons(ETH_P_IPV6): | 217 | case htons(ETH_P_IPV6): |
214 | if (skb_cow_head(skb, sizeof(struct ipv6hdr))) | 218 | wlen += sizeof(struct ipv6hdr); |
219 | if (!pskb_may_pull(skb, wlen) || | ||
220 | skb_try_make_writable(skb, wlen)) | ||
215 | goto drop; | 221 | goto drop; |
216 | 222 | ||
217 | skb->tc_index = ipv6_get_dsfield(ipv6_hdr(skb)) | 223 | skb->tc_index = ipv6_get_dsfield(ipv6_hdr(skb)) |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 2a6835b4562b..0439a1a68367 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -71,9 +71,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
71 | { | 71 | { |
72 | struct net *net = sock_net(sk); | 72 | struct net *net = sock_net(sk); |
73 | struct sctp_sock *sp; | 73 | struct sctp_sock *sp; |
74 | int i; | ||
75 | sctp_paramhdr_t *p; | 74 | sctp_paramhdr_t *p; |
76 | int err; | 75 | int i; |
77 | 76 | ||
78 | /* Retrieve the SCTP per socket area. */ | 77 | /* Retrieve the SCTP per socket area. */ |
79 | sp = sctp_sk((struct sock *)sk); | 78 | sp = sctp_sk((struct sock *)sk); |
@@ -264,8 +263,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
264 | 263 | ||
265 | /* AUTH related initializations */ | 264 | /* AUTH related initializations */ |
266 | INIT_LIST_HEAD(&asoc->endpoint_shared_keys); | 265 | INIT_LIST_HEAD(&asoc->endpoint_shared_keys); |
267 | err = sctp_auth_asoc_copy_shkeys(ep, asoc, gfp); | 266 | if (sctp_auth_asoc_copy_shkeys(ep, asoc, gfp)) |
268 | if (err) | ||
269 | goto fail_init; | 267 | goto fail_init; |
270 | 268 | ||
271 | asoc->active_key_id = ep->active_key_id; | 269 | asoc->active_key_id = ep->active_key_id; |
diff --git a/net/sctp/output.c b/net/sctp/output.c index 71ce6b945dcb..1224421036b3 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -546,7 +546,6 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp) | |||
546 | struct sctp_association *asoc = tp->asoc; | 546 | struct sctp_association *asoc = tp->asoc; |
547 | struct sctp_chunk *chunk, *tmp; | 547 | struct sctp_chunk *chunk, *tmp; |
548 | int pkt_count, gso = 0; | 548 | int pkt_count, gso = 0; |
549 | int confirm; | ||
550 | struct dst_entry *dst; | 549 | struct dst_entry *dst; |
551 | struct sk_buff *head; | 550 | struct sk_buff *head; |
552 | struct sctphdr *sh; | 551 | struct sctphdr *sh; |
@@ -625,13 +624,13 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp) | |||
625 | asoc->peer.last_sent_to = tp; | 624 | asoc->peer.last_sent_to = tp; |
626 | } | 625 | } |
627 | head->ignore_df = packet->ipfragok; | 626 | head->ignore_df = packet->ipfragok; |
628 | confirm = tp->dst_pending_confirm; | 627 | if (tp->dst_pending_confirm) |
629 | if (confirm) | ||
630 | skb_set_dst_pending_confirm(head, 1); | 628 | skb_set_dst_pending_confirm(head, 1); |
631 | /* neighbour should be confirmed on successful transmission or | 629 | /* neighbour should be confirmed on successful transmission or |
632 | * positive error | 630 | * positive error |
633 | */ | 631 | */ |
634 | if (tp->af_specific->sctp_xmit(head, tp) >= 0 && confirm) | 632 | if (tp->af_specific->sctp_xmit(head, tp) >= 0 && |
633 | tp->dst_pending_confirm) | ||
635 | tp->dst_pending_confirm = 0; | 634 | tp->dst_pending_confirm = 0; |
636 | 635 | ||
637 | out: | 636 | out: |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index db352e5d61f8..025ccff67072 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -382,17 +382,18 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc, | |||
382 | } | 382 | } |
383 | 383 | ||
384 | static int sctp_prsctp_prune_unsent(struct sctp_association *asoc, | 384 | static int sctp_prsctp_prune_unsent(struct sctp_association *asoc, |
385 | struct sctp_sndrcvinfo *sinfo, | 385 | struct sctp_sndrcvinfo *sinfo, int msg_len) |
386 | struct list_head *queue, int msg_len) | ||
387 | { | 386 | { |
387 | struct sctp_outq *q = &asoc->outqueue; | ||
388 | struct sctp_chunk *chk, *temp; | 388 | struct sctp_chunk *chk, *temp; |
389 | 389 | ||
390 | list_for_each_entry_safe(chk, temp, queue, list) { | 390 | list_for_each_entry_safe(chk, temp, &q->out_chunk_list, list) { |
391 | if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || | 391 | if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || |
392 | chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive) | 392 | chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive) |
393 | continue; | 393 | continue; |
394 | 394 | ||
395 | list_del_init(&chk->list); | 395 | list_del_init(&chk->list); |
396 | q->out_qlen -= chk->skb->len; | ||
396 | asoc->sent_cnt_removable--; | 397 | asoc->sent_cnt_removable--; |
397 | asoc->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++; | 398 | asoc->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++; |
398 | 399 | ||
@@ -431,9 +432,7 @@ void sctp_prsctp_prune(struct sctp_association *asoc, | |||
431 | return; | 432 | return; |
432 | } | 433 | } |
433 | 434 | ||
434 | sctp_prsctp_prune_unsent(asoc, sinfo, | 435 | sctp_prsctp_prune_unsent(asoc, sinfo, msg_len); |
435 | &asoc->outqueue.out_chunk_list, | ||
436 | msg_len); | ||
437 | } | 436 | } |
438 | 437 | ||
439 | /* Mark all the eligible packets on a transport for retransmission. */ | 438 | /* Mark all the eligible packets on a transport for retransmission. */ |
diff --git a/net/socket.c b/net/socket.c index e034fe4164be..985ef06792d6 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -652,6 +652,16 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg, | |||
652 | } | 652 | } |
653 | EXPORT_SYMBOL(kernel_sendmsg); | 653 | EXPORT_SYMBOL(kernel_sendmsg); |
654 | 654 | ||
655 | static bool skb_is_err_queue(const struct sk_buff *skb) | ||
656 | { | ||
657 | /* pkt_type of skbs enqueued on the error queue are set to | ||
658 | * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do | ||
659 | * in recvmsg, since skbs received on a local socket will never | ||
660 | * have a pkt_type of PACKET_OUTGOING. | ||
661 | */ | ||
662 | return skb->pkt_type == PACKET_OUTGOING; | ||
663 | } | ||
664 | |||
655 | /* | 665 | /* |
656 | * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) | 666 | * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) |
657 | */ | 667 | */ |
@@ -695,7 +705,8 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | |||
695 | put_cmsg(msg, SOL_SOCKET, | 705 | put_cmsg(msg, SOL_SOCKET, |
696 | SCM_TIMESTAMPING, sizeof(tss), &tss); | 706 | SCM_TIMESTAMPING, sizeof(tss), &tss); |
697 | 707 | ||
698 | if (skb->len && (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS)) | 708 | if (skb_is_err_queue(skb) && skb->len && |
709 | SKB_EXT_ERR(skb)->opt_stats) | ||
699 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS, | 710 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS, |
700 | skb->len, skb->data); | 711 | skb->len, skb->data); |
701 | } | 712 | } |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 9d94e65d0894..271cd66e4b3b 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
@@ -141,6 +141,11 @@ void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower, | |||
141 | static void tipc_subscrp_timeout(unsigned long data) | 141 | static void tipc_subscrp_timeout(unsigned long data) |
142 | { | 142 | { |
143 | struct tipc_subscription *sub = (struct tipc_subscription *)data; | 143 | struct tipc_subscription *sub = (struct tipc_subscription *)data; |
144 | struct tipc_subscriber *subscriber = sub->subscriber; | ||
145 | |||
146 | spin_lock_bh(&subscriber->lock); | ||
147 | tipc_nametbl_unsubscribe(sub); | ||
148 | spin_unlock_bh(&subscriber->lock); | ||
144 | 149 | ||
145 | /* Notify subscriber of timeout */ | 150 | /* Notify subscriber of timeout */ |
146 | tipc_subscrp_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper, | 151 | tipc_subscrp_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper, |
@@ -173,7 +178,6 @@ static void tipc_subscrp_kref_release(struct kref *kref) | |||
173 | struct tipc_subscriber *subscriber = sub->subscriber; | 178 | struct tipc_subscriber *subscriber = sub->subscriber; |
174 | 179 | ||
175 | spin_lock_bh(&subscriber->lock); | 180 | spin_lock_bh(&subscriber->lock); |
176 | tipc_nametbl_unsubscribe(sub); | ||
177 | list_del(&sub->subscrp_list); | 181 | list_del(&sub->subscrp_list); |
178 | atomic_dec(&tn->subscription_count); | 182 | atomic_dec(&tn->subscription_count); |
179 | spin_unlock_bh(&subscriber->lock); | 183 | spin_unlock_bh(&subscriber->lock); |
@@ -205,6 +209,7 @@ static void tipc_subscrb_subscrp_delete(struct tipc_subscriber *subscriber, | |||
205 | if (s && memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) | 209 | if (s && memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) |
206 | continue; | 210 | continue; |
207 | 211 | ||
212 | tipc_nametbl_unsubscribe(sub); | ||
208 | tipc_subscrp_get(sub); | 213 | tipc_subscrp_get(sub); |
209 | spin_unlock_bh(&subscriber->lock); | 214 | spin_unlock_bh(&subscriber->lock); |
210 | tipc_subscrp_delete(sub); | 215 | tipc_subscrp_delete(sub); |
diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 6a0d48525fcf..c36757e72844 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c | |||
@@ -146,6 +146,7 @@ void unix_notinflight(struct user_struct *user, struct file *fp) | |||
146 | if (s) { | 146 | if (s) { |
147 | struct unix_sock *u = unix_sk(s); | 147 | struct unix_sock *u = unix_sk(s); |
148 | 148 | ||
149 | BUG_ON(!atomic_long_read(&u->inflight)); | ||
149 | BUG_ON(list_empty(&u->link)); | 150 | BUG_ON(list_empty(&u->link)); |
150 | 151 | ||
151 | if (atomic_long_dec_and_test(&u->inflight)) | 152 | if (atomic_long_dec_and_test(&u->inflight)) |
@@ -341,6 +342,14 @@ void unix_gc(void) | |||
341 | } | 342 | } |
342 | list_del(&cursor); | 343 | list_del(&cursor); |
343 | 344 | ||
345 | /* Now gc_candidates contains only garbage. Restore original | ||
346 | * inflight counters for these as well, and remove the skbuffs | ||
347 | * which are creating the cycle(s). | ||
348 | */ | ||
349 | skb_queue_head_init(&hitlist); | ||
350 | list_for_each_entry(u, &gc_candidates, link) | ||
351 | scan_children(&u->sk, inc_inflight, &hitlist); | ||
352 | |||
344 | /* not_cycle_list contains those sockets which do not make up a | 353 | /* not_cycle_list contains those sockets which do not make up a |
345 | * cycle. Restore these to the inflight list. | 354 | * cycle. Restore these to the inflight list. |
346 | */ | 355 | */ |
@@ -350,14 +359,6 @@ void unix_gc(void) | |||
350 | list_move_tail(&u->link, &gc_inflight_list); | 359 | list_move_tail(&u->link, &gc_inflight_list); |
351 | } | 360 | } |
352 | 361 | ||
353 | /* Now gc_candidates contains only garbage. Restore original | ||
354 | * inflight counters for these as well, and remove the skbuffs | ||
355 | * which are creating the cycle(s). | ||
356 | */ | ||
357 | skb_queue_head_init(&hitlist); | ||
358 | list_for_each_entry(u, &gc_candidates, link) | ||
359 | scan_children(&u->sk, inc_inflight, &hitlist); | ||
360 | |||
361 | spin_unlock(&unix_gc_lock); | 362 | spin_unlock(&unix_gc_lock); |
362 | 363 | ||
363 | /* Here we are. Hitlist is filled. Die. */ | 364 | /* Here we are. Hitlist is filled. Die. */ |
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 9f770f33c100..6f7f6757ceef 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c | |||
@@ -1102,10 +1102,19 @@ static const struct proto_ops vsock_dgram_ops = { | |||
1102 | .sendpage = sock_no_sendpage, | 1102 | .sendpage = sock_no_sendpage, |
1103 | }; | 1103 | }; |
1104 | 1104 | ||
1105 | static int vsock_transport_cancel_pkt(struct vsock_sock *vsk) | ||
1106 | { | ||
1107 | if (!transport->cancel_pkt) | ||
1108 | return -EOPNOTSUPP; | ||
1109 | |||
1110 | return transport->cancel_pkt(vsk); | ||
1111 | } | ||
1112 | |||
1105 | static void vsock_connect_timeout(struct work_struct *work) | 1113 | static void vsock_connect_timeout(struct work_struct *work) |
1106 | { | 1114 | { |
1107 | struct sock *sk; | 1115 | struct sock *sk; |
1108 | struct vsock_sock *vsk; | 1116 | struct vsock_sock *vsk; |
1117 | int cancel = 0; | ||
1109 | 1118 | ||
1110 | vsk = container_of(work, struct vsock_sock, dwork.work); | 1119 | vsk = container_of(work, struct vsock_sock, dwork.work); |
1111 | sk = sk_vsock(vsk); | 1120 | sk = sk_vsock(vsk); |
@@ -1116,8 +1125,11 @@ static void vsock_connect_timeout(struct work_struct *work) | |||
1116 | sk->sk_state = SS_UNCONNECTED; | 1125 | sk->sk_state = SS_UNCONNECTED; |
1117 | sk->sk_err = ETIMEDOUT; | 1126 | sk->sk_err = ETIMEDOUT; |
1118 | sk->sk_error_report(sk); | 1127 | sk->sk_error_report(sk); |
1128 | cancel = 1; | ||
1119 | } | 1129 | } |
1120 | release_sock(sk); | 1130 | release_sock(sk); |
1131 | if (cancel) | ||
1132 | vsock_transport_cancel_pkt(vsk); | ||
1121 | 1133 | ||
1122 | sock_put(sk); | 1134 | sock_put(sk); |
1123 | } | 1135 | } |
@@ -1224,11 +1236,13 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr, | |||
1224 | err = sock_intr_errno(timeout); | 1236 | err = sock_intr_errno(timeout); |
1225 | sk->sk_state = SS_UNCONNECTED; | 1237 | sk->sk_state = SS_UNCONNECTED; |
1226 | sock->state = SS_UNCONNECTED; | 1238 | sock->state = SS_UNCONNECTED; |
1239 | vsock_transport_cancel_pkt(vsk); | ||
1227 | goto out_wait; | 1240 | goto out_wait; |
1228 | } else if (timeout == 0) { | 1241 | } else if (timeout == 0) { |
1229 | err = -ETIMEDOUT; | 1242 | err = -ETIMEDOUT; |
1230 | sk->sk_state = SS_UNCONNECTED; | 1243 | sk->sk_state = SS_UNCONNECTED; |
1231 | sock->state = SS_UNCONNECTED; | 1244 | sock->state = SS_UNCONNECTED; |
1245 | vsock_transport_cancel_pkt(vsk); | ||
1232 | goto out_wait; | 1246 | goto out_wait; |
1233 | } | 1247 | } |
1234 | 1248 | ||
diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c index 9d24c0e958b1..68675a151f22 100644 --- a/net/vmw_vsock/virtio_transport.c +++ b/net/vmw_vsock/virtio_transport.c | |||
@@ -213,6 +213,47 @@ virtio_transport_send_pkt(struct virtio_vsock_pkt *pkt) | |||
213 | return len; | 213 | return len; |
214 | } | 214 | } |
215 | 215 | ||
216 | static int | ||
217 | virtio_transport_cancel_pkt(struct vsock_sock *vsk) | ||
218 | { | ||
219 | struct virtio_vsock *vsock; | ||
220 | struct virtio_vsock_pkt *pkt, *n; | ||
221 | int cnt = 0; | ||
222 | LIST_HEAD(freeme); | ||
223 | |||
224 | vsock = virtio_vsock_get(); | ||
225 | if (!vsock) { | ||
226 | return -ENODEV; | ||
227 | } | ||
228 | |||
229 | spin_lock_bh(&vsock->send_pkt_list_lock); | ||
230 | list_for_each_entry_safe(pkt, n, &vsock->send_pkt_list, list) { | ||
231 | if (pkt->vsk != vsk) | ||
232 | continue; | ||
233 | list_move(&pkt->list, &freeme); | ||
234 | } | ||
235 | spin_unlock_bh(&vsock->send_pkt_list_lock); | ||
236 | |||
237 | list_for_each_entry_safe(pkt, n, &freeme, list) { | ||
238 | if (pkt->reply) | ||
239 | cnt++; | ||
240 | list_del(&pkt->list); | ||
241 | virtio_transport_free_pkt(pkt); | ||
242 | } | ||
243 | |||
244 | if (cnt) { | ||
245 | struct virtqueue *rx_vq = vsock->vqs[VSOCK_VQ_RX]; | ||
246 | int new_cnt; | ||
247 | |||
248 | new_cnt = atomic_sub_return(cnt, &vsock->queued_replies); | ||
249 | if (new_cnt + cnt >= virtqueue_get_vring_size(rx_vq) && | ||
250 | new_cnt < virtqueue_get_vring_size(rx_vq)) | ||
251 | queue_work(virtio_vsock_workqueue, &vsock->rx_work); | ||
252 | } | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
216 | static void virtio_vsock_rx_fill(struct virtio_vsock *vsock) | 257 | static void virtio_vsock_rx_fill(struct virtio_vsock *vsock) |
217 | { | 258 | { |
218 | int buf_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE; | 259 | int buf_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE; |
@@ -462,6 +503,7 @@ static struct virtio_transport virtio_transport = { | |||
462 | .release = virtio_transport_release, | 503 | .release = virtio_transport_release, |
463 | .connect = virtio_transport_connect, | 504 | .connect = virtio_transport_connect, |
464 | .shutdown = virtio_transport_shutdown, | 505 | .shutdown = virtio_transport_shutdown, |
506 | .cancel_pkt = virtio_transport_cancel_pkt, | ||
465 | 507 | ||
466 | .dgram_bind = virtio_transport_dgram_bind, | 508 | .dgram_bind = virtio_transport_dgram_bind, |
467 | .dgram_dequeue = virtio_transport_dgram_dequeue, | 509 | .dgram_dequeue = virtio_transport_dgram_dequeue, |
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 8d592a45b597..af087b44ceea 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c | |||
@@ -58,6 +58,7 @@ virtio_transport_alloc_pkt(struct virtio_vsock_pkt_info *info, | |||
58 | pkt->len = len; | 58 | pkt->len = len; |
59 | pkt->hdr.len = cpu_to_le32(len); | 59 | pkt->hdr.len = cpu_to_le32(len); |
60 | pkt->reply = info->reply; | 60 | pkt->reply = info->reply; |
61 | pkt->vsk = info->vsk; | ||
61 | 62 | ||
62 | if (info->msg && len > 0) { | 63 | if (info->msg && len > 0) { |
63 | pkt->buf = kmalloc(len, GFP_KERNEL); | 64 | pkt->buf = kmalloc(len, GFP_KERNEL); |
@@ -180,6 +181,7 @@ static int virtio_transport_send_credit_update(struct vsock_sock *vsk, | |||
180 | struct virtio_vsock_pkt_info info = { | 181 | struct virtio_vsock_pkt_info info = { |
181 | .op = VIRTIO_VSOCK_OP_CREDIT_UPDATE, | 182 | .op = VIRTIO_VSOCK_OP_CREDIT_UPDATE, |
182 | .type = type, | 183 | .type = type, |
184 | .vsk = vsk, | ||
183 | }; | 185 | }; |
184 | 186 | ||
185 | return virtio_transport_send_pkt_info(vsk, &info); | 187 | return virtio_transport_send_pkt_info(vsk, &info); |
@@ -519,6 +521,7 @@ int virtio_transport_connect(struct vsock_sock *vsk) | |||
519 | struct virtio_vsock_pkt_info info = { | 521 | struct virtio_vsock_pkt_info info = { |
520 | .op = VIRTIO_VSOCK_OP_REQUEST, | 522 | .op = VIRTIO_VSOCK_OP_REQUEST, |
521 | .type = VIRTIO_VSOCK_TYPE_STREAM, | 523 | .type = VIRTIO_VSOCK_TYPE_STREAM, |
524 | .vsk = vsk, | ||
522 | }; | 525 | }; |
523 | 526 | ||
524 | return virtio_transport_send_pkt_info(vsk, &info); | 527 | return virtio_transport_send_pkt_info(vsk, &info); |
@@ -534,6 +537,7 @@ int virtio_transport_shutdown(struct vsock_sock *vsk, int mode) | |||
534 | VIRTIO_VSOCK_SHUTDOWN_RCV : 0) | | 537 | VIRTIO_VSOCK_SHUTDOWN_RCV : 0) | |
535 | (mode & SEND_SHUTDOWN ? | 538 | (mode & SEND_SHUTDOWN ? |
536 | VIRTIO_VSOCK_SHUTDOWN_SEND : 0), | 539 | VIRTIO_VSOCK_SHUTDOWN_SEND : 0), |
540 | .vsk = vsk, | ||
537 | }; | 541 | }; |
538 | 542 | ||
539 | return virtio_transport_send_pkt_info(vsk, &info); | 543 | return virtio_transport_send_pkt_info(vsk, &info); |
@@ -560,6 +564,7 @@ virtio_transport_stream_enqueue(struct vsock_sock *vsk, | |||
560 | .type = VIRTIO_VSOCK_TYPE_STREAM, | 564 | .type = VIRTIO_VSOCK_TYPE_STREAM, |
561 | .msg = msg, | 565 | .msg = msg, |
562 | .pkt_len = len, | 566 | .pkt_len = len, |
567 | .vsk = vsk, | ||
563 | }; | 568 | }; |
564 | 569 | ||
565 | return virtio_transport_send_pkt_info(vsk, &info); | 570 | return virtio_transport_send_pkt_info(vsk, &info); |
@@ -581,6 +586,7 @@ static int virtio_transport_reset(struct vsock_sock *vsk, | |||
581 | .op = VIRTIO_VSOCK_OP_RST, | 586 | .op = VIRTIO_VSOCK_OP_RST, |
582 | .type = VIRTIO_VSOCK_TYPE_STREAM, | 587 | .type = VIRTIO_VSOCK_TYPE_STREAM, |
583 | .reply = !!pkt, | 588 | .reply = !!pkt, |
589 | .vsk = vsk, | ||
584 | }; | 590 | }; |
585 | 591 | ||
586 | /* Send RST only if the original pkt is not a RST pkt */ | 592 | /* Send RST only if the original pkt is not a RST pkt */ |
@@ -826,6 +832,7 @@ virtio_transport_send_response(struct vsock_sock *vsk, | |||
826 | .remote_cid = le64_to_cpu(pkt->hdr.src_cid), | 832 | .remote_cid = le64_to_cpu(pkt->hdr.src_cid), |
827 | .remote_port = le32_to_cpu(pkt->hdr.src_port), | 833 | .remote_port = le32_to_cpu(pkt->hdr.src_port), |
828 | .reply = true, | 834 | .reply = true, |
835 | .vsk = vsk, | ||
829 | }; | 836 | }; |
830 | 837 | ||
831 | return virtio_transport_send_pkt_info(vsk, &info); | 838 | return virtio_transport_send_pkt_info(vsk, &info); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d7f8be4e321a..2312dc2ffdb9 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -545,22 +545,18 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |||
545 | { | 545 | { |
546 | int err; | 546 | int err; |
547 | 547 | ||
548 | rtnl_lock(); | ||
549 | |||
550 | if (!cb->args[0]) { | 548 | if (!cb->args[0]) { |
551 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | 549 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, |
552 | genl_family_attrbuf(&nl80211_fam), | 550 | genl_family_attrbuf(&nl80211_fam), |
553 | nl80211_fam.maxattr, nl80211_policy); | 551 | nl80211_fam.maxattr, nl80211_policy); |
554 | if (err) | 552 | if (err) |
555 | goto out_unlock; | 553 | return err; |
556 | 554 | ||
557 | *wdev = __cfg80211_wdev_from_attrs( | 555 | *wdev = __cfg80211_wdev_from_attrs( |
558 | sock_net(skb->sk), | 556 | sock_net(skb->sk), |
559 | genl_family_attrbuf(&nl80211_fam)); | 557 | genl_family_attrbuf(&nl80211_fam)); |
560 | if (IS_ERR(*wdev)) { | 558 | if (IS_ERR(*wdev)) |
561 | err = PTR_ERR(*wdev); | 559 | return PTR_ERR(*wdev); |
562 | goto out_unlock; | ||
563 | } | ||
564 | *rdev = wiphy_to_rdev((*wdev)->wiphy); | 560 | *rdev = wiphy_to_rdev((*wdev)->wiphy); |
565 | /* 0 is the first index - add 1 to parse only once */ | 561 | /* 0 is the first index - add 1 to parse only once */ |
566 | cb->args[0] = (*rdev)->wiphy_idx + 1; | 562 | cb->args[0] = (*rdev)->wiphy_idx + 1; |
@@ -570,10 +566,8 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |||
570 | struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); | 566 | struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); |
571 | struct wireless_dev *tmp; | 567 | struct wireless_dev *tmp; |
572 | 568 | ||
573 | if (!wiphy) { | 569 | if (!wiphy) |
574 | err = -ENODEV; | 570 | return -ENODEV; |
575 | goto out_unlock; | ||
576 | } | ||
577 | *rdev = wiphy_to_rdev(wiphy); | 571 | *rdev = wiphy_to_rdev(wiphy); |
578 | *wdev = NULL; | 572 | *wdev = NULL; |
579 | 573 | ||
@@ -584,21 +578,11 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |||
584 | } | 578 | } |
585 | } | 579 | } |
586 | 580 | ||
587 | if (!*wdev) { | 581 | if (!*wdev) |
588 | err = -ENODEV; | 582 | return -ENODEV; |
589 | goto out_unlock; | ||
590 | } | ||
591 | } | 583 | } |
592 | 584 | ||
593 | return 0; | 585 | return 0; |
594 | out_unlock: | ||
595 | rtnl_unlock(); | ||
596 | return err; | ||
597 | } | ||
598 | |||
599 | static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev) | ||
600 | { | ||
601 | rtnl_unlock(); | ||
602 | } | 586 | } |
603 | 587 | ||
604 | /* IE validation */ | 588 | /* IE validation */ |
@@ -2608,17 +2592,17 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * | |||
2608 | int filter_wiphy = -1; | 2592 | int filter_wiphy = -1; |
2609 | struct cfg80211_registered_device *rdev; | 2593 | struct cfg80211_registered_device *rdev; |
2610 | struct wireless_dev *wdev; | 2594 | struct wireless_dev *wdev; |
2595 | int ret; | ||
2611 | 2596 | ||
2612 | rtnl_lock(); | 2597 | rtnl_lock(); |
2613 | if (!cb->args[2]) { | 2598 | if (!cb->args[2]) { |
2614 | struct nl80211_dump_wiphy_state state = { | 2599 | struct nl80211_dump_wiphy_state state = { |
2615 | .filter_wiphy = -1, | 2600 | .filter_wiphy = -1, |
2616 | }; | 2601 | }; |
2617 | int ret; | ||
2618 | 2602 | ||
2619 | ret = nl80211_dump_wiphy_parse(skb, cb, &state); | 2603 | ret = nl80211_dump_wiphy_parse(skb, cb, &state); |
2620 | if (ret) | 2604 | if (ret) |
2621 | return ret; | 2605 | goto out_unlock; |
2622 | 2606 | ||
2623 | filter_wiphy = state.filter_wiphy; | 2607 | filter_wiphy = state.filter_wiphy; |
2624 | 2608 | ||
@@ -2663,12 +2647,14 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * | |||
2663 | wp_idx++; | 2647 | wp_idx++; |
2664 | } | 2648 | } |
2665 | out: | 2649 | out: |
2666 | rtnl_unlock(); | ||
2667 | |||
2668 | cb->args[0] = wp_idx; | 2650 | cb->args[0] = wp_idx; |
2669 | cb->args[1] = if_idx; | 2651 | cb->args[1] = if_idx; |
2670 | 2652 | ||
2671 | return skb->len; | 2653 | ret = skb->len; |
2654 | out_unlock: | ||
2655 | rtnl_unlock(); | ||
2656 | |||
2657 | return ret; | ||
2672 | } | 2658 | } |
2673 | 2659 | ||
2674 | static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) | 2660 | static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) |
@@ -4452,9 +4438,10 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
4452 | int sta_idx = cb->args[2]; | 4438 | int sta_idx = cb->args[2]; |
4453 | int err; | 4439 | int err; |
4454 | 4440 | ||
4441 | rtnl_lock(); | ||
4455 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | 4442 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); |
4456 | if (err) | 4443 | if (err) |
4457 | return err; | 4444 | goto out_err; |
4458 | 4445 | ||
4459 | if (!wdev->netdev) { | 4446 | if (!wdev->netdev) { |
4460 | err = -EINVAL; | 4447 | err = -EINVAL; |
@@ -4489,7 +4476,7 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
4489 | cb->args[2] = sta_idx; | 4476 | cb->args[2] = sta_idx; |
4490 | err = skb->len; | 4477 | err = skb->len; |
4491 | out_err: | 4478 | out_err: |
4492 | nl80211_finish_wdev_dump(rdev); | 4479 | rtnl_unlock(); |
4493 | 4480 | ||
4494 | return err; | 4481 | return err; |
4495 | } | 4482 | } |
@@ -5275,9 +5262,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb, | |||
5275 | int path_idx = cb->args[2]; | 5262 | int path_idx = cb->args[2]; |
5276 | int err; | 5263 | int err; |
5277 | 5264 | ||
5265 | rtnl_lock(); | ||
5278 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | 5266 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); |
5279 | if (err) | 5267 | if (err) |
5280 | return err; | 5268 | goto out_err; |
5281 | 5269 | ||
5282 | if (!rdev->ops->dump_mpath) { | 5270 | if (!rdev->ops->dump_mpath) { |
5283 | err = -EOPNOTSUPP; | 5271 | err = -EOPNOTSUPP; |
@@ -5310,7 +5298,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb, | |||
5310 | cb->args[2] = path_idx; | 5298 | cb->args[2] = path_idx; |
5311 | err = skb->len; | 5299 | err = skb->len; |
5312 | out_err: | 5300 | out_err: |
5313 | nl80211_finish_wdev_dump(rdev); | 5301 | rtnl_unlock(); |
5314 | return err; | 5302 | return err; |
5315 | } | 5303 | } |
5316 | 5304 | ||
@@ -5470,9 +5458,10 @@ static int nl80211_dump_mpp(struct sk_buff *skb, | |||
5470 | int path_idx = cb->args[2]; | 5458 | int path_idx = cb->args[2]; |
5471 | int err; | 5459 | int err; |
5472 | 5460 | ||
5461 | rtnl_lock(); | ||
5473 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | 5462 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); |
5474 | if (err) | 5463 | if (err) |
5475 | return err; | 5464 | goto out_err; |
5476 | 5465 | ||
5477 | if (!rdev->ops->dump_mpp) { | 5466 | if (!rdev->ops->dump_mpp) { |
5478 | err = -EOPNOTSUPP; | 5467 | err = -EOPNOTSUPP; |
@@ -5505,7 +5494,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb, | |||
5505 | cb->args[2] = path_idx; | 5494 | cb->args[2] = path_idx; |
5506 | err = skb->len; | 5495 | err = skb->len; |
5507 | out_err: | 5496 | out_err: |
5508 | nl80211_finish_wdev_dump(rdev); | 5497 | rtnl_unlock(); |
5509 | return err; | 5498 | return err; |
5510 | } | 5499 | } |
5511 | 5500 | ||
@@ -7674,9 +7663,12 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb) | |||
7674 | int start = cb->args[2], idx = 0; | 7663 | int start = cb->args[2], idx = 0; |
7675 | int err; | 7664 | int err; |
7676 | 7665 | ||
7666 | rtnl_lock(); | ||
7677 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | 7667 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); |
7678 | if (err) | 7668 | if (err) { |
7669 | rtnl_unlock(); | ||
7679 | return err; | 7670 | return err; |
7671 | } | ||
7680 | 7672 | ||
7681 | wdev_lock(wdev); | 7673 | wdev_lock(wdev); |
7682 | spin_lock_bh(&rdev->bss_lock); | 7674 | spin_lock_bh(&rdev->bss_lock); |
@@ -7699,7 +7691,7 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb) | |||
7699 | wdev_unlock(wdev); | 7691 | wdev_unlock(wdev); |
7700 | 7692 | ||
7701 | cb->args[2] = idx; | 7693 | cb->args[2] = idx; |
7702 | nl80211_finish_wdev_dump(rdev); | 7694 | rtnl_unlock(); |
7703 | 7695 | ||
7704 | return skb->len; | 7696 | return skb->len; |
7705 | } | 7697 | } |
@@ -7784,9 +7776,10 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) | |||
7784 | int res; | 7776 | int res; |
7785 | bool radio_stats; | 7777 | bool radio_stats; |
7786 | 7778 | ||
7779 | rtnl_lock(); | ||
7787 | res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | 7780 | res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); |
7788 | if (res) | 7781 | if (res) |
7789 | return res; | 7782 | goto out_err; |
7790 | 7783 | ||
7791 | /* prepare_wdev_dump parsed the attributes */ | 7784 | /* prepare_wdev_dump parsed the attributes */ |
7792 | radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS]; | 7785 | radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS]; |
@@ -7827,7 +7820,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) | |||
7827 | cb->args[2] = survey_idx; | 7820 | cb->args[2] = survey_idx; |
7828 | res = skb->len; | 7821 | res = skb->len; |
7829 | out_err: | 7822 | out_err: |
7830 | nl80211_finish_wdev_dump(rdev); | 7823 | rtnl_unlock(); |
7831 | return res; | 7824 | return res; |
7832 | } | 7825 | } |
7833 | 7826 | ||
@@ -11508,17 +11501,13 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, | |||
11508 | void *data = NULL; | 11501 | void *data = NULL; |
11509 | unsigned int data_len = 0; | 11502 | unsigned int data_len = 0; |
11510 | 11503 | ||
11511 | rtnl_lock(); | ||
11512 | |||
11513 | if (cb->args[0]) { | 11504 | if (cb->args[0]) { |
11514 | /* subtract the 1 again here */ | 11505 | /* subtract the 1 again here */ |
11515 | struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); | 11506 | struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); |
11516 | struct wireless_dev *tmp; | 11507 | struct wireless_dev *tmp; |
11517 | 11508 | ||
11518 | if (!wiphy) { | 11509 | if (!wiphy) |
11519 | err = -ENODEV; | 11510 | return -ENODEV; |
11520 | goto out_unlock; | ||
11521 | } | ||
11522 | *rdev = wiphy_to_rdev(wiphy); | 11511 | *rdev = wiphy_to_rdev(wiphy); |
11523 | *wdev = NULL; | 11512 | *wdev = NULL; |
11524 | 11513 | ||
@@ -11538,23 +11527,19 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, | |||
11538 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | 11527 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, |
11539 | attrbuf, nl80211_fam.maxattr, nl80211_policy); | 11528 | attrbuf, nl80211_fam.maxattr, nl80211_policy); |
11540 | if (err) | 11529 | if (err) |
11541 | goto out_unlock; | 11530 | return err; |
11542 | 11531 | ||
11543 | if (!attrbuf[NL80211_ATTR_VENDOR_ID] || | 11532 | if (!attrbuf[NL80211_ATTR_VENDOR_ID] || |
11544 | !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) { | 11533 | !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) |
11545 | err = -EINVAL; | 11534 | return -EINVAL; |
11546 | goto out_unlock; | ||
11547 | } | ||
11548 | 11535 | ||
11549 | *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf); | 11536 | *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf); |
11550 | if (IS_ERR(*wdev)) | 11537 | if (IS_ERR(*wdev)) |
11551 | *wdev = NULL; | 11538 | *wdev = NULL; |
11552 | 11539 | ||
11553 | *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf); | 11540 | *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf); |
11554 | if (IS_ERR(*rdev)) { | 11541 | if (IS_ERR(*rdev)) |
11555 | err = PTR_ERR(*rdev); | 11542 | return PTR_ERR(*rdev); |
11556 | goto out_unlock; | ||
11557 | } | ||
11558 | 11543 | ||
11559 | vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]); | 11544 | vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]); |
11560 | subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]); | 11545 | subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]); |
@@ -11567,19 +11552,15 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, | |||
11567 | if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd) | 11552 | if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd) |
11568 | continue; | 11553 | continue; |
11569 | 11554 | ||
11570 | if (!vcmd->dumpit) { | 11555 | if (!vcmd->dumpit) |
11571 | err = -EOPNOTSUPP; | 11556 | return -EOPNOTSUPP; |
11572 | goto out_unlock; | ||
11573 | } | ||
11574 | 11557 | ||
11575 | vcmd_idx = i; | 11558 | vcmd_idx = i; |
11576 | break; | 11559 | break; |
11577 | } | 11560 | } |
11578 | 11561 | ||
11579 | if (vcmd_idx < 0) { | 11562 | if (vcmd_idx < 0) |
11580 | err = -EOPNOTSUPP; | 11563 | return -EOPNOTSUPP; |
11581 | goto out_unlock; | ||
11582 | } | ||
11583 | 11564 | ||
11584 | if (attrbuf[NL80211_ATTR_VENDOR_DATA]) { | 11565 | if (attrbuf[NL80211_ATTR_VENDOR_DATA]) { |
11585 | data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]); | 11566 | data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]); |
@@ -11596,9 +11577,6 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, | |||
11596 | 11577 | ||
11597 | /* keep rtnl locked in successful case */ | 11578 | /* keep rtnl locked in successful case */ |
11598 | return 0; | 11579 | return 0; |
11599 | out_unlock: | ||
11600 | rtnl_unlock(); | ||
11601 | return err; | ||
11602 | } | 11580 | } |
11603 | 11581 | ||
11604 | static int nl80211_vendor_cmd_dump(struct sk_buff *skb, | 11582 | static int nl80211_vendor_cmd_dump(struct sk_buff *skb, |
@@ -11613,9 +11591,10 @@ static int nl80211_vendor_cmd_dump(struct sk_buff *skb, | |||
11613 | int err; | 11591 | int err; |
11614 | struct nlattr *vendor_data; | 11592 | struct nlattr *vendor_data; |
11615 | 11593 | ||
11594 | rtnl_lock(); | ||
11616 | err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev); | 11595 | err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev); |
11617 | if (err) | 11596 | if (err) |
11618 | return err; | 11597 | goto out; |
11619 | 11598 | ||
11620 | vcmd_idx = cb->args[2]; | 11599 | vcmd_idx = cb->args[2]; |
11621 | data = (void *)cb->args[3]; | 11600 | data = (void *)cb->args[3]; |
@@ -11624,15 +11603,21 @@ static int nl80211_vendor_cmd_dump(struct sk_buff *skb, | |||
11624 | 11603 | ||
11625 | if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV | | 11604 | if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV | |
11626 | WIPHY_VENDOR_CMD_NEED_NETDEV)) { | 11605 | WIPHY_VENDOR_CMD_NEED_NETDEV)) { |
11627 | if (!wdev) | 11606 | if (!wdev) { |
11628 | return -EINVAL; | 11607 | err = -EINVAL; |
11608 | goto out; | ||
11609 | } | ||
11629 | if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV && | 11610 | if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV && |
11630 | !wdev->netdev) | 11611 | !wdev->netdev) { |
11631 | return -EINVAL; | 11612 | err = -EINVAL; |
11613 | goto out; | ||
11614 | } | ||
11632 | 11615 | ||
11633 | if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) { | 11616 | if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) { |
11634 | if (!wdev_running(wdev)) | 11617 | if (!wdev_running(wdev)) { |
11635 | return -ENETDOWN; | 11618 | err = -ENETDOWN; |
11619 | goto out; | ||
11620 | } | ||
11636 | } | 11621 | } |
11637 | } | 11622 | } |
11638 | 11623 | ||
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 67531f47781b..6a1ad58cb66f 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile | |||
@@ -1,22 +1,23 @@ | |||
1 | LIBDIR := ../../../lib | 1 | LIBDIR := ../../../lib |
2 | BPFOBJ := $(LIBDIR)/bpf/bpf.o | 2 | BPFDIR := $(LIBDIR)/bpf |
3 | 3 | ||
4 | CFLAGS += -Wall -O2 -lcap -I../../../include/uapi -I$(LIBDIR) $(BPFOBJ) | 4 | CFLAGS += -Wall -O2 -I../../../include/uapi -I$(LIBDIR) |
5 | LDLIBS += -lcap | ||
5 | 6 | ||
6 | TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map | 7 | TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map |
7 | 8 | ||
8 | TEST_PROGS := test_kmod.sh | 9 | TEST_PROGS := test_kmod.sh |
9 | 10 | ||
10 | all: $(TEST_GEN_PROGS) | 11 | include ../lib.mk |
12 | |||
13 | BPFOBJ := $(OUTPUT)/bpf.o | ||
14 | |||
15 | $(TEST_GEN_PROGS): $(BPFOBJ) | ||
11 | 16 | ||
12 | .PHONY: all clean force | 17 | .PHONY: force |
13 | 18 | ||
14 | # force a rebuild of BPFOBJ when its dependencies are updated | 19 | # force a rebuild of BPFOBJ when its dependencies are updated |
15 | force: | 20 | force: |
16 | 21 | ||
17 | $(BPFOBJ): force | 22 | $(BPFOBJ): force |
18 | $(MAKE) -C $(dir $(BPFOBJ)) | 23 | $(MAKE) -C $(BPFDIR) OUTPUT=$(OUTPUT)/ |
19 | |||
20 | $(test_objs): $(BPFOBJ) | ||
21 | |||
22 | include ../lib.mk | ||
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c index cada17ac00b8..a0aa2009b0e0 100644 --- a/tools/testing/selftests/bpf/test_maps.c +++ b/tools/testing/selftests/bpf/test_maps.c | |||
@@ -80,8 +80,9 @@ static void test_hashmap(int task, void *data) | |||
80 | assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0); | 80 | assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0); |
81 | key = 2; | 81 | key = 2; |
82 | assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); | 82 | assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); |
83 | key = 1; | 83 | key = 3; |
84 | assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); | 84 | assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && |
85 | errno == E2BIG); | ||
85 | 86 | ||
86 | /* Check that key = 0 doesn't exist. */ | 87 | /* Check that key = 0 doesn't exist. */ |
87 | key = 0; | 88 | key = 0; |
@@ -110,6 +111,24 @@ static void test_hashmap(int task, void *data) | |||
110 | close(fd); | 111 | close(fd); |
111 | } | 112 | } |
112 | 113 | ||
114 | static void test_hashmap_sizes(int task, void *data) | ||
115 | { | ||
116 | int fd, i, j; | ||
117 | |||
118 | for (i = 1; i <= 512; i <<= 1) | ||
119 | for (j = 1; j <= 1 << 18; j <<= 1) { | ||
120 | fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j, | ||
121 | 2, map_flags); | ||
122 | if (fd < 0) { | ||
123 | printf("Failed to create hashmap key=%d value=%d '%s'\n", | ||
124 | i, j, strerror(errno)); | ||
125 | exit(1); | ||
126 | } | ||
127 | close(fd); | ||
128 | usleep(10); /* give kernel time to destroy */ | ||
129 | } | ||
130 | } | ||
131 | |||
113 | static void test_hashmap_percpu(int task, void *data) | 132 | static void test_hashmap_percpu(int task, void *data) |
114 | { | 133 | { |
115 | unsigned int nr_cpus = bpf_num_possible_cpus(); | 134 | unsigned int nr_cpus = bpf_num_possible_cpus(); |
@@ -317,7 +336,10 @@ static void test_arraymap_percpu(int task, void *data) | |||
317 | static void test_arraymap_percpu_many_keys(void) | 336 | static void test_arraymap_percpu_many_keys(void) |
318 | { | 337 | { |
319 | unsigned int nr_cpus = bpf_num_possible_cpus(); | 338 | unsigned int nr_cpus = bpf_num_possible_cpus(); |
320 | unsigned int nr_keys = 20000; | 339 | /* nr_keys is not too large otherwise the test stresses percpu |
340 | * allocator more than anything else | ||
341 | */ | ||
342 | unsigned int nr_keys = 2000; | ||
321 | long values[nr_cpus]; | 343 | long values[nr_cpus]; |
322 | int key, fd, i; | 344 | int key, fd, i; |
323 | 345 | ||
@@ -419,6 +441,7 @@ static void test_map_stress(void) | |||
419 | { | 441 | { |
420 | run_parallel(100, test_hashmap, NULL); | 442 | run_parallel(100, test_hashmap, NULL); |
421 | run_parallel(100, test_hashmap_percpu, NULL); | 443 | run_parallel(100, test_hashmap_percpu, NULL); |
444 | run_parallel(100, test_hashmap_sizes, NULL); | ||
422 | 445 | ||
423 | run_parallel(100, test_arraymap, NULL); | 446 | run_parallel(100, test_arraymap, NULL); |
424 | run_parallel(100, test_arraymap_percpu, NULL); | 447 | run_parallel(100, test_arraymap_percpu, NULL); |