diff options
| -rw-r--r-- | drivers/acpi/ec.c | 31 | ||||
| -rw-r--r-- | drivers/acpi/scan.c | 70 |
2 files changed, 75 insertions, 26 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 3d304ff7f095..5f9b74b9b71f 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -126,6 +126,7 @@ static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */ | |||
| 126 | static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ | 126 | static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ |
| 127 | static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */ | 127 | static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */ |
| 128 | static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ | 128 | static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ |
| 129 | static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */ | ||
| 129 | 130 | ||
| 130 | /* -------------------------------------------------------------------------- | 131 | /* -------------------------------------------------------------------------- |
| 131 | * Transaction Management | 132 | * Transaction Management |
| @@ -236,13 +237,8 @@ static bool advance_transaction(struct acpi_ec *ec) | |||
| 236 | } | 237 | } |
| 237 | return wakeup; | 238 | return wakeup; |
| 238 | } else { | 239 | } else { |
| 239 | /* | 240 | if (EC_FLAGS_QUERY_HANDSHAKE && |
| 240 | * There is firmware refusing to respond QR_EC when SCI_EVT | 241 | !(status & ACPI_EC_FLAG_SCI) && |
| 241 | * is not set, for which case, we complete the QR_EC | ||
| 242 | * without issuing it to the firmware. | ||
| 243 | * https://bugzilla.kernel.org/show_bug.cgi?id=86211 | ||
| 244 | */ | ||
| 245 | if (!(status & ACPI_EC_FLAG_SCI) && | ||
| 246 | (t->command == ACPI_EC_COMMAND_QUERY)) { | 242 | (t->command == ACPI_EC_COMMAND_QUERY)) { |
| 247 | t->flags |= ACPI_EC_COMMAND_POLL; | 243 | t->flags |= ACPI_EC_COMMAND_POLL; |
| 248 | t->rdata[t->ri++] = 0x00; | 244 | t->rdata[t->ri++] = 0x00; |
| @@ -334,13 +330,13 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
| 334 | pr_debug("***** Command(%s) started *****\n", | 330 | pr_debug("***** Command(%s) started *****\n", |
| 335 | acpi_ec_cmd_string(t->command)); | 331 | acpi_ec_cmd_string(t->command)); |
| 336 | start_transaction(ec); | 332 | start_transaction(ec); |
| 337 | spin_unlock_irqrestore(&ec->lock, tmp); | ||
| 338 | ret = ec_poll(ec); | ||
| 339 | spin_lock_irqsave(&ec->lock, tmp); | ||
| 340 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { | 333 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { |
| 341 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | 334 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
| 342 | pr_debug("***** Event stopped *****\n"); | 335 | pr_debug("***** Event stopped *****\n"); |
| 343 | } | 336 | } |
| 337 | spin_unlock_irqrestore(&ec->lock, tmp); | ||
| 338 | ret = ec_poll(ec); | ||
| 339 | spin_lock_irqsave(&ec->lock, tmp); | ||
| 344 | pr_debug("***** Command(%s) stopped *****\n", | 340 | pr_debug("***** Command(%s) stopped *****\n", |
| 345 | acpi_ec_cmd_string(t->command)); | 341 | acpi_ec_cmd_string(t->command)); |
| 346 | ec->curr = NULL; | 342 | ec->curr = NULL; |
| @@ -1012,6 +1008,18 @@ static int ec_enlarge_storm_threshold(const struct dmi_system_id *id) | |||
| 1012 | } | 1008 | } |
| 1013 | 1009 | ||
| 1014 | /* | 1010 | /* |
| 1011 | * Acer EC firmware refuses to respond QR_EC when SCI_EVT is not set, for | ||
| 1012 | * which case, we complete the QR_EC without issuing it to the firmware. | ||
| 1013 | * https://bugzilla.kernel.org/show_bug.cgi?id=86211 | ||
| 1014 | */ | ||
| 1015 | static int ec_flag_query_handshake(const struct dmi_system_id *id) | ||
| 1016 | { | ||
| 1017 | pr_debug("Detected the EC firmware requiring QR_EC issued when SCI_EVT set\n"); | ||
| 1018 | EC_FLAGS_QUERY_HANDSHAKE = 1; | ||
| 1019 | return 0; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | /* | ||
| 1015 | * On some hardware it is necessary to clear events accumulated by the EC during | 1023 | * On some hardware it is necessary to clear events accumulated by the EC during |
| 1016 | * sleep. These ECs stop reporting GPEs until they are manually polled, if too | 1024 | * sleep. These ECs stop reporting GPEs until they are manually polled, if too |
| 1017 | * many events are accumulated. (e.g. Samsung Series 5/9 notebooks) | 1025 | * many events are accumulated. (e.g. Samsung Series 5/9 notebooks) |
| @@ -1085,6 +1093,9 @@ static struct dmi_system_id ec_dmi_table[] __initdata = { | |||
| 1085 | { | 1093 | { |
| 1086 | ec_clear_on_resume, "Samsung hardware", { | 1094 | ec_clear_on_resume, "Samsung hardware", { |
| 1087 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL}, | 1095 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL}, |
| 1096 | { | ||
| 1097 | ec_flag_query_handshake, "Acer hardware", { | ||
| 1098 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), }, NULL}, | ||
| 1088 | {}, | 1099 | {}, |
| 1089 | }; | 1100 | }; |
| 1090 | 1101 | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index d670158a26c5..0476e90b2091 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -142,6 +142,53 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | /* | 144 | /* |
| 145 | * acpi_companion_match() - Can we match via ACPI companion device | ||
| 146 | * @dev: Device in question | ||
| 147 | * | ||
| 148 | * Check if the given device has an ACPI companion and if that companion has | ||
| 149 | * a valid list of PNP IDs, and if the device is the first (primary) physical | ||
| 150 | * device associated with it. | ||
| 151 | * | ||
| 152 | * If multiple physical devices are attached to a single ACPI companion, we need | ||
| 153 | * to be careful. The usage scenario for this kind of relationship is that all | ||
| 154 | * of the physical devices in question use resources provided by the ACPI | ||
| 155 | * companion. A typical case is an MFD device where all the sub-devices share | ||
| 156 | * the parent's ACPI companion. In such cases we can only allow the primary | ||
| 157 | * (first) physical device to be matched with the help of the companion's PNP | ||
| 158 | * IDs. | ||
| 159 | * | ||
| 160 | * Additional physical devices sharing the ACPI companion can still use | ||
| 161 | * resources available from it but they will be matched normally using functions | ||
| 162 | * provided by their bus types (and analogously for their modalias). | ||
| 163 | */ | ||
| 164 | static bool acpi_companion_match(const struct device *dev) | ||
| 165 | { | ||
| 166 | struct acpi_device *adev; | ||
| 167 | bool ret; | ||
| 168 | |||
| 169 | adev = ACPI_COMPANION(dev); | ||
| 170 | if (!adev) | ||
| 171 | return false; | ||
| 172 | |||
| 173 | if (list_empty(&adev->pnp.ids)) | ||
| 174 | return false; | ||
| 175 | |||
| 176 | mutex_lock(&adev->physical_node_lock); | ||
| 177 | if (list_empty(&adev->physical_node_list)) { | ||
| 178 | ret = false; | ||
| 179 | } else { | ||
| 180 | const struct acpi_device_physical_node *node; | ||
| 181 | |||
| 182 | node = list_first_entry(&adev->physical_node_list, | ||
| 183 | struct acpi_device_physical_node, node); | ||
| 184 | ret = node->dev == dev; | ||
| 185 | } | ||
| 186 | mutex_unlock(&adev->physical_node_lock); | ||
| 187 | |||
| 188 | return ret; | ||
| 189 | } | ||
| 190 | |||
| 191 | /* | ||
| 145 | * Creates uevent modalias field for ACPI enumerated devices. | 192 | * Creates uevent modalias field for ACPI enumerated devices. |
| 146 | * Because the other buses does not support ACPI HIDs & CIDs. | 193 | * Because the other buses does not support ACPI HIDs & CIDs. |
| 147 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: | 194 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: |
| @@ -149,20 +196,14 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
| 149 | */ | 196 | */ |
| 150 | int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) | 197 | int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) |
| 151 | { | 198 | { |
| 152 | struct acpi_device *acpi_dev; | ||
| 153 | int len; | 199 | int len; |
| 154 | 200 | ||
| 155 | acpi_dev = ACPI_COMPANION(dev); | 201 | if (!acpi_companion_match(dev)) |
| 156 | if (!acpi_dev) | ||
| 157 | return -ENODEV; | ||
| 158 | |||
| 159 | /* Fall back to bus specific way of modalias exporting */ | ||
| 160 | if (list_empty(&acpi_dev->pnp.ids)) | ||
| 161 | return -ENODEV; | 202 | return -ENODEV; |
| 162 | 203 | ||
| 163 | if (add_uevent_var(env, "MODALIAS=")) | 204 | if (add_uevent_var(env, "MODALIAS=")) |
| 164 | return -ENOMEM; | 205 | return -ENOMEM; |
| 165 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], | 206 | len = create_modalias(ACPI_COMPANION(dev), &env->buf[env->buflen - 1], |
| 166 | sizeof(env->buf) - env->buflen); | 207 | sizeof(env->buf) - env->buflen); |
| 167 | if (len <= 0) | 208 | if (len <= 0) |
| 168 | return len; | 209 | return len; |
| @@ -179,18 +220,12 @@ EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias); | |||
| 179 | */ | 220 | */ |
| 180 | int acpi_device_modalias(struct device *dev, char *buf, int size) | 221 | int acpi_device_modalias(struct device *dev, char *buf, int size) |
| 181 | { | 222 | { |
| 182 | struct acpi_device *acpi_dev; | ||
| 183 | int len; | 223 | int len; |
| 184 | 224 | ||
| 185 | acpi_dev = ACPI_COMPANION(dev); | 225 | if (!acpi_companion_match(dev)) |
| 186 | if (!acpi_dev) | ||
| 187 | return -ENODEV; | 226 | return -ENODEV; |
| 188 | 227 | ||
| 189 | /* Fall back to bus specific way of modalias exporting */ | 228 | len = create_modalias(ACPI_COMPANION(dev), buf, size -1); |
| 190 | if (list_empty(&acpi_dev->pnp.ids)) | ||
| 191 | return -ENODEV; | ||
| 192 | |||
| 193 | len = create_modalias(acpi_dev, buf, size -1); | ||
| 194 | if (len <= 0) | 229 | if (len <= 0) |
| 195 | return len; | 230 | return len; |
| 196 | buf[len++] = '\n'; | 231 | buf[len++] = '\n'; |
| @@ -853,6 +888,9 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, | |||
| 853 | if (!ids || !handle || acpi_bus_get_device(handle, &adev)) | 888 | if (!ids || !handle || acpi_bus_get_device(handle, &adev)) |
| 854 | return NULL; | 889 | return NULL; |
| 855 | 890 | ||
| 891 | if (!acpi_companion_match(dev)) | ||
| 892 | return NULL; | ||
| 893 | |||
| 856 | return __acpi_match_device(adev, ids); | 894 | return __acpi_match_device(adev, ids); |
| 857 | } | 895 | } |
| 858 | EXPORT_SYMBOL_GPL(acpi_match_device); | 896 | EXPORT_SYMBOL_GPL(acpi_match_device); |
