Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 2/6] cnic: Unify IRQ code for all hardware types.
From: Michael Chan @ 2010-06-25  0:58 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1277427522-17306-1-git-send-email-mchan@broadcom.com>

By creating a common cnic_doirq().

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

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 23395fa..bd92a24 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -2188,6 +2188,9 @@ static void cnic_chk_pkt_rings(struct cnic_local *cp)
 	u16 tx_cons = *cp->tx_cons_ptr;
 	int comp = 0;
 
+	if (!test_bit(CNIC_F_CNIC_UP, &cp->dev->flags))
+		return;
+
 	if (cp->tx_cons != tx_cons || cp->rx_cons != rx_cons) {
 		if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags))
 			comp = cnic_l2_completion(cp);
@@ -2284,20 +2287,28 @@ done:
 		BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx);
 }
 
+static void cnic_doirq(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	u16 prod = cp->kcq_prod_idx & MAX_KCQ_IDX;
+
+	if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags))) {
+		prefetch(cp->status_blk.gen);
+		prefetch(&cp->kcq[KCQ_PG(prod)][KCQ_IDX(prod)]);
+
+		tasklet_schedule(&cp->cnic_irq_task);
+	}
+}
+
 static irqreturn_t cnic_irq(int irq, void *dev_instance)
 {
 	struct cnic_dev *dev = dev_instance;
 	struct cnic_local *cp = dev->cnic_priv;
-	u16 prod = cp->kcq_prod_idx & MAX_KCQ_IDX;
 
 	if (cp->ack_int)
 		cp->ack_int(dev);
 
-	prefetch(cp->status_blk.gen);
-	prefetch(&cp->kcq[KCQ_PG(prod)][KCQ_IDX(prod)]);
-
-	if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags)))
-		tasklet_schedule(&cp->cnic_irq_task);
+	cnic_doirq(dev);
 
 	return IRQ_HANDLED;
 }
@@ -2373,15 +2384,11 @@ static int cnic_service_bnx2x(void *data, void *status_blk)
 {
 	struct cnic_dev *dev = data;
 	struct cnic_local *cp = dev->cnic_priv;
-	u16 prod = cp->kcq_prod_idx & MAX_KCQ_IDX;
 
-	if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags))) {
-		prefetch(cp->status_blk.bnx2x);
-		prefetch(&cp->kcq[KCQ_PG(prod)][KCQ_IDX(prod)]);
+	if (!(cp->ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX))
+		cnic_doirq(dev);
 
-		tasklet_schedule(&cp->cnic_irq_task);
-		cnic_chk_pkt_rings(cp);
-	}
+	cnic_chk_pkt_rings(cp);
 
 	return 0;
 }
-- 
1.6.4.GIT



^ permalink raw reply related

* [PATCH net-next 3/6] cnic: Unify kcq allocation for all devices.
From: Michael Chan @ 2010-06-25  0:58 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1277427522-17306-2-git-send-email-mchan@broadcom.com>

By creating a common data stucture kcq_info for all devices, the kcq
(kernel completion queue) for all devices can be allocated by common
code.

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

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index bd92a24..948b25b 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -804,7 +804,7 @@ static void cnic_free_resc(struct cnic_dev *dev)
 	cnic_free_dma(dev, &cp->conn_buf_info);
 	cnic_free_dma(dev, &cp->kwq_info);
 	cnic_free_dma(dev, &cp->kwq_16_data_info);
-	cnic_free_dma(dev, &cp->kcq_info);
+	cnic_free_dma(dev, &cp->kcq1.dma);
 	kfree(cp->iscsi_tbl);
 	cp->iscsi_tbl = NULL;
 	kfree(cp->ctx_tbl);
@@ -863,6 +863,37 @@ static int cnic_alloc_context(struct cnic_dev *dev)
 	return 0;
 }
 
+static int cnic_alloc_kcq(struct cnic_dev *dev, struct kcq_info *info)
+{
+	int err, i, is_bnx2 = 0;
+	struct kcqe **kcq;
+
+	if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags))
+		is_bnx2 = 1;
+
+	err = cnic_alloc_dma(dev, &info->dma, KCQ_PAGE_CNT, is_bnx2);
+	if (err)
+		return err;
+
+	kcq = (struct kcqe **) info->dma.pg_arr;
+	info->kcq = kcq;
+
+	if (is_bnx2)
+		return 0;
+
+	for (i = 0; i < KCQ_PAGE_CNT; i++) {
+		struct bnx2x_bd_chain_next *next =
+			(struct bnx2x_bd_chain_next *) &kcq[i][MAX_KCQE_CNT];
+		int j = i + 1;
+
+		if (j >= KCQ_PAGE_CNT)
+			j = 0;
+		next->addr_hi = (u64) info->dma.pg_map_arr[j] >> 32;
+		next->addr_lo = info->dma.pg_map_arr[j] & 0xffffffff;
+	}
+	return 0;
+}
+
 static int cnic_alloc_l2_rings(struct cnic_dev *dev, int pages)
 {
 	struct cnic_local *cp = dev->cnic_priv;
@@ -954,10 +985,9 @@ static int cnic_alloc_bnx2_resc(struct cnic_dev *dev)
 		goto error;
 	cp->kwq = (struct kwqe **) cp->kwq_info.pg_arr;
 
-	ret = cnic_alloc_dma(dev, &cp->kcq_info, KCQ_PAGE_CNT, 1);
+	ret = cnic_alloc_kcq(dev, &cp->kcq1);
 	if (ret)
 		goto error;
-	cp->kcq = (struct kcqe **) cp->kcq_info.pg_arr;
 
 	ret = cnic_alloc_context(dev);
 	if (ret)
@@ -1076,22 +1106,9 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
 			j++;
 	}
 
-	ret = cnic_alloc_dma(dev, &cp->kcq_info, KCQ_PAGE_CNT, 0);
+	ret = cnic_alloc_kcq(dev, &cp->kcq1);
 	if (ret)
 		goto error;
-	cp->kcq = (struct kcqe **) cp->kcq_info.pg_arr;
-
-	for (i = 0; i < KCQ_PAGE_CNT; i++) {
-		struct bnx2x_bd_chain_next *next =
-			(struct bnx2x_bd_chain_next *)
-			&cp->kcq[i][MAX_KCQE_CNT];
-		int j = i + 1;
-
-		if (j >= KCQ_PAGE_CNT)
-			j = 0;
-		next->addr_hi = (u64) cp->kcq_info.pg_map_arr[j] >> 32;
-		next->addr_lo = cp->kcq_info.pg_map_arr[j] & 0xffffffff;
-	}
 
 	pages = PAGE_ALIGN(BNX2X_ISCSI_NUM_CONNECTIONS *
 			   BNX2X_ISCSI_CONN_BUF_SIZE) / PAGE_SIZE;
@@ -2135,7 +2152,7 @@ static int cnic_get_kcqes(struct cnic_dev *dev, u16 hw_prod, u16 *sw_prod)
 	ri &= MAX_KCQ_IDX;
 
 	while ((i != hw_prod) && (kcqe_cnt < MAX_COMPLETED_KCQE)) {
-		kcqe = &cp->kcq[KCQ_PG(ri)][KCQ_IDX(ri)];
+		kcqe = &cp->kcq1.kcq[KCQ_PG(ri)][KCQ_IDX(ri)];
 		cp->completed_kcq[kcqe_cnt++] = kcqe;
 		i = cp->next_idx(i);
 		ri = i & MAX_KCQ_IDX;
@@ -2219,7 +2236,7 @@ static int cnic_service_bnx2(void *data, void *status_blk)
 	cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
 
 	hw_prod = sblk->status_completion_producer_index;
-	sw_prod = cp->kcq_prod_idx;
+	sw_prod = cp->kcq1.sw_prod_idx;
 	while (sw_prod != hw_prod) {
 		kcqe_cnt = cnic_get_kcqes(dev, hw_prod, &sw_prod);
 		if (kcqe_cnt == 0)
@@ -2238,9 +2255,9 @@ static int cnic_service_bnx2(void *data, void *status_blk)
 	}
 
 done:
-	CNIC_WR16(dev, cp->kcq_io_addr, sw_prod);
+	CNIC_WR16(dev, cp->kcq1.io_addr, sw_prod);
 
-	cp->kcq_prod_idx = sw_prod;
+	cp->kcq1.sw_prod_idx = sw_prod;
 
 	cnic_chk_pkt_rings(cp);
 	return status_idx;
@@ -2258,7 +2275,7 @@ static void cnic_service_bnx2_msix(unsigned long data)
 	cp->kwq_con_idx = status_blk->status_cmd_consumer_index;
 
 	hw_prod = status_blk->status_completion_producer_index;
-	sw_prod = cp->kcq_prod_idx;
+	sw_prod = cp->kcq1.sw_prod_idx;
 	while (sw_prod != hw_prod) {
 		kcqe_cnt = cnic_get_kcqes(dev, hw_prod, &sw_prod);
 		if (kcqe_cnt == 0)
@@ -2277,8 +2294,8 @@ static void cnic_service_bnx2_msix(unsigned long data)
 	}
 
 done:
-	CNIC_WR16(dev, cp->kcq_io_addr, sw_prod);
-	cp->kcq_prod_idx = sw_prod;
+	CNIC_WR16(dev, cp->kcq1.io_addr, sw_prod);
+	cp->kcq1.sw_prod_idx = sw_prod;
 
 	cnic_chk_pkt_rings(cp);
 
@@ -2290,11 +2307,11 @@ done:
 static void cnic_doirq(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	u16 prod = cp->kcq_prod_idx & MAX_KCQ_IDX;
+	u16 prod = cp->kcq1.sw_prod_idx & MAX_KCQ_IDX;
 
 	if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags))) {
 		prefetch(cp->status_blk.gen);
-		prefetch(&cp->kcq[KCQ_PG(prod)][KCQ_IDX(prod)]);
+		prefetch(&cp->kcq1.kcq[KCQ_PG(prod)][KCQ_IDX(prod)]);
 
 		tasklet_schedule(&cp->cnic_irq_task);
 	}
