From nobody Mon May 25 04:35:09 2026 Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CEBC3330675 for ; Sun, 24 May 2026 21:06:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779656767; cv=none; b=JalOZytCRX6+FxhdMQl0Ixx2+2LAFyjGrSNG4v7i734LZt4aDWXssNQjlbzFiCVSRtVkQZAIwJpsYKrcjoAjWb1K9iUDC1ctyytg8cWD/TI2ge6zvFu5l8zs3jWGvj+ekosjOPg5xWbEfDZUTrEtPUEaXw/IuQLPJ4o9QtfCNy8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779656767; c=relaxed/simple; bh=Bt3my+6l00h9cgScvXgngonjEUgxY/cU8mMorKuK7Cg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YWLxDrcQT0xb9B3NJkCOD1x0J5CoMi37Q358Sedcd9IIBUjmNX3yZmmV36HfdSjyERorASK9J3uhfvqEYtBlGipE8RSFjfUAQTAD2xwjTbD7HkxPQczl6+7iwDXteUX9fnHRk6mM645DKTX28ZKvPjzXEr7au5igPl7+5lD10o8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=eVdmu+3/; arc=none smtp.client-ip=209.85.128.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="eVdmu+3/" Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-4903997fcb5so32936515e9.2 for ; Sun, 24 May 2026 14:06:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779656763; x=1780261563; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=f8+wQM4a4tsMzXZ7biCKDr40TVU55tRrbtX6KIaXn24=; b=eVdmu+3/dRcaOdCzy4MIt1RLpEdCXEf3fOvULXgm9GifoGPgKMVFk+3fU362cK4eMi otDAIOSDnvJ7z/AXuSpjAdv9ajflE/QNSDi45yYuXftJP/iCFCDEmj8Il7Ls9chLa6fC pKZCMkLmuc4SiaFsQk5QpmyvQjtKbrlYZ9Sg0fZKOzH7ysknLsv+ysoqXDHLxwc35dZo gO97nGHCbnrtBInNgzzd31pNvtLli04Dd/NLATn6whXJS+JPlZGzbnKltxPdsh4X3kQR 16lneip3b5QdoV68275bihIsWO9C3G8UO2FG9Zcl5d5gvaUEDR/2qJgrFe9Go18KQiU7 fE/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779656763; x=1780261563; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=f8+wQM4a4tsMzXZ7biCKDr40TVU55tRrbtX6KIaXn24=; b=ETJ0Yf+z2OYXaJlG0ypaj2oUQfZfBJBJlEOIeXHxj9uoLAtCw8xygdbbVO685gG6Rp nl8TFRPAZUn/SlGBFE1CeNwzPZMHnXQcXBQDQ2gl3ZBmy3vJCskampiAOYebDWTCHvzK Z/soFPMKDZ3czW5EW0S/LBEWgwtokJREzkbK7+mgpK9NDuX2ke2izon/ksy0+gKBYoy0 0mB++hipgvlX/RznPyLCW9tEtNnOme+hyuQEcTP1RyuvEhF5ck8QvBLeboW9XK1Y7Z7O cITfJHPIjv1roVTBf7ZzGMrH/KorFAfcX9Ecr0dcgHFRhzwO4Qo0EDzIBXEuzUWJwHjz YBeA== X-Forwarded-Encrypted: i=1; AFNElJ8DeTJPSfebQJRZZkR1OHpjLgh8In7w1NJAbdTjxqNzcOQ5SmF7pguvE4Y5JRizm6JjzPZEAN0Wqh51XPQ=@vger.kernel.org X-Gm-Message-State: AOJu0Yyp/PUQXXBFvhFDEoJ3xhAS1eer9PnrnMqjngzQPogVaXl6W2ax SA+aOaL+iS2w5zk2ONdBecqbgCRXKZ4ENgA80XK8Yovj0SlDoDdwl7QN X-Gm-Gg: Acq92OEyXJyfIvkJbZMEi9OfwyDVr5Yh8Z2WMLXNNbw0fvllIrRyuliTeHxfPvyTulB X/q9HoVv2aSRyTft1ml/gNmGCqLGuLxLZ0KfOqNQmx540Vh09dDHSmJkIdBPBQAEdIR7UYu/3yl Ah1lAb6f0WzHWL9L5E8W1b+8pCMmIcrlqVRlLGWpOYjtJiqopK2x0EQNVcVtwi4kAqAuZUXJ6Oz dgBXjawNxacEhDJbgxECZx9QaoPFPaNOft1vSiRZgfYPV1EHpcAh1KS4wX37a6LB0nzviLrc7oo X/9qac1+Qs8t3N7AIy5gGVfXQixfABMulC2GGzQvQ3A8GLHLfJ611MNfPjyn5njiE/PdPitGx54 M5Nk8Qn/ybZ5A1SwjNaTt4HZnji5OYfH9PxhUl3qtNf/MYa8qRb+Jy7YgMwDCgFgKcsStAGyNqE pVTB7EBOrFr4UgP0ffXQ== X-Received: by 2002:a05:600c:474a:b0:490:51e2:d992 with SMTP id 5b1f17b1804b1-49051e2daa6mr127785455e9.13.1779656762894; Sun, 24 May 2026 14:06:02 -0700 (PDT) Received: from localhost ([2603:c027:c000:3cde::f]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49059fb42dasm85170925e9.7.2026.05.24.14.06.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 24 May 2026 14:06:02 -0700 (PDT) From: Louis Sautier To: Sathya Prakash , Sreekanth Reddy , Suganath Prabu Subramani , Ranjan Kumar , "James E.J. Bottomley" , "Martin K. Petersen" Cc: Guenter Roeck , MPT-FusionLinux.pdl@broadcom.com, linux-scsi@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/2] scsi: mpt3sas: add IO Unit Page 7 config accessor Date: Sun, 24 May 2026 23:05:44 +0200 Message-ID: <20260524210545.1333637-2-sautier.louis@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260524210545.1333637-1-sautier.louis@gmail.com> References: <20260524210545.1333637-1-sautier.louis@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add mpt3sas_config_get_iounit_pg7(), mirroring the existing iounit page accessors. Used by the hwmon driver added in the following patch to read the IOC and board temperatures. Assisted-by: Claude:claude-opus-4-7 Signed-off-by: Louis Sautier --- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 ++ drivers/scsi/mpt3sas/mpt3sas_config.c | 36 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt= 3sas_base.h index d4597d058705..c655742d0dde 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1904,6 +1904,8 @@ int mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAP= TER *ioc, Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz); int mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigR= eply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page); +int mpt3sas_config_get_iounit_pg7(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage7_t *config_page); int mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigR= eply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page); int mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/m= pt3sas_config.c index 45ac853e1289..ef07825046bc 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c @@ -991,6 +991,42 @@ mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *= ioc, return r; } =20 +/** + * mpt3sas_config_get_iounit_pg7 - obtain iounit page 7 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Return: 0 for success, non-zero for failure. + */ +int +mpt3sas_config_get_iounit_pg7(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage7_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function =3D MPI2_FUNCTION_CONFIG; + mpi_request.Action =3D MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType =3D MPI2_CONFIG_PAGETYPE_IO_UNIT; + mpi_request.Header.PageNumber =3D 7; + mpi_request.Header.PageVersion =3D MPI2_IOUNITPAGE7_PAGEVERSION; + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); + r =3D _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); + if (r) + goto out; + + mpi_request.Action =3D MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + r =3D _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + out: + return r; +} + /** * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8 * @ioc: per adapter object --=20 2.54.0 From nobody Mon May 25 04:35:09 2026 Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 36467333434 for ; Sun, 24 May 2026 21:06:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779656770; cv=none; b=Hqk0KmACULP1VMVM2MVeoQTNGyG5+J9sKflZRUuH+7fSXHkVcW2SCcjunI8iW3QV3gTwjH/Ur57Y/5HryHefETI0Rho5HsCZKflYC48cPvVBQk5H1R3SfAbbPV3lqL9/1wfotzzCIFqs90xBJsNRjhLyNyw22T5DgheZQbdmLng= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779656770; c=relaxed/simple; bh=q6nh2I0IJZkv6Er5gFdVYCsD7i1PPhsOiOfEvHDC0mM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=jfnCPle3d1kJdmYaWydIPw+DZGFkWkh1C+ISGUFH34kpOXlcTa8y3jRERv2Bm9KNC/zp+MLT2jMGqrNZLHfjWTgjeJFtPMzWOw/NL7bWSofbJPgOWlfmFnVZsFJRvw7QocrpFIONOrSxyx1xL7PdzXH7dtN5KAUqZ1bUkep9zyA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=eCeeTv7d; arc=none smtp.client-ip=209.85.128.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="eCeeTv7d" Received: by mail-wm1-f48.google.com with SMTP id 5b1f17b1804b1-4904c1ce4c1so22004955e9.3 for ; Sun, 24 May 2026 14:06:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779656764; x=1780261564; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=b4S5uxuhqvO1rYma67W1OJrzGbqLrgJBV9Tf3hpikpE=; b=eCeeTv7doPGh5iccSBFofQHwQUyVPxLFWxnynm4bMgOkxuJSIusuGuBcu8Ovsrc5ny 4VhodLY0qqoSun3KNUiSs3SgjNLnJaT33k1W7hG1cLdootjEwT7sb0Vq7zsZQp3OAzRR 1Wxu8abxkLsy8XGwO6QXfwh737IOd1b4LUPjAfzlC8I+42ENHZFKMykVnaOjFpBGP2te D9MtYod3lgVq11duPw/HrAnMn7TjNYr71Zq+LrrrQ8WgiuML1HZblSKmRB/qB7Hqw5Jn aWknQ6GspnWE0yiOiSR1tmN7n37VKRi3FGj8wGWjnyN4INuWSLTSVHgJ8VCsdnovsu2q vCPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779656764; x=1780261564; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=b4S5uxuhqvO1rYma67W1OJrzGbqLrgJBV9Tf3hpikpE=; b=jsyryws120lBmlW7JdQgrdgfsvg+uORI1XPzNv/iF1fsnxcHhHBcctq7y7tjJm0ccU MDbdipzm3/OR0/JGiM7eTZ1SlQ3hErBvcwPqmYbjN3MJGcRVSWriUcSi2yh1ns6xVv6R 7uGQKIleZcFHtvptOxR72s+Yl5oGSXRCHT7NhpiMmkle6A/MUxvzWcaaEJxxPwEOtZOl EXVWm1U/Q/hOHA6qss+3GYD0jK0Z7W5R9j2fhhg93rcj+b90lIv6DBOPXJX1AbfjNmIJ RMf3X8ElIX1fsxwF/TW6TLJJTvBlF9yFddN8Y7pZBIwwUozZg8XYl8iD7gmSZJN9lyo5 oeng== X-Forwarded-Encrypted: i=1; AFNElJ/d8uWbsyxPYYUsuHG2cvS2GNRhGvJD+0SXq351js050q5+cL6PTzg1KpQlqPHG0BgW2zx5YqXb6zvYYDk=@vger.kernel.org X-Gm-Message-State: AOJu0Yz03QQ0yiqo32T70FcmY8IsUc54AUyEvy9TeX1yijng1nBNuCz4 RXgLkG3Muf8LkCDI08ny4UjxL9gencdBs4Fh58oiApkIp5XJBggRbvyw X-Gm-Gg: Acq92OEiu7Z0TPX0mrKodJ41klRZaNtz/Hzd91EwfYyTKFmpvn7Zuq8x6fEwJlSzdL7 xelvge9UwQKskEtGpycyh3udomSpfD2W32kzHUqC0fUf2YEPqkDge04VlVaNb2MGsrmVqD9QdwJ vVL8fiOAVt2BLEhlJtUEof3vEliOF6nug2b0oYEW2G+am5DoJrycWvFBNcfxIznND+Hdp01nAnR NYjJ5bICFioGFEbyD8e30GmE838lmAplULsPdTf6TsMcpNHFSl2+AsgnKVn5UTYmr1C592SKoeN FixQ/g6yraIBbDmyGY2EdJS9fh20qnlO8P/2CjFx2xiNg/SbKnbRUUTZqOvoCdaccNduKXzVQ5j RgA/Ea6jHwivXRCpNGGgq6xixGnjyH/s67/2RXTUka9rlWKnnE/AhdK7nX2Yxn0K+juR9ZbrHFy PAqeID3jbIXDBCw6TFMw== X-Received: by 2002:a05:600c:354d:b0:48a:65a5:750f with SMTP id 5b1f17b1804b1-490426d0785mr207680155e9.21.1779656763467; Sun, 24 May 2026 14:06:03 -0700 (PDT) Received: from localhost ([2603:c027:c000:3cde::f]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49059fb42dasm85170925e9.7.2026.05.24.14.06.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 24 May 2026 14:06:03 -0700 (PDT) From: Louis Sautier To: Sathya Prakash , Sreekanth Reddy , Suganath Prabu Subramani , Ranjan Kumar , "James E.J. Bottomley" , "Martin K. Petersen" Cc: Guenter Roeck , MPT-FusionLinux.pdl@broadcom.com, linux-scsi@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/2] scsi: mpt3sas: add hwmon support Date: Sun, 24 May 2026 23:05:45 +0200 Message-ID: <20260524210545.1333637-3-sautier.louis@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260524210545.1333637-1-sautier.louis@gmail.com> References: <20260524210545.1333637-1-sautier.louis@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Expose the IOC and board temperature sensors of LSI / Broadcom SAS HBAs through hwmon. Readings come from MPI IO Unit Page 7 via the accessor added in the preceding patch. The same fields are exposed by Broadcom's userspace tooling through the /dev/mpt[23]ctl ioctl path (typically root-only): IOCTemperature and BoardTemperature in lsiutil; ROC and Controller in storcli. With this driver, sensors(1) shows them unprivileged: $ sensors mpt3sas-pci-0200 mpt3sas-pci-0200 Adapter: PCI adapter IOC: +42.0=C2=B0C Each channel is gated independently by its *TemperatureUnits field through is_visible(); cards that populate only one sensor expose only one input file, and cards that populate neither do not register an hwmon device. Built into mpt3sas.ko under a new CONFIG_SCSI_MPT3SAS_HWMON Kconfig option. Assisted-by: Claude:claude-opus-4-7 Signed-off-by: Louis Sautier --- drivers/scsi/mpt3sas/Kconfig | 9 ++ drivers/scsi/mpt3sas/Makefile | 2 + drivers/scsi/mpt3sas/mpt3sas_base.h | 17 +++ drivers/scsi/mpt3sas/mpt3sas_hwmon.c | 200 +++++++++++++++++++++++++++ drivers/scsi/mpt3sas/mpt3sas_scsih.c | 6 + 5 files changed, 234 insertions(+) create mode 100644 drivers/scsi/mpt3sas/mpt3sas_hwmon.c diff --git a/drivers/scsi/mpt3sas/Kconfig b/drivers/scsi/mpt3sas/Kconfig index c299f7e078fb..a2e1e112b7a3 100644 --- a/drivers/scsi/mpt3sas/Kconfig +++ b/drivers/scsi/mpt3sas/Kconfig @@ -73,6 +73,15 @@ config SCSI_MPT3SAS_MAX_SGE can be 256. However, it may decreased down to 16. Decreasing this parameter will reduce memory requirements on a per controller instance. =20 +config SCSI_MPT3SAS_HWMON + bool "LSI MPT Fusion SAS hwmon support" + depends on SCSI_MPT3SAS && HWMON + depends on !(SCSI_MPT3SAS=3Dy && HWMON=3Dm) + help + Say Y here to expose the IOC and board temperature sensors of + LSI / Broadcom SAS HBAs (such as the 9300, 9400, and 9500 series) + through hwmon. + config SCSI_MPT2SAS tristate "Legacy MPT2SAS config option" default n diff --git a/drivers/scsi/mpt3sas/Makefile b/drivers/scsi/mpt3sas/Makefile index e76d994dbed3..9a2f3ce4158a 100644 --- a/drivers/scsi/mpt3sas/Makefile +++ b/drivers/scsi/mpt3sas/Makefile @@ -9,3 +9,5 @@ mpt3sas-y +=3D mpt3sas_base.o \ mpt3sas_trigger_diag.o \ mpt3sas_warpdrive.o \ mpt3sas_debugfs.o \ + +mpt3sas-$(CONFIG_SCSI_MPT3SAS_HWMON) +=3D mpt3sas_hwmon.o diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt= 3sas_base.h index c655742d0dde..63252f30343b 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1629,6 +1629,7 @@ struct MPT3SAS_ADAPTER { u8 is_aero_ioc; struct dentry *debugfs_root; struct dentry *ioc_dump; + struct mpt3sas_hwmon *hwmon; PUT_SMID_IO_FP_HIP put_smid_scsi_io; PUT_SMID_IO_FP_HIP put_smid_fast_path; PUT_SMID_IO_FP_HIP put_smid_hi_priority; @@ -2049,6 +2050,22 @@ void mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER = *ioc); void mpt3sas_init_debugfs(void); void mpt3sas_exit_debugfs(void); =20 +#if IS_ENABLED(CONFIG_SCSI_MPT3SAS_HWMON) +int mpt3sas_hwmon_register(struct MPT3SAS_ADAPTER *ioc); +void mpt3sas_hwmon_unregister(struct MPT3SAS_ADAPTER *ioc); +#else +static inline int +mpt3sas_hwmon_register(struct MPT3SAS_ADAPTER *ioc) +{ + return 0; +} + +static inline void +mpt3sas_hwmon_unregister(struct MPT3SAS_ADAPTER *ioc) +{ +} +#endif + /** * _scsih_is_pcie_scsi_device - determines if device is an pcie scsi device * @device_info: bitfield providing information about the device. diff --git a/drivers/scsi/mpt3sas/mpt3sas_hwmon.c b/drivers/scsi/mpt3sas/mp= t3sas_hwmon.c new file mode 100644 index 000000000000..26227a992f35 --- /dev/null +++ b/drivers/scsi/mpt3sas/mpt3sas_hwmon.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Hardware monitoring (hwmon) support for the LSI / Broadcom mpt3sas + * SAS HBA driver. Exposes the IOC and board temperature sensors by + * reading MPI IO Unit Page 7. + */ + +#include +#include +#include +#include + +#include "mpt3sas_base.h" + +struct mpt3sas_hwmon { + struct MPT3SAS_ADAPTER *ioc; + struct device *hwmon_dev; + bool ioc_present; + bool board_present; +}; + +/* + * Convert a (raw, units) reading to millidegrees Celsius. + * Returns -ENODATA when the sensor reports "not present" or + * unknown units. Temperature values are interpreted as signed + * two's-complement integers. + * + * The MPI2_IOUNITPAGE7_IOC_TEMP_* and MPI2_IOUNITPAGE7_BOARD_TEMP_* + * defines in mpi2_cnfg.h share the same values; the IOC ones are + * used for both channels. + */ +static int +_hwmon_to_mdegc(s16 raw, u8 units, long *out) +{ + switch (units) { + case MPI2_IOUNITPAGE7_IOC_TEMP_CELSIUS: + *out =3D (long)raw * 1000; + return 0; + case MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT: + /* (F - 32) * 5 / 9, expressed in milli-units */ + *out =3D ((long)raw - 32) * 5000 / 9; + return 0; + default: + return -ENODATA; + } +} + +static umode_t +_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type, + u32 attr, int channel) +{ + const struct mpt3sas_hwmon *h =3D drvdata; + + if (type !=3D hwmon_temp) + return 0; + if (attr !=3D hwmon_temp_input && attr !=3D hwmon_temp_label) + return 0; + if (channel =3D=3D 0 && h->ioc_present) + return 0444; + if (channel =3D=3D 1 && h->board_present) + return 0444; + return 0; +} + +static int +_hwmon_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + struct mpt3sas_hwmon *h =3D dev_get_drvdata(dev); + Mpi2ConfigReply_t mpi_reply; + Mpi2IOUnitPage7_t page; + int r; + + if (type !=3D hwmon_temp || attr !=3D hwmon_temp_input) + return -EOPNOTSUPP; + + r =3D mpt3sas_config_get_iounit_pg7(h->ioc, &mpi_reply, &page); + if (r) + return r; + + if (channel =3D=3D 0) + return _hwmon_to_mdegc((s16)le16_to_cpu(page.IOCTemperature), + page.IOCTemperatureUnits, val); + if (channel =3D=3D 1) + return _hwmon_to_mdegc((s16)le16_to_cpu(page.BoardTemperature), + page.BoardTemperatureUnits, val); + return -EOPNOTSUPP; +} + +static const char * const mpt3sas_hwmon_temp_labels[] =3D { + "IOC", + "Board", +}; + +static int +_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, const char **str) +{ + if (type !=3D hwmon_temp || attr !=3D hwmon_temp_label) + return -EOPNOTSUPP; + *str =3D mpt3sas_hwmon_temp_labels[channel]; + return 0; +} + +static const struct hwmon_channel_info * const mpt3sas_hwmon_info[] =3D { + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL), + NULL, +}; + +static const struct hwmon_ops mpt3sas_hwmon_ops =3D { + .is_visible =3D _hwmon_is_visible, + .read =3D _hwmon_read, + .read_string =3D _hwmon_read_string, +}; + +static const struct hwmon_chip_info mpt3sas_hwmon_chip_info =3D { + .ops =3D &mpt3sas_hwmon_ops, + .info =3D mpt3sas_hwmon_info, +}; + +/** + * mpt3sas_hwmon_register - register an hwmon device for the IOC + * @ioc: per adapter object + * Context: sleep. + * + * Succeeds without registering when no temperature sensors are present, + * so cards without thermal monitoring do not expose an empty hwmon node. + * Paired with mpt3sas_hwmon_unregister() from the driver's remove path. + * + * Return: 0 for success, non-zero for failure. + */ +int +mpt3sas_hwmon_register(struct MPT3SAS_ADAPTER *ioc) +{ + struct device *parent =3D &ioc->pdev->dev; + struct mpt3sas_hwmon *h; + struct device *hwdev; + Mpi2ConfigReply_t mpi_reply; + Mpi2IOUnitPage7_t page; + int r; + + h =3D kzalloc_obj(*h); + if (!h) + return -ENOMEM; + + h->ioc =3D ioc; + + r =3D mpt3sas_config_get_iounit_pg7(ioc, &mpi_reply, &page); + if (r) { + kfree(h); + return r; + } + + h->ioc_present =3D page.IOCTemperatureUnits !=3D MPI2_IOUNITPAGE7_IOC_TEM= P_NOT_PRESENT; + h->board_present =3D page.BoardTemperatureUnits !=3D MPI2_IOUNITPAGE7_BOA= RD_TEMP_NOT_PRESENT; + + /* + * A page where both *TemperatureUnits are NOT_PRESENT covers + * two cases: cards that genuinely lack sensors, and firmware + * errors that left the page zero-filled (the accessor mirrors + * _config_request() behaviour). Either way: skip registration. + */ + if (!h->ioc_present && !h->board_present) { + kfree(h); + return 0; + } + + hwdev =3D hwmon_device_register_with_info(parent, "mpt3sas", h, + &mpt3sas_hwmon_chip_info, + NULL); + if (IS_ERR(hwdev)) { + kfree(h); + return PTR_ERR(hwdev); + } + + h->hwmon_dev =3D hwdev; + ioc->hwmon =3D h; + return 0; +} + +/** + * mpt3sas_hwmon_unregister - tear down the hwmon device, if any + * @ioc: per adapter object + * + * Safe to call when registration was skipped (no sensors) or + * failed; in those cases ioc->hwmon is NULL and this is a no-op. + */ +void +mpt3sas_hwmon_unregister(struct MPT3SAS_ADAPTER *ioc) +{ + struct mpt3sas_hwmon *h =3D ioc->hwmon; + + if (!h) + return; + hwmon_device_unregister(h->hwmon_dev); + kfree(h); + ioc->hwmon =3D NULL; +} diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mp= t3sas_scsih.c index 12caffeed3a0..dea78688cc9b 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -12562,6 +12562,7 @@ static void scsih_remove(struct pci_dev *pdev) /* release all the volumes */ _scsih_ir_shutdown(ioc); mpt3sas_destroy_debugfs(ioc); + mpt3sas_hwmon_unregister(ioc); sas_remove_host(shost); list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list, list) { @@ -13651,6 +13652,11 @@ _scsih_probe(struct pci_dev *pdev, const struct pc= i_device_id *id) } =20 scsi_scan_host(shost); + + if (mpt3sas_hwmon_register(ioc)) + ioc_warn(ioc, + "hwmon registration failed; temperatures not exposed\n"); + mpt3sas_setup_debugfs(ioc); return 0; out_add_shost_fail: --=20 2.54.0