};
 
 struct mt76_mcu_ops {
-       struct sk_buff *(*mcu_msg_alloc)(const void *data, int len);
-       int (*mcu_send_msg)(struct mt76_dev *dev, struct sk_buff *skb,
-                           int cmd, bool wait_resp);
+       int (*mcu_send_msg)(struct mt76_dev *dev, int cmd, const void *data,
+                           int len, bool wait_resp);
        int (*mcu_wr_rp)(struct mt76_dev *dev, u32 base,
                         const struct mt76_reg_pair *rp, int len);
        int (*mcu_rd_rp)(struct mt76_dev *dev, u32 base,
 #define mt76_wr_rp(dev, ...)   (dev)->mt76.bus->wr_rp(&((dev)->mt76), __VA_ARGS__)
 #define mt76_rd_rp(dev, ...)   (dev)->mt76.bus->rd_rp(&((dev)->mt76), __VA_ARGS__)
 
-#define mt76_mcu_msg_alloc(dev, ...)   (dev)->mt76.mcu_ops->mcu_msg_alloc(__VA_ARGS__)
 #define mt76_mcu_send_msg(dev, ...)    (dev)->mt76.mcu_ops->mcu_send_msg(&((dev)->mt76), __VA_ARGS__)
 
 #define mt76_set(dev, offset, val)     mt76_rmw(dev, offset, 0, val)
 
 int mt76x0e_mcu_init(struct mt76x02_dev *dev)
 {
        static const struct mt76_mcu_ops mt76x0e_mcu_ops = {
-               .mcu_msg_alloc = mt76x02_mcu_msg_alloc,
                .mcu_send_msg = mt76x02_mcu_msg_send,
        };
        int err;
 
 
 #include "mt76x02_mcu.h"
 
-struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len)
+static struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len)
 {
        struct sk_buff *skb;
 
 
        return skb;
 }
-EXPORT_SYMBOL_GPL(mt76x02_mcu_msg_alloc);
 
 static struct sk_buff *
 mt76x02_mcu_get_response(struct mt76x02_dev *dev, unsigned long expires)
        return 0;
 }
 
-int mt76x02_mcu_msg_send(struct mt76_dev *mdev, struct sk_buff *skb,
-                        int cmd, bool wait_resp)
+int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
+                        int len, bool wait_resp)
 {
        struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
        unsigned long expires = jiffies + HZ;
+       struct sk_buff *skb;
        int ret;
        u8 seq;
 
+       skb = mt76x02_mcu_msg_alloc(data, len);
        if (!skb)
-               return -EINVAL;
+               return -ENOMEM;
 
        mutex_lock(&mdev->mmio.mcu.mutex);
 
                                enum mcu_function func,
                                u32 val, bool wait_resp)
 {
-       struct sk_buff *skb;
        struct {
            __le32 id;
            __le32 value;
            .value = cpu_to_le32(val),
        };
 
-       skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg));
-       return mt76_mcu_send_msg(dev, skb, CMD_FUN_SET_OP, wait_resp);
+       return mt76_mcu_send_msg(dev, CMD_FUN_SET_OP, &msg, sizeof(msg),
+                                wait_resp);
 }
 EXPORT_SYMBOL_GPL(mt76x02_mcu_function_select);
 
 int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on,
                                bool wait_resp)
 {
-       struct sk_buff *skb;
        struct {
                __le32 mode;
                __le32 level;
                .level = cpu_to_le32(0),
        };
 
-       skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg));
-       return mt76_mcu_send_msg(dev, skb, CMD_POWER_SAVING_OP, wait_resp);
+       return mt76_mcu_send_msg(dev, CMD_POWER_SAVING_OP, &msg, sizeof(msg),
+                                wait_resp);
 }
 EXPORT_SYMBOL_GPL(mt76x02_mcu_set_radio_state);
 
 int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type,
                          u32 param, bool wait)
 {
-       struct sk_buff *skb;
        struct {
                __le32 id;
                __le32 value;
        if (wait)
                mt76_rmw(dev, MT_MCU_COM_REG0, BIT(31), 0);
 
-       skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg));
-       ret = mt76_mcu_send_msg(dev, skb, CMD_CALIBRATION_OP, true);
+       ret = mt76_mcu_send_msg(dev, CMD_CALIBRATION_OP, &msg, sizeof(msg),
+                               true);
        if (ret)
                return ret;
 
 
 int mt76x02_mcu_cleanup(struct mt76x02_dev *dev);
 int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type,
                          u32 param, bool wait);
-struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len);
-int mt76x02_mcu_msg_send(struct mt76_dev *mdev, struct sk_buff *skb,
-                        int cmd, bool wait_resp);
+int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
+                        int len, bool wait_resp);
 int mt76x02_mcu_function_select(struct mt76x02_dev *dev,
                                enum mcu_function func,
                                u32 val, bool wait_resp);
 
        u8 seq = 0;
        u32 info;
 
