Commit 84052541 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'counter-fixes-6.3a' of...

Merge tag 'counter-fixes-6.3a' of git://git.kernel.org/pub/scm/linux/kernel/git/wbg/counter into char-misc-linus

William writes:

First set of Counter driver fixes for 6.3

This set consists of two fixes for the 104-quad-8 driver:
	- fix a read race condition between the FLAG and CNTR registers
	  (as a result 25-bit count values are no longer supported)
	- invert condition check to report correct Index Synapse action

* tag 'counter-fixes-6.3a' of git://git.kernel.org/pub/scm/linux/kernel/git/wbg/counter:
  counter: 104-quad-8: Fix Synapse action reported for Index signals
  counter: 104-quad-8: Fix race condition between FLAG and CNTR reads
parents e8d018dd 00f4bc51
Loading
Loading
Loading
Loading
+9 −22
Original line number Diff line number Diff line
@@ -97,10 +97,6 @@ struct quad8 {
	struct quad8_reg __iomem *reg;
};

/* Borrow Toggle flip-flop */
#define QUAD8_FLAG_BT BIT(0)
/* Carry Toggle flip-flop */
#define QUAD8_FLAG_CT BIT(1)
/* Error flag */
#define QUAD8_FLAG_E BIT(4)
/* Up/Down flag */
@@ -133,6 +129,9 @@ struct quad8 {
#define QUAD8_CMR_QUADRATURE_X2 0x10
#define QUAD8_CMR_QUADRATURE_X4 0x18

/* Each Counter is 24 bits wide */
#define LS7267_CNTR_MAX GENMASK(23, 0)

static int quad8_signal_read(struct counter_device *counter,
			     struct counter_signal *signal,
			     enum counter_signal_level *level)
@@ -156,18 +155,10 @@ static int quad8_count_read(struct counter_device *counter,
{
	struct quad8 *const priv = counter_priv(counter);
	struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
	unsigned int flags;
	unsigned int borrow;
	unsigned int carry;
	unsigned long irqflags;
	int i;

	flags = ioread8(&chan->control);
	borrow = flags & QUAD8_FLAG_BT;
	carry = !!(flags & QUAD8_FLAG_CT);

	/* Borrow XOR Carry effectively doubles count range */
	*val = (unsigned long)(borrow ^ carry) << 24;
	*val = 0;

	spin_lock_irqsave(&priv->lock, irqflags);

@@ -191,8 +182,7 @@ static int quad8_count_write(struct counter_device *counter,
	unsigned long irqflags;
	int i;

	/* Only 24-bit values are supported */
	if (val > 0xFFFFFF)
	if (val > LS7267_CNTR_MAX)
		return -ERANGE;

	spin_lock_irqsave(&priv->lock, irqflags);
@@ -378,7 +368,7 @@ static int quad8_action_read(struct counter_device *counter,

	/* Handle Index signals */
	if (synapse->signal->id >= 16) {
		if (priv->preset_enable[count->id])
		if (!priv->preset_enable[count->id])
			*action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
		else
			*action = COUNTER_SYNAPSE_ACTION_NONE;
@@ -806,8 +796,7 @@ static int quad8_count_preset_write(struct counter_device *counter,
	struct quad8 *const priv = counter_priv(counter);
	unsigned long irqflags;

	/* Only 24-bit values are supported */
	if (preset > 0xFFFFFF)
	if (preset > LS7267_CNTR_MAX)
		return -ERANGE;

	spin_lock_irqsave(&priv->lock, irqflags);
@@ -834,8 +823,7 @@ static int quad8_count_ceiling_read(struct counter_device *counter,
		*ceiling = priv->preset[count->id];
		break;
	default:
		/* By default 0x1FFFFFF (25 bits unsigned) is maximum count */
		*ceiling = 0x1FFFFFF;
		*ceiling = LS7267_CNTR_MAX;
		break;
	}

@@ -850,8 +838,7 @@ static int quad8_count_ceiling_write(struct counter_device *counter,
	struct quad8 *const priv = counter_priv(counter);
	unsigned long irqflags;

	/* Only 24-bit values are supported */
	if (ceiling > 0xFFFFFF)
	if (ceiling > LS7267_CNTR_MAX)
		return -ERANGE;

	spin_lock_irqsave(&priv->lock, irqflags);