diff options
author | Mika Westerberg <mika.westerberg@linux.intel.com> | 2014-03-10 08:54:51 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-03-13 10:14:16 -0400 |
commit | aa92b6f689acf159120ce0753f36100c3b190b4d (patch) | |
tree | c6cc39b0910489fb023d9bfeef6fa42d0d63faa5 /drivers/gpio/gpiolib-acpi.c | |
parent | 77c2d7929d7d7f0e391b17f85d2d954912ed0590 (diff) |
gpio / ACPI: Allocate ACPI specific data directly in acpi_gpiochip_add()
We are going to add more ACPI specific data to accompany GPIO chip so
instead of allocating it per each use-case we allocate it once when
acpi_gpiochip_add() is called and release it when acpi_gpiochip_remove() is
called.
Doing this allows us to add more ACPI specific data by merely adding new
fields to struct acpi_gpio_chip.
In addition we embed evt_pins member directly to the structure instead of
having it as a pointer. This simplifies the code a bit since we don't need
to check against NULL.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpiolib-acpi.c')
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 106 |
1 files changed, 64 insertions, 42 deletions
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index b7db098ba060..5c0cf1d76c8b 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c | |||
@@ -26,6 +26,11 @@ struct acpi_gpio_evt_pin { | |||
26 | unsigned int irq; | 26 | unsigned int irq; |
27 | }; | 27 | }; |
28 | 28 | ||
29 | struct acpi_gpio_chip { | ||
30 | struct gpio_chip *chip; | ||
31 | struct list_head evt_pins; | ||
32 | }; | ||
33 | |||
29 | static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) | 34 | static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) |
30 | { | 35 | { |
31 | if (!gc->dev) | 36 | if (!gc->dev) |
@@ -81,14 +86,14 @@ static irqreturn_t acpi_gpio_irq_handler_evt(int irq, void *data) | |||
81 | return IRQ_HANDLED; | 86 | return IRQ_HANDLED; |
82 | } | 87 | } |
83 | 88 | ||
84 | static void acpi_gpio_evt_dh(acpi_handle handle, void *data) | 89 | static void acpi_gpio_chip_dh(acpi_handle handle, void *data) |
85 | { | 90 | { |
86 | /* The address of this function is used as a key. */ | 91 | /* The address of this function is used as a key. */ |
87 | } | 92 | } |
88 | 93 | ||
89 | /** | 94 | /** |
90 | * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events | 95 | * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events |
91 | * @chip: gpio chip | 96 | * @acpi_gpio: ACPI GPIO chip |
92 | * | 97 | * |
93 | * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are | 98 | * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are |
94 | * handled by ACPI event methods which need to be called from the GPIO | 99 | * handled by ACPI event methods which need to be called from the GPIO |
@@ -96,12 +101,12 @@ static void acpi_gpio_evt_dh(acpi_handle handle, void *data) | |||
96 | * gpio pins have acpi event methods and assigns interrupt handlers that calls | 101 | * gpio pins have acpi event methods and assigns interrupt handlers that calls |
97 | * the acpi event methods for those pins. | 102 | * the acpi event methods for those pins. |
98 | */ | 103 | */ |
99 | static void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) | 104 | static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio) |
100 | { | 105 | { |
101 | struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; | 106 | struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; |
107 | struct gpio_chip *chip = acpi_gpio->chip; | ||
102 | struct acpi_resource *res; | 108 | struct acpi_resource *res; |
103 | acpi_handle handle, evt_handle; | 109 | acpi_handle handle, evt_handle; |
104 | struct list_head *evt_pins = NULL; | ||
105 | acpi_status status; | 110 | acpi_status status; |
106 | unsigned int pin; | 111 | unsigned int pin; |
107 | int irq, ret; | 112 | int irq, ret; |
@@ -114,23 +119,7 @@ static void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) | |||
114 | if (!handle) | 119 | if (!handle) |
115 | return; | 120 | return; |
116 | 121 | ||
117 | status = acpi_get_event_resources(handle, &buf); | 122 | INIT_LIST_HEAD(&acpi_gpio->evt_pins); |
118 | if (ACPI_FAILURE(status)) | ||
119 | return; | ||
120 | |||
121 | status = acpi_get_handle(handle, "_EVT", &evt_handle); | ||
122 | if (ACPI_SUCCESS(status)) { | ||
123 | evt_pins = kzalloc(sizeof(*evt_pins), GFP_KERNEL); | ||
124 | if (evt_pins) { | ||
125 | INIT_LIST_HEAD(evt_pins); | ||
126 | status = acpi_attach_data(handle, acpi_gpio_evt_dh, | ||
127 | evt_pins); | ||
128 | if (ACPI_FAILURE(status)) { | ||
129 | kfree(evt_pins); | ||
130 | evt_pins = NULL; | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | 123 | ||
135 | /* | 124 | /* |
136 | * If a GPIO interrupt has an ACPI event handler method, or _EVT is | 125 | * If a GPIO interrupt has an ACPI event handler method, or _EVT is |
@@ -167,14 +156,18 @@ static void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) | |||
167 | data = ev_handle; | 156 | data = ev_handle; |
168 | } | 157 | } |
169 | } | 158 | } |
170 | if (!handler && evt_pins) { | 159 | if (!handler) { |
171 | struct acpi_gpio_evt_pin *evt_pin; | 160 | struct acpi_gpio_evt_pin *evt_pin; |
172 | 161 | ||
162 | status = acpi_get_handle(handle, "_EVT", &evt_handle); | ||
163 | if (ACPI_FAILURE(status)) | ||
164 | continue | ||
165 | |||
173 | evt_pin = kzalloc(sizeof(*evt_pin), GFP_KERNEL); | 166 | evt_pin = kzalloc(sizeof(*evt_pin), GFP_KERNEL); |
174 | if (!evt_pin) | 167 | if (!evt_pin) |
175 | continue; | 168 | continue; |
176 | 169 | ||
177 | list_add_tail(&evt_pin->node, evt_pins); | 170 | list_add_tail(&evt_pin->node, &acpi_gpio->evt_pins); |
178 | evt_pin->evt_handle = evt_handle; | 171 | evt_pin->evt_handle = evt_handle; |
179 | evt_pin->pin = pin; | 172 | evt_pin->pin = pin; |
180 | evt_pin->irq = irq; | 173 | evt_pin->irq = irq; |
@@ -197,39 +190,27 @@ static void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) | |||
197 | 190 | ||
198 | /** | 191 | /** |
199 | * acpi_gpiochip_free_interrupts() - Free GPIO _EVT ACPI event interrupts. | 192 | * acpi_gpiochip_free_interrupts() - Free GPIO _EVT ACPI event interrupts. |
200 | * @chip: gpio chip | 193 | * @acpi_gpio: ACPI GPIO chip |
201 | * | 194 | * |
202 | * Free interrupts associated with the _EVT method for the given GPIO chip. | 195 | * Free interrupts associated with the _EVT method for the given GPIO chip. |
203 | * | 196 | * |
204 | * The remaining ACPI event interrupts associated with the chip are freed | 197 | * The remaining ACPI event interrupts associated with the chip are freed |
205 | * automatically. | 198 | * automatically. |
206 | */ | 199 | */ |
207 | static void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) | 200 | static void acpi_gpiochip_free_interrupts(struct acpi_gpio_chip *acpi_gpio) |
208 | { | 201 | { |
209 | acpi_handle handle; | ||
210 | acpi_status status; | ||
211 | struct list_head *evt_pins; | ||
212 | struct acpi_gpio_evt_pin *evt_pin, *ep; | 202 | struct acpi_gpio_evt_pin *evt_pin, *ep; |
203 | struct gpio_chip *chip = acpi_gpio->chip; | ||
213 | 204 | ||
214 | if (!chip->dev || !chip->to_irq) | 205 | if (!chip->dev || !chip->to_irq) |
215 | return; | 206 | return; |
216 | 207 | ||
217 | handle = ACPI_HANDLE(chip->dev); | 208 | list_for_each_entry_safe_reverse(evt_pin, ep, &acpi_gpio->evt_pins, |
218 | if (!handle) | 209 | node) { |
219 | return; | ||
220 | |||
221 | status = acpi_get_data(handle, acpi_gpio_evt_dh, (void **)&evt_pins); | ||
222 | if (ACPI_FAILURE(status)) | ||
223 | return; | ||
224 | |||
225 | list_for_each_entry_safe_reverse(evt_pin, ep, evt_pins, node) { | ||
226 | devm_free_irq(chip->dev, evt_pin->irq, evt_pin); | 210 | devm_free_irq(chip->dev, evt_pin->irq, evt_pin); |
227 | list_del(&evt_pin->node); | 211 | list_del(&evt_pin->node); |
228 | kfree(evt_pin); | 212 | kfree(evt_pin); |
229 | } | 213 | } |
230 | |||
231 | acpi_detach_data(handle, acpi_gpio_evt_dh); | ||
232 | kfree(evt_pins); | ||
233 | } | 214 | } |
234 | 215 | ||
235 | struct acpi_gpio_lookup { | 216 | struct acpi_gpio_lookup { |
@@ -312,10 +293,51 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, | |||
312 | 293 | ||
313 | void acpi_gpiochip_add(struct gpio_chip *chip) | 294 | void acpi_gpiochip_add(struct gpio_chip *chip) |
314 | { | 295 | { |
315 | acpi_gpiochip_request_interrupts(chip); | 296 | struct acpi_gpio_chip *acpi_gpio; |
297 | acpi_handle handle; | ||
298 | acpi_status status; | ||
299 | |||
300 | handle = ACPI_HANDLE(chip->dev); | ||
301 | if (!handle) | ||
302 | return; | ||
303 | |||
304 | acpi_gpio = kzalloc(sizeof(*acpi_gpio), GFP_KERNEL); | ||
305 | if (!acpi_gpio) { | ||
306 | dev_err(chip->dev, | ||
307 | "Failed to allocate memory for ACPI GPIO chip\n"); | ||
308 | return; | ||
309 | } | ||
310 | |||
311 | acpi_gpio->chip = chip; | ||
312 | |||
313 | status = acpi_attach_data(handle, acpi_gpio_chip_dh, acpi_gpio); | ||
314 | if (ACPI_FAILURE(status)) { | ||
315 | dev_err(chip->dev, "Failed to attach ACPI GPIO chip\n"); | ||
316 | kfree(acpi_gpio); | ||
317 | return; | ||
318 | } | ||
319 | |||
320 | acpi_gpiochip_request_interrupts(acpi_gpio); | ||
316 | } | 321 | } |
317 | 322 | ||
318 | void acpi_gpiochip_remove(struct gpio_chip *chip) | 323 | void acpi_gpiochip_remove(struct gpio_chip *chip) |
319 | { | 324 | { |
320 | acpi_gpiochip_free_interrupts(chip); | 325 | struct acpi_gpio_chip *acpi_gpio; |
326 | acpi_handle handle; | ||
327 | acpi_status status; | ||
328 | |||
329 | handle = ACPI_HANDLE(chip->dev); | ||
330 | if (!handle) | ||
331 | return; | ||
332 | |||
333 | status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio); | ||
334 | if (ACPI_FAILURE(status)) { | ||
335 | dev_warn(chip->dev, "Failed to retrieve ACPI GPIO chip\n"); | ||
336 | return; | ||
337 | } | ||
338 | |||
339 | acpi_gpiochip_free_interrupts(acpi_gpio); | ||
340 | |||
341 | acpi_detach_data(handle, acpi_gpio_chip_dh); | ||
342 | kfree(acpi_gpio); | ||
321 | } | 343 | } |