diff mbox

[net-next,1/4] bnx2x: refactor nvram read procedure

Message ID 1365843411-27103-2-git-send-email-dmitry@broadcom.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Dmitry Kravkov April 13, 2013, 8:56 a.m. UTC
introduce a parameter to allow nvram read to return
data in BE or cpu order.

Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
 .../net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c    |   53 +++++++++-----------
 1 files changed, 24 insertions(+), 29 deletions(-)

Comments

Francois Romieu April 13, 2013, 11:09 a.m. UTC | #1
Dmitry Kravkov <dmitry@broadcom.com> :
> introduce a parameter to allow nvram read to return
> data in BE or cpu order.
[...]
> @@ -1295,10 +1296,14 @@ static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, __be32 *ret_val,
>  		if (val & MCPR_NVM_COMMAND_DONE) {
>  			val = REG_RD(bp, MCP_REG_MCPR_NVM_READ);
>  			/* we read nvram data in cpu order
> -			 * but ethtool sees it as an array of bytes
> +			 * but ethtool uses it as an array of bytes
>  			 * converting to big-endian will do the work
> +			 * if requested.

You memcpy a u32 to an array of bytes instead of copying it byte after
byte with proper shift operators and now you are paving the way for more
endianess headaches. I'd rather avoid the memcpy when readying data for
ethtool in the first place.

Nit: the true/false method parameter style in middle layers is mildly
readable when compared to usual _{be/le} kernel style (you should be
able to avoid both almost completely anyway :o) ).
Dmitry Kravkov April 15, 2013, 7:14 a.m. UTC | #2
> -----Original Message-----
> From: Francois Romieu [mailto:romieu@fr.zoreil.com]
> Sent: Saturday, April 13, 2013 2:09 PM
> To: Dmitry Kravkov
> Cc: davem@davemloft.net; netdev@vger.kernel.org; Eilon Greenstein
> Subject: Re: [PATCH net-next 1/4] bnx2x: refactor nvram read procedure
> 
> Dmitry Kravkov <dmitry@broadcom.com> :
> > introduce a parameter to allow nvram read to return
> > data in BE or cpu order.
> [...]
> > @@ -1295,10 +1296,14 @@ static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, __be32 *ret_val,
> >  		if (val & MCPR_NVM_COMMAND_DONE) {
> >  			val = REG_RD(bp, MCP_REG_MCPR_NVM_READ);
> >  			/* we read nvram data in cpu order
> > -			 * but ethtool sees it as an array of bytes
> > +			 * but ethtool uses it as an array of bytes
> >  			 * converting to big-endian will do the work
> > +			 * if requested.
> 
> You memcpy a u32 to an array of bytes instead of copying it byte after
> byte with proper shift operators and now you are paving the way for more
> endianess headaches. I'd rather avoid the memcpy when readying data for
> ethtool in the first place.
In case of _be data I don't see any issue with copying _be32 it into byte array.
When internal driver function (not exposed to external usage) requests data in CPU order - it meant to bring u32 data ( or array of u32) and memcpy dword by dword also should be harmless.
 
> Nit: the true/false method parameter style in middle layers is mildly
> readable when compared to usual _{be/le} kernel style (you should be
> able to avoid both almost completely anyway :o) ).
Boolean parameter used to share pre- and post-configuring nvram for read operation.
_be/le is less suitable here, since the usage is BE or cpu order.
I was thinking about separating stream read and u32 read to separate callbacks, but this will add another level and this is less preferable than true/false param.
 
> --
> Ueimor


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Francois Romieu April 15, 2013, 11:31 p.m. UTC | #3
Dmitry Kravkov <dmitry@broadcom.com> :
[...]
> > You memcpy a u32 to an array of bytes instead of copying it byte after
> > byte with proper shift operators and now you are paving the way for more
> > endianess headaches. I'd rather avoid the memcpy when readying data for
> > ethtool in the first place.
> In case of _be data I don't see any issue with copying _be32 it into byte array.

The modified code (bnx2x_nvram_read) will not be copying __be32 but u32.
It issmuggling _be data behind neutral u32 and using casting when the
kernel has provided cpu_to_{le / be} helpers for years. Think of type
checking as kind of messed up as soon as u32 *ret_val contains a _le or
_be data depending on the value of bool to_be.

I don't want to worry about the endianness of a u32. If it's a u32 (u16,
s32, whatever), I only want to think of bytes in it through '>>' or '<<'
operators. No need to remember the semantic of the last bnx2x_nvram_read_dword
parameter, if it's internal, external, nor assume that the lower layers
enforce some ability to memcpy it blindly. So I'd just favor using cpu order
as soon and as much as possible.

Of course it's your driver, whence your maintenance choices.
Dmitry Kravkov April 17, 2013, 8:19 p.m. UTC | #4
> -----Original Message-----
> From: Francois Romieu [mailto:romieu@fr.zoreil.com]
> Sent: Tuesday, April 16, 2013 2:32 AM
> To: Dmitry Kravkov
> Cc: davem@davemloft.net; netdev@vger.kernel.org; Eilon Greenstein
> Subject: Re: [PATCH net-next 1/4] bnx2x: refactor nvram read procedure
> 
> Dmitry Kravkov <dmitry@broadcom.com> :
> [...]
> > > You memcpy a u32 to an array of bytes instead of copying it byte after
> > > byte with proper shift operators and now you are paving the way for more
> > > endianess headaches. I'd rather avoid the memcpy when readying data for
> > > ethtool in the first place.
> > In case of _be data I don't see any issue with copying _be32 it into byte array.
> 
> The modified code (bnx2x_nvram_read) will not be copying __be32 but u32.
> It issmuggling _be data behind neutral u32 and using casting when the
> kernel has provided cpu_to_{le / be} helpers for years. Think of type
> checking as kind of messed up as soon as u32 *ret_val contains a _le or
> _be data depending on the value of bool to_be.
> 
> I don't want to worry about the endianness of a u32. If it's a u32 (u16,
> s32, whatever), I only want to think of bytes in it through '>>' or '<<'
> operators. No need to remember the semantic of the last bnx2x_nvram_read_dword
> parameter, if it's internal, external, nor assume that the lower layers
> enforce some ability to memcpy it blindly. So I'd just favor using cpu order
> as soon and as much as possible.
> 
> Of course it's your driver, whence your maintenance choices.

I will re-work it soon! Thanks

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index 129d6b2..900c0d7 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -1261,11 +1261,12 @@  static void bnx2x_disable_nvram_access(struct bnx2x *bp)
 			MCPR_NVM_ACCESS_ENABLE_WR_EN)));
 }
 
-static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, __be32 *ret_val,
-				  u32 cmd_flags)
+static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, u32 *ret_val,
+				  u32 cmd_flags, bool to_be)
 {
 	int count, i, rc;
 	u32 val;
+	__be32 *be_val = (__be32 *)ret_val;
 
 	/* build the command word */
 	cmd_flags |= MCPR_NVM_COMMAND_DOIT;
@@ -1295,10 +1296,14 @@  static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, __be32 *ret_val,
 		if (val & MCPR_NVM_COMMAND_DONE) {
 			val = REG_RD(bp, MCP_REG_MCPR_NVM_READ);
 			/* we read nvram data in cpu order
-			 * but ethtool sees it as an array of bytes
+			 * but ethtool uses it as an array of bytes
 			 * converting to big-endian will do the work
+			 * if requested.
 			 */
-			*ret_val = cpu_to_be32(val);
+			if (to_be)
+				*be_val = cpu_to_be32(val);
+			else
+				*ret_val = val;
 			rc = 0;
 			break;
 		}
@@ -1310,11 +1315,10 @@  static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, __be32 *ret_val,
 }
 
 static int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf,
