ACK/cmnt[Bionic/Cosmic/Disco]: [SRU][Cosmic][Disco][PATCH 1/1] s390/zcrypt: reinit ap queue state machine during device probe

Kleber Souza kleber.souza at canonical.com
Mon Dec 17 13:24:45 UTC 2018


On 12/14/18 5:32 PM, Joseph Salisbury wrote:
> From: Harald Freudenberger <freude at linux.ibm.com>
>
> BugLink: https://bugs.launchpad.net/bugs/1805414
>
> Until the vfio-ap driver came into live there was a well known
> agreement about the way how ap devices are initialized and their
> states when the driver's probe function is called.
>
> However, the vfio device driver when receiving an ap queue device does
> additional resets thereby removing the registration for interrupts for
> the ap device done by the ap bus core code. So when later the vfio
> driver releases the device and one of the default zcrypt drivers takes
> care of the device the interrupt registration needs to get
> renewed. The current code does no renew and result is that requests
> send into such a queue will never see a reply processed - the
> application hangs.
>
> This patch adds a function which resets the aq queue state machine for
> the ap queue device and triggers the walk through the initial states
> (which are reset and registration for interrupts). This function is
> now called before the driver's probe function is invoked.
>
> When the association between driver and device is released, the
> driver's remove function is called. The current implementation calls a
> ap queue function ap_queue_remove(). This invokation has been moved to
> the ap bus function to make the probe / remove pair for ap bus and
> drivers more symmetric.
>
> Fixes: 7e0bdbe5c21c ("s390/zcrypt: AP bus support for alternate driver(s)")
> Cc: stable at vger.kernel.org # 4.19+
> Signed-off-by: Harald Freudenberger <freude at linux.ibm.com>
> Reviewd-by: Tony Krowiak <akrowiak at linux.ibm.com>
> Reviewd-by: Martin Schwidefsky <schwidefsky at de.ibm.com>
> Signed-off-by: Martin Schwidefsky <schwidefsky at de.ibm.com>
> (cherry picked from commit 104f708fd1241b22f808bdf066ab67dc5a051de5)
> Signed-off-by: Joseph Salisbury <joseph.salisbury at canonical.com>

Clean cherry-pick, limited to s390x. ACK'ing also for Bionic:

Acked-by: Kleber Sacilotto de Souza <kleber.souza at canonical.com>

