From: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> To: David Daney <ddaney.cavm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> Cc: Alexandre Courbot <gnurou-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>, Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>, Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>, "linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org" <linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>, "devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org" <devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>, "linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org" <linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>, David Daney <david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>, Marc Zyngier <marc.zyngier-5wv7dgnIgG8@public.gmane.org> Subject: Re: [PATCH v2 2/3] gpio: Add gpio driver support for ThunderX and OCTEON-TX Date: Mon, 9 Jan 2017 20:35:37 +0100 [thread overview] Message-ID: <CACRpkdaOQM7=mDTA1K92N5P=jjaCyhsSw5DGL+bnXE_GOYw82Q@mail.gmail.com> (raw) In-Reply-To: <1483744980-25898-3-git-send-email-ddaney.cavm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> On Sat, Jan 7, 2017 at 12:22 AM, David Daney <ddaney.cavm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > From: David Daney <david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org> > > Cavium ThunderX and OCTEON-TX are arm64 based SoCs. Add driver for > the on-chip GPIO pins. > > Signed-off-by: David Daney <david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org> (...) > +config GPIO_THUNDERX > + tristate "Cavium ThunderX/OCTEON-TX GPIO" Do you really load this as module? OK then... > +#include <linux/gpio.h> No. #include <linux/gpio/driver.h> Nothing else. > +#define GLITCH_FILTER_400NS ((4ull << GPIO_BIT_CFG_FIL_SEL_SHIFT) | \ > + (9ull << GPIO_BIT_CFG_FIL_CNT_SHIFT)) > + > +static unsigned int bit_cfg_reg(unsigned int line) > +{ > + return 8 * line + GPIO_BIT_CFG; > +} > + > +static unsigned int intr_reg(unsigned int line) > +{ > + return 8 * line + GPIO_INTR; > +} This looks a bit overzealous, but OK. > +struct thunderx_gpio; > + > +struct thunderx_irqdev { > + struct thunderx_gpio *gpio; > + char *name; > + unsigned int line; > +}; > + > +struct thunderx_gpio { > + struct gpio_chip chip; > + u8 __iomem *register_base; > + struct msix_entry *msix_entries; > + struct thunderx_irqdev *irqdev_entries; > + raw_spinlock_t lock; > + unsigned long invert_mask[2]; > + unsigned long od_mask[2]; > + int base_msi; > +}; Why can't you just move the thunderx_irqdev fields into thunderx_gpio? It will save very little memory for non-irq systems, I do not think footprint warrants it. > + > +static bool thunderx_gpio_is_gpio(struct thunderx_gpio *gpio, > + unsigned int line) > +{ > + u64 bit_cfg = readq(gpio->register_base + bit_cfg_reg(line)); > + bool rv = (bit_cfg & GPIO_BIT_CFG_PIN_SEL_MASK) == 0; > + > + WARN_RATELIMIT(!rv, "Pin %d not available for GPIO\n", line); > + > + return rv; > +} Nifty. So this actually has a pin controller back-end? I haven't seen the code for that yet, I think. This seems like a cheap version of /* External interface to pin control */ extern int pinctrl_request_gpio(unsigned gpio); extern void pinctrl_free_gpio(unsigned gpio); extern int pinctrl_gpio_direction_input(unsigned gpio); extern int pinctrl_gpio_direction_output(unsigned gpio); >From <linux/pinctrl/consumer.h> So are you planning pin control support separately in drivers/pinctrl/* in the future? Maybe some comment to replace this with proper pin control in the future is warranted? > +static int thunderx_gpio_dir_in(struct gpio_chip *chip, unsigned int line) > +{ > + struct thunderx_gpio *gpio = container_of(chip, struct thunderx_gpio, chip); 1. Please use gpiochip_get_data() instead of the container_of() construction, utilized devm_gpiochip_add_data() in your probe() call. 2. Do not call this local variable "gpio" that is superconfusing, at least call it txgpio or something. 1 & 2 applies EVERYWHERE in thid driver. > +static void thunderx_gpio_set(struct gpio_chip *chip, unsigned int line, > + int value) > +{ > + struct thunderx_gpio *gpio = container_of(chip, struct thunderx_gpio, chip); > + int bank = line / 64; > + int bank_bit = line % 64; > + > + void __iomem *reg = gpio->register_base + > + (bank * GPIO_2ND_BANK) + (value ? GPIO_TX_SET : GPIO_TX_CLR); > + > + writeq(1ull << bank_bit, reg); Use this: #include <linus/bitops.h> writeq(BIT(bank_bit), reg); Applies EVERYWHERE you use (1ULL << n) > +static int thunderx_gpio_set_single_ended(struct gpio_chip *chip, > + unsigned int line, > + enum single_ended_mode mode) Thanks for implementing this properly. > + read_bits >>= bank_bit; > + > + if (test_bit(line, gpio->invert_mask)) > + return !(read_bits & 1); > + else > + return read_bits & 1; This looks superconvoluted. Can't you just: if (test_bit(line, gpio->invert_mask)) return !(read_bits & BIT(bank_bit)); else return !!(read_bits & BIT(bank_bit)); OK maybe not much clearer but seems clearer to me. > +static int thunderx_gpio_irq_request_resources(struct irq_data *data) > +{ > + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); > + struct thunderx_gpio *gpio = container_of(chip, struct thunderx_gpio, chip); > + unsigned int line = data->hwirq; > + struct thunderx_irqdev *irqdev; > + int err; > + > + if (!thunderx_gpio_is_gpio(gpio, line)) > + return -EIO; > + > + irqdev = gpio->irqdev_entries + line; > + > + irqdev->gpio = gpio; > + irqdev->line = line; > + irqdev->name = devm_kasprintf(chip->parent, GFP_KERNEL, > + "gpio-%d", line + chip->base); > + > + writeq(GPIO_INTR_ENA_W1C, gpio->register_base + intr_reg(line)); > + > + err = devm_request_irq(chip->parent, gpio->msix_entries[line].vector, > + thunderx_gpio_chain_handler, IRQF_NO_THREAD, irqdev->name, irqdev); > + return err; > +} > + > +static void thunderx_gpio_irq_release_resources(struct irq_data *data) > +{ > + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); > + struct thunderx_gpio *gpio = container_of(chip, struct thunderx_gpio, chip); > + unsigned int line = data->hwirq; > + struct thunderx_irqdev *irqdev; > + > + irqdev = gpio->irqdev_entries + line; > + > + /* > + * The request_resources/release_resources functions may be > + * called multiple times in the lifitime of the driver, so we > + * need to clean up the devm_* things to avoid a resource > + * leak. > + */ > + devm_free_irq(chip->parent, gpio->msix_entries[line].vector, irqdev); > + > + writeq(GPIO_INTR_ENA_W1C, gpio->register_base + intr_reg(line)); > + > + devm_kfree(chip->parent, irqdev->name); > +} Then just do not use the devm* variants. Explicitly allocate and free instead. These callbacks should be called on all resources anyways. > +static void thunderx_gpio_irq_unmask(struct irq_data *data) > +{ > + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); > + struct thunderx_gpio *gpio = container_of(chip, struct thunderx_gpio, chip); > + unsigned int line = data->hwirq; > + > + writeq(GPIO_INTR_ENA_W1S, gpio->register_base + intr_reg(line)); > +} > + > +static int thunderx_gpio_irq_set_type(struct irq_data *data, > + unsigned int flow_type) > +{ > + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); > + struct thunderx_gpio *gpio = container_of(chip, struct thunderx_gpio, chip); > + unsigned int line = data->hwirq; > + u64 bit_cfg; > + > + irqd_set_trigger_type(data, flow_type); > + > + bit_cfg = GLITCH_FILTER_400NS | GPIO_BIT_CFG_INT_EN; > + > + if (flow_type & IRQ_TYPE_EDGE_BOTH) { > + irq_set_handler_locked(data, handle_edge_irq); > + bit_cfg |= GPIO_BIT_CFG_INT_TYPE; > + } else { > + irq_set_handler_locked(data, handle_level_irq); > + } > + > + raw_spin_lock(&gpio->lock); > + if (flow_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)) { > + bit_cfg |= GPIO_BIT_CFG_PIN_XOR; > + set_bit(line, gpio->invert_mask); > + } else { > + clear_bit(line, gpio->invert_mask); > + } > + clear_bit(line, gpio->od_mask); > + writeq(bit_cfg, gpio->register_base + bit_cfg_reg(line)); > + raw_spin_unlock(&gpio->lock); > + > + return IRQ_SET_MASK_OK; > +} > + > +/* > + * Interrupts are chained from underlying MSI-X vectors. We have > + * these irq_chip functions to be able to handle level triggering > + * semantics and other acknowledgment tasks associated with the GPIO > + * mechanism. > + */ > +static struct irq_chip thunderx_gpio_irq_chip = { > + .name = "GPIO", > + .irq_enable = thunderx_gpio_irq_unmask, > + .irq_disable = thunderx_gpio_irq_mask, > + .irq_ack = thunderx_gpio_irq_ack, > + .irq_mask = thunderx_gpio_irq_mask, > + .irq_mask_ack = thunderx_gpio_irq_mask_ack, > + .irq_unmask = thunderx_gpio_irq_unmask, > + .irq_set_type = thunderx_gpio_irq_set_type, > + .irq_request_resources = thunderx_gpio_irq_request_resources, > + .irq_release_resources = thunderx_gpio_irq_release_resources, > + .flags = IRQCHIP_SET_TYPE_MASKED > +}; This looks wrong. If you're calling devm_request_irq() on *every* *single* *irq* like you do here, you are dealing with a hieararchical irqdomain, not a linear one, and GPIOLIB_IRQCHIP may not be used. Look at drivers/gpio/gpio-xgene-sb.c for inspiration. That is the only hierarchical GPIO irqdomain I have right now. Consult Marc Zyngier's IRQ domain lecture if you have time: https://www.youtube.com/watch?v=YE8cRHVIM4E If you have ideas how to combine hierarchical irqdomain and GPIOLIB_IRQCHIP pls help out. > + gpio->irqdev_entries = devm_kzalloc(dev, > + sizeof(struct thunderx_irqdev) * ngpio, > + GFP_KERNEL); > + if (!gpio->irqdev_entries) { > + err = -ENOMEM; > + goto out; > + } I think this is overkill. Use hierarchical irqdomain. Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html
WARNING: multiple messages have this Message-ID (diff)
From: Linus Walleij <linus.walleij@linaro.org> To: David Daney <ddaney.cavm@gmail.com> Cc: Alexandre Courbot <gnurou@gmail.com>, Rob Herring <robh+dt@kernel.org>, Mark Rutland <mark.rutland@arm.com>, "linux-gpio@vger.kernel.org" <linux-gpio@vger.kernel.org>, "devicetree@vger.kernel.org" <devicetree@vger.kernel.org>, "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>, David Daney <david.daney@cavium.com>, Marc Zyngier <marc.zyngier@arm.com> Subject: Re: [PATCH v2 2/3] gpio: Add gpio driver support for ThunderX and OCTEON-TX Date: Mon, 9 Jan 2017 20:35:37 +0100 [thread overview] Message-ID: <CACRpkdaOQM7=mDTA1K92N5P=jjaCyhsSw5DGL+bnXE_GOYw82Q@mail.gmail.com> (raw) In-Reply-To: <1483744980-25898-3-git-send-email-ddaney.cavm@gmail.com> On Sat, Jan 7, 2017 at 12:22 AM, David Daney <ddaney.cavm@gmail.com> wrote: > From: David Daney <david.daney@cavium.com> > > Cavium ThunderX and OCTEON-TX are arm64 based SoCs. Add driver for > the on-chip GPIO pins. > > Signed-off-by: David Daney <david.daney@cavium.com> (...) > +config GPIO_THUNDERX > + tristate "Cavium ThunderX/OCTEON-TX GPIO" Do you really load this as module? OK then... > +#include <linux/gpio.h> No. #include <linux/gpio/driver.h> Nothing else. > +#define GLITCH_FILTER_400NS ((4ull << GPIO_BIT_CFG_FIL_SEL_SHIFT) | \ > + (9ull << GPIO_BIT_CFG_FIL_CNT_SHIFT)) > + > +static unsigned int bit_cfg_reg(unsigned int line) > +{ > + return 8 * line + GPIO_BIT_CFG; > +} > + > +static unsigned int intr_reg(unsigned int line) > +{ > + return 8 * line + GPIO_INTR; > +} This looks a bit overzealous, but OK. > +struct thunderx_gpio; > + > +struct thunderx_irqdev { > + struct thunderx_gpio *gpio; > + char *name; > + unsigned int line; > +}; > + > +struct thunderx_gpio { > + struct gpio_chip chip; > + u8 __iomem *register_base; > + struct msix_entry *msix_entries; > + struct thunderx_irqdev *irqdev_entries; > + raw_spinlock_t lock; > + unsigned long invert_mask[2]; > + unsigned long od_mask[2]; > + int base_msi; > +}; Why can't you just move the thunderx_irqdev fields into thunderx_gpio? It will save very little memory for non-irq systems, I do not think footprint warrants it. > + > +static bool thunderx_gpio_is_gpio(struct thunderx_gpio *gpio, > + unsigned int line) > +{ > + u64 bit_cfg = readq(gpio->register_base + bit_cfg_reg(line)); > + bool rv = (bit_cfg & GPIO_BIT_CFG_PIN_SEL_MASK) == 0; > + > + WARN_RATELIMIT(!rv, "Pin %d not available for GPIO\n", line); > + > + return rv; > +} Nifty. So this actually has a pin controller back-end? I haven't seen the code for that yet, I think. This seems like a cheap version of /* External interface to pin control */ extern int pinctrl_request_gpio(unsigned gpio); extern void pinctrl_free_gpio(unsigned gpio); extern int pinctrl_gpio_direction_input(unsigned gpio); extern int pinctrl_gpio_direction_output(unsigned gpio); >From <linux/pinctrl/consumer.h> So are you planning pin control support separately in drivers/pinctrl/* in the future? Maybe some comment to replace this with proper pin control in the future is warranted? > +static int thunderx_gpio_dir_in(struct gpio_chip *chip, unsigned int line) > +{ > + struct thunderx_gpio *gpio = container_of(chip, struct thunderx_gpio, chip); 1. Please use gpiochip_get_data() instead of the container_of() construction, utilized devm_gpiochip_add_data() in your probe() call. 2. Do not call this local variable "gpio" that is superconfusing, at least call it txgpio or something. 1 & 2 applies EVERYWHERE in thid driver. > +static void thunderx_gpio_set(struct gpio_chip *chip, unsigned int line, > + int value) > +{ > + struct thunderx_gpio *gpio = container_of(chip, struct thunderx_gpio, chip); > + int bank = line / 64; > + int bank_bit = line % 64; > + > + void __iomem *reg = gpio->register_base + > + (bank * GPIO_2ND_BANK) + (value ? GPIO_TX_SET : GPIO_TX_CLR); > + > + writeq(1ull << bank_bit, reg); Use this: #include <linus/bitops.h> writeq(BIT(bank_bit), reg); Applies EVERYWHERE you use (1ULL << n) > +static int thunderx_gpio_set_single_ended(struct gpio_chip *chip, > + unsigned int line, > + enum single_ended_mode mode) Thanks for implementing this properly. > + read_bits >>= bank_bit; > + > + if (test_bit(line, gpio->invert_mask)) > + return !(read_bits & 1); > + else > + return read_bits & 1; This looks superconvoluted. Can't you just: if (test_bit(line, gpio->invert_mask)) return !(read_bits & BIT(bank_bit)); else return !!(read_bits & BIT(bank_bit)); OK maybe not much clearer but seems clearer to me. > +static int thunderx_gpio_irq_request_resources(struct irq_data *data) > +{ > + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); > + struct thunderx_gpio *gpio = container_of(chip, struct thunderx_gpio, chip); > + unsigned int line = data->hwirq; > + struct thunderx_irqdev *irqdev; > + int err; > + > + if (!thunderx_gpio_is_gpio(gpio, line)) > + return -EIO; > + > + irqdev = gpio->irqdev_entries + line; > + > + irqdev->gpio = gpio; > + irqdev->line = line; > + irqdev->name = devm_kasprintf(chip->parent, GFP_KERNEL, > + "gpio-%d", line + chip->base); > + > + writeq(GPIO_INTR_ENA_W1C, gpio->register_base + intr_reg(line)); > + > + err = devm_request_irq(chip->parent, gpio->msix_entries[line].vector, > + thunderx_gpio_chain_handler, IRQF_NO_THREAD, irqdev->name, irqdev); > + return err; > +} > + > +static void thunderx_gpio_irq_release_resources(struct irq_data *data) > +{ > + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); > + struct thunderx_gpio *gpio = container_of(chip, struct thunderx_gpio, chip); > + unsigned int line = data->hwirq; > + struct thunderx_irqdev *irqdev; > + > + irqdev = gpio->irqdev_entries + line; > + > + /* > + * The request_resources/release_resources functions may be > + * called multiple times in the lifitime of the driver, so we > + * need to clean up the devm_* things to avoid a resource > + * leak. > + */ > + devm_free_irq(chip->parent, gpio->msix_entries[line].vector, irqdev); > + > + writeq(GPIO_INTR_ENA_W1C, gpio->register_base + intr_reg(line)); > + > + devm_kfree(chip->parent, irqdev->name); > +} Then just do not use the devm* variants. Explicitly allocate and free instead. These callbacks should be called on all resources anyways. > +static void thunderx_gpio_irq_unmask(struct irq_data *data) > +{ > + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); > + struct thunderx_gpio *gpio = container_of(chip, struct thunderx_gpio, chip); > + unsigned int line = data->hwirq; > + > + writeq(GPIO_INTR_ENA_W1S, gpio->register_base + intr_reg(line)); > +} > + > +static int thunderx_gpio_irq_set_type(struct irq_data *data, > + unsigned int flow_type) > +{ > + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); > + struct thunderx_gpio *gpio = container_of(chip, struct thunderx_gpio, chip); > + unsigned int line = data->hwirq; > + u64 bit_cfg; > + > + irqd_set_trigger_type(data, flow_type); > + > + bit_cfg = GLITCH_FILTER_400NS | GPIO_BIT_CFG_INT_EN; > + > + if (flow_type & IRQ_TYPE_EDGE_BOTH) { > + irq_set_handler_locked(data, handle_edge_irq); > + bit_cfg |= GPIO_BIT_CFG_INT_TYPE; > + } else { > + irq_set_handler_locked(data, handle_level_irq); > + } > + > + raw_spin_lock(&gpio->lock); > + if (flow_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)) { > + bit_cfg |= GPIO_BIT_CFG_PIN_XOR; > + set_bit(line, gpio->invert_mask); > + } else { > + clear_bit(line, gpio->invert_mask); > + } > + clear_bit(line, gpio->od_mask); > + writeq(bit_cfg, gpio->register_base + bit_cfg_reg(line)); > + raw_spin_unlock(&gpio->lock); > + > + return IRQ_SET_MASK_OK; > +} > + > +/* > + * Interrupts are chained from underlying MSI-X vectors. We have > + * these irq_chip functions to be able to handle level triggering > + * semantics and other acknowledgment tasks associated with the GPIO > + * mechanism. > + */ > +static struct irq_chip thunderx_gpio_irq_chip = { > + .name = "GPIO", > + .irq_enable = thunderx_gpio_irq_unmask, > + .irq_disable = thunderx_gpio_irq_mask, > + .irq_ack = thunderx_gpio_irq_ack, > + .irq_mask = thunderx_gpio_irq_mask, > + .irq_mask_ack = thunderx_gpio_irq_mask_ack, > + .irq_unmask = thunderx_gpio_irq_unmask, > + .irq_set_type = thunderx_gpio_irq_set_type, > + .irq_request_resources = thunderx_gpio_irq_request_resources, > + .irq_release_resources = thunderx_gpio_irq_release_resources, > + .flags = IRQCHIP_SET_TYPE_MASKED > +}; This looks wrong. If you're calling devm_request_irq() on *every* *single* *irq* like you do here, you are dealing with a hieararchical irqdomain, not a linear one, and GPIOLIB_IRQCHIP may not be used. Look at drivers/gpio/gpio-xgene-sb.c for inspiration. That is the only hierarchical GPIO irqdomain I have right now. Consult Marc Zyngier's IRQ domain lecture if you have time: https://www.youtube.com/watch?v=YE8cRHVIM4E If you have ideas how to combine hierarchical irqdomain and GPIOLIB_IRQCHIP pls help out. > + gpio->irqdev_entries = devm_kzalloc(dev, > + sizeof(struct thunderx_irqdev) * ngpio, > + GFP_KERNEL); > + if (!gpio->irqdev_entries) { > + err = -ENOMEM; > + goto out; > + } I think this is overkill. Use hierarchical irqdomain. Yours, Linus Walleij
next prev parent reply other threads:[~2017-01-09 19:35 UTC|newest] Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top 2017-01-06 23:22 [PATCH v2 0/3] GPIO: Add driver for ThunderX and OCTEON-TX SoCs David Daney 2017-01-06 23:22 ` David Daney [not found] ` <1483744980-25898-1-git-send-email-ddaney.cavm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> 2017-01-06 23:22 ` [PATCH v2 1/3] dt-bindings: gpio: Add binding documentation for gpio-thunderx David Daney 2017-01-06 23:22 ` David Daney 2017-01-09 19:36 ` Linus Walleij [not found] ` <CACRpkdZ0xkhUC7_0A4uHxpGaU7BHgNp8TNuDPuPN9h6dDsQx4g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2017-01-09 19:44 ` David Daney 2017-01-09 19:44 ` David Daney [not found] ` <a1b6c9da-5b19-c9a7-3774-0bc0e9dcdeb6-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org> 2017-01-10 8:42 ` Linus Walleij 2017-01-10 8:42 ` Linus Walleij 2017-01-10 5:35 ` Rob Herring 2017-01-06 23:22 ` [PATCH v2 2/3] gpio: Add gpio driver support for ThunderX and OCTEON-TX David Daney 2017-01-06 23:22 ` David Daney [not found] ` <1483744980-25898-3-git-send-email-ddaney.cavm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> 2017-01-09 19:35 ` Linus Walleij [this message] 2017-01-09 19:35 ` Linus Walleij 2017-01-09 20:02 ` David Daney 2017-01-11 15:07 ` Linus Walleij 2017-01-06 23:23 ` [PATCH v2 3/3] MAINTAINERS: Add entry for THUNDERX GPIO Driver David Daney
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to='CACRpkdaOQM7=mDTA1K92N5P=jjaCyhsSw5DGL+bnXE_GOYw82Q@mail.gmail.com' \ --to=linus.walleij-qsej5fyqhm4dnm+yrofe0a@public.gmane.org \ --cc=david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org \ --cc=ddaney.cavm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \ --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=gnurou-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \ --cc=linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=marc.zyngier-5wv7dgnIgG8@public.gmane.org \ --cc=mark.rutland-5wv7dgnIgG8@public.gmane.org \ --cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.