-       if (!skb)
-               return -EINVAL;
-
        if (test_bit(MT76_REMOVED, &dev->state))
                return 0;
 
 }
 
 static int
-mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb,
-                     int cmd, bool wait_resp)
+mt76x02u_mcu_send_msg(struct mt76_dev *dev, int cmd, const void *data,
+                     int len, bool wait_resp)
 {
        struct mt76_usb *usb = &dev->usb;
+       struct sk_buff *skb;
        int err;
 
+       skb = mt76x02u_mcu_msg_alloc(data, len);
+       if (!skb)
+               return -ENOMEM;
+
        mutex_lock(&usb->mcu.mutex);
        err = __mt76x02u_mcu_send_msg(dev, skb, cmd, wait_resp);
        mutex_unlock(&usb->mcu.mutex);
 {
        const int CMD_RANDOM_WRITE = 12;
        const int max_vals_per_cmd = MT_INBAND_PACKET_MAX_LEN / 8;
+       struct mt76_usb *usb = &dev->usb;
        struct sk_buff *skb;
        int cnt, i, ret;
 
                skb_put_le32(skb, data[i].value);
        }
 
-       ret = mt76x02u_mcu_send_msg(dev, skb, CMD_RANDOM_WRITE, cnt == n);
+       mutex_lock(&usb->mcu.mutex);
+       ret = __mt76x02u_mcu_send_msg(dev, skb, CMD_RANDOM_WRITE, cnt == n);
+       mutex_unlock(&usb->mcu.mutex);
        if (ret)
                return ret;
 
 void mt76x02u_init_mcu(struct mt76_dev *dev)
 {
        static const struct mt76_mcu_ops mt76x02u_mcu_ops = {
-               .mcu_msg_alloc = mt76x02u_mcu_msg_alloc,
                .mcu_send_msg = mt76x02u_mcu_send_msg,
                .mcu_wr_rp = mt76x02u_mcu_wr_rp,
                .mcu_rd_rp = mt76x02u_mcu_rd_rp,
 
 int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw,
                           u8 bw_index, bool scan)
 {
-       struct sk_buff *skb;
        struct {
                u8 idx;
                u8 scan;
        };
 
        /* first set the channel without the extension channel info */
-       skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg));
-       mt76_mcu_send_msg(dev, skb, CMD_SWITCH_CHANNEL_OP, true);
+       mt76_mcu_send_msg(dev, CMD_SWITCH_CHANNEL_OP, &msg, sizeof(msg), true);
 
        usleep_range(5000, 10000);
 
        msg.ext_chan = 0xe0 + bw_index;
-       skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg));
-       return mt76_mcu_send_msg(dev, skb, CMD_SWITCH_CHANNEL_OP, true);
+       return mt76_mcu_send_msg(dev, CMD_SWITCH_CHANNEL_OP, &msg, sizeof(msg),
+                                true);
 }
 EXPORT_SYMBOL_GPL(mt76x2_mcu_set_channel);
 
 int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level,
                       u8 channel)
 {
-       struct sk_buff *skb;
        struct {
                u8 cr_mode;
                u8 temp;
        msg.cfg = cpu_to_le32(val);
 
        /* first set the channel without the extension channel info */
-       skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg));
-       return mt76_mcu_send_msg(dev, skb, CMD_LOAD_CR, true);
+       return mt76_mcu_send_msg(dev, CMD_LOAD_CR, &msg, sizeof(msg), true);
 }
 EXPORT_SYMBOL_GPL(mt76x2_mcu_load_cr);
 
 int mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain,
                         bool force)
 {
-       struct sk_buff *skb;
        struct {
                __le32 channel;
                __le32 gain_val;
        if (force)
                msg.channel |= cpu_to_le32(BIT(31));
 
-       skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg));
-       return mt76_mcu_send_msg(dev, skb, CMD_INIT_GAIN_OP, true);
+       return mt76_mcu_send_msg(dev, CMD_INIT_GAIN_OP, &msg, sizeof(msg),
+                                true);
 }
 EXPORT_SYMBOL_GPL(mt76x2_mcu_init_gain);
 
 int mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev,
                         struct mt76x2_tssi_comp *tssi_data)
 {
-       struct sk_buff *skb;
        struct {
                __le32 id;
                struct mt76x2_tssi_comp data;
                .data = *tssi_data,
        };
 
-       skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg));
-       return mt76_mcu_send_msg(dev, skb, CMD_CALIBRATION_OP, true);
+       return mt76_mcu_send_msg(dev, CMD_CALIBRATION_OP, &msg, sizeof(msg),
+                                true);
 }
 EXPORT_SYMBOL_GPL(mt76x2_mcu_tssi_comp);
 
 int mt76x2_mcu_init(struct mt76x02_dev *dev)
 {
        static const struct mt76_mcu_ops mt76x2_mcu_ops = {
-               .mcu_msg_alloc = mt76x02_mcu_msg_alloc,
                .mcu_send_msg = mt76x02_mcu_msg_send,
        };
        int ret;