Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'drm-misc-next-2025-08-21' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next

drm-misc-next for v6.18:

Core Changes:

bridge:
- Support Content Protection property

gpuvm:
- Support madvice in Xe driver

mipi:
- Add more multi-read/write helpers for improved error handling

Driver Changes:

amdxdna:
- Refactoring wrt. hardware contexts

bridge:
- display-connector: Improve DP display detection

panel:
- Fix includes in various drivers

panthor:
- Add support for Mali G710, G510, G310, Gx15, Gx20, Gx25
- Improve cache flushing

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://lore.kernel.org/r/20250821073822.GA45904@2a02-2454-fd5e-fd00-8f09-b5f-980b-a7ef.dyn6.pyur.net

Dave Airlie 1cd0c7af dd489c01

+861 -562
+22 -16
drivers/accel/amdxdna/aie2_ctx.c
··· 133 133 dma_fence_put(fence); 134 134 } 135 135 136 + static int aie2_hwctx_suspend_cb(struct amdxdna_hwctx *hwctx, void *arg) 137 + { 138 + struct amdxdna_dev *xdna = hwctx->client->xdna; 139 + 140 + aie2_hwctx_wait_for_idle(hwctx); 141 + aie2_hwctx_stop(xdna, hwctx, NULL); 142 + aie2_hwctx_status_shift_stop(hwctx); 143 + 144 + return 0; 145 + } 146 + 136 147 void aie2_hwctx_suspend(struct amdxdna_client *client) 137 148 { 138 149 struct amdxdna_dev *xdna = client->xdna; 139 - struct amdxdna_hwctx *hwctx; 140 - unsigned long hwctx_id; 141 150 142 151 /* 143 152 * Command timeout is unlikely. But if it happens, it doesn't ··· 154 145 * and abort all commands. 155 146 */ 156 147 drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock)); 157 - guard(mutex)(&client->hwctx_lock); 158 - amdxdna_for_each_hwctx(client, hwctx_id, hwctx) { 159 - aie2_hwctx_wait_for_idle(hwctx); 160 - aie2_hwctx_stop(xdna, hwctx, NULL); 161 - aie2_hwctx_status_shift_stop(hwctx); 162 - } 148 + amdxdna_hwctx_walk(client, NULL, aie2_hwctx_suspend_cb); 163 149 } 164 150 165 - void aie2_hwctx_resume(struct amdxdna_client *client) 151 + static int aie2_hwctx_resume_cb(struct amdxdna_hwctx *hwctx, void *arg) 152 + { 153 + struct amdxdna_dev *xdna = hwctx->client->xdna; 154 + 155 + aie2_hwctx_status_restore(hwctx); 156 + return aie2_hwctx_restart(xdna, hwctx); 157 + } 158 + 159 + int aie2_hwctx_resume(struct amdxdna_client *client) 166 160 { 167 161 struct amdxdna_dev *xdna = client->xdna; 168 - struct amdxdna_hwctx *hwctx; 169 - unsigned long hwctx_id; 170 162 171 163 /* 172 164 * The resume path cannot guarantee that mailbox channel can be ··· 175 165 * mailbox channel, error will return. 176 166 */ 177 167 drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock)); 178 - guard(mutex)(&client->hwctx_lock); 179 - amdxdna_for_each_hwctx(client, hwctx_id, hwctx) { 180 - aie2_hwctx_status_restore(hwctx); 181 - aie2_hwctx_restart(xdna, hwctx); 182 - } 168 + return amdxdna_hwctx_walk(client, NULL, aie2_hwctx_resume_cb); 183 169 } 184 170 185 171 static void
+12 -9
drivers/accel/amdxdna/aie2_message.c
··· 290 290 return 0; 291 291 } 292 292 293 + static int amdxdna_hwctx_col_map(struct amdxdna_hwctx *hwctx, void *arg) 294 + { 295 + u32 *bitmap = arg; 296 + 297 + *bitmap |= GENMASK(hwctx->start_col + hwctx->num_col - 1, hwctx->start_col); 298 + 299 + return 0; 300 + } 301 + 293 302 int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf, 294 303 u32 size, u32 *cols_filled) 295 304 { 296 305 DECLARE_AIE2_MSG(aie_column_info, MSG_OP_QUERY_COL_STATUS); 297 306 struct amdxdna_dev *xdna = ndev->xdna; 298 307 struct amdxdna_client *client; 299 - struct amdxdna_hwctx *hwctx; 300 - unsigned long hwctx_id; 301 308 dma_addr_t dma_addr; 302 309 u32 aie_bitmap = 0; 303 310 u8 *buff_addr; 304 - int ret, idx; 311 + int ret; 305 312 306 313 buff_addr = dma_alloc_noncoherent(xdna->ddev.dev, size, &dma_addr, 307 314 DMA_FROM_DEVICE, GFP_KERNEL); ··· 316 309 return -ENOMEM; 317 310 318 311 /* Go through each hardware context and mark the AIE columns that are active */ 319 - list_for_each_entry(client, &xdna->client_list, node) { 320 - idx = srcu_read_lock(&client->hwctx_srcu); 321 - amdxdna_for_each_hwctx(client, hwctx_id, hwctx) 322 - aie_bitmap |= amdxdna_hwctx_col_map(hwctx); 323 - srcu_read_unlock(&client->hwctx_srcu, idx); 324 - } 312 + list_for_each_entry(client, &xdna->client_list, node) 313 + amdxdna_hwctx_walk(client, &aie_bitmap, amdxdna_hwctx_col_map); 325 314 326 315 *cols_filled = 0; 327 316 req.dump_buff_addr = dma_addr;
+46 -51
drivers/accel/amdxdna/aie2_pci.c
··· 10 10 #include <drm/drm_managed.h> 11 11 #include <drm/drm_print.h> 12 12 #include <drm/gpu_scheduler.h> 13 + #include <linux/cleanup.h> 13 14 #include <linux/errno.h> 14 15 #include <linux/firmware.h> 15 16 #include <linux/iommu.h> ··· 466 465 return ret; 467 466 } 468 467 469 - list_for_each_entry(client, &xdna->client_list, node) 470 - aie2_hwctx_resume(client); 468 + list_for_each_entry(client, &xdna->client_list, node) { 469 + ret = aie2_hwctx_resume(client); 470 + if (ret) 471 + break; 472 + } 471 473 472 474 return ret; 473 475 } ··· 783 779 return ret; 784 780 } 785 781 786 - static int aie2_get_hwctx_status(struct amdxdna_client *client, 787 - struct amdxdna_drm_get_info *args) 782 + static int aie2_hwctx_status_cb(struct amdxdna_hwctx *hwctx, void *arg) 788 783 { 789 - struct amdxdna_drm_query_hwctx __user *buf; 790 - struct amdxdna_dev *xdna = client->xdna; 791 - struct amdxdna_drm_query_hwctx *tmp; 792 - struct amdxdna_client *tmp_client; 793 - struct amdxdna_hwctx *hwctx; 794 - unsigned long hwctx_id; 795 - bool overflow = false; 796 - u32 req_bytes = 0; 797 - u32 hw_i = 0; 798 - int ret = 0; 799 - int idx; 784 + struct amdxdna_drm_query_hwctx __user *buf, *tmp __free(kfree) = NULL; 785 + struct amdxdna_drm_get_info *get_info_args = arg; 800 786 801 - drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock)); 787 + if (get_info_args->buffer_size < sizeof(*tmp)) 788 + return -EINVAL; 802 789 803 790 tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); 804 791 if (!tmp) 805 792 return -ENOMEM; 806 793 807 - buf = u64_to_user_ptr(args->buffer); 794 + tmp->pid = hwctx->client->pid; 795 + tmp->context_id = hwctx->id; 796 + tmp->start_col = hwctx->start_col; 797 + tmp->num_col = hwctx->num_col; 798 + tmp->command_submissions = hwctx->priv->seq; 799 + tmp->command_completions = hwctx->priv->completed; 800 + 801 + buf = u64_to_user_ptr(get_info_args->buffer); 802 + 803 + if (copy_to_user(buf, tmp, sizeof(*tmp))) 804 + return -EFAULT; 805 + 806 + get_info_args->buffer += sizeof(*tmp); 807 + get_info_args->buffer_size -= sizeof(*tmp); 808 + 809 + return 0; 810 + } 811 + 812 + static int aie2_get_hwctx_status(struct amdxdna_client *client, 813 + struct amdxdna_drm_get_info *args) 814 + { 815 + struct amdxdna_dev *xdna = client->xdna; 816 + struct amdxdna_drm_get_info info_args; 817 + struct amdxdna_client *tmp_client; 818 + int ret; 819 + 820 + drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock)); 821 + 822 + info_args.buffer = args->buffer; 823 + info_args.buffer_size = args->buffer_size; 824 + 808 825 list_for_each_entry(tmp_client, &xdna->client_list, node) { 809 - idx = srcu_read_lock(&tmp_client->hwctx_srcu); 810 - amdxdna_for_each_hwctx(tmp_client, hwctx_id, hwctx) { 811 - req_bytes += sizeof(*tmp); 812 - if (args->buffer_size < req_bytes) { 813 - /* Continue iterating to get the required size */ 814 - overflow = true; 815 - continue; 816 - } 817 - 818 - memset(tmp, 0, sizeof(*tmp)); 819 - tmp->pid = tmp_client->pid; 820 - tmp->context_id = hwctx->id; 821 - tmp->start_col = hwctx->start_col; 822 - tmp->num_col = hwctx->num_col; 823 - tmp->command_submissions = hwctx->priv->seq; 824 - tmp->command_completions = hwctx->priv->completed; 825 - 826 - if (copy_to_user(&buf[hw_i], tmp, sizeof(*tmp))) { 827 - ret = -EFAULT; 828 - srcu_read_unlock(&tmp_client->hwctx_srcu, idx); 829 - goto out; 830 - } 831 - hw_i++; 832 - } 833 - srcu_read_unlock(&tmp_client->hwctx_srcu, idx); 826 + ret = amdxdna_hwctx_walk(tmp_client, &info_args, aie2_hwctx_status_cb); 827 + if (ret) 828 + break; 834 829 } 835 830 836 - if (overflow) { 837 - XDNA_ERR(xdna, "Invalid buffer size. Given: %u Need: %u.", 838 - args->buffer_size, req_bytes); 839 - ret = -EINVAL; 840 - } 841 - 842 - out: 843 - kfree(tmp); 844 - args->buffer_size = req_bytes; 831 + args->buffer_size = (u32)(info_args.buffer - args->buffer); 845 832 return ret; 846 833 } 847 834
+1 -1
drivers/accel/amdxdna/aie2_pci.h
··· 289 289 void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx); 290 290 int aie2_hwctx_config(struct amdxdna_hwctx *hwctx, u32 type, u64 value, void *buf, u32 size); 291 291 void aie2_hwctx_suspend(struct amdxdna_client *client); 292 - void aie2_hwctx_resume(struct amdxdna_client *client); 292 + int aie2_hwctx_resume(struct amdxdna_client *client); 293 293 int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, u64 *seq); 294 294 void aie2_hmm_invalidate(struct amdxdna_gem_obj *abo, unsigned long cur_seq); 295 295
+20 -6
drivers/accel/amdxdna/amdxdna_ctx.c
··· 68 68 synchronize_srcu(ss); 69 69 70 70 /* At this point, user is not able to submit new commands */ 71 - mutex_lock(&xdna->dev_lock); 72 71 xdna->dev_info->ops->hwctx_fini(hwctx); 73 - mutex_unlock(&xdna->dev_lock); 74 72 75 73 kfree(hwctx->name); 76 74 kfree(hwctx); 75 + } 76 + 77 + int amdxdna_hwctx_walk(struct amdxdna_client *client, void *arg, 78 + int (*walk)(struct amdxdna_hwctx *hwctx, void *arg)) 79 + { 80 + struct amdxdna_hwctx *hwctx; 81 + unsigned long hwctx_id; 82 + int ret = 0, idx; 83 + 84 + idx = srcu_read_lock(&client->hwctx_srcu); 85 + amdxdna_for_each_hwctx(client, hwctx_id, hwctx) { 86 + ret = walk(hwctx, arg); 87 + if (ret) 88 + break; 89 + } 90 + srcu_read_unlock(&client->hwctx_srcu, idx); 91 + 92 + return ret; 77 93 } 78 94 79 95 void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size) ··· 142 126 struct amdxdna_hwctx *hwctx; 143 127 unsigned long hwctx_id; 144 128 145 - mutex_lock(&client->hwctx_lock); 146 129 amdxdna_for_each_hwctx(client, hwctx_id, hwctx) { 147 130 XDNA_DBG(client->xdna, "PID %d close HW context %d", 148 131 client->pid, hwctx->id); 149 132 xa_erase(&client->hwctx_xa, hwctx->id); 150 - mutex_unlock(&client->hwctx_lock); 151 133 amdxdna_hwctx_destroy_rcu(hwctx, &client->hwctx_srcu); 152 - mutex_lock(&client->hwctx_lock); 153 134 } 154 - mutex_unlock(&client->hwctx_lock); 155 135 } 156 136 157 137 int amdxdna_drm_create_hwctx_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) ··· 237 225 if (!drm_dev_enter(dev, &idx)) 238 226 return -ENODEV; 239 227 228 + mutex_lock(&xdna->dev_lock); 240 229 hwctx = xa_erase(&client->hwctx_xa, args->handle); 241 230 if (!hwctx) { 242 231 ret = -EINVAL; ··· 254 241 255 242 XDNA_DBG(xdna, "PID %d destroyed HW context %d", client->pid, args->handle); 256 243 out: 244 + mutex_unlock(&xdna->dev_lock); 257 245 drm_dev_exit(idx); 258 246 return ret; 259 247 }
+2 -6
drivers/accel/amdxdna/amdxdna_ctx.h
··· 139 139 void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size); 140 140 int amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo); 141 141 142 - static inline u32 amdxdna_hwctx_col_map(struct amdxdna_hwctx *hwctx) 143 - { 144 - return GENMASK(hwctx->start_col + hwctx->num_col - 1, 145 - hwctx->start_col); 146 - } 147 - 148 142 void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job); 149 143 void amdxdna_hwctx_remove_all(struct amdxdna_client *client); 144 + int amdxdna_hwctx_walk(struct amdxdna_client *client, void *arg, 145 + int (*walk)(struct amdxdna_hwctx *hwctx, void *arg)); 150 146 151 147 int amdxdna_cmd_submit(struct amdxdna_client *client, 152 148 u32 cmd_bo_hdls, u32 *arg_bo_hdls, u32 arg_bo_cnt,
+1 -6
drivers/accel/amdxdna/amdxdna_pci_drv.c
··· 81 81 ret = -ENODEV; 82 82 goto unbind_sva; 83 83 } 84 - mutex_init(&client->hwctx_lock); 85 84 init_srcu_struct(&client->hwctx_srcu); 86 85 xa_init_flags(&client->hwctx_xa, XA_FLAGS_ALLOC); 87 86 mutex_init(&client->mm_lock); ··· 115 116 116 117 xa_destroy(&client->hwctx_xa); 117 118 cleanup_srcu_struct(&client->hwctx_srcu); 118 - mutex_destroy(&client->hwctx_lock); 119 119 mutex_destroy(&client->mm_lock); 120 120 if (client->dev_heap) 121 121 drm_gem_object_put(to_gobj(client->dev_heap)); ··· 140 142 141 143 mutex_lock(&xdna->dev_lock); 142 144 list_del_init(&client->node); 143 - mutex_unlock(&xdna->dev_lock); 144 145 amdxdna_hwctx_remove_all(client); 146 + mutex_unlock(&xdna->dev_lock); 145 147 146 148 drm_dev_exit(idx); 147 149 return 0; ··· 328 330 struct amdxdna_client, node); 329 331 while (client) { 330 332 list_del_init(&client->node); 331 - mutex_unlock(&xdna->dev_lock); 332 - 333 333 amdxdna_hwctx_remove_all(client); 334 334 335 - mutex_lock(&xdna->dev_lock); 336 335 client = list_first_entry_or_null(&xdna->client_list, 337 336 struct amdxdna_client, node); 338 337 }
-2
drivers/accel/amdxdna/amdxdna_pci_drv.h
··· 116 116 struct amdxdna_client { 117 117 struct list_head node; 118 118 pid_t pid; 119 - struct mutex hwctx_lock; /* protect hwctx */ 120 - /* do NOT wait this srcu when hwctx_lock is held */ 121 119 struct srcu_struct hwctx_srcu; 122 120 struct xarray hwctx_xa; 123 121 u32 next_hwctxid;
+1
drivers/gpu/drm/bridge/analogix/anx7625.c
··· 2604 2604 platform->bridge.type = platform->pdata.panel_bridge ? 2605 2605 DRM_MODE_CONNECTOR_eDP : 2606 2606 DRM_MODE_CONNECTOR_DisplayPort; 2607 + platform->bridge.support_hdcp = true; 2607 2608 2608 2609 drm_bridge_add(&platform->bridge); 2609 2610
+2 -1
drivers/gpu/drm/bridge/display-connector.c
··· 373 373 if (conn->bridge.ddc) 374 374 conn->bridge.ops |= DRM_BRIDGE_OP_EDID 375 375 | DRM_BRIDGE_OP_DETECT; 376 - if (conn->hpd_gpio) 376 + /* Detecting the monitor requires reading DPCD */ 377 + if (conn->hpd_gpio && type != DRM_MODE_CONNECTOR_DisplayPort) 377 378 conn->bridge.ops |= DRM_BRIDGE_OP_DETECT; 378 379 if (conn->hpd_irq >= 0) 379 380 conn->bridge.ops |= DRM_BRIDGE_OP_HPD;
+9
drivers/gpu/drm/display/drm_bridge_connector.c
··· 20 20 #include <drm/drm_modeset_helper_vtables.h> 21 21 #include <drm/drm_print.h> 22 22 #include <drm/drm_probe_helper.h> 23 + #include <drm/display/drm_hdcp_helper.h> 23 24 #include <drm/display/drm_hdmi_audio_helper.h> 24 25 #include <drm/display/drm_hdmi_cec_helper.h> 25 26 #include <drm/display/drm_hdmi_helper.h> ··· 642 641 struct drm_bridge *bridge, *panel_bridge = NULL; 643 642 unsigned int supported_formats = BIT(HDMI_COLORSPACE_RGB); 644 643 unsigned int max_bpc = 8; 644 + bool support_hdcp = false; 645 645 int connector_type; 646 646 int ret; 647 647 ··· 765 763 766 764 if (drm_bridge_is_panel(bridge)) 767 765 panel_bridge = bridge; 766 + 767 + if (bridge->support_hdcp) 768 + support_hdcp = true; 768 769 } 769 770 770 771 if (connector_type == DRM_MODE_CONNECTOR_Unknown) ··· 853 848 854 849 if (panel_bridge) 855 850 drm_panel_bridge_set_orientation(connector, panel_bridge); 851 + 852 + if (support_hdcp && IS_REACHABLE(CONFIG_DRM_DISPLAY_HELPER) && 853 + IS_ENABLED(CONFIG_DRM_DISPLAY_HDCP_HELPER)) 854 + drm_connector_attach_content_protection_property(connector, true); 856 855 857 856 return connector; 858 857 }
+26 -98
drivers/gpu/drm/drm_gpusvm.c
··· 271 271 } 272 272 273 273 /** 274 + * drm_gpusvm_notifier_find() - Find GPU SVM notifier from GPU SVM 275 + * @gpusvm: Pointer to the GPU SVM structure. 276 + * @start: Start address of the notifier 277 + * @end: End address of the notifier 278 + * 279 + * Return: A pointer to the drm_gpusvm_notifier if found or NULL 280 + */ 281 + struct drm_gpusvm_notifier * 282 + drm_gpusvm_notifier_find(struct drm_gpusvm *gpusvm, unsigned long start, 283 + unsigned long end) 284 + { 285 + struct interval_tree_node *itree; 286 + 287 + itree = interval_tree_iter_first(&gpusvm->root, start, end - 1); 288 + 289 + if (itree) 290 + return container_of(itree, struct drm_gpusvm_notifier, itree); 291 + else 292 + return NULL; 293 + } 294 + EXPORT_SYMBOL_GPL(drm_gpusvm_notifier_find); 295 + 296 + /** 274 297 * drm_gpusvm_range_find() - Find GPU SVM range from GPU SVM notifier 275 298 * @notifier: Pointer to the GPU SVM notifier structure. 276 299 * @start: Start address of the range ··· 315 292 return NULL; 316 293 } 317 294 EXPORT_SYMBOL_GPL(drm_gpusvm_range_find); 318 - 319 - /** 320 - * drm_gpusvm_for_each_range_safe() - Safely iterate over GPU SVM ranges in a notifier 321 - * @range__: Iterator variable for the ranges 322 - * @next__: Iterator variable for the ranges temporay storage 323 - * @notifier__: Pointer to the GPU SVM notifier 324 - * @start__: Start address of the range 325 - * @end__: End address of the range 326 - * 327 - * This macro is used to iterate over GPU SVM ranges in a notifier while 328 - * removing ranges from it. 329 - */ 330 - #define drm_gpusvm_for_each_range_safe(range__, next__, notifier__, start__, end__) \ 331 - for ((range__) = drm_gpusvm_range_find((notifier__), (start__), (end__)), \ 332 - (next__) = __drm_gpusvm_range_next(range__); \ 333 - (range__) && (drm_gpusvm_range_start(range__) < (end__)); \ 334 - (range__) = (next__), (next__) = __drm_gpusvm_range_next(range__)) 335 - 336 - /** 337 - * __drm_gpusvm_notifier_next() - get the next drm_gpusvm_notifier in the list 338 - * @notifier: a pointer to the current drm_gpusvm_notifier 339 - * 340 - * Return: A pointer to the next drm_gpusvm_notifier if available, or NULL if 341 - * the current notifier is the last one or if the input notifier is 342 - * NULL. 343 - */ 344 - static struct drm_gpusvm_notifier * 345 - __drm_gpusvm_notifier_next(struct drm_gpusvm_notifier *notifier) 346 - { 347 - if (notifier && !list_is_last(&notifier->entry, 348 - &notifier->gpusvm->notifier_list)) 349 - return list_next_entry(notifier, entry); 350 - 351 - return NULL; 352 - } 353 - 354 - static struct drm_gpusvm_notifier * 355 - notifier_iter_first(struct rb_root_cached *root, unsigned long start, 356 - unsigned long last) 357 - { 358 - struct interval_tree_node *itree; 359 - 360 - itree = interval_tree_iter_first(root, start, last); 361 - 362 - if (itree) 363 - return container_of(itree, struct drm_gpusvm_notifier, itree); 364 - else 365 - return NULL; 366 - } 367 - 368 - /** 369 - * drm_gpusvm_for_each_notifier() - Iterate over GPU SVM notifiers in a gpusvm 370 - * @notifier__: Iterator variable for the notifiers 371 - * @notifier__: Pointer to the GPU SVM notifier 372 - * @start__: Start address of the notifier 373 - * @end__: End address of the notifier 374 - * 375 - * This macro is used to iterate over GPU SVM notifiers in a gpusvm. 376 - */ 377 - #define drm_gpusvm_for_each_notifier(notifier__, gpusvm__, start__, end__) \ 378 - for ((notifier__) = notifier_iter_first(&(gpusvm__)->root, (start__), (end__) - 1); \ 379 - (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__)); \ 380 - (notifier__) = __drm_gpusvm_notifier_next(notifier__)) 381 - 382 - /** 383 - * drm_gpusvm_for_each_notifier_safe() - Safely iterate over GPU SVM notifiers in a gpusvm 384 - * @notifier__: Iterator variable for the notifiers 385 - * @next__: Iterator variable for the notifiers temporay storage 386 - * @notifier__: Pointer to the GPU SVM notifier 387 - * @start__: Start address of the notifier 388 - * @end__: End address of the notifier 389 - * 390 - * This macro is used to iterate over GPU SVM notifiers in a gpusvm while 391 - * removing notifiers from it. 392 - */ 393 - #define drm_gpusvm_for_each_notifier_safe(notifier__, next__, gpusvm__, start__, end__) \ 394 - for ((notifier__) = notifier_iter_first(&(gpusvm__)->root, (start__), (end__) - 1), \ 395 - (next__) = __drm_gpusvm_notifier_next(notifier__); \ 396 - (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__)); \ 397 - (notifier__) = (next__), (next__) = __drm_gpusvm_notifier_next(notifier__)) 398 295 399 296 /** 400 297 * drm_gpusvm_notifier_invalidate() - Invalidate a GPU SVM notifier. ··· 414 471 return 0; 415 472 } 416 473 EXPORT_SYMBOL_GPL(drm_gpusvm_init); 417 - 418 - /** 419 - * drm_gpusvm_notifier_find() - Find GPU SVM notifier 420 - * @gpusvm: Pointer to the GPU SVM structure 421 - * @fault_addr: Fault address 422 - * 423 - * This function finds the GPU SVM notifier associated with the fault address. 424 - * 425 - * Return: Pointer to the GPU SVM notifier on success, NULL otherwise. 426 - */ 427 - static struct drm_gpusvm_notifier * 428 - drm_gpusvm_notifier_find(struct drm_gpusvm *gpusvm, 429 - unsigned long fault_addr) 430 - { 431 - return notifier_iter_first(&gpusvm->root, fault_addr, fault_addr + 1); 432 - } 433 474 434 475 /** 435 476 * to_drm_gpusvm_notifier() - retrieve the container struct for a given rbtree node ··· 870 943 if (!mmget_not_zero(mm)) 871 944 return ERR_PTR(-EFAULT); 872 945 873 - notifier = drm_gpusvm_notifier_find(gpusvm, fault_addr); 946 + notifier = drm_gpusvm_notifier_find(gpusvm, fault_addr, fault_addr + 1); 874 947 if (!notifier) { 875 948 notifier = drm_gpusvm_notifier_alloc(gpusvm, fault_addr); 876 949 if (IS_ERR(notifier)) { ··· 1034 1107 drm_gpusvm_driver_lock_held(gpusvm); 1035 1108 1036 1109 notifier = drm_gpusvm_notifier_find(gpusvm, 1037 - drm_gpusvm_range_start(range)); 1110 + drm_gpusvm_range_start(range), 1111 + drm_gpusvm_range_start(range) + 1); 1038 1112 if (WARN_ON_ONCE(!notifier)) 1039 1113 return; 1040 1114
+213 -74
drivers/gpu/drm/drm_gpuvm.c
··· 421 421 */ 422 422 423 423 /** 424 + * DOC: Madvise Logic - Splitting and Traversal 425 + * 426 + * This logic handles GPU VA range updates by generating remap and map operations 427 + * without performing unmaps or merging existing mappings. 428 + * 429 + * 1) The requested range lies entirely within a single drm_gpuva. The logic splits 430 + * the existing mapping at the start and end boundaries and inserts a new map. 431 + * 432 + * :: 433 + * a start end b 434 + * pre: |-----------------------| 435 + * drm_gpuva1 436 + * 437 + * a start end b 438 + * new: |-----|=========|-------| 439 + * remap map remap 440 + * 441 + * one REMAP and one MAP : Same behaviour as SPLIT and MERGE 442 + * 443 + * 2) The requested range spans multiple drm_gpuva regions. The logic traverses 444 + * across boundaries, remapping the start and end segments, and inserting two 445 + * map operations to cover the full range. 446 + * 447 + * :: a start b c end d 448 + * pre: |------------------|--------------|------------------| 449 + * drm_gpuva1 drm_gpuva2 drm_gpuva3 450 + * 451 + * a start b c end d 452 + * new: |-------|==========|--------------|========|---------| 453 + * remap1 map1 drm_gpuva2 map2 remap2 454 + * 455 + * two REMAPS and two MAPS 456 + * 457 + * 3) Either start or end lies within a drm_gpuva. A single remap and map operation 458 + * are generated to update the affected portion. 459 + * 460 + * 461 + * :: a/start b c end d 462 + * pre: |------------------|--------------|------------------| 463 + * drm_gpuva1 drm_gpuva2 drm_gpuva3 464 + * 465 + * a/start b c end d 466 + * new: |------------------|--------------|========|---------| 467 + * drm_gpuva1 drm_gpuva2 map1 remap1 468 + * 469 + * :: a start b c/end d 470 + * pre: |------------------|--------------|------------------| 471 + * drm_gpuva1 drm_gpuva2 drm_gpuva3 472 + * 473 + * a start b c/end d 474 + * new: |-------|==========|--------------|------------------| 475 + * remap1 map1 drm_gpuva2 drm_gpuva3 476 + * 477 + * one REMAP and one MAP 478 + * 479 + * 4) Both start and end align with existing drm_gpuva boundaries. No operations 480 + * are needed as the range is already covered. 481 + * 482 + * 5) No existing drm_gpuvas. No operations. 483 + * 484 + * Unlike drm_gpuvm_sm_map_ops_create, this logic avoids unmaps and merging, 485 + * focusing solely on remap and map operations for efficient traversal and update. 486 + */ 487 + 488 + /** 424 489 * DOC: Locking 425 490 * 426 491 * In terms of managing &drm_gpuva entries DRM GPUVM does not take care of ··· 551 486 * u64 addr, u64 range, 552 487 * struct drm_gem_object *obj, u64 offset) 553 488 * { 489 + * struct drm_gpuvm_map_req map_req = { 490 + * .map.va.addr = addr, 491 + * .map.va.range = range, 492 + * .map.gem.obj = obj, 493 + * .map.gem.offset = offset, 494 + * }; 554 495 * struct drm_gpuva_ops *ops; 555 496 * struct drm_gpuva_op *op 556 497 * struct drm_gpuvm_bo *vm_bo; 557 498 * 558 499 * driver_lock_va_space(); 559 - * ops = drm_gpuvm_sm_map_ops_create(gpuvm, addr, range, 560 - * obj, offset); 500 + * ops = drm_gpuvm_sm_map_ops_create(gpuvm, &map_req); 561 501 * if (IS_ERR(ops)) 562 502 * return PTR_ERR(ops); 563 503 * ··· 2124 2054 2125 2055 static int 2126 2056 op_map_cb(const struct drm_gpuvm_ops *fn, void *priv, 2127 - u64 addr, u64 range, 2128 - struct drm_gem_object *obj, u64 offset) 2057 + const struct drm_gpuvm_map_req *req) 2129 2058 { 2130 2059 struct drm_gpuva_op op = {}; 2131 2060 2061 + if (!req) 2062 + return 0; 2063 + 2132 2064 op.op = DRM_GPUVA_OP_MAP; 2133 - op.map.va.addr = addr; 2134 - op.map.va.range = range; 2135 - op.map.gem.obj = obj; 2136 - op.map.gem.offset = offset; 2065 + op.map.va.addr = req->map.va.addr; 2066 + op.map.va.range = req->map.va.range; 2067 + op.map.gem.obj = req->map.gem.obj; 2068 + op.map.gem.offset = req->map.gem.offset; 2137 2069 2138 2070 return fn->sm_step_map(&op, priv); 2139 2071 } ··· 2160 2088 2161 2089 static int 2162 2090 op_unmap_cb(const struct drm_gpuvm_ops *fn, void *priv, 2163 - struct drm_gpuva *va, bool merge) 2091 + struct drm_gpuva *va, bool merge, bool madvise) 2164 2092 { 2165 2093 struct drm_gpuva_op op = {}; 2094 + 2095 + if (madvise) 2096 + return 0; 2166 2097 2167 2098 op.op = DRM_GPUVA_OP_UNMAP; 2168 2099 op.unmap.va = va; ··· 2177 2102 static int 2178 2103 __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm, 2179 2104 const struct drm_gpuvm_ops *ops, void *priv, 2180 - u64 req_addr, u64 req_range, 2181 - struct drm_gem_object *req_obj, u64 req_offset) 2105 + const struct drm_gpuvm_map_req *req, 2106 + bool madvise) 2182 2107 { 2108 + struct drm_gem_object *req_obj = req->map.gem.obj; 2109 + const struct drm_gpuvm_map_req *op_map = madvise ? NULL : req; 2183 2110 struct drm_gpuva *va, *next; 2111 + u64 req_offset = req->map.gem.offset; 2112 + u64 req_range = req->map.va.range; 2113 + u64 req_addr = req->map.va.addr; 2184 2114 u64 req_end = req_addr + req_range; 2185 2115 int ret; 2186 2116 ··· 2200 2120 u64 end = addr + range; 2201 2121 bool merge = !!va->gem.obj; 2202 2122 2123 + if (madvise && obj) 2124 + continue; 2125 + 2203 2126 if (addr == req_addr) { 2204 2127 merge &= obj == req_obj && 2205 2128 offset == req_offset; 2206 2129 2207 2130 if (end == req_end) { 2208 - ret = op_unmap_cb(ops, priv, va, merge); 2131 + ret = op_unmap_cb(ops, priv, va, merge, madvise); 2209 2132 if (ret) 2210 2133 return ret; 2211 2134 break; 2212 2135 } 2213 2136 2214 2137 if (end < req_end) { 2215 - ret = op_unmap_cb(ops, priv, va, merge); 2138 + ret = op_unmap_cb(ops, priv, va, merge, madvise); 2216 2139 if (ret) 2217 2140 return ret; 2218 2141 continue; ··· 2236 2153 ret = op_remap_cb(ops, priv, NULL, &n, &u); 2237 2154 if (ret) 2238 2155 return ret; 2156 + 2157 + if (madvise) 2158 + op_map = req; 2239 2159 break; 2240 2160 } 2241 2161 } else if (addr < req_addr) { ··· 2259 2173 ret = op_remap_cb(ops, priv, &p, NULL, &u); 2260 2174 if (ret) 2261 2175 return ret; 2176 + 2177 + if (madvise) 2178 + op_map = req; 2262 2179 break; 2263 2180 } 2264 2181 ··· 2269 2180 ret = op_remap_cb(ops, priv, &p, NULL, &u); 2270 2181 if (ret) 2271 2182 return ret; 2183 + 2184 + if (madvise) { 2185 + struct drm_gpuvm_map_req map_req = { 2186 + .map.va.addr = req_addr, 2187 + .map.va.range = end - req_addr, 2188 + }; 2189 + 2190 + ret = op_map_cb(ops, priv, &map_req); 2191 + if (ret) 2192 + return ret; 2193 + } 2194 + 2272 2195 continue; 2273 2196 } 2274 2197 ··· 2296 2195 ret = op_remap_cb(ops, priv, &p, &n, &u); 2297 2196 if (ret) 2298 2197 return ret; 2198 + 2199 + if (madvise) 2200 + op_map = req; 2299 2201 break; 2300 2202 } 2301 2203 } else if (addr > req_addr) { ··· 2307 2203 (addr - req_addr); 2308 2204 2309 2205 if (end == req_end) { 2310 - ret = op_unmap_cb(ops, priv, va, merge); 2206 + ret = op_unmap_cb(ops, priv, va, merge, madvise); 2311 2207 if (ret) 2312 2208 return ret; 2209 + 2313 2210 break; 2314 2211 } 2315 2212 2316 2213 if (end < req_end) { 2317 - ret = op_unmap_cb(ops, priv, va, merge); 2214 + ret = op_unmap_cb(ops, priv, va, merge, madvise); 2318 2215 if (ret) 2319 2216 return ret; 2217 + 2320 2218 continue; 2321 2219 } 2322 2220 ··· 2337 2231 ret = op_remap_cb(ops, priv, NULL, &n, &u); 2338 2232 if (ret) 2339 2233 return ret; 2234 + 2235 + if (madvise) { 2236 + struct drm_gpuvm_map_req map_req = { 2237 + .map.va.addr = addr, 2238 + .map.va.range = req_end - addr, 2239 + }; 2240 + 2241 + return op_map_cb(ops, priv, &map_req); 2242 + } 2340 2243 break; 2341 2244 } 2342 2245 } 2343 2246 } 2344 - 2345 - return op_map_cb(ops, priv, 2346 - req_addr, req_range, 2347 - req_obj, req_offset); 2247 + return op_map_cb(ops, priv, op_map); 2348 2248 } 2349 2249 2350 2250 static int ··· 2402 2290 if (ret) 2403 2291 return ret; 2404 2292 } else { 2405 - ret = op_unmap_cb(ops, priv, va, false); 2293 + ret = op_unmap_cb(ops, priv, va, false, false); 2406 2294 if (ret) 2407 2295 return ret; 2408 2296 } ··· 2415 2303 * drm_gpuvm_sm_map() - calls the &drm_gpuva_op split/merge steps 2416 2304 * @gpuvm: the &drm_gpuvm representing the GPU VA space 2417 2305 * @priv: pointer to a driver private data structure 2418 - * @req_addr: the start address of the new mapping 2419 - * @req_range: the range of the new mapping 2420 - * @req_obj: the &drm_gem_object to map 2421 - * @req_offset: the offset within the &drm_gem_object 2306 + * @req: ptr to struct drm_gpuvm_map_req 2422 2307 * 2423 2308 * This function iterates the given range of the GPU VA space. It utilizes the 2424 2309 * &drm_gpuvm_ops to call back into the driver providing the split and merge ··· 2442 2333 */ 2443 2334 int 2444 2335 drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm, void *priv, 2445 - u64 req_addr, u64 req_range, 2446 - struct drm_gem_object *req_obj, u64 req_offset) 2336 + const struct drm_gpuvm_map_req *req) 2447 2337 { 2448 2338 const struct drm_gpuvm_ops *ops = gpuvm->ops; 2449 2339 ··· 2451 2343 ops->sm_step_unmap))) 2452 2344 return -EINVAL; 2453 2345 2454 - return __drm_gpuvm_sm_map(gpuvm, ops, priv, 2455 - req_addr, req_range, 2456 - req_obj, req_offset); 2346 + return __drm_gpuvm_sm_map(gpuvm, ops, priv, req, false); 2457 2347 } 2458 2348 EXPORT_SYMBOL_GPL(drm_gpuvm_sm_map); 2459 2349 ··· 2527 2421 * @gpuvm: the &drm_gpuvm representing the GPU VA space 2528 2422 * @exec: the &drm_exec locking context 2529 2423 * @num_fences: for newly mapped objects, the # of fences to reserve 2530 - * @req_addr: the start address of the range to unmap 2531 - * @req_range: the range of the mappings to unmap 2532 - * @req_obj: the &drm_gem_object to map 2533 - * @req_offset: the offset within the &drm_gem_object 2424 + * @req: ptr to drm_gpuvm_map_req struct 2534 2425 * 2535 2426 * This function locks (drm_exec_lock_obj()) objects that will be unmapped/ 2536 2427 * remapped, and locks+prepares (drm_exec_prepare_object()) objects that ··· 2548 2445 * ret = drm_gpuvm_sm_unmap_exec_lock(gpuvm, &exec, op->addr, op->range); 2549 2446 * break; 2550 2447 * case DRIVER_OP_MAP: 2551 - * ret = drm_gpuvm_sm_map_exec_lock(gpuvm, &exec, num_fences, 2552 - * op->addr, op->range, 2553 - * obj, op->obj_offset); 2448 + * ret = drm_gpuvm_sm_map_exec_lock(gpuvm, &exec, num_fences, &req); 2554 2449 * break; 2555 2450 * } 2556 2451 * ··· 2579 2478 int 2580 2479 drm_gpuvm_sm_map_exec_lock(struct drm_gpuvm *gpuvm, 2581 2480 struct drm_exec *exec, unsigned int num_fences, 2582 - u64 req_addr, u64 req_range, 2583 - struct drm_gem_object *req_obj, u64 req_offset) 2481 + struct drm_gpuvm_map_req *req) 2584 2482 { 2483 + struct drm_gem_object *req_obj = req->map.gem.obj; 2484 + 2585 2485 if (req_obj) { 2586 2486 int ret = drm_exec_prepare_obj(exec, req_obj, num_fences); 2587 2487 if (ret) 2588 2488 return ret; 2589 2489 } 2590 2490 2591 - return __drm_gpuvm_sm_map(gpuvm, &lock_ops, exec, 2592 - req_addr, req_range, 2593 - req_obj, req_offset); 2491 + return __drm_gpuvm_sm_map(gpuvm, &lock_ops, exec, req, false); 2594 2492 2595 2493 } 2596 2494 EXPORT_SYMBOL_GPL(drm_gpuvm_sm_map_exec_lock); ··· 2708 2608 .sm_step_unmap = drm_gpuva_sm_step, 2709 2609 }; 2710 2610 2611 + static struct drm_gpuva_ops * 2612 + __drm_gpuvm_sm_map_ops_create(struct drm_gpuvm *gpuvm, 2613 + const struct drm_gpuvm_map_req *req, 2614 + bool madvise) 2615 + { 2616 + struct drm_gpuva_ops *ops; 2617 + struct { 2618 + struct drm_gpuvm *vm; 2619 + struct drm_gpuva_ops *ops; 2620 + } args; 2621 + int ret; 2622 + 2623 + ops = kzalloc(sizeof(*ops), GFP_KERNEL); 2624 + if (unlikely(!ops)) 2625 + return ERR_PTR(-ENOMEM); 2626 + 2627 + INIT_LIST_HEAD(&ops->list); 2628 + 2629 + args.vm = gpuvm; 2630 + args.ops = ops; 2631 + 2632 + ret = __drm_gpuvm_sm_map(gpuvm, &gpuvm_list_ops, &args, req, madvise); 2633 + if (ret) 2634 + goto err_free_ops; 2635 + 2636 + return ops; 2637 + 2638 + err_free_ops: 2639 + drm_gpuva_ops_free(gpuvm, ops); 2640 + return ERR_PTR(ret); 2641 + } 2642 + 2711 2643 /** 2712 2644 * drm_gpuvm_sm_map_ops_create() - creates the &drm_gpuva_ops to split and merge 2713 2645 * @gpuvm: the &drm_gpuvm representing the GPU VA space 2714 - * @req_addr: the start address of the new mapping 2715 - * @req_range: the range of the new mapping 2716 - * @req_obj: the &drm_gem_object to map 2717 - * @req_offset: the offset within the &drm_gem_object 2646 + * @req: map request arguments 2718 2647 * 2719 2648 * This function creates a list of operations to perform splitting and merging 2720 2649 * of existent mapping(s) with the newly requested one. ··· 2771 2642 */ 2772 2643 struct drm_gpuva_ops * 2773 2644 drm_gpuvm_sm_map_ops_create(struct drm_gpuvm *gpuvm, 2774 - u64 req_addr, u64 req_range, 2775 - struct drm_gem_object *req_obj, u64 req_offset) 2645 + const struct drm_gpuvm_map_req *req) 2776 2646 { 2777 - struct drm_gpuva_ops *ops; 2778 - struct { 2779 - struct drm_gpuvm *vm; 2780 - struct drm_gpuva_ops *ops; 2781 - } args; 2782 - int ret; 2783 - 2784 - ops = kzalloc(sizeof(*ops), GFP_KERNEL); 2785 - if (unlikely(!ops)) 2786 - return ERR_PTR(-ENOMEM); 2787 - 2788 - INIT_LIST_HEAD(&ops->list); 2789 - 2790 - args.vm = gpuvm; 2791 - args.ops = ops; 2792 - 2793 - ret = __drm_gpuvm_sm_map(gpuvm, &gpuvm_list_ops, &args, 2794 - req_addr, req_range, 2795 - req_obj, req_offset); 2796 - if (ret) 2797 - goto err_free_ops; 2798 - 2799 - return ops; 2800 - 2801 - err_free_ops: 2802 - drm_gpuva_ops_free(gpuvm, ops); 2803 - return ERR_PTR(ret); 2647 + return __drm_gpuvm_sm_map_ops_create(gpuvm, req, false); 2804 2648 } 2805 2649 EXPORT_SYMBOL_GPL(drm_gpuvm_sm_map_ops_create); 2650 + 2651 + /** 2652 + * drm_gpuvm_madvise_ops_create() - creates the &drm_gpuva_ops to split 2653 + * @gpuvm: the &drm_gpuvm representing the GPU VA space 2654 + * @req: map request arguments 2655 + * 2656 + * This function creates a list of operations to perform splitting 2657 + * of existent mapping(s) at start or end, based on the request map. 2658 + * 2659 + * The list can be iterated with &drm_gpuva_for_each_op and must be processed 2660 + * in the given order. It can contain map and remap operations, but it 2661 + * also can be empty if no operation is required, e.g. if the requested mapping 2662 + * already exists is the exact same way. 2663 + * 2664 + * There will be no unmap operations, a maximum of two remap operations and two 2665 + * map operations. The two map operations correspond to: one from start to the 2666 + * end of drm_gpuvaX, and another from the start of drm_gpuvaY to end. 2667 + * 2668 + * Note that before calling this function again with another mapping request it 2669 + * is necessary to update the &drm_gpuvm's view of the GPU VA space. The 2670 + * previously obtained operations must be either processed or abandoned. To 2671 + * update the &drm_gpuvm's view of the GPU VA space drm_gpuva_insert(), 2672 + * drm_gpuva_destroy_locked() and/or drm_gpuva_destroy_unlocked() should be 2673 + * used. 2674 + * 2675 + * After the caller finished processing the returned &drm_gpuva_ops, they must 2676 + * be freed with &drm_gpuva_ops_free. 2677 + * 2678 + * Returns: a pointer to the &drm_gpuva_ops on success, an ERR_PTR on failure 2679 + */ 2680 + struct drm_gpuva_ops * 2681 + drm_gpuvm_madvise_ops_create(struct drm_gpuvm *gpuvm, 2682 + const struct drm_gpuvm_map_req *req) 2683 + { 2684 + return __drm_gpuvm_sm_map_ops_create(gpuvm, req, true); 2685 + } 2686 + EXPORT_SYMBOL_GPL(drm_gpuvm_madvise_ops_create); 2806 2687 2807 2688 /** 2808 2689 * drm_gpuvm_sm_unmap_ops_create() - creates the &drm_gpuva_ops to split on
+37
drivers/gpu/drm/drm_mipi_dsi.c
··· 1097 1097 EXPORT_SYMBOL(mipi_dsi_dcs_read); 1098 1098 1099 1099 /** 1100 + * mipi_dsi_dcs_read_multi() - mipi_dsi_dcs_read() w/ accum_err 1101 + * @ctx: Context for multiple DSI transactions 1102 + * @cmd: DCS command 1103 + * @data: buffer in which to receive data 1104 + * @len: size of receive buffer 1105 + * 1106 + * Like mipi_dsi_dcs_read() but deals with errors in a way that makes it 1107 + * convenient to make several calls in a row. 1108 + */ 1109 + void mipi_dsi_dcs_read_multi(struct mipi_dsi_multi_context *ctx, u8 cmd, 1110 + void *data, size_t len) 1111 + { 1112 + struct mipi_dsi_device *dsi = ctx->dsi; 1113 + struct device *dev = &dsi->dev; 1114 + struct mipi_dsi_msg msg = { 1115 + .channel = dsi->channel, 1116 + .type = MIPI_DSI_DCS_READ, 1117 + .tx_buf = &cmd, 1118 + .tx_len = 1, 1119 + .rx_buf = data, 1120 + .rx_len = len 1121 + }; 1122 + ssize_t ret; 1123 + 1124 + if (ctx->accum_err) 1125 + return; 1126 + 1127 + ret = mipi_dsi_device_transfer(dsi, &msg); 1128 + if (ret < 0) { 1129 + ctx->accum_err = ret; 1130 + dev_err(dev, "dcs read with command %#x failed: %d\n", cmd, 1131 + ctx->accum_err); 1132 + } 1133 + } 1134 + EXPORT_SYMBOL(mipi_dsi_dcs_read_multi); 1135 + 1136 + /** 1100 1137 * mipi_dsi_dcs_nop() - send DCS nop packet 1101 1138 * @dsi: DSI peripheral device 1102 1139 *
+10 -5
drivers/gpu/drm/imagination/pvr_vm.c
··· 185 185 static int pvr_vm_bind_op_exec(struct pvr_vm_bind_op *bind_op) 186 186 { 187 187 switch (bind_op->type) { 188 - case PVR_VM_BIND_TYPE_MAP: 188 + case PVR_VM_BIND_TYPE_MAP: { 189 + const struct drm_gpuvm_map_req map_req = { 190 + .map.va.addr = bind_op->device_addr, 191 + .map.va.range = bind_op->size, 192 + .map.gem.obj = gem_from_pvr_gem(bind_op->pvr_obj), 193 + .map.gem.offset = bind_op->offset, 194 + }; 195 + 189 196 return drm_gpuvm_sm_map(&bind_op->vm_ctx->gpuvm_mgr, 190 - bind_op, bind_op->device_addr, 191 - bind_op->size, 192 - gem_from_pvr_gem(bind_op->pvr_obj), 193 - bind_op->offset); 197 + bind_op, &map_req); 198 + } 194 199 195 200 case PVR_VM_BIND_TYPE_UNMAP: 196 201 return drm_gpuvm_sm_unmap(&bind_op->vm_ctx->gpuvm_mgr,
+27 -8
drivers/gpu/drm/msm/msm_gem_vma.c
··· 371 371 msm_gem_vma_new(struct drm_gpuvm *gpuvm, struct drm_gem_object *obj, 372 372 u64 offset, u64 range_start, u64 range_end) 373 373 { 374 + struct drm_gpuva_op_map op_map = { 375 + .va.addr = range_start, 376 + .va.range = range_end - range_start, 377 + .gem.obj = obj, 378 + .gem.offset = offset, 379 + }; 374 380 struct msm_gem_vm *vm = to_msm_vm(gpuvm); 375 381 struct drm_gpuvm_bo *vm_bo; 376 382 struct msm_gem_vma *vma; ··· 405 399 if (obj) 406 400 GEM_WARN_ON((range_end - range_start) > obj->size); 407 401 408 - drm_gpuva_init(&vma->base, range_start, range_end - range_start, obj, offset); 402 + drm_gpuva_init_from_op(&vma->base, &op_map); 409 403 vma->mapped = false; 410 404 411 405 ret = drm_gpuva_insert(&vm->base, &vma->base); ··· 1177 1171 op->obj_offset); 1178 1172 break; 1179 1173 case MSM_VM_BIND_OP_MAP: 1180 - case MSM_VM_BIND_OP_MAP_NULL: 1181 - ret = drm_gpuvm_sm_map_exec_lock(job->vm, exec, 1, 1182 - op->iova, op->range, 1183 - op->obj, op->obj_offset); 1174 + case MSM_VM_BIND_OP_MAP_NULL: { 1175 + struct drm_gpuvm_map_req map_req = { 1176 + .map.va.addr = op->iova, 1177 + .map.va.range = op->range, 1178 + .map.gem.obj = op->obj, 1179 + .map.gem.offset = op->obj_offset, 1180 + }; 1181 + 1182 + ret = drm_gpuvm_sm_map_exec_lock(job->vm, exec, 1, &map_req); 1184 1183 break; 1184 + } 1185 1185 default: 1186 1186 /* 1187 1187 * lookup_op() should have already thrown an error for ··· 1294 1282 if (op->flags & MSM_VM_BIND_OP_DUMP) 1295 1283 arg.flags |= MSM_VMA_DUMP; 1296 1284 fallthrough; 1297 - case MSM_VM_BIND_OP_MAP_NULL: 1298 - ret = drm_gpuvm_sm_map(job->vm, &arg, op->iova, 1299 - op->range, op->obj, op->obj_offset); 1285 + case MSM_VM_BIND_OP_MAP_NULL: { 1286 + struct drm_gpuvm_map_req map_req = { 1287 + .map.va.addr = op->iova, 1288 + .map.va.range = op->range, 1289 + .map.gem.obj = op->obj, 1290 + .map.gem.offset = op->obj_offset, 1291 + }; 1292 + 1293 + ret = drm_gpuvm_sm_map(job->vm, &arg, &map_req); 1300 1294 break; 1295 + } 1301 1296 default: 1302 1297 /* 1303 1298 * lookup_op() should have already thrown an error for
+7 -4
drivers/gpu/drm/nouveau/nouveau_uvmm.c
··· 1276 1276 break; 1277 1277 case OP_MAP: { 1278 1278 struct nouveau_uvma_region *reg; 1279 + struct drm_gpuvm_map_req map_req = { 1280 + .map.va.addr = op->va.addr, 1281 + .map.va.range = op->va.range, 1282 + .map.gem.obj = op->gem.obj, 1283 + .map.gem.offset = op->gem.offset, 1284 + }; 1279 1285 1280 1286 reg = nouveau_uvma_region_find_first(uvmm, 1281 1287 op->va.addr, ··· 1307 1301 } 1308 1302 1309 1303 op->ops = drm_gpuvm_sm_map_ops_create(&uvmm->base, 1310 - op->va.addr, 1311 - op->va.range, 1312 - op->gem.obj, 1313 - op->gem.offset); 1304 + &map_req); 1314 1305 if (IS_ERR(op->ops)) { 1315 1306 ret = PTR_ERR(op->ops); 1316 1307 goto unwind_continue;
+60 -138
drivers/gpu/drm/panel/panel-novatek-nt35560.c
··· 148 148 static int nt35560_set_brightness(struct backlight_device *bl) 149 149 { 150 150 struct nt35560 *nt = bl_get_data(bl); 151 - struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev); 152 - int period_ns = 1023; 151 + struct mipi_dsi_multi_context dsi_ctx = { 152 + .dsi = to_mipi_dsi_device(nt->dev) 153 + }; 153 154 int duty_ns = bl->props.brightness; 155 + int period_ns = 1023; 154 156 u8 pwm_ratio; 155 157 u8 pwm_div; 156 - u8 par; 157 - int ret; 158 158 159 159 if (backlight_is_blank(bl)) { 160 160 /* Disable backlight */ 161 - par = 0x00; 162 - ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 163 - &par, 1); 164 - if (ret < 0) { 165 - dev_err(nt->dev, "failed to disable display backlight (%d)\n", ret); 166 - return ret; 167 - } 168 - return 0; 161 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 162 + MIPI_DCS_WRITE_CONTROL_DISPLAY, 163 + 0x00); 164 + return dsi_ctx.accum_err; 169 165 } 170 166 171 167 /* Calculate the PWM duty cycle in n/256's */ ··· 172 176 173 177 /* Set up PWM dutycycle ONE byte (differs from the standard) */ 174 178 dev_dbg(nt->dev, "calculated duty cycle %02x\n", pwm_ratio); 175 - ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, 176 - &pwm_ratio, 1); 177 - if (ret < 0) { 178 - dev_err(nt->dev, "failed to set display PWM ratio (%d)\n", ret); 179 - return ret; 180 - } 181 179 182 180 /* 183 181 * Sequence to write PWMDIV: ··· 182 192 * 0x22 PWMDIV 183 193 * 0x7F 0xAA CMD2 page 1 lock 184 194 */ 185 - par = 0xaa; 186 - ret = mipi_dsi_dcs_write(dsi, 0xf3, &par, 1); 187 - if (ret < 0) { 188 - dev_err(nt->dev, "failed to unlock CMD 2 (%d)\n", ret); 189 - return ret; 190 - } 191 - par = 0x01; 192 - ret = mipi_dsi_dcs_write(dsi, 0x00, &par, 1); 193 - if (ret < 0) { 194 - dev_err(nt->dev, "failed to enter page 1 (%d)\n", ret); 195 - return ret; 196 - } 197 - par = 0x01; 198 - ret = mipi_dsi_dcs_write(dsi, 0x7d, &par, 1); 199 - if (ret < 0) { 200 - dev_err(nt->dev, "failed to disable MTP reload (%d)\n", ret); 201 - return ret; 202 - } 203 - ret = mipi_dsi_dcs_write(dsi, 0x22, &pwm_div, 1); 204 - if (ret < 0) { 205 - dev_err(nt->dev, "failed to set PWM divisor (%d)\n", ret); 206 - return ret; 207 - } 208 - par = 0xaa; 209 - ret = mipi_dsi_dcs_write(dsi, 0x7f, &par, 1); 210 - if (ret < 0) { 211 - dev_err(nt->dev, "failed to lock CMD 2 (%d)\n", ret); 212 - return ret; 213 - } 195 + mipi_dsi_dcs_write_var_seq_multi(&dsi_ctx, 196 + MIPI_DCS_SET_DISPLAY_BRIGHTNESS, 197 + pwm_ratio); 198 + 199 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0xaa); 200 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x01); 201 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x01); 202 + 203 + mipi_dsi_dcs_write_var_seq_multi(&dsi_ctx, 0x22, pwm_div); 204 + 205 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0xaa); 214 206 215 207 /* Enable backlight */ 216 - par = 0x24; 217 - ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 218 - &par, 1); 219 - if (ret < 0) { 220 - dev_err(nt->dev, "failed to enable display backlight (%d)\n", ret); 221 - return ret; 222 - } 208 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 209 + 0x24); 223 210 224 - return 0; 211 + return dsi_ctx.accum_err; 225 212 } 226 213 227 214 static const struct backlight_ops nt35560_bl_ops = { ··· 211 244 .max_brightness = 1023, 212 245 }; 213 246 214 - static int nt35560_read_id(struct nt35560 *nt) 247 + static void nt35560_read_id(struct mipi_dsi_multi_context *dsi_ctx) 215 248 { 216 - struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev); 249 + struct device dev = dsi_ctx->dsi->dev; 217 250 u8 vendor, version, panel; 218 251 u16 val; 219 - int ret; 220 252 221 - ret = mipi_dsi_dcs_read(dsi, NT35560_DCS_READ_ID1, &vendor, 1); 222 - if (ret < 0) { 223 - dev_err(nt->dev, "could not vendor ID byte\n"); 224 - return ret; 225 - } 226 - ret = mipi_dsi_dcs_read(dsi, NT35560_DCS_READ_ID2, &version, 1); 227 - if (ret < 0) { 228 - dev_err(nt->dev, "could not read device version byte\n"); 229 - return ret; 230 - } 231 - ret = mipi_dsi_dcs_read(dsi, NT35560_DCS_READ_ID3, &panel, 1); 232 - if (ret < 0) { 233 - dev_err(nt->dev, "could not read panel ID byte\n"); 234 - return ret; 235 - } 253 + mipi_dsi_dcs_read_multi(dsi_ctx, NT35560_DCS_READ_ID1, &vendor, 1); 254 + mipi_dsi_dcs_read_multi(dsi_ctx, NT35560_DCS_READ_ID2, &version, 1); 255 + mipi_dsi_dcs_read_multi(dsi_ctx, NT35560_DCS_READ_ID3, &panel, 1); 256 + 257 + if (dsi_ctx->accum_err < 0) 258 + return; 236 259 237 260 if (vendor == 0x00) { 238 - dev_err(nt->dev, "device vendor ID is zero\n"); 239 - return -ENODEV; 261 + dev_err(&dev, "device vendor ID is zero\n"); 262 + dsi_ctx->accum_err = -ENODEV; 263 + return; 240 264 } 241 265 242 266 val = (vendor << 8) | panel; ··· 236 278 case DISPLAY_SONY_ACX424AKP_ID2: 237 279 case DISPLAY_SONY_ACX424AKP_ID3: 238 280 case DISPLAY_SONY_ACX424AKP_ID4: 239 - dev_info(nt->dev, "MTP vendor: %02x, version: %02x, panel: %02x\n", 281 + dev_info(&dev, 282 + "MTP vendor: %02x, version: %02x, panel: %02x\n", 240 283 vendor, version, panel); 241 284 break; 242 285 default: 243 - dev_info(nt->dev, "unknown vendor: %02x, version: %02x, panel: %02x\n", 286 + dev_info(&dev, 287 + "unknown vendor: %02x, version: %02x, panel: %02x\n", 244 288 vendor, version, panel); 245 289 break; 246 290 } 247 - 248 - return 0; 249 291 } 250 292 251 293 static int nt35560_power_on(struct nt35560 *nt) ··· 280 322 static int nt35560_prepare(struct drm_panel *panel) 281 323 { 282 324 struct nt35560 *nt = panel_to_nt35560(panel); 283 - struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev); 284 - const u8 mddi = 3; 325 + struct mipi_dsi_multi_context dsi_ctx = { 326 + .dsi = to_mipi_dsi_device(nt->dev) 327 + }; 285 328 int ret; 286 329 287 330 ret = nt35560_power_on(nt); 288 331 if (ret) 289 332 return ret; 290 333 291 - ret = nt35560_read_id(nt); 292 - if (ret) { 293 - dev_err(nt->dev, "failed to read panel ID (%d)\n", ret); 294 - goto err_power_off; 295 - } 334 + nt35560_read_id(&dsi_ctx); 296 335 297 - /* Enabe tearing mode: send TE (tearing effect) at VBLANK */ 298 - ret = mipi_dsi_dcs_set_tear_on(dsi, 336 + /* Enable tearing mode: send TE (tearing effect) at VBLANK */ 337 + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, 299 338 MIPI_DSI_DCS_TEAR_MODE_VBLANK); 300 - if (ret) { 301 - dev_err(nt->dev, "failed to enable vblank TE (%d)\n", ret); 302 - goto err_power_off; 303 - } 304 339 305 340 /* 306 341 * Set MDDI 307 342 * 308 343 * This presumably deactivates the Qualcomm MDDI interface and 309 344 * selects DSI, similar code is found in other drivers such as the 310 - * Sharp LS043T1LE01 which makes us suspect that this panel may be 311 - * using a Novatek NT35565 or similar display driver chip that shares 312 - * this command. Due to the lack of documentation we cannot know for 313 - * sure. 345 + * Sharp LS043T1LE01. 314 346 */ 315 - ret = mipi_dsi_dcs_write(dsi, NT35560_DCS_SET_MDDI, 316 - &mddi, sizeof(mddi)); 317 - if (ret < 0) { 318 - dev_err(nt->dev, "failed to set MDDI (%d)\n", ret); 319 - goto err_power_off; 320 - } 347 + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, NT35560_DCS_SET_MDDI, 3); 321 348 322 - /* Exit sleep mode */ 323 - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 324 - if (ret) { 325 - dev_err(nt->dev, "failed to exit sleep mode (%d)\n", ret); 326 - goto err_power_off; 327 - } 328 - msleep(140); 349 + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); 350 + mipi_dsi_msleep(&dsi_ctx, 140); 329 351 330 - ret = mipi_dsi_dcs_set_display_on(dsi); 331 - if (ret) { 332 - dev_err(nt->dev, "failed to turn display on (%d)\n", ret); 333 - goto err_power_off; 334 - } 352 + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); 335 353 if (nt->video_mode) { 336 - /* In video mode turn peripheral on */ 337 - ret = mipi_dsi_turn_on_peripheral(dsi); 338 - if (ret) { 339 - dev_err(nt->dev, "failed to turn on peripheral\n"); 340 - goto err_power_off; 341 - } 354 + mipi_dsi_turn_on_peripheral_multi(&dsi_ctx); 342 355 } 343 356 344 - return 0; 345 - 346 - err_power_off: 347 - nt35560_power_off(nt); 348 - return ret; 357 + if (dsi_ctx.accum_err < 0) 358 + nt35560_power_off(nt); 359 + return dsi_ctx.accum_err; 349 360 } 350 361 351 362 static int nt35560_unprepare(struct drm_panel *panel) 352 363 { 353 364 struct nt35560 *nt = panel_to_nt35560(panel); 354 - struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev); 355 - int ret; 365 + struct mipi_dsi_multi_context dsi_ctx = { 366 + .dsi = to_mipi_dsi_device(nt->dev) 367 + }; 356 368 357 - ret = mipi_dsi_dcs_set_display_off(dsi); 358 - if (ret) { 359 - dev_err(nt->dev, "failed to turn display off (%d)\n", ret); 360 - return ret; 361 - } 369 + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); 370 + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); 362 371 363 - /* Enter sleep mode */ 364 - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 365 - if (ret) { 366 - dev_err(nt->dev, "failed to enter sleep mode (%d)\n", ret); 367 - return ret; 368 - } 372 + if (dsi_ctx.accum_err < 0) 373 + return dsi_ctx.accum_err; 374 + 369 375 msleep(85); 370 376 371 377 nt35560_power_off(nt);
+2
drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c
··· 7 7 #include <linux/backlight.h> 8 8 #include <linux/delay.h> 9 9 #include <linux/gpio/consumer.h> 10 + #include <linux/mod_devicetable.h> 10 11 #include <linux/module.h> 12 + #include <linux/property.h> 11 13 #include <linux/regulator/consumer.h> 12 14 13 15 #include <video/mipi_display.h>
-2
drivers/gpu/drm/panfrost/panfrost_perfcnt.c
··· 203 203 panfrost_mmu_as_put(pfdev, perfcnt->mapping->mmu); 204 204 panfrost_gem_mapping_put(perfcnt->mapping); 205 205 perfcnt->mapping = NULL; 206 - pm_runtime_mark_last_busy(pfdev->dev); 207 206 pm_runtime_put_autosuspend(pfdev->dev); 208 207 209 208 return 0; ··· 278 279 if (perfcnt->user == pfile) 279 280 panfrost_perfcnt_disable_locked(pfdev, file_priv); 280 281 mutex_unlock(&perfcnt->lock); 281 - pm_runtime_mark_last_busy(pfdev->dev); 282 282 pm_runtime_put_autosuspend(pfdev->dev); 283 283 } 284 284
+1
drivers/gpu/drm/panthor/Makefile
··· 8 8 panthor_gem.o \ 9 9 panthor_gpu.o \ 10 10 panthor_heap.o \ 11 + panthor_hw.o \ 11 12 panthor_mmu.o \ 12 13 panthor_sched.o 13 14
+5
drivers/gpu/drm/panthor/panthor_device.c
··· 18 18 #include "panthor_device.h" 19 19 #include "panthor_fw.h" 20 20 #include "panthor_gpu.h" 21 + #include "panthor_hw.h" 21 22 #include "panthor_mmu.h" 22 23 #include "panthor_regs.h" 23 24 #include "panthor_sched.h" ··· 244 243 if (ret) 245 244 return ret; 246 245 } 246 + 247 + ret = panthor_hw_init(ptdev); 248 + if (ret) 249 + goto err_rpm_put; 247 250 248 251 ret = panthor_gpu_init(ptdev); 249 252 if (ret)
+5
drivers/gpu/drm/panthor/panthor_fw.c
··· 1402 1402 } 1403 1403 1404 1404 MODULE_FIRMWARE("arm/mali/arch10.8/mali_csffw.bin"); 1405 + MODULE_FIRMWARE("arm/mali/arch10.10/mali_csffw.bin"); 1406 + MODULE_FIRMWARE("arm/mali/arch10.12/mali_csffw.bin"); 1407 + MODULE_FIRMWARE("arm/mali/arch11.8/mali_csffw.bin"); 1408 + MODULE_FIRMWARE("arm/mali/arch12.8/mali_csffw.bin"); 1409 + MODULE_FIRMWARE("arm/mali/arch13.8/mali_csffw.bin");
+6 -94
drivers/gpu/drm/panthor/panthor_gpu.c
··· 35 35 36 36 /** @reqs_acked: GPU request wait queue. */ 37 37 wait_queue_head_t reqs_acked; 38 - }; 39 38 40 - /** 41 - * struct panthor_model - GPU model description 42 - */ 43 - struct panthor_model { 44 - /** @name: Model name. */ 45 - const char *name; 46 - 47 - /** @arch_major: Major version number of architecture. */ 48 - u8 arch_major; 49 - 50 - /** @product_major: Major version number of product. */ 51 - u8 product_major; 52 - }; 53 - 54 - /** 55 - * GPU_MODEL() - Define a GPU model. A GPU product can be uniquely identified 56 - * by a combination of the major architecture version and the major product 57 - * version. 58 - * @_name: Name for the GPU model. 59 - * @_arch_major: Architecture major. 60 - * @_product_major: Product major. 61 - */ 62 - #define GPU_MODEL(_name, _arch_major, _product_major) \ 63 - {\ 64 - .name = __stringify(_name), \ 65 - .arch_major = _arch_major, \ 66 - .product_major = _product_major, \ 67 - } 68 - 69 - static const struct panthor_model gpu_models[] = { 70 - GPU_MODEL(g610, 10, 7), 71 - {}, 39 + /** @cache_flush_lock: Lock to serialize cache flushes */ 40 + struct mutex cache_flush_lock; 72 41 }; 73 42 74 43 #define GPU_INTERRUPTS_MASK \ ··· 50 81 { 51 82 gpu_write(ptdev, GPU_COHERENCY_PROTOCOL, 52 83 ptdev->coherent ? GPU_COHERENCY_PROT_BIT(ACE_LITE) : GPU_COHERENCY_NONE); 53 - } 54 - 55 - static void panthor_gpu_init_info(struct panthor_device *ptdev) 56 - { 57 - const struct panthor_model *model; 58 - u32 arch_major, product_major; 59 - u32 major, minor, status; 60 - unsigned int i; 61 - 62 - ptdev->gpu_info.gpu_id = gpu_read(ptdev, GPU_ID); 63 - ptdev->gpu_info.csf_id = gpu_read(ptdev, GPU_CSF_ID); 64 - ptdev->gpu_info.gpu_rev = gpu_read(ptdev, GPU_REVID); 65 - ptdev->gpu_info.core_features = gpu_read(ptdev, GPU_CORE_FEATURES); 66 - ptdev->gpu_info.l2_features = gpu_read(ptdev, GPU_L2_FEATURES); 67 - ptdev->gpu_info.tiler_features = gpu_read(ptdev, GPU_TILER_FEATURES); 68 - ptdev->gpu_info.mem_features = gpu_read(ptdev, GPU_MEM_FEATURES); 69 - ptdev->gpu_info.mmu_features = gpu_read(ptdev, GPU_MMU_FEATURES); 70 - ptdev->gpu_info.thread_features = gpu_read(ptdev, GPU_THREAD_FEATURES); 71 - ptdev->gpu_info.max_threads = gpu_read(ptdev, GPU_THREAD_MAX_THREADS); 72 - ptdev->gpu_info.thread_max_workgroup_size = gpu_read(ptdev, GPU_THREAD_MAX_WORKGROUP_SIZE); 73 - ptdev->gpu_info.thread_max_barrier_size = gpu_read(ptdev, GPU_THREAD_MAX_BARRIER_SIZE); 74 - ptdev->gpu_info.coherency_features = gpu_read(ptdev, GPU_COHERENCY_FEATURES); 75 - for (i = 0; i < 4; i++) 76 - ptdev->gpu_info.texture_features[i] = gpu_read(ptdev, GPU_TEXTURE_FEATURES(i)); 77 - 78 - ptdev->gpu_info.as_present = gpu_read(ptdev, GPU_AS_PRESENT); 79 - 80 - ptdev->gpu_info.shader_present = gpu_read64(ptdev, GPU_SHADER_PRESENT); 81 - ptdev->gpu_info.tiler_present = gpu_read64(ptdev, GPU_TILER_PRESENT); 82 - ptdev->gpu_info.l2_present = gpu_read64(ptdev, GPU_L2_PRESENT); 83 - 84 - arch_major = GPU_ARCH_MAJOR(ptdev->gpu_info.gpu_id); 85 - product_major = GPU_PROD_MAJOR(ptdev->gpu_info.gpu_id); 86 - major = GPU_VER_MAJOR(ptdev->gpu_info.gpu_id); 87 - minor = GPU_VER_MINOR(ptdev->gpu_info.gpu_id); 88 - status = GPU_VER_STATUS(ptdev->gpu_info.gpu_id); 89 - 90 - for (model = gpu_models; model->name; model++) { 91 - if (model->arch_major == arch_major && 92 - model->product_major == product_major) 93 - break; 94 - } 95 - 96 - drm_info(&ptdev->base, 97 - "mali-%s id 0x%x major 0x%x minor 0x%x status 0x%x", 98 - model->name ?: "unknown", ptdev->gpu_info.gpu_id >> 16, 99 - major, minor, status); 100 - 101 - drm_info(&ptdev->base, 102 - "Features: L2:%#x Tiler:%#x Mem:%#x MMU:%#x AS:%#x", 103 - ptdev->gpu_info.l2_features, 104 - ptdev->gpu_info.tiler_features, 105 - ptdev->gpu_info.mem_features, 106 - ptdev->gpu_info.mmu_features, 107 - ptdev->gpu_info.as_present); 108 - 109 - drm_info(&ptdev->base, 110 - "shader_present=0x%0llx l2_present=0x%0llx tiler_present=0x%0llx", 111 - ptdev->gpu_info.shader_present, ptdev->gpu_info.l2_present, 112 - ptdev->gpu_info.tiler_present); 113 84 } 114 85 115 86 static void panthor_gpu_irq_handler(struct panthor_device *ptdev, u32 status) ··· 113 204 114 205 spin_lock_init(&gpu->reqs_lock); 115 206 init_waitqueue_head(&gpu->reqs_acked); 207 + mutex_init(&gpu->cache_flush_lock); 116 208 ptdev->gpu = gpu; 117 - panthor_gpu_init_info(ptdev); 118 209 119 210 dma_set_max_seg_size(ptdev->base.dev, UINT_MAX); 120 211 pa_bits = GPU_MMU_FEATURES_PA_BITS(ptdev->gpu_info.mmu_features); ··· 261 352 { 262 353 bool timedout = false; 263 354 unsigned long flags; 355 + 356 + /* Serialize cache flush operations. */ 357 + guard(mutex)(&ptdev->gpu->cache_flush_lock); 264 358 265 359 spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags); 266 360 if (!drm_WARN_ON(&ptdev->base,
+125
drivers/gpu/drm/panthor/panthor_hw.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 or MIT 2 + /* Copyright 2025 ARM Limited. All rights reserved. */ 3 + 4 + #include "panthor_device.h" 5 + #include "panthor_hw.h" 6 + #include "panthor_regs.h" 7 + 8 + #define GPU_PROD_ID_MAKE(arch_major, prod_major) \ 9 + (((arch_major) << 24) | (prod_major)) 10 + 11 + static char *get_gpu_model_name(struct panthor_device *ptdev) 12 + { 13 + const u32 gpu_id = ptdev->gpu_info.gpu_id; 14 + const u32 product_id = GPU_PROD_ID_MAKE(GPU_ARCH_MAJOR(gpu_id), 15 + GPU_PROD_MAJOR(gpu_id)); 16 + const bool ray_intersection = !!(ptdev->gpu_info.gpu_features & 17 + GPU_FEATURES_RAY_INTERSECTION); 18 + const u8 shader_core_count = hweight64(ptdev->gpu_info.shader_present); 19 + 20 + switch (product_id) { 21 + case GPU_PROD_ID_MAKE(10, 2): 22 + return "Mali-G710"; 23 + case GPU_PROD_ID_MAKE(10, 3): 24 + return "Mali-G510"; 25 + case GPU_PROD_ID_MAKE(10, 4): 26 + return "Mali-G310"; 27 + case GPU_PROD_ID_MAKE(10, 7): 28 + return "Mali-G610"; 29 + case GPU_PROD_ID_MAKE(11, 2): 30 + if (shader_core_count > 10 && ray_intersection) 31 + return "Mali-G715-Immortalis"; 32 + else if (shader_core_count >= 7) 33 + return "Mali-G715"; 34 + 35 + fallthrough; 36 + case GPU_PROD_ID_MAKE(11, 3): 37 + return "Mali-G615"; 38 + case GPU_PROD_ID_MAKE(12, 0): 39 + if (shader_core_count >= 10 && ray_intersection) 40 + return "Mali-G720-Immortalis"; 41 + else if (shader_core_count >= 6) 42 + return "Mali-G720"; 43 + 44 + fallthrough; 45 + case GPU_PROD_ID_MAKE(12, 1): 46 + return "Mali-G620"; 47 + case GPU_PROD_ID_MAKE(13, 0): 48 + if (shader_core_count >= 10 && ray_intersection) 49 + return "Mali-G925-Immortalis"; 50 + else if (shader_core_count >= 6) 51 + return "Mali-G725"; 52 + 53 + fallthrough; 54 + case GPU_PROD_ID_MAKE(13, 1): 55 + return "Mali-G625"; 56 + } 57 + 58 + return "(Unknown Mali GPU)"; 59 + } 60 + 61 + static void panthor_gpu_info_init(struct panthor_device *ptdev) 62 + { 63 + unsigned int i; 64 + 65 + ptdev->gpu_info.gpu_id = gpu_read(ptdev, GPU_ID); 66 + ptdev->gpu_info.csf_id = gpu_read(ptdev, GPU_CSF_ID); 67 + ptdev->gpu_info.gpu_rev = gpu_read(ptdev, GPU_REVID); 68 + ptdev->gpu_info.core_features = gpu_read(ptdev, GPU_CORE_FEATURES); 69 + ptdev->gpu_info.l2_features = gpu_read(ptdev, GPU_L2_FEATURES); 70 + ptdev->gpu_info.tiler_features = gpu_read(ptdev, GPU_TILER_FEATURES); 71 + ptdev->gpu_info.mem_features = gpu_read(ptdev, GPU_MEM_FEATURES); 72 + ptdev->gpu_info.mmu_features = gpu_read(ptdev, GPU_MMU_FEATURES); 73 + ptdev->gpu_info.thread_features = gpu_read(ptdev, GPU_THREAD_FEATURES); 74 + ptdev->gpu_info.max_threads = gpu_read(ptdev, GPU_THREAD_MAX_THREADS); 75 + ptdev->gpu_info.thread_max_workgroup_size = gpu_read(ptdev, GPU_THREAD_MAX_WORKGROUP_SIZE); 76 + ptdev->gpu_info.thread_max_barrier_size = gpu_read(ptdev, GPU_THREAD_MAX_BARRIER_SIZE); 77 + ptdev->gpu_info.coherency_features = gpu_read(ptdev, GPU_COHERENCY_FEATURES); 78 + for (i = 0; i < 4; i++) 79 + ptdev->gpu_info.texture_features[i] = gpu_read(ptdev, GPU_TEXTURE_FEATURES(i)); 80 + 81 + ptdev->gpu_info.as_present = gpu_read(ptdev, GPU_AS_PRESENT); 82 + 83 + ptdev->gpu_info.shader_present = gpu_read64(ptdev, GPU_SHADER_PRESENT); 84 + ptdev->gpu_info.tiler_present = gpu_read64(ptdev, GPU_TILER_PRESENT); 85 + ptdev->gpu_info.l2_present = gpu_read64(ptdev, GPU_L2_PRESENT); 86 + 87 + /* Introduced in arch 11.x */ 88 + ptdev->gpu_info.gpu_features = gpu_read64(ptdev, GPU_FEATURES); 89 + } 90 + 91 + static void panthor_hw_info_init(struct panthor_device *ptdev) 92 + { 93 + u32 major, minor, status; 94 + 95 + panthor_gpu_info_init(ptdev); 96 + 97 + major = GPU_VER_MAJOR(ptdev->gpu_info.gpu_id); 98 + minor = GPU_VER_MINOR(ptdev->gpu_info.gpu_id); 99 + status = GPU_VER_STATUS(ptdev->gpu_info.gpu_id); 100 + 101 + drm_info(&ptdev->base, 102 + "%s id 0x%x major 0x%x minor 0x%x status 0x%x", 103 + get_gpu_model_name(ptdev), ptdev->gpu_info.gpu_id >> 16, 104 + major, minor, status); 105 + 106 + drm_info(&ptdev->base, 107 + "Features: L2:%#x Tiler:%#x Mem:%#x MMU:%#x AS:%#x", 108 + ptdev->gpu_info.l2_features, 109 + ptdev->gpu_info.tiler_features, 110 + ptdev->gpu_info.mem_features, 111 + ptdev->gpu_info.mmu_features, 112 + ptdev->gpu_info.as_present); 113 + 114 + drm_info(&ptdev->base, 115 + "shader_present=0x%0llx l2_present=0x%0llx tiler_present=0x%0llx", 116 + ptdev->gpu_info.shader_present, ptdev->gpu_info.l2_present, 117 + ptdev->gpu_info.tiler_present); 118 + } 119 + 120 + int panthor_hw_init(struct panthor_device *ptdev) 121 + { 122 + panthor_hw_info_init(ptdev); 123 + 124 + return 0; 125 + }
+11
drivers/gpu/drm/panthor/panthor_hw.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 or MIT */ 2 + /* Copyright 2025 ARM Limited. All rights reserved. */ 3 + 4 + #ifndef __PANTHOR_HW_H__ 5 + #define __PANTHOR_HW_H__ 6 + 7 + struct panthor_device; 8 + 9 + int panthor_hw_init(struct panthor_device *ptdev); 10 + 11 + #endif /* __PANTHOR_HW_H__ */
+43 -3
drivers/gpu/drm/panthor/panthor_mmu.c
··· 29 29 30 30 #include "panthor_device.h" 31 31 #include "panthor_gem.h" 32 + #include "panthor_gpu.h" 32 33 #include "panthor_heap.h" 33 34 #include "panthor_mmu.h" 34 35 #include "panthor_regs.h" ··· 569 568 write_cmd(ptdev, as_nr, AS_COMMAND_LOCK); 570 569 } 571 570 571 + static int mmu_hw_do_flush_on_gpu_ctrl(struct panthor_device *ptdev, int as_nr, 572 + u32 op) 573 + { 574 + const u32 l2_flush_op = CACHE_CLEAN | CACHE_INV; 575 + u32 lsc_flush_op = 0; 576 + int ret; 577 + 578 + if (op == AS_COMMAND_FLUSH_MEM) 579 + lsc_flush_op = CACHE_CLEAN | CACHE_INV; 580 + 581 + ret = wait_ready(ptdev, as_nr); 582 + if (ret) 583 + return ret; 584 + 585 + ret = panthor_gpu_flush_caches(ptdev, l2_flush_op, lsc_flush_op, 0); 586 + if (ret) 587 + return ret; 588 + 589 + /* 590 + * Explicitly unlock the region as the AS is not unlocked automatically 591 + * at the end of the GPU_CONTROL cache flush command, unlike 592 + * AS_COMMAND_FLUSH_MEM or AS_COMMAND_FLUSH_PT. 593 + */ 594 + write_cmd(ptdev, as_nr, AS_COMMAND_UNLOCK); 595 + 596 + /* Wait for the unlock command to complete */ 597 + return wait_ready(ptdev, as_nr); 598 + } 599 + 572 600 static int mmu_hw_do_operation_locked(struct panthor_device *ptdev, int as_nr, 573 601 u64 iova, u64 size, u32 op) 574 602 { ··· 614 584 615 585 if (op != AS_COMMAND_UNLOCK) 616 586 lock_region(ptdev, as_nr, iova, size); 587 + 588 + if (op == AS_COMMAND_FLUSH_MEM || op == AS_COMMAND_FLUSH_PT) 589 + return mmu_hw_do_flush_on_gpu_ctrl(ptdev, as_nr, op); 617 590 618 591 /* Run the MMU operation */ 619 592 write_cmd(ptdev, as_nr, op); ··· 2202 2169 mutex_lock(&vm->op_lock); 2203 2170 vm->op_ctx = op; 2204 2171 switch (op_type) { 2205 - case DRM_PANTHOR_VM_BIND_OP_TYPE_MAP: 2172 + case DRM_PANTHOR_VM_BIND_OP_TYPE_MAP: { 2173 + const struct drm_gpuvm_map_req map_req = { 2174 + .map.va.addr = op->va.addr, 2175 + .map.va.range = op->va.range, 2176 + .map.gem.obj = op->map.vm_bo->obj, 2177 + .map.gem.offset = op->map.bo_offset, 2178 + }; 2179 + 2206 2180 if (vm->unusable) { 2207 2181 ret = -EINVAL; 2208 2182 break; 2209 2183 } 2210 2184 2211 - ret = drm_gpuvm_sm_map(&vm->base, vm, op->va.addr, op->va.range, 2212 - op->map.vm_bo->obj, op->map.bo_offset); 2185 + ret = drm_gpuvm_sm_map(&vm->base, vm, &map_req); 2213 2186 break; 2187 + } 2214 2188 2215 2189 case DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP: 2216 2190 ret = drm_gpuvm_sm_unmap(&vm->base, vm, op->va.addr, op->va.range);
+3
drivers/gpu/drm/panthor/panthor_regs.h
··· 70 70 #define GPU_PWR_OVERRIDE0 0x54 71 71 #define GPU_PWR_OVERRIDE1 0x58 72 72 73 + #define GPU_FEATURES 0x60 74 + #define GPU_FEATURES_RAY_INTERSECTION BIT(2) 75 + 73 76 #define GPU_TIMESTAMP_OFFSET 0x88 74 77 #define GPU_CYCLE_COUNT 0x90 75 78 #define GPU_TIMESTAMP 0x98
+1 -2
drivers/gpu/drm/virtio/virtgpu_display.c
··· 131 131 * in the plane update callback, and here we just check 132 132 * whenever we must force the modeset. 133 133 */ 134 - if (drm_atomic_crtc_needs_modeset(crtc_state)) { 134 + if (drm_atomic_crtc_needs_modeset(crtc_state)) 135 135 output->needs_modeset = true; 136 - } 137 136 } 138 137 139 138 static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = {
+10 -10
drivers/gpu/drm/virtio/virtgpu_kms.c
··· 162 162 if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_VIRGL)) 163 163 vgdev->has_virgl_3d = true; 164 164 #endif 165 - if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_EDID)) { 165 + if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_EDID)) 166 166 vgdev->has_edid = true; 167 - } 168 - if (virtio_has_feature(vgdev->vdev, VIRTIO_RING_F_INDIRECT_DESC)) { 167 + 168 + if (virtio_has_feature(vgdev->vdev, VIRTIO_RING_F_INDIRECT_DESC)) 169 169 vgdev->has_indirect = true; 170 - } 171 - if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_RESOURCE_UUID)) { 170 + 171 + if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_RESOURCE_UUID)) 172 172 vgdev->has_resource_assign_uuid = true; 173 - } 174 - if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_RESOURCE_BLOB)) { 173 + 174 + if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_RESOURCE_BLOB)) 175 175 vgdev->has_resource_blob = true; 176 - } 176 + 177 177 if (virtio_get_shm_region(vgdev->vdev, &vgdev->host_visible_region, 178 178 VIRTIO_GPU_SHM_ID_HOST_VISIBLE)) { 179 179 if (!devm_request_mem_region(&vgdev->vdev->dev, ··· 193 193 (unsigned long)vgdev->host_visible_region.addr, 194 194 (unsigned long)vgdev->host_visible_region.len); 195 195 } 196 - if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_CONTEXT_INIT)) { 196 + 197 + if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_CONTEXT_INIT)) 197 198 vgdev->has_context_init = true; 198 - } 199 199 200 200 DRM_INFO("features: %cvirgl %cedid %cresource_blob %chost_visible", 201 201 vgdev->has_virgl_3d ? '+' : '-',
+2 -2
drivers/gpu/drm/virtio/virtgpu_object.c
··· 47 47 *resid = handle + 1; 48 48 } else { 49 49 int handle = ida_alloc(&vgdev->resource_ida, GFP_KERNEL); 50 + 50 51 if (handle < 0) 51 52 return handle; 52 53 *resid = handle + 1; ··· 57 56 58 57 static void virtio_gpu_resource_id_put(struct virtio_gpu_device *vgdev, uint32_t id) 59 58 { 60 - if (!virtio_gpu_virglrenderer_workaround) { 59 + if (!virtio_gpu_virglrenderer_workaround) 61 60 ida_free(&vgdev->resource_ida, id - 1); 62 - } 63 61 } 64 62 65 63 void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo)
+1 -1
drivers/gpu/drm/virtio/virtgpu_plane.c
··· 120 120 crtc_state = drm_atomic_get_crtc_state(state, 121 121 new_plane_state->crtc); 122 122 if (IS_ERR(crtc_state)) 123 - return PTR_ERR(crtc_state); 123 + return PTR_ERR(crtc_state); 124 124 125 125 ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, 126 126 DRM_PLANE_NO_SCALING,
+2
drivers/gpu/drm/virtio/virtgpu_vq.c
··· 248 248 if (resp->type != cpu_to_le32(VIRTIO_GPU_RESP_OK_NODATA)) { 249 249 if (le32_to_cpu(resp->type) >= VIRTIO_GPU_RESP_ERR_UNSPEC) { 250 250 struct virtio_gpu_ctrl_hdr *cmd; 251 + 251 252 cmd = virtio_gpu_vbuf_ctrl_hdr(entry); 252 253 DRM_ERROR_RATELIMITED("response 0x%x (command 0x%x)\n", 253 254 le32_to_cpu(resp->type), ··· 469 468 if (vbuf->data_size) { 470 469 if (is_vmalloc_addr(vbuf->data_buf)) { 471 470 int sg_ents; 471 + 472 472 sgt = vmalloc_to_sgt(vbuf->data_buf, vbuf->data_size, 473 473 &sg_ents); 474 474 if (!sgt) {
+10 -3
drivers/gpu/drm/xe/xe_vm.c
··· 2316 2316 2317 2317 switch (operation) { 2318 2318 case DRM_XE_VM_BIND_OP_MAP: 2319 - case DRM_XE_VM_BIND_OP_MAP_USERPTR: 2320 - ops = drm_gpuvm_sm_map_ops_create(&vm->gpuvm, addr, range, 2321 - obj, bo_offset_or_userptr); 2319 + case DRM_XE_VM_BIND_OP_MAP_USERPTR: { 2320 + struct drm_gpuvm_map_req map_req = { 2321 + .map.va.addr = addr, 2322 + .map.va.range = range, 2323 + .map.gem.obj = obj, 2324 + .map.gem.offset = bo_offset_or_userptr, 2325 + }; 2326 + 2327 + ops = drm_gpuvm_sm_map_ops_create(&vm->gpuvm, &map_req); 2322 2328 break; 2329 + } 2323 2330 case DRM_XE_VM_BIND_OP_UNMAP: 2324 2331 ops = drm_gpuvm_sm_unmap_ops_create(&vm->gpuvm, addr, range); 2325 2332 break;
+4
include/drm/drm_bridge.h
··· 1172 1172 */ 1173 1173 bool pre_enable_prev_first; 1174 1174 /** 1175 + * @support_hdcp: Indicate that the bridge supports HDCP. 1176 + */ 1177 + bool support_hdcp; 1178 + /** 1175 1179 * @ddc: Associated I2C adapter for DDC access, if any. 1176 1180 */ 1177 1181 struct i2c_adapter *ddc;
+70
include/drm/drm_gpusvm.h
··· 282 282 bool drm_gpusvm_has_mapping(struct drm_gpusvm *gpusvm, unsigned long start, 283 283 unsigned long end); 284 284 285 + struct drm_gpusvm_notifier * 286 + drm_gpusvm_notifier_find(struct drm_gpusvm *gpusvm, unsigned long start, 287 + unsigned long end); 288 + 285 289 struct drm_gpusvm_range * 286 290 drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier, unsigned long start, 287 291 unsigned long end); ··· 437 433 drm_gpusvm_range_find((notifier__), (start__), (end__)); \ 438 434 (range__) && (drm_gpusvm_range_start(range__) < (end__)); \ 439 435 (range__) = __drm_gpusvm_range_next(range__)) 436 + 437 + /** 438 + * drm_gpusvm_for_each_range_safe() - Safely iterate over GPU SVM ranges in a notifier 439 + * @range__: Iterator variable for the ranges 440 + * @next__: Iterator variable for the ranges temporay storage 441 + * @notifier__: Pointer to the GPU SVM notifier 442 + * @start__: Start address of the range 443 + * @end__: End address of the range 444 + * 445 + * This macro is used to iterate over GPU SVM ranges in a notifier while 446 + * removing ranges from it. 447 + */ 448 + #define drm_gpusvm_for_each_range_safe(range__, next__, notifier__, start__, end__) \ 449 + for ((range__) = drm_gpusvm_range_find((notifier__), (start__), (end__)), \ 450 + (next__) = __drm_gpusvm_range_next(range__); \ 451 + (range__) && (drm_gpusvm_range_start(range__) < (end__)); \ 452 + (range__) = (next__), (next__) = __drm_gpusvm_range_next(range__)) 453 + 454 + /** 455 + * __drm_gpusvm_notifier_next() - get the next drm_gpusvm_notifier in the list 456 + * @notifier: a pointer to the current drm_gpusvm_notifier 457 + * 458 + * Return: A pointer to the next drm_gpusvm_notifier if available, or NULL if 459 + * the current notifier is the last one or if the input notifier is 460 + * NULL. 461 + */ 462 + static inline struct drm_gpusvm_notifier * 463 + __drm_gpusvm_notifier_next(struct drm_gpusvm_notifier *notifier) 464 + { 465 + if (notifier && !list_is_last(&notifier->entry, 466 + &notifier->gpusvm->notifier_list)) 467 + return list_next_entry(notifier, entry); 468 + 469 + return NULL; 470 + } 471 + 472 + /** 473 + * drm_gpusvm_for_each_notifier() - Iterate over GPU SVM notifiers in a gpusvm 474 + * @notifier__: Iterator variable for the notifiers 475 + * @gpusvm__: Pointer to the GPU SVM notifier 476 + * @start__: Start address of the notifier 477 + * @end__: End address of the notifier 478 + * 479 + * This macro is used to iterate over GPU SVM notifiers in a gpusvm. 480 + */ 481 + #define drm_gpusvm_for_each_notifier(notifier__, gpusvm__, start__, end__) \ 482 + for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__)); \ 483 + (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__)); \ 484 + (notifier__) = __drm_gpusvm_notifier_next(notifier__)) 485 + 486 + /** 487 + * drm_gpusvm_for_each_notifier_safe() - Safely iterate over GPU SVM notifiers in a gpusvm 488 + * @notifier__: Iterator variable for the notifiers 489 + * @next__: Iterator variable for the notifiers temporay storage 490 + * @gpusvm__: Pointer to the GPU SVM notifier 491 + * @start__: Start address of the notifier 492 + * @end__: End address of the notifier 493 + * 494 + * This macro is used to iterate over GPU SVM notifiers in a gpusvm while 495 + * removing notifiers from it. 496 + */ 497 + #define drm_gpusvm_for_each_notifier_safe(notifier__, next__, gpusvm__, start__, end__) \ 498 + for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__)), \ 499 + (next__) = __drm_gpusvm_notifier_next(notifier__); \ 500 + (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__)); \ 501 + (notifier__) = (next__), (next__) = __drm_gpusvm_notifier_next(notifier__)) 440 502 441 503 #endif /* __DRM_GPUSVM_H__ */
+21 -17
include/drm/drm_gpuvm.h
··· 160 160 struct drm_gpuva *drm_gpuva_find_prev(struct drm_gpuvm *gpuvm, u64 start); 161 161 struct drm_gpuva *drm_gpuva_find_next(struct drm_gpuvm *gpuvm, u64 end); 162 162 163 - static inline void drm_gpuva_init(struct drm_gpuva *va, u64 addr, u64 range, 164 - struct drm_gem_object *obj, u64 offset) 165 - { 166 - va->va.addr = addr; 167 - va->va.range = range; 168 - va->gem.obj = obj; 169 - va->gem.offset = offset; 170 - } 171 - 172 163 /** 173 164 * drm_gpuva_invalidate() - sets whether the backing GEM of this &drm_gpuva is 174 165 * invalidated ··· 1049 1058 */ 1050 1059 #define drm_gpuva_next_op(op) list_next_entry(op, entry) 1051 1060 1061 + /** 1062 + * struct drm_gpuvm_map_req - arguments passed to drm_gpuvm_sm_map[_ops_create]() 1063 + */ 1064 + struct drm_gpuvm_map_req { 1065 + /** 1066 + * @op_map: struct drm_gpuva_op_map 1067 + */ 1068 + struct drm_gpuva_op_map map; 1069 + }; 1070 + 1052 1071 struct drm_gpuva_ops * 1053 1072 drm_gpuvm_sm_map_ops_create(struct drm_gpuvm *gpuvm, 1054 - u64 addr, u64 range, 1055 - struct drm_gem_object *obj, u64 offset); 1073 + const struct drm_gpuvm_map_req *req); 1074 + struct drm_gpuva_ops * 1075 + drm_gpuvm_madvise_ops_create(struct drm_gpuvm *gpuvm, 1076 + const struct drm_gpuvm_map_req *req); 1077 + 1056 1078 struct drm_gpuva_ops * 1057 1079 drm_gpuvm_sm_unmap_ops_create(struct drm_gpuvm *gpuvm, 1058 1080 u64 addr, u64 range); ··· 1083 1079 static inline void drm_gpuva_init_from_op(struct drm_gpuva *va, 1084 1080 struct drm_gpuva_op_map *op) 1085 1081 { 1086 - drm_gpuva_init(va, op->va.addr, op->va.range, 1087 - op->gem.obj, op->gem.offset); 1082 + va->va.addr = op->va.addr; 1083 + va->va.range = op->va.range; 1084 + va->gem.obj = op->gem.obj; 1085 + va->gem.offset = op->gem.offset; 1088 1086 } 1089 1087 1090 1088 /** ··· 1211 1205 }; 1212 1206 1213 1207 int drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm, void *priv, 1214 - u64 addr, u64 range, 1215 - struct drm_gem_object *obj, u64 offset); 1208 + const struct drm_gpuvm_map_req *req); 1216 1209 1217 1210 int drm_gpuvm_sm_unmap(struct drm_gpuvm *gpuvm, void *priv, 1218 1211 u64 addr, u64 range); 1219 1212 1220 1213 int drm_gpuvm_sm_map_exec_lock(struct drm_gpuvm *gpuvm, 1221 1214 struct drm_exec *exec, unsigned int num_fences, 1222 - u64 req_addr, u64 req_range, 1223 - struct drm_gem_object *obj, u64 offset); 1215 + struct drm_gpuvm_map_req *req); 1224 1216 1225 1217 int drm_gpuvm_sm_unmap_exec_lock(struct drm_gpuvm *gpuvm, struct drm_exec *exec, 1226 1218 u64 req_addr, u64 req_range);
+35
include/drm/drm_mipi_dsi.h
··· 342 342 const void *data, size_t len); 343 343 ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data, 344 344 size_t len); 345 + void mipi_dsi_dcs_read_multi(struct mipi_dsi_multi_context *ctx, u8 cmd, 346 + void *data, size_t len); 345 347 int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi); 346 348 int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi); 347 349 int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode); ··· 406 404 } while (0) 407 405 408 406 /** 407 + * mipi_dsi_generic_write_var_seq_multi - transmit non-constant data using a 408 + * generic write packet 409 + * 410 + * This macro will print errors for you and error handling is optimized for 411 + * callers that call this multiple times in a row. 412 + * 413 + * @ctx: Context for multiple DSI transactions 414 + * @seq: buffer containing the payload 415 + */ 416 + #define mipi_dsi_generic_write_var_seq_multi(ctx, seq...) \ 417 + do { \ 418 + const u8 d[] = { seq }; \ 419 + mipi_dsi_generic_write_multi(ctx, d, ARRAY_SIZE(d)); \ 420 + } while (0) 421 + 422 + /** 409 423 * mipi_dsi_dcs_write_seq_multi - transmit a DCS command with payload 410 424 * 411 425 * This macro will print errors for you and error handling is optimized for ··· 435 417 do { \ 436 418 static const u8 d[] = { cmd, seq }; \ 437 419 mipi_dsi_dcs_write_buffer_multi(ctx, d, ARRAY_SIZE(d)); \ 420 + } while (0) 421 + 422 + /** 423 + * mipi_dsi_dcs_write_var_seq_multi - transmit a DCS command with non-constant 424 + * payload 425 + * 426 + * This macro will print errors for you and error handling is optimized for 427 + * callers that call this multiple times in a row. 428 + * 429 + * @ctx: Context for multiple DSI transactions 430 + * @cmd: Command 431 + * @seq: buffer containing data to be transmitted 432 + */ 433 + #define mipi_dsi_dcs_write_var_seq_multi(ctx, cmd, seq...) \ 434 + do { \ 435 + const u8 d[] = { cmd, seq }; \ 436 + mipi_dsi_dcs_write_buffer_multi(ctx, d, ARRAY_SIZE(d)); \ 438 437 } while (0) 439 438 440 439 /**
+3
include/uapi/drm/panthor_drm.h
··· 327 327 328 328 /** @pad: MBZ. */ 329 329 __u32 pad; 330 + 331 + /** @gpu_features: Bitmask describing supported GPU-wide features */ 332 + __u64 gpu_features; 330 333 }; 331 334 332 335 /**
+2 -1
rust/kernel/drm/device.rs
··· 10 10 error::from_err_ptr, 11 11 error::Result, 12 12 prelude::*, 13 - types::{ARef, AlwaysRefCounted, Opaque}, 13 + sync::aref::{ARef, AlwaysRefCounted}, 14 + types::Opaque, 14 15 }; 15 16 use core::{mem, ops::Deref, ptr, ptr::NonNull}; 16 17
+1 -1
rust/kernel/drm/driver.rs
··· 8 8 bindings, device, devres, drm, 9 9 error::{to_result, Result}, 10 10 prelude::*, 11 - types::ARef, 11 + sync::aref::ARef, 12 12 }; 13 13 use macros::vtable; 14 14
+2 -1
rust/kernel/drm/gem/mod.rs
··· 10 10 drm::driver::{AllocImpl, AllocOps}, 11 11 error::{to_result, Result}, 12 12 prelude::*, 13 - types::{ARef, AlwaysRefCounted, Opaque}, 13 + sync::aref::{ARef, AlwaysRefCounted}, 14 + types::Opaque, 14 15 }; 15 16 use core::{mem, ops::Deref, ptr::NonNull}; 16 17