Re: [PATCH 2/4] WIP: drm: Introduce rvkms

2024-04-29 Thread Lyude Paul
On Thu, 2024-04-25 at 15:46 +, Benno Lossin wrote:
> On 22.04.24 03:54, Lyude Paul wrote:
> > On Wed, 2024-03-27 at 21:06 +, Benno Lossin wrote:
> > > On 22.03.24 23:03, Lyude Paul wrote:
> > > > +
> > > > +pub(crate) type Connector =
> > > > connector::Connector;
> > > > +
> > > > +impl connector::DriverConnector for DriverConnector {
> > > > +    type Initializer = impl PinInit;
> > > > +
> > > > +    type State = ConnectorState;
> > > > +
> > > > +    type Driver = RvkmsDriver;
> > > > +
> > > > +    type Args = ();
> > > > +
> > > > +    fn new(dev: , args: Self::Args) ->
> > > > Self::Initializer {
> > > 
> > > And then here just return `Self`.
> > > 
> > > This works, since there is a blanket impl `PinInit for T`.
> > > 
> > > Looking at how you use this API, I am not sure if you actually
> > > need
> > > pin-init for the type that implements `DriverConnector`.
> > > Do you need to store eg `Mutex` or something else that needs
> > > pin-init in here in a more complex driver?
> > 
> > Most likely yes - a lot of drivers have various private locks
> > contained
> > within their subclassed mode objects. I'm not sure we will in
> > rvkms's
> > connector since vkms doesn't really do much with connectors - but
> > we at
> > a minimum be using pinned types (spinlocks and hrtimers) in our
> > DriverCrtc implementation once I've started implementing support
> > for
> > vblanks[1]
> > 
> > [1]
> > https://www.kernel.org/doc/html/v6.9-rc5/gpu/drm-kms.html?highlight=vblank#vertical-blanking
> > 
> > In nova (the main reason I'm working on rvkms in the first place),
> > we'll definitely have locks in our connectors and possibly other
> > types.
> 
> I see, in that case it would be a good idea to either have an RFC of
> the nova driver (or something else that needs pinned types) as
> motivation for why it needs to be pin-initialized.

I mean - I'll happily include this with the RFC of nova if nova is
ready at that point, but the purpose of rvkms is to exercise enough of
this API to justify merging it :P - and I think it's a lot likely rvkm
is probably going to be ready well before nova gets to the point of
modesetting. And we will definitely have some uses of pinned types in
rvkms once the driver's ready for submission.

> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



[PATCH v2 2/2] drm/nouveau/gsp: Use the sg allocator for level 2 of radix3

2024-04-29 Thread Lyude Paul
Currently we allocate all 3 levels of radix3 page tables using
nvkm_gsp_mem_ctor(), which uses dma_alloc_coherent() for allocating all of
the relevant memory. This can end up failing in scenarios where the system
has very high memory fragmentation, and we can't find enough contiguous
memory to allocate level 2 of the page table.

Currently, this can result in runtime PM issues on systems where memory
fragmentation is high - as we'll fail to allocate the page table for our
suspend/resume buffer:

  kworker/10:2: page allocation failure: order:7, mode:0xcc0(GFP_KERNEL),
  nodemask=(null),cpuset=/,mems_allowed=0
  CPU: 10 PID: 479809 Comm: kworker/10:2 Not tainted
  6.8.6-201.ChopperV6.fc39.x86_64 #1
  Hardware name: SLIMBOOK Executive/Executive, BIOS N.1.10GRU06 02/02/2024
  Workqueue: pm pm_runtime_work
  Call Trace:
   
   dump_stack_lvl+0x64/0x80
   warn_alloc+0x165/0x1e0
   ? __alloc_pages_direct_compact+0xb3/0x2b0
   __alloc_pages_slowpath.constprop.0+0xd7d/0xde0
   __alloc_pages+0x32d/0x350
   __dma_direct_alloc_pages.isra.0+0x16a/0x2b0
   dma_direct_alloc+0x70/0x270
   nvkm_gsp_radix3_sg+0x5e/0x130 [nouveau]
   r535_gsp_fini+0x1d4/0x350 [nouveau]
   nvkm_subdev_fini+0x67/0x150 [nouveau]
   nvkm_device_fini+0x95/0x1e0 [nouveau]
   nvkm_udevice_fini+0x53/0x70 [nouveau]
   nvkm_object_fini+0xb9/0x240 [nouveau]
   nvkm_object_fini+0x75/0x240 [nouveau]
   nouveau_do_suspend+0xf5/0x280 [nouveau]
   nouveau_pmops_runtime_suspend+0x3e/0xb0 [nouveau]
   pci_pm_runtime_suspend+0x67/0x1e0
   ? __pfx_pci_pm_runtime_suspend+0x10/0x10
   __rpm_callback+0x41/0x170
   ? __pfx_pci_pm_runtime_suspend+0x10/0x10
   rpm_callback+0x5d/0x70
   ? __pfx_pci_pm_runtime_suspend+0x10/0x10
   rpm_suspend+0x120/0x6a0
   pm_runtime_work+0x98/0xb0
   process_one_work+0x171/0x340
   worker_thread+0x27b/0x3a0
   ? __pfx_worker_thread+0x10/0x10
   kthread+0xe5/0x120
   ? __pfx_kthread+0x10/0x10
   ret_from_fork+0x31/0x50
   ? __pfx_kthread+0x10/0x10
   ret_from_fork_asm+0x1b/0x30

Luckily, we don't actually need to allocate coherent memory for the page
table thanks to being able to pass the GPU a radix3 page table for
suspend/resume data. So, let's rewrite nvkm_gsp_radix3_sg() to use the sg
allocator for level 2. We continue using coherent allocations for lvl0 and
1, since they only take a single page.

V2:
* Don't forget to actually jump to the next scatterlist when we reach the
  end of the scatterlist we're currently on when writing out the page table
  for level 2

Signed-off-by: Lyude Paul 
Cc: sta...@vger.kernel.org
---
 .../gpu/drm/nouveau/include/nvkm/subdev/gsp.h |  4 +-
 .../gpu/drm/nouveau/nvkm/subdev/gsp/r535.c| 77 ---
 2 files changed, 54 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h 
b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
index 6f5d376d8fcc1..a11d16a16c3b2 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
@@ -15,7 +15,9 @@ struct nvkm_gsp_mem {
 };
 
 struct nvkm_gsp_radix3 {
-   struct nvkm_gsp_mem mem[3];
+   struct nvkm_gsp_mem lvl0;
+   struct nvkm_gsp_mem lvl1;
+   struct sg_table lvl2;
 };
 
 int nvkm_gsp_sg(struct nvkm_device *, u64 size, struct sg_table *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
index 9858c1438aa7f..fd4e80ba6adfc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
@@ -1624,7 +1624,7 @@ r535_gsp_wpr_meta_init(struct nvkm_gsp *gsp)
meta->magic = GSP_FW_WPR_META_MAGIC;
meta->revision = GSP_FW_WPR_META_REVISION;
 
-   meta->sysmemAddrOfRadix3Elf = gsp->radix3.mem[0].addr;
+   meta->sysmemAddrOfRadix3Elf = gsp->radix3.lvl0.addr;
meta->sizeOfRadix3Elf = gsp->fb.wpr2.elf.size;
 
meta->sysmemAddrOfBootloader = gsp->boot.fw.addr;
@@ -1919,8 +1919,9 @@ nvkm_gsp_sg(struct nvkm_device *device, u64 size, struct 
sg_table *sgt)
 static void
 nvkm_gsp_radix3_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_radix3 *rx3)
 {
-   for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--)
-   nvkm_gsp_mem_dtor(gsp, >mem[i]);
+   nvkm_gsp_sg_free(gsp->subdev.device, >lvl2);
+   nvkm_gsp_mem_dtor(gsp, >lvl1);
+   nvkm_gsp_mem_dtor(gsp, >lvl0);
 }
 
 /**
@@ -1960,36 +1961,60 @@ static int
 nvkm_gsp_radix3_sg(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size,
   struct nvkm_gsp_radix3 *rx3)
 {
-   u64 addr;
+   struct sg_dma_page_iter sg_dma_iter;
+   struct scatterlist *sg;
+   size_t bufsize;
+   u64 *pte;
+   int ret, i, page_idx = 0;
 
-   for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--) {
-   u64 *ptes;
-   size_t bufsize;
-   int ret, idx;
+   ret = nvkm_gsp_mem_ctor(gsp, GSP_PAGE_SIZE, >lvl0);
+   if (ret)
+  

[PATCH v2 1/2] drm/nouveau/firmware: Fix SG_DEBUG error with nvkm_firmware_ctor()

2024-04-29 Thread Lyude Paul
Currently, enabling SG_DEBUG in the kernel will cause nouveau to hit a
BUG() on startup:

  kernel BUG at include/linux/scatterlist.h:187!
  invalid opcode:  [#1] PREEMPT SMP NOPTI
  CPU: 7 PID: 930 Comm: (udev-worker) Not tainted 6.9.0-rc3Lyude-Test+ #30
  Hardware name: MSI MS-7A39/A320M GAMING PRO (MS-7A39), BIOS 1.I0 01/22/2019
  RIP: 0010:sg_init_one+0x85/0xa0
  Code: 69 88 32 01 83 e1 03 f6 c3 03 75 20 a8 01 75 1e 48 09 cb 41 89 54
  24 08 49 89 1c 24 41 89 6c 24 0c 5b 5d 41 5c e9 7b b9 88 00 <0f> 0b 0f 0b
  0f 0b 48 8b 05 5e 46 9a 01 eb b2 66 66 2e 0f 1f 84 00
  RSP: 0018:a776017bf6a0 EFLAGS: 00010246
  RAX:  RBX: a77600d87000 RCX: 002b
  RDX: 0001 RSI:  RDI: a77680d87000
  RBP: e000 R08:  R09: 
  R10: 98f4c46aa508 R11:  R12: 98f4c46aa508
  R13: 98f4c46aa008 R14: a77600d4a000 R15: a77600d4a018
  FS:  7feeb5aae980() GS:98f5c4dc() knlGS:
  CS:  0010 DS:  ES:  CR0: 80050033
  CR2: 7f22cb9a4520 CR3: 0001043ba000 CR4: 003506f0
  Call Trace:
   
   ? die+0x36/0x90
   ? do_trap+0xdd/0x100
   ? sg_init_one+0x85/0xa0
   ? do_error_trap+0x65/0x80
   ? sg_init_one+0x85/0xa0
   ? exc_invalid_op+0x50/0x70
   ? sg_init_one+0x85/0xa0
   ? asm_exc_invalid_op+0x1a/0x20
   ? sg_init_one+0x85/0xa0
   nvkm_firmware_ctor+0x14a/0x250 [nouveau]
   nvkm_falcon_fw_ctor+0x42/0x70 [nouveau]
   ga102_gsp_booter_ctor+0xb4/0x1a0 [nouveau]
   r535_gsp_oneinit+0xb3/0x15f0 [nouveau]
   ? srso_return_thunk+0x5/0x5f
   ? srso_return_thunk+0x5/0x5f
   ? nvkm_udevice_new+0x95/0x140 [nouveau]
   ? srso_return_thunk+0x5/0x5f
   ? srso_return_thunk+0x5/0x5f
   ? ktime_get+0x47/0xb0
   ? srso_return_thunk+0x5/0x5f
   nvkm_subdev_oneinit_+0x4f/0x120 [nouveau]
   nvkm_subdev_init_+0x39/0x140 [nouveau]
   ? srso_return_thunk+0x5/0x5f
   nvkm_subdev_init+0x44/0x90 [nouveau]
   nvkm_device_init+0x166/0x2e0 [nouveau]
   nvkm_udevice_init+0x47/0x70 [nouveau]
   nvkm_object_init+0x41/0x1c0 [nouveau]
   nvkm_ioctl_new+0x16a/0x290 [nouveau]
   ? __pfx_nvkm_client_child_new+0x10/0x10 [nouveau]
   ? __pfx_nvkm_udevice_new+0x10/0x10 [nouveau]
   nvkm_ioctl+0x126/0x290 [nouveau]
   nvif_object_ctor+0x112/0x190 [nouveau]
   nvif_device_ctor+0x23/0x60 [nouveau]
   nouveau_cli_init+0x164/0x640 [nouveau]
   nouveau_drm_device_init+0x97/0x9e0 [nouveau]
   ? srso_return_thunk+0x5/0x5f
   ? pci_update_current_state+0x72/0xb0
   ? srso_return_thunk+0x5/0x5f
   nouveau_drm_probe+0x12c/0x280 [nouveau]
   ? srso_return_thunk+0x5/0x5f
   local_pci_probe+0x45/0xa0
   pci_device_probe+0xc7/0x270
   really_probe+0xe6/0x3a0
   __driver_probe_device+0x87/0x160
   driver_probe_device+0x1f/0xc0
   __driver_attach+0xec/0x1f0
   ? __pfx___driver_attach+0x10/0x10
   bus_for_each_dev+0x88/0xd0
   bus_add_driver+0x116/0x220
   driver_register+0x59/0x100
   ? __pfx_nouveau_drm_init+0x10/0x10 [nouveau]
   do_one_initcall+0x5b/0x320
   do_init_module+0x60/0x250
   init_module_from_file+0x86/0xc0
   idempotent_init_module+0x120/0x2b0
   __x64_sys_finit_module+0x5e/0xb0
   do_syscall_64+0x83/0x160
   ? srso_return_thunk+0x5/0x5f
   entry_SYSCALL_64_after_hwframe+0x71/0x79
  RIP: 0033:0x7feeb5cc20cd
  Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89
  f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0
  ff ff 73 01 c3 48 8b 0d 1b cd 0c 00 f7 d8 64 89 01 48
  RSP: 002b:7ffcf220b2c8 EFLAGS: 0246 ORIG_RAX: 0139
  RAX: ffda RBX: 55fdd2916aa0 RCX: 7feeb5cc20cd
  RDX:  RSI: 55fdd29161e0 RDI: 0035
  RBP: 7ffcf220b380 R08: 7feeb5d8fb20 R09: 7ffcf220b310
  R10: 55fdd2909dc0 R11: 0246 R12: 55fdd29161e0
  R13: 0002 R14: 55fdd29203e0 R15: 55fdd2909d80
   

We hit this when trying to initialize firmware of type
NVKM_FIRMWARE_IMG_DMA because we allocate our memory with
dma_alloc_coherent, and DMA allocations can't be turned back into memory
pages - which a scatterlist needs in order to map them.

So, fix this by allocating the memory with vmalloc instead().

V2:
* Fixup explanation as the prior one was bogus

Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvkm/core/firmware.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c 
b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
index adc60b25f8e6c..141b0a513bf52 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
@@ -205,7 +205,9 @@ nvkm_firmware_dtor(struct nvkm_firmware *fw)
break;
case NVKM_FIRMWARE_IMG_DMA:
nvkm_memory_unref();
-   dma_free_coherent(fw->device->dev, sg_dma_len(>mem.sgl), 
fw->img, fw->phys);
+   dma_unmap_singl

Re: [PATCH 2/2] drm/nouveau/gsp: Use the sg allocator for level 2 of radix3

2024-04-29 Thread Lyude Paul
On Mon, 2024-04-29 at 16:03 +1000, Dave Airlie wrote:
> > Currently, this can result in runtime PM issues on systems where
> > memory
> > Luckily, we don't actually need to allocate coherent memory for the
> > page
> > table thanks to being able to pass the GPU a radix3 page table for
> > suspend/resume data. So, let's rewrite nvkm_gsp_radix3_sg() to use
> > the sg
> > allocator for level 2. We continue using coherent allocations for
> > lvl0 and
> > 1, since they only take a single page.
> > 
> > Signed-off-by: Lyude Paul 
> > Cc: sta...@vger.kernel.org
> > ---
> >  .../gpu/drm/nouveau/include/nvkm/subdev/gsp.h |  4 +-
> >  .../gpu/drm/nouveau/nvkm/subdev/gsp/r535.c    | 71 ---
> > 
> >  2 files changed, 47 insertions(+), 28 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
> > b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
> > index 6f5d376d8fcc1..a11d16a16c3b2 100644
> > --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
> > +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
> > @@ -15,7 +15,9 @@ struct nvkm_gsp_mem {
> >  };
> > 
> >  struct nvkm_gsp_radix3 {
> > -   struct nvkm_gsp_mem mem[3];
> > +   struct nvkm_gsp_mem lvl0;
> > +   struct nvkm_gsp_mem lvl1;
> > +   struct sg_table lvl2;
> 
> This looks great, could we go a step further and combine lvl0 and
> lvl1
> into a 2 page allocation, I thought we could combine lvl0/lvl1 into a
> 2 page alloc, but that actually might be a bad idea under memory
> pressure.

I'm not sure I understand :P, do we want to go for that or not? TBH -
I'm not sure there's any hardware reason we wouldn't be able to do the
whole radix3 table as an sg allocation with two additional memory pages
added on for level 0 and 1 - since both of those can only be the size
of a single page anyway it probably doesn't make much of a difference.

The main reason I didn't end up doing that though is because it would
make the codepath in nvkm_radix3_sg() a lot uglier. We need the virtual
addresses of level 0-2's first/only pages to populate them, and we also
need the DMA addresses of level 1-2. There isn't an iterator that lets
you go through both DMA/virtual addresses as far as I can tell - and
even if there was we'd start having to keep track of when we reach the
end of a page in the loop and make sure that we always set pte to the
address of the third sg page on the first iteration of the loop. IMO,
scatterlist could definitely benefit from having an iterator that does
both and can be stepped through both in and out of for loop macros
(like Iterator in rust).

So - it's definitely possible, but considering:

 * nvkm_gsp_mem isn't a very big struct
 * We're only allocating a single page for level 0 and 1, so at least
   according to the advice I got from Sima this should be a safe amount
   to allocate coherently under memory pressure.
 * It's just a lot easier code-wise having direct address to the
   DMA/virt addresses for the first two levels

I decided to stay with nvkm_gsp_mem_ctor() for the first two pages and
just use nvkm_gsp_sg() for the rest. I can definitely convert the whole
thing to using nvkm_gsp_sg() if we really want though - but I don't
think it'll give us much benefit.

I'll send out the new version of the patch without these changes and a
fix for one of the issues with this patch I already mentioned to Timur,
just let me know what you end up deciding and I can revise the patch if
you want.

> 
> Dave.
> 

-- 
Cheers, Lyude Paul (she/her) Software Engineer at Red Hat



Re: [PATCH 1/2] drm/nouveau/firmware: Fix SG_DEBUG error with nvkm_firmware_ctor()

2024-04-28 Thread Lyude Paul
On Fri, 2024-04-26 at 15:47 +, Timur Tabi wrote:
> On Fri, 2024-04-26 at 11:41 -0400, Lyude Paul wrote:
> > We hit this because when initializing firmware of type
> > NVKM_FIRMWARE_IMG_DMA we allocate coherent memory and then attempt
> > to
> > include that coherent memory in a scatterlist. 
> 
> I'm sure this patch is a good one, and I will try to test it soon,
> but I am
> very curious to know why including coherent memory in a scatterlist
> is bad.

Thanks for asking this as I think you unintentionally pointed out this
explanation I gave doesn't make sense - so I looked a bit more into it.
The issue isn't coherent memory in the scatterlist, the issue is that
we're allocating with dma_alloc_coherent(). And according to the source
in dma_alloc_attrs() (which dma_alloc_coherent() is just a wrapper)
for):

   /*
* DMA allocations can never be turned back into a page pointer, so
* requesting compound pages doesn't make sense (and can't even be
* supported at all by various backends).
*/
   if (WARN_ON_ONCE(flag & __GFP_COMP))
return NULL;

Which explains the check in sg_set_buf() that this patch stops us from
hitting:

   BUG_ON(!virt_addr_valid(buf));

Scatterlists need page pointers (we use one later down here:)

   sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));

But we can't get a page pointer from an allocation made by
dma_alloc_coherent() - but we can from vmalloc(). I'll fix the patch
explanation in the next version, I have to send out another version
anyhow since I realized that patch #2 still needs one more check to
work properly
-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



[PATCH 2/2] drm/nouveau/gsp: Use the sg allocator for level 2 of radix3

2024-04-26 Thread Lyude Paul
Currently we allocate all 3 levels of radix3 page tables using
nvkm_gsp_mem_ctor(), which uses dma_alloc_coherent() for allocating all of
the relevant memory. This can end up failing in scenarios where the system
has very high memory fragmentation, and we can't find enough contiguous
memory to allocate level 2 of the page table.

Currently, this can result in runtime PM issues on systems where memory
fragmentation is high - as we'll fail to allocate the page table for our
suspend/resume buffer:

  kworker/10:2: page allocation failure: order:7, mode:0xcc0(GFP_KERNEL),
  nodemask=(null),cpuset=/,mems_allowed=0
  CPU: 10 PID: 479809 Comm: kworker/10:2 Not tainted
  6.8.6-201.ChopperV6.fc39.x86_64 #1
  Hardware name: SLIMBOOK Executive/Executive, BIOS N.1.10GRU06 02/02/2024
  Workqueue: pm pm_runtime_work
  Call Trace:
   
   dump_stack_lvl+0x64/0x80
   warn_alloc+0x165/0x1e0
   ? __alloc_pages_direct_compact+0xb3/0x2b0
   __alloc_pages_slowpath.constprop.0+0xd7d/0xde0
   __alloc_pages+0x32d/0x350
   __dma_direct_alloc_pages.isra.0+0x16a/0x2b0
   dma_direct_alloc+0x70/0x270
   nvkm_gsp_radix3_sg+0x5e/0x130 [nouveau]
   r535_gsp_fini+0x1d4/0x350 [nouveau]
   nvkm_subdev_fini+0x67/0x150 [nouveau]
   nvkm_device_fini+0x95/0x1e0 [nouveau]
   nvkm_udevice_fini+0x53/0x70 [nouveau]
   nvkm_object_fini+0xb9/0x240 [nouveau]
   nvkm_object_fini+0x75/0x240 [nouveau]
   nouveau_do_suspend+0xf5/0x280 [nouveau]
   nouveau_pmops_runtime_suspend+0x3e/0xb0 [nouveau]
   pci_pm_runtime_suspend+0x67/0x1e0
   ? __pfx_pci_pm_runtime_suspend+0x10/0x10
   __rpm_callback+0x41/0x170
   ? __pfx_pci_pm_runtime_suspend+0x10/0x10
   rpm_callback+0x5d/0x70
   ? __pfx_pci_pm_runtime_suspend+0x10/0x10
   rpm_suspend+0x120/0x6a0
   pm_runtime_work+0x98/0xb0
   process_one_work+0x171/0x340
   worker_thread+0x27b/0x3a0
   ? __pfx_worker_thread+0x10/0x10
   kthread+0xe5/0x120
   ? __pfx_kthread+0x10/0x10
   ret_from_fork+0x31/0x50
   ? __pfx_kthread+0x10/0x10
   ret_from_fork_asm+0x1b/0x30

Luckily, we don't actually need to allocate coherent memory for the page
table thanks to being able to pass the GPU a radix3 page table for
suspend/resume data. So, let's rewrite nvkm_gsp_radix3_sg() to use the sg
allocator for level 2. We continue using coherent allocations for lvl0 and
1, since they only take a single page.

Signed-off-by: Lyude Paul 
Cc: sta...@vger.kernel.org
---
 .../gpu/drm/nouveau/include/nvkm/subdev/gsp.h |  4 +-
 .../gpu/drm/nouveau/nvkm/subdev/gsp/r535.c| 71 ---
 2 files changed, 47 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h 
b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
index 6f5d376d8fcc1..a11d16a16c3b2 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
@@ -15,7 +15,9 @@ struct nvkm_gsp_mem {
 };
 
 struct nvkm_gsp_radix3 {
-   struct nvkm_gsp_mem mem[3];
+   struct nvkm_gsp_mem lvl0;
+   struct nvkm_gsp_mem lvl1;
+   struct sg_table lvl2;
 };
 
 int nvkm_gsp_sg(struct nvkm_device *, u64 size, struct sg_table *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
index 9858c1438aa7f..2bf9077d37118 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
@@ -1624,7 +1624,7 @@ r535_gsp_wpr_meta_init(struct nvkm_gsp *gsp)
meta->magic = GSP_FW_WPR_META_MAGIC;
meta->revision = GSP_FW_WPR_META_REVISION;
 
-   meta->sysmemAddrOfRadix3Elf = gsp->radix3.mem[0].addr;
+   meta->sysmemAddrOfRadix3Elf = gsp->radix3.lvl0.addr;
meta->sizeOfRadix3Elf = gsp->fb.wpr2.elf.size;
 
meta->sysmemAddrOfBootloader = gsp->boot.fw.addr;
@@ -1919,8 +1919,9 @@ nvkm_gsp_sg(struct nvkm_device *device, u64 size, struct 
sg_table *sgt)
 static void
 nvkm_gsp_radix3_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_radix3 *rx3)
 {
-   for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--)
-   nvkm_gsp_mem_dtor(gsp, >mem[i]);
+   nvkm_gsp_sg_free(gsp->subdev.device, >lvl2);
+   nvkm_gsp_mem_dtor(gsp, >lvl1);
+   nvkm_gsp_mem_dtor(gsp, >lvl0);
 }
 
 /**
@@ -1960,36 +1961,52 @@ static int
 nvkm_gsp_radix3_sg(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size,
   struct nvkm_gsp_radix3 *rx3)
 {
-   u64 addr;
+   struct sg_dma_page_iter sg_dma_iter;
+   struct scatterlist *sg;
+   size_t bufsize;
+   u64 *pte;
+   int ret, i, page_idx = 0;
 
-   for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--) {
-   u64 *ptes;
-   size_t bufsize;
-   int ret, idx;
-
-   bufsize = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), 
GSP_PAGE_SIZE);
-   ret = nvkm_gsp_mem_ctor(gsp, bufsize, >mem[i]);
-   if (ret)
-   return ret;
+   ret = nvkm_gsp_mem_ctor(gsp, GS

[PATCH 1/2] drm/nouveau/firmware: Fix SG_DEBUG error with nvkm_firmware_ctor()

2024-04-26 Thread Lyude Paul
Currently, enabling SG_DEBUG in the kernel will cause nouveau to hit a
BUG() on startup:

  kernel BUG at include/linux/scatterlist.h:187!
  invalid opcode:  [#1] PREEMPT SMP NOPTI
  CPU: 7 PID: 930 Comm: (udev-worker) Not tainted 6.9.0-rc3Lyude-Test+ #30
  Hardware name: MSI MS-7A39/A320M GAMING PRO (MS-7A39), BIOS 1.I0 01/22/2019
  RIP: 0010:sg_init_one+0x85/0xa0
  Code: 69 88 32 01 83 e1 03 f6 c3 03 75 20 a8 01 75 1e 48 09 cb 41 89 54
  24 08 49 89 1c 24 41 89 6c 24 0c 5b 5d 41 5c e9 7b b9 88 00 <0f> 0b 0f 0b
  0f 0b 48 8b 05 5e 46 9a 01 eb b2 66 66 2e 0f 1f 84 00
  RSP: 0018:a776017bf6a0 EFLAGS: 00010246
  RAX:  RBX: a77600d87000 RCX: 002b
  RDX: 0001 RSI:  RDI: a77680d87000
  RBP: e000 R08:  R09: 
  R10: 98f4c46aa508 R11:  R12: 98f4c46aa508
  R13: 98f4c46aa008 R14: a77600d4a000 R15: a77600d4a018
  FS:  7feeb5aae980() GS:98f5c4dc() knlGS:
  CS:  0010 DS:  ES:  CR0: 80050033
  CR2: 7f22cb9a4520 CR3: 0001043ba000 CR4: 003506f0
  Call Trace:
   
   ? die+0x36/0x90
   ? do_trap+0xdd/0x100
   ? sg_init_one+0x85/0xa0
   ? do_error_trap+0x65/0x80
   ? sg_init_one+0x85/0xa0
   ? exc_invalid_op+0x50/0x70
   ? sg_init_one+0x85/0xa0
   ? asm_exc_invalid_op+0x1a/0x20
   ? sg_init_one+0x85/0xa0
   nvkm_firmware_ctor+0x14a/0x250 [nouveau]
   nvkm_falcon_fw_ctor+0x42/0x70 [nouveau]
   ga102_gsp_booter_ctor+0xb4/0x1a0 [nouveau]
   r535_gsp_oneinit+0xb3/0x15f0 [nouveau]
   ? srso_return_thunk+0x5/0x5f
   ? srso_return_thunk+0x5/0x5f
   ? nvkm_udevice_new+0x95/0x140 [nouveau]
   ? srso_return_thunk+0x5/0x5f
   ? srso_return_thunk+0x5/0x5f
   ? ktime_get+0x47/0xb0
   ? srso_return_thunk+0x5/0x5f
   nvkm_subdev_oneinit_+0x4f/0x120 [nouveau]
   nvkm_subdev_init_+0x39/0x140 [nouveau]
   ? srso_return_thunk+0x5/0x5f
   nvkm_subdev_init+0x44/0x90 [nouveau]
   nvkm_device_init+0x166/0x2e0 [nouveau]
   nvkm_udevice_init+0x47/0x70 [nouveau]
   nvkm_object_init+0x41/0x1c0 [nouveau]
   nvkm_ioctl_new+0x16a/0x290 [nouveau]
   ? __pfx_nvkm_client_child_new+0x10/0x10 [nouveau]
   ? __pfx_nvkm_udevice_new+0x10/0x10 [nouveau]
   nvkm_ioctl+0x126/0x290 [nouveau]
   nvif_object_ctor+0x112/0x190 [nouveau]
   nvif_device_ctor+0x23/0x60 [nouveau]
   nouveau_cli_init+0x164/0x640 [nouveau]
   nouveau_drm_device_init+0x97/0x9e0 [nouveau]
   ? srso_return_thunk+0x5/0x5f
   ? pci_update_current_state+0x72/0xb0
   ? srso_return_thunk+0x5/0x5f
   nouveau_drm_probe+0x12c/0x280 [nouveau]
   ? srso_return_thunk+0x5/0x5f
   local_pci_probe+0x45/0xa0
   pci_device_probe+0xc7/0x270
   really_probe+0xe6/0x3a0
   __driver_probe_device+0x87/0x160
   driver_probe_device+0x1f/0xc0
   __driver_attach+0xec/0x1f0
   ? __pfx___driver_attach+0x10/0x10
   bus_for_each_dev+0x88/0xd0
   bus_add_driver+0x116/0x220
   driver_register+0x59/0x100
   ? __pfx_nouveau_drm_init+0x10/0x10 [nouveau]
   do_one_initcall+0x5b/0x320
   do_init_module+0x60/0x250
   init_module_from_file+0x86/0xc0
   idempotent_init_module+0x120/0x2b0
   __x64_sys_finit_module+0x5e/0xb0
   do_syscall_64+0x83/0x160
   ? srso_return_thunk+0x5/0x5f
   entry_SYSCALL_64_after_hwframe+0x71/0x79
  RIP: 0033:0x7feeb5cc20cd
  Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89
  f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0
  ff ff 73 01 c3 48 8b 0d 1b cd 0c 00 f7 d8 64 89 01 48
  RSP: 002b:7ffcf220b2c8 EFLAGS: 0246 ORIG_RAX: 0139
  RAX: ffda RBX: 55fdd2916aa0 RCX: 7feeb5cc20cd
  RDX:  RSI: 55fdd29161e0 RDI: 0035
  RBP: 7ffcf220b380 R08: 7feeb5d8fb20 R09: 7ffcf220b310
  R10: 55fdd2909dc0 R11: 0246 R12: 55fdd29161e0
  R13: 0002 R14: 55fdd29203e0 R15: 55fdd2909d80
   

We hit this because when initializing firmware of type
NVKM_FIRMWARE_IMG_DMA we allocate coherent memory and then attempt to
include that coherent memory in a scatterlist. What we actually mean to do
here though is to pass a CPU-allocated memory address, since that's the
only thing that would make sense to put in the scatterlist.

Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvkm/core/firmware.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c 
b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
index adc60b25f8e6c..141b0a513bf52 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
@@ -205,7 +205,9 @@ nvkm_firmware_dtor(struct nvkm_firmware *fw)
break;
case NVKM_FIRMWARE_IMG_DMA:
nvkm_memory_unref();
-   dma_free_coherent(fw->device->dev, sg_dma_len(>mem.sgl), 
fw->img, fw->phys);
+   dma_unmap_single(fw->device->de

Re: [PATCH 1/2] drm/print: drop include debugfs.h and include where needed

2024-04-24 Thread Lyude Paul
For the nouveau bits:

Reviewed-by: Lyude Paul 

On Mon, 2024-04-22 at 15:10 +0300, Jani Nikula wrote:
> Surprisingly many places depend on debugfs.h to be included via
> drm_print.h. Fix them.
> 
> v3: Also fix armada, ite-it6505, imagination, msm, sti, vc4, and xe
> 
> v2: Also fix ivpu and vmwgfx
> 
> Reviewed-by: Andrzej Hajda 
> Acked-by: Maxime Ripard 
> Link:
> https://patchwork.freedesktop.org/patch/msgid/20240410141434.157908-1-jani.nik...@intel.com
> Signed-off-by: Jani Nikula 
> 
> ---
> 
> Cc: Jacek Lawrynowicz 
> Cc: Stanislaw Gruszka 
> Cc: Oded Gabbay 
> Cc: Russell King 
> Cc: David Airlie 
> Cc: Daniel Vetter 
> Cc: Andrzej Hajda 
> Cc: Neil Armstrong 
> Cc: Robert Foss 
> Cc: Laurent Pinchart 
> Cc: Jonas Karlman 
> Cc: Jernej Skrabec 
> Cc: Maarten Lankhorst 
> Cc: Maxime Ripard 
> Cc: Thomas Zimmermann 
> Cc: Jani Nikula 
> Cc: Rodrigo Vivi 
> Cc: Joonas Lahtinen 
> Cc: Tvrtko Ursulin 
> Cc: Frank Binns 
> Cc: Matt Coster 
> Cc: Rob Clark 
> Cc: Abhinav Kumar 
> Cc: Dmitry Baryshkov 
> Cc: Sean Paul 
> Cc: Marijn Suijten 
> Cc: Karol Herbst 
> Cc: Lyude Paul 
> Cc: Danilo Krummrich 
> Cc: Alex Deucher 
> Cc: "Christian König" 
> Cc: "Pan, Xinhui" 
> Cc: Alain Volmat 
> Cc: Huang Rui 
> Cc: Zack Rusin 
> Cc: Broadcom internal kernel review list
> 
> Cc: Lucas De Marchi 
> Cc: "Thomas Hellström" 
> Cc: dri-devel@lists.freedesktop.org
> Cc: intel-...@lists.freedesktop.org
> Cc: intel...@lists.freedesktop.org
> Cc: linux-arm-...@vger.kernel.org
> Cc: freedr...@lists.freedesktop.org
> Cc: nouv...@lists.freedesktop.org
> Cc: amd-...@lists.freedesktop.org
> ---
>  drivers/accel/ivpu/ivpu_debugfs.c   | 2 ++
>  drivers/gpu/drm/armada/armada_debugfs.c | 1 +
>  drivers/gpu/drm/bridge/ite-it6505.c | 1 +
>  drivers/gpu/drm/bridge/panel.c  | 2 ++
>  drivers/gpu/drm/drm_print.c | 6 +++---
>  drivers/gpu/drm/i915/display/intel_dmc.c    | 1 +
>  drivers/gpu/drm/imagination/pvr_fw_trace.c  | 1 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 2 ++
>  drivers/gpu/drm/nouveau/dispnv50/crc.c  | 2 ++
>  drivers/gpu/drm/radeon/r100.c   | 1 +
>  drivers/gpu/drm/radeon/r300.c   | 1 +
>  drivers/gpu/drm/radeon/r420.c   | 1 +
>  drivers/gpu/drm/radeon/r600.c   | 3 ++-
>  drivers/gpu/drm/radeon/radeon_fence.c   | 1 +
>  drivers/gpu/drm/radeon/radeon_gem.c | 1 +
>  drivers/gpu/drm/radeon/radeon_ib.c  | 2 ++
>  drivers/gpu/drm/radeon/radeon_pm.c  | 1 +
>  drivers/gpu/drm/radeon/radeon_ring.c    | 2 ++
>  drivers/gpu/drm/radeon/radeon_ttm.c | 1 +
>  drivers/gpu/drm/radeon/rs400.c  | 1 +
>  drivers/gpu/drm/radeon/rv515.c  | 1 +
>  drivers/gpu/drm/sti/sti_drv.c   | 1 +
>  drivers/gpu/drm/ttm/ttm_device.c    | 1 +
>  drivers/gpu/drm/ttm/ttm_resource.c  | 3 ++-
>  drivers/gpu/drm/ttm/ttm_tt.c    | 5 +++--
>  drivers/gpu/drm/vc4/vc4_drv.h   | 1 +
>  drivers/gpu/drm/vmwgfx/vmwgfx_gem.c | 2 ++
>  drivers/gpu/drm/xe/xe_debugfs.c | 1 +
>  drivers/gpu/drm/xe/xe_gt_debugfs.c  | 2 ++
>  drivers/gpu/drm/xe/xe_uc_debugfs.c  | 2 ++
>  include/drm/drm_print.h | 2 +-
>  31 files changed, 46 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/accel/ivpu/ivpu_debugfs.c
> b/drivers/accel/ivpu/ivpu_debugfs.c
> index d09d29775b3f..e07e447d08d1 100644
> --- a/drivers/accel/ivpu/ivpu_debugfs.c
> +++ b/drivers/accel/ivpu/ivpu_debugfs.c
> @@ -3,6 +3,8 @@
>   * Copyright (C) 2020-2023 Intel Corporation
>   */
>  
> +#include 
> +
>  #include 
>  #include 
>  #include 
> diff --git a/drivers/gpu/drm/armada/armada_debugfs.c
> b/drivers/gpu/drm/armada/armada_debugfs.c
> index 29f4b52e3c8d..a763349dd89f 100644
> --- a/drivers/gpu/drm/armada/armada_debugfs.c
> +++ b/drivers/gpu/drm/armada/armada_debugfs.c
> @@ -5,6 +5,7 @@
>   */
>  
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> diff --git a/drivers/gpu/drm/bridge/ite-it6505.c
> b/drivers/gpu/drm/bridge/ite-it6505.c
> index 27334173e911..3f68c82888c2 100644
> --- a/drivers/gpu/drm/bridge/ite-it6505.c
> +++ b/drivers/gpu/drm/bridge/ite-it6505.c
> @@ -3,6 +3,7 @@
>   * Copyright (c) 2020, The Linux Foundation. All rights reserved.
>   */
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> diff --git a/drivers/gpu/drm/bridge/panel.c
> b/drivers/gpu/drm/bridge/panel.c
> index 7f41525f7a6e..32506524d9a2 100644
> --- a/drivers/gpu/drm/bridge/panel.c
>

Re: [PATCH 2/4] WIP: drm: Introduce rvkms

