Netdev List
 help / color / mirror / Atom feed
* Re: [PATCHv2] can: ti hecc module : add platform specific initialization callback.
From: Marc Kleine-Budde @ 2010-02-25 18:00 UTC (permalink / raw)
  To: Sriramakrishnan
  Cc: socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1267118802-19263-1-git-send-email-srk-l0cyMroinI0@public.gmane.org>


[-- Attachment #1.1: Type: text/plain, Size: 3784 bytes --]

Sriramakrishnan wrote:
> CAN module on AM3517 requires programming of IO expander as part
> of init sequence - to enable CAN PHY. Added platform specific
> callback to handle phy control(switch on /off).
> 
> Signed-off-by: Sriramakrishnan <srk-l0cyMroinI0@public.gmane.org>

looks good, just minor nitpicking inline

Cheers, Marc

> ---
> Modified as per review comments received.
> 
>  drivers/net/can/ti_hecc.c            |   15 ++++++++++++++-
>  include/linux/can/platform/ti_hecc.h |    3 ++-
>  2 files changed, 16 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
> index df27d82..871a3fe 100644
> --- a/drivers/net/can/ti_hecc.c
> +++ b/drivers/net/can/ti_hecc.c
> @@ -28,9 +28,11 @@
>   *         .mbx_offset             = 0x2000,
>   *         .int_line               = 0,
>   *         .revision               = 1,
> + *         .transceiver_switch     = hecc_phy_control,
>   * };
>   *
> - * Please see include/can/platform/ti_hecc.h for description of above fields
> + * Please see include/linux/can/platform/ti_hecc.h for description of
> + * above fields.
>   *
>   */
>  
> @@ -220,6 +222,7 @@ struct ti_hecc_priv {
>  	u32 tx_head;
>  	u32 tx_tail;
>  	u32 rx_next;
> +	void (*transceiver_switch)(int);
>  };
>  
>  static inline int get_tx_head_mb(struct ti_hecc_priv *priv)
> @@ -317,6 +320,13 @@ static int ti_hecc_set_btc(struct ti_hecc_priv *priv)
>  	return 0;
>  }
>  
> +static void ti_hecc_transceiver_switch(const struct ti_hecc_priv *priv,
> +					int on)
> +{
> +	if (priv->transceiver_switch)
> +		priv->transceiver_switch(on);
> +}
> +
>  static void ti_hecc_reset(struct net_device *ndev)
>  {
>  	u32 cnt;
> @@ -824,6 +834,7 @@ static int ti_hecc_open(struct net_device *ndev)
>  		return err;
>  	}
>  
> +	ti_hecc_transceiver_switch(priv, 1);
>  	ti_hecc_start(ndev);
>  	napi_enable(&priv->napi);
>  	netif_start_queue(ndev);
> @@ -840,6 +851,7 @@ static int ti_hecc_close(struct net_device *ndev)
>  	ti_hecc_stop(ndev);
>  	free_irq(ndev->irq, ndev);
>  	close_candev(ndev);
> +	ti_hecc_transceiver_switch(priv, 0);

nitpick: it's not symetric to the _start function.

>  
>  	return 0;
>  }
> @@ -901,6 +913,7 @@ static int ti_hecc_probe(struct platform_device *pdev)
>  	priv->hecc_ram_offset = pdata->hecc_ram_offset;
>  	priv->mbx_offset = pdata->mbx_offset;
>  	priv->int_line = pdata->int_line;
> +	priv->transceiver_switch = pdata->transceiver_switch;
>  
>  	priv->can.bittiming_const = &ti_hecc_bittiming_const;
>  	priv->can.do_set_mode = ti_hecc_do_set_mode;
> diff --git a/include/linux/can/platform/ti_hecc.h b/include/linux/can/platform/ti_hecc.h
> index 4688c7b..825bc6a 100644
> --- a/include/linux/can/platform/ti_hecc.h
> +++ b/include/linux/can/platform/ti_hecc.h
> @@ -23,6 +23,7 @@
>   * @mbx_offset:		Mailbox RAM offset
>   * @int_line:		Interrupt line to use - 0 or 1
>   * @version:		version for future use
> + * @transceiver_switch  platform specific callback fn for transceiver control
                         ^^
nitpick:
these are spaces, but the other lines use tabs

>   *
>   * Platform data structure to get all platform specific settings.
>   * this structure also accounts the fact that the IP may have different
> @@ -35,6 +36,6 @@ struct ti_hecc_platform_data {
>  	u32 mbx_offset;
>  	u32 int_line;
>  	u32 version;
> +	void (*transceiver_switch) (int);
>  };
>  
> -


-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

[-- Attachment #2: Type: text/plain, Size: 188 bytes --]

_______________________________________________
Socketcan-core mailing list
Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
https://lists.berlios.de/mailman/listinfo/socketcan-core

^ permalink raw reply

* [PATCH 1/7] pci: Add PCI LRDT tag size and section size
From: Matt Carlson @ 2010-02-25 18:19 UTC (permalink / raw)
  To: jbarnes; +Cc: linux-pci, netdev, andy, mcarlson, Michael Chan

This patch adds a preprocessor constant to describe the PCI VPD large
resource data type tag size and an inline function to extract the large
resource section size from the large resource data type tag.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/bnx2.c      |    9 ++++++---
 drivers/net/tg3.c       |   14 +++++++-------
 include/linux/pci-vpd.h |   26 ++++++++++++++++++++++++++
 3 files changed, 39 insertions(+), 10 deletions(-)
 create mode 100644 include/linux/pci-vpd.h

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 65df1de..9f5b0fc 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -21,6 +21,7 @@
 #include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/pci-vpd.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -7763,15 +7764,17 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp)
 		unsigned int block_end;
 
 		if (val == 0x82 || val == 0x91) {
-			i = (i + 3 + (data[i + 1] + (data[i + 2] << 8)));
+			i += PCI_VPD_LRDT_TAG_SIZE +
+			     pci_vpd_lrdt_size(&data[i]);
 			continue;
 		}
 
 		if (val != 0x90)
 			goto vpd_done;
 
-		block_end = (i + 3 + (data[i + 1] + (data[i + 2] << 8)));
-		i += 3;
+		block_end = (i + PCI_VPD_LRDT_TAG_SIZE +
+			    pci_vpd_lrdt_size(&data[i]));
+		i += PCI_VPD_LRDT_TAG_SIZE;
 
 		if (block_end > BNX2_VPD_LEN)
 			goto vpd_done;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 7f82b02..6cab97f 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
+#include <linux/pci-vpd.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -12483,19 +12484,18 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
 		unsigned int block_end;
 
 		if (val == 0x82 || val == 0x91) {
-			i = (i + 3 +
-			     (vpd_data[i + 1] +
-			      (vpd_data[i + 2] << 8)));
+			i += PCI_VPD_LRDT_TAG_SIZE +
+			     pci_vpd_lrdt_size(&vpd_data[i]);
 			continue;
 		}
 
 		if (val != 0x90)
 			goto out_not_found;
 
-		block_end = (i + 3 +
-			     (vpd_data[i + 1] +
-			      (vpd_data[i + 2] << 8)));
-		i += 3;
+		block_end = i + PCI_VPD_LRDT_TAG_SIZE +
+			    pci_vpd_lrdt_size(&vpd_data[i]);
+
+		i += PCI_VPD_LRDT_TAG_SIZE;
 
 		if (block_end > TG3_NVM_VPD_LEN)
 			goto out_not_found;
diff --git a/include/linux/pci-vpd.h b/include/linux/pci-vpd.h
new file mode 100644
index 0000000..c077369
--- /dev/null
+++ b/include/linux/pci-vpd.h
@@ -0,0 +1,26 @@
+/*
+ *	pci-vpd.h
+ *
+ *	PCI VPD defines and function prototypes
+ *
+ *	Copyright (C) 2010 Broadcom Corporation.
+ *
+ *	For more information, please consult the following manuals (look at
+ *	http://www.pcisig.com/ for how to get them):
+ *
+ *	PCI Local Bus Specification, Rev. 3.0 : Appendix I
+ */
+
+#ifndef LINUX_PCI_VPD_H
+#define LINUX_PCI_VPD_H
+
+#include <linux/pci.h>
+
+#define PCI_VPD_LRDT_TAG_SIZE	3
+
+static inline u16 pci_vpd_lrdt_size(u8 *lrdt)
+{
+	return (u16)lrdt[1] + ((u16)lrdt[2] << 8);
+}
+
+#endif /* LINUX_PCI_VPD_H */
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 4/7] pci: Add VPD information field helper functions
From: Matt Carlson @ 2010-02-25 18:19 UTC (permalink / raw)
  To: jbarnes; +Cc: linux-pci, netdev, andy, mcarlson, Michael Chan

This patch adds a preprocessor constant to describe the PCI VPD
information field header size and an inline function to extract the
size of the information field itself.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/bnx2.c      |   11 ++++++-----
 drivers/net/tg3.c       |    7 ++++---
 include/linux/pci-vpd.h |    6 ++++++
 3 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 2de3576..c3e5182 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -7775,14 +7775,15 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp)
 			goto vpd_done;
 
 		while (i < (block_end - 2)) {
-			int len = data[i + 2];
+			int len = pci_vpd_info_field_size(&data[i]);
 
-			if (i + 3 + len > block_end)
+			if (i + PCI_VPD_INFO_FLD_HDR_SIZE + len > block_end)
 				goto vpd_done;
 
 			if (data[i] == 'M' && data[i + 1] == 'N') {
 				if (len != 4 ||
-				    memcmp(&data[i + 3], "1028", 4))
+				    memcmp(&data[i + PCI_VPD_INFO_FLD_HDR_SIZE],
+					   "1028", 4))
 					goto vpd_done;
 				mn_match = true;
 
@@ -7791,9 +7792,9 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp)
 					goto vpd_done;
 
 				v0_len = len;
