fix race condition
This commit is contained in:
parent
d238c8b1cd
commit
a73edd885d
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
copy.sh
|
93
lora_sx127.c
93
lora_sx127.c
|
@ -37,9 +37,10 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DEBUG
|
|
||||||
#define SX127X_LEGACY_KERNEL
|
#define SX127X_LEGACY_KERNEL
|
||||||
|
|
||||||
|
#define DEBUG
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
@ -50,28 +51,9 @@
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
#include <net/mac802154.h>
|
#include <net/mac802154.h>
|
||||||
|
|
||||||
#ifndef F_XOSC
|
static unsigned tx_poll_div = 10;
|
||||||
#define F_XOSC 32000000
|
module_param(tx_poll_div, uint, 0000);
|
||||||
#endif
|
MODULE_PARM_DESC(tx_poll_div, "Number of RX poll cycles to perform before attempting a single TX op");
|
||||||
static u32 xosc_frq = F_XOSC;
|
|
||||||
module_param(xosc_frq, uint, 0000);
|
|
||||||
MODULE_PARM_DESC(xosc_frq, "Crystal oscillator frequency of the LoRa chip");
|
|
||||||
|
|
||||||
#define __POW_2_19 0x80000
|
|
||||||
|
|
||||||
#ifndef SX127X_SPRF
|
|
||||||
#define SX127X_SPRF 512
|
|
||||||
#endif
|
|
||||||
static u32 sprf = SX127X_SPRF;
|
|
||||||
module_param(sprf, uint, 0000);
|
|
||||||
MODULE_PARM_DESC(sprf, "Spreading factor of Chirp Spread Spectrum modulation");
|
|
||||||
|
|
||||||
#ifndef SX127X_RX_BYTE_TIMEOUT
|
|
||||||
#define SX127X_RX_BYTE_TIMEOUT 1023
|
|
||||||
#endif
|
|
||||||
static u32 rx_timeout = SX127X_RX_BYTE_TIMEOUT;
|
|
||||||
module_param(rx_timeout, uint, 0000);
|
|
||||||
MODULE_PARM_DESC(rx_timeout, "RX time-out value as number of symbols");
|
|
||||||
|
|
||||||
/* SX127X Registers addresses */
|
/* SX127X Registers addresses */
|
||||||
#define SX127X_REG_FIFO 0x00
|
#define SX127X_REG_FIFO 0x00
|
||||||
|
@ -167,10 +149,6 @@ MODULE_PARM_DESC(rx_timeout, "RX time-out value as number of symbols");
|
||||||
#define SX127X_MODEM_CONFIG1_HEADER_MODE_EXPLICIT 0x00
|
#define SX127X_MODEM_CONFIG1_HEADER_MODE_EXPLICIT 0x00
|
||||||
#define SX127X_MODEM_CONFIG1_HEADER_MODE_IMPLICIT 0x01
|
#define SX127X_MODEM_CONFIG1_HEADER_MODE_IMPLICIT 0x01
|
||||||
|
|
||||||
#define SX127X_MODEM_CONFIG2_RXPAYLOADCRCON 0x04
|
|
||||||
|
|
||||||
#define SX127X_MODEM_CONFIG3_AGCAUTOON 0x04
|
|
||||||
|
|
||||||
/* SX127X's RX/TX FIFO base address */
|
/* SX127X's RX/TX FIFO base address */
|
||||||
#define SX127X_FIFO_RX_BASE_ADDRESS 0x00
|
#define SX127X_FIFO_RX_BASE_ADDRESS 0x00
|
||||||
#define SX127X_FIFO_TX_BASE_ADDRESS 0x80
|
#define SX127X_FIFO_TX_BASE_ADDRESS 0x80
|
||||||
|
@ -186,6 +164,7 @@ struct sx127x {
|
||||||
bool busy;
|
bool busy;
|
||||||
struct sk_buff *tx_skb;
|
struct sk_buff *tx_skb;
|
||||||
size_t delayed_tx_length;
|
size_t delayed_tx_length;
|
||||||
|
unsigned tx_wait;
|
||||||
|
|
||||||
struct timer_list poll_timer;
|
struct timer_list poll_timer;
|
||||||
struct work_struct poll_work;
|
struct work_struct poll_work;
|
||||||
|
@ -316,7 +295,7 @@ static int sx127x_set_tx_power(struct sx127x *hw, int level)
|
||||||
|
|
||||||
static int sx127x_init(struct sx127x *hw, u8 *major, u8 *minor)
|
static int sx127x_init(struct sx127x *hw, u8 *major, u8 *minor)
|
||||||
{
|
{
|
||||||
u8 modem_config1, modem_config2, lna, version;
|
u8 modem_config1, lna, version;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = sx127x_reg_read(hw, SX127X_REG_VERSION, &version);
|
ret = sx127x_reg_read(hw, SX127X_REG_VERSION, &version);
|
||||||
|
@ -358,23 +337,14 @@ static int sx127x_init(struct sx127x *hw, u8 *major, u8 *minor)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = sx127x_reg_read(hw, SX127X_REG_MODEM_CONFIG2, &modem_config2);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
modem_config1 &= ~SX127X_MODEM_CONFIG1_HEADER_MODE_MASK;
|
modem_config1 &= ~SX127X_MODEM_CONFIG1_HEADER_MODE_MASK;
|
||||||
modem_config1 |= SX127X_MODEM_CONFIG1_HEADER_MODE_EXPLICIT;
|
modem_config1 |= SX127X_MODEM_CONFIG1_HEADER_MODE_EXPLICIT;
|
||||||
modem_config2 |= SX127X_MODEM_CONFIG2_RXPAYLOADCRCON;
|
|
||||||
|
|
||||||
ret = sx127x_reg_write(hw, SX127X_REG_MODEM_CONFIG1, modem_config1);
|
ret = sx127x_reg_write(hw, SX127X_REG_MODEM_CONFIG1, modem_config1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = sx127x_reg_write(hw, SX127X_REG_MODEM_CONFIG2, modem_config2);
|
ret = sx127x_reg_write(hw, SX127X_REG_MODEM_CONFIG3, 0x4);
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = sx127x_reg_write(hw, SX127X_REG_MODEM_CONFIG3, SX127X_MODEM_CONFIG3_AGCAUTOON);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -493,7 +463,7 @@ static void sx127x_poll_work(struct work_struct *work)
|
||||||
goto exit_busy;
|
goto exit_busy;
|
||||||
|
|
||||||
ack_flags = 0;
|
ack_flags = 0;
|
||||||
|
|
||||||
if (read_flags & SX127X_FLAG_TXDONE)
|
if (read_flags & SX127X_FLAG_TXDONE)
|
||||||
ack_flags |= SX127X_FLAG_TXDONE;
|
ack_flags |= SX127X_FLAG_TXDONE;
|
||||||
else
|
else
|
||||||
|
@ -526,9 +496,6 @@ static void sx127x_poll_work(struct work_struct *work)
|
||||||
if (!rx_skb)
|
if (!rx_skb)
|
||||||
goto exit_busy;
|
goto exit_busy;
|
||||||
|
|
||||||
if (rx_length > IEEE802154_MTU)
|
|
||||||
rx_length = IEEE802154_MTU;
|
|
||||||
|
|
||||||
rx_data = skb_put(rx_skb, rx_length);
|
rx_data = skb_put(rx_skb, rx_length);
|
||||||
while (rx_length--)
|
while (rx_length--)
|
||||||
if (sx127x_reg_read(hw, SX127X_REG_FIFO, rx_data++) < 0)
|
if (sx127x_reg_read(hw, SX127X_REG_FIFO, rx_data++) < 0)
|
||||||
|
@ -545,7 +512,10 @@ static void sx127x_poll_work(struct work_struct *work)
|
||||||
goto exit_busy;
|
goto exit_busy;
|
||||||
|
|
||||||
if ((mode & SX127X_MODE_MASK) != SX127X_TX_MODE) {
|
if ((mode & SX127X_MODE_MASK) != SX127X_TX_MODE) {
|
||||||
if (hw->delayed_tx_length) {
|
if (++hw->tx_wait >= tx_poll_div)
|
||||||
|
hw->tx_wait = 0;
|
||||||
|
|
||||||
|
if (hw->delayed_tx_length && hw->tx_wait == 0) {
|
||||||
sx127x_mode(hw, SX127X_TX_MODE);
|
sx127x_mode(hw, SX127X_TX_MODE);
|
||||||
hw->delayed_tx_length = 0;
|
hw->delayed_tx_length = 0;
|
||||||
} else if ((mode & SX127X_MODE_MASK) != SX127X_RXCONTINUOUS_MODE)
|
} else if ((mode & SX127X_MODE_MASK) != SX127X_RXCONTINUOUS_MODE)
|
||||||
|
@ -562,14 +532,14 @@ exit_busy:
|
||||||
if (rx_skb)
|
if (rx_skb)
|
||||||
kfree_skb(rx_skb);
|
kfree_skb(rx_skb);
|
||||||
|
|
||||||
if (tx_skb)
|
|
||||||
ieee802154_xmit_complete(hw->ieee, tx_skb, false);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&hw->lock, spin_irq);
|
spin_lock_irqsave(&hw->lock, spin_irq);
|
||||||
hw->busy = false;
|
hw->busy = false;
|
||||||
if (tx_skb)
|
if (tx_skb)
|
||||||
hw->tx_skb = NULL;
|
hw->tx_skb = NULL;
|
||||||
spin_unlock_irqrestore(&hw->lock, spin_irq);
|
spin_unlock_irqrestore(&hw->lock, spin_irq);
|
||||||
|
|
||||||
|
if (tx_skb)
|
||||||
|
ieee802154_xmit_complete(hw->ieee, tx_skb, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sx127x_poll_timer(struct timer_list *timer)
|
static void sx127x_poll_timer(struct timer_list *timer)
|
||||||
|
@ -592,7 +562,9 @@ static int sx127x_802154_xmit_async(struct ieee802154_hw *ieee, struct sk_buff *
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
spin_unlock_irqrestore(&hw->lock, spin_irq);
|
spin_unlock_irqrestore(&hw->lock, spin_irq);
|
||||||
|
|
||||||
schedule_work(&hw->tx_work);
|
if (!ret)
|
||||||
|
schedule_work(&hw->tx_work);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,7 +601,6 @@ static int sx127x_802154_start(struct ieee802154_hw *ieee)
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_timer(&hw->poll_timer, jiffies + POLL_JIFFIES);
|
mod_timer(&hw->poll_timer, jiffies + POLL_JIFFIES);
|
||||||
dev_dbg(regmap_get_device(hw->regmap), "%s\n", __func__);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,7 +612,6 @@ static void sx127x_802154_stop(struct ieee802154_hw *ieee)
|
||||||
cancel_work_sync(&hw->poll_work);
|
cancel_work_sync(&hw->poll_work);
|
||||||
|
|
||||||
(void) sx127x_mode(hw, SX127X_SLEEP_MODE);
|
(void) sx127x_mode(hw, SX127X_SLEEP_MODE);
|
||||||
dev_dbg(regmap_get_device(hw->regmap), "%s\n", __func__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sx127x_802154_set_promiscuous_mode(struct ieee802154_hw *ieee, const bool on)
|
static int sx127x_802154_set_promiscuous_mode(struct ieee802154_hw *ieee, const bool on)
|
||||||
|
@ -700,6 +670,7 @@ static int sx127x_spi_probe(struct spi_device *spi)
|
||||||
hw->spi = spi;
|
hw->spi = spi;
|
||||||
hw->ieee = ieee;
|
hw->ieee = ieee;
|
||||||
hw->busy = false;
|
hw->busy = false;
|
||||||
|
hw->tx_wait = 0;
|
||||||
hw->delayed_tx_length = 0;
|
hw->delayed_tx_length = 0;
|
||||||
spin_lock_init(&hw->lock);
|
spin_lock_init(&hw->lock);
|
||||||
|
|
||||||
|
@ -774,6 +745,30 @@ static int sx127x_spi_probe(struct spi_device *spi)
|
||||||
dev_err(&spi->dev, "ieee802154_register_hw() failed: %d\n", ret);
|
dev_err(&spi->dev, "ieee802154_register_hw() failed: %d\n", ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
/*u8 buffer[] = { 0x36, 0x39 }; // 69?
|
||||||
|
ret = sx127x_mode(hw, SX127X_STANDBY_MODE);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&spi->dev, "%s: sx127x_mode() failed: %d\n", __func__, ret);
|
||||||
|
goto fail_begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sx127x_begin_packet(hw);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&spi->dev, "%s: sx127x_begin_packet() failed: %d\n", __func__, ret);
|
||||||
|
goto fail_begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sx127x_write_buffer(hw, buffer, sizeof buffer);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&spi->dev, "%s: sx127x_send() failed: %d\n", __func__, ret);
|
||||||
|
goto fail_begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sx127x_end_packet(hw, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&spi->dev, "%s: sx127x_end_packet() failed: %d\n", __func__, ret);
|
||||||
|
goto fail_begin;
|
||||||
|
}*/
|
||||||
|
|
||||||
fail_init:
|
fail_init:
|
||||||
ieee802154_free_hw(ieee);
|
ieee802154_free_hw(ieee);
|
||||||
|
|
Loading…
Reference in a new issue