int (*set_txpower)(struct ieee802154_hw*, s32);
 };
 
-/* ----- USB commands without data ----------------------------------------- */
-
-/* To reduce the number of error checks in the code, we record the first error
- * in atusb->err and reject all subsequent requests until the error is cleared.
- */
-
-static int atusb_control_msg(struct atusb *atusb, unsigned int pipe,
-                            __u8 request, __u8 requesttype,
-                            __u16 value, __u16 index,
-                            void *data, __u16 size, int timeout)
-{
-       struct usb_device *usb_dev = atusb->usb_dev;
-       int ret;
-
-       if (atusb->err)
-               return atusb->err;
-
-       ret = usb_control_msg(usb_dev, pipe, request, requesttype,
-                             value, index, data, size, timeout);
-       if (ret < size) {
-               ret = ret < 0 ? ret : -ENODATA;
-
-               atusb->err = ret;
-               dev_err(&usb_dev->dev,
-                       "%s: req 0x%02x val 0x%x idx 0x%x, error %d\n",
-                       __func__, request, value, index, ret);
-       }
-       return ret;
-}
-
-static int atusb_command(struct atusb *atusb, u8 cmd, u8 arg)
-{
-       struct usb_device *usb_dev = atusb->usb_dev;
-
-       dev_dbg(&usb_dev->dev, "%s: cmd = 0x%x\n", __func__, cmd);
-       return atusb_control_msg(atusb, usb_sndctrlpipe(usb_dev, 0),
-                                cmd, ATUSB_REQ_TO_DEV, arg, 0, NULL, 0, 1000);
-}
-
-static int atusb_write_reg(struct atusb *atusb, u8 reg, u8 value)
-{
-       struct usb_device *usb_dev = atusb->usb_dev;
-
-       dev_dbg(&usb_dev->dev, "%s: 0x%02x <- 0x%02x\n", __func__, reg, value);
-       return atusb_control_msg(atusb, usb_sndctrlpipe(usb_dev, 0),
-                                ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
-                                value, reg, NULL, 0, 1000);
-}
-
-static int atusb_read_reg(struct atusb *atusb, u8 reg)
-{
-       struct usb_device *usb_dev = atusb->usb_dev;
-       int ret;
-       u8 *buffer;
-       u8 value;
-
-       buffer = kmalloc(1, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
-       dev_dbg(&usb_dev->dev, "%s: reg = 0x%x\n", __func__, reg);
-       ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0),
-                               ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
-                               0, reg, buffer, 1, 1000);
-
-       if (ret >= 0) {
-               value = buffer[0];
-               kfree(buffer);
-               return value;
-       } else {
-               kfree(buffer);
-               return ret;
-       }
-}
-
 static int atusb_write_subreg(struct atusb *atusb, u8 reg, u8 mask,
                              u8 shift, u8 value)
 {
 
        dev_dbg(&usb_dev->dev, "%s: 0x%02x <- 0x%02x\n", __func__, reg, value);
 
-       orig = atusb_read_reg(atusb, reg);
+       ret = usb_control_msg_recv(usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
+                                  0, reg, &orig, 1, 1000, GFP_KERNEL);
+       if (ret < 0)
+               return ret;
 
        /* Write the value only into that part of the register which is allowed
         * by the mask. All other bits stay as before.
        tmp |= (value << shift) & mask;
 
        if (tmp != orig)
-               ret = atusb_write_reg(atusb, reg, tmp);
+               ret = usb_control_msg_send(usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
+                                          tmp, reg, NULL, 0, 1000, GFP_KERNEL);
 
        return ret;
 }
                             unsigned int addr, unsigned int mask,
                             unsigned int shift)
 {
-       int rc;
+       int reg, ret;
+
+       ret = usb_control_msg_recv(lp->usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
+                                  0, addr, ®, 1, 1000, GFP_KERNEL);
+       if (ret < 0)
+               return ret;
 
-       rc = atusb_read_reg(lp, addr);
-       rc = (rc & mask) >> shift;
+       reg = (reg & mask) >> shift;
 
-       return rc;
+       return reg;
 }
 
 static int atusb_get_and_clear_error(struct atusb *atusb)
                u16 addr = le16_to_cpu(filt->short_addr);
 
                dev_vdbg(dev, "%s called for saddr\n", __func__);
-               atusb_write_reg(atusb, RG_SHORT_ADDR_0, addr);
-               atusb_write_reg(atusb, RG_SHORT_ADDR_1, addr >> 8);
+               usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
+                                    addr, RG_SHORT_ADDR_0, NULL, 0, 1000, GFP_KERNEL);
+
+               usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
+                                    addr >> 8, RG_SHORT_ADDR_1, NULL, 0, 1000, GFP_KERNEL);
        }
 
        if (changed & IEEE802154_AFILT_PANID_CHANGED) {
                u16 pan = le16_to_cpu(filt->pan_id);
 
                dev_vdbg(dev, "%s called for pan id\n", __func__);
-               atusb_write_reg(atusb, RG_PAN_ID_0, pan);
-               atusb_write_reg(atusb, RG_PAN_ID_1, pan >> 8);
+               usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
+                                    pan, RG_PAN_ID_0, NULL, 0, 1000, GFP_KERNEL);
+
+               usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
+                                    pan >> 8, RG_PAN_ID_1, NULL, 0, 1000, GFP_KERNEL);
        }
 
        if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
                memcpy(addr, &filt->ieee_addr, IEEE802154_EXTENDED_ADDR_LEN);
                dev_vdbg(dev, "%s called for IEEE addr\n", __func__);
                for (i = 0; i < 8; i++)
-                       atusb_write_reg(atusb, RG_IEEE_ADDR_0 + i, addr[i]);
+                       usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
+                                            addr[i], RG_IEEE_ADDR_0 + i, NULL, 0,
+                                            1000, GFP_KERNEL);
        }
 
        if (changed & IEEE802154_AFILT_PANC_CHANGED) {
 
        dev_dbg(&usb_dev->dev, "%s\n", __func__);
        schedule_delayed_work(&atusb->work, 0);
-       atusb_command(atusb, ATUSB_RX_MODE, 1);
+       usb_control_msg_send(atusb->usb_dev, 0, ATUSB_RX_MODE, ATUSB_REQ_TO_DEV, 1, 0,
+                            NULL, 0, 1000, GFP_KERNEL);
        ret = atusb_get_and_clear_error(atusb);
        if (ret < 0)
                usb_kill_anchored_urbs(&atusb->idle_urbs);
 
        dev_dbg(&usb_dev->dev, "%s\n", __func__);
        usb_kill_anchored_urbs(&atusb->idle_urbs);
-       atusb_command(atusb, ATUSB_RX_MODE, 0);
+       usb_control_msg_send(atusb->usb_dev, 0, ATUSB_RX_MODE, ATUSB_REQ_TO_DEV, 0, 0,
+                            NULL, 0, 1000, GFP_KERNEL);
        atusb_get_and_clear_error(atusb);
 }
 
 
 static int hulusb_set_cca_ed_level(struct atusb *lp, int rssi_base_val)
 {
-       unsigned int cca_ed_thres;
+       int cca_ed_thres;
 
        cca_ed_thres = atusb_read_subreg(lp, SR_CCA_ED_THRES);
+       if (cca_ed_thres < 0)
+               return cca_ed_thres;
 
        switch (rssi_base_val) {
        case -98:
 {
        struct usb_device *usb_dev = atusb->usb_dev;
        char *hw_name;
-       unsigned char *buffer;
+       unsigned char buffer[3];
        int ret;
 
-       buffer = kmalloc(3, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
        /* Get a couple of the ATMega Firmware values */
-       ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0),
-                               ATUSB_ID, ATUSB_REQ_FROM_DEV, 0, 0,
-                               buffer, 3, 1000);
-       if (ret >= 0) {
+       ret = usb_control_msg_recv(atusb->usb_dev, 0, ATUSB_ID, ATUSB_REQ_FROM_DEV, 0, 0,
+                                  buffer, 3, 1000, GFP_KERNEL);
+       if (!ret) {
                atusb->fw_ver_maj = buffer[0];
                atusb->fw_ver_min = buffer[1];
                atusb->fw_hw_type = buffer[2];
                dev_info(&usb_dev->dev, "Please update to version 0.2 or newer");
        }
 
-       kfree(buffer);
        return ret;
 }
 
        if (!build)
                return -ENOMEM;
 
