Merge branch 'sfi-release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-sfi-2.6

* 'sfi-release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-sfi-2.6:
SFI: add sysfs interface for SFI tables.
SFI: add support for v0.81 spec

+191 -2
+15
Documentation/ABI/testing/sysfs-firmware-sfi
···
··· 1 + What: /sys/firmware/sfi/tables/ 2 + Date: May 2010 3 + Contact: Len Brown <lenb@kernel.org> 4 + Description: 5 + SFI defines a number of small static memory tables 6 + so the kernel can get platform information from firmware. 7 + 8 + The tables are defined in the latest SFI specification: 9 + http://simplefirmware.org/documentation 10 + 11 + While the tables are used by the kernel, user-space 12 + can observe them this way: 13 + 14 + # cd /sys/firmware/sfi/tables 15 + # cat $TABLENAME > $TABLENAME.bin
+41
drivers/sfi/sfi_acpi.c
··· 173 sfi_acpi_put_table(table); 174 return ret; 175 }
··· 173 sfi_acpi_put_table(table); 174 return ret; 175 } 176 + 177 + static ssize_t sfi_acpi_table_show(struct file *filp, struct kobject *kobj, 178 + struct bin_attribute *bin_attr, char *buf, 179 + loff_t offset, size_t count) 180 + { 181 + struct sfi_table_attr *tbl_attr = 182 + container_of(bin_attr, struct sfi_table_attr, attr); 183 + struct acpi_table_header *th = NULL; 184 + struct sfi_table_key key; 185 + ssize_t cnt; 186 + 187 + key.sig = tbl_attr->name; 188 + key.oem_id = NULL; 189 + key.oem_table_id = NULL; 190 + 191 + th = sfi_acpi_get_table(&key); 192 + if (!th) 193 + return 0; 194 + 195 + cnt = memory_read_from_buffer(buf, count, &offset, 196 + th, th->length); 197 + sfi_acpi_put_table(th); 198 + 199 + return cnt; 200 + } 201 + 202 + 203 + void __init sfi_acpi_sysfs_init(void) 204 + { 205 + u32 tbl_cnt, i; 206 + struct sfi_table_attr *tbl_attr; 207 + 208 + tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64); 209 + for (i = 0; i < tbl_cnt; i++) { 210 + tbl_attr = 211 + sfi_sysfs_install_table(xsdt_va->table_offset_entry[i]); 212 + tbl_attr->attr.read = sfi_acpi_table_show; 213 + } 214 + 215 + return; 216 + }
+104 -1
drivers/sfi/sfi_core.c
··· 67 #include <linux/acpi.h> 68 #include <linux/init.h> 69 #include <linux/sfi.h> 70 71 #include "sfi_core.h" 72 ··· 383 return -1; 384 } 385 386 void __init sfi_init(void) 387 { 388 if (!acpi_disabled) ··· 487 if (sfi_disabled) 488 return; 489 490 - pr_info("Simple Firmware Interface v0.7 http://simplefirmware.org\n"); 491 492 if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init()) 493 disable_sfi(); ··· 511 512 sfi_acpi_init(); 513 }
··· 67 #include <linux/acpi.h> 68 #include <linux/init.h> 69 #include <linux/sfi.h> 70 + #include <linux/slab.h> 71 72 #include "sfi_core.h" 73 ··· 382 return -1; 383 } 384 385 + static struct kobject *sfi_kobj; 386 + static struct kobject *tables_kobj; 387 + 388 + static ssize_t sfi_table_show(struct file *filp, struct kobject *kobj, 389 + struct bin_attribute *bin_attr, char *buf, 390 + loff_t offset, size_t count) 391 + { 392 + struct sfi_table_attr *tbl_attr = 393 + container_of(bin_attr, struct sfi_table_attr, attr); 394 + struct sfi_table_header *th = NULL; 395 + struct sfi_table_key key; 396 + ssize_t cnt; 397 + 398 + key.sig = tbl_attr->name; 399 + key.oem_id = NULL; 400 + key.oem_table_id = NULL; 401 + 402 + if (strncmp(SFI_SIG_SYST, tbl_attr->name, SFI_SIGNATURE_SIZE)) { 403 + th = sfi_get_table(&key); 404 + if (!th) 405 + return 0; 406 + 407 + cnt = memory_read_from_buffer(buf, count, &offset, 408 + th, th->len); 409 + sfi_put_table(th); 410 + } else 411 + cnt = memory_read_from_buffer(buf, count, &offset, 412 + syst_va, syst_va->header.len); 413 + 414 + return cnt; 415 + } 416 + 417 + struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa) 418 + { 419 + struct sfi_table_attr *tbl_attr; 420 + struct sfi_table_header *th; 421 + int ret; 422 + 423 + tbl_attr = kzalloc(sizeof(struct sfi_table_attr), GFP_KERNEL); 424 + if (!tbl_attr) 425 + return NULL; 426 + 427 + th = sfi_map_table(pa); 428 + if (!th || !th->sig[0]) { 429 + kfree(tbl_attr); 430 + return NULL; 431 + } 432 + 433 + sysfs_attr_init(&tbl_attr->attr.attr); 434 + memcpy(tbl_attr->name, th->sig, SFI_SIGNATURE_SIZE); 435 + 436 + tbl_attr->attr.size = 0; 437 + tbl_attr->attr.read = sfi_table_show; 438 + tbl_attr->attr.attr.name = tbl_attr->name; 439 + tbl_attr->attr.attr.mode = 0400; 440 + 441 + ret = sysfs_create_bin_file(tables_kobj, 442 + &tbl_attr->attr); 443 + if (ret) 444 + kfree(tbl_attr); 445 + 446 + sfi_unmap_table(th); 447 + return tbl_attr; 448 + } 449 + 450 + static int __init sfi_sysfs_init(void) 451 + { 452 + int tbl_cnt, i; 453 + 454 + if (sfi_disabled) 455 + return 0; 456 + 457 + sfi_kobj = kobject_create_and_add("sfi", firmware_kobj); 458 + if (!sfi_kobj) 459 + return 0; 460 + 461 + tables_kobj = kobject_create_and_add("tables", sfi_kobj); 462 + if (!tables_kobj) { 463 + kobject_put(sfi_kobj); 464 + return 0; 465 + } 466 + 467 + sfi_sysfs_install_table(syst_pa); 468 + 469 + tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); 470 + 471 + for (i = 0; i < tbl_cnt; i++) 472 + sfi_sysfs_install_table(syst_va->pentry[i]); 473 + 474 + sfi_acpi_sysfs_init(); 475 + kobject_uevent(sfi_kobj, KOBJ_ADD); 476 + kobject_uevent(tables_kobj, KOBJ_ADD); 477 + pr_info("SFI sysfs interfaces init success\n"); 478 + return 0; 479 + } 480 + 481 void __init sfi_init(void) 482 { 483 if (!acpi_disabled) ··· 390 if (sfi_disabled) 391 return; 392 393 + pr_info("Simple Firmware Interface v0.81 http://simplefirmware.org\n"); 394 395 if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init()) 396 disable_sfi(); ··· 414 415 sfi_acpi_init(); 416 } 417 + 418 + /* 419 + * The reason we put it here becasue we need wait till the /sys/firmware 420 + * is setup, then our interface can be registered in /sys/firmware/sfi 421 + */ 422 + core_initcall(sfi_sysfs_init);
+8
drivers/sfi/sfi_core.h
··· 61 char *oem_table_id; 62 }; 63 64 #define SFI_ANY_KEY { .sig = NULL, .oem_id = NULL, .oem_table_id = NULL } 65 66 extern int __init sfi_acpi_init(void); ··· 74 struct sfi_table_key *key); 75 struct sfi_table_header *sfi_get_table(struct sfi_table_key *key); 76 extern void sfi_put_table(struct sfi_table_header *table);
··· 61 char *oem_table_id; 62 }; 63 64 + /* sysfs interface */ 65 + struct sfi_table_attr { 66 + struct bin_attribute attr; 67 + char name[8]; 68 + }; 69 + 70 #define SFI_ANY_KEY { .sig = NULL, .oem_id = NULL, .oem_table_id = NULL } 71 72 extern int __init sfi_acpi_init(void); ··· 68 struct sfi_table_key *key); 69 struct sfi_table_header *sfi_get_table(struct sfi_table_key *key); 70 extern void sfi_put_table(struct sfi_table_header *table); 71 + extern struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa); 72 + extern void __init sfi_acpi_sysfs_init(void);
+23 -1
include/linux/sfi.h
··· 73 #define SFI_SIG_SPIB "SPIB" 74 #define SFI_SIG_I2CB "I2CB" 75 #define SFI_SIG_GPEM "GPEM" 76 77 #define SFI_SIGNATURE_SIZE 4 78 #define SFI_OEM_ID_SIZE 6 ··· 147 u32 irq; 148 } __packed; 149 150 struct sfi_spi_table_entry { 151 u16 host_num; /* attached to host 0, 1...*/ 152 u16 cs; /* chip select */ ··· 188 u16 logical_id; /* logical id */ 189 u16 phys_id; /* physical GPE id */ 190 } __packed; 191 - 192 193 typedef int (*sfi_table_handler) (struct sfi_table_header *table); 194
··· 73 #define SFI_SIG_SPIB "SPIB" 74 #define SFI_SIG_I2CB "I2CB" 75 #define SFI_SIG_GPEM "GPEM" 76 + #define SFI_SIG_DEVS "DEVS" 77 + #define SFI_SIG_GPIO "GPIO" 78 79 #define SFI_SIGNATURE_SIZE 4 80 #define SFI_OEM_ID_SIZE 6 ··· 145 u32 irq; 146 } __packed; 147 148 + struct sfi_device_table_entry { 149 + u8 type; /* bus type, I2C, SPI or ...*/ 150 + #define SFI_DEV_TYPE_SPI 0 151 + #define SFI_DEV_TYPE_I2C 1 152 + #define SFI_DEV_TYPE_UART 2 153 + #define SFI_DEV_TYPE_HSI 3 154 + #define SFI_DEV_TYPE_IPC 4 155 + 156 + u8 host_num; /* attached to host 0, 1...*/ 157 + u16 addr; 158 + u8 irq; 159 + u32 max_freq; 160 + char name[16]; 161 + } __packed; 162 + 163 + struct sfi_gpio_table_entry { 164 + char controller_name[16]; 165 + u16 pin_no; 166 + char pin_name[16]; 167 + } __packed; 168 + 169 struct sfi_spi_table_entry { 170 u16 host_num; /* attached to host 0, 1...*/ 171 u16 cs; /* chip select */ ··· 165 u16 logical_id; /* logical id */ 166 u16 phys_id; /* physical GPE id */ 167 } __packed; 168 169 typedef int (*sfi_table_handler) (struct sfi_table_header *table); 170