|
@@ -275,6 +275,8 @@ struct adf7242_local {
|
|
struct spi_message stat_msg;
|
|
struct spi_message stat_msg;
|
|
struct spi_transfer stat_xfer;
|
|
struct spi_transfer stat_xfer;
|
|
struct dentry *debugfs_root;
|
|
struct dentry *debugfs_root;
|
|
|
|
+ struct delayed_work work;
|
|
|
|
+ struct workqueue_struct *wqueue;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
int tx_stat;
|
|
int tx_stat;
|
|
bool promiscuous;
|
|
bool promiscuous;
|
|
@@ -575,10 +577,26 @@ static int adf7242_cmd_rx(struct adf7242_local *lp)
|
|
/* Wait until the ACK is sent */
|
|
/* Wait until the ACK is sent */
|
|
adf7242_wait_status(lp, RC_STATUS_PHY_RDY, RC_STATUS_MASK, __LINE__);
|
|
adf7242_wait_status(lp, RC_STATUS_PHY_RDY, RC_STATUS_MASK, __LINE__);
|
|
adf7242_clear_irqstat(lp);
|
|
adf7242_clear_irqstat(lp);
|
|
|
|
+ mod_delayed_work(lp->wqueue, &lp->work, msecs_to_jiffies(400));
|
|
|
|
|
|
return adf7242_cmd(lp, CMD_RC_RX);
|
|
return adf7242_cmd(lp, CMD_RC_RX);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void adf7242_rx_cal_work(struct work_struct *work)
|
|
|
|
+{
|
|
|
|
+ struct adf7242_local *lp =
|
|
|
|
+ container_of(work, struct adf7242_local, work.work);
|
|
|
|
+
|
|
|
|
+ /* Reissuing RC_RX every 400ms - to adjust for offset
|
|
|
|
+ * drift in receiver (datasheet page 61, OCL section)
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ if (!test_bit(FLAG_XMIT, &lp->flags)) {
|
|
|
|
+ adf7242_cmd(lp, CMD_RC_PHY_RDY);
|
|
|
|
+ adf7242_cmd_rx(lp);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static int adf7242_set_txpower(struct ieee802154_hw *hw, int mbm)
|
|
static int adf7242_set_txpower(struct ieee802154_hw *hw, int mbm)
|
|
{
|
|
{
|
|
struct adf7242_local *lp = hw->priv;
|
|
struct adf7242_local *lp = hw->priv;
|
|
@@ -686,7 +704,7 @@ static int adf7242_start(struct ieee802154_hw *hw)
|
|
enable_irq(lp->spi->irq);
|
|
enable_irq(lp->spi->irq);
|
|
set_bit(FLAG_START, &lp->flags);
|
|
set_bit(FLAG_START, &lp->flags);
|
|
|
|
|
|
- return adf7242_cmd(lp, CMD_RC_RX);
|
|
|
|
|
|
+ return adf7242_cmd_rx(lp);
|
|
}
|
|
}
|
|
|
|
|
|
static void adf7242_stop(struct ieee802154_hw *hw)
|
|
static void adf7242_stop(struct ieee802154_hw *hw)
|
|
@@ -694,6 +712,7 @@ static void adf7242_stop(struct ieee802154_hw *hw)
|
|
struct adf7242_local *lp = hw->priv;
|
|
struct adf7242_local *lp = hw->priv;
|
|
|
|
|
|
disable_irq(lp->spi->irq);
|
|
disable_irq(lp->spi->irq);
|
|
|
|
+ cancel_delayed_work_sync(&lp->work);
|
|
adf7242_cmd(lp, CMD_RC_IDLE);
|
|
adf7242_cmd(lp, CMD_RC_IDLE);
|
|
clear_bit(FLAG_START, &lp->flags);
|
|
clear_bit(FLAG_START, &lp->flags);
|
|
adf7242_clear_irqstat(lp);
|
|
adf7242_clear_irqstat(lp);
|
|
@@ -719,7 +738,10 @@ static int adf7242_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
|
|
adf7242_write_reg(lp, REG_CH_FREQ1, freq >> 8);
|
|
adf7242_write_reg(lp, REG_CH_FREQ1, freq >> 8);
|
|
adf7242_write_reg(lp, REG_CH_FREQ2, freq >> 16);
|
|
adf7242_write_reg(lp, REG_CH_FREQ2, freq >> 16);
|
|
|
|
|
|
- return adf7242_cmd(lp, CMD_RC_RX);
|
|
|
|
|
|
+ if (test_bit(FLAG_START, &lp->flags))
|
|
|
|
+ return adf7242_cmd_rx(lp);
|
|
|
|
+ else
|
|
|
|
+ return adf7242_cmd(lp, CMD_RC_PHY_RDY);
|
|
}
|
|
}
|
|
|
|
|
|
static int adf7242_set_hw_addr_filt(struct ieee802154_hw *hw,
|
|
static int adf7242_set_hw_addr_filt(struct ieee802154_hw *hw,
|
|
@@ -814,6 +836,7 @@ static int adf7242_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
|
|
/* ensure existing instances of the IRQ handler have completed */
|
|
/* ensure existing instances of the IRQ handler have completed */
|
|
disable_irq(lp->spi->irq);
|
|
disable_irq(lp->spi->irq);
|
|
set_bit(FLAG_XMIT, &lp->flags);
|
|
set_bit(FLAG_XMIT, &lp->flags);
|
|
|
|
+ cancel_delayed_work_sync(&lp->work);
|
|
reinit_completion(&lp->tx_complete);
|
|
reinit_completion(&lp->tx_complete);
|
|
adf7242_cmd(lp, CMD_RC_PHY_RDY);
|
|
adf7242_cmd(lp, CMD_RC_PHY_RDY);
|
|
adf7242_clear_irqstat(lp);
|
|
adf7242_clear_irqstat(lp);
|
|
@@ -952,6 +975,7 @@ static irqreturn_t adf7242_isr(int irq, void *data)
|
|
unsigned int xmit;
|
|
unsigned int xmit;
|
|
u8 irq1;
|
|
u8 irq1;
|
|
|
|
|
|
|
|
+ mod_delayed_work(lp->wqueue, &lp->work, msecs_to_jiffies(400));
|
|
adf7242_read_reg(lp, REG_IRQ1_SRC1, &irq1);
|
|
adf7242_read_reg(lp, REG_IRQ1_SRC1, &irq1);
|
|
|
|
|
|
if (!(irq1 & (IRQ_RX_PKT_RCVD | IRQ_CSMA_CA)))
|
|
if (!(irq1 & (IRQ_RX_PKT_RCVD | IRQ_CSMA_CA)))
|
|
@@ -1241,6 +1265,9 @@ static int adf7242_probe(struct spi_device *spi)
|
|
spi_message_add_tail(&lp->stat_xfer, &lp->stat_msg);
|
|
spi_message_add_tail(&lp->stat_xfer, &lp->stat_msg);
|
|
|
|
|
|
spi_set_drvdata(spi, lp);
|
|
spi_set_drvdata(spi, lp);
|
|
|
|
+ INIT_DELAYED_WORK(&lp->work, adf7242_rx_cal_work);
|
|
|
|
+ lp->wqueue = alloc_ordered_workqueue(dev_name(&spi->dev),
|
|
|
|
+ WQ_MEM_RECLAIM);
|
|
|
|
|
|
ret = adf7242_hw_init(lp);
|
|
ret = adf7242_hw_init(lp);
|
|
if (ret)
|
|
if (ret)
|
|
@@ -1284,6 +1311,9 @@ static int adf7242_remove(struct spi_device *spi)
|
|
if (!IS_ERR_OR_NULL(lp->debugfs_root))
|
|
if (!IS_ERR_OR_NULL(lp->debugfs_root))
|
|
debugfs_remove_recursive(lp->debugfs_root);
|
|
debugfs_remove_recursive(lp->debugfs_root);
|
|
|
|
|
|
|
|
+ cancel_delayed_work_sync(&lp->work);
|
|
|
|
+ destroy_workqueue(lp->wqueue);
|
|
|
|
+
|
|
ieee802154_unregister_hw(lp->hw);
|
|
ieee802154_unregister_hw(lp->hw);
|
|
mutex_destroy(&lp->bmux);
|
|
mutex_destroy(&lp->bmux);
|
|
ieee802154_free_hw(lp->hw);
|
|
ieee802154_free_hw(lp->hw);
|