-       /* We cannot call atusb_control_msg() here, since this request may read various length data */
        ret = usb_control_msg(atusb->usb_dev, usb_rcvctrlpipe(usb_dev, 0), ATUSB_BUILD,
                              ATUSB_REQ_FROM_DEV, 0, 0, build, ATUSB_BUILD_SIZE, 1000);
        if (ret >= 0) {
        u8 man_id_0, man_id_1, part_num, version_num;
        const char *chip;
        struct ieee802154_hw *hw = atusb->hw;
+       int ret;
 
-       man_id_0 = atusb_read_reg(atusb, RG_MAN_ID_0);
-       man_id_1 = atusb_read_reg(atusb, RG_MAN_ID_1);
-       part_num = atusb_read_reg(atusb, RG_PART_NUM);
-       version_num = atusb_read_reg(atusb, RG_VERSION_NUM);
+       ret = usb_control_msg_recv(usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
+                                  0, RG_MAN_ID_0, &man_id_0, 1, 1000, GFP_KERNEL);
+       if (ret < 0)
+               return ret;
 
-       if (atusb->err)
-               return atusb->err;
+       ret = usb_control_msg_recv(usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
+                                  0, RG_MAN_ID_1, &man_id_1, 1, 1000, GFP_KERNEL);
+       if (ret < 0)
+               return ret;
+
+       ret = usb_control_msg_recv(usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
+                                  0, RG_PART_NUM, &part_num, 1, 1000, GFP_KERNEL);
+       if (ret < 0)
+               return ret;
+
+       ret = usb_control_msg_recv(usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
+                                  0, RG_VERSION_NUM, &version_num, 1, 1000, GFP_KERNEL);
+       if (ret < 0)
+               return ret;
 
        hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
                    IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_CSMA_PARAMS;
 static int atusb_set_extended_addr(struct atusb *atusb)
 {
        struct usb_device *usb_dev = atusb->usb_dev;
-       unsigned char *buffer;
+       unsigned char buffer[IEEE802154_EXTENDED_ADDR_LEN];
        __le64 extended_addr;
        u64 addr;
        int ret;
                return 0;
        }
 
-       buffer = kmalloc(IEEE802154_EXTENDED_ADDR_LEN, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
        /* Firmware is new enough so we fetch the address from EEPROM */
-       ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0),
-                               ATUSB_EUI64_READ, ATUSB_REQ_FROM_DEV, 0, 0,
-                               buffer, IEEE802154_EXTENDED_ADDR_LEN, 1000);
+       ret = usb_control_msg_recv(atusb->usb_dev, 0, ATUSB_EUI64_READ, ATUSB_REQ_FROM_DEV, 0, 0,
+                                  buffer, IEEE802154_EXTENDED_ADDR_LEN, 1000, GFP_KERNEL);
        if (ret < 0) {
                dev_err(&usb_dev->dev, "failed to fetch extended address, random address set\n");
                ieee802154_random_extended_addr(&atusb->hw->phy->perm_extended_addr);
-               kfree(buffer);
                return ret;
        }
 
                         &addr);
        }
 