-				v0_str = &data[i + 3];
+				v0_str = &data[i + PCI_VPD_INFO_FLD_HDR_SIZE];
 			}
-			i += 3 + len;
+			i += PCI_VPD_INFO_FLD_HDR_SIZE + len;
 
 			if (mn_match && v0_str) {
 				memcpy(bp->fw_version, v0_str, v0_len);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index eaf178b..500a145 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -12498,9 +12498,9 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
 		while (i < (block_end - 2)) {
 			if (vpd_data[i + 0] == 'P' &&
 			    vpd_data[i + 1] == 'N') {
-				int partno_len = vpd_data[i + 2];
+				int partno_len = pci_vpd_info_field_size(&vpd_data[i]);
 
-				i += 3;
+				i += PCI_VPD_INFO_FLD_HDR_SIZE;
 				if (partno_len > TG3_BPN_SIZE ||
 				    (partno_len + i) > TG3_NVM_VPD_LEN)
 					goto out_not_found;
@@ -12511,7 +12511,8 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
 				/* Success. */
 				return;
 			}
-			i += 3 + vpd_data[i + 2];
+			i += PCI_VPD_INFO_FLD_HDR_SIZE +
+			     pci_vpd_info_field_size(&vpd_data[i]);
 		}
 
 		/* Part number not found. */
diff --git a/include/linux/pci-vpd.h b/include/linux/pci-vpd.h
index 04eb87e..ebde9b9 100644
--- a/include/linux/pci-vpd.h
+++ b/include/linux/pci-vpd.h
@@ -38,6 +38,7 @@
 
 #define PCI_VPD_LRDT_TAG_SIZE		3
 #define PCI_VPD_SRDT_TAG_SIZE		1
+#define PCI_VPD_INFO_FLD_HDR_SIZE	3
 
 static inline u16 pci_vpd_lrdt_size(u8 *lrdt)
 {
@@ -51,4 +52,9 @@ static inline u8 pci_vpd_srdt_size(u8 *srdt)
 
 int pci_vpd_find_tag(u8 *data, unsigned int start, unsigned int len, u8 tagid);
 
+static inline u8 pci_vpd_info_field_size(u8 *info_field)
+{
+	return info_field[2];
+}
+
 #endif /* LINUX_PCI_VPD_H */
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 5/7] pci: Add helper to search for VPD keywords
From: Matt Carlson @ 2010-02-25 18:19 UTC (permalink / raw)
  To: jbarnes; +Cc: linux-pci, netdev, andy, mcarlson, Michael Chan

This patch adds the pci_vpd_find_info_keyword() helper function to
find information field keywords within read-only and read-write large
resource data type sections.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/bnx2.c      |   54 ++++++++++++++++++++++++++--------------------
 drivers/net/tg3.c       |   32 +++++++++++----------------
 drivers/pci/vpd.c       |   18 +++++++++++++++
 include/linux/pci-vpd.h |    7 ++++++
 4 files changed, 68 insertions(+), 43 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index c3e5182..fa4dc85 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -7760,48 +7760,54 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp)
 	}
 
 	for (i = 0; i <= BNX2_VPD_LEN - 3; ) {
-		unsigned int block_end;
+		int j;
+		unsigned int block_end, rosize;
 
 		i = pci_vpd_find_tag(data, i, BNX2_VPD_LEN,
 				     PCI_VPD_LRDT_RO_DATA);
 		if (i < 0)
 			break;
 
-		block_end = (i + PCI_VPD_LRDT_TAG_SIZE +
-			    pci_vpd_lrdt_size(&data[i]));
+		rosize = pci_vpd_lrdt_size(&data[i]);
+		block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize;
 		i += PCI_VPD_LRDT_TAG_SIZE;
 
 		if (block_end > BNX2_VPD_LEN)
 			goto vpd_done;
 
-		while (i < (block_end - 2)) {
-			int len = pci_vpd_info_field_size(&data[i]);
+		j = pci_vpd_find_info_keyword(data, i, rosize,
+					      PCI_VPD_RO_KEYWORD_MFR_ID);
+		if (j > 0) {
+			int len = pci_vpd_info_field_size(&data[j]);
 
-			if (i + PCI_VPD_INFO_FLD_HDR_SIZE + len > block_end)
+			if (j + PCI_VPD_INFO_FLD_HDR_SIZE + len > block_end ||
+			    len != 4 ||
+			    memcmp(&data[j + PCI_VPD_INFO_FLD_HDR_SIZE],
+				   "1028", 4))
 				goto vpd_done;
 
-			if (data[i] == 'M' && data[i + 1] == 'N') {
-				if (len != 4 ||
-				    memcmp(&data[i + PCI_VPD_INFO_FLD_HDR_SIZE],
-					   "1028", 4))
-					goto vpd_done;
-				mn_match = true;
+			mn_match = true;
+		}
 
-			} else if (data[i] == 'V' && data[i + 1] == '0') {
-				if (len > BNX2_MAX_VER_SLEN)
-					goto vpd_done;
+		j = pci_vpd_find_info_keyword(data, i, rosize,
+					      PCI_VPD_RO_KEYWORD_VENDOR0);
+		if (j > 0) {
+			int len = pci_vpd_info_field_size(&data[j]);
 
-				v0_len = len;
-				v0_str = &data[i + PCI_VPD_INFO_FLD_HDR_SIZE];
-			}
-			i += PCI_VPD_INFO_FLD_HDR_SIZE + len;
-
-			if (mn_match && v0_str) {
-				memcpy(bp->fw_version, v0_str, v0_len);
-				bp->fw_version[v0_len] = ' ';
+			j += PCI_VPD_INFO_FLD_HDR_SIZE;
+			if (j + len > block_end || len > BNX2_MAX_VER_SLEN)
 				goto vpd_done;
-			}
+
+			v0_len = len;
+			v0_str = &data[j];
 		}
+
+		if (mn_match && v0_str) {
+			memcpy(bp->fw_version, v0_str, v0_len);
+			bp->fw_version[v0_len] = ' ';
+			goto vpd_done;
+		}
+
 		goto vpd_done;
 	}
 
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 500a145..d9fa6c0 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -12480,39 +12480,33 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
 
 	/* Now parse and find the part number. */
 	for (i = 0; i < TG3_NVM_VPD_LEN - 2; ) {
-		unsigned int block_end;
+		unsigned int block_end, rosize;
 
 		i = pci_vpd_find_tag(vpd_data, i, TG3_NVM_VPD_LEN,
 				     PCI_VPD_LRDT_RO_DATA);
 		if (i < 0)
 			break;
 
-		block_end = i + PCI_VPD_LRDT_TAG_SIZE +
-			    pci_vpd_lrdt_size(&vpd_data[i]);
-
+		rosize = pci_vpd_lrdt_size(&vpd_data[i]);
+		block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize;
 		i += PCI_VPD_LRDT_TAG_SIZE;
 
 		if (block_end > TG3_NVM_VPD_LEN)
 			goto out_not_found;
 
-		while (i < (block_end - 2)) {
-			if (vpd_data[i + 0] == 'P' &&
-			    vpd_data[i + 1] == 'N') {
-				int partno_len = pci_vpd_info_field_size(&vpd_data[i]);
+		i = pci_vpd_find_info_keyword(vpd_data, i, rosize,
+					      PCI_VPD_RO_KEYWORD_PARTNO);
+		if (i > 0) {
+			u8 len = pci_vpd_info_field_size(&vpd_data[i]);
 
-				i += PCI_VPD_INFO_FLD_HDR_SIZE;
-				if (partno_len > TG3_BPN_SIZE ||
-				    (partno_len + i) > TG3_NVM_VPD_LEN)
-					goto out_not_found;
+			i += PCI_VPD_INFO_FLD_HDR_SIZE;
+			if (len > TG3_BPN_SIZE ||
+			    (len + i) > TG3_NVM_VPD_LEN)
+				break;
 
-				memcpy(tp->board_part_number,
-				       &vpd_data[i], partno_len);
+			memcpy(tp->board_part_number, &vpd_data[i], len);
 
-				/* Success. */
-				return;
-			}
-			i += PCI_VPD_INFO_FLD_HDR_SIZE +
-			     pci_vpd_info_field_size(&vpd_data[i]);
+			return;
 		}
 
 		/* Part number not found. */
diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c
index 1b5b3cc..c0b00cc 100644
--- a/drivers/pci/vpd.c
+++ b/drivers/pci/vpd.c
@@ -42,3 +42,21 @@ int pci_vpd_find_tag(u8 *data, unsigned int start, unsigned int len, u8 tagid)
 	return -ENOENT;
 }
 EXPORT_SYMBOL_GPL(pci_vpd_find_tag);
+
+int pci_vpd_find_info_keyword(u8 *rodata, unsigned int start,
+			      unsigned int rosize, char *kw)
+{
+	int i;
+
+	for (i = start; i + PCI_VPD_INFO_FLD_HDR_SIZE <= start + rosize;) {
+		if (rodata[i + 0] == kw[0] &&
+		    rodata[i + 1] == kw[1])
+			return i;
+
+		i += PCI_VPD_INFO_FLD_HDR_SIZE +
+		     pci_vpd_info_field_size(&rodata[i]);
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(pci_vpd_find_info_keyword);
diff --git a/include/linux/pci-vpd.h b/include/linux/pci-vpd.h
index ebde9b9..94b3a2a 100644
--- a/include/linux/pci-vpd.h
+++ b/include/linux/pci-vpd.h
@@ -36,6 +36,10 @@
 #define PCI_VPD_SRDT_TIN_MASK		0x78
 #define PCI_VPD_SRDT_LEN_MASK		0x07
 
+#define PCI_VPD_RO_KEYWORD_PARTNO	"PN"
+#define PCI_VPD_RO_KEYWORD_MFR_ID	"MN"
+#define PCI_VPD_RO_KEYWORD_VENDOR0	"V0"
+
 #define PCI_VPD_LRDT_TAG_SIZE		3
 #define PCI_VPD_SRDT_TAG_SIZE		1
 #define PCI_VPD_INFO_FLD_HDR_SIZE	3
@@ -57,4 +61,7 @@ static inline u8 pci_vpd_info_field_size(u8 *info_field)
 	return info_field[2];
 }
 
+int pci_vpd_find_info_keyword(u8 *rodata, unsigned int start,
+			      unsigned int rosize, char *kw);
+
 #endif /* LINUX_PCI_VPD_H */
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 6/7] bnx2: Remove now useless VPD code
From: Matt Carlson @ 2010-02-25 18:19 UTC (permalink / raw)
  To: jbarnes; +Cc: linux-pci, netdev, andy, mcarlson

Now that the VPD searching code is abstracted away, the outer loop used
to detect the read-only large resource data type section is useless.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
---
 drivers/net/bnx2.c |   74 ++++++++++++++++++++-------------------------------
 1 files changed, 29 insertions(+), 45 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index fa4dc85..f2f984a 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -7734,10 +7734,9 @@ bnx2_get_pci_speed(struct bnx2 *bp)
 static void __devinit
 bnx2_read_vpd_fw_ver(struct bnx2 *bp)
 {
-	int rc, i, v0_len = 0;
+	int rc, i, j;
 	u8 *data;
-	u8 *v0_str = NULL;
-	bool mn_match = false;
+	unsigned int block_end, rosize, len;
 
 #define BNX2_VPD_NVRAM_OFFSET	0x300
 #define BNX2_VPD_LEN		128
@@ -7759,57 +7758,42 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp)
 		data[i + 3] = data[i + BNX2_VPD_LEN];
 	}
 
-	for (i = 0; i <= BNX2_VPD_LEN - 3; ) {
-		int j;
-		unsigned int block_end, rosize;
-
-		i = pci_vpd_find_tag(data, i, BNX2_VPD_LEN,
-				     PCI_VPD_LRDT_RO_DATA);
-		if (i < 0)
-			break;
-
-		rosize = pci_vpd_lrdt_size(&data[i]);
-		block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize;
-		i += PCI_VPD_LRDT_TAG_SIZE;
-
-		if (block_end > BNX2_VPD_LEN)
-			goto vpd_done;
+	i = pci_vpd_find_tag(data, 0, BNX2_VPD_LEN, PCI_VPD_LRDT_RO_DATA);
+	if (i < 0)
+		goto vpd_done;
 
-		j = pci_vpd_find_info_keyword(data, i, rosize,
-					      PCI_VPD_RO_KEYWORD_MFR_ID);
-		if (j > 0) {
-			int len = pci_vpd_info_field_size(&data[j]);
+	rosize = pci_vpd_lrdt_size(&data[i]);
+	i += PCI_VPD_LRDT_TAG_SIZE;
+	block_end = i + rosize;
 
-			if (j + PCI_VPD_INFO_FLD_HDR_SIZE + len > block_end ||
-			    len != 4 ||
-			    memcmp(&data[j + PCI_VPD_INFO_FLD_HDR_SIZE],
-				   "1028", 4))
-				goto vpd_done;
+	if (block_end > BNX2_VPD_LEN)
+		goto vpd_done;
 
-			mn_match = true;
-		}
+	j = pci_vpd_find_info_keyword(data, i, rosize,
+				      PCI_VPD_RO_KEYWORD_MFR_ID);
+	if (j < 0)
+		goto vpd_done;
 
-		j = pci_vpd_find_info_keyword(data, i, rosize,
-					      PCI_VPD_RO_KEYWORD_VENDOR0);
-		if (j > 0) {
-			int len = pci_vpd_info_field_size(&data[j]);
+	len = pci_vpd_info_field_size(&data[j]);
 
-			j += PCI_VPD_INFO_FLD_HDR_SIZE;
-			if (j + len > block_end || len > BNX2_MAX_VER_SLEN)
-				goto vpd_done;
+	j += PCI_VPD_INFO_FLD_HDR_SIZE;
+	if (j + len > block_end || len != 4 ||
+	    memcmp(&data[j], "1028", 4))
+		goto vpd_done;
 
-			v0_len = len;
-			v0_str = &data[j];
-		}
+	j = pci_vpd_find_info_keyword(data, i, rosize,
+				      PCI_VPD_RO_KEYWORD_VENDOR0);
+	if (j < 0)
+		goto vpd_done;
 
-		if (mn_match && v0_str) {
-			memcpy(bp->fw_version, v0_str, v0_len);
-			bp->fw_version[v0_len] = ' ';
-			goto vpd_done;
-		}
+	len = pci_vpd_info_field_size(&data[j]);
 
+	j += PCI_VPD_INFO_FLD_HDR_SIZE;
+	if (j + len > block_end || len > BNX2_MAX_VER_SLEN)
 		goto vpd_done;
-	}
+
+	memcpy(bp->fw_version, &data[j], len);
+	bp->fw_version[len] = ' ';
 
 vpd_done:
 	kfree(data);
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 3/7] pci: Add helper to find a VPD resource data type
From: Matt Carlson @ 2010-02-25 18:19 UTC (permalink / raw)
  To: jbarnes; +Cc: linux-pci, netdev, andy, mcarlson, Michael Chan

