Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 5/9] cnic: Support NIC Partition mode
From: Michael Chan @ 2010-12-23 17:43 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1293126184-13097-5-git-send-email-mchan@broadcom.com>

Add a common function cnic_read_bnx2x_iscsi_mac() to read the iSCSI
MAC address at any specified shared memory location.  In NIC Partition
mode, we need to get the MAC address from the MF_CFG area of shared
memory.

Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/cnic.c |   84 ++++++++++++++++++++++++++++++++++++++++-----------
 drivers/net/cnic.h |    3 ++
 2 files changed, 69 insertions(+), 18 deletions(-)

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 9bd133d..bf4a804 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -4247,10 +4247,36 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
 	cp->rx_cons = *cp->rx_cons_ptr;
 }
 
+static int cnic_read_bnx2x_iscsi_mac(struct cnic_dev *dev, u32 upper_addr,
+				     u32 lower_addr)
+{
+	u32 val;
+	u8 mac[6];
+
+	val = CNIC_RD(dev, upper_addr);
+
+	mac[0] = (u8) (val >> 8);
+	mac[1] = (u8) val;
+
+	val = CNIC_RD(dev, lower_addr);
+
+	mac[2] = (u8) (val >> 24);
+	mac[3] = (u8) (val >> 16);
+	mac[4] = (u8) (val >> 8);
+	mac[5] = (u8) val;
+
+	if (is_valid_ether_addr(mac)) {
+		memcpy(dev->mac_addr, mac, 6);
+		return 0;
+	} else {
+		return -EINVAL;
+	}
+}
+
 static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	u32 base, base2, addr, val;
+	u32 base, base2, addr, addr1, val;
 	int port = CNIC_PORT(cp);
 
 	dev->max_iscsi_conn = 0;
@@ -4263,20 +4289,10 @@ static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
 	addr = BNX2X_SHMEM_ADDR(base,
 		dev_info.port_hw_config[port].iscsi_mac_upper);
 
-	val = CNIC_RD(dev, addr);
-
-	dev->mac_addr[0] = (u8) (val >> 8);
-	dev->mac_addr[1] = (u8) val;
-
-	addr = BNX2X_SHMEM_ADDR(base,
+	addr1 = BNX2X_SHMEM_ADDR(base,
 		dev_info.port_hw_config[port].iscsi_mac_lower);
 
-	val = CNIC_RD(dev, addr);
-
-	dev->mac_addr[2] = (u8) (val >> 24);
-	dev->mac_addr[3] = (u8) (val >> 16);
-	dev->mac_addr[4] = (u8) (val >> 8);
-	dev->mac_addr[5] = (u8) val;
+	cnic_read_bnx2x_iscsi_mac(dev, addr, addr1);
 
 	addr = BNX2X_SHMEM_ADDR(base, validity_map[port]);
 	val = CNIC_RD(dev, addr);
@@ -4302,21 +4318,53 @@ static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
 		else
 			mf_cfg_addr = base + BNX2X_SHMEM_MF_BLK_OFFSET;
 
-		addr = mf_cfg_addr +
-			offsetof(struct mf_cfg, func_mf_config[func].e1hov_tag);
+		if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+			/* Must determine if the MF is SD vs SI mode */
+			addr = BNX2X_SHMEM_ADDR(base,
+					dev_info.shared_feature_config.config);
+			val = CNIC_RD(dev, addr);
+			if ((val & SHARED_FEAT_CFG_FORCE_SF_MODE_MASK) ==
+			    SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT) {
+				int rc;
+
+				/* MULTI_FUNCTION_SI mode */
+				addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+					func_ext_config[func].func_cfg);
+				val = CNIC_RD(dev, addr);
+				if (!(val & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD))
+					dev->max_iscsi_conn = 0;
+
+				addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+					func_ext_config[func].
+					iscsi_mac_addr_upper);
+				addr1 = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+					func_ext_config[func].
+					iscsi_mac_addr_lower);
+				rc = cnic_read_bnx2x_iscsi_mac(dev, addr,
+								addr1);
+				if (rc && func > 1)
+					dev->max_iscsi_conn = 0;
+
+				return;
+			}
+		}
+
+		addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+			func_mf_config[func].e1hov_tag);
 
 		val = CNIC_RD(dev, addr);
 		val &= FUNC_MF_CFG_E1HOV_TAG_MASK;
 		if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
-			addr = mf_cfg_addr +
-				offsetof(struct mf_cfg,
-					 func_mf_config[func].config);
+			addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+				func_mf_config[func].config);
 			val = CNIC_RD(dev, addr);
 			val &= FUNC_MF_CFG_PROTOCOL_MASK;
 			if (val != FUNC_MF_CFG_PROTOCOL_ISCSI)
 				dev->max_iscsi_conn = 0;
 		}
 	}
+	if (!is_valid_ether_addr(dev->mac_addr))
+		dev->max_iscsi_conn = 0;
 }
 
 static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h
index 8e947b7..fb3b753 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/cnic.h
@@ -422,6 +422,9 @@ struct bnx2x_bd_chain_next {
 		 (CNIC_RD(dev, BNX2X_SHMEM2_ADDR(base, size)) >	\
 		  offsetof(struct shmem2_region, field)))
 
+#define BNX2X_MF_CFG_ADDR(base, field)				\
+			((base) + offsetof(struct mf_cfg, field))
+
 #define CNIC_PORT(cp)			((cp)->pfid & 1)
 #define CNIC_FUNC(cp)			((cp)->func)
 #define CNIC_PATH(cp)			(!BNX2X_CHIP_IS_E2(cp->chip_id) ? 0 :\
-- 
1.6.4.GIT



^ permalink raw reply related

* [PATCH net-next 2/9] cnic: Prevent "scheduling while atomic" when calling ->cnic_init()
From: Michael Chan @ 2010-12-23 17:42 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1293126184-13097-2-git-send-email-mchan@broadcom.com>

cnic_dev_list is protected by rtnl_lock and cnic_dev_lock spin_lock during
modifications.  When looping on cnic_dev_list and calling ->cnic_init(),
we should just hold rtnl_lock since ->cnic_init() may sleep.

Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/cnic.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 9c2e786..3a7d3ce 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -59,6 +59,7 @@ MODULE_DESCRIPTION("Broadcom NetXtreme II CNIC Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(CNIC_MODULE_VERSION);
 
+/* cnic_dev_list modifications are protected by both rtnl and cnic_dev_lock */
 static LIST_HEAD(cnic_dev_list);
 static LIST_HEAD(cnic_udev_list);
 static DEFINE_RWLOCK(cnic_dev_lock);
@@ -445,14 +446,12 @@ int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops)
 
 	/* Prevent race conditions with netdev_event */
 	rtnl_lock();
-	read_lock(&cnic_dev_lock);
 	list_for_each_entry(dev, &cnic_dev_list, list) {
 		struct cnic_local *cp = dev->cnic_priv;
 
 		if (!test_and_set_bit(ULP_F_INIT, &cp->ulp_flags[ulp_type]))
 			ulp_ops->cnic_init(dev);
 	}
-	read_unlock(&cnic_dev_lock);
 	rtnl_unlock();
 
 	return 0;
-- 
1.6.4.GIT



^ permalink raw reply related

* [PATCH net-next 4/9] cnic: Use proper client and connection IDs on iSCSI ring
From: Michael Chan @ 2010-12-23 17:42 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1293126184-13097-4-git-send-email-mchan@broadcom.com>

Use the IDs specified by the bnx2x driver when initializing the ring.
We don't have to make code changes when these IDs change in the future.

Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/cnic.c |   21 ++++++++++++---------
 drivers/net/cnic.h |    5 -----
 2 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 9f80fb4..9bd133d 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -4119,7 +4119,7 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
 	struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
 	int port = CNIC_PORT(cp);
 	int i;
-	int cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
+	u32 cli = cp->ethdev->iscsi_l2_client_id;
 	u32 val;
 
 	memset(txbd, 0, BCM_PAGE_SIZE);
@@ -4180,7 +4180,7 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
 	struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
 	int i;
 	int port = CNIC_PORT(cp);
-	int cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
+	u32 cli = cp->ethdev->iscsi_l2_client_id;
 	int cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
 	u32 val;
 	dma_addr_t ring_map = udev->l2_ring_map;
@@ -4244,6 +4244,7 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
 
 	cp->rx_cons_ptr =
 		&sb->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS];
+	cp->rx_cons = *cp->rx_cons_ptr;
 }
 
 static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
@@ -4437,7 +4438,8 @@ static void cnic_init_rings(struct cnic_dev *dev)
 		cnic_init_bnx2_rx_ring(dev);
 		set_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
 	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
-		u32 cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
+		u32 cli = cp->ethdev->iscsi_l2_client_id;
+		u32 cid = cp->ethdev->iscsi_l2_cid;
 		u32 cl_qzone_id, type;
 		struct client_init_ramrod_data *data;
 		union l5cm_specific_data l5_data;
@@ -4478,7 +4480,7 @@ static void cnic_init_rings(struct cnic_dev *dev)
 		set_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
 
 		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CLIENT_SETUP,