@@ -2354,7 +2371,7 @@ static void cnic_service_bnx2x_bh(unsigned long data)
 
 	hw_prod = sblk->index_values[HC_INDEX_C_ISCSI_EQ_CONS];
 	hw_prod = cp->hw_idx(hw_prod);
-	sw_prod = cp->kcq_prod_idx;
+	sw_prod = cp->kcq1.sw_prod_idx;
 	while (sw_prod != hw_prod) {
 		kcqe_cnt = cnic_get_kcqes(dev, hw_prod, &sw_prod);
 		if (kcqe_cnt == 0)
@@ -2373,11 +2390,11 @@ static void cnic_service_bnx2x_bh(unsigned long data)
 	}
 
 done:
-	CNIC_WR16(dev, cp->kcq_io_addr, sw_prod + MAX_KCQ_IDX);
+	CNIC_WR16(dev, cp->kcq1.io_addr, sw_prod + MAX_KCQ_IDX);
 	cnic_ack_bnx2x_int(dev, cp->status_blk_num, CSTORM_ID,
 			   status_idx, IGU_INT_ENABLE, 1);
 
-	cp->kcq_prod_idx = sw_prod;
+	cp->kcq1.sw_prod_idx = sw_prod;
 }
 
 static int cnic_service_bnx2x(void *data, void *status_blk)
@@ -3711,7 +3728,7 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
 	struct cnic_local *cp = dev->cnic_priv;
 	struct cnic_eth_dev *ethdev = cp->ethdev;
 	struct status_block *sblk = cp->status_blk.gen;
-	u32 val;
+	u32 val, kcq_cid_addr, kwq_cid_addr;
 	int err;
 
 	cnic_set_bnx2_mac(dev);
@@ -3736,7 +3753,7 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
 	cnic_init_context(dev, KWQ_CID);
 	cnic_init_context(dev, KCQ_CID);
 
-	cp->kwq_cid_addr = GET_CID_ADDR(KWQ_CID);
+	kwq_cid_addr = GET_CID_ADDR(KWQ_CID);
 	cp->kwq_io_addr = MB_GET_CID_ADDR(KWQ_CID) + L5_KRNLQ_HOST_QIDX;
 
 	cp->max_kwq_idx = MAX_KWQ_IDX;
@@ -3752,50 +3769,58 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
 	/* Initialize the kernel work queue context. */
 	val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE |
 	      (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
-	cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_TYPE, val);
+	cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_TYPE, val);
 
 	val = (BCM_PAGE_SIZE / sizeof(struct kwqe) - 1) << 16;
-	cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
+	cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
 
 	val = ((BCM_PAGE_SIZE / sizeof(struct kwqe)) << 16) | KWQ_PAGE_CNT;
-	cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
+	cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
 
 	val = (u32) ((u64) cp->kwq_info.pgtbl_map >> 32);
-	cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_PGTBL_HADDR_HI, val);
+	cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_PGTBL_HADDR_HI, val);
 
 	val = (u32) cp->kwq_info.pgtbl_map;
-	cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_PGTBL_HADDR_LO, val);
+	cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_PGTBL_HADDR_LO, val);
+
+	kcq_cid_addr = GET_CID_ADDR(KCQ_CID);
+	cp->kcq1.io_addr = MB_GET_CID_ADDR(KCQ_CID) + L5_KRNLQ_HOST_QIDX;
 
-	cp->kcq_cid_addr = GET_CID_ADDR(KCQ_CID);
-	cp->kcq_io_addr = MB_GET_CID_ADDR(KCQ_CID) + L5_KRNLQ_HOST_QIDX;
+	cp->kcq1.sw_prod_idx = 0;
+	cp->kcq1.hw_prod_idx_ptr =
+		(u16 *) &sblk->status_completion_producer_index;
 
-	cp->kcq_prod_idx = 0;
+	cp->kcq1.status_idx_ptr = (u16 *) &sblk->status_idx;
 
 	/* Initialize the kernel complete queue context. */
 	val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE |
 	      (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
-	cnic_ctx_wr(dev, cp->kcq_cid_addr, L5_KRNLQ_TYPE, val);
+	cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_TYPE, val);
 
 	val = (BCM_PAGE_SIZE / sizeof(struct kcqe) - 1) << 16;
-	cnic_ctx_wr(dev, cp->kcq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
+	cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
 
 	val = ((BCM_PAGE_SIZE / sizeof(struct kcqe)) << 16) | KCQ_PAGE_CNT;
-	cnic_ctx_wr(dev, cp->kcq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
+	cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
 
-	val = (u32) ((u64) cp->kcq_info.pgtbl_map >> 32);
-	cnic_ctx_wr(dev, cp->kcq_cid_addr, L5_KRNLQ_PGTBL_HADDR_HI, val);
+	val = (u32) ((u64) cp->kcq1.dma.pgtbl_map >> 32);
+	cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_PGTBL_HADDR_HI, val);
 
-	val = (u32) cp->kcq_info.pgtbl_map;
-	cnic_ctx_wr(dev, cp->kcq_cid_addr, L5_KRNLQ_PGTBL_HADDR_LO, val);
+	val = (u32) cp->kcq1.dma.pgtbl_map;
+	cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_PGTBL_HADDR_LO, val);
 
 	cp->int_num = 0;
 	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
+		struct status_block_msix *msblk = cp->status_blk.bnx2;
 		u32 sb_id = cp->status_blk_num;
 		u32 sb = BNX2_L2CTX_L5_STATUSB_NUM(sb_id);
 
+		cp->kcq1.hw_prod_idx_ptr =
+			(u16 *) &msblk->status_completion_producer_index;
+		cp->kcq1.status_idx_ptr = (u16 *) &msblk->status_idx;
 		cp->int_num = sb_id << BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT;
-		cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_HOST_QIDX, sb);
-		cnic_ctx_wr(dev, cp->kcq_cid_addr, L5_KRNLQ_HOST_QIDX, sb);
+		cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_HOST_QIDX, sb);
+		cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_HOST_QIDX, sb);
 	}
 
 	/* Enable Commnad Scheduler notification when we write to the
@@ -4132,28 +4157,34 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
 	if (ret)
 		return -ENOMEM;
 
-	cp->kcq_io_addr = BAR_CSTRORM_INTMEM +
+	cp->kcq1.io_addr = BAR_CSTRORM_INTMEM +
 			  CSTORM_ISCSI_EQ_PROD_OFFSET(func, 0);
-	cp->kcq_prod_idx = 0;
+	cp->kcq1.sw_prod_idx = 0;
+
+	cp->kcq1.hw_prod_idx_ptr =
+		&cp->status_blk.bnx2x->c_status_block.index_values[
+			HC_INDEX_C_ISCSI_EQ_CONS];
+	cp->kcq1.status_idx_ptr =
+		&cp->status_blk.bnx2x->c_status_block.status_block_index;
 
 	cnic_get_bnx2x_iscsi_info(dev);
 
 	/* Only 1 EQ */
-	CNIC_WR16(dev, cp->kcq_io_addr, MAX_KCQ_IDX);
+	CNIC_WR16(dev, cp->kcq1.io_addr, MAX_KCQ_IDX);
 	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
 		CSTORM_ISCSI_EQ_CONS_OFFSET(func, 0), 0);
 	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
 		CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(func, 0),
-		cp->kcq_info.pg_map_arr[1] & 0xffffffff);
+		cp->kcq1.dma.pg_map_arr[1] & 0xffffffff);
 	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
 		CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(func, 0) + 4,
-		(u64) cp->kcq_info.pg_map_arr[1] >> 32);
+		(u64) cp->kcq1.dma.pg_map_arr[1] >> 32);
 	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
 		CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(func, 0),
-		cp->kcq_info.pg_map_arr[0] & 0xffffffff);
+		cp->kcq1.dma.pg_map_arr[0] & 0xffffffff);
 	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
 		CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(func, 0) + 4,
-		(u64) cp->kcq_info.pg_map_arr[0] >> 32);
+		(u64) cp->kcq1.dma.pg_map_arr[0] >> 32);
 	CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
 		CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(func, 0), 1);
 	CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