This patch adds the pci_vpd_find_tag() helper function to find VPD
resource data types in a buffer.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/bnx2.c      |   24 ++++--------------------
 drivers/net/tg3.c       |   26 +++++---------------------
 drivers/pci/Makefile    |    2 +-
 drivers/pci/vpd.c       |   44 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pci-vpd.h |    2 ++
 5 files changed, 56 insertions(+), 42 deletions(-)
 create mode 100644 drivers/pci/vpd.c

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 1c48d4a..2de3576 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -7760,28 +7760,12 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp)
 	}
 
 	for (i = 0; i <= BNX2_VPD_LEN - 3; ) {
-		unsigned char val = data[i];
 		unsigned int block_end;
 
-		if (val & PCI_VPD_LRDT) {
-			if (i + PCI_VPD_LRDT_TAG_SIZE > BNX2_VPD_LEN)
-				break;
-
-			if (val != PCI_VPD_LRDT_RO_DATA) {
-				i += PCI_VPD_LRDT_TAG_SIZE +
-				     pci_vpd_lrdt_size(&data[i]);
-
-				continue;
-			}
-		} else {
-			if ((val & PCI_VPD_SRDT_TIN_MASK) == PCI_VPD_STIN_END)
-				break;
-
-			i += PCI_VPD_SRDT_TAG_SIZE +
-			     pci_vpd_srdt_size(&data[i]);
-
-			continue;
-		}
+		i = pci_vpd_find_tag(data, i, BNX2_VPD_LEN,
+				     PCI_VPD_LRDT_RO_DATA);
+		if (i < 0)
+			break;
 
 		block_end = (i + PCI_VPD_LRDT_TAG_SIZE +
 			    pci_vpd_lrdt_size(&data[i]));
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 2ec6eca..eaf178b 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -12441,7 +12441,7 @@ skip_phy_reset:
 static void __devinit tg3_read_partno(struct tg3 *tp)
 {
 	unsigned char vpd_data[TG3_NVM_VPD_LEN];   /* in little-endian format */
-	unsigned int i;
+	int i;
 	u32 magic;
 
 	if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) ||
@@ -12480,28 +12480,12 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
 
 	/* Now parse and find the part number. */
 	for (i = 0; i < TG3_NVM_VPD_LEN - 2; ) {
-		unsigned char val = vpd_data[i];
 		unsigned int block_end;
 
-		if (val & PCI_VPD_LRDT) {
-			if (i + PCI_VPD_LRDT_TAG_SIZE > TG3_NVM_VPD_LEN)
-				break;
-
-			if (val != PCI_VPD_LRDT_RO_DATA) {
-				i += PCI_VPD_LRDT_TAG_SIZE +
-				     pci_vpd_lrdt_size(&vpd_data[i]);
-
-				continue;
-			}
-		} else {
-			if ((val & PCI_VPD_SRDT_TIN_MASK) == PCI_VPD_STIN_END)
-				break;
-
-			i += PCI_VPD_SRDT_TAG_SIZE +
-			     pci_vpd_srdt_size(&vpd_data[i]);
-
-			continue;
-		}
+		i = pci_vpd_find_tag(vpd_data, i, TG3_NVM_VPD_LEN,
+				     PCI_VPD_LRDT_RO_DATA);
+		if (i < 0)
+			break;
 
 		block_end = i + PCI_VPD_LRDT_TAG_SIZE +
 			    pci_vpd_lrdt_size(&vpd_data[i]);
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 4df48d5..b2f6d77 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -4,7 +4,7 @@
 
 obj-y		+= access.o bus.o probe.o remove.o pci.o quirks.o \
 			pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
-			irq.o
+			irq.o vpd.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSFS) += slot.o
 
diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c
new file mode 100644
index 0000000..1b5b3cc
--- /dev/null
+++ b/drivers/pci/vpd.c
@@ -0,0 +1,44 @@
+/*
+ * File:	vpd.c
+ * Purpose:	Provide PCI VPD support
+ *
+ * Copyright (C) 2010 Broadcom Corporation.
+ */
+
+#include <linux/pci.h>
+#include <linux/pci-vpd.h>
+
+int pci_vpd_find_tag(u8 *data, unsigned int start, unsigned int len, u8 tagid)
+{
+	int i;
+
+	for (i = start; i < start + len; ) {
+		u8 val = data[i];
+
+		if (val & PCI_VPD_LRDT) {
+			/* Don't return success of the tag isn't complete */
+			if (i + PCI_VPD_LRDT_TAG_SIZE > start + len)
+				break;
+
+			if (val == tagid)
+				return i;
+
+			i += PCI_VPD_LRDT_TAG_SIZE +
+			     pci_vpd_lrdt_size(&data[i]);
+		} else {
+			u8 tag = val & ~PCI_VPD_SRDT_LEN_MASK;
+
+			if (tag == tagid)
+				return i;
+
+			if (tag == PCI_VPD_SRDT_END)
+				break;
+
+			i += PCI_VPD_SRDT_TAG_SIZE +
+			     pci_vpd_srdt_size(&data[i]);
+		}
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(pci_vpd_find_tag);
diff --git a/include/linux/pci-vpd.h b/include/linux/pci-vpd.h
index b80d5c0..04eb87e 100644
--- a/include/linux/pci-vpd.h
+++ b/include/linux/pci-vpd.h
@@ -49,4 +49,6 @@ static inline u8 pci_vpd_srdt_size(u8 *srdt)
 	return (*srdt) & PCI_VPD_SRDT_LEN_MASK;
 }
 
+int pci_vpd_find_tag(u8 *data, unsigned int start, unsigned int len, u8 tagid);
+
 #endif /* LINUX_PCI_VPD_H */
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 2/7] pci: Add large and small resource data type code
From: Matt Carlson @ 2010-02-25 18:19 UTC (permalink / raw)
  To: jbarnes; +Cc: linux-pci, netdev, andy, mcarlson, Michael Chan

This patch introduces more VPD preprocessor definitions to identify some
small and large resource data type item names.  The patch then continues
to correct how the tg3 and bnx2 drivers search for the "read-only data"
large resource data type.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/bnx2.c      |   23 +++++++++++++++++------
 drivers/net/tg3.c       |   23 +++++++++++++++++------
 include/linux/pci-vpd.h |   28 +++++++++++++++++++++++++++-
 3 files changed, 61 insertions(+), 13 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 9f5b0fc..1c48d4a 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -7763,15 +7763,26 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp)
 		unsigned char val = data[i];
 		unsigned int block_end;
 
