Netdev List
 help / color / mirror / Atom feed
* [PATCH 03/10] bna: Fix ethtool register dump and reordered an API
From: Rasesh Mody @ 2010-12-24  7:45 UTC (permalink / raw)
  To: netdev; +Cc: huangj, Rasesh Mody, Debashis Dutt
In-Reply-To: <1293176710-21335-1-git-send-email-rmody@brocade.com>

Change Details:
	- Removed semaphore register dump from ethtool
	- Moved netif_carrier_off() call to before calling bna_init()

Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bnad.c         |    8 +++-----
 drivers/net/bna/bnad_ethtool.c |    4 ----
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 3c40502..5e7a030 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -3061,6 +3061,9 @@ bnad_pci_probe(struct pci_dev *pdev,
 	/* Initialize netdev structure, set up ethtool ops */
 	bnad_netdev_init(bnad, using_dac);
 
+	/* Set link to down state */
+	netif_carrier_off(netdev);
+
 	bnad_enable_msix(bnad);
 
 	/* Get resource requirement form bna */
@@ -3114,11 +3117,6 @@ bnad_pci_probe(struct pci_dev *pdev,
 
 	mutex_unlock(&bnad->conf_mutex);
 
-	/*
-	 * Make sure the link appears down to the stack
-	 */
-	netif_carrier_off(netdev);
-
 	/* Finally, reguister with net_device layer */
 	err = register_netdev(netdev);
 	if (err) {
diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c
index 11fa2ea..3011110 100644
--- a/drivers/net/bna/bnad_ethtool.c
+++ b/drivers/net/bna/bnad_ethtool.c
@@ -330,10 +330,6 @@ do {								\
 
 	BNAD_GET_REG(PCIE_MISC_REG);
 
-	BNAD_GET_REG(HOST_SEM0_REG);
-	BNAD_GET_REG(HOST_SEM1_REG);
-	BNAD_GET_REG(HOST_SEM2_REG);
-	BNAD_GET_REG(HOST_SEM3_REG);
 	BNAD_GET_REG(HOST_SEM0_INFO_REG);
 	BNAD_GET_REG(HOST_SEM1_INFO_REG);
 	BNAD_GET_REG(HOST_SEM2_INFO_REG);
-- 
1.7.1


^ permalink raw reply related

* [PATCH 02/10] bna: Port enable disable sync and txq priority fix
From: Rasesh Mody @ 2010-12-24  7:45 UTC (permalink / raw)
  To: netdev; +Cc: huangj, Rasesh Mody, Debashis Dutt
In-Reply-To: <1293176710-21335-1-git-send-email-rmody@brocade.com>

Change Details:
	- Fixed port enable/disable sync through a change in LL port state
	machine
	- Change txq->priority masking to 0x7 (3 bits) from 0x3 (2 bits)

Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bna.h       |    4 +-
 drivers/net/bna/bna_ctrl.c  |  136 +++++++++++++++++++++++++++++++++----------
 drivers/net/bna/bna_txrx.c  |    8 +-
 drivers/net/bna/bna_types.h |    7 +-
 4 files changed, 116 insertions(+), 39 deletions(-)

diff --git a/drivers/net/bna/bna.h b/drivers/net/bna/bna.h
index df6676b..fd93f76 100644
--- a/drivers/net/bna/bna.h
+++ b/drivers/net/bna/bna.h
@@ -390,8 +390,8 @@ void bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe);
 
 /* API for RX */
 int bna_port_mtu_get(struct bna_port *port);
-void bna_llport_admin_up(struct bna_llport *llport);
-void bna_llport_admin_down(struct bna_llport *llport);
+void bna_llport_rx_started(struct bna_llport *llport);
+void bna_llport_rx_stopped(struct bna_llport *llport);
 
 /* API for BNAD */
 void bna_port_enable(struct bna_port *port);
diff --git a/drivers/net/bna/bna_ctrl.c b/drivers/net/bna/bna_ctrl.c
index 07b2659..68e4c5e 100644
--- a/drivers/net/bna/bna_ctrl.c
+++ b/drivers/net/bna/bna_ctrl.c
@@ -59,14 +59,70 @@ bna_port_cb_link_down(struct bna_port *port, int status)
 	port->link_cbfn(port->bna->bnad, BNA_LINK_DOWN);
 }
 
+static inline int
+llport_can_be_up(struct bna_llport *llport)
+{
+	int ready = 0;
+	if (llport->type == BNA_PORT_T_REGULAR)
+		ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) &&
+			 (llport->flags & BNA_LLPORT_F_RX_STARTED) &&
+			 (llport->flags & BNA_LLPORT_F_PORT_ENABLED));
+	else
+		ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) &&
+			 (llport->flags & BNA_LLPORT_F_RX_STARTED) &&
+			 !(llport->flags & BNA_LLPORT_F_PORT_ENABLED));
+	return ready;
+}
+
+#define llport_is_up llport_can_be_up
+
+enum bna_llport_event {
+	LLPORT_E_START			= 1,
+	LLPORT_E_STOP			= 2,
+	LLPORT_E_FAIL			= 3,
+	LLPORT_E_UP			= 4,
+	LLPORT_E_DOWN			= 5,
+	LLPORT_E_FWRESP_UP_OK		= 6,
+	LLPORT_E_FWRESP_UP_FAIL		= 7,
+	LLPORT_E_FWRESP_DOWN		= 8
+};
+
+static void
+bna_llport_cb_port_enabled(struct bna_llport *llport)
+{
+	llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
+
+	if (llport_can_be_up(llport))
+		bfa_fsm_send_event(llport, LLPORT_E_UP);
+}
+
+static void
+bna_llport_cb_port_disabled(struct bna_llport *llport)
+{
+	int llport_up = llport_is_up(llport);
+
+	llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
+
+	if (llport_up)
+		bfa_fsm_send_event(llport, LLPORT_E_DOWN);
+}
+
 /**
  * MBOX
  */
 static int
 bna_is_aen(u8 msg_id)
 {
-	return msg_id == BFI_LL_I2H_LINK_DOWN_AEN ||
-	       msg_id == BFI_LL_I2H_LINK_UP_AEN;
+	switch (msg_id) {
+	case BFI_LL_I2H_LINK_DOWN_AEN:
+	case BFI_LL_I2H_LINK_UP_AEN:
+	case BFI_LL_I2H_PORT_ENABLE_AEN:
+	case BFI_LL_I2H_PORT_DISABLE_AEN:
+		return 1;
+
+	default:
+		return 0;
+	}
 }
 
 static void