@@ -4381,7 +4412,7 @@ static void cnic_stop_bnx2x_hw(struct cnic_dev *dev)
 		  0);
 	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
 		CSTORM_ISCSI_EQ_CONS_OFFSET(cp->func, 0), 0);
-	CNIC_WR16(dev, cp->kcq_io_addr, 0);
+	CNIC_WR16(dev, cp->kcq1.io_addr, 0);
 	cnic_free_resc(dev);
 }
 
diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h
index b7e2f7f..275c361 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/cnic.h
@@ -169,6 +169,16 @@ struct cnic_context {
 	} proto;
 };
 
+struct kcq_info {
+	struct cnic_dma	dma;
+	struct kcqe	**kcq;
+
+	u16		*hw_prod_idx_ptr;
+	u16		sw_prod_idx;
+	u16		*status_idx_ptr;
+	u32		io_addr;
+};
+
 struct cnic_local {
 
 	spinlock_t cnic_ulp_lock;
@@ -202,9 +212,6 @@ struct cnic_local {
 	u16		rx_cons;
 	u16		tx_cons;
 
-	u32 kwq_cid_addr;
-	u32 kcq_cid_addr;
-
 	struct cnic_dma		kwq_info;
 	struct kwqe		**kwq;
 
@@ -218,11 +225,7 @@ struct cnic_local {
 	u16		*kwq_con_idx_ptr;
 	u16		kwq_con_idx;
 
-	struct cnic_dma	kcq_info;
-	struct kcqe	**kcq;
-
-	u16		kcq_prod_idx;
-	u32		kcq_io_addr;
+	struct kcq_info	kcq1;
 
 	union {
 		void				*gen;
-- 
1.6.4.GIT



^ permalink raw reply related

* [PATCH net-next 6/6] cnic: Update version to 2.1.3.
From: Michael Chan @ 2010-06-25  0:58 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1277427522-17306-5-git-send-email-mchan@broadcom.com>

---
 drivers/net/cnic_if.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h
index 0c55177..344c842 100644
--- a/drivers/net/cnic_if.h
+++ b/drivers/net/cnic_if.h
@@ -12,8 +12,8 @@
 #ifndef CNIC_IF_H
 #define CNIC_IF_H
 
-#define CNIC_MODULE_VERSION	"2.1.2"
-#define CNIC_MODULE_RELDATE	"May 26, 2010"
+#define CNIC_MODULE_VERSION	"2.1.3"
+#define CNIC_MODULE_RELDATE	"June 24, 2010"
 
 #define CNIC_ULP_RDMA		0
 #define CNIC_ULP_ISCSI		1
-- 
1.6.4.GIT



^ permalink raw reply related

* [PATCH net-next 1/6] cnic: Fine-tune CID memory space calculation.
From: Michael Chan @ 2010-06-25  0:58 UTC (permalink / raw)
  To: davem; +Cc: netdev

The current code makes assumptions about the CID (context ID) memory
space and starting CID that may not be always correct when firmware
changes.  In particular, BNX2_ISCSI_START_CID may not always be fixed.
We now calculate cp->max_cid_space and cp->iscsi_start_cid dynamically
instead of using fixed constants.  The unused cp->max_iscsi_conn is also
eliminated.

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

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index e5539f0..23395fa 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -257,7 +257,7 @@ static int cnic_get_l5_cid(struct cnic_local *cp, u32 cid, u32 *l5_cid)
 {
 	u32 i;
 
-	for (i = 0; i < MAX_ISCSI_TBL_SZ; i++) {
+	for (i = 0; i < cp->max_cid_space; i++) {
 		if (cp->ctx_tbl[i].cid == cid) {
 			*l5_cid = i;
 			return 0;
@@ -981,17 +981,10 @@ error:
 static int cnic_alloc_bnx2x_context(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
 	int ctx_blk_size = cp->ethdev->ctx_blk_size;
-	int total_mem, blks, i, cid_space;
-
-	if (BNX2X_ISCSI_START_CID < ethdev->starting_cid)
-		return -EINVAL;
-
-	cid_space = MAX_ISCSI_TBL_SZ +
-		    (BNX2X_ISCSI_START_CID - ethdev->starting_cid);
+	int total_mem, blks, i;
 
-	total_mem = BNX2X_CONTEXT_MEM_SIZE * cid_space;
+	total_mem = BNX2X_CONTEXT_MEM_SIZE * cp->max_cid_space;
 	blks = total_mem / ctx_blk_size;
 	if (total_mem % ctx_blk_size)
 		blks++;
@@ -1035,16 +1028,27 @@ static int cnic_alloc_bnx2x_context(struct cnic_dev *dev)
 static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+	u32 start_cid = ethdev->starting_cid;
 	int i, j, n, ret, pages;
 	struct cnic_dma *kwq_16_dma = &cp->kwq_16_data_info;
 
+	cp->max_cid_space = MAX_ISCSI_TBL_SZ;
+	cp->iscsi_start_cid = start_cid;
+	if (start_cid < BNX2X_ISCSI_START_CID) {
+		u32 delta = BNX2X_ISCSI_START_CID - start_cid;
+
+		cp->iscsi_start_cid = BNX2X_ISCSI_START_CID;
+		cp->max_cid_space += delta;
+	}
+
 	cp->iscsi_tbl = kzalloc(sizeof(struct cnic_iscsi) * MAX_ISCSI_TBL_SZ,
 				GFP_KERNEL);
 	if (!cp->iscsi_tbl)
 		goto error;
 
 	cp->ctx_tbl = kzalloc(sizeof(struct cnic_context) *
-				  MAX_CNIC_L5_CONTEXT, GFP_KERNEL);
+				cp->max_cid_space, GFP_KERNEL);
 	if (!cp->ctx_tbl)
 		goto error;
 
@@ -1053,7 +1057,7 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
 		cp->ctx_tbl[i].ulp_proto_id = CNIC_ULP_ISCSI;
 	}
 
-	pages = PAGE_ALIGN(MAX_CNIC_L5_CONTEXT * CNIC_KWQ16_DATA_SIZE) /
+	pages = PAGE_ALIGN(cp->max_cid_space * CNIC_KWQ16_DATA_SIZE) /
 		PAGE_SIZE;
 
 	ret = cnic_alloc_dma(dev, kwq_16_dma, pages, 0);
@@ -1061,7 +1065,7 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
 		return -ENOMEM;
 
 	n = PAGE_SIZE / CNIC_KWQ16_DATA_SIZE;
-	for (i = 0, j = 0; i < MAX_ISCSI_TBL_SZ; i++) {
+	for (i = 0, j = 0; i < cp->max_cid_space; i++) {
 		long off = CNIC_KWQ16_DATA_SIZE * (i % n);
 
 		cp->ctx_tbl[i].kwqe_data = kwq_16_dma->pg_arr[j] + off;
@@ -4116,7 +4120,7 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
 	u8 sb_id = cp->status_blk_num;
 
 	ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ,
-			       BNX2X_ISCSI_START_CID);
+			       cp->iscsi_start_cid);
 
 	if (ret)
 		return -ENOMEM;
diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h
index 08b1235..b7e2f7f 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/cnic.h
@@ -248,8 +248,10 @@ struct cnic_local {
 	struct cnic_iscsi	*iscsi_tbl;
 	struct cnic_context	*ctx_tbl;
 	struct cnic_id_tbl	cid_tbl;
-	int			max_iscsi_conn;
 	atomic_t		iscsi_conn;
+	u32			iscsi_start_cid;
+
+	u32			max_cid_space;
 
 	/* per connection parameters */
 	int			num_iscsi_tasks;
-- 
1.6.4.GIT



^ permalink raw reply related

* [PATCH net-next 4/6] cnic: Restructure kcq processing.
From: Michael Chan @ 2010-06-25  0:58 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1277427522-17306-3-git-send-email-mchan@broadcom.com>

By doing more work in the common function cnic_get_kcqes(), and
making full use of the kcq_info structure.

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

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 948b25b..8c41fe0 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -2141,18 +2141,20 @@ static u16 cnic_bnx2x_hw_idx(u16 idx)
 	return idx;
 }
 
-static int cnic_get_kcqes(struct cnic_dev *dev, u16 hw_prod, u16 *sw_prod)
+static int cnic_get_kcqes(struct cnic_dev *dev, struct kcq_info *info)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	u16 i, ri, last;
+	u16 i, ri, hw_prod, last;
 	struct kcqe *kcqe;
 	int kcqe_cnt = 0, last_cnt = 0;
 
-	i = ri = last = *sw_prod;
+	i = ri = last = info->sw_prod_idx;
 	ri &= MAX_KCQ_IDX;
+	hw_prod = *info->hw_prod_idx_ptr;
+	hw_prod = cp->hw_idx(hw_prod);
 
 	while ((i != hw_prod) && (kcqe_cnt < MAX_COMPLETED_KCQE)) {
-		kcqe = &cp->kcq1.kcq[KCQ_PG(ri)][KCQ_IDX(ri)];
+		kcqe = &info->kcq[KCQ_PG(ri)][KCQ_IDX(ri)];
 		cp->completed_kcq[kcqe_cnt++] = kcqe;
 		i = cp->next_idx(i);
 		ri = i & MAX_KCQ_IDX;
@@ -2162,7 +2164,7 @@ static int cnic_get_kcqes(struct cnic_dev *dev, u16 hw_prod, u16 *sw_prod)
 		}
 	}
 
-	*sw_prod = last;
+	info->sw_prod_idx = last;
 	return last_cnt;
 }
 
@@ -2224,10 +2226,8 @@ static void cnic_chk_pkt_rings(struct cnic_local *cp)
 static int cnic_service_bnx2(void *data, void *status_blk)
 {
 	struct cnic_dev *dev = data;
-	struct status_block *sblk = status_blk;
 	struct cnic_local *cp = dev->cnic_priv;
-	u32 status_idx = sblk->status_idx;
-	u16 hw_prod, sw_prod;
+	u32 status_idx = *cp->kcq1.status_idx_ptr;
 	int kcqe_cnt;
 
 	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags)))
@@ -2235,29 +2235,20 @@ static int cnic_service_bnx2(void *data, void *status_blk)
 
 	cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
 
-	hw_prod = sblk->status_completion_producer_index;
-	sw_prod = cp->kcq1.sw_prod_idx;
-	while (sw_prod != hw_prod) {
-		kcqe_cnt = cnic_get_kcqes(dev, hw_prod, &sw_prod);
-		if (kcqe_cnt == 0)
-			goto done;
+	while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) {
 
 		service_kcqes(dev, kcqe_cnt);
 
 		/* Tell compiler that status_blk fields can change. */
 		barrier();
-		if (status_idx != sblk->status_idx) {
-			status_idx = sblk->status_idx;
+		if (status_idx != *cp->kcq1.status_idx_ptr) {
+			status_idx = *cp->kcq1.status_idx_ptr;
 			cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
-			hw_prod = sblk->status_completion_producer_index;
 		} else
 			break;
 	}
 
-done:
-	CNIC_WR16(dev, cp->kcq1.io_addr, sw_prod);
-
-	cp->kcq1.sw_prod_idx = sw_prod;
+	CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx);
 
 	cnic_chk_pkt_rings(cp);
 	return status_idx;
@@ -2268,34 +2259,25 @@ static void cnic_service_bnx2_msix(unsigned long data)
 	struct cnic_dev *dev = (struct cnic_dev *) data;
 	struct cnic_local *cp = dev->cnic_priv;
 	struct status_block_msix *status_blk = cp->status_blk.bnx2;
-	u32 status_idx = status_blk->status_idx;
-	u16 hw_prod, sw_prod;
+	u32 status_idx = *cp->kcq1.status_idx_ptr;
 	int kcqe_cnt;
 
 	cp->kwq_con_idx = status_blk->status_cmd_consumer_index;
 
-	hw_prod = status_blk->status_completion_producer_index;
-	sw_prod = cp->kcq1.sw_prod_idx;
-	while (sw_prod != hw_prod) {
-		kcqe_cnt = cnic_get_kcqes(dev, hw_prod, &sw_prod);
-		if (kcqe_cnt == 0)
-			goto done;
+	while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) {
 
 		service_kcqes(dev, kcqe_cnt);
 
 		/* Tell compiler that status_blk fields can change. */
 		barrier();
-		if (status_idx != status_blk->status_idx) {
-			status_idx = status_blk->status_idx;
+		if (status_idx != *cp->kcq1.status_idx_ptr) {
+			status_idx = *cp->kcq1.status_idx_ptr;
 			cp->kwq_con_idx = status_blk->status_cmd_consumer_index;
-			hw_prod = status_blk->status_completion_producer_index;
 		} else
 			break;
 	}
 
-done:
-	CNIC_WR16(dev, cp->kcq1.io_addr, sw_prod);
-	cp->kcq1.sw_prod_idx = sw_prod;
+	CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx);
 
 	cnic_chk_pkt_rings(cp);
 
@@ -2360,41 +2342,27 @@ static void cnic_service_bnx2x_bh(unsigned long data)
 {
 	struct cnic_dev *dev = (struct cnic_dev *) data;
 	struct cnic_local *cp = dev->cnic_priv;
-	u16 hw_prod, sw_prod;
-	struct cstorm_status_block_c *sblk =
-		&cp->status_blk.bnx2x->c_status_block;
-	u32 status_idx = sblk->status_block_index;
+	u32 status_idx = *cp->kcq1.status_idx_ptr;
 	int kcqe_cnt;
 
 	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags)))
 		return;
 
-	hw_prod = sblk->index_values[HC_INDEX_C_ISCSI_EQ_CONS];
-	hw_prod = cp->hw_idx(hw_prod);
-	sw_prod = cp->kcq1.sw_prod_idx;
-	while (sw_prod != hw_prod) {
-		kcqe_cnt = cnic_get_kcqes(dev, hw_prod, &sw_prod);
-		if (kcqe_cnt == 0)
-			goto done;
+	while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) {
 
 		service_kcqes(dev, kcqe_cnt);
 
 		/* Tell compiler that sblk fields can change. */
 		barrier();
-		if (status_idx == sblk->status_block_index)
+		if (status_idx == *cp->kcq1.status_idx_ptr)
 			break;
 
-		status_idx = sblk->status_block_index;
-		hw_prod = sblk->index_values[HC_INDEX_C_ISCSI_EQ_CONS];
-		hw_prod = cp->hw_idx(hw_prod);
+		status_idx = *cp->kcq1.status_idx_ptr;
 	}
 
-done:
-	CNIC_WR16(dev, cp->kcq1.io_addr, sw_prod + MAX_KCQ_IDX);
+	CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx + MAX_KCQ_IDX);
 	cnic_ack_bnx2x_int(dev, cp->status_blk_num, CSTORM_ID,
 			   status_idx, IGU_INT_ENABLE, 1);