-		if (val == 0x82 || val == 0x91) {
-			i += PCI_VPD_LRDT_TAG_SIZE +
-			     pci_vpd_lrdt_size(&data[i]);
+		if (val & PCI_VPD_LRDT) {
+			if (i + PCI_VPD_LRDT_TAG_SIZE > BNX2_VPD_LEN)
+				break;
+
+			if (val != PCI_VPD_LRDT_RO_DATA) {
+				i += PCI_VPD_LRDT_TAG_SIZE +
+				     pci_vpd_lrdt_size(&data[i]);
+
+				continue;
+			}
+		} else {
+			if ((val & PCI_VPD_SRDT_TIN_MASK) == PCI_VPD_STIN_END)
+				break;
+
+			i += PCI_VPD_SRDT_TAG_SIZE +
+			     pci_vpd_srdt_size(&data[i]);
+
 			continue;
 		}
 
-		if (val != 0x90)
-			goto vpd_done;
-
 		block_end = (i + PCI_VPD_LRDT_TAG_SIZE +
 			    pci_vpd_lrdt_size(&data[i]));
 		i += PCI_VPD_LRDT_TAG_SIZE;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 6cab97f..2ec6eca 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -12483,15 +12483,26 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
 		unsigned char val = vpd_data[i];
 		unsigned int block_end;
 
-		if (val == 0x82 || val == 0x91) {
-			i += PCI_VPD_LRDT_TAG_SIZE +
-			     pci_vpd_lrdt_size(&vpd_data[i]);
+		if (val & PCI_VPD_LRDT) {
+			if (i + PCI_VPD_LRDT_TAG_SIZE > TG3_NVM_VPD_LEN)
+				break;
+
+			if (val != PCI_VPD_LRDT_RO_DATA) {
+				i += PCI_VPD_LRDT_TAG_SIZE +
+				     pci_vpd_lrdt_size(&vpd_data[i]);
+
+				continue;
+			}
+		} else {
+			if ((val & PCI_VPD_SRDT_TIN_MASK) == PCI_VPD_STIN_END)
+				break;
+
+			i += PCI_VPD_SRDT_TAG_SIZE +
+			     pci_vpd_srdt_size(&vpd_data[i]);
+
 			continue;
 		}
 
-		if (val != 0x90)
-			goto out_not_found;
-
 		block_end = i + PCI_VPD_LRDT_TAG_SIZE +
 			    pci_vpd_lrdt_size(&vpd_data[i]);
 
diff --git a/include/linux/pci-vpd.h b/include/linux/pci-vpd.h
index c077369..b80d5c0 100644
--- a/include/linux/pci-vpd.h
+++ b/include/linux/pci-vpd.h
@@ -16,11 +16,37 @@
 
 #include <linux/pci.h>
 
-#define PCI_VPD_LRDT_TAG_SIZE	3
+#define PCI_VPD_LRDT			0x80	/* Large Resource Data Type */
+#define PCI_VPD_LRDT_ID(x)		(x | PCI_VPD_LRDT)
+
+/* Large Resource Data Type Tag Item Names */
+#define PCI_VPD_LTIN_ID_STRING		0x02	/* Identifier String */
+#define PCI_VPD_LTIN_RO_DATA		0x10	/* Read-Only Data */
+#define PCI_VPD_LTIN_RW_DATA		0x11	/* Read-Write Data */
+
+#define PCI_VPD_LRDT_ID_STRING		PCI_VPD_LRDT_ID(PCI_VPD_LTIN_ID_STRING)
+#define PCI_VPD_LRDT_RO_DATA		PCI_VPD_LRDT_ID(PCI_VPD_LTIN_RO_DATA)
+#define PCI_VPD_LRDT_RW_DATA		PCI_VPD_LRDT_ID(PCI_VPD_LTIN_RW_DATA)
+
+/* Small Resource Data Type Tag Item Names */
+#define PCI_VPD_STIN_END		0x78	/* End */
+
+#define PCI_VPD_SRDT_END		PCI_VPD_STIN_END
+
+#define PCI_VPD_SRDT_TIN_MASK		0x78
+#define PCI_VPD_SRDT_LEN_MASK		0x07
+
+#define PCI_VPD_LRDT_TAG_SIZE		3
+#define PCI_VPD_SRDT_TAG_SIZE		1
 
 static inline u16 pci_vpd_lrdt_size(u8 *lrdt)
 {
 	return (u16)lrdt[1] + ((u16)lrdt[2] << 8);
 }
 
+static inline u8 pci_vpd_srdt_size(u8 *srdt)
+{
+	return (*srdt) & PCI_VPD_SRDT_LEN_MASK;
+}
+
 #endif /* LINUX_PCI_VPD_H */
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 0/7] pci: Add VPD parsing support
From: Matt Carlson @ 2010-02-25 18:19 UTC (permalink / raw)
  To: jbarnes; +Cc: linux-pci, netdev, andy, mcarlson

This patch adds code to help parse a device's VPD.  The bnx2 and tg3
network drivers are modified as an example on how to use the API.  I
believe the bnx2x driver will also use this API in the future.



^ permalink raw reply

* [PATCH 7/7] tg3: Remove now useless VPD code
From: Matt Carlson @ 2010-02-25 18:19 UTC (permalink / raw)
  To: jbarnes; +Cc: linux-pci, netdev, andy, mcarlson

Now that the VPD searching code is abstracted away, the outer loop used
to detect the read-only large resource data type section is useless.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
---
 drivers/net/tg3.c |   52 +++++++++++++++++++++++-----------------------------
 1 files changed, 23 insertions(+), 29 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index d9fa6c0..66d0a33 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -12441,7 +12441,8 @@ skip_phy_reset:
 static void __devinit tg3_read_partno(struct tg3 *tp)
 {
 	unsigned char vpd_data[TG3_NVM_VPD_LEN];   /* in little-endian format */
-	int i;
+	unsigned int block_end, rosize, len;
+	int i = 0;
 	u32 magic;
 
 	if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) ||
@@ -12463,7 +12464,7 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
 		}
 	} else {
 		ssize_t cnt;
-		unsigned int pos = 0, i = 0;
+		unsigned int pos = 0;
 
 		for (; pos < TG3_NVM_VPD_LEN && i < 3; i++, pos += cnt) {
 			cnt = pci_read_vpd(tp->pdev, pos,
@@ -12478,40 +12479,33 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
 			goto out_not_found;
 	}
 
-	/* Now parse and find the part number. */
-	for (i = 0; i < TG3_NVM_VPD_LEN - 2; ) {
-		unsigned int block_end, rosize;
+	i = pci_vpd_find_tag(vpd_data, 0, TG3_NVM_VPD_LEN,
+			     PCI_VPD_LRDT_RO_DATA);
+	if (i < 0)
+		goto out_not_found;
 
-		i = pci_vpd_find_tag(vpd_data, i, TG3_NVM_VPD_LEN,
-				     PCI_VPD_LRDT_RO_DATA);
-		if (i < 0)
-			break;
+	rosize = pci_vpd_lrdt_size(&vpd_data[i]);
+	block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize;
+	i += PCI_VPD_LRDT_TAG_SIZE;
 
-		rosize = pci_vpd_lrdt_size(&vpd_data[i]);
-		block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize;
-		i += PCI_VPD_LRDT_TAG_SIZE;
+	if (block_end > TG3_NVM_VPD_LEN)
+		goto out_not_found;
 
-		if (block_end > TG3_NVM_VPD_LEN)
-			goto out_not_found;
+	i = pci_vpd_find_info_keyword(vpd_data, i, rosize,
+				      PCI_VPD_RO_KEYWORD_PARTNO);
+	if (i < 0)
+		goto out_not_found;
 
-		i = pci_vpd_find_info_keyword(vpd_data, i, rosize,
-					      PCI_VPD_RO_KEYWORD_PARTNO);
-		if (i > 0) {
-			u8 len = pci_vpd_info_field_size(&vpd_data[i]);
+	len = pci_vpd_info_field_size(&vpd_data[i]);
 
-			i += PCI_VPD_INFO_FLD_HDR_SIZE;
-			if (len > TG3_BPN_SIZE ||
-			    (len + i) > TG3_NVM_VPD_LEN)
-				break;
-
-			memcpy(tp->board_part_number, &vpd_data[i], len);
+	i += PCI_VPD_INFO_FLD_HDR_SIZE;
+	if (len > TG3_BPN_SIZE ||
+	    (len + i) > TG3_NVM_VPD_LEN)
+		goto out_not_found;
 
-			return;
-		}
+	memcpy(tp->board_part_number, &vpd_data[i], len);
 
-		/* Part number not found. */
-		goto out_not_found;
-	}
+	return;
 
 out_not_found:
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
-- 
1.6.4.4



^ permalink raw reply related

* Re: Gianfar driver failing on MPC8641D based board
From: Kumar Gala @ 2010-02-25 18:27 UTC (permalink / raw)
  To: Martyn Welch
  Cc: linuxppc-dev list, netdev, linux-kernel, Anton Vorontsov,
	Sandeep Gopalpet, davem
In-Reply-To: <4B86A97E.6050509@ge.com>


On Feb 25, 2010, at 10:46 AM, Martyn Welch wrote:

> 
> Further testing has shown that this isn't restricted to warm reboots, it
> happens from cold as well. In addition, the exact timing of the failure
> seems to vary, some boots have got further before failing.

what mechanism do you use for warm resets?

- k

^ permalink raw reply

* Re:Royal Dutch Oil
From: ©Web Unit @ 2010-02-25 18:28 UTC (permalink / raw)
  To: info

$1.500,000.00 US Dollars has been award to you by your Email in the ROYAL DUTCH OIL 2010 send your requirement immediately such as your
Names,,,,,,,,,,,
Tel,,,,,,,,,,,,,,,,,,
Age,,,,,,,,,,,,,,,,
Address,,,,,,,,,,,,
Occupation,,,,,,,,,,
Country,,,,,,,,,,,,,,,
Email:pyunit23@yahoo.ie

^ permalink raw reply

* Re:Royal Dutch Oil
From: ©Web Unit @ 2010-02-25 18:28 UTC (permalink / raw)
  To: info

$1.500,000.00 US Dollars has been award to you by your Email in the ROYAL DUTCH OIL 2010 send your requirement immediately such as your
Names,,,,,,,,,,,
Tel,,,,,,,,,,,,,,,,,,
Age,,,,,,,,,,,,,,,,
Address,,,,,,,,,,,,
Occupation,,,,,,,,,,
Country,,,,,,,,,,,,,,,
Email:pyunit23@yahoo.ie

^ permalink raw reply

* Re:Royal Dutch Oil
From: ©Web Unit @ 2010-02-25 18:34 UTC (permalink / raw)
  To: info

$1.500,000.00 US Dollars has been award to you by your Email in the ROYAL DUTCH OIL 2010 send your requirement immediately such as your
Names,,,,,,,,,,,
Tel,,,,,,,,,,,,,,,,,,
Age,,,,,,,,,,,,,,,,
Address,,,,,,,,,,,,
Occupation,,,,,,,,,,
Country,,,,,,,,,,,,,,,
Email:pyunit23@yahoo.ie

^ permalink raw reply

* Re: [PATCH 1/7] pci: Add PCI LRDT tag size and section size
From: Stephen Hemminger @ 2010-02-25 18:53 UTC (permalink / raw)
  To: Matt Carlson; +Cc: jbarnes, linux-pci, netdev, andy, mcarlson, Michael Chan
In-Reply-To: <1267121962-6077-2-git-send-email-mcarlson@broadcom.com>

On Thu, 25 Feb 2010 10:19:16 -0800
"Matt Carlson" <mcarlson@broadcom.com> wrote:

> +++ b/include/linux/pci-vpd.h
> @@ -0,0 +1,26 @@
> +/*
> + *	pci-vpd.h
> + *
> + *	PCI VPD defines and function prototypes
> + *
> + *	Copyright (C) 2010 Broadcom Corporation.
> + *
> + *	For more information, please consult the following manuals (look at
> + *	http://www.pcisig.com/ for how to get them):
> + *
> + *	PCI Local Bus Specification, Rev. 3.0 : Appendix I
> + */
> +
> +#ifndef LINUX_PCI_VPD_H
> +#define LINUX_PCI_VPD_H
> +
> +#include <linux/pci.h>
> +
> +#define PCI_VPD_LRDT_TAG_SIZE	3
> +
> +static inline u16 pci_vpd_lrdt_size(u8 *lrdt)
> +{
> +	return (u16)lrdt[1] + ((u16)lrdt[2] << 8);
> +}
> +
> +#endif /* LINUX_PCI_VPD_H */
> -- 

No need for new file for this, it should be part of existing pci.h
Also need kernel doc format comment to describe usage.
Shouldn't the function take the pci resource not just the register.

And finally, how common is this or is it just something unique to your hw.

^ permalink raw reply

* Re: [PATCH 1/7] pci: Add PCI LRDT tag size and section size
From: Matt Carlson @ 2010-02-25 19:11 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Matthew Carlson, jbarnes@virtuousgeek.org,
	linux-pci@vger.kernel.org, netdev@vger.kernel.org,
	andy@greyhouse.net, Michael Chan
In-Reply-To: <20100225105345.0baadeb4@nehalam>

On Thu, Feb 25, 2010 at 10:53:45AM -0800, Stephen Hemminger wrote:
> On Thu, 25 Feb 2010 10:19:16 -0800
> "Matt Carlson" <mcarlson@broadcom.com> wrote:
> 
> > +++ b/include/linux/pci-vpd.h
> > @@ -0,0 +1,26 @@
> > +/*
> > + *	pci-vpd.h
> > + *
> > + *	PCI VPD defines and function prototypes
> > + *
> > + *	Copyright (C) 2010 Broadcom Corporation.
> > + *
> > + *	For more information, please consult the following manuals (look at
> > + *	http://www.pcisig.com/ for how to get them):
> > + *
> > + *	PCI Local Bus Specification, Rev. 3.0 : Appendix I
> > + */
> > +
> > +#ifndef LINUX_PCI_VPD_H
> > +#define LINUX_PCI_VPD_H
> > +
> > +#include <linux/pci.h>
> > +
> > +#define PCI_VPD_LRDT_TAG_SIZE	3
> > +
> > +static inline u16 pci_vpd_lrdt_size(u8 *lrdt)
> > +{
> > +	return (u16)lrdt[1] + ((u16)lrdt[2] << 8);
> > +}
> > +
> > +#endif /* LINUX_PCI_VPD_H */
> > -- 
> 
> No need for new file for this, it should be part of existing pci.h

O.K.  I'll make the change.

> Also need kernel doc format comment to describe usage.

O.K.

> Shouldn't the function take the pci resource not just the register.

The functions are designed to operate on a buffer of VPD data, not from
the hardware directly.

> And finally, how common is this or is it just something unique to your hw.

The VPD area is defined by the PCI specs, in the section noted in the
comment above.  The definitions and functions introduced in this patchset
should be usable by any driver.  I stopped short of modifying other
drivers, but I certainly could have.

However, there are two approaches taken as to how the VPD data is
extracted and used.  Drivers like tg3 and bnx2 load the VPD data into
a buffer and operate on that.  Other drivers like niu navigate the VPD
by loading a dword at a time.  This API would cover the former
implementation which I've only found to be used by the tg3 and bnx2
drivers so far.

^ permalink raw reply

* Re: [Bugme-new] [Bug 15379] New: u32 classifier port range calculation error
From: Reinaldo de Carvalho @ 2010-02-25 19:11 UTC (permalink / raw)
  To: hadi; +Cc: Andrew Morton, netdev, bugzilla-daemon, bugme-daemon
In-Reply-To: <1267104293.3973.947.camel@bigi>

On Thu, Feb 25, 2010 at 10:24 AM, jamal <hadi@cyberus.ca> wrote:
> On Thu, 2010-02-25 at 08:25 -0300, Reinaldo de Carvalho wrote:
>> Then u32 mask is useless. Or exist a correct mask to match with especific range?
>
> Ranges and masks typically dont mix well generally - this has nothing to
> do with u32; try doing subnet ranges for example. It is hard to describe
> port range 10->20 using masks..
>
> If i read your email correctly: you are trying to get the first 32 ports
> after 6880. It would seem to me the mask should be 0xFFE0, no? i.e your
> bc calculation should be:
> echo "obase=16;(2^16)-32" | bc
>

No.

Testing with mask 0xFFE0... (1 port match)

# Stats...
# tc -s filter show dev eth0
filter parent 1: protocol ip pref 1 u32
filter parent 1: protocol ip pref 1 u32 fh 800: ht divisor 1
filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht
800 bkt 0 flowid 1:1200  (rule hit 13 success 0)
  match 00001ae0/0000ffe0 at 20 (success 0 )

# Sending packets...
# nmap example.ufpa.br -p 1-65535

# Stats...
# tc -s filter show dev eth0
filter parent 1: protocol ip pref 1 u32
filter parent 1: protocol ip pref 1 u32 fh 800: ht divisor 1
filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht
800 bkt 0 flowid 1:1200  (rule hit 65459 success 1)
  match 00001ae0/0000ffe0 at 20 (success 1 )




-- 
Reinaldo de Carvalho
http://korreio.sf.net
http://python-cyrus.sf.net

"Don't try to adapt the software to the way you work, but rather
yourself to the way the software works" (myself)

^ permalink raw reply

* Re: [PATCH 1/7] pci: Add PCI LRDT tag size and section size
From: Ben Hutchings @ 2010-02-25 19:36 UTC (permalink / raw)
  To: Matt Carlson
  Cc: Stephen Hemminger, jbarnes@virtuousgeek.org,
	linux-pci@vger.kernel.org, netdev@vger.kernel.org,
	andy@greyhouse.net, Michael Chan
In-Reply-To: <20100225191110.GA6231@xw6200.broadcom.net>

On Thu, 2010-02-25 at 11:11 -0800, Matt Carlson wrote:
> On Thu, Feb 25, 2010 at 10:53:45AM -0800, Stephen Hemminger wrote:
[...]
> > Shouldn't the function take the pci resource not just the register.
> 
> The functions are designed to operate on a buffer of VPD data, not from
> the hardware directly.
> 
> > And finally, how common is this or is it just something unique to your hw.
> 
> The VPD area is defined by the PCI specs, in the section noted in the
> comment above.  The definitions and functions introduced in this patchset
> should be usable by any driver.  I stopped short of modifying other
> drivers, but I certainly could have.
> 
> However, there are two approaches taken as to how the VPD data is
> extracted and used.  Drivers like tg3 and bnx2 load the VPD data into
> a buffer and operate on that.  Other drivers like niu navigate the VPD
> by loading a dword at a time.  This API would cover the former
> implementation which I've only found to be used by the tg3 and bnx2
> drivers so far.

VPD *access* can be done generically through pci_read_vpd() and
pci_write_vpd(), which use struct pci_vpd_ops.  Currently the only
implementation of pci_vpd_ops is for standard PCI 2.2 VPD.  Other
implementations could be provided for PCI 2.1 VPD or non-standard access
methods.

VPD *parsing* is currently left to user-space (lspci etc.) and to a few
drivers that need it for some reason.

I notice that bnx2 and tg3 are not using pci_read_vpd().  Presumably
this is an optimisation?

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* Re: [PATCH 1/7] pci: Add PCI LRDT tag size and section size
From: Matt Carlson @ 2010-02-25 19:48 UTC (permalink / raw)
  To: Ben Hutchings
  Cc: Matthew Carlson, Stephen Hemminger, jbarnes@virtuousgeek.org,
	linux-pci@vger.kernel.org, netdev@vger.kernel.org,
	andy@greyhouse.net, Michael Chan
In-Reply-To: <1267126561.2107.13.camel@achroite.uk.solarflarecom.com>

On Thu, Feb 25, 2010 at 11:36:01AM -0800, Ben Hutchings wrote:
> On Thu, 2010-02-25 at 11:11 -0800, Matt Carlson wrote:
> > On Thu, Feb 25, 2010 at 10:53:45AM -0800, Stephen Hemminger wrote:
> [...]
> > > Shouldn't the function take the pci resource not just the register.
> > 
> > The functions are designed to operate on a buffer of VPD data, not from
> > the hardware directly.
> > 
> > > And finally, how common is this or is it just something unique to your hw.
> > 
> > The VPD area is defined by the PCI specs, in the section noted in the
> > comment above.  The definitions and functions introduced in this patchset
> > should be usable by any driver.  I stopped short of modifying other
> > drivers, but I certainly could have.
> > 
> > However, there are two approaches taken as to how the VPD data is
> > extracted and used.  Drivers like tg3 and bnx2 load the VPD data into
> > a buffer and operate on that.  Other drivers like niu navigate the VPD
> > by loading a dword at a time.  This API would cover the former
> > implementation which I've only found to be used by the tg3 and bnx2
> > drivers so far.
> 
> VPD *access* can be done generically through pci_read_vpd() and
> pci_write_vpd(), which use struct pci_vpd_ops.  Currently the only
> implementation of pci_vpd_ops is for standard PCI 2.2 VPD.  Other
> implementations could be provided for PCI 2.1 VPD or non-standard access
> methods.
> 
> VPD *parsing* is currently left to user-space (lspci etc.) and to a few
> drivers that need it for some reason.
> 
> I notice that bnx2 and tg3 are not using pci_read_vpd().  Presumably
> this is an optimisation?

The tg3 driver does use pci_read_vpd() for those cases where
(magic != TG3_EEPROM_MAGIC).  But yes, it is an optimization.


^ permalink raw reply

* [PATCH] Export smbios strings associated with onboard devices to sysfs
From: Narendra K @ 2010-02-25 20:29 UTC (permalink / raw)
  To: netdev, linux-hotplug, linux-pci
  Cc: matt_domsch, jordan_hargrave, sandeep_k_shandilya, charles_rose,
	shyam_iyer

Hello,

[Please let me know if any other list needs to be copied]

* We have been having discussions in the netdev list about creating multiple names for the network interfaces to bring determinism into the way network interfaces are named in the OSes. In specific, "eth0 in the OS does not always map to the integrated NIC Gb1 as labelled on the chassis".  

http://marc.info/?l=linux-netdev&m=125510301513312&w=2 - (Re: PATCH: Network Device Naming mechanism and policy)
http://marc.info/?l=linux-netdev&m=125619338904322&w=2 - ([PATCH] udev: create empty regular files to represent net)

This was not favored.

* We also had proposed an installer based approach where installers would provide options to rename kernel eth names to namespaces based on different policies like smbios names etc. That was also not favored.

As a result of these discussions we propose another solution - 

1.Export smbios strings of onboard devices, to sysfs. For example -

cat /sys/class/net/eth0/device/smbiosname
Embedded NIC 2

cat  /sys/bus/pci/devices/0000\:03\:00.0/smbiosname
Embedded NIC 2

2. User space library like libnetdevname would map these smbiosname names to eth names and eth names to smbiosnames

3. User space tools would use the smbios alias names in addition to the eth names they already support. This ensures that, right interface is referred to, irrespective of how the interface is named by the kernel (eth0 or eth1..).

For example:

/sbin/ethtool -p "Embedded NIC 1" (Might be eth0 or eth1)
/sbin/ip link show "Embedded NIC 2"

Please refer to - 

* http://linux.dell.com/wiki/index.php/Oss/libnetdevname#Linux_Enumeration_of_NICs_in_the_Enterprise -  for more information for more information on the issue we are trying to address
* http://linux.dell.com/wiki/index.php/Oss/libnetdevname#Proposal_2:  - for more information on the current proposal.

Submitting the patch which addresses point 1 mentioned above for review. 


Signed-off-by: Jordan Hargrave <Jordan_Hargrave@dell.com>
Signed-off-by: Narendra K <Narendra_K@dell.com>
---
 drivers/base/bus.c          |    5 +++++
 drivers/firmware/dmi_scan.c |   23 +++++++++++++++++++++++
 drivers/pci/pci-sysfs.c     |   38 ++++++++++++++++++++++++++++++++++++++
 include/linux/device.h      |    4 ++++
 include/linux/dmi.h         |    9 +++++++++
 5 files changed, 79 insertions(+), 0 deletions(-)

diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index c0c5a43..ad0fcfb 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -419,6 +419,11 @@ static int device_add_attrs(struct bus_type *bus, struct device *dev)
 		return 0;
 
 	for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
+		/* if the device does not have an associated smbios string in the smbios table, do not create this attribute */ 
+		if (!(strcmp(attr_name(bus->dev_attrs[i]), "smbiosname"))) {
+			if (!smbiosname_string_is_valid(dev, NULL)) 
+				continue;
+		}
 		error = device_create_file(dev, &bus->dev_attrs[i]);
 		if (error) {
 			while (--i >= 0)
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 31b983d..1d10663 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -278,6 +278,28 @@ static void __init dmi_save_ipmi_device(const struct dmi_header *dm)
 	list_add_tail(&dev->list, &dmi_devices);
 }
 
+static void __init dmi_save_devslot(int id, int seg, int bus, int devfn, const char *name)
+{
+	struct dmi_devslot *slot;
+
+	slot = dmi_alloc(sizeof(*slot) + strlen(name) + 1);
+	if (!slot) {
+		printk(KERN_ERR "dmi_save_devslot: out of memory.\n");
+		return;
+	}	
+	slot->id = id;
+	slot->seg = seg;
+	slot->bus = bus;
+	slot->devfn = devfn;
+
+	strcpy((char *)&slot[1], name);
+	slot->dev.type = DMI_DEV_TYPE_DEVSLOT;
+	slot->dev.name = &slot[1];
+	slot->dev.device_data = slot;
+
+	list_add(&slot->dev.list, &dmi_devices);
+}
+
 static void __init dmi_save_extended_devices(const struct dmi_header *dm)
 {
 	const u8 *d = (u8*) dm + 5;
@@ -286,6 +308,7 @@ static void __init dmi_save_extended_devices(const struct dmi_header *dm)
 	if ((*d & 0x80) == 0)
 		return;
 
+	dmi_save_devslot(-1, *(u16 *)(d+2), *(d+4), *(d+5), dmi_string_nosave(dm, *(d-1)));
 	dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1)));
 }
 
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index c5df94e..a3b9bf9 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -140,6 +140,41 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
 		       (u8)(pci_dev->class));
 }
 
