Re: Multiple issues with radeondrm startup code

2022-02-13 Thread Ted Bullock




On 2022-02-14 12:50 a.m., Jonathan Gray wrote:

On Mon, Feb 14, 2022 at 12:05:44AM -0700, Ted Bullock wrote:


On 2022-02-13 11:02 p.m., Jonathan Gray wrote:

On Sun, Feb 13, 2022 at 12:22:38PM -0700, Ted Bullock wrote:

On 2022-02-12 6:46 p.m., Jonathan Gray wrote:

I will review further when you drop the function.


Alright try this again,


I have committed some parts of this, with one commit per specific issue.

pa_memex NULL test
sparc64 ifndef
drm_attach_pci return test

the result of pci_mapreg_type() is already fine as it does
_PCI_MAPREG_TYPEBITS() which which masks the bits

I still find this diff hard to follow as you are moving code around.
The arrays of bar information can be dropped.

When you cherrypicked fixes, you missed the for loop as per the initial
mail, the type checks are incorrect and won't match. You need the helper
macros since those types are bitmaps not types. This has been like this
since 1.71 (Oct 2020)

for (i = PCI_MAPREG_START; i < PCI_MAPREG_END; i += 4) {
type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, i);
if (type == PCI_MAPREG_TYPE_IO) {
 
pci_mapreg_map(pa, i, type, 0, NULL,
&rdev->rio_mem, NULL, &rdev->rio_mem_size, 0);
break;
}
if (type == PCI_MAPREG_MEM_TYPE_64BIT)
 
i += 4;
}


type = _PCI_MAPREG_TYPEBITS(pci_conf_read(pc, tag, reg));
if (type == 1) {
pci_mapreg_map();
break;
}
if (type == 4)
i += 4;

---

x = pci_conf_read(pc, tag, reg);
if ((x & 1) == 1)
type = x & 1;
else
type = x & 7;

if (type == 1) {
pci_mapreg_map();
break;
}
if (type == 4)
i += 4;

which other bits do you expect?

001 io space
000 32-bit mem space
100 64-bit mem space


See below quote


if (type == PCI_MAPREG_TYPE_IO) {
  
This is a bitmap, you cannot use it like this, the correct usage
would be PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO
pci_mapreg_map(pa, i, type, 0, NULL,
&rdev->rio_mem, NULL, &rdev->rio_mem_size, 0);
break;
}
if (type == PCI_MAPREG_MEM_TYPE_64BIT)

Same as above, this is incorrect usage
i += 4;


A note about this for loop. This loop was broken in revision 1.72 to
support radeon devices on POWER9 systems. These registers are available
(I believe) through the MMIO BAR so people haven't noticed that it's
broken.  I don't know if ALL devices work like that, though certainly
most do, if so this entire loop could possibly be removed and just rely
on MMIO access to these registers.




From my initial mail on the issues I saw. Is this incorrect and isn't 
PCI_MAPREG_TYPE needed for checking type? I think so, but maybe I'm wrong.


--
Ted Bullock 



Re: Multiple issues with radeondrm startup code

2022-02-13 Thread Jonathan Gray
On Mon, Feb 14, 2022 at 12:05:44AM -0700, Ted Bullock wrote:
> 
> On 2022-02-13 11:02 p.m., Jonathan Gray wrote:
> > On Sun, Feb 13, 2022 at 12:22:38PM -0700, Ted Bullock wrote:
> > > On 2022-02-12 6:46 p.m., Jonathan Gray wrote:
> > > > I will review further when you drop the function.
> > > 
> > > Alright try this again,
> > 
> > I have committed some parts of this, with one commit per specific issue.
> > 
> > pa_memex NULL test
> > sparc64 ifndef
> > drm_attach_pci return test
> > 
> > the result of pci_mapreg_type() is already fine as it does
> > _PCI_MAPREG_TYPEBITS() which which masks the bits
> > 
> > I still find this diff hard to follow as you are moving code around.
> > The arrays of bar information can be dropped.
> When you cherrypicked fixes, you missed the for loop as per the initial
> mail, the type checks are incorrect and won't match. You need the helper
> macros since those types are bitmaps not types. This has been like this
> since 1.71 (Oct 2020)
> 
> for (i = PCI_MAPREG_START; i < PCI_MAPREG_END; i += 4) {
>   type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, i);
>   if (type == PCI_MAPREG_TYPE_IO) {
> 
>   pci_mapreg_map(pa, i, type, 0, NULL,
>   &rdev->rio_mem, NULL, &rdev->rio_mem_size, 0);
>   break;
>   }
>   if (type == PCI_MAPREG_MEM_TYPE_64BIT)
> 
>   i += 4;
> }

