Re: [PATCH 4/8] drm/bridge: it66121: Add a helper function to get the next bridge
On Thu, 23 Nov 2023 at 07:25, Sui Jingfeng wrote: > > Hi, > > > On 2023/11/15 00:05, Dmitry Baryshkov wrote: > > On Tue, 14 Nov 2023 at 17:09, Sui Jingfeng wrote: > >> From: Sui Jingfeng > >> > >> Group the code lines(which with the same functional) into one dedicated > >> function, which reduce the weight of it66121_probe() function. Just trivial > >> cleanuo, no functional change. > >> > >> Signed-off-by: Sui Jingfeng > >> --- > >> drivers/gpu/drm/bridge/ite-it66121.c | 53 ++-- > >> 1 file changed, 34 insertions(+), 19 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/bridge/ite-it66121.c > >> b/drivers/gpu/drm/bridge/ite-it66121.c > >> index 0f78737adc83..7e473beefc79 100644 > >> --- a/drivers/gpu/drm/bridge/ite-it66121.c > >> +++ b/drivers/gpu/drm/bridge/ite-it66121.c > >> @@ -340,6 +340,37 @@ static int it66121_of_read_bus_width(struct device > >> *dev, u32 *bus_width) > >> return 0; > >> } > >> > >> +static int it66121_of_get_next_bridge(struct device *dev, > >> + struct drm_bridge **next_bridge) > > it already exists and it is called drm_of_find_panel_or_bridge(), > > could you please use it instead? > > That function is too fat and tangled, and should be untangled. > it66121 can not connect with a panel, this is a prior knowledge > and is known at compile time. So this prior knowledge shouldn't > be dropped. This prior knowledge is kept by passing NULL as a panel. We already have a helper. It covers your use case. There is no need to write your own boilerplate code for it. > > >> +{ > >> + struct device_node *np; > >> + struct drm_bridge *bridge; > >> + > >> + np = of_graph_get_remote_node(dev->of_node, 1, -1); > >> + if (!np) { > >> + dev_err(dev, "The endpoint is unconnected\n"); > >> + return -EINVAL; > >> + } > >> + > >> + if (!of_device_is_available(np)) { > >> + of_node_put(np); > >> + dev_err(dev, "The remote device is disabled\n"); > >> + return -ENODEV; > >> + } > >> + > >> + bridge = of_drm_find_bridge(np); > >> + of_node_put(np); > >> + > >> + if (!bridge) { > >> + dev_dbg(dev, "Next bridge not found, deferring probe\n"); > >> + return -EPROBE_DEFER; > >> + } > >> + > >> + *next_bridge = bridge; > >> + > >> + return 0; > >> +} > >> + > >> static const struct regmap_range_cfg it66121_regmap_banks[] = { > >> { > >> .name = "it66121", > >> @@ -1531,7 +1562,6 @@ static const char * const it66121_supplies[] = { > >> static int it66121_probe(struct i2c_client *client) > >> { > >> u32 revision_id, vendor_ids[2] = { 0 }, device_ids[2] = { 0 }; > >> - struct device_node *ep; > >> int ret; > >> struct it66121_ctx *ctx; > >> struct device *dev = >dev; > >> @@ -1553,24 +1583,9 @@ static int it66121_probe(struct i2c_client *client) > >> if (ret) > >> return ret; > >> > >> - ep = of_graph_get_remote_node(dev->of_node, 1, -1); > >> - if (!ep) { > >> - dev_err(dev, "The endpoint is unconnected\n"); > >> - return -EINVAL; > >> - } > >> - > >> - if (!of_device_is_available(ep)) { > >> - of_node_put(ep); > >> - dev_err(dev, "The remote device is disabled\n"); > >> - return -ENODEV; > >> - } > >> - > >> - ctx->next_bridge = of_drm_find_bridge(ep); > >> - of_node_put(ep); > >> - if (!ctx->next_bridge) { > >> - dev_dbg(dev, "Next bridge not found, deferring probe\n"); > >> - return -EPROBE_DEFER; > >> - } > >> + ret = it66121_of_get_next_bridge(dev, >next_bridge); > >> + if (ret) > >> + return ret; > >> > >> i2c_set_clientdata(client, ctx); > >> mutex_init(>lock); > >> -- > >> 2.34.1 > >> > > -- With best wishes Dmitry
Re: [PATCH 5/8] drm/bridge: it66121: Add a helper function to read chip id
On Thu, 23 Nov 2023 at 07:37, Sui Jingfeng wrote: > > Hi, > > > On 2023/11/16 21:00, Dmitry Baryshkov wrote: > > On Thu, 16 Nov 2023 at 14:18, Sui Jingfeng wrote: > >> Hi, > >> > >> > >> On 2023/11/15 00:06, Dmitry Baryshkov wrote: > >>> On Tue, 14 Nov 2023 at 17:09, Sui Jingfeng wrote: > From: Sui Jingfeng > > Read the required chip id data back by calling regmap_bulk_read() once, > reduce the number of local variables needed in it66121_probe() function. > And store its values into struct it66121_ctx, as it will be used latter. > > Signed-off-by: Sui Jingfeng > --- > drivers/gpu/drm/bridge/ite-it66121.c | 47 > 1 file changed, 34 insertions(+), 13 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/ite-it66121.c > b/drivers/gpu/drm/bridge/ite-it66121.c > index 7e473beefc79..f36d05331f25 100644 > --- a/drivers/gpu/drm/bridge/ite-it66121.c > +++ b/drivers/gpu/drm/bridge/ite-it66121.c > @@ -313,6 +313,9 @@ struct it66121_ctx { > bool auto_cts; > } audio; > const struct it66121_chip_info *info; > + u16 vender_id; > + u16 device_id; > + u8 revision; > >>> There is no need to store them, they are not used by the driver anywhere. > >>> > }; > > static inline struct it66121_ctx *bridge_to_it66121(struct drm_bridge > *bridge) > @@ -399,6 +402,30 @@ static void it66121_hw_reset(struct it66121_ctx > *ctx) > gpiod_set_value(ctx->gpio_reset, 0); > } > > +static int it66121_read_chip_id(struct it66121_ctx *ctx, bool verbose) > +{ > + u8 id[4]; > + int ret; > + > + ret = regmap_bulk_read(ctx->regmap, IT66121_VENDOR_ID0_REG, id, > 4); > + if (ret < 0) { > + dev_err(ctx->dev, "Failed to read chip ID: %d\n", ret); > + return ret; > + } > + > + ctx->vender_id = (u16)id[1] << 8 | id[0]; > + ctx->device_id = ((u16)(id[3] & IT66121_DEVICE_ID1_MASK) << 8 | > id[2]); > + /* Revision is shared with DEVICE_ID1 */ > + ctx->revision = FIELD_GET(IT66121_REVISION_MASK, id[3]); > + > + if (verbose) { > + dev_info(ctx->dev, "Found ITE66121: 0x%x%x, revision: > %u\n", > +ctx->vender_id, ctx->device_id, ctx->revision); > + } > + > + return 0; > +} > + > static inline int it66121_preamble_ddc(struct it66121_ctx *ctx) > { > return regmap_write(ctx->regmap, IT66121_MASTER_SEL_REG, > IT66121_MASTER_SEL_HOST); > @@ -1561,7 +1588,6 @@ static const char * const it66121_supplies[] = { > > static int it66121_probe(struct i2c_client *client) > { > - u32 revision_id, vendor_ids[2] = { 0 }, device_ids[2] = { 0 }; > int ret; > struct it66121_ctx *ctx; > struct device *dev = >dev; > @@ -1603,19 +1629,13 @@ static int it66121_probe(struct i2c_client > *client) > if (IS_ERR(ctx->regmap)) > return PTR_ERR(ctx->regmap); > > - regmap_read(ctx->regmap, IT66121_VENDOR_ID0_REG, _ids[0]); > - regmap_read(ctx->regmap, IT66121_VENDOR_ID1_REG, _ids[1]); > - regmap_read(ctx->regmap, IT66121_DEVICE_ID0_REG, _ids[0]); > - regmap_read(ctx->regmap, IT66121_DEVICE_ID1_REG, _ids[1]); > - > - /* Revision is shared with DEVICE_ID1 */ > - revision_id = FIELD_GET(IT66121_REVISION_MASK, device_ids[1]); > - device_ids[1] &= IT66121_DEVICE_ID1_MASK; > + ret = it66121_read_chip_id(ctx, false); > + if (ret) > + return ret; > > - if ((vendor_ids[1] << 8 | vendor_ids[0]) != ctx->info->vid || > - (device_ids[1] << 8 | device_ids[0]) != ctx->info->pid) { > + if (ctx->vender_id != ctx->info->vid || > + ctx->device_id != ctx->info->pid) > >> Q: There is no need to store them, they are not used by the driver > >> anywhere. > >> > >> A: Here it is used, it is also used by the 0007-patch to get the > >> entity(instance)-specific data. > > And the patch 7 will be changed once you have proper i2c client struct > > registered. > > > >> > >> Since it6610 was introduced, this is used for chip identifying. > >> It can also be used with in debugfs context, to show who I am. > > I'd say, there is little point in whoami debugfs files. Debugfs is for > > the useful information. > > Sinceit6610 was introduced, how do you know what the device it66121 driver is > binding? Printing model specific information is common practice for a > large driver. Especially if you can only able to debug remotely where > only
Re: [PATCH v4 00/20] remove I2C_CLASS_DDC support
On 23.11.2023 07:56, Thomas Zimmermann wrote: > Hi > > Am 20.11.23 um 22:46 schrieb Heiner Kallweit: >> After removal of the legacy EEPROM driver and I2C_CLASS_DDC support in >> olpc_dcon there's no i2c client driver left supporting I2C_CLASS_DDC. >> Class-based device auto-detection is a legacy mechanism and shouldn't >> be used in new code. So we can remove this class completely now. >> >> Preferably this series should be applied via the i2c tree. >> >> v2: >> - change tag in commit subject of patch 03 >> - add ack tags >> v3: >> - fix a compile error in patch 5 >> v4: >> - more ack and review tags >> >> Signed-off-by: Heiner Kallweit > > Acked-by: Thomas Zimmermann > > for the patches that don't already have my r-b. > This refers to which patches of the series? Patches 8, 16, 18 are the remaining ones w/o A-b or R-b. > Best regards > Thomas > Thanks, Heiner >> >> --- >> >> drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c | 1 - >> drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 - >> drivers/gpu/drm/ast/ast_i2c.c | 1 - >> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 - >> drivers/gpu/drm/display/drm_dp_helper.c | 1 - >> drivers/gpu/drm/display/drm_dp_mst_topology.c | 1 - >> drivers/gpu/drm/gma500/cdv_intel_dp.c | 1 - >> drivers/gpu/drm/gma500/intel_gmbus.c | 1 - >> drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 1 - >> drivers/gpu/drm/gma500/psb_intel_sdvo.c | 1 - >> drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c | 1 - >> drivers/gpu/drm/i915/display/intel_gmbus.c | 1 - >> drivers/gpu/drm/i915/display/intel_sdvo.c | 1 - >> drivers/gpu/drm/loongson/lsdc_i2c.c | 1 - >> drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c | 1 - >> drivers/gpu/drm/mgag200/mgag200_i2c.c | 1 - >> drivers/gpu/drm/msm/hdmi/hdmi_i2c.c | 1 - >> drivers/gpu/drm/radeon/radeon_i2c.c | 1 - >> drivers/gpu/drm/rockchip/inno_hdmi.c | 1 - >> drivers/gpu/drm/rockchip/rk3066_hdmi.c | 1 - >> drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c | 1 - >> drivers/video/fbdev/core/fb_ddc.c | 1 - >> drivers/video/fbdev/cyber2000fb.c | 1 - >> drivers/video/fbdev/i740fb.c | 1 - >> drivers/video/fbdev/intelfb/intelfb_i2c.c | 15 +-- >> drivers/video/fbdev/matrox/i2c-matroxfb.c | 12 >> drivers/video/fbdev/s3fb.c | 1 - >> drivers/video/fbdev/tdfxfb.c | 1 - >> drivers/video/fbdev/tridentfb.c | 1 - >> drivers/video/fbdev/via/via_i2c.c | 1 - >> include/linux/i2c.h | 1 - >> 31 files changed, 9 insertions(+), 47 deletions(-) >
[PATCH v5 3/5] mm/gup: Introduce pin_user_pages_fd() for pinning shmem/hugetlbfs file pages (v5)
For drivers that would like to longterm-pin the pages associated with a file, the pin_user_pages_fd() API provides an option to not only pin the pages via FOLL_PIN but also to check and migrate them if they reside in movable zone or CMA block. This API currently works with files that belong to either shmem or hugetlbfs. Files belonging to other filesystems are rejected for now. The pages need to be located first before pinning them via FOLL_PIN. If they are found in the page cache, they can be immediately pinned. Otherwise, they need to be allocated using the filesystem specific APIs and then pinned. v2: - Drop gup_flags and improve comments and commit message (David) - Allocate a page if we cannot find in page cache for the hugetlbfs case as well (David) - Don't unpin pages if there is a migration related failure (David) - Drop the unnecessary nr_pages <= 0 check (Jason) - Have the caller of the API pass in file * instead of fd (Jason) v3: (David) - Enclose the huge page allocation code with #ifdef CONFIG_HUGETLB_PAGE (Build error reported by kernel test robot ) - Don't forget memalloc_pin_restore() on non-migration related errors - Improve the readability of the cleanup code associated with non-migration related errors - Augment the comments by describing FOLL_LONGTERM like behavior - Include the R-b tag from Jason v4: - Remove the local variable "page" and instead use 3 return statements in alloc_file_page() (David) - Add the R-b tag from David v5: (David) - For hugetlb case, ensure that we only obtain head pages from the mapping by using __filemap_get_folio() instead of find_get_page_flags() - Handle -EEXIST when two or more potential users try to simultaneously add a huge page to the mapping by forcing them to retry on failure Cc: David Hildenbrand Cc: Daniel Vetter Cc: Mike Kravetz Cc: Hugh Dickins Cc: Peter Xu Cc: Gerd Hoffmann Cc: Dongwon Kim Cc: Junxiao Chang Suggested-by: Jason Gunthorpe Reviewed-by: Jason Gunthorpe (v2) Reviewed-by: David Hildenbrand (v3) Signed-off-by: Vivek Kasireddy --- include/linux/mm.h | 2 + mm/gup.c | 114 + 2 files changed, 116 insertions(+) diff --git a/include/linux/mm.h b/include/linux/mm.h index 418d26608ece..1b675fa35059 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2472,6 +2472,8 @@ long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages, struct page **pages, unsigned int gup_flags); long pin_user_pages_unlocked(unsigned long start, unsigned long nr_pages, struct page **pages, unsigned int gup_flags); +long pin_user_pages_fd(struct file *file, pgoff_t start, + unsigned long nr_pages, struct page **pages); int get_user_pages_fast(unsigned long start, int nr_pages, unsigned int gup_flags, struct page **pages); diff --git a/mm/gup.c b/mm/gup.c index 231711efa390..ab1056b3e75b 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -3410,3 +3410,117 @@ long pin_user_pages_unlocked(unsigned long start, unsigned long nr_pages, , gup_flags); } EXPORT_SYMBOL(pin_user_pages_unlocked); + +static struct page *alloc_file_page(struct file *file, pgoff_t idx) +{ +#ifdef CONFIG_HUGETLB_PAGE + struct folio *folio; + int err; + + if (is_file_hugepages(file)) { + folio = alloc_hugetlb_folio_nodemask(hstate_file(file), +NUMA_NO_NODE, +NULL, +GFP_USER); + if (folio && folio_try_get(folio)) { + err = hugetlb_add_to_page_cache(folio, + file->f_mapping, + idx); + if (err) { + folio_put(folio); + free_huge_folio(folio); + return ERR_PTR(err); + } + return >page; + } + return ERR_PTR(-ENOMEM); + } +#endif + return shmem_read_mapping_page(file->f_mapping, idx); +} + +/** + * pin_user_pages_fd() - pin user pages associated with a file + * @file: the file whose pages are to be pinned + * @start: starting file offset + * @nr_pages: number of pages from start to pin + * @pages: array that receives pointers to the pages pinned. + * Should be at-least nr_pages long. + * + * Attempt to pin pages associated with a file that belongs to either shmem + * or hugetlb. The pages are either found in the page cache or allocated if + * necessary. Once the pages are located, they are all pinned via FOLL_PIN. + * And, these pinned pages need to be released either using unpin_user_pages() + * or unpin_user_page(). + * + * It must
[PATCH v5 4/5] udmabuf: Pin the pages using pin_user_pages_fd() API (v3)
Using pin_user_pages_fd() will ensure that the pages are pinned correctly using FOLL_PIN. And, this also ensures that we don't accidentally break features such as memory hotunplug as it would not allow pinning pages in the movable zone. Using this new API also simplifies the code as we no longer have to deal with extracting individual pages from their mappings. As a result, we can drop some of the local variables such as page, hpage, mapping, etc. v2: - Adjust to the change in signature of pin_user_pages_fd() by passing in file * instead of fd. v3: - Limit the changes in this patch only to those that are required for using pin_user_pages_fd() - Slightly improve the commit message Cc: David Hildenbrand Cc: Daniel Vetter Cc: Mike Kravetz Cc: Hugh Dickins Cc: Peter Xu Cc: Jason Gunthorpe Cc: Gerd Hoffmann Cc: Dongwon Kim Cc: Junxiao Chang Signed-off-by: Vivek Kasireddy --- drivers/dma-buf/udmabuf.c | 61 ++- 1 file changed, 22 insertions(+), 39 deletions(-) diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index d77d119f4048..883bd97e4076 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -156,7 +156,8 @@ static void release_udmabuf(struct dma_buf *buf) put_sg_table(dev, ubuf->sg, DMA_BIDIRECTIONAL); for (pg = 0; pg < ubuf->pagecount; pg++) - put_page(ubuf->pages[pg]); + unpin_user_page(ubuf->pages[pg]); + kfree(ubuf->subpgoff); kfree(ubuf->pages); kfree(ubuf); @@ -217,15 +218,13 @@ static long udmabuf_create(struct miscdevice *device, { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); struct file *memfd = NULL; - struct address_space *mapping = NULL; struct udmabuf *ubuf; struct dma_buf *buf; - pgoff_t pgoff, pgcnt, pgidx, pgbuf = 0, pglimit; - struct page *page, *hpage = NULL; - struct folio *folio; + pgoff_t pgcnt, pgbuf = 0, pglimit, nr_pages; pgoff_t mapidx, chunkoff, maxchunks; struct hstate *hpstate; - int seals, ret = -EINVAL; + long ret = -EINVAL; + int seals; u32 i, flags; ubuf = kzalloc(sizeof(*ubuf), GFP_KERNEL); @@ -259,8 +258,7 @@ static long udmabuf_create(struct miscdevice *device, memfd = fget(list[i].memfd); if (!memfd) goto err; - mapping = memfd->f_mapping; - if (!shmem_mapping(mapping) && !is_file_hugepages(memfd)) + if (!shmem_file(memfd) && !is_file_hugepages(memfd)) goto err; seals = memfd_fcntl(memfd, F_GET_SEALS, 0); if (seals == -EINVAL) @@ -269,7 +267,7 @@ static long udmabuf_create(struct miscdevice *device, if ((seals & SEALS_WANTED) != SEALS_WANTED || (seals & SEALS_DENIED) != 0) goto err; - pgoff = list[i].offset >> PAGE_SHIFT; + mapidx = list[i].offset >> PAGE_SHIFT; pgcnt = list[i].size >> PAGE_SHIFT; if (is_file_hugepages(memfd)) { if (!ubuf->subpgoff) { @@ -287,42 +285,26 @@ static long udmabuf_create(struct miscdevice *device, ~huge_page_mask(hpstate)) >> PAGE_SHIFT; maxchunks = huge_page_size(hpstate) >> PAGE_SHIFT; } - for (pgidx = 0; pgidx < pgcnt; pgidx++) { + + do { + nr_pages = shmem_file(memfd) ? pgcnt : 1; + ret = pin_user_pages_fd(memfd, mapidx, nr_pages, + ubuf->pages + pgbuf); + if (ret < 0) + goto err; + if (is_file_hugepages(memfd)) { - if (!hpage) { - folio = __filemap_get_folio(mapping, mapidx, - FGP_ACCESSED, 0); - hpage = IS_ERR(folio) ? NULL: >page; - if (!hpage) { - ret = -EINVAL; - goto err; - } - } - get_page(hpage); - ubuf->pages[pgbuf] = hpage; - ubuf->subpgoff[pgbuf++] = chunkoff << PAGE_SHIFT; + ubuf->subpgoff[pgbuf] = chunkoff << PAGE_SHIFT; if (++chunkoff == maxchunks) { - put_page(hpage); - hpage = NULL; chunkoff = 0; mapidx++;
[PATCH v5 2/5] udmabuf: Add back support for mapping hugetlb pages (v4)
A user or admin can configure a VMM (Qemu) Guest's memory to be backed by hugetlb pages for various reasons. However, a Guest OS would still allocate (and pin) buffers that are backed by regular 4k sized pages. In order to map these buffers and create dma-bufs for them on the Host, we first need to find the hugetlb pages where the buffer allocations are located and then determine the offsets of individual chunks (within those pages) and use this information to eventually populate a scatterlist. Testcase: default_hugepagesz=2M hugepagesz=2M hugepages=2500 options were passed to the Host kernel and Qemu was launched with these relevant options: qemu-system-x86_64 -m 4096m -device virtio-gpu-pci,max_outputs=1,blob=true,xres=1920,yres=1080 -display gtk,gl=on -object memory-backend-memfd,hugetlb=on,id=mem1,size=4096M -machine memory-backend=mem1 Replacing -display gtk,gl=on with -display gtk,gl=off above would exercise the mmap handler. v2: Updated get_sg_table() to manually populate the scatterlist for both huge page and non-huge-page cases. v3: s/offsets/subpgoff/g s/hpoff/mapidx/g v4: Replaced find_get_page_flags() with __filemap_get_folio() to ensure that we only obtain head pages from the mapping Cc: David Hildenbrand Cc: Daniel Vetter Cc: Mike Kravetz Cc: Hugh Dickins Cc: Peter Xu Cc: Jason Gunthorpe Cc: Gerd Hoffmann Cc: Dongwon Kim Cc: Junxiao Chang Acked-by: Mike Kravetz (v2) Signed-off-by: Vivek Kasireddy --- drivers/dma-buf/udmabuf.c | 87 +-- 1 file changed, 74 insertions(+), 13 deletions(-) diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index 820c993c8659..d77d119f4048 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ struct udmabuf { struct page **pages; struct sg_table *sg; struct miscdevice *device; + pgoff_t *subpgoff; }; static vm_fault_t udmabuf_vm_fault(struct vm_fault *vmf) @@ -41,6 +43,10 @@ static vm_fault_t udmabuf_vm_fault(struct vm_fault *vmf) return VM_FAULT_SIGBUS; pfn = page_to_pfn(ubuf->pages[pgoff]); + if (ubuf->subpgoff) { + pfn += ubuf->subpgoff[pgoff] >> PAGE_SHIFT; + } + return vmf_insert_pfn(vma, vmf->address, pfn); } @@ -90,23 +96,31 @@ static struct sg_table *get_sg_table(struct device *dev, struct dma_buf *buf, { struct udmabuf *ubuf = buf->priv; struct sg_table *sg; + struct scatterlist *sgl; + pgoff_t offset; + unsigned long i = 0; int ret; sg = kzalloc(sizeof(*sg), GFP_KERNEL); if (!sg) return ERR_PTR(-ENOMEM); - ret = sg_alloc_table_from_pages(sg, ubuf->pages, ubuf->pagecount, - 0, ubuf->pagecount << PAGE_SHIFT, - GFP_KERNEL); + + ret = sg_alloc_table(sg, ubuf->pagecount, GFP_KERNEL); if (ret < 0) - goto err; + goto err_alloc; + + for_each_sg(sg->sgl, sgl, ubuf->pagecount, i) { + offset = ubuf->subpgoff ? ubuf->subpgoff[i] : 0; + sg_set_page(sgl, ubuf->pages[i], PAGE_SIZE, offset); + } ret = dma_map_sgtable(dev, sg, direction, 0); if (ret < 0) - goto err; + goto err_map; return sg; -err: +err_map: sg_free_table(sg); +err_alloc: kfree(sg); return ERR_PTR(ret); } @@ -143,6 +157,7 @@ static void release_udmabuf(struct dma_buf *buf) for (pg = 0; pg < ubuf->pagecount; pg++) put_page(ubuf->pages[pg]); + kfree(ubuf->subpgoff); kfree(ubuf->pages); kfree(ubuf); } @@ -206,7 +221,10 @@ static long udmabuf_create(struct miscdevice *device, struct udmabuf *ubuf; struct dma_buf *buf; pgoff_t pgoff, pgcnt, pgidx, pgbuf = 0, pglimit; - struct page *page; + struct page *page, *hpage = NULL; + struct folio *folio; + pgoff_t mapidx, chunkoff, maxchunks; + struct hstate *hpstate; int seals, ret = -EINVAL; u32 i, flags; @@ -242,7 +260,7 @@ static long udmabuf_create(struct miscdevice *device, if (!memfd) goto err; mapping = memfd->f_mapping; - if (!shmem_mapping(mapping)) + if (!shmem_mapping(mapping) && !is_file_hugepages(memfd)) goto err; seals = memfd_fcntl(memfd, F_GET_SEALS, 0); if (seals == -EINVAL) @@ -253,16 +271,58 @@ static long udmabuf_create(struct miscdevice *device, goto err; pgoff = list[i].offset >> PAGE_SHIFT; pgcnt = list[i].size >> PAGE_SHIFT; + if (is_file_hugepages(memfd)) { + if
[PATCH v5 1/5] udmabuf: Use vmf_insert_pfn and VM_PFNMAP for handling mmap
Add VM_PFNMAP to vm_flags in the mmap handler to ensure that the mappings would be managed without using struct page. And, in the vm_fault handler, use vmf_insert_pfn to share the page's pfn to userspace instead of directly sharing the page (via struct page *). Cc: David Hildenbrand Cc: Daniel Vetter Cc: Mike Kravetz Cc: Hugh Dickins Cc: Peter Xu Cc: Jason Gunthorpe Cc: Gerd Hoffmann Cc: Dongwon Kim Cc: Junxiao Chang Suggested-by: David Hildenbrand Acked-by: David Hildenbrand Signed-off-by: Vivek Kasireddy --- drivers/dma-buf/udmabuf.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index c40645999648..820c993c8659 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -35,12 +35,13 @@ static vm_fault_t udmabuf_vm_fault(struct vm_fault *vmf) struct vm_area_struct *vma = vmf->vma; struct udmabuf *ubuf = vma->vm_private_data; pgoff_t pgoff = vmf->pgoff; + unsigned long pfn; if (pgoff >= ubuf->pagecount) return VM_FAULT_SIGBUS; - vmf->page = ubuf->pages[pgoff]; - get_page(vmf->page); - return 0; + + pfn = page_to_pfn(ubuf->pages[pgoff]); + return vmf_insert_pfn(vma, vmf->address, pfn); } static const struct vm_operations_struct udmabuf_vm_ops = { @@ -56,6 +57,7 @@ static int mmap_udmabuf(struct dma_buf *buf, struct vm_area_struct *vma) vma->vm_ops = _vm_ops; vma->vm_private_data = ubuf; + vm_flags_set(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP); return 0; } -- 2.39.2
[PATCH v5 5/5] selftests/dma-buf/udmabuf: Add tests to verify data after page migration
Since the memfd pages associated with a udmabuf may be migrated as part of udmabuf create, we need to verify the data coherency after successful migration. The new tests added in this patch try to do just that using 4k sized pages and also 2 MB sized huge pages for the memfd. Successful completion of the tests would mean that there is no disconnect between the memfd pages and the ones associated with a udmabuf. And, these tests can also be augmented in the future to test newer udmabuf features (such as handling memfd hole punch). Cc: Shuah Khan Cc: David Hildenbrand Cc: Daniel Vetter Cc: Mike Kravetz Cc: Hugh Dickins Cc: Peter Xu Cc: Jason Gunthorpe Cc: Gerd Hoffmann Cc: Dongwon Kim Cc: Junxiao Chang Based-on-patch-by: Mike Kravetz Signed-off-by: Vivek Kasireddy --- .../selftests/drivers/dma-buf/udmabuf.c | 151 +- 1 file changed, 147 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/drivers/dma-buf/udmabuf.c b/tools/testing/selftests/drivers/dma-buf/udmabuf.c index c812080e304e..d76c813fe652 100644 --- a/tools/testing/selftests/drivers/dma-buf/udmabuf.c +++ b/tools/testing/selftests/drivers/dma-buf/udmabuf.c @@ -9,26 +9,132 @@ #include #include #include +#include #include #include +#include #include #include #define TEST_PREFIX"drivers/dma-buf/udmabuf" #define NUM_PAGES 4 +#define NUM_ENTRIES 4 +#define MEMFD_SIZE 1024 /* in pages */ -static int memfd_create(const char *name, unsigned int flags) +static unsigned int page_size; + +static int create_memfd_with_seals(off64_t size, bool hpage) +{ + int memfd, ret; + unsigned int flags = MFD_ALLOW_SEALING; + + if (hpage) + flags |= MFD_HUGETLB; + + memfd = memfd_create("udmabuf-test", flags); + if (memfd < 0) { + printf("%s: [skip,no-memfd]\n", TEST_PREFIX); + exit(77); + } + + ret = fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK); + if (ret < 0) { + printf("%s: [skip,fcntl-add-seals]\n", TEST_PREFIX); + exit(77); + } + + ret = ftruncate(memfd, size); + if (ret == -1) { + printf("%s: [FAIL,memfd-truncate]\n", TEST_PREFIX); + exit(1); + } + + return memfd; +} + +static int create_udmabuf_list(int devfd, int memfd, off64_t memfd_size) +{ + struct udmabuf_create_list *list; + int ubuf_fd, i; + + list = malloc(sizeof(struct udmabuf_create_list) + + sizeof(struct udmabuf_create_item) * NUM_ENTRIES); + if (!list) { + printf("%s: [FAIL, udmabuf-malloc]\n", TEST_PREFIX); + exit(1); + } + + for (i = 0; i < NUM_ENTRIES; i++) { + list->list[i].memfd = memfd; + list->list[i].offset = i * (memfd_size / NUM_ENTRIES); + list->list[i].size = getpagesize() * NUM_PAGES; + } + + list->count = NUM_ENTRIES; + list->flags = UDMABUF_FLAGS_CLOEXEC; + ubuf_fd = ioctl(devfd, UDMABUF_CREATE_LIST, list); + free(list); + if (ubuf_fd < 0) { + printf("%s: [FAIL, udmabuf-create]\n", TEST_PREFIX); + exit(1); + } + + return ubuf_fd; +} + +static void write_to_memfd(void *addr, off64_t size, char chr) +{ + int i; + + for (i = 0; i < size / page_size; i++) { + *((char *)addr + (i * page_size)) = chr; + } +} + +static void *mmap_fd(int fd, off64_t size) { - return syscall(__NR_memfd_create, name, flags); + void *addr; + + addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + printf("%s: ubuf_fd mmap fail\n", TEST_PREFIX); + exit(1); + } + + return addr; +} + +static int compare_chunks(void *addr1, void *addr2, off64_t memfd_size) +{ + off64_t off; + int i = 0, j, k = 0, ret = 0; + char char1, char2; + + while (i < NUM_ENTRIES) { + off = i * (memfd_size / NUM_ENTRIES); + for (j = 0; j < NUM_PAGES; j++, k++) { + char1 = *((char *)addr1 + off + (j * getpagesize())); + char2 = *((char *)addr2 + (k * getpagesize())); + if (char1 != char2) { + ret = -1; + goto err; + } + } + i++; + } +err: + munmap(addr1, memfd_size); + munmap(addr2, NUM_ENTRIES * NUM_PAGES * getpagesize()); + return ret; } int main(int argc, char *argv[]) { struct udmabuf_create create; int devfd, memfd, buf, ret; - off_t size; - void *mem; + off64_t size; + void *addr1, *addr2; devfd = open("/dev/udmabuf", O_RDWR); if (devfd < 0) { @@ -90,6 +196,9 @@ int main(int argc, char *argv[]) } /* should work */ +
[PATCH v5 0/5] mm/gup: Introduce pin_user_pages_fd() for pinning shmem/hugetlbfs file pages (v5)
The first two patches were previously reviewed but not yet merged. These ones need to be merged first as the fourth patch depends on the changes introduced in them and they also fix bugs seen in very specific scenarios (running Qemu with hugetlb=on, blob=true and rebooting guest VM). The third patch introduces pin_user_pages_fd() API and the fourth patch shows how the udmabuf driver can make use of it to longterm-pin the the pages. The last patch adds two new udmabuf selftests to verify data coherency after potential page migration. v2: - Updated the first patch to include review feedback from David and Jason. The main change in this series is the allocation of page in the case of hugetlbfs if it is not found in the page cache. v3: - Made changes to include review feedback from David to improve the comments and readability of code - Enclosed the hugepage alloc code with #ifdef CONFIG_HUGETLB_PAGE v4: - Augmented the commit message of the udmabuf patch that uses pin_user_pages_fd() - Added previously reviewed but unmerged udmabuf patches to this series v5: - Updated the patch that adds pin_user_pages_fd() to include feedback from David to handle simultaneous users trying to add a huge page to the mapping - Replaced find_get_page_flags() with __filemap_get_folio() in the second and third patches to ensure that we only obtain head pages from the mapping Cc: David Hildenbrand Cc: Daniel Vetter Cc: Mike Kravetz Cc: Hugh Dickins Cc: Peter Xu Cc: Jason Gunthorpe Cc: Gerd Hoffmann Cc: Dongwon Kim Cc: Junxiao Chang Vivek Kasireddy (5): udmabuf: Use vmf_insert_pfn and VM_PFNMAP for handling mmap udmabuf: Add back support for mapping hugetlb pages (v4) mm/gup: Introduce pin_user_pages_fd() for pinning shmem/hugetlbfs file pages (v5) udmabuf: Pin the pages using pin_user_pages_fd() API (v3) selftests/dma-buf/udmabuf: Add tests to verify data after page migration drivers/dma-buf/udmabuf.c | 96 --- include/linux/mm.h| 2 + mm/gup.c | 114 + .../selftests/drivers/dma-buf/udmabuf.c | 151 +- 4 files changed, 334 insertions(+), 29 deletions(-) -- 2.39.2
RE: [PATCH] drm/i915/psr: Fix unsigned expression compared with zero
> -Original Message- > From: Jani Nikula > Sent: Wednesday, November 22, 2023 11:15 AM > To: Jiapeng Chong > Cc: joonas.lahti...@linux.intel.com; Vivi, Rodrigo ; > tvrtko.ursu...@linux.intel.com; airl...@gmail.com; > dan...@ffwll.ch; intel-...@lists.freedesktop.org; > dri-devel@lists.freedesktop.org; linux-ker...@vger.kernel.org; Jiapeng Chong > ; Abaci Robot ; > Kahola, Mika > Subject: Re: [PATCH] drm/i915/psr: Fix unsigned expression compared with zero > > On Wed, 22 Nov 2023, Jiapeng Chong wrote: > > The entry_setup_frames is defined as u8 type, else(entry_setup_frames > > < 0) is invalid. At the same time, the return value of function > > intel_psr_entry_setup_frames is also of type int. so modified its type > > to int. > > > > ./drivers/gpu/drm/i915/display/intel_psr.c:1336:5-23: WARNING: Unsigned > > expression compared with zero: > entry_setup_frames >= 0. > > > > Reported-by: Abaci Robot > > Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=7610 > > Signed-off-by: Jiapeng Chong > > There's already a patch. Mika, please follow up with it. > > https://patchwork.freedesktop.org/patch/msgid/20231116090512.480373-1-mika.kah...@intel.com The patch is now merged. Thanks for the review. -Mika- > > > --- > > drivers/gpu/drm/i915/display/intel_psr.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/i915/display/intel_psr.c > > b/drivers/gpu/drm/i915/display/intel_psr.c > > index 8d180132a74b..204da50e3f28 100644 > > --- a/drivers/gpu/drm/i915/display/intel_psr.c > > +++ b/drivers/gpu/drm/i915/display/intel_psr.c > > @@ -1319,7 +1319,7 @@ static bool _psr_compute_config(struct intel_dp > > *intel_dp, { > > struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); > > const struct drm_display_mode *adjusted_mode = > > _state->hw.adjusted_mode; > > - u8 entry_setup_frames; > > + int entry_setup_frames; > > > > /* > > * Current PSR panels don't work reliably with VRR enabled > > -- > Jani Nikula, Intel
Re: [PATCH v4 00/20] remove I2C_CLASS_DDC support
Hi Am 20.11.23 um 22:46 schrieb Heiner Kallweit: After removal of the legacy EEPROM driver and I2C_CLASS_DDC support in olpc_dcon there's no i2c client driver left supporting I2C_CLASS_DDC. Class-based device auto-detection is a legacy mechanism and shouldn't be used in new code. So we can remove this class completely now. Preferably this series should be applied via the i2c tree. v2: - change tag in commit subject of patch 03 - add ack tags v3: - fix a compile error in patch 5 v4: - more ack and review tags Signed-off-by: Heiner Kallweit Acked-by: Thomas Zimmermann for the patches that don't already have my r-b. Best regards Thomas --- drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c |1 - drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |1 - drivers/gpu/drm/ast/ast_i2c.c |1 - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |1 - drivers/gpu/drm/display/drm_dp_helper.c |1 - drivers/gpu/drm/display/drm_dp_mst_topology.c |1 - drivers/gpu/drm/gma500/cdv_intel_dp.c |1 - drivers/gpu/drm/gma500/intel_gmbus.c |1 - drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c|1 - drivers/gpu/drm/gma500/psb_intel_sdvo.c |1 - drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c |1 - drivers/gpu/drm/i915/display/intel_gmbus.c|1 - drivers/gpu/drm/i915/display/intel_sdvo.c |1 - drivers/gpu/drm/loongson/lsdc_i2c.c |1 - drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c |1 - drivers/gpu/drm/mgag200/mgag200_i2c.c |1 - drivers/gpu/drm/msm/hdmi/hdmi_i2c.c |1 - drivers/gpu/drm/radeon/radeon_i2c.c |1 - drivers/gpu/drm/rockchip/inno_hdmi.c |1 - drivers/gpu/drm/rockchip/rk3066_hdmi.c|1 - drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c|1 - drivers/video/fbdev/core/fb_ddc.c |1 - drivers/video/fbdev/cyber2000fb.c |1 - drivers/video/fbdev/i740fb.c |1 - drivers/video/fbdev/intelfb/intelfb_i2c.c | 15 +-- drivers/video/fbdev/matrox/i2c-matroxfb.c | 12 drivers/video/fbdev/s3fb.c|1 - drivers/video/fbdev/tdfxfb.c |1 - drivers/video/fbdev/tridentfb.c |1 - drivers/video/fbdev/via/via_i2c.c |1 - include/linux/i2c.h |1 - 31 files changed, 9 insertions(+), 47 deletions(-) -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Frankenstrasse 146, 90461 Nuernberg, Germany GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman HRB 36809 (AG Nuernberg) OpenPGP_signature.asc Description: OpenPGP digital signature
Re: [PATCH 5/8] drm/bridge: it66121: Add a helper function to read chip id
Hi, On 2023/11/16 21:00, Dmitry Baryshkov wrote: On Thu, 16 Nov 2023 at 14:18, Sui Jingfeng wrote: Hi, On 2023/11/15 00:06, Dmitry Baryshkov wrote: On Tue, 14 Nov 2023 at 17:09, Sui Jingfeng wrote: From: Sui Jingfeng Read the required chip id data back by calling regmap_bulk_read() once, reduce the number of local variables needed in it66121_probe() function. And store its values into struct it66121_ctx, as it will be used latter. Signed-off-by: Sui Jingfeng --- drivers/gpu/drm/bridge/ite-it66121.c | 47 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c index 7e473beefc79..f36d05331f25 100644 --- a/drivers/gpu/drm/bridge/ite-it66121.c +++ b/drivers/gpu/drm/bridge/ite-it66121.c @@ -313,6 +313,9 @@ struct it66121_ctx { bool auto_cts; } audio; const struct it66121_chip_info *info; + u16 vender_id; + u16 device_id; + u8 revision; There is no need to store them, they are not used by the driver anywhere. }; static inline struct it66121_ctx *bridge_to_it66121(struct drm_bridge *bridge) @@ -399,6 +402,30 @@ static void it66121_hw_reset(struct it66121_ctx *ctx) gpiod_set_value(ctx->gpio_reset, 0); } +static int it66121_read_chip_id(struct it66121_ctx *ctx, bool verbose) +{ + u8 id[4]; + int ret; + + ret = regmap_bulk_read(ctx->regmap, IT66121_VENDOR_ID0_REG, id, 4); + if (ret < 0) { + dev_err(ctx->dev, "Failed to read chip ID: %d\n", ret); + return ret; + } + + ctx->vender_id = (u16)id[1] << 8 | id[0]; + ctx->device_id = ((u16)(id[3] & IT66121_DEVICE_ID1_MASK) << 8 | id[2]); + /* Revision is shared with DEVICE_ID1 */ + ctx->revision = FIELD_GET(IT66121_REVISION_MASK, id[3]); + + if (verbose) { + dev_info(ctx->dev, "Found ITE66121: 0x%x%x, revision: %u\n", +ctx->vender_id, ctx->device_id, ctx->revision); + } + + return 0; +} + static inline int it66121_preamble_ddc(struct it66121_ctx *ctx) { return regmap_write(ctx->regmap, IT66121_MASTER_SEL_REG, IT66121_MASTER_SEL_HOST); @@ -1561,7 +1588,6 @@ static const char * const it66121_supplies[] = { static int it66121_probe(struct i2c_client *client) { - u32 revision_id, vendor_ids[2] = { 0 }, device_ids[2] = { 0 }; int ret; struct it66121_ctx *ctx; struct device *dev = >dev; @@ -1603,19 +1629,13 @@ static int it66121_probe(struct i2c_client *client) if (IS_ERR(ctx->regmap)) return PTR_ERR(ctx->regmap); - regmap_read(ctx->regmap, IT66121_VENDOR_ID0_REG, _ids[0]); - regmap_read(ctx->regmap, IT66121_VENDOR_ID1_REG, _ids[1]); - regmap_read(ctx->regmap, IT66121_DEVICE_ID0_REG, _ids[0]); - regmap_read(ctx->regmap, IT66121_DEVICE_ID1_REG, _ids[1]); - - /* Revision is shared with DEVICE_ID1 */ - revision_id = FIELD_GET(IT66121_REVISION_MASK, device_ids[1]); - device_ids[1] &= IT66121_DEVICE_ID1_MASK; + ret = it66121_read_chip_id(ctx, false); + if (ret) + return ret; - if ((vendor_ids[1] << 8 | vendor_ids[0]) != ctx->info->vid || - (device_ids[1] << 8 | device_ids[0]) != ctx->info->pid) { + if (ctx->vender_id != ctx->info->vid || + ctx->device_id != ctx->info->pid) Q: There is no need to store them, they are not used by the driver anywhere. A: Here it is used, it is also used by the 0007-patch to get the entity(instance)-specific data. And the patch 7 will be changed once you have proper i2c client struct registered. Since it6610 was introduced, this is used for chip identifying. It can also be used with in debugfs context, to show who I am. I'd say, there is little point in whoami debugfs files. Debugfs is for the useful information. Sinceit6610 was introduced, how do you know what the device it66121 driver is binding? Printing model specific information is common practice for a large driver. Especially if you can only able to debug remotely where only a SSH is given. You could see debugfs of drm/etnaviv for a reference. It is common to testing a large driver running on 20+ machines with various hardware model. return -ENODEV; - } ctx->bridge.funcs = _bridge_funcs; ctx->bridge.of_node = dev->of_node; @@ -1633,7 +1653,8 @@ static int it66121_probe(struct i2c_client *client) drm_bridge_add(>bridge); - dev_info(dev, "IT66121 revision %d probed\n", revision_id); + dev_info(dev, "IT66121 probed, chip id: 0x%x:0x%x, revision: %u\n", +ctx->vender_id, ctx->device_id, ctx->revision); return 0; } -- 2.34.1
Re: [PATCH 4/8] drm/bridge: it66121: Add a helper function to get the next bridge
Hi, On 2023/11/15 00:05, Dmitry Baryshkov wrote: On Tue, 14 Nov 2023 at 17:09, Sui Jingfeng wrote: From: Sui Jingfeng Group the code lines(which with the same functional) into one dedicated function, which reduce the weight of it66121_probe() function. Just trivial cleanuo, no functional change. Signed-off-by: Sui Jingfeng --- drivers/gpu/drm/bridge/ite-it66121.c | 53 ++-- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c index 0f78737adc83..7e473beefc79 100644 --- a/drivers/gpu/drm/bridge/ite-it66121.c +++ b/drivers/gpu/drm/bridge/ite-it66121.c @@ -340,6 +340,37 @@ static int it66121_of_read_bus_width(struct device *dev, u32 *bus_width) return 0; } +static int it66121_of_get_next_bridge(struct device *dev, + struct drm_bridge **next_bridge) it already exists and it is called drm_of_find_panel_or_bridge(), could you please use it instead? That function is too fat and tangled, and should be untangled. it66121 can not connect with a panel, this is a prior knowledge and is known at compile time. So this prior knowledge shouldn't be dropped. +{ + struct device_node *np; + struct drm_bridge *bridge; + + np = of_graph_get_remote_node(dev->of_node, 1, -1); + if (!np) { + dev_err(dev, "The endpoint is unconnected\n"); + return -EINVAL; + } + + if (!of_device_is_available(np)) { + of_node_put(np); + dev_err(dev, "The remote device is disabled\n"); + return -ENODEV; + } + + bridge = of_drm_find_bridge(np); + of_node_put(np); + + if (!bridge) { + dev_dbg(dev, "Next bridge not found, deferring probe\n"); + return -EPROBE_DEFER; + } + + *next_bridge = bridge; + + return 0; +} + static const struct regmap_range_cfg it66121_regmap_banks[] = { { .name = "it66121", @@ -1531,7 +1562,6 @@ static const char * const it66121_supplies[] = { static int it66121_probe(struct i2c_client *client) { u32 revision_id, vendor_ids[2] = { 0 }, device_ids[2] = { 0 }; - struct device_node *ep; int ret; struct it66121_ctx *ctx; struct device *dev = >dev; @@ -1553,24 +1583,9 @@ static int it66121_probe(struct i2c_client *client) if (ret) return ret; - ep = of_graph_get_remote_node(dev->of_node, 1, -1); - if (!ep) { - dev_err(dev, "The endpoint is unconnected\n"); - return -EINVAL; - } - - if (!of_device_is_available(ep)) { - of_node_put(ep); - dev_err(dev, "The remote device is disabled\n"); - return -ENODEV; - } - - ctx->next_bridge = of_drm_find_bridge(ep); - of_node_put(ep); - if (!ctx->next_bridge) { - dev_dbg(dev, "Next bridge not found, deferring probe\n"); - return -EPROBE_DEFER; - } + ret = it66121_of_get_next_bridge(dev, >next_bridge); + if (ret) + return ret; i2c_set_clientdata(client, ctx); mutex_init(>lock); -- 2.34.1
[PATCH v2] drm/bridge: imx93-mipi-dsi: Fix a couple of building warnings
Fix a couple of building warnings on used uninitialized 'best_m' and 'best_n' local variables by initializing 'best_m' to zero and 'best_n' to UINT_MAX. This makes compiler happy only. No functional change. Fixes: ce62f8ea7e3f ("drm/bridge: imx: Add i.MX93 MIPI DSI support") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202311151746.f7u7dzbz-...@intel.com/ Signed-off-by: Liu Ying --- v2: * Initialize 'best_n' to UINT_MAX instead of zero. (Maxime) drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c index 3ff30ce80c5b..2347f8dd632f 100644 --- a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c @@ -226,8 +226,8 @@ dphy_pll_get_configure_from_opts(struct imx93_dsi *dsi, unsigned long fout; unsigned long best_fout = 0; unsigned int fvco_div; - unsigned int min_n, max_n, n, best_n; - unsigned long m, best_m; + unsigned int min_n, max_n, n, best_n = UINT_MAX; + unsigned long m, best_m = 0; unsigned long min_delta = ULONG_MAX; unsigned long delta; u64 tmp; -- 2.37.1
Re: [PATCH 8/8] drm/bridge: it66121: Allow link this driver as a lib
Hi, On 2023/11/16 19:19, Dmitry Baryshkov wrote: On Thu, 16 Nov 2023 at 12:13, Sui Jingfeng wrote: Hi, On 2023/11/16 17:30, Dmitry Baryshkov wrote: On Thu, 16 Nov 2023 at 11:14, Sui Jingfeng wrote: Hi, Thanks a lot for reviewing! On 2023/11/15 00:30, Dmitry Baryshkov wrote: On Tue, 14 Nov 2023 at 17:09, Sui Jingfeng wrote: From: Sui Jingfeng The it66121_create_bridge() and it66121_destroy_bridge() are added to export the core functionalities. Create a connector manually by using bridge connector helpers when link as a lib. Signed-off-by: Sui Jingfeng --- drivers/gpu/drm/bridge/ite-it66121.c | 134 +++ include/drm/bridge/ite-it66121.h | 17 2 files changed, 113 insertions(+), 38 deletions(-) create mode 100644 include/drm/bridge/ite-it66121.h diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c index 8971414a2a60..f5968b679c5d 100644 --- a/drivers/gpu/drm/bridge/ite-it66121.c +++ b/drivers/gpu/drm/bridge/ite-it66121.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -703,14 +704,32 @@ static int it66121_bridge_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { struct it66121_ctx *ctx = bridge_to_it66121(bridge); + struct drm_bridge *next_bridge = ctx->next_bridge; + struct drm_encoder *encoder = bridge->encoder; int ret; - if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) - return -EINVAL; + if (next_bridge) { + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { + WARN_ON(1); Why? At least use WARN() instead Originally I want to + flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR; + } + ret = drm_bridge_attach(encoder, next_bridge, bridge, flags); + if (ret) + return ret; + } else { + struct drm_connector *connector; - ret = drm_bridge_attach(bridge->encoder, ctx->next_bridge, bridge, flags); - if (ret) - return ret; + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) + WARN_ON(1); No. It is perfectly fine to create attach a bridge with no next_bridge and with the DRM_BRIDGE_ATTACH_NO_CONNECTOR flag. The document say when DRM_BRIDGE_ATTACH_NO_CONNECTOR flag is set the bridge shall not create a drm_connector. So I think if a display bridge driver don't have a next bridge attached (Currently, this is told by the DT), it says that this is a non-DT environment. On such a case, this display bridge driver(it66121.ko) should behavior like a *agent*. Because the upstream port of it66121 is the DVO port of the display controller, the downstream port of it66121 is the HDMI connector. it66121 is on the middle. So I think the it66121.ko should handle all of troubles on behalf of the display controller drivers. No. Don't make decisions for the other drivers. They might have different needs. [...] Therefore (when in non-DT use case), the display controller drivers side should not set DRM_BRIDGE_ATTACH_NO_CONNECTOR flag anymore. Which is to hint that the it66121 should totally in charge of those tasks (either by using bridge connector helper or create a connector manually). I don't understand on such a case, why bother display controller drivers anymore. This is the reason why we had introduced this flag. It allows the driver to customise the connector. It even allows the driver to implement a connector on its own, completely ignoring the drm_bridge_connector. I know what you said is right in the sense of the universe cases, but I think the most frequent(majority) use case is that there is only one display bridge on the middle. Therefore, I don't want to movethe connector things into device driver if there is only one display bridge(say it66121) in the middle. After all, there is no *direct physical connection* from the perspective of the hardware. I means that there is no hardware wires connectthe HDMI connector and the DVO port. So display controller drivers should not interact with anything related with the connector on a perfect abstract on the software side. Especially for such a simple use case. It probably make senses to make a decision for themost frequently use case, please also note that this patch didn't introduce any-restriction for the more advance uses cases(multiple bridges in the middle). So, for the sake of not having the connector in the display driver, you want to add boilerplate code basically to each and every bridge driver. In the end, they should all behave in the same way. Moreover, there is no way this implementation can work without a warning if there are two bridges in a chain and the it66121 is the second (the last) one. The host can not specify the DRM_BRIDGE_ATTACH_NO_CONNECTOR) +
[PATCH] drm/msm/gpu: Fix null-pointer dereference in zap_shader_load_mdt
kasprintf() returns a pointer to dynamically allocated memory which can be NULL upon failure. Ensure the allocation was successful by checking the pointer validity. Fixes: a9e2559c931d ("drm/msm/gpu: Move zap shader loading to adreno") Signed-off-by: Kunwu Chan --- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 3fe9fd240cc7..0ebf86ffd57b 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -144,6 +144,10 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname, char *newname; newname = kasprintf(GFP_KERNEL, "qcom/%s", fwname); + if (!newname) { + ret = -ENOMEM; + goto out; + } ret = qcom_mdt_load(dev, fw, newname, pasid, mem_region, mem_phys, mem_size, NULL); -- 2.34.1
[PATCH] drm/bridge: panel: Check device dependency before managing device link
Some panel devices already depend on DRM device, like the panel in arch/arm/boot/dts/st/ste-ux500-samsung-skomer.dts, because DRM device is the ancestor of those panel devices. device_link_add() would fail by returning a NULL pointer for those panel devices because of the existing dependency. So, check the dependency by calling device_is_dependent() before adding or deleting device link between panel device and DRM device so that the link is managed only for independent panel devices. Fixes: 887878014534 ("drm/bridge: panel: Fix device link for DRM_BRIDGE_ATTACH_NO_CONNECTOR") Fixes: 199cf07ebd2b ("drm/bridge: panel: Add a device link between drm device and panel device") Reported-by: Linus Walleij Closes: https://lore.kernel.org/lkml/cacrpkdagzxd6hbix7mvunjajtmepg00pp6+nj1p0jrfj-ar...@mail.gmail.com/T/ Tested-by: Linus Walleij Signed-off-by: Liu Ying --- drivers/gpu/drm/bridge/panel.c | 27 ++- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index e48823a4f1ed..5e8980023407 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -23,6 +23,7 @@ struct panel_bridge { struct drm_panel *panel; struct device_link *link; u32 connector_type; + bool is_independent; }; static inline struct panel_bridge * @@ -67,12 +68,17 @@ static int panel_bridge_attach(struct drm_bridge *bridge, struct drm_device *drm_dev = bridge->dev; int ret; - panel_bridge->link = device_link_add(drm_dev->dev, panel->dev, -DL_FLAG_STATELESS); - if (!panel_bridge->link) { - DRM_ERROR("Failed to add device link between %s and %s\n", - dev_name(drm_dev->dev), dev_name(panel->dev)); - return -EINVAL; + panel_bridge->is_independent = !device_is_dependent(drm_dev->dev, + panel->dev); + + if (panel_bridge->is_independent) { + panel_bridge->link = device_link_add(drm_dev->dev, panel->dev, +DL_FLAG_STATELESS); + if (!panel_bridge->link) { + DRM_ERROR("Failed to add device link between %s and %s\n", + dev_name(drm_dev->dev), dev_name(panel->dev)); + return -EINVAL; + } } if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) @@ -80,7 +86,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge, if (!bridge->encoder) { DRM_ERROR("Missing encoder\n"); - device_link_del(panel_bridge->link); + if (panel_bridge->is_independent) + device_link_del(panel_bridge->link); return -ENODEV; } @@ -92,7 +99,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge, panel_bridge->connector_type); if (ret) { DRM_ERROR("Failed to initialize connector\n"); - device_link_del(panel_bridge->link); + if (panel_bridge->is_independent) + device_link_del(panel_bridge->link); return ret; } @@ -115,7 +123,8 @@ static void panel_bridge_detach(struct drm_bridge *bridge) struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); struct drm_connector *connector = _bridge->connector; - device_link_del(panel_bridge->link); + if (panel_bridge->is_independent) + device_link_del(panel_bridge->link); /* * Cleanup the connector if we know it was initialized. -- 2.37.1
RE: [PATCH v3] drm/bridge: panel: Add a device link between drm device and panel device
On Wednesday, November 22, 2023 9:59 PM, Linus Walleij wrote: > Hi Ying, Hi Linus, > > On Mon, Nov 20, 2023 at 11:08 AM Ying Liu wrote: > > [Me] > > > > v2->v3: > > > > * Improve commit message s/swapped/reversed/. > > > > > > This patch causes a regression in the Ux500 MCDE > > > drivers/gpu/drm/mcde/* driver with the nt35510 panel > > > drivers/gpu/drm/panel/panel-novatek-nt35510.c > > > my dmesg looks like this: > (...) > > Sorry for the breakage and a bit late response(I'm a bit busy with internal > > things). > > > > I think device_link_add() fails because a0351000.dsi.0 already depends > > on a035.mcde. Can you confirm that device_link_add() returns NULL > > right after it calls device_is_dependent()? > > > > Does this patch fix the issue? > > Yep it works! > > You missed one device_link_del() instance on the errorpath. Will add it. > > Tested-by: Linus Walleij Thanks for the test. > > Can you send it as a proper patch? Will do. Regards, Liu Ying
Re: [PATCH 1/3] riscv: Add support for kernel-mode FPU
Hi Samuel, kernel test robot noticed the following build errors: [auto build test ERROR on drm-misc/drm-misc-next] [also build test ERROR on linus/master v6.7-rc2 next-20231122] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Samuel-Holland/riscv-Add-support-for-kernel-mode-FPU/20231122-111015 base: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next patch link: https://lore.kernel.org/r/20231122030621.3759313-2-samuel.holland%40sifive.com patch subject: [PATCH 1/3] riscv: Add support for kernel-mode FPU config: riscv-randconfig-r111-20231123 (https://download.01.org/0day-ci/archive/20231123/202311230628.tkl31mjj-...@intel.com/config) compiler: riscv64-linux-gcc (GCC) 13.2.0 reproduce: (https://download.01.org/0day-ci/archive/20231123/202311230628.tkl31mjj-...@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot | Closes: https://lore.kernel.org/oe-kbuild-all/202311230628.tkl31mjj-...@intel.com/ All errors (new ones prefixed by >>): In file included from include/linux/linkage.h:7, from include/linux/printk.h:8, from include/asm-generic/bug.h:22, from arch/riscv/include/asm/bug.h:83, from include/linux/bug.h:5, from arch/riscv/include/asm/current.h:13, from include/linux/sched.h:12, from include/linux/ratelimit.h:6, from include/linux/dev_printk.h:16, from include/linux/device.h:15, from include/linux/node.h:18, from include/linux/cpu.h:17, from arch/riscv/kernel/process.c:10: >> arch/riscv/kernel/process.c:229:19: error: '__fstate_save' undeclared here >> (not in a function); did you mean 'fstate_save'? 229 | EXPORT_SYMBOL_GPL(__fstate_save); | ^ include/linux/export.h:74:23: note: in definition of macro '__EXPORT_SYMBOL' 74 | extern typeof(sym) sym; \ | ^~~ include/linux/export.h:87:41: note: in expansion of macro '_EXPORT_SYMBOL' 87 | #define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "GPL") | ^~ arch/riscv/kernel/process.c:229:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL' 229 | EXPORT_SYMBOL_GPL(__fstate_save); | ^ >> arch/riscv/kernel/process.c:230:19: error: '__fstate_restore' undeclared >> here (not in a function); did you mean 'fstate_restore'? 230 | EXPORT_SYMBOL_GPL(__fstate_restore); | ^~~~ include/linux/export.h:74:23: note: in definition of macro '__EXPORT_SYMBOL' 74 | extern typeof(sym) sym; \ | ^~~ include/linux/export.h:87:41: note: in expansion of macro '_EXPORT_SYMBOL' 87 | #define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "GPL") | ^~ arch/riscv/kernel/process.c:230:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL' 230 | EXPORT_SYMBOL_GPL(__fstate_restore); | ^ vim +229 arch/riscv/kernel/process.c 228 > 229 EXPORT_SYMBOL_GPL(__fstate_save); > 230 EXPORT_SYMBOL_GPL(__fstate_restore); -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Re: Radeon regression in 6.6 kernel
On 2023-11-21 17:05, Phillip Susi wrote: > Alex Deucher writes: > >> Does reverting 56e449603f0ac580700621a356d35d5716a62ce5 alone fix it? >> Can you also attach your full dmesg log for the failed suspend? > > No, it doesn't. Here is the full syslog from the boot with only that > revert: > Thank you Phillip for verifying this. BTW, luben.tui...@amd.com should absolutely bounce for everyone sending emails to it. Not sure why it is still active. My new email is the one this email is coming from. -- Regards, Luben OpenPGP_0x4C15479431A334AF.asc Description: OpenPGP public key OpenPGP_signature.asc Description: OpenPGP digital signature
Re: [PATCH] drm/rockchip: rk3066_hdmi: include drm/drm_atomic.h
On Wed, 22 Nov 2023 23:18:29 +0100, Arnd Bergmann wrote: > From: Arnd Bergmann > > Without this header, the newly added code fails to build: > > drivers/gpu/drm/rockchip/rk3066_hdmi.c: In function > 'rk3066_hdmi_encoder_enable': > drivers/gpu/drm/rockchip/rk3066_hdmi.c:397:22: error: implicit declaration of > function 'drm_atomic_get_new_connector_state'; did you mean > 'drm_atomic_helper_connector_reset'? [-Werror=implicit-function-declaration] > 397 | conn_state = drm_atomic_get_new_connector_state(state, > >connector); > | ^~ > | drm_atomic_helper_connector_reset > drivers/gpu/drm/rockchip/rk3066_hdmi.c:397:20: error: assignment to 'struct > drm_connector_state *' from 'int' makes pointer from integer without a cast > [-Werror=int-conversion] > 397 | conn_state = drm_atomic_get_new_connector_state(state, > >connector); > |^ > drivers/gpu/drm/rockchip/rk3066_hdmi.c:401:22: error: implicit declaration of > function 'drm_atomic_get_new_crtc_state'; did you mean > 'drm_atomic_helper_swap_state'? [-Werror=implicit-function-declaration] > 401 | crtc_state = drm_atomic_get_new_crtc_state(state, > conn_state->crtc); > | ^ > | drm_atomic_helper_swap_state > drivers/gpu/drm/rockchip/rk3066_hdmi.c:401:20: error: assignment to 'struct > drm_crtc_state *' from 'int' makes pointer from integer without a cast > [-Werror=int-conversion] > 401 | crtc_state = drm_atomic_get_new_crtc_state(state, > conn_state->crtc); > |^ > > [...] Applied, thanks! [1/1] drm/rockchip: rk3066_hdmi: include drm/drm_atomic.h commit: f4814c20d14ca168382e8887c768f290e4a2a861 Very puzzling, I did testbuild with the atomic conversion in place and also re-did it again to before applying this patch and didn't get the mentioned error - not sure what I might have done differently to create a dufferent reszkt, In any case, I applied the fix. Best regards, -- Heiko Stuebner
[PATCH v2] drm/amdgpu: Fix cat debugfs amdgpu_regs_didt causes kernel null pointer
For 'AMDGPU_FAMILY_SI' family cards, in 'si_common_early_init' func, init 'didt_rreg' and 'didt_wreg' to 'NULL'. But in func 'amdgpu_debugfs_regs_didt_read/write', using 'RREG32_DIDT' 'WREG32_DIDT' lacks of relevant judgment. And other 'amdgpu_ip_block_version' that use these two definitions won't be added for 'AMDGPU_FAMILY_SI'. So, add null pointer judgment before calling. Signed-off-by: Lu Yao --- Changes in v2: 1. Drop dev_err message. 2. Change error code from 'EPERM' to 'EOPNOTSUPP' Link to v1: https://lore.kernel.org/all/20231122093509.34302-1-ya...@kylinos.cn/ Thanks Christian for his comments. --- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index a53f436fa9f1..e098cd66fa2a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -638,6 +638,9 @@ static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, if (size & 0x3 || *pos & 0x3) return -EINVAL; + if (adev->didt_rreg == NULL) + return -EOPNOTSUPP; + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -694,6 +697,9 @@ static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user if (size & 0x3 || *pos & 0x3) return -EINVAL; + if (adev->didt_wreg == NULL) + return -EOPNOTSUPP; + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); -- 2.25.1
Re: [PATCH v2 1/1] drm/msm/adreno: Add support for SM7150 SoC machine
sc7180/sm7125 (atoll) expects speedbins from atoll.dtsi: And has a parameter: /delete-property/ qcom,gpu-speed-bin; 107 for 504Mhz max freq, pwrlevel 4 130 for 610Mhz max freq, pwrlevel 3 159 for 750Mhz max freq, pwrlevel 5 169 for 800Mhz max freq, pwrlevel 2 174 for 825Mhz max freq, pwrlevel 1 (Downstream says 172, but thats probably typo) For rest of the speed bins, speed-bin value is calulated as FMAX/4.8MHz + 2 round up to zero decimal places. sm7150 (sdmmagpie) expects speedbins from sdmmagpie-gpu.dtsi: 128 for 610Mhz max freq, pwrlevel 3 146 for 700Mhz max freq, pwrlevel 2 167 for 800Mhz max freq, pwrlevel 4 172 for 504Mhz max freq, pwrlevel 1 For rest of the speed bins, speed-bin value is calulated as FMAX/4.8 MHz round up to zero decimal places. Creating a new entry does not make much sense. I can suggest expanding the standard entry: .speedbins = ADRENO_SPEEDBINS( { 0, 0 }, /* sc7180/sm7125 */ { 107, 3 }, { 130, 4 }, { 159, 5 }, { 168, 1 }, has already { 174, 2 }, has already /* sm7150 */ { 128, 1 }, { 146, 2 }, { 167, 3 }, { 172, 4 }, ), All the best, Danila On 11/22/23 23:28, Konrad Dybcio wrote: On 10/16/23 16:32, Dmitry Baryshkov wrote: On 26/09/2023 23:03, Konrad Dybcio wrote: On 26.09.2023 21:10, Danila Tikhonov wrote: I think you mean by name downstream dt - sdmmagpie-gpu.dtsi You can see the forked version of the mainline here: https://github.com/sm7150-mainline/linux/blob/next/arch/arm64/boot/dts/qcom/sm7150.dtsi All fdt that we got here, if it is useful for you: https://github.com/sm7150-mainline/downstream-fdt Best wishes, Danila Taking a look at downstream, atoll.dtsi (SC7180) includes sdmmagpie-gpu.dtsi. Bottom line is, they share the speed bins, so it should be fine to just extend the existing entry. But then atoll.dtsi rewrites speed bins and pwrlevel bins. So they are not shared. +Akhil could you please check internally? Konrad
Re: [PATCH v2 1/4] i915: make inject_virtual_interrupt() void
On 2023.11.22 13:48:22 +0100, Christian Brauner wrote: > The single caller of inject_virtual_interrupt() ignores the return value > anyway. This allows us to simplify eventfd_signal() in follow-up > patches. > > Signed-off-by: Christian Brauner > --- > drivers/gpu/drm/i915/gvt/interrupt.c | 14 +++--- > 1 file changed, 7 insertions(+), 7 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c > b/drivers/gpu/drm/i915/gvt/interrupt.c > index de3f5903d1a7..9665876b4b13 100644 > --- a/drivers/gpu/drm/i915/gvt/interrupt.c > +++ b/drivers/gpu/drm/i915/gvt/interrupt.c > @@ -422,7 +422,7 @@ static void init_irq_map(struct intel_gvt_irq *irq) > #define MSI_CAP_DATA(offset) (offset + 8) > #define MSI_CAP_EN 0x1 > > -static int inject_virtual_interrupt(struct intel_vgpu *vgpu) > +static void inject_virtual_interrupt(struct intel_vgpu *vgpu) > { > unsigned long offset = vgpu->gvt->device_info.msi_cap_offset; > u16 control, data; > @@ -434,10 +434,10 @@ static int inject_virtual_interrupt(struct intel_vgpu > *vgpu) > > /* Do not generate MSI if MSIEN is disabled */ > if (!(control & MSI_CAP_EN)) > - return 0; > + return; > > if (WARN(control & GENMASK(15, 1), "only support one MSI format\n")) > - return -EINVAL; > + return; > > trace_inject_msi(vgpu->id, addr, data); > > @@ -451,10 +451,10 @@ static int inject_virtual_interrupt(struct intel_vgpu > *vgpu) >* returned and don't inject interrupt into guest. >*/ > if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status)) > - return -ESRCH; > - if (vgpu->msi_trigger && eventfd_signal(vgpu->msi_trigger, 1) != 1) > - return -EFAULT; > - return 0; > + return; > + if (!vgpu->msi_trigger) > + return; > + eventfd_signal(vgpu->msi_trigger, 1); > } I think it's a little simpler to write as if (vgpu->msi_trigger) eventfd_signal(vgpu->msi_trigger, 1); Looks fine with me. Reviewed-by: Zhenyu Wang Thanks! > > static void propagate_event(struct intel_gvt_irq *irq, > > -- > 2.42.0 > signature.asc Description: PGP signature
[PATCH 6/6] x86/vmware: Add TDX hypercall support
VMware hypercalls use I/O port, VMCALL or VMMCALL instructions. Add __tdx_hypercall path to support TDX guests. No change in high bandwidth hypercalls, as only low bandwidth ones are supported for TDX guests. Co-developed-by: Tim Merrifield Signed-off-by: Tim Merrifield Signed-off-by: Alexey Makhalov --- arch/x86/include/asm/vmware.h | 72 +++ arch/x86/kernel/cpu/vmware.c | 9 + 2 files changed, 81 insertions(+) diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h index 17091eba68cb..cd58ff8ef1af 100644 --- a/arch/x86/include/asm/vmware.h +++ b/arch/x86/include/asm/vmware.h @@ -40,6 +40,54 @@ extern u8 vmware_hypercall_mode; +#define VMWARE_TDX_VENDOR_LEAF 0x1AF7E4909ULL +#define VMWARE_TDX_HCALL_FUNC 1 + +extern void vmware_tdx_hypercall_args(struct tdx_module_args *args); + +/* + * TDCALL[TDG.VP.VMCALL] uses rax (arg0) and rcx (arg2), while the use of + * rbp (arg6) is discouraged by the TDX specification. Therefore, we + * remap those registers to r12, r13 and r14, respectively. + */ +static inline +unsigned long vmware_tdx_hypercall(unsigned long cmd, unsigned long in1, + unsigned long in3, unsigned long in4, + unsigned long in5, unsigned long in6, + uint32_t *out1, uint32_t *out2, + uint32_t *out3, uint32_t *out4, + uint32_t *out5, uint32_t *out6) +{ + struct tdx_module_args args = { + .r10 = VMWARE_TDX_VENDOR_LEAF, + .r11 = VMWARE_TDX_HCALL_FUNC, + .r12 = VMWARE_HYPERVISOR_MAGIC, + .r13 = cmd, + .rbx = in1, + .rdx = in3, + .rsi = in4, + .rdi = in5, + .r14 = in6, + }; + + vmware_tdx_hypercall_args(); + + if (out1) + *out1 = args.rbx; + if (out2) + *out2 = args.r13; + if (out3) + *out3 = args.rdx; + if (out4) + *out4 = args.rsi; + if (out5) + *out5 = args.rdi; + if (out6) + *out6 = args.r14; + + return args.r12; +} + /* * The low bandwidth call. The low word of edx is presumed to have OUT bit * set. The high word of edx may contain input data from the caller. @@ -67,6 +115,10 @@ unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1) { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall(cmd, in1, 0, 0, 0, 0, NULL, NULL, + NULL, NULL, NULL, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0) : [port] "i" (VMWARE_HYPERVISOR_PORT), @@ -85,6 +137,10 @@ unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1, { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall(cmd, in1, 0, 0, 0, 0, out1, out2, + NULL, NULL, NULL, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0), "=b" (*out1), "=c" (*out2) : [port] "i" (VMWARE_HYPERVISOR_PORT), @@ -104,6 +160,10 @@ unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1, { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall(cmd, in1, 0, 0, 0, 0, out1, out2, + out3, NULL, NULL, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3) : [port] "i" (VMWARE_HYPERVISOR_PORT), @@ -123,6 +183,10 @@ unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1, { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall(cmd, in1, in3, in4, in5, 0, NULL, + out2, NULL, NULL, NULL, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0), "=c" (*out2) : [port] "i" (VMWARE_HYPERVISOR_PORT), @@ -145,6 +209,10 @@ unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1, { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall(cmd, in1, in3, 0, 0, 0, NULL, out2, + out3, out4, out5, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0), "=c" (*out2), "=d" (*out3), "=S" (*out4), "=D" (*out5) @@ -166,6 +234,10 @@ unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1, { unsigned long out0; + if
[PATCH 5/6] drm/vmwgfx: Use vmware_hypercall API
Switch from VMWARE_HYPERCALL macro to vmware_hypercall API. Eliminate arch specific code. drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h: implement arm64 variant of vmware_hypercall here. To be moved to arch/arm64/include/asm/vmware.h later. Signed-off-by: Alexey Makhalov --- drivers/gpu/drm/vmwgfx/vmwgfx_msg.c | 173 +++ drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h | 197 +++--- drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h | 185 3 files changed, 197 insertions(+), 358 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c index 2651fe0ef518..1f15990d3934 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c @@ -48,8 +48,6 @@ #define RETRIES 3 -#define VMW_HYPERVISOR_MAGIC0x564D5868 - #define VMW_PORT_CMD_MSG30 #define VMW_PORT_CMD_HB_MSG 0 #define VMW_PORT_CMD_OPEN_CHANNEL (MSG_TYPE_OPEN << 16 | VMW_PORT_CMD_MSG) @@ -104,20 +102,18 @@ static const char* const mksstat_kern_name_desc[MKSSTAT_KERN_COUNT][2] = */ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol) { - unsigned long eax, ebx, ecx, edx, si = 0, di = 0; + u32 ecx, edx, esi, edi; - VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL, - (protocol | GUESTMSG_FLAG_COOKIE), si, di, - 0, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall6(VMW_PORT_CMD_OPEN_CHANNEL, + (protocol | GUESTMSG_FLAG_COOKIE), 0, + , , , ); if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) return -EINVAL; channel->channel_id = HIGH_WORD(edx); - channel->cookie_high = si; - channel->cookie_low = di; + channel->cookie_high = esi; + channel->cookie_low = edi; return 0; } @@ -133,17 +129,13 @@ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol) */ static int vmw_close_channel(struct rpc_channel *channel) { - unsigned long eax, ebx, ecx, edx, si, di; - - /* Set up additional parameters */ - si = channel->cookie_high; - di = channel->cookie_low; + u32 ecx; - VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL, - 0, si, di, - channel->channel_id << 16, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall5(VMW_PORT_CMD_CLOSE_CHANNEL, + 0, channel->channel_id << 16, + channel->cookie_high, + channel->cookie_low, + ); if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) return -EINVAL; @@ -163,24 +155,18 @@ static int vmw_close_channel(struct rpc_channel *channel) static unsigned long vmw_port_hb_out(struct rpc_channel *channel, const char *msg, bool hb) { - unsigned long si, di, eax, ebx, ecx, edx; + u32 ebx, ecx; unsigned long msg_len = strlen(msg); /* HB port can't access encrypted memory. */ if (hb && !cc_platform_has(CC_ATTR_MEM_ENCRYPT)) { - unsigned long bp = channel->cookie_high; - u32 channel_id = (channel->channel_id << 16); - - si = (uintptr_t) msg; - di = channel->cookie_low; - - VMW_PORT_HB_OUT( + vmware_hypercall_hb_out( (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, - msg_len, si, di, - VMWARE_HYPERVISOR_HB | channel_id | - VMWARE_HYPERVISOR_OUT, - VMW_HYPERVISOR_MAGIC, bp, - eax, ebx, ecx, edx, si, di); + msg_len, + channel->channel_id << 16, + (uintptr_t) msg, channel->cookie_low, + channel->cookie_high, + ); return ebx; } @@ -194,14 +180,13 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel, memcpy(, msg, bytes); msg_len -= bytes; msg += bytes; - si = channel->cookie_high; - di = channel->cookie_low; - - VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_SENDPAYLOAD << 16), -word, si, di, -channel->channel_id << 16, -VMW_HYPERVISOR_MAGIC, -eax, ebx, ecx, edx, si, di); + + vmware_hypercall5(VMW_PORT_CMD_MSG | + (MSG_TYPE_SENDPAYLOAD << 16), + word, channel->channel_id << 16, + channel->cookie_high, + channel->cookie_low, +
[PATCH 3/6] ptp/vmware: Use vmware_hypercall API
Switch from VMWARE_HYPERCALL macro to vmware_hypercall API. Eliminate arch specific code. No functional changes intended. Signed-off-by: Alexey Makhalov --- drivers/ptp/ptp_vmw.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/ptp/ptp_vmw.c b/drivers/ptp/ptp_vmw.c index 27c5547aa8a9..e5bb521b9b82 100644 --- a/drivers/ptp/ptp_vmw.c +++ b/drivers/ptp/ptp_vmw.c @@ -14,7 +14,6 @@ #include #include -#define VMWARE_MAGIC 0x564D5868 #define VMWARE_CMD_PCLK(nr) ((nr << 16) | 97) #define VMWARE_CMD_PCLK_GETTIME VMWARE_CMD_PCLK(0) @@ -24,15 +23,10 @@ static struct ptp_clock *ptp_vmw_clock; static int ptp_vmw_pclk_read(u64 *ns) { - u32 ret, nsec_hi, nsec_lo, unused1, unused2, unused3; - - asm volatile (VMWARE_HYPERCALL : - "=a"(ret), "=b"(nsec_hi), "=c"(nsec_lo), "=d"(unused1), - "=S"(unused2), "=D"(unused3) : - "a"(VMWARE_MAGIC), "b"(0), - "c"(VMWARE_CMD_PCLK_GETTIME), "d"(0) : - "memory"); + u32 ret, nsec_hi, nsec_lo; + ret = vmware_hypercall3(VMWARE_CMD_PCLK_GETTIME, 0, + _hi, _lo); if (ret == 0) *ns = ((u64)nsec_hi << 32) | nsec_lo; return ret; -- 2.39.0
[PATCH 1/6] x86/vmware: Move common macros to vmware.h
Move VMware hypercall macros to vmware.h as a preparation step for the next commit. No functional changes besides exporting vmware_hypercall_mode symbol. Signed-off-by: Alexey Makhalov --- arch/x86/include/asm/vmware.h | 69 ++- arch/x86/kernel/cpu/vmware.c | 57 +++-- 2 files changed, 66 insertions(+), 60 deletions(-) diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h index ac9fc51e2b18..8cabf4a577bf 100644 --- a/arch/x86/include/asm/vmware.h +++ b/arch/x86/include/asm/vmware.h @@ -8,25 +8,37 @@ /* * The hypercall definitions differ in the low word of the %edx argument - * in the following way: the old port base interface uses the port - * number to distinguish between high- and low bandwidth versions. + * in the following way: the old I/O port based interface uses the port + * number to distinguish between high- and low bandwidth versions, and + * uses IN/OUT instructions to define transfer direction. * * The new vmcall interface instead uses a set of flags to select * bandwidth mode and transfer direction. The flags should be loaded * into %dx by any user and are automatically replaced by the port - * number if the VMWARE_HYPERVISOR_PORT method is used. + * number if the I/O port method is used. * * In short, new driver code should strictly use the new definition of * %dx content. */ -/* Old port-based version */ -#define VMWARE_HYPERVISOR_PORT0x5658 -#define VMWARE_HYPERVISOR_PORT_HB 0x5659 +#define VMWARE_HYPERVISOR_HB BIT(0) +#define VMWARE_HYPERVISOR_OUT BIT(1) -/* Current vmcall / vmmcall version */ -#define VMWARE_HYPERVISOR_HB BIT(0) -#define VMWARE_HYPERVISOR_OUT BIT(1) +#define VMWARE_HYPERVISOR_PORT 0x5658 +#define VMWARE_HYPERVISOR_PORT_HB (VMWARE_HYPERVISOR_PORT | \ +VMWARE_HYPERVISOR_HB) + +#define VMWARE_HYPERVISOR_MAGIC0x564D5868U + +#define VMWARE_CMD_GETVERSION 10 +#define VMWARE_CMD_GETHZ 45 +#define VMWARE_CMD_GETVCPU_INFO68 +#define VMWARE_CMD_STEALCLOCK 91 + +#define CPUID_VMWARE_FEATURES_ECX_VMMCALL BIT(0) +#define CPUID_VMWARE_FEATURES_ECX_VMCALL BIT(1) + +extern u8 vmware_hypercall_mode; /* The low bandwidth call. The low word of edx is presumed clear. */ #define VMWARE_HYPERCALL \ @@ -54,4 +66,43 @@ "rep insb", \ "vmcall", X86_FEATURE_VMCALL, \ "vmmcall", X86_FEATURE_VMW_VMMCALL) + +#define VMWARE_PORT(cmd, eax, ebx, ecx, edx) \ + __asm__("inl (%%dx), %%eax" : \ + "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) :\ + "a"(VMWARE_HYPERVISOR_MAGIC), \ + "c"(VMWARE_CMD_##cmd), \ + "d"(VMWARE_HYPERVISOR_PORT), "b"(UINT_MAX) :\ + "memory") + +#define VMWARE_VMCALL(cmd, eax, ebx, ecx, edx) \ + __asm__("vmcall" : \ + "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) :\ + "a"(VMWARE_HYPERVISOR_MAGIC), \ + "c"(VMWARE_CMD_##cmd), \ + "d"(0), "b"(UINT_MAX) : \ + "memory") + +#define VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx) \ + __asm__("vmmcall" : \ + "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) :\ + "a"(VMWARE_HYPERVISOR_MAGIC), \ + "c"(VMWARE_CMD_##cmd), \ + "d"(0), "b"(UINT_MAX) : \ + "memory") + +#define VMWARE_CMD(cmd, eax, ebx, ecx, edx) do { \ + switch (vmware_hypercall_mode) {\ + case CPUID_VMWARE_FEATURES_ECX_VMCALL: \ + VMWARE_VMCALL(cmd, eax, ebx, ecx, edx); \ + break; \ + case CPUID_VMWARE_FEATURES_ECX_VMMCALL: \ + VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx);\ + break; \ + default:\ + VMWARE_PORT(cmd, eax, ebx, ecx, edx); \ + break; \ + } \ + } while (0) + #endif diff --git a/arch/x86/kernel/cpu/vmware.c
[PATCH 0/6] VMware hypercalls enhancements
VMware hypercalls invocations were all spread out across the kernel implementing same ABI as in-place asm-inline. With encrypted memory and confidential computing it became harder to maintain every changes in these hypercall implementations. Intention of this patchset is to introduce arch independent VMware hypercall API layer other subsystems such as device drivers can call to, while hiding architecture specific implementation behind. Second patch introduces the vmware_hypercall low and high bandwidth families of functions, with little enhancements there. Sixth patch adds tdx hypercall support arm64 implementation of vmware_hypercalls is in drivers/gpu/drm/ vmwgfx/vmwgfx_msg_arm64.h and going to be moved to arch/arm64 with a separate patchset with the introduction of VMware Linux guest support for arm64. No functional changes in drivers/input/mouse/vmmouse.c and drivers/ptp/ptp_vmw.c Alexey Makhalov (6): x86/vmware: Move common macros to vmware.h x86/vmware: Introduce vmware_hypercall API ptp/vmware: Use vmware_hypercall API input/vmmouse: Use vmware_hypercall API drm/vmwgfx: Use vmware_hypercall API x86/vmware: Add TDX hypercall support arch/x86/include/asm/vmware.h | 327 -- arch/x86/kernel/cpu/vmware.c | 101 ++- drivers/gpu/drm/vmwgfx/vmwgfx_msg.c | 173 drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h | 197 + drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h | 185 drivers/input/mouse/vmmouse.c | 76 ++--- drivers/ptp/ptp_vmw.c | 12 +- 7 files changed, 551 insertions(+), 520 deletions(-) -- 2.39.0
[PATCH 6/6] x86/vmware: Add TDX hypercall support
VMware hypercalls use I/O port, VMCALL or VMMCALL instructions. Add __tdx_hypercall path to support TDX guests. No change in high bandwidth hypercalls, as only low bandwidth ones are supported for TDX guests. Co-developed-by: Tim Merrifield Signed-off-by: Tim Merrifield Signed-off-by: Alexey Makhalov --- arch/x86/include/asm/vmware.h | 72 +++ arch/x86/kernel/cpu/vmware.c | 9 + 2 files changed, 81 insertions(+) diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h index 17091eba68cb..cd58ff8ef1af 100644 --- a/arch/x86/include/asm/vmware.h +++ b/arch/x86/include/asm/vmware.h @@ -40,6 +40,54 @@ extern u8 vmware_hypercall_mode; +#define VMWARE_TDX_VENDOR_LEAF 0x1AF7E4909ULL +#define VMWARE_TDX_HCALL_FUNC 1 + +extern void vmware_tdx_hypercall_args(struct tdx_module_args *args); + +/* + * TDCALL[TDG.VP.VMCALL] uses rax (arg0) and rcx (arg2), while the use of + * rbp (arg6) is discouraged by the TDX specification. Therefore, we + * remap those registers to r12, r13 and r14, respectively. + */ +static inline +unsigned long vmware_tdx_hypercall(unsigned long cmd, unsigned long in1, + unsigned long in3, unsigned long in4, + unsigned long in5, unsigned long in6, + uint32_t *out1, uint32_t *out2, + uint32_t *out3, uint32_t *out4, + uint32_t *out5, uint32_t *out6) +{ + struct tdx_module_args args = { + .r10 = VMWARE_TDX_VENDOR_LEAF, + .r11 = VMWARE_TDX_HCALL_FUNC, + .r12 = VMWARE_HYPERVISOR_MAGIC, + .r13 = cmd, + .rbx = in1, + .rdx = in3, + .rsi = in4, + .rdi = in5, + .r14 = in6, + }; + + vmware_tdx_hypercall_args(); + + if (out1) + *out1 = args.rbx; + if (out2) + *out2 = args.r13; + if (out3) + *out3 = args.rdx; + if (out4) + *out4 = args.rsi; + if (out5) + *out5 = args.rdi; + if (out6) + *out6 = args.r14; + + return args.r12; +} + /* * The low bandwidth call. The low word of edx is presumed to have OUT bit * set. The high word of edx may contain input data from the caller. @@ -67,6 +115,10 @@ unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1) { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall(cmd, in1, 0, 0, 0, 0, NULL, NULL, + NULL, NULL, NULL, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0) : [port] "i" (VMWARE_HYPERVISOR_PORT), @@ -85,6 +137,10 @@ unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1, { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall(cmd, in1, 0, 0, 0, 0, out1, out2, + NULL, NULL, NULL, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0), "=b" (*out1), "=c" (*out2) : [port] "i" (VMWARE_HYPERVISOR_PORT), @@ -104,6 +160,10 @@ unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1, { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall(cmd, in1, 0, 0, 0, 0, out1, out2, + out3, NULL, NULL, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3) : [port] "i" (VMWARE_HYPERVISOR_PORT), @@ -123,6 +183,10 @@ unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1, { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall(cmd, in1, in3, in4, in5, 0, NULL, + out2, NULL, NULL, NULL, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0), "=c" (*out2) : [port] "i" (VMWARE_HYPERVISOR_PORT), @@ -145,6 +209,10 @@ unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1, { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall(cmd, in1, in3, 0, 0, 0, NULL, out2, + out3, out4, out5, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0), "=c" (*out2), "=d" (*out3), "=S" (*out4), "=D" (*out5) @@ -166,6 +234,10 @@ unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1, { unsigned long out0; + if
[PATCH 2/6] x86/vmware: Introduce vmware_hypercall API
Introducing vmware_hypercall family of functions as a common implementation to be used by the VMware guest code and virtual device drivers in arhitecture independent manner. By analogy with KVM hypercall API, vmware_hypercallX and vmware_hypercall_hb_{out,in} set of functions was added to achieve that. Architecture specific implementation should be hidden inside. It will simplify future enhancements in VMware hypercalls such as SEV-ES and TDX related changes without needs to modify a caller in device drivers code. Current implementation extends an idea from commit bac7b4e84323 ("x86/vmware: Update platform detection code for VMCALL/VMMCALL hypercalls") to have a slow, but safe path in VMWARE_HYPERCALL when alternatives are not yet applied. This logic was inherited from VMWARE_CMD from the commit mentioned above. Default alternative code was optimized by size to reduse excessive nop alignment once alternatives are applied. Total default code size is 26 bytes, in worse case (3 bytes alternative) remaining 23 bytes will be aligned by only 3 long NOP instructions. Signed-off-by: Alexey Makhalov --- arch/x86/include/asm/vmware.h | 262 ++ arch/x86/kernel/cpu/vmware.c | 35 ++--- 2 files changed, 220 insertions(+), 77 deletions(-) diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h index 8cabf4a577bf..17091eba68cb 100644 --- a/arch/x86/include/asm/vmware.h +++ b/arch/x86/include/asm/vmware.h @@ -40,69 +40,219 @@ extern u8 vmware_hypercall_mode; -/* The low bandwidth call. The low word of edx is presumed clear. */ -#define VMWARE_HYPERCALL \ - ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT) ", %%dx; " \ - "inl (%%dx), %%eax", \ - "vmcall", X86_FEATURE_VMCALL, \ - "vmmcall", X86_FEATURE_VMW_VMMCALL) - /* - * The high bandwidth out call. The low word of edx is presumed to have the - * HB and OUT bits set. + * The low bandwidth call. The low word of edx is presumed to have OUT bit + * set. The high word of edx may contain input data from the caller. */ -#define VMWARE_HYPERCALL_HB_OUT \ - ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT_HB) ", %%dx; " \ - "rep outsb", \ +#define VMWARE_HYPERCALL \ + ALTERNATIVE_3("cmpb $" \ + __stringify(CPUID_VMWARE_FEATURES_ECX_VMMCALL) \ + ", %[mode]\n\t" \ + "jg 2f\n\t" \ + "je 1f\n\t" \ + "movw %[port], %%dx\n\t" \ + "inl (%%dx), %%eax\n\t" \ + "jmp 3f\n\t" \ + "1: vmmcall\n\t" \ + "jmp 3f\n\t" \ + "2: vmcall\n\t" \ + "3:\n\t", \ + "movw %[port], %%dx\n\t" \ + "inl (%%dx), %%eax", X86_FEATURE_HYPERVISOR, \ "vmcall", X86_FEATURE_VMCALL, \ "vmmcall", X86_FEATURE_VMW_VMMCALL) +static inline +unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1) +{ + unsigned long out0; + + asm_inline volatile (VMWARE_HYPERCALL + : "=a" (out0) + : [port] "i" (VMWARE_HYPERVISOR_PORT), + [mode] "m" (vmware_hypercall_mode), + "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (in1), + "c" (cmd), + "d" (0) + : "cc", "memory"); + return out0; +} + +static inline +unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1, + uint32_t *out1, uint32_t *out2) +{ + unsigned long out0; + + asm_inline volatile (VMWARE_HYPERCALL + : "=a" (out0), "=b" (*out1), "=c" (*out2) + : [port] "i" (VMWARE_HYPERVISOR_PORT), + [mode] "m" (vmware_hypercall_mode), + "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (in1), + "c" (cmd), + "d" (0) + : "cc", "memory"); + return out0; +} + +static inline +unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1, + uint32_t *out1, uint32_t *out2, + uint32_t *out3) +{ +
[PATCH 1/6] x86/vmware: Move common macros to vmware.h
Move VMware hypercall macros to vmware.h as a preparation step for the next commit. No functional changes besides exporting vmware_hypercall_mode symbol. Signed-off-by: Alexey Makhalov --- arch/x86/include/asm/vmware.h | 69 ++- arch/x86/kernel/cpu/vmware.c | 57 +++-- 2 files changed, 66 insertions(+), 60 deletions(-) diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h index ac9fc51e2b18..8cabf4a577bf 100644 --- a/arch/x86/include/asm/vmware.h +++ b/arch/x86/include/asm/vmware.h @@ -8,25 +8,37 @@ /* * The hypercall definitions differ in the low word of the %edx argument - * in the following way: the old port base interface uses the port - * number to distinguish between high- and low bandwidth versions. + * in the following way: the old I/O port based interface uses the port + * number to distinguish between high- and low bandwidth versions, and + * uses IN/OUT instructions to define transfer direction. * * The new vmcall interface instead uses a set of flags to select * bandwidth mode and transfer direction. The flags should be loaded * into %dx by any user and are automatically replaced by the port - * number if the VMWARE_HYPERVISOR_PORT method is used. + * number if the I/O port method is used. * * In short, new driver code should strictly use the new definition of * %dx content. */ -/* Old port-based version */ -#define VMWARE_HYPERVISOR_PORT0x5658 -#define VMWARE_HYPERVISOR_PORT_HB 0x5659 +#define VMWARE_HYPERVISOR_HB BIT(0) +#define VMWARE_HYPERVISOR_OUT BIT(1) -/* Current vmcall / vmmcall version */ -#define VMWARE_HYPERVISOR_HB BIT(0) -#define VMWARE_HYPERVISOR_OUT BIT(1) +#define VMWARE_HYPERVISOR_PORT 0x5658 +#define VMWARE_HYPERVISOR_PORT_HB (VMWARE_HYPERVISOR_PORT | \ +VMWARE_HYPERVISOR_HB) + +#define VMWARE_HYPERVISOR_MAGIC0x564D5868U + +#define VMWARE_CMD_GETVERSION 10 +#define VMWARE_CMD_GETHZ 45 +#define VMWARE_CMD_GETVCPU_INFO68 +#define VMWARE_CMD_STEALCLOCK 91 + +#define CPUID_VMWARE_FEATURES_ECX_VMMCALL BIT(0) +#define CPUID_VMWARE_FEATURES_ECX_VMCALL BIT(1) + +extern u8 vmware_hypercall_mode; /* The low bandwidth call. The low word of edx is presumed clear. */ #define VMWARE_HYPERCALL \ @@ -54,4 +66,43 @@ "rep insb", \ "vmcall", X86_FEATURE_VMCALL, \ "vmmcall", X86_FEATURE_VMW_VMMCALL) + +#define VMWARE_PORT(cmd, eax, ebx, ecx, edx) \ + __asm__("inl (%%dx), %%eax" : \ + "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) :\ + "a"(VMWARE_HYPERVISOR_MAGIC), \ + "c"(VMWARE_CMD_##cmd), \ + "d"(VMWARE_HYPERVISOR_PORT), "b"(UINT_MAX) :\ + "memory") + +#define VMWARE_VMCALL(cmd, eax, ebx, ecx, edx) \ + __asm__("vmcall" : \ + "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) :\ + "a"(VMWARE_HYPERVISOR_MAGIC), \ + "c"(VMWARE_CMD_##cmd), \ + "d"(0), "b"(UINT_MAX) : \ + "memory") + +#define VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx) \ + __asm__("vmmcall" : \ + "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) :\ + "a"(VMWARE_HYPERVISOR_MAGIC), \ + "c"(VMWARE_CMD_##cmd), \ + "d"(0), "b"(UINT_MAX) : \ + "memory") + +#define VMWARE_CMD(cmd, eax, ebx, ecx, edx) do { \ + switch (vmware_hypercall_mode) {\ + case CPUID_VMWARE_FEATURES_ECX_VMCALL: \ + VMWARE_VMCALL(cmd, eax, ebx, ecx, edx); \ + break; \ + case CPUID_VMWARE_FEATURES_ECX_VMMCALL: \ + VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx);\ + break; \ + default:\ + VMWARE_PORT(cmd, eax, ebx, ecx, edx); \ + break; \ + } \ + } while (0) + #endif diff --git a/arch/x86/kernel/cpu/vmware.c
[PATCH 4/6] input/vmmouse: Use vmware_hypercall API
Switch from VMWARE_HYPERCALL macro to vmware_hypercall API. Eliminate arch specific code. No functional changes intended. Signed-off-by: Alexey Makhalov --- drivers/input/mouse/vmmouse.c | 76 ++- 1 file changed, 22 insertions(+), 54 deletions(-) diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c index ea9eff7c8099..fb1d986a6895 100644 --- a/drivers/input/mouse/vmmouse.c +++ b/drivers/input/mouse/vmmouse.c @@ -21,19 +21,16 @@ #include "psmouse.h" #include "vmmouse.h" -#define VMMOUSE_PROTO_MAGIC0x564D5868U - /* * Main commands supported by the vmmouse hypervisor port. */ -#define VMMOUSE_PROTO_CMD_GETVERSION 10 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_DATA 39 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_STATUS40 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND 41 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_RESTRICT 86 +#define VMWARE_CMD_ABSPOINTER_DATA 39 +#define VMWARE_CMD_ABSPOINTER_STATUS 40 +#define VMWARE_CMD_ABSPOINTER_COMMAND 41 +#define VMWARE_CMD_ABSPOINTER_RESTRICT 86 /* - * Subcommands for VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND + * Subcommands for VMWARE_CMD_ABSPOINTER_COMMAND */ #define VMMOUSE_CMD_ENABLE 0x45414552U #define VMMOUSE_CMD_DISABLE0x00f5U @@ -76,28 +73,6 @@ struct vmmouse_data { char dev_name[128]; }; -/* - * Hypervisor-specific bi-directional communication channel - * implementing the vmmouse protocol. Should never execute on - * bare metal hardware. - */ -#define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4) \ -({ \ - unsigned long __dummy1, __dummy2; \ - __asm__ __volatile__ (VMWARE_HYPERCALL :\ - "=a"(out1), \ - "=b"(out2), \ - "=c"(out3), \ - "=d"(out4), \ - "=S"(__dummy1), \ - "=D"(__dummy2) :\ - "a"(VMMOUSE_PROTO_MAGIC), \ - "b"(in1), \ - "c"(VMMOUSE_PROTO_CMD_##cmd), \ - "d"(0) :\ - "memory"); \ -}) - /** * vmmouse_report_button - report button state on the correct input device * @@ -145,14 +120,12 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse) struct input_dev *abs_dev = priv->abs_dev; struct input_dev *pref_dev; u32 status, x, y, z; - u32 dummy1, dummy2, dummy3; unsigned int queue_length; unsigned int count = 255; while (count--) { /* See if we have motion data. */ - VMMOUSE_CMD(ABSPOINTER_STATUS, 0, - status, dummy1, dummy2, dummy3); + status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0); if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR) { psmouse_err(psmouse, "failed to fetch status data\n"); /* @@ -172,7 +145,8 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse) } /* Now get it */ - VMMOUSE_CMD(ABSPOINTER_DATA, 4, status, x, y, z); + status = vmware_hypercall4(VMWARE_CMD_ABSPOINTER_DATA, 4, + , , ); /* * And report what we've got. Prefer to report button @@ -247,14 +221,10 @@ static psmouse_ret_t vmmouse_process_byte(struct psmouse *psmouse) static void vmmouse_disable(struct psmouse *psmouse) { u32 status; - u32 dummy1, dummy2, dummy3, dummy4; - - VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE, - dummy1, dummy2, dummy3, dummy4); - VMMOUSE_CMD(ABSPOINTER_STATUS, 0, - status, dummy1, dummy2, dummy3); + vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE); + status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0); if ((status & VMMOUSE_ERROR) != VMMOUSE_ERROR) psmouse_warn(psmouse, "failed to disable vmmouse device\n"); } @@ -271,26 +241,24 @@ static void vmmouse_disable(struct psmouse *psmouse) static int vmmouse_enable(struct psmouse *psmouse) { u32 status, version; - u32 dummy1, dummy2, dummy3, dummy4; /* * Try enabling the device. If successful, we should be able to * read valid version ID back from it. */ - VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE, - dummy1, dummy2, dummy3, dummy4); + vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE); /* * See if version ID can be
[PATCH 4/6] input/vmmouse: Use vmware_hypercall API
Switch from VMWARE_HYPERCALL macro to vmware_hypercall API. Eliminate arch specific code. No functional changes intended. Signed-off-by: Alexey Makhalov --- drivers/input/mouse/vmmouse.c | 76 ++- 1 file changed, 22 insertions(+), 54 deletions(-) diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c index ea9eff7c8099..fb1d986a6895 100644 --- a/drivers/input/mouse/vmmouse.c +++ b/drivers/input/mouse/vmmouse.c @@ -21,19 +21,16 @@ #include "psmouse.h" #include "vmmouse.h" -#define VMMOUSE_PROTO_MAGIC0x564D5868U - /* * Main commands supported by the vmmouse hypervisor port. */ -#define VMMOUSE_PROTO_CMD_GETVERSION 10 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_DATA 39 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_STATUS40 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND 41 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_RESTRICT 86 +#define VMWARE_CMD_ABSPOINTER_DATA 39 +#define VMWARE_CMD_ABSPOINTER_STATUS 40 +#define VMWARE_CMD_ABSPOINTER_COMMAND 41 +#define VMWARE_CMD_ABSPOINTER_RESTRICT 86 /* - * Subcommands for VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND + * Subcommands for VMWARE_CMD_ABSPOINTER_COMMAND */ #define VMMOUSE_CMD_ENABLE 0x45414552U #define VMMOUSE_CMD_DISABLE0x00f5U @@ -76,28 +73,6 @@ struct vmmouse_data { char dev_name[128]; }; -/* - * Hypervisor-specific bi-directional communication channel - * implementing the vmmouse protocol. Should never execute on - * bare metal hardware. - */ -#define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4) \ -({ \ - unsigned long __dummy1, __dummy2; \ - __asm__ __volatile__ (VMWARE_HYPERCALL :\ - "=a"(out1), \ - "=b"(out2), \ - "=c"(out3), \ - "=d"(out4), \ - "=S"(__dummy1), \ - "=D"(__dummy2) :\ - "a"(VMMOUSE_PROTO_MAGIC), \ - "b"(in1), \ - "c"(VMMOUSE_PROTO_CMD_##cmd), \ - "d"(0) :\ - "memory"); \ -}) - /** * vmmouse_report_button - report button state on the correct input device * @@ -145,14 +120,12 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse) struct input_dev *abs_dev = priv->abs_dev; struct input_dev *pref_dev; u32 status, x, y, z; - u32 dummy1, dummy2, dummy3; unsigned int queue_length; unsigned int count = 255; while (count--) { /* See if we have motion data. */ - VMMOUSE_CMD(ABSPOINTER_STATUS, 0, - status, dummy1, dummy2, dummy3); + status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0); if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR) { psmouse_err(psmouse, "failed to fetch status data\n"); /* @@ -172,7 +145,8 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse) } /* Now get it */ - VMMOUSE_CMD(ABSPOINTER_DATA, 4, status, x, y, z); + status = vmware_hypercall4(VMWARE_CMD_ABSPOINTER_DATA, 4, + , , ); /* * And report what we've got. Prefer to report button @@ -247,14 +221,10 @@ static psmouse_ret_t vmmouse_process_byte(struct psmouse *psmouse) static void vmmouse_disable(struct psmouse *psmouse) { u32 status; - u32 dummy1, dummy2, dummy3, dummy4; - - VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE, - dummy1, dummy2, dummy3, dummy4); - VMMOUSE_CMD(ABSPOINTER_STATUS, 0, - status, dummy1, dummy2, dummy3); + vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE); + status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0); if ((status & VMMOUSE_ERROR) != VMMOUSE_ERROR) psmouse_warn(psmouse, "failed to disable vmmouse device\n"); } @@ -271,26 +241,24 @@ static void vmmouse_disable(struct psmouse *psmouse) static int vmmouse_enable(struct psmouse *psmouse) { u32 status, version; - u32 dummy1, dummy2, dummy3, dummy4; /* * Try enabling the device. If successful, we should be able to * read valid version ID back from it. */ - VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE, - dummy1, dummy2, dummy3, dummy4); + vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE); /* * See if version ID can be
[PATCH 2/6] x86/vmware: Introduce vmware_hypercall API
Introducing vmware_hypercall family of functions as a common implementation to be used by the VMware guest code and virtual device drivers in arhitecture independent manner. By analogy with KVM hypercall API, vmware_hypercallX and vmware_hypercall_hb_{out,in} set of functions was added to achieve that. Architecture specific implementation should be hidden inside. It will simplify future enhancements in VMware hypercalls such as SEV-ES and TDX related changes without needs to modify a caller in device drivers code. Current implementation extends an idea from commit bac7b4e84323 ("x86/vmware: Update platform detection code for VMCALL/VMMCALL hypercalls") to have a slow, but safe path in VMWARE_HYPERCALL when alternatives are not yet applied. This logic was inherited from VMWARE_CMD from the commit mentioned above. Default alternative code was optimized by size to reduse excessive nop alignment once alternatives are applied. Total default code size is 26 bytes, in worse case (3 bytes alternative) remaining 23 bytes will be aligned by only 3 long NOP instructions. Signed-off-by: Alexey Makhalov --- arch/x86/include/asm/vmware.h | 262 ++ arch/x86/kernel/cpu/vmware.c | 35 ++--- 2 files changed, 220 insertions(+), 77 deletions(-) diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h index 8cabf4a577bf..17091eba68cb 100644 --- a/arch/x86/include/asm/vmware.h +++ b/arch/x86/include/asm/vmware.h @@ -40,69 +40,219 @@ extern u8 vmware_hypercall_mode; -/* The low bandwidth call. The low word of edx is presumed clear. */ -#define VMWARE_HYPERCALL \ - ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT) ", %%dx; " \ - "inl (%%dx), %%eax", \ - "vmcall", X86_FEATURE_VMCALL, \ - "vmmcall", X86_FEATURE_VMW_VMMCALL) - /* - * The high bandwidth out call. The low word of edx is presumed to have the - * HB and OUT bits set. + * The low bandwidth call. The low word of edx is presumed to have OUT bit + * set. The high word of edx may contain input data from the caller. */ -#define VMWARE_HYPERCALL_HB_OUT \ - ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT_HB) ", %%dx; " \ - "rep outsb", \ +#define VMWARE_HYPERCALL \ + ALTERNATIVE_3("cmpb $" \ + __stringify(CPUID_VMWARE_FEATURES_ECX_VMMCALL) \ + ", %[mode]\n\t" \ + "jg 2f\n\t" \ + "je 1f\n\t" \ + "movw %[port], %%dx\n\t" \ + "inl (%%dx), %%eax\n\t" \ + "jmp 3f\n\t" \ + "1: vmmcall\n\t" \ + "jmp 3f\n\t" \ + "2: vmcall\n\t" \ + "3:\n\t", \ + "movw %[port], %%dx\n\t" \ + "inl (%%dx), %%eax", X86_FEATURE_HYPERVISOR, \ "vmcall", X86_FEATURE_VMCALL, \ "vmmcall", X86_FEATURE_VMW_VMMCALL) +static inline +unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1) +{ + unsigned long out0; + + asm_inline volatile (VMWARE_HYPERCALL + : "=a" (out0) + : [port] "i" (VMWARE_HYPERVISOR_PORT), + [mode] "m" (vmware_hypercall_mode), + "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (in1), + "c" (cmd), + "d" (0) + : "cc", "memory"); + return out0; +} + +static inline +unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1, + uint32_t *out1, uint32_t *out2) +{ + unsigned long out0; + + asm_inline volatile (VMWARE_HYPERCALL + : "=a" (out0), "=b" (*out1), "=c" (*out2) + : [port] "i" (VMWARE_HYPERVISOR_PORT), + [mode] "m" (vmware_hypercall_mode), + "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (in1), + "c" (cmd), + "d" (0) + : "cc", "memory"); + return out0; +} + +static inline +unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1, + uint32_t *out1, uint32_t *out2, + uint32_t *out3) +{ +
[PATCH 5/6] drm/vmwgfx: Use vmware_hypercall API
Switch from VMWARE_HYPERCALL macro to vmware_hypercall API. Eliminate arch specific code. drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h: implement arm64 variant of vmware_hypercall here. To be moved to arch/arm64/include/asm/vmware.h later. Signed-off-by: Alexey Makhalov --- drivers/gpu/drm/vmwgfx/vmwgfx_msg.c | 173 +++ drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h | 197 +++--- drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h | 185 3 files changed, 197 insertions(+), 358 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c index 2651fe0ef518..1f15990d3934 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c @@ -48,8 +48,6 @@ #define RETRIES 3 -#define VMW_HYPERVISOR_MAGIC0x564D5868 - #define VMW_PORT_CMD_MSG30 #define VMW_PORT_CMD_HB_MSG 0 #define VMW_PORT_CMD_OPEN_CHANNEL (MSG_TYPE_OPEN << 16 | VMW_PORT_CMD_MSG) @@ -104,20 +102,18 @@ static const char* const mksstat_kern_name_desc[MKSSTAT_KERN_COUNT][2] = */ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol) { - unsigned long eax, ebx, ecx, edx, si = 0, di = 0; + u32 ecx, edx, esi, edi; - VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL, - (protocol | GUESTMSG_FLAG_COOKIE), si, di, - 0, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall6(VMW_PORT_CMD_OPEN_CHANNEL, + (protocol | GUESTMSG_FLAG_COOKIE), 0, + , , , ); if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) return -EINVAL; channel->channel_id = HIGH_WORD(edx); - channel->cookie_high = si; - channel->cookie_low = di; + channel->cookie_high = esi; + channel->cookie_low = edi; return 0; } @@ -133,17 +129,13 @@ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol) */ static int vmw_close_channel(struct rpc_channel *channel) { - unsigned long eax, ebx, ecx, edx, si, di; - - /* Set up additional parameters */ - si = channel->cookie_high; - di = channel->cookie_low; + u32 ecx; - VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL, - 0, si, di, - channel->channel_id << 16, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall5(VMW_PORT_CMD_CLOSE_CHANNEL, + 0, channel->channel_id << 16, + channel->cookie_high, + channel->cookie_low, + ); if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) return -EINVAL; @@ -163,24 +155,18 @@ static int vmw_close_channel(struct rpc_channel *channel) static unsigned long vmw_port_hb_out(struct rpc_channel *channel, const char *msg, bool hb) { - unsigned long si, di, eax, ebx, ecx, edx; + u32 ebx, ecx; unsigned long msg_len = strlen(msg); /* HB port can't access encrypted memory. */ if (hb && !cc_platform_has(CC_ATTR_MEM_ENCRYPT)) { - unsigned long bp = channel->cookie_high; - u32 channel_id = (channel->channel_id << 16); - - si = (uintptr_t) msg; - di = channel->cookie_low; - - VMW_PORT_HB_OUT( + vmware_hypercall_hb_out( (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, - msg_len, si, di, - VMWARE_HYPERVISOR_HB | channel_id | - VMWARE_HYPERVISOR_OUT, - VMW_HYPERVISOR_MAGIC, bp, - eax, ebx, ecx, edx, si, di); + msg_len, + channel->channel_id << 16, + (uintptr_t) msg, channel->cookie_low, + channel->cookie_high, + ); return ebx; } @@ -194,14 +180,13 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel, memcpy(, msg, bytes); msg_len -= bytes; msg += bytes; - si = channel->cookie_high; - di = channel->cookie_low; - - VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_SENDPAYLOAD << 16), -word, si, di, -channel->channel_id << 16, -VMW_HYPERVISOR_MAGIC, -eax, ebx, ecx, edx, si, di); + + vmware_hypercall5(VMW_PORT_CMD_MSG | + (MSG_TYPE_SENDPAYLOAD << 16), + word, channel->channel_id << 16, + channel->cookie_high, + channel->cookie_low, +
[PATCH 0/6] VMware hypercalls enhancements
VMware hypercalls invocations were all spread out across the kernel implementing same ABI as in-place asm-inline. With encrypted memory and confidential computing it became harder to maintain every changes in these hypercall implementations. Intention of this patchset is to introduce arch independent VMware hypercall API layer other subsystems such as device drivers can call to, while hiding architecture specific implementation behind. Second patch introduces the vmware_hypercall low and high bandwidth families of functions, with little enhancements there. Sixth patch adds tdx hypercall support arm64 implementation of vmware_hypercalls is in drivers/gpu/drm/ vmwgfx/vmwgfx_msg_arm64.h and going to be moved to arch/arm64 with a separate patchset with the introduction of VMware Linux guest support for arm64. No functional changes in drivers/input/mouse/vmmouse.c and drivers/ptp/ptp_vmw.c Alexey Makhalov (6): x86/vmware: Move common macros to vmware.h x86/vmware: Introduce vmware_hypercall API ptp/vmware: Use vmware_hypercall API input/vmmouse: Use vmware_hypercall API drm/vmwgfx: Use vmware_hypercall API x86/vmware: Add TDX hypercall support arch/x86/include/asm/vmware.h | 327 -- arch/x86/kernel/cpu/vmware.c | 101 ++- drivers/gpu/drm/vmwgfx/vmwgfx_msg.c | 173 drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h | 197 + drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h | 185 drivers/input/mouse/vmmouse.c | 76 ++--- drivers/ptp/ptp_vmw.c | 12 +- 7 files changed, 551 insertions(+), 520 deletions(-) -- 2.39.0
[PATCH 3/6] ptp/vmware: Use vmware_hypercall API
Switch from VMWARE_HYPERCALL macro to vmware_hypercall API. Eliminate arch specific code. No functional changes intended. Signed-off-by: Alexey Makhalov --- drivers/ptp/ptp_vmw.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/ptp/ptp_vmw.c b/drivers/ptp/ptp_vmw.c index 27c5547aa8a9..e5bb521b9b82 100644 --- a/drivers/ptp/ptp_vmw.c +++ b/drivers/ptp/ptp_vmw.c @@ -14,7 +14,6 @@ #include #include -#define VMWARE_MAGIC 0x564D5868 #define VMWARE_CMD_PCLK(nr) ((nr << 16) | 97) #define VMWARE_CMD_PCLK_GETTIME VMWARE_CMD_PCLK(0) @@ -24,15 +23,10 @@ static struct ptp_clock *ptp_vmw_clock; static int ptp_vmw_pclk_read(u64 *ns) { - u32 ret, nsec_hi, nsec_lo, unused1, unused2, unused3; - - asm volatile (VMWARE_HYPERCALL : - "=a"(ret), "=b"(nsec_hi), "=c"(nsec_lo), "=d"(unused1), - "=S"(unused2), "=D"(unused3) : - "a"(VMWARE_MAGIC), "b"(0), - "c"(VMWARE_CMD_PCLK_GETTIME), "d"(0) : - "memory"); + u32 ret, nsec_hi, nsec_lo; + ret = vmware_hypercall3(VMWARE_CMD_PCLK_GETTIME, 0, + _hi, _lo); if (ret == 0) *ns = ((u64)nsec_hi << 32) | nsec_lo; return ret; -- 2.39.0
Re: drm scheduler redesign causes deadlocks [extended repost]
On 2023-11-21 04:00, Bert Karwatzki wrote: > Since linux-next-20231115 my linux system (debian sid on msi alpha 15 laptop) > suffers from random deadlocks which can occur after 30 - 180min of usage. > These > deadlocks can be actively provoked by creating high system load (usually by > compiling a kernel with make -j NRCPUS) and the opening instances of > libreoffice > --writer until the system GUI locks (the mouse cursor can still be moved but > the > screen is frozen). In this state ssh'ing into the machine is still possible > and > at least sometimes log messages about hung tasks appear in /var/log/kern.log. > > More info can be found here: > https://gitlab.freedesktop.org/drm/amd/-/issues/2994 > > Using the method described to trigger the bug I bisected the problem in the > linux-next and drm-misc trees to give commit f3123c2590005 as the problem. > As this simple patch fixes the problem > > diff --git a/drivers/gpu/drm/scheduler/sched_main.c > b/drivers/gpu/drm/scheduler/sched_main.c > index 044a8c4875ba..25b97db1b623 100644 > --- a/drivers/gpu/drm/scheduler/sched_main.c > +++ b/drivers/gpu/drm/scheduler/sched_main.c > @@ -1029,9 +1029,8 @@ EXPORT_SYMBOL(drm_sched_job_cleanup); > void drm_sched_wakeup(struct drm_gpu_scheduler *sched, > struct drm_sched_entity *entity) > { > - if (drm_sched_entity_is_ready(entity)) > - if (drm_sched_can_queue(sched, entity)) > - drm_sched_run_job_queue(sched); > + if (drm_sched_can_queue(sched, entity)) > + drm_sched_run_job_queue(sched); > } > > /** > > there might be in the entity->dependency branch of drm_sched_entity_is_ready > (some kind of circular dependencies ...). > > To see if the change to drm_sched_wakeup is the actual cause of the problem or > if this problem has been cause by the redesign of the drm scheduler in linux > next-20231115+, I created the following patch for linux-6.6.0: > > diff --git a/drivers/gpu/drm/scheduler/sched_entity.c > b/drivers/gpu/drm/scheduler/sched_entity.c > index a42763e1429d..dc2abd299aeb 100644 > --- a/drivers/gpu/drm/scheduler/sched_entity.c > +++ b/drivers/gpu/drm/scheduler/sched_entity.c > @@ -358,7 +358,7 @@ static void drm_sched_entity_wakeup(struct dma_fence *f, > container_of(cb, struct drm_sched_entity, cb); > > drm_sched_entity_clear_dep(f, cb); > - drm_sched_wakeup_if_can_queue(entity->rq->sched); > + drm_sched_wakeup_if_can_queue(entity->rq->sched, entity); > } > > /** > @@ -590,7 +590,7 @@ void drm_sched_entity_push_job(struct drm_sched_job > *sched_job) > if (drm_sched_policy == DRM_SCHED_POLICY_FIFO) > drm_sched_rq_update_fifo(entity, submit_ts); > > - drm_sched_wakeup_if_can_queue(entity->rq->sched); > + drm_sched_wakeup_if_can_queue(entity->rq->sched, entity); > } > } > EXPORT_SYMBOL(drm_sched_entity_push_job); > diff --git a/drivers/gpu/drm/scheduler/sched_main.c > b/drivers/gpu/drm/scheduler/sched_main.c > index 5a3a622fc672..bbe06403b33d 100644 > --- a/drivers/gpu/drm/scheduler/sched_main.c > +++ b/drivers/gpu/drm/scheduler/sched_main.c > @@ -865,10 +865,11 @@ static bool drm_sched_can_queue(struct drm_gpu_scheduler > *sched) > * > * Wake up the scheduler if we can queue jobs. > */ > -void drm_sched_wakeup_if_can_queue(struct drm_gpu_scheduler *sched) > +void drm_sched_wakeup_if_can_queue(struct drm_gpu_scheduler *sched, struct > drm_sched_entity *entity) > { > - if (drm_sched_can_queue(sched)) > - wake_up_interruptible(>wake_up_worker); > + if(drm_sched_entity_is_ready(entity)) > + if (drm_sched_can_queue(sched)) > + wake_up_interruptible(>wake_up_worker); > } > > /** > diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h > index ac65f0626cfc..6cfe3d193e69 100644 > --- a/include/drm/gpu_scheduler.h > +++ b/include/drm/gpu_scheduler.h > @@ -548,7 +548,7 @@ void drm_sched_entity_modify_sched(struct drm_sched_entity > *entity, > unsigned int num_sched_list); > > void drm_sched_job_cleanup(struct drm_sched_job *job); > -void drm_sched_wakeup_if_can_queue(struct drm_gpu_scheduler *sched); > +void drm_sched_wakeup_if_can_queue(struct drm_gpu_scheduler *sched, struct > drm_sched_entity *entity); > void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job > *bad); > void drm_sched_start(struct drm_gpu_scheduler *sched, bool full_recovery); > void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched); > > This brings the extra check to the old scheduler and has so far not caused any > trouble (using the same stress test described above), so chances are that the > error is somewhere else in redesigned scheduler. > > > Bert Karwatzki Hi Bert, Thanks for looking into this. As an afterthought, removing the "entity_is_ready()" qualifier in wake-up, makes the scheduling more opportunistic, and I agree that that is the more correct approach. Commit f3123c2590005, basically made the code as close to the way it
Re: [PATCH v3] drm/i915/vma: Fix VMA UAF on destroy against deactivate race
Hi Janusz, this patch is conflicting now with: 5e4e06e4087e ("drm/i915: Track gt pm wakerefs") from Andrzej. I have fixed the conflict and if you want I can send it. But I thought you might want to check it yourself, first. Andi On Thu, Nov 16, 2023 at 03:07:20PM +0100, Janusz Krzysztofik wrote: > Object debugging tools were sporadically reporting illegal attempts to > free a still active i915 VMA object from when parking a GPU tile believed > to be idle. > > [161.359441] ODEBUG: free active (active state 0) object: 88811643b958 > object type: i915_active hint: __i915_vma_active+0x0/0x50 [i915] > [161.360082] WARNING: CPU: 5 PID: 276 at lib/debugobjects.c:514 > debug_print_object+0x80/0xb0 > ... > [161.360304] CPU: 5 PID: 276 Comm: kworker/5:2 Not tainted > 6.5.0-rc1-CI_DRM_13375-g003f860e5577+ #1 > [161.360314] Hardware name: Intel Corporation Rocket Lake Client > Platform/RocketLake S UDIMM 6L RVP, BIOS RKLSFWI1.R00.3173.A03.2204210138 > 04/21/2022 > [161.360322] Workqueue: i915-unordered __intel_wakeref_put_work [i915] > [161.360592] RIP: 0010:debug_print_object+0x80/0xb0 > ... > [161.361347] debug_object_free+0xeb/0x110 > [161.361362] i915_active_fini+0x14/0x130 [i915] > [161.361866] release_references+0xfe/0x1f0 [i915] > [161.362543] i915_vma_parked+0x1db/0x380 [i915] > [161.363129] __gt_park+0x121/0x230 [i915] > [161.363515] intel_wakeref_put_last+0x1f/0x70 [i915] > > That has been tracked down to be happening when another thread is > deactivating the VMA inside __active_retire() helper, after the VMA's > active counter has been already decremented to 0, but before deactivation > of the VMA's object is reported to the object debugging tool. > > We could prevent from that race by serializing i915_active_fini() with > __active_retire() via ref->tree_lock, but that wouldn't stop the VMA from > being used, e.g. from __i915_vma_retire() called at the end of > __active_retire(), after that VMA has been already freed by a concurrent > i915_vma_destroy() on return from the i915_active_fini(). Then, we should > rather fix the issue at the VMA level, not in i915_active. > > Since __i915_vma_parked() is called from __gt_park() on last put of the > GT's wakeref, the issue could be addressed by holding the GT wakeref long > enough for __active_retire() to complete before that wakeref is released > and the GT parked. > > A VMA associated with a request doesn't acquire a GT wakeref by itself. > Instead, it depends on a wakeref held directly by the request's active > intel_context for a GT associated with its VM, and indirectly on that > intel_context's engine wakeref if the engine belongs to the same GT as the > VMA's VM. In case of single-tile platforms, at least one of those > wakerefs is usually held long enough for the request's VMA to be > deactivated on time, before it is destroyed on last put of its VM GT > wakeref. However, on multi-tile platforms, a request may use a VMA from a > tile other than the one that hosts the request's engine, then it is > protected only with the intel_context's VM GT wakeref. > > There was an attempt to fix this issue on 2-tile Meteor Lake by acquiring > an extra wakeref for a Primary GT from i915_gem_do_execbuffer() -- see > commit f56fe3e91787 ("drm/i915: Fix a VMA UAF for multi-gt platform"). > However, it occurred insufficient -- the issue was still reported by CI. > That wakeref was released on exit from i915_gem_do_execbuffer(), then > potentially before completion of the request and deactivation of its > associated VMAs. > > OTOH, CI reports indicate that single-tile platforms also suffer > sporadically from the same race. > > I believe the issue was introduced by commit d93939730347 ("drm/i915: > Remove the vma refcount") which moved a call to i915_active_fini() from > a dropped i915_vma_release(), called on last put of the removed VMA kref, > to i915_vma_parked() processing path called on last put of a GT wakeref. > However, its visibility to the object debugging tool was suppressed by a > bug in i915_active that was fixed two weeks later with commit e92eb246feb9 > ("drm/i915/active: Fix missing debug object activation"). > > Fix the issue by getting a wakeref for the VMA's tile when activating it, > and putting that wakeref only after the VMA is deactivated. However, > exclude global GTT from that processing path, otherwise the GPU never goes > idle. Since __i915_vma_retire() may be called from atomic contexts, use > async variant of wakeref put. > > Having that fixed, stop explicitly acquiring the extra GT0 wakeref from > inside i915_gem_do_execbuffer(), and also drop an extra call to > i915_active_wait(), introduced by commit 7a2280e8dcd2 ("drm/i915: Wait for > active retire before i915_active_fini()") as another insufficient fix for > this UAF race. > > v3: Identify root cause more precisely, and a commit to blame, > - identify and drop former workarounds, > - update commit message and description. > v2: Get the wakeref before
Re: linux-next: Signed-off-by missing for commit in the drm-misc tree
On 2023-11-22 07:00, Maxime Ripard wrote: > Hi Luben, > > On Thu, Nov 16, 2023 at 09:27:58AM +0100, Daniel Vetter wrote: >> On Thu, Nov 16, 2023 at 09:11:43AM +0100, Maxime Ripard wrote: >>> On Tue, Nov 14, 2023 at 06:46:21PM -0500, Luben Tuikov wrote: On 2023-11-13 22:08, Stephen Rothwell wrote: > BTW, cherry picking commits does not avoid conflicts - in fact it can > cause conflicts if there are further changes to the files affected by > the cherry picked commit in either the tree/branch the commit was > cheery picked from or the destination tree/branch (I have to deal with > these all the time when merging the drm trees in linux-next). Much > better is to cross merge the branches so that the patch only appears > once or have a shared branches that are merged by any other branch that > needs the changes. > > I understand that things are not done like this in the drm trees :-( Hi Stephen, Thank you for the clarification--understood. I'll be more careful in the future. Thanks again! :-) >>> >>> In this case, the best thing to do would indeed have been to ask the >>> drm-misc maintainers to merge drm-misc-fixes into drm-misc-next. >>> >>> We're doing that all the time, but we're not ubiquitous so you need to >>> ask us :) >>> >>> Also, dim should have caught that when you pushed the branch. Did you >>> use it? >> >> Yeah dim must be used, exactly to avoid these issues. Both for applying >> patches (so not git am directly, or cherry-picking from your own >> development branch), and for pushing. The latter is even checked for by >> the server (dim sets a special push flag which is very long and contains a >> very clear warning if you bypass it). >> >> If dim was used, this would be a bug in the dim script that we need to >> fix. > > It would be very useful for you to explain what happened here so we > improve the tooling or doc and can try to make sure it doesn't happen > again > > Maxime There is no problem with the tooling--I just forced the commit in. -- Regards, Luben OpenPGP_0x4C15479431A334AF.asc Description: OpenPGP public key OpenPGP_signature.asc Description: OpenPGP digital signature
Re: [PATCH v18 24/26] drm/virtio: Attach shmem BOs dynamically
On 11/23/23 01:37, Dmitry Osipenko wrote: > On 11/13/23 12:57, Boris Brezillon wrote: >> On Mon, 30 Oct 2023 02:02:03 +0300 >> Dmitry Osipenko wrote: >> >>> Prepare for addition of memory shrinker support by attaching shmem pages >>> to host dynamically on first use. Previously the attachment vq command >>> wasn't fenced and there was no vq kick made in the BO creation code path, >>> hence the attachment already was happening dynamically, but implicitly. >>> Making attachment explicitly dynamic will allow to simplify and reuse more >>> code when shrinker will be added. The virtio_gpu_object_shmem_init() now >>> works under the held reservation lock, which will be important to have for >>> shrinker to avoid moving pages while they are in active use by the driver. >> Ah, this commit might actually help getting rid of the workaround >> introduced in "drm/shmem-helper: Add common memory shrinker". > > Not really. The virtio_gpu_free_object() is unchanged, it's only > allocation that is being deferred and it's only done for a one BO type > (virtio-gpu has multiple BO types). s/allocation/attachment/ Pages are still allocated by virtio_gpu_object_create(). -- Best regards, Dmitry
Re: [PATCH v18 24/26] drm/virtio: Attach shmem BOs dynamically
On 11/13/23 12:57, Boris Brezillon wrote: > On Mon, 30 Oct 2023 02:02:03 +0300 > Dmitry Osipenko wrote: > >> Prepare for addition of memory shrinker support by attaching shmem pages >> to host dynamically on first use. Previously the attachment vq command >> wasn't fenced and there was no vq kick made in the BO creation code path, >> hence the attachment already was happening dynamically, but implicitly. >> Making attachment explicitly dynamic will allow to simplify and reuse more >> code when shrinker will be added. The virtio_gpu_object_shmem_init() now >> works under the held reservation lock, which will be important to have for >> shrinker to avoid moving pages while they are in active use by the driver. > Ah, this commit might actually help getting rid of the workaround > introduced in "drm/shmem-helper: Add common memory shrinker". Not really. The virtio_gpu_free_object() is unchanged, it's only allocation that is being deferred and it's only done for a one BO type (virtio-gpu has multiple BO types). -- Best regards, Dmitry
Re: [PATCH] drm/rockchip: rk3066_hdmi: include drm/drm_atomic.h
On 11/22/23 14:18, Arnd Bergmann wrote: > From: Arnd Bergmann > > Without this header, the newly added code fails to build: > > drivers/gpu/drm/rockchip/rk3066_hdmi.c: In function > 'rk3066_hdmi_encoder_enable': > drivers/gpu/drm/rockchip/rk3066_hdmi.c:397:22: error: implicit declaration of > function 'drm_atomic_get_new_connector_state'; did you mean > 'drm_atomic_helper_connector_reset'? [-Werror=implicit-function-declaration] > 397 | conn_state = drm_atomic_get_new_connector_state(state, > >connector); > | ^~ > | drm_atomic_helper_connector_reset > drivers/gpu/drm/rockchip/rk3066_hdmi.c:397:20: error: assignment to 'struct > drm_connector_state *' from 'int' makes pointer from integer without a cast > [-Werror=int-conversion] > 397 | conn_state = drm_atomic_get_new_connector_state(state, > >connector); > |^ > drivers/gpu/drm/rockchip/rk3066_hdmi.c:401:22: error: implicit declaration of > function 'drm_atomic_get_new_crtc_state'; did you mean > 'drm_atomic_helper_swap_state'? [-Werror=implicit-function-declaration] > 401 | crtc_state = drm_atomic_get_new_crtc_state(state, > conn_state->crtc); > | ^ > | drm_atomic_helper_swap_state > drivers/gpu/drm/rockchip/rk3066_hdmi.c:401:20: error: assignment to 'struct > drm_crtc_state *' from 'int' makes pointer from integer without a cast > [-Werror=int-conversion] > 401 | crtc_state = drm_atomic_get_new_crtc_state(state, > conn_state->crtc); > |^ > > Fixes: ae3436a5e7c2 ("drm/rockchip: rk3066_hdmi: Switch encoder hooks to > atomic") > Signed-off-by: Arnd Bergmann Acked-by: Randy Dunlap Tested-by: Randy Dunlap # build-tested Thanks. > --- > drivers/gpu/drm/rockchip/rk3066_hdmi.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/gpu/drm/rockchip/rk3066_hdmi.c > b/drivers/gpu/drm/rockchip/rk3066_hdmi.c > index 0e7aae341960..7d561c5a650f 100644 > --- a/drivers/gpu/drm/rockchip/rk3066_hdmi.c > +++ b/drivers/gpu/drm/rockchip/rk3066_hdmi.c > @@ -4,6 +4,7 @@ > *Zheng Yang > */ > > +#include > #include > #include > #include -- ~Randy
Re: [PATCH v18 22/26] drm/shmem-helper: Don't free refcounted GEM
On 11/13/23 12:54, Boris Brezillon wrote: > On Mon, 30 Oct 2023 02:02:01 +0300 > Dmitry Osipenko wrote: > >> Don't free refcounted shmem object to prevent use-after-free bug that >> is worse than a memory leak. >> >> Signed-off-by: Dmitry Osipenko >> --- >> drivers/gpu/drm/drm_gem_shmem_helper.c | 7 --- >> 1 file changed, 4 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c >> b/drivers/gpu/drm/drm_gem_shmem_helper.c >> index 6dd087f19ea3..4253c367dc07 100644 >> --- a/drivers/gpu/drm/drm_gem_shmem_helper.c >> +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c >> @@ -203,9 +203,10 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object >> *shmem) >> if (obj->import_attach) >> drm_prime_gem_destroy(obj, shmem->sgt); >> >> -drm_WARN_ON(obj->dev, refcount_read(>vmap_use_count)); >> -drm_WARN_ON(obj->dev, refcount_read(>pages_use_count)); >> -drm_WARN_ON(obj->dev, refcount_read(>pages_pin_count)); >> +if (drm_WARN_ON(obj->dev, refcount_read(>vmap_use_count)) || >> +drm_WARN_ON(obj->dev, refcount_read(>pages_use_count)) || >> +drm_WARN_ON(obj->dev, refcount_read(>pages_pin_count))) >> +return; > > I guess you're worried about ->sgt being referenced by the driver after > the GEM is destroyed. If we assume drivers don't cache the sgt and > always call get_pages_sgt() when they need it that shouldn't be an > issue. What we really don't want to release is the pages themselves, > but the GPU MMU might still have active mappings pointing to these > pages. > > In any case, I'm not against leaking the GEM object when any of these > counters are not zero, but can we at least have a comment in the > code explaining why we're doing that, so people don't have to go look > at the git history to figure it out. This patch is a minor improvement, it doesn't address any specific issue. This should be a common pattern in kernel. If you're giving a warning and know about the inevitable catastrophe, then avoid it if you can. Actually, there are other similar cases in drm-shmem that can be improved. -- Best regards, Dmitry
[PATCH] drm/rockchip: rk3066_hdmi: include drm/drm_atomic.h
From: Arnd Bergmann Without this header, the newly added code fails to build: drivers/gpu/drm/rockchip/rk3066_hdmi.c: In function 'rk3066_hdmi_encoder_enable': drivers/gpu/drm/rockchip/rk3066_hdmi.c:397:22: error: implicit declaration of function 'drm_atomic_get_new_connector_state'; did you mean 'drm_atomic_helper_connector_reset'? [-Werror=implicit-function-declaration] 397 | conn_state = drm_atomic_get_new_connector_state(state, >connector); | ^~ | drm_atomic_helper_connector_reset drivers/gpu/drm/rockchip/rk3066_hdmi.c:397:20: error: assignment to 'struct drm_connector_state *' from 'int' makes pointer from integer without a cast [-Werror=int-conversion] 397 | conn_state = drm_atomic_get_new_connector_state(state, >connector); |^ drivers/gpu/drm/rockchip/rk3066_hdmi.c:401:22: error: implicit declaration of function 'drm_atomic_get_new_crtc_state'; did you mean 'drm_atomic_helper_swap_state'? [-Werror=implicit-function-declaration] 401 | crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); | ^ | drm_atomic_helper_swap_state drivers/gpu/drm/rockchip/rk3066_hdmi.c:401:20: error: assignment to 'struct drm_crtc_state *' from 'int' makes pointer from integer without a cast [-Werror=int-conversion] 401 | crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); |^ Fixes: ae3436a5e7c2 ("drm/rockchip: rk3066_hdmi: Switch encoder hooks to atomic") Signed-off-by: Arnd Bergmann --- drivers/gpu/drm/rockchip/rk3066_hdmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rockchip/rk3066_hdmi.c b/drivers/gpu/drm/rockchip/rk3066_hdmi.c index 0e7aae341960..7d561c5a650f 100644 --- a/drivers/gpu/drm/rockchip/rk3066_hdmi.c +++ b/drivers/gpu/drm/rockchip/rk3066_hdmi.c @@ -4,6 +4,7 @@ *Zheng Yang */ +#include #include #include #include -- 2.39.2
[PATCH] drm/amd/display: avoid stringop-overflow warnings for dp_decide_lane_settings()
From: Arnd Bergmann gcc prints a warning about a possible array overflow for a couple of callers of dp_decide_lane_settings() after commit 1b56c90018f0 ("Makefile: Enable -Wstringop-overflow globally"): drivers/gpu/drm/amd/amdgpu/../display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c: In function 'dp_perform_fixed_vs_pe_training_sequence_legacy': drivers/gpu/drm/amd/amdgpu/../display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c:426:25: error: 'dp_decide_lane_settings' accessing 4 bytes in a region of size 1 [-Werror=stringop-overflow=] 426 | dp_decide_lane_settings(lt_settings, dpcd_lane_adjust, | ^~ 427 | lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); | ~~~ drivers/gpu/drm/amd/amdgpu/../display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c:426:25: note: referencing argument 4 of type 'union dpcd_training_lane[4]' I'm not entirely sure what caused this, but changing the prototype to expect a pointer instead of an array avoids the warnings. Fixes: 7727e7b60f82 ("drm/amd/display: Improve robustness of FIXED_VS link training at DP1 rates") Signed-off-by: Arnd Bergmann --- .../gpu/drm/amd/display/dc/link/protocols/link_dp_training.c| 2 +- .../gpu/drm/amd/display/dc/link/protocols/link_dp_training.h| 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c index 90339c2dfd84..5a0b04518956 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c @@ -807,7 +807,7 @@ void dp_decide_lane_settings( const struct link_training_settings *lt_settings, const union lane_adjust ln_adjust[LANE_COUNT_DP_MAX], struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX], - union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX]) + union dpcd_training_lane *dpcd_lane_settings) { uint32_t lane; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h index 7d027bac8255..851bd17317a0 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h @@ -111,7 +111,7 @@ void dp_decide_lane_settings( const struct link_training_settings *lt_settings, const union lane_adjust ln_adjust[LANE_COUNT_DP_MAX], struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX], - union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX]); + union dpcd_training_lane *dpcd_lane_settings); enum dc_dp_training_pattern decide_cr_training_pattern( const struct dc_link_settings *link_settings); -- 2.39.2
Re: [PATCH v18 15/26] drm/panfrost: Explicitly get and put drm-shmem pages
On 11/10/23 13:53, Boris Brezillon wrote: > Hm, there was no drm_gem_shmem_get_pages_sgt() call here, why should we > add a drm_gem_shmem_get_pages()? What we should do instead is add a > drm_gem_shmem_get_pages() for each drm_gem_shmem_get_pages_sgt() we > have in the driver (in panfrost_mmu_map()), and add > drm_gem_shmem_put_pages() calls where they are missing > (panfrost_mmu_unmap()). > >> +if (err) >> +goto err_free; >> +} >> + >> return bo; >> + >> +err_free: >> +drm_gem_shmem_free(>base); >> + >> +return ERR_PTR(err); >> } >> >> struct drm_gem_object * >> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c >> b/drivers/gpu/drm/panfrost/panfrost_mmu.c >> index 770dab1942c2..ac145a98377b 100644 >> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c >> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c >> @@ -504,7 +504,7 @@ static int panfrost_mmu_map_fault_addr(struct >> panfrost_device *pfdev, int as, >> if (IS_ERR(pages[i])) { >> ret = PTR_ERR(pages[i]); >> pages[i] = NULL; >> -goto err_pages; >> +goto err_unlock; >> } >> } >> >> @@ -512,7 +512,7 @@ static int panfrost_mmu_map_fault_addr(struct >> panfrost_device *pfdev, int as, >> ret = sg_alloc_table_from_pages(sgt, pages + page_offset, >> NUM_FAULT_PAGES, 0, SZ_2M, GFP_KERNEL); >> if (ret) >> -goto err_pages; >> +goto err_unlock; > Feels like the panfrost_gem_mapping object should hold a ref on the BO > pages, not the BO itself, because, ultimately, the user of the BO is > the GPU. This matches what I was saying about moving get/put_pages() to > panfrost_mmu_map/unmap(): everytime a panfrost_gem_mapping becomes > active, to want to take a pages ref, every time it becomes inactive, > you should release the pages ref. The panfrost_mmu_unmap() is also used by shrinker when BO is purged. I'm unhappy with how icky it all becomes if unmap is made to put pages. Previously map() was implicitly allocating pages with get_sgt() and then pages were implicitly released by drm_gem_shmem_free(). A non-heap BO is mapped when it's created by Panfrost, hence the actual lifetime of pages is kept unchanged by this patch. The implicit allocation is turned into explicit one, i.e. pages are explicitly allocated before BO is mapped. -- Best regards, Dmitry
[PATCH v2 1/1] drm/i915/pxp: Add missing tag for Wa_14019159160
Add missing tag for "Wa_14019159160 - Case 2" (for existing PXP code that ensures run alone mode bit is set to allow PxP-decryption. v2: - Fix WA id number (John Harrison). - Improve comments and code to be specific for the targetted platforms (John Harrison) Signed-off-by: Alan Previn --- drivers/gpu/drm/i915/gt/intel_lrc.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 7c367ba8d9dc..2959dfed2aa0 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -863,11 +863,13 @@ static bool ctx_needs_runalone(const struct intel_context *ce) bool ctx_is_protected = false; /* -* On MTL and newer platforms, protected contexts require setting -* the LRC run-alone bit or else the encryption will not happen. +* Wa_14019159160 - Case 2: mtl +* On some platforms, protected contexts require setting +* the LRC run-alone bit or else the encryption/decryption will not happen. +* NOTE: Case 2 only applies to PXP use-case of said workaround. */ - if (GRAPHICS_VER_FULL(ce->engine->i915) >= IP_VER(12, 70) && - (ce->engine->class == COMPUTE_CLASS || ce->engine->class == RENDER_CLASS)) { + if (IS_METEORLAKE(ce->engine->i915) && (ce->engine->class == COMPUTE_CLASS || + ce->engine->class == RENDER_CLASS)) { rcu_read_lock(); gem_ctx = rcu_dereference(ce->gem_context); if (gem_ctx) base-commit: 5429d55de723544dfc0630cf39d96392052b27a1 -- 2.39.0
Re: [PATCH v9 0/4] drm: Add support for atomic async page-flip
Hi Hamza, Em 22/11/2023 17:23, Hamza Mahfooz escreveu: Hi André, On 11/22/23 11:19, André Almeida wrote: Hi, This work from me and Simon adds support for DRM_MODE_PAGE_FLIP_ASYNC through the atomic API. This feature is already available via the legacy API. The use case is to be able to present a new frame immediately (or as soon as possible), even if after missing a vblank. This might result in tearing, but it's useful when a high framerate is desired, such as for gaming. Differently from earlier versions, this one refuses to flip if any prop changes for async flips. The idea is that the fast path of immediate page flips doesn't play well with modeset changes, so only the fb_id can be changed. Tested with: - Intel TigerLake-LP GT2 - AMD VanGogh Have you had a chance to test this with VRR enabled? Since, I suspect this series might break that feature. Someone asked this question in an earlier version of this patch, and the result is that VRR still works as expected. You can follow the thread at this link: https://lore.kernel.org/lkml/b48bd1fc-fcb0-481b-8413-9210d44d7...@igalia.com/ I should have included this note at my cover letter, my bad. Thanks, André
Re: [PATCH v2 1/1] drm/msm/adreno: Add support for SM7150 SoC machine
On 10/16/23 16:32, Dmitry Baryshkov wrote: On 26/09/2023 23:03, Konrad Dybcio wrote: On 26.09.2023 21:10, Danila Tikhonov wrote: I think you mean by name downstream dt - sdmmagpie-gpu.dtsi You can see the forked version of the mainline here: https://github.com/sm7150-mainline/linux/blob/next/arch/arm64/boot/dts/qcom/sm7150.dtsi All fdt that we got here, if it is useful for you: https://github.com/sm7150-mainline/downstream-fdt Best wishes, Danila Taking a look at downstream, atoll.dtsi (SC7180) includes sdmmagpie-gpu.dtsi. Bottom line is, they share the speed bins, so it should be fine to just extend the existing entry. But then atoll.dtsi rewrites speed bins and pwrlevel bins. So they are not shared. +Akhil could you please check internally? Konrad
Re: [PATCH 1/3] riscv: Add support for kernel-mode FPU
Hi Samuel, kernel test robot noticed the following build errors: [auto build test ERROR on drm-misc/drm-misc-next] [also build test ERROR on linus/master v6.7-rc2 next-20231122] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Samuel-Holland/riscv-Add-support-for-kernel-mode-FPU/20231122-111015 base: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next patch link: https://lore.kernel.org/r/20231122030621.3759313-2-samuel.holland%40sifive.com patch subject: [PATCH 1/3] riscv: Add support for kernel-mode FPU config: riscv-allnoconfig (https://download.01.org/0day-ci/archive/20231123/202311230215.dbfywpqb-...@intel.com/config) compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project.git 4a5ac14ee968ff0ad5d2cc1ffa0299048db4c88a) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231123/202311230215.dbfywpqb-...@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot | Closes: https://lore.kernel.org/oe-kbuild-all/202311230215.dbfywpqb-...@intel.com/ All errors (new ones prefixed by >>): >> arch/riscv/kernel/process.c:229:19: error: use of undeclared identifier >> '__fstate_save' 229 | EXPORT_SYMBOL_GPL(__fstate_save); | ^ >> arch/riscv/kernel/process.c:230:19: error: use of undeclared identifier >> '__fstate_restore' 230 | EXPORT_SYMBOL_GPL(__fstate_restore); | ^ 2 errors generated. vim +/__fstate_save +229 arch/riscv/kernel/process.c 228 > 229 EXPORT_SYMBOL_GPL(__fstate_save); > 230 EXPORT_SYMBOL_GPL(__fstate_restore); -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Re: [PATCH v9 0/4] drm: Add support for atomic async page-flip
Hi André, On 11/22/23 11:19, André Almeida wrote: Hi, This work from me and Simon adds support for DRM_MODE_PAGE_FLIP_ASYNC through the atomic API. This feature is already available via the legacy API. The use case is to be able to present a new frame immediately (or as soon as possible), even if after missing a vblank. This might result in tearing, but it's useful when a high framerate is desired, such as for gaming. Differently from earlier versions, this one refuses to flip if any prop changes for async flips. The idea is that the fast path of immediate page flips doesn't play well with modeset changes, so only the fb_id can be changed. Tested with: - Intel TigerLake-LP GT2 - AMD VanGogh Have you had a chance to test this with VRR enabled? Since, I suspect this series might break that feature. Thanks, André - User-space patch: https://github.com/Plagman/gamescope/pull/595 - IGT tests: https://lore.kernel.org/all/20231110163811.24158-1-andrealm...@igalia.com/ Changes from v8: - Dropped atomic_async_page_flip_not_supported, giving that current design works with any driver that support atomic and async at the same time. - Dropped the patch that disabled atomic_async_page_flip_not_supported for AMD. - Reordered commits v8: https://lore.kernel.org/all/20231025005318.293690-1-andrealm...@igalia.com/ Changes from v7: - Only accept flips to primary planes. If a driver support flips in different planes, support will be added later. v7: https://lore.kernel.org/dri-devel/20231017092837.32428-1-andrealm...@igalia.com/ Changes from v6: - Dropped the exception to allow MODE_ID changes (Simon) - Clarify what happens when flipping with the same FB_ID (Pekka) v6: https://lore.kernel.org/dri-devel/20230815185710.159779-1-andrealm...@igalia.com/ Changes from v5: - Add note in the docs that not every redundant attribute will result in no-op, some might cause oversynchronization issues. v5: https://lore.kernel.org/dri-devel/20230707224059.305474-1-andrealm...@igalia.com/ Changes from v4: - Documentation rewrote by Pekka Paalanen v4: https://lore.kernel.org/dri-devel/20230701020917.143394-1-andrealm...@igalia.com/ Changes from v3: - Add new patch to reject prop changes - Add a documentation clarifying the KMS atomic state set v3: https://lore.kernel.org/dri-devel/20220929184307.258331-1-cont...@emersion.fr/ André Almeida (1): drm: Refuse to async flip with atomic prop changes Pekka Paalanen (1): drm/doc: Define KMS atomic state set Simon Ser (2): drm: allow DRM_MODE_PAGE_FLIP_ASYNC for atomic commits drm: introduce DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP Documentation/gpu/drm-uapi.rst | 47 ++ drivers/gpu/drm/drm_atomic_uapi.c | 77 ++--- drivers/gpu/drm/drm_crtc_internal.h | 2 +- drivers/gpu/drm/drm_ioctl.c | 4 ++ drivers/gpu/drm/drm_mode_object.c | 2 +- include/uapi/drm/drm.h | 10 +++- include/uapi/drm/drm_mode.h | 9 7 files changed, 142 insertions(+), 9 deletions(-) -- Hamza
Re: [PATCH -next] drm/nouveau/fifo: Remove duplicated include in chan.c
Reviewed-by: Lyude Paul Will push upstream in a moment On Wed, 2023-11-22 at 08:49 +0800, Yang Li wrote: > ./drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c: chid.h is included more > than once. > > Reported-by: Abaci Robot > Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=7603 > Signed-off-by: Yang Li > --- > drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 1 - > 1 file changed, 1 deletion(-) > > diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c > b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c > index 87a62d4ff4bd..7d4716dcd512 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c > +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c > @@ -24,7 +24,6 @@ > #include "chan.h" > #include "chid.h" > #include "cgrp.h" > -#include "chid.h" > #include "runl.h" > #include "priv.h" > -- Cheers, Lyude Paul (she/her) Software Engineer at Red Hat
Re: [PATCH v9 00/20] Imagination Technologies PowerVR DRM driver
Hi, On Wed, Nov 22, 2023 at 04:34:21PM +, Donald Robson wrote: > This patch series adds the initial DRM driver for Imagination Technologies > PowerVR > GPUs, starting with those based on our Rogue architecture. It's worth pointing > out that this is a new driver, written from the ground up, rather than a > refactored version of our existing downstream driver (pvrsrvkm). > > This new DRM driver supports: > - GEM shmem allocations > - dma-buf / PRIME > - Per-context userspace managed virtual address space > - DRM sync objects (binary and timeline) > - Power management suspend / resume > - GPU job submission (geometry, fragment, compute, transfer) > - META firmware processor > - MIPS firmware processor > - GPU hang detection and recovery > > Currently our main focus is on the AXE-1-16M GPU. Testing so far has been done > using a TI SK-AM62 board (AXE-1-16M GPU). The driver has also been confirmed > to > work on the BeaglePlay board. Firmware for the AXE-1-16M can be found here: > https://gitlab.freedesktop.org/frankbinns/linux-firmware/-/tree/powervr > > A Vulkan driver that works with our downstream kernel driver has already been > merged into Mesa [1][2]. Support for this new DRM driver is being maintained > in > a merge request [3], with the branch located here: > https://gitlab.freedesktop.org/frankbinns/mesa/-/tree/powervr-winsys > > Vulkan driver links referred to above: > [1] https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15243 > [2] > https://gitlab.freedesktop.org/mesa/mesa/-/tree/main/src/imagination/vulkan > [3] https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15507 > > Job stream formats are documented at: > https://gitlab.freedesktop.org/mesa/mesa/-/blob/f8d2b42ae65c2f16f36a43e0ae39d288431e4263/src/imagination/csbgen/rogue_kmd_stream.xml > > The Vulkan driver is progressing towards Vulkan 1.0. The current combination > of this > kernel driver with the Mesa Vulkan driver (powervr-mesa-next branch) > successfully > completes Vulkan CTS 1.3.4.1 in our local runs. The driver is expected to > pass the > Khronos Conformance Process once the submission is made. > > The code in this patch series, along with the needed dts changes can be found > here: > https://gitlab.freedesktop.org/frankbinns/powervr/-/tree/dev/v9_dts > The full development history can be found here: > https://gitlab.freedesktop.org/frankbinns/powervr/-/tree/powervr-next I just merged all the patches to drm-misc-next. Congrats :) Maxime signature.asc Description: PGP signature
Re: [PATCH v2 2/4] drm/prime: Helper to export dmabuf without fd
On 2023-11-22 05:32, Thomas Zimmermann wrote: Hi, my apologies if this sounds picky or annoying. This change appears to be going in the wrong direction. The goal of the refactoring is to be able to use drm_driver.gem_prime_import and drm_gem_object_funcs.export for the additional import/export code; and hence keep the GEM object code in a single place. Keeping the prime_fd file descriptor within amdkfd will likely help with that. Here's my suggestion: 1) Please keep the internal interfaces drm_gem_prime_handle_to_fd() and drm_gem_prime_fd_to_handle(). They should be called from the _ioctl entry functions as is. That could be stream-lined in a later patch set. 2) From drm_gem_prime_handle_to_fd() and drm_gem_prime_fd_to_handle(), create drm_gem_prime_handle_to_dmabuf() and drm_gem_prime_dmabuf_to_handle(). Do you mean duplicate the code, or call drm_gem_prime_handle_to_dmabuf from drm_gem_prime_handle_to_fd? They should be exported. You can then keep the file-descriptor code in amdkfd and out of the PRIME helpers. 3) Patches 1 and 2 should be squashed into one. 4) And if I'm not mistaken, the additional import/export code can then go into drm_driver.gem_prime_import and drm_gem_object_funcs.export, which are being called from within the PRIME helpers. I'm not sure what you mean by "additional import/export code" that would move into those driver callbacks. That's admittedly quite a bit of refactoring. OR simply go back to v1 of this patch set, which was consistent at least. I think I'd prefer that because I don't really understand what you're trying to achieve. Thanks, Felix Best regards Thomas Am 22.11.23 um 00:11 schrieb Felix Kuehling: Change drm_gem_prime_handle_to_fd to drm_gem_prime_handle_to_dmabuf to export a dmabuf without creating an FD as a user mode handle. This is more useful for users in kernel mode. Suggested-by: Thomas Zimmermann Signed-off-by: Felix Kuehling --- drivers/gpu/drm/drm_prime.c | 63 ++--- include/drm/drm_prime.h | 6 ++-- 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 834a5e28abbe..d491b5f73eea 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -410,26 +410,25 @@ static struct dma_buf *export_and_register_object(struct drm_device *dev, } /** - * drm_gem_prime_handle_to_fd - PRIME export function for GEM drivers + * drm_gem_prime_handle_to_dmabuf - PRIME export function for GEM drivers * @dev: dev to export the buffer from * @file_priv: drm file-private structure * @handle: buffer handle to export * @flags: flags like DRM_CLOEXEC - * @prime_fd: pointer to storage for the fd id of the create dma-buf + * @dma_buf: pointer to storage for the dma-buf reference * * This is the PRIME export function which must be used mandatorily by GEM * drivers to ensure correct lifetime management of the underlying GEM object. * The actual exporting from GEM object to a dma-buf is done through the * _gem_object_funcs.export callback. */ -int drm_gem_prime_handle_to_fd(struct drm_device *dev, - struct drm_file *file_priv, uint32_t handle, - uint32_t flags, - int *prime_fd) +struct dma_buf *drm_gem_prime_handle_to_dmabuf(struct drm_device *dev, + struct drm_file *file_priv, + uint32_t handle, uint32_t flags) { struct drm_gem_object *obj; int ret = 0; - struct dma_buf *dmabuf; + struct dma_buf *dmabuf = NULL; mutex_lock(_priv->prime.lock); obj = drm_gem_object_lookup(file_priv, handle); @@ -441,7 +440,7 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev, dmabuf = drm_prime_lookup_buf_by_handle(_priv->prime, handle); if (dmabuf) { get_dma_buf(dmabuf); - goto out_have_handle; + goto out; } mutex_lock(>object_name_lock); @@ -479,40 +478,22 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev, dmabuf, handle); mutex_unlock(>object_name_lock); if (ret) - goto fail_put_dmabuf; - -out_have_handle: - ret = dma_buf_fd(dmabuf, flags); - /* -* We must _not_ remove the buffer from the handle cache since the newly -* created dma buf is already linked in the global obj->dma_buf pointer, -* and that is invariant as long as a userspace gem handle exists. -* Closing the handle will clean out the cache anyway, so we don't leak. -*/ - if (ret < 0) { - goto fail_put_dmabuf; - } else { - *prime_fd = ret; - ret = 0; - } - - goto out; - -fail_put_dmabuf: -
[PATCH v5] drm/i915/pxp: Add drm_dbgs for critical PXP events.
Debugging PXP issues can't even begin without understanding precedding sequence of important events. Add drm_dbg into the most important PXP events. v5 : - rebase. v4 : - rebase. v3 : - move gt_dbg to after mutex block in function i915_gsc_proxy_component_bind. (Vivaik) v2 : - remove __func__ since drm_dbg covers that (Jani). - add timeout dbg of the restart from front-end (Alan). Signed-off-by: Alan Previn Reviewed-by: Vivaik Balasubrawmanian --- drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c | 2 ++ drivers/gpu/drm/i915/pxp/intel_pxp.c | 15 --- drivers/gpu/drm/i915/pxp/intel_pxp_irq.c | 5 +++-- drivers/gpu/drm/i915/pxp/intel_pxp_session.c | 6 +- drivers/gpu/drm/i915/pxp/intel_pxp_types.h | 1 + 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c index 5f138de3c14f..40817ebcca71 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c @@ -322,6 +322,7 @@ static int i915_gsc_proxy_component_bind(struct device *i915_kdev, gsc->proxy.component = data; gsc->proxy.component->mei_dev = mei_kdev; mutex_unlock(>proxy.mutex); + gt_dbg(gt, "GSC proxy mei component bound\n"); return 0; } @@ -342,6 +343,7 @@ static void i915_gsc_proxy_component_unbind(struct device *i915_kdev, with_intel_runtime_pm(>runtime_pm, wakeref) intel_uncore_rmw(gt->uncore, HECI_H_CSR(MTL_GSC_HECI2_BASE), HECI_H_CSR_IE | HECI_H_CSR_RST, 0); + gt_dbg(gt, "GSC proxy mei component unbound\n"); } static const struct component_ops i915_gsc_proxy_component_ops = { diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c b/drivers/gpu/drm/i915/pxp/intel_pxp.c index dc327cf40b5a..e11f562b1876 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c @@ -303,6 +303,8 @@ static int __pxp_global_teardown_final(struct intel_pxp *pxp) if (!pxp->arb_is_valid) return 0; + + drm_dbg(>ctrl_gt->i915->drm, "PXP: teardown for suspend/fini"); /* * To ensure synchronous and coherent session teardown completion * in response to suspend or shutdown triggers, don't use a worker. @@ -324,6 +326,8 @@ static int __pxp_global_teardown_restart(struct intel_pxp *pxp) if (pxp->arb_is_valid) return 0; + + drm_dbg(>ctrl_gt->i915->drm, "PXP: teardown for restart"); /* * The arb-session is currently inactive and we are doing a reset and restart * due to a runtime event. Use the worker that was designed for this. @@ -332,8 +336,11 @@ static int __pxp_global_teardown_restart(struct intel_pxp *pxp) timeout = intel_pxp_get_backend_timeout_ms(pxp); - if (!wait_for_completion_timeout(>termination, msecs_to_jiffies(timeout))) + if (!wait_for_completion_timeout(>termination, msecs_to_jiffies(timeout))) { + drm_dbg(>ctrl_gt->i915->drm, "PXP: restart backend timed out (%d ms)", + timeout); return -ETIMEDOUT; + } return 0; } @@ -414,10 +421,12 @@ int intel_pxp_start(struct intel_pxp *pxp) int ret = 0; ret = intel_pxp_get_readiness_status(pxp, PXP_READINESS_TIMEOUT); - if (ret < 0) + if (ret < 0) { + drm_dbg(>ctrl_gt->i915->drm, "PXP: tried but not-avail (%d)", ret); return ret; - else if (ret > 1) + } else if (ret > 1) { return -EIO; /* per UAPI spec, user may retry later */ + } mutex_lock(>arb_mutex); diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_irq.c b/drivers/gpu/drm/i915/pxp/intel_pxp_irq.c index 91e9622c07d0..d81750b9bdda 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_irq.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_irq.c @@ -40,11 +40,12 @@ void intel_pxp_irq_handler(struct intel_pxp *pxp, u16 iir) GEN12_DISPLAY_APP_TERMINATED_PER_FW_REQ_INTERRUPT)) { /* immediately mark PXP as inactive on termination */ intel_pxp_mark_termination_in_progress(pxp); - pxp->session_events |= PXP_TERMINATION_REQUEST | PXP_INVAL_REQUIRED; + pxp->session_events |= PXP_TERMINATION_REQUEST | PXP_INVAL_REQUIRED | + PXP_EVENT_TYPE_IRQ; } if (iir & GEN12_DISPLAY_STATE_RESET_COMPLETE_INTERRUPT) - pxp->session_events |= PXP_TERMINATION_COMPLETE; + pxp->session_events |= PXP_TERMINATION_COMPLETE | PXP_EVENT_TYPE_IRQ; if (pxp->session_events) queue_work(system_unbound_wq, >session_work); diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c index 0a3e66b0265e..091c86e03d1a 100644 ---
Re: [PATCH v2 09/12] dt-bindings: soc: vop2: Add more endpoint definition
On 22/11/2023 13:55, Andy Yan wrote: > From: Andy Yan > > There are 2 HDMI, 2 DP, 2 eDP on rk3588, so add > corresponding endpoint definition for it. Please wrap commit message according to Linux coding style / submission process (neither too early nor over the limit): https://elixir.bootlin.com/linux/v6.4-rc1/source/Documentation/process/submitting-patches.rst#L597 Subject: dt-bindings: soc: rockchip,vop2: or dt-bindings: rockchip,vop2: Acked-by: Krzysztof Kozlowski --- This is an automated instruction, just in case, because many review tags are being ignored. If you know the process, you can skip it (please do not feel offended by me posting it here - no bad intentions intended). If you do not know the process, here is a short explanation: Please add Acked-by/Reviewed-by/Tested-by tags when posting new versions, under or above your Signed-off-by tag. Tag is "received", when provided in a message replied to you on the mailing list. Tools like b4 can help here. However, there's no need to repost patches *only* to add the tags. The upstream maintainer will do that for tags received on the version they apply. https://elixir.bootlin.com/linux/v6.5-rc3/source/Documentation/process/submitting-patches.rst#L577 Best regards, Krzysztof
Re: [PATCH v2 08/12] dt-bindings: display: vop2: Add rk3588 support
On 22/11/2023 13:55, Andy Yan wrote: > From: Andy Yan > > The vop2 on rk3588 is similar to which on rk356x > but with 4 video ports and need to reference > more grf modules. > > Signed-off-by: Andy Yan > > --- > > Changes in v2: > - fix errors when running 'make DT_CHECKER_FLAGS=-m dt_binding_check' > > .../display/rockchip/rockchip-vop2.yaml | 27 +++ > 1 file changed, 27 insertions(+) > > diff --git > a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml > b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml > index b60b90472d42..24148d9b3b14 100644 > --- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml > +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml > @@ -20,6 +20,7 @@ properties: > enum: >- rockchip,rk3566-vop >- rockchip,rk3568-vop > + - rockchip,rk3588-vop > >reg: > items: > @@ -42,26 +43,47 @@ properties: >frame start (VSYNC), line flag and other status interrupts. > >clocks: > +minItems: 3 > items: >- description: Clock for ddr buffer transfer. >- description: Clock for the ahb bus to R/W the phy regs. >- description: Pixel clock for video port 0. >- description: Pixel clock for video port 1. >- description: Pixel clock for video port 2. > + - description: Pixel clock for video port 4. > + - description: Peripheral clock for vop on rk3588. > >clock-names: > +minItems: 3 You relax requirements for all existing variants here which is not explained in commit msg. I assume this was not intentional, so you need to re-constrain them in allOf:if:then. See for example: https://elixir.bootlin.com/linux/v5.19-rc6/source/Documentation/devicetree/bindings/clock/samsung,exynos7-clock.yaml#L57 for some ideas. > items: >- const: aclk >- const: hclk >- const: dclk_vp0 >- const: dclk_vp1 >- const: dclk_vp2 > + - const: dclk_vp3 > + - const: pclk_vop > >rockchip,grf: > $ref: /schemas/types.yaml#/definitions/phandle > description: >Phandle to GRF regs used for misc control > > + rockchip,vo-grf: > +$ref: /schemas/types.yaml#/definitions/phandle > +description: > + Phandle to VO GRF regs used for misc control, required for rk3588 Drop last sentence, instead add it to required in allOf:if:then. Is this valid for other variants? If not, should be disallowed in allOf:if:then: for them. > + > + rockchip,vop-grf: > +$ref: /schemas/types.yaml#/definitions/phandle > +description: > + Phandle to VOP GRF regs used for misc control, required for rk3588 > + > + rockchip,pmu: > +$ref: /schemas/types.yaml#/definitions/phandle > +description: > + Phandle to PMU regs used for misc control, required for rk3588 For all these three: what is "misc control"? Way too vague. Everything is a misc and everything can be control. You must be here specific and much more descriptive. > + >ports: > $ref: /schemas/graph.yaml#/properties/ports > > @@ -81,6 +103,11 @@ properties: > description: >Output endpoint of VP2 > > + port@3: > +$ref: /schemas/graph.yaml#/properties/port > +description: > + Output endpoint of VP3 Valid for other variants? Best regards, Krzysztof
Re: [PATCH] dma-buf: Correct the documentation of name and exp_name symbols
Am 22.11.23 um 17:05 schrieb Ramesh Errabolu: Fix the documentation of struct dma_buf members name and exp_name as to how these members are to be used and accessed. Signed-off-by: Ramesh Errabolu Reviewed-by: Christian König --- include/linux/dma-buf.h | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 3f31baa3293f..8ff4add71f88 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -343,16 +343,19 @@ struct dma_buf { /** * @exp_name: * -* Name of the exporter; useful for debugging. See the -* DMA_BUF_SET_NAME IOCTL. +* Name of the exporter; useful for debugging. Must not be NULL */ const char *exp_name; /** * @name: * -* Userspace-provided name; useful for accounting and debugging, -* protected by dma_resv_lock() on @resv and @name_lock for read access. +* Userspace-provided name. Default value is NULL. If not NULL, +* length cannot be longer than DMA_BUF_NAME_LEN, including NIL +* char. Useful for accounting and debugging. Read/Write accesses +* are protected by @name_lock +* +* See the IOCTLs DMA_BUF_SET_NAME or DMA_BUF_SET_NAME_A/B */ const char *name;
Re: Implement per-key keyboard backlight as auxdisplay?
Hi Werner, On 11/21/23 14:29, Werner Sembach wrote: > > Am 21.11.23 um 13:20 schrieb Hans de Goede: >> Hi Werner, >> >> On 11/21/23 12:33, Werner Sembach wrote: >>> Hi, >>> >>> Am 20.11.23 um 21:52 schrieb Pavel Machek: Hi! >>> So... a bit of rationale. The keyboard does not really fit into the >>> LED subsystem; LEDs are expected to be independent ("hdd led") and not >>> a matrix of them. >> Makes sense. >> >>> We do see various strange displays these days -- they commonly have >>> rounded corners and holes in them. I'm not sure how that's currently >>> supported, but I believe it is reasonable to view keyboard as a >>> display with slightly weird placing of pixels. >>> >>> Plus, I'd really like to play tetris on one of those :-). >>> >>> So, would presenting them as auxdisplay be acceptable? Or are there >>> better options? >> It sounds like a fair use case -- auxdisplay are typically simple >> character-based or small graphical displays, e.g. 128x64, that may not >> be a "main" / usual screen as typically understood, but the concept is >> a bit fuzzy and we are a bit of a catch-all. >> >> And "keyboard backlight display with a pixel/color per-key" does not >> sound like a "main" screen, and having some cute effects displayed >> there are the kind of thing that one could do in the usual small >> graphical ones too. :) >> >> But if somebody prefers to create new categories (or subcategories >> within auxdisplay) to hold these, that could be nice too (in the >> latter case, I would perhaps suggest reorganizing all of the existing >> ones while at it). > One could also reasonably make the argument that controlling the > individual keyboard key backlights should be part of the input > subsystem. It's not a display per se. (Unless you actually have small > displays on the keycaps, and I think that's a thing too.) While it would not be completely crazy to do that... I believe the backlight is more of a display and less of a keyboard. Plus input subystem is very far away from supporting this, and we had no input from input people here. I don't think LED subsystem is right place for this, and I believe auxdisplay makes slightly more sense than input. Unless someone steps up, I'd suggest Werner tries to implement this as an auxdisplay. [And yes, this will not be simple task. RGB on LED is different from RGB on display. But there are other LED displays, so auxdisplay should handle this. Plus pixels are really funnily shaped. But displays with missing pixels -- aka holes for camera -- are common in phones, and I believe we'll get variable pixel densities -- less dense over camera -- too. So displays will have to deal with these in the end.] >>> Another idea I want to throw in the mix: >>> >>> Maybe the kernel is not the right place to implement this at all. RGB stuff >>> is not at all standardized and every vendor is doing completely different >>> interfaces, which does not fit the kernel userpsace apis desire to be >>> uniformal and fixed. e.g. Auxdisplay might fit static setting of RGB >>> values, but it does not fit the snake-effect mode, or the raindrops mode, >>> or the 4-different-colors-in-the-edges-breathing-and-color-cycling mode. >>> >>> So my current idea: Implement these keyboards as a single zone RGB >>> kbd_backlight in the leds interface to have something functional out of the >>> box, but make it runtime disable-able if something like >>> https://gitlab.com/CalcProgrammer1/OpenRGB wants to take over more fine >>> granular control from userspace via hidraw. >> That sounds like a good approach to me. We are seeing the same with game >> controllers where steam and wine/proton also sometimes use hidraw mode to >> get access to all the crazy^W interesting features. >> >> That would mean that all we need to standardize and the kernel <-> userspace >> API level is adding a standard way to disable the single zone RGB >> kbd_backlight support in the kernel. > > I would suggest a simple "enable" entry. Default is 1. When set to 0 the > kernel driver no longer does anything. I'm not in favor of using "enable" as sysfs attribute for this, I would like to see a more descriptive name, how about: "disable_kernel_kbd_backlight_support" And then maybe also have the driver actually unregister the LED class device ? Or just make the support inactive when writing 1 to this and allow re-enabling it by writing 0? > Questions: > > - Should the driver try to reset the settings to boot default? Or just leave > the device in the current state? With the former I could see issues that they > keyboard is flashing when changing from kernelspace control to userspace > control. With the later the burden on bringing the device to a know state > lies with the userspace driver. My vote would
Re: [PATCH v6 0/6] drm: simplify support for transparent DRM bridges
On Wed, 22 Nov 2023 at 18:03, Sui Jingfeng wrote: > > Hi, > > > On 2023/11/4 07:03, Dmitry Baryshkov wrote: > > Supporting DP/USB-C can result in a chain of several transparent > > bridges (PHY, redrivers, mux, etc). All attempts to implement DP support > > in a different way resulted either in series of hacks or in device tree > > not reflecting the actual hardware design. This results in drivers > > having similar boilerplate code for such bridges. > > Please improve the written, "resulted" -> "yield" ? > > > Next, these drivers are susceptible to -EPROBE_DEFER loops: the next > > bridge can either be probed from the bridge->attach callback, when it is > > too late to return -EPROBE_DEFER, or from the probe() callback, when the > > next bridge might not yet be available, because it depends on the > > resources provided by the probing device. Device links can not fully > > solve this problem since there are mutual dependencies between adjancent > > devices. > > > > Last, but not least, this results in the the internal knowledge of DRM > > There is a duplicated "the" word in this sentence. > > As far as I can understand, nearly all of those troubles are because the > display bridges > drivers are designed as a kernel module(.ko) instead of making them as static > link-able > helpers. I means that a display bridge device can not work standalone, as it > have to be > used with a display controller. So a display bridge is just a slave device or > a auxiliary > device. My question is: if it can't works by itself, we probably shouldn't > design them as > kernel modules style. Am I correct? No. This has nothing to do with the driver being a kernel module or built-in. > > > subsystem slowly diffusing into other subsystems, like PHY or USB/TYPEC. > > Yeah, this indeed a problem. > > > To solve all these issues, define a separate DRM helper, which creates > > separate aux device just for the bridge. > > I'm supporting you if want to solve all these problems, this is fine and > thanks a lot. > But I want to ask a question, now that you are solving these problems by > creating separate > devices, does this manner match the hardware design perfectly? which is the > hardware units > you newly created device is corresponding to? Aux devices do not always follow the actual hardware internals. For example, see the TI sn65dsi86 driver, which also uses aux devices to split dependency and probing chains. > > During probe such aux device > > doesn't result in the EPROBE_DEFER loops. Instead it allows the device > > drivers to probe properly, according to the actual resource > > dependencies. The bridge auxdevs are then probed when the next bridge > > becomes available, sparing drivers from drm_bridge_attach() returning > > -EPROBE_DEFER. > > OK, as far as I can understand, in order to solve the mentioned problem > you are also retire the defer probe mechanism. No, I'm not retiring the probe deferral mechanism. Instead I'm splitting it into two chains. One going from the controller to the usb-c connector for the signal flow, another going from the connector back to the drm_encoder for the drm_bridge dependencies. > > > > Changes since v5: > > - Removed extra semicolon in !DRM_AUX_HPD_BRIDGE stubs definition. > > > > Changes since v4: > > - Added documentation for new API (Sima) > > - Added generic code to handle "last mile" DP bridges implementing just > > the HPD functionality. > > - Rebased on top of linux-next to be able to drop #ifdef's around > > drm_bridge->of_node > > > > Changes since v3: > > - Moved bridge driver to gpu/drm/bridge (Neil Armstrong) > > - Renamed it to aux-bridge (since there is already a simple_bridge driver) > > - Made CONFIG_OF mandatory for this driver (Neil Armstrong) > > - Added missing kfree and ida_free (Dan Carpenter) > > > > Changes since v2: > > - ifdef'ed bridge->of_node access (LKP) > > > > Changes since v1: > > - Added EXPORT_SYMBOL_GPL / MODULE_LICENSE / etc. to drm_simple_bridge > > > > Dmitry Baryshkov (6): > >drm/bridge: add transparent bridge helper > >phy: qcom: qmp-combo: switch to DRM_AUX_BRIDGE > >usb: typec: nb7vpq904m: switch to DRM_AUX_BRIDGE > >drm/bridge: implement generic DP HPD bridge > >soc: qcom: pmic-glink: switch to DRM_AUX_HPD_BRIDGE > >usb: typec: qcom-pmic-typec: switch to DRM_AUX_HPD_BRIDGE > > > > drivers/gpu/drm/bridge/Kconfig| 17 ++ > > drivers/gpu/drm/bridge/Makefile | 2 + > > drivers/gpu/drm/bridge/aux-bridge.c | 140 +++ > > drivers/gpu/drm/bridge/aux-hpd-bridge.c | 164 ++ > > drivers/phy/qualcomm/Kconfig | 2 +- > > drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 44 + > > drivers/soc/qcom/Kconfig | 1 + > > drivers/soc/qcom/pmic_glink_altmode.c | 33 +--- > > drivers/usb/typec/mux/Kconfig | 2 +- > >
Re: [PATCH 04/14] drm/i915: Include
On Wed, 22 Nov 2023, Thomas Zimmermann wrote: > One of the source files includes via , > which will be removed. Include drm_auth.h directly. > > Signed-off-by: Thomas Zimmermann > Cc: Jani Nikula > Cc: Joonas Lahtinen > Cc: Rodrigo Vivi > Cc: Tvrtko Ursulin > Cc: intel-...@lists.freedesktop.org Acked-by: Jani Nikula > --- > drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > index b1aa62dfb155d..81a57dd52dfda 100644 > --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > @@ -9,6 +9,7 @@ > #include > #include > > +#include > #include > > #include "display/intel_frontbuffer.h" -- Jani Nikula, Intel
Re: [v6,1/6] drm/bridge: add transparent bridge helper
Hi, On 2023/11/4 07:03, Dmitry Baryshkov wrote: Define a helper for creating simple transparent bridges which serve the only purpose of linking devices into the bridge chain up to the last bridge representing the connector. As far as I can tell, traditionally, transparent display bridges are used to refer to the hardware encoders which transform the video signals. Such as ADV7123/ADV7125(RGB888 to VGA), TFP410 (RGB888 to DVI) etc. Which can be used without the need of software configuration. TFP410 is a little bit special, it can be configured by I2C interface, but TFP410 don't support read edid for the monitor. But at the least, there do has a corresponding *hardware entity* working in the chains. It is just that it don't need a driver to configure. Does the "simple transparent bridges" you created has a corresponding hardware entity? Are you trying to solve software side problems by abusing the device-driver model? I'm afraid that the written "simple transparent bridges" is not a accurate description if you don't really has a hardware entity to corresponding with. Because all of the classic drm display bridges are able to transform transfer/consume video(and/or audio) data. Well, the device you create just can't. Probably, you should call it as "simple auxiliary device". This is especially useful for DP/USB-C bridge chains, which can span across several devices, but do not require any additional functionality from the intermediate bridges. Signed-off-by: Dmitry Baryshkov Reviewed-by: Neil Armstrong --- drivers/gpu/drm/bridge/Kconfig | 9 ++ drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/aux-bridge.c | 140 include/drm/bridge/aux-bridge.h | 19 4 files changed, 169 insertions(+) create mode 100644 drivers/gpu/drm/bridge/aux-bridge.c create mode 100644 include/drm/bridge/aux-bridge.h diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index ba82a1142adf..f12eab62799f 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -12,6 +12,15 @@ config DRM_PANEL_BRIDGE help DRM bridge wrapper of DRM panels +config DRM_AUX_BRIDGE + tristate + depends on DRM_BRIDGE && OF + select AUXILIARY_BUS + select DRM_PANEL_BRIDGE + help + Simple transparent bridge that is used by several non-DRM drivers to + build bridges chain. + menu "Display Interface Bridges" depends on DRM && DRM_BRIDGE diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 2b892b7ed59e..918e3bfff079 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_DRM_AUX_BRIDGE) += aux-bridge.o obj-$(CONFIG_DRM_CHIPONE_ICN6211) += chipone-icn6211.o obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o obj-$(CONFIG_DRM_CROS_EC_ANX7688) += cros-ec-anx7688.o diff --git a/drivers/gpu/drm/bridge/aux-bridge.c b/drivers/gpu/drm/bridge/aux-bridge.c new file mode 100644 index ..6245976b8fef --- /dev/null +++ b/drivers/gpu/drm/bridge/aux-bridge.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Linaro Ltd. + * + * Author: Dmitry Baryshkov + */ +#include +#include + +#include +#include + +static DEFINE_IDA(drm_aux_bridge_ida); + +static void drm_aux_bridge_release(struct device *dev) +{ + struct auxiliary_device *adev = to_auxiliary_dev(dev); + + ida_free(_aux_bridge_ida, adev->id); + + kfree(adev); +} + +static void drm_aux_bridge_unregister_adev(void *_adev) +{ + struct auxiliary_device *adev = _adev; It seems that the single underscore(prefix) at here is a little bit not good in looking, please replace it with 'void *data'. + + auxiliary_device_delete(adev); + auxiliary_device_uninit(adev); +} + +/** + * drm_aux_bridge_register - Create a simple bridge device to link the chain + * @parent: device instance providing this bridge + * + * Creates a simple DRM bridge that doesn't implement any drm_bridge + * operations. Such bridges merely fill a place in the bridge chain linking + * surrounding DRM bridges. + * + * Return: zero on success, negative error code on failure + */ +int drm_aux_bridge_register(struct device *parent) +{ + struct auxiliary_device *adev; + int ret; + + adev = kzalloc(sizeof(*adev), GFP_KERNEL); + if (!adev) + return -ENOMEM; + + ret = ida_alloc(_aux_bridge_ida, GFP_KERNEL); + if (ret < 0) { + kfree(adev); + return ret; + } + + adev->id = ret; + adev->name = "aux_bridge"; + adev->dev.parent = parent; + adev->dev.of_node = parent->of_node; + adev->dev.release = drm_aux_bridge_release; + + ret = auxiliary_device_init(adev); + if (ret) { + ida_free(_aux_bridge_ida,
[PATCH v9 20/20] drm/imagination: Add driver documentation
From: Sarah Walker Add documentation for the UAPI. Changes since v5: - Remove obsolete VM documentation Co-developed-by: Matt Coster Signed-off-by: Matt Coster Co-developed-by: Donald Robson Signed-off-by: Donald Robson Signed-off-by: Sarah Walker Reviewed-by: Maxime Ripard --- Documentation/gpu/drivers.rst | 2 + Documentation/gpu/imagination/index.rst | 13 ++ Documentation/gpu/imagination/uapi.rst | 174 MAINTAINERS | 1 + 4 files changed, 190 insertions(+) create mode 100644 Documentation/gpu/imagination/index.rst create mode 100644 Documentation/gpu/imagination/uapi.rst diff --git a/Documentation/gpu/drivers.rst b/Documentation/gpu/drivers.rst index 45a12e552091..cc6535f5f28c 100644 --- a/Documentation/gpu/drivers.rst +++ b/Documentation/gpu/drivers.rst @@ -3,9 +3,11 @@ GPU Driver Documentation .. toctree:: + :maxdepth: 3 amdgpu/index i915 + imagination/index mcde meson pl111 diff --git a/Documentation/gpu/imagination/index.rst b/Documentation/gpu/imagination/index.rst new file mode 100644 index ..dc9579e758c3 --- /dev/null +++ b/Documentation/gpu/imagination/index.rst @@ -0,0 +1,13 @@ +=== +drm/imagination PowerVR Graphics Driver +=== + +.. kernel-doc:: drivers/gpu/drm/imagination/pvr_drv.c + :doc: PowerVR Graphics Driver + +Contents + +.. toctree:: + :maxdepth: 2 + + uapi diff --git a/Documentation/gpu/imagination/uapi.rst b/Documentation/gpu/imagination/uapi.rst new file mode 100644 index ..2227ea7e6222 --- /dev/null +++ b/Documentation/gpu/imagination/uapi.rst @@ -0,0 +1,174 @@ + +UAPI + +The sources associated with this section can be found in ``pvr_drm.h``. + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :doc: PowerVR UAPI + +OBJECT ARRAYS += +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: drm_pvr_obj_array + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: DRM_PVR_OBJ_ARRAY + +IOCTLS +== +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :doc: PowerVR IOCTL interface + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: PVR_IOCTL + +DEV_QUERY +- +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :doc: PowerVR IOCTL DEV_QUERY interface + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: drm_pvr_dev_query + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: drm_pvr_ioctl_dev_query_args + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: drm_pvr_dev_query_gpu_info + drm_pvr_dev_query_runtime_info + drm_pvr_dev_query_hwrt_info + drm_pvr_dev_query_quirks + drm_pvr_dev_query_enhancements + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: drm_pvr_heap_id + drm_pvr_heap + drm_pvr_dev_query_heap_info + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :doc: Flags for DRM_PVR_DEV_QUERY_HEAP_INFO_GET. + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: drm_pvr_static_data_area_usage + drm_pvr_static_data_area + drm_pvr_dev_query_static_data_areas + +CREATE_BO +- +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :doc: PowerVR IOCTL CREATE_BO interface + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: drm_pvr_ioctl_create_bo_args + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :doc: Flags for CREATE_BO + +GET_BO_MMAP_OFFSET +-- +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :doc: PowerVR IOCTL GET_BO_MMAP_OFFSET interface + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: drm_pvr_ioctl_get_bo_mmap_offset_args + +CREATE_VM_CONTEXT and DESTROY_VM_CONTEXT + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :doc: PowerVR IOCTL CREATE_VM_CONTEXT and DESTROY_VM_CONTEXT interfaces + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: drm_pvr_ioctl_create_vm_context_args + drm_pvr_ioctl_destroy_vm_context_args + +VM_MAP and VM_UNMAP +--- +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :doc: PowerVR IOCTL VM_MAP and VM_UNMAP interfaces + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: drm_pvr_ioctl_vm_map_args + drm_pvr_ioctl_vm_unmap_args + +CREATE_CONTEXT and DESTROY_CONTEXT +-- +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :doc: PowerVR IOCTL CREATE_CONTEXT and DESTROY_CONTEXT interfaces + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: drm_pvr_ioctl_create_context_args + +.. kernel-doc:: include/uapi/drm/pvr_drm.h + :identifiers: drm_pvr_ctx_priority + drm_pvr_ctx_type + drm_pvr_static_render_context_state + drm_pvr_static_render_context_state_format +
[PATCH v9 19/20] drm/imagination: Add firmware trace to debugfs
From: Sarah Walker Firmware trace is exposed at /sys/debug/dri//pvr_fw/trace_0. Trace is enabled via the group mask at /sys/debug/dri//pvr_params/fw_trace_mask. Changes since v8: - Corrected license identifiers Changes since v3: - Use drm_dev_{enter,exit} Co-developed-by: Matt Coster Signed-off-by: Matt Coster Signed-off-by: Sarah Walker Signed-off-by: Donald Robson --- drivers/gpu/drm/imagination/Makefile | 4 + drivers/gpu/drm/imagination/pvr_debugfs.c | 53 +++ drivers/gpu/drm/imagination/pvr_debugfs.h | 29 ++ drivers/gpu/drm/imagination/pvr_device.c | 9 + drivers/gpu/drm/imagination/pvr_device.h | 10 + drivers/gpu/drm/imagination/pvr_drv.c | 4 + drivers/gpu/drm/imagination/pvr_fw_trace.c | 395 + drivers/gpu/drm/imagination/pvr_params.c | 147 drivers/gpu/drm/imagination/pvr_params.h | 72 9 files changed, 723 insertions(+) create mode 100644 drivers/gpu/drm/imagination/pvr_debugfs.c create mode 100644 drivers/gpu/drm/imagination/pvr_debugfs.h create mode 100644 drivers/gpu/drm/imagination/pvr_params.c create mode 100644 drivers/gpu/drm/imagination/pvr_params.h diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile index 7e3515c99caa..ec6db8e9b403 100644 --- a/drivers/gpu/drm/imagination/Makefile +++ b/drivers/gpu/drm/imagination/Makefile @@ -20,6 +20,7 @@ powervr-y := \ pvr_hwrt.o \ pvr_job.o \ pvr_mmu.o \ + pvr_params.o \ pvr_power.o \ pvr_queue.o \ pvr_stream.o \ @@ -28,4 +29,7 @@ powervr-y := \ pvr_vm.o \ pvr_vm_mips.o +powervr-$(CONFIG_DEBUG_FS) += \ + pvr_debugfs.o + obj-$(CONFIG_DRM_POWERVR) += powervr.o diff --git a/drivers/gpu/drm/imagination/pvr_debugfs.c b/drivers/gpu/drm/imagination/pvr_debugfs.c new file mode 100644 index ..6b77c9b4bde8 --- /dev/null +++ b/drivers/gpu/drm/imagination/pvr_debugfs.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* Copyright (c) 2023 Imagination Technologies Ltd. */ + +#include "pvr_debugfs.h" + +#include "pvr_device.h" +#include "pvr_fw_trace.h" +#include "pvr_params.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +static const struct pvr_debugfs_entry pvr_debugfs_entries[] = { + {"pvr_params", pvr_params_debugfs_init}, + {"pvr_fw", pvr_fw_trace_debugfs_init}, +}; + +void +pvr_debugfs_init(struct drm_minor *minor) +{ + struct drm_device *drm_dev = minor->dev; + struct pvr_device *pvr_dev = to_pvr_device(drm_dev); + struct dentry *root = minor->debugfs_root; + size_t i; + + for (i = 0; i < ARRAY_SIZE(pvr_debugfs_entries); ++i) { + const struct pvr_debugfs_entry *entry = _debugfs_entries[i]; + struct dentry *dir; + + dir = debugfs_create_dir(entry->name, root); + if (IS_ERR(dir)) { + drm_warn(drm_dev, +"failed to create debugfs dir '%s' (err=%d)", +entry->name, (int)PTR_ERR(dir)); + continue; + } + + entry->init(pvr_dev, dir); + } +} + +/* + * Since all entries are created under _minor->debugfs_root, there's no + * need for a pvr_debugfs_fini() as DRM will clean up everything under its root + * automatically. + */ diff --git a/drivers/gpu/drm/imagination/pvr_debugfs.h b/drivers/gpu/drm/imagination/pvr_debugfs.h new file mode 100644 index ..ebacbd13b84a --- /dev/null +++ b/drivers/gpu/drm/imagination/pvr_debugfs.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ +/* Copyright (c) 2023 Imagination Technologies Ltd. */ + +#ifndef PVR_DEBUGFS_H +#define PVR_DEBUGFS_H + +/* Forward declaration from . */ +struct drm_minor; + +#if defined(CONFIG_DEBUG_FS) +/* Forward declaration from "pvr_device.h". */ +struct pvr_device; + +/* Forward declaration from . */ +struct dentry; + +struct pvr_debugfs_entry { + const char *name; + void (*init)(struct pvr_device *pvr_dev, struct dentry *dir); +}; + +void pvr_debugfs_init(struct drm_minor *minor); +#else /* defined(CONFIG_DEBUG_FS) */ +#include + +static __always_inline void pvr_debugfs_init(struct drm_minor *minor) {} +#endif /* defined(CONFIG_DEBUG_FS) */ + +#endif /* PVR_DEBUGFS_H */ diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c index 199f812d1ee7..8499becf4fbb 100644 --- a/drivers/gpu/drm/imagination/pvr_device.c +++ b/drivers/gpu/drm/imagination/pvr_device.c @@ -5,6 +5,7 @@ #include "pvr_device_info.h" #include "pvr_fw.h" +#include "pvr_params.h" #include "pvr_power.h" #include "pvr_queue.h" #include "pvr_rogue_cr_defs.h" @@ -495,6 +496,14 @@ pvr_device_init(struct pvr_device *pvr_dev) struct device *dev = drm_dev->dev; int err; + /* +* Setup device parameters. We do this
[PATCH v9 18/20] drm/imagination: Add firmware trace header
From: Sarah Walker Changes since v8: - Corrected license identifiers Changes since v5: - Split up header commit due to size Signed-off-by: Sarah Walker Signed-off-by: Donald Robson --- .../gpu/drm/imagination/pvr_rogue_fwif_sf.h | 1648 + 1 file changed, 1648 insertions(+) create mode 100644 drivers/gpu/drm/imagination/pvr_rogue_fwif_sf.h diff --git a/drivers/gpu/drm/imagination/pvr_rogue_fwif_sf.h b/drivers/gpu/drm/imagination/pvr_rogue_fwif_sf.h new file mode 100644 index ..571954182f33 --- /dev/null +++ b/drivers/gpu/drm/imagination/pvr_rogue_fwif_sf.h @@ -0,0 +1,1648 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ +/* Copyright (c) 2023 Imagination Technologies Ltd. */ + +#ifndef PVR_ROGUE_FWIF_SF_H +#define PVR_ROGUE_FWIF_SF_H + +/* + ** + * *DO*NOT* rearrange or delete lines in rogue_fw_log_sfgroups or stid_fmts + * WILL BREAK fw tracing message compatibility with previous + * fw versions. Only add new ones, if so required. + ** + */ + +/* Available log groups. */ +enum rogue_fw_log_sfgroups { + ROGUE_FW_GROUP_NULL, + ROGUE_FW_GROUP_MAIN, + ROGUE_FW_GROUP_CLEANUP, + ROGUE_FW_GROUP_CSW, + ROGUE_FW_GROUP_PM, + ROGUE_FW_GROUP_RTD, + ROGUE_FW_GROUP_SPM, + ROGUE_FW_GROUP_MTS, + ROGUE_FW_GROUP_BIF, + ROGUE_FW_GROUP_MISC, + ROGUE_FW_GROUP_POW, + ROGUE_FW_GROUP_HWR, + ROGUE_FW_GROUP_HWP, + ROGUE_FW_GROUP_RPM, + ROGUE_FW_GROUP_DMA, + ROGUE_FW_GROUP_DBG, +}; + +#define PVR_SF_STRING_MAX_SIZE 256U + +/* pair of string format id and string formats */ +struct rogue_fw_stid_fmt { + u32 id; + char name[PVR_SF_STRING_MAX_SIZE]; +}; + +/* + * The symbolic names found in the table above are assigned an u32 value of + * the following format: + * 31 30 28 27 20 19 1615 12 110 bits + * - --- + * 0-11: id number + *12-15: group id number + *16-19: number of parameters + *20-27: unused + *28-30: active: identify SF packet, otherwise regular int32 + * 31: reserved for signed/unsigned compatibility + * + * The following macro assigns those values to the enum generated SF ids list. + */ +#define ROGUE_FW_LOG_IDMARKER (0x7000U) +#define ROGUE_FW_LOG_CREATESFID(a, b, e) ((u32)(a) | ((u32)(b) << 12) | ((u32)(e) << 16) | \ + ROGUE_FW_LOG_IDMARKER) + +#define ROGUE_FW_LOG_IDMASK (0xFFF0) +#define ROGUE_FW_LOG_VALIDID(I) (((I) & ROGUE_FW_LOG_IDMASK) == ROGUE_FW_LOG_IDMARKER) + +/* Return the group id that the given (enum generated) id belongs to */ +#define ROGUE_FW_SF_GID(x) (((u32)(x) >> 12) & 0xfU) +/* Returns how many arguments the SF(string format) for the given (enum generated) id requires */ +#define ROGUE_FW_SF_PARAMNUM(x) (((u32)(x) >> 16) & 0xfU) + +/* pair of string format id and string formats */ +struct rogue_km_stid_fmt { + u32 id; + const char *name; +}; + +static const struct rogue_km_stid_fmt stid_fmts[] = { + { ROGUE_FW_LOG_CREATESFID(0, ROGUE_FW_GROUP_NULL, 0), + "You should not use this string" }, + + { ROGUE_FW_LOG_CREATESFID(1, ROGUE_FW_GROUP_MAIN, 6), + "Kick 3D: FWCtx 0x%08.8x @ %d, RTD 0x%08x. Partial render:%d, CSW resume:%d, prio:%d" }, + { ROGUE_FW_LOG_CREATESFID(2, ROGUE_FW_GROUP_MAIN, 2), + "3D finished, HWRTData0State=%x, HWRTData1State=%x" }, + { ROGUE_FW_LOG_CREATESFID(3, ROGUE_FW_GROUP_MAIN, 4), + "Kick 3D TQ: FWCtx 0x%08.8x @ %d, CSW resume:%d, prio: %d" }, + { ROGUE_FW_LOG_CREATESFID(4, ROGUE_FW_GROUP_MAIN, 0), + "3D Transfer finished" }, + { ROGUE_FW_LOG_CREATESFID(5, ROGUE_FW_GROUP_MAIN, 3), + "Kick Compute: FWCtx 0x%08.8x @ %d, prio: %d" }, + { ROGUE_FW_LOG_CREATESFID(6, ROGUE_FW_GROUP_MAIN, 0), + "Compute finished" }, + { ROGUE_FW_LOG_CREATESFID(7, ROGUE_FW_GROUP_MAIN, 7), + "Kick TA: FWCtx 0x%08.8x @ %d, RTD 0x%08x. First kick:%d, Last kick:%d, CSW resume:%d, prio:%d" }, + { ROGUE_FW_LOG_CREATESFID(8, ROGUE_FW_GROUP_MAIN, 0), + "TA finished" }, + { ROGUE_FW_LOG_CREATESFID(9, ROGUE_FW_GROUP_MAIN, 0), + "Restart TA after partial render" }, + { ROGUE_FW_LOG_CREATESFID(10, ROGUE_FW_GROUP_MAIN, 0), + "Resume TA without partial render" }, + { ROGUE_FW_LOG_CREATESFID(11, ROGUE_FW_GROUP_MAIN, 2), + "Out of memory! Context 0x%08x, HWRTData 0x%x" }, + { ROGUE_FW_LOG_CREATESFID(12, ROGUE_FW_GROUP_MAIN, 3), + "Kick TLA: FWCtx 0x%08.8x @ %d, prio:%d" }, + { ROGUE_FW_LOG_CREATESFID(13, ROGUE_FW_GROUP_MAIN, 0), + "TLA finished" }, + { ROGUE_FW_LOG_CREATESFID(14, ROGUE_FW_GROUP_MAIN, 3), + "cCCB
[PATCH v9 03/20] dt-bindings: gpu: Add Imagination Technologies PowerVR/IMG GPU
From: Sarah Walker Add the device tree binding documentation for the IMG AXE GPU used in TI AM62 SoCs. Co-developed-by: Frank Binns Signed-off-by: Frank Binns Signed-off-by: Sarah Walker Signed-off-by: Donald Robson Reviewed-by: Maxime Ripard Reviewed-by: Linus Walleij Reviewed-by: Conor Dooley --- Changes since v8: - Updated maintainer Changes since v7: - Updated maintainer Changes since v6: - Remove unused gpu label from example - Updated maintainer Changes since v5: - Update compatible string & description to match marketing name - Remove unnecessary clock-names definition in ti,am62-gpu constraints - Document that GPU revision is discoverable Changes since v4: - Add clocks constraint for ti,am62-gpu - Remove excess address and size cells in example - Remove interrupt name and add maxItems - Make property order consistent between dts and bindings doc - Update example to match dts Changes since v3: - Remove oneOf in compatible property - Remove power-supply (not used on AM62) Changes since v2: - Add commit message description - Remove mt8173-gpu support (not currently supported) - Drop quotes from $id and $schema - Remove reg: minItems - Drop _clk suffixes from clock-names - Remove operating-points-v2 property and cooling-cells (not currently used) - Add additionalProperties: false - Remove stray blank line at the end of file .../devicetree/bindings/gpu/img,powervr.yaml | 73 +++ MAINTAINERS | 7 ++ 2 files changed, 80 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpu/img,powervr.yaml diff --git a/Documentation/devicetree/bindings/gpu/img,powervr.yaml b/Documentation/devicetree/bindings/gpu/img,powervr.yaml new file mode 100644 index ..a13298f1a182 --- /dev/null +++ b/Documentation/devicetree/bindings/gpu/img,powervr.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (c) 2023 Imagination Technologies Ltd. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpu/img,powervr.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Imagination Technologies PowerVR and IMG GPU + +maintainers: + - Frank Binns + +properties: + compatible: +items: + - enum: + - ti,am62-gpu + - const: img,img-axe # IMG AXE GPU model/revision is fully discoverable + + reg: +maxItems: 1 + + clocks: +minItems: 1 +maxItems: 3 + + clock-names: +items: + - const: core + - const: mem + - const: sys +minItems: 1 + + interrupts: +maxItems: 1 + + power-domains: +maxItems: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - interrupts + +additionalProperties: false + +allOf: + - if: + properties: +compatible: + contains: +const: ti,am62-gpu +then: + properties: +clocks: + maxItems: 1 + +examples: + - | +#include +#include +#include + +gpu@fd0 { +compatible = "ti,am62-gpu", "img,img-axe"; +reg = <0x0fd0 0x2>; +clocks = <_clks 187 0>; +clock-names = "core"; +interrupts = ; +power-domains = <_pds 187 TI_SCI_PD_EXCLUSIVE>; +}; diff --git a/MAINTAINERS b/MAINTAINERS index 8a70be8f08ee..59c60abf341e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10392,6 +10392,13 @@ IMGTEC IR DECODER DRIVER S: Orphan F: drivers/media/rc/img-ir/ +IMGTEC POWERVR DRM DRIVER +M: Frank Binns +M: Donald Robson +M: Matt Coster +S: Supported +F: Documentation/devicetree/bindings/gpu/img,powervr.yaml + IMON SOUNDGRAPH USB IR RECEIVER M: Sean Young L: linux-me...@vger.kernel.org -- 2.25.1
[PATCH v9 05/20] drm/imagination: Add skeleton PowerVR driver
From: Sarah Walker This adds the basic skeleton of the driver. The driver registers itself with DRM on probe. Ioctl handlers are currently implemented as stubs. Changes since v8: - Corrected license identifiers Changes since v5: - Update compatible string & description to match marketing name - Checkpatch fixes in to/from_pvr_device/file macros Changes since v3: - Clarify supported GPU generations in driver description - Use drm_dev_unplug() when removing device - Change from_* and to_* functions to macros - Fix IS_PTR/PTR_ERR confusion in pvr_probe() - Remove err_out labels in favour of direct returning - Remove specific am62 compatible match string - Drop MODULE_FIRMWARE() Co-developed-by: Frank Binns Signed-off-by: Frank Binns Co-developed-by: Matt Coster Signed-off-by: Matt Coster Signed-off-by: Sarah Walker Signed-off-by: Donald Robson Reviewed-by: Maxime Ripard --- MAINTAINERS | 1 + drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/imagination/Kconfig | 15 + drivers/gpu/drm/imagination/Makefile | 9 + drivers/gpu/drm/imagination/pvr_device.h | 153 +++ drivers/gpu/drm/imagination/pvr_drv.c| 509 +++ drivers/gpu/drm/imagination/pvr_drv.h| 22 + 8 files changed, 712 insertions(+) create mode 100644 drivers/gpu/drm/imagination/Kconfig create mode 100644 drivers/gpu/drm/imagination/Makefile create mode 100644 drivers/gpu/drm/imagination/pvr_device.h create mode 100644 drivers/gpu/drm/imagination/pvr_drv.c create mode 100644 drivers/gpu/drm/imagination/pvr_drv.h diff --git a/MAINTAINERS b/MAINTAINERS index 37642011c319..debbc1956b8e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10398,6 +10398,7 @@ M: Donald Robson M: Matt Coster S: Supported F: Documentation/devicetree/bindings/gpu/img,powervr.yaml +F: drivers/gpu/drm/imagination/ F: include/uapi/drm/pvr_drm.h IMON SOUNDGRAPH USB IR RECEIVER diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index cdbc56e07649..740c1c0bd068 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -394,6 +394,8 @@ source "drivers/gpu/drm/solomon/Kconfig" source "drivers/gpu/drm/sprd/Kconfig" +source "drivers/gpu/drm/imagination/Kconfig" + config DRM_HYPERV tristate "DRM Support for Hyper-V synthetic video device" depends on DRM && PCI && MMU && HYPERV diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index cdbe91ac0bfc..b4cb0835620a 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -199,3 +199,4 @@ obj-$(CONFIG_DRM_HYPERV) += hyperv/ obj-y += solomon/ obj-$(CONFIG_DRM_SPRD) += sprd/ obj-$(CONFIG_DRM_LOONGSON) += loongson/ +obj-$(CONFIG_DRM_POWERVR) += imagination/ diff --git a/drivers/gpu/drm/imagination/Kconfig b/drivers/gpu/drm/imagination/Kconfig new file mode 100644 index ..03d0a5031f5c --- /dev/null +++ b/drivers/gpu/drm/imagination/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only OR MIT +# Copyright (c) 2023 Imagination Technologies Ltd. + +config DRM_POWERVR + tristate "Imagination Technologies PowerVR (Series 6 and later) & IMG Graphics" + depends on ARM64 + depends on DRM + select DRM_GEM_SHMEM_HELPER + select DRM_SCHED + select FW_LOADER + help + Choose this option if you have a system that has an Imagination + Technologies PowerVR (Series 6 or later) or IMG GPU. + + If "M" is selected, the module will be called powervr. diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile new file mode 100644 index ..f12a06ada9ec --- /dev/null +++ b/drivers/gpu/drm/imagination/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only OR MIT +# Copyright (c) 2023 Imagination Technologies Ltd. + +subdir-ccflags-y := -I$(srctree)/$(src) + +powervr-y := \ + pvr_drv.o \ + +obj-$(CONFIG_DRM_POWERVR) += powervr.o diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h new file mode 100644 index ..d3629164a629 --- /dev/null +++ b/drivers/gpu/drm/imagination/pvr_device.h @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ +/* Copyright (c) 2023 Imagination Technologies Ltd. */ + +#ifndef PVR_DEVICE_H +#define PVR_DEVICE_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/** + * struct pvr_device - powervr-specific wrapper for drm_device + */ +struct pvr_device { + /** +* @base: The underlying drm_device. +* +* Do not access this member directly, instead call +* from_pvr_device(). +*/ + struct drm_device base; +}; + +/** + * struct pvr_file - powervr-specific data to be assigned to + * drm_file.driver_priv + */ +struct pvr_file { + /** +*
[PATCH v9 04/20] drm/imagination/uapi: Add PowerVR driver UAPI
From: Sarah Walker Add the UAPI implementation for the PowerVR driver. Changes from v8: - Fixed documentation for unmapping, which previously suggested the size was not used - Corrected license identifier Changes from v7: - Remove prefixes from DRM_PVR_BO_* flags - Improve struct drm_pvr_ioctl_create_hwrt_dataset_args documentation - Remove references to static area carveouts - CREATE_BO ioctl now returns an error if provided size isn't page aligned - Clarify documentation for DRM_PVR_STATIC_DATA_AREA_EOT Changes from v6: - Add padding to struct drm_pvr_dev_query_gpu_info - Improve BYPASS_CACHE flag documentation - Add SUBMIT_JOB_FRAG_CMD_DISABLE_PIXELMERGE flag Changes from v4: - Remove CREATE_ZEROED flag for BO creation (all buffers are now zeroed) Co-developed-by: Frank Binns Signed-off-by: Frank Binns Co-developed-by: Boris Brezillon Signed-off-by: Boris Brezillon Co-developed-by: Matt Coster Signed-off-by: Matt Coster Co-developed-by: Donald Robson Signed-off-by: Donald Robson Signed-off-by: Sarah Walker Reviewed-by: Faith Ekstrand --- MAINTAINERS|1 + include/uapi/drm/pvr_drm.h | 1297 2 files changed, 1298 insertions(+) create mode 100644 include/uapi/drm/pvr_drm.h diff --git a/MAINTAINERS b/MAINTAINERS index 59c60abf341e..37642011c319 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10398,6 +10398,7 @@ M: Donald Robson M: Matt Coster S: Supported F: Documentation/devicetree/bindings/gpu/img,powervr.yaml +F: include/uapi/drm/pvr_drm.h IMON SOUNDGRAPH USB IR RECEIVER M: Sean Young diff --git a/include/uapi/drm/pvr_drm.h b/include/uapi/drm/pvr_drm.h new file mode 100644 index ..1834375390c4 --- /dev/null +++ b/include/uapi/drm/pvr_drm.h @@ -0,0 +1,1297 @@ +/* SPDX-License-Identifier: (GPL-2.0-only WITH Linux-syscall-note) OR MIT */ +/* Copyright (c) 2023 Imagination Technologies Ltd. */ + +#ifndef PVR_DRM_UAPI_H +#define PVR_DRM_UAPI_H + +#include "drm.h" + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * DOC: PowerVR UAPI + * + * The PowerVR IOCTL argument structs have a few limitations in place, in + * addition to the standard kernel restrictions: + * + * - All members must be type-aligned. + * - The overall struct must be padded to 64-bit alignment. + * - Explicit padding is almost always required. This takes the form of + *``_padding_[x]`` members of sufficient size to pad to the next power-of-two + *alignment, where [x] is the offset into the struct in hexadecimal. Arrays + *are never used for alignment. Padding fields must be zeroed; this is + *always checked. + * - Unions may only appear as the last member of a struct. + * - Individual union members may grow in the future. The space between the + *end of a union member and the end of its containing union is considered + *"implicit padding" and must be zeroed. This is always checked. + * + * In addition to the IOCTL argument structs, the PowerVR UAPI makes use of + * DEV_QUERY argument structs. These are used to fetch information about the + * device and runtime. These structs are subject to the same rules set out + * above. + */ + +/** + * struct drm_pvr_obj_array - Container used to pass arrays of objects + * + * It is not unusual to have to extend objects to pass new parameters, and the DRM + * ioctl infrastructure is supporting that by padding ioctl arguments with zeros + * when the data passed by userspace is smaller than the struct defined in the + * drm_ioctl_desc, thus keeping things backward compatible. This type is just + * applying the same concepts to indirect objects passed through arrays referenced + * from the main ioctl arguments structure: the stride basically defines the size + * of the object passed by userspace, which allows the kernel driver to pad with + * zeros when it's smaller than the size of the object it expects. + * + * Use ``DRM_PVR_OBJ_ARRAY()`` to fill object array fields, unless you + * have a very good reason not to. + */ +struct drm_pvr_obj_array { + /** @stride: Stride of object struct. Used for versioning. */ + __u32 stride; + + /** @count: Number of objects in the array. */ + __u32 count; + + /** @array: User pointer to an array of objects. */ + __u64 array; +}; + +/** + * DRM_PVR_OBJ_ARRAY() - Helper macro for filling drm_pvr_obj_array. + * @cnt: Number of elements pointed to py @ptr. + * @ptr: Pointer to start of a C array. + * + * Return: Literal of type drm_pvr_obj_array. + */ +#define DRM_PVR_OBJ_ARRAY(cnt, ptr) \ + { .stride = sizeof((ptr)[0]), .count = (cnt), .array = (__u64)(uintptr_t)(ptr) } + +/** + * DOC: PowerVR IOCTL interface + */ + +/** + * PVR_IOCTL() - Build a PowerVR IOCTL number + * @_ioctl: An incrementing id for this IOCTL. Added to %DRM_COMMAND_BASE. + * @_mode: Must be one of %DRM_IOR, %DRM_IOW or %DRM_IOWR. + * @_data: The type of the args struct
[PATCH v9 17/20] drm/imagination: Implement job submission and scheduling
From: Sarah Walker Implement job submission ioctl. Job scheduling is implemented using drm_sched. Jobs are submitted in a stream format. This is intended to allow the UAPI data format to be independent of the actual FWIF structures in use, which vary depending on the GPU in use. The stream formats are documented at: https://gitlab.freedesktop.org/mesa/mesa/-/blob/f8d2b42ae65c2f16f36a43e0ae39d288431e4263/src/imagination/csbgen/rogue_kmd_stream.xml Changes since v8: - Updated for upstreamed DRM scheduler changes - Removed workaround code for the pending_list previously being updated after run_job() returned - Fixed null deref in pvr_queue_cleanup_fw_context() for bad stream ptr given to create_context ioctl - Corrected license identifiers Changes since v7: - Updated for v8 "DRM scheduler changes for XE" patchset Changes since v6: - Fix fence handling in pvr_sync_signal_array_add() - Add handling for SUBMIT_JOB_FRAG_CMD_DISABLE_PIXELMERGE flag - Fix missing dma_resv locking in job submit path Changes since v5: - Fix leak in job creation error path Changes since v4: - Use a regular workqueue for job scheduling Changes since v3: - Support partial render jobs - Add job timeout handler - Split sync handling out of job code - Use drm_dev_{enter,exit} Changes since v2: - Use drm_sched for job scheduling Co-developed-by: Boris Brezillon Signed-off-by: Boris Brezillon Co-developed-by: Donald Robson Signed-off-by: Donald Robson Signed-off-by: Sarah Walker --- drivers/gpu/drm/imagination/Kconfig |1 + drivers/gpu/drm/imagination/Makefile |3 + drivers/gpu/drm/imagination/pvr_context.c | 125 +- drivers/gpu/drm/imagination/pvr_context.h | 44 + drivers/gpu/drm/imagination/pvr_device.c | 31 + drivers/gpu/drm/imagination/pvr_device.h | 21 + drivers/gpu/drm/imagination/pvr_drv.c | 40 +- drivers/gpu/drm/imagination/pvr_job.c | 788 + drivers/gpu/drm/imagination/pvr_job.h | 161 ++ drivers/gpu/drm/imagination/pvr_power.c | 28 + drivers/gpu/drm/imagination/pvr_queue.c | 1432 + drivers/gpu/drm/imagination/pvr_queue.h | 169 ++ drivers/gpu/drm/imagination/pvr_stream_defs.c | 226 +++ drivers/gpu/drm/imagination/pvr_sync.c| 289 drivers/gpu/drm/imagination/pvr_sync.h| 84 + 15 files changed, 3438 insertions(+), 4 deletions(-) create mode 100644 drivers/gpu/drm/imagination/pvr_job.c create mode 100644 drivers/gpu/drm/imagination/pvr_job.h create mode 100644 drivers/gpu/drm/imagination/pvr_queue.c create mode 100644 drivers/gpu/drm/imagination/pvr_queue.h create mode 100644 drivers/gpu/drm/imagination/pvr_sync.c create mode 100644 drivers/gpu/drm/imagination/pvr_sync.h diff --git a/drivers/gpu/drm/imagination/Kconfig b/drivers/gpu/drm/imagination/Kconfig index 0abd1b9bf3be..3bfa2ac212dc 100644 --- a/drivers/gpu/drm/imagination/Kconfig +++ b/drivers/gpu/drm/imagination/Kconfig @@ -6,6 +6,7 @@ config DRM_POWERVR depends on ARM64 depends on DRM depends on PM + select DRM_EXEC select DRM_GEM_SHMEM_HELPER select DRM_SCHED select DRM_GPUVM diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile index 7f7bea8c60c4..7e3515c99caa 100644 --- a/drivers/gpu/drm/imagination/Makefile +++ b/drivers/gpu/drm/imagination/Makefile @@ -18,10 +18,13 @@ powervr-y := \ pvr_fw_trace.o \ pvr_gem.o \ pvr_hwrt.o \ + pvr_job.o \ pvr_mmu.o \ pvr_power.o \ + pvr_queue.o \ pvr_stream.o \ pvr_stream_defs.o \ + pvr_sync.o \ pvr_vm.o \ pvr_vm_mips.o diff --git a/drivers/gpu/drm/imagination/pvr_context.c b/drivers/gpu/drm/imagination/pvr_context.c index 6cec5aa5a759..eded5e955cc0 100644 --- a/drivers/gpu/drm/imagination/pvr_context.c +++ b/drivers/gpu/drm/imagination/pvr_context.c @@ -6,10 +6,12 @@ #include "pvr_device.h" #include "pvr_drv.h" #include "pvr_gem.h" +#include "pvr_job.h" #include "pvr_power.h" #include "pvr_rogue_fwif.h" #include "pvr_rogue_fwif_common.h" #include "pvr_rogue_fwif_resetframework.h" +#include "pvr_stream.h" #include "pvr_stream_defs.h" #include "pvr_vm.h" @@ -164,6 +166,116 @@ ctx_fw_data_init(void *cpu_ptr, void *priv) memcpy(cpu_ptr, ctx->data, ctx->data_size); } +/** + * pvr_context_destroy_queues() - Destroy all queues attached to a context. + * @ctx: Context to destroy queues on. + * + * Should be called when the last reference to a context object is dropped. + * It releases all resources attached to the queues bound to this context. + */ +static void pvr_context_destroy_queues(struct pvr_context *ctx) +{ + switch (ctx->type) { + case DRM_PVR_CTX_TYPE_RENDER: + pvr_queue_destroy(ctx->queues.fragment); + pvr_queue_destroy(ctx->queues.geometry); + break; + case DRM_PVR_CTX_TYPE_COMPUTE: +
[PATCH v9 06/20] drm/imagination: Get GPU resources
From: Sarah Walker Acquire clock and register resources, and enable/map as appropriate. Changes since v8: - Corrected license identifiers Changes since v3: - Remove regulator resource (not used on supported platform) - Use devm helpers - Use devm_clk_get_optional() for optional clocks - Don't prepare clocks on resource acquisition - Drop pvr_device_clk_core_get_freq() helper - Drop pvr_device_reg_fini() - Drop NULLing of clocks in pvr_device_clk_init() - Use dev_err_probe() on clock acquisition failure - Remove PVR_CR_READ/WRITE helper macros - Improve documentation for GPU clocks - Remove regs resource (not used in this commit) Co-developed-by: Frank Binns Signed-off-by: Frank Binns Co-developed-by: Matt Coster Signed-off-by: Matt Coster Signed-off-by: Sarah Walker Signed-off-by: Donald Robson Reviewed-by: Maxime Ripard --- drivers/gpu/drm/imagination/Makefile | 1 + drivers/gpu/drm/imagination/pvr_device.c | 147 ++ drivers/gpu/drm/imagination/pvr_device.h | 152 +++ drivers/gpu/drm/imagination/pvr_drv.c| 18 ++- 4 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/imagination/pvr_device.c diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile index f12a06ada9ec..d36007f2825c 100644 --- a/drivers/gpu/drm/imagination/Makefile +++ b/drivers/gpu/drm/imagination/Makefile @@ -4,6 +4,7 @@ subdir-ccflags-y := -I$(srctree)/$(src) powervr-y := \ + pvr_device.o \ pvr_drv.o \ obj-$(CONFIG_DRM_POWERVR) += powervr.o diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c new file mode 100644 index ..abcdf733f57b --- /dev/null +++ b/drivers/gpu/drm/imagination/pvr_device.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* Copyright (c) 2023 Imagination Technologies Ltd. */ + +#include "pvr_device.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * pvr_device_reg_init() - Initialize kernel access to a PowerVR device's + * control registers. + * @pvr_dev: Target PowerVR device. + * + * Sets struct pvr_device->regs. + * + * This method of mapping the device control registers into memory ensures that + * they are unmapped when the driver is detached (i.e. no explicit cleanup is + * required). + * + * Return: + * * 0 on success, or + * * Any error returned by devm_platform_ioremap_resource(). + */ +static int +pvr_device_reg_init(struct pvr_device *pvr_dev) +{ + struct drm_device *drm_dev = from_pvr_device(pvr_dev); + struct platform_device *plat_dev = to_platform_device(drm_dev->dev); + void __iomem *regs; + + pvr_dev->regs = NULL; + + regs = devm_platform_ioremap_resource(plat_dev, 0); + if (IS_ERR(regs)) + return dev_err_probe(drm_dev->dev, PTR_ERR(regs), +"failed to ioremap gpu registers\n"); + + pvr_dev->regs = regs; + + return 0; +} + +/** + * pvr_device_clk_init() - Initialize clocks required by a PowerVR device + * @pvr_dev: Target PowerVR device. + * + * Sets struct pvr_device->core_clk, struct pvr_device->sys_clk and + * struct pvr_device->mem_clk. + * + * Three clocks are required by the PowerVR device: core, sys and mem. On + * return, this function guarantees that the clocks are in one of the following + * states: + * + * * All successfully initialized, + * * Core errored, sys and mem uninitialized, + * * Core deinitialized, sys errored, mem uninitialized, or + * * Core and sys deinitialized, mem errored. + * + * Return: + * * 0 on success, + * * Any error returned by devm_clk_get(), or + * * Any error returned by devm_clk_get_optional(). + */ +static int pvr_device_clk_init(struct pvr_device *pvr_dev) +{ + struct drm_device *drm_dev = from_pvr_device(pvr_dev); + struct clk *core_clk; + struct clk *sys_clk; + struct clk *mem_clk; + + core_clk = devm_clk_get(drm_dev->dev, "core"); + if (IS_ERR(core_clk)) + return dev_err_probe(drm_dev->dev, PTR_ERR(core_clk), +"failed to get core clock\n"); + + sys_clk = devm_clk_get_optional(drm_dev->dev, "sys"); + if (IS_ERR(sys_clk)) + return dev_err_probe(drm_dev->dev, PTR_ERR(core_clk), +"failed to get sys clock\n"); + + mem_clk = devm_clk_get_optional(drm_dev->dev, "mem"); + if (IS_ERR(mem_clk)) + return dev_err_probe(drm_dev->dev, PTR_ERR(core_clk), +"failed to get mem clock\n"); + + pvr_dev->core_clk = core_clk; + pvr_dev->sys_clk = sys_clk; + pvr_dev->mem_clk = mem_clk; + + return 0; +} + +/** + * pvr_device_init() - Initialize a PowerVR device + * @pvr_dev: Target PowerVR device. + * + * If this function returns
[PATCH v9 14/20] drm/imagination: Implement MIPS firmware processor and MMU support
From: Sarah Walker Add support for the MIPS firmware processor, used in the Series AXE GPU. The MIPS firmware processor uses a separate MMU to the rest of the GPU, so this patch adds support for that as well. Changes since v8: - Corrected license identifiers Changes since v6: - Fix integer overflow in VM map error path Changes since v5: - Use alloc_page() when allocating MIPS pagetable Changes since v3: - Get regs resource (removed from GPU resources commit) Signed-off-by: Sarah Walker Signed-off-by: Donald Robson --- drivers/gpu/drm/imagination/Makefile | 4 +- drivers/gpu/drm/imagination/pvr_device.c | 5 +- drivers/gpu/drm/imagination/pvr_device.h | 3 + drivers/gpu/drm/imagination/pvr_fw.c | 2 + drivers/gpu/drm/imagination/pvr_fw_mips.c | 252 ++ drivers/gpu/drm/imagination/pvr_fw_mips.h | 48 + drivers/gpu/drm/imagination/pvr_vm_mips.c | 238 drivers/gpu/drm/imagination/pvr_vm_mips.h | 22 ++ 8 files changed, 572 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/imagination/pvr_fw_mips.c create mode 100644 drivers/gpu/drm/imagination/pvr_fw_mips.h create mode 100644 drivers/gpu/drm/imagination/pvr_vm_mips.c create mode 100644 drivers/gpu/drm/imagination/pvr_vm_mips.h diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile index 5c1c918af7a3..71dc36cc6b9d 100644 --- a/drivers/gpu/drm/imagination/Makefile +++ b/drivers/gpu/drm/imagination/Makefile @@ -10,11 +10,13 @@ powervr-y := \ pvr_drv.o \ pvr_fw.o \ pvr_fw_meta.o \ + pvr_fw_mips.o \ pvr_fw_startstop.o \ pvr_fw_trace.o \ pvr_gem.o \ pvr_mmu.o \ pvr_power.o \ - pvr_vm.o + pvr_vm.o \ + pvr_vm_mips.o obj-$(CONFIG_DRM_POWERVR) += powervr.o diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c index 1be14cdbdace..2d6db4715f85 100644 --- a/drivers/gpu/drm/imagination/pvr_device.c +++ b/drivers/gpu/drm/imagination/pvr_device.c @@ -50,16 +50,19 @@ pvr_device_reg_init(struct pvr_device *pvr_dev) { struct drm_device *drm_dev = from_pvr_device(pvr_dev); struct platform_device *plat_dev = to_platform_device(drm_dev->dev); + struct resource *regs_resource; void __iomem *regs; + pvr_dev->regs_resource = NULL; pvr_dev->regs = NULL; - regs = devm_platform_ioremap_resource(plat_dev, 0); + regs = devm_platform_get_and_ioremap_resource(plat_dev, 0, _resource); if (IS_ERR(regs)) return dev_err_probe(drm_dev->dev, PTR_ERR(regs), "failed to ioremap gpu registers\n"); pvr_dev->regs = regs; + pvr_dev->regs_resource = regs_resource; return 0; } diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h index 39347595c6f0..8853249f4884 100644 --- a/drivers/gpu/drm/imagination/pvr_device.h +++ b/drivers/gpu/drm/imagination/pvr_device.h @@ -93,6 +93,9 @@ struct pvr_device { /** @fw_version: Firmware version detected at runtime. */ struct pvr_fw_version fw_version; + /** @regs_resource: Resource representing device control registers. */ + struct resource *regs_resource; + /** * @regs: Device control registers. * diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c index f8ed981f1807..3debc9870a82 100644 --- a/drivers/gpu/drm/imagination/pvr_fw.c +++ b/drivers/gpu/drm/imagination/pvr_fw.c @@ -933,6 +933,8 @@ pvr_fw_init(struct pvr_device *pvr_dev) if (fw_dev->processor_type == PVR_FW_PROCESSOR_TYPE_META) fw_dev->defs = _fw_defs_meta; + else if (fw_dev->processor_type == PVR_FW_PROCESSOR_TYPE_MIPS) + fw_dev->defs = _fw_defs_mips; else return -EINVAL; diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c new file mode 100644 index ..0bed0257e2ab --- /dev/null +++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* Copyright (c) 2023 Imagination Technologies Ltd. */ + +#include "pvr_device.h" +#include "pvr_fw.h" +#include "pvr_fw_mips.h" +#include "pvr_gem.h" +#include "pvr_rogue_mips.h" +#include "pvr_vm_mips.h" + +#include +#include +#include + +#define ROGUE_FW_HEAP_MIPS_BASE 0xC000 +#define ROGUE_FW_HEAP_MIPS_SHIFT 24 /* 16 MB */ +#define ROGUE_FW_HEAP_MIPS_RESERVED_SIZE SZ_1M + +/** + * process_elf_command_stream() - Process ELF firmware image and populate + *firmware sections + * @pvr_dev: Device pointer. + * @fw: Pointer to firmware image. + * @fw_code_ptr: Pointer to FW code section. + * @fw_data_ptr: Pointer to FW data section. + * @fw_core_code_ptr: Pointer to FW coremem code section. + *
[PATCH v9 01/20] sizes.h: Add entries between SZ_32G and SZ_64T
From: Matt Coster sizes.h has a gap in defines between SZ_32G and SZ_64T. Add the missing defines so they can be used in drivers. Signed-off-by: Matt Coster Signed-off-by: Sarah Walker Signed-off-by: Donald Robson Reviewed-by: Linus Walleij --- include/linux/sizes.h | 9 + 1 file changed, 9 insertions(+) diff --git a/include/linux/sizes.h b/include/linux/sizes.h index 84aa448d8bb3..c3a00b967d18 100644 --- a/include/linux/sizes.h +++ b/include/linux/sizes.h @@ -47,8 +47,17 @@ #define SZ_8G _AC(0x2, ULL) #define SZ_16G _AC(0x4, ULL) #define SZ_32G _AC(0x8, ULL) +#define SZ_64G _AC(0x10, ULL) +#define SZ_128G_AC(0x20, ULL) +#define SZ_256G_AC(0x40, ULL) +#define SZ_512G_AC(0x80, ULL) #define SZ_1T _AC(0x100, ULL) +#define SZ_2T _AC(0x200, ULL) +#define SZ_4T _AC(0x400, ULL) +#define SZ_8T _AC(0x800, ULL) +#define SZ_16T _AC(0x1000, ULL) +#define SZ_32T _AC(0x2000, ULL) #define SZ_64T _AC(0x4000, ULL) #endif /* __LINUX_SIZES_H__ */ -- 2.25.1
Re: [PATCH v2 0/8] dma-buf: heaps: Add secure heap
Hi We have sent a patch series at [1] using this series to add support for Qualcomm secure heaps. Instead of TEE calls, it uses qcom_scm_assign_mem() to secure the memory. Thanks, Pratyush [1] https://lore.kernel.org/lkml/cover.1700544802.git.quic_vji...@quicinc.com/
[PATCH v9 13/20] drm/imagination: Implement firmware infrastructure and META FW support
From: Sarah Walker The infrastructure includes parsing of the firmware image, initialising FW-side structures, handling the kernel and firmware command ringbuffers and starting & stopping the firmware processor. This patch also adds the necessary support code for the META firmware processor. Changes since v8: - Fix documentation for pvr_fwccb_process() - Corrected license identifiers Changes since v6: - Add a minimum retry count to pvr_kccb_reserve_slot_sync() Changes since v5: - Add workaround for BRN 71242 - Attempt to recover GPU on MMU flush command failure Changes since v4: - Remove use of drm_gem_shmem_get_pages() - Remove interrupt resource name Changes since v3: - Hard reset FW processor on watchdog timeout - Switch to threaded IRQ - Rework FW object creation/initialisation to aid hard reset - Added MODULE_FIRMWARE() - Use drm_dev_{enter,exit} Signed-off-by: Sarah Walker Signed-off-by: Donald Robson --- drivers/gpu/drm/imagination/Makefile |4 + drivers/gpu/drm/imagination/pvr_ccb.c | 635 drivers/gpu/drm/imagination/pvr_ccb.h | 71 + drivers/gpu/drm/imagination/pvr_device.c | 103 ++ drivers/gpu/drm/imagination/pvr_device.h | 60 + drivers/gpu/drm/imagination/pvr_drv.c |1 + drivers/gpu/drm/imagination/pvr_fw.c | 1342 + drivers/gpu/drm/imagination/pvr_fw.h | 474 ++ drivers/gpu/drm/imagination/pvr_fw_meta.c | 554 +++ drivers/gpu/drm/imagination/pvr_fw_meta.h | 14 + .../gpu/drm/imagination/pvr_fw_startstop.c| 306 .../gpu/drm/imagination/pvr_fw_startstop.h| 13 + drivers/gpu/drm/imagination/pvr_fw_trace.c| 120 ++ drivers/gpu/drm/imagination/pvr_fw_trace.h| 78 + drivers/gpu/drm/imagination/pvr_mmu.c | 70 +- drivers/gpu/drm/imagination/pvr_power.c | 166 +- drivers/gpu/drm/imagination/pvr_power.h |2 + drivers/gpu/drm/imagination/pvr_vm.c | 26 +- 18 files changed, 4015 insertions(+), 24 deletions(-) create mode 100644 drivers/gpu/drm/imagination/pvr_ccb.c create mode 100644 drivers/gpu/drm/imagination/pvr_ccb.h create mode 100644 drivers/gpu/drm/imagination/pvr_fw_meta.c create mode 100644 drivers/gpu/drm/imagination/pvr_fw_meta.h create mode 100644 drivers/gpu/drm/imagination/pvr_fw_startstop.c create mode 100644 drivers/gpu/drm/imagination/pvr_fw_startstop.h create mode 100644 drivers/gpu/drm/imagination/pvr_fw_trace.c create mode 100644 drivers/gpu/drm/imagination/pvr_fw_trace.h diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile index d9e00a0db6b2..5c1c918af7a3 100644 --- a/drivers/gpu/drm/imagination/Makefile +++ b/drivers/gpu/drm/imagination/Makefile @@ -4,10 +4,14 @@ subdir-ccflags-y := -I$(srctree)/$(src) powervr-y := \ + pvr_ccb.o \ pvr_device.o \ pvr_device_info.o \ pvr_drv.o \ pvr_fw.o \ + pvr_fw_meta.o \ + pvr_fw_startstop.o \ + pvr_fw_trace.o \ pvr_gem.o \ pvr_mmu.o \ pvr_power.o \ diff --git a/drivers/gpu/drm/imagination/pvr_ccb.c b/drivers/gpu/drm/imagination/pvr_ccb.c new file mode 100644 index ..48f06f58f3f1 --- /dev/null +++ b/drivers/gpu/drm/imagination/pvr_ccb.c @@ -0,0 +1,635 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* Copyright (c) 2023 Imagination Technologies Ltd. */ + +#include "pvr_ccb.h" +#include "pvr_device.h" +#include "pvr_drv.h" +#include "pvr_fw.h" +#include "pvr_gem.h" +#include "pvr_power.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define RESERVE_SLOT_TIMEOUT (1 * HZ) /* 1s */ +#define RESERVE_SLOT_MIN_RETRIES 10 + +static void +ccb_ctrl_init(void *cpu_ptr, void *priv) +{ + struct rogue_fwif_ccb_ctl *ctrl = cpu_ptr; + struct pvr_ccb *pvr_ccb = priv; + + ctrl->write_offset = 0; + ctrl->read_offset = 0; + ctrl->wrap_mask = pvr_ccb->num_cmds - 1; + ctrl->cmd_size = pvr_ccb->cmd_size; +} + +/** + * pvr_ccb_init() - Initialise a CCB + * @pvr_dev: Device pointer. + * @pvr_ccb: Pointer to CCB structure to initialise. + * @num_cmds_log2: Log2 of number of commands in this CCB. + * @cmd_size: Command size for this CCB. + * + * Return: + * * Zero on success, or + * * Any error code returned by pvr_fw_object_create_and_map(). + */ +static int +pvr_ccb_init(struct pvr_device *pvr_dev, struct pvr_ccb *pvr_ccb, +u32 num_cmds_log2, size_t cmd_size) +{ + u32 num_cmds = 1 << num_cmds_log2; + u32 ccb_size = num_cmds * cmd_size; + int err; + + pvr_ccb->num_cmds = num_cmds; + pvr_ccb->cmd_size = cmd_size; + + err = drmm_mutex_init(from_pvr_device(pvr_dev), _ccb->lock); + if (err) + return err; + + /* +* Map CCB and control structure as uncached, so we don't have to flush +* CPU cache repeatedly when polling for space. +*/ + pvr_ccb->ctrl =
[PATCH v9 15/20] drm/imagination: Implement free list and HWRT create and destroy ioctls
From: Sarah Walker Implement ioctls to create and destroy free lists and HWRT datasets. Free lists are used for GPU-side memory allocation during geometry processing. HWRT datasets are the FW-side structures representing render targets. Changes since v8: - Corrected license identifiers Changes since v6: - Fix out-of-bounds shift in get_cr_multisamplectl_val() Changes since v4: - Remove use of drm_gem_shmem_get_pages() Changes since v3: - Support free list grow requests from FW - Use drm_dev_{enter,exit} Co-developed-by: Boris Brezillon Signed-off-by: Boris Brezillon Co-developed-by: Donald Robson Signed-off-by: Donald Robson Signed-off-by: Sarah Walker --- drivers/gpu/drm/imagination/Makefile| 2 + drivers/gpu/drm/imagination/pvr_ccb.c | 10 + drivers/gpu/drm/imagination/pvr_device.h| 24 + drivers/gpu/drm/imagination/pvr_drv.c | 112 +++- drivers/gpu/drm/imagination/pvr_free_list.c | 625 drivers/gpu/drm/imagination/pvr_free_list.h | 195 ++ drivers/gpu/drm/imagination/pvr_hwrt.c | 549 + drivers/gpu/drm/imagination/pvr_hwrt.h | 165 ++ 8 files changed, 1678 insertions(+), 4 deletions(-) create mode 100644 drivers/gpu/drm/imagination/pvr_free_list.c create mode 100644 drivers/gpu/drm/imagination/pvr_free_list.h create mode 100644 drivers/gpu/drm/imagination/pvr_hwrt.c create mode 100644 drivers/gpu/drm/imagination/pvr_hwrt.h diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile index 71dc36cc6b9d..2bd501018d5d 100644 --- a/drivers/gpu/drm/imagination/Makefile +++ b/drivers/gpu/drm/imagination/Makefile @@ -8,12 +8,14 @@ powervr-y := \ pvr_device.o \ pvr_device_info.o \ pvr_drv.o \ + pvr_free_list.o \ pvr_fw.o \ pvr_fw_meta.o \ pvr_fw_mips.o \ pvr_fw_startstop.o \ pvr_fw_trace.o \ pvr_gem.o \ + pvr_hwrt.o \ pvr_mmu.o \ pvr_power.o \ pvr_vm.o \ diff --git a/drivers/gpu/drm/imagination/pvr_ccb.c b/drivers/gpu/drm/imagination/pvr_ccb.c index 48f06f58f3f1..4deeac7ed40a 100644 --- a/drivers/gpu/drm/imagination/pvr_ccb.c +++ b/drivers/gpu/drm/imagination/pvr_ccb.c @@ -4,6 +4,7 @@ #include "pvr_ccb.h" #include "pvr_device.h" #include "pvr_drv.h" +#include "pvr_free_list.h" #include "pvr_fw.h" #include "pvr_gem.h" #include "pvr_power.h" @@ -139,6 +140,15 @@ process_fwccb_command(struct pvr_device *pvr_dev, struct rogue_fwif_fwccb_cmd *c pvr_power_reset(pvr_dev, false); break; + case ROGUE_FWIF_FWCCB_CMD_FREELISTS_RECONSTRUCTION: + pvr_free_list_process_reconstruct_req(pvr_dev, + >cmd_data.cmd_freelists_reconstruction); + break; + + case ROGUE_FWIF_FWCCB_CMD_FREELIST_GROW: + pvr_free_list_process_grow_req(pvr_dev, >cmd_data.cmd_free_list_gs); + break; + default: drm_info(from_pvr_device(pvr_dev), "Received unknown FWCCB command %x\n", cmd->cmd_type); diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h index 8853249f4884..f5b82b793566 100644 --- a/drivers/gpu/drm/imagination/pvr_device.h +++ b/drivers/gpu/drm/imagination/pvr_device.h @@ -152,6 +152,14 @@ struct pvr_device { */ atomic_t mmu_flush_cache_flags; + /** +* @free_list_ids: Array of free lists belonging to this device. Array members +* are of type "struct pvr_free_list *". +* +* This array is used to allocate IDs used by the firmware. +*/ + struct xarray free_list_ids; + struct { /** @work: Work item for watchdog callback. */ struct delayed_work work; @@ -247,6 +255,22 @@ struct pvr_file { */ struct pvr_device *pvr_dev; + /** +* @free_list_handles: Array of free lists belonging to this file. Array +* members are of type "struct pvr_free_list *". +* +* This array is used to allocate handles returned to userspace. +*/ + struct xarray free_list_handles; + + /** +* @hwrt_handles: Array of HWRT datasets belonging to this file. Array +* members are of type "struct pvr_hwrt_dataset *". +* +* This array is used to allocate handles returned to userspace. +*/ + struct xarray hwrt_handles; + /** * @vm_ctx_handles: Array of VM contexts belonging to this file. Array * members are of type "struct pvr_vm_context *". diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c index 33b38c0d79c8..f485e2cc60f9 100644 --- a/drivers/gpu/drm/imagination/pvr_drv.c +++ b/drivers/gpu/drm/imagination/pvr_drv.c @@ -3,7 +3,9 @@ #include "pvr_device.h" #include "pvr_drv.h" +#include
[PATCH v9 10/20] drm/imagination: Add GPU ID parsing and firmware loading
From: Sarah Walker Read the GPU ID register at probe time and select the correct features/quirks/enhancements. Use the GPU ID to form the firmware file name and load the firmware. The features/quirks/enhancements arrays are currently hardcoded in the driver for the supported GPUs. We are looking at moving this information to the firmware image. Changes since v8: - Corrected license identifiers Changes since v7: - Fix kerneldoc for pvr_device_info_set_enhancements() Changes since v5: - Add BRN 71242 to device info Changes since v4: - Retrieve device information from firmware header - Pull forward firmware header parsing from FW infrastructure patch - Use devm_add_action_or_reset to release firmware Changes since v3: - Use drm_dev_{enter,exit} Co-developed-by: Frank Binns Signed-off-by: Frank Binns Co-developed-by: Matt Coster Signed-off-by: Matt Coster Co-developed-by: Donald Robson Signed-off-by: Donald Robson Signed-off-by: Sarah Walker --- drivers/gpu/drm/imagination/Makefile | 2 + drivers/gpu/drm/imagination/pvr_device.c | 323 ++- drivers/gpu/drm/imagination/pvr_device.h | 220 drivers/gpu/drm/imagination/pvr_device_info.c | 254 + drivers/gpu/drm/imagination/pvr_device_info.h | 186 +++ drivers/gpu/drm/imagination/pvr_drv.c | 521 +- drivers/gpu/drm/imagination/pvr_drv.h | 107 drivers/gpu/drm/imagination/pvr_fw.c | 145 + drivers/gpu/drm/imagination/pvr_fw.h | 34 ++ drivers/gpu/drm/imagination/pvr_fw_info.h | 135 + 10 files changed, 1925 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/imagination/pvr_device_info.c create mode 100644 drivers/gpu/drm/imagination/pvr_device_info.h create mode 100644 drivers/gpu/drm/imagination/pvr_fw.c create mode 100644 drivers/gpu/drm/imagination/pvr_fw.h create mode 100644 drivers/gpu/drm/imagination/pvr_fw_info.h diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile index d36007f2825c..0b863e9f51b8 100644 --- a/drivers/gpu/drm/imagination/Makefile +++ b/drivers/gpu/drm/imagination/Makefile @@ -5,6 +5,8 @@ subdir-ccflags-y := -I$(srctree)/$(src) powervr-y := \ pvr_device.o \ + pvr_device_info.o \ pvr_drv.o \ + pvr_fw.o obj-$(CONFIG_DRM_POWERVR) += powervr.o diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c index abcdf733f57b..05e382cacb27 100644 --- a/drivers/gpu/drm/imagination/pvr_device.c +++ b/drivers/gpu/drm/imagination/pvr_device.c @@ -2,19 +2,31 @@ /* Copyright (c) 2023 Imagination Technologies Ltd. */ #include "pvr_device.h" +#include "pvr_device_info.h" + +#include "pvr_fw.h" +#include "pvr_rogue_cr_defs.h" #include +#include #include #include #include #include #include +#include #include +#include #include +#include #include #include #include +#include + +/* Major number for the supported version of the firmware. */ +#define PVR_FW_VERSION_MAJOR 1 /** * pvr_device_reg_init() - Initialize kernel access to a PowerVR device's @@ -100,6 +112,209 @@ static int pvr_device_clk_init(struct pvr_device *pvr_dev) return 0; } +/** + * pvr_build_firmware_filename() - Construct a PowerVR firmware filename + * @pvr_dev: Target PowerVR device. + * @base: First part of the filename. + * @major: Major version number. + * + * A PowerVR firmware filename consists of three parts separated by underscores + * (``'_'``) along with a '.fw' file suffix. The first part is the exact value + * of @base, the second part is the hardware version string derived from @pvr_fw + * and the final part is the firmware version number constructed from @major with + * a 'v' prefix, e.g. powervr/rogue_4.40.2.51_v1.fw. + * + * The returned string will have been slab allocated and must be freed with + * kfree(). + * + * Return: + * * The constructed filename on success, or + * * Any error returned by kasprintf(). + */ +static char * +pvr_build_firmware_filename(struct pvr_device *pvr_dev, const char *base, + u8 major) +{ + struct pvr_gpu_id *gpu_id = _dev->gpu_id; + + return kasprintf(GFP_KERNEL, "%s_%d.%d.%d.%d_v%d.fw", base, gpu_id->b, +gpu_id->v, gpu_id->n, gpu_id->c, major); +} + +static void +pvr_release_firmware(void *data) +{ + struct pvr_device *pvr_dev = data; + + release_firmware(pvr_dev->fw_dev.firmware); +} + +/** + * pvr_request_firmware() - Load firmware for a PowerVR device + * @pvr_dev: Target PowerVR device. + * + * See pvr_build_firmware_filename() for details on firmware file naming. + * + * Return: + * * 0 on success, + * * Any error returned by pvr_build_firmware_filename(), or + * * Any error returned by request_firmware(). + */ +static int +pvr_request_firmware(struct pvr_device *pvr_dev) +{ + struct drm_device *drm_dev = _dev->base; + char *filename; +
[PATCH v9 16/20] drm/imagination: Implement context creation/destruction ioctls
From: Sarah Walker Implement ioctls for the creation and destruction of contexts. Contexts are used for job submission and each is associated with a particular job type. Changes since v8: - Fixed one error path in pvr_stream_process_1() - Corrected license identifiers Changes since v5: - Fix context release in final error path in pvr_context_create() Changes since v3: - Use drm_dev_{enter,exit} Co-developed-by: Boris Brezillon Signed-off-by: Boris Brezillon Signed-off-by: Sarah Walker Signed-off-by: Donald Robson --- drivers/gpu/drm/imagination/Makefile | 4 + drivers/gpu/drm/imagination/pvr_cccb.c| 267 ++ drivers/gpu/drm/imagination/pvr_cccb.h| 109 ++ drivers/gpu/drm/imagination/pvr_context.c | 341 ++ drivers/gpu/drm/imagination/pvr_context.h | 161 + drivers/gpu/drm/imagination/pvr_device.h | 21 ++ drivers/gpu/drm/imagination/pvr_drv.c | 29 +- drivers/gpu/drm/imagination/pvr_stream.c | 285 +++ drivers/gpu/drm/imagination/pvr_stream.h | 75 drivers/gpu/drm/imagination/pvr_stream_defs.c | 125 +++ drivers/gpu/drm/imagination/pvr_stream_defs.h | 16 + 11 files changed, 1431 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/imagination/pvr_cccb.c create mode 100644 drivers/gpu/drm/imagination/pvr_cccb.h create mode 100644 drivers/gpu/drm/imagination/pvr_context.c create mode 100644 drivers/gpu/drm/imagination/pvr_context.h create mode 100644 drivers/gpu/drm/imagination/pvr_stream.c create mode 100644 drivers/gpu/drm/imagination/pvr_stream.h create mode 100644 drivers/gpu/drm/imagination/pvr_stream_defs.c create mode 100644 drivers/gpu/drm/imagination/pvr_stream_defs.h diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile index 2bd501018d5d..7f7bea8c60c4 100644 --- a/drivers/gpu/drm/imagination/Makefile +++ b/drivers/gpu/drm/imagination/Makefile @@ -5,6 +5,8 @@ subdir-ccflags-y := -I$(srctree)/$(src) powervr-y := \ pvr_ccb.o \ + pvr_cccb.o \ + pvr_context.o \ pvr_device.o \ pvr_device_info.o \ pvr_drv.o \ @@ -18,6 +20,8 @@ powervr-y := \ pvr_hwrt.o \ pvr_mmu.o \ pvr_power.o \ + pvr_stream.o \ + pvr_stream_defs.o \ pvr_vm.o \ pvr_vm_mips.o diff --git a/drivers/gpu/drm/imagination/pvr_cccb.c b/drivers/gpu/drm/imagination/pvr_cccb.c new file mode 100644 index ..4fabab41bea7 --- /dev/null +++ b/drivers/gpu/drm/imagination/pvr_cccb.c @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* Copyright (c) 2023 Imagination Technologies Ltd. */ + +#include "pvr_ccb.h" +#include "pvr_cccb.h" +#include "pvr_device.h" +#include "pvr_gem.h" +#include "pvr_hwrt.h" + +#include +#include +#include +#include +#include + +static __always_inline u32 +get_ccb_space(u32 w_off, u32 r_off, u32 ccb_size) +{ + return (((r_off) - (w_off)) + ((ccb_size) - 1)) & ((ccb_size) - 1); +} + +static void +cccb_ctrl_init(void *cpu_ptr, void *priv) +{ + struct rogue_fwif_cccb_ctl *ctrl = cpu_ptr; + struct pvr_cccb *pvr_cccb = priv; + + WRITE_ONCE(ctrl->write_offset, 0); + WRITE_ONCE(ctrl->read_offset, 0); + WRITE_ONCE(ctrl->dep_offset, 0); + WRITE_ONCE(ctrl->wrap_mask, pvr_cccb->wrap_mask); +} + +/** + * pvr_cccb_init() - Initialise a Client CCB + * @pvr_dev: Device pointer. + * @pvr_cccb: Pointer to Client CCB structure to initialise. + * @size_log2: Log2 size of Client CCB in bytes. + * @name: Name of owner of Client CCB. Used for fence context. + * + * Return: + * * Zero on success, or + * * Any error code returned by pvr_fw_object_create_and_map(). + */ +int +pvr_cccb_init(struct pvr_device *pvr_dev, struct pvr_cccb *pvr_cccb, + u32 size_log2, const char *name) +{ + size_t size = 1 << size_log2; + int err; + + pvr_cccb->size = size; + pvr_cccb->write_offset = 0; + pvr_cccb->wrap_mask = size - 1; + + /* +* Map CCCB and control structure as uncached, so we don't have to flush +* CPU cache repeatedly when polling for space. +*/ + pvr_cccb->ctrl = pvr_fw_object_create_and_map(pvr_dev, sizeof(*pvr_cccb->ctrl), + PVR_BO_FW_FLAGS_DEVICE_UNCACHED, + cccb_ctrl_init, pvr_cccb, + _cccb->ctrl_obj); + if (IS_ERR(pvr_cccb->ctrl)) + return PTR_ERR(pvr_cccb->ctrl); + + pvr_cccb->cccb = pvr_fw_object_create_and_map(pvr_dev, size, + PVR_BO_FW_FLAGS_DEVICE_UNCACHED, + NULL, NULL, _cccb->cccb_obj); + if (IS_ERR(pvr_cccb->cccb)) { + err = PTR_ERR(pvr_cccb->cccb); + goto err_free_ctrl; + } +
[PATCH v9 12/20] drm/imagination: Implement power management
From: Sarah Walker Add power management to the driver, using runtime pm. The power off sequence depends on firmware commands which are not implemented in this patch. Changes since v8: - Corrected license identifiers Changes since v5: - Use RUNTIME_PM_OPS() to declare PM callbacks - Add Kconfig dependency on CONFIG_PM Changes since v4: - Suspend runtime PM before unplugging device on rmmod Changes since v3: - Don't power device when calling pvr_device_gpu_fini() - Documentation for pvr_dev->lost has been improved - pvr_power_init() renamed to pvr_watchdog_init() - Use drm_dev_{enter,exit} Changes since v2: - Use runtime PM - Implement watchdog Signed-off-by: Sarah Walker Signed-off-by: Donald Robson Reviewed-by: Maxime Ripard --- drivers/gpu/drm/imagination/Kconfig | 1 + drivers/gpu/drm/imagination/Makefile | 1 + drivers/gpu/drm/imagination/pvr_device.c | 23 +- drivers/gpu/drm/imagination/pvr_device.h | 22 ++ drivers/gpu/drm/imagination/pvr_drv.c| 20 +- drivers/gpu/drm/imagination/pvr_power.c | 271 +++ drivers/gpu/drm/imagination/pvr_power.h | 39 7 files changed, 374 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/imagination/pvr_power.c create mode 100644 drivers/gpu/drm/imagination/pvr_power.h diff --git a/drivers/gpu/drm/imagination/Kconfig b/drivers/gpu/drm/imagination/Kconfig index 6f82edf89144..0abd1b9bf3be 100644 --- a/drivers/gpu/drm/imagination/Kconfig +++ b/drivers/gpu/drm/imagination/Kconfig @@ -5,6 +5,7 @@ config DRM_POWERVR tristate "Imagination Technologies PowerVR (Series 6 and later) & IMG Graphics" depends on ARM64 depends on DRM + depends on PM select DRM_GEM_SHMEM_HELPER select DRM_SCHED select DRM_GPUVM diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile index 678c3dbb4326..d9e00a0db6b2 100644 --- a/drivers/gpu/drm/imagination/Makefile +++ b/drivers/gpu/drm/imagination/Makefile @@ -10,6 +10,7 @@ powervr-y := \ pvr_fw.o \ pvr_gem.o \ pvr_mmu.o \ + pvr_power.o \ pvr_vm.o obj-$(CONFIG_DRM_POWERVR) += powervr.o diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c index 201ae780494f..e16282325178 100644 --- a/drivers/gpu/drm/imagination/pvr_device.c +++ b/drivers/gpu/drm/imagination/pvr_device.c @@ -5,6 +5,7 @@ #include "pvr_device_info.h" #include "pvr_fw.h" +#include "pvr_power.h" #include "pvr_rogue_cr_defs.h" #include "pvr_vm.h" @@ -361,6 +362,8 @@ pvr_device_gpu_fini(struct pvr_device *pvr_dev) int pvr_device_init(struct pvr_device *pvr_dev) { + struct drm_device *drm_dev = from_pvr_device(pvr_dev); + struct device *dev = drm_dev->dev; int err; /* Enable and initialize clocks required for the device to operate. */ @@ -368,13 +371,29 @@ pvr_device_init(struct pvr_device *pvr_dev) if (err) return err; + /* Explicitly power the GPU so we can access control registers before the FW is booted. */ + err = pm_runtime_resume_and_get(dev); + if (err) + return err; + /* Map the control registers into memory. */ err = pvr_device_reg_init(pvr_dev); if (err) - return err; + goto err_pm_runtime_put; /* Perform GPU-specific initialization steps. */ - return pvr_device_gpu_init(pvr_dev); + err = pvr_device_gpu_init(pvr_dev); + if (err) + goto err_pm_runtime_put; + + pm_runtime_put(dev); + + return 0; + +err_pm_runtime_put: + pm_runtime_put_sync_suspend(dev); + + return err; } /** diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h index bfc853ffd58f..771ba879f02d 100644 --- a/drivers/gpu/drm/imagination/pvr_device.h +++ b/drivers/gpu/drm/imagination/pvr_device.h @@ -141,6 +141,28 @@ struct pvr_device { * before submitting the next job. */ atomic_t mmu_flush_cache_flags; + + struct { + /** @work: Work item for watchdog callback. */ + struct delayed_work work; + + /** @old_kccb_cmds_executed: KCCB command execution count at last watchdog poll. */ + u32 old_kccb_cmds_executed; + + /** @kccb_stall_count: Number of watchdog polls KCCB has been stalled for. */ + u32 kccb_stall_count; + } watchdog; + + /** +* @lost: %true if the device has been lost. +* +* This variable is set if the device has become irretrievably unavailable, e.g. if the +* firmware processor has stopped responding and can not be revived via a hard reset. +*/ + bool lost; + + /** @sched_wq: Workqueue for schedulers. */ + struct workqueue_struct *sched_wq; }; /** diff --git a/drivers/gpu/drm/imagination/pvr_drv.c
[PATCH v9 08/20] drm/imagination: Add firmware and MMU related headers
From: Sarah Walker Changes since v8: - Corrected license identifiers Changes since v5: - Split up header commit due to size Signed-off-by: Sarah Walker Signed-off-by: Donald Robson Acked-by: Maxime Ripard --- .../drm/imagination/pvr_rogue_heap_config.h | 113 ++ drivers/gpu/drm/imagination/pvr_rogue_meta.h | 356 ++ drivers/gpu/drm/imagination/pvr_rogue_mips.h | 335 .../drm/imagination/pvr_rogue_mips_check.h| 58 +++ .../gpu/drm/imagination/pvr_rogue_mmu_defs.h | 136 +++ 5 files changed, 998 insertions(+) create mode 100644 drivers/gpu/drm/imagination/pvr_rogue_heap_config.h create mode 100644 drivers/gpu/drm/imagination/pvr_rogue_meta.h create mode 100644 drivers/gpu/drm/imagination/pvr_rogue_mips.h create mode 100644 drivers/gpu/drm/imagination/pvr_rogue_mips_check.h create mode 100644 drivers/gpu/drm/imagination/pvr_rogue_mmu_defs.h diff --git a/drivers/gpu/drm/imagination/pvr_rogue_heap_config.h b/drivers/gpu/drm/imagination/pvr_rogue_heap_config.h new file mode 100644 index ..684766006703 --- /dev/null +++ b/drivers/gpu/drm/imagination/pvr_rogue_heap_config.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ +/* Copyright (c) 2023 Imagination Technologies Ltd. */ + +#ifndef PVR_ROGUE_HEAP_CONFIG_H +#define PVR_ROGUE_HEAP_CONFIG_H + +#include + +/* + * ROGUE Device Virtual Address Space Definitions + * + * This file defines the ROGUE virtual address heaps that are used in + * application memory contexts. It also shows where the Firmware memory heap + * fits into this, but the firmware heap is only ever created in the + * kernel driver and never exposed to userspace. + * + * ROGUE_PDSCODEDATA_HEAP_BASE and ROGUE_USCCODE_HEAP_BASE will be programmed, + * on a global basis, into ROGUE_CR_PDS_EXEC_BASE and ROGUE_CR_USC_CODE_BASE_* + * respectively. Therefore if client drivers use multiple configs they must + * still be consistent with their definitions for these heaps. + * + * Base addresses have to be a multiple of 4MiB. + * Heaps must not start at 0x00, as this is reserved for internal + * use within the driver. + * Range comments, those starting in column 0 below are a section heading of + * sorts and are above the heaps in that range. Often this is the reserved + * size of the heap within the range. + */ + +/* 0x00__ / + +/* 0x00__ - 0x00_0040_ */ +/* 0 MiB to 4 MiB, size of 4 MiB : RESERVED */ + +/* 0x00_0040_ - 0x7F_FFC0_ **/ +/* 4 MiB to 512 GiB, size of 512 GiB less 4 MiB : RESERVED **/ + +/* 0x80__ / + +/* 0x80__ - 0x9F__ **/ +/* 512 GiB to 640 GiB, size of 128 GiB : GENERAL_HEAP **/ +#define ROGUE_GENERAL_HEAP_BASE 0x80ull +#define ROGUE_GENERAL_HEAP_SIZE SZ_128G + +/* 0xA0__ - 0xAF__ */ +/* 640 GiB to 704 GiB, size of 64 GiB : FREE */ + +/* B0__ - 0xB7__ */ +/* 704 GiB to 736 GiB, size of 32 GiB : FREE */ + +/* 0xB8__ - 0xBF__ */ +/* 736 GiB to 768 GiB, size of 32 GiB : RESERVED */ + +/* 0xC0__ / + +/* 0xC0__ - 0xD9__ */ +/* 768 GiB to 872 GiB, size of 104 GiB : FREE */ + +/* 0xDA__ - 0xDA__ */ +/* 872 GiB to 876 GiB, size of 4 GiB : PDSCODEDATA_HEAP */ +#define ROGUE_PDSCODEDATA_HEAP_BASE 0xDAull +#define ROGUE_PDSCODEDATA_HEAP_SIZE SZ_4G + +/* 0xDB__ - 0xDB__ */ +/* 876 GiB to 880 GiB, size of 256 MiB (reserved 4GiB) : BRN **/ +/* + * The BRN63142 quirk workaround requires Region Header memory to be at the top + * of a 16GiB aligned range. This is so when masked with 0x03 the + * address will avoid aliasing PB addresses. Start at 879.75GiB. Size of 256MiB. + */ +#define ROGUE_RGNHDR_HEAP_BASE 0xDBF000ull +#define ROGUE_RGNHDR_HEAP_SIZE SZ_256M + +/* 0xDC__ - 0xDF__ */ +/* 880 GiB to 896 GiB, size of 16 GiB : FREE */ + +/* 0xE0__ - 0xE0__ */ +/* 896 GiB to 900 GiB, size of 4 GiB : USCCODE_HEAP */ +#define ROGUE_USCCODE_HEAP_BASE 0xE0ull +#define ROGUE_USCCODE_HEAP_SIZE SZ_4G + +/* 0xE1__ - 0xE1_BFFF_ */ +/* 900 GiB to 903 GiB, size of 3 GiB : RESERVED */ + +/* 0xE1_C000_000 - 0xE1__ */ +/* 903 GiB to 904 GiB, reserved 1 GiB, : FIRMWARE_HEAP */ +#define ROGUE_FW_HEAP_BASE 0xE1C000ull + +/* 0xE2__ - 0xE3__ */ +/* 904 GiB to 912 GiB, size of 8 GiB : FREE */ + +/* 0xE4__ - 0xE7__ */ +/* 912 GiB to 968 GiB, size of 16 GiB : TRANSFER_FRAG */ +#define ROGUE_TRANSFER_FRAG_HEAP_BASE 0xE4ull +#define ROGUE_TRANSFER_FRAG_HEAP_SIZE SZ_16G + +/* 0xE8__ - 0xF1__ */ +/* 928 GiB to 968 GiB, size of 40 GiB : RESERVED */ + +/* 0xF2__ - 0xF2_001F_ **/ +/* 968 GiB to 969 GiB, size of 2 MiB : VISTEST_HEAP */ +#define
[PATCH v9 02/20] drm/gpuvm: Helper to get range of unmap from a remap op.
Determining the start and range of the unmap stage of a remap op is a common piece of code currently implemented by multiple drivers. Add a helper for this. Changes since v7: - Renamed helper to drm_gpuva_op_remap_to_unmap_range() - Improved documentation Changes since v6: - Remove use of __always_inline Signed-off-by: Donald Robson Signed-off-by: Sarah Walker Reviewed-by: Danilo Krummrich --- include/drm/drm_gpuvm.h | 28 1 file changed, 28 insertions(+) diff --git a/include/drm/drm_gpuvm.h b/include/drm/drm_gpuvm.h index 8ca10461d8ac..f94fec9a8517 100644 --- a/include/drm/drm_gpuvm.h +++ b/include/drm/drm_gpuvm.h @@ -1213,4 +1213,32 @@ void drm_gpuva_remap(struct drm_gpuva *prev, void drm_gpuva_unmap(struct drm_gpuva_op_unmap *op); +/** + * drm_gpuva_op_remap_to_unmap_range() - Helper to get the start and range of + * the unmap stage of a remap op. + * @op: Remap op. + * @start_addr: Output pointer for the start of the required unmap. + * @range: Output pointer for the length of the required unmap. + * + * The given start address and range will be set such that they represent the + * range of the address space that was previously covered by the mapping being + * re-mapped, but is now empty. + */ +static inline void +drm_gpuva_op_remap_to_unmap_range(const struct drm_gpuva_op_remap *op, + u64 *start_addr, u64 *range) +{ + const u64 va_start = op->prev ? +op->prev->va.addr + op->prev->va.range : +op->unmap->va->va.addr; + const u64 va_end = op->next ? + op->next->va.addr : + op->unmap->va->va.addr + op->unmap->va->va.range; + + if (start_addr) + *start_addr = va_start; + if (range) + *range = va_end - va_start; +} + #endif /* __DRM_GPUVM_H__ */ -- 2.25.1
[PATCH v9 00/20] Imagination Technologies PowerVR DRM driver
This patch series adds the initial DRM driver for Imagination Technologies PowerVR GPUs, starting with those based on our Rogue architecture. It's worth pointing out that this is a new driver, written from the ground up, rather than a refactored version of our existing downstream driver (pvrsrvkm). This new DRM driver supports: - GEM shmem allocations - dma-buf / PRIME - Per-context userspace managed virtual address space - DRM sync objects (binary and timeline) - Power management suspend / resume - GPU job submission (geometry, fragment, compute, transfer) - META firmware processor - MIPS firmware processor - GPU hang detection and recovery Currently our main focus is on the AXE-1-16M GPU. Testing so far has been done using a TI SK-AM62 board (AXE-1-16M GPU). The driver has also been confirmed to work on the BeaglePlay board. Firmware for the AXE-1-16M can be found here: https://gitlab.freedesktop.org/frankbinns/linux-firmware/-/tree/powervr A Vulkan driver that works with our downstream kernel driver has already been merged into Mesa [1][2]. Support for this new DRM driver is being maintained in a merge request [3], with the branch located here: https://gitlab.freedesktop.org/frankbinns/mesa/-/tree/powervr-winsys Vulkan driver links referred to above: [1] https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15243 [2] https://gitlab.freedesktop.org/mesa/mesa/-/tree/main/src/imagination/vulkan [3] https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15507 Job stream formats are documented at: https://gitlab.freedesktop.org/mesa/mesa/-/blob/f8d2b42ae65c2f16f36a43e0ae39d288431e4263/src/imagination/csbgen/rogue_kmd_stream.xml The Vulkan driver is progressing towards Vulkan 1.0. The current combination of this kernel driver with the Mesa Vulkan driver (powervr-mesa-next branch) successfully completes Vulkan CTS 1.3.4.1 in our local runs. The driver is expected to pass the Khronos Conformance Process once the submission is made. The code in this patch series, along with the needed dts changes can be found here: https://gitlab.freedesktop.org/frankbinns/powervr/-/tree/dev/v9_dts The full development history can be found here: https://gitlab.freedesktop.org/frankbinns/powervr/-/tree/powervr-next High level summary of changes: v9: * Bug fixes related to rebasing on latest drm_sched changes * Updated for recent changes to drm_gpuvm * Switch to dma_resv locking in pvr_vm * Corrected license identifiers v8: * Documentation clarifications/fixes for UAPI * CREATE_BO ioctl now returns an error if provided size isn't page aligned * Optimisations to MMU flush operations * FWIF change to support CPU cached FW allocations/mappings v7: * Fix fence handling in pvr_sync_signal_array_add() * Add a minimum retry count to pvr_kccb_reserve_slot_sync() * Don't initialise kernel_vm_ctx when using MIPS firmware processor * Remove unused gpu label from dt bindings example * Improve UAPI BYPASS_CACHE documentation * Add DRM_PVR_SUBMIT_JOB_FRAG_CMD_DISABLE_PIXELMERGE flag to UAPI * Rename gpuva_manager usage to gpuvm * Sync GEM objects to device on creation * Fix out-of-bounds shift bug * Fix integer overflow in MIPS MMU map error path * Add missing commit messages v6: * Fix a number of error paths * Attempt to recover GPU on MMU flush command failure * Defer freeing/releasing page table backing pages until after TLB flush * Add memory barriers and use WRITE_ONCE() when writing to page tables * Add Kconfig dependency on CONFIG_PM * Fix a few issues with GPU VA manager usage * Split up header commit due to size * Update compatible string and driver description to match marketing name * Use alloc_page() to allocate MIPS pagetable * Remove obsolete documentation v5: * Retrieve GPU device information from firmware image header * Address issues with DT binding and example DTS * Update VM code for upstream GPU VA manager * BOs are always zeroed on allocation * Update copyright v4: * Implemented hang recovery via firmware hard reset * Add support for partial render jobs * Move to a threaded IRQ * Remove unnecessary read/write and clock helpers * Remove device tree elements not relevant to AXE-1-16M * Clean up resource acquisition * Remove unused DT binding attributes v3: * Use drm_sched for scheduling * Use GPU VA manager * Use runtime PM * Use drm_gem_shmem * GPU watchdog and device loss handling * DT binding changes: remove unused attributes, add additionProperties:false v2: * Redesigned and simplified UAPI based on RFC feedback from XDC 2022 * Support for transfer and partial render jobs * Support for timeline sync objects RFC v1: https://lore.kernel.org/dri-devel/20220815165156.118212-1-sarah.wal...@imgtec.com/ RFC v2: https://lore.kernel.org/dri-devel/20230413103419.293493-1-sarah.wal...@imgtec.com/ v3: https://lore.kernel.org/dri-devel/20230613144800.52657-1-sarah.wal...@imgtec.com/ v4: https://lore.kernel.org/dri-devel/20230714142355.111382-1-sarah.wal...@imgtec.com/ v5:
[PATCH v9 4/4] drm/doc: Define KMS atomic state set
From: Pekka Paalanen Specify how the atomic state is maintained between userspace and kernel, plus the special case for async flips. Signed-off-by: Pekka Paalanen Signed-off-by: André Almeida --- v9: - no changes v8: - no changes v7: - add a note that drivers can make exceptions for ad-hoc prop changes - add a note about flipping the same FB_ID as a no-op --- --- Documentation/gpu/drm-uapi.rst | 47 ++ 1 file changed, 47 insertions(+) diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 370d820be248..d0693f902a5c 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -570,3 +570,50 @@ dma-buf interoperability Please see Documentation/userspace-api/dma-buf-alloc-exchange.rst for information on how dma-buf is integrated and exposed within DRM. + +KMS atomic state + + +An atomic commit can change multiple KMS properties in an atomic fashion, +without ever applying intermediate or partial state changes. Either the whole +commit succeeds or fails, and it will never be applied partially. This is the +fundamental improvement of the atomic API over the older non-atomic API which is +referred to as the "legacy API". Applying intermediate state could unexpectedly +fail, cause visible glitches, or delay reaching the final state. + +An atomic commit can be flagged with DRM_MODE_ATOMIC_TEST_ONLY, which means the +complete state change is validated but not applied. Userspace should use this +flag to validate any state change before asking to apply it. If validation fails +for any reason, userspace should attempt to fall back to another, perhaps +simpler, final state. This allows userspace to probe for various configurations +without causing visible glitches on screen and without the need to undo a +probing change. + +The changes recorded in an atomic commit apply on top the current KMS state in +the kernel. Hence, the complete new KMS state is the complete old KMS state with +the committed property settings done on top. The kernel will try to avoid +no-operation changes, so it is safe for userspace to send redundant property +settings. However, not every situation allows for no-op changes, due to the +need to acquire locks for some attributes. Userspace needs to be aware that some +redundant information might result in oversynchronization issues. No-operation +changes do not count towards actually needed changes, e.g. setting MODE_ID to a +different blob with identical contents as the current KMS state shall not be a +modeset on its own. As a special exception for VRR needs, explicitly setting +FB_ID to its current value is not a no-op. + +A "modeset" is a change in KMS state that might enable, disable, or temporarily +disrupt the emitted video signal, possibly causing visible glitches on screen. A +modeset may also take considerably more time to complete than other kinds of +changes, and the video sink might also need time to adapt to the new signal +properties. Therefore a modeset must be explicitly allowed with the flag +DRM_MODE_ATOMIC_ALLOW_MODESET. This in combination with +DRM_MODE_ATOMIC_TEST_ONLY allows userspace to determine if a state change is +likely to cause visible disruption on screen and avoid such changes when end +users do not expect them. + +An atomic commit with the flag DRM_MODE_PAGE_FLIP_ASYNC is allowed to +effectively change only the FB_ID property on any planes. No-operation changes +are ignored as always. Changing any other property will cause the commit to be +rejected. Each driver may relax this restriction if they have guarantees that +such property change doesn't cause modesets. Userspace can use TEST_ONLY commits +to query the driver about this. -- 2.42.1
[PATCH v9 3/4] drm: introduce DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP
From: Simon Ser This new kernel capability indicates whether async page-flips are supported via the atomic uAPI. DRM clients can use it to check for support before feeding DRM_MODE_PAGE_FLIP_ASYNC to the kernel. Make it clear that DRM_CAP_ASYNC_PAGE_FLIP is for legacy uAPI only. Signed-off-by: Simon Ser Reviewed-by: André Almeida Reviewed-by: Alex Deucher Signed-off-by: André Almeida --- v9: no changes --- --- drivers/gpu/drm/drm_ioctl.c | 4 include/uapi/drm/drm.h | 10 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 44fda68c28ae..f461ed862480 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -301,6 +301,10 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ case DRM_CAP_CRTC_IN_VBLANK_EVENT: req->value = 1; break; + case DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP: + req->value = drm_core_check_feature(dev, DRIVER_ATOMIC) && +dev->mode_config.async_page_flip; + break; default: return -EINVAL; } diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 8662b5aeea0c..796de831f4a0 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -713,7 +713,8 @@ struct drm_gem_open { /** * DRM_CAP_ASYNC_PAGE_FLIP * - * If set to 1, the driver supports _MODE_PAGE_FLIP_ASYNC. + * If set to 1, the driver supports _MODE_PAGE_FLIP_ASYNC for legacy + * page-flips. */ #define DRM_CAP_ASYNC_PAGE_FLIP0x7 /** @@ -773,6 +774,13 @@ struct drm_gem_open { * :ref:`drm_sync_objects`. */ #define DRM_CAP_SYNCOBJ_TIMELINE 0x14 +/** + * DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP + * + * If set to 1, the driver supports _MODE_PAGE_FLIP_ASYNC for atomic + * commits. + */ +#define DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP 0x15 /* DRM_IOCTL_GET_CAP ioctl argument type */ struct drm_get_cap { -- 2.42.1
[PATCH v9 2/4] drm: allow DRM_MODE_PAGE_FLIP_ASYNC for atomic commits
From: Simon Ser If the driver supports it, allow user-space to supply the DRM_MODE_PAGE_FLIP_ASYNC flag to request an async page-flip. Set drm_crtc_state.async_flip accordingly. Document that drivers will reject atomic commits if an async flip isn't possible. This allows user-space to fall back to something else. For instance, Xorg falls back to a blit. Another option is to wait as close to the next vblank as possible before performing the page-flip to reduce latency. Signed-off-by: Simon Ser Reviewed-by: Alex Deucher Co-developed-by: André Almeida Signed-off-by: André Almeida --- v9: dropped atomic_async_page_flip_not_supported --- drivers/gpu/drm/drm_atomic_uapi.c | 25 ++--- include/uapi/drm/drm_mode.h | 9 + 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index ed46133a2dd7..de4265423ddc 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1368,6 +1368,18 @@ static void complete_signaling(struct drm_device *dev, kfree(fence_state); } +static void +set_async_flip(struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + int i; + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + crtc_state->async_flip = true; + } +} + int drm_mode_atomic_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -1409,9 +1421,13 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, } if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) { - drm_dbg_atomic(dev, - "commit failed: invalid flag DRM_MODE_PAGE_FLIP_ASYNC\n"); - return -EINVAL; + if (!dev->mode_config.async_page_flip) { + drm_dbg_atomic(dev, + "commit failed: DRM_MODE_PAGE_FLIP_ASYNC not supported\n"); + return -EINVAL; + } + + async_flip = true; } /* can't test and expect an event at the same time. */ @@ -1514,6 +1530,9 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, if (ret) goto out; + if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) + set_async_flip(state); + if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { ret = drm_atomic_check_only(state); } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 09e7a471ee30..95630f170110 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -957,6 +957,15 @@ struct hdr_output_metadata { * Request that the page-flip is performed as soon as possible, ie. with no * delay due to waiting for vblank. This may cause tearing to be visible on * the screen. + * + * When used with atomic uAPI, the driver will return an error if the hardware + * doesn't support performing an asynchronous page-flip for this update. + * User-space should handle this, e.g. by falling back to a regular page-flip. + * + * Note, some hardware might need to perform one last synchronous page-flip + * before being able to switch to asynchronous page-flips. As an exception, + * the driver will return success even though that first page-flip is not + * asynchronous. */ #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4 -- 2.42.1
[PATCH v9 1/4] drm: Refuse to async flip with atomic prop changes
Given that prop changes may lead to modesetting, which would defeat the fast path of the async flip, refuse any atomic prop change for async flips in atomic API. The only exception is the framebuffer ID to flip to. Currently the only plane type supported is the primary one. Signed-off-by: André Almeida Reviewed-by: Simon Ser --- v9: no changes v8: add a check for plane type, we can only flip primary planes v7: drop the mode_id exception for prop changes --- drivers/gpu/drm/drm_atomic_uapi.c | 52 +++-- drivers/gpu/drm/drm_crtc_internal.h | 2 +- drivers/gpu/drm/drm_mode_object.c | 2 +- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 98d3b10c08ae..ed46133a2dd7 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1006,13 +1006,28 @@ int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state, return ret; } +static int drm_atomic_check_prop_changes(int ret, uint64_t old_val, uint64_t prop_value, +struct drm_property *prop) +{ + if (ret != 0 || old_val != prop_value) { + drm_dbg_atomic(prop->dev, + "[PROP:%d:%s] No prop can be changed during async flip\n", + prop->base.id, prop->name); + return -EINVAL; + } + + return 0; +} + int drm_atomic_set_property(struct drm_atomic_state *state, struct drm_file *file_priv, struct drm_mode_object *obj, struct drm_property *prop, - uint64_t prop_value) + uint64_t prop_value, + bool async_flip) { struct drm_mode_object *ref; + uint64_t old_val; int ret; if (!drm_property_change_valid_get(prop, prop_value, )) @@ -1029,6 +1044,13 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } + if (async_flip) { + ret = drm_atomic_connector_get_property(connector, connector_state, + prop, _val); + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); + break; + } + ret = drm_atomic_connector_set_property(connector, connector_state, file_priv, prop, prop_value); @@ -1044,6 +1066,13 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } + if (async_flip) { + ret = drm_atomic_crtc_get_property(crtc, crtc_state, + prop, _val); + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); + break; + } + ret = drm_atomic_crtc_set_property(crtc, crtc_state, prop, prop_value); break; @@ -1051,6 +1080,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state, case DRM_MODE_OBJECT_PLANE: { struct drm_plane *plane = obj_to_plane(obj); struct drm_plane_state *plane_state; + struct drm_mode_config *config = >dev->mode_config; plane_state = drm_atomic_get_plane_state(state, plane); if (IS_ERR(plane_state)) { @@ -1058,6 +1088,21 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } + if (async_flip && prop != config->prop_fb_id) { + ret = drm_atomic_plane_get_property(plane, plane_state, + prop, _val); + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); + break; + } + + if (async_flip && plane_state->plane->type != DRM_PLANE_TYPE_PRIMARY) { + drm_dbg_atomic(prop->dev, + "[OBJECT:%d] Only primary planes can be changed during async flip\n", + obj->id); + ret = -EINVAL; + break; + } + ret = drm_atomic_plane_set_property(plane, plane_state, file_priv, prop, prop_value); @@ -1337,6 +1382,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, struct drm_out_fence_state *fence_state; int ret = 0; unsigned int i, j, num_fences; + bool async_flip = false; /* disallow for drivers not supporting atomic: */
[PATCH v9 0/4] drm: Add support for atomic async page-flip
Hi, This work from me and Simon adds support for DRM_MODE_PAGE_FLIP_ASYNC through the atomic API. This feature is already available via the legacy API. The use case is to be able to present a new frame immediately (or as soon as possible), even if after missing a vblank. This might result in tearing, but it's useful when a high framerate is desired, such as for gaming. Differently from earlier versions, this one refuses to flip if any prop changes for async flips. The idea is that the fast path of immediate page flips doesn't play well with modeset changes, so only the fb_id can be changed. Tested with: - Intel TigerLake-LP GT2 - AMD VanGogh Thanks, André - User-space patch: https://github.com/Plagman/gamescope/pull/595 - IGT tests: https://lore.kernel.org/all/20231110163811.24158-1-andrealm...@igalia.com/ Changes from v8: - Dropped atomic_async_page_flip_not_supported, giving that current design works with any driver that support atomic and async at the same time. - Dropped the patch that disabled atomic_async_page_flip_not_supported for AMD. - Reordered commits v8: https://lore.kernel.org/all/20231025005318.293690-1-andrealm...@igalia.com/ Changes from v7: - Only accept flips to primary planes. If a driver support flips in different planes, support will be added later. v7: https://lore.kernel.org/dri-devel/20231017092837.32428-1-andrealm...@igalia.com/ Changes from v6: - Dropped the exception to allow MODE_ID changes (Simon) - Clarify what happens when flipping with the same FB_ID (Pekka) v6: https://lore.kernel.org/dri-devel/20230815185710.159779-1-andrealm...@igalia.com/ Changes from v5: - Add note in the docs that not every redundant attribute will result in no-op, some might cause oversynchronization issues. v5: https://lore.kernel.org/dri-devel/20230707224059.305474-1-andrealm...@igalia.com/ Changes from v4: - Documentation rewrote by Pekka Paalanen v4: https://lore.kernel.org/dri-devel/20230701020917.143394-1-andrealm...@igalia.com/ Changes from v3: - Add new patch to reject prop changes - Add a documentation clarifying the KMS atomic state set v3: https://lore.kernel.org/dri-devel/20220929184307.258331-1-cont...@emersion.fr/ André Almeida (1): drm: Refuse to async flip with atomic prop changes Pekka Paalanen (1): drm/doc: Define KMS atomic state set Simon Ser (2): drm: allow DRM_MODE_PAGE_FLIP_ASYNC for atomic commits drm: introduce DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP Documentation/gpu/drm-uapi.rst | 47 ++ drivers/gpu/drm/drm_atomic_uapi.c | 77 ++--- drivers/gpu/drm/drm_crtc_internal.h | 2 +- drivers/gpu/drm/drm_ioctl.c | 4 ++ drivers/gpu/drm/drm_mode_object.c | 2 +- include/uapi/drm/drm.h | 10 +++- include/uapi/drm/drm_mode.h | 9 7 files changed, 142 insertions(+), 9 deletions(-) -- 2.42.1
Re: [PATCH] drm/msm/a690: Fix reg values for a690
On 11/21/23 17:21, Rob Clark wrote: From: Danylo Piliaiev KGSL doesn't support a690 so all reg values were the same as on a660. Now we know the values and they are different from the windows driver. This fixes hangs on D3D12 games and some CTS tests. Signed-off-by: Danylo Piliaiev Signed-off-by: Rob Clark --- Very interesting.. did you document how to get these on windows? Konrad
[PATCH] dma-buf: Correct the documentation of name and exp_name symbols
Fix the documentation of struct dma_buf members name and exp_name as to how these members are to be used and accessed. Signed-off-by: Ramesh Errabolu --- include/linux/dma-buf.h | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 3f31baa3293f..8ff4add71f88 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -343,16 +343,19 @@ struct dma_buf { /** * @exp_name: * -* Name of the exporter; useful for debugging. See the -* DMA_BUF_SET_NAME IOCTL. +* Name of the exporter; useful for debugging. Must not be NULL */ const char *exp_name; /** * @name: * -* Userspace-provided name; useful for accounting and debugging, -* protected by dma_resv_lock() on @resv and @name_lock for read access. +* Userspace-provided name. Default value is NULL. If not NULL, +* length cannot be longer than DMA_BUF_NAME_LEN, including NIL +* char. Useful for accounting and debugging. Read/Write accesses +* are protected by @name_lock +* +* See the IOCTLs DMA_BUF_SET_NAME or DMA_BUF_SET_NAME_A/B */ const char *name; -- 2.34.1
Re: [PATCH v6 0/6] drm: simplify support for transparent DRM bridges
Hi, On 2023/11/4 07:03, Dmitry Baryshkov wrote: Supporting DP/USB-C can result in a chain of several transparent bridges (PHY, redrivers, mux, etc). All attempts to implement DP support in a different way resulted either in series of hacks or in device tree not reflecting the actual hardware design. This results in drivers having similar boilerplate code for such bridges. Please improve the written, "resulted" -> "yield" ? Next, these drivers are susceptible to -EPROBE_DEFER loops: the next bridge can either be probed from the bridge->attach callback, when it is too late to return -EPROBE_DEFER, or from the probe() callback, when the next bridge might not yet be available, because it depends on the resources provided by the probing device. Device links can not fully solve this problem since there are mutual dependencies between adjancent devices. Last, but not least, this results in the the internal knowledge of DRM There is a duplicated "the" word in this sentence. As far as I can understand, nearly all of those troubles are because the display bridges drivers are designed as a kernel module(.ko) instead of making them as static link-able helpers. I means that a display bridge device can not work standalone, as it have to be used with a display controller. So a display bridge is just a slave device or a auxiliary device. My question is: if it can't works by itself, we probably shouldn't design them as kernel modules style. Am I correct? subsystem slowly diffusing into other subsystems, like PHY or USB/TYPEC. Yeah, this indeed a problem. To solve all these issues, define a separate DRM helper, which creates separate aux device just for the bridge. I'm supporting you if want to solve all these problems, this is fine and thanks a lot. But I want to ask a question, now that you are solving these problems by creating separate devices, does this manner match the hardware design perfectly? which is the hardware units you newly created device is corresponding to? During probe such aux device doesn't result in the EPROBE_DEFER loops. Instead it allows the device drivers to probe properly, according to the actual resource dependencies. The bridge auxdevs are then probed when the next bridge becomes available, sparing drivers from drm_bridge_attach() returning -EPROBE_DEFER. OK, as far as I can understand, in order to solve the mentioned problem you are also retire the defer probe mechanism. Changes since v5: - Removed extra semicolon in !DRM_AUX_HPD_BRIDGE stubs definition. Changes since v4: - Added documentation for new API (Sima) - Added generic code to handle "last mile" DP bridges implementing just the HPD functionality. - Rebased on top of linux-next to be able to drop #ifdef's around drm_bridge->of_node Changes since v3: - Moved bridge driver to gpu/drm/bridge (Neil Armstrong) - Renamed it to aux-bridge (since there is already a simple_bridge driver) - Made CONFIG_OF mandatory for this driver (Neil Armstrong) - Added missing kfree and ida_free (Dan Carpenter) Changes since v2: - ifdef'ed bridge->of_node access (LKP) Changes since v1: - Added EXPORT_SYMBOL_GPL / MODULE_LICENSE / etc. to drm_simple_bridge Dmitry Baryshkov (6): drm/bridge: add transparent bridge helper phy: qcom: qmp-combo: switch to DRM_AUX_BRIDGE usb: typec: nb7vpq904m: switch to DRM_AUX_BRIDGE drm/bridge: implement generic DP HPD bridge soc: qcom: pmic-glink: switch to DRM_AUX_HPD_BRIDGE usb: typec: qcom-pmic-typec: switch to DRM_AUX_HPD_BRIDGE drivers/gpu/drm/bridge/Kconfig| 17 ++ drivers/gpu/drm/bridge/Makefile | 2 + drivers/gpu/drm/bridge/aux-bridge.c | 140 +++ drivers/gpu/drm/bridge/aux-hpd-bridge.c | 164 ++ drivers/phy/qualcomm/Kconfig | 2 +- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 44 + drivers/soc/qcom/Kconfig | 1 + drivers/soc/qcom/pmic_glink_altmode.c | 33 +--- drivers/usb/typec/mux/Kconfig | 2 +- drivers/usb/typec/mux/nb7vpq904m.c| 44 + drivers/usb/typec/tcpm/Kconfig| 1 + drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c | 41 + include/drm/bridge/aux-bridge.h | 37 13 files changed, 383 insertions(+), 145 deletions(-) create mode 100644 drivers/gpu/drm/bridge/aux-bridge.c create mode 100644 drivers/gpu/drm/bridge/aux-hpd-bridge.c create mode 100644 include/drm/bridge/aux-bridge.h
[drm-intel:for-linux-next-gt 1/6] drivers/gpu/drm/i915/i915_drm_client.h:81:1: error: non-void function does not return a value
tree: git://anongit.freedesktop.org/drm-intel for-linux-next-gt head: 5032c607e886e0c40749a05d37b835c1757d38ff commit: e4ae85e364fc652ea15d85b0f3a6da304c9b5ce7 [1/6] drm/i915: Add ability for tracking buffer objects per client config: x86_64-buildonly-randconfig-006-20231122 (https://download.01.org/0day-ci/archive/20231122/202311222102.lhbe6kcx-...@intel.com/config) compiler: clang version 16.0.4 (https://github.com/llvm/llvm-project.git ae42196bc493ffe877a7e3dff8be32035dea4d07) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231122/202311222102.lhbe6kcx-...@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot | Closes: https://lore.kernel.org/oe-kbuild-all/202311222102.lhbe6kcx-...@intel.com/ Note: the drm-intel/for-linux-next-gt HEAD 5032c607e886e0c40749a05d37b835c1757d38ff builds fine. It only hurts bisectability. All errors (new ones prefixed by >>): In file included from drivers/gpu/drm/i915/selftests/igt_spinner.c:12: In file included from drivers/gpu/drm/i915/selftests/igt_spinner.h:10: In file included from drivers/gpu/drm/i915/gem/i915_gem_context.h:12: In file included from drivers/gpu/drm/i915/gt/intel_context.h:14: In file included from drivers/gpu/drm/i915/i915_drv.h:54: >> drivers/gpu/drm/i915/i915_drm_client.h:81:1: error: non-void function does >> not return a value [-Werror,-Wreturn-type] } ^ 1 error generated. vim +81 drivers/gpu/drm/i915/i915_drm_client.h 78 79 static inline bool i915_drm_client_remove_object(struct drm_i915_gem_object *obj) 80 { > 81 } 82 #endif 83 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
[PATCH AUTOSEL 4.14 3/3] drm/amdgpu: correct chunk_ptr to a pointer to chunk.
From: YuanShang [ Upstream commit 50d51374b498457c4dea26779d32ccfed12ddaff ] The variable "chunk_ptr" should be a pointer pointing to a struct drm_amdgpu_cs_chunk instead of to a pointer of that. Signed-off-by: YuanShang Reviewed-by: Christian König Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 7bad519aaae08..d24ef103471b9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -113,7 +113,7 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) } for (i = 0; i < p->nchunks; i++) { - struct drm_amdgpu_cs_chunk __user **chunk_ptr = NULL; + struct drm_amdgpu_cs_chunk __user *chunk_ptr = NULL; struct drm_amdgpu_cs_chunk user_chunk; uint32_t __user *cdata; -- 2.42.0
[PATCH AUTOSEL 4.19 6/6] drm/amdgpu: correct chunk_ptr to a pointer to chunk.
From: YuanShang [ Upstream commit 50d51374b498457c4dea26779d32ccfed12ddaff ] The variable "chunk_ptr" should be a pointer pointing to a struct drm_amdgpu_cs_chunk instead of to a pointer of that. Signed-off-by: YuanShang Reviewed-by: Christian König Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 70e446c2acf82..94b06c918e80d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -147,7 +147,7 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, union drm_amdgpu_cs } for (i = 0; i < p->nchunks; i++) { - struct drm_amdgpu_cs_chunk __user **chunk_ptr = NULL; + struct drm_amdgpu_cs_chunk __user *chunk_ptr = NULL; struct drm_amdgpu_cs_chunk user_chunk; uint32_t __user *cdata; -- 2.42.0
[PATCH AUTOSEL 5.4 6/6] drm/amdgpu: correct chunk_ptr to a pointer to chunk.
From: YuanShang [ Upstream commit 50d51374b498457c4dea26779d32ccfed12ddaff ] The variable "chunk_ptr" should be a pointer pointing to a struct drm_amdgpu_cs_chunk instead of to a pointer of that. Signed-off-by: YuanShang Reviewed-by: Christian König Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 1a83055211762..f9c725a8991b7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -141,7 +141,7 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, union drm_amdgpu_cs } for (i = 0; i < p->nchunks; i++) { - struct drm_amdgpu_cs_chunk __user **chunk_ptr = NULL; + struct drm_amdgpu_cs_chunk __user *chunk_ptr = NULL; struct drm_amdgpu_cs_chunk user_chunk; uint32_t __user *cdata; -- 2.42.0
[PATCH AUTOSEL 5.10 7/7] drm/amdgpu: correct chunk_ptr to a pointer to chunk.
From: YuanShang [ Upstream commit 50d51374b498457c4dea26779d32ccfed12ddaff ] The variable "chunk_ptr" should be a pointer pointing to a struct drm_amdgpu_cs_chunk instead of to a pointer of that. Signed-off-by: YuanShang Reviewed-by: Christian König Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 7f2adac82e3a6..addeda42339fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -143,7 +143,7 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, union drm_amdgpu_cs } for (i = 0; i < p->nchunks; i++) { - struct drm_amdgpu_cs_chunk __user **chunk_ptr = NULL; + struct drm_amdgpu_cs_chunk __user *chunk_ptr = NULL; struct drm_amdgpu_cs_chunk user_chunk; uint32_t __user *cdata; -- 2.42.0
[PATCH AUTOSEL 5.15 7/7] drm/amdgpu: correct chunk_ptr to a pointer to chunk.
From: YuanShang [ Upstream commit 50d51374b498457c4dea26779d32ccfed12ddaff ] The variable "chunk_ptr" should be a pointer pointing to a struct drm_amdgpu_cs_chunk instead of to a pointer of that. Signed-off-by: YuanShang Reviewed-by: Christian König Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 2d8f71dde9803..f293d0dfec613 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -142,7 +142,7 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, union drm_amdgpu_cs } for (i = 0; i < p->nchunks; i++) { - struct drm_amdgpu_cs_chunk __user **chunk_ptr = NULL; + struct drm_amdgpu_cs_chunk __user *chunk_ptr = NULL; struct drm_amdgpu_cs_chunk user_chunk; uint32_t __user *cdata; -- 2.42.0
[PATCH AUTOSEL 6.1 9/9] drm/amdgpu: correct chunk_ptr to a pointer to chunk.
From: YuanShang [ Upstream commit 50d51374b498457c4dea26779d32ccfed12ddaff ] The variable "chunk_ptr" should be a pointer pointing to a struct drm_amdgpu_cs_chunk instead of to a pointer of that. Signed-off-by: YuanShang Reviewed-by: Christian König Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 4624160315648..26b55cca27680 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -201,7 +201,7 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p, } for (i = 0; i < p->nchunks; i++) { - struct drm_amdgpu_cs_chunk __user **chunk_ptr = NULL; + struct drm_amdgpu_cs_chunk __user *chunk_ptr = NULL; struct drm_amdgpu_cs_chunk user_chunk; uint32_t __user *cdata; -- 2.42.0
[PATCH AUTOSEL 6.5 14/15] drm/amdgpu: correct chunk_ptr to a pointer to chunk.
From: YuanShang [ Upstream commit 50d51374b498457c4dea26779d32ccfed12ddaff ] The variable "chunk_ptr" should be a pointer pointing to a struct drm_amdgpu_cs_chunk instead of to a pointer of that. Signed-off-by: YuanShang Reviewed-by: Christian König Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 946d031d2520e..c66719a92e9ba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -208,7 +208,7 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p, } for (i = 0; i < p->nchunks; i++) { - struct drm_amdgpu_cs_chunk __user **chunk_ptr = NULL; + struct drm_amdgpu_cs_chunk __user *chunk_ptr = NULL; struct drm_amdgpu_cs_chunk user_chunk; uint32_t __user *cdata; -- 2.42.0
[PATCH AUTOSEL 6.5 13/15] drm/amdgpu: finalizing mem_partitions at the end of GMC v9 sw_fini
From: Le Ma [ Upstream commit bdb72185d310fc8049c7ea95221d640e9e7165e5 ] The valid num_mem_partitions is required during ttm pool fini, thus move the cleanup at the end of the function. Signed-off-by: Le Ma Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 67e669e0141cc..00c719b93c76e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -2211,8 +2211,6 @@ static int gmc_v9_0_sw_fini(void *handle) if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) amdgpu_gmc_sysfs_fini(adev); - adev->gmc.num_mem_partitions = 0; - kfree(adev->gmc.mem_partitions); amdgpu_gmc_ras_fini(adev); amdgpu_gem_force_release(adev); @@ -2226,6 +2224,9 @@ static int gmc_v9_0_sw_fini(void *handle) amdgpu_bo_free_kernel(>gmc.pdb0_bo, NULL, >gmc.ptr_pdb0); amdgpu_bo_fini(adev); + adev->gmc.num_mem_partitions = 0; + kfree(adev->gmc.mem_partitions); + return 0; } -- 2.42.0