+#ifdef CONFIG_DMI
+#include <linux/dmi.h>
+ssize_t
+smbiosname_string_is_valid(struct device *dev, char *buf)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+  	struct dmi_device *dmi;
+  	struct dmi_devslot *dslot;
+  	int bus;
+  	int devfn;
+
+  	bus = pdev->bus->number;
+  	devfn = pdev->devfn;
+
+  	dmi = NULL;
+  	while ((dmi = dmi_find_device(DMI_DEV_TYPE_DEVSLOT, NULL, dmi)) != NULL) {
+    		dslot = dmi->device_data;
+    		if (dslot && dslot->bus == bus && dslot->devfn == devfn) {
+			if (buf)
+      				return scnprintf(buf, PAGE_SIZE, "%s\n", dmi->name);
+			return strlen(dmi->name);
+		}
+		
+	}
+}
+EXPORT_SYMBOL(smbiosname_string_is_valid);
+
+static ssize_t
+smbiosname_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return smbiosname_string_is_valid(dev, buf);
+
+}
+#endif
+
 static ssize_t is_enabled_store(struct device *dev,
 				struct device_attribute *attr, const char *buf,
 				size_t count)
@@ -324,6 +359,9 @@ struct device_attribute pci_dev_attrs[] = {
 	__ATTR_RO(class),
 	__ATTR_RO(irq),
 	__ATTR_RO(local_cpus),
+#ifdef CONFIG_DMI
+	__ATTR_RO(smbiosname),
+#endif
 	__ATTR_RO(local_cpulist),
 	__ATTR_RO(modalias),
 #ifdef CONFIG_NUMA
diff --git a/include/linux/device.h b/include/linux/device.h
index a62799f..647246c 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -427,6 +427,10 @@ struct device {
 	void	(*release)(struct device *dev);
 };
 
+#ifdef CONFIG_DMI
+extern ssize_t smbiosname_string_is_valid(struct device *, char *);
+#endif
+
 /* Get the wakeup routines, which depend on struct device */
 #include <linux/pm_wakeup.h>
 
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index a8a3e1a..cc57c3a 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -20,6 +20,7 @@ enum dmi_device_type {
 	DMI_DEV_TYPE_SAS,
 	DMI_DEV_TYPE_IPMI = -1,
 	DMI_DEV_TYPE_OEM_STRING = -2,
+	DMI_DEV_TYPE_DEVSLOT = -3,
 };
 
 struct dmi_header {
@@ -37,6 +38,14 @@ struct dmi_device {
 
 #ifdef CONFIG_DMI
 
+struct dmi_devslot {
+	struct dmi_device dev;
+	int id;
+	int seg;
+	int bus;
+	int devfn;
+};
+
 extern int dmi_check_system(const struct dmi_system_id *list);
 const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list);
 extern const char * dmi_get_system_info(int field);
-- 
1.6.5.2

With regards,
Narendra K

^ permalink raw reply related

* [PATCH 0/7] tcp: bugs and cleanup for 2.6.33
From: William Allen Simpson @ 2010-02-25 20:30 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton
  Cc: Linux Kernel Developers, Linux Kernel Network Developers,
	David Miller

I'd have thought that there would be greater interest about patching
crashing bugs, signed versus unsigned (underflow) bugs, TCP DoS bugs,
TCP data corruption, and TCP performance problems....

Combination of patches reported in October, November, December, January,
and February, for 2.6.32 and now 2.6.33.

This code has had previous review and several months of limited testing.

Some portions were removed during the various TCPCT part 1 patch splits,
then were cut off by the sudden unexpected end of that merge window.
[03 Dec 2009]  I've restarted the sub-numbering (again).

Of particular interest are the TCPCT header extensions that already
appear in the next phase of testing with other platforms.  These patches
allow correct reception without data corruption.

The remainder of the original TCPCT part 2 will be merged with part 3.

[Updated to 2010 Feb 24 2.6.33 release.]

^ permalink raw reply

* RE: [PATCH]: tipc: Fix oops on send prior to entering networked mode
From: Stephens, Allan @ 2010-02-25 20:33 UTC (permalink / raw)
  To: Neil Horman, David Miller; +Cc: netdev, jon.maloy, tipc-discussion
In-Reply-To: <20100225152328.GA2990@shamino.rdu.redhat.com>

> From: Neil Horman [mailto:nhorman@tuxdriver.com] 
> Sent: Thursday, February 25, 2010 10:23 AM

[text deleted]

> To me I see that and read it as:
> "We didn't have time to do things the way the Linux 
> maintainers like to have them done, so we went off and did it 
> on our own, figuring we'd get back to doing it the right way later"
> 
> Well, flash forward 1.5 years, and getting back to it never 
> happened.  While I understand that can happen, it puts users 
> in the lurch if they expect upstream to be the latest bits.  
> As such, have you considered just dropping TIPC from upstream 
> entirely?  I know that sounds a bit angry, I don't intend it 
> to, I mean it in all seriousness.  Companies have constraints 
> that sometimes conflict with upstream practices though, thats 
> just a fact of life, and theres nothing we can really do 
> about that.  But if the review/accptance criteria of upstream 
> development doesn't fit into a companies budget or schedule, 
> not doing kernel community development might be the best 
> solution.  Doing so tells the distros that they have extra 
> work to do if they want to incorporate/support tipc in their 
> kernels, and frees your company to develop on its own 
> schedule, and according to its own resources, while still 
> being accessable to end users.  Of course, in so doing you 
> don't get the maintenence changes that come with an ever 
> evolving ABI/etc, but thats the price you would have to pay, 
> and a decision you could make.
> 
> I'm not trying to tell you its the best solution, just an 
> alternate option.
> Honestly, what I'd like to see is all the remaining changes 
> in TIPC 1.7 go in as individual commits, so that we have a 
> good change history, and a resonable review on all the 
> changes.  I know that takes longer but I think its the right 
> solution.  I'll even volunteer to help, if that lightens your 
> load any.  If you can provide me access to whatever scm you 
> used (or even some modicum of changelog in a text file, so 
> that we could try to match up changes with documentation), 
> I'll happily start pulling stuff apart to get it upstream.

I can't argue with the basic thrust of your comments, Neil, nor with the
similar comments David has made in his previous emails.  The current
situation is certainly regrettable, and I think we're all in agreement
that the best solution is to get the remainder of TIPC 1.7 into Linux as
soon as possible (as individual patches, not a single mega-patch), then
to limit any future changes to the upstream side of things.

I've got no problem with Neil's offer to assist in getting the necessary
patches generated, as this will undoubtedly speed things along faster
than anything I could do on my own.  (I suggest that we get started on
this once we get the current oops situation resolved.)  This kind of
offer to share the burden is to be commended, and is an example that
other TIPC users should look to.


> But if thats a one shot deal, and you believe that the next 
> schedule crunch you have will result in your company making 
> another out-of-tree update, then perhaps switching to that 
> mode of out-of-tree development might be worth consideration.
> 
> Regards
> Neil

Actually, we've got no plans to continue doing out-of-tree development
on TIPC -- we've already suffered enough pain by following that route,
and I certainly don't want to repeat the experience!  The upside of
having done things out-of-tree in the past is that it gives us hard data
we can use to squelch discussion the next time somebody suggests doing
it again.

Regards,
Al
 

^ permalink raw reply

* Re: [PATCH 0/7] tcp: bugs and cleanup for 2.6.33
From: William Allen Simpson @ 2010-02-25 20:34 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton
  Cc: Linux Kernel Developers, Linux Kernel Network Developers,
	David Miller
In-Reply-To: <4B86DDCB.50608@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 359 bytes --]

Redefine two TCP header functions to accept TCP header pointer.
When subtracting, return signed int to allow error checking.

These functions will be used in subsequent patches that implement
additional features.

Signed-off-by: William.Allen.Simpson@gmail.com
---
  include/linux/tcp.h |   12 ++++++++++++
  1 files changed, 12 insertions(+), 0 deletions(-)

[-- Attachment #2: len_th+2a3+2.6.33.patch --]
[-- Type: text/plain, Size: 719 bytes --]

diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 7fee8a4..d0133cf 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -223,6 +223,18 @@ static inline unsigned int tcp_optlen(const struct sk_buff *skb)
 	return (tcp_hdr(skb)->doff - 5) * 4;
 }
 
+/* Length of fixed header plus standard options. */
+static inline unsigned int tcp_header_len_th(const struct tcphdr *th)
+{
+	return th->doff * 4;
+}
+
+/* Length of standard options only.  This could be negative. */
+static inline int tcp_option_len_th(const struct tcphdr *th)
+{
+	return (int)(th->doff * 4) - sizeof(*th);
+}
+
 /* This defines a selective acknowledgement block. */
 struct tcp_sack_block_wire {
 	__be32	start_seq;
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH v3 1/7] net: tcp_header_len_th and tcp_option_len_th
From: William Allen Simpson @ 2010-02-25 20:35 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton
  Cc: Linux Kernel Developers, Linux Kernel Network Developers,
	David Miller
In-Reply-To: <4B86DDCB.50608@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 361 bytes --]