type = _PCI_MAPREG_TYPEBITS(pci_conf_read(pc, tag, reg));
if (type == 1) {
pci_mapreg_map();
break;
}
if (type == 4)
i += 4;

---

x = pci_conf_read(pc, tag, reg);
if ((x & 1) == 1)
type = x & 1;
else
type = x & 7;

if (type == 1) {
pci_mapreg_map();
break;
}
if (type == 4)
i += 4;

which other bits do you expect?

001 io space
000 32-bit mem space
100 64-bit mem space



Re: Multiple issues with radeondrm startup code

2022-02-13 Thread Ted Bullock



On 2022-02-13 11:02 p.m., Jonathan Gray wrote:

On Sun, Feb 13, 2022 at 12:22:38PM -0700, Ted Bullock wrote:

On 2022-02-12 6:46 p.m., Jonathan Gray wrote:

I will review further when you drop the function.


Alright try this again,


I have committed some parts of this, with one commit per specific issue.

pa_memex NULL test
sparc64 ifndef
drm_attach_pci return test

the result of pci_mapreg_type() is already fine as it does
_PCI_MAPREG_TYPEBITS() which which masks the bits

I still find this diff hard to follow as you are moving code around.
The arrays of bar information can be dropped.
When you cherrypicked fixes, you missed the for loop as per the initial 
mail, the type checks are incorrect and won't match. You need the helper 
macros since those types are bitmaps not types. This has been like this 
since 1.71 (Oct 2020)


for (i = PCI_MAPREG_START; i < PCI_MAPREG_END; i += 4) {
type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, i);
if (type == PCI_MAPREG_TYPE_IO) {

pci_mapreg_map(pa, i, type, 0, NULL,
&rdev->rio_mem, NULL, &rdev->rio_mem_size, 0);
break;
}
if (type == PCI_MAPREG_MEM_TYPE_64BIT)

i += 4;
}

--
Ted Bullock 



Re: Multiple issues with radeondrm startup code

2022-02-13 Thread Jonathan Gray
On Sun, Feb 13, 2022 at 12:22:38PM -0700, Ted Bullock wrote:
> On 2022-02-12 6:46 p.m., Jonathan Gray wrote:
> > I will review further when you drop the function.
> 
> Alright try this again,

I have committed some parts of this, with one commit per specific issue.

pa_memex NULL test
sparc64 ifndef
drm_attach_pci return test

the result of pci_mapreg_type() is already fine as it does
_PCI_MAPREG_TYPEBITS() which which masks the bits

I still find this diff hard to follow as you are moving code around.
The arrays of bar information can be dropped.

