mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 22:21:42 +00:00
Merge tag 'ieee802154-for-davem-2022-02-10' of git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan-next
Stefan Schmidt says: ==================== pull-request: ieee802154-next 2022-02-10 An update from ieee802154 for your *net-next* tree. There is more ongoing in ieee802154 than usual. This will be the first pull request for this cycle, but I expect one more. Depending on review and rework times. Pavel Skripkin ported the atusb driver over to the new USB api to avoid unint problems as well as making use of the modern api without kmalloc() needs in he driver. Miquel Raynal landed some changes to ensure proper frame checksum checking with hwsim, documenting our use of wake and stop_queue and eliding a magic value by using the proper define. David Girault documented the address struct used in ieee802154. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
9557167bc6
@ -74,81 +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 < 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)
|
||||
{
|
||||
@ -158,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.
|
||||
@ -167,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;
|
||||
}
|
||||
@ -176,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)
|
||||
@ -419,16 +352,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) {
|
||||
@ -437,7 +376,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) {
|
||||
@ -459,7 +400,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);
|
||||
@ -473,7 +415,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);
|
||||
}
|
||||
|
||||
@ -580,9 +523,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:
|
||||
@ -799,18 +744,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];
|
||||
@ -849,7 +789,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;
|
||||
}
|
||||
|
||||
@ -863,7 +802,6 @@ static int atusb_get_and_show_build(struct atusb *atusb)
|
||||
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) {
|
||||
@ -881,14 +819,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;
|
||||
@ -969,7 +920,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;
|
||||
@ -982,18 +933,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;
|
||||
}
|
||||
|
||||
@ -1009,7 +954,6 @@ static int atusb_set_extended_addr(struct atusb *atusb)
|
||||
&addr);
|
||||
}
|
||||
|
||||
kfree(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1051,7 +995,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);
|
||||
@ -1076,7 +1021,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
|
||||
@ -1104,7 +1051,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)
|
||||
|
@ -791,7 +791,7 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
|
||||
phy->idx = idx;
|
||||
INIT_LIST_HEAD(&phy->edges);
|
||||
|
||||
hw->flags = IEEE802154_HW_PROMISCUOUS;
|
||||
hw->flags = IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_RX_DROP_BAD_CKSUM;
|
||||
hw->parent = dev;
|
||||
|
||||
err = ieee802154_register_hw(hw);
|
||||
|
@ -227,6 +227,16 @@ static inline void wpan_phy_net_set(struct wpan_phy *wpan_phy, struct net *net)
|
||||
write_pnet(&wpan_phy->_net, net);
|
||||
}
|
||||
|
||||
/**
|
||||
* struct ieee802154_addr - IEEE802.15.4 device address
|
||||
* @mode: Address mode from frame header. Can be one of:
|
||||
* - @IEEE802154_ADDR_NONE
|
||||
* - @IEEE802154_ADDR_SHORT
|
||||
* - @IEEE802154_ADDR_LONG
|
||||
* @pan_id: The PAN ID this address belongs to
|
||||
* @short_addr: address if @mode is @IEEE802154_ADDR_SHORT
|
||||
* @extended_addr: address if @mode is @IEEE802154_ADDR_LONG
|
||||
*/
|
||||
struct ieee802154_addr {
|
||||
u8 mode;
|
||||
__le16 pan_id;
|
||||
|
@ -464,6 +464,12 @@ void ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb,
|
||||
* ieee802154_wake_queue - wake ieee802154 queue
|
||||
* @hw: pointer as obtained from ieee802154_alloc_hw().
|
||||
*
|
||||
* Tranceivers usually have either one transmit framebuffer or one framebuffer
|
||||
* for both transmitting and receiving. Hence, the core currently only handles
|
||||
* one frame at a time for each phy, which means we had to stop the queue to
|
||||
* avoid new skb to come during the transmission. The queue then needs to be
|
||||
* woken up after the operation.
|
||||
*
|
||||
* Drivers should use this function instead of netif_wake_queue.
|
||||
*/
|
||||
void ieee802154_wake_queue(struct ieee802154_hw *hw);
|
||||
@ -472,6 +478,12 @@ void ieee802154_wake_queue(struct ieee802154_hw *hw);
|
||||
* ieee802154_stop_queue - stop ieee802154 queue
|
||||
* @hw: pointer as obtained from ieee802154_alloc_hw().
|
||||
*
|
||||
* Tranceivers usually have either one transmit framebuffer or one framebuffer
|
||||
* for both transmitting and receiving. Hence, the core currently only handles
|
||||
* one frame at a time for each phy, which means we need to tell upper layers to
|
||||
* stop giving us new skbs while we are busy with the transmitted one. The queue
|
||||
* must then be stopped before transmitting.
|
||||
*
|
||||
* Drivers should use this function instead of netif_stop_queue.
|
||||
*/
|
||||
void ieee802154_stop_queue(struct ieee802154_hw *hw);
|
||||
|
@ -30,7 +30,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
|
||||
{
|
||||
void *hdr;
|
||||
int i, pages = 0;
|
||||
uint32_t *buf = kcalloc(32, sizeof(uint32_t), GFP_KERNEL);
|
||||
u32 *buf = kcalloc(IEEE802154_MAX_PAGE + 1, sizeof(u32), GFP_KERNEL);
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
@ -47,7 +47,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
|
||||
nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) ||
|
||||
nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel))
|
||||
goto nla_put_failure;
|
||||
for (i = 0; i < 32; i++) {
|
||||
for (i = 0; i <= IEEE802154_MAX_PAGE; i++) {
|
||||
if (phy->supported.channels[i])
|
||||
buf[pages++] = phy->supported.channels[i] | (i << 27);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user