-
-	cp->kcq1.sw_prod_idx = sw_prod;
 }
 
 static int cnic_service_bnx2x(void *data, void *status_blk)
-- 
1.6.4.GIT



^ permalink raw reply related

* [PATCH net-next 5/6] cnic: Further unify kcq handling code.
From: Michael Chan @ 2010-06-25  0:58 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1277427522-17306-4-git-send-email-mchan@broadcom.com>

This eliminates some of the duplicate code for the various devices
that require the same basic kcq handling.

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

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 8c41fe0..c0cc0d8 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -2223,16 +2223,12 @@ static void cnic_chk_pkt_rings(struct cnic_local *cp)
 		clear_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags);
 }
 
-static int cnic_service_bnx2(void *data, void *status_blk)
+static u32 cnic_service_bnx2_queues(struct cnic_dev *dev)
 {
-	struct cnic_dev *dev = data;
 	struct cnic_local *cp = dev->cnic_priv;
-	u32 status_idx = *cp->kcq1.status_idx_ptr;
+	u32 status_idx = (u16) *cp->kcq1.status_idx_ptr;
 	int kcqe_cnt;
 
-	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags)))
-		return status_idx;
-
 	cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
 
 	while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) {
@@ -2242,7 +2238,7 @@ static int cnic_service_bnx2(void *data, void *status_blk)
 		/* Tell compiler that status_blk fields can change. */
 		barrier();
 		if (status_idx != *cp->kcq1.status_idx_ptr) {
-			status_idx = *cp->kcq1.status_idx_ptr;
+			status_idx = (u16) *cp->kcq1.status_idx_ptr;
 			cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
 		} else
 			break;
@@ -2251,37 +2247,29 @@ static int cnic_service_bnx2(void *data, void *status_blk)
 	CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx);
 
 	cnic_chk_pkt_rings(cp);
+
 	return status_idx;
 }
 
-static void cnic_service_bnx2_msix(unsigned long data)
+static int cnic_service_bnx2(void *data, void *status_blk)
 {
-	struct cnic_dev *dev = (struct cnic_dev *) data;
+	struct cnic_dev *dev = data;
 	struct cnic_local *cp = dev->cnic_priv;
-	struct status_block_msix *status_blk = cp->status_blk.bnx2;
 	u32 status_idx = *cp->kcq1.status_idx_ptr;
-	int kcqe_cnt;
-
-	cp->kwq_con_idx = status_blk->status_cmd_consumer_index;
 
-	while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) {
-
-		service_kcqes(dev, kcqe_cnt);
+	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags)))
+		return status_idx;
 
-		/* Tell compiler that status_blk fields can change. */
-		barrier();
-		if (status_idx != *cp->kcq1.status_idx_ptr) {
-			status_idx = *cp->kcq1.status_idx_ptr;
-			cp->kwq_con_idx = status_blk->status_cmd_consumer_index;
-		} else
-			break;
-	}
+	return cnic_service_bnx2_queues(dev);
+}
 
-	CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx);
+static void cnic_service_bnx2_msix(unsigned long data)
+{
+	struct cnic_dev *dev = (struct cnic_dev *) data;
+	struct cnic_local *cp = dev->cnic_priv;
 
-	cnic_chk_pkt_rings(cp);
+	cp->last_status_idx = cnic_service_bnx2_queues(dev);
 
-	cp->last_status_idx = status_idx;
 	CNIC_WR(dev, BNX2_PCICFG_INT_ACK_CMD, cp->int_num |
 		BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx);
 }
