[PATCH] Revert "clocksource/drivers/timer_sun5i: Replace code by clocksource_mmio_init"
This reverts commit 157dfadef832 ("clocksource/drivers/timer_sun5i: Replace code by clocksource_mmio_init"). struct clocksource is also used by the clk notifier callback, to unregister and re-register the clocksource with a different clock rate. clocksource_mmio_init does not pass back a pointer to the struct used, and the clk notifier callback fixed assumed the struct clocksource in struct sun5i_timer_clksrc was valid. This results in a kernel NULL pointer dereference when the hstimer clock is changed: Unable to handle kernel NULL pointer dereference at virtual address 0004 pgd = c0204000 [0004] *pgd= Internal error: Oops: 805 [#1] SMP ARM Modules linked in: CPU: 0 PID: 44 Comm: kworker/0:1 Not tainted 4.8.0-14234-g346c22e #1 Hardware name: Allwinner sun6i (A31) Family Workqueue: events dbs_work_handler task: ee1e0a80 task.stack: ee282000 PC is at clocksource_unbind+0x2c/0x5c LR is at clocksource_unregister+0x2c/0x44 pc : []lr : []psr: 2013 sp : ee283d38 ip : ee019288 fp : 00124f80 r10: r9 : r8 : ee007808 r7 : r6 : 0001 r5 : c1442b50 r4 : ee019298 r3 : ee0192cc r2 : r1 : r0 : Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none Control: 10c5387d Table: 4020406a DAC: 0051 Process kworker/0:1 (pid: 44, stack limit = 0xee282220) Stack: (0xee283d38 to 0xee284000) 3d20: ee019298 ee283dac 3d40: 0001 c03a46d4 c0a6f350 c035ea50 ee01a0dc ee01a0c4 3d60: 0001 ee283dac c035edc0 c066fb7c ee01a0c0 c1388890 3d80: ee00f480 0001 fffa 00124f80 00124f80 c035edf4 c13ab624 3da0: 0001 c0670174 ee0188c0 0501bd00 044aa200 ee01a01c ee00f480 3dc0: ee00f480 0001 c06702c0 ee00f480 ee00cd00 0001 3de0: fffa c0670288 ee00cd00 ee00cc80 0001 fffa c0670288 3e00: ee00cc80 ee00cc00 0001 fffa c0670288 ee00cc00 ee00c300 3e20: 0001 fffa c0670288 ee00cc00 337f9800 eefa8050 ee00c300 3e40: fffa c0672020 ee686940 337f9800 eefa8050 ee6868c0 fffa c0672098 3e60: ee686940 ee663400 eefa8050 c07eea64 000d2f00 c0a216fc 337f9800 3c14dc00 3e80: c1302514 ee57ac00 0002 c1462434 000d2f00 3ea0: ee22d680 c0a21cb8 0010 000f6180 000d2f00 0021 ee68cc00 ee57ac00 3ec0: 0092a180 00a79400 ee68cc80 ee686c40 eefad900 c0a25344 ee68cc40 3ee0: ee68cc04 ee57ac00 c1408bac eefad900 c0a2588c ee68cc40 ee22d680 3f00: eefad900 eefb0e00 c0357d84 c1302100 eefad918 eefad900 ee22d698 3f20: 0008 c1302100 eefad918 ee282000 eefad900 c0358a00 ee22bc00 ee22d680 3f40: c03589c8 ee22bc00 ee22d680 c03589c8 3f60: c035d66c ee22d680 3f80: ee283f80 ee283f80 ee283f90 ee283f90 ee22bc00 ee22bc00 3fa0: c035d590 c0307d38 3fc0: 3fe0: 0013 [] (clocksource_unbind) from [] (clocksource_unregister+0x2c/0x44) [] (clocksource_unregister) from [] (sun5i_rate_cb_clksrc+0x34/0x3c) [] (sun5i_rate_cb_clksrc) from [] (notifier_call_chain+0x44/0x84) [] (notifier_call_chain) from [] (__srcu_notifier_call_chain+0x44/0x60) [] (__srcu_notifier_call_chain) from [] (srcu_notifier_call_chain+0x18/0x20) [] (srcu_notifier_call_chain) from [] (__clk_notify+0x70/0x7c) [] (__clk_notify) from [] (clk_propagate_rate_change+0xa4/0xc4) [] (clk_propagate_rate_change) from [] (clk_propagate_rate_change+0x6c/0xc4) Code: e5942038 e2843034 e5941034 e3a0 (e5812004) ---[ end trace c5149f92effb19a4 ]--- Revert the commit for now. clocksource_mmio_init can be made to pass back a pointer, but the code churn and usage of an inner struct might not be worth it. Reported-by: Maxime RipardFixes: 157dfadef832 ("clocksource/drivers/timer_sun5i: Replace code by clocksource_mmio_init") Signed-off-by: Chen-Yu Tsai --- drivers/clocksource/timer-sun5i.c | 16 ++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c index c184eb84101e..4f87f3e76d83 100644 --- a/drivers/clocksource/timer-sun5i.c +++ b/drivers/clocksource/timer-sun5i.c @@
[PATCH] Revert "clocksource/drivers/timer_sun5i: Replace code by clocksource_mmio_init"
This reverts commit 157dfadef832 ("clocksource/drivers/timer_sun5i: Replace code by clocksource_mmio_init"). struct clocksource is also used by the clk notifier callback, to unregister and re-register the clocksource with a different clock rate. clocksource_mmio_init does not pass back a pointer to the struct used, and the clk notifier callback fixed assumed the struct clocksource in struct sun5i_timer_clksrc was valid. This results in a kernel NULL pointer dereference when the hstimer clock is changed: Unable to handle kernel NULL pointer dereference at virtual address 0004 pgd = c0204000 [0004] *pgd= Internal error: Oops: 805 [#1] SMP ARM Modules linked in: CPU: 0 PID: 44 Comm: kworker/0:1 Not tainted 4.8.0-14234-g346c22e #1 Hardware name: Allwinner sun6i (A31) Family Workqueue: events dbs_work_handler task: ee1e0a80 task.stack: ee282000 PC is at clocksource_unbind+0x2c/0x5c LR is at clocksource_unregister+0x2c/0x44 pc : []lr : []psr: 2013 sp : ee283d38 ip : ee019288 fp : 00124f80 r10: r9 : r8 : ee007808 r7 : r6 : 0001 r5 : c1442b50 r4 : ee019298 r3 : ee0192cc r2 : r1 : r0 : Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none Control: 10c5387d Table: 4020406a DAC: 0051 Process kworker/0:1 (pid: 44, stack limit = 0xee282220) Stack: (0xee283d38 to 0xee284000) 3d20: ee019298 ee283dac 3d40: 0001 c03a46d4 c0a6f350 c035ea50 ee01a0dc ee01a0c4 3d60: 0001 ee283dac c035edc0 c066fb7c ee01a0c0 c1388890 3d80: ee00f480 0001 fffa 00124f80 00124f80 c035edf4 c13ab624 3da0: 0001 c0670174 ee0188c0 0501bd00 044aa200 ee01a01c ee00f480 3dc0: ee00f480 0001 c06702c0 ee00f480 ee00cd00 0001 3de0: fffa c0670288 ee00cd00 ee00cc80 0001 fffa c0670288 3e00: ee00cc80 ee00cc00 0001 fffa c0670288 ee00cc00 ee00c300 3e20: 0001 fffa c0670288 ee00cc00 337f9800 eefa8050 ee00c300 3e40: fffa c0672020 ee686940 337f9800 eefa8050 ee6868c0 fffa c0672098 3e60: ee686940 ee663400 eefa8050 c07eea64 000d2f00 c0a216fc 337f9800 3c14dc00 3e80: c1302514 ee57ac00 0002 c1462434 000d2f00 3ea0: ee22d680 c0a21cb8 0010 000f6180 000d2f00 0021 ee68cc00 ee57ac00 3ec0: 0092a180 00a79400 ee68cc80 ee686c40 eefad900 c0a25344 ee68cc40 3ee0: ee68cc04 ee57ac00 c1408bac eefad900 c0a2588c ee68cc40 ee22d680 3f00: eefad900 eefb0e00 c0357d84 c1302100 eefad918 eefad900 ee22d698 3f20: 0008 c1302100 eefad918 ee282000 eefad900 c0358a00 ee22bc00 ee22d680 3f40: c03589c8 ee22bc00 ee22d680 c03589c8 3f60: c035d66c ee22d680 3f80: ee283f80 ee283f80 ee283f90 ee283f90 ee22bc00 ee22bc00 3fa0: c035d590 c0307d38 3fc0: 3fe0: 0013 [] (clocksource_unbind) from [] (clocksource_unregister+0x2c/0x44) [] (clocksource_unregister) from [] (sun5i_rate_cb_clksrc+0x34/0x3c) [] (sun5i_rate_cb_clksrc) from [] (notifier_call_chain+0x44/0x84) [] (notifier_call_chain) from [] (__srcu_notifier_call_chain+0x44/0x60) [] (__srcu_notifier_call_chain) from [] (srcu_notifier_call_chain+0x18/0x20) [] (srcu_notifier_call_chain) from [] (__clk_notify+0x70/0x7c) [] (__clk_notify) from [] (clk_propagate_rate_change+0xa4/0xc4) [] (clk_propagate_rate_change) from [] (clk_propagate_rate_change+0x6c/0xc4) Code: e5942038 e2843034 e5941034 e3a0 (e5812004) ---[ end trace c5149f92effb19a4 ]--- Revert the commit for now. clocksource_mmio_init can be made to pass back a pointer, but the code churn and usage of an inner struct might not be worth it. Reported-by: Maxime Ripard Fixes: 157dfadef832 ("clocksource/drivers/timer_sun5i: Replace code by clocksource_mmio_init") Signed-off-by: Chen-Yu Tsai --- drivers/clocksource/timer-sun5i.c | 16 ++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c index c184eb84101e..4f87f3e76d83 100644 --- a/drivers/clocksource/timer-sun5i.c +++ b/drivers/clocksource/timer-sun5i.c @@ -152,6 +152,13 @@ static irqreturn_t
[PATCH] clk: sunxi-ng: sun6i-a31: Force AHB1 clock to use PLL6 as parent
On the A31, the DMA engine only works if AHB1 is clocked from PLL6. In addition, the hstimer is clocked from AHB1, and if AHB1 is clocked from the CPU clock, and cpufreq is working, we get an unstable timer. Force the AHB1 clock to use PLL6 as its parent. Previously this was done in the device tree with the assigned-clocks and assigned-clocks-parent bindings. However with this new monolithic driver, the system critical clocks aren't exported through the device tree. The alternative is to force this setting in the driver before the clocks are registered. This is also done in newer versions of mainline U-boot. But people still using an older version, or even the vendor version, can still hit this issue. Hence the need to do it in the kernel as well. Reported-by: Hans de GoedeReported-by: Maxime Ripard Fixes: c6e6c96d8fa6 ("clk: sunxi-ng: Add A31/A31s clocks") Signed-off-by: Chen-Yu Tsai --- Hi, This fix is for 4.9. This should fix issues with hstimer and DMA when booting with an old bootloader. ChenYu --- drivers/clk/sunxi-ng/ccu-sun6i-a31.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c index 79596463e0d9..4a82a49cff5e 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c @@ -191,6 +191,8 @@ static struct clk_div_table axi_div_table[] = { static SUNXI_CCU_DIV_TABLE(axi_clk, "axi", "cpu", 0x050, 0, 3, axi_div_table, 0); +#define SUN6I_A31_AHB1_REG 0x054 + static const char * const ahb1_parents[] = { "osc32k", "osc24M", "axi", "pll-periph" }; @@ -1230,6 +1232,16 @@ static void __init sun6i_a31_ccu_setup(struct device_node *node) val &= BIT(16); writel(val, reg + SUN6I_A31_PLL_MIPI_REG); + /* Force AHB1 to PLL6 / 3 */ + val = readl(reg + SUN6I_A31_AHB1_REG); + /* set PLL6 pre-div = 3 */ + val &= ~GENMASK(7, 6); + val |= 0x2 << 6; + /* select PLL6 / pre-div */ + val &= ~GENMASK(13, 12); + val |= 0x3 << 12; + writel(val, reg + SUN6I_A31_AHB1_REG); + sunxi_ccu_probe(node, reg, _a31_ccu_desc); ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, -- 2.9.3
[PATCH] clk: sunxi-ng: sun6i-a31: Force AHB1 clock to use PLL6 as parent
On the A31, the DMA engine only works if AHB1 is clocked from PLL6. In addition, the hstimer is clocked from AHB1, and if AHB1 is clocked from the CPU clock, and cpufreq is working, we get an unstable timer. Force the AHB1 clock to use PLL6 as its parent. Previously this was done in the device tree with the assigned-clocks and assigned-clocks-parent bindings. However with this new monolithic driver, the system critical clocks aren't exported through the device tree. The alternative is to force this setting in the driver before the clocks are registered. This is also done in newer versions of mainline U-boot. But people still using an older version, or even the vendor version, can still hit this issue. Hence the need to do it in the kernel as well. Reported-by: Hans de Goede Reported-by: Maxime Ripard Fixes: c6e6c96d8fa6 ("clk: sunxi-ng: Add A31/A31s clocks") Signed-off-by: Chen-Yu Tsai --- Hi, This fix is for 4.9. This should fix issues with hstimer and DMA when booting with an old bootloader. ChenYu --- drivers/clk/sunxi-ng/ccu-sun6i-a31.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c index 79596463e0d9..4a82a49cff5e 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c @@ -191,6 +191,8 @@ static struct clk_div_table axi_div_table[] = { static SUNXI_CCU_DIV_TABLE(axi_clk, "axi", "cpu", 0x050, 0, 3, axi_div_table, 0); +#define SUN6I_A31_AHB1_REG 0x054 + static const char * const ahb1_parents[] = { "osc32k", "osc24M", "axi", "pll-periph" }; @@ -1230,6 +1232,16 @@ static void __init sun6i_a31_ccu_setup(struct device_node *node) val &= BIT(16); writel(val, reg + SUN6I_A31_PLL_MIPI_REG); + /* Force AHB1 to PLL6 / 3 */ + val = readl(reg + SUN6I_A31_AHB1_REG); + /* set PLL6 pre-div = 3 */ + val &= ~GENMASK(7, 6); + val |= 0x2 << 6; + /* select PLL6 / pre-div */ + val &= ~GENMASK(13, 12); + val |= 0x3 << 12; + writel(val, reg + SUN6I_A31_AHB1_REG); + sunxi_ccu_probe(node, reg, _a31_ccu_desc); ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, -- 2.9.3
Re: [PATCH v5 02/23] of: device: Export of_device_{get_modalias, uvent_modalias} to modules
On Tue, Oct 18, 2016 at 9:56 AM, Stephen Boydwrote: > The ULPI bus can be built as a module, and it will soon be > calling these functions when it supports probing devices from DT. > Export them so they can be used by the ULPI module. > > Acked-by: Rob Herring > Cc: > Signed-off-by: Stephen Boyd I'm interested in this as well. The sunxi-rsb bus is non-enumerable and DT only, and existing slave device drivers can be built as modules. We'd need this to support modalias loading of drivers. ChenYu
Re: [PATCH v5 02/23] of: device: Export of_device_{get_modalias, uvent_modalias} to modules
On Tue, Oct 18, 2016 at 9:56 AM, Stephen Boyd wrote: > The ULPI bus can be built as a module, and it will soon be > calling these functions when it supports probing devices from DT. > Export them so they can be used by the ULPI module. > > Acked-by: Rob Herring > Cc: > Signed-off-by: Stephen Boyd I'm interested in this as well. The sunxi-rsb bus is non-enumerable and DT only, and existing slave device drivers can be built as modules. We'd need this to support modalias loading of drivers. ChenYu
Re: [PATCH 02/28] [v2] mtd: mtk: avoid warning in mtk_ecc_encode
On Tue, 18 Oct 2016 00:05:31 +0200 Arnd Bergmannwrote: > When building with -Wmaybe-uninitialized, gcc produces a silly false positive > warning for the mtk_ecc_encode function: > > drivers/mtd/nand/mtk_ecc.c: In function 'mtk_ecc_encode': > drivers/mtd/nand/mtk_ecc.c:402:15: error: 'val' may be used uninitialized in > this function [-Werror=maybe-uninitialized] > > The function for some reason contains a double byte swap on big-endian > builds to get the OOB data into the correct order again, and is written > in a slightly confusing way. > > Using a simple memcpy32_fromio() to read the data simplifies it a lot > so it becomes more readable and produces no warning. However, the > output might not have 32-bit alignment, so we have to use another > memcpy to avoid taking alignment faults or writing beyond the end > of the array. > > Signed-off-by: Arnd Bergmann Jorge, RogerCC, can I have an Acked-by and/or Tested-by for this patch? > --- > v2: move temporary buffer into struct mtk_ecc instead of having it > on the stack, as suggested by Boris Brezillon > --- > drivers/mtd/nand/mtk_ecc.c | 19 +-- > 1 file changed, 9 insertions(+), 10 deletions(-) > > diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/mtk_ecc.c > index d54f666..dbf2562 100644 > --- a/drivers/mtd/nand/mtk_ecc.c > +++ b/drivers/mtd/nand/mtk_ecc.c > @@ -86,6 +86,8 @@ struct mtk_ecc { > struct completion done; > struct mutex lock; > u32 sectors; > + > + u8 eccdata[112]; > }; > > static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, > @@ -366,9 +368,8 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct > mtk_ecc_config *config, > u8 *data, u32 bytes) > { > dma_addr_t addr; > - u8 *p; > - u32 len, i, val; > - int ret = 0; > + u32 len; > + int ret; > > addr = dma_map_single(ecc->dev, data, bytes, DMA_TO_DEVICE); > ret = dma_mapping_error(ecc->dev, addr); > @@ -393,14 +394,12 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct > mtk_ecc_config *config, > > /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ > len = (config->strength * ECC_PARITY_BITS + 7) >> 3; > - p = data + bytes; > > - /* write the parity bytes generated by the ECC back to the OOB region */ > - for (i = 0; i < len; i++) { > - if ((i % 4) == 0) > - val = readl(ecc->regs + ECC_ENCPAR(i / 4)); > - p[i] = (val >> ((i % 4) * 8)) & 0xff; > - } > + /* write the parity bytes generated by the ECC back to temp buffer */ > + __ioread32_copy(ecc->eccdata, ecc->regs + ECC_ENCPAR(0), round_up(len, > 4)); > + > + /* copy into possibly unaligned OOB region with actual length */ > + memcpy(data + bytes, ecc->eccdata, len); > timeout: > > dma_unmap_single(ecc->dev, addr, bytes, DMA_TO_DEVICE);
Re: [PATCH 02/28] [v2] mtd: mtk: avoid warning in mtk_ecc_encode
On Tue, 18 Oct 2016 00:05:31 +0200 Arnd Bergmann wrote: > When building with -Wmaybe-uninitialized, gcc produces a silly false positive > warning for the mtk_ecc_encode function: > > drivers/mtd/nand/mtk_ecc.c: In function 'mtk_ecc_encode': > drivers/mtd/nand/mtk_ecc.c:402:15: error: 'val' may be used uninitialized in > this function [-Werror=maybe-uninitialized] > > The function for some reason contains a double byte swap on big-endian > builds to get the OOB data into the correct order again, and is written > in a slightly confusing way. > > Using a simple memcpy32_fromio() to read the data simplifies it a lot > so it becomes more readable and produces no warning. However, the > output might not have 32-bit alignment, so we have to use another > memcpy to avoid taking alignment faults or writing beyond the end > of the array. > > Signed-off-by: Arnd Bergmann Jorge, RogerCC, can I have an Acked-by and/or Tested-by for this patch? > --- > v2: move temporary buffer into struct mtk_ecc instead of having it > on the stack, as suggested by Boris Brezillon > --- > drivers/mtd/nand/mtk_ecc.c | 19 +-- > 1 file changed, 9 insertions(+), 10 deletions(-) > > diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/mtk_ecc.c > index d54f666..dbf2562 100644 > --- a/drivers/mtd/nand/mtk_ecc.c > +++ b/drivers/mtd/nand/mtk_ecc.c > @@ -86,6 +86,8 @@ struct mtk_ecc { > struct completion done; > struct mutex lock; > u32 sectors; > + > + u8 eccdata[112]; > }; > > static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, > @@ -366,9 +368,8 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct > mtk_ecc_config *config, > u8 *data, u32 bytes) > { > dma_addr_t addr; > - u8 *p; > - u32 len, i, val; > - int ret = 0; > + u32 len; > + int ret; > > addr = dma_map_single(ecc->dev, data, bytes, DMA_TO_DEVICE); > ret = dma_mapping_error(ecc->dev, addr); > @@ -393,14 +394,12 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct > mtk_ecc_config *config, > > /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ > len = (config->strength * ECC_PARITY_BITS + 7) >> 3; > - p = data + bytes; > > - /* write the parity bytes generated by the ECC back to the OOB region */ > - for (i = 0; i < len; i++) { > - if ((i % 4) == 0) > - val = readl(ecc->regs + ECC_ENCPAR(i / 4)); > - p[i] = (val >> ((i % 4) * 8)) & 0xff; > - } > + /* write the parity bytes generated by the ECC back to temp buffer */ > + __ioread32_copy(ecc->eccdata, ecc->regs + ECC_ENCPAR(0), round_up(len, > 4)); > + > + /* copy into possibly unaligned OOB region with actual length */ > + memcpy(data + bytes, ecc->eccdata, len); > timeout: > > dma_unmap_single(ecc->dev, addr, bytes, DMA_TO_DEVICE);
Re: [PATCH 10/28] UBI: fix uninitialized access of vid_hdr pointer
Hi Arnd, On Tue, 18 Oct 2016 00:10:13 +0200 Arnd Bergmannwrote: > A rework of UBI that just appeared in linux-next during the merge > window introduced caused the recover_peb to use a variable that > is never initialized as seen from this gcc warning: > > drivers/mtd/ubi/eba.c: In function ‘recover_peb’: > drivers/mtd/ubi/eba.c:744:40: error: ‘vid_hdr’ may be used uninitialized in > this function [-Werror=maybe-uninitialized] > > It seems clear that the change to the function arguments was missing > the initialization that I'm now adding back to restore the > way the function was working before. Thanks for the fix, but Geert already sent a patch for this bug a few days ago. Regards, Boris > > Fixes: 3291b52f9ff0 ("UBI: introduce the VID buffer concept") > Cc: Boris Brezillon > Cc: Richard Weinberger > Signed-off-by: Arnd Bergmann > --- > drivers/mtd/ubi/eba.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c > index 95c4048..2e152be 100644 > --- a/drivers/mtd/ubi/eba.c > +++ b/drivers/mtd/ubi/eba.c > @@ -719,7 +719,7 @@ static int try_recover_peb(struct ubi_volume *vol, int > pnum, int lnum, > struct ubi_vid_io_buf *vidb, bool *retry) > { > struct ubi_device *ubi = vol->ubi; > - struct ubi_vid_hdr *vid_hdr; > + struct ubi_vid_hdr *vid_hdr = ubi_get_vid_hdr(vidb); > int new_pnum, err, vol_id = vol->vol_id, data_size; > uint32_t crc; >
Re: [PATCH 10/28] UBI: fix uninitialized access of vid_hdr pointer
Hi Arnd, On Tue, 18 Oct 2016 00:10:13 +0200 Arnd Bergmann wrote: > A rework of UBI that just appeared in linux-next during the merge > window introduced caused the recover_peb to use a variable that > is never initialized as seen from this gcc warning: > > drivers/mtd/ubi/eba.c: In function ‘recover_peb’: > drivers/mtd/ubi/eba.c:744:40: error: ‘vid_hdr’ may be used uninitialized in > this function [-Werror=maybe-uninitialized] > > It seems clear that the change to the function arguments was missing > the initialization that I'm now adding back to restore the > way the function was working before. Thanks for the fix, but Geert already sent a patch for this bug a few days ago. Regards, Boris > > Fixes: 3291b52f9ff0 ("UBI: introduce the VID buffer concept") > Cc: Boris Brezillon > Cc: Richard Weinberger > Signed-off-by: Arnd Bergmann > --- > drivers/mtd/ubi/eba.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c > index 95c4048..2e152be 100644 > --- a/drivers/mtd/ubi/eba.c > +++ b/drivers/mtd/ubi/eba.c > @@ -719,7 +719,7 @@ static int try_recover_peb(struct ubi_volume *vol, int > pnum, int lnum, > struct ubi_vid_io_buf *vidb, bool *retry) > { > struct ubi_device *ubi = vol->ubi; > - struct ubi_vid_hdr *vid_hdr; > + struct ubi_vid_hdr *vid_hdr = ubi_get_vid_hdr(vidb); > int new_pnum, err, vol_id = vol->vol_id, data_size; > uint32_t crc; >
Re: [PATCH 6/8] IB/hns: Replace counting semaphore event_sem with wait condition
On 18 October 2016 at 01:59, Arnd Bergmannwrote: > On Monday, October 17, 2016 10:01:00 PM CEST Binoy Jayan wrote: >> --- a/drivers/infiniband/hw/hns/hns_roce_cmd.c >> +++ b/drivers/infiniband/hw/hns/hns_roce_cmd.c >> @@ -248,10 +248,14 @@ static int hns_roce_cmd_mbox_wait(struct hns_roce_dev >> *hr_dev, u64 in_param, >> { >> int ret = 0; >> >> - down(_dev->cmd.event_sem); >> + wait_event(hr_dev->cmd.event_sem.wq, >> + atomic_add_unless(_dev->cmd.event_sem.count, -1, 0)); >> + >> ret = __hns_roce_cmd_mbox_wait(hr_dev, in_param, out_param, >>in_modifier, op_modifier, op, >> timeout); >> - up(_dev->cmd.event_sem); >> + >> + if (atomic_inc_return(_dev->cmd.event_sem.count) == 1) >> + wake_up(_dev->cmd.event_sem.wq); >> >> return ret; >> } > > This is the only interesting use of the event_sem that cares about > the counting and it protects the __hns_roce_cmd_mbox_wait() from being > entered too often. The count here is the number of size of the > hr_dev->cmd.context[] array. > > However, that function already use a spinlock to protect that array > and pick the correct context. I think changing the inner function > to handle the case of 'no context available' by using a waitqueue > without counting anything would be a reasonable transformation > away from the semaphore. > > Arnd Hi Arnd, Thank you for replying for the questions. I''ll look for alternatives for patches 6,7 and 8 and resend the series. -Binoy
Re: [PATCH 6/8] IB/hns: Replace counting semaphore event_sem with wait condition
On 18 October 2016 at 01:59, Arnd Bergmann wrote: > On Monday, October 17, 2016 10:01:00 PM CEST Binoy Jayan wrote: >> --- a/drivers/infiniband/hw/hns/hns_roce_cmd.c >> +++ b/drivers/infiniband/hw/hns/hns_roce_cmd.c >> @@ -248,10 +248,14 @@ static int hns_roce_cmd_mbox_wait(struct hns_roce_dev >> *hr_dev, u64 in_param, >> { >> int ret = 0; >> >> - down(_dev->cmd.event_sem); >> + wait_event(hr_dev->cmd.event_sem.wq, >> + atomic_add_unless(_dev->cmd.event_sem.count, -1, 0)); >> + >> ret = __hns_roce_cmd_mbox_wait(hr_dev, in_param, out_param, >>in_modifier, op_modifier, op, >> timeout); >> - up(_dev->cmd.event_sem); >> + >> + if (atomic_inc_return(_dev->cmd.event_sem.count) == 1) >> + wake_up(_dev->cmd.event_sem.wq); >> >> return ret; >> } > > This is the only interesting use of the event_sem that cares about > the counting and it protects the __hns_roce_cmd_mbox_wait() from being > entered too often. The count here is the number of size of the > hr_dev->cmd.context[] array. > > However, that function already use a spinlock to protect that array > and pick the correct context. I think changing the inner function > to handle the case of 'no context available' by using a waitqueue > without counting anything would be a reasonable transformation > away from the semaphore. > > Arnd Hi Arnd, Thank you for replying for the questions. I''ll look for alternatives for patches 6,7 and 8 and resend the series. -Binoy
Re: [PATCH V3 00/11] block-throttle: add .high limit
Not to compound upon this again. However if BFQ isn't suitable to replace CFQ for high I/O workloads (I've yet to see 20k IOPS on any reasonably sized SAN (SC4020 / v5000, etc)), can't we at-least default BFQ to become the default I/O scheduler for people otherwise requesting CFQ? Paolo has had a team of students working on this for years, even if the otherwise "secret weapon" is mainlined I highly doubt his work will stop. We're pretty close to fixing hard I/O stalls in Linux, mainlining being the last major burden. While I've contributed nothing to BFQ code wise, absolutely let any of us know if there's anything outstanding to solve hard lockups and I believe any of us will try our best. Kyle. On Sun, Oct 16, 2016 at 12:02 PM, Paolo Valentewrote: > >> Il giorno 14 ott 2016, alle ore 20:35, Tejun Heo ha >> scritto: >> >> Hello, Paolo. >> >> On Fri, Oct 14, 2016 at 07:13:41PM +0200, Paolo Valente wrote: >>> That said, your 'thus' seems a little too strong: "bfq does not yet >>> handle fast SSDs, thus we need something else". What about the >>> millions of devices (and people) still within 10-20 K IOPS, and >>> experiencing awful latencies and lack of bandwidth guarantees? >> >> I'm not objecting to any of that. > > Ok, sorry for misunderstanding. I'm just more and more confused about > why a readily available, and not proven wrong solution has not yet > been accepted, if everybody apparently acknowledges the problem. > >> My point just is that bfq, at least >> as currently implemented, is unfit for certain classes of use cases. >> > > Absolutely correct. > FWIW, it looks like the only way we can implement proportional control on highspeed ssds with acceptable overhead >>> >>> Maybe not: as I wrote to Viveck in a previous reply, containing >>> pointers to documentation, we have already achieved twenty millions >>> of decisions per second with a prototype driving existing >>> proportional-share packet schedulers (essentially without >>> modifications). >> >> And that doesn't require idling and thus doesn't severely impact >> utilization? >> > > Nope. Packets are commonly assumed to be sent asynchronously. > I guess that discussing the validity of this assumption is out of the > scope of this thread. > > Thanks, > Paolo > is somehow finding a way to calculate the cost of each IO and throttle IOs according to that while controlling for latency as necessary. Slice scheduling with idling seems too expensive with highspeed devices with high io depth. >>> >>> Yes, that's absolutely true. I'm already thinking about an idleless >>> solution. As I already wrote, I'm willing to help with scheduling in >>> blk-mq. I hope there will be the opportunity to find some way to go >>> at KS. >> >> It'd be great to have a proportional control mechanism whose overhead >> is acceptable. Unfortunately, we don't have one now and nothing seems >> right around the corner. (Mostly) work-conserving throttling would be >> fiddlier to use but is something which is useful regardless of such >> proportional control mechanism and can be obtained relatively easily. >> >> I don't see why the two approaches would be mutually exclusive. >> >> Thanks. >> >> -- >> tejun >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-block" in >> the body of a message to majord...@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html > > > -- > Paolo Valente > Algogroup > Dipartimento di Scienze Fisiche, Informatiche e Matematiche > Via Campi 213/B > 41125 Modena - Italy > http://algogroup.unimore.it/people/paolo/ > > > > >
Re: [PATCH 05/28] ext2: avoid bogus -Wmaybe-uninitialized warning
Thanks Arnd, this looks fine to me: Reviewed-by: Christoph Hellwig
Re: [PATCH V3 00/11] block-throttle: add .high limit
Not to compound upon this again. However if BFQ isn't suitable to replace CFQ for high I/O workloads (I've yet to see 20k IOPS on any reasonably sized SAN (SC4020 / v5000, etc)), can't we at-least default BFQ to become the default I/O scheduler for people otherwise requesting CFQ? Paolo has had a team of students working on this for years, even if the otherwise "secret weapon" is mainlined I highly doubt his work will stop. We're pretty close to fixing hard I/O stalls in Linux, mainlining being the last major burden. While I've contributed nothing to BFQ code wise, absolutely let any of us know if there's anything outstanding to solve hard lockups and I believe any of us will try our best. Kyle. On Sun, Oct 16, 2016 at 12:02 PM, Paolo Valente wrote: > >> Il giorno 14 ott 2016, alle ore 20:35, Tejun Heo ha >> scritto: >> >> Hello, Paolo. >> >> On Fri, Oct 14, 2016 at 07:13:41PM +0200, Paolo Valente wrote: >>> That said, your 'thus' seems a little too strong: "bfq does not yet >>> handle fast SSDs, thus we need something else". What about the >>> millions of devices (and people) still within 10-20 K IOPS, and >>> experiencing awful latencies and lack of bandwidth guarantees? >> >> I'm not objecting to any of that. > > Ok, sorry for misunderstanding. I'm just more and more confused about > why a readily available, and not proven wrong solution has not yet > been accepted, if everybody apparently acknowledges the problem. > >> My point just is that bfq, at least >> as currently implemented, is unfit for certain classes of use cases. >> > > Absolutely correct. > FWIW, it looks like the only way we can implement proportional control on highspeed ssds with acceptable overhead >>> >>> Maybe not: as I wrote to Viveck in a previous reply, containing >>> pointers to documentation, we have already achieved twenty millions >>> of decisions per second with a prototype driving existing >>> proportional-share packet schedulers (essentially without >>> modifications). >> >> And that doesn't require idling and thus doesn't severely impact >> utilization? >> > > Nope. Packets are commonly assumed to be sent asynchronously. > I guess that discussing the validity of this assumption is out of the > scope of this thread. > > Thanks, > Paolo > is somehow finding a way to calculate the cost of each IO and throttle IOs according to that while controlling for latency as necessary. Slice scheduling with idling seems too expensive with highspeed devices with high io depth. >>> >>> Yes, that's absolutely true. I'm already thinking about an idleless >>> solution. As I already wrote, I'm willing to help with scheduling in >>> blk-mq. I hope there will be the opportunity to find some way to go >>> at KS. >> >> It'd be great to have a proportional control mechanism whose overhead >> is acceptable. Unfortunately, we don't have one now and nothing seems >> right around the corner. (Mostly) work-conserving throttling would be >> fiddlier to use but is something which is useful regardless of such >> proportional control mechanism and can be obtained relatively easily. >> >> I don't see why the two approaches would be mutually exclusive. >> >> Thanks. >> >> -- >> tejun >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-block" in >> the body of a message to majord...@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html > > > -- > Paolo Valente > Algogroup > Dipartimento di Scienze Fisiche, Informatiche e Matematiche > Via Campi 213/B > 41125 Modena - Italy > http://algogroup.unimore.it/people/paolo/ > > > > >
Re: [PATCH 05/28] ext2: avoid bogus -Wmaybe-uninitialized warning
Thanks Arnd, this looks fine to me: Reviewed-by: Christoph Hellwig
Re: [PATCH 00/28] Reenable maybe-uninitialized warnings
On Tue, Oct 18, 2016 at 12:03:28AM +0200, Arnd Bergmann wrote: > This is a set of patches that I hope to get into v4.9 in some form > in order to turn on the -Wmaybe-uninitialized warnings again. Hi Arnd, I jsut complained to Geert that I was introducing way to many bugs or pointless warnings for some compilers lately, but gcc didn't warn me about them. From a little research the lack of -Wmaybe-uninitialized seems to be the reason for it, so I'm all for re-enabling it.
Re: [PATCH 00/28] Reenable maybe-uninitialized warnings
On Tue, Oct 18, 2016 at 12:03:28AM +0200, Arnd Bergmann wrote: > This is a set of patches that I hope to get into v4.9 in some form > in order to turn on the -Wmaybe-uninitialized warnings again. Hi Arnd, I jsut complained to Geert that I was introducing way to many bugs or pointless warnings for some compilers lately, but gcc didn't warn me about them. From a little research the lack of -Wmaybe-uninitialized seems to be the reason for it, so I'm all for re-enabling it.
[PATCH] Documentation/RCU: Fix minor typo
deference should actually be dereference. Signed-off-by: Pranith Kumar--- Documentation/RCU/whatisRCU.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt index 2044227..5cbd8b2 100644 --- a/Documentation/RCU/whatisRCU.txt +++ b/Documentation/RCU/whatisRCU.txt @@ -237,7 +237,7 @@ rcu_dereference() The reader uses rcu_dereference() to fetch an RCU-protected pointer, which returns a value that may then be safely - dereferenced. Note that rcu_deference() does not actually + dereferenced. Note that rcu_dereference() does not actually dereference the pointer, instead, it protects the pointer for later dereferencing. It also executes any needed memory-barrier instructions for a given CPU architecture. Currently, only Alpha -- 2.10.1
[PATCH] Documentation/RCU: Fix minor typo
deference should actually be dereference. Signed-off-by: Pranith Kumar --- Documentation/RCU/whatisRCU.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt index 2044227..5cbd8b2 100644 --- a/Documentation/RCU/whatisRCU.txt +++ b/Documentation/RCU/whatisRCU.txt @@ -237,7 +237,7 @@ rcu_dereference() The reader uses rcu_dereference() to fetch an RCU-protected pointer, which returns a value that may then be safely - dereferenced. Note that rcu_deference() does not actually + dereferenced. Note that rcu_dereference() does not actually dereference the pointer, instead, it protects the pointer for later dereferencing. It also executes any needed memory-barrier instructions for a given CPU architecture. Currently, only Alpha -- 2.10.1
Bug in fua code
Ming, I recently discovered a bug in the FUA code - a recent bcachefs change exposed it - and my best guess is it's related to your recent changes to blk-flush.c. What I'm seeing is if all writes are issued as FUA writes, in a short period of time the request queue get stuck - writes are on the queue but they aren't being issued or completed. This is with an AHCI device - so no blk-mq, and it's emulating FUA with flushes. You ought to be able to reproduce this yourself by changing generic_make_request() to make all writes FUA, and then just doing O_DIRECT writes with dd or something. I suspect that if there's non FUA flushes being issued they'll end up kicking the queue and keeping things from getting stuck, in my testing I'm only seeing things get completely stuck when testing bcachefs in multi device mode, with no metadata or journal IO to the device in question, just FUA data writes. After things get stuck, with kgdb I'm seeing a request on the request queue that has flush_data_end_io for its endio function. I've still been trying to figure out how the flush machinery is supposed to work, I don't know what else you'd want to know. Much appreciated if you could take a look.
Bug in fua code
Ming, I recently discovered a bug in the FUA code - a recent bcachefs change exposed it - and my best guess is it's related to your recent changes to blk-flush.c. What I'm seeing is if all writes are issued as FUA writes, in a short period of time the request queue get stuck - writes are on the queue but they aren't being issued or completed. This is with an AHCI device - so no blk-mq, and it's emulating FUA with flushes. You ought to be able to reproduce this yourself by changing generic_make_request() to make all writes FUA, and then just doing O_DIRECT writes with dd or something. I suspect that if there's non FUA flushes being issued they'll end up kicking the queue and keeping things from getting stuck, in my testing I'm only seeing things get completely stuck when testing bcachefs in multi device mode, with no metadata or journal IO to the device in question, just FUA data writes. After things get stuck, with kgdb I'm seeing a request on the request queue that has flush_data_end_io for its endio function. I've still been trying to figure out how the flush machinery is supposed to work, I don't know what else you'd want to know. Much appreciated if you could take a look.
[PATCH 7/7] ufs-qcom: phy/hcd: Refactoring phy clock handling
Add phy clock enable code to phy_power_on/off callbacks, and remove explicit calls to enable these phy clocks from the ufs-qcom hcd driver. Signed-off-by: Vivek GautamReviewed-by: Subhash Jadavani --- drivers/phy/phy-qcom-ufs.c | 12 +++- drivers/scsi/ufs/ufs-qcom.c | 15 --- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 3a87e88..687b9b7 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -681,11 +681,18 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy) goto out_disable_phy; } + err = ufs_qcom_phy_enable_iface_clk(generic_phy); + if (err) { + dev_err(dev, "%s enable phy iface clock failed, err=%d\n", + __func__, err); + goto out_disable_pll; + } + err = ufs_qcom_phy_enable_ref_clk(generic_phy); if (err) { dev_err(dev, "%s enable phy ref clock failed, err=%d\n", __func__, err); - goto out_disable_pll; + goto out_disable_iface_clk; } /* enable device PHY ref_clk pad rail */ @@ -704,6 +711,8 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy) out_disable_ref_clk: ufs_qcom_phy_disable_ref_clk(generic_phy); +out_disable_iface_clk: + ufs_qcom_phy_disable_iface_clk(generic_phy); out_disable_pll: ufs_qcom_phy_disable_vreg(dev, _common->vdda_pll); out_disable_phy: @@ -723,6 +732,7 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy) ufs_qcom_phy_disable_vreg(phy_common->dev, _common->vddp_ref_clk); ufs_qcom_phy_disable_ref_clk(generic_phy); + ufs_qcom_phy_disable_iface_clk(generic_phy); ufs_qcom_phy_disable_vreg(phy_common->dev, _common->vdda_pll); ufs_qcom_phy_disable_vreg(phy_common->dev, _common->vdda_phy); diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 3aedf73..6e4ce5f 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1112,17 +1112,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) return 0; if (on) { - err = ufs_qcom_phy_enable_iface_clk(host->generic_phy); - if (err) - goto out; - - err = ufs_qcom_phy_enable_ref_clk(host->generic_phy); - if (err) { - dev_err(hba->dev, "%s enable phy ref clock failed, err=%d\n", - __func__, err); - ufs_qcom_phy_disable_iface_clk(host->generic_phy); - goto out; - } /* enable the device ref clock for HS mode*/ if (ufshcd_is_hs_mode(>pwr_info)) ufs_qcom_dev_ref_clk_ctrl(host, true); @@ -1131,9 +1120,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) ufs_qcom_update_bus_bw_vote(host); } else { - - /* M-PHY RMMI interface clocks can be turned off */ - ufs_qcom_phy_disable_iface_clk(host->generic_phy); if (!ufs_qcom_is_link_active(hba)) /* disable device ref_clk */ ufs_qcom_dev_ref_clk_ctrl(host, false); @@ -1146,7 +1132,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) dev_err(hba->dev, "%s: set bus vote failed %d\n", __func__, err); -out: return err; } -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 7/7] ufs-qcom: phy/hcd: Refactoring phy clock handling
Add phy clock enable code to phy_power_on/off callbacks, and remove explicit calls to enable these phy clocks from the ufs-qcom hcd driver. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani --- drivers/phy/phy-qcom-ufs.c | 12 +++- drivers/scsi/ufs/ufs-qcom.c | 15 --- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 3a87e88..687b9b7 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -681,11 +681,18 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy) goto out_disable_phy; } + err = ufs_qcom_phy_enable_iface_clk(generic_phy); + if (err) { + dev_err(dev, "%s enable phy iface clock failed, err=%d\n", + __func__, err); + goto out_disable_pll; + } + err = ufs_qcom_phy_enable_ref_clk(generic_phy); if (err) { dev_err(dev, "%s enable phy ref clock failed, err=%d\n", __func__, err); - goto out_disable_pll; + goto out_disable_iface_clk; } /* enable device PHY ref_clk pad rail */ @@ -704,6 +711,8 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy) out_disable_ref_clk: ufs_qcom_phy_disable_ref_clk(generic_phy); +out_disable_iface_clk: + ufs_qcom_phy_disable_iface_clk(generic_phy); out_disable_pll: ufs_qcom_phy_disable_vreg(dev, _common->vdda_pll); out_disable_phy: @@ -723,6 +732,7 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy) ufs_qcom_phy_disable_vreg(phy_common->dev, _common->vddp_ref_clk); ufs_qcom_phy_disable_ref_clk(generic_phy); + ufs_qcom_phy_disable_iface_clk(generic_phy); ufs_qcom_phy_disable_vreg(phy_common->dev, _common->vdda_pll); ufs_qcom_phy_disable_vreg(phy_common->dev, _common->vdda_phy); diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 3aedf73..6e4ce5f 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1112,17 +1112,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) return 0; if (on) { - err = ufs_qcom_phy_enable_iface_clk(host->generic_phy); - if (err) - goto out; - - err = ufs_qcom_phy_enable_ref_clk(host->generic_phy); - if (err) { - dev_err(hba->dev, "%s enable phy ref clock failed, err=%d\n", - __func__, err); - ufs_qcom_phy_disable_iface_clk(host->generic_phy); - goto out; - } /* enable the device ref clock for HS mode*/ if (ufshcd_is_hs_mode(>pwr_info)) ufs_qcom_dev_ref_clk_ctrl(host, true); @@ -1131,9 +1120,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) ufs_qcom_update_bus_bw_vote(host); } else { - - /* M-PHY RMMI interface clocks can be turned off */ - ufs_qcom_phy_disable_iface_clk(host->generic_phy); if (!ufs_qcom_is_link_active(hba)) /* disable device ref_clk */ ufs_qcom_dev_ref_clk_ctrl(host, false); @@ -1146,7 +1132,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) dev_err(hba->dev, "%s: set bus vote failed %d\n", __func__, err); -out: return err; } -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 6/7] phy: qcom-ufs-qmp-xx: Move clock and regulator init out of phy init
The phy init is meant to do phy initialization rather than just getting the clock and regulator. Move these clock and regulator get to probe(), to make room for actual phy initialization sequence. Signed-off-by: Vivek GautamReviewed-by: Subhash Jadavani --- drivers/phy/phy-qcom-ufs-qmp-14nm.c | 52 ++--- drivers/phy/phy-qcom-ufs-qmp-20nm.c | 46 +++- 2 files changed, 46 insertions(+), 52 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index 55fecbb..a60cf34 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c @@ -44,30 +44,7 @@ void ufs_qcom_phy_qmp_14nm_advertise_quirks(struct ufs_qcom_phy *phy_common) static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy) { - struct ufs_qcom_phy_qmp_14nm *phy = phy_get_drvdata(generic_phy); - struct ufs_qcom_phy *phy_common = >common_cfg; - int err; - - err = ufs_qcom_phy_init_clks(phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", - __func__, err); - goto out; - } - - err = ufs_qcom_phy_init_vregulators(phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", - __func__, err); - goto out; - } - phy_common->vdda_phy.max_uV = UFS_PHY_VDDA_PHY_UV; - phy_common->vdda_phy.min_uV = UFS_PHY_VDDA_PHY_UV; - - ufs_qcom_phy_qmp_14nm_advertise_quirks(phy_common); - -out: - return err; + return 0; } static @@ -136,6 +113,7 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev) struct device *dev = >dev; struct phy *generic_phy; struct ufs_qcom_phy_qmp_14nm *phy; + struct ufs_qcom_phy *phy_common; int err = 0; phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); @@ -143,8 +121,9 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev) err = -ENOMEM; goto out; } + phy_common = >common_cfg; - generic_phy = ufs_qcom_phy_generic_probe(pdev, >common_cfg, + generic_phy = ufs_qcom_phy_generic_probe(pdev, phy_common, _qcom_phy_qmp_14nm_phy_ops, _14nm_ops); if (!generic_phy) { @@ -154,10 +133,29 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev) goto out; } + err = ufs_qcom_phy_init_clks(phy_common); + if (err) { + dev_err(phy_common->dev, + "%s: ufs_qcom_phy_init_clks() failed %d\n", + __func__, err); + goto out; + } + + err = ufs_qcom_phy_init_vregulators(phy_common); + if (err) { + dev_err(phy_common->dev, + "%s: ufs_qcom_phy_init_vregulators() failed %d\n", + __func__, err); + goto out; + } + phy_common->vdda_phy.max_uV = UFS_PHY_VDDA_PHY_UV; + phy_common->vdda_phy.min_uV = UFS_PHY_VDDA_PHY_UV; + + ufs_qcom_phy_qmp_14nm_advertise_quirks(phy_common); + phy_set_drvdata(generic_phy, phy); - strlcpy(phy->common_cfg.name, UFS_PHY_NAME, - sizeof(phy->common_cfg.name)); + strlcpy(phy_common->name, UFS_PHY_NAME, sizeof(phy_common->name)); out: return err; diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c index 9a2f53d..dfc5175 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c @@ -63,28 +63,7 @@ void ufs_qcom_phy_qmp_20nm_advertise_quirks(struct ufs_qcom_phy *phy_common) static int ufs_qcom_phy_qmp_20nm_init(struct phy *generic_phy) { - struct ufs_qcom_phy_qmp_20nm *phy = phy_get_drvdata(generic_phy); - struct ufs_qcom_phy *phy_common = >common_cfg; - int err = 0; - - err = ufs_qcom_phy_init_clks(phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", - __func__, err); - goto out; - } - - err = ufs_qcom_phy_init_vregulators(phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", - __func__, err); - goto out; - } - - ufs_qcom_phy_qmp_20nm_advertise_quirks(phy_common); - -out: - return err; + return 0; } static @@ -192,6 +171,7 @@ static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev) struct device *dev = >dev; struct phy *generic_phy; struct ufs_qcom_phy_qmp_20nm *phy; + struct ufs_qcom_phy *phy_common; int err = 0; phy =
[PATCH 4/7] phy: qcom-ufs-qmp-xx: Discard remove callback for drivers.
remove() callback does a phy_exit() only and nothing else now. The phy_exit() over the generic phy is called from the phy consumer, and phy provider driver should not explicitly need to call any phy_exit(). So discard the remove callback for qcom-ufs phy platform drivers. Signed-off-by: Vivek GautamReviewed-by: Subhash Jadavani --- drivers/phy/phy-qcom-ufs-qmp-14nm.c | 16 drivers/phy/phy-qcom-ufs-qmp-20nm.c | 16 drivers/phy/phy-qcom-ufs.c | 9 - 3 files changed, 41 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index 6ee5149..a305016 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c @@ -163,21 +163,6 @@ out: return err; } -static int ufs_qcom_phy_qmp_14nm_remove(struct platform_device *pdev) -{ - struct device *dev = >dev; - struct phy *generic_phy = to_phy(dev); - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - int err = 0; - - err = ufs_qcom_phy_remove(generic_phy, ufs_qcom_phy); - if (err) - dev_err(dev, "%s: ufs_qcom_phy_remove failed = %d\n", - __func__, err); - - return err; -} - static const struct of_device_id ufs_qcom_phy_qmp_14nm_of_match[] = { {.compatible = "qcom,ufs-phy-qmp-14nm"}, {}, @@ -186,7 +171,6 @@ MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_14nm_of_match); static struct platform_driver ufs_qcom_phy_qmp_14nm_driver = { .probe = ufs_qcom_phy_qmp_14nm_probe, - .remove = ufs_qcom_phy_qmp_14nm_remove, .driver = { .of_match_table = ufs_qcom_phy_qmp_14nm_of_match, .name = "ufs_qcom_phy_qmp_14nm", diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c index 770087a..2db1fbb 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c @@ -219,21 +219,6 @@ out: return err; } -static int ufs_qcom_phy_qmp_20nm_remove(struct platform_device *pdev) -{ - struct device *dev = >dev; - struct phy *generic_phy = to_phy(dev); - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - int err = 0; - - err = ufs_qcom_phy_remove(generic_phy, ufs_qcom_phy); - if (err) - dev_err(dev, "%s: ufs_qcom_phy_remove failed = %d\n", - __func__, err); - - return err; -} - static const struct of_device_id ufs_qcom_phy_qmp_20nm_of_match[] = { {.compatible = "qcom,ufs-phy-qmp-20nm"}, {}, @@ -242,7 +227,6 @@ MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_20nm_of_match); static struct platform_driver ufs_qcom_phy_qmp_20nm_driver = { .probe = ufs_qcom_phy_qmp_20nm_probe, - .remove = ufs_qcom_phy_qmp_20nm_remove, .driver = { .of_match_table = ufs_qcom_phy_qmp_20nm_of_match, .name = "ufs_qcom_phy_qmp_20nm", diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index f639a7c..b8f9286 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -645,15 +645,6 @@ int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B) } EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy); -int ufs_qcom_phy_remove(struct phy *generic_phy, - struct ufs_qcom_phy *ufs_qcom_phy) -{ - phy_power_off(generic_phy); - - return 0; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_remove); - int ufs_qcom_phy_exit(struct phy *generic_phy) { struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 6/7] phy: qcom-ufs-qmp-xx: Move clock and regulator init out of phy init
The phy init is meant to do phy initialization rather than just getting the clock and regulator. Move these clock and regulator get to probe(), to make room for actual phy initialization sequence. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani --- drivers/phy/phy-qcom-ufs-qmp-14nm.c | 52 ++--- drivers/phy/phy-qcom-ufs-qmp-20nm.c | 46 +++- 2 files changed, 46 insertions(+), 52 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index 55fecbb..a60cf34 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c @@ -44,30 +44,7 @@ void ufs_qcom_phy_qmp_14nm_advertise_quirks(struct ufs_qcom_phy *phy_common) static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy) { - struct ufs_qcom_phy_qmp_14nm *phy = phy_get_drvdata(generic_phy); - struct ufs_qcom_phy *phy_common = >common_cfg; - int err; - - err = ufs_qcom_phy_init_clks(phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", - __func__, err); - goto out; - } - - err = ufs_qcom_phy_init_vregulators(phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", - __func__, err); - goto out; - } - phy_common->vdda_phy.max_uV = UFS_PHY_VDDA_PHY_UV; - phy_common->vdda_phy.min_uV = UFS_PHY_VDDA_PHY_UV; - - ufs_qcom_phy_qmp_14nm_advertise_quirks(phy_common); - -out: - return err; + return 0; } static @@ -136,6 +113,7 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev) struct device *dev = >dev; struct phy *generic_phy; struct ufs_qcom_phy_qmp_14nm *phy; + struct ufs_qcom_phy *phy_common; int err = 0; phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); @@ -143,8 +121,9 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev) err = -ENOMEM; goto out; } + phy_common = >common_cfg; - generic_phy = ufs_qcom_phy_generic_probe(pdev, >common_cfg, + generic_phy = ufs_qcom_phy_generic_probe(pdev, phy_common, _qcom_phy_qmp_14nm_phy_ops, _14nm_ops); if (!generic_phy) { @@ -154,10 +133,29 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev) goto out; } + err = ufs_qcom_phy_init_clks(phy_common); + if (err) { + dev_err(phy_common->dev, + "%s: ufs_qcom_phy_init_clks() failed %d\n", + __func__, err); + goto out; + } + + err = ufs_qcom_phy_init_vregulators(phy_common); + if (err) { + dev_err(phy_common->dev, + "%s: ufs_qcom_phy_init_vregulators() failed %d\n", + __func__, err); + goto out; + } + phy_common->vdda_phy.max_uV = UFS_PHY_VDDA_PHY_UV; + phy_common->vdda_phy.min_uV = UFS_PHY_VDDA_PHY_UV; + + ufs_qcom_phy_qmp_14nm_advertise_quirks(phy_common); + phy_set_drvdata(generic_phy, phy); - strlcpy(phy->common_cfg.name, UFS_PHY_NAME, - sizeof(phy->common_cfg.name)); + strlcpy(phy_common->name, UFS_PHY_NAME, sizeof(phy_common->name)); out: return err; diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c index 9a2f53d..dfc5175 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c @@ -63,28 +63,7 @@ void ufs_qcom_phy_qmp_20nm_advertise_quirks(struct ufs_qcom_phy *phy_common) static int ufs_qcom_phy_qmp_20nm_init(struct phy *generic_phy) { - struct ufs_qcom_phy_qmp_20nm *phy = phy_get_drvdata(generic_phy); - struct ufs_qcom_phy *phy_common = >common_cfg; - int err = 0; - - err = ufs_qcom_phy_init_clks(phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", - __func__, err); - goto out; - } - - err = ufs_qcom_phy_init_vregulators(phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", - __func__, err); - goto out; - } - - ufs_qcom_phy_qmp_20nm_advertise_quirks(phy_common); - -out: - return err; + return 0; } static @@ -192,6 +171,7 @@ static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev) struct device *dev = >dev; struct phy *generic_phy; struct ufs_qcom_phy_qmp_20nm *phy; + struct ufs_qcom_phy *phy_common; int err = 0; phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); @@ -199,8
[PATCH 4/7] phy: qcom-ufs-qmp-xx: Discard remove callback for drivers.
remove() callback does a phy_exit() only and nothing else now. The phy_exit() over the generic phy is called from the phy consumer, and phy provider driver should not explicitly need to call any phy_exit(). So discard the remove callback for qcom-ufs phy platform drivers. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani --- drivers/phy/phy-qcom-ufs-qmp-14nm.c | 16 drivers/phy/phy-qcom-ufs-qmp-20nm.c | 16 drivers/phy/phy-qcom-ufs.c | 9 - 3 files changed, 41 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index 6ee5149..a305016 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c @@ -163,21 +163,6 @@ out: return err; } -static int ufs_qcom_phy_qmp_14nm_remove(struct platform_device *pdev) -{ - struct device *dev = >dev; - struct phy *generic_phy = to_phy(dev); - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - int err = 0; - - err = ufs_qcom_phy_remove(generic_phy, ufs_qcom_phy); - if (err) - dev_err(dev, "%s: ufs_qcom_phy_remove failed = %d\n", - __func__, err); - - return err; -} - static const struct of_device_id ufs_qcom_phy_qmp_14nm_of_match[] = { {.compatible = "qcom,ufs-phy-qmp-14nm"}, {}, @@ -186,7 +171,6 @@ MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_14nm_of_match); static struct platform_driver ufs_qcom_phy_qmp_14nm_driver = { .probe = ufs_qcom_phy_qmp_14nm_probe, - .remove = ufs_qcom_phy_qmp_14nm_remove, .driver = { .of_match_table = ufs_qcom_phy_qmp_14nm_of_match, .name = "ufs_qcom_phy_qmp_14nm", diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c index 770087a..2db1fbb 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c @@ -219,21 +219,6 @@ out: return err; } -static int ufs_qcom_phy_qmp_20nm_remove(struct platform_device *pdev) -{ - struct device *dev = >dev; - struct phy *generic_phy = to_phy(dev); - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - int err = 0; - - err = ufs_qcom_phy_remove(generic_phy, ufs_qcom_phy); - if (err) - dev_err(dev, "%s: ufs_qcom_phy_remove failed = %d\n", - __func__, err); - - return err; -} - static const struct of_device_id ufs_qcom_phy_qmp_20nm_of_match[] = { {.compatible = "qcom,ufs-phy-qmp-20nm"}, {}, @@ -242,7 +227,6 @@ MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_20nm_of_match); static struct platform_driver ufs_qcom_phy_qmp_20nm_driver = { .probe = ufs_qcom_phy_qmp_20nm_probe, - .remove = ufs_qcom_phy_qmp_20nm_remove, .driver = { .of_match_table = ufs_qcom_phy_qmp_20nm_of_match, .name = "ufs_qcom_phy_qmp_20nm", diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index f639a7c..b8f9286 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -645,15 +645,6 @@ int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B) } EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy); -int ufs_qcom_phy_remove(struct phy *generic_phy, - struct ufs_qcom_phy *ufs_qcom_phy) -{ - phy_power_off(generic_phy); - - return 0; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_remove); - int ufs_qcom_phy_exit(struct phy *generic_phy) { struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 5/7] phy: qcom-ufs: Cleanup clock and regulator initialization
Different methods pass around generic phy pointer to extract device pointer. Instead, pass the device pointer directly between function calls. Signed-off-by: Vivek GautamReviewed-by: Subhash Jadavani --- drivers/phy/phy-qcom-ufs-i.h| 6 +-- drivers/phy/phy-qcom-ufs-qmp-14nm.c | 4 +- drivers/phy/phy-qcom-ufs-qmp-20nm.c | 4 +- drivers/phy/phy-qcom-ufs.c | 79 - 4 files changed, 39 insertions(+), 54 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h index 2bd5ce4..69e836d 100644 --- a/drivers/phy/phy-qcom-ufs-i.h +++ b/drivers/phy/phy-qcom-ufs-i.h @@ -142,10 +142,8 @@ struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy); int ufs_qcom_phy_power_on(struct phy *generic_phy); int ufs_qcom_phy_power_off(struct phy *generic_phy); int ufs_qcom_phy_exit(struct phy *generic_phy); -int ufs_qcom_phy_init_clks(struct phy *generic_phy, - struct ufs_qcom_phy *phy_common); -int ufs_qcom_phy_init_vregulators(struct phy *generic_phy, - struct ufs_qcom_phy *phy_common); +int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common); +int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common); int ufs_qcom_phy_remove(struct phy *generic_phy, struct ufs_qcom_phy *ufs_qcom_phy); struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index a305016..55fecbb 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c @@ -48,14 +48,14 @@ static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy) struct ufs_qcom_phy *phy_common = >common_cfg; int err; - err = ufs_qcom_phy_init_clks(generic_phy, phy_common); + err = ufs_qcom_phy_init_clks(phy_common); if (err) { dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", __func__, err); goto out; } - err = ufs_qcom_phy_init_vregulators(generic_phy, phy_common); + err = ufs_qcom_phy_init_vregulators(phy_common); if (err) { dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", __func__, err); diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c index 2db1fbb..9a2f53d 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c @@ -67,14 +67,14 @@ static int ufs_qcom_phy_qmp_20nm_init(struct phy *generic_phy) struct ufs_qcom_phy *phy_common = >common_cfg; int err = 0; - err = ufs_qcom_phy_init_clks(generic_phy, phy_common); + err = ufs_qcom_phy_init_clks(phy_common); if (err) { dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", __func__, err); goto out; } - err = ufs_qcom_phy_init_vregulators(generic_phy, phy_common); + err = ufs_qcom_phy_init_vregulators(phy_common); if (err) { dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", __func__, err); diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index b8f9286..3a87e88 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -22,9 +22,9 @@ #define VDDP_REF_CLK_MIN_UV120 #define VDDP_REF_CLK_MAX_UV120 -static int __ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *, +static int __ufs_qcom_phy_init_vreg(struct device *, struct ufs_qcom_phy_vreg *, const char *, bool); -static int ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *, +static int ufs_qcom_phy_init_vreg(struct device *, struct ufs_qcom_phy_vreg *, const char *); static int ufs_qcom_phy_base_init(struct platform_device *pdev, struct ufs_qcom_phy *phy_common); @@ -154,13 +154,11 @@ int ufs_qcom_phy_base_init(struct platform_device *pdev, return 0; } -static int __ufs_qcom_phy_clk_get(struct phy *phy, +static int __ufs_qcom_phy_clk_get(struct device *dev, const char *name, struct clk **clk_out, bool err_print) { struct clk *clk; int err = 0; - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); - struct device *dev = ufs_qcom_phy->dev; clk = devm_clk_get(dev, name); if (IS_ERR(clk)) { @@ -175,40 +173,38 @@ static int __ufs_qcom_phy_clk_get(struct phy *phy, } static -int ufs_qcom_phy_clk_get(struct phy *phy, +int ufs_qcom_phy_clk_get(struct device *dev, const char *name, struct clk **clk_out) { - return __ufs_qcom_phy_clk_get(phy,
[PATCH 2/7] phy: qcom-ufs: Remove unnecessary BUG_ON
BUG_ON() are not preferred in the driver, plus the variable on which BUG_ON is asserted is already checked in the code before passing. Signed-off-by: Vivek GautamReviewed-by: Subhash Jadavani --- drivers/phy/phy-qcom-ufs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 183ec04..805c91d 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -335,8 +335,6 @@ int ufs_qcom_phy_cfg_vreg(struct phy *phy, struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); struct device *dev = ufs_qcom_phy->dev; - BUG_ON(!vreg); - if (regulator_count_voltages(reg) > 0) { min_uV = on ? vreg->min_uV : 0; ret = regulator_set_voltage(reg, min_uV, vreg->max_uV); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 3/7] phy: qcom-ufs: Use devm sibling of kstrdup for regulator names
This helps us in avoiding any requirement for kfree() operation to be called exclusively over the allocated string pointer. Signed-off-by: Vivek GautamReviewed-by: Subhash Jadavani --- drivers/phy/phy-qcom-ufs.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 805c91d..f639a7c 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -262,7 +262,7 @@ static int __ufs_qcom_phy_init_vreg(struct phy *phy, char prop_name[MAX_PROP_NAME]; - vreg->name = kstrdup(name, GFP_KERNEL); + vreg->name = devm_kstrdup(dev, name, GFP_KERNEL); if (!vreg->name) { err = -ENOMEM; goto out; @@ -650,9 +650,6 @@ int ufs_qcom_phy_remove(struct phy *generic_phy, { phy_power_off(generic_phy); - kfree(ufs_qcom_phy->vdda_pll.name); - kfree(ufs_qcom_phy->vdda_phy.name); - return 0; } EXPORT_SYMBOL_GPL(ufs_qcom_phy_remove); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 2/7] phy: qcom-ufs: Remove unnecessary BUG_ON
BUG_ON() are not preferred in the driver, plus the variable on which BUG_ON is asserted is already checked in the code before passing. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani --- drivers/phy/phy-qcom-ufs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 183ec04..805c91d 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -335,8 +335,6 @@ int ufs_qcom_phy_cfg_vreg(struct phy *phy, struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); struct device *dev = ufs_qcom_phy->dev; - BUG_ON(!vreg); - if (regulator_count_voltages(reg) > 0) { min_uV = on ? vreg->min_uV : 0; ret = regulator_set_voltage(reg, min_uV, vreg->max_uV); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 3/7] phy: qcom-ufs: Use devm sibling of kstrdup for regulator names
This helps us in avoiding any requirement for kfree() operation to be called exclusively over the allocated string pointer. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani --- drivers/phy/phy-qcom-ufs.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 805c91d..f639a7c 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -262,7 +262,7 @@ static int __ufs_qcom_phy_init_vreg(struct phy *phy, char prop_name[MAX_PROP_NAME]; - vreg->name = kstrdup(name, GFP_KERNEL); + vreg->name = devm_kstrdup(dev, name, GFP_KERNEL); if (!vreg->name) { err = -ENOMEM; goto out; @@ -650,9 +650,6 @@ int ufs_qcom_phy_remove(struct phy *generic_phy, { phy_power_off(generic_phy); - kfree(ufs_qcom_phy->vdda_pll.name); - kfree(ufs_qcom_phy->vdda_phy.name); - return 0; } EXPORT_SYMBOL_GPL(ufs_qcom_phy_remove); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 5/7] phy: qcom-ufs: Cleanup clock and regulator initialization
Different methods pass around generic phy pointer to extract device pointer. Instead, pass the device pointer directly between function calls. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani --- drivers/phy/phy-qcom-ufs-i.h| 6 +-- drivers/phy/phy-qcom-ufs-qmp-14nm.c | 4 +- drivers/phy/phy-qcom-ufs-qmp-20nm.c | 4 +- drivers/phy/phy-qcom-ufs.c | 79 - 4 files changed, 39 insertions(+), 54 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h index 2bd5ce4..69e836d 100644 --- a/drivers/phy/phy-qcom-ufs-i.h +++ b/drivers/phy/phy-qcom-ufs-i.h @@ -142,10 +142,8 @@ struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy); int ufs_qcom_phy_power_on(struct phy *generic_phy); int ufs_qcom_phy_power_off(struct phy *generic_phy); int ufs_qcom_phy_exit(struct phy *generic_phy); -int ufs_qcom_phy_init_clks(struct phy *generic_phy, - struct ufs_qcom_phy *phy_common); -int ufs_qcom_phy_init_vregulators(struct phy *generic_phy, - struct ufs_qcom_phy *phy_common); +int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common); +int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common); int ufs_qcom_phy_remove(struct phy *generic_phy, struct ufs_qcom_phy *ufs_qcom_phy); struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index a305016..55fecbb 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c @@ -48,14 +48,14 @@ static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy) struct ufs_qcom_phy *phy_common = >common_cfg; int err; - err = ufs_qcom_phy_init_clks(generic_phy, phy_common); + err = ufs_qcom_phy_init_clks(phy_common); if (err) { dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", __func__, err); goto out; } - err = ufs_qcom_phy_init_vregulators(generic_phy, phy_common); + err = ufs_qcom_phy_init_vregulators(phy_common); if (err) { dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", __func__, err); diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c index 2db1fbb..9a2f53d 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c @@ -67,14 +67,14 @@ static int ufs_qcom_phy_qmp_20nm_init(struct phy *generic_phy) struct ufs_qcom_phy *phy_common = >common_cfg; int err = 0; - err = ufs_qcom_phy_init_clks(generic_phy, phy_common); + err = ufs_qcom_phy_init_clks(phy_common); if (err) { dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", __func__, err); goto out; } - err = ufs_qcom_phy_init_vregulators(generic_phy, phy_common); + err = ufs_qcom_phy_init_vregulators(phy_common); if (err) { dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", __func__, err); diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index b8f9286..3a87e88 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -22,9 +22,9 @@ #define VDDP_REF_CLK_MIN_UV120 #define VDDP_REF_CLK_MAX_UV120 -static int __ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *, +static int __ufs_qcom_phy_init_vreg(struct device *, struct ufs_qcom_phy_vreg *, const char *, bool); -static int ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *, +static int ufs_qcom_phy_init_vreg(struct device *, struct ufs_qcom_phy_vreg *, const char *); static int ufs_qcom_phy_base_init(struct platform_device *pdev, struct ufs_qcom_phy *phy_common); @@ -154,13 +154,11 @@ int ufs_qcom_phy_base_init(struct platform_device *pdev, return 0; } -static int __ufs_qcom_phy_clk_get(struct phy *phy, +static int __ufs_qcom_phy_clk_get(struct device *dev, const char *name, struct clk **clk_out, bool err_print) { struct clk *clk; int err = 0; - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); - struct device *dev = ufs_qcom_phy->dev; clk = devm_clk_get(dev, name); if (IS_ERR(clk)) { @@ -175,40 +173,38 @@ static int __ufs_qcom_phy_clk_get(struct phy *phy, } static -int ufs_qcom_phy_clk_get(struct phy *phy, +int ufs_qcom_phy_clk_get(struct device *dev, const char *name, struct clk **clk_out) { - return __ufs_qcom_phy_clk_get(phy, name, clk_out, true); + return
[PATCH 1/7] phy: qcom-ufs: remove failure when rx/tx_iface_clk are absent
From: Yaniv GardiSince in future UFS Phy's the tx_iface_clk and rx_iface_clk are no longer exist, we should not fail when their initialization fail, but rather just report with debug message. Signed-off-by: Yaniv Gardi Signed-off-by: Vivek Gautam --- drivers/phy/phy-qcom-ufs.c | 15 +-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 107cb57..183ec04 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -186,16 +186,27 @@ ufs_qcom_phy_init_clks(struct phy *generic_phy, struct ufs_qcom_phy *phy_common) { int err; + struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy); err = ufs_qcom_phy_clk_get(generic_phy, "tx_iface_clk", _common->tx_iface_clk); + /* +* tx_iface_clk does not exist in newer version of ufs-phy HW, +* so don't return error if it is not found +*/ if (err) - goto out; + dev_dbg(phy->dev, "%s: failed to get tx_iface_clk\n", + __func__); err = ufs_qcom_phy_clk_get(generic_phy, "rx_iface_clk", _common->rx_iface_clk); + /* +* rx_iface_clk does not exist in newer version of ufs-phy HW, +* so don't return error if it is not found +*/ if (err) - goto out; + dev_dbg(phy->dev, "%s: failed to get rx_iface_clk\n", + __func__); err = ufs_qcom_phy_clk_get(generic_phy, "ref_clk_src", _common->ref_clk_src); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 1/7] phy: qcom-ufs: remove failure when rx/tx_iface_clk are absent
From: Yaniv Gardi Since in future UFS Phy's the tx_iface_clk and rx_iface_clk are no longer exist, we should not fail when their initialization fail, but rather just report with debug message. Signed-off-by: Yaniv Gardi Signed-off-by: Vivek Gautam --- drivers/phy/phy-qcom-ufs.c | 15 +-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 107cb57..183ec04 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -186,16 +186,27 @@ ufs_qcom_phy_init_clks(struct phy *generic_phy, struct ufs_qcom_phy *phy_common) { int err; + struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy); err = ufs_qcom_phy_clk_get(generic_phy, "tx_iface_clk", _common->tx_iface_clk); + /* +* tx_iface_clk does not exist in newer version of ufs-phy HW, +* so don't return error if it is not found +*/ if (err) - goto out; + dev_dbg(phy->dev, "%s: failed to get tx_iface_clk\n", + __func__); err = ufs_qcom_phy_clk_get(generic_phy, "rx_iface_clk", _common->rx_iface_clk); + /* +* rx_iface_clk does not exist in newer version of ufs-phy HW, +* so don't return error if it is not found +*/ if (err) - goto out; + dev_dbg(phy->dev, "%s: failed to get rx_iface_clk\n", + __func__); err = ufs_qcom_phy_clk_get(generic_phy, "ref_clk_src", _common->ref_clk_src); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 0/7] ufs-qcom: phy/hcd: Clean up qcom-ufs phy and ufs-qcom hcd
These patches cleanup the ufs phy driver to an extent. Subsequent patches will target to clean the phy_init() of these qcom-ufs phy drivers in order to get rid of a number of exported APIs that phy drivers expose for ufs-qcom hcd driver to use. These patches are based on linux-phy next branch, and have been tested with on db820c hardware with integration branch - 'integration-linux-qcomlt' of qualcomm linaro lt tree [1]. [1] https://git.linaro.org/landing-teams/working/qualcomm/kernel.git Vivek Gautam (6): phy: qcom-ufs: Remove unnecessary BUG_ON phy: qcom-ufs: Use devm sibling of kstrdup for regulator names phy: qcom-ufs-qmp-xx: Discard remove callback for drivers. phy: qcom-ufs: Cleanup clock and regulator initialization phy: qcom-ufs-qmp-xx: Move clock and regulator init out of phy init ufs-qcom: phy/hcd: Refactoring phy clock handling Yaniv Gardi (1): phy: qcom-ufs: remove failure when rx/tx_iface_clk are absence drivers/phy/phy-qcom-ufs-i.h| 6 +- drivers/phy/phy-qcom-ufs-qmp-14nm.c | 66 drivers/phy/phy-qcom-ufs-qmp-20nm.c | 60 +++ drivers/phy/phy-qcom-ufs.c | 116 +--- drivers/scsi/ufs/ufs-qcom.c | 15 - 5 files changed, 101 insertions(+), 162 deletions(-) -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 0/7] ufs-qcom: phy/hcd: Clean up qcom-ufs phy and ufs-qcom hcd
These patches cleanup the ufs phy driver to an extent. Subsequent patches will target to clean the phy_init() of these qcom-ufs phy drivers in order to get rid of a number of exported APIs that phy drivers expose for ufs-qcom hcd driver to use. These patches are based on linux-phy next branch, and have been tested with on db820c hardware with integration branch - 'integration-linux-qcomlt' of qualcomm linaro lt tree [1]. [1] https://git.linaro.org/landing-teams/working/qualcomm/kernel.git Vivek Gautam (6): phy: qcom-ufs: Remove unnecessary BUG_ON phy: qcom-ufs: Use devm sibling of kstrdup for regulator names phy: qcom-ufs-qmp-xx: Discard remove callback for drivers. phy: qcom-ufs: Cleanup clock and regulator initialization phy: qcom-ufs-qmp-xx: Move clock and regulator init out of phy init ufs-qcom: phy/hcd: Refactoring phy clock handling Yaniv Gardi (1): phy: qcom-ufs: remove failure when rx/tx_iface_clk are absence drivers/phy/phy-qcom-ufs-i.h| 6 +- drivers/phy/phy-qcom-ufs-qmp-14nm.c | 66 drivers/phy/phy-qcom-ufs-qmp-20nm.c | 60 +++ drivers/phy/phy-qcom-ufs.c | 116 +--- drivers/scsi/ufs/ufs-qcom.c | 15 - 5 files changed, 101 insertions(+), 162 deletions(-) -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v2] hwmon: (adm1275) Enable adm1278 VOUT sampling
On Tue, Oct 18, 2016 at 3:50 AM, Guenter Roeckwrote: > On Mon, Oct 17, 2016 at 06:38:53PM +1030, Joel Stanley wrote: >> From: Yi Li >> >> The adm1278 can optionally monitor the VOUT pin. This functioanltiy is >> not enabled at reset, so PMON_CONFIG needs to be modified in order to >> enable it. >> >> Signed-off-by: Yi Li >> Signed-off-by: Joel Stanley > > Applied to -next, after s/functioanltiy/functionality/ Thank you! And thanks for fixing the grammar and spelling. The author is not a native speaker, but I could have done a better job at checking. Cheers, Joel > > Thanks, > Guenter > >> --- >> v2: >> Return an error when unable to enable VOUT monitoring as suggestd by Guenter >> >> drivers/hwmon/pmbus/adm1275.c | 20 >> 1 file changed, 16 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c >> index 3baa4f4a8c5e..9940849351a1 100644 >> --- a/drivers/hwmon/pmbus/adm1275.c >> +++ b/drivers/hwmon/pmbus/adm1275.c >> @@ -499,15 +499,27 @@ static int adm1275_probe(struct i2c_client *client, >> pindex = 2; >> tindex = 3; >> >> - info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT; >> + info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | >> + PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; >> + >> + /* By default when reset VOUT is not enabled */ > > I also rephrased the comment a bit to make it easier to understand. > >> + if (!(config & ADM1278_VOUT_EN)) { >> + config |= ADM1278_VOUT_EN; >> + ret = i2c_smbus_write_byte_data(client, >> + ADM1275_PMON_CONFIG, >> + config); >> + if (ret < 0) { >> + dev_err(>dev, >> + "Failed to enable VOUT monitoring\n"); >> + return -ENODEV; >> + } >> + } >> + >> if (config & ADM1278_TEMP1_EN) >> info->func[0] |= >> PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; >> if (config & ADM1278_VIN_EN) >> info->func[0] |= PMBUS_HAVE_VIN; >> - if (config & ADM1278_VOUT_EN) >> - info->func[0] |= >> - PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; >> break; >> case adm1293: >> case adm1294: >> -- >> 2.9.3 >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in >> the body of a message to majord...@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] hwmon: (adm1275) Enable adm1278 VOUT sampling
On Tue, Oct 18, 2016 at 3:50 AM, Guenter Roeck wrote: > On Mon, Oct 17, 2016 at 06:38:53PM +1030, Joel Stanley wrote: >> From: Yi Li >> >> The adm1278 can optionally monitor the VOUT pin. This functioanltiy is >> not enabled at reset, so PMON_CONFIG needs to be modified in order to >> enable it. >> >> Signed-off-by: Yi Li >> Signed-off-by: Joel Stanley > > Applied to -next, after s/functioanltiy/functionality/ Thank you! And thanks for fixing the grammar and spelling. The author is not a native speaker, but I could have done a better job at checking. Cheers, Joel > > Thanks, > Guenter > >> --- >> v2: >> Return an error when unable to enable VOUT monitoring as suggestd by Guenter >> >> drivers/hwmon/pmbus/adm1275.c | 20 >> 1 file changed, 16 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c >> index 3baa4f4a8c5e..9940849351a1 100644 >> --- a/drivers/hwmon/pmbus/adm1275.c >> +++ b/drivers/hwmon/pmbus/adm1275.c >> @@ -499,15 +499,27 @@ static int adm1275_probe(struct i2c_client *client, >> pindex = 2; >> tindex = 3; >> >> - info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT; >> + info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | >> + PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; >> + >> + /* By default when reset VOUT is not enabled */ > > I also rephrased the comment a bit to make it easier to understand. > >> + if (!(config & ADM1278_VOUT_EN)) { >> + config |= ADM1278_VOUT_EN; >> + ret = i2c_smbus_write_byte_data(client, >> + ADM1275_PMON_CONFIG, >> + config); >> + if (ret < 0) { >> + dev_err(>dev, >> + "Failed to enable VOUT monitoring\n"); >> + return -ENODEV; >> + } >> + } >> + >> if (config & ADM1278_TEMP1_EN) >> info->func[0] |= >> PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; >> if (config & ADM1278_VIN_EN) >> info->func[0] |= PMBUS_HAVE_VIN; >> - if (config & ADM1278_VOUT_EN) >> - info->func[0] |= >> - PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; >> break; >> case adm1293: >> case adm1294: >> -- >> 2.9.3 >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in >> the body of a message to majord...@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 00/32] Create an User's manual and improve development-process book
Hi Jon, Am 18.10.2016 um 00:43 schrieb Jonathan Corbet: > I've only been able to take a quick look at these - I'm buried fairly deep > at the moment. A few superficial thoughts. > > On Mon, 17 Oct 2016 14:55:37 -0200 > Mauro Carvalho Chehab wrote: > >> In my opinion, it would be better to move the converted files to be inside >> a Sphinx build directory, but Jon seems reluctant to that, so, this series >> use symlinks, as it is easy to move the files in the future with a very >> simple >> patch, if we decide to do so. > > So I raised this topic in talks at both Kernel Recipes and LinuxCon > Europe, and nobody threw things at me. sounds good ;-) > I have come to suspect that I'm > worrying a little too much about it; maybe we should go ahead and move > the documents and see who screams. The work could go into docs-next soon, > and there would be an opportunity to fix things up if all hell breaks > loose at the kernel summit. > > Can I make some silly requests? > > - Can we move development-process to something shorter, like just > "process"? We'll be typing it a lot, and tab completion doesn't work in > most email clients :) > > - I think we should leave pointers behind in the form of one-line "this > file has moved" messages. Probably only SubmittingPatches and > CodingStyle need that treatment, I think. > > - The "user manual" is certainly something that has been on my mind as > well. We have documentation for completely separate audiences all mixed > together now, and definitely need to fix that. But rather than "user", > can we paint that shed "admin-guide" or something like that? > One Silly request of mine: Is there a chance moving "./Documentation" to something shorter like "./doc"? Even with "Text completion" (in Emacs [1]), IMO "Documentation" is to long. --Markus-- [1] https://www.emacswiki.org/emacs/CategoryCompletion > Thanks for doing all of this, > > jon > -- > To unsubscribe from this list: send the line "unsubscribe linux-doc" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 00/32] Create an User's manual and improve development-process book
Hi Jon, Am 18.10.2016 um 00:43 schrieb Jonathan Corbet : > I've only been able to take a quick look at these - I'm buried fairly deep > at the moment. A few superficial thoughts. > > On Mon, 17 Oct 2016 14:55:37 -0200 > Mauro Carvalho Chehab wrote: > >> In my opinion, it would be better to move the converted files to be inside >> a Sphinx build directory, but Jon seems reluctant to that, so, this series >> use symlinks, as it is easy to move the files in the future with a very >> simple >> patch, if we decide to do so. > > So I raised this topic in talks at both Kernel Recipes and LinuxCon > Europe, and nobody threw things at me. sounds good ;-) > I have come to suspect that I'm > worrying a little too much about it; maybe we should go ahead and move > the documents and see who screams. The work could go into docs-next soon, > and there would be an opportunity to fix things up if all hell breaks > loose at the kernel summit. > > Can I make some silly requests? > > - Can we move development-process to something shorter, like just > "process"? We'll be typing it a lot, and tab completion doesn't work in > most email clients :) > > - I think we should leave pointers behind in the form of one-line "this > file has moved" messages. Probably only SubmittingPatches and > CodingStyle need that treatment, I think. > > - The "user manual" is certainly something that has been on my mind as > well. We have documentation for completely separate audiences all mixed > together now, and definitely need to fix that. But rather than "user", > can we paint that shed "admin-guide" or something like that? > One Silly request of mine: Is there a chance moving "./Documentation" to something shorter like "./doc"? Even with "Text completion" (in Emacs [1]), IMO "Documentation" is to long. --Markus-- [1] https://www.emacswiki.org/emacs/CategoryCompletion > Thanks for doing all of this, > > jon > -- > To unsubscribe from this list: send the line "unsubscribe linux-doc" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] MAINTAINERS: mmc: Move the mmc tree to kernel.org
On 10/18/2016 01:08 PM, Shawn Lin wrote: > 在 2016/10/18 11:52, Jaehoon Chung 写道: >> On 10/18/2016 12:19 PM, Shawn Lin wrote: >>> Hi Ulf, >>> >>> On 2016/10/17 20:54, Ulf Hansson wrote: Signed-off-by: Ulf Hansson--- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index a009e00..e685724 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8164,7 +8164,7 @@ F:include/linux/mfd/ MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM M:Ulf Hansson L:linux-...@vger.kernel.org -T:git git://git.linaro.org/people/ulf.hansson/mmc.git +T:git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git >>> >>> I cannot clone this tree, and I have tried some of my servers, although. >>> >>> remote: Total 5031043 (delta 4225582), reused 5030965 (delta 4225531) >>> Resolving deltas: 100% (4225582/4225582), done. >>> Checking connectivity... done. >>> warning: remote HEAD refers to nonexistent ref, unable to checkout. >> >> you have to checkout to "next" > > yep, it does need to assign a HEAD blob after cloning. > But I never did it when cloning other maintainers' tree. Indeed. Best Regards, Jaehoon Chung > > Thanks. > >> e.g) git checkout next >> >> Best Regards, >> Jaehoon Chung >> >>> >>> ...then the clone process failed. >>> S:Maintained F:Documentation/devicetree/bindings/mmc/ F:drivers/mmc/ >>> >>> >> >> >> >> > >
Re: [PATCH] MAINTAINERS: mmc: Move the mmc tree to kernel.org
On 10/18/2016 01:08 PM, Shawn Lin wrote: > 在 2016/10/18 11:52, Jaehoon Chung 写道: >> On 10/18/2016 12:19 PM, Shawn Lin wrote: >>> Hi Ulf, >>> >>> On 2016/10/17 20:54, Ulf Hansson wrote: Signed-off-by: Ulf Hansson --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index a009e00..e685724 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8164,7 +8164,7 @@ F:include/linux/mfd/ MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM M:Ulf Hansson L:linux-...@vger.kernel.org -T:git git://git.linaro.org/people/ulf.hansson/mmc.git +T:git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git >>> >>> I cannot clone this tree, and I have tried some of my servers, although. >>> >>> remote: Total 5031043 (delta 4225582), reused 5030965 (delta 4225531) >>> Resolving deltas: 100% (4225582/4225582), done. >>> Checking connectivity... done. >>> warning: remote HEAD refers to nonexistent ref, unable to checkout. >> >> you have to checkout to "next" > > yep, it does need to assign a HEAD blob after cloning. > But I never did it when cloning other maintainers' tree. Indeed. Best Regards, Jaehoon Chung > > Thanks. > >> e.g) git checkout next >> >> Best Regards, >> Jaehoon Chung >> >>> >>> ...then the clone process failed. >>> S:Maintained F:Documentation/devicetree/bindings/mmc/ F:drivers/mmc/ >>> >>> >> >> >> >> > >
Re: [PATCH] MAINTAINERS: mmc: Move the mmc tree to kernel.org
在 2016/10/18 11:52, Jaehoon Chung 写道: On 10/18/2016 12:19 PM, Shawn Lin wrote: Hi Ulf, On 2016/10/17 20:54, Ulf Hansson wrote: Signed-off-by: Ulf Hansson--- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index a009e00..e685724 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8164,7 +8164,7 @@ F:include/linux/mfd/ MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM M:Ulf Hansson L:linux-...@vger.kernel.org -T:git git://git.linaro.org/people/ulf.hansson/mmc.git +T:git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git I cannot clone this tree, and I have tried some of my servers, although. remote: Total 5031043 (delta 4225582), reused 5030965 (delta 4225531) Resolving deltas: 100% (4225582/4225582), done. Checking connectivity... done. warning: remote HEAD refers to nonexistent ref, unable to checkout. you have to checkout to "next" yep, it does need to assign a HEAD blob after cloning. But I never did it when cloning other maintainers' tree. Thanks. e.g) git checkout next Best Regards, Jaehoon Chung ...then the clone process failed. S:Maintained F:Documentation/devicetree/bindings/mmc/ F:drivers/mmc/ -- Best Regards Shawn Lin
Re: [PATCH] MAINTAINERS: mmc: Move the mmc tree to kernel.org
在 2016/10/18 11:52, Jaehoon Chung 写道: On 10/18/2016 12:19 PM, Shawn Lin wrote: Hi Ulf, On 2016/10/17 20:54, Ulf Hansson wrote: Signed-off-by: Ulf Hansson --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index a009e00..e685724 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8164,7 +8164,7 @@ F:include/linux/mfd/ MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM M:Ulf Hansson L:linux-...@vger.kernel.org -T:git git://git.linaro.org/people/ulf.hansson/mmc.git +T:git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git I cannot clone this tree, and I have tried some of my servers, although. remote: Total 5031043 (delta 4225582), reused 5030965 (delta 4225531) Resolving deltas: 100% (4225582/4225582), done. Checking connectivity... done. warning: remote HEAD refers to nonexistent ref, unable to checkout. you have to checkout to "next" yep, it does need to assign a HEAD blob after cloning. But I never did it when cloning other maintainers' tree. Thanks. e.g) git checkout next Best Regards, Jaehoon Chung ...then the clone process failed. S:Maintained F:Documentation/devicetree/bindings/mmc/ F:drivers/mmc/ -- Best Regards Shawn Lin
Re: [PATCH] MAINTAINERS: mmc: Move the mmc tree to kernel.org
On 10/18/2016 12:19 PM, Shawn Lin wrote: > Hi Ulf, > > On 2016/10/17 20:54, Ulf Hansson wrote: >> Signed-off-by: Ulf Hansson>> --- >> MAINTAINERS | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/MAINTAINERS b/MAINTAINERS >> index a009e00..e685724 100644 >> --- a/MAINTAINERS >> +++ b/MAINTAINERS >> @@ -8164,7 +8164,7 @@ F:include/linux/mfd/ >> MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM >> M:Ulf Hansson >> L:linux-...@vger.kernel.org >> -T:git git://git.linaro.org/people/ulf.hansson/mmc.git >> +T:git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git > > I cannot clone this tree, and I have tried some of my servers, although. > > remote: Total 5031043 (delta 4225582), reused 5030965 (delta 4225531) > Resolving deltas: 100% (4225582/4225582), done. > Checking connectivity... done. > warning: remote HEAD refers to nonexistent ref, unable to checkout. you have to checkout to "next" e.g) git checkout next Best Regards, Jaehoon Chung > > ...then the clone process failed. > >> S:Maintained >> F:Documentation/devicetree/bindings/mmc/ >> F:drivers/mmc/ >> > >
Re: [PATCH] MAINTAINERS: mmc: Move the mmc tree to kernel.org
On 10/18/2016 12:19 PM, Shawn Lin wrote: > Hi Ulf, > > On 2016/10/17 20:54, Ulf Hansson wrote: >> Signed-off-by: Ulf Hansson >> --- >> MAINTAINERS | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/MAINTAINERS b/MAINTAINERS >> index a009e00..e685724 100644 >> --- a/MAINTAINERS >> +++ b/MAINTAINERS >> @@ -8164,7 +8164,7 @@ F:include/linux/mfd/ >> MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM >> M:Ulf Hansson >> L:linux-...@vger.kernel.org >> -T:git git://git.linaro.org/people/ulf.hansson/mmc.git >> +T:git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git > > I cannot clone this tree, and I have tried some of my servers, although. > > remote: Total 5031043 (delta 4225582), reused 5030965 (delta 4225531) > Resolving deltas: 100% (4225582/4225582), done. > Checking connectivity... done. > warning: remote HEAD refers to nonexistent ref, unable to checkout. you have to checkout to "next" e.g) git checkout next Best Regards, Jaehoon Chung > > ...then the clone process failed. > >> S:Maintained >> F:Documentation/devicetree/bindings/mmc/ >> F:drivers/mmc/ >> > >
[PATCH net-next] r8152: add new products of Lenovo
Add the following four products of Lenovo and sort the order of the list. VID PID 0x17ef 0x3062 0x17ef 0x3069 0x17ef 0x720c 0x17ef 0x7214 Signed-off-by: Hayes Wang--- drivers/net/usb/cdc_ether.c | 28 drivers/net/usb/r8152.c | 6 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index c47ec0a..45e5e43 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -687,6 +687,20 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +/* ThinkPad USB-C Dock (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + +/* ThinkPad Thunderbolt 3 Dock (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3069, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* Lenovo Thinkpad USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ { USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7205, USB_CLASS_COMM, @@ -694,6 +708,20 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +/* Lenovo USB C to Ethernet Adapter (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x720c, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + +/* Lenovo USB-C Travel Hub (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7214, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ { USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM, diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 2886946..8d6e13c 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -4411,8 +4411,12 @@ static struct usb_device_id rtl8152_table[] = { {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)}, {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)}, {REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)}, - {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3062)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3069)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x720c)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7214)}, {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)}, {} }; -- 2.7.4
[PATCH net-next] r8152: add new products of Lenovo
Add the following four products of Lenovo and sort the order of the list. VID PID 0x17ef 0x3062 0x17ef 0x3069 0x17ef 0x720c 0x17ef 0x7214 Signed-off-by: Hayes Wang --- drivers/net/usb/cdc_ether.c | 28 drivers/net/usb/r8152.c | 6 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index c47ec0a..45e5e43 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -687,6 +687,20 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +/* ThinkPad USB-C Dock (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + +/* ThinkPad Thunderbolt 3 Dock (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3069, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* Lenovo Thinkpad USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ { USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7205, USB_CLASS_COMM, @@ -694,6 +708,20 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +/* Lenovo USB C to Ethernet Adapter (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x720c, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + +/* Lenovo USB-C Travel Hub (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7214, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ { USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM, diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 2886946..8d6e13c 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -4411,8 +4411,12 @@ static struct usb_device_id rtl8152_table[] = { {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)}, {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)}, {REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)}, - {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3062)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3069)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x720c)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7214)}, {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)}, {} }; -- 2.7.4
[PATCH v2 3/4] input: Deprecate real timestamps beyond year 2106
struct timeval is not y2038 safe. All usage of timeval in the kernel will be replaced by y2038 safe structures. struct input_event maintains time for each input event. Real time timestamps are not ideal for input as this time can go backwards as noted in the patch a80b83b7b8 by John Stultz. Hence, having the input_event.time fields only big enough for monotonic and boot times are sufficient. Leave the original input_event as is. This is to maintain backward compatibility with existing userspace interfaces that use input_event. Introduce a new replacement struct raw_input_event. This replaces timeval with struct input_timeval. This structure maintains time in __kernel_ulong_t or compat_ulong_t to allow for architectures to override types as in the case of x32. The change requires any userspace utilities reading or writing from event nodes to update their reading format to match raw_input_event. The changes to the popular libraries will be posted along with the kernel changes. The driver version is also updated to reflect the change in event format. Suggested-by: Arnd BergmannSigned-off-by: Deepa Dinamani Reviewed-by: Arnd Bergmann --- drivers/input/evdev.c| 20 +-- drivers/input/input-compat.c | 29 ++- drivers/input/input-compat.h | 19 +++--- drivers/input/misc/uinput.c | 6 +++--- include/linux/uinput.h | 2 +- include/uapi/linux/input.h | 47 6 files changed, 88 insertions(+), 35 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index b4e3171..459e3ba 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -60,7 +60,7 @@ struct evdev_client { bool revoked; unsigned long *evmasks[EV_CNT]; unsigned int bufsize; - struct input_event buffer[]; + struct raw_input_event buffer[]; }; static size_t evdev_get_mask_cnt(unsigned int type) @@ -113,7 +113,7 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) unsigned int i, head, num; unsigned int mask = client->bufsize - 1; bool is_report; - struct input_event *ev; + struct raw_input_event *ev; BUG_ON(type == EV_SYN); @@ -155,7 +155,7 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) static void __evdev_queue_syn_dropped(struct evdev_client *client) { - struct input_event ev; + struct raw_input_event ev; struct timespec64 ts; switch (client->clk_type) { @@ -236,7 +236,7 @@ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) } static void __pass_event(struct evdev_client *client, -const struct input_event *event) +const struct raw_input_event *event) { client->buffer[client->head++] = *event; client->head &= client->bufsize - 1; @@ -268,7 +268,7 @@ static void evdev_pass_values(struct evdev_client *client, { struct evdev *evdev = client->evdev; const struct input_value *v; - struct input_event event; + struct raw_input_event event; struct timespec64 ts; bool wakeup = false; @@ -507,7 +507,7 @@ static int evdev_open(struct inode *inode, struct file *file) struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev); unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev); unsigned int size = sizeof(struct evdev_client) + - bufsize * sizeof(struct input_event); + bufsize * sizeof(struct raw_input_event); struct evdev_client *client; int error; @@ -542,7 +542,7 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer, { struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; - struct input_event event; + struct raw_input_event event; int retval = 0; if (count != 0 && count < input_event_size()) @@ -575,7 +575,7 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer, } static int evdev_fetch_next_event(struct evdev_client *client, - struct input_event *event) + struct raw_input_event *event) { int have_event; @@ -597,7 +597,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, { struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; - struct input_event event; + struct raw_input_event event; size_t read = 0; int error; @@ -1083,7 +1083,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, switch (cmd) { case EVIOCGVERSION: - return put_user(EV_VERSION, ip); +
[PATCH v2 1/4] uinput: Add ioctl for using monotonic/ boot times
struct timeval which is part of struct input_event to maintain the event times is not y2038 safe. Real time timestamps are also not ideal for input_event as this time can go backwards as noted in the patch a80b83b7b8 by John Stultz. Arnd Bergmann suggested deprecating real time and using monotonic or other timers for all input_event times as a solution to both the above problems. Add a new ioctl to let the user dictate the kind of time to be used for input events. This is similar to the evdev implementation of the feature. Realtime is still the default time. This is to maintain backward compatibility. The structure to maintain input events will be changed in a different patch. Signed-off-by: Deepa Dinamani--- drivers/input/misc/uinput.c | 56 - include/linux/uinput.h | 1 + include/uapi/linux/uinput.h | 3 +++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 92595b9..3d75c5a 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -46,11 +46,26 @@ static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { struct uinput_device*udev = input_get_drvdata(dev); + struct timespec64 ts; udev->buff[udev->head].type = type; udev->buff[udev->head].code = code; udev->buff[udev->head].value = value; - do_gettimeofday(>buff[udev->head].time); + + switch (udev->clk_type) { + case CLOCK_REALTIME: + ktime_get_real_ts64(); + break; + case CLOCK_MONOTONIC: + ktime_get_ts64(); + break; + case CLOCK_BOOTTIME: + get_monotonic_boottime64(); + break; + } + + udev->buff[udev->head].time.tv_sec = ts.tv_sec; + udev->buff[udev->head].time.tv_usec = ts.tv_nsec / NSEC_PER_USEC; udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE; wake_up_interruptible(>waitq); @@ -295,6 +310,7 @@ static int uinput_create_device(struct uinput_device *udev) if (error) goto fail2; + udev->clk_type = CLOCK_REALTIME; udev->state = UIST_CREATED; return 0; @@ -304,6 +320,38 @@ static int uinput_create_device(struct uinput_device *udev) return error; } +static int uinput_set_clk_type(struct uinput_device *udev, unsigned int clkid) +{ + unsigned int clk_type; + + if (udev->state != UIST_CREATED) + return -EINVAL; + + switch (clkid) { + /* Realtime clock is only valid until year 2038.*/ + case CLOCK_REALTIME: + clk_type = CLOCK_REALTIME; + break; + case CLOCK_MONOTONIC: + clk_type = CLOCK_MONOTONIC; + break; + case CLOCK_BOOTTIME: + clk_type = CLOCK_BOOTTIME; + break; + default: + return -EINVAL; + } + + if (udev->clk_type != clk_type) { + udev->clk_type = clk_type; + + /* Flush pending events */ + uinput_flush_requests(udev); + } + + return 0; +} + static int uinput_open(struct inode *inode, struct file *file) { struct uinput_device *newdev; @@ -787,6 +835,7 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, char*phys; const char *name; unsigned intsize; + int clock_id; retval = mutex_lock_interruptible(>mutex); if (retval) @@ -817,6 +866,11 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, retval = uinput_dev_setup(udev, p); goto out; + case UI_SET_CLOCKID: + if (copy_from_user(_id, p, sizeof(unsigned int))) + return -EFAULT; + return uinput_set_clk_type(udev, clock_id); + /* UI_ABS_SETUP is handled in the variable size ioctls */ case UI_SET_EVBIT: diff --git a/include/linux/uinput.h b/include/linux/uinput.h index 75de43d..6527fb7 100644 --- a/include/linux/uinput.h +++ b/include/linux/uinput.h @@ -72,6 +72,7 @@ struct uinput_device { unsigned char head; unsigned char tail; struct input_event buff[UINPUT_BUFFER_SIZE]; + int clk_type; unsigned intff_effects_max; struct uinput_request *requests[UINPUT_NUM_REQUESTS]; diff --git a/include/uapi/linux/uinput.h b/include/uapi/linux/uinput.h index dc652e2..d9494ae 100644 --- a/include/uapi/linux/uinput.h +++ b/include/uapi/linux/uinput.h @@ -133,6 +133,9 @@ struct uinput_abs_setup { */ #define UI_ABS_SETUP _IOW(UINPUT_IOCTL_BASE, 4, struct
[PATCH v2 3/4] input: Deprecate real timestamps beyond year 2106
struct timeval is not y2038 safe. All usage of timeval in the kernel will be replaced by y2038 safe structures. struct input_event maintains time for each input event. Real time timestamps are not ideal for input as this time can go backwards as noted in the patch a80b83b7b8 by John Stultz. Hence, having the input_event.time fields only big enough for monotonic and boot times are sufficient. Leave the original input_event as is. This is to maintain backward compatibility with existing userspace interfaces that use input_event. Introduce a new replacement struct raw_input_event. This replaces timeval with struct input_timeval. This structure maintains time in __kernel_ulong_t or compat_ulong_t to allow for architectures to override types as in the case of x32. The change requires any userspace utilities reading or writing from event nodes to update their reading format to match raw_input_event. The changes to the popular libraries will be posted along with the kernel changes. The driver version is also updated to reflect the change in event format. Suggested-by: Arnd Bergmann Signed-off-by: Deepa Dinamani Reviewed-by: Arnd Bergmann --- drivers/input/evdev.c| 20 +-- drivers/input/input-compat.c | 29 ++- drivers/input/input-compat.h | 19 +++--- drivers/input/misc/uinput.c | 6 +++--- include/linux/uinput.h | 2 +- include/uapi/linux/input.h | 47 6 files changed, 88 insertions(+), 35 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index b4e3171..459e3ba 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -60,7 +60,7 @@ struct evdev_client { bool revoked; unsigned long *evmasks[EV_CNT]; unsigned int bufsize; - struct input_event buffer[]; + struct raw_input_event buffer[]; }; static size_t evdev_get_mask_cnt(unsigned int type) @@ -113,7 +113,7 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) unsigned int i, head, num; unsigned int mask = client->bufsize - 1; bool is_report; - struct input_event *ev; + struct raw_input_event *ev; BUG_ON(type == EV_SYN); @@ -155,7 +155,7 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) static void __evdev_queue_syn_dropped(struct evdev_client *client) { - struct input_event ev; + struct raw_input_event ev; struct timespec64 ts; switch (client->clk_type) { @@ -236,7 +236,7 @@ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) } static void __pass_event(struct evdev_client *client, -const struct input_event *event) +const struct raw_input_event *event) { client->buffer[client->head++] = *event; client->head &= client->bufsize - 1; @@ -268,7 +268,7 @@ static void evdev_pass_values(struct evdev_client *client, { struct evdev *evdev = client->evdev; const struct input_value *v; - struct input_event event; + struct raw_input_event event; struct timespec64 ts; bool wakeup = false; @@ -507,7 +507,7 @@ static int evdev_open(struct inode *inode, struct file *file) struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev); unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev); unsigned int size = sizeof(struct evdev_client) + - bufsize * sizeof(struct input_event); + bufsize * sizeof(struct raw_input_event); struct evdev_client *client; int error; @@ -542,7 +542,7 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer, { struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; - struct input_event event; + struct raw_input_event event; int retval = 0; if (count != 0 && count < input_event_size()) @@ -575,7 +575,7 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer, } static int evdev_fetch_next_event(struct evdev_client *client, - struct input_event *event) + struct raw_input_event *event) { int have_event; @@ -597,7 +597,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, { struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; - struct input_event event; + struct raw_input_event event; size_t read = 0; int error; @@ -1083,7 +1083,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, switch (cmd) { case EVIOCGVERSION: - return put_user(EV_VERSION, ip); + return put_user(EV_VERSION_1_2, ip); case
[PATCH v2 1/4] uinput: Add ioctl for using monotonic/ boot times
struct timeval which is part of struct input_event to maintain the event times is not y2038 safe. Real time timestamps are also not ideal for input_event as this time can go backwards as noted in the patch a80b83b7b8 by John Stultz. Arnd Bergmann suggested deprecating real time and using monotonic or other timers for all input_event times as a solution to both the above problems. Add a new ioctl to let the user dictate the kind of time to be used for input events. This is similar to the evdev implementation of the feature. Realtime is still the default time. This is to maintain backward compatibility. The structure to maintain input events will be changed in a different patch. Signed-off-by: Deepa Dinamani --- drivers/input/misc/uinput.c | 56 - include/linux/uinput.h | 1 + include/uapi/linux/uinput.h | 3 +++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 92595b9..3d75c5a 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -46,11 +46,26 @@ static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { struct uinput_device*udev = input_get_drvdata(dev); + struct timespec64 ts; udev->buff[udev->head].type = type; udev->buff[udev->head].code = code; udev->buff[udev->head].value = value; - do_gettimeofday(>buff[udev->head].time); + + switch (udev->clk_type) { + case CLOCK_REALTIME: + ktime_get_real_ts64(); + break; + case CLOCK_MONOTONIC: + ktime_get_ts64(); + break; + case CLOCK_BOOTTIME: + get_monotonic_boottime64(); + break; + } + + udev->buff[udev->head].time.tv_sec = ts.tv_sec; + udev->buff[udev->head].time.tv_usec = ts.tv_nsec / NSEC_PER_USEC; udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE; wake_up_interruptible(>waitq); @@ -295,6 +310,7 @@ static int uinput_create_device(struct uinput_device *udev) if (error) goto fail2; + udev->clk_type = CLOCK_REALTIME; udev->state = UIST_CREATED; return 0; @@ -304,6 +320,38 @@ static int uinput_create_device(struct uinput_device *udev) return error; } +static int uinput_set_clk_type(struct uinput_device *udev, unsigned int clkid) +{ + unsigned int clk_type; + + if (udev->state != UIST_CREATED) + return -EINVAL; + + switch (clkid) { + /* Realtime clock is only valid until year 2038.*/ + case CLOCK_REALTIME: + clk_type = CLOCK_REALTIME; + break; + case CLOCK_MONOTONIC: + clk_type = CLOCK_MONOTONIC; + break; + case CLOCK_BOOTTIME: + clk_type = CLOCK_BOOTTIME; + break; + default: + return -EINVAL; + } + + if (udev->clk_type != clk_type) { + udev->clk_type = clk_type; + + /* Flush pending events */ + uinput_flush_requests(udev); + } + + return 0; +} + static int uinput_open(struct inode *inode, struct file *file) { struct uinput_device *newdev; @@ -787,6 +835,7 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, char*phys; const char *name; unsigned intsize; + int clock_id; retval = mutex_lock_interruptible(>mutex); if (retval) @@ -817,6 +866,11 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, retval = uinput_dev_setup(udev, p); goto out; + case UI_SET_CLOCKID: + if (copy_from_user(_id, p, sizeof(unsigned int))) + return -EFAULT; + return uinput_set_clk_type(udev, clock_id); + /* UI_ABS_SETUP is handled in the variable size ioctls */ case UI_SET_EVBIT: diff --git a/include/linux/uinput.h b/include/linux/uinput.h index 75de43d..6527fb7 100644 --- a/include/linux/uinput.h +++ b/include/linux/uinput.h @@ -72,6 +72,7 @@ struct uinput_device { unsigned char head; unsigned char tail; struct input_event buff[UINPUT_BUFFER_SIZE]; + int clk_type; unsigned intff_effects_max; struct uinput_request *requests[UINPUT_NUM_REQUESTS]; diff --git a/include/uapi/linux/uinput.h b/include/uapi/linux/uinput.h index dc652e2..d9494ae 100644 --- a/include/uapi/linux/uinput.h +++ b/include/uapi/linux/uinput.h @@ -133,6 +133,9 @@ struct uinput_abs_setup { */ #define UI_ABS_SETUP _IOW(UINPUT_IOCTL_BASE, 4, struct uinput_abs_setup) +/* Set
[PATCH v2 4/4] input: serio: Replace timeval by timespec64
struct timeval is not y2038 safe. All references to timeval will be deleted from the kernel to make it y2038 safe. Replace its uses by y2038 safe struct timespec64. The timestamps changed here only keep track of delta times. These timestamps are also internal to kernel. Hence, monotonic times are sufficient here. The unit of the delta times is also changed in certain cases to nanoseconds rather than microseconds. This is in line with timespec64 which keeps time in nanoseconds. Signed-off-by: Deepa DinamaniReviewed-by: Arnd Bergmann --- drivers/input/serio/hil_mlc.c| 37 ++--- drivers/input/serio/hp_sdc.c | 17 + drivers/input/serio/hp_sdc_mlc.c | 10 +- include/linux/hil_mlc.h | 6 +++--- include/linux/hp_sdc.h | 6 +++--- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index 65605e4..7c59a79 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c @@ -274,14 +274,14 @@ static int hilse_match(hil_mlc *mlc, int unused) /* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */ static int hilse_init_lcv(hil_mlc *mlc, int unused) { - struct timeval tv; + time64_t time; - do_gettimeofday(); + time = ktime_get_seconds(); - if (mlc->lcv && (tv.tv_sec - mlc->lcv_tv.tv_sec) < 5) + if (mlc->lcv && (time - mlc->lcv_tv.tv_sec) < 5) return -1; - mlc->lcv_tv = tv; + mlc->lcv_tv.tv_sec = time; mlc->lcv = 0; return 0; @@ -466,7 +466,7 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = { FUNC(hilse_init_lcv, 0, HILSEN_NEXT,HILSEN_SLEEP, 0) /* 1 HILSEN_RESTART */ - FUNC(hilse_inc_lcv, 10, HILSEN_NEXT,HILSEN_START, 0) + FUNC(hilse_inc_lcv, 1, HILSEN_NEXT,HILSEN_START, 0) OUT(HIL_CTRL_ONLY) /* Disable APE */ CTS @@ -485,7 +485,7 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = { FUNC(hilse_init_lcv, 0, HILSEN_NEXT,HILSEN_SLEEP, 0) /* 10 HILSEN_DHR2 */ - FUNC(hilse_inc_lcv, 10, HILSEN_NEXT,HILSEN_START, 0) + FUNC(hilse_inc_lcv, 1, HILSEN_NEXT,HILSEN_START, 0) FUNC(hilse_set_ddi, -1, HILSEN_NEXT,0, 0) OUT(HIL_PKT_CMD | HIL_CMD_DHR) IN(30, HILSEN_DHR2,HILSEN_DHR2,HILSEN_NEXT) @@ -515,7 +515,7 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = { FUNC(hilse_init_lcv, 0, HILSEN_NEXT,HILSEN_DOZE,0) /* 22 HILSEN_ACF2 */ - FUNC(hilse_inc_lcv, 10, HILSEN_NEXT,HILSEN_START, 0) + FUNC(hilse_inc_lcv, 1, HILSEN_NEXT,HILSEN_START, 0) OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1) IN(2, HILSEN_NEXT,HILSEN_DSR, HILSEN_NEXT) @@ -572,7 +572,7 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = { OUT(HIL_PKT_CMD | HIL_CMD_RPL) EXPECT(HIL_PKT_CMD | HIL_CMD_RPL | HIL_ERR_INT, 2, HILSEN_NEXT,HILSEN_DSR, HILSEN_NEXT) - FUNC(hilse_operate, 1, HILSEN_OPERATE, HILSEN_IFC, HILSEN_PROBE) + FUNC(hilse_operate, 1000, HILSEN_OPERATE, HILSEN_IFC, HILSEN_PROBE) /* 58 HILSEN_IFCACF */ OUT(HIL_PKT_CMD | HIL_CMD_IFC) @@ -584,7 +584,6 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = { static inline void hilse_setup_input(hil_mlc *mlc, const struct hilse_node *node) { - switch (node->act) { case HILSE_EXPECT_DISC: mlc->imatch = node->object.packet; @@ -605,7 +604,7 @@ static inline void hilse_setup_input(hil_mlc *mlc, const struct hilse_node *node } mlc->istarted = 1; mlc->intimeout = node->arg; - do_gettimeofday(&(mlc->instart)); + ktime_get_ts64(&(mlc->instart)); mlc->icount = 15; memset(mlc->ipacket, 0, 16 * sizeof(hil_packet)); BUG_ON(down_trylock(>isem)); @@ -710,7 +709,7 @@ static int hilse_donode(hil_mlc *mlc) break; } mlc->ostarted = 0; - do_gettimeofday(&(mlc->instart)); + ktime_get_ts64(&(mlc->instart)); write_unlock_irqrestore(>lock, flags); nextidx = HILSEN_NEXT; break; @@ -731,18 +730,18 @@ static int hilse_donode(hil_mlc *mlc) #endif while (nextidx & HILSEN_SCHED) { - struct timeval tv; + struct timespec64 ts; if (!sched_long) goto sched; - do_gettimeofday(); - tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec); - tv.tv_usec -= mlc->instart.tv_usec; - if (tv.tv_usec >= mlc->intimeout) goto sched; -
[PATCH v2 2/4] input: evdev: Replace timeval with timespec64
struct timeval is not y2038 safe. All references to timeval in the kernel will be replaced by y2038 safe structures. Replace all references to timeval with y2038 safe struct timespec64 here. struct input_event will be changed in a different patch. Signed-off-by: Deepa DinamaniReviewed-by: Arnd Bergmann --- drivers/input/evdev.c | 37 +++-- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e9ae3d5..b4e3171 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -156,15 +156,22 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) static void __evdev_queue_syn_dropped(struct evdev_client *client) { struct input_event ev; - ktime_t time; + struct timespec64 ts; - time = client->clk_type == EV_CLK_REAL ? - ktime_get_real() : - client->clk_type == EV_CLK_MONO ? - ktime_get() : - ktime_get_boottime(); + switch (client->clk_type) { + case EV_CLK_REAL: + ktime_get_real_ts64(); + break; + case EV_CLK_MONO: + ktime_get_ts64(); + break; + case EV_CLK_BOOT: + get_monotonic_boottime64(); + break; + } - ev.time = ktime_to_timeval(time); + ev.time.tv_sec = ts.tv_sec; + ev.time.tv_usec = ts.tv_nsec / NSEC_PER_USEC; ev.type = EV_SYN; ev.code = SYN_DROPPED; ev.value = 0; @@ -257,17 +264,20 @@ static void __pass_event(struct evdev_client *client, static void evdev_pass_values(struct evdev_client *client, const struct input_value *vals, unsigned int count, - ktime_t *ev_time) + struct timespec64 *ev_time) { struct evdev *evdev = client->evdev; const struct input_value *v; struct input_event event; + struct timespec64 ts; bool wakeup = false; if (client->revoked) return; - event.time = ktime_to_timeval(ev_time[client->clk_type]); + ts = ev_time[client->clk_type]; + event.time.tv_sec = ts.tv_sec; + event.time.tv_usec = ts.tv_nsec / NSEC_PER_USEC; /* Interrupts are disabled, just acquire the lock. */ spin_lock(>buffer_lock); @@ -304,12 +314,11 @@ static void evdev_events(struct input_handle *handle, { struct evdev *evdev = handle->private; struct evdev_client *client; - ktime_t ev_time[EV_CLK_MAX]; + struct timespec64 ev_time[EV_CLK_MAX]; - ev_time[EV_CLK_MONO] = ktime_get(); - ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]); - ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO], -TK_OFFS_BOOT); + ktime_get_ts64(_time[EV_CLK_MONO]); + ktime_get_real_ts64(_time[EV_CLK_REAL]); + get_monotonic_boottime64(_time[EV_CLK_BOOT]); rcu_read_lock(); -- 2.7.4
[PATCH v2 4/4] input: serio: Replace timeval by timespec64
struct timeval is not y2038 safe. All references to timeval will be deleted from the kernel to make it y2038 safe. Replace its uses by y2038 safe struct timespec64. The timestamps changed here only keep track of delta times. These timestamps are also internal to kernel. Hence, monotonic times are sufficient here. The unit of the delta times is also changed in certain cases to nanoseconds rather than microseconds. This is in line with timespec64 which keeps time in nanoseconds. Signed-off-by: Deepa Dinamani Reviewed-by: Arnd Bergmann --- drivers/input/serio/hil_mlc.c| 37 ++--- drivers/input/serio/hp_sdc.c | 17 + drivers/input/serio/hp_sdc_mlc.c | 10 +- include/linux/hil_mlc.h | 6 +++--- include/linux/hp_sdc.h | 6 +++--- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index 65605e4..7c59a79 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c @@ -274,14 +274,14 @@ static int hilse_match(hil_mlc *mlc, int unused) /* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */ static int hilse_init_lcv(hil_mlc *mlc, int unused) { - struct timeval tv; + time64_t time; - do_gettimeofday(); + time = ktime_get_seconds(); - if (mlc->lcv && (tv.tv_sec - mlc->lcv_tv.tv_sec) < 5) + if (mlc->lcv && (time - mlc->lcv_tv.tv_sec) < 5) return -1; - mlc->lcv_tv = tv; + mlc->lcv_tv.tv_sec = time; mlc->lcv = 0; return 0; @@ -466,7 +466,7 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = { FUNC(hilse_init_lcv, 0, HILSEN_NEXT,HILSEN_SLEEP, 0) /* 1 HILSEN_RESTART */ - FUNC(hilse_inc_lcv, 10, HILSEN_NEXT,HILSEN_START, 0) + FUNC(hilse_inc_lcv, 1, HILSEN_NEXT,HILSEN_START, 0) OUT(HIL_CTRL_ONLY) /* Disable APE */ CTS @@ -485,7 +485,7 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = { FUNC(hilse_init_lcv, 0, HILSEN_NEXT,HILSEN_SLEEP, 0) /* 10 HILSEN_DHR2 */ - FUNC(hilse_inc_lcv, 10, HILSEN_NEXT,HILSEN_START, 0) + FUNC(hilse_inc_lcv, 1, HILSEN_NEXT,HILSEN_START, 0) FUNC(hilse_set_ddi, -1, HILSEN_NEXT,0, 0) OUT(HIL_PKT_CMD | HIL_CMD_DHR) IN(30, HILSEN_DHR2,HILSEN_DHR2,HILSEN_NEXT) @@ -515,7 +515,7 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = { FUNC(hilse_init_lcv, 0, HILSEN_NEXT,HILSEN_DOZE,0) /* 22 HILSEN_ACF2 */ - FUNC(hilse_inc_lcv, 10, HILSEN_NEXT,HILSEN_START, 0) + FUNC(hilse_inc_lcv, 1, HILSEN_NEXT,HILSEN_START, 0) OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1) IN(2, HILSEN_NEXT,HILSEN_DSR, HILSEN_NEXT) @@ -572,7 +572,7 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = { OUT(HIL_PKT_CMD | HIL_CMD_RPL) EXPECT(HIL_PKT_CMD | HIL_CMD_RPL | HIL_ERR_INT, 2, HILSEN_NEXT,HILSEN_DSR, HILSEN_NEXT) - FUNC(hilse_operate, 1, HILSEN_OPERATE, HILSEN_IFC, HILSEN_PROBE) + FUNC(hilse_operate, 1000, HILSEN_OPERATE, HILSEN_IFC, HILSEN_PROBE) /* 58 HILSEN_IFCACF */ OUT(HIL_PKT_CMD | HIL_CMD_IFC) @@ -584,7 +584,6 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = { static inline void hilse_setup_input(hil_mlc *mlc, const struct hilse_node *node) { - switch (node->act) { case HILSE_EXPECT_DISC: mlc->imatch = node->object.packet; @@ -605,7 +604,7 @@ static inline void hilse_setup_input(hil_mlc *mlc, const struct hilse_node *node } mlc->istarted = 1; mlc->intimeout = node->arg; - do_gettimeofday(&(mlc->instart)); + ktime_get_ts64(&(mlc->instart)); mlc->icount = 15; memset(mlc->ipacket, 0, 16 * sizeof(hil_packet)); BUG_ON(down_trylock(>isem)); @@ -710,7 +709,7 @@ static int hilse_donode(hil_mlc *mlc) break; } mlc->ostarted = 0; - do_gettimeofday(&(mlc->instart)); + ktime_get_ts64(&(mlc->instart)); write_unlock_irqrestore(>lock, flags); nextidx = HILSEN_NEXT; break; @@ -731,18 +730,18 @@ static int hilse_donode(hil_mlc *mlc) #endif while (nextidx & HILSEN_SCHED) { - struct timeval tv; + struct timespec64 ts; if (!sched_long) goto sched; - do_gettimeofday(); - tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec); - tv.tv_usec -= mlc->instart.tv_usec; - if (tv.tv_usec >= mlc->intimeout) goto sched; - tv.tv_usec = (mlc->intimeout -
[PATCH v2 2/4] input: evdev: Replace timeval with timespec64
struct timeval is not y2038 safe. All references to timeval in the kernel will be replaced by y2038 safe structures. Replace all references to timeval with y2038 safe struct timespec64 here. struct input_event will be changed in a different patch. Signed-off-by: Deepa Dinamani Reviewed-by: Arnd Bergmann --- drivers/input/evdev.c | 37 +++-- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e9ae3d5..b4e3171 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -156,15 +156,22 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) static void __evdev_queue_syn_dropped(struct evdev_client *client) { struct input_event ev; - ktime_t time; + struct timespec64 ts; - time = client->clk_type == EV_CLK_REAL ? - ktime_get_real() : - client->clk_type == EV_CLK_MONO ? - ktime_get() : - ktime_get_boottime(); + switch (client->clk_type) { + case EV_CLK_REAL: + ktime_get_real_ts64(); + break; + case EV_CLK_MONO: + ktime_get_ts64(); + break; + case EV_CLK_BOOT: + get_monotonic_boottime64(); + break; + } - ev.time = ktime_to_timeval(time); + ev.time.tv_sec = ts.tv_sec; + ev.time.tv_usec = ts.tv_nsec / NSEC_PER_USEC; ev.type = EV_SYN; ev.code = SYN_DROPPED; ev.value = 0; @@ -257,17 +264,20 @@ static void __pass_event(struct evdev_client *client, static void evdev_pass_values(struct evdev_client *client, const struct input_value *vals, unsigned int count, - ktime_t *ev_time) + struct timespec64 *ev_time) { struct evdev *evdev = client->evdev; const struct input_value *v; struct input_event event; + struct timespec64 ts; bool wakeup = false; if (client->revoked) return; - event.time = ktime_to_timeval(ev_time[client->clk_type]); + ts = ev_time[client->clk_type]; + event.time.tv_sec = ts.tv_sec; + event.time.tv_usec = ts.tv_nsec / NSEC_PER_USEC; /* Interrupts are disabled, just acquire the lock. */ spin_lock(>buffer_lock); @@ -304,12 +314,11 @@ static void evdev_events(struct input_handle *handle, { struct evdev *evdev = handle->private; struct evdev_client *client; - ktime_t ev_time[EV_CLK_MAX]; + struct timespec64 ev_time[EV_CLK_MAX]; - ev_time[EV_CLK_MONO] = ktime_get(); - ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]); - ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO], -TK_OFFS_BOOT); + ktime_get_ts64(_time[EV_CLK_MONO]); + ktime_get_real_ts64(_time[EV_CLK_REAL]); + get_monotonic_boottime64(_time[EV_CLK_BOOT]); rcu_read_lock(); -- 2.7.4
[PATCH v2 0/4] Make input drivers y2038 safe
Reposting the series as I did not hear comments from the maintainers. The series is aimed at making input events y2038 safe. It extends the lifetime of the realtime timestamps in the events to year 2106. The plan is to deprecate realtime timestamps anyway as they are not appropriate for these timestamps as noted in the patch a80b83b7b8 by John Stultz. The series is a result of many discussions with Arnd Bergmann. The design updates the format of the input events read/ written to the device nodes. This structure and the uapi/input.h header file are copied across many userspace libraries. These libraries not only use this struct input_event locally, but also expose interfaces that contain input_event. To maintain backward compatibility with all these interfaces, kernel updates the format of the input events at the dev node to struct raw_input_event. Kernel also maintains the old struct input_event and provides apis to convert between the old and new input event types. The userspace library changes to libevdev, libuinput and mtdev will be posted to the respective mailing groups for review. Once there is a consensus on the design, all the changes dependent on the kernel change will be merged at the same time. Changes from v1: * Updated changes according to review comments. * Posted userspace library changes that go along with the series. Deepa Dinamani (4): uinput: Add ioctl for using monotonic/ boot times input: evdev: Replace timeval with timespec64 input: Deprecate real timestamps beyond year 2106 input: serio: Replace timeval by timespec64 drivers/input/evdev.c| 57 drivers/input/input-compat.c | 29 ++- drivers/input/input-compat.h | 19 +++- drivers/input/misc/uinput.c | 62 +--- drivers/input/serio/hil_mlc.c| 37 drivers/input/serio/hp_sdc.c | 17 +-- drivers/input/serio/hp_sdc_mlc.c | 10 +++ include/linux/hil_mlc.h | 6 ++-- include/linux/hp_sdc.h | 6 ++-- include/linux/uinput.h | 3 +- include/uapi/linux/input.h | 47 ++ include/uapi/linux/uinput.h | 3 ++ 12 files changed, 208 insertions(+), 88 deletions(-) -- 2.7.4
[PATCH v2 0/4] Make input drivers y2038 safe
Reposting the series as I did not hear comments from the maintainers. The series is aimed at making input events y2038 safe. It extends the lifetime of the realtime timestamps in the events to year 2106. The plan is to deprecate realtime timestamps anyway as they are not appropriate for these timestamps as noted in the patch a80b83b7b8 by John Stultz. The series is a result of many discussions with Arnd Bergmann. The design updates the format of the input events read/ written to the device nodes. This structure and the uapi/input.h header file are copied across many userspace libraries. These libraries not only use this struct input_event locally, but also expose interfaces that contain input_event. To maintain backward compatibility with all these interfaces, kernel updates the format of the input events at the dev node to struct raw_input_event. Kernel also maintains the old struct input_event and provides apis to convert between the old and new input event types. The userspace library changes to libevdev, libuinput and mtdev will be posted to the respective mailing groups for review. Once there is a consensus on the design, all the changes dependent on the kernel change will be merged at the same time. Changes from v1: * Updated changes according to review comments. * Posted userspace library changes that go along with the series. Deepa Dinamani (4): uinput: Add ioctl for using monotonic/ boot times input: evdev: Replace timeval with timespec64 input: Deprecate real timestamps beyond year 2106 input: serio: Replace timeval by timespec64 drivers/input/evdev.c| 57 drivers/input/input-compat.c | 29 ++- drivers/input/input-compat.h | 19 +++- drivers/input/misc/uinput.c | 62 +--- drivers/input/serio/hil_mlc.c| 37 drivers/input/serio/hp_sdc.c | 17 +-- drivers/input/serio/hp_sdc_mlc.c | 10 +++ include/linux/hil_mlc.h | 6 ++-- include/linux/hp_sdc.h | 6 ++-- include/linux/uinput.h | 3 +- include/uapi/linux/input.h | 47 ++ include/uapi/linux/uinput.h | 3 ++ 12 files changed, 208 insertions(+), 88 deletions(-) -- 2.7.4
RE: USB GADGET: have a question about usb2eth
> -Original Message- > From: Felipe Balbi [mailto:ba...@kernel.org] > Sent: Monday, October 17, 2016 5:29 PM > To: Lipengcheng; Peter Chen > Cc: gre...@linuxfoundation.org; linux-...@vger.kernel.org; > linux-kernel@vger.kernel.org > Subject: RE: USB GADGET: have a question about usb2eth > > > Hi, > > (please, avoid top-posting: http://daringfireball.net/2007/07/on_top) > > Lipengchengwrites: > > Hi, > > thank you for your suggestion. > > > > I have a question about usb2eth. In the function gen_ndis_set_resp of > > the rndis.c, the value of *params->filter may be 0x20 from the pc set > > command; Howerver the value is used cdc_filter = > > dev->port_usb->cdc_filter in the function eth_start_xmit of the u_ether.c. > > If we do not judge the RNDIS_PACKET_TYPE_PROMISCUOUS and the value is > > 0x20, the broadcast packet can not send the pc win7; At the result, > > the linux ping the win7 is slow an the first. At the same time, Why > > are different value between RNDIS_PACKET_TYPE_PROMISCUOUS and > > USB_CDC_PACKET_TYPE_PROMISCUOUS? If the value of > > RNDIS_PACKET_TYPE_PROMISCUOUS > > because they are defined by different specifications. You should read both > CDC specification from USB.org and RNDIS spec from Microsoft to > understand the details of that. Ok. I will understand the different both CDC specification from USB.org and RNDIS spec from Microsoft. They should have transformational rule in the linux code between CDC spe and RNDIS spe. Through debugging, I found there has been no conversion about the filter. I feel a little problem. I will find the rule. > > > and USB_CDC_PACKET_TYPE_PROMISCUOUS is same, then the linux ping the > > win7 is normal speed. > > I don't understand what's going on here. Care to describe which kernel you're > using, which USB peripheral controller, what is the actual > problem you're trying to solve? VERSION = 3.18.20 USB peripheral controller: Synopsys HS OTG Linux Software Driver. It's not the standard linux code. But I think the controller do not have problem. The probem is that I am using one controller board with Linux running on it. I want to interface my device to the Host computer (Windows OS) through USB. I have driver ready at device side (linux) and the bridge has been established. The device side ping the Host computer is very slow at the first time. It spends a few minutes. The problem is the first ping takes too long time. Now I have a way to quickly ping at the first , but I do not know the risk about the change.I will continue debug the problem. If it is valuable, I will submit the kernel community. Thanks very much! > > -- > Balbi Best Regards Pengcheng Li
RE: USB GADGET: have a question about usb2eth
> -Original Message- > From: Felipe Balbi [mailto:ba...@kernel.org] > Sent: Monday, October 17, 2016 5:29 PM > To: Lipengcheng; Peter Chen > Cc: gre...@linuxfoundation.org; linux-...@vger.kernel.org; > linux-kernel@vger.kernel.org > Subject: RE: USB GADGET: have a question about usb2eth > > > Hi, > > (please, avoid top-posting: http://daringfireball.net/2007/07/on_top) > > Lipengcheng writes: > > Hi, > > thank you for your suggestion. > > > > I have a question about usb2eth. In the function gen_ndis_set_resp of > > the rndis.c, the value of *params->filter may be 0x20 from the pc set > > command; Howerver the value is used cdc_filter = > > dev->port_usb->cdc_filter in the function eth_start_xmit of the u_ether.c. > > If we do not judge the RNDIS_PACKET_TYPE_PROMISCUOUS and the value is > > 0x20, the broadcast packet can not send the pc win7; At the result, > > the linux ping the win7 is slow an the first. At the same time, Why > > are different value between RNDIS_PACKET_TYPE_PROMISCUOUS and > > USB_CDC_PACKET_TYPE_PROMISCUOUS? If the value of > > RNDIS_PACKET_TYPE_PROMISCUOUS > > because they are defined by different specifications. You should read both > CDC specification from USB.org and RNDIS spec from Microsoft to > understand the details of that. Ok. I will understand the different both CDC specification from USB.org and RNDIS spec from Microsoft. They should have transformational rule in the linux code between CDC spe and RNDIS spe. Through debugging, I found there has been no conversion about the filter. I feel a little problem. I will find the rule. > > > and USB_CDC_PACKET_TYPE_PROMISCUOUS is same, then the linux ping the > > win7 is normal speed. > > I don't understand what's going on here. Care to describe which kernel you're > using, which USB peripheral controller, what is the actual > problem you're trying to solve? VERSION = 3.18.20 USB peripheral controller: Synopsys HS OTG Linux Software Driver. It's not the standard linux code. But I think the controller do not have problem. The probem is that I am using one controller board with Linux running on it. I want to interface my device to the Host computer (Windows OS) through USB. I have driver ready at device side (linux) and the bridge has been established. The device side ping the Host computer is very slow at the first time. It spends a few minutes. The problem is the first ping takes too long time. Now I have a way to quickly ping at the first , but I do not know the risk about the change.I will continue debug the problem. If it is valuable, I will submit the kernel community. Thanks very much! > > -- > Balbi Best Regards Pengcheng Li
Re: [PATCH] MAINTAINERS: mmc: Move the mmc tree to kernel.org
Hi Ulf, On 2016/10/17 20:54, Ulf Hansson wrote: Signed-off-by: Ulf Hansson--- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index a009e00..e685724 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8164,7 +8164,7 @@ F:include/linux/mfd/ MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM M: Ulf Hansson L: linux-...@vger.kernel.org -T: git git://git.linaro.org/people/ulf.hansson/mmc.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git I cannot clone this tree, and I have tried some of my servers, although. remote: Total 5031043 (delta 4225582), reused 5030965 (delta 4225531) Resolving deltas: 100% (4225582/4225582), done. Checking connectivity... done. warning: remote HEAD refers to nonexistent ref, unable to checkout. ...then the clone process failed. S: Maintained F: Documentation/devicetree/bindings/mmc/ F: drivers/mmc/ -- Best Regards Shawn Lin
Re: [PATCH] MAINTAINERS: mmc: Move the mmc tree to kernel.org
Hi Ulf, On 2016/10/17 20:54, Ulf Hansson wrote: Signed-off-by: Ulf Hansson --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index a009e00..e685724 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8164,7 +8164,7 @@ F:include/linux/mfd/ MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM M: Ulf Hansson L: linux-...@vger.kernel.org -T: git git://git.linaro.org/people/ulf.hansson/mmc.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git I cannot clone this tree, and I have tried some of my servers, although. remote: Total 5031043 (delta 4225582), reused 5030965 (delta 4225531) Resolving deltas: 100% (4225582/4225582), done. Checking connectivity... done. warning: remote HEAD refers to nonexistent ref, unable to checkout. ...then the clone process failed. S: Maintained F: Documentation/devicetree/bindings/mmc/ F: drivers/mmc/ -- Best Regards Shawn Lin
Re: [PATCH v5 2/3] z3fold: remove redundant locking
On Mon, Oct 17, 2016 at 10:48 PM, Dan Streetmanwrote: > On Sat, Oct 15, 2016 at 7:59 AM, Vitaly Wool wrote: >> The per-pool z3fold spinlock should generally be taken only when >> a non-atomic pool variable is modified. There's no need to take it >> to map/unmap an object. > > no. it absolutely needs to be taken, because z3fold_compact_page > could move the middle bud's contents to the first bud, and if the > middle bud gets mapped while it's being moved really bad things will > happen. > > you can change that to a per-page lock in the z3fold_header, but some > locking needs to happen between mapping and middle bud moving (and > handle encoding/decoding and first_num access). Yep, probably per-page lock is the way to go. I was thinking of making first_num atomic but that obviously creates more problems than it solves. ~vitaly > > >> >> Signed-off-by: Vitaly Wool >> --- >> mm/z3fold.c | 17 + >> 1 file changed, 5 insertions(+), 12 deletions(-) >> >> diff --git a/mm/z3fold.c b/mm/z3fold.c >> index 5197d7b..10513b5 100644 >> --- a/mm/z3fold.c >> +++ b/mm/z3fold.c >> @@ -580,6 +580,7 @@ next: >> if ((test_bit(PAGE_HEADLESS, >private) && ret == 0) || >> (zhdr->first_chunks == 0 && zhdr->last_chunks == 0 && >> zhdr->middle_chunks == 0)) { >> + spin_unlock(>lock); >> /* >> * All buddies are now free, free the z3fold page and >> * return success. >> @@ -587,7 +588,6 @@ next: >> clear_bit(PAGE_HEADLESS, >private); >> free_z3fold_page(zhdr); >> atomic64_dec(>pages_nr); >> - spin_unlock(>lock); >> return 0; >> } else if (!test_bit(PAGE_HEADLESS, >private)) { >> if (zhdr->first_chunks != 0 && >> @@ -629,7 +629,6 @@ static void *z3fold_map(struct z3fold_pool *pool, >> unsigned long handle) >> void *addr; >> enum buddy buddy; >> >> - spin_lock(>lock); >> zhdr = handle_to_z3fold_header(handle); >> addr = zhdr; >> page = virt_to_page(zhdr); >> @@ -656,7 +655,6 @@ static void *z3fold_map(struct z3fold_pool *pool, >> unsigned long handle) >> break; >> } >> out: >> - spin_unlock(>lock); >> return addr; >> } >> >> @@ -671,19 +669,14 @@ static void z3fold_unmap(struct z3fold_pool *pool, >> unsigned long handle) >> struct page *page; >> enum buddy buddy; >> >> - spin_lock(>lock); >> zhdr = handle_to_z3fold_header(handle); >> page = virt_to_page(zhdr); >> >> - if (test_bit(PAGE_HEADLESS, >private)) { >> - spin_unlock(>lock); >> - return; >> + if (!test_bit(PAGE_HEADLESS, >private)) { >> + buddy = handle_to_buddy(handle); >> + if (buddy == MIDDLE) >> + clear_bit(MIDDLE_CHUNK_MAPPED, >private); >> } >> - >> - buddy = handle_to_buddy(handle); >> - if (buddy == MIDDLE) >> - clear_bit(MIDDLE_CHUNK_MAPPED, >private); >> - spin_unlock(>lock); >> } >> >> /** >> -- >> 2.4.2
Re: [PATCH v5 2/3] z3fold: remove redundant locking
On Mon, Oct 17, 2016 at 10:48 PM, Dan Streetman wrote: > On Sat, Oct 15, 2016 at 7:59 AM, Vitaly Wool wrote: >> The per-pool z3fold spinlock should generally be taken only when >> a non-atomic pool variable is modified. There's no need to take it >> to map/unmap an object. > > no. it absolutely needs to be taken, because z3fold_compact_page > could move the middle bud's contents to the first bud, and if the > middle bud gets mapped while it's being moved really bad things will > happen. > > you can change that to a per-page lock in the z3fold_header, but some > locking needs to happen between mapping and middle bud moving (and > handle encoding/decoding and first_num access). Yep, probably per-page lock is the way to go. I was thinking of making first_num atomic but that obviously creates more problems than it solves. ~vitaly > > >> >> Signed-off-by: Vitaly Wool >> --- >> mm/z3fold.c | 17 + >> 1 file changed, 5 insertions(+), 12 deletions(-) >> >> diff --git a/mm/z3fold.c b/mm/z3fold.c >> index 5197d7b..10513b5 100644 >> --- a/mm/z3fold.c >> +++ b/mm/z3fold.c >> @@ -580,6 +580,7 @@ next: >> if ((test_bit(PAGE_HEADLESS, >private) && ret == 0) || >> (zhdr->first_chunks == 0 && zhdr->last_chunks == 0 && >> zhdr->middle_chunks == 0)) { >> + spin_unlock(>lock); >> /* >> * All buddies are now free, free the z3fold page and >> * return success. >> @@ -587,7 +588,6 @@ next: >> clear_bit(PAGE_HEADLESS, >private); >> free_z3fold_page(zhdr); >> atomic64_dec(>pages_nr); >> - spin_unlock(>lock); >> return 0; >> } else if (!test_bit(PAGE_HEADLESS, >private)) { >> if (zhdr->first_chunks != 0 && >> @@ -629,7 +629,6 @@ static void *z3fold_map(struct z3fold_pool *pool, >> unsigned long handle) >> void *addr; >> enum buddy buddy; >> >> - spin_lock(>lock); >> zhdr = handle_to_z3fold_header(handle); >> addr = zhdr; >> page = virt_to_page(zhdr); >> @@ -656,7 +655,6 @@ static void *z3fold_map(struct z3fold_pool *pool, >> unsigned long handle) >> break; >> } >> out: >> - spin_unlock(>lock); >> return addr; >> } >> >> @@ -671,19 +669,14 @@ static void z3fold_unmap(struct z3fold_pool *pool, >> unsigned long handle) >> struct page *page; >> enum buddy buddy; >> >> - spin_lock(>lock); >> zhdr = handle_to_z3fold_header(handle); >> page = virt_to_page(zhdr); >> >> - if (test_bit(PAGE_HEADLESS, >private)) { >> - spin_unlock(>lock); >> - return; >> + if (!test_bit(PAGE_HEADLESS, >private)) { >> + buddy = handle_to_buddy(handle); >> + if (buddy == MIDDLE) >> + clear_bit(MIDDLE_CHUNK_MAPPED, >private); >> } >> - >> - buddy = handle_to_buddy(handle); >> - if (buddy == MIDDLE) >> - clear_bit(MIDDLE_CHUNK_MAPPED, >private); >> - spin_unlock(>lock); >> } >> >> /** >> -- >> 2.4.2
Re: [PATCH v2] MAINTAINERS: add myself as Marvell berlin SoC maintainer
On Thu, Sep 29, 2016 at 06:51:20PM +0800, Jisheng Zhang wrote: > I would like to take maintainership for Marvell berlin SoCs. > > Signed-off-by: Jisheng Zhang> Acked-by: Sebastian Hesselbarth Applied to fixes. Thanks. -Olof
Re: [PATCH v2] MAINTAINERS: add myself as Marvell berlin SoC maintainer
On Thu, Sep 29, 2016 at 06:51:20PM +0800, Jisheng Zhang wrote: > I would like to take maintainership for Marvell berlin SoCs. > > Signed-off-by: Jisheng Zhang > Acked-by: Sebastian Hesselbarth Applied to fixes. Thanks. -Olof
Re: [PATCH vmalloc] reduce purge_lock range and hold time of
hey Hellwig: cond_resched_lock is a good choice. i mixed the cond_resched_lock and batch to balance of realtime and performance and resubmit this patch. On 2016/10/16 0:55, Christoph Hellwig wrote: On Sat, Oct 15, 2016 at 10:12:48PM +0800, zhouxianr...@huawei.com wrote: From: z00281421i think no need to place __free_vmap_area loop in purge_lock; _free_vmap_area could be non-atomic operations with flushing tlb but must be done after flush tlb. and the whole__free_vmap_area loops also could be non-atomic operations. if so we could improve realtime because the loop times sometimes is larg and spend a few time. Right, see the previous patch in reply to Joel that drops purge_lock entirely. Instead of your open coded batch counter you probably want to add a cond_resched_lock after the call to __free_vmap_area. .
Re: [PATCH vmalloc] reduce purge_lock range and hold time of
hey Hellwig: cond_resched_lock is a good choice. i mixed the cond_resched_lock and batch to balance of realtime and performance and resubmit this patch. On 2016/10/16 0:55, Christoph Hellwig wrote: On Sat, Oct 15, 2016 at 10:12:48PM +0800, zhouxianr...@huawei.com wrote: From: z00281421 i think no need to place __free_vmap_area loop in purge_lock; _free_vmap_area could be non-atomic operations with flushing tlb but must be done after flush tlb. and the whole__free_vmap_area loops also could be non-atomic operations. if so we could improve realtime because the loop times sometimes is larg and spend a few time. Right, see the previous patch in reply to Joel that drops purge_lock entirely. Instead of your open coded batch counter you probably want to add a cond_resched_lock after the call to __free_vmap_area. .
Re: [PATCH v2 1/2] watchdog: Introduce arch_watchdog_nmi_enable and arch_watchdog_nmi_disable
Don, On 10/17/2016 12:31 PM, Don Zickus wrote: On Thu, Oct 13, 2016 at 01:38:01PM -0700, Babu Moger wrote: Currently we do not have a way to enable/disable arch specific watchdog handlers if it was implemented by any of the architectures. This patch introduces new functions arch_watchdog_nmi_enable and arch_watchdog_nmi_disable which can be used to enable/disable architecture specific NMI watchdog handlers. These functions are defined as weak as architectures can override their definitions to enable/disable nmi watchdog behaviour. Hi Babu, This patch tested fine on my x86 box and I am ok with the changes. I do have one small cosmetic request below for a failure path. Other than that I will give my ack. Yes. I am testing these changes. If everything goes as expected, I will post v3 version tomorrow. Thanks Babu Cheers, Don Signed-off-by: Babu Moger--- kernel/watchdog.c | 65 +++- 1 files changed, 44 insertions(+), 21 deletions(-) diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 9acb29f..d1e84e6 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -46,7 +46,7 @@ static DEFINE_MUTEX(watchdog_proc_mutex); -#ifdef CONFIG_HARDLOCKUP_DETECTOR +#if defined(CONFIG_HARDLOCKUP_DETECTOR) || defined(CONFIG_HAVE_NMI_WATCHDOG) static unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED|NMI_WATCHDOG_ENABLED; #else static unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED; @@ -585,15 +585,11 @@ static void watchdog(unsigned int cpu) */ static unsigned long cpu0_err; -static int watchdog_nmi_enable(unsigned int cpu) +static int arch_watchdog_nmi_enable(unsigned int cpu) { struct perf_event_attr *wd_attr; struct perf_event *event = per_cpu(watchdog_ev, cpu); - /* nothing to do if the hard lockup detector is disabled */ - if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED)) - goto out; - /* is it already setup and enabled? */ if (event && event->state > PERF_EVENT_STATE_OFF) goto out; @@ -619,18 +615,6 @@ static int watchdog_nmi_enable(unsigned int cpu) goto out_save; } - /* -* Disable the hard lockup detector if _any_ CPU fails to set up -* set up the hardware perf event. The watchdog() function checks -* the NMI_WATCHDOG_ENABLED bit periodically. -* -* The barriers are for syncing up watchdog_enabled across all the -* cpus, as clear_bit() does not use barriers. -*/ - smp_mb__before_atomic(); - clear_bit(NMI_WATCHDOG_ENABLED_BIT, _enabled); - smp_mb__after_atomic(); - /* skip displaying the same error again */ if (cpu > 0 && (PTR_ERR(event) == cpu0_err)) return PTR_ERR(event); In the arch_watchdog_nmi_enable code is a pr_info on failure pr_info("Shutting down hard lockup detector on all cpus\n"); that should be moved to below.. @@ -658,7 +642,7 @@ out: return 0; } -static void watchdog_nmi_disable(unsigned int cpu) +static void arch_watchdog_nmi_disable(unsigned int cpu) { struct perf_event *event = per_cpu(watchdog_ev, cpu); @@ -676,8 +660,13 @@ static void watchdog_nmi_disable(unsigned int cpu) } #else -static int watchdog_nmi_enable(unsigned int cpu) { return 0; } -static void watchdog_nmi_disable(unsigned int cpu) { return; } +/* + * These two functions are mostly architecture specific + * defining them as weak here. + */ +int __weak arch_watchdog_nmi_enable(unsigned int cpu) { return 0; } +void __weak arch_watchdog_nmi_disable(unsigned int cpu) { return; } + #endif /* CONFIG_HARDLOCKUP_DETECTOR */ static struct smp_hotplug_thread watchdog_threads = { @@ -781,6 +770,40 @@ void lockup_detector_resume(void) put_online_cpus(); } +void watchdog_nmi_disable(unsigned int cpu) +{ + arch_watchdog_nmi_disable(cpu); +} + +int watchdog_nmi_enable(unsigned int cpu) +{ + int err; + + /* nothing to do if the hard lockup detector is disabled */ + if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED)) + return 0; + + err = arch_watchdog_nmi_enable(cpu); + + if (err) { + /* +* Disable the hard lockup detector if _any_ CPU fails to set up +* set up the hardware perf event. The watchdog() function checks +* the NMI_WATCHDOG_ENABLED bit periodically. +* +* The barriers are for syncing up watchdog_enabled across all the +* cpus, as clear_bit() does not use barriers. +*/ + smp_mb__before_atomic(); + clear_bit(NMI_WATCHDOG_ENABLED_BIT, _enabled); + smp_mb__after_atomic(); moved to here: pr_info("Shutting down hard lockup detector on all cpus\n"); This lets the failure message be
Re: [PATCH v2 1/2] watchdog: Introduce arch_watchdog_nmi_enable and arch_watchdog_nmi_disable
Don, On 10/17/2016 12:31 PM, Don Zickus wrote: On Thu, Oct 13, 2016 at 01:38:01PM -0700, Babu Moger wrote: Currently we do not have a way to enable/disable arch specific watchdog handlers if it was implemented by any of the architectures. This patch introduces new functions arch_watchdog_nmi_enable and arch_watchdog_nmi_disable which can be used to enable/disable architecture specific NMI watchdog handlers. These functions are defined as weak as architectures can override their definitions to enable/disable nmi watchdog behaviour. Hi Babu, This patch tested fine on my x86 box and I am ok with the changes. I do have one small cosmetic request below for a failure path. Other than that I will give my ack. Yes. I am testing these changes. If everything goes as expected, I will post v3 version tomorrow. Thanks Babu Cheers, Don Signed-off-by: Babu Moger --- kernel/watchdog.c | 65 +++- 1 files changed, 44 insertions(+), 21 deletions(-) diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 9acb29f..d1e84e6 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -46,7 +46,7 @@ static DEFINE_MUTEX(watchdog_proc_mutex); -#ifdef CONFIG_HARDLOCKUP_DETECTOR +#if defined(CONFIG_HARDLOCKUP_DETECTOR) || defined(CONFIG_HAVE_NMI_WATCHDOG) static unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED|NMI_WATCHDOG_ENABLED; #else static unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED; @@ -585,15 +585,11 @@ static void watchdog(unsigned int cpu) */ static unsigned long cpu0_err; -static int watchdog_nmi_enable(unsigned int cpu) +static int arch_watchdog_nmi_enable(unsigned int cpu) { struct perf_event_attr *wd_attr; struct perf_event *event = per_cpu(watchdog_ev, cpu); - /* nothing to do if the hard lockup detector is disabled */ - if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED)) - goto out; - /* is it already setup and enabled? */ if (event && event->state > PERF_EVENT_STATE_OFF) goto out; @@ -619,18 +615,6 @@ static int watchdog_nmi_enable(unsigned int cpu) goto out_save; } - /* -* Disable the hard lockup detector if _any_ CPU fails to set up -* set up the hardware perf event. The watchdog() function checks -* the NMI_WATCHDOG_ENABLED bit periodically. -* -* The barriers are for syncing up watchdog_enabled across all the -* cpus, as clear_bit() does not use barriers. -*/ - smp_mb__before_atomic(); - clear_bit(NMI_WATCHDOG_ENABLED_BIT, _enabled); - smp_mb__after_atomic(); - /* skip displaying the same error again */ if (cpu > 0 && (PTR_ERR(event) == cpu0_err)) return PTR_ERR(event); In the arch_watchdog_nmi_enable code is a pr_info on failure pr_info("Shutting down hard lockup detector on all cpus\n"); that should be moved to below.. @@ -658,7 +642,7 @@ out: return 0; } -static void watchdog_nmi_disable(unsigned int cpu) +static void arch_watchdog_nmi_disable(unsigned int cpu) { struct perf_event *event = per_cpu(watchdog_ev, cpu); @@ -676,8 +660,13 @@ static void watchdog_nmi_disable(unsigned int cpu) } #else -static int watchdog_nmi_enable(unsigned int cpu) { return 0; } -static void watchdog_nmi_disable(unsigned int cpu) { return; } +/* + * These two functions are mostly architecture specific + * defining them as weak here. + */ +int __weak arch_watchdog_nmi_enable(unsigned int cpu) { return 0; } +void __weak arch_watchdog_nmi_disable(unsigned int cpu) { return; } + #endif /* CONFIG_HARDLOCKUP_DETECTOR */ static struct smp_hotplug_thread watchdog_threads = { @@ -781,6 +770,40 @@ void lockup_detector_resume(void) put_online_cpus(); } +void watchdog_nmi_disable(unsigned int cpu) +{ + arch_watchdog_nmi_disable(cpu); +} + +int watchdog_nmi_enable(unsigned int cpu) +{ + int err; + + /* nothing to do if the hard lockup detector is disabled */ + if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED)) + return 0; + + err = arch_watchdog_nmi_enable(cpu); + + if (err) { + /* +* Disable the hard lockup detector if _any_ CPU fails to set up +* set up the hardware perf event. The watchdog() function checks +* the NMI_WATCHDOG_ENABLED bit periodically. +* +* The barriers are for syncing up watchdog_enabled across all the +* cpus, as clear_bit() does not use barriers. +*/ + smp_mb__before_atomic(); + clear_bit(NMI_WATCHDOG_ENABLED_BIT, _enabled); + smp_mb__after_atomic(); moved to here: pr_info("Shutting down hard lockup detector on all cpus\n"); This lets the failure message be displayed on all arches
Re: [PATCH v5 3/3] z3fold: add shrinker
Hi Dan, On Tue, Oct 18, 2016 at 4:06 AM, Dan Streetmanwrote: > On Sat, Oct 15, 2016 at 8:05 AM, Vitaly Wool wrote: >> This patch implements shrinker for z3fold. This shrinker >> implementation does not free up any pages directly but it allows >> for a denser placement of compressed objects which results in >> less actual pages consumed and higher compression ratio therefore. >> >> This update removes z3fold page compaction from the freeing path >> since we can rely on shrinker to do the job. Also, a new flag >> UNDER_COMPACTION is introduced to protect against two threads >> trying to compact the same page. > > i'm completely unconvinced that this should be a shrinker. The > alloc/free paths are much, much better suited to compacting a page > than a shrinker that must scan through all the unbuddied pages. Why > not just improve compaction for the alloc/free paths? Basically the main reason is performance, I want to avoid compaction on hot paths as much as possible. This patchset brings both performance and compression ratio gain, I'm not sure how to achieve that with improving compaction on alloc/free paths. > >> >> This patch has been checked with the latest Linus's tree. >> >> Signed-off-by: Vitaly Wool >> --- >> mm/z3fold.c | 144 >> +--- >> 1 file changed, 119 insertions(+), 25 deletions(-) >> >> diff --git a/mm/z3fold.c b/mm/z3fold.c >> index 10513b5..8f84d3c 100644 >> --- a/mm/z3fold.c >> +++ b/mm/z3fold.c >> @@ -27,6 +27,7 @@ >> #include >> #include >> #include >> +#include >> #include >> #include >> #include >> @@ -72,6 +73,7 @@ struct z3fold_ops { >> * @unbuddied_nr: number of unbuddied z3fold pages in the pool. >> * @ops: pointer to a structure of user defined operations specified >> at >> * pool creation time. >> + * @shrinker: shrinker structure to optimize page layout in background >> * >> * This structure is allocated at pool creation time and maintains metadata >> * pertaining to a particular z3fold pool. >> @@ -86,6 +88,7 @@ struct z3fold_pool { >> const struct z3fold_ops *ops; >> struct zpool *zpool; >> const struct zpool_ops *zpool_ops; >> + struct shrinker shrinker; >> }; >> >> enum buddy { >> @@ -121,6 +124,7 @@ enum z3fold_page_flags { >> UNDER_RECLAIM = 0, >> PAGE_HEADLESS, >> MIDDLE_CHUNK_MAPPED, >> + UNDER_COMPACTION, >> }; >> >> /* >> @@ -136,6 +140,9 @@ static int size_to_chunks(size_t size) >> #define for_each_unbuddied_list(_iter, _begin) \ >> for ((_iter) = (_begin); (_iter) < NCHUNKS; (_iter)++) >> >> +#define for_each_unbuddied_list_down(_iter, _end) \ >> + for ((_iter) = (_end); (_iter) > 0; (_iter)--) >> + > > bikeshed: the conventional suffix is _reverse, not _down, i.e. > for_each_unbuddied_list_reverse() Ok :) >> /* Initializes the z3fold header of a newly allocated z3fold page */ >> static struct z3fold_header *init_z3fold_page(struct page *page) >> { >> @@ -145,6 +152,7 @@ static struct z3fold_header *init_z3fold_page(struct >> page *page) >> clear_bit(UNDER_RECLAIM, >private); >> clear_bit(PAGE_HEADLESS, >private); >> clear_bit(MIDDLE_CHUNK_MAPPED, >private); >> + clear_bit(UNDER_COMPACTION, >private); >> >> zhdr->first_chunks = 0; >> zhdr->middle_chunks = 0; >> @@ -211,6 +219,103 @@ static int num_free_chunks(struct z3fold_header *zhdr) >> return nfree; >> } >> >> +/* Has to be called with lock held */ >> +static int z3fold_compact_page(struct z3fold_header *zhdr, bool sync) >> +{ >> + struct page *page = virt_to_page(zhdr); >> + void *beg = zhdr; >> + >> + >> + if (!test_bit(MIDDLE_CHUNK_MAPPED, >private) && >> + !test_bit(UNDER_RECLAIM, >private) && >> + !test_bit(UNDER_COMPACTION, >private)) { >> + set_bit(UNDER_COMPACTION, >private); > > i assume the reclaim check, and new compaction bit check, is due to > the removal of the spinlock, which was incorrect. changing to a > per-page spinlock may be the best way to handle this, but flags are > absolutely not appropriate - they don't provide the needed locking. > Even if the compaction bit was the only locking needed (which it > isn't), it still isn't correct here - while extremely unlikely, it's > still possible for multiple threads to race between checking the > compaction bit, and setting it. That's what test_and_set_bit() is > for. Yep, thanks, will fix that. > >> + if (zhdr->middle_chunks != 0 && > > only need to check if the middle bud is in use once; if it isn't, > there's no compaction to do. > >> + zhdr->first_chunks == 0 && >> + zhdr->last_chunks == 0) { >> + memmove(beg + ZHDR_SIZE_ALIGNED, >> + beg + (zhdr->start_middle
Re: [PATCH v5 3/3] z3fold: add shrinker
Hi Dan, On Tue, Oct 18, 2016 at 4:06 AM, Dan Streetman wrote: > On Sat, Oct 15, 2016 at 8:05 AM, Vitaly Wool wrote: >> This patch implements shrinker for z3fold. This shrinker >> implementation does not free up any pages directly but it allows >> for a denser placement of compressed objects which results in >> less actual pages consumed and higher compression ratio therefore. >> >> This update removes z3fold page compaction from the freeing path >> since we can rely on shrinker to do the job. Also, a new flag >> UNDER_COMPACTION is introduced to protect against two threads >> trying to compact the same page. > > i'm completely unconvinced that this should be a shrinker. The > alloc/free paths are much, much better suited to compacting a page > than a shrinker that must scan through all the unbuddied pages. Why > not just improve compaction for the alloc/free paths? Basically the main reason is performance, I want to avoid compaction on hot paths as much as possible. This patchset brings both performance and compression ratio gain, I'm not sure how to achieve that with improving compaction on alloc/free paths. > >> >> This patch has been checked with the latest Linus's tree. >> >> Signed-off-by: Vitaly Wool >> --- >> mm/z3fold.c | 144 >> +--- >> 1 file changed, 119 insertions(+), 25 deletions(-) >> >> diff --git a/mm/z3fold.c b/mm/z3fold.c >> index 10513b5..8f84d3c 100644 >> --- a/mm/z3fold.c >> +++ b/mm/z3fold.c >> @@ -27,6 +27,7 @@ >> #include >> #include >> #include >> +#include >> #include >> #include >> #include >> @@ -72,6 +73,7 @@ struct z3fold_ops { >> * @unbuddied_nr: number of unbuddied z3fold pages in the pool. >> * @ops: pointer to a structure of user defined operations specified >> at >> * pool creation time. >> + * @shrinker: shrinker structure to optimize page layout in background >> * >> * This structure is allocated at pool creation time and maintains metadata >> * pertaining to a particular z3fold pool. >> @@ -86,6 +88,7 @@ struct z3fold_pool { >> const struct z3fold_ops *ops; >> struct zpool *zpool; >> const struct zpool_ops *zpool_ops; >> + struct shrinker shrinker; >> }; >> >> enum buddy { >> @@ -121,6 +124,7 @@ enum z3fold_page_flags { >> UNDER_RECLAIM = 0, >> PAGE_HEADLESS, >> MIDDLE_CHUNK_MAPPED, >> + UNDER_COMPACTION, >> }; >> >> /* >> @@ -136,6 +140,9 @@ static int size_to_chunks(size_t size) >> #define for_each_unbuddied_list(_iter, _begin) \ >> for ((_iter) = (_begin); (_iter) < NCHUNKS; (_iter)++) >> >> +#define for_each_unbuddied_list_down(_iter, _end) \ >> + for ((_iter) = (_end); (_iter) > 0; (_iter)--) >> + > > bikeshed: the conventional suffix is _reverse, not _down, i.e. > for_each_unbuddied_list_reverse() Ok :) >> /* Initializes the z3fold header of a newly allocated z3fold page */ >> static struct z3fold_header *init_z3fold_page(struct page *page) >> { >> @@ -145,6 +152,7 @@ static struct z3fold_header *init_z3fold_page(struct >> page *page) >> clear_bit(UNDER_RECLAIM, >private); >> clear_bit(PAGE_HEADLESS, >private); >> clear_bit(MIDDLE_CHUNK_MAPPED, >private); >> + clear_bit(UNDER_COMPACTION, >private); >> >> zhdr->first_chunks = 0; >> zhdr->middle_chunks = 0; >> @@ -211,6 +219,103 @@ static int num_free_chunks(struct z3fold_header *zhdr) >> return nfree; >> } >> >> +/* Has to be called with lock held */ >> +static int z3fold_compact_page(struct z3fold_header *zhdr, bool sync) >> +{ >> + struct page *page = virt_to_page(zhdr); >> + void *beg = zhdr; >> + >> + >> + if (!test_bit(MIDDLE_CHUNK_MAPPED, >private) && >> + !test_bit(UNDER_RECLAIM, >private) && >> + !test_bit(UNDER_COMPACTION, >private)) { >> + set_bit(UNDER_COMPACTION, >private); > > i assume the reclaim check, and new compaction bit check, is due to > the removal of the spinlock, which was incorrect. changing to a > per-page spinlock may be the best way to handle this, but flags are > absolutely not appropriate - they don't provide the needed locking. > Even if the compaction bit was the only locking needed (which it > isn't), it still isn't correct here - while extremely unlikely, it's > still possible for multiple threads to race between checking the > compaction bit, and setting it. That's what test_and_set_bit() is > for. Yep, thanks, will fix that. > >> + if (zhdr->middle_chunks != 0 && > > only need to check if the middle bud is in use once; if it isn't, > there's no compaction to do. > >> + zhdr->first_chunks == 0 && >> + zhdr->last_chunks == 0) { >> + memmove(beg + ZHDR_SIZE_ALIGNED, >> + beg + (zhdr->start_middle << CHUNK_SHIFT), >> +
Re: [PATCH v4] usb: dwc3: Wait for control tranfer completed when stopping gadget
Hi, On 17 October 2016 at 19:53, Felipe Balbiwrote: > > Hi, > > Baolin Wang writes: >>> Baolin Wang writes: When we change the USB function with configfs dynamically, we possibly met this situation: one core is doing the control transfer, another core is trying to unregister the USB gadget from userspace, we must wait for completing this control tranfer, or it will hang the controller to set the DEVCTRLHLT flag. Signed-off-by: Baolin Wang >>> >>> Can you make sure this still works? >> >> With applying this patch, It can work well on my platform, but I have >> some worries about the risk of accessing 'dwc->ep0state' without lock >> protection in dwc3_gadget_pullup() function. > > hmm, I might be missing something, but I think there's no risk here. If > anything, a wmb() is probably enough before reading ep0state. No? OK, I agree with you and I think a wmb() is not useful here. -- Baolin.wang Best Regards
Re: [PATCH v4] usb: dwc3: Wait for control tranfer completed when stopping gadget
Hi, On 17 October 2016 at 19:53, Felipe Balbi wrote: > > Hi, > > Baolin Wang writes: >>> Baolin Wang writes: When we change the USB function with configfs dynamically, we possibly met this situation: one core is doing the control transfer, another core is trying to unregister the USB gadget from userspace, we must wait for completing this control tranfer, or it will hang the controller to set the DEVCTRLHLT flag. Signed-off-by: Baolin Wang >>> >>> Can you make sure this still works? >> >> With applying this patch, It can work well on my platform, but I have >> some worries about the risk of accessing 'dwc->ep0state' without lock >> protection in dwc3_gadget_pullup() function. > > hmm, I might be missing something, but I think there's no risk here. If > anything, a wmb() is probably enough before reading ep0state. No? OK, I agree with you and I think a wmb() is not useful here. -- Baolin.wang Best Regards
Re: Oops on Power8 (was Re: [PATCH v2 1/7] workqueue: make workqueue available early during boot)
Balbir Singhwrites: > On 17/10/16 23:24, Michael Ellerman wrote: >> That happened because we haven't yet called set_cpu_numa_node() for the >> non-boot >> cpus, because that happens in smp_prepare_cpus(), and >> workqueue_init_early() is called much earlier than that. >> >> This doesn't trigger on x86 because it does set_cpu_numa_node() in >> setup_per_cpu_areas(), which is called prior to workqueue_init_early(). >> >> We can (should) probably do the same on powerpc, I'll look at that >> tomorrow. But other arches may have a similar problem, and at the very >> least we need to document that workqueue_init_early() relies on >> cpu_to_node() working. > > Don't we do the setup cpu->node mapings in initmem_init()? > Ideally we have setup_arch->intmem_init->numa_setup_cpu That sets up numa_cpu_lookup_table, which is a powerpc only data structure. But it doesn't setup the percpu numa_node variables, used by cpu_to_node(), because percpu areas are not setup yet. cheers
Re: Oops on Power8 (was Re: [PATCH v2 1/7] workqueue: make workqueue available early during boot)
Balbir Singh writes: > On 17/10/16 23:24, Michael Ellerman wrote: >> That happened because we haven't yet called set_cpu_numa_node() for the >> non-boot >> cpus, because that happens in smp_prepare_cpus(), and >> workqueue_init_early() is called much earlier than that. >> >> This doesn't trigger on x86 because it does set_cpu_numa_node() in >> setup_per_cpu_areas(), which is called prior to workqueue_init_early(). >> >> We can (should) probably do the same on powerpc, I'll look at that >> tomorrow. But other arches may have a similar problem, and at the very >> least we need to document that workqueue_init_early() relies on >> cpu_to_node() working. > > Don't we do the setup cpu->node mapings in initmem_init()? > Ideally we have setup_arch->intmem_init->numa_setup_cpu That sets up numa_cpu_lookup_table, which is a powerpc only data structure. But it doesn't setup the percpu numa_node variables, used by cpu_to_node(), because percpu areas are not setup yet. cheers
[PATCH vmalloc] reduce purge_lock range and hold time of vmap_area_lock
From: z00281421Signed-off-by: z00281421 --- mm/vmalloc.c |9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 91f44e7..e9c9c04 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -661,13 +661,18 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end, if (nr || force_flush) flush_tlb_kernel_range(*start, *end); + spin_unlock(_lock); + if (nr) { + unsigned char batch = 0; spin_lock(_area_lock); - llist_for_each_entry_safe(va, n_va, valist, purge_list) + llist_for_each_entry_safe(va, n_va, valist, purge_list) { __free_vmap_area(va); + if (!batch++) + cond_resched_lock(_area_lock); + } spin_unlock(_area_lock); } - spin_unlock(_lock); } /* -- 1.7.9.5
[PATCH vmalloc] reduce purge_lock range and hold time of vmap_area_lock
From: z00281421 Signed-off-by: z00281421 --- mm/vmalloc.c |9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 91f44e7..e9c9c04 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -661,13 +661,18 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end, if (nr || force_flush) flush_tlb_kernel_range(*start, *end); + spin_unlock(_lock); + if (nr) { + unsigned char batch = 0; spin_lock(_area_lock); - llist_for_each_entry_safe(va, n_va, valist, purge_list) + llist_for_each_entry_safe(va, n_va, valist, purge_list) { __free_vmap_area(va); + if (!batch++) + cond_resched_lock(_area_lock); + } spin_unlock(_area_lock); } - spin_unlock(_lock); } /* -- 1.7.9.5
Re: [PATCH] staging: dgnc: Replace CamelCase namings with underscores.
On Mon, Oct 17, 2016 at 1:16 PM, Greg KHwrote: > > On Mon, Oct 17, 2016 at 01:13:55AM +0530, Pankaj Bharadiya wrote: > > Replace CamelCase names with underscores to comply with the standard > > kernel coding style. > > > > Signed-off-by: Pankaj Bharadiya > > --- > > drivers/staging/dgnc/dgnc_tty.c | 20 ++-- > > 1 file changed, 10 insertions(+), 10 deletions(-) > > > > diff --git a/drivers/staging/dgnc/dgnc_tty.c > > b/drivers/staging/dgnc/dgnc_tty.c > > index ef9a45b..1a21902 100644 > > --- a/drivers/staging/dgnc/dgnc_tty.c > > +++ b/drivers/staging/dgnc/dgnc_tty.c > > @@ -45,7 +45,7 @@ > > /* > > * internal variables > > */ > > -static unsigned char *dgnc_TmpWriteBuf; > > +static unsigned char *dgnc_tmp_write_buf; > > Why not just fix the code to not have this variable at all? It's not > correct to have it from what I can tell... > > Also, you modify many different variables all at once, can you please > just modify one at a time (one per patch), to make it more obvious it is > correct? > > > /* > > * Default transparent print information. > > @@ -69,7 +69,7 @@ > > * This defines a raw port at 9600 baud, 8 data bits, no parity, > > * 1 stop bit. > > */ > > -static struct ktermios DgncDefaultTermios = { > > +static struct ktermios dgnc_default_termios = { > > rename to "default_termios"? > > No need to keep the driver name prefix on a static variable, right? > Hi Greg, Thank you for your comments. I have submitted v2 patchset. I hope that makes more sense now. Thanks, Pankaj > thanks, > > greg k-h
Re: [PATCH] staging: dgnc: Replace CamelCase namings with underscores.
On Mon, Oct 17, 2016 at 1:16 PM, Greg KH wrote: > > On Mon, Oct 17, 2016 at 01:13:55AM +0530, Pankaj Bharadiya wrote: > > Replace CamelCase names with underscores to comply with the standard > > kernel coding style. > > > > Signed-off-by: Pankaj Bharadiya > > --- > > drivers/staging/dgnc/dgnc_tty.c | 20 ++-- > > 1 file changed, 10 insertions(+), 10 deletions(-) > > > > diff --git a/drivers/staging/dgnc/dgnc_tty.c > > b/drivers/staging/dgnc/dgnc_tty.c > > index ef9a45b..1a21902 100644 > > --- a/drivers/staging/dgnc/dgnc_tty.c > > +++ b/drivers/staging/dgnc/dgnc_tty.c > > @@ -45,7 +45,7 @@ > > /* > > * internal variables > > */ > > -static unsigned char *dgnc_TmpWriteBuf; > > +static unsigned char *dgnc_tmp_write_buf; > > Why not just fix the code to not have this variable at all? It's not > correct to have it from what I can tell... > > Also, you modify many different variables all at once, can you please > just modify one at a time (one per patch), to make it more obvious it is > correct? > > > /* > > * Default transparent print information. > > @@ -69,7 +69,7 @@ > > * This defines a raw port at 9600 baud, 8 data bits, no parity, > > * 1 stop bit. > > */ > > -static struct ktermios DgncDefaultTermios = { > > +static struct ktermios dgnc_default_termios = { > > rename to "default_termios"? > > No need to keep the driver name prefix on a static variable, right? > Hi Greg, Thank you for your comments. I have submitted v2 patchset. I hope that makes more sense now. Thanks, Pankaj > thanks, > > greg k-h
linux-next: Tree for Oct 18
Hi all, Changes since 20161017: The drm-intel tree gained build failures so I used the version from next-20161017. The akpm-current tree still had its build failures for which I applied 2 patches. Non-merge commits (relative to Linus' tree): 910 1213 files changed, 32579 insertions(+), 17418 deletions(-) I have created today's linux-next tree at git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git (patches at http://www.kernel.org/pub/linux/kernel/next/ ). If you are tracking the linux-next tree using git, you should not use "git pull" to do so as that will try to merge the new linux-next release with the old one. You should use "git fetch" and checkout or reset to the new master. You can see which trees have been included by looking in the Next/Trees file in the source. There are also quilt-import.log and merge.log files in the Next directory. Between each merge, the tree was built with a ppc64_defconfig for powerpc and an allmodconfig (with CONFIG_BUILD_DOCSRC=n) for x86_64, a multi_v7_defconfig for arm and a native build of tools/perf. After the final fixups (if any), I do an x86_64 modules_install followed by builds for x86_64 allnoconfig, powerpc allnoconfig (32 and 64 bit), ppc44x_defconfig, allyesconfig (this fails its final link) and pseries_le_defconfig and i386, sparc and sparc64 defconfig. Below is a summary of the state of the merge. I am currently merging 243 trees (counting Linus' and 34 trees of patches pending for Linus' tree). Stats about the size of the tree over time can be seen at http://neuling.org/linux-next-size.html . Status of my local build tests will be at http://kisskb.ellerman.id.au/linux-next . If maintainers want to give advice about cross compilers/configs that work, we are always open to add more builds. Thanks to Randy Dunlap for doing many randconfig builds. And to Paul Gortmaker for triage and bug fixes. -- Cheers, Stephen Rothwell $ git checkout master $ git reset --hard stable Merging origin/master (1001354ca341 Linux 4.9-rc1) Merging fixes/master (30066ce675d3 Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6) Merging kbuild-current/rc-fixes (d3e2773c4ede builddeb: Skip gcc-plugins when not configured) Merging arc-current/for-curr (27f3d2a3b59f ARC: [build] Support gz, lzma compressed uImage) Merging arm-current/fixes (fb833b1fbb68 ARM: fix delays) Merging m68k-current/for-linus (6736e65effc3 m68k: Migrate exception table users off module.h and onto extable.h) Merging metag-fixes/fixes (35d04077ad96 metag: Only define atomic_dec_if_positive conditionally) Merging powerpc-fixes/fixes (b79331a5eb9f powerpc/powernv/pci: Fix m64 checks for SR-IOV and window alignment) Merging sparc/master (4c1fad64eff4 Merge tag 'for-f2fs-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs) Merging net/master (3dfcb4f56f35 Merge branch 'net-driver-autoload') CONFLICT (content): Merge conflict in drivers/net/ethernet/qlogic/Kconfig Applying: qed*: merge fix for CONFIG_INFINIBAND_QEDR Kconfig move Merging ipsec/master (7f92083eb58f vti6: flush x-netns xfrm cache when vti interface is removed) Merging netfilter/master (6d3a4c404648 strparser: Propagate correct error code in strp_recv()) Merging ipvs/master (ea43f860d984 Merge branch 'ethoc-fixes') Merging wireless-drivers/master (1ea2643961b0 ath6kl: add Dell OEM SDIO I/O for the Venue 8 Pro) Merging mac80211/master (f4a067f9ffca mac80211: move struct aead_req off the stack) Merging sound-current/for-linus (fdd8218d7d1b ALSA: line6: fix a crash in line6_hwdep_write()) Merging pci-current/for-linus (15480f3ab7a8 PCI: layerscape: Fix drvdata usage before assignment) Merging driver-core.current/driver-core-linus (1001354ca341 Linux 4.9-rc1) Merging tty.current/tty-linus (1001354ca341 Linux 4.9-rc1) Merging usb.current/usb-linus (a19b882c07a6 wusb: Stop using the stack for sg crypto scratch space) Merging usb-gadget-fixes/fixes (1001354ca341 Linux 4.9-rc1) Merging usb-serial-fixes/usb-linus (ca006f785fbf USB: serial: ftdi_sio: add support for Infineon TriBoard TC2X7) Merging usb-chipidea-fixes/ci-for-usb-stable (6b7f456e67a1 usb: chipidea: host: fix NULL ptr dereference during shutdown) Merging staging.current/staging-linus (c89d98e224b4 staging/lustre/llite: Move unstable_stats from sysfs to debugfs) Merging char-misc.current/char-misc-linus (1001354ca341 Linux 4.9-rc1) Merging input-current/for-linus (1134ca268e73 Merge branch 'next' into for-linus) Merging crypto-current/master (c3afafa47898 Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6) Merging ide/master (797cee982eef Merge branch 'stable-4.8' of git://git.infradead.org/users/pcmoore/audit) Merging rr-fixes/fixes (8244062ef1e5 modules: fix longstanding /proc/kallsyms vs module insertion race.) Merging vfio-fixes/for-linus (c8952a707556 vfio/pci: Fix NULL po
linux-next: Tree for Oct 18
Hi all, Changes since 20161017: The drm-intel tree gained build failures so I used the version from next-20161017. The akpm-current tree still had its build failures for which I applied 2 patches. Non-merge commits (relative to Linus' tree): 910 1213 files changed, 32579 insertions(+), 17418 deletions(-) I have created today's linux-next tree at git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git (patches at http://www.kernel.org/pub/linux/kernel/next/ ). If you are tracking the linux-next tree using git, you should not use "git pull" to do so as that will try to merge the new linux-next release with the old one. You should use "git fetch" and checkout or reset to the new master. You can see which trees have been included by looking in the Next/Trees file in the source. There are also quilt-import.log and merge.log files in the Next directory. Between each merge, the tree was built with a ppc64_defconfig for powerpc and an allmodconfig (with CONFIG_BUILD_DOCSRC=n) for x86_64, a multi_v7_defconfig for arm and a native build of tools/perf. After the final fixups (if any), I do an x86_64 modules_install followed by builds for x86_64 allnoconfig, powerpc allnoconfig (32 and 64 bit), ppc44x_defconfig, allyesconfig (this fails its final link) and pseries_le_defconfig and i386, sparc and sparc64 defconfig. Below is a summary of the state of the merge. I am currently merging 243 trees (counting Linus' and 34 trees of patches pending for Linus' tree). Stats about the size of the tree over time can be seen at http://neuling.org/linux-next-size.html . Status of my local build tests will be at http://kisskb.ellerman.id.au/linux-next . If maintainers want to give advice about cross compilers/configs that work, we are always open to add more builds. Thanks to Randy Dunlap for doing many randconfig builds. And to Paul Gortmaker for triage and bug fixes. -- Cheers, Stephen Rothwell $ git checkout master $ git reset --hard stable Merging origin/master (1001354ca341 Linux 4.9-rc1) Merging fixes/master (30066ce675d3 Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6) Merging kbuild-current/rc-fixes (d3e2773c4ede builddeb: Skip gcc-plugins when not configured) Merging arc-current/for-curr (27f3d2a3b59f ARC: [build] Support gz, lzma compressed uImage) Merging arm-current/fixes (fb833b1fbb68 ARM: fix delays) Merging m68k-current/for-linus (6736e65effc3 m68k: Migrate exception table users off module.h and onto extable.h) Merging metag-fixes/fixes (35d04077ad96 metag: Only define atomic_dec_if_positive conditionally) Merging powerpc-fixes/fixes (b79331a5eb9f powerpc/powernv/pci: Fix m64 checks for SR-IOV and window alignment) Merging sparc/master (4c1fad64eff4 Merge tag 'for-f2fs-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs) Merging net/master (3dfcb4f56f35 Merge branch 'net-driver-autoload') CONFLICT (content): Merge conflict in drivers/net/ethernet/qlogic/Kconfig Applying: qed*: merge fix for CONFIG_INFINIBAND_QEDR Kconfig move Merging ipsec/master (7f92083eb58f vti6: flush x-netns xfrm cache when vti interface is removed) Merging netfilter/master (6d3a4c404648 strparser: Propagate correct error code in strp_recv()) Merging ipvs/master (ea43f860d984 Merge branch 'ethoc-fixes') Merging wireless-drivers/master (1ea2643961b0 ath6kl: add Dell OEM SDIO I/O for the Venue 8 Pro) Merging mac80211/master (f4a067f9ffca mac80211: move struct aead_req off the stack) Merging sound-current/for-linus (fdd8218d7d1b ALSA: line6: fix a crash in line6_hwdep_write()) Merging pci-current/for-linus (15480f3ab7a8 PCI: layerscape: Fix drvdata usage before assignment) Merging driver-core.current/driver-core-linus (1001354ca341 Linux 4.9-rc1) Merging tty.current/tty-linus (1001354ca341 Linux 4.9-rc1) Merging usb.current/usb-linus (a19b882c07a6 wusb: Stop using the stack for sg crypto scratch space) Merging usb-gadget-fixes/fixes (1001354ca341 Linux 4.9-rc1) Merging usb-serial-fixes/usb-linus (ca006f785fbf USB: serial: ftdi_sio: add support for Infineon TriBoard TC2X7) Merging usb-chipidea-fixes/ci-for-usb-stable (6b7f456e67a1 usb: chipidea: host: fix NULL ptr dereference during shutdown) Merging staging.current/staging-linus (c89d98e224b4 staging/lustre/llite: Move unstable_stats from sysfs to debugfs) Merging char-misc.current/char-misc-linus (1001354ca341 Linux 4.9-rc1) Merging input-current/for-linus (1134ca268e73 Merge branch 'next' into for-linus) Merging crypto-current/master (c3afafa47898 Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6) Merging ide/master (797cee982eef Merge branch 'stable-4.8' of git://git.infradead.org/users/pcmoore/audit) Merging rr-fixes/fixes (8244062ef1e5 modules: fix longstanding /proc/kallsyms vs module insertion race.) Merging vfio-fixes/for-linus (c8952a707556 vfio/pci: Fix NULL po
Re: [PATCH v3] time: alarmtimer: Add the trcepoints for alarmtimer
On 18 October 2016 at 03:03, Steven Rostedtwrote: > On Tue, 11 Oct 2016 18:48:16 +0800 > Baolin Wang wrote: > >> --- >> Changes since v2: >> - Save time as s64 type. >> - Remove 'process_name' parameter and add 'now' parameter. >> - Rename the trace event name. >> - Remove restart trace event. >> - Other optimization. >> --- >> include/trace/events/alarmtimer.h | 92 >> + >> kernel/time/alarmtimer.c | 16 ++- >> 2 files changed, 106 insertions(+), 2 deletions(-) >> create mode 100644 include/trace/events/alarmtimer.h >> >> diff --git a/include/trace/events/alarmtimer.h >> b/include/trace/events/alarmtimer.h >> new file mode 100644 >> index 000..4c92a3e >> --- /dev/null >> +++ b/include/trace/events/alarmtimer.h >> @@ -0,0 +1,92 @@ >> +#undef TRACE_SYSTEM >> +#define TRACE_SYSTEM alarmtimer >> + >> +#if !defined(_TRACE_ALARMTIMER_H) || defined(TRACE_HEADER_MULTI_READ) >> +#define _TRACE_ALARMTIMER_H >> + >> +#include >> +#include >> +#include >> + >> +TRACE_DEFINE_ENUM(ALARM_REALTIME); >> +TRACE_DEFINE_ENUM(ALARM_BOOTTIME); >> + >> +#define show_alarm_type(type)__print_flags(type, " | ", \ >> + { 1 << ALARM_REALTIME, "ALARM_REALTIME" }, \ >> + { 1 << ALARM_BOOTTIME, "ALARM_BOOTTIME" }) > > Why have the "ALARM_" prefix in the string? We already know that these > are "alarm" tracepoints. They just make the lines longer than they need > to be. > > Other than that, from a tracing point of view, this looks fine to me. Thanks Steven. I will remove the prefix and add your ACK in next version. -- Baolin.wang Best Regards
Re: [PATCH v3] time: alarmtimer: Add the trcepoints for alarmtimer
On 18 October 2016 at 03:03, Steven Rostedt wrote: > On Tue, 11 Oct 2016 18:48:16 +0800 > Baolin Wang wrote: > >> --- >> Changes since v2: >> - Save time as s64 type. >> - Remove 'process_name' parameter and add 'now' parameter. >> - Rename the trace event name. >> - Remove restart trace event. >> - Other optimization. >> --- >> include/trace/events/alarmtimer.h | 92 >> + >> kernel/time/alarmtimer.c | 16 ++- >> 2 files changed, 106 insertions(+), 2 deletions(-) >> create mode 100644 include/trace/events/alarmtimer.h >> >> diff --git a/include/trace/events/alarmtimer.h >> b/include/trace/events/alarmtimer.h >> new file mode 100644 >> index 000..4c92a3e >> --- /dev/null >> +++ b/include/trace/events/alarmtimer.h >> @@ -0,0 +1,92 @@ >> +#undef TRACE_SYSTEM >> +#define TRACE_SYSTEM alarmtimer >> + >> +#if !defined(_TRACE_ALARMTIMER_H) || defined(TRACE_HEADER_MULTI_READ) >> +#define _TRACE_ALARMTIMER_H >> + >> +#include >> +#include >> +#include >> + >> +TRACE_DEFINE_ENUM(ALARM_REALTIME); >> +TRACE_DEFINE_ENUM(ALARM_BOOTTIME); >> + >> +#define show_alarm_type(type)__print_flags(type, " | ", \ >> + { 1 << ALARM_REALTIME, "ALARM_REALTIME" }, \ >> + { 1 << ALARM_BOOTTIME, "ALARM_BOOTTIME" }) > > Why have the "ALARM_" prefix in the string? We already know that these > are "alarm" tracepoints. They just make the lines longer than they need > to be. > > Other than that, from a tracing point of view, this looks fine to me. Thanks Steven. I will remove the prefix and add your ACK in next version. -- Baolin.wang Best Regards
Re: [PATCH 2/2] builddeb: allow building without headers/firmware packages
On 26/08/16 18:17, Andrew Donnellan wrote: Currently, the deb-pkg and bindeb-pkg targets create multiple packages for the kernel binaries, headers, userspace headers and firmware. For developers who generate Debian packages as part of their development workflows, it's often not necessary to generate all these packages. Allow the creation of the linux-headers, linux-libc-dev and linux-firmware packages to be disabled if the environment variables KDEB_NO_HEADERS, KDEB_NO_LIBC_HEADERS or KDEB_NO_FIRMWARE are non-empty. Signed-off-by: Andrew DonnellanPing :) On top of d3e2773c4ede5c62d2a92dae20e3a09b1ca55b6e in kbuild#rc-fixes This of course is now in mainline. -- Andrew Donnellan OzLabs, ADL Canberra andrew.donnel...@au1.ibm.com IBM Australia Limited
Re: [PATCH 2/2] builddeb: allow building without headers/firmware packages
On 26/08/16 18:17, Andrew Donnellan wrote: Currently, the deb-pkg and bindeb-pkg targets create multiple packages for the kernel binaries, headers, userspace headers and firmware. For developers who generate Debian packages as part of their development workflows, it's often not necessary to generate all these packages. Allow the creation of the linux-headers, linux-libc-dev and linux-firmware packages to be disabled if the environment variables KDEB_NO_HEADERS, KDEB_NO_LIBC_HEADERS or KDEB_NO_FIRMWARE are non-empty. Signed-off-by: Andrew Donnellan Ping :) On top of d3e2773c4ede5c62d2a92dae20e3a09b1ca55b6e in kbuild#rc-fixes This of course is now in mainline. -- Andrew Donnellan OzLabs, ADL Canberra andrew.donnel...@au1.ibm.com IBM Australia Limited
Re: [PATCH 07/28] ceph: avoid false positive maybe-uninitialized warning
> On 18 Oct 2016, at 06:08, Arnd Bergmannwrote: > > A recent rework removed the initialization of the local 'root' > variable that is returned from ceph_real_mount: > > fs/ceph/super.c: In function 'ceph_mount': > fs/ceph/super.c:1016:38: error: 'root' may be used uninitialized in this > function [-Werror=maybe-uninitialized] > > It's not obvious to me what the correct fix is, so this just > returns the saved root as we did before. > > Fixes: ce2728aaa82b ("ceph: avoid accessing / when mounting a subpath") > Signed-off-by: Arnd Bergmann > Cc: "Yan, Zheng" > --- > fs/ceph/super.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/fs/ceph/super.c b/fs/ceph/super.c > index a29ffce..79a4be8 100644 > --- a/fs/ceph/super.c > +++ b/fs/ceph/super.c > @@ -821,7 +821,8 @@ static struct dentry *ceph_real_mount(struct > ceph_fs_client *fsc) > dout("mount start %p\n", fsc); > mutex_lock(>client->mount_mutex); > > - if (!fsc->sb->s_root) { > + root = dget(fsc->sb->s_root); > + if (!root) { > const char *path; > err = __ceph_open_session(fsc->client, started); > if (err < 0) > — This bug has already been fixed. Regards Yan, Zheng > 2.9.0 >
Re: [PATCH 07/28] ceph: avoid false positive maybe-uninitialized warning
> On 18 Oct 2016, at 06:08, Arnd Bergmann wrote: > > A recent rework removed the initialization of the local 'root' > variable that is returned from ceph_real_mount: > > fs/ceph/super.c: In function 'ceph_mount': > fs/ceph/super.c:1016:38: error: 'root' may be used uninitialized in this > function [-Werror=maybe-uninitialized] > > It's not obvious to me what the correct fix is, so this just > returns the saved root as we did before. > > Fixes: ce2728aaa82b ("ceph: avoid accessing / when mounting a subpath") > Signed-off-by: Arnd Bergmann > Cc: "Yan, Zheng" > --- > fs/ceph/super.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/fs/ceph/super.c b/fs/ceph/super.c > index a29ffce..79a4be8 100644 > --- a/fs/ceph/super.c > +++ b/fs/ceph/super.c > @@ -821,7 +821,8 @@ static struct dentry *ceph_real_mount(struct > ceph_fs_client *fsc) > dout("mount start %p\n", fsc); > mutex_lock(>client->mount_mutex); > > - if (!fsc->sb->s_root) { > + root = dget(fsc->sb->s_root); > + if (!root) { > const char *path; > err = __ceph_open_session(fsc->client, started); > if (err < 0) > — This bug has already been fixed. Regards Yan, Zheng > 2.9.0 >
Re: [PATCH v5 3/3] z3fold: add shrinker
On Sat, Oct 15, 2016 at 8:05 AM, Vitaly Woolwrote: > This patch implements shrinker for z3fold. This shrinker > implementation does not free up any pages directly but it allows > for a denser placement of compressed objects which results in > less actual pages consumed and higher compression ratio therefore. > > This update removes z3fold page compaction from the freeing path > since we can rely on shrinker to do the job. Also, a new flag > UNDER_COMPACTION is introduced to protect against two threads > trying to compact the same page. i'm completely unconvinced that this should be a shrinker. The alloc/free paths are much, much better suited to compacting a page than a shrinker that must scan through all the unbuddied pages. Why not just improve compaction for the alloc/free paths? > > This patch has been checked with the latest Linus's tree. > > Signed-off-by: Vitaly Wool > --- > mm/z3fold.c | 144 > +--- > 1 file changed, 119 insertions(+), 25 deletions(-) > > diff --git a/mm/z3fold.c b/mm/z3fold.c > index 10513b5..8f84d3c 100644 > --- a/mm/z3fold.c > +++ b/mm/z3fold.c > @@ -27,6 +27,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -72,6 +73,7 @@ struct z3fold_ops { > * @unbuddied_nr: number of unbuddied z3fold pages in the pool. > * @ops: pointer to a structure of user defined operations specified at > * pool creation time. > + * @shrinker: shrinker structure to optimize page layout in background > * > * This structure is allocated at pool creation time and maintains metadata > * pertaining to a particular z3fold pool. > @@ -86,6 +88,7 @@ struct z3fold_pool { > const struct z3fold_ops *ops; > struct zpool *zpool; > const struct zpool_ops *zpool_ops; > + struct shrinker shrinker; > }; > > enum buddy { > @@ -121,6 +124,7 @@ enum z3fold_page_flags { > UNDER_RECLAIM = 0, > PAGE_HEADLESS, > MIDDLE_CHUNK_MAPPED, > + UNDER_COMPACTION, > }; > > /* > @@ -136,6 +140,9 @@ static int size_to_chunks(size_t size) > #define for_each_unbuddied_list(_iter, _begin) \ > for ((_iter) = (_begin); (_iter) < NCHUNKS; (_iter)++) > > +#define for_each_unbuddied_list_down(_iter, _end) \ > + for ((_iter) = (_end); (_iter) > 0; (_iter)--) > + bikeshed: the conventional suffix is _reverse, not _down, i.e. for_each_unbuddied_list_reverse() > /* Initializes the z3fold header of a newly allocated z3fold page */ > static struct z3fold_header *init_z3fold_page(struct page *page) > { > @@ -145,6 +152,7 @@ static struct z3fold_header *init_z3fold_page(struct page > *page) > clear_bit(UNDER_RECLAIM, >private); > clear_bit(PAGE_HEADLESS, >private); > clear_bit(MIDDLE_CHUNK_MAPPED, >private); > + clear_bit(UNDER_COMPACTION, >private); > > zhdr->first_chunks = 0; > zhdr->middle_chunks = 0; > @@ -211,6 +219,103 @@ static int num_free_chunks(struct z3fold_header *zhdr) > return nfree; > } > > +/* Has to be called with lock held */ > +static int z3fold_compact_page(struct z3fold_header *zhdr, bool sync) > +{ > + struct page *page = virt_to_page(zhdr); > + void *beg = zhdr; > + > + > + if (!test_bit(MIDDLE_CHUNK_MAPPED, >private) && > + !test_bit(UNDER_RECLAIM, >private) && > + !test_bit(UNDER_COMPACTION, >private)) { > + set_bit(UNDER_COMPACTION, >private); i assume the reclaim check, and new compaction bit check, is due to the removal of the spinlock, which was incorrect. changing to a per-page spinlock may be the best way to handle this, but flags are absolutely not appropriate - they don't provide the needed locking. Even if the compaction bit was the only locking needed (which it isn't), it still isn't correct here - while extremely unlikely, it's still possible for multiple threads to race between checking the compaction bit, and setting it. That's what test_and_set_bit() is for. > + if (zhdr->middle_chunks != 0 && only need to check if the middle bud is in use once; if it isn't, there's no compaction to do. > + zhdr->first_chunks == 0 && > + zhdr->last_chunks == 0) { > + memmove(beg + ZHDR_SIZE_ALIGNED, > + beg + (zhdr->start_middle << CHUNK_SHIFT), > + zhdr->middle_chunks << CHUNK_SHIFT); > + zhdr->first_chunks = zhdr->middle_chunks; > + zhdr->middle_chunks = 0; > + zhdr->start_middle = 0; > + zhdr->first_num++; > + clear_bit(UNDER_COMPACTION, >private); > + return 1; > + } > + if (sync) > + goto out; i don't get it, why is
Re: [PATCH v5 3/3] z3fold: add shrinker
On Sat, Oct 15, 2016 at 8:05 AM, Vitaly Wool wrote: > This patch implements shrinker for z3fold. This shrinker > implementation does not free up any pages directly but it allows > for a denser placement of compressed objects which results in > less actual pages consumed and higher compression ratio therefore. > > This update removes z3fold page compaction from the freeing path > since we can rely on shrinker to do the job. Also, a new flag > UNDER_COMPACTION is introduced to protect against two threads > trying to compact the same page. i'm completely unconvinced that this should be a shrinker. The alloc/free paths are much, much better suited to compacting a page than a shrinker that must scan through all the unbuddied pages. Why not just improve compaction for the alloc/free paths? > > This patch has been checked with the latest Linus's tree. > > Signed-off-by: Vitaly Wool > --- > mm/z3fold.c | 144 > +--- > 1 file changed, 119 insertions(+), 25 deletions(-) > > diff --git a/mm/z3fold.c b/mm/z3fold.c > index 10513b5..8f84d3c 100644 > --- a/mm/z3fold.c > +++ b/mm/z3fold.c > @@ -27,6 +27,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -72,6 +73,7 @@ struct z3fold_ops { > * @unbuddied_nr: number of unbuddied z3fold pages in the pool. > * @ops: pointer to a structure of user defined operations specified at > * pool creation time. > + * @shrinker: shrinker structure to optimize page layout in background > * > * This structure is allocated at pool creation time and maintains metadata > * pertaining to a particular z3fold pool. > @@ -86,6 +88,7 @@ struct z3fold_pool { > const struct z3fold_ops *ops; > struct zpool *zpool; > const struct zpool_ops *zpool_ops; > + struct shrinker shrinker; > }; > > enum buddy { > @@ -121,6 +124,7 @@ enum z3fold_page_flags { > UNDER_RECLAIM = 0, > PAGE_HEADLESS, > MIDDLE_CHUNK_MAPPED, > + UNDER_COMPACTION, > }; > > /* > @@ -136,6 +140,9 @@ static int size_to_chunks(size_t size) > #define for_each_unbuddied_list(_iter, _begin) \ > for ((_iter) = (_begin); (_iter) < NCHUNKS; (_iter)++) > > +#define for_each_unbuddied_list_down(_iter, _end) \ > + for ((_iter) = (_end); (_iter) > 0; (_iter)--) > + bikeshed: the conventional suffix is _reverse, not _down, i.e. for_each_unbuddied_list_reverse() > /* Initializes the z3fold header of a newly allocated z3fold page */ > static struct z3fold_header *init_z3fold_page(struct page *page) > { > @@ -145,6 +152,7 @@ static struct z3fold_header *init_z3fold_page(struct page > *page) > clear_bit(UNDER_RECLAIM, >private); > clear_bit(PAGE_HEADLESS, >private); > clear_bit(MIDDLE_CHUNK_MAPPED, >private); > + clear_bit(UNDER_COMPACTION, >private); > > zhdr->first_chunks = 0; > zhdr->middle_chunks = 0; > @@ -211,6 +219,103 @@ static int num_free_chunks(struct z3fold_header *zhdr) > return nfree; > } > > +/* Has to be called with lock held */ > +static int z3fold_compact_page(struct z3fold_header *zhdr, bool sync) > +{ > + struct page *page = virt_to_page(zhdr); > + void *beg = zhdr; > + > + > + if (!test_bit(MIDDLE_CHUNK_MAPPED, >private) && > + !test_bit(UNDER_RECLAIM, >private) && > + !test_bit(UNDER_COMPACTION, >private)) { > + set_bit(UNDER_COMPACTION, >private); i assume the reclaim check, and new compaction bit check, is due to the removal of the spinlock, which was incorrect. changing to a per-page spinlock may be the best way to handle this, but flags are absolutely not appropriate - they don't provide the needed locking. Even if the compaction bit was the only locking needed (which it isn't), it still isn't correct here - while extremely unlikely, it's still possible for multiple threads to race between checking the compaction bit, and setting it. That's what test_and_set_bit() is for. > + if (zhdr->middle_chunks != 0 && only need to check if the middle bud is in use once; if it isn't, there's no compaction to do. > + zhdr->first_chunks == 0 && > + zhdr->last_chunks == 0) { > + memmove(beg + ZHDR_SIZE_ALIGNED, > + beg + (zhdr->start_middle << CHUNK_SHIFT), > + zhdr->middle_chunks << CHUNK_SHIFT); > + zhdr->first_chunks = zhdr->middle_chunks; > + zhdr->middle_chunks = 0; > + zhdr->start_middle = 0; > + zhdr->first_num++; > + clear_bit(UNDER_COMPACTION, >private); > + return 1; > + } > + if (sync) > + goto out; i don't get it, why is that compaction synchronous while the
[PATCH v5 02/23] of: device: Export of_device_{get_modalias,uvent_modalias} to modules
The ULPI bus can be built as a module, and it will soon be calling these functions when it supports probing devices from DT. Export them so they can be used by the ULPI module. Acked-by: Rob HerringCc: Signed-off-by: Stephen Boyd --- drivers/of/device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/of/device.c b/drivers/of/device.c index 8a22a253a830..6719ab35b62e 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -225,6 +225,7 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) return tsize; } +EXPORT_SYMBOL_GPL(of_device_get_modalias); int of_device_request_module(struct device *dev) { @@ -290,6 +291,7 @@ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env) } mutex_unlock(_mutex); } +EXPORT_SYMBOL_GPL(of_device_uevent_modalias); int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) { -- 2.10.0.297.gf6727b0
[PATCH v5 02/23] of: device: Export of_device_{get_modalias,uvent_modalias} to modules
The ULPI bus can be built as a module, and it will soon be calling these functions when it supports probing devices from DT. Export them so they can be used by the ULPI module. Acked-by: Rob Herring Cc: Signed-off-by: Stephen Boyd --- drivers/of/device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/of/device.c b/drivers/of/device.c index 8a22a253a830..6719ab35b62e 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -225,6 +225,7 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) return tsize; } +EXPORT_SYMBOL_GPL(of_device_get_modalias); int of_device_request_module(struct device *dev) { @@ -290,6 +291,7 @@ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env) } mutex_unlock(_mutex); } +EXPORT_SYMBOL_GPL(of_device_uevent_modalias); int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) { -- 2.10.0.297.gf6727b0
[PATCH v5 03/23] usb: ulpi: Support device discovery via DT
The qcom HSIC ULPI phy doesn't have any bits set in the vendor or product ID registers. This makes it impossible to make a ULPI driver match against the ID registers. Add support to discover the ULPI phys via DT help alleviate this problem. In the DT case, we'll look for a ULPI bus node underneath the device registering the ULPI viewport (or the parent of that device to support chipidea's device layout) and then match up the phy node underneath that with the ULPI device that's created. The side benefit of this is that we can use standard properties in the phy node like clks, regulators, gpios, etc. because we don't have firmware like ACPI to turn these things on for us. And we can use the DT phy binding to point our phy consumer to the phy provider. The ULPI bus code supports native enumeration by reading the vendor ID and product ID registers at device creation time, but we can't be certain that those register reads will succeed if the phy is not powered up. To avoid any problems with reading the ID registers before the phy is powered we fallback to DT matching when the ID reads fail. If the ULPI spec had some generic power sequencing for these registers we could put that into the ULPI bus layer and power up the device before reading the ID registers. Unfortunately this doesn't exist and the power sequence is usually device specific. By having the device matched up with DT we can avoid this problem. Cc: Greg Kroah-HartmanCc: Heikki Krogerus Cc: Cc: Rob Herring Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/usb/ulpi.txt | 20 +++ drivers/usb/common/ulpi.c | 79 -- 2 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 Documentation/devicetree/bindings/usb/ulpi.txt diff --git a/Documentation/devicetree/bindings/usb/ulpi.txt b/Documentation/devicetree/bindings/usb/ulpi.txt new file mode 100644 index ..ca179dc4bd50 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/ulpi.txt @@ -0,0 +1,20 @@ +ULPI bus binding + + +Phys that are behind a ULPI connection can be described with the following +binding. The host controller shall have a "ulpi" named node as a child, and +that node shall have one enabled node underneath it representing the ulpi +device on the bus. + +EXAMPLE +--- + +usb { + compatible = "vendor,usb-controller"; + + ulpi { + phy { + compatible = "vendor,phy"; + }; + }; +}; diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 8b317702d761..c9480d77810c 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -16,6 +16,9 @@ #include #include #include +#include +#include +#include /* -- */ @@ -39,6 +42,10 @@ static int ulpi_match(struct device *dev, struct device_driver *driver) struct ulpi *ulpi = to_ulpi_dev(dev); const struct ulpi_device_id *id; + /* Some ULPI devices don't have a vendor id so rely on OF match */ + if (ulpi->id.vendor == 0) + return of_driver_match_device(dev, driver); + for (id = drv->id_table; id->vendor; id++) if (id->vendor == ulpi->id.vendor && id->product == ulpi->id.product) @@ -50,6 +57,11 @@ static int ulpi_match(struct device *dev, struct device_driver *driver) static int ulpi_uevent(struct device *dev, struct kobj_uevent_env *env) { struct ulpi *ulpi = to_ulpi_dev(dev); + int ret; + + ret = of_device_uevent_modalias(dev, env); + if (ret != -ENODEV) + return ret; if (add_uevent_var(env, "MODALIAS=ulpi:v%04xp%04x", ulpi->id.vendor, ulpi->id.product)) @@ -60,6 +72,11 @@ static int ulpi_uevent(struct device *dev, struct kobj_uevent_env *env) static int ulpi_probe(struct device *dev) { struct ulpi_driver *drv = to_ulpi_driver(dev->driver); + int ret; + + ret = of_clk_set_defaults(dev->of_node, false); + if (ret < 0) + return ret; return drv->probe(to_ulpi_dev(dev)); } @@ -87,8 +104,13 @@ static struct bus_type ulpi_bus = { static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { + int len; struct ulpi *ulpi = to_ulpi_dev(dev); + len = of_device_get_modalias(dev, buf, PAGE_SIZE - 1); + if (len != -ENODEV) + return len; + return sprintf(buf, "ulpi:v%04xp%04x\n", ulpi->id.vendor, ulpi->id.product); } @@ -153,23 +175,45 @@ EXPORT_SYMBOL_GPL(ulpi_unregister_driver); /* -- */ -static int
[PATCH v5 03/23] usb: ulpi: Support device discovery via DT
The qcom HSIC ULPI phy doesn't have any bits set in the vendor or product ID registers. This makes it impossible to make a ULPI driver match against the ID registers. Add support to discover the ULPI phys via DT help alleviate this problem. In the DT case, we'll look for a ULPI bus node underneath the device registering the ULPI viewport (or the parent of that device to support chipidea's device layout) and then match up the phy node underneath that with the ULPI device that's created. The side benefit of this is that we can use standard properties in the phy node like clks, regulators, gpios, etc. because we don't have firmware like ACPI to turn these things on for us. And we can use the DT phy binding to point our phy consumer to the phy provider. The ULPI bus code supports native enumeration by reading the vendor ID and product ID registers at device creation time, but we can't be certain that those register reads will succeed if the phy is not powered up. To avoid any problems with reading the ID registers before the phy is powered we fallback to DT matching when the ID reads fail. If the ULPI spec had some generic power sequencing for these registers we could put that into the ULPI bus layer and power up the device before reading the ID registers. Unfortunately this doesn't exist and the power sequence is usually device specific. By having the device matched up with DT we can avoid this problem. Cc: Greg Kroah-Hartman Cc: Heikki Krogerus Cc: Cc: Rob Herring Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/usb/ulpi.txt | 20 +++ drivers/usb/common/ulpi.c | 79 -- 2 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 Documentation/devicetree/bindings/usb/ulpi.txt diff --git a/Documentation/devicetree/bindings/usb/ulpi.txt b/Documentation/devicetree/bindings/usb/ulpi.txt new file mode 100644 index ..ca179dc4bd50 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/ulpi.txt @@ -0,0 +1,20 @@ +ULPI bus binding + + +Phys that are behind a ULPI connection can be described with the following +binding. The host controller shall have a "ulpi" named node as a child, and +that node shall have one enabled node underneath it representing the ulpi +device on the bus. + +EXAMPLE +--- + +usb { + compatible = "vendor,usb-controller"; + + ulpi { + phy { + compatible = "vendor,phy"; + }; + }; +}; diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 8b317702d761..c9480d77810c 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -16,6 +16,9 @@ #include #include #include +#include +#include +#include /* -- */ @@ -39,6 +42,10 @@ static int ulpi_match(struct device *dev, struct device_driver *driver) struct ulpi *ulpi = to_ulpi_dev(dev); const struct ulpi_device_id *id; + /* Some ULPI devices don't have a vendor id so rely on OF match */ + if (ulpi->id.vendor == 0) + return of_driver_match_device(dev, driver); + for (id = drv->id_table; id->vendor; id++) if (id->vendor == ulpi->id.vendor && id->product == ulpi->id.product) @@ -50,6 +57,11 @@ static int ulpi_match(struct device *dev, struct device_driver *driver) static int ulpi_uevent(struct device *dev, struct kobj_uevent_env *env) { struct ulpi *ulpi = to_ulpi_dev(dev); + int ret; + + ret = of_device_uevent_modalias(dev, env); + if (ret != -ENODEV) + return ret; if (add_uevent_var(env, "MODALIAS=ulpi:v%04xp%04x", ulpi->id.vendor, ulpi->id.product)) @@ -60,6 +72,11 @@ static int ulpi_uevent(struct device *dev, struct kobj_uevent_env *env) static int ulpi_probe(struct device *dev) { struct ulpi_driver *drv = to_ulpi_driver(dev->driver); + int ret; + + ret = of_clk_set_defaults(dev->of_node, false); + if (ret < 0) + return ret; return drv->probe(to_ulpi_dev(dev)); } @@ -87,8 +104,13 @@ static struct bus_type ulpi_bus = { static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { + int len; struct ulpi *ulpi = to_ulpi_dev(dev); + len = of_device_get_modalias(dev, buf, PAGE_SIZE - 1); + if (len != -ENODEV) + return len; + return sprintf(buf, "ulpi:v%04xp%04x\n", ulpi->id.vendor, ulpi->id.product); } @@ -153,23 +175,45 @@ EXPORT_SYMBOL_GPL(ulpi_unregister_driver); /* -- */ -static int ulpi_register(struct device *dev, struct ulpi *ulpi) +static int ulpi_of_register(struct ulpi *ulpi) { - int ret; + struct
[PATCH v5 10/23] usb: chipidea: Consolidate extcon notifiers
The two extcon notifiers are almost the same except for the variable name for the cable structure and the id notifier inverts the cable->state logic. Make it the same and replace two functions with one to save some lines. This also makes it so that the id cable state is true when the id pin is pulled low, so we change the name of ->state to ->connected to properly reflect that we're interested in the cable being connected. Acked-by: Peter ChenCc: Greg Kroah-Hartman Cc: "Ivan T. Ivanov" Signed-off-by: Stephen Boyd --- drivers/usb/chipidea/core.c | 45 drivers/usb/chipidea/otg.c | 8 include/linux/usb/chipidea.h | 4 ++-- 3 files changed, 18 insertions(+), 39 deletions(-) diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index f144e1bbcc82..83bc2f2dd6a8 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -577,35 +577,14 @@ static irqreturn_t ci_irq(int irq, void *data) return ret; } -static int ci_vbus_notifier(struct notifier_block *nb, unsigned long event, - void *ptr) +static int ci_cable_notifier(struct notifier_block *nb, unsigned long event, +void *ptr) { - struct ci_hdrc_cable *vbus = container_of(nb, struct ci_hdrc_cable, nb); - struct ci_hdrc *ci = vbus->ci; + struct ci_hdrc_cable *cbl = container_of(nb, struct ci_hdrc_cable, nb); + struct ci_hdrc *ci = cbl->ci; - if (event) - vbus->state = true; - else - vbus->state = false; - - vbus->changed = true; - - ci_irq(ci->irq, ci); - return NOTIFY_DONE; -} - -static int ci_id_notifier(struct notifier_block *nb, unsigned long event, - void *ptr) -{ - struct ci_hdrc_cable *id = container_of(nb, struct ci_hdrc_cable, nb); - struct ci_hdrc *ci = id->ci; - - if (event) - id->state = false; - else - id->state = true; - - id->changed = true; + cbl->connected = event; + cbl->changed = true; ci_irq(ci->irq, ci); return NOTIFY_DONE; @@ -714,27 +693,27 @@ static int ci_get_platdata(struct device *dev, } cable = >vbus_extcon; - cable->nb.notifier_call = ci_vbus_notifier; + cable->nb.notifier_call = ci_cable_notifier; cable->edev = ext_vbus; if (!IS_ERR(ext_vbus)) { ret = extcon_get_cable_state_(cable->edev, EXTCON_USB); if (ret) - cable->state = true; + cable->connected = true; else - cable->state = false; + cable->connected = false; } cable = >id_extcon; - cable->nb.notifier_call = ci_id_notifier; + cable->nb.notifier_call = ci_cable_notifier; cable->edev = ext_id; if (!IS_ERR(ext_id)) { ret = extcon_get_cable_state_(cable->edev, EXTCON_USB_HOST); if (ret) - cable->state = false; + cable->connected = true; else - cable->state = true; + cable->connected = false; } return 0; } diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index 0cf149e8..695f3fe3ae21 100644 --- a/drivers/usb/chipidea/otg.c +++ b/drivers/usb/chipidea/otg.c @@ -44,7 +44,7 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) else val &= ~OTGSC_BSVIS; - if (cable->state) + if (cable->connected) val |= OTGSC_BSV; else val &= ~OTGSC_BSV; @@ -62,10 +62,10 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) else val &= ~OTGSC_IDIS; - if (cable->state) - val |= OTGSC_ID; + if (cable->connected) + val &= ~OTGSC_ID; /* host */ else - val &= ~OTGSC_ID; + val |= OTGSC_ID; /* device */ if (cable->enabled) val |= OTGSC_IDIE; diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index d07b162073f7..7e3daa37cf60 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h @@ -12,7 +12,7 @@ struct ci_hdrc; /** * struct ci_hdrc_cable - structure for external connector cable state tracking - * @state: current state of the line + * @connected: true if cable is connected, false otherwise * @changed: set to true when extcon event happen * @enabled: set to true if we've enabled the vbus or id interrupt * @edev: device which generate events @@ -21,7 +21,7 @@ struct ci_hdrc;
[PATCH v5 10/23] usb: chipidea: Consolidate extcon notifiers
The two extcon notifiers are almost the same except for the variable name for the cable structure and the id notifier inverts the cable->state logic. Make it the same and replace two functions with one to save some lines. This also makes it so that the id cable state is true when the id pin is pulled low, so we change the name of ->state to ->connected to properly reflect that we're interested in the cable being connected. Acked-by: Peter Chen Cc: Greg Kroah-Hartman Cc: "Ivan T. Ivanov" Signed-off-by: Stephen Boyd --- drivers/usb/chipidea/core.c | 45 drivers/usb/chipidea/otg.c | 8 include/linux/usb/chipidea.h | 4 ++-- 3 files changed, 18 insertions(+), 39 deletions(-) diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index f144e1bbcc82..83bc2f2dd6a8 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -577,35 +577,14 @@ static irqreturn_t ci_irq(int irq, void *data) return ret; } -static int ci_vbus_notifier(struct notifier_block *nb, unsigned long event, - void *ptr) +static int ci_cable_notifier(struct notifier_block *nb, unsigned long event, +void *ptr) { - struct ci_hdrc_cable *vbus = container_of(nb, struct ci_hdrc_cable, nb); - struct ci_hdrc *ci = vbus->ci; + struct ci_hdrc_cable *cbl = container_of(nb, struct ci_hdrc_cable, nb); + struct ci_hdrc *ci = cbl->ci; - if (event) - vbus->state = true; - else - vbus->state = false; - - vbus->changed = true; - - ci_irq(ci->irq, ci); - return NOTIFY_DONE; -} - -static int ci_id_notifier(struct notifier_block *nb, unsigned long event, - void *ptr) -{ - struct ci_hdrc_cable *id = container_of(nb, struct ci_hdrc_cable, nb); - struct ci_hdrc *ci = id->ci; - - if (event) - id->state = false; - else - id->state = true; - - id->changed = true; + cbl->connected = event; + cbl->changed = true; ci_irq(ci->irq, ci); return NOTIFY_DONE; @@ -714,27 +693,27 @@ static int ci_get_platdata(struct device *dev, } cable = >vbus_extcon; - cable->nb.notifier_call = ci_vbus_notifier; + cable->nb.notifier_call = ci_cable_notifier; cable->edev = ext_vbus; if (!IS_ERR(ext_vbus)) { ret = extcon_get_cable_state_(cable->edev, EXTCON_USB); if (ret) - cable->state = true; + cable->connected = true; else - cable->state = false; + cable->connected = false; } cable = >id_extcon; - cable->nb.notifier_call = ci_id_notifier; + cable->nb.notifier_call = ci_cable_notifier; cable->edev = ext_id; if (!IS_ERR(ext_id)) { ret = extcon_get_cable_state_(cable->edev, EXTCON_USB_HOST); if (ret) - cable->state = false; + cable->connected = true; else - cable->state = true; + cable->connected = false; } return 0; } diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index 0cf149e8..695f3fe3ae21 100644 --- a/drivers/usb/chipidea/otg.c +++ b/drivers/usb/chipidea/otg.c @@ -44,7 +44,7 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) else val &= ~OTGSC_BSVIS; - if (cable->state) + if (cable->connected) val |= OTGSC_BSV; else val &= ~OTGSC_BSV; @@ -62,10 +62,10 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) else val &= ~OTGSC_IDIS; - if (cable->state) - val |= OTGSC_ID; + if (cable->connected) + val &= ~OTGSC_ID; /* host */ else - val &= ~OTGSC_ID; + val |= OTGSC_ID; /* device */ if (cable->enabled) val |= OTGSC_IDIE; diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index d07b162073f7..7e3daa37cf60 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h @@ -12,7 +12,7 @@ struct ci_hdrc; /** * struct ci_hdrc_cable - structure for external connector cable state tracking - * @state: current state of the line + * @connected: true if cable is connected, false otherwise * @changed: set to true when extcon event happen * @enabled: set to true if we've enabled the vbus or id interrupt * @edev: device which generate events @@ -21,7 +21,7 @@ struct ci_hdrc; * @conn: used for notification registration */ struct ci_hdrc_cable { - bool
[PATCH v5 16/23] usb: chipidea: msm: Mux over secondary phy at the right time
We need to pick the correct phy at runtime based on how the SoC has been wired onto the board. If the secondary phy is used, take it out of reset and mux over to it by writing into the TCSR register. Make sure to do this on reset too, because this register is reset to the default value (primary phy) after the RESET bit is set in USBCMD. Acked-by: Peter ChenCc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd --- drivers/usb/chipidea/ci_hdrc_msm.c | 62 -- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c index 7e870a253f55..4b0aadc2be2f 100644 --- a/drivers/usb/chipidea/ci_hdrc_msm.c +++ b/drivers/usb/chipidea/ci_hdrc_msm.c @@ -8,29 +8,44 @@ #include #include #include -#include #include #include #include +#include +#include +#include #include "ci.h" #define HS_PHY_AHB_MODE0x0098 +/* Vendor base starts at 0x200 beyond CI base */ +#define HS_PHY_SEC_CTRL0x0078 +#define HS_PHY_DIG_CLAMP_N BIT(16) + struct ci_hdrc_msm { struct platform_device *ci; struct clk *core_clk; struct clk *iface_clk; struct clk *fs_clk; + bool secondary_phy; + void __iomem *base; }; static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) { - struct device *dev = ci->gadget.dev.parent; + struct device *dev = ci->dev->parent; + struct ci_hdrc_msm *msm_ci = dev_get_drvdata(dev); switch (event) { case CI_HDRC_CONTROLLER_RESET_EVENT: dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n"); + if (msm_ci->secondary_phy) { + u32 val = readl_relaxed(msm_ci->base + HS_PHY_SEC_CTRL); + val |= HS_PHY_DIG_CLAMP_N; + writel_relaxed(val, msm_ci->base + HS_PHY_SEC_CTRL); + } + /* use AHB transactor, allow posted data writes */ hw_write_id_reg(ci, HS_PHY_AHB_MODE, 0x, 0x8); usb_phy_init(ci->usb_phy); @@ -59,6 +74,39 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = { .notify_event = ci_hdrc_msm_notify_event, }; +static int ci_hdrc_msm_mux_phy(struct ci_hdrc_msm *ci, + struct platform_device *pdev) +{ + struct regmap *regmap; + struct device *dev = >dev; + struct of_phandle_args args; + u32 val; + int ret; + + ret = of_parse_phandle_with_fixed_args(dev->of_node, "phy-select", 2, 0, + ); + if (ret) + return 0; + + regmap = syscon_node_to_regmap(args.np); + of_node_put(args.np); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + ret = regmap_write(regmap, args.args[0], args.args[1]); + if (ret) + return ret; + + ci->secondary_phy = !!args.args[1]; + if (ci->secondary_phy) { + val = readl_relaxed(ci->base + HS_PHY_SEC_CTRL); + val |= HS_PHY_DIG_CLAMP_N; + writel_relaxed(val, ci->base + HS_PHY_SEC_CTRL); + } + + return 0; +} + static int ci_hdrc_msm_probe(struct platform_device *pdev) { struct ci_hdrc_msm *ci; @@ -66,6 +114,7 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev) struct usb_phy *phy; struct clk *clk; struct reset_control *reset; + struct resource *res; int ret; dev_dbg(>dev, "ci_hdrc_msm_probe\n"); @@ -105,6 +154,11 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev) ci->fs_clk = NULL; } + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + ci->base = devm_ioremap_resource(>dev, res); + if (!ci->base) + return -ENOMEM; + ret = clk_prepare_enable(ci->fs_clk); if (ret) return ret; @@ -123,6 +177,10 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev) if (ret) goto err_iface; + ret = ci_hdrc_msm_mux_phy(ci, pdev); + if (ret) + goto err_mux; + plat_ci = ci_hdrc_add_device(>dev, pdev->resource, pdev->num_resources, _hdrc_msm_platdata); -- 2.10.0.297.gf6727b0
[PATCH v5 13/23] usb: chipidea: msm: Rely on core to override AHBBURST
The core framework already handles setting this parameter with a platform quirk. Add the appropriate flag so that we always set AHBBURST to 0. Technically DT should be doing this, but we always do it for msm chipidea devices so setting the flag in the driver works just as well. If the burst needs to be anything besides 0, we expect the 'ahb-burst-config' dts property to be present. Acked-by: Peter ChenCc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd --- drivers/usb/chipidea/ci_hdrc_msm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c index 89c1a02d69b5..719b20caf88e 100644 --- a/drivers/usb/chipidea/ci_hdrc_msm.c +++ b/drivers/usb/chipidea/ci_hdrc_msm.c @@ -24,7 +24,6 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) switch (event) { case CI_HDRC_CONTROLLER_RESET_EVENT: dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n"); - writel(0, USB_AHBBURST); /* use AHB transactor, allow posted data writes */ writel(0x8, USB_AHBMODE); usb_phy_init(ci->usb_phy); @@ -47,7 +46,8 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = { .name = "ci_hdrc_msm", .capoffset = DEF_CAPOFFSET, .flags = CI_HDRC_REGS_SHARED | - CI_HDRC_DISABLE_STREAMING, + CI_HDRC_DISABLE_STREAMING | + CI_HDRC_OVERRIDE_AHB_BURST, .notify_event = ci_hdrc_msm_notify_event, }; -- 2.10.0.297.gf6727b0