From: Sasha Levin Date: Sat, 1 Oct 2022 22:03:37 +0000 (-0400) Subject: Fixes for 5.19 X-Git-Tag: v5.19.13~59 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=352109195be2e794aa7c5f72d987f62834898809;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.19 Signed-off-by: Sasha Levin --- diff --git a/queue-5.19/counter-104-quad-8-fix-skipped-irq-lines-during-even.patch b/queue-5.19/counter-104-quad-8-fix-skipped-irq-lines-during-even.patch new file mode 100644 index 00000000000..1ab709438e6 --- /dev/null +++ b/queue-5.19/counter-104-quad-8-fix-skipped-irq-lines-during-even.patch @@ -0,0 +1,54 @@ +From 0065390921085a7d416a5333356bf6264a309d76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 07:20:56 -0400 +Subject: counter: 104-quad-8: Fix skipped IRQ lines during events + configuration + +From: William Breathitt Gray + +[ Upstream commit 2bc54aaa65d2126ae629919175708a28ce7ef06e ] + +IRQ trigger configuration is skipped if it has already been set before; +however, the IRQ line still needs to be OR'd to irq_enabled because +irq_enabled is reset for every events_configure call. This patch moves +the irq_enabled OR operation update to before the irq_trigger check so +that IRQ line enablement is not skipped. + +Fixes: c95cc0d95702 ("counter: 104-quad-8: Fix persistent enabled events bug") +Cc: stable +Link: https://lore.kernel.org/r/20220815122301.2750-1-william.gray@linaro.org/ +Signed-off-by: William Breathitt Gray +Link: https://lore.kernel.org/r/179eed11eaf225dbd908993b510df0c8f67b1230.1663844776.git.william.gray@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/counter/104-quad-8.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c +index 62c2b7ac4339..4407203e0c9b 100644 +--- a/drivers/counter/104-quad-8.c ++++ b/drivers/counter/104-quad-8.c +@@ -449,6 +449,9 @@ static int quad8_events_configure(struct counter_device *counter) + return -EINVAL; + } + ++ /* Enable IRQ line */ ++ irq_enabled |= BIT(event_node->channel); ++ + /* Skip configuration if it is the same as previously set */ + if (priv->irq_trigger[event_node->channel] == next_irq_trigger) + continue; +@@ -462,9 +465,6 @@ static int quad8_events_configure(struct counter_device *counter) + priv->irq_trigger[event_node->channel] << 3; + iowrite8(QUAD8_CTR_IOR | ior_cfg, + &priv->reg->channel[event_node->channel].control); +- +- /* Enable IRQ line */ +- irq_enabled |= BIT(event_node->channel); + } + + iowrite8(irq_enabled, &priv->reg->index_interrupt); +-- +2.35.1 + diff --git a/queue-5.19/counter-104-quad-8-implement-and-utilize-register-st.patch b/queue-5.19/counter-104-quad-8-implement-and-utilize-register-st.patch new file mode 100644 index 00000000000..73158784305 --- /dev/null +++ b/queue-5.19/counter-104-quad-8-implement-and-utilize-register-st.patch @@ -0,0 +1,504 @@ +From 5ea881f1eafbc400c3fd912ad3f5e0e6e3713e03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Jul 2022 12:07:14 -0400 +Subject: counter: 104-quad-8: Implement and utilize register structures + +From: William Breathitt Gray + +[ Upstream commit daae1ee572d1f99daddef26afe6c6fc7aeea741d ] + +Reduce magic numbers and improve code readability by implementing and +utilizing named register data structures. + +Link: https://lore.kernel.org/r/20220707171709.36010-1-william.gray@linaro.org/ +Cc: Syed Nayyar Waris +Tested-by: Fred Eckert +Reviewed-by: Jonathan Cameron +Signed-off-by: William Breathitt Gray +Link: https://lore.kernel.org/r/285fdc7c03892251f50bdbf2c28c19998243a6a3.1657813472.git.william.gray@linaro.org +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 2bc54aaa65d2 ("counter: 104-quad-8: Fix skipped IRQ lines during events configuration") +Signed-off-by: Sasha Levin +--- + drivers/counter/104-quad-8.c | 166 ++++++++++++++++++++--------------- + 1 file changed, 93 insertions(+), 73 deletions(-) + +diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c +index 43dde9abfdcf..62c2b7ac4339 100644 +--- a/drivers/counter/104-quad-8.c ++++ b/drivers/counter/104-quad-8.c +@@ -33,6 +33,36 @@ MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers"); + + #define QUAD8_NUM_COUNTERS 8 + ++/** ++ * struct channel_reg - channel register structure ++ * @data: Count data ++ * @control: Channel flags and control ++ */ ++struct channel_reg { ++ u8 data; ++ u8 control; ++}; ++ ++/** ++ * struct quad8_reg - device register structure ++ * @channel: quadrature counter data and control ++ * @interrupt_status: channel interrupt status ++ * @channel_oper: enable/reset counters and interrupt functions ++ * @index_interrupt: enable channel interrupts ++ * @reserved: reserved for Factory Use ++ * @index_input_levels: index signal logical input level ++ * @cable_status: differential encoder cable status ++ */ ++struct quad8_reg { ++ struct channel_reg channel[QUAD8_NUM_COUNTERS]; ++ u8 interrupt_status; ++ u8 channel_oper; ++ u8 index_interrupt; ++ u8 reserved[3]; ++ u8 index_input_levels; ++ u8 cable_status; ++}; ++ + /** + * struct quad8 - device private data structure + * @lock: lock to prevent clobbering device states during R/W ops +@@ -48,7 +78,7 @@ MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers"); + * @synchronous_mode: array of index function synchronous mode configurations + * @index_polarity: array of index function polarity configurations + * @cable_fault_enable: differential encoder cable status enable configurations +- * @base: base port address of the device ++ * @reg: I/O address offset for the device registers + */ + struct quad8 { + spinlock_t lock; +@@ -63,14 +93,9 @@ struct quad8 { + unsigned int synchronous_mode[QUAD8_NUM_COUNTERS]; + unsigned int index_polarity[QUAD8_NUM_COUNTERS]; + unsigned int cable_fault_enable; +- void __iomem *base; ++ struct quad8_reg __iomem *reg; + }; + +-#define QUAD8_REG_INTERRUPT_STATUS 0x10 +-#define QUAD8_REG_CHAN_OP 0x11 +-#define QUAD8_REG_INDEX_INTERRUPT 0x12 +-#define QUAD8_REG_INDEX_INPUT_LEVELS 0x16 +-#define QUAD8_DIFF_ENCODER_CABLE_STATUS 0x17 + /* Borrow Toggle flip-flop */ + #define QUAD8_FLAG_BT BIT(0) + /* Carry Toggle flip-flop */ +@@ -118,8 +143,7 @@ static int quad8_signal_read(struct counter_device *counter, + if (signal->id < 16) + return -EINVAL; + +- state = ioread8(priv->base + QUAD8_REG_INDEX_INPUT_LEVELS) & +- BIT(signal->id - 16); ++ state = ioread8(&priv->reg->index_input_levels) & BIT(signal->id - 16); + + *level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW; + +@@ -130,14 +154,14 @@ static int quad8_count_read(struct counter_device *counter, + struct counter_count *count, u64 *val) + { + struct quad8 *const priv = counter_priv(counter); +- void __iomem *const base_offset = priv->base + 2 * count->id; ++ 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(base_offset + 1); ++ flags = ioread8(&chan->control); + borrow = flags & QUAD8_FLAG_BT; + carry = !!(flags & QUAD8_FLAG_CT); + +@@ -148,10 +172,10 @@ static int quad8_count_read(struct counter_device *counter, + + /* Reset Byte Pointer; transfer Counter to Output Latch */ + iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT, +- base_offset + 1); ++ &chan->control); + + for (i = 0; i < 3; i++) +- *val |= (unsigned long)ioread8(base_offset) << (8 * i); ++ *val |= (unsigned long)ioread8(&chan->data) << (8 * i); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -162,7 +186,7 @@ static int quad8_count_write(struct counter_device *counter, + struct counter_count *count, u64 val) + { + struct quad8 *const priv = counter_priv(counter); +- void __iomem *const base_offset = priv->base + 2 * count->id; ++ struct channel_reg __iomem *const chan = priv->reg->channel + count->id; + unsigned long irqflags; + int i; + +@@ -173,27 +197,27 @@ static int quad8_count_write(struct counter_device *counter, + spin_lock_irqsave(&priv->lock, irqflags); + + /* Reset Byte Pointer */ +- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); + + /* Counter can only be set via Preset Register */ + for (i = 0; i < 3; i++) +- iowrite8(val >> (8 * i), base_offset); ++ iowrite8(val >> (8 * i), &chan->data); + + /* Transfer Preset Register to Counter */ +- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, &chan->control); + + /* Reset Byte Pointer */ +- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); + + /* Set Preset Register back to original value */ + val = priv->preset[count->id]; + for (i = 0; i < 3; i++) +- iowrite8(val >> (8 * i), base_offset); ++ iowrite8(val >> (8 * i), &chan->data); + + /* Reset Borrow, Carry, Compare, and Sign flags */ +- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control); + /* Reset Error flag */ +- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -246,7 +270,7 @@ static int quad8_function_write(struct counter_device *counter, + unsigned int *const quadrature_mode = priv->quadrature_mode + id; + unsigned int *const scale = priv->quadrature_scale + id; + unsigned int *const synchronous_mode = priv->synchronous_mode + id; +- void __iomem *const base_offset = priv->base + 2 * id + 1; ++ u8 __iomem *const control = &priv->reg->channel[id].control; + unsigned long irqflags; + unsigned int mode_cfg; + unsigned int idr_cfg; +@@ -266,7 +290,7 @@ static int quad8_function_write(struct counter_device *counter, + if (*synchronous_mode) { + *synchronous_mode = 0; + /* Disable synchronous function mode */ +- iowrite8(QUAD8_CTR_IDR | idr_cfg, base_offset); ++ iowrite8(QUAD8_CTR_IDR | idr_cfg, control); + } + } else { + *quadrature_mode = 1; +@@ -292,7 +316,7 @@ static int quad8_function_write(struct counter_device *counter, + } + + /* Load mode configuration to Counter Mode Register */ +- iowrite8(QUAD8_CTR_CMR | mode_cfg, base_offset); ++ iowrite8(QUAD8_CTR_CMR | mode_cfg, control); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -305,7 +329,7 @@ static int quad8_direction_read(struct counter_device *counter, + { + const struct quad8 *const priv = counter_priv(counter); + unsigned int ud_flag; +- void __iomem *const flag_addr = priv->base + 2 * count->id + 1; ++ u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control; + + /* U/D flag: nonzero = up, zero = down */ + ud_flag = ioread8(flag_addr) & QUAD8_FLAG_UD; +@@ -402,7 +426,6 @@ static int quad8_events_configure(struct counter_device *counter) + struct counter_event_node *event_node; + unsigned int next_irq_trigger; + unsigned long ior_cfg; +- void __iomem *base_offset; + + spin_lock_irqsave(&priv->lock, irqflags); + +@@ -437,14 +460,14 @@ static int quad8_events_configure(struct counter_device *counter) + ior_cfg = priv->ab_enable[event_node->channel] | + priv->preset_enable[event_node->channel] << 1 | + priv->irq_trigger[event_node->channel] << 3; +- base_offset = priv->base + 2 * event_node->channel + 1; +- iowrite8(QUAD8_CTR_IOR | ior_cfg, base_offset); ++ iowrite8(QUAD8_CTR_IOR | ior_cfg, ++ &priv->reg->channel[event_node->channel].control); + + /* Enable IRQ line */ + irq_enabled |= BIT(event_node->channel); + } + +- iowrite8(irq_enabled, priv->base + QUAD8_REG_INDEX_INTERRUPT); ++ iowrite8(irq_enabled, &priv->reg->index_interrupt); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -508,7 +531,7 @@ static int quad8_index_polarity_set(struct counter_device *counter, + { + struct quad8 *const priv = counter_priv(counter); + const size_t channel_id = signal->id - 16; +- void __iomem *const base_offset = priv->base + 2 * channel_id + 1; ++ u8 __iomem *const control = &priv->reg->channel[channel_id].control; + unsigned long irqflags; + unsigned int idr_cfg = index_polarity << 1; + +@@ -519,7 +542,7 @@ static int quad8_index_polarity_set(struct counter_device *counter, + priv->index_polarity[channel_id] = index_polarity; + + /* Load Index Control configuration to Index Control Register */ +- iowrite8(QUAD8_CTR_IDR | idr_cfg, base_offset); ++ iowrite8(QUAD8_CTR_IDR | idr_cfg, control); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -549,7 +572,7 @@ static int quad8_synchronous_mode_set(struct counter_device *counter, + { + struct quad8 *const priv = counter_priv(counter); + const size_t channel_id = signal->id - 16; +- void __iomem *const base_offset = priv->base + 2 * channel_id + 1; ++ u8 __iomem *const control = &priv->reg->channel[channel_id].control; + unsigned long irqflags; + unsigned int idr_cfg = synchronous_mode; + +@@ -566,7 +589,7 @@ static int quad8_synchronous_mode_set(struct counter_device *counter, + priv->synchronous_mode[channel_id] = synchronous_mode; + + /* Load Index Control configuration to Index Control Register */ +- iowrite8(QUAD8_CTR_IDR | idr_cfg, base_offset); ++ iowrite8(QUAD8_CTR_IDR | idr_cfg, control); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -614,7 +637,7 @@ static int quad8_count_mode_write(struct counter_device *counter, + struct quad8 *const priv = counter_priv(counter); + unsigned int count_mode; + unsigned int mode_cfg; +- void __iomem *const base_offset = priv->base + 2 * count->id + 1; ++ u8 __iomem *const control = &priv->reg->channel[count->id].control; + unsigned long irqflags; + + /* Map Generic Counter count mode to 104-QUAD-8 count mode */ +@@ -648,7 +671,7 @@ static int quad8_count_mode_write(struct counter_device *counter, + mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3; + + /* Load mode configuration to Counter Mode Register */ +- iowrite8(QUAD8_CTR_CMR | mode_cfg, base_offset); ++ iowrite8(QUAD8_CTR_CMR | mode_cfg, control); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -669,7 +692,7 @@ static int quad8_count_enable_write(struct counter_device *counter, + struct counter_count *count, u8 enable) + { + struct quad8 *const priv = counter_priv(counter); +- void __iomem *const base_offset = priv->base + 2 * count->id; ++ u8 __iomem *const control = &priv->reg->channel[count->id].control; + unsigned long irqflags; + unsigned int ior_cfg; + +@@ -681,7 +704,7 @@ static int quad8_count_enable_write(struct counter_device *counter, + priv->irq_trigger[count->id] << 3; + + /* Load I/O control configuration */ +- iowrite8(QUAD8_CTR_IOR | ior_cfg, base_offset + 1); ++ iowrite8(QUAD8_CTR_IOR | ior_cfg, control); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -697,9 +720,9 @@ static int quad8_error_noise_get(struct counter_device *counter, + struct counter_count *count, u32 *noise_error) + { + const struct quad8 *const priv = counter_priv(counter); +- void __iomem *const base_offset = priv->base + 2 * count->id + 1; ++ u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control; + +- *noise_error = !!(ioread8(base_offset) & QUAD8_FLAG_E); ++ *noise_error = !!(ioread8(flag_addr) & QUAD8_FLAG_E); + + return 0; + } +@@ -717,17 +740,17 @@ static int quad8_count_preset_read(struct counter_device *counter, + static void quad8_preset_register_set(struct quad8 *const priv, const int id, + const unsigned int preset) + { +- void __iomem *const base_offset = priv->base + 2 * id; ++ struct channel_reg __iomem *const chan = priv->reg->channel + id; + int i; + + priv->preset[id] = preset; + + /* Reset Byte Pointer */ +- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); + + /* Set Preset Register */ + for (i = 0; i < 3; i++) +- iowrite8(preset >> (8 * i), base_offset); ++ iowrite8(preset >> (8 * i), &chan->data); + } + + static int quad8_count_preset_write(struct counter_device *counter, +@@ -816,7 +839,7 @@ static int quad8_count_preset_enable_write(struct counter_device *counter, + u8 preset_enable) + { + struct quad8 *const priv = counter_priv(counter); +- void __iomem *const base_offset = priv->base + 2 * count->id + 1; ++ u8 __iomem *const control = &priv->reg->channel[count->id].control; + unsigned long irqflags; + unsigned int ior_cfg; + +@@ -831,7 +854,7 @@ static int quad8_count_preset_enable_write(struct counter_device *counter, + priv->irq_trigger[count->id] << 3; + + /* Load I/O control configuration to Input / Output Control Register */ +- iowrite8(QUAD8_CTR_IOR | ior_cfg, base_offset); ++ iowrite8(QUAD8_CTR_IOR | ior_cfg, control); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -858,7 +881,7 @@ static int quad8_signal_cable_fault_read(struct counter_device *counter, + } + + /* Logic 0 = cable fault */ +- status = ioread8(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); ++ status = ioread8(&priv->reg->cable_status); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -899,8 +922,7 @@ static int quad8_signal_cable_fault_enable_write(struct counter_device *counter, + /* Enable is active low in Differential Encoder Cable Status register */ + cable_fault_enable = ~priv->cable_fault_enable; + +- iowrite8(cable_fault_enable, +- priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); ++ iowrite8(cable_fault_enable, &priv->reg->cable_status); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -924,7 +946,7 @@ static int quad8_signal_fck_prescaler_write(struct counter_device *counter, + { + struct quad8 *const priv = counter_priv(counter); + const size_t channel_id = signal->id / 2; +- void __iomem *const base_offset = priv->base + 2 * channel_id; ++ struct channel_reg __iomem *const chan = priv->reg->channel + channel_id; + unsigned long irqflags; + + spin_lock_irqsave(&priv->lock, irqflags); +@@ -932,12 +954,12 @@ static int quad8_signal_fck_prescaler_write(struct counter_device *counter, + priv->fck_prescaler[channel_id] = prescaler; + + /* Reset Byte Pointer */ +- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); + + /* Set filter clock factor */ +- iowrite8(prescaler, base_offset); ++ iowrite8(prescaler, &chan->data); + iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, +- base_offset + 1); ++ &chan->control); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -1085,12 +1107,11 @@ static irqreturn_t quad8_irq_handler(int irq, void *private) + { + struct counter_device *counter = private; + struct quad8 *const priv = counter_priv(counter); +- void __iomem *const base = priv->base; + unsigned long irq_status; + unsigned long channel; + u8 event; + +- irq_status = ioread8(base + QUAD8_REG_INTERRUPT_STATUS); ++ irq_status = ioread8(&priv->reg->interrupt_status); + if (!irq_status) + return IRQ_NONE; + +@@ -1119,36 +1140,36 @@ static irqreturn_t quad8_irq_handler(int irq, void *private) + } + + /* Clear pending interrupts on device */ +- iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base + QUAD8_REG_CHAN_OP); ++ iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper); + + return IRQ_HANDLED; + } + +-static void quad8_init_counter(void __iomem *const base_offset) ++static void quad8_init_counter(struct channel_reg __iomem *const chan) + { + unsigned long i; + + /* Reset Byte Pointer */ +- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); + /* Reset filter clock factor */ +- iowrite8(0, base_offset); ++ iowrite8(0, &chan->data); + iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, +- base_offset + 1); ++ &chan->control); + /* Reset Byte Pointer */ +- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); + /* Reset Preset Register */ + for (i = 0; i < 3; i++) +- iowrite8(0x00, base_offset); ++ iowrite8(0x00, &chan->data); + /* Reset Borrow, Carry, Compare, and Sign flags */ +- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control); + /* Reset Error flag */ +- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control); + /* Binary encoding; Normal count; non-quadrature mode */ +- iowrite8(QUAD8_CTR_CMR, base_offset + 1); ++ iowrite8(QUAD8_CTR_CMR, &chan->control); + /* Disable A and B inputs; preset on index; FLG1 as Carry */ +- iowrite8(QUAD8_CTR_IOR, base_offset + 1); ++ iowrite8(QUAD8_CTR_IOR, &chan->control); + /* Disable index function; negative index polarity */ +- iowrite8(QUAD8_CTR_IDR, base_offset + 1); ++ iowrite8(QUAD8_CTR_IDR, &chan->control); + } + + static int quad8_probe(struct device *dev, unsigned int id) +@@ -1169,8 +1190,8 @@ static int quad8_probe(struct device *dev, unsigned int id) + return -ENOMEM; + priv = counter_priv(counter); + +- priv->base = devm_ioport_map(dev, base[id], QUAD8_EXTENT); +- if (!priv->base) ++ priv->reg = devm_ioport_map(dev, base[id], QUAD8_EXTENT); ++ if (!priv->reg) + return -ENOMEM; + + /* Initialize Counter device and driver data */ +@@ -1185,17 +1206,16 @@ static int quad8_probe(struct device *dev, unsigned int id) + spin_lock_init(&priv->lock); + + /* Reset Index/Interrupt Register */ +- iowrite8(0x00, priv->base + QUAD8_REG_INDEX_INTERRUPT); ++ iowrite8(0x00, &priv->reg->index_interrupt); + /* Reset all counters and disable interrupt function */ +- iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, priv->base + QUAD8_REG_CHAN_OP); ++ iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, &priv->reg->channel_oper); + /* Set initial configuration for all counters */ + for (i = 0; i < QUAD8_NUM_COUNTERS; i++) +- quad8_init_counter(priv->base + 2 * i); ++ quad8_init_counter(priv->reg->channel + i); + /* Disable Differential Encoder Cable Status for all channels */ +- iowrite8(0xFF, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); ++ iowrite8(0xFF, &priv->reg->cable_status); + /* Enable all counters and enable interrupt function */ +- iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, +- priv->base + QUAD8_REG_CHAN_OP); ++ iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper); + + err = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler, + IRQF_SHARED, counter->name, counter); +-- +2.35.1 + diff --git a/queue-5.19/counter-104-quad-8-utilize-iomap-interface.patch b/queue-5.19/counter-104-quad-8-utilize-iomap-interface.patch new file mode 100644 index 00000000000..56f65988545 --- /dev/null +++ b/queue-5.19/counter-104-quad-8-utilize-iomap-interface.patch @@ -0,0 +1,487 @@ +From 25ebedbb5ed2470217a480bf5fe7f16ccf1867ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Jul 2022 12:07:13 -0400 +Subject: counter: 104-quad-8: Utilize iomap interface + +From: William Breathitt Gray + +[ Upstream commit b6e9cded90d46b1066a1ca260d8b5ecf67787aba ] + +This driver doesn't need to access I/O ports directly via inb()/outb() +and friends. This patch abstracts such access by calling ioport_map() +to enable the use of more typical ioread8()/iowrite8() I/O memory +accessor calls. + +Link: https://lore.kernel.org/r/861c003318dce3d2bef4061711643bb04f5ec14f.1652201921.git.william.gray@linaro.org +Cc: Syed Nayyar Waris +Suggested-by: David Laight +Reviewed-by: Linus Walleij +Signed-off-by: William Breathitt Gray +Link: https://lore.kernel.org/r/e971b897cacfac4cb2eca478f5533d2875f5cadd.1657813472.git.william.gray@linaro.org +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 2bc54aaa65d2 ("counter: 104-quad-8: Fix skipped IRQ lines during events configuration") +Signed-off-by: Sasha Levin +--- + drivers/counter/104-quad-8.c | 169 ++++++++++++++++++----------------- + 1 file changed, 89 insertions(+), 80 deletions(-) + +diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c +index a17e51d65aca..43dde9abfdcf 100644 +--- a/drivers/counter/104-quad-8.c ++++ b/drivers/counter/104-quad-8.c +@@ -63,7 +63,7 @@ struct quad8 { + unsigned int synchronous_mode[QUAD8_NUM_COUNTERS]; + unsigned int index_polarity[QUAD8_NUM_COUNTERS]; + unsigned int cable_fault_enable; +- unsigned int base; ++ void __iomem *base; + }; + + #define QUAD8_REG_INTERRUPT_STATUS 0x10 +@@ -118,8 +118,8 @@ static int quad8_signal_read(struct counter_device *counter, + if (signal->id < 16) + return -EINVAL; + +- state = inb(priv->base + QUAD8_REG_INDEX_INPUT_LEVELS) +- & BIT(signal->id - 16); ++ state = ioread8(priv->base + QUAD8_REG_INDEX_INPUT_LEVELS) & ++ BIT(signal->id - 16); + + *level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW; + +@@ -130,14 +130,14 @@ static int quad8_count_read(struct counter_device *counter, + struct counter_count *count, u64 *val) + { + struct quad8 *const priv = counter_priv(counter); +- const int base_offset = priv->base + 2 * count->id; ++ void __iomem *const base_offset = priv->base + 2 * count->id; + unsigned int flags; + unsigned int borrow; + unsigned int carry; + unsigned long irqflags; + int i; + +- flags = inb(base_offset + 1); ++ flags = ioread8(base_offset + 1); + borrow = flags & QUAD8_FLAG_BT; + carry = !!(flags & QUAD8_FLAG_CT); + +@@ -147,11 +147,11 @@ static int quad8_count_read(struct counter_device *counter, + spin_lock_irqsave(&priv->lock, irqflags); + + /* Reset Byte Pointer; transfer Counter to Output Latch */ +- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT, +- base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT, ++ base_offset + 1); + + for (i = 0; i < 3; i++) +- *val |= (unsigned long)inb(base_offset) << (8 * i); ++ *val |= (unsigned long)ioread8(base_offset) << (8 * i); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -162,7 +162,7 @@ static int quad8_count_write(struct counter_device *counter, + struct counter_count *count, u64 val) + { + struct quad8 *const priv = counter_priv(counter); +- const int base_offset = priv->base + 2 * count->id; ++ void __iomem *const base_offset = priv->base + 2 * count->id; + unsigned long irqflags; + int i; + +@@ -173,27 +173,27 @@ static int quad8_count_write(struct counter_device *counter, + spin_lock_irqsave(&priv->lock, irqflags); + + /* Reset Byte Pointer */ +- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); + + /* Counter can only be set via Preset Register */ + for (i = 0; i < 3; i++) +- outb(val >> (8 * i), base_offset); ++ iowrite8(val >> (8 * i), base_offset); + + /* Transfer Preset Register to Counter */ +- outb(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, base_offset + 1); + + /* Reset Byte Pointer */ +- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); + + /* Set Preset Register back to original value */ + val = priv->preset[count->id]; + for (i = 0; i < 3; i++) +- outb(val >> (8 * i), base_offset); ++ iowrite8(val >> (8 * i), base_offset); + + /* Reset Borrow, Carry, Compare, and Sign flags */ +- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1); + /* Reset Error flag */ +- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -246,7 +246,7 @@ static int quad8_function_write(struct counter_device *counter, + unsigned int *const quadrature_mode = priv->quadrature_mode + id; + unsigned int *const scale = priv->quadrature_scale + id; + unsigned int *const synchronous_mode = priv->synchronous_mode + id; +- const int base_offset = priv->base + 2 * id + 1; ++ void __iomem *const base_offset = priv->base + 2 * id + 1; + unsigned long irqflags; + unsigned int mode_cfg; + unsigned int idr_cfg; +@@ -266,7 +266,7 @@ static int quad8_function_write(struct counter_device *counter, + if (*synchronous_mode) { + *synchronous_mode = 0; + /* Disable synchronous function mode */ +- outb(QUAD8_CTR_IDR | idr_cfg, base_offset); ++ iowrite8(QUAD8_CTR_IDR | idr_cfg, base_offset); + } + } else { + *quadrature_mode = 1; +@@ -292,7 +292,7 @@ static int quad8_function_write(struct counter_device *counter, + } + + /* Load mode configuration to Counter Mode Register */ +- outb(QUAD8_CTR_CMR | mode_cfg, base_offset); ++ iowrite8(QUAD8_CTR_CMR | mode_cfg, base_offset); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -305,10 +305,10 @@ static int quad8_direction_read(struct counter_device *counter, + { + const struct quad8 *const priv = counter_priv(counter); + unsigned int ud_flag; +- const unsigned int flag_addr = priv->base + 2 * count->id + 1; ++ void __iomem *const flag_addr = priv->base + 2 * count->id + 1; + + /* U/D flag: nonzero = up, zero = down */ +- ud_flag = inb(flag_addr) & QUAD8_FLAG_UD; ++ ud_flag = ioread8(flag_addr) & QUAD8_FLAG_UD; + + *direction = (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD : + COUNTER_COUNT_DIRECTION_BACKWARD; +@@ -402,7 +402,7 @@ static int quad8_events_configure(struct counter_device *counter) + struct counter_event_node *event_node; + unsigned int next_irq_trigger; + unsigned long ior_cfg; +- unsigned long base_offset; ++ void __iomem *base_offset; + + spin_lock_irqsave(&priv->lock, irqflags); + +@@ -438,13 +438,13 @@ static int quad8_events_configure(struct counter_device *counter) + priv->preset_enable[event_node->channel] << 1 | + priv->irq_trigger[event_node->channel] << 3; + base_offset = priv->base + 2 * event_node->channel + 1; +- outb(QUAD8_CTR_IOR | ior_cfg, base_offset); ++ iowrite8(QUAD8_CTR_IOR | ior_cfg, base_offset); + + /* Enable IRQ line */ + irq_enabled |= BIT(event_node->channel); + } + +- outb(irq_enabled, priv->base + QUAD8_REG_INDEX_INTERRUPT); ++ iowrite8(irq_enabled, priv->base + QUAD8_REG_INDEX_INTERRUPT); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -508,7 +508,7 @@ static int quad8_index_polarity_set(struct counter_device *counter, + { + struct quad8 *const priv = counter_priv(counter); + const size_t channel_id = signal->id - 16; +- const int base_offset = priv->base + 2 * channel_id + 1; ++ void __iomem *const base_offset = priv->base + 2 * channel_id + 1; + unsigned long irqflags; + unsigned int idr_cfg = index_polarity << 1; + +@@ -519,7 +519,7 @@ static int quad8_index_polarity_set(struct counter_device *counter, + priv->index_polarity[channel_id] = index_polarity; + + /* Load Index Control configuration to Index Control Register */ +- outb(QUAD8_CTR_IDR | idr_cfg, base_offset); ++ iowrite8(QUAD8_CTR_IDR | idr_cfg, base_offset); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -549,7 +549,7 @@ static int quad8_synchronous_mode_set(struct counter_device *counter, + { + struct quad8 *const priv = counter_priv(counter); + const size_t channel_id = signal->id - 16; +- const int base_offset = priv->base + 2 * channel_id + 1; ++ void __iomem *const base_offset = priv->base + 2 * channel_id + 1; + unsigned long irqflags; + unsigned int idr_cfg = synchronous_mode; + +@@ -566,7 +566,7 @@ static int quad8_synchronous_mode_set(struct counter_device *counter, + priv->synchronous_mode[channel_id] = synchronous_mode; + + /* Load Index Control configuration to Index Control Register */ +- outb(QUAD8_CTR_IDR | idr_cfg, base_offset); ++ iowrite8(QUAD8_CTR_IDR | idr_cfg, base_offset); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -614,7 +614,7 @@ static int quad8_count_mode_write(struct counter_device *counter, + struct quad8 *const priv = counter_priv(counter); + unsigned int count_mode; + unsigned int mode_cfg; +- const int base_offset = priv->base + 2 * count->id + 1; ++ void __iomem *const base_offset = priv->base + 2 * count->id + 1; + unsigned long irqflags; + + /* Map Generic Counter count mode to 104-QUAD-8 count mode */ +@@ -648,7 +648,7 @@ static int quad8_count_mode_write(struct counter_device *counter, + mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3; + + /* Load mode configuration to Counter Mode Register */ +- outb(QUAD8_CTR_CMR | mode_cfg, base_offset); ++ iowrite8(QUAD8_CTR_CMR | mode_cfg, base_offset); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -669,7 +669,7 @@ static int quad8_count_enable_write(struct counter_device *counter, + struct counter_count *count, u8 enable) + { + struct quad8 *const priv = counter_priv(counter); +- const int base_offset = priv->base + 2 * count->id; ++ void __iomem *const base_offset = priv->base + 2 * count->id; + unsigned long irqflags; + unsigned int ior_cfg; + +@@ -681,7 +681,7 @@ static int quad8_count_enable_write(struct counter_device *counter, + priv->irq_trigger[count->id] << 3; + + /* Load I/O control configuration */ +- outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1); ++ iowrite8(QUAD8_CTR_IOR | ior_cfg, base_offset + 1); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -697,9 +697,9 @@ static int quad8_error_noise_get(struct counter_device *counter, + struct counter_count *count, u32 *noise_error) + { + const struct quad8 *const priv = counter_priv(counter); +- const int base_offset = priv->base + 2 * count->id + 1; ++ void __iomem *const base_offset = priv->base + 2 * count->id + 1; + +- *noise_error = !!(inb(base_offset) & QUAD8_FLAG_E); ++ *noise_error = !!(ioread8(base_offset) & QUAD8_FLAG_E); + + return 0; + } +@@ -717,17 +717,17 @@ static int quad8_count_preset_read(struct counter_device *counter, + static void quad8_preset_register_set(struct quad8 *const priv, const int id, + const unsigned int preset) + { +- const unsigned int base_offset = priv->base + 2 * id; ++ void __iomem *const base_offset = priv->base + 2 * id; + int i; + + priv->preset[id] = preset; + + /* Reset Byte Pointer */ +- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); + + /* Set Preset Register */ + for (i = 0; i < 3; i++) +- outb(preset >> (8 * i), base_offset); ++ iowrite8(preset >> (8 * i), base_offset); + } + + static int quad8_count_preset_write(struct counter_device *counter, +@@ -816,7 +816,7 @@ static int quad8_count_preset_enable_write(struct counter_device *counter, + u8 preset_enable) + { + struct quad8 *const priv = counter_priv(counter); +- const int base_offset = priv->base + 2 * count->id + 1; ++ void __iomem *const base_offset = priv->base + 2 * count->id + 1; + unsigned long irqflags; + unsigned int ior_cfg; + +@@ -831,7 +831,7 @@ static int quad8_count_preset_enable_write(struct counter_device *counter, + priv->irq_trigger[count->id] << 3; + + /* Load I/O control configuration to Input / Output Control Register */ +- outb(QUAD8_CTR_IOR | ior_cfg, base_offset); ++ iowrite8(QUAD8_CTR_IOR | ior_cfg, base_offset); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -858,7 +858,7 @@ static int quad8_signal_cable_fault_read(struct counter_device *counter, + } + + /* Logic 0 = cable fault */ +- status = inb(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); ++ status = ioread8(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -899,7 +899,8 @@ static int quad8_signal_cable_fault_enable_write(struct counter_device *counter, + /* Enable is active low in Differential Encoder Cable Status register */ + cable_fault_enable = ~priv->cable_fault_enable; + +- outb(cable_fault_enable, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); ++ iowrite8(cable_fault_enable, ++ priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -923,7 +924,7 @@ static int quad8_signal_fck_prescaler_write(struct counter_device *counter, + { + struct quad8 *const priv = counter_priv(counter); + const size_t channel_id = signal->id / 2; +- const int base_offset = priv->base + 2 * channel_id; ++ void __iomem *const base_offset = priv->base + 2 * channel_id; + unsigned long irqflags; + + spin_lock_irqsave(&priv->lock, irqflags); +@@ -931,12 +932,12 @@ static int quad8_signal_fck_prescaler_write(struct counter_device *counter, + priv->fck_prescaler[channel_id] = prescaler; + + /* Reset Byte Pointer */ +- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); + + /* Set filter clock factor */ +- outb(prescaler, base_offset); +- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, +- base_offset + 1); ++ iowrite8(prescaler, base_offset); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, ++ base_offset + 1); + + spin_unlock_irqrestore(&priv->lock, irqflags); + +@@ -1084,12 +1085,12 @@ static irqreturn_t quad8_irq_handler(int irq, void *private) + { + struct counter_device *counter = private; + struct quad8 *const priv = counter_priv(counter); +- const unsigned long base = priv->base; ++ void __iomem *const base = priv->base; + unsigned long irq_status; + unsigned long channel; + u8 event; + +- irq_status = inb(base + QUAD8_REG_INTERRUPT_STATUS); ++ irq_status = ioread8(base + QUAD8_REG_INTERRUPT_STATUS); + if (!irq_status) + return IRQ_NONE; + +@@ -1118,17 +1119,43 @@ static irqreturn_t quad8_irq_handler(int irq, void *private) + } + + /* Clear pending interrupts on device */ +- outb(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base + QUAD8_REG_CHAN_OP); ++ iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base + QUAD8_REG_CHAN_OP); + + return IRQ_HANDLED; + } + ++static void quad8_init_counter(void __iomem *const base_offset) ++{ ++ unsigned long i; ++ ++ /* Reset Byte Pointer */ ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); ++ /* Reset filter clock factor */ ++ iowrite8(0, base_offset); ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, ++ base_offset + 1); ++ /* Reset Byte Pointer */ ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); ++ /* Reset Preset Register */ ++ for (i = 0; i < 3; i++) ++ iowrite8(0x00, base_offset); ++ /* Reset Borrow, Carry, Compare, and Sign flags */ ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1); ++ /* Reset Error flag */ ++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1); ++ /* Binary encoding; Normal count; non-quadrature mode */ ++ iowrite8(QUAD8_CTR_CMR, base_offset + 1); ++ /* Disable A and B inputs; preset on index; FLG1 as Carry */ ++ iowrite8(QUAD8_CTR_IOR, base_offset + 1); ++ /* Disable index function; negative index polarity */ ++ iowrite8(QUAD8_CTR_IDR, base_offset + 1); ++} ++ + static int quad8_probe(struct device *dev, unsigned int id) + { + struct counter_device *counter; + struct quad8 *priv; +- int i, j; +- unsigned int base_offset; ++ unsigned long i; + int err; + + if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) { +@@ -1142,6 +1169,10 @@ static int quad8_probe(struct device *dev, unsigned int id) + return -ENOMEM; + priv = counter_priv(counter); + ++ priv->base = devm_ioport_map(dev, base[id], QUAD8_EXTENT); ++ if (!priv->base) ++ return -ENOMEM; ++ + /* Initialize Counter device and driver data */ + counter->name = dev_name(dev); + counter->parent = dev; +@@ -1150,43 +1181,21 @@ static int quad8_probe(struct device *dev, unsigned int id) + counter->num_counts = ARRAY_SIZE(quad8_counts); + counter->signals = quad8_signals; + counter->num_signals = ARRAY_SIZE(quad8_signals); +- priv->base = base[id]; + + spin_lock_init(&priv->lock); + + /* Reset Index/Interrupt Register */ +- outb(0x00, base[id] + QUAD8_REG_INDEX_INTERRUPT); ++ iowrite8(0x00, priv->base + QUAD8_REG_INDEX_INTERRUPT); + /* Reset all counters and disable interrupt function */ +- outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); ++ iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, priv->base + QUAD8_REG_CHAN_OP); + /* Set initial configuration for all counters */ +- for (i = 0; i < QUAD8_NUM_COUNTERS; i++) { +- base_offset = base[id] + 2 * i; +- /* Reset Byte Pointer */ +- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); +- /* Reset filter clock factor */ +- outb(0, base_offset); +- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, +- base_offset + 1); +- /* Reset Byte Pointer */ +- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); +- /* Reset Preset Register */ +- for (j = 0; j < 3; j++) +- outb(0x00, base_offset); +- /* Reset Borrow, Carry, Compare, and Sign flags */ +- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1); +- /* Reset Error flag */ +- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1); +- /* Binary encoding; Normal count; non-quadrature mode */ +- outb(QUAD8_CTR_CMR, base_offset + 1); +- /* Disable A and B inputs; preset on index; FLG1 as Carry */ +- outb(QUAD8_CTR_IOR, base_offset + 1); +- /* Disable index function; negative index polarity */ +- outb(QUAD8_CTR_IDR, base_offset + 1); +- } ++ for (i = 0; i < QUAD8_NUM_COUNTERS; i++) ++ quad8_init_counter(priv->base + 2 * i); + /* Disable Differential Encoder Cable Status for all channels */ +- outb(0xFF, base[id] + QUAD8_DIFF_ENCODER_CABLE_STATUS); ++ iowrite8(0xFF, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); + /* Enable all counters and enable interrupt function */ +- outb(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base[id] + QUAD8_REG_CHAN_OP); ++ iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, ++ priv->base + QUAD8_REG_CHAN_OP); + + err = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler, + IRQF_SHARED, counter->name, counter); +-- +2.35.1 + diff --git a/queue-5.19/perf-record-fix-cpu-mask-bit-setting-for-mixed-mmaps.patch b/queue-5.19/perf-record-fix-cpu-mask-bit-setting-for-mixed-mmaps.patch new file mode 100644 index 00000000000..599923f243e --- /dev/null +++ b/queue-5.19/perf-record-fix-cpu-mask-bit-setting-for-mixed-mmaps.patch @@ -0,0 +1,60 @@ +From 57224444030ba3d24e26a125231d5b7c56fb0bd8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 15:26:11 +0300 +Subject: perf record: Fix cpu mask bit setting for mixed mmaps + +From: Adrian Hunter + +[ Upstream commit ca76d7d2812b46124291f99c9b50aaf63a936f23 ] + +With mixed per-thread and (system-wide) per-cpu maps, the "any cpu" value + -1 must be skipped when setting CPU mask bits. + +Prior to commit cbd7bfc7fd99acdd ("tools/perf: Fix out of bound access +to cpu mask array") the invalid setting went unnoticed, but since then +it causes perf record to fail with an error. + +Example: + + Before: + + $ perf record -e intel_pt// --per-thread uname + Failed to initialize parallel data streaming masks + + After: + + $ perf record -e intel_pt// --per-thread uname + Linux + [ perf record: Woken up 1 times to write data ] + [ perf record: Captured and wrote 0.068 MB perf.data ] + +Fixes: ae4f8ae16a078964 ("libperf evlist: Allow mixing per-thread and per-cpu mmaps") +Signed-off-by: Adrian Hunter +Acked-by: Namhyung Kim +Cc: Athira Rajeev +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20220915122612.81738-2-adrian.hunter@intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + tools/perf/builtin-record.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c +index 708880a1c83c..7fbc85c1da81 100644 +--- a/tools/perf/builtin-record.c ++++ b/tools/perf/builtin-record.c +@@ -3344,6 +3344,8 @@ static int record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cp + return 0; + + perf_cpu_map__for_each_cpu(cpu, idx, cpus) { ++ if (cpu.cpu == -1) ++ continue; + /* Return ENODEV is input cpu is greater than max cpu */ + if ((unsigned long)cpu.cpu > mask->nbits) + return -ENODEV; +-- +2.35.1 + diff --git a/queue-5.19/riscv-make-t-head-erratas-depend-on-mmu.patch b/queue-5.19/riscv-make-t-head-erratas-depend-on-mmu.patch new file mode 100644 index 00000000000..33cb804f753 --- /dev/null +++ b/queue-5.19/riscv-make-t-head-erratas-depend-on-mmu.patch @@ -0,0 +1,42 @@ +From c516c7a2f5d290f4c3e3b9a527a25309a5cbe793 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 17:49:32 +0200 +Subject: riscv: make t-head erratas depend on MMU + +From: Heiko Stuebner + +[ Upstream commit 2a2018c3ac84c2dc7cfbad117ce9339ea0914622 ] + +Both basic extensions of SVPBMT and ZICBOM depend on CONFIG_MMU. +Make the T-Head errata implementations of the similar functionality +also depend on it to prevent build errors. + +Fixes: a35707c3d850 ("riscv: add memory-type errata for T-Head") +Fixes: d20ec7529236 ("riscv: implement cache-management errata for T-Head SoCs") +Reported-by: kernel test robot +Signed-off-by: Heiko Stuebner +Reviewed-by: Guo Ren +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20220907154932.2858518-1-heiko@sntech.de +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + arch/riscv/Kconfig.erratas | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas +index 457ac72c9b36..e59a770b4432 100644 +--- a/arch/riscv/Kconfig.erratas ++++ b/arch/riscv/Kconfig.erratas +@@ -46,7 +46,7 @@ config ERRATA_THEAD + + config ERRATA_THEAD_PBMT + bool "Apply T-Head memory type errata" +- depends on ERRATA_THEAD && 64BIT ++ depends on ERRATA_THEAD && 64BIT && MMU + select RISCV_ALTERNATIVE_EARLY + default y + help +-- +2.35.1 + diff --git a/queue-5.19/series b/queue-5.19/series new file mode 100644 index 00000000000..6ecf5832d6f --- /dev/null +++ b/queue-5.19/series @@ -0,0 +1,6 @@ +riscv-make-t-head-erratas-depend-on-mmu.patch +tools-perf-fix-out-of-bound-access-to-cpu-mask-array.patch +perf-record-fix-cpu-mask-bit-setting-for-mixed-mmaps.patch +counter-104-quad-8-utilize-iomap-interface.patch +counter-104-quad-8-implement-and-utilize-register-st.patch +counter-104-quad-8-fix-skipped-irq-lines-during-even.patch diff --git a/queue-5.19/tools-perf-fix-out-of-bound-access-to-cpu-mask-array.patch b/queue-5.19/tools-perf-fix-out-of-bound-access-to-cpu-mask-array.patch new file mode 100644 index 00000000000..1b41f7f8cfd --- /dev/null +++ b/queue-5.19/tools-perf-fix-out-of-bound-access-to-cpu-mask-array.patch @@ -0,0 +1,139 @@ +From 02f569478c767d5365ece100794c29dca8e76eb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 19:49:29 +0530 +Subject: tools/perf: Fix out of bound access to cpu mask array + +From: Athira Rajeev + +[ Upstream commit cbd7bfc7fd99acdde58ec2b0bce990158fba1654 ] + +The cpu mask init code in "record__mmap_cpu_mask_init" function access +"bits" array part of "struct mmap_cpu_mask". The size of this array is +the value from cpu__max_cpu().cpu. This array is used to contain the +cpumask value for each cpu. While setting bit for each cpu, it calls +"set_bit" function which access index in "bits" array. + +If we provide a command line option to -C which is greater than the +number of CPU's present in the system, the set_bit could access an array +member which is out-of the array size. This is because currently, there +is no boundary check for the CPU. This will result in seg fault: + +<<>> + ./perf record -C 12341234 ls + Perf can support 2048 CPUs. Consider raising MAX_NR_CPUS + Segmentation fault (core dumped) +<<>> + +Debugging with gdb, points to function flow as below: + +<<>> + set_bit + record__mmap_cpu_mask_init + record__init_thread_default_masks + record__init_thread_masks + cmd_record +<<>> + +Fix this by adding boundary check for the array. + +After the patch: + +<<>> +./perf record -C 12341234 ls + Perf can support 2048 CPUs. Consider raising MAX_NR_CPUS + Failed to initialize parallel data streaming masks +<<>> + +With this fix, if -C is given a non-exsiting CPU, perf +record will fail with: + +<<>> + ./perf record -C 50 ls + Failed to initialize parallel data streaming masks +<<>> + +Reported-by: Nageswara R Sastry +Signed-off-by: Athira Jajeev +Tested-by: Arnaldo Carvalho de Melo +Tested-by: Nageswara R Sastry +Cc: Jiri Olsa +Cc: Kajol Jain +Cc: Madhavan Srinivasan +Cc: Michael Ellerman +Cc: linuxppc-dev@lists.ozlabs.org +Link: https://lore.kernel.org/r/20220905141929.7171-2-atrajeev@linux.vnet.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: ca76d7d2812b ("perf record: Fix cpu mask bit setting for mixed mmaps") +Signed-off-by: Sasha Levin +--- + tools/perf/builtin-record.c | 26 ++++++++++++++++++++------ + 1 file changed, 20 insertions(+), 6 deletions(-) + +diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c +index 68c878b4e5e4..708880a1c83c 100644 +--- a/tools/perf/builtin-record.c ++++ b/tools/perf/builtin-record.c +@@ -3335,16 +3335,22 @@ static struct option __record_options[] = { + + struct option *record_options = __record_options; + +-static void record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cpu_map *cpus) ++static int record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cpu_map *cpus) + { + struct perf_cpu cpu; + int idx; + + if (cpu_map__is_dummy(cpus)) +- return; ++ return 0; + +- perf_cpu_map__for_each_cpu(cpu, idx, cpus) ++ perf_cpu_map__for_each_cpu(cpu, idx, cpus) { ++ /* Return ENODEV is input cpu is greater than max cpu */ ++ if ((unsigned long)cpu.cpu > mask->nbits) ++ return -ENODEV; + set_bit(cpu.cpu, mask->bits); ++ } ++ ++ return 0; + } + + static int record__mmap_cpu_mask_init_spec(struct mmap_cpu_mask *mask, const char *mask_spec) +@@ -3356,7 +3362,9 @@ static int record__mmap_cpu_mask_init_spec(struct mmap_cpu_mask *mask, const cha + return -ENOMEM; + + bitmap_zero(mask->bits, mask->nbits); +- record__mmap_cpu_mask_init(mask, cpus); ++ if (record__mmap_cpu_mask_init(mask, cpus)) ++ return -ENODEV; ++ + perf_cpu_map__put(cpus); + + return 0; +@@ -3438,7 +3446,12 @@ static int record__init_thread_masks_spec(struct record *rec, struct perf_cpu_ma + pr_err("Failed to allocate CPUs mask\n"); + return ret; + } +- record__mmap_cpu_mask_init(&cpus_mask, cpus); ++ ++ ret = record__mmap_cpu_mask_init(&cpus_mask, cpus); ++ if (ret) { ++ pr_err("Failed to init cpu mask\n"); ++ goto out_free_cpu_mask; ++ } + + ret = record__thread_mask_alloc(&full_mask, cpu__max_cpu().cpu); + if (ret) { +@@ -3679,7 +3692,8 @@ static int record__init_thread_default_masks(struct record *rec, struct perf_cpu + if (ret) + return ret; + +- record__mmap_cpu_mask_init(&rec->thread_masks->maps, cpus); ++ if (record__mmap_cpu_mask_init(&rec->thread_masks->maps, cpus)) ++ return -ENODEV; + + rec->nr_threads = 1; + +-- +2.35.1 +