Redefine two TCP header functions to accept TCP header pointer.
When subtracting, return signed int to allow error checking.

These functions will be used in subsequent patches that implement
additional features.

Signed-off-by: William.Allen.Simpson@gmail.com
---
  include/linux/tcp.h |   12 ++++++++++++
  1 files changed, 12 insertions(+), 0 deletions(-)



[-- Attachment #2: len_th+2a3+2.6.33.patch --]
[-- Type: text/plain, Size: 719 bytes --]

diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 7fee8a4..d0133cf 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -223,6 +223,18 @@ static inline unsigned int tcp_optlen(const struct sk_buff *skb)
 	return (tcp_hdr(skb)->doff - 5) * 4;
 }
 
+/* Length of fixed header plus standard options. */
+static inline unsigned int tcp_header_len_th(const struct tcphdr *th)
+{
+	return th->doff * 4;
+}
+
+/* Length of standard options only.  This could be negative. */
+static inline int tcp_option_len_th(const struct tcphdr *th)
+{
+	return (int)(th->doff * 4) - sizeof(*th);
+}
+
 /* This defines a selective acknowledgement block. */
 struct tcp_sack_block_wire {
 	__be32	start_seq;
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH v3 2/7] net: remove old tcp_optlen function
From: William Allen Simpson @ 2010-02-25 20:39 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton
  Cc: Linux Kernel Developers, Linux Kernel Network Developers,
	David Miller, Michael Chan
