Skip to content

Commit b468033

Browse files
author
Wolfram Sang
committed
Merge tag 'i2c-host-fixes-6.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux into i2c/for-current
This tag includes a nice fix in the PNX driver that has been pending for a long time. Piotr has replaced a potential lock in the interrupt context with a more efficient and straightforward handling of the timeout signaling.
2 parents 22a40d1 + f63b94b commit b468033

File tree

1 file changed

+10
-38
lines changed

1 file changed

+10
-38
lines changed

drivers/i2c/busses/i2c-pnx.c

Lines changed: 10 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include <linux/ioport.h>
1616
#include <linux/delay.h>
1717
#include <linux/i2c.h>
18-
#include <linux/timer.h>
1918
#include <linux/completion.h>
2019
#include <linux/platform_device.h>
2120
#include <linux/io.h>
@@ -32,7 +31,6 @@ struct i2c_pnx_mif {
3231
int ret; /* Return value */
3332
int mode; /* Interface mode */
3433
struct completion complete; /* I/O completion */
35-
struct timer_list timer; /* Timeout */
3634
u8 * buf; /* Data buffer */
3735
int len; /* Length of data buffer */
3836
int order; /* RX Bytes to order via TX */
@@ -117,24 +115,6 @@ static inline int wait_reset(struct i2c_pnx_algo_data *data)
117115
return (timeout <= 0);
118116
}
119117

120-
static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
121-
{
122-
struct timer_list *timer = &alg_data->mif.timer;
123-
unsigned long expires = msecs_to_jiffies(alg_data->timeout);
124-
125-
if (expires <= 1)
126-
expires = 2;
127-
128-
del_timer_sync(timer);
129-
130-
dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %lu jiffies.\n",
131-
jiffies, expires);
132-
133-
timer->expires = jiffies + expires;
134-
135-
add_timer(timer);
136-
}
137-
138118
/**
139119
* i2c_pnx_start - start a device
140120
* @slave_addr: slave address
@@ -259,8 +239,6 @@ static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
259239
~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
260240
I2C_REG_CTL(alg_data));
261241

262-
del_timer_sync(&alg_data->mif.timer);
263-
264242
dev_dbg(&alg_data->adapter.dev,
265243
"%s(): Waking up xfer routine.\n",
266244
__func__);
@@ -276,8 +254,6 @@ static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
276254
~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
277255
I2C_REG_CTL(alg_data));
278256

279-
/* Stop timer. */
280-
del_timer_sync(&alg_data->mif.timer);
281257
dev_dbg(&alg_data->adapter.dev,
282258
"%s(): Waking up xfer routine after zero-xfer.\n",
283259
__func__);
@@ -364,8 +340,6 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
364340
mcntrl_drmie | mcntrl_daie);
365341
iowrite32(ctl, I2C_REG_CTL(alg_data));
366342

367-
/* Kill timer. */
368-
del_timer_sync(&alg_data->mif.timer);
369343
complete(&alg_data->mif.complete);
370344
}
371345
}
@@ -400,8 +374,6 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
400374
mcntrl_drmie);
401375
iowrite32(ctl, I2C_REG_CTL(alg_data));
402376

403-
/* Stop timer, to prevent timeout. */
404-
del_timer_sync(&alg_data->mif.timer);
405377
complete(&alg_data->mif.complete);
406378
} else if (stat & mstatus_nai) {
407379
/* Slave did not acknowledge, generate a STOP */
@@ -419,8 +391,6 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
419391
/* Our return value. */
420392
alg_data->mif.ret = -EIO;
421393

422-
/* Stop timer, to prevent timeout. */
423-
del_timer_sync(&alg_data->mif.timer);
424394
complete(&alg_data->mif.complete);
425395
} else {
426396
/*
@@ -453,9 +423,8 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
453423
return IRQ_HANDLED;
454424
}
455425

456-
static void i2c_pnx_timeout(struct timer_list *t)
426+
static void i2c_pnx_timeout(struct i2c_pnx_algo_data *alg_data)
457427
{
458-
struct i2c_pnx_algo_data *alg_data = from_timer(alg_data, t, mif.timer);
459428
u32 ctl;
460429

461430
dev_err(&alg_data->adapter.dev,
@@ -472,7 +441,6 @@ static void i2c_pnx_timeout(struct timer_list *t)
472441
iowrite32(ctl, I2C_REG_CTL(alg_data));
473442
wait_reset(alg_data);
474443
alg_data->mif.ret = -EIO;
475-
complete(&alg_data->mif.complete);
476444
}
477445

478446
static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data)
@@ -514,6 +482,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
514482
struct i2c_msg *pmsg;
515483
int rc = 0, completed = 0, i;
516484
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
485+
unsigned long time_left;
517486
u32 stat;
518487

519488
dev_dbg(&alg_data->adapter.dev,
@@ -548,7 +517,6 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
548517
dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n",
549518
__func__, alg_data->mif.mode, alg_data->mif.len);
550519

551-
i2c_pnx_arm_timer(alg_data);
552520

553521
/* initialize the completion var */
554522
init_completion(&alg_data->mif.complete);
@@ -564,7 +532,10 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
564532
break;
565533

566534
/* Wait for completion */
567-
wait_for_completion(&alg_data->mif.complete);
535+
time_left = wait_for_completion_timeout(&alg_data->mif.complete,
536+
alg_data->timeout);
537+
if (time_left == 0)
538+
i2c_pnx_timeout(alg_data);
568539

569540
if (!(rc = alg_data->mif.ret))
570541
completed++;
@@ -653,7 +624,10 @@ static int i2c_pnx_probe(struct platform_device *pdev)
653624
alg_data->adapter.algo_data = alg_data;
654625
alg_data->adapter.nr = pdev->id;
655626

656-
alg_data->timeout = I2C_PNX_TIMEOUT_DEFAULT;
627+
alg_data->timeout = msecs_to_jiffies(I2C_PNX_TIMEOUT_DEFAULT);
628+
if (alg_data->timeout <= 1)
629+
alg_data->timeout = 2;
630+
657631
#ifdef CONFIG_OF
658632
alg_data->adapter.dev.of_node = of_node_get(pdev->dev.of_node);
659633
if (pdev->dev.of_node) {
@@ -673,8 +647,6 @@ static int i2c_pnx_probe(struct platform_device *pdev)
673647
if (IS_ERR(alg_data->clk))
674648
return PTR_ERR(alg_data->clk);
675649

676-
timer_setup(&alg_data->mif.timer, i2c_pnx_timeout, 0);
677-
678650
snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name),
679651
"%s", pdev->name);
680652

0 commit comments

Comments
 (0)