2024-04-21 Thread Lyude Paul
On Wed, 2024-03-27 at 21:06 +, Benno Lossin wrote:
> On 22.03.24 23:03, Lyude Paul wrote:
> > diff --git a/drivers/gpu/drm/rvkms/connector.rs
> > b/drivers/gpu/drm/rvkms/connector.rs
> > new file mode 100644
> > index 0..40f84d38437ee
> > --- /dev/null
> > +++ b/drivers/gpu/drm/rvkms/connector.rs
> > @@ -0,0 +1,55 @@
> > +// TODO: License and stuff
> > +// Contain's rvkms's drm_connector implementation
> > +
> > +use super::{RvkmsDriver, RvkmsDevice, MAX_RES, DEFAULT_RES};
> > +use kernel::{
> > +    prelude::*,
> > +    drm::{
> > +    device::Device,
> > +    kms::{
> > +    connector::{self, ConnectorGuard},
> > +    ModeConfigGuard
> > +    }
> > +    },
> > +    prelude::*
> > +};
> > +use core::marker::PhantomPinned;
> > +
> > +#[pin_data]
> > +pub(crate) struct DriverConnector {
> > +    #[pin]
> > +    _p: PhantomPinned
> > +}
> 
> This struct does not need to be annotated with `#[pin_data]`, this
> should just work:
> 
> pub(crate) struct DriverConnector;
> 
> > +
> > +pub(crate) type Connector = connector::Connector;
> > +
> > +impl connector::DriverConnector for DriverConnector {
> > +    type Initializer = impl PinInit;
> > +
> > +    type State = ConnectorState;
> > +
> > +    type Driver = RvkmsDriver;
> > +
> > +    type Args = ();
> > +
> > +    fn new(dev: , args: Self::Args) ->
> > Self::Initializer {
> 
> And then here just return `Self`.
> 
> This works, since there is a blanket impl `PinInit for T`.
> 
> Looking at how you use this API, I am not sure if you actually need
> pin-init for the type that implements `DriverConnector`.
> Do you need to store eg `Mutex` or something else that needs
> pin-init in here in a more complex driver?

Most likely yes - a lot of drivers have various private locks contained
within their subclassed mode objects. I'm not sure we will in rvkms's
connector since vkms doesn't really do much with connectors - but we at
a minimum be using pinned types (spinlocks and hrtimers) in our
DriverCrtc implementation once I've started implementing support for
vblanks[1]

[1]
https://www.kernel.org/doc/html/v6.9-rc5/gpu/drm-kms.html?highlight=vblank#vertical-blanking

In nova (the main reason I'm working on rvkms in the first place),
we'll definitely have locks in our connectors and possibly other types.

> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH 1/4] WIP: rust: Add basic KMS bindings

2024-04-21 Thread Lyude Paul
On Wed, 2024-03-27 at 20:50 +, Benno Lossin wrote:
> Hi,
> 
> I just took a quick look and commented on the things that stuck
> out to me. Some general things:
> - several `unsafe` blocks have missing SAFETY comments,
> - missing documentation and examples.

This is really early on - so I had wanted to post a WIP before I
actually wrote up everything to make sure I'm going in the right
direction (I'm certainly not planning on leaving things undocumented
when this is actually ready for submission :).

> 
> On 22.03.24 23:03, Lyude Paul wrote:
> > Signed-off-by: Lyude Paul 
> > ---
> >  rust/bindings/bindings_helper.h  |   4 +
> >  rust/helpers.c   |  17 ++
> >  rust/kernel/drm/device.rs    |   2 +
> >  rust/kernel/drm/drv.rs   | 115 +++--
> >  rust/kernel/drm/kms.rs   | 146 +++
> >  rust/kernel/drm/kms/connector.rs | 404
> > +++
> >  rust/kernel/drm/kms/crtc.rs  | 300 +++
> >  rust/kernel/drm/kms/encoder.rs   | 175 +
> >  rust/kernel/drm/kms/plane.rs | 300 +++
> >  rust/kernel/drm/mod.rs   |   1 +
> >  10 files changed, 1448 insertions(+), 16 deletions(-)
> 
> Please try to break this up into smaller patches. It makes review
> a lot easier!

I'll definitely try to do that next time!

> 
> [...]
> 
> > diff --git a/rust/kernel/drm/kms.rs b/rust/kernel/drm/kms.rs
> > new file mode 100644
> > index 0..b55d14415367a
> > --- /dev/null
> > +++ b/rust/kernel/drm/kms.rs
> > @@ -0,0 +1,146 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR MIT
> > +
> > +//! KMS driver abstractions for rust.
> > +
> > +pub mod connector;
> > +pub mod crtc;
> > +pub mod encoder;
> > +pub mod plane;
> > +
> > +use crate::{
> > +    drm::{drv, device::Device},
> > +    prelude::*,
> > +    types::ARef,
> > +    private::Sealed
> > +};
> > +use core::{
> > +    ops::Deref,
> > +    ptr,
> > +};
> > +use bindings;
> > +
> > +#[derive(Copy, Clone)]
> > +pub struct ModeConfigInfo {
> > +    /// The minimum (w, h) resolution this driver can support
> > +    pub min_resolution: (i32, i32),
> > +    /// The maximum (w, h) resolution this driver can support
> > +    pub max_resolution: (i32, i32),
> > +    /// The maximum (w, h) cursor size this driver can support
> > +    pub max_cursor: (u32, u32),
> > +    /// The preferred depth for dumb ioctls
> > +    pub preferred_depth: u32,
> > +}
> > +
> > +// TODO: I am not totally sure about this. Ideally, I'd like a
> > nice way of hiding KMS-specific
> > +// functions for DRM drivers which don't implement KMS - so that
> > we don't have to have a bunch of
> > +// random modesetting functions all over the DRM device trait.
> > But, unfortunately I don't know of
> > +// any nice way of doing that yet :(
> 
> I don't follow, can't you put the KMS specific functions into the
> KmsDriver trait?

I can, lol. I realized how that would work a little while after writing
this, so I'm not quite sure where my confusion was with this - so I'll
fix this on the next version I send out.

> 
> > +
> > +/// An atomic KMS driver implementation
> > +pub trait KmsDriver: drv::Driver { }
> > +
> > +impl Device {
> > +    pub fn mode_config_reset() {
> > +    // SAFETY: The previous build assertion ensures this can
> > only be called for devices with KMS
> > +    // support, which means mode_config is initialized
> > +    unsafe { bindings::drm_mode_config_reset(self.drm.get()) }
> > +    }
> > +}
> > +
> > +/// Main trait for a modesetting object in DRM
> > +pub trait ModeObject: Sealed + Send + Sync {
> > +    /// The parent driver for this ModeObject
> > +    type Driver: KmsDriver;
> > +
> > +    /// Return the `drv::Device` for this `ModeObject`
> > +    fn drm_dev() -> ;
> > +}
> 
> [...]
> 
> > diff --git a/rust/kernel/drm/kms/connector.rs
> > b/rust/kernel/drm/kms/connector.rs
> > new file mode 100644
> > index 0..88dfa946d306b
> > --- /dev/null
> > +++ b/rust/kernel/drm/kms/connector.rs
> > @@ -0,0 +1,404 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR MIT
> > +
> > +//! Rust bindings for DRM connectors
> > +
> > +use crate::{
> > +    bindings,
> > +    sync::ArcBorrow,
> > +    drm::{
> > +    drv::{Driver, FEAT_MODESET},
> > +    device::Device,
> > +    },

Re: [PATCH v2 1/2] drm/nouveau/disp: add backlight for ada lovelace

2024-04-15 Thread Lyude Paul
Hm. Could you share some logs with drm.debug=0x116? I'm a bit confused
because I would have thought that we were already probing for eDP
backlights seeing as I added support for them at one point?

(I hope this isn't the point I learn I actually forgot to add support
for them :P)


On Fri, 2024-04-12 at 21:49 +0200, Angelo Dureghello wrote:
> Add working backlight for "ada lovelace" missing case.
> 
> The nvif method is actually not working for this chipset so
> used the drm apis. Also, by dpcd, drm layer is calculating a
> max brightness of 255, but to get a real correct max brightnes
> the maximum must be multiplied by a factor of 16.
> 
> Tested to work properly in Legion Lenovo Pro 5
> 
> Lenovo Legion 5 Pro 16ARX8
> Bios ver LPCN49WW
>LPEC49WW
> SN PF4T63AZ
> Nvidia RTX4060 MaxQ/Mobile rev a1 (ADA LOVELACE AD107M)
> AMD Ryzen 9 7945HX + Radeon
> 
> and wayland.
> 
> ---
> Changes for v2:
> - add some comments
> - remove x16 multiplication (hack)
> - remove forgot debug printk
> 
> Signed-off-by: Angelo Dureghello 
> ---
>  drivers/gpu/drm/nouveau/nouveau_backlight.c | 54
> +
>  1 file changed, 54 insertions(+)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c
> b/drivers/gpu/drm/nouveau/nouveau_backlight.c
> index d47442125fa1..7b7306d18ad7 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
> @@ -286,6 +286,56 @@ nv50_backlight_init(struct nouveau_backlight
> *bl,
>   return 0;
>  }
>  
> +static int
> +nv19x_backlight_init(struct nouveau_backlight *bl,
> +  struct nouveau_connector *nv_conn,
> +  struct nouveau_encoder *nv_encoder,
> +  struct backlight_properties *props,
> +  const struct backlight_ops **ops)
> +{
> + int ret;
> + u16 current_level;
> + u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
> + u8 current_mode;
> + struct nouveau_drm *drm = nouveau_drm(nv_encoder-
> >base.base.dev);
> +
> + /*
> +  * nvif functions, so also nvif_outp_bl_get, are not working
> with this
> +  * connector (return -22), using only drm layer.
> +  */
> + if (nv_conn->type == DCB_CONNECTOR_eDP) {
> +
> + ret = drm_dp_dpcd_read(_conn->aux,
> DP_EDP_DPCD_REV, edp_dpcd,
> +    EDP_DISPLAY_CTL_CAP_SIZE);
> + if (ret < 0)
> + return ret;
> + if (!drm_edp_backlight_supported(edp_dpcd))
> + return -ENODEV;
> +
> + ret = drm_edp_backlight_init(_conn->aux, 
> >edp_info, 0, edp_dpcd,
> +  _level,
> _mode);
> + if (ret < 0)
> + return ret;
> +
> + ret = drm_edp_backlight_enable(_conn->aux, 
> >edp_info, current_level);
> + if (ret < 0) {
> + NV_ERROR(drm, "Failed to enable backlight on
> %s: %d\n",
> +  nv_conn->base.name, ret);
> + return ret;
> + }
> +
> + *ops = _edp_bl_ops;
> +
> + props->max_brightness = bl->edp_info.max;
> + props->brightness = current_level;
> + bl->uses_dpcd = true;
> +
> + return 0;
> + }
> +
> + return -ENODEV;
> +}
> +
>  int
>  nouveau_backlight_init(struct drm_connector *connector)
>  {
> @@ -332,6 +382,10 @@ nouveau_backlight_init(struct drm_connector
> *connector)
>   ret = nv50_backlight_init(bl,
> nouveau_connector(connector),
>     nv_encoder, , );
>   break;
> + case NV_DEVICE_INFO_V0_ADA:
> + ret = nv19x_backlight_init(bl,
> nouveau_connector(connector),
> +    nv_encoder, ,
> );
> + break;
>   default:
>   ret = 0;
>   goto fail_alloc;

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH 4/5] drm/nouveau: Use drm_crtc_vblank_crtc()

2024-04-08 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Mon, 2024-04-08 at 22:06 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä 
> 
> Replace the open coded drm_crtc_vblank_crtc() with the real
> thing.
> 
> Cc: Karol Herbst 
> Cc: Lyude Paul 
> Cc: Danilo Krummrich 
> Cc: nouv...@lists.freedesktop.org
> Signed-off-by: Ville Syrjälä 
> ---
>  drivers/gpu/drm/nouveau/nouveau_display.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c
> b/drivers/gpu/drm/nouveau/nouveau_display.c
> index f28f9a857458..aed5d5b51b43 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_display.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_display.c
> @@ -83,7 +83,7 @@ static bool
>  nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos,
> int *hpos,
>   ktime_t *stime, ktime_t *etime)
>  {
> - struct drm_vblank_crtc *vblank = >dev-
> >vblank[drm_crtc_index(crtc)];
> + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
>   struct nvif_head *head = _crtc(crtc)->head;
>   struct nvif_head_scanoutpos_v0 args;
>   int retry = 20;

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH] drm: nv04: Add check to avoid out of bounds access

2024-04-05 Thread Lyude Paul
On Fri, 2024-04-05 at 17:53 +0200, Danilo Krummrich wrote:
> On 3/31/24 08:45, Mikhail Kobuk wrote:
> > Output Resource (dcb->or) value is not guaranteed to be non-zero
> > (i.e.
> > in drivers/gpu/drm/nouveau/nouveau_bios.c, in
> > 'fabricate_dcb_encoder_table()'
> > 'dcb->or' is assigned value '0' in call to
> > 'fabricate_dcb_output()').
> 
> I don't really know much about the semantics of this code.
> 
> Looking at fabricate_dcb_output() though I wonder if the intention
> was to assign
> BIT(or) to entry->or.
> 
> @Lyude, can you help here?

This code is definitely a bit before my time as well - but I think
you're completely correct. Especially considering this bit I found in
nouveau_bios.h:

enum nouveau_or {
DCB_OUTPUT_A = (1 << 0),
DCB_OUTPUT_B = (1 << 1),
DCB_OUTPUT_C = (1 << 2)
};


> 
> Otherwise, for parsing the DCB entries, it seems that the bound
> checks are
> happening in olddcb_outp_foreach() [1].
> 
> [1]
> https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/nouveau/nouveau_bios.c#L1331
> 
> > 
> > Add check to validate 'dcb->or' before it's used.
> > 
> > Found by Linux Verification Center (linuxtesting.org) with SVACE.
> > 
> > Fixes: 2e5702aff395 ("drm/nouveau: fabricate DCB encoder table for
> > iMac G4")
> > Signed-off-by: Mikhail Kobuk 
> > ---
> >   drivers/gpu/drm/nouveau/dispnv04/dac.c | 4 ++--
> >   1 file changed, 2 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/nouveau/dispnv04/dac.c
> > b/drivers/gpu/drm/nouveau/dispnv04/dac.c
> > index d6b8e0cce2ac..0c8d4fc95ff3 100644
> > --- a/drivers/gpu/drm/nouveau/dispnv04/dac.c
> > +++ b/drivers/gpu/drm/nouveau/dispnv04/dac.c
> > @@ -428,7 +428,7 @@ void nv04_dac_update_dacclk(struct drm_encoder
> > *encoder, bool enable)
> >     struct drm_device *dev = encoder->dev;
> >     struct dcb_output *dcb = nouveau_encoder(encoder)->dcb;
> >   
> > -   if (nv_gf4_disp_arch(dev)) {
> > +   if (nv_gf4_disp_arch(dev) && ffs(dcb->or)) {
> >     uint32_t *dac_users = _display(dev)-
> > >dac_users[ffs(dcb->or) - 1];
> >     int dacclk_off = NV_PRAMDAC_DACCLK +
> > nv04_dac_output_offset(encoder);
> >     uint32_t dacclk = NVReadRAMDAC(dev, 0,
> > dacclk_off);
> > @@ -453,7 +453,7 @@ bool nv04_dac_in_use(struct drm_encoder
> > *encoder)
> >     struct drm_device *dev = encoder->dev;
> >     struct dcb_output *dcb = nouveau_encoder(encoder)->dcb;
> >   
> > -   return nv_gf4_disp_arch(encoder->dev) &&
> > +   return nv_gf4_disp_arch(encoder->dev) && ffs(dcb->or) &&
> >     (nv04_display(dev)->dac_users[ffs(dcb->or) - 1] &
> > ~(1 << dcb->index));
> >   }
> >   
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH v0 13/14] drm/nouveau: Make I2C terminology more inclusive

2024-04-05 Thread Lyude Paul
On Fri, 2024-04-05 at 09:30 -0700, Easwar Hariharan wrote:
> 
> Thanks for the review, and for the appetite to go further! So we are
> on the same page, you would prefer
> renaming to controller/target like the feedback on other drm drivers
> (i915, gma500, radeon)?

FWIW I'm in support of this as well! As long as we make sure it gets
renamed everywhere :)

> 
> Thanks,
> Easwar
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



[PATCH 2/2] drm/nouveau/dp: Don't probe eDP ports twice harder

2024-04-04 Thread Lyude Paul
I didn't pay close enough attention the last time I tried to fix this
problem - while we currently do correctly take care to make sure we don't
probe a connected eDP port more then once, we don't do the same thing for
eDP ports we found to be disconnected.

So, fix this and make sure we only ever probe eDP ports once and then leave
them at that connector state forever (since without HPD, it's not going to
change on its own anyway). This should get rid of the last few GSP errors
getting spit out during runtime suspend and resume on some machines, as we
tried to reprobe eDP ports in response to ACPI hotplug probe events.

Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nouveau_dp.c | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 8b1be7dd64ebe..8b27d372e86da 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -225,12 +225,16 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
u8 *dpcd = nv_encoder->dp.dpcd;
int ret = NOUVEAU_DP_NONE, hpd;
 
-   /* If we've already read the DPCD on an eDP device, we don't need to
-* reread it as it won't change
+   /* eDP ports don't support hotplugging - so there's no point in probing 
eDP ports unless we
+* haven't probed them once before.
 */
-   if (connector->connector_type == DRM_MODE_CONNECTOR_eDP &&
-   dpcd[DP_DPCD_REV] != 0)
-   return NOUVEAU_DP_SST;
+   if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+   if (connector->status == connector_status_connected) {
+   return NOUVEAU_DP_SST;
+   } else if (connector->status == connector_status_disconnected) {
+   return NOUVEAU_DP_NONE;
+   }
+   }
 
// Ensure that the aux bus is enabled for probing
drm_dp_dpcd_set_powered(_connector->aux, true);
-- 
2.44.0



[PATCH 1/2] drm/nouveau/kms/nv50-: Disable AUX bus for disconnected DP ports

2024-04-04 Thread Lyude Paul
GSP has its own state for keeping track of whether or not a given display
connector is plugged in or not, and enforces this state on the driver. In
particular, AUX transactions on a DisplayPort connector which GSP says is
disconnected can never succeed - and can in some cases even cause
unexpected timeouts, which can trickle up to cause other problems. A good
example of this is runtime power management: where we can actually get
stuck trying to resume the GPU if a userspace application like fwupd tries
accessing a drm_aux_dev for a disconnected port. This was an issue I hit a
few times with my Slimbook Executive 16 - where trying to offload something
to the discrete GPU would wake it up, and then potentially cause it to
timeout as fwupd tried to immediately access the dp_aux_dev nodes for
nouveau.

Likewise: we don't really have any cases I know of where we'd want to
ignore this state and try an aux transaction anyway - and failing pointless
aux transactions immediately can even speed things up. So - let's start
enabling/disabling the aux bus in nouveau_dp_detect() to fix this. We
enable the aux bus during connector probing, and leave it enabled if we
discover something is actually on the connector. Otherwise, we just shut it
off.

This should fix some people's runtime PM issues (like myself), and also get
rid of quite of a lot of GSP error spam in dmesg.

Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nouveau_dp.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index fb06ee17d9e54..8b1be7dd64ebe 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -232,6 +232,9 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
dpcd[DP_DPCD_REV] != 0)
return NOUVEAU_DP_SST;
 
+   // Ensure that the aux bus is enabled for probing
+   drm_dp_dpcd_set_powered(_connector->aux, true);
+
mutex_lock(_encoder->dp.hpd_irq_lock);
if (mstm) {
/* If we're not ready to handle MST state changes yet, just
@@ -293,6 +296,13 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
if (mstm && !mstm->suspended && ret != NOUVEAU_DP_MST)
nv50_mstm_remove(mstm);
 
+   /* GSP doesn't like when we try to do aux transactions on a port it 
considers disconnected,
+* and since we don't really have a usecase for that anyway - just 
disable the aux bus here
+* if we've decided the connector is disconnected
+*/
+   if (ret == NOUVEAU_DP_NONE)
+   drm_dp_dpcd_set_powered(_connector->aux, false);
+
mutex_unlock(_encoder->dp.hpd_irq_lock);
return ret;
 }
-- 
2.44.0



[PATCH 0/2] nouveau: GSP DP aux fixes

2024-04-04 Thread Lyude Paul
Fixes for a few issues I've been seeing around regarding DP aux
transactions with nouveau and GSP support - mainly stemming from the
fact that GSP returns an error for aux transactions that are attempted
on disconnected ports. Some of these issues somehow manage to make
runtime PM fail on my Slimbook Executive 16!

Lyude Paul (2):
  drm/nouveau/kms/nv50-: Disable AUX bus for disconnected DP ports
  drm/nouveau/dp: Don't probe eDP ports twice harder

 drivers/gpu/drm/nouveau/nouveau_dp.c | 24 +++-
 1 file changed, 19 insertions(+), 5 deletions(-)

-- 
2.44.0



[PATCH 4/4] WIP: rust/drm/kms: Add ShadowPlaneState

2024-03-22 Thread Lyude Paul
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/rvkms/plane.rs   |  7 +++-
 rust/bindings/bindings_helper.h  |  2 +
 rust/kernel/drm/kms.rs   |  1 +
 rust/kernel/drm/kms/gem_atomic_helper.rs | 48 
 4 files changed, 56 insertions(+), 2 deletions(-)
 create mode 100644 rust/kernel/drm/kms/gem_atomic_helper.rs

diff --git a/drivers/gpu/drm/rvkms/plane.rs b/drivers/gpu/drm/rvkms/plane.rs
index d98a1f7bf79e2..5fb1b63842929 100644
--- a/drivers/gpu/drm/rvkms/plane.rs
+++ b/drivers/gpu/drm/rvkms/plane.rs
@@ -4,7 +4,10 @@
 prelude::*,
 drm::{
 device::Device,
-kms::plane::{self, DriverPlaneState},
+kms::{
+plane::{self, DriverPlaneState},
+gem_atomic_helper::ShadowPlaneState,
+}
 },
 };
 
@@ -15,7 +18,7 @@ pub(crate) struct DriverPlane {
 }
 
 pub(crate) type Plane = plane::Plane;