@@ -81,6 +137,12 @@ bna_mbox_aen_callback(struct bna *bna, struct bfi_mbmsg *msg)
 	case BFI_LL_I2H_LINK_DOWN_AEN:
 		bna_port_cb_link_down(&bna->port, aen->reason);
 		break;
+	case BFI_LL_I2H_PORT_ENABLE_AEN:
+		bna_llport_cb_port_enabled(&bna->port.llport);
+		break;
+	case BFI_LL_I2H_PORT_DISABLE_AEN:
+		bna_llport_cb_port_disabled(&bna->port.llport);
+		break;
 	default:
 		break;
 	}
@@ -251,16 +313,6 @@ static void bna_llport_start(struct bna_llport *llport);
 static void bna_llport_stop(struct bna_llport *llport);
 static void bna_llport_fail(struct bna_llport *llport);
 
-enum bna_llport_event {
-	LLPORT_E_START			= 1,
-	LLPORT_E_STOP			= 2,
-	LLPORT_E_FAIL			= 3,
-	LLPORT_E_UP			= 4,
-	LLPORT_E_DOWN			= 5,
-	LLPORT_E_FWRESP_UP		= 6,
-	LLPORT_E_FWRESP_DOWN		= 7
-};
-
 enum bna_llport_state {
 	BNA_LLPORT_STOPPED		= 1,
 	BNA_LLPORT_DOWN			= 2,
@@ -320,7 +372,7 @@ bna_llport_sm_stopped(struct bna_llport *llport,
 		/* No-op */
 		break;
 
-	case LLPORT_E_FWRESP_UP:
+	case LLPORT_E_FWRESP_UP_OK:
 	case LLPORT_E_FWRESP_DOWN:
 		/**
 		 * These events are received due to flushing of mbox when
@@ -366,6 +418,7 @@ bna_llport_sm_down(struct bna_llport *llport,
 static void
 bna_llport_sm_up_resp_wait_entry(struct bna_llport *llport)
 {
+	BUG_ON(!llport_can_be_up(llport));
 	/**
 	 * NOTE: Do not call bna_fw_llport_up() here. That will over step
 	 * mbox due to down_resp_wait -> up_resp_wait transition on event
@@ -390,10 +443,14 @@ bna_llport_sm_up_resp_wait(struct bna_llport *llport,
 		bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait);
 		break;
 
-	case LLPORT_E_FWRESP_UP:
+	case LLPORT_E_FWRESP_UP_OK:
 		bfa_fsm_set_state(llport, bna_llport_sm_up);
 		break;
 
+	case LLPORT_E_FWRESP_UP_FAIL:
+		bfa_fsm_set_state(llport, bna_llport_sm_down);
+		break;
+
 	case LLPORT_E_FWRESP_DOWN:
 		/* down_resp_wait -> up_resp_wait transition on LLPORT_E_UP */
 		bna_fw_llport_up(llport);
@@ -431,11 +488,12 @@ bna_llport_sm_down_resp_wait(struct bna_llport *llport,
 		bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait);
 		break;
 
-	case LLPORT_E_FWRESP_UP:
+	case LLPORT_E_FWRESP_UP_OK:
 		/* up_resp_wait->down_resp_wait transition on LLPORT_E_DOWN */
 		bna_fw_llport_down(llport);
 		break;
 
+	case LLPORT_E_FWRESP_UP_FAIL:
 	case LLPORT_E_FWRESP_DOWN:
 		bfa_fsm_set_state(llport, bna_llport_sm_down);
 		break;
@@ -496,11 +554,12 @@ bna_llport_sm_last_resp_wait(struct bna_llport *llport,
 		/* No-op */
 		break;
 
-	case LLPORT_E_FWRESP_UP:
+	case LLPORT_E_FWRESP_UP_OK:
 		/* up_resp_wait->last_resp_wait transition on LLPORT_T_STOP */
 		bna_fw_llport_down(llport);
 		break;
 
+	case LLPORT_E_FWRESP_UP_FAIL:
 	case LLPORT_E_FWRESP_DOWN:
 		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
 		break;
@@ -541,7 +600,14 @@ bna_fw_cb_llport_up(void *arg, int status)
 	struct bna_llport *llport = (struct bna_llport *)arg;
 
 	bfa_q_qe_init(&llport->mbox_qe.qe);
-	bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP);
+	if (status == BFI_LL_CMD_FAIL) {
+		if (llport->type == BNA_PORT_T_REGULAR)
+			llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
+		else
+			llport->flags &= ~BNA_LLPORT_F_ADMIN_UP;
+		bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_FAIL);
+	} else
+		bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_OK);
 }
 
 static void