-			BNX2X_ISCSI_L2_CID, type, &l5_data);
+			cid, type, &l5_data);
 
 		i = 0;
 		while (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags) &&
@@ -4489,7 +4491,7 @@ static void cnic_init_rings(struct cnic_dev *dev)
 			netdev_err(dev->netdev,
 				"iSCSI CLIENT_SETUP did not complete\n");
 		cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);
-		cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 1);
+		cnic_ring_ctl(dev, cid, cli, 1);
 	}
 }
 
@@ -4504,19 +4506,20 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
 		cnic_shutdown_bnx2_rx_ring(dev);
 	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
 		struct cnic_local *cp = dev->cnic_priv;
-		u32 cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
+		u32 cli = cp->ethdev->iscsi_l2_client_id;
+		u32 cid = cp->ethdev->iscsi_l2_cid;
 		union l5cm_specific_data l5_data;
 		int i;
 		u32 type;
 
-		cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 0);
+		cnic_ring_ctl(dev, cid, cli, 0);
 
 		set_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags);
 
 		l5_data.phy_address.lo = cli;
 		l5_data.phy_address.hi = 0;
 		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_HALT,
-			BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE, &l5_data);
+			cid, ETH_CONNECTION_TYPE, &l5_data);
 		i = 0;
 		while (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags) &&
 		       ++i < 10)
@@ -4533,7 +4536,7 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
 		type |= ((cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
 			 SPE_HDR_FUNCTION_ID);
 		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,
-			BNX2X_ISCSI_L2_CID, type, &l5_data);
+			cid, type, &l5_data);
 		msleep(10);
 	}
 	clear_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h
index bf38e57..8e947b7 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/cnic.h
@@ -356,11 +356,6 @@ struct bnx2x_bd_chain_next {
 #define BNX2X_CONTEXT_MEM_SIZE		1024
 #define BNX2X_FCOE_CID			16
 
-/* iSCSI client IDs are 17, 19, 21, 23 */
-#define BNX2X_ISCSI_BASE_CL_ID		17
-#define BNX2X_ISCSI_CL_ID(vn)		(BNX2X_ISCSI_BASE_CL_ID + ((vn) << 1))
-
-#define BNX2X_ISCSI_L2_CID		17
 #define BNX2X_ISCSI_START_CID		18
 #define BNX2X_ISCSI_NUM_CONNECTIONS	128
 #define BNX2X_ISCSI_TASK_CONTEXT_SIZE	128
-- 
1.6.4.GIT



^ permalink raw reply related

* [PATCH net-next 5/9] cnic: Support NIC Partition mode
From: Michael Chan @ 2010-12-23 17:43 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1293126184-13097-6-git-send-email-mchan@broadcom.com>

Add a common function cnic_read_bnx2x_iscsi_mac() to read the iSCSI
MAC address at any specified shared memory location.  In NIC Partition
mode, we need to get the MAC address from the MF_CFG area of shared
memory.

Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/cnic.c |   84 ++++++++++++++++++++++++++++++++++++++++-----------
 drivers/net/cnic.h |    3 ++
 2 files changed, 69 insertions(+), 18 deletions(-)

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 9bd133d..bf4a804 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -4247,10 +4247,36 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
 	cp->rx_cons = *cp->rx_cons_ptr;
 }
 
+static int cnic_read_bnx2x_iscsi_mac(struct cnic_dev *dev, u32 upper_addr,
+				     u32 lower_addr)
+{
+	u32 val;
+	u8 mac[6];
+
+	val = CNIC_RD(dev, upper_addr);
+
+	mac[0] = (u8) (val >> 8);
+	mac[1] = (u8) val;
+
+	val = CNIC_RD(dev, lower_addr);
+
+	mac[2] = (u8) (val >> 24);
+	mac[3] = (u8) (val >> 16);
+	mac[4] = (u8) (val >> 8);
+	mac[5] = (u8) val;
+
+	if (is_valid_ether_addr(mac)) {
+		memcpy(dev->mac_addr, mac, 6);
+		return 0;
+	} else {
+		return -EINVAL;
+	}
+}
+
 static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	u32 base, base2, addr, val;
+	u32 base, base2, addr, addr1, val;
 	int port = CNIC_PORT(cp);
 
 	dev->max_iscsi_conn = 0;
@@ -4263,20 +4289,10 @@ static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
 	addr = BNX2X_SHMEM_ADDR(base,
 		dev_info.port_hw_config[port].iscsi_mac_upper);
 
-	val = CNIC_RD(dev, addr);
-
-	dev->mac_addr[0] = (u8) (val >> 8);
-	dev->mac_addr[1] = (u8) val;
-
-	addr = BNX2X_SHMEM_ADDR(base,
+	addr1 = BNX2X_SHMEM_ADDR(base,
 		dev_info.port_hw_config[port].iscsi_mac_lower);
 
-	val = CNIC_RD(dev, addr);
-
-	dev->mac_addr[2] = (u8) (val >> 24);
-	dev->mac_addr[3] = (u8) (val >> 16);
-	dev->mac_addr[4] = (u8) (val >> 8);
-	dev->mac_addr[5] = (u8) val;
+	cnic_read_bnx2x_iscsi_mac(dev, addr, addr1);
 
 	addr = BNX2X_SHMEM_ADDR(base, validity_map[port]);
 	val = CNIC_RD(dev, addr);
@@ -4302,21 +4318,53 @@ static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
 		else
 			mf_cfg_addr = base + BNX2X_SHMEM_MF_BLK_OFFSET;
 
-		addr = mf_cfg_addr +
-			offsetof(struct mf_cfg, func_mf_config[func].e1hov_tag);
+		if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+			/* Must determine if the MF is SD vs SI mode */
+			addr = BNX2X_SHMEM_ADDR(base,
+					dev_info.shared_feature_config.config);
+			val = CNIC_RD(dev, addr);
+			if ((val & SHARED_FEAT_CFG_FORCE_SF_MODE_MASK) ==
+			    SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT) {
+				int rc;
+
+				/* MULTI_FUNCTION_SI mode */
+				addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+					func_ext_config[func].func_cfg);
+				val = CNIC_RD(dev, addr);
+				if (!(val & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD))
+					dev->max_iscsi_conn = 0;
+
+				addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+					func_ext_config[func].
+					iscsi_mac_addr_upper);
+				addr1 = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+					func_ext_config[func].
+					iscsi_mac_addr_lower);
+				rc = cnic_read_bnx2x_iscsi_mac(dev, addr,
+								addr1);
+				if (rc && func > 1)
+					dev->max_iscsi_conn = 0;
+
+				return;
+			}
+		}
+
+		addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+			func_mf_config[func].e1hov_tag);
 
 		val = CNIC_RD(dev, addr);
 		val &= FUNC_MF_CFG_E1HOV_TAG_MASK;
 		if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
-			addr = mf_cfg_addr +
-				offsetof(struct mf_cfg,
-					 func_mf_config[func].config);
+			addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+				func_mf_config[func].config);
 			val = CNIC_RD(dev, addr);
 			val &= FUNC_MF_CFG_PROTOCOL_MASK;
 			if (val != FUNC_MF_CFG_PROTOCOL_ISCSI)
 				dev->max_iscsi_conn = 0;
 		}
 	}
+	if (!is_valid_ether_addr(dev->mac_addr))
+		dev->max_iscsi_conn = 0;
 }
 
 static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h
index 8e947b7..fb3b753 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/cnic.h
@@ -422,6 +422,9 @@ struct bnx2x_bd_chain_next {
 		 (CNIC_RD(dev, BNX2X_SHMEM2_ADDR(base, size)) >	\
 		  offsetof(struct shmem2_region, field)))
 
+#define BNX2X_MF_CFG_ADDR(base, field)				\
+			((base) + offsetof(struct mf_cfg, field))
+
 #define CNIC_PORT(cp)			((cp)->pfid & 1)
 #define CNIC_FUNC(cp)			((cp)->func)
 #define CNIC_PATH(cp)			(!BNX2X_CHIP_IS_E2(cp->chip_id) ? 0 :\
-- 
1.6.4.GIT



^ permalink raw reply related

* [PATCH net-next 3/9] cnic: Improve ->iscsi_nl_msg_send()
From: Michael Chan @ 2010-12-23 17:42 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1293126184-13097-3-git-send-email-mchan@broadcom.com>

1. Change first parameter from cnic_dev to ulp_handle which is the hba
pointer.  All other similar upcalls are using hba pointer.  The callee
can then directly reference the hba without conversion.

2. Change return value from void to int so that an error code can be
passed back.  This allows the operation to be retried.

Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/cnic.c             |   21 ++++++++++++++++-----
 drivers/net/cnic_if.h          |    2 +-
 drivers/scsi/bnx2i/bnx2i_hwi.c |   14 ++++++++------
 3 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 3a7d3ce..9f80fb4 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -279,6 +279,7 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type,
 	u32 msg_type = ISCSI_KEVENT_IF_DOWN;
 	struct cnic_ulp_ops *ulp_ops;
 	struct cnic_uio_dev *udev = cp->udev;
+	int rc = 0, retry = 0;
 
 	if (!udev || udev->uio_dev == -1)
 		return -ENODEV;
