Re: [tip:x86/urgent 3/3] arch/x86/kernel/apic/apic.c:1182:6: warning: the address of 'x2apic_enabled' will always evaluate as 'true'
Thomas Gleixner writes: > On Tue, 27 Aug 2019, Bandan Das wrote: >> kbuild test robot writes: >> >> > tree: >> > https://kernel.googlesource.com/pub/scm/linux/kernel/git/tip/tip.git >> > x86/urgent >> > head: cfa16294b1c5b320c0a0e1cac37c784b92366c87 >> > commit: cfa16294b1c5b320c0a0e1cac37c784b92366c87 [3/3] x86/apic: Include >> > the LDR when clearing out APIC registers >> > config: i386-defconfig (attached as .config) >> > compiler: gcc-7 (Debian 7.4.0-10) 7.4.0 >> > reproduce: >> > git checkout cfa16294b1c5b320c0a0e1cac37c784b92366c87 >> > # save the attached .config to linux build tree >> > make ARCH=i386 >> > >> > If you fix the issue, kindly add following tag >> > Reported-by: kbuild test robot >> > >> > All warnings (new ones prefixed by >>): >> > >> >arch/x86/kernel/apic/apic.c: In function 'clear_local_APIC': >> >>> arch/x86/kernel/apic/apic.c:1182:6: warning: the address of >> >>> 'x2apic_enabled' will always evaluate as 'true' [-Waddress] >> > if (!x2apic_enabled) { >> > ^ >> Thomas, I apologize for the typo here. This is the x2apic_enabled() function. >> Should I respin ? > > > https://lkml.kernel.org/r/156684295076.23440.2192639697586451635.tip-bot2@tip-bot2 > > You have that mail in your inbox .. Ah, thanks!
Re: [RESEND PATCH v3 10/20] mtd: spi-nor: Rework the SPI NOR lock/unlock logic
On 08/27/2019 09:36 AM, Vignesh Raghavendra wrote: >> +nor->flags = SNOR_F_HAS_LOCK; > This is okay for now. But Perhaps its safer to do: > > nor->flags |= SNOR_F_HAS_LOCK; > > so that we don't override flags if set earlier than > spi_nor_manufacturer_init_params(). I see that patch 20/20 does indeed > present one such case wrt atmel/Xilinix flashes IIUC yep, you're right, I'll update as you suggested. Thanks!
[PATCH 1/2] gpio: gpio-pca953x.c: Correct type of reg_direction
The type of reg_direction needs to match the type of the regmap, which is u8. Signed-off-by: David Jander --- drivers/gpio/gpio-pca953x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 378b206d2dc9..30072a570bc2 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -604,7 +604,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) u8 new_irqs; int level, i; u8 invert_irq_mask[MAX_BANK]; - int reg_direction[MAX_BANK]; + u8 reg_direction[MAX_BANK]; regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction, NBANK(chip)); @@ -679,7 +679,7 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) bool pending_seen = false; bool trigger_seen = false; u8 trigger[MAX_BANK]; - int reg_direction[MAX_BANK]; + u8 reg_direction[MAX_BANK]; int ret, i; if (chip->driver_data & PCA_PCAL) { @@ -768,7 +768,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, { struct i2c_client *client = chip->client; struct irq_chip *irq_chip = &chip->irq_chip; - int reg_direction[MAX_BANK]; + u8 reg_direction[MAX_BANK]; int ret, i; if (!client->irq) -- 2.19.1
[PATCH 2/2] gpio: pca953x.c: Use pca953x_read_regs instead of regmap_bulk_read
The register number needs to be translated for chips with more than 8 ports. This patch fixes a bug causing all chips with more than 8 GPIO pins to not work correctly. Signed-off-by: David Jander --- drivers/gpio/gpio-pca953x.c | 9 +++-- 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 30072a570bc2..48fea4c68e8d 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -606,8 +606,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) u8 invert_irq_mask[MAX_BANK]; u8 reg_direction[MAX_BANK]; - regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction, -NBANK(chip)); + pca953x_read_regs(chip, chip->regs->direction, reg_direction); if (chip->driver_data & PCA_PCAL) { /* Enable latch on interrupt-enabled inputs */ @@ -710,8 +709,7 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) return false; /* Remove output pins from the equation */ - regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction, -NBANK(chip)); + pca953x_read_regs(chip, chip->regs->direction, reg_direction); for (i = 0; i < NBANK(chip); i++) cur_stat[i] &= reg_direction[i]; @@ -789,8 +787,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, * interrupt. We have to rely on the previous read for * this purpose. */ - regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction, -NBANK(chip)); + pca953x_read_regs(chip, chip->regs->direction, reg_direction); for (i = 0; i < NBANK(chip); i++) chip->irq_stat[i] &= reg_direction[i]; mutex_init(&chip->irq_lock); -- 2.19.1
Re: [PATCH v5 2/4] iio: imu: st_lsm6sdx: move register definitions to sensor_settings struct
On 21.08.19 15:25, Martin Kepplinger wrote: > Move some register definitions to the per-device array of struct > st_lsm6dsx_sensor_settings in order to simplify adding new sensor > devices to the driver. > > Also, remove completely unused register definitions. > > Signed-off-by: Martin Kepplinger > Acked-by: Lorenzo Bianconi > --- > drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 6 > drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 31 ++-- > 2 files changed, 28 insertions(+), 9 deletions(-) > I just notices the commit message header typo "st_lsm6sdx" should be "st_lsm6dsx" of course. If you can still rebase/force-push to testing, would you be able to fix that? If it's too far out there already, so be it :) sorry for the typo, and thanks for adding "-imu" yourself where applicable. thanks, martin
Re: [tip:x86/urgent 3/3] arch/x86/kernel/apic/apic.c:1182:6: warning: the address of 'x2apic_enabled' will always evaluate as 'true'
On Tue, 27 Aug 2019, Bandan Das wrote: > kbuild test robot writes: > > > tree: > > https://kernel.googlesource.com/pub/scm/linux/kernel/git/tip/tip.git > > x86/urgent > > head: cfa16294b1c5b320c0a0e1cac37c784b92366c87 > > commit: cfa16294b1c5b320c0a0e1cac37c784b92366c87 [3/3] x86/apic: Include > > the LDR when clearing out APIC registers > > config: i386-defconfig (attached as .config) > > compiler: gcc-7 (Debian 7.4.0-10) 7.4.0 > > reproduce: > > git checkout cfa16294b1c5b320c0a0e1cac37c784b92366c87 > > # save the attached .config to linux build tree > > make ARCH=i386 > > > > If you fix the issue, kindly add following tag > > Reported-by: kbuild test robot > > > > All warnings (new ones prefixed by >>): > > > >arch/x86/kernel/apic/apic.c: In function 'clear_local_APIC': > >>> arch/x86/kernel/apic/apic.c:1182:6: warning: the address of > >>> 'x2apic_enabled' will always evaluate as 'true' [-Waddress] > > if (!x2apic_enabled) { > > ^ > Thomas, I apologize for the typo here. This is the x2apic_enabled() function. > Should I respin ? https://lkml.kernel.org/r/156684295076.23440.2192639697586451635.tip-bot2@tip-bot2 You have that mail in your inbox ..
[PATCH] pci: get pm runtime ref before resetting bus
When I inject a PCIE Fatal error into a mellanox netdevice, 'dmesg' shows the device is recovered successfully, but 'lspci' didn't show the device. I checked the configuration space of the slot where the netdevice is inserted and found out the bit 'PCI_BRIDGE_CTL_BUS_RESET' is set. Later, I found out it is because this bit is saved in 'saved_config_space' of 'struct pci_dev' when 'pci_pm_runtime_suspend()' is called. And 'PCI_BRIDGE_CTL_BUS_RESET' is set every time we restore the configuration sapce. This patch use 'pm_runtime_get' to avoid saving the configuration space of the bridge when the bus is being reset. Signed-off-by: Xiongfeng Wang --- drivers/pci/pci.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9cae66c..0079f0a 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4546,6 +4546,9 @@ void pci_reset_secondary_bus(struct pci_dev *dev) { u16 ctrl; + /* avoid wrongly saving 'PCI_BRIDGE_CTL_BUS_RESET' */ + pm_runtime_get(&dev->dev); + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl); ctrl |= PCI_BRIDGE_CTL_BUS_RESET; pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl); @@ -4567,6 +4570,8 @@ void pci_reset_secondary_bus(struct pci_dev *dev) * but we don't make use of them yet. */ ssleep(1); + + pm_runtime_put(&dev->dev); } void __weak pcibios_reset_secondary_bus(struct pci_dev *dev) -- 1.7.12.4
Re: [tip:x86/urgent 3/3] arch/x86/kernel/apic/apic.c:1182:6: warning: the address of 'x2apic_enabled' will always evaluate as 'true'
kbuild test robot writes: > tree: https://kernel.googlesource.com/pub/scm/linux/kernel/git/tip/tip.git > x86/urgent > head: cfa16294b1c5b320c0a0e1cac37c784b92366c87 > commit: cfa16294b1c5b320c0a0e1cac37c784b92366c87 [3/3] x86/apic: Include the > LDR when clearing out APIC registers > config: i386-defconfig (attached as .config) > compiler: gcc-7 (Debian 7.4.0-10) 7.4.0 > reproduce: > git checkout cfa16294b1c5b320c0a0e1cac37c784b92366c87 > # save the attached .config to linux build tree > make ARCH=i386 > > If you fix the issue, kindly add following tag > Reported-by: kbuild test robot > > All warnings (new ones prefixed by >>): > >arch/x86/kernel/apic/apic.c: In function 'clear_local_APIC': >>> arch/x86/kernel/apic/apic.c:1182:6: warning: the address of >>> 'x2apic_enabled' will always evaluate as 'true' [-Waddress] > if (!x2apic_enabled) { > ^ Thomas, I apologize for the typo here. This is the x2apic_enabled() function. Should I respin ? > > vim +1182 arch/x86/kernel/apic/apic.c > > 1142 > 1143/* > 1144 * Local APIC start and shutdown > 1145 */ > 1146 > 1147/** > 1148 * clear_local_APIC - shutdown the local APIC > 1149 * > 1150 * This is called, when a CPU is disabled and before rebooting, > so the state of > 1151 * the local APIC has no dangling leftovers. Also used to > cleanout any BIOS > 1152 * leftovers during boot. > 1153 */ > 1154void clear_local_APIC(void) > 1155{ > 1156int maxlvt; > 1157u32 v; > 1158 > 1159/* APIC hasn't been mapped yet */ > 1160if (!x2apic_mode && !apic_phys) > 1161return; > 1162 > 1163maxlvt = lapic_get_maxlvt(); > 1164/* > 1165 * Masking an LVT entry can trigger a local APIC error > 1166 * if the vector is zero. Mask LVTERR first to prevent > this. > 1167 */ > 1168if (maxlvt >= 3) { > 1169v = ERROR_APIC_VECTOR; /* any non-zero vector > will do */ > 1170apic_write(APIC_LVTERR, v | APIC_LVT_MASKED); > 1171} > 1172/* > 1173 * Careful: we have to set masks only first to deassert > 1174 * any level-triggered sources. > 1175 */ > 1176v = apic_read(APIC_LVTT); > 1177apic_write(APIC_LVTT, v | APIC_LVT_MASKED); > 1178v = apic_read(APIC_LVT0); > 1179apic_write(APIC_LVT0, v | APIC_LVT_MASKED); > 1180v = apic_read(APIC_LVT1); > 1181apic_write(APIC_LVT1, v | APIC_LVT_MASKED); >> 1182 if (!x2apic_enabled) { > 1183v = apic_read(APIC_LDR) & ~APIC_LDR_MASK; > 1184apic_write(APIC_LDR, v); > 1185} > 1186if (maxlvt >= 4) { > 1187v = apic_read(APIC_LVTPC); > 1188apic_write(APIC_LVTPC, v | APIC_LVT_MASKED); > 1189} > 1190 > 1191/* lets not touch this if we didn't frob it */ > 1192#ifdef CONFIG_X86_THERMAL_VECTOR > 1193if (maxlvt >= 5) { > 1194v = apic_read(APIC_LVTTHMR); > 1195apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED); > 1196} > 1197#endif > 1198#ifdef CONFIG_X86_MCE_INTEL > 1199if (maxlvt >= 6) { > 1200v = apic_read(APIC_LVTCMCI); > 1201if (!(v & APIC_LVT_MASKED)) > 1202apic_write(APIC_LVTCMCI, v | > APIC_LVT_MASKED); > 1203} > 1204#endif > 1205 > 1206/* > 1207 * Clean APIC state for other OSs: > 1208 */ > 1209apic_write(APIC_LVTT, APIC_LVT_MASKED); > 1210apic_write(APIC_LVT0, APIC_LVT_MASKED); > 1211apic_write(APIC_LVT1, APIC_LVT_MASKED); > 1212if (maxlvt >= 3) > 1213apic_write(APIC_LVTERR, APIC_LVT_MASKED); > 1214if (maxlvt >= 4) > 1215apic_write(APIC_LVTPC, APIC_LVT_MASKED); > 1216 > 1217/* Integrated APIC (!82489DX) ? */ > 1218if (lapic_is_integrated()) { > 1219if (maxlvt > 3) > 1220/* Clear ESR due to Pentium errata 3AP > and 11AP */ > 1221apic_write(APIC_ESR, 0); > 1222apic_read(APIC_ESR); > 1223} > 1224
Re: [PATCH] powerpc: Perform a bounds check in arch_add_memory
On Tue, 2019-08-27 at 08:28 +0200, Michal Hocko wrote: > On Tue 27-08-19 15:20:46, Alastair D'Silva wrote: > > From: Alastair D'Silva > > > > It is possible for firmware to allocate memory ranges outside > > the range of physical memory that we support (MAX_PHYSMEM_BITS). > > Doesn't that count as a FW bug? Do you have any evidence of that in > the > field? Just wondering... > Not outside our lab, but OpenCAPI attached LPC memory is assigned addresses based on the slot/NPU it is connected to. These addresses prior to: 4ffe713b7587 ("powerpc/mm: Increase the max addressable memory to 2PB") were inaccessible and resulted in bogus sections - see our discussion on 'mm: Trigger bug on if a section is not found in __section_nr'. Doing this check here was your suggestion :) It's entirely possible that a similar problem will occur in the future, and it's cheap to guard against, which is why I've added this. -- Alastair D'Silva Open Source Developer Linux Technology Centre, IBM Australia mob: 0423 762 819
[PATCH v2] kbuild: change *FLAGS_.o to take the path relative to $(obj)
Kbuild provides per-file compiler flag addition/removal: CFLAGS_.o CFLAGS_REMOVE_.o AFLAGS_.o AFLAGS_REMOVE_.o CPPFLAGS_.lds HOSTCFLAGS_.o HOSTCXXFLAGS_.o The is the filename of the target with its directory and suffix stripped. This syntax comes into a trouble when two files with the same name appear in one Makefile, for example: obj-y += foo.o obj-y += dir/foo.o CFLAGS_foo.o := Here, the applies to both foo.o and dir/foo.o The real world problem is: scripts/kconfig/util.c scripts/kconfig/lxdialog/util.c Both files are compiled into scripts/kconfig/mconf, but only the latter should be given with additional flags for ncurses. It is more sensible to use the relative path to the Makefile, like this: obj-y += foo.o CFLAGS_foo.o := obj-y += dir/foo.o CFLAGS_dir/foo.o := The $* variable is replaced with the stem ('%') part in a pattern rule. In other words, this only works for pattern rules. Signed-off-by: Masahiro Yamada Acked-by: Marc Zyngier --- Changes in v2: - Fix build errors for gpu drivers arch/arm/kvm/Makefile | 5 ++-- arch/x86/entry/vdso/Makefile | 3 +- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 6 ++-- drivers/gpu/drm/amd/display/dc/dcn20/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dml/Makefile | 17 +-- drivers/gpu/drm/amd/display/dc/dsc/Makefile | 7 ++--- drivers/gpu/drm/i915/Makefile | 2 +- scripts/Makefile.host | 30 +-- scripts/Makefile.lib | 10 +++ scripts/kconfig/Makefile | 8 ++--- 10 files changed, 44 insertions(+), 46 deletions(-) diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile index 531e59f5be9c..b76b75bd9e00 100644 --- a/arch/arm/kvm/Makefile +++ b/arch/arm/kvm/Makefile @@ -8,13 +8,14 @@ ifeq ($(plus_virt),+virt) plus_virt_def := -DREQUIRES_VIRT=1 endif +KVM := ../../../virt/kvm + ccflags-y += -I $(srctree)/$(src) -I $(srctree)/virt/kvm/arm/vgic -CFLAGS_arm.o := $(plus_virt_def) +CFLAGS_$(KVM)/arm/arm.o := $(plus_virt_def) AFLAGS_init.o := -Wa,-march=armv7-a$(plus_virt) AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt) -KVM := ../../../virt/kvm kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o obj-$(CONFIG_KVM_ARM_HOST) += hyp/ diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile index 8df549138193..0f2154106d01 100644 --- a/arch/x86/entry/vdso/Makefile +++ b/arch/x86/entry/vdso/Makefile @@ -89,6 +89,7 @@ $(vobjs): KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS) $(RETPOLINE_CFLAGS # CFLAGS_REMOVE_vdso-note.o = -pg CFLAGS_REMOVE_vclock_gettime.o = -pg +CFLAGS_REMOVE_vdso32/vclock_gettime.o = -pg CFLAGS_REMOVE_vgetcpu.o = -pg CFLAGS_REMOVE_vvar.o = -pg @@ -128,7 +129,7 @@ $(obj)/%.so: $(obj)/%.so.dbg FORCE $(obj)/vdsox32.so.dbg: $(obj)/vdsox32.lds $(vobjx32s) FORCE $(call if_changed,vdso_and_check) -CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds) +CPPFLAGS_vdso32/vdso32.lds = $(CPPFLAGS_vdso.lds) VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -soname linux-gate.so.1 targets += vdso32/vdso32.lds diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 95f332ee3e7e..d930df63772c 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -32,9 +32,9 @@ endif calcs_ccflags := -mhard-float -msse $(cc_stack_align) -CFLAGS_dcn_calcs.o := $(calcs_ccflags) -CFLAGS_dcn_calc_auto.o := $(calcs_ccflags) -CFLAGS_dcn_calc_math.o := $(calcs_ccflags) -Wno-tautological-compare +CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calcs.o := $(calcs_ccflags) +CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calc_auto.o := $(calcs_ccflags) +CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calc_math.o := $(calcs_ccflags) -Wno-tautological-compare BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile index e9721a906592..83635ad9124e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile @@ -16,7 +16,7 @@ else ifneq ($(call cc-option, -mstack-alignment=16),) cc_stack_align := -mstack-alignment=16 endif -CFLAGS_dcn20_resource.o := -mhard-float -msse $(cc_stack_align) +CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o := -mhard-float -msse $(cc_stack_align) AMD_DAL_DCN20 = $(addprefix $(AMDDALPATH)/dc/dcn20/,$(DCN20)) diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 0bb7a20675c4..83792e2c0f0e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -32,19 +32,16 @@ endif dml_ccflags := -mhard-float -msse $(cc_stack_align) -CFLAGS_display_mode_lib.o := $(dml_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(d
Re: [RESEND PATCH v3 10/20] mtd: spi-nor: Rework the SPI NOR lock/unlock logic
On 26/08/19 5:38 PM, tudor.amba...@microchip.com wrote: > From: Boris Brezillon > > Add the SNOR_F_HAS_LOCK flag and set it when SPI_NOR_HAS_LOCK is set > in the flash_info entry or when it's a Micron or ST flash. > > Move the locking hooks in a separate struct so that we have just > one field to update when we change the locking implementation. > > Signed-off-by: Boris Brezillon > [tudor.amba...@microchip.com: use ->default_init() hook, introduce > spi_nor_late_init_params(), set ops in nor->params] > Signed-off-by: Tudor Ambarus > --- > v3: no changes, clear_sr_bp() is handled in the last patch of the > series. > Reviewed-by: Vignesh Raghavendra One suggestion below: > drivers/mtd/spi-nor/spi-nor.c | 50 > --- > include/linux/mtd/spi-nor.h | 23 ++-- > 2 files changed, 53 insertions(+), 20 deletions(-) > > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c > index 235e82a121a1..3f997797fa9d 100644 > --- a/drivers/mtd/spi-nor/spi-nor.c > +++ b/drivers/mtd/spi-nor/spi-nor.c > @@ -1598,6 +1598,12 @@ static int stm_is_locked(struct spi_nor *nor, loff_t > ofs, uint64_t len) > return stm_is_locked_sr(nor, ofs, len, status); > } > > +static const struct spi_nor_locking_ops stm_locking_ops = { > + .lock = stm_lock, > + .unlock = stm_unlock, > + .is_locked = stm_is_locked, > +}; > + > static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) > { > struct spi_nor *nor = mtd_to_spi_nor(mtd); > @@ -1607,7 +1613,7 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t > ofs, uint64_t len) > if (ret) > return ret; > > - ret = nor->flash_lock(nor, ofs, len); > + ret = nor->params.locking_ops->lock(nor, ofs, len); > > spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); > return ret; > @@ -1622,7 +1628,7 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t > ofs, uint64_t len) > if (ret) > return ret; > > - ret = nor->flash_unlock(nor, ofs, len); > + ret = nor->params.locking_ops->unlock(nor, ofs, len); > > spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); > return ret; > @@ -1637,7 +1643,7 @@ static int spi_nor_is_locked(struct mtd_info *mtd, > loff_t ofs, uint64_t len) > if (ret) > return ret; > > - ret = nor->flash_is_locked(nor, ofs, len); > + ret = nor->params.locking_ops->is_locked(nor, ofs, len); > > spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); > return ret; > @@ -4148,6 +4154,7 @@ static void macronix_set_default_init(struct spi_nor > *nor) > > static void st_micron_set_default_init(struct spi_nor *nor) > { > + nor->flags = SNOR_F_HAS_LOCK; This is okay for now. But Perhaps its safer to do: nor->flags |= SNOR_F_HAS_LOCK; so that we don't override flags if set earlier than spi_nor_manufacturer_init_params(). I see that patch 20/20 does indeed present one such case wrt atmel/Xilinix flashes IIUC Regards Vignesh > nor->params.quad_enable = NULL; > nor->params.set_4byte = st_micron_set_4byte; > } > @@ -4292,6 +4299,23 @@ static void spi_nor_info_init_params(struct spi_nor > *nor) > } > > /** > + * spi_nor_late_init_params() - Late initialization of default flash > parameters. > + * @nor: pointer to a 'struct spi_nor' > + * > + * Used to set default flash parameters and settings when the > ->default_init() > + * hook or the SFDP parser let voids. > + */ > +static void spi_nor_late_init_params(struct spi_nor *nor) > +{ > + /* > + * NOR protection support. When locking_ops are not provided, we pick > + * the default ones. > + */ > + if (nor->flags & SNOR_F_HAS_LOCK && !nor->params.locking_ops) > + nor->params.locking_ops = &stm_locking_ops; > +} > + > +/** > * spi_nor_init_params() - Initialize the flash's parameters and settings. > * @nor: pointer to a 'struct spi-nor'. > * > @@ -4316,6 +4340,10 @@ static void spi_nor_info_init_params(struct spi_nor > *nor) > *Please not that there is a ->post_bfpt() fixup hook that can overwrite > the > *flash parameters and settings imediately after parsing the Basic Flash > *Parameter Table. > + * > + * 4/ Late default flash parameters initialization, used when the > + * ->default_init() hook or the SFDP parser do not set specific params. > + * spi_nor_late_init_params() > */ > static void spi_nor_init_params(struct spi_nor *nor) > { > @@ -4326,6 +4354,8 @@ static void spi_nor_init_params(struct spi_nor *nor) > if ((nor->info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) && > !(nor->info->flags & SPI_NOR_SKIP_SFDP)) > spi_nor_sfdp_init_params(nor); > + > + spi_nor_late_init_params(nor); > } > > static int spi_nor_select_read(struct spi_nor *nor, > @@ -4707,6 +4737,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, > if
Re: Linux-next-20190823: x86_64/i386: prot_hsymlinks.c:325: Failed to run cmd: useradd hsym
On Tue, 27 Aug 2019 at 04:42, Jan Stancek wrote: > > > - Original Message - > > On Mon, 2019-08-26 at 10:38 -0400, Jan Stancek wrote: > > No change with that patch, Same for me. > but following one fixes it for me: Works for me. Thanks for the fix patch. > > diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c > index 20b3717cd7ca..56cefa0ab804 100644 > --- a/fs/nfs/pagelist.c > +++ b/fs/nfs/pagelist.c > @@ -590,7 +590,7 @@ static void nfs_pgio_rpcsetup(struct nfs_pgio_header *hdr, > } > > hdr->res.fattr = &hdr->fattr; > - hdr->res.count = 0; > + hdr->res.count = count; > hdr->res.eof = 0; > hdr->res.verf= &hdr->verf; > nfs_fattr_init(&hdr->fattr); > > which is functionally revert of "NFS: Fix initialisation of I/O result struct > in nfs_pgio_rpcsetup". > > This hunk caught my eye, could res.eof == 0 explain those I/O errors? > /* Emulate the eof flag, which isn't normally needed in NFSv2 > * as it is guaranteed to always return the file attributes > */ > if (hdr->args.offset + hdr->res.count >= hdr->res.fattr->size) > hdr->res.eof = 1; - Naresh
[PATCH v2 48/49] Input: atmel_mxt_ts: Implement synchronization during various operation
From: Sanjeev Chugh There could be scope of race conditions when sysfs is being handled and at the same time, device removal is occurring. For example, we don't want the device removal to begin if the Atmel device cfg update is going on or firmware update is going on. In such cases, wait for device update to be completed before the removal continues. Thread Thread 2: = = mxt_update_fw_store() mxt_remove() mutex_lock(&data->lock) ... mxt_initialize()//Tries to acquire lock request_firmware_nowait() mutex_lock(&data->lock) ... ==>waits for lock() ... . ... . mutex_unlock(&data->lock) . //Gets lock and proceeds mxt_free_input_device(); ... mutex_unlock(&data->lock) //Frees atmel driver data kfree(data) If the request_firmware_nowait() completes after the driver removal, and callback is triggered. But kernel crashes since the module is already removed. This commit adds state machine to serialize such scenarios. Signed-off-by: Sanjeev Chugh Signed-off-by: Bhuvanesh Surachari Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 222 --- 1 file changed, 196 insertions(+), 26 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 63ff8a211a90..a461220cd336 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -224,6 +224,7 @@ enum t100_type { #define MXT_POWERON_DELAY 150 /* msec */ #define MXT_BOOTLOADER_WAIT36E5/* 1 minute */ #define MXT_WATCHDOG_TIMEOUT 1000/* msec */ +#define MXT_CONFIG_TIMEOUT 1000/* msec */ /* Command to unlock bootloader */ #define MXT_UNLOCK_CMD_MSB 0xaa @@ -247,6 +248,20 @@ enum t100_type { #define DEBUG_MSG_MAX 200 +enum device_state { + MXT_STATE_READY, + MXT_STATE_UPDATING_CONFIG, + MXT_STATE_UPDATING_CONFIG_ASYNC, + MXT_STATE_START, + MXT_STATE_STOP, + MXT_STATE_GOING_AWAY +}; + +enum mxt_cmd { + UPDATE_CFG, + UPDATE_FW +}; + struct mxt_info { u8 family_id; u8 variant_id; @@ -426,11 +441,15 @@ struct mxt_data { /* Indicates whether device is in suspend */ bool suspended; - /* Indicates whether device is updating configuration */ - bool updating_config; + struct mutex lock; unsigned int mtu; bool t25_status; + + /* State handling for probe/remove, open/close and config update */ + enum device_state e_state; + + struct completion update_cfg_completion; }; struct mxt_vb2_buffer { @@ -1654,6 +1673,7 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) struct mxt_data *data = dev_id; int ret; + mutex_lock(&data->lock); data->mxt_status.intp_triggered = true; if (data->in_bootloader) { @@ -1681,6 +1701,8 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) exit: data->mxt_status.intp_triggered = false; + mutex_unlock(&data->lock); + return ret; } @@ -2261,6 +2283,8 @@ static void mxt_free_object_table(struct mxt_data *data) video_unregister_device(&data->dbg.vdev); v4l2_device_unregister(&data->dbg.v4l2); #endif + mutex_lock(&data->lock); + data->object_table = NULL; kfree(data->info); data->info = NULL; @@ -2290,6 +2314,8 @@ static void mxt_free_object_table(struct mxt_data *data) data->T100_reportid_min = 0; data->T100_reportid_max = 0; data->max_reportid = 0; + + mutex_unlock(&data->lock); } static int mxt_parse_object_table(struct mxt_data *data, @@ -2971,8 +2997,15 @@ static int mxt_configure_objects(struct mxt_data *data, static void mxt_config_cb(const struct firmware *cfg, void *ctx) { + struct mxt_data *data = ctx; + mxt_configure_objects(ctx, cfg); release_firmware(cfg); + complete(&data->update_cfg_completion); + mutex_lock(&data->lock); + if (data->e_state != MXT_STATE_GOING_AWAY) + data->e_state = MXT_STATE_READY; + mutex_unlock(&data->lock); } static int mxt_bootloader_status(struct mxt_data *data) @@ -3085,6 +3118,15 @@ static int mxt_initialize(struct mxt_data *data) goto err_free_sysfs; if (data->cfg_name) { +
[PATCH v2 49/49] Input: atmel_mxt_ts - Fix compilation warning
fix "make W=1" compilation warnings from Atmel driver as per the compilation logs. Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index a461220cd336..115c94d3f0d4 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -2046,7 +2046,7 @@ static int mxt_prepare_cfg_mem(struct mxt_data *data, struct mxt_cfg *cfg) byte_offset = reg + i - cfg->start_ofs; - if (byte_offset >= 0 && byte_offset < cfg->mem_size) { + if (byte_offset < cfg->mem_size) { *(cfg->mem + byte_offset) = val; } else { dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n", -- 2.19.2
[PATCH v2 43/49] Input: Atmel: handle ReportID "0x00" while processing T5 messages
From: Deepak Das ReportID "0x00" is reserved by Atmel and should not be used by any Atmel touch controller. reportID is the first byte retrieved from T5 message payload. Currently Atmel driver continues to process the T5 messages even if the reportID "0x00" is returned by Touch Controller. This commit modifies Atmel touch driver to return -EINVAL if ReportID "0x00" is received while processing T5 messages. Signed-off-by: Deepak Das Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 41d92d765aa2..b6f50fee3695 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -76,6 +76,7 @@ #define MXT_PROCI_TOUCHSEQUENCELOGGER 93 #define MXT_TOUCH_MULTITOUCHSCREEN_T100 100 #define MXT_PROCI_ACTIVESTYLUS_T107107 +#define MXT_RPTID_RESERVED 0 /* MXT_GEN_MESSAGE_T5 object */ #define MXT_RPTID_NOMSG0xff @@ -1381,6 +1382,11 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message) u8 report_id = message[0]; bool dump = data->debug_enabled; + if (report_id == MXT_RPTID_RESERVED) { + dev_err(&data->client->dev, + "Received Reserved ReportID 0x00\n"); + return -EINVAL; + } if (report_id == MXT_RPTID_NOMSG) return 0; @@ -1451,6 +1457,8 @@ static int mxt_read_and_process_messages(struct mxt_data *data, u8 count) ret = mxt_proc_message(data, data->msg_buf + data->T5_msg_size * i); + if (ret < 0) + return ret; if (ret == 1) num_valid++; } -- 2.19.2
[PATCH v2 44/49] Input: Atmel: use T44 object to process T5 messages
From: Deepak Das T44 object returns the count of valid T5 messages in the buffer. According to atmel, this count should be the main criteria to read the number of T5 messages. Following is the statement from atmel confirming the same :- "For the readout of messages we recommend to stop after the last message is read out from the buffer. One way to identify the amount of new messages is to read T44. The other way is to monitor the /CHG line which indicates independent of mode 0 or mode 1 if there are still data in the buffer. 0xFF indicates that there is no message pending anymore, but it is not recommended to use this as the main criteria to control the data transfer." This commit modifies the logic to readout the T5 messages on the basis of T44 object. Signed-off-by: Deepak Das Signed-off-by: Sanjeev Chugh Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 55 +++- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index b6f50fee3695..58e54eb45cf0 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1486,7 +1486,7 @@ static u8 mxt_max_msg_read_count(struct mxt_data *data, u8 max_T5_msg_count) return min(T5_msg_count_limit, max_T5_msg_count); } -static irqreturn_t mxt_process_messages_t44(struct mxt_data *data) +static int mxt_process_messages_t44(struct mxt_data *data) { struct device *dev = &data->client->dev; int ret; @@ -1499,7 +1499,7 @@ static irqreturn_t mxt_process_messages_t44(struct mxt_data *data) data->T5_msg_size + 1, data->msg_buf); if (ret) { dev_err(dev, "Failed to read T44 and T5 (%d)\n", ret); - return IRQ_NONE; + return ret; } T5_msg_count = data->msg_buf[0]; @@ -1509,7 +1509,7 @@ static irqreturn_t mxt_process_messages_t44(struct mxt_data *data) * Mode 0. It results in unnecessary I2C operations but it is benign. */ if (!T5_msg_count) - return IRQ_NONE; + return processed_valid; if (T5_msg_count > data->max_reportid) { dev_warn(dev, "T44 count %d exceeded max report id\n", @@ -1521,12 +1521,14 @@ static irqreturn_t mxt_process_messages_t44(struct mxt_data *data) ret = mxt_proc_message(data, data->msg_buf + 1); if (ret < 0) { dev_warn(dev, "Unexpected invalid message\n"); - return IRQ_NONE; + return ret; } total_pending = T5_msg_count - 1; - if (!total_pending) + if (!total_pending) { + processed_valid = 1; goto end; + } /* Process remaining messages if necessary */ T5_msg_count = mxt_max_msg_read_count(data, total_pending); @@ -1550,7 +1552,7 @@ static irqreturn_t mxt_process_messages_t44(struct mxt_data *data) data->update_input = false; } - return IRQ_HANDLED; + return processed_valid; } static int mxt_process_messages_until_invalid(struct mxt_data *data) @@ -1580,7 +1582,7 @@ static int mxt_process_messages_until_invalid(struct mxt_data *data) return -EBUSY; } -static irqreturn_t mxt_process_messages(struct mxt_data *data) +static int mxt_process_messages(struct mxt_data *data) { int total_handled, num_handled; u8 count = data->last_message_count; @@ -1591,7 +1593,7 @@ static irqreturn_t mxt_process_messages(struct mxt_data *data) /* include final invalid message */ total_handled = mxt_read_and_process_messages(data, count + 1); if (total_handled < 0) - return IRQ_NONE; + return total_handled; /* if there were invalid messages, then we are done */ else if (total_handled <= count) goto update_count; @@ -1600,7 +1602,7 @@ static irqreturn_t mxt_process_messages(struct mxt_data *data) do { num_handled = mxt_read_and_process_messages(data, 2); if (num_handled < 0) - return IRQ_NONE; + return num_handled; total_handled += num_handled; @@ -1616,12 +1618,13 @@ static irqreturn_t mxt_process_messages(struct mxt_data *data) data->update_input = false; } - return IRQ_HANDLED; + return total_handled; } static irqreturn_t mxt_interrupt(int irq, void *dev_id) { struct mxt_data *data = dev_id; + int ret; if (data->in_bootloader) { complete(&data->chg_completion); @@ -1629,17 +1632,22 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) if (data->flash && &data->flash->work) cancel_delayed_work_sync(&data->flash->work); - return IRQ_R
[PATCH v2 41/49] Input: Atmel: improve error handling in mxt_update_cfg()
From: Deepak Das mxt_update_cfg() failed to propagate the error code from mxt_init_t7_power_cfg() so return the error code. Signed-off-by: Deepak Das Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 59533753a431..716b91e6fd66 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -2183,7 +2183,9 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) dev_info(dev, "Config successfully updated\n"); /* T7 config may have changed */ - mxt_init_t7_power_cfg(data); + ret = mxt_init_t7_power_cfg(data); + if (ret) + dev_warn(dev, "Power Config failed to update\n"); release_mem: kfree(cfg.mem); -- 2.19.2
[PATCH v2 46/49] input: touchscreen: atmel_mxt_ts: Added sysfs entry for touchscreen status
From: Naveen Chakka To know the current communication status of the touch controller during runtime, sysfs interface is added sysfs interface: /sys/class/i2c-dev/i2c-*/device/*/touch_dev_stat Executing the above sysfs interface provides two output values 1)Status of the touch device value 0 represents device is inactive value 1 represents device is active 2)Error counter value represents the number of times device in inactive since last read Signed-off-by: Naveen Chakka Signed-off-by: Sanjeev Chugh Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 109 +-- 1 file changed, 102 insertions(+), 7 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 1187e21a67e4..5a112dfe30e4 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -222,6 +223,7 @@ enum t100_type { #define MXT_CHG_DELAY 100 /* msec */ #define MXT_POWERON_DELAY 150 /* msec */ #define MXT_BOOTLOADER_WAIT36E5/* 1 minute */ +#define MXT_WATCHDOG_TIMEOUT 1000/* msec */ /* Command to unlock bootloader */ #define MXT_UNLOCK_CMD_MSB 0xaa @@ -317,6 +319,12 @@ struct mxt_flash { struct delayed_work work; }; +struct mxt_statusinfo { + bool dev_status; + bool intp_triggered; + u32 error_count; +}; + /* Each client has this additional data */ struct mxt_data { struct i2c_client *client; @@ -372,6 +380,9 @@ struct mxt_data { const char *pcfg_name; const char *input_name; struct mxt_flash *flash; + struct work_struct watchdog_work; + struct timer_list watchdog_timer; + struct mxt_statusinfo mxt_status; /* Cached parameters from object table */ u16 T5_address; @@ -1621,11 +1632,30 @@ static int mxt_process_messages(struct mxt_data *data) return total_handled; } +static void mxt_start_wd_timer(struct mxt_data *data) +{ + mod_timer(&data->watchdog_timer, jiffies + + msecs_to_jiffies(MXT_WATCHDOG_TIMEOUT)); +} + +static void mxt_stop_wd_timer(struct mxt_data *data) +{ + /* +* Ensure we wait until the watchdog timer +* running on a different CPU finishes +*/ + del_timer_sync(&data->watchdog_timer); + cancel_work_sync(&data->watchdog_work); + del_timer_sync(&data->watchdog_timer); +} + static irqreturn_t mxt_interrupt(int irq, void *dev_id) { struct mxt_data *data = dev_id; int ret; + data->mxt_status.intp_triggered = true; + if (data->in_bootloader) { complete(&data->chg_completion); @@ -1633,21 +1663,25 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) cancel_delayed_work_sync(&data->flash->work); ret = mxt_check_bootloader(data); - return IRQ_RETVAL(ret); + ret = IRQ_RETVAL(ret); + goto exit; } - if (!data->object_table) - return IRQ_HANDLED; + if (!data->object_table) { + ret = IRQ_HANDLED; + goto exit; + } if (data->T44_address) ret = mxt_process_messages_t44(data); else ret = mxt_process_messages(data); - if (ret <= 0) - return IRQ_NONE; - else - return IRQ_HANDLED; + ret = (ret <= 0) ? IRQ_NONE : IRQ_HANDLED; + +exit: + data->mxt_status.intp_triggered = false; + return ret; } static int mxt_t6_command(struct mxt_data *data, u16 cmd_offset, @@ -2967,6 +3001,36 @@ static int mxt_bootloader_status(struct mxt_data *data) return 0; } +static void mxt_watchdog_timer(struct timer_list *t) +{ + struct mxt_data *data = from_timer(data, t, watchdog_timer); + + if (!work_pending(&data->watchdog_work)) { + if (!data->mxt_status.intp_triggered) + schedule_work(&data->watchdog_work); + } + + mxt_start_wd_timer(data); +} + +static void mxt_watchdog_work(struct work_struct *work) +{ + struct mxt_data *data = + container_of(work, struct mxt_data, watchdog_work); + u16 info_buf; + int ret = 0; + u8 size = 2; + + ret = __mxt_read_reg(data->client, 0, size, &info_buf); + + if (ret) { + data->mxt_status.error_count++; + data->mxt_status.dev_status = false; + } else { + data->mxt_status.dev_status = true; + } +} + static int mxt_initialize(struct mxt_data *data) { struct i2c_client *client = data->client; @@ -3944,6 +4008,22 @@ static const struct attribute_group mxt_fw_attr_group = { .attrs = mxt_fw_attrs, }; +static ssize_t m
[PATCH v2 45/49] Input: atmel_mxt_ts: use gpiod_set_value_cansleep for reset pin
From: Balasubramani Vivekanandan In case of remote display, touch controller will be also remote. In such cases, the reset pin of the touch controller will be controlled through bridging ICs like Deserilizer and Serializer. Therefore accessing the gpio pins require transactions with the external IC. Using the function gpiod_set_value will print a warning like below WARNING: CPU: 0 PID: 576 at drivers/gpio/gpiolib.c:1441 gpiod_set_value+0x34/0x60() CPU: 0 PID: 576 Comm: modprobe Not tainted 3.14.79-08377-g84ea22f-dirty #4 Backtrace: [<80011c58>] (dump_backtrace) from [<80011e60>] (show_stack+0x18/0x1c) [<80011e48>] (show_stack) from [<8052d7ac>] (dump_stack+0x7c/0x9c) [<8052d730>] (dump_stack) from [<800241bc>] (warn_slowpath_common+0x74/0x9c) [<80024148>] (warn_slowpath_common) from [<80024288>] (warn_slowpath_null+0x24/0x2c) [<80024264>] (warn_slowpath_null) from [<8029e070>] (gpiod_set_value+0x34/0x60) [<8029e03c>] (gpiod_set_value) from [<7f492e98>] (mxt_probe+0x1e0/0x718 [atmel_mxt_ts]) [<7f492cb8>] (mxt_probe [atmel_mxt_ts]) from [<803c4d34>] (i2c_device_probe+0xcc/0xec) [<803c4c68>] (i2c_device_probe) from [<803252a0>] (driver_probe_device+0xc0/0x200) Signed-off-by: Balasubramani Vivekanandan Signed-off-by: Vladimir Zapolskiy Signed-off-by: Sanjeev Chugh Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 58e54eb45cf0..1187e21a67e4 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -2487,7 +2487,7 @@ static void mxt_regulator_enable(struct mxt_data *data) if (!data->reg_vdd || !data->reg_avdd) return; - gpiod_set_value(data->reset_gpio, 0); + gpiod_set_value_cansleep(data->reset_gpio, 0); error = regulator_enable(data->reg_vdd); if (error) @@ -2505,7 +2505,7 @@ static void mxt_regulator_enable(struct mxt_data *data) * voltage */ msleep(MXT_REGULATOR_DELAY); - gpiod_set_value(data->reset_gpio, 1); + gpiod_set_value_cansleep(data->reset_gpio, 1); msleep(MXT_CHG_DELAY); retry_wait: @@ -4311,7 +4311,7 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) disable_irq(data->irq); } else if (data->reset_gpio) { msleep(MXT_RESET_GPIO_TIME); - gpiod_set_value(data->reset_gpio, 1); + gpiod_set_value_cansleep(data->reset_gpio, 1); msleep(MXT_RESET_INVALID_CHG); } else { dev_dbg(&client->dev, -- 2.19.2
[PATCH v2 47/49] input: atmel_mxt_ts: added sysfs interface to update atmel T38 data
From: Naveen Chakka Atmel touch controller contains T38 object where a user can store its own data of length 64 bytes. T38 data will not be part of checksum calculation on executing T6 BACKUP command. format used to update the T38 data is given below: offset: offset address of the data to be written in the t38 object (in decimal) length: length of the data to be written into the t38 object(in decimal) data: actual data bytes to be written into the t38 object (values should be in hex) Ex: 1. 0 2 10 20 updates first two bytes of the t38 data with values 10 and 20 2. 19 6 10 2f 30 4a 50 60 updates 6 bytes of t38 data from the index 19-24 with hex values Signed-off-by: Naveen Chakka Signed-off-by: Sanjeev Chugh Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 102 +++ 1 file changed, 102 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 5a112dfe30e4..63ff8a211a90 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -4024,6 +4024,106 @@ static ssize_t mxt_touch_device_status(struct device *dev, struct return ret; } +static ssize_t mxt_t38_data_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + struct mxt_data *data = dev_get_drvdata(dev); + struct mxt_object *object; + size_t count = 0, size; + u8 i, *t38_buf; + + if (!data->object_table) + return -ENXIO; + + object = mxt_get_object(data, MXT_SPT_USERDATA_T38); + size = mxt_obj_size(object); + + /* Pre-allocate buffer large enough to hold max size of t38 object.*/ + t38_buf = kmalloc(size, GFP_KERNEL); + if (!t38_buf) + return -ENOMEM; + + count = __mxt_read_reg(data->client, object->start_address, + size, t38_buf); + if (count) + goto end; + + for (i = 0; i < size; i++) + count += scnprintf(buf + count, PAGE_SIZE - count, + "[%2u]: %02x\n", i, t38_buf[i]); + count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); +end: + kfree(t38_buf); + return count; +} + +static ssize_t mxt_t38_data_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mxt_data *data = dev_get_drvdata(dev); + struct mxt_object *object; + ssize_t ret = 0, pos, offset; + unsigned int i, len, index; + u8 *t38_buf; + + if (!data->object_table) + return -ENXIO; + + object = mxt_get_object(data, MXT_SPT_USERDATA_T38); + + /* Pre-allocate buffer large enough to hold max size of t38 object.*/ + t38_buf = kmalloc(mxt_obj_size(object), GFP_KERNEL); + if (!t38_buf) + return -ENOMEM; + + ret = sscanf(buf, "%zd %d%zd", &offset, &len, &pos); + if (ret != 2) { + dev_err(dev, "Bad format: Invalid parameter to update t38\n"); + ret = -EINVAL; + goto end; + } + + if (len == 0) { + dev_err(dev, + "Bad format: Data length should not be equal to 0\n"); + ret = -EINVAL; + goto end; + } + + if (offset < 0 || ((offset + len) > 64)) { + dev_err(dev, "Invalid offset value to update t38\n"); + ret = -EINVAL; + goto end; + } + + index = pos; + for (i = 0; i < len; i++) { + ret = sscanf(buf + index, "%hhx%zd", t38_buf + i, &pos); + if (ret != 1) { + dev_err(dev, "Bad format: Invalid Data\n"); + ret = -EINVAL; + goto end; + } + index += pos; + } + + ret = __mxt_write_reg(data->client, object->start_address + offset, + len, t38_buf); + if (ret) + goto end; + + ret = mxt_t6_command(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE, +true); + if (ret) + dev_err(dev, "backup command failed\n"); + else + ret = count; +end: + kfree(t38_buf); + return ret; +} + static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL); static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL); static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL); @@ -4036,6 +4136,7 @@ static DEVICE_ATTR(debug_v2_enable, S_IWUSR | S_IRUSR, NULL, static DEVICE_ATTR(debug_notify, S_IRUGO, mxt_debug_notify_show, NULL); static DEVICE_ATTR(t25, 0600, mxt_t25_selftest_show, mxt_t25_selftest_store); static DEVICE_ATTR(touch_dev_stat, 0444, mxt_touch_device_status, NULL); +static DEVIC
[PATCH v2 42/49] Input: Atmel: Improve error handling in mxt_initialize_input_device()
From: Deepak Das Currently Driver probe continues with a warning message when it fails to get the proper multitouch object configurations like TouchScreen resolution. But Driver probe should fail in case of above scneario because it will not behave as expected without the proper touchscreen configurations. This commit modifies mxt_initialize_input_device() to return error when it fails to get the proper touch screen configurations. Signed-off-by: Deepak Das Signed-off-by: Dean Jenkins Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 716b91e6fd66..41d92d765aa2 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -2759,15 +2759,19 @@ static int mxt_initialize_input_device(struct mxt_data *data) case MXT_TOUCH_MULTI_T9: num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1; error = mxt_read_t9_resolution(data); - if (error) - dev_warn(dev, "Failed to initialize T9 resolution\n"); + if (error) { + dev_err(dev, "Failed to initialize T9 resolution\n"); + return error; + } break; case MXT_TOUCH_MULTITOUCHSCREEN_T100: num_mt_slots = data->num_touchids; error = mxt_read_t100_config(data); - if (error) - dev_warn(dev, "Failed to read T100 config\n"); + if (error) { + dev_err(dev, "Failed to read T100 config\n"); + return error; + } break; default: -- 2.19.2
[PATCH v2 40/49] Input: Atmel: improve error handling in mxt_initialize()
From: Deepak Das Currently mxt_initialize() tries to probe bootloader mode even if valid bootloader address is not specified. This commit modifies mxt_initialize() to return error if Device is not in appmode and bootloader address is not specified. This commit also returns error code from mxt_send_bootloader_cmd() in mxt_initialize(). Signed-off-by: Deepak Das Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 58 +--- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index dd70f3b9678f..59533753a431 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -713,17 +713,13 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry) return 0; } -static int mxt_probe_bootloader(struct mxt_data *data, bool alt_address) +static int mxt_probe_bootloader(struct mxt_data *data) { struct device *dev = &data->client->dev; int error; u8 buf[3]; bool crc_failure, extended_id; - error = mxt_lookup_bootloader_address(data, alt_address); - if (error) - return error; - /* Check bootloader status and version information */ error = mxt_bootloader_read(data, buf, sizeof(buf)); if (error) @@ -2920,6 +2916,32 @@ static void mxt_config_cb(const struct firmware *cfg, void *ctx) release_firmware(cfg); } +static int mxt_bootloader_status(struct mxt_data *data) +{ + struct i2c_client *client = data->client; + int error; + + error = mxt_lookup_bootloader_address(data, false); + if (error) { + dev_info(&client->dev, +"Bootloader address is not specified\n"); + return error; + } + /* Check bootloader state */ + error = mxt_probe_bootloader(data); + if (error) { + dev_info(&client->dev, "Trying alternate bootloader address\n"); + mxt_lookup_bootloader_address(data, true); + error = mxt_probe_bootloader(data); + if (error) { + dev_err(&client->dev, + "Chip is not in appmode or bootloader mode\n"); + return error; + } + } + return 0; +} + static int mxt_initialize(struct mxt_data *data) { struct i2c_client *client = data->client; @@ -2931,16 +2953,13 @@ static int mxt_initialize(struct mxt_data *data) if (!error) break; - /* Check bootloader state */ - error = mxt_probe_bootloader(data, false); - if (error) { - dev_info(&client->dev, "Trying alternate bootloader address\n"); - error = mxt_probe_bootloader(data, true); - if (error) { - /* Chip is not in appmode or bootloader mode */ - return error; - } - } + dev_info(&client->dev, +"info block read failed (%d), so try bootloader method\n", +error); + + error = mxt_bootloader_status(data); + if (error) + return error; /* OK, we are in bootloader, see if we can recover */ if (++recovery_attempts > 1) { @@ -2954,7 +2973,9 @@ static int mxt_initialize(struct mxt_data *data) } /* Attempt to exit bootloader into app mode */ - mxt_send_bootloader_cmd(data, false); + error = mxt_send_bootloader_cmd(data, false); + if (error) + return error; msleep(MXT_FW_RESET_TIME); } @@ -3646,8 +3667,11 @@ static int mxt_enter_bootloader(struct mxt_data *data) msleep(MXT_RESET_TIME); + ret = mxt_lookup_bootloader_address(data, false); + if (ret) + return ret; /* Do not need to scan since we know family ID */ - ret = mxt_probe_bootloader(data, 0); + ret = mxt_probe_bootloader(data); if (ret) return ret; -- 2.19.2
[PATCH v2 36/49] Input: atmel_mxt_ts: Add support for run self-test routine.
From: Nikhil Ravindran The self test object T25 runs self test routines in device to find faults Sysfs entry add to start self test routine and read back the test results for atmel touchcontrollers.The feature will be used for A-IVI and CAF projects. Signed-off-by: Nikhil Ravindran Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 111 +++ 1 file changed, 111 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 192cf47ff5f4..aa33962ed1dc 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -336,6 +336,9 @@ struct mxt_data { u8 t100_aux_ampl; u8 t100_aux_area; u8 t100_aux_vect; + u16 T25_address; + u8 T25_reportid; + u8 t25_msg[6]; bool debug_enabled; bool debug_v2_enabled; u8 *debug_msg_data; @@ -413,6 +416,8 @@ struct mxt_data { /* Indicates whether device is updating configuration */ bool updating_config; + + bool t25_status; }; struct mxt_vb2_buffer { @@ -1356,6 +1361,24 @@ static void mxt_proc_t93_messages(struct mxt_data *data, u8 *msg) dev_info(dev, "T93 report double tap %d\n", status); } +static void mxt_proc_t25_messages(struct mxt_data *data, u8 *msg) +{ + struct device *dev = &data->client->dev; + + /* Output debug if status has changed */ + dev_dbg(dev, "T25 Status 0x%x Info: %x %x %x %x %x\n", + msg[1], + msg[2], + msg[3], + msg[4], + msg[5], + msg[6]); + + /* Save current status */ + memcpy(&data->t25_msg[0], &msg[1], sizeof(data->t25_msg)); + data->t25_status = false; +} + static int mxt_proc_message(struct mxt_data *data, u8 *message) { u8 report_id = message[0]; @@ -1386,6 +1409,8 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message) } else if (report_id == data->T19_reportid) { mxt_input_button(data, message); data->update_input = true; + } else if (report_id == data->T25_reportid) { + mxt_proc_t25_messages(data, message); } else if (report_id >= data->T15_reportid_min && report_id <= data->T15_reportid_max) { mxt_proc_t15_messages(data, message); @@ -1610,6 +1635,84 @@ static int mxt_t6_command(struct mxt_data *data, u16 cmd_offset, return 0; } +static int mxt_t25_command(struct mxt_data *data, u8 cmd, bool wait) +{ + u16 reg; + int timeout_counter = 0; + int ret; + u8 val[2]; + + reg = data->T25_address; + val[0] = 0x3; + val[1] = cmd; + + data->t25_status = true; + ret = __mxt_write_reg(data->client, reg, sizeof(val), val); + if (ret) { + data->t25_status = false; + return ret; + } + + if (!wait) + return 0; + + do { + msleep(MXT_WAKEUP_TIME); + ret = __mxt_read_reg(data->client, reg + 1, 1, &val[1]); + if (ret) + return ret; + } while ((val[1] != 0) && (timeout_counter++ <= 100)); + + if (timeout_counter > 100) { + dev_err(&data->client->dev, "Command failed!\n"); + data->t25_status = false; + return -EIO; + } + return 0; +} + +/* Firmware Version is returned as Major.Minor.Build */ +static ssize_t mxt_t25_selftest_show(struct device *dev, struct +device_attribute *attr, char *buf) +{ + struct mxt_data *data = dev_get_drvdata(dev); + ssize_t offset = 0; + + if (data->t25_status) + return -EAGAIN; + + if (data->t25_msg[0] == 0xFE) + offset += scnprintf(buf, PAGE_SIZE, "PASS\n"); + else + offset += scnprintf(buf, PAGE_SIZE, "FAILED\n"); + + offset += scnprintf(buf + offset, PAGE_SIZE, "%x %x %x %x %x %x\n", +data->t25_msg[0], +data->t25_msg[1], +data->t25_msg[2], +data->t25_msg[3], +data->t25_msg[4], +data->t25_msg[5]); + return offset; +} + +static ssize_t mxt_t25_selftest_store(struct device *dev, struct + device_attribute *attr, const char *buf, + size_t count) +{ + struct mxt_data *data = dev_get_drvdata(dev); + u32 cmd; + + if (sscanf(buf, "%x", &cmd) == 1) { + if (mxt_t25_command(data, (u8)cmd, 1) == 0) + return count; + + dev_dbg(dev, "mxt_t25_cmd_store write cmd %x error\n", cmd); + return -EINVAL; + } + return 0; +} + static int mxt_acquire_irq(struct mxt_data *data) { int error; @@ -2088,6 +2
[PATCH v2 32/49] Input: atmel_mxt_ts - Change call-points of mxt_free_* functions
From: Kautuk Consul Revamping the code to call mxt_free_object_table and mxt_free_input_device functions only in the following scenarios and code paths: 1) The error path of the mxt_probe() entry point 2) The mxt_remove de-init path entry point 3) All paths which definitely expect to populate the object table like: - the mxt_update_fw_store path which first calls mxt_load_fw and then resorts to calling mxt_initialize itself. - the mxt_read_info_block function which attempts to fill in the object table itself as the main non-error part of the logic. 4) All paths in the code expected to definitely allocate and register the input device such as: - the mxt_update_fw_store path which first calls mxt_load_fw and then resorts to calling mxt_initialize itself. - the mxt_update_cfg_store function which will call mxt_configure_objects. Signed-off-by: Kautuk Consul Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 19 ++- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index f6d65930885a..f8e80471be8a 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -3336,21 +3336,21 @@ static int mxt_configure_objects(struct mxt_data *data, error = mxt_init_t7_power_cfg(data); if (error) { dev_err(dev, "Failed to initialize power cfg\n"); - goto err_free_object_table; + return error; } if (cfg) { error = mxt_update_cfg(data, cfg); if (error) { dev_warn(dev, "Error %d updating config\n", error); - goto err_free_object_table; + return error; } } if (data->multitouch) { error = mxt_initialize_input_device(data); if (error) - goto err_free_object_table; + return error; } else { dev_warn(dev, "No touch object detected\n"); } @@ -3358,10 +3358,6 @@ static int mxt_configure_objects(struct mxt_data *data, mxt_debug_init(data); return 0; - -err_free_object_table: - mxt_free_object_table(data); - return error; } /* Configuration crc check sum is returned as hex xx */ @@ -4098,16 +4094,21 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) error = mxt_initialize(data); if (error) - return error; + goto err_free_object; error = sysfs_create_group(&client->dev.kobj, &mxt_fw_attr_group); if (error) { dev_err(&client->dev, "Failure %d creating fw sysfs group\n", error); - return error; + goto err_free_object; } return 0; + +err_free_object: + mxt_free_input_device(data); + mxt_free_object_table(data); + return error; } static int mxt_remove(struct i2c_client *client) -- 2.19.2
[PATCH v2 31/49] Input: atmel_mxt_ts - eliminate data->raw_info_block
Dynamically allocated in mxt_read_info_block() buffer buf is assigned both to data->info and data->raw_info_block, having both data->info and data->raw_info_block is redundant and confusing. This patch eliminates data->raw_info_block. Signed-off-by: Jiada Wang Signed-off-by: George G. Davis Signed-off-by: Vladimir Zapolskiy --- drivers/input/touchscreen/atmel_mxt_ts.c | 7 ++- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 2d9d2c1e39dd..f6d65930885a 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -323,7 +323,6 @@ struct mxt_data { char phys[64]; /* device physical location */ struct mxt_object *object_table; struct mxt_info *info; - void *raw_info_block; unsigned int irq; unsigned int max_x; unsigned int max_y; @@ -2067,9 +2066,8 @@ static void mxt_free_object_table(struct mxt_data *data) v4l2_device_unregister(&data->dbg.v4l2); #endif data->object_table = NULL; + kfree(data->info); data->info = NULL; - kfree(data->raw_info_block); - data->raw_info_block = NULL; kfree(data->msg_buf); data->msg_buf = NULL; data->T5_address = 0; @@ -2238,7 +2236,7 @@ static int mxt_read_info_block(struct mxt_data *data) u8 *crc_ptr; /* If info block already allocated, free it */ - if (data->raw_info_block) + if (data->info) mxt_free_object_table(data); /* Read 7-byte ID information block starting at address 0 */ @@ -2289,7 +2287,6 @@ static int mxt_read_info_block(struct mxt_data *data) goto err_free_mem; } - data->raw_info_block = id_buf; data->info = (struct mxt_info *)id_buf; dev_info(&client->dev, -- 2.19.2
[PATCH v2 28/49] Input: atmel_mxt_ts - orientation is not present in hover
From: Nick Dyer When in hover, the orientation information is not sent Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit 0c885d5bd276bd9240c43aa046fc407cbe2ae864) Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 4 1 file changed, 4 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 5b7ab798f27d..2d2e8ea30547 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1029,10 +1029,6 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) distance = MXT_DISTANCE_HOVERING; hover = true; active = true; - - if (data->t100_aux_vect) - orientation = message[data->t100_aux_vect]; - break; case MXT_T100_TYPE_FINGER: -- 2.19.2
[PATCH v2 35/49] input: atmel_mxt_ts: Add Missing Delay for reset handling of Atmel touch panel controller in detachable displays.
From: keerthikumarp In case of attached display, the touchpanel reset is controlled via imx gpio's from atmel driver and the delay between touchpanel reset and the time at which the chip becomes capable to communicate with the host processor, has be taken care. However in case of detachable displays, the touchpanel reset is controlled via a deserializer gpio which is triggered just before the atmel driver is probed.The delay between touchpanel reset and the time at which the chip becomes capable to communicate (as specified in datasheet) was not being accounted for. This patch introduces that delay. Signed-off-by: keerthikumarp Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 35f41bfa70d5..192cf47ff5f4 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -4110,6 +4110,10 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) msleep(MXT_RESET_GPIO_TIME); gpiod_set_value(data->reset_gpio, 1); msleep(MXT_RESET_INVALID_CHG); + } else { + dev_dbg(&client->dev, + "atmel reset pin not found in device tree"); + msleep(MXT_RESET_TIME); } error = mxt_initialize(data); -- 2.19.2
[PATCH v2 39/49] Input: Atmel: improve error handling in mxt_start()
From: Deepak Das mxt_start() does not return error in any of the failure cases which will allow input_dev->open() to return success even in case of any failure. This commit modifies mxt_start() to return error in failure cases. Signed-off-by: Deepak Das Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 31 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index e9a895473ed8..dd70f3b9678f 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -3971,12 +3971,13 @@ static int mxt_start(struct mxt_data *data) switch (data->suspend_mode) { case MXT_SUSPEND_T9_CTRL: - mxt_soft_reset(data); - + ret = mxt_soft_reset(data); + if (ret) + break; /* Touch enable */ /* 0x83 = SCANEN | RPTEN | ENABLE */ - mxt_write_object(data, - MXT_TOUCH_MULTI_T9, MXT_T9_CTRL, 0x83); + ret = mxt_write_object(data, + MXT_TOUCH_MULTI_T9, MXT_T9_CTRL, 0x83); break; case MXT_SUSPEND_REGULATOR: @@ -3990,27 +3991,26 @@ static int mxt_start(struct mxt_data *data) * Discard any touch messages still in message buffer * from before chip went to sleep */ - mxt_process_messages_until_invalid(data); + ret = mxt_process_messages_until_invalid(data); + if (ret) + break; ret = mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN); if (ret) - return ret; + break; /* Recalibrate since chip has been in deep sleep */ ret = mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false); if (ret) - return ret; + break; ret = mxt_acquire_irq(data); - if (ret) - return ret; - - break; } - data->suspended = false; + if (!ret) + data->suspended = false; - return 0; + return ret; } static int mxt_stop(struct mxt_data *data) @@ -4331,6 +4331,7 @@ static int __maybe_unused mxt_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct mxt_data *data = i2c_get_clientdata(client); struct input_dev *input_dev = data->input_dev; + int ret = 0; if (!input_dev) return 0; @@ -4338,11 +4339,11 @@ static int __maybe_unused mxt_resume(struct device *dev) mutex_lock(&input_dev->mutex); if (input_dev->users) - mxt_start(data); + ret = mxt_start(data); mutex_unlock(&input_dev->mutex); - return 0; + return ret; } static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume); -- 2.19.2
[PATCH v2 37/49] Input: atmel_mxt_ts: Limit the max bytes transferred in an i2c transaction
From: Balasubramani Vivekanandan In mxt_process_messages_until_invalid() function, driver tries to read all possible reportid in a single i2c transaction. Number of bytes read is limited by the max_reportid parameter. If the max_reportid is a very large value, then a large chunk of bytes will be requested from the controller in a single i2c transaction. This transaction can fail due to timeout. This is visible when the Atmel controller is connected to the SOC via a i2c mux hardware. mxt_process_messages_t44() reads the T44 message which contains the pending T5 message count. If the number of pending T5 messages returned by T44 message is too high then there is a risk of i2c transaction timeout while reading T5 messages in mxt_process_messages_t44(). New property 'atmel,mtu' is created. This property limits the maximum number of bytes that can read/transferred in an i2c transcation Signed-off-by: Balasubramani Vivekanandan Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- .../bindings/input/atmel,maxtouch.txt | 3 + drivers/input/touchscreen/atmel_mxt_ts.c | 65 +++ 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt index d7db16920083..62c93d94bc5d 100644 --- a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt +++ b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt @@ -42,6 +42,8 @@ Optional properties for main touchpad device: - atmel,input_name: Override name of input device from the default. +- atmel,mtu: Maximum number of bytes that can read/transferred in an i2c transaction + Example: touch@4b { @@ -49,4 +51,5 @@ Example: reg = <0x4b>; interrupt-parent = <&gpio>; interrupts = ; + atmel,mtu = <200> }; diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index aa33962ed1dc..169107413823 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -417,6 +417,7 @@ struct mxt_data { /* Indicates whether device is updating configuration */ bool updating_config; + unsigned int mtu; bool t25_status; }; @@ -1462,11 +1463,32 @@ static int mxt_read_and_process_messages(struct mxt_data *data, u8 count) return num_valid; } +static u8 mxt_max_msg_read_count(struct mxt_data *data, u8 max_T5_msg_count) +{ + u8 T5_msg_count_limit = data->mtu / data->T5_msg_size; + + if (!data->mtu) + return max_T5_msg_count; + + if (data->mtu < data->T5_msg_size) { + WARN(1, "mtu set is lesser than the T5 message size\n"); + /* Return count of 1, as fallback */ + return 1; + } + /* +* Return maximum number of T5 messages in single i2c transaction +* based on "atmel,mtu" property. +*/ + return min(T5_msg_count_limit, max_T5_msg_count); +} + static irqreturn_t mxt_process_messages_t44(struct mxt_data *data) { struct device *dev = &data->client->dev; int ret; - u8 count, num_left; + u8 T5_msg_count, total_pending; + u8 total_processed = 0; + u8 processed_valid = 0; /* Read T44 and T5 together */ ret = __mxt_read_reg(data->client, data->T44_address, @@ -1476,18 +1498,19 @@ static irqreturn_t mxt_process_messages_t44(struct mxt_data *data) return IRQ_NONE; } - count = data->msg_buf[0]; + T5_msg_count = data->msg_buf[0]; /* * This condition may be caused by the CHG line being configured in * Mode 0. It results in unnecessary I2C operations but it is benign. */ - if (count == 0) + if (!T5_msg_count) return IRQ_NONE; - if (count > data->max_reportid) { - dev_warn(dev, "T44 count %d exceeded max report id\n", count); - count = data->max_reportid; + if (T5_msg_count > data->max_reportid) { + dev_warn(dev, "T44 count %d exceeded max report id\n", +T5_msg_count); + T5_msg_count = data->max_reportid; } /* Process first message */ @@ -1497,16 +1520,25 @@ static irqreturn_t mxt_process_messages_t44(struct mxt_data *data) return IRQ_NONE; } - num_left = count - 1; + total_pending = T5_msg_count - 1; + if (!total_pending) + goto end; /* Process remaining messages if necessary */ - if (num_left) { - ret = mxt_read_and_process_messages(data, num_left); + T5_msg_count = mxt_max_msg_read_count(data, total_pending); + + do { + if ((total_pending - total_processed) < T5_msg_count) + T5_msg_count = total_pending - total_p
[PATCH v2 38/49] Input: atmel_mxt_ts: return error from mxt_process_messages_until_invalid()
From: Dean Jenkins mxt_process_messages_until_invalid() failed to propagate the error code from mxt_read_and_process_messages() so return the error code. Signed-off-by: Dean Jenkins Signed-off-by: Deepak Das Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 169107413823..e9a895473ed8 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1561,6 +1561,8 @@ static int mxt_process_messages_until_invalid(struct mxt_data *data) /* Read messages until we force an invalid */ do { read = mxt_read_and_process_messages(data, count); + if (read < 0) + return read; if (read < count) return 0; } while (--tries); -- 2.19.2
[PATCH v2 33/49] Input: atmel_mxt_ts - rely on calculated_crc rather than file config_crc
From: Kautuk Consul We now prefer to rely on the calculated CRC and not on the CRC stored in the file. The new logic is as follows: 1) stored CRC of file != calculated CRC of file, then refuse the possible corrupted file 2) calculated CRC of file != CRC of configuration in controller, then update configuration in controller 3) calculated CRC of file == CRC of configuration in controller, then ignore configuration file Signed-off-by: Kautuk Consul Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 65 +--- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index f8e80471be8a..560d46634bae 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1905,7 +1905,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) int ret; int offset; int i; - u32 info_crc, config_crc, calculated_crc; + u32 info_crc, config_crc, calculated_crc = 0; u16 crc_start = 0; /* Make zero terminated copy of the OBP_RAW file */ @@ -1968,30 +1968,6 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) } cfg.raw_pos += offset; - /* -* The Info Block CRC is calculated over mxt_info and the object -* table. If it does not match then we are trying to load the -* configuration from a different chip or firmware version, so -* the configuration CRC is invalid anyway. -*/ - if (info_crc == data->info_crc) { - if (config_crc == 0 || data->config_crc == 0) { - dev_info(dev, "CRC zero, attempting to apply config\n"); - } else if (config_crc == data->config_crc) { - dev_dbg(dev, "Config CRC 0x%06X: OK\n", -data->config_crc); - ret = 0; - goto release_raw; - } else { - dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n", -data->config_crc, config_crc); - } - } else { - dev_warn(dev, -"Warning: Info CRC error - device=0x%06X file=0x%06X\n", -data->info_crc, info_crc); - } - /* Malloc memory to store configuration */ cfg.start_ofs = MXT_OBJECT_START + data->info->object_num * sizeof(struct mxt_object) + @@ -2015,14 +1991,45 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) else dev_warn(dev, "Could not find CRC start\n"); - if (crc_start > cfg.start_ofs) { + if (crc_start > cfg.start_ofs) calculated_crc = mxt_calculate_crc(cfg.mem, crc_start - cfg.start_ofs, cfg.mem_size); - if (config_crc > 0 && config_crc != calculated_crc) - dev_warn(dev, "Config CRC in file inconsistent, calculated=%06X, file=%06X\n", -calculated_crc, config_crc); + /* If the CRC stored in the file is not the same as what +* was calculated by mxt_calculate_crc, this means we +* have to refuse the config file and abort download. +*/ + if (config_crc != calculated_crc) { + dev_warn(dev, +"Config CRC in file inconsistent, calculated=%06X, file=%06X\n", +calculated_crc, config_crc); + ret = 0; + goto release_mem; + } + + /* +* The Info Block CRC is calculated over mxt_info and the object +* table. If it does not match then we are trying to load the +* configuration from a different chip or firmware version, so +* the configuration CRC is invalid anyway. +*/ + if (info_crc == data->info_crc) { + if (config_crc == 0 || data->config_crc == 0) { + dev_info(dev, "CRC zero, attempting to apply config\n"); + } else if (config_crc == data->config_crc) { + dev_dbg(dev, "Config CRC 0x%06X: OK\n", + data->config_crc); + ret = 0; + goto release_mem; + } else { + dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n", +data->config_crc, config_crc); + } + } else { + dev_warn(dev, +"Warning: Info CRC error - device=0x%06X file=0x%06X\n", +data->info_crc, info_crc); } ret = mxt_upload_cfg_mem
[PATCH v2 30/49] Input: atmel_mxt_ts - implement improved debug message interface
From: Nick Dyer Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit 078569c13c88dcb6f8d882bfe17168587712df7d) [gdavis: Resolve forward port conflicts due to v4.14.51 commit 960fe000b1d3 ("Input: atmel_mxt_ts - fix the firmware update").] Signed-off-by: George G. Davis [gdavis: Squash fixes from Dirk Behme: - Input: atmel_mxt_ts - add missing unlock in error path - Input: atmel_mxt_ts - add missing unlock in error path - Input: atmel_mxt_ts - call mxt_debug_msg_remove() in error path - Input: atmel_mxt_ts - protect debug_v2_enabled by mutex Signed-off-by: Dirk Behme [gdavis: Squash fix from Vladimir Zapolskiy: - Input: atmel_mxt_ts - simplify debug_msg binary attribute handling] Signed-off-by: Vladimir Zapolskiy --- Notes: - Squash fixes from Dirk Behme: + Input: atmel_mxt_ts - add missing unlock in error path Unlock the mutex in case the function is exited in the error case. + Input: atmel_mxt_ts - add missing unlock in error path + Input: atmel_mxt_ts - protect debug_v2_enabled by mutex Put the modification of debug_v2_enabled into the protected section. Same as in mxt_debug_msg_enable(). + Input: atmel_mxt_ts - call mxt_debug_msg_remove() in error path Add the missing mxt_debug_msg_remove() to the error path. - Squash fix from Vladimir Zapolskiy: + Input: atmel_mxt_ts - simplify debug_msg binary attribute handling The change introduces several updates, but all of them are related to "debug_msg" binary attribute: * removed dynamic initialization of data->debug_msg_attr * removed mxt_debug_msg_write callback * removed wrong check in mxt_debug_msg_remove() * mxt_debug_msg_remove() now is not called from mxt_free_object_table() avoiding multiple double deallocations. [jiada: Add NULL check for sysfs attribute debug_msg_attr] Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 194 ++- 1 file changed, 192 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 941c6970cb70..2d9d2c1e39dd 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -242,6 +242,8 @@ enum t100_type { #define MXT_PIXELS_PER_MM 20 +#define DEBUG_MSG_MAX 200 + struct mxt_info { u8 family_id; u8 variant_id; @@ -336,6 +338,11 @@ struct mxt_data { u8 t100_aux_area; u8 t100_aux_vect; bool debug_enabled; + bool debug_v2_enabled; + u8 *debug_msg_data; + u16 debug_msg_count; + struct bin_attribute *debug_msg_attr; + struct mutex debug_msg_lock; u8 max_reportid; u32 config_crc; u32 info_crc; @@ -465,6 +472,144 @@ static void mxt_dump_message(struct mxt_data *data, u8 *message) data->T5_msg_size, message); } +static void mxt_debug_msg_enable(struct mxt_data *data) +{ + struct device *dev = &data->client->dev; + + if (data->debug_v2_enabled) + return; + + mutex_lock(&data->debug_msg_lock); + + data->debug_msg_data = kcalloc(DEBUG_MSG_MAX, + data->T5_msg_size, GFP_KERNEL); + if (!data->debug_msg_data) { + mutex_unlock(&data->debug_msg_lock); + return; + } + + data->debug_v2_enabled = true; + mutex_unlock(&data->debug_msg_lock); + + dev_dbg(dev, "Enabled message output\n"); +} + +static void mxt_debug_msg_disable(struct mxt_data *data) +{ + struct device *dev = &data->client->dev; + + if (!data->debug_v2_enabled) + return; + + mutex_lock(&data->debug_msg_lock); + + data->debug_v2_enabled = false; + + kfree(data->debug_msg_data); + data->debug_msg_data = NULL; + data->debug_msg_count = 0; + mutex_unlock(&data->debug_msg_lock); + dev_dbg(dev, "Disabled message output\n"); +} + +static void mxt_debug_msg_add(struct mxt_data *data, u8 *msg) +{ + struct device *dev = &data->client->dev; + + mutex_lock(&data->debug_msg_lock); + + if (!data->debug_msg_data) { + mutex_unlock(&data->debug_msg_lock); + dev_err(dev, "No buffer!\n"); + return; + } + + if (data->debug_msg_count < DEBUG_MSG_MAX) { + memcpy(data->debug_msg_data + + data->debug_msg_count * data->T5_msg_size, + msg, + data->T5_msg_size); + data->debug_msg_count++; + } else { + dev_dbg(dev, "Discarding %u messages\n", data->debug_msg_count); + data->debug_msg_count = 0; + } + + mutex_unlock(&data->debug_msg_lock); + + sysfs_notify(&data->client->dev.kobj, NULL, "debug_notify"); +} + +static ssize_t mxt_debug_msg_read(struct file
[PATCH v2 34/49] input: atmel_mxt_ts: export GPIO reset line via sysfs
From: "George G. Davis" N.B. Modifying the atmel_mxt_ts GPIO reset line during operation will cause problems with normal driver operation. This feature is provided as a diagnostic debug aid. It does not take into consideration any pending operations which may be in progress. Modifying the atmel_mxt_ts GPIO reset line at any time will inevitably cause the driver to fail. Signed-off-by: George G. Davis Signed-off-by: Rajeev Kumar Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 21 + 1 file changed, 21 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 560d46634bae..35f41bfa70d5 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -4083,6 +4083,19 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) return error; } + if (data->reset_gpio) { + error = gpiod_export(data->reset_gpio, 0); + if (error) + return error; + + error = gpiod_export_link(&client->dev, "reset", + data->reset_gpio); + if (error) { + gpiod_unexport(data->reset_gpio); + return error; + } + } + if (data->suspend_mode == MXT_SUSPEND_REGULATOR) { error = mxt_acquire_irq(data); if (error) @@ -4115,6 +4128,10 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) err_free_object: mxt_free_input_device(data); mxt_free_object_table(data); + if (data->reset_gpio) { + sysfs_remove_link(&client->dev.kobj, "reset"); + gpiod_unexport(data->reset_gpio); + } return error; } @@ -4124,6 +4141,10 @@ static int mxt_remove(struct i2c_client *client) disable_irq(data->irq); sysfs_remove_group(&client->dev.kobj, &mxt_fw_attr_group); + if (data->reset_gpio) { + sysfs_remove_link(&client->dev.kobj, "reset"); + gpiod_unexport(data->reset_gpio); + } mxt_debug_msg_remove(data); mxt_sysfs_remove(data); mxt_free_input_device(data); -- 2.19.2
[PATCH v2 29/49] Input: atmel_mxt_ts - implement debug output for messages
From: Nick Dyer Add a debug switch which causes all messages from the touch controller to be dumped to the dmesg log with a set prefix "MXT MSG:". This is used by Atmel user-space utilities to debug touch operation. Enabling this output does impact touch performance. Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit 3c3fcfdd4889dfeb1c80ae8cd94a622c6342b06a) [gdavis: Forward port and fix conflicts.] Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 44 ++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 2d2e8ea30547..941c6970cb70 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -335,6 +335,7 @@ struct mxt_data { u8 t100_aux_ampl; u8 t100_aux_area; u8 t100_aux_vect; + bool debug_enabled; u8 max_reportid; u32 config_crc; u32 info_crc; @@ -460,8 +461,8 @@ static bool mxt_object_readable(unsigned int type) static void mxt_dump_message(struct mxt_data *data, u8 *message) { - dev_dbg(&data->client->dev, "message: %*ph\n", - data->T5_msg_size, message); + dev_dbg(&data->client->dev, "MXT MSG: %*ph\n", + data->T5_msg_size, message); } static int mxt_wait_for_completion(struct mxt_data *data, @@ -1214,6 +1215,7 @@ static void mxt_proc_t93_messages(struct mxt_data *data, u8 *msg) static int mxt_proc_message(struct mxt_data *data, u8 *message) { u8 report_id = message[0]; + bool dump = data->debug_enabled; if (report_id == MXT_RPTID_NOMSG) return 0; @@ -1248,9 +1250,12 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message) } else if (report_id == data->T93_reportid) { mxt_proc_t93_messages(data, message); } else { - mxt_dump_message(data, message); + dump = true; } + if (dump) + mxt_dump_message(data, message); + return 1; } @@ -3522,6 +3527,36 @@ static ssize_t mxt_update_cfg_store(struct device *dev, return ret; } +static ssize_t mxt_debug_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mxt_data *data = dev_get_drvdata(dev); + char c; + + c = data->debug_enabled ? '1' : '0'; + return scnprintf(buf, PAGE_SIZE, "%c\n", c); +} + +static ssize_t mxt_debug_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct mxt_data *data = dev_get_drvdata(dev); + u8 i; + ssize_t ret; + + if (kstrtou8(buf, 0, &i) == 0 && i < 2) { + data->debug_enabled = (i == 1); + + dev_dbg(dev, "%s\n", i ? "debug enabled" : "debug disabled"); + ret = count; + } else { + dev_dbg(dev, "debug_enabled write error\n"); + ret = -EINVAL; + } + + return ret; +} + static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store); static struct attribute *mxt_fw_attrs[] = { @@ -3538,6 +3573,8 @@ static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL); static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL); static DEVICE_ATTR(update_cfg, S_IWUSR, NULL, mxt_update_cfg_store); static DEVICE_ATTR(config_crc, S_IRUGO, mxt_config_crc_show, NULL); +static DEVICE_ATTR(debug_enable, S_IWUSR | S_IRUSR, mxt_debug_enable_show, + mxt_debug_enable_store); static struct attribute *mxt_attrs[] = { &dev_attr_fw_version.attr, @@ -3545,6 +3582,7 @@ static struct attribute *mxt_attrs[] = { &dev_attr_object.attr, &dev_attr_update_cfg.attr, &dev_attr_config_crc.attr, + &dev_attr_debug_enable.attr, NULL }; -- 2.19.2
Re: KASAN: slab-out-of-bounds Read in sctp_inq_pop
On Tue, Aug 27, 2019 at 1:15 AM syzbot wrote: > > Hello, > > syzbot found the following crash on: > > HEAD commit:9733a7c6 Add linux-next specific files for 20190823 > git tree: linux-next > console output: https://syzkaller.appspot.com/x/log.txt?x=143ec11e60 > kernel config: https://syzkaller.appspot.com/x/.config?x=f6c78a1438582bd1 > dashboard link: https://syzkaller.appspot.com/bug?extid=3ca06c5cb35ee3fc1f89 > compiler: gcc (GCC) 9.0.0 20181231 (experimental) > > Unfortunately, I don't have any reproducer for this crash yet. > > IMPORTANT: if you fix the bug, please add the following tag to the commit: > Reported-by: syzbot+3ca06c5cb35ee3fc1...@syzkaller.appspotmail.com > > == > BUG: KASAN: slab-out-of-bounds in sctp_inq_pop+0xafd/0xd80 > net/sctp/inqueue.c:201 > Read of size 2 at addr 8880a4e37222 by task syz-executor.3/32407 > > CPU: 1 PID: 32407 Comm: syz-executor.3 Not tainted 5.3.0-rc5-next-20190823 > #72 > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS > Google 01/01/2011 > Call Trace: > __dump_stack lib/dump_stack.c:77 [inline] > dump_stack+0x172/0x1f0 lib/dump_stack.c:113 > print_address_description.cold+0xd4/0x306 mm/kasan/report.c:351 > __kasan_report.cold+0x1b/0x36 mm/kasan/report.c:482 > kasan_report+0x12/0x17 mm/kasan/common.c:610 > __asan_report_load2_noabort+0x14/0x20 mm/kasan/generic_report.c:130 > sctp_inq_pop+0xafd/0xd80 net/sctp/inqueue.c:201 > sctp_endpoint_bh_rcv+0x184/0x8d0 net/sctp/endpointola.c:335 > sctp_inq_push+0x1e4/0x280 net/sctp/inqueue.c:80 > sctp_rcv+0x2807/0x3590 net/sctp/input.c:256 > sctp6_rcv+0x17/0x30 net/sctp/ipv6.c:1049 > ip6_protocol_deliver_rcu+0x2fe/0x1660 net/ipv6/ip6_input.c:397 > ip6_input_finish+0x84/0x170 net/ipv6/ip6_input.c:438 > NF_HOOK include/linux/netfilter.h:305 [inline] > NF_HOOK include/linux/netfilter.h:299 [inline] > ip6_input+0xe4/0x3f0 net/ipv6/ip6_input.c:447 > dst_input include/net/dst.h:442 [inline] > ip6_sublist_rcv_finish+0x98/0x1e0 net/ipv6/ip6_input.c:84 > ip6_list_rcv_finish net/ipv6/ip6_input.c:118 [inline] > ip6_sublist_rcv+0x80c/0xcf0 net/ipv6/ip6_input.c:282 > ipv6_list_rcv+0x373/0x4b0 net/ipv6/ip6_input.c:316 > __netif_receive_skb_list_ptype net/core/dev.c:5049 [inline] > __netif_receive_skb_list_core+0x1a2/0x9d0 net/core/dev.c:5087 > __netif_receive_skb_list net/core/dev.c:5149 [inline] > netif_receive_skb_list_internal+0x7eb/0xe60 net/core/dev.c:5244 > gro_normal_list.part.0+0x1e/0xb0 net/core/dev.c:5757 > gro_normal_list net/core/dev.c:5755 [inline] > gro_normal_one net/core/dev.c:5769 [inline] > napi_frags_finish net/core/dev.c:5782 [inline] > napi_gro_frags+0xa6a/0xea0 net/core/dev.c:5855 > tun_get_user+0x2e98/0x3fa0 drivers/net/tun.c:1974 > tun_chr_write_iter+0xbd/0x156 drivers/net/tun.c:2020 > call_write_iter include/linux/fs.h:1890 [inline] > do_iter_readv_writev+0x5f8/0x8f0 fs/read_write.c:693 > do_iter_write fs/read_write.c:976 [inline] > do_iter_write+0x17b/0x380 fs/read_write.c:957 > vfs_writev+0x1b3/0x2f0 fs/read_write.c:1021 > do_writev+0x15b/0x330 fs/read_write.c:1064 > __do_sys_writev fs/read_write.c:1137 [inline] > __se_sys_writev fs/read_write.c:1134 [inline] > __x64_sys_writev+0x75/0xb0 fs/read_write.c:1134 > do_syscall_64+0xfa/0x760 arch/x86/entry/common.c:290 > entry_SYSCALL_64_after_hwframe+0x49/0xbe > RIP: 0033:0x459731 > Code: 75 14 b8 14 00 00 00 0f 05 48 3d 01 f0 ff ff 0f 83 34 b9 fb ff c3 48 > 83 ec 08 e8 fa 2c 00 00 48 89 04 24 b8 14 00 00 00 0f 05 <48> 8b 3c 24 48 > 89 c2 e8 43 2d 00 00 48 89 d0 48 83 c4 08 48 3d 01 > RSP: 002b:7fb4cd361ba0 EFLAGS: 0293 ORIG_RAX: 0014 > RAX: ffda RBX: 002a RCX: 00459731 > RDX: 0001 RSI: 7fb4cd361c00 RDI: 00f0 > RBP: 0075bf20 R08: R09: > R10: R11: 0293 R12: 7fb4cd3626d4 > R13: 004c87e3 R14: 004df640 R15: > > Allocated by task 32407: > save_stack+0x23/0x90 mm/kasan/common.c:69 > set_track mm/kasan/common.c:77 [inline] > __kasan_kmalloc mm/kasan/common.c:486 [inline] > __kasan_kmalloc.constprop.0+0xcf/0xe0 mm/kasan/common.c:459 > kasan_slab_alloc+0xf/0x20 mm/kasan/common.c:494 > slab_post_alloc_hook mm/slab.h:584 [inline] > slab_alloc mm/slab.c:3319 [inline] > kmem_cache_alloc+0x121/0x710 mm/slab.c:3483 > __build_skb+0x26/0x70 net/core/skbuff.c:310 > __napi_alloc_skb+0x1d2/0x300 net/core/skbuff.c:523 > napi_alloc_skb include/linux/skbuff.h:2801 [inline] > napi_get_frags net/core/dev.c:5742 [inline] > napi_get_frags+0x65/0x140 net/core/dev.c:5737 > tun_napi_alloc_frags drivers/net/tun.c:1473 [inline] > tun_get_user+0x16bd/0x3fa0 drivers/net/tun.c:1834 > tun_chr_write_iter+0xbd/0x156 drivers/net/tun.c:2020 > call_write_iter include/linux/fs.h:1890 [inline] >
[PATCH v2 22/49] Input: atmel_mxt_ts - combine bootloader version query with probe
From: Nick Dyer This removes some complexity from the bootloader state machine, and means that we always output some debug about the version as soon as we start talking to the bootloader. Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit a2d141f170c80fea6663af98aab0be32abc0ddb0) Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 45 +++- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 3da3f27ed580..4ec28b73ee83 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -558,47 +558,31 @@ static int mxt_probe_bootloader(struct mxt_data *data, bool alt_address) { struct device *dev = &data->client->dev; int error; - u8 val; - bool crc_failure; + u8 buf[3]; + bool crc_failure, extended_id; error = mxt_lookup_bootloader_address(data, alt_address); if (error) return error; - error = mxt_bootloader_read(data, &val, 1); + /* Check bootloader status and version information */ + error = mxt_bootloader_read(data, buf, sizeof(buf)); if (error) return error; - /* Check app crc fail mode */ - crc_failure = (val & ~MXT_BOOT_STATUS_MASK) == MXT_APP_CRC_FAIL; + crc_failure = (buf[0] & ~MXT_BOOT_STATUS_MASK) == MXT_APP_CRC_FAIL; + extended_id = buf[0] & MXT_BOOT_EXTENDED_ID; - dev_err(dev, "Detected bootloader, status:%02X%s\n", - val, crc_failure ? ", APP_CRC_FAIL" : ""); + dev_info(dev, "Found bootloader addr:%02x ID:%u%s%u%s\n", +data->bootloader_addr, +extended_id ? (buf[1] & MXT_BOOT_ID_MASK) : buf[0], +extended_id ? " version:" : "", +extended_id ? buf[2] : 0, +crc_failure ? ", APP_CRC_FAIL" : ""); return 0; } -static u8 mxt_get_bootloader_version(struct mxt_data *data, u8 val) -{ - struct device *dev = &data->client->dev; - u8 buf[3]; - - if (val & MXT_BOOT_EXTENDED_ID) { - if (mxt_bootloader_read(data, &buf[0], 3) != 0) { - dev_err(dev, "%s: i2c failure\n", __func__); - return val; - } - - dev_dbg(dev, "Bootloader ID:%d Version:%d\n", buf[1], buf[2]); - - return buf[0]; - } else { - dev_dbg(dev, "Bootloader ID:%d\n", val & MXT_BOOT_ID_MASK); - - return val; - } -} - static int mxt_check_bootloader(struct mxt_data *data, unsigned int state, bool wait) { @@ -632,9 +616,6 @@ static int mxt_check_bootloader(struct mxt_data *data, unsigned int state, if (ret) return ret; - if (state == MXT_WAITING_BOOTLOAD_CMD) - val = mxt_get_bootloader_version(data, val); - switch (state) { case MXT_WAITING_BOOTLOAD_CMD: case MXT_WAITING_FRAME_DATA: @@ -3283,7 +3264,7 @@ static int mxt_enter_bootloader(struct mxt_data *data) msleep(MXT_RESET_TIME); /* Do not need to scan since we know family ID */ - ret = mxt_lookup_bootloader_address(data, 0); + ret = mxt_probe_bootloader(data, 0); if (ret) return ret; -- 2.19.2
[PATCH v2 25/49] Input: atmel_mxt_ts - make bootloader interrupt driven
From: Nick Dyer Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit 67a3eea0cfc724c3c2a7410ac064f74227c7c6ef) [gdavis: Resolve forward port conflicts due to applying upstream commit 96a938aa214e ("Input: atmel_mxt_ts - remove platform data support").] Signed-off-by: George G. Davis [jiada: Replace two use msecs_to_jiffies() instead of HZ] Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 118 --- 1 file changed, 60 insertions(+), 58 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index e5843cb9a35e..cfc84f3b5a9e 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -218,6 +219,7 @@ enum t100_type { #define MXT_REGULATOR_DELAY150 /* msec */ #define MXT_CHG_DELAY 100 /* msec */ #define MXT_POWERON_DELAY 150 /* msec */ +#define MXT_BOOTLOADER_WAIT36E5/* 1 minute */ /* Command to unlock bootloader */ #define MXT_UNLOCK_CMD_MSB 0xaa @@ -299,6 +301,7 @@ struct mxt_fw_frame { /* Firmware update context */ struct mxt_flash { + struct mxt_data *data; const struct firmware *fw; struct mxt_fw_frame *frame; loff_t pos; @@ -306,7 +309,8 @@ struct mxt_flash { unsigned int count; unsigned int retry; u8 previous; - bool complete; + struct completion flash_completion; + struct delayed_work work; }; /* Each client has this additional data */ @@ -355,6 +359,7 @@ struct mxt_data { char *cfg_name; const char *pcfg_name; const char *input_name; + struct mxt_flash *flash; /* Cached parameters from object table */ u16 T5_address; @@ -599,28 +604,17 @@ static int mxt_write_firmware_frame(struct mxt_data *data, struct mxt_flash *f) f->frame_size); } -static int mxt_check_bootloader(struct mxt_data *data, struct mxt_flash *f) +static int mxt_check_bootloader(struct mxt_data *data) { struct device *dev = &data->client->dev; + struct mxt_flash *f = data->flash; u8 state; int ret; - /* -* In application update mode, the interrupt -* line signals state transitions. We must wait for the -* CHG assertion before reading the status byte. -* Once the status byte has been read, the line is deasserted. -*/ - ret = mxt_wait_for_completion(data, &data->chg_completion, - MXT_FW_CHG_TIMEOUT); - if (ret) { - /* -* TODO: handle -ERESTARTSYS better by terminating -* fw update process before returning to userspace -* by writing length 0x000 to device (iff we are in -* WAITING_FRAME_DATA state). -*/ - dev_warn(dev, "Update wait error %d\n", ret); + /* Handle interrupt after download/flash process */ + if (f->pos >= f->fw->size) { + complete(&f->flash_completion); + return 0; } ret = mxt_bootloader_read(data, &state, 1); @@ -666,14 +660,12 @@ static int mxt_check_bootloader(struct mxt_data *data, struct mxt_flash *f) f->pos += f->frame_size; f->count++; - if (f->pos >= f->fw->size) { - f->complete = true; + if (f->pos >= f->fw->size) dev_info(dev, "Sent %u frames, %zu bytes\n", f->count, f->fw->size); - } else if (f->count % 50 == 0) { + else if (f->count % 50 == 0) dev_dbg(dev, "Sent %u frames, %lld/%zu bytes\n", f->count, f->pos, f->fw->size); - } break; @@ -695,6 +687,9 @@ static int mxt_check_bootloader(struct mxt_data *data, struct mxt_flash *f) f->previous = state; + /* Poll after 0.1s if no interrupt received */ + schedule_delayed_work(&f->work, msecs_to_jiffies(100)); + return 0; unexpected: @@ -1403,7 +1398,11 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) if (data->in_bootloader) { complete(&data->chg_completion); - return IRQ_HANDLED; + + if (data->flash && &data->flash->work) + cancel_delayed_work_sync(&data->flash->work); + + return IRQ_RETVAL(mxt_check_bootloader(data)); } if (!data->object_table) @@ -3304,16 +3303,13 @@ static int mxt_enter_bootloader(struct mxt_data *data) if (data->suspend_mode == MXT_SUSPEND_REGULATOR) mxt_regulator_enable(data); - if (data->suspend_mode == MXT_
[PATCH v2 21/49] Input: atmel_mxt_ts - refactor code to enter bootloader into separate func
From: Nick Dyer Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit bedd706a32522b946467e15f4f4f24de86a1b4d7) [gdavis: Resolve forward port conflicts due to applying upstream commit 96a938aa214e ("Input: atmel_mxt_ts - remove platform data support").] Signed-off-by: George G. Davis [jiada: Squash change from ndyer/linux/for-upstream commit d691d3ee6c6de84b38464a42 3207b3e23cb9dc3a - Input: atmel_mxt_ts - check firmware format before entering bootloader] Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 43 +++- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 85eefd4fbc9a..3da3f27ed580 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -3257,23 +3257,10 @@ static int mxt_check_firmware_format(struct device *dev, return -EINVAL; } -static int mxt_load_fw(struct device *dev) +static int mxt_enter_bootloader(struct mxt_data *data) { - struct mxt_data *data = dev_get_drvdata(dev); - struct mxt_flash f = { 0, }; int ret; - ret = request_firmware(&f.fw, data->fw_name, dev); - if (ret) { - dev_err(dev, "Unable to open firmware %s\n", data->fw_name); - return ret; - } - - /* Check for incorrect enc file */ - ret = mxt_check_firmware_format(dev, f.fw); - if (ret) - goto release_firmware; - if (data->suspended) { if (data->suspend_mode == MXT_SUSPEND_REGULATOR) mxt_regulator_enable(data); @@ -3291,14 +3278,14 @@ static int mxt_load_fw(struct device *dev) ret = mxt_t6_command(data, MXT_COMMAND_RESET, MXT_BOOT_VALUE, false); if (ret) - goto release_firmware; + return ret; msleep(MXT_RESET_TIME); /* Do not need to scan since we know family ID */ ret = mxt_lookup_bootloader_address(data, 0); if (ret) - goto release_firmware; + return ret; mxt_sysfs_remove(data); mxt_free_input_device(data); @@ -3309,6 +3296,30 @@ static int mxt_load_fw(struct device *dev) reinit_completion(&data->bl_completion); + return 0; +} + +static int mxt_load_fw(struct device *dev) +{ + struct mxt_data *data = dev_get_drvdata(dev); + struct mxt_flash f = { 0, }; + int ret; + + ret = request_firmware(&f.fw, data->fw_name, dev); + if (ret) { + dev_err(dev, "Unable to open firmware %s\n", data->fw_name); + return ret; + } + + /* Check for incorrect enc file */ + ret = mxt_check_firmware_format(dev, f.fw); + if (ret) + goto release_firmware; + + ret = mxt_enter_bootloader(data); + if (ret) + goto release_firmware; + ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false); if (ret) { /* Bootloader may still be unlocked from previous attempt */ -- 2.19.2
[PATCH v2 20/49] Input: atmel_mxt_ts - refactor firmware flash to extract context into struct
From: Nick Dyer Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit 1bbe20ff3dcd6612e7942c495929eae5c138ece2) Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 59 +++- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 77a1f8209cee..85eefd4fbc9a 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -291,6 +291,22 @@ struct mxt_cfg { struct mxt_info info; }; +/* Firmware frame structure */ +struct mxt_fw_frame { + __be16 size; + u8 data[]; +}; + +/* Firmware update context */ +struct mxt_flash { + const struct firmware *fw; + struct mxt_fw_frame *frame; + loff_t pos; + size_t frame_size; + unsigned int count; + unsigned int retry; +}; + /* Each client has this additional data */ struct mxt_data { struct i2c_client *client; @@ -3244,21 +3260,17 @@ static int mxt_check_firmware_format(struct device *dev, static int mxt_load_fw(struct device *dev) { struct mxt_data *data = dev_get_drvdata(dev); - const struct firmware *fw = NULL; - unsigned int frame_size; - unsigned int pos = 0; - unsigned int retry = 0; - unsigned int frame = 0; + struct mxt_flash f = { 0, }; int ret; - ret = request_firmware(&fw, data->fw_name, dev); + ret = request_firmware(&f.fw, data->fw_name, dev); if (ret) { dev_err(dev, "Unable to open firmware %s\n", data->fw_name); return ret; } /* Check for incorrect enc file */ - ret = mxt_check_firmware_format(dev, fw); + ret = mxt_check_firmware_format(dev, f.fw); if (ret) goto release_firmware; @@ -3312,41 +3324,42 @@ static int mxt_load_fw(struct device *dev) goto disable_irq; } - while (pos < fw->size) { + while (f.pos < f.fw->size) { + f.frame = (struct mxt_fw_frame *)(f.fw->data + f.pos); + ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, true); if (ret) goto disable_irq; - frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1)); - /* Take account of CRC bytes */ - frame_size += 2; + f.frame_size = __be16_to_cpu(f.frame->size) + 2U; /* Write one frame to device */ - ret = mxt_bootloader_write(data, fw->data + pos, frame_size); + ret = mxt_bootloader_write(data, f.fw->data + f.pos, + f.frame_size); if (ret) goto disable_irq; ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS, true); if (ret) { - retry++; + f.retry++; /* Back off by 20ms per retry */ - msleep(retry * 20); + msleep(f.retry * 20); - if (retry > 20) { + if (f.retry > 20) { dev_err(dev, "Retry count exceeded\n"); goto disable_irq; } } else { - retry = 0; - pos += frame_size; - frame++; + f.retry = 0; + f.pos += f.frame_size; + f.count++; } - if (frame % 50 == 0) - dev_dbg(dev, "Sent %d frames, %d/%zd bytes\n", - frame, pos, fw->size); + if (f.count % 50 == 0) + dev_dbg(dev, "Sent %u frames, %lld/%zu bytes\n", + f.count, f.pos, f.fw->size); } /* Wait for flash. */ @@ -3355,7 +3368,7 @@ static int mxt_load_fw(struct device *dev) if (ret) goto disable_irq; - dev_dbg(dev, "Sent %d frames, %d bytes\n", frame, pos); + dev_dbg(dev, "Sent %u frames, %lld bytes\n", f.count, f.pos); /* * Wait for device to reset. Some bootloader versions do not assert @@ -3369,7 +3382,7 @@ static int mxt_load_fw(struct device *dev) disable_irq: disable_irq(data->irq); release_firmware: - release_firmware(fw); + release_firmware(f.fw); return ret; } -- 2.19.2
[PATCH v2 27/49] Input: atmel_mxt_ts - implement I2C retries
From: Nick Dyer Some maXTouch chips (eg mXT1386) will not respond on the first I2C request when they are in a sleep state. It must be retried after a delay for the chip to wake up. Signed-off-by: Nick Dyer Acked-by: Yufeng Shen (cherry picked from ndyer/linux/for-upstream commit 63fd7a2cd03c3a572a5db39c52f4856819e1835d) [gdavis: Forward port and fix conflicts.] Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 45 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index daf119c2957d..5b7ab798f27d 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -216,6 +216,7 @@ enum t100_type { #define MXT_CRC_TIMEOUT1000/* msec */ #define MXT_FW_RESET_TIME 3000/* msec */ #define MXT_FW_CHG_TIMEOUT 300 /* msec */ +#define MXT_WAKEUP_TIME25 /* msec */ #define MXT_REGULATOR_DELAY150 /* msec */ #define MXT_CHG_DELAY 100 /* msec */ #define MXT_POWERON_DELAY 150 /* msec */ @@ -723,6 +724,7 @@ static int __mxt_read_chunk(struct i2c_client *client, struct i2c_msg xfer[2]; u8 buf[2]; int ret; + bool retry = false; buf[0] = reg & 0xff; buf[1] = (reg >> 8) & 0xff; @@ -739,17 +741,22 @@ static int __mxt_read_chunk(struct i2c_client *client, xfer[1].len = len; xfer[1].buf = val; - ret = i2c_transfer(client->adapter, xfer, 2); - if (ret == 2) { - ret = 0; - } else { - if (ret >= 0) - ret = -EIO; - dev_err(&client->dev, "%s: i2c transfer failed (%d)\n", - __func__, ret); +retry_read: + ret = i2c_transfer(client->adapter, xfer, ARRAY_SIZE(xfer)); + if (ret != ARRAY_SIZE(xfer)) { + if (!retry) { + dev_dbg(&client->dev, "%s: i2c retry\n", __func__); + msleep(MXT_WAKEUP_TIME); + retry = true; + goto retry_read; + } else { + dev_err(&client->dev, "%s: i2c transfer failed (%d)\n", + __func__, ret); + return -EIO; + } } - return ret; + return 0; } static int __mxt_read_reg(struct i2c_client *client, @@ -780,6 +787,7 @@ static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len, u8 *buf; size_t count; int ret; + bool retry = false; count = len + 2; buf = kmalloc(count, GFP_KERNEL); @@ -790,14 +798,21 @@ static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len, buf[1] = (reg >> 8) & 0xff; memcpy(&buf[2], val, len); +retry_write: ret = i2c_master_send(client, buf, count); - if (ret == count) { - ret = 0; - } else { - if (ret >= 0) + if (ret != count) { + if (!retry) { + dev_dbg(&client->dev, "%s: i2c retry\n", __func__); + msleep(MXT_WAKEUP_TIME); + retry = true; + goto retry_write; + } else { + dev_err(&client->dev, "%s: i2c send failed (%d)\n", + __func__, ret); ret = -EIO; - dev_err(&client->dev, "%s: i2c send failed (%d)\n", - __func__, ret); + } + } else { + ret = 0; } kfree(buf); -- 2.19.2
[PATCH v2 23/49] Input: atmel_mxt_ts - improve bootloader state machine handling
From: Nick Dyer The code is much clearer if we switch on the actual state the bootloader is in, rather than the state we want it to be in, and allows the removal of a goto retry tangle. Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit 463e15ee95ee6e6274017ff645839dbe34d75c99) [gdavis: Squash fix from George G. Davis: - input: atmel_mxt_ts - Fix 'mxt_send_bootloader_cmd' was not declared warning] Signed-off-by: George G. Davis --- Notes: - Squash fix from George G. Davis: + input: atmel_mxt_ts - Fix 'mxt_send_bootloader_cmd' was not declared warning The following sparse warning was introduced by ndyer/linux/for-upstream commit 463e15ee95ee ("Input: atmel_mxt_ts - improve bootloader state machine handling"): drivers/input/touchscreen/atmel_mxt_ts.c:888:5: warning: symbol 'mxt_send_bootloader_cmd' was not declared. Should it be static? Fix the above sparse warning by restoring the 'mxt_send_bootloader_cmd' static declaration which was errantly removed by ndyer/linux/for-upstream commit 463e15ee95ee ("Input: atmel_mxt_ts - improve bootloader state machine handling"). Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 183 --- 1 file changed, 98 insertions(+), 85 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 4ec28b73ee83..4e7f82e2fc0c 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -305,6 +305,8 @@ struct mxt_flash { size_t frame_size; unsigned int count; unsigned int retry; + u8 previous; + bool complete; }; /* Each client has this additional data */ @@ -583,64 +585,121 @@ static int mxt_probe_bootloader(struct mxt_data *data, bool alt_address) return 0; } -static int mxt_check_bootloader(struct mxt_data *data, unsigned int state, - bool wait) +static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock); + +static int mxt_write_firmware_frame(struct mxt_data *data, struct mxt_flash *f) +{ + f->frame = (struct mxt_fw_frame *)(f->fw->data + f->pos); + + /* Take account of CRC bytes */ + f->frame_size = __be16_to_cpu(f->frame->size) + 2U; + + /* Write one frame to device */ + return mxt_bootloader_write(data, f->fw->data + f->pos, + f->frame_size); +} + +static int mxt_check_bootloader(struct mxt_data *data, struct mxt_flash *f) { struct device *dev = &data->client->dev; - u8 val; + u8 state; int ret; -recheck: - if (wait) { + /* +* In application update mode, the interrupt +* line signals state transitions. We must wait for the +* CHG assertion before reading the status byte. +* Once the status byte has been read, the line is deasserted. +*/ + ret = mxt_wait_for_completion(data, &data->bl_completion, + MXT_FW_CHG_TIMEOUT); + if (ret) { /* -* In application update mode, the interrupt -* line signals state transitions. We must wait for the -* CHG assertion before reading the status byte. -* Once the status byte has been read, the line is deasserted. +* TODO: handle -ERESTARTSYS better by terminating +* fw update process before returning to userspace +* by writing length 0x000 to device (iff we are in +* WAITING_FRAME_DATA state). */ - ret = mxt_wait_for_completion(data, &data->bl_completion, - MXT_FW_CHG_TIMEOUT); - if (ret) { - /* -* TODO: handle -ERESTARTSYS better by terminating -* fw update process before returning to userspace -* by writing length 0x000 to device (iff we are in -* WAITING_FRAME_DATA state). -*/ - dev_err(dev, "Update wait error %d\n", ret); - return ret; - } + dev_warn(dev, "Update wait error %d\n", ret); } - ret = mxt_bootloader_read(data, &val, 1); + ret = mxt_bootloader_read(data, &state, 1); if (ret) return ret; + /* Remove don't care bits */ + if (state & ~MXT_BOOT_STATUS_MASK) + state &= ~MXT_BOOT_STATUS_MASK; + switch (state) { case MXT_WAITING_BOOTLOAD_CMD: + dev_info(dev, "Unlocking bootloader\n"); + ret = mxt_send_bootloader_cmd(data, true); + if (ret) + return ret; + + break; + case MXT_WAITING_FRAME_DATA: - case MXT_APP_CR
[PATCH v2 24/49] Input: atmel_mxt_ts - rename bl_completion to chg_completion
From: Nick Dyer Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit dda8453bfb44216645ede798918a314d4fca2481) [gdavis: Resolve forward port conflicts due to applying upstream commit 96a938aa214e ("Input: atmel_mxt_ts - remove platform data support").] Signed-off-by: George G. Davis [jiada: call complete(&data->chg_completion) only when in_bootloader is TRUE] Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 23 +++ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 4e7f82e2fc0c..e5843cb9a35e 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -381,9 +381,6 @@ struct mxt_data { u8 T100_reportid_max; u16 T107_address; - /* for fw update in bootloader */ - struct completion bl_completion; - /* for reset handling */ struct completion reset_completion; @@ -395,6 +392,9 @@ struct mxt_data { enum mxt_suspend_mode suspend_mode; + /* for power up handling */ + struct completion chg_completion; + /* Indicates whether device is in suspend */ bool suspended; @@ -611,7 +611,7 @@ static int mxt_check_bootloader(struct mxt_data *data, struct mxt_flash *f) * CHG assertion before reading the status byte. * Once the status byte has been read, the line is deasserted. */ - ret = mxt_wait_for_completion(data, &data->bl_completion, + ret = mxt_wait_for_completion(data, &data->chg_completion, MXT_FW_CHG_TIMEOUT); if (ret) { /* @@ -1402,8 +1402,7 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) struct mxt_data *data = dev_id; if (data->in_bootloader) { - /* bootloader state transition completion */ - complete(&data->bl_completion); + complete(&data->chg_completion); return IRQ_HANDLED; } @@ -2167,9 +2166,9 @@ static void mxt_regulator_enable(struct mxt_data *data) msleep(MXT_CHG_DELAY); retry_wait: - reinit_completion(&data->bl_completion); + reinit_completion(&data->chg_completion); data->in_bootloader = true; - error = mxt_wait_for_completion(data, &data->bl_completion, + error = mxt_wait_for_completion(data, &data->chg_completion, MXT_POWERON_DELAY); if (error == -EINTR) goto retry_wait; @@ -3334,7 +,7 @@ static int mxt_enter_bootloader(struct mxt_data *data) enable_irq(data->irq); } - reinit_completion(&data->bl_completion); + reinit_completion(&data->chg_completion); return 0; } @@ -3370,7 +3369,7 @@ static int mxt_load_fw(struct device *dev) } /* Wait for flash. */ - ret = mxt_wait_for_completion(data, &data->bl_completion, + ret = mxt_wait_for_completion(data, &data->chg_completion, MXT_FW_RESET_TIME); if (ret) goto disable_irq; @@ -3381,7 +3380,7 @@ static int mxt_load_fw(struct device *dev) * the CHG line after bootloading has finished, so ignore potential * errors. */ - mxt_wait_for_completion(data, &data->bl_completion, MXT_FW_RESET_TIME); + mxt_wait_for_completion(data, &data->chg_completion, MXT_FW_RESET_TIME); data->in_bootloader = false; disable_irq: @@ -3803,7 +3802,7 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) data->irq = client->irq; i2c_set_clientdata(client, data); - init_completion(&data->bl_completion); + init_completion(&data->chg_completion); init_completion(&data->reset_completion); init_completion(&data->crc_completion); -- 2.19.2
[PATCH v2 26/49] Input: atmel_mxt_ts - delay enabling IRQ when not using regulators
From: Nick Dyer The path of enabling the IRQ in the probe function is not safe in level triggered operation, if it was already powered up and there is a message waiting on the device (eg finger down) because the object table has not yet been read. This forces the ISR into a hard loop. Delay enabling the interrupt until it is first needed. Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit 64c9dadc4a3250a185baf06ab0f628be45d5d9a0) [gdavis: Resolve forward port conflicts due to v4.14-rc1 commit 8cc8446b9b62 ("Input: atmel_mxt_ts - use more managed resources") and applying upstream commit 96a938aa214e ("Input: atmel_mxt_ts - remove platform data support").] Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 40 +++- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index cfc84f3b5a9e..daf119c2957d 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1451,9 +1451,24 @@ static int mxt_acquire_irq(struct mxt_data *data) { int error; - enable_irq(data->irq); + if (!data->irq) { + error = devm_request_threaded_irq(&data->client->dev, + data->client->irq, + NULL, mxt_interrupt, + IRQF_ONESHOT, + data->client->name, data); + if (error) { + dev_err(&data->client->dev, "Error requesting irq\n"); + return error; + } + + /* Presence of data->irq means IRQ initialised */ + data->irq = data->client->irq; + } else { + enable_irq(data->irq); + } - if (data->use_retrigen_workaround) { + if (data->object_table && data->use_retrigen_workaround) { error = mxt_process_messages_until_invalid(data); if (error) return error; @@ -3373,7 +3388,9 @@ static int mxt_load_fw(struct device *dev) goto release_firmware; } - enable_irq(data->irq); + ret = mxt_acquire_irq(data); + if (ret) + goto release_firmware; /* Poll after 0.1s if no interrupt received */ schedule_delayed_work(&data->flash->work, msecs_to_jiffies(100)); @@ -3801,7 +3818,6 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) client->adapter->nr, client->addr); data->client = client; - data->irq = client->irq; i2c_set_clientdata(client, data); init_completion(&data->chg_completion); @@ -3829,26 +3845,22 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) return error; } - error = devm_request_threaded_irq(&client->dev, client->irq, - NULL, mxt_interrupt, IRQF_ONESHOT, - client->name, data); - if (error) { - dev_err(&client->dev, "Failed to register interrupt\n"); - return error; - } - if (data->suspend_mode == MXT_SUSPEND_REGULATOR) { + error = mxt_acquire_irq(data); + if (error) + return error; + error = mxt_probe_regulators(data); if (error) return error; + + disable_irq(data->irq); } else if (data->reset_gpio) { msleep(MXT_RESET_GPIO_TIME); gpiod_set_value(data->reset_gpio, 1); msleep(MXT_RESET_INVALID_CHG); } - disable_irq(data->irq); - error = mxt_initialize(data); if (error) return error; -- 2.19.2
[PATCH v2 19/49] Input: atmel_mxt_ts - add config checksum attribute to sysfs
From: karl tsou Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit 03477477ddbe5dcad42853ab3f84166a8f807acf) [gdavis: Forward port and fix conflicts.] Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 923ceb5118c5..77a1f8209cee 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -3128,6 +3128,15 @@ static int mxt_configure_objects(struct mxt_data *data, return error; } +/* Configuration crc check sum is returned as hex xx */ +static ssize_t mxt_config_crc_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mxt_data *data = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%06x\n", data->config_crc); +} + /* Firmware Version is returned as Major.Minor.Build */ static ssize_t mxt_fw_version_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -3481,12 +3490,14 @@ static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL); static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL); static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL); static DEVICE_ATTR(update_cfg, S_IWUSR, NULL, mxt_update_cfg_store); +static DEVICE_ATTR(config_crc, S_IRUGO, mxt_config_crc_show, NULL); static struct attribute *mxt_attrs[] = { &dev_attr_fw_version.attr, &dev_attr_hw_version.attr, &dev_attr_object.attr, &dev_attr_update_cfg.attr, + &dev_attr_config_crc.attr, NULL }; -- 2.19.2
[PATCH v2 18/49] Input: atmel_mxt_ts - allow input name to be specified in platform data
From: Nick Dyer Android systems identify the input device and map to IDC file by using the input device name. To avoid unnecessary deltas to the driver file, allow this to be set from the platform data. Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit cbf94a7bda754d2e1899d9f50313a0bccc91422d) [gdavis: Resolve forward port conflicts due to applying upstream commit 96a938aa214e ("Input: atmel_mxt_ts - remove platform data support").] Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- .../devicetree/bindings/input/atmel,maxtouch.txt | 2 ++ drivers/input/touchscreen/atmel_mxt_ts.c | 9 - 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt index 713ce870805c..d7db16920083 100644 --- a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt +++ b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt @@ -40,6 +40,8 @@ Optional properties for main touchpad device: - atmel,cfg_name: Provide name of configuration file in OBP_RAW format. This will be downloaded from the firmware loader on probe to the device. +- atmel,input_name: Override name of input device from the default. + Example: touch@4b { diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index c6be716a974c..923ceb5118c5 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -336,6 +336,7 @@ struct mxt_data { char *fw_name; char *cfg_name; const char *pcfg_name; + const char *input_name; /* Cached parameters from object table */ u16 T5_address; @@ -2412,7 +2413,11 @@ static int mxt_initialize_input_device(struct mxt_data *data) if (!input_dev) return -ENOMEM; - input_dev->name = "Atmel maXTouch Touchscreen"; + if (data->input_name) + input_dev->name = data->input_name; + else + input_dev->name = "Atmel maXTouch Touchscreen"; + input_dev->phys = data->phys; input_dev->id.bustype = BUS_I2C; input_dev->dev.parent = dev; @@ -3653,6 +3658,8 @@ static int mxt_parse_device_properties(struct mxt_data *data) device_property_read_string(dev, "atmel,cfg_name", &data->pcfg_name); + device_property_read_string(dev, "atmel,input_name", &data->input_name); + if (device_property_present(dev, keymap_property)) { n_keys = device_property_read_u32_array(dev, keymap_property, NULL, 0); -- 2.19.2
[PATCH v2 16/49] Input: atmel_mxt_ts - allow specification of firmware file name
From: Nick Dyer On platforms which have multiple device instances using this driver, the firmware may be different on each device. This patch makes the user give the name of the firmware file when flashing. This also prevents accidental triggering of the firmware load process. Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen (cherry picked from ndyer/linux/for-upstream commit 76ebb7cee971cb42dfb0a3a9224403b8b09abcf1) [gdavis: Forward port and fix conflicts.] Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 43 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 641dd14489e1..14f665f12778 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -33,8 +33,7 @@ #include #include -/* Firmware files */ -#define MXT_FW_NAME"maxtouch.fw" +/* Configuration file */ #define MXT_CFG_NAME "maxtouch.cfg" #define MXT_CFG_MAGIC "OBP_RAW V1" @@ -335,6 +334,7 @@ struct mxt_data { bool use_retrigen_workaround; struct regulator *reg_vdd; struct regulator *reg_avdd; + char *fw_name; /* Cached parameters from object table */ u16 T5_address; @@ -3207,7 +3207,7 @@ static int mxt_check_firmware_format(struct device *dev, return -EINVAL; } -static int mxt_load_fw(struct device *dev, const char *fn) +static int mxt_load_fw(struct device *dev) { struct mxt_data *data = dev_get_drvdata(dev); const struct firmware *fw = NULL; @@ -3217,9 +3217,9 @@ static int mxt_load_fw(struct device *dev, const char *fn) unsigned int frame = 0; int ret; - ret = request_firmware(&fw, fn, dev); + ret = request_firmware(&fw, data->fw_name, dev); if (ret) { - dev_err(dev, "Unable to open firmware %s\n", fn); + dev_err(dev, "Unable to open firmware %s\n", data->fw_name); return ret; } @@ -3339,6 +3339,33 @@ static int mxt_load_fw(struct device *dev, const char *fn) return ret; } +static int mxt_update_file_name(struct device *dev, char **file_name, + const char *buf, size_t count) +{ + char *file_name_tmp; + + /* Simple sanity check */ + if (count > 64) { + dev_warn(dev, "File name too long\n"); + return -EINVAL; + } + + file_name_tmp = krealloc(*file_name, count + 1, GFP_KERNEL); + if (!file_name_tmp) + return -ENOMEM; + + *file_name = file_name_tmp; + memcpy(*file_name, buf, count); + + /* Echo into the sysfs entry may append newline at the end of buf */ + if (buf[count - 1] == '\n') + (*file_name)[count - 1] = '\0'; + else + (*file_name)[count] = '\0'; + + return 0; +} + static ssize_t mxt_update_fw_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -3346,7 +3373,11 @@ static ssize_t mxt_update_fw_store(struct device *dev, struct mxt_data *data = dev_get_drvdata(dev); int error; - error = mxt_load_fw(dev, MXT_FW_NAME); + error = mxt_update_file_name(dev, &data->fw_name, buf, count); + if (error) + return error; + + error = mxt_load_fw(dev); if (error) { dev_err(dev, "The firmware update failed(%d)\n", error); count = error; -- 2.19.2
[PATCH v2 15/49] Input: atmel_mxt_ts - report failures in suspend/resume
From: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit 93a57575403de4dd07cd64807d3c2ed7f2cca262) [gdavis: Resolve forward port conflicts due to applying upstream commit 96a938aa214e ("Input: atmel_mxt_ts - remove platform data support").] Signed-off-by: George G. Davis [jiada: Fix compilation warning] Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 51 ++-- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 83ac2f1ba3be..641dd14489e1 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -3425,10 +3425,12 @@ static void mxt_reset_slots(struct mxt_data *data) mxt_input_sync(data); } -static void mxt_start(struct mxt_data *data) +static int mxt_start(struct mxt_data *data) { + int ret = 0; + if (!data->suspended || data->in_bootloader) - return; + return 0; switch (data->suspend_mode) { case MXT_SUSPEND_T9_CTRL: @@ -3453,28 +3455,42 @@ static void mxt_start(struct mxt_data *data) */ mxt_process_messages_until_invalid(data); - mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN); + ret = mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN); + if (ret) + return ret; /* Recalibrate since chip has been in deep sleep */ - mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false); + ret = mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false); + if (ret) + return ret; + + ret = mxt_acquire_irq(data); + if (ret) + return ret; - mxt_acquire_irq(data); break; } data->suspended = false; + + return 0; } -static void mxt_stop(struct mxt_data *data) +static int mxt_stop(struct mxt_data *data) { + int ret; + if (data->suspended || data->in_bootloader) - return; + return 0; switch (data->suspend_mode) { case MXT_SUSPEND_T9_CTRL: /* Touch disable */ - mxt_write_object(data, + ret = mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_T9_CTRL, 0); + if (ret) + return ret; + break; case MXT_SUSPEND_REGULATOR: @@ -3487,29 +3503,40 @@ static void mxt_stop(struct mxt_data *data) default: disable_irq(data->irq); - mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP); + ret = mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP); + if (ret) + return ret; mxt_reset_slots(data); break; } data->suspended = true; + return 0; } static int mxt_input_open(struct input_dev *dev) { struct mxt_data *data = input_get_drvdata(dev); + int ret; - mxt_start(data); + ret = mxt_start(data); - return 0; + if (ret) + dev_err(&data->client->dev, "%s failed rc=%d\n", __func__, ret); + + return ret; } static void mxt_input_close(struct input_dev *dev) { struct mxt_data *data = input_get_drvdata(dev); + int ret; - mxt_stop(data); + ret = mxt_stop(data); + + if (ret) + dev_err(&data->client->dev, "%s failed rc=%d\n", __func__, ret); } static int mxt_parse_device_properties(struct mxt_data *data) -- 2.19.2
[PATCH v2 17/49] Input: atmel_mxt_ts - handle cfg filename via pdata/sysfs
From: Nick Dyer There may be multiple maXTouch chips on a single device which will require different configuration files. Add a platform data value for the configuration filename. Add sysfs entry to write configuration file if the platform data is not set. Split out the object initialisation code from mxt_initialize() into mxt_configure_objects() to allow this. Signed-off-by: Nick Dyer Acked-by: Yufeng Shen (cherry picked from ndyer/linux/for-upstream commit 71a2a4d1954460b949a16b607f72bafab294ca79) [gdavis: Resolve forward port conflicts due to applying upstream commit 96a938aa214e ("Input: atmel_mxt_ts - remove platform data support").] Signed-off-by: George G. Davis [gdavis: Squash fix from Vladimir Zapolskiy: - Input: atmel_mxt_ts - fix error paths in mxt_configure_objects()] Signed-off-by: Vladimir Zapolskiy --- Notes: - Squash fix from Vladimir Zapolskiy: + Input: atmel_mxt_ts - fix error paths in mxt_configure_objects() Fail in mxt_update_cfg() is critical, because the driver state machine is broken and it can not be safely used afterwards. [jiada: Squash fix from ndyer/linux/for-upstream commit c909ada856861f305653b127db3ea0fa60264331 - Input: atmel_mxt_ts - check data->input_dev is not null in mxt_input_sync()] Signed-off-by: Jiada Wang --- .../bindings/input/atmel,maxtouch.txt | 3 + drivers/input/touchscreen/atmel_mxt_ts.c | 109 +++--- 2 files changed, 97 insertions(+), 15 deletions(-) diff --git a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt index e28139ce3cae..713ce870805c 100644 --- a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt +++ b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt @@ -37,6 +37,9 @@ Optional properties for main touchpad device: MXT_SUSPEND_REGULATOR - use regulators to power down device during suspend Definitions are in . +- atmel,cfg_name: Provide name of configuration file in OBP_RAW format. This +will be downloaded from the firmware loader on probe to the device. + Example: touch@4b { diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 14f665f12778..c6be716a974c 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -34,7 +34,6 @@ #include /* Configuration file */ -#define MXT_CFG_NAME "maxtouch.cfg" #define MXT_CFG_MAGIC "OBP_RAW V1" /* Registers */ @@ -335,6 +334,8 @@ struct mxt_data { struct regulator *reg_vdd; struct regulator *reg_avdd; char *fw_name; + char *cfg_name; + const char *pcfg_name; /* Cached parameters from object table */ u16 T5_address; @@ -377,6 +378,9 @@ struct mxt_data { /* Indicates whether device is in suspend */ bool suspended; + + /* Indicates whether device is updating configuration */ + bool updating_config; }; struct mxt_vb2_buffer { @@ -833,9 +837,11 @@ static void mxt_input_button(struct mxt_data *data, u8 *message) static void mxt_input_sync(struct mxt_data *data) { - input_mt_report_pointer_emulation(data->input_dev, - data->t19_num_keys); - input_sync(data->input_dev); + if (data->input_dev) { + input_mt_report_pointer_emulation(data->input_dev, + data->t19_num_keys); + input_sync(data->input_dev); + } } static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) @@ -2578,13 +2584,21 @@ static int mxt_initialize(struct mxt_data *data) if (error) return error; - error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, - &client->dev, GFP_KERNEL, data, - mxt_config_cb); - if (error) { - dev_err(&client->dev, "Failed to invoke firmware loader: %d\n", - error); - goto err_free_sysfs; + if (data->cfg_name) { + error = request_firmware_nowait(THIS_MODULE, true, + data->cfg_name, + &client->dev, + GFP_KERNEL, data, + mxt_config_cb); + if (error) { + dev_err(&client->dev, "Failed to invoke firmware loader: %d\n", + error); + goto err_free_sysfs; + } + } else { + error = mxt_configure_objects(data, NULL); + if (error) + goto err_free_sysfs; } return 0; @@ -3081,19 +3095,21 @@ static int mxt_configure_objects(struct mxt_data *
Re: [PATCH] powerpc: Perform a bounds check in arch_add_memory
On Tue 27-08-19 15:20:46, Alastair D'Silva wrote: > From: Alastair D'Silva > > It is possible for firmware to allocate memory ranges outside > the range of physical memory that we support (MAX_PHYSMEM_BITS). Doesn't that count as a FW bug? Do you have any evidence of that in the field? Just wondering... > This patch adds a bounds check to ensure that any hotplugged > memory is addressable. > > Signed-off-by: Alastair D'Silva > --- > arch/powerpc/mm/mem.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c > index 9191a66b3bc5..de18fb73de30 100644 > --- a/arch/powerpc/mm/mem.c > +++ b/arch/powerpc/mm/mem.c > @@ -111,6 +111,9 @@ int __ref arch_add_memory(int nid, u64 start, u64 size, > unsigned long nr_pages = size >> PAGE_SHIFT; > int rc; > > + if ((start + size - 1) >> MAX_PHYSMEM_BITS) > + return -EINVAL; > + > resize_hpt_for_hotplug(memblock_phys_mem_size()); > > start = (unsigned long)__va(start); > -- > 2.21.0 -- Michal Hocko SUSE Labs
[PATCH v2 14/49] Input: atmel_mxt_ts - add regulator control support
From: Nick Dyer Allow the driver to optionally manage enabling/disable power to the touch controller itself. If the regulators are not present then use the deep sleep power mode instead. For a correct power on sequence, it is required that we have control over the RESET line. Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen (cherry picked from ndyer/linux/for-upstream commit 14052b61bb66c2f2283c00e733e131be7a9b8bfc) [gdavis: Resolve forward port conflicts due to v4.14-rc1 commmit f657b00df22e ("Input: atmel_mxt_ts - add support for reset line") and applying upstream commit 96a938aa214e ("Input: atmel_mxt_ts - remove platform data support").] Signed-off-by: George G. Davis [gdavis: Squash fixes from Dirk Behme: - Input: atmel_mxt_ts - in failure case disable the regulator - Input: atmel_mxt_ts - disable only enabled regulators - Input: atmel_mxt_ts - use devm_regulator_get()] Signed-off-by: Dirk Behme --- Notes: - Squash fixes by Dirk Behme: + Input: atmel_mxt_ts - in failure case disable the regulator If the second regulator_enable(), disable the previously enabled regulator, again. + Input: atmel_mxt_ts - disable only enabled regulators As enabling the regulators in mxt_regulator_enable() might fail, check if the regulators are really enabled and disable them only in this case. + Input: atmel_mxt_ts - use devm_regulator_get() Switch to devm_regulator_get() enabling us to drop the regulator_put() in the remove function. [jiada: Resolve forward port conflicts due to commit 5cecc2bccc03f ("Input: atmel_mxt_ts - fix -Wunused-const-variable")] Signed-off-by: Jiada Wang --- .../bindings/input/atmel,maxtouch.txt | 6 + MAINTAINERS | 1 + drivers/input/touchscreen/atmel_mxt_ts.c | 129 -- include/dt-bindings/input/atmel_mxt_ts.h | 22 +++ 4 files changed, 149 insertions(+), 9 deletions(-) create mode 100644 include/dt-bindings/input/atmel_mxt_ts.h diff --git a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt index c88919480d37..e28139ce3cae 100644 --- a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt +++ b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt @@ -31,6 +31,12 @@ Optional properties for main touchpad device: - reset-gpios: GPIO specifier for the touchscreen's reset pin (active low) +- atmel,suspend-mode: Select method used to suspend: +MXT_SUSPEND_DEEP_SLEEP - use T7 to suspend the device into deep sleep +MXT_SUSPEND_T9_CTRL - use T9.CTRL to turn off touch processing +MXT_SUSPEND_REGULATOR - use regulators to power down device during suspend +Definitions are in . + Example: touch@4b { diff --git a/MAINTAINERS b/MAINTAINERS index 47800d32cfbc..1509bb9072fc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2777,6 +2777,7 @@ T:git git://github.com/ndyer/linux.git S: Maintained F: Documentation/devicetree/bindings/input/atmel,maxtouch.txt F: drivers/input/touchscreen/atmel_mxt_ts.c +F: include/dt-bindings/input/atmel_mxt_ts.h ATMEL WIRELESS DRIVER M: Simon Kelley diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 4d28b30c4f76..83ac2f1ba3be 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -26,10 +26,12 @@ #include #include #include +#include #include #include #include #include +#include /* Firmware files */ #define MXT_FW_NAME"maxtouch.fw" @@ -215,6 +217,9 @@ enum t100_type { #define MXT_CRC_TIMEOUT1000/* msec */ #define MXT_FW_RESET_TIME 3000/* msec */ #define MXT_FW_CHG_TIMEOUT 300 /* msec */ +#define MXT_REGULATOR_DELAY150 /* msec */ +#define MXT_CHG_DELAY 100 /* msec */ +#define MXT_POWERON_DELAY 150 /* msec */ /* Command to unlock bootloader */ #define MXT_UNLOCK_CMD_MSB 0xaa @@ -275,11 +280,6 @@ enum v4l_dbg_inputs { MXT_V4L_INPUT_MAX, }; -enum mxt_suspend_mode { - MXT_SUSPEND_DEEP_SLEEP = 0, - MXT_SUSPEND_T9_CTRL = 1, -}; - /* Config update context */ struct mxt_cfg { u8 *raw; @@ -333,6 +333,8 @@ struct mxt_data { u8 stylus_aux_pressure; u8 stylus_aux_peak; bool use_retrigen_workaround; + struct regulator *reg_vdd; + struct regulator *reg_avdd; /* Cached parameters from object table */ u16 T5_address; @@ -2073,6 +2075,94 @@ static int mxt_read_info_block(struct mxt_data *data) return error; } +static void mxt_regulator_enable(struct mxt_data *data) +{ + int error; + + if (!data->reg_vdd || !data->reg_avdd) + return; + + gpiod_set_value(data->reset_gpio, 0); + + error = regulator_ena
[PATCH v2 05/49] Input: atmel_mxt_ts - split large i2c transfers into blocks
From: Nick Dyer On some firmware variants, the size of the info block exceeds what can be read in a single transfer. Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit 74c4f5277cfa403d43fafc404119dc57a08677db) [gdavis: Forward port and fix conflicts due to v4.14.51 commit 960fe000b1d3 ("Input: atmel_mxt_ts - fix the firmware update").] Signed-off-by: George G. Davis [jiada: Change mxt_read_blks() to __mxt_read_reg(), original __mxt_read_reg() to __mxt_read_chunk()] Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 28 +--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 35cbe60094ab..45bab5253775 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -40,7 +40,7 @@ #define MXT_OBJECT_START 0x07 #define MXT_OBJECT_SIZE6 #define MXT_INFO_CHECKSUM_SIZE 3 -#define MXT_MAX_BLOCK_WRITE256 +#define MXT_MAX_BLOCK_WRITE255 /* Object types */ #define MXT_DEBUG_DIAGNOSTIC_T37 37 @@ -624,8 +624,8 @@ static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock) return 0; } -static int __mxt_read_reg(struct i2c_client *client, - u16 reg, u16 len, void *val) +static int __mxt_read_chunk(struct i2c_client *client, + u16 reg, u16 len, void *val) { struct i2c_msg xfer[2]; u8 buf[2]; @@ -659,6 +659,28 @@ static int __mxt_read_reg(struct i2c_client *client, return ret; } +static int __mxt_read_reg(struct i2c_client *client, + u16 reg, u16 len, void *buf) +{ + u16 offset = 0; + int error; + u16 size; + + while (offset < len) { + size = min(MXT_MAX_BLOCK_WRITE, len - offset); + + error = __mxt_read_chunk(client, +reg + offset, +size, buf + offset); + if (error) + return error; + + offset += size; + } + + return 0; +} + static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len, const void *val) { -- 2.19.2
[PATCH v2 06/49] Input: atmel_mxt_ts - output status from T48 Noise Supression
From: Nick Dyer Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen (cherry picked from ndyer/linux/for-upstream commit 2895a6ff150a49f27a02938f8d262be238b296d8) Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 25 1 file changed, 25 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 45bab5253775..351347e2eced 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -324,6 +324,7 @@ struct mxt_data { u16 T18_address; u8 T19_reportid; u16 T44_address; + u8 T48_reportid; u8 T100_reportid_min; u8 T100_reportid_max; @@ -978,6 +979,24 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) data->update_input = true; } +static int mxt_proc_t48_messages(struct mxt_data *data, u8 *msg) +{ + struct device *dev = &data->client->dev; + u8 status, state; + + status = msg[1]; + state = msg[4]; + + dev_dbg(dev, "T48 state %d status %02X %s%s%s%s%s\n", state, status, + status & 0x01 ? "FREQCHG " : "", + status & 0x02 ? "APXCHG " : "", + status & 0x04 ? "ALGOERR " : "", + status & 0x10 ? "STATCHG " : "", + status & 0x20 ? "NLVLCHG " : ""); + + return 0; +} + static int mxt_proc_message(struct mxt_data *data, u8 *message) { u8 report_id = message[0]; @@ -987,6 +1006,8 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message) if (report_id == data->T6_reportid) { mxt_proc_t6_messages(data, message); + } else if (report_id == data->T48_reportid) { + mxt_proc_t48_messages(data, message); } else if (!data->input_dev) { /* * Do not report events if input device @@ -1666,6 +1687,7 @@ static void mxt_free_object_table(struct mxt_data *data) data->T18_address = 0; data->T19_reportid = 0; data->T44_address = 0; + data->T48_reportid = 0; data->T100_reportid_min = 0; data->T100_reportid_max = 0; data->max_reportid = 0; @@ -1747,6 +1769,9 @@ static int mxt_parse_object_table(struct mxt_data *data, case MXT_SPT_GPIOPWM_T19: data->T19_reportid = min_id; break; + case MXT_PROCG_NOISESUPPRESSION_T48: + data->T48_reportid = min_id; + break; case MXT_TOUCH_MULTITOUCHSCREEN_T100: data->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100; data->T100_reportid_min = min_id; -- 2.19.2
[PATCH v2 13/49] Input: atmel_mxt_ts - release touch state during suspend
From: Nick Dyer If fingers are down as the MXT chip goes into suspend it does not send a lift message. In addition, it may not complete its final measurement cycle immediately, which means touch messages may be received by the interrupt handler after mxt_stop() has completed. So: - disable irq during suspend - flush any messages created after suspend - tell app layer that slots were released at suspend Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen (cherry picked from ndyer/linux/for-upstream commit 26794433086dbc7dea18d2f6a1c8d61ab25bcfda) [gdavis: Resolve forward port conflicts due to applying upstream commit 96a938aa214e ("Input: atmel_mxt_ts - remove platform data support").] Signed-off-by: George G. Davis [gdavis: Squash fix from Dirk Behme: - Input: atmel_mxt_ts - remove superfluous data->suspended] Signed-off-by: Dirk Behme --- Notes: - Squash fix from Dirk Behme: + Input: atmel_mxt_ts - remove superfluous data->suspended data->suspended is already set to false in mxt_load_fw(), so it's not needed here. Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 52 ++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 26861252c088..4d28b30c4f76 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -372,6 +372,9 @@ struct mxt_data { unsigned int t19_num_keys; enum mxt_suspend_mode suspend_mode; + + /* Indicates whether device is in suspend */ + bool suspended; }; struct mxt_vb2_buffer { @@ -1151,10 +1154,10 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message) mxt_proc_t42_messages(data, message); } else if (report_id == data->T48_reportid) { mxt_proc_t48_messages(data, message); - } else if (!data->input_dev) { + } else if (!data->input_dev || data->suspended) { /* -* Do not report events if input device -* is not yet registered. +* Do not report events if input device is not +* yet registered or returning from suspend */ mxt_dump_message(data, message); } else if (report_id >= data->T9_reportid_min && @@ -3135,6 +3138,11 @@ static int mxt_load_fw(struct device *dev, const char *fn) if (ret) goto release_firmware; + if (data->suspended) { + enable_irq(data->irq); + data->suspended = false; + } + if (!data->in_bootloader) { /* Change to the bootloader mode */ data->in_bootloader = true; @@ -3306,8 +3314,27 @@ static void mxt_sysfs_remove(struct mxt_data *data) sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); } +static void mxt_reset_slots(struct mxt_data *data) +{ + struct input_dev *input_dev = data->input_dev; + int id; + + if (!input_dev) + return; + + for (id = 0; id < data->num_touchids; id++) { + input_mt_slot(input_dev, id); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0); + } + + mxt_input_sync(data); +} + static void mxt_start(struct mxt_data *data) { + if (!data->suspended || data->in_bootloader) + return; + switch (data->suspend_mode) { case MXT_SUSPEND_T9_CTRL: mxt_soft_reset(data); @@ -3320,16 +3347,29 @@ static void mxt_start(struct mxt_data *data) case MXT_SUSPEND_DEEP_SLEEP: default: + /* +* Discard any touch messages still in message buffer +* from before chip went to sleep +*/ + mxt_process_messages_until_invalid(data); + mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN); /* Recalibrate since chip has been in deep sleep */ mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false); + + mxt_acquire_irq(data); break; } + + data->suspended = false; } static void mxt_stop(struct mxt_data *data) { + if (data->suspended || data->in_bootloader) + return; + switch (data->suspend_mode) { case MXT_SUSPEND_T9_CTRL: /* Touch disable */ @@ -3339,9 +3379,15 @@ static void mxt_stop(struct mxt_data *data) case MXT_SUSPEND_DEEP_SLEEP: default: + disable_irq(data->irq); + mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP); + + mxt_reset_slots(data); break; } + + data->suspended = true; } static int mxt_input_open(struct input_dev *dev) -- 2.19.2
[PATCH v2 07/49] Input: atmel_mxt_ts - output status from T42 Touch Suppression
From: Nick Dyer Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen (cherry picked from ndyer/linux/for-upstream commit ab95b5a30d2c098daaa9f88d9fcfae7eb516) Signed-off-by: George G. Davis [jiada: Replace dev_info() with dev_dbg()] Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 25 1 file changed, 25 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 351347e2eced..19fa3e58269a 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -155,6 +155,9 @@ struct t37_debug { #define MXT_RESET_VALUE0x01 #define MXT_BACKUP_VALUE 0x55 +/* Define for MXT_PROCI_TOUCHSUPPRESSION_T42 */ +#define MXT_T42_MSG_TCHSUP BIT(0) + /* T100 Multiple Touch Touchscreen */ #define MXT_T100_CTRL 0 #define MXT_T100_CFG1 1 @@ -323,6 +326,8 @@ struct mxt_data { u8 T9_reportid_max; u16 T18_address; u8 T19_reportid; + u8 T42_reportid_min; + u8 T42_reportid_max; u16 T44_address; u8 T48_reportid; u8 T100_reportid_min; @@ -979,6 +984,17 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) data->update_input = true; } +static void mxt_proc_t42_messages(struct mxt_data *data, u8 *msg) +{ + struct device *dev = &data->client->dev; + u8 status = msg[1]; + + if (status & MXT_T42_MSG_TCHSUP) + dev_dbg(dev, "T42 suppress\n"); + else + dev_dbg(dev, "T42 normal\n"); +} + static int mxt_proc_t48_messages(struct mxt_data *data, u8 *msg) { struct device *dev = &data->client->dev; @@ -1006,6 +1022,9 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message) if (report_id == data->T6_reportid) { mxt_proc_t6_messages(data, message); + } else if (report_id >= data->T42_reportid_min + && report_id <= data->T42_reportid_max) { + mxt_proc_t42_messages(data, message); } else if (report_id == data->T48_reportid) { mxt_proc_t48_messages(data, message); } else if (!data->input_dev) { @@ -1686,6 +1705,8 @@ static void mxt_free_object_table(struct mxt_data *data) data->T9_reportid_max = 0; data->T18_address = 0; data->T19_reportid = 0; + data->T42_reportid_min = 0; + data->T42_reportid_max = 0; data->T44_address = 0; data->T48_reportid = 0; data->T100_reportid_min = 0; @@ -1763,6 +1784,10 @@ static int mxt_parse_object_table(struct mxt_data *data, case MXT_SPT_COMMSCONFIG_T18: data->T18_address = object->start_address; break; + case MXT_PROCI_TOUCHSUPPRESSION_T42: + data->T42_reportid_min = min_id; + data->T42_reportid_max = max_id; + break; case MXT_SPT_MESSAGECOUNT_T44: data->T44_address = object->start_address; break; -- 2.19.2
[PATCH v2 11/49] Input: atmel_mxt_ts - implement support for T107 active stylus
From: Nick Dyer Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit 20e357dd9acf8c2040068c8b22d6bc1401a1893f) [gdavis: Forward port and fix conflicts due to applying upstream commit 96a938aa214e ("Input: atmel_mxt_ts - remove platform data support").] Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 117 ++- 1 file changed, 113 insertions(+), 4 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 83dad225458e..4e237209cb34 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -72,6 +72,7 @@ #define MXT_SPT_CTECONFIG_T46 46 #define MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71 71 #define MXT_TOUCH_MULTITOUCHSCREEN_T100 100 +#define MXT_PROCI_ACTIVESTYLUS_T107107 /* MXT_GEN_MESSAGE_T5 object */ #define MXT_RPTID_NOMSG0xff @@ -181,6 +182,7 @@ struct t37_debug { enum t100_type { MXT_T100_TYPE_FINGER= 1, MXT_T100_TYPE_PASSIVE_STYLUS= 2, + MXT_T100_TYPE_ACTIVE_STYLUS = 3, MXT_T100_TYPE_HOVERING_FINGER = 4, MXT_T100_TYPE_GLOVE = 5, MXT_T100_TYPE_LARGE_TOUCH = 6, @@ -192,6 +194,16 @@ enum t100_type { #define MXT_TOUCH_MAJOR_DEFAULT1 #define MXT_PRESSURE_DEFAULT 1 +/* Gen2 Active Stylus */ +#define MXT_T107_STYLUS_STYAUX 42 +#define MXT_T107_STYLUS_STYAUX_PRESSUREBIT(0) +#define MXT_T107_STYLUS_STYAUX_PEAKBIT(4) + +#define MXT_T107_STYLUS_HOVER BIT(0) +#define MXT_T107_STYLUS_TIPSWITCH BIT(1) +#define MXT_T107_STYLUS_BUTTON0BIT(2) +#define MXT_T107_STYLUS_BUTTON1BIT(3) + /* Delay times */ #define MXT_BACKUP_TIME50 /* msec */ #define MXT_RESET_GPIO_TIME20 /* msec */ @@ -313,10 +325,12 @@ struct mxt_data { struct t7_config t7_cfg; struct mxt_dbg dbg; struct gpio_desc *reset_gpio; - bool use_retrigen_workaround; unsigned long t15_keystatus; int t15_num_keys; const unsigned int *t15_keymap; + u8 stylus_aux_pressure; + u8 stylus_aux_peak; + bool use_retrigen_workaround; /* Cached parameters from object table */ u16 T5_address; @@ -337,6 +351,7 @@ struct mxt_data { u8 T48_reportid; u8 T100_reportid_min; u8 T100_reportid_max; + u16 T107_address; /* for fw update in bootloader */ struct completion bl_completion; @@ -908,6 +923,8 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) u8 major = 0; u8 pressure = 0; u8 orientation = 0; + bool active = false; + bool hover = false; id = message[0] - data->T100_reportid_min - 2; @@ -926,6 +943,8 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) case MXT_T100_TYPE_HOVERING_FINGER: tool = MT_TOOL_FINGER; distance = MXT_DISTANCE_HOVERING; + hover = true; + active = true; if (data->t100_aux_vect) orientation = message[data->t100_aux_vect]; @@ -936,6 +955,8 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) case MXT_T100_TYPE_GLOVE: tool = MT_TOOL_FINGER; distance = MXT_DISTANCE_ACTIVE_TOUCH; + hover = false; + active = true; if (data->t100_aux_area) major = message[data->t100_aux_area]; @@ -950,6 +971,9 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) case MXT_T100_TYPE_PASSIVE_STYLUS: tool = MT_TOOL_PEN; + distance = MXT_DISTANCE_ACTIVE_TOUCH; + hover = false; + active = true; /* * Passive stylus is reported with size zero so @@ -962,6 +986,31 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) break; + case MXT_T100_TYPE_ACTIVE_STYLUS: + /* Report input buttons */ + input_report_key(input_dev, BTN_STYLUS, +message[6] & MXT_T107_STYLUS_BUTTON0); + input_report_key(input_dev, BTN_STYLUS2, +message[6] & MXT_T107_STYLUS_BUTTON1); + + /* stylus in range, but position unavailable */ + if (!(message[6] & MXT_T107_STYLUS_HOVER)) + break; + + tool = MT_TOOL_
[PATCH v2 08/49] Input: atmel_mxt_ts - implement T9 vector/orientation support
From: Nick Dyer The atmel touch messages contain orientation information as a byte in a packed format which can be passed straight on to Android if the input device configuration is correct. This requires vector reports to be enabled in maXTouch config (zero DISVECT bit 3 in T9 CTRL field) Android converts the format in InputReader.cpp, search for ORIENTATION_CALIBRATION_VECTOR. Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen (cherry picked from ndyer/linux/for-upstream commit a6f0ee919d2631678169b23fb18f55b6dbabcd4c) Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 19fa3e58269a..68c8237f7932 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -817,6 +817,7 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) int y; int area; int amplitude; + u8 vector; id = message[0] - data->T9_reportid_min; status = message[1]; @@ -831,9 +832,10 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) area = message[5]; amplitude = message[6]; + vector = message[7]; dev_dbg(dev, - "[%u] %c%c%c%c%c%c%c%c x: %5u y: %5u area: %3u amp: %3u\n", + "[%u] %c%c%c%c%c%c%c%c x: %5u y: %5u area: %3u amp: %3u vector: %02X\n", id, (status & MXT_T9_DETECT) ? 'D' : '.', (status & MXT_T9_PRESS) ? 'P' : '.', @@ -843,7 +845,7 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) (status & MXT_T9_AMP) ? 'A' : '.', (status & MXT_T9_SUPPRESS) ? 'S' : '.', (status & MXT_T9_UNGRIP) ? 'U' : '.', - x, y, area, amplitude); + x, y, area, amplitude, vector); input_mt_slot(input_dev, id); @@ -868,6 +870,7 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) input_report_abs(input_dev, ABS_MT_POSITION_Y, y); input_report_abs(input_dev, ABS_MT_PRESSURE, amplitude); input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, area); + input_report_abs(input_dev, ABS_MT_ORIENTATION, vector); } else { /* Touch no longer active, close out slot */ input_mt_report_slot_inactive(input_dev); @@ -2180,8 +2183,9 @@ static int mxt_initialize_input_device(struct mxt_data *data) 0, 255, 0, 0); } - if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && - data->t100_aux_vect) { + if (data->multitouch == MXT_TOUCH_MULTI_T9 || + (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && + data->t100_aux_vect)) { input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 255, 0, 0); } -- 2.19.2
[PATCH v2 09/49] Input: atmel_mxt_ts - implement T15 Key Array support
From: Nick Dyer There is a key array object in many maXTouch chips which allows some X/Y lines to be used as a key array. This patch maps them to a series of keys which may be configured in a platform data array. Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen (cherry picked from ndyer/linux/for-upstream commit 15bb074b5abf3a101f7b79544213f1c110ea4cab) [gdavis: Resolve forward port conflicts due to applying upstream commit 96a938aa214e ("Input: atmel_mxt_ts - remove platform data support").] Signed-off-by: George G. Davis [jiada: Fix compilation warning] Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 85 1 file changed, 85 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 68c8237f7932..1d738c488bdd 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -314,6 +314,9 @@ struct mxt_data { struct mxt_dbg dbg; struct gpio_desc *reset_gpio; bool use_retrigen_workaround; + unsigned long t15_keystatus; + int t15_num_keys; + const unsigned int *t15_keymap; /* Cached parameters from object table */ u16 T5_address; @@ -324,6 +327,8 @@ struct mxt_data { u16 T71_address; u8 T9_reportid_min; u8 T9_reportid_max; + u8 T15_reportid_min; + u8 T15_reportid_max; u16 T18_address; u8 T19_reportid; u8 T42_reportid_min; @@ -987,6 +992,38 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) data->update_input = true; } +static void mxt_proc_t15_messages(struct mxt_data *data, u8 *msg) +{ + struct input_dev *input_dev = data->input_dev; + struct device *dev = &data->client->dev; + int key; + bool curr_state, new_state; + bool sync = false; + unsigned long keystates = le32_to_cpu((__force __le32)msg[2]); + + for (key = 0; key < data->t15_num_keys; key++) { + curr_state = test_bit(key, &data->t15_keystatus); + new_state = test_bit(key, &keystates); + + if (!curr_state && new_state) { + dev_dbg(dev, "T15 key press: %u\n", key); + __set_bit(key, &data->t15_keystatus); + input_event(input_dev, EV_KEY, + data->t15_keymap[key], 1); + sync = true; + } else if (curr_state && !new_state) { + dev_dbg(dev, "T15 key release: %u\n", key); + __clear_bit(key, &data->t15_keystatus); + input_event(input_dev, EV_KEY, + data->t15_keymap[key], 0); + sync = true; + } + } + + if (sync) + input_sync(input_dev); +} + static void mxt_proc_t42_messages(struct mxt_data *data, u8 *msg) { struct device *dev = &data->client->dev; @@ -1045,6 +1082,9 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message) } else if (report_id == data->T19_reportid) { mxt_input_button(data, message); data->update_input = true; + } else if (report_id >= data->T15_reportid_min + && report_id <= data->T15_reportid_max) { + mxt_proc_t15_messages(data, message); } else { mxt_dump_message(data, message); } @@ -1706,6 +1746,8 @@ static void mxt_free_object_table(struct mxt_data *data) data->T71_address = 0; data->T9_reportid_min = 0; data->T9_reportid_max = 0; + data->T15_reportid_min = 0; + data->T15_reportid_max = 0; data->T18_address = 0; data->T19_reportid = 0; data->T42_reportid_min = 0; @@ -1784,6 +1826,10 @@ static int mxt_parse_object_table(struct mxt_data *data, object->num_report_ids - 1; data->num_touchids = object->num_report_ids; break; + case MXT_TOUCH_KEYARRAY_T15: + data->T15_reportid_min = min_id; + data->T15_reportid_max = max_id; + break; case MXT_SPT_COMMSCONFIG_T18: data->T18_address = object->start_address; break; @@ -2077,6 +2123,7 @@ static int mxt_initialize_input_device(struct mxt_data *data) int error; unsigned int num_mt_slots; unsigned int mt_flags = 0; + int i; switch (data->multitouch) { case MXT_TOUCH_MULTI_T9: @@ -2190,6 +2237,15 @@ static int mxt_initialize_input_device(struct mxt_data *data) 0, 255, 0, 0); } + /* For T15 Key Array */ + if (data->T15_reportid_min) { + data
[PATCH v2 12/49] Input: atmel_mxt_ts - add debug for T92 gesture and T93 touch seq msgs
From: Karl Tsou Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit cb98986f8342107bf4a536aed4160b20839e97c1) Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 40 1 file changed, 40 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 4e237209cb34..26861252c088 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -71,6 +71,8 @@ #define MXT_SPT_MESSAGECOUNT_T44 44 #define MXT_SPT_CTECONFIG_T46 46 #define MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71 71 +#define MXT_PROCI_SYMBOLGESTUREPROCESSOR 92 +#define MXT_PROCI_TOUCHSEQUENCELOGGER 93 #define MXT_TOUCH_MULTITOUCHSCREEN_T100 100 #define MXT_PROCI_ACTIVESTYLUS_T107107 @@ -349,6 +351,10 @@ struct mxt_data { u8 T42_reportid_max; u16 T44_address; u8 T48_reportid; + u16 T92_address; + u8 T92_reportid; + u16 T93_address; + u8 T93_reportid; u8 T100_reportid_min; u8 T100_reportid_max; u16 T107_address; @@ -1113,6 +1119,24 @@ static int mxt_proc_t48_messages(struct mxt_data *data, u8 *msg) return 0; } +static void mxt_proc_t92_messages(struct mxt_data *data, u8 *msg) +{ + struct device *dev = &data->client->dev; + u8 status = msg[1]; + + dev_info(dev, "T92 long stroke LSTR=%d %d\n", +(status & 0x80) ? 1 : 0, +status & 0x0F); +} + +static void mxt_proc_t93_messages(struct mxt_data *data, u8 *msg) +{ + struct device *dev = &data->client->dev; + u8 status = msg[1]; + + dev_info(dev, "T93 report double tap %d\n", status); +} + static int mxt_proc_message(struct mxt_data *data, u8 *message) { u8 report_id = message[0]; @@ -1145,6 +1169,10 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message) } else if (report_id >= data->T15_reportid_min && report_id <= data->T15_reportid_max) { mxt_proc_t15_messages(data, message); + } else if (report_id == data->T92_reportid) { + mxt_proc_t92_messages(data, message); + } else if (report_id == data->T93_reportid) { + mxt_proc_t93_messages(data, message); } else { mxt_dump_message(data, message); } @@ -1814,6 +1842,10 @@ static void mxt_free_object_table(struct mxt_data *data) data->T42_reportid_max = 0; data->T44_address = 0; data->T48_reportid = 0; + data->T92_reportid = 0; + data->T92_address = 0; + data->T93_reportid = 0; + data->T93_address = 0; data->T100_reportid_min = 0; data->T100_reportid_max = 0; data->max_reportid = 0; @@ -1906,6 +1938,14 @@ static int mxt_parse_object_table(struct mxt_data *data, case MXT_PROCG_NOISESUPPRESSION_T48: data->T48_reportid = min_id; break; + case MXT_PROCI_SYMBOLGESTUREPROCESSOR: + data->T92_reportid = min_id; + data->T92_address = object->start_address; + break; + case MXT_PROCI_TOUCHSEQUENCELOGGER: + data->T93_reportid = min_id; + data->T93_address = object->start_address; + break; case MXT_TOUCH_MULTITOUCHSCREEN_T100: data->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100; data->T100_reportid_min = min_id; -- 2.19.2
[PATCH v2 10/49] Input: atmel_mxt_ts - handle reports from T47 Stylus object
From: Nick Dyer Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen (cherry picked from ndyer/linux/for-upstream commit 56405a5ea08eb34cfe83f3121867c9de0a5c48c1) Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 12 +++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 1d738c488bdd..83dad225458e 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -823,6 +823,7 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) int area; int amplitude; u8 vector; + int tool; id = message[0] - data->T9_reportid_min; status = message[1]; @@ -836,6 +837,7 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) y >>= 2; area = message[5]; + amplitude = message[6]; vector = message[7]; @@ -865,12 +867,20 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) mxt_input_sync(data); } + /* A size of zero indicates touch is from a linked T47 Stylus */ + if (area == 0) { + area = MXT_TOUCH_MAJOR_DEFAULT; + tool = MT_TOOL_PEN; + } else { + tool = MT_TOOL_FINGER; + } + /* if active, pressure must be non-zero */ if (!amplitude) amplitude = MXT_PRESSURE_DEFAULT; /* Touch active */ - input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 1); + input_mt_report_slot_state(input_dev, tool, 1); input_report_abs(input_dev, ABS_MT_POSITION_X, x); input_report_abs(input_dev, ABS_MT_POSITION_Y, y); input_report_abs(input_dev, ABS_MT_PRESSURE, amplitude); -- 2.19.2
[PATCH v2 01/49] Input: switch to use return value of input_mt_report_slot_state
Currently several places are calling input_mt_report_slot_state() like following: input_mt_report_slot_state(dev, tool_type, active) if (active) { ... < report events for active slot > } when 'active' is false, input_mt_report_slot_state() will always return false, so instead of checking 'active', switch to use return value of input_mt_report_slot_state() Signed-off-by: Jiada Wang --- drivers/hid/hid-asus.c | 3 +-- drivers/hid/hid-elan.c | 3 +-- drivers/hid/hid-logitech-hidpp.c| 5 ++--- drivers/hid/hid-magicmouse.c| 3 +-- drivers/hid/hid-multitouch.c| 3 +-- drivers/hid/hid-sony.c | 8 drivers/hid/wacom_wac.c | 15 +-- drivers/input/mouse/elantech.c | 5 ++--- drivers/input/mouse/focaltech.c | 3 +-- drivers/input/mouse/sentelic.c | 3 +-- drivers/input/mouse/synaptics.c | 3 +-- drivers/input/rmi4/rmi_2d_sensor.c | 6 ++ drivers/input/touchscreen/chipone_icn8505.c | 4 ++-- drivers/input/touchscreen/egalax_ts.c | 3 +-- drivers/input/touchscreen/hideep.c | 7 +++ drivers/input/touchscreen/ili210x.c | 3 +-- drivers/input/touchscreen/mms114.c | 4 ++-- drivers/input/touchscreen/penmount.c| 5 ++--- drivers/input/touchscreen/raydium_i2c_ts.c | 4 ++-- drivers/input/touchscreen/sis_i2c.c | 5 ++--- drivers/input/touchscreen/surface3_spi.c| 4 ++-- drivers/input/touchscreen/wacom_w8001.c | 3 +-- drivers/input/touchscreen/zforce_ts.c | 6 ++ 23 files changed, 42 insertions(+), 66 deletions(-) diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index 8063b1d567b1..55f1004f0e58 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c @@ -240,9 +240,8 @@ static int asus_report_input(struct asus_drvdata *drvdat, u8 *data, int size) MT_TOOL_PALM : MT_TOOL_FINGER; input_mt_slot(drvdat->input, i); - input_mt_report_slot_state(drvdat->input, toolType, down); - if (down) { + if (input_mt_report_slot_state(drvdat->input, toolType, down)) { asus_report_contact_down(drvdat, toolType, contactData); contactData += drvdat->tp->contact_size; } diff --git a/drivers/hid/hid-elan.c b/drivers/hid/hid-elan.c index 45c4f888b7c4..84a317c6feb6 100644 --- a/drivers/hid/hid-elan.c +++ b/drivers/hid/hid-elan.c @@ -216,8 +216,7 @@ static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data, bool active = !!data; input_mt_slot(input, slot_num); - input_mt_report_slot_state(input, MT_TOOL_FINGER, active); - if (active) { + if (input_mt_report_slot_state(input, MT_TOOL_FINGER, active)) { x = ((data[0] & 0xF0) << 4) | data[1]; y = drvdata->max_y - (((data[0] & 0x07) << 8) | data[2]); diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 21268c9fa71a..a7b552a797f1 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -2295,9 +2295,8 @@ static void wtp_touch_event(struct hidpp_device *hidpp, slot = input_mt_get_slot_by_key(hidpp->input, touch_report->finger_id); input_mt_slot(hidpp->input, slot); - input_mt_report_slot_state(hidpp->input, MT_TOOL_FINGER, - touch_report->contact_status); - if (touch_report->contact_status) { + if (input_mt_report_slot_state(hidpp->input, MT_TOOL_FINGER, + touch_report->contact_status)) { input_event(hidpp->input, EV_ABS, ABS_MT_POSITION_X, touch_report->x); input_event(hidpp->input, EV_ABS, ABS_MT_POSITION_Y, diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 34138667f8af..5f9f6426d7b8 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -282,10 +282,9 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda msc->ntouches++; input_mt_slot(input, id); - input_mt_report_slot_state(input, MT_TOOL_FINGER, down); /* Generate the input events for this touch. */ - if (down) { + if (input_mt_report_slot_state(input, MT_TOOL_FINGER, down)) { input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2); input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2); input_report_abs(input, ABS_MT_ORIENTATION, -orientation); diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index b603c14d043b..672396ed413e 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1020,8 +1020,7
[PATCH v2 02/49] Input: introduce input_mt_report_slot_inactive
input_mt_report_slot_state() ignores the tool when the slot is closed. which has caused a bit of confusion. This patch introduces input_mt_report_slot_inactive() to report slot inactive state. replaces all input_mt_report_slot_state() with input_mt_report_slot_inactive() in case of close of slot. Signed-off-by: Jiada Wang --- drivers/hid/hid-alps.c | 3 +-- drivers/hid/hid-multitouch.c | 6 ++ drivers/input/input-mt.c | 2 +- drivers/input/misc/xen-kbdfront.c | 2 +- drivers/input/mouse/elan_i2c_core.c| 2 +- drivers/input/touchscreen/atmel_mxt_ts.c | 7 +++ drivers/input/touchscreen/cyttsp4_core.c | 5 ++--- drivers/input/touchscreen/cyttsp_core.c| 2 +- drivers/input/touchscreen/melfas_mip4.c| 4 ++-- drivers/input/touchscreen/mms114.c | 2 +- drivers/input/touchscreen/raspberrypi-ts.c | 2 +- drivers/input/touchscreen/stmfts.c | 2 +- include/linux/input/mt.h | 5 + 13 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c index ae79a7c66737..36ca1d815d53 100644 --- a/drivers/hid/hid-alps.c +++ b/drivers/hid/hid-alps.c @@ -387,8 +387,7 @@ static int u1_raw_event(struct alps_dev *hdata, u8 *data, int size) input_report_abs(hdata->input, ABS_MT_PRESSURE, z); } else { - input_mt_report_slot_state(hdata->input, - MT_TOOL_FINGER, 0); + input_mt_report_slot_inactive(hdata->input); } } diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 672396ed413e..b2221f2030c1 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -880,7 +880,7 @@ static void mt_release_pending_palms(struct mt_device *td, clear_bit(slotnum, app->pending_palm_slots); input_mt_slot(input, slotnum); - input_mt_report_slot_state(input, MT_TOOL_PALM, false); + input_mt_report_slot_inactive(input); need_sync = true; } @@ -1620,9 +1620,7 @@ static void mt_release_contacts(struct hid_device *hid) if (mt) { for (i = 0; i < mt->num_slots; i++) { input_mt_slot(input_dev, i); - input_mt_report_slot_state(input_dev, - MT_TOOL_FINGER, - false); + input_mt_report_slot_inactive(input_dev); } input_mt_sync_frame(input_dev); input_sync(input_dev); diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index a81e14148407..7626fe5bfe44 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -145,7 +145,7 @@ bool input_mt_report_slot_state(struct input_dev *dev, slot->frame = mt->frame; if (!active) { - input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); + input_mt_report_slot_inactive(dev); return false; } diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 24bc5c5d876f..a1bba722b234 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -146,7 +146,7 @@ static void xenkbd_handle_mt_event(struct xenkbd_info *info, break; case XENKBD_MT_EV_UP: - input_mt_report_slot_state(info->mtouch, MT_TOOL_FINGER, false); + input_mt_report_slot_inactive(info->mtouch); break; case XENKBD_MT_EV_SYN: diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index d9b103a81a79..b72358d4b35c 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -938,7 +938,7 @@ static void elan_report_contact(struct elan_tp_data *data, input_report_abs(input, ABS_MT_TOUCH_MINOR, minor); } else { input_mt_slot(input, contact_num); - input_mt_report_slot_state(input, MT_TOOL_FINGER, false); + input_mt_report_slot_inactive(input); } } diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 4a5f482cf1af..573b94a049b2 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -822,8 +822,7 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) * have happened. */ if (status & MXT_T9_RELEASE) { - input_mt_report_slot_state(input_dev, -
[PATCH v2 03/49] Input: atmel_mxt_ts - rework sysfs init/remove
From: Nick Dyer An error in the sysfs init may otherwise interfere with the async return from the firmware loader Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit 3114584ae77c2b03b6dad87174f010d002e9c05d) [gdavis: Forward port and fixup conflicts. Also fixed sysfs leaks in both the mxt_initialize() and mxt_probe() error return cases.] Signed-off-by: George G. Davis [jiada: keep call mxt_initialize() before sysfs creation] Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 64 +++- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 573b94a049b2..17263c260124 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -2086,10 +2086,14 @@ static int mxt_initialize_input_device(struct mxt_data *data) return 0; err_free_mem: + data->input_dev = NULL; input_free_device(input_dev); return error; } +static int mxt_sysfs_init(struct mxt_data *data); +static void mxt_sysfs_remove(struct mxt_data *data); + static int mxt_configure_objects(struct mxt_data *data, const struct firmware *cfg); @@ -2141,16 +2145,24 @@ static int mxt_initialize(struct mxt_data *data) if (error) return error; + error = mxt_sysfs_init(data); + if (error) + return error; + error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, &client->dev, GFP_KERNEL, data, mxt_config_cb); if (error) { dev_err(&client->dev, "Failed to invoke firmware loader: %d\n", error); - return error; + goto err_free_sysfs; } return 0; + +err_free_sysfs: + mxt_sysfs_remove(data); + return error; } static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep) @@ -2803,6 +2815,7 @@ static int mxt_load_fw(struct device *dev, const char *fn) if (ret) goto release_firmware; + mxt_sysfs_remove(data); mxt_free_input_device(data); mxt_free_object_table(data); } else { @@ -2909,16 +2922,25 @@ static ssize_t mxt_update_fw_store(struct device *dev, return count; } +static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store); + +static struct attribute *mxt_fw_attrs[] = { + &dev_attr_update_fw.attr, + NULL +}; + +static const struct attribute_group mxt_fw_attr_group = { + .attrs = mxt_fw_attrs, +}; + static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL); static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL); static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL); -static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store); static struct attribute *mxt_attrs[] = { &dev_attr_fw_version.attr, &dev_attr_hw_version.attr, &dev_attr_object.attr, - &dev_attr_update_fw.attr, NULL }; @@ -2926,6 +2948,28 @@ static const struct attribute_group mxt_attr_group = { .attrs = mxt_attrs, }; +static int mxt_sysfs_init(struct mxt_data *data) +{ + struct i2c_client *client = data->client; + int error; + + error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group); + if (error) { + dev_err(&client->dev, "Failure %d creating sysfs group\n", + error); + return error; + } + + return 0; +} + +static void mxt_sysfs_remove(struct mxt_data *data) +{ + struct i2c_client *client = data->client; + + sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); +} + static void mxt_start(struct mxt_data *data) { switch (data->suspend_mode) { @@ -3113,19 +3157,14 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) if (error) return error; - error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group); + error = sysfs_create_group(&client->dev.kobj, &mxt_fw_attr_group); if (error) { - dev_err(&client->dev, "Failure %d creating sysfs group\n", + dev_err(&client->dev, "Failure %d creating fw sysfs group\n", error); - goto err_free_object; + return error; } return 0; - -err_free_object: - mxt_free_input_device(data); - mxt_free_object_table(data); - return error; } static int mxt_remove(struct i2c_client *client) @@ -3133,7 +3172,8 @@ static int mxt_remove(struct i2c_client *client) struct mxt_data *data = i2c_get_clientdata(client); disable_irq(data->irq); - sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
[PATCH v2 04/49] Input: atmel_mxt_ts - only read messages in mxt_acquire_irq() when necessary
From: Nick Dyer The workaround of reading all messages until an invalid is received is a way of forcing the CHG line high, which means that when using edge-triggered interrupts the interrupt can be acquired. With level-triggered interrupts the workaround is unnecessary. Also, most recent maXTouch chips have a feature called RETRIGEN which, when enabled, reasserts the interrupt line every cycle if there are messages waiting. This also makes the workaround unnecessary. Note: the RETRIGEN feature is only in some firmware versions/chips, it's not valid simply to enable the bit. Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen (cherry picked from ndyer/linux/for-upstream commit 1ae4e8281e491b22442cd5acdfca1862555f8ecb) [gdavis: Fix conflicts due to v4.6-rc7 commit eb43335c4095 ("Input: atmel_mxt_ts - use mxt_acquire_irq in mxt_soft_reset").] Signed-off-by: George G. Davis [jiada: reset use_retrigen_workaround at beginning of mxt_check_retrigen()] Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 51 ++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 17263c260124..35cbe60094ab 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -129,6 +130,7 @@ struct t9_range { /* MXT_SPT_COMMSCONFIG_T18 */ #define MXT_COMMS_CTRL 0 #define MXT_COMMS_CMD 1 +#define MXT_COMMS_RETRIGEN BIT(6) /* MXT_DEBUG_DIAGNOSTIC_T37 */ #define MXT_DIAGNOSTIC_PAGEUP 0x01 @@ -308,6 +310,7 @@ struct mxt_data { struct t7_config t7_cfg; struct mxt_dbg dbg; struct gpio_desc *reset_gpio; + bool use_retrigen_workaround; /* Cached parameters from object table */ u16 T5_address; @@ -318,6 +321,7 @@ struct mxt_data { u16 T71_address; u8 T9_reportid_min; u8 T9_reportid_max; + u16 T18_address; u8 T19_reportid; u16 T44_address; u8 T100_reportid_min; @@ -1190,9 +1194,11 @@ static int mxt_acquire_irq(struct mxt_data *data) enable_irq(data->irq); - error = mxt_process_messages_until_invalid(data); - if (error) - return error; + if (data->use_retrigen_workaround) { + error = mxt_process_messages_until_invalid(data); + if (error) + return error; + } return 0; } @@ -1282,6 +1288,33 @@ static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off) return crc; } +static int mxt_check_retrigen(struct mxt_data *data) +{ + struct i2c_client *client = data->client; + int error; + int val; + + data->use_retrigen_workaround = false; + + if (irq_get_trigger_type(data->irq) & IRQF_TRIGGER_LOW) + return 0; + + if (data->T18_address) { + error = __mxt_read_reg(client, + data->T18_address + MXT_COMMS_CTRL, + 1, &val); + if (error) + return error; + + if (val & MXT_COMMS_RETRIGEN) + return 0; + } + + dev_warn(&client->dev, "Enabling RETRIGEN workaround\n"); + data->use_retrigen_workaround = true; + return 0; +} + static int mxt_prepare_cfg_mem(struct mxt_data *data, struct mxt_cfg *cfg) { struct device *dev = &data->client->dev; @@ -1561,6 +1594,10 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE); + ret = mxt_check_retrigen(data); + if (ret) + goto release_mem; + ret = mxt_soft_reset(data); if (ret) goto release_mem; @@ -1604,6 +1641,7 @@ static void mxt_free_object_table(struct mxt_data *data) data->T71_address = 0; data->T9_reportid_min = 0; data->T9_reportid_max = 0; + data->T18_address = 0; data->T19_reportid = 0; data->T44_address = 0; data->T100_reportid_min = 0; @@ -1678,6 +1716,9 @@ static int mxt_parse_object_table(struct mxt_data *data, object->num_report_ids - 1; data->num_touchids = object->num_report_ids; break; + case MXT_SPT_COMMSCONFIG_T18: + data->T18_address = object->start_address; + break; case MXT_SPT_MESSAGECOUNT_T44: data->T44_address = object->start_address; break; @@ -2141,6 +2182,10 @@ static int mxt_initialize(struct mxt_data *data) msleep(MXT_FW_RESET_TIME); } +
[PATCH v2 00/49] atmel_mxt_ts misc
This patch-set forward ports Nick Dyer's work in ndyer/linux github repository as long as some other features and fixes Balasubramani Vivekanandan (2): Input: atmel_mxt_ts: Limit the max bytes transferred in an i2c transaction Input: atmel_mxt_ts: use gpiod_set_value_cansleep for reset pin Dean Jenkins (1): Input: atmel_mxt_ts: return error from mxt_process_messages_until_invalid() Deepak Das (6): Input: Atmel: improve error handling in mxt_start() Input: Atmel: improve error handling in mxt_initialize() Input: Atmel: improve error handling in mxt_update_cfg() Input: Atmel: Improve error handling in mxt_initialize_input_device() Input: Atmel: handle ReportID "0x00" while processing T5 messages Input: Atmel: use T44 object to process T5 messages George G. Davis (1): input: atmel_mxt_ts: export GPIO reset line via sysfs Jiada Wang (4): Input: switch to use return value of input_mt_report_slot_state Input: introduce input_mt_report_slot_inactive Input: atmel_mxt_ts - eliminate data->raw_info_block Input: atmel_mxt_ts - Fix compilation warning Karl Tsou (1): Input: atmel_mxt_ts - add debug for T92 gesture and T93 touch seq msgs Kautuk Consul (2): Input: atmel_mxt_ts - Change call-points of mxt_free_* functions Input: atmel_mxt_ts - rely on calculated_crc rather than file config_crc Naveen Chakka (2): input: touchscreen: atmel_mxt_ts: Added sysfs entry for touchscreen status input: atmel_mxt_ts: added sysfs interface to update atmel T38 data Nick Dyer (26): Input: atmel_mxt_ts - rework sysfs init/remove Input: atmel_mxt_ts - only read messages in mxt_acquire_irq() when necessary Input: atmel_mxt_ts - split large i2c transfers into blocks Input: atmel_mxt_ts - output status from T48 Noise Supression Input: atmel_mxt_ts - output status from T42 Touch Suppression Input: atmel_mxt_ts - implement T9 vector/orientation support Input: atmel_mxt_ts - implement T15 Key Array support Input: atmel_mxt_ts - handle reports from T47 Stylus object Input: atmel_mxt_ts - implement support for T107 active stylus Input: atmel_mxt_ts - release touch state during suspend Input: atmel_mxt_ts - add regulator control support Input: atmel_mxt_ts - report failures in suspend/resume Input: atmel_mxt_ts - allow specification of firmware file name Input: atmel_mxt_ts - handle cfg filename via pdata/sysfs Input: atmel_mxt_ts - allow input name to be specified in platform data Input: atmel_mxt_ts - refactor firmware flash to extract context into struct Input: atmel_mxt_ts - refactor code to enter bootloader into separate func Input: atmel_mxt_ts - combine bootloader version query with probe Input: atmel_mxt_ts - improve bootloader state machine handling Input: atmel_mxt_ts - rename bl_completion to chg_completion Input: atmel_mxt_ts - make bootloader interrupt driven Input: atmel_mxt_ts - delay enabling IRQ when not using regulators Input: atmel_mxt_ts - implement I2C retries Input: atmel_mxt_ts - orientation is not present in hover Input: atmel_mxt_ts - implement debug output for messages Input: atmel_mxt_ts - implement improved debug message interface Nikhil Ravindran (1): Input: atmel_mxt_ts: Add support for run self-test routine. Sanjeev Chugh (1): Input: atmel_mxt_ts: Implement synchronization during various operation karl tsou (1): Input: atmel_mxt_ts - add config checksum attribute to sysfs keerthikumarp (1): input: atmel_mxt_ts: Add Missing Delay for reset handling of Atmel touch panel controller in detachable displays. --- v2: Following commit in v1 patchset has been split into two commits Input: introduce input_mt_report_slot_inactive Following commits have been updated compared to v1 patchset Input: atmel_mxt_ts - split large i2c transfers into blocks Input: atmel_mxt_ts - output status from T42 Touch Suppression Following commits in v1 patchset have been squashed Input: touchscreen: Atmel: Add device tree support for T15 key array objects Input: atmel_mxt_ts - check data->input_dev is not null in mxt_input_sync() Input: atmel_mxt_ts - check firmware format before entering bootloader Input: atmel_mxt_ts: update stale use_retrigen_workaround flag input: atmel_mxt_ts: move bootloader probe from mxt_initialize() input: Atmel: limit the max bytes transferred while reading T5 messages Input: atmel_mxt_ts: Use msecs_to_jiffies() instead of HZ Input: atmel_mxt_ts: Use complete when in_bootloader true Input: atmel_mxt_ts: Prevent crash due to freeing of input device input: atmel_mxt_ts: Add NULL check for sysfs attribute debug_msg_attr Following commits in v1 patchset have been dropped: Input: atmel_mxt_ts - configure and use gpios as real gpios Input: touchscreen: Atmel: Enable IRQ_DISABLE_UNLAZY flag for interrupt Input: atmel_mxt_ts - add memory access interface via sysfs Input: atmel_mxt_ts: Remove sysfs attributes during driver detach Input: atmel_mxt_ts: Avoid race condition in f
Re: [PATCH 1/2] mm: Don't manually decrement num_poisoned_pages
On Tue 27-08-19 15:36:54, Alastair D'Silva wrote: > From: Alastair D'Silva > > Use the function written to do it instead. > > Signed-off-by: Alastair D'Silva Acked-by: Michal Hocko > --- > mm/sparse.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/mm/sparse.c b/mm/sparse.c > index 72f010d9bff5..e41917a7e844 100644 > --- a/mm/sparse.c > +++ b/mm/sparse.c > @@ -11,6 +11,8 @@ > #include > #include > #include > +#include > +#include > > #include "internal.h" > #include > @@ -898,7 +900,7 @@ static void clear_hwpoisoned_pages(struct page *memmap, > int nr_pages) > > for (i = 0; i < nr_pages; i++) { > if (PageHWPoison(&memmap[i])) { > - atomic_long_sub(1, &num_poisoned_pages); > + num_poisoned_pages_dec(); > ClearPageHWPoison(&memmap[i]); > } > } > -- > 2.21.0 -- Michal Hocko SUSE Labs
Re: [PATCH 2/2] mm: don't hide potentially null memmap pointer in sparse_remove_section
On Tue 27-08-19 15:36:55, Alastair D'Silva wrote: > From: Alastair D'Silva > > By adding offset to memmap before passing it in to clear_hwpoisoned_pages, > we hide a theoretically null memmap from the null check inside > clear_hwpoisoned_pages. Isn't that other way around? Calculating the offset struct page pointer will actually make the null check effective. Besides that I cannot really see how pfn_to_page would return NULL. I have to confess that I cannot really see how offset could lead to a NULL struct page either and I strongly suspect that the NULL check is not really needed. Maybe it used to be in the past. > This patch passes the offset to clear_hwpoisoned_pages instead, allowing > memmap to successfully perform it's null check. I do not see any improvement in this patch. It just adds a new argument unnecessarily. > Signed-off-by: Alastair D'Silva > --- > mm/sparse.c | 9 + > 1 file changed, 5 insertions(+), 4 deletions(-) > > diff --git a/mm/sparse.c b/mm/sparse.c > index e41917a7e844..3ff84e627e58 100644 > --- a/mm/sparse.c > +++ b/mm/sparse.c > @@ -882,7 +882,7 @@ int __meminit sparse_add_section(int nid, unsigned long > start_pfn, > } > > #ifdef CONFIG_MEMORY_FAILURE > -static void clear_hwpoisoned_pages(struct page *memmap, int nr_pages) > +static void clear_hwpoisoned_pages(struct page *memmap, int start, int count) > { > int i; > > @@ -898,7 +898,7 @@ static void clear_hwpoisoned_pages(struct page *memmap, > int nr_pages) > if (atomic_long_read(&num_poisoned_pages) == 0) > return; > > - for (i = 0; i < nr_pages; i++) { > + for (i = start; i < start + count; i++) { > if (PageHWPoison(&memmap[i])) { > num_poisoned_pages_dec(); > ClearPageHWPoison(&memmap[i]); > @@ -906,7 +906,8 @@ static void clear_hwpoisoned_pages(struct page *memmap, > int nr_pages) > } > } > #else > -static inline void clear_hwpoisoned_pages(struct page *memmap, int nr_pages) > +static inline void clear_hwpoisoned_pages(struct page *memmap, int start, > + int count) > { > } > #endif > @@ -915,7 +916,7 @@ void sparse_remove_section(struct mem_section *ms, > unsigned long pfn, > unsigned long nr_pages, unsigned long map_offset, > struct vmem_altmap *altmap) > { > - clear_hwpoisoned_pages(pfn_to_page(pfn) + map_offset, > + clear_hwpoisoned_pages(pfn_to_page(pfn), map_offset, > nr_pages - map_offset); > section_deactivate(pfn, nr_pages, altmap); > } > -- > 2.21.0 > -- Michal Hocko SUSE Labs
[PATCH v7 0/3] media: venus: Update clock scaling
In this patch series, clock scaling and core selection methods are updated. Current clock scaling is same for vpu4 and previous versions. Introducing load calculations using vpp cycles, which indicates the cycles required by video hardware to process each macroblock. Also adding vsp cycles, cycles require by stream processor. Clock scaling is now done more precisely using vpp and vsp cycles. Removing core selection from this series, there will be separate patch once issue related to power domain is fixed. This patch depends on the following patches: https://lore.kernel.org/patchwork/patch/1114762/ - Venus interconnect support for sdm845 https://lore.kernel.org/patchwork/patch/1114761/ - Venus interconnect support for sdm845 Changes since v6: - Removed core selection. - Corrected frequency calculations. - Removed instance lock used while iterating over buffers. Changes since v5: - Corrected load_per_core calculations. Changes since v4: - Added call to load_scale_clocks from venus_helper_vb2_buf_queue. - Modified check to match core_id in core_selection. Changes since v3: - vsp_cycles and vpp_cyles are now unsigned long. - Core number counting aligned with VIDC_CORE_ID_. - Aligned hardware overload handling of scale_clocks_v4 with scale_clocks. - Added bitrate based clock scaling patch in this patch series. - Instance state check is now moved from scale_clocks to load_scale_clocks Aniket Masule (3): media: venus: Add codec data table media: venus: Update clock scaling media: venus: Update to bitrate based clock scaling drivers/media/platform/qcom/venus/core.c| 13 ++ drivers/media/platform/qcom/venus/core.h| 16 +++ drivers/media/platform/qcom/venus/helpers.c | 188 +--- drivers/media/platform/qcom/venus/helpers.h | 3 +- drivers/media/platform/qcom/venus/vdec.c| 8 +- drivers/media/platform/qcom/venus/venc.c| 4 + 6 files changed, 209 insertions(+), 23 deletions(-) -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH v7 3/3] media: venus: Update to bitrate based clock scaling
Introduced clock scaling using bitrate, preavious calculations consider only the cycles per mb. Also, clock scaling is now triggered before every buffer being queued to the device. This helps in deciding precise clock cycles required. Signed-off-by: Aniket Masule --- drivers/media/platform/qcom/venus/helpers.c | 33 - 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 4ed630b..8fee0ef 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -516,17 +516,26 @@ static int scale_clocks(struct venus_inst *inst) return 0; } -static unsigned long calculate_vpp_freq(struct venus_inst *inst) +static unsigned long calculate_inst_freq(struct venus_inst *inst, +unsigned long filled_len) { - unsigned long vpp_freq = 0; + unsigned long vpp_freq = 0, vsp_freq = 0; + u64 fps = inst->fps; u32 mbs_per_sec; - mbs_per_sec = load_per_instance(inst); + mbs_per_sec = load_per_instance(inst) / inst->fps; vpp_freq = mbs_per_sec * inst->clk_data.codec_freq_data->vpp_freq; /* 21 / 20 is overhead factor */ vpp_freq += vpp_freq / 20; + vsp_freq = mbs_per_sec * inst->clk_data.codec_freq_data->vsp_freq; - return vpp_freq; + /* 10 / 7 is overhead factor */ + if (inst->session_type == VIDC_SESSION_TYPE_ENC) + vsp_freq += (inst->controls.enc.bitrate * 10) / 7; + else + vsp_freq += ((fps * filled_len * 8) * 10) / 7; + + return max(vpp_freq, vsp_freq); } static int scale_clocks_v4(struct venus_inst *inst) @@ -534,12 +543,24 @@ static int scale_clocks_v4(struct venus_inst *inst) struct venus_core *core = inst->core; const struct freq_tbl *table = core->res->freq_tbl; unsigned int num_rows = core->res->freq_tbl_size; + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; struct device *dev = core->dev; unsigned int i; unsigned long freq = 0, freq_core1 = 0, freq_core2 = 0; + unsigned long filled_len = 0; + struct venus_buffer *buf, *n; + struct vb2_buffer *vb; int ret; - freq = calculate_vpp_freq(inst); + v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) { + vb = &buf->vb.vb2_buf; + filled_len = max(filled_len, vb2_get_plane_payload(vb, 0)); + } + + if (inst->session_type == VIDC_SESSION_TYPE_DEC && !filled_len) + return 0; + + freq = calculate_inst_freq(inst, filled_len); inst->clk_data.freq = freq; mutex_lock(&core->lock); @@ -701,6 +722,8 @@ void venus_helper_get_ts_metadata(struct venus_inst *inst, u64 timestamp_us, if (inst->session_type == VIDC_SESSION_TYPE_DEC) put_ts_metadata(inst, vbuf); + + venus_helper_load_scale_clocks(inst); } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { if (inst->session_type == VIDC_SESSION_TYPE_ENC) fdata.buffer_type = HFI_BUFFER_OUTPUT; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH v7 2/3] media: venus: Update clock scaling
Current clock scaling calculations are same for vpu4 and previous versions. For vpu4, Clock scaling calculations are updated with cycles/mb. This helps in getting precise clock required Signed-off-by: Aniket Masule --- drivers/media/platform/qcom/venus/helpers.c | 135 +++- drivers/media/platform/qcom/venus/helpers.h | 2 +- drivers/media/platform/qcom/venus/vdec.c| 4 +- 3 files changed, 118 insertions(+), 23 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 71af237..4ed630b 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -448,12 +448,32 @@ static int load_scale_bw(struct venus_core *core) return icc_set_bw(core->video_path, total_avg, total_peak); } -int venus_helper_load_scale_clocks(struct venus_core *core) +static int set_clk_freq(struct venus_core *core, unsigned long freq) { + struct clk *clk = core->clks[0]; + int ret; + + ret = clk_set_rate(clk, freq); + if (ret) + return ret; + + ret = clk_set_rate(core->core0_clk, freq); + if (ret) + return ret; + + ret = clk_set_rate(core->core1_clk, freq); + if (ret) + return ret; + + return 0; +} + +static int scale_clocks(struct venus_inst *inst) +{ + struct venus_core *core = inst->core; const struct freq_tbl *table = core->res->freq_tbl; unsigned int num_rows = core->res->freq_tbl_size; unsigned long freq = table[0].freq; - struct clk *clk = core->clks[0]; struct device *dev = core->dev; u32 mbs_per_sec; unsigned int i; @@ -479,28 +499,103 @@ int venus_helper_load_scale_clocks(struct venus_core *core) set_freq: - ret = clk_set_rate(clk, freq); - if (ret) - goto err; + ret = set_clk_freq(core, freq); + if (ret) { + dev_err(dev, "failed to set clock rate %lu (%d)\n", + freq, ret); + return ret; + } - ret = clk_set_rate(core->core0_clk, freq); - if (ret) - goto err; + ret = load_scale_bw(core); + if (ret) { + dev_err(dev, "failed to set bandwidth (%d)\n", + ret); + return ret; + } - ret = clk_set_rate(core->core1_clk, freq); - if (ret) - goto err; + return 0; +} + +static unsigned long calculate_vpp_freq(struct venus_inst *inst) +{ + unsigned long vpp_freq = 0; + u32 mbs_per_sec; + + mbs_per_sec = load_per_instance(inst); + vpp_freq = mbs_per_sec * inst->clk_data.codec_freq_data->vpp_freq; + /* 21 / 20 is overhead factor */ + vpp_freq += vpp_freq / 20; + + return vpp_freq; +} + +static int scale_clocks_v4(struct venus_inst *inst) +{ + struct venus_core *core = inst->core; + const struct freq_tbl *table = core->res->freq_tbl; + unsigned int num_rows = core->res->freq_tbl_size; + struct device *dev = core->dev; + unsigned int i; + unsigned long freq = 0, freq_core1 = 0, freq_core2 = 0; + int ret; + + freq = calculate_vpp_freq(inst); + inst->clk_data.freq = freq; + + mutex_lock(&core->lock); + list_for_each_entry(inst, &core->instances, list) { + if (inst->clk_data.core_id == VIDC_CORE_ID_1) { + freq_core1 += inst->clk_data.freq; + } else if (inst->clk_data.core_id == VIDC_CORE_ID_2) { + freq_core2 += inst->clk_data.freq; + } else if (inst->clk_data.core_id == VIDC_CORE_ID_3) { + freq_core1 += inst->clk_data.freq; + freq_core2 += inst->clk_data.freq; + } + } + mutex_unlock(&core->lock); + + freq = max(freq_core1, freq_core2); + + if (freq >= table[0].freq) { + freq = table[0].freq; + dev_warn(dev, "HW is overloaded, needed: %lu max: %lu\n", +freq, table[0].freq); + goto set_freq; + } + + for (i = num_rows - 1 ; i >= 0; i--) { + if (freq <= table[i].freq) { + freq = table[i].freq; + break; + } + } + +set_freq: + + ret = set_clk_freq(core, freq); + if (ret) { + dev_err(dev, "failed to set clock rate %lu (%d)\n", + freq, ret); + return ret; + } ret = load_scale_bw(core); - if (ret) - goto err; + if (ret) { + dev_err(dev, "failed to set bandwidth (%d)\n", + ret); + return ret; + } return 0; +} -err: - dev_err(dev, "failed to set clock rate %lu or bandwidth (%d)\n", - freq, ret); - return ret; +int venus_helper_load_scale_
[PATCH v7 1/3] media: venus: Add codec data table
Add vpp cycles for different types of codec. It indicates the cycles required by video hardware to process each macroblock. Add vsp cycles, cycles required by stream processor. Initialize the codec data with core resources. Signed-off-by: Aniket Masule --- drivers/media/platform/qcom/venus/core.c| 13 + drivers/media/platform/qcom/venus/core.h| 16 +++ drivers/media/platform/qcom/venus/helpers.c | 30 + drivers/media/platform/qcom/venus/helpers.h | 1 + drivers/media/platform/qcom/venus/vdec.c| 4 drivers/media/platform/qcom/venus/venc.c| 4 6 files changed, 68 insertions(+) diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 19cbe9d..49d32b2 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -480,6 +480,17 @@ static __maybe_unused int venus_runtime_resume(struct device *dev) { 244800, 1 }, /* 1920x1080@30 */ }; +static struct codec_freq_data sdm845_codec_freq_data[] = { + { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 10 }, + { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 10 }, + { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_ENC, 675, 10 }, + { V4L2_PIX_FMT_MPEG2, VIDC_SESSION_TYPE_DEC, 200, 10 }, + { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 200, 10 }, + { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 200, 10 }, + { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_DEC, 200, 10 }, + { V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 10 }, +}; + static const struct bw_tbl sdm845_bw_table_enc[] = { { 1944000, 1612000, 0, 2416000, 0 },/* 3840x2160@60 */ { 972000, 951000, 0, 1434000, 0 },/* 3840x2160@30 */ @@ -501,6 +512,8 @@ static __maybe_unused int venus_runtime_resume(struct device *dev) .bw_tbl_enc_size = ARRAY_SIZE(sdm845_bw_table_enc), .bw_tbl_dec = sdm845_bw_table_dec, .bw_tbl_dec_size = ARRAY_SIZE(sdm845_bw_table_dec), + .codec_freq_data = sdm845_codec_freq_data, + .codec_freq_data_size = ARRAY_SIZE(sdm845_codec_freq_data), .clks = {"core", "iface", "bus" }, .clks_num = 3, .max_load = 3110400,/* 4096x2160@90 */ diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 13e35f3..684a950 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -26,6 +26,13 @@ struct reg_val { u32 value; }; +struct codec_freq_data { + u32 pixfmt; + u32 session_type; + unsigned long vpp_freq; + unsigned long vsp_freq; +}; + struct bw_tbl { u32 mbs_per_sec; u32 avg; @@ -44,6 +51,8 @@ struct venus_resources { unsigned int bw_tbl_dec_size; const struct reg_val *reg_tbl; unsigned int reg_tbl_size; + const struct codec_freq_data *codec_freq_data; + unsigned int codec_freq_data_size; const char * const clks[VIDC_CLKS_NUM_MAX]; unsigned int clks_num; enum hfi_version hfi_version; @@ -221,6 +230,12 @@ struct venus_buffer { struct list_head ref_list; }; +struct clock_data { + u32 core_id; + unsigned long freq; + const struct codec_freq_data *codec_freq_data; +}; + #define to_venus_buffer(ptr) container_of(ptr, struct venus_buffer, vb) enum venus_dec_state { @@ -301,6 +316,7 @@ struct venus_inst { struct list_head list; struct mutex lock; struct venus_core *core; + struct clock_data clk_data; struct list_head dpbbufs; struct list_head internalbufs; struct list_head registeredbufs; diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 4320ea9..71af237 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -883,6 +883,36 @@ int venus_helper_set_core_usage(struct venus_inst *inst, u32 usage) } EXPORT_SYMBOL_GPL(venus_helper_set_core_usage); +int venus_helper_init_codec_freq_data(struct venus_inst *inst) +{ + const struct codec_freq_data *data; + unsigned int i, data_size; + u32 pixfmt; + int ret = 0; + + if (!IS_V4(inst->core)) + return 0; + + data = inst->core->res->codec_freq_data; + data_size = inst->core->res->codec_freq_data_size; + pixfmt = inst->session_type == VIDC_SESSION_TYPE_DEC ? + inst->fmt_out->pixfmt : inst->fmt_cap->pixfmt; + + for (i = 0; i < data_size; i++) { + if (data[i].pixfmt == pixfmt && + data[i].session_type == inst->session_type) { + inst->clk_data.codec_freq_data = &data[i]; + break; + } + } + + if (!inst->clk_data.codec_freq_data) + ret = -EINVAL; + + return ret; +} +EXPORT_S
Re: Early EFI-related boot freeze in parse_setup_data()
On Fri, Aug 16, 2019 at 2:14 PM Daniel Drake wrote: > Anyway, the system freeze occurs in parse_setup_data(), specifically: > > data = early_memremap(pa_data, sizeof(*data)); > data_len = data->len + sizeof(struct setup_data); > > Dereferencing data->len causes the system to hang. I presume it > triggers an exception handler due to some kind of invalid memory > access. > > By returning early in that function, boot continues basically fine. So > I could then log the details: pa_data has value 0x892bb018 and > early_memremap returns address 0xff200018. Accessing just a > single byte at that address causes the system hang. I noticed a complaint about NX in the logs, right where it does the early_memremap of this data (which is now at address 0x893c0018): Notice: NX (Execute Disable) protection missing in CPU! e820: update [mem 0x893c0018-0x893cec57] usable ==> usable e820: update [mem 0x893c0018-0x893cec57] usable ==> usable e820: update [mem 0x893b3018-0x893bf057] usable ==> usable e820: update [mem 0x893b3018-0x893bf057] usable ==> usable Indeed, in the BIOS setup menu, "NX Mode" was Disabled. Setting it to Enabled avoids the hang and Linux boots as normal. Weird! Daniel
Re: [PATCH v2 2/2] PCI/AER: Split the AER stats into multiple sysfs attributes
On Mon, Aug 26, 2019 at 05:51:14PM -0700, Rajat Jain wrote: > --- a/Documentation/ABI/testing/sysfs-bus-pci-devices-aer_stats > +++ b/Documentation/ABI/testing/sysfs-bus-pci-devices-aer_stats > @@ -9,89 +9,72 @@ errors may be "seen" / reported by the link partner and not > the > problematic endpoint itself (which may report all counters as 0 as it never > saw any problems). > > -What:/sys/bus/pci/devices//aer_dev_correctable > -Date:July 2018 > -KernelVersion: 4.19.0 > +What: Following files in /sys/bus/pci/devices//aer_stats/ > +correctable_bit0_RxErr > +correctable_bit12_Timeout > +correctable_bit13_NonFatalErr > +correctable_bit14_CorrIntErr > +correctable_bit15_HeaderOF > +correctable_bit6_BadTLP > +correctable_bit7_BadDLLP > +correctable_bit8_Rollover > +fatal_bit0_Undefined > +fatal_bit12_TLP > +fatal_bit13_FCP > +fatal_bit14_CmpltTO > +fatal_bit15_CmpltAbrt > +fatal_bit16_UnxCmplt > +fatal_bit17_RxOF > +fatal_bit18_MalfTLP > +fatal_bit19_ECRC > +fatal_bit20_UnsupReq > +fatal_bit21_ACSViol > +fatal_bit22_UncorrIntErr > +fatal_bit23_BlockedTLP > +fatal_bit24_AtomicOpBlocked > +fatal_bit25_TLPBlockedErr > +fatal_bit26_PoisonTLPBlocked > +fatal_bit4_DLP > +fatal_bit5_SDES > +nonfatal_bit0_Undefined > +nonfatal_bit12_TLP > +nonfatal_bit13_FCP > +nonfatal_bit14_CmpltTO > +nonfatal_bit15_CmpltAbrt > +nonfatal_bit16_UnxCmplt > +nonfatal_bit17_RxOF > +nonfatal_bit18_MalfTLP > +nonfatal_bit19_ECRC > +nonfatal_bit20_UnsupReq > +nonfatal_bit21_ACSViol > +nonfatal_bit22_UncorrIntErr > +nonfatal_bit23_BlockedTLP > +nonfatal_bit24_AtomicOpBlocked > +nonfatal_bit25_TLPBlockedErr > +nonfatal_bit26_PoisonTLPBlocked > +nonfatal_bit4_DLP > +nonfatal_bit5_SDES All of those should be indented, right? Same for other entries thanks, greg k-h
[PATCH 0/3] media: venus: Update clock scaling
In this patch series, clock scaling and core selection methods are updated. Current clock scaling is same for vpu4 and previous versions. Introducing load calculations using vpp cycles, which indicates the cycles required by video hardware to process each macroblock. Also adding vsp cycles, cycles require by stream processor. Clock scaling is now done more precisely using vpp and vsp cycles. Removing core selection from this series, there will be separate patch once issue related to power domain is fixed. This patch depends on the following patches: https://lore.kernel.org/patchwork/patch/1114762/ - Venus interconnect support for sdm845 https://lore.kernel.org/patchwork/patch/1114761/ - Venus interconnect support for sdm845 Changes since v6: - Removed core selection. - Corrected frequency calculations. - Removed instance lock used while iterating over buffers. Changes since v5: - Corrected load_per_core calculations. Changes since v4: - Added call to load_scale_clocks from venus_helper_vb2_buf_queue. - Modified check to match core_id in core_selection. Changes since v3: - vsp_cycles and vpp_cyles are now unsigned long. - Core number counting aligned with VIDC_CORE_ID_. - Aligned hardware overload handling of scale_clocks_v4 with scale_clocks. - Added bitrate based clock scaling patch in this patch series. - Instance state check is now moved from scale_clocks to load_scale_clocks. Aniket Masule (3): media: venus: Add codec data table media: venus: Update clock scaling media: venus: Update to bitrate based clock scaling drivers/media/platform/qcom/venus/core.c| 13 ++ drivers/media/platform/qcom/venus/core.h| 16 +++ drivers/media/platform/qcom/venus/helpers.c | 188 +--- drivers/media/platform/qcom/venus/helpers.h | 3 +- drivers/media/platform/qcom/venus/vdec.c| 8 +- drivers/media/platform/qcom/venus/venc.c| 4 + 6 files changed, 209 insertions(+), 23 deletions(-) -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 1/3] media: venus: Add codec data table
Add vpp cycles for different types of codec. It indicates the cycles required by video hardware to process each macroblock. Add vsp cycles, cycles required by stream processor. Initialize the codec data with core resources. Signed-off-by: Aniket Masule --- drivers/media/platform/qcom/venus/core.c| 13 + drivers/media/platform/qcom/venus/core.h| 16 +++ drivers/media/platform/qcom/venus/helpers.c | 30 + drivers/media/platform/qcom/venus/helpers.h | 1 + drivers/media/platform/qcom/venus/vdec.c| 4 drivers/media/platform/qcom/venus/venc.c| 4 6 files changed, 68 insertions(+) diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 19cbe9d..49d32b2 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -480,6 +480,17 @@ static __maybe_unused int venus_runtime_resume(struct device *dev) { 244800, 1 }, /* 1920x1080@30 */ }; +static struct codec_freq_data sdm845_codec_freq_data[] = { + { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 10 }, + { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 10 }, + { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_ENC, 675, 10 }, + { V4L2_PIX_FMT_MPEG2, VIDC_SESSION_TYPE_DEC, 200, 10 }, + { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 200, 10 }, + { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 200, 10 }, + { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_DEC, 200, 10 }, + { V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 10 }, +}; + static const struct bw_tbl sdm845_bw_table_enc[] = { { 1944000, 1612000, 0, 2416000, 0 },/* 3840x2160@60 */ { 972000, 951000, 0, 1434000, 0 },/* 3840x2160@30 */ @@ -501,6 +512,8 @@ static __maybe_unused int venus_runtime_resume(struct device *dev) .bw_tbl_enc_size = ARRAY_SIZE(sdm845_bw_table_enc), .bw_tbl_dec = sdm845_bw_table_dec, .bw_tbl_dec_size = ARRAY_SIZE(sdm845_bw_table_dec), + .codec_freq_data = sdm845_codec_freq_data, + .codec_freq_data_size = ARRAY_SIZE(sdm845_codec_freq_data), .clks = {"core", "iface", "bus" }, .clks_num = 3, .max_load = 3110400,/* 4096x2160@90 */ diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 13e35f3..684a950 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -26,6 +26,13 @@ struct reg_val { u32 value; }; +struct codec_freq_data { + u32 pixfmt; + u32 session_type; + unsigned long vpp_freq; + unsigned long vsp_freq; +}; + struct bw_tbl { u32 mbs_per_sec; u32 avg; @@ -44,6 +51,8 @@ struct venus_resources { unsigned int bw_tbl_dec_size; const struct reg_val *reg_tbl; unsigned int reg_tbl_size; + const struct codec_freq_data *codec_freq_data; + unsigned int codec_freq_data_size; const char * const clks[VIDC_CLKS_NUM_MAX]; unsigned int clks_num; enum hfi_version hfi_version; @@ -221,6 +230,12 @@ struct venus_buffer { struct list_head ref_list; }; +struct clock_data { + u32 core_id; + unsigned long freq; + const struct codec_freq_data *codec_freq_data; +}; + #define to_venus_buffer(ptr) container_of(ptr, struct venus_buffer, vb) enum venus_dec_state { @@ -301,6 +316,7 @@ struct venus_inst { struct list_head list; struct mutex lock; struct venus_core *core; + struct clock_data clk_data; struct list_head dpbbufs; struct list_head internalbufs; struct list_head registeredbufs; diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 4320ea9..71af237 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -883,6 +883,36 @@ int venus_helper_set_core_usage(struct venus_inst *inst, u32 usage) } EXPORT_SYMBOL_GPL(venus_helper_set_core_usage); +int venus_helper_init_codec_freq_data(struct venus_inst *inst) +{ + const struct codec_freq_data *data; + unsigned int i, data_size; + u32 pixfmt; + int ret = 0; + + if (!IS_V4(inst->core)) + return 0; + + data = inst->core->res->codec_freq_data; + data_size = inst->core->res->codec_freq_data_size; + pixfmt = inst->session_type == VIDC_SESSION_TYPE_DEC ? + inst->fmt_out->pixfmt : inst->fmt_cap->pixfmt; + + for (i = 0; i < data_size; i++) { + if (data[i].pixfmt == pixfmt && + data[i].session_type == inst->session_type) { + inst->clk_data.codec_freq_data = &data[i]; + break; + } + } + + if (!inst->clk_data.codec_freq_data) + ret = -EINVAL; + + return ret; +} +EXPORT_S
[PATCH 2/3] media: venus: Update clock scaling
Current clock scaling calculations are same for vpu4 and previous versions. For vpu4, Clock scaling calculations are updated with cycles/mb. This helps in getting precise clock required Signed-off-by: Aniket Masule --- drivers/media/platform/qcom/venus/helpers.c | 135 +++- drivers/media/platform/qcom/venus/helpers.h | 2 +- drivers/media/platform/qcom/venus/vdec.c| 4 +- 3 files changed, 118 insertions(+), 23 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 71af237..4ed630b 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -448,12 +448,32 @@ static int load_scale_bw(struct venus_core *core) return icc_set_bw(core->video_path, total_avg, total_peak); } -int venus_helper_load_scale_clocks(struct venus_core *core) +static int set_clk_freq(struct venus_core *core, unsigned long freq) { + struct clk *clk = core->clks[0]; + int ret; + + ret = clk_set_rate(clk, freq); + if (ret) + return ret; + + ret = clk_set_rate(core->core0_clk, freq); + if (ret) + return ret; + + ret = clk_set_rate(core->core1_clk, freq); + if (ret) + return ret; + + return 0; +} + +static int scale_clocks(struct venus_inst *inst) +{ + struct venus_core *core = inst->core; const struct freq_tbl *table = core->res->freq_tbl; unsigned int num_rows = core->res->freq_tbl_size; unsigned long freq = table[0].freq; - struct clk *clk = core->clks[0]; struct device *dev = core->dev; u32 mbs_per_sec; unsigned int i; @@ -479,28 +499,103 @@ int venus_helper_load_scale_clocks(struct venus_core *core) set_freq: - ret = clk_set_rate(clk, freq); - if (ret) - goto err; + ret = set_clk_freq(core, freq); + if (ret) { + dev_err(dev, "failed to set clock rate %lu (%d)\n", + freq, ret); + return ret; + } - ret = clk_set_rate(core->core0_clk, freq); - if (ret) - goto err; + ret = load_scale_bw(core); + if (ret) { + dev_err(dev, "failed to set bandwidth (%d)\n", + ret); + return ret; + } - ret = clk_set_rate(core->core1_clk, freq); - if (ret) - goto err; + return 0; +} + +static unsigned long calculate_vpp_freq(struct venus_inst *inst) +{ + unsigned long vpp_freq = 0; + u32 mbs_per_sec; + + mbs_per_sec = load_per_instance(inst); + vpp_freq = mbs_per_sec * inst->clk_data.codec_freq_data->vpp_freq; + /* 21 / 20 is overhead factor */ + vpp_freq += vpp_freq / 20; + + return vpp_freq; +} + +static int scale_clocks_v4(struct venus_inst *inst) +{ + struct venus_core *core = inst->core; + const struct freq_tbl *table = core->res->freq_tbl; + unsigned int num_rows = core->res->freq_tbl_size; + struct device *dev = core->dev; + unsigned int i; + unsigned long freq = 0, freq_core1 = 0, freq_core2 = 0; + int ret; + + freq = calculate_vpp_freq(inst); + inst->clk_data.freq = freq; + + mutex_lock(&core->lock); + list_for_each_entry(inst, &core->instances, list) { + if (inst->clk_data.core_id == VIDC_CORE_ID_1) { + freq_core1 += inst->clk_data.freq; + } else if (inst->clk_data.core_id == VIDC_CORE_ID_2) { + freq_core2 += inst->clk_data.freq; + } else if (inst->clk_data.core_id == VIDC_CORE_ID_3) { + freq_core1 += inst->clk_data.freq; + freq_core2 += inst->clk_data.freq; + } + } + mutex_unlock(&core->lock); + + freq = max(freq_core1, freq_core2); + + if (freq >= table[0].freq) { + freq = table[0].freq; + dev_warn(dev, "HW is overloaded, needed: %lu max: %lu\n", +freq, table[0].freq); + goto set_freq; + } + + for (i = num_rows - 1 ; i >= 0; i--) { + if (freq <= table[i].freq) { + freq = table[i].freq; + break; + } + } + +set_freq: + + ret = set_clk_freq(core, freq); + if (ret) { + dev_err(dev, "failed to set clock rate %lu (%d)\n", + freq, ret); + return ret; + } ret = load_scale_bw(core); - if (ret) - goto err; + if (ret) { + dev_err(dev, "failed to set bandwidth (%d)\n", + ret); + return ret; + } return 0; +} -err: - dev_err(dev, "failed to set clock rate %lu or bandwidth (%d)\n", - freq, ret); - return ret; +int venus_helper_load_scale_
[PATCH 3/3] media: venus: Update to bitrate based clock scaling
Introduced clock scaling using bitrate, preavious calculations consider only the cycles per mb. Also, clock scaling is now triggered before every buffer being queued to the device. This helps in deciding precise clock cycles required. Signed-off-by: Aniket Masule --- drivers/media/platform/qcom/venus/helpers.c | 33 - 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 4ed630b..8fee0ef 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -516,17 +516,26 @@ static int scale_clocks(struct venus_inst *inst) return 0; } -static unsigned long calculate_vpp_freq(struct venus_inst *inst) +static unsigned long calculate_inst_freq(struct venus_inst *inst, +unsigned long filled_len) { - unsigned long vpp_freq = 0; + unsigned long vpp_freq = 0, vsp_freq = 0; + u64 fps = inst->fps; u32 mbs_per_sec; - mbs_per_sec = load_per_instance(inst); + mbs_per_sec = load_per_instance(inst) / inst->fps; vpp_freq = mbs_per_sec * inst->clk_data.codec_freq_data->vpp_freq; /* 21 / 20 is overhead factor */ vpp_freq += vpp_freq / 20; + vsp_freq = mbs_per_sec * inst->clk_data.codec_freq_data->vsp_freq; - return vpp_freq; + /* 10 / 7 is overhead factor */ + if (inst->session_type == VIDC_SESSION_TYPE_ENC) + vsp_freq += (inst->controls.enc.bitrate * 10) / 7; + else + vsp_freq += ((fps * filled_len * 8) * 10) / 7; + + return max(vpp_freq, vsp_freq); } static int scale_clocks_v4(struct venus_inst *inst) @@ -534,12 +543,24 @@ static int scale_clocks_v4(struct venus_inst *inst) struct venus_core *core = inst->core; const struct freq_tbl *table = core->res->freq_tbl; unsigned int num_rows = core->res->freq_tbl_size; + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; struct device *dev = core->dev; unsigned int i; unsigned long freq = 0, freq_core1 = 0, freq_core2 = 0; + unsigned long filled_len = 0; + struct venus_buffer *buf, *n; + struct vb2_buffer *vb; int ret; - freq = calculate_vpp_freq(inst); + v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) { + vb = &buf->vb.vb2_buf; + filled_len = max(filled_len, vb2_get_plane_payload(vb, 0)); + } + + if (inst->session_type == VIDC_SESSION_TYPE_DEC && !filled_len) + return 0; + + freq = calculate_inst_freq(inst, filled_len); inst->clk_data.freq = freq; mutex_lock(&core->lock); @@ -701,6 +722,8 @@ void venus_helper_get_ts_metadata(struct venus_inst *inst, u64 timestamp_us, if (inst->session_type == VIDC_SESSION_TYPE_DEC) put_ts_metadata(inst, vbuf); + + venus_helper_load_scale_clocks(inst); } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { if (inst->session_type == VIDC_SESSION_TYPE_ENC) fdata.buffer_type = HFI_BUFFER_OUTPUT; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v2] powerpc: Allow flush_(inval_)dcache_range to work across ranges >4GB
On Wed, Aug 21, 2019 at 10:19:27AM +1000, Alastair D'Silva wrote: > From: Alastair D'Silva > > The upstream commit: > 22e9c88d486a ("powerpc/64: reuse PPC32 static inline flush_dcache_range()") > has a similar effect, but since it is a rewrite of the assembler to C, is > too invasive for stable. This patch is a minimal fix to address the issue in > assembler. > > This patch applies cleanly to v5.2, v4.19 & v4.14. > > When calling flush_(inval_)dcache_range with a size >4GB, we were masking > off the upper 32 bits, so we would incorrectly flush a range smaller > than intended. > > This patch replaces the 32 bit shifts with 64 bit ones, so that > the full size is accounted for. > > Changelog: > v2 > - Add related upstream commit Now applied, thanks. greg k-h
RE: [PATCH] input: keyboard: snvs_pwrkey: Send press and release event for i.MX6 S,DL and Q
On Fri, Aug 23, 2019 at 02:30:02PM +0200, Robin van der Gracht wrote:> > The older generation i.MX6 processors send a powerdown request interrupt > if the powerkey is released before a hard shutdown (5 second press). This > should allow software to bring down the SoC safely. > > For this driver to work as a regular powerkey with the older SoCs, we need to > send a keypress AND release when we get the powerdown request interrupt. Please clarify here more clearly that because there is NO press interrupt triggered but only release interrupt on elder i.mx6 processors and that HW issue fixed from i.mx6sx. > > Signed-off-by: Robin van der Gracht > --- > arch/arm/boot/dts/imx6qdl.dtsi | 2 +- > arch/arm/boot/dts/imx6sll.dtsi | 2 +- > arch/arm/boot/dts/imx6sx.dtsi| 2 +- > arch/arm/boot/dts/imx6ul.dtsi| 2 +- > arch/arm/boot/dts/imx7s.dtsi | 2 +- As Shawn talked, please keep the original "fsl,sec-v4.0-pwrkey", just add 'imx6qdl-snvs-pwrkey' for elder i.mx6 processor i.mx6q/dl/sl, thus no need to touch other newer processor's dts. > > static void imx_imx_snvs_check_for_events(struct timer_list *t) @@ -67,13 > +85,23 @@ static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void > *dev_id) { > struct platform_device *pdev = dev_id; > struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev); > + struct input_dev *input = pdata->input; > u32 lp_status; > > - pm_wakeup_event(pdata->input->dev.parent, 0); > + pm_wakeup_event(input->dev.parent, 0); > > regmap_read(pdata->snvs, SNVS_LPSR_REG, &lp_status); > - if (lp_status & SNVS_LPSR_SPO) > - mod_timer(&pdata->check_timer, jiffies + > msecs_to_jiffies(DEBOUNCE_TIME)); > + if (lp_status & SNVS_LPSR_SPO) { > + if (pdata->hwtype == IMX6QDL_SNVS) { > + input_report_key(input, pdata->keycode, 1); > + input_report_key(input, pdata->keycode, 0); > + input_sync(input); > + pm_relax(input->dev.parent); Could you move the above input event report steps into imx_imx_snvs_check_for_events() as before? That make code better to understand and less operation in ISR. > + } else { > + mod_timer(&pdata->check_timer, > + jiffies + msecs_to_jiffies(DEBOUNCE_TIME)); > + } > + } > > /* clear SPO status */ > regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO); @@ > -88,11 +116,24 @@ static void imx_snvs_pwrkey_act(void *pdata) > del_timer_sync(&pd->check_timer); > } > > +static const struct of_device_id imx_snvs_pwrkey_ids[] = { > + { > + .compatible = "fsl,imx6sx-sec-v4.0-pwrkey", > + .data = &imx_snvs_devtype[IMX6SX_SNVS], > + }, { > + .compatible = "fsl,imx6qdl-sec-v4.0-pwrkey", > + .data = &imx_snvs_devtype[IMX6QDL_SNVS], No ' IMX6QDL_SNVS ' defined in your patch or am I missing? > + }, > + { /* sentinel */ } > +}; > +MODULE_DEVICE_TABLE(of, imx_snvs_pwrkey_ids); > -- > 2.20.1
Re: [PATCH v2] powerpc: Allow flush_(inval_)dcache_range to work across ranges >4GB
On Mon, Aug 26, 2019 at 10:08:26PM +0200, Christophe Leroy wrote: > > > Le 26/08/2019 à 18:50, Greg Kroah-Hartman a écrit : > > On Wed, Aug 21, 2019 at 10:19:27AM +1000, Alastair D'Silva wrote: > > > From: Alastair D'Silva > > > > > > The upstream commit: > > > 22e9c88d486a ("powerpc/64: reuse PPC32 static inline > > > flush_dcache_range()") > > > has a similar effect, but since it is a rewrite of the assembler to C, is > > > too invasive for stable. This patch is a minimal fix to address the issue > > > in > > > assembler. > > > > > > This patch applies cleanly to v5.2, v4.19 & v4.14. > > > > > > When calling flush_(inval_)dcache_range with a size >4GB, we were masking > > > off the upper 32 bits, so we would incorrectly flush a range smaller > > > than intended. > > > > > > This patch replaces the 32 bit shifts with 64 bit ones, so that > > > the full size is accounted for. > > > > > > Changelog: > > > v2 > > >- Add related upstream commit > > > > > > Signed-off-by: Alastair D'Silva > > > --- > > > arch/powerpc/kernel/misc_64.S | 4 ++-- > > > 1 file changed, 2 insertions(+), 2 deletions(-) > > > > > > diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S > > > index 1ad4089dd110..d4d096f80f4b 100644 > > > --- a/arch/powerpc/kernel/misc_64.S > > > +++ b/arch/powerpc/kernel/misc_64.S > > > @@ -130,7 +130,7 @@ _GLOBAL_TOC(flush_dcache_range) > > > subfr8,r6,r4/* compute length */ > > > add r8,r8,r5/* ensure we get enough */ > > > lwz r9,DCACHEL1LOGBLOCKSIZE(r10)/* Get log-2 of dcache > > > block size */ > > > - srw.r8,r8,r9/* compute line count */ > > > + srd.r8,r8,r9/* compute line count */ > > > beqlr /* nothing to do? */ > > > mtctr r8 > > > 0: dcbst 0,r6 > > > @@ -148,7 +148,7 @@ _GLOBAL(flush_inval_dcache_range) > > > subfr8,r6,r4/* compute length */ > > > add r8,r8,r5/* ensure we get enough */ > > > lwz r9,DCACHEL1LOGBLOCKSIZE(r10)/* Get log-2 of dcache > > > block size */ > > > - srw.r8,r8,r9/* compute line count */ > > > + srd.r8,r8,r9/* compute line count */ > > > beqlr /* nothing to do? */ > > > sync > > > isync > > > > I need an ack from the powerpc maintainer(s) before I can take this. > > I think you already got an ack (on v1). See > https://patchwork.ozlabs.org/patch/1147403/#2239663 How am I supposed to remember that? :) greg k-h
Re: [RFC PATCH 0/2] Add predictive memory reclamation and compaction
On Tue 27-08-19 02:14:20, Bharath Vedartham wrote: > Hi Michal, > > Here are some of my thoughts, > On Wed, Aug 21, 2019 at 04:06:32PM +0200, Michal Hocko wrote: > > On Thu 15-08-19 14:51:04, Khalid Aziz wrote: > > > Hi Michal, > > > > > > The smarts for tuning these knobs can be implemented in userspace and > > > more knobs added to allow for what is missing today, but we get back to > > > the same issue as before. That does nothing to make kernel self-tuning > > > and adds possibly even more knobs to userspace. Something so fundamental > > > to kernel memory management as making free pages available when they are > > > needed really should be taken care of in the kernel itself. Moving it to > > > userspace just means the kernel is hobbled unless one installs and tunes > > > a userspace package correctly. > > > > From my past experience the existing autotunig works mostly ok for a > > vast variety of workloads. A more clever tuning is possible and people > > are doing that already. Especially for cases when the machine is heavily > > overcommited. There are different ways to achieve that. Your new > > in-kernel auto tuning would have to be tested on a large variety of > > workloads to be proven and riskless. So I am quite skeptical to be > > honest. > Could you give some references to such works regarding tuning the kernel? Talk to Facebook guys and their usage of PSI to control the memory distribution and OOM situations. > Essentially, Our idea here is to foresee potential memory exhaustion. > This foreseeing is done by observing the workload, observing the memory > usage of the workload. Based on this observations, we make a prediction > whether or not memory exhaustion could occur. I understand that and I am not disputing this can be useful. All I do argue here is that there is unlikely a good "crystall ball" for most/all workloads that would justify its inclusion into the kernel and that this is something better done in the userspace where you can experiment and tune the behavior for a particular workload of your interest. Therefore I would like to shift the discussion towards existing APIs and whether they are suitable for such an advance auto-tuning. I haven't heard any arguments about missing pieces. > If memory exhaustion > occurs, we reclaim some more memory. kswapd stops reclaim when > hwmark is reached. hwmark is usually set to a fairly low percentage of > total memory, in my system for zone Normal hwmark is 13% of total pages. > So there is scope for reclaiming more pages to make sure system does not > suffer from a lack of pages. Yes and we have ways to control those watermarks that your monitoring tool can use to alter the reclaim behavior. [...] > > Therefore I would really focus on discussing whether we have sufficient > > APIs to tune the kernel to do the right thing when needed. That requires > > to identify gaps in that area. > One thing that comes to my mind is based on the issue Khalid mentioned > earlier on how his desktop took more than 30secs to boot up because of > the caches using up a lot of memory. > Rather than allowing any unused memory to be the page cache, would it be > a good idea to fix a size for the caches and elastically change the size > based on the workload? I do not think so. Limiting the pagecache is unlikely to help as it is really cheap to reclaim most of the time. In those cases when this is not the case (e.g. the underlying FS needs to flush and/or metadata) then the same would be possible in a restricted page cache situation and you could easily end up stalled waiting for pagecache (e.g. any executable/library) while there is a lot of memory. I cannot comment on the Khalid's example because there were no details there but I would be really surprised if the primary source of stall was the pagecache. -- Michal Hocko SUSE Labs
Re: [PATCH 4/4] iio: adc: ina2xx: Use label proper for device identification
On 27. 08. 19 5:55, Phil Reid wrote: > On 26/08/2019 02:07, Jonathan Cameron wrote: >> On Wed, 21 Aug 2019 11:12:00 +0200 >> Michal Simek wrote: >> >>> On 21. 08. 19 4:11, Phil Reid wrote: On 20/08/2019 22:11, Michal Simek wrote: > Add support for using label property for easier device > identification via > iio framework. > > Signed-off-by: Michal Simek > --- > > drivers/iio/adc/ina2xx-adc.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/iio/adc/ina2xx-adc.c > b/drivers/iio/adc/ina2xx-adc.c > index 7c7c63677bf4..077c54915f70 100644 > --- a/drivers/iio/adc/ina2xx-adc.c > +++ b/drivers/iio/adc/ina2xx-adc.c > @@ -1033,7 +1033,7 @@ static int ina2xx_probe(struct i2c_client > *client, > snprintf(chip->name, sizeof(chip->name), "%s-%s", > client->name, dev_name(&client->dev)); > - indio_dev->name = chip->name; > + indio_dev->name = of_get_property(np, "label", NULL) ? : > chip->name; > indio_dev->setup_ops = &ina2xx_setup_ops; > buffer = devm_iio_kfifo_allocate(&indio_dev->dev); > I like this personally. It'd be nice if it was a core function so it could be an opt in to any iio device. Don't know how well received that'd be thou. >> I'm not particularly keen on changing the semantics of existing >> ABI, but how about adding new ABI to provide this? >> >> /sys/bus/iio/devices/iio\:device0/label for example? >> >> I haven't thought about it in depth yet though. If you spin >> a patch with that and the DT docs we'll be more likely to get >> a view from DT maintainers if this is acceptable use of label. >> > > I've sent "iio: core: Add optional symbolic label to device attributes" > for further discussion. Series looks good. I expect that there will be also update in libiio if this is accepted. Thanks, Michal
Re: [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage
On Tue, 27 Aug 2019, Frederic Weisbecker wrote: > On Wed, Aug 21, 2019 at 09:09:25PM +0200, Thomas Gleixner wrote: > > /** > > @@ -92,14 +130,10 @@ struct posix_cputimers { > > > > static inline void posix_cputimers_init(struct posix_cputimers *pct) > > { > > - pct->timers_active = 0; > > - pct->expiry_active = 0; > > No more need to initialize these? > > > + memset(pct->bases, 0, sizeof(pct->bases)); memset() does that IIRC :) > > pct->bases[0].nextevt = U64_MAX; > > pct->bases[1].nextevt = U64_MAX; > > pct->bases[2].nextevt = U64_MAX; > > - INIT_LIST_HEAD(&pct->bases[0].cpu_timers); > > - INIT_LIST_HEAD(&pct->bases[1].cpu_timers); > > - INIT_LIST_HEAD(&pct->bases[2].cpu_timers); > > } > > [...] > > > @@ -393,15 +395,15 @@ static int posix_cpu_timer_del(struct k_ > > sighand = lock_task_sighand(p, &flags); > > if (unlikely(sighand == NULL)) { > > /* > > -* We raced with the reaping of the task. > > -* The deletion should have cleared us off the list. > > +* This raced with the reaping of the task. The exit cleanup > > +* should have removed this timer from the timer queue. > > */ > > - WARN_ON_ONCE(!list_empty(&timer->it.cpu.entry)); > > + WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node)); > > Should we clear ctmr->head upon cleanup_timerqueue() ? Probably.
Re: [RESEND PATCH v3 09/20] mtd: spi-nor: Create a ->set_4byte() method
On 26/08/19 5:38 PM, tudor.amba...@microchip.com wrote: > From: Boris Brezillon > > The procedure used to enable 4 byte addressing mode depends on the NOR > device, so let's provide a hook so that manufacturer specific handling > can be implemented in a sane way. > > Signed-off-by: Boris Brezillon > [tudor.amba...@microchip.com: use nor->params.set_4byte() instead of > nor->set_4byte()] > Signed-off-by: Tudor Ambarus > --- Reviewed-by: Vignesh Raghavendra Regards Vignesh > v3: no changes> > drivers/mtd/spi-nor/spi-nor.c | 76 > ++- > include/linux/mtd/spi-nor.h | 2 ++ > 2 files changed, 41 insertions(+), 37 deletions(-) > > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c > index 1e7f8dc3457d..235e82a121a1 100644 > --- a/drivers/mtd/spi-nor/spi-nor.c > +++ b/drivers/mtd/spi-nor/spi-nor.c > @@ -633,6 +633,17 @@ static int macronix_set_4byte(struct spi_nor *nor, bool > enable) > NULL, 0); > } > > +static int st_micron_set_4byte(struct spi_nor *nor, bool enable) > +{ > + int ret; > + > + write_enable(nor); > + ret = macronix_set_4byte(nor, enable); > + write_disable(nor); > + > + return ret; > +} > + > static int spansion_set_4byte(struct spi_nor *nor, bool enable) > { > nor->bouncebuf[0] = enable << 7; > @@ -667,45 +678,24 @@ static int spi_nor_write_ear(struct spi_nor *nor, u8 > ear) > return nor->write_reg(nor, SPINOR_OP_WREAR, nor->bouncebuf, 1); > } > > -/* Enable/disable 4-byte addressing mode. */ > -static int set_4byte(struct spi_nor *nor, bool enable) > +static int winbond_set_4byte(struct spi_nor *nor, bool enable) > { > - int status; > - bool need_wren = false; > - > - switch (JEDEC_MFR(nor->info)) { > - case SNOR_MFR_ST: > - case SNOR_MFR_MICRON: > - /* Some Micron need WREN command; all will accept it */ > - need_wren = true; > - /* fall through */ > - case SNOR_MFR_MACRONIX: > - case SNOR_MFR_WINBOND: > - if (need_wren) > - write_enable(nor); > + int ret; > > - status = macronix_set_4byte(nor, enable); > - if (need_wren) > - write_disable(nor); > + ret = macronix_set_4byte(nor, enable); > + if (ret || enable) > + return ret; > > - if (!status && !enable && > - JEDEC_MFR(nor->info) == SNOR_MFR_WINBOND) { > - /* > - * On Winbond W25Q256FV, leaving 4byte mode causes > - * the Extended Address Register to be set to 1, so all > - * 3-byte-address reads come from the second 16M. > - * We must clear the register to enable normal behavior. > - */ > - write_enable(nor); > - spi_nor_write_ear(nor, 0); > - write_disable(nor); > - } > + /* > + * On Winbond W25Q256FV, leaving 4byte mode causes the Extended Address > + * Register to be set to 1, so all 3-byte-address reads come from the > + * second 16M. We must clear the register to enable normal behavior. > + */ > + write_enable(nor); > + ret = spi_nor_write_ear(nor, 0); > + write_disable(nor); > > - return status; > - default: > - /* Spansion style */ > - return spansion_set_4byte(nor, enable); > - } > + return ret; > } > > static int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr) > @@ -4153,11 +4143,18 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor, > static void macronix_set_default_init(struct spi_nor *nor) > { > nor->params.quad_enable = macronix_quad_enable; > + nor->params.set_4byte = macronix_set_4byte; > } > > static void st_micron_set_default_init(struct spi_nor *nor) > { > nor->params.quad_enable = NULL; > + nor->params.set_4byte = st_micron_set_4byte; > +} > + > +static void winbond_set_default_init(struct spi_nor *nor) > +{ > + nor->params.set_4byte = winbond_set_4byte; > } > > /** > @@ -4178,6 +4175,10 @@ static void spi_nor_manufacturer_init_params(struct > spi_nor *nor) > st_micron_set_default_init(nor); > break; > > + case SNOR_MFR_WINBOND: > + winbond_set_default_init(nor); > + break; > + > default: > break; > } > @@ -4222,6 +4223,7 @@ static void spi_nor_info_init_params(struct spi_nor > *nor) > > /* Initialize legacy flash parameters and settings. */ > params->quad_enable = spansion_quad_enable; > + params->set_4byte = spansion_set_4byte; > > /* Set SPI NOR sizes. */ > params->size = (u64)info->sector_size * info->n_sectors; > @@ -4587,7 +4589,7 @@ static int spi_nor_init(struct spi_nor *nor) >*/ > WARN_ONCE(nor->flags & SNOR_
Re: [v2 PATCH -mm] mm: account deferred split THPs into MemAvailable
On Mon 26-08-19 16:15:38, Kirill A. Shutemov wrote: > On Mon, Aug 26, 2019 at 09:40:35AM +0200, Michal Hocko wrote: > > On Thu 22-08-19 18:29:34, Kirill A. Shutemov wrote: > > > On Thu, Aug 22, 2019 at 02:56:56PM +0200, Vlastimil Babka wrote: > > > > On 8/22/19 10:04 AM, Michal Hocko wrote: > > > > > On Thu 22-08-19 01:55:25, Yang Shi wrote: > > > > >> Available memory is one of the most important metrics for memory > > > > >> pressure. > > > > > > > > > > I would disagree with this statement. It is a rough estimate that > > > > > tells > > > > > how much memory you can allocate before going into a more expensive > > > > > reclaim (mostly swapping). Allocating that amount still might result > > > > > in > > > > > direct reclaim induced stalls. I do realize that this is simple metric > > > > > that is attractive to use and works in many cases though. > > > > > > > > > >> Currently, the deferred split THPs are not accounted into > > > > >> available memory, but they are reclaimable actually, like reclaimable > > > > >> slabs. > > > > >> > > > > >> And, they seems very common with the common workloads when THP is > > > > >> enabled. A simple run with MariaDB test of mmtest with THP enabled > > > > >> as > > > > >> always shows it could generate over fifteen thousand deferred split > > > > >> THPs > > > > >> (accumulated around 30G in one hour run, 75% of 40G memory for my > > > > >> VM). > > > > >> It looks worth accounting in MemAvailable. > > > > > > > > > > OK, this makes sense. But your above numbers are really worrying. > > > > > Accumulating such a large amount of pages that are likely not going to > > > > > be used is really bad. They are essentially blocking any higher order > > > > > allocations and also push the system towards more memory pressure. > > > > > > > > > > IIUC deferred splitting is mostly a workaround for nasty locking > > > > > issues > > > > > during splitting, right? This is not really an optimization to cache > > > > > THPs for reuse or something like that. What is the reason this is not > > > > > done from a worker context? At least THPs which would be freed > > > > > completely sound like a good candidate for kworker tear down, no? > > > > > > > > Agreed that it's a good question. For Kirill :) Maybe with kworker > > > > approach we > > > > also wouldn't need the cgroup awareness? > > > > > > I don't remember a particular locking issue, but I cannot say there's > > > none :P > > > > > > It's artifact from decoupling PMD split from compound page split: the same > > > page can be mapped multiple times with combination of PMDs and PTEs. Split > > > of one PMD doesn't need to trigger split of all PMDs and underlying > > > compound page. > > > > > > Other consideration is the fact that page split can fail and we need to > > > have fallback for this case. > > > > > > Also in most cases THP split would be just waste of time if we would do > > > them at the spot. If you don't have memory pressure it's better to wait > > > until process termination: less pages on LRU is still beneficial. > > > > This might be true but the reality shows that a lot of THPs might be > > waiting for the memory pressure that is essentially freeable on the > > spot. So I am not really convinced that "less pages on LRUs" is really a > > plausible justification. Can we free at least those THPs which are > > unmapped completely without any pte mappings? > > Unmapped completely pages will be freed with current code. Deferred split > only applies to partly mapped THPs: at least on 4k of the THP is still > mapped somewhere. Hmm, I am probably misreading the code but at least current Linus' tree reads page_remove_rmap -> [page_remove_anon_compound_rmap ->\ deferred_split_huge_page even for fully mapped THP. > > > Main source of partly mapped THPs comes from exit path. When PMD mapping > > > of THP got split across multiple VMAs (for instance due to mprotect()), > > > in exit path we unmap PTEs belonging to one VMA just before unmapping the > > > rest of the page. It would be total waste of time to split the page in > > > this scenario. > > > > > > The whole deferred split thing still looks as a reasonable compromise > > > to me. > > > > Even when it leads to all other problems mentioned in this and memcg > > deferred reclaim series? > > Yes. > > You would still need deferred split even if you *try* to split the page on > the spot. split_huge_page() can fail (due to pin on the page) and you will > need to have a way to try again later. > > You'll not win anything in complexity by trying split_huge_page() > immediately. I would ague you'll create much more complexity. I am not arguing for in place split. I am arguing to do it ASAP rather than to wait for memory pressure which might be in an unbound amount of time. So let me ask again. Why cannot we do that in the worker context? Essentially schedure the work item right away? > > > We may have some kind of watermark and try to keep the number
Re: [v2 PATCH -mm] mm: account deferred split THPs into MemAvailable
On Mon 26-08-19 21:27:38, Yang Shi wrote: > > > On 8/26/19 12:43 AM, Michal Hocko wrote: > > On Thu 22-08-19 08:33:40, Yang Shi wrote: > > > > > > On 8/22/19 1:04 AM, Michal Hocko wrote: > > > > On Thu 22-08-19 01:55:25, Yang Shi wrote: > > [...] > > > > > And, they seems very common with the common workloads when THP is > > > > > enabled. A simple run with MariaDB test of mmtest with THP enabled as > > > > > always shows it could generate over fifteen thousand deferred split > > > > > THPs > > > > > (accumulated around 30G in one hour run, 75% of 40G memory for my VM). > > > > > It looks worth accounting in MemAvailable. > > > > OK, this makes sense. But your above numbers are really worrying. > > > > Accumulating such a large amount of pages that are likely not going to > > > > be used is really bad. They are essentially blocking any higher order > > > > allocations and also push the system towards more memory pressure. > > > That is accumulated number, during the running of the test, some of them > > > were freed by shrinker already. IOW, it should not reach that much at any > > > given time. > > Then the above description is highly misleading. What is the actual > > number of lingering THPs that wait for the memory pressure in the peak? > > By rerunning sysbench mariadb test of mmtest, I didn't see too many THPs in > the peak. I saw around 2K THPs sometimes on my VM with 40G memory. But they > were short-lived (should be freed when the test exit). And, the number of > accumulated THPs are variable. > > And, this reminded me to go back double check our internal bug report which > lead to the "make deferred split shrinker memcg aware" patchset. > > In that case, a mysql instance with real production load was running in a > memcg with ~86G limit, the number of deferred split THPs may reach to ~68G > (~34K deferred split THPs) in a few hours. The deferred split THP shrinker > was not invoked since global memory pressure is still fine since the host > has 256G memory, but memcg limit reclaim was triggered. > > And, I can't tell if all those deferred split THPs came from mysql or not > since there were some other processes run in that container too according to > the oom log. > > I will update the commit log with the more solid data from production > environment. This is a very useful information. Thanks! > > > > IIUC deferred splitting is mostly a workaround for nasty locking issues > > > > during splitting, right? This is not really an optimization to cache > > > > THPs for reuse or something like that. What is the reason this is not > > > > done from a worker context? At least THPs which would be freed > > > > completely sound like a good candidate for kworker tear down, no? > > > Yes, deferred split THP was introduced to avoid locking issues according > > > to > > > the document. Memcg awareness would help to trigger the shrinker more > > > often. > > > > > > I think it could be done in a worker context, but when to trigger to > > > worker > > > is a subtle problem. > > Why? What is the problem to trigger it after unmap of a batch worth of > > THPs? > > This leads to another question, how many THPs are "a batch of worth"? Some arbitrary reasonable number. Few dozens of THPs waiting for split are no big deal. Going into GB as you pointed out above is definitely a problem. -- Michal Hocko SUSE Labs
Re: [RESEND PATCH v3 08/20] mtd: spi-nor: Split spi_nor_init_params()
On 26/08/19 5:38 PM, tudor.amba...@microchip.com wrote: > From: Tudor Ambarus > > Add functions to delimit what the chunks of code do: > > static void spi_nor_init_params() > { > spi_nor_info_init_params() > spi_nor_manufacturer_init_params() > spi_nor_sfdp_init_params() > } > > Add descriptions to all methods. > > spi_nor_init_params() becomes of type void, as all its children > return void. > > Signed-off-by: Tudor Ambarus > Reviewed-by: Boris Brezillon > --- > v3: rename spi_nor_legacy_init_params() to spi_nor_info_init_params() Reviewed-by: Vignesh Raghavendra Minor nits below... [...] > > +/** > + * spi_nor_init_params() - Initialize the flash's parameters and settings. > + * @nor: pointer to a 'struct spi-nor'. > + * > + * The flash parameters and settings are initialized based on a sequence of > + * calls that are ordered by priority: > + * > + * 1/ Default flash parameters initialization. The initializations are done > + *based on nor->info data: > + * spi_nor_info_init_params() > + * > + * which can be overwritten by: > + * 2/ Manufacturer flash parameters initialization. The initializations are > + *done based on MFR register, or when the decisions can not be done > solely > + *based on MFR, by using specific flash_info tweeks, ->default_init(): > + * spi_nor_manufacturer_init_params() > + * > + * which can be overwritten by: > + * 3/ SFDP flash parameters initialization. JESD216 SFDP is a standard and > + *should be more accurate that the above. > + * spi_nor_sfdp_init_params() > + * > + *Please not that there is a ->post_bfpt() fixup hook that can overwrite > the s/not/note > + *flash parameters and settings imediately after parsing the Basic Flash s/imediately/immediately > + *Parameter Table. > + */ > +static void spi_nor_init_params(struct spi_nor *nor) > +{ > + spi_nor_info_init_params(nor); > > spi_nor_manufacturer_init_params(nor); > > - if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) && > - !(info->flags & SPI_NOR_SKIP_SFDP)) { > - struct spi_nor_flash_parameter sfdp_params; > - > - memcpy(&sfdp_params, params, sizeof(sfdp_params)); > - > - if (spi_nor_parse_sfdp(nor, &sfdp_params)) { > - nor->addr_width = 0; > - nor->flags &= ~SNOR_F_4B_OPCODES; > - } else { > - memcpy(params, &sfdp_params, sizeof(*params)); > - } > - } > - > - return 0; > + if ((nor->info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) && > + !(nor->info->flags & SPI_NOR_SKIP_SFDP)) > + spi_nor_sfdp_init_params(nor); > } > > static int spi_nor_select_read(struct spi_nor *nor, > @@ -4670,10 +4715,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, > nor->info->flags & SPI_NOR_HAS_LOCK) > nor->clear_sr_bp = spi_nor_clear_sr_bp; > > - /* Parse the Serial Flash Discoverable Parameters table. */ > - ret = spi_nor_init_params(nor); > - if (ret) > - return ret; > + /* Init flash parameters based on flash_info struct and SFDP */ > + spi_nor_init_params(nor); > > if (!mtd->name) > mtd->name = dev_name(dev); > -- Regards Vignesh
Re: [linux-sunxi] [PATCH v6 1/3] ASoC: sun4i-i2s: incorrect regmap for A83T
On Tue, 27 Aug 2019 at 06:13, Chen-Yu Tsai wrote: > > On Tue, Aug 27, 2019 at 2:07 AM wrote: > > > > From: Marcus Cooper > > > > The regmap configuration is set up for the legacy block on the > > A83T whereas it uses the new block with a larger register map. > > Looking at the code Allwinner previously released [1], that doesn't seem to be > the case. Keep in mind that the register map shown in the user manual is for > the TDM interface, which we don't actually support right now. Should it matter what we support right now?, the block according to the user manual shows the bigger range. I don't have a A83T device and from what I gather not many users do. But the compatible for the H3 has been removed and replaced with the settings for the A83T which also has default settings in registers further up than SUNXI_RXCHMAP. > > The file shows the base address as 0x01c22800, and the last defined register > is SUNXI_RXCHMAP at 0x3c. > > The I2S driver [2] also shows that it is the old register map size, but with > TX_FIFO and INT_STA swapped around. This might mean that it would need a > separate regmap_config, as the read/write callbacks need to be changed to > fit the swapped registers. > > Finally, the TDM driver [3], which matches the TDM section in the manual, > shows > a larger register map. > > A83T is SUN8IW6, while SUN8IW7 refers to the H3. Since when have we trusted Allwinner code?, the TDM labelled block clearly supports I2S. The biggest use case for this block is getting HDMI audio working on the newer devices(LibreELEC nightlies has a user base of over 300) and I've tested this on numerous set ups over the last couple of years. Failing that reverting (3e9acd7ac693: "ASoC: sun4i-i2s: Remove duplicated quirks structure") would help. BR, CK > > ChenYu > > [1] > https://github.com/allwinner-zh/linux-3.4-sunxi/blob/master/sound/soc/sunxi/hdmiaudio/sunxi-hdmipcm.h > [2] > https://github.com/allwinner-zh/linux-3.4-sunxi/blob/master/sound/soc/sunxi/i2s0/sunxi-i2s0.h > [3] > https://github.com/allwinner-zh/linux-3.4-sunxi/blob/master/sound/soc/sunxi/daudio0/sunxi-daudio0.h > > > Fixes: 21faaea1343f ("ASoC: sun4i-i2s: Add support for A83T") > > Signed-off-by: Marcus Cooper > > --- > > sound/soc/sunxi/sun4i-i2s.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c > > index 57bf2a33753e..34575a8aa9f6 100644 > > --- a/sound/soc/sunxi/sun4i-i2s.c > > +++ b/sound/soc/sunxi/sun4i-i2s.c > > @@ -1100,7 +1100,7 @@ static const struct sun4i_i2s_quirks > > sun6i_a31_i2s_quirks = { > > static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { > > .has_reset = true, > > .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, > > - .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, > > + .sun4i_i2s_regmap = &sun8i_i2s_regmap_config, > > .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), > > .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2), > > .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6), > > -- > > 2.23.0 > > > > -- > > You received this message because you are subscribed to the Google Groups > > "linux-sunxi" group. > > To unsubscribe from this group and stop receiving emails from it, send an > > email to linux-sunxi+unsubscr...@googlegroups.com. > > To view this discussion on the web, visit > > https://groups.google.com/d/msgid/linux-sunxi/20190826180734.15801-2-codekipper%40gmail.com.
Re: [RESEND PATCH v3 07/20] mtd: spi_nor: Move manufacturer quad_enable() in ->default_init()
On 26/08/19 5:38 PM, tudor.amba...@microchip.com wrote: > From: Tudor Ambarus > > The goal is to move the quad_enable manufacturer specific init in the > nor->manufacturer->fixups->default_init() > > The legacy quad_enable() implementation is spansion_quad_enable(), > select this method by default. > > Set specific manufacturer fixups->default_init() hooks to overwrite > the default quad_enable() implementation when needed. > > Signed-off-by: Tudor Ambarus > Reviewed-by: Boris Brezillon > --- Reviewed-by: Vignesh Raghavendra Regards Vignesh > v3: collect R-b > > drivers/mtd/spi-nor/spi-nor.c | 48 > ++- > 1 file changed, 29 insertions(+), 19 deletions(-) > > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c > index 3dbbfe34d1d2..2a239531704a 100644 > --- a/drivers/mtd/spi-nor/spi-nor.c > +++ b/drivers/mtd/spi-nor/spi-nor.c > @@ -4150,13 +4150,38 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor, > return err; > } > > +static void macronix_set_default_init(struct spi_nor *nor) > +{ > + nor->params.quad_enable = macronix_quad_enable; > +} > + > +static void st_micron_set_default_init(struct spi_nor *nor) > +{ > + nor->params.quad_enable = NULL; > +} > + > /** > * spi_nor_manufacturer_init_params() - Initialize the flash's parameters and > - * settings based on ->default_init() hook. > + * settings based on MFR register and ->default_init() hook. > * @nor: pointer to a 'struct spi-nor'. > */ > static void spi_nor_manufacturer_init_params(struct spi_nor *nor) > { > + /* Init flash parameters based on MFR */ > + switch (JEDEC_MFR(nor->info)) { > + case SNOR_MFR_MACRONIX: > + macronix_set_default_init(nor); > + break; > + > + case SNOR_MFR_ST: > + case SNOR_MFR_MICRON: > + st_micron_set_default_init(nor); > + break; > + > + default: > + break; > + } > + > if (nor->info->fixups && nor->info->fixups->default_init) > nor->info->fixups->default_init(nor); > } > @@ -4168,6 +4193,9 @@ static int spi_nor_init_params(struct spi_nor *nor) > const struct flash_info *info = nor->info; > u8 i, erase_mask; > > + /* Initialize legacy flash parameters and settings. */ > + params->quad_enable = spansion_quad_enable; > + > /* Set SPI NOR sizes. */ > params->size = (u64)info->sector_size * info->n_sectors; > params->page_size = info->page_size; > @@ -4233,24 +4261,6 @@ static int spi_nor_init_params(struct spi_nor *nor) > SPINOR_OP_SE); > spi_nor_init_uniform_erase_map(map, erase_mask, params->size); > > - /* Select the procedure to set the Quad Enable bit. */ > - if (params->hwcaps.mask & (SNOR_HWCAPS_READ_QUAD | > -SNOR_HWCAPS_PP_QUAD)) { > - switch (JEDEC_MFR(info)) { > - case SNOR_MFR_MACRONIX: > - params->quad_enable = macronix_quad_enable; > - break; > - > - case SNOR_MFR_ST: > - case SNOR_MFR_MICRON: > - break; > - > - default: > - /* Kept only for backward compatibility purpose. */ > - params->quad_enable = spansion_quad_enable; > - break; > - } > - } > > spi_nor_manufacturer_init_params(nor); > > -- Regards Vignesh
Re: [RFC PATCH v2 1/3] x86/mm/tlb: Change __flush_tlb_one_user interface
On 26.08.19 18:38, Nadav Amit wrote: On Aug 26, 2019, at 12:51 AM, Juergen Gross wrote: On 24.08.19 00:52, Nadav Amit wrote: __flush_tlb_one_user() currently flushes a single entry, and flushes it both in the kernel and user page-tables, when PTI is enabled. Change __flush_tlb_one_user() and related interfaces into __flush_tlb_range() that flushes a range and does not flush the user page-table. This refactoring is needed for the next patch, but regardless makes sense and has several advantages. First, only Xen-PV, which does not use PTI, implements the paravirtual interface of flush_tlb_one_user() so nothing is broken by separating the user and kernel page-table flushes, and the interface is more intuitive. Second, INVLPG can flush unrelated mappings, and it is also a serializing instruction. It is better to have a tight loop that flushes the entries. Third, currently __flush_tlb_one_kernel() also flushes the user page-tables, which is not needed. This allows to avoid this redundant flush. Cc: Boris Ostrovsky Cc: Juergen Gross Cc: Stefano Stabellini Cc: xen-de...@lists.xenproject.org Signed-off-by: Nadav Amit --- arch/x86/include/asm/paravirt.h | 5 ++-- arch/x86/include/asm/paravirt_types.h | 3 ++- arch/x86/include/asm/tlbflush.h | 24 + arch/x86/kernel/paravirt.c| 7 ++--- arch/x86/mm/tlb.c | 39 ++- arch/x86/xen/mmu_pv.c | 21 +-- 6 files changed, 62 insertions(+), 37 deletions(-) ... diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c index 48f7c7eb4dbc..ed68657f5e77 100644 --- a/arch/x86/xen/mmu_pv.c +++ b/arch/x86/xen/mmu_pv.c @@ -1325,22 +1325,27 @@ static noinline void xen_flush_tlb(void) preempt_enable(); } -static void xen_flush_tlb_one_user(unsigned long addr) +static void xen_flush_tlb_range(unsigned long start, unsigned long end, + u8 stride_shift) { struct mmuext_op *op; struct multicall_space mcs; - - trace_xen_mmu_flush_tlb_one_user(addr); + unsigned long addr; preempt_disable(); mcs = xen_mc_entry(sizeof(*op)); op = mcs.args; - op->cmd = MMUEXT_INVLPG_LOCAL; - op->arg1.linear_addr = addr & PAGE_MASK; - MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); - xen_mc_issue(PARAVIRT_LAZY_MMU); + for (addr = start; addr < end; addr += 1ul << stride_shift) { + trace_xen_mmu_flush_tlb_one_user(addr); + + op->cmd = MMUEXT_INVLPG_LOCAL; + op->arg1.linear_addr = addr & PAGE_MASK; + MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); + + xen_mc_issue(PARAVIRT_LAZY_MMU); + } For this kind of usage (a loop) you should: - replace the call of xen_mc_entry() with xen_mc_batch() - use xen_extend_mmuext_op() for each loop iteration - call xen_mc_issue() after the loop Additionally I'd like you to replace trace_xen_mmu_flush_tlb_one_user() with trace_xen_mmu_flush_tlb_range() taking all three parameters and keep it where it was (out of the loop). The paravirt parts seem to be okay. Thanks for the quick response. I don’t think the preempt_disable/enable() is needed in this case, but I kept them. Does the following match what you had in mind? Yes, it does. BTW, preempt_disable/enable() is needed as xen_mc_batch() ... xen_mc_issue() is using a percpu buffer. Juergen --- arch/x86/xen/mmu_pv.c | 25 ++--- include/trace/events/xen.h | 18 -- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c index 48f7c7eb4dbc..faa01591df36 100644 --- a/arch/x86/xen/mmu_pv.c +++ b/arch/x86/xen/mmu_pv.c @@ -1325,20 +1325,23 @@ static noinline void xen_flush_tlb(void) preempt_enable(); } -static void xen_flush_tlb_one_user(unsigned long addr) +static void xen_flush_tlb_range(unsigned long start, unsigned long end, + u8 stride_shift) { - struct mmuext_op *op; - struct multicall_space mcs; - - trace_xen_mmu_flush_tlb_one_user(addr); + struct mmuext_op op; + unsigned long addr; preempt_disable(); - mcs = xen_mc_entry(sizeof(*op)); - op = mcs.args; - op->cmd = MMUEXT_INVLPG_LOCAL; - op->arg1.linear_addr = addr & PAGE_MASK; - MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); + xen_mc_batch(); + op.cmd = MMUEXT_INVLPG_LOCAL; + + trace_xen_mmu_flush_tlb_range(start, end, stride_shift); + + for (addr = start; addr < end; addr += 1ul << stride_shift) { + op.arg1.linear_addr = addr & PAGE_MASK; + xen_extend_mmuext_op(&op); + } xen_mc_issue(PARAVIRT_LAZY_MMU); @@ -2394,7 +2397,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = { .flush_tlb_user = xen_flush_tlb, .flush_tlb_kernel = xen_flush_tl
linux-next: build failure after merge of the phy-next tree
Hi all, After merging the phy-next tree, today's linux-next build (x86_64 allmodconfig) failed like this: ERROR: "__arm_smccc_smc" [drivers/phy/marvell/phy-mvebu-cp110-comphy.ko] undefined! Caused by commit ccee80654309 ("phy: mvebu-cp110-comphy: Add SMC call support") I have used the phy-next tree from next-20190826 for today. -- Cheers, Stephen Rothwell pgpcsCZMbwn6u.pgp Description: OpenPGP digital signature
Re: [PATCH V5 1/3] riscv: Add perf callchain support
We need know the values of *regs, eg: regs->sepc, regs->ra, regs->fp, regs->sp, regs->tp void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) { ... walk_stackframe(&fr, entry); // May be we could detect error here and print the regs' value } On Mon, Aug 26, 2019 at 4:03 PM Greentime Hu wrote: > > Hi Guo, > > Guo Ren 於 2019年8月24日 週六 上午8:54寫道: > > > > Please check CONFIG_FRAME_POINTER > > > > 1 *frame = *((struct stackframe *)frame->fp - 1); > > This code is origionally from riscv/kernel/stacktrace.c: walk_stackframe > > > > In linux/Makefile it'll involve the options for gcc to definitely > > store ra & prev_fp in fp pointer. > > ifdef CONFIG_FRAME_POINTER > > KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls > > > > So --call-graph fp need depends on CONFIG_FRAME_POINTER. > > > > I am pretty sure CONFIG_FRAME_POINTER is Y > # zcat /proc/config.gz |grep CONFIG_FRAME_POINTER > CONFIG_FRAME_POINTER=y > > This is not going to go wrong every time, the probability of error is > about one tenth or one quarter. randomly > There may be some conditions that we have not considered. > > I add one more condition to check if it is a valid virtual address and > it( ./perf record -e cpu-clock --call-graph fp ls) passes 1000 times > without failure in Unleashed board based on 5.3-rc5. > Here is my patch. Please have a look at it. I am not sure if it is a > good solution. > > diff --git a/arch/riscv/kernel/perf_callchain.c > b/arch/riscv/kernel/perf_callchain.c > index d75d15c13dc7..4717942435df 100644 > --- a/arch/riscv/kernel/perf_callchain.c > +++ b/arch/riscv/kernel/perf_callchain.c > @@ -18,6 +18,8 @@ static int unwind_frame_kernel(struct stackframe *frame) > return -EPERM; > if (frame->fp < CONFIG_PAGE_OFFSET) > return -EPERM; > + if (!virt_addr_valid(frame->fp)) > + return -EPERM; > > *frame = *((struct stackframe *)frame->fp - 1); > if (__kernel_text_address(frame->ra)) { > > It could catch cases called in this way. > > [ 1381.936586] frame->fp=:00547550 > [ 1382.038542] CPU: 1 PID: 135 Comm: ls Not tainted > 5.3.0-rc5-3-gb008f6bcd67c-dirty #14 > [ 1382.307440] Call Trace: > [ 1382.388947] [] walk_stackframe+0x0/0x9a > [ 1382.568053] [] show_stack+0x2a/0x34 > [ 1382.735960] [] dump_stack+0x62/0x7c > [ 1382.903863] [] perf_callchain_kernel+0xd8/0x102 > [ 1383.106558] [] get_perf_callchain+0x136/0x1f2 > [ 1383.303128] [] perf_callchain+0x52/0x6e > [ 1383.482553] [] perf_prepare_sample+0x6e/0x476 > [ 1383.679357] [] perf_event_output_forward+0x1c/0x50 > [ 1383.890633] [] __perf_event_overflow+0x6a/0xa4 > [ 1384.090279] [] perf_swevent_hrtimer+0xba/0x106 > [ 1384.290094] [] __hrtimer_run_queues+0x84/0x108 > [ 1384.489694] [] hrtimer_interrupt+0xca/0x1ce > [ 1384.680974] [] riscv_timer_interrupt+0x32/0x3a > [ 1384.880449] [] do_IRQ+0x64/0xbe > [ 1385.036698] [] ret_from_exception+0x0/0xc > > [13915.697989] frame->fp=:f000 > [13915.799937] CPU: 2 PID: 663 Comm: ls Not tainted > 5.3.0-rc5-3-gb008f6bcd67c-dirty #14 > [13916.068832] Call Trace: > [13916.150380] [] walk_stackframe+0x0/0x9a > [13916.329450] [] show_stack+0x2a/0x34 > [13916.497360] [] dump_stack+0x62/0x7c > [13916.665265] [] perf_callchain_kernel+0xd8/0x102 > [13916.867949] [] get_perf_callchain+0x136/0x1f2 > [13917.064526] [] perf_callchain+0x52/0x6e > [13917.243950] [] perf_prepare_sample+0x6e/0x476 > [13917.440759] [] perf_event_output_forward+0x1c/0x50 > [13917.652021] [] __perf_event_overflow+0x6a/0xa4 > [13917.851683] [] perf_swevent_hrtimer+0xba/0x106 > [13918.051494] [] __hrtimer_run_queues+0x84/0x108 > [13918.251094] [] hrtimer_interrupt+0xca/0x1ce > [13918.442379] [] riscv_timer_interrupt+0x32/0x3a > [13918.641840] [] do_IRQ+0x64/0xbe > [13918.798082] [] ret_from_exception+0x0/0xc -- Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/
Re: [RESEND PATCH v3 05/20] mtd: spi-nor: Add default_init() hook to tweak flash parameters
On 26/08/19 5:38 PM, tudor.amba...@microchip.com wrote: > From: Tudor Ambarus > > As of now, the flash parameters initialization logic is as following: > > a/ default flash parameters init in spi_nor_init_params() > b/ manufacturer specific flash parameters updates, split across entire >spi-nor core code > c/ flash parameters updates based on SFDP tables > d/ post BFPT flash parameter updates > > In the quest of removing the manufacturer specific code from the spi-nor > core, we want to impose a timeline/priority on how the flash parameters > are updated. The following sequence of calls is pursued: > > 1/ spi-nor core parameters init based on 'flash_info' struct: > spi_nor_info_init_params() > > which can be overwritten by: > 2/ MFR-based manufacturer flash parameters init: > nor->manufacturer->fixups->default_init() > > which can be overwritten by: > 3/ specific flash_info tweeks done when decisions can not be done just on >MFR: > nor->info->fixups->default_init() > > which can be overwritten by: > 4/ SFDP tables flash parameters init - SFDP knows better: > spi_nor_sfdp_init_params() > > which can be overwritten by: > 5/ post SFDP tables flash parameters updates - in case manufacturers get >the serial flash tables wrong or incomplete. > nor->info->fixups->post_sfdp() >The later can be extended to nor->manufacturer->fixups->post_sfdp() if >needed. > > This patch opens doors for steps 2/ and 3/. > > Signed-off-by: Tudor Ambarus > Reviewed-by: Boris Brezillon > --- Reviewed-by: Vignesh Raghavendra Regards Vignesh > v3: reword description > > drivers/mtd/spi-nor/spi-nor.c | 17 + > 1 file changed, 17 insertions(+) > > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c > index 9dd6cd8cd13c..8fd60e1eebd2 100644 > --- a/drivers/mtd/spi-nor/spi-nor.c > +++ b/drivers/mtd/spi-nor/spi-nor.c > @@ -154,12 +154,16 @@ struct sfdp_bfpt { > > /** > * struct spi_nor_fixups - SPI NOR fixup hooks > + * @default_init: called after default flash parameters init. Used to tweak > + *flash parameters when information provided by the > flash_info > + *table is incomplete or wrong. > * @post_bfpt: called after the BFPT table has been parsed > * > * Those hooks can be used to tweak the SPI NOR configuration when the SFDP > * table is broken or not available. > */ > struct spi_nor_fixups { > + void (*default_init)(struct spi_nor *nor); > int (*post_bfpt)(struct spi_nor *nor, >const struct sfdp_parameter_header *bfpt_header, >const struct sfdp_bfpt *bfpt, > @@ -4133,6 +4137,17 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor, > return err; > } > > +/** > + * spi_nor_manufacturer_init_params() - Initialize the flash's parameters and > + * settings based on ->default_init() hook. > + * @nor: pointer to a 'struct spi-nor'. > + */ > +static void spi_nor_manufacturer_init_params(struct spi_nor *nor) > +{ > + if (nor->info->fixups && nor->info->fixups->default_init) > + nor->info->fixups->default_init(nor); > +} > + > static int spi_nor_init_params(struct spi_nor *nor) > { > struct spi_nor_flash_parameter *params = &nor->params; > @@ -4233,6 +4248,8 @@ static int spi_nor_init_params(struct spi_nor *nor) > params->quad_enable = info->quad_enable; > } > > + spi_nor_manufacturer_init_params(nor); > + > if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) && > !(info->flags & SPI_NOR_SKIP_SFDP)) { > struct spi_nor_flash_parameter sfdp_params; > -- Regards Vignesh
Re: [RESEND PATCH v3 06/20] mtd: spi-nor: Add a default_init() fixup hook for gd25q256
On 26/08/19 5:38 PM, tudor.amba...@microchip.com wrote: > From: Boris Brezillon > > gd25q256 needs to tweak the ->quad_enable() implementation and the > ->default_init() fixup hook is the perfect place to do that. This way, > if we ever need to tweak more things for this flash, we won't have to > add new fields in flash_info. > > We can get rid of the flash_info->quad_enable field as gd25q256 was > the only user. > > Signed-off-by: Boris Brezillon > [tudor.amba...@microchip.com: use ->default_init() hook instead of > ->post_sfdp()] > Signed-off-by: Tudor Ambarus > --- Reviewed-by: Vignesh Raghavendra Regards Vignesh > v3: no changes > > drivers/mtd/spi-nor/spi-nor.c | 28 > 1 file changed, 16 insertions(+), 12 deletions(-) > > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c > index 8fd60e1eebd2..3dbbfe34d1d2 100644 > --- a/drivers/mtd/spi-nor/spi-nor.c > +++ b/drivers/mtd/spi-nor/spi-nor.c > @@ -222,8 +222,6 @@ struct flash_info { > > /* Part specific fixup hooks. */ > const struct spi_nor_fixups *fixups; > - > - int (*quad_enable)(struct spi_nor *nor); > }; > > #define JEDEC_MFR(info) ((info)->id[0]) > @@ -2126,6 +2124,21 @@ static struct spi_nor_fixups mx25l25635_fixups = { > .post_bfpt = mx25l25635_post_bfpt_fixups, > }; > > +static void gd25q256_default_init(struct spi_nor *nor) > +{ > + /* > + * Some manufacturer like GigaDevice may use different > + * bit to set QE on different memories, so the MFR can't > + * indicate the quad_enable method for this case, we need > + * to set it in the default_init fixup hook. > + */ > + nor->params.quad_enable = macronix_quad_enable; > +} > + > +static struct spi_nor_fixups gd25q256_fixups = { > + .default_init = gd25q256_default_init, > +}; > + > /* NOTE: double check command sets and memory organization when you add > * more nor chips. This current list focusses on newer chips, which > * have been converging on command sets which including JEDEC ID. > @@ -2218,7 +2231,7 @@ static const struct flash_info spi_nor_ids[] = { > "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512, > SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | > SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) > - .quad_enable = macronix_quad_enable, > + .fixups = &gd25q256_fixups, > }, > > /* Intel/Numonyx -- xxxs33b */ > @@ -4237,15 +4250,6 @@ static int spi_nor_init_params(struct spi_nor *nor) > params->quad_enable = spansion_quad_enable; > break; > } > - > - /* > - * Some manufacturer like GigaDevice may use different > - * bit to set QE on different memories, so the MFR can't > - * indicate the quad_enable method for this case, we need > - * set it in flash info list. > - */ > - if (info->quad_enable) > - params->quad_enable = info->quad_enable; > } > > spi_nor_manufacturer_init_params(nor); > -- Regards Vignesh
Re: [PATCH] ext4: change the type of ext4 cache stats to percpu_counter to improve performance
Hi Theodore, On 2019/8/26 23:57, Theodore Y. Ts'o wrote: > On Mon, Aug 26, 2019 at 04:24:20PM +0800, Shaokun Zhang wrote: >>> The other problem with this patch is that it initializes >>> es_stats_cache_hits and es_stats_cache_miesses too late. They will >>> get used when the journal inode is loaded. This is mostly harmless, >> >> I have checked it again, @es_stats_cache_hits and @es_stats_cache_miesses >> have been initialized before the journal inode is loaded, Maybe I miss >> something else? > > No, sorry, that was my mistake. I misread things when I was looking > over your patch last night. > > Please resubmit your patch once you've fixed things up and tested it. > Sure, will do it soon. > I would recommend that you at least try running your patch using the > kvm-xfstests's smoke test[1] before submitting them. It will save you > and me time. > Ok, thanks your guidance. Shaokun, > [1] > https://github.com/tytso/xfstests-bld/blob/master/Documentation/kvm-quickstart.md > > Thanks, > > - Ted > > > . >
Re: PageBlocks and Migrate Types
On Mon 26-08-19 22:35:08, Pankaj Suryawanshi wrote: > On Mon, Aug 26, 2019 at 12:34 PM Michal Hocko wrote: > > > > On Thu 22-08-19 23:54:19, Pankaj Suryawanshi wrote: > > > On Thu, Aug 22, 2019 at 6:22 PM Michal Hocko wrote: > > > > > > > > On Wed 21-08-19 22:23:44, Pankaj Suryawanshi wrote: > > > > > Hello, > > > > > > > > > > 1. What are Pageblocks and migrate types(MIGRATE_CMA) in Linux > memory ? > > > > > > > > Pageblocks are a simple grouping of physically contiguous pages with > > > > common set of flags. I haven't checked closely recently so I might > > > > misremember but my recollection is that only the migrate type is > stored > > > > there. Normally we would store that information into page flags but > > > > there is not enough room there. > > > > > > > > MIGRATE_CMA represent pages allocated for the CMA allocator. There are > > > > other migrate types denoting unmovable/movable allocations or pages > that > > > > are isolated from the page allocator. > > > > > > > > Very broadly speaking, the migrate type groups pages with similar > > > > movability properties to reduce fragmentation that compaction cannot > > > > do anything about because there are objects of different properti > > > > around. Please note that pageblock might contain objects of a > different > > > > migrate type in some cases (e.g. low on memory). > > > > > > > > Have a look at gfpflags_to_migratetype and how the gfp mask is > converted > > > > to a migratetype for the allocation. Also follow different > MIGRATE_$TYPE > > > > to see how it is used in the code. > > > > > > > > > How many movable/unmovable pages are defined by default? > > > > > > > > There is nothing like that. It depends on how many objects of a > specific > > > > type are allocated. > > > > > > > > > It means that it started creating pageblocks after allocation of > > > different objects, but from which block it allocate initially when > > > there is nothing like pageblocks ? (when memory subsystem up) > > > > Pageblocks are just a way to group physically contiguous pages. They > > just exist along with the physically contiguous memory. The migrate type > > for most of the memory is set to MIGRATE_MOVABLE. Portion of the memory > > might be reserved by CMA then that memory has MIGRATE_CMA. Following > > set_pageblock_migratetype call paths will give you a good picture. > > it means if i have 4096 continuous pages = 1 pageblock > then all the 4096 pages of same type. but if any one page is different than > block type then ? it changed the block type or something else ? That really depends on the specific migrate type. CMA, ISOLATE migrate types are all or nothing IIRC. I would have to check the code to tell exactly when MOVABLE/UNMOVABLE pageblocks transitions are done. steal_suitable_fallback sounds like a good start to look at. -- Michal Hocko SUSE Labs
Re: [RESEND PATCH v3 04/20] mtd: spi-nor: Move erase_map to 'struct spi_nor_flash_parameter'
On 26/08/19 5:38 PM, tudor.amba...@microchip.com wrote: > From: Tudor Ambarus > > All flash parameters and settings should reside inside > 'struct spi_nor_flash_parameter'. Move the SMPT parsed erase map > from 'struct spi_nor' to 'struct spi_nor_flash_parameter'. > > Please note that there is a roll-back mechanism for the flash > parameter and settings, for cases when SFDP parser fails. The SFDP > parser receives a Stack allocated copy of nor->params, called > sfdp_params, and uses it to retrieve the serial flash discoverable > parameters. JESD216 SFDP is a standard and has a higher priority > than the default initialized flash parameters, so will overwrite the > sfdp_params data when needed. All SFDP code uses the local copy of > nor->params, that will overwrite it in the end, if the parser succeds. > > Saving and restoring the nor->params.erase_map is no longer needed, > since the SFDP code does not touch it. > > Signed-off-by: Tudor Ambarus > --- Reviewed-by: Vignesh Raghavendra Regards Vignesh > v3: Collect R-b > > drivers/mtd/spi-nor/spi-nor.c | 40 +--- > include/linux/mtd/spi-nor.h | 8 +--- > 2 files changed, 26 insertions(+), 22 deletions(-) > > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c > index effda372cb33..9dd6cd8cd13c 100644 > --- a/drivers/mtd/spi-nor/spi-nor.c > +++ b/drivers/mtd/spi-nor/spi-nor.c > @@ -600,7 +600,7 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor) > nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode); > > if (!spi_nor_has_uniform_erase(nor)) { > - struct spi_nor_erase_map *map = &nor->erase_map; > + struct spi_nor_erase_map *map = &nor->params.erase_map; > struct spi_nor_erase_type *erase; > int i; > > @@ -1133,7 +1133,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor > *nor, > struct list_head *erase_list, > u64 addr, u32 len) > { > - const struct spi_nor_erase_map *map = &nor->erase_map; > + const struct spi_nor_erase_map *map = &nor->params.erase_map; > const struct spi_nor_erase_type *erase, *prev_erase = NULL; > struct spi_nor_erase_region *region; > struct spi_nor_erase_command *cmd = NULL; > @@ -3328,7 +3328,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, > const struct sfdp_parameter_header *bfpt_header, > struct spi_nor_flash_parameter *params) > { > - struct spi_nor_erase_map *map = &nor->erase_map; > + struct spi_nor_erase_map *map = ¶ms->erase_map; > struct spi_nor_erase_type *erase_type = map->erase_type; > struct sfdp_bfpt bfpt; > size_t len; > @@ -3409,7 +3409,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, >* Erase Types defined in the bfpt table. >*/ > erase_mask = 0; > - memset(&nor->erase_map, 0, sizeof(nor->erase_map)); > + memset(¶ms->erase_map, 0, sizeof(params->erase_map)); > for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_erases); i++) { > const struct sfdp_bfpt_erase *er = &sfdp_bfpt_erases[i]; > u32 erasesize; > @@ -3684,14 +3684,18 @@ spi_nor_region_check_overlay(struct > spi_nor_erase_region *region, > /** > * spi_nor_init_non_uniform_erase_map() - initialize the non-uniform erase > map > * @nor: pointer to a 'struct spi_nor' > + * @params: pointer to a duplicate 'struct spi_nor_flash_parameter' that > is > + * used for storing SFDP parsed data > * @smpt:pointer to the sector map parameter table > * > * Return: 0 on success, -errno otherwise. > */ > -static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, > - const u32 *smpt) > +static int > +spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, > +struct spi_nor_flash_parameter *params, > +const u32 *smpt) > { > - struct spi_nor_erase_map *map = &nor->erase_map; > + struct spi_nor_erase_map *map = ¶ms->erase_map; > struct spi_nor_erase_type *erase = map->erase_type; > struct spi_nor_erase_region *region; > u64 offset; > @@ -3770,6 +3774,8 @@ static int spi_nor_init_non_uniform_erase_map(struct > spi_nor *nor, > * spi_nor_parse_smpt() - parse Sector Map Parameter Table > * @nor: pointer to a 'struct spi_nor' > * @smpt_header: sector map parameter table header > + * @params: pointer to a duplicate 'struct spi_nor_flash_parameter' > + * that is used for storing SFDP parsed data > * > * This table is optional, but when available, we parse it to identify the > * location and size of sectors within the main data array of the flash > memory > @@ -3778,7 +3784,8 @@ static int spi_nor_init_non_uniform_erase_map(struct >
[PATCH 1/2] mm: Don't manually decrement num_poisoned_pages
From: Alastair D'Silva Use the function written to do it instead. Signed-off-by: Alastair D'Silva --- mm/sparse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm/sparse.c b/mm/sparse.c index 72f010d9bff5..e41917a7e844 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "internal.h" #include @@ -898,7 +900,7 @@ static void clear_hwpoisoned_pages(struct page *memmap, int nr_pages) for (i = 0; i < nr_pages; i++) { if (PageHWPoison(&memmap[i])) { - atomic_long_sub(1, &num_poisoned_pages); + num_poisoned_pages_dec(); ClearPageHWPoison(&memmap[i]); } } -- 2.21.0
[PATCH 2/2] mm: don't hide potentially null memmap pointer in sparse_remove_section
From: Alastair D'Silva By adding offset to memmap before passing it in to clear_hwpoisoned_pages, we hide a theoretically null memmap from the null check inside clear_hwpoisoned_pages. This patch passes the offset to clear_hwpoisoned_pages instead, allowing memmap to successfully perform it's null check. Signed-off-by: Alastair D'Silva --- mm/sparse.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mm/sparse.c b/mm/sparse.c index e41917a7e844..3ff84e627e58 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -882,7 +882,7 @@ int __meminit sparse_add_section(int nid, unsigned long start_pfn, } #ifdef CONFIG_MEMORY_FAILURE -static void clear_hwpoisoned_pages(struct page *memmap, int nr_pages) +static void clear_hwpoisoned_pages(struct page *memmap, int start, int count) { int i; @@ -898,7 +898,7 @@ static void clear_hwpoisoned_pages(struct page *memmap, int nr_pages) if (atomic_long_read(&num_poisoned_pages) == 0) return; - for (i = 0; i < nr_pages; i++) { + for (i = start; i < start + count; i++) { if (PageHWPoison(&memmap[i])) { num_poisoned_pages_dec(); ClearPageHWPoison(&memmap[i]); @@ -906,7 +906,8 @@ static void clear_hwpoisoned_pages(struct page *memmap, int nr_pages) } } #else -static inline void clear_hwpoisoned_pages(struct page *memmap, int nr_pages) +static inline void clear_hwpoisoned_pages(struct page *memmap, int start, + int count) { } #endif @@ -915,7 +916,7 @@ void sparse_remove_section(struct mem_section *ms, unsigned long pfn, unsigned long nr_pages, unsigned long map_offset, struct vmem_altmap *altmap) { - clear_hwpoisoned_pages(pfn_to_page(pfn) + map_offset, + clear_hwpoisoned_pages(pfn_to_page(pfn), map_offset, nr_pages - map_offset); section_deactivate(pfn, nr_pages, altmap); } -- 2.21.0
[PATCH 0/2] mm: Minor cleanup
From: Alastair D'Silva This series addresses some minor issues & obsoletes: mm: Cleanup & allow modules to hotplug memory Alastair D'Silva (2): mm: Don't manually decrement num_poisoned_pages mm: don't hide potentially null memmap pointer in sparse_remove_section mm/sparse.c | 13 - 1 file changed, 8 insertions(+), 5 deletions(-) -- 2.21.0
Re: [RESEND PATCH v3 00/20] mtd: spi-nor: move manuf out of the core
On 26/08/19 5:38 PM, tudor.amba...@microchip.com wrote: > From: Tudor Ambarus [...] > > Tested on sst26vf064b with atmel-quadspi SPIMEM driver. > Tested s25fl256s, mx66l51235l with ti-qspi and s25fl512s with cadence-quadspi. n25q128a13 with legacy 1 bit SPI controller. > Boris Brezillon (7): > mtd: spi-nor: Add a default_init() fixup hook for gd25q256 > mtd: spi-nor: Create a ->set_4byte() method > mtd: spi-nor: Rework the SPI NOR lock/unlock logic > mtd: spi-nor: Add post_sfdp() hook to tweak flash config > mtd: spi-nor: Add spansion_post_sfdp_fixups() > mtd: spi-nor: Add a ->convert_addr() method > mtd: spi-nor: Add the SPI_NOR_XSR_RDY flag > > Tudor Ambarus (13): > mtd: spi-nor: Regroup flash parameter and settings > mtd: spi-nor: Use nor->params > mtd: spi-nor: Drop quad_enable() from 'struct spi-nor' > mtd: spi-nor: Move erase_map to 'struct spi_nor_flash_parameter' > mtd: spi-nor: Add default_init() hook to tweak flash parameters > mtd: spi_nor: Move manufacturer quad_enable() in ->default_init() > mtd: spi-nor: Split spi_nor_init_params() > mtd: spi_nor: Add a ->setup() method > mtd: spi-nor: Add s3an_post_sfdp_fixups() > mtd: spi-nor: Bring flash params init together > mtd: spi_nor: Introduce spi_nor_set_addr_width() > mtd: spi-nor: Introduce spi_nor_get_flash_info() > mtd: spi-nor: Rework the disabling of block write protection > > drivers/mtd/spi-nor/spi-nor.c | 1304 > +++-- > include/linux/mtd/spi-nor.h | 298 +++--- > 2 files changed, 927 insertions(+), 675 deletions(-) > -- Regards Vignesh