diff options
-rw-r--r-- | drivers/thunderbolt/Kconfig | 1 | ||||
-rw-r--r-- | drivers/thunderbolt/eeprom.c | 43 | ||||
-rw-r--r-- | drivers/thunderbolt/switch.c | 2 |
3 files changed, 45 insertions, 1 deletions
diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig index c121acc15bfe..0056df7f3c09 100644 --- a/drivers/thunderbolt/Kconfig +++ b/drivers/thunderbolt/Kconfig @@ -1,6 +1,7 @@ menuconfig THUNDERBOLT tristate "Thunderbolt support for Apple devices" depends on PCI + select APPLE_PROPERTIES select CRC32 help Cactus Ridge Thunderbolt Controller driver diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c index 2b9602c2c355..6392990c984d 100644 --- a/drivers/thunderbolt/eeprom.c +++ b/drivers/thunderbolt/eeprom.c @@ -5,6 +5,7 @@ */ #include <linux/crc32.h> +#include <linux/property.h> #include <linux/slab.h> #include "tb.h" @@ -360,6 +361,40 @@ static int tb_drom_parse_entries(struct tb_switch *sw) } /** + * tb_drom_copy_efi - copy drom supplied by EFI to sw->drom if present + */ +static int tb_drom_copy_efi(struct tb_switch *sw, u16 *size) +{ + struct device *dev = &sw->tb->nhi->pdev->dev; + int len, res; + + len = device_property_read_u8_array(dev, "ThunderboltDROM", NULL, 0); + if (len < 0 || len < sizeof(struct tb_drom_header)) + return -EINVAL; + + sw->drom = kmalloc(len, GFP_KERNEL); + if (!sw->drom) + return -ENOMEM; + + res = device_property_read_u8_array(dev, "ThunderboltDROM", sw->drom, + len); + if (res) + goto err; + + *size = ((struct tb_drom_header *)sw->drom)->data_len + + TB_DROM_DATA_START; + if (*size > len) + goto err; + + return 0; + +err: + kfree(sw->drom); + sw->drom = NULL; + return -EINVAL; +} + +/** * tb_drom_read - copy drom to sw->drom and parse it */ int tb_drom_read(struct tb_switch *sw) @@ -374,6 +409,13 @@ int tb_drom_read(struct tb_switch *sw) if (tb_route(sw) == 0) { /* + * Apple's NHI EFI driver supplies a DROM for the root switch + * in a device property. Use it if available. + */ + if (tb_drom_copy_efi(sw, &size) == 0) + goto parse; + + /* * The root switch contains only a dummy drom (header only, * no entries). Hardcode the configuration here. */ @@ -418,6 +460,7 @@ int tb_drom_read(struct tb_switch *sw) if (res) goto err; +parse: header = (void *) sw->drom; if (header->data_len + TB_DROM_DATA_START != size) { diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 9840fdecb73b..c6f30b1695a9 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -460,7 +460,7 @@ int tb_switch_resume(struct tb_switch *sw) tb_sw_warn(sw, "uid read failed\n"); return err; } - if (sw->uid != uid) { + if (sw != sw->tb->root_switch && sw->uid != uid) { tb_sw_info(sw, "changed while suspended (uid %#llx -> %#llx)\n", sw->uid, uid); |