@@ -303,11 +304,21 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type,
 		path_req.pmtu = csk->mtu;
 	}
 
-	rcu_read_lock();
-	ulp_ops = rcu_dereference(cnic_ulp_tbl[CNIC_ULP_ISCSI]);
-	if (ulp_ops)
-		ulp_ops->iscsi_nl_send_msg(cp->dev, msg_type, buf, len);
-	rcu_read_unlock();
+	while (retry < 3) {
+		rc = 0;
+		rcu_read_lock();
+		ulp_ops = rcu_dereference(cnic_ulp_tbl[CNIC_ULP_ISCSI]);
+		if (ulp_ops)
+			rc = ulp_ops->iscsi_nl_send_msg(
+				cp->ulp_handle[CNIC_ULP_ISCSI],
+				msg_type, buf, len);
+		rcu_read_unlock();
+		if (rc == 0 || msg_type != ISCSI_KEVENT_PATH_REQ)
+			break;
+
+		msleep(100);
+		retry++;
+	}
 	return 0;
 }
 
diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h
index 0dbeaec..33333e7 100644
--- a/drivers/net/cnic_if.h
+++ b/drivers/net/cnic_if.h
@@ -301,7 +301,7 @@ struct cnic_ulp_ops {
 	void (*cm_abort_complete)(struct cnic_sock *);
 	void (*cm_remote_close)(struct cnic_sock *);
 	void (*cm_remote_abort)(struct cnic_sock *);
-	void (*iscsi_nl_send_msg)(struct cnic_dev *dev, u32 msg_type,
+	int (*iscsi_nl_send_msg)(void *ulp_ctx, u32 msg_type,
 				  char *data, u16 data_size);
 	struct module *owner;
 	atomic_t ref_count;
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 8d9dbb3..2f9622e 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -2346,19 +2346,21 @@ static void bnx2i_cm_remote_abort(struct cnic_sock *cm_sk)
 }
 
 
-static void bnx2i_send_nl_mesg(struct cnic_dev *dev, u32 msg_type,
+static int bnx2i_send_nl_mesg(void *context, u32 msg_type,
 			       char *buf, u16 buflen)
 {
-	struct bnx2i_hba *hba;
+	struct bnx2i_hba *hba = context;
+	int rc;
 
-	hba = bnx2i_find_hba_for_cnic(dev);
 	if (!hba)
-		return;
+		return -ENODEV;
 
-	if (iscsi_offload_mesg(hba->shost, &bnx2i_iscsi_transport,
-				   msg_type, buf, buflen))
+	rc = iscsi_offload_mesg(hba->shost, &bnx2i_iscsi_transport,
+				msg_type, buf, buflen);
+	if (rc)
 		printk(KERN_ALERT "bnx2i: private nl message send error\n");
 
+	return rc;
 }
 
 
-- 
1.6.4.GIT



^ permalink raw reply related

* [PATCH net-next 1/9] cnic: Fix iSCSI TCP port endian order.
From: Michael Chan @ 2010-12-23 17:42 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1293126184-13097-1-git-send-email-mchan@broadcom.com>

Pass the TCP port parameter for iSCSI connections to the firmware in
proper endian order.

Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/cnic.c |   23 +++++++++++++----------
 drivers/net/cnic.h |    2 +-
 2 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 594ca9c..9c2e786 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -2883,7 +2883,7 @@ static void cnic_cm_cleanup(struct cnic_sock *csk)
 		struct cnic_dev *dev = csk->dev;
 		struct cnic_local *cp = dev->cnic_priv;
 
-		cnic_free_id(&cp->csk_port_tbl, csk->src_port);
+		cnic_free_id(&cp->csk_port_tbl, be16_to_cpu(csk->src_port));
 		csk->src_port = 0;
 	}
 }
@@ -3014,7 +3014,8 @@ static int cnic_get_route(struct cnic_sock *csk, struct cnic_sockaddr *saddr)
 	int is_v6, rc = 0;
 	struct dst_entry *dst = NULL;
 	struct net_device *realdev;
-	u32 local_port;
+	__be16 local_port;
+	u32 port_id;
 
 	if (saddr->local.v6.sin6_family == AF_INET6 &&
 	    saddr->remote.v6.sin6_family == AF_INET6)
@@ -3054,19 +3055,21 @@ static int cnic_get_route(struct cnic_sock *csk, struct cnic_sockaddr *saddr)
 		}
 	}
 