@@ -588,13 +654,14 @@ bna_port_cb_llport_stopped(struct bna_port *port,
 static void
 bna_llport_init(struct bna_llport *llport, struct bna *bna)
 {
-	llport->flags |= BNA_LLPORT_F_ENABLED;
+	llport->flags |= BNA_LLPORT_F_ADMIN_UP;
+	llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
 	llport->type = BNA_PORT_T_REGULAR;
 	llport->bna = bna;
 
 	llport->link_status = BNA_LINK_DOWN;
 
-	llport->admin_up_count = 0;
+	llport->rx_started_count = 0;
 
 	llport->stop_cbfn = NULL;
 
@@ -606,7 +673,8 @@ bna_llport_init(struct bna_llport *llport, struct bna *bna)
 static void
 bna_llport_uninit(struct bna_llport *llport)
 {
-	llport->flags &= ~BNA_LLPORT_F_ENABLED;
+	llport->flags &= ~BNA_LLPORT_F_ADMIN_UP;
+	llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
 
 	llport->bna = NULL;
 }
@@ -628,6 +696,8 @@ bna_llport_stop(struct bna_llport *llport)
 static void
 bna_llport_fail(struct bna_llport *llport)
 {
+	/* Reset the physical port status to enabled */
+	llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
 	bfa_fsm_send_event(llport, LLPORT_E_FAIL);
 }
 
@@ -638,25 +708,31 @@ bna_llport_state_get(struct bna_llport *llport)
 }
 
 void
-bna_llport_admin_up(struct bna_llport *llport)
+bna_llport_rx_started(struct bna_llport *llport)
 {
-	llport->admin_up_count++;
+	llport->rx_started_count++;
+
+	if (llport->rx_started_count == 1) {
+
+		llport->flags |= BNA_LLPORT_F_RX_STARTED;
 
-	if (llport->admin_up_count == 1) {
-		llport->flags |= BNA_LLPORT_F_RX_ENABLED;
-		if (llport->flags & BNA_LLPORT_F_ENABLED)
+		if (llport_can_be_up(llport))
 			bfa_fsm_send_event(llport, LLPORT_E_UP);
 	}
 }
 
 void
-bna_llport_admin_down(struct bna_llport *llport)
+bna_llport_rx_stopped(struct bna_llport *llport)
 {
-	llport->admin_up_count--;
+	int llport_up = llport_is_up(llport);
+
+	llport->rx_started_count--;
+
+	if (llport->rx_started_count == 0) {
+
+		llport->flags &= ~BNA_LLPORT_F_RX_STARTED;
 
-	if (llport->admin_up_count == 0) {
-		llport->flags &= ~BNA_LLPORT_F_RX_ENABLED;
-		if (llport->flags & BNA_LLPORT_F_ENABLED)
+		if (llport_up)
 			bfa_fsm_send_event(llport, LLPORT_E_DOWN);
 	}
 }
diff --git a/drivers/net/bna/bna_txrx.c b/drivers/net/bna/bna_txrx.c
index ad93fdb..fb6cf1f 100644
--- a/drivers/net/bna/bna_txrx.c
+++ b/drivers/net/bna/bna_txrx.c
@@ -1947,7 +1947,7 @@ bna_rx_sm_started_entry(struct bna_rx *rx)
 		bna_ib_ack(&rxp->cq.ib->door_bell, 0);
 	}
 
-	bna_llport_admin_up(&rx->bna->port.llport);
+	bna_llport_rx_started(&rx->bna->port.llport);
 }
 
 void
@@ -1955,13 +1955,13 @@ bna_rx_sm_started(struct bna_rx *rx, enum bna_rx_event event)
 {
 	switch (event) {
 	case RX_E_FAIL:
-		bna_llport_admin_down(&rx->bna->port.llport);
+		bna_llport_rx_stopped(&rx->bna->port.llport);
 		bfa_fsm_set_state(rx, bna_rx_sm_stopped);
 		rx_ib_fail(rx);
 		bna_rxf_fail(&rx->rxf);
 		break;
 	case RX_E_STOP:
-		bna_llport_admin_down(&rx->bna->port.llport);
+		bna_llport_rx_stopped(&rx->bna->port.llport);
 		bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
 		break;
 	default:
@@ -3373,7 +3373,7 @@ __bna_txq_start(struct bna_tx *tx, struct bna_txq *txq)
 
 	txq_cfg.cns_ptr2_n_q_state = BNA_Q_IDLE_STATE;
 	txq_cfg.nxt_qid_n_fid_n_pri = (((tx->txf.txf_id & 0x3f) << 3) |
-			(txq->priority & 0x3));
+			(txq->priority & 0x7));
 	txq_cfg.wvc_n_cquota_n_rquota =
 			((((u32)BFI_TX_MAX_WRR_QUOTA & 0xfff) << 12) |
 			(BFI_TX_MAX_WRR_QUOTA & 0xfff));
diff --git a/drivers/net/bna/bna_types.h b/drivers/net/bna/bna_types.h
index 6877310..d79fd98 100644
--- a/drivers/net/bna/bna_types.h
+++ b/drivers/net/bna/bna_types.h
@@ -249,8 +249,9 @@ enum bna_link_status {
 };
 
 enum bna_llport_flags {
-	BNA_LLPORT_F_ENABLED 	= 1,
-	BNA_LLPORT_F_RX_ENABLED	= 2
+	BNA_LLPORT_F_ADMIN_UP	 	= 1,
+	BNA_LLPORT_F_PORT_ENABLED	= 2,
+	BNA_LLPORT_F_RX_STARTED		= 4
 };
 
 enum bna_port_flags {
@@ -405,7 +406,7 @@ struct bna_llport {
 
 	enum bna_link_status link_status;
 
-	int			admin_up_count;
+	int			rx_started_count;
 
 	void (*stop_cbfn)(struct bna_port *, enum bna_cb_status);
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 01/10] bna: TxRx and datapath fix
From: Rasesh Mody @ 2010-12-24  7:45 UTC (permalink / raw)
  To: netdev; +Cc: huangj, Rasesh Mody, Debashis Dutt
In-Reply-To: <1293176710-21335-1-git-send-email-rmody@brocade.com>

Change Details:
	- Check HW ready condition before accessing h/w register in data-path
	- Postpone clean-up of data buffers to the data-path restart path and
	wait in the cleanup routines for in-flight DMA to complete
	- Separate out Tx completion processing from Rx poll routine

Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bnad.c |  353 ++++++++++++++++++++++-------------------------
 drivers/net/bna/bnad.h |   22 ++--
 2 files changed, 178 insertions(+), 197 deletions(-)

diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 7e839b9..3c40502 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -70,6 +70,8 @@ do {								\
 	(sizeof(struct bnad_skb_unmap) * ((_depth) - 1));	\
 } while (0)
 
+#define BNAD_TXRX_SYNC_MDELAY	250	/* 250 msecs */
+
 /*
  * Reinitialize completions in CQ, once Rx is taken down
  */
@@ -130,7 +132,9 @@ bnad_free_all_txbufs(struct bnad *bnad,
 						PCI_DMA_TODEVICE);
 
 		pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
-		unmap_cons++;
+		if (++unmap_cons >= unmap_q->q_depth)
+			break;
+
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 			pci_unmap_page(bnad->pcidev,
 				       pci_unmap_addr(&unmap_array[unmap_cons],
@@ -139,7 +143,8 @@ bnad_free_all_txbufs(struct bnad *bnad,
 				       PCI_DMA_TODEVICE);
 			pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
 					   0);
-			unmap_cons++;
+			if (++unmap_cons >= unmap_q->q_depth)
+				break;
 		}
 		dev_kfree_skb_any(skb);
 	}
@@ -167,11 +172,11 @@ bnad_free_txbufs(struct bnad *bnad,
 	/*
 	 * Just return if TX is stopped. This check is useful
 	 * when bnad_free_txbufs() runs out of a tasklet scheduled
-	 * before bnad_cb_tx_cleanup() cleared BNAD_RF_TX_STARTED bit
+	 * before bnad_cb_tx_cleanup() cleared BNAD_TXQ_TX_STARTED bit
 	 * but this routine runs actually after the cleanup has been
 	 * executed.
 	 */
-	if (!test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))
+	if (!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
 		return 0;
 
 	updated_hw_cons = *(tcb->hw_consumer_index);
@@ -252,7 +257,9 @@ bnad_tx_free_tasklet(unsigned long bnad_ptr)
 				(!test_and_set_bit(BNAD_TXQ_FREE_SENT,
 						  &tcb->flags))) {
 				acked = bnad_free_txbufs(bnad, tcb);
-				bna_ib_ack(tcb->i_dbell, acked);
+				if (likely(test_bit(BNAD_TXQ_TX_STARTED,
+					&tcb->flags)))
+					bna_ib_ack(tcb->i_dbell, acked);
 				smp_mb__before_clear_bit();
 				clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
 			}
@@ -264,7 +271,7 @@ static u32
 bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
 {
 	struct net_device *netdev = bnad->netdev;
-	u32 sent;
+	u32 sent = 0;
 
 	if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
 		return 0;
@@ -275,12 +282,15 @@ bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
 		    netif_carrier_ok(netdev) &&
 		    BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
 				    BNAD_NETIF_WAKE_THRESHOLD) {
-			netif_wake_queue(netdev);
-			BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+			if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) {
+				netif_wake_queue(netdev);
+				BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+			}
 		}
+	}
+
+	if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
 		bna_ib_ack(tcb->i_dbell, sent);
