From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755829AbbDGNTL (ORCPT ); Tue, 7 Apr 2015 09:19:11 -0400 Received: from ip4-83-240-67-251.cust.nbox.cz ([83.240.67.251]:54450 "EHLO ip4-83-240-18-248.cust.nbox.cz" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754085AbbDGMwH (ORCPT ); Tue, 7 Apr 2015 08:52:07 -0400 From: Jiri Slaby To: stable@vger.kernel.org Cc: linux-kernel@vger.kernel.org, "Michael S. Tsirkin" , Rusty Russell , Jiri Slaby Subject: [PATCH 3.12 039/155] virtio_console: avoid config access from irq Date: Tue, 7 Apr 2015 14:50:08 +0200 Message-Id: X-Mailer: git-send-email 2.3.4 In-Reply-To: <9a548862b8a26cbccc14f2c6c9c3688813d8d14b.1428411003.git.jslaby@suse.cz> References: <9a548862b8a26cbccc14f2c6c9c3688813d8d14b.1428411003.git.jslaby@suse.cz> In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: "Michael S. Tsirkin" 3.12-stable review patch. If anyone has any objections, please let me know. =============== commit eeb8a7e8bb123e84daeef84f5a2eab99ad2839a2 upstream. when multiport is off, virtio console invokes config access from irq context, config access is blocking on s390. Fix this up by scheduling work from config irq - similar to what we do for multiport configs. Signed-off-by: Michael S. Tsirkin Reviewed-by: Amit Shah Signed-off-by: Rusty Russell Signed-off-by: Jiri Slaby --- drivers/char/virtio_console.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 4d5fcc2d6c9c..f6b96ba57b32 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -142,6 +142,7 @@ struct ports_device { * notification */ struct work_struct control_work; + struct work_struct config_work; struct list_head ports; @@ -1833,10 +1834,21 @@ static void config_intr(struct virtio_device *vdev) portdev = vdev->priv; + if (!use_multiport(portdev)) + schedule_work(&portdev->config_work); +} + +static void config_work_handler(struct work_struct *work) +{ + struct ports_device *portdev; + + portdev = container_of(work, struct ports_device, control_work); if (!use_multiport(portdev)) { + struct virtio_device *vdev; struct port *port; u16 rows, cols; + vdev = portdev->vdev; vdev->config->get(vdev, offsetof(struct virtio_console_config, cols), &cols, sizeof(u16)); @@ -2030,6 +2042,7 @@ static int virtcons_probe(struct virtio_device *vdev) spin_lock_init(&portdev->ports_lock); INIT_LIST_HEAD(&portdev->ports); + INIT_WORK(&portdev->config_work, &config_work_handler); INIT_WORK(&portdev->control_work, &control_work_handler); if (multiport) { @@ -2104,6 +2117,8 @@ static void virtcons_remove(struct virtio_device *vdev) /* Finish up work that's lined up */ if (use_multiport(portdev)) cancel_work_sync(&portdev->control_work); + else + cancel_work_sync(&portdev->config_work); list_for_each_entry_safe(port, port2, &portdev->ports, list) unplug_port(port); @@ -2155,6 +2170,7 @@ static int virtcons_freeze(struct virtio_device *vdev) virtqueue_disable_cb(portdev->c_ivq); cancel_work_sync(&portdev->control_work); + cancel_work_sync(&portdev->config_work); /* * Once more: if control_work_handler() was running, it would * enable the cb as the last step. -- 2.3.4