-	if (local_port >= CNIC_LOCAL_PORT_MIN &&
-	    local_port < CNIC_LOCAL_PORT_MAX) {
-		if (cnic_alloc_id(&cp->csk_port_tbl, local_port))
-			local_port = 0;
+	port_id = be16_to_cpu(local_port);
+	if (port_id >= CNIC_LOCAL_PORT_MIN &&
+	    port_id < CNIC_LOCAL_PORT_MAX) {
+		if (cnic_alloc_id(&cp->csk_port_tbl, port_id))
+			port_id = 0;
 	} else
-		local_port = 0;
+		port_id = 0;
 
-	if (!local_port) {
-		local_port = cnic_alloc_new_id(&cp->csk_port_tbl);
-		if (local_port == -1) {
+	if (!port_id) {
+		port_id = cnic_alloc_new_id(&cp->csk_port_tbl);
+		if (port_id == -1) {
 			rc = -ENOMEM;
 			goto err_out;
 		}
+		local_port = cpu_to_be16(port_id);
 	}
 	csk->src_port = local_port;
 
diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h
index 6a4a0ae..bf38e57 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/cnic.h
@@ -82,7 +82,7 @@ struct cnic_redirect_entry {
 #define MAX_ISCSI_TBL_SZ	256
 
 #define CNIC_LOCAL_PORT_MIN	60000
-#define CNIC_LOCAL_PORT_MAX	61000
+#define CNIC_LOCAL_PORT_MAX	61024
 #define CNIC_LOCAL_PORT_RANGE	(CNIC_LOCAL_PORT_MAX - CNIC_LOCAL_PORT_MIN)
 
 #define KWQE_CNT (BCM_PAGE_SIZE / sizeof(struct kwqe))
-- 
1.6.4.GIT



^ permalink raw reply related

* [PATCH net-next 7/9] cnic: Call cm_connect_complete() immediately on error
From: Michael Chan @ 2010-12-23 17:43 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1293126184-13097-7-git-send-email-mchan@broadcom.com>

From: Eddie Wai <waie@broadcom.com>

If we get a path_resp error from userspace, call cm_connect_complete()
immediately with error so that bnx2i can react to the error faster.

Signed-off-by: Eddie Wai <waie@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/cnic.c |   16 ++++++++++++++--
 1 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 1240dea..36c1578 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -322,6 +322,8 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type,
 	return 0;
 }
 
+static void cnic_cm_upcall(struct cnic_local *, struct cnic_sock *, u8);
+
 static int cnic_iscsi_nl_msg_recv(struct cnic_dev *dev, u32 msg_type,
 				  char *buf, u16 len)
 {
@@ -351,7 +353,9 @@ static int cnic_iscsi_nl_msg_recv(struct cnic_dev *dev, u32 msg_type,
 		}
 		csk = &cp->csk_tbl[l5_cid];
 		csk_hold(csk);
-		if (cnic_in_use(csk)) {
+		if (cnic_in_use(csk) &&
+		    test_bit(SK_F_CONNECT_START, &csk->flags)) {
+
 			memcpy(csk->ha, path_resp->mac_addr, 6);
 			if (test_bit(SK_F_IPV6, &csk->flags))
 				memcpy(&csk->src_ip[0], &path_resp->src.v6_addr,
@@ -359,8 +363,16 @@ static int cnic_iscsi_nl_msg_recv(struct cnic_dev *dev, u32 msg_type,
 			else
 				memcpy(&csk->src_ip[0], &path_resp->src.v4_addr,
 				       sizeof(struct in_addr));
-			if (is_valid_ether_addr(csk->ha))
+
+			if (is_valid_ether_addr(csk->ha)) {
 				cnic_cm_set_pg(csk);
+			} else if (!test_bit(SK_F_OFFLD_SCHED, &csk->flags) &&
+				!test_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) {
+
+				cnic_cm_upcall(cp, csk,
+					L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE);
+				clear_bit(SK_F_CONNECT_START, &csk->flags);
+			}
 		}
 		csk_put(csk);
 		rcu_read_unlock();
-- 
1.6.4.GIT



^ permalink raw reply related

* [PATCH net-next 0/9] cnic: Bug fixes and FCoE support
From: Michael Chan @ 2010-12-23 17:42 UTC (permalink / raw)
  To: davem; +Cc: netdev


David, bug fixes and FCoE enablement patches for net-next.
Please review.  Thanks.


^ permalink raw reply

* Re: [PATCH 1/4] net: phy: balance disable/enable irq on change
From: David Miller @ 2010-12-23 19:24 UTC (permalink / raw)
  To: jhautbois
  Cc: richard.cochran, shemminger, tj, randy.dunlap, netdev,
	linux-kernel
In-Reply-To: <1292756331-3735-1-git-send-email-jhautbois@gmail.com>

From: Jean-Michel Hautbois <jhautbois@gmail.com>
Date: Sun, 19 Dec 2010 11:58:48 +0100

> When phy interface changes its status, it calls phy_change() function.
> This function calls the interrupt disabling functions for the driver
> registered, but if this driver doesn't implement it, there is no IRQ
> disabling. After doing the work, we call enable_irq and not the
> respective driver function. This fixes it, as it could lead to an
> unbalanced IRQ. Error code changed to EOPNOTSUPP.
> 
> Signed-off-by: Jean-Michel Hautbois <jhautbois@gmail.com>

This is completely bogus.

First of all, there are 5 call sites for phy_change_interrupt() but
you've only implemented the new semantics for two of those.

Therefore, if we even wanted this, we should implement the behavior in
phy_change_interrupt() itself instead of duplicating the logic at
each and every call site.

But we don't want this.

It's not appropriate at all.  If a device lacks a way to turn
interrupt off and on, using disable_irq() and enable_irq() is not
necessarily correct.

If the interrupt line is shared, for example, this will break
everything.


^ permalink raw reply

* Re: [PATCH] Export ACPI _DSM provided firmware instance number and string name to sysfs
From: Narendra_K @ 2010-12-23 19:24 UTC (permalink / raw)
  To: Matt_Domsch
  Cc: linux-pci, linux-hotplug, netdev, Jordan_Hargrave, Charles_Rose,
	Vijay_Nijhawan
In-Reply-To: <20101223143203.GA12256@auslistsprd01.us.dell.com>

On Thu, Dec 23, 2010 at 08:02:03PM +0530, Domsch, Matt wrote:
> On Wed, Dec 22, 2010 at 08:42:39AM -0800, Narendra_K@Dell.com wrote:
> > Hello,
> > 
> > This patch exports ACPI _DSM provided firmware instance number and
> > string name to sysfs.
> > 
> > Please review -
> 
> There are now two different meanings for the 'index' file:
> 
> 1) SMBIOS-provided "type instance" value, which I've only seen in
>    range [1..N] for N devices, monotonically stepwise increasing.
> 
> 2) ACPI-provided "index" value, which per spec only needs to be a
>    "sort key", not starting at 0 or 1, and while monotonically
>    increasing, not necessarily stepwise.  It's perfectly valid for the
>    values to be (12, 16, 27, 29) if that's convenient for BIOS to
>    generate.
> 
> Therefore, a consumer of this value (such as biosdevname) must know
> which of the two it's dealing with, and either accept the value as-is,
> or sort the value list.  While I suppose it could sort the value list
> in either case, I'd prefer the ACPI value to be exposed in its own
> file, perhaps 'acpi_index', to make this explicit rather than
> implicit.
> 
> 'label' is fine for either case, with ACPI taking priority over
> SMBIOS if both happen to be present.
> 

Matt,

Thanks for the suggestion. I agree.

Please find the version 2 of the patch.

V1 -> V2:

The attribute 'index' is changed to 'acpi_index' as the semantics of
SMBIOS provided device type instance and ACPI _DSM provided instance
number are different.

From: Narendra K <narendra_k@dell.com>
Subject: [PATCH V2] Export ACPI _DSM provided firmware instance number and string to sysfs

This patch exports ACPI _DSM (Device Specific Method) provided firmware
instance number and string name of PCI devices as defined by
'PCI Firmware Specification Revision 3.1' section 4.6.7.( DSM for Naming
a PCI or PCI Express Device Under Operating Systems) to sysfs.

New files created are:
  /sys/bus/pci/devices/.../label which contains the firmware name for
the device in question, and
  /sys/bus/pci/devices/.../acpi_index which contains the firmware device type
instance for the given device.

cat /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/acpi_index
1
cat /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/label
Embedded Broadcom 5709C NIC 1

cat /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.1/acpi_index
2
cat /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.1/label
Embedded Broadcom 5709C NIC 2

The ACPI _DSM provided firmware 'instance number' and 'string name' will
be given priority if the firmware also provides 'SMBIOS type 41 device
type instance and string'.

Signed-off-by: Jordan Hargrave <jordan_hargrave@dell.com>
Signed-off-by: Narendra K <narendra_k@dell.com>
---
 Documentation/ABI/testing/sysfs-bus-pci |   31 +++-
 drivers/pci/Makefile                    |    3 +-
 drivers/pci/pci-label.c                 |  236 ++++++++++++++++++++++++++++++-
 drivers/pci/pci.h                       |    2 +-
 4 files changed, 260 insertions(+), 12 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index f979d82..36bf454 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -145,9 +145,11 @@ Date:		July 2010
 Contact:	Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
 Description:
 		Reading this attribute will provide the firmware
-		given name(SMBIOS type 41 string) of the PCI device.
-		The attribute will be created only if the firmware
-		has given a name to the PCI device.
+		given name (SMBIOS type 41 string or ACPI _DSM string) of
+		the PCI device.	The attribute will be created only
+		if the firmware	has given a name to the PCI device.
+		ACPI _DSM string name will be given priority if the
+		system firmware provides SMBIOS type 41 string also.
 Users:
 		Userspace applications interested in knowing the
 		firmware assigned name of the PCI device.
@@ -157,12 +159,27 @@ Date:		July 2010
 Contact:	Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
 Description:
 		Reading this attribute will provide the firmware
-		given instance(SMBIOS type 41 device type instance)
-		of the PCI device. The attribute will be created
-		only if the firmware has given a device type instance
-		to the PCI device.
+		given instance (SMBIOS type 41 device type instance) of the
+		PCI device. The attribute will be created only if the firmware
+		has given an instance number to the PCI device.
 Users:
 		Userspace applications interested in knowing the
 		firmware assigned device type instance of the PCI
 		device that can help in understanding the firmware
 		intended order of the PCI device.
+
+What:		/sys/bus/pci/devices/.../acpi_index
+Date:		July 2010
+Contact:	Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
+Description:
+		Reading this attribute will provide the firmware
+		given instance (ACPI _DSM instance number) of the PCI device.
+		The attribute will be created only if the firmware has given
+		an instance number to the PCI device. ACPI _DSM instance number
+		will be given priority if the system firmware provides SMBIOS
+		type 41 device type instance also.
+Users:
+		Userspace applications interested in knowing the
+		firmware assigned instance number of the PCI
+		device that can help in understanding the firmware
+		intended order of the PCI device.
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 98e6fdf..bb1d3b2 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -53,8 +53,9 @@ obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
 
 #
 # ACPI Related PCI FW Functions
+# ACPI _DSM provided firmware instance and string name
 #
-obj-$(CONFIG_ACPI)    += pci-acpi.o
+obj-$(CONFIG_ACPI)    += pci-acpi.o pci-label.o
 
 # SMBIOS provided firmware instance and labels
 obj-$(CONFIG_DMI)    += pci-label.o
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c
index 90c0a72..d46693c 100644
--- a/drivers/pci/pci-label.c
+++ b/drivers/pci/pci-label.c
@@ -5,6 +5,13 @@
  * by Narendra K <Narendra_K@dell.com>,
  * Jordan Hargrave <Jordan_Hargrave@dell.com>
  *
+ * PCI Firmware Specification Revision 3.1 section 4.6.7 (DSM for Naming a
+ * PCI or PCI Express Device Under Operating Systems) defines an instance
+ * number and string name. This code retrieves them and exports them to sysfs.
+ * If the system firmware does not provide the ACPI _DSM (Device Specific
+ * Method), then the SMBIOS type 41 instance number and string is exported to
+ * sysfs.
+ *
  * SMBIOS defines type 41 for onboard pci devices. This code retrieves
  * the instance number and string from the type 41 record and exports
  * it to sysfs.
@@ -19,8 +26,30 @@
 #include <linux/pci_ids.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/nls.h>
+#include <linux/acpi.h>
+#include <linux/pci-acpi.h>
+#include <acpi/acpi_drivers.h>
+#include <acpi/acpi_bus.h>
 #include "pci.h"
 
+#define	DEVICE_LABEL_DSM	0x07
+
+#ifndef CONFIG_DMI
+
+static inline int
+pci_create_smbiosname_file(struct pci_dev *pdev)
+{
+	return -1;
+}
+
+static inline void
+pci_remove_smbiosname_file(struct pci_dev *pdev)
+{
+}
+
+#else
+
 enum smbios_attr_enum {
 	SMBIOS_ATTR_NONE = 0,
 	SMBIOS_ATTR_LABEL_SHOW,
@@ -131,13 +160,214 @@ pci_remove_smbiosname_file(struct pci_dev *pdev)
 	sysfs_remove_group(&pdev->dev.kobj, &smbios_attr_group);
 }
 
+#endif
+
+#ifndef CONFIG_ACPI
+
+static inline int
+pci_create_acpi_index_label_files(struct pci_dev *pdev)
+{
+	return -1;
+}
+
+static inline int
+pci_remove_acpi_index_label_files(struct pci_dev *pdev)
+{
+	return -1;
+}
+
+#else
+
+static const char device_label_dsm_uuid[] = {
+	0xD0, 0x37, 0xC9, 0xE5, 0x53, 0x35, 0x7A, 0x4D,
+	0x91, 0x17, 0xEA, 0x4D, 0x19, 0xC3, 0x43, 0x4D
+};
+
+enum acpi_attr_enum {
+	ACPI_ATTR_NONE = 0,
+	ACPI_ATTR_LABEL_SHOW,
+	ACPI_ATTR_INDEX_SHOW,
+};
+
+static int dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf)
+{
+	int err;
+	err = utf16s_to_utf8s((const wchar_t *)obj->
+			      package.elements[1].string.pointer,
+			      obj->package.elements[1].string.length,
+			      UTF16_LITTLE_ENDIAN,
+			      buf, PAGE_SIZE);
+	buf[err] = '\n';
+	return err;
+}
+
+static int
+dsm_get_label(acpi_handle handle, int func,
+	      struct acpi_buffer *output,
+	      char *buf, enum acpi_attr_enum attribute)
+{
+	struct acpi_object_list input;
+	union acpi_object params[4];
+	union acpi_object *obj;
+	int len = 0;
+
+	int err;
+
+	input.count = 4;
+	input.pointer = params;
+	params[0].type = ACPI_TYPE_BUFFER;
+	params[0].buffer.length = sizeof(device_label_dsm_uuid);
+	params[0].buffer.pointer = (char *)device_label_dsm_uuid;
+	params[1].type = ACPI_TYPE_INTEGER;
+	params[1].integer.value = 0x02;
+	params[2].type = ACPI_TYPE_INTEGER;
+	params[2].integer.value = func;
+	params[3].type = ACPI_TYPE_PACKAGE;
+	params[3].package.count = 0;
+	params[3].package.elements = NULL;
+
+	err = acpi_evaluate_object(handle, "_DSM", &input, output);
+	if (err)
+		return -1;
+
+	obj = (union acpi_object *)output->pointer;
+
+	switch (obj->type) {
+	case ACPI_TYPE_PACKAGE:
+		if (obj->package.count != 2)
+			break;
+		len = obj->package.elements[0].integer.value;
+		if (buf) {
+			if (attribute == ACPI_ATTR_INDEX_SHOW)
+				scnprintf(buf, PAGE_SIZE, "%llu\n",
+				obj->package.elements[0].integer.value);
+			else if (attribute == ACPI_ATTR_LABEL_SHOW) {
+				if (dsm_label_utf16s_to_utf8s(obj, buf) < 0)
+					return -1;
+			}
+			kfree(output->pointer);
+			return strlen(buf);
+		}
+		kfree(output->pointer);
+		return len;
+	break;
+	default:
+		kfree(output->pointer);
+	}
+	return -1;
+}
+
+static mode_t
+acpi_index_string_exist(struct kobject *kobj, struct attribute *attr, int n)
+{
+	struct device *dev;
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_handle handle;
+	int length;
+
+	dev = container_of(kobj, struct device, kobj);
+	handle = DEVICE_ACPI_HANDLE(dev);
+
+	if (!handle)
+		return 0;
+
+	length = dsm_get_label(handle, DEVICE_LABEL_DSM,
+			       &output, NULL, ACPI_ATTR_NONE);
+
+	return (length > 0) ? S_IRUGO : 0;
+}
+
+static ssize_t
+acpilabel_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_handle handle;
+	int length;
+
+	handle = DEVICE_ACPI_HANDLE(dev);
+
+	if (!handle)
+		return -1;
+
+	length = dsm_get_label(handle, DEVICE_LABEL_DSM,
+			       &output, buf, ACPI_ATTR_LABEL_SHOW);
+
+	if (length < 1)
+		return -1;
+
+	return length;
+}
+
+static ssize_t
+acpiindex_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_handle handle;
+	int length;
+
+	handle = DEVICE_ACPI_HANDLE(dev);
+
+	if (!handle)
+		return -1;
+
+	length = dsm_get_label(handle, DEVICE_LABEL_DSM,
+			       &output, buf, ACPI_ATTR_INDEX_SHOW);
+
+	if (length < 0)
+		return -1;
+
+	return length;
+
+}
+
+static struct device_attribute acpi_attr_label = {
+	.attr = {.name = "label", .mode = 0444},
+	.show = acpilabel_show,
+};
+
+static struct device_attribute acpi_attr_index = {
+	.attr = {.name = "acpi_index", .mode = 0444},
+	.show = acpiindex_show,
+};
+
+static struct attribute *acpi_attributes[] = {
+	&acpi_attr_label.attr,
+	&acpi_attr_index.attr,
+	NULL,
+};
+
+static struct attribute_group acpi_attr_group = {
+	.attrs = acpi_attributes,
+	.is_visible = acpi_index_string_exist,
+};
+
+static int
+pci_create_acpi_index_label_files(struct pci_dev *pdev)
+{
+	if (!sysfs_create_group(&pdev->dev.kobj, &acpi_attr_group))
+		return 0;
+	return -ENODEV;
+}
+
+static int
+pci_remove_acpi_index_label_files(struct pci_dev *pdev)
+{
+	sysfs_remove_group(&pdev->dev.kobj, &acpi_attr_group);
+	return 0;
+}
+#endif
+
 void pci_create_firmware_label_files(struct pci_dev *pdev)
 {
-	if (!pci_create_smbiosname_file(pdev))
-		;
+	if (!pci_create_acpi_index_label_files(pdev))
+		return;
+	pci_create_smbiosname_file(pdev);
 }
 
 void pci_remove_firmware_label_files(struct pci_dev *pdev)
 {
-	pci_remove_smbiosname_file(pdev);
+	if (!pci_remove_acpi_index_label_files(pdev))
+		return;
+	else
+		pci_remove_smbiosname_file(pdev);
 }
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 7d33f66..d0d0bd4 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -11,7 +11,7 @@
 extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
 extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
-#ifndef CONFIG_DMI
+#if !defined(CONFIG_DMI) && !defined(CONFIG_ACPI)
 static inline void pci_create_firmware_label_files(struct pci_dev *pdev)
 { return; }
 static inline void pci_remove_firmware_label_files(struct pci_dev *pdev)
-- 
1.7.3.1

With regards,
Narendra K

^ permalink raw reply related

* Re: [PATCH net-next 0/9] cnic: Bug fixes and FCoE support
From: David Miller @ 2010-12-23 19:27 UTC (permalink / raw)
  To: mchan; +Cc: netdev
In-Reply-To: <1293126184-13097-1-git-send-email-mchan@broadcom.com>

From: "Michael Chan" <mchan@broadcom.com>
Date: Thu, 23 Dec 2010 09:42:55 -0800

> 
> David, bug fixes and FCoE enablement patches for net-next.
> Please review.  Thanks.

There are two identical patch #5's and no patch #6.

If you're going to generate these patch postings by hand and not use
automated tools to help you out, please at least double check your
work.

^ permalink raw reply

* Re: [PATCH net-next 0/9] cnic: Bug fixes and FCoE support
From: Michael Chan @ 2010-12-23 19:29 UTC (permalink / raw)
  To: David Miller; +Cc: netdev@vger.kernel.org
In-Reply-To: <20101223.112758.28829172.davem@davemloft.net>


On Thu, 2010-12-23 at 11:27 -0800, David Miller wrote:

> 
> There are two identical patch #5's and no patch #6.
> 
> If you're going to generate these patch postings by hand and not use
> automated tools to help you out, please at least double check your
> work.
> 

Sorry, re-sending #6 now.  There are scripts to do these things, but not
100% automated.  Thanks.



^ permalink raw reply

* [PATCH net-next 6/9] cnic: Check device state before reading the kcq pointer in IRQ
From: Michael Chan @ 2010-12-23 18:38 UTC (permalink / raw)
  To: davem; +Cc: netdev

If the device is down, the kcq pointer may be NULL.

Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/cnic.c |   12 +++++++-----
 1 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index bf4a804..1240dea 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -2352,11 +2352,12 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev)
 static int cnic_service_bnx2(void *data, void *status_blk)
 {
 	struct cnic_dev *dev = data;
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 status_idx = *cp->kcq1.status_idx_ptr;
 
-	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags)))
-		return status_idx;
+	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags))) {
+		struct status_block *sblk = status_blk;
+
+		return sblk->status_idx;
+	}
 
 	return cnic_service_bnx2_queues(dev);
 }