> ---
>  drivers/s390/crypto/ap_bus.c        |  8 ++++----
>  drivers/s390/crypto/ap_bus.h        |  1 +
>  drivers/s390/crypto/ap_queue.c      | 15 +++++++++++++++
>  drivers/s390/crypto/zcrypt_cex2a.c  |  1 -
>  drivers/s390/crypto/zcrypt_cex4.c   |  1 -
>  drivers/s390/crypto/zcrypt_pcixcc.c |  1 -
>  6 files changed, 20 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
> index 4521b21..84595b2 100644
> --- a/drivers/s390/crypto/ap_bus.c
> +++ b/drivers/s390/crypto/ap_bus.c
> @@ -795,6 +795,8 @@ static int ap_device_probe(struct device *dev)
>  		drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;
>  		if (!!devres != !!drvres)
>  			return -ENODEV;
> +		/* (re-)init queue's state machine */
> +		ap_queue_reinit_state(to_ap_queue(dev));
>  	}
>  
>  	/* Add queue/card to list of active queues/cards */
> @@ -827,6 +829,8 @@ static int ap_device_remove(struct device *dev)
>  	struct ap_device *ap_dev = to_ap_dev(dev);
>  	struct ap_driver *ap_drv = ap_dev->drv;
>  
> +	if (is_queue_dev(dev))
> +		ap_queue_remove(to_ap_queue(dev));
>  	if (ap_drv->remove)
>  		ap_drv->remove(ap_dev);
>  
> @@ -1484,10 +1488,6 @@ static void ap_scan_bus(struct work_struct *unused)
>  			aq->ap_dev.device.parent = &ac->ap_dev.device;
>  			dev_set_name(&aq->ap_dev.device,
>  				     "%02x.%04x", id, dom);
> -			/* Start with a device reset */
> -			spin_lock_bh(&aq->lock);
> -			ap_wait(ap_sm_event(aq, AP_EVENT_POLL));
> -			spin_unlock_bh(&aq->lock);
>  			/* Register device */
>  			rc = device_register(&aq->ap_dev.device);
>  			if (rc) {
> diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
> index 7c3c077..5ea5eaf 100644
> --- a/drivers/s390/crypto/ap_bus.h
> +++ b/drivers/s390/crypto/ap_bus.h
> @@ -252,6 +252,7 @@ struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type);
>  void ap_queue_remove(struct ap_queue *aq);
>  void ap_queue_suspend(struct ap_device *ap_dev);
>  void ap_queue_resume(struct ap_device *ap_dev);
> +void ap_queue_reinit_state(struct ap_queue *aq);
>  
>  struct ap_card *ap_card_create(int id, int queue_depth, int raw_device_type,
>  			       int comp_device_type, unsigned int functions);
> diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c
> index c3e9e9f..7450b3b 100644
> --- a/drivers/s390/crypto/ap_queue.c
> +++ b/drivers/s390/crypto/ap_queue.c
> @@ -738,5 +738,20 @@ void ap_queue_remove(struct ap_queue *aq)
>  {
>  	ap_flush_queue(aq);
>  	del_timer_sync(&aq->timeout);
> +
> +	/* reset with zero, also clears irq registration */
> +	spin_lock_bh(&aq->lock);
> +	ap_zapq(aq->qid);
> +	aq->state = AP_STATE_BORKED;
> +	spin_unlock_bh(&aq->lock);
>  }
>  EXPORT_SYMBOL(ap_queue_remove);
> +
> +void ap_queue_reinit_state(struct ap_queue *aq)
> +{
> +	spin_lock_bh(&aq->lock);
> +	aq->state = AP_STATE_RESET_START;
> +	ap_wait(ap_sm_event(aq, AP_EVENT_POLL));
> +	spin_unlock_bh(&aq->lock);
> +}
> +EXPORT_SYMBOL(ap_queue_reinit_state);
> diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
> index f4ae5fa..ff17a00 100644
> --- a/drivers/s390/crypto/zcrypt_cex2a.c
> +++ b/drivers/s390/crypto/zcrypt_cex2a.c
> @@ -198,7 +198,6 @@ static void zcrypt_cex2a_queue_remove(struct ap_device *ap_dev)
>  	struct ap_queue *aq = to_ap_queue(&ap_dev->device);
>  	struct zcrypt_queue *zq = aq->private;
>  
> -	ap_queue_remove(aq);
>  	if (zq)
>  		zcrypt_queue_unregister(zq);
>  }
> diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c
> index 35d58db..2a42e59 100644
> --- a/drivers/s390/crypto/zcrypt_cex4.c
> +++ b/drivers/s390/crypto/zcrypt_cex4.c
> @@ -273,7 +273,6 @@ static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev)
>  	struct ap_queue *aq = to_ap_queue(&ap_dev->device);
>  	struct zcrypt_queue *zq = aq->private;
>  
> -	ap_queue_remove(aq);
>  	if (zq)
>  		zcrypt_queue_unregister(zq);
>  }
> diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
> index 94d9f72..baa683c 100644
> --- a/drivers/s390/crypto/zcrypt_pcixcc.c
> +++ b/drivers/s390/crypto/zcrypt_pcixcc.c
> @@ -276,7 +276,6 @@ static void zcrypt_pcixcc_queue_remove(struct ap_device *ap_dev)
>  	struct ap_queue *aq = to_ap_queue(&ap_dev->device);
>  	struct zcrypt_queue *zq = aq->private;
>  
> -	ap_queue_remove(aq);
>  	if (zq)
>  		zcrypt_queue_unregister(zq);
>  }






More information about the kernel-team mailing list