From patchwork Fri Jun 22 11:22:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gersner X-Patchwork-Id: 933282 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="sEUA4+LZ"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41BxPS6v47z9s2L for ; Fri, 22 Jun 2018 21:37:16 +1000 (AEST) Received: from localhost ([::1]:32865 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fWKNO-0000r7-J9 for incoming@patchwork.ozlabs.org; Fri, 22 Jun 2018 07:37:14 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58683) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fWKAN-0007WM-Nc for qemu-devel@nongnu.org; Fri, 22 Jun 2018 07:23:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fWKAM-0005Zo-3A for qemu-devel@nongnu.org; Fri, 22 Jun 2018 07:23:47 -0400 Received: from mail-wm0-x242.google.com ([2a00:1450:400c:c09::242]:50792) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fWKAH-0005X9-83; Fri, 22 Jun 2018 07:23:41 -0400 Received: by mail-wm0-x242.google.com with SMTP id e16-v6so1909812wmd.0; Fri, 22 Jun 2018 04:23:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Uj+DXpMP1wpbvpX/i+9MA4AsoO05AZ13ThPQ6sdnlHo=; b=sEUA4+LZ+n/4zNtSytnIy9ATINW1fmcbLJH8+PLt/tHZo3m7t2MQ5U1uiv2z06BTQr linuOzVNtaVAB1UsnFvAU8EN4Y6MLgsvyEM6+mrD1KPsMAbEEW9fhEyPB8dVzmn7IuhJ x5oy1dDkijJ1Avv8tKc/qgE+FERktHq2bu7Mz7PaquG86sYq9Lt9y5NemzQp2Tc0SWF2 F7hWXEbx0IO8rxwwXbqTsshvoW0TTNGTQklsmQ9+dkjoG0pjzB6S6Gq11TmulW99ZfRK wnCf/eNmGvEGCwTOvWRI6nu3NCpggsXGmqwM6xms8EJMOlDTbDbzcmS7txQgM0u97Uh7 I3mA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Uj+DXpMP1wpbvpX/i+9MA4AsoO05AZ13ThPQ6sdnlHo=; b=sXBCncCpF+9j95wpRukcAVB8fjdIOKMyVppxj3/EVDrDl5/fD0ID4pScFc9Uq2N+Ng yKmpPfKkz53gnJSiVLXnjSCdfOu7e7Ig8murjXNr53qrz1XN9EZ/cH9ZxvdmTKnKT0pt dg6NeXlcjO41SJqYCzawO94nIJvUPH/fDcZL4fuLeVz+E3/Rkj0tDAdb/UReRa5TUKKk oiyFP35WWL6HoooMhPw+IV3ZKPmz/xMCGfDdxtKqnytN+nvEqakFMXhrxrQBfvanOb+9 EIUbjuwA8jI7hzz6MTGEde8g4vVNFV0mQYXR+8kzAgTC7AZvK0wyFcY5QWA/X+UpGcKy Sq5g== X-Gm-Message-State: APt69E0wxX7csHQO9g29RlUFupzraPEW4O/E6LXq96OyZiTA71Wu/jzY m1XQlbJmJoeaOYdqYRP/0vj/JYLVhp4= X-Google-Smtp-Source: ADUXVKJEKrIs06HkTOuavqwAn4GgalbaWIdtll1N1sD92i5Jdc2924M3Y0wK217JqIY0yL34suL8vg== X-Received: by 2002:a1c:ae8b:: with SMTP id x133-v6mr1476652wme.125.1529666620158; Fri, 22 Jun 2018 04:23:40 -0700 (PDT) Received: from localhost.localdomain (bzq-109-64-22-141.red.bezeqint.net. [109.64.22.141]) by smtp.gmail.com with ESMTPSA id e81-v6sm1758833wmi.28.2018.06.22.04.23.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 22 Jun 2018 04:23:39 -0700 (PDT) From: Shimi Gersner To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 22 Jun 2018 11:22:35 +0000 Message-Id: <20180622112237.2131-3-gersner@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180622112237.2131-1-gersner@gmail.com> References: <20180622112237.2131-1-gersner@gmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c09::242 Subject: [Qemu-devel] [PATCH 3/5] nvme: Proper state handling on enable/disable X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Keith Busch , Kevin Wolf , David Sariel , Shimi Gersner , Max Reitz Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" When device transitions from CC.EN=1 to CC.EN=0 (Controller Reset) it should properly reset its state, currently device only partially clears its state. Following actions were added to controller reset phase - Clear CC and CSTS completely - Clear and deassert irqs - On shutdown, leave state as is and only notify on shutdown completion. Change-Id: Ia0bc29775b12586c3aab2ca217603051062c3efe Signed-off-by: Shimi Gersner --- hw/block/nvme.c | 67 ++++++++++++++++++++++++++------------------ include/block/nvme.h | 5 ++++ 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 24a51d33ea..206d8428fd 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -805,7 +805,7 @@ static void nvme_process_sq(void *opaque) } } -static void nvme_clear_ctrl(NvmeCtrl *n) +static void nvme_clear_ctrl(NvmeCtrl *n, bool reset) { int i; @@ -820,8 +820,18 @@ static void nvme_clear_ctrl(NvmeCtrl *n) } } + if (reset) { + // Reset clears all except for AWA, ASW, ACQ + n->bar.cc = 0; + n->bar.csts = 0; + } + + // Update the IRQ status + n->bar.intmc = n->bar.intms = 0; + n->irq_status = 0; + nvme_irq_check(n); + blk_flush(n->conf.blk); - n->bar.cc = 0; } static int nvme_start_ctrl(NvmeCtrl *n) @@ -963,16 +973,14 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, nvme_irq_check(n); break; case 0x14: /* CC */ - trace_nvme_mmio_cfg(data & 0xffffffff); - /* Windows first sends data, then sends enable bit */ - if (!NVME_CC_EN(data) && !NVME_CC_EN(n->bar.cc) && - !NVME_CC_SHN(data) && !NVME_CC_SHN(n->bar.cc)) - { - n->bar.cc = data; - } + trace_nvme_mmio_cfg(data & NVME_CC_WR_MASK); + + uint32_t previous_cc = n->bar.cc; + + // CC is all writeable + n->bar.cc = data & NVME_CC_WR_MASK; - if (NVME_CC_EN(data) && !NVME_CC_EN(n->bar.cc)) { - n->bar.cc = data; + if (NVME_CC_EN(data) && !NVME_CC_EN(previous_cc)) { if (unlikely(nvme_start_ctrl(n))) { trace_nvme_err_startfail(); n->bar.csts = NVME_CSTS_FAILED; @@ -980,21 +988,24 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, trace_nvme_mmio_start_success(); n->bar.csts = NVME_CSTS_READY; } - } else if (!NVME_CC_EN(data) && NVME_CC_EN(n->bar.cc)) { + + } else if (!NVME_CC_EN(data) && NVME_CC_EN(previous_cc)) { trace_nvme_mmio_stopped(); - nvme_clear_ctrl(n); - n->bar.csts &= ~NVME_CSTS_READY; + nvme_clear_ctrl(n, true); + } - if (NVME_CC_SHN(data) && !(NVME_CC_SHN(n->bar.cc))) { + + if (NVME_CC_SHN(data) && !(NVME_CC_SHN(previous_cc))) { trace_nvme_mmio_shutdown_set(); - nvme_clear_ctrl(n); - n->bar.cc = data; + nvme_clear_ctrl(n, false); n->bar.csts |= NVME_CSTS_SHST_COMPLETE; - } else if (!NVME_CC_SHN(data) && NVME_CC_SHN(n->bar.cc)) { + + } else if (!NVME_CC_SHN(data) && NVME_CC_SHN(previous_cc)) { trace_nvme_mmio_shutdown_cleared(); n->bar.csts &= ~NVME_CSTS_SHST_COMPLETE; - n->bar.cc = data; + } + break; case 0x1C: /* CSTS */ if (data & (1 << 4)) { @@ -1016,23 +1027,23 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, } break; case 0x24: /* AQA */ - n->bar.aqa = data & 0xffffffff; - trace_nvme_mmio_aqattr(data & 0xffffffff); + n->bar.aqa = data & NVME_AQA_WR_MASK; + trace_nvme_mmio_aqattr(n->bar.aqa); break; case 0x28: /* ASQ */ - n->bar.asq = data; - trace_nvme_mmio_asqaddr(data); + n->bar.asq = data & NVME_ASQ_WR_MASK; + trace_nvme_mmio_asqaddr(n->bar.asq); break; case 0x2c: /* ASQ hi */ - n->bar.asq |= data << 32; + n->bar.asq |= (data << 32) & NVME_ASQ_WR_MASK; trace_nvme_mmio_asqaddr_hi(data, n->bar.asq); break; case 0x30: /* ACQ */ - trace_nvme_mmio_acqaddr(data); - n->bar.acq = data; + n->bar.acq = data & NVME_ACQ_WR_MASK; + trace_nvme_mmio_acqaddr(n->bar.acq); break; case 0x34: /* ACQ hi */ - n->bar.acq |= data << 32; + n->bar.acq |= (data << 32) & NVME_ACQ_WR_MASK; trace_nvme_mmio_acqaddr_hi(data, n->bar.acq); break; case 0x38: /* CMBLOC */ @@ -1390,7 +1401,7 @@ static void nvme_exit(PCIDevice *pci_dev) { NvmeCtrl *n = NVME(pci_dev); - nvme_clear_ctrl(n); + nvme_clear_ctrl(n, true); g_free(n->namespaces); g_free(n->cq); g_free(n->sq); diff --git a/include/block/nvme.h b/include/block/nvme.h index 849a6f3fa3..4da6740543 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -90,6 +90,11 @@ enum NvmeCcMask { CC_IOCQES_MASK = 0xf, }; +#define NVME_CC_WR_MASK (0x00fffff1) +#define NVME_AQA_WR_MASK (0x0fff0fff) +#define NVME_ASQ_WR_MASK (0xfffffffffffff000) +#define NVME_ACQ_WR_MASK (0xfffffffffffff000) + #define NVME_CC_EN(cc) ((cc >> CC_EN_SHIFT) & CC_EN_MASK) #define NVME_CC_CSS(cc) ((cc >> CC_CSS_SHIFT) & CC_CSS_MASK) #define NVME_CC_MPS(cc) ((cc >> CC_MPS_SHIFT) & CC_MPS_MASK)