In-Reply-To: <4B86DDCB.50608@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1070 bytes --]

The tcp_optlen() function returns a potential *negative* unsigned.

In the only two existing files using the old tcp_optlen() function,
clean up confusing and inconsistent mixing of both byte and word
offsets, and other coding style issues.  Document assumptions.

Quoth David Miller:
    This is transmit, and the packets can only come from the Linux
    TCP stack, not some external entity.

    You're being way too anal here, and adding these checks to
    drivers would be just a lot of rediculious bloat. [sic]

Therefore, there are *no* checks for bad TCP and IP header sizes, nor
any semantic changes.  The drivers should function exactly as existing.

No response from testers in 19+ weeks.

Requires:
   net: tcp_header_len_th and tcp_option_len_th

Signed-off-by: William.Allen.Simpson@gmail.com
CC: Michael Chan <mchan@broadcom.com>
---
  drivers/net/bnx2.c  |   29 +++++++++++++-----------
  drivers/net/tg3.c   |   60 +++++++++++++++++++++++---------------------------
  include/linux/tcp.h |    5 ----
  3 files changed, 44 insertions(+), 50 deletions(-)

[-- Attachment #2: len_th+2b3+2.6.33.patch --]
[-- Type: text/plain, Size: 6936 bytes --]

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 65df1de..45452c5 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -6352,6 +6352,8 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
 /* Called with netif_tx_lock.
  * bnx2_tx_int() runs without netif_tx_lock unless it needs to call
  * netif_wake_queue().
+ *
+ * No TCP or IP length checking, per David Miller (see commit log).
  */
 static netdev_tx_t
 bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -6396,19 +6398,19 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 			(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
 	}
 #endif
-	if ((mss = skb_shinfo(skb)->gso_size)) {
-		u32 tcp_opt_len;
-		struct iphdr *iph;
+	mss = skb_shinfo(skb)->gso_size;
+	if (mss != 0) {
+		struct tcphdr *th = tcp_hdr(skb);
+		int tcp_opt_words = th->doff - (sizeof(*th) >> 2);
+		/* assumes positive tcp_opt_words without checking */
 
 		vlan_tag_flags |= TX_BD_FLAGS_SW_LSO;
 
-		tcp_opt_len = tcp_optlen(skb);
-
 		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
 			u32 tcp_off = skb_transport_offset(skb) -
 				      sizeof(struct ipv6hdr) - ETH_HLEN;
 
-			vlan_tag_flags |= ((tcp_opt_len >> 2) << 8) |
+			vlan_tag_flags |= (tcp_opt_words << 8) |
 					  TX_BD_FLAGS_SW_FLAGS;
 			if (likely(tcp_off == 0))
 				vlan_tag_flags &= ~TX_BD_FLAGS_TCP6_OFF0_MSK;
@@ -6421,14 +6423,15 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 				mss |= (tcp_off & 0xc) << TX_BD_TCP6_OFF2_SHL;
 			}
 		} else {
-			iph = ip_hdr(skb);
-			if (tcp_opt_len || (iph->ihl > 5)) {
-				vlan_tag_flags |= ((iph->ihl - 5) +
-						   (tcp_opt_len >> 2)) << 8;
-			}
+			struct iphdr *iph = ip_hdr(skb);
+			int ip_opt_words = iph->ihl - (sizeof(*iph) >> 2);
+			/* assumes positive ip_opt_words without checking */
+			int opt_words = ip_opt_words + tcp_opt_words;
+
+			if (opt_words > 0)
+				vlan_tag_flags |= opt_words << 8;
 		}
-	} else
-		mss = 0;
+	}
 
 	mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
 	if (pci_dma_mapping_error(bp->pdev, mapping)) {
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 7f82b02..c20c800 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -5426,6 +5426,8 @@ static void tg3_set_txd(struct tg3_napi *tnapi, int entry,
 
 /* hard_start_xmit for devices that don't have any bugs and
  * support TG3_FLG2_HW_TSO_2 and TG3_FLG2_HW_TSO_3 only.
+ *
+ * No TCP or IP length checking, per David Miller (see commit log).
  */
 static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 				  struct net_device *dev)
@@ -5461,9 +5463,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 
 	entry = tnapi->tx_prod;
 	base_flags = 0;
-	mss = 0;
-	if ((mss = skb_shinfo(skb)->gso_size) != 0) {
-		int tcp_opt_len, ip_tcp_len;
+	mss = skb_shinfo(skb)->gso_size;
+	if (mss != 0) {
+		struct tcphdr *th;
 		u32 hdrlen;
 
 		if (skb_header_cloned(skb) &&
@@ -5471,18 +5473,16 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 			dev_kfree_skb(skb);
 			goto out_unlock;
 		}
+		th = tcp_hdr(skb);
 
 		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
 			hdrlen = skb_headlen(skb) - ETH_HLEN;
 		else {
 			struct iphdr *iph = ip_hdr(skb);
 
-			tcp_opt_len = tcp_optlen(skb);
-			ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
-
+			hdrlen = ip_hdrlen(skb) + tcp_header_len_th(th);
+			iph->tot_len = htons(mss + hdrlen);
 			iph->check = 0;
-			iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
-			hdrlen = ip_tcp_len + tcp_opt_len;
 		}
 
 		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) {
@@ -5496,7 +5496,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 		base_flags |= (TXD_FLAG_CPU_PRE_DMA |
 			       TXD_FLAG_CPU_POST_DMA);
 
-		tcp_hdr(skb)->check = 0;
+		th->check = 0;
 
 	}
 	else if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -5629,6 +5629,8 @@ tg3_tso_bug_end:
 
 /* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and
  * support TG3_FLG2_HW_TSO_1 or firmware TSO only.
+ *
+ * No TCP or IP length checking, per David Miller (see commit log).
  */
 static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
 					  struct net_device *dev)
@@ -5668,20 +5670,21 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
 		base_flags |= TXD_FLAG_TCPUDP_CSUM;
 
-	if ((mss = skb_shinfo(skb)->gso_size) != 0) {
+	mss = skb_shinfo(skb)->gso_size;
+	if (mss != 0) {
 		struct iphdr *iph;
-		u32 tcp_opt_len, ip_tcp_len, hdr_len;
+		struct tcphdr *th;
+		u32 hdr_len;
+		int opt_bytes;
 
 		if (skb_header_cloned(skb) &&
 		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
 			dev_kfree_skb(skb);
 			goto out_unlock;
 		}
+		th = tcp_hdr(skb);
+		hdr_len = ip_hdrlen(skb) + tcp_header_len_th(th);
 
-		tcp_opt_len = tcp_optlen(skb);
-		ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
-
-		hdr_len = ip_tcp_len + tcp_opt_len;
 		if (unlikely((ETH_HLEN + hdr_len) > 80) &&
 			     (tp->tg3_flags2 & TG3_FLG2_TSO_BUG))
 			return (tg3_tso_bug(tp, skb));
@@ -5693,13 +5696,14 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
 		iph->check = 0;
 		iph->tot_len = htons(mss + hdr_len);
 		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
-			tcp_hdr(skb)->check = 0;
+			th->check = 0;
 			base_flags &= ~TXD_FLAG_TCPUDP_CSUM;
 		} else
-			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
-								 iph->daddr, 0,
-								 IPPROTO_TCP,
-								 0);
+			th->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+						       0, IPPROTO_TCP, 0);
+
+		opt_bytes = hdr_len - sizeof(*iph) - sizeof(*th);
+		/* assumes positive opt_bytes without checking */
 
 		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) {
 			mss |= (hdr_len & 0xc) << 12;
@@ -5710,19 +5714,11 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
 			mss |= hdr_len << 9;
 		else if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1) ||
 			 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
