diff options
| author | Bartlomiej Zolnierkiewicz <[email protected]> | 2018-09-26 15:54:31 +0200 | 
|---|---|---|
| committer | Bartlomiej Zolnierkiewicz <[email protected]> | 2018-09-26 15:54:31 +0200 | 
| commit | aaccf3c97418f169afdbb5855e9cbcbda34e90fd (patch) | |
| tree | 5d4207e67958bdbc23288cf30178692f5534e1a0 /drivers/gpu/vga/vga_switcheroo.c | |
| parent | f39684524b391c5a7ed0ac44db4fec3357af1c5d (diff) | |
| parent | 6bf4ca7fbc85d80446ac01c0d1d77db4d91a6d84 (diff) | |
Merge tag 'v4.19-rc5' of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux into fbdev-for-next
Sync with upstream (which now contains fbdev-v4.19 changes) to
prepare a base for fbdev-v4.20 changes.
Diffstat (limited to 'drivers/gpu/vga/vga_switcheroo.c')
| -rw-r--r-- | drivers/gpu/vga/vga_switcheroo.c | 65 | 
1 files changed, 54 insertions, 11 deletions
| diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index fc4adf3d34e8..cf2a18571d48 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -103,9 +103,11 @@   *	runtime pm. If true, writing ON and OFF to the vga_switcheroo debugfs   *	interface is a no-op so as not to interfere with runtime pm   * @list: client list + * @vga_dev: pci device, indicate which GPU is bound to current audio client   *   * Registered client. A client can be either a GPU or an audio device on a GPU. - * For audio clients, the @fb_info and @active members are bogus. + * For audio clients, the @fb_info and @active members are bogus. For GPU + * clients, the @vga_dev is bogus.   */  struct vga_switcheroo_client {  	struct pci_dev *pdev; @@ -116,6 +118,7 @@ struct vga_switcheroo_client {  	bool active;  	bool driver_power_control;  	struct list_head list; +	struct pci_dev *vga_dev;  };  /* @@ -161,9 +164,8 @@ struct vgasr_priv {  };  #define ID_BIT_AUDIO		0x100 -#define client_is_audio(c)	((c)->id & ID_BIT_AUDIO) -#define client_is_vga(c)	((c)->id == VGA_SWITCHEROO_UNKNOWN_ID || \ -				 !client_is_audio(c)) +#define client_is_audio(c)		((c)->id & ID_BIT_AUDIO) +#define client_is_vga(c)		(!client_is_audio(c))  #define client_id(c)		((c)->id & ~ID_BIT_AUDIO)  static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv); @@ -192,14 +194,31 @@ static void vga_switcheroo_enable(void)  		vgasr_priv.handler->init();  	list_for_each_entry(client, &vgasr_priv.clients, list) { -		if (client->id != VGA_SWITCHEROO_UNKNOWN_ID) +		if (!client_is_vga(client) || +		     client_id(client) != VGA_SWITCHEROO_UNKNOWN_ID)  			continue; +  		ret = vgasr_priv.handler->get_client_id(client->pdev);  		if (ret < 0)  			return;  		client->id = ret;  	} + +	list_for_each_entry(client, &vgasr_priv.clients, list) { +		if (!client_is_audio(client) || +		     client_id(client) != VGA_SWITCHEROO_UNKNOWN_ID) +			continue; + +		ret = vgasr_priv.handler->get_client_id(client->vga_dev); +		if (ret < 0) +			return; + +		client->id = ret | ID_BIT_AUDIO; +		if (client->ops->gpu_bound) +			client->ops->gpu_bound(client->pdev, ret); +	} +  	vga_switcheroo_debugfs_init(&vgasr_priv);  	vgasr_priv.active = true;  } @@ -272,7 +291,9 @@ EXPORT_SYMBOL(vga_switcheroo_handler_flags);  static int register_client(struct pci_dev *pdev,  			   const struct vga_switcheroo_client_ops *ops, -			   enum vga_switcheroo_client_id id, bool active, +			   enum vga_switcheroo_client_id id, +			   struct pci_dev *vga_dev, +			   bool active,  			   bool driver_power_control)  {  	struct vga_switcheroo_client *client; @@ -287,6 +308,7 @@ static int register_client(struct pci_dev *pdev,  	client->id = id;  	client->active = active;  	client->driver_power_control = driver_power_control; +	client->vga_dev = vga_dev;  	mutex_lock(&vgasr_mutex);  	list_add_tail(&client->list, &vgasr_priv.clients); @@ -319,7 +341,7 @@ int vga_switcheroo_register_client(struct pci_dev *pdev,  				   const struct vga_switcheroo_client_ops *ops,  				   bool driver_power_control)  { -	return register_client(pdev, ops, VGA_SWITCHEROO_UNKNOWN_ID, +	return register_client(pdev, ops, VGA_SWITCHEROO_UNKNOWN_ID, NULL,  			       pdev == vga_default_device(),  			       driver_power_control);  } @@ -329,19 +351,40 @@ EXPORT_SYMBOL(vga_switcheroo_register_client);   * vga_switcheroo_register_audio_client - register audio client   * @pdev: client pci device   * @ops: client callbacks - * @id: client identifier + * @vga_dev:  pci device which is bound to current audio client   *   * Register audio client (audio device on a GPU). The client is assumed   * to use runtime PM. Beforehand, vga_switcheroo_client_probe_defer()   * shall be called to ensure that all prerequisites are met.   * - * Return: 0 on success, -ENOMEM on memory allocation error. + * Return: 0 on success, -ENOMEM on memory allocation error, -EINVAL on getting + * client id error.   */  int vga_switcheroo_register_audio_client(struct pci_dev *pdev,  			const struct vga_switcheroo_client_ops *ops, -			enum vga_switcheroo_client_id id) +			struct pci_dev *vga_dev)  { -	return register_client(pdev, ops, id | ID_BIT_AUDIO, false, true); +	enum vga_switcheroo_client_id id = VGA_SWITCHEROO_UNKNOWN_ID; + +	/* +	 * if vga_switcheroo has enabled, that mean two GPU clients and also +	 * handler are registered. Get audio client id from bound GPU client +	 * id directly, otherwise, set it as VGA_SWITCHEROO_UNKNOWN_ID, +	 * it will set to correct id in later when vga_switcheroo_enable() +	 * is called. +	 */ +	mutex_lock(&vgasr_mutex); +	if (vgasr_priv.active) { +		id = vgasr_priv.handler->get_client_id(vga_dev); +		if (id < 0) { +			mutex_unlock(&vgasr_mutex); +			return -EINVAL; +		} +	} +	mutex_unlock(&vgasr_mutex); + +	return register_client(pdev, ops, id | ID_BIT_AUDIO, vga_dev, +			       false, true);  }  EXPORT_SYMBOL(vga_switcheroo_register_audio_client); |