-pub(crate) type PlaneState = plane::PlaneState;
+pub(crate) type PlaneState = ShadowPlaneState;
 
 impl plane::DriverPlane for DriverPlane {
 type Initializer = impl PinInit;
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 5856afbe6e8f6..73a5eb00e8625 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -12,6 +12,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
diff --git a/rust/kernel/drm/kms.rs b/rust/kernel/drm/kms.rs
index b55d14415367a..14f4c3842ada0 100644
--- a/rust/kernel/drm/kms.rs
+++ b/rust/kernel/drm/kms.rs
@@ -6,6 +6,7 @@
 pub mod crtc;
 pub mod encoder;
 pub mod plane;
+pub mod gem_atomic_helper;
 
 use crate::{
 drm::{drv, device::Device},
diff --git a/rust/kernel/drm/kms/gem_atomic_helper.rs 
b/rust/kernel/drm/kms/gem_atomic_helper.rs
new file mode 100644
index 0..85bc3df32d8b7
--- /dev/null
+++ b/rust/kernel/drm/kms/gem_atomic_helper.rs
@@ -0,0 +1,48 @@
+use crate::{
+prelude::*,
+private::Sealed,
+bindings,
+init::Zeroable,
+};
+use super::plane::{IntoPlaneState, DriverPlaneState};
+
+unsafe impl Zeroable for bindings::drm_shadow_plane_state {}
+
+#[derive(Default)]
+#[repr(C)]
+pub struct ShadowPlaneState {
+shadow_state: bindings::drm_shadow_plane_state,
+inner: T,
+}
+
+impl Sealed for ShadowPlaneState {}
+
+static_assert!(crate::offset_of!(bindings::drm_shadow_plane_state, base) == 0);
+
+// SAFETY: Our data layout starts with drm_plane_state (contained at the start 
of
+// drm_shadow_plane_state)
+unsafe impl IntoPlaneState for ShadowPlaneState {
+fn __duplicate_state(, plane: *mut bindings::drm_plane) -> 
Result> {
+let mut new: Box = Box::try_init(try_init!(Self {
+shadow_state: bindings::drm_shadow_plane_state { 
..Default::default() },
+inner: self.inner.clone()
+}))?;
+
+// SAFETY: FFI call with no special requirements
+unsafe { bindings::__drm_gem_duplicate_shadow_plane_state(plane,  
new.shadow_state) };
+
+Ok(new)
+}
+
+fn __destroy_state(state: *mut bindings::drm_plane_state) {
+// SAFETY: This would not be called without a plane state to destroy, 
and our data layout
+// starts with `bindings::drm_plane_state`
+unsafe { bindings::__drm_gem_destroy_shadow_plane_state(state.cast()) 
};
+}
+
+fn __reset_state(plane: *mut bindings::drm_plane, state: *mut 
bindings::drm_plane_state) {
+// SAFETY: This would not be called without a plane state to reset, 
and our data layout
+// starts with `bindings::drm_plane_state`
+unsafe { bindings::__drm_gem_reset_shadow_plane(plane, state.cast()) }
+}
+}
-- 
2.43.0



[PATCH 3/4] rust/drm/kms: Extract PlaneState into IntoPlaneState

2024-03-22 Thread Lyude Paul
DRM actually has a number of helpers that wrap drm_plane_state, one of
which is actually needed by VKMS - drm_shadow_plane_state.

So, let's start preparing to write bindings for this by first extracting
PlaneState into the IntoPlaneState trait - which all DRM structs which
wrap drm_plane_state will implement. This is basically the same idea as the
GEM ops - but for plane states.

Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/rvkms/plane.rs |   2 +-
 rust/kernel/drm/kms/plane.rs   | 165 -
 2 files changed, 103 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/rvkms/plane.rs b/drivers/gpu/drm/rvkms/plane.rs
index 54c4bbda64d8e..d98a1f7bf79e2 100644
--- a/drivers/gpu/drm/rvkms/plane.rs
+++ b/drivers/gpu/drm/rvkms/plane.rs
@@ -20,7 +20,7 @@ pub(crate) struct DriverPlane {
 impl plane::DriverPlane for DriverPlane {
 type Initializer = impl PinInit;
 
-type State = RvkmsPlaneState;
+type State = PlaneState;
 
 type Driver = RvkmsDriver;
 
diff --git a/rust/kernel/drm/kms/plane.rs b/rust/kernel/drm/kms/plane.rs
index 78c8e370b997c..73c285445be63 100644
--- a/rust/kernel/drm/kms/plane.rs
+++ b/rust/kernel/drm/kms/plane.rs
@@ -13,6 +13,7 @@
 sync::{Arc, ArcBorrow},
 init::InPlaceInit,
 offset_of,
+private::Sealed,
 };
 use core::{
 cell::UnsafeCell,
@@ -62,14 +63,16 @@ pub trait DriverPlane: Send + Sync + Sized {
 /// The parent driver implementation
 type Driver: KmsDriver;
 
-/// The type for this driver's drm_plane_state implementation
-type State: DriverPlaneState;
+/// The full type for this driver's drm_plane_state implementation. 
Drivers which don't need
+/// special DRM helpers for their plane states may just use 
`PlaneState` here, where `T` is
+/// their private state struct which implements `DriverPlaneState`
+type State: IntoPlaneState;
 
 /// Create a new plane for this driver
 fn new(device: , args: Self::Args) -> 
Self::Initializer;
 }
 
-impl crate::private::Sealed for Plane {}
+impl Sealed for Plane {}
 
 impl ModeObject for Plane {
 type Driver = T::Driver;
@@ -177,6 +180,70 @@ pub(super) fn raw_mut_ptr() -> *mut 
bindings::drm_plane {
 unsafe { drop(Box::from_raw(plane as *mut Plane)) };
 }
 
+/// Operations implemented by any base atomic plane state. These are 
implemented by DRM to provide
+/// wrappers around the generic atomic plane state, along with various plane 
state helpers.
+///
+/// SAFETY: Incorrect implementation of these methods will result in UB, users 
should take care to
+/// read through the documentation of each method - especially the provided 
methods.
+pub unsafe trait IntoPlaneState: Default + Sealed {
+/// Consume the box for this plane state without dropping its contents, 
and return a reference
+/// to it's base plane state to hand off to DRM
+///
+/// Implementors must override this if their data layout does not start 
with
+/// `bindings::drm_plane_state`.
+fn into_raw(self: Box) -> *mut bindings::drm_plane_state {
+// Our data layout starts with drm_plane_state
+Box::into_raw(self).cast()
+}
+
+/// Reconstruct the box for this plate state for deallocation
+///
+/// Implementors must override this if their data layout does not start 
with
+/// `bindings::drm_plane_state`.
+unsafe fn from_raw(ptr: *mut bindings::drm_plane_state) -> Box {
+// SAFETY: Users of this default promise their data layout starts with 
drm_plane_state
+unsafe { Box::from_raw(ptr.cast()) }
+}
+
+/// Get a mutable reference to the raw `bindings::drm_plane_state` 
contained within this type
+/// that we can pass to DRM
+fn as_raw_mut( self) ->  bindings::drm_plane_state {
+// SAFETY: Users of this default promise their data layout starts with 
drm_plane_state
+unsafe { mem::transmute(self) }
+}
+
+/// Get an immutable reference to this type from the given raw 
`bindings::drm_plane_state`
+/// pointer
+///
+/// Implementors must override this if their data layout does not start 
with
+/// `bindings::drm_plane_state`.
+///
+/// SAFETY: The caller guarantees `ptr` is contained within a valid 
instance of `Self`
+unsafe fn ref_from_raw<'a>(ptr: *const bindings::drm_plane_state) -> &'a 
Self {
+// SAFETY: Users of this default promise their data layout starts with 
drm_plane_state
+unsafe { &*ptr.cast() }
+}
+
+/// Get a mutable reference to this type from the given raw 
`bindings::drm_plane_state` pointer
+///
+/// SAFETY: The caller guarantees `ptr` is contained within a valid 
instance of `Self`
+unsafe fn ref_from_raw_mut<'a>(ptr: *mut bindings::drm_plane_state) -> &'a 
mut Self {
+// SAFETY: Users of this default promise their data layout starts with 
drm_plane_state
+unsafe {  (*ptr.cast()) }
+}
+
+// Allocate a &

[PATCH 2/4] WIP: drm: Introduce rvkms

2024-03-22 Thread Lyude Paul
This introduces a work in progress port of the VKMS driver to rust to
provide a user of the kernel's new rust bindings for KMS drivers! This
driver is very incomplete, I'm not even sure if it loads right now without
crashing (but it did at one point, and I'll be checking very soon!).

Squash into rvkms introduction

Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/Kconfig|   2 +
 drivers/gpu/drm/Makefile   |   1 +
 drivers/gpu/drm/rvkms/Kconfig  |   3 +
 drivers/gpu/drm/rvkms/Makefile |   1 +
 drivers/gpu/drm/rvkms/connector.rs |  55 +++
 drivers/gpu/drm/rvkms/crtc.rs  |  40 
 drivers/gpu/drm/rvkms/encoder.rs   |  26 +
 drivers/gpu/drm/rvkms/file.rs  |  22 +
 drivers/gpu/drm/rvkms/gem.rs   |  32 +++
 drivers/gpu/drm/rvkms/output.rs|  72 ++
 drivers/gpu/drm/rvkms/plane.rs |  39 
 drivers/gpu/drm/rvkms/rvkms.rs | 146 +
 12 files changed, 439 insertions(+)
 create mode 100644 drivers/gpu/drm/rvkms/Kconfig
 create mode 100644 drivers/gpu/drm/rvkms/Makefile
 create mode 100644 drivers/gpu/drm/rvkms/connector.rs
 create mode 100644 drivers/gpu/drm/rvkms/crtc.rs
 create mode 100644 drivers/gpu/drm/rvkms/encoder.rs
 create mode 100644 drivers/gpu/drm/rvkms/file.rs
 create mode 100644 drivers/gpu/drm/rvkms/gem.rs
 create mode 100644 drivers/gpu/drm/rvkms/output.rs
 create mode 100644 drivers/gpu/drm/rvkms/plane.rs
 create mode 100644 drivers/gpu/drm/rvkms/rvkms.rs

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index c7edba18a6f09..48c140f943356 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -275,6 +275,8 @@ source "drivers/gpu/drm/amd/amdgpu/Kconfig"
 
 source "drivers/gpu/drm/nouveau/Kconfig"
 
+source "drivers/gpu/drm/rvkms/Kconfig"
+
 source "drivers/gpu/drm/i915/Kconfig"
 
 source "drivers/gpu/drm/xe/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 104b42df2e956..91a18c8290fa4 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -143,6 +143,7 @@ obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
 obj-$(CONFIG_DRM_VGEM) += vgem/
 obj-$(CONFIG_DRM_VKMS) += vkms/
 obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
+obj-$(CONFIG_DRM_RVKMS) += rvkms/
 obj-$(CONFIG_DRM_EXYNOS) +=exynos/
 obj-$(CONFIG_DRM_ROCKCHIP) +=rockchip/
 obj-$(CONFIG_DRM_GMA500) += gma500/
diff --git a/drivers/gpu/drm/rvkms/Kconfig b/drivers/gpu/drm/rvkms/Kconfig
new file mode 100644
index 0..d888aa4ffc84c
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/Kconfig
@@ -0,0 +1,3 @@
+config DRM_RVKMS
+tristate "Rust VKMS PoC driver (EXPERIMENTAL)"
+depends on RUST && DRM && DRM_GEM_SHMEM_HELPER
diff --git a/drivers/gpu/drm/rvkms/Makefile b/drivers/gpu/drm/rvkms/Makefile
new file mode 100644
index 0..18e06fc3343c6
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_DRM_RVKMS) += rvkms.o
diff --git a/drivers/gpu/drm/rvkms/connector.rs 
b/drivers/gpu/drm/rvkms/connector.rs
new file mode 100644
index 0..40f84d38437ee
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/connector.rs
@@ -0,0 +1,55 @@
+// TODO: License and stuff
+// Contain's rvkms's drm_connector implementation
+
+use super::{RvkmsDriver, RvkmsDevice, MAX_RES, DEFAULT_RES};
+use kernel::{
+prelude::*,
+drm::{
+device::Device,
+kms::{
+connector::{self, ConnectorGuard},
+ModeConfigGuard
+}
+},
+prelude::*
+};
+use core::marker::PhantomPinned;
+
+#[pin_data]
+pub(crate) struct DriverConnector {
+#[pin]
+_p: PhantomPinned
+}
+
+pub(crate) type Connector = connector::Connector;
+
+impl connector::DriverConnector for DriverConnector {
+type Initializer = impl PinInit;
+
+type State = ConnectorState;
+
+type Driver = RvkmsDriver;
+
+type Args = ();
+
+fn new(dev: , args: Self::Args) -> Self::Initializer {
+try_pin_init!(Self { _p: PhantomPinned })
+}
+
+fn get_modes(
+connector: ConnectorGuard<'_, Self>,
+_guard: <'_, Self::Driver>
+) -> i32 {
+let count = connector.add_modes_noedid(MAX_RES);
+
+connector.set_preferred_mode(DEFAULT_RES);
+count
+}
+}
+
+#[derive(Clone, Default)]
+pub(crate) struct ConnectorState;
+
+impl connector::DriverConnectorState for ConnectorState {
+type Connector = DriverConnector;
+}
diff --git a/drivers/gpu/drm/rvkms/crtc.rs b/drivers/gpu/drm/rvkms/crtc.rs
new file mode 100644
index 0..2998f288b88e6
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/crtc.rs
@@ -0,0 +1,40 @@
+// TODO: License and stuff
+// Contain's rvkms's drm_crtc implementation
+use core::marker::PhantomPinned;
+use super::RvkmsDriver;
+use kernel::{
+prelude::*,
+drm::{
+device::Device,
+kms::crtc,
+},
+};
+
+pub(crate) type Crtc = crtc::Crtc;
+
+#[pin_data]
+pub(crate) str

[PATCH 1/4] WIP: rust: Add basic KMS bindings

2024-03-22 Thread Lyude Paul
Signed-off-by: Lyude Paul 
---
 rust/bindings/bindings_helper.h  |   4 +
 rust/helpers.c   |  17 ++
 rust/kernel/drm/device.rs|   2 +
 rust/kernel/drm/drv.rs   | 115 +++--
 rust/kernel/drm/kms.rs   | 146 +++
 rust/kernel/drm/kms/connector.rs | 404 +++
 rust/kernel/drm/kms/crtc.rs  | 300 +++
 rust/kernel/drm/kms/encoder.rs   | 175 +
 rust/kernel/drm/kms/plane.rs | 300 +++
 rust/kernel/drm/mod.rs   |   1 +
 10 files changed, 1448 insertions(+), 16 deletions(-)
 create mode 100644 rust/kernel/drm/kms.rs
 create mode 100644 rust/kernel/drm/kms/connector.rs
 create mode 100644 rust/kernel/drm/kms/crtc.rs
 create mode 100644 rust/kernel/drm/kms/encoder.rs
 create mode 100644 rust/kernel/drm/kms/plane.rs

diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index a712efecdb1a9..5856afbe6e8f6 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -6,12 +6,16 @@
  * Sorted alphabetically.
  */
 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
diff --git a/rust/helpers.c b/rust/helpers.c
index 69fc66164c785..bf9b299f4597f 100644
--- a/rust/helpers.c
+++ b/rust/helpers.c
@@ -20,6 +20,7 @@
  * Sorted alphabetically.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -284,6 +285,22 @@ int rust_helper_drm_gem_shmem_object_mmap(struct 
drm_gem_object *obj, struct vm_
 EXPORT_SYMBOL_GPL(rust_helper_drm_gem_shmem_object_mmap);
 
 #endif
+
+#ifdef CONFIG_DRM_KMS_HELPER
+
+void rust_helper_drm_connector_get(struct drm_connector *connector)
+{
+   drm_connector_get(connector);
+}
+EXPORT_SYMBOL_GPL(rust_helper_drm_connector_get);
+
+void rust_helper_drm_connector_put(struct drm_connector *connector)
+{
+   drm_connector_put(connector);
+}
+EXPORT_SYMBOL_GPL(rust_helper_drm_connector_put);
+
+#endif /* CONFIG_DRM_KMS_HELPER */
 #endif
 
 void rust_helper_pci_set_drvdata(struct pci_dev *pdev, void *data)
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 6176e2e879d0b..07bc8ed50eae0 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -20,6 +20,8 @@ pub struct Device {
 }
 
 impl Device {
+pub const HAS_KMS: bool = T::FEATURES & drm::drv::FEAT_MODESET != 0;
+
 #[allow(dead_code, clippy::mut_from_ref)]
 pub(crate) unsafe fn raw_mut() ->  bindings::drm_device {
 unsafe {  *self.drm.get() }
diff --git a/rust/kernel/drm/drv.rs b/rust/kernel/drm/drv.rs
index fa9ce64a5080c..308f0a117f546 100644
--- a/rust/kernel/drm/drv.rs
+++ b/rust/kernel/drm/drv.rs
@@ -5,9 +5,13 @@
 //! C header: 
[`include/linux/drm/drm_drv.h`](../../../../include/linux/drm/drm_drv.h)
 
 use crate::{
-bindings, device, drm,
+bindings, device,
+drm::{
+self,
+kms,
+},
 error::code::*,
-error::from_err_ptr,
+error::{from_err_ptr, to_result},
 error::{Error, Result},
 prelude::*,
 private::Sealed,
@@ -15,6 +19,7 @@
 types::{ARef, ForeignOwnable},
 ThisModule,
 sync::Arc,
+init::Zeroable,
 };
 use core::{
 marker::{PhantomData, PhantomPinned},
@@ -150,7 +155,11 @@ pub trait Driver {
 /// The struct which contains both the driver's fops and vtable
 ///
 /// These live in the same structure since it needs to be self-referential, so 
having them in their
-/// own structure allows us to pin this struct without pinning the 
[`Registration`] object
+/// own structure allows us to pin this struct without pinning the 
[`Registration`] object.
+///
+/// Drivers should not need to create this structure themselves, as it will be 
created for them by
+/// DRM. As well: this object is a temporary holdover until we can generate 
the DRM fops and vtable
+/// in a const function (which should be possible once const mem::zeroed 
becomes stable).
 #[pin_data]
 pub struct DriverOps {
 #[pin]
@@ -225,8 +234,10 @@ macro_rules! drm_legacy_fields {
 #[allow(clippy::crate_in_macro_def)]
 #[macro_export]
 macro_rules! new_drm_registration {
-($type:ty, $parent:expr) => {{
-$crate::drm::drv::Registration::<$type>::new($parent, 
::THIS_MODULE)
+($type:ty, $parent:expr, $mode_config_info:expr) => {{
+$crate::drm::drv::Registration::<$type>::new(
+$parent, $mode_config_info, ::THIS_MODULE
+)
 }};
 }
 
@@ -249,6 +260,8 @@ pub struct RegistrationInfo {
 drm: ARef>,
 }
 
+unsafe impl Zeroable for bindings::drm_mode_config { }
+
 impl Registration {
 const VTABLE: bindings::drm_driver = drm_legacy_fields! {
 load: None,
@@ -282,28 +295,89 @@ impl Registration {
 fops: core::ptr::null_mut(),
 };
 
+const KMS_VTABLE: bindings::drm_mode_config_funcs = 
bindings::drm_mode_config_funcs {
+atomic_check: None, // TODO
+// TODO TODO: T

[RFC WIP 0/4] Rust bindings for KMS + RVKMS

2024-03-22 Thread Lyude Paul
in the same struct, the same struct is used for
both cases - even though it's entirely possible to have a drm_device
without KMS support and thus without an initialized mode_config struct.
This would be very nice to figure out, because I assume there's likely
to be UB if a non-KMS device attempts to do KMS-like operations on
itself. Currently, a modesetting device indicates it has KMS in my
branch by doing two things:

* Setting FEAT_MODESET and FEAT_ATOMIC in drm::drv::Driver::FEATURES
* Passing a ModeConfigInfo struct to drm::drv::Registration::register(),
  containing various misc. information drivers usually populate in
  mode_config

Figuring out how to gate these to only KMS-supporting devices would
likely mean moving the global modesetting callbacks we need to support
into a different trait that's only implemented by KMS drivers - but I'm
not quite sure how to do that cleanly yet.

# Other issues/hacks

* Currently, a DRM driver's vtable and file operations table are not
  static. I totally think we can (and should) make this static by making
  drm::gem::create_fops() a const fn, and also turning DriverOps's
  constructors into const fns. The current blocker for this is that
  Default::default() is not const, along with mem::zeroed() - giving us
  no way of creating a zero-initialized struct at compile-time.
  Coincidentally, mem::zeroed() actually becomes const in rust 1.75 - so
  once the kernel updates its rust version we should be able to fix
  this.
* There is a leak somewhere? Unloading rvkms currently leaves behind a
  few DRI directories, I'm not totally sure why yet - but I think this
  may be an issue with the DRM bindings themselves.
* bindgen doesn't understand fourcc, and probably a number of other
  similar files. So we're going to need some nasty hacks to expose
  these.
* I'm sure there's bits of code that need cleaning up, but I figured it
  was more important to start getting feedback on all of this first :).

Lyude Paul (4):
  WIP: rust: Add basic KMS bindings
  WIP: drm: Introduce rvkms
  rust/drm/kms: Extract PlaneState into IntoPlaneState
  WIP: rust/drm/kms: Add ShadowPlaneState

 drivers/gpu/drm/Kconfig  |   2 +
 drivers/gpu/drm/Makefile |   1 +
 drivers/gpu/drm/rvkms/Kconfig|   3 +
 drivers/gpu/drm/rvkms/Makefile   |   1 +
 drivers/gpu/drm/rvkms/connector.rs   |  55 +++
 drivers/gpu/drm/rvkms/crtc.rs|  40 +++
 drivers/gpu/drm/rvkms/encoder.rs |  26 ++
 drivers/gpu/drm/rvkms/file.rs|  22 ++
 drivers/gpu/drm/rvkms/gem.rs |  32 ++
 drivers/gpu/drm/rvkms/output.rs  |  72 
 drivers/gpu/drm/rvkms/plane.rs   |  42 +++
 drivers/gpu/drm/rvkms/rvkms.rs   | 146 
 rust/bindings/bindings_helper.h  |   6 +
 rust/helpers.c   |  17 +
 rust/kernel/drm/device.rs|   2 +
 rust/kernel/drm/drv.rs   | 115 ++-
 rust/kernel/drm/kms.rs   | 147 +
 rust/kernel/drm/kms/connector.rs | 404 +++
 rust/kernel/drm/kms/crtc.rs  | 300 +
 rust/kernel/drm/kms/encoder.rs   | 175 ++
 rust/kernel/drm/kms/gem_atomic_helper.rs |  48 +++
 rust/kernel/drm/kms/plane.rs | 339 +++
 rust/kernel/drm/mod.rs   |   1 +
 23 files changed, 1980 insertions(+), 16 deletions(-)
 create mode 100644 drivers/gpu/drm/rvkms/Kconfig
 create mode 100644 drivers/gpu/drm/rvkms/Makefile
 create mode 100644 drivers/gpu/drm/rvkms/connector.rs
 create mode 100644 drivers/gpu/drm/rvkms/crtc.rs
 create mode 100644 drivers/gpu/drm/rvkms/encoder.rs
 create mode 100644 drivers/gpu/drm/rvkms/file.rs
 create mode 100644 drivers/gpu/drm/rvkms/gem.rs
 create mode 100644 drivers/gpu/drm/rvkms/output.rs
 create mode 100644 drivers/gpu/drm/rvkms/plane.rs
 create mode 100644 drivers/gpu/drm/rvkms/rvkms.rs
 create mode 100644 rust/kernel/drm/kms.rs
 create mode 100644 rust/kernel/drm/kms/connector.rs
 create mode 100644 rust/kernel/drm/kms/crtc.rs
 create mode 100644 rust/kernel/drm/kms/encoder.rs
 create mode 100644 rust/kernel/drm/kms/gem_atomic_helper.rs
 create mode 100644 rust/kernel/drm/kms/plane.rs

-- 
2.43.0



[PATCH] drm/nouveau/dp: Fix incorrect return code in r535_dp_aux_xfer()

2024-03-15 Thread Lyude Paul
I've recently been seeing some unexplained GSP errors on my RTX 6000 from
failed aux transactions:

  [  132.915867] nouveau :1f:00.0: gsp: cli:0xc1d2 obj:0x0073
  ctrl cmd:0x00731341 failed: 0x

While the cause of these is not yet clear, these messages made me notice
that the aux transactions causing these transactions were succeeding - not
failing. As it turns out, this is because we're currently not returning the
correct variable when r535_dp_aux_xfer() hits an error - causing us to
never propagate GSP errors for failed aux transactions to userspace.

So, let's fix that.

Fixes: 4ae3a20102b2 ("nouveau/gsp: don't free ctrl messages on errors")
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c
index 6a0a4d3b8902d..027867c2a8c5b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c
@@ -1080,7 +1080,7 @@ r535_dp_aux_xfer(struct nvkm_outp *outp, u8 type, u32 
addr, u8 *data, u8 *psize)
ret = nvkm_gsp_rm_ctrl_push(>rm.objcom, , sizeof(*ctrl));
if (ret) {
nvkm_gsp_rm_ctrl_done(>rm.objcom, ctrl);
-   return PTR_ERR(ctrl);
+   return ret;
}
 
memcpy(data, ctrl->data, size);
-- 
2.43.0



Re: [PATCH 2/2] drm/nouveau: move more missing UAPI bits

2024-03-04 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Mon, 2024-03-04 at 19:31 +0100, Karol Herbst wrote:
> Those are already de-facto UAPI, so let's just move it into the uapi
> header.
> 
> Signed-off-by: Karol Herbst 
> ---
>  drivers/gpu/drm/nouveau/nouveau_abi16.c | 20 +++-
>  drivers/gpu/drm/nouveau/nouveau_abi16.h | 12 
>  include/uapi/drm/nouveau_drm.h  | 22 ++
>  3 files changed, 37 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c 
> b/drivers/gpu/drm/nouveau/nouveau_abi16.c
> index cd14f993bdd1b..92f9127b284ac 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
> @@ -312,11 +312,21 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
>   if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
>   if (init->fb_ctxdma_handle == ~0) {
>   switch (init->tt_ctxdma_handle) {
> - case 0x01: engine = NV_DEVICE_HOST_RUNLIST_ENGINES_GR   
>  ; break;
> - case 0x02: engine = 
> NV_DEVICE_HOST_RUNLIST_ENGINES_MSPDEC; break;
> - case 0x04: engine = 
> NV_DEVICE_HOST_RUNLIST_ENGINES_MSPPP ; break;
> - case 0x08: engine = 
> NV_DEVICE_HOST_RUNLIST_ENGINES_MSVLD ; break;
> - case 0x30: engine = NV_DEVICE_HOST_RUNLIST_ENGINES_CE   
>  ; break;
> + case NOUVEAU_FIFO_ENGINE_GR:
> + engine = NV_DEVICE_HOST_RUNLIST_ENGINES_GR;
> + break;
> + case NOUVEAU_FIFO_ENGINE_VP:
> + engine = NV_DEVICE_HOST_RUNLIST_ENGINES_MSPDEC;
> + break;
> + case NOUVEAU_FIFO_ENGINE_PPP:
> + engine = NV_DEVICE_HOST_RUNLIST_ENGINES_MSPPP;
> + break;
> + case NOUVEAU_FIFO_ENGINE_BSP:
> + engine = NV_DEVICE_HOST_RUNLIST_ENGINES_MSVLD;
> + break;
> + case NOUVEAU_FIFO_ENGINE_CE:
> + engine = NV_DEVICE_HOST_RUNLIST_ENGINES_CE;
> + break;
>   default:
>   return nouveau_abi16_put(abi16, -ENOSYS);
>   }
> diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h 
> b/drivers/gpu/drm/nouveau/nouveau_abi16.h
> index 11c8c4a80079b..661b901d8ecc9 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_abi16.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h
> @@ -50,18 +50,6 @@ struct drm_nouveau_grobj_alloc {
>   int  class;
>  };
>  
> -struct drm_nouveau_notifierobj_alloc {
> - uint32_t channel;
> - uint32_t handle;
> - uint32_t size;
> - uint32_t offset;
> -};
> -
> -struct drm_nouveau_gpuobj_free {
> - int  channel;
> - uint32_t handle;
> -};
> -
>  struct drm_nouveau_setparam {
>   uint64_t param;
>   uint64_t value;
> diff --git a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h
> index 77d7ff0d5b110..5404d4cfff4c2 100644
> --- a/include/uapi/drm/nouveau_drm.h
> +++ b/include/uapi/drm/nouveau_drm.h
> @@ -73,6 +73,16 @@ struct drm_nouveau_getparam {
>   __u64 value;
>  };
>  
> +/*
> + * Those are used to support selecting the main engine used on Kepler.
> + * This goes into drm_nouveau_channel_alloc::tt_ctxdma_handle
> + */
> +#define NOUVEAU_FIFO_ENGINE_GR  0x01
> +#define NOUVEAU_FIFO_ENGINE_VP  0x02
> +#define NOUVEAU_FIFO_ENGINE_PPP 0x04
> +#define NOUVEAU_FIFO_ENGINE_BSP 0x08
> +#define NOUVEAU_FIFO_ENGINE_CE  0x30
> +
>  struct drm_nouveau_channel_alloc {
>   __u32 fb_ctxdma_handle;
>   __u32 tt_ctxdma_handle;
> @@ -95,6 +105,18 @@ struct drm_nouveau_channel_free {
>   __s32 channel;
>  };
>  
> +struct drm_nouveau_notifierobj_alloc {
> + __u32 channel;
> + __u32 handle;
> + __u32 size;
> + __u32 offset;
> +};
> +
> +struct drm_nouveau_gpuobj_free {
> + __s32 channel;
> + __u32 handle;
> +};
> +
>  #define NOUVEAU_GEM_DOMAIN_CPU   (1 << 0)
>  #define NOUVEAU_GEM_DOMAIN_VRAM  (1 << 1)
>  #define NOUVEAU_GEM_DOMAIN_GART  (1 << 2)

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH 1/2] drm/nouveau: fix stale locked mutex in nouveau_gem_ioctl_pushbuf

2024-03-04 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Mon, 2024-03-04 at 19:31 +0100, Karol Herbst wrote:
> If VM_BIND is enabled on the client the legacy submission ioctl can't be
> used, however if a client tries to do so regardless it will return an
> error. In this case the clients mutex remained unlocked leading to a
> deadlock inside nouveau_drm_postclose or any other nouveau ioctl call.
> 
> Fixes: b88baab82871 ("drm/nouveau: implement new VM_BIND uAPI")
> Cc: Danilo Krummrich 
> Signed-off-by: Karol Herbst 
> ---
>  drivers/gpu/drm/nouveau/nouveau_gem.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c 
> b/drivers/gpu/drm/nouveau/nouveau_gem.c
> index 49c2bcbef1299..5a887d67dc0e8 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_gem.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
> @@ -764,7 +764,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void 
> *data,
>   return -ENOMEM;
>  
>   if (unlikely(nouveau_cli_uvmm(cli)))
> - return -ENOSYS;
> + return nouveau_abi16_put(abi16, -ENOSYS);
>  
>   list_for_each_entry(temp, >channels, head) {
>   if (temp->chan->chid == req->channel) {

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Future of nouveau/nova's display driver, and rvkms introduction!

2024-02-06 Thread Lyude Paul
Hi everyone! As I'm sure a number of you are aware, since Nvidia's release of
the GSP firmware a lot of things have changed for nouveau. In particular, the
interfaces which we use for controlling the hardware from nouveau have changed
pretty dramatically in many areas as a result of going through the GSP instead
of directly interfacing with various hardware registers. Enough so that at
least outside of modesetting, there isn't much potential for codesharing
between non-GSP devices and GSP devices.

As such a few folks at Red Hat, myself included, have been working on writing
up a new kernel driver intended solely for GSP devices known as nova:

https://gitlab.freedesktop.org/dakr/nova

As well, nova is a rust based driver - something we're hoping will become much
more common in the kernel as a result of this project (and the efforts of
other projects like Asahi!).

Of course, you'll notice I mentioned earlier that most of the GSP changes have
been outside of the area of modesetting. This is to say that while modesetting
with nvidia hardware hasn't remained totally the same, it's mostly the same:
we've only had a small number of modesetting interfaces moved into the GSP,
and the evo/nvdisplay architecture remains largely identical to what it looked
like pre-GSP. This of course led us to the question of whether we should try
sharing a modesetting driver with nouveau, or if the effort of having a C
based modesetting driver alongside a rust counterpart would be too much work.

Eventually, while it would have been nice to have done code sharing here - we
ended up deciding that it probably would be more work then it's worth, and
that it wouldn't be a bad idea for us also to write up a new modesetting
driver for nova in rust so that we don't have to maintain a Rust <-> C layer
within nova. It's going to be a while before writing this driver starts
though, since there's not much we can do without having nova a bit further
ahead in the driver bringup-process. So…

For the time being, to figure out a set of rust bindings for KMS drivers in
the kernel I've been working on a small project called rvkms!

https://gitlab.freedesktop.org/lyudess/linux/-/commits/rvkms

The basic idea is to figure out as much of the KMS bindings as we can before
we're at a point where it's possible to start writing up a modesetting driver
for nova. RVKMS as you may have guessed, is intended to be a port of VKMS to
rust. We choose VKMS since it's got a very small codebase, and only really
implements the minimum requirements for an atomic KMS driver. Currently I'm
not planning on upstreaming rvkms itself, however if there's actually enough
interest in such a driver being upstreamed I certainly wouldn't be against it
:).

At the moment I don't have much more then a basic skeleton driver that's based
off the nova development branch (currently the 6.6 branch, but I'm currently
rebasing it to the latest 6.7 branch), but I hope to have more in the near
future as I'm currently working on writing up KMS bindings.

If anyone has any questions or comments feel free to reply :)!
-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



[PATCH] drm/nouveau/kms/nv50-: Don't allow inheritance of headless iors

2023-12-13 Thread Lyude Paul
Turns out we made a silly mistake when coming up with OR inheritance on
nouveau. On pre-DCB 4.1, iors are statically routed to output paths via the
DCB. On later generations iors are only routed to an output path if they're
actually being used. Unfortunately, it appears with NVIF_OUTP_INHERIT_V0 we
make the mistake of assuming the later is true on all generations, which is
currently leading us to return bogus ior -> head assignments through nvif,
which causes WARN_ON().

So - fix this by verifying that we actually know that there's a head
assigned to an ior before allowing it to be inherited through nvif. This
-should- hopefully fix the WARN_ON on GT218 reported by Borislav.

Signed-off-by: Lyude Paul 
Cc: Borislav Petkov 
---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index e4279f1772a1b..377d0e0cef848 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -385,7 +385,7 @@ nvkm_uoutp_mthd_inherit(struct nvkm_outp *outp, void *argv, 
u32 argc)
 
/* Ensure an ior is hooked up to this outp already */
ior = outp->func->inherit(outp);
-   if (!ior)
+   if (!ior || !ior->arm.head)
return -ENODEV;
 
/* With iors, there will be a separate output path for each type of 
connector - and all of
-- 
2.43.0



Re: nouveau 0000:01:00.0: drm_WARN_ON(!found_head)

2023-12-13 Thread Lyude Paul
Nevermind - I don't think I'll need the logs, I stared at the code for long
enough and I think I realized what's happening.

I will have a patch for you to test in just a moment, just waiting for it to
compile so I can verify nothing else breaks

On Wed, 2023-12-13 at 18:48 -0500, Lyude Paul wrote:
> Hopefully you're still on at this point - if you are, could you try starting
> the machine up with the following kernel module arguments passed to nouveau?
> 
> debug=disp=trace
> 
> Then see if you can find any lines that mention INHERIT? I have a feeling I'm
> just going to have to add a workaround for the time being, but I'd really love
> to know how we're managing to get that far on a hardware generation we never
> implemented that nvkm ioctl for…
> 
> On Wed, 2023-12-13 at 18:37 -0500, Lyude Paul wrote:
> > agh - thank you for repeatedly poking on this, I've been busy enough with 
> > GSP
> > work I totally missed this. Yes - I'm quite surprised that this is blowing 
> > up,
> > but considering that looks to be a GT218 I guess display state readback must
> > just work a bit differently there since that's really early on into the NV50
> > days.
> > 
> > The reason that was a drm_WARN_ON() was because it indicates that we're not
> > reading back OR -> head assignments properly. But, I'm confused how we're 
> > even
> > getting that far on a non-GSP platform. I'm going to dig into this now, but 
> > if
> > I don't figure out a good fix by the end of the day I'll just send a patch 
> > to
> > silent the warning.
> > 
> > Thanks again for bugging me about this!
> > 
> > On Wed, 2023-12-13 at 13:49 +0100, Borislav Petkov wrote:
> > > On Wed, Dec 13, 2023 at 12:39:36PM +0100, Borislav Petkov wrote:
> > > > We're getting close to releasing so I guess we either debug this or shut
> > > > up the WARN.
> > > 
> > > Not only that - panic_on_warn turns this into an explosion so you don't
> > > want that in a released kernel.
> > > 
> > 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: nouveau 0000:01:00.0: drm_WARN_ON(!found_head)

2023-12-13 Thread Lyude Paul
Hopefully you're still on at this point - if you are, could you try starting
the machine up with the following kernel module arguments passed to nouveau?

debug=disp=trace

Then see if you can find any lines that mention INHERIT? I have a feeling I'm
just going to have to add a workaround for the time being, but I'd really love
to know how we're managing to get that far on a hardware generation we never
implemented that nvkm ioctl for…

On Wed, 2023-12-13 at 18:37 -0500, Lyude Paul wrote:
> agh - thank you for repeatedly poking on this, I've been busy enough with GSP
> work I totally missed this. Yes - I'm quite surprised that this is blowing up,
> but considering that looks to be a GT218 I guess display state readback must
> just work a bit differently there since that's really early on into the NV50
> days.
> 
> The reason that was a drm_WARN_ON() was because it indicates that we're not
> reading back OR -> head assignments properly. But, I'm confused how we're even
> getting that far on a non-GSP platform. I'm going to dig into this now, but if
> I don't figure out a good fix by the end of the day I'll just send a patch to
> silent the warning.
> 
> Thanks again for bugging me about this!
> 
> On Wed, 2023-12-13 at 13:49 +0100, Borislav Petkov wrote:
> > On Wed, Dec 13, 2023 at 12:39:36PM +0100, Borislav Petkov wrote:
> > > We're getting close to releasing so I guess we either debug this or shut
> > > up the WARN.
> > 
> > Not only that - panic_on_warn turns this into an explosion so you don't
> > want that in a released kernel.
> > 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: nouveau 0000:01:00.0: drm_WARN_ON(!found_head)

2023-12-13 Thread Lyude Paul
agh - thank you for repeatedly poking on this, I've been busy enough with GSP
work I totally missed this. Yes - I'm quite surprised that this is blowing up,
but considering that looks to be a GT218 I guess display state readback must
just work a bit differently there since that's really early on into the NV50
days.

The reason that was a drm_WARN_ON() was because it indicates that we're not
reading back OR -> head assignments properly. But, I'm confused how we're even
getting that far on a non-GSP platform. I'm going to dig into this now, but if
I don't figure out a good fix by the end of the day I'll just send a patch to
silent the warning.

Thanks again for bugging me about this!

On Wed, 2023-12-13 at 13:49 +0100, Borislav Petkov wrote:
> On Wed, Dec 13, 2023 at 12:39:36PM +0100, Borislav Petkov wrote:
> > We're getting close to releasing so I guess we either debug this or shut
> > up the WARN.
> 
> Not only that - panic_on_warn turns this into an explosion so you don't
> want that in a released kernel.
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH -next] drm/nouveau/fifo: Remove duplicated include in chan.c

2023-11-22 Thread Lyude Paul
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 v5 09/30] drm/dp: Add helpers to calculate the link BW overhead

2023-11-07 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Tue, 2023-11-07 at 02:14 +0200, Imre Deak wrote:
> Add helpers drivers can use to calculate the BW allocation overhead -
> due to SSC, FEC, DSC and data alignment on symbol cycles - and the
> channel coding efficiency - due to the 8b/10b, 128b/132b encoding. On
> 128b/132b links the FEC overhead is part of the coding efficiency, so
> not accounted for in the BW allocation overhead.
> 
> The drivers can use these functions to calculate a ratio, controlling
> the stream symbol insertion rate of the source device in each SST TU
> or MST MTP frame. Drivers can calculate this
> 
> m/n = (pixel_data_rate * drm_dp_bw_overhead()) /
>   (link_data_rate * drm_dp_bw_channel_coding_efficiency())
> 
> ratio for a given link and pixel stream and with that the
> 
> slots_per_mtp = CEIL(64 * m / n)
> 
> allocated slots per MTP for the stream in a link frame and with
> that the
> 
> pbn = slots_per_mtp * drm_mst_get_pbn_divider()
> 
> allocated PBNs for the stream on the MST link path.
> 
> Take drm_dp_bw_overhead() into use in drm_dp_calc_pbn_mode(), for
> drivers calculating the PBN value directly.
> 
> v2:
> - Add dockbook description to drm_dp_bw_channel_coding_efficiency().
>   (LKP).
> - Clarify the way m/n ratio is calculated in the commit log.
> v3:
> - Fix compile breakage for !CONFIG_BACKLIGHT_CLASS_DEVICE. (LKP)
> - Account for FEC_PM overhead (+ 0.0015625 %), add comment
>   with the formula to calculate the total FEC overhead. (Ville)
> v4:
> - Rename DRM_DP_OVERHEAD_SSC to DRM_DP_OVERHEAD_SSC_REF_CLK. (Ville)
> v5:
> - Clarify in the commit log what MTP means.
> - Simplify the commit log's formula to calculate PBN.
> 
> Cc: Lyude Paul 
> Cc: Ville Syrjälä 
> Cc: kernel test robot 
> Cc: dri-devel@lists.freedesktop.org
> Reviewed-by: Stanislav Lisovskiy  (v2)
> Acked-by: Maxime Ripard 
> Signed-off-by: Imre Deak 
> ---
>  drivers/gpu/drm/display/drm_dp_helper.c   | 132 ++
>  drivers/gpu/drm/display/drm_dp_mst_topology.c |  23 ++-
>  include/drm/display/drm_dp_helper.h   |  11 ++
>  3 files changed, 160 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> b/drivers/gpu/drm/display/drm_dp_helper.c
> index e5d7970a9ddd0..72ba9ae89f862 100644
> --- a/drivers/gpu/drm/display/drm_dp_helper.c
> +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> @@ -3900,3 +3900,135 @@ int drm_panel_dp_aux_backlight(struct drm_panel 
> *panel, struct drm_dp_aux *aux)
>  EXPORT_SYMBOL(drm_panel_dp_aux_backlight);
>  
>  #endif
> +
> +/* See DP Standard v2.1 2.6.4.4.1.1, 2.8.4.4, 2.8.7 */
> +static int drm_dp_link_symbol_cycles(int lane_count, int pixels, int bpp_x16,
> +  int symbol_size, bool is_mst)
> +{
> + int cycles = DIV_ROUND_UP(pixels * bpp_x16, 16 * symbol_size * 
> lane_count);
> + int align = is_mst ? 4 / lane_count : 1;
> +
> + return ALIGN(cycles, align);
> +}
> +
> +static int drm_dp_link_dsc_symbol_cycles(int lane_count, int pixels, int 
> slice_count,
> +  int bpp_x16, int symbol_size, bool 
> is_mst)
> +{
> + int slice_pixels = DIV_ROUND_UP(pixels, slice_count);
> + int slice_data_cycles = drm_dp_link_symbol_cycles(lane_count, 
> slice_pixels,
> +   bpp_x16, symbol_size, 
> is_mst);
> + int slice_eoc_cycles = is_mst ? 4 / lane_count : 1;
> +
> + return slice_count * (slice_data_cycles + slice_eoc_cycles);
> +}
> +
> +/**
> + * drm_dp_bw_overhead - Calculate the BW overhead of a DP link stream
> + * @lane_count: DP link lane count
> + * @hactive: pixel count of the active period in one scanline of the stream
> + * @dsc_slice_count: DSC slice count if @flags/DRM_DP_LINK_BW_OVERHEAD_DSC 
> is set
> + * @bpp_x16: bits per pixel in .4 binary fixed point
> + * @flags: DRM_DP_OVERHEAD_x flags
> + *
> + * Calculate the BW allocation overhead of a DP link stream, depending
> + * on the link's
> + * - @lane_count
> + * - SST/MST mode (@flags / %DRM_DP_OVERHEAD_MST)
> + * - symbol size (@flags / %DRM_DP_OVERHEAD_UHBR)
> + * - FEC mode (@flags / %DRM_DP_OVERHEAD_FEC)
> + * - SSC/REF_CLK mode (@flags / %DRM_DP_OVERHEAD_SSC_REF_CLK)
> + * as well as the stream's
> + * - @hactive timing
> + * - @bpp_x16 color depth
> + * - compression mode (@flags / %DRM_DP_OVERHEAD_DSC).
> + * Note that this overhead doesn't account for the 8b/10b, 128b/132b
> + * channel coding efficiency, for that see
> + * @drm_dp_link_bw_channel_coding_efficiency().
> + *
> + * Returns the overhead as 100% + overhead% in 1ppm units.
> + */
> +int drm_dp_bw_overhead(int 

Re: [PATCH v4 09/30] drm/dp: Add helpers to calculate the link BW overhead

2023-11-07 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Mon, 2023-10-30 at 17:58 +0200, Imre Deak wrote:
> Add helpers drivers can use to calculate the BW allocation overhead -
> due to SSC, FEC, DSC and data alignment on symbol cycles - and the
> channel coding efficiency - due to the 8b/10b, 128b/132b encoding. On
> 128b/132b links the FEC overhead is part of the coding efficiency, so
> not accounted for in the BW allocation overhead.
> 
> The drivers can use these functions to calculate a ratio, controlling
> the stream symbol insertion rate of the source device in each SST TU
> or MST MTP frame. Drivers can calculate this
> 
> m/n = (pixel_data_rate * drm_dp_bw_overhead()) /
>   (link_data_rate * drm_dp_bw_channel_coding_efficiency())
> 
> ratio for a given link and pixel stream and with that the
> 
> mtp_count = CEIL(64 * m / n)
> 
> allocated MTPs for the stream in a link frame and
> 
> pbn = CEIL(64 * dm_mst_get_pbn_divider() * m / n)
> 
> allocated PBNs for the stream on the MST link path.
> 
> Take drm_dp_bw_overhead() into use in drm_dp_calc_pbn_mode(), for
> drivers calculating the PBN value directly.
> 
> v2:
> - Add dockbook description to drm_dp_bw_channel_coding_efficiency().
>   (LKP).
> - Clarify the way m/n ratio is calculated in the commit log.
> v3:
> - Fix compile breakage for !CONFIG_BACKLIGHT_CLASS_DEVICE. (LKP)
> - Account for FEC_PM overhead (+ 0.0015625 %), add comment
>   with the formula to calculate the total FEC overhead. (Ville)
> v4:
> - Rename DRM_DP_OVERHEAD_SSC to DRM_DP_OVERHEAD_SSC_REF_CLK. (Ville)
> 
> Cc: Lyude Paul 
> Cc: Ville Syrjälä 
> Cc: kernel test robot 
> Cc: dri-devel@lists.freedesktop.org
> Reviewed-by: Stanislav Lisovskiy  (v2)
> Signed-off-by: Imre Deak 
> ---
>  drivers/gpu/drm/display/drm_dp_helper.c   | 132 ++
>  drivers/gpu/drm/display/drm_dp_mst_topology.c |  23 ++-
>  include/drm/display/drm_dp_helper.h   |  11 ++
>  3 files changed, 160 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> b/drivers/gpu/drm/display/drm_dp_helper.c
> index e5d7970a9ddd0..72ba9ae89f862 100644
> --- a/drivers/gpu/drm/display/drm_dp_helper.c
> +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> @@ -3900,3 +3900,135 @@ int drm_panel_dp_aux_backlight(struct drm_panel 
> *panel, struct drm_dp_aux *aux)
>  EXPORT_SYMBOL(drm_panel_dp_aux_backlight);
>  
>  #endif
> +
> +/* See DP Standard v2.1 2.6.4.4.1.1, 2.8.4.4, 2.8.7 */
> +static int drm_dp_link_symbol_cycles(int lane_count, int pixels, int bpp_x16,
> +  int symbol_size, bool is_mst)
> +{
> + int cycles = DIV_ROUND_UP(pixels * bpp_x16, 16 * symbol_size * 
> lane_count);
> + int align = is_mst ? 4 / lane_count : 1;
> +
> + return ALIGN(cycles, align);
> +}
> +
> +static int drm_dp_link_dsc_symbol_cycles(int lane_count, int pixels, int 
> slice_count,
> +  int bpp_x16, int symbol_size, bool 
> is_mst)
> +{
> + int slice_pixels = DIV_ROUND_UP(pixels, slice_count);
> + int slice_data_cycles = drm_dp_link_symbol_cycles(lane_count, 
> slice_pixels,
> +   bpp_x16, symbol_size, 
> is_mst);
> + int slice_eoc_cycles = is_mst ? 4 / lane_count : 1;
> +
> + return slice_count * (slice_data_cycles + slice_eoc_cycles);
> +}
> +
> +/**
> + * drm_dp_bw_overhead - Calculate the BW overhead of a DP link stream
> + * @lane_count: DP link lane count
> + * @hactive: pixel count of the active period in one scanline of the stream
> + * @dsc_slice_count: DSC slice count if @flags/DRM_DP_LINK_BW_OVERHEAD_DSC 
> is set
> + * @bpp_x16: bits per pixel in .4 binary fixed point
> + * @flags: DRM_DP_OVERHEAD_x flags
> + *
> + * Calculate the BW allocation overhead of a DP link stream, depending
> + * on the link's
> + * - @lane_count
> + * - SST/MST mode (@flags / %DRM_DP_OVERHEAD_MST)
> + * - symbol size (@flags / %DRM_DP_OVERHEAD_UHBR)
> + * - FEC mode (@flags / %DRM_DP_OVERHEAD_FEC)
> + * - SSC/REF_CLK mode (@flags / %DRM_DP_OVERHEAD_SSC_REF_CLK)
> + * as well as the stream's
> + * - @hactive timing
> + * - @bpp_x16 color depth
> + * - compression mode (@flags / %DRM_DP_OVERHEAD_DSC).
> + * Note that this overhead doesn't account for the 8b/10b, 128b/132b
> + * channel coding efficiency, for that see
> + * @drm_dp_link_bw_channel_coding_efficiency().
> + *
> + * Returns the overhead as 100% + overhead% in 1ppm units.
> + */
> +int drm_dp_bw_overhead(int lane_count, int hactive,
> +int dsc_slice_count,
> +int bpp_x16, unsigned long flags)
> +{
> + int symbol_size = flags & 

Re: [PATCH v4 08/30] drm/dp_mst: Add HBLANK expansion quirk for Synaptics MST hubs

2023-11-07 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Mon, 2023-10-30 at 17:58 +0200, Imre Deak wrote:
> Add a quirk for Synaptics MST hubs, which require a workaround - at leat
> on i915 - for some modes, on which the hub applies HBLANK expansion.
> These modes will only work by enabling DSC decompression for them, a
> follow-up patch will do this in i915.
> 
> v2:
> - Fix the quirk name in its DocBook description.
> 
> Cc: Lyude Paul 
> Cc: dri-devel@lists.freedesktop.org
> Reviewed-by: Stanislav Lisovskiy 
> Signed-off-by: Imre Deak 
> ---
>  drivers/gpu/drm/display/drm_dp_helper.c | 2 ++
>  include/drm/display/drm_dp_helper.h | 7 +++
>  2 files changed, 9 insertions(+)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> b/drivers/gpu/drm/display/drm_dp_helper.c
> index f3680f4e69708..e5d7970a9ddd0 100644
> --- a/drivers/gpu/drm/display/drm_dp_helper.c
> +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> @@ -2245,6 +2245,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {
>   { OUI(0x00, 0x00, 0x00), DEVICE_ID('C', 'H', '7', '5', '1', '1'), 
> false, BIT(DP_DPCD_QUIRK_NO_SINK_COUNT) },
>   /* Synaptics DP1.4 MST hubs can support DSC without virtual DPCD */
>   { OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, 
> BIT(DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) },
> + /* Synaptics DP1.4 MST hubs require DSC for some modes on which it 
> applies HBLANK expansion. */
> + { OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, 
> BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) },
>   /* Apple MacBookPro 2017 15 inch eDP Retina panel reports too low 
> DP_MAX_LINK_RATE */
>   { OUI(0x00, 0x10, 0xfa), DEVICE_ID(101, 68, 21, 101, 98, 97), false, 
> BIT(DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS) },
>  };
> diff --git a/include/drm/display/drm_dp_helper.h 
> b/include/drm/display/drm_dp_helper.h
> index 3d74b2cec72fd..da94932f4262b 100644
> --- a/include/drm/display/drm_dp_helper.h
> +++ b/include/drm/display/drm_dp_helper.h
> @@ -632,6 +632,13 @@ enum drm_dp_quirk {
>* the DP_MAX_LINK_RATE register reporting a lower max multiplier.
>*/
>   DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS,
> + /**
> +  * @DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC:
> +  *
> +  * The device applies HBLANK expansion for some modes, but this
> +  * requires enabling DSC.
> +  */
> + DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC,
>  };
>  
>  /**

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH v4 07/30] drm/dp: Add DP_HBLANK_EXPANSION_CAPABLE and DSC_PASSTHROUGH_EN DPCD flags

2023-11-07 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Mon, 2023-10-30 at 17:58 +0200, Imre Deak wrote:
> Add the DPCD flag to enable DSC passthrough in a last branch device,
> used in a follow-up i915 patch.
> 
> Also add a flag to detect HBLANK expansion support in a branch device,
> used by a workaround in a follow-up i915 patch.
> 
> Cc: Lyude Paul 
> Cc: dri-devel@lists.freedesktop.org
> Reviewed-by: Stanislav Lisovskiy 
> Signed-off-by: Imre Deak 
> ---
>  include/drm/display/drm_dp.h | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
> index e69cece404b3c..763d45a612f35 100644
> --- a/include/drm/display/drm_dp.h
> +++ b/include/drm/display/drm_dp.h
> @@ -148,6 +148,7 @@
>  #define DP_RECEIVE_PORT_0_CAP_0  0x008
>  # define DP_LOCAL_EDID_PRESENT   (1 << 1)
>  # define DP_ASSOCIATED_TO_PRECEDING_PORT(1 << 2)
> +# define DP_HBLANK_EXPANSION_CAPABLE(1 << 3)
>  
>  #define DP_RECEIVE_PORT_0_BUFFER_SIZE0x009
>  
> @@ -699,6 +700,7 @@
>  
>  #define DP_DSC_ENABLE   0x160   /* DP 1.4 */
>  # define DP_DECOMPRESSION_EN(1 << 0)
> +# define DP_DSC_PASSTHROUGH_EN   (1 << 1)
>  #define DP_DSC_CONFIGURATION     0x161   /* DP 2.0 */
>  
>  #define DP_PSR_EN_CFG0x170   /* XXX 1.2? */

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH v4 06/30] drm/dp_mst: Allow DSC in any Synaptics last branch device

2023-11-07 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Mon, 2023-10-30 at 17:58 +0200, Imre Deak wrote:
> The Synaptics MST branch devices support DSC decompression on all their
> output ports, provided that they are last branch devices (with their
> output ports connected to the sinks). The Thinkpad 40B0 TBT dock for
> instance has two such branch devices, a secondary one connected to one
> of the output ports of the primary; hence the decompression needs to be
> enabled in both branch devices to enable decompression for all the
> sinks.
> 
> Based on the above add support for enabling decompression in last
> Synaptics branch devices.
> 
> Cc: Lyude Paul 
> Cc: dri-devel@lists.freedesktop.org
> Reviewed-by: Stanislav Lisovskiy 
> Signed-off-by: Imre Deak 
> ---
>  drivers/gpu/drm/display/drm_dp_mst_topology.c | 21 ---
>  1 file changed, 13 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
> b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> index 5972c93615f18..cc0a8fe84d290 100644
> --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> @@ -5994,6 +5994,7 @@ static bool drm_dp_mst_is_virtual_dpcd(struct 
> drm_dp_mst_port *port)
>  struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port)
>  {
>   struct drm_dp_mst_port *immediate_upstream_port;
> + struct drm_dp_aux *immediate_upstream_aux;
>   struct drm_dp_mst_port *fec_port;
>   struct drm_dp_desc desc = {};
>   u8 endpoint_fec;
> @@ -6058,21 +6059,25 @@ struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct 
> drm_dp_mst_port *port)
>* - Port is on primary branch device
>* - Not a VGA adapter (DP_DWN_STRM_PORT_TYPE_ANALOG)
>*/
> - if (drm_dp_read_desc(port->mgr->aux, , true))
> + if (immediate_upstream_port)
> + immediate_upstream_aux = _upstream_port->aux;
> + else
> + immediate_upstream_aux = port->mgr->aux;
> +
> + if (drm_dp_read_desc(immediate_upstream_aux, , true))
>   return NULL;
>  
> - if (drm_dp_has_quirk(, DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) &&
> - port->mgr->dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14 &&
> - port->parent == port->mgr->mst_primary) {
> + if (drm_dp_has_quirk(, DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD)) {
>   u8 dpcd_ext[DP_RECEIVER_CAP_SIZE];
>  
> - if (drm_dp_read_dpcd_caps(port->mgr->aux, dpcd_ext) < 0)
> + if (drm_dp_read_dpcd_caps(immediate_upstream_aux, dpcd_ext) < 0)
>   return NULL;
>  
> - if ((dpcd_ext[DP_DOWNSTREAMPORT_PRESENT] & 
> DP_DWN_STRM_PORT_PRESENT) &&
> + if (dpcd_ext[DP_DPCD_REV] >= DP_DPCD_REV_14 &&
> + ((dpcd_ext[DP_DOWNSTREAMPORT_PRESENT] & 
> DP_DWN_STRM_PORT_PRESENT) &&
>   ((dpcd_ext[DP_DOWNSTREAMPORT_PRESENT] & 
> DP_DWN_STRM_PORT_TYPE_MASK)
> -  != DP_DWN_STRM_PORT_TYPE_ANALOG))
> - return port->mgr->aux;
> +  != DP_DWN_STRM_PORT_TYPE_ANALOG)))
> + return immediate_upstream_aux;
>   }
>  
>   /*

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH] drm/nouveau/disp: fix DP capable DSM connectors

2023-10-12 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Wed, 2023-10-11 at 13:41 +0200, Karol Herbst wrote:
> Just special case DP DSM connectors until we properly figure out how to
> deal with this.
> 
> This resolves user regressions on GPUs with such connectors without
> reverting the original fix.
> 
> Cc: Lyude Paul 
> Cc: sta...@vger.kernel.org # 6.4+
> Closes: https://gitlab.freedesktop.org/drm/nouveau/-/issues/255
> Fixes: 2b5d1c29f6c4 ("drm/nouveau/disp: PIOR DP uses GPIO for HPD, not PMGR 
> AUX interrupts")
> Signed-off-by: Karol Herbst 
> ---
>  drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c | 14 +-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c 
> b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
> index 46b057fe1412e..3249e5c1c8930 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
> @@ -62,6 +62,18 @@ nvkm_uconn_uevent_gpio(struct nvkm_object *object, u64 
> token, u32 bits)
>   return object->client->event(token, , sizeof(args.v0));
>  }
>  
> +static bool
> +nvkm_connector_is_dp_dms(u8 type)
> +{
> + switch (type) {
> + case DCB_CONNECTOR_DMS59_DP0:
> + case DCB_CONNECTOR_DMS59_DP1:
> + return true;
> + default:
> + return false;
> + }
> +}
> +
>  static int
>  nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct 
> nvkm_uevent *uevent)
>  {
> @@ -101,7 +113,7 @@ nvkm_uconn_uevent(struct nvkm_object *object, void *argv, 
> u32 argc, struct nvkm_
>   if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_GPIO_LO;
>   if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ) {
>   /* TODO: support DP IRQ on ANX9805 and remove this hack. */
> - if (!outp->info.location)
> + if (!outp->info.location && 
> !nvkm_connector_is_dp_dms(conn->info.type))
>   return -EINVAL;
>   }
>  

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH] drm/nouveau: exec: fix ioctl kernel-doc warning

2023-10-09 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Fri, 2023-10-06 at 17:55 -0700, Randy Dunlap wrote:
> include/uapi/drm/nouveau_drm.h:49: warning: Cannot understand  * 
> @NOUVEAU_GETPARAM_EXEC_PUSH_MAX
>  on line 49 - I thought it was a doc line
> 
> Fixes: d59e75eef52d ("drm/nouveau: exec: report max pushs through getparam")
> Signed-off-by: Randy Dunlap 
> Cc: Dave Airlie 
> Cc: Danilo Krummrich 
> Cc: Karol Herbst 
> Cc: Lyude Paul 
> Cc: dri-devel@lists.freedesktop.org
> Cc: nouv...@lists.freedesktop.org
> ---
>  include/uapi/drm/nouveau_drm.h |4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff -- a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h
> --- a/include/uapi/drm/nouveau_drm.h
> +++ b/include/uapi/drm/nouveau_drm.h
> @@ -45,8 +45,8 @@ extern "C" {
>  #define NOUVEAU_GETPARAM_HAS_BO_USAGE15
>  #define NOUVEAU_GETPARAM_HAS_PAGEFLIP16
>  
> -/**
> - * @NOUVEAU_GETPARAM_EXEC_PUSH_MAX
> +/*
> + * NOUVEAU_GETPARAM_EXEC_PUSH_MAX - query max pushes through getparam
>   *
>   * Query the maximum amount of IBs that can be pushed through a single
>   * _nouveau_exec structure and hence a single _IOCTL_NOUVEAU_EXEC
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH] drm/i2c/ch7006: fix a possible null pointer dereference

2023-10-09 Thread Lyude Paul
On Sat, 2023-10-07 at 11:17 +0800, Ma Ke wrote:
> In ch7006_encoder_get_modes(), the return value of drm_mode_duplicate()
> is assigned to mode, which will lead to a NULL pointer dereference
> on failure of drm_mode_duplicate(). Add a check to avoid npd.
> 
> Signed-off-by: Ma Ke 
> ---
>  drivers/gpu/drm/i2c/ch7006_drv.c | 6 --
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c 
> b/drivers/gpu/drm/i2c/ch7006_drv.c
> index 131512a5f3bd..27c2f02f5b43 100644
> --- a/drivers/gpu/drm/i2c/ch7006_drv.c
> +++ b/drivers/gpu/drm/i2c/ch7006_drv.c
> @@ -236,8 +236,10 @@ static int ch7006_encoder_get_modes(struct drm_encoder 
> *encoder,
>   ~mode->valid_norms & 1<norm)
>   continue;
>  
> - drm_mode_probed_add(connector,
> - drm_mode_duplicate(encoder->dev, >mode));
> + struct drm_display_mode *encoder_mode;
> + encoder_mode = drm_mode_duplicate(encoder->dev, >mode);

I think the kernel prefers to have variable declaration at the top of the
scope, and as well: this breaks things because you don't add back the
drm_mode_probed_add() call.

> + if (!mode)
> + continue;
>  
>   n++;
>   }

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH v2] drm/nouveau: exec: fix ioctl kernel-doc warning

2023-10-09 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Sun, 2023-10-08 at 07:02 -0700, Randy Dunlap wrote:
> kernel-doc emits a warning:
> 
> include/uapi/drm/nouveau_drm.h:49: warning: Cannot understand  * 
> @NOUVEAU_GETPARAM_EXEC_PUSH_MAX
>  on line 49 - I thought it was a doc line
> 
> We don't have a way to document a macro value via kernel-doc, so
> change the "/**" kernel-doc marker to a C comment and format the comment
> more like a kernel-doc comment for consistency.
> 
> Fixes: d59e75eef52d ("drm/nouveau: exec: report max pushs through getparam")
> Signed-off-by: Randy Dunlap 
> Cc: Dave Airlie 
> Cc: Danilo Krummrich 
> Cc: Karol Herbst 
> Cc: Lyude Paul 
> Cc: dri-devel@lists.freedesktop.org
> Cc: nouv...@lists.freedesktop.org
> Cc: Bragatheswaran Manickavel 
> ---
> v2: update commit text; somehow I sent a version of the patch before
> adding the full text.
> v1: https://lore.kernel.org/lkml/20231007005518.32015-1-rdun...@infradead.org/
> 
>  include/uapi/drm/nouveau_drm.h |4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff -- a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h
> --- a/include/uapi/drm/nouveau_drm.h
> +++ b/include/uapi/drm/nouveau_drm.h
> @@ -45,8 +45,8 @@ extern "C" {
>  #define NOUVEAU_GETPARAM_HAS_BO_USAGE15
>  #define NOUVEAU_GETPARAM_HAS_PAGEFLIP16
>  
> -/**
> - * @NOUVEAU_GETPARAM_EXEC_PUSH_MAX
> +/*
> + * NOUVEAU_GETPARAM_EXEC_PUSH_MAX - query max pushes through getparam
>   *
>   * Query the maximum amount of IBs that can be pushed through a single
>   * _nouveau_exec structure and hence a single _IOCTL_NOUVEAU_EXEC
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH] drm/atomic-helper: relax unregistered connector check

2023-10-05 Thread Lyude Paul
This seems like a very good solution to the problem :)

Reviewed-by: Lyude Paul 

On Thu, 2023-10-05 at 13:16 +, Simon Ser wrote:
> The driver might pull connectors which weren't submitted by
> user-space into the atomic state. For instance,
> intel_dp_mst_atomic_master_trans_check() pulls in connectors
> sharing the same DP-MST stream. However, if the connector is
> unregistered, this later fails with:
> 
> [  559.425658] i915 :00:02.0: [drm:drm_atomic_helper_check_modeset] 
> [CONNECTOR:378:DP-7] is not registered
> 
> Skip the unregistered connector check to allow user-space to turn
> off connectors one-by-one.
> 
> See this wlroots issue:
> https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3407
> 
> Previous discussion:
> https://lore.kernel.org/intel-gfx/y6gx7z17wmdsk...@ideak-desk.fi.intel.com/
> 
> Signed-off-by: Simon Ser 
> Cc: Ville Syrjälä 
> Cc: Jani Nikula 
> Cc: Lyude Paul 
> Cc: Imre Deak 
> ---
>  drivers/gpu/drm/drm_atomic_helper.c | 17 +
>  1 file changed, 13 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> b/drivers/gpu/drm/drm_atomic_helper.c
> index 71d399397107..c9b8343eaa20 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -290,7 +290,8 @@ static int
>  update_connector_routing(struct drm_atomic_state *state,
>struct drm_connector *connector,
>struct drm_connector_state *old_connector_state,
> -  struct drm_connector_state *new_connector_state)
> +  struct drm_connector_state *new_connector_state,
> +  bool added_by_user)
>  {
>   const struct drm_connector_helper_funcs *funcs;
>   struct drm_encoder *new_encoder;
> @@ -339,9 +340,13 @@ update_connector_routing(struct drm_atomic_state *state,
>* there's a chance the connector may have been destroyed during the
>* process, but it's better to ignore that then cause
>* drm_atomic_helper_resume() to fail.
> +  *
> +  * Last, we want to ignore connector registration when the connector
> +  * was not pulled in the atomic state by user-space (ie, was pulled
> +  * in by the driver, e.g. when updating a DP-MST stream).
>*/
>   if (!state->duplicated && drm_connector_is_unregistered(connector) &&
> - crtc_state->active) {
> + added_by_user && crtc_state->active) {
>   drm_dbg_atomic(connector->dev,
>  "[CONNECTOR:%d:%s] is not registered\n",
>  connector->base.id, connector->name);
> @@ -620,7 +625,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
>   struct drm_connector *connector;
>   struct drm_connector_state *old_connector_state, *new_connector_state;
>   int i, ret;
> - unsigned int connectors_mask = 0;
> + unsigned int connectors_mask = 0, user_connectors_mask = 0;
> +
> + for_each_oldnew_connector_in_state(state, connector, 
> old_connector_state, new_connector_state, i)
> + user_connectors_mask |= BIT(i);
>  
>   for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
> new_crtc_state, i) {
>   bool has_connectors =
> @@ -685,7 +693,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
>*/
>   ret = update_connector_routing(state, connector,
>  old_connector_state,
> -new_connector_state);
> +new_connector_state,
> +BIT(i) & 
> user_connectors_mask);
>   if (ret)
>   return ret;
>   if (old_connector_state->crtc) {

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH v2 1/3] drm/nouveau: chan: use struct nvif_mclass

2023-10-02 Thread Lyude Paul
For the whole series:

Reviewed-by: Lyude Paul 

On Mon, 2023-10-02 at 15:46 +0200, Danilo Krummrich wrote:
> Use actual struct nvif_mclass instead of identical anonymous struct.
> 
> Signed-off-by: Danilo Krummrich 
> ---
>  drivers/gpu/drm/nouveau/nouveau_chan.c | 5 +
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c 
> b/drivers/gpu/drm/nouveau/nouveau_chan.c
> index 1fd5ccf41128..dffbee59be6a 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_chan.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
> @@ -259,10 +259,7 @@ static int
>  nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, 
> bool priv, u64 runm,
>struct nouveau_channel **pchan)
>  {
> - static const struct {
> - s32 oclass;
> - int version;
> - } hosts[] = {
> + const struct nvif_mclass hosts[] = {
>   {  AMPERE_CHANNEL_GPFIFO_B, 0 },
>   {  AMPERE_CHANNEL_GPFIFO_A, 0 },
>   {  TURING_CHANNEL_GPFIFO_A, 0 },

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH] drm/nouveau: fence: fix type cast warning in nouveau_fence_emit()

2023-09-29 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Sat, 2023-09-16 at 03:14 +0200, Danilo Krummrich wrote:
> Fix the following warning.
> 
>   drivers/gpu/drm/nouveau/nouveau_fence.c:210:45: sparse: sparse:
>   incorrect type in initializer (different address spaces)
>   @@ expected struct nouveau_channel *chan
>   @@ got struct nouveau_channel [noderef] __rcu *channel
> 
> We're just about to emit the fence, there is nothing to protect against
> yet, hence it is safe to just cast __rcu away.
> 
> Reported-by: kernel test robot 
> Closes: 
> https://lore.kernel.org/oe-kbuild-all/202309140340.bwkxzadx-...@intel.com/
> Fixes: 978474dc8278 ("drm/nouveau: fence: fix undefined fence state after 
> emit")
> Signed-off-by: Danilo Krummrich 
> ---
>  drivers/gpu/drm/nouveau/nouveau_fence.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c 
> b/drivers/gpu/drm/nouveau/nouveau_fence.c
> index 61d9e70da9fd..ca762ea55413 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_fence.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
> @@ -207,7 +207,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, 
> struct nouveau_fence_cha
>  int
>  nouveau_fence_emit(struct nouveau_fence *fence)
>  {
> - struct nouveau_channel *chan = fence->channel;
> + struct nouveau_channel *chan = unrcu_pointer(fence->channel);
>   struct nouveau_fence_chan *fctx = chan->fence;
>   struct nouveau_fence_priv *priv = (void*)chan->drm->fence;
>   int ret;

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [RFT PATCH v2 04/12] drm/nouveau: Call drm_atomic_helper_shutdown() or equiv at shutdown time

2023-09-22 Thread Lyude Paul
actually very glad to see this because I think I've seen one bug in the wild
as a result of things not getting shut down :)

Reviewed-by: Lyude Paul 
Tested-by: Lyude Paul 

On Thu, 2023-09-21 at 12:26 -0700, Douglas Anderson wrote:
> Based on grepping through the source code this driver appears to be
> missing a call to drm_atomic_helper_shutdown() (or
> drm_helper_force_disable_all() if not using atomic) at system shutdown
> time. Among other things, this means that if a panel is in use that it
> won't be cleanly powered off at system shutdown time.
> 
> The fact that we should call drm_atomic_helper_shutdown() in the case
> of OS shutdown/restart comes straight out of the kernel doc "driver
> instance overview" in drm_drv.c.
> 
> Suggested-by: Maxime Ripard 
> Reviewed-by: Maxime Ripard 
> Signed-off-by: Douglas Anderson 
> ---
> This commit is only compile-time tested. I made my best guess about
> how to fit this into the existing code. If someone wishes a different
> style, please yell.
> 
> (no changes since v1)
> 
>  drivers/gpu/drm/nouveau/nouveau_display.c  |  9 +
>  drivers/gpu/drm/nouveau/nouveau_display.h  |  1 +
>  drivers/gpu/drm/nouveau/nouveau_drm.c  | 13 +
>  drivers/gpu/drm/nouveau/nouveau_drv.h  |  1 +
>  drivers/gpu/drm/nouveau/nouveau_platform.c |  6 ++
>  5 files changed, 30 insertions(+)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
> b/drivers/gpu/drm/nouveau/nouveau_display.c
> index d8c92521226d..05c3688ccb76 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_display.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_display.c
> @@ -642,6 +642,15 @@ nouveau_display_fini(struct drm_device *dev, bool 
> suspend, bool runtime)
>   disp->fini(dev, runtime, suspend);
>  }
>  
> +void
> +nouveau_display_shutdown(struct drm_device *dev)
> +{
> + if (drm_drv_uses_atomic_modeset(dev))
> + drm_atomic_helper_shutdown(dev);
> + else
> + drm_helper_force_disable_all(dev);
> +}
> +
>  static void
>  nouveau_display_create_properties(struct drm_device *dev)
>  {
> diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h 
> b/drivers/gpu/drm/nouveau/nouveau_display.h
> index 2ab2ddb1eadf..9df62e833cda 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_display.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_display.h
> @@ -47,6 +47,7 @@ void nouveau_display_destroy(struct drm_device *dev);
>  int  nouveau_display_init(struct drm_device *dev, bool resume, bool runtime);
>  void nouveau_display_hpd_resume(struct drm_device *dev);
>  void nouveau_display_fini(struct drm_device *dev, bool suspend, bool 
> runtime);
> +void nouveau_display_shutdown(struct drm_device *dev);
>  int  nouveau_display_suspend(struct drm_device *dev, bool runtime);
>  void nouveau_display_resume(struct drm_device *dev, bool runtime);
>  int  nouveau_display_vblank_enable(struct drm_crtc *crtc);
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c 
> b/drivers/gpu/drm/nouveau/nouveau_drm.c
> index 50589f982d1a..8ecfd66b7aab 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drm.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
> @@ -879,6 +879,18 @@ nouveau_drm_remove(struct pci_dev *pdev)
>   pci_disable_device(pdev);
>  }
>  
> +void
> +nouveau_drm_device_shutdown(struct drm_device *dev)
> +{
> + nouveau_display_shutdown(dev);
> +}
> +
> +static void
> +nouveau_drm_shutdown(struct pci_dev *pdev)
> +{
> + nouveau_drm_device_shutdown(pci_get_drvdata(pdev));
> +}
> +
>  static int
>  nouveau_do_suspend(struct drm_device *dev, bool runtime)
>  {
> @@ -1346,6 +1358,7 @@ nouveau_drm_pci_driver = {
>   .id_table = nouveau_drm_pci_table,
>   .probe = nouveau_drm_probe,
>   .remove = nouveau_drm_remove,
> + .shutdown = nouveau_drm_shutdown,
>   .driver.pm = _pm_ops,
>  };
>  
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h 
> b/drivers/gpu/drm/nouveau/nouveau_drv.h
> index 3666a7403e47..aa936cabb6cf 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
> @@ -327,6 +327,7 @@ struct drm_device *
>  nouveau_platform_device_create(const struct nvkm_device_tegra_func *,
>  struct platform_device *, struct nvkm_device **);
>  void nouveau_drm_device_remove(struct drm_device *dev);
> +void nouveau_drm_device_shutdown(struct drm_device *dev);
>  
>  #define NV_PRINTK(l,c,f,a...) do {   
>   \
>   struct nouveau_cli *_cli = (c);\
> diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c 
> b/drivers/gpu/drm/nouveau/nouveau_platform.c
> index 23cd43a7fd19..

Re: [PATCH] drm/mst: check connector state before dereference

2023-09-22 Thread Lyude Paul
;connector);
> - topology_state->pending_crtc_mask |= drm_crtc_mask(conn_state->crtc);
> + WARN_ON(!conn_state);
> + if (conn_state)
> + topology_state->pending_crtc_mask |= 
> drm_crtc_mask(conn_state->crtc);
>  
>   /* Find the current allocation for this port, if any */
>   payload = drm_atomic_get_mst_payload_state(topology_state, port);
> @@ -4400,12 +4402,14 @@ int drm_dp_atomic_release_time_slots(struct 
> drm_atomic_state *state,
>   bool update_payload = true;
>  
>   old_conn_state = drm_atomic_get_old_connector_state(state, 
> port->connector);
> - if (!old_conn_state->crtc)
> + WARN_ON(!old_conn_state);

> + if (!old_conn_state || !old_conn_state->crtc)
>   return 0;
>  
>   /* If the CRTC isn't disabled by this state, don't release it's payload 
> */
>   new_conn_state = drm_atomic_get_new_connector_state(state, 
> port->connector);
> - if (new_conn_state->crtc) {
> + WARN_ON(!new_conn_state);
> + if (new_conn_state && new_conn_state->crtc) {
>   struct drm_crtc_state *crtc_state =
>   drm_atomic_get_new_crtc_state(state, 
> new_conn_state->crtc);
>  
> @@ -4432,7 +4436,7 @@ int drm_dp_atomic_release_time_slots(struct 
> drm_atomic_state *state,
>   return -EINVAL;
>   }
>  
> - if (new_conn_state->crtc)
> + if (new_conn_state && new_conn_state->crtc)
>   return 0;
>  
>   drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, 
> payload->time_slots);

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH v1] drm/dp/mst: fix missing modeset unlock for MST port detect

2023-09-22 Thread Lyude Paul
…ugh, thanks for catching that :|

yes you're completely right - NAK on this patch then

On Fri, 2023-09-22 at 22:22 +0300, Imre Deak wrote:
> On Fri, Sep 22, 2023 at 03:02:23PM -0400, Lyude Paul wrote:
> > 
> > Oh! wow thank you for catching this:
> > 
> > Reviewed-by: Lyude Paul 
> > 
> > I will go and push this to drm-misc-next in just a moment
> > 
> > On Fri, 2023-09-15 at 10:24 +0530, Ramya SR wrote:
> > > Modeset mutex unlock is missing in drm_dp_mst_detect_port function.
> > > This will lead to deadlock if calling the function multiple times in
> > > an atomic operation, for example, getting imultiple MST ports status
> > > for a DP MST bonding scenario.
> > > 
> > > Signed-off-by: Ramya SR 
> > > ---
> > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 4 +++-
> > >  1 file changed, 3 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
> > > b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > index ed96cfc..d6512c4 100644
> > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > @@ -4154,7 +4154,7 @@ drm_dp_mst_detect_port(struct drm_connector 
> > > *connector,
> > >  
> > >   ret = drm_modeset_lock(>base.lock, ctx);
> > >   if (ret)
> > > - goto out;
> > > + goto fail;
> > >  
> > >   ret = connector_status_disconnected;
> > >  
> > > @@ -4181,6 +4181,8 @@ drm_dp_mst_detect_port(struct drm_connector 
> > > *connector,
> > >       break;
> > >   }
> > >  out:
> > > + drm_modeset_unlock(>base.lock);
> 
> Isn't this supposed to be unlocked only by drm_helper_probe_detect_ctx()
> / drm_helper_probe_detect() ?
> 
> > > +fail:
> > >   drm_dp_mst_topology_put_port(port);
> > >   return ret;
> > >  }
> > 
> > -- 
> > Cheers,
> >  Lyude Paul (she/her)
> >  Software Engineer at Red Hat
> > 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH v1] drm/dp/mst: fix missing modeset unlock for MST port detect

2023-09-22 Thread Lyude Paul


Oh! wow thank you for catching this:

Reviewed-by: Lyude Paul 

I will go and push this to drm-misc-next in just a moment

On Fri, 2023-09-15 at 10:24 +0530, Ramya SR wrote:
> Modeset mutex unlock is missing in drm_dp_mst_detect_port function.
> This will lead to deadlock if calling the function multiple times in
> an atomic operation, for example, getting imultiple MST ports status
> for a DP MST bonding scenario.
> 
> Signed-off-by: Ramya SR 
> ---
>  drivers/gpu/drm/display/drm_dp_mst_topology.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
> b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> index ed96cfc..d6512c4 100644
> --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> @@ -4154,7 +4154,7 @@ drm_dp_mst_detect_port(struct drm_connector *connector,
>  
>   ret = drm_modeset_lock(>base.lock, ctx);
>   if (ret)
> - goto out;
> + goto fail;
>  
>   ret = connector_status_disconnected;
>  
> @@ -4181,6 +4181,8 @@ drm_dp_mst_detect_port(struct drm_connector *connector,
>   break;
>   }
>  out:
> + drm_modeset_unlock(>base.lock);
> +fail:
>   drm_dp_mst_topology_put_port(port);
>   return ret;
>  }

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH 5/9] drm/nouveau/pm: Annotate struct nvkm_perfdom with __counted_by

2023-09-22 Thread Lyude Paul
Reviewed-by: Lyude Paul 

Thanks!

On Fri, 2023-09-22 at 10:32 -0700, Kees Cook wrote:
> Prepare for the coming implementation by GCC and Clang of the __counted_by
> attribute. Flexible array members annotated with __counted_by can have
> their accesses bounds-checked at run-time checking via CONFIG_UBSAN_BOUNDS
> (for array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family
> functions).
> 
> As found with Coccinelle[1], add __counted_by for struct nvkm_perfdom.
> 
> [1] 
> https://github.com/kees/kernel-tools/blob/trunk/coccinelle/examples/counted_by.cocci
> 
> Cc: Ben Skeggs 
> Cc: Karol Herbst 
> Cc: Lyude Paul 
> Cc: David Airlie 
> Cc: Daniel Vetter 
> Cc: dri-devel@lists.freedesktop.org
> Cc: nouv...@lists.freedesktop.org
> Signed-off-by: Kees Cook 
> ---
>  drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h 
> b/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h
> index 6ae25d3e7f45..c011227f7052 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h
> +++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h
> @@ -82,7 +82,7 @@ struct nvkm_perfdom {
>   u8  mode;
>   u32 clk;
>   u16 signal_nr;
> - struct nvkm_perfsig signal[];
> + struct nvkm_perfsig signal[] __counted_by(signal_nr);
>  };
>  
>  struct nvkm_funcdom {

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



[PATCH v3 44/44] drm/nouveau/kms/nv50-: disable dcb parsing

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- nvkm should provide all this info now
- preparation for GSP-RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nouveau_bios.c| 8 +---
 drivers/gpu/drm/nouveau/nouveau_display.c | 8 
 drivers/gpu/drm/nouveau/nvif/disp.c   | 2 +-
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c 
b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 189903b65edc9..9e878cdc8e38e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -2093,9 +2093,11 @@ nouveau_bios_init(struct drm_device *dev)
if (!NVInitVBIOS(dev))
return -ENODEV;
 
-   ret = parse_dcb_table(dev, bios);
-   if (ret)
-   return ret;
+   if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) {
+   ret = parse_dcb_table(dev, bios);
+   if (ret)
+   return ret;
+   }
 
if (!bios->major_version)   /* we don't run version 0 bios */
return 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c
index 99977e5fe7161..d8c92521226d9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -724,10 +724,10 @@ nouveau_display_create(struct drm_device *dev)
drm_kms_helper_poll_init(dev);
drm_kms_helper_poll_disable(dev);
 
-   if (nouveau_modeset != 2 && drm->vbios.dcb.entries) {
-   ret = nvif_disp_ctor(>client.device, "kmsDisp", 0,
->disp);
-   if (ret == 0) {
+   if (nouveau_modeset != 2) {
+   ret = nvif_disp_ctor(>client.device, "kmsDisp", 0, 
>disp);
+
+   if (!ret && (disp->disp.outp_mask || drm->vbios.dcb.entries)) {
nouveau_display_create_properties(dev);
if (disp->disp.object.oclass < NV50_DISP) {
dev->mode_config.fb_modifiers_not_supported = 
true;
diff --git a/drivers/gpu/drm/nouveau/nvif/disp.c 
b/drivers/gpu/drm/nouveau/nvif/disp.c
index 09915f2715afd..097246e10cdb7 100644
--- a/drivers/gpu/drm/nouveau/nvif/disp.c
+++ b/drivers/gpu/drm/nouveau/nvif/disp.c
@@ -60,7 +60,7 @@ nvif_disp_ctor(struct nvif_device *device, const char *name, 
s32 oclass, struct
cid = nvif_sclass(>object, disps, oclass);
disp->object.client = NULL;
if (cid < 0) {
-   NVIF_ERRON(cid, >object, "[NEW disp%04x] not 
supported", oclass);
+   NVIF_DEBUG(>object, "[NEW disp%04x] not supported", 
oclass);
return cid;
}
 
-- 
2.41.0



[PATCH v3 43/44] drm/nouveau/kms/nv50-: create outputs based on nvkm info

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- preparation for GSP-RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 97 ++-
 drivers/gpu/drm/nouveau/dispnv50/disp.h   |  2 -
 drivers/gpu/drm/nouveau/include/nvif/if0012.h | 31 +-
 drivers/gpu/drm/nouveau/include/nvif/outp.h   | 40 
 drivers/gpu/drm/nouveau/nouveau_connector.c   |  2 +-
 drivers/gpu/drm/nouveau/nvif/outp.c   | 44 +
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c |  5 +-
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.h   |  2 +
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  | 50 ++
 9 files changed, 223 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index e2fa748e66f16..dcd19c4183894 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -66,8 +66,6 @@
 #include "nouveau_fence.h"
 #include "nv50_display.h"
 
-#include 
-
 /**
  * EVO channel
  */
@@ -1704,7 +1702,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, 
struct drm_atomic_state *sta
}
 
if (head->func->display_id)
-   head->func->display_id(head, BIT(nv_encoder->dcb->id));
+   head->func->display_id(head, BIT(nv_encoder->outp.id));
 
nv_encoder->update(nv_encoder, nv_crtc->index, asyh, proto, depth);
 }
@@ -1736,16 +1734,6 @@ nv50_sor_func = {
.destroy = nv50_sor_destroy,
 };
 
-bool nv50_has_mst(struct nouveau_drm *drm)
-{
-   struct nvkm_bios *bios = nvxx_bios(>client.device);
-   u32 data;
-   u8 ver, hdr, cnt, len;
-
-   data = nvbios_dp_table(bios, , , , );
-   return data && ver >= 0x40 && (nvbios_rd08(bios, data + 0x08) & 0x04);
-}
-
 static int
 nv50_sor_create(struct nouveau_encoder *nv_encoder)
 {
@@ -1798,15 +1786,15 @@ nv50_sor_create(struct nouveau_encoder *nv_encoder)
nv_encoder->i2c = _connector->aux.ddc;
}
 
-   if (nv_connector->type != DCB_CONNECTOR_eDP &&
-   nv50_has_mst(drm)) {
+   if (nv_connector->type != DCB_CONNECTOR_eDP && 
nv_encoder->outp.info.dp.mst) {
ret = nv50_mstm_new(nv_encoder, _connector->aux,
16, nv_connector->base.base.id,
_encoder->dp.mstm);
if (ret)
return ret;
}
-   } else {
+   } else
+   if (nv_encoder->outp.info.ddc != NVIF_OUTP_DDC_INVALID) {
struct nvkm_i2c_bus *bus =
nvkm_i2c_bus_find(i2c, dcbe->i2c_index);
if (bus)
@@ -1927,12 +1915,12 @@ nv50_pior_create(struct nouveau_encoder *nv_encoder)
 
switch (dcbe->type) {
case DCB_OUTPUT_TMDS:
-   bus  = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_EXT(dcbe->extdev));
+   bus  = nvkm_i2c_bus_find(i2c, nv_encoder->outp.info.ddc);
ddc  = bus ? >i2c : NULL;
type = DRM_MODE_ENCODER_TMDS;
break;
case DCB_OUTPUT_DP:
-   aux  = nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_EXT(dcbe->extdev));
+   aux  = nvkm_i2c_aux_find(i2c, nv_encoder->outp.info.dp.aux);
ddc  = aux ? >i2c : NULL;
type = DRM_MODE_ENCODER_TMDS;
break;
@@ -2693,12 +2681,10 @@ int
 nv50_display_create(struct drm_device *dev)
 {
struct nouveau_drm *drm = nouveau_drm(dev);
-   struct dcb_table *dcb = >vbios.dcb;
struct drm_connector *connector, *tmp;
struct nv50_disp *disp;
-   struct dcb_output *dcbe;
int ret, i;
-   bool has_mst = nv50_has_mst(drm);
+   bool has_mst = false;
 
disp = kzalloc(sizeof(*disp), GFP_KERNEL);
if (!disp)
@@ -2775,54 +2761,75 @@ nv50_display_create(struct drm_device *dev)
}
 
/* create encoder/connector objects based on VBIOS DCB table */
-   for (i = 0, dcbe = >entry[0]; i < dcb->entries; i++, dcbe++) {
+   for_each_set_bit(i, >disp->outp_mask, 
sizeof(disp->disp->outp_mask) * 8) {
struct nouveau_encoder *outp;
 
outp = kzalloc(sizeof(*outp), GFP_KERNEL);
if (!outp)
break;
 
-   ret = nvif_outp_ctor(disp->disp, "kmsOutp", dcbe->id, 
>outp);
+   ret = nvif_outp_ctor(disp->disp, "kmsOutp", i, >outp);
if (ret) {
kfree(outp);
   

[PATCH v3 41/44] drm/nouveau/kms/nv50-: name aux channels after their connector

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- removes use of VBIOS data for naming
- preparation for GSP-RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nouveau_connector.c | 25 -
 1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 063cefe26be20..73657736ce838 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -400,10 +400,8 @@ nouveau_connector_destroy(struct drm_connector *connector)
kfree(nv_connector->edid);
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
-   if (nv_connector->aux.transfer) {
+   if (nv_connector->aux.transfer)
drm_dp_cec_unregister_connector(_connector->aux);
-   kfree(nv_connector->aux.name);
-   }
nvif_conn_dtor(_connector->conn);
kfree(connector);
 }
@@ -1280,13 +1278,11 @@ struct drm_connector *
 nouveau_connector_create(struct drm_device *dev,
 const struct dcb_output *dcbe)
 {
-   const struct drm_connector_funcs *funcs = _connector_funcs;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_display *disp = nouveau_display(dev);
struct nouveau_connector *nv_connector = NULL;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
-   char aux_name[48] = {0};
int index = dcbe->connector;
int type, ret = 0;
bool dummy;
@@ -1376,7 +1372,13 @@ nouveau_connector_create(struct drm_device *dev,
}
}
 
-   switch ((type = drm_conntype_from_dcb(nv_connector->type))) {
+   type = drm_conntype_from_dcb(nv_connector->type);
+   if (type == DRM_MODE_CONNECTOR_LVDS)
+   drm_connector_init(dev, connector, 
_connector_funcs_lvds, type);
+   else
+   drm_connector_init(dev, connector, _connector_funcs, 
type);
+
+   switch (type) {
case DRM_MODE_CONNECTOR_LVDS:
ret = nouveau_bios_parse_lvds_table(dev, 0, , );
if (ret) {
@@ -1385,24 +1387,16 @@ nouveau_connector_create(struct drm_device *dev,
return ERR_PTR(ret);
}
 
-   funcs = _connector_funcs_lvds;
break;
case DRM_MODE_CONNECTOR_DisplayPort:
case DRM_MODE_CONNECTOR_eDP:
nv_connector->aux.dev = connector->kdev;
nv_connector->aux.drm_dev = dev;
nv_connector->aux.transfer = nouveau_connector_aux_xfer;
-   snprintf(aux_name, sizeof(aux_name), "sor-%04x-%04x",
-dcbe->hasht, dcbe->hashm);
-   nv_connector->aux.name = kstrdup(aux_name, GFP_KERNEL);
-   if (!nv_connector->aux.name) {
-   kfree(nv_connector);
-   return ERR_PTR(-ENOMEM);
-   }
+   nv_connector->aux.name = connector->name;
drm_dp_aux_init(_connector->aux);
break;
default:
-   funcs = _connector_funcs;
break;
}
 
@@ -1417,7 +1411,6 @@ nouveau_connector_create(struct drm_device *dev,
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
 
-   drm_connector_init(dev, connector, funcs, type);
drm_connector_helper_add(connector, _connector_helper_funcs);
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 
-- 
2.41.0



[PATCH v3 39/44] drm/nouveau/kms/nv50-: create heads based on nvkm head mask

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

No need to go poking HW directly, and probably shouldn't on GSP-RM.

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 18 +++---
 1 file changed, 3 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index d6de5ee89d543..2134502ec04e2 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -2692,13 +2692,12 @@ nv50_display_destroy(struct drm_device *dev)
 int
 nv50_display_create(struct drm_device *dev)
 {
-   struct nvif_device *device = _drm(dev)->client.device;
struct nouveau_drm *drm = nouveau_drm(dev);
struct dcb_table *dcb = >vbios.dcb;
struct drm_connector *connector, *tmp;
struct nv50_disp *disp;
struct dcb_output *dcbe;
-   int crtcs, ret, i;
+   int ret, i;
bool has_mst = nv50_has_mst(drm);
 
disp = kzalloc(sizeof(*disp), GFP_KERNEL);
@@ -2776,20 +2775,9 @@ nv50_display_create(struct drm_device *dev)
}
 
/* create crtc objects to represent the hw heads */
-   if (disp->disp->object.oclass >= GV100_DISP)
-   crtcs = nvif_rd32(>object, 0x610060) & 0xff;
-   else
-   if (disp->disp->object.oclass >= GF110_DISP)
-   crtcs = nvif_rd32(>object, 0x612004) & 0xf;
-   else
-   crtcs = 0x3;
-
-   for (i = 0; i < fls(crtcs); i++) {
+   for_each_set_bit(i, >disp->head_mask, 
sizeof(disp->disp->head_mask) * 8) {
struct nv50_head *head;
 
-   if (!(crtcs & (1 << i)))
-   continue;
-
head = nv50_head_create(dev, i);
if (IS_ERR(head)) {
ret = PTR_ERR(head);
@@ -2814,7 +2802,7 @@ nv50_display_create(struct drm_device *dev)
 * Once these issues are closed, this should be
 * removed
 */
-   head->msto->encoder.possible_crtcs = crtcs;
+   head->msto->encoder.possible_crtcs = 
disp->disp->head_mask;
}
}
 
-- 
2.41.0



[PATCH v3 38/44] drm/nouveau/disp/nv50-: skip DCB_OUTPUT_TV

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

We've never supported it.

Signed-off-by: Ben Skeggs 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
index 4be09ec4fd5c2..2d05e2f7e46b8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
@@ -1656,7 +1656,6 @@ nv50_disp_oneinit(struct nvkm_disp *disp)
 
switch (dcbE.type) {
case DCB_OUTPUT_ANALOG:
-   case DCB_OUTPUT_TV:
case DCB_OUTPUT_TMDS:
case DCB_OUTPUT_LVDS:
ret = nvkm_outp_new(disp, i, , );
@@ -1664,6 +1663,7 @@ nv50_disp_oneinit(struct nvkm_disp *disp)
case DCB_OUTPUT_DP:
ret = nvkm_dp_new(disp, i, , );
break;
+   case DCB_OUTPUT_TV:
case DCB_OUTPUT_WFD:
/* No support for WFD yet. */
ret = -ENODEV;
-- 
2.41.0



[PATCH v3 40/44] drm/nouveau/kms/nv50-: create heads after outps/conns

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- output info will be used later to determine MST support

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 64 -
 1 file changed, 32 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 2134502ec04e2..26d59346703e3 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -2774,38 +2774,6 @@ nv50_display_create(struct drm_device *dev)
dev->mode_config.cursor_height = 64;
}
 
-   /* create crtc objects to represent the hw heads */
-   for_each_set_bit(i, >disp->head_mask, 
sizeof(disp->disp->head_mask) * 8) {
-   struct nv50_head *head;
-
-   head = nv50_head_create(dev, i);
-   if (IS_ERR(head)) {
-   ret = PTR_ERR(head);
-   goto out;
-   }
-
-   if (has_mst) {
-   head->msto = nv50_msto_new(dev, head, i);
-   if (IS_ERR(head->msto)) {
-   ret = PTR_ERR(head->msto);
-   head->msto = NULL;
-   goto out;
-   }
-
-   /*
-* FIXME: This is a hack to workaround the following
-* issues:
-*
-* https://gitlab.gnome.org/GNOME/mutter/issues/759
-* 
https://gitlab.freedesktop.org/xorg/xserver/merge_requests/277
-*
-* Once these issues are closed, this should be
-* removed
-*/
-   head->msto->encoder.possible_crtcs = 
disp->disp->head_mask;
-   }
-   }
-
/* create encoder/connector objects based on VBIOS DCB table */
for (i = 0, dcbe = >entry[0]; i < dcb->entries; i++, dcbe++) {
struct nouveau_encoder *outp;
@@ -2868,6 +2836,38 @@ nv50_display_create(struct drm_device *dev)
connector->funcs->destroy(connector);
}
 
+   /* create crtc objects to represent the hw heads */
+   for_each_set_bit(i, >disp->head_mask, 
sizeof(disp->disp->head_mask) * 8) {
+   struct nv50_head *head;
+
+   head = nv50_head_create(dev, i);
+   if (IS_ERR(head)) {
+   ret = PTR_ERR(head);
+   goto out;
+   }
+
+   if (has_mst) {
+   head->msto = nv50_msto_new(dev, head, i);
+   if (IS_ERR(head->msto)) {
+   ret = PTR_ERR(head->msto);
+   head->msto = NULL;
+   goto out;
+   }
+
+   /*
+* FIXME: This is a hack to workaround the following
+* issues:
+*
+* https://gitlab.gnome.org/GNOME/mutter/issues/759
+* 
https://gitlab.freedesktop.org/xorg/xserver/merge_requests/277
+*
+* Once these issues are closed, this should be
+* removed
+*/
+   head->msto->encoder.possible_crtcs = 
disp->disp->head_mask;
+   }
+   }
+
/* Disable vblank irqs aggressively for power-saving, safe on nv50+ */
dev->vblank_disable_immediate = true;
 
-- 
2.41.0



[PATCH v3 37/44] drm/nouveau/disp: move outp init/fini paths to chipset code

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- pre-nv5x doesn't use any of this
- preparation for GSP-RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 .../gpu/drm/nouveau/nvkm/engine/disp/base.c   | 31 +++
 .../gpu/drm/nouveau/nvkm/engine/disp/conn.c   | 10 --
 .../gpu/drm/nouveau/nvkm/engine/disp/conn.h   |  2 --
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/nv50.c   | 14 +
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.c   | 20 ++--
 6 files changed, 22 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
index 1dbe68f9a0e07..39f7e7ce9f4a2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
@@ -102,18 +102,14 @@ static int
 nvkm_disp_fini(struct nvkm_engine *engine, bool suspend)
 {
struct nvkm_disp *disp = nvkm_disp(engine);
-   struct nvkm_conn *conn;
struct nvkm_outp *outp;
 
if (disp->func->fini)
disp->func->fini(disp);
 
list_for_each_entry(outp, >outps, head) {
-   nvkm_outp_fini(outp);
-   }
-
-   list_for_each_entry(conn, >conns, head) {
-   nvkm_conn_fini(conn);
+   if (outp->func->fini)
+   outp->func->fini(outp);
}
 
return 0;
@@ -123,16 +119,12 @@ static int
 nvkm_disp_init(struct nvkm_engine *engine)
 {
struct nvkm_disp *disp = nvkm_disp(engine);
-   struct nvkm_conn *conn;
struct nvkm_outp *outp;
struct nvkm_ior *ior;
 
-   list_for_each_entry(conn, >conns, head) {
-   nvkm_conn_init(conn);
-   }
-
list_for_each_entry(outp, >outps, head) {
-   nvkm_outp_init(outp);
+   if (outp->func->init)
+   outp->func->init(outp);
}
 
if (disp->func->init) {
@@ -156,9 +148,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine)
 {
struct nvkm_disp *disp = nvkm_disp(engine);
struct nvkm_subdev *subdev = >engine.subdev;
-   struct nvkm_outp *outp;
struct nvkm_head *head;
-   struct nvkm_ior *ior;
int ret, i;
 
if (disp->func->oneinit) {
@@ -167,19 +157,6 @@ nvkm_disp_oneinit(struct nvkm_engine *engine)
return ret;
}
 
-   /* Enforce identity-mapped SOR assignment for panels, which have
-* certain bits (ie. backlight controls) wired to a specific SOR.
-*/
-   list_for_each_entry(outp, >outps, head) {
-   if (outp->conn->info.type == DCB_CONNECTOR_LVDS ||
-   outp->conn->info.type == DCB_CONNECTOR_eDP) {
-   ior = nvkm_ior_find(disp, SOR, ffs(outp->info.or) - 1);
-   if (!WARN_ON(!ior))
-   ior->identity = true;
-   outp->identity = true;
-   }
-   }
-
i = 0;
list_for_each_entry(head, >heads, head)
i = max(i, head->id + 1);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c
index fbdae11378646..ff88a5a5253a7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c
@@ -29,16 +29,6 @@
 
 #include 
 
-void
-nvkm_conn_fini(struct nvkm_conn *conn)
-{
-}
-
-void
-nvkm_conn_init(struct nvkm_conn *conn)
-{
-}
-
 void
 nvkm_conn_del(struct nvkm_conn **pconn)
 {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h
index a0600e72b0ecd..01c3146c7066f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h
@@ -19,8 +19,6 @@ struct nvkm_conn {
 int nvkm_conn_new(struct nvkm_disp *, int index, struct nvbios_connE *,
  struct nvkm_conn **);
 void nvkm_conn_del(struct nvkm_conn **);
-void nvkm_conn_init(struct nvkm_conn *);
-void nvkm_conn_fini(struct nvkm_conn *);
 
 #define CONN_MSG(c,l,f,a...) do {  
\
struct nvkm_conn *_conn = (c);\
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
index aaa7796946ceb..b35fae96d855d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
@@ -603,6 +603,7 @@ nvkm_dp_fini(struct nvkm_outp *outp)
 static void
 nvkm_dp_init(struct nvkm_outp *outp)
 {
+   nvkm_outp_init(outp);
nvkm_dp_enable(outp, outp->dp.enabled);
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
index 7343b24f10eb7..4be09ec4fd5c2

[PATCH v3 36/44] drm/nouveau/disp: move outp/conn construction to chipset code

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- pre-nv5x doesn't use any of this, has its own version DRM-side
- preparation for GSP-RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 .../gpu/drm/nouveau/nvkm/engine/disp/base.c   | 117 +
 .../gpu/drm/nouveau/nvkm/engine/disp/nv50.c   | 122 +-
 2 files changed, 121 insertions(+), 118 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
index 73104b59f97fe..1dbe68f9a0e07 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
@@ -23,15 +23,12 @@
  */
 #include "priv.h"
 #include "conn.h"
-#include "dp.h"
 #include "head.h"
 #include "ior.h"
 #include "outp.h"
 
 #include 
 #include 
-#include 
-#include 
 
 #include 
 #include 
@@ -159,123 +156,11 @@ nvkm_disp_oneinit(struct nvkm_engine *engine)
 {
struct nvkm_disp *disp = nvkm_disp(engine);
struct nvkm_subdev *subdev = >engine.subdev;
-   struct nvkm_bios *bios = subdev->device->bios;
-   struct nvkm_outp *outp, *outt, *pair;
-   struct nvkm_conn *conn;
+   struct nvkm_outp *outp;
struct nvkm_head *head;
struct nvkm_ior *ior;
-   struct nvbios_connE connE;
-   struct dcb_output dcbE;
-   u8  hpd = 0, ver, hdr;
-   u32 data;
int ret, i;
 
-   /* Create output path objects for each VBIOS display path. */
-   i = -1;
-   while ((data = dcb_outp_parse(bios, ++i, , , ))) {
-   if (ver < 0x40) /* No support for chipsets prior to NV50. */
-   break;
-   if (dcbE.type == DCB_OUTPUT_UNUSED)
-   continue;
-   if (dcbE.type == DCB_OUTPUT_EOL)
-   break;
-   outp = NULL;
-
-   switch (dcbE.type) {
-   case DCB_OUTPUT_ANALOG:
-   case DCB_OUTPUT_TV:
-   case DCB_OUTPUT_TMDS:
-   case DCB_OUTPUT_LVDS:
-   ret = nvkm_outp_new(disp, i, , );
-   break;
-   case DCB_OUTPUT_DP:
-   ret = nvkm_dp_new(disp, i, , );
-   break;
-   case DCB_OUTPUT_WFD:
-   /* No support for WFD yet. */
-   ret = -ENODEV;
-   continue;
-   default:
-   nvkm_warn(subdev, "dcb %d type %d unknown\n",
- i, dcbE.type);
-   continue;
-   }
-
-   if (ret) {
-   if (outp) {
-   if (ret != -ENODEV)
-   OUTP_ERR(outp, "ctor failed: %d", ret);
-   else
-   OUTP_DBG(outp, "not supported");
-   nvkm_outp_del();
-   continue;
-   }
-   nvkm_error(subdev, "failed to create outp %d\n", i);
-   continue;
-   }
-
-   list_add_tail(>head, >outps);
-   hpd = max(hpd, (u8)(dcbE.connector + 1));
-   }
-
-   /* Create connector objects based on available output paths. */
-   list_for_each_entry_safe(outp, outt, >outps, head) {
-   /* VBIOS data *should* give us the most useful information. */
-   data = nvbios_connEp(bios, outp->info.connector, , ,
-);
-
-   /* No bios connector data... */
-   if (!data) {
-   /* Heuristic: anything with the same ccb index is
-* considered to be on the same connector, any
-* output path without an associated ccb entry will
-* be put on its own connector.
-*/
-   int ccb_index = outp->info.i2c_index;
-   if (ccb_index != 0xf) {
-   list_for_each_entry(pair, >outps, head) {
-   if (pair->info.i2c_index == ccb_index) {
-   outp->conn = pair->conn;
-   break;
-   }
-   }
-   }
-
-   /* Connector shared with another output path. */
-   if (outp->conn)
-   continue;
-
-   memset(, 0x00, sizeof(connE));
-   connE.type = DCB_CONNECTOR_NONE;
-   i = -1;
-   } else {

[PATCH v3 35/44] drm/nouveau/disp: add dp mst id get/put methods

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- preparation for GSP-RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 32 ---
 drivers/gpu/drm/nouveau/dispnv50/head.h   |  1 +
 drivers/gpu/drm/nouveau/dispnv50/headc57d.c   | 14 
 drivers/gpu/drm/nouveau/include/nvif/if0012.h | 18 +++
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |  2 ++
 drivers/gpu/drm/nouveau/nvif/outp.c   | 29 +
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 15 +
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.h   |  2 ++
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  | 28 
 9 files changed, 137 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index d8ed23ddd2e4c..d6de5ee89d543 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -869,6 +869,8 @@ struct nv50_msto {
struct nv50_mstc *mstc;
bool disabled;
bool enabled;
+
+   u32 display_id;
 };
 
 struct nouveau_encoder *nv50_real_outp(struct drm_encoder *encoder)
@@ -897,10 +899,17 @@ nv50_msto_cleanup(struct drm_atomic_state *state,
drm_atomic_get_old_mst_topology_state(state, mgr);
const struct drm_dp_mst_atomic_payload *old_payload =
drm_atomic_get_mst_payload_state(old_mst_state, 
msto->mstc->port);
+   struct nv50_mstc *mstc = msto->mstc;
+   struct nv50_mstm *mstm = mstc->mstm;
 
NV_ATOMIC(drm, "%s: msto cleanup\n", msto->encoder.name);
 
if (msto->disabled) {
+   if (msto->head->func->display_id) {
+   nvif_outp_dp_mst_id_put(>outp->outp, 
msto->display_id);
+   msto->display_id = 0;
+   }
+
msto->mstc = NULL;
msto->disabled = false;
drm_dp_remove_payload_part2(mgr, new_mst_state, old_payload, 
new_payload);
@@ -1041,6 +1050,11 @@ nv50_msto_atomic_enable(struct drm_encoder *encoder, 
struct drm_atomic_state *st
nouveau_dp_train(mstm->outp, true, 0, 0);
}
 
+   if (head->func->display_id) {
+   if (!WARN_ON(nvif_outp_dp_mst_id_get(>outp->outp, 
>display_id)))
+   head->func->display_id(head, msto->display_id);
+   }
+
if (mstm->outp->outp.or.link & 1)
proto = NV917D_SOR_SET_CONTROL_PROTOCOL_DP_A;
else
@@ -1061,6 +1075,9 @@ nv50_msto_atomic_disable(struct drm_encoder *encoder, 
struct drm_atomic_state *s
struct nv50_mstc *mstc = msto->mstc;
struct nv50_mstm *mstm = mstc->mstm;
 
+   if (msto->head->func->display_id)
+   msto->head->func->display_id(msto->head, 0);
+
mstm->outp->update(mstm->outp, msto->head->base.index, NULL, 0, 0);
mstm->modified = true;
if (!--mstm->links)
@@ -1544,7 +1561,7 @@ static void
 nv50_sor_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state 
*state)
 {
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-   struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc);
+   struct nv50_head *head = nv50_head(nv_encoder->crtc);
struct nouveau_connector *nv_connector = 
nv50_outp_get_old_connector(state, nv_encoder);
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
@@ -1563,7 +1580,7 @@ nv50_sor_atomic_disable(struct drm_encoder *encoder, 
struct drm_atomic_state *st
 #endif
 
if (nv_encoder->dcb->type == DCB_OUTPUT_TMDS && 
nv_encoder->hdmi.enabled) {
-   nvif_outp_hdmi(_encoder->outp, nv_crtc->index,
+   nvif_outp_hdmi(_encoder->outp, head->base.index,
   false, 0, 0, 0, false, false, false);
nv_encoder->hdmi.enabled = false;
}
@@ -1571,8 +1588,11 @@ nv50_sor_atomic_disable(struct drm_encoder *encoder, 
struct drm_atomic_state *st
if (nv_encoder->dcb->type == DCB_OUTPUT_DP)
nouveau_dp_power_down(nv_encoder);
 
-   nv_encoder->update(nv_encoder, nv_crtc->index, NULL, 0, 0);
-   nv50_audio_disable(encoder, nv_crtc);
+   if (head->func->display_id)
+   head->func->display_id(head, 0);
+
+   nv_encoder->update(nv_encoder, head->base.index, NULL, 0, 0);
+   nv50_audio_disable(encoder, >base);
nv_encoder->crtc = NULL;
 }
 
@@ -1585,6 +1605,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, 
struct drm_atomic_state *sta
nv50_head_atom(drm_atomic_get_new_crtc_state(state, 
_crtc->base));
struct drm_display_mode *mod

[PATCH v3 34/44] drm/nouveau/disp: add dp sst config method

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

This is presently unused on HW, we read a bunch of regs and calculate
the watermark during the second supervisor interrupt.

I don't want to change this yet as I need to re-remember how older HW
works exactly, but RM wants this info via RPC.

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/include/nvif/if0012.h | 12 +++
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |  1 +
 drivers/gpu/drm/nouveau/nvif/outp.c   | 18 
 .../gpu/drm/nouveau/nvkm/engine/disp/ior.h|  2 ++
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  | 21 +++
 5 files changed, 54 insertions(+)

diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index 00ce0a46c152b..6fb297b65ae87 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -36,6 +36,7 @@ union nvif_outp_args {
 #define NVIF_OUTP_V0_DP_RATES  0x72
 #define NVIF_OUTP_V0_DP_TRAIN  0x73
 #define NVIF_OUTP_V0_DP_DRIVE  0x74
+#define NVIF_OUTP_V0_DP_SST0x75
 #define NVIF_OUTP_V0_DP_MST_VCPI   0x78
 
 union nvif_outp_detect_args {
@@ -222,6 +223,17 @@ union nvif_outp_dp_drive_args {
} v0;
 };
 
+union nvif_outp_dp_sst_args {
+   struct nvif_outp_dp_sst_v0 {
+   __u8  version;
+   __u8  head;
+   __u8  pad02[2];
+   __u32 watermark;
+   __u32 hblanksym;
+   __u32 vblanksym;
+   } v0;
+};
+
 union nvif_outp_dp_mst_vcpi_args {
struct nvif_outp_dp_mst_vcpi_v0 {
__u8  version;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h 
b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index b4f97fabecbdc..881cbed5f0ee3 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -68,6 +68,7 @@ int nvif_outp_dp_train(struct nvif_outp *, u8 
dpcd[DP_RECEIVER_CAP_SIZE],
   u8 lttprs, u8 link_nr, u32 link_bw, bool mst, bool 
post_lt_adj,
   bool retrain);
 int nvif_outp_dp_drive(struct nvif_outp *, u8 link_nr, u8 pe[4], u8 vs[4]);
+int nvif_outp_dp_sst(struct nvif_outp *, int head, u32 watermark, u32 
hblanksym, u32 vblanksym);
 int nvif_outp_dp_mst_vcpi(struct nvif_outp *, int head,
  u8 start_slot, u8 num_slots, u16 pbn, u16 
aligned_pbn);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c 
b/drivers/gpu/drm/nouveau/nvif/outp.c
index 5fe5523587e6a..952103aa93b78 100644
--- a/drivers/gpu/drm/nouveau/nvif/outp.c
+++ b/drivers/gpu/drm/nouveau/nvif/outp.c
@@ -46,6 +46,24 @@ nvif_outp_dp_mst_vcpi(struct nvif_outp *outp, int head,
return ret;
 }
 
+int
+nvif_outp_dp_sst(struct nvif_outp *outp, int head, u32 watermark, u32 
hblanksym, u32 vblanksym)
+{
+   struct nvif_outp_dp_sst_v0 args;
+   int ret;
+
+   args.version = 0;
+   args.head = head;
+   args.watermark = watermark;
+   args.hblanksym = hblanksym;
+   args.vblanksym = vblanksym;
+   ret = nvif_object_mthd(>object, NVIF_OUTP_V0_DP_SST, , 
sizeof(args));
+   NVIF_ERRON(ret, >object,
+  "[DP_SST head:%d watermark:%d hblanksym:%d vblanksym:%d]",
+  args.head, args.watermark, args.hblanksym, args.vblanksym);
+   return ret;
+}
+
 int
 nvif_outp_dp_drive(struct nvif_outp *outp, u8 link_nr, u8 pe[4], u8 vs[4])
 {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
index 8686e5c044a5d..9beb9d1e86334 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
@@ -84,6 +84,8 @@ struct nvkm_ior_func {
void (*pattern)(struct nvkm_ior *, int pattern);
void (*drive)(struct nvkm_ior *, int ln, int pc,
  int dc, int pe, int tx_pu);
+   int (*sst)(struct nvkm_ior *, int head, bool ef,
+  u32 watermark, u32 hblanksym, u32 vblanksym);
void (*vcpi)(struct nvkm_ior *, int head, u8 slot,
 u8 slot_nr, u16 pbn, u16 aligned);
void (*audio)(struct nvkm_ior *, int head, bool enable);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index b634e76c2a9ba..225f88fbdae0f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -45,6 +45,26 @@ nvkm_uoutp_mthd_dp_mst_vcpi(struct nvkm_outp *outp, void 
*argv, u32 argc)
return 0;
 }
 
+static int
+nvkm_uoutp_mthd_dp_sst(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+   union nvif_outp_dp_sst_args *args = argv;
+   struct nvkm_disp *disp = outp->disp;
+   struct nvkm_ior *ior = outp->ior;
+
+   if (a

[PATCH v3 29/44] drm/nouveau/kms/nv50-: split DP disable+enable into two modesets

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

Link training can finally be moved out of the supervisor sequence,
but first we need to split DP modesets into separate disable and
enable sequences to be able to perform link training between them
instead.

- preparation for GSP-RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index ee53bc5d10042..48e099ed7d51c 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -2375,7 +2375,8 @@ nv50_disp_outp_atomic_check_clr(struct nv50_atom *atom,
if (IS_ERR(outp))
return PTR_ERR(outp);
 
-   if (outp->encoder->encoder_type == DRM_MODE_ENCODER_DPMST) {
+   if (outp->encoder->encoder_type == DRM_MODE_ENCODER_DPMST ||
+   nouveau_encoder(outp->encoder)->dcb->type == DCB_OUTPUT_DP) 
{
outp->flush_disable = true;
atom->flush_disable = true;
}
-- 
2.41.0



[PATCH v3 33/44] drm/nouveau/disp: move link training out of supervisor

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- preparation for GSP-RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/include/nvif/if0012.h |  11 ++
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |   1 +
 drivers/gpu/drm/nouveau/nouveau_dp.c  | 122 ++-
 drivers/gpu/drm/nouveau/nvif/outp.c   |  16 ++
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 148 +-
 .../gpu/drm/nouveau/nvkm/engine/disp/nv50.c   |  13 --
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.c   |  18 ++-
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.h   |   8 +-
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  |  27 +++-
 9 files changed, 218 insertions(+), 146 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index 14972b942be7e..00ce0a46c152b 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -35,6 +35,7 @@ union nvif_outp_args {
 #define NVIF_OUTP_V0_DP_AUX_XFER   0x71
 #define NVIF_OUTP_V0_DP_RATES  0x72
 #define NVIF_OUTP_V0_DP_TRAIN  0x73
+#define NVIF_OUTP_V0_DP_DRIVE  0x74
 #define NVIF_OUTP_V0_DP_MST_VCPI   0x78
 
 union nvif_outp_detect_args {
@@ -211,6 +212,16 @@ union nvif_outp_dp_train_args {
} v0;
 };
 
+union nvif_outp_dp_drive_args {
+   struct nvif_outp_dp_drive_v0 {
+   __u8  version;
+   __u8  pad01[2];
+   __u8  lanes;
+   __u8  pe[4];
+   __u8  vs[4];
+   } v0;
+};
+
 union nvif_outp_dp_mst_vcpi_args {
struct nvif_outp_dp_mst_vcpi_v0 {
__u8  version;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h 
b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index 9a78483e0289d..b4f97fabecbdc 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -67,6 +67,7 @@ int nvif_outp_dp_rates(struct nvif_outp *, struct 
nvif_outp_dp_rate *rate, int r
 int nvif_outp_dp_train(struct nvif_outp *, u8 dpcd[DP_RECEIVER_CAP_SIZE],
   u8 lttprs, u8 link_nr, u32 link_bw, bool mst, bool 
post_lt_adj,
   bool retrain);
+int nvif_outp_dp_drive(struct nvif_outp *, u8 link_nr, u8 pe[4], u8 vs[4]);
 int nvif_outp_dp_mst_vcpi(struct nvif_outp *, int head,
  u8 start_slot, u8 num_slots, u16 pbn, u16 
aligned_pbn);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 9280daf325341..7de7707ec6a89 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -320,15 +320,83 @@ nouveau_dp_power_down(struct nouveau_encoder *outp)
 static bool
 nouveau_dp_train_link(struct nouveau_encoder *outp, bool retrain)
 {
-   int ret;
+   struct drm_dp_aux *aux = >conn->aux;
+   bool post_lt = false;
+   int ret, retries = 0;
+
+   if ( (outp->dp.dpcd[DP_MAX_LANE_COUNT] & 0x20) &&
+   !(outp->dp.dpcd[DP_MAX_DOWNSPREAD] & DP_TPS4_SUPPORTED))
+   post_lt = true;
 
+retry:
ret = nvif_outp_dp_train(>outp, outp->dp.dpcd,
  outp->dp.lttpr.nr,
  outp->dp.lt.nr,
  outp->dp.lt.bw,
  outp->dp.lt.mst,
- false,
+ post_lt,
  retrain);
+   if (ret)
+   return false;
+
+   if (post_lt) {
+   u8 stat[DP_LINK_STATUS_SIZE];
+   u8 prev[2];
+   u8 time = 0, adjusts = 0, tmp;
+
+   ret = drm_dp_dpcd_read_phy_link_status(aux, DP_PHY_DPRX, stat);
+   if (ret)
+   return false;
+
+   for (;;) {
+   if (!drm_dp_channel_eq_ok(stat, outp->dp.lt.nr)) {
+   ret = 1;
+   break;
+   }
+
+   if (!(stat[2] & 0x02))
+   break;
+
+   msleep(5);
+   time += 5;
+
+   memcpy(prev, [4], sizeof(prev));
+   ret = drm_dp_dpcd_read_phy_link_status(aux, 
DP_PHY_DPRX, stat);
+   if (ret)
+   break;
+
+   if (!memcmp(prev, [4], sizeof(prev))) {
+   if (time > 200)
+   break;
+   } else {
+   u8 pe[4], vs[4];
+
+   if (adjusts++ == 6)
+   break;
+
+

[PATCH v3 32/44] drm/nouveau/disp: add dp train method

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- passes DPCD information from DRM to NVKM
- removes NVKM's own sink caps handling
- link still trained from supervisor, more patches to come

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c   |   6 +-
 drivers/gpu/drm/nouveau/include/nvif/if0012.h |  25 ++--
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |   7 +-
 drivers/gpu/drm/nouveau/nouveau_dp.c  |  75 +--
 drivers/gpu/drm/nouveau/nouveau_encoder.h |   7 ++
 drivers/gpu/drm/nouveau/nvif/outp.c   |  38 +++---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 118 +++---
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.h   |   2 +
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  |  41 +++---
 9 files changed, 143 insertions(+), 176 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 1ea4b113058cd..d8ed23ddd2e4c 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1038,7 +1038,7 @@ nv50_msto_atomic_enable(struct drm_encoder *encoder, 
struct drm_atomic_state *st
 
if (!mstm->links++) {
nvif_outp_acquire_sor(>outp->outp, false /*TODO: MST 
audio... */);
-   nvif_outp_acquire_dp(>outp->outp, mstm->outp->dp.dpcd, 0, 
0, false, true);
+   nouveau_dp_train(mstm->outp, true, 0, 0);
}
 
if (mstm->outp->outp.or.link & 1)
@@ -1661,7 +1661,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, 
struct drm_atomic_state *sta
nvif_outp_lvds(_encoder->outp, lvds_dual, lvds_8bpc);
break;
case DCB_OUTPUT_DP:
-   nvif_outp_acquire_dp(_encoder->outp, nv_encoder->dp.dpcd, 0, 
0, hda, false);
+   nouveau_dp_train(nv_encoder, false, mode->clock, asyh->or.bpc);
depth = nv50_dp_bpc_to_depth(asyh->or.bpc);
 
if (nv_encoder->outp.or.link & 1)
@@ -1852,7 +1852,7 @@ nv50_pior_atomic_enable(struct drm_encoder *encoder, 
struct drm_atomic_state *st
break;
case DCB_OUTPUT_DP:
ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC);
-   nvif_outp_acquire_dp(_encoder->outp, nv_encoder->dp.dpcd, 0, 
0, false, false);
+   nouveau_dp_train(nv_encoder, false, 
asyh->state.adjusted_mode.clock, 6);
break;
default:
BUG();
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index ddc8e3d858235..14972b942be7e 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -34,7 +34,7 @@ union nvif_outp_args {
 #define NVIF_OUTP_V0_DP_AUX_PWR0x70
 #define NVIF_OUTP_V0_DP_AUX_XFER   0x71
 #define NVIF_OUTP_V0_DP_RATES  0x72
-#define NVIF_OUTP_V0_DP_RETRAIN0x73
+#define NVIF_OUTP_V0_DP_TRAIN  0x73
 #define NVIF_OUTP_V0_DP_MST_VCPI   0x78
 
 union nvif_outp_detect_args {
@@ -71,7 +71,6 @@ union nvif_outp_acquire_args {
 #define NVIF_OUTP_ACQUIRE_V0_DAC  0x00
 #define NVIF_OUTP_ACQUIRE_V0_SOR  0x01
 #define NVIF_OUTP_ACQUIRE_V0_PIOR 0x02
-#define NVIF_OUTP_ACQUIRE_V0_DP  0x04
__u8 type;
__u8 or;
__u8 link;
@@ -80,14 +79,6 @@ union nvif_outp_acquire_args {
struct {
__u8 hda;
} sor;
-   struct {
-   __u8 link_nr; /* 0 = highest possible. */
-   __u8 link_bw; /* 0 = highest possible, DP BW 
code otherwise. */
-   __u8 hda;
-   __u8 mst;
-   __u8 pad04[4];
-   __u8 dpcd[DP_RECEIVER_CAP_SIZE];
-   } dp;
};
} v0;
 };
@@ -207,9 +198,17 @@ union nvif_outp_dp_rates_args {
} v0;
 };
 
-union nvif_outp_dp_retrain_args {
-   struct nvif_outp_dp_retrain_vn {
-   } vn;
+union nvif_outp_dp_train_args {
+   struct nvif_outp_dp_train_v0 {
+   __u8  version;
+   __u8  retrain;
+   __u8  mst;
+   __u8  lttprs;
+   __u8  post_lt_adj;
+   __u8  link_nr;
+   __u32 link_bw;
+   __u8 dpcd[DP_RECEIVER_CAP_SIZE];
+   } v0;
 };
 
 union nvif_outp_dp_mst_vcpi_args {
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h 
b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index 596d543acd302..9a78483e0289d 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -31,8 +31,6 @@ int nvif_outp_load_detect(struct nvif_outp *, u32 loadval);
 int nvif_outp_acquire_dac(struct nvif_out

[PATCH v3 31/44] drm/nouveau/kms/nv50-: fixup sink D3 before tearing down link

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- fixes bug preventing this on SST
- implement for MST

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 13 +++--
 drivers/gpu/drm/nouveau/nouveau_dp.c  | 15 +++
 drivers/gpu/drm/nouveau/nouveau_encoder.h |  1 +
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 1fcd1b36a2751..1ea4b113058cd 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1300,6 +1300,7 @@ nv50_mstm_cleanup(struct drm_atomic_state *state,
}
 
if (mstm->disabled) {
+   nouveau_dp_power_down(mstm->outp);
nvif_outp_release(>outp->outp);
mstm->disabled = false;
}
@@ -1551,7 +1552,6 @@ nv50_sor_atomic_disable(struct drm_encoder *encoder, 
struct drm_atomic_state *st
 #endif
struct drm_dp_aux *aux = _connector->aux;
int ret;
-   u8 pwr;
 
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
if (backlight && backlight->uses_dpcd) {
@@ -1568,15 +1568,8 @@ nv50_sor_atomic_disable(struct drm_encoder *encoder, 
struct drm_atomic_state *st
nv_encoder->hdmi.enabled = false;
}
 
-   if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
-   ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, );
-
-   if (ret == 0) {
-   pwr &= ~DP_SET_POWER_MASK;
-   pwr |=  DP_SET_POWER_D3;
-   drm_dp_dpcd_writeb(aux, DP_SET_POWER, pwr);
-   }
-   }
+   if (nv_encoder->dcb->type == DCB_OUTPUT_DP)
+   nouveau_dp_power_down(nv_encoder);
 
nv_encoder->update(nv_encoder, nv_crtc->index, NULL, 0, 0);
nv50_audio_disable(encoder, nv_crtc);
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index f26769bca1950..1c0b992fe2416 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -284,6 +284,21 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
return ret;
 }
 
+void
+nouveau_dp_power_down(struct nouveau_encoder *outp)
+{
+   struct drm_dp_aux *aux = >conn->aux;
+   int ret;
+   u8 pwr;
+
+   ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, );
+   if (ret == 1) {
+   pwr &= ~DP_SET_POWER_MASK;
+   pwr |=  DP_SET_POWER_D3;
+   drm_dp_dpcd_writeb(aux, DP_SET_POWER, pwr);
+   }
+}
+
 bool
 nouveau_dp_link_check(struct nouveau_connector *nv_connector)
 {
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h 
b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index 123d0ecf5f586..ed31db58176c3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -155,6 +155,7 @@ enum nouveau_dp_status {
 };
 
 int nouveau_dp_detect(struct nouveau_connector *, struct nouveau_encoder *);
+void nouveau_dp_power_down(struct nouveau_encoder *);
 bool nouveau_dp_link_check(struct nouveau_connector *);
 void nouveau_dp_irq(struct work_struct *);
 enum drm_mode_status nv50_dp_mode_valid(struct nouveau_encoder *,
-- 
2.41.0



[PATCH v3 30/44] drm/nouveau/kms/nv50-: flush mst disables together

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- fixes some issues tearing down modes on tiled displays

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 11 +--
 drivers/gpu/drm/nouveau/dispnv50/disp.h |  1 -
 2 files changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 48e099ed7d51c..1fcd1b36a2751 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -2084,13 +2084,6 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state 
*state)
help->atomic_disable(encoder, state);
outp->disabled = true;
interlock[NV50_DISP_INTERLOCK_CORE] |= 1;
-   if (outp->flush_disable) {
-   nv50_disp_atomic_commit_wndw(state, interlock);
-   nv50_disp_atomic_commit_core(state, interlock);
-   memset(interlock, 0x00, sizeof(interlock));
-
-   flushed = true;
-   }
}
}
 
@@ -2376,10 +2369,8 @@ nv50_disp_outp_atomic_check_clr(struct nv50_atom *atom,
return PTR_ERR(outp);
 
if (outp->encoder->encoder_type == DRM_MODE_ENCODER_DPMST ||
-   nouveau_encoder(outp->encoder)->dcb->type == DCB_OUTPUT_DP) 
{
-   outp->flush_disable = true;
+   nouveau_encoder(outp->encoder)->dcb->type == DCB_OUTPUT_DP)
atom->flush_disable = true;
-   }
outp->clr.ctrl = true;
atom->lock_core = true;
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.h 
b/drivers/gpu/drm/nouveau/dispnv50/disp.h
index 42209f5b06f91..1e5601223c753 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.h
@@ -83,7 +83,6 @@ struct nv50_outp_atom {
struct list_head head;
 
struct drm_encoder *encoder;
-   bool flush_disable;
 
bool disabled;
bool enabled;
-- 
2.41.0



[PATCH v3 28/44] drm/nouveau/disp: add dp rates method

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- moves building of link rates table from NVKM to DRM
- preparing to move link training out of supervisor

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/include/nvif/if0012.h |  13 ++
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |   8 +
 drivers/gpu/drm/nouveau/nouveau_dp.c  | 143 ++
 drivers/gpu/drm/nouveau/nouveau_encoder.h |  12 +-
 drivers/gpu/drm/nouveau/nvif/outp.c   |  21 +++
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c |  66 
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.h   |   1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  |  24 +++
 8 files changed, 189 insertions(+), 99 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index 94f1e55b0ce6c..ddc8e3d858235 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -33,6 +33,7 @@ union nvif_outp_args {
 
 #define NVIF_OUTP_V0_DP_AUX_PWR0x70
 #define NVIF_OUTP_V0_DP_AUX_XFER   0x71
+#define NVIF_OUTP_V0_DP_RATES  0x72
 #define NVIF_OUTP_V0_DP_RETRAIN0x73
 #define NVIF_OUTP_V0_DP_MST_VCPI   0x78
 
@@ -194,6 +195,18 @@ union nvif_outp_dp_aux_xfer_args {
} v0;
 };
 
+union nvif_outp_dp_rates_args {
+   struct nvif_outp_dp_rates_v0 {
+   __u8  version;
+   __u8  pad01[6];
+   __u8  rates;
+   struct {
+   __s8  dpcd;
+   __u32 rate;
+   } rate[8];
+   } v0;
+};
+
 union nvif_outp_dp_retrain_args {
struct nvif_outp_dp_retrain_vn {
} vn;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h 
b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index dd4dd0e2a7a1d..596d543acd302 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -59,6 +59,14 @@ int nvif_outp_hda_eld(struct nvif_outp *, int head, void 
*data, u32 size);
 
 int nvif_outp_dp_aux_pwr(struct nvif_outp *, bool enable);
 int nvif_outp_dp_aux_xfer(struct nvif_outp *, u8 type, u8 *size, u32 addr, u8 
*data);
+
+struct nvif_outp_dp_rate {
+   int dpcd; /* -1 for non-indexed rates */
+   u32 rate;
+};
+
+int nvif_outp_dp_rates(struct nvif_outp *, struct nvif_outp_dp_rate *rate, int 
rate_nr);
+
 int nvif_outp_dp_retrain(struct nvif_outp *);
 int nvif_outp_dp_mst_vcpi(struct nvif_outp *, int head,
  u8 start_slot, u8 num_slots, u16 pbn, u16 
aligned_pbn);
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 01aa9b9c74a2a..f26769bca1950 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -42,6 +42,21 @@ nouveau_dp_has_sink_count(struct drm_connector *connector,
return drm_dp_read_sink_count_cap(connector, outp->dp.dpcd, 
>dp.desc);
 }
 
+static bool
+nouveau_dp_probe_lttpr(struct nouveau_encoder *outp)
+{
+   u8 rev, size = sizeof(rev);
+   int ret;
+
+   ret = nvif_outp_dp_aux_xfer(>outp, DP_AUX_NATIVE_READ, ,
+   
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
+   );
+   if (ret || size < sizeof(rev) || rev < 0x14)
+   return false;
+
+   return true;
+}
+
 static enum drm_connector_status
 nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector,
  struct nouveau_encoder *outp)
@@ -53,10 +68,99 @@ nouveau_dp_probe_dpcd(struct nouveau_connector 
*nv_connector,
int ret;
u8 *dpcd = outp->dp.dpcd;
 
+   outp->dp.lttpr.nr = 0;
+   outp->dp.rate_nr  = 0;
+   outp->dp.link_nr  = 0;
+   outp->dp.link_bw  = 0;
+
+   if (connector->connector_type != DRM_MODE_CONNECTOR_eDP &&
+   nouveau_dp_probe_lttpr(outp) &&
+   !drm_dp_read_dpcd_caps(aux, dpcd) &&
+   !drm_dp_read_lttpr_common_caps(aux, dpcd, outp->dp.lttpr.caps)) {
+   int nr = drm_dp_lttpr_count(outp->dp.lttpr.caps);
+
+   if (nr > 0)
+   outp->dp.lttpr.nr = nr;
+   }
+
ret = drm_dp_read_dpcd_caps(aux, dpcd);
if (ret < 0)
goto out;
 
+   outp->dp.link_nr = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
+   if (outp->dcb->dpconf.link_nr < outp->dp.link_nr)
+   outp->dp.link_nr = outp->dcb->dpconf.link_nr;
+
+   if (outp->dp.lttpr.nr) {
+   int links = drm_dp_lttpr_max_lane_count(outp->dp.lttpr.caps);
+
+   if (links && links < outp->dp.link_nr)
+   outp->dp.link_nr = links;
+   }
+
+   if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && 
dpcd[DP_DPCD_REV] >= 0x13) {
+   

[PATCH v3 27/44] drm/nouveau/disp: add dp aux xfer method

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- preparation for GSP-RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 32 +--
 drivers/gpu/drm/nouveau/include/nvif/if0012.h | 12 +++
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |  2 ++
 drivers/gpu/drm/nouveau/nouveau_connector.c   | 12 ++-
 drivers/gpu/drm/nouveau/nouveau_encoder.h |  1 -
 drivers/gpu/drm/nouveau/nvif/outp.c   | 24 ++
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 14 
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.h   |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  | 27 +---
 9 files changed, 94 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 11b11284a3218..ee53bc5d10042 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1704,14 +1704,13 @@ nv50_sor_destroy(struct drm_encoder *encoder)
 {
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 
-   nvif_outp_dtor(_encoder->outp);
-
nv50_mstm_del(_encoder->dp.mstm);
drm_encoder_cleanup(encoder);
 
if (nv_encoder->dcb->type == DCB_OUTPUT_DP)
mutex_destroy(_encoder->dp.hpd_irq_lock);
 
+   nvif_outp_dtor(_encoder->outp);
kfree(encoder);
 }
 
@@ -1764,22 +1763,22 @@ nv50_sor_create(struct nouveau_encoder *nv_encoder)
nv50_outp_dump_caps(drm, nv_encoder);
 
if (dcbe->type == DCB_OUTPUT_DP) {
-   struct nvkm_i2c_aux *aux =
-   nvkm_i2c_aux_find(i2c, dcbe->i2c_index);
-
mutex_init(_encoder->dp.hpd_irq_lock);
 
-   if (aux) {
-   if (disp->disp->object.oclass < GF110_DISP) {
-   /* HW has no support for address-only
-* transactions, so we're required to
-* use custom I2C-over-AUX code.
-*/
-   nv_encoder->i2c = >i2c;
-   } else {
-   nv_encoder->i2c = _connector->aux.ddc;
-   }
-   nv_encoder->aux = aux;
+   if (disp->disp->object.oclass < GF110_DISP) {
+   /* HW has no support for address-only
+* transactions, so we're required to
+* use custom I2C-over-AUX code.
+*/
+   struct nvkm_i2c_aux *aux;
+
+   aux = nvkm_i2c_aux_find(i2c, dcbe->i2c_index);
+   if (!aux)
+   return -EINVAL;
+
+   nv_encoder->i2c = >i2c;
+   } else {
+   nv_encoder->i2c = _connector->aux.ddc;
}
 
if (nv_connector->type != DCB_CONNECTOR_eDP &&
@@ -1925,7 +1924,6 @@ nv50_pior_create(struct nouveau_encoder *nv_encoder)
}
 
nv_encoder->i2c = ddc;
-   nv_encoder->aux = aux;
 
encoder = to_drm_encoder(nv_encoder);
drm_encoder_init(connector->dev, encoder, _pior_func, type,
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index ee4cec541a90e..94f1e55b0ce6c 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -32,6 +32,7 @@ union nvif_outp_args {
 #define NVIF_OUTP_V0_HDA_ELD   0x61
 
 #define NVIF_OUTP_V0_DP_AUX_PWR0x70
+#define NVIF_OUTP_V0_DP_AUX_XFER   0x71
 #define NVIF_OUTP_V0_DP_RETRAIN0x73
 #define NVIF_OUTP_V0_DP_MST_VCPI   0x78
 
@@ -182,6 +183,17 @@ union nvif_outp_dp_aux_pwr_args {
} v0;
 };
 
+union nvif_outp_dp_aux_xfer_args {
+   struct nvif_outp_dp_aux_xfer_v0 {
+   __u8  version;
+   __u8  pad01;
+   __u8  type;
+   __u8  size;
+   __u32 addr;
+   __u8  data[16];
+   } v0;
+};
+
 union nvif_outp_dp_retrain_args {
struct nvif_outp_dp_retrain_vn {
} vn;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h 
b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index 0ddaec9416eed..dd4dd0e2a7a1d 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -56,7 +56,9 @@ int nvif_outp_hdmi(struct nvif_outp *, int head, bool enable, 
u8 max_ac_packet,
 
 int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct 
nvif_outp_infoframe_v0 *, u32 size);
 int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size);
+
 int nvif_outp_dp_aux_pwr(struct nvif_outp *, bool enable);
+int nvif_outp_dp_aux_xfer(struct nvif_outp *, u8 type, u8 *size, 

[PATCH v3 26/44] drm/nouveau/disp: move dp aux pwr method to HAL

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- preparation for GSP-RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c| 9 +
 drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h  | 4 
 drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 6 +++---
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
index 0e6e388003765..99fe7ef07a443 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
@@ -41,6 +41,14 @@
  */
 #define AMPERE_IED_HACK(disp) ((disp)->engine.subdev.device->card_type >= 
GA100)
 
+static int
+nvkm_dp_aux_pwr(struct nvkm_outp *outp, bool pu)
+{
+   outp->dp.enabled = pu;
+   nvkm_dp_enable(outp, outp->dp.enabled);
+   return 0;
+}
+
 struct lt_state {
struct nvkm_outp *outp;
 
@@ -814,6 +822,7 @@ nvkm_dp_func = {
.disable = nvkm_dp_disable,
.bl.get = nvkm_outp_bl_get,
.bl.set = nvkm_outp_bl_set,
+   .dp.aux_pwr = nvkm_dp_aux_pwr,
 };
 
 int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
index 38b6b43a9f200..513794a278a91 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
@@ -104,6 +104,10 @@ struct nvkm_outp_func {
int (*get)(struct nvkm_outp *);
int (*set)(struct nvkm_outp *, int level);
} bl;
+
+   struct {
+   int (*aux_pwr)(struct nvkm_outp *, bool pu);
+   } dp;
 };
 
 #define OUTP_MSG(o,l,f,a...) do {  
\
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index 7574f22006441..6ca364e953bd7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -75,10 +75,10 @@ nvkm_uoutp_mthd_dp_aux_pwr(struct nvkm_outp *outp, void 
*argv, u32 argc)
 
if (argc != sizeof(args->v0) || args->v0.version != 0)
return -ENOSYS;
+   if (!outp->func->dp.aux_pwr)
+   return -EINVAL;
 
-   outp->dp.enabled = !!args->v0.state;
-   nvkm_dp_enable(outp, outp->dp.enabled);
-   return 0;
+   return outp->func->dp.aux_pwr(outp, !!args->v0.state);
 }
 
 static int
-- 
2.41.0



[PATCH v3 25/44] drm/nouveau/disp: add hdmi audio hal function

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

This just adds a hook for RM to use, HW paths remain untouched, but
should probably be cleaned up to use this too at some point.

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h   |  1 +
 drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 10 +-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
index 6e750890bcc93..8686e5c044a5d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
@@ -74,6 +74,7 @@ struct nvkm_ior_func {
 bool scrambling_low_rates);
void (*infoframe_avi)(struct nvkm_ior *, int head, void *data, 
u32 size);
void (*infoframe_vsi)(struct nvkm_ior *, int head, void *data, 
u32 size);
+   void (*audio)(struct nvkm_ior *, int head, bool enable);
} *hdmi;
 
const struct nvkm_ior_func_dp {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index ad75dc5c50cf7..7574f22006441 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -99,12 +99,20 @@ nvkm_uoutp_mthd_hda_eld(struct nvkm_outp *outp, void *argv, 
u32 argc)
if (argc && args->v0.data[0]) {
if (outp->info.type == DCB_OUTPUT_DP)
ior->func->dp->audio(ior, args->v0.head, true);
+   else
+   if (ior->func->hdmi->audio)
+   ior->func->hdmi->audio(ior, args->v0.head, true);
+
ior->func->hda->hpd(ior, args->v0.head, true);
ior->func->hda->eld(ior, args->v0.head, args->v0.data, argc);
} else {
+   ior->func->hda->hpd(ior, args->v0.head, false);
+
if (outp->info.type == DCB_OUTPUT_DP)
ior->func->dp->audio(ior, args->v0.head, false);
-   ior->func->hda->hpd(ior, args->v0.head, false);
+   else
+   if (ior->func->hdmi->audio)
+   ior->func->hdmi->audio(ior, args->v0.head, false);
}
 
return 0;
-- 
2.41.0



[PATCH v3 24/44] drm/nouveau/disp: add output lvds config method

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- was previously part of acquire()

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c  |  2 +-
 drivers/gpu/drm/nouveau/include/nvif/if0012.h| 16 ++--
 drivers/gpu/drm/nouveau/include/nvif/outp.h  |  3 ++-
 drivers/gpu/drm/nouveau/nvif/outp.c  | 15 +++
 drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 14 --
 5 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 50a0ff304291e..11b11284a3218 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1665,7 +1665,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, 
struct drm_atomic_state *sta
lvds_8bpc = true;
}
 
-   nvif_outp_acquire_lvds(_encoder->outp, lvds_dual, lvds_8bpc);
+   nvif_outp_lvds(_encoder->outp, lvds_dual, lvds_8bpc);
break;
case DCB_OUTPUT_DP:
nvif_outp_acquire_dp(_encoder->outp, nv_encoder->dp.dpcd, 0, 
0, hda, false);
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index f878784593b43..ee4cec541a90e 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -24,6 +24,8 @@ union nvif_outp_args {
 #define NVIF_OUTP_V0_BL_GET0x30
 #define NVIF_OUTP_V0_BL_SET0x31
 
+#define NVIF_OUTP_V0_LVDS  0x40
+
 #define NVIF_OUTP_V0_HDMI  0x50
 
 #define NVIF_OUTP_V0_INFOFRAME 0x60
@@ -67,7 +69,6 @@ union nvif_outp_acquire_args {
 #define NVIF_OUTP_ACQUIRE_V0_DAC  0x00
 #define NVIF_OUTP_ACQUIRE_V0_SOR  0x01
 #define NVIF_OUTP_ACQUIRE_V0_PIOR 0x02
-#define NVIF_OUTP_ACQUIRE_V0_LVDS0x03
 #define NVIF_OUTP_ACQUIRE_V0_DP  0x04
__u8 type;
__u8 or;
@@ -77,11 +78,6 @@ union nvif_outp_acquire_args {
struct {
__u8 hda;
} sor;
-   struct {
-   __u8 dual;
-   __u8 bpc8;
-   __u8 pad02[6];
-   } lvds;
struct {
__u8 link_nr; /* 0 = highest possible. */
__u8 link_bw; /* 0 = highest possible, DP BW 
code otherwise. */
@@ -135,6 +131,14 @@ union nvif_outp_bl_set_args {
} v0;
 };
 
+union nvif_outp_lvds_args {
+   struct nvif_outp_lvds_v0 {
+   __u8  version;
+   __u8  dual;
+   __u8  bpc8;
+   } v0;
+};
+
 union nvif_outp_hdmi_args {
struct nvif_outp_hdmi_v0 {
__u8 version;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h 
b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index ef63d22b62f84..0ddaec9416eed 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -31,7 +31,6 @@ int nvif_outp_load_detect(struct nvif_outp *, u32 loadval);
 int nvif_outp_acquire_dac(struct nvif_outp *);
 int nvif_outp_acquire_sor(struct nvif_outp *, bool hda);
 int nvif_outp_acquire_pior(struct nvif_outp *);
-int nvif_outp_acquire_lvds(struct nvif_outp *, bool dual, bool bpc8);
 int nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE],
 int link_nr, int link_bw, bool hda, bool mst);
 int nvif_outp_inherit_rgb_crt(struct nvif_outp *outp, u8 *proto_out);
@@ -50,6 +49,8 @@ nvif_outp_acquired(struct nvif_outp *outp)
 int nvif_outp_bl_get(struct nvif_outp *);
 int nvif_outp_bl_set(struct nvif_outp *, int level);
 
+int nvif_outp_lvds(struct nvif_outp *, bool dual, bool bpc8);
+
 int nvif_outp_hdmi(struct nvif_outp *, int head, bool enable, u8 
max_ac_packet, u8 rekey, u32 khz,
   bool scdc, bool scdc_scrambling, bool scdc_low_rates);
 
diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c 
b/drivers/gpu/drm/nouveau/nvif/outp.c
index 5a3c0dd7d5324..dbb0986f05558 100644
--- a/drivers/gpu/drm/nouveau/nvif/outp.c
+++ b/drivers/gpu/drm/nouveau/nvif/outp.c
@@ -150,18 +150,17 @@ nvif_outp_hdmi(struct nvif_outp *outp, int head, bool 
enable, u8 max_ac_packet,
 }
 
 int
-nvif_outp_acquire_lvds(struct nvif_outp *outp, bool dual, bool bpc8)
+nvif_outp_lvds(struct nvif_outp *outp, bool dual, bool bpc8)
 {
-   struct nvif_outp_acquire_v0 args;
+   struct nvif_outp_lvds_v0 args;
int ret;
 
-   args.lvds.dual = dual;
-   args.lvds.bpc8 = bpc8;
+   args.version = 0;
+   args.dual = dual;
+   args.bpc8 = bpc8;
 
-   ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_LVDS, );
-   NVIF_ERRON(ret, >object,
-  "[ACQUIRE proto:LVDS du

[PATCH v3 23/44] drm/nouveau/disp: add output backlight control methods

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- preparation for GSP-RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/include/nvif/if0012.h | 17 
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |  3 +
 drivers/gpu/drm/nouveau/nouveau_backlight.c   | 90 ++-
 drivers/gpu/drm/nouveau/nvif/outp.c   | 27 ++
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c |  2 +
 .../gpu/drm/nouveau/nvkm/engine/disp/g84.c|  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/g94.c|  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/ga102.c  |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/gf119.c  |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/gk104.c  |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/gm107.c  |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/gm200.c  |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/gp100.c  |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/gt215.c  | 38 
 .../gpu/drm/nouveau/nvkm/engine/disp/gv100.c  |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/ior.h|  7 ++
 .../gpu/drm/nouveau/nvkm/engine/disp/mcp89.c  |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/nv50.c   | 32 +++
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.c   | 38 
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.h   |  8 ++
 .../gpu/drm/nouveau/nvkm/engine/disp/tu102.c  |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  | 41 +
 22 files changed, 233 insertions(+), 81 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index 230084d675ec2..f878784593b43 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -21,6 +21,9 @@ union nvif_outp_args {
 
 #define NVIF_OUTP_V0_LOAD_DETECT   0x20
 
+#define NVIF_OUTP_V0_BL_GET0x30
+#define NVIF_OUTP_V0_BL_SET0x31
+
 #define NVIF_OUTP_V0_HDMI  0x50
 
 #define NVIF_OUTP_V0_INFOFRAME 0x60
@@ -118,6 +121,20 @@ union nvif_outp_release_args {
} vn;
 };
 
+union nvif_outp_bl_get_args {
+   struct nvif_outp_bl_get_v0 {
+   __u8  version;
+   __u8  level;
+   } v0;
+};
+
+union nvif_outp_bl_set_args {
+   struct nvif_outp_bl_set_v0 {
+   __u8  version;
+   __u8  level;
+   } v0;
+};
+
 union nvif_outp_hdmi_args {
struct nvif_outp_hdmi_v0 {
__u8 version;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h 
b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index ea60d418d7f09..ef63d22b62f84 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -47,6 +47,9 @@ nvif_outp_acquired(struct nvif_outp *outp)
return outp->or.id >= 0;
 }
 
+int nvif_outp_bl_get(struct nvif_outp *);
+int nvif_outp_bl_set(struct nvif_outp *, int level);
+
 int nvif_outp_hdmi(struct nvif_outp *, int head, bool enable, u8 
max_ac_packet, u8 rekey, u32 khz,
   bool scdc, bool scdc_scrambling, bool scdc_low_rates);
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c 
b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 91b5ecc575380..d47442125fa18 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -109,42 +109,6 @@ nv40_backlight_init(struct nouveau_encoder *encoder,
return 0;
 }
 
-static int
-nv50_get_intensity(struct backlight_device *bd)
-{
-   struct nouveau_encoder *nv_encoder = bl_get_data(bd);
-   struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
-   struct nvif_object *device = >client.device.object;
-   int or = ffs(nv_encoder->dcb->or) - 1;
-   u32 div = 1025;
-   u32 val;
-
-   val  = nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
-   val &= NV50_PDISP_SOR_PWM_CTL_VAL;
-   return ((val * 100) + (div / 2)) / div;
-}
-
-static int
-nv50_set_intensity(struct backlight_device *bd)
-{
-   struct nouveau_encoder *nv_encoder = bl_get_data(bd);
-   struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
-   struct nvif_object *device = >client.device.object;
-   int or = ffs(nv_encoder->dcb->or) - 1;
-   u32 div = 1025;
-   u32 val = (bd->props.brightness * div) / 100;
-
-   nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
- NV50_PDISP_SOR_PWM_CTL_NEW | val);
-   return 0;
-}
-
-static const struct backlight_ops nv50_bl_ops = {
-   .options = BL_CORE_SUSPENDRESUME,
-   .get_brightness = nv50_get_intensity,
-   .update_status = nv50_set_intensity,
-};
-
 /*
  * eDP brightness callbacks need to happen under lock, since we need to
  * enable/disable the backlight ourselves for modesets
@@ -238,53 +202,25 @@ static const struct backlight_ops nv50_edp_bl_ops = {
 };
 
 static int
-nva3_get_intensity(struct backlight_device *bd)
+nv50_get_intensity(struct backlight_device *bd)
 {
struct nouveau

[PATCH v3 14/44] drm/nouveau/disp: update SOR routing immediately on acquire()

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- was previously delayed until second supervisor interrupt

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c  | 2 +-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
index 5b55598e09c85..b288ea6658da6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
@@ -48,8 +48,8 @@ nvkm_outp_route(struct nvkm_disp *disp)
 
list_for_each_entry(ior, >iors, head) {
if ((outp = ior->asy.outp)) {
-   OUTP_DBG(outp, "acquire %s", ior->name);
if (ior->asy.outp != ior->arm.outp) {
+   OUTP_DBG(outp, "acquire %s", ior->name);
if (ior->func->route.set)
ior->func->route.set(outp, ior);
ior->arm.outp = ior->asy.outp;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index d71bc188047e3..042a43c22061e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -235,6 +235,8 @@ nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, 
u32 argc)
if (ret)
return ret;
 
+   nvkm_outp_route(outp->disp);
+
args->v0.or = outp->ior->id;
args->v0.link = outp->ior->asy.link;
return 0;
-- 
2.41.0



[PATCH v3 22/44] drm/nouveau/disp: remove SOR routing updates from supervisor

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- these shouldn't be necessary now, and are done in acquire()/release()
- preparation for GSP-RM, where we don't control the supervisor

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c | 1 -
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c | 1 -
 drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c  | 1 -
 3 files changed, 3 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
index a48e9bdf4cd07..937baae6a3ebb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
@@ -1038,7 +1038,6 @@ gf119_disp_super(struct work_struct *work)
continue;
nv50_disp_super_2_0(disp, head);
}
-   nvkm_outp_route(disp);
list_for_each_entry(head, >heads, head) {
if (!(mask[head->id] & 0x0001))
continue;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
index 4ebc030e40d12..7ac59bab6309f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
@@ -863,7 +863,6 @@ gv100_disp_super(struct work_struct *work)
continue;
nv50_disp_super_2_0(disp, head);
}
-   nvkm_outp_route(disp);
list_for_each_entry(head, >heads, head) {
if (!(mask[head->id] & 0x0001))
continue;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
index be81168029604..a4ce605177895 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
@@ -1371,7 +1371,6 @@ nv50_disp_super(struct work_struct *work)
continue;
nv50_disp_super_2_0(disp, head);
}
-   nvkm_outp_route(disp);
list_for_each_entry(head, >heads, head) {
if (!(super & (0x0200 << head->id)))
continue;
-- 
2.41.0



[PATCH v3 21/44] drm/nouveau/disp: release outputs post-modeset

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

Prior to this commit, KMS would call release() prior to modeset, and the
second supervisor interrupt would update SOR routing if needed.

Now, KMS will call release() post-modeset and update routing immediately.

- preparation for GSP-RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c| 18 --
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.c|  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c   |  2 ++
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index ab048cf25d866..50a0ff304291e 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -477,7 +477,6 @@ nv50_dac_atomic_disable(struct drm_encoder *encoder, struct 
drm_atomic_state *st
 
core->func->dac->ctrl(core, nv_encoder->outp.or.id, ctrl, NULL);
nv_encoder->crtc = NULL;
-   nvif_outp_release(_encoder->outp);
 }
 
 static void
@@ -1300,6 +1299,11 @@ nv50_mstm_cleanup(struct drm_atomic_state *state,
}
}
 
+   if (mstm->disabled) {
+   nvif_outp_release(>outp->outp);
+   mstm->disabled = false;
+   }
+
mstm->modified = false;
 }
 
@@ -1334,12 +1338,6 @@ nv50_mstm_prepare(struct drm_atomic_state *state,
nv50_msto_prepare(state, mst_state, >mgr, 
msto);
}
}
-
-   if (mstm->disabled) {
-   if (!mstm->links)
-   nvif_outp_release(>outp->outp);
-   mstm->disabled = false;
-   }
 }
 
 static struct drm_connector *
@@ -1582,7 +1580,6 @@ nv50_sor_atomic_disable(struct drm_encoder *encoder, 
struct drm_atomic_state *st
 
nv_encoder->update(nv_encoder, nv_crtc->index, NULL, 0, 0);
nv50_audio_disable(encoder, nv_crtc);
-   nvif_outp_release(_encoder->outp);
nv_encoder->crtc = NULL;
 }
 
@@ -1827,7 +1824,6 @@ nv50_pior_atomic_disable(struct drm_encoder *encoder, 
struct drm_atomic_state *s
 
core->func->pior->ctrl(core, nv_encoder->outp.or.id, ctrl, NULL);
nv_encoder->crtc = NULL;
-   nvif_outp_release(_encoder->outp);
 }
 
 static void
@@ -1990,8 +1986,10 @@ nv50_disp_atomic_commit_core(struct drm_atomic_state 
*state, u32 *interlock)
  nv_encoder->conn, NULL, NULL);
outp->enabled = outp->disabled = false;
} else {
-   if (outp->disabled)
+   if (outp->disabled) {
+   nvif_outp_release(_encoder->outp);
outp->disabled = false;
+   }
}
}
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
index b288ea6658da6..20a013f1bbbac 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
@@ -238,6 +238,7 @@ void
 nvkm_outp_release(struct nvkm_outp *outp)
 {
nvkm_outp_release_or(outp, NVKM_OUTP_USER);
+   nvkm_outp_route(outp->disp);
 }
 
 void
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index ffd174091454f..40cbb4ddc0378 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -188,6 +188,8 @@ nvkm_uoutp_mthd_release(struct nvkm_outp *outp, void *argv, 
u32 argc)
 
if (argc != sizeof(args->vn))
return -ENOSYS;
+   if (!outp->ior)
+   return -EINVAL;
 
nvkm_outp_release(outp);
return 0;
-- 
2.41.0



[PATCH v3 18/44] drm/nouveau/kms/nv50-: move audio enable post-modeset

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- adds tracking for post-UPDATE modeset operations, similar to mst[mo]'s
- audio won't work on RM without this
- we should probably have been doing this anyway

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 35 ++---
 drivers/gpu/drm/nouveau/dispnv50/disp.h |  3 +++
 2 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 8fa3bb8c2f41e..99aa8d208711c 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -707,6 +707,18 @@ nv50_audio_supported(struct drm_encoder *encoder)
disp->disp->object.oclass == GT206_DISP)
return false;
 
+   if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
+   struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+   switch (nv_encoder->dcb->type) {
+   case DCB_OUTPUT_TMDS:
+   case DCB_OUTPUT_DP:
+   break;
+   default:
+   return false;
+   }
+   }
+
return true;
 }
 
@@ -829,8 +841,6 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct 
nouveau_crtc *nv_crtc,
size = 0;
 
nvif_outp_infoframe(_encoder->outp, NVIF_OUTP_INFOFRAME_V0_VSI, 
, size);
-
-   nv50_audio_enable(encoder, nv_crtc, nv_connector, state, mode);
 }
 
 /**
@@ -1660,8 +1670,6 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, 
struct drm_atomic_state *sta
else
proto = NV887D_SOR_SET_CONTROL_PROTOCOL_DP_B;
 
-   nv50_audio_enable(encoder, nv_crtc, nv_connector, state, mode);
-
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
backlight = nv_connector->backlight;
if (backlight && backlight->uses_dpcd)
@@ -1939,7 +1947,9 @@ nv50_disp_atomic_commit_core(struct drm_atomic_state 
*state, u32 *interlock)
struct drm_dp_mst_topology_state *mst_state;
struct nouveau_drm *drm = nouveau_drm(state->dev);
struct nv50_disp *disp = nv50_disp(drm->dev);
+   struct nv50_atom *atom = nv50_atom(state);
struct nv50_core *core = disp->core;
+   struct nv50_outp_atom *outp;
struct nv50_mstm *mstm;
int i;
 
@@ -1962,6 +1972,21 @@ nv50_disp_atomic_commit_core(struct drm_atomic_state 
*state, u32 *interlock)
if (mstm->modified)
nv50_mstm_cleanup(state, mst_state, mstm);
}
+
+   list_for_each_entry(outp, >outp, head) {
+   if (outp->encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
+   struct nouveau_encoder *nv_encoder = 
nouveau_encoder(outp->encoder);
+
+   if (outp->enabled) {
+   nv50_audio_enable(outp->encoder, 
nouveau_crtc(nv_encoder->crtc),
+ nv_encoder->conn, NULL, NULL);
+   outp->enabled = outp->disabled = false;
+   } else {
+   if (outp->disabled)
+   outp->disabled = false;
+   }
+   }
+   }
 }
 
 static void
@@ -2053,6 +2078,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state 
*state)
 
if (outp->clr.mask) {
help->atomic_disable(encoder, state);
+   outp->disabled = true;
interlock[NV50_DISP_INTERLOCK_CORE] |= 1;
if (outp->flush_disable) {
nv50_disp_atomic_commit_wndw(state, interlock);
@@ -2092,6 +2118,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state 
*state)
 
if (outp->set.mask) {
help->atomic_enable(encoder, state);
+   outp->enabled = true;
interlock[NV50_DISP_INTERLOCK_CORE] = 1;
}
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.h 
b/drivers/gpu/drm/nouveau/dispnv50/disp.h
index 9d66c9c726c35..42209f5b06f91 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.h
@@ -85,6 +85,9 @@ struct nv50_outp_atom {
struct drm_encoder *encoder;
bool flush_disable;
 
+   bool disabled;
+   bool enabled;
+
union nv50_outp_atom_mask {
struct {
bool ctrl:1;
-- 
2.41.0



[PATCH v3 20/44] drm/nouveau/disp: move hdmi disable out of release()

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- release() is being moved post-modeset, preserve hdmi behaviour for now

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c  |  8 
 drivers/gpu/drm/nouveau/nouveau_encoder.h|  6 +-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 15 +++
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 7a7b3464a6671..ab048cf25d866 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -842,6 +842,8 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct 
nouveau_crtc *nv_crtc,
size = 0;
 
nvif_outp_infoframe(_encoder->outp, NVIF_OUTP_INFOFRAME_V0_VSI, 
, size);
+
+   nv_encoder->hdmi.enabled = true;
 }
 
 /**
@@ -1562,6 +1564,12 @@ nv50_sor_atomic_disable(struct drm_encoder *encoder, 
struct drm_atomic_state *st
}
 #endif
 
+   if (nv_encoder->dcb->type == DCB_OUTPUT_TMDS && 
nv_encoder->hdmi.enabled) {
+   nvif_outp_hdmi(_encoder->outp, nv_crtc->index,
+  false, 0, 0, 0, false, false, false);
+   nv_encoder->hdmi.enabled = false;
+   }
+
if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, );
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h 
b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index ea8ef10e71aae..b3a9415ba879c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -69,7 +69,11 @@ struct nouveau_encoder {
 
struct nv04_output_reg restore;
 
-   union {
+   struct {
+   struct {
+   bool enabled;
+   } hdmi;
+
struct {
struct nv50_mstm *mstm;
int link_nr;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index 8ba96323e1de5..ffd174091454f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -154,6 +154,13 @@ nvkm_uoutp_mthd_hdmi(struct nvkm_outp *outp, void *argv, 
u32 argc)
(args->v0.scdc && !ior->func->hdmi->scdc))
return -EINVAL;
 
+   if (!args->v0.enable) {
+   ior->func->hdmi->infoframe_avi(ior, args->v0.head, NULL, 0);
+   ior->func->hdmi->infoframe_vsi(ior, args->v0.head, NULL, 0);
+   ior->func->hdmi->ctrl(ior, args->v0.head, false, 0, 0);
+   return 0;
+   }
+
ior->func->hdmi->ctrl(ior, args->v0.head, args->v0.enable,
  args->v0.max_ac_packet, args->v0.rekey);
if (ior->func->hdmi->scdc)
@@ -177,19 +184,11 @@ nvkm_uoutp_mthd_acquire_lvds(struct nvkm_outp *outp, bool 
dual, bool bpc8)
 static int
 nvkm_uoutp_mthd_release(struct nvkm_outp *outp, void *argv, u32 argc)
 {
-   struct nvkm_head *head = outp->asy.head;
-   struct nvkm_ior *ior = outp->ior;
union nvif_outp_release_args *args = argv;
 
if (argc != sizeof(args->vn))
return -ENOSYS;
 
-   if (ior->func->hdmi && head) {
-   ior->func->hdmi->infoframe_avi(ior, head->id, NULL, 0);
-   ior->func->hdmi->infoframe_vsi(ior, head->id, NULL, 0);
-   ior->func->hdmi->ctrl(ior, head->id, false, 0, 0);
-   }
-
nvkm_outp_release(outp);
return 0;
 }
-- 
2.41.0



[PATCH v3 19/44] drm/nouveau/disp: add output hdmi config method

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- was previously part of acquire()
- preparation for GSP-RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 10 ++---
 drivers/gpu/drm/nouveau/include/nvif/if0012.h | 28 --
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |  5 ++-
 drivers/gpu/drm/nouveau/nvif/outp.c   | 33 +
 .../gpu/drm/nouveau/nvkm/engine/disp/gm200.c  | 16 ++--
 .../gpu/drm/nouveau/nvkm/engine/disp/ior.h|  5 ++-
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  | 37 +--
 7 files changed, 74 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 99aa8d208711c..7a7b3464a6671 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -778,7 +778,6 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct 
nouveau_crtc *nv_crtc,
struct drm_hdmi_info *hdmi = _connector->base.display_info.hdmi;
union hdmi_infoframe infoframe = { 0 };
const u8 rekey = 56; /* binary driver, and tegra, constant */
-   u8 scdc = 0;
u32 max_ac_packet;
struct {
struct nvif_outp_infoframe_v0 infoframe;
@@ -791,8 +790,9 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct 
nouveau_crtc *nv_crtc,
max_ac_packet -= 18; /* constant from tegra */
max_ac_packet /= 32;
 
-   if (hdmi->scdc.scrambling.supported) {
+   if (nv_encoder->i2c && hdmi->scdc.scrambling.supported) {
const bool high_tmds_clock_ratio = mode->clock > 34;
+   u8 scdc;
 
ret = drm_scdc_readb(nv_encoder->i2c, SCDC_TMDS_CONFIG, );
if (ret < 0) {
@@ -812,8 +812,9 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct 
nouveau_crtc *nv_crtc,
 scdc, ret);
}
 
-   ret = nvif_outp_acquire_tmds(_encoder->outp, nv_crtc->index, true,
-max_ac_packet, rekey, scdc, hda);
+   ret = nvif_outp_hdmi(_encoder->outp, nv_crtc->index, true, 
max_ac_packet, rekey,
+mode->clock, hdmi->scdc.supported, 
hdmi->scdc.scrambling.supported,
+hdmi->scdc.scrambling.low_rates);
if (ret)
return;
 
@@ -1852,7 +1853,6 @@ nv50_pior_atomic_enable(struct drm_encoder *encoder, 
struct drm_atomic_state *st
switch (nv_encoder->dcb->type) {
case DCB_OUTPUT_TMDS:
ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC);
-   nvif_outp_acquire_tmds(_encoder->outp, false, false, 0, 0, 
0, false);
break;
case DCB_OUTPUT_DP:
ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC);
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index 57bc4b2f2b170..230084d675ec2 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -21,6 +21,8 @@ union nvif_outp_args {
 
 #define NVIF_OUTP_V0_LOAD_DETECT   0x20
 
+#define NVIF_OUTP_V0_HDMI  0x50
+
 #define NVIF_OUTP_V0_INFOFRAME 0x60
 #define NVIF_OUTP_V0_HDA_ELD   0x61
 
@@ -62,7 +64,6 @@ union nvif_outp_acquire_args {
 #define NVIF_OUTP_ACQUIRE_V0_DAC  0x00
 #define NVIF_OUTP_ACQUIRE_V0_SOR  0x01
 #define NVIF_OUTP_ACQUIRE_V0_PIOR 0x02
-#define NVIF_OUTP_ACQUIRE_V0_TMDS0x05
 #define NVIF_OUTP_ACQUIRE_V0_LVDS0x03
 #define NVIF_OUTP_ACQUIRE_V0_DP  0x04
__u8 type;
@@ -73,17 +74,6 @@ union nvif_outp_acquire_args {
struct {
__u8 hda;
} sor;
-   struct {
-   __u8 head;
-   __u8 hdmi;
-   __u8 hdmi_max_ac_packet;
-   __u8 hdmi_rekey;
-#define NVIF_OUTP_ACQUIRE_V0_TMDS_HDMI_SCDC_SCRAMBLE (1 << 0)
-#define NVIF_OUTP_ACQUIRE_V0_TMDS_HDMI_SCDC_DIV_BY_4 (1 << 1)
-   __u8 hdmi_scdc;
-   __u8 hdmi_hda;
-   __u8 pad06[2];
-   } tmds;
struct {
__u8 dual;
__u8 bpc8;
@@ -128,6 +118,20 @@ union nvif_outp_release_args {
} vn;
 };
 
+union nvif_outp_hdmi_args {
+   struct nvif_outp_hdmi_v0 {
+   __u8 version;
+   __u8 head;
+   __u8 enable;
+   __u8 max_ac_packet;
+   __u8 rekey;
+   __u8 scdc;
+   __u8 scdc_scrambling;
+   __u8 scdc_low_rates;
+   __u32 khz;
+   } v0;

[PATCH v3 17/44] drm/nouveau/kms/nv50-: keep output state around until modeset complete

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- we'll want this info post-UPDATE for later patches

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index a72cb74184472..8fa3bb8c2f41e 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -2080,7 +2080,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state 
*state)
nv50_crc_atomic_init_notifier_contexts(state);
 
/* Update output path(s). */
-   list_for_each_entry_safe(outp, outt, >outp, head) {
+   list_for_each_entry(outp, >outp, head) {
const struct drm_encoder_helper_funcs *help;
struct drm_encoder *encoder;
 
@@ -2094,9 +2094,6 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state 
*state)
help->atomic_enable(encoder, state);
interlock[NV50_DISP_INTERLOCK_CORE] = 1;
}
-
-   list_del(>head);
-   kfree(outp);
}
 
/* Update head(s). */
@@ -2194,6 +2191,11 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state 
*state)
if (atom->lock_core)
mutex_unlock(>mutex);
 
+   list_for_each_entry_safe(outp, outt, >outp, head) {
+   list_del(>head);
+   kfree(outp);
+   }
+
/* Wait for HW to signal completion. */
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
struct nv50_wndw_atom *asyw = nv50_wndw_atom(new_plane_state);
-- 
2.41.0



[PATCH v3 15/44] drm/nouveau/kms/nv50-: pull some common init out of OR-specific code

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- cleanup before additional changes

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 69 ---
 drivers/gpu/drm/nouveau/nouveau_encoder.h |  2 +
 2 files changed, 38 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 814d2be34d202..5c88d2e5321b1 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -554,34 +554,27 @@ nv50_dac_func = {
 };
 
 static int
-nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe)
+nv50_dac_create(struct nouveau_encoder *nv_encoder)
 {
+   struct drm_connector *connector = _encoder->conn->base;
struct nouveau_drm *drm = nouveau_drm(connector->dev);
-   struct nv50_disp *disp = nv50_disp(connector->dev);
struct nvkm_i2c *i2c = nvxx_i2c(>client.device);
struct nvkm_i2c_bus *bus;
-   struct nouveau_encoder *nv_encoder;
struct drm_encoder *encoder;
+   struct dcb_output *dcbe = nv_encoder->dcb;
int type = DRM_MODE_ENCODER_DAC;
 
-   nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
-   if (!nv_encoder)
-   return -ENOMEM;
-   nv_encoder->dcb = dcbe;
-
bus = nvkm_i2c_bus_find(i2c, dcbe->i2c_index);
if (bus)
nv_encoder->i2c = >i2c;
 
encoder = to_drm_encoder(nv_encoder);
-   encoder->possible_crtcs = dcbe->heads;
-   encoder->possible_clones = 0;
drm_encoder_init(connector->dev, encoder, _dac_func, type,
 "dac-%04x-%04x", dcbe->hasht, dcbe->hashm);
drm_encoder_helper_add(encoder, _dac_help);
 
drm_connector_attach_encoder(connector, encoder);
-   return nvif_outp_ctor(disp->disp, nv_encoder->base.base.name, dcbe->id, 
_encoder->outp);
+   return 0;
 }
 
 /*
@@ -1726,13 +1719,14 @@ bool nv50_has_mst(struct nouveau_drm *drm)
 }
 
 static int
-nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
+nv50_sor_create(struct nouveau_encoder *nv_encoder)
 {
+   struct drm_connector *connector = _encoder->conn->base;
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_drm *drm = nouveau_drm(connector->dev);
struct nvkm_i2c *i2c = nvxx_i2c(>client.device);
-   struct nouveau_encoder *nv_encoder;
struct drm_encoder *encoder;
+   struct dcb_output *dcbe = nv_encoder->dcb;
struct nv50_disp *disp = nv50_disp(connector->dev);
int type, ret;
 
@@ -1745,15 +1739,9 @@ nv50_sor_create(struct drm_connector *connector, struct 
dcb_output *dcbe)
break;
}
 
-   nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
-   if (!nv_encoder)
-   return -ENOMEM;
-   nv_encoder->dcb = dcbe;
nv_encoder->update = nv50_sor_update;
 
encoder = to_drm_encoder(nv_encoder);
-   encoder->possible_crtcs = dcbe->heads;
-   encoder->possible_clones = 0;
drm_encoder_init(connector->dev, encoder, _sor_func, type,
 "sor-%04x-%04x", dcbe->hasht, dcbe->hashm);
drm_encoder_helper_add(encoder, _sor_help);
@@ -1797,7 +1785,7 @@ nv50_sor_create(struct drm_connector *connector, struct 
dcb_output *dcbe)
nv_encoder->i2c = >i2c;
}
 
-   return nvif_outp_ctor(disp->disp, nv_encoder->base.base.name, dcbe->id, 
_encoder->outp);
+   return 0;
 }
 
 /**
@@ -1897,8 +1885,9 @@ nv50_pior_func = {
 };
 
 static int
-nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
+nv50_pior_create(struct nouveau_encoder *nv_encoder)
 {
+   struct drm_connector *connector = _encoder->conn->base;
struct drm_device *dev = connector->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nv50_disp *disp = nv50_disp(dev);
@@ -1906,8 +1895,8 @@ nv50_pior_create(struct drm_connector *connector, struct 
dcb_output *dcbe)
struct nvkm_i2c_bus *bus = NULL;
struct nvkm_i2c_aux *aux = NULL;
struct i2c_adapter *ddc;
-   struct nouveau_encoder *nv_encoder;
struct drm_encoder *encoder;
+   struct dcb_output *dcbe = nv_encoder->dcb;
int type;
 
switch (dcbe->type) {
@@ -1925,16 +1914,10 @@ nv50_pior_create(struct drm_connector *connector, 
struct dcb_output *dcbe)
return -ENODEV;
}
 
-   nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
-   if (!nv_encoder)
-   return -ENOMEM;
-   nv_encoder->dcb = dcbe;
nv_encoder->i2c = ddc;
 

[PATCH v3 16/44] drm/nouveau/kms/nv50-: remove nv_encoder.audio.connector

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- use nv_encoder.conn instead, outp->conn never changes

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 4 +---
 drivers/gpu/drm/nouveau/nouveau_encoder.h | 1 -
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 5c88d2e5321b1..a72cb74184472 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -611,7 +611,7 @@ nv50_audio_component_get_eld(struct device *kdev, int port, 
int dev_id,
continue; /* TODO */
 
nv_encoder = nouveau_encoder(encoder);
-   nv_connector = nouveau_connector(nv_encoder->audio.connector);
+   nv_connector = nv_encoder->conn;
nv_crtc = nouveau_crtc(nv_encoder->crtc);
 
if (!nv_crtc || nv_encoder->outp.or.id != port || 
nv_crtc->index != dev_id)
@@ -723,7 +723,6 @@ nv50_audio_disable(struct drm_encoder *encoder, struct 
nouveau_crtc *nv_crtc)
mutex_lock(>audio.lock);
if (nv_encoder->audio.enabled) {
nv_encoder->audio.enabled = false;
-   nv_encoder->audio.connector = NULL;
nvif_outp_hda_eld(_encoder->outp, nv_crtc->index, NULL, 0);
}
mutex_unlock(>audio.lock);
@@ -748,7 +747,6 @@ nv50_audio_enable(struct drm_encoder *encoder, struct 
nouveau_crtc *nv_crtc,
nvif_outp_hda_eld(_encoder->outp, nv_crtc->index, 
nv_connector->base.eld,
  drm_eld_size(nv_connector->base.eld));
nv_encoder->audio.enabled = true;
-   nv_encoder->audio.connector = _connector->base;
 
mutex_unlock(>audio.lock);
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h 
b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index b1554ad9d929b..ea8ef10e71aae 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -62,7 +62,6 @@ struct nouveau_encoder {
/* Protected by nouveau_drm.audio.lock */
struct {
bool enabled;
-   struct drm_connector *connector;
} audio;
 
struct drm_display_mode mode;
-- 
2.41.0



[PATCH v3 13/44] drm/nouveau/disp: add acquire_sor/pior()

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- preparing to move protocol-specific args out of acquire() again
- avoid re-acquiring acquired output, will matter when enforced later
- sor/pior done at same time due to shared tmds/dp handling

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 15 ++
 drivers/gpu/drm/nouveau/include/nvif/if0012.h |  7 -
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |  2 ++
 drivers/gpu/drm/nouveau/nvif/outp.c   | 24 
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  | 28 ++-
 5 files changed, 50 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 62fd910ffef61..814d2be34d202 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1034,7 +1034,7 @@ nv50_msto_atomic_enable(struct drm_encoder *encoder, 
struct drm_atomic_state *st
return;
 
if (!mstm->links++) {
-   /*XXX: MST audio. */
+   nvif_outp_acquire_sor(>outp->outp, false /*TODO: MST 
audio... */);
nvif_outp_acquire_dp(>outp->outp, mstm->outp->dp.dpcd, 0, 
0, false, true);
}
 
@@ -1602,15 +1602,17 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, 
struct drm_atomic_state *sta
 
if ((disp->disp->object.oclass == GT214_DISP ||
 disp->disp->object.oclass >= GF110_DISP) &&
+   nv_encoder->dcb->type != DCB_OUTPUT_LVDS &&
drm_detect_monitor_audio(nv_connector->edid))
hda = true;
 
+   if (!nvif_outp_acquired(outp))
+   nvif_outp_acquire_sor(outp, hda);
+
switch (nv_encoder->dcb->type) {
case DCB_OUTPUT_TMDS:
-   if (disp->disp->object.oclass == NV50_DISP ||
-   !drm_detect_hdmi_monitor(nv_connector->edid))
-   nvif_outp_acquire_tmds(outp, nv_crtc->index, false, 0, 
0, 0, false);
-   else
+   if (disp->disp->object.oclass != NV50_DISP &&
+   drm_detect_hdmi_monitor(nv_connector->edid))
nv50_hdmi_enable(encoder, nv_crtc, nv_connector, state, 
mode, hda);
 
if (nv_encoder->outp.or.link & 1) {
@@ -1850,6 +1852,9 @@ nv50_pior_atomic_enable(struct drm_encoder *encoder, 
struct drm_atomic_state *st
default: asyh->or.depth = NV837D_PIOR_SET_CONTROL_PIXEL_DEPTH_DEFAULT; 
break;
}
 
+   if (!nvif_outp_acquired(_encoder->outp))
+   nvif_outp_acquire_pior(_encoder->outp);
+
switch (nv_encoder->dcb->type) {
case DCB_OUTPUT_TMDS:
ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC);
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index d139d070c0bc6..57bc4b2f2b170 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -60,7 +60,9 @@ union nvif_outp_acquire_args {
struct nvif_outp_acquire_v0 {
__u8 version;
 #define NVIF_OUTP_ACQUIRE_V0_DAC  0x00
-#define NVIF_OUTP_ACQUIRE_V0_TMDS0x02
+#define NVIF_OUTP_ACQUIRE_V0_SOR  0x01
+#define NVIF_OUTP_ACQUIRE_V0_PIOR 0x02
+#define NVIF_OUTP_ACQUIRE_V0_TMDS0x05
 #define NVIF_OUTP_ACQUIRE_V0_LVDS0x03
 #define NVIF_OUTP_ACQUIRE_V0_DP  0x04
__u8 type;
@@ -68,6 +70,9 @@ union nvif_outp_acquire_args {
__u8 link;
__u8 pad04[4];
union {
+   struct {
+   __u8 hda;
+   } sor;
struct {
__u8 head;
__u8 hdmi;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h 
b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index c6d8823ef782c..a9090424dbf7e 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -29,6 +29,8 @@ int nvif_outp_edid_get(struct nvif_outp *, u8 **pedid);
 
 int nvif_outp_load_detect(struct nvif_outp *, u32 loadval);
 int nvif_outp_acquire_dac(struct nvif_outp *);
+int nvif_outp_acquire_sor(struct nvif_outp *, bool hda);
+int nvif_outp_acquire_pior(struct nvif_outp *);
 int nvif_outp_acquire_tmds(struct nvif_outp *, int head,
   bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool 
hda);
 int nvif_outp_acquire_lvds(struct nvif_outp *, bool dual, bool bpc8);
diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c 
b/drivers/gpu/drm/nouveau/nvif/outp.c
index 41c4de40895f0..81dbda52117ec 100644
--- a/drivers/gpu/drm/nouveau/nvif/outp.c
+++ b/drivers/gpu/drm/nouveau/nvif/outp.c
@@ -187,6 +187,30 @@ nvif_outp_acquire(stru

[PATCH v3 12/44] drm/nouveau/disp: add acquire_dac()

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- preparing to move protocol-specific args out of acquire() again
- avoid re-acquiring acquired output, will matter when enforced later
- this one is basically just a rename

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c  |  3 ++-
 drivers/gpu/drm/nouveau/include/nvif/if0012.h|  5 ++---
 drivers/gpu/drm/nouveau/include/nvif/outp.h  |  9 -
 drivers/gpu/drm/nouveau/nvif/outp.c  | 10 +-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c |  4 ++--
 5 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 290f3c80ba4eb..62fd910ffef61 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -502,7 +502,8 @@ nv50_dac_atomic_enable(struct drm_encoder *encoder, struct 
drm_atomic_state *sta
 
ctrl |= NVDEF(NV507D, DAC_SET_CONTROL, PROTOCOL, RGB_CRT);
 
-   nvif_outp_acquire_rgb_crt(_encoder->outp);
+   if (!nvif_outp_acquired(_encoder->outp))
+   nvif_outp_acquire_dac(_encoder->outp);
 
core->func->dac->ctrl(core, nv_encoder->outp.or.id, ctrl, asyh);
asyh->or.depth = 0;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index 6cfc885e0aa9a..d139d070c0bc6 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -59,12 +59,11 @@ union nvif_outp_load_detect_args {
 union nvif_outp_acquire_args {
struct nvif_outp_acquire_v0 {
__u8 version;
-#define NVIF_OUTP_ACQUIRE_V0_RGB_CRT 0x00
-#define NVIF_OUTP_ACQUIRE_V0_TV  0x01
+#define NVIF_OUTP_ACQUIRE_V0_DAC  0x00
 #define NVIF_OUTP_ACQUIRE_V0_TMDS0x02
 #define NVIF_OUTP_ACQUIRE_V0_LVDS0x03
 #define NVIF_OUTP_ACQUIRE_V0_DP  0x04
-   __u8 proto;
+   __u8 type;
__u8 or;
__u8 link;
__u8 pad04[4];
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h 
b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index 23776057bfea8..c6d8823ef782c 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -28,7 +28,7 @@ enum nvif_outp_detect_status nvif_outp_detect(struct 
nvif_outp *);
 int nvif_outp_edid_get(struct nvif_outp *, u8 **pedid);
 
 int nvif_outp_load_detect(struct nvif_outp *, u32 loadval);
-int nvif_outp_acquire_rgb_crt(struct nvif_outp *);
+int nvif_outp_acquire_dac(struct nvif_outp *);
 int nvif_outp_acquire_tmds(struct nvif_outp *, int head,
   bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool 
hda);
 int nvif_outp_acquire_lvds(struct nvif_outp *, bool dual, bool bpc8);
@@ -40,6 +40,13 @@ int nvif_outp_inherit_tmds(struct nvif_outp *outp, u8 
*proto_out);
 int nvif_outp_inherit_dp(struct nvif_outp *outp, u8 *proto_out);
 
 void nvif_outp_release(struct nvif_outp *);
+
+static inline bool
+nvif_outp_acquired(struct nvif_outp *outp)
+{
+   return outp->or.id >= 0;
+}
+
 int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct 
nvif_outp_infoframe_v0 *, u32 size);
 int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size);
 int nvif_outp_dp_aux_pwr(struct nvif_outp *, bool enable);
diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c 
b/drivers/gpu/drm/nouveau/nvif/outp.c
index eecccfc17c1c6..41c4de40895f0 100644
--- a/drivers/gpu/drm/nouveau/nvif/outp.c
+++ b/drivers/gpu/drm/nouveau/nvif/outp.c
@@ -171,12 +171,12 @@ nvif_outp_release(struct nvif_outp *outp)
 }
 
 static inline int
-nvif_outp_acquire(struct nvif_outp *outp, u8 proto, struct 
nvif_outp_acquire_v0 *args)
+nvif_outp_acquire(struct nvif_outp *outp, u8 type, struct nvif_outp_acquire_v0 
*args)
 {
int ret;
 
args->version = 0;
-   args->proto = proto;
+   args->type = type;
 
ret = nvif_mthd(>object, NVIF_OUTP_V0_ACQUIRE, args, 
sizeof(*args));
if (ret)
@@ -188,13 +188,13 @@ nvif_outp_acquire(struct nvif_outp *outp, u8 proto, 
struct nvif_outp_acquire_v0
 }
 
 int
-nvif_outp_acquire_rgb_crt(struct nvif_outp *outp)
+nvif_outp_acquire_dac(struct nvif_outp *outp)
 {
struct nvif_outp_acquire_v0 args;
int ret;
 
-   ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_RGB_CRT, );
-   NVIF_ERRON(ret, >object, "[ACQUIRE proto:RGB_CRT] or:%d", 
args.or);
+   ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_DAC, );
+   NVIF_ERRON(ret, >object, "[ACQUIRE DAC] or:%d", args.or);
return ret;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index d56a87ae5b265..73c6227446fb8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++

[PATCH v3 11/44] drm/nouveau/disp: shuffle to make upcoming diffs prettier

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- preparing to move protocol-specific args out of acquire() again
- no code changes

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvif/outp.c   | 106 +-
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  |  74 ++--
 2 files changed, 91 insertions(+), 89 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c 
b/drivers/gpu/drm/nouveau/nvif/outp.c
index 795658f0c920c..eecccfc17c1c6 100644
--- a/drivers/gpu/drm/nouveau/nvif/outp.c
+++ b/drivers/gpu/drm/nouveau/nvif/outp.c
@@ -54,6 +54,28 @@ nvif_outp_dp_retrain(struct nvif_outp *outp)
return ret;
 }
 
+static inline int nvif_outp_acquire(struct nvif_outp *, u8, struct 
nvif_outp_acquire_v0 *);
+
+int
+nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE],
+int link_nr, int link_bw, bool hda, bool mst)
+{
+   struct nvif_outp_acquire_v0 args;
+   int ret;
+
+   args.dp.link_nr = link_nr;
+   args.dp.link_bw = link_bw;
+   args.dp.hda = hda;
+   args.dp.mst = mst;
+   memcpy(args.dp.dpcd, dpcd, sizeof(args.dp.dpcd));
+
+   ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_DP, );
+   NVIF_ERRON(ret, >object,
+  "[ACQUIRE proto:DP link_nr:%d link_bw:%02x hda:%d mst:%d] 
or:%d link:%d",
+  args.dp.link_nr, args.dp.link_bw, args.dp.hda, args.dp.mst, 
args.or, args.link);
+   return ret;
+}
+
 int
 nvif_outp_dp_aux_pwr(struct nvif_outp *outp, bool enable)
 {
@@ -101,48 +123,26 @@ nvif_outp_infoframe(struct nvif_outp *outp, u8 type, 
struct nvif_outp_infoframe_
return ret;
 }
 
-void
-nvif_outp_release(struct nvif_outp *outp)
-{
-   int ret = nvif_mthd(>object, NVIF_OUTP_V0_RELEASE, NULL, 0);
-   NVIF_ERRON(ret, >object, "[RELEASE]");
-   outp->or.id = -1;
-}
-
-static inline int
-nvif_outp_acquire(struct nvif_outp *outp, u8 proto, struct 
nvif_outp_acquire_v0 *args)
-{
-   int ret;
-
-   args->version = 0;
-   args->proto = proto;
-
-   ret = nvif_mthd(>object, NVIF_OUTP_V0_ACQUIRE, args, 
sizeof(*args));
-   if (ret)
-   return ret;
-
-   outp->or.id = args->or;
-   outp->or.link = args->link;
-   return 0;
-}
-
 int
-nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE],
-int link_nr, int link_bw, bool hda, bool mst)
+nvif_outp_acquire_tmds(struct nvif_outp *outp, int head,
+  bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool hda)
 {
struct nvif_outp_acquire_v0 args;
int ret;
 
-   args.dp.link_nr = link_nr;
-   args.dp.link_bw = link_bw;
-   args.dp.hda = hda;
-   args.dp.mst = mst;
-   memcpy(args.dp.dpcd, dpcd, sizeof(args.dp.dpcd));
+   args.tmds.head = head;
+   args.tmds.hdmi = hdmi;
+   args.tmds.hdmi_max_ac_packet = max_ac_packet;
+   args.tmds.hdmi_rekey = rekey;
+   args.tmds.hdmi_scdc = scdc;
+   args.tmds.hdmi_hda = hda;
 
-   ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_DP, );
+   ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_TMDS, );
NVIF_ERRON(ret, >object,
-  "[ACQUIRE proto:DP link_nr:%d link_bw:%02x hda:%d mst:%d] 
or:%d link:%d",
-  args.dp.link_nr, args.dp.link_bw, args.dp.hda, args.dp.mst, 
args.or, args.link);
+  "[ACQUIRE proto:TMDS head:%d hdmi:%d max_ac_packet:%d 
rekey:%d scdc:%d hda:%d]"
+  " or:%d link:%d", args.tmds.head, args.tmds.hdmi, 
args.tmds.hdmi_max_ac_packet,
+  args.tmds.hdmi_rekey, args.tmds.hdmi_scdc, 
args.tmds.hdmi_hda,
+  args.or, args.link);
return ret;
 }
 
@@ -162,27 +162,29 @@ nvif_outp_acquire_lvds(struct nvif_outp *outp, bool dual, 
bool bpc8)
return ret;
 }
 
-int
-nvif_outp_acquire_tmds(struct nvif_outp *outp, int head,
-  bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool hda)
+void
+nvif_outp_release(struct nvif_outp *outp)
+{
+   int ret = nvif_mthd(>object, NVIF_OUTP_V0_RELEASE, NULL, 0);
+   NVIF_ERRON(ret, >object, "[RELEASE]");
+   outp->or.id = -1;
+}
+
+static inline int
+nvif_outp_acquire(struct nvif_outp *outp, u8 proto, struct 
nvif_outp_acquire_v0 *args)
 {
-   struct nvif_outp_acquire_v0 args;
int ret;
 
-   args.tmds.head = head;
-   args.tmds.hdmi = hdmi;
-   args.tmds.hdmi_max_ac_packet = max_ac_packet;
-   args.tmds.hdmi_rekey = rekey;
-   args.tmds.hdmi_scdc = scdc;
-   args.tmds.hdmi_hda = hda;
+   args->version = 0;
+   args->proto = proto;
 
-   ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_TMDS, );
-   NVIF_ERRON(ret, >object,
-  "[ACQUIRE proto:TMDS head:%d 

[PATCH v3 09/44] drm/nouveau/disp: rename internal output acquire/release functions

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

These will be made static later in the patch series, after the code that
uses them has been cleaned up in preparation for GSP-RM support.

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c  | 10 --
 drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h  |  5 +++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 16 
 3 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
index fb061144438dc..3ed93df475fcc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
@@ -89,7 +89,7 @@ nvkm_outp_xlat(struct nvkm_outp *outp, enum nvkm_ior_type 
*type)
 }
 
 void
-nvkm_outp_release(struct nvkm_outp *outp, u8 user)
+nvkm_outp_release_or(struct nvkm_outp *outp, u8 user)
 {
struct nvkm_ior *ior = outp->ior;
OUTP_TRACE(outp, "release %02x &= %02x %p", outp->acquired, ~user, ior);
@@ -142,7 +142,7 @@ nvkm_outp_acquire_hda(struct nvkm_outp *outp, enum 
nvkm_ior_type type,
 }
 
 int
-nvkm_outp_acquire(struct nvkm_outp *outp, u8 user, bool hda)
+nvkm_outp_acquire_or(struct nvkm_outp *outp, u8 user, bool hda)
 {
struct nvkm_ior *ior = outp->ior;
enum nvkm_ior_proto proto;
@@ -234,6 +234,12 @@ nvkm_outp_detect(struct nvkm_outp *outp)
return ret;
 }
 
+void
+nvkm_outp_release(struct nvkm_outp *outp)
+{
+   nvkm_outp_release_or(outp, NVKM_OUTP_USER);
+}
+
 void
 nvkm_outp_fini(struct nvkm_outp *outp)
 {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
index 1cd70868f2255..76d83fb9c6e59 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
@@ -77,8 +77,9 @@ void nvkm_outp_fini(struct nvkm_outp *);
 
 int nvkm_outp_detect(struct nvkm_outp *);
 
-int nvkm_outp_acquire(struct nvkm_outp *, u8 user, bool hda);
-void nvkm_outp_release(struct nvkm_outp *, u8 user);
+int nvkm_outp_acquire_or(struct nvkm_outp *, u8 user, bool hda);
+void nvkm_outp_release(struct nvkm_outp *);
+void nvkm_outp_release_or(struct nvkm_outp *, u8 user);
 void nvkm_outp_route(struct nvkm_disp *);
 
 struct nvkm_outp_func {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index 0c4ffa3ffb288..828db77af242b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -141,7 +141,7 @@ nvkm_uoutp_mthd_release(struct nvkm_outp *outp, void *argv, 
u32 argc)
ior->func->hdmi->ctrl(ior, head->id, false, 0, 0);
}
 
-   nvkm_outp_release(outp, NVKM_OUTP_USER);
+   nvkm_outp_release(outp);
return 0;
 }
 
@@ -151,7 +151,7 @@ nvkm_uoutp_mthd_acquire_dp(struct nvkm_outp *outp, u8 
dpcd[DP_RECEIVER_CAP_SIZE]
 {
int ret;
 
-   ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, hda);
+   ret = nvkm_outp_acquire_or(outp, NVKM_OUTP_USER, hda);
if (ret)
return ret;
 
@@ -172,7 +172,7 @@ nvkm_uoutp_mthd_acquire_tmds(struct nvkm_outp *outp, u8 
head, u8 hdmi, u8 hdmi_m
if (!(outp->asy.head = nvkm_head_find(outp->disp, head)))
return -EINVAL;
 
-   ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, hdmi && hdmi_hda);
+   ret = nvkm_outp_acquire_or(outp, NVKM_OUTP_USER, hdmi && hdmi_hda);
if (ret)
return ret;
 
@@ -182,7 +182,7 @@ nvkm_uoutp_mthd_acquire_tmds(struct nvkm_outp *outp, u8 
head, u8 hdmi, u8 hdmi_m
if (!ior->func->hdmi ||
hdmi_max_ac_packet > 0x1f || hdmi_rekey > 0x7f ||
(hdmi_scdc && !ior->func->hdmi->scdc)) {
-   nvkm_outp_release(outp, NVKM_OUTP_USER);
+   nvkm_outp_release_or(outp, NVKM_OUTP_USER);
return -EINVAL;
}
 
@@ -203,7 +203,7 @@ nvkm_uoutp_mthd_acquire_lvds(struct nvkm_outp *outp, bool 
dual, bool bpc8)
outp->lvds.dual = dual;
outp->lvds.bpc8 = bpc8;
 
-   return nvkm_outp_acquire(outp, NVKM_OUTP_USER, false);
+   return nvkm_outp_acquire_or(outp, NVKM_OUTP_USER, false);
 }
 
 static int
@@ -219,7 +219,7 @@ nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, 
u32 argc)
 
switch (args->v0.proto) {
case NVIF_OUTP_ACQUIRE_V0_RGB_CRT:
-   ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, false);
+   ret = nvkm_outp_acquire_or(outp, NVKM_OUTP_USER, false);
break;
case NVIF_OUTP_ACQUIRE_V0_TMDS:
ret = nvkm_uoutp_mthd_acquire_tmds(outp, args->v0.tmds.head,
@@ -261,7 +261,7 @@ nvkm_uoutp_mthd_load_dete

[PATCH v3 10/44] drm/nouveau/kms: Add INHERIT ioctl to nvkm/nvif for reading IOR state

2023-09-19 Thread Lyude Paul
Now that we're supporting things like Ada and the GSP, there's situations
where we really need to actually know the display state that we're starting
with when loading the driver in order to prevent breaking GSP expectations.
The first step in doing this is making it so that we can read the current
state of IORs from nvkm in DRM, so that we can fill in said into into the
atomic state.

We do this by introducing an INHERIT ioctl to nvkm/nvif. This is basically
another form of ACQUIRE, except that it will only acquire the given output
path for userspace if it's already set up in hardware. This way, we can go
through and probe each outp object we have in DRM in order to figure out
the current hardware state of each one. If the outp isn't in use, it simply
returns -ENODEV.

This is also part of the work that will be required for implementing GSP
support for display. While the GSP should mostly work without this commit,
this commit should fix some edge case bugs that can occur on initial driver
load. This also paves the way for some of the initial groundwork for
fastboot support.

Signed-off-by: Lyude Paul 
Signed-off-by: Ben Skeggs 
Acked-by: Danilo Krummrich 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 101 ++
 drivers/gpu/drm/nouveau/include/nvif/if0012.h |  23 
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |   5 +
 drivers/gpu/drm/nouveau/nvif/outp.c   |  68 
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c |   1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.c   |  39 ---
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.h   |   3 +
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  |  64 +++
 8 files changed, 291 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 889ff667d0293..290f3c80ba4eb 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -2519,6 +2519,104 @@ nv50_display_fini(struct drm_device *dev, bool runtime, 
bool suspend)
cancel_work_sync(>hpd_work);
 }
 
+static inline void
+nv50_display_read_hw_or_state(struct drm_device *dev, struct nv50_disp *disp,
+ struct nouveau_encoder *outp)
+{
+   struct drm_crtc *crtc;
+   struct drm_connector_list_iter conn_iter;
+   struct drm_connector *conn;
+   struct nv50_head_atom *armh;
+   const u32 encoder_mask = drm_encoder_mask(>base.base);
+   bool found_conn = false, found_head = false;
+   u8 proto;
+   int head_idx;
+   int ret;
+
+   switch (outp->dcb->type) {
+   case DCB_OUTPUT_TMDS:
+   ret = nvif_outp_inherit_tmds(>outp, );
+   break;
+   case DCB_OUTPUT_DP:
+   ret = nvif_outp_inherit_dp(>outp, );
+   break;
+   case DCB_OUTPUT_LVDS:
+   ret = nvif_outp_inherit_lvds(>outp, );
+   break;
+   case DCB_OUTPUT_ANALOG:
+   ret = nvif_outp_inherit_rgb_crt(>outp, );
+   break;
+   default:
+   drm_dbg_kms(dev, "Readback for %s not implemented yet, 
skipping\n",
+   outp->base.base.name);
+   drm_WARN_ON(dev, true);
+   return;
+   }
+
+   if (ret < 0)
+   return;
+
+   head_idx = ret;
+
+   drm_for_each_crtc(crtc, dev) {
+   if (crtc->index != head_idx)
+   continue;
+
+   armh = nv50_head_atom(crtc->state);
+   found_head = true;
+   break;
+   }
+   if (drm_WARN_ON(dev, !found_head))
+   return;
+
+   /* Figure out which connector is being used by this encoder */
+   drm_connector_list_iter_begin(dev, _iter);
+   nouveau_for_each_non_mst_connector_iter(conn, _iter) {
+   if (nouveau_connector(conn)->index == outp->dcb->connector) {
+   found_conn = true;
+   break;
+   }
+   }
+   drm_connector_list_iter_end(_iter);
+   if (drm_WARN_ON(dev, !found_conn))
+   return;
+
+   armh->state.encoder_mask = encoder_mask;
+   armh->state.connector_mask = drm_connector_mask(conn);
+   armh->state.active = true;
+   armh->state.enable = true;
+   pm_runtime_get_noresume(dev->dev);
+
+   outp->crtc = crtc;
+   outp->ctrl = NVVAL(NV507D, SOR_SET_CONTROL, PROTOCOL, proto) | 
BIT(crtc->index);
+
+   drm_connector_get(conn);
+   conn->state->crtc = crtc;
+   conn->state->best_encoder = >base.base;
+}
+
+/* Read back the currently programmed display state */
+static void
+nv50_display_read_hw_state(struct nouveau_drm *drm)
+{
+   struct drm_device *dev = drm->dev;
+   struct drm_encoder *encoder;
+   struct drm_modeset_acquire_ctx ctx;
+   struct nv50_di

[PATCH v3 07/44] drm/nouveau/disp: add output detect method

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

This will check the relevant hotplug pin and skip the DDC probe we
currently do if a display is present.

- preparation for GSP-RM.

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/include/nvif/conn.h   |  5 --
 drivers/gpu/drm/nouveau/include/nvif/if0011.h | 11 
 drivers/gpu/drm/nouveau/include/nvif/if0012.h | 12 
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |  9 +++
 drivers/gpu/drm/nouveau/nouveau_connector.c   | 60 ---
 drivers/gpu/drm/nouveau/nouveau_dp.c  | 10 +---
 drivers/gpu/drm/nouveau/nvif/conn.c   | 14 -
 drivers/gpu/drm/nouveau/nvif/outp.c   | 25 
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.c   | 28 +
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.h   |  6 ++
 .../gpu/drm/nouveau/nvkm/engine/disp/uconn.c  | 41 -
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  | 24 
 13 files changed, 145 insertions(+), 101 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvif/conn.h 
b/drivers/gpu/drm/nouveau/include/nvif/conn.h
index dc355e1dfafa0..8a6017a358976 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/conn.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/conn.h
@@ -18,11 +18,6 @@ nvif_conn_id(struct nvif_conn *conn)
return conn->object.handle;
 }
 
-#define NVIF_CONN_HPD_STATUS_UNSUPPORTED 0 /* negative if query fails */
-#define NVIF_CONN_HPD_STATUS_NOT_PRESENT 1
-#define NVIF_CONN_HPD_STATUS_PRESENT 2
-int nvif_conn_hpd_status(struct nvif_conn *);
-
 int nvif_conn_event_ctor(struct nvif_conn *, const char *name, 
nvif_event_func, u8 types,
 struct nvif_event *);
 #endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0011.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0011.h
index 69b0b779f9424..0c25288a5a789 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0011.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0011.h
@@ -20,15 +20,4 @@ union nvif_conn_event_args {
__u8 pad02[6];
} v0;
 };
-
-#define NVIF_CONN_V0_HPD_STATUS 0x
-
-union nvif_conn_hpd_status_args {
-   struct nvif_conn_hpd_status_v0 {
-   __u8 version;
-   __u8 support;
-   __u8 present;
-   __u8 pad03[5];
-   } v0;
-};
 #endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index 7c56f653070c9..923bc30af2a92 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -12,6 +12,8 @@ union nvif_outp_args {
} v0;
 };
 
+#define NVIF_OUTP_V0_DETECT0x00
+
 #define NVIF_OUTP_V0_ACQUIRE   0x11
 #define NVIF_OUTP_V0_RELEASE   0x12
 
@@ -24,6 +26,16 @@ union nvif_outp_args {
 #define NVIF_OUTP_V0_DP_RETRAIN0x73
 #define NVIF_OUTP_V0_DP_MST_VCPI   0x78
 
+union nvif_outp_detect_args {
+   struct nvif_outp_detect_v0 {
+   __u8 version;
+#define NVIF_OUTP_DETECT_V0_NOT_PRESENT 0x00
+#define NVIF_OUTP_DETECT_V0_PRESENT 0x01
+#define NVIF_OUTP_DETECT_V0_UNKNOWN 0x02
+   __u8 status;
+   } v0;
+};
+
 union nvif_outp_load_detect_args {
struct nvif_outp_load_detect_v0 {
__u8  version;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h 
b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index fa76a7b5e4b37..c3e1e4d2f1a11 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -17,6 +17,15 @@ struct nvif_outp {
 
 int nvif_outp_ctor(struct nvif_disp *, const char *name, int id, struct 
nvif_outp *);
 void nvif_outp_dtor(struct nvif_outp *);
+
+enum nvif_outp_detect_status {
+   NOT_PRESENT,
+   PRESENT,
+   UNKNOWN,
+};
+
+enum nvif_outp_detect_status nvif_outp_detect(struct nvif_outp *);
+
 int nvif_outp_load_detect(struct nvif_outp *, u32 loadval);
 int nvif_outp_acquire_rgb_crt(struct nvif_outp *);
 int nvif_outp_acquire_tmds(struct nvif_outp *, int head,
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 68b4fb4bec63f..a290a2844547c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -413,6 +413,7 @@ nouveau_connector_ddc_detect(struct drm_connector 
*connector)
 {
struct drm_device *dev = connector->dev;
struct pci_dev *pdev = to_pci_dev(dev->dev);
+   struct nouveau_connector *conn = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = NULL, *found = NULL;
struct drm_encoder *encoder;
int ret;
@@ -421,33 +422,48 @@ nouveau_connector_ddc_detect(struct drm_connector 
*connector)
drm_connector_for_each_possible_encoder(connector, encoder) {
nv_encoder = nouveau_encoder(encoder);
 
-   switch (n

[PATCH v3 08/44] drm/nouveau/disp: add output method to fetch edid

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- needed to support TMDS EDID on RM

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/include/nvif/if0012.h | 10 +++
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |  1 +
 drivers/gpu/drm/nouveau/nouveau_connector.c   | 22 --
 drivers/gpu/drm/nouveau/nvif/outp.c   | 30 +++
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.h   |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  | 15 ++
 6 files changed, 70 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index 923bc30af2a92..725d6e8e3d2d3 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -13,6 +13,7 @@ union nvif_outp_args {
 };
 
 #define NVIF_OUTP_V0_DETECT0x00
+#define NVIF_OUTP_V0_EDID_GET  0x01
 
 #define NVIF_OUTP_V0_ACQUIRE   0x11
 #define NVIF_OUTP_V0_RELEASE   0x12
@@ -36,6 +37,15 @@ union nvif_outp_detect_args {
} v0;
 };
 
+union nvif_outp_edid_get_args {
+   struct nvif_outp_edid_get_v0 {
+   __u8  version;
+   __u8  pad01;
+   __u16 size;
+   __u8  data[2048];
+   } v0;
+};
+
 union nvif_outp_load_detect_args {
struct nvif_outp_load_detect_v0 {
__u8  version;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h 
b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index c3e1e4d2f1a11..7c2c34a84fbd8 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -25,6 +25,7 @@ enum nvif_outp_detect_status {
 };
 
 enum nvif_outp_detect_status nvif_outp_detect(struct nvif_outp *);
+int nvif_outp_edid_get(struct nvif_outp *, u8 **pedid);
 
 int nvif_outp_load_detect(struct nvif_outp *, u32 loadval);
 int nvif_outp_acquire_rgb_crt(struct nvif_outp *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index a290a2844547c..c079686fa2408 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -570,7 +570,6 @@ nouveau_connector_detect(struct drm_connector *connector, 
bool force)
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = NULL;
struct nouveau_encoder *nv_partner;
-   struct i2c_adapter *i2c;
int type;
int ret;
enum drm_connector_status conn_status = connector_status_disconnected;
@@ -593,15 +592,20 @@ nouveau_connector_detect(struct drm_connector *connector, 
bool force)
}
 
nv_encoder = nouveau_connector_ddc_detect(connector);
-   if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) {
-   struct edid *new_edid;
+   if (nv_encoder) {
+   struct edid *new_edid = NULL;
 
-   if ((vga_switcheroo_handler_flags() &
-VGA_SWITCHEROO_CAN_SWITCH_DDC) &&
-   nv_connector->type == DCB_CONNECTOR_LVDS)
-   new_edid = drm_get_edid_switcheroo(connector, i2c);
-   else
-   new_edid = drm_get_edid(connector, i2c);
+   if (nv_encoder->i2c) {
+   if ((vga_switcheroo_handler_flags() & 
VGA_SWITCHEROO_CAN_SWITCH_DDC) &&
+   nv_connector->type == DCB_CONNECTOR_LVDS)
+   new_edid = drm_get_edid_switcheroo(connector, 
nv_encoder->i2c);
+   else
+   new_edid = drm_get_edid(connector, 
nv_encoder->i2c);
+   } else {
+   ret = nvif_outp_edid_get(_encoder->outp, (u8 
**)_edid);
+   if (ret < 0)
+   return connector_status_disconnected;
+   }
 
nouveau_connector_set_edid(nv_connector, new_edid);
if (!nv_connector->edid) {
diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c 
b/drivers/gpu/drm/nouveau/nvif/outp.c
index 7f1daab35a0d2..10480142eea5a 100644
--- a/drivers/gpu/drm/nouveau/nvif/outp.c
+++ b/drivers/gpu/drm/nouveau/nvif/outp.c
@@ -210,6 +210,36 @@ nvif_outp_load_detect(struct nvif_outp *outp, u32 loadval)
return ret < 0 ? ret : args.load;
 }
 
+int
+nvif_outp_edid_get(struct nvif_outp *outp, u8 **pedid)
+{
+   struct nvif_outp_edid_get_v0 *args;
+   int ret;
+
+   args = kmalloc(sizeof(*args), GFP_KERNEL);
+   if (!args)
+   return -ENOMEM;
+
+   args->version = 0;
+
+   ret = nvif_mthd(>object, NVIF_OUTP_V0_EDID_GET, args, 
sizeof(*args));
+   NVIF_ERRON(ret, >object, "[EDID_GET] size:%d", args->size);
+   if (ret)
+   goto done;
+
+   *pedid = k

[PATCH v3 02/44] drm/nouveau/imem: support allocations not preserved across suspend

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

Will initially be used to tag some large grctx allocations which don't
need to be saved, to speedup suspend/resume.

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 .../drm/nouveau/include/nvkm/core/memory.h|  1 +
 .../drm/nouveau/include/nvkm/subdev/instmem.h |  2 +-
 drivers/gpu/drm/nouveau/nvkm/core/memory.c| 15 +--
 .../drm/nouveau/nvkm/subdev/instmem/base.c| 19 ++-
 .../drm/nouveau/nvkm/subdev/instmem/priv.h|  1 +
 5 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h 
b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h
index d3b6a68ddda36..fc0f389813916 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h
@@ -12,6 +12,7 @@ struct nvkm_tags {
 };
 
 enum nvkm_memory_target {
+   NVKM_MEM_TARGET_INST_SR_LOST, /* instance memory - not preserved across 
suspend */
NVKM_MEM_TARGET_INST, /* instance memory */
NVKM_MEM_TARGET_VRAM, /* video memory */
NVKM_MEM_TARGET_HOST, /* coherent system memory */
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h 
b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
index fcdaefc99fe85..92a36ddfc29ff 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
@@ -26,7 +26,7 @@ struct nvkm_instmem {
 
 u32 nvkm_instmem_rd32(struct nvkm_instmem *, u32 addr);
 void nvkm_instmem_wr32(struct nvkm_instmem *, u32 addr, u32 data);
-int nvkm_instobj_new(struct nvkm_instmem *, u32 size, u32 align, bool zero,
+int nvkm_instobj_new(struct nvkm_instmem *, u32 size, u32 align, bool zero, 
bool preserve,
 struct nvkm_memory **);
 int nvkm_instobj_wrap(struct nvkm_device *, struct nvkm_memory *, struct 
nvkm_memory **);
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/memory.c 
b/drivers/gpu/drm/nouveau/nvkm/core/memory.c
index c69daac9bac7b..a705c2dfca809 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/memory.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/memory.c
@@ -140,12 +140,23 @@ nvkm_memory_new(struct nvkm_device *device, enum 
nvkm_memory_target target,
 {
struct nvkm_instmem *imem = device->imem;
struct nvkm_memory *memory;
+   bool preserve = true;
int ret;
 
-   if (unlikely(target != NVKM_MEM_TARGET_INST || !imem))
+   if (unlikely(!imem))
return -ENOSYS;
 
-   ret = nvkm_instobj_new(imem, size, align, zero, );
+   switch (target) {
+   case NVKM_MEM_TARGET_INST_SR_LOST:
+   preserve = false;
+   break;
+   case NVKM_MEM_TARGET_INST:
+   break;
+   default:
+   return -ENOSYS;
+   }
+
+   ret = nvkm_instobj_new(imem, size, align, zero, preserve, );
if (ret)
return ret;
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
index e0e4f97be0294..24886eabe8dc3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
@@ -94,15 +94,21 @@ nvkm_instobj_wrap(struct nvkm_device *device,
  struct nvkm_memory *memory, struct nvkm_memory **pmemory)
 {
struct nvkm_instmem *imem = device->imem;
+   int ret;
 
if (!imem->func->memory_wrap)
return -ENOSYS;
 
-   return imem->func->memory_wrap(imem, memory, pmemory);
+   ret = imem->func->memory_wrap(imem, memory, pmemory);
+   if (ret)
+   return ret;
+
+   container_of(*pmemory, struct nvkm_instobj, memory)->preserve = true;
+   return 0;
 }
 
 int
-nvkm_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero,
+nvkm_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero, 
bool preserve,
 struct nvkm_memory **pmemory)
 {
struct nvkm_subdev *subdev = >subdev;
@@ -130,6 +136,7 @@ nvkm_instobj_new(struct nvkm_instmem *imem, u32 size, u32 
align, bool zero,
nvkm_done(memory);
}
 
+   container_of(memory, struct nvkm_instobj, memory)->preserve = preserve;
 done:
if (ret)
nvkm_memory_unref();
@@ -176,9 +183,11 @@ nvkm_instmem_fini(struct nvkm_subdev *subdev, bool suspend)
 
if (suspend) {
list_for_each_entry(iobj, >list, head) {
-   int ret = nvkm_instobj_save(iobj);
-   if (ret)
-   return ret;
+   if (iobj->preserve) {
+   int ret = nvkm_instobj_save(iobj);
+   if (ret)
+   return ret;
+   }
}
 
nvkm_bar_bar2_fin

[PATCH v3 04/44] drm/nouveau/mmu/gp100-: always invalidate TLBs at CACHE_LEVEL_ALL

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

Fixes some issues when running on top of RM.

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c | 2 +-
 drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c
index f3630d0e0d55d..bddac77f48f06 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c
@@ -558,7 +558,7 @@ gp100_vmm_invalidate_pdb(struct nvkm_vmm *vmm, u64 addr)
 void
 gp100_vmm_flush(struct nvkm_vmm *vmm, int depth)
 {
-   u32 type = (5 /* CACHE_LEVEL_UP_TO_PDE3 */ - depth) << 24;
+   u32 type = 0;
if (atomic_read(>engref[NVKM_SUBDEV_BAR]))
type |= 0x0004; /* HUB_ONLY */
type |= 0x0001; /* PAGE_ALL */
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c
index 6cb5eefa45e9a..0095d58d4d9a1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c
@@ -27,7 +27,7 @@ static void
 tu102_vmm_flush(struct nvkm_vmm *vmm, int depth)
 {
struct nvkm_device *device = vmm->mmu->subdev.device;
-   u32 type = (5 /* CACHE_LEVEL_UP_TO_PDE3 */ - depth) << 24;
+   u32 type = 0;
 
type |= 0x0001; /* PAGE_ALL */
if (atomic_read(>engref[NVKM_SUBDEV_BAR]))
-- 
2.41.0



[PATCH v3 06/44] drm/nouveau/disp: rearrange output methods

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

- preparation for a bunch of API changes, to make diffs prettier

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/include/nvif/if0012.h | 19 +++
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  | 12 ++--
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index 16d4ad5023a3e..7c56f653070c9 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -12,14 +12,17 @@ union nvif_outp_args {
} v0;
 };
 
-#define NVIF_OUTP_V0_LOAD_DETECT 0x00
-#define NVIF_OUTP_V0_ACQUIRE 0x01
-#define NVIF_OUTP_V0_RELEASE 0x02
-#define NVIF_OUTP_V0_INFOFRAME   0x03
-#define NVIF_OUTP_V0_HDA_ELD 0x04
-#define NVIF_OUTP_V0_DP_AUX_PWR  0x05
-#define NVIF_OUTP_V0_DP_RETRAIN  0x06
-#define NVIF_OUTP_V0_DP_MST_VCPI 0x07
+#define NVIF_OUTP_V0_ACQUIRE   0x11
+#define NVIF_OUTP_V0_RELEASE   0x12
+
+#define NVIF_OUTP_V0_LOAD_DETECT   0x20
+
+#define NVIF_OUTP_V0_INFOFRAME 0x60
+#define NVIF_OUTP_V0_HDA_ELD   0x61
+
+#define NVIF_OUTP_V0_DP_AUX_PWR0x70
+#define NVIF_OUTP_V0_DP_RETRAIN0x73
+#define NVIF_OUTP_V0_DP_MST_VCPI   0x78
 
 union nvif_outp_load_detect_args {
struct nvif_outp_load_detect_v0 {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index fc283a4a1522a..440ea52cc7d2b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -279,11 +279,11 @@ static int
 nvkm_uoutp_mthd_acquired(struct nvkm_outp *outp, u32 mthd, void *argv, u32 
argc)
 {
switch (mthd) {
-   case NVIF_OUTP_V0_RELEASE: return nvkm_uoutp_mthd_release(outp, 
argv, argc);
-   case NVIF_OUTP_V0_INFOFRAME  : return nvkm_uoutp_mthd_infoframe  (outp, 
argv, argc);
-   case NVIF_OUTP_V0_HDA_ELD: return nvkm_uoutp_mthd_hda_eld(outp, 
argv, argc);
-   case NVIF_OUTP_V0_DP_RETRAIN : return nvkm_uoutp_mthd_dp_retrain (outp, 
argv, argc);
-   case NVIF_OUTP_V0_DP_MST_VCPI: return nvkm_uoutp_mthd_dp_mst_vcpi(outp, 
argv, argc);
+   case NVIF_OUTP_V0_RELEASE  : return nvkm_uoutp_mthd_release  
(outp, argv, argc);
+   case NVIF_OUTP_V0_INFOFRAME: return nvkm_uoutp_mthd_infoframe
(outp, argv, argc);
+   case NVIF_OUTP_V0_HDA_ELD  : return nvkm_uoutp_mthd_hda_eld  
(outp, argv, argc);
+   case NVIF_OUTP_V0_DP_RETRAIN   : return nvkm_uoutp_mthd_dp_retrain   
(outp, argv, argc);
+   case NVIF_OUTP_V0_DP_MST_VCPI  : return nvkm_uoutp_mthd_dp_mst_vcpi  
(outp, argv, argc);
default:
break;
}
@@ -295,8 +295,8 @@ static int
 nvkm_uoutp_mthd_noacquire(struct nvkm_outp *outp, u32 mthd, void *argv, u32 
argc)
 {
switch (mthd) {
-   case NVIF_OUTP_V0_LOAD_DETECT: return nvkm_uoutp_mthd_load_detect(outp, 
argv, argc);
case NVIF_OUTP_V0_ACQUIRE: return nvkm_uoutp_mthd_acquire(outp, 
argv, argc);
+   case NVIF_OUTP_V0_LOAD_DETECT: return nvkm_uoutp_mthd_load_detect(outp, 
argv, argc);
case NVIF_OUTP_V0_DP_AUX_PWR : return nvkm_uoutp_mthd_dp_aux_pwr (outp, 
argv, argc);
default:
break;
-- 
2.41.0



[PATCH v3 05/44] drm/nouveau/kms/nv50-: fix mst payload alloc fail crashing evo

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

Programming -1 (vc_start_slot, if alloc fails) into HW probably isn't
the best idea.

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 39e9ba4139c7d..889ff667d0293 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -916,23 +916,27 @@ nv50_msto_prepare(struct drm_atomic_state *state,
struct nv50_mstc *mstc = msto->mstc;
struct nv50_mstm *mstm = mstc->mstm;
struct drm_dp_mst_atomic_payload *payload;
+   int ret = 0;
 
NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name);
 
payload = drm_atomic_get_mst_payload_state(mst_state, mstc->port);
 
-   // TODO: Figure out if we want to do a better job of handling VCPI 
allocation failures here?
if (msto->disabled) {
drm_dp_remove_payload_part1(mgr, mst_state, payload);
-
nvif_outp_dp_mst_vcpi(>outp->outp, 
msto->head->base.index, 0, 0, 0, 0);
+   ret = 1;
} else {
if (msto->enabled)
-   drm_dp_add_payload_part1(mgr, mst_state, payload);
+   ret = drm_dp_add_payload_part1(mgr, mst_state, payload);
+   }
 
+   if (ret == 0) {
nvif_outp_dp_mst_vcpi(>outp->outp, msto->head->base.index,
  payload->vc_start_slot, 
payload->time_slots,
  payload->pbn, payload->time_slots * 
mst_state->pbn_div);
+   } else {
+   nvif_outp_dp_mst_vcpi(>outp->outp, 
msto->head->base.index, 0, 0, 0, 0);
}
 }
 
-- 
2.41.0



[PATCH v3 03/44] drm/nouveau/gr/gf100-: lose contents of global ctxbufs across suspend

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

Some of these buffers are quite large, and there's no need to preserve
them across suspend.

Mark the contents as lost to speedup suspend/resume.

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
index 3648868bb9fc5..c494a1ff2d572 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -2032,18 +2032,18 @@ gf100_gr_oneinit(struct nvkm_gr *base)
}
 
/* Allocate global context buffers. */
-   ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 
gr->func->grctx->pagepool_size,
- 0x100, false, >pagepool);
+   ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST_SR_LOST,
+ gr->func->grctx->pagepool_size, 0x100, false, 
>pagepool);
if (ret)
return ret;
 
-   ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 
gr->func->grctx->bundle_size,
+   ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST_SR_LOST, 
gr->func->grctx->bundle_size,
  0x100, false, >bundle_cb);
if (ret)
return ret;
 
-   ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 
gr->func->grctx->attrib_cb_size(gr),
- 0x1000, false, >attrib_cb);
+   ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST_SR_LOST,
+ gr->func->grctx->attrib_cb_size(gr), 0x1000, 
false, >attrib_cb);
if (ret)
return ret;
 
-- 
2.41.0



[PATCH v3 00/44] drm/nouveau: initial support for GSP-RM 535.54.04 (and Ada GPUs)

2023-09-19 Thread Lyude Paul
Hey everyone! I'm just going through and rebasing Ben's display patches
so I can push them in just a moment :).

(*the rest of this email can be read in Ben Skegg's voice*)

The primary issue being tackled here is that, for historical reasons (we
didn't know any better / couldn't make it work reliably otherwise), some
operations (SOR routing, DP link training) were performed during the 2nd
HW supervisor interrupt.

We don't have control of the display supervisor when running on top of
RM, so this needed to be untangled and fixed - which, is one of the main
aims of this patch series.

The ordering of this series is pretty important, so take care if/when
backporting patches from it.

Beyond that main goal, various other interfaces have been added or
extended to provide the information that RM will need for its version of
similar interfaces.

Ben Skeggs (43):
  drm/nouveau/devinit/tu102-: remove attempt at loading PreOS
  drm/nouveau/imem: support allocations not preserved across suspend
  drm/nouveau/gr/gf100-: lose contents of global ctxbufs across suspend
  drm/nouveau/mmu/gp100-: always invalidate TLBs at CACHE_LEVEL_ALL
  drm/nouveau/kms/nv50-: fix mst payload alloc fail crashing evo
  drm/nouveau/disp: rearrange output methods
  drm/nouveau/disp: add output detect method
  drm/nouveau/disp: add output method to fetch edid
  drm/nouveau/disp: rename internal output acquire/release functions
  drm/nouveau/disp: shuffle to make upcoming diffs prettier
  drm/nouveau/disp: add acquire_dac()
  drm/nouveau/disp: add acquire_sor/pior()
  drm/nouveau/disp: update SOR routing immediately on acquire()
  drm/nouveau/kms/nv50-: pull some common init out of OR-specific code
  drm/nouveau/kms/nv50-: remove nv_encoder.audio.connector
  drm/nouveau/kms/nv50-: keep output state around until modeset complete
  drm/nouveau/kms/nv50-: move audio enable post-modeset
  drm/nouveau/disp: add output hdmi config method
  drm/nouveau/disp: move hdmi disable out of release()
  drm/nouveau/disp: release outputs post-modeset
  drm/nouveau/disp: remove SOR routing updates from supervisor
  drm/nouveau/disp: add output backlight control methods
  drm/nouveau/disp: add output lvds config method
  drm/nouveau/disp: add hdmi audio hal function
  drm/nouveau/disp: move dp aux pwr method to HAL
  drm/nouveau/disp: add dp aux xfer method
  drm/nouveau/disp: add dp rates method
  drm/nouveau/kms/nv50-: split DP disable+enable into two modesets
  drm/nouveau/kms/nv50-: flush mst disables together
  drm/nouveau/kms/nv50-: fixup sink D3 before tearing down link
  drm/nouveau/disp: add dp train method
  drm/nouveau/disp: move link training out of supervisor
  drm/nouveau/disp: add dp sst config method
  drm/nouveau/disp: add dp mst id get/put methods
  drm/nouveau/disp: move outp/conn construction to chipset code
  drm/nouveau/disp: move outp init/fini paths to chipset code
  drm/nouveau/disp/nv50-: skip DCB_OUTPUT_TV
  drm/nouveau/kms/nv50-: create heads based on nvkm head mask
  drm/nouveau/kms/nv50-: create heads after outps/conns
  drm/nouveau/kms/nv50-: name aux channels after their connector
  drm/nouveau/kms/nv50-: create connectors based on nvkm info
  drm/nouveau/kms/nv50-: create outputs based on nvkm info
  drm/nouveau/kms/nv50-: disable dcb parsing

Lyude Paul (1):
  drm/nouveau/kms: Add INHERIT ioctl to nvkm/nvif for reading IOR state

 drivers/gpu/drm/nouveau/dispnv04/disp.c   |   2 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 511 +++---
 drivers/gpu/drm/nouveau/dispnv50/disp.h   |   6 +-
 drivers/gpu/drm/nouveau/dispnv50/head.h   |   1 +
 drivers/gpu/drm/nouveau/dispnv50/headc57d.c   |  14 +
 drivers/gpu/drm/nouveau/include/nvif/conn.h   |  20 +-
 drivers/gpu/drm/nouveau/include/nvif/if0011.h |  21 +-
 drivers/gpu/drm/nouveau/include/nvif/if0012.h | 249 +++--
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |  96 +++-
 .../drm/nouveau/include/nvkm/core/memory.h|   1 +
 .../drm/nouveau/include/nvkm/subdev/instmem.h |   2 +-
 drivers/gpu/drm/nouveau/nouveau_backlight.c   |  90 +--
 drivers/gpu/drm/nouveau/nouveau_bios.c|   8 +-
 drivers/gpu/drm/nouveau/nouveau_connector.c   | 252 -
 drivers/gpu/drm/nouveau/nouveau_connector.h   |   3 +-
 drivers/gpu/drm/nouveau/nouveau_display.c |   8 +-
 drivers/gpu/drm/nouveau/nouveau_dp.c  | 345 ++--
 drivers/gpu/drm/nouveau/nouveau_encoder.h |  30 +-
 drivers/gpu/drm/nouveau/nvif/conn.c   |  36 +-
 drivers/gpu/drm/nouveau/nvif/disp.c   |   2 +-
 drivers/gpu/drm/nouveau/nvif/outp.c   | 412 --
 drivers/gpu/drm/nouveau/nvkm/core/memory.c|  15 +-
 .../gpu/drm/nouveau/nvkm/engine/disp/base.c   | 146 +
 .../gpu/drm/nouveau/nvkm/engine/disp/conn.c   |  10 -
 .../gpu/drm/nouveau/nvkm/engine/disp/conn.h   |   2 -
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 362 -
 .../gpu/drm/nouveau/nvkm/engine/disp/g84.c|   1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/g94.c|   1

[PATCH v3 01/44] drm/nouveau/devinit/tu102-: remove attempt at loading PreOS

2023-09-19 Thread Lyude Paul
From: Ben Skeggs 

>From Turing, HW will already have handled this and locked-down the
falcon before we get control.  So this *should* be a no-op.

Signed-off-by: Ben Skeggs 
Reviewed-by: Lyude Paul 
Acked-by: Danilo Krummrich 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu102.c | 12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu102.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu102.c
index 81a1ad2c88a7e..40997ad1d101c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu102.c
@@ -83,17 +83,9 @@ tu102_devinit_wait(struct nvkm_device *device)
 }
 
 int
-tu102_devinit_post(struct nvkm_devinit *base, bool post)
+tu102_devinit_post(struct nvkm_devinit *init, bool post)
 {
-   struct nv50_devinit *init = nv50_devinit(base);
-   int ret;
-
-   ret = tu102_devinit_wait(init->base.subdev.device);
-   if (ret)
-   return ret;
-
-   gm200_devinit_preos(init, post);
-   return 0;
+   return tu102_devinit_wait(init->subdev.device);
 }
 
 static const struct nvkm_devinit_func
-- 
2.41.0



Re: [PATCH] nouveau/u_memcpya: fix NULL vs error pointer bug

2023-09-18 Thread Lyude Paul
Reviewed-by: Lyude Paul 

I assume you need me to push this to drm-misc?

On Fri, 2023-09-15 at 15:59 +0300, Dan Carpenter wrote:
> The u_memcpya() function is supposed to return error pointers on
> error.  Returning NULL will lead to an Oops.
> 
> Fixes: 68132cc6d1bc ("nouveau/u_memcpya: use vmemdup_user")
> Signed-off-by: Dan Carpenter 
> ---
>  drivers/gpu/drm/nouveau/nouveau_drv.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h 
> b/drivers/gpu/drm/nouveau/nouveau_drv.h
> index 3666a7403e47..52a708a98915 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
> @@ -193,7 +193,7 @@ u_memcpya(uint64_t user, unsigned int nmemb, unsigned int 
> size)
>   size_t bytes;
>  
>   if (unlikely(check_mul_overflow(nmemb, size, )))
> - return NULL;
> + return ERR_PTR(-ENOMEM);
>   return vmemdup_user(userptr, bytes);
>  }
>  

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH] drm/nouveau: sched: fix leaking memory of timedout job

2023-09-18 Thread Lyude Paul
BTW - Would you like me to review work like this? I'm totally happy to do
that, although I'm not terribly familiar with these parts of nouveau/drm (but
I'm always willing to learn, and would like to know more about these areas
anyway :)

…if the answer is yes, this patch looks fine to me so far - I guess the one
question I have that might have an obvious answer - how are jobs without an
job->ops->timeout callback cleaned up?

On Sat, 2023-09-16 at 18:28 +0200, Danilo Krummrich wrote:
> Always stop and re-start the scheduler in order to let the scheduler
> free up the timedout job in case it got signaled. In case of exec jobs
> the job type specific callback will take care to signal all fences and
> tear down the channel.
> 
> Fixes: b88baab82871 ("drm/nouveau: implement new VM_BIND uAPI")
> Signed-off-by: Danilo Krummrich 
> ---
>  drivers/gpu/drm/nouveau/nouveau_exec.c  |  2 +-
>  drivers/gpu/drm/nouveau/nouveau_sched.c | 12 +---
>  2 files changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c 
> b/drivers/gpu/drm/nouveau/nouveau_exec.c
> index 9c031d15fe0b..49d83ac9e036 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_exec.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_exec.c
> @@ -185,7 +185,7 @@ nouveau_exec_job_timeout(struct nouveau_job *job)
>  
>   nouveau_sched_entity_fini(job->entity);
>  
> - return DRM_GPU_SCHED_STAT_ENODEV;
> + return DRM_GPU_SCHED_STAT_NOMINAL;
>  }
>  
>  static struct nouveau_job_ops nouveau_exec_job_ops = {
> diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c 
> b/drivers/gpu/drm/nouveau/nouveau_sched.c
> index 88217185e0f3..3b7ea5221226 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_sched.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c
> @@ -375,14 +375,20 @@ nouveau_sched_run_job(struct drm_sched_job *sched_job)
>  static enum drm_gpu_sched_stat
>  nouveau_sched_timedout_job(struct drm_sched_job *sched_job)
>  {
> + struct drm_gpu_scheduler *sched = sched_job->sched;
>   struct nouveau_job *job = to_nouveau_job(sched_job);
> + enum drm_gpu_sched_stat stat = DRM_GPU_SCHED_STAT_NOMINAL;
>  
> - NV_PRINTK(warn, job->cli, "Job timed out.\n");
> + drm_sched_stop(sched, sched_job);
>  
>   if (job->ops->timeout)
> - return job->ops->timeout(job);
> + stat = job->ops->timeout(job);
> + else
> + NV_PRINTK(warn, job->cli, "Generic job timeout.\n");
> +
> + drm_sched_start(sched, true);
>  
> - return DRM_GPU_SCHED_STAT_ENODEV;
> + return stat;
>  }
>  
>  static void

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH 1/4] drm/dp_mst: Fix NULL dereference during payload addition

2023-09-15 Thread Lyude Paul
Thanks for catching all of this! for the whole series:

Reviewed-by: Lyude Paul 


On Thu, 2023-09-14 at 01:32 +0300, Imre Deak wrote:
> Fix the NULL dereference leading to the following stack trace:
> 
> [  129.687181] i915 :00:02.0: [drm:drm_dp_add_payload_part1 
> [drm_display_helper]] VCPI 1 for port 5be4423e not in topology, not 
> creating a payload to remote
> [  129.687257] BUG: kernel NULL pointer dereference, address: 0560
> [  129.694276] #PF: supervisor read access in kernel mode
> [  129.699459] #PF: error_code(0x) - not-present page
> [  129.704612] PGD 0 P4D 0
> [  129.707178] Oops:  [#1] PREEMPT SMP NOPTI
> [  129.711556] CPU: 2 PID: 1623 Comm: Xorg Tainted: G U 
> 6.6.0-rc1-imre+ #985
> [  129.719744] Hardware name: Intel Corporation Alder Lake Client 
> Platform/AlderLake-P DDR5 RVP, BIOS RPLPFWI1.R00.4035.A00.2301200723 
> 01/20/2023
> [  129.732509] RIP: 0010:drm_dp_mst_topology_put_port+0x19/0x170 
> [drm_display_helper]
> [  129.740111] Code: 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 
> 44 00 00 55 48 89 e5 41 57 41 56 41 55 41 54 53 48 89 fb 48 83 ec 08 <48> 8b 
> 87 60 05 00 00 44 8b 0f 48 8b 70 58 41 83 e9 01 48 85 f6 74
> [  129.758842] RSP: 0018:c90001daf900 EFLAGS: 00010286
> [  129.764104] RAX: 0001 RBX:  RCX: 
> 
> [  129.771246] RDX:  RSI: 9e73d613 RDI: 
> 
> [  129.778394] RBP: c90001daf930 R08:  R09: 
> 0020
> [  129.785533] R10: 0010 R11: 000f R12: 
> 888116c65e40
> [  129.792680] R13:  R14:  R15: 
> 
> [  129.799822] FS:  7f39f74b1a80() GS:88840f68() 
> knlGS:
> [  129.807913] CS:  0010 DS:  ES:  CR0: 80050033
> [  129.813670] CR2: 0560 CR3: 000138b88000 CR4: 
> 00750ee0
> [  129.820815] PKRU: 5554
> [  129.823551] Call Trace:
> [  129.826022]  
> [  129.828154]  ? show_regs+0x65/0x70
> [  129.831599]  ? __die+0x24/0x70
> [  129.834683]  ? page_fault_oops+0x160/0x480
> [  129.838824]  ? dev_printk_emit+0x83/0xb0
> [  129.842797]  ? do_user_addr_fault+0x2e2/0x680
> [  129.847175]  ? exc_page_fault+0x78/0x180
> [  129.851143]  ? asm_exc_page_fault+0x27/0x30
> [  129.855353]  ? drm_dp_mst_topology_put_port+0x19/0x170 [drm_display_helper]
> [  129.862354]  drm_dp_add_payload_part1+0x85/0x100 [drm_display_helper]
> [  129.868832]  intel_mst_pre_enable_dp+0x1ef/0x240 [i915]
> [  129.874170]  intel_encoders_pre_enable+0x83/0xa0 [i915]
> [  129.879524]  hsw_crtc_enable+0xbe/0x750 [i915]
> [  129.884095]  intel_enable_crtc+0x68/0xa0 [i915]
> [  129.888752]  skl_commit_modeset_enables+0x2c4/0x5d0 [i915]
> [  129.894365]  intel_atomic_commit_tail+0x765/0x1070 [i915]
> [  129.899885]  intel_atomic_commit+0x3ba/0x400 [i915]
> [  129.904892]  drm_atomic_commit+0x96/0xd0 [drm]
> [  129.909405]  ? __pfx___drm_printfn_info+0x10/0x10 [drm]
> [  129.914698]  drm_atomic_helper_set_config+0x7e/0xc0 [drm_kms_helper]
> [  129.921102]  drm_mode_setcrtc+0x5af/0x8d0 [drm]
> [  129.925695]  ? __pfx_drm_mode_setcrtc+0x10/0x10 [drm]
> [  129.930810]  drm_ioctl_kernel+0xc4/0x170 [drm]
> [  129.935317]  drm_ioctl+0x2a4/0x520 [drm]
> [  129.939305]  ? __pfx_drm_mode_setcrtc+0x10/0x10 [drm]
> [  129.944415]  ? __fget_light+0xa5/0x110
> [  129.948212]  __x64_sys_ioctl+0x98/0xd0
> [  129.951985]  do_syscall_64+0x37/0x90
> [  129.955581]  entry_SYSCALL_64_after_hwframe+0x6e/0xd8
> 
> Fixes: 5aa1dfcdf0a4 ("drm/mst: Refactor the flow for payload 
> allocation/removement")
> Cc: Wayne Lin 
> Cc: Lyude Paul 
> Cc: dri-devel@lists.freedesktop.org
> Signed-off-by: Imre Deak 
> ---
>  drivers/gpu/drm/display/drm_dp_mst_topology.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
> b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> index e04f87ff755ac..5f90860d49c34 100644
> --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> @@ -3341,7 +3341,8 @@ int drm_dp_add_payload_part1(struct 
> drm_dp_mst_topology_mgr *mgr,
>   (!allocate || ret < 0) ? DRM_DP_MST_PAYLOAD_ALLOCATION_LOCAL :
>   
> DRM_DP_MST_PAYLOAD_ALLOCATION_DFP;
>  
> - drm_dp_mst_topology_put_port(port);
> + if (port)
> + drm_dp_mst_topology_put_port(port);
>  
>   return ret;
>  }

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH] drm/nouveau/nvif: refactor deprecated strncpy

2023-09-15 Thread Lyude Paul
Reviewed-by: Lyude Paul 

Will push this and your other patches in just a moment

On Thu, 2023-09-14 at 21:30 +, Justin Stitt wrote:
> `strncpy` is deprecated and as such we should prefer more robust and
> less ambiguous string interfaces.
> 
> A suitable replacement is `strscpy_pad` due to the fact that it
> guarantees NUL-termination on the destination buffer whilst also
> maintaining the NUL-padding behavior that `strncpy` provides. I am not
> sure whether NUL-padding is strictly needed but I see in
> `nvif_object_ctor()` args is memcpy'd elsewhere so I figured we'd keep
> the same functionality.
> 
> Link: 
> https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings
>  [1]
> Link: https://github.com/KSPP/linux/issues/90
> Cc: linux-harden...@vger.kernel.org
> Signed-off-by: Justin Stitt 
> ---
> Note: build-tested only.
> ---
>  drivers/gpu/drm/nouveau/nvif/client.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nvif/client.c 
> b/drivers/gpu/drm/nouveau/nvif/client.c
> index a3264a0e933a..3a27245f467f 100644
> --- a/drivers/gpu/drm/nouveau/nvif/client.c
> +++ b/drivers/gpu/drm/nouveau/nvif/client.c
> @@ -69,7 +69,7 @@ nvif_client_ctor(struct nvif_client *parent, const char 
> *name, u64 device,
>   } nop = {};
>   int ret;
>  
> - strncpy(args.name, name, sizeof(args.name));
> + strscpy_pad(args.name, name, sizeof(args.name));
>   ret = nvif_object_ctor(parent != client ? >object : NULL,
>  name ? name : "nvifClient", 0,
>  NVIF_CLASS_CLIENT, , sizeof(args),
> 
> ---
> base-commit: 3669558bdf354cd352be955ef2764cde6a9bf5ec
> change-id: 20230914-strncpy-drivers-gpu-drm-nouveau-nvif-client-c-82b023c36953
> 
> Best regards,
> --
> Justin Stitt 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH] drm/nouveau/pm: refactor deprecated strncpy

2023-09-15 Thread Lyude Paul
...oops, responded to the wrong email :P

Reviewed-by: Lyude Paul 


On Thu, 2023-09-14 at 22:17 +, Justin Stitt wrote:
> `strncpy` is deprecated for use on NUL-terminated destination strings [1].
> 
> We should prefer more robust and less ambiguous string interfaces.
> 
> A suitable replacement is `strscpy` [2] due to the fact that it guarantees
> NUL-termination on the destination buffer without unnecessarily NUL-padding.
> 
> Link: 
> https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings
>  [1]
> Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html 
> [2]
> Link: https://github.com/KSPP/linux/issues/90
> Cc: linux-harden...@vger.kernel.org
> Signed-off-by: Justin Stitt 
> ---
>  drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c | 7 +++
>  1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c 
> b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
> index 8fe0444f761e..131db2645f84 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
> @@ -462,7 +462,7 @@ nvkm_perfmon_mthd_query_domain(struct nvkm_perfmon 
> *perfmon,
>  
>   args->v0.id = di;
>   args->v0.signal_nr  = nvkm_perfdom_count_perfsig(dom);
> - strncpy(args->v0.name, dom->name, sizeof(args->v0.name) - 1);
> + strscpy(args->v0.name, dom->name, sizeof(args->v0.name));
>  
>   /* Currently only global counters (PCOUNTER) are implemented
>* but this will be different for local counters (MP). */
> @@ -513,8 +513,7 @@ nvkm_perfmon_mthd_query_signal(struct nvkm_perfmon 
> *perfmon,
>   snprintf(args->v0.name, sizeof(args->v0.name),
>"/%s/%02x", dom->name, si);
>   } else {
> - strncpy(args->v0.name, sig->name,
> - sizeof(args->v0.name) - 1);
> + strscpy(args->v0.name, sig->name, 
> sizeof(args->v0.name));
>   }
>  
>   args->v0.signal = si;
> @@ -572,7 +571,7 @@ nvkm_perfmon_mthd_query_source(struct nvkm_perfmon 
> *perfmon,
>  
>   args->v0.source = sig->source[si];
>   args->v0.mask   = src->mask;
> - strncpy(args->v0.name, src->name, sizeof(args->v0.name) - 1);
> + strscpy(args->v0.name, src->name, sizeof(args->v0.name));
>   }
>  
>   if (++si < source_nr) {
> 
> ---
> base-commit: 3669558bdf354cd352be955ef2764cde6a9bf5ec
> change-id: 
> 20230914-strncpy-drivers-gpu-drm-nouveau-nvkm-engine-pm-base-c-38bf9c78bc0f
> 
> Best regards,
> --
> Justin Stitt 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH] drm/nouveau/core: refactor deprecated strncpy

2023-09-15 Thread Lyude Paul
Eek, I didn't realize how many instances of this we had. Thanks for doing this
:)

Reviewed-by: Lyude Paul 

On Thu, 2023-09-14 at 21:40 +, Justin Stitt wrote:
> `strncpy` is deprecated for use on NUL-terminated destination strings [1].
> 
> We should prefer more robust and less ambiguous string interfaces.
> 
> A suitable replacement is `strscpy` [2] due to the fact that it guarantees
> NUL-termination on the destination buffer without unnecessarily NUL-padding.
> 
> There is likely no bug in the current implementation due to the safeguard:
> > cname[sizeof(cname) - 1] = '\0';
> ... however we can provide simpler and easier to understand code using
> the newer (and recommended) `strscpy` api.
> 
> Link: 
> https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings
>  [1]
> Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html 
> [2]
> Link: https://github.com/KSPP/linux/issues/90
> Cc: linux-harden...@vger.kernel.org
> Signed-off-by: Justin Stitt 
> ---
>  drivers/gpu/drm/nouveau/nvkm/core/firmware.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c 
> b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
> index 91fb494d4009..374212da9e95 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
> @@ -79,8 +79,7 @@ nvkm_firmware_get(const struct nvkm_subdev *subdev, const 
> char *fwname, int ver,
>   int i;
>  
>   /* Convert device name to lowercase */
> - strncpy(cname, device->chip->name, sizeof(cname));
> - cname[sizeof(cname) - 1] = '\0';
> + strscpy(cname, device->chip->name, sizeof(cname));
>   i = strlen(cname);
>   while (i) {
>   --i;
> 
> ---
> base-commit: 3669558bdf354cd352be955ef2764cde6a9bf5ec
> change-id: 
> 20230914-strncpy-drivers-gpu-drm-nouveau-nvkm-core-firmware-c-791223838b72
> 
> Best regards,
> --
> Justin Stitt 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH] drm/nouveau/pm: refactor deprecated strncpy

2023-09-15 Thread Lyude Paul
Nice catch!

Reviewed-by: Lyude Paul 

Will push in just a moment

On Thu, 2023-09-14 at 21:59 -0700, Kees Cook wrote:
> On Thu, Sep 14, 2023 at 10:17:08PM +, Justin Stitt wrote:
> > `strncpy` is deprecated for use on NUL-terminated destination strings [1].
> > 
> > We should prefer more robust and less ambiguous string interfaces.
> > 
> > A suitable replacement is `strscpy` [2] due to the fact that it guarantees
> > NUL-termination on the destination buffer without unnecessarily NUL-padding.
> > 
> > Link: 
> > https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings
> >  [1]
> > Link: 
> > https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2]
> > Link: https://github.com/KSPP/linux/issues/90
> > Cc: linux-harden...@vger.kernel.org
> > Signed-off-by: Justin Stitt 
> 
> The "- 1" use in the original code is strong evidence for this being a
> sane conversion. :)
> 
> Reviewed-by: Kees Cook 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [Patch v2 2/3] drm/mst: Refactor the flow for payload allocation/removement

2023-08-31 Thread Lyude Paul
On Thu, 2023-08-24 at 04:12 +, Lin, Wayne wrote:
> [Public]
> 
> Hi Lyude,
> 
> I'm afraid that I don't have the permissions to push and would like to have
> your help. Thanks!

Whoops, sorry I only just noticed this message. I set a reminder on my phone
to bug me to push it tomorrow :), sorry about the delay

> 
> > -Original Message-
> > From: Lyude Paul 
> > Sent: Thursday, August 24, 2023 5:00 AM
> > To: Lin, Wayne ; dri-devel@lists.freedesktop.org;
> > amd-...@lists.freedesktop.org
> > Cc: jani.nik...@intel.com; ville.syrj...@linux.intel.com; 
> > imre.d...@intel.com;
> > Wentland, Harry ; Zuo, Jerry
> > 
> > Subject: Re: [Patch v2 2/3] drm/mst: Refactor the flow for payload
> > allocation/removement
> > 
> > Sure - you're also welcome to push the first two patches after fixing the
> > indentation if you'd like
> > 
> > On Wed, 2023-08-23 at 03:19 +, Lin, Wayne wrote:
> > > [Public]
> > > 
> > > Thanks, Lyude!
> > > Should I push another version to fix the indention?
> > > 
> > > > -Original Message-
> > > > From: Lyude Paul 
> > > > Sent: Friday, August 18, 2023 6:17 AM
> > > > To: Lin, Wayne ; dri-devel@lists.freedesktop.org;
> > > > amd-...@lists.freedesktop.org
> > > > Cc: jani.nik...@intel.com; ville.syrj...@linux.intel.com;
> > > > imre.d...@intel.com; Wentland, Harry ; Zuo,
> > > > Jerry 
> > > > Subject: Re: [Patch v2 2/3] drm/mst: Refactor the flow for payload
> > > > allocation/removement
> > > > 
> > > > Two small comments:
> > > > 
> > > > On Mon, 2023-08-07 at 10:56 +0800, Wayne Lin wrote:
> > > > > [Why]
> > > > > Today, the allocation/deallocation steps and status is a bit unclear.
> > > > > 
> > > > > For instance, payload->vc_start_slot = -1 stands for "the failure
> > > > > of updating DPCD payload ID table" and can also represent as
> > > > > "payload is not allocated yet". These two cases should be handled
> > > > > differently and hence better to distinguish them for better 
> > > > > understanding.
> > > > > 
> > > > > [How]
> > > > > Define enumeration - ALLOCATION_LOCAL, ALLOCATION_DFP and
> > > > > ALLOCATION_REMOTE to distinguish different allocation status.
> > > > > Adjust the code to handle different status accordingly for better
> > > > > understanding the sequence of payload allocation and payload
> > > > removement.
> > > > > 
> > > > > For payload creation, the procedure should look like this:
> > > > > DRM part 1:
> > > > > * step 1 - update sw mst mgr variables to add a new payload
> > > > > * step 2 - add payload at immediate DFP DPCD payload table
> > > > > 
> > > > > Driver:
> > > > > * Add new payload in HW and sync up with DFP by sending ACT
> > > > > 
> > > > > DRM Part 2:
> > > > > * Send ALLOCATE_PAYLOAD sideband message to allocate bandwidth
> > > > > along
> > > > the
> > > > >   virtual channel.
> > > > > 
> > > > > And as for payload removement, the procedure should look like this:
> > > > > DRM part 1:
> > > > > * step 1 - Send ALLOCATE_PAYLOAD sideband message to release
> > bandwidth
> > > > >along the virtual channel
> > > > > * step 2 - Clear payload allocation at immediate DFP DPCD payload
> > > > > table
> > > > > 
> > > > > Driver:
> > > > > * Remove the payload in HW and sync up with DFP by sending ACT
> > > > > 
> > > > > DRM part 2:
> > > > > * update sw mst mgr variables to remove the payload
> > > > > 
> > > > > Note that it's fine to fail when communicate with the branch
> > > > > device connected at immediate downstrean-facing port, but updating
> > > > > variables of SW mst mgr and HW configuration should be conducted
> > > > > anyway. That's because it's under commit_tail and we need to
> > > > > complete the HW
> > > > programming.
> > > > > 
> > > > > Changes since v1:
> > > > > * Remove the set but not use variable 'old_payload' in function
> > > > >   'nv50_msto_prepare'.

  1   2   3   4   5   6   7   8   9   10   >