@@ -2338,27 +2326,35 @@ static void cnic_ack_bnx2x_msix(struct cnic_dev *dev)
 			   IGU_INT_DISABLE, 0);
 }
 
-static void cnic_service_bnx2x_bh(unsigned long data)
+static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info)
 {
-	struct cnic_dev *dev = (struct cnic_dev *) data;
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 status_idx = *cp->kcq1.status_idx_ptr;
+	u32 last_status = *info->status_idx_ptr;
 	int kcqe_cnt;
 
-	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags)))
-		return;
-
-	while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) {
+	while ((kcqe_cnt = cnic_get_kcqes(dev, info))) {
 
 		service_kcqes(dev, kcqe_cnt);
 
 		/* Tell compiler that sblk fields can change. */
 		barrier();
-		if (status_idx == *cp->kcq1.status_idx_ptr)
+		if (last_status == *info->status_idx_ptr)
 			break;
 
-		status_idx = *cp->kcq1.status_idx_ptr;
+		last_status = *info->status_idx_ptr;
 	}
+	return last_status;
+}
+
+static void cnic_service_bnx2x_bh(unsigned long data)
+{
+	struct cnic_dev *dev = (struct cnic_dev *) data;
+	struct cnic_local *cp = dev->cnic_priv;
+	u32 status_idx;
+
+	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags)))
+		return;
+
+	status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq1);
 
 	CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx + MAX_KCQ_IDX);
 	cnic_ack_bnx2x_int(dev, cp->status_blk_num, CSTORM_ID,
@@ -3786,6 +3782,7 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
 		cp->kcq1.hw_prod_idx_ptr =
 			(u16 *) &msblk->status_completion_producer_index;
 		cp->kcq1.status_idx_ptr = (u16 *) &msblk->status_idx;
+		cp->kwq_con_idx_ptr = (u16 *) &msblk->status_cmd_consumer_index;
 		cp->int_num = sb_id << BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT;
 		cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_HOST_QIDX, sb);
 		cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_HOST_QIDX, sb);
-- 
1.6.4.GIT



^ permalink raw reply related

* RE: [RFC PATCH v7 01/19] Add a new structure for skb buffer from external.
From: Dong, Eddie @ 2010-06-25  1:03 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Xin, Xiaohui, Stephen Hemminger, netdev@vger.kernel.org,
	kvm@vger.kernel.org, linux-kernel@vger.kernel.org, mst@redhat.com,
	mingo@elte.hu, davem@davemloft.net, jdike@linux.intel.com,
	Dong, Eddie, Dong, Eddie
In-Reply-To: <20100624100836.GA16220@gondor.apana.org.au>

Herbert Xu wrote:
> On Wed, Jun 23, 2010 at 06:05:41PM +0800, Dong, Eddie wrote:
>> 
>> I mean once the frontend side driver post the buffers to the backend
>> driver, the backend driver will "immediately" use that buffers to
>> compose skb or gro_frags and post them to the assigned host NIC
>> driver as receive buffers. In that case, if the backend driver
>> recieves a packet from the NIC that requires to do copy, it may be
>> unable to find additional free guest buffer because all of them are
>> already used by the NIC driver. We have to reserve some guest
>> buffers for the possible copy even if the buffer address is not
>> identified by original skb :(        
> 
> OK I see what you mean.  Can you tell me how does Xiaohui's
> previous patch-set deal with this problem?
> 
> Thanks,

In current patch, each SKB for the assigned device (SRIOV VF or NIC or a complete queue pairs) uses the buffer from guest, so it eliminates copy completely in software and requires hardware to do so. If we can have an additonal place to store the buffer per skb (may cause copy later on), we can do copy later on or re-post the buffer to assigned NIC driver later on. But that may be not very clean either :(

BTW, some hardware may require certain level of packet copy such as for broadcast packets in very old VMDq device, which is not addressed in previous Xiaohui's patch yet. We may address this by implementing an additional virtqueue between guest and host for slow path (broadcast packets only here) with additinal complexity in FE/BE driver. 

Thx, Eddie

^ permalink raw reply

* Re: [PATCH 6/8] netpoll: Allow netpoll_setup/cleanup recursion
From: Andrew Morton @ 2010-06-25  1:21 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Michael S. Tsirkin, Qianfeng Zhang, David S. Miller, netdev,
	WANG Cong, Stephen Hemminger, Matt Mackall, Paul E. McKenney,
	Peter Zijlstra, Ingo Molnar
In-Reply-To: <E1OMtjk-0006P2-6r@gondolin.me.apana.org.au>

On Fri, 11 Jun 2010 12:12:48 +1000
Herbert Xu <herbert@gondor.hengli.com.au> wrote:

> netpoll: Allow netpoll_setup/cleanup recursion
> 
> This patch adds the functions __netpoll_setup/__netpoll_cleanup
> which is designed to be called recursively through ndo_netpoll_seutp.
> 
> They must be called with RTNL held, and the caller must initialise
> np->dev and ensure that it has a valid reference count.
> 
> ...
>
> -int netpoll_setup(struct netpoll *np)
> +int __netpoll_setup(struct netpoll *np)
>  {
> -	struct net_device *ndev = NULL;
> -	struct in_device *in_dev;
> +	struct net_device *ndev = np->dev;
>  	struct netpoll_info *npinfo;
>  	const struct net_device_ops *ops;
>  	unsigned long flags;
>  	int err;
>  
> +	if ((ndev->priv_flags & IFF_DISABLE_NETPOLL) ||
> +	    !ndev->netdev_ops->ndo_poll_controller) {
> +		printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
> +		       np->name, np->dev_name);
> +		err = -ENOTSUPP;
> +		goto out;
> +	}
> +
> +	if (!ndev->npinfo) {
> +		npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);
> +		if (!npinfo) {
> +			err = -ENOMEM;
> +			goto out;
> +		}
> +
> +		npinfo->rx_flags = 0;
> +		INIT_LIST_HEAD(&npinfo->rx_np);
> +
> +		spin_lock_init(&npinfo->rx_lock);
> +		skb_queue_head_init(&npinfo->arp_tx);
> +		skb_queue_head_init(&npinfo->txq);
> +		INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);
> +
> +		atomic_set(&npinfo->refcnt, 1);
> +
> +		ops = np->dev->netdev_ops;
> +		if (ops->ndo_netpoll_setup) {
> +			err = ops->ndo_netpoll_setup(ndev, npinfo);
> +			if (err)
> +				goto free_npinfo;
> +		}
> +	} else {
> +		npinfo = ndev->npinfo;
> +		atomic_inc(&npinfo->refcnt);
> +	}
> +
> +	npinfo->netpoll = np;
> +
> +	if (np->rx_hook) {
> +		spin_lock_irqsave(&npinfo->rx_lock, flags);
> +		npinfo->rx_flags |= NETPOLL_RX_ENABLED;
> +		list_add_tail(&np->rx, &npinfo->rx_np);
> +		spin_unlock_irqrestore(&npinfo->rx_lock, flags);
> +	}
> +
> +	/* last thing to do is link it to the net device structure */
> +	rcu_assign_pointer(ndev->npinfo, npinfo);
> +	rtnl_unlock();

And there it is, an unbalanced rtnl_unlock().

This stupid little thing took me over a day's work to find - it's just
been awful.

The user-visible symptom was that a bug in the netpoll code causes the
machine to hang after loading ipv6 (!), because
addrconf_fixup_forwarding()'s rtnl_trylock() kept on failing, and the
restart_syscall() kept on getting restarted, so an initscripts procfs
write just kept banging its head against the excessively-unlocked
mutex.

The mutex code handles an excessively-unlocked mutex (mutex.count==2)
really badly.  Some API functions say "its locked", others say "it
isn't", etc.

Maybe it's better with mutex debugging enabled - didn't try that. 
Things get pretty user-unfriendly when there's a bug within the
netconsole code itself.

Enabling lockdep simply made the bug cure itself - I suspect the mutex
code's handling of mutexes is different if lockdep is enabled.  That
would be pretty bad behaviour from the lockdep code.

I just removed the rtnl_unlock() - I couldn't see much in there which
needed rtnl_locking..

Dave, the fixup should be folded into the original patch please -
otherwise we'll have a machine-hangs-up bisection hole which spans two
weeks work of commits.


^ permalink raw reply

* Re: [PATCH] smsc95xx: Add module parameter to override MAC address
From: Simon Horman @ 2010-06-25  1:25 UTC (permalink / raw)
  To: Sebastien Jan; +Cc: Steve Glendinning, netdev, linux-omap
In-Reply-To: <1277367254-9345-1-git-send-email-s-jan@ti.com>

On Thu, Jun 24, 2010 at 10:14:14AM +0200, Sebastien Jan wrote:
> Define a new module parameter 'macaddr' to override the MAC address
> fetched either from eeprom, or randomly generated.
> 
> The expected MAC address shall be in the 01:23:45:67:89:AB format.

I'm confused as to why this is desirable when the mac address
can already be configured after module insertion via
smsc95xx_netdev_ops.eth_mac_addr().


^ permalink raw reply

* RE: [RFC PATCH v7 01/19] Add a new structure for skb buffer from external.
From: Xin, Xiaohui @ 2010-06-25  2:07 UTC (permalink / raw)
  To: Herbert Xu, Dong, Eddie
  Cc: Stephen Hemminger, netdev@vger.kernel.org, kvm@vger.kernel.org,
	linux-kernel@vger.kernel.org, mst@redhat.com, mingo@elte.hu,
	davem@davemloft.net, jdike@linux.intel.com
In-Reply-To: <20100624100836.GA16220@gondor.apana.org.au>

Herbert,
That's why I have sent you the patch for guest virtio-net driver. I reserved 512 bytes in each page, then I can always have the space to copy and avoid the backend memory used up issue.

Thanks
Xiaohui

>-----Original Message-----
>From: Herbert Xu [mailto:herbert@gondor.apana.org.au]
>Sent: Thursday, June 24, 2010 6:09 PM
>To: Dong, Eddie
>Cc: Xin, Xiaohui; Stephen Hemminger; netdev@vger.kernel.org; kvm@vger.kernel.org;
>linux-kernel@vger.kernel.org; mst@redhat.com; mingo@elte.hu; davem@davemloft.net;
>jdike@linux.intel.com
>Subject: Re: [RFC PATCH v7 01/19] Add a new structure for skb buffer from external.
>
>On Wed, Jun 23, 2010 at 06:05:41PM +0800, Dong, Eddie wrote:
>>
>> I mean once the frontend side driver post the buffers to the backend driver, the backend
>driver will "immediately" use that buffers to compose skb or gro_frags and post them to the
>assigned host NIC driver as receive buffers. In that case, if the backend driver recieves a
>packet from the NIC that requires to do copy, it may be unable to find additional free guest
>buffer because all of them are already used by the NIC driver. We have to reserve some guest
>buffers for the possible copy even if the buffer address is not identified by original skb :(
>
>OK I see what you mean.  Can you tell me how does Xiaohui's
>previous patch-set deal with this problem?
>
>Thanks,
>--
>Visit Openswan at http://www.openswan.org/
>Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
>Home Page: http://gondor.apana.org.au/~herbert/
>PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH v3] act_mirred: don't clone skb when skb isn't shared
From: Changli Gao @ 2010-06-25  2:25 UTC (permalink / raw)
  To: Jamal Hadi Salim; +Cc: David S. Miller, netdev, Changli Gao

don't clone skb when skb isn't shared

When the tcf_action is TC_ACT_STOLEN, and the skb isn't shared, we don't need
to clone a new skb. As the skb will be freed after this function returns, we
can use it freely once we get a reference to it.

Signed-off-by: Changli Gao <xiaosuo@gmail.com>
----
 include/net/sch_generic.h |   11 +++++++++--
 net/sched/act_mirred.c    |    6 +++---
 2 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index b35301b..977ec06 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -594,9 +594,16 @@ static inline u32 qdisc_l2t(struct qdisc_rate_table* rtab, unsigned int pktlen)
 }
 
 #ifdef CONFIG_NET_CLS_ACT
-static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask)
+static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask,
+					    int action)
 {
-	struct sk_buff *n = skb_clone(skb, gfp_mask);
+	struct sk_buff *n;
+
+	if ((action == TC_ACT_STOLEN || action == TC_ACT_QUEUED) &&
+	    !skb_shared(skb))
+		n = skb_get(skb);
+	else
+		n = skb_clone(skb, gfp_mask);
 
 	if (n) {
 		n->tc_verd = SET_TC_VERD(n->tc_verd, 0);
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index c0b6863..2e9a7b9 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -169,13 +169,13 @@ static int tcf_mirred(struct sk_buff *skb, struct tc_action *a,
 		goto out;
 	}
 
-	skb2 = skb_act_clone(skb, GFP_ATOMIC);
+	at = G_TC_AT(skb->tc_verd);
+	skb2 = skb_act_clone(skb, GFP_ATOMIC, m->tcf_action);
 	if (skb2 == NULL)
 		goto out;
 
 	m->tcf_bstats.bytes += qdisc_pkt_len(skb2);
 	m->tcf_bstats.packets++;
-	at = G_TC_AT(skb->tc_verd);
 	if (!(at & AT_EGRESS)) {
 		if (m->tcfm_ok_push)
 			skb_push(skb2, skb2->dev->hard_header_len);
@@ -185,8 +185,8 @@ static int tcf_mirred(struct sk_buff *skb, struct tc_action *a,
 	if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
 		skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at);
 
-	skb2->dev = dev;
 	skb2->skb_iif = skb->dev->ifindex;
+	skb2->dev = dev;
 	dev_queue_xmit(skb2);
 	err = 0;
 

^ permalink raw reply related

* Re: [PATCH net-next] MAINTAINERS: b43 updates
From: Larry Finger @ 2010-06-25  2:41 UTC (permalink / raw)
  To: Joe Perches
  Cc: John W. Linville, Stefano Brivio,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, mb-fseUSCV1ubazQB+pC5nmwQ,
	zajec5-Re5JQEeQqe8AvxtiuMwx3w, Gábor Stefanik,
	Rafał Miłecki
In-Reply-To: <1277423829.1654.111.camel-AkRN8/LKpobuYGix6ZUp1Q@public.gmane.org>

On 06/24/2010 06:57 PM, Joe Perches wrote:
> On Thu, 2010-06-24 at 18:53 -0500, Larry Finger wrote:
>> I never said that b43 is unmaintained. It is definitely getting much
>> more than "odd fixes".
> 
> If Stefano isn't maintaining it, who is?

We are working on that.

Larry
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v2] fragment: add fast path
From: Changli Gao @ 2010-06-25  2:54 UTC (permalink / raw)
  To: David Miller
  Cc: Alexey Kuznetsov, Pekka Savola (ipv6), James Morris,
	Hideaki YOSHIFUJI, Patrick McHardy, Eric Dumazet, netdev,
	Mitchell Erblich, Changli Gao

add fast path

As the fragments are sent in order in most of OSes, such as Windows, Darwin and
FreeBSD, it is likely the new fragments are at the end of the inet_frag_queue.
In the fast path, we check if the skb at the end of the inet_frag_queue is the
prev we expect.

Signed-off-by: Changli Gao <xiaosuo@gmail.com>
----
 include/net/inet_frag.h |    1 +
 net/ipv4/ip_fragment.c  |   12 ++++++++++++
 net/ipv6/reassembly.c   |   11 +++++++++++
 3 files changed, 24 insertions(+)
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
index 39f2dc9..16ff29a 100644
--- a/include/net/inet_frag.h
+++ b/include/net/inet_frag.h
@@ -20,6 +20,7 @@ struct inet_frag_queue {
 	atomic_t		refcnt;
 	struct timer_list	timer;      /* when will this queue expire? */
 	struct sk_buff		*fragments; /* list of received fragments */
+	struct sk_buff		*fragments_tail;
 	ktime_t			stamp;
 	int			len;        /* total length of orig datagram */
 	int			meat;
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 858d346..dbe8999 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -314,6 +314,7 @@ static int ip_frag_reinit(struct ipq *qp)
 	qp->q.len = 0;
 	qp->q.meat = 0;
 	qp->q.fragments = NULL;
+	qp->q.fragments_tail = NULL;
 	qp->iif = 0;
 
 	return 0;
@@ -386,6 +387,11 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
 	 * in the chain of fragments so far.  We must know where to put
 	 * this fragment, right?
 	 */
+	prev = qp->q.fragments_tail;
+	if (!prev || FRAG_CB(prev)->offset < offset) {
+			next = NULL;
+			goto found;
+	}
 	prev = NULL;
 	for (next = qp->q.fragments; next != NULL; next = next->next) {
 		if (FRAG_CB(next)->offset >= offset)
@@ -393,6 +399,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
 		prev = next;
 	}
 
+found:
 	/* We found where to put this one.  Check for overlap with
 	 * preceding fragment, and, if needed, align things so that
 	 * any overlaps are eliminated.
@@ -451,6 +458,8 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
 
 	/* Insert this fragment in the chain of fragments. */
 	skb->next = next;
+	if (!next)
+		qp->q.fragments_tail = skb;
 	if (prev)
 		prev->next = skb;
 	else
@@ -504,6 +513,8 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
 			goto out_nomem;
 
 		fp->next = head->next;
+		if (!fp->next)
+			qp->q.fragments_tail = fp;
 		prev->next = fp;
 
 		skb_morph(head, qp->q.fragments);
@@ -574,6 +585,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
 	iph->tot_len = htons(len);
 	IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS);
 	qp->q.fragments = NULL;
+	qp->q.fragments_tail = NULL;
 	return 0;
 
 out_nomem:
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 0b97230..b832f7b 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -333,6 +333,11 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
 	 * in the chain of fragments so far.  We must know where to put
 	 * this fragment, right?
 	 */
+	prev = fq->q.fragments_tail;
+	if (!prev || FRAG6_CB(prev)->offset < offset) {
+			next = NULL;
+			goto found;
+	}
 	prev = NULL;
 	for(next = fq->q.fragments; next != NULL; next = next->next) {
 		if (FRAG6_CB(next)->offset >= offset)
@@ -340,6 +345,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
 		prev = next;
 	}
 
+found:
 	/* We found where to put this one.  Check for overlap with
 	 * preceding fragment, and, if needed, align things so that
 	 * any overlaps are eliminated.
@@ -397,6 +403,8 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
 
 	/* Insert this fragment in the chain of fragments. */
 	skb->next = next;
+	if (!next)
+		fq->q.fragments_tail = skb;
 	if (prev)
 		prev->next = skb;
 	else
@@ -463,6 +471,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
 			goto out_oom;
 
 		fp->next = head->next;
+		if (!fp->next)
+			fq->q.fragments_tail = fp;
 		prev->next = fp;
 
 		skb_morph(head, fq->q.fragments);
@@ -549,6 +559,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
 	IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS);
 	rcu_read_unlock();
 	fq->q.fragments = NULL;
+	fq->q.fragments_tail = NULL;
 	return 1;
 
 out_oversize:

^ permalink raw reply related

* Re: + fix-netpoll-allow-netpoll_setup-cleanup-recursion.patch added to -mm tree
From: Herbert Xu @ 2010-06-25  3:00 UTC (permalink / raw)
  To: akpm; +Cc: mm-commits, davem, netdev
In-Reply-To: <201006250121.o5P1La69008693@imap1.linux-foundation.org>

On Thu, Jun 24, 2010 at 05:52:47PM -0700, akpm@linux-foundation.org wrote:
> 
> The patch titled
>      fix "netpoll: Allow netpoll_setup/cleanup recursion"
> has been added to the -mm tree.  Its filename is
>      fix-netpoll-allow-netpoll_setup-cleanup-recursion.patch
> 
> Before you just go and hit "reply", please:
>    a) Consider who else should be cc'ed
>    b) Prefer to cc a suitable mailing list as well
>    c) Ideally: find the original patch on the mailing list and do a
>       reply-to-all to that, adding suitable additional cc's
> 
> *** Remember to use Documentation/SubmitChecklist when testing your code ***
> 
> See http://userweb.kernel.org/~akpm/stuff/added-to-mm.txt to find
> out what to do about this
> 
> The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/
> 
> ------------------------------------------------------
> Subject: fix "netpoll: Allow netpoll_setup/cleanup recursion"
> From: Andrew Morton <akpm@linux-foundation.org>
> 
> Remove rtnl_unlock() which had no corresponding rtnl_lock().
> 
> Cc: Herbert Xu <herbert@gondor.apana.org.au>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

Thanks for catching this Andrew!

> ---
> 
>  net/core/netpoll.c |    1 -
>  1 file changed, 1 deletion(-)
> 
> diff -puN net/core/netpoll.c~fix-netpoll-allow-netpoll_setup-cleanup-recursion net/core/netpoll.c
> --- a/net/core/netpoll.c~fix-netpoll-allow-netpoll_setup-cleanup-recursion
> +++ a/net/core/netpoll.c
> @@ -748,7 +748,6 @@ int __netpoll_setup(struct netpoll *np)
>  
>  	/* last thing to do is link it to the net device structure */
>  	rcu_assign_pointer(ndev->npinfo, npinfo);
> -	rtnl_unlock();
>  
>  	return 0;
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [PATCH 6/8] netpoll: Allow netpoll_setup/cleanup recursion
From: Herbert Xu @ 2010-06-25  3:01 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Michael S. Tsirkin, Qianfeng Zhang, David S. Miller, netdev,
	WANG Cong, Stephen Hemminger, Matt Mackall, Paul E. McKenney,
	Peter Zijlstra, Ingo Molnar
In-Reply-To: <20100624182123.45264dfe.akpm@linux-foundation.org>

On Thu, Jun 24, 2010 at 06:21:23PM -0700, Andrew Morton wrote:
>
> I just removed the rtnl_unlock() - I couldn't see much in there which
> needed rtnl_locking..

Yes that's the correct fix.  I forgot to remove it from the
recursive setup path after moving the RTNL lock out.  Sorry!
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [PATCH 6/8] netpoll: Allow netpoll_setup/cleanup recursion
From: David Miller @ 2010-06-25  3:30 UTC (permalink / raw)
  To: akpm
  Cc: herbert, mst, frzhang, netdev, amwang, shemminger, mpm, paulmck,
	a.p.zijlstra, mingo
In-Reply-To: <20100624182123.45264dfe.akpm@linux-foundation.org>

From: Andrew Morton <akpm@linux-foundation.org>
Date: Thu, 24 Jun 2010 18:21:23 -0700

> Dave, the fixup should be folded into the original patch please -
> otherwise we'll have a machine-hangs-up bisection hole which spans two
> weeks work of commits.

I'm not unwrapping my tree that far back, and there's already been
a dependent tree pull or two which depend upon the tree past that
commit, one of it was a rather large wireless merge.

It's going to screw over too many people.

We'll just merge the bug fix in, and be done with it.

^ permalink raw reply

* Re: [PATCH 6/8] netpoll: Allow netpoll_setup/cleanup recursion
From: Andrew Morton @ 2010-06-25  3:50 UTC (permalink / raw)
  To: David Miller
  Cc: herbert, mst, frzhang, netdev, amwang, shemminger, mpm, paulmck,
	a.p.zijlstra, mingo
In-Reply-To: <20100624.203006.35035648.davem@davemloft.net>

On Thu, 24 Jun 2010 20:30:06 -0700 (PDT) David Miller <davem@davemloft.net> wrote:

> From: Andrew Morton <akpm@linux-foundation.org>
> Date: Thu, 24 Jun 2010 18:21:23 -0700
> 
> > Dave, the fixup should be folded into the original patch please -
> > otherwise we'll have a machine-hangs-up bisection hole which spans two
> > weeks work of commits.
> 
> I'm not unwrapping my tree that far back, and there's already been
> a dependent tree pull or two which depend upon the tree past that
> commit, one of it was a rather large wireless merge.
> 
> It's going to screw over too many people.
> 
> We'll just merge the bug fix in, and be done with it.

Sigh.  That really sucks.

What happens if you want to actually *drop* a patch from net-next? 
Surely that happens?


^ permalink raw reply

* [patch 1/1] fix "netpoll: Allow netpoll_setup/cleanup recursion"
From: akpm @ 2010-06-25  3:54 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, herbert

From: Andrew Morton <akpm@linux-foundation.org>

Remove rtnl_unlock() which had no corresponding rtnl_lock().

Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 net/core/netpoll.c |    1 -
 1 file changed, 1 deletion(-)

diff -puN net/core/netpoll.c~fix-netpoll-allow-netpoll_setup-cleanup-recursion net/core/netpoll.c
--- a/net/core/netpoll.c~fix-netpoll-allow-netpoll_setup-cleanup-recursion
+++ a/net/core/netpoll.c
@@ -748,7 +748,6 @@ int __netpoll_setup(struct netpoll *np)
 
 	/* last thing to do is link it to the net device structure */
 	rcu_assign_pointer(ndev->npinfo, npinfo);
-	rtnl_unlock();
 
 	return 0;
 
_

^ permalink raw reply

* Re: [PATCH 6/8] netpoll: Allow netpoll_setup/cleanup recursion
From: David Miller @ 2010-06-25  4:27 UTC (permalink / raw)
  To: akpm
  Cc: herbert, mst, frzhang, netdev, amwang, shemminger, mpm, paulmck,
	a.p.zijlstra, mingo
In-Reply-To: <20100624205059.a28756b0.akpm@linux-foundation.org>

From: Andrew Morton <akpm@linux-foundation.org>
Date: Thu, 24 Jun 2010 20:50:59 -0700

> What happens if you want to actually *drop* a patch from net-next? 
> Surely that happens?

I've only respun the tree on two or three occasions and that was
because I made some significant error myself and screwed up the
GIT tree somehow.

We've fixed much worse bugs than this one weeks after the changes
causing them went in, life goes on.

And the fact that it took two weeks of it being in -next before
anyone even reported it says how wide a net this particular bug
covers :-)  (hint: personally I've still never used netconsole
even one single time, and it's been around for what, something
like 6 years?)


^ permalink raw reply

* Re: [patch 1/1] fix "netpoll: Allow netpoll_setup/cleanup recursion"
From: David Miller @ 2010-06-25  4:27 UTC (permalink / raw)
  To: akpm; +Cc: netdev, herbert
In-Reply-To: <201006250353.o5P3rwti014499@imap1.linux-foundation.org>

From: akpm@linux-foundation.org
Date: Thu, 24 Jun 2010 20:54:01 -0700

> From: Andrew Morton <akpm@linux-foundation.org>
> 
> Remove rtnl_unlock() which had no corresponding rtnl_lock().
> 
> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

I found a time machine and applied this before you even posted
it here :-)

^ permalink raw reply

* Re: [PATCH v2 1/2] broadcom: move all PHY_ID's to header
From: David Miller @ 2010-06-25  4:30 UTC (permalink / raw)
  To: dbaryshkov; +Cc: netdev, mcarlson, mchan
In-Reply-To: <1276765344-12675-1-git-send-email-dbaryshkov@gmail.com>

From: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Date: Thu, 17 Jun 2010 13:02:23 +0400

