diff options
Diffstat (limited to 'drivers/net/ieee802154/atusb.c')
-rw-r--r-- | drivers/net/ieee802154/atusb.c | 225 |
1 files changed, 70 insertions, 155 deletions
diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index 23ee0b14cbfa..2c338783893d 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -74,79 +74,6 @@ struct atusb_chip_data { 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 < 0) { - 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) { @@ -156,7 +83,10 @@ static int atusb_write_subreg(struct atusb *atusb, u8 reg, u8 mask, 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. @@ -165,7 +95,8 @@ static int atusb_write_subreg(struct atusb *atusb, u8 reg, u8 mask, 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; } @@ -174,12 +105,16 @@ static int atusb_read_subreg(struct atusb *lp, unsigned int addr, unsigned int mask, unsigned int shift) { - int rc; + int reg, ret; - rc = atusb_read_reg(lp, addr); - rc = (rc & mask) >> shift; + 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; - return rc; + reg = (reg & mask) >> shift; + + return reg; } static int atusb_get_and_clear_error(struct atusb *atusb) @@ -271,9 +206,7 @@ static void atusb_tx_done(struct atusb *atusb, u8 seq) * unlikely case now that seq == expect is then true, but can * happen and fail with a tx_skb = NULL; */ - ieee802154_wake_queue(atusb->hw); - if (atusb->tx_skb) - dev_kfree_skb_irq(atusb->tx_skb); + ieee802154_xmit_hw_error(atusb->hw, atusb->tx_skb); } } @@ -417,16 +350,22 @@ static int atusb_set_hw_addr_filt(struct ieee802154_hw *hw, 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) { @@ -435,7 +374,9 @@ static int atusb_set_hw_addr_filt(struct ieee802154_hw *hw, 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) { @@ -457,7 +398,8 @@ static int atusb_start(struct ieee802154_hw *hw) 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); @@ -471,7 +413,8 @@ static void atusb_stop(struct ieee802154_hw *hw) 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); } @@ -578,9 +521,11 @@ atusb_set_cca_mode(struct ieee802154_hw *hw, const struct wpan_phy_cca *cca) 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: @@ -667,36 +612,6 @@ static int hulusb_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel) if (rc < 0) return rc; - /* This sets the symbol_duration according frequency on the 212. - * TODO move this handling while set channel and page in cfg802154. - * We can do that, this timings are according 802.15.4 standard. - * If we do that in cfg802154, this is a more generic calculation. - * - * This should also protected from ifs_timer. Means cancel timer and - * init with a new value. For now, this is okay. - */ - if (channel == 0) { - if (page == 0) { - /* SUB:0 and BPSK:0 -> BPSK-20 */ - lp->hw->phy->symbol_duration = 50; - } else { - /* SUB:1 and BPSK:0 -> BPSK-40 */ - lp->hw->phy->symbol_duration = 25; - } - } else { - if (page == 0) - /* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */ - lp->hw->phy->symbol_duration = 40; - else - /* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */ - lp->hw->phy->symbol_duration = 16; - } - - lp->hw->phy->lifs_period = IEEE802154_LIFS_PERIOD * - lp->hw->phy->symbol_duration; - lp->hw->phy->sifs_period = IEEE802154_SIFS_PERIOD * - lp->hw->phy->symbol_duration; - return atusb_write_subreg(lp, SR_CHANNEL, channel); } @@ -797,18 +712,13 @@ static int atusb_get_and_show_revision(struct atusb *atusb) { 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]; @@ -847,7 +757,6 @@ static int atusb_get_and_show_revision(struct atusb *atusb) dev_info(&usb_dev->dev, "Please update to version 0.2 or newer"); } - kfree(buffer); return ret; } @@ -861,9 +770,8 @@ static int atusb_get_and_show_build(struct atusb *atusb) if (!build) return -ENOMEM; - ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0), - ATUSB_BUILD, ATUSB_REQ_FROM_DEV, 0, 0, - build, ATUSB_BUILD_SIZE, 1000); + 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) { build[ret] = 0; dev_info(&usb_dev->dev, "Firmware: build %s\n", build); @@ -879,14 +787,27 @@ static int atusb_get_and_conf_chip(struct atusb *atusb) 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; @@ -916,7 +837,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb) chip = "AT86RF230"; atusb->hw->phy->supported.channels[0] = 0x7FFF800; atusb->hw->phy->current_channel = 11; /* reset default */ - atusb->hw->phy->symbol_duration = 16; atusb->hw->phy->supported.tx_powers = atusb_powers; atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers); hw->phy->supported.cca_ed_levels = atusb_ed_levels; @@ -926,7 +846,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb) chip = "AT86RF231"; atusb->hw->phy->supported.channels[0] = 0x7FFF800; atusb->hw->phy->current_channel = 11; /* reset default */ - atusb->hw->phy->symbol_duration = 16; atusb->hw->phy->supported.tx_powers = atusb_powers; atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers); hw->phy->supported.cca_ed_levels = atusb_ed_levels; @@ -938,7 +857,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb) atusb->hw->phy->supported.channels[0] = 0x00007FF; atusb->hw->phy->supported.channels[2] = 0x00007FF; atusb->hw->phy->current_channel = 5; - atusb->hw->phy->symbol_duration = 25; atusb->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH; atusb->hw->phy->supported.tx_powers = at86rf212_powers; atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers); @@ -967,7 +885,7 @@ fail: 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; @@ -980,18 +898,12 @@ static int atusb_set_extended_addr(struct atusb *atusb) 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; } @@ -1007,7 +919,6 @@ static int atusb_set_extended_addr(struct atusb *atusb) &addr); } - kfree(buffer); return ret; } @@ -1049,7 +960,8 @@ static int atusb_probe(struct usb_interface *interface, 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); @@ -1074,7 +986,9 @@ static int atusb_probe(struct usb_interface *interface, * 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 @@ -1102,7 +1016,8 @@ static int atusb_probe(struct usb_interface *interface, 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) |