> 
> diff b5c3be43fcdaf7cbd7d070c07746b451413f6b4a 
> 453e49da7f0804392d6d51fb578cfd8255f4fb77
> blob - a2d53f752bccb1ab54993ec2a7d5791ec2216e0a
> blob + f6353eb5f76e0ae0e21277f82e86b70b36dd401d
> --- sys/dev/pci/drm/radeon/radeon_kms.c
> +++ sys/dev/pci/drm/radeon/radeon_kms.c
> @@ -494,14 +494,13 @@ radeondrm_attach_kms(struct device *parent, struct dev
>   struct pci_attach_args  *pa = aux;
>   const struct pci_device_id *id_entry;
>   int  is_agp;
> - pcireg_t type;
> - int  i;
> - uint8_t  rmmio_bar;
>   paddr_t  fb_aper;
> -#if !defined(__sparc64__)
>   pcireg_t addr, mask;
> - int  s;
> -#endif
> + int  s, error;
> + uint8_t  i, mm;
> + pcireg_t type[6];
> + int  bar[6];
> + const uint8_tBAR[6] = {0x10,0x14,0x18,0x1C,0x20,0x24};
>  
>  #if defined(__sparc64__) || defined(__macppc__)
>   extern int fbnode;
> @@ -542,75 +541,115 @@ radeondrm_attach_kms(struct device *parent, struct dev
>  #endif
>  #endif
>  
> -#define RADEON_PCI_MEM   0x10
> + /* Start PCI BAR mappings */
> + bar[0] = pci_mapreg_probe(rdev->pc, rdev->pa_tag, BAR[0], &type[0]);
> + bar[1] = pci_mapreg_probe(rdev->pc, rdev->pa_tag, BAR[1], &type[1]);
> + bar[2] = pci_mapreg_probe(rdev->pc, rdev->pa_tag, BAR[2], &type[2]);
> + bar[3] = pci_mapreg_probe(rdev->pc, rdev->pa_tag, BAR[3], &type[3]);
> + bar[4] = pci_mapreg_probe(rdev->pc, rdev->pa_tag, BAR[4], &type[4]);
> + bar[5] = pci_mapreg_probe(rdev->pc, rdev->pa_tag, BAR[5], &type[5]);
>  
> - type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM);
> - if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
> - pci_mapreg_info(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM,
> - type, &rdev->fb_aper_offset, &rdev->fb_aper_size, NULL)) {
> - printf(": can't get frambuffer info\n");
> + /* Framebuffer offset is saved at BAR0 */
> + if (!bar[0] || PCI_MAPREG_TYPE(type[0]) != PCI_MAPREG_TYPE_MEM) {
> + printf(": BAR0 (framebuffer) is not memory mapped.\n");
> + radeon_fatal_error = 1;
>   return;
>   }
> -#if !defined(__sparc64__)
> +
> + error = pci_mapreg_info(rdev->pc, rdev->pa_tag, BAR[0],
> + type[0], &rdev->fb_aper_offset, &rdev->fb_aper_size, NULL);
> + if (error) {
> + printf(": Cannot get FB parameters from BAR0 (%d).\n", error);
> + radeon_fatal_error = 1;
> + return;
> + }
> +
>   if (rdev->fb_aper_offset == 0) {
>   bus_size_t start, end;
>   bus_addr_t base;
>  
> + KASSERT(pa->pa_memex != NULL);
> +
>   start = max(PCI_MEM_START, pa->pa_memex->ex_start);
>   end = min(PCI_MEM_END, pa->pa_memex->ex_end);
> - if (pa->pa_memex == NULL ||
> - extent_alloc_subregion(pa->pa_memex, start, end,
> - rdev->fb_aper_size, rdev->fb_aper_size, 0, 0, 0, &base)) {
> - printf(": can't reserve framebuffer space\n");
> +
> + error = extent_alloc_subregion(pa->pa_memex, start, end,
> + rdev->fb_aper_size, rdev->fb_aper_size, 0, 0, 0, &base);
> + if (error) {
> + printf(": Cannot allocate framebuffer (%d).\n", error);
> + radeon_fatal_error = 1;
>   return;
>   }
> - pci_conf_write(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM, base);
> - if (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT)
> - pci_conf_write(pa->pa_pc, pa->pa_tag,
> - RADEON_PCI_MEM + 4, (uint64_t)base >> 32);
> +
> + /* Set FB aperature to 32bit space for MI purposes */
> + switch (PCI_MAPREG_MEM_TYPE(type[0])) {
> + default:
> + printf(": Unhandled BAR0 memory type.\n");
> + radeon_fatal_error = 1;
> + return;
> + case PCI_MAPREG_MEM_TYPE_64BIT:
> + pci_conf_write(pa->pa_pc, pa->pa_tag, BAR[1], 0);
> + /* FALLTHROUGH */
> + case PCI_MAPREG_MEM_TYPE_32BIT:
> + pci_conf_wr

Re: Multiple issues with radeondrm startup code

2022-02-13 Thread Ted Bullock
On 2022-02-12 6:46 p.m., Jonathan Gray wrote:
> I will review further when you drop the function.

Alright try this again,

diff b5c3be43fcdaf7cbd7d070c07746b451413f6b4a 
453e49da7f0804392d6d51fb578cfd8255f4fb77
blob - a2d53f752bccb1ab54993ec2a7d5791ec2216e0a
blob + f6353eb5f76e0ae0e21277f82e86b70b36dd401d
--- sys/dev/pci/drm/radeon/radeon_kms.c
+++ sys/dev/pci/drm/radeon/radeon_kms.c
@@ -494,14 +494,13 @@ radeondrm_attach_kms(struct device *parent, struct dev
struct pci_attach_args  *pa = aux;
const struct pci_device_id *id_entry;
int  is_agp;
-   pcireg_t type;
-   int  i;
-   uint8_t  rmmio_bar;
paddr_t  fb_aper;
-#if !defined(__sparc64__)
pcireg_t addr, mask;
-   int  s;
-#endif
+   int  s, error;
+   uint8_t  i, mm;
+   pcireg_t type[6];
+   int  bar[6];
+   const uint8_tBAR[6] = {0x10,0x14,0x18,0x1C,0x20,0x24};
 
 #if defined(__sparc64__) || defined(__macppc__)
extern int fbnode;
@@ -542,75 +541,115 @@ radeondrm_attach_kms(struct device *parent, struct dev
 #endif
 #endif
 
-#define RADEON_PCI_MEM 0x10
+   /* Start PCI BAR mappings */
+   bar[0] = pci_mapreg_probe(rdev->pc, rdev->pa_tag, BAR[0], &type[0]);
+   bar[1] = pci_mapreg_probe(rdev->pc, rdev->pa_tag, BAR[1], &type[1]);
+   bar[2] = pci_mapreg_probe(rdev->pc, rdev->pa_tag, BAR[2], &type[2]);
+   bar[3] = pci_mapreg_probe(rdev->pc, rdev->pa_tag, BAR[3], &type[3]);
+   bar[4] = pci_mapreg_probe(rdev->pc, rdev->pa_tag, BAR[4], &type[4]);
+   bar[5] = pci_mapreg_probe(rdev->pc, rdev->pa_tag, BAR[5], &type[5]);
 
-   type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM);
-   if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
-   pci_mapreg_info(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM,
-   type, &rdev->fb_aper_offset, &rdev->fb_aper_size, NULL)) {
-   printf(": can't get frambuffer info\n");
+   /* Framebuffer offset is saved at BAR0 */
+   if (!bar[0] || PCI_MAPREG_TYPE(type[0]) != PCI_MAPREG_TYPE_MEM) {
+   printf(": BAR0 (framebuffer) is not memory mapped.\n");
+   radeon_fatal_error = 1;
return;
}
-#if !defined(__sparc64__)
+
+   error = pci_mapreg_info(rdev->pc, rdev->pa_tag, BAR[0],
+   type[0], &rdev->fb_aper_offset, &rdev->fb_aper_size, NULL);
+   if (error) {
+   printf(": Cannot get FB parameters from BAR0 (%d).\n", error);
+   radeon_fatal_error = 1;
+   return;
+   }
+
if (rdev->fb_aper_offset == 0) {
bus_size_t start, end;
bus_addr_t base;
 
+   KASSERT(pa->pa_memex != NULL);
+
start = max(PCI_MEM_START, pa->pa_memex->ex_start);
end = min(PCI_MEM_END, pa->pa_memex->ex_end);
-   if (pa->pa_memex == NULL ||
-   extent_alloc_subregion(pa->pa_memex, start, end,
-   rdev->fb_aper_size, rdev->fb_aper_size, 0, 0, 0, &base)) {
-   printf(": can't reserve framebuffer space\n");
+
+   error = extent_alloc_subregion(pa->pa_memex, start, end,
+   rdev->fb_aper_size, rdev->fb_aper_size, 0, 0, 0, &base);
+   if (error) {
+   printf(": Cannot allocate framebuffer (%d).\n", error);
+   radeon_fatal_error = 1;
return;
}
-   pci_conf_write(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM, base);
-   if (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT)
-   pci_conf_write(pa->pa_pc, pa->pa_tag,
-   RADEON_PCI_MEM + 4, (uint64_t)base >> 32);
+
+   /* Set FB aperature to 32bit space for MI purposes */
+   switch (PCI_MAPREG_MEM_TYPE(type[0])) {
+   default:
+   printf(": Unhandled BAR0 memory type.\n");
+   radeon_fatal_error = 1;
+   return;
+   case PCI_MAPREG_MEM_TYPE_64BIT:
+   pci_conf_write(pa->pa_pc, pa->pa_tag, BAR[1], 0);
+   /* FALLTHROUGH */
+   case PCI_MAPREG_MEM_TYPE_32BIT:
+   pci_conf_write(pa->pa_pc, pa->pa_tag, BAR[0], base);
+   }
rdev->fb_aper_offset = base;
}
-#endif
 
-   for (i = PCI_MAPREG_START; i < PCI_MAPREG_END; i += 4) {
-   type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, i);
-   if (type == PCI_MAPREG_TYPE_IO) {
-   pci_mapreg_map(pa, i, type, 0, NULL,
+   /* Search BARs for IO registers (if supported/available) usually BAR1 */
+   for (i = 0; i < 6; i++) {
+ 

Re: Multiple issues with radeondrm startup code

2022-02-12 Thread Jonathan Gray
On Sat, Feb 12, 2022 at 02:42:16PM -0700, Ted Bullock wrote:
> On 2022-02-11 7:16 p.m., Jonathan Gray wrote:
> > I'm not so keen on another function and putting bar information into
> >  local arrays seems odd.
> 
> Are there technical reasons for not wanting a function? I know that
> pulling in the linux kernel code is probably a big headache, does it
> have to do with that?

Look at other pci drivers and you will see they deal with
bars in attach.

> 
> As to the arrays, I chose to use a idiom for searching the BARs
> deliberately that (to me) reads as dramatically simpler and clearer. The
> BAR code already in tree for this driver is a mess with inline global
> defines sometimes, direct hex codes other times and assigned variables
> yet other times.

Drivers normally look at one bar and have a define for the offset
used in attach.  Iterating over bars and generation specific tests
aren't the norm.  The linux interfaces all want to deal with a bar
number instead of of offset.  For radeon linux does it in
radeon_device_init().

> 
> > It would be easier to review changes if you would stick to either 
> > changing or moving code, not both at the same time.
> 
> Yeah, moving/changing does make the review harder sorry about that :(
> 
> > For example when iterating over bars you lost the part that skips one
> > if a bar is 64-bit.
> 
> No. This was deliberate and not lost, I looked at this very carefully.
> 
> bar[i] && PCI_MAPREG_TYPE(type[i]) == PCI_MAPREG_TYPE_IO
> 
> This should not match to the top half of a 64bit memory mapped
> BAR, so having a special code to modify the loop to handle such a
> condition is just adding needless complexity.
> 
> For a memory BAR, bit 0 is always 0.
> For an IO BAR, bit 0 is 1.
> 
> Since this loop is explicitly searching for an IO bar, we should not
> need to handle MM semantics when searching, the simple match for the
> first bit should be enough. Is this incorrect?
> 
> > Generally bool is avoided in kernel code, it was added to not have
> > to change drm code.
> 
> No problem, the function is probably more correctly written with integer
> returns accurately describing problems from errno.h
> 
> > We use 'if (' not 'if(' as well.
> 
> Oops; I missed this despite staring at the code for a week.
> 
> Thanks for taking the time to review :) Much appreciated, tentatively I
> left the function in but with the changed return type and adjusted to
> your other notes, if it is a problem this can of course be amended.

I will review further when you drop the function.



Re: Multiple issues with radeondrm startup code

2022-02-12 Thread Ted Bullock
On 2022-02-11 7:16 p.m., Jonathan Gray wrote:
> On Fri, Feb 11, 2022 at 06:42:11PM -0700, Ted Bullock wrote:
>> 
>> There is more to this function that I think is problematic, 
>> especially from a MI point of view but I thought I would leave it 
>> off here. Below is a diff that resolves all my notes above. I 
>> generated the diff with the got tool, so if it doesn't apply I 
>> definitely blame stephan :P
>> 
>> Some words on how I approached this. Many of the failures tested 
>> here need to be followed by radeon_fatal_error = 1 so I moved all 
>> the BAR fiddling into it's own function with a single check.
>> 
>> I don't know if its really worth checking for IO registers, this 
>> has been broken for a few years now and nobody noticed.
>> 
>> I also don't know if its worth checking for 64bit FB BARs, I 
>> couldn't find any examples of such a radeon devices, but I left
>> the logic in because the original writers thought it was worth 
>> handling. In either case the BAR is mapped in 32bit space to keep 
>> it MI for 32bit arch.
>> 
>> Using pci_mapreg_probe like I have done here seems like a much 
>> stronger idiom for device polling, especially for devices that may 
>> be shaped all weird like the massive number of radeon parts this 
>> matches too. I am aware there is toctou implications with how far 
>> pci_mapreg_probe is from when it's used; does this matter on pcie 
>> devices?
>> 
>> pci_mapreg_probe.9 manpage is still incorrect, I sent a diff out a 
>> while back but it didn't manage to catch much attention.
>> 
>> I have tested this extensively on sparc64 with xvr-100, I believe 
>> it should work for all other arch too that use radeondrm. I don't 
>> have a POWER9 or PPC machine though, or a radeon x86 computer so 
>> that needs other peoples eyes.
>> 
>> This code doesn't exist upstream so we can be fairly abusive to it
>>  without making jonathans life any more difficult.
>> 
>> I have put many recent hours into reviewing my change here, I hope
>>  it's sufficiently not insane.
> 
> I'm not so keen on another function and putting bar information into
>  local arrays seems odd.

Are there technical reasons for not wanting a function? I know that
pulling in the linux kernel code is probably a big headache, does it
have to do with that?

As to the arrays, I chose to use a idiom for searching the BARs
deliberately that (to me) reads as dramatically simpler and clearer. The
BAR code already in tree for this driver is a mess with inline global
defines sometimes, direct hex codes other times and assigned variables
yet other times.

> It would be easier to review changes if you would stick to either 
> changing or moving code, not both at the same time.

Yeah, moving/changing does make the review harder sorry about that :(

> For example when iterating over bars you lost the part that skips one
> if a bar is 64-bit.

No. This was deliberate and not lost, I looked at this very carefully.

bar[i] && PCI_MAPREG_TYPE(type[i]) == PCI_MAPREG_TYPE_IO

This should not match to the top half of a 64bit memory mapped
BAR, so having a special code to modify the loop to handle such a
condition is just adding needless complexity.

For a memory BAR, bit 0 is always 0.
For an IO BAR, bit 0 is 1.

Since this loop is explicitly searching for an IO bar, we should not
need to handle MM semantics when searching, the simple match for the
first bit should be enough. Is this incorrect?

> Generally bool is avoided in kernel code, it was added to not have
> to change drm code.

No problem, the function is probably more correctly written with integer
returns accurately describing problems from errno.h

> We use 'if (' not 'if(' as well.

Oops; I missed this despite staring at the code for a week.

Thanks for taking the time to review :) Much appreciated, tentatively I
left the function in but with the changed return type and adjusted to
your other notes, if it is a problem this can of course be amended.

diff b5c3be43fcdaf7cbd7d070c07746b451413f6b4a 
ec22ab3eae34402e7c0b5269b98b531810553aa2
blob - a2d53f752bccb1ab54993ec2a7d5791ec2216e0a
blob + b367e6b0a0a6dce01389033fbd62ba2aa14455b4
--- sys/dev/pci/drm/radeon/radeon_kms.c
+++ sys/dev/pci/drm/radeon/radeon_kms.c
@@ -76,6 +76,9 @@ int   radeondrm_activate_kms(struct device *, int);
 void   radeondrm_attachhook(struct device *);
 intradeondrm_forcedetach(struct radeon_device *);
 
+/* KMS attach setup */
+intradeondrm_conf_bar(struct radeon_device *, struct pci_attach_args *);
+
 bool   radeon_msi_ok(struct radeon_device *);
 irqreturn_tradeon_driver_irq_handler_kms(void *);
 
@@ -486,6 +489,125 @@ out:
 }
 #endif
 
+/* Configure and map radeon registers */
+int
+radeondrm_conf_bar(struct radeon_device *rdev, struct pci_attach_args *pa)
+{ 
+   uint8_t  i, mm;
+   pcireg_t type[6];
+   int  bar[6];
+   const uint8_tBAR[6] = {0x10, 0x14, 0x18, 0x1C, 0x20, 0x24};
+   int  error;
+   
+ 

Re: Multiple issues with radeondrm startup code

2022-02-11 Thread Jonathan Gray
On Fri, Feb 11, 2022 at 06:42:11PM -0700, Ted Bullock wrote:
> Hey,
> 
> I've found some problems with the radeondrm initialization
> codepath (radeon_kms.c). Before I start, I should mention that I am
> working on some diffs to remove a bunch of the sparc64 MD ifdef's as
> well. In radeondrm_attach_kms:
> 
> starting from line 545
> ==
> #define RADEON_PCI_MEM0x10
> ^^ inline defines for bar registers reads as weird/bad to me
> 
>   type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM);
>   if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
>   pci_mapreg_info(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM,
>   type, &rdev->fb_aper_offset, &rdev->fb_aper_size, NULL)) {
>   printf(": can't get frambuffer info\n");
>   return;
> ^^
> Should set radeon_fatal_error = 1 before returning
>   }
> #if !defined(__sparc64__)
> ^^ I've tested this on sparc64 xvr-100, this ifdef isn't needed
>   if (rdev->fb_aper_offset == 0) {
>   bus_size_t start, end;
>   bus_addr_t base;
> 
>   start = max(PCI_MEM_START, pa->pa_memex->ex_start);
> Potential NULL dereference ->
>   end = min(PCI_MEM_END, pa->pa_memex->ex_end);
> And here --->^^
>   if (pa->pa_memex == NULL ||
> 
> Obviously just move this NULL check up two lines
>   extent_alloc_subregion(pa->pa_memex, start, end,
>   rdev->fb_aper_size, rdev->fb_aper_size, 0, 0, 0, &base)) {
>   printf(": can't reserve framebuffer space\n");
>   return;
> ^^
> Should set radeon_fatal_error = 1 before returning
>   }
>   pci_conf_write(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM, base);
>   if (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT)
>   pci_conf_write(pa->pa_pc, pa->pa_tag,
>   RADEON_PCI_MEM + 4, (uint64_t)base >> 32);
> This evaluates to zero on all architectures --->
>   rdev->fb_aper_offset = base;
>   }
> #endif
> 
>   for (i = PCI_MAPREG_START; i < PCI_MAPREG_END; i += 4) {
> ^^
> This is an awkward (bad) idiom to iterate through BARs
>   type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, i);
>   if (type == PCI_MAPREG_TYPE_IO) {
> 
> This is a bitmap, you cannot use it like this, the correct usage
> would be PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO
> 
>   pci_mapreg_map(pa, i, type, 0, NULL,
>   &rdev->rio_mem, NULL, &rdev->rio_mem_size, 0);
>   break;
>   }
>   if (type == PCI_MAPREG_MEM_TYPE_64BIT)
>   
> Same as above, this is incorrect usage
>   i += 4;
>   }
> 
> A note about this for loop. This loop was broken in revision 1.72 to
> support radeon devices on POWER9 systems. These registers are available
> (I believe) through the MMIO BAR so people haven't noticed that it's
> broken.  I don't know if ALL devices work like that, though certainly
> most do, if so this entire loop could possibly be removed and just rely
> on MMIO access to these registers.
> 
>   if (rdev->family >= CHIP_BONAIRE) {
>   type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, 0x18);
>-->
> If putting an inline #define was appropriate earlier why not here
>   if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
>   pci_mapreg_map(pa, 0x18, type, BUS_SPACE_MAP_LINEAR, NULL,
> And here  >
>   &rdev->doorbell.bsh, &rdev->doorbell.base,
>   &rdev->doorbell.size, 0)) {
>   printf(": can't map doorbell space\n");
>   return;
>   ^^
> Should set radeon_fatal_error = 1 before returning
>   }
>   rdev->doorbell.ptr = bus_space_vaddr(rdev->memt,
>   rdev->doorbell.bsh);
>   }
> 
>   if (rdev->family >= CHIP_BONAIRE)
>   rmmio_bar = 0x24;
>   else
>   rmmio_bar = 0x18;
> 
>   type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, rmmio_bar);
>   if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
>   pci_mapreg_map(pa, rmmio_bar, type, BUS_SPACE_MAP_LINEAR, NULL,
>   &rdev->rmmio_bsh, &rdev->rmmio_base, &rdev->rmmio_size, 0)) {
>   printf(": can't map rmmio space\n");
>   return;
>   ^^
> Should set radeon_fatal_error = 1 before returning
>   }
>   rdev->rmmio = bus_space_vaddr(rdev->memt, rdev->rmmio_bsh);

Multiple issues with radeondrm startup code

2022-02-11 Thread Ted Bullock
Hey,

I've found some problems with the radeondrm initialization
codepath (radeon_kms.c). Before I start, I should mention that I am
working on some diffs to remove a bunch of the sparc64 MD ifdef's as
well. In radeondrm_attach_kms:

starting from line 545
==
#define RADEON_PCI_MEM  0x10
^^ inline defines for bar registers reads as weird/bad to me

type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM);
if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
pci_mapreg_info(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM,
type, &rdev->fb_aper_offset, &rdev->fb_aper_size, NULL)) {
printf(": can't get frambuffer info\n");
return;
^^
Should set radeon_fatal_error = 1 before returning
}
#if !defined(__sparc64__)
^^ I've tested this on sparc64 xvr-100, this ifdef isn't needed
if (rdev->fb_aper_offset == 0) {
bus_size_t start, end;
bus_addr_t base;

start = max(PCI_MEM_START, pa->pa_memex->ex_start);
Potential NULL dereference ->
end = min(PCI_MEM_END, pa->pa_memex->ex_end);
And here --->^^
if (pa->pa_memex == NULL ||

Obviously just move this NULL check up two lines
extent_alloc_subregion(pa->pa_memex, start, end,
rdev->fb_aper_size, rdev->fb_aper_size, 0, 0, 0, &base)) {
printf(": can't reserve framebuffer space\n");
return;
^^
Should set radeon_fatal_error = 1 before returning
}
pci_conf_write(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM, base);
if (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT)
pci_conf_write(pa->pa_pc, pa->pa_tag,
RADEON_PCI_MEM + 4, (uint64_t)base >> 32);
This evaluates to zero on all architectures --->
rdev->fb_aper_offset = base;
}
#endif

for (i = PCI_MAPREG_START; i < PCI_MAPREG_END; i += 4) {
^^
This is an awkward (bad) idiom to iterate through BARs
type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, i);
if (type == PCI_MAPREG_TYPE_IO) {

This is a bitmap, you cannot use it like this, the correct usage
would be PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO

pci_mapreg_map(pa, i, type, 0, NULL,
&rdev->rio_mem, NULL, &rdev->rio_mem_size, 0);
break;
}
if (type == PCI_MAPREG_MEM_TYPE_64BIT)

Same as above, this is incorrect usage
i += 4;
}

A note about this for loop. This loop was broken in revision 1.72 to
support radeon devices on POWER9 systems. These registers are available
(I believe) through the MMIO BAR so people haven't noticed that it's
broken.  I don't know if ALL devices work like that, though certainly
most do, if so this entire loop could possibly be removed and just rely
on MMIO access to these registers.

if (rdev->family >= CHIP_BONAIRE) {
type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, 0x18);
   -->
If putting an inline #define was appropriate earlier why not here
if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
pci_mapreg_map(pa, 0x18, type, BUS_SPACE_MAP_LINEAR, NULL,
And here  >
&rdev->doorbell.bsh, &rdev->doorbell.base,
&rdev->doorbell.size, 0)) {
printf(": can't map doorbell space\n");
return;
^^
Should set radeon_fatal_error = 1 before returning
}
rdev->doorbell.ptr = bus_space_vaddr(rdev->memt,
rdev->doorbell.bsh);
}

if (rdev->family >= CHIP_BONAIRE)
rmmio_bar = 0x24;
else
rmmio_bar = 0x18;

type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, rmmio_bar);
if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
pci_mapreg_map(pa, rmmio_bar, type, BUS_SPACE_MAP_LINEAR, NULL,
&rdev->rmmio_bsh, &rdev->rmmio_base, &rdev->rmmio_size, 0)) {
printf(": can't map rmmio space\n");
return;
^^
Should set radeon_fatal_error = 1 before returning
}
rdev->rmmio = bus_space_vaddr(rdev->memt, rdev->rmmio_bsh);

#if !defined(__sparc64__)
^
I've tested without this MD ifdef on sparc64, there is no adverse
behavior when using xvr-100 that I have noti