/* * WiMAX stack operation: relay a message from user space * * @wimax_dev: device descriptor * @pipe_name: named pipe the message is for * @msg_buf: pointer to the message bytes * @msg_len: length of the buffer * @genl_info: passed by the generic netlink layer * * The WiMAX stack will call this function when a message was received * from user space. * * For the i2400m, this is an L3L4 message, as specified in * include/linux/wimax/i2400m.h, and thus prefixed with a 'struct * i2400m_l3l4_hdr'. Driver (and device) expect the messages to be * coded in Little Endian. * * This function just verifies that the header declaration and the * payload are consistent and then deals with it, either forwarding it * to the device or procesing it locally. * * In the i2400m, messages are basically commands that will carry an * ack, so we use i2400m_msg_to_dev() and then deliver the ack back to * user space. The rx.c code might intercept the response and use it * to update the driver's state, but then it will pass it on so it can * be relayed back to user space. * * Note that asynchronous events from the device are processed and * sent to user space in rx.c. */ static int i2400m_op_msg_from_user(struct wimax_dev *wimax_dev, const char *pipe_name, const void *msg_buf, size_t msg_len, const struct genl_info *genl_info) { int result; struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev); struct device *dev = i2400m_dev(i2400m); struct sk_buff *ack_skb; d_fnstart(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p " "msg_len %zu genl_info %p)\n", wimax_dev, i2400m, msg_buf, msg_len, genl_info); ack_skb = i2400m_msg_to_dev(i2400m, msg_buf, msg_len); result = PTR_ERR(ack_skb); if (IS_ERR(ack_skb)) goto error_msg_to_dev; result = wimax_msg_send(&i2400m->wimax_dev, ack_skb); error_msg_to_dev: d_fnend(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p msg_len %zu " "genl_info %p) = %d\n", wimax_dev, i2400m, msg_buf, msg_len, genl_info, result); return result; }
int wimax_msg(struct wimax_dev *wimax_dev, const char *pipe_name, const void *buf, size_t size, gfp_t gfp_flags) { int result = -ENOMEM; struct sk_buff *skb; skb = wimax_msg_alloc(wimax_dev, pipe_name, buf, size, gfp_flags); if (IS_ERR(skb)) result = PTR_ERR(skb); else result = wimax_msg_send(wimax_dev, skb); return result; }