已合并
6.0 CVE 漏洞 #306
何京晶创建于 3月5日
6.0 CVE 漏洞 #306
已合并
共 32 个文件变更+4956-4244
| @@ -221,3 +221,35 @@ static int __init sgi_ds1286_devinit(void) | |||
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | device_initcall(sgi_ds1286_devinit); | 223 | device_initcall(sgi_ds1286_devinit); |
| 224 | + | ||
| 225 | +#define SGI_ZILOG_BASE (HPC3_CHIP0_BASE + \ | ||
| 226 | + offsetof(struct hpc3_regs, pbus_extregs[6]) + \ | ||
| 227 | + offsetof(struct sgioc_regs, uart)) | ||
| 228 | + | ||
| 229 | +static struct resource sgi_zilog_resources[] = { | ||
| 230 | + { | ||
| 231 | + .start = SGI_ZILOG_BASE, | ||
| 232 | + .end = SGI_ZILOG_BASE + 15, | ||
| 233 | + .flags = IORESOURCE_MEM | ||
| 234 | + }, | ||
| 235 | + { | ||
| 236 | + .start = SGI_SERIAL_IRQ, | ||
| 237 | + .end = SGI_SERIAL_IRQ, | ||
| 238 | + .flags = IORESOURCE_IRQ | ||
| 239 | + } | ||
| 240 | +}; | ||
| 241 | + | ||
| 242 | +static struct platform_device zilog_device = { | ||
| 243 | + .name = "ip22zilog", | ||
| 244 | + .id = 0, | ||
| 245 | + .num_resources = ARRAY_SIZE(sgi_zilog_resources), | ||
| 246 | + .resource = sgi_zilog_resources, | ||
| 247 | +}; | ||
| 248 | + | ||
| 249 | + | ||
| 250 | +static int __init sgi_zilog_devinit(void) | ||
| 251 | +{ | ||
| 252 | + return platform_device_register(&zilog_device); | ||
| 253 | +} | ||
| 254 | + | ||
| 255 | +device_initcall(sgi_zilog_devinit); | ||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <asm/sclp.h> | 16 | #include <asm/sclp.h> |
| 17 | 17 | ||
| 18 | #include "pci_bus.h" | 18 | #include "pci_bus.h" |
| 19 | +#include "pci_report.h" | ||
| 19 | 20 | ||
| 20 | /* Content Code Description for PCI Function Error */ | 21 | /* Content Code Description for PCI Function Error */ |
| 21 | struct zpci_ccdf_err { | 22 | struct zpci_ccdf_err { |
| @@ -53,15 +54,23 @@ static inline bool ers_result_indicates_abort(pci_ers_result_t ers_res) | |||
| 53 | case PCI_ERS_RESULT_CAN_RECOVER: | 54 | case PCI_ERS_RESULT_CAN_RECOVER: |
| 54 | case PCI_ERS_RESULT_RECOVERED: | 55 | case PCI_ERS_RESULT_RECOVERED: |
| 55 | case PCI_ERS_RESULT_NEED_RESET: | 56 | case PCI_ERS_RESULT_NEED_RESET: |
| 57 | + case PCI_ERS_RESULT_NONE: | ||
| 56 | return false; | 58 | return false; |
| 57 | default: | 59 | default: |
| 58 | return true; | 60 | return true; |
| 59 | } | 61 | } |
| 60 | } | 62 | } |
| 61 | 63 | ||
| 62 | -static bool is_passed_through(struct zpci_dev *zdev) | 64 | +static bool is_passed_through(struct pci_dev *pdev) |
| 63 | { | 65 | { |
| 64 | - return zdev->s390_domain; | 66 | + struct zpci_dev *zdev = to_zpci(pdev); |
| 67 | + bool ret; | ||
| 68 | + | ||
| 69 | + mutex_lock(&zdev->kzdev_lock); | ||
| 70 | + ret = !!zdev->kzdev; | ||
| 71 | + mutex_unlock(&zdev->kzdev_lock); | ||
| 72 | + | ||
| 73 | + return ret; | ||
| 65 | } | 74 | } |
| 66 | 75 | ||
| 67 | static bool is_driver_supported(struct pci_driver *driver) | 76 | static bool is_driver_supported(struct pci_driver *driver) |
| @@ -70,10 +79,6 @@ static bool is_driver_supported(struct pci_driver *driver) | |||
| 70 | return false; | 79 | return false; |
| 71 | if (!driver->err_handler->error_detected) | 80 | if (!driver->err_handler->error_detected) |
| 72 | return false; | 81 | return false; |
| 73 | - if (!driver->err_handler->slot_reset) | ||
| 74 | - return false; | ||
| 75 | - if (!driver->err_handler->resume) | ||
| 76 | - return false; | ||
| 77 | return true; | 82 | return true; |
| 78 | } | 83 | } |
| 79 | 84 | ||
| @@ -83,6 +88,7 @@ static pci_ers_result_t zpci_event_notify_error_detected(struct pci_dev *pdev, | |||
| 83 | pci_ers_result_t ers_res = PCI_ERS_RESULT_DISCONNECT; | 88 | pci_ers_result_t ers_res = PCI_ERS_RESULT_DISCONNECT; |
| 84 | 89 | ||
| 85 | ers_res = driver->err_handler->error_detected(pdev, pdev->error_state); | 90 | ers_res = driver->err_handler->error_detected(pdev, pdev->error_state); |
| 91 | + pci_uevent_ers(pdev, ers_res); | ||
| 86 | if (ers_result_indicates_abort(ers_res)) | 92 | if (ers_result_indicates_abort(ers_res)) |
| 87 | pr_info("%s: Automatic recovery failed after initial reporting\n", pci_name(pdev)); | 93 | pr_info("%s: Automatic recovery failed after initial reporting\n", pci_name(pdev)); |
| 88 | else if (ers_res == PCI_ERS_RESULT_NEED_RESET) | 94 | else if (ers_res == PCI_ERS_RESULT_NEED_RESET) |
| @@ -110,16 +116,18 @@ static pci_ers_result_t zpci_event_do_error_state_clear(struct pci_dev *pdev, | |||
| 110 | return PCI_ERS_RESULT_NEED_RESET; | 116 | return PCI_ERS_RESULT_NEED_RESET; |
| 111 | } | 117 | } |
| 112 | 118 | ||
| 113 | - if (driver->err_handler->mmio_enabled) { | 119 | + if (driver->err_handler->mmio_enabled) |
| 114 | ers_res = driver->err_handler->mmio_enabled(pdev); | 120 | ers_res = driver->err_handler->mmio_enabled(pdev); |
| 115 | - if (ers_result_indicates_abort(ers_res)) { | 121 | + else |
| 116 | - pr_info("%s: Automatic recovery failed after MMIO re-enable\n", | 122 | + ers_res = PCI_ERS_RESULT_NONE; |
| 117 | - pci_name(pdev)); | 123 | + |
| 118 | - return ers_res; | 124 | + if (ers_result_indicates_abort(ers_res)) { |
| 119 | - } else if (ers_res == PCI_ERS_RESULT_NEED_RESET) { | 125 | + pr_info("%s: Automatic recovery failed after MMIO re-enable\n", |
| 120 | - pr_debug("%s: Driver needs reset to recover\n", pci_name(pdev)); | 126 | + pci_name(pdev)); |
| 121 | - return ers_res; | 127 | + return ers_res; |
| 122 | - } | 128 | + } else if (ers_res == PCI_ERS_RESULT_NEED_RESET) { |
| 129 | + pr_debug("%s: Driver needs reset to recover\n", pci_name(pdev)); | ||
| 130 | + return ers_res; | ||
| 123 | } | 131 | } |
| 124 | 132 | ||
| 125 | pr_debug("%s: Unblocking DMA\n", pci_name(pdev)); | 133 | pr_debug("%s: Unblocking DMA\n", pci_name(pdev)); |
| @@ -146,7 +154,12 @@ static pci_ers_result_t zpci_event_do_reset(struct pci_dev *pdev, | |||
| 146 | return ers_res; | 154 | return ers_res; |
| 147 | } | 155 | } |
| 148 | pdev->error_state = pci_channel_io_normal; | 156 | pdev->error_state = pci_channel_io_normal; |
| 149 | - ers_res = driver->err_handler->slot_reset(pdev); | 157 | + |
| 158 | + if (driver->err_handler->slot_reset) | ||
| 159 | + ers_res = driver->err_handler->slot_reset(pdev); | ||
| 160 | + else | ||
| 161 | + ers_res = PCI_ERS_RESULT_NONE; | ||
| 162 | + | ||
| 150 | if (ers_result_indicates_abort(ers_res)) { | 163 | if (ers_result_indicates_abort(ers_res)) { |
| 151 | pr_info("%s: Automatic recovery failed after slot reset\n", pci_name(pdev)); | 164 | pr_info("%s: Automatic recovery failed after slot reset\n", pci_name(pdev)); |
| 152 | return ers_res; | 165 | return ers_res; |
| @@ -166,6 +179,8 @@ static pci_ers_result_t zpci_event_do_reset(struct pci_dev *pdev, | |||
| 166 | static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev) | 179 | static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev) |
| 167 | { | 180 | { |
| 168 | pci_ers_result_t ers_res = PCI_ERS_RESULT_DISCONNECT; | 181 | pci_ers_result_t ers_res = PCI_ERS_RESULT_DISCONNECT; |
| 182 | + struct zpci_dev *zdev = to_zpci(pdev); | ||
| 183 | + char *status_str = "success"; | ||
| 169 | struct pci_driver *driver; | 184 | struct pci_driver *driver; |
| 170 | 185 | ||
| 171 | /* | 186 | /* |
| @@ -173,55 +188,77 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev) | |||
| 173 | * is unbound or probed and that userspace can't access its | 188 | * is unbound or probed and that userspace can't access its |
| 174 | * configuration space while we perform recovery. | 189 | * configuration space while we perform recovery. |
| 175 | */ | 190 | */ |
| 176 | - pci_dev_lock(pdev); | 191 | + device_lock(&pdev->dev); |
| 177 | if (pdev->error_state == pci_channel_io_perm_failure) { | 192 | if (pdev->error_state == pci_channel_io_perm_failure) { |
| 178 | ers_res = PCI_ERS_RESULT_DISCONNECT; | 193 | ers_res = PCI_ERS_RESULT_DISCONNECT; |
| 179 | goto out_unlock; | 194 | goto out_unlock; |
| 180 | } | 195 | } |
| 181 | pdev->error_state = pci_channel_io_frozen; | 196 | pdev->error_state = pci_channel_io_frozen; |
| 182 | 197 | ||
| 183 | - if (is_passed_through(to_zpci(pdev))) { | 198 | + if (is_passed_through(pdev)) { |
| 184 | pr_info("%s: Cannot be recovered in the host because it is a pass-through device\n", | 199 | pr_info("%s: Cannot be recovered in the host because it is a pass-through device\n", |
| 185 | pci_name(pdev)); | 200 | pci_name(pdev)); |
| 201 | + status_str = "failed (pass-through)"; | ||
| 186 | goto out_unlock; | 202 | goto out_unlock; |
| 187 | } | 203 | } |
| 188 | 204 | ||
| 189 | driver = to_pci_driver(pdev->dev.driver); | 205 | driver = to_pci_driver(pdev->dev.driver); |
| 190 | if (!is_driver_supported(driver)) { | 206 | if (!is_driver_supported(driver)) { |
| 191 | - if (!driver) | 207 | + if (!driver) { |
| 192 | pr_info("%s: Cannot be recovered because no driver is bound to the device\n", | 208 | pr_info("%s: Cannot be recovered because no driver is bound to the device\n", |
| 193 | pci_name(pdev)); | 209 | pci_name(pdev)); |
| 194 | - else | 210 | + status_str = "failed (no driver)"; |
| 211 | + } else { | ||
| 195 | pr_info("%s: The %s driver bound to the device does not support error recovery\n", | 212 | pr_info("%s: The %s driver bound to the device does not support error recovery\n", |
| 196 | pci_name(pdev), | 213 | pci_name(pdev), |
| 197 | driver->name); | 214 | driver->name); |
| 215 | + status_str = "failed (no driver support)"; | ||
| 216 | + } | ||
| 198 | goto out_unlock; | 217 | goto out_unlock; |
| 199 | } | 218 | } |
| 200 | 219 | ||
| 201 | ers_res = zpci_event_notify_error_detected(pdev, driver); | 220 | ers_res = zpci_event_notify_error_detected(pdev, driver); |
| 202 | - if (ers_result_indicates_abort(ers_res)) | 221 | + if (ers_result_indicates_abort(ers_res)) { |
| 222 | + status_str = "failed (abort on detection)"; | ||
| 203 | goto out_unlock; | 223 | goto out_unlock; |
| 224 | + } | ||
| 204 | 225 | ||
| 205 | - if (ers_res == PCI_ERS_RESULT_CAN_RECOVER) { | 226 | + if (ers_res != PCI_ERS_RESULT_NEED_RESET) { |
| 206 | ers_res = zpci_event_do_error_state_clear(pdev, driver); | 227 | ers_res = zpci_event_do_error_state_clear(pdev, driver); |
| 207 | - if (ers_result_indicates_abort(ers_res)) | 228 | + if (ers_result_indicates_abort(ers_res)) { |
| 229 | + status_str = "failed (abort on MMIO enable)"; | ||
| 208 | goto out_unlock; | 230 | goto out_unlock; |
| 231 | + } | ||
| 209 | } | 232 | } |
| 210 | 233 | ||
| 211 | if (ers_res == PCI_ERS_RESULT_NEED_RESET) | 234 | if (ers_res == PCI_ERS_RESULT_NEED_RESET) |
| 212 | ers_res = zpci_event_do_reset(pdev, driver); | 235 | ers_res = zpci_event_do_reset(pdev, driver); |
| 213 | 236 | ||
| 237 | + /* | ||
| 238 | + * ers_res can be PCI_ERS_RESULT_NONE either because the driver | ||
| 239 | + * decided to return it, indicating that it abstains from voting | ||
| 240 | + * on how to recover, or because it didn't implement the callback. | ||
| 241 | + * Both cases assume, that if there is nothing else causing a | ||
| 242 | + * disconnect, we recovered successfully. | ||
| 243 | + */ | ||
| 244 | + if (ers_res == PCI_ERS_RESULT_NONE) | ||
| 245 | + ers_res = PCI_ERS_RESULT_RECOVERED; | ||
| 246 | + | ||
| 214 | if (ers_res != PCI_ERS_RESULT_RECOVERED) { | 247 | if (ers_res != PCI_ERS_RESULT_RECOVERED) { |
| 248 | + pci_uevent_ers(pdev, PCI_ERS_RESULT_DISCONNECT); | ||
| 215 | pr_err("%s: Automatic recovery failed; operator intervention is required\n", | 249 | pr_err("%s: Automatic recovery failed; operator intervention is required\n", |
| 216 | pci_name(pdev)); | 250 | pci_name(pdev)); |
| 251 | + status_str = "failed (driver can't recover)"; | ||
| 217 | goto out_unlock; | 252 | goto out_unlock; |
| 218 | } | 253 | } |
| 219 | 254 | ||
| 220 | pr_info("%s: The device is ready to resume operations\n", pci_name(pdev)); | 255 | pr_info("%s: The device is ready to resume operations\n", pci_name(pdev)); |
| 221 | if (driver->err_handler->resume) | 256 | if (driver->err_handler->resume) |
| 222 | driver->err_handler->resume(pdev); | 257 | driver->err_handler->resume(pdev); |
| 258 | + pci_uevent_ers(pdev, PCI_ERS_RESULT_RECOVERED); | ||
| 223 | out_unlock: | 259 | out_unlock: |
| 224 | - pci_dev_unlock(pdev); | 260 | + device_unlock(&pdev->dev); |
| 261 | + zpci_report_status(zdev, "recovery", status_str); | ||
| 225 | 262 | ||
| 226 | return ers_res; | 263 | return ers_res; |
| 227 | } | 264 | } |
| @@ -243,7 +280,7 @@ static void zpci_event_io_failure(struct pci_dev *pdev, pci_channel_state_t es) | |||
| 243 | * we will inject the error event and let the guest recover the device | 280 | * we will inject the error event and let the guest recover the device |
| 244 | * itself. | 281 | * itself. |
| 245 | */ | 282 | */ |
| 246 | - if (is_passed_through(to_zpci(pdev))) | 283 | + if (is_passed_through(pdev)) |
| 247 | goto out; | 284 | goto out; |
| 248 | driver = to_pci_driver(pdev->dev.driver); | 285 | driver = to_pci_driver(pdev->dev.driver); |
| 249 | if (driver && driver->err_handler && driver->err_handler->error_detected) | 286 | if (driver && driver->err_handler && driver->err_handler->error_detected) |
| @@ -257,6 +294,8 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf) | |||
| 257 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); | 294 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); |
| 258 | struct pci_dev *pdev = NULL; | 295 | struct pci_dev *pdev = NULL; |
| 259 | pci_ers_result_t ers_res; | 296 | pci_ers_result_t ers_res; |
| 297 | + u32 fh = 0; | ||
| 298 | + int rc; | ||
| 260 | 299 | ||
| 261 | zpci_dbg(3, "err fid:%x, fh:%x, pec:%x\n", | 300 | zpci_dbg(3, "err fid:%x, fh:%x, pec:%x\n", |
| 262 | ccdf->fid, ccdf->fh, ccdf->pec); | 301 | ccdf->fid, ccdf->fh, ccdf->pec); |
| @@ -264,6 +303,16 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf) | |||
| 264 | zpci_err_hex(ccdf, sizeof(*ccdf)); | 303 | zpci_err_hex(ccdf, sizeof(*ccdf)); |
| 265 | 304 | ||
| 266 | if (zdev) { | 305 | if (zdev) { |
| 306 | + mutex_lock(&zdev->state_lock); | ||
| 307 | + rc = clp_refresh_fh(zdev->fid, &fh); | ||
| 308 | + if (rc) | ||
| 309 | + goto no_pdev; | ||
| 310 | + if (!fh || ccdf->fh != fh) { | ||
| 311 | + /* Ignore events with stale handles */ | ||
| 312 | + zpci_dbg(3, "err fid:%x, fh:%x (stale %x)\n", | ||
| 313 | + ccdf->fid, fh, ccdf->fh); | ||
| 314 | + goto no_pdev; | ||
| 315 | + } | ||
| 267 | zpci_update_fh(zdev, ccdf->fh); | 316 | zpci_update_fh(zdev, ccdf->fh); |
| 268 | if (zdev->zbus->bus) | 317 | if (zdev->zbus->bus) |
| 269 | pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn); | 318 | pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn); |
| @@ -292,6 +341,8 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf) | |||
| 292 | } | 341 | } |
| 293 | pci_dev_put(pdev); | 342 | pci_dev_put(pdev); |
| 294 | no_pdev: | 343 | no_pdev: |
| 344 | + if (zdev) | ||
| 345 | + mutex_unlock(&zdev->state_lock); | ||
| 295 | zpci_zdev_put(zdev); | 346 | zpci_zdev_put(zdev); |
| 296 | } | 347 | } |
| 297 | 348 | ||
| @@ -311,13 +362,27 @@ static void zpci_event_hard_deconfigured(struct zpci_dev *zdev, u32 fh) | |||
| 311 | /* Even though the device is already gone we still | 362 | /* Even though the device is already gone we still |
| 312 | * need to free zPCI resources as part of the disable. | 363 | * need to free zPCI resources as part of the disable. |
| 313 | */ | 364 | */ |
| 314 | - if (zdev->dma_table) | ||
| 315 | - zpci_dma_exit_device(zdev); | ||
| 316 | if (zdev_enabled(zdev)) | 365 | if (zdev_enabled(zdev)) |
| 317 | zpci_disable_device(zdev); | 366 | zpci_disable_device(zdev); |
| 318 | zdev->state = ZPCI_FN_STATE_STANDBY; | 367 | zdev->state = ZPCI_FN_STATE_STANDBY; |
| 319 | } | 368 | } |
| 320 | 369 | ||
| 370 | +static void zpci_event_reappear(struct zpci_dev *zdev) | ||
| 371 | +{ | ||
| 372 | + lockdep_assert_held(&zdev->state_lock); | ||
| 373 | + /* | ||
| 374 | + * The zdev is in the reserved state. This means that it was presumed to | ||
| 375 | + * go away but there are still undropped references. Now, the platform | ||
| 376 | + * announced its availability again. Bring back the lingering zdev | ||
| 377 | + * to standby. This is safe because we hold a temporary reference | ||
| 378 | + * now so that it won't go away. Account for the re-appearance of the | ||
| 379 | + * underlying device by incrementing the reference count. | ||
| 380 | + */ | ||
| 381 | + zdev->state = ZPCI_FN_STATE_STANDBY; | ||
| 382 | + zpci_zdev_get(zdev); | ||
| 383 | + zpci_dbg(1, "rea fid:%x, fh:%x\n", zdev->fid, zdev->fh); | ||
| 384 | +} | ||
| 385 | + | ||
| 321 | static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) | 386 | static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) |
| 322 | { | 387 | { |
| 323 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); | 388 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); |
| @@ -326,29 +391,48 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) | |||
| 326 | 391 | ||
| 327 | zpci_dbg(3, "avl fid:%x, fh:%x, pec:%x\n", | 392 | zpci_dbg(3, "avl fid:%x, fh:%x, pec:%x\n", |
| 328 | ccdf->fid, ccdf->fh, ccdf->pec); | 393 | ccdf->fid, ccdf->fh, ccdf->pec); |
| 394 | + | ||
| 395 | + if (existing_zdev) | ||
| 396 | + mutex_lock(&zdev->state_lock); | ||
| 397 | + | ||
| 329 | switch (ccdf->pec) { | 398 | switch (ccdf->pec) { |
| 330 | case 0x0301: /* Reserved|Standby -> Configured */ | 399 | case 0x0301: /* Reserved|Standby -> Configured */ |
| 331 | if (!zdev) { | 400 | if (!zdev) { |
| 332 | zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_CONFIGURED); | 401 | zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_CONFIGURED); |
| 333 | if (IS_ERR(zdev)) | 402 | if (IS_ERR(zdev)) |
| 334 | break; | 403 | break; |
| 404 | + if (zpci_add_device(zdev)) { | ||
| 405 | + kfree(zdev); | ||
| 406 | + break; | ||
| 407 | + } | ||
| 335 | } else { | 408 | } else { |
| 409 | + if (zdev->state == ZPCI_FN_STATE_RESERVED) | ||
| 410 | + zpci_event_reappear(zdev); | ||
| 336 | /* the configuration request may be stale */ | 411 | /* the configuration request may be stale */ |
| 337 | - if (zdev->state != ZPCI_FN_STATE_STANDBY) | 412 | + else if (zdev->state != ZPCI_FN_STATE_STANDBY) |
| 338 | break; | 413 | break; |
| 339 | zdev->state = ZPCI_FN_STATE_CONFIGURED; | 414 | zdev->state = ZPCI_FN_STATE_CONFIGURED; |
| 340 | } | 415 | } |
| 341 | zpci_scan_configured_device(zdev, ccdf->fh); | 416 | zpci_scan_configured_device(zdev, ccdf->fh); |
| 342 | break; | 417 | break; |
| 343 | case 0x0302: /* Reserved -> Standby */ | 418 | case 0x0302: /* Reserved -> Standby */ |
| 344 | - if (!zdev) | 419 | + if (!zdev) { |
| 345 | - zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY); | 420 | + zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY); |
| 346 | - else | 421 | + if (IS_ERR(zdev)) |
| 422 | + break; | ||
| 423 | + if (zpci_add_device(zdev)) { | ||
| 424 | + kfree(zdev); | ||
| 425 | + break; | ||
| 426 | + } | ||
| 427 | + } else { | ||
| 428 | + if (zdev->state == ZPCI_FN_STATE_RESERVED) | ||
| 429 | + zpci_event_reappear(zdev); | ||
| 347 | zpci_update_fh(zdev, ccdf->fh); | 430 | zpci_update_fh(zdev, ccdf->fh); |
| 431 | + } | ||
| 348 | break; | 432 | break; |
| 349 | case 0x0303: /* Deconfiguration requested */ | 433 | case 0x0303: /* Deconfiguration requested */ |
| 350 | if (zdev) { | 434 | if (zdev) { |
| 351 | - /* The event may have been queued before we confirgured | 435 | + /* The event may have been queued before we configured |
| 352 | * the device. | 436 | * the device. |
| 353 | */ | 437 | */ |
| 354 | if (zdev->state != ZPCI_FN_STATE_CONFIGURED) | 438 | if (zdev->state != ZPCI_FN_STATE_CONFIGURED) |
| @@ -359,7 +443,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) | |||
| 359 | break; | 443 | break; |
| 360 | case 0x0304: /* Configured -> Standby|Reserved */ | 444 | case 0x0304: /* Configured -> Standby|Reserved */ |
| 361 | if (zdev) { | 445 | if (zdev) { |
| 362 | - /* The event may have been queued before we confirgured | 446 | + /* The event may have been queued before we configured |
| 363 | * the device.: | 447 | * the device.: |
| 364 | */ | 448 | */ |
| 365 | if (zdev->state == ZPCI_FN_STATE_CONFIGURED) | 449 | if (zdev->state == ZPCI_FN_STATE_CONFIGURED) |
| @@ -373,7 +457,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) | |||
| 373 | break; | 457 | break; |
| 374 | case 0x0306: /* 0x308 or 0x302 for multiple devices */ | 458 | case 0x0306: /* 0x308 or 0x302 for multiple devices */ |
| 375 | zpci_remove_reserved_devices(); | 459 | zpci_remove_reserved_devices(); |
| 376 | - clp_scan_pci_devices(); | 460 | + zpci_scan_devices(); |
| 377 | break; | 461 | break; |
| 378 | case 0x0308: /* Standby -> Reserved */ | 462 | case 0x0308: /* Standby -> Reserved */ |
| 379 | if (!zdev) | 463 | if (!zdev) |
| @@ -383,8 +467,10 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) | |||
| 383 | default: | 467 | default: |
| 384 | break; | 468 | break; |
| 385 | } | 469 | } |
| 386 | - if (existing_zdev) | 470 | + if (existing_zdev) { |
| 471 | + mutex_unlock(&zdev->state_lock); | ||
| 387 | zpci_zdev_put(zdev); | 472 | zpci_zdev_put(zdev); |
| 473 | + } | ||
| 388 | } | 474 | } |
| 389 | 475 | ||
| 390 | void zpci_event_availability(void *data) | 476 | void zpci_event_availability(void *data) |
| @@ -14,7 +14,7 @@ | |||
| 14 | * memory ranges: uncached, write-combining, write-through, write-protected, | 14 | * memory ranges: uncached, write-combining, write-through, write-protected, |
| 15 | * and the most commonly used and default attribute: write-back caching. | 15 | * and the most commonly used and default attribute: write-back caching. |
| 16 | * | 16 | * |
| 17 | - * PAT support supercedes and augments MTRR support in a compatible fashion: MTRR is | 17 | + * PAT support supersedes and augments MTRR support in a compatible fashion: MTRR is |
| 18 | * a hardware interface to enumerate a limited number of physical memory ranges | 18 | * a hardware interface to enumerate a limited number of physical memory ranges |
| 19 | * and set their caching attributes explicitly, programmed into the CPU via MSRs. | 19 | * and set their caching attributes explicitly, programmed into the CPU via MSRs. |
| 20 | * Even modern CPUs have MTRRs enabled - but these are typically not touched | 20 | * Even modern CPUs have MTRRs enabled - but these are typically not touched |
| @@ -240,6 +240,8 @@ void pat_cpu_init(void) | |||
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | wrmsrl(MSR_IA32_CR_PAT, pat_msr_val); | 242 | wrmsrl(MSR_IA32_CR_PAT, pat_msr_val); |
| 243 | + | ||
| 244 | + __flush_tlb_all(); | ||
| 243 | } | 245 | } |
| 244 | 246 | ||
| 245 | /** | 247 | /** |
| @@ -296,13 +298,8 @@ void __init pat_bp_init(void) | |||
| 296 | /* | 298 | /* |
| 297 | * Xen PV doesn't allow to set PAT MSR, but all cache modes are | 299 | * Xen PV doesn't allow to set PAT MSR, but all cache modes are |
| 298 | * supported. | 300 | * supported. |
| 299 | - * When running as TDX guest setting the PAT MSR won't work either | ||
| 300 | - * due to the requirement to set CR0.CD when doing so. Rely on | ||
| 301 | - * firmware to have set the PAT MSR correctly. | ||
| 302 | */ | 301 | */ |
| 303 | - if (pat_disabled || | 302 | + if (pat_disabled || cpu_feature_enabled(X86_FEATURE_XENPV)) { |
| 304 | - cpu_feature_enabled(X86_FEATURE_XENPV) || | ||
| 305 | - cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) { | ||
| 306 | init_cache_modes(pat_msr_val); | 303 | init_cache_modes(pat_msr_val); |
| 307 | return; | 304 | return; |
| 308 | } | 305 | } |
| @@ -982,42 +979,29 @@ static int get_pat_info(struct vm_area_struct *vma, resource_size_t *paddr, | |||
| 982 | return -EINVAL; | 979 | return -EINVAL; |
| 983 | } | 980 | } |
| 984 | 981 | ||
| 985 | -int track_pfn_copy(struct vm_area_struct *dst_vma, | 982 | +/* |
| 986 | - struct vm_area_struct *src_vma, unsigned long *pfn) | 983 | + * track_pfn_copy is called when vma that is covering the pfnmap gets |
| 984 | + * copied through copy_page_range(). | ||
| 985 | + * | ||
| 986 | + * If the vma has a linear pfn mapping for the entire range, we get the prot | ||
| 987 | + * from pte and reserve the entire vma range with single reserve_pfn_range call. | ||
| 988 | + */ | ||
| 989 | +int track_pfn_copy(struct vm_area_struct *vma) | ||
| 987 | { | 990 | { |
| 988 | - const unsigned long vma_size = src_vma->vm_end - src_vma->vm_start; | ||
| 989 | resource_size_t paddr; | 991 | resource_size_t paddr; |
| 992 | + unsigned long vma_size = vma->vm_end - vma->vm_start; | ||
| 990 | pgprot_t pgprot; | 993 | pgprot_t pgprot; |
| 991 | - int rc; | ||
| 992 | 994 | ||
| 993 | - if (!(src_vma->vm_flags & VM_PAT)) | 995 | + if (vma->vm_flags & VM_PAT) { |
| 994 | - return 0; | 996 | + if (get_pat_info(vma, &paddr, &pgprot)) |
| 997 | + return -EINVAL; | ||
| 998 | + /* reserve the whole chunk covered by vma. */ | ||
| 999 | + return reserve_pfn_range(paddr, vma_size, &pgprot, 1); | ||
| 1000 | + } | ||
| 995 | 1001 | ||
| 996 | - /* | ||
| 997 | - * Duplicate the PAT information for the dst VMA based on the src | ||
| 998 | - * VMA. | ||
| 999 | - */ | ||
| 1000 | - if (get_pat_info(src_vma, &paddr, &pgprot)) | ||
| 1001 | - return -EINVAL; | ||
| 1002 | - rc = reserve_pfn_range(paddr, vma_size, &pgprot, 1); | ||
| 1003 | - if (rc) | ||
| 1004 | - return rc; | ||
| 1005 | - | ||
| 1006 | - /* Reservation for the destination VMA succeeded. */ | ||
| 1007 | - vm_flags_set(dst_vma, VM_PAT); | ||
| 1008 | - *pfn = PHYS_PFN(paddr); | ||
| 1009 | return 0; | 1002 | return 0; |
| 1010 | } | 1003 | } |
| 1011 | 1004 | ||
| 1012 | -void untrack_pfn_copy(struct vm_area_struct *dst_vma, unsigned long pfn) | ||
| 1013 | -{ | ||
| 1014 | - untrack_pfn(dst_vma, pfn, dst_vma->vm_end - dst_vma->vm_start, true); | ||
| 1015 | - /* | ||
| 1016 | - * Reservation was freed, any copied page tables will get cleaned | ||
| 1017 | - * up later, but without getting PAT involved again. | ||
| 1018 | - */ | ||
| 1019 | -} | ||
| 1020 | - | ||
| 1021 | /* | 1005 | /* |
| 1022 | * prot is passed in as a parameter for the new mapping. If the vma has | 1006 | * prot is passed in as a parameter for the new mapping. If the vma has |
| 1023 | * a linear pfn mapping for the entire range, or no vma is provided, | 1007 | * a linear pfn mapping for the entire range, or no vma is provided, |
| @@ -1106,6 +1090,15 @@ void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn, | |||
| 1106 | } | 1090 | } |
| 1107 | } | 1091 | } |
| 1108 | 1092 | ||
| 1093 | +/* | ||
| 1094 | + * untrack_pfn_clear is called if the following situation fits: | ||
| 1095 | + * | ||
| 1096 | + * 1) while mremapping a pfnmap for a new region, with the old vma after | ||
| 1097 | + * its pfnmap page table has been removed. The new vma has a new pfnmap | ||
| 1098 | + * to the same pfn & cache type with VM_PAT set. | ||
| 1099 | + * 2) while duplicating vm area, the new vma fails to copy the pgtable from | ||
| 1100 | + * old vma. | ||
| 1101 | + */ | ||
| 1109 | void untrack_pfn_clear(struct vm_area_struct *vma) | 1102 | void untrack_pfn_clear(struct vm_area_struct *vma) |
| 1110 | { | 1103 | { |
| 1111 | vm_flags_clear(vma, VM_PAT); | 1104 | vm_flags_clear(vma, VM_PAT); |
| @@ -574,7 +574,7 @@ static u_long get_word(struct vc_data *vc) | |||
| 574 | } | 574 | } |
| 575 | attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr); | 575 | attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr); |
| 576 | buf[cnt++] = attr_ch; | 576 | buf[cnt++] = attr_ch; |
| 577 | - while (tmpx < vc->vc_cols - 1 && cnt < ARRAY_SIZE(buf) - 1) { | 577 | + while (tmpx < vc->vc_cols - 1 && cnt < sizeof(buf) - 1) { |
| 578 | tmp_pos += 2; | 578 | tmp_pos += 2; |
| 579 | tmpx++; | 579 | tmpx++; |
| 580 | ch = get_char(vc, (u_short *)tmp_pos, &temp); | 580 | ch = get_char(vc, (u_short *)tmp_pos, &temp); |
| @@ -601,8 +601,6 @@ static struct aspeed_acry_alg aspeed_acry_akcipher_algs[] = { | |||
| 601 | .akcipher.base = { | 601 | .akcipher.base = { |
| 602 | .encrypt = aspeed_acry_rsa_enc, | 602 | .encrypt = aspeed_acry_rsa_enc, |
| 603 | .decrypt = aspeed_acry_rsa_dec, | 603 | .decrypt = aspeed_acry_rsa_dec, |
| 604 | - .sign = aspeed_acry_rsa_dec, | ||
| 605 | - .verify = aspeed_acry_rsa_enc, | ||
| 606 | .set_pub_key = aspeed_acry_rsa_set_pub_key, | 604 | .set_pub_key = aspeed_acry_rsa_set_pub_key, |
| 607 | .set_priv_key = aspeed_acry_rsa_set_priv_key, | 605 | .set_priv_key = aspeed_acry_rsa_set_priv_key, |
| 608 | .max_size = aspeed_acry_rsa_max_size, | 606 | .max_size = aspeed_acry_rsa_max_size, |
| @@ -789,21 +787,17 @@ static int aspeed_acry_probe(struct platform_device *pdev) | |||
| 789 | err_engine_rsa_start: | 787 | err_engine_rsa_start: |
| 790 | crypto_engine_exit(acry_dev->crypt_engine_rsa); | 788 | crypto_engine_exit(acry_dev->crypt_engine_rsa); |
| 791 | clk_exit: | 789 | clk_exit: |
| 792 | - clk_disable_unprepare(acry_dev->clk); | ||
| 793 | 790 | ||
| 794 | return rc; | 791 | return rc; |
| 795 | } | 792 | } |
| 796 | 793 | ||
| 797 | -static int aspeed_acry_remove(struct platform_device *pdev) | 794 | +static void aspeed_acry_remove(struct platform_device *pdev) |
| 798 | { | 795 | { |
| 799 | struct aspeed_acry_dev *acry_dev = platform_get_drvdata(pdev); | 796 | struct aspeed_acry_dev *acry_dev = platform_get_drvdata(pdev); |
| 800 | 797 | ||
| 801 | aspeed_acry_unregister(acry_dev); | 798 | aspeed_acry_unregister(acry_dev); |
| 802 | crypto_engine_exit(acry_dev->crypt_engine_rsa); | 799 | crypto_engine_exit(acry_dev->crypt_engine_rsa); |
| 803 | tasklet_kill(&acry_dev->done_task); | 800 | tasklet_kill(&acry_dev->done_task); |
| 804 | - clk_disable_unprepare(acry_dev->clk); | ||
| 805 | - | ||
| 806 | - return 0; | ||
| 807 | } | 801 | } |
| 808 | 802 | ||
| 809 | MODULE_DEVICE_TABLE(of, aspeed_acry_of_matches); | 803 | MODULE_DEVICE_TABLE(of, aspeed_acry_of_matches); |
| @@ -32,7 +32,7 @@ | |||
| 32 | #include <linux/atomic.h> | 32 | #include <linux/atomic.h> |
| 33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
| 34 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
| 35 | -#include <linux/kfd_ioctl.h> | 35 | +#include <uapi/linux/kfd_ioctl.h> |
| 36 | #include <linux/idr.h> | 36 | #include <linux/idr.h> |
| 37 | #include <linux/kfifo.h> | 37 | #include <linux/kfifo.h> |
| 38 | #include <linux/seq_file.h> | 38 | #include <linux/seq_file.h> |
| @@ -99,11 +99,11 @@ | |||
| 99 | /* | 99 | /* |
| 100 | * Size of the per-process TBA+TMA buffer: 2 pages | 100 | * Size of the per-process TBA+TMA buffer: 2 pages |
| 101 | * | 101 | * |
| 102 | - * The first page is the TBA used for the CWSR ISA code. The second | 102 | + * The first chunk is the TBA used for the CWSR ISA code. The second |
| 103 | - * page is used as TMA for user-mode trap handler setup in daisy-chain mode. | 103 | + * chunk is used as TMA for user-mode trap handler setup in daisy-chain mode. |
| 104 | */ | 104 | */ |
| 105 | #define KFD_CWSR_TBA_TMA_SIZE (PAGE_SIZE * 2) | 105 | #define KFD_CWSR_TBA_TMA_SIZE (PAGE_SIZE * 2) |
| 106 | -#define KFD_CWSR_TMA_OFFSET PAGE_SIZE | 106 | +#define KFD_CWSR_TMA_OFFSET (PAGE_SIZE + 2048) |
| 107 | 107 | ||
| 108 | #define KFD_MAX_NUM_OF_QUEUES_PER_DEVICE \ | 108 | #define KFD_MAX_NUM_OF_QUEUES_PER_DEVICE \ |
| 109 | (KFD_MAX_NUM_OF_PROCESSES * \ | 109 | (KFD_MAX_NUM_OF_PROCESSES * \ |
| @@ -111,7 +111,14 @@ | |||
| 111 | 111 | ||
| 112 | #define KFD_KERNEL_QUEUE_SIZE 2048 | 112 | #define KFD_KERNEL_QUEUE_SIZE 2048 |
| 113 | 113 | ||
| 114 | -#define KFD_UNMAP_LATENCY_MS (4000) | 114 | +/* KFD_UNMAP_LATENCY_MS is the timeout CP waiting for SDMA preemption. One XCC |
| 115 | + * can be associated to 2 SDMA engines. queue_preemption_timeout_ms is the time | ||
| 116 | + * driver waiting for CP returning the UNMAP_QUEUE fence. Thus the math is | ||
| 117 | + * queue_preemption_timeout_ms = sdma_preemption_time * 2 + cp workload | ||
| 118 | + * The format here makes CP workload 10% of total timeout | ||
| 119 | + */ | ||
| 120 | +#define KFD_UNMAP_LATENCY_MS \ | ||
| 121 | + ((queue_preemption_timeout_ms - queue_preemption_timeout_ms / 10) >> 1) | ||
| 115 | 122 | ||
| 116 | #define KFD_MAX_SDMA_QUEUES 128 | 123 | #define KFD_MAX_SDMA_QUEUES 128 |
| 117 | 124 | ||
| @@ -202,11 +209,13 @@ enum cache_policy { | |||
| 202 | cache_policy_noncoherent | 209 | cache_policy_noncoherent |
| 203 | }; | 210 | }; |
| 204 | 211 | ||
| 205 | -#define KFD_GC_VERSION(dev) ((dev)->adev->ip_versions[GC_HWIP][0]) | 212 | +#define KFD_GC_VERSION(dev) (amdgpu_ip_version((dev)->adev, GC_HWIP, 0)) |
| 206 | #define KFD_IS_SOC15(dev) ((KFD_GC_VERSION(dev)) >= (IP_VERSION(9, 0, 1))) | 213 | #define KFD_IS_SOC15(dev) ((KFD_GC_VERSION(dev)) >= (IP_VERSION(9, 0, 1))) |
| 207 | #define KFD_SUPPORT_XNACK_PER_PROCESS(dev)\ | 214 | #define KFD_SUPPORT_XNACK_PER_PROCESS(dev)\ |
| 208 | ((KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 2)) || \ | 215 | ((KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 2)) || \ |
| 209 | - (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 3))) | 216 | + (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 3)) || \ |
| 217 | + (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 4)) || \ | ||
| 218 | + (KFD_GC_VERSION(dev) == IP_VERSION(9, 5, 0))) | ||
| 210 | 219 | ||
| 211 | struct kfd_node; | 220 | struct kfd_node; |
| 212 | 221 | ||
| @@ -272,7 +281,6 @@ struct kfd_node { | |||
| 272 | 281 | ||
| 273 | /* Interrupts */ | 282 | /* Interrupts */ |
| 274 | struct kfifo ih_fifo; | 283 | struct kfifo ih_fifo; |
| 275 | - struct workqueue_struct *ih_wq; | ||
| 276 | struct work_struct interrupt_work; | 284 | struct work_struct interrupt_work; |
| 277 | spinlock_t interrupt_lock; | 285 | spinlock_t interrupt_lock; |
| 278 | 286 | ||
| @@ -288,7 +296,6 @@ struct kfd_node { | |||
| 288 | 296 | ||
| 289 | /* Global GWS resource shared between processes */ | 297 | /* Global GWS resource shared between processes */ |
| 290 | void *gws; | 298 | void *gws; |
| 291 | - bool gws_debug_workaround; | ||
| 292 | 299 | ||
| 293 | /* Clients watching SMI events */ | 300 | /* Clients watching SMI events */ |
| 294 | struct list_head smi_clients; | 301 | struct list_head smi_clients; |
| @@ -309,6 +316,10 @@ struct kfd_node { | |||
| 309 | struct kfd_local_mem_info local_mem_info; | 316 | struct kfd_local_mem_info local_mem_info; |
| 310 | 317 | ||
| 311 | struct kfd_dev *kfd; | 318 | struct kfd_dev *kfd; |
| 319 | + | ||
| 320 | + /* Track per device allocated watch points */ | ||
| 321 | + uint32_t alloc_watch_ids; | ||
| 322 | + spinlock_t watch_points_lock; | ||
| 312 | }; | 323 | }; |
| 313 | 324 | ||
| 314 | struct kfd_dev { | 325 | struct kfd_dev { |
| @@ -361,15 +372,18 @@ struct kfd_dev { | |||
| 361 | struct kfd_node *nodes[MAX_KFD_NODES]; | 372 | struct kfd_node *nodes[MAX_KFD_NODES]; |
| 362 | unsigned int num_nodes; | 373 | unsigned int num_nodes; |
| 363 | 374 | ||
| 364 | - /* Track per device allocated watch points */ | 375 | + struct workqueue_struct *ih_wq; |
| 365 | - uint32_t alloc_watch_ids; | ||
| 366 | - spinlock_t watch_points_lock; | ||
| 367 | 376 | ||
| 368 | /* Kernel doorbells for KFD device */ | 377 | /* Kernel doorbells for KFD device */ |
| 369 | struct amdgpu_bo *doorbells; | 378 | struct amdgpu_bo *doorbells; |
| 370 | 379 | ||
| 371 | /* bitmap for dynamic doorbell allocation from doorbell object */ | 380 | /* bitmap for dynamic doorbell allocation from doorbell object */ |
| 372 | unsigned long *doorbell_bitmap; | 381 | unsigned long *doorbell_bitmap; |
| 382 | + | ||
| 383 | + /* for dynamic partitioning */ | ||
| 384 | + int kfd_dev_lock; | ||
| 385 | + | ||
| 386 | + atomic_t kfd_processes_count; | ||
| 373 | }; | 387 | }; |
| 374 | 388 | ||
| 375 | enum kfd_mempool { | 389 | enum kfd_mempool { |
| @@ -413,13 +427,16 @@ enum kfd_unmap_queues_filter { | |||
| 413 | * @KFD_QUEUE_TYPE_DIQ: DIQ queue type. | 427 | * @KFD_QUEUE_TYPE_DIQ: DIQ queue type. |
| 414 | * | 428 | * |
| 415 | * @KFD_QUEUE_TYPE_SDMA_XGMI: Special SDMA queue for XGMI interface. | 429 | * @KFD_QUEUE_TYPE_SDMA_XGMI: Special SDMA queue for XGMI interface. |
| 430 | + * | ||
| 431 | + * @KFD_QUEUE_TYPE_SDMA_BY_ENG_ID: SDMA user mode queue with target SDMA engine ID. | ||
| 416 | */ | 432 | */ |
| 417 | enum kfd_queue_type { | 433 | enum kfd_queue_type { |
| 418 | KFD_QUEUE_TYPE_COMPUTE, | 434 | KFD_QUEUE_TYPE_COMPUTE, |
| 419 | KFD_QUEUE_TYPE_SDMA, | 435 | KFD_QUEUE_TYPE_SDMA, |
| 420 | KFD_QUEUE_TYPE_HIQ, | 436 | KFD_QUEUE_TYPE_HIQ, |
| 421 | KFD_QUEUE_TYPE_DIQ, | 437 | KFD_QUEUE_TYPE_DIQ, |
| 422 | - KFD_QUEUE_TYPE_SDMA_XGMI | 438 | + KFD_QUEUE_TYPE_SDMA_XGMI, |
| 439 | + KFD_QUEUE_TYPE_SDMA_BY_ENG_ID | ||
| 423 | }; | 440 | }; |
| 424 | 441 | ||
| 425 | enum kfd_queue_format { | 442 | enum kfd_queue_format { |
| @@ -493,8 +510,8 @@ struct queue_properties { | |||
| 493 | uint64_t queue_size; | 510 | uint64_t queue_size; |
| 494 | uint32_t priority; | 511 | uint32_t priority; |
| 495 | uint32_t queue_percent; | 512 | uint32_t queue_percent; |
| 496 | - uint32_t *read_ptr; | 513 | + void __user *read_ptr; |
| 497 | - uint32_t *write_ptr; | 514 | + void __user *write_ptr; |
| 498 | void __iomem *doorbell_ptr; | 515 | void __iomem *doorbell_ptr; |
| 499 | uint32_t doorbell_off; | 516 | uint32_t doorbell_off; |
| 500 | bool is_interop; | 517 | bool is_interop; |
| @@ -521,6 +538,12 @@ struct queue_properties { | |||
| 521 | uint64_t tba_addr; | 538 | uint64_t tba_addr; |
| 522 | uint64_t tma_addr; | 539 | uint64_t tma_addr; |
| 523 | uint64_t exception_status; | 540 | uint64_t exception_status; |
| 541 | + | ||
| 542 | + struct amdgpu_bo *wptr_bo; | ||
| 543 | + struct amdgpu_bo *rptr_bo; | ||
| 544 | + struct amdgpu_bo *ring_bo; | ||
| 545 | + struct amdgpu_bo *eop_buf_bo; | ||
| 546 | + struct amdgpu_bo *cwsr_bo; | ||
| 524 | }; | 547 | }; |
| 525 | 548 | ||
| 526 | #define QUEUE_IS_ACTIVE(q) ((q).queue_size > 0 && \ | 549 | #define QUEUE_IS_ACTIVE(q) ((q).queue_size > 0 && \ |
| @@ -532,6 +555,7 @@ struct queue_properties { | |||
| 532 | enum mqd_update_flag { | 555 | enum mqd_update_flag { |
| 533 | UPDATE_FLAG_DBG_WA_ENABLE = 1, | 556 | UPDATE_FLAG_DBG_WA_ENABLE = 1, |
| 534 | UPDATE_FLAG_DBG_WA_DISABLE = 2, | 557 | UPDATE_FLAG_DBG_WA_DISABLE = 2, |
| 558 | + UPDATE_FLAG_IS_GWS = 4, /* quirk for gfx9 IP */ | ||
| 535 | }; | 559 | }; |
| 536 | 560 | ||
| 537 | struct mqd_update_info { | 561 | struct mqd_update_info { |
| @@ -602,7 +626,7 @@ struct queue { | |||
| 602 | uint64_t gang_ctx_gpu_addr; | 626 | uint64_t gang_ctx_gpu_addr; |
| 603 | void *gang_ctx_cpu_ptr; | 627 | void *gang_ctx_cpu_ptr; |
| 604 | 628 | ||
| 605 | - struct amdgpu_bo *wptr_bo; | 629 | + struct amdgpu_bo *wptr_bo_gart; |
| 606 | }; | 630 | }; |
| 607 | 631 | ||
| 608 | enum KFD_MQD_TYPE { | 632 | enum KFD_MQD_TYPE { |
| @@ -748,7 +772,6 @@ struct kfd_process_device { | |||
| 748 | /* VM context for GPUVM allocations */ | 772 | /* VM context for GPUVM allocations */ |
| 749 | struct file *drm_file; | 773 | struct file *drm_file; |
| 750 | void *drm_priv; | 774 | void *drm_priv; |
| 751 | - atomic64_t tlb_seq; | ||
| 752 | 775 | ||
| 753 | /* GPUVM allocations storage */ | 776 | /* GPUVM allocations storage */ |
| 754 | struct idr alloc_idr; | 777 | struct idr alloc_idr; |
| @@ -836,6 +859,11 @@ struct kfd_process_device { | |||
| 836 | void *proc_ctx_bo; | 859 | void *proc_ctx_bo; |
| 837 | uint64_t proc_ctx_gpu_addr; | 860 | uint64_t proc_ctx_gpu_addr; |
| 838 | void *proc_ctx_cpu_ptr; | 861 | void *proc_ctx_cpu_ptr; |
| 862 | + | ||
| 863 | + /* Tracks queue reset status */ | ||
| 864 | + bool has_reset_queue; | ||
| 865 | + | ||
| 866 | + u32 pasid; | ||
| 839 | }; | 867 | }; |
| 840 | 868 | ||
| 841 | #define qpd_to_pdd(x) container_of(x, struct kfd_process_device, qpd) | 869 | #define qpd_to_pdd(x) container_of(x, struct kfd_process_device, qpd) |
| @@ -853,6 +881,14 @@ struct svm_range_list { | |||
| 853 | struct delayed_work restore_work; | 881 | struct delayed_work restore_work; |
| 854 | DECLARE_BITMAP(bitmap_supported, MAX_GPU_INSTANCE); | 882 | DECLARE_BITMAP(bitmap_supported, MAX_GPU_INSTANCE); |
| 855 | struct task_struct *faulting_task; | 883 | struct task_struct *faulting_task; |
| 884 | + /* check point ts decides if page fault recovery need be dropped */ | ||
| 885 | + uint64_t checkpoint_ts[MAX_GPU_INSTANCE]; | ||
| 886 | + | ||
| 887 | + /* Default granularity to use in buffer migration | ||
| 888 | + * and restoration of backing memory while handling | ||
| 889 | + * recoverable page faults | ||
| 890 | + */ | ||
| 891 | + uint8_t default_granularity; | ||
| 856 | }; | 892 | }; |
| 857 | 893 | ||
| 858 | /* Process data */ | 894 | /* Process data */ |
| @@ -887,8 +923,6 @@ struct kfd_process { | |||
| 887 | /* We want to receive a notification when the mm_struct is destroyed */ | 923 | /* We want to receive a notification when the mm_struct is destroyed */ |
| 888 | struct mmu_notifier mmu_notifier; | 924 | struct mmu_notifier mmu_notifier; |
| 889 | 925 | ||
| 890 | - u32 pasid; | ||
| 891 | - | ||
| 892 | /* | 926 | /* |
| 893 | * Array of kfd_process_device pointers, | 927 | * Array of kfd_process_device pointers, |
| 894 | * one for each device the process is using. | 928 | * one for each device the process is using. |
| @@ -918,7 +952,7 @@ struct kfd_process { | |||
| 918 | * fence will be triggered during eviction and new one will be created | 952 | * fence will be triggered during eviction and new one will be created |
| 919 | * during restore | 953 | * during restore |
| 920 | */ | 954 | */ |
| 921 | - struct dma_fence *ef; | 955 | + struct dma_fence __rcu *ef; |
| 922 | 956 | ||
| 923 | /* Work items for evicting and restoring BOs */ | 957 | /* Work items for evicting and restoring BOs */ |
| 924 | struct delayed_work eviction_work; | 958 | struct delayed_work eviction_work; |
| @@ -981,6 +1015,9 @@ struct kfd_process { | |||
| 981 | struct semaphore runtime_enable_sema; | 1015 | struct semaphore runtime_enable_sema; |
| 982 | bool is_runtime_retry; | 1016 | bool is_runtime_retry; |
| 983 | struct kfd_runtime_info runtime_info; | 1017 | struct kfd_runtime_info runtime_info; |
| 1018 | + | ||
| 1019 | + /* if gpu page fault sent to KFD */ | ||
| 1020 | + bool gpu_page_fault; | ||
| 984 | }; | 1021 | }; |
| 985 | 1022 | ||
| 986 | #define KFD_PROCESS_TABLE_SIZE 5 /* bits: 32 entries */ | 1023 | #define KFD_PROCESS_TABLE_SIZE 5 /* bits: 32 entries */ |
| @@ -1013,7 +1050,8 @@ void kfd_process_destroy_wq(void); | |||
| 1013 | void kfd_cleanup_processes(void); | 1050 | void kfd_cleanup_processes(void); |
| 1014 | struct kfd_process *kfd_create_process(struct task_struct *thread); | 1051 | struct kfd_process *kfd_create_process(struct task_struct *thread); |
| 1015 | struct kfd_process *kfd_get_process(const struct task_struct *task); | 1052 | struct kfd_process *kfd_get_process(const struct task_struct *task); |
| 1016 | -struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid); | 1053 | +struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid, |
| 1054 | + struct kfd_process_device **pdd); | ||
| 1017 | struct kfd_process *kfd_lookup_process_by_mm(const struct mm_struct *mm); | 1055 | struct kfd_process *kfd_lookup_process_by_mm(const struct mm_struct *mm); |
| 1018 | 1056 | ||
| 1019 | int kfd_process_gpuidx_from_gpuid(struct kfd_process *p, uint32_t gpu_id); | 1057 | int kfd_process_gpuidx_from_gpuid(struct kfd_process *p, uint32_t gpu_id); |
| @@ -1065,8 +1103,6 @@ struct kfd_process *kfd_lookup_process_by_pid(struct pid *pid); | |||
| 1065 | /* PASIDs */ | 1103 | /* PASIDs */ |
| 1066 | int kfd_pasid_init(void); | 1104 | int kfd_pasid_init(void); |
| 1067 | void kfd_pasid_exit(void); | 1105 | void kfd_pasid_exit(void); |
| 1068 | -bool kfd_set_pasid_limit(unsigned int new_limit); | ||
| 1069 | -unsigned int kfd_get_pasid_limit(void); | ||
| 1070 | u32 kfd_pasid_alloc(void); | 1106 | u32 kfd_pasid_alloc(void); |
| 1071 | void kfd_pasid_free(u32 pasid); | 1107 | void kfd_pasid_free(u32 pasid); |
| 1072 | 1108 | ||
| @@ -1116,7 +1152,6 @@ struct kfd_topology_device *kfd_topology_device_by_proximity_domain_no_lock( | |||
| 1116 | uint32_t proximity_domain); | 1152 | uint32_t proximity_domain); |
| 1117 | struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id); | 1153 | struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id); |
| 1118 | struct kfd_node *kfd_device_by_id(uint32_t gpu_id); | 1154 | struct kfd_node *kfd_device_by_id(uint32_t gpu_id); |
| 1119 | -struct kfd_node *kfd_device_by_pci_dev(const struct pci_dev *pdev); | ||
| 1120 | static inline bool kfd_irq_is_from_node(struct kfd_node *node, uint32_t node_id, | 1155 | static inline bool kfd_irq_is_from_node(struct kfd_node *node, uint32_t node_id, |
| 1121 | uint32_t vmid) | 1156 | uint32_t vmid) |
| 1122 | { | 1157 | { |
| @@ -1128,7 +1163,9 @@ static inline struct kfd_node *kfd_node_by_irq_ids(struct amdgpu_device *adev, | |||
| 1128 | struct kfd_dev *dev = adev->kfd.dev; | 1163 | struct kfd_dev *dev = adev->kfd.dev; |
| 1129 | uint32_t i; | 1164 | uint32_t i; |
| 1130 | 1165 | ||
| 1131 | - if (KFD_GC_VERSION(dev) != IP_VERSION(9, 4, 3)) | 1166 | + if (KFD_GC_VERSION(dev) != IP_VERSION(9, 4, 3) && |
| 1167 | + KFD_GC_VERSION(dev) != IP_VERSION(9, 4, 4) && | ||
| 1168 | + KFD_GC_VERSION(dev) != IP_VERSION(9, 5, 0)) | ||
| 1132 | return dev->nodes[0]; | 1169 | return dev->nodes[0]; |
| 1133 | 1170 | ||
| 1134 | for (i = 0; i < dev->num_nodes; i++) | 1171 | for (i = 0; i < dev->num_nodes; i++) |
| @@ -1282,6 +1319,15 @@ int init_queue(struct queue **q, const struct queue_properties *properties); | |||
| 1282 | void uninit_queue(struct queue *q); | 1319 | void uninit_queue(struct queue *q); |
| 1283 | void print_queue_properties(struct queue_properties *q); | 1320 | void print_queue_properties(struct queue_properties *q); |
| 1284 | void print_queue(struct queue *q); | 1321 | void print_queue(struct queue *q); |
| 1322 | +int kfd_queue_buffer_get(struct amdgpu_vm *vm, void __user *addr, struct amdgpu_bo **pbo, | ||
| 1323 | + u64 expected_size); | ||
| 1324 | +void kfd_queue_buffer_put(struct amdgpu_bo **bo); | ||
| 1325 | +int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_properties *properties); | ||
| 1326 | +int kfd_queue_release_buffers(struct kfd_process_device *pdd, struct queue_properties *properties); | ||
| 1327 | +void kfd_queue_unref_bo_va(struct amdgpu_vm *vm, struct amdgpu_bo **bo); | ||
| 1328 | +int kfd_queue_unref_bo_vas(struct kfd_process_device *pdd, | ||
| 1329 | + struct queue_properties *properties); | ||
| 1330 | +void kfd_queue_ctx_save_restore_size(struct kfd_topology_device *dev); | ||
| 1285 | 1331 | ||
| 1286 | struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type, | 1332 | struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type, |
| 1287 | struct kfd_node *dev); | 1333 | struct kfd_node *dev); |
| @@ -1293,12 +1339,15 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type, | |||
| 1293 | struct kfd_node *dev); | 1339 | struct kfd_node *dev); |
| 1294 | struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type, | 1340 | struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type, |
| 1295 | struct kfd_node *dev); | 1341 | struct kfd_node *dev); |
| 1342 | +struct mqd_manager *mqd_manager_init_v12(enum KFD_MQD_TYPE type, | ||
| 1343 | + struct kfd_node *dev); | ||
| 1296 | struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev); | 1344 | struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev); |
| 1297 | void device_queue_manager_uninit(struct device_queue_manager *dqm); | 1345 | void device_queue_manager_uninit(struct device_queue_manager *dqm); |
| 1298 | struct kernel_queue *kernel_queue_init(struct kfd_node *dev, | 1346 | struct kernel_queue *kernel_queue_init(struct kfd_node *dev, |
| 1299 | enum kfd_queue_type type); | 1347 | enum kfd_queue_type type); |
| 1300 | -void kernel_queue_uninit(struct kernel_queue *kq, bool hanging); | 1348 | +void kernel_queue_uninit(struct kernel_queue *kq); |
| 1301 | -int kfd_dqm_evict_pasid(struct device_queue_manager *dqm, u32 pasid); | 1349 | +int kfd_evict_process_device(struct kfd_process_device *pdd); |
| 1350 | +int kfd_dqm_suspend_bad_queue_mes(struct kfd_node *knode, u32 pasid, u32 doorbell_id); | ||
| 1302 | 1351 | ||
| 1303 | /* Process Queue Manager */ | 1352 | /* Process Queue Manager */ |
| 1304 | struct process_queue_node { | 1353 | struct process_queue_node { |
| @@ -1313,10 +1362,8 @@ int pqm_init(struct process_queue_manager *pqm, struct kfd_process *p); | |||
| 1313 | void pqm_uninit(struct process_queue_manager *pqm); | 1362 | void pqm_uninit(struct process_queue_manager *pqm); |
| 1314 | int pqm_create_queue(struct process_queue_manager *pqm, | 1363 | int pqm_create_queue(struct process_queue_manager *pqm, |
| 1315 | struct kfd_node *dev, | 1364 | struct kfd_node *dev, |
| 1316 | - struct file *f, | ||
| 1317 | struct queue_properties *properties, | 1365 | struct queue_properties *properties, |
| 1318 | unsigned int *qid, | 1366 | unsigned int *qid, |
| 1319 | - struct amdgpu_bo *wptr_bo, | ||
| 1320 | const struct kfd_criu_queue_priv_data *q_data, | 1367 | const struct kfd_criu_queue_priv_data *q_data, |
| 1321 | const void *restore_mqd, | 1368 | const void *restore_mqd, |
| 1322 | const void *restore_ctl_stack, | 1369 | const void *restore_ctl_stack, |
| @@ -1328,8 +1375,6 @@ int pqm_update_mqd(struct process_queue_manager *pqm, unsigned int qid, | |||
| 1328 | struct mqd_update_info *minfo); | 1375 | struct mqd_update_info *minfo); |
| 1329 | int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid, | 1376 | int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid, |
| 1330 | void *gws); | 1377 | void *gws); |
| 1331 | -struct kernel_queue *pqm_get_kernel_queue(struct process_queue_manager *pqm, | ||
| 1332 | - unsigned int qid); | ||
| 1333 | struct queue *pqm_get_user_queue(struct process_queue_manager *pqm, | 1378 | struct queue *pqm_get_user_queue(struct process_queue_manager *pqm, |
| 1334 | unsigned int qid); | 1379 | unsigned int qid); |
| 1335 | int pqm_get_wave_state(struct process_queue_manager *pqm, | 1380 | int pqm_get_wave_state(struct process_queue_manager *pqm, |
| @@ -1343,7 +1388,7 @@ int pqm_get_queue_snapshot(struct process_queue_manager *pqm, | |||
| 1343 | int *num_qss_entries, | 1388 | int *num_qss_entries, |
| 1344 | uint32_t *entry_size); | 1389 | uint32_t *entry_size); |
| 1345 | 1390 | ||
| 1346 | -int amdkfd_fence_wait_timeout(uint64_t *fence_addr, | 1391 | +int amdkfd_fence_wait_timeout(struct device_queue_manager *dqm, |
| 1347 | uint64_t fence_value, | 1392 | uint64_t fence_value, |
| 1348 | unsigned int timeout_ms); | 1393 | unsigned int timeout_ms); |
| 1349 | 1394 | ||
| @@ -1356,6 +1401,24 @@ int pqm_get_queue_checkpoint_info(struct process_queue_manager *pqm, | |||
| 1356 | #define KFD_FENCE_COMPLETED (100) | 1401 | #define KFD_FENCE_COMPLETED (100) |
| 1357 | #define KFD_FENCE_INIT (10) | 1402 | #define KFD_FENCE_INIT (10) |
| 1358 | 1403 | ||
| 1404 | +/** | ||
| 1405 | + * enum kfd_config_dequeue_wait_counts_cmd - Command for configuring | ||
| 1406 | + * dequeue wait counts. | ||
| 1407 | + * | ||
| 1408 | + * @KFD_DEQUEUE_WAIT_INIT: Set optimized dequeue wait counts for a | ||
| 1409 | + * certain ASICs. For these ASICs, this is default value used by RESET | ||
| 1410 | + * @KFD_DEQUEUE_WAIT_RESET: Reset dequeue wait counts to the optimized value | ||
| 1411 | + * for certain ASICs. For others set it to default hardware reset value | ||
| 1412 | + * @KFD_DEQUEUE_WAIT_SET_SCH_WAVE: Set context switch latency wait | ||
| 1413 | + * | ||
| 1414 | + */ | ||
| 1415 | +enum kfd_config_dequeue_wait_counts_cmd { | ||
| 1416 | + KFD_DEQUEUE_WAIT_INIT = 1, | ||
| 1417 | + KFD_DEQUEUE_WAIT_RESET = 2, | ||
| 1418 | + KFD_DEQUEUE_WAIT_SET_SCH_WAVE = 3 | ||
| 1419 | +}; | ||
| 1420 | + | ||
| 1421 | + | ||
| 1359 | struct packet_manager { | 1422 | struct packet_manager { |
| 1360 | struct device_queue_manager *dqm; | 1423 | struct device_queue_manager *dqm; |
| 1361 | struct kernel_queue *priv_queue; | 1424 | struct kernel_queue *priv_queue; |
| @@ -1381,8 +1444,8 @@ struct packet_manager_funcs { | |||
| 1381 | int (*unmap_queues)(struct packet_manager *pm, uint32_t *buffer, | 1444 | int (*unmap_queues)(struct packet_manager *pm, uint32_t *buffer, |
| 1382 | enum kfd_unmap_queues_filter mode, | 1445 | enum kfd_unmap_queues_filter mode, |
| 1383 | uint32_t filter_param, bool reset); | 1446 | uint32_t filter_param, bool reset); |
| 1384 | - int (*set_grace_period)(struct packet_manager *pm, uint32_t *buffer, | 1447 | + int (*config_dequeue_wait_counts)(struct packet_manager *pm, uint32_t *buffer, |
| 1385 | - uint32_t grace_period); | 1448 | + enum kfd_config_dequeue_wait_counts_cmd cmd, uint32_t value); |
| 1386 | int (*query_status)(struct packet_manager *pm, uint32_t *buffer, | 1449 | int (*query_status)(struct packet_manager *pm, uint32_t *buffer, |
| 1387 | uint64_t fence_address, uint64_t fence_value); | 1450 | uint64_t fence_address, uint64_t fence_value); |
| 1388 | int (*release_mem)(uint64_t gpu_addr, uint32_t *buffer); | 1451 | int (*release_mem)(uint64_t gpu_addr, uint32_t *buffer); |
| @@ -1393,7 +1456,7 @@ struct packet_manager_funcs { | |||
| 1393 | int set_resources_size; | 1456 | int set_resources_size; |
| 1394 | int map_queues_size; | 1457 | int map_queues_size; |
| 1395 | int unmap_queues_size; | 1458 | int unmap_queues_size; |
| 1396 | - int set_grace_period_size; | 1459 | + int config_dequeue_wait_counts_size; |
| 1397 | int query_status_size; | 1460 | int query_status_size; |
| 1398 | int release_mem_size; | 1461 | int release_mem_size; |
| 1399 | }; | 1462 | }; |
| @@ -1403,7 +1466,7 @@ extern const struct packet_manager_funcs kfd_v9_pm_funcs; | |||
| 1403 | extern const struct packet_manager_funcs kfd_aldebaran_pm_funcs; | 1466 | extern const struct packet_manager_funcs kfd_aldebaran_pm_funcs; |
| 1404 | 1467 | ||
| 1405 | int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm); | 1468 | int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm); |
| 1406 | -void pm_uninit(struct packet_manager *pm, bool hanging); | 1469 | +void pm_uninit(struct packet_manager *pm); |
| 1407 | int pm_send_set_resources(struct packet_manager *pm, | 1470 | int pm_send_set_resources(struct packet_manager *pm, |
| 1408 | struct scheduling_resources *res); | 1471 | struct scheduling_resources *res); |
| 1409 | int pm_send_runlist(struct packet_manager *pm, struct list_head *dqm_queues); | 1472 | int pm_send_runlist(struct packet_manager *pm, struct list_head *dqm_queues); |
| @@ -1416,7 +1479,9 @@ int pm_send_unmap_queue(struct packet_manager *pm, | |||
| 1416 | 1479 | ||
| 1417 | void pm_release_ib(struct packet_manager *pm); | 1480 | void pm_release_ib(struct packet_manager *pm); |
| 1418 | 1481 | ||
| 1419 | -int pm_update_grace_period(struct packet_manager *pm, uint32_t grace_period); | 1482 | +int pm_config_dequeue_wait_counts(struct packet_manager *pm, |
| 1483 | + enum kfd_config_dequeue_wait_counts_cmd cmd, | ||
| 1484 | + uint32_t wait_counts_config); | ||
| 1420 | 1485 | ||
| 1421 | /* Following PM funcs can be shared among VI and AI */ | 1486 | /* Following PM funcs can be shared among VI and AI */ |
| 1422 | unsigned int pm_build_pm4_header(unsigned int opcode, size_t packet_size); | 1487 | unsigned int pm_build_pm4_header(unsigned int opcode, size_t packet_size); |
| @@ -1454,7 +1519,9 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p, | |||
| 1454 | int kfd_get_num_events(struct kfd_process *p); | 1519 | int kfd_get_num_events(struct kfd_process *p); |
| 1455 | int kfd_event_destroy(struct kfd_process *p, uint32_t event_id); | 1520 | int kfd_event_destroy(struct kfd_process *p, uint32_t event_id); |
| 1456 | 1521 | ||
| 1457 | -void kfd_signal_vm_fault_event(struct kfd_node *dev, u32 pasid, | 1522 | +void kfd_signal_vm_fault_event_with_userptr(struct kfd_process *p, uint64_t gpu_va); |
| 1523 | + | ||
| 1524 | +void kfd_signal_vm_fault_event(struct kfd_process_device *pdd, | ||
| 1458 | struct kfd_vm_fault_info *info, | 1525 | struct kfd_vm_fault_info *info, |
| 1459 | struct kfd_hsa_memory_exception_data *data); | 1526 | struct kfd_hsa_memory_exception_data *data); |
| 1460 | 1527 | ||
| @@ -1462,7 +1529,14 @@ void kfd_signal_reset_event(struct kfd_node *dev); | |||
| 1462 | 1529 | ||
| 1463 | void kfd_signal_poison_consumed_event(struct kfd_node *dev, u32 pasid); | 1530 | void kfd_signal_poison_consumed_event(struct kfd_node *dev, u32 pasid); |
| 1464 | 1531 | ||
| 1465 | -void kfd_flush_tlb(struct kfd_process_device *pdd, enum TLB_FLUSH_TYPE type); | 1532 | +static inline void kfd_flush_tlb(struct kfd_process_device *pdd, |
| 1533 | + enum TLB_FLUSH_TYPE type) | ||
| 1534 | +{ | ||
| 1535 | + struct amdgpu_device *adev = pdd->dev->adev; | ||
| 1536 | + struct amdgpu_vm *vm = drm_priv_to_vm(pdd->drm_priv); | ||
| 1537 | + | ||
| 1538 | + amdgpu_vm_flush_compute_tlb(adev, vm, type, pdd->dev->xcc_mask); | ||
| 1539 | +} | ||
| 1466 | 1540 | ||
| 1467 | static inline bool kfd_flush_tlb_after_unmap(struct kfd_dev *dev) | 1541 | static inline bool kfd_flush_tlb_after_unmap(struct kfd_dev *dev) |
| 1468 | { | 1542 | { |
| @@ -1474,7 +1548,7 @@ static inline bool kfd_flush_tlb_after_unmap(struct kfd_dev *dev) | |||
| 1474 | int kfd_send_exception_to_runtime(struct kfd_process *p, | 1548 | int kfd_send_exception_to_runtime(struct kfd_process *p, |
| 1475 | unsigned int queue_id, | 1549 | unsigned int queue_id, |
| 1476 | uint64_t error_reason); | 1550 | uint64_t error_reason); |
| 1477 | -bool kfd_is_locked(void); | 1551 | +bool kfd_is_locked(struct kfd_dev *kfd); |
| 1478 | 1552 | ||
| 1479 | /* Compute profile */ | 1553 | /* Compute profile */ |
| 1480 | void kfd_inc_compute_active(struct kfd_node *dev); | 1554 | void kfd_inc_compute_active(struct kfd_node *dev); |
| @@ -1521,10 +1595,15 @@ int kfd_debugfs_hang_hws(struct kfd_node *dev); | |||
| 1521 | int pm_debugfs_hang_hws(struct packet_manager *pm); | 1595 | int pm_debugfs_hang_hws(struct packet_manager *pm); |
| 1522 | int dqm_debugfs_hang_hws(struct device_queue_manager *dqm); | 1596 | int dqm_debugfs_hang_hws(struct device_queue_manager *dqm); |
| 1523 | 1597 | ||
| 1598 | +void kfd_debugfs_add_process(struct kfd_process *p); | ||
| 1599 | +void kfd_debugfs_remove_process(struct kfd_process *p); | ||
| 1600 | + | ||
| 1524 | #else | 1601 | #else |
| 1525 | 1602 | ||
| 1526 | static inline void kfd_debugfs_init(void) {} | 1603 | static inline void kfd_debugfs_init(void) {} |
| 1527 | static inline void kfd_debugfs_fini(void) {} | 1604 | static inline void kfd_debugfs_fini(void) {} |
| 1605 | +static inline void kfd_debugfs_add_process(struct kfd_process *p) {} | ||
| 1606 | +static inline void kfd_debugfs_remove_process(struct kfd_process *p) {} | ||
| 1528 | 1607 | ||
| 1529 | #endif | 1608 | #endif |
| 1530 | 1609 | ||
| @@ -1061,6 +1061,8 @@ static void kfd_process_destroy_pdds(struct kfd_process *p) | |||
| 1061 | pdd->runtime_inuse = false; | 1061 | pdd->runtime_inuse = false; |
| 1062 | } | 1062 | } |
| 1063 | 1063 | ||
| 1064 | + atomic_dec(&pdd->dev->kfd->kfd_processes_count); | ||
| 1065 | + | ||
| 1064 | kfree(pdd); | 1066 | kfree(pdd); |
| 1065 | p->pdds[i] = NULL; | 1067 | p->pdds[i] = NULL; |
| 1066 | } | 1068 | } |
| @@ -1623,6 +1625,8 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_node *dev, | |||
| 1623 | /* Init idr used for memory handle translation */ | 1625 | /* Init idr used for memory handle translation */ |
| 1624 | idr_init(&pdd->alloc_idr); | 1626 | idr_init(&pdd->alloc_idr); |
| 1625 | 1627 | ||
| 1628 | + atomic_inc(&dev->kfd->kfd_processes_count); | ||
| 1629 | + | ||
| 1626 | return pdd; | 1630 | return pdd; |
| 1627 | } | 1631 | } |
| 1628 | 1632 | ||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include "dm_helpers.h" | 34 | #include "dm_helpers.h" |
| 35 | #include "dc_dmub_srv.h" | 35 | #include "dc_dmub_srv.h" |
| 36 | #include "dce/dmub_hw_lock_mgr.h" | 36 | #include "dce/dmub_hw_lock_mgr.h" |
| 37 | +#include "clk_mgr.h" | ||
| 37 | 38 | ||
| 38 | #define DC_LOGGER \ | 39 | #define DC_LOGGER \ |
| 39 | link->ctx->logger | 40 | link->ctx->logger |
| @@ -53,6 +54,7 @@ static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate) | |||
| 53 | return LINK_RATE_UHBR10; | 54 | return LINK_RATE_UHBR10; |
| 54 | case DP_TEST_LINK_RATE_UHBR20: | 55 | case DP_TEST_LINK_RATE_UHBR20: |
| 55 | return LINK_RATE_UHBR20; | 56 | return LINK_RATE_UHBR20; |
| 57 | + case DP_TEST_LINK_RATE_UHBR13_5_LEGACY: | ||
| 56 | case DP_TEST_LINK_RATE_UHBR13_5: | 58 | case DP_TEST_LINK_RATE_UHBR13_5: |
| 57 | return LINK_RATE_UHBR13_5; | 59 | return LINK_RATE_UHBR13_5; |
| 58 | default: | 60 | default: |
| @@ -60,31 +62,26 @@ static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate) | |||
| 60 | } | 62 | } |
| 61 | } | 63 | } |
| 62 | 64 | ||
| 63 | -static bool is_dp_phy_sqaure_pattern(enum dp_test_pattern test_pattern) | ||
| 64 | -{ | ||
| 65 | - return (DP_TEST_PATTERN_SQUARE_BEGIN <= test_pattern && | ||
| 66 | - test_pattern <= DP_TEST_PATTERN_SQUARE_END); | ||
| 67 | -} | ||
| 68 | - | ||
| 69 | -static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern) | ||
| 70 | -{ | ||
| 71 | - if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern && | ||
| 72 | - test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) || | ||
| 73 | - test_pattern == DP_TEST_PATTERN_VIDEO_MODE) | ||
| 74 | - return true; | ||
| 75 | - else | ||
| 76 | - return false; | ||
| 77 | -} | ||
| 78 | - | ||
| 79 | static void dp_retrain_link_dp_test(struct dc_link *link, | 65 | static void dp_retrain_link_dp_test(struct dc_link *link, |
| 80 | struct dc_link_settings *link_setting, | 66 | struct dc_link_settings *link_setting, |
| 81 | bool skip_video_pattern) | 67 | bool skip_video_pattern) |
| 82 | { | 68 | { |
| 83 | struct pipe_ctx *pipes[MAX_PIPES]; | 69 | struct pipe_ctx *pipes[MAX_PIPES]; |
| 84 | struct dc_state *state = link->dc->current_state; | 70 | struct dc_state *state = link->dc->current_state; |
| 71 | + struct dc_stream_update stream_update = { 0 }; | ||
| 72 | + bool dpms_off = false; | ||
| 73 | + bool needs_divider_update = false; | ||
| 74 | + bool was_hpo_acquired = resource_is_hpo_acquired(link->dc->current_state); | ||
| 75 | + bool is_hpo_acquired; | ||
| 85 | uint8_t count; | 76 | uint8_t count; |
| 86 | int i; | 77 | int i; |
| 87 | 78 | ||
| 79 | + struct dc_stream_state *streams_on_link[MAX_PIPES]; | ||
| 80 | + int num_streams_on_link = 0; | ||
| 81 | + | ||
| 82 | + needs_divider_update = (link->dc->link_srv->dp_get_encoding_format(link_setting) != | ||
| 83 | + link->dc->link_srv->dp_get_encoding_format((const struct dc_link_settings *) &link->cur_link_settings)); | ||
| 84 | + | ||
| 88 | udelay(100); | 85 | udelay(100); |
| 89 | 86 | ||
| 90 | link_get_master_pipes_with_dpms_on(link, state, &count, pipes); | 87 | link_get_master_pipes_with_dpms_on(link, state, &count, pipes); |
| @@ -96,10 +93,67 @@ static void dp_retrain_link_dp_test(struct dc_link *link, | |||
| 96 | link->dc, | 93 | link->dc, |
| 97 | state, | 94 | state, |
| 98 | pipes[i]); | 95 | pipes[i]); |
| 96 | + | ||
| 97 | + // Disable OTG and re-enable after updating clocks | ||
| 98 | + pipes[i]->stream_res.tg->funcs->disable_crtc(pipes[i]->stream_res.tg); | ||
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | - for (i = count-1; i >= 0; i--) | 101 | + if (needs_divider_update && link->dc->res_pool->funcs->update_dc_state_for_encoder_switch) { |
| 102 | - link_set_dpms_on(state, pipes[i]); | 102 | + link->dc->res_pool->funcs->update_dc_state_for_encoder_switch(link, |
| 103 | + link_setting, count, | ||
| 104 | + *pipes); | ||
| 105 | + for (i = 0; i < count; i++) { | ||
| 106 | + pipes[i]->clock_source->funcs->program_pix_clk( | ||
| 107 | + pipes[i]->clock_source, | ||
| 108 | + &pipes[i]->stream_res.pix_clk_params, | ||
| 109 | + link->dc->link_srv->dp_get_encoding_format(&pipes[i]->link_config.dp_link_settings), | ||
| 110 | + &pipes[i]->pll_settings); | ||
| 111 | + | ||
| 112 | + if (pipes[i]->stream_res.audio != NULL) { | ||
| 113 | + const struct link_hwss *link_hwss = get_link_hwss( | ||
| 114 | + link, &pipes[i]->link_res); | ||
| 115 | + | ||
| 116 | + link_hwss->setup_audio_output(pipes[i], | ||
| 117 | + &pipes[i]->stream_res.audio_output, | ||
| 118 | + pipes[i]->stream_res.audio->inst); | ||
| 119 | + | ||
| 120 | + pipes[i]->stream_res.audio->funcs->az_configure( | ||
| 121 | + pipes[i]->stream_res.audio, | ||
| 122 | + pipes[i]->stream->signal, | ||
| 123 | + &pipes[i]->stream_res.audio_output.crtc_info, | ||
| 124 | + &pipes[i]->stream->audio_info, | ||
| 125 | + &pipes[i]->stream_res.audio_output.dp_link_info); | ||
| 126 | + | ||
| 127 | + if (link->dc->config.disable_hbr_audio_dp2 && | ||
| 128 | + pipes[i]->stream_res.audio->funcs->az_disable_hbr_audio && | ||
| 129 | + link->dc->link_srv->dp_is_128b_132b_signal(pipes[i])) | ||
| 130 | + pipes[i]->stream_res.audio->funcs->az_disable_hbr_audio(pipes[i]->stream_res.audio); | ||
| 131 | + } | ||
| 132 | + } | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + // Toggle on HPO I/O if necessary | ||
| 136 | + is_hpo_acquired = resource_is_hpo_acquired(state); | ||
| 137 | + if (was_hpo_acquired != is_hpo_acquired && link->dc->hwss.setup_hpo_hw_control) | ||
| 138 | + link->dc->hwss.setup_hpo_hw_control(link->dc->hwseq, is_hpo_acquired); | ||
| 139 | + | ||
| 140 | + for (i = 0; i < count; i++) | ||
| 141 | + pipes[i]->stream_res.tg->funcs->enable_crtc(pipes[i]->stream_res.tg); | ||
| 142 | + | ||
| 143 | + // Set DPMS on with stream update | ||
| 144 | + // Cache all streams on current link since dc_update_planes_and_stream might kill current_state | ||
| 145 | + for (i = 0; i < MAX_PIPES; i++) { | ||
| 146 | + if (state->streams[i] && state->streams[i]->link && state->streams[i]->link == link) | ||
| 147 | + streams_on_link[num_streams_on_link++] = state->streams[i]; | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | + for (i = 0; i < num_streams_on_link; i++) { | ||
| 151 | + if (streams_on_link[i] && streams_on_link[i]->link && streams_on_link[i]->link == link) { | ||
| 152 | + stream_update.stream = streams_on_link[i]; | ||
| 153 | + stream_update.dpms_off = &dpms_off; | ||
| 154 | + dc_update_planes_and_stream(state->clk_mgr->ctx->dc, NULL, 0, streams_on_link[i], &stream_update); | ||
| 155 | + } | ||
| 156 | + } | ||
| 103 | } | 157 | } |
| 104 | 158 | ||
| 105 | static void dp_test_send_link_training(struct dc_link *link) | 159 | static void dp_test_send_link_training(struct dc_link *link) |
| @@ -119,6 +173,11 @@ static void dp_test_send_link_training(struct dc_link *link) | |||
| 119 | 1); | 173 | 1); |
| 120 | link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate); | 174 | link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate); |
| 121 | 175 | ||
| 176 | + if (link_settings.link_rate == LINK_RATE_UNKNOWN) { | ||
| 177 | + DC_LOG_ERROR("%s: Invalid test link rate.", __func__); | ||
| 178 | + ASSERT(0); | ||
| 179 | + } | ||
| 180 | + | ||
| 122 | /* Set preferred link settings */ | 181 | /* Set preferred link settings */ |
| 123 | link->verified_link_cap.lane_count = link_settings.lane_count; | 182 | link->verified_link_cap.lane_count = link_settings.lane_count; |
| 124 | link->verified_link_cap.link_rate = link_settings.link_rate; | 183 | link->verified_link_cap.link_rate = link_settings.link_rate; |
| @@ -253,7 +312,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) | |||
| 253 | 312 | ||
| 254 | link_training_settings.lttpr_mode = dp_decide_lttpr_mode(link, &link->cur_link_settings); | 313 | link_training_settings.lttpr_mode = dp_decide_lttpr_mode(link, &link->cur_link_settings); |
| 255 | 314 | ||
| 256 | - if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && | 315 | + if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && |
| 257 | link_training_settings.lttpr_mode == LTTPR_MODE_TRANSPARENT) | 316 | link_training_settings.lttpr_mode == LTTPR_MODE_TRANSPARENT) |
| 258 | dp_fixed_vs_pe_read_lane_adjust( | 317 | dp_fixed_vs_pe_read_lane_adjust( |
| 259 | link, | 318 | link, |
| @@ -355,7 +414,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) | |||
| 355 | test_pattern_size); | 414 | test_pattern_size); |
| 356 | } | 415 | } |
| 357 | 416 | ||
| 358 | - if (is_dp_phy_sqaure_pattern(test_pattern)) { | 417 | + if (IS_DP_PHY_SQUARE_PATTERN(test_pattern)) { |
| 359 | test_pattern_size = 1; // Square pattern data is 1 byte (DP spec) | 418 | test_pattern_size = 1; // Square pattern data is 1 byte (DP spec) |
| 360 | core_link_read_dpcd( | 419 | core_link_read_dpcd( |
| 361 | link, | 420 | link, |
| @@ -429,49 +488,13 @@ static void set_crtc_test_pattern(struct dc_link *link, | |||
| 429 | struct bit_depth_reduction_params params; | 488 | struct bit_depth_reduction_params params; |
| 430 | struct output_pixel_processor *opp = pipe_ctx->stream_res.opp; | 489 | struct output_pixel_processor *opp = pipe_ctx->stream_res.opp; |
| 431 | struct pipe_ctx *odm_pipe; | 490 | struct pipe_ctx *odm_pipe; |
| 432 | - int odm_cnt = 1; | 491 | + struct test_pattern_params *tp_params; |
| 433 | - int h_active = pipe_ctx->stream->timing.h_addressable + | ||
| 434 | - pipe_ctx->stream->timing.h_border_left + | ||
| 435 | - pipe_ctx->stream->timing.h_border_right; | ||
| 436 | - int v_active = pipe_ctx->stream->timing.v_addressable + | ||
| 437 | - pipe_ctx->stream->timing.v_border_bottom + | ||
| 438 | - pipe_ctx->stream->timing.v_border_top; | ||
| 439 | - int odm_slice_width, last_odm_slice_width, offset = 0; | ||
| 440 | 492 | ||
| 441 | memset(¶ms, 0, sizeof(params)); | 493 | memset(¶ms, 0, sizeof(params)); |
| 442 | 494 | ||
| 443 | - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) | 495 | + resource_build_test_pattern_params(&link->dc->current_state->res_ctx, |
| 444 | - odm_cnt++; | 496 | + pipe_ctx); |
| 445 | - | 497 | + controller_test_pattern = pipe_ctx->stream_res.test_pattern_params.test_pattern; |
| 446 | - odm_slice_width = h_active / odm_cnt; | ||
| 447 | - last_odm_slice_width = h_active - odm_slice_width * (odm_cnt - 1); | ||
| 448 | - | ||
| 449 | - switch (test_pattern) { | ||
| 450 | - case DP_TEST_PATTERN_COLOR_SQUARES: | ||
| 451 | - controller_test_pattern = | ||
| 452 | - CONTROLLER_DP_TEST_PATTERN_COLORSQUARES; | ||
| 453 | - break; | ||
| 454 | - case DP_TEST_PATTERN_COLOR_SQUARES_CEA: | ||
| 455 | - controller_test_pattern = | ||
| 456 | - CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA; | ||
| 457 | - break; | ||
| 458 | - case DP_TEST_PATTERN_VERTICAL_BARS: | ||
| 459 | - controller_test_pattern = | ||
| 460 | - CONTROLLER_DP_TEST_PATTERN_VERTICALBARS; | ||
| 461 | - break; | ||
| 462 | - case DP_TEST_PATTERN_HORIZONTAL_BARS: | ||
| 463 | - controller_test_pattern = | ||
| 464 | - CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS; | ||
| 465 | - break; | ||
| 466 | - case DP_TEST_PATTERN_COLOR_RAMP: | ||
| 467 | - controller_test_pattern = | ||
| 468 | - CONTROLLER_DP_TEST_PATTERN_COLORRAMP; | ||
| 469 | - break; | ||
| 470 | - default: | ||
| 471 | - controller_test_pattern = | ||
| 472 | - CONTROLLER_DP_TEST_PATTERN_VIDEOMODE; | ||
| 473 | - break; | ||
| 474 | - } | ||
| 475 | 498 | ||
| 476 | switch (test_pattern) { | 499 | switch (test_pattern) { |
| 477 | case DP_TEST_PATTERN_COLOR_SQUARES: | 500 | case DP_TEST_PATTERN_COLOR_SQUARES: |
| @@ -490,51 +513,29 @@ static void set_crtc_test_pattern(struct dc_link *link, | |||
| 490 | enum controller_dp_color_space controller_color_space; | 513 | enum controller_dp_color_space controller_color_space; |
| 491 | struct output_pixel_processor *odm_opp; | 514 | struct output_pixel_processor *odm_opp; |
| 492 | 515 | ||
| 493 | - switch (test_pattern_color_space) { | 516 | + controller_color_space = pipe_ctx->stream_res.test_pattern_params.color_space; |
| 494 | - case DP_TEST_PATTERN_COLOR_SPACE_RGB: | 517 | + |
| 495 | - controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB; | 518 | + if (controller_color_space == CONTROLLER_DP_COLOR_SPACE_UDEFINED) { |
| 496 | - break; | ||
| 497 | - case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601: | ||
| 498 | - controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601; | ||
| 499 | - break; | ||
| 500 | - case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709: | ||
| 501 | - controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709; | ||
| 502 | - break; | ||
| 503 | - case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED: | ||
| 504 | - default: | ||
| 505 | - controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED; | ||
| 506 | DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__); | 519 | DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__); |
| 507 | ASSERT(0); | 520 | ASSERT(0); |
| 508 | - break; | ||
| 509 | } | 521 | } |
| 510 | 522 | ||
| 511 | odm_pipe = pipe_ctx; | 523 | odm_pipe = pipe_ctx; |
| 512 | - while (odm_pipe->next_odm_pipe) { | 524 | + while (odm_pipe) { |
| 525 | + tp_params = &odm_pipe->stream_res.test_pattern_params; | ||
| 513 | odm_opp = odm_pipe->stream_res.opp; | 526 | odm_opp = odm_pipe->stream_res.opp; |
| 514 | odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms); | 527 | odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms); |
| 515 | link->dc->hwss.set_disp_pattern_generator(link->dc, | 528 | link->dc->hwss.set_disp_pattern_generator(link->dc, |
| 516 | odm_pipe, | 529 | odm_pipe, |
| 517 | - controller_test_pattern, | 530 | + tp_params->test_pattern, |
| 518 | - controller_color_space, | 531 | + tp_params->color_space, |
| 519 | - color_depth, | 532 | + tp_params->color_depth, |
| 520 | NULL, | 533 | NULL, |
| 521 | - odm_slice_width, | 534 | + tp_params->width, |
| 522 | - v_active, | 535 | + tp_params->height, |
| 523 | - offset); | 536 | + tp_params->offset); |
| 524 | - offset += odm_slice_width; | ||
| 525 | odm_pipe = odm_pipe->next_odm_pipe; | 537 | odm_pipe = odm_pipe->next_odm_pipe; |
| 526 | } | 538 | } |
| 527 | - odm_opp = odm_pipe->stream_res.opp; | ||
| 528 | - odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms); | ||
| 529 | - link->dc->hwss.set_disp_pattern_generator(link->dc, | ||
| 530 | - odm_pipe, | ||
| 531 | - controller_test_pattern, | ||
| 532 | - controller_color_space, | ||
| 533 | - color_depth, | ||
| 534 | - NULL, | ||
| 535 | - last_odm_slice_width, | ||
| 536 | - v_active, | ||
| 537 | - offset); | ||
| 538 | } | 539 | } |
| 539 | } | 540 | } |
| 540 | break; | 541 | break; |
| @@ -552,32 +553,21 @@ static void set_crtc_test_pattern(struct dc_link *link, | |||
| 552 | struct output_pixel_processor *odm_opp; | 553 | struct output_pixel_processor *odm_opp; |
| 553 | 554 | ||
| 554 | odm_pipe = pipe_ctx; | 555 | odm_pipe = pipe_ctx; |
| 555 | - while (odm_pipe->next_odm_pipe) { | 556 | + while (odm_pipe) { |
| 557 | + tp_params = &odm_pipe->stream_res.test_pattern_params; | ||
| 556 | odm_opp = odm_pipe->stream_res.opp; | 558 | odm_opp = odm_pipe->stream_res.opp; |
| 557 | odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms); | 559 | odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms); |
| 558 | link->dc->hwss.set_disp_pattern_generator(link->dc, | 560 | link->dc->hwss.set_disp_pattern_generator(link->dc, |
| 559 | odm_pipe, | 561 | odm_pipe, |
| 560 | - CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, | 562 | + tp_params->test_pattern, |
| 561 | - CONTROLLER_DP_COLOR_SPACE_UDEFINED, | 563 | + tp_params->color_space, |
| 562 | - color_depth, | 564 | + tp_params->color_depth, |
| 563 | NULL, | 565 | NULL, |
| 564 | - odm_slice_width, | 566 | + tp_params->width, |
| 565 | - v_active, | 567 | + tp_params->height, |
| 566 | - offset); | 568 | + tp_params->offset); |
| 567 | - offset += odm_slice_width; | ||
| 568 | odm_pipe = odm_pipe->next_odm_pipe; | 569 | odm_pipe = odm_pipe->next_odm_pipe; |
| 569 | } | 570 | } |
| 570 | - odm_opp = odm_pipe->stream_res.opp; | ||
| 571 | - odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms); | ||
| 572 | - link->dc->hwss.set_disp_pattern_generator(link->dc, | ||
| 573 | - odm_pipe, | ||
| 574 | - CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, | ||
| 575 | - CONTROLLER_DP_COLOR_SPACE_UDEFINED, | ||
| 576 | - color_depth, | ||
| 577 | - NULL, | ||
| 578 | - last_odm_slice_width, | ||
| 579 | - v_active, | ||
| 580 | - offset); | ||
| 581 | } | 571 | } |
| 582 | } | 572 | } |
| 583 | break; | 573 | break; |
| @@ -661,6 +651,7 @@ bool dp_set_test_pattern( | |||
| 661 | const unsigned char *p_custom_pattern, | 651 | const unsigned char *p_custom_pattern, |
| 662 | unsigned int cust_pattern_size) | 652 | unsigned int cust_pattern_size) |
| 663 | { | 653 | { |
| 654 | + const struct link_hwss *link_hwss; | ||
| 664 | struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; | 655 | struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; |
| 665 | struct pipe_ctx *pipe_ctx = NULL; | 656 | struct pipe_ctx *pipe_ctx = NULL; |
| 666 | unsigned int lane; | 657 | unsigned int lane; |
| @@ -685,6 +676,8 @@ bool dp_set_test_pattern( | |||
| 685 | if (pipe_ctx == NULL) | 676 | if (pipe_ctx == NULL) |
| 686 | return false; | 677 | return false; |
| 687 | 678 | ||
| 679 | + link->pending_test_pattern = test_pattern; | ||
| 680 | + | ||
| 688 | /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */ | 681 | /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */ |
| 689 | if (link->test_pattern_enabled && test_pattern == | 682 | if (link->test_pattern_enabled && test_pattern == |
| 690 | DP_TEST_PATTERN_VIDEO_MODE) { | 683 | DP_TEST_PATTERN_VIDEO_MODE) { |
| @@ -705,15 +698,16 @@ bool dp_set_test_pattern( | |||
| 705 | /* Reset Test Pattern state */ | 698 | /* Reset Test Pattern state */ |
| 706 | link->test_pattern_enabled = false; | 699 | link->test_pattern_enabled = false; |
| 707 | link->current_test_pattern = test_pattern; | 700 | link->current_test_pattern = test_pattern; |
| 701 | + link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED; | ||
| 708 | 702 | ||
| 709 | return true; | 703 | return true; |
| 710 | } | 704 | } |
| 711 | 705 | ||
| 712 | /* Check for PHY Test Patterns */ | 706 | /* Check for PHY Test Patterns */ |
| 713 | - if (is_dp_phy_pattern(test_pattern)) { | 707 | + if (IS_DP_PHY_PATTERN(test_pattern)) { |
| 714 | /* Set DPCD Lane Settings before running test pattern */ | 708 | /* Set DPCD Lane Settings before running test pattern */ |
| 715 | if (p_link_settings != NULL) { | 709 | if (p_link_settings != NULL) { |
| 716 | - if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && | 710 | + if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && |
| 717 | p_link_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) { | 711 | p_link_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) { |
| 718 | dp_fixed_vs_pe_set_retimer_lane_settings( | 712 | dp_fixed_vs_pe_set_retimer_lane_settings( |
| 719 | link, | 713 | link, |
| @@ -743,6 +737,7 @@ bool dp_set_test_pattern( | |||
| 743 | /* Set Test Pattern state */ | 737 | /* Set Test Pattern state */ |
| 744 | link->test_pattern_enabled = true; | 738 | link->test_pattern_enabled = true; |
| 745 | link->current_test_pattern = test_pattern; | 739 | link->current_test_pattern = test_pattern; |
| 740 | + link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED; | ||
| 746 | if (p_link_settings != NULL) | 741 | if (p_link_settings != NULL) |
| 747 | dpcd_set_link_settings(link, | 742 | dpcd_set_link_settings(link, |
| 748 | p_link_settings); | 743 | p_link_settings); |
| @@ -818,7 +813,7 @@ bool dp_set_test_pattern( | |||
| 818 | return false; | 813 | return false; |
| 819 | 814 | ||
| 820 | if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { | 815 | if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { |
| 821 | - if (is_dp_phy_sqaure_pattern(test_pattern)) | 816 | + if (IS_DP_PHY_SQUARE_PATTERN(test_pattern)) |
| 822 | core_link_write_dpcd(link, | 817 | core_link_write_dpcd(link, |
| 823 | DP_LINK_SQUARE_PATTERN, | 818 | DP_LINK_SQUARE_PATTERN, |
| 824 | p_custom_pattern, | 819 | p_custom_pattern, |
| @@ -878,8 +873,11 @@ bool dp_set_test_pattern( | |||
| 878 | break; | 873 | break; |
| 879 | } | 874 | } |
| 880 | 875 | ||
| 876 | + if (!pipe_ctx->stream) | ||
| 877 | + return false; | ||
| 878 | + | ||
| 881 | if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) { | 879 | if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) { |
| 882 | - if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) { | 880 | + if (should_use_dmub_lock(pipe_ctx->stream->link)) { |
| 883 | union dmub_hw_lock_flags hw_locks = { 0 }; | 881 | union dmub_hw_lock_flags hw_locks = { 0 }; |
| 884 | struct dmub_hw_lock_inst_flags inst_flags = { 0 }; | 882 | struct dmub_hw_lock_inst_flags inst_flags = { 0 }; |
| 885 | 883 | ||
| @@ -897,17 +895,21 @@ bool dp_set_test_pattern( | |||
| 897 | 895 | ||
| 898 | pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); | 896 | pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); |
| 899 | /* update MSA to requested color space */ | 897 | /* update MSA to requested color space */ |
| 900 | - pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(pipe_ctx->stream_res.stream_enc, | 898 | + link_hwss = get_link_hwss(link, &pipe_ctx->link_res); |
| 901 | - &pipe_ctx->stream->timing, | 899 | + pipe_ctx->stream->output_color_space = color_space; |
| 902 | - color_space, | 900 | + link_hwss->setup_stream_attribute(pipe_ctx); |
| 903 | - pipe_ctx->stream->use_vsc_sdp_for_colorimetry, | ||
| 904 | - link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP); | ||
| 905 | 901 | ||
| 906 | if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) { | 902 | if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) { |
| 907 | if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA) | 903 | if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA) |
| 908 | pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range | 904 | pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range |
| 909 | else | 905 | else |
| 910 | pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7); | 906 | pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7); |
| 907 | + | ||
| 908 | + if (color_space == COLOR_SPACE_YCBCR601_LIMITED) | ||
| 909 | + pipe_ctx->stream->vsc_infopacket.sb[16] &= 0xf0; | ||
| 910 | + else if (color_space == COLOR_SPACE_YCBCR709_LIMITED) | ||
| 911 | + pipe_ctx->stream->vsc_infopacket.sb[16] |= 1; | ||
| 912 | + | ||
| 911 | resource_build_info_frame(pipe_ctx); | 913 | resource_build_info_frame(pipe_ctx); |
| 912 | link->dc->hwss.update_info_frame(pipe_ctx); | 914 | link->dc->hwss.update_info_frame(pipe_ctx); |
| 913 | } | 915 | } |
| @@ -923,7 +925,7 @@ bool dp_set_test_pattern( | |||
| 923 | CRTC_STATE_VACTIVE); | 925 | CRTC_STATE_VACTIVE); |
| 924 | 926 | ||
| 925 | if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) { | 927 | if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) { |
| 926 | - if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) { | 928 | + if (should_use_dmub_lock(pipe_ctx->stream->link)) { |
| 927 | union dmub_hw_lock_flags hw_locks = { 0 }; | 929 | union dmub_hw_lock_flags hw_locks = { 0 }; |
| 928 | struct dmub_hw_lock_inst_flags inst_flags = { 0 }; | 930 | struct dmub_hw_lock_inst_flags inst_flags = { 0 }; |
| 929 | 931 | ||
| @@ -942,6 +944,7 @@ bool dp_set_test_pattern( | |||
| 942 | /* Set Test Pattern state */ | 944 | /* Set Test Pattern state */ |
| 943 | link->test_pattern_enabled = true; | 945 | link->test_pattern_enabled = true; |
| 944 | link->current_test_pattern = test_pattern; | 946 | link->current_test_pattern = test_pattern; |
| 947 | + link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED; | ||
| 945 | } | 948 | } |
| 946 | 949 | ||
| 947 | return true; | 950 | return true; |
| @@ -953,7 +956,7 @@ void dp_set_preferred_link_settings(struct dc *dc, | |||
| 953 | { | 956 | { |
| 954 | int i; | 957 | int i; |
| 955 | struct pipe_ctx *pipe; | 958 | struct pipe_ctx *pipe; |
| 956 | - struct dc_stream_state *link_stream; | 959 | + struct dc_stream_state *link_stream = 0; |
| 957 | struct dc_link_settings store_settings = *link_setting; | 960 | struct dc_link_settings store_settings = *link_setting; |
| 958 | 961 | ||
| 959 | link->preferred_link_setting = store_settings; | 962 | link->preferred_link_setting = store_settings; |
| @@ -258,6 +258,11 @@ struct canfd_quirk { | |||
| 258 | u8 quirk; | 258 | u8 quirk; |
| 259 | } __packed; | 259 | } __packed; |
| 260 | 260 | ||
| 261 | +/* struct gs_host_frame::echo_id == GS_HOST_FRAME_ECHO_ID_RX indicates | ||
| 262 | + * a regular RX'ed CAN frame | ||
| 263 | + */ | ||
| 264 | +#define GS_HOST_FRAME_ECHO_ID_RX 0xffffffff | ||
| 265 | + | ||
| 261 | struct gs_host_frame { | 266 | struct gs_host_frame { |
| 262 | struct_group(header, | 267 | struct_group(header, |
| 263 | u32 echo_id; | 268 | u32 echo_id; |
| @@ -571,6 +576,37 @@ gs_usb_get_echo_skb(struct gs_can *dev, struct sk_buff *skb, | |||
| 571 | return len; | 576 | return len; |
| 572 | } | 577 | } |
| 573 | 578 | ||
| 579 | +static unsigned int | ||
| 580 | +gs_usb_get_minimum_rx_length(const struct gs_can *dev, const struct gs_host_frame *hf, | ||
| 581 | + unsigned int *data_length_p) | ||
| 582 | +{ | ||
| 583 | + unsigned int minimum_length, data_length = 0; | ||
| 584 | + | ||
| 585 | + if (hf->flags & GS_CAN_FLAG_FD) { | ||
| 586 | + if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX) | ||
| 587 | + data_length = can_fd_dlc2len(hf->can_dlc); | ||
| 588 | + | ||
| 589 | + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) | ||
| 590 | + /* timestamp follows data field of max size */ | ||
| 591 | + minimum_length = struct_size(hf, canfd_ts, 1); | ||
| 592 | + else | ||
| 593 | + minimum_length = sizeof(hf->header) + data_length; | ||
| 594 | + } else { | ||
| 595 | + if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX && | ||
| 596 | + !(hf->can_id & cpu_to_le32(CAN_RTR_FLAG))) | ||
| 597 | + data_length = can_cc_dlc2len(hf->can_dlc); | ||
| 598 | + | ||
| 599 | + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) | ||
| 600 | + /* timestamp follows data field of max size */ | ||
| 601 | + minimum_length = struct_size(hf, classic_can_ts, 1); | ||
| 602 | + else | ||
| 603 | + minimum_length = sizeof(hf->header) + data_length; | ||
| 604 | + } | ||
| 605 | + | ||
| 606 | + *data_length_p = data_length; | ||
| 607 | + return minimum_length; | ||
| 608 | +} | ||
| 609 | + | ||
| 574 | static void gs_usb_receive_bulk_callback(struct urb *urb) | 610 | static void gs_usb_receive_bulk_callback(struct urb *urb) |
| 575 | { | 611 | { |
| 576 | struct gs_usb *parent = urb->context; | 612 | struct gs_usb *parent = urb->context; |
| @@ -579,7 +615,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) | |||
| 579 | int rc; | 615 | int rc; |
| 580 | struct net_device_stats *stats; | 616 | struct net_device_stats *stats; |
| 581 | struct gs_host_frame *hf = urb->transfer_buffer; | 617 | struct gs_host_frame *hf = urb->transfer_buffer; |
| 582 | - unsigned int minimum_length; | 618 | + unsigned int minimum_length, data_length; |
| 583 | struct gs_tx_context *txc; | 619 | struct gs_tx_context *txc; |
| 584 | struct can_frame *cf; | 620 | struct can_frame *cf; |
| 585 | struct canfd_frame *cfd; | 621 | struct canfd_frame *cfd; |
| @@ -622,20 +658,33 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) | |||
| 622 | if (!netif_running(netdev)) | 658 | if (!netif_running(netdev)) |
| 623 | goto resubmit_urb; | 659 | goto resubmit_urb; |
| 624 | 660 | ||
| 625 | - if (hf->echo_id == -1) { /* normal rx */ | 661 | + minimum_length = gs_usb_get_minimum_rx_length(dev, hf, &data_length); |
| 662 | + if (urb->actual_length < minimum_length) { | ||
| 663 | + stats->rx_errors++; | ||
| 664 | + stats->rx_length_errors++; | ||
| 665 | + | ||
| 666 | + if (net_ratelimit()) | ||
| 667 | + netdev_err(netdev, | ||
| 668 | + "short read (actual_length=%u, minimum_length=%u)\n", | ||
| 669 | + urb->actual_length, minimum_length); | ||
| 670 | + | ||
| 671 | + goto resubmit_urb; | ||
| 672 | + } | ||
| 673 | + | ||
| 674 | + if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX) { /* normal rx */ | ||
| 626 | if (hf->flags & GS_CAN_FLAG_FD) { | 675 | if (hf->flags & GS_CAN_FLAG_FD) { |
| 627 | skb = alloc_canfd_skb(netdev, &cfd); | 676 | skb = alloc_canfd_skb(netdev, &cfd); |
| 628 | if (!skb) | 677 | if (!skb) |
| 629 | return; | 678 | return; |
| 630 | 679 | ||
| 631 | cfd->can_id = le32_to_cpu(hf->can_id); | 680 | cfd->can_id = le32_to_cpu(hf->can_id); |
| 632 | - cfd->len = can_fd_dlc2len(hf->can_dlc); | 681 | + cfd->len = data_length; |
| 633 | if (hf->flags & GS_CAN_FLAG_BRS) | 682 | if (hf->flags & GS_CAN_FLAG_BRS) |
| 634 | cfd->flags |= CANFD_BRS; | 683 | cfd->flags |= CANFD_BRS; |
| 635 | if (hf->flags & GS_CAN_FLAG_ESI) | 684 | if (hf->flags & GS_CAN_FLAG_ESI) |
| 636 | cfd->flags |= CANFD_ESI; | 685 | cfd->flags |= CANFD_ESI; |
| 637 | 686 | ||
| 638 | - memcpy(cfd->data, hf->canfd->data, cfd->len); | 687 | + memcpy(cfd->data, hf->canfd->data, data_length); |
| 639 | } else { | 688 | } else { |
| 640 | skb = alloc_can_skb(netdev, &cf); | 689 | skb = alloc_can_skb(netdev, &cf); |
| 641 | if (!skb) | 690 | if (!skb) |
| @@ -644,7 +693,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) | |||
| 644 | cf->can_id = le32_to_cpu(hf->can_id); | 693 | cf->can_id = le32_to_cpu(hf->can_id); |
| 645 | can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode); | 694 | can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode); |
| 646 | 695 | ||
| 647 | - memcpy(cf->data, hf->classic_can->data, 8); | 696 | + memcpy(cf->data, hf->classic_can->data, data_length); |
| 648 | 697 | ||
| 649 | /* ERROR frames tell us information about the controller */ | 698 | /* ERROR frames tell us information about the controller */ |
| 650 | if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) | 699 | if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) |
| @@ -47,6 +47,7 @@ void amd_pmc_quirks_init(struct amd_pmc_dev *dev); | |||
| 47 | #define AMD_CPU_ID_RN 0x1630 | 47 | #define AMD_CPU_ID_RN 0x1630 |
| 48 | #define AMD_CPU_ID_PCO AMD_CPU_ID_RV | 48 | #define AMD_CPU_ID_PCO AMD_CPU_ID_RV |
| 49 | #define AMD_CPU_ID_CZN AMD_CPU_ID_RN | 49 | #define AMD_CPU_ID_CZN AMD_CPU_ID_RN |
| 50 | +#define AMD_CPU_ID_VG 0x1645 | ||
| 50 | #define AMD_CPU_ID_YC 0x14B5 | 51 | #define AMD_CPU_ID_YC 0x14B5 |
| 51 | #define AMD_CPU_ID_CB 0x14D8 | 52 | #define AMD_CPU_ID_CB 0x14D8 |
| 52 | #define AMD_CPU_ID_PS 0x14E8 | 53 | #define AMD_CPU_ID_PS 0x14E8 |
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/console.h> | 30 | #include <linux/console.h> |
| 31 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
| 32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
| 33 | +#include <linux/platform_device.h> | ||
| 33 | 34 | ||
| 34 | #include <linux/io.h> | 35 | #include <linux/io.h> |
| 35 | #include <asm/irq.h> | 36 | #include <asm/irq.h> |
| @@ -4133,7 +4133,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, | |||
| 4133 | mutex_unlock(&fs_info->chunk_mutex); | 4133 | mutex_unlock(&fs_info->chunk_mutex); |
| 4134 | } else { | 4134 | } else { |
| 4135 | /* Proceed with allocation */ | 4135 | /* Proceed with allocation */ |
| 4136 | - space_info->chunk_alloc = 1; | 4136 | + space_info->chunk_alloc = true; |
| 4137 | wait_for_alloc = false; | 4137 | wait_for_alloc = false; |
| 4138 | spin_unlock(&space_info->lock); | 4138 | spin_unlock(&space_info->lock); |
| 4139 | } | 4139 | } |
| @@ -4182,7 +4182,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, | |||
| 4182 | spin_lock(&space_info->lock); | 4182 | spin_lock(&space_info->lock); |
| 4183 | if (ret < 0) { | 4183 | if (ret < 0) { |
| 4184 | if (ret == -ENOSPC) | 4184 | if (ret == -ENOSPC) |
| 4185 | - space_info->full = 1; | 4185 | + space_info->full = true; |
| 4186 | else | 4186 | else |
| 4187 | goto out; | 4187 | goto out; |
| 4188 | } else { | 4188 | } else { |
| @@ -4192,7 +4192,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, | |||
| 4192 | 4192 | ||
| 4193 | space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; | 4193 | space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; |
| 4194 | out: | 4194 | out: |
| 4195 | - space_info->chunk_alloc = 0; | 4195 | + space_info->chunk_alloc = false; |
| 4196 | spin_unlock(&space_info->lock); | 4196 | spin_unlock(&space_info->lock); |
| 4197 | mutex_unlock(&fs_info->chunk_mutex); | 4197 | mutex_unlock(&fs_info->chunk_mutex); |
| 4198 | 4198 | ||
| @@ -116,11 +116,11 @@ struct btrfs_space_info { | |||
| 116 | flushing. The value is >> clamp, so turns | 116 | flushing. The value is >> clamp, so turns |
| 117 | out to be a 2^clamp divisor. */ | 117 | out to be a 2^clamp divisor. */ |
| 118 | 118 | ||
| 119 | - unsigned int full:1; /* indicates that we cannot allocate any more | 119 | + bool full; /* indicates that we cannot allocate any more |
| 120 | chunks for this space */ | 120 | chunks for this space */ |
| 121 | - unsigned int chunk_alloc:1; /* set if we are allocating a chunk */ | 121 | + bool chunk_alloc; /* set if we are allocating a chunk */ |
| 122 | 122 | ||
| 123 | - unsigned int flush:1; /* set if we are trying to make space */ | 123 | + bool flush; /* set if we are trying to make space */ |
| 124 | 124 | ||
| 125 | unsigned int force_alloc; /* set if we need to force a chunk | 125 | unsigned int force_alloc; /* set if we need to force a chunk |
| 126 | alloc for this space */ | 126 | alloc for this space */ |
| @@ -3255,6 +3255,17 @@ static inline bool f2fs_need_compress_data(struct inode *inode) | |||
| 3255 | return false; | 3255 | return false; |
| 3256 | } | 3256 | } |
| 3257 | 3257 | ||
| 3258 | +static inline unsigned int addrs_per_page(struct inode *inode, | ||
| 3259 | + bool is_inode) | ||
| 3260 | +{ | ||
| 3261 | + unsigned int addrs = is_inode ? (CUR_ADDRS_PER_INODE(inode) - | ||
| 3262 | + get_inline_xattr_addrs(inode)) : DEF_ADDRS_PER_BLOCK; | ||
| 3263 | + | ||
| 3264 | + if (f2fs_compressed_file(inode)) | ||
| 3265 | + return ALIGN_DOWN(addrs, F2FS_I(inode)->i_cluster_size); | ||
| 3266 | + return addrs; | ||
| 3267 | +} | ||
| 3268 | + | ||
| 3258 | static inline unsigned int addrs_per_inode(struct inode *inode) | 3269 | static inline unsigned int addrs_per_inode(struct inode *inode) |
| 3259 | { | 3270 | { |
| 3260 | unsigned int addrs = CUR_ADDRS_PER_INODE(inode) - | 3271 | unsigned int addrs = CUR_ADDRS_PER_INODE(inode) - |
| @@ -27,12 +27,17 @@ static struct kmem_cache *free_nid_slab; | |||
| 27 | static struct kmem_cache *nat_entry_set_slab; | 27 | static struct kmem_cache *nat_entry_set_slab; |
| 28 | static struct kmem_cache *fsync_node_entry_slab; | 28 | static struct kmem_cache *fsync_node_entry_slab; |
| 29 | 29 | ||
| 30 | +static inline bool is_invalid_nid(struct f2fs_sb_info *sbi, nid_t nid) | ||
| 31 | +{ | ||
| 32 | + return nid < F2FS_ROOT_INO(sbi) || nid >= NM_I(sbi)->max_nid; | ||
| 33 | +} | ||
| 34 | + | ||
| 30 | /* | 35 | /* |
| 31 | * Check whether the given nid is within node id range. | 36 | * Check whether the given nid is within node id range. |
| 32 | */ | 37 | */ |
| 33 | int f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid) | 38 | int f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid) |
| 34 | { | 39 | { |
| 35 | - if (unlikely(nid < F2FS_ROOT_INO(sbi) || nid >= NM_I(sbi)->max_nid)) { | 40 | + if (unlikely(is_invalid_nid(sbi, nid))) { |
| 36 | set_sbi_flag(sbi, SBI_NEED_FSCK); | 41 | set_sbi_flag(sbi, SBI_NEED_FSCK); |
| 37 | f2fs_warn(sbi, "%s: out-of-range nid=%x, run fsck to fix.", | 42 | f2fs_warn(sbi, "%s: out-of-range nid=%x, run fsck to fix.", |
| 38 | __func__, nid); | 43 | __func__, nid); |
| @@ -633,7 +638,7 @@ static void f2fs_ra_node_pages(struct page *parent, int start, int n) | |||
| 633 | 638 | ||
| 634 | /* Then, try readahead for siblings of the desired node */ | 639 | /* Then, try readahead for siblings of the desired node */ |
| 635 | end = start + n; | 640 | end = start + n; |
| 636 | - end = min(end, NIDS_PER_BLOCK); | 641 | + end = min(end, (int)NIDS_PER_BLOCK); |
| 637 | for (i = start; i < end; i++) { | 642 | for (i = start; i < end; i++) { |
| 638 | nid = get_nid(parent, i, false); | 643 | nid = get_nid(parent, i, false); |
| 639 | f2fs_ra_node_page(sbi, nid); | 644 | f2fs_ra_node_page(sbi, nid); |
| @@ -2587,6 +2592,16 @@ bool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid) | |||
| 2587 | f2fs_bug_on(sbi, list_empty(&nm_i->free_nid_list)); | 2592 | f2fs_bug_on(sbi, list_empty(&nm_i->free_nid_list)); |
| 2588 | i = list_first_entry(&nm_i->free_nid_list, | 2593 | i = list_first_entry(&nm_i->free_nid_list, |
| 2589 | struct free_nid, list); | 2594 | struct free_nid, list); |
| 2595 | + | ||
| 2596 | + if (unlikely(is_invalid_nid(sbi, i->nid))) { | ||
| 2597 | + spin_unlock(&nm_i->nid_list_lock); | ||
| 2598 | + f2fs_err(sbi, "Corrupted nid %u in free_nid_list", | ||
| 2599 | + i->nid); | ||
| 2600 | + f2fs_stop_checkpoint(sbi, false, | ||
| 2601 | + STOP_CP_REASON_CORRUPTED_NID); | ||
| 2602 | + return false; | ||
| 2603 | + } | ||
| 2604 | + | ||
| 2590 | *nid = i->nid; | 2605 | *nid = i->nid; |
| 2591 | 2606 | ||
| 2592 | __move_free_nid(sbi, i, FREE_NID, PREALLOC_NID); | 2607 | __move_free_nid(sbi, i, FREE_NID, PREALLOC_NID); |
| @@ -89,6 +89,19 @@ static int iget_set(struct inode *inode, void *opaque) | |||
| 89 | return 0; | 89 | return 0; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | +void gfs2_setup_inode(struct inode *inode) | ||
| 93 | +{ | ||
| 94 | + gfp_t gfp_mask; | ||
| 95 | + | ||
| 96 | + /* | ||
| 97 | + * Ensure all page cache allocations are done from GFP_NOFS context to | ||
| 98 | + * prevent direct reclaim recursion back into the filesystem and blowing | ||
| 99 | + * stacks or deadlocking. | ||
| 100 | + */ | ||
| 101 | + gfp_mask = mapping_gfp_mask(inode->i_mapping); | ||
| 102 | + mapping_set_gfp_mask(inode->i_mapping, gfp_mask & ~__GFP_FS); | ||
| 103 | +} | ||
| 104 | + | ||
| 92 | /** | 105 | /** |
| 93 | * gfs2_inode_lookup - Lookup an inode | 106 | * gfs2_inode_lookup - Lookup an inode |
| 94 | * @sb: The super block | 107 | * @sb: The super block |
| @@ -132,6 +145,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, | |||
| 132 | struct gfs2_glock *io_gl; | 145 | struct gfs2_glock *io_gl; |
| 133 | int extra_flags = 0; | 146 | int extra_flags = 0; |
| 134 | 147 | ||
| 148 | + gfs2_setup_inode(inode); | ||
| 135 | error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, | 149 | error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, |
| 136 | &ip->i_gl); | 150 | &ip->i_gl); |
| 137 | if (unlikely(error)) | 151 | if (unlikely(error)) |
| @@ -684,6 +698,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
| 684 | error = -ENOMEM; | 698 | error = -ENOMEM; |
| 685 | if (!inode) | 699 | if (!inode) |
| 686 | goto fail_gunlock; | 700 | goto fail_gunlock; |
| 701 | + gfs2_setup_inode(inode); | ||
| 687 | ip = GFS2_I(inode); | 702 | ip = GFS2_I(inode); |
| 688 | 703 | ||
| 689 | error = posix_acl_create(dir, &mode, &default_acl, &acl); | 704 | error = posix_acl_create(dir, &mode, &default_acl, &acl); |
| @@ -88,6 +88,7 @@ static inline int gfs2_check_internal_file_size(struct inode *inode, | |||
| 88 | return -EIO; | 88 | return -EIO; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | +void gfs2_setup_inode(struct inode *inode); | ||
| 91 | struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, | 92 | struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, |
| 92 | u64 no_addr, u64 no_formal_ino, | 93 | u64 no_addr, u64 no_formal_ino, |
| 93 | unsigned int blktype); | 94 | unsigned int blktype); |
| @@ -64,15 +64,16 @@ static void gfs2_tune_init(struct gfs2_tune *gt) | |||
| 64 | 64 | ||
| 65 | void free_sbd(struct gfs2_sbd *sdp) | 65 | void free_sbd(struct gfs2_sbd *sdp) |
| 66 | { | 66 | { |
| 67 | - if (sdp->sd_lkstats) | 67 | + struct super_block *sb = sdp->sd_vfs; |
| 68 | - free_percpu(sdp->sd_lkstats); | 68 | + |
| 69 | + free_percpu(sdp->sd_lkstats); | ||
| 70 | + sb->s_fs_info = NULL; | ||
| 69 | kfree(sdp); | 71 | kfree(sdp); |
| 70 | } | 72 | } |
| 71 | 73 | ||
| 72 | static struct gfs2_sbd *init_sbd(struct super_block *sb) | 74 | static struct gfs2_sbd *init_sbd(struct super_block *sb) |
| 73 | { | 75 | { |
| 74 | struct gfs2_sbd *sdp; | 76 | struct gfs2_sbd *sdp; |
| 75 | - struct address_space *mapping; | ||
| 76 | 77 | ||
| 77 | sdp = kzalloc(sizeof(struct gfs2_sbd), GFP_KERNEL); | 78 | sdp = kzalloc(sizeof(struct gfs2_sbd), GFP_KERNEL); |
| 78 | if (!sdp) | 79 | if (!sdp) |
| @@ -103,23 +104,12 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) | |||
| 103 | init_completion(&sdp->sd_journal_ready); | 104 | init_completion(&sdp->sd_journal_ready); |
| 104 | 105 | ||
| 105 | INIT_LIST_HEAD(&sdp->sd_quota_list); | 106 | INIT_LIST_HEAD(&sdp->sd_quota_list); |
| 106 | - mutex_init(&sdp->sd_quota_mutex); | ||
| 107 | mutex_init(&sdp->sd_quota_sync_mutex); | 107 | mutex_init(&sdp->sd_quota_sync_mutex); |
| 108 | init_waitqueue_head(&sdp->sd_quota_wait); | 108 | init_waitqueue_head(&sdp->sd_quota_wait); |
| 109 | spin_lock_init(&sdp->sd_bitmap_lock); | 109 | spin_lock_init(&sdp->sd_bitmap_lock); |
| 110 | 110 | ||
| 111 | INIT_LIST_HEAD(&sdp->sd_sc_inodes_list); | 111 | INIT_LIST_HEAD(&sdp->sd_sc_inodes_list); |
| 112 | 112 | ||
| 113 | - mapping = &sdp->sd_aspace; | ||
| 114 | - | ||
| 115 | - address_space_init_once(mapping); | ||
| 116 | - mapping->a_ops = &gfs2_rgrp_aops; | ||
| 117 | - mapping->host = sb->s_bdev->bd_inode; | ||
| 118 | - mapping->flags = 0; | ||
| 119 | - mapping_set_gfp_mask(mapping, GFP_NOFS); | ||
| 120 | - mapping->private_data = NULL; | ||
| 121 | - mapping->writeback_index = 0; | ||
| 122 | - | ||
| 123 | spin_lock_init(&sdp->sd_log_lock); | 113 | spin_lock_init(&sdp->sd_log_lock); |
| 124 | atomic_set(&sdp->sd_log_pinned, 0); | 114 | atomic_set(&sdp->sd_log_pinned, 0); |
| 125 | INIT_LIST_HEAD(&sdp->sd_log_revokes); | 115 | INIT_LIST_HEAD(&sdp->sd_log_revokes); |
| @@ -173,7 +163,7 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent) | |||
| 173 | return -EINVAL; | 163 | return -EINVAL; |
| 174 | } | 164 | } |
| 175 | 165 | ||
| 176 | - if (sb->sb_bsize < 512 || sb->sb_bsize > PAGE_SIZE || | 166 | + if (sb->sb_bsize < SECTOR_SIZE || sb->sb_bsize > PAGE_SIZE || |
| 177 | (sb->sb_bsize & (sb->sb_bsize - 1))) { | 167 | (sb->sb_bsize & (sb->sb_bsize - 1))) { |
| 178 | pr_warn("Invalid block size\n"); | 168 | pr_warn("Invalid block size\n"); |
| 179 | return -EINVAL; | 169 | return -EINVAL; |
| @@ -185,22 +175,10 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent) | |||
| 185 | return 0; | 175 | return 0; |
| 186 | } | 176 | } |
| 187 | 177 | ||
| 188 | -static void end_bio_io_page(struct bio *bio) | 178 | +static void gfs2_sb_in(struct gfs2_sbd *sdp, const struct gfs2_sb *str) |
| 189 | -{ | ||
| 190 | - struct page *page = bio->bi_private; | ||
| 191 | - | ||
| 192 | - if (!bio->bi_status) | ||
| 193 | - SetPageUptodate(page); | ||
| 194 | - else | ||
| 195 | - pr_warn("error %d reading superblock\n", bio->bi_status); | ||
| 196 | - unlock_page(page); | ||
| 197 | -} | ||
| 198 | - | ||
| 199 | -static void gfs2_sb_in(struct gfs2_sbd *sdp, const void *buf) | ||
| 200 | { | 179 | { |
| 201 | struct gfs2_sb_host *sb = &sdp->sd_sb; | 180 | struct gfs2_sb_host *sb = &sdp->sd_sb; |
| 202 | struct super_block *s = sdp->sd_vfs; | 181 | struct super_block *s = sdp->sd_vfs; |
| 203 | - const struct gfs2_sb *str = buf; | ||
| 204 | 182 | ||
| 205 | sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic); | 183 | sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic); |
| 206 | sb->sb_type = be32_to_cpu(str->sb_header.mh_type); | 184 | sb->sb_type = be32_to_cpu(str->sb_header.mh_type); |
| @@ -215,7 +193,7 @@ static void gfs2_sb_in(struct gfs2_sbd *sdp, const void *buf) | |||
| 215 | 193 | ||
| 216 | memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN); | 194 | memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN); |
| 217 | memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN); | 195 | memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN); |
| 218 | - memcpy(&s->s_uuid, str->sb_uuid, 16); | 196 | + super_set_uuid(s, str->sb_uuid, 16); |
| 219 | } | 197 | } |
| 220 | 198 | ||
| 221 | /** | 199 | /** |
| @@ -239,36 +217,22 @@ static void gfs2_sb_in(struct gfs2_sbd *sdp, const void *buf) | |||
| 239 | 217 | ||
| 240 | static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent) | 218 | static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent) |
| 241 | { | 219 | { |
| 242 | - struct super_block *sb = sdp->sd_vfs; | 220 | + struct gfs2_sb *sb; |
| 243 | - struct gfs2_sb *p; | 221 | + int err; |
| 244 | - struct page *page; | ||
| 245 | - struct bio *bio; | ||
| 246 | 222 | ||
| 247 | - page = alloc_page(GFP_NOFS); | 223 | + sb = kmalloc(PAGE_SIZE, GFP_KERNEL); |
| 248 | - if (unlikely(!page)) | 224 | + if (unlikely(!sb)) |
| 249 | return -ENOMEM; | 225 | return -ENOMEM; |
| 250 | - | 226 | + err = bdev_rw_virt(sdp->sd_vfs->s_bdev, |
| 251 | - ClearPageUptodate(page); | 227 | + sector << (sdp->sd_vfs->s_blocksize_bits - SECTOR_SHIFT), |
| 252 | - ClearPageDirty(page); | 228 | + sb, PAGE_SIZE, REQ_OP_READ | REQ_META); |
| 253 | - lock_page(page); | 229 | + if (err) { |
| 254 | - | 230 | + pr_warn("error %d reading superblock\n", err); |
| 255 | - bio = bio_alloc(sb->s_bdev, 1, REQ_OP_READ | REQ_META, GFP_NOFS); | 231 | + kfree(sb); |
| 256 | - bio->bi_iter.bi_sector = sector * (sb->s_blocksize >> 9); | 232 | + return err; |
| 257 | - __bio_add_page(bio, page, PAGE_SIZE, 0); | ||
| 258 | - | ||
| 259 | - bio->bi_end_io = end_bio_io_page; | ||
| 260 | - bio->bi_private = page; | ||
| 261 | - submit_bio(bio); | ||
| 262 | - wait_on_page_locked(page); | ||
| 263 | - bio_put(bio); | ||
| 264 | - if (!PageUptodate(page)) { | ||
| 265 | - __free_page(page); | ||
| 266 | - return -EIO; | ||
| 267 | } | 233 | } |
| 268 | - p = kmap(page); | 234 | + gfs2_sb_in(sdp, sb); |
| 269 | - gfs2_sb_in(sdp, p); | 235 | + kfree(sb); |
| 270 | - kunmap(page); | ||
| 271 | - __free_page(page); | ||
| 272 | return gfs2_check_sb(sdp, silent); | 236 | return gfs2_check_sb(sdp, silent); |
| 273 | } | 237 | } |
| 274 | 238 | ||
| @@ -293,8 +257,7 @@ static int gfs2_read_sb(struct gfs2_sbd *sdp, int silent) | |||
| 293 | return error; | 257 | return error; |
| 294 | } | 258 | } |
| 295 | 259 | ||
| 296 | - sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - | 260 | + sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - SECTOR_SHIFT; |
| 297 | - GFS2_BASIC_BLOCK_SHIFT; | ||
| 298 | sdp->sd_fsb2bb = BIT(sdp->sd_fsb2bb_shift); | 261 | sdp->sd_fsb2bb = BIT(sdp->sd_fsb2bb_shift); |
| 299 | sdp->sd_diptrs = (sdp->sd_sb.sb_bsize - | 262 | sdp->sd_diptrs = (sdp->sd_sb.sb_bsize - |
| 300 | sizeof(struct gfs2_dinode)) / sizeof(u64); | 263 | sizeof(struct gfs2_dinode)) / sizeof(u64); |
| @@ -522,7 +485,9 @@ static int init_sb(struct gfs2_sbd *sdp, int silent) | |||
| 522 | sdp->sd_sb.sb_bsize, (unsigned int)PAGE_SIZE); | 485 | sdp->sd_sb.sb_bsize, (unsigned int)PAGE_SIZE); |
| 523 | goto out; | 486 | goto out; |
| 524 | } | 487 | } |
| 525 | - sb_set_blocksize(sb, sdp->sd_sb.sb_bsize); | 488 | + ret = -EINVAL; |
| 489 | + if (!sb_set_blocksize(sb, sdp->sd_sb.sb_bsize)) | ||
| 490 | + goto out; | ||
| 526 | 491 | ||
| 527 | /* Get the root inode */ | 492 | /* Get the root inode */ |
| 528 | no_addr = sdp->sd_sb.sb_root_dir.no_addr; | 493 | no_addr = sdp->sd_sb.sb_root_dir.no_addr; |
| @@ -1157,6 +1122,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) | |||
| 1157 | int silent = fc->sb_flags & SB_SILENT; | 1122 | int silent = fc->sb_flags & SB_SILENT; |
| 1158 | struct gfs2_sbd *sdp; | 1123 | struct gfs2_sbd *sdp; |
| 1159 | struct gfs2_holder mount_gh; | 1124 | struct gfs2_holder mount_gh; |
| 1125 | + struct address_space *mapping; | ||
| 1160 | int error; | 1126 | int error; |
| 1161 | 1127 | ||
| 1162 | sdp = init_sbd(sb); | 1128 | sdp = init_sbd(sb); |
| @@ -1178,7 +1144,8 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) | |||
| 1178 | sb->s_flags |= SB_NOSEC; | 1144 | sb->s_flags |= SB_NOSEC; |
| 1179 | sb->s_magic = GFS2_MAGIC; | 1145 | sb->s_magic = GFS2_MAGIC; |
| 1180 | sb->s_op = &gfs2_super_ops; | 1146 | sb->s_op = &gfs2_super_ops; |
| 1181 | - sb->s_d_op = &gfs2_dops; | 1147 | + |
| 1148 | + set_default_d_op(sb, &gfs2_dops); | ||
| 1182 | sb->s_export_op = &gfs2_export_ops; | 1149 | sb->s_export_op = &gfs2_export_ops; |
| 1183 | sb->s_qcop = &gfs2_quotactl_ops; | 1150 | sb->s_qcop = &gfs2_quotactl_ops; |
| 1184 | sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; | 1151 | sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; |
| @@ -1188,10 +1155,12 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) | |||
| 1188 | 1155 | ||
| 1189 | /* Set up the buffer cache and fill in some fake block size values | 1156 | /* Set up the buffer cache and fill in some fake block size values |
| 1190 | to allow us to read-in the on-disk superblock. */ | 1157 | to allow us to read-in the on-disk superblock. */ |
| 1191 | - sdp->sd_sb.sb_bsize = sb_min_blocksize(sb, GFS2_BASIC_BLOCK); | 1158 | + sdp->sd_sb.sb_bsize = sb_min_blocksize(sb, SECTOR_SIZE); |
| 1159 | + error = -EINVAL; | ||
| 1160 | + if (!sdp->sd_sb.sb_bsize) | ||
| 1161 | + goto fail_free; | ||
| 1192 | sdp->sd_sb.sb_bsize_shift = sb->s_blocksize_bits; | 1162 | sdp->sd_sb.sb_bsize_shift = sb->s_blocksize_bits; |
| 1193 | - sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - | 1163 | + sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - SECTOR_SHIFT; |
| 1194 | - GFS2_BASIC_BLOCK_SHIFT; | ||
| 1195 | sdp->sd_fsb2bb = BIT(sdp->sd_fsb2bb_shift); | 1164 | sdp->sd_fsb2bb = BIT(sdp->sd_fsb2bb_shift); |
| 1196 | 1165 | ||
| 1197 | sdp->sd_tune.gt_logd_secs = sdp->sd_args.ar_commit; | 1166 | sdp->sd_tune.gt_logd_secs = sdp->sd_args.ar_commit; |
| @@ -1204,17 +1173,37 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) | |||
| 1204 | sdp->sd_tune.gt_statfs_quantum = 30; | 1173 | sdp->sd_tune.gt_statfs_quantum = 30; |
| 1205 | } | 1174 | } |
| 1206 | 1175 | ||
| 1176 | + /* Set up an address space for metadata writes */ | ||
| 1177 | + sdp->sd_inode = new_inode(sb); | ||
| 1178 | + error = -ENOMEM; | ||
| 1179 | + if (!sdp->sd_inode) | ||
| 1180 | + goto fail_free; | ||
| 1181 | + sdp->sd_inode->i_ino = GFS2_BAD_INO; | ||
| 1182 | + sdp->sd_inode->i_size = OFFSET_MAX; | ||
| 1183 | + | ||
| 1184 | + mapping = gfs2_aspace(sdp); | ||
| 1185 | + mapping->a_ops = &gfs2_rgrp_aops; | ||
| 1186 | + gfs2_setup_inode(sdp->sd_inode); | ||
| 1187 | + | ||
| 1207 | error = init_names(sdp, silent); | 1188 | error = init_names(sdp, silent); |
| 1208 | if (error) | 1189 | if (error) |
| 1209 | - goto fail_free; | 1190 | + goto fail_iput; |
| 1210 | 1191 | ||
| 1211 | snprintf(sdp->sd_fsname, sizeof(sdp->sd_fsname), "%s", sdp->sd_table_name); | 1192 | snprintf(sdp->sd_fsname, sizeof(sdp->sd_fsname), "%s", sdp->sd_table_name); |
| 1212 | 1193 | ||
| 1213 | - sdp->sd_delete_wq = alloc_workqueue("gfs2-delete/%s", | ||
| 1214 | - WQ_MEM_RECLAIM | WQ_FREEZABLE, 0, sdp->sd_fsname); | ||
| 1215 | error = -ENOMEM; | 1194 | error = -ENOMEM; |
| 1195 | + sdp->sd_glock_wq = alloc_workqueue("gfs2-glock/%s", | ||
| 1196 | + WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_FREEZABLE | WQ_PERCPU, | ||
| 1197 | + 0, | ||
| 1198 | + sdp->sd_fsname); | ||
| 1199 | + if (!sdp->sd_glock_wq) | ||
| 1200 | + goto fail_iput; | ||
| 1201 | + | ||
| 1202 | + sdp->sd_delete_wq = alloc_workqueue("gfs2-delete/%s", | ||
| 1203 | + WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_PERCPU, 0, | ||
| 1204 | + sdp->sd_fsname); | ||
| 1216 | if (!sdp->sd_delete_wq) | 1205 | if (!sdp->sd_delete_wq) |
| 1217 | - goto fail_free; | 1206 | + goto fail_glock_wq; |
| 1218 | 1207 | ||
| 1219 | error = gfs2_sys_fs_add(sdp); | 1208 | error = gfs2_sys_fs_add(sdp); |
| 1220 | if (error) | 1209 | if (error) |
| @@ -1291,7 +1280,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) | |||
| 1291 | error = gfs2_make_fs_rw(sdp); | 1280 | error = gfs2_make_fs_rw(sdp); |
| 1292 | 1281 | ||
| 1293 | if (error) { | 1282 | if (error) { |
| 1294 | - gfs2_freeze_unlock(&sdp->sd_freeze_gh); | 1283 | + gfs2_freeze_unlock(sdp); |
| 1295 | gfs2_destroy_threads(sdp); | 1284 | gfs2_destroy_threads(sdp); |
| 1296 | fs_err(sdp, "can't make FS RW: %d\n", error); | 1285 | fs_err(sdp, "can't make FS RW: %d\n", error); |
| 1297 | goto fail_per_node; | 1286 | goto fail_per_node; |
| @@ -1323,9 +1312,13 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) | |||
| 1323 | gfs2_sys_fs_del(sdp); | 1312 | gfs2_sys_fs_del(sdp); |
| 1324 | fail_delete_wq: | 1313 | fail_delete_wq: |
| 1325 | destroy_workqueue(sdp->sd_delete_wq); | 1314 | destroy_workqueue(sdp->sd_delete_wq); |
| 1315 | +fail_glock_wq: | ||
| 1316 | + if (sdp->sd_glock_wq) | ||
| 1317 | + destroy_workqueue(sdp->sd_glock_wq); | ||
| 1318 | +fail_iput: | ||
| 1319 | + iput(sdp->sd_inode); | ||
| 1326 | fail_free: | 1320 | fail_free: |
| 1327 | free_sbd(sdp); | 1321 | free_sbd(sdp); |
| 1328 | - sb->s_fs_info = NULL; | ||
| 1329 | return error; | 1322 | return error; |
| 1330 | } | 1323 | } |
| 1331 | 1324 | ||
| @@ -1763,7 +1756,7 @@ static void gfs2_evict_inodes(struct super_block *sb) | |||
| 1763 | spin_unlock(&inode->i_lock); | 1756 | spin_unlock(&inode->i_lock); |
| 1764 | continue; | 1757 | continue; |
| 1765 | } | 1758 | } |
| 1766 | - atomic_inc(&inode->i_count); | 1759 | + __iget(inode); |
| 1767 | spin_unlock(&inode->i_lock); | 1760 | spin_unlock(&inode->i_lock); |
| 1768 | spin_unlock(&sb->s_inode_list_lock); | 1761 | spin_unlock(&sb->s_inode_list_lock); |
| 1769 | 1762 | ||
| @@ -3,6 +3,7 @@ | |||
| 3 | * Copyright (c) 2022 Paulo Alcantara <palcantara@suse.de> | 3 | * Copyright (c) 2022 Paulo Alcantara <palcantara@suse.de> |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | +#include <linux/namei.h> | ||
| 6 | #include "cifsproto.h" | 7 | #include "cifsproto.h" |
| 7 | #include "cifs_debug.h" | 8 | #include "cifs_debug.h" |
| 8 | #include "dns_resolve.h" | 9 | #include "dns_resolve.h" |
| @@ -13,21 +13,22 @@ | |||
| 13 | 13 | ||
| 14 | #define F2FS_SUPER_OFFSET 1024 /* byte-size offset */ | 14 | #define F2FS_SUPER_OFFSET 1024 /* byte-size offset */ |
| 15 | #define F2FS_MIN_LOG_SECTOR_SIZE 9 /* 9 bits for 512 bytes */ | 15 | #define F2FS_MIN_LOG_SECTOR_SIZE 9 /* 9 bits for 512 bytes */ |
| 16 | -#define F2FS_MAX_LOG_SECTOR_SIZE 12 /* 12 bits for 4096 bytes */ | 16 | +#define F2FS_MAX_LOG_SECTOR_SIZE PAGE_SHIFT /* Max is Block Size */ |
| 17 | -#define F2FS_LOG_SECTORS_PER_BLOCK 3 /* log number for sector/blk */ | 17 | +#define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sector/blk */ |
| 18 | -#define F2FS_BLKSIZE 4096 /* support only 4KB block */ | 18 | +#define F2FS_BLKSIZE PAGE_SIZE /* support only block == page */ |
| 19 | -#define F2FS_BLKSIZE_BITS 12 /* bits for F2FS_BLKSIZE */ | 19 | +#define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */ |
| 20 | #define F2FS_MAX_EXTENSION 64 /* # of extension entries */ | 20 | #define F2FS_MAX_EXTENSION 64 /* # of extension entries */ |
| 21 | #define F2FS_EXTENSION_LEN 8 /* max size of extension */ | 21 | #define F2FS_EXTENSION_LEN 8 /* max size of extension */ |
| 22 | -#define F2FS_BLK_ALIGN(x) (((x) + F2FS_BLKSIZE - 1) >> F2FS_BLKSIZE_BITS) | ||
| 23 | 22 | ||
| 24 | #define NULL_ADDR ((block_t)0) /* used as block_t addresses */ | 23 | #define NULL_ADDR ((block_t)0) /* used as block_t addresses */ |
| 25 | #define NEW_ADDR ((block_t)-1) /* used as block_t addresses */ | 24 | #define NEW_ADDR ((block_t)-1) /* used as block_t addresses */ |
| 26 | #define COMPRESS_ADDR ((block_t)-2) /* used as compressed data flag */ | 25 | #define COMPRESS_ADDR ((block_t)-2) /* used as compressed data flag */ |
| 27 | 26 | ||
| 28 | -#define F2FS_BYTES_TO_BLK(bytes) ((bytes) >> F2FS_BLKSIZE_BITS) | 27 | +#define F2FS_BLKSIZE_MASK (F2FS_BLKSIZE - 1) |
| 29 | -#define F2FS_BLK_TO_BYTES(blk) ((blk) << F2FS_BLKSIZE_BITS) | 28 | +#define F2FS_BYTES_TO_BLK(bytes) ((unsigned long long)(bytes) >> F2FS_BLKSIZE_BITS) |
| 29 | +#define F2FS_BLK_TO_BYTES(blk) ((unsigned long long)(blk) << F2FS_BLKSIZE_BITS) | ||
| 30 | #define F2FS_BLK_END_BYTES(blk) (F2FS_BLK_TO_BYTES(blk + 1) - 1) | 30 | #define F2FS_BLK_END_BYTES(blk) (F2FS_BLK_TO_BYTES(blk + 1) - 1) |
| 31 | +#define F2FS_BLK_ALIGN(x) (F2FS_BYTES_TO_BLK((x) + F2FS_BLKSIZE - 1)) | ||
| 31 | 32 | ||
| 32 | /* 0, 1(node nid), 2(meta nid) are reserved node id */ | 33 | /* 0, 1(node nid), 2(meta nid) are reserved node id */ |
| 33 | #define F2FS_RESERVED_NODE_NUM 3 | 34 | #define F2FS_RESERVED_NODE_NUM 3 |
| @@ -77,6 +78,8 @@ enum stop_cp_reason { | |||
| 77 | STOP_CP_REASON_UPDATE_INODE, | 78 | STOP_CP_REASON_UPDATE_INODE, |
| 78 | STOP_CP_REASON_FLUSH_FAIL, | 79 | STOP_CP_REASON_FLUSH_FAIL, |
| 79 | STOP_CP_REASON_NO_SEGMENT, | 80 | STOP_CP_REASON_NO_SEGMENT, |
| 81 | + STOP_CP_REASON_CORRUPTED_FREE_BITMAP, | ||
| 82 | + STOP_CP_REASON_CORRUPTED_NID, | ||
| 80 | STOP_CP_REASON_MAX, | 83 | STOP_CP_REASON_MAX, |
| 81 | }; | 84 | }; |
| 82 | 85 | ||
| @@ -207,14 +210,14 @@ struct f2fs_checkpoint { | |||
| 207 | unsigned char sit_nat_version_bitmap[]; | 210 | unsigned char sit_nat_version_bitmap[]; |
| 208 | } __packed; | 211 | } __packed; |
| 209 | 212 | ||
| 210 | -#define CP_CHKSUM_OFFSET 4092 /* default chksum offset in checkpoint */ | 213 | +#define CP_CHKSUM_OFFSET (F2FS_BLKSIZE - sizeof(__le32)) /* default chksum offset in checkpoint */ |
| 211 | #define CP_MIN_CHKSUM_OFFSET \ | 214 | #define CP_MIN_CHKSUM_OFFSET \ |
| 212 | (offsetof(struct f2fs_checkpoint, sit_nat_version_bitmap)) | 215 | (offsetof(struct f2fs_checkpoint, sit_nat_version_bitmap)) |
| 213 | 216 | ||
| 214 | /* | 217 | /* |
| 215 | * For orphan inode management | 218 | * For orphan inode management |
| 216 | */ | 219 | */ |
| 217 | -#define F2FS_ORPHANS_PER_BLOCK 1020 | 220 | +#define F2FS_ORPHANS_PER_BLOCK ((F2FS_BLKSIZE - 4 * sizeof(__le32)) / sizeof(__le32)) |
| 218 | 221 | ||
| 219 | #define GET_ORPHAN_BLOCKS(n) (((n) + F2FS_ORPHANS_PER_BLOCK - 1) / \ | 222 | #define GET_ORPHAN_BLOCKS(n) (((n) + F2FS_ORPHANS_PER_BLOCK - 1) / \ |
| 220 | F2FS_ORPHANS_PER_BLOCK) | 223 | F2FS_ORPHANS_PER_BLOCK) |
| @@ -240,17 +243,33 @@ struct f2fs_extent { | |||
| 240 | #define F2FS_NAME_LEN 255 | 243 | #define F2FS_NAME_LEN 255 |
| 241 | /* 200 bytes for inline xattrs by default */ | 244 | /* 200 bytes for inline xattrs by default */ |
| 242 | #define DEFAULT_INLINE_XATTR_ADDRS 50 | 245 | #define DEFAULT_INLINE_XATTR_ADDRS 50 |
| 243 | -#define DEF_ADDRS_PER_INODE 923 /* Address Pointers in an Inode */ | 246 | + |
| 247 | +#define OFFSET_OF_END_OF_I_EXT 360 | ||
| 248 | +#define SIZE_OF_I_NID 20 | ||
| 249 | + | ||
| 250 | +struct node_footer { | ||
| 251 | + __le32 nid; /* node id */ | ||
| 252 | + __le32 ino; /* inode number */ | ||
| 253 | + __le32 flag; /* include cold/fsync/dentry marks and offset */ | ||
| 254 | + __le64 cp_ver; /* checkpoint version */ | ||
| 255 | + __le32 next_blkaddr; /* next node page block address */ | ||
| 256 | +} __packed; | ||
| 257 | + | ||
| 258 | +/* Address Pointers in an Inode */ | ||
| 259 | +#define DEF_ADDRS_PER_INODE ((F2FS_BLKSIZE - OFFSET_OF_END_OF_I_EXT \ | ||
| 260 | + - SIZE_OF_I_NID \ | ||
| 261 | + - sizeof(struct node_footer)) / sizeof(__le32)) | ||
| 244 | #define CUR_ADDRS_PER_INODE(inode) (DEF_ADDRS_PER_INODE - \ | 262 | #define CUR_ADDRS_PER_INODE(inode) (DEF_ADDRS_PER_INODE - \ |
| 245 | get_extra_isize(inode)) | 263 | get_extra_isize(inode)) |
| 246 | #define DEF_NIDS_PER_INODE 5 /* Node IDs in an Inode */ | 264 | #define DEF_NIDS_PER_INODE 5 /* Node IDs in an Inode */ |
| 247 | -#define ADDRS_PER_INODE(inode) addrs_per_inode(inode) | 265 | +#define ADDRS_PER_INODE(inode) addrs_per_page(inode, true) |
| 248 | -#define DEF_ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */ | 266 | +/* Address Pointers in a Direct Block */ |
| 249 | -#define ADDRS_PER_BLOCK(inode) addrs_per_block(inode) | 267 | +#define DEF_ADDRS_PER_BLOCK ((F2FS_BLKSIZE - sizeof(struct node_footer)) / sizeof(__le32)) |
| 250 | -#define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block */ | 268 | +#define ADDRS_PER_BLOCK(inode) addrs_per_page(inode, false) |
| 269 | +/* Node IDs in an Indirect Block */ | ||
| 270 | +#define NIDS_PER_BLOCK ((F2FS_BLKSIZE - sizeof(struct node_footer)) / sizeof(__le32)) | ||
| 251 | 271 | ||
| 252 | -#define ADDRS_PER_PAGE(page, inode) \ | 272 | +#define ADDRS_PER_PAGE(folio, inode) (addrs_per_page(inode, IS_INODE(folio))) |
| 253 | - (IS_INODE(page) ? ADDRS_PER_INODE(inode) : ADDRS_PER_BLOCK(inode)) | ||
| 254 | 273 | ||
| 255 | #define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1) | 274 | #define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1) |
| 256 | #define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2) | 275 | #define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2) |
| @@ -339,14 +358,6 @@ enum { | |||
| 339 | 358 | ||
| 340 | #define OFFSET_BIT_MASK GENMASK(OFFSET_BIT_SHIFT - 1, 0) | 359 | #define OFFSET_BIT_MASK GENMASK(OFFSET_BIT_SHIFT - 1, 0) |
| 341 | 360 | ||
| 342 | -struct node_footer { | ||
| 343 | - __le32 nid; /* node id */ | ||
| 344 | - __le32 ino; /* inode number */ | ||
| 345 | - __le32 flag; /* include cold/fsync/dentry marks and offset */ | ||
| 346 | - __le64 cp_ver; /* checkpoint version */ | ||
| 347 | - __le32 next_blkaddr; /* next node page block address */ | ||
| 348 | -} __packed; | ||
| 349 | - | ||
| 350 | struct f2fs_node { | 361 | struct f2fs_node { |
| 351 | /* can be one of three types: inode, direct, and indirect types */ | 362 | /* can be one of three types: inode, direct, and indirect types */ |
| 352 | union { | 363 | union { |
| @@ -360,7 +371,7 @@ struct f2fs_node { | |||
| 360 | /* | 371 | /* |
| 361 | * For NAT entries | 372 | * For NAT entries |
| 362 | */ | 373 | */ |
| 363 | -#define NAT_ENTRY_PER_BLOCK (PAGE_SIZE / sizeof(struct f2fs_nat_entry)) | 374 | +#define NAT_ENTRY_PER_BLOCK (F2FS_BLKSIZE / sizeof(struct f2fs_nat_entry)) |
| 364 | 375 | ||
| 365 | struct f2fs_nat_entry { | 376 | struct f2fs_nat_entry { |
| 366 | __u8 version; /* latest version of cached nat entry */ | 377 | __u8 version; /* latest version of cached nat entry */ |
| @@ -375,16 +386,18 @@ struct f2fs_nat_block { | |||
| 375 | /* | 386 | /* |
| 376 | * For SIT entries | 387 | * For SIT entries |
| 377 | * | 388 | * |
| 378 | - * Each segment is 2MB in size by default so that a bitmap for validity of | 389 | + * A validity bitmap of 64 bytes covers 512 blocks of area. For a 4K page size, |
| 379 | - * there-in blocks should occupy 64 bytes, 512 bits. | 390 | + * this results in a segment size of 2MB. For 16k pages, the default segment size |
| 391 | + * is 8MB. | ||
| 380 | * Not allow to change this. | 392 | * Not allow to change this. |
| 381 | */ | 393 | */ |
| 382 | #define SIT_VBLOCK_MAP_SIZE 64 | 394 | #define SIT_VBLOCK_MAP_SIZE 64 |
| 383 | -#define SIT_ENTRY_PER_BLOCK (PAGE_SIZE / sizeof(struct f2fs_sit_entry)) | 395 | +#define SIT_ENTRY_PER_BLOCK (F2FS_BLKSIZE / sizeof(struct f2fs_sit_entry)) |
| 384 | 396 | ||
| 385 | /* | 397 | /* |
| 386 | * F2FS uses 4 bytes to represent block address. As a result, supported size of | 398 | * F2FS uses 4 bytes to represent block address. As a result, supported size of |
| 387 | - * disk is 16 TB and it equals to 16 * 1024 * 1024 / 2 segments. | 399 | + * disk is 16 TB for a 4K page size and 64 TB for a 16K page size and it equals |
| 400 | + * to 16 * 1024 * 1024 / 2 segments. | ||
| 388 | */ | 401 | */ |
| 389 | #define F2FS_MAX_SEGMENT ((16 * 1024 * 1024) / 2) | 402 | #define F2FS_MAX_SEGMENT ((16 * 1024 * 1024) / 2) |
| 390 | 403 | ||
| @@ -414,8 +427,10 @@ struct f2fs_sit_block { | |||
| 414 | /* | 427 | /* |
| 415 | * For segment summary | 428 | * For segment summary |
| 416 | * | 429 | * |
| 417 | - * One summary block contains exactly 512 summary entries, which represents | 430 | + * One summary block with 4KB size contains exactly 512 summary entries, which |
| 418 | - * exactly 2MB segment by default. Not allow to change the basic units. | 431 | + * represents exactly one segment with 2MB size. |
| 432 | + * Similarly, in the case of block with 16KB size, it represents one segment with 8MB size. | ||
| 433 | + * Not allow to change the basic units. | ||
| 419 | * | 434 | * |
| 420 | * NOTE: For initializing fields, you must use set_summary | 435 | * NOTE: For initializing fields, you must use set_summary |
| 421 | * | 436 | * |
| @@ -426,12 +441,12 @@ struct f2fs_sit_block { | |||
| 426 | * from node's page's beginning to get a data block address. | 441 | * from node's page's beginning to get a data block address. |
| 427 | * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node) | 442 | * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node) |
| 428 | */ | 443 | */ |
| 429 | -#define ENTRIES_IN_SUM 512 | 444 | +#define ENTRIES_IN_SUM (F2FS_BLKSIZE / 8) |
| 430 | -#define SUMMARY_SIZE (7) /* sizeof(struct summary) */ | 445 | +#define SUMMARY_SIZE (7) /* sizeof(struct f2fs_summary) */ |
| 431 | #define SUM_FOOTER_SIZE (5) /* sizeof(struct summary_footer) */ | 446 | #define SUM_FOOTER_SIZE (5) /* sizeof(struct summary_footer) */ |
| 432 | #define SUM_ENTRY_SIZE (SUMMARY_SIZE * ENTRIES_IN_SUM) | 447 | #define SUM_ENTRY_SIZE (SUMMARY_SIZE * ENTRIES_IN_SUM) |
| 433 | 448 | ||
| 434 | -/* a summary entry for a 4KB-sized block in a segment */ | 449 | +/* a summary entry for a block in a segment */ |
| 435 | struct f2fs_summary { | 450 | struct f2fs_summary { |
| 436 | __le32 nid; /* parent node id */ | 451 | __le32 nid; /* parent node id */ |
| 437 | union { | 452 | union { |
| @@ -515,7 +530,7 @@ struct f2fs_journal { | |||
| 515 | }; | 530 | }; |
| 516 | } __packed; | 531 | } __packed; |
| 517 | 532 | ||
| 518 | -/* 4KB-sized summary block structure */ | 533 | +/* Block-sized summary block structure */ |
| 519 | struct f2fs_summary_block { | 534 | struct f2fs_summary_block { |
| 520 | struct f2fs_summary entries[ENTRIES_IN_SUM]; | 535 | struct f2fs_summary entries[ENTRIES_IN_SUM]; |
| 521 | struct f2fs_journal journal; | 536 | struct f2fs_journal journal; |
| @@ -546,6 +561,7 @@ typedef __le32 f2fs_hash_t; | |||
| 546 | 561 | ||
| 547 | /* | 562 | /* |
| 548 | * space utilization of regular dentry and inline dentry (w/o extra reservation) | 563 | * space utilization of regular dentry and inline dentry (w/o extra reservation) |
| 564 | + * when block size is 4KB. | ||
| 549 | * regular dentry inline dentry (def) inline dentry (min) | 565 | * regular dentry inline dentry (def) inline dentry (min) |
| 550 | * bitmap 1 * 27 = 27 1 * 23 = 23 1 * 1 = 1 | 566 | * bitmap 1 * 27 = 27 1 * 23 = 23 1 * 1 = 1 |
| 551 | * reserved 1 * 3 = 3 1 * 7 = 7 1 * 1 = 1 | 567 | * reserved 1 * 3 = 3 1 * 7 = 7 1 * 1 = 1 |
| @@ -556,11 +572,14 @@ typedef __le32 f2fs_hash_t; | |||
| 556 | * Note: there are more reserved space in inline dentry than in regular | 572 | * Note: there are more reserved space in inline dentry than in regular |
| 557 | * dentry, when converting inline dentry we should handle this carefully. | 573 | * dentry, when converting inline dentry we should handle this carefully. |
| 558 | */ | 574 | */ |
| 559 | -#define NR_DENTRY_IN_BLOCK 214 /* the number of dentry in a block */ | 575 | + |
| 576 | +/* the number of dentry in a block */ | ||
| 577 | +#define NR_DENTRY_IN_BLOCK ((BITS_PER_BYTE * F2FS_BLKSIZE) / \ | ||
| 578 | + ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * BITS_PER_BYTE + 1)) | ||
| 560 | #define SIZE_OF_DIR_ENTRY 11 /* by byte */ | 579 | #define SIZE_OF_DIR_ENTRY 11 /* by byte */ |
| 561 | #define SIZE_OF_DENTRY_BITMAP ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \ | 580 | #define SIZE_OF_DENTRY_BITMAP ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \ |
| 562 | BITS_PER_BYTE) | 581 | BITS_PER_BYTE) |
| 563 | -#define SIZE_OF_RESERVED (PAGE_SIZE - ((SIZE_OF_DIR_ENTRY + \ | 582 | +#define SIZE_OF_RESERVED (F2FS_BLKSIZE - ((SIZE_OF_DIR_ENTRY + \ |
| 564 | F2FS_SLOT_LEN) * \ | 583 | F2FS_SLOT_LEN) * \ |
| 565 | NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP)) | 584 | NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP)) |
| 566 | #define MIN_INLINE_DENTRY_SIZE 40 /* just include '.' and '..' entries */ | 585 | #define MIN_INLINE_DENTRY_SIZE 40 /* just include '.' and '..' entries */ |
| @@ -573,7 +592,7 @@ struct f2fs_dir_entry { | |||
| 573 | __u8 file_type; /* file type */ | 592 | __u8 file_type; /* file type */ |
| 574 | } __packed; | 593 | } __packed; |
| 575 | 594 | ||
| 576 | -/* 4KB-sized directory entry block */ | 595 | +/* Block-sized directory entry block */ |
| 577 | struct f2fs_dentry_block { | 596 | struct f2fs_dentry_block { |
| 578 | /* validity bitmap for directory entries in each block */ | 597 | /* validity bitmap for directory entries in each block */ |
| 579 | __u8 dentry_bitmap[SIZE_OF_DENTRY_BITMAP]; | 598 | __u8 dentry_bitmap[SIZE_OF_DENTRY_BITMAP]; |
| @@ -914,6 +914,11 @@ static int convert___skb_to_skb(struct sk_buff *skb, struct __sk_buff *__skb) | |||
| 914 | 914 | ||
| 915 | if (__skb->gso_segs > GSO_MAX_SEGS) | 915 | if (__skb->gso_segs > GSO_MAX_SEGS) |
| 916 | return -EINVAL; | 916 | return -EINVAL; |
| 917 | + | ||
| 918 | + /* Currently GSO type is zero/unset. If this gets extended with | ||
| 919 | + * a small list of accepted GSO types in future, the filter for | ||
| 920 | + * an unset GSO type in bpf_clone_redirect() can be lifted. | ||
| 921 | + */ | ||
| 917 | skb_shinfo(skb)->gso_segs = __skb->gso_segs; | 922 | skb_shinfo(skb)->gso_segs = __skb->gso_segs; |
| 918 | skb_shinfo(skb)->gso_size = __skb->gso_size; | 923 | skb_shinfo(skb)->gso_size = __skb->gso_size; |
| 919 | skb_shinfo(skb)->hwtstamps.hwtstamp = __skb->hwtstamp; | 924 | skb_shinfo(skb)->hwtstamps.hwtstamp = __skb->hwtstamp; |
| @@ -2449,6 +2449,13 @@ BPF_CALL_3(bpf_clone_redirect, struct sk_buff *, skb, u32, ifindex, u64, flags) | |||
| 2449 | if (unlikely(flags & (~(BPF_F_INGRESS) | BPF_F_REDIRECT_INTERNAL))) | 2449 | if (unlikely(flags & (~(BPF_F_INGRESS) | BPF_F_REDIRECT_INTERNAL))) |
| 2450 | return -EINVAL; | 2450 | return -EINVAL; |
| 2451 | 2451 | ||
| 2452 | + /* BPF test infra's convert___skb_to_skb() can create type-less | ||
| 2453 | + * GSO packets. gso_features_check() will detect this as a bad | ||
| 2454 | + * offload. However, lets not leak them out in the first place. | ||
| 2455 | + */ | ||
| 2456 | + if (unlikely(skb_is_gso(skb) && !skb_shinfo(skb)->gso_type)) | ||
| 2457 | + return -EBADMSG; | ||
| 2458 | + | ||
| 2452 | dev = dev_get_by_index_rcu(dev_net(skb->dev), ifindex); | 2459 | dev = dev_get_by_index_rcu(dev_net(skb->dev), ifindex); |
| 2453 | if (unlikely(!dev)) | 2460 | if (unlikely(!dev)) |
| 2454 | return -EINVAL; | 2461 | return -EINVAL; |
| @@ -186,10 +186,15 @@ int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm, | |||
| 186 | coalesced_mmio_in_range(dev, zone->addr, zone->size)) { | 186 | coalesced_mmio_in_range(dev, zone->addr, zone->size)) { |
| 187 | r = kvm_io_bus_unregister_dev(kvm, | 187 | r = kvm_io_bus_unregister_dev(kvm, |
| 188 | zone->pio ? KVM_PIO_BUS : KVM_MMIO_BUS, &dev->dev); | 188 | zone->pio ? KVM_PIO_BUS : KVM_MMIO_BUS, &dev->dev); |
| 189 | + | ||
| 190 | + kvm_iodevice_destructor(&dev->dev); | ||
| 191 | + | ||
| 189 | /* | 192 | /* |
| 190 | * On failure, unregister destroys all devices on the | 193 | * On failure, unregister destroys all devices on the |
| 191 | - * bus, including the target device. There's no need | 194 | + * bus _except_ the target device, i.e. coalesced_zones |
| 192 | - * to restart the walk as there aren't any zones left. | 195 | + * has been modified. Bail after destroying the target |
| 196 | + * device, there's no need to restart the walk as there | ||
| 197 | + * aren't any zones left. | ||
| 193 | */ | 198 | */ |
| 194 | if (r) | 199 | if (r) |
| 195 | break; | 200 | break; |