-       kfree(buffer);
        return ret;
 }
 
 
        hw->parent = &usb_dev->dev;
 
-       atusb_command(atusb, ATUSB_RF_RESET, 0);
+       usb_control_msg_send(atusb->usb_dev, 0, ATUSB_RF_RESET, ATUSB_REQ_TO_DEV, 0, 0,
+                            NULL, 0, 1000, GFP_KERNEL);
        atusb_get_and_conf_chip(atusb);
        atusb_get_and_show_revision(atusb);
        atusb_get_and_show_build(atusb);
         * explicitly. Any resets after that will send us straight to TRX_OFF,
         * making the command below redundant.
         */
-       atusb_write_reg(atusb, RG_TRX_STATE, STATE_FORCE_TRX_OFF);
+       usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
+                            STATE_FORCE_TRX_OFF, RG_TRX_STATE, NULL, 0, 1000, GFP_KERNEL);
+
        msleep(1);      /* reset => TRX_OFF, tTR13 = 37 us */
 
 #if 0
 
        atusb_write_subreg(atusb, SR_RX_SAFE_MODE, 1);
 #endif
-       atusb_write_reg(atusb, RG_IRQ_MASK, 0xff);
+       usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
+                            0xff, RG_IRQ_MASK, NULL, 0, 1000, GFP_KERNEL);
 
        ret = atusb_get_and_clear_error(atusb);
        if (!ret)