diff options
Diffstat (limited to 'net/wimax/op-msg.c')
| -rw-r--r-- | net/wimax/op-msg.c | 67 |
1 files changed, 27 insertions, 40 deletions
diff --git a/net/wimax/op-msg.c b/net/wimax/op-msg.c index cb3b4ad5368..c278b3356f7 100644 --- a/net/wimax/op-msg.c +++ b/net/wimax/op-msg.c @@ -72,10 +72,12 @@ * wimax_msg_send() */ #include <linux/device.h> +#include <linux/slab.h> #include <net/genetlink.h> #include <linux/netdevice.h> #include <linux/wimax.h> #include <linux/security.h> +#include <linux/export.h> #include "wimax-internal.h" @@ -108,6 +110,12 @@ * Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as * wimax_msg_send() depends on skb->data being placed at the * beginning of the user message. + * + * Unlike other WiMAX stack calls, this call can be used way early, + * even before wimax_dev_add() is called, as long as the + * wimax_dev->net_dev pointer is set to point to a proper + * net_dev. This is so that drivers can use it early in case they need + * to send stuff around or communicate with user space. */ struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev, const char *pipe_name, @@ -115,7 +123,7 @@ struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev, gfp_t gfp_flags) { int result; - struct device *dev = wimax_dev->net_dev->dev.parent; + struct device *dev = wimax_dev_to_dev(wimax_dev); size_t msg_size; void *genl_msg; struct sk_buff *skb; @@ -149,7 +157,8 @@ struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev, } result = nla_put(skb, WIMAX_GNL_MSG_DATA, size, msg); if (result < 0) { - dev_err(dev, "no memory to add payload in attribute\n"); + dev_err(dev, "no memory to add payload (msg %p size %zu) in " + "attribute: %d\n", msg, size, result); goto error_nla_put; } genlmsg_end(skb, genl_msg); @@ -160,7 +169,6 @@ error_genlmsg_put: error_new: nlmsg_free(skb); return ERR_PTR(result); - } EXPORT_SYMBOL_GPL(wimax_msg_alloc); @@ -255,22 +263,25 @@ EXPORT_SYMBOL_GPL(wimax_msg_len); * Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as * wimax_msg_send() depends on skb->data being placed at the * beginning of the user message. + * + * Unlike other WiMAX stack calls, this call can be used way early, + * even before wimax_dev_add() is called, as long as the + * wimax_dev->net_dev pointer is set to point to a proper + * net_dev. This is so that drivers can use it early in case they need + * to send stuff around or communicate with user space. */ int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb) { - int result; - struct device *dev = wimax_dev->net_dev->dev.parent; + struct device *dev = wimax_dev_to_dev(wimax_dev); void *msg = skb->data; size_t size = skb->len; might_sleep(); d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size); d_dump(2, dev, msg, size); - result = genlmsg_multicast(skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); - d_printf(1, dev, "CTX: genl multicast result %d\n", result); - if (result == -ESRCH) /* Nobody connected, ignore it */ - result = 0; /* btw, the skb is freed already */ - return result; + genlmsg_multicast(&wimax_gnl_family, skb, 0, 0, GFP_KERNEL); + d_printf(1, dev, "CTX: genl multicast done\n"); + return 0; } EXPORT_SYMBOL_GPL(wimax_msg_send); @@ -302,26 +313,14 @@ int wimax_msg(struct wimax_dev *wimax_dev, const char *pipe_name, struct sk_buff *skb; skb = wimax_msg_alloc(wimax_dev, pipe_name, buf, size, gfp_flags); - if (skb == NULL) - goto error_msg_new; - result = wimax_msg_send(wimax_dev, skb); -error_msg_new: + if (IS_ERR(skb)) + result = PTR_ERR(skb); + else + result = wimax_msg_send(wimax_dev, skb); return result; } EXPORT_SYMBOL_GPL(wimax_msg); - -static const -struct nla_policy wimax_gnl_msg_policy[WIMAX_GNL_ATTR_MAX + 1] = { - [WIMAX_GNL_MSG_IFIDX] = { - .type = NLA_U32, - }, - [WIMAX_GNL_MSG_DATA] = { - .type = NLA_UNSPEC, /* libnl doesn't grok BINARY yet */ - }, -}; - - /* * Relays a message from user space to the driver * @@ -330,7 +329,6 @@ struct nla_policy wimax_gnl_msg_policy[WIMAX_GNL_ATTR_MAX + 1] = { * * This call will block while handling/relaying the message. */ -static int wimax_gnl_doit_msg_from_user(struct sk_buff *skb, struct genl_info *info) { int result, ifindex; @@ -379,6 +377,8 @@ int wimax_gnl_doit_msg_from_user(struct sk_buff *skb, struct genl_info *info) } mutex_lock(&wimax_dev->mutex); result = wimax_dev_is_ready(wimax_dev); + if (result == -ENOMEDIUM) + result = 0; if (result < 0) goto error_not_ready; result = -ENOSYS; @@ -406,16 +406,3 @@ error_no_wimax_dev: return result; } - -/* - * Generic Netlink glue - */ - -struct genl_ops wimax_gnl_msg_from_user = { - .cmd = WIMAX_GNL_OP_MSG_FROM_USER, - .flags = GENL_ADMIN_PERM, - .policy = wimax_gnl_msg_policy, - .doit = wimax_gnl_doit_msg_from_user, - .dumpit = NULL, -}; - |
