aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2022-05-02 13:57:54 -0700
committerJakub Kicinski <kuba@kernel.org>2022-05-02 13:57:56 -0700
commitc5f50500a0270ee1618373baa85a0bac9a0dc4bf (patch)
tree096fa863dad4f664e51efdd0cc616843cce4c9e9
parentMerge branch 'net-more-heap-allocation-and-split-of-rtnl_newlink' (diff)
parentnet: mac802154: Fix symbol durations (diff)
downloadlinux-dev-c5f50500a0270ee1618373baa85a0bac9a0dc4bf.tar.xz
linux-dev-c5f50500a0270ee1618373baa85a0bac9a0dc4bf.zip
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.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/net/ieee802154/Kconfig7
-rw-r--r--drivers/net/ieee802154/at86rf230.c163
-rw-r--r--drivers/net/ieee802154/atusb.c37
-rw-r--r--drivers/net/ieee802154/ca8210.c181
-rw-r--r--drivers/net/ieee802154/mcr20a.c5
-rw-r--r--include/linux/ieee802154.h81
-rw-r--r--include/net/cfg802154.h6
-rw-r--r--include/net/mac802154.h19
-rw-r--r--net/mac802154/cfg.c1
-rw-r--r--net/mac802154/ieee802154_i.h2
-rw-r--r--net/mac802154/main.c54
-rw-r--r--net/mac802154/util.c22
12 files changed, 262 insertions, 316 deletions
diff --git a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig
index 0f7c6dc2ed15..95da876c5613 100644
--- a/drivers/net/ieee802154/Kconfig
+++ b/drivers/net/ieee802154/Kconfig
@@ -33,13 +33,6 @@ config IEEE802154_AT86RF230
This driver can also be built as a module. To do so, say M here.
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
tristate "Microchip MRF24J40 transceiver driver"
depends on IEEE802154_DRIVERS && MAC802154
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 549d04b5f3d4..15f283b26721 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -23,7 +23,6 @@
#include <linux/skbuff.h>
#include <linux/of_gpio.h>
#include <linux/ieee802154.h>
-#include <linux/debugfs.h>
#include <net/mac802154.h>
#include <net/cfg802154.h>
@@ -72,19 +71,11 @@ struct at86rf230_state_change {
void (*complete)(void *context);
u8 from_state;
u8 to_state;
+ int trac;
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 spi_device *spi;
@@ -104,8 +95,6 @@ struct at86rf230_local {
u8 tx_retry;
struct sk_buff *tx_skb;
struct at86rf230_state_change tx;
-
- struct at86rf230_trac trac;
};
#define AT86RF2XX_NUMREGS 0x3F
@@ -346,8 +335,7 @@ at86rf230_async_error_recover_complete(void *context)
if (lp->was_tx) {
lp->was_tx = 0;
- dev_kfree_skb_any(lp->tx_skb);
- ieee802154_wake_queue(lp->hw);
+ ieee802154_xmit_hw_error(lp->hw, lp->tx_skb);
}
}
@@ -653,7 +641,11 @@ at86rf230_tx_complete(void *context)
struct at86rf230_state_change *ctx = context;
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);
}
@@ -672,30 +664,21 @@ at86rf230_tx_trac_check(void *context)
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
+ u8 trac = TRAC_MASK(ctx->buf[1]);
- if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) {
- u8 trac = TRAC_MASK(ctx->buf[1]);
-
- switch (trac) {
- case TRAC_SUCCESS:
- lp->trac.success++;
- break;
- case TRAC_SUCCESS_DATA_PENDING:
- lp->trac.success_data_pending++;
- break;
- case TRAC_CHANNEL_ACCESS_FAILURE:
- lp->trac.channel_access_failure++;
- break;
- 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;
- }
+ switch (trac) {
+ case TRAC_SUCCESS:
+ case TRAC_SUCCESS_DATA_PENDING:
+ ctx->trac = IEEE802154_SUCCESS;
+ break;
+ case TRAC_CHANNEL_ACCESS_FAILURE:
+ ctx->trac = IEEE802154_CHANNEL_ACCESS_FAILURE;
+ break;
+ case TRAC_NO_ACK:
+ ctx->trac = IEEE802154_NO_ACK;
+ break;
+ default:
+ ctx->trac = IEEE802154_SYSTEM_ERROR;
}
at86rf230_async_state_change(lp, ctx, STATE_TX_ON, at86rf230_tx_on);
@@ -737,25 +720,6 @@ at86rf230_rx_trac_check(void *context)
u8 *buf = ctx->buf;
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;
ctx->trx.len = AT86RF2XX_MAX_BUF;
ctx->msg.complete = at86rf230_rx_read_frame_complete;
@@ -951,10 +915,6 @@ at86rf230_start(struct ieee802154_hw *hw)
{
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);
enable_irq(lp->spi->irq);
@@ -1064,36 +1024,6 @@ at86rf212_set_channel(struct at86rf230_local *lp, 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 at86rf230_write_subreg(lp, SR_CHANNEL, channel);
}
@@ -1569,7 +1499,6 @@ at86rf230_detect_device(struct at86rf230_local *lp)
lp->data = &at86rf231_data;
lp->hw->phy->supported.channels[0] = 0x7FFF800;
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_size = ARRAY_SIZE(at86rf231_powers);
lp->hw->phy->supported.cca_ed_levels = at86rf231_ed_levels;
@@ -1582,7 +1511,6 @@ at86rf230_detect_device(struct at86rf230_local *lp)
lp->hw->phy->supported.channels[0] = 0x00007FF;
lp->hw->phy->supported.channels[2] = 0x00007FF;
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.tx_powers = at86rf212_powers;
lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers);
@@ -1594,7 +1522,6 @@ at86rf230_detect_device(struct at86rf230_local *lp)
lp->data = &at86rf233_data;
lp->hw->phy->supported.channels[0] = 0x7FFF800;
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_size = ARRAY_SIZE(at86rf233_powers);
lp->hw->phy->supported.cca_ed_levels = at86rf233_ed_levels;
@@ -1615,47 +1542,6 @@ not_supp:
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)
{
struct ieee802154_hw *hw;
@@ -1752,16 +1638,12 @@ static int at86rf230_probe(struct spi_device *spi)
/* going into sleep by default */
at86rf230_sleep(lp);
- at86rf230_debugfs_init(lp);
-
rc = ieee802154_register_hw(lp->hw);
if (rc)
- goto free_debugfs;
+ goto free_dev;
return rc;
-free_debugfs:
- at86rf230_debugfs_remove();
free_dev:
ieee802154_free_hw(lp->hw);
@@ -1776,7 +1658,6 @@ static void at86rf230_remove(struct spi_device *spi)
at86rf230_write_subreg(lp, SR_IRQ_MASK, 0);
ieee802154_unregister_hw(lp->hw);
ieee802154_free_hw(lp->hw);
- at86rf230_debugfs_remove();
dev_dbg(&spi->dev, "unregistered at86rf230\n");
}
diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c
index 07bafbf94680..2c338783893d 100644
--- a/drivers/net/ieee802154/atusb.c
+++ b/drivers/net/ieee802154/atusb.c
@@ -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
* 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);
}
}
@@ -614,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);
}
@@ -869,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;
@@ -879,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;
@@ -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[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);
diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
index 187cbc634ce8..42c0b451088d 100644
--- a/drivers/net/ieee802154/ca8210.c
+++ b/drivers/net/ieee802154/ca8210.c
@@ -89,48 +89,6 @@
#define CA8210_TEST_INT_FILE_NAME "ca8210_test"
#define CA8210_TEST_INT_FIFO_SIZE 256
-/* MAC status enumerations */
-#define MAC_SUCCESS (0x00)
-#define MAC_ERROR (0x01)
-#define MAC_CANCELLED (0x02)
-#define MAC_READY_FOR_POLL (0x03)
-#define MAC_COUNTER_ERROR (0xDB)
-#define MAC_IMPROPER_KEY_TYPE (0xDC)
-#define MAC_IMPROPER_SECURITY_LEVEL (0xDD)
-#define MAC_UNSUPPORTED_LEGACY (0xDE)
-#define MAC_UNSUPPORTED_SECURITY (0xDF)
-#define MAC_BEACON_LOST (0xE0)
-#define MAC_CHANNEL_ACCESS_FAILURE (0xE1)
-#define MAC_DENIED (0xE2)
-#define MAC_DISABLE_TRX_FAILURE (0xE3)
-#define MAC_SECURITY_ERROR (0xE4)
-#define MAC_FRAME_TOO_LONG (0xE5)
-#define MAC_INVALID_GTS (0xE6)
-#define MAC_INVALID_HANDLE (0xE7)
-#define MAC_INVALID_PARAMETER (0xE8)
-#define MAC_NO_ACK (0xE9)
-#define MAC_NO_BEACON (0xEA)
-#define MAC_NO_DATA (0xEB)
-#define MAC_NO_SHORT_ADDRESS (0xEC)
-#define MAC_OUT_OF_CAP (0xED)
-#define MAC_PAN_ID_CONFLICT (0xEE)
-#define MAC_REALIGNMENT (0xEF)
-#define MAC_TRANSACTION_EXPIRED (0xF0)
-#define MAC_TRANSACTION_OVERFLOW (0xF1)
-#define MAC_TX_ACTIVE (0xF2)
-#define MAC_UNAVAILABLE_KEY (0xF3)
-#define MAC_UNSUPPORTED_ATTRIBUTE (0xF4)
-#define MAC_INVALID_ADDRESS (0xF5)
-#define MAC_ON_TIME_TOO_LONG (0xF6)
-#define MAC_PAST_TIME (0xF7)
-#define MAC_TRACKING_OFF (0xF8)
-#define MAC_INVALID_INDEX (0xF9)
-#define MAC_LIMIT_REACHED (0xFA)
-#define MAC_READ_ONLY (0xFB)
-#define MAC_SCAN_IN_PROGRESS (0xFC)
-#define MAC_SUPERFRAME_OVERLAP (0xFD)
-#define MAC_SYSTEM_ERROR (0xFF)
-
/* HWME attribute IDs */
#define HWME_EDTHRESHOLD (0x04)
#define HWME_EDVALUE (0x06)
@@ -551,58 +509,58 @@ static int link_to_linux_err(int link_status)
return link_status;
}
switch (link_status) {
- case MAC_SUCCESS:
- case MAC_REALIGNMENT:
+ case IEEE802154_SUCCESS:
+ case IEEE802154_REALIGNMENT:
return 0;
- case MAC_IMPROPER_KEY_TYPE:
+ case IEEE802154_IMPROPER_KEY_TYPE:
return -EKEYREJECTED;
- case MAC_IMPROPER_SECURITY_LEVEL:
- case MAC_UNSUPPORTED_LEGACY:
- case MAC_DENIED:
+ case IEEE802154_IMPROPER_SECURITY_LEVEL:
+ case IEEE802154_UNSUPPORTED_LEGACY:
+ case IEEE802154_DENIED:
return -EACCES;
- case MAC_BEACON_LOST:
- case MAC_NO_ACK:
- case MAC_NO_BEACON:
+ case IEEE802154_BEACON_LOST:
+ case IEEE802154_NO_ACK:
+ case IEEE802154_NO_BEACON:
return -ENETUNREACH;
- case MAC_CHANNEL_ACCESS_FAILURE:
- case MAC_TX_ACTIVE:
- case MAC_SCAN_IN_PROGRESS:
+ case IEEE802154_CHANNEL_ACCESS_FAILURE:
+ case IEEE802154_TX_ACTIVE:
+ case IEEE802154_SCAN_IN_PROGRESS:
return -EBUSY;
- case MAC_DISABLE_TRX_FAILURE:
- case MAC_OUT_OF_CAP:
+ case IEEE802154_DISABLE_TRX_FAILURE:
+ case IEEE802154_OUT_OF_CAP:
return -EAGAIN;
- case MAC_FRAME_TOO_LONG:
+ case IEEE802154_FRAME_TOO_LONG:
return -EMSGSIZE;
- case MAC_INVALID_GTS:
- case MAC_PAST_TIME:
+ case IEEE802154_INVALID_GTS:
+ case IEEE802154_PAST_TIME:
return -EBADSLT;
- case MAC_INVALID_HANDLE:
+ case IEEE802154_INVALID_HANDLE:
return -EBADMSG;
- case MAC_INVALID_PARAMETER:
- case MAC_UNSUPPORTED_ATTRIBUTE:
- case MAC_ON_TIME_TOO_LONG:
- case MAC_INVALID_INDEX:
+ case IEEE802154_INVALID_PARAMETER:
+ case IEEE802154_UNSUPPORTED_ATTRIBUTE:
+ case IEEE802154_ON_TIME_TOO_LONG:
+ case IEEE802154_INVALID_INDEX:
return -EINVAL;
- case MAC_NO_DATA:
+ case IEEE802154_NO_DATA:
return -ENODATA;
- case MAC_NO_SHORT_ADDRESS:
+ case IEEE802154_NO_SHORT_ADDRESS:
return -EFAULT;
- case MAC_PAN_ID_CONFLICT:
+ case IEEE802154_PAN_ID_CONFLICT:
return -EADDRINUSE;
- case MAC_TRANSACTION_EXPIRED:
+ case IEEE802154_TRANSACTION_EXPIRED:
return -ETIME;
- case MAC_TRANSACTION_OVERFLOW:
+ case IEEE802154_TRANSACTION_OVERFLOW:
return -ENOBUFS;
- case MAC_UNAVAILABLE_KEY:
+ case IEEE802154_UNAVAILABLE_KEY:
return -ENOKEY;
- case MAC_INVALID_ADDRESS:
+ case IEEE802154_INVALID_ADDRESS:
return -ENXIO;
- case MAC_TRACKING_OFF:
- case MAC_SUPERFRAME_OVERLAP:
+ case IEEE802154_TRACKING_OFF:
+ case IEEE802154_SUPERFRAME_OVERLAP:
return -EREMOTEIO;
- case MAC_LIMIT_REACHED:
+ case IEEE802154_LIMIT_REACHED:
return -EDQUOT;
- case MAC_READ_ONLY:
+ case IEEE802154_READ_ONLY:
return -EROFS;
default:
return -EPROTO;
@@ -754,7 +712,7 @@ static void ca8210_rx_done(struct cas_control *cas_ctl)
ca8210_net_rx(priv->hw, buf, len);
if (buf[0] == SPI_MCPS_DATA_CONFIRM) {
- if (buf[3] == MAC_TRANSACTION_OVERFLOW) {
+ if (buf[3] == IEEE802154_TRANSACTION_OVERFLOW) {
dev_info(
&priv->spi->dev,
"Waiting for transaction overflow to stabilise...\n");
@@ -1128,7 +1086,7 @@ static u8 tdme_setsfr_request_sync(
);
if (ret) {
dev_crit(&spi->dev, "cascoda_api_downstream returned %d", ret);
- return MAC_SYSTEM_ERROR;
+ return IEEE802154_SYSTEM_ERROR;
}
if (response.command_id != SPI_TDME_SETSFR_CONFIRM) {
@@ -1137,7 +1095,7 @@ static u8 tdme_setsfr_request_sync(
"sync response to SPI_TDME_SETSFR_REQUEST was not SPI_TDME_SETSFR_CONFIRM, it was %d\n",
response.command_id
);
- return MAC_SYSTEM_ERROR;
+ return IEEE802154_SYSTEM_ERROR;
}
return response.pdata.tdme_set_sfr_cnf.status;
@@ -1151,7 +1109,7 @@ static u8 tdme_setsfr_request_sync(
*/
static u8 tdme_chipinit(void *device_ref)
{
- u8 status = MAC_SUCCESS;
+ u8 status = IEEE802154_SUCCESS;
u8 sfr_address;
struct spi_device *spi = device_ref;
struct preamble_cfg_sfr pre_cfg_value = {
@@ -1220,7 +1178,7 @@ static u8 tdme_chipinit(void *device_ref)
goto finish;
finish:
- if (status != MAC_SUCCESS) {
+ if (status != IEEE802154_SUCCESS) {
dev_err(
&spi->dev,
"failed to set sfr at %#03x, status = %#03x\n",
@@ -1287,7 +1245,7 @@ static u8 tdme_checkpibattribute(
const void *pib_attribute_value
)
{
- u8 status = MAC_SUCCESS;
+ u8 status = IEEE802154_SUCCESS;
u8 value;
value = *((u8 *)pib_attribute_value);
@@ -1296,52 +1254,52 @@ static u8 tdme_checkpibattribute(
/* PHY */
case PHY_TRANSMIT_POWER:
if (value > 0x3F)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
case PHY_CCA_MODE:
if (value > 0x03)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
/* MAC */
case MAC_BATT_LIFE_EXT_PERIODS:
if (value < 6 || value > 41)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
case MAC_BEACON_PAYLOAD:
if (pib_attribute_length > MAX_BEACON_PAYLOAD_LENGTH)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
case MAC_BEACON_PAYLOAD_LENGTH:
if (value > MAX_BEACON_PAYLOAD_LENGTH)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
case MAC_BEACON_ORDER:
if (value > 15)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
case MAC_MAX_BE:
if (value < 3 || value > 8)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
case MAC_MAX_CSMA_BACKOFFS:
if (value > 5)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
case MAC_MAX_FRAME_RETRIES:
if (value > 7)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
case MAC_MIN_BE:
if (value > 8)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
case MAC_RESPONSE_WAIT_TIME:
if (value < 2 || value > 64)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
case MAC_SUPERFRAME_ORDER:
if (value > 15)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
/* boolean */
case MAC_ASSOCIATED_PAN_COORD:
@@ -1353,16 +1311,16 @@ static u8 tdme_checkpibattribute(
case MAC_RX_ON_WHEN_IDLE:
case MAC_SECURITY_ENABLED:
if (value > 1)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
/* MAC SEC */
case MAC_AUTO_REQUEST_SECURITY_LEVEL:
if (value > 7)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
case MAC_AUTO_REQUEST_KEY_ID_MODE:
if (value > 3)
- status = MAC_INVALID_PARAMETER;
+ status = IEEE802154_INVALID_PARAMETER;
break;
default:
break;
@@ -1522,9 +1480,9 @@ static u8 mcps_data_request(
if (ca8210_spi_transfer(device_ref, &command.command_id,
command.length + 2))
- return MAC_SYSTEM_ERROR;
+ return IEEE802154_SYSTEM_ERROR;
- return MAC_SUCCESS;
+ return IEEE802154_SUCCESS;
}
/**
@@ -1553,11 +1511,11 @@ static u8 mlme_reset_request_sync(
&response.command_id,
device_ref)) {
dev_err(&spi->dev, "cascoda_api_downstream failed\n");
- return MAC_SYSTEM_ERROR;
+ return IEEE802154_SYSTEM_ERROR;
}
if (response.command_id != SPI_MLME_RESET_CONFIRM)
- return MAC_SYSTEM_ERROR;
+ return IEEE802154_SYSTEM_ERROR;
status = response.pdata.status;
@@ -1600,7 +1558,7 @@ static u8 mlme_set_request_sync(
*/
if (tdme_checkpibattribute(
pib_attribute, pib_attribute_length, pib_attribute_value)) {
- return MAC_INVALID_PARAMETER;
+ return IEEE802154_INVALID_PARAMETER;
}
if (pib_attribute == PHY_CURRENT_CHANNEL) {
@@ -1636,11 +1594,11 @@ static u8 mlme_set_request_sync(
command.length + 2,
&response.command_id,
device_ref)) {
- return MAC_SYSTEM_ERROR;
+ return IEEE802154_SYSTEM_ERROR;
}
if (response.command_id != SPI_MLME_SET_CONFIRM)
- return MAC_SYSTEM_ERROR;
+ return IEEE802154_SYSTEM_ERROR;
return response.pdata.status;
}
@@ -1678,11 +1636,11 @@ static u8 hwme_set_request_sync(
command.length + 2,
&response.command_id,
device_ref)) {
- return MAC_SYSTEM_ERROR;
+ return IEEE802154_SYSTEM_ERROR;
}
if (response.command_id != SPI_HWME_SET_CONFIRM)
- return MAC_SYSTEM_ERROR;
+ return IEEE802154_SYSTEM_ERROR;
return response.pdata.hwme_set_cnf.status;
}
@@ -1714,13 +1672,13 @@ static u8 hwme_get_request_sync(
command.length + 2,
&response.command_id,
device_ref)) {
- return MAC_SYSTEM_ERROR;
+ return IEEE802154_SYSTEM_ERROR;
}
if (response.command_id != SPI_HWME_GET_CONFIRM)
- return MAC_SYSTEM_ERROR;
+ return IEEE802154_SYSTEM_ERROR;
- if (response.pdata.hwme_get_cnf.status == MAC_SUCCESS) {
+ if (response.pdata.hwme_get_cnf.status == IEEE802154_SUCCESS) {
*hw_attribute_length =
response.pdata.hwme_get_cnf.hw_attribute_length;
memcpy(
@@ -1770,9 +1728,8 @@ static int ca8210_async_xmit_complete(
"Link transmission unsuccessful, status = %d\n",
status
);
- if (status != MAC_TRANSACTION_OVERFLOW) {
- dev_kfree_skb_any(priv->tx_skb);
- ieee802154_wake_queue(priv->hw);
+ if (status != IEEE802154_TRANSACTION_OVERFLOW) {
+ ieee802154_xmit_error(priv->hw, priv->tx_skb, status);
return 0;
}
}
@@ -2436,7 +2393,7 @@ static int ca8210_test_check_upstream(u8 *buf, void *device_ref)
if (ret) {
response[0] = SPI_MLME_SET_CONFIRM;
response[1] = 3;
- response[2] = MAC_INVALID_PARAMETER;
+ response[2] = IEEE802154_INVALID_PARAMETER;
response[3] = buf[2];
response[4] = buf[3];
if (cascoda_api_upstream)
diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c
index c927a5ae0d05..2fe0e4a0a0c4 100644
--- a/drivers/net/ieee802154/mcr20a.c
+++ b/drivers/net/ieee802154/mcr20a.c
@@ -975,10 +975,6 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
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 |
IEEE802154_HW_AFILT |
IEEE802154_HW_PROMISCUOUS;
@@ -1006,7 +1002,6 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
phy->current_page = 0;
/* MCR20A default reset value */
phy->current_channel = 20;
- phy->symbol_duration = 16;
phy->supported.tx_powers = mcr20a_powers;
phy->supported.tx_powers_size = ARRAY_SIZE(mcr20a_powers);
phy->cca_ed_level = phy->supported.cca_ed_levels[75];
diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h
index 95c831162212..f1f9412b6ac6 100644
--- a/include/linux/ieee802154.h
+++ b/include/linux/ieee802154.h
@@ -134,18 +134,46 @@ enum {
* a successful transmission.
*/
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. */
- IEEE802154_BEACON_LOSS = 0xe0,
+ IEEE802154_BEACON_LOST = 0xe0,
/*
* A transmission could not take place due to activity on the
* 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. */
- IEEE802154_DENINED = 0xe2,
+ IEEE802154_DENIED = 0xe2,
/* 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 security suite.
@@ -185,9 +213,9 @@ enum {
* A PAN identifier conflict has been detected and communicated to the
* PAN coordinator.
*/
- IEEE802154_PANID_CONFLICT = 0xee,
+ IEEE802154_PAN_ID_CONFLICT = 0xee,
/* A coordinator realignment command has been received. */
- IEEE802154_REALIGMENT = 0xef,
+ IEEE802154_REALIGNMENT = 0xef,
/* The transaction has expired and its information discarded. */
IEEE802154_TRANSACTION_EXPIRED = 0xf0,
/* There is no capacity to store the transaction. */
@@ -203,12 +231,49 @@ enum {
* A SET/GET request was issued with the identifier of a PIB attribute
* 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
* in the process of performing a previously initiated scan operation.
*/
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 */
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 833672d6fbe4..85f9e8417688 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -203,8 +203,8 @@ struct wpan_phy {
/* PHY depended MAC PIB values */
- /* 802.15.4 acronym: Tdsym in usec */
- u8 symbol_duration;
+ /* 802.15.4 acronym: Tdsym in nsec */
+ u32 symbol_duration;
/* lifs and sifs periods timing */
u16 lifs_period;
u16 sifs_period;
@@ -415,4 +415,6 @@ static inline const char *wpan_phy_name(struct wpan_phy *phy)
return dev_name(&phy->dev);
}
+void ieee802154_configure_durations(struct wpan_phy *phy);
+
#endif /* __NET_CFG802154_H */
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 2c3bbc6645ba..bdac0ddbdcdb 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -498,4 +498,23 @@ void ieee802154_stop_queue(struct ieee802154_hw *hw);
void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
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 */
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index fbeebe3bc31d..1e4a9f74ed43 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -118,6 +118,7 @@ ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
if (!ret) {
wpan_phy->current_page = page;
wpan_phy->current_channel = channel;
+ ieee802154_configure_durations(wpan_phy);
}
return ret;
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 702560acc8ce..1381e6a5e180 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -56,6 +56,8 @@ struct ieee802154_local {
struct sk_buff *tx_skb;
struct work_struct tx_work;
+ /* A negative Linux error code or a null/positive MLME error status */
+ int tx_result;
};
enum {
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index 520cedc594e1..bd7bdb1219dd 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -113,6 +113,50 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
}
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)
{
struct ieee802154_local *local = hw_to_local(hw);
@@ -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.
*/
- wpan_phy->lifs_period = IEEE802154_LIFS_PERIOD *
- wpan_phy->symbol_duration;
- wpan_phy->sifs_period = IEEE802154_SIFS_PERIOD *
- wpan_phy->symbol_duration;
+ wpan_phy->lifs_period =
+ (IEEE802154_LIFS_PERIOD * wpan_phy->symbol_duration) / 1000;
+ wpan_phy->sifs_period =
+ (IEEE802154_SIFS_PERIOD * wpan_phy->symbol_duration) / 1000;
}
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_configure_durations(local->phy);
+
if (!(hw->flags & IEEE802154_HW_CSMA_PARAMS)) {
local->phy->supported.min_csma_backoffs = 4;
local->phy->supported.max_csma_backoffs = 4;
diff --git a/net/mac802154/util.c b/net/mac802154/util.c
index f2078238718b..9f024d85563b 100644
--- a/net/mac802154/util.c
+++ b/net/mac802154/util.c
@@ -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,
bool ifs_handling)
{
+ struct ieee802154_local *local = hw_to_local(hw);
+
+ local->tx_result = IEEE802154_SUCCESS;
+
if (ifs_handling) {
- struct ieee802154_local *local = hw_to_local(hw);
u8 max_sifs_size;
/* 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,
}
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)
{
flush_workqueue(local->workqueue);