From patchwork Sun May 26 16:29:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akinobu Mita X-Patchwork-Id: 10961807 X-Patchwork-Delegate: eduardo.valentin@ti.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 19A856C5 for ; Sun, 26 May 2019 16:29:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0944628A7A for ; Sun, 26 May 2019 16:29:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F188E28A92; Sun, 26 May 2019 16:29:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9036228A7A for ; Sun, 26 May 2019 16:29:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727913AbfEZQ3g (ORCPT ); Sun, 26 May 2019 12:29:36 -0400 Received: from mail-pl1-f194.google.com ([209.85.214.194]:39125 "EHLO mail-pl1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727865AbfEZQ3f (ORCPT ); Sun, 26 May 2019 12:29:35 -0400 Received: by mail-pl1-f194.google.com with SMTP id g9so6057548plm.6 for ; Sun, 26 May 2019 09:29:35 -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=1BqvJJeVVCvs0h+j3cS25Wx+bnAq+ov/vIwl8l2RLms=; b=BNLmADcNmNIb0xyZY4640jC68/vGLSOFkKRCsEnldzfXm8AvSwFH1rlc3vR88myTKT llk+6ct4c930HK0KJZ/jJH9epqKx46Oc4tKmEXN6XCAjM5OGwT3G4871cMVuGn+eXlHX JJK2CTcG9vo/If7fPsbwHngHLGuoRrQq7yuaKdPH7nUGR7q3YFGytJCkrjlLdpPkKuM6 M+55b4KOSyZSmzyRTTx+vntGakn2p6MumwMnLDar7YM+ywS3pYNzrUUJlfunY6ZfK1V+ 20bUuxYk6H7PMNXfEW+2rmJpXR8xCIAhaTeXP2ydt2b/ftXXCVPUllWsC9OUWqmka15U ciug== 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=1BqvJJeVVCvs0h+j3cS25Wx+bnAq+ov/vIwl8l2RLms=; b=Fvch4sZjtkvZtXQe8VQCLGiFT6tAi1DzpmPdQ7tdvomgdQYfb+QhVpuJsLKC8Wpzrt K7rhpB78cSXut0QnAZcg/Eh3RLYLq+rVClpS0gngnboKTevF5Ae68IZxmjEx7jM9787h t4Sbu+Aj4I+SdVQnrPAo4WzVBbdTvDzrGMk6HVbySmbZfBH+h0pVKIoeIuIWXAzcEo0i ZK59+HdRisHGKZv3Dcmx5zowULE/og+4JPoomy7ZzlrULQQdYQJPAU9DAf+hdkjf9/LL XRRarrhuC62TVMmYlW1E/eGL4r3fvccenfX/vSYnjE3LpzCa/5ek9NrX2SLTa1wsk/4t gJEw== X-Gm-Message-State: APjAAAWKIMH25DzPCbfFhRvnQ7BfK021psHy8Wq9rLF6LqAazJjjGrAz 9wi9LQsDji2tPSoX7dAQ1WGXdcXfbBk= X-Google-Smtp-Source: APXvYqwcMnR13bWuM/qj//SA6dYy9/isqc4TFI68/tH71VAeSbjJ7Qdub2NSgkNp6mEoef7NjCATUA== X-Received: by 2002:a17:902:4906:: with SMTP id u6mr22258670pld.220.1558888175361; Sun, 26 May 2019 09:29:35 -0700 (PDT) Received: from mita-MS-7A45.lan ([240f:34:212d:1:3427:8c7f:94e8:c445]) by smtp.gmail.com with ESMTPSA id a11sm8671107pff.128.2019.05.26.09.29.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 26 May 2019 09:29:34 -0700 (PDT) From: Akinobu Mita To: linux-nvme@lists.infradead.org, linux-pm@vger.kernel.org Cc: Keith Busch , Akinobu Mita Subject: [PATCH v3 1/3] nvme: Export get and set features Date: Mon, 27 May 2019 01:29:01 +0900 Message-Id: <1558888143-5121-2-git-send-email-akinobu.mita@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1558888143-5121-1-git-send-email-akinobu.mita@gmail.com> References: <1558888143-5121-1-git-send-email-akinobu.mita@gmail.com> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Keith Busch Future use intends to make use of both, so export these functions. And since their implementation is identical except for the opcode, provide a new function that implement both. [akinobu.mita@gmail.com>: fix line over 80 characters] Signed-off-by: Keith Busch Signed-off-by: Akinobu Mita Reviewed-by: Chaitanya Kulkarni Reviewed-by: Minwoo Im --- drivers/nvme/host/core.c | 24 +++++++++++++++++++++--- drivers/nvme/host/nvme.h | 6 ++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index c6a29a3..c950916 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1113,15 +1113,15 @@ static struct nvme_id_ns *nvme_identify_ns(struct nvme_ctrl *ctrl, return id; } -static int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11, - void *buffer, size_t buflen, u32 *result) +static int nvme_features(struct nvme_ctrl *dev, u8 op, unsigned int fid, + unsigned int dword11, void *buffer, size_t buflen, u32 *result) { struct nvme_command c; union nvme_result res; int ret; memset(&c, 0, sizeof(c)); - c.features.opcode = nvme_admin_set_features; + c.features.opcode = op; c.features.fid = cpu_to_le32(fid); c.features.dword11 = cpu_to_le32(dword11); @@ -1132,6 +1132,24 @@ static int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword return ret; } +int nvme_set_features(struct nvme_ctrl *dev, unsigned int fid, + unsigned int dword11, void *buffer, size_t buflen, + u32 *result) +{ + return nvme_features(dev, nvme_admin_set_features, fid, dword11, buffer, + buflen, result); +} +EXPORT_SYMBOL_GPL(nvme_set_features); + +int nvme_get_features(struct nvme_ctrl *dev, unsigned int fid, + unsigned int dword11, void *buffer, size_t buflen, + u32 *result) +{ + return nvme_features(dev, nvme_admin_get_features, fid, dword11, buffer, + buflen, result); +} +EXPORT_SYMBOL_GPL(nvme_get_features); + int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count) { u32 q_count = (*count - 1) | ((*count - 1) << 16); diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index de624ec..802aa19 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -460,6 +460,12 @@ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, union nvme_result *result, void *buffer, unsigned bufflen, unsigned timeout, int qid, int at_head, blk_mq_req_flags_t flags, bool poll); +int nvme_set_features(struct nvme_ctrl *dev, unsigned int fid, + unsigned int dword11, void *buffer, size_t buflen, + u32 *result); +int nvme_get_features(struct nvme_ctrl *dev, unsigned int fid, + unsigned int dword11, void *buffer, size_t buflen, + u32 *result); int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count); void nvme_stop_keep_alive(struct nvme_ctrl *ctrl); int nvme_reset_ctrl(struct nvme_ctrl *ctrl); From patchwork Sun May 26 16:29:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akinobu Mita X-Patchwork-Id: 10961809 X-Patchwork-Delegate: eduardo.valentin@ti.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A140B13AD for ; Sun, 26 May 2019 16:29:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8F97828A7A for ; Sun, 26 May 2019 16:29:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 830B728A92; Sun, 26 May 2019 16:29:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9D06B28A7A for ; Sun, 26 May 2019 16:29:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727926AbfEZQ3k (ORCPT ); Sun, 26 May 2019 12:29:40 -0400 Received: from mail-pl1-f196.google.com ([209.85.214.196]:46507 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727865AbfEZQ3k (ORCPT ); Sun, 26 May 2019 12:29:40 -0400 Received: by mail-pl1-f196.google.com with SMTP id r18so6056085pls.13 for ; Sun, 26 May 2019 09:29:39 -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=Z/7N3FhP/XzlTmVfCMWtwNrEmlfytpQrFSZU3h+cIgs=; b=E5SFvFP3Ji3dUkDY7ebCzwaQwEkRBw33dRHN0X1k9yq7BQQt9n8dDcZw39SGJWqHn7 3BrppduoJrgl5TqOznW4UOnwfuZ2+GtbbySH11xthBBN5crgl4d5aSnoaZV8BKQm3FoI Cxv9CyH8rfVaDTcO+qffPzk9DW1rZsDlz1lhbSmg7O9sCkfD3NpEYeBaUdqzvwG9bXU/ +Fgal2CaSmU6tjVuwTu1kbOOQs9TB/QF5iQLXJLp52eZG2tv5+03Yjen80ck0zdCePe3 2isyNjjIU1hf8w6p+p94QQcdBNGLVyLRx2rNmruhQ9DEDxLpqlUsYXXTnws/6TgGVqHM ft8Q== 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=Z/7N3FhP/XzlTmVfCMWtwNrEmlfytpQrFSZU3h+cIgs=; b=Qu7Cm4rautXEHIuCiDSpGwWpsIT3WFNMLswqJjV/rvtz8pbKT00t3adWGQKy+aJf50 fl+IghPo3j3TKp7nQo3wDVbAf3njPpqdrUf29G+6KIAZww5FpUntjw9TdzdhUTZtW6iE 02W7P72HqcD/13rgu/3Nf3A5VtO6nsb/JVATnSRSqY0JEPxpCnyVIDDT3bIY5OI5unTC dzswMZ0SJheQMZJ9WdaU5qNRC4H1COdZb81FL0xxXOGo4pMmNqsftF+EF71HCztumWEy NlXq8n9bYkbnnQ2HUqVSMNZEq30OyKtb2rnkXmwPEAlMHlKIuEs9+mDlE5ZYE4VrD4Ac 0HGw== X-Gm-Message-State: APjAAAWJ+De5T2pJstapMdWGAMsFbn8UviWDZ3Smvo+8IncFU57fagFu LPUfRrICekZSwS0KgLebEB4= X-Google-Smtp-Source: APXvYqyugbUHAtukgyvI2u8HFF5I8sQ5OK/HnG4TQfh9k2Xvmzor2nfbk87/fIDuPe8SAxAW/zQjeQ== X-Received: by 2002:a17:902:8a8f:: with SMTP id p15mr28616390plo.157.1558888179086; Sun, 26 May 2019 09:29:39 -0700 (PDT) Received: from mita-MS-7A45.lan ([240f:34:212d:1:3427:8c7f:94e8:c445]) by smtp.gmail.com with ESMTPSA id a11sm8671107pff.128.2019.05.26.09.29.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 26 May 2019 09:29:38 -0700 (PDT) From: Akinobu Mita To: linux-nvme@lists.infradead.org, linux-pm@vger.kernel.org Cc: Akinobu Mita , Zhang Rui , Eduardo Valentin , Daniel Lezcano , Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg , Minwoo Im , Kenneth Heitke , Chaitanya Kulkarni Subject: [PATCH v3 2/3] nvme: add thermal zone devices Date: Mon, 27 May 2019 01:29:02 +0900 Message-Id: <1558888143-5121-3-git-send-email-akinobu.mita@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1558888143-5121-1-git-send-email-akinobu.mita@gmail.com> References: <1558888143-5121-1-git-send-email-akinobu.mita@gmail.com> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The NVMe controller reports up to nine temperature values in the SMART / Health log page (the composite temperature and temperature sensor 1 through temperature sensor 8). This provides these temperatures via thermal zone devices. Once the controller is identified, the thermal zone devices are created for all implemented temperature sensors including the composite temperature. /sys/class/thermal/thermal_zone[0-*]: |---type: 'nvme-temp' |---temp: Temperature |---trip_point_0_temp: Over temperature threshold The thermal_zone[0-*] contains a 'device' symlink to the corresponding nvme device. On the other hand, the following symlinks to the thermal zone devices are created in the nvme device sysfs directory. - temp0: Composite temperature - temp1: Temperature sensor 1 ... - temp8: Temperature sensor 8 Cc: Zhang Rui Cc: Eduardo Valentin Cc: Daniel Lezcano Cc: Keith Busch Cc: Jens Axboe Cc: Christoph Hellwig Cc: Sagi Grimberg Cc: Minwoo Im Cc: Kenneth Heitke Cc: Chaitanya Kulkarni Signed-off-by: Akinobu Mita --- * v3 - Change the type name of thermal zone devices from 'nvme_temp' to 'nvme_temp' - Pass a NULL to the status argument of nvme_set_feature() - Change the name of symbolic link from 'nvme_temp' to 'temp' - Don't make it fatal error if the device provides a response - Don't register thermal zone for composite temperature if smart log reports zero value - Move the thermal zones registration and unregistration into the core module. drivers/nvme/host/core.c | 288 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/nvme/host/nvme.h | 9 ++ include/linux/nvme.h | 5 + 3 files changed, 302 insertions(+) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index c950916..4c8271a 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2200,6 +2200,289 @@ static void nvme_set_latency_tolerance(struct device *dev, s32 val) } } +#ifdef CONFIG_THERMAL + +static int nvme_get_temp(struct nvme_ctrl *ctrl, unsigned int sensor, int *temp) +{ + struct nvme_smart_log *log; + int ret; + + BUILD_BUG_ON(ARRAY_SIZE(log->temp_sensor) + 1 != + ARRAY_SIZE(ctrl->tzdev)); + + if (WARN_ON_ONCE(sensor > ARRAY_SIZE(log->temp_sensor))) + return -EINVAL; + + log = kzalloc(sizeof(*log), GFP_KERNEL); + if (!log) + return -ENOMEM; + + ret = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_SMART, 0, + log, sizeof(*log), 0); + if (ret) { + ret = ret > 0 ? -EINVAL : ret; + goto free_log; + } + + if (sensor) + *temp = le16_to_cpu(log->temp_sensor[sensor - 1]); + else + *temp = get_unaligned_le16(log->temperature); + +free_log: + kfree(log); + + return ret; +} + +static unsigned int nvme_tz_type_to_sensor(const char *type) +{ + int instance; + unsigned int sensor; + + if (sscanf(type, "nvme%d_temp%u", &instance, &sensor) != 2) + return UINT_MAX; + + return sensor; +} + +#define KELVIN_TO_MILLICELSIUS(t) DECI_KELVIN_TO_MILLICELSIUS((t) * 10) +#define MILLICELSIUS_TO_KELVIN(t) ((MILLICELSIUS_TO_DECI_KELVIN(t) + 5) / 10) + +static int nvme_tz_get_temp(struct thermal_zone_device *tzdev, int *temp) +{ + unsigned int sensor = nvme_tz_type_to_sensor(tzdev->type); + struct nvme_ctrl *ctrl = tzdev->devdata; + int ret; + + ret = nvme_get_temp(ctrl, sensor, temp); + if (!ret) + *temp = KELVIN_TO_MILLICELSIUS(*temp); + + return ret; +} + +static int nvme_tz_get_trip_type(struct thermal_zone_device *tzdev, + int trip, enum thermal_trip_type *type) +{ + *type = THERMAL_TRIP_ACTIVE; + + return 0; +} + +static int nvme_get_over_temp_thresh(struct nvme_ctrl *ctrl, + unsigned int sensor, int *temp) +{ + unsigned int threshold = sensor << NVME_TEMP_THRESH_SELECT_SHIFT; + int status; + int ret; + + if (WARN_ON_ONCE(sensor >= ARRAY_SIZE(ctrl->tzdev))) + return -EINVAL; + + ret = nvme_get_features(ctrl, NVME_FEAT_TEMP_THRESH, threshold, NULL, 0, + &status); + if (!ret) + *temp = status & NVME_TEMP_THRESH_MASK; + + return ret > 0 ? -EINVAL : ret; +} + +static int nvme_set_over_temp_thresh(struct nvme_ctrl *ctrl, + unsigned int sensor, int temp) +{ + unsigned int threshold = sensor << NVME_TEMP_THRESH_SELECT_SHIFT; + int ret; + + if (WARN_ON_ONCE(sensor >= ARRAY_SIZE(ctrl->tzdev))) + return -EINVAL; + + if (temp > NVME_TEMP_THRESH_MASK) + return -EINVAL; + + threshold |= temp & NVME_TEMP_THRESH_MASK; + + ret = nvme_set_features(ctrl, NVME_FEAT_TEMP_THRESH, threshold, NULL, 0, + NULL); + + return ret > 0 ? -EINVAL : ret; +} + +static int nvme_tz_get_trip_temp(struct thermal_zone_device *tzdev, + int trip, int *temp) +{ + unsigned int sensor = nvme_tz_type_to_sensor(tzdev->type); + struct nvme_ctrl *ctrl = tzdev->devdata; + int ret; + + ret = nvme_get_over_temp_thresh(ctrl, sensor, temp); + if (!ret) + *temp = KELVIN_TO_MILLICELSIUS(*temp); + + return ret; +} + +static int nvme_tz_set_trip_temp(struct thermal_zone_device *tzdev, + int trip, int temp) +{ + unsigned int sensor = nvme_tz_type_to_sensor(tzdev->type); + struct nvme_ctrl *ctrl = tzdev->devdata; + + temp = MILLICELSIUS_TO_KELVIN(temp); + + return nvme_set_over_temp_thresh(ctrl, sensor, temp); +} + +static struct thermal_zone_device_ops nvme_tz_ops = { + .get_temp = nvme_tz_get_temp, + .get_trip_type = nvme_tz_get_trip_type, + .get_trip_temp = nvme_tz_get_trip_temp, + .set_trip_temp = nvme_tz_set_trip_temp, +}; + +static struct thermal_zone_params nvme_tz_params = { + .governor_name = "user_space", + .no_hwmon = true, +}; + +static struct thermal_zone_device * +nvme_thermal_zone_register(struct nvme_ctrl *ctrl, unsigned int sensor) +{ + struct thermal_zone_device *tzdev; + char name[THERMAL_NAME_LENGTH]; + int ret; + + snprintf(name, sizeof(name), "nvme%d_temp%u", ctrl->instance, sensor); + + tzdev = thermal_zone_device_register(name, 1, 1, ctrl, &nvme_tz_ops, + &nvme_tz_params, 0, 0); + if (IS_ERR(tzdev)) { + dev_err(ctrl->device, + "Failed to register thermal zone device: %ld\n", + PTR_ERR(tzdev)); + return tzdev; + } + + snprintf(name, sizeof(name), "temp%d", sensor); + ret = sysfs_create_link(&ctrl->ctrl_device.kobj, &tzdev->device.kobj, + name); + if (ret) + goto device_unregister; + + ret = sysfs_create_link(&tzdev->device.kobj, + &ctrl->ctrl_device.kobj, "device"); + if (ret) + goto remove_link; + + return tzdev; + +remove_link: + sysfs_remove_link(&ctrl->ctrl_device.kobj, name); +device_unregister: + thermal_zone_device_unregister(tzdev); + + return ERR_PTR(ret); +} + +/** + * nvme_thermal_zones_register() - register nvme thermal zone devices + * @ctrl: controller instance + * + * This function creates up to nine thermal zone devices for all implemented + * temperature sensors including the composite temperature. + * Each thermal zone device provides a single trip point temperature that is + * associated with an over temperature threshold. + */ +static int nvme_thermal_zones_register(struct nvme_ctrl *ctrl) +{ + struct nvme_smart_log *log; + int ret; + int i; + + log = kzalloc(sizeof(*log), GFP_KERNEL); + if (!log) + return 0; /* non-fatal error */ + + ret = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_SMART, 0, + log, sizeof(*log), 0); + if (ret) { + dev_err(ctrl->device, "Failed to get SMART log: %d\n", ret); + /* If the device provided a response, then it's non-fatal */ + if (ret > 0) + ret = 0; + goto free_log; + } + + for (i = 0; i < ARRAY_SIZE(ctrl->tzdev); i++) { + struct thermal_zone_device *tzdev; + int temp; + + if (i) + temp = le16_to_cpu(log->temp_sensor[i - 1]); + else + temp = get_unaligned_le16(log->temperature); + + /* + * All implemented temperature sensors report a non-zero value + * in temperature sensor fields in the smart log page. + */ + if (!temp) + continue; + if (ctrl->tzdev[i]) + continue; + + tzdev = nvme_thermal_zone_register(ctrl, i); + if (!IS_ERR(tzdev)) + ctrl->tzdev[i] = tzdev; + } + +free_log: + kfree(log); + + return ret; +} + +/** + * nvme_thermal_zones_unregister() - unregister nvme thermal zone devices + * @ctrl: controller instance + * + * This function removes the registered thermal zone devices and symlinks. + */ +static void nvme_thermal_zones_unregister(struct nvme_ctrl *ctrl) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ctrl->tzdev); i++) { + struct thermal_zone_device *tzdev = ctrl->tzdev[i]; + char name[20]; + + if (!tzdev) + continue; + + sysfs_remove_link(&tzdev->device.kobj, "device"); + + snprintf(name, sizeof(name), "temp%d", i); + sysfs_remove_link(&ctrl->ctrl_device.kobj, name); + + thermal_zone_device_unregister(tzdev); + + ctrl->tzdev[i] = NULL; + } +} + +#else + +static inline int nvme_thermal_zones_register(struct nvme_ctrl *ctrl) +{ + return 0; +} + +static inline void nvme_thermal_zones_unregister(struct nvme_ctrl *ctrl) +{ +} + +#endif /* CONFIG_THERMAL */ + struct nvme_core_quirk_entry { /* * NVMe model and firmware strings are padded with spaces. For @@ -2754,6 +3037,10 @@ int nvme_init_identify(struct nvme_ctrl *ctrl) if (ret < 0) return ret; + ret = nvme_thermal_zones_register(ctrl); + if (ret < 0) + return ret; + ctrl->identified = true; return 0; @@ -3756,6 +4043,7 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl) { nvme_mpath_stop(ctrl); nvme_stop_keep_alive(ctrl); + nvme_thermal_zones_unregister(ctrl); flush_work(&ctrl->async_event_work); cancel_work_sync(&ctrl->fw_act_work); } diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 802aa19..53f0b24 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -15,6 +15,7 @@ #include #include #include +#include extern unsigned int nvme_io_timeout; #define NVME_IO_TIMEOUT (nvme_io_timeout * HZ) @@ -248,6 +249,14 @@ struct nvme_ctrl { struct page *discard_page; unsigned long discard_page_busy; + +#ifdef CONFIG_THERMAL + /* + * tzdev[0]: composite temperature + * tzdev[1-8]: temperature sensor 1 through 8 + */ + struct thermal_zone_device *tzdev[9]; +#endif }; enum nvme_iopolicy { diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 658ac75..54f0a13 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -780,6 +780,11 @@ struct nvme_write_zeroes_cmd { /* Features */ +enum { + NVME_TEMP_THRESH_MASK = 0xffff, + NVME_TEMP_THRESH_SELECT_SHIFT = 16, +}; + struct nvme_feat_auto_pst { __le64 entries[32]; }; From patchwork Sun May 26 16:29:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akinobu Mita X-Patchwork-Id: 10961811 X-Patchwork-Delegate: eduardo.valentin@ti.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CC36D13AD for ; Sun, 26 May 2019 16:29:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BB44328A7A for ; Sun, 26 May 2019 16:29:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AEF4E28A92; Sun, 26 May 2019 16:29:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3C2F928A7A for ; Sun, 26 May 2019 16:29:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727935AbfEZQ3n (ORCPT ); Sun, 26 May 2019 12:29:43 -0400 Received: from mail-pf1-f196.google.com ([209.85.210.196]:42001 "EHLO mail-pf1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727865AbfEZQ3n (ORCPT ); Sun, 26 May 2019 12:29:43 -0400 Received: by mail-pf1-f196.google.com with SMTP id r22so5254763pfh.9 for ; Sun, 26 May 2019 09:29:43 -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=d9UooUjAx6NBScigOGnH7Gz4QNuQjVumDoAAYHZwJ0I=; b=iJnOYm7COmsXgX5f8j5IS+0oQvSzQ6Yvq70wyjHOGa0RULDcfSKhqE2UWULKt2ZtgV STtCPlFp9E0CLBT8ESwbD4zGEKkUkHuJ3jdiVi+btWnIAXJo48wqrNxhYS9KDUbMiih4 lP2AZzwpPDTDZsjns2zad7pxI4IEhtD5/3jrSIVK70CePseHq3V5Po8NIJpFXJzfOBQr SNO8IbtaNQ78kAceRNRrTvAytX3T1x8aATAq1Ceh6Qwdtl1dXPePywGHE57NFTjDgAWf YqsT3Ociq8yr2sylmrYDzmO2ZhZMXL1m9ynLr6r3HlEtP01InL9NBPYkWKbEfQ/LbQ+C Srsg== 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=d9UooUjAx6NBScigOGnH7Gz4QNuQjVumDoAAYHZwJ0I=; b=dZdj2SMSU/9WdwweE67PcfCnJNnhvUWYEQ2Y6X7h09tG9rI0kHsFHc/ZGKEGumfZok VlHCKv7jSuoaWEGUPJV4om8amCeHQJR96q4AzDkd2xOJgSvRw1bNQiDdUc+asGCTtNHx t0mvwFVEil3h/0f+p9D6/jj3mlyGSfShqGWmCH5AFkypsx6HUis01zLkRcvehETLkEJh 7IxUzEd+YUrMtkQkSfym4p0L+n3ojl3Kj1Xx6nVN09GrDaSzxhgaXK0nmMwTbTe/PIEW PzxjzjOX+k7sC21m1uKHSOk9j2425z/lg9Vb4rHKa4r2+UtbMltlJmRTofDfJiKx5efo Vc5A== X-Gm-Message-State: APjAAAUiLpbhPgl+8XcyNvxCP7iXw4uI5sTtQYweEULtOiKnMqZUDQgx JbAfML/SbjpqoW2L3uDE/w8= X-Google-Smtp-Source: APXvYqws+ecJtvqyZ24/vvgqtYW/1tC7KALjt0s11+al3CEJpigcuD4z8IOh5k+7gY1dQmXNq5KMpw== X-Received: by 2002:a17:90a:25ca:: with SMTP id k68mr25990305pje.14.1558888182933; Sun, 26 May 2019 09:29:42 -0700 (PDT) Received: from mita-MS-7A45.lan ([240f:34:212d:1:3427:8c7f:94e8:c445]) by smtp.gmail.com with ESMTPSA id a11sm8671107pff.128.2019.05.26.09.29.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 26 May 2019 09:29:42 -0700 (PDT) From: Akinobu Mita To: linux-nvme@lists.infradead.org, linux-pm@vger.kernel.org Cc: Akinobu Mita , Zhang Rui , Eduardo Valentin , Daniel Lezcano , Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg , Minwoo Im , Kenneth Heitke , Chaitanya Kulkarni Subject: [PATCH v3 3/3] nvme: notify thermal framework when temperature threshold events occur Date: Mon, 27 May 2019 01:29:03 +0900 Message-Id: <1558888143-5121-4-git-send-email-akinobu.mita@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1558888143-5121-1-git-send-email-akinobu.mita@gmail.com> References: <1558888143-5121-1-git-send-email-akinobu.mita@gmail.com> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The NVMe controller supports the temperature threshold feature (Feature Identifier 04h) that enables to configure the asynchronous event request command to complete when the temperature is crossed its corresponding temperature threshold. This enables the reporting of asynchronous events from the controller when the temperature reached or exceeded a temperature threshold. In the case of the temperature threshold conditions, this notifies the thermal framework. Cc: Zhang Rui Cc: Eduardo Valentin Cc: Daniel Lezcano Cc: Keith Busch Cc: Jens Axboe Cc: Christoph Hellwig Cc: Sagi Grimberg Cc: Minwoo Im Cc: Kenneth Heitke Cc: Chaitanya Kulkarni Signed-off-by: Akinobu Mita --- * v3 - No changes since v2 drivers/nvme/host/core.c | 28 ++++++++++++++++++++++++++++ include/linux/nvme.h | 7 +++++++ 2 files changed, 35 insertions(+) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 4c8271a..26c8b59 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1186,6 +1186,9 @@ static void nvme_enable_aen(struct nvme_ctrl *ctrl) u32 result, supported_aens = ctrl->oaes & NVME_AEN_SUPPORTED; int status; + if (IS_ENABLED(CONFIG_THERMAL)) + supported_aens |= NVME_SMART_CRIT_TEMPERATURE; + if (!supported_aens) return; @@ -2470,6 +2473,16 @@ static void nvme_thermal_zones_unregister(struct nvme_ctrl *ctrl) } } +static void nvme_thermal_notify_framework(struct nvme_ctrl *ctrl) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ctrl->tzdev); i++) { + if (ctrl->tzdev[i]) + thermal_notify_framework(ctrl->tzdev[i], 0); + } +} + #else static inline int nvme_thermal_zones_register(struct nvme_ctrl *ctrl) @@ -2481,6 +2494,10 @@ static inline void nvme_thermal_zones_unregister(struct nvme_ctrl *ctrl) { } +static void nvme_thermal_notify_framework(struct nvme_ctrl *ctrl) +{ +} + #endif /* CONFIG_THERMAL */ struct nvme_core_quirk_entry { @@ -3901,6 +3918,16 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl) } EXPORT_SYMBOL_GPL(nvme_remove_namespaces); +static void nvme_handle_aen_smart(struct nvme_ctrl *ctrl, u32 result) +{ + u32 aer_type = result & NVME_AER_TYPE_MASK; + u32 aer_info = (result >> NVME_AER_INFO_SHIFT) & NVME_AER_INFO_MASK; + + if (aer_type == NVME_AER_SMART && + aer_info == NVME_AER_SMART_TEMP_THRESH) + nvme_thermal_notify_framework(ctrl); +} + static void nvme_aen_uevent(struct nvme_ctrl *ctrl) { char *envp[2] = { NULL, NULL }; @@ -3922,6 +3949,7 @@ static void nvme_async_event_work(struct work_struct *work) struct nvme_ctrl *ctrl = container_of(work, struct nvme_ctrl, async_event_work); + nvme_handle_aen_smart(ctrl, ctrl->aen_result); nvme_aen_uevent(ctrl); ctrl->ops->submit_async_event(ctrl); } diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 54f0a13..8e7d599 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -507,6 +507,7 @@ enum { }; enum { + NVME_AER_TYPE_MASK = 0x7, NVME_AER_ERROR = 0, NVME_AER_SMART = 1, NVME_AER_NOTICE = 2, @@ -515,6 +516,12 @@ enum { }; enum { + NVME_AER_INFO_SHIFT = 8, + NVME_AER_INFO_MASK = 0xff, + NVME_AER_SMART_TEMP_THRESH = 0x01, +}; + +enum { NVME_AER_NOTICE_NS_CHANGED = 0x00, NVME_AER_NOTICE_FW_ACT_STARTING = 0x01, NVME_AER_NOTICE_ANA = 0x03,