-			if (tcp_opt_len || iph->ihl > 5) {
-				int tsflags;
-
-				tsflags = (iph->ihl - 5) + (tcp_opt_len >> 2);
-				mss |= (tsflags << 11);
-			}
+			if (opt_bytes > 0)
+				mss |= opt_bytes << (11 - 2);
 		} else {
-			if (tcp_opt_len || iph->ihl > 5) {
-				int tsflags;
-
-				tsflags = (iph->ihl - 5) + (tcp_opt_len >> 2);
-				base_flags |= tsflags << 12;
-			}
+			if (opt_bytes > 0)
+				base_flags |= opt_bytes << (12 - 2);
 		}
 	}
 #if TG3_VLAN_TAG_USED
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index d0133cf..74728f7 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -218,11 +218,6 @@ static inline unsigned int tcp_hdrlen(const struct sk_buff *skb)
 	return tcp_hdr(skb)->doff * 4;
 }
 
-static inline unsigned int tcp_optlen(const struct sk_buff *skb)
-{
-	return (tcp_hdr(skb)->doff - 5) * 4;
-}
-
 /* Length of fixed header plus standard options. */
 static inline unsigned int tcp_header_len_th(const struct tcphdr *th)
 {
-- 
1.6.3.3


^ permalink raw reply related

* Re: [PATCH 0/7] tcp: bugs and cleanup for 2.6.33
From: Ben Hutchings @ 2010-02-25 20:43 UTC (permalink / raw)
  To: William Allen Simpson
  Cc: Linus Torvalds, Andrew Morton, Linux Kernel Developers,
	Linux Kernel Network Developers, David Miller
In-Reply-To: <4B86DEC6.1090307@gmail.com>

On Thu, 2010-02-25 at 15:34 -0500, William Allen Simpson wrote:
> Redefine two TCP header functions to accept TCP header pointer.
> When subtracting, return signed int to allow error checking.

This patch only adds functions, so why do you say 'redefine'?

> These functions will be used in subsequent patches that implement
> additional features.
[...]
> +/* Length of standard options only.  This could be negative. */
> +static inline int tcp_option_len_th(const struct tcphdr *th)
> +{
> +       return (int)(th->doff * 4) - sizeof(*th);
> +}

I don't see  the point of this cast; the left operand of the subtraction
will in any case be promoted to size_t to match the right operand.

Did you mean
	return (int)(th->doff * 4 - sizeof(*th));
?

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox