diff options
Diffstat (limited to 'net')
31 files changed, 526 insertions, 87 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 476709bd068a..4663c3dad3f5 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -1557,7 +1557,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
1557 | { | 1557 | { |
1558 | BT_DBG("%s %p", hdev->name, hdev); | 1558 | BT_DBG("%s %p", hdev->name, hdev); |
1559 | 1559 | ||
1560 | if (!hci_dev_test_flag(hdev, HCI_UNREGISTER)) { | 1560 | if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) && |
1561 | test_bit(HCI_UP, &hdev->flags)) { | ||
1561 | /* Execute vendor specific shutdown routine */ | 1562 | /* Execute vendor specific shutdown routine */ |
1562 | if (hdev->shutdown) | 1563 | if (hdev->shutdown) |
1563 | hdev->shutdown(hdev); | 1564 | hdev->shutdown(hdev); |
diff --git a/net/core/dev.c b/net/core/dev.c index fd012bbe0486..90a568a150b4 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -5190,7 +5190,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, | |||
5190 | if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper)) | 5190 | if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper)) |
5191 | return -EBUSY; | 5191 | return -EBUSY; |
5192 | 5192 | ||
5193 | if (__netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper)) | 5193 | if (__netdev_find_adj(dev, upper_dev, &dev->adj_list.upper)) |
5194 | return -EEXIST; | 5194 | return -EEXIST; |
5195 | 5195 | ||
5196 | if (master && netdev_master_upper_dev_get(dev)) | 5196 | if (master && netdev_master_upper_dev_get(dev)) |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index a665bf490c88..cbee75f2fc28 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -641,7 +641,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
641 | 641 | ||
642 | id = peernet2id(net, peer); | 642 | id = peernet2id(net, peer); |
643 | err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, | 643 | err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, |
644 | RTM_GETNSID, net, id); | 644 | RTM_NEWNSID, net, id); |
645 | if (err < 0) | 645 | if (err < 0) |
646 | goto err_out; | 646 | goto err_out; |
647 | 647 | ||
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile index 05dab2957cd4..4adfd4d5471b 100644 --- a/net/ieee802154/Makefile +++ b/net/ieee802154/Makefile | |||
@@ -3,7 +3,9 @@ obj-$(CONFIG_IEEE802154_SOCKET) += ieee802154_socket.o | |||
3 | obj-y += 6lowpan/ | 3 | obj-y += 6lowpan/ |
4 | 4 | ||
5 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o core.o \ | 5 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o core.o \ |
6 | header_ops.o sysfs.o nl802154.o | 6 | header_ops.o sysfs.o nl802154.o trace.o |
7 | ieee802154_socket-y := socket.o | 7 | ieee802154_socket-y := socket.o |
8 | 8 | ||
9 | CFLAGS_trace.o := -I$(src) | ||
10 | |||
9 | ccflags-y += -D__CHECK_ENDIAN__ | 11 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index 1b9d25f6e898..346c6665d25e 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c | |||
@@ -175,6 +175,7 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) | |||
175 | int rc = -ENOBUFS; | 175 | int rc = -ENOBUFS; |
176 | struct net_device *dev; | 176 | struct net_device *dev; |
177 | int type = __IEEE802154_DEV_INVALID; | 177 | int type = __IEEE802154_DEV_INVALID; |
178 | unsigned char name_assign_type; | ||
178 | 179 | ||
179 | pr_debug("%s\n", __func__); | 180 | pr_debug("%s\n", __func__); |
180 | 181 | ||
@@ -190,8 +191,10 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) | |||
190 | if (devname[nla_len(info->attrs[IEEE802154_ATTR_DEV_NAME]) - 1] | 191 | if (devname[nla_len(info->attrs[IEEE802154_ATTR_DEV_NAME]) - 1] |
191 | != '\0') | 192 | != '\0') |
192 | return -EINVAL; /* phy name should be null-terminated */ | 193 | return -EINVAL; /* phy name should be null-terminated */ |
194 | name_assign_type = NET_NAME_USER; | ||
193 | } else { | 195 | } else { |
194 | devname = "wpan%d"; | 196 | devname = "wpan%d"; |
197 | name_assign_type = NET_NAME_ENUM; | ||
195 | } | 198 | } |
196 | 199 | ||
197 | if (strlen(devname) >= IFNAMSIZ) | 200 | if (strlen(devname) >= IFNAMSIZ) |
@@ -221,7 +224,7 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) | |||
221 | } | 224 | } |
222 | 225 | ||
223 | dev = rdev_add_virtual_intf_deprecated(wpan_phy_to_rdev(phy), devname, | 226 | dev = rdev_add_virtual_intf_deprecated(wpan_phy_to_rdev(phy), devname, |
224 | type); | 227 | name_assign_type, type); |
225 | if (IS_ERR(dev)) { | 228 | if (IS_ERR(dev)) { |
226 | rc = PTR_ERR(dev); | 229 | rc = PTR_ERR(dev); |
227 | goto nla_put_failure; | 230 | goto nla_put_failure; |
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index a4daf91b8d0a..f3c12f6a4a39 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c | |||
@@ -589,7 +589,7 @@ static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
589 | 589 | ||
590 | return rdev_add_virtual_intf(rdev, | 590 | return rdev_add_virtual_intf(rdev, |
591 | nla_data(info->attrs[NL802154_ATTR_IFNAME]), | 591 | nla_data(info->attrs[NL802154_ATTR_IFNAME]), |
592 | type, extended_addr); | 592 | NET_NAME_USER, type, extended_addr); |
593 | } | 593 | } |
594 | 594 | ||
595 | static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info) | 595 | static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info) |
diff --git a/net/ieee802154/rdev-ops.h b/net/ieee802154/rdev-ops.h index 7c46732fad2b..7b5a9dd94fe5 100644 --- a/net/ieee802154/rdev-ops.h +++ b/net/ieee802154/rdev-ops.h | |||
@@ -4,13 +4,16 @@ | |||
4 | #include <net/cfg802154.h> | 4 | #include <net/cfg802154.h> |
5 | 5 | ||
6 | #include "core.h" | 6 | #include "core.h" |
7 | #include "trace.h" | ||
7 | 8 | ||
8 | static inline struct net_device * | 9 | static inline struct net_device * |
9 | rdev_add_virtual_intf_deprecated(struct cfg802154_registered_device *rdev, | 10 | rdev_add_virtual_intf_deprecated(struct cfg802154_registered_device *rdev, |
10 | const char *name, int type) | 11 | const char *name, |
12 | unsigned char name_assign_type, | ||
13 | int type) | ||
11 | { | 14 | { |
12 | return rdev->ops->add_virtual_intf_deprecated(&rdev->wpan_phy, name, | 15 | return rdev->ops->add_virtual_intf_deprecated(&rdev->wpan_phy, name, |
13 | type); | 16 | name_assign_type, type); |
14 | } | 17 | } |
15 | 18 | ||
16 | static inline void | 19 | static inline void |
@@ -22,75 +25,131 @@ rdev_del_virtual_intf_deprecated(struct cfg802154_registered_device *rdev, | |||
22 | 25 | ||
23 | static inline int | 26 | static inline int |
24 | rdev_add_virtual_intf(struct cfg802154_registered_device *rdev, char *name, | 27 | rdev_add_virtual_intf(struct cfg802154_registered_device *rdev, char *name, |
28 | unsigned char name_assign_type, | ||
25 | enum nl802154_iftype type, __le64 extended_addr) | 29 | enum nl802154_iftype type, __le64 extended_addr) |
26 | { | 30 | { |
27 | return rdev->ops->add_virtual_intf(&rdev->wpan_phy, name, type, | 31 | int ret; |
32 | |||
33 | trace_802154_rdev_add_virtual_intf(&rdev->wpan_phy, name, type, | ||
28 | extended_addr); | 34 | extended_addr); |
35 | ret = rdev->ops->add_virtual_intf(&rdev->wpan_phy, name, | ||
36 | name_assign_type, type, | ||
37 | extended_addr); | ||
38 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
39 | return ret; | ||
29 | } | 40 | } |
30 | 41 | ||
31 | static inline int | 42 | static inline int |
32 | rdev_del_virtual_intf(struct cfg802154_registered_device *rdev, | 43 | rdev_del_virtual_intf(struct cfg802154_registered_device *rdev, |
33 | struct wpan_dev *wpan_dev) | 44 | struct wpan_dev *wpan_dev) |
34 | { | 45 | { |
35 | return rdev->ops->del_virtual_intf(&rdev->wpan_phy, wpan_dev); | 46 | int ret; |
47 | |||
48 | trace_802154_rdev_del_virtual_intf(&rdev->wpan_phy, wpan_dev); | ||
49 | ret = rdev->ops->del_virtual_intf(&rdev->wpan_phy, wpan_dev); | ||
50 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
51 | return ret; | ||
36 | } | 52 | } |
37 | 53 | ||
38 | static inline int | 54 | static inline int |
39 | rdev_set_channel(struct cfg802154_registered_device *rdev, u8 page, u8 channel) | 55 | rdev_set_channel(struct cfg802154_registered_device *rdev, u8 page, u8 channel) |
40 | { | 56 | { |
41 | return rdev->ops->set_channel(&rdev->wpan_phy, page, channel); | 57 | int ret; |
58 | |||
59 | trace_802154_rdev_set_channel(&rdev->wpan_phy, page, channel); | ||
60 | ret = rdev->ops->set_channel(&rdev->wpan_phy, page, channel); | ||
61 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
62 | return ret; | ||
42 | } | 63 | } |
43 | 64 | ||
44 | static inline int | 65 | static inline int |
45 | rdev_set_cca_mode(struct cfg802154_registered_device *rdev, | 66 | rdev_set_cca_mode(struct cfg802154_registered_device *rdev, |
46 | const struct wpan_phy_cca *cca) | 67 | const struct wpan_phy_cca *cca) |
47 | { | 68 | { |
48 | return rdev->ops->set_cca_mode(&rdev->wpan_phy, cca); | 69 | int ret; |
70 | |||
71 | trace_802154_rdev_set_cca_mode(&rdev->wpan_phy, cca); | ||
72 | ret = rdev->ops->set_cca_mode(&rdev->wpan_phy, cca); | ||
73 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
74 | return ret; | ||
49 | } | 75 | } |
50 | 76 | ||
51 | static inline int | 77 | static inline int |
52 | rdev_set_pan_id(struct cfg802154_registered_device *rdev, | 78 | rdev_set_pan_id(struct cfg802154_registered_device *rdev, |
53 | struct wpan_dev *wpan_dev, __le16 pan_id) | 79 | struct wpan_dev *wpan_dev, __le16 pan_id) |
54 | { | 80 | { |
55 | return rdev->ops->set_pan_id(&rdev->wpan_phy, wpan_dev, pan_id); | 81 | int ret; |
82 | |||
83 | trace_802154_rdev_set_pan_id(&rdev->wpan_phy, wpan_dev, pan_id); | ||
84 | ret = rdev->ops->set_pan_id(&rdev->wpan_phy, wpan_dev, pan_id); | ||
85 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
86 | return ret; | ||
56 | } | 87 | } |
57 | 88 | ||
58 | static inline int | 89 | static inline int |
59 | rdev_set_short_addr(struct cfg802154_registered_device *rdev, | 90 | rdev_set_short_addr(struct cfg802154_registered_device *rdev, |
60 | struct wpan_dev *wpan_dev, __le16 short_addr) | 91 | struct wpan_dev *wpan_dev, __le16 short_addr) |
61 | { | 92 | { |
62 | return rdev->ops->set_short_addr(&rdev->wpan_phy, wpan_dev, short_addr); | 93 | int ret; |
94 | |||
95 | trace_802154_rdev_set_short_addr(&rdev->wpan_phy, wpan_dev, short_addr); | ||
96 | ret = rdev->ops->set_short_addr(&rdev->wpan_phy, wpan_dev, short_addr); | ||
97 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
98 | return ret; | ||
63 | } | 99 | } |
64 | 100 | ||
65 | static inline int | 101 | static inline int |
66 | rdev_set_backoff_exponent(struct cfg802154_registered_device *rdev, | 102 | rdev_set_backoff_exponent(struct cfg802154_registered_device *rdev, |
67 | struct wpan_dev *wpan_dev, u8 min_be, u8 max_be) | 103 | struct wpan_dev *wpan_dev, u8 min_be, u8 max_be) |
68 | { | 104 | { |
69 | return rdev->ops->set_backoff_exponent(&rdev->wpan_phy, wpan_dev, | 105 | int ret; |
106 | |||
107 | trace_802154_rdev_set_backoff_exponent(&rdev->wpan_phy, wpan_dev, | ||
70 | min_be, max_be); | 108 | min_be, max_be); |
109 | ret = rdev->ops->set_backoff_exponent(&rdev->wpan_phy, wpan_dev, | ||
110 | min_be, max_be); | ||
111 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
112 | return ret; | ||
71 | } | 113 | } |
72 | 114 | ||
73 | static inline int | 115 | static inline int |
74 | rdev_set_max_csma_backoffs(struct cfg802154_registered_device *rdev, | 116 | rdev_set_max_csma_backoffs(struct cfg802154_registered_device *rdev, |
75 | struct wpan_dev *wpan_dev, u8 max_csma_backoffs) | 117 | struct wpan_dev *wpan_dev, u8 max_csma_backoffs) |
76 | { | 118 | { |
77 | return rdev->ops->set_max_csma_backoffs(&rdev->wpan_phy, wpan_dev, | 119 | int ret; |
78 | max_csma_backoffs); | 120 | |
121 | trace_802154_rdev_set_csma_backoffs(&rdev->wpan_phy, wpan_dev, | ||
122 | max_csma_backoffs); | ||
123 | ret = rdev->ops->set_max_csma_backoffs(&rdev->wpan_phy, wpan_dev, | ||
124 | max_csma_backoffs); | ||
125 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
126 | return ret; | ||
79 | } | 127 | } |
80 | 128 | ||
81 | static inline int | 129 | static inline int |
82 | rdev_set_max_frame_retries(struct cfg802154_registered_device *rdev, | 130 | rdev_set_max_frame_retries(struct cfg802154_registered_device *rdev, |
83 | struct wpan_dev *wpan_dev, s8 max_frame_retries) | 131 | struct wpan_dev *wpan_dev, s8 max_frame_retries) |
84 | { | 132 | { |
85 | return rdev->ops->set_max_frame_retries(&rdev->wpan_phy, wpan_dev, | 133 | int ret; |
134 | |||
135 | trace_802154_rdev_set_max_frame_retries(&rdev->wpan_phy, wpan_dev, | ||
86 | max_frame_retries); | 136 | max_frame_retries); |
137 | ret = rdev->ops->set_max_frame_retries(&rdev->wpan_phy, wpan_dev, | ||
138 | max_frame_retries); | ||
139 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
140 | return ret; | ||
87 | } | 141 | } |
88 | 142 | ||
89 | static inline int | 143 | static inline int |
90 | rdev_set_lbt_mode(struct cfg802154_registered_device *rdev, | 144 | rdev_set_lbt_mode(struct cfg802154_registered_device *rdev, |
91 | struct wpan_dev *wpan_dev, bool mode) | 145 | struct wpan_dev *wpan_dev, bool mode) |
92 | { | 146 | { |
93 | return rdev->ops->set_lbt_mode(&rdev->wpan_phy, wpan_dev, mode); | 147 | int ret; |
148 | |||
149 | trace_802154_rdev_set_lbt_mode(&rdev->wpan_phy, wpan_dev, mode); | ||
150 | ret = rdev->ops->set_lbt_mode(&rdev->wpan_phy, wpan_dev, mode); | ||
151 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
152 | return ret; | ||
94 | } | 153 | } |
95 | 154 | ||
96 | #endif /* __CFG802154_RDEV_OPS */ | 155 | #endif /* __CFG802154_RDEV_OPS */ |
diff --git a/net/ieee802154/trace.c b/net/ieee802154/trace.c new file mode 100644 index 000000000000..95f997fad755 --- /dev/null +++ b/net/ieee802154/trace.c | |||
@@ -0,0 +1,7 @@ | |||
1 | #include <linux/module.h> | ||
2 | |||
3 | #ifndef __CHECKER__ | ||
4 | #define CREATE_TRACE_POINTS | ||
5 | #include "trace.h" | ||
6 | |||
7 | #endif | ||
diff --git a/net/ieee802154/trace.h b/net/ieee802154/trace.h new file mode 100644 index 000000000000..5ac25eb6ed17 --- /dev/null +++ b/net/ieee802154/trace.h | |||
@@ -0,0 +1,247 @@ | |||
1 | /* Based on net/wireless/tracing.h */ | ||
2 | |||
3 | #undef TRACE_SYSTEM | ||
4 | #define TRACE_SYSTEM cfg802154 | ||
5 | |||
6 | #if !defined(__RDEV_CFG802154_OPS_TRACE) || defined(TRACE_HEADER_MULTI_READ) | ||
7 | #define __RDEV_CFG802154_OPS_TRACE | ||
8 | |||
9 | #include <linux/tracepoint.h> | ||
10 | |||
11 | #include <net/cfg802154.h> | ||
12 | |||
13 | #define MAXNAME 32 | ||
14 | #define WPAN_PHY_ENTRY __array(char, wpan_phy_name, MAXNAME) | ||
15 | #define WPAN_PHY_ASSIGN strlcpy(__entry->wpan_phy_name, \ | ||
16 | wpan_phy_name(wpan_phy), \ | ||
17 | MAXNAME) | ||
18 | #define WPAN_PHY_PR_FMT "%s" | ||
19 | #define WPAN_PHY_PR_ARG __entry->wpan_phy_name | ||
20 | |||
21 | #define WPAN_DEV_ENTRY __field(u32, identifier) | ||
22 | #define WPAN_DEV_ASSIGN (__entry->identifier) = (!IS_ERR_OR_NULL(wpan_dev) \ | ||
23 | ? wpan_dev->identifier : 0) | ||
24 | #define WPAN_DEV_PR_FMT "wpan_dev(%u)" | ||
25 | #define WPAN_DEV_PR_ARG (__entry->identifier) | ||
26 | |||
27 | #define WPAN_CCA_ENTRY __field(enum nl802154_cca_modes, cca_mode) \ | ||
28 | __field(enum nl802154_cca_opts, cca_opt) | ||
29 | #define WPAN_CCA_ASSIGN \ | ||
30 | do { \ | ||
31 | (__entry->cca_mode) = cca->mode; \ | ||
32 | (__entry->cca_opt) = cca->opt; \ | ||
33 | } while (0) | ||
34 | #define WPAN_CCA_PR_FMT "cca_mode: %d, cca_opt: %d" | ||
35 | #define WPAN_CCA_PR_ARG __entry->cca_mode, __entry->cca_opt | ||
36 | |||
37 | #define BOOL_TO_STR(bo) (bo) ? "true" : "false" | ||
38 | |||
39 | /************************************************************* | ||
40 | * rdev->ops traces * | ||
41 | *************************************************************/ | ||
42 | |||
43 | TRACE_EVENT(802154_rdev_add_virtual_intf, | ||
44 | TP_PROTO(struct wpan_phy *wpan_phy, char *name, | ||
45 | enum nl802154_iftype type, __le64 extended_addr), | ||
46 | TP_ARGS(wpan_phy, name, type, extended_addr), | ||
47 | TP_STRUCT__entry( | ||
48 | WPAN_PHY_ENTRY | ||
49 | __string(vir_intf_name, name ? name : "<noname>") | ||
50 | __field(enum nl802154_iftype, type) | ||
51 | __field(__le64, extended_addr) | ||
52 | ), | ||
53 | TP_fast_assign( | ||
54 | WPAN_PHY_ASSIGN; | ||
55 | __assign_str(vir_intf_name, name ? name : "<noname>"); | ||
56 | __entry->type = type; | ||
57 | __entry->extended_addr = extended_addr; | ||
58 | ), | ||
59 | TP_printk(WPAN_PHY_PR_FMT ", virtual intf name: %s, type: %d, ea %llx", | ||
60 | WPAN_PHY_PR_ARG, __get_str(vir_intf_name), __entry->type, | ||
61 | __le64_to_cpu(__entry->extended_addr)) | ||
62 | ); | ||
63 | |||
64 | TRACE_EVENT(802154_rdev_del_virtual_intf, | ||
65 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev), | ||
66 | TP_ARGS(wpan_phy, wpan_dev), | ||
67 | TP_STRUCT__entry( | ||
68 | WPAN_PHY_ENTRY | ||
69 | WPAN_DEV_ENTRY | ||
70 | ), | ||
71 | TP_fast_assign( | ||
72 | WPAN_PHY_ASSIGN; | ||
73 | WPAN_DEV_ASSIGN; | ||
74 | ), | ||
75 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT, WPAN_PHY_PR_ARG, | ||
76 | WPAN_DEV_PR_ARG) | ||
77 | ); | ||
78 | |||
79 | TRACE_EVENT(802154_rdev_set_channel, | ||
80 | TP_PROTO(struct wpan_phy *wpan_phy, u8 page, u8 channel), | ||
81 | TP_ARGS(wpan_phy, page, channel), | ||
82 | TP_STRUCT__entry( | ||
83 | WPAN_PHY_ENTRY | ||
84 | __field(u8, page) | ||
85 | __field(u8, channel) | ||
86 | ), | ||
87 | TP_fast_assign( | ||
88 | WPAN_PHY_ASSIGN; | ||
89 | __entry->page = page; | ||
90 | __entry->channel = channel; | ||
91 | ), | ||
92 | TP_printk(WPAN_PHY_PR_FMT ", page: %d, channel: %d", WPAN_PHY_PR_ARG, | ||
93 | __entry->page, __entry->channel) | ||
94 | ); | ||
95 | |||
96 | TRACE_EVENT(802154_rdev_set_cca_mode, | ||
97 | TP_PROTO(struct wpan_phy *wpan_phy, const struct wpan_phy_cca *cca), | ||
98 | TP_ARGS(wpan_phy, cca), | ||
99 | TP_STRUCT__entry( | ||
100 | WPAN_PHY_ENTRY | ||
101 | WPAN_CCA_ENTRY | ||
102 | ), | ||
103 | TP_fast_assign( | ||
104 | WPAN_PHY_ASSIGN; | ||
105 | WPAN_CCA_ASSIGN; | ||
106 | ), | ||
107 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_CCA_PR_FMT, WPAN_PHY_PR_ARG, | ||
108 | WPAN_CCA_PR_ARG) | ||
109 | ); | ||
110 | |||
111 | DECLARE_EVENT_CLASS(802154_le16_template, | ||
112 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
113 | __le16 le16arg), | ||
114 | TP_ARGS(wpan_phy, wpan_dev, le16arg), | ||
115 | TP_STRUCT__entry( | ||
116 | WPAN_PHY_ENTRY | ||
117 | WPAN_DEV_ENTRY | ||
118 | __field(__le16, le16arg) | ||
119 | ), | ||
120 | TP_fast_assign( | ||
121 | WPAN_PHY_ASSIGN; | ||
122 | WPAN_DEV_ASSIGN; | ||
123 | __entry->le16arg = le16arg; | ||
124 | ), | ||
125 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT ", pan id: 0x%04x", | ||
126 | WPAN_PHY_PR_ARG, WPAN_DEV_PR_ARG, | ||
127 | __le16_to_cpu(__entry->le16arg)) | ||
128 | ); | ||
129 | |||
130 | DEFINE_EVENT(802154_le16_template, 802154_rdev_set_pan_id, | ||
131 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
132 | __le16 le16arg), | ||
133 | TP_ARGS(wpan_phy, wpan_dev, le16arg) | ||
134 | ); | ||
135 | |||
136 | DEFINE_EVENT_PRINT(802154_le16_template, 802154_rdev_set_short_addr, | ||
137 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
138 | __le16 le16arg), | ||
139 | TP_ARGS(wpan_phy, wpan_dev, le16arg), | ||
140 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT ", sa: 0x%04x", | ||
141 | WPAN_PHY_PR_ARG, WPAN_DEV_PR_ARG, | ||
142 | __le16_to_cpu(__entry->le16arg)) | ||
143 | ); | ||
144 | |||
145 | TRACE_EVENT(802154_rdev_set_backoff_exponent, | ||
146 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
147 | u8 min_be, u8 max_be), | ||
148 | TP_ARGS(wpan_phy, wpan_dev, min_be, max_be), | ||
149 | TP_STRUCT__entry( | ||
150 | WPAN_PHY_ENTRY | ||
151 | WPAN_DEV_ENTRY | ||
152 | __field(u8, min_be) | ||
153 | __field(u8, max_be) | ||
154 | ), | ||
155 | TP_fast_assign( | ||
156 | WPAN_PHY_ASSIGN; | ||
157 | WPAN_DEV_ASSIGN; | ||
158 | __entry->min_be = min_be; | ||
159 | __entry->max_be = max_be; | ||
160 | ), | ||
161 | |||
162 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT | ||
163 | ", min be: %d, max_be: %d", WPAN_PHY_PR_ARG, | ||
164 | WPAN_DEV_PR_ARG, __entry->min_be, __entry->max_be) | ||
165 | ); | ||
166 | |||
167 | TRACE_EVENT(802154_rdev_set_csma_backoffs, | ||
168 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
169 | u8 max_csma_backoffs), | ||
170 | TP_ARGS(wpan_phy, wpan_dev, max_csma_backoffs), | ||
171 | TP_STRUCT__entry( | ||
172 | WPAN_PHY_ENTRY | ||
173 | WPAN_DEV_ENTRY | ||
174 | __field(u8, max_csma_backoffs) | ||
175 | ), | ||
176 | TP_fast_assign( | ||
177 | WPAN_PHY_ASSIGN; | ||
178 | WPAN_DEV_ASSIGN; | ||
179 | __entry->max_csma_backoffs = max_csma_backoffs; | ||
180 | ), | ||
181 | |||
182 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT | ||
183 | ", max csma backoffs: %d", WPAN_PHY_PR_ARG, | ||
184 | WPAN_DEV_PR_ARG, __entry->max_csma_backoffs) | ||
185 | ); | ||
186 | |||
187 | TRACE_EVENT(802154_rdev_set_max_frame_retries, | ||
188 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
189 | s8 max_frame_retries), | ||
190 | TP_ARGS(wpan_phy, wpan_dev, max_frame_retries), | ||
191 | TP_STRUCT__entry( | ||
192 | WPAN_PHY_ENTRY | ||
193 | WPAN_DEV_ENTRY | ||
194 | __field(s8, max_frame_retries) | ||
195 | ), | ||
196 | TP_fast_assign( | ||
197 | WPAN_PHY_ASSIGN; | ||
198 | WPAN_DEV_ASSIGN; | ||
199 | __entry->max_frame_retries = max_frame_retries; | ||
200 | ), | ||
201 | |||
202 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT | ||
203 | ", max frame retries: %d", WPAN_PHY_PR_ARG, | ||
204 | WPAN_DEV_PR_ARG, __entry->max_frame_retries) | ||
205 | ); | ||
206 | |||
207 | TRACE_EVENT(802154_rdev_set_lbt_mode, | ||
208 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
209 | bool mode), | ||
210 | TP_ARGS(wpan_phy, wpan_dev, mode), | ||
211 | TP_STRUCT__entry( | ||
212 | WPAN_PHY_ENTRY | ||
213 | WPAN_DEV_ENTRY | ||
214 | __field(bool, mode) | ||
215 | ), | ||
216 | TP_fast_assign( | ||
217 | WPAN_PHY_ASSIGN; | ||
218 | WPAN_DEV_ASSIGN; | ||
219 | __entry->mode = mode; | ||
220 | ), | ||
221 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT | ||
222 | ", lbt mode: %s", WPAN_PHY_PR_ARG, | ||
223 | WPAN_DEV_PR_ARG, BOOL_TO_STR(__entry->mode)) | ||
224 | ); | ||
225 | |||
226 | TRACE_EVENT(802154_rdev_return_int, | ||
227 | TP_PROTO(struct wpan_phy *wpan_phy, int ret), | ||
228 | TP_ARGS(wpan_phy, ret), | ||
229 | TP_STRUCT__entry( | ||
230 | WPAN_PHY_ENTRY | ||
231 | __field(int, ret) | ||
232 | ), | ||
233 | TP_fast_assign( | ||
234 | WPAN_PHY_ASSIGN; | ||
235 | __entry->ret = ret; | ||
236 | ), | ||
237 | TP_printk(WPAN_PHY_PR_FMT ", returned: %d", WPAN_PHY_PR_ARG, | ||
238 | __entry->ret) | ||
239 | ); | ||
240 | |||
241 | #endif /* !__RDEV_CFG802154_OPS_TRACE || TRACE_HEADER_MULTI_READ */ | ||
242 | |||
243 | #undef TRACE_INCLUDE_PATH | ||
244 | #define TRACE_INCLUDE_PATH . | ||
245 | #undef TRACE_INCLUDE_FILE | ||
246 | #define TRACE_INCLUDE_FILE trace | ||
247 | #include <trace/define_trace.h> | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 7fde1f265c90..c21777565c58 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -886,22 +886,45 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
886 | #endif | 886 | #endif |
887 | int err; | 887 | int err; |
888 | 888 | ||
889 | if (!*dst) | 889 | /* The correct way to handle this would be to do |
890 | *dst = ip6_route_output(net, sk, fl6); | 890 | * ip6_route_get_saddr, and then ip6_route_output; however, |
891 | 891 | * the route-specific preferred source forces the | |
892 | err = (*dst)->error; | 892 | * ip6_route_output call _before_ ip6_route_get_saddr. |
893 | if (err) | 893 | * |
894 | goto out_err_release; | 894 | * In source specific routing (no src=any default route), |
895 | * ip6_route_output will fail given src=any saddr, though, so | ||
896 | * that's why we try it again later. | ||
897 | */ | ||
898 | if (ipv6_addr_any(&fl6->saddr) && (!*dst || !(*dst)->error)) { | ||
899 | struct rt6_info *rt; | ||
900 | bool had_dst = *dst != NULL; | ||
895 | 901 | ||
896 | if (ipv6_addr_any(&fl6->saddr)) { | 902 | if (!had_dst) |
897 | struct rt6_info *rt = (struct rt6_info *) *dst; | 903 | *dst = ip6_route_output(net, sk, fl6); |
904 | rt = (*dst)->error ? NULL : (struct rt6_info *)*dst; | ||
898 | err = ip6_route_get_saddr(net, rt, &fl6->daddr, | 905 | err = ip6_route_get_saddr(net, rt, &fl6->daddr, |
899 | sk ? inet6_sk(sk)->srcprefs : 0, | 906 | sk ? inet6_sk(sk)->srcprefs : 0, |
900 | &fl6->saddr); | 907 | &fl6->saddr); |
901 | if (err) | 908 | if (err) |
902 | goto out_err_release; | 909 | goto out_err_release; |
910 | |||
911 | /* If we had an erroneous initial result, pretend it | ||
912 | * never existed and let the SA-enabled version take | ||
913 | * over. | ||
914 | */ | ||
915 | if (!had_dst && (*dst)->error) { | ||
916 | dst_release(*dst); | ||
917 | *dst = NULL; | ||
918 | } | ||
903 | } | 919 | } |
904 | 920 | ||
921 | if (!*dst) | ||
922 | *dst = ip6_route_output(net, sk, fl6); | ||
923 | |||
924 | err = (*dst)->error; | ||
925 | if (err) | ||
926 | goto out_err_release; | ||
927 | |||
905 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | 928 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD |
906 | /* | 929 | /* |
907 | * Here if the dst entry we've looked up | 930 | * Here if the dst entry we've looked up |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 106dbe5140f1..6f4a35096bde 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2235,9 +2235,10 @@ int ip6_route_get_saddr(struct net *net, | |||
2235 | unsigned int prefs, | 2235 | unsigned int prefs, |
2236 | struct in6_addr *saddr) | 2236 | struct in6_addr *saddr) |
2237 | { | 2237 | { |
2238 | struct inet6_dev *idev = ip6_dst_idev((struct dst_entry *)rt); | 2238 | struct inet6_dev *idev = |
2239 | rt ? ip6_dst_idev((struct dst_entry *)rt) : NULL; | ||
2239 | int err = 0; | 2240 | int err = 0; |
2240 | if (rt->rt6i_prefsrc.plen) | 2241 | if (rt && rt->rt6i_prefsrc.plen) |
2241 | *saddr = rt->rt6i_prefsrc.addr; | 2242 | *saddr = rt->rt6i_prefsrc.addr; |
2242 | else | 2243 | else |
2243 | err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, | 2244 | err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index dc2d7133c4f6..4ee8fea263ed 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -816,13 +816,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
816 | * (because if we remove a STA after ops->remove_interface() | 816 | * (because if we remove a STA after ops->remove_interface() |
817 | * the driver will have removed the vif info already!) | 817 | * the driver will have removed the vif info already!) |
818 | * | 818 | * |
819 | * This is relevant only in WDS mode, in all other modes we've | 819 | * In WDS mode a station must exist here and be flushed, for |
820 | * already removed all stations when disconnecting or similar, | 820 | * AP_VLANs stations may exist since there's nothing else that |
821 | * so warn otherwise. | 821 | * would have removed them, but in other modes there shouldn't |
822 | * be any stations. | ||
822 | */ | 823 | */ |
823 | flushed = sta_info_flush(sdata); | 824 | flushed = sta_info_flush(sdata); |
824 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || | 825 | WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
825 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); | 826 | ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || |
827 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1))); | ||
826 | 828 | ||
827 | /* don't count this interface for allmulti while it is down */ | 829 | /* don't count this interface for allmulti while it is down */ |
828 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | 830 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index aec15d746aea..ce0c1662de42 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -66,6 +66,7 @@ | |||
66 | 66 | ||
67 | static const struct rhashtable_params sta_rht_params = { | 67 | static const struct rhashtable_params sta_rht_params = { |
68 | .nelem_hint = 3, /* start small */ | 68 | .nelem_hint = 3, /* start small */ |
69 | .automatic_shrinking = true, | ||
69 | .head_offset = offsetof(struct sta_info, hash_node), | 70 | .head_offset = offsetof(struct sta_info, hash_node), |
70 | .key_offset = offsetof(struct sta_info, sta.addr), | 71 | .key_offset = offsetof(struct sta_info, sta.addr), |
71 | .key_len = ETH_ALEN, | 72 | .key_len = ETH_ALEN, |
@@ -158,8 +159,24 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
158 | const u8 *addr) | 159 | const u8 *addr) |
159 | { | 160 | { |
160 | struct ieee80211_local *local = sdata->local; | 161 | struct ieee80211_local *local = sdata->local; |
162 | struct sta_info *sta; | ||
163 | struct rhash_head *tmp; | ||
164 | const struct bucket_table *tbl; | ||
165 | |||
166 | rcu_read_lock(); | ||
167 | tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash); | ||
161 | 168 | ||
162 | return rhashtable_lookup_fast(&local->sta_hash, addr, sta_rht_params); | 169 | for_each_sta_info(local, tbl, addr, sta, tmp) { |
170 | if (sta->sdata == sdata) { | ||
171 | rcu_read_unlock(); | ||
172 | /* this is safe as the caller must already hold | ||
173 | * another rcu read section or the mutex | ||
174 | */ | ||
175 | return sta; | ||
176 | } | ||
177 | } | ||
178 | rcu_read_unlock(); | ||
179 | return NULL; | ||
163 | } | 180 | } |
164 | 181 | ||
165 | /* | 182 | /* |
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c index 5d9f68c75e5f..70be9c799f8a 100644 --- a/net/mac802154/cfg.c +++ b/net/mac802154/cfg.c | |||
@@ -22,13 +22,14 @@ | |||
22 | 22 | ||
23 | static struct net_device * | 23 | static struct net_device * |
24 | ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy, | 24 | ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy, |
25 | const char *name, int type) | 25 | const char *name, |
26 | unsigned char name_assign_type, int type) | ||
26 | { | 27 | { |
27 | struct ieee802154_local *local = wpan_phy_priv(wpan_phy); | 28 | struct ieee802154_local *local = wpan_phy_priv(wpan_phy); |
28 | struct net_device *dev; | 29 | struct net_device *dev; |
29 | 30 | ||
30 | rtnl_lock(); | 31 | rtnl_lock(); |
31 | dev = ieee802154_if_add(local, name, type, | 32 | dev = ieee802154_if_add(local, name, name_assign_type, type, |
32 | cpu_to_le64(0x0000000000000000ULL)); | 33 | cpu_to_le64(0x0000000000000000ULL)); |
33 | rtnl_unlock(); | 34 | rtnl_unlock(); |
34 | 35 | ||
@@ -45,12 +46,14 @@ static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy, | |||
45 | 46 | ||
46 | static int | 47 | static int |
47 | ieee802154_add_iface(struct wpan_phy *phy, const char *name, | 48 | ieee802154_add_iface(struct wpan_phy *phy, const char *name, |
49 | unsigned char name_assign_type, | ||
48 | enum nl802154_iftype type, __le64 extended_addr) | 50 | enum nl802154_iftype type, __le64 extended_addr) |
49 | { | 51 | { |
50 | struct ieee802154_local *local = wpan_phy_priv(phy); | 52 | struct ieee802154_local *local = wpan_phy_priv(phy); |
51 | struct net_device *err; | 53 | struct net_device *err; |
52 | 54 | ||
53 | err = ieee802154_if_add(local, name, type, extended_addr); | 55 | err = ieee802154_if_add(local, name, name_assign_type, type, |
56 | extended_addr); | ||
54 | return PTR_ERR_OR_ZERO(err); | 57 | return PTR_ERR_OR_ZERO(err); |
55 | } | 58 | } |
56 | 59 | ||
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h index bebd70ffc7a3..127ba18386fc 100644 --- a/net/mac802154/ieee802154_i.h +++ b/net/mac802154/ieee802154_i.h | |||
@@ -182,7 +182,8 @@ void ieee802154_iface_exit(void); | |||
182 | void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata); | 182 | void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata); |
183 | struct net_device * | 183 | struct net_device * |
184 | ieee802154_if_add(struct ieee802154_local *local, const char *name, | 184 | ieee802154_if_add(struct ieee802154_local *local, const char *name, |
185 | enum nl802154_iftype type, __le64 extended_addr); | 185 | unsigned char name_assign_type, enum nl802154_iftype type, |
186 | __le64 extended_addr); | ||
186 | void ieee802154_remove_interfaces(struct ieee802154_local *local); | 187 | void ieee802154_remove_interfaces(struct ieee802154_local *local); |
187 | 188 | ||
188 | #endif /* __IEEE802154_I_H */ | 189 | #endif /* __IEEE802154_I_H */ |
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 38b56f9d9386..91b75abbd1a1 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c | |||
@@ -522,7 +522,8 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, | |||
522 | 522 | ||
523 | struct net_device * | 523 | struct net_device * |
524 | ieee802154_if_add(struct ieee802154_local *local, const char *name, | 524 | ieee802154_if_add(struct ieee802154_local *local, const char *name, |
525 | enum nl802154_iftype type, __le64 extended_addr) | 525 | unsigned char name_assign_type, enum nl802154_iftype type, |
526 | __le64 extended_addr) | ||
526 | { | 527 | { |
527 | struct net_device *ndev = NULL; | 528 | struct net_device *ndev = NULL; |
528 | struct ieee802154_sub_if_data *sdata = NULL; | 529 | struct ieee802154_sub_if_data *sdata = NULL; |
@@ -531,7 +532,7 @@ ieee802154_if_add(struct ieee802154_local *local, const char *name, | |||
531 | ASSERT_RTNL(); | 532 | ASSERT_RTNL(); |
532 | 533 | ||
533 | ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, name, | 534 | ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, name, |
534 | NET_NAME_UNKNOWN, ieee802154_if_setup); | 535 | name_assign_type, ieee802154_if_setup); |
535 | if (!ndev) | 536 | if (!ndev) |
536 | return ERR_PTR(-ENOMEM); | 537 | return ERR_PTR(-ENOMEM); |
537 | 538 | ||
diff --git a/net/mac802154/llsec.c b/net/mac802154/llsec.c index dcf73958133a..5b2be12832e6 100644 --- a/net/mac802154/llsec.c +++ b/net/mac802154/llsec.c | |||
@@ -134,7 +134,7 @@ llsec_key_alloc(const struct ieee802154_llsec_key *template) | |||
134 | for (i = 0; i < ARRAY_SIZE(key->tfm); i++) { | 134 | for (i = 0; i < ARRAY_SIZE(key->tfm); i++) { |
135 | key->tfm[i] = crypto_alloc_aead("ccm(aes)", 0, | 135 | key->tfm[i] = crypto_alloc_aead("ccm(aes)", 0, |
136 | CRYPTO_ALG_ASYNC); | 136 | CRYPTO_ALG_ASYNC); |
137 | if (!key->tfm[i]) | 137 | if (IS_ERR(key->tfm[i])) |
138 | goto err_tfm; | 138 | goto err_tfm; |
139 | if (crypto_aead_setkey(key->tfm[i], template->key, | 139 | if (crypto_aead_setkey(key->tfm[i], template->key, |
140 | IEEE802154_LLSEC_KEY_SIZE)) | 140 | IEEE802154_LLSEC_KEY_SIZE)) |
@@ -144,7 +144,7 @@ llsec_key_alloc(const struct ieee802154_llsec_key *template) | |||
144 | } | 144 | } |
145 | 145 | ||
146 | key->tfm0 = crypto_alloc_blkcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC); | 146 | key->tfm0 = crypto_alloc_blkcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC); |
147 | if (!key->tfm0) | 147 | if (IS_ERR(key->tfm0)) |
148 | goto err_tfm; | 148 | goto err_tfm; |
149 | 149 | ||
150 | if (crypto_blkcipher_setkey(key->tfm0, template->key, | 150 | if (crypto_blkcipher_setkey(key->tfm0, template->key, |
diff --git a/net/mac802154/main.c b/net/mac802154/main.c index 8500378c8318..08cb32dc8fd3 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c | |||
@@ -161,18 +161,21 @@ int ieee802154_register_hw(struct ieee802154_hw *hw) | |||
161 | 161 | ||
162 | rtnl_lock(); | 162 | rtnl_lock(); |
163 | 163 | ||
164 | dev = ieee802154_if_add(local, "wpan%d", NL802154_IFTYPE_NODE, | 164 | dev = ieee802154_if_add(local, "wpan%d", NET_NAME_ENUM, |
165 | NL802154_IFTYPE_NODE, | ||
165 | cpu_to_le64(0x0000000000000000ULL)); | 166 | cpu_to_le64(0x0000000000000000ULL)); |
166 | if (IS_ERR(dev)) { | 167 | if (IS_ERR(dev)) { |
167 | rtnl_unlock(); | 168 | rtnl_unlock(); |
168 | rc = PTR_ERR(dev); | 169 | rc = PTR_ERR(dev); |
169 | goto out_wq; | 170 | goto out_phy; |
170 | } | 171 | } |
171 | 172 | ||
172 | rtnl_unlock(); | 173 | rtnl_unlock(); |
173 | 174 | ||
174 | return 0; | 175 | return 0; |
175 | 176 | ||
177 | out_phy: | ||
178 | wpan_phy_unregister(local->phy); | ||
176 | out_wq: | 179 | out_wq: |
177 | destroy_workqueue(local->workqueue); | 180 | destroy_workqueue(local->workqueue); |
178 | out: | 181 | out: |
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index 954810c76a86..7b3f732269e4 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c | |||
@@ -647,7 +647,7 @@ int nla_get_labels(const struct nlattr *nla, | |||
647 | return -EINVAL; | 647 | return -EINVAL; |
648 | 648 | ||
649 | switch (dec.label) { | 649 | switch (dec.label) { |
650 | case LABEL_IMPLICIT_NULL: | 650 | case MPLS_LABEL_IMPLNULL: |
651 | /* RFC3032: This is a label that an LSR may | 651 | /* RFC3032: This is a label that an LSR may |
652 | * assign and distribute, but which never | 652 | * assign and distribute, but which never |
653 | * actually appears in the encapsulation. | 653 | * actually appears in the encapsulation. |
@@ -935,7 +935,7 @@ static int resize_platform_label_table(struct net *net, size_t limit) | |||
935 | } | 935 | } |
936 | 936 | ||
937 | /* In case the predefined labels need to be populated */ | 937 | /* In case the predefined labels need to be populated */ |
938 | if (limit > LABEL_IPV4_EXPLICIT_NULL) { | 938 | if (limit > MPLS_LABEL_IPV4NULL) { |
939 | struct net_device *lo = net->loopback_dev; | 939 | struct net_device *lo = net->loopback_dev; |
940 | rt0 = mpls_rt_alloc(lo->addr_len); | 940 | rt0 = mpls_rt_alloc(lo->addr_len); |
941 | if (!rt0) | 941 | if (!rt0) |
@@ -945,7 +945,7 @@ static int resize_platform_label_table(struct net *net, size_t limit) | |||
945 | rt0->rt_via_table = NEIGH_LINK_TABLE; | 945 | rt0->rt_via_table = NEIGH_LINK_TABLE; |
946 | memcpy(rt0->rt_via, lo->dev_addr, lo->addr_len); | 946 | memcpy(rt0->rt_via, lo->dev_addr, lo->addr_len); |
947 | } | 947 | } |
948 | if (limit > LABEL_IPV6_EXPLICIT_NULL) { | 948 | if (limit > MPLS_LABEL_IPV6NULL) { |
949 | struct net_device *lo = net->loopback_dev; | 949 | struct net_device *lo = net->loopback_dev; |
950 | rt2 = mpls_rt_alloc(lo->addr_len); | 950 | rt2 = mpls_rt_alloc(lo->addr_len); |
951 | if (!rt2) | 951 | if (!rt2) |
@@ -973,15 +973,15 @@ static int resize_platform_label_table(struct net *net, size_t limit) | |||
973 | memcpy(labels, old, cp_size); | 973 | memcpy(labels, old, cp_size); |
974 | 974 | ||
975 | /* If needed set the predefined labels */ | 975 | /* If needed set the predefined labels */ |
976 | if ((old_limit <= LABEL_IPV6_EXPLICIT_NULL) && | 976 | if ((old_limit <= MPLS_LABEL_IPV6NULL) && |
977 | (limit > LABEL_IPV6_EXPLICIT_NULL)) { | 977 | (limit > MPLS_LABEL_IPV6NULL)) { |
978 | RCU_INIT_POINTER(labels[LABEL_IPV6_EXPLICIT_NULL], rt2); | 978 | RCU_INIT_POINTER(labels[MPLS_LABEL_IPV6NULL], rt2); |
979 | rt2 = NULL; | 979 | rt2 = NULL; |
980 | } | 980 | } |
981 | 981 | ||
982 | if ((old_limit <= LABEL_IPV4_EXPLICIT_NULL) && | 982 | if ((old_limit <= MPLS_LABEL_IPV4NULL) && |
983 | (limit > LABEL_IPV4_EXPLICIT_NULL)) { | 983 | (limit > MPLS_LABEL_IPV4NULL)) { |
984 | RCU_INIT_POINTER(labels[LABEL_IPV4_EXPLICIT_NULL], rt0); | 984 | RCU_INIT_POINTER(labels[MPLS_LABEL_IPV4NULL], rt0); |
985 | rt0 = NULL; | 985 | rt0 = NULL; |
986 | } | 986 | } |
987 | 987 | ||
diff --git a/net/mpls/internal.h b/net/mpls/internal.h index 693877d69606..b064c345042c 100644 --- a/net/mpls/internal.h +++ b/net/mpls/internal.h | |||
@@ -1,16 +1,6 @@ | |||
1 | #ifndef MPLS_INTERNAL_H | 1 | #ifndef MPLS_INTERNAL_H |
2 | #define MPLS_INTERNAL_H | 2 | #define MPLS_INTERNAL_H |
3 | 3 | ||
4 | #define LABEL_IPV4_EXPLICIT_NULL 0 /* RFC3032 */ | ||
5 | #define LABEL_ROUTER_ALERT_LABEL 1 /* RFC3032 */ | ||
6 | #define LABEL_IPV6_EXPLICIT_NULL 2 /* RFC3032 */ | ||
7 | #define LABEL_IMPLICIT_NULL 3 /* RFC3032 */ | ||
8 | #define LABEL_ENTROPY_INDICATOR 7 /* RFC6790 */ | ||
9 | #define LABEL_GAL 13 /* RFC5586 */ | ||
10 | #define LABEL_OAM_ALERT 14 /* RFC3429 */ | ||
11 | #define LABEL_EXTENSION 15 /* RFC7274 */ | ||
12 | |||
13 | |||
14 | struct mpls_shim_hdr { | 4 | struct mpls_shim_hdr { |
15 | __be32 label_stack_entry; | 5 | __be32 label_stack_entry; |
16 | }; | 6 | }; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index e9b9559731bb..164ded7050b8 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -3179,7 +3179,6 @@ static const struct rhashtable_params netlink_rhashtable_params = { | |||
3179 | .key_len = netlink_compare_arg_len, | 3179 | .key_len = netlink_compare_arg_len, |
3180 | .obj_hashfn = netlink_hash, | 3180 | .obj_hashfn = netlink_hash, |
3181 | .obj_cmpfn = netlink_compare, | 3181 | .obj_cmpfn = netlink_compare, |
3182 | .max_size = 65536, | ||
3183 | .automatic_shrinking = true, | 3182 | .automatic_shrinking = true, |
3184 | }; | 3183 | }; |
3185 | 3184 | ||
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 94713276a1d9..12c5dde8e344 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -2311,11 +2311,14 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
2311 | tlen = dev->needed_tailroom; | 2311 | tlen = dev->needed_tailroom; |
2312 | skb = sock_alloc_send_skb(&po->sk, | 2312 | skb = sock_alloc_send_skb(&po->sk, |
2313 | hlen + tlen + sizeof(struct sockaddr_ll), | 2313 | hlen + tlen + sizeof(struct sockaddr_ll), |
2314 | 0, &err); | 2314 | !need_wait, &err); |
2315 | 2315 | ||
2316 | if (unlikely(skb == NULL)) | 2316 | if (unlikely(skb == NULL)) { |
2317 | /* we assume the socket was initially writeable ... */ | ||
2318 | if (likely(len_sum > 0)) | ||
2319 | err = len_sum; | ||
2317 | goto out_status; | 2320 | goto out_status; |
2318 | 2321 | } | |
2319 | tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, | 2322 | tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, |
2320 | addr, hlen); | 2323 | addr, hlen); |
2321 | if (tp_len > dev->mtu + dev->hard_header_len) { | 2324 | if (tp_len > dev->mtu + dev->hard_header_len) { |
diff --git a/net/rds/connection.c b/net/rds/connection.c index 14f041398ca1..da6da57e5f36 100644 --- a/net/rds/connection.c +++ b/net/rds/connection.c | |||
@@ -126,7 +126,10 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, | |||
126 | struct rds_transport *loop_trans; | 126 | struct rds_transport *loop_trans; |
127 | unsigned long flags; | 127 | unsigned long flags; |
128 | int ret; | 128 | int ret; |
129 | struct rds_transport *otrans = trans; | ||
129 | 130 | ||
131 | if (!is_outgoing && otrans->t_type == RDS_TRANS_TCP) | ||
132 | goto new_conn; | ||
130 | rcu_read_lock(); | 133 | rcu_read_lock(); |
131 | conn = rds_conn_lookup(head, laddr, faddr, trans); | 134 | conn = rds_conn_lookup(head, laddr, faddr, trans); |
132 | if (conn && conn->c_loopback && conn->c_trans != &rds_loop_transport && | 135 | if (conn && conn->c_loopback && conn->c_trans != &rds_loop_transport && |
@@ -142,6 +145,7 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, | |||
142 | if (conn) | 145 | if (conn) |
143 | goto out; | 146 | goto out; |
144 | 147 | ||
148 | new_conn: | ||
145 | conn = kmem_cache_zalloc(rds_conn_slab, gfp); | 149 | conn = kmem_cache_zalloc(rds_conn_slab, gfp); |
146 | if (!conn) { | 150 | if (!conn) { |
147 | conn = ERR_PTR(-ENOMEM); | 151 | conn = ERR_PTR(-ENOMEM); |
@@ -230,13 +234,22 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, | |||
230 | /* Creating normal conn */ | 234 | /* Creating normal conn */ |
231 | struct rds_connection *found; | 235 | struct rds_connection *found; |
232 | 236 | ||
233 | found = rds_conn_lookup(head, laddr, faddr, trans); | 237 | if (!is_outgoing && otrans->t_type == RDS_TRANS_TCP) |
238 | found = NULL; | ||
239 | else | ||
240 | found = rds_conn_lookup(head, laddr, faddr, trans); | ||
234 | if (found) { | 241 | if (found) { |
235 | trans->conn_free(conn->c_transport_data); | 242 | trans->conn_free(conn->c_transport_data); |
236 | kmem_cache_free(rds_conn_slab, conn); | 243 | kmem_cache_free(rds_conn_slab, conn); |
237 | conn = found; | 244 | conn = found; |
238 | } else { | 245 | } else { |
239 | hlist_add_head_rcu(&conn->c_hash_node, head); | 246 | if ((is_outgoing && otrans->t_type == RDS_TRANS_TCP) || |
247 | (otrans->t_type != RDS_TRANS_TCP)) { | ||
248 | /* Only the active side should be added to | ||
249 | * reconnect list for TCP. | ||
250 | */ | ||
251 | hlist_add_head_rcu(&conn->c_hash_node, head); | ||
252 | } | ||
240 | rds_cong_add_conn(conn); | 253 | rds_cong_add_conn(conn); |
241 | rds_conn_count++; | 254 | rds_conn_count++; |
242 | } | 255 | } |
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index 31b74f5e61ad..8a09ee7db3c1 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c | |||
@@ -183,8 +183,17 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even | |||
183 | 183 | ||
184 | /* If the peer gave us the last packet it saw, process this as if | 184 | /* If the peer gave us the last packet it saw, process this as if |
185 | * we had received a regular ACK. */ | 185 | * we had received a regular ACK. */ |
186 | if (dp && dp->dp_ack_seq) | 186 | if (dp) { |
187 | rds_send_drop_acked(conn, be64_to_cpu(dp->dp_ack_seq), NULL); | 187 | /* dp structure start is not guaranteed to be 8 bytes aligned. |
188 | * Since dp_ack_seq is 64-bit extended load operations can be | ||
189 | * used so go through get_unaligned to avoid unaligned errors. | ||
190 | */ | ||
191 | __be64 dp_ack_seq = get_unaligned(&dp->dp_ack_seq); | ||
192 | |||
193 | if (dp_ack_seq) | ||
194 | rds_send_drop_acked(conn, be64_to_cpu(dp_ack_seq), | ||
195 | NULL); | ||
196 | } | ||
188 | 197 | ||
189 | rds_connect_complete(conn); | 198 | rds_connect_complete(conn); |
190 | } | 199 | } |
diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c index f9f564a6c960..973109c7b8e8 100644 --- a/net/rds/tcp_connect.c +++ b/net/rds/tcp_connect.c | |||
@@ -62,6 +62,7 @@ void rds_tcp_state_change(struct sock *sk) | |||
62 | case TCP_ESTABLISHED: | 62 | case TCP_ESTABLISHED: |
63 | rds_connect_complete(conn); | 63 | rds_connect_complete(conn); |
64 | break; | 64 | break; |
65 | case TCP_CLOSE_WAIT: | ||
65 | case TCP_CLOSE: | 66 | case TCP_CLOSE: |
66 | rds_conn_drop(conn); | 67 | rds_conn_drop(conn); |
67 | default: | 68 | default: |
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index 23ab4dcd1d9f..0da49e34495f 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c | |||
@@ -45,12 +45,45 @@ static void rds_tcp_accept_worker(struct work_struct *work); | |||
45 | static DECLARE_WORK(rds_tcp_listen_work, rds_tcp_accept_worker); | 45 | static DECLARE_WORK(rds_tcp_listen_work, rds_tcp_accept_worker); |
46 | static struct socket *rds_tcp_listen_sock; | 46 | static struct socket *rds_tcp_listen_sock; |
47 | 47 | ||
48 | static int rds_tcp_keepalive(struct socket *sock) | ||
49 | { | ||
50 | /* values below based on xs_udp_default_timeout */ | ||
51 | int keepidle = 5; /* send a probe 'keepidle' secs after last data */ | ||
52 | int keepcnt = 5; /* number of unack'ed probes before declaring dead */ | ||
53 | int keepalive = 1; | ||
54 | int ret = 0; | ||
55 | |||
56 | ret = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, | ||
57 | (char *)&keepalive, sizeof(keepalive)); | ||
58 | if (ret < 0) | ||
59 | goto bail; | ||
60 | |||
61 | ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, | ||
62 | (char *)&keepcnt, sizeof(keepcnt)); | ||
63 | if (ret < 0) | ||
64 | goto bail; | ||
65 | |||
66 | ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, | ||
67 | (char *)&keepidle, sizeof(keepidle)); | ||
68 | if (ret < 0) | ||
69 | goto bail; | ||
70 | |||
71 | /* KEEPINTVL is the interval between successive probes. We follow | ||
72 | * the model in xs_tcp_finish_connecting() and re-use keepidle. | ||
73 | */ | ||
74 | ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, | ||
75 | (char *)&keepidle, sizeof(keepidle)); | ||
76 | bail: | ||
77 | return ret; | ||
78 | } | ||
79 | |||
48 | static int rds_tcp_accept_one(struct socket *sock) | 80 | static int rds_tcp_accept_one(struct socket *sock) |
49 | { | 81 | { |
50 | struct socket *new_sock = NULL; | 82 | struct socket *new_sock = NULL; |
51 | struct rds_connection *conn; | 83 | struct rds_connection *conn; |
52 | int ret; | 84 | int ret; |
53 | struct inet_sock *inet; | 85 | struct inet_sock *inet; |
86 | struct rds_tcp_connection *rs_tcp; | ||
54 | 87 | ||
55 | ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type, | 88 | ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type, |
56 | sock->sk->sk_protocol, &new_sock); | 89 | sock->sk->sk_protocol, &new_sock); |
@@ -63,6 +96,10 @@ static int rds_tcp_accept_one(struct socket *sock) | |||
63 | if (ret < 0) | 96 | if (ret < 0) |
64 | goto out; | 97 | goto out; |
65 | 98 | ||
99 | ret = rds_tcp_keepalive(new_sock); | ||
100 | if (ret < 0) | ||
101 | goto out; | ||
102 | |||
66 | rds_tcp_tune(new_sock); | 103 | rds_tcp_tune(new_sock); |
67 | 104 | ||
68 | inet = inet_sk(new_sock->sk); | 105 | inet = inet_sk(new_sock->sk); |
@@ -77,6 +114,15 @@ static int rds_tcp_accept_one(struct socket *sock) | |||
77 | ret = PTR_ERR(conn); | 114 | ret = PTR_ERR(conn); |
78 | goto out; | 115 | goto out; |
79 | } | 116 | } |
117 | /* An incoming SYN request came in, and TCP just accepted it. | ||
118 | * We always create a new conn for listen side of TCP, and do not | ||
119 | * add it to the c_hash_list. | ||
120 | * | ||
121 | * If the client reboots, this conn will need to be cleaned up. | ||
122 | * rds_tcp_state_change() will do that cleanup | ||
123 | */ | ||
124 | rs_tcp = (struct rds_tcp_connection *)conn->c_transport_data; | ||
125 | WARN_ON(!rs_tcp || rs_tcp->t_sock); | ||
80 | 126 | ||
81 | /* | 127 | /* |
82 | * see the comment above rds_queue_delayed_reconnect() | 128 | * see the comment above rds_queue_delayed_reconnect() |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 8b0470e418dc..b6ef9a04de06 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -308,12 +308,11 @@ replay: | |||
308 | case RTM_DELTFILTER: | 308 | case RTM_DELTFILTER: |
309 | err = tp->ops->delete(tp, fh); | 309 | err = tp->ops->delete(tp, fh); |
310 | if (err == 0) { | 310 | if (err == 0) { |
311 | tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); | 311 | struct tcf_proto *next = rtnl_dereference(tp->next); |
312 | if (tcf_destroy(tp, false)) { | ||
313 | struct tcf_proto *next = rtnl_dereference(tp->next); | ||
314 | 312 | ||
313 | tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); | ||
314 | if (tcf_destroy(tp, false)) | ||
315 | RCU_INIT_POINTER(*back, next); | 315 | RCU_INIT_POINTER(*back, next); |
316 | } | ||
317 | } | 316 | } |
318 | goto errout; | 317 | goto errout; |
319 | case RTM_GETTFILTER: | 318 | case RTM_GETTFILTER: |
diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c index 1474b6560fac..535007d5f0b5 100644 --- a/net/sched/sch_codel.c +++ b/net/sched/sch_codel.c | |||
@@ -171,7 +171,7 @@ static int codel_init(struct Qdisc *sch, struct nlattr *opt) | |||
171 | 171 | ||
172 | sch->limit = DEFAULT_CODEL_LIMIT; | 172 | sch->limit = DEFAULT_CODEL_LIMIT; |
173 | 173 | ||
174 | codel_params_init(&q->params); | 174 | codel_params_init(&q->params, sch); |
175 | codel_vars_init(&q->vars); | 175 | codel_vars_init(&q->vars); |
176 | codel_stats_init(&q->stats); | 176 | codel_stats_init(&q->stats); |
177 | 177 | ||
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 778739786b32..d75993f89fac 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c | |||
@@ -391,7 +391,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt) | |||
391 | q->perturbation = prandom_u32(); | 391 | q->perturbation = prandom_u32(); |
392 | INIT_LIST_HEAD(&q->new_flows); | 392 | INIT_LIST_HEAD(&q->new_flows); |
393 | INIT_LIST_HEAD(&q->old_flows); | 393 | INIT_LIST_HEAD(&q->old_flows); |
394 | codel_params_init(&q->cparams); | 394 | codel_params_init(&q->cparams, sch); |
395 | codel_stats_init(&q->cstats); | 395 | codel_stats_init(&q->cstats); |
396 | q->cparams.ecn = true; | 396 | q->cparams.ecn = true; |
397 | 397 | ||
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 826e2994152b..abb9f2fec28f 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c | |||
@@ -230,7 +230,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
230 | break; | 230 | break; |
231 | } | 231 | } |
232 | 232 | ||
233 | if (q->backlog + qdisc_pkt_len(skb) <= q->limit) { | 233 | if (gred_backlog(t, q, sch) + qdisc_pkt_len(skb) <= q->limit) { |
234 | q->backlog += qdisc_pkt_len(skb); | 234 | q->backlog += qdisc_pkt_len(skb); |
235 | return qdisc_enqueue_tail(skb, sch); | 235 | return qdisc_enqueue_tail(skb, sch); |
236 | } | 236 | } |
@@ -573,7 +573,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
573 | 573 | ||
574 | opt.limit = q->limit; | 574 | opt.limit = q->limit; |
575 | opt.DP = q->DP; | 575 | opt.DP = q->DP; |
576 | opt.backlog = q->backlog; | 576 | opt.backlog = gred_backlog(table, q, sch); |
577 | opt.prio = q->prio; | 577 | opt.prio = q->prio; |
578 | opt.qth_min = q->parms.qth_min >> q->parms.Wlog; | 578 | opt.qth_min = q->parms.qth_min >> q->parms.Wlog; |
579 | opt.qth_max = q->parms.qth_max >> q->parms.Wlog; | 579 | opt.qth_max = q->parms.qth_max >> q->parms.Wlog; |
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c index 1ec19f6f0c2b..eeeba5adee6d 100644 --- a/net/sunrpc/auth_gss/gss_rpc_xdr.c +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c | |||
@@ -793,20 +793,26 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, | |||
793 | { | 793 | { |
794 | u32 value_follows; | 794 | u32 value_follows; |
795 | int err; | 795 | int err; |
796 | struct page *scratch; | ||
797 | |||
798 | scratch = alloc_page(GFP_KERNEL); | ||
799 | if (!scratch) | ||
800 | return -ENOMEM; | ||
801 | xdr_set_scratch_buffer(xdr, page_address(scratch), PAGE_SIZE); | ||
796 | 802 | ||
797 | /* res->status */ | 803 | /* res->status */ |
798 | err = gssx_dec_status(xdr, &res->status); | 804 | err = gssx_dec_status(xdr, &res->status); |
799 | if (err) | 805 | if (err) |
800 | return err; | 806 | goto out_free; |
801 | 807 | ||
802 | /* res->context_handle */ | 808 | /* res->context_handle */ |
803 | err = gssx_dec_bool(xdr, &value_follows); | 809 | err = gssx_dec_bool(xdr, &value_follows); |
804 | if (err) | 810 | if (err) |
805 | return err; | 811 | goto out_free; |
806 | if (value_follows) { | 812 | if (value_follows) { |
807 | err = gssx_dec_ctx(xdr, res->context_handle); | 813 | err = gssx_dec_ctx(xdr, res->context_handle); |
808 | if (err) | 814 | if (err) |
809 | return err; | 815 | goto out_free; |
810 | } else { | 816 | } else { |
811 | res->context_handle = NULL; | 817 | res->context_handle = NULL; |
812 | } | 818 | } |
@@ -814,11 +820,11 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, | |||
814 | /* res->output_token */ | 820 | /* res->output_token */ |
815 | err = gssx_dec_bool(xdr, &value_follows); | 821 | err = gssx_dec_bool(xdr, &value_follows); |
816 | if (err) | 822 | if (err) |
817 | return err; | 823 | goto out_free; |
818 | if (value_follows) { | 824 | if (value_follows) { |
819 | err = gssx_dec_buffer(xdr, res->output_token); | 825 | err = gssx_dec_buffer(xdr, res->output_token); |
820 | if (err) | 826 | if (err) |
821 | return err; | 827 | goto out_free; |
822 | } else { | 828 | } else { |
823 | res->output_token = NULL; | 829 | res->output_token = NULL; |
824 | } | 830 | } |
@@ -826,14 +832,17 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, | |||
826 | /* res->delegated_cred_handle */ | 832 | /* res->delegated_cred_handle */ |
827 | err = gssx_dec_bool(xdr, &value_follows); | 833 | err = gssx_dec_bool(xdr, &value_follows); |
828 | if (err) | 834 | if (err) |
829 | return err; | 835 | goto out_free; |
830 | if (value_follows) { | 836 | if (value_follows) { |
831 | /* we do not support upcall servers sending this data. */ | 837 | /* we do not support upcall servers sending this data. */ |
832 | return -EINVAL; | 838 | err = -EINVAL; |
839 | goto out_free; | ||
833 | } | 840 | } |
834 | 841 | ||
835 | /* res->options */ | 842 | /* res->options */ |
836 | err = gssx_dec_option_array(xdr, &res->options); | 843 | err = gssx_dec_option_array(xdr, &res->options); |
837 | 844 | ||
845 | out_free: | ||
846 | __free_page(scratch); | ||
838 | return err; | 847 | return err; |
839 | } | 848 | } |