mrf24j40: async interrupt handling

This patch removes the threaded irq handling and do a hardirq instead.
We need to switch to spi_async for this step for getting the irq status
register.

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
Alexander Aring 2015-09-21 11:24:36 +02:00 коммит произвёл Marcel Holtmann
Родитель c91a301162
Коммит 374416112b
1 изменённых файлов: 40 добавлений и 53 удалений

Просмотреть файл

@ -181,8 +181,10 @@ struct mrf24j40 {
u8 rx_fifo_buf[RX_FIFO_SIZE]; u8 rx_fifo_buf[RX_FIFO_SIZE];
struct spi_transfer rx_fifo_buf_trx; struct spi_transfer rx_fifo_buf_trx;
struct mutex buffer_mutex; /* only used to protect buf */ /* isr handling for reading intstat */
u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */ struct spi_message irq_msg;
u8 irq_buf[2];
struct spi_transfer irq_trx;
}; };
/* regmap information for short address register access */ /* regmap information for short address register access */
@ -486,34 +488,6 @@ static const struct regmap_bus mrf24j40_long_regmap_bus = {
.val_format_endian_default = REGMAP_ENDIAN_BIG, .val_format_endian_default = REGMAP_ENDIAN_BIG,
}; };
static int read_short_reg(struct mrf24j40 *devrec, u8 reg, u8 *val)
{
int ret = -1;
struct spi_message msg;
struct spi_transfer xfer = {
.len = 2,
.tx_buf = devrec->buf,
.rx_buf = devrec->buf,
};
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
mutex_lock(&devrec->buffer_mutex);
devrec->buf[0] = MRF24J40_READSHORT(reg);
devrec->buf[1] = 0;
ret = spi_sync(devrec->spi, &msg);
if (ret)
dev_err(printdev(devrec),
"SPI read Failed for short register 0x%hhx\n", reg);
else
*val = devrec->buf[1];
mutex_unlock(&devrec->buffer_mutex);
return ret;
}
static void write_tx_buf_complete(void *context) static void write_tx_buf_complete(void *context)
{ {
struct mrf24j40 *devrec = context; struct mrf24j40 *devrec = context;
@ -812,16 +786,12 @@ static const struct ieee802154_ops mrf24j40_ops = {
.set_hw_addr_filt = mrf24j40_filter, .set_hw_addr_filt = mrf24j40_filter,
}; };
static irqreturn_t mrf24j40_isr(int irq, void *data) static void mrf24j40_intstat_complete(void *context)
{ {
struct mrf24j40 *devrec = data; struct mrf24j40 *devrec = context;
u8 intstat; u8 intstat = devrec->irq_buf[1];
int ret;
/* Read the interrupt status */ enable_irq(devrec->spi->irq);
ret = read_short_reg(devrec, REG_INTSTAT, &intstat);
if (ret)
goto out;
/* Check for TX complete */ /* Check for TX complete */
if (intstat & 0x1) if (intstat & 0x1)
@ -830,8 +800,23 @@ static irqreturn_t mrf24j40_isr(int irq, void *data)
/* Check for Rx */ /* Check for Rx */
if (intstat & 0x8) if (intstat & 0x8)
mrf24j40_handle_rx(devrec); mrf24j40_handle_rx(devrec);
}
static irqreturn_t mrf24j40_isr(int irq, void *data)
{
struct mrf24j40 *devrec = data;
int ret;
disable_irq_nosync(irq);
devrec->irq_buf[0] = MRF24J40_READSHORT(REG_INTSTAT);
/* Read the interrupt status */
ret = spi_async(devrec->spi, &devrec->irq_msg);
if (ret) {
enable_irq(irq);
return IRQ_NONE;
}
out:
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -978,6 +963,18 @@ mrf24j40_setup_rx_spi_messages(struct mrf24j40 *devrec)
spi_message_add_tail(&devrec->rx_lqi_trx, &devrec->rx_buf_msg); spi_message_add_tail(&devrec->rx_lqi_trx, &devrec->rx_buf_msg);
} }
static void
mrf24j40_setup_irq_spi_messages(struct mrf24j40 *devrec)
{
spi_message_init(&devrec->irq_msg);
devrec->irq_msg.context = devrec;
devrec->irq_msg.complete = mrf24j40_intstat_complete;
devrec->irq_trx.len = 2;
devrec->irq_trx.tx_buf = devrec->irq_buf;
devrec->irq_trx.rx_buf = devrec->irq_buf;
spi_message_add_tail(&devrec->irq_trx, &devrec->irq_msg);
}
static void mrf24j40_phy_setup(struct mrf24j40 *devrec) static void mrf24j40_phy_setup(struct mrf24j40 *devrec)
{ {
ieee802154_random_extended_addr(&devrec->hw->phy->perm_extended_addr); ieee802154_random_extended_addr(&devrec->hw->phy->perm_extended_addr);
@ -1008,6 +1005,7 @@ static int mrf24j40_probe(struct spi_device *spi)
mrf24j40_setup_tx_spi_messages(devrec); mrf24j40_setup_tx_spi_messages(devrec);
mrf24j40_setup_rx_spi_messages(devrec); mrf24j40_setup_rx_spi_messages(devrec);
mrf24j40_setup_irq_spi_messages(devrec);
devrec->regmap_short = devm_regmap_init_spi(spi, devrec->regmap_short = devm_regmap_init_spi(spi,
&mrf24j40_short_regmap); &mrf24j40_short_regmap);
@ -1028,32 +1026,21 @@ static int mrf24j40_probe(struct spi_device *spi)
goto err_register_device; goto err_register_device;
} }
devrec->buf = devm_kzalloc(&spi->dev, 3, GFP_KERNEL);
if (!devrec->buf)
goto err_register_device;
if (spi->max_speed_hz > MAX_SPI_SPEED_HZ) { if (spi->max_speed_hz > MAX_SPI_SPEED_HZ) {
dev_warn(&spi->dev, "spi clock above possible maximum: %d", dev_warn(&spi->dev, "spi clock above possible maximum: %d",
MAX_SPI_SPEED_HZ); MAX_SPI_SPEED_HZ);
return -EINVAL; return -EINVAL;
} }
mutex_init(&devrec->buffer_mutex);
ret = mrf24j40_hw_init(devrec); ret = mrf24j40_hw_init(devrec);
if (ret) if (ret)
goto err_register_device; goto err_register_device;
mrf24j40_phy_setup(devrec); mrf24j40_phy_setup(devrec);
ret = devm_request_threaded_irq(&spi->dev, ret = devm_request_irq(&spi->dev, spi->irq, mrf24j40_isr,
spi->irq, IRQF_TRIGGER_LOW, dev_name(&spi->dev),
NULL, devrec);
mrf24j40_isr,
IRQF_TRIGGER_LOW|IRQF_ONESHOT,
dev_name(&spi->dev),
devrec);
if (ret) { if (ret) {
dev_err(printdev(devrec), "Unable to get IRQ"); dev_err(printdev(devrec), "Unable to get IRQ");
goto err_register_device; goto err_register_device;