[PATCH v9 9/9] gpio: uniphier: Utilize for_each_set_clump8 macro

2019-03-02 Thread William Breathitt Gray
Replace verbose implementation in set_multiple callback with
for_each_set_clump8 macro to simplify code and improve clarity. An
improvement in this case is that banks that are not masked will now be
skipped.

Cc: Masahiro Yamada 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-uniphier.c | 16 ++--
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c
index 0f662b297a95..df640cb29b9c 100644
--- a/drivers/gpio/gpio-uniphier.c
+++ b/drivers/gpio/gpio-uniphier.c
@@ -15,9 +15,6 @@
 #include 
 #include 
 
-#define UNIPHIER_GPIO_BANK_MASK\
-   GENMASK((UNIPHIER_GPIO_LINES_PER_BANK) - 1, 0)
-
 #define UNIPHIER_GPIO_IRQ_MAX_NUM  24
 
 #define UNIPHIER_GPIO_PORT_DATA0x0 /* data */
@@ -147,15 +144,14 @@ static void uniphier_gpio_set(struct gpio_chip *chip,
 static void uniphier_gpio_set_multiple(struct gpio_chip *chip,
   unsigned long *mask, unsigned long *bits)
 {
-   unsigned int bank, shift, bank_mask, bank_bits;
-   int i;
+   unsigned int i;
+   unsigned long bank_mask;
+   unsigned int bank;
+   unsigned int bank_bits;
 
-   for (i = 0; i < chip->ngpio; i += UNIPHIER_GPIO_LINES_PER_BANK) {
+   for_each_set_clump8(i, bank_mask, mask, chip->ngpio) {
bank = i / UNIPHIER_GPIO_LINES_PER_BANK;
-   shift = i % BITS_PER_LONG;
-   bank_mask = (mask[BIT_WORD(i)] >> shift) &
-   UNIPHIER_GPIO_BANK_MASK;
-   bank_bits = bits[BIT_WORD(i)] >> shift;
+   bank_bits = bitmap_get_value8(bits, chip->ngpio, i);
 
uniphier_gpio_bank_write(chip, bank, UNIPHIER_GPIO_PORT_DATA,
 bank_mask, bank_bits);
-- 
2.21.0



[PATCH v9 8/9] gpio: pcie-idio-24: Utilize for_each_set_clump8 macro

2019-03-02 Thread William Breathitt Gray
Replace verbose implementation in get_multiple/set_multiple callbacks
with for_each_set_clump8 macro to simplify code and improve clarity.

Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-pcie-idio-24.c | 111 ---
 1 file changed, 42 insertions(+), 69 deletions(-)

diff --git a/drivers/gpio/gpio-pcie-idio-24.c b/drivers/gpio/gpio-pcie-idio-24.c
index 52f1647a46fd..2ceff1f5d8fd 100644
--- a/drivers/gpio/gpio-pcie-idio-24.c
+++ b/drivers/gpio/gpio-pcie-idio-24.c
@@ -198,52 +198,35 @@ static int idio_24_gpio_get_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
-   size_t i;
-   const unsigned int gpio_reg_size = 8;
-   unsigned int bits_offset;
-   size_t word_index;
-   unsigned int word_offset;
-   unsigned long word_mask;
-   const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
-   unsigned long port_state;
+   unsigned int offset;
+   unsigned long gpio_mask;
void __iomem *ports[] = {
>reg->out0_7, >reg->out8_15,
>reg->out16_23, >reg->in0_7,
>reg->in8_15, >reg->in16_23,
};
+   const unsigned int ngpio = ARRAY_SIZE(ports) * 8;
+   size_t index;
+   unsigned long port_state;
const unsigned long out_mode_mask = BIT(1);
 
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
 
-   /* get bits are evaluated a gpio port register at a time */
-   for (i = 0; i < ARRAY_SIZE(ports) + 1; i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
-
-   /* word index for bits array */
-   word_index = BIT_WORD(bits_offset);
-
-   /* gpio offset within current word of bits array */
-   word_offset = bits_offset % BITS_PER_LONG;
-
-   /* mask of get bits for current gpio within current word */
-   word_mask = mask[word_index] & (port_mask << word_offset);
-   if (!word_mask) {
-   /* no get bits in this port so skip to next one */
-   continue;
-   }
+   for_each_set_clump8(offset, gpio_mask, mask, ngpio) {
+   index = offset / 8;
 
/* read bits from current gpio port (port 6 is TTL GPIO) */
-   if (i < 6)
-   port_state = ioread8(ports[i]);
+   if (index < 6)
+   port_state = ioread8(ports[index]);
else if (ioread8(>reg->ctl) & out_mode_mask)
port_state = ioread8(>reg->ttl_out0_7);
else
port_state = ioread8(>reg->ttl_in0_7);
 
-   /* store acquired bits at respective bits array offset */
-   bits[word_index] |= (port_state << word_offset) & word_mask;
+   port_state &= gpio_mask;
+
+   bitmap_set_value8(bits, ngpio, port_state, offset);
}
 
return 0;
@@ -294,59 +277,49 @@ static void idio_24_gpio_set_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
-   size_t i;
-   unsigned long bits_offset;
+   unsigned int offset;
unsigned long gpio_mask;
-   const unsigned int gpio_reg_size = 8;
-   const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
-   unsigned long flags;
-   unsigned int out_state;
void __iomem *ports[] = {
>reg->out0_7, >reg->out8_15,
>reg->out16_23
};
+   const unsigned int ngpio = ARRAY_SIZE(ports) * 8;
+   size_t index;
+   unsigned int bitmask;
+   unsigned long flags;
+   unsigned int out_state;
const unsigned long out_mode_mask = BIT(1);
-   const unsigned int ttl_offset = 48;
-   const size_t ttl_i = BIT_WORD(ttl_offset);
-   const unsigned int word_offset = ttl_offset % BITS_PER_LONG;
-   const unsigned long ttl_mask = (mask[ttl_i] >> word_offset) & port_mask;
-   const unsigned long ttl_bits = (bits[ttl_i] >> word_offset) & ttl_mask;
-
-   /* set bits are processed a gpio port register at a time */
-   for (i = 0; i < ARRAY_SIZE(ports); i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
-
-   /* check if any set bits for current port */
-   gpio_mask = (*mask >> bits_offset) & port_mask;
-   if (!gpio_mask) {
-   /* no set bits for this port so move on to next port */
-   continue;
-   }
 
-   raw_spin_lock_irqsave(>lock, flags);
+   for_each_set_clump8(offset, gpio_mask, mask, ngpio) {
+   index = offset / 8;
 
-  

[PATCH v9 7/9] gpio: pci-idio-16: Utilize for_each_set_clump8 macro

2019-03-02 Thread William Breathitt Gray
Replace verbose implementation in get_multiple/set_multiple callbacks
with for_each_set_clump8 macro to simplify code and improve clarity.

Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-pci-idio-16.c | 75 -
 1 file changed, 28 insertions(+), 47 deletions(-)

diff --git a/drivers/gpio/gpio-pci-idio-16.c b/drivers/gpio/gpio-pci-idio-16.c
index 6b7349783223..b0ed6bb68296 100644
--- a/drivers/gpio/gpio-pci-idio-16.c
+++ b/drivers/gpio/gpio-pci-idio-16.c
@@ -108,45 +108,24 @@ static int idio_16_gpio_get_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
-   size_t i;
-   const unsigned int gpio_reg_size = 8;
-   unsigned int bits_offset;
-   size_t word_index;
-   unsigned int word_offset;
-   unsigned long word_mask;
-   const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
-   unsigned long port_state;
+   unsigned int offset;
+   unsigned long gpio_mask;
void __iomem *ports[] = {
>reg->out0_7, >reg->out8_15,
>reg->in0_7, >reg->in8_15,
};
+   const unsigned int ngpio = ARRAY_SIZE(ports) * 8;
+   void __iomem *port_addr;
+   unsigned long port_state;
 
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
 
-   /* get bits are evaluated a gpio port register at a time */
-   for (i = 0; i < ARRAY_SIZE(ports); i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
-
-   /* word index for bits array */
-   word_index = BIT_WORD(bits_offset);
-
-   /* gpio offset within current word of bits array */
-   word_offset = bits_offset % BITS_PER_LONG;
+   for_each_set_clump8(offset, gpio_mask, mask, ngpio) {
+   port_addr = ports[offset / 8];
+   port_state = ioread8(port_addr) & gpio_mask;
 
-   /* mask of get bits for current gpio within current word */
-   word_mask = mask[word_index] & (port_mask << word_offset);
-   if (!word_mask) {
-   /* no get bits in this port so skip to next one */
-   continue;
-   }
-
-   /* read bits from current gpio port */
-   port_state = ioread8(ports[i]);
-
-   /* store acquired bits at respective bits array offset */
-   bits[word_index] |= (port_state << word_offset) & word_mask;
+   bitmap_set_value8(bits, ngpio, port_state, offset);
}
 
return 0;
@@ -186,30 +165,32 @@ static void idio_16_gpio_set_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
+   unsigned int offset;
+   unsigned long gpio_mask;
+   void __iomem *ports[] = {
+   >reg->out0_7, >reg->out8_15,
+   };
+   const unsigned int ngpio = ARRAY_SIZE(ports) * 8;
+   size_t index;
+   void __iomem *port_addr;
+   unsigned int bitmask;
unsigned long flags;
unsigned int out_state;
 
-   raw_spin_lock_irqsave(>lock, flags);
+   for_each_set_clump8(offset, gpio_mask, mask, ngpio) {
+   index = offset / 8;
+   port_addr = ports[index];
 
-   /* process output lines 0-7 */
-   if (*mask & 0xFF) {
-   out_state = ioread8(>reg->out0_7) & ~*mask;
-   out_state |= *mask & *bits;
-   iowrite8(out_state, >reg->out0_7);
-   }
+   bitmask = bitmap_get_value8(bits, ngpio, offset) & gpio_mask;
+
+   raw_spin_lock_irqsave(>lock, flags);
 
-   /* shift to next output line word */
-   *mask >>= 8;
+   out_state = ioread8(port_addr) & ~gpio_mask;
+   out_state |= bitmask;
+   iowrite8(out_state, port_addr);
 
-   /* process output lines 8-15 */
-   if (*mask & 0xFF) {
-   *bits >>= 8;
-   out_state = ioread8(>reg->out8_15) & ~*mask;
-   out_state |= *mask & *bits;
-   iowrite8(out_state, >reg->out8_15);
+   raw_spin_unlock_irqrestore(>lock, flags);
}
-
-   raw_spin_unlock_irqrestore(>lock, flags);
 }
 
 static void idio_16_irq_ack(struct irq_data *data)
-- 
2.21.0



[PATCH v9 6/9] gpio: ws16c48: Utilize for_each_set_clump8 macro

2019-03-02 Thread William Breathitt Gray
Replace verbose implementation in get_multiple/set_multiple callbacks
with for_each_set_clump8 macro to simplify code and improve clarity.

Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-ws16c48.c | 72 +++--
 1 file changed, 20 insertions(+), 52 deletions(-)

diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c
index 5cf3697bfb15..1d071a3d3e81 100644
--- a/drivers/gpio/gpio-ws16c48.c
+++ b/drivers/gpio/gpio-ws16c48.c
@@ -134,42 +134,19 @@ static int ws16c48_gpio_get_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip);
-   const unsigned int gpio_reg_size = 8;
-   size_t i;
-   const size_t num_ports = chip->ngpio / gpio_reg_size;
-   unsigned int bits_offset;
-   size_t word_index;
-   unsigned int word_offset;
-   unsigned long word_mask;
-   const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
+   unsigned int offset;
+   unsigned long gpio_mask;
+   unsigned int port_addr;
unsigned long port_state;
 
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
 
-   /* get bits are evaluated a gpio port register at a time */
-   for (i = 0; i < num_ports; i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
+   for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) {
+   port_addr = ws16c48gpio->base + offset / 8;
+   port_state = inb(port_addr) & gpio_mask;
 
-   /* word index for bits array */
-   word_index = BIT_WORD(bits_offset);
-
-   /* gpio offset within current word of bits array */
-   word_offset = bits_offset % BITS_PER_LONG;
-
-   /* mask of get bits for current gpio within current word */
-   word_mask = mask[word_index] & (port_mask << word_offset);
-   if (!word_mask) {
-   /* no get bits in this port so skip to next one */
-   continue;
-   }
-
-   /* read bits from current gpio port */
-   port_state = inb(ws16c48gpio->base + i);
-
-   /* store acquired bits at respective bits array offset */
-   bits[word_index] |= (port_state << word_offset) & word_mask;
+   bitmap_set_value8(bits, chip->ngpio, port_state, offset);
}
 
return 0;
@@ -203,39 +180,30 @@ static void ws16c48_gpio_set_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip);
-   unsigned int i;
-   const unsigned int gpio_reg_size = 8;
-   unsigned int port;
-   unsigned int iomask;
+   unsigned int offset;
+   unsigned long gpio_mask;
+   size_t index;
+   unsigned int port_addr;
unsigned int bitmask;
unsigned long flags;
 
-   /* set bits are evaluated a gpio register size at a time */
-   for (i = 0; i < chip->ngpio; i += gpio_reg_size) {
-   /* no more set bits in this mask word; skip to the next word */
-   if (!mask[BIT_WORD(i)]) {
-   i = (BIT_WORD(i) + 1) * BITS_PER_LONG - gpio_reg_size;
-   continue;
-   }
-
-   port = i / gpio_reg_size;
+   for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) {
+   index = offset / 8;
+   port_addr = ws16c48gpio->base + index;
 
/* mask out GPIO configured for input */
-   iomask = mask[BIT_WORD(i)] & ~ws16c48gpio->io_state[port];
-   bitmask = iomask & bits[BIT_WORD(i)];
+   gpio_mask &= ~ws16c48gpio->io_state[index];
+   bitmask = bitmap_get_value8(bits, chip->ngpio, offset) &
+ gpio_mask;
 
raw_spin_lock_irqsave(>lock, flags);
 
/* update output state data and set device gpio register */
-   ws16c48gpio->out_state[port] &= ~iomask;
-   ws16c48gpio->out_state[port] |= bitmask;
-   outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
+   ws16c48gpio->out_state[index] &= ~gpio_mask;
+   ws16c48gpio->out_state[index] |= bitmask;
+   outb(ws16c48gpio->out_state[index], port_addr);
 
raw_spin_unlock_irqrestore(>lock, flags);
-
-   /* prepare for next gpio register set */
-   mask[BIT_WORD(i)] >>= gpio_reg_size;
-   bits[BIT_WORD(i)] >>= gpio_reg_size;
}
 }
 
-- 
2.21.0



[PATCH v9 5/9] gpio: gpio-mm: Utilize for_each_set_clump8 macro

2019-03-02 Thread William Breathitt Gray
Replace verbose implementation in get_multiple/set_multiple callbacks
with for_each_set_clump8 macro to simplify code and improve clarity.

Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-gpio-mm.c | 73 +++--
 1 file changed, 22 insertions(+), 51 deletions(-)

diff --git a/drivers/gpio/gpio-gpio-mm.c b/drivers/gpio/gpio-gpio-mm.c
index 8c150fd68d9d..4c1037a005ab 100644
--- a/drivers/gpio/gpio-gpio-mm.c
+++ b/drivers/gpio/gpio-gpio-mm.c
@@ -172,46 +172,26 @@ static int gpiomm_gpio_get(struct gpio_chip *chip, 
unsigned int offset)
return !!(port_state & mask);
 }
 
+static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
+
 static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long 
*mask,
unsigned long *bits)
 {
struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
-   size_t i;
-   static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
-   const unsigned int gpio_reg_size = 8;
-   unsigned int bits_offset;
-   size_t word_index;
-   unsigned int word_offset;
-   unsigned long word_mask;
-   const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
+   unsigned int offset;
+   unsigned long gpio_mask;
+   const unsigned int ngpio = ARRAY_SIZE(ports) * 8;
+   unsigned int port_addr;
unsigned long port_state;
 
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
 
-   /* get bits are evaluated a gpio port register at a time */
-   for (i = 0; i < ARRAY_SIZE(ports); i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
-
-   /* word index for bits array */
-   word_index = BIT_WORD(bits_offset);
-
-   /* gpio offset within current word of bits array */
-   word_offset = bits_offset % BITS_PER_LONG;
-
-   /* mask of get bits for current gpio within current word */
-   word_mask = mask[word_index] & (port_mask << word_offset);
-   if (!word_mask) {
-   /* no get bits in this port so skip to next one */
-   continue;
-   }
-
-   /* read bits from current gpio port */
-   port_state = inb(gpiommgpio->base + ports[i]);
+   for_each_set_clump8(offset, gpio_mask, mask, ngpio) {
+   port_addr = gpiommgpio->base + ports[offset / 8];
+   port_state = inb(port_addr) & gpio_mask;
 
-   /* store acquired bits at respective bits array offset */
-   bits[word_index] |= (port_state << word_offset) & word_mask;
+   bitmap_set_value8(bits, ngpio, port_state, offset);
}
 
return 0;
@@ -242,37 +222,28 @@ static void gpiomm_gpio_set_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
-   unsigned int i;
-   const unsigned int gpio_reg_size = 8;
-   unsigned int port;
-   unsigned int out_port;
+   unsigned int offset;
+   unsigned long gpio_mask;
+   const unsigned int ngpio = ARRAY_SIZE(ports) * 8;
+   size_t index;
+   unsigned int port_addr;
unsigned int bitmask;
unsigned long flags;
 
-   /* set bits are evaluated a gpio register size at a time */
-   for (i = 0; i < chip->ngpio; i += gpio_reg_size) {
-   /* no more set bits in this mask word; skip to the next word */
-   if (!mask[BIT_WORD(i)]) {
-   i = (BIT_WORD(i) + 1) * BITS_PER_LONG - gpio_reg_size;
-   continue;
-   }
+   for_each_set_clump8(offset, gpio_mask, mask, ngpio) {
+   index = offset / 8;
+   port_addr = gpiommgpio->base + ports[index];
 
-   port = i / gpio_reg_size;
-   out_port = (port > 2) ? port + 1 : port;
-   bitmask = mask[BIT_WORD(i)] & bits[BIT_WORD(i)];
+   bitmask = bitmap_get_value8(bits, ngpio, offset) & gpio_mask;
 
spin_lock_irqsave(>lock, flags);
 
/* update output state data and set device gpio register */
-   gpiommgpio->out_state[port] &= ~mask[BIT_WORD(i)];
-   gpiommgpio->out_state[port] |= bitmask;
-   outb(gpiommgpio->out_state[port], gpiommgpio->base + out_port);
+   gpiommgpio->out_state[index] &= ~gpio_mask;
+   gpiommgpio->out_state[index] |= bitmask;
+   outb(gpiommgpio->out_state[index], port_addr);
 
spin_unlock_irqrestore(>lock, flags);
-
-   /* prepare for next gpio register set */
-   mask[BIT_WORD(i)] >>= gpio_reg_size;
-   bits[BIT_WORD(i)] >>= gpio_reg_size;
}
 }
 
-- 
2.21.0



[PATCH v9 3/9] gpio: 104-dio-48e: Utilize for_each_set_clump8 macro

2019-03-02 Thread William Breathitt Gray
Replace verbose implementation in get_multiple/set_multiple callbacks
with for_each_set_clump8 macro to simplify code and improve clarity.

Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-104-dio-48e.c | 73 ++---
 1 file changed, 22 insertions(+), 51 deletions(-)

diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c
index 92c8f944bf64..23413d90e944 100644
--- a/drivers/gpio/gpio-104-dio-48e.c
+++ b/drivers/gpio/gpio-104-dio-48e.c
@@ -183,46 +183,26 @@ static int dio48e_gpio_get(struct gpio_chip *chip, 
unsigned offset)
return !!(port_state & mask);
 }
 
+static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
+
 static int dio48e_gpio_get_multiple(struct gpio_chip *chip, unsigned long 
*mask,
unsigned long *bits)
 {
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
-   size_t i;
-   static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
-   const unsigned int gpio_reg_size = 8;
-   unsigned int bits_offset;
-   size_t word_index;
-   unsigned int word_offset;
-   unsigned long word_mask;
-   const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
+   unsigned int offset;
+   unsigned long gpio_mask;
+   const unsigned int ngpio = ARRAY_SIZE(ports) * 8;
+   unsigned int port_addr;
unsigned long port_state;
 
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
 
-   /* get bits are evaluated a gpio port register at a time */
-   for (i = 0; i < ARRAY_SIZE(ports); i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
-
-   /* word index for bits array */
-   word_index = BIT_WORD(bits_offset);
-
-   /* gpio offset within current word of bits array */
-   word_offset = bits_offset % BITS_PER_LONG;
-
-   /* mask of get bits for current gpio within current word */
-   word_mask = mask[word_index] & (port_mask << word_offset);
-   if (!word_mask) {
-   /* no get bits in this port so skip to next one */
-   continue;
-   }
-
-   /* read bits from current gpio port */
-   port_state = inb(dio48egpio->base + ports[i]);
+   for_each_set_clump8(offset, gpio_mask, mask, ngpio) {
+   port_addr = dio48egpio->base + ports[offset / 8];
+   port_state = inb(port_addr) & gpio_mask;
 
-   /* store acquired bits at respective bits array offset */
-   bits[word_index] |= (port_state << word_offset) & word_mask;
+   bitmap_set_value8(bits, ngpio, port_state, offset);
}
 
return 0;
@@ -252,37 +232,28 @@ static void dio48e_gpio_set_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
-   unsigned int i;
-   const unsigned int gpio_reg_size = 8;
-   unsigned int port;
-   unsigned int out_port;
+   unsigned int offset;
+   unsigned long gpio_mask;
+   const unsigned int ngpio = ARRAY_SIZE(ports) * 8;
+   size_t index;
+   unsigned int port_addr;
unsigned int bitmask;
unsigned long flags;
 
-   /* set bits are evaluated a gpio register size at a time */
-   for (i = 0; i < chip->ngpio; i += gpio_reg_size) {
-   /* no more set bits in this mask word; skip to the next word */
-   if (!mask[BIT_WORD(i)]) {
-   i = (BIT_WORD(i) + 1) * BITS_PER_LONG - gpio_reg_size;
-   continue;
-   }
+   for_each_set_clump8(offset, gpio_mask, mask, ngpio) {
+   index = offset / 8;
+   port_addr = dio48egpio->base + ports[index];
 
-   port = i / gpio_reg_size;
-   out_port = (port > 2) ? port + 1 : port;
-   bitmask = mask[BIT_WORD(i)] & bits[BIT_WORD(i)];
+   bitmask = bitmap_get_value8(bits, ngpio, offset) & gpio_mask;
 
raw_spin_lock_irqsave(>lock, flags);
 
/* update output state data and set device gpio register */
-   dio48egpio->out_state[port] &= ~mask[BIT_WORD(i)];
-   dio48egpio->out_state[port] |= bitmask;
-   outb(dio48egpio->out_state[port], dio48egpio->base + out_port);
+   dio48egpio->out_state[index] &= ~gpio_mask;
+   dio48egpio->out_state[index] |= bitmask;
+   outb(dio48egpio->out_state[index], port_addr);
 
raw_spin_unlock_irqrestore(>lock, flags);
-
-   /* prepare for next gpio register set */
-   mask[BIT_WORD(i)] >>= gpio_reg_size;
-   bits[BIT_WORD(i)] >>= gpio_reg_size;
}
 }
 
-- 
2.21.0



[PATCH v9 4/9] gpio: 104-idi-48: Utilize for_each_set_clump8 macro

2019-03-02 Thread William Breathitt Gray
Replace verbose implementation in get_multiple/set_multiple callbacks
with for_each_set_clump8 macro to simplify code and improve clarity.

Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-104-idi-48.c | 37 --
 1 file changed, 8 insertions(+), 29 deletions(-)

diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c
index 88dc6f2449f6..59c571aecf9a 100644
--- a/drivers/gpio/gpio-104-idi-48.c
+++ b/drivers/gpio/gpio-104-idi-48.c
@@ -93,42 +93,21 @@ static int idi_48_gpio_get_multiple(struct gpio_chip *chip, 
unsigned long *mask,
unsigned long *bits)
 {
struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
-   size_t i;
+   unsigned int offset;
+   unsigned long gpio_mask;
static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
-   const unsigned int gpio_reg_size = 8;
-   unsigned int bits_offset;
-   size_t word_index;
-   unsigned int word_offset;
-   unsigned long word_mask;
-   const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
+   const unsigned int ngpio = ARRAY_SIZE(ports) * 8;
+   unsigned int port_addr;
unsigned long port_state;
 
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
 
-   /* get bits are evaluated a gpio port register at a time */
-   for (i = 0; i < ARRAY_SIZE(ports); i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
+   for_each_set_clump8(offset, gpio_mask, mask, ngpio) {
+   port_addr = idi48gpio->base + ports[offset / 8];
+   port_state = inb(port_addr) & gpio_mask;
 
-   /* word index for bits array */
-   word_index = BIT_WORD(bits_offset);
-
-   /* gpio offset within current word of bits array */
-   word_offset = bits_offset % BITS_PER_LONG;
-
-   /* mask of get bits for current gpio within current word */
-   word_mask = mask[word_index] & (port_mask << word_offset);
-   if (!word_mask) {
-   /* no get bits in this port so skip to next one */
-   continue;
-   }
-
-   /* read bits from current gpio port */
-   port_state = inb(idi48gpio->base + ports[i]);
-
-   /* store acquired bits at respective bits array offset */
-   bits[word_index] |= (port_state << word_offset) & word_mask;
+   bitmap_set_value8(bits, ngpio, port_state, offset);
}
 
return 0;
-- 
2.21.0



[PATCH v9 1/9] bitops: Introduce the for_each_set_clump8 macro

2019-03-02 Thread William Breathitt Gray
This macro iterates for each 8-bit group of bits (clump) with set bits,
within a bitmap memory region. For each iteration, "start" is set to the
bit offset of the found clump, while the respective clump value is
stored to the location pointed by "clump". Additionally, the
bitmap_get_value8 and bitmap_set_value8 functions are introduced to
respectively get and set an 8-bit value in a bitmap memory region.

Suggested-by: Andy Shevchenko 
Suggested-by: Rasmus Villemoes 
Cc: Arnd Bergmann 
Cc: Andrew Morton 
Reviewed-by: Andy Shevchenko 
Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 include/asm-generic/bitops/find.h | 14 ++
 include/linux/bitops.h|  5 ++
 lib/find_bit.c| 81 +++
 3 files changed, 100 insertions(+)

diff --git a/include/asm-generic/bitops/find.h 
b/include/asm-generic/bitops/find.h
index 8a1ee10014de..9a76adff59c6 100644
--- a/include/asm-generic/bitops/find.h
+++ b/include/asm-generic/bitops/find.h
@@ -80,4 +80,18 @@ extern unsigned long find_first_zero_bit(const unsigned long 
*addr,
 
 #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
 
+unsigned long bitmap_get_value8(const unsigned long *const bitmap,
+   const unsigned int size,
+   const unsigned int start);
+
+void bitmap_set_value8(unsigned long *const bitmap, const unsigned int size,
+  const unsigned long value, const unsigned int start);
+
+unsigned int find_next_clump8(unsigned long *const clump,
+ const unsigned long *const addr,
+ unsigned int offset, const unsigned int size);
+
+#define find_first_clump8(clump, bits, size) \
+   find_next_clump8((clump), (bits), 0, (size))
+
 #endif /*_ASM_GENERIC_BITOPS_FIND_H_ */
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 705f7c442691..61c10f20079e 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -40,6 +40,11 @@ extern unsigned long __sw_hweight64(__u64 w);
 (bit) < (size);\
 (bit) = find_next_zero_bit((addr), (size), (bit) + 1))
 
+#define for_each_set_clump8(start, clump, bits, size) \
+   for ((start) = find_first_clump8(&(clump), (bits), (size)); \
+(start) < (size); \
+(start) = find_next_clump8(&(clump), (bits), (start) + 8, (size)))
+
 static inline int get_bitmask_order(unsigned int count)
 {
int order;
diff --git a/lib/find_bit.c b/lib/find_bit.c
index ee3df93ba69a..c2af1f013ea2 100644
--- a/lib/find_bit.c
+++ b/lib/find_bit.c
@@ -218,3 +218,84 @@ EXPORT_SYMBOL(find_next_bit_le);
 #endif
 
 #endif /* __BIG_ENDIAN */
+
+/**
+ * bitmap_get_value8 - get an 8-bit value within a memory region
+ * @bitmap: address to the bitmap memory region
+ * @size: bitmap size in number of bits
+ * @start: bit offset of the 8-bit value
+ *
+ * Returns the 8-bit value located at the @start bit offset within the @bitmap
+ * memory region.
+ */
+unsigned long bitmap_get_value8(const unsigned long *const bitmap,
+   const unsigned int size,
+   const unsigned int start)
+{
+   const size_t index = BIT_WORD(start);
+   const unsigned int offset = start % BITS_PER_LONG;
+   const unsigned int low_width = (offset + 8 > BITS_PER_LONG) ?
+  BITS_PER_LONG - offset : 8;
+   const unsigned long low = bitmap[index] >> offset;
+   const unsigned long high = (low_width < 8 && start + 8 <= size) ?
+  bitmap[index + 1] << low_width : 0;
+
+   return (low | high) & 0xFF;
+}
+EXPORT_SYMBOL(bitmap_get_value8);
+
+/**
+ * bitmap_set_value8 - set an 8-bit value within a memory region
+ * @bitmap: address to the bitmap memory region
+ * @size: bitmap size in number of bits
+ * @value: the 8-bit value; values wider than 8 bits may clobber bitmap
+ * @start: bit offset of the 8-bit value
+ */
+void bitmap_set_value8(unsigned long *const bitmap, const unsigned int size,
+  const unsigned long value, const unsigned int start)
+{
+   const size_t index = BIT_WORD(start);
+   const unsigned int offset = start % BITS_PER_LONG;
+   const unsigned int low_width = (offset + 8 > BITS_PER_LONG) ?
+  BITS_PER_LONG - offset : 8;
+   const unsigned long low_mask = GENMASK(offset + low_width - 1, offset);
+   const unsigned int high_width = 8 - low_width;
+   const unsigned long high_mask = GENMASK(high_width - 1, 0);
+
+   /* set lower portion */
+   bitmap[index] &= ~low_mask;
+   bitmap[index] |= value << offset;
+
+   /* set higher portion if space available in bitmap */
+   if (high_width && start + 8 <= size) {
+   bitmap[index + 1] &= ~high_mask;
+   bitmap[index + 1] |= value >> low_width;
+   }
+}

[PATCH v9 2/9] lib/test_bitmap.c: Add for_each_set_clump8 test cases

2019-03-02 Thread William Breathitt Gray
The introduction of the for_each_set_clump8 macro warrants test cases to
verify the implementation. This patch adds test case checks for whether
an out-of-bounds clump index is returned, a zero clump is returned, or
the returned clump value differs from the expected clump value.

Cc: Andrew Morton 
Cc: Rasmus Villemoes 
Reviewed-by: Andy Shevchenko 
Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 lib/test_bitmap.c | 65 +++
 1 file changed, 65 insertions(+)

diff --git a/lib/test_bitmap.c b/lib/test_bitmap.c
index 6cd7d0740005..66ddb3fb98cb 100644
--- a/lib/test_bitmap.c
+++ b/lib/test_bitmap.c
@@ -88,6 +88,36 @@ __check_eq_u32_array(const char *srcfile, unsigned int line,
return true;
 }
 
+static bool __init __check_eq_clump8(const char *srcfile, unsigned int line,
+   const unsigned int offset,
+   const unsigned int size,
+   const unsigned char *const clump_exp,
+   const unsigned long *const clump)
+{
+   unsigned long exp;
+
+   if (offset >= size) {
+   pr_warn("[%s:%u] bit offset for clump out-of-bounds: expected 
less than %u, got %u\n",
+   srcfile, line, size, offset);
+   return false;
+   }
+
+   exp = clump_exp[offset / 8];
+   if (!exp) {
+   pr_warn("[%s:%u] bit offset for zero clump: expected nonzero 
clump, got bit offset %u with clump value 0",
+   srcfile, line, offset);
+   return false;
+   }
+
+   if (*clump != exp) {
+   pr_warn("[%s:%u] expected clump value of 0x%lX, got clump value 
of 0x%lX",
+   srcfile, line, exp, *clump);
+   return false;
+   }
+
+   return true;
+}
+
 #define __expect_eq(suffix, ...)   \
({  \
int result = 0; \
@@ -104,6 +134,7 @@ __check_eq_u32_array(const char *srcfile, unsigned int line,
 #define expect_eq_bitmap(...)  __expect_eq(bitmap, ##__VA_ARGS__)
 #define expect_eq_pbl(...) __expect_eq(pbl, ##__VA_ARGS__)
 #define expect_eq_u32_array(...)   __expect_eq(u32_array, ##__VA_ARGS__)
+#define expect_eq_clump8(...)  __expect_eq(clump8, ##__VA_ARGS__)
 
 static void __init test_zero_clear(void)
 {
@@ -361,6 +392,39 @@ static void noinline __init test_mem_optimisations(void)
}
 }
 
+static const unsigned char clump_exp[] __initconst = {
+   0x01,   /* 1 bit set */
+   0x02,   /* non-edge 1 bit set */
+   0x00,   /* zero bits set */
+   0x28,   /* 3 bits set across 4-bit boundary */
+   0x28,   /* Repeated clump */
+   0x0F,   /* 4 bits set */
+   0xFF,   /* all bits set */
+   0x05,   /* non-adjacent 2 bits set */
+};
+
+static void __init test_for_each_set_clump8(void)
+{
+#define CLUMP_EXP_NUMBITS 64
+   DECLARE_BITMAP(bits, CLUMP_EXP_NUMBITS);
+   unsigned int start;
+   unsigned long clump;
+
+   /* set bitmap to test case */
+   bitmap_zero(bits, CLUMP_EXP_NUMBITS);
+   bitmap_set(bits, 0, 1); /* 0x01 */
+   bitmap_set(bits, 8, 1); /* 0x02 */
+   bitmap_set(bits, 27, 3);/* 0x28 */
+   bitmap_set(bits, 35, 3);/* 0x28 */
+   bitmap_set(bits, 40, 4);/* 0x0F */
+   bitmap_set(bits, 48, 8);/* 0xFF */
+   bitmap_set(bits, 56, 1);/* 0x05 - part 1 */
+   bitmap_set(bits, 58, 1);/* 0x05 - part 2 */
+
+   for_each_set_clump8(start, clump, bits, CLUMP_EXP_NUMBITS)
+   expect_eq_clump8(start, CLUMP_EXP_NUMBITS, clump_exp, );
+}
+
 static int __init test_bitmap_init(void)
 {
test_zero_clear();
@@ -369,6 +433,7 @@ static int __init test_bitmap_init(void)
test_bitmap_arr32();
test_bitmap_parselist();
test_mem_optimisations();
+   test_for_each_set_clump8();
 
if (failed_tests == 0)
pr_info("all %u tests passed\n", total_tests);
-- 
2.21.0



[PATCH v9 0/9] Introduce the for_each_set_clump8 macro

2019-03-02 Thread William Breathitt Gray
Changes in v9:
  - Return unsigned long for bitmap_get_value8 for consistency

While adding GPIO get_multiple/set_multiple callback support for various
drivers, I noticed a pattern of looping manifesting that would be useful
standardized as a macro.

This patchset introduces the for_each_set_clump8 macro and utilizes it
in several GPIO drivers. The for_each_set_clump macro8 facilitates a
for-loop syntax that iterates over a memory region entire groups of set
bits at a time.

For example, suppose you would like to iterate over a 32-bit integer 8
bits at a time, skipping over 8-bit groups with no set bit, where
 represents the current 8-bit group:

Example:1010   00110011
First loop: 1010   
Second loop:1010   00110011
Third loop:    00110011

Each iteration of the loop returns the next 8-bit group that has at
least one set bit.

The for_each_set_clump8 macro has four parameters:

* start: set to the bit offset of the current clump
* clump: set to the current clump value
* bits: bitmap to search within
* size: bitmap size in number of bits

In this version of the patchset, the for_each_set_clump macro has been
reimplemented and simplified based on the suggestions provided by Rasmus
Villemoes and Andy Shevchenko in the version 4 submission.

In particular, the function of the for_each_set_clump macro has been
restricted to handle only 8-bit clumps; the drivers that use the
for_each_set_clump macro only handle 8-bit ports so a generic
for_each_set_clump implementation is not necessary. Thus, a solution for
large clumps (i.e. those larger than the width of a bitmap word) can be
postponed until a driver appears that actually requires such a generic
for_each_set_clump implementation.

For what it's worth, a semi-generic for_each_set_clump (i.e. for clumps
smaller than the width of a bitmap word) can be implemented by simply
replacing the hardcoded '8' and '0xFF' instances with respective
variables. I have not yet had a need for such an implementation, and
since it falls short of a true generic for_each_set_clump function, I
have decided to forgo such an implementation for now.

In addition, the bitmap_get_value8 and bitmap_set_value8 functions are
introduced to get and set 8-bit values respectively. Their use is based
on the behavior suggested in the patchset version 4 review.

William Breathitt Gray (9):
  bitops: Introduce the for_each_set_clump8 macro
  lib/test_bitmap.c: Add for_each_set_clump8 test cases
  gpio: 104-dio-48e: Utilize for_each_set_clump8 macro
  gpio: 104-idi-48: Utilize for_each_set_clump8 macro
  gpio: gpio-mm: Utilize for_each_set_clump8 macro
  gpio: ws16c48: Utilize for_each_set_clump8 macro
  gpio: pci-idio-16: Utilize for_each_set_clump8 macro
  gpio: pcie-idio-24: Utilize for_each_set_clump8 macro
  gpio: uniphier: Utilize for_each_set_clump8 macro

 drivers/gpio/gpio-104-dio-48e.c   |  73 ++--
 drivers/gpio/gpio-104-idi-48.c|  37 +++---
 drivers/gpio/gpio-gpio-mm.c   |  73 ++--
 drivers/gpio/gpio-pci-idio-16.c   |  75 
 drivers/gpio/gpio-pcie-idio-24.c  | 111 +++---
 drivers/gpio/gpio-uniphier.c  |  16 ++---
 drivers/gpio/gpio-ws16c48.c   |  72 ++-
 include/asm-generic/bitops/find.h |  14 
 include/linux/bitops.h|   5 ++
 lib/find_bit.c|  81 ++
 lib/test_bitmap.c |  65 +
 11 files changed, 313 insertions(+), 309 deletions(-)

-- 
2.21.0



[PATCH v3] mm/memory.c: do_fault: avoid usage of stale vm_area_struct

2019-03-02 Thread Jan Stancek
LTP testcase mtest06 [1] can trigger a crash on s390x running 5.0.0-rc8.
This is a stress test, where one thread mmaps/writes/munmaps memory area
and other thread is trying to read from it:

  CPU: 0 PID: 2611 Comm: mmap1 Not tainted 5.0.0-rc8+ #51
  Hardware name: IBM 2964 N63 400 (z/VM 6.4.0)
  Krnl PSW : 0404e0018000 001ac8d8 (__lock_acquire+0x7/0x7a8)
  Call Trace:
  ([<>]   (null))
   [<001adae4>] lock_acquire+0xec/0x258
   [<0080d1ac>] _raw_spin_lock_bh+0x5c/0x98
   [<0012a780>] page_table_free+0x48/0x1a8
   [<002f6e54>] do_fault+0xdc/0x670
   [<002fadae>] __handle_mm_fault+0x416/0x5f0
   [<002fb138>] handle_mm_fault+0x1b0/0x320
   [<001248cc>] do_dat_exception+0x19c/0x2c8
   [<0080e5ee>] pgm_check_handler+0x19e/0x200

page_table_free() is called with NULL mm parameter, but because
"0" is a valid address on s390 (see S390_lowcore), it keeps
going until it eventually crashes in lockdep's lock_acquire.
This crash is reproducible at least since 4.14.

Problem is that "vmf->vma" used in do_fault() can become stale.
Because mmap_sem may be released, other threads can come in,
call munmap() and cause "vma" be returned to kmem cache, and
get zeroed/re-initialized and re-used:

handle_mm_fault   |
  __handle_mm_fault   |
do_fault  |
  vma = vmf->vma  |
  do_read_fault   |
__do_fault|
  vma->vm_ops->fault(vmf);|
mmap_sem is released  |
  |
  | do_munmap()
  |   remove_vma_list()
  | remove_vma()
  |   vm_area_free()
  | # vma is released
  | ...
  | # same vma is allocated
  | # from kmem cache
  | do_mmap()
  |   vm_area_alloc()
  | memset(vma, 0, ...)
  |
  pte_free(vma->vm_mm, ...);  |
page_table_free   |
  spin_lock_bh(>context.lock);|
   |

Cache mm_struct to avoid using potentially stale "vma".

[1] 
https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/mem/mtest06/mmap1.c

Signed-off-by: Jan Stancek 
Reviewed-by: Andrea Arcangeli 
---
 mm/memory.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/mm/memory.c b/mm/memory.c
index e11ca9dd823f..e8d69ade5acc 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3517,10 +3517,13 @@ static vm_fault_t do_shared_fault(struct vm_fault *vmf)
  * but allow concurrent faults).
  * The mmap_sem may have been released depending on flags and our
  * return value.  See filemap_fault() and __lock_page_or_retry().
+ * If mmap_sem is released, vma may become invalid (for example
+ * by other thread calling munmap()).
  */
 static vm_fault_t do_fault(struct vm_fault *vmf)
 {
struct vm_area_struct *vma = vmf->vma;
+   struct mm_struct *vm_mm = vma->vm_mm;
vm_fault_t ret;
 
/*
@@ -3561,7 +3564,7 @@ static vm_fault_t do_fault(struct vm_fault *vmf)
 
/* preallocated pagetable is unused: free it */
if (vmf->prealloc_pte) {
-   pte_free(vma->vm_mm, vmf->prealloc_pte);
+   pte_free(vm_mm, vmf->prealloc_pte);
vmf->prealloc_pte = NULL;
}
return ret;
-- 
1.8.3.1



Re: [PATCH v2] mm/memory.c: do_fault: avoid usage of stale vm_area_struct

2019-03-02 Thread Jan Stancek



- Original Message -
> Hello Jan,
> 
> On Sat, Mar 02, 2019 at 07:19:39PM +0100, Jan Stancek wrote:
> > +   struct mm_struct *vm_mm = READ_ONCE(vma->vm_mm);
> 
> The vma->vm_mm cannot change under gcc there, so no need of
> READ_ONCE. The release of mmap_sem has release semantics so the
> vma->vm_mm access cannot be reordered after up_read(mmap_sem) either.
> 
> Other than the above detail:
> 
> Reviewed-by: Andrea Arcangeli 

Thank you for review, I dropped READ_ONCE and sent v3 with your
Reviewed-by included. I also successfully re-ran tests over-night.

> Would this not need a corresponding WRITE_ONCE() in vma_init() ?

There's at least 2 context switches between, so I think it wouldn't matter.
My concern was gcc optimizing out vm_mm, and vma->vm_mm access happening only
after do_read_fault().



Re: [PATCH v2 03/13] mm: Add generic p?d_large() macros

2019-03-02 Thread Mike Rapoport
On Fri, Mar 01, 2019 at 01:39:30PM +, Steven Price wrote:
> On 01/03/2019 12:30, Kirill A. Shutemov wrote:
> > On Fri, Mar 01, 2019 at 01:53:01PM +0200, Mike Rapoport wrote:
> >> Him Kirill,
> >>
> >> On Fri, Feb 22, 2019 at 12:06:18AM +0300, Kirill A. Shutemov wrote:
> >>> On Thu, Feb 21, 2019 at 05:16:46PM +, Steven Price wrote:
> >> Note that in terms of the new page walking code, these new defines are
> >> only used when walking a page table without a VMA (which isn't 
> >> currently
> >> done), so architectures which don't use p?d_large currently will work
> >> fine with the generic versions. They only need to provide meaningful
> >> definitions when switching to use the walk-without-a-VMA functionality.
> >
> > How other architectures would know that they need to provide the helpers
> > to get walk-without-a-VMA functionality? This looks very fragile to me.
> 
>  Yes, you've got a good point there. This would apply to the p?d_large
>  macros as well - any arch which (inadvertently) uses the generic version
>  is likely to be fragile/broken.
> 
>  I think probably the best option here is to scrap the generic versions
>  altogether and simply introduce a ARCH_HAS_PXD_LARGE config option which
>  would enable the new functionality to those arches that opt-in. Do you
>  think this would be less fragile?
> >>>
> >>> These helpers are useful beyond pagewalker.
> >>>
> >>> Can we actually do some grinding and make *all* archs to provide correct
> >>> helpers? Yes, it's tedious, but not that bad.
> >>
> >> Many architectures simply cannot support non-leaf entries at the higher
> >> levels. I think letting the use a generic helper actually does make sense.
> > 
> > I disagree.
> > 
> > It's makes sense if the level doesn't exists on the arch.
> 
> This is what patch 24 [1] of the series does - if the level doesn't
> exist then appropriate stubs are provided.
> 
> > But if the level exists, it will be less frugile to ask the arch to
> > provide the helper. Even if it is dummy always-false.
> 
> The problem (as I see it), is we need a reliable set of p?d_large()
> implementations to be able to walk arbitrary page tables. Either the
> entire functionality of walking page tables without a VMA has to be an
> opt-in per architecture, or we need to mandate that every architecture
> provide these implementations.

I agree that we need a reliable set of p?d_large(), but I'm still not
convinced that every architecture should provide these.

Why having generic versions if p?d_large() is more fragile, than e.g.
p??__access_permitted() or atomic ops?

IMHO, adding those functions/macros for architectures that support large
pages and providing defines to avoid override of 'static inline' implementations
would be robust enough and will avoid unnecessary stubs in architectures
that don't have large pages.
 
> I could provide an asm-generic header to provide a complete set of dummy
> implementations for architectures that don't support large pages at all,
> but that seems a bit overkill when most architectures only need to
> define 2 or 3 implementations (the rest being provided by the
> folded-levels automatically).
> 
> Thanks,
> 
> Steve
> 
> [1]
> https://lore.kernel.org/lkml/20190227170608.27963-25-steven.pr...@arm.com/

-- 
Sincerely yours,
Mike.



RE: [PATCH 10/12] percpu: make pcpu_block_md generic

2019-03-02 Thread Peng Fan


> -Original Message-
> From: owner-linux...@kvack.org [mailto:owner-linux...@kvack.org] On
> Behalf Of Dennis Zhou
> Sent: 2019年2月28日 10:19
> To: Dennis Zhou ; Tejun Heo ; Christoph
> Lameter 
> Cc: Vlad Buslov ; kernel-t...@fb.com;
> linux...@kvack.org; linux-kernel@vger.kernel.org
> Subject: [PATCH 10/12] percpu: make pcpu_block_md generic
> 
> In reality, a chunk is just a block covering a larger number of bits.
> The hints themselves are one in the same. Rather than maintaining the hints
> separately, first introduce nr_bits to genericize
> pcpu_block_update() to correctly maintain block->right_free. The next patch
> will convert chunk hints to be managed as a pcpu_block_md.
> 
> Signed-off-by: Dennis Zhou 
> ---
>  mm/percpu-internal.h |  1 +
>  mm/percpu.c  | 20 +---
>  2 files changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/mm/percpu-internal.h b/mm/percpu-internal.h index
> ec58b244545d..119bd1119aa7 100644
> --- a/mm/percpu-internal.h
> +++ b/mm/percpu-internal.h
> @@ -28,6 +28,7 @@ struct pcpu_block_md {
>   int right_free; /* size of free space along
>  the right side of the block 
> */
>   int first_free; /* block position of first free
> */
> + int nr_bits;/* total bits responsible for */
>  };
> 
>  struct pcpu_chunk {
> diff --git a/mm/percpu.c b/mm/percpu.c
> index e51c151ed692..7cdf14c242de 100644
> --- a/mm/percpu.c
> +++ b/mm/percpu.c
> @@ -658,7 +658,7 @@ static void pcpu_block_update(struct pcpu_block_md
> *block, int start, int end)
>   if (start == 0)
>   block->left_free = contig;
> 
> - if (end == PCPU_BITMAP_BLOCK_BITS)
> + if (end == block->nr_bits)
>   block->right_free = contig;
> 
>   if (contig > block->contig_hint) {
> @@ -1271,18 +1271,24 @@ static void pcpu_free_area(struct pcpu_chunk
> *chunk, int off)
>   pcpu_chunk_relocate(chunk, oslot);
>  }
> 
> +static void pcpu_init_md_block(struct pcpu_block_md *block, int
> +nr_bits) {
> + block->scan_hint = 0;
> + block->contig_hint = nr_bits;
> + block->left_free = nr_bits;
> + block->right_free = nr_bits;
> + block->first_free = 0;
> + block->nr_bits = nr_bits;
> +}
> +
>  static void pcpu_init_md_blocks(struct pcpu_chunk *chunk)  {
>   struct pcpu_block_md *md_block;
> 
>   for (md_block = chunk->md_blocks;
>md_block != chunk->md_blocks + pcpu_chunk_nr_blocks(chunk);
> -  md_block++) {
> - md_block->scan_hint = 0;
> - md_block->contig_hint = PCPU_BITMAP_BLOCK_BITS;
> - md_block->left_free = PCPU_BITMAP_BLOCK_BITS;
> - md_block->right_free = PCPU_BITMAP_BLOCK_BITS;
> - }
> +  md_block++)
> + pcpu_init_md_block(md_block, PCPU_BITMAP_BLOCK_BITS);
>  }

Reviewed-by: Peng Fan 

> 
>  /**
> --
> 2.17.1



Re

2019-03-02 Thread Pablo Mancilla
Good day,
I did send you an email on charity works and I
dont know if you got it.Please reach me for updates or let me know if to
resend

Pablo Mancilla


RE: [PATCH 07/12] percpu: add block level scan_hint

2019-03-02 Thread Peng Fan
Hi Dennis

> -Original Message-
> From: owner-linux...@kvack.org [mailto:owner-linux...@kvack.org] On
> Behalf Of Dennis Zhou
> Sent: 2019年2月28日 10:19
> To: Dennis Zhou ; Tejun Heo ; Christoph
> Lameter 
> Cc: Vlad Buslov ; kernel-t...@fb.com;
> linux...@kvack.org; linux-kernel@vger.kernel.org
> Subject: [PATCH 07/12] percpu: add block level scan_hint
> 
> Fragmentation can cause both blocks and chunks to have an early first_firee
> bit available, but only able to satisfy allocations much later on. This patch
> introduces a scan_hint to help mitigate some unnecessary scanning.
> 
> The scan_hint remembers the largest area prior to the contig_hint. If the
> contig_hint == scan_hint, then scan_hint_start > contig_hint_start.
> This is necessary for scan_hint discovery when refreshing a block.
> 
> Signed-off-by: Dennis Zhou 
> ---
>  mm/percpu-internal.h |   9 
>  mm/percpu.c  | 101
> ---
>  2 files changed, 103 insertions(+), 7 deletions(-)
> 
> diff --git a/mm/percpu-internal.h b/mm/percpu-internal.h index
> b1739dc06b73..ec58b244545d 100644
> --- a/mm/percpu-internal.h
> +++ b/mm/percpu-internal.h
> @@ -9,8 +9,17 @@
>   * pcpu_block_md is the metadata block struct.
>   * Each chunk's bitmap is split into a number of full blocks.
>   * All units are in terms of bits.
> + *
> + * The scan hint is the largest known contiguous area before the contig hint.
> + * It is not necessarily the actual largest contig hint though.  There
> + is an
> + * invariant that the scan_hint_start > contig_hint_start iff
> + * scan_hint == contig_hint.  This is necessary because when scanning
> + forward,
> + * we don't know if a new contig hint would be better than the current one.
>   */
>  struct pcpu_block_md {
> + int scan_hint;  /* scan hint for block */
> + int scan_hint_start; /* block relative starting
> + position of the scan hint */
>   int contig_hint;/* contig hint for block */
>   int contig_hint_start; /* block relative starting
> position of the contig 
> hint */ diff --git
> a/mm/percpu.c b/mm/percpu.c index 967c9cc3a928..df1aacf58ac8 100644
> --- a/mm/percpu.c
> +++ b/mm/percpu.c
> @@ -320,6 +320,34 @@ static unsigned long pcpu_block_off_to_off(int index,
> int off)
>   return index * PCPU_BITMAP_BLOCK_BITS + off;  }
> 
> +/*
> + * pcpu_next_hint - determine which hint to use
> + * @block: block of interest
> + * @alloc_bits: size of allocation
> + *
> + * This determines if we should scan based on the scan_hint or first_free.
> + * In general, we want to scan from first_free to fulfill allocations
> +by
> + * first fit.  However, if we know a scan_hint at position
> +scan_hint_start
> + * cannot fulfill an allocation, we can begin scanning from there
> +knowing
> + * the contig_hint will be our fallback.
> + */
> +static int pcpu_next_hint(struct pcpu_block_md *block, int alloc_bits)
> +{
> + /*
> +  * The three conditions below determine if we can skip past the
> +  * scan_hint.  First, does the scan hint exist.  Second, is the
> +  * contig_hint after the scan_hint (possibly not true iff
> +  * contig_hint == scan_hint).  Third, is the allocation request
> +  * larger than the scan_hint.
> +  */
> + if (block->scan_hint &&
> + block->contig_hint_start > block->scan_hint_start &&
> + alloc_bits > block->scan_hint)
> + return block->scan_hint_start + block->scan_hint;
> +
> + return block->first_free;
> +}
> +
>  /**
>   * pcpu_next_md_free_region - finds the next hint free area
>   * @chunk: chunk of interest
> @@ -415,9 +443,11 @@ static void pcpu_next_fit_region(struct pcpu_chunk
> *chunk, int alloc_bits,
>   if (block->contig_hint &&
>   block->contig_hint_start >= block_off &&
>   block->contig_hint >= *bits + alloc_bits) {
> + int start = pcpu_next_hint(block, alloc_bits);
> +
>   *bits += alloc_bits + block->contig_hint_start -
> -  block->first_free;
> - *bit_off = pcpu_block_off_to_off(i, block->first_free);
> +  start;

This might not relevant to this patch.
Not sure it is intended or not.
For `alloc_bits + block->contig_hink_start - [block->first_free or start]`
If the reason is to let pcpu_is_populated return a proper next_off when 
pcpu_is_populated
fail, it makes sense. If not, why not just use *bits += alloc_bits.

> + *bit_off = pcpu_block_off_to_off(i, start);
>   return;
>   }
>   /* reset to satisfy the second predicate above */ @@ -632,12
> +662,57 @@ static void pcpu_block_update(struct pcpu_block_md *block, int
> start, int end)
> 

RE: [PATCH 06/12] percpu: set PCPU_BITMAP_BLOCK_SIZE to PAGE_SIZE

2019-03-02 Thread Peng Fan


> -Original Message-
> From: owner-linux...@kvack.org [mailto:owner-linux...@kvack.org] On
> Behalf Of Dennis Zhou
> Sent: 2019年2月28日 10:19
> To: Dennis Zhou ; Tejun Heo ; Christoph
> Lameter 
> Cc: Vlad Buslov ; kernel-t...@fb.com;
> linux...@kvack.org; linux-kernel@vger.kernel.org
> Subject: [PATCH 06/12] percpu: set PCPU_BITMAP_BLOCK_SIZE to PAGE_SIZE
> 
> Previously, block size was flexible based on the constraint that the
> GCD(PCPU_BITMAP_BLOCK_SIZE, PAGE_SIZE) > 1. However, this carried the
> overhead that keeping a floating number of populated free pages required
> scanning over the free regions of a chunk.
> 
> Setting the block size to be fixed at PAGE_SIZE lets us know when an empty
> page becomes used as we will break a full contig_hint of a block.
> This means we no longer have to scan the whole chunk upon breaking a
> contig_hint which empty page management piggybacks off. A later patch
> takes advantage of this to optimize the allocation path by only scanning
> forward using the scan_hint introduced later too.
> 
> Signed-off-by: Dennis Zhou 
> ---
>  include/linux/percpu.h |  12 ++---
>  mm/percpu-km.c |   2 +-
>  mm/percpu.c| 111 +
>  3 files changed, 49 insertions(+), 76 deletions(-)
> 
> diff --git a/include/linux/percpu.h b/include/linux/percpu.h index
> 70b7123f38c7..9909dc0e273a 100644
> --- a/include/linux/percpu.h
> +++ b/include/linux/percpu.h
> @@ -26,16 +26,10 @@
>  #define PCPU_MIN_ALLOC_SHIFT 2
>  #define PCPU_MIN_ALLOC_SIZE  (1 << PCPU_MIN_ALLOC_SHIFT)
> 
> -/* number of bits per page, used to trigger a scan if blocks are > PAGE_SIZE
> */
> -#define PCPU_BITS_PER_PAGE   (PAGE_SIZE >>
> PCPU_MIN_ALLOC_SHIFT)
> -
>  /*
> - * This determines the size of each metadata block.  There are several
> subtle
> - * constraints around this constant.  The reserved region must be a multiple
> of
> - * PCPU_BITMAP_BLOCK_SIZE.  Additionally, PCPU_BITMAP_BLOCK_SIZE
> must be a
> - * multiple of PAGE_SIZE or PAGE_SIZE must be a multiple of
> - * PCPU_BITMAP_BLOCK_SIZE to align with the populated page map. The
> unit_size
> - * also has to be a multiple of PCPU_BITMAP_BLOCK_SIZE to ensure full
> blocks.
> + * The PCPU_BITMAP_BLOCK_SIZE must be the same size as PAGE_SIZE as
> the
> + * updating of hints is used to manage the nr_empty_pop_pages in both
> + * the chunk and globally.
>   */
>  #define PCPU_BITMAP_BLOCK_SIZE   PAGE_SIZE
>  #define PCPU_BITMAP_BLOCK_BITS   (PCPU_BITMAP_BLOCK_SIZE >>
>   \
> diff --git a/mm/percpu-km.c b/mm/percpu-km.c index
> 0f643dc2dc65..c10bf7466596 100644
> --- a/mm/percpu-km.c
> +++ b/mm/percpu-km.c
> @@ -70,7 +70,7 @@ static struct pcpu_chunk *pcpu_create_chunk(gfp_t
> gfp)
>   chunk->base_addr = page_address(pages) - pcpu_group_offsets[0];
> 
>   spin_lock_irqsave(_lock, flags);
> - pcpu_chunk_populated(chunk, 0, nr_pages, false);
> + pcpu_chunk_populated(chunk, 0, nr_pages);
>   spin_unlock_irqrestore(_lock, flags);
> 
>   pcpu_stats_chunk_alloc();
> diff --git a/mm/percpu.c b/mm/percpu.c
> index 3d7deece9556..967c9cc3a928 100644
> --- a/mm/percpu.c
> +++ b/mm/percpu.c
> @@ -527,37 +527,21 @@ static void pcpu_chunk_relocate(struct
> pcpu_chunk *chunk, int oslot)
>   __pcpu_chunk_move(chunk, nslot, oslot < nslot);  }
> 
> -/**
> - * pcpu_cnt_pop_pages- counts populated backing pages in range
> +/*
> + * pcpu_update_empty_pages - update empty page counters
>   * @chunk: chunk of interest
> - * @bit_off: start offset
> - * @bits: size of area to check
> + * @nr: nr of empty pages
>   *
> - * Calculates the number of populated pages in the region
> - * [page_start, page_end).  This keeps track of how many empty populated
> - * pages are available and decide if async work should be scheduled.
> - *
> - * RETURNS:
> - * The nr of populated pages.
> + * This is used to keep track of the empty pages now based on the
> + premise
> + * a pcpu_block_md covers a page.  The hint update functions recognize
> + if
> + * a block is made full or broken to calculate deltas for keeping track
> + of
> + * free pages.
>   */
> -static inline int pcpu_cnt_pop_pages(struct pcpu_chunk *chunk, int bit_off,
> -  int bits)
> +static inline void pcpu_update_empty_pages(struct pcpu_chunk *chunk,
> +int nr)
>  {
> - int page_start = PFN_UP(bit_off * PCPU_MIN_ALLOC_SIZE);
> - int page_end = PFN_DOWN((bit_off + bits) * PCPU_MIN_ALLOC_SIZE);
> -
> - if (page_start >= page_end)
> - return 0;
> -
> - /*
> -  * bitmap_weight counts the number of bits set in a bitmap up to
> -  * the specified number of bits.  This is counting the populated
> -  * pages up to page_end and then subtracting the populated pages
> -  * up to page_start to count the populated pages in
> -  * [page_start, page_end).
> -  */
> - return bitmap_weight(chunk->populated, page_end) 

[PATCH -next] lockdep: skip debugobjects for lock_classes[] init

2019-03-02 Thread Qian Cai
The linux-next commit a0b0fd53e1e6 ("locking/lockdep: Free lock classes
that are no longer in use") let init_data_structures_once() call
init_rcu_head(). As the result, smp_setup_processor_id() calls
debug_object_init() before debug_objects_early_init() triggering errors
below on arm64 and ppc64le. Since debug_objects_early_init() depends on
smp_setup_processor_id(), so it is not straightforward to move the
former earlier in start_kernel(). Hence, just skip all debugobjects
creations in init_data_structures_once() as a good trade-off by losing
track of some RCU list heads debugging.

BUG: spinlock bad magic on CPU#0, swapper/0
 lock: obj_hash+0xc3048/0x10, .magic: , .owner: /-1,
.owner_cpu: 0
CPU: 0 PID: 0 Comm: swapper Not tainted 5.0.0-rc8-next-20190301+ #1
Call trace:
 dump_backtrace+0x0/0x450
 show_stack+0x20/0x2c
 dump_stack+0xe0/0x16c
 spin_bug+0x200/0x224
 do_raw_spin_lock+0x1bc/0x23c
 _raw_spin_lock_irqsave+0xac/0xd0
 __debug_object_init+0xf0/0x19dc
 debug_object_init+0x54/0x6c
 init_rcu_head+0x24/0x30
 init_data_structures_once+0xb0/0x41c
 register_lock_class+0x70c/0x1454
 __lock_acquire+0xc4/0x235c
 lock_acquire+0x508/0x668
 _raw_spin_lock+0x88/0xac
 vprintk_emit+0x33c/0x53c
 vprintk_default+0x54/0x7c
 vprintk_func+0x320/0x40c
 printk+0x64/0x8c
 smp_setup_processor_id+0x6c/0x84
 start_kernel+0x38/0x8f8
ODEBUG: Out of memory. ODEBUG disabled

Signed-off-by: Qian Cai 
---
 kernel/locking/lockdep.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 21cb81fe6359..1309a6fe88ee 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -988,7 +988,6 @@ static void init_data_structures_once(void)
 
initialization_happened = true;
 
-   init_rcu_head(_free.rcu_head);
INIT_LIST_HEAD(_free.pf[0].zapped);
INIT_LIST_HEAD(_free.pf[1].zapped);
 
-- 
2.17.2 (Apple Git-113)



Re: x86 VM Boot hang with latest linux-next

2019-03-02 Thread Mike Snitzer
On Sat, Mar 02 2019 at  6:34pm -0500,
Alexander Duyck  wrote:

> So I have been seeing an issue with an intermittent boot hang on my
> x86 KVM VM with the latest linux-next and have bisected it down to the
> following commit:
> 1efa3bb79d3de8ca1b7f6770313a1fc0bebe25c7 is the first bad commit
> commit 1efa3bb79d3de8ca1b7f6770313a1fc0bebe25c7
> Author: Mike Snitzer 
> Date:   Fri Feb 22 11:23:01 2019 -0500
> 
> dm: must allocate dm_noclone for stacked noclone devices
> 
> Otherwise various lvm2 testsuite tests fail because the lower layers of
> the stacked noclone device aren't updated to allocate a new 'struct
> dm_clone' that reflects the upper layer bio that was issued to it.
> 
> Fixes: 97a89458020b38 ("dm: improve noclone bio support")
> Reported-by: Mikulas Patocka 
> Signed-off-by: Mike Snitzer 
> 
> What I am seeing is in about 3 out of 4 boots the startup just hangs
> at the filesystem check stage with the following message:
> [  OK  ] Reached target Local File Systems (Pre).
>  Starting File System Check on 
> /dev/…127-ad57-426f-bb45-363950544c0c...
> [**] (1 of 2) A start job is running for…n on device 252:2 (19s / no 
> limit)
> 
> I did some googling and it looks like a similar issue has been
> reported for s390. Based on the request for data there I have the
> following info:
> [root@localhost ~]# dmsetup ls --tree
> fedora-swap (253:1)
>  └─ (252:2)
> fedora-root (253:0)
>  └─ (252:2)
> 
> [root@localhost ~]# dmsetup table
> fedora-swap: 0 4194304 linear 252:2 2048
> fedora-root: 0 31457280 linear 252:2 4196352

Thanks, which version of Fedora are you running?

Your case is more straightforward in that you're clearly using bio-based
DM linear (which was updated to leverage "noclone" support); whereas the
s390 case is using request-based DM which isn't impacted by the commit
in question at all.

I'll attempt to reproduce first thing Monday.

Mike


Re: [PATCH v2] RDMA/umem: minor bug fix and cleanup in error handling paths

2019-03-02 Thread Ira Weiny
FWIW I don't have ODP hardware either.  So I can't test this either.

On Sat, Mar 02, 2019 at 12:24:35PM -0800, john.hubb...@gmail.com wrote:
> From: John Hubbard 
> 
> 1. Bug fix: the error handling release pages starting
> at the first page that experienced an error.
> 
> 2. Refinement: release_pages() is better than put_page()
> in a loop.
> 
> 3. Dead code removal: the check for (user_virt & ~page_mask)
> is checking for a condition that can never happen,
> because earlier:
> 
> user_virt = user_virt & page_mask;
> 
> ...so, remove that entire phrase.
> 
> 4. Minor: As long as I'm here, shorten up a couple of long lines
> in the same function, without harming the ability to
> grep for the printed error message.
> 
> Cc: Ira Weiny 
> Cc: Jason Gunthorpe 
> Cc: Andrew Morton 
> Cc: Doug Ledford 
> Cc: linux-r...@vger.kernel.org
> Cc: linux...@kvack.org
> Signed-off-by: John Hubbard 
> ---
> 
> v2: Fixes a kbuild test robot reported build failure, by directly
> including pagemap.h
> 
>  drivers/infiniband/core/umem_odp.c | 25 ++---
>  1 file changed, 10 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/infiniband/core/umem_odp.c 
> b/drivers/infiniband/core/umem_odp.c
> index acb882f279cb..83872c1f3f2c 100644
> --- a/drivers/infiniband/core/umem_odp.c
> +++ b/drivers/infiniband/core/umem_odp.c
> @@ -40,6 +40,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  #include 
> @@ -648,25 +649,17 @@ int ib_umem_odp_map_dma_pages(struct ib_umem_odp 
> *umem_odp, u64 user_virt,
>  
>   if (npages < 0) {
>   if (npages != -EAGAIN)
> - pr_warn("fail to get %zu user pages with error 
> %d\n", gup_num_pages, npages);
> + pr_warn("fail to get %zu user pages with error 
> %d\n",
> + gup_num_pages, npages);
>   else
> - pr_debug("fail to get %zu user pages with error 
> %d\n", gup_num_pages, npages);
> + pr_debug("fail to get %zu user pages with error 
> %d\n",
> +  gup_num_pages, npages);
>   break;
>   }
>  
>   bcnt -= min_t(size_t, npages << PAGE_SHIFT, bcnt);
>   mutex_lock(_odp->umem_mutex);
>   for (j = 0; j < npages; j++, user_virt += PAGE_SIZE) {
> - if (user_virt & ~page_mask) {
> - p += PAGE_SIZE;
> - if (page_to_phys(local_page_list[j]) != p) {
> - ret = -EFAULT;
> - break;
> - }
> - put_page(local_page_list[j]);
> - continue;
> - }
> -

I think this is trying to account for compound pages. (ie page_mask could
represent more than PAGE_SIZE which is what user_virt is being incrimented by.)
But putting the page in that case seems to be the wrong thing to do?

Yes this was added by Artemy[1] now cc'ed.

>   ret = ib_umem_odp_map_dma_single_page(
>   umem_odp, k, local_page_list[j],
>   access_mask, current_seq);
> @@ -684,9 +677,11 @@ int ib_umem_odp_map_dma_pages(struct ib_umem_odp 
> *umem_odp, u64 user_virt,
>   mutex_unlock(_odp->umem_mutex);
>  
>   if (ret < 0) {
> - /* Release left over pages when handling errors. */
> - for (++j; j < npages; ++j)
> - put_page(local_page_list[j]);
> + /*
> +  * Release pages, starting at the the first page
> +  * that experienced an error.
> +  */
> + release_pages(_page_list[j], npages - j);

My concern here is that release_pages handle compound pages, perhaps
differently from the above code so calling it may may not work?  But I've not
really spent a lot of time on it...

:-/

Ira

[1]

commit 403cd12e2cf759ead5cbdcb62bf9872b9618d400
Author: Artemy Kovalyov 
Date:   Wed Apr 5 09:23:55 2017 +0300

IB/umem: Add contiguous ODP support

Currenlty ODP supports only regular MMU pages.
Add ODP support for regions consisting of physically contiguous chunks
of arbitrary order (huge pages for instance) to improve performance.

Signed-off-by: Artemy Kovalyov 
Signed-off-by: Leon Romanovsky 
Signed-off-by: Doug Ledford 




[git pull] vfs.git fixes

2019-03-02 Thread Al Viro
Assorted fixes that sat in -next for a while, all over the
place.

The following changes since commit 1c7fc5cbc33980acd13d668f1c8f0313d6ae9fd8:

  Linux 5.0-rc2 (2019-01-14 10:41:12 +1200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git fixes

for you to fetch changes up to d3d6a18d7d351cbcc9b33dbedf710e65f8ce1595:

  aio: Fix locking in aio_poll() (2019-02-21 22:16:47 -0500)


Al Viro (2):
  fix cgroup_do_mount() handling of failure exits
  cgroup: saner refcounting for cgroup_root

Bart Van Assche (1):
  aio: Fix locking in aio_poll()

Chandan Rajendra (1):
  copy_mount_string: Limit string length to PATH_MAX

YueHaibing (1):
  exec: Fix mem leak in kernel_read_file

 fs/aio.c| 12 ++---
 fs/exec.c   |  2 +-
 fs/kernfs/mount.c   |  8 --
 fs/namespace.c  |  2 +-
 kernel/cgroup/cgroup-internal.h |  2 +-
 kernel/cgroup/cgroup-v1.c   | 58 +
 kernel/cgroup/cgroup.c  | 25 +-
 7 files changed, 44 insertions(+), 65 deletions(-)


Re: [PATCH 01/20] asm-generic/mmiowb: Add generic implementation of mmiowb() tracking

2019-03-02 Thread Nicholas Piggin
Linus Torvalds's on March 3, 2019 12:18 pm:
> On Sat, Mar 2, 2019 at 5:43 PM Nicholas Piggin  wrote:
>>
>> Is there a reason to call this "mmiowb"? We already have wmb that
>> orders cacheable stores vs mmio stores don't we?
> 
> Sadly no it doesn't. Not on ia64, and people tried to make that the
> new rule because of the platform breakage on what some people thought
> would be a major platform.

Let me try this again, because I was babbling a train of thought 
continuing from my past mails on the subject.

  Kill mmiowb with fire.

It was added for a niche platform that hasn't been produced for 10
years for a CPU ISA that is no longer being developed. Let's make mb/wmb
great again (aka actually possible for normal people to understand).

If something comes along again that reorders mmios from different CPUs 
in the IO controller like the Altix did, they implement wmb the slow and 
correct way. They can add a new faster primitive for the few devices 
they care about in the couple of perf critical places that matter.

It doesn't have to be done all at once with this series, obviously this 
is a big improvement on its own. But why perpetuate the nomenclature
and concept for new code added now? 

Thanks,
Nick



Re: [PATCH] x86/KASLR: always return a value from process_mem_region

2019-03-02 Thread Nathan Chancellor
On Sat, Mar 02, 2019 at 06:49:29PM +, Louis Taylor wrote:
> When compiling with -Wreturn-type, clang warns:
> 
> arch/x86/boot/compressed/kaslr.c:704:1: warning: control may reach end of
>   non-void function [-Wreturn-type]
> 
> This function's return statement should probably have been placed
> outside the #endif, so move it there
> 
> Link: https://github.com/ClangBuiltLinux/linux/issues/360
> Signed-off-by: Louis Taylor 

Reviewed-by: Nathan Chancellor 

Thanks for the patch!

> ---
>  arch/x86/boot/compressed/kaslr.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/x86/boot/compressed/kaslr.c 
> b/arch/x86/boot/compressed/kaslr.c
> index fa0332dda9f2..2e53c056ba20 100644
> --- a/arch/x86/boot/compressed/kaslr.c
> +++ b/arch/x86/boot/compressed/kaslr.c
> @@ -697,8 +697,8 @@ static bool process_mem_region(struct mem_vector *region,
>   return 1;
>   }
>   }
> - return 0;
>  #endif
> + return 0;
>  }
>  
>  #ifdef CONFIG_EFI
> -- 
> 2.20.1


Re: [PATCH] rsi: Fix NULL pointer dereference in kmalloc

2019-03-02 Thread Joe Perches
On Sat, 2019-03-02 at 14:31 -0600, Aditya Pakki wrote:
> kmalloc can fail in rsi_register_rates_channels but memcpy still attempts
> to write to channels. The patch checks and avoids such a situation.
[]
> diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c 
> b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
[]
> @@ -197,6 +197,11 @@ static void rsi_register_rates_channels(struct rsi_hw 
> *adapter, int band)

It'd be better to make this return -ENOMEM on failure
and test in the caller and push the failure up-stack.

>  
>   if (band == NL80211_BAND_2GHZ) {
>   channels = kmalloc(sizeof(rsi_2ghz_channels), GFP_KERNEL);
> + if (!channels) {
> + rsi_dbg(ERR_ZONE, "Failed to allocate memory\n");

Allocation error messages aren't really useful
as there's a generic OOM message.

> + return;
> + }
> +
>   memcpy(channels,
>  rsi_2ghz_channels,
>  sizeof(rsi_2ghz_channels));
> @@ -206,6 +211,11 @@ static void rsi_register_rates_channels(struct rsi_hw 
> *adapter, int band)
>   sbands->n_bitrates = ARRAY_SIZE(rsi_rates);
>   } else {
>   channels = kmalloc(sizeof(rsi_5ghz_channels), GFP_KERNEL);
> + if (!channels) {
> + rsi_dbg(ERR_ZONE, "Failed to allocate memory\n");
> + return;
> + }
> +
>   memcpy(channels,
>  rsi_5ghz_channels,
>  sizeof(rsi_5ghz_channels));



Re: [PATCH 01/20] asm-generic/mmiowb: Add generic implementation of mmiowb() tracking

2019-03-02 Thread Linus Torvalds
On Sat, Mar 2, 2019 at 5:43 PM Nicholas Piggin  wrote:
>
> Is there a reason to call this "mmiowb"? We already have wmb that
> orders cacheable stores vs mmio stores don't we?

Sadly no it doesn't. Not on ia64, and people tried to make that the
new rule because of the platform breakage on what some people thought
would be a major platform.

Plain wmb() was only guaranteed to order regular memory against each
other (mostly useful for dma) on some of these platforms, because they
had such broken IO synchronization.

So mmiowb() is not a new name. It's been around for a while, and the
people who wanted it have happily become irrelevant. Will is making it
go away, but the name remains for historical reasons, even if Will's
new acronym explanation for the name is much better ;)

Linus


Re: [PATCH v4 1/2] Provide in-kernel headers for making it easy to extend the kernel

2019-03-02 Thread kbuild test robot
Hi Joel,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v5.0-rc8]
[cannot apply to next-20190301]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Joel-Fernandes-Google/Provide-in-kernel-headers-for-making-it-easy-to-extend-the-kernel/20190303-014850
config: microblaze-allmodconfig (attached as .config)
compiler: microblaze-linux-gcc (GCC) 8.2.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=8.2.0 make.cross ARCH=microblaze 

All errors (new ones prefixed by >>):

>> find: 'arch/microblaze/kernel/module.lds': No such file or directory
>> find: 'arch/microblaze/kernel/module.lds': No such file or directory

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


[PATCH v2 0/1] PINCTRL: Mediatek pinctrl patch for mt8183

2019-03-02 Thread Zhiyong Tao
This series includes one patche:
1.Add drive for I2C related pins on MT8183.

Changes in patch v2:
1)add the details strength specification description of the I2C pin.
2)change "mt8183_pin_drv_en_dis_range" to "mt8183_pin_e1e0en_range".
3)change "mt8183_pin_drv_e0_range" to "mt8183_pin_e0_range".
4)change "mt8183_pin_drv_e1_range" to "mt8183_pin_drv_e1_range".

Zhiyong Tao (1):
  pinctrl: add drive for I2C related pins on MT8183

 drivers/pinctrl/mediatek/pinctrl-mt8183.c| 50 
 drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 45 +
 drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h | 13 ++
 drivers/pinctrl/mediatek/pinctrl-paris.c | 20 ++
 4 files changed, 128 insertions(+)

--
2.12.5


[PATCH] pinctrl: add drive for I2C related pins on MT8183

2019-03-02 Thread Zhiyong Tao
This patch provides the advanced drive for I2C used pins on MT8183.
The detail strength specification description of the I2C pin is as follows.
When E1=0/E0=0, the strength is 0.125mA.
When E1=0/E0=1, the strength is 0.25mA.
When E1=1/E0=0, the strength is 0.5mA.
When E1=1/E0=1, the strength is 1mA.

Signed-off-by: Zhiyong Tao 
---
 drivers/pinctrl/mediatek/pinctrl-mt8183.c| 50 
 drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 45 +
 drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h | 13 ++
 drivers/pinctrl/mediatek/pinctrl-paris.c | 20 ++
 4 files changed, 128 insertions(+)

diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8183.c 
b/drivers/pinctrl/mediatek/pinctrl-mt8183.c
index 6262fd3678ea..f034574fc593 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8183.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8183.c
@@ -472,6 +472,51 @@ static const struct mtk_pin_field_calc 
mt8183_pin_r1_range[] = {
PIN_FIELD_BASE(133, 133, 8, 0x0D0, 0x10, 13, 1),
 };
 
+static const struct mtk_pin_field_calc mt8183_pin_e1e0en_range[] = {
+   PIN_FIELD_BASE(48, 48, 3, 0x0F0, 0x10, 20, 1),
+   PIN_FIELD_BASE(49, 49, 3, 0x0F0, 0x10, 15, 1),
+   PIN_FIELD_BASE(50, 50, 4, 0x0F0, 0x10, 12, 1),
+   PIN_FIELD_BASE(51, 51, 4, 0x0F0, 0x10, 7, 1),
+   PIN_FIELD_BASE(81, 81, 5, 0x0F0, 0x10, 12, 1),
+   PIN_FIELD_BASE(82, 82, 5, 0x0F0, 0x10, 9, 1),
+   PIN_FIELD_BASE(83, 83, 5, 0x0F0, 0x10, 19, 1),
+   PIN_FIELD_BASE(84, 84, 5, 0x0F0, 0x10, 22, 1),
+   PIN_FIELD_BASE(103, 103, 6, 0x0F0, 0x10, 24, 1),
+   PIN_FIELD_BASE(104, 104, 6, 0x0F0, 0x10, 14, 1),
+   PIN_FIELD_BASE(105, 105, 6, 0x0F0, 0x10, 27, 1),
+   PIN_FIELD_BASE(106, 106, 6, 0x0F0, 0x10, 17, 1),
+};
+
+static const struct mtk_pin_field_calc mt8183_pin_e0_range[] = {
+   PIN_FIELD_BASE(48, 48, 3, 0x0F0, 0x10, 21, 1),
+   PIN_FIELD_BASE(49, 49, 3, 0x0F0, 0x10, 16, 1),
+   PIN_FIELD_BASE(50, 50, 4, 0x0F0, 0x10, 13, 1),
+   PIN_FIELD_BASE(51, 51, 4, 0x0F0, 0x10, 8, 1),
+   PIN_FIELD_BASE(81, 81, 5, 0x0F0, 0x10, 13, 1),
+   PIN_FIELD_BASE(82, 82, 5, 0x0F0, 0x10, 10, 1),
+   PIN_FIELD_BASE(83, 83, 5, 0x0F0, 0x10, 20, 1),
+   PIN_FIELD_BASE(84, 84, 5, 0x0F0, 0x10, 23, 1),
+   PIN_FIELD_BASE(103, 103, 6, 0x0F0, 0x10, 25, 1),
+   PIN_FIELD_BASE(104, 104, 6, 0x0F0, 0x10, 15, 1),
+   PIN_FIELD_BASE(105, 105, 6, 0x0F0, 0x10, 28, 1),
+   PIN_FIELD_BASE(106, 106, 6, 0x0F0, 0x10, 18, 1),
+};
+
+static const struct mtk_pin_field_calc mt8183_pin_e1_range[] = {
+   PIN_FIELD_BASE(48, 48, 3, 0x0F0, 0x10, 22, 1),
+   PIN_FIELD_BASE(49, 49, 3, 0x0F0, 0x10, 17, 1),
+   PIN_FIELD_BASE(50, 50, 4, 0x0F0, 0x10, 14, 1),
+   PIN_FIELD_BASE(51, 51, 4, 0x0F0, 0x10, 9, 1),
+   PIN_FIELD_BASE(81, 81, 5, 0x0F0, 0x10, 14, 1),
+   PIN_FIELD_BASE(82, 82, 5, 0x0F0, 0x10, 11, 1),
+   PIN_FIELD_BASE(83, 83, 5, 0x0F0, 0x10, 21, 1),
+   PIN_FIELD_BASE(84, 84, 5, 0x0F0, 0x10, 24, 1),
+   PIN_FIELD_BASE(103, 103, 6, 0x0F0, 0x10, 26, 1),
+   PIN_FIELD_BASE(104, 104, 6, 0x0F0, 0x10, 16, 1),
+   PIN_FIELD_BASE(105, 105, 6, 0x0F0, 0x10, 29, 1),
+   PIN_FIELD_BASE(106, 106, 6, 0x0F0, 0x10, 19, 1),
+};
+
 static const struct mtk_pin_reg_calc mt8183_reg_cals[PINCTRL_PIN_REG_MAX] = {
[PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt8183_pin_mode_range),
[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt8183_pin_dir_range),
@@ -485,6 +530,9 @@ static const struct mtk_pin_reg_calc 
mt8183_reg_cals[PINCTRL_PIN_REG_MAX] = {
[PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt8183_pin_pupd_range),
[PINCTRL_PIN_REG_R0] = MTK_RANGE(mt8183_pin_r0_range),
[PINCTRL_PIN_REG_R1] = MTK_RANGE(mt8183_pin_r1_range),
+   [PINCTRL_PIN_REG_DRV_EN_DIS] = MTK_RANGE(mt8183_pin_e1e0en_range),
+   [PINCTRL_PIN_REG_DRV_E0] = MTK_RANGE(mt8183_pin_e0_range),
+   [PINCTRL_PIN_REG_DRV_E1] = MTK_RANGE(mt8183_pin_e1_range),
 };
 
 static const char * const mt8183_pinctrl_register_base_names[] = {
@@ -517,6 +565,8 @@ static const struct mtk_pin_soc mt8183_data = {
.drive_get = mtk_pinconf_drive_get_rev1,
.adv_pull_get = mtk_pinconf_adv_pull_get,
.adv_pull_set = mtk_pinconf_adv_pull_set,
+   .adv_drive_get = mtk_pinconf_adv_drive_get,
+   .adv_drive_set = mtk_pinconf_adv_drive_set,
 };
 
 static const struct of_device_id mt8183_pinctrl_of_match[] = {
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c 
b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
index 4a9e0d4c2bbc..da024279ec59 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
@@ -668,3 +668,48 @@ int mtk_pinconf_adv_pull_get(struct mtk_pinctrl *hw,
 
return 0;
 }
+
+int mtk_pinconf_adv_drive_set(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc, bool enable,
+ u32 arg)
+{
+   int err;
+
+

Re: [PATCH 03/20] mmiowb: Hook up mmiowb helpers to spinlocks and generic I/O accessors

2019-03-02 Thread Nicholas Piggin
Will Deacon's on March 2, 2019 12:03 am:
> @@ -177,6 +178,7 @@ do {  
> \
>  static inline void do_raw_spin_lock(raw_spinlock_t *lock) __acquires(lock)
>  {
>   __acquire(lock);
> + mmiowb_spin_lock();
>   arch_spin_lock(>raw_lock);
>  }
>  
> @@ -188,16 +190,23 @@ static inline void
>  do_raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long *flags) 
> __acquires(lock)
>  {
>   __acquire(lock);
> + mmiowb_spin_lock();
>   arch_spin_lock_flags(>raw_lock, *flags);
>  }

You'd be better to put these inside the spin lock, to match your 
trylock.

Also it means the mmiowb state can be used inside a lock/unlock pair
without a compiler barrer forcing it to be reloaded, should be better
code generation for very small critical sections on archs which inline
lock and unlock.

>  
>  static inline int do_raw_spin_trylock(raw_spinlock_t *lock)
>  {
> - return arch_spin_trylock(&(lock)->raw_lock);
> + int ret = arch_spin_trylock(&(lock)->raw_lock);
> +
> + if (ret)
> + mmiowb_spin_lock();
> +
> + return ret;
>  }
>  
>  static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock)
>  {
> + mmiowb_spin_unlock();
>   arch_spin_unlock(>raw_lock);
>   __release(lock);
>  }

Thanks,
Nick



Re: [PATCH 01/20] asm-generic/mmiowb: Add generic implementation of mmiowb() tracking

2019-03-02 Thread Nicholas Piggin
Will Deacon's on March 2, 2019 12:03 am:
> In preparation for removing all explicit mmiowb() calls from driver
> code, implement a tracking system in asm-generic based loosely on the
> PowerPC implementation. This allows architectures with a non-empty
> mmiowb() definition to have the barrier automatically inserted in
> spin_unlock() following a critical section containing an I/O write.

Is there a reason to call this "mmiowb"? We already have wmb that
orders cacheable stores vs mmio stores don't we?

Yes ia64 "sn2" is broken in that case, but that can be fixed (if
anyone really cares about the platform any more). Maybe that's
orthogonal to what you're doing here, I just don't like seeing
"mmiowb" spread.

This series works for spin locks, but you would want a driver to
be able to use wmb() to order locks vs mmio when using a bit lock
or a mutex or whatever else. Calling your wmb-if-io-is-pending
version io_mb_before_unlock() would kind of match with existing
patterns.

> +static inline void mmiowb_set_pending(void)
> +{
> + struct mmiowb_state *ms = __mmiowb_state();
> + ms->mmiowb_pending = ms->nesting_count;
> +}
> +
> +static inline void mmiowb_spin_lock(void)
> +{
> + struct mmiowb_state *ms = __mmiowb_state();
> + ms->nesting_count++;
> +}
> +
> +static inline void mmiowb_spin_unlock(void)
> +{
> + struct mmiowb_state *ms = __mmiowb_state();
> +
> + if (unlikely(ms->mmiowb_pending)) {
> + ms->mmiowb_pending = 0;
> + mmiowb();
> + }
> +
> + ms->nesting_count--;
> +}

Humour me for a minute and tell me what this algorithm is doing, or
what was broken about the powerpc one, which is basically:

static inline void mmiowb_set_pending(void)
{
struct mmiowb_state *ms = __mmiowb_state();
ms->mmiowb_pending = 1;
}

static inline void mmiowb_spin_lock(void)
{
}

static inline void mmiowb_spin_unlock(void)
{
struct mmiowb_state *ms = __mmiowb_state();

if (unlikely(ms->mmiowb_pending)) {
ms->mmiowb_pending = 0;
mmiowb();
}
}

> diff --git a/include/asm-generic/mmiowb_types.h 
> b/include/asm-generic/mmiowb_types.h
> new file mode 100644
> index ..8eb0095655e7
> --- /dev/null
> +++ b/include/asm-generic/mmiowb_types.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __ASM_GENERIC_MMIOWB_TYPES_H
> +#define __ASM_GENERIC_MMIOWB_TYPES_H
> +
> +#include 
> +
> +struct mmiowb_state {
> + u16 nesting_count;
> + u16 mmiowb_pending;
> +};

Really need more than 255 nested spin locks? I had the idea that 16
bit operations were a bit more costly than 8 bit on some CPUs... may
not be true, but at least the smaller size packs a bit better on
powerpc.

Thanks,
Nick



Re: [PATCH 3/6] x86: clean up _TIF_SYSCALL_EMU handling using ptrace_syscall_enter hook

2019-03-02 Thread Andy Lutomirski
On Thu, Feb 28, 2019 at 10:32 AM Sudeep Holla  wrote:
>
> Now that we have a new hook ptrace_syscall_enter that can be called from
> syscall entry code and it handles PTRACE_SYSEMU in generic code, we
> can do some cleanup using the same in syscall_trace_enter.
>
> Further the extra logic to find single stepping PTRACE_SYSEMU_SINGLESTEP
> in syscall_slow_exit_work seems unnecessary. Let's remove the same.

I wasn't cc'd on the whole series, so I can't easily review this.  Do
you have a test case to make sure that emulation still works?  Are
there adequate tests in tools/testing/selftests/x86?  Do they still
pass after this patch?

--Andy


Re: a.out coredumping: fix or delete?

2019-03-02 Thread Andy Lutomirski
On Fri, Mar 1, 2019 at 3:57 PM Jann Horn  wrote:
>
> In theory, Linux can dump cores for a.out binaries. In practice, that
> code is pretty bitrotten and buggy. Does anyone want that code so much
> that they'd like to fix it, or can we just delete it?

I would propose just deleting it.


Re: [GIT PULL] ARM: SoC fixes for v5.0

2019-03-02 Thread pr-tracker-bot
The pull request you sent on Sat, 2 Mar 2019 23:28:17 +0100:

> git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git tags/armsoc-fixes

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/c027c7cf1577bc2333449447c6e48c93126a56b0

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.wiki.kernel.org/userdoc/prtracker


Re: [RFC PATCH 2/2] ceph: quota: fix quota subdir mounts

2019-03-02 Thread Jeff Layton
On Fri, 2019-03-01 at 17:57 +, Luis Henriques wrote:
> The CephFS kernel client doesn't enforce quotas that are set in a
> directory that isn't visible in the mount point.  For example, given the
> path '/dir1/dir2', if quotas are set in 'dir1' and the mount is done in with
> 
>   mount -t ceph ::/dir1/ /mnt
> 
> then the client can't access the 'dir1' inode from the quota realm dir2
> belongs to.
> 
> This patch fixes this by simply doing an MDS LOOKUPINO Op and grabbing a
> reference to it (so that it doesn't disappear again).  This also requires an
> extra field in ceph_snap_realm so that we know we have to release that
> reference when destroying the realm.
> 
> Links: https://tracker.ceph.com/issues/3848

This bug looks unrelated to the patch description. Are you sure it's
correct?

> Reported-by: Hendrik Peyerl 
> Signed-off-by: Luis Henriques 
> ---
>  fs/ceph/caps.c  |  2 +-
>  fs/ceph/quota.c | 30 +++---
>  fs/ceph/snap.c  |  3 +++
>  fs/ceph/super.h |  2 ++
>  4 files changed, 33 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
> index bba28a5034ba..e79994ff53d6 100644
> --- a/fs/ceph/caps.c
> +++ b/fs/ceph/caps.c
> @@ -1035,7 +1035,7 @@ static void drop_inode_snap_realm(struct 
> ceph_inode_info *ci)
>   list_del_init(>i_snap_realm_item);
>   ci->i_snap_realm_counter++;
>   ci->i_snap_realm = NULL;
> - if (realm->ino == ci->i_vino.ino)
> + if ((realm->ino == ci->i_vino.ino) && !realm->own_inode)
>   realm->inode = NULL;
>   spin_unlock(>inodes_with_caps_lock);
>   ceph_put_snap_realm(ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc,
> diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c
> index 9455d3aef0c3..f6b972d222e4 100644
> --- a/fs/ceph/quota.c
> +++ b/fs/ceph/quota.c
> @@ -22,7 +22,16 @@ void ceph_adjust_quota_realms_count(struct inode *inode, 
> bool inc)
>  static inline bool ceph_has_realms_with_quotas(struct inode *inode)
>  {
>   struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
> - return atomic64_read(>quotarealms_count) > 0;
> + struct super_block *sb = mdsc->fsc->sb;
> +
> + if (atomic64_read(>quotarealms_count) > 0)
> + return true;
> + /* if root is the real CephFS root, we don't have quota realms */
> + if (sb->s_root->d_inode &&
> + (sb->s_root->d_inode->i_ino == CEPH_INO_ROOT))
> + return false;
> + /* otherwise, we can't know for sure */
> + return true;
>  }
>  
>  void ceph_handle_quota(struct ceph_mds_client *mdsc,
> @@ -166,6 +175,7 @@ static bool check_quota_exceeded(struct inode *inode, 
> enum quota_check_op op,
>   return false;
>  
>   down_read(>snap_rwsem);
> +restart:
>   realm = ceph_inode(inode)->i_snap_realm;
>   if (realm)
>   ceph_get_snap_realm(mdsc, realm);
> @@ -176,8 +186,22 @@ static bool check_quota_exceeded(struct inode *inode, 
> enum quota_check_op op,
>   spin_lock(>inodes_with_caps_lock);
>   in = realm->inode ? igrab(realm->inode) : NULL;
>   spin_unlock(>inodes_with_caps_lock);
> - if (!in)
> - break;
> + if (!in) {
> + up_read(>snap_rwsem);
> + in = ceph_lookup_inode(inode->i_sb, realm->ino);
> + down_read(>snap_rwsem);
> + if (IS_ERR(in)) {
> + pr_warn("Can't lookup inode %llx (err: %ld)\n",
> + realm->ino, PTR_ERR(in));
> + break;
> + }
> + spin_lock(>inodes_with_caps_lock);
> + realm->inode = in;
> + realm->own_inode = true;
> + spin_unlock(>inodes_with_caps_lock);
> + ceph_put_snap_realm(mdsc, realm);
> + goto restart;
> + }
>  
>   ci = ceph_inode(in);
>   spin_lock(>i_ceph_lock);
> diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
> index f74193da0e09..c84ed8e8526a 100644
> --- a/fs/ceph/snap.c
> +++ b/fs/ceph/snap.c
> @@ -117,6 +117,7 @@ static struct ceph_snap_realm *ceph_create_snap_realm(
>  
>   atomic_set(>nref, 1);/* for caller */
>   realm->ino = ino;
> + realm->own_inode = false;
>   INIT_LIST_HEAD(>children);
>   INIT_LIST_HEAD(>child_item);
>   INIT_LIST_HEAD(>empty_item);
> @@ -184,6 +185,8 @@ static void __destroy_snap_realm(struct ceph_mds_client 
> *mdsc,
>   kfree(realm->prior_parent_snaps);
>   kfree(realm->snaps);
>   ceph_put_snap_context(realm->cached_context);
> + if (realm->own_inode && realm->inode)
> + iput(realm->inode);
>   kfree(realm);
>  }
>  
> diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> index ce51e98b08ec..3f0d74d2150f 100644
> --- a/fs/ceph/super.h
> +++ b/fs/ceph/super.h
> @@ -764,6 +764,8 @@ struct ceph_snap_realm {
>   

[PATCH v10 22/27] MIPS: qi_lb60: Reduce system timer and clocksource to 750 kHz

2019-03-02 Thread Paul Cercueil
The default clock (12 MHz) is too fast for the system timer, which fails
to report time accurately.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v5: New patch

 v6: Remove ingenic,clocksource-channel property

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 arch/mips/boot/dts/ingenic/qi_lb60.dts | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/mips/boot/dts/ingenic/qi_lb60.dts 
b/arch/mips/boot/dts/ingenic/qi_lb60.dts
index 85529a142409..de9d45e2c24a 100644
--- a/arch/mips/boot/dts/ingenic/qi_lb60.dts
+++ b/arch/mips/boot/dts/ingenic/qi_lb60.dts
@@ -45,3 +45,9 @@
bias-disable;
};
 };
+
+ {
+   /* 750 kHz for the system timer and clocksource */
+   assigned-clocks = < TCU_CLK_TIMER0>, < TCU_CLK_TIMER1>;
+   assigned-clock-rates = <75>, <75>;
+};
-- 
2.11.0



[PATCH v10 21/27] MIPS: qi_lb60: Move PWM devices to devicetree

2019-03-02 Thread Paul Cercueil
Probe the few drivers using PWMs from devicetree, now that we have a
devicetree node for the PWM driver.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v5: New patch

 v6: No change

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 arch/mips/boot/dts/ingenic/qi_lb60.dts | 14 ++
 arch/mips/jz4740/board-qi_lb60.c   | 19 ---
 2 files changed, 14 insertions(+), 19 deletions(-)

diff --git a/arch/mips/boot/dts/ingenic/qi_lb60.dts 
b/arch/mips/boot/dts/ingenic/qi_lb60.dts
index 76aaf8982554..85529a142409 100644
--- a/arch/mips/boot/dts/ingenic/qi_lb60.dts
+++ b/arch/mips/boot/dts/ingenic/qi_lb60.dts
@@ -9,6 +9,14 @@
chosen {
stdout-path = 
};
+
+   beeper {
+   compatible = "pwm-beeper";
+   pwms = < 4 0 0>;
+
+   pinctrl-names = "default";
+   pinctrl-0 = <_pwm4>;
+   };
 };
 
  {
@@ -30,4 +38,10 @@
groups = "uart0-data";
bias-disable;
};
+
+   pins_pwm4: pwm4 {
+   function = "pwm4";
+   groups = "pwm4";
+   bias-disable;
+   };
 };
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index 6718efb400f4..02b9c131a051 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -27,7 +27,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include 
 
@@ -395,17 +394,6 @@ static struct gpiod_lookup_table qi_lb60_mmc_gpio_table = {
},
 };
 
-/* beeper */
-static struct pwm_lookup qi_lb60_pwm_lookup[] = {
-   PWM_LOOKUP("jz4740-pwm", 4, "pwm-beeper", NULL, 0,
-  PWM_POLARITY_NORMAL),
-};
-
-static struct platform_device qi_lb60_pwm_beeper = {
-   .name = "pwm-beeper",
-   .id = -1,
-};
-
 /* charger */
 static char *qi_lb60_batteries[] = {
"battery",
@@ -454,10 +442,8 @@ static struct platform_device *jz_platform_devices[] 
__initdata = {
_i2s_device,
_codec_device,
_adc_device,
-   _pwm_device,
_dma_device,
_lb60_gpio_keys,
-   _lb60_pwm_beeper,
_lb60_charger_device,
_lb60_audio_device,
 };
@@ -486,10 +472,6 @@ static struct pinctrl_map pin_map[] __initdata = {
"1001.jz4740-pinctrl", "PD0", pin_cfg_bias_disable),
PIN_MAP_CONFIGS_PIN_DEFAULT("jz4740-mmc.0",
"1001.jz4740-pinctrl", "PD2", pin_cfg_bias_disable),
-
-   /* PWM pin configuration */
-   PIN_MAP_MUX_GROUP_DEFAULT("jz4740-pwm",
-   "1001.jz4740-pinctrl", "pwm4", "pwm4"),
 };
 
 
@@ -508,7 +490,6 @@ static int __init qi_lb60_init_platform_devices(void)
spi_register_board_info(qi_lb60_spi_board_info,
ARRAY_SIZE(qi_lb60_spi_board_info));
 
-   pwm_add_table(qi_lb60_pwm_lookup, ARRAY_SIZE(qi_lb60_pwm_lookup));
pinctrl_register_mappings(pin_map, ARRAY_SIZE(pin_map));
 
return platform_add_devices(jz_platform_devices,
-- 
2.11.0



[PATCH v10 27/27] MIPS: jz4740: Drop obsolete code

2019-03-02 Thread Paul Cercueil
The old clocksource/timer platform code is now obsoleted by the newly
introduced ingenic-timer and ingenic-ost drivers.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v5: New patch

 v6: No change

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 arch/mips/include/asm/mach-jz4740/platform.h |   1 -
 arch/mips/include/asm/mach-jz4740/timer.h| 135 
 arch/mips/jz4740/Makefile|   3 +-
 arch/mips/jz4740/platform.c  |   6 -
 arch/mips/jz4740/setup.c |   8 ++
 arch/mips/jz4740/time.c  | 176 ---
 arch/mips/jz4740/timer.c |  51 
 7 files changed, 9 insertions(+), 371 deletions(-)
 delete mode 100644 arch/mips/include/asm/mach-jz4740/timer.h
 delete mode 100644 arch/mips/jz4740/time.c
 delete mode 100644 arch/mips/jz4740/timer.c

diff --git a/arch/mips/include/asm/mach-jz4740/platform.h 
b/arch/mips/include/asm/mach-jz4740/platform.h
index c0c932ac72a7..cd464d956882 100644
--- a/arch/mips/include/asm/mach-jz4740/platform.h
+++ b/arch/mips/include/asm/mach-jz4740/platform.h
@@ -29,7 +29,6 @@ extern struct platform_device jz4740_i2s_device;
 extern struct platform_device jz4740_pcm_device;
 extern struct platform_device jz4740_codec_device;
 extern struct platform_device jz4740_adc_device;
-extern struct platform_device jz4740_pwm_device;
 extern struct platform_device jz4740_dma_device;
 
 #endif
diff --git a/arch/mips/include/asm/mach-jz4740/timer.h 
b/arch/mips/include/asm/mach-jz4740/timer.h
deleted file mode 100644
index 8750a1d04e22..
--- a/arch/mips/include/asm/mach-jz4740/timer.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen 
- *  JZ4740 platform timer support
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under  the terms of the GNU General Public License as published by 
the
- *  Free Software Foundation;  either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef __ASM_MACH_JZ4740_TIMER
-#define __ASM_MACH_JZ4740_TIMER
-
-#define JZ_REG_TIMER_STOP  0x0C
-#define JZ_REG_TIMER_STOP_SET  0x1C
-#define JZ_REG_TIMER_STOP_CLEAR0x2C
-#define JZ_REG_TIMER_ENABLE0x00
-#define JZ_REG_TIMER_ENABLE_SET0x04
-#define JZ_REG_TIMER_ENABLE_CLEAR  0x08
-#define JZ_REG_TIMER_FLAG  0x10
-#define JZ_REG_TIMER_FLAG_SET  0x14
-#define JZ_REG_TIMER_FLAG_CLEAR0x18
-#define JZ_REG_TIMER_MASK  0x20
-#define JZ_REG_TIMER_MASK_SET  0x24
-#define JZ_REG_TIMER_MASK_CLEAR0x28
-
-#define JZ_REG_TIMER_DFR(x) (((x) * 0x10) + 0x30)
-#define JZ_REG_TIMER_DHR(x) (((x) * 0x10) + 0x34)
-#define JZ_REG_TIMER_CNT(x) (((x) * 0x10) + 0x38)
-#define JZ_REG_TIMER_CTRL(x) (((x) * 0x10) + 0x3C)
-
-#define JZ_TIMER_IRQ_HALF(x) BIT((x) + 0x10)
-#define JZ_TIMER_IRQ_FULL(x) BIT(x)
-
-#define JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN BIT(9)
-#define JZ_TIMER_CTRL_PWM_ACTIVE_LOW   BIT(8)
-#define JZ_TIMER_CTRL_PWM_ENABLE   BIT(7)
-#define JZ_TIMER_CTRL_PRESCALE_MASK0x1c
-#define JZ_TIMER_CTRL_PRESCALE_OFFSET  0x3
-#define JZ_TIMER_CTRL_PRESCALE_1   (0 << 3)
-#define JZ_TIMER_CTRL_PRESCALE_4   (1 << 3)
-#define JZ_TIMER_CTRL_PRESCALE_16  (2 << 3)
-#define JZ_TIMER_CTRL_PRESCALE_64  (3 << 3)
-#define JZ_TIMER_CTRL_PRESCALE_256 (4 << 3)
-#define JZ_TIMER_CTRL_PRESCALE_1024(5 << 3)
-
-#define JZ_TIMER_CTRL_PRESCALER(x) ((x) << JZ_TIMER_CTRL_PRESCALE_OFFSET)
-
-#define JZ_TIMER_CTRL_SRC_EXT  BIT(2)
-#define JZ_TIMER_CTRL_SRC_RTC  BIT(1)
-#define JZ_TIMER_CTRL_SRC_PCLK BIT(0)
-
-extern void __iomem *jz4740_timer_base;
-void __init jz4740_timer_init(void);
-
-void jz4740_timer_enable_watchdog(void);
-void jz4740_timer_disable_watchdog(void);
-
-static inline void jz4740_timer_stop(unsigned int timer)
-{
-   writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_SET);
-}
-
-static inline void jz4740_timer_start(unsigned int timer)
-{
-   writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR);
-}
-
-static inline bool jz4740_timer_is_enabled(unsigned int timer)
-{
-   return readb(jz4740_timer_base + JZ_REG_TIMER_ENABLE) & BIT(timer);
-}
-
-static inline void jz4740_timer_enable(unsigned int timer)
-{
-   writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_SET);
-}
-
-static inline void jz4740_timer_disable(unsigned int timer)
-{
-   writeb(BIT(timer), 

[PATCH v10 23/27] MIPS: CI20: Reduce system timer and clocksource to 3 MHz

2019-03-02 Thread Paul Cercueil
The default clock (48 MHz) is too fast for the system timer.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v5: New patch

 v6: Set also the rate for the clocksource channel's clock

 v7: No change

 v8: No change

 v9: Don't configure clock timer1, as the OS Timer is used as
 clocksource on this SoC

 v10: Revert back to v8 bahaviour. Let the user choose what
  clocksource should be used.

 arch/mips/boot/dts/ingenic/ci20.dts | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/mips/boot/dts/ingenic/ci20.dts 
b/arch/mips/boot/dts/ingenic/ci20.dts
index 4f7b1fa31cf5..30b01cfaaf5a 100644
--- a/arch/mips/boot/dts/ingenic/ci20.dts
+++ b/arch/mips/boot/dts/ingenic/ci20.dts
@@ -238,3 +238,9 @@
bias-disable;
};
 };
+
+ {
+   /* 3 MHz for the system timer and clocksource */
+   assigned-clocks = < TCU_CLK_TIMER0>, < TCU_CLK_TIMER1>;
+   assigned-clock-rates = <300>, <300>;
+};
-- 
2.11.0



[PATCH v10 26/27] MIPS: GCW0: defconfig: Enable OST, watchdog, PWM drivers

2019-03-02 Thread Paul Cercueil
The OST driver provides a clocksource and sched_clock that are much more
accurate than the default ones.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v8: New patch

 v9: No change

 v10: No change

 arch/mips/configs/gcw0_defconfig | 5 +
 1 file changed, 5 insertions(+)

diff --git a/arch/mips/configs/gcw0_defconfig b/arch/mips/configs/gcw0_defconfig
index a3e3eb3c5a8b..7116400e8cbf 100644
--- a/arch/mips/configs/gcw0_defconfig
+++ b/arch/mips/configs/gcw0_defconfig
@@ -20,8 +20,13 @@ CONFIG_SERIAL_8250=y
 # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_INGENIC=y
+CONFIG_WATCHDOG=y
+CONFIG_JZ4740_WDT=y
 CONFIG_USB=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_NOP_USB_XCEIV=y
+CONFIG_INGENIC_OST=y
+CONFIG_PWM=y
+CONFIG_PWM_JZ4740=y
 CONFIG_TMPFS=y
-- 
2.11.0



[PATCH v10 25/27] MIPS: GCW0: Reduce system timer and clocksource to 750 kHz

2019-03-02 Thread Paul Cercueil
The default clock (12 MHz) is too fast for the system timer.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v8: New patch

 v9: Don't configure clock timer1, as the OS Timer is used as
 clocksource on this SoC

 v10: Revert back to v8 bahaviour. Let the user choose what
  clocksource should be used.

 arch/mips/boot/dts/ingenic/gcw0.dts | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/mips/boot/dts/ingenic/gcw0.dts 
b/arch/mips/boot/dts/ingenic/gcw0.dts
index 35f0291e8d38..2f26b8a498e9 100644
--- a/arch/mips/boot/dts/ingenic/gcw0.dts
+++ b/arch/mips/boot/dts/ingenic/gcw0.dts
@@ -60,3 +60,9 @@
/* The WiFi module is connected to the UHC. */
status = "okay";
 };
+
+ {
+   /* 750 kHz for the system timer and clocksource */
+   assigned-clocks = < TCU_CLK_TIMER0>, < TCU_CLK_TIMER1>;
+   assigned-clock-rates = <75>, <75>;
+};
-- 
2.11.0



[PATCH v10 24/27] MIPS: CI20: defconfig: enable OST driver

2019-03-02 Thread Paul Cercueil
The OST driver provides a clocksource and sched_clock that are much more
accurate than the default ones.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v5: New patch

 v6: No change

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 arch/mips/configs/ci20_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/mips/configs/ci20_defconfig b/arch/mips/configs/ci20_defconfig
index 412800d5d7e0..2f101c7c1749 100644
--- a/arch/mips/configs/ci20_defconfig
+++ b/arch/mips/configs/ci20_defconfig
@@ -105,6 +105,7 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_JZ4740=y
 CONFIG_DMADEVICES=y
 CONFIG_DMA_JZ4780=y
+CONFIG_INGENIC_OST=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_MEMORY=y
 CONFIG_EXT4_FS=y
-- 
2.11.0



[PATCH v10 15/27] pwm: jz4740: Allow selection of PWM channels 0 and 1

2019-03-02 Thread Paul Cercueil
The TCU channels 0 and 1 were previously reserved for system tasks, and
thus unavailable for PWM.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v6: New patch

 v7: No change

 v8: ingenic_tcu_[request,release]_channel are dropped. We now use
 the memory resources provided to the driver to detect whether
 or not we are allowed to use the TCU channel.

 v9: Drop previous system. Call a API function provided by the
 clocksource driver to know if we can use the channel as PWM.

 v10: No change

 drivers/pwm/pwm-jz4740.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
index f497388fc818..c914589d547b 100644
--- a/drivers/pwm/pwm-jz4740.c
+++ b/drivers/pwm/pwm-jz4740.c
@@ -44,11 +44,7 @@ static int jz4740_pwm_request(struct pwm_chip *chip, struct 
pwm_device *pwm)
char clk_name[16];
int ret;
 
-   /*
-* Timers 0 and 1 are used for system tasks, so they are unavailable
-* for use as PWMs.
-*/
-   if (pwm->hwpwm < 2)
+   if (!ingenic_tcu_pwm_can_use_chn(pwm->hwpwm))
return -EBUSY;
 
snprintf(clk_name, sizeof(clk_name), "timer%u", pwm->hwpwm);
-- 
2.11.0



[PATCH v10 19/27] MIPS: Kconfig: Select TCU timer driver when MACH_INGENIC is set

2019-03-02 Thread Paul Cercueil
We cannot boot to userspace (not even initramfs) if the timer driver is
not present; so it makes sense to enable it unconditionally when
MACH_INGENIC is set.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v5: New patch

 v6: No change

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 arch/mips/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index a84c24d894aa..8e27d9983243 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -394,6 +394,7 @@ config MACH_INGENIC
select BUILTIN_DTB
select USE_OF
select LIBFDT
+   select INGENIC_TIMER
 
 config LANTIQ
bool "Lantiq based platforms"
-- 
2.11.0



[PATCH v10 16/27] pwm: jz4740: Drop dependency on MACH_INGENIC, use COMPILE_TEST

2019-03-02 Thread Paul Cercueil
Depending on MACH_INGENIC prevent us from creating a generic kernel that
works on more than one MIPS board. Instead, we just depend on MIPS being
set.

On other architectures, this driver can still be built, thanks to
COMPILE_TEST. This is used by automated tools to find bugs, for
instance.

Signed-off-by: Paul Cercueil 
Acked-by: Thierry Reding 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v5: New patch

 v6: No change

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 drivers/pwm/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 4e201e970509..0c9b07cb77ff 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -203,7 +203,7 @@ config PWM_IMX
 
 config PWM_JZ4740
tristate "Ingenic JZ47xx PWM support"
-   depends on MACH_INGENIC
+   depends on MIPS || COMPILE_TEST
depends on COMMON_CLK
select INGENIC_TIMER
help
-- 
2.11.0



[PATCH v10 14/27] pwm: jz4740: Improve algorithm of clock calculation

2019-03-02 Thread Paul Cercueil
The previous algorithm hardcoded details about how the TCU clocks work.
The new algorithm will use clk_round_rate to find the perfect clock rate
for the PWM channel.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v9: New patch

v10: - New algorithm. Instead of starting with the maximum clock rate
   and using clk_round_rate(rate - 1) to get the next (smaller)
   clock, we compute the maximum rate we can use before the
   register overflows, and apply it with clk_set_max_rate.
   Then we read the new clock rate and compute the register values
   of the period and duty from that.
 - Use NSEC_PER_SEC instead of magic 10 value

 drivers/pwm/pwm-jz4740.c | 49 
 1 file changed, 33 insertions(+), 16 deletions(-)

diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
index c6136bd4434b..f497388fc818 100644
--- a/drivers/pwm/pwm-jz4740.c
+++ b/drivers/pwm/pwm-jz4740.c
@@ -110,24 +110,45 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip);
struct clk *clk = jz4740->clks[pwm->hwpwm],
   *parent_clk = clk_get_parent(clk);
-   unsigned long rate, period, duty;
+   unsigned long rate, parent_rate, period, duty;
unsigned long long tmp;
-   unsigned int prescaler = 0;
+   int ret;
 
-   rate = clk_get_rate(parent_clk);
-   tmp = (unsigned long long)rate * state->period;
-   do_div(tmp, 10);
-   period = tmp;
+   parent_rate = clk_get_rate(parent_clk);
+
+   jz4740_pwm_disable(chip, pwm);
+
+   /* Reset the clock to the maximum rate, and we'll reduce it if needed */
+   ret = clk_set_rate(clk, parent_rate);
+   if (ret)
+   return ret;
 
-   while (period > 0x && prescaler < 6) {
-   period >>= 2;
-   rate >>= 2;
-   ++prescaler;
+   /* Limit the clock to a maximum rate that still gives us a period value
+* which fits in 16 bits.
+*/
+   tmp = 0xull * NSEC_PER_SEC;
+   do_div(tmp, state->period);
+
+   ret = clk_set_max_rate(clk, tmp);
+   if (ret) {
+   dev_err(chip->dev, "Unable to set max rate: %i\n", ret);
+   return ret;
}
 
-   if (prescaler == 6)
-   return -EINVAL;
+   /* Read back the clock rate, as it may have been modified by
+* clk_set_max_rate()
+*/
+   rate = clk_get_rate(clk);
 
+   if (rate != parent_rate)
+   dev_dbg(chip->dev, "PWM clock updated to %lu Hz\n", rate);
+
+   /* Calculate period value */
+   tmp = (unsigned long long)rate * state->period;
+   do_div(tmp, NSEC_PER_SEC);
+   period = (unsigned long)tmp;
+
+   /* Calculate duty value */
tmp = (unsigned long long)period * state->duty_cycle;
do_div(tmp, state->period);
duty = period - tmp;
@@ -135,14 +156,10 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
if (duty >= period)
duty = period - 1;
 
-   jz4740_pwm_disable(chip, pwm);
-
/* Set abrupt shutdown */
regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm),
   TCU_TCSR_PWM_SD, TCU_TCSR_PWM_SD);
 
-   clk_set_rate(clk, rate);
-
/* Reset counter to 0 */
regmap_write(jz4740->map, TCU_REG_TCNTc(pwm->hwpwm), 0);
 
-- 
2.11.0



[PATCH v10 11/27] pwm: jz4740: Apply configuration atomically

2019-03-02 Thread Paul Cercueil
This is cleaner, more future-proof, and incidentally it also fixes the
PWM resetting its config when stopped/started several times.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v9: New patch

 v10: No change

 drivers/pwm/pwm-jz4740.c | 37 -
 1 file changed, 12 insertions(+), 25 deletions(-)

diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
index a7b134af5e04..b2f910413f81 100644
--- a/drivers/pwm/pwm-jz4740.c
+++ b/drivers/pwm/pwm-jz4740.c
@@ -83,17 +83,16 @@ static void jz4740_pwm_disable(struct pwm_chip *chip, 
struct pwm_device *pwm)
jz4740_timer_disable(pwm->hwpwm);
 }
 
-static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-int duty_ns, int period_ns)
+static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+   struct pwm_state *state)
 {
struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip);
unsigned long long tmp;
unsigned long period, duty;
unsigned int prescaler = 0;
uint16_t ctrl;
-   bool is_enabled;
 
-   tmp = (unsigned long long)clk_get_rate(jz4740->clk) * period_ns;
+   tmp = (unsigned long long)clk_get_rate(jz4740->clk) * state->period;
do_div(tmp, 10);
period = tmp;
 
@@ -105,16 +104,14 @@ static int jz4740_pwm_config(struct pwm_chip *chip, 
struct pwm_device *pwm,
if (prescaler == 6)
return -EINVAL;
 
-   tmp = (unsigned long long)period * duty_ns;
-   do_div(tmp, period_ns);
+   tmp = (unsigned long long)period * state->duty_cycle;
+   do_div(tmp, state->period);
duty = period - tmp;
 
if (duty >= period)
duty = period - 1;
 
-   is_enabled = jz4740_timer_is_enabled(pwm->hwpwm);
-   if (is_enabled)
-   jz4740_pwm_disable(chip, pwm);
+   jz4740_pwm_disable(chip, pwm);
 
jz4740_timer_set_count(pwm->hwpwm, 0);
jz4740_timer_set_duty(pwm->hwpwm, duty);
@@ -125,18 +122,7 @@ static int jz4740_pwm_config(struct pwm_chip *chip, struct 
pwm_device *pwm,
 
jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
 
-   if (is_enabled)
-   jz4740_pwm_enable(chip, pwm);
-
-   return 0;
-}
-
-static int jz4740_pwm_set_polarity(struct pwm_chip *chip,
-   struct pwm_device *pwm, enum pwm_polarity polarity)
-{
-   uint32_t ctrl = jz4740_timer_get_ctrl(pwm->pwm);
-
-   switch (polarity) {
+   switch (state->polarity) {
case PWM_POLARITY_NORMAL:
ctrl &= ~JZ_TIMER_CTRL_PWM_ACTIVE_LOW;
break;
@@ -146,16 +132,17 @@ static int jz4740_pwm_set_polarity(struct pwm_chip *chip,
}
 
jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
+
+   if (state->enabled)
+   jz4740_pwm_enable(chip, pwm);
+
return 0;
 }
 
 static const struct pwm_ops jz4740_pwm_ops = {
.request = jz4740_pwm_request,
.free = jz4740_pwm_free,
-   .config = jz4740_pwm_config,
-   .set_polarity = jz4740_pwm_set_polarity,
-   .enable = jz4740_pwm_enable,
-   .disable = jz4740_pwm_disable,
+   .apply = jz4740_pwm_apply,
.owner = THIS_MODULE,
 };
 
-- 
2.11.0



[PATCH v10 13/27] pwm: jz4740: Use clocks from TCU driver

2019-03-02 Thread Paul Cercueil
The ingenic-timer "TCU" driver provides us with clocks, that can be
(un)gated, reparented or reclocked from devicetree, instead of having
these settings hardcoded in this driver.

While this driver is devicetree-compatible, it is never (as of now)
probed from devicetree, so this change does not introduce a ABI problem
with current devicetree files.

Note that the "select REGMAP" has been dropped because it's
already enabled by the "select INGENIC_TIMER".

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v9: New patch

 v10: Explain in commit message why "select REGMAP" was dropped

 drivers/pwm/Kconfig  |  3 ++-
 drivers/pwm/pwm-jz4740.c | 39 ++-
 2 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index ace8ea4b6247..4e201e970509 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -204,7 +204,8 @@ config PWM_IMX
 config PWM_JZ4740
tristate "Ingenic JZ47xx PWM support"
depends on MACH_INGENIC
-   select REGMAP
+   depends on COMMON_CLK
+   select INGENIC_TIMER
help
  Generic PWM framework driver for Ingenic JZ47xx based
  machines.
diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
index 8dfac5ffd71c..c6136bd4434b 100644
--- a/drivers/pwm/pwm-jz4740.c
+++ b/drivers/pwm/pwm-jz4740.c
@@ -28,7 +28,7 @@
 
 struct jz4740_pwm_chip {
struct pwm_chip chip;
-   struct clk *clk;
+   struct clk *clks[NUM_PWM];
struct regmap *map;
 };
 
@@ -40,6 +40,9 @@ static inline struct jz4740_pwm_chip *to_jz4740(struct 
pwm_chip *chip)
 static int jz4740_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
 {
struct jz4740_pwm_chip *jz = to_jz4740(chip);
+   struct clk *clk;
+   char clk_name[16];
+   int ret;
 
/*
 * Timers 0 and 1 are used for system tasks, so they are unavailable
@@ -48,16 +51,29 @@ static int jz4740_pwm_request(struct pwm_chip *chip, struct 
pwm_device *pwm)
if (pwm->hwpwm < 2)
return -EBUSY;
 
-   regmap_write(jz->map, TCU_REG_TSCR, BIT(pwm->hwpwm));
+   snprintf(clk_name, sizeof(clk_name), "timer%u", pwm->hwpwm);
 
+   clk = clk_get(chip->dev, clk_name);
+   if (IS_ERR(clk))
+   return PTR_ERR(clk);
+
+   ret = clk_prepare_enable(clk);
+   if (ret) {
+   clk_put(clk);
+   return ret;
+   }
+
+   jz->clks[pwm->hwpwm] = clk;
return 0;
 }
 
 static void jz4740_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 {
struct jz4740_pwm_chip *jz = to_jz4740(chip);
+   struct clk *clk = jz->clks[pwm->hwpwm];
 
-   regmap_write(jz->map, TCU_REG_TSCR, BIT(pwm->hwpwm));
+   clk_disable_unprepare(clk);
+   clk_put(clk);
 }
 
 static int jz4740_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
@@ -92,16 +108,20 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
struct pwm_state *state)
 {
struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip);
+   struct clk *clk = jz4740->clks[pwm->hwpwm],
+  *parent_clk = clk_get_parent(clk);
+   unsigned long rate, period, duty;
unsigned long long tmp;
-   unsigned long period, duty;
unsigned int prescaler = 0;
 
-   tmp = (unsigned long long)clk_get_rate(jz4740->clk) * state->period;
+   rate = clk_get_rate(parent_clk);
+   tmp = (unsigned long long)rate * state->period;
do_div(tmp, 10);
period = tmp;
 
while (period > 0x && prescaler < 6) {
period >>= 2;
+   rate >>= 2;
++prescaler;
}
 
@@ -121,10 +141,7 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm),
   TCU_TCSR_PWM_SD, TCU_TCSR_PWM_SD);
 
-   /* Set clock prescale */
-   regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm),
-  TCU_TCSR_PRESCALE_MASK,
-  prescaler << TCU_TCSR_PRESCALE_LSB);
+   clk_set_rate(clk, rate);
 
/* Reset counter to 0 */
regmap_write(jz4740->map, TCU_REG_TCNTc(pwm->hwpwm), 0);
@@ -170,10 +187,6 @@ static int jz4740_pwm_probe(struct platform_device *pdev)
if (!jz4740)
return -ENOMEM;
 
-   jz4740->clk = devm_clk_get(>dev, "ext");
-   if (IS_ERR(jz4740->clk))
-   return PTR_ERR(jz4740->clk);
-
jz4740->map = dev_get_regmap(dev->parent, NULL);
if (!jz4740->map) {
dev_err(dev, "regmap not found\n");
-- 
2.11.0



[PATCH v10 17/27] pwm: jz4740: Remove unused devicetree compatible strings

2019-03-02 Thread Paul Cercueil
Right now none of the Ingenic-based boards probe this driver from
devicetree. This driver defined three compatible strings for the exact
same behaviour. Before these strings are used, we can remove two of
them.

Signed-off-by: Paul Cercueil 
Acked-by: Thierry Reding 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v5: New patch

 v6: No change

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 drivers/pwm/pwm-jz4740.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
index c914589d547b..823d51c8e6fe 100644
--- a/drivers/pwm/pwm-jz4740.c
+++ b/drivers/pwm/pwm-jz4740.c
@@ -228,8 +228,6 @@ static int jz4740_pwm_remove(struct platform_device *pdev)
 #ifdef CONFIG_OF
 static const struct of_device_id jz4740_pwm_dt_ids[] = {
{ .compatible = "ingenic,jz4740-pwm", },
-   { .compatible = "ingenic,jz4770-pwm", },
-   { .compatible = "ingenic,jz4780-pwm", },
{},
 };
 MODULE_DEVICE_TABLE(of, jz4740_pwm_dt_ids);
-- 
2.11.0



[PATCH v10 20/27] MIPS: jz4740: Add DTS nodes for the TCU drivers

2019-03-02 Thread Paul Cercueil
Add DTS nodes for the JZ4780, JZ4770 and JZ4740 devicetree files.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v5: New patch

 v6: Fix register lengths in watchdog/pwm nodes

 v7: No change

 v8: - Fix wrong start address for PWM node
 - Add system timer and clocksource sub-nodes

 v9: Drop timer and clocksource sub-nodes

 v10: No change

 arch/mips/boot/dts/ingenic/jz4740.dtsi | 51 +++---
 arch/mips/boot/dts/ingenic/jz4770.dtsi | 59 ++
 arch/mips/boot/dts/ingenic/jz4780.dtsi | 67 ++
 3 files changed, 164 insertions(+), 13 deletions(-)

diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi 
b/arch/mips/boot/dts/ingenic/jz4740.dtsi
index 2beb78a62b7d..bfa97e29f348 100644
--- a/arch/mips/boot/dts/ingenic/jz4740.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include 
+#include 
 
 / {
#address-cells = <1>;
@@ -45,12 +46,52 @@
#clock-cells = <1>;
};
 
-   watchdog: watchdog@10002000 {
-   compatible = "ingenic,jz4740-watchdog";
-   reg = <0x10002000 0x10>;
+   tcu: timer@10002000 {
+   compatible = "ingenic,jz4740-tcu";
+   reg = <0x10002000 0x1000>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0x0 0x10002000 0x1000>;
 
-   clocks = < JZ4740_CLK_RTC>;
-   clock-names = "rtc";
+   #clock-cells = <1>;
+
+   clocks = < JZ4740_CLK_RTC
+  JZ4740_CLK_EXT
+  JZ4740_CLK_PCLK
+  JZ4740_CLK_TCU>;
+   clock-names = "rtc", "ext", "pclk", "tcu";
+
+   interrupt-controller;
+   #interrupt-cells = <1>;
+
+   interrupt-parent = <>;
+   interrupts = <23 22 21>;
+
+   watchdog: watchdog@0 {
+   compatible = "ingenic,jz4740-watchdog";
+   reg = <0x0 0xc>;
+
+   clocks = < TCU_CLK_WDT>;
+   clock-names = "wdt";
+   };
+
+   pwm: pwm@40 {
+   compatible = "ingenic,jz4740-pwm";
+   reg = <0x40 0x80>;
+
+   #pwm-cells = <3>;
+
+   clocks = < TCU_CLK_TIMER0
+  TCU_CLK_TIMER1
+  TCU_CLK_TIMER2
+  TCU_CLK_TIMER3
+  TCU_CLK_TIMER4
+  TCU_CLK_TIMER5
+  TCU_CLK_TIMER6
+  TCU_CLK_TIMER7>;
+   clock-names = "timer0", "timer1", "timer2", "timer3",
+ "timer4", "timer5", "timer6", "timer7";
+   };
};
 
rtc_dev: rtc@10003000 {
diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi 
b/arch/mips/boot/dts/ingenic/jz4770.dtsi
index 49ede6c14ff3..89c7a4b9773c 100644
--- a/arch/mips/boot/dts/ingenic/jz4770.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4770.dtsi
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
 #include 
+#include 
 
 / {
#address-cells = <1>;
@@ -46,6 +47,64 @@
#clock-cells = <1>;
};
 
+   tcu: timer@10002000 {
+   compatible = "ingenic,jz4770-tcu";
+   reg = <0x10002000 0x1000>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0x0 0x10002000 0x1000>;
+
+   #clock-cells = <1>;
+
+   clocks = < JZ4770_CLK_RTC
+  JZ4770_CLK_EXT
+  JZ4770_CLK_PCLK
+  JZ4770_CLK_EXT>;
+   clock-names = "rtc", "ext", "pclk", "tcu";
+
+   interrupt-controller;
+   #interrupt-cells = <1>;
+
+   interrupt-parent = <>;
+   interrupts = <27 26 25>;
+
+   watchdog: watchdog@0 {
+   compatible = "ingenic,jz4740-watchdog";
+   reg = <0x0 0xc>;
+
+   clocks = < TCU_CLK_WDT>;
+   clock-names = "wdt";
+   };
+
+   pwm: pwm@40 {
+   compatible = "ingenic,jz4740-pwm";
+   reg = <0x40 0x80>;
+
+   #pwm-cells = <3>;
+
+   clocks = < TCU_CLK_TIMER0
+  TCU_CLK_TIMER1
+  TCU_CLK_TIMER2
+  TCU_CLK_TIMER3
+  TCU_CLK_TIMER4
+  TCU_CLK_TIMER5
+  TCU_CLK_TIMER6
+  

[PATCH v10 18/27] clk: jz4740: Add TCU clock

2019-03-02 Thread Paul Cercueil
Add the missing TCU clock to the list of clocks supplied by the CGU for
the JZ4740 SoC.

Signed-off-by: Paul Cercueil 
Acked-by: Stephen Boyd 
Acked-by: Rob Herring 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v5: New patch

 v6: No change

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 drivers/clk/ingenic/jz4740-cgu.c   | 6 ++
 include/dt-bindings/clock/jz4740-cgu.h | 1 +
 2 files changed, 7 insertions(+)

diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c
index 4479c102e899..d8ac7f2e183a 100644
--- a/drivers/clk/ingenic/jz4740-cgu.c
+++ b/drivers/clk/ingenic/jz4740-cgu.c
@@ -211,6 +211,12 @@ static const struct ingenic_cgu_clk_info 
jz4740_cgu_clocks[] = {
.parents = { JZ4740_CLK_EXT, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 5 },
},
+
+   [JZ4740_CLK_TCU] = {
+   "tcu", CGU_CLK_GATE,
+   .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
+   .gate = { CGU_REG_CLKGR, 1 },
+   },
 };
 
 static void __init jz4740_cgu_init(struct device_node *np)
diff --git a/include/dt-bindings/clock/jz4740-cgu.h 
b/include/dt-bindings/clock/jz4740-cgu.h
index 6ed83f926ae7..e82d77028581 100644
--- a/include/dt-bindings/clock/jz4740-cgu.h
+++ b/include/dt-bindings/clock/jz4740-cgu.h
@@ -34,5 +34,6 @@
 #define JZ4740_CLK_ADC 19
 #define JZ4740_CLK_I2C 20
 #define JZ4740_CLK_AIC 21
+#define JZ4740_CLK_TCU 22
 
 #endif /* __DT_BINDINGS_CLOCK_JZ4740_CGU_H__ */
-- 
2.11.0



[PATCH v10 09/27] watchdog: jz4740: Avoid starting watchdog in set_timeout

2019-03-02 Thread Paul Cercueil
Previously the jz4740_wdt_set_timeout() function was starting the timer
unconditionally, even if it was stopped when that function was entered.

Now, the timer will be restarted only if it was already running before
this function is called.

Signed-off-by: Paul Cercueil 
Reviewed-by: Guenter Roeck 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v6: New patch

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 drivers/watchdog/jz4740_wdt.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
index 0f54306aee25..45d9495170e5 100644
--- a/drivers/watchdog/jz4740_wdt.c
+++ b/drivers/watchdog/jz4740_wdt.c
@@ -64,13 +64,15 @@ static int jz4740_wdt_set_timeout(struct watchdog_device 
*wdt_dev,
 {
struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
u16 timeout_value = (u16)(drvdata->clk_rate * new_timeout);
+   u32 tcer;
 
+   regmap_read(drvdata->map, TCU_REG_WDT_TCER, );
regmap_write(drvdata->map, TCU_REG_WDT_TCER, 0);
 
regmap_write(drvdata->map, TCU_REG_WDT_TDR, timeout_value);
regmap_write(drvdata->map, TCU_REG_WDT_TCNT, 0);
 
-   regmap_write(drvdata->map, TCU_REG_WDT_TCER, TCU_WDT_TCER_TCEN);
+   regmap_write(drvdata->map, TCU_REG_WDT_TCER, tcer & TCU_WDT_TCER_TCEN);
 
wdt_dev->timeout = new_timeout;
return 0;
@@ -86,6 +88,7 @@ static int jz4740_wdt_start(struct watchdog_device *wdt_dev)
return ret;
 
jz4740_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
+   regmap_write(drvdata->map, TCU_REG_WDT_TCER, TCU_WDT_TCER_TCEN);
 
return 0;
 }
-- 
2.11.0



[PATCH v10 12/27] pwm: jz4740: Use regmap from TCU driver

2019-03-02 Thread Paul Cercueil
The ingenic-timer "TCU" driver provides us with a regmap, that we can
use to safely access the TCU registers.

While this driver is devicetree-compatible, it is never (as of now)
probed from devicetree, so this change does not introduce a ABI problem
with current devicetree files.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v9: New patch

 v10: No change

 drivers/pwm/Kconfig  |  1 +
 drivers/pwm/pwm-jz4740.c | 74 +++-
 2 files changed, 49 insertions(+), 26 deletions(-)

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index a8f47df0655a..ace8ea4b6247 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -204,6 +204,7 @@ config PWM_IMX
 config PWM_JZ4740
tristate "Ingenic JZ47xx PWM support"
depends on MACH_INGENIC
+   select REGMAP
help
  Generic PWM framework driver for Ingenic JZ47xx based
  machines.
diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
index b2f910413f81..8dfac5ffd71c 100644
--- a/drivers/pwm/pwm-jz4740.c
+++ b/drivers/pwm/pwm-jz4740.c
@@ -17,18 +17,19 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
-
-#include 
+#include 
 
 #define NUM_PWM 8
 
 struct jz4740_pwm_chip {
struct pwm_chip chip;
struct clk *clk;
+   struct regmap *map;
 };
 
 static inline struct jz4740_pwm_chip *to_jz4740(struct pwm_chip *chip)
@@ -38,6 +39,8 @@ static inline struct jz4740_pwm_chip *to_jz4740(struct 
pwm_chip *chip)
 
 static int jz4740_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
 {
+   struct jz4740_pwm_chip *jz = to_jz4740(chip);
+
/*
 * Timers 0 and 1 are used for system tasks, so they are unavailable
 * for use as PWMs.
@@ -45,42 +48,44 @@ static int jz4740_pwm_request(struct pwm_chip *chip, struct 
pwm_device *pwm)
if (pwm->hwpwm < 2)
return -EBUSY;
 
-   jz4740_timer_start(pwm->hwpwm);
+   regmap_write(jz->map, TCU_REG_TSCR, BIT(pwm->hwpwm));
 
return 0;
 }
 
 static void jz4740_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 {
-   jz4740_timer_set_ctrl(pwm->hwpwm, 0);
+   struct jz4740_pwm_chip *jz = to_jz4740(chip);
 
-   jz4740_timer_stop(pwm->hwpwm);
+   regmap_write(jz->map, TCU_REG_TSCR, BIT(pwm->hwpwm));
 }
 
 static int jz4740_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
-   uint32_t ctrl = jz4740_timer_get_ctrl(pwm->pwm);
+   struct jz4740_pwm_chip *jz = to_jz4740(chip);
 
-   ctrl |= JZ_TIMER_CTRL_PWM_ENABLE;
-   jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
-   jz4740_timer_enable(pwm->hwpwm);
+   /* Enable PWM output */
+   regmap_update_bits(jz->map, TCU_REG_TCSRc(pwm->hwpwm),
+  TCU_TCSR_PWM_EN, TCU_TCSR_PWM_EN);
 
+   /* Start counter */
+   regmap_write(jz->map, TCU_REG_TESR, BIT(pwm->hwpwm));
return 0;
 }
 
 static void jz4740_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
-   uint32_t ctrl = jz4740_timer_get_ctrl(pwm->hwpwm);
+   struct jz4740_pwm_chip *jz = to_jz4740(chip);
 
/* Disable PWM output.
 * In TCU2 mode (channel 1/2 on JZ4750+), this must be done before the
 * counter is stopped, while in TCU1 mode the order does not matter.
 */
-   ctrl &= ~JZ_TIMER_CTRL_PWM_ENABLE;
-   jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
+   regmap_update_bits(jz->map, TCU_REG_TCSRc(pwm->hwpwm),
+  TCU_TCSR_PWM_EN, 0);
 
/* Stop counter */
-   jz4740_timer_disable(pwm->hwpwm);
+   regmap_write(jz->map, TCU_REG_TECR, BIT(pwm->hwpwm));
 }
 
 static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -90,7 +95,6 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
unsigned long long tmp;
unsigned long period, duty;
unsigned int prescaler = 0;
-   uint16_t ctrl;
 
tmp = (unsigned long long)clk_get_rate(jz4740->clk) * state->period;
do_div(tmp, 10);
@@ -113,26 +117,37 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
 
jz4740_pwm_disable(chip, pwm);
 
-   jz4740_timer_set_count(pwm->hwpwm, 0);
-   jz4740_timer_set_duty(pwm->hwpwm, duty);
-   jz4740_timer_set_period(pwm->hwpwm, period);
+   /* Set abrupt shutdown */
+   regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm),
+  TCU_TCSR_PWM_SD, TCU_TCSR_PWM_SD);
+
+   /* Set clock prescale */
+   regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm),
+  TCU_TCSR_PRESCALE_MASK,
+  prescaler << TCU_TCSR_PRESCALE_LSB);
+
+   /* Reset counter to 0 */
+   regmap_write(jz4740->map, TCU_REG_TCNTc(pwm->hwpwm), 0);
 
-   ctrl = JZ_TIMER_CTRL_PRESCALER(prescaler) | 

[PATCH v10 10/27] watchdog: jz4740: Drop dependency on MACH_JZ47xx, use COMPILE_TEST

2019-03-02 Thread Paul Cercueil
Depending on MACH_JZ47xx prevent us from creating a generic kernel that
works on more than one MIPS board. Instead, we just depend on MIPS being
set.

On other architectures, this driver can still be built, thanks to
COMPILE_TEST. This is used by automated tools to find bugs, for
instance.

Signed-off-by: Paul Cercueil 
Reviewed-by: Guenter Roeck 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v5: New patch

 v6: No change

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 drivers/watchdog/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index a2a065eefb59..061885fd94ad 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1516,7 +1516,7 @@ config INDYDOG
 
 config JZ4740_WDT
tristate "Ingenic jz4740 SoC hardware watchdog"
-   depends on MACH_JZ4740 || MACH_JZ4780
+   depends on MIPS || COMPILE_TEST
depends on COMMON_CLK
select WATCHDOG_CORE
select INGENIC_TIMER
-- 
2.11.0



[PATCH v10 05/27] clocksource: Add driver for the Ingenic JZ47xx OST

2019-03-02 Thread Paul Cercueil
From: Maarten ter Huurne 

OST is the OS Timer, a 64-bit timer/counter with buffered reading.

SoCs before the JZ4770 had (if any) a 32-bit OST; the JZ4770 and
JZ4780 have a 64-bit OST.

This driver will register both a clocksource and a sched_clock to the
system.

Signed-off-by: Maarten ter Huurne 
Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v5: New patch

 v6: - Get rid of SoC IDs; pass pointer to ingenic_ost_soc_info as
   devicetree match data instead.
 - Use device_get_match_data() instead of the of_* variant
 - Handle error of dev_get_regmap() properly

 v7: Fix section mismatch by using builtin_platform_driver_probe()

 v8: builtin_platform_driver_probe() does not work anymore in
 4.20-rc6? The probe function won't be called. Work around this
 for now by using late_initcall.

 v9: No change

v10: Fix TCU_OST_TCSR_MASK only covering 8 bits instead of the 16 bits
 of the register. This fixes hangs on JZ4770 and JZ4780.

 drivers/clocksource/Kconfig   |   8 ++
 drivers/clocksource/Makefile  |   1 +
 drivers/clocksource/ingenic-ost.c | 212 ++
 3 files changed, 221 insertions(+)
 create mode 100644 drivers/clocksource/ingenic-ost.c

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index d841934e126c..9793db79798b 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -644,4 +644,12 @@ config INGENIC_TIMER
help
  Support for the timer/counter unit of the Ingenic JZ SoCs.
 
+config INGENIC_OST
+   bool "Ingenic JZ47xx Operating System Timer"
+   depends on MIPS || COMPILE_TEST
+   depends on COMMON_CLK
+   select INGENIC_TIMER
+   help
+ Support for the OS Timer of the Ingenic JZ4770 or similar SoC.
+
 endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 3eb8c544917f..7240a35413c0 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_ASM9260_TIMER)   += asm9260_timer.o
 obj-$(CONFIG_H8300_TMR8)   += h8300_timer8.o
 obj-$(CONFIG_H8300_TMR16)  += h8300_timer16.o
 obj-$(CONFIG_H8300_TPU)+= h8300_tpu.o
+obj-$(CONFIG_INGENIC_OST)  += ingenic-ost.o
 obj-$(CONFIG_INGENIC_TIMER)+= ingenic-timer.o
 obj-$(CONFIG_CLKSRC_ST_LPC)+= clksrc_st_lpc.o
 obj-$(CONFIG_X86_NUMACHIP) += numachip.o
diff --git a/drivers/clocksource/ingenic-ost.c 
b/drivers/clocksource/ingenic-ost.c
new file mode 100644
index ..0f64d939168a
--- /dev/null
+++ b/drivers/clocksource/ingenic-ost.c
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * JZ47xx SoCs TCU Operating System Timer driver
+ *
+ * Copyright (C) 2016 Maarten ter Huurne 
+ * Copyright (C) 2018 Paul Cercueil 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ingenic-timer.h"
+
+#define TCU_OST_TCSR_MASK  0xffc0
+#define TCU_OST_TCSR_CNT_MDBIT(15)
+
+#define TCU_OST_CHANNEL15
+
+struct ingenic_ost_soc_info {
+   bool is64bit;
+};
+
+struct ingenic_ost {
+   struct regmap *map;
+   struct clk *clk;
+
+   struct clocksource cs;
+};
+
+static u64 notrace ingenic_ost_read_cntl(void)
+{
+   /* Bypass the regmap here as we must return as soon as possible */
+   return readl(ingenic_tcu_base + TCU_REG_OST_CNTL);
+}
+
+static u64 notrace ingenic_ost_read_cnth(void)
+{
+   /* Bypass the regmap here as we must return as soon as possible */
+   return readl(ingenic_tcu_base + TCU_REG_OST_CNTH);
+}
+
+static u64 notrace ingenic_ost_clocksource_read64(struct clocksource *cs)
+{
+   u32 val1, val2;
+   u64 count, recount;
+   s64 diff;
+
+   /*
+* The buffering of the upper 32 bits of the timer prevents wrong
+* results from the bottom 32 bits overflowing due to the timer ticking
+* along. However, it does not prevent wrong results from simultaneous
+* reads of the timer, which could reset the buffer mid-read.
+* Since this kind of wrong read can happen only when the bottom bits
+* overflow, there will be minutes between wrong reads, so if we read
+* twice in succession, at least one of the reads will be correct.
+*/
+
+   /* Bypass the regmap here as we must return as soon as possible */
+   val1 = readl(ingenic_tcu_base + TCU_REG_OST_CNTL);
+   val2 = readl(ingenic_tcu_base + TCU_REG_OST_CNTHBUF);
+   count = (u64)val1 | (u64)val2 << 32;
+
+   val1 = readl(ingenic_tcu_base + TCU_REG_OST_CNTL);
+   val2 = readl(ingenic_tcu_base + TCU_REG_OST_CNTHBUF);
+   recount = (u64)val1 | (u64)val2 << 32;
+
+   /*
+* A wrong read will produce a result 

[PATCH v10 06/27] MAINTAINERS: Add myself as maintainer for Ingenic TCU drivers

2019-03-02 Thread Paul Cercueil
Add myself as maintainer for the ingenic-timer and ingenic-ost drivers.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v2: No change

 v3: No change

 v4: No change

 v5: Update with new files

 v6: No change

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 MAINTAINERS | 9 +
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index dce5c099f43c..3347efa545f1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7515,6 +7515,15 @@ L:   linux-...@lists.infradead.org
 S: Maintained
 F: drivers/mtd/nand/raw/jz4780_*
 
+INGENIC TCU driver
+M: Paul Cercueil 
+S: Maintained
+F: drivers/clocksource/ingenic-ost.c
+F: drivers/clocksource/ingenic-timer.c
+F: drivers/clocksource/ingenic-timer.h
+F: include/linux/mfd/ingenic-tcu.h
+F: include/dt-bindings/clock/ingenic,tcu.h
+
 INOTIFY
 M: Jan Kara 
 R: Amir Goldstein 
-- 
2.11.0



[PATCH v10 08/27] watchdog: jz4740: Use regmap provided by TCU driver

2019-03-02 Thread Paul Cercueil
Since we broke the ABI by changing the clock, the driver was also
updated to use the regmap provided by the TCU driver.

Signed-off-by: Paul Cercueil 
Reviewed-by: Guenter Roeck 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v6: New patch

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 drivers/watchdog/jz4740_wdt.c | 30 ++
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
index 1d504ecf45e1..0f54306aee25 100644
--- a/drivers/watchdog/jz4740_wdt.c
+++ b/drivers/watchdog/jz4740_wdt.c
@@ -13,6 +13,7 @@
  *
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -25,10 +26,7 @@
 #include 
 #include 
 #include 
-
-#define JZ_REG_WDT_TIMER_DATA 0x0
-#define JZ_REG_WDT_COUNTER_ENABLE 0x4
-#define JZ_REG_WDT_TIMER_COUNTER  0x8
+#include 
 
 #define DEFAULT_HEARTBEAT 5
 #define MAX_HEARTBEAT 2048
@@ -48,7 +46,7 @@ MODULE_PARM_DESC(heartbeat,
 
 struct jz4740_wdt_drvdata {
struct watchdog_device wdt;
-   void __iomem *base;
+   struct regmap *map;
struct clk *clk;
unsigned long clk_rate;
 };
@@ -57,7 +55,7 @@ static int jz4740_wdt_ping(struct watchdog_device *wdt_dev)
 {
struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
 
-   writew(0x0, drvdata->base + JZ_REG_WDT_TIMER_COUNTER);
+   regmap_write(drvdata->map, TCU_REG_WDT_TCNT, 0);
return 0;
 }
 
@@ -67,12 +65,12 @@ static int jz4740_wdt_set_timeout(struct watchdog_device 
*wdt_dev,
struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
u16 timeout_value = (u16)(drvdata->clk_rate * new_timeout);
 
-   writeb(0x0, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE);
+   regmap_write(drvdata->map, TCU_REG_WDT_TCER, 0);
 
-   writew((u16)timeout_value, drvdata->base + JZ_REG_WDT_TIMER_DATA);
-   writew(0x0, drvdata->base + JZ_REG_WDT_TIMER_COUNTER);
+   regmap_write(drvdata->map, TCU_REG_WDT_TDR, timeout_value);
+   regmap_write(drvdata->map, TCU_REG_WDT_TCNT, 0);
 
-   writeb(0x1, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE);
+   regmap_write(drvdata->map, TCU_REG_WDT_TCER, TCU_WDT_TCER_TCEN);
 
wdt_dev->timeout = new_timeout;
return 0;
@@ -96,7 +94,7 @@ static int jz4740_wdt_stop(struct watchdog_device *wdt_dev)
 {
struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
 
-   writeb(0x0, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE);
+   regmap_write(drvdata->map, TCU_REG_WDT_TCER, 0);
clk_disable_unprepare(drvdata->clk);
 
return 0;
@@ -138,7 +136,6 @@ static int jz4740_wdt_probe(struct platform_device *pdev)
struct device *dev = >dev;
struct jz4740_wdt_drvdata *drvdata;
struct watchdog_device *jz4740_wdt;
-   struct resource *res;
long rate;
int ret;
 
@@ -174,10 +171,11 @@ static int jz4740_wdt_probe(struct platform_device *pdev)
watchdog_set_nowayout(jz4740_wdt, nowayout);
watchdog_set_drvdata(jz4740_wdt, drvdata);
 
-   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-   drvdata->base = devm_ioremap_resource(>dev, res);
-   if (IS_ERR(drvdata->base))
-   return PTR_ERR(drvdata->base);
+   drvdata->map = dev_get_regmap(dev->parent, NULL);
+   if (!drvdata->map) {
+   dev_err(dev, "regmap not found\n");
+   return -EINVAL;
+   }
 
ret = devm_watchdog_register_device(>dev, >wdt);
if (ret < 0)
-- 
2.11.0



[PATCH v10 02/27] doc: Add doc for the Ingenic TCU hardware

2019-03-02 Thread Paul Cercueil
Add a documentation file about the Timer/Counter Unit (TCU) present in
the Ingenic JZ47xx SoCs.

The Timer/Counter Unit (TCU) in Ingenic JZ47xx SoCs is a multi-function
hardware block. It features up to to eight channels, that can be used as
counters, timers, or PWM.

- JZ4725B, JZ4750, JZ4755 only have six TCU channels. The other SoCs all
  have eight channels.

- JZ4725B introduced a separate channel, called Operating System Timer
  (OST). It is a 32-bit programmable timer. On JZ4770 and above, it is
  64-bit.

- Each one of the TCU channels has its own clock, which can be reparented
  to three different clocks (pclk, ext, rtc), gated, and reclocked, through
  their TCSR register.
  * The watchdog and OST hardware blocks also feature a TCSR register with
the same format in their register space.
  * The TCU registers used to gate/ungate can also gate/ungate the watchdog
and OST clocks.

- Each TCU channel works in one of two modes:
  * mode TCU1: channels cannot work in sleep mode, but are easier to
operate.
  * mode TCU2: channels can work in sleep mode, but the operation is a bit
more complicated than with TCU1 channels.

- The mode of each TCU channel depends on the SoC used:
  * On the oldest SoCs (up to JZ4740), all of the eight channels operate in
TCU1 mode.
  * On JZ4725B, channel 5 operates as TCU2, the others operate as TCU1.
  * On newest SoCs (JZ4750 and above), channels 1-2 operate as TCU2, the
others operate as TCU1.

- Each channel can generate an interrupt. Some channels share an interrupt
  line, some don't, and this changes between SoC versions:
  * on older SoCs (JZ4740 and below), channel 0 and channel 1 have their
own interrupt line; channels 2-7 share the last interrupt line.
  * On JZ4725B, channel 0 has its own interrupt; channels 1-5 share one
interrupt line; the OST uses the last interrupt line.
  * on newer SoCs (JZ4750 and above), channel 5 has its own interrupt;
channels 0-4 and (if eight channels) 6-7 all share one interrupt line;
the OST uses the last interrupt line.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v4: New patch in this series

 v5: Added information about number of channels, and improved
 documentation about channel modes

 v6: Add info about OST (can be 32-bit on older SoCs)

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 Documentation/mips/ingenic-tcu.txt | 60 ++
 1 file changed, 60 insertions(+)
 create mode 100644 Documentation/mips/ingenic-tcu.txt

diff --git a/Documentation/mips/ingenic-tcu.txt 
b/Documentation/mips/ingenic-tcu.txt
new file mode 100644
index ..0ea35b2a46da
--- /dev/null
+++ b/Documentation/mips/ingenic-tcu.txt
@@ -0,0 +1,60 @@
+Ingenic JZ47xx SoCs Timer/Counter Unit hardware
+---
+
+The Timer/Counter Unit (TCU) in Ingenic JZ47xx SoCs is a multi-function
+hardware block. It features up to to eight channels, that can be used as
+counters, timers, or PWM.
+
+- JZ4725B, JZ4750, JZ4755 only have six TCU channels. The other SoCs all
+  have eight channels.
+
+- JZ4725B introduced a separate channel, called Operating System Timer
+  (OST). It is a 32-bit programmable timer. On JZ4770 and above, it is
+  64-bit.
+
+- Each one of the TCU channels has its own clock, which can be reparented
+  to three different clocks (pclk, ext, rtc), gated, and reclocked, through
+  their TCSR register.
+  * The watchdog and OST hardware blocks also feature a TCSR register with
+the same format in their register space.
+  * The TCU registers used to gate/ungate can also gate/ungate the watchdog
+and OST clocks.
+
+- Each TCU channel works in one of two modes:
+  * mode TCU1: channels cannot work in sleep mode, but are easier to
+operate.
+  * mode TCU2: channels can work in sleep mode, but the operation is a bit
+more complicated than with TCU1 channels.
+
+- The mode of each TCU channel depends on the SoC used:
+  * On the oldest SoCs (up to JZ4740), all of the eight channels operate in
+TCU1 mode.
+  * On JZ4725B, channel 5 operates as TCU2, the others operate as TCU1.
+  * On newest SoCs (JZ4750 and above), channels 1-2 operate as TCU2, the
+others operate as TCU1.
+
+- Each channel can generate an interrupt. Some channels share an interrupt
+  line, some don't, and this changes between SoC versions:
+  * on older SoCs (JZ4740 and below), channel 0 and channel 1 have their
+own interrupt line; channels 2-7 share the last interrupt line.
+  * On JZ4725B, channel 0 has its own interrupt; channels 1-5 share one
+interrupt line; the OST uses the last interrupt line.
+  * on newer SoCs (JZ4750 and above), channel 5 has its own interrupt;
+channels 0-4 and (if eight channels) 6-7 all share one interrupt line;
+the OST uses the last 

[PATCH v10 07/27] watchdog: jz4740: Use WDT clock provided by TCU driver

2019-03-02 Thread Paul Cercueil
Instead of requesting the "ext" clock and handling the watchdog clock
divider and gating in the watchdog driver, we now request and use the
"wdt" clock that is supplied by the ingenic-timer "TCU" driver.

The major benefit is that the watchdog's clock rate and parent can now
be specified from within devicetree, instead of hardcoded in the driver.

Also, this driver won't poke anymore into the TCU registers to
enable/disable the clock, as this is now handled by the TCU driver.

On the bad side, we break the ABI with devicetree - as we now request a
different clock. In this very specific case it is still okay, as every
Ingenic JZ47xx-based board out there compile the devicetree within the
kernel; so it's still time to push breaking changes, in order to get a
clean devicetree that won't break once it musn't.

Signed-off-by: Paul Cercueil 
Reviewed-by: Guenter Roeck 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v5: New patch

 v6: - Split regmap change to new patch 09/24
 - The code now sets the WDT clock to the smallest rate possible and
   calculates the maximum timeout from that

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 drivers/watchdog/Kconfig  |  2 +
 drivers/watchdog/jz4740_wdt.c | 86 +--
 2 files changed, 36 insertions(+), 52 deletions(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 57f017d74a97..a2a065eefb59 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1517,7 +1517,9 @@ config INDYDOG
 config JZ4740_WDT
tristate "Ingenic jz4740 SoC hardware watchdog"
depends on MACH_JZ4740 || MACH_JZ4780
+   depends on COMMON_CLK
select WATCHDOG_CORE
+   select INGENIC_TIMER
help
  Hardware driver for the built-in watchdog timer on Ingenic jz4740 
SoCs.
 
diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
index ec4d99a830ba..1d504ecf45e1 100644
--- a/drivers/watchdog/jz4740_wdt.c
+++ b/drivers/watchdog/jz4740_wdt.c
@@ -26,25 +26,9 @@
 #include 
 #include 
 
-#include 
-
 #define JZ_REG_WDT_TIMER_DATA 0x0
 #define JZ_REG_WDT_COUNTER_ENABLE 0x4
 #define JZ_REG_WDT_TIMER_COUNTER  0x8
-#define JZ_REG_WDT_TIMER_CONTROL  0xC
-
-#define JZ_WDT_CLOCK_PCLK 0x1
-#define JZ_WDT_CLOCK_RTC  0x2
-#define JZ_WDT_CLOCK_EXT  0x4
-
-#define JZ_WDT_CLOCK_DIV_SHIFT   3
-
-#define JZ_WDT_CLOCK_DIV_1(0 << JZ_WDT_CLOCK_DIV_SHIFT)
-#define JZ_WDT_CLOCK_DIV_4(1 << JZ_WDT_CLOCK_DIV_SHIFT)
-#define JZ_WDT_CLOCK_DIV_16   (2 << JZ_WDT_CLOCK_DIV_SHIFT)
-#define JZ_WDT_CLOCK_DIV_64   (3 << JZ_WDT_CLOCK_DIV_SHIFT)
-#define JZ_WDT_CLOCK_DIV_256  (4 << JZ_WDT_CLOCK_DIV_SHIFT)
-#define JZ_WDT_CLOCK_DIV_1024 (5 << JZ_WDT_CLOCK_DIV_SHIFT)
 
 #define DEFAULT_HEARTBEAT 5
 #define MAX_HEARTBEAT 2048
@@ -65,7 +49,8 @@ MODULE_PARM_DESC(heartbeat,
 struct jz4740_wdt_drvdata {
struct watchdog_device wdt;
void __iomem *base;
-   struct clk *rtc_clk;
+   struct clk *clk;
+   unsigned long clk_rate;
 };
 
 static int jz4740_wdt_ping(struct watchdog_device *wdt_dev)
@@ -80,31 +65,12 @@ static int jz4740_wdt_set_timeout(struct watchdog_device 
*wdt_dev,
unsigned int new_timeout)
 {
struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
-   unsigned int rtc_clk_rate;
-   unsigned int timeout_value;
-   unsigned short clock_div = JZ_WDT_CLOCK_DIV_1;
-
-   rtc_clk_rate = clk_get_rate(drvdata->rtc_clk);
-
-   timeout_value = rtc_clk_rate * new_timeout;
-   while (timeout_value > 0x) {
-   if (clock_div == JZ_WDT_CLOCK_DIV_1024) {
-   /* Requested timeout too high;
-   * use highest possible value. */
-   timeout_value = 0x;
-   break;
-   }
-   timeout_value >>= 2;
-   clock_div += (1 << JZ_WDT_CLOCK_DIV_SHIFT);
-   }
+   u16 timeout_value = (u16)(drvdata->clk_rate * new_timeout);
 
writeb(0x0, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE);
-   writew(clock_div, drvdata->base + JZ_REG_WDT_TIMER_CONTROL);
 
writew((u16)timeout_value, drvdata->base + JZ_REG_WDT_TIMER_DATA);
writew(0x0, drvdata->base + JZ_REG_WDT_TIMER_COUNTER);
-   writew(clock_div | JZ_WDT_CLOCK_RTC,
-   drvdata->base + JZ_REG_WDT_TIMER_CONTROL);
 
writeb(0x1, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE);
 
@@ -114,7 +80,13 @@ static int jz4740_wdt_set_timeout(struct watchdog_device 
*wdt_dev,
 
 static int jz4740_wdt_start(struct watchdog_device *wdt_dev)
 {
-   jz4740_timer_enable_watchdog();
+   struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+   int ret;
+
+   ret = clk_prepare_enable(drvdata->clk);
+   if (ret)
+   return ret;
+
  

[PATCH v10 03/27] dt-bindings: Add doc for the Ingenic TCU drivers

2019-03-02 Thread Paul Cercueil
Add documentation about how to properly use the Ingenic TCU
(Timer/Counter Unit) drivers from devicetree.

Signed-off-by: Paul Cercueil 
Reviewed-by: Rob Herring 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v4: New patch in this series. Corresponds to V2 patches 3-4-5 with
 added content.

 v5: - Edited PWM/watchdog DT bindings documentation to point to the new
   document.
 - Moved main document to
   Documentation/devicetree/bindings/timer/ingenic,tcu.txt
 - Updated documentation to reflect the new devicetree bindings.

 v6: - Removed PWM/watchdog documentation files as asked by upstream
 - Removed doc about properties that should be implicit
 - Removed doc about ingenic,timer-channel /
   ingenic,clocksource-channel as they are gone
 - Fix WDT clock name in the binding doc
 - Fix lengths of register areas in watchdog/pwm nodes

 v7: No change

 v8: - Fix address of the PWM node
 - Added doc about system timer and clocksource children nodes

 v9: - Remove doc about system timer and clocksource children
   nodes...
 - Add doc about ingenic,pwm-channels-mask property

 v10: No change

 .../devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt |  25 
 .../devicetree/bindings/timer/ingenic,tcu.txt  | 139 +
 .../bindings/watchdog/ingenic,jz4740-wdt.txt   |  17 ---
 3 files changed, 139 insertions(+), 42 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ingenic,tcu.txt
 delete mode 100644 
Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt

diff --git a/Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt 
b/Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt
deleted file mode 100644
index 7d9d3f90641b..
--- a/Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-Ingenic JZ47xx PWM Controller
-=
-
-Required properties:
-- compatible: One of:
-  * "ingenic,jz4740-pwm"
-  * "ingenic,jz4770-pwm"
-  * "ingenic,jz4780-pwm"
-- #pwm-cells: Should be 3. See pwm.txt in this directory for a description
-  of the cells format.
-- clocks : phandle to the external clock.
-- clock-names : Should be "ext".
-
-
-Example:
-
-   pwm: pwm@10002000 {
-   compatible = "ingenic,jz4740-pwm";
-   reg = <0x10002000 0x1000>;
-
-   #pwm-cells = <3>;
-
-   clocks = <>;
-   clock-names = "ext";
-   };
diff --git a/Documentation/devicetree/bindings/timer/ingenic,tcu.txt 
b/Documentation/devicetree/bindings/timer/ingenic,tcu.txt
new file mode 100644
index ..ec9639700115
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/ingenic,tcu.txt
@@ -0,0 +1,139 @@
+Ingenic JZ47xx SoCs Timer/Counter Unit devicetree bindings
+==
+
+For a description of the TCU hardware and drivers, have a look at
+Documentation/mips/ingenic-tcu.txt.
+
+Required properties:
+
+- compatible: Must be one of:
+  * ingenic,jz4740-tcu
+  * ingenic,jz4725b-tcu
+  * ingenic,jz4770-tcu
+- reg: Should be the offset/length value corresponding to the TCU registers
+- clocks: List of phandle & clock specifiers for clocks external to the TCU.
+  The "pclk", "rtc", "ext" and "tcu" clocks should be provided.
+- clock-names: List of name strings for the external clocks.
+- #clock-cells: Should be <1>;
+  Clock consumers specify this argument to identify a clock. The valid values
+  may be found in .
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value should be 1.
+- interrupt-parent : phandle of the interrupt controller.
+- interrupts : Specifies the interrupt the controller is connected to.
+
+Optional properties:
+
+- ingenic,pwm-channels-mask: Bitmask of TCU channels reserved for PWM use.
+  Default value is 0xfe or 0xfc if the SoC does not have the OS Timer.
+
+
+Children nodes
+==
+
+
+PWM node:
+-
+
+Required properties:
+
+- compatible: Must be one of:
+  * ingenic,jz4740-pwm
+  * ingenic,jz4725b-pwm
+- #pwm-cells: Should be 3. See ../pwm/pwm.txt for a description of the cell
+  format.
+- clocks: List of phandle & clock specifiers for the TCU clocks.
+- clock-names: List of name strings for the TCU clocks.
+
+
+Watchdog node:
+--
+
+Required properties:
+
+- compatible: Must be one of:
+  * ingenic,jz4740-watchdog
+  * ingenic,jz4780-watchdog
+- clocks: phandle to the WDT clock
+- clock-names: should be "wdt"
+
+
+OS Timer node:
+-
+
+Required 

[PATCH v10 04/27] clocksource: Add a new timer-ingenic driver

2019-03-02 Thread Paul Cercueil
This driver handles the TCU (Timer Counter Unit) present on the Ingenic
JZ47xx SoCs, and provides the kernel with a system timer, and optionally
with a clocksource and a sched_clock.

It also provides clocks and interrupt handling to client drivers.

Signed-off-by: Paul Cercueil 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v2: Use SPDX identifier for the license

 v3: - Move documentation to its own patch
 - Search the devicetree for PWM clients, and use all the TCU
   channels that won't be used for PWM

 v4: - Add documentation about why we search for PWM clients
 - Verify that the PWM clients are for the TCU PWM driver

 v5: Major overhaul. Too many changes to list. Consider it's a new
 patch.

 v6: - Add two API functions ingenic_tcu_request_channel and
   ingenic_tcu_release_channel. To be used by the PWM driver to
   request the use of a TCU channel. The driver will now dynamically
   move away the system timer or clocksource to a new TCU channel.
 - The system timer now defaults to channel 0, the clocksource now
   defaults to channel 1 and is no more optional. The
   ingenic,timer-channel and ingenic,clocksource-channel devicetree
   properties are now gone.
 - Fix round_rate / set_rate not calculating the prescale divider
   the same way. This caused problems when (parent_rate / div) would
   give a non-integer result. The behaviour is correct now.
 - The clocksource clock is turned off on suspend now.

 v7: Fix section mismatch by using builtin_platform_driver_probe()

 v8: - Removed ingenic_tcu_[request,release]_channel, and the mechanism
   to dynamically change the TCU channel of the system timer or
   the clocksource.
 - The driver's devicetree node can now have two more children
   nodes, that correspond to the system timer and clocksource.
   For these two, the driver will use the TCU timer that
   correspond to the memory resource supplied in their
   respective node.

 v9: - Removed support for clocksource / timer children devicetree
   nodes. Now, we use a property "ingenic,pwm-channels-mask" to
   know which PWM channels are reserved for PWM use and should
   not be used as OS timers.

v10: - Use CLK_SET_RATE_UNGATE instead of CLK_SET_RATE_GATE + manually
   un-gating the clock before changing rate. Same for re-parenting.
 - Unconditionally create the clocksource and sched_clock even if
   the SoC possesses a OS Timer. That gives the choice back to the
   user which clocksource should be selected.
 - Use subsys_initcall() instead of builtin_platform_driver_probe().
   The OS Timer driver calls builtin_platform_driver_probe, which
   requires the device to be created before that.
 - Cosmetic cleanups

 drivers/clocksource/Kconfig |  10 +
 drivers/clocksource/Makefile|   1 +
 drivers/clocksource/ingenic-timer.c | 903 
 drivers/clocksource/ingenic-timer.h |  15 +
 include/linux/mfd/ingenic-tcu.h |   2 +
 5 files changed, 931 insertions(+)
 create mode 100644 drivers/clocksource/ingenic-timer.c
 create mode 100644 drivers/clocksource/ingenic-timer.h

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index a9e26f6a81a1..d841934e126c 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -634,4 +634,14 @@ config GX6605S_TIMER
help
  This option enables support for gx6605s SOC's timer.
 
+config INGENIC_TIMER
+   bool "Clocksource/timer using the TCU in Ingenic JZ SoCs"
+   depends on MIPS || COMPILE_TEST
+   depends on COMMON_CLK
+   select TIMER_OF
+   select IRQ_DOMAIN
+   select REGMAP
+   help
+ Support for the timer/counter unit of the Ingenic JZ SoCs.
+
 endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index cdd210ff89ea..3eb8c544917f 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_ASM9260_TIMER)   += asm9260_timer.o
 obj-$(CONFIG_H8300_TMR8)   += h8300_timer8.o
 obj-$(CONFIG_H8300_TMR16)  += h8300_timer16.o
 obj-$(CONFIG_H8300_TPU)+= h8300_tpu.o
+obj-$(CONFIG_INGENIC_TIMER)+= ingenic-timer.o
 obj-$(CONFIG_CLKSRC_ST_LPC)+= clksrc_st_lpc.o
 obj-$(CONFIG_X86_NUMACHIP) += numachip.o
 obj-$(CONFIG_ATCPIT100_TIMER)  += timer-atcpit100.o
diff --git a/drivers/clocksource/ingenic-timer.c 
b/drivers/clocksource/ingenic-timer.c
new file mode 100644
index ..9529f6389ea4
--- /dev/null
+++ 

[5.2][PATCH v10 00/27] Ingenic TCU patchset

2019-03-02 Thread Paul Cercueil
Hi,

This is the Ingenic JZ47xx TCU patchset version 10.

Changes from v9:
- [04/27]: - The clocksource is now created unconditionally, even if the
 SoC has the better OS Timer. This gives the choice back to
 the user.
   - Simplify the set_rate/set_parent callbacks for the clocks
   - Probe platform driver at subsys_initcall() instead of
 using builtin_platform_driver_probe(), to ensure that the
 devices are populated before the children drivers (e.g. OS
 Timer driver) are probed.
- [05/27]: Fix incorrect mask used with regmap_update_bits, which caused
   the clocksource to be unstable on JZ4770 and JZ4780.
- [13/27]: Update commit message to reflect why "select REGMAP" was
   removed.
- [14/27]: Use a new algorithm that does not use clk_round_rate().
- [23/27] and [25/27]: Revert behaviour to what was in V8.

It has been tested and reported to be working, on the JZ4725B by me,
on the JZ4740 by Artur Rojek, and on the JZ4780 by Mathieu Malaterre.

I'd like this patchset to go through the MIPS tree, that will allow other
unrelated cleanups to follow.

Thanks,
- Paul



x86 VM Boot hang with latest linux-next

2019-03-02 Thread Alexander Duyck
So I have been seeing an issue with an intermittent boot hang on my
x86 KVM VM with the latest linux-next and have bisected it down to the
following commit:
1efa3bb79d3de8ca1b7f6770313a1fc0bebe25c7 is the first bad commit
commit 1efa3bb79d3de8ca1b7f6770313a1fc0bebe25c7
Author: Mike Snitzer 
Date:   Fri Feb 22 11:23:01 2019 -0500

dm: must allocate dm_noclone for stacked noclone devices

Otherwise various lvm2 testsuite tests fail because the lower layers of
the stacked noclone device aren't updated to allocate a new 'struct
dm_clone' that reflects the upper layer bio that was issued to it.

Fixes: 97a89458020b38 ("dm: improve noclone bio support")
Reported-by: Mikulas Patocka 
Signed-off-by: Mike Snitzer 

What I am seeing is in about 3 out of 4 boots the startup just hangs
at the filesystem check stage with the following message:
[  OK  ] Reached target Local File Systems (Pre).
 Starting File System Check on /dev/…127-ad57-426f-bb45-363950544c0c...
[**] (1 of 2) A start job is running for…n on device 252:2 (19s / no limit)

I did some googling and it looks like a similar issue has been
reported for s390. Based on the request for data there I have the
following info:
[root@localhost ~]# dmsetup ls --tree
fedora-swap (253:1)
 └─ (252:2)
fedora-root (253:0)
 └─ (252:2)

[root@localhost ~]# dmsetup table
fedora-swap: 0 4194304 linear 252:2 2048
fedora-root: 0 31457280 linear 252:2 4196352


[PATCH v10 01/27] dt-bindings: ingenic: Add DT bindings for TCU clocks

2019-03-02 Thread Paul Cercueil
This header provides clock numbers for the ingenic,tcu
DT binding.

Signed-off-by: Paul Cercueil 
Reviewed-by: Rob Herring 
Acked-by: Stephen Boyd 
Tested-by: Mathieu Malaterre 
Tested-by: Artur Rojek 
---

Notes:
 v2: Use SPDX identifier for the license

 v3: No change

 v4: No change

 v5: s/JZ47*_/TCU_/ and dropped *_CLK_LAST defines

 v6: No change

 v7: No change

 v8: No change

 v9: No change

 v10: No change

 include/dt-bindings/clock/ingenic,tcu.h | 20 
 1 file changed, 20 insertions(+)
 create mode 100644 include/dt-bindings/clock/ingenic,tcu.h

diff --git a/include/dt-bindings/clock/ingenic,tcu.h 
b/include/dt-bindings/clock/ingenic,tcu.h
new file mode 100644
index ..d569650a7945
--- /dev/null
+++ b/include/dt-bindings/clock/ingenic,tcu.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides clock numbers for the ingenic,tcu DT binding.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_INGENIC_TCU_H__
+#define __DT_BINDINGS_CLOCK_INGENIC_TCU_H__
+
+#define TCU_CLK_TIMER0 0
+#define TCU_CLK_TIMER1 1
+#define TCU_CLK_TIMER2 2
+#define TCU_CLK_TIMER3 3
+#define TCU_CLK_TIMER4 4
+#define TCU_CLK_TIMER5 5
+#define TCU_CLK_TIMER6 6
+#define TCU_CLK_TIMER7 7
+#define TCU_CLK_WDT8
+#define TCU_CLK_OST9
+
+#endif /* __DT_BINDINGS_CLOCK_INGENIC_TCU_H__ */
-- 
2.11.0



Re: [PATCH] net/bluetooth: Fix bound check in event handling

2019-03-02 Thread Tomas Bortoli
Hi Marcel,

On 3/2/19 5:46 PM, Marcel Holtmann wrote:
> Hi Tomas,
> 
>> hci_inquiry_result_with_rssi_evt() can perform out of bound reads
>> on skb->data as a bound check is missing.
>>
>> Signed-off-by: Tomas Bortoli 
>> Reported-by: syzbot+cec7a50c412a2c03f...@syzkaller.appspotmail.com
>> Reported-by: syzbot+660883c56e2fa65d4...@syzkaller.appspotmail.com
>> ---
>> Syzkaler reports:
>> https://syzkaller.appspot.com/bug?id=d708485af9edc3af35f3b4d554e827c6c8bf6b0f
>> https://syzkaller.appspot.com/bug?id=3acd1155d48a5acc5d76711568b04926945a6885
>>
>> net/bluetooth/hci_event.c | 4 
>> 1 file changed, 4 insertions(+)
>>
>> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
>> index ac2826ce162b..aa953d23bb72 100644
>> --- a/net/bluetooth/hci_event.c
>> +++ b/net/bluetooth/hci_event.c
>> @@ -3983,6 +3983,10 @@ static void hci_inquiry_result_with_rssi_evt(struct 
>> hci_dev *hdev,
>>  for (; num_rsp; num_rsp--, info++) {
>>  u32 flags;
>>
>> +if ((void *)(info + sizeof(info)) >
>> +   (void *)(skb->data + skb->len))
>> +break;
>> +
> 
> first of all, the loop exists twice here. If one is vulnerable, then the 
> second is a well. And second, can we not just do this inside the 
> for-condition check or a lot simpler than this void casting fun.
> 

1. The other for loop is not vulnerable because of the `if` that wraps
the loops. Unfortunately the condition only provides bound checking for
the "else" branch.

2. Sure. I was just getting some compiler warning like "calculated value
but unused" when putting the additional condition. By the way I am
curious to see how to avoid this void casting.

Regards,
Tomas





Re: [PATCH v4 2/7] dt-bindings: ti-lmu: Modify dt bindings for the LM3697

2019-03-02 Thread Pavel Machek
Hi!

> I just want to follow up here and let you know that I have not abandoned this.
> I am trying to rework and fix up the ti lmu binding as asked by Pavel.  Its 
> proving
> to be a bit of a challenge based on looking forward to what will be the 
> implementation.
> 
> I also did go offline and speak with Tony.  I have a Droid 4 so I can test 
> all of this on
> production hardware as well.
> 
> Updated patchset will take some time to get out.

Is there any progress here?

This is needed for display on Droid 4, so it is somehow
important... and Milo Kim's patches are pretty reasonable.

I still believe best way forward is to merge them, and let you submit
any improvements on top of them...

Best regards,
Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


signature.asc
Description: Digital signature


[PATCH 2/2] ARM: uaccess: use unified assembler language syntax

2019-03-02 Thread Stefan Agner
Convert the conditional infix to a postfix to make sure this inline
assembly is unified syntax. Since gcc assumes non-unified syntax
when emitting ARM instructions, make sure to define the syntax as
unified.

This allows to use LLVM's integrated assembler.

Additionally, for GCC ".syntax unified" for inline assembly.
When compiling non-Thumb2 GCC always emits a ".syntax divided"
at the beginning of the inline assembly which makes the
assembler fail. Since GCC 5 there is the -masm-syntax-unified
GCC option which make GCC assume unified syntax asm and hence
emits ".syntax unified" even in ARM mode. However, the option
is broken since GCC version 6 (see GCC PR88648 [1]). Work
around by adding ".syntax unified" as part of the inline
assembly.

[0] 
https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html#index-masm-syntax-unified
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88648

Signed-off-by: Stefan Agner 
---
I missed this instance in my previous commits and realized only
after running some randconfig.

 arch/arm/include/asm/uaccess.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 89a28680934b..18303bcc9990 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -113,10 +113,11 @@ static inline void __user *__uaccess_mask_range_ptr(const 
void __user *ptr,
unsigned long tmp;
 
asm volatile(
+   "   .syntax unified\n"
"   sub %1, %3, #1\n"
"   subs%1, %1, %0\n"
"   addhs   %1, %1, #1\n"
-   "   subhss  %1, %1, %2\n"
+   "   subshs  %1, %1, %2\n"
"   movlo   %0, #0\n"
: "+r" (safe_ptr), "=" (tmp)
: "r" (size), "r" (current_thread_info()->addr_limit)
-- 
2.20.1



[PATCH 1/2] ARM: add TUSERCOND() macro for conditional postfix

2019-03-02 Thread Stefan Agner
Unified assembly syntax requires conditionals to be postfixes.
TUSER() currently only takes a single argument which then gets
appended t (with translation) on every instruction.

This fixes a build error when using LLVM's integrated assembler:
  In file included from kernel/futex.c:72:
  ./arch/arm/include/asm/futex.h:116:3: error: invalid instruction, did you 
mean: strt?
  "2: " TUSER(streq) "%3, [%4]\n"
   ^
  :5:4: note: instantiated into assembly here
  2:  streqt  r2, [r4]
  ^~

Additionally, for GCC ".syntax unified" for inline assembly.
When compiling non-Thumb2 GCC always emits a ".syntax divided"
at the beginning of the inline assembly which makes the
assembler fail. Since GCC 5 there is the -masm-syntax-unified
GCC option which make GCC assume unified syntax asm and hence
emits ".syntax unified" even in ARM mode. However, the option
is broken since GCC version 6 (see GCC PR88648 [1]). Work
around by adding ".syntax unified" as part of the inline
assembly.

[0] 
https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html#index-masm-syntax-unified
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88648

Signed-off-by: Stefan Agner 
---
 arch/arm/include/asm/domain.h | 6 --
 arch/arm/include/asm/futex.h  | 3 ++-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h
index 99d9f630d6b6..1888c2d15da5 100644
--- a/arch/arm/include/asm/domain.h
+++ b/arch/arm/include/asm/domain.h
@@ -133,9 +133,11 @@ static inline void modify_domain(unsigned dom, unsigned 
type)  { }
  * instructions (inline assembly)
  */
 #ifdef CONFIG_CPU_USE_DOMAINS
-#define TUSER(instr)   #instr "t"
+#define TUSER(instr)   TUSERCOND(instr, )
+#define TUSERCOND(instr, cond) #instr "t" #cond
 #else
-#define TUSER(instr)   #instr
+#define TUSER(instr)   TUSERCOND(instr, )
+#define TUSERCOND(instr, cond) #instr #cond
 #endif
 
 #else /* __ASSEMBLY__ */
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index 0a46676b4245..83c391b597d4 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -110,10 +110,11 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user 
*uaddr,
preempt_disable();
__ua_flags = uaccess_save_and_enable();
__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
+   "   .syntax unified\n"
"1: " TUSER(ldr) "  %1, [%4]\n"
"   teq %1, %2\n"
"   it  eq  @ explicit IT needed for the 2b label\n"
-   "2: " TUSER(streq) "%3, [%4]\n"
+   "2: " TUSERCOND(str, eq) "  %3, [%4]\n"
__futex_atomic_ex_table("%5")
: "+r" (ret), "=" (val)
: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
-- 
2.20.1



[PATCH][next] RDMA/nes: remove redundant check on udata

2019-03-02 Thread Colin King
From: Colin Ian King 

The non-null check on udata is redundant as this check was performed
just a few statements earlier and the check is always true as udata
must be non-null at this point. Remove redundant the check on udata
and the redundant else part that can never be executed.

Detected by CoverityScan, CID#1477317 ("Logically dead code")

Signed-off-by: Colin Ian King 
---
 drivers/infiniband/hw/nes/nes_verbs.c | 73 +--
 1 file changed, 34 insertions(+), 39 deletions(-)

diff --git a/drivers/infiniband/hw/nes/nes_verbs.c 
b/drivers/infiniband/hw/nes/nes_verbs.c
index 828e4af3f951..526092d435df 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -1039,53 +1039,48 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
}
if (req.user_qp_buffer)
nesqp->nesuqp_addr = req.user_qp_buffer;
-   if (udata) {
-   nesqp->user_mode = 1;
-   if (virt_wqs) {
-   err = 1;
-   list_for_each_entry(nespbl, 
_ucontext->qp_reg_mem_list, list) {
-   if (nespbl->user_base 
== (unsigned long )req.user_wqe_buffers) {
-   
list_del(>list);
-   err = 0;
-   
nes_debug(NES_DBG_QP, "Found PBL for virtual QP. nespbl=%p. user_base=0x%lx\n",
- 
nespbl, nespbl->user_base);
-   break;
-   }
-   }
-   if (err) {
-   nes_debug(NES_DBG_QP, 
"Didn't Find PBL for virtual QP. address = %llx.\n",
- (long long 
unsigned int)req.user_wqe_buffers);
-   
nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
-   
kfree(nesqp->allocated_buffer);
-   return ERR_PTR(-EFAULT);
+
+   nesqp->user_mode = 1;
+   if (virt_wqs) {
+   err = 1;
+   list_for_each_entry(nespbl, 
_ucontext->qp_reg_mem_list, list) {
+   if (nespbl->user_base == 
(unsigned long )req.user_wqe_buffers) {
+   list_del(>list);
+   err = 0;
+   nes_debug(NES_DBG_QP, 
"Found PBL for virtual QP. nespbl=%p. user_base=0x%lx\n",
+ nespbl, 
nespbl->user_base);
+   break;
}
}
-
-   nesqp->mmap_sq_db_index =
-   
find_next_zero_bit(nes_ucontext->allocated_wqs,
-  
NES_MAX_USER_WQ_REGIONS, nes_ucontext->first_free_wq);
-   /* nes_debug(NES_DBG_QP, 
"find_first_zero_biton wqs returned %u\n",
-   nespd->mmap_db_index); 
*/
-   if (nesqp->mmap_sq_db_index >= 
NES_MAX_USER_WQ_REGIONS) {
-   nes_debug(NES_DBG_QP,
- "db index > max user 
regions, failing create QP\n");
+   if (err) {
+   nes_debug(NES_DBG_QP, "Didn't 
Find PBL for virtual QP. address = %llx.\n",
+ (long long unsigned 
int)req.user_wqe_buffers);
nes_free_resource(nesadapter, 
nesadapter->allocated_qps, qp_num);
-   if (virt_wqs) {
-   
pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,
-   
nespbl->pbl_pbase);
- 

Re: [PATCH] mm: compaction: show gfp flag names in try_to_compact_pages tracepoint

2019-03-02 Thread kbuild test robot
Hi Yafang,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on tip/perf/core]
[also build test WARNING on v5.0-rc8 next-20190301]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Yafang-Shao/mm-compaction-show-gfp-flag-names-in-try_to_compact_pages-tracepoint/20190302-212241
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'

All warnings (new ones prefixed by >>):

>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t
>> include/trace/events/compaction.h:171:1: sparse: warning: cast from 
>> restricted gfp_t

sparse warnings: (new ones prefixed by >>)

   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:171:1: sparse: warning: cast from 
restricted gfp_t
   include/trace/events/compaction.h:1

[PATCH] mm/hotplug: don't reset pagetype flags for offline

2019-03-02 Thread Qian Cai
The commit f1dd2cd13c4b ("mm, memory_hotplug: do not associate hotadded
memory to zones until online") introduced move_pfn_range_to_zone() which
calls memmap_init_zone() during onlining a memory block.
memmap_init_zone() will reset pagetype flags and makes migrate type to
be MOVABLE.

However, in __offline_pages(), it also call undo_isolate_page_range()
after offline_isolated_pages() to do the same thing. Due to
the commit 2ce13640b3f4 ("mm: __first_valid_page skip over offline
pages") changed __first_valid_page() to skip offline pages,
undo_isolate_page_range() here just waste CPU cycles looping around the
offlining PFN range while doing nothing, because __first_valid_page()
will return NULL as offline_isolated_pages() has already marked all
memory sections within the pfn range as offline via
offline_mem_sections().

Since undo_isolate_page_range() is rather unnecessary here, just remove
it. Also, fix an incorrect comment along the way.

Signed-off-by: Qian Cai 
---
 mm/memory_hotplug.c | 2 --
 mm/sparse.c | 2 +-
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 736e107e2197..e793f6514fb2 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1643,8 +1643,6 @@ static int __ref __offline_pages(unsigned long start_pfn,
/* Ok, all of our target is isolated.
   We cannot do rollback at this point. */
offline_isolated_pages(start_pfn, end_pfn);
-   /* reset pagetype flags and makes migrate type to be MOVABLE */
-   undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
/* removal success */
adjust_managed_page_count(pfn_to_page(start_pfn), -offlined_pages);
zone->present_pages -= offlined_pages;
diff --git a/mm/sparse.c b/mm/sparse.c
index 77a0554fa5bd..b3771f35a0ed 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -556,7 +556,7 @@ void online_mem_sections(unsigned long start_pfn, unsigned 
long end_pfn)
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-/* Mark all memory sections within the pfn range as online */
+/* Mark all memory sections within the pfn range as offline */
 void offline_mem_sections(unsigned long start_pfn, unsigned long end_pfn)
 {
unsigned long pfn;
-- 
2.17.2 (Apple Git-113)



[PATCH] ARM: dts: imx7s-warp: PMIC swbst boot-on/always-on

2019-03-02 Thread Pierre-Jean Texier
PMIC swbst regulator is used for the MikroBUS socket (pin +5V).

We have to set the regulator to "boot-on" and "always-on"
to output a voltage of 5V on this socket.

Signed-off-by: Pierre-Jean Texier 
---
 arch/arm/boot/dts/imx7s-warp.dts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/imx7s-warp.dts b/arch/arm/boot/dts/imx7s-warp.dts
index 23431fa..b1e9562 100644
--- a/arch/arm/boot/dts/imx7s-warp.dts
+++ b/arch/arm/boot/dts/imx7s-warp.dts
@@ -121,6 +121,8 @@
swbst_reg: swbst {
regulator-min-microvolt = <500>;
regulator-max-microvolt = <515>;
+   regulator-boot-on;
+   regulator-always-on;
};
 
snvs_reg: vsnvs {
-- 
2.7.4



Re: [PATCH 05/12] percpu: relegate chunks unusable when failing small allocations

2019-03-02 Thread Dennis Zhou
On Sat, Mar 02, 2019 at 01:55:54PM +, Peng Fan wrote:
> Hi Dennis,
> 
> > -Original Message-
> > From: owner-linux...@kvack.org [mailto:owner-linux...@kvack.org] On
> > Behalf Of Dennis Zhou
> > Sent: 2019年2月28日 10:19
> > To: Dennis Zhou ; Tejun Heo ; Christoph
> > Lameter 
> > Cc: Vlad Buslov ; kernel-t...@fb.com;
> > linux...@kvack.org; linux-kernel@vger.kernel.org
> > Subject: [PATCH 05/12] percpu: relegate chunks unusable when failing small
> > allocations
> > 
> > In certain cases, requestors of percpu memory may want specific alignments.
> > However, it is possible to end up in situations where the contig_hint 
> > matches,
> > but the alignment does not. This causes excess scanning of chunks that will 
> > fail.
> > To prevent this, if a small allocation fails (< 32B), the chunk is moved to 
> > the
> > empty list. Once an allocation is freed from that chunk, it is placed back 
> > into
> > rotation.
> > 
> > Signed-off-by: Dennis Zhou 
> > ---
> >  mm/percpu.c | 35 ++-
> >  1 file changed, 26 insertions(+), 9 deletions(-)
> > 
> > diff --git a/mm/percpu.c b/mm/percpu.c
> > index c996bcffbb2a..3d7deece9556 100644
> > --- a/mm/percpu.c
> > +++ b/mm/percpu.c
> > @@ -94,6 +94,8 @@
> > 
> >  /* the slots are sorted by free bytes left, 1-31 bytes share the same slot 
> > */
> >  #define PCPU_SLOT_BASE_SHIFT   5
> > +/* chunks in slots below this are subject to being sidelined on failed 
> > alloc */
> > +#define PCPU_SLOT_FAIL_THRESHOLD   3
> > 
> >  #define PCPU_EMPTY_POP_PAGES_LOW   2
> >  #define PCPU_EMPTY_POP_PAGES_HIGH  4
> > @@ -488,6 +490,22 @@ static void pcpu_mem_free(void *ptr)
> > kvfree(ptr);
> >  }
> > 
> > +static void __pcpu_chunk_move(struct pcpu_chunk *chunk, int slot,
> > + bool move_front)
> > +{
> > +   if (chunk != pcpu_reserved_chunk) {
> > +   if (move_front)
> > +   list_move(>list, _slot[slot]);
> > +   else
> > +   list_move_tail(>list, _slot[slot]);
> > +   }
> > +}
> > +
> > +static void pcpu_chunk_move(struct pcpu_chunk *chunk, int slot) {
> > +   __pcpu_chunk_move(chunk, slot, true);
> > +}
> > +
> >  /**
> >   * pcpu_chunk_relocate - put chunk in the appropriate chunk slot
> >   * @chunk: chunk of interest
> > @@ -505,12 +523,8 @@ static void pcpu_chunk_relocate(struct pcpu_chunk
> > *chunk, int oslot)  {
> > int nslot = pcpu_chunk_slot(chunk);
> > 
> > -   if (chunk != pcpu_reserved_chunk && oslot != nslot) {
> > -   if (oslot < nslot)
> > -   list_move(>list, _slot[nslot]);
> > -   else
> > -   list_move_tail(>list, _slot[nslot]);
> > -   }
> > +   if (oslot != nslot)
> > +   __pcpu_chunk_move(chunk, nslot, oslot < nslot);
> >  }
> > 
> >  /**
> > @@ -1381,7 +1395,7 @@ static void __percpu *pcpu_alloc(size_t size, size_t
> > align, bool reserved,
> > bool is_atomic = (gfp & GFP_KERNEL) != GFP_KERNEL;
> > bool do_warn = !(gfp & __GFP_NOWARN);
> > static int warn_limit = 10;
> > -   struct pcpu_chunk *chunk;
> > +   struct pcpu_chunk *chunk, *next;
> > const char *err;
> > int slot, off, cpu, ret;
> > unsigned long flags;
> > @@ -1443,11 +1457,14 @@ static void __percpu *pcpu_alloc(size_t size,
> > size_t align, bool reserved,
> >  restart:
> > /* search through normal chunks */
> > for (slot = pcpu_size_to_slot(size); slot < pcpu_nr_slots; slot++) {
> > -   list_for_each_entry(chunk, _slot[slot], list) {
> > +   list_for_each_entry_safe(chunk, next, _slot[slot], list) {
> > off = pcpu_find_block_fit(chunk, bits, bit_align,
> >   is_atomic);
> > -   if (off < 0)
> > +   if (off < 0) {
> > +   if (slot < PCPU_SLOT_FAIL_THRESHOLD)
> > +   pcpu_chunk_move(chunk, 0);
> > continue;
> > +   }
> > 
> > off = pcpu_alloc_area(chunk, bits, bit_align, off);
> > if (off >= 0)
> 
> For the code: Reviewed-by: Peng Fan 
> 
> But I did not understand well why choose 32B? If there are
> more information, better put in commit log.
> 

There isn't I just picked a small allocation size.

Thanks,
Dennis


Re: [PATCH 04/12] percpu: manage chunks based on contig_bits instead of free_bytes

2019-03-02 Thread Dennis Zhou
On Sat, Mar 02, 2019 at 01:48:20PM +, Peng Fan wrote:
> 
> 
> > -Original Message-
> > From: owner-linux...@kvack.org [mailto:owner-linux...@kvack.org] On
> > Behalf Of Dennis Zhou
> > Sent: 2019年2月28日 10:19
> > To: Dennis Zhou ; Tejun Heo ; Christoph
> > Lameter 
> > Cc: Vlad Buslov ; kernel-t...@fb.com;
> > linux...@kvack.org; linux-kernel@vger.kernel.org
> > Subject: [PATCH 04/12] percpu: manage chunks based on contig_bits instead
> > of free_bytes
> > 
> > When a chunk becomes fragmented, it can end up having a large number of
> > small allocation areas free. The free_bytes sorting of chunks leads to
> > unnecessary checking of chunks that cannot satisfy the allocation.
> > Switch to contig_bits sorting to prevent scanning chunks that may not be 
> > able
> > to service the allocation request.
> > 
> > Signed-off-by: Dennis Zhou 
> > ---
> >  mm/percpu.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/mm/percpu.c b/mm/percpu.c
> > index b40112b2fc59..c996bcffbb2a 100644
> > --- a/mm/percpu.c
> > +++ b/mm/percpu.c
> > @@ -234,7 +234,7 @@ static int pcpu_chunk_slot(const struct pcpu_chunk
> > *chunk)
> > if (chunk->free_bytes < PCPU_MIN_ALLOC_SIZE || chunk->contig_bits
> > == 0)
> > return 0;
> > 
> > -   return pcpu_size_to_slot(chunk->free_bytes);
> > +   return pcpu_size_to_slot(chunk->contig_bits * PCPU_MIN_ALLOC_SIZE);
> >  }
> > 
> >  /* set the pointer to a chunk in a page struct */
> 
> Reviewed-by: Peng Fan 
> 
> Not relevant to this patch, another optimization to percpu might be good
> to use per chunk spin_lock, not gobal pcpu_lock.
> 

Percpu memory itself is expensive and for the most part shouldn't be
part of the critical path. Ideally, we don't have multiple chunks being
allocated simultaneously because once an allocation is given out, the
chunk is pinned until all allocations are freed.

Thanks,
Dennis


[GIT PULL] ARM: SoC fixes for v5.0

2019-03-02 Thread Arnd Bergmann
The following changes since commit 5908e6b738e3357af42c10e1183753c70a0117a9:

  Linux 5.0-rc8 (2019-02-24 16:46:45 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git tags/armsoc-fixes

for you to fetch changes up to 6089e65618dca3fc0e7ccd7a6315de62ebf893a4:

  Merge tag 'qcom-fixes-for-5.0-rc8' of
git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux into
arm/fixes (2019-03-01 15:08:16 +0100)


ARM: SoC fixes for v5.0

One more set of simple ARM platform fixes:

 - A boot regression on qualcomm msm8998
 - Gemini display controllers got turned off by accident
 - incorrect reference counting in optee


Andy Gross (1):
  Merge tag 'qcom-fixes-for-5.0-rc3' into fixes-for-5.0-rc8

Arnd Bergmann (2):
  Merge tag 'tee-fix-for-v5.0' of
https://git.linaro.org/people/jens.wiklander/linux-tee into arm/fixes
  Merge tag 'qcom-fixes-for-5.0-rc8' of
git://git.kernel.org/.../agross/linux into arm/fixes

Julia Lawall (1):
  tee: optee: add missing of_node_put after of_device_is_available

Linus Walleij (1):
  ARM: dts: gemini: Re-enable display controller

Marc Gonzalez (1):
  arm64: dts: qcom: msm8998: Extend TZ reserved memory area

 arch/arm/boot/dts/gemini-dlink-dir-685.dts | 2 +-
 arch/arm64/boot/dts/qcom/msm8998.dtsi  | 2 +-
 drivers/tee/optee/core.c   | 4 +++-
 3 files changed, 5 insertions(+), 3 deletions(-)


Re: [PATCH 03/12] percpu: introduce helper to determine if two regions overlap

2019-03-02 Thread Dennis Zhou
On Sat, Mar 02, 2019 at 01:37:37PM +, Peng Fan wrote:
> Hi Dennis,
> 
> > -Original Message-
> > From: owner-linux...@kvack.org [mailto:owner-linux...@kvack.org] On
> > Behalf Of Dennis Zhou
> > Sent: 2019年2月28日 10:19
> > To: Dennis Zhou ; Tejun Heo ; Christoph
> > Lameter 
> > Cc: Vlad Buslov ; kernel-t...@fb.com;
> > linux...@kvack.org; linux-kernel@vger.kernel.org
> > Subject: [PATCH 03/12] percpu: introduce helper to determine if two regions
> > overlap
> > 
> > While block hints were always accurate, it's possible when spanning across
> > blocks that we miss updating the chunk's contig_hint. Rather than rely on
> > correctness of the boundaries of hints, do a full overlap comparison.
> > 
> > Signed-off-by: Dennis Zhou 
> > ---
> >  mm/percpu.c | 31 +++
> >  1 file changed, 27 insertions(+), 4 deletions(-)
> > 
> > diff --git a/mm/percpu.c b/mm/percpu.c
> > index 69ca51d238b5..b40112b2fc59 100644
> > --- a/mm/percpu.c
> > +++ b/mm/percpu.c
> > @@ -546,6 +546,24 @@ static inline int pcpu_cnt_pop_pages(struct
> > pcpu_chunk *chunk, int bit_off,
> >bitmap_weight(chunk->populated, page_start);  }
> > 
> > +/*
> > + * pcpu_region_overlap - determines if two regions overlap
> > + * @a: start of first region, inclusive
> > + * @b: end of first region, exclusive
> > + * @x: start of second region, inclusive
> > + * @y: end of second region, exclusive
> > + *
> > + * This is used to determine if the hint region [a, b) overlaps with
> > +the
> > + * allocated region [x, y).
> > + */
> > +static inline bool pcpu_region_overlap(int a, int b, int x, int y) {
> > +   if ((x >= a && x < b) || (y > a && y <= b) ||
> > +   (x <= a && y >= b))
> 
> I think this could be simplified:
>  (a < y) && (x < b) could be used to do overlap check.
> 

I'll change it to be the negative.

Thanks,
Dennis

> 
> > +   return true;
> > +   return false;
> > +}
> > +
> >  /**
> >   * pcpu_chunk_update - updates the chunk metadata given a free area
> >   * @chunk: chunk of interest
> > @@ -710,8 +728,11 @@ static void pcpu_block_update_hint_alloc(struct
> > pcpu_chunk *chunk, int bit_off,
> > PCPU_BITMAP_BLOCK_BITS,
> > s_off + bits);
> > 
> > -   if (s_off >= s_block->contig_hint_start &&
> > -   s_off < s_block->contig_hint_start + s_block->contig_hint) {
> > +   if (pcpu_region_overlap(s_block->contig_hint_start,
> > +   s_block->contig_hint_start +
> > +   s_block->contig_hint,
> > +   s_off,
> > +   s_off + bits)) {
> > /* block contig hint is broken - scan to fix it */
> > pcpu_block_refresh_hint(chunk, s_index);
> > } else {
> > @@ -764,8 +785,10 @@ static void pcpu_block_update_hint_alloc(struct
> > pcpu_chunk *chunk, int bit_off,
> >  * contig hint is broken.  Otherwise, it means a smaller space
> >  * was used and therefore the chunk contig hint is still correct.
> >  */
> > -   if (bit_off >= chunk->contig_bits_start  &&
> > -   bit_off < chunk->contig_bits_start + chunk->contig_bits)
> > +   if (pcpu_region_overlap(chunk->contig_bits_start,
> > +   chunk->contig_bits_start + chunk->contig_bits,
> > +   bit_off,
> > +   bit_off + bits))
> > pcpu_chunk_refresh_hint(chunk);
> >  }
> > 
> > --
> > 2.17.1
> 


[PATCH][next] HID: uclogic: remove redudant duplicated null check on ver_ptr

2019-03-02 Thread Colin King
From: Colin Ian King 

Currently ver_ptr is being null checked twice, once before calling
usb_string and once afterwards.  The second null check is redundant
and can be removed, remove it.

Detected by CoverityScan, CID#1477308 ("Logically dead code")

Signed-off-by: Colin Ian King 
---
 drivers/hid/hid-uclogic-params.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c
index 7710d9f957da..0187c9f8fc22 100644
--- a/drivers/hid/hid-uclogic-params.c
+++ b/drivers/hid/hid-uclogic-params.c
@@ -735,10 +735,6 @@ static int uclogic_params_huion_init(struct uclogic_params 
*params,
goto cleanup;
}
rc = usb_string(udev, 201, ver_ptr, ver_len);
-   if (ver_ptr == NULL) {
-   rc = -ENOMEM;
-   goto cleanup;
-   }
if (rc == -EPIPE) {
*ver_ptr = '\0';
} else if (rc < 0) {
-- 
2.20.1



Re: [PATCH 02/12] percpu: do not search past bitmap when allocating an area

2019-03-02 Thread Dennis Zhou
On Sat, Mar 02, 2019 at 01:32:04PM +, Peng Fan wrote:
> Hi Dennis,
> 
> > -Original Message-
> > From: owner-linux...@kvack.org [mailto:owner-linux...@kvack.org] On
> > Behalf Of Dennis Zhou
> > Sent: 2019年2月28日 10:18
> > To: Dennis Zhou ; Tejun Heo ; Christoph
> > Lameter 
> > Cc: Vlad Buslov ; kernel-t...@fb.com;
> > linux...@kvack.org; linux-kernel@vger.kernel.org
> > Subject: [PATCH 02/12] percpu: do not search past bitmap when allocating an
> > area
> > 
> > pcpu_find_block_fit() guarantees that a fit is found within
> > PCPU_BITMAP_BLOCK_BITS. Iteration is used to determine the first fit as it
> > compares against the block's contig_hint. This can lead to incorrectly 
> > scanning
> > past the end of the bitmap. The behavior was okay given the check after for
> > bit_off >= end and the correctness of the hints from pcpu_find_block_fit().
> > 
> > This patch fixes this by bounding the end offset by the number of bits in a
> > chunk.
> > 
> > Signed-off-by: Dennis Zhou 
> > ---
> >  mm/percpu.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> > 
> > diff --git a/mm/percpu.c b/mm/percpu.c
> > index 53bd79a617b1..69ca51d238b5 100644
> > --- a/mm/percpu.c
> > +++ b/mm/percpu.c
> > @@ -988,7 +988,8 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk,
> > int alloc_bits,
> > /*
> >  * Search to find a fit.
> >  */
> > -   end = start + alloc_bits + PCPU_BITMAP_BLOCK_BITS;
> > +   end = min_t(int, start + alloc_bits + PCPU_BITMAP_BLOCK_BITS,
> > +   pcpu_chunk_map_bits(chunk));
> > bit_off = bitmap_find_next_zero_area(chunk->alloc_map, end, start,
> >  alloc_bits, align_mask);
> > if (bit_off >= end)
> > --
> 
> From pcpu_alloc_area itself, I think this is correct to avoid 
> bitmap_find_next_zero_area
> scan past the boundaries of alloc_map, so
> 
> Reviewed-by: Peng Fan 
> 
> There are a few points I did not understand well,
> Per understanding pcpu_find_block_fit is to find the first bit off in a chunk 
> which could satisfy
> the bits allocation, so bits might be larger than PCPU_BITMAP_BLOCK_BITS. And 
> if
> pcpu_find_block_fit returns a good off, it means there is a area in the chunk 
> could satisfy
> the bits allocation, then the following pcpu_alloc_area will not scan past 
> the boundaries of
> alloc_map, right?
> 

pcpu_find_block_fit() finds the chunk offset corresponding to the block
that will be able to fit the chunk. Allocations are done by first fit,
so scanning begins from the first_free of a block. Because the hints are
always accurate, you never fail to find a fit in pcpu_alloc_area() if
pcpu_find_block_fit() gives you an offset. This means you never scan
past the end anyway.

Thanks,
Dennis


[PATCH][drm-next] drm/amdgpu: fix missing assignment of error return code to variable ret

2019-03-02 Thread Colin King
From: Colin Ian King 

An earlier commit replaced ttm_bo_wait with amdgpu_bo_sync_wait and
removed the error return assignment to variable ret. Fix this by adding
the assignment back. Also break line to clean up checkpatch overly
long line warning.

Detected by CoverityScan, CID#1477327 ("Logically dead code")

Fixes: c60cd590cb7d ("drm/amdgpu: Replace ttm_bo_wait with amdgpu_bo_sync_wait")
Signed-off-by: Colin Ian King 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 1921dec3df7a..92993baac91a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -906,7 +906,8 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void 
**process_info,
pr_err("validate_pt_pd_bos() failed\n");
goto validate_pd_fail;
}
-   amdgpu_bo_sync_wait(vm->root.base.bo, AMDGPU_FENCE_OWNER_KFD, false);
+   ret = amdgpu_bo_sync_wait(vm->root.base.bo,
+ AMDGPU_FENCE_OWNER_KFD, false);
if (ret)
goto wait_pd_fail;
amdgpu_bo_fence(vm->root.base.bo,
-- 
2.20.1



Re: [PATCH 1/2] gcc-plugins: structleak: Generalize to all variable types

2019-03-02 Thread Arnd Bergmann
On Sat, Mar 2, 2019 at 4:43 PM Kees Cook  wrote:
>
> On Sat, Mar 2, 2019 at 1:05 AM Ard Biesheuvel  
> wrote:
> >
> > On Thu, 28 Feb 2019 at 21:27, Arnd Bergmann  wrote:
> > > I get similar results with asan-stack=1 but without your plugin, only
> > > the combination of the two has the explosive stack size growth.
>
> I can look more closely, but I'm not sure it's entirely worth it:
> these two may not make sense to build at the same time. (e.g. the
> use-after-scope config was disallowed to work with this plugin.)

Well, I still want to make sure all 'randconfig' builds complete without
warnings, and without having to turn off the otherwise useful
stack overflow warnings.

One thing I noticed is that your patch removes the 'depends on
!COMPILE_TEST' check for GCC_PLUGIN_STRUCTLEAK_BYREF_ALL,
so if we add that back in, it would at least take care of the
allmodconfig and randconfig cases.

> > > I can help analyze this further, but maybe you can have a look first,
> > > there might be something obvious when you read the input to the
> > > plugin.
> > >
> >
> > Is this before or after use-after-scope was disabled entirely?
>
> I was wondering the same thing, but I assumed it didn't matter: it
> wasn't possible to use both before it was entirely disabled.

Right. I already had the use-after-scope stuff disabled for
build testing, using the same 'depends on !COMPILE_TEST'
check, so one more reason it did not make a difference.

  Arnd


Re: [PATCH v4 1/2] Provide in-kernel headers for making it easy to extend the kernel

2019-03-02 Thread kbuild test robot
Hi Joel,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v5.0-rc8]
[cannot apply to next-20190301]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Joel-Fernandes-Google/Provide-in-kernel-headers-for-making-it-easy-to-extend-the-kernel/20190303-014850
config: sh-allmodconfig (attached as .config)
compiler: sh4-linux-gnu-gcc (Debian 8.2.0-11) 8.2.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=8.2.0 make.cross ARCH=sh 

All errors (new ones prefixed by >>):

>> find: 'arch/sh/kernel/module.lds': No such file or directory
>> find: 'arch/sh/kernel/module.lds': No such file or directory

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH] isdn: mISDN: Fix potential NULL pointer dereference of kzalloc

2019-03-02 Thread Kangjie Lu



On 3/2/19 3:26 PM, Gustavo A. R. Silva wrote:


On 3/2/19 3:20 PM, Aditya Pakki wrote:

Allocating memory via kzalloc for phi may fail and causes a
NULL pointer dereference. This patch avoids such a scenario.


Was this detected by Coccinelle?



It was detected by an LLVM-based static analyzer we recently developed.




If so, please mention it in the commit log.

Thanks
--
Gustavo


Signed-off-by: Aditya Pakki 
---
  drivers/isdn/hardware/mISDN/hfcsusb.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c 
b/drivers/isdn/hardware/mISDN/hfcsusb.c
index 124ff530da82..26e3182bbca8 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -263,6 +263,9 @@ hfcsusb_ph_info(struct hfcsusb *hw)
int i;
  
  	phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC);

+   if (!phi)
+   return;
+
phi->dch.ch.protocol = hw->protocol;
phi->dch.ch.Flags = dch->Flags;
phi->dch.state = dch->state;



Re: [PATCH] staging: speakup: i18n: fix spelling mistake "phoneticly" -> "phonetically"

2019-03-02 Thread Christopher Brannon
Samuel Thibault writes:
> Hello,
>
> Colin King, le mer. 28 nov. 2018 16:12:32 +, a ecrit:
> > From: Colin Ian King 
> > 
> > There is a spelling mistake in array speakup_default_msgs at index
> > MSG_FUNCNAME_SPELL_WORD_PHONETICALLY, fix this.
> > 
> > Signed-off-by: Colin Ian King 
>
> We never got any feedback from the speakup mailing list, I guess fixing
> the typo is fine.

I'm sure there were deliberate mis-spellings in Speakup error
messages to accomodate pronunciation issues with older synths, but I
have no idea whether this is one of them.  It's probably fine either way.

-- Chris


[mt76/mt7603/mac] Question about missing variable assignment

2019-03-02 Thread Gustavo A. R. Silva
Hi all,

The following piece of code in drivers/net/wireless/mediatek/mt76/mt7603/mac.c
is missing a variable assignment before line 1058.  Notice that there
is a potential execution path in which variable *i* is compared against
magic number 15 at line 1075 without being initialized previously
(this was reported by Coverity):

1055 out:
1056 final_rate_flags = info->status.rates[final_idx].flags;
1057 
1058 switch (FIELD_GET(MT_TX_RATE_MODE, final_rate)) {
1059 case MT_PHY_TYPE_CCK:
1060 cck = true;
1061 /* fall through */
1062 case MT_PHY_TYPE_OFDM:
1063 if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ)
1064 sband = >mt76.sband_5g.sband;
1065 else
1066 sband = >mt76.sband_2g.sband;
1067 final_rate &= GENMASK(5, 0);
1068 final_rate = mt7603_get_rate(dev, sband, final_rate, cck);
1069 final_rate_flags = 0;
1070 break;
1071 case MT_PHY_TYPE_HT_GF:
1072 case MT_PHY_TYPE_HT:
1073 final_rate_flags |= IEEE80211_TX_RC_MCS;
1074 final_rate &= GENMASK(5, 0);
1075 if (i > 15)
1076 return false;
1077 break;
1078 default:
1079 return false;
1080 }

My guess is that such missing assignment should be something similar
to the one at line 566:

i = FIELD_GET(MT_RXV1_TX_RATE, rxdg0);

but I'm not sure what the proper arguments for macro FIELD_GET should
be.

This code was introduced by commit c8846e1015022d2531ac4c895783e400b3e5babe

What do you think?

Thanks
--
Gustavo



[PATCH] mfd: sm501: Fix potential NULL pointer dereference

2019-03-02 Thread Aditya Pakki
lookup variable on failure of allocating memory via devm_kzalloc
can cause a NULL pointer dereference. This patch avoids such a scenario.

Signed-off-by: Aditya Pakki 
---
 drivers/mfd/sm501.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index a530972c5a7e..e0173bf4b0dc 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1145,6 +1145,9 @@ static int sm501_register_gpio_i2c_instance(struct 
sm501_devdata *sm,
lookup = devm_kzalloc(>dev,
  sizeof(*lookup) + 3 * sizeof(struct gpiod_lookup),
  GFP_KERNEL);
+   if (!lookup)
+   return -ENOMEM;
+
lookup->dev_id = "i2c-gpio";
if (iic->pin_sda < 32)
lookup->table[0].chip_label = "SM501-LOW";
-- 
2.17.1



Re: [PATCH] isdn: mISDN: Fix potential NULL pointer dereference of kzalloc

2019-03-02 Thread Gustavo A. R. Silva



On 3/2/19 3:20 PM, Aditya Pakki wrote:
> Allocating memory via kzalloc for phi may fail and causes a
> NULL pointer dereference. This patch avoids such a scenario.
> 

Was this detected by Coccinelle?

If so, please mention it in the commit log.

Thanks
--
Gustavo

> Signed-off-by: Aditya Pakki 
> ---
>  drivers/isdn/hardware/mISDN/hfcsusb.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c 
> b/drivers/isdn/hardware/mISDN/hfcsusb.c
> index 124ff530da82..26e3182bbca8 100644
> --- a/drivers/isdn/hardware/mISDN/hfcsusb.c
> +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
> @@ -263,6 +263,9 @@ hfcsusb_ph_info(struct hfcsusb *hw)
>   int i;
>  
>   phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC);
> + if (!phi)
> + return;
> +
>   phi->dch.ch.protocol = hw->protocol;
>   phi->dch.ch.Flags = dch->Flags;
>   phi->dch.state = dch->state;
> 


Re: [PATCH v2 6/8] clk: Allow parents to be specified without string names

2019-03-02 Thread Jeffrey Hugo

On 2/26/2019 3:34 PM, Stephen Boyd wrote:

The common clk framework is lacking in ability to describe the clk
topology without specifying strings for every possible parent-child
link. There are a few drawbacks to the current approach:

  1) String comparisons are used for everything, including describing
  topologies that are 'local' to a single clock controller.

  2) clk providers (e.g. i2c clk drivers) need to create globally unique
  clk names to avoid collisions in the clk namespace, leading to awkward
  name generation code in various clk drivers.

  3) DT bindings may not fully describe the clk topology and linkages
  between clk controllers because drivers can easily rely on globally unique
  strings to describe connections between clks.

This leads to confusing DT bindings, complicated clk name generation
code, and inefficient string comparisons during clk registration just so
that the clk framework can detect the topology of the clk tree.
Furthermore, some drivers call clk_get() and then __clk_get_name() to
extract the globally unique clk name just so they can specify the parent
of the clk they're registering. We have of_clk_parent_fill() but that
mostly only works for single clks registered from a DT node, which isn't
the norm. Let's simplify this all by introducing two new ways of
specifying clk parents.

The first method is an array of pointers to clk_hw structures
corresponding to the parents at that index. This works for clks that are
registered when we have access to all the clk_hw pointers for the
parents.

The second method is a mix of clk_hw pointers and strings of local and
global parent clk names. If the .name member of the map is set we'll
look for that clk by performing a DT based lookup of the device the clk
is registered with and the .name specified in the map. If that fails,
we'll fallback to the .fallback member and perform a global clk name
lookup like we've always done before.

Using either one of these new methods is entirely optional. Existing
drivers will continue to work, and they can migrate to this new approach
as they see fit. Eventually, we'll want to get rid of the 'parent_names'
array in struct clk_init_data and use one of these new methods instead.



I don't know exactly what regressed from V1, but this change breaks all 
clock drivers as far as I can tell.  All clocks from old and new (ie 
8998 mmcc rebased onto this) drivers end up as orphans.


Is there some data I can provide to help you figure out the issue?


Cc: Miquel Raynal 
Cc: Jerome Brunet 
Cc: Russell King 
Cc: Michael Turquette 
Cc: Jeffrey Hugo 
Cc: Chen-Yu Tsai 
Signed-off-by: Stephen Boyd 
---
  drivers/clk/clk.c| 260 ++-
  include/linux/clk-provider.h |  19 +++
  2 files changed, 217 insertions(+), 62 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 937b8d092d17..3d01e8c56400 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -39,6 +39,13 @@ static LIST_HEAD(clk_notifier_list);
  
  /***private data structures***/
  
+struct clk_parent_map {

+   const struct clk_hw *hw;
+   struct clk_core *core;
+   const char  *fw_name;
+   const char  *name;
+};
+
  struct clk_core {
const char  *name;
const struct clk_ops*ops;
@@ -46,8 +53,7 @@ struct clk_core {
struct module   *owner;
struct device   *dev;
struct clk_core *parent;
-   const char  **parent_names;
-   struct clk_core **parents;
+   struct clk_parent_map   *parents;
u8  num_parents;
u8  new_parent_index;
unsigned long   rate;
@@ -316,17 +322,92 @@ static struct clk_core *clk_core_lookup(const char *name)
return NULL;
  }
  
+/**

+ * clk_core_get - Find the parent of a clk using a clock specifier in DT
+ * @core: clk to find parent of
+ * @name: name to search for in 'clock-names' of device providing clk
+ *
+ * This is the preferred method for clk providers to find the parent of a
+ * clk when that parent is external to the clk controller. The parent_names
+ * array is indexed and treated as a local name matching a string in the device
+ * node's 'clock-names' property. This allows clk providers to use their own
+ * namespace instead of looking for a globally unique parent string.
+ *
+ * For example the following DT snippet would allow a clock registered by the
+ * clock-controller@c001 that has a clk_init_data::parent_data array
+ * with 'xtal' in the 'name' member to find the clock provided by the
+ * clock-controller@f00abcd without needing to get the globally unique name of
+ * the xtal clk.
+ *
+ * parent: clock-controller@f00abcd {
+ * reg = <0xf00abcd 0xabcd>;
+ * #clock-cells = <0>;
+ * };
+ *
+ * clock-controller@c001 {
+ * reg = <0xc001 0xf00d>;
+ * 

Re: [PATCH] x86: uv: Fix potential NULL pointer dereference of kmalloc_node

2019-03-02 Thread Gustavo A. R. Silva
Hi Aditya,

On 3/2/19 3:09 PM, Aditya Pakki wrote:
> kmalloc_node might fail to allocate memory for thp field. This fix
> attempts to avoid a potential NULL pointer dereference.
>

If this was detected by any static analyzer, please mention the
tool in the commit log.

Also, notice that this code does not apply to linux-next.

Thanks
--
Gustavo

> Signed-off-by: Aditya Pakki 
> ---
>  arch/x86/platform/uv/tlb_uv.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
> index a4130b84d1ff..5a6d51e30a36 100644
> --- a/arch/x86/platform/uv/tlb_uv.c
> +++ b/arch/x86/platform/uv/tlb_uv.c
> @@ -2011,6 +2011,9 @@ static void make_per_cpu_thp(struct bau_control 
> *smaster)
>   size_t hpsz = sizeof(struct hub_and_pnode) * num_possible_cpus();
>  
>   smaster->thp = kmalloc_node(hpsz, GFP_KERNEL, smaster->osnode);
> + if (!smaster->thp)
> + return;
> +
>   memset(smaster->thp, 0, hpsz);
>   for_each_present_cpu(cpu) {
>   smaster->thp[cpu].pnode = uv_cpu_hub_info(cpu)->pnode;
> 


[PATCH] isdn: mISDN: Fix potential NULL pointer dereference of kzalloc

2019-03-02 Thread Aditya Pakki
Allocating memory via kzalloc for phi may fail and causes a
NULL pointer dereference. This patch avoids such a scenario.

Signed-off-by: Aditya Pakki 
---
 drivers/isdn/hardware/mISDN/hfcsusb.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c 
b/drivers/isdn/hardware/mISDN/hfcsusb.c
index 124ff530da82..26e3182bbca8 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -263,6 +263,9 @@ hfcsusb_ph_info(struct hfcsusb *hw)
int i;
 
phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC);
+   if (!phi)
+   return;
+
phi->dch.ch.protocol = hw->protocol;
phi->dch.ch.Flags = dch->Flags;
phi->dch.state = dch->state;
-- 
2.17.1



Re: [PATCH] x86: uv: Fix potential NULL pointer dereference of kmalloc_node

2019-03-02 Thread Joe Perches
On Sat, 2019-03-02 at 15:09 -0600, Aditya Pakki wrote:
> kmalloc_node might fail to allocate memory for thp field. This fix
> attempts to avoid a potential NULL pointer dereference.

right

> diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
[]
> @@ -2011,6 +2011,9 @@ static void make_per_cpu_thp(struct bau_control 
> *smaster)
>   size_t hpsz = sizeof(struct hub_and_pnode) * num_possible_cpus();
>  
>   smaster->thp = kmalloc_node(hpsz, GFP_KERNEL, smaster->osnode);
> + if (!smaster->thp)
> + return;
> +
>   memset(smaster->thp, 0, hpsz);

Could use kzalloc_node as well




[PATCH] x86: uv: Fix potential NULL pointer dereference of kmalloc_node

2019-03-02 Thread Aditya Pakki
kmalloc_node might fail to allocate memory for thp field. This fix
attempts to avoid a potential NULL pointer dereference.

Signed-off-by: Aditya Pakki 
---
 arch/x86/platform/uv/tlb_uv.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index a4130b84d1ff..5a6d51e30a36 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -2011,6 +2011,9 @@ static void make_per_cpu_thp(struct bau_control *smaster)
size_t hpsz = sizeof(struct hub_and_pnode) * num_possible_cpus();
 
smaster->thp = kmalloc_node(hpsz, GFP_KERNEL, smaster->osnode);
+   if (!smaster->thp)
+   return;
+
memset(smaster->thp, 0, hpsz);
for_each_present_cpu(cpu) {
smaster->thp[cpu].pnode = uv_cpu_hub_info(cpu)->pnode;
-- 
2.17.1



Re: [PATCH] rtc: pcf85063: remove dead code

2019-03-02 Thread Alexandre Belloni
On 19/02/2019 15:39:29+0700, Alexey Roslyakov wrote:
> Some of defines are not in use since
> 7b5768486a910532885f01b9d2dad4818c8b3be1. Remove it to make the code
> easier to read and understand.
> 
> Signed-off-by: Alexey Roslyakov 
> ---
>  drivers/rtc/rtc-pcf85063.c | 7 ---
>  1 file changed, 7 deletions(-)
> 
Applied, thanks.

-- 
Alexandre Belloni, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


[PATCH] omapfb: Fix potential NULL pointer dereference in kmalloc

2019-03-02 Thread Aditya Pakki
Memory allocated, using kmalloc, for new_compat may fail. This patch
checks for such an error and prevents potential NULL pointer
dereference.

Signed-off-by: Aditya Pakki 
---
 drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c 
b/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c
index 136d30484d02..0592c436b2da 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c
@@ -111,6 +111,8 @@ static void __init omapdss_omapify_node(struct device_node 
*node)
 
new_len = prop->length + strlen(prefix) * num_strs;
new_compat = kmalloc(new_len, GFP_KERNEL);
+   if (!new_compat)
+   return;
 
omapdss_prefix_strcpy(new_compat, new_len, prop->value, prop->length);
 
-- 
2.17.1



[PATCH] rsi: Fix NULL pointer dereference in kmalloc

2019-03-02 Thread Aditya Pakki
kmalloc can fail in rsi_register_rates_channels but memcpy still attempts
to write to channels. The patch checks and avoids such a situation.

Signed-off-by: Aditya Pakki 
---
 drivers/net/wireless/rsi/rsi_91x_mac80211.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c 
b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index e56fc83faf0e..59eb1f533d0e 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -197,6 +197,11 @@ static void rsi_register_rates_channels(struct rsi_hw 
*adapter, int band)
 
if (band == NL80211_BAND_2GHZ) {
channels = kmalloc(sizeof(rsi_2ghz_channels), GFP_KERNEL);
+   if (!channels) {
+   rsi_dbg(ERR_ZONE, "Failed to allocate memory\n");
+   return;
+   }
+
memcpy(channels,
   rsi_2ghz_channels,
   sizeof(rsi_2ghz_channels));
@@ -206,6 +211,11 @@ static void rsi_register_rates_channels(struct rsi_hw 
*adapter, int band)
sbands->n_bitrates = ARRAY_SIZE(rsi_rates);
} else {
channels = kmalloc(sizeof(rsi_5ghz_channels), GFP_KERNEL);
+   if (!channels) {
+   rsi_dbg(ERR_ZONE, "Failed to allocate memory\n");
+   return;
+   }
+
memcpy(channels,
   rsi_5ghz_channels,
   sizeof(rsi_5ghz_channels));
-- 
2.17.1



Re: [PATCH] staging: speakup: i18n: fix spelling mistake "phoneticly" -> "phonetically"

2019-03-02 Thread Samuel Thibault
Hello,

Colin King, le mer. 28 nov. 2018 16:12:32 +, a ecrit:
> From: Colin Ian King 
> 
> There is a spelling mistake in array speakup_default_msgs at index
> MSG_FUNCNAME_SPELL_WORD_PHONETICALLY, fix this.
> 
> Signed-off-by: Colin Ian King 

We never got any feedback from the speakup mailing list, I guess fixing
the typo is fine.

Reviewed-by: Samuel Thibault 

> ---
>  drivers/staging/speakup/i18n.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/staging/speakup/i18n.c b/drivers/staging/speakup/i18n.c
> index cea8707653f5..ee240d36f947 100644
> --- a/drivers/staging/speakup/i18n.c
> +++ b/drivers/staging/speakup/i18n.c
> @@ -336,7 +336,7 @@ static char *speakup_default_msgs[MSG_LAST_INDEX] = {
>   [MSG_FUNCNAME_SPELL_DELAY_DEC] = "spell delay decrement",
>   [MSG_FUNCNAME_SPELL_DELAY_INC] = "spell delay increment",
>   [MSG_FUNCNAME_SPELL_WORD] = "spell word",
> - [MSG_FUNCNAME_SPELL_WORD_PHONETICALLY] = "spell word phoneticly",
> + [MSG_FUNCNAME_SPELL_WORD_PHONETICALLY] = "spell word phonetically",
>   [MSG_FUNCNAME_TONE_DEC] = "tone decrement",
>   [MSG_FUNCNAME_TONE_INC] = "tone increment",
>   [MSG_FUNCNAME_VOICE_DEC] = "voice decrement",
> -- 
> 2.19.1
> 



[PATCH v2] RDMA/umem: minor bug fix and cleanup in error handling paths

2019-03-02 Thread john . hubbard
From: John Hubbard 

1. Bug fix: the error handling release pages starting
at the first page that experienced an error.

2. Refinement: release_pages() is better than put_page()
in a loop.

3. Dead code removal: the check for (user_virt & ~page_mask)
is checking for a condition that can never happen,
because earlier:

user_virt = user_virt & page_mask;

...so, remove that entire phrase.

4. Minor: As long as I'm here, shorten up a couple of long lines
in the same function, without harming the ability to
grep for the printed error message.

Cc: Ira Weiny 
Cc: Jason Gunthorpe 
Cc: Andrew Morton 
Cc: Doug Ledford 
Cc: linux-r...@vger.kernel.org
Cc: linux...@kvack.org
Signed-off-by: John Hubbard 
---

v2: Fixes a kbuild test robot reported build failure, by directly
including pagemap.h

 drivers/infiniband/core/umem_odp.c | 25 ++---
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/infiniband/core/umem_odp.c 
b/drivers/infiniband/core/umem_odp.c
index acb882f279cb..83872c1f3f2c 100644
--- a/drivers/infiniband/core/umem_odp.c
+++ b/drivers/infiniband/core/umem_odp.c
@@ -40,6 +40,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -648,25 +649,17 @@ int ib_umem_odp_map_dma_pages(struct ib_umem_odp 
*umem_odp, u64 user_virt,
 
if (npages < 0) {
if (npages != -EAGAIN)
-   pr_warn("fail to get %zu user pages with error 
%d\n", gup_num_pages, npages);
+   pr_warn("fail to get %zu user pages with error 
%d\n",
+   gup_num_pages, npages);
else
-   pr_debug("fail to get %zu user pages with error 
%d\n", gup_num_pages, npages);
+   pr_debug("fail to get %zu user pages with error 
%d\n",
+gup_num_pages, npages);
break;
}
 
bcnt -= min_t(size_t, npages << PAGE_SHIFT, bcnt);
mutex_lock(_odp->umem_mutex);
for (j = 0; j < npages; j++, user_virt += PAGE_SIZE) {
-   if (user_virt & ~page_mask) {
-   p += PAGE_SIZE;
-   if (page_to_phys(local_page_list[j]) != p) {
-   ret = -EFAULT;
-   break;
-   }
-   put_page(local_page_list[j]);
-   continue;
-   }
-
ret = ib_umem_odp_map_dma_single_page(
umem_odp, k, local_page_list[j],
access_mask, current_seq);
@@ -684,9 +677,11 @@ int ib_umem_odp_map_dma_pages(struct ib_umem_odp 
*umem_odp, u64 user_virt,
mutex_unlock(_odp->umem_mutex);
 
if (ret < 0) {
-   /* Release left over pages when handling errors. */
-   for (++j; j < npages; ++j)
-   put_page(local_page_list[j]);
+   /*
+* Release pages, starting at the the first page
+* that experienced an error.
+*/
+   release_pages(_page_list[j], npages - j);
break;
}
}
-- 
2.21.0



Re: kernel BUG at include/linux/mm.h:LINE! (4)

2019-03-02 Thread Eric Biggers
On Fri, Mar 01, 2019 at 11:05:05PM -0800, syzbot wrote:
> Hello,
> 
> syzbot found the following crash on:
> 
> HEAD commit:42fd8df9d1d9 Add linux-next specific files for 20190228
> git tree:   linux-next
> console output: https://syzkaller.appspot.com/x/log.txt?x=16c3cd5cc0
> kernel config:  https://syzkaller.appspot.com/x/.config?x=c0f38652d28b522f
> dashboard link: https://syzkaller.appspot.com/bug?extid=cc252aa9d2d3b576246f
> compiler:   gcc (GCC) 9.0.0 20181231 (experimental)
> 
> Unfortunately, I don't have any reproducer for this crash yet.
> 
> IMPORTANT: if you fix the bug, please add the following tag to the commit:
> Reported-by: syzbot+cc252aa9d2d3b5762...@syzkaller.appspotmail.com
> 
> page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
> page->mem_cgroup:888059786cc0
> [ cut here ]
> kernel BUG at include/linux/mm.h:579!
> invalid opcode:  [#1] PREEMPT SMP KASAN
> CPU: 0 PID: 22405 Comm: syz-executor.3 Not tainted 5.0.0-rc8-next-20190228
> #45
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> Google 01/01/2011
> RIP: 0010:put_page_testzero include/linux/mm.h:579 [inline]
> RIP: 0010:put_page include/linux/mm.h:1025 [inline]
> RIP: 0010:generic_pipe_buf_release+0x120/0x160 fs/pipe.c:224
> Code: bd ff 4c 89 e7 e8 90 43 db ff e8 5b 07 bd ff 5b 41 5c 41 5d 5d c3 e8
> 4f 07 bd ff 48 c7 c6 60 98 75 87 4c 89 e7 e8 c0 db e4 ff <0f> 0b e8 39 07 bd
> ff 4d 8d 65 ff e9 3d ff ff ff 48 89 df e8 e8 f8
> RSP: 0018:888056c57920 EFLAGS: 00010246
> RAX: 0004 RBX: ea0002283db4 RCX: c9000c456000
> RDX: 0004 RSI: 81984e72 RDI: ed100ad8af08
> RBP: 888056c57938 R08: 0021 R09: ed1015d05011
> R10: ed1015d05010 R11: 8880ae828087 R12: ea0002283d80
> R13:  R14: 88809ad3c800 R15: 8880592ac928
> FS:  7fb53aaf2700() GS:8880ae80() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 7fff65e0fdb8 CR3: 93a2f000 CR4: 001406f0
> DR0:  DR1:  DR2: 
> DR3:  DR6: fffe0ff0 DR7: 0400
> Call Trace:
>  pipe_buf_release include/linux/pipe_fs_i.h:129 [inline]
>  iter_file_splice_write+0x7d1/0xbe0 fs/splice.c:759
>  do_splice_from fs/splice.c:847 [inline]
>  direct_splice_actor+0x126/0x1a0 fs/splice.c:1019
>  splice_direct_to_actor+0x369/0x970 fs/splice.c:974
>  do_splice_direct+0x1da/0x2a0 fs/splice.c:1062
>  do_sendfile+0x597/0xd00 fs/read_write.c:1442
>  __do_sys_sendfile64 fs/read_write.c:1503 [inline]
>  __se_sys_sendfile64 fs/read_write.c:1489 [inline]
>  __x64_sys_sendfile64+0x1dd/0x220 fs/read_write.c:1489
>  do_syscall_64+0x103/0x610 arch/x86/entry/common.c:290
>  entry_SYSCALL_64_after_hwframe+0x49/0xbe
> RIP: 0033:0x457e29
> Code: ad b8 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7
> 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff
> 0f 83 7b b8 fb ff c3 66 2e 0f 1f 84 00 00 00 00
> RSP: 002b:7fb53aaf1c78 EFLAGS: 0246 ORIG_RAX: 0028
> RAX: ffda RBX: 0004 RCX: 00457e29
> RDX:  RSI: 0003 RDI: 0003
> RBP: 0073bf00 R08:  R09: 
> R10: 00010200 R11: 0246 R12: 7fb53aaf26d4
> R13: 004c4dce R14: 004d8af8 R15: 
> Modules linked in:
> ---[ end trace ce17ea3937b628f2 ]---
> RIP: 0010:put_page_testzero include/linux/mm.h:579 [inline]
> RIP: 0010:put_page include/linux/mm.h:1025 [inline]
> RIP: 0010:generic_pipe_buf_release+0x120/0x160 fs/pipe.c:224
> Code: bd ff 4c 89 e7 e8 90 43 db ff e8 5b 07 bd ff 5b 41 5c 41 5d 5d c3 e8
> 4f 07 bd ff 48 c7 c6 60 98 75 87 4c 89 e7 e8 c0 db e4 ff <0f> 0b e8 39 07 bd
> ff 4d 8d 65 ff e9 3d ff ff ff 48 89 df e8 e8 f8
> RSP: 0018:888056c57920 EFLAGS: 00010246
> RAX: 0004 RBX: ea0002283db4 RCX: c9000c456000
> RDX: 0004 RSI: 81984e72 RDI: ed100ad8af08
> RBP: 888056c57938 R08: 0021 R09: ed1015d05011
> R10: ed1015d05010 R11: 8880ae828087 R12: ea0002283d80
> R13:  R14: 88809ad3c800 R15: 8880592ac928
> FS:  7fb53aaf2700() GS:8880ae90() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 001b30225000 CR3: 93a2f000 CR4: 001406e0
> DR0:  DR1:  DR2: 
> DR3:  DR6: fffe0ff0 DR7: 0400
> 
> 
> ---
> This bug is generated by a bot. It may contain errors.
> See https://goo.gl/tpsmEJ for more information about syzbot.
> syzbot engineers can be reached at syzkal...@googlegroups.com.
> 
> syzbot will keep track of this bug report. See:
> https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with
> 

[PATCH] mtd: ubi: wl: Fix uninitialized variable

2019-03-02 Thread Gustavo A. R. Silva
There is a potential execution path in which variable *err*
is compared against UBI_IO_BITFLIPS without being properly
initialized previously.

Fix this by initializing variable *err* to 0.

Addresses-Coverity-ID: 1477298 "(Uninitialized scalar variable")
Fixes: 663586c0a892 ("ubi: Expose the bitrot interface")
Signed-off-by: Gustavo A. R. Silva 
---
 drivers/mtd/ubi/wl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 40f838d54b0f..cf07d869724f 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1475,7 +1475,7 @@ static bool scrub_possible(struct ubi_device *ubi, struct 
ubi_wl_entry *e)
  */
 int ubi_bitflip_check(struct ubi_device *ubi, int pnum, int force)
 {
-   int err;
+   int err = 0;
struct ubi_wl_entry *e;
 
if (pnum < 0 || pnum >= ubi->peb_count) {
-- 
2.21.0



Re: [GIT pull] x86 fixes for 5.0

2019-03-02 Thread pr-tracker-bot
The pull request you sent on Sat, 2 Mar 2019 20:19:57 +0100 (CET):

> git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-urgent-for-linus

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/e7c42a89e9f16039684418dfe3c43b068734ff8f

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.wiki.kernel.org/userdoc/prtracker


Re: [GIT PULL] SCSI fixes for 5.0-rc7

2019-03-02 Thread pr-tracker-bot
The pull request you sent on Sat, 02 Mar 2019 07:49:48 -0800:

> git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git scsi-fixes

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/df49fd0ff83a0c20c5ce68a790a4f43601ecdc4a

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.wiki.kernel.org/userdoc/prtracker


[PATCH][next] net/mlx5e: Remove redundant assignment

2019-03-02 Thread Gustavo A. R. Silva
Remove redundant assignment to tun_entropy->enabled.

Addesses-Coverity-ID: 1477328 ("Unused value")
Fixes: 97417f6182f8 ("net/mlx5e: Fix GRE key by controlling port tunnel entropy 
calculation")
Signed-off-by: Gustavo A. R. Silva 
---
 drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c 
b/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c
index 40f4a19b1ce1..be69c1d7941a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c
@@ -80,10 +80,8 @@ void mlx5_init_port_tun_entropy(struct mlx5_tun_entropy 
*tun_entropy,
mlx5_query_port_tun_entropy(mdev, _flags);
tun_entropy->num_enabling_entries = 0;
tun_entropy->num_disabling_entries = 0;
-   tun_entropy->enabled = entropy_flags.calc_enabled;
-   tun_entropy->enabled =
-   (entropy_flags.calc_supported) ?
-   entropy_flags.calc_enabled : true;
+   tun_entropy->enabled = entropy_flags.calc_supported ?
+  entropy_flags.calc_enabled : true;
 }
 
 static int mlx5_set_entropy(struct mlx5_tun_entropy *tun_entropy,
-- 
2.21.0



  1   2   3   >