The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/nvdimm/nvdimm_nfit.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2018 Intel Corporation
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/bio.h>
   32 #include <sys/bus.h>
   33 #include <sys/malloc.h>
   34 #include <sys/uuid.h>
   35 
   36 #include <contrib/dev/acpica/include/acpi.h>
   37 #include <dev/acpica/acpivar.h>
   38 #include <dev/nvdimm/nvdimm_var.h>
   39 
   40 static int
   41 uint32_t_compare(const void *a, const void *b)
   42 {
   43 
   44         return (*(const uint32_t *)a - *(const uint32_t *)b);
   45 }
   46 
   47 static int
   48 find_matches(ACPI_TABLE_NFIT *nfitbl, uint16_t type, uint16_t offset,
   49     uint64_t mask, uint64_t value, void **ptrs, int ptrs_len)
   50 {
   51         ACPI_NFIT_HEADER *h, *end;
   52         uint64_t val;
   53         size_t load_size;
   54         int count;
   55 
   56         h = (ACPI_NFIT_HEADER *)(nfitbl + 1);
   57         end = (ACPI_NFIT_HEADER *)((char *)nfitbl +
   58             nfitbl->Header.Length);
   59         load_size = roundup2(flsl(mask), 8) / 8;
   60         count = 0;
   61 
   62         while (h < end) {
   63                 if (h->Type == type) {
   64                         bcopy((char *)h + offset, &val, load_size);
   65                         val &= mask;
   66                         if (val == value) {
   67                                 if (ptrs_len > 0) {
   68                                         ptrs[count] = h;
   69                                         ptrs_len--;
   70                                 }
   71                                 count++;
   72                         }
   73                 }
   74                 if (h->Length == 0)
   75                         break;
   76                 h = (ACPI_NFIT_HEADER *)((char *)h + h->Length);
   77         }
   78         return (count);
   79 }
   80 
   81 static void
   82 malloc_find_matches(ACPI_TABLE_NFIT *nfitbl, uint16_t type, uint16_t offset,
   83     uint64_t mask, uint64_t value, void ***ptrs, int *ptrs_len)
   84 {
   85         int count;
   86 
   87         count = find_matches(nfitbl, type, offset, mask, value, NULL, 0);
   88         *ptrs_len = count;
   89         if (count == 0) {
   90                 *ptrs = NULL;
   91                 return;
   92         }
   93         *ptrs = mallocarray(count, sizeof(void *), M_NVDIMM, M_WAITOK);
   94         find_matches(nfitbl, type, offset, mask, value, *ptrs, *ptrs_len);
   95 }
   96 
   97 void
   98 acpi_nfit_get_dimm_ids(ACPI_TABLE_NFIT *nfitbl, nfit_handle_t **listp,
   99     int *countp)
  100 {
  101         ACPI_NFIT_SYSTEM_ADDRESS **spas;
  102         ACPI_NFIT_MEMORY_MAP ***regions;
  103         int i, j, k, maxids, num_spas, *region_counts;
  104 
  105         acpi_nfit_get_spa_ranges(nfitbl, &spas, &num_spas);
  106         if (num_spas == 0) {
  107                 *listp = NULL;
  108                 *countp = 0;
  109                 return;
  110         }
  111         regions = mallocarray(num_spas, sizeof(uint16_t *), M_NVDIMM,
  112             M_WAITOK);
  113         region_counts = mallocarray(num_spas, sizeof(int), M_NVDIMM, M_WAITOK);
  114         for (i = 0; i < num_spas; i++) {
  115                 acpi_nfit_get_region_mappings_by_spa_range(nfitbl,
  116                     spas[i]->RangeIndex, &regions[i], &region_counts[i]);
  117         }
  118         maxids = 0;
  119         for (i = 0; i < num_spas; i++) {
  120                 maxids += region_counts[i];
  121         }
  122         *listp = mallocarray(maxids, sizeof(nfit_handle_t), M_NVDIMM, M_WAITOK);
  123         k = 0;
  124         for (i = 0; i < num_spas; i++) {
  125                 for (j = 0; j < region_counts[i]; j++)
  126                         (*listp)[k++] = regions[i][j]->DeviceHandle;
  127         }
  128         qsort((*listp), maxids, sizeof(uint32_t), uint32_t_compare);
  129         i = 0;
  130         for (j = 1; j < maxids; j++) {
  131                 if ((*listp)[i] != (*listp)[j])
  132                         (*listp)[++i] = (*listp)[j];
  133         }
  134         *countp = i + 1;
  135         free(region_counts, M_NVDIMM);
  136         for (i = 0; i < num_spas; i++)
  137                 free(regions[i], M_NVDIMM);
  138         free(regions, M_NVDIMM);
  139         free(spas, M_NVDIMM);
  140 }
  141 
  142 void
  143 acpi_nfit_get_spa_range(ACPI_TABLE_NFIT *nfitbl, uint16_t range_index,
  144     ACPI_NFIT_SYSTEM_ADDRESS **spa)
  145 {
  146 
  147         *spa = NULL;
  148         find_matches(nfitbl, ACPI_NFIT_TYPE_SYSTEM_ADDRESS,
  149             offsetof(ACPI_NFIT_SYSTEM_ADDRESS, RangeIndex), UINT16_MAX,
  150             range_index, (void **)spa, 1);
  151 }
  152 
  153 void
  154 acpi_nfit_get_spa_ranges(ACPI_TABLE_NFIT *nfitbl,
  155     ACPI_NFIT_SYSTEM_ADDRESS ***listp, int *countp)
  156 {
  157 
  158         malloc_find_matches(nfitbl, ACPI_NFIT_TYPE_SYSTEM_ADDRESS, 0, 0, 0,
  159             (void ***)listp, countp);
  160 }
  161 
  162 void
  163 acpi_nfit_get_region_mappings_by_spa_range(ACPI_TABLE_NFIT *nfitbl,
  164     uint16_t spa_range_index, ACPI_NFIT_MEMORY_MAP ***listp, int *countp)
  165 {
  166 
  167         malloc_find_matches(nfitbl, ACPI_NFIT_TYPE_MEMORY_MAP,
  168             offsetof(ACPI_NFIT_MEMORY_MAP, RangeIndex), UINT16_MAX,
  169             spa_range_index, (void ***)listp, countp);
  170 }
  171 
  172 void acpi_nfit_get_control_region(ACPI_TABLE_NFIT *nfitbl,
  173     uint16_t control_region_index, ACPI_NFIT_CONTROL_REGION **out)
  174 {
  175 
  176         *out = NULL;
  177         find_matches(nfitbl, ACPI_NFIT_TYPE_CONTROL_REGION,
  178             offsetof(ACPI_NFIT_CONTROL_REGION, RegionIndex), UINT16_MAX,
  179             control_region_index, (void **)out, 1);
  180 }
  181 
  182 void
  183 acpi_nfit_get_flush_addrs(ACPI_TABLE_NFIT *nfitbl, nfit_handle_t dimm,
  184     uint64_t ***listp, int *countp)
  185 {
  186         ACPI_NFIT_FLUSH_ADDRESS *subtable;
  187         int i;
  188 
  189         subtable = NULL;
  190         find_matches(nfitbl, ACPI_NFIT_TYPE_FLUSH_ADDRESS,
  191             offsetof(ACPI_NFIT_FLUSH_ADDRESS, DeviceHandle), UINT32_MAX,
  192             dimm, (void **)&subtable, 1);
  193         if (subtable == NULL || subtable->HintCount == 0) {
  194                 *listp = NULL;
  195                 *countp = 0;
  196                 return;
  197         }
  198         *countp = subtable->HintCount;
  199         *listp = mallocarray(subtable->HintCount, sizeof(uint64_t *), M_NVDIMM,
  200             M_WAITOK);
  201         for (i = 0; i < subtable->HintCount; i++)
  202                 (*listp)[i] = (uint64_t *)(intptr_t)subtable->HintAddress[i];
  203 }
  204 
  205 void
  206 acpi_nfit_get_memory_maps_by_dimm(ACPI_TABLE_NFIT *nfitbl, nfit_handle_t dimm,
  207     ACPI_NFIT_MEMORY_MAP ***listp, int *countp)
  208 {
  209 
  210         malloc_find_matches(nfitbl, ACPI_NFIT_TYPE_MEMORY_MAP,
  211             offsetof(ACPI_NFIT_MEMORY_MAP, DeviceHandle), UINT32_MAX, dimm,
  212             (void ***)listp, countp);
  213 }

Cache object: a10bce7ee791ea5c50d4cbc31957b1e5


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.