Merge tag 'sched_ext-for-6.12-rc1-fixes-1' of git://git.kernel.org/pub/scm/linux...
[linux-block.git] / drivers / acpi / acpica / exregion.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: exregion - ACPI default op_region (address space) handlers
5  *
6  * Copyright (C) 2000 - 2023, Intel Corp.
7  *
8  *****************************************************************************/
9
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "acinterp.h"
13
14 #define _COMPONENT          ACPI_EXECUTER
15 ACPI_MODULE_NAME("exregion")
16
17 /*******************************************************************************
18  *
19  * FUNCTION:    acpi_ex_system_memory_space_handler
20  *
21  * PARAMETERS:  function            - Read or Write operation
22  *              address             - Where in the space to read or write
23  *              bit_width           - Field width in bits (8, 16, or 32)
24  *              value               - Pointer to in or out value
25  *              handler_context     - Pointer to Handler's context
26  *              region_context      - Pointer to context specific to the
27  *                                    accessed region
28  *
29  * RETURN:      Status
30  *
31  * DESCRIPTION: Handler for the System Memory address space (Op Region)
32  *
33  ******************************************************************************/
34 acpi_status
35 acpi_ex_system_memory_space_handler(u32 function,
36                                     acpi_physical_address address,
37                                     u32 bit_width,
38                                     u64 *value,
39                                     void *handler_context, void *region_context)
40 {
41         acpi_status status = AE_OK;
42         void *logical_addr_ptr = NULL;
43         struct acpi_mem_space_context *mem_info = region_context;
44         struct acpi_mem_mapping *mm = mem_info->cur_mm;
45         u32 length;
46         acpi_size map_length;
47 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
48         u32 remainder;
49 #endif
50
51         ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);
52
53         /* Validate and translate the bit width */
54
55         switch (bit_width) {
56         case 8:
57
58                 length = 1;
59                 break;
60
61         case 16:
62
63                 length = 2;
64                 break;
65
66         case 32:
67
68                 length = 4;
69                 break;
70
71         case 64:
72
73                 length = 8;
74                 break;
75
76         default:
77
78                 ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u",
79                             bit_width));
80                 return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
81         }
82
83 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
84         /*
85          * Hardware does not support non-aligned data transfers, we must verify
86          * the request.
87          */
88         (void)acpi_ut_short_divide((u64) address, length, NULL, &remainder);
89         if (remainder != 0) {
90                 return_ACPI_STATUS(AE_AML_ALIGNMENT);
91         }
92 #endif
93
94         /*
95          * Does the request fit into the cached memory mapping?
96          * Is 1) Address below the current mapping? OR
97          *    2) Address beyond the current mapping?
98          */
99         if (!mm || (address < mm->physical_address) ||
100             ((u64) address + length > (u64) mm->physical_address + mm->length)) {
101                 /*
102                  * The request cannot be resolved by the current memory mapping.
103                  *
104                  * Look for an existing saved mapping covering the address range
105                  * at hand.  If found, save it as the current one and carry out
106                  * the access.
107                  */
108                 for (mm = mem_info->first_mm; mm; mm = mm->next_mm) {
109                         if (mm == mem_info->cur_mm)
110                                 continue;
111
112                         if (address < mm->physical_address)
113                                 continue;
114
115                         if ((u64) address + length >
116                                         (u64) mm->physical_address + mm->length)
117                                 continue;
118
119                         mem_info->cur_mm = mm;
120                         goto access;
121                 }
122
123                 /* Create a new mappings list entry */
124                 mm = ACPI_ALLOCATE_ZEROED(sizeof(*mm));
125                 if (!mm) {
126                         ACPI_ERROR((AE_INFO,
127                                     "Unable to save memory mapping at 0x%8.8X%8.8X, size %u",
128                                     ACPI_FORMAT_UINT64(address), length));
129                         return_ACPI_STATUS(AE_NO_MEMORY);
130                 }
131
132                 /*
133                  * October 2009: Attempt to map from the requested address to the
134                  * end of the region. However, we will never map more than one
135                  * page, nor will we cross a page boundary.
136                  */
137                 map_length = (acpi_size)
138                     ((mem_info->address + mem_info->length) - address);
139
140                 if (map_length > ACPI_DEFAULT_PAGE_SIZE)
141                         map_length = ACPI_DEFAULT_PAGE_SIZE;
142
143                 /* Create a new mapping starting at the address given */
144
145                 logical_addr_ptr = acpi_os_map_memory(address, map_length);
146                 if (!logical_addr_ptr) {
147                         ACPI_ERROR((AE_INFO,
148                                     "Could not map memory at 0x%8.8X%8.8X, size %u",
149                                     ACPI_FORMAT_UINT64(address),
150                                     (u32)map_length));
151                         ACPI_FREE(mm);
152                         return_ACPI_STATUS(AE_NO_MEMORY);
153                 }
154
155                 /* Save the physical address and mapping size */
156
157                 mm->logical_address = logical_addr_ptr;
158                 mm->physical_address = address;
159                 mm->length = map_length;
160
161                 /*
162                  * Add the new entry to the mappigs list and save it as the
163                  * current mapping.
164                  */
165                 mm->next_mm = mem_info->first_mm;
166                 mem_info->first_mm = mm;
167
168                 mem_info->cur_mm = mm;
169         }
170
171 access:
172         /*
173          * Generate a logical pointer corresponding to the address we want to
174          * access
175          */
176         logical_addr_ptr = mm->logical_address +
177                 ((u64) address - (u64) mm->physical_address);
178
179         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
180                           "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
181                           bit_width, function, ACPI_FORMAT_UINT64(address)));
182
183         /*
184          * Perform the memory read or write
185          *
186          * Note: For machines that do not support non-aligned transfers, the target
187          * address was checked for alignment above. We do not attempt to break the
188          * transfer up into smaller (byte-size) chunks because the AML specifically
189          * asked for a transfer width that the hardware may require.
190          */
191         switch (function) {
192         case ACPI_READ:
193
194                 *value = 0;
195                 switch (bit_width) {
196                 case 8:
197
198                         *value = (u64)ACPI_GET8(logical_addr_ptr);
199                         break;
200
201                 case 16:
202
203                         *value = (u64)ACPI_GET16(logical_addr_ptr);
204                         break;
205
206                 case 32:
207
208                         *value = (u64)ACPI_GET32(logical_addr_ptr);
209                         break;
210
211                 case 64:
212
213                         *value = (u64)ACPI_GET64(logical_addr_ptr);
214                         break;
215
216                 default:
217
218                         /* bit_width was already validated */
219
220                         break;
221                 }
222                 break;
223
224         case ACPI_WRITE:
225
226                 switch (bit_width) {
227                 case 8:
228
229                         ACPI_SET8(logical_addr_ptr, *value);
230                         break;
231
232                 case 16:
233
234                         ACPI_SET16(logical_addr_ptr, *value);
235                         break;
236
237                 case 32:
238
239                         ACPI_SET32(logical_addr_ptr, *value);
240                         break;
241
242                 case 64:
243
244                         ACPI_SET64(logical_addr_ptr, *value);
245                         break;
246
247                 default:
248
249                         /* bit_width was already validated */
250
251                         break;
252                 }
253                 break;
254
255         default:
256
257                 status = AE_BAD_PARAMETER;
258                 break;
259         }
260
261         return_ACPI_STATUS(status);
262 }
263
264 /*******************************************************************************
265  *
266  * FUNCTION:    acpi_ex_system_io_space_handler
267  *
268  * PARAMETERS:  function            - Read or Write operation
269  *              address             - Where in the space to read or write
270  *              bit_width           - Field width in bits (8, 16, or 32)
271  *              value               - Pointer to in or out value
272  *              handler_context     - Pointer to Handler's context
273  *              region_context      - Pointer to context specific to the
274  *                                    accessed region
275  *
276  * RETURN:      Status
277  *
278  * DESCRIPTION: Handler for the System IO address space (Op Region)
279  *
280  ******************************************************************************/
281
282 acpi_status
283 acpi_ex_system_io_space_handler(u32 function,
284                                 acpi_physical_address address,
285                                 u32 bit_width,
286                                 u64 *value,
287                                 void *handler_context, void *region_context)
288 {
289         acpi_status status = AE_OK;
290         u32 value32;
291
292         ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
293
294         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
295                           "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
296                           bit_width, function, ACPI_FORMAT_UINT64(address)));
297
298         /* Decode the function parameter */
299
300         switch (function) {
301         case ACPI_READ:
302
303                 status = acpi_hw_read_port((acpi_io_address)address,
304                                            &value32, bit_width);
305                 *value = value32;
306                 break;
307
308         case ACPI_WRITE:
309
310                 status = acpi_hw_write_port((acpi_io_address)address,
311                                             (u32)*value, bit_width);
312                 break;
313
314         default:
315
316                 status = AE_BAD_PARAMETER;
317                 break;
318         }
319
320         return_ACPI_STATUS(status);
321 }
322
323 #ifdef ACPI_PCI_CONFIGURED
324 /*******************************************************************************
325  *
326  * FUNCTION:    acpi_ex_pci_config_space_handler
327  *
328  * PARAMETERS:  function            - Read or Write operation
329  *              address             - Where in the space to read or write
330  *              bit_width           - Field width in bits (8, 16, or 32)
331  *              value               - Pointer to in or out value
332  *              handler_context     - Pointer to Handler's context
333  *              region_context      - Pointer to context specific to the
334  *                                    accessed region
335  *
336  * RETURN:      Status
337  *
338  * DESCRIPTION: Handler for the PCI Config address space (Op Region)
339  *
340  ******************************************************************************/
341
342 acpi_status
343 acpi_ex_pci_config_space_handler(u32 function,
344                                  acpi_physical_address address,
345                                  u32 bit_width,
346                                  u64 *value,
347                                  void *handler_context, void *region_context)
348 {
349         acpi_status status = AE_OK;
350         struct acpi_pci_id *pci_id;
351         u16 pci_register;
352
353         ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
354
355         /*
356          *  The arguments to acpi_os(Read|Write)pci_configuration are:
357          *
358          *  pci_segment is the PCI bus segment range 0-31
359          *  pci_bus     is the PCI bus number range 0-255
360          *  pci_device  is the PCI device number range 0-31
361          *  pci_function is the PCI device function number
362          *  pci_register is the Config space register range 0-255 bytes
363          *
364          *  value - input value for write, output address for read
365          *
366          */
367         pci_id = (struct acpi_pci_id *)region_context;
368         pci_register = (u16) (u32) address;
369
370         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
371                           "Pci-Config %u (%u) Seg(%04x) Bus(%04x) "
372                           "Dev(%04x) Func(%04x) Reg(%04x)\n",
373                           function, bit_width, pci_id->segment, pci_id->bus,
374                           pci_id->device, pci_id->function, pci_register));
375
376         switch (function) {
377         case ACPI_READ:
378
379                 *value = 0;
380                 status =
381                     acpi_os_read_pci_configuration(pci_id, pci_register, value,
382                                                    bit_width);
383                 break;
384
385         case ACPI_WRITE:
386
387                 status =
388                     acpi_os_write_pci_configuration(pci_id, pci_register,
389                                                     *value, bit_width);
390                 break;
391
392         default:
393
394                 status = AE_BAD_PARAMETER;
395                 break;
396         }
397
398         return_ACPI_STATUS(status);
399 }
400 #endif
401
402 /*******************************************************************************
403  *
404  * FUNCTION:    acpi_ex_cmos_space_handler
405  *
406  * PARAMETERS:  function            - Read or Write operation
407  *              address             - Where in the space to read or write
408  *              bit_width           - Field width in bits (8, 16, or 32)
409  *              value               - Pointer to in or out value
410  *              handler_context     - Pointer to Handler's context
411  *              region_context      - Pointer to context specific to the
412  *                                    accessed region
413  *
414  * RETURN:      Status
415  *
416  * DESCRIPTION: Handler for the CMOS address space (Op Region)
417  *
418  ******************************************************************************/
419
420 acpi_status
421 acpi_ex_cmos_space_handler(u32 function,
422                            acpi_physical_address address,
423                            u32 bit_width,
424                            u64 *value,
425                            void *handler_context, void *region_context)
426 {
427         acpi_status status = AE_OK;
428
429         ACPI_FUNCTION_TRACE(ex_cmos_space_handler);
430
431         return_ACPI_STATUS(status);
432 }
433
434 #ifdef ACPI_PCI_CONFIGURED
435 /*******************************************************************************
436  *
437  * FUNCTION:    acpi_ex_pci_bar_space_handler
438  *
439  * PARAMETERS:  function            - Read or Write operation
440  *              address             - Where in the space to read or write
441  *              bit_width           - Field width in bits (8, 16, or 32)
442  *              value               - Pointer to in or out value
443  *              handler_context     - Pointer to Handler's context
444  *              region_context      - Pointer to context specific to the
445  *                                    accessed region
446  *
447  * RETURN:      Status
448  *
449  * DESCRIPTION: Handler for the PCI bar_target address space (Op Region)
450  *
451  ******************************************************************************/
452
453 acpi_status
454 acpi_ex_pci_bar_space_handler(u32 function,
455                               acpi_physical_address address,
456                               u32 bit_width,
457                               u64 *value,
458                               void *handler_context, void *region_context)
459 {
460         acpi_status status = AE_OK;
461
462         ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler);
463
464         return_ACPI_STATUS(status);
465 }
466 #endif
467
468 /*******************************************************************************
469  *
470  * FUNCTION:    acpi_ex_data_table_space_handler
471  *
472  * PARAMETERS:  function            - Read or Write operation
473  *              address             - Where in the space to read or write
474  *              bit_width           - Field width in bits (8, 16, or 32)
475  *              value               - Pointer to in or out value
476  *              handler_context     - Pointer to Handler's context
477  *              region_context      - Pointer to context specific to the
478  *                                    accessed region
479  *
480  * RETURN:      Status
481  *
482  * DESCRIPTION: Handler for the Data Table address space (Op Region)
483  *
484  ******************************************************************************/
485
486 acpi_status
487 acpi_ex_data_table_space_handler(u32 function,
488                                  acpi_physical_address address,
489                                  u32 bit_width,
490                                  u64 *value,
491                                  void *handler_context, void *region_context)
492 {
493         struct acpi_data_table_mapping *mapping;
494         char *pointer;
495
496         ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
497
498         mapping = (struct acpi_data_table_mapping *) region_context;
499         pointer = ACPI_CAST_PTR(char, mapping->pointer) +
500             (address - ACPI_PTR_TO_PHYSADDR(mapping->pointer));
501
502         /*
503          * Perform the memory read or write. The bit_width was already
504          * validated.
505          */
506         switch (function) {
507         case ACPI_READ:
508
509                 memcpy(ACPI_CAST_PTR(char, value), pointer,
510                        ACPI_DIV_8(bit_width));
511                 break;
512
513         case ACPI_WRITE:
514
515                 memcpy(pointer, ACPI_CAST_PTR(char, value),
516                        ACPI_DIV_8(bit_width));
517                 break;
518
519         default:
520
521                 return_ACPI_STATUS(AE_BAD_PARAMETER);
522         }
523
524         return_ACPI_STATUS(AE_OK);
525 }