> Move all PHY IDs to brcmphy.h header for completeness and unification of code.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>

Applied to net-next-2.6.

^ permalink raw reply

* Re: [PATCH v2 2/2] broadcom: Add 5241 support
From: David Miller @ 2010-06-25  4:30 UTC (permalink / raw)
  To: dbaryshkov; +Cc: netdev, mcarlson, mchan
In-Reply-To: <1276765344-12675-2-git-send-email-dbaryshkov@gmail.com>

From: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Date: Thu, 17 Jun 2010 13:02:24 +0400

> This patch adds the 5241 PHY ID to the broadcom module.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>

Applied to net-next-2.6

^ permalink raw reply

* Re: [v4 Patch 1/2] s2io: add dynamic LRO disable support
From: Jon Mason @ 2010-06-25  4:33 UTC (permalink / raw)
  To: Amerigo Wang
  Cc: netdev@vger.kernel.org, nhorman@redhat.com, sgruszka@redhat.com,
	herbert.xu@redhat.com, bhutchings@solarflare.com, Ramkrishna Vepa,
	davem@davemloft.net
In-Reply-To: <20100622085415.5566.22523.sendpatchset@localhost.localdomain>

On Tue, Jun 22, 2010 at 01:50:07AM -0700, Amerigo Wang wrote:
> 
> This patch adds dynamic LRO diable support for s2io net driver.
> 
> (I don't have s2io card, so only did compiling test. Anyone who wants
> to test this is more than welcome.)

Unfortunately the patch did not quite work, mostly due to NETIF_F_LRO
needing to be added at probe time to the device features.  I was able
to modify the patch to get it working, and will respond seperately
with the working patch.

Thanks,
Jon

> 
> This is based on Neil's initial work, and heavily modified
> based on Ramkrishna's suggestions.
> 
> Signed-off-by: WANG Cong <amwang@redhat.com>
> Signed-off-by: Neil Horman <nhorman@redhat.com>
> Acked-by: Neil Horman <nhorman@redhat.com>
> Reviewed-by: Stanislaw Gruszka <sgruszka@redhat.com>
> Cc: Ramkrishna Vepa <Ramkrishna.Vepa@exar.com>
> 
> ---
> 
> diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
> index 668327c..2e6e3b3 100644
> --- a/drivers/net/s2io.c
> +++ b/drivers/net/s2io.c
> @@ -795,7 +795,6 @@ static int init_shared_mem(struct s2io_nic *nic)
>  		ring->rx_curr_put_info.ring_len = rx_cfg->num_rxd - 1;
>  		ring->nic = nic;
>  		ring->ring_no = i;
> -		ring->lro = lro_enable;
>  
>  		blk_cnt = rx_cfg->num_rxd / (rxd_count[nic->rxd_mode] + 1);
>  		/*  Allocating all the Rx blocks */
> @@ -6684,6 +6683,41 @@ static int s2io_ethtool_op_set_tso(struct net_device *dev, u32 data)
>  
>  	return 0;
>  }
> +static int s2io_ethtool_set_flags(struct net_device *dev, u32 data)
> +{
> +	struct s2io_nic *sp = netdev_priv(dev);
> +	int rc = 0;
> +	int changed = 0;
> +
> +	if (data & ~ETH_FLAG_LRO)
> +		return -EOPNOTSUPP;
> +
> +	if (data & ETH_FLAG_LRO) {
> +		if (lro_enable) {
> +			if (!(dev->features & NETIF_F_LRO)) {
> +				dev->features |= NETIF_F_LRO;
> +				changed = 1;
> +			}
> +		} else
> +			rc = -EOPNOTSUPP;
> +	} else if (dev->features & NETIF_F_LRO) {
> +		dev->features &= ~NETIF_F_LRO;
> +		changed = 1;
> +	}
> +
> +	if (changed && netif_running(dev)) {
> +		s2io_stop_all_tx_queue(sp);
> +		s2io_card_down(sp);
> +		sp->lro = dev->features & NETIF_F_LRO;
> +		rc = s2io_card_up(sp);
> +		if (rc)
> +			s2io_reset(sp);
> +		else
> +			s2io_start_all_tx_queue(sp);
> +	}
> +
> +	return rc;
> +}
>  
>  static const struct ethtool_ops netdev_ethtool_ops = {
>  	.get_settings = s2io_ethtool_gset,
> @@ -6701,6 +6735,8 @@ static const struct ethtool_ops netdev_ethtool_ops = {
>  	.get_rx_csum = s2io_ethtool_get_rx_csum,
>  	.set_rx_csum = s2io_ethtool_set_rx_csum,
>  	.set_tx_csum = s2io_ethtool_op_set_tx_csum,
> +	.set_flags = s2io_ethtool_set_flags,
> +	.get_flags = ethtool_op_get_flags,
>  	.set_sg = ethtool_op_set_sg,
>  	.get_tso = s2io_ethtool_op_get_tso,
>  	.set_tso = s2io_ethtool_op_set_tso,
> @@ -7229,6 +7265,7 @@ static int s2io_card_up(struct s2io_nic *sp)
>  		struct ring_info *ring = &mac_control->rings[i];
>  
>  		ring->mtu = dev->mtu;
> +		ring->lro = sp->lro;
>  		ret = fill_rx_buffers(sp, ring, 1);
>  		if (ret) {
>  			DBG_PRINT(ERR_DBG, "%s: Out of memory in Open\n",
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* I am Mr. Chen Guan
From: Bank Of China @ 2010-06-25  4:36 UTC (permalink / raw)


Dear Friend,

I have a business suggestion for you. let me start by introducing myself
to you fully. I am Mr. Chen Guan, Foreign Operations Manager of the Bank
of China (Hong Kong). Before the U.S and Iraqi war our client Late Ali
Hussein who was with the Iraqi forces and also a businessman made a
numbered fixed deposit for 12 calendar months, with a value of Seventeen
Million Three Hundred Thousand United State Dollars only into an account
with my branch. Upon maturity several notice was sent to him, even during
the war . Again after the war another notification was sent and still no
response came from him. We later found out that the Ali Hussein and his
family had been killed during the war in bomb blast that hit their home.
After further investigation it was also discovered that Ali Hussein did
not declare any next of kin in his official papers including the paper
work of his bank deposit. And he also confided in me the last time he was
at my office that no one except me knew of his deposit in my bank. So,
Seventeen Million Three Hundred Thousand United State
Dollars(US$17,300,000.00) is still lying in my bank and no one will ever
come forward to claim it. What bothers me most is that according to the
laws of my country at the expiration 7 years the funds will revert to the
ownership of the Hong Kong Government if nobody applies to claim the
funds. Against this backdrop, my suggestion to you is that I will like you
as a foreigner to stand as the next of kin to Ali Hussein so that you will
be able to receive his funds. Please reply to my private email for more
Details ( chen_guan777@w.cn ) Thank you for your time and understanding

Kind Regards,
Mr. Chen Guan.

^ permalink raw reply

* Re: [PATCH 6/8] netpoll: Allow netpoll_setup/cleanup recursion
From: Andrew Morton @ 2010-06-25  4:42 UTC (permalink / raw)
  To: David Miller
  Cc: herbert, mst, frzhang, netdev, amwang, shemminger, mpm, paulmck,
	a.p.zijlstra, mingo
In-Reply-To: <20100624.212713.242141362.davem@davemloft.net>

On Thu, 24 Jun 2010 21:27:13 -0700 (PDT) David Miller <davem@davemloft.net> wrote:

> From: Andrew Morton <akpm@linux-foundation.org>
> Date: Thu, 24 Jun 2010 20:50:59 -0700
> 
> > What happens if you want to actually *drop* a patch from net-next? 
> > Surely that happens?
> 
> I've only respun the tree on two or three occasions and that was
> because I made some significant error myself and screwed up the
> GIT tree somehow.
> 
> We've fixed much worse bugs than this one weeks after the changes
> causing them went in, life goes on.

Still sucks - this is a quite ugly drawback to how we're using git. 
I've hit bisection holes several times which held up the show. 
Sometimes you can make them go away by fiddling the .config, other
times I've hunted down the fix and manually applied it for each
iteration.  It makes me feel all guilty each time I ask some poor sap
to bisect a bug for us.

> And the fact that it took two weeks of it being in -next before
> anyone even reported it says how wide a net this particular bug
> covers :-)  (hint: personally I've still never used netconsole
> even one single time, and it's been around for what, something
> like 6 years?)

I'd imagine that netconsole would get in the way rather a lot for net
developers, but it's really useful!


That being said, I wonder why Herbert didn't hit this in his testing. 
I suspect that he'd enabled lockdep, which hid the bug.  I haven't
worked out _why_ lockdep hides the double-mutex_unlock bug, but it's a
pretty bad thing to do.

Presumably mutex debugging _would_ have found it, but because the bug
was in netconsole code, the mutex-debugging blurt of course didn't come
out.  We don't replay the log buffer when netconsole is brought up -
perhaps we should.

And that machine has a screwy USB keyboard on which I've never managed
to invoke the vt-srcoll-backwards thing, so it would have been darned
hard for me to see and mutex-debugging warnings anyway.

^ 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