Commit c5f50500 authored by Jakub Kicinski's avatar Jakub Kicinski

Stefan Schmidt says:

====================
pull-request: ieee802154-next 2022-05-01

Miquel Raynal landed two patch series bundled in this pull request.

The first series re-works the symbol duration handling to better
accommodate the needs of the various phy layers in ieee802154.

In the second series Miquel improves th errors handling from drivers
up mac802154. THis streamlines the error handling throughout the
ieee/mac802154 stack in preparation for sync TX to be introduced for
MLME frames.
====================

Link: https://lore.kernel.org/r/20220501194614.1198325-1-stefan@datenfreihafen.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 0decb97c 1229df4b
...@@ -33,13 +33,6 @@ config IEEE802154_AT86RF230 ...@@ -33,13 +33,6 @@ config IEEE802154_AT86RF230
This driver can also be built as a module. To do so, say M here. This driver can also be built as a module. To do so, say M here.
the module will be called 'at86rf230'. the module will be called 'at86rf230'.
config IEEE802154_AT86RF230_DEBUGFS
depends on IEEE802154_AT86RF230
bool "AT86RF230 debugfs interface"
depends on DEBUG_FS
help
This option compiles debugfs code for the at86rf230 driver.
config IEEE802154_MRF24J40 config IEEE802154_MRF24J40
tristate "Microchip MRF24J40 transceiver driver" tristate "Microchip MRF24J40 transceiver driver"
depends on IEEE802154_DRIVERS && MAC802154 depends on IEEE802154_DRIVERS && MAC802154
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/ieee802154.h> #include <linux/ieee802154.h>
#include <linux/debugfs.h>
#include <net/mac802154.h> #include <net/mac802154.h>
#include <net/cfg802154.h> #include <net/cfg802154.h>
...@@ -72,19 +71,11 @@ struct at86rf230_state_change { ...@@ -72,19 +71,11 @@ struct at86rf230_state_change {
void (*complete)(void *context); void (*complete)(void *context);
u8 from_state; u8 from_state;
u8 to_state; u8 to_state;
int trac;
bool free; bool free;
}; };
struct at86rf230_trac {
u64 success;
u64 success_data_pending;
u64 success_wait_for_ack;
u64 channel_access_failure;
u64 no_ack;
u64 invalid;
};
struct at86rf230_local { struct at86rf230_local {
struct spi_device *spi; struct spi_device *spi;
...@@ -104,8 +95,6 @@ struct at86rf230_local { ...@@ -104,8 +95,6 @@ struct at86rf230_local {
u8 tx_retry; u8 tx_retry;
struct sk_buff *tx_skb; struct sk_buff *tx_skb;
struct at86rf230_state_change tx; struct at86rf230_state_change tx;
struct at86rf230_trac trac;
}; };
#define AT86RF2XX_NUMREGS 0x3F #define AT86RF2XX_NUMREGS 0x3F
...@@ -346,8 +335,7 @@ at86rf230_async_error_recover_complete(void *context) ...@@ -346,8 +335,7 @@ at86rf230_async_error_recover_complete(void *context)
if (lp->was_tx) { if (lp->was_tx) {
lp->was_tx = 0; lp->was_tx = 0;
dev_kfree_skb_any(lp->tx_skb); ieee802154_xmit_hw_error(lp->hw, lp->tx_skb);
ieee802154_wake_queue(lp->hw);
} }
} }
...@@ -653,7 +641,11 @@ at86rf230_tx_complete(void *context) ...@@ -653,7 +641,11 @@ at86rf230_tx_complete(void *context)
struct at86rf230_state_change *ctx = context; struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp; struct at86rf230_local *lp = ctx->lp;
ieee802154_xmit_complete(lp->hw, lp->tx_skb, false); if (ctx->trac == IEEE802154_SUCCESS)
ieee802154_xmit_complete(lp->hw, lp->tx_skb, false);
else
ieee802154_xmit_error(lp->hw, lp->tx_skb, ctx->trac);
kfree(ctx); kfree(ctx);
} }
...@@ -672,30 +664,21 @@ at86rf230_tx_trac_check(void *context) ...@@ -672,30 +664,21 @@ at86rf230_tx_trac_check(void *context)
{ {
struct at86rf230_state_change *ctx = context; struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp; struct at86rf230_local *lp = ctx->lp;
u8 trac = TRAC_MASK(ctx->buf[1]);
if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) { switch (trac) {
u8 trac = TRAC_MASK(ctx->buf[1]); case TRAC_SUCCESS:
case TRAC_SUCCESS_DATA_PENDING:
switch (trac) { ctx->trac = IEEE802154_SUCCESS;
case TRAC_SUCCESS: break;
lp->trac.success++; case TRAC_CHANNEL_ACCESS_FAILURE:
break; ctx->trac = IEEE802154_CHANNEL_ACCESS_FAILURE;
case TRAC_SUCCESS_DATA_PENDING: break;
lp->trac.success_data_pending++; case TRAC_NO_ACK:
break; ctx->trac = IEEE802154_NO_ACK;
case TRAC_CHANNEL_ACCESS_FAILURE: break;
lp->trac.channel_access_failure++; default:
break; ctx->trac = IEEE802154_SYSTEM_ERROR;
case TRAC_NO_ACK:
lp->trac.no_ack++;
break;
case TRAC_INVALID:
lp->trac.invalid++;
break;
default:
WARN_ONCE(1, "received tx trac status %d\n", trac);
break;
}
} }
at86rf230_async_state_change(lp, ctx, STATE_TX_ON, at86rf230_tx_on); at86rf230_async_state_change(lp, ctx, STATE_TX_ON, at86rf230_tx_on);
...@@ -737,25 +720,6 @@ at86rf230_rx_trac_check(void *context) ...@@ -737,25 +720,6 @@ at86rf230_rx_trac_check(void *context)
u8 *buf = ctx->buf; u8 *buf = ctx->buf;
int rc; int rc;
if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) {
u8 trac = TRAC_MASK(buf[1]);
switch (trac) {
case TRAC_SUCCESS:
lp->trac.success++;
break;
case TRAC_SUCCESS_WAIT_FOR_ACK:
lp->trac.success_wait_for_ack++;
break;
case TRAC_INVALID:
lp->trac.invalid++;
break;
default:
WARN_ONCE(1, "received rx trac status %d\n", trac);
break;
}
}
buf[0] = CMD_FB; buf[0] = CMD_FB;
ctx->trx.len = AT86RF2XX_MAX_BUF; ctx->trx.len = AT86RF2XX_MAX_BUF;
ctx->msg.complete = at86rf230_rx_read_frame_complete; ctx->msg.complete = at86rf230_rx_read_frame_complete;
...@@ -951,10 +915,6 @@ at86rf230_start(struct ieee802154_hw *hw) ...@@ -951,10 +915,6 @@ at86rf230_start(struct ieee802154_hw *hw)
{ {
struct at86rf230_local *lp = hw->priv; struct at86rf230_local *lp = hw->priv;
/* reset trac stats on start */
if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS))
memset(&lp->trac, 0, sizeof(struct at86rf230_trac));
at86rf230_awake(lp); at86rf230_awake(lp);
enable_irq(lp->spi->irq); enable_irq(lp->spi->irq);
...@@ -1064,36 +1024,6 @@ at86rf212_set_channel(struct at86rf230_local *lp, u8 page, u8 channel) ...@@ -1064,36 +1024,6 @@ at86rf212_set_channel(struct at86rf230_local *lp, u8 page, u8 channel)
if (rc < 0) if (rc < 0)
return rc; 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 at86rf230_write_subreg(lp, SR_CHANNEL, channel); return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
} }
...@@ -1569,7 +1499,6 @@ at86rf230_detect_device(struct at86rf230_local *lp) ...@@ -1569,7 +1499,6 @@ at86rf230_detect_device(struct at86rf230_local *lp)
lp->data = &at86rf231_data; lp->data = &at86rf231_data;
lp->hw->phy->supported.channels[0] = 0x7FFF800; lp->hw->phy->supported.channels[0] = 0x7FFF800;
lp->hw->phy->current_channel = 11; lp->hw->phy->current_channel = 11;
lp->hw->phy->symbol_duration = 16;
lp->hw->phy->supported.tx_powers = at86rf231_powers; lp->hw->phy->supported.tx_powers = at86rf231_powers;
lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf231_powers); lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf231_powers);
lp->hw->phy->supported.cca_ed_levels = at86rf231_ed_levels; lp->hw->phy->supported.cca_ed_levels = at86rf231_ed_levels;
...@@ -1582,7 +1511,6 @@ at86rf230_detect_device(struct at86rf230_local *lp) ...@@ -1582,7 +1511,6 @@ at86rf230_detect_device(struct at86rf230_local *lp)
lp->hw->phy->supported.channels[0] = 0x00007FF; lp->hw->phy->supported.channels[0] = 0x00007FF;
lp->hw->phy->supported.channels[2] = 0x00007FF; lp->hw->phy->supported.channels[2] = 0x00007FF;
lp->hw->phy->current_channel = 5; lp->hw->phy->current_channel = 5;
lp->hw->phy->symbol_duration = 25;
lp->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH; lp->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH;
lp->hw->phy->supported.tx_powers = at86rf212_powers; lp->hw->phy->supported.tx_powers = at86rf212_powers;
lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers); lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers);
...@@ -1594,7 +1522,6 @@ at86rf230_detect_device(struct at86rf230_local *lp) ...@@ -1594,7 +1522,6 @@ at86rf230_detect_device(struct at86rf230_local *lp)
lp->data = &at86rf233_data; lp->data = &at86rf233_data;
lp->hw->phy->supported.channels[0] = 0x7FFF800; lp->hw->phy->supported.channels[0] = 0x7FFF800;
lp->hw->phy->current_channel = 13; lp->hw->phy->current_channel = 13;
lp->hw->phy->symbol_duration = 16;
lp->hw->phy->supported.tx_powers = at86rf233_powers; lp->hw->phy->supported.tx_powers = at86rf233_powers;
lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf233_powers); lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf233_powers);
lp->hw->phy->supported.cca_ed_levels = at86rf233_ed_levels; lp->hw->phy->supported.cca_ed_levels = at86rf233_ed_levels;
...@@ -1615,47 +1542,6 @@ at86rf230_detect_device(struct at86rf230_local *lp) ...@@ -1615,47 +1542,6 @@ at86rf230_detect_device(struct at86rf230_local *lp)
return rc; return rc;
} }
#ifdef CONFIG_IEEE802154_AT86RF230_DEBUGFS
static struct dentry *at86rf230_debugfs_root;
static int at86rf230_stats_show(struct seq_file *file, void *offset)
{
struct at86rf230_local *lp = file->private;
seq_printf(file, "SUCCESS:\t\t%8llu\n", lp->trac.success);
seq_printf(file, "SUCCESS_DATA_PENDING:\t%8llu\n",
lp->trac.success_data_pending);
seq_printf(file, "SUCCESS_WAIT_FOR_ACK:\t%8llu\n",
lp->trac.success_wait_for_ack);
seq_printf(file, "CHANNEL_ACCESS_FAILURE:\t%8llu\n",
lp->trac.channel_access_failure);
seq_printf(file, "NO_ACK:\t\t\t%8llu\n", lp->trac.no_ack);
seq_printf(file, "INVALID:\t\t%8llu\n", lp->trac.invalid);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(at86rf230_stats);
static void at86rf230_debugfs_init(struct at86rf230_local *lp)
{
char debugfs_dir_name[DNAME_INLINE_LEN + 1] = "at86rf230-";
strncat(debugfs_dir_name, dev_name(&lp->spi->dev), DNAME_INLINE_LEN);
at86rf230_debugfs_root = debugfs_create_dir(debugfs_dir_name, NULL);
debugfs_create_file("trac_stats", 0444, at86rf230_debugfs_root, lp,
&at86rf230_stats_fops);
}
static void at86rf230_debugfs_remove(void)
{
debugfs_remove_recursive(at86rf230_debugfs_root);
}
#else
static void at86rf230_debugfs_init(struct at86rf230_local *lp) { }
static void at86rf230_debugfs_remove(void) { }
#endif
static int at86rf230_probe(struct spi_device *spi) static int at86rf230_probe(struct spi_device *spi)
{ {
struct ieee802154_hw *hw; struct ieee802154_hw *hw;
...@@ -1752,16 +1638,12 @@ static int at86rf230_probe(struct spi_device *spi) ...@@ -1752,16 +1638,12 @@ static int at86rf230_probe(struct spi_device *spi)
/* going into sleep by default */ /* going into sleep by default */
at86rf230_sleep(lp); at86rf230_sleep(lp);
at86rf230_debugfs_init(lp);
rc = ieee802154_register_hw(lp->hw); rc = ieee802154_register_hw(lp->hw);
if (rc) if (rc)
goto free_debugfs; goto free_dev;
return rc; return rc;
free_debugfs:
at86rf230_debugfs_remove();
free_dev: free_dev:
ieee802154_free_hw(lp->hw); ieee802154_free_hw(lp->hw);
...@@ -1776,7 +1658,6 @@ static void at86rf230_remove(struct spi_device *spi) ...@@ -1776,7 +1658,6 @@ static void at86rf230_remove(struct spi_device *spi)
at86rf230_write_subreg(lp, SR_IRQ_MASK, 0); at86rf230_write_subreg(lp, SR_IRQ_MASK, 0);
ieee802154_unregister_hw(lp->hw); ieee802154_unregister_hw(lp->hw);
ieee802154_free_hw(lp->hw); ieee802154_free_hw(lp->hw);
at86rf230_debugfs_remove();
dev_dbg(&spi->dev, "unregistered at86rf230\n"); dev_dbg(&spi->dev, "unregistered at86rf230\n");
} }
......
...@@ -206,9 +206,7 @@ static void atusb_tx_done(struct atusb *atusb, u8 seq) ...@@ -206,9 +206,7 @@ static void atusb_tx_done(struct atusb *atusb, u8 seq)
* unlikely case now that seq == expect is then true, but can * unlikely case now that seq == expect is then true, but can
* happen and fail with a tx_skb = NULL; * happen and fail with a tx_skb = NULL;
*/ */
ieee802154_wake_queue(atusb->hw); ieee802154_xmit_hw_error(atusb->hw, atusb->tx_skb);
if (atusb->tx_skb)
dev_kfree_skb_irq(atusb->tx_skb);
} }
} }
...@@ -614,36 +612,6 @@ static int hulusb_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel) ...@@ -614,36 +612,6 @@ static int hulusb_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
if (rc < 0) if (rc < 0)
return rc; 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); return atusb_write_subreg(lp, SR_CHANNEL, channel);
} }
...@@ -869,7 +837,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb) ...@@ -869,7 +837,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
chip = "AT86RF230"; chip = "AT86RF230";
atusb->hw->phy->supported.channels[0] = 0x7FFF800; atusb->hw->phy->supported.channels[0] = 0x7FFF800;
atusb->hw->phy->current_channel = 11; /* reset default */ 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 = atusb_powers;
atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers); atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers);
hw->phy->supported.cca_ed_levels = atusb_ed_levels; hw->phy->supported.cca_ed_levels = atusb_ed_levels;
...@@ -879,7 +846,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb) ...@@ -879,7 +846,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
chip = "AT86RF231"; chip = "AT86RF231";
atusb->hw->phy->supported.channels[0] = 0x7FFF800; atusb->hw->phy->supported.channels[0] = 0x7FFF800;
atusb->hw->phy->current_channel = 11; /* reset default */ 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 = atusb_powers;
atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers); atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers);
hw->phy->supported.cca_ed_levels = atusb_ed_levels; hw->phy->supported.cca_ed_levels = atusb_ed_levels;
...@@ -891,7 +857,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb) ...@@ -891,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[0] = 0x00007FF;
atusb->hw->phy->supported.channels[2] = 0x00007FF; atusb->hw->phy->supported.channels[2] = 0x00007FF;
atusb->hw->phy->current_channel = 5; 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.lbt = NL802154_SUPPORTED_BOOL_BOTH;
atusb->hw->phy->supported.tx_powers = at86rf212_powers; atusb->hw->phy->supported.tx_powers = at86rf212_powers;
atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers); atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers);
......
This diff is collapsed.
...@@ -975,10 +975,6 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp) ...@@ -975,10 +975,6 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
dev_dbg(printdev(lp), "%s\n", __func__); dev_dbg(printdev(lp), "%s\n", __func__);
phy->symbol_duration = 16;
phy->lifs_period = 40 * phy->symbol_duration;
phy->sifs_period = 12 * phy->symbol_duration;
hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | hw->flags = IEEE802154_HW_TX_OMIT_CKSUM |
IEEE802154_HW_AFILT | IEEE802154_HW_AFILT |
IEEE802154_HW_PROMISCUOUS; IEEE802154_HW_PROMISCUOUS;
...@@ -1006,7 +1002,6 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp) ...@@ -1006,7 +1002,6 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
phy->current_page = 0; phy->current_page = 0;
/* MCR20A default reset value */ /* MCR20A default reset value */
phy->current_channel = 20; phy->current_channel = 20;
phy->symbol_duration = 16;
phy->supported.tx_powers = mcr20a_powers; phy->supported.tx_powers = mcr20a_powers;
phy->supported.tx_powers_size = ARRAY_SIZE(mcr20a_powers); phy->supported.tx_powers_size = ARRAY_SIZE(mcr20a_powers);
phy->cca_ed_level = phy->supported.cca_ed_levels[75]; phy->cca_ed_level = phy->supported.cca_ed_levels[75];
......
...@@ -134,18 +134,46 @@ enum { ...@@ -134,18 +134,46 @@ enum {
* a successful transmission. * a successful transmission.
*/ */
IEEE802154_SUCCESS = 0x0, IEEE802154_SUCCESS = 0x0,
/* The requested operation failed. */
IEEE802154_MAC_ERROR = 0x1,
/* The requested operation has been cancelled. */
IEEE802154_CANCELLED = 0x2,
/*
* Device is ready to poll the coordinator for data in a non beacon
* enabled PAN.
*/
IEEE802154_READY_FOR_POLL = 0x3,
/* Wrong frame counter. */
IEEE802154_COUNTER_ERROR = 0xdb,
/*
* The frame does not conforms to the incoming key usage policy checking
* procedure.
*/
IEEE802154_IMPROPER_KEY_TYPE = 0xdc,
/*
* The frame does not conforms to the incoming security level usage
* policy checking procedure.
*/
IEEE802154_IMPROPER_SECURITY_LEVEL = 0xdd,
/* Secured frame received with an empty Frame Version field. */
IEEE802154_UNSUPPORTED_LEGACY = 0xde,
/*
* A secured frame is received or must be sent but security is not
* enabled in the device. Or, the Auxiliary Security Header has security
* level of zero in it.
*/
IEEE802154_UNSUPPORTED_SECURITY = 0xdf,
/* The beacon was lost following a synchronization request. */ /* The beacon was lost following a synchronization request. */
IEEE802154_BEACON_LOSS = 0xe0, IEEE802154_BEACON_LOST = 0xe0,
/* /*
* A transmission could not take place due to activity on the * A transmission could not take place due to activity on the
* channel, i.e., the CSMA-CA mechanism has failed. * channel, i.e., the CSMA-CA mechanism has failed.
*/ */
IEEE802154_CHNL_ACCESS_FAIL = 0xe1, IEEE802154_CHANNEL_ACCESS_FAILURE = 0xe1,
/* The GTS request has been denied by the PAN coordinator. */ /* The GTS request has been denied by the PAN coordinator. */
IEEE802154_DENINED = 0xe2, IEEE802154_DENIED = 0xe2,
/* The attempt to disable the transceiver has failed. */ /* The attempt to disable the transceiver has failed. */
IEEE802154_DISABLE_TRX_FAIL = 0xe3, IEEE802154_DISABLE_TRX_FAILURE = 0xe3,
/* /*
* The received frame induces a failed security check according to * The received frame induces a failed security check according to
* the security suite. * the security suite.
...@@ -185,9 +213,9 @@ enum { ...@@ -185,9 +213,9 @@ enum {
* A PAN identifier conflict has been detected and communicated to the * A PAN identifier conflict has been detected and communicated to the
* PAN coordinator. * PAN coordinator.
*/ */
IEEE802154_PANID_CONFLICT = 0xee, IEEE802154_PAN_ID_CONFLICT = 0xee,
/* A coordinator realignment command has been received. */ /* A coordinator realignment command has been received. */
IEEE802154_REALIGMENT = 0xef, IEEE802154_REALIGNMENT = 0xef,
/* The transaction has expired and its information discarded. */ /* The transaction has expired and its information discarded. */
IEEE802154_TRANSACTION_EXPIRED = 0xf0, IEEE802154_TRANSACTION_EXPIRED = 0xf0,
/* There is no capacity to store the transaction. */ /* There is no capacity to store the transaction. */
...@@ -203,12 +231,49 @@ enum { ...@@ -203,12 +231,49 @@ enum {
* A SET/GET request was issued with the identifier of a PIB attribute * A SET/GET request was issued with the identifier of a PIB attribute
* that is not supported. * that is not supported.
*/ */
IEEE802154_UNSUPPORTED_ATTR = 0xf4, IEEE802154_UNSUPPORTED_ATTRIBUTE = 0xf4,
/* Missing source or destination address or address mode. */
IEEE802154_INVALID_ADDRESS = 0xf5,
/*
* MLME asked to turn the receiver on, but the on time duration is too
* big compared to the macBeaconOrder.
*/
IEEE802154_ON_TIME_TOO_LONG = 0xf6,
/*
* MLME asaked to turn the receiver on, but the request was delayed for
* too long before getting processed.
*/
IEEE802154_PAST_TIME = 0xf7,
/*
* The StartTime parameter is nonzero, and the MLME is not currently
* tracking the beacon of the coordinator through which it is
* associated.
*/
IEEE802154_TRACKING_OFF = 0xf8,
/*
* The index inside the hierarchical values in PIBAttribute is out of
* range.
*/
IEEE802154_INVALID_INDEX = 0xf9,
/*
* The number of PAN descriptors discovered during a scan has been
* reached.
*/
IEEE802154_LIMIT_REACHED = 0xfa,
/*
* The PIBAttribute parameter specifies an attribute that is a read-only
* attribute.
*/
IEEE802154_READ_ONLY = 0xfb,
/* /*
* A request to perform a scan operation failed because the MLME was * A request to perform a scan operation failed because the MLME was
* in the process of performing a previously initiated scan operation. * in the process of performing a previously initiated scan operation.
*/ */
IEEE802154_SCAN_IN_PROGRESS = 0xfc, IEEE802154_SCAN_IN_PROGRESS = 0xfc,
/* The outgoing superframe overlaps the incoming superframe. */
IEEE802154_SUPERFRAME_OVERLAP = 0xfd,
/* Any other error situation. */
IEEE802154_SYSTEM_ERROR = 0xff,
}; };
/* frame control handling */ /* frame control handling */
......
...@@ -203,8 +203,8 @@ struct wpan_phy { ...@@ -203,8 +203,8 @@ struct wpan_phy {
/* PHY depended MAC PIB values */ /* PHY depended MAC PIB values */
/* 802.15.4 acronym: Tdsym in usec */ /* 802.15.4 acronym: Tdsym in nsec */
u8 symbol_duration; u32 symbol_duration;
/* lifs and sifs periods timing */ /* lifs and sifs periods timing */
u16 lifs_period; u16 lifs_period;
u16 sifs_period; u16 sifs_period;
...@@ -415,4 +415,6 @@ static inline const char *wpan_phy_name(struct wpan_phy *phy) ...@@ -415,4 +415,6 @@ static inline const char *wpan_phy_name(struct wpan_phy *phy)
return dev_name(&phy->dev); return dev_name(&phy->dev);
} }
void ieee802154_configure_durations(struct wpan_phy *phy);
#endif /* __NET_CFG802154_H */ #endif /* __NET_CFG802154_H */
...@@ -498,4 +498,23 @@ void ieee802154_stop_queue(struct ieee802154_hw *hw); ...@@ -498,4 +498,23 @@ void ieee802154_stop_queue(struct ieee802154_hw *hw);
void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb, void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
bool ifs_handling); bool ifs_handling);
/**
* ieee802154_xmit_error - offloaded frame transmission failed
*
* @hw: pointer as obtained from ieee802154_alloc_hw().
* @skb: buffer for transmission
* @reason: error code
*/
void ieee802154_xmit_error(struct ieee802154_hw *hw, struct sk_buff *skb,
int reason);
/**
* ieee802154_xmit_hw_error - frame could not be offloaded to the transmitter
* because of a hardware error (bus error, timeout, etc)
*
* @hw: pointer as obtained from ieee802154_alloc_hw().
* @skb: buffer for transmission
*/
void ieee802154_xmit_hw_error(struct ieee802154_hw *hw, struct sk_buff *skb);
#endif /* NET_MAC802154_H */ #endif /* NET_MAC802154_H */
...@@ -118,6 +118,7 @@ ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel) ...@@ -118,6 +118,7 @@ ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
if (!ret) { if (!ret) {
wpan_phy->current_page = page; wpan_phy->current_page = page;
wpan_phy->current_channel = channel; wpan_phy->current_channel = channel;
ieee802154_configure_durations(wpan_phy);
} }
return ret; return ret;
......
...@@ -56,6 +56,8 @@ struct ieee802154_local { ...@@ -56,6 +56,8 @@ struct ieee802154_local {
struct sk_buff *tx_skb; struct sk_buff *tx_skb;
struct work_struct tx_work; struct work_struct tx_work;
/* A negative Linux error code or a null/positive MLME error status */
int tx_result;
}; };
enum { enum {
......
...@@ -113,6 +113,50 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops) ...@@ -113,6 +113,50 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
} }
EXPORT_SYMBOL(ieee802154_alloc_hw); EXPORT_SYMBOL(ieee802154_alloc_hw);
void ieee802154_configure_durations(struct wpan_phy *phy)
{
u32 duration = 0;
switch (phy->current_page) {
case 0:
if (BIT(phy->current_channel) & 0x1)
/* 868 MHz BPSK 802.15.4-2003: 20 ksym/s */
duration = 50 * NSEC_PER_USEC;
else if (BIT(phy->current_channel) & 0x7FE)
/* 915 MHz BPSK 802.15.4-2003: 40 ksym/s */
duration = 25 * NSEC_PER_USEC;
else if (BIT(phy->current_channel) & 0x7FFF800)
/* 2400 MHz O-QPSK 802.15.4-2006: 62.5 ksym/s */
duration = 16 * NSEC_PER_USEC;
break;
case 2:
if (BIT(phy->current_channel) & 0x1)
/* 868 MHz O-QPSK 802.15.4-2006: 25 ksym/s */
duration = 40 * NSEC_PER_USEC;
else if (BIT(phy->current_channel) & 0x7FE)
/* 915 MHz O-QPSK 802.15.4-2006: 62.5 ksym/s */
duration = 16 * NSEC_PER_USEC;
break;
case 3:
if (BIT(phy->current_channel) & 0x3FFF)
/* 2.4 GHz CSS 802.15.4a-2007: 1/6 Msym/s */
duration = 6 * NSEC_PER_USEC;
break;
default:
break;
}
if (!duration) {
pr_debug("Unknown PHY symbol duration\n");
return;
}
phy->symbol_duration = duration;
phy->lifs_period = (IEEE802154_LIFS_PERIOD * phy->symbol_duration) / NSEC_PER_SEC;
phy->sifs_period = (IEEE802154_SIFS_PERIOD * phy->symbol_duration) / NSEC_PER_SEC;
}
EXPORT_SYMBOL(ieee802154_configure_durations);
void ieee802154_free_hw(struct ieee802154_hw *hw) void ieee802154_free_hw(struct ieee802154_hw *hw)
{ {
struct ieee802154_local *local = hw_to_local(hw); struct ieee802154_local *local = hw_to_local(hw);
...@@ -131,10 +175,10 @@ static void ieee802154_setup_wpan_phy_pib(struct wpan_phy *wpan_phy) ...@@ -131,10 +175,10 @@ static void ieee802154_setup_wpan_phy_pib(struct wpan_phy *wpan_phy)
* Should be done when all drivers sets this value. * Should be done when all drivers sets this value.
*/ */
wpan_phy->lifs_period = IEEE802154_LIFS_PERIOD * wpan_phy->lifs_period =
wpan_phy->symbol_duration; (IEEE802154_LIFS_PERIOD * wpan_phy->symbol_duration) / 1000;
wpan_phy->sifs_period = IEEE802154_SIFS_PERIOD * wpan_phy->sifs_period =
wpan_phy->symbol_duration; (IEEE802154_SIFS_PERIOD * wpan_phy->symbol_duration) / 1000;
} }
int ieee802154_register_hw(struct ieee802154_hw *hw) int ieee802154_register_hw(struct ieee802154_hw *hw)
...@@ -157,6 +201,8 @@ int ieee802154_register_hw(struct ieee802154_hw *hw) ...@@ -157,6 +201,8 @@ int ieee802154_register_hw(struct ieee802154_hw *hw)
ieee802154_setup_wpan_phy_pib(local->phy); ieee802154_setup_wpan_phy_pib(local->phy);
ieee802154_configure_durations(local->phy);
if (!(hw->flags & IEEE802154_HW_CSMA_PARAMS)) { if (!(hw->flags & IEEE802154_HW_CSMA_PARAMS)) {
local->phy->supported.min_csma_backoffs = 4; local->phy->supported.min_csma_backoffs = 4;
local->phy->supported.max_csma_backoffs = 4; local->phy->supported.max_csma_backoffs = 4;
......
...@@ -58,8 +58,11 @@ enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer) ...@@ -58,8 +58,11 @@ enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer)
void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb, void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
bool ifs_handling) bool ifs_handling)
{ {
struct ieee802154_local *local = hw_to_local(hw);
local->tx_result = IEEE802154_SUCCESS;
if (ifs_handling) { if (ifs_handling) {
struct ieee802154_local *local = hw_to_local(hw);
u8 max_sifs_size; u8 max_sifs_size;
/* If transceiver sets CRC on his own we need to use lifs /* If transceiver sets CRC on his own we need to use lifs
...@@ -88,6 +91,23 @@ void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb, ...@@ -88,6 +91,23 @@ void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
} }
EXPORT_SYMBOL(ieee802154_xmit_complete); EXPORT_SYMBOL(ieee802154_xmit_complete);
void ieee802154_xmit_error(struct ieee802154_hw *hw, struct sk_buff *skb,
int reason)
{
struct ieee802154_local *local = hw_to_local(hw);
local->tx_result = reason;
ieee802154_wake_queue(hw);
dev_kfree_skb_any(skb);
}
EXPORT_SYMBOL(ieee802154_xmit_error);
void ieee802154_xmit_hw_error(struct ieee802154_hw *hw, struct sk_buff *skb)
{
ieee802154_xmit_error(hw, skb, IEEE802154_SYSTEM_ERROR);
}
EXPORT_SYMBOL(ieee802154_xmit_hw_error);
void ieee802154_stop_device(struct ieee802154_local *local) void ieee802154_stop_device(struct ieee802154_local *local)
{ {
flush_workqueue(local->workqueue); flush_workqueue(local->workqueue);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment