diff mbox series

[v3,i-g-t] lib/intel_mmio: Fix mmapped resources not unmapped on fini

Message ID 20220307082643.380066-1-janusz.krzysztofik@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series [v3,i-g-t] lib/intel_mmio: Fix mmapped resources not unmapped on fini | expand

Commit Message

Janusz Krzysztofik March 7, 2022, 8:26 a.m. UTC
Commit 5f3cfa485eb4 ("lib: Use safe wrappers around libpciaccess
initialization functions") took care of not leaking memory allocated by
pci_system_init() but didn't take care of users potentially attempting to
reinitialize global data maintained by libpciaccess.  For example,
intel_register_access_init() mmaps device's PCI BAR0 resource with
pci_device_map_range() but intel_register_access_fini() doesn't unmap it
and next call to intel_register_access_init() fails on attempt to mmap it
again.

Fix it, and also provide intel_mmio_unmap_*() counterparts to public
functions intel_mmio_use_pci_bar() and intel_mmio_use_dump_file().

v2: apply last minute fixes, cached but unfortunately not committed before
    sending
v3: use .pci_device_id field content as an indicator of arg initialization
    via intel_register_access_init(),
  - improve checks of argument initialization status,
  - shorten warning messages (Kamil),
  - don't fill .mmio_size field until initialization succeeds (Kamil)

Signed-off-by: Janusz Krzysztofik <janusz.krzysztofik@linux.intel.com>
Cc: Kamil Konieczny <kamil.konieczny@linux.intel.com>
---
 lib/intel_io.h   |  4 +++
 lib/intel_mmio.c | 64 +++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 65 insertions(+), 3 deletions(-)

Comments

Kamil Konieczny March 7, 2022, 1:23 p.m. UTC | #1
Hi Janusz,

Dnia 2022-03-07 at 09:26:43 +0100, Janusz Krzysztofik napisał(a):
> Commit 5f3cfa485eb4 ("lib: Use safe wrappers around libpciaccess
> initialization functions") took care of not leaking memory allocated by
> pci_system_init() but didn't take care of users potentially attempting to
> reinitialize global data maintained by libpciaccess.  For example,
> intel_register_access_init() mmaps device's PCI BAR0 resource with
> pci_device_map_range() but intel_register_access_fini() doesn't unmap it
> and next call to intel_register_access_init() fails on attempt to mmap it
> again.
> 
> Fix it, and also provide intel_mmio_unmap_*() counterparts to public
> functions intel_mmio_use_pci_bar() and intel_mmio_use_dump_file().
> 
> v2: apply last minute fixes, cached but unfortunately not committed before
>     sending
> v3: use .pci_device_id field content as an indicator of arg initialization
>     via intel_register_access_init(),
>   - improve checks of argument initialization status,
>   - shorten warning messages (Kamil),
>   - don't fill .mmio_size field until initialization succeeds (Kamil)
> 
> Signed-off-by: Janusz Krzysztofik <janusz.krzysztofik@linux.intel.com>
> Cc: Kamil Konieczny <kamil.konieczny@linux.intel.com>
> ---
>  lib/intel_io.h   |  4 +++
>  lib/intel_mmio.c | 64 +++++++++++++++++++++++++++++++++++++++++++++---
>  2 files changed, 65 insertions(+), 3 deletions(-)
> 
> diff --git a/lib/intel_io.h b/lib/intel_io.h
> index 1cfe4fb6b9..ea2649d9bc 100644
> --- a/lib/intel_io.h
> +++ b/lib/intel_io.h
> @@ -49,6 +49,8 @@ struct intel_register_map {
>  
>  struct intel_mmio_data {
>  	void *igt_mmio;
> +	size_t mmio_size;
> +	struct pci_device *dev;
>  	struct intel_register_map map;
>  	uint32_t pci_device_id;
>  	int key;
> @@ -57,7 +59,9 @@ struct intel_mmio_data {
>  
>  void intel_mmio_use_pci_bar(struct intel_mmio_data *mmio_data,
>  			    struct pci_device *pci_dev);
> +void intel_mmio_unmap_pci_bar(struct intel_mmio_data *mmio_data);
>  void intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file);
> +void intel_mmio_unmap_dump_file(struct intel_mmio_data *mmio_data);
>  
>  int intel_register_access_init(struct intel_mmio_data *mmio_data,
>  			       struct pci_device *pci_dev, int safe, int fd);
> diff --git a/lib/intel_mmio.c b/lib/intel_mmio.c
> index 667a69f5aa..d6ce0ee3ea 100644
> --- a/lib/intel_mmio.c
> +++ b/lib/intel_mmio.c
> @@ -82,6 +82,8 @@ void *igt_global_mmio;
>   * Sets also up mmio_data->igt_mmio to point at the data contained
>   * in @file. This allows the same code to get reused for dumping and decoding
>   * from running hardware as from register dumps.
> + *
> + * Users are expected to call intel_mmio_unmap_dump_file() after use.
>   */
>  void
>  intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file)
> @@ -99,11 +101,32 @@ intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file)
>  	igt_fail_on_f(mmio_data->igt_mmio == MAP_FAILED,
>  		      "Couldn't mmap %s\n", file);
>  
> +	mmio_data->mmio_size = st.st_size;
>  	igt_global_mmio = mmio_data->igt_mmio;
>  
>  	close(fd);
>  }
>  
> +/**
> + * intel_mmio_unmap_dump_file:
> + * @mmio_data:  mmio structure for IO operations
> + *
> + * Unmaps a dump file mmapped with intel_mmio_use_dump_file()
> + */
> +void intel_mmio_unmap_dump_file(struct intel_mmio_data *mmio_data)
> +{
> +	if (igt_warn_on_f(mmio_data->dev,
> +			  "test bug: arg initialized with intel_mmio_use_pci_bar()\n"))
> +		return;

Please add a global description about this kind of errors, this
one is for using unmap when mmio was mmap-ed from other mmap
type.

> +	if (igt_warn_on_f(!mmio_data->mmio_size,
> +			  "test bug: arg not initialized\n"))
> +		return;

Can we replace this with one check igt_global_mmio != NULL ?
Something like:

	if (igt_warn_on_f(!igt_global_mmio,
			  "mmio regs not mmap-ed\n"))
		return;

Or should we add this before all other checks in unmap functions
and keep this additional check ?

> +
> +	igt_global_mmio = NULL;
> +	igt_debug_on(munmap(mmio_data->igt_mmio, mmio_data->mmio_size) < 0);
> +	mmio_data->mmio_size = 0;
> +}
> +
>  /**
>   * intel_mmio_use_pci_bar:
>   * @mmio_data:  mmio structure for IO operations
> @@ -112,6 +135,8 @@ intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file)
>   * Fill a mmio_data stucture with igt_mmio to point at the mmio bar.
>   *
>   * @pci_dev can be obtained from intel_get_pci_device().
> + *
> + * Users are expected to call intel_mmio_unmap_pci_bar() after use.
>   */
>  void
>  intel_mmio_use_pci_bar(struct intel_mmio_data *mmio_data, struct pci_device *pci_dev)
> @@ -141,10 +166,34 @@ intel_mmio_use_pci_bar(struct intel_mmio_data *mmio_data, struct pci_device *pci
>  				      PCI_DEV_MAP_FLAG_WRITABLE,
>  				      &mmio_data->igt_mmio);
>  
> -	igt_global_mmio = mmio_data->igt_mmio;
> -
>  	igt_fail_on_f(error != 0,
>  		      "Couldn't map MMIO region\n");
> +
> +	mmio_data->mmio_size = mmio_size;
> +	mmio_data->dev = pci_dev;
> +	igt_global_mmio = mmio_data->igt_mmio;
> +}
> +
> +/**
> + * intel_mmio_unmap_pci_bar:
> + * @mmio_data:  mmio structure for IO operations
> + *
> + * Unmaps a PCI BAR region mmapped with intel_mmio_use_pci_bar()
> + */
> +void intel_mmio_unmap_pci_bar(struct intel_mmio_data *mmio_data)
> +{
> +	if (igt_warn_on_f(mmio_data->pci_device_id,
> +			  "test bug: arg initialized with intel_register_access_init()\n"))
> +		return;
> +	if (igt_warn_on_f(!mmio_data->dev,
> +			  "test bug: arg not initialized with intel_mmio_use_pci_bar()\n"))
> +		return;
> +
> +	igt_global_mmio = NULL;
> +	igt_debug_on(pci_device_unmap_range(mmio_data->dev,
> +					    mmio_data->igt_mmio, mmio_data->mmio_size) < 0);
> +	mmio_data->dev = NULL;
> +	mmio_data->mmio_size = 0;
>  }
>  
>  static void
> @@ -166,6 +215,8 @@ release_forcewake_lock(int fd)
>   * It also initializes mmio_data->igt_mmio like intel_mmio_use_pci_bar().
>   *
>   * @pci_dev can be obtained from intel_get_pci_device().
> + *
> + * Users are expected to call intel_register_access_fini() after use.
>   */
>  int
>  intel_register_access_init(struct intel_mmio_data *mmio_data, struct pci_device *pci_dev, int safe, int fd)
> @@ -222,8 +273,15 @@ int intel_register_access_needs_fakewake(struct intel_mmio_data *mmio_data)
>  void
>  intel_register_access_fini(struct intel_mmio_data *mmio_data)
>  {
> -	if (mmio_data->key && intel_register_access_needs_wake(mmio_data))
> +	if (igt_warn_on_f(!mmio_data->pci_device_id,
> +			  "test bug: arg not initialized with intel_register_access_init()\n"))
> +		return;
> +
> +	if (intel_register_access_needs_wake(mmio_data))
>  		release_forcewake_lock(mmio_data->key);
> +
> +	mmio_data->pci_device_id = 0;

Here we should check other conditions so no warn triggers in unmap_pci_bar
or make the messages generic (and document it in comments at beggining)
or maybe make helper with no checks for unmap_pci_bar.

> +	intel_mmio_unmap_pci_bar(mmio_data);
>  }
>  
>  /**
> -- 
> 2.25.1
>
Janusz Krzysztofik March 7, 2022, 3:06 p.m. UTC | #2
Hi Kamil,

On Monday, 7 March 2022 14:23:30 CET Kamil Konieczny wrote:
> Hi Janusz,
> 
> Dnia 2022-03-07 at 09:26:43 +0100, Janusz Krzysztofik napisał(a):
> > Commit 5f3cfa485eb4 ("lib: Use safe wrappers around libpciaccess
> > initialization functions") took care of not leaking memory allocated by
> > pci_system_init() but didn't take care of users potentially attempting to
> > reinitialize global data maintained by libpciaccess.  For example,
> > intel_register_access_init() mmaps device's PCI BAR0 resource with
> > pci_device_map_range() but intel_register_access_fini() doesn't unmap it
> > and next call to intel_register_access_init() fails on attempt to mmap it
> > again.
> > 
> > Fix it, and also provide intel_mmio_unmap_*() counterparts to public
> > functions intel_mmio_use_pci_bar() and intel_mmio_use_dump_file().
> > 
> > v2: apply last minute fixes, cached but unfortunately not committed before
> >     sending
> > v3: use .pci_device_id field content as an indicator of arg initialization
> >     via intel_register_access_init(),
> >   - improve checks of argument initialization status,
> >   - shorten warning messages (Kamil),
> >   - don't fill .mmio_size field until initialization succeeds (Kamil)
> > 
> > Signed-off-by: Janusz Krzysztofik <janusz.krzysztofik@linux.intel.com>
> > Cc: Kamil Konieczny <kamil.konieczny@linux.intel.com>
> > ---
> >  lib/intel_io.h   |  4 +++
> >  lib/intel_mmio.c | 64 +++++++++++++++++++++++++++++++++++++++++++++---
> >  2 files changed, 65 insertions(+), 3 deletions(-)
> > 
> > diff --git a/lib/intel_io.h b/lib/intel_io.h
> > index 1cfe4fb6b9..ea2649d9bc 100644
> > --- a/lib/intel_io.h
> > +++ b/lib/intel_io.h
> > @@ -49,6 +49,8 @@ struct intel_register_map {
> >  
> >  struct intel_mmio_data {
> >  	void *igt_mmio;
> > +	size_t mmio_size;
> > +	struct pci_device *dev;
> >  	struct intel_register_map map;
> >  	uint32_t pci_device_id;
> >  	int key;
> > @@ -57,7 +59,9 @@ struct intel_mmio_data {
> >  
> >  void intel_mmio_use_pci_bar(struct intel_mmio_data *mmio_data,
> >  			    struct pci_device *pci_dev);
> > +void intel_mmio_unmap_pci_bar(struct intel_mmio_data *mmio_data);
> >  void intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file);
> > +void intel_mmio_unmap_dump_file(struct intel_mmio_data *mmio_data);
> >  
> >  int intel_register_access_init(struct intel_mmio_data *mmio_data,
> >  			       struct pci_device *pci_dev, int safe, int fd);
> > diff --git a/lib/intel_mmio.c b/lib/intel_mmio.c
> > index 667a69f5aa..d6ce0ee3ea 100644
> > --- a/lib/intel_mmio.c
> > +++ b/lib/intel_mmio.c
> > @@ -82,6 +82,8 @@ void *igt_global_mmio;
> >   * Sets also up mmio_data->igt_mmio to point at the data contained
> >   * in @file. This allows the same code to get reused for dumping and decoding
> >   * from running hardware as from register dumps.
> > + *
> > + * Users are expected to call intel_mmio_unmap_dump_file() after use.
> >   */
> >  void
> >  intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file)
> > @@ -99,11 +101,32 @@ intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file)
> >  	igt_fail_on_f(mmio_data->igt_mmio == MAP_FAILED,
> >  		      "Couldn't mmap %s\n", file);
> >  
> > +	mmio_data->mmio_size = st.st_size;
> >  	igt_global_mmio = mmio_data->igt_mmio;
> >  
> >  	close(fd);
> >  }
> >  
> > +/**
> > + * intel_mmio_unmap_dump_file:
> > + * @mmio_data:  mmio structure for IO operations
> > + *
> > + * Unmaps a dump file mmapped with intel_mmio_use_dump_file()
> > + */
> > +void intel_mmio_unmap_dump_file(struct intel_mmio_data *mmio_data)
> > +{
> > +	if (igt_warn_on_f(mmio_data->dev,
> > +			  "test bug: arg initialized with intel_mmio_use_pci_bar()\n"))
> > +		return;
> 
> Please add a global description about this kind of errors, this
> one is for using unmap when mmio was mmap-ed from other mmap
> type.

Can you please be more specific in what you mean by "global description of 
this kind of errors"?  A more detailed warning?  A comment?  If the latter 
then how would you like me to make it global?

If you just don't like the reference to intel_mmio_use_pci_bar() here then 
would you be satisfied with something like "test bug: arg initialized by a 
method other than intel_mmio_use_dump_file()\n"?

> > +	if (igt_warn_on_f(!mmio_data->mmio_size,
> > +			  "test bug: arg not initialized\n"))
> > +		return;
> 
> Can we replace this with one check igt_global_mmio != NULL ?
> Something like:
> 
> 	if (igt_warn_on_f(!igt_global_mmio,
> 			  "mmio regs not mmap-ed\n"))
> 		return;
> 
> Or should we add this before all other checks in unmap functions
> and keep this additional check ?

Why igt_global_mmio again?  I still think this global variable is broken and 
users should just use the structure they pass to intel_mmio_use_*() or 
intel_register_access_init(), then introducing another a dependency on it with 
this patch doesn't make sense to me.  If you think the opposite then please 
explain why.

> > +
> > +	igt_global_mmio = NULL;
> > +	igt_debug_on(munmap(mmio_data->igt_mmio, mmio_data->mmio_size) < 0);
> > +	mmio_data->mmio_size = 0;
> > +}
> > +
> >  /**
> >   * intel_mmio_use_pci_bar:
> >   * @mmio_data:  mmio structure for IO operations
> > @@ -112,6 +135,8 @@ intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file)
> >   * Fill a mmio_data stucture with igt_mmio to point at the mmio bar.
> >   *
> >   * @pci_dev can be obtained from intel_get_pci_device().
> > + *
> > + * Users are expected to call intel_mmio_unmap_pci_bar() after use.
> >   */
> >  void
> >  intel_mmio_use_pci_bar(struct intel_mmio_data *mmio_data, struct pci_device *pci_dev)
> > @@ -141,10 +166,34 @@ intel_mmio_use_pci_bar(struct intel_mmio_data *mmio_data, struct pci_device *pci
> >  				      PCI_DEV_MAP_FLAG_WRITABLE,
> >  				      &mmio_data->igt_mmio);
> >  
> > -	igt_global_mmio = mmio_data->igt_mmio;
> > -
> >  	igt_fail_on_f(error != 0,
> >  		      "Couldn't map MMIO region\n");
> > +
> > +	mmio_data->mmio_size = mmio_size;
> > +	mmio_data->dev = pci_dev;
> > +	igt_global_mmio = mmio_data->igt_mmio;

To be consequent with what I said above, in next version of the patch I'm 
going to not touch the assignment of mmio_data->igt_mmio to the out of scope 
and depreciated igt_global_mmio, leaving it as broken as it already is.

> > +}
> > +
> > +/**
> > + * intel_mmio_unmap_pci_bar:
> > + * @mmio_data:  mmio structure for IO operations
> > + *
> > + * Unmaps a PCI BAR region mmapped with intel_mmio_use_pci_bar()
> > + */
> > +void intel_mmio_unmap_pci_bar(struct intel_mmio_data *mmio_data)
> > +{
> > +	if (igt_warn_on_f(mmio_data->pci_device_id,
> > +			  "test bug: arg initialized with intel_register_access_init()\n"))

Similarly to the case of intel_mmio_unmap_dump_file(), I can change the 
message to "test bug: arg initialized with a method other than 
intel_mmio_use_pci_bar()\n" if that's what you prefer.

> > +		return;
> > +	if (igt_warn_on_f(!mmio_data->dev,
> > +			  "test bug: arg not initialized with intel_mmio_use_pci_bar()\n"))
> > +		return;
> > +
> > +	igt_global_mmio = NULL;
> > +	igt_debug_on(pci_device_unmap_range(mmio_data->dev,
> > +					    mmio_data->igt_mmio, mmio_data->mmio_size) < 0);
> > +	mmio_data->dev = NULL;
> > +	mmio_data->mmio_size = 0;
> >  }
> >  
> >  static void
> > @@ -166,6 +215,8 @@ release_forcewake_lock(int fd)
> >   * It also initializes mmio_data->igt_mmio like intel_mmio_use_pci_bar().
> >   *
> >   * @pci_dev can be obtained from intel_get_pci_device().
> > + *
> > + * Users are expected to call intel_register_access_fini() after use.
> >   */
> >  int
> >  intel_register_access_init(struct intel_mmio_data *mmio_data, struct pci_device *pci_dev, int safe, int fd)
> > @@ -222,8 +273,15 @@ int intel_register_access_needs_fakewake(struct intel_mmio_data *mmio_data)
> >  void
> >  intel_register_access_fini(struct intel_mmio_data *mmio_data)
> >  {
> > -	if (mmio_data->key && intel_register_access_needs_wake(mmio_data))
> > +	if (igt_warn_on_f(!mmio_data->pci_device_id,
> > +			  "test bug: arg not initialized with intel_register_access_init()\n"))
> > +		return;
> > +
> > +	if (intel_register_access_needs_wake(mmio_data))

As mmio_data->key is no longer used since v3 as an indication of mmio_data 
having been initialized by intel_register_access_init() or not, the original 
(potentially broken) condition:

	if (mmio_data->key && intel_register_access_needs_wake(mmio_data))

should be not touched by this patch as out of scope but its original form 
preserved.  I'm going to restore it in next version of the patch.

> >  		release_forcewake_lock(mmio_data->key);
> > +
> > +	mmio_data->pci_device_id = 0;
> 
> Here we should check other conditions so no warn triggers in unmap_pci_bar
> or make the messages generic (and document it in comments at beggining)
> or maybe make helper with no checks for unmap_pci_bar.

Why? I can't see any potential scenario where mmio_data->pci_device_id is not 
0 but mmio_data->dev is NULL.  If you can see one then please tell me more 
about it.

Thanks,
Janusz


> > +	intel_mmio_unmap_pci_bar(mmio_data);
> >  }
> >  
> >  /**
>
Kamil Konieczny March 7, 2022, 5:04 p.m. UTC | #3
Hi Janusz,

Dnia 2022-03-07 at 16:06:10 +0100, Janusz Krzysztofik napisał(a):
> Hi Kamil,
> 
> On Monday, 7 March 2022 14:23:30 CET Kamil Konieczny wrote:
> > Hi Janusz,
> > 
> > Dnia 2022-03-07 at 09:26:43 +0100, Janusz Krzysztofik napisał(a):
> > > Commit 5f3cfa485eb4 ("lib: Use safe wrappers around libpciaccess
> > > initialization functions") took care of not leaking memory allocated by
> > > pci_system_init() but didn't take care of users potentially attempting to
> > > reinitialize global data maintained by libpciaccess.  For example,
> > > intel_register_access_init() mmaps device's PCI BAR0 resource with
> > > pci_device_map_range() but intel_register_access_fini() doesn't unmap it
> > > and next call to intel_register_access_init() fails on attempt to mmap it
> > > again.
> > > 
> > > Fix it, and also provide intel_mmio_unmap_*() counterparts to public
> > > functions intel_mmio_use_pci_bar() and intel_mmio_use_dump_file().
> > > 
> > > v2: apply last minute fixes, cached but unfortunately not committed before
> > >     sending
> > > v3: use .pci_device_id field content as an indicator of arg initialization
> > >     via intel_register_access_init(),
> > >   - improve checks of argument initialization status,
> > >   - shorten warning messages (Kamil),
> > >   - don't fill .mmio_size field until initialization succeeds (Kamil)
> > > 
> > > Signed-off-by: Janusz Krzysztofik <janusz.krzysztofik@linux.intel.com>
> > > Cc: Kamil Konieczny <kamil.konieczny@linux.intel.com>
> > > ---
> > >  lib/intel_io.h   |  4 +++
> > >  lib/intel_mmio.c | 64 +++++++++++++++++++++++++++++++++++++++++++++---
> > >  2 files changed, 65 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/lib/intel_io.h b/lib/intel_io.h
> > > index 1cfe4fb6b9..ea2649d9bc 100644
> > > --- a/lib/intel_io.h
> > > +++ b/lib/intel_io.h
> > > @@ -49,6 +49,8 @@ struct intel_register_map {
> > >  
> > >  struct intel_mmio_data {
> > >  	void *igt_mmio;
> > > +	size_t mmio_size;
> > > +	struct pci_device *dev;
> > >  	struct intel_register_map map;
> > >  	uint32_t pci_device_id;
> > >  	int key;
> > > @@ -57,7 +59,9 @@ struct intel_mmio_data {
> > >  
> > >  void intel_mmio_use_pci_bar(struct intel_mmio_data *mmio_data,
> > >  			    struct pci_device *pci_dev);
> > > +void intel_mmio_unmap_pci_bar(struct intel_mmio_data *mmio_data);
> > >  void intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file);
> > > +void intel_mmio_unmap_dump_file(struct intel_mmio_data *mmio_data);
> > >  
> > >  int intel_register_access_init(struct intel_mmio_data *mmio_data,
> > >  			       struct pci_device *pci_dev, int safe, int fd);
> > > diff --git a/lib/intel_mmio.c b/lib/intel_mmio.c
> > > index 667a69f5aa..d6ce0ee3ea 100644
> > > --- a/lib/intel_mmio.c
> > > +++ b/lib/intel_mmio.c
> > > @@ -82,6 +82,8 @@ void *igt_global_mmio;
> > >   * Sets also up mmio_data->igt_mmio to point at the data contained
> > >   * in @file. This allows the same code to get reused for dumping and decoding
> > >   * from running hardware as from register dumps.
> > > + *
> > > + * Users are expected to call intel_mmio_unmap_dump_file() after use.
> > >   */
> > >  void
> > >  intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file)
> > > @@ -99,11 +101,32 @@ intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file)
> > >  	igt_fail_on_f(mmio_data->igt_mmio == MAP_FAILED,
> > >  		      "Couldn't mmap %s\n", file);
> > >  
> > > +	mmio_data->mmio_size = st.st_size;
> > >  	igt_global_mmio = mmio_data->igt_mmio;
> > >  
> > >  	close(fd);
> > >  }
> > >  
> > > +/**
> > > + * intel_mmio_unmap_dump_file:
> > > + * @mmio_data:  mmio structure for IO operations
> > > + *
> > > + * Unmaps a dump file mmapped with intel_mmio_use_dump_file()
> > > + */
> > > +void intel_mmio_unmap_dump_file(struct intel_mmio_data *mmio_data)
> > > +{
> > > +	if (igt_warn_on_f(mmio_data->dev,
> > > +			  "test bug: arg initialized with intel_mmio_use_pci_bar()\n"))
> > > +		return;
> > 
> > Please add a global description about this kind of errors, this
> > one is for using unmap when mmio was mmap-ed from other mmap
> > type.
> 
> Can you please be more specific in what you mean by "global description of 
> this kind of errors"?  A more detailed warning?  A comment?  If the latter 
> then how would you like me to make it global?

Yes, I was thinking about comment at begin of file, but maybe
it is better to change warning message like below.

> 
> If you just don't like the reference to intel_mmio_use_pci_bar() here then 
> would you be satisfied with something like "test bug: arg initialized by a 
> method other than intel_mmio_use_dump_file()\n"?

Yes, this sounds good.

> 
> > > +	if (igt_warn_on_f(!mmio_data->mmio_size,
> > > +			  "test bug: arg not initialized\n"))
> > > +		return;
> > 
> > Can we replace this with one check igt_global_mmio != NULL ?
> > Something like:
> > 
> > 	if (igt_warn_on_f(!igt_global_mmio,
> > 			  "mmio regs not mmap-ed\n"))
> > 		return;
> > 
> > Or should we add this before all other checks in unmap functions
> > and keep this additional check ?
> 
> Why igt_global_mmio again?  I still think this global variable is broken and 
> users should just use the structure they pass to intel_mmio_use_*() or 
> intel_register_access_init(), then introducing another a dependency on it with 
> this patch doesn't make sense to me.  If you think the opposite then please 
> explain why.

Good point, maybe in next series you will remove this global
var ?

> 
> > > +
> > > +	igt_global_mmio = NULL;
> > > +	igt_debug_on(munmap(mmio_data->igt_mmio, mmio_data->mmio_size) < 0);
> > > +	mmio_data->mmio_size = 0;
> > > +}
> > > +
> > >  /**
> > >   * intel_mmio_use_pci_bar:
> > >   * @mmio_data:  mmio structure for IO operations
> > > @@ -112,6 +135,8 @@ intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file)
> > >   * Fill a mmio_data stucture with igt_mmio to point at the mmio bar.
> > >   *
> > >   * @pci_dev can be obtained from intel_get_pci_device().
> > > + *
> > > + * Users are expected to call intel_mmio_unmap_pci_bar() after use.
> > >   */
> > >  void
> > >  intel_mmio_use_pci_bar(struct intel_mmio_data *mmio_data, struct pci_device *pci_dev)
> > > @@ -141,10 +166,34 @@ intel_mmio_use_pci_bar(struct intel_mmio_data *mmio_data, struct pci_device *pci
> > >  				      PCI_DEV_MAP_FLAG_WRITABLE,
> > >  				      &mmio_data->igt_mmio);
> > >  
> > > -	igt_global_mmio = mmio_data->igt_mmio;
> > > -
> > >  	igt_fail_on_f(error != 0,
> > >  		      "Couldn't map MMIO region\n");
> > > +
> > > +	mmio_data->mmio_size = mmio_size;
> > > +	mmio_data->dev = pci_dev;
> > > +	igt_global_mmio = mmio_data->igt_mmio;
> 
> To be consequent with what I said above, in next version of the patch I'm 
> going to not touch the assignment of mmio_data->igt_mmio to the out of scope 
> and depreciated igt_global_mmio, leaving it as broken as it already is.

If it is not used anywhere then ok.

> > > +}
> > > +
> > > +/**
> > > + * intel_mmio_unmap_pci_bar:
> > > + * @mmio_data:  mmio structure for IO operations
> > > + *
> > > + * Unmaps a PCI BAR region mmapped with intel_mmio_use_pci_bar()
> > > + */
> > > +void intel_mmio_unmap_pci_bar(struct intel_mmio_data *mmio_data)
> > > +{
> > > +	if (igt_warn_on_f(mmio_data->pci_device_id,
> > > +			  "test bug: arg initialized with intel_register_access_init()\n"))
> 
> Similarly to the case of intel_mmio_unmap_dump_file(), I can change the 
> message to "test bug: arg initialized with a method other than 
> intel_mmio_use_pci_bar()\n" if that's what you prefer.
> 
> > > +		return;
> > > +	if (igt_warn_on_f(!mmio_data->dev,
> > > +			  "test bug: arg not initialized with intel_mmio_use_pci_bar()\n"))
> > > +		return;
> > > +
> > > +	igt_global_mmio = NULL;
> > > +	igt_debug_on(pci_device_unmap_range(mmio_data->dev,
> > > +					    mmio_data->igt_mmio, mmio_data->mmio_size) < 0);
> > > +	mmio_data->dev = NULL;
> > > +	mmio_data->mmio_size = 0;
> > >  }
> > >  
> > >  static void
> > > @@ -166,6 +215,8 @@ release_forcewake_lock(int fd)
> > >   * It also initializes mmio_data->igt_mmio like intel_mmio_use_pci_bar().
> > >   *
> > >   * @pci_dev can be obtained from intel_get_pci_device().
> > > + *
> > > + * Users are expected to call intel_register_access_fini() after use.
> > >   */
> > >  int
> > >  intel_register_access_init(struct intel_mmio_data *mmio_data, struct pci_device *pci_dev, int safe, int fd)
> > > @@ -222,8 +273,15 @@ int intel_register_access_needs_fakewake(struct intel_mmio_data *mmio_data)
> > >  void
> > >  intel_register_access_fini(struct intel_mmio_data *mmio_data)
> > >  {
> > > -	if (mmio_data->key && intel_register_access_needs_wake(mmio_data))
> > > +	if (igt_warn_on_f(!mmio_data->pci_device_id,
> > > +			  "test bug: arg not initialized with intel_register_access_init()\n"))
> > > +		return;
> > > +
> > > +	if (intel_register_access_needs_wake(mmio_data))
> 
> As mmio_data->key is no longer used since v3 as an indication of mmio_data 
> having been initialized by intel_register_access_init() or not, the original 
> (potentially broken) condition:
> 
> 	if (mmio_data->key && intel_register_access_needs_wake(mmio_data))
> 
> should be not touched by this patch as out of scope but its original form 
> preserved.  I'm going to restore it in next version of the patch.

ok

> 
> > >  		release_forcewake_lock(mmio_data->key);
> > > +
> > > +	mmio_data->pci_device_id = 0;
> > 
> > Here we should check other conditions so no warn triggers in unmap_pci_bar
> > or make the messages generic (and document it in comments at beggining)
> > or maybe make helper with no checks for unmap_pci_bar.
> 
> Why? I can't see any potential scenario where mmio_data->pci_device_id is not 
> 0 but mmio_data->dev is NULL.  If you can see one then please tell me more 
> about it.

Yes, you are right, I overlooked that.

> 
> Thanks,
> Janusz
> 
> 
> > > +	intel_mmio_unmap_pci_bar(mmio_data);
> > >  }
> > >  
> > >  /**

Regards,
Kamil
diff mbox series

Patch

diff --git a/lib/intel_io.h b/lib/intel_io.h
index 1cfe4fb6b9..ea2649d9bc 100644
--- a/lib/intel_io.h
+++ b/lib/intel_io.h
@@ -49,6 +49,8 @@  struct intel_register_map {
 
 struct intel_mmio_data {
 	void *igt_mmio;
+	size_t mmio_size;
+	struct pci_device *dev;
 	struct intel_register_map map;
 	uint32_t pci_device_id;
 	int key;
@@ -57,7 +59,9 @@  struct intel_mmio_data {
 
 void intel_mmio_use_pci_bar(struct intel_mmio_data *mmio_data,
 			    struct pci_device *pci_dev);
+void intel_mmio_unmap_pci_bar(struct intel_mmio_data *mmio_data);
 void intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file);
+void intel_mmio_unmap_dump_file(struct intel_mmio_data *mmio_data);
 
 int intel_register_access_init(struct intel_mmio_data *mmio_data,
 			       struct pci_device *pci_dev, int safe, int fd);
diff --git a/lib/intel_mmio.c b/lib/intel_mmio.c
index 667a69f5aa..d6ce0ee3ea 100644
--- a/lib/intel_mmio.c
+++ b/lib/intel_mmio.c
@@ -82,6 +82,8 @@  void *igt_global_mmio;
  * Sets also up mmio_data->igt_mmio to point at the data contained
  * in @file. This allows the same code to get reused for dumping and decoding
  * from running hardware as from register dumps.
+ *
+ * Users are expected to call intel_mmio_unmap_dump_file() after use.
  */
 void
 intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file)
@@ -99,11 +101,32 @@  intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file)
 	igt_fail_on_f(mmio_data->igt_mmio == MAP_FAILED,
 		      "Couldn't mmap %s\n", file);
 
+	mmio_data->mmio_size = st.st_size;
 	igt_global_mmio = mmio_data->igt_mmio;
 
 	close(fd);
 }
 
+/**
+ * intel_mmio_unmap_dump_file:
+ * @mmio_data:  mmio structure for IO operations
+ *
+ * Unmaps a dump file mmapped with intel_mmio_use_dump_file()
+ */
+void intel_mmio_unmap_dump_file(struct intel_mmio_data *mmio_data)
+{
+	if (igt_warn_on_f(mmio_data->dev,
+			  "test bug: arg initialized with intel_mmio_use_pci_bar()\n"))
+		return;
+	if (igt_warn_on_f(!mmio_data->mmio_size,
+			  "test bug: arg not initialized\n"))
+		return;
+
+	igt_global_mmio = NULL;
+	igt_debug_on(munmap(mmio_data->igt_mmio, mmio_data->mmio_size) < 0);
+	mmio_data->mmio_size = 0;
+}
+
 /**
  * intel_mmio_use_pci_bar:
  * @mmio_data:  mmio structure for IO operations
@@ -112,6 +135,8 @@  intel_mmio_use_dump_file(struct intel_mmio_data *mmio_data, char *file)
  * Fill a mmio_data stucture with igt_mmio to point at the mmio bar.
  *
  * @pci_dev can be obtained from intel_get_pci_device().
+ *
+ * Users are expected to call intel_mmio_unmap_pci_bar() after use.
  */
 void
 intel_mmio_use_pci_bar(struct intel_mmio_data *mmio_data, struct pci_device *pci_dev)
@@ -141,10 +166,34 @@  intel_mmio_use_pci_bar(struct intel_mmio_data *mmio_data, struct pci_device *pci
 				      PCI_DEV_MAP_FLAG_WRITABLE,
 				      &mmio_data->igt_mmio);
 
-	igt_global_mmio = mmio_data->igt_mmio;
-
 	igt_fail_on_f(error != 0,
 		      "Couldn't map MMIO region\n");
+
+	mmio_data->mmio_size = mmio_size;
+	mmio_data->dev = pci_dev;
+	igt_global_mmio = mmio_data->igt_mmio;
+}
+
+/**
+ * intel_mmio_unmap_pci_bar:
+ * @mmio_data:  mmio structure for IO operations
+ *
+ * Unmaps a PCI BAR region mmapped with intel_mmio_use_pci_bar()
+ */
+void intel_mmio_unmap_pci_bar(struct intel_mmio_data *mmio_data)
+{
+	if (igt_warn_on_f(mmio_data->pci_device_id,
+			  "test bug: arg initialized with intel_register_access_init()\n"))
+		return;
+	if (igt_warn_on_f(!mmio_data->dev,
+			  "test bug: arg not initialized with intel_mmio_use_pci_bar()\n"))
+		return;
+
+	igt_global_mmio = NULL;
+	igt_debug_on(pci_device_unmap_range(mmio_data->dev,
+					    mmio_data->igt_mmio, mmio_data->mmio_size) < 0);
+	mmio_data->dev = NULL;
+	mmio_data->mmio_size = 0;
 }
 
 static void
@@ -166,6 +215,8 @@  release_forcewake_lock(int fd)
  * It also initializes mmio_data->igt_mmio like intel_mmio_use_pci_bar().
  *
  * @pci_dev can be obtained from intel_get_pci_device().
+ *
+ * Users are expected to call intel_register_access_fini() after use.
  */
 int
 intel_register_access_init(struct intel_mmio_data *mmio_data, struct pci_device *pci_dev, int safe, int fd)
@@ -222,8 +273,15 @@  int intel_register_access_needs_fakewake(struct intel_mmio_data *mmio_data)
 void
 intel_register_access_fini(struct intel_mmio_data *mmio_data)
 {
-	if (mmio_data->key && intel_register_access_needs_wake(mmio_data))
+	if (igt_warn_on_f(!mmio_data->pci_device_id,
+			  "test bug: arg not initialized with intel_register_access_init()\n"))
+		return;
+
+	if (intel_register_access_needs_wake(mmio_data))
 		release_forcewake_lock(mmio_data->key);
+
+	mmio_data->pci_device_id = 0;
+	intel_mmio_unmap_pci_bar(mmio_data);
 }
 
 /**