diff mbox series

[v2,next] scsi: mpt3sas: Replace one-element array with flexible-array in struct _MPI2_CONFIG_PAGE_IO_UNIT_3

Message ID 20210202235118.GA314410@embeddedor (mailing list archive)
State Deferred
Headers show
Series [v2,next] scsi: mpt3sas: Replace one-element array with flexible-array in struct _MPI2_CONFIG_PAGE_IO_UNIT_3 | expand

Commit Message

Gustavo A. R. Silva Feb. 2, 2021, 11:51 p.m. UTC
There is a regular need in the kernel to provide a way to declare having
a dynamically sized set of trailing elements in a structure. Kernel code
should always use “flexible array members”[1] for these cases. The older
style of one-element or zero-length arrays should no longer be used[2].

Refactor the code according to the use of a flexible-array member in
struct _MPI2_CONFIG_PAGE_IO_UNIT_3, instead of a one-element array,
and use the struct_size() helper to calculate the size for the
allocation.

Also, this helps the ongoing efforts to enable -Warray-bounds and fix the
following warnings:

drivers/scsi/mpt3sas/mpt3sas_ctl.c:3193:63: warning: array subscript 24
is above array bounds of ‘U16[1]’ {aka ‘short unsigned int[1]’}
[-Warray-bounds]

[1] https://en.wikipedia.org/wiki/Flexible_array_member
[2] https://www.kernel.org/doc/html/v5.9/process/deprecated.html#zero-length-and-one-element-arrays

Link: https://github.com/KSPP/linux/issues/79
Link: https://github.com/KSPP/linux/issues/109
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
Changes in v2:
 - Fix format specifier: use %zu for size_t type.

 drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h | 11 +----------
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |  6 +++---
 2 files changed, 4 insertions(+), 13 deletions(-)

Comments

Gustavo A. R. Silva March 8, 2021, 7:32 p.m. UTC | #1
Hi all,

Friendly ping: who can review/take this, please?

Thanks!
--
Gustavo