-			    int buf_size)
+			    int buf_size, bool to_be)
 {
 	int rc;
-	u32 cmd_flags;
-	__be32 val;
+	u32 cmd_flags, val;
 
 	if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) {
 		DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
@@ -1341,7 +1345,7 @@  static int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf,
 	/* read the first word(s) */
 	cmd_flags = MCPR_NVM_COMMAND_FIRST;
 	while ((buf_size > sizeof(u32)) && (rc == 0)) {
-		rc = bnx2x_nvram_read_dword(bp, offset, &val, cmd_flags);
+		rc = bnx2x_nvram_read_dword(bp, offset, &val, cmd_flags, to_be);
 		memcpy(ret_buf, &val, 4);
 
 		/* advance to the next dword */
@@ -1353,7 +1357,7 @@  static int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf,
 
 	if (rc == 0) {
 		cmd_flags |= MCPR_NVM_COMMAND_LAST;
-		rc = bnx2x_nvram_read_dword(bp, offset, &val, cmd_flags);
+		rc = bnx2x_nvram_read_dword(bp, offset, &val, cmd_flags, to_be);
 		memcpy(ret_buf, &val, 4);
 	}
 
@@ -1383,7 +1387,7 @@  static int bnx2x_get_eeprom(struct net_device *dev,
 
 	/* parameters already validated in ethtool_get_eeprom */
 
-	rc = bnx2x_nvram_read(bp, eeprom->offset, eebuf, eeprom->len);
+	rc = bnx2x_nvram_read(bp, eeprom->offset, eebuf, eeprom->len, true);
 
 	return rc;
 }
@@ -1552,9 +1556,7 @@  static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf,
 			      int buf_size)
 {
 	int rc;
-	u32 cmd_flags;
-	u32 align_offset;
-	__be32 val;
+	u32 cmd_flags, align_offset, val;
 
 	if (offset + buf_size > bp->common.flash_size) {
 		DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
@@ -1573,16 +1575,11 @@  static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf,
 
 	cmd_flags = (MCPR_NVM_COMMAND_FIRST | MCPR_NVM_COMMAND_LAST);
 	align_offset = (offset & ~0x03);
-	rc = bnx2x_nvram_read_dword(bp, align_offset, &val, cmd_flags);
+	rc = bnx2x_nvram_read_dword(bp, align_offset, &val, cmd_flags, false);
 
 	if (rc == 0) {
-		val &= ~(0xff << BYTE_OFFSET(offset));
-		val |= (*data_buf << BYTE_OFFSET(offset));
-
-		/* nvram data is returned as an array of bytes
-		 * convert it back to cpu order
-		 */
-		val = be32_to_cpu(val);
+		val &= ~le32_to_cpu(0xff << BYTE_OFFSET(offset));
+		val |= le32_to_cpu(*data_buf << BYTE_OFFSET(offset));
 
 		rc = bnx2x_nvram_write_dword(bp, align_offset, val,
 					     cmd_flags);
@@ -2598,8 +2595,7 @@  static int bnx2x_test_nvram(struct bnx2x *bp)
 		{ 0x708,  0x70 }, /* manuf_key_info */
 		{     0,     0 }
 	};
-	__be32 *buf;
-	u8 *data;
+	u8 *buf;
 	int i, rc;
 	u32 magic, crc;
 
@@ -2612,16 +2608,15 @@  static int bnx2x_test_nvram(struct bnx2x *bp)
 		rc = -ENOMEM;
 		goto test_nvram_exit;
 	}
-	data = (u8 *)buf;
 
-	rc = bnx2x_nvram_read(bp, 0, data, 4);
+	rc = bnx2x_nvram_read(bp, 0, buf, 4, false);
 	if (rc) {
 		DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
 		   "magic value read (rc %d)\n", rc);
 		goto test_nvram_exit;
 	}
 
-	magic = be32_to_cpu(buf[0]);
+	magic = *(u32 *)(buf);
 	if (magic != 0x669955aa) {
 		DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
 		   "wrong magic value (0x%08x)\n", magic);
@@ -2631,15 +2626,15 @@  static int bnx2x_test_nvram(struct bnx2x *bp)
 
 	for (i = 0; nvram_tbl[i].size; i++) {
 
-		rc = bnx2x_nvram_read(bp, nvram_tbl[i].offset, data,
-				      nvram_tbl[i].size);
+		rc = bnx2x_nvram_read(bp, nvram_tbl[i].offset, buf,
+				      nvram_tbl[i].size, true);
 		if (rc) {
 			DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
 			   "nvram_tbl[%d] read data (rc %d)\n", i, rc);
 			goto test_nvram_exit;
 		}
 
-		crc = ether_crc_le(nvram_tbl[i].size, data);
+		crc = ether_crc_le(nvram_tbl[i].size, buf);
 		if (crc != CRC32_RESIDUAL) {
 			DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
 			   "nvram_tbl[%d] wrong crc value (0x%08x)\n", i, crc);