net/mlx5e: Offload tc vlan push/pop using HW action
[sfrench/cifs-2.6.git] / drivers / sfi / sfi_core.c
1 /* sfi_core.c Simple Firmware Interface - core internals */
2
3 /*
4
5   This file is provided under a dual BSD/GPLv2 license.  When using or
6   redistributing this file, you may do so under either license.
7
8   GPL LICENSE SUMMARY
9
10   Copyright(c) 2009 Intel Corporation. All rights reserved.
11
12   This program is free software; you can redistribute it and/or modify
13   it under the terms of version 2 of the GNU General Public License as
14   published by the Free Software Foundation.
15
16   This program is distributed in the hope that it will be useful, but
17   WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19   General Public License for more details.
20
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
24   The full GNU General Public License is included in this distribution
25   in the file called LICENSE.GPL.
26
27   BSD LICENSE
28
29   Copyright(c) 2009 Intel Corporation. All rights reserved.
30
31   Redistribution and use in source and binary forms, with or without
32   modification, are permitted provided that the following conditions
33   are met:
34
35     * Redistributions of source code must retain the above copyright
36       notice, this list of conditions and the following disclaimer.
37     * Redistributions in binary form must reproduce the above copyright
38       notice, this list of conditions and the following disclaimer in
39       the documentation and/or other materials provided with the
40       distribution.
41     * Neither the name of Intel Corporation nor the names of its
42       contributors may be used to endorse or promote products derived
43       from this software without specific prior written permission.
44
45   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
46   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
47   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
48   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
49   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
52   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
53   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
54   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
55   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56
57 */
58
59 #define KMSG_COMPONENT "SFI"
60 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
61
62 #include <linux/bootmem.h>
63 #include <linux/kernel.h>
64 #include <linux/module.h>
65 #include <linux/errno.h>
66 #include <linux/types.h>
67 #include <linux/acpi.h>
68 #include <linux/init.h>
69 #include <linux/sfi.h>
70 #include <linux/slab.h>
71 #include <linux/io.h>
72
73 #include "sfi_core.h"
74
75 #define ON_SAME_PAGE(addr1, addr2) \
76         (((unsigned long)(addr1) & PAGE_MASK) == \
77         ((unsigned long)(addr2) & PAGE_MASK))
78 #define TABLE_ON_PAGE(page, table, size) (ON_SAME_PAGE(page, table) && \
79                                 ON_SAME_PAGE(page, table + size))
80
81 int sfi_disabled __read_mostly;
82 EXPORT_SYMBOL(sfi_disabled);
83
84 static u64 syst_pa __read_mostly;
85 static struct sfi_table_simple *syst_va __read_mostly;
86
87 /*
88  * FW creates and saves the SFI tables in memory. When these tables get
89  * used, they may need to be mapped to virtual address space, and the mapping
90  * can happen before or after the memremap() is ready, so a flag is needed
91  * to indicating this
92  */
93 static u32 sfi_use_memremap __read_mostly;
94
95 /*
96  * sfi_un/map_memory calls early_memremap/memunmap which is a __init function
97  * and introduces section mismatch. So use __ref to make it calm.
98  */
99 static void __iomem * __ref sfi_map_memory(u64 phys, u32 size)
100 {
101         if (!phys || !size)
102                 return NULL;
103
104         if (sfi_use_memremap)
105                 return memremap(phys, size, MEMREMAP_WB);
106         else
107                 return early_memremap(phys, size);
108 }
109
110 static void __ref sfi_unmap_memory(void __iomem *virt, u32 size)
111 {
112         if (!virt || !size)
113                 return;
114
115         if (sfi_use_memremap)
116                 memunmap(virt);
117         else
118                 early_memunmap(virt, size);
119 }
120
121 static void sfi_print_table_header(unsigned long long pa,
122                                 struct sfi_table_header *header)
123 {
124         pr_info("%4.4s %llX, %04X (v%d %6.6s %8.8s)\n",
125                 header->sig, pa,
126                 header->len, header->rev, header->oem_id,
127                 header->oem_table_id);
128 }
129
130 /*
131  * sfi_verify_table()
132  * Sanity check table lengh, calculate checksum
133  */
134 static int sfi_verify_table(struct sfi_table_header *table)
135 {
136
137         u8 checksum = 0;
138         u8 *puchar = (u8 *)table;
139         u32 length = table->len;
140
141         /* Sanity check table length against arbitrary 1MB limit */
142         if (length > 0x100000) {
143                 pr_err("Invalid table length 0x%x\n", length);
144                 return -1;
145         }
146
147         while (length--)
148                 checksum += *puchar++;
149
150         if (checksum) {
151                 pr_err("Checksum %2.2X should be %2.2X\n",
152                         table->csum, table->csum - checksum);
153                 return -1;
154         }
155         return 0;
156 }
157
158 /*
159  * sfi_map_table()
160  *
161  * Return address of mapped table
162  * Check for common case that we can re-use mapping to SYST,
163  * which requires syst_pa, syst_va to be initialized.
164  */
165 static struct sfi_table_header *sfi_map_table(u64 pa)
166 {
167         struct sfi_table_header *th;
168         u32 length;
169
170         if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header)))
171                 th = sfi_map_memory(pa, sizeof(struct sfi_table_header));
172         else
173                 th = (void *)syst_va + (pa - syst_pa);
174
175          /* If table fits on same page as its header, we are done */
176         if (TABLE_ON_PAGE(th, th, th->len))
177                 return th;
178
179         /* Entire table does not fit on same page as SYST */
180         length = th->len;
181         if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header)))
182                 sfi_unmap_memory(th, sizeof(struct sfi_table_header));
183
184         return sfi_map_memory(pa, length);
185 }
186
187 /*
188  * sfi_unmap_table()
189  *
190  * Undoes effect of sfi_map_table() by unmapping table
191  * if it did not completely fit on same page as SYST.
192  */
193 static void sfi_unmap_table(struct sfi_table_header *th)
194 {
195         if (!TABLE_ON_PAGE(syst_va, th, th->len))
196                 sfi_unmap_memory(th, TABLE_ON_PAGE(th, th, th->len) ?
197                                         sizeof(*th) : th->len);
198 }
199
200 static int sfi_table_check_key(struct sfi_table_header *th,
201                                 struct sfi_table_key *key)
202 {
203
204         if (strncmp(th->sig, key->sig, SFI_SIGNATURE_SIZE)
205                 || (key->oem_id && strncmp(th->oem_id,
206                                 key->oem_id, SFI_OEM_ID_SIZE))
207                 || (key->oem_table_id && strncmp(th->oem_table_id,
208                                 key->oem_table_id, SFI_OEM_TABLE_ID_SIZE)))
209                 return -1;
210
211         return 0;
212 }
213
214 /*
215  * This function will be used in 2 cases:
216  * 1. used to enumerate and verify the tables addressed by SYST/XSDT,
217  *    thus no signature will be given (in kernel boot phase)
218  * 2. used to parse one specific table, signature must exist, and
219  *    the mapped virt address will be returned, and the virt space
220  *    will be released by call sfi_put_table() later
221  *
222  * This two cases are from two different functions with two different
223  * sections and causes section mismatch warning. So use __ref to tell
224  * modpost not to make any noise.
225  *
226  * Return value:
227  *      NULL:                   when can't find a table matching the key
228  *      ERR_PTR(error):         error value
229  *      virt table address:     when a matched table is found
230  */
231 struct sfi_table_header *
232  __ref sfi_check_table(u64 pa, struct sfi_table_key *key)
233 {
234         struct sfi_table_header *th;
235         void *ret = NULL;
236
237         th = sfi_map_table(pa);
238         if (!th)
239                 return ERR_PTR(-ENOMEM);
240
241         if (!key->sig) {
242                 sfi_print_table_header(pa, th);
243                 if (sfi_verify_table(th))
244                         ret = ERR_PTR(-EINVAL);
245         } else {
246                 if (!sfi_table_check_key(th, key))
247                         return th;      /* Success */
248         }
249
250         sfi_unmap_table(th);
251         return ret;
252 }
253
254 /*
255  * sfi_get_table()
256  *
257  * Search SYST for the specified table with the signature in
258  * the key, and return the mapped table
259  */
260 struct sfi_table_header *sfi_get_table(struct sfi_table_key *key)
261 {
262         struct sfi_table_header *th;
263         u32 tbl_cnt, i;
264
265         tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64);
266         for (i = 0; i < tbl_cnt; i++) {
267                 th = sfi_check_table(syst_va->pentry[i], key);
268                 if (!IS_ERR(th) && th)
269                         return th;
270         }
271
272         return NULL;
273 }
274
275 void sfi_put_table(struct sfi_table_header *th)
276 {
277         sfi_unmap_table(th);
278 }
279
280 /* Find table with signature, run handler on it */
281 int sfi_table_parse(char *signature, char *oem_id, char *oem_table_id,
282                         sfi_table_handler handler)
283 {
284         struct sfi_table_header *table = NULL;
285         struct sfi_table_key key;
286         int ret = -EINVAL;
287
288         if (sfi_disabled || !handler || !signature)
289                 goto exit;
290
291         key.sig = signature;
292         key.oem_id = oem_id;
293         key.oem_table_id = oem_table_id;
294
295         table = sfi_get_table(&key);
296         if (!table)
297                 goto exit;
298
299         ret = handler(table);
300         sfi_put_table(table);
301 exit:
302         return ret;
303 }
304 EXPORT_SYMBOL_GPL(sfi_table_parse);
305
306 /*
307  * sfi_parse_syst()
308  * Checksum all the tables in SYST and print their headers
309  *
310  * success: set syst_va, return 0
311  */
312 static int __init sfi_parse_syst(void)
313 {
314         struct sfi_table_key key = SFI_ANY_KEY;
315         int tbl_cnt, i;
316         void *ret;
317
318         syst_va = sfi_map_memory(syst_pa, sizeof(struct sfi_table_simple));
319         if (!syst_va)
320                 return -ENOMEM;
321
322         tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64);
323         for (i = 0; i < tbl_cnt; i++) {
324                 ret = sfi_check_table(syst_va->pentry[i], &key);
325                 if (IS_ERR(ret))
326                         return PTR_ERR(ret);
327         }
328
329         return 0;
330 }
331
332 /*
333  * The OS finds the System Table by searching 16-byte boundaries between
334  * physical address 0x000E0000 and 0x000FFFFF. The OS shall search this region
335  * starting at the low address and shall stop searching when the 1st valid SFI
336  * System Table is found.
337  *
338  * success: set syst_pa, return 0
339  * fail: return -1
340  */
341 static __init int sfi_find_syst(void)
342 {
343         unsigned long offset, len;
344         void *start;
345
346         len = SFI_SYST_SEARCH_END - SFI_SYST_SEARCH_BEGIN;
347         start = sfi_map_memory(SFI_SYST_SEARCH_BEGIN, len);
348         if (!start)
349                 return -1;
350
351         for (offset = 0; offset < len; offset += 16) {
352                 struct sfi_table_header *syst_hdr;
353
354                 syst_hdr = start + offset;
355                 if (strncmp(syst_hdr->sig, SFI_SIG_SYST,
356                                 SFI_SIGNATURE_SIZE))
357                         continue;
358
359                 if (syst_hdr->len > PAGE_SIZE)
360                         continue;
361
362                 sfi_print_table_header(SFI_SYST_SEARCH_BEGIN + offset,
363                                         syst_hdr);
364
365                 if (sfi_verify_table(syst_hdr))
366                         continue;
367
368                 /*
369                  * Enforce SFI spec mandate that SYST reside within a page.
370                  */
371                 if (!ON_SAME_PAGE(syst_pa, syst_pa + syst_hdr->len)) {
372                         pr_info("SYST 0x%llx + 0x%x crosses page\n",
373                                         syst_pa, syst_hdr->len);
374                         continue;
375                 }
376
377                 /* Success */
378                 syst_pa = SFI_SYST_SEARCH_BEGIN + offset;
379                 sfi_unmap_memory(start, len);
380                 return 0;
381         }
382
383         sfi_unmap_memory(start, len);
384         return -1;
385 }
386
387 static struct kobject *sfi_kobj;
388 static struct kobject *tables_kobj;
389
390 static ssize_t sfi_table_show(struct file *filp, struct kobject *kobj,
391                                struct bin_attribute *bin_attr, char *buf,
392                                loff_t offset, size_t count)
393 {
394         struct sfi_table_attr *tbl_attr =
395             container_of(bin_attr, struct sfi_table_attr, attr);
396         struct sfi_table_header *th = NULL;
397         struct sfi_table_key key;
398         ssize_t cnt;
399
400         key.sig = tbl_attr->name;
401         key.oem_id = NULL;
402         key.oem_table_id = NULL;
403
404         if (strncmp(SFI_SIG_SYST, tbl_attr->name, SFI_SIGNATURE_SIZE)) {
405                 th = sfi_get_table(&key);
406                 if (!th)
407                         return 0;
408
409                 cnt =  memory_read_from_buffer(buf, count, &offset,
410                                                 th, th->len);
411                 sfi_put_table(th);
412         } else
413                 cnt =  memory_read_from_buffer(buf, count, &offset,
414                                         syst_va, syst_va->header.len);
415
416         return cnt;
417 }
418
419 struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa)
420 {
421         struct sfi_table_attr *tbl_attr;
422         struct sfi_table_header *th;
423         int ret;
424
425         tbl_attr = kzalloc(sizeof(struct sfi_table_attr), GFP_KERNEL);
426         if (!tbl_attr)
427                 return NULL;
428
429         th = sfi_map_table(pa);
430         if (!th || !th->sig[0]) {
431                 kfree(tbl_attr);
432                 return NULL;
433         }
434
435         sysfs_attr_init(&tbl_attr->attr.attr);
436         memcpy(tbl_attr->name, th->sig, SFI_SIGNATURE_SIZE);
437
438         tbl_attr->attr.size = 0;
439         tbl_attr->attr.read = sfi_table_show;
440         tbl_attr->attr.attr.name = tbl_attr->name;
441         tbl_attr->attr.attr.mode = 0400;
442
443         ret = sysfs_create_bin_file(tables_kobj,
444                                   &tbl_attr->attr);
445         if (ret) {
446                 kfree(tbl_attr);
447                 tbl_attr = NULL;
448         }
449
450         sfi_unmap_table(th);
451         return tbl_attr;
452 }
453
454 static int __init sfi_sysfs_init(void)
455 {
456         int tbl_cnt, i;
457
458         if (sfi_disabled)
459                 return 0;
460
461         sfi_kobj = kobject_create_and_add("sfi", firmware_kobj);
462         if (!sfi_kobj)
463                 return 0;
464
465         tables_kobj = kobject_create_and_add("tables", sfi_kobj);
466         if (!tables_kobj) {
467                 kobject_put(sfi_kobj);
468                 return 0;
469         }
470
471         sfi_sysfs_install_table(syst_pa);
472
473         tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64);
474
475         for (i = 0; i < tbl_cnt; i++)
476                 sfi_sysfs_install_table(syst_va->pentry[i]);
477
478         sfi_acpi_sysfs_init();
479         kobject_uevent(sfi_kobj, KOBJ_ADD);
480         kobject_uevent(tables_kobj, KOBJ_ADD);
481         pr_info("SFI sysfs interfaces init success\n");
482         return 0;
483 }
484
485 void __init sfi_init(void)
486 {
487         if (!acpi_disabled)
488                 disable_sfi();
489
490         if (sfi_disabled)
491                 return;
492
493         pr_info("Simple Firmware Interface v0.81 http://simplefirmware.org\n");
494
495         if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init())
496                 disable_sfi();
497
498         return;
499 }
500
501 void __init sfi_init_late(void)
502 {
503         int length;
504
505         if (sfi_disabled)
506                 return;
507
508         length = syst_va->header.len;
509         sfi_unmap_memory(syst_va, sizeof(struct sfi_table_simple));
510
511         /* Use memremap now after it is ready */
512         sfi_use_memremap = 1;
513         syst_va = sfi_map_memory(syst_pa, length);
514
515         sfi_acpi_init();
516 }
517
518 /*
519  * The reason we put it here because we need wait till the /sys/firmware
520  * is setup, then our interface can be registered in /sys/firmware/sfi
521  */
522 core_initcall(sfi_sysfs_init);