On Tue, Feb 02, 2021 at 05:51:18PM -0600, Gustavo A. R. Silva wrote:
> There is a regular need in the kernel to provide a way to declare having
> a dynamically sized set of trailing elements in a structure. Kernel code
> should always use “flexible array members”[1] for these cases. The older
> style of one-element or zero-length arrays should no longer be used[2].
> 
> Refactor the code according to the use of a flexible-array member in
> struct _MPI2_CONFIG_PAGE_IO_UNIT_3, instead of a one-element array,
> and use the struct_size() helper to calculate the size for the
> allocation.
> 
> Also, this helps the ongoing efforts to enable -Warray-bounds and fix the
> following warnings:
> 
> drivers/scsi/mpt3sas/mpt3sas_ctl.c:3193:63: warning: array subscript 24
> is above array bounds of ‘U16[1]’ {aka ‘short unsigned int[1]’}
> [-Warray-bounds]
> 
> [1] https://en.wikipedia.org/wiki/Flexible_array_member
> [2] https://www.kernel.org/doc/html/v5.9/process/deprecated.html#zero-length-and-one-element-arrays
> 
> Link: https://github.com/KSPP/linux/issues/79
> Link: https://github.com/KSPP/linux/issues/109
> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
> ---
> Changes in v2:
>  - Fix format specifier: use %zu for size_t type.
> 
>  drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h | 11 +----------
>  drivers/scsi/mpt3sas/mpt3sas_ctl.c   |  6 +++---
>  2 files changed, 4 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
> index 43a3bf8ff428..908b0ca63204 100644
> --- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
> +++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
> @@ -987,21 +987,12 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 {
>  
>  /*IO Unit Page 3 */
>  
> -/*
> - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
> - *one and check the value returned for GPIOCount at runtime.
> - */
> -#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
> -#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX    (1)
> -#endif
> -
>  typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 {
>  	MPI2_CONFIG_PAGE_HEADER Header;			 /*0x00 */
>  	U8                      GPIOCount;		 /*0x04 */
>  	U8                      Reserved1;		 /*0x05 */
>  	U16                     Reserved2;		 /*0x06 */
> -	U16
> -		GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/*0x08 */
> +	U16			GPIOVal[];		 /*0x08 */
>  } MPI2_CONFIG_PAGE_IO_UNIT_3,
>  	*PTR_MPI2_CONFIG_PAGE_IO_UNIT_3,
>  	Mpi2IOUnitPage3_t, *pMpi2IOUnitPage3_t;
> diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
> index c8a0ce18f2c5..ffb21f873058 100644
> --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
> +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
> @@ -3143,7 +3143,7 @@ BRM_status_show(struct device *cdev, struct device_attribute *attr,
>  	Mpi2ConfigReply_t mpi_reply;
>  	u16 backup_rail_monitor_status = 0;
>  	u16 ioc_status;
> -	int sz;
> +	size_t sz;
>  	ssize_t rc = 0;
>  
>  	if (!ioc->is_warpdrive) {
> @@ -3157,11 +3157,11 @@ BRM_status_show(struct device *cdev, struct device_attribute *attr,
>  		goto out;
>  
>  	/* allocate upto GPIOVal 36 entries */
> -	sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36);
> +	sz = struct_size(io_unit_pg3, GPIOVal, 36);
>  	io_unit_pg3 = kzalloc(sz, GFP_KERNEL);
>  	if (!io_unit_pg3) {
>  		rc = -ENOMEM;
> -		ioc_err(ioc, "%s: failed allocating memory for iounit_pg3: (%d) bytes\n",
> +		ioc_err(ioc, "%s: failed allocating memory for iounit_pg3: (%zu) bytes\n",
>  			__func__, sz);
>  		goto out;
>  	}
> -- 
> 2.27.0
>
James Bottomley March 8, 2021, 8:12 p.m. UTC | #2
On Mon, 2021-03-08 at 13:32 -0600, Gustavo A. R. Silva wrote:
> Hi all,
> 
> Friendly ping: who can review/take this, please?

Well, before embarking on a huge dynamic update, let's ask Broadcom the
simpler question of why isn't MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX simply
set to 36?  There's no dynamic allocation of anything in the current
code ... it's all hard coded to allocate 36 entries.  If there's no
need for anything dynamic then the kzalloc could become 

	io_unit_pg3 = kzalloc(sizeof(*io_unit_pg3), GFP_KERNEL);

James
Gustavo A. R. Silva March 8, 2021, 8:41 p.m. UTC | #3
On Mon, Mar 08, 2021 at 12:12:59PM -0800, James Bottomley wrote:
> On Mon, 2021-03-08 at 13:32 -0600, Gustavo A. R. Silva wrote:
> > Hi all,
> > 
> > Friendly ping: who can review/take this, please?
> 
> Well, before embarking on a huge dynamic update, let's ask Broadcom the
> simpler question of why isn't MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX simply
> set to 36?  There's no dynamic allocation of anything in the current
> code ... it's all hard coded to allocate 36 entries.  If there's no
> need for anything dynamic then the kzalloc could become 

Yeah; and if that is the case, then there is no even need for kzalloc()
at all, and it can be replaced by memset():

diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
index 43a3bf8ff428..d00431f553e1 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
@@ -992,7 +992,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 {
  *one and check the value returned for GPIOCount at runtime.
  */
 #ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
-#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX    (1)
+#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX    (36)
 #endif

 typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 {
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index 44f9a05db94e..23fcf29bfd67 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -3203,7 +3203,7 @@ BRM_status_show(struct device *cdev, struct device_attribute *attr,
 {
        struct Scsi_Host *shost = class_to_shost(cdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
-       Mpi2IOUnitPage3_t *io_unit_pg3 = NULL;
+       Mpi2IOUnitPage3_t io_unit_pg3;
        Mpi2ConfigReply_t mpi_reply;
        u16 backup_rail_monitor_status = 0;
        u16 ioc_status;
@@ -3221,16 +3221,10 @@ BRM_status_show(struct device *cdev, struct device_attribute *attr,
                goto out;

        /* allocate upto GPIOVal 36 entries */
-       sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36);
-       io_unit_pg3 = kzalloc(sz, GFP_KERNEL);
-       if (!io_unit_pg3) {
-               rc = -ENOMEM;
-               ioc_err(ioc, "%s: failed allocating memory for iounit_pg3: (%d) bytes\n",
-                       __func__, sz);
-               goto out;
-       }
+       sz = sizeof(io_unit_pg3);
+       memset(&io_unit_pg3, 0, sz);

-       if (mpt3sas_config_get_iounit_pg3(ioc, &mpi_reply, io_unit_pg3, sz) !=
+       if (mpt3sas_config_get_iounit_pg3(ioc, &mpi_reply, &io_unit_pg3, sz) !=
            0) {
                ioc_err(ioc, "%s: failed reading iounit_pg3\n",
                        __func__);
@@ -3246,19 +3240,18 @@ BRM_status_show(struct device *cdev, struct device_attribute *attr,
                goto out;
        }

-       if (io_unit_pg3->GPIOCount < 25) {
-               ioc_err(ioc, "%s: iounit_pg3->GPIOCount less than 25 entries, detected (%d) entries\n",
-                       __func__, io_unit_pg3->GPIOCount);
+       if (io_unit_pg3.GPIOCount < 25) {
+               ioc_err(ioc, "%s: iounit_pg3.GPIOCount less than 25 entries, detected (%d) entries\n",
+                       __func__, io_unit_pg3.GPIOCount);
                rc = -EINVAL;
                goto out;
        }

        /* BRM status is in bit zero of GPIOVal[24] */
-       backup_rail_monitor_status = le16_to_cpu(io_unit_pg3->GPIOVal[24]);
+       backup_rail_monitor_status = le16_to_cpu(io_unit_pg3.GPIOVal[24]);
        rc = snprintf(buf, PAGE_SIZE, "%d\n", (backup_rail_monitor_status & 1));

  out:
-       kfree(io_unit_pg3);
        mutex_unlock(&ioc->pci_access_mutex);
        return rc;
 }

> 
> 	io_unit_pg3 = kzalloc(sizeof(*io_unit_pg3), GFP_KERNEL);
>

Thanks
--
Gustavo
Kees Cook March 10, 2021, 7:07 p.m. UTC | #4
On Mon, Mar 08, 2021 at 02:41:29PM -0600, Gustavo A. R. Silva wrote:
> On Mon, Mar 08, 2021 at 12:12:59PM -0800, James Bottomley wrote:
> > On Mon, 2021-03-08 at 13:32 -0600, Gustavo A. R. Silva wrote:
> > > Hi all,
> > > 
> > > Friendly ping: who can review/take this, please?
> > 
> > Well, before embarking on a huge dynamic update, let's ask Broadcom the
> > simpler question of why isn't MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX simply
> > set to 36?  There's no dynamic allocation of anything in the current
> > code ... it's all hard coded to allocate 36 entries.  If there's no
> > need for anything dynamic then the kzalloc could become 
> 
> Yeah; and if that is the case, then there is no even need for kzalloc()
> at all, and it can be replaced by memset():
> 
> diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
> index 43a3bf8ff428..d00431f553e1 100644
> --- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
> +++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
> @@ -992,7 +992,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 {
>   *one and check the value returned for GPIOCount at runtime.
>   */
>  #ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
> -#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX    (1)
> +#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX    (36)
>  #endif
> 
>  typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 {
> diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
> index 44f9a05db94e..23fcf29bfd67 100644
> --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
> +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
> @@ -3203,7 +3203,7 @@ BRM_status_show(struct device *cdev, struct device_attribute *attr,
>  {
>         struct Scsi_Host *shost = class_to_shost(cdev);
>         struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
> -       Mpi2IOUnitPage3_t *io_unit_pg3 = NULL;
> +       Mpi2IOUnitPage3_t io_unit_pg3;
>         Mpi2ConfigReply_t mpi_reply;
>         u16 backup_rail_monitor_status = 0;
>         u16 ioc_status;
> @@ -3221,16 +3221,10 @@ BRM_status_show(struct device *cdev, struct device_attribute *attr,
>                 goto out;
> 
>         /* allocate upto GPIOVal 36 entries */
> -       sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36);
> -       io_unit_pg3 = kzalloc(sz, GFP_KERNEL);
> -       if (!io_unit_pg3) {
> -               rc = -ENOMEM;
> -               ioc_err(ioc, "%s: failed allocating memory for iounit_pg3: (%d) bytes\n",
> -                       __func__, sz);
> -               goto out;
> -       }
> +       sz = sizeof(io_unit_pg3);
> +       memset(&io_unit_pg3, 0, sz);

I like this a lot. It makes the code way simpler.

Putting this on the stack makes it faster, and it's less than 100 bytes,
which seems entirely reasonable.

> 
> -       if (mpt3sas_config_get_iounit_pg3(ioc, &mpi_reply, io_unit_pg3, sz) !=
> +       if (mpt3sas_config_get_iounit_pg3(ioc, &mpi_reply, &io_unit_pg3, sz) !=

The only thing I can imagine is if this ends up doing DMA, which isn't
allowed on the stack. However, in looking down through the call path,
it's _copied_ into DMA memory, so this appears entirely safe.
 
Can you send this as a "normal" patch? Feel free to include:

Reviewed-by: Kees Cook <keescook@chromium.org>

Thanks!

-Kees

>             0) {
>                 ioc_err(ioc, "%s: failed reading iounit_pg3\n",
>                         __func__);
> @@ -3246,19 +3240,18 @@ BRM_status_show(struct device *cdev, struct device_attribute *attr,
>                 goto out;
>         }
> 
> -       if (io_unit_pg3->GPIOCount < 25) {
> -               ioc_err(ioc, "%s: iounit_pg3->GPIOCount less than 25 entries, detected (%d) entries\n",
> -                       __func__, io_unit_pg3->GPIOCount);
> +       if (io_unit_pg3.GPIOCount < 25) {
> +               ioc_err(ioc, "%s: iounit_pg3.GPIOCount less than 25 entries, detected (%d) entries\n",
> +                       __func__, io_unit_pg3.GPIOCount);
>                 rc = -EINVAL;
>                 goto out;
>         }
> 
>         /* BRM status is in bit zero of GPIOVal[24] */
> -       backup_rail_monitor_status = le16_to_cpu(io_unit_pg3->GPIOVal[24]);
> +       backup_rail_monitor_status = le16_to_cpu(io_unit_pg3.GPIOVal[24]);
>         rc = snprintf(buf, PAGE_SIZE, "%d\n", (backup_rail_monitor_status & 1));
> 
>   out:
> -       kfree(io_unit_pg3);
>         mutex_unlock(&ioc->pci_access_mutex);
>         return rc;
>  }
> 
> > 
> > 	io_unit_pg3 = kzalloc(sizeof(*io_unit_pg3), GFP_KERNEL);
> >
> 
> Thanks
> --
> Gustavo
Gustavo A. R. Silva March 11, 2021, 12:06 a.m. UTC | #5
On 3/10/21 13:07, Kees Cook wrote:

>> diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
>> index 43a3bf8ff428..d00431f553e1 100644
>> --- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
>> +++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
>> @@ -992,7 +992,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 {
>>   *one and check the value returned for GPIOCount at runtime.
>>   */
>>  #ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
>> -#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX    (1)
>> +#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX    (36)
>>  #endif
>>
>>  typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 {
>> diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
>> index 44f9a05db94e..23fcf29bfd67 100644
>> --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
>> +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
>> @@ -3203,7 +3203,7 @@ BRM_status_show(struct device *cdev, struct device_attribute *attr,
>>  {
>>         struct Scsi_Host *shost = class_to_shost(cdev);
>>         struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
>> -       Mpi2IOUnitPage3_t *io_unit_pg3 = NULL;
>> +       Mpi2IOUnitPage3_t io_unit_pg3;
>>         Mpi2ConfigReply_t mpi_reply;
>>         u16 backup_rail_monitor_status = 0;
>>         u16 ioc_status;
>> @@ -3221,16 +3221,10 @@ BRM_status_show(struct device *cdev, struct device_attribute *attr,
>>                 goto out;
>>
>>         /* allocate upto GPIOVal 36 entries */
>> -       sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36);
>> -       io_unit_pg3 = kzalloc(sz, GFP_KERNEL);
>> -       if (!io_unit_pg3) {
>> -               rc = -ENOMEM;
>> -               ioc_err(ioc, "%s: failed allocating memory for iounit_pg3: (%d) bytes\n",
>> -                       __func__, sz);
>> -               goto out;
>> -       }
>> +       sz = sizeof(io_unit_pg3);
>> +       memset(&io_unit_pg3, 0, sz);
> 
> I like this a lot. It makes the code way simpler.
> 
> Putting this on the stack makes it faster, and it's less than 100 bytes,
> which seems entirely reasonable.
> 
>>
>> -       if (mpt3sas_config_get_iounit_pg3(ioc, &mpi_reply, io_unit_pg3, sz) !=
>> +       if (mpt3sas_config_get_iounit_pg3(ioc, &mpi_reply, &io_unit_pg3, sz) !=
> 
> The only thing I can imagine is if this ends up doing DMA, which isn't
> allowed on the stack. However, in looking down through the call path,
> it's _copied_ into DMA memory, so this appears entirely safe.
>  
> Can you send this as a "normal" patch? Feel free to include:
> 
> Reviewed-by: Kees Cook <keescook@chromium.org>

Done: https://lore.kernel.org/lkml/20210310235951.GA108661@embeddedor/

Thanks for the comments!
--
Gustavo
diff mbox series

Patch

diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
index 43a3bf8ff428..908b0ca63204 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
@@ -987,21 +987,12 @@  typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 {
 
 /*IO Unit Page 3 */
 
-/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for GPIOCount at runtime.
- */
-#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
-#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX    (1)
-#endif
-
 typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 {
 	MPI2_CONFIG_PAGE_HEADER Header;			 /*0x00 */
 	U8                      GPIOCount;		 /*0x04 */
 	U8                      Reserved1;		 /*0x05 */
 	U16                     Reserved2;		 /*0x06 */
-	U16
-		GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/*0x08 */
+	U16			GPIOVal[];		 /*0x08 */
 } MPI2_CONFIG_PAGE_IO_UNIT_3,
 	*PTR_MPI2_CONFIG_PAGE_IO_UNIT_3,
 	Mpi2IOUnitPage3_t, *pMpi2IOUnitPage3_t;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index c8a0ce18f2c5..ffb21f873058 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -3143,7 +3143,7 @@  BRM_status_show(struct device *cdev, struct device_attribute *attr,
 	Mpi2ConfigReply_t mpi_reply;
 	u16 backup_rail_monitor_status = 0;
 	u16 ioc_status;
-	int sz;
+	size_t sz;
 	ssize_t rc = 0;
 
 	if (!ioc->is_warpdrive) {
@@ -3157,11 +3157,11 @@  BRM_status_show(struct device *cdev, struct device_attribute *attr,
 		goto out;
 
 	/* allocate upto GPIOVal 36 entries */
-	sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36);
+	sz = struct_size(io_unit_pg3, GPIOVal, 36);
 	io_unit_pg3 = kzalloc(sz, GFP_KERNEL);
 	if (!io_unit_pg3) {
 		rc = -ENOMEM;
-		ioc_err(ioc, "%s: failed allocating memory for iounit_pg3: (%d) bytes\n",
+		ioc_err(ioc, "%s: failed allocating memory for iounit_pg3: (%zu) bytes\n",
 			__func__, sz);
 		goto out;
 	}