@@ -2375,9 +2376,10 @@ static void cnic_service_bnx2_msix(unsigned long data)
 static void cnic_doirq(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	u16 prod = cp->kcq1.sw_prod_idx & MAX_KCQ_IDX;
 
 	if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags))) {
+		u16 prod = cp->kcq1.sw_prod_idx & MAX_KCQ_IDX;
+
 		prefetch(cp->status_blk.gen);
 		prefetch(&cp->kcq1.kcq[KCQ_PG(prod)][KCQ_IDX(prod)]);
 
-- 
1.6.4.GIT



^ permalink raw reply related

* Re: [PATCH net-next 0/9] cnic: Bug fixes and FCoE support
From: David Miller @ 2010-12-23 20:01 UTC (permalink / raw)
  To: mchan; +Cc: netdev
In-Reply-To: <1293126184-13097-1-git-send-email-mchan@broadcom.com>

From: "Michael Chan" <mchan@broadcom.com>
Date: Thu, 23 Dec 2010 09:42:55 -0800

> David, bug fixes and FCoE enablement patches for net-next.
> Please review.  Thanks.

All applied, thanks.

^ permalink raw reply

* Re: ip rule and/or route problem in 2.6.37-rc5+
From: David Miller @ 2010-12-23 20:06 UTC (permalink / raw)
  To: zenczykowski; +Cc: therbert, greearb, netdev
In-Reply-To: <AANLkTin0mNkfaDvs3ZrEhxY27kdmZLh8ikKNpc-MXC44@mail.gmail.com>

From: Maciej Żenczykowski <zenczykowski@gmail.com>
Date: Thu, 23 Dec 2010 10:22:23 +0100

> Could we please revert this ( 4465b469008bc03b98a1b8df4e9ae501b6c69d4b
> ) and make sure the revert makes it into 2.6.37?  We definitely don't
> want to ship 2.6.37 with this patch in its current state.

I'm pushing out a revert right now, thanks everyone.

^ permalink raw reply

* [PATCH] Revert "ipv4: Allow configuring subnets as local addresses"
From: David Miller @ 2010-12-23 20:10 UTC (permalink / raw)
  To: netdev


This reverts commit 4465b469008bc03b98a1b8df4e9ae501b6c69d4b.

Conflicts:

	net/ipv4/fib_frontend.c

As reported by Ben Greear, this causes regressions:

> Change 4465b469008bc03b98a1b8df4e9ae501b6c69d4b caused rules
> to stop matching the input device properly because the
> FLOWI_FLAG_MATCH_ANY_IIF is always defined in ip_dev_find().
>
> This breaks rules such as:
>
> ip rule add pref 512 lookup local
> ip rule del pref 0 lookup local
> ip link set eth2 up
> ip -4 addr add 172.16.0.102/24 broadcast 172.16.0.255 dev eth2
> ip rule add to 172.16.0.102 iif eth2 lookup local pref 10
> ip rule add iif eth2 lookup 10001 pref 20
> ip route add 172.16.0.0/24 dev eth2 table 10001
> ip route add unreachable 0/0 table 10001
>
> If you had a second interface 'eth0' that was on a different
> subnet, pinging a system on that interface would fail:
>
>   [root@ct503-60 ~]# ping 192.168.100.1
>   connect: Invalid argument

Reported-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---

I'm posting this because there were non-trivial merge conflicts
with Eric Dumazet's RCU work.

 include/net/flow.h      |    1 -
 net/core/fib_rules.c    |    3 +--
 net/ipv4/fib_frontend.c |   10 ++++++++--
 3 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/include/net/flow.h b/include/net/flow.h
index 0ac3fb5..bb08692 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -49,7 +49,6 @@ struct flowi {
 	__u8	proto;
 	__u8	flags;
 #define FLOWI_FLAG_ANYSRC 0x01
-#define FLOWI_FLAG_MATCH_ANY_IIF 0x02
 	union {
 		struct {
 			__be16	sport;
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 82a4369..a20e5d3 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -181,8 +181,7 @@ static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
 {
 	int ret = 0;
 
-	if (rule->iifindex && (rule->iifindex != fl->iif) &&
-	    !(fl->flags & FLOWI_FLAG_MATCH_ANY_IIF))
+	if (rule->iifindex && (rule->iifindex != fl->iif))
 		goto out;
 
 	if (rule->oifindex && (rule->oifindex != fl->oif))
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index eb6f69a..c19c1f7 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -163,13 +163,19 @@ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
 				.daddr = addr
 			}
 		},
-		.flags = FLOWI_FLAG_MATCH_ANY_IIF
 	};
 	struct fib_result res = { 0 };
 	struct net_device *dev = NULL;
+	struct fib_table *local_table;
+
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+	res.r = NULL;
+#endif
 
 	rcu_read_lock();
-	if (fib_lookup(net, &fl, &res)) {
+	local_table = fib_get_table(net, RT_TABLE_LOCAL);
+	if (!local_table ||
+	    fib_table_lookup(local_table, &fl, &res, FIB_LOOKUP_NOREF)) {
 		rcu_read_unlock();
 		return NULL;
 	}
-- 
1.7.3.4


^ permalink raw reply related

* Re: Help: major pppoe regression since 2.6.35 (panic on first ppp conection)?
From: Jarek Poplawski @ 2010-12-23 20:25 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Joel Soete, Andrew Morton, Linux Kernel, netdev
In-Reply-To: <1293106348.7789.5.camel@edumazet-laptop>

On Thu, Dec 23, 2010 at 01:12:28PM +0100, Eric Dumazet wrote:
> Le jeudi 23 décembre 2010 ?? 11:02 +0000, Joel Soete a écrit :
...
> > Sorry for delay but I have good news, I am sending this answer from:
> > $ uname -a
> > Linux sidh2 2.6.37-rc7-amd64-t1 #1 SMP Thu Dec 23 10:30:27 GMT 2010 x86_64 GNU/Linux
> > 
> > with your tips ;<) (without kernel had already died)
> > 
> > That said how can find stuff overflowing skb head? (all I say, is that this issue started with 2.6.34-git6???)

Hi Joel,
2.6.34-git6 or 7 is almost a whole netdev batch for 2.6.35 so still
a lot of guessing. One such guess could be e.g. this one:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=18e8c134f4e984e6639e62846345192816f06d5c

I've added to Eric's patch some debugging. After taking several
warnings (might a lot) revert this patch and apply Eric's again.
Btw, could you send your pppoe config (without any personal data,
of course), and mention if there are other changes like mtu etc.

> I am taking holidays right now for about 5 days, I guess someone else
> might find the bug before me ;)

Good job, Eric, we can try. Have a nice rest!

Thanks,
Jarek P.
--- (a debugging patch, apply to clean 2.6.37-rc)

 drivers/net/pppoe.c    |    8 ++++++++
 include/linux/skbuff.h |    6 ++++++
 net/core/dev.c         |    8 ++++++++
 net/core/skbuff.c      |    9 +++++++++
 4 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index d72fb05..0d41a04 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -385,6 +385,7 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
 	 * can't change.
 	 */
 
+	DEBUG_SKB_POISON(skb);
 	if (sk->sk_state & PPPOX_BOUND) {
 		ppp_input(&po->chan, skb);
 	} else if (sk->sk_state & PPPOX_RELAY) {
@@ -430,6 +431,7 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (!skb)
 		goto out;
 
+	DEBUG_SKB_POISON(skb);
 	if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
 		goto drop;
 
@@ -452,6 +454,7 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (!po)
 		goto drop;
 
+	DEBUG_SKB_POISON(skb);
 	return sk_receive_skb(sk_pppox(po), skb, 0);
 
 drop:
@@ -485,6 +488,7 @@ static int pppoe_disc_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (ph->code != PADT_CODE)
 		goto abort;
 
+	DEBUG_SKB_POISON(skb);
 	pn = pppoe_pernet(dev_net(dev));
 	po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
 	if (po) {
@@ -888,6 +892,7 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock,
 
 	ph->length = htons(total_len);
 
+	DEBUG_SKB_POISON(skb);
 	dev_queue_xmit(skb);
 
 end:
@@ -921,6 +926,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
 	if (!dev)
 		goto abort;
 
+	DEBUG_SKB_POISON(skb);
 	/* Copy the data if there is no space for the header or if it's
 	 * read-only.
 	 */
@@ -943,6 +949,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
 	dev_hard_header(skb, dev, ETH_P_PPP_SES,
 			po->pppoe_pa.remote, NULL, data_len);
 
+	DEBUG_SKB_POISON(skb);
 	dev_queue_xmit(skb);
 	return 1;
 
@@ -987,6 +994,7 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
 	m->msg_namelen = 0;
 
 	if (skb) {
+		DEBUG_SKB_POISON(skb);
 		total_len = min_t(size_t, total_len, skb->len);
 		error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len);
 		if (error == 0)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index e6ba898..706f182 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -187,6 +187,12 @@ enum {
  * the end of the header data, ie. at skb->end.
  */
 struct skb_shared_info {
+#define SKB_POISON	0xe2e4e7e5
+#define SET_SKB_POISON(skb)	skb_shinfo(skb)->poison = SKB_POISON
+#define DEBUG_SKB_POISON(skb)	WARN_ON(skb_shinfo(skb)->poison != SKB_POISON)
+
+	unsigned int	poison;
+	char		filler[60];
 	unsigned short	nr_frags;
 	unsigned short	gso_size;
 	/* Warning: this field is not always filled in (UFO)! */
diff --git a/net/core/dev.c b/net/core/dev.c
index 0dd54a6..01ca7de 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1994,6 +1994,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 	const struct net_device_ops *ops = dev->netdev_ops;
 	int rc = NETDEV_TX_OK;
 
+	DEBUG_SKB_POISON(skb);
 	if (likely(!skb->next)) {
 		if (!list_empty(&ptype_all))
 			dev_queue_xmit_nit(skb, dev);
@@ -2026,6 +2027,8 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 			    __skb_linearize(skb))
 				goto out_kfree_skb;
 
+			DEBUG_SKB_POISON(skb);
+
 			/* If packet is not checksummed and device does not
 			 * support checksumming for this protocol, complete
 			 * checksumming here.
@@ -2039,6 +2042,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 			}
 		}
 
+		DEBUG_SKB_POISON(skb);
 		rc = ops->ndo_start_xmit(skb, dev);
 		trace_net_dev_xmit(skb, rc);
 		if (rc == NETDEV_TX_OK)
@@ -2243,6 +2247,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 	struct Qdisc *q;
 	int rc = -ENOMEM;
 
+	DEBUG_SKB_POISON(skb);
 	/* Disable soft irqs for various locks below. Also
 	 * stops preemption for RCU.
 	 */
@@ -2604,6 +2609,7 @@ int netif_rx(struct sk_buff *skb)
 {
 	int ret;
 
+	DEBUG_SKB_POISON(skb);
 	/* if netpoll wants it, pretend we never saw it */
 	if (netpoll_rx(skb))
 		return NET_RX_DROP;
@@ -2898,6 +2904,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
 	int ret = NET_RX_DROP;
 	__be16 type;
 
+	DEBUG_SKB_POISON(skb);
 	if (!netdev_tstamp_prequeue)
 		net_timestamp_check(skb);
 
@@ -3043,6 +3050,7 @@ out:
  */
 int netif_receive_skb(struct sk_buff *skb)
 {
+	DEBUG_SKB_POISON(skb);
 	if (netdev_tstamp_prequeue)
 		net_timestamp_check(skb);
 
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 104f844..b112c7d 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -210,6 +210,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
 	shinfo = skb_shinfo(skb);
 	memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
 	atomic_set(&shinfo->dataref, 1);
+	SET_SKB_POISON(skb);
 
 	if (fclone) {
 		struct sk_buff *child = skb + 1;
@@ -412,6 +413,7 @@ static void skb_release_all(struct sk_buff *skb)
 
 void __kfree_skb(struct sk_buff *skb)
 {
+	DEBUG_SKB_POISON(skb);
 	skb_release_all(skb);
 	kfree_skbmem(skb);
 }
@@ -428,6 +430,7 @@ void kfree_skb(struct sk_buff *skb)
 {
 	if (unlikely(!skb))
 		return;
+	DEBUG_SKB_POISON(skb);
 	if (likely(atomic_read(&skb->users) == 1))
 		smp_rmb();
 	else if (likely(!atomic_dec_and_test(&skb->users)))
@@ -449,6 +452,7 @@ void consume_skb(struct sk_buff *skb)
 {
 	if (unlikely(!skb))
 		return;
+	DEBUG_SKB_POISON(skb);
 	if (likely(atomic_read(&skb->users) == 1))
 		smp_rmb();
 	else if (likely(!atomic_dec_and_test(&skb->users)))
@@ -487,11 +491,13 @@ bool skb_recycle_check(struct sk_buff *skb, int skb_size)
 	if (skb_shared(skb) || skb_cloned(skb))
 		return false;
 
+	DEBUG_SKB_POISON(skb);
 	skb_release_head_state(skb);
 
 	shinfo = skb_shinfo(skb);
 	memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
 	atomic_set(&shinfo->dataref, 1);
+	SET_SKB_POISON(skb);
 
 	memset(skb, 0, offsetof(struct sk_buff, tail));
 	skb->data = skb->head + NET_SKB_PAD;
@@ -571,6 +577,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
 
 	atomic_inc(&(skb_shinfo(skb)->dataref));
 	skb->cloned = 1;
+	DEBUG_SKB_POISON(skb);
 
 	return n;
 #undef C
@@ -772,6 +779,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
 	bool fastpath;
 
 	BUG_ON(nhead < 0);
+	DEBUG_SKB_POISON(skb);
 
 	if (skb_shared(skb))
 		BUG();
@@ -836,6 +844,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
 	skb->hdr_len  = 0;
 	skb->nohdr    = 0;
 	atomic_set(&skb_shinfo(skb)->dataref, 1);
+	SET_SKB_POISON(skb);
 	return 0;
 
 nodata:

^ permalink raw reply related

* Re: [PATCH net-next-2.6 1/2] can: add driver for Softing card
From: Oliver Hartkopp @ 2010-12-23 20:33 UTC (permalink / raw)
  To: Marc Kleine-Budde, Kurt Van Dijck; +Cc: socketcan-core, netdev
In-Reply-To: <4D135BC3.6070707@pengutronix.de>

Hello Kurt,

thanks for the effort to make this driver available in Mainline!

>> +
>> +MODULE_DESCRIPTION("socketcan softing driver");

MODULE_DESCRIPTION("Softing CAN driver");

MODULE_DESCRIPTION("Softing DPRAM CAN driver");

???

>> diff --git a/drivers/net/can/softing/softing_platform.h b/drivers/net/can/softing/softing_platform.h
>> new file mode 100644
>> index 0000000..9ff69a1
>> --- /dev/null
>> +++ b/drivers/net/can/softing/softing_platform.h

Shouldn't this file be placed in include/linux/can/platform/softing.h ??

Regards,
Oliver

^ permalink raw reply

* Re: [PATCH net-2.6] net_sched: always clone skbs
From: Jarek Poplawski @ 2010-12-23 23:04 UTC (permalink / raw)
  To: jamal; +Cc: Changli Gao, Eric Dumazet, David S. Miller, netdev,
	Pawel Staszewski
In-Reply-To: <1293111333.11306.170.camel@mojatatu>

On Thu, Dec 23, 2010 at 08:35:33AM -0500, jamal wrote:
> On Tue, 2010-12-21 at 23:37 +0100, Jarek Poplawski wrote:
> 
> > Actually, when dumb isn't a good principle? ;->
> > 
> > Speaking about wrong things like optimizing this 1st commandment: it
> > seems, if we're stealing not shared skb it's not unreasonable to tell
> > others not to touch it anymore, and skip kfree_skb() in handle_ing(),
> > unless I miss something?
> 
> I dont know how much cycles it will save you vs the code you add
> but it is not unreasonable. Of course it would mean we are moving
> beyond KISSes[1] now Jarek;->

Hmm... seeing all those multiqued multiques I thought everybody was
beyond, but no problem, let's go back to KISSes[2] ;-)

> > > In order to make my trick work. We need to assure dev_queue_xmit() and
> > > dev_hard_start_xmit() accept shared skbs. As Eric pointed, pktgen also
> > > need dev->netdev_ops->ndo_start_xmit() accept shared skbs. We need to
> > > fix every ndo_start_xmit() one by one, then dev_hard_start_xmit(), and
> > > when dev_queue_xmit() is also fixed, my trick can be added back.
> > > :)
> > 
> > I'm not sure pktgen is right - even if it's safe in its case, it seems
> > to break some older rules, and drivers should really own the things.
> > So it needs reviewing first.
> 
> The idea we always try to keep is that the caller is responsible for the
> fate of the skb it sent. The callee will do things like make a copy or
> clone if it needed to make changes or keep the skb. Same should be
> expected of a driver.

Well, I'm not sure we talk about the same thing. I mean e.g. the
comment above dev_queue_xmit(); the caller passes all control to the
callee here.

Cheers,
Jarek P.

> [1] Jarek - so you dont misunderstand this as an overture - it means
> Keep It Simple Silly (or the principle of dumb we talked about) ;->

OK, I can remember the seventies too ;-)

^ permalink raw reply

* [PATCH 1/1] netfilter: ebtables: make broute table work again
From: Florian Westphal @ 2010-12-24  0:27 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, netfilter-devel, Florian Westphal

broute table init hook sets up the "br_should_route_hook" pointer,
which then gets called from br_input.

commit a386f99025f13b32502fe5dedf223c20d7283826
(bridge: add proper RCU annotation to should_route_hook)
introduced a typedef, and then changed this to:

br_should_route_hook_t *rhook;
[..]
rhook = rcu_dereference(br_should_route_hook);
if (*rhook(skb))

problem is that "br_should_route_hook" contains the address of the function,
so calling *rhook() results in kernel panic.

Can't simply use "if (rhook(skb)", because br_should_route_hook_t *rhook
is not a function.

Signed-off-by: Florian Westphal <fw@strlen.de>
---

 include/linux/if_bridge.h |    2 +-
 net/bridge/br_input.c     |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index f7e73c3..dd3f201 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -103,7 +103,7 @@ struct __fdb_entry {
 
 extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
 
-typedef int (*br_should_route_hook_t)(struct sk_buff *skb);
+typedef int br_should_route_hook_t(struct sk_buff *skb);
 extern br_should_route_hook_t __rcu *br_should_route_hook;
 
 #endif
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 6f6d8e1..1d677bf 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -178,7 +178,7 @@ forward:
 	case BR_STATE_FORWARDING:
 		rhook = rcu_dereference(br_should_route_hook);
 		if (rhook) {
-			if ((*rhook)(skb))
+			if (rhook(skb))
 				return skb;
 			dest = eth_hdr(skb)->h_dest;
 		}
-- 
1.7.2.2


^ permalink raw reply related

* Re: [PATCH 1/1] netfilter: ebtables: make broute table work again
From: Changli Gao @ 2010-12-24  0:47 UTC (permalink / raw)
  To: Florian Westphal; +Cc: eric.dumazet, netdev, netfilter-devel
In-Reply-To: <1293150436-12092-1-git-send-email-fw@strlen.de>

On Fri, Dec 24, 2010 at 8:27 AM, Florian Westphal <fw@strlen.de> wrote:
> broute table init hook sets up the "br_should_route_hook" pointer,
> which then gets called from br_input.
>
> commit a386f99025f13b32502fe5dedf223c20d7283826
> (bridge: add proper RCU annotation to should_route_hook)
> introduced a typedef, and then changed this to:
>
> br_should_route_hook_t *rhook;
> [..]
> rhook = rcu_dereference(br_should_route_hook);
> if (*rhook(skb))
>
> problem is that "br_should_route_hook" contains the address of the function,
> so calling *rhook() results in kernel panic.
>
> Can't simply use "if (rhook(skb)", because br_should_route_hook_t *rhook
> is not a function.
>
> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
>
>  include/linux/if_bridge.h |    2 +-
>  net/bridge/br_input.c     |    2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
> index f7e73c3..dd3f201 100644
> --- a/include/linux/if_bridge.h
> +++ b/include/linux/if_bridge.h
> @@ -103,7 +103,7 @@ struct __fdb_entry {
>
>  extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
>
> -typedef int (*br_should_route_hook_t)(struct sk_buff *skb);
> +typedef int br_should_route_hook_t(struct sk_buff *skb);
>  extern br_should_route_hook_t __rcu *br_should_route_hook;
>
>  #endif
> diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
> index 6f6d8e1..1d677bf 100644
> --- a/net/bridge/br_input.c
> +++ b/net/bridge/br_input.c
> @@ -178,7 +178,7 @@ forward:
>        case BR_STATE_FORWARDING:
>                rhook = rcu_dereference(br_should_route_hook);
>                if (rhook) {
> -                       if ((*rhook)(skb))
> +                       if (rhook(skb))

I don't think this change is necessary. Would you like to remove this
change and test again?

>                                return skb;
>                        dest = eth_hdr(skb)->h_dest;
>                }




-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* Re: [PATCH 1/1] netfilter: ebtables: make broute table work again
From: Florian Westphal @ 2010-12-24  0:55 UTC (permalink / raw)
  To: Changli Gao; +Cc: eric.dumazet, netdev, netfilter-devel
In-Reply-To: <AANLkTikgoc6xzx-0xn4cXsVuWVETOG1=dpE_1kZKBVnM@mail.gmail.com>

Changli Gao <xiaosuo@gmail.com> wrote:
> > diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
> > index 6f6d8e1..1d677bf 100644
> > --- a/net/bridge/br_input.c
> > +++ b/net/bridge/br_input.c
> > @@ -178,7 +178,7 @@ forward:
> >        case BR_STATE_FORWARDING:
> >                rhook = rcu_dereference(br_should_route_hook);
> >                if (rhook) {
> > -                       if ((*rhook)(skb))
> > +                       if (rhook(skb))
> 
> I don't think this change is necessary. Would you like to remove this
> change and test again?

Its not needed, but i consider it less confusing.
I do not have a strong preference, though.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] smsc911x: add disable and re-enable Rx int to de-assert interrupt pin
From: Jason Wang @ 2010-12-24  2:18 UTC (permalink / raw)
  To: David Miller; +Cc: jason77.wang, netdev, steve.glendinning, linux-omap
In-Reply-To: <20101223.095917.59696176.davem@davemloft.net>

David Miller wrote:
> From: Jason Wang <jason77.wang@gmail.com>
> Date: Thu, 23 Dec 2010 18:43:13 +0800
>
>   
>> When kernel enters irqhanlder, it will check the Rx interrupt status
>> bit, if Rx status is set but can't call napi_schedule(), it will do
>> nothing and directly return form irqhandler. This situation is prone
>> to be produced when we repeatly call irqhandler through netpoll
>> interface(i.e kgdboe connecting).
>>
>> This is a potential risk for those level triggered platforms(i.e
>> ti_omap3evm), because if we don't handle Rx int and just return from
>> irqhandler, the irq pin will be keeping asserted, the level triggered
>> platforms will have no chance to jump out from the Rx irq. The whole
>> system will hung into the irq subsystem.
>>
>> To solve it, we add a disable/re-enable Rx int operation for this
>> situation, this operation can de-assert interrupt pin for this time
>> and will leave the received data and status in the FIFO for later
>> interrupts to handle.
>>
>> Signed-off-by: Jason Wang <jason77.wang@gmail.com>
>>     
>
>   
Hi David,

Thanks for your comments.
> You absolutely cannot do this.
>
> You now can race with the NAPI completion code turning the RX
> interrupts back on, and you'll leave the chip with RX interrupts
> disabled.
>   
I think my modification almost have the same execution path as the 
original design and don't produce the race condition with NAPI threads.

The original design is:
If (can call napi_schedule) {
disable rx int;
call napi_schedule()
} else {
keep rx int enabled;
return;
}

my modification is:
disable rx int;
if (can call napi_schedule) {
call napi_schedule();
} else {
re-enable rx int; // this will de-assert interrupt pin for this time
return;
}

So my modification is: if we can call napi_schedule(), we will disable 
the rx int until the NAPI thread re-enable it. if we can't call 
napi_schedule(), the rx int will keep enabled. This logic is almost same 
as the original design. I can't figure out why original design is safe 
while my modification is risky.


Add more info:

the Freescale imx31pdk, imx51pdk and ti_omap3evm boards all use this 
driver, before apply this modification, their kgdboe connecting is not 
stable. After applied this patch, their nfs root is as good as before 
and their kgdboe connecting is stable.

Thanks,
Jason.
> You must solve your level triggered interrupt some other way, every
> NAPI based device must manage the interrupt disabling carefully and
> only when the napi POLL is successfully scheduled in order to avoid
> races.
>
> And especially you must not make a crazy hack like this for obscure
> things like kgdboe.
>
>   


^ permalink raw reply

* [PATCH net-next 1/2] bnx2: Free IRQ before freeing status block memory
From: Michael Chan @ 2010-12-24  2:21 UTC (permalink / raw)
  To: davem; +Cc: netdev

When changing ring size, we free all memory including status block
memory.  If we're in INTA mode and sharing IRQ, the IRQ handler can
be called and it will reference the NULL status block pointer.

Because of the lockless design of the IRQ handler, there is no simple
way to synchronize and prevent this.  So we avoid this problem by
freeing the IRQ handler before freeing the status block memory.

Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/bnx2.c |   13 ++++++++++++-
 1 files changed, 12 insertions(+), 1 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 6fa7984..44aed3b 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -6096,7 +6096,7 @@ bnx2_request_irq(struct bnx2 *bp)
 }
 
 static void
-bnx2_free_irq(struct bnx2 *bp)
+__bnx2_free_irq(struct bnx2 *bp)
 {
 	struct bnx2_irq *irq;
 	int i;
@@ -6107,6 +6107,13 @@ bnx2_free_irq(struct bnx2 *bp)
 			free_irq(irq->vector, &bp->bnx2_napi[i]);
 		irq->requested = 0;
 	}
+}
+
+static void
+bnx2_free_irq(struct bnx2 *bp)
+{
+
+	__bnx2_free_irq(bp);
 	if (bp->flags & BNX2_FLAG_USING_MSI)
 		pci_disable_msi(bp->pdev);
 	else if (bp->flags & BNX2_FLAG_USING_MSIX)
@@ -7092,6 +7099,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
 
 		bnx2_netif_stop(bp, true);
 		bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
+		__bnx2_free_irq(bp);
 		bnx2_free_skbs(bp);
 		bnx2_free_mem(bp);
 	}
@@ -7104,6 +7112,9 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
 
 		rc = bnx2_alloc_mem(bp);
 		if (!rc)
+			rc = bnx2_request_irq(bp);
+
+		if (!rc)
 			rc = bnx2_init_nic(bp, 0);
 
 		if (rc) {
-- 
1.6.4.GIT



^ permalink raw reply related

* [patch] skfp: testing the wrong variable in skfp_driver_init()
From: Dan Carpenter @ 2010-12-24  5:17 UTC (permalink / raw)
  To: netdev
  Cc: Jiri Pirko, Eric Dumazet, H Hartley Sweeten, David S. Miller,
	kernel-janitors

The intent here was to test if the allocation failed but we tested 
"SharedMemSize" instead of "SharedMemAddr" by mistake.

Signed-off-by: Dan Carpenter <error27@gmail.com>

diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index 0a66fed..16c6265 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -412,7 +412,7 @@ static  int skfp_driver_init(struct net_device *dev)
 		bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev,
 							 bp->SharedMemSize,
 							 &bp->SharedMemDMA);
-		if (!bp->SharedMemSize) {
+		if (!bp->SharedMemAddr) {
 			printk("could not allocate mem for ");
 			printk("hardware module: %ld byte\n",
 			       bp->SharedMemSize);

^ permalink raw reply related


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