-	} else
-		bna_ib_ack(tcb->i_dbell, 0);
 
 	smp_mb__before_clear_bit();
 	clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
@@ -313,25 +323,26 @@ bnad_reset_rcb(struct bnad *bnad, struct bna_rcb *rcb)
 }
 
 static void
-bnad_free_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
+bnad_free_all_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
 {
 	struct bnad_unmap_q *unmap_q;
 	struct sk_buff *skb;
+	int unmap_cons;
 
 	unmap_q = rcb->unmap_q;
-	while (BNA_QE_IN_USE_CNT(unmap_q, unmap_q->q_depth)) {
-		skb = unmap_q->unmap_array[unmap_q->consumer_index].skb;
-		BUG_ON(!(skb));
-		unmap_q->unmap_array[unmap_q->consumer_index].skb = NULL;
+	for (unmap_cons = 0; unmap_cons < unmap_q->q_depth; unmap_cons++) {
+		skb = unmap_q->unmap_array[unmap_cons].skb;
+		if (!skb)
+			continue;
+		BUG_ON(!(pci_unmap_addr(
+			&unmap_q->unmap_array[unmap_cons], dma_addr)));
+		unmap_q->unmap_array[unmap_cons].skb = NULL;
 		pci_unmap_single(bnad->pcidev, pci_unmap_addr(&unmap_q->
-					unmap_array[unmap_q->consumer_index],
-					dma_addr), rcb->rxq->buffer_size +
-					NET_IP_ALIGN, PCI_DMA_FROMDEVICE);
+					unmap_array[unmap_cons],
+					dma_addr), rcb->rxq->buffer_size,
+					PCI_DMA_FROMDEVICE);
 		dev_kfree_skb(skb);
-		BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth);
-		BNA_QE_INDX_ADD(rcb->consumer_index, 1, rcb->q_depth);
 	}
-
 	bnad_reset_rcb(bnad, rcb);
 }
 
@@ -385,41 +396,9 @@ finishing:
 		unmap_q->producer_index = unmap_prod;
 		rcb->producer_index = unmap_prod;
 		smp_mb();
-		bna_rxq_prod_indx_doorbell(rcb);
-	}
-}
-
-/*
- * Locking is required in the enable path
- * because it is called from a napi poll
- * context, where the bna_lock is not held
- * unlike the IRQ context.
- */
-static void
-bnad_enable_txrx_irqs(struct bnad *bnad)
-{
-	struct bna_tcb *tcb;
-	struct bna_ccb *ccb;
-	int i, j;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	for (i = 0; i < bnad->num_tx; i++) {
-		for (j = 0; j < bnad->num_txq_per_tx; j++) {
-			tcb = bnad->tx_info[i].tcb[j];
-			bna_ib_coalescing_timer_set(tcb->i_dbell,
-				tcb->txq->ib->ib_config.coalescing_timeo);
-			bna_ib_ack(tcb->i_dbell, 0);
-		}
-	}
-
-	for (i = 0; i < bnad->num_rx; i++) {
-		for (j = 0; j < bnad->num_rxp_per_rx; j++) {
-			ccb = bnad->rx_info[i].rx_ctrl[j].ccb;
-			bnad_enable_rx_irq_unsafe(ccb);
-		}
+		if (likely(test_bit(BNAD_RXQ_STARTED, &rcb->flags)))
+			bna_rxq_prod_indx_doorbell(rcb);
 	}
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 }
 
 static inline void
@@ -448,6 +427,9 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
 	u32 qid0 = ccb->rcb[0]->rxq->rxq_id;
 	struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
 
+	if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))
+		return 0;
+
 	prefetch(bnad->netdev);
 	BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl,
 			    wi_range);
@@ -544,12 +526,15 @@ next:
 	BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
 
 	if (likely(ccb)) {
-		bna_ib_ack(ccb->i_dbell, packets);
+		if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
+			bna_ib_ack(ccb->i_dbell, packets);
 		bnad_refill_rxq(bnad, ccb->rcb[0]);
 		if (ccb->rcb[1])
 			bnad_refill_rxq(bnad, ccb->rcb[1]);
-	} else
-		bna_ib_ack(ccb->i_dbell, 0);
+	} else {
+		if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
+			bna_ib_ack(ccb->i_dbell, 0);
+	}
 
 	return packets;
 }
@@ -557,6 +542,9 @@ next:
 static void
 bnad_disable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
 {
+	if (unlikely(!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
+		return;
+
 	bna_ib_coalescing_timer_set(ccb->i_dbell, 0);
 	bna_ib_ack(ccb->i_dbell, 0);
 }
@@ -575,9 +563,11 @@ static void
 bnad_netif_rx_schedule_poll(struct bnad *bnad, struct bna_ccb *ccb)
 {
 	struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl);
-	if (likely(napi_schedule_prep((&rx_ctrl->napi)))) {
+	struct napi_struct *napi = &rx_ctrl->napi;
+
+	if (likely(napi_schedule_prep(napi))) {
 		bnad_disable_rx_irq(bnad, ccb);
-		__napi_schedule((&rx_ctrl->napi));
+		__napi_schedule(napi);
 	}
 	BNAD_UPDATE_CTR(bnad, netif_rx_schedule);
 }
@@ -602,12 +592,11 @@ bnad_msix_mbox_handler(int irq, void *data)
 {
 	u32 intr_status;
 	unsigned long flags;
-	struct net_device *netdev = data;
-	struct bnad *bnad;
+	struct bnad *bnad = (struct bnad *)data;
 
-	bnad = netdev_priv(netdev);
+	if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
+		return IRQ_HANDLED;
 
-	/* BNA_ISR_GET(bnad); Inc Ref count */
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 
 	bna_intr_status_get(&bnad->bna, intr_status);
@@ -617,7 +606,6 @@ bnad_msix_mbox_handler(int irq, void *data)
 
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
-	/* BNAD_ISR_PUT(bnad); Dec Ref count */
 	return IRQ_HANDLED;
 }
 
@@ -627,8 +615,7 @@ bnad_isr(int irq, void *data)
 	int i, j;
 	u32 intr_status;
 	unsigned long flags;
-	struct net_device *netdev = data;
-	struct bnad *bnad = netdev_priv(netdev);
+	struct bnad *bnad = (struct bnad *)data;
 	struct bnad_rx_info *rx_info;
 	struct bnad_rx_ctrl *rx_ctrl;
 
@@ -642,16 +629,21 @@ bnad_isr(int irq, void *data)
 
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 
-	if (BNA_IS_MBOX_ERR_INTR(intr_status)) {
+	if (BNA_IS_MBOX_ERR_INTR(intr_status))
 		bna_mbox_handler(&bnad->bna, intr_status);
-		if (!BNA_IS_INTX_DATA_INTR(intr_status)) {
-			spin_unlock_irqrestore(&bnad->bna_lock, flags);
-			goto done;
-		}
-	}
+
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
+	if (!BNA_IS_INTX_DATA_INTR(intr_status))
+		return IRQ_HANDLED;
+
 	/* Process data interrupts */
+	/* Tx processing */
+	for (i = 0; i < bnad->num_tx; i++) {
+		for (j = 0; j < bnad->num_txq_per_tx; j++)
+			bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
+	}
+	/* Rx processing */
 	for (i = 0; i < bnad->num_rx; i++) {
 		rx_info = &bnad->rx_info[i];
 		if (!rx_info->rx)
@@ -663,7 +655,6 @@ bnad_isr(int irq, void *data)
 							    rx_ctrl->ccb);
 		}
 	}
-done:
 	return IRQ_HANDLED;
 }
 
@@ -674,11 +665,7 @@ done:
 static void
 bnad_enable_mbox_irq(struct bnad *bnad)
 {
-	int irq = BNAD_GET_MBOX_IRQ(bnad);
-
-	if (test_and_clear_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))
-		if (bnad->cfg_flags & BNAD_CF_MSIX)
-			enable_irq(irq);
+	clear_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
 
 	BNAD_UPDATE_CTR(bnad, mbox_intr_enabled);
 }
@@ -690,14 +677,19 @@ bnad_enable_mbox_irq(struct bnad *bnad)
 static void
 bnad_disable_mbox_irq(struct bnad *bnad)
 {
-	int irq = BNAD_GET_MBOX_IRQ(bnad);
+	set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
 
+	BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
+}
 
-	if (!test_and_set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))
-		if (bnad->cfg_flags & BNAD_CF_MSIX)
-			disable_irq_nosync(irq);
+static void
+bnad_set_netdev_perm_addr(struct bnad *bnad)
+{
+	struct net_device *netdev = bnad->netdev;
 
-	BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
+	memcpy(netdev->perm_addr, &bnad->perm_addr, netdev->addr_len);
+	if (is_zero_ether_addr(netdev->dev_addr))
+		memcpy(netdev->dev_addr, &bnad->perm_addr, netdev->addr_len);
 }
 
 /* Control Path Handlers */
@@ -755,11 +747,14 @@ bnad_cb_port_link_status(struct bnad *bnad,
 
 	if (link_up) {
 		if (!netif_carrier_ok(bnad->netdev)) {
+			struct bna_tcb *tcb = bnad->tx_info[0].tcb[0];
+			if (!tcb)
+				return;
 			pr_warn("bna: %s link up\n",
 				bnad->netdev->name);
 			netif_carrier_on(bnad->netdev);
 			BNAD_UPDATE_CTR(bnad, link_toggle);
-			if (test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags)) {
+			if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) {
 				/* Force an immediate Transmit Schedule */
 				pr_info("bna: %s TX_STARTED\n",
 					bnad->netdev->name);
@@ -807,6 +802,18 @@ bnad_cb_tcb_destroy(struct bnad *bnad, struct bna_tcb *tcb)
 {
 	struct bnad_tx_info *tx_info =
 			(struct bnad_tx_info *)tcb->txq->tx->priv;
+	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
+
+	while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
+		cpu_relax();
+
+	bnad_free_all_txbufs(bnad, tcb);
+
+	unmap_q->producer_index = 0;
+	unmap_q->consumer_index = 0;
+
+	smp_mb__before_clear_bit();
+	clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
 
 	tx_info->tcb[tcb->id] = NULL;
 }
@@ -822,6 +829,12 @@ bnad_cb_rcb_setup(struct bnad *bnad, struct bna_rcb *rcb)
 }
 
 static void
+bnad_cb_rcb_destroy(struct bnad *bnad, struct bna_rcb *rcb)
+{
+	bnad_free_all_rxbufs(bnad, rcb);
+}
+
+static void
 bnad_cb_ccb_setup(struct bnad *bnad, struct bna_ccb *ccb)
 {
 	struct bnad_rx_info *rx_info =
@@ -849,7 +862,7 @@ bnad_cb_tx_stall(struct bnad *bnad, struct bna_tcb *tcb)
 	if (tx_info != &bnad->tx_info[0])
 		return;
 
-	clear_bit(BNAD_RF_TX_STARTED, &bnad->run_flags);
+	clear_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
 	netif_stop_queue(bnad->netdev);
 	pr_info("bna: %s TX_STOPPED\n", bnad->netdev->name);
 }
@@ -857,30 +870,15 @@ bnad_cb_tx_stall(struct bnad *bnad, struct bna_tcb *tcb)
 static void
 bnad_cb_tx_resume(struct bnad *bnad, struct bna_tcb *tcb)
 {
-	if (test_and_set_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))
-		return;
-
-	if (netif_carrier_ok(bnad->netdev)) {
-		pr_info("bna: %s TX_STARTED\n", bnad->netdev->name);
-		netif_wake_queue(bnad->netdev);
-		BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
-	}
-}
-
-static void
-bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
-{
-	struct bnad_unmap_q *unmap_q;
+	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
 
-	if (!tcb || (!tcb->unmap_q))
+	if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
 		return;
 
-	unmap_q = tcb->unmap_q;
-	if (!unmap_q->unmap_array)
-		return;
+	clear_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags);
 
-	if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
-		return;
+	while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
+		cpu_relax();
 
 	bnad_free_all_txbufs(bnad, tcb);
 
@@ -889,21 +887,45 @@ bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
 
 	smp_mb__before_clear_bit();
 	clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+
+	/*
+	 * Workaround for first device enable failure & we
+	 * get a 0 MAC address. We try to get the MAC address
+	 * again here.
+	 */
+	if (is_zero_ether_addr(&bnad->perm_addr.mac[0])) {
+		bna_port_mac_get(&bnad->bna.port, &bnad->perm_addr);
+		bnad_set_netdev_perm_addr(bnad);
+	}
+
+	set_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
+
+	if (netif_carrier_ok(bnad->netdev)) {
+		pr_info("bna: %s TX_STARTED\n", bnad->netdev->name);
+		netif_wake_queue(bnad->netdev);
+		BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+	}
+}
+
+static void
+bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
+{
+	/* Delay only once for the whole Tx Path Shutdown */
+	if (!test_and_set_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags))
+		mdelay(BNAD_TXRX_SYNC_MDELAY);
 }
 
 static void
 bnad_cb_rx_cleanup(struct bnad *bnad,
 			struct bna_ccb *ccb)
 {
-	bnad_cq_cmpl_init(bnad, ccb);
-
-	bnad_free_rxbufs(bnad, ccb->rcb[0]);
 	clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags);
 
-	if (ccb->rcb[1]) {
-		bnad_free_rxbufs(bnad, ccb->rcb[1]);
+	if (ccb->rcb[1])
 		clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags);
-	}
+
+	if (!test_and_set_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags))
+		mdelay(BNAD_TXRX_SYNC_MDELAY);
 }
 
 static void
@@ -911,6 +933,13 @@ bnad_cb_rx_post(struct bnad *bnad, struct bna_rcb *rcb)
 {
 	struct bnad_unmap_q *unmap_q = rcb->unmap_q;
 
+	clear_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags);
+
+	if (rcb == rcb->cq->ccb->rcb[0])
+		bnad_cq_cmpl_init(bnad, rcb->cq->ccb);
+
+	bnad_free_all_rxbufs(bnad, rcb);
+
 	set_bit(BNAD_RXQ_STARTED, &rcb->flags);
 
 	/* Now allocate & post buffers for this RCB */
@@ -1047,7 +1076,7 @@ bnad_mbox_irq_free(struct bnad *bnad,
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
 	irq = BNAD_GET_MBOX_IRQ(bnad);
-	free_irq(irq, bnad->netdev);
+	free_irq(irq, bnad);
 
 	kfree(intr_info->idl);
 }
@@ -1061,7 +1090,7 @@ static int
 bnad_mbox_irq_alloc(struct bnad *bnad,
 		    struct bna_intr_info *intr_info)
 {
-	int 		err;
+	int 		err = 0;
 	unsigned long 	flags;
 	u32	irq;
 	irq_handler_t 	irq_handler;
@@ -1096,22 +1125,17 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
 	 */
 	set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
 
+	BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
+
 	err = request_irq(irq, irq_handler, flags,
-			  bnad->mbox_irq_name, bnad->netdev);
+			  bnad->mbox_irq_name, bnad);
 
 	if (err) {
 		kfree(intr_info->idl);
 		intr_info->idl = NULL;
-		return err;
 	}
 
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-
-	if (bnad->cfg_flags & BNAD_CF_MSIX)
-		disable_irq_nosync(irq);
-
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	return 0;
+	return err;
 }
 
 static void
@@ -1555,62 +1579,19 @@ poll_exit:
 	return rcvd;
 }
 
-static int
-bnad_napi_poll_txrx(struct napi_struct *napi, int budget)
-{
-	struct bnad_rx_ctrl *rx_ctrl =
-		container_of(napi, struct bnad_rx_ctrl, napi);
-	struct bna_ccb *ccb;
-	struct bnad *bnad;
-	int 			rcvd = 0;
-	int			i, j;
-
-	ccb = rx_ctrl->ccb;
-
-	bnad = ccb->bnad;
-
-	if (!netif_carrier_ok(bnad->netdev))
-		goto poll_exit;
-
-	/* Handle Tx Completions, if any */
-	for (i = 0; i < bnad->num_tx; i++) {
-		for (j = 0; j < bnad->num_txq_per_tx; j++)
-			bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
-	}
-
-	/* Handle Rx Completions */
-	rcvd = bnad_poll_cq(bnad, ccb, budget);
-	if (rcvd == budget)
-		return rcvd;
-poll_exit:
-	napi_complete((napi));
-
-	BNAD_UPDATE_CTR(bnad, netif_rx_complete);
-
-	bnad_enable_txrx_irqs(bnad);
-	return rcvd;
-}
-
 static void
 bnad_napi_enable(struct bnad *bnad, u32 rx_id)
 {
-	int (*napi_poll) (struct napi_struct *, int);
 	struct bnad_rx_ctrl *rx_ctrl;
 	int i;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	if (bnad->cfg_flags & BNAD_CF_MSIX)
-		napi_poll = bnad_napi_poll_rx;
-	else
-		napi_poll = bnad_napi_poll_txrx;
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
 	/* Initialize & enable NAPI */
 	for (i = 0; i <	bnad->num_rxp_per_rx; i++) {
 		rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i];
+
 		netif_napi_add(bnad->netdev, &rx_ctrl->napi,
-			       napi_poll, 64);
+			       bnad_napi_poll_rx, 64);
+
 		napi_enable(&rx_ctrl->napi);
 	}
 }
@@ -1825,6 +1806,7 @@ bnad_setup_rx(struct bnad *bnad, uint rx_id)
 
 	/* Initialize the Rx event handlers */
 	rx_cbfn.rcb_setup_cbfn = bnad_cb_rcb_setup;
+	rx_cbfn.rcb_destroy_cbfn = bnad_cb_rcb_destroy;
 	rx_cbfn.rcb_destroy_cbfn = NULL;
 	rx_cbfn.ccb_setup_cbfn = bnad_cb_ccb_setup;
 	rx_cbfn.ccb_destroy_cbfn = bnad_cb_ccb_destroy;
@@ -2152,16 +2134,6 @@ bnad_q_num_adjust(struct bnad *bnad, int msix_vectors)
 		bnad->num_rxp_per_rx = 1;
 }
 
-static void
-bnad_set_netdev_perm_addr(struct bnad *bnad)
-{
-	struct net_device *netdev = bnad->netdev;
-
-	memcpy(netdev->perm_addr, &bnad->perm_addr, netdev->addr_len);
-	if (is_zero_ether_addr(netdev->dev_addr))
-		memcpy(netdev->dev_addr, &bnad->perm_addr, netdev->addr_len);
-}
-
 /* Enable / disable device */
 static void
 bnad_device_disable(struct bnad *bnad)
@@ -2433,21 +2405,21 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 		return NETDEV_TX_OK;
 	}
 
+	tx_id = 0;
+
+	tx_info = &bnad->tx_info[tx_id];
+	tcb = tx_info->tcb[tx_id];
+	unmap_q = tcb->unmap_q;
+
 	/*
 	 * Takes care of the Tx that is scheduled between clearing the flag
 	 * and the netif_stop_queue() call.
 	 */
-	if (unlikely(!test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))) {
+	if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) {
 		dev_kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
 
-	tx_id = 0;
-
-	tx_info = &bnad->tx_info[tx_id];
-	tcb = tx_info->tcb[tx_id];
-	unmap_q = tcb->unmap_q;
-
 	vectors = 1 + skb_shinfo(skb)->nr_frags;
 	if (vectors > BFI_TX_MAX_VECTORS_PER_PKT) {
 		dev_kfree_skb(skb);
@@ -2462,7 +2434,8 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 		    tcb->consumer_index &&
 		    !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
 			acked = bnad_free_txbufs(bnad, tcb);
-			bna_ib_ack(tcb->i_dbell, acked);
+			if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
+				bna_ib_ack(tcb->i_dbell, acked);
 			smp_mb__before_clear_bit();
 			clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
 		} else {
@@ -2624,6 +2597,10 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 	tcb->producer_index = txq_prod;
 
 	smp_mb();
+
+	if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
+		return NETDEV_TX_OK;
+
 	bna_txq_prod_indx_doorbell(tcb);
 
 	if ((u16) (*tcb->hw_consumer_index) != tcb->consumer_index)
@@ -3066,7 +3043,7 @@ bnad_pci_probe(struct pci_dev *pdev,
 	/*
 	 * PCI initialization
 	 * 	Output : using_dac = 1 for 64 bit DMA
-	 *		           = 0 for 32 bit DMA
+	 *			   = 0 for 32 bit DMA
 	 */
 	err = bnad_pci_init(bnad, pdev, &using_dac);
 	if (err)
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index ebc3a90..f59685a 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -51,6 +51,7 @@
  */
 struct bnad_rx_ctrl {
 	struct bna_ccb *ccb;
+	unsigned long  flags;
 	struct napi_struct	napi;
 };
 
@@ -82,6 +83,7 @@ struct bnad_rx_ctrl {
 
 /* Bit positions for tcb->flags */
 #define BNAD_TXQ_FREE_SENT		0
+#define BNAD_TXQ_TX_STARTED		1
 
 /* Bit positions for rcb->flags */
 #define BNAD_RXQ_REFILL			0
@@ -199,12 +201,12 @@ struct bnad_unmap_q {
 /* Set, tested & cleared using xxx_bit() functions */
 /* Values indicated bit positions */
 #define	BNAD_RF_CEE_RUNNING		1
-#define BNAD_RF_HW_ERROR 		2
-#define BNAD_RF_MBOX_IRQ_DISABLED	3
-#define BNAD_RF_TX_STARTED		4
-#define BNAD_RF_RX_STARTED		5
-#define BNAD_RF_DIM_TIMER_RUNNING	6
-#define BNAD_RF_STATS_TIMER_RUNNING	7
+#define BNAD_RF_MBOX_IRQ_DISABLED	2
+#define BNAD_RF_RX_STARTED		3
+#define BNAD_RF_DIM_TIMER_RUNNING	4
+#define BNAD_RF_STATS_TIMER_RUNNING	5
+#define BNAD_RF_TX_SHUTDOWN_DELAYED	6
+#define BNAD_RF_RX_SHUTDOWN_DELAYED	7
 
 struct bnad {
 	struct net_device 	*netdev;
@@ -320,9 +322,11 @@ extern void bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64
 
 #define bnad_enable_rx_irq_unsafe(_ccb)			\
 {							\
-	bna_ib_coalescing_timer_set((_ccb)->i_dbell,	\
-		(_ccb)->rx_coalescing_timeo);		\
-	bna_ib_ack((_ccb)->i_dbell, 0);			\
+	if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))) {\
+		bna_ib_coalescing_timer_set((_ccb)->i_dbell,	\
+			(_ccb)->rx_coalescing_timeo);		\
+		bna_ib_ack((_ccb)->i_dbell, 0);			\
+	}							\
 }
 
 #define bnad_dim_timer_running(_bnad)				\
-- 
1.7.1


^ permalink raw reply related

* [PATCH 00/10] bna: Update Brocade BNA Ethernet driver to v2.3.2.3
From: Rasesh Mody @ 2010-12-24  7:45 UTC (permalink / raw)
  To: netdev; +Cc: huangj, Rasesh Mody

The following patch set updates the Brocade BNA driver to v2.3.2.3.

The patches are generated, compiled and tested against net-next-2.6 (2.6.37-rc1).

Rasesh Mody (10):
  bna: TxRx and datapath fix
  bna: Port enable disable sync and txq priority fix
  bna: Fix ethtool register dump and reordered an API
  bna: Enable pure priority tagged packet reception and rxf uninit
    cleanup fix
  bna: Fix for TX queue
  bna: IOC uninit check and misc cleanup
  bna: Removed unused code
  bna: Restore VLAN filter table
  bna: IOC failure auto recovery fix
  bna: Update the driver version to 2.3.2.3

 drivers/net/bna/bfa_defs.h          |   22 +-
 drivers/net/bna/bfa_defs_mfg_comm.h |   22 -
 drivers/net/bna/bfa_ioc.c           | 1219 +++++++++++++++++++++++++----------
 drivers/net/bna/bfa_ioc.h           |   49 +-
 drivers/net/bna/bfa_ioc_ct.c        |  102 +++-
 drivers/net/bna/bfi_ctreg.h         |   41 +-
 drivers/net/bna/bna.h               |    6 +-
 drivers/net/bna/bna_ctrl.c          |  377 +++--------
 drivers/net/bna/bna_txrx.c          |   44 +-
 drivers/net/bna/bna_types.h         |   11 +-
 drivers/net/bna/bnad.c              |  427 +++++++------
 drivers/net/bna/bnad.h              |   31 +-
 drivers/net/bna/bnad_ethtool.c      |    8 +-
 13 files changed, 1439 insertions(+), 920 deletions(-)


^ permalink raw reply

* [patch] vxge: remove duplicated part of check
From: Dan Carpenter @ 2010-12-24  6:15 UTC (permalink / raw)
  To: Ramkrishna Vepa
  Cc: Sivakumar Subramani, Sreenivasa Honnur, Jon Mason, netdev,
	kernel-janitors

This is just a cleanup to make the static checkers happy.  We don't need
to check "own" twice.

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

diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c
index 42cc298..4c10d6c 100644
--- a/drivers/net/vxge/vxge-traffic.c
+++ b/drivers/net/vxge/vxge-traffic.c
@@ -1240,7 +1240,7 @@ enum vxge_hw_status vxge_hw_ring_rxd_next_completed(
 	*t_code	= (u8)VXGE_HW_RING_RXD_T_CODE_GET(control_0);
 
 	/* check whether it is not the end */
-	if (!own || ((*t_code == VXGE_HW_RING_T_CODE_FRM_DROP) && own)) {
+	if (!own || *t_code == VXGE_HW_RING_T_CODE_FRM_DROP) {
 
 		vxge_assert(((struct vxge_hw_ring_rxd_1 *)rxdp)->host_control !=
 				0);

^ 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

* [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

* 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

* 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 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

* [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 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

* 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: 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

* [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: 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

* 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

* [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: 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

* 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] 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 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

* [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

* [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 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


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