* Re: [PATCH net V4 2/2] igb: offer a PTP Hardware Clock instead of the timecompare method
From: chetan loke @ 2012-03-26 19:32 UTC (permalink / raw)
To: Keller, Jacob E
Cc: e1000-devel@lists.sourceforge.net, netdev@vger.kernel.org,
Ronciak, John, john.stultz@linaro.org, tglx@linutronix.de
In-Reply-To: <02874ECE860811409154E81DA85FBB580DC04D@ORSMSX105.amr.corp.intel.com>
On Mon, Mar 26, 2012 at 2:56 PM, Keller, Jacob E
<jacob.e.keller@intel.com> wrote:
> I am curious how you see a kernel thread resolving the Tx/Rx issue? or is the
> kernel thread being used by gettime? I don't believe we can wait for the Tx/Rx
tx, rx path and kernel thread will use seq_lock_isave(tmreg_lock).
A new 'u64 cached_ns' will be introduced.
tx and rx path can update 'cached_ns' when they read the NIC counter.
A kernel-thread should be scheduled periodically, will read the NIC
counter and update cached_ns. It will use a _trylock variant. If the
lock fails then its a hint that 'cached_ns' is getting updated
somewhere, so just refresh the timer. Periodic update is needed to
handle idle/bursty link conditions because the Rx/tx path may not run
that often.
gettime uses read_seq_lock and reads 'cached_ns'. I mean we could also
do a atomic_read(?).
> path, because if we take too long the software sees it as a dropped timestamp.
What code-path is this?
> How would we only allow one app? Any app with permissions could call the ioctls.
> I do agree that having too many ioctls is a problem. Even in cases where PTP is
We don't. So this is what I'm thinking. Ideally speaking only 1 app
should be adjusting the host-clock and 1 app per NIC if you adjust
NIC's clock. Ignore the host-clock app. Once you enforce the
rate-limit, driver will return -EBUSY if you exceed it. Too many
EBUSYs will provide a hint on user-side.
Chetan
------------------------------------------------------------------------------
This SF email is sponsosred by:
Try Windows Azure free for 90 days Click Here
http://p.sf.net/sfu/sfd2d-msazure
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply
* [PATCH 0/7] bna: Update driver version to 3.0.23.0
From: Jing Huang @ 2012-03-26 19:37 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, Jing Huang
This patch set contains fixes in adapter initialization and tx/rx cleanup path.
It also include code cleanups by removing and renaming some functions.
The driver version has been updated to 3.0.23.0 to reflect the changes.
Jing Huang (7):
bna: Serialize smem access during adapter initialization
bna: Flash controller ioc pll init fixes
bna: ioc cleanups
bfa: tx rx cleanup fix
bna: Remove tx tasklet
bfa: Function name changes and cleanups
bfa: Update driver version to 3.0.23.0
drivers/net/ethernet/brocade/bna/bfa_ioc.c | 61 +++--
drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c | 142 +++++++----
drivers/net/ethernet/brocade/bna/bfi_reg.h | 6 +
drivers/net/ethernet/brocade/bna/bnad.c | 316 +++++++++++------------
drivers/net/ethernet/brocade/bna/bnad.h | 11 +-
drivers/net/ethernet/brocade/bna/bnad_ethtool.c | 6 +-
6 files changed, 300 insertions(+), 242 deletions(-)
^ permalink raw reply
* [PATCH 1/7] bna: Serialize smem access during adapter initialization
From: Jing Huang @ 2012-03-26 19:38 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, Jing Huang
Use init semaphore to serialize execution of the "unlock IOC semaphore"
code. Added bfa_ioc_fwver_clear() function to clear the firmware header if
last firmwar boot is not from driver.
Signed-off-by: Jing Huang <huangj@brocade.com>
---
drivers/net/ethernet/brocade/bna/bfa_ioc.c | 50 +++++++++++++++++++++++----
1 files changed, 42 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
index 77977d7..7a3e79c 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
@@ -1207,27 +1207,62 @@ bfa_nw_ioc_sem_release(void __iomem *sem_reg)
writel(1, sem_reg);
}
+/* Clear fwver hdr */
+static void
+bfa_ioc_fwver_clear(struct bfa_ioc *ioc)
+{
+ u32 pgnum, pgoff, loff = 0;
+ int i;
+
+ pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
+ pgoff = PSS_SMEM_PGOFF(loff);
+ writel(pgnum, ioc->ioc_regs.host_page_num_fn);
+
+ for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr) / sizeof(u32)); i++) {
+ writel(0, ioc->ioc_regs.smem_page_start + loff);
+ loff += sizeof(u32);
+ }
+}
+
+
static void
bfa_ioc_hw_sem_init(struct bfa_ioc *ioc)
{
struct bfi_ioc_image_hdr fwhdr;
- u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+ u32 fwstate, r32;
- if (fwstate == BFI_IOC_UNINIT)
+ /* Spin on init semaphore to serialize. */
+ r32 = readl(ioc->ioc_regs.ioc_init_sem_reg);
+ while (r32 & 0x1) {
+ udelay(20);
+ r32 = readl(ioc->ioc_regs.ioc_init_sem_reg);
+ }
+
+ fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+ if (fwstate == BFI_IOC_UNINIT) {
+ writel(1, ioc->ioc_regs.ioc_init_sem_reg);
return;
+ }
bfa_nw_ioc_fwver_get(ioc, &fwhdr);
- if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL)
+ if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL) {
+ writel(1, ioc->ioc_regs.ioc_init_sem_reg);
return;
+ }
+ bfa_ioc_fwver_clear(ioc);
writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+ writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
/*
* Try to lock and then unlock the semaphore.
*/
readl(ioc->ioc_regs.ioc_sem_reg);
writel(1, ioc->ioc_regs.ioc_sem_reg);
+
+ /* Unlock init semaphore */
+ writel(1, ioc->ioc_regs.ioc_init_sem_reg);
}
static void
@@ -1585,11 +1620,6 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
u32 i;
u32 asicmode;
- /**
- * Initialize LMEM first before code download
- */
- bfa_ioc_lmem_init(ioc);
-
fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
pgnum = bfa_ioc_smem_pgnum(ioc, loff);
@@ -1914,6 +1944,10 @@ bfa_ioc_pll_init(struct bfa_ioc *ioc)
bfa_ioc_pll_init_asic(ioc);
ioc->pllinit = true;
+
+ /* Initialize LMEM */
+ bfa_ioc_lmem_init(ioc);
+
/*
* release semaphore.
*/
--
1.6.5.2
^ permalink raw reply related
* [PATCH 2/7] bna: Flash controller ioc pll init fixes
From: Jing Huang @ 2012-03-26 19:38 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, Jing Huang
Added NFC pause/resume logic. We only do NFC pause/resume if NFC version
is greater than 0x143 and it was halted before, otherwise we revert to
old NFC halt mechanism.
Made changes to avoid clearing off the interrupts during the initial
pll initialization.
Signed-off-by: Jing Huang <huangj@brocade.com>
---
drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c | 142 +++++++++++++++++--------
drivers/net/ethernet/brocade/bna/bfi_reg.h | 6 +
2 files changed, 102 insertions(+), 46 deletions(-)
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c b/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c
index 348479b..b6b036a 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c
@@ -199,9 +199,9 @@ bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc)
* Host to LPU mailbox message addresses
*/
static const struct {
- u32 hfn_mbox;
- u32 lpu_mbox;
- u32 hfn_pgn;
+ u32 hfn_mbox;
+ u32 lpu_mbox;
+ u32 hfn_pgn;
} ct_fnreg[] = {
{ HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
{ HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },
@@ -803,17 +803,72 @@ bfa_ioc_ct2_mac_reset(void __iomem *rb)
}
#define CT2_NFC_MAX_DELAY 1000
+#define CT2_NFC_VER_VALID 0x143
+#define BFA_IOC_PLL_POLL 1000000
+
+static bool
+bfa_ioc_ct2_nfc_halted(void __iomem *rb)
+{
+ volatile u32 r32;
+
+ r32 = readl(rb + CT2_NFC_CSR_SET_REG);
+ if (r32 & __NFC_CONTROLLER_HALTED)
+ return true;
+
+ return false;
+}
+
+static void
+bfa_ioc_ct2_nfc_resume(void __iomem *rb)
+{
+ volatile u32 r32;
+ int i;
+
+ writel(__HALT_NFC_CONTROLLER, rb + CT2_NFC_CSR_CLR_REG);
+ for (i = 0; i < CT2_NFC_MAX_DELAY; i++) {
+ r32 = readl(rb + CT2_NFC_CSR_SET_REG);
+ if (!(r32 & __NFC_CONTROLLER_HALTED))
+ return;
+ udelay(1000);
+ }
+ BUG_ON(1);
+}
+
static enum bfa_status
bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode asic_mode)
{
volatile u32 wgn, r32;
- int i;
+ u32 nfc_ver, i;
- /*
- * Initialize PLL if not already done by NFC
- */
wgn = readl(rb + CT2_WGN_STATUS);
- if (!(wgn & __GLBL_PF_VF_CFG_RDY)) {
+
+ nfc_ver = readl(rb + CT2_RSC_GPR15_REG);
+
+ if ((wgn == (__A2T_AHB_LOAD | __WGN_READY)) &&
+ (nfc_ver >= CT2_NFC_VER_VALID)) {
+ if (bfa_ioc_ct2_nfc_halted(rb))
+ bfa_ioc_ct2_nfc_resume(rb);
+ writel(__RESET_AND_START_SCLK_LCLK_PLLS,
+ rb + CT2_CSI_FW_CTL_SET_REG);
+
+ for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
+ r32 = readl(rb + CT2_APP_PLL_LCLK_CTL_REG);
+ if (r32 & __RESET_AND_START_SCLK_LCLK_PLLS)
+ break;
+ }
+ BUG_ON(!(r32 & __RESET_AND_START_SCLK_LCLK_PLLS));
+
+ for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
+ r32 = readl(rb + CT2_APP_PLL_LCLK_CTL_REG);
+ if (!(r32 & __RESET_AND_START_SCLK_LCLK_PLLS))
+ break;
+ }
+ BUG_ON(r32 & __RESET_AND_START_SCLK_LCLK_PLLS);
+ udelay(1000);
+
+ r32 = readl(rb + CT2_CSI_FW_CTL_REG);
+ BUG_ON(r32 & __RESET_AND_START_SCLK_LCLK_PLLS);
+ } else {
writel(__HALT_NFC_CONTROLLER, (rb + CT2_NFC_CSR_SET_REG));
for (i = 0; i < CT2_NFC_MAX_DELAY; i++) {
r32 = readl(rb + CT2_NFC_CSR_SET_REG);
@@ -821,53 +876,48 @@ bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode asic_mode)
break;
udelay(1000);
}
+
+ bfa_ioc_ct2_mac_reset(rb);
+ bfa_ioc_ct2_sclk_init(rb);
+ bfa_ioc_ct2_lclk_init(rb);
+
+ /* release soft reset on s_clk & l_clk */
+ r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+ writel(r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET,
+ rb + CT2_APP_PLL_SCLK_CTL_REG);
+ r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+ writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
+ rb + CT2_APP_PLL_LCLK_CTL_REG);
+ }
+
+ /* Announce flash device presence, if flash was corrupted. */
+ if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) {
+ r32 = readl((rb + PSS_GPIO_OUT_REG));
+ writel(r32 & ~1, rb + PSS_GPIO_OUT_REG);
+ r32 = readl((rb + PSS_GPIO_OE_REG));
+ writel(r32 | 1, rb + PSS_GPIO_OE_REG);
}
/*
* Mask the interrupts and clear any
* pending interrupts left by BIOS/EFI
*/
-
writel(1, (rb + CT2_LPU0_HOSTFN_MBOX0_MSK));
writel(1, (rb + CT2_LPU1_HOSTFN_MBOX0_MSK));
- r32 = readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
- if (r32 == 1) {
- writel(1, (rb + CT2_LPU0_HOSTFN_CMD_STAT));
- readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
- }
- r32 = readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
- if (r32 == 1) {
- writel(1, (rb + CT2_LPU1_HOSTFN_CMD_STAT));
- readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
- }
-
- bfa_ioc_ct2_mac_reset(rb);
- bfa_ioc_ct2_sclk_init(rb);
- bfa_ioc_ct2_lclk_init(rb);
-
- /*
- * release soft reset on s_clk & l_clk
- */
- r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
- writel((r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET),
- (rb + CT2_APP_PLL_SCLK_CTL_REG));
-
- /*
- * release soft reset on s_clk & l_clk
- */
- r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
- writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
- (rb + CT2_APP_PLL_LCLK_CTL_REG));
-
- /*
- * Announce flash device presence, if flash was corrupted.
- */
- if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) {
- r32 = readl((rb + PSS_GPIO_OUT_REG));
- writel((r32 & ~1), (rb + PSS_GPIO_OUT_REG));
- r32 = readl((rb + PSS_GPIO_OE_REG));
- writel((r32 | 1), (rb + PSS_GPIO_OE_REG));
+ /* For first time initialization, no need to clear interrupts */
+ r32 = readl(rb + HOST_SEM5_REG);
+ if (r32 & 0x1) {
+ r32 = readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
+ if (r32 == 1) {
+ writel(1, (rb + CT2_LPU0_HOSTFN_CMD_STAT));
+ readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
+ }
+ r32 = readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
+ if (r32 == 1) {
+ writel(1, (rb + CT2_LPU1_HOSTFN_CMD_STAT));
+ readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
+ }
}
bfa_ioc_ct2_mem_init(rb);
diff --git a/drivers/net/ethernet/brocade/bna/bfi_reg.h b/drivers/net/ethernet/brocade/bna/bfi_reg.h
index efacff3..0e094fe 100644
--- a/drivers/net/ethernet/brocade/bna/bfi_reg.h
+++ b/drivers/net/ethernet/brocade/bna/bfi_reg.h
@@ -339,10 +339,16 @@ enum {
#define __A2T_AHB_LOAD 0x00000800
#define __WGN_READY 0x00000400
#define __GLBL_PF_VF_CFG_RDY 0x00000200
+#define CT2_NFC_CSR_CLR_REG 0x00027420
#define CT2_NFC_CSR_SET_REG 0x00027424
#define __HALT_NFC_CONTROLLER 0x00000002
#define __NFC_CONTROLLER_HALTED 0x00001000
+#define CT2_RSC_GPR15_REG 0x0002765c
+#define CT2_CSI_FW_CTL_REG 0x00027080
+#define __RESET_AND_START_SCLK_LCLK_PLLS 0x00010000
+#define CT2_CSI_FW_CTL_SET_REG 0x00027088
+
#define CT2_CSI_MAC0_CONTROL_REG 0x000270d0
#define __CSI_MAC_RESET 0x00000010
#define __CSI_MAC_AHB_RESET 0x00000008
--
1.6.5.2
^ permalink raw reply related
* [PATCH 3/7] bna: ioc cleanups
From: Jing Huang @ 2012-03-26 19:39 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, Jing Huang
Remove irrelevant code. Change to start Hearbeat failure moniter after IOC
become operational.
Signed-off-by: Jing Huang <huangj@brocade.com>
---
drivers/net/ethernet/brocade/bna/bfa_ioc.c | 11 +----------
1 files changed, 1 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
index 7a3e79c..0b640fa 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
@@ -70,7 +70,6 @@ static void bfa_ioc_reset(struct bfa_ioc *ioc, bool force);
static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc);
static void bfa_ioc_mbox_flush(struct bfa_ioc *ioc);
static void bfa_ioc_recover(struct bfa_ioc *ioc);
-static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc);
static void bfa_ioc_event_notify(struct bfa_ioc *, enum bfa_ioc_event);
static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);
static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
@@ -346,8 +345,6 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
switch (event) {
case IOC_E_FWRSP_GETATTR:
del_timer(&ioc->ioc_timer);
- bfa_ioc_check_attr_wwns(ioc);
- bfa_ioc_hb_monitor(ioc);
bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
break;
@@ -380,6 +377,7 @@ bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
{
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
+ bfa_ioc_hb_monitor(ioc);
}
static void
@@ -2547,13 +2545,6 @@ bfa_ioc_recover(struct bfa_ioc *ioc)
bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
}
-static void
-bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc)
-{
- if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
- return;
-}
-
/**
* @dg hal_iocpf_pvt BFA IOC PF private functions
* @{
--
1.6.5.2
^ permalink raw reply related
* [PATCH 4/7] bna: tx rx cleanup fix
From: Jing Huang @ 2012-03-26 19:39 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, Jing Huang
This patch removes busy wait in tx/rx cleanup. bnad_cb_tx_cleanup() and
bnad_cb_rx_cleanup() functions are called from irq context, and currently
they do busy wait for the in-flight transmit or the currently executing napi
polling routine to complete. To fix the issue, we create a workqueue to defer
tx & rx cleanup processing, an in the tx rx cleanup handler, we will
wait respective in flight processing to complete, before freeing the buffers.
Signed-off-by: Jing Huang <huangj@brocade.com>
---
drivers/net/ethernet/brocade/bna/bnad.c | 201 +++++++++++++++++++------------
drivers/net/ethernet/brocade/bna/bnad.h | 4 +
2 files changed, 125 insertions(+), 80 deletions(-)
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index ff78f77..032a306 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -80,8 +80,6 @@ do { \
(sizeof(struct bnad_skb_unmap) * ((_depth) - 1)); \
} while (0)
-#define BNAD_TXRX_SYNC_MDELAY 250 /* 250 msecs */
-
static void
bnad_add_to_list(struct bnad *bnad)
{
@@ -141,7 +139,8 @@ bnad_pci_unmap_skb(struct device *pdev, struct bnad_skb_unmap *array,
for (j = 0; j < frag; j++) {
dma_unmap_page(pdev, dma_unmap_addr(&array[index], dma_addr),
- skb_frag_size(&skb_shinfo(skb)->frags[j]), DMA_TO_DEVICE);
+ skb_frag_size(&skb_shinfo(skb)->frags[j]),
+ DMA_TO_DEVICE);
dma_unmap_addr_set(&array[index], dma_addr, 0);
BNA_QE_INDX_ADD(index, 1, depth);
}
@@ -453,12 +452,8 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl);
- set_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
-
- if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)) {
- clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
+ 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,
@@ -533,9 +528,8 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
if (skb->ip_summed == CHECKSUM_UNNECESSARY)
napi_gro_receive(&rx_ctrl->napi, skb);
- else {
+ else
netif_receive_skb(skb);
- }
next:
cmpl->valid = 0;
@@ -839,20 +833,9 @@ 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;
+ tcb->priv = NULL;
}
static void
@@ -866,12 +849,6 @@ 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 =
@@ -916,7 +893,6 @@ bnad_cb_tx_resume(struct bnad *bnad, struct bna_tx *tx)
{
struct bnad_tx_info *tx_info = (struct bnad_tx_info *)tx->priv;
struct bna_tcb *tcb;
- struct bnad_unmap_q *unmap_q;
u32 txq_id;
int i;
@@ -926,23 +902,9 @@ bnad_cb_tx_resume(struct bnad *bnad, struct bna_tx *tx)
continue;
txq_id = tcb->id;
- unmap_q = tcb->unmap_q;
-
- if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
- continue;
-
- 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);
-
+ BUG_ON(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags));
set_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
+ BUG_ON(*(tcb->hw_consumer_index) != 0);
if (netif_carrier_ok(bnad->netdev)) {
printk(KERN_INFO "bna: %s %d TXQ_STARTED\n",
@@ -963,6 +925,54 @@ bnad_cb_tx_resume(struct bnad *bnad, struct bna_tx *tx)
}
}
+/*
+ * Free all TxQs buffers and then notify TX_E_CLEANUP_DONE to Tx fsm.
+ */
+static void
+bnad_tx_cleanup(struct delayed_work *work)
+{
+ struct bnad_tx_info *tx_info =
+ container_of(work, struct bnad_tx_info, tx_cleanup_work);
+ struct bnad *bnad = NULL;
+ struct bnad_unmap_q *unmap_q;
+ struct bna_tcb *tcb;
+ unsigned long flags;
+ uint32_t i, pending = 0;
+
+ for (i = 0; i < BNAD_MAX_TXQ_PER_TX; i++) {
+ tcb = tx_info->tcb[i];
+ if (!tcb)
+ continue;
+
+ bnad = tcb->bnad;
+
+ if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
+ pending++;
+ continue;
+ }
+
+ bnad_free_all_txbufs(bnad, tcb);
+
+ unmap_q = tcb->unmap_q;
+ unmap_q->producer_index = 0;
+ unmap_q->consumer_index = 0;
+
+ smp_mb__before_clear_bit();
+ clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+ }
+
+ if (pending) {
+ queue_delayed_work(bnad->work_q, &tx_info->tx_cleanup_work,
+ msecs_to_jiffies(1));
+ return;
+ }
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_tx_cleanup_complete(tx_info->tx);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+
static void
bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tx *tx)
{
@@ -976,8 +986,7 @@ bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tx *tx)
continue;
}
- mdelay(BNAD_TXRX_SYNC_MDELAY);
- bna_tx_cleanup_complete(tx);
+ queue_delayed_work(bnad->work_q, &tx_info->tx_cleanup_work, 0);
}
static void
@@ -1001,6 +1010,44 @@ bnad_cb_rx_stall(struct bnad *bnad, struct bna_rx *rx)
}
}
+/*
+ * Free all RxQs buffers and then notify RX_E_CLEANUP_DONE to Rx fsm.
+ */
+static void
+bnad_rx_cleanup(void *work)
+{
+ struct bnad_rx_info *rx_info =
+ container_of(work, struct bnad_rx_info, rx_cleanup_work);
+ struct bnad_rx_ctrl *rx_ctrl;
+ struct bnad *bnad = NULL;
+ unsigned long flags;
+ uint32_t i;
+
+ for (i = 0; i < BNAD_MAX_RXP_PER_RX; i++) {
+ rx_ctrl = &rx_info->rx_ctrl[i];
+
+ if (!rx_ctrl->ccb)
+ continue;
+
+ bnad = rx_ctrl->ccb->bnad;
+
+ /*
+ * Wait till the poll handler has exited
+ * and nothing can be scheduled anymore
+ */
+ napi_disable(&rx_ctrl->napi);
+
+ bnad_cq_cmpl_init(bnad, rx_ctrl->ccb);
+ bnad_free_all_rxbufs(bnad, rx_ctrl->ccb->rcb[0]);
+ if (rx_ctrl->ccb->rcb[1])
+ bnad_free_all_rxbufs(bnad, rx_ctrl->ccb->rcb[1]);
+ }
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_rx_cleanup_complete(rx_info->rx);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
static void
bnad_cb_rx_cleanup(struct bnad *bnad, struct bna_rx *rx)
{
@@ -1009,8 +1056,6 @@ bnad_cb_rx_cleanup(struct bnad *bnad, struct bna_rx *rx)
struct bnad_rx_ctrl *rx_ctrl;
int i;
- mdelay(BNAD_TXRX_SYNC_MDELAY);
-
for (i = 0; i < BNAD_MAX_RXP_PER_RX; i++) {
rx_ctrl = &rx_info->rx_ctrl[i];
ccb = rx_ctrl->ccb;
@@ -1021,12 +1066,9 @@ bnad_cb_rx_cleanup(struct bnad *bnad, struct bna_rx *rx)
if (ccb->rcb[1])
clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags);
-
- while (test_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags))
- cpu_relax();
}
- bna_rx_cleanup_complete(rx);
+ queue_work(bnad->work_q, &rx_info->rx_cleanup_work);
}
static void
@@ -1046,13 +1088,12 @@ bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx)
if (!ccb)
continue;
- bnad_cq_cmpl_init(bnad, ccb);
+ napi_enable(&rx_ctrl->napi);
for (j = 0; j < BNAD_MAX_RXQ_PER_RXP; j++) {
rcb = ccb->rcb[j];
if (!rcb)
continue;
- bnad_free_all_rxbufs(bnad, rcb);
set_bit(BNAD_RXQ_STARTED, &rcb->flags);
set_bit(BNAD_RXQ_POST_OK, &rcb->flags);
@@ -1704,7 +1745,7 @@ poll_exit:
#define BNAD_NAPI_POLL_QUOTA 64
static void
-bnad_napi_init(struct bnad *bnad, u32 rx_id)
+bnad_napi_add(struct bnad *bnad, u32 rx_id)
{
struct bnad_rx_ctrl *rx_ctrl;
int i;
@@ -1718,29 +1759,13 @@ bnad_napi_init(struct bnad *bnad, u32 rx_id)
}
static void
-bnad_napi_enable(struct bnad *bnad, u32 rx_id)
-{
- struct bnad_rx_ctrl *rx_ctrl;
- int i;
-
- /* Initialize & enable NAPI */
- for (i = 0; i < bnad->num_rxp_per_rx; i++) {
- rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i];
-
- napi_enable(&rx_ctrl->napi);
- }
-}
-
-static void
-bnad_napi_disable(struct bnad *bnad, u32 rx_id)
+bnad_napi_delete(struct bnad *bnad, u32 rx_id)
{
int i;
/* First disable and then clean up */
- for (i = 0; i < bnad->num_rxp_per_rx; i++) {
- napi_disable(&bnad->rx_info[rx_id].rx_ctrl[i].napi);
+ for (i = 0; i < bnad->num_rxp_per_rx; i++)
netif_napi_del(&bnad->rx_info[rx_id].rx_ctrl[i].napi);
- }
}
/* Should be held with conf_lock held */
@@ -1832,6 +1857,9 @@ bnad_setup_tx(struct bnad *bnad, u32 tx_id)
goto err_return;
tx_info->tx = tx;
+ INIT_DELAYED_WORK(&tx_info->tx_cleanup_work,
+ (work_func_t)bnad_tx_cleanup);
+
/* Register ISR for the Tx object */
if (intr_info->intr_type == BNA_INTR_T_MSIX) {
err = bnad_tx_msix_register(bnad, tx_info,
@@ -1928,7 +1956,7 @@ bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
if (rx_info->rx_ctrl[0].ccb->intr_type == BNA_INTR_T_MSIX)
bnad_rx_msix_unregister(bnad, rx_info, rx_config->num_paths);
- bnad_napi_disable(bnad, rx_id);
+ bnad_napi_delete(bnad, rx_id);
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_rx_destroy(rx_info->rx);
@@ -1952,7 +1980,7 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
static const struct bna_rx_event_cbfn rx_cbfn = {
.rcb_setup_cbfn = bnad_cb_rcb_setup,
- .rcb_destroy_cbfn = bnad_cb_rcb_destroy,
+ .rcb_destroy_cbfn = NULL,
.ccb_setup_cbfn = bnad_cb_ccb_setup,
.ccb_destroy_cbfn = bnad_cb_ccb_destroy,
.rx_stall_cbfn = bnad_cb_rx_stall,
@@ -1998,11 +2026,14 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
rx_info->rx = rx;
spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ INIT_WORK(&rx_info->rx_cleanup_work,
+ (work_func_t)(bnad_rx_cleanup));
+
/*
* Init NAPI, so that state is set to NAPI_STATE_SCHED,
* so that IRQ handler cannot schedule NAPI at this point.
*/
- bnad_napi_init(bnad, rx_id);
+ bnad_napi_add(bnad, rx_id);
/* Register ISR for the Rx object */
if (intr_info->intr_type == BNA_INTR_T_MSIX) {
@@ -2028,9 +2059,6 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
bna_rx_enable(rx);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- /* Enable scheduling of NAPI */
- bnad_napi_enable(bnad, rx_id);
-
return 0;
err_return:
@@ -3129,6 +3157,7 @@ bnad_netdev_init(struct bnad *bnad, bool using_dac)
* 2. Setup netdev pointer in pci_dev
* 3. Initialze Tx free tasklet
* 4. Initialize no. of TxQ & CQs & MSIX vectors
+ * 5. Initialize work queue.
*/
static int
bnad_init(struct bnad *bnad,
@@ -3174,6 +3203,12 @@ bnad_init(struct bnad *bnad,
tasklet_init(&bnad->tx_free_tasklet, bnad_tx_free_tasklet,
(unsigned long)bnad);
+ sprintf(bnad->wq_name, "%s_wq_%d", BNAD_NAME, bnad->id);
+ bnad->work_q = create_singlethread_workqueue(bnad->wq_name);
+
+ if (!bnad->work_q)
+ return -ENOMEM;
+
return 0;
}
@@ -3185,6 +3220,12 @@ bnad_init(struct bnad *bnad,
static void
bnad_uninit(struct bnad *bnad)
{
+ if (bnad->work_q) {
+ flush_workqueue(bnad->work_q);
+ destroy_workqueue(bnad->work_q);
+ bnad->work_q = NULL;
+ }
+
if (bnad->bar0)
iounmap(bnad->bar0);
pci_set_drvdata(bnad->pcidev, NULL);
diff --git a/drivers/net/ethernet/brocade/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h
index 55824d9..ff129aa 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.h
+++ b/drivers/net/ethernet/brocade/bna/bnad.h
@@ -210,6 +210,7 @@ struct bnad_tx_info {
struct bna_tx *tx; /* 1:1 between tx_info & tx */
struct bna_tcb *tcb[BNAD_MAX_TXQ_PER_TX];
u32 tx_id;
+ struct delayed_work tx_cleanup_work;
} ____cacheline_aligned;
struct bnad_rx_info {
@@ -217,6 +218,7 @@ struct bnad_rx_info {
struct bnad_rx_ctrl rx_ctrl[BNAD_MAX_RXP_PER_RX];
u32 rx_id;
+ struct work_struct rx_cleanup_work;
} ____cacheline_aligned;
/* Unmap queues for Tx / Rx cleanup */
@@ -319,6 +321,7 @@ struct bnad {
mac_t perm_addr;
struct tasklet_struct tx_free_tasklet;
+ struct workqueue_struct *work_q;
/* Statistics */
struct bnad_stats stats;
@@ -328,6 +331,7 @@ struct bnad {
char adapter_name[BNAD_NAME_LEN];
char port_name[BNAD_NAME_LEN];
char mbox_irq_name[BNAD_NAME_LEN];
+ char wq_name[BNAD_NAME_LEN];
/* debugfs specific data */
char *regdata;
--
1.6.5.2
^ permalink raw reply related
* [PATCH 5/7] bna: Remove tx tasklet
From: Jing Huang @ 2012-03-26 19:40 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, Jing Huang
The scheduling of tasklet and keeping the interrupts enabled makes interrupt
reduntant. 20% of the Tx interrupts have nothing left to process or could not
process as Tx tasklet was running.
Signed-off-by: Jing Huang <huangj@brocade.com>
---
drivers/net/ethernet/brocade/bna/bnad.c | 73 +-----------------------------
drivers/net/ethernet/brocade/bna/bnad.h | 1 -
2 files changed, 3 insertions(+), 71 deletions(-)
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 032a306..f1103e6 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -185,7 +185,6 @@ bnad_free_all_txbufs(struct bnad *bnad,
* bnad_free_txbufs : Frees the Tx bufs on Tx completion
* Can be called in a) Interrupt context
* b) Sending context
- * c) Tasklet context
*/
static u32
bnad_free_txbufs(struct bnad *bnad,
@@ -197,13 +196,7 @@ bnad_free_txbufs(struct bnad *bnad,
struct bnad_skb_unmap *unmap_array;
struct sk_buff *skb;
- /*
- * 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_TXQ_TX_STARTED bit
- * but this routine runs actually after the cleanup has been
- * executed.
- */
+ /* Just return if TX is stopped */
if (!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
return 0;
@@ -242,55 +235,6 @@ bnad_free_txbufs(struct bnad *bnad,
return sent_packets;
}
-/* Tx Free Tasklet function */
-/* Frees for all the tcb's in all the Tx's */
-/*
- * Scheduled from sending context, so that
- * the fat Tx lock is not held for too long
- * in the sending context.
- */
-static void
-bnad_tx_free_tasklet(unsigned long bnad_ptr)
-{
- struct bnad *bnad = (struct bnad *)bnad_ptr;
- struct bna_tcb *tcb;
- u32 acked = 0;
- int i, j;
-
- 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];
- if (!tcb)
- continue;
- if (((u16) (*tcb->hw_consumer_index) !=
- tcb->consumer_index) &&
- (!test_and_set_bit(BNAD_TXQ_FREE_SENT,
- &tcb->flags))) {
- acked = bnad_free_txbufs(bnad, tcb);
- 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);
- }
- if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED,
- &tcb->flags)))
- continue;
- if (netif_queue_stopped(bnad->netdev)) {
- if (acked && netif_carrier_ok(bnad->netdev) &&
- BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
- BNAD_NETIF_WAKE_THRESHOLD) {
- netif_wake_queue(bnad->netdev);
- /* TODO */
- /* Counters for individual TxQs? */
- BNAD_UPDATE_CTR(bnad,
- netif_queue_wakeup);
- }
- }
- }
- }
-}
-
static u32
bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
{
@@ -1789,9 +1733,6 @@ bnad_cleanup_tx(struct bnad *bnad, u32 tx_id)
bnad_tx_msix_unregister(bnad, tx_info,
bnad->num_txq_per_tx);
- if (0 == tx_id)
- tasklet_kill(&bnad->tx_free_tasklet);
-
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_tx_destroy(tx_info->tx);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -2871,9 +2812,6 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
bna_txq_prod_indx_doorbell(tcb);
smp_mb();
- if ((u16) (*tcb->hw_consumer_index) != tcb->consumer_index)
- tasklet_schedule(&bnad->tx_free_tasklet);
-
return NETDEV_TX_OK;
}
@@ -3155,9 +3093,8 @@ bnad_netdev_init(struct bnad *bnad, bool using_dac)
/*
* 1. Initialize the bnad structure
* 2. Setup netdev pointer in pci_dev
- * 3. Initialze Tx free tasklet
- * 4. Initialize no. of TxQ & CQs & MSIX vectors
- * 5. Initialize work queue.
+ * 3. Initialize no. of TxQ & CQs & MSIX vectors
+ * 4. Initialize work queue.
*/
static int
bnad_init(struct bnad *bnad,
@@ -3200,9 +3137,6 @@ bnad_init(struct bnad *bnad,
bnad->tx_coalescing_timeo = BFI_TX_COALESCING_TIMEO;
bnad->rx_coalescing_timeo = BFI_RX_COALESCING_TIMEO;
- tasklet_init(&bnad->tx_free_tasklet, bnad_tx_free_tasklet,
- (unsigned long)bnad);
-
sprintf(bnad->wq_name, "%s_wq_%d", BNAD_NAME, bnad->id);
bnad->work_q = create_singlethread_workqueue(bnad->wq_name);
@@ -3345,7 +3279,6 @@ bnad_pci_probe(struct pci_dev *pdev,
/*
* Initialize bnad structure
* Setup relation between pci_dev & netdev
- * Init Tx free tasklet
*/
err = bnad_init(bnad, pdev, netdev);
if (err)
diff --git a/drivers/net/ethernet/brocade/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h
index ff129aa..cf1d3ba 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.h
+++ b/drivers/net/ethernet/brocade/bna/bnad.h
@@ -320,7 +320,6 @@ struct bnad {
/* Burnt in MAC address */
mac_t perm_addr;
- struct tasklet_struct tx_free_tasklet;
struct workqueue_struct *work_q;
/* Statistics */
--
1.6.5.2
^ permalink raw reply related
* [PATCH 6/7] bna: Function name changes and cleanups
From: Jing Huang @ 2012-03-26 19:40 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, Jing Huang
Renamed following functions:
bnad_cleanup_tx to bnad_destroy_tx
bnad_free_all_txbufs to bnad_txq_cleanup
bnad_free_txbufs to bnad_txcmpl_process
bnad_tx to bnad_tx_complete
bnad_cleanup_rx to bnad_destroy_rx
bnad_reset_rcb to bnad_rcb_cleanup
bnad_free_all_rxbufs to bnad_rxq_cleanup
bnad_cq_cmpl_init to bnad_cq_cleanup
bnad_alloc_n_post_rxbufs to bnad_rxq_post
bnad_poll_cq to bnad_cq_process
Signed-off-by: Jing Huang <huangj@brocade.com>
---
drivers/net/ethernet/brocade/bna/bnad.c | 54 +++++++++++-----------
drivers/net/ethernet/brocade/bna/bnad.h | 4 +-
drivers/net/ethernet/brocade/bna/bnad_ethtool.c | 6 +-
3 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index f1103e6..25c4e7f 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -101,7 +101,7 @@ bnad_remove_from_list(struct bnad *bnad)
* Reinitialize completions in CQ, once Rx is taken down
*/
static void
-bnad_cq_cmpl_init(struct bnad *bnad, struct bna_ccb *ccb)
+bnad_cq_cleanup(struct bnad *bnad, struct bna_ccb *ccb)
{
struct bna_cq_entry *cmpl, *next_cmpl;
unsigned int wi_range, wis = 0, ccb_prod = 0;
@@ -154,7 +154,7 @@ bnad_pci_unmap_skb(struct device *pdev, struct bnad_skb_unmap *array,
* so DMA unmap & freeing is fine.
*/
static void
-bnad_free_all_txbufs(struct bnad *bnad,
+bnad_txq_cleanup(struct bnad *bnad,
struct bna_tcb *tcb)
{
u32 unmap_cons;
@@ -182,12 +182,12 @@ bnad_free_all_txbufs(struct bnad *bnad,
/* Data Path Handlers */
/*
- * bnad_free_txbufs : Frees the Tx bufs on Tx completion
+ * bnad_txcmpl_process : Frees the Tx bufs on Tx completion
* Can be called in a) Interrupt context
* b) Sending context
*/
static u32
-bnad_free_txbufs(struct bnad *bnad,
+bnad_txcmpl_process(struct bnad *bnad,
struct bna_tcb *tcb)
{
u32 unmap_cons, sent_packets = 0, sent_bytes = 0;
@@ -236,7 +236,7 @@ bnad_free_txbufs(struct bnad *bnad,
}
static u32
-bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
+bnad_tx_complete(struct bnad *bnad, struct bna_tcb *tcb)
{
struct net_device *netdev = bnad->netdev;
u32 sent = 0;
@@ -244,7 +244,7 @@ bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
return 0;
- sent = bnad_free_txbufs(bnad, tcb);
+ sent = bnad_txcmpl_process(bnad, tcb);
if (sent) {
if (netif_queue_stopped(netdev) &&
netif_carrier_ok(netdev) &&
@@ -273,13 +273,13 @@ bnad_msix_tx(int irq, void *data)
struct bna_tcb *tcb = (struct bna_tcb *)data;
struct bnad *bnad = tcb->bnad;
- bnad_tx(bnad, tcb);
+ bnad_tx_complete(bnad, tcb);
return IRQ_HANDLED;
}
static void
-bnad_reset_rcb(struct bnad *bnad, struct bna_rcb *rcb)
+bnad_rcb_cleanup(struct bnad *bnad, struct bna_rcb *rcb)
{
struct bnad_unmap_q *unmap_q = rcb->unmap_q;
@@ -291,7 +291,7 @@ bnad_reset_rcb(struct bnad *bnad, struct bna_rcb *rcb)
}
static void
-bnad_free_all_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
+bnad_rxq_cleanup(struct bnad *bnad, struct bna_rcb *rcb)
{
struct bnad_unmap_q *unmap_q;
struct bnad_skb_unmap *unmap_array;
@@ -312,11 +312,11 @@ bnad_free_all_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
DMA_FROM_DEVICE);
dev_kfree_skb(skb);
}
- bnad_reset_rcb(bnad, rcb);
+ bnad_rcb_cleanup(bnad, rcb);
}
static void
-bnad_alloc_n_post_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
+bnad_rxq_post(struct bnad *bnad, struct bna_rcb *rcb)
{
u16 to_alloc, alloced, unmap_prod, wi_range;
struct bnad_unmap_q *unmap_q = rcb->unmap_q;
@@ -377,14 +377,14 @@ bnad_refill_rxq(struct bnad *bnad, struct bna_rcb *rcb)
if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
>> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
- bnad_alloc_n_post_rxbufs(bnad, rcb);
+ bnad_rxq_post(bnad, rcb);
smp_mb__before_clear_bit();
clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
}
}
static u32
-bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
+bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget)
{
struct bna_cq_entry *cmpl, *next_cmpl;
struct bna_rcb *rcb = NULL;
@@ -584,7 +584,7 @@ bnad_isr(int irq, void *data)
for (j = 0; j < bnad->num_txq_per_tx; j++) {
tcb = bnad->tx_info[i].tcb[j];
if (tcb && test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
- bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
+ bnad_tx_complete(bnad, bnad->tx_info[i].tcb[j]);
}
}
/* Rx processing */
@@ -895,7 +895,7 @@ bnad_tx_cleanup(struct delayed_work *work)
continue;
}
- bnad_free_all_txbufs(bnad, tcb);
+ bnad_txq_cleanup(bnad, tcb);
unmap_q = tcb->unmap_q;
unmap_q->producer_index = 0;
@@ -981,10 +981,10 @@ bnad_rx_cleanup(void *work)
*/
napi_disable(&rx_ctrl->napi);
- bnad_cq_cmpl_init(bnad, rx_ctrl->ccb);
- bnad_free_all_rxbufs(bnad, rx_ctrl->ccb->rcb[0]);
+ bnad_cq_cleanup(bnad, rx_ctrl->ccb);
+ bnad_rxq_cleanup(bnad, rx_ctrl->ccb->rcb[0]);
if (rx_ctrl->ccb->rcb[1])
- bnad_free_all_rxbufs(bnad, rx_ctrl->ccb->rcb[1]);
+ bnad_rxq_cleanup(bnad, rx_ctrl->ccb->rcb[1]);
}
spin_lock_irqsave(&bnad->bna_lock, flags);
@@ -1048,7 +1048,7 @@ bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx)
if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
>> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
- bnad_alloc_n_post_rxbufs(bnad, rcb);
+ bnad_rxq_post(bnad, rcb);
smp_mb__before_clear_bit();
clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
}
@@ -1672,7 +1672,7 @@ bnad_napi_poll_rx(struct napi_struct *napi, int budget)
if (!netif_carrier_ok(bnad->netdev))
goto poll_exit;
- rcvd = bnad_poll_cq(bnad, rx_ctrl->ccb, budget);
+ rcvd = bnad_cq_process(bnad, rx_ctrl->ccb, budget);
if (rcvd >= budget)
return rcvd;
@@ -1714,7 +1714,7 @@ bnad_napi_delete(struct bnad *bnad, u32 rx_id)
/* Should be held with conf_lock held */
void
-bnad_cleanup_tx(struct bnad *bnad, u32 tx_id)
+bnad_destroy_tx(struct bnad *bnad, u32 tx_id)
{
struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0];
@@ -1865,7 +1865,7 @@ bnad_rx_ctrl_init(struct bnad *bnad, u32 rx_id)
/* Called with mutex_lock(&bnad->conf_mutex) held */
void
-bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
+bnad_destroy_rx(struct bnad *bnad, u32 rx_id)
{
struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
@@ -2003,7 +2003,7 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
return 0;
err_return:
- bnad_cleanup_rx(bnad, rx_id);
+ bnad_destroy_rx(bnad, rx_id);
return err;
}
@@ -2488,7 +2488,7 @@ bnad_open(struct net_device *netdev)
return 0;
cleanup_tx:
- bnad_cleanup_tx(bnad, 0);
+ bnad_destroy_tx(bnad, 0);
err_return:
mutex_unlock(&bnad->conf_mutex);
@@ -2515,8 +2515,8 @@ bnad_stop(struct net_device *netdev)
wait_for_completion(&bnad->bnad_completions.enet_comp);
- bnad_cleanup_tx(bnad, 0);
- bnad_cleanup_rx(bnad, 0);
+ bnad_destroy_tx(bnad, 0);
+ bnad_destroy_rx(bnad, 0);
/* Synchronize mailbox IRQ */
bnad_mbox_irq_sync(bnad);
@@ -2589,7 +2589,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
if ((u16) (*tcb->hw_consumer_index) !=
tcb->consumer_index &&
!test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
- acked = bnad_free_txbufs(bnad, tcb);
+ acked = bnad_txcmpl_process(bnad, tcb);
if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
bna_ib_ack(tcb->i_dbell, acked);
smp_mb__before_clear_bit();
diff --git a/drivers/net/ethernet/brocade/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h
index cf1d3ba..d73967a 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.h
+++ b/drivers/net/ethernet/brocade/bna/bnad.h
@@ -373,8 +373,8 @@ extern void bnad_rx_coalescing_timeo_set(struct bnad *bnad);
extern int bnad_setup_rx(struct bnad *bnad, u32 rx_id);
extern int bnad_setup_tx(struct bnad *bnad, u32 tx_id);
-extern void bnad_cleanup_tx(struct bnad *bnad, u32 tx_id);
-extern void bnad_cleanup_rx(struct bnad *bnad, u32 rx_id);
+extern void bnad_destroy_tx(struct bnad *bnad, u32 tx_id);
+extern void bnad_destroy_rx(struct bnad *bnad, u32 rx_id);
/* Timer start/stop protos */
extern void bnad_dim_timer_start(struct bnad *bnad);
diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
index ab753d7..40e1e84 100644
--- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
@@ -464,7 +464,7 @@ bnad_set_ringparam(struct net_device *netdev,
for (i = 0; i < bnad->num_rx; i++) {
if (!bnad->rx_info[i].rx)
continue;
- bnad_cleanup_rx(bnad, i);
+ bnad_destroy_rx(bnad, i);
current_err = bnad_setup_rx(bnad, i);
if (current_err && !err)
err = current_err;
@@ -492,7 +492,7 @@ bnad_set_ringparam(struct net_device *netdev,
for (i = 0; i < bnad->num_tx; i++) {
if (!bnad->tx_info[i].tx)
continue;
- bnad_cleanup_tx(bnad, i);
+ bnad_destroy_tx(bnad, i);
current_err = bnad_setup_tx(bnad, i);
if (current_err && !err)
err = current_err;
@@ -539,7 +539,7 @@ bnad_set_pauseparam(struct net_device *netdev,
}
static void
-bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
+bnad_get_strings(struct net_device *netdev, u32 stringset, u8 *string)
{
struct bnad *bnad = netdev_priv(netdev);
int i, j, q_num;
--
1.6.5.2
^ permalink raw reply related
* [PATCH 7/7] bna: Update driver version to 3.0.23.0
From: Jing Huang @ 2012-03-26 19:41 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, Jing Huang
Driver version update
Signed-off-by: Jing Huang <huangj@brocade.com>
---
drivers/net/ethernet/brocade/bna/bnad.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/brocade/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h
index d73967a..72742be 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.h
+++ b/drivers/net/ethernet/brocade/bna/bnad.h
@@ -71,7 +71,7 @@ struct bnad_rx_ctrl {
#define BNAD_NAME "bna"
#define BNAD_NAME_LEN 64
-#define BNAD_VERSION "3.0.2.2"
+#define BNAD_VERSION "3.0.23.0"
#define BNAD_MAILBOX_MSIX_INDEX 0
#define BNAD_MAILBOX_MSIX_VECTORS 1
--
1.6.5.2
^ permalink raw reply related
* Re: [PATCH V2 4/7] net/mlx4_en: Set max rate-limit for a TC
From: Roland Dreier @ 2012-03-26 19:49 UTC (permalink / raw)
To: Amir Vadai
Cc: David S. Miller, netdev, Yevgeny Petrilin, Oren Duer, Amir Vadai
In-Reply-To: <1332752874-8086-5-git-send-email-amirv@mellanox.com>
On Mon, Mar 26, 2012 at 2:07 AM, Amir Vadai <amirv@mellanox.com> wrote:
> Values in Mbps units.
Hopefully not nitpicking too much, but Mbps still seems to coarse to me.
Eg in wireless world I can imagine wanting to limit a tos to a small # of kbps.
If this is done through netlink, the ABI can use a small unit and then tc
can accept abbreviations for kbps / Mbps / Gbps?
- R.
^ permalink raw reply
* Re: socket option IP_MSFILTER questions and observations
From: David Miller @ 2012-03-26 20:14 UTC (permalink / raw)
To: cedric.jehasse; +Cc: netdev
In-Reply-To: <4F708E08.7040500@softathome.com>
From: Cedric Jehasse <cedric.jehasse@softathome.com>
Date: Mon, 26 Mar 2012 17:40:56 +0200
> This message and any attachments herein are confidential, intended
> solely for the addressees and are SoftAtHome's ownership. Any
> unauthorized use or dissemination is prohibited. If you are not the
> intended addressee of this message, please cancel it immediately and
> inform the sender.
Do not send posting to this mailing list with such disclaimers, they
make absolutely no sense on a publicly distributed mailing list that
anyone in the world can legitimately read.
^ permalink raw reply
* [PATCH 2/2] be2net: Added functionality to support RoCE driver
From: Parav Pandit @ 2012-03-27 0:27 UTC (permalink / raw)
To: netdev, linux-rdma; +Cc: Parav Pandit
In-Reply-To: <1332808033-29985-2-git-send-email-parav.pandit@emulex.com>
From: Parav Pandit <parav.pandit@emulex.com>
- Increased MSIX vectors by 5 for RoCE traffic.
- Added macro to check roce support on a device.
- Added device specific doorbell, msix vector fields shared with nic functionality.
- Provides RoCE driver registration and deregistration functions.
- Added support functions which will be invoked on adapter
add/remove and port up/down events.
- Traverses through the list of adapters for invoking callback functions
Signed-off-by: Parav Pandit <parav.pandit@emulex.com>
---
drivers/net/ethernet/emulex/benet/Makefile | 2 +-
drivers/net/ethernet/emulex/benet/be.h | 38 ++++++-
drivers/net/ethernet/emulex/benet/be_cmds.h | 1 +
drivers/net/ethernet/emulex/benet/be_hw.h | 4 +-
drivers/net/ethernet/emulex/benet/be_main.c | 88 +++++++++++--
drivers/net/ethernet/emulex/benet/be_roce.c | 182 +++++++++++++++++++++++++++
drivers/net/ethernet/emulex/benet/be_roce.h | 75 +++++++++++
7 files changed, 375 insertions(+), 15 deletions(-)
create mode 100644 drivers/net/ethernet/emulex/benet/be_roce.c
create mode 100644 drivers/net/ethernet/emulex/benet/be_roce.h
diff --git a/drivers/net/ethernet/emulex/benet/Makefile b/drivers/net/ethernet/emulex/benet/Makefile
index a60cd80..1a91b27 100644
--- a/drivers/net/ethernet/emulex/benet/Makefile
+++ b/drivers/net/ethernet/emulex/benet/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_BE2NET) += be2net.o
-be2net-y := be_main.o be_cmds.o be_ethtool.o
+be2net-y := be_main.o be_cmds.o be_ethtool.o be_roce.o
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index ab24e46..15d0c88 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -32,6 +32,7 @@
#include <linux/u64_stats_sync.h>
#include "be_hw.h"
+#include "be_roce.h"
#define DRV_VER "4.2.116u"
#define DRV_NAME "be2net"
@@ -98,7 +99,8 @@ static inline char *nic_name(struct pci_dev *pdev)
#define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */
#define MAX_TX_QS 8
-#define MAX_MSIX_VECTORS MAX_RSS_QS
+#define MAX_ROCE_EQS 5
+#define MAX_MSIX_VECTORS (MAX_RSS_QS + MAX_ROCE_EQS) /* RSS qs + RoCE */
#define BE_TX_BUDGET 256
#define BE_NAPI_WEIGHT 64
#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */
@@ -376,6 +378,17 @@ struct be_adapter {
u8 transceiver;
u8 autoneg;
u8 generation; /* BladeEngine ASIC generation */
+ u32 if_type;
+ struct {
+ u8 __iomem *base; /* Door Bell */
+ u32 size;
+ u32 total_size;
+ u64 io_addr;
+ } roce_db;
+ u32 num_msix_roce_vec;
+ struct ocrdma_dev *ocrdma_dev;
+ struct list_head entry;
+
u32 flash_status;
struct completion flash_compl;
@@ -403,6 +416,10 @@ struct be_adapter {
#define lancer_chip(adapter) ((adapter->pdev->device == OC_DEVICE_ID3) || \
(adapter->pdev->device == OC_DEVICE_ID4))
+#define be_roce_supported(adapter) ((adapter->if_type == SLI_INTF_TYPE_3 || \
+ adapter->sli_family == SKYHAWK_SLI_FAMILY) && \
+ (adapter->function_mode & RDMA_ENABLED))
+
extern const struct ethtool_ops be_ethtool_ops;
#define msix_enabled(adapter) (adapter->num_msix_vec > 0)
@@ -549,9 +566,28 @@ static inline bool be_error(struct be_adapter *adapter)
return adapter->eeh_err || adapter->ue_detected || adapter->fw_timeout;
}
+static inline bool be_type_2_3(struct be_adapter *adapter)
+{
+ return (adapter->if_type == SLI_INTF_TYPE_2 ||
+ adapter->if_type == SLI_INTF_TYPE_3) ? true : false;
+}
+
extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
u16 num_popped);
extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
extern void be_parse_stats(struct be_adapter *adapter);
extern int be_load_fw(struct be_adapter *adapter, u8 *func);
+
+/*
+ * internal function to initialize-cleanup roce device.
+ */
+extern void be_roce_dev_add(struct be_adapter *);
+extern void be_roce_dev_remove(struct be_adapter *);
+
+/*
+ * internal function to open-close roce device during ifup-ifdown.
+ */
+extern void be_roce_dev_open(struct be_adapter *);
+extern void be_roce_dev_close(struct be_adapter *);
+
#endif /* BE_H */
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 687c420..b457532 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -1054,6 +1054,7 @@ struct be_cmd_resp_modify_eq_delay {
/* The HW can come up in either of the following multi-channel modes
* based on the skew/IPL.
*/
+#define RDMA_ENABLED 0x4
#define FLEX10_MODE 0x400
#define VNIC_MODE 0x20000
#define UMC_ENABLED 0x1000000
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index f2c89e3..23a3454 100644
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -98,11 +98,13 @@
#define SLI_INTF_REV_SHIFT 4
#define SLI_INTF_FT_MASK 0x00000001
+#define SLI_INTF_TYPE_2 2
+#define SLI_INTF_TYPE_3 3
/* SLI family */
#define BE_SLI_FAMILY 0x0
#define LANCER_A0_SLI_FAMILY 0xA
-
+#define SKYHAWK_SLI_FAMILY 0x2
/********* ISR0 Register offset **********/
#define CEV_ISR0_OFFSET 0xC18
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index e382278..cd8d7c9 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -2073,10 +2073,17 @@ static uint be_num_rss_want(struct be_adapter *adapter)
static void be_msix_enable(struct be_adapter *adapter)
{
#define BE_MIN_MSIX_VECTORS 1
- int i, status, num_vec;
+ int i, status, num_vec, num_roce_vec = 0;
/* If RSS queues are not used, need a vec for default RX Q */
num_vec = min(be_num_rss_want(adapter), num_online_cpus());
+ if (be_roce_supported(adapter)) {
+ num_roce_vec = min_t(u32, MAX_ROCE_MSIX_VECTORS,
+ (num_online_cpus() + 1));
+ num_roce_vec = min(num_roce_vec, MAX_ROCE_EQS);
+ num_vec += num_roce_vec;
+ num_vec = min(num_vec, MAX_MSIX_VECTORS);
+ }
num_vec = max(num_vec, BE_MIN_MSIX_VECTORS);
for (i = 0; i < num_vec; i++)
@@ -2093,7 +2100,17 @@ static void be_msix_enable(struct be_adapter *adapter)
}
return;
done:
- adapter->num_msix_vec = num_vec;
+ if (be_roce_supported(adapter)) {
+ if (num_vec > num_roce_vec) {
+ adapter->num_msix_vec = num_vec - num_roce_vec;
+ adapter->num_msix_roce_vec =
+ num_vec - adapter->num_msix_vec;
+ } else {
+ adapter->num_msix_vec = num_vec;
+ adapter->num_msix_roce_vec = 0;
+ }
+ } else
+ adapter->num_msix_vec = num_vec;
return;
}
@@ -2252,6 +2269,8 @@ static int be_close(struct net_device *netdev)
struct be_eq_obj *eqo;
int i;
+ be_roce_dev_close(adapter);
+
be_async_mcc_disable(adapter);
if (!lancer_chip(adapter))
@@ -2360,6 +2379,7 @@ static int be_open(struct net_device *netdev)
if (!status)
be_link_status_update(adapter, link_status);
+ be_roce_dev_open(adapter);
return 0;
err:
be_close(adapter->netdev);
@@ -3077,6 +3097,24 @@ static void be_unmap_pci_bars(struct be_adapter *adapter)
iounmap(adapter->csr);
if (adapter->db)
iounmap(adapter->db);
+ if (adapter->roce_db.base)
+ pci_iounmap(adapter->pdev, adapter->roce_db.base);
+}
+
+static int lancer_roce_map_pci_bars(struct be_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ u8 __iomem *addr;
+
+ addr = pci_iomap(pdev, 2, 0);
+ if (addr == NULL)
+ return -ENOMEM;
+
+ adapter->roce_db.base = addr;
+ adapter->roce_db.io_addr = pci_resource_start(pdev, 2);
+ adapter->roce_db.size = 8192;
+ adapter->roce_db.total_size = pci_resource_len(pdev, 2);
+ return 0;
}
static int be_map_pci_bars(struct be_adapter *adapter)
@@ -3085,11 +3123,18 @@ static int be_map_pci_bars(struct be_adapter *adapter)
int db_reg;
if (lancer_chip(adapter)) {
- addr = ioremap_nocache(pci_resource_start(adapter->pdev, 0),
- pci_resource_len(adapter->pdev, 0));
- if (addr == NULL)
- return -ENOMEM;
- adapter->db = addr;
+ if (be_type_2_3(adapter)) {
+ addr = ioremap_nocache(
+ pci_resource_start(adapter->pdev, 0),
+ pci_resource_len(adapter->pdev, 0));
+ if (addr == NULL)
+ return -ENOMEM;
+ adapter->db = addr;
+ }
+ if (adapter->if_type == SLI_INTF_TYPE_3) {
+ if (lancer_roce_map_pci_bars(adapter))
+ goto pci_map_err;
+ }
return 0;
}
@@ -3114,14 +3159,19 @@ static int be_map_pci_bars(struct be_adapter *adapter)
if (addr == NULL)
goto pci_map_err;
adapter->db = addr;
-
+ if (adapter->sli_family == SKYHAWK_SLI_FAMILY) {
+ adapter->roce_db.size = 4096;
+ adapter->roce_db.io_addr =
+ pci_resource_start(adapter->pdev, db_reg);
+ adapter->roce_db.total_size =
+ pci_resource_len(adapter->pdev, db_reg);
+ }
return 0;
pci_map_err:
be_unmap_pci_bars(adapter);
return -ENOMEM;
}
-
static void be_ctrl_cleanup(struct be_adapter *adapter)
{
struct be_dma_mem *mem = &adapter->mbox_mem_alloced;
@@ -3227,6 +3277,8 @@ static void __devexit be_remove(struct pci_dev *pdev)
if (!adapter)
return;
+ be_roce_dev_remove(adapter);
+
unregister_netdev(adapter->netdev);
be_clear(adapter);
@@ -3277,17 +3329,27 @@ static int be_dev_family_check(struct be_adapter *adapter)
break;
case BE_DEVICE_ID2:
case OC_DEVICE_ID2:
- case OC_DEVICE_ID5:
adapter->generation = BE_GEN3;
break;
case OC_DEVICE_ID3:
case OC_DEVICE_ID4:
pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+ adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
+ SLI_INTF_IF_TYPE_SHIFT;
if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
SLI_INTF_IF_TYPE_SHIFT;
-
if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) ||
- if_type != 0x02) {
+ !be_type_2_3(adapter)) {
+ dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
+ return -EINVAL;
+ }
+ adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
+ SLI_INTF_FAMILY_SHIFT);
+ adapter->generation = BE_GEN3;
+ break;
+ case OC_DEVICE_ID5:
+ pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+ if ((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) {
dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
return -EINVAL;
}
@@ -3547,6 +3609,8 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status != 0)
goto unsetup;
+ be_roce_dev_add(adapter);
+
dev_info(&pdev->dev, "%s: %s port %d\n", netdev->name, nic_name(pdev),
adapter->port_num);
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c
new file mode 100644
index 0000000..deecc44
--- /dev/null
+++ b/drivers/net/ethernet/emulex/benet/be_roce.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2005 - 2011 Emulex
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ */
+
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/module.h>
+
+#include "be.h"
+#include "be_cmds.h"
+
+static struct ocrdma_driver *ocrdma_drv;
+static LIST_HEAD(be_adapter_list);
+static DEFINE_MUTEX(be_adapter_list_lock);
+
+static void _be_roce_dev_add(struct be_adapter *adapter)
+{
+ struct be_dev_info dev_info;
+ int i, num_vec;
+ struct pci_dev *pdev = adapter->pdev;
+
+ if (!ocrdma_drv)
+ return;
+ if (pdev->device == OC_DEVICE_ID5) {
+ /* only msix is supported on these devices */
+ if (!msix_enabled(adapter))
+ return;
+ /* DPP region address and length */
+ dev_info.dpp_unmapped_addr = pci_resource_start(pdev, 2);
+ dev_info.dpp_unmapped_len = pci_resource_len(pdev, 2);
+ } else {
+ dev_info.dpp_unmapped_addr = 0;
+ dev_info.dpp_unmapped_len = 0;
+ }
+ dev_info.pdev = adapter->pdev;
+ if (adapter->sli_family == SKYHAWK_SLI_FAMILY)
+ dev_info.db = adapter->db;
+ else
+ dev_info.db = adapter->roce_db.base;
+ dev_info.unmapped_db = adapter->roce_db.io_addr;
+ dev_info.db_page_size = adapter->roce_db.size;
+ dev_info.db_total_size = adapter->roce_db.total_size;
+ dev_info.netdev = adapter->netdev;
+ memcpy(dev_info.mac_addr, adapter->netdev->dev_addr, ETH_ALEN);
+ dev_info.dev_family = adapter->sli_family;
+ if (msix_enabled(adapter)) {
+ /* provide all the vectors, so that EQ creation response
+ * can decide which one to use.
+ */
+ num_vec = adapter->num_msix_vec + adapter->num_msix_roce_vec;
+ dev_info.intr_mode = BE_INTERRUPT_MODE_MSIX;
+ dev_info.msix.num_vectors = min(num_vec, MAX_ROCE_MSIX_VECTORS);
+ /* provide start index of the vector,
+ * so in case of linear usage,
+ * it can use the base as starting point.
+ */
+ dev_info.msix.start_vector = adapter->num_evt_qs;
+ for (i = 0; i < dev_info.msix.num_vectors; i++) {
+ dev_info.msix.vector_list[i] =
+ adapter->msix_entries[i].vector;
+ }
+ } else {
+ dev_info.msix.num_vectors = 0;
+ dev_info.intr_mode = BE_INTERRUPT_MODE_INTX;
+ }
+ adapter->ocrdma_dev = ocrdma_drv->add(&dev_info);
+}
+
+void be_roce_dev_add(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ INIT_LIST_HEAD(&adapter->entry);
+ mutex_lock(&be_adapter_list_lock);
+ list_add_tail(&adapter->entry, &be_adapter_list);
+
+ /* invoke add() routine of roce driver only if
+ * valid driver registered with add method and add() is not yet
+ * invoked on a given adapter.
+ */
+ _be_roce_dev_add(adapter);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+void _be_roce_dev_remove(struct be_adapter *adapter)
+{
+ if (ocrdma_drv && ocrdma_drv->remove && adapter->ocrdma_dev)
+ ocrdma_drv->remove(adapter->ocrdma_dev);
+ adapter->ocrdma_dev = NULL;
+}
+
+void be_roce_dev_remove(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ mutex_lock(&be_adapter_list_lock);
+ _be_roce_dev_remove(adapter);
+ list_del(&adapter->entry);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+void _be_roce_dev_open(struct be_adapter *adapter)
+{
+ if (ocrdma_drv && adapter->ocrdma_dev &&
+ ocrdma_drv->state_change_handler)
+ ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 0);
+}
+
+void be_roce_dev_open(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ mutex_lock(&be_adapter_list_lock);
+ _be_roce_dev_open(adapter);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+void _be_roce_dev_close(struct be_adapter *adapter)
+{
+ if (ocrdma_drv && adapter->ocrdma_dev &&
+ ocrdma_drv->state_change_handler)
+ ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 1);
+}
+
+void be_roce_dev_close(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ mutex_lock(&be_adapter_list_lock);
+ _be_roce_dev_close(adapter);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+int be_roce_register_driver(struct ocrdma_driver *drv)
+{
+ struct be_adapter *dev;
+
+ mutex_lock(&be_adapter_list_lock);
+ if (ocrdma_drv) {
+ mutex_unlock(&be_adapter_list_lock);
+ return -EINVAL;
+ }
+ ocrdma_drv = drv;
+ list_for_each_entry(dev, &be_adapter_list, entry) {
+ struct net_device *netdev;
+ _be_roce_dev_add(dev);
+ netdev = dev->netdev;
+ if (netif_running(netdev) && netif_oper_up(netdev))
+ _be_roce_dev_open(dev);
+ }
+ mutex_unlock(&be_adapter_list_lock);
+ return 0;
+}
+EXPORT_SYMBOL(be_roce_register_driver);
+
+void be_roce_unregister_driver(struct ocrdma_driver *drv)
+{
+ struct be_adapter *dev;
+
+ mutex_lock(&be_adapter_list_lock);
+ list_for_each_entry(dev, &be_adapter_list, entry) {
+ if (dev->ocrdma_dev)
+ _be_roce_dev_remove(dev);
+ }
+ ocrdma_drv = NULL;
+ mutex_unlock(&be_adapter_list_lock);
+}
+EXPORT_SYMBOL(be_roce_unregister_driver);
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.h b/drivers/net/ethernet/emulex/benet/be_roce.h
new file mode 100644
index 0000000..db4ea80
--- /dev/null
+++ b/drivers/net/ethernet/emulex/benet/be_roce.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2005 - 2011 Emulex
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ */
+
+#ifndef BE_ROCE_H
+#define BE_ROCE_H
+
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+
+struct ocrdma_dev;
+
+enum be_interrupt_mode {
+ BE_INTERRUPT_MODE_MSIX = 0,
+ BE_INTERRUPT_MODE_INTX = 1,
+ BE_INTERRUPT_MODE_MSI = 2,
+};
+
+#define MAX_ROCE_MSIX_VECTORS 16
+struct be_dev_info {
+ u8 __iomem *db;
+ u64 unmapped_db;
+ u32 db_page_size;
+ u32 db_total_size;
+ u64 dpp_unmapped_addr;
+ u32 dpp_unmapped_len;
+ struct pci_dev *pdev;
+ struct net_device *netdev;
+ u8 mac_addr[ETH_ALEN];
+ u32 dev_family;
+ enum be_interrupt_mode intr_mode;
+ struct {
+ int num_vectors;
+ int start_vector;
+ u32 vector_list[MAX_ROCE_MSIX_VECTORS];
+ } msix;
+};
+
+/* ocrdma driver register's the callback functions with nic driver. */
+struct ocrdma_driver {
+ unsigned char name[32];
+ struct ocrdma_dev *(*add) (struct be_dev_info *dev_info);
+ void (*remove) (struct ocrdma_dev *);
+ void (*state_change_handler) (struct ocrdma_dev *, u32 new_state);
+};
+
+enum {
+ BE_DEV_UP = 0,
+ BE_DEV_DOWN = 1
+};
+
+/* APIs for RoCE driver to register callback handlers,
+ * which will be invoked when device is added, removed, ifup, ifdown
+ */
+int be_roce_register_driver(struct ocrdma_driver *drv);
+void be_roce_unregister_driver(struct ocrdma_driver *drv);
+
+/* API for RoCE driver to issue mailbox commands */
+int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
+ int wrb_payload_size, u16 *cmd_status, u16 *ext_status);
+
+#endif /* BE_ROCE_H */
--
1.6.0.2
^ permalink raw reply related
* RE: [PATCH net V4 2/2] igb: offer a PTP Hardware Clock instead of the timecompare method
From: Keller, Jacob E @ 2012-03-26 20:46 UTC (permalink / raw)
To: chetan loke
Cc: Richard Cochran, netdev@vger.kernel.org,
e1000-devel@lists.sourceforge.net, Kirsher, Jeffrey T,
Ronciak, John, john.stultz@linaro.org, tglx@linutronix.de
In-Reply-To: <CAAsGZS4Jqe5ZcZyGZjurmjBCgzj=+a0cgHAEwB+esXNoQ3P7NQ@mail.gmail.com>
> -----Original Message-----
> From: chetan loke [mailto:loke.chetan@gmail.com]
> Sent: Monday, March 26, 2012 12:32 PM
> To: Keller, Jacob E
> Cc: Richard Cochran; netdev@vger.kernel.org; e1000-
> devel@lists.sourceforge.net; Kirsher, Jeffrey T; Ronciak, John;
> john.stultz@linaro.org; tglx@linutronix.de
> Subject: Re: [PATCH net V4 2/2] igb: offer a PTP Hardware Clock instead of the
> timecompare method
>
> On Mon, Mar 26, 2012 at 2:56 PM, Keller, Jacob E <jacob.e.keller@intel.com>
> wrote:
>
> > I am curious how you see a kernel thread resolving the Tx/Rx issue? or
> > is the kernel thread being used by gettime? I don't believe we can
> > wait for the Tx/Rx
>
> tx, rx path and kernel thread will use seq_lock_isave(tmreg_lock).
>
> A new 'u64 cached_ns' will be introduced.
>
> tx and rx path can update 'cached_ns' when they read the NIC counter.
>
Tx and rx paths don't read the SYSTIM registers. When hardware (other
than the 82580 which could use a different software implementation)
receives a PTP packet, it is time stamped *by the hardware* and the
result is stored in the RXSTAMP registers (analog for rx/tx). The
hardware will not timestamp again until after the register is read.
(ignore 82580, it is different). Then the driver will read this register.
The clincher for why we have so much issues here: the SYSTIM registers
are *not* 64bit nanosecond values. They are 64 bits wide (82580 is 40
bits + 32 bits of sub precision or 72 bits wide) but with a fixed point
system. This system allows for defining how much room for adjustment
you want but sacrifices the total amount that can be stored as nanoseconds.
The timecounter structure keeps track of a 64bit field of nanoseconds,
and is based on the cyclecounter. (By knowing how fast the cyclecounter
should be running at 100% optimum circumstances.)
In the tx/rx routine, we convert the cycle timestamps which has an
overflow rate anywhere from once a minute to a few hours. This
conversion uses last updated value of the timecounter, but does not
modify/update the counter. However, it has to lock the structure in
case an update occurs during the cyc2time function call, otherwise you
can corrupt the values. There is no problem using seqlock here. (as
long as we retry). I would take the write lock here, so that it doesn't
have to retry, although you could take the read version. Retrying is
necessary because otherwise there is a window where wildly inaccurate
nanosecond values could be obtained.
The issue with gettime is in the SYSTIM registers. Gettime could also
use cyc2time, and allow the background worktask to be the only one updating
the timecounter's last read value. (this only has to happen at least twice
every wraparound value, so for the 10gig 82599 about once every 30 seconds).
But the lock is also protecting against corruption of the SYSTIM register
reads. (The lock does 2 different things. We could add a separate lock,
but I am not convinced it is worth it).
We can't use timecounter_read inside a read portion of the seqlock because
it has side effects. Reading SYSTIM registers has side effects also
because we have to read them sequentially (lo, then hi, cannot intersperse
two sets of lo and hi reads).
I wrote a patch which shows how you could use just seqlocks, but it has
the issue mentioned above with the SYSTIM registers. These only get used
in the gettime code and the watchdog task that updates the timecounter.
We could implement a basic spinlock around that also, and that would mean
the seqlock would only be around the timecounter structure. This does add
the complication of two locks. :(
I feel like this approach is best, considering that each lock does precisely
one thing, and rarely need to be acquired at the same time. (the only place
being inside timecounter_read, and possibly in cyclecounter_update for the ixgbe)
> A kernel-thread should be scheduled periodically, will read the NIC counter
> and update cached_ns. It will use a _trylock variant. If the lock fails then
> its a hint that 'cached_ns' is getting updated somewhere, so just refresh the
> timer. Periodic update is needed to handle idle/bursty link conditions because
> the Rx/tx path may not run that often.
>
> gettime uses read_seq_lock and reads 'cached_ns'. I mean we could also do a
> atomic_read(?)
As above cached_ns would not work. Timecounter structure isn't ticking on its
own. It converts the SYSTIM values to nanoseconds and keeps track of overflows.
(thereby allowing it to create nanoseconds since the epoch as a 64bit value,
which is what the user software expects). Atomic reads don't work because the
atomic values only have around 24bits of actual data. (we would need at least 64bits)
>
>
> > path, because if we take too long the software sees it as a dropped
> timestamp.
>
> What code-path is this?
>
For transmit only, inside the user software, it sends a packet then waits
for a copy of that packet on the receive errqueue which is copied by the kernel
and put there with the TX timestamp. If the driver takes too long to report the
timestamp then the user software times out and reports a time stamp as missing
even though it would later be returned by the driver. It is not an issue with
the RX timestamps.
>
> > How would we only allow one app? Any app with permissions could call the
> ioctls.
> > I do agree that having too many ioctls is a problem. Even in cases
> > where PTP is
>
> We don't. So this is what I'm thinking. Ideally speaking only 1 app should be
> adjusting the host-clock and 1 app per NIC if you adjust NIC's clock. Ignore
> the host-clock app. Once you enforce the rate-limit, driver will return -EBUSY
> if you exceed it. Too many EBUSYs will provide a hint on user-side.
>
This might be possible, but how would you code the solution? Software wouldn't
have any idea how often things are being run. Maybe have a timeout value that you
check for determining whether the last call came too soon?
>
> Chetan
^ permalink raw reply
* RE: [PATCH net V4 2/2] igb: offer a PTP Hardware Clock instead of the timecompare method
From: Keller, Jacob E @ 2012-03-26 20:51 UTC (permalink / raw)
To: Richard Cochran, chetan loke
Cc: netdev@vger.kernel.org, e1000-devel@lists.sourceforge.net,
Kirsher, Jeffrey T, Ronciak, John, john.stultz@linaro.org,
tglx@linutronix.de
In-Reply-To: <20120324065147.GB2201@netboy.at.omicron.at>
> -----Original Message-----
> From: Richard Cochran [mailto:richardcochran@gmail.com]
> Sent: Friday, March 23, 2012 11:52 PM
> To: chetan loke
> Cc: Keller, Jacob E; netdev@vger.kernel.org; e1000-
> devel@lists.sourceforge.net; Kirsher, Jeffrey T; Ronciak, John;
> john.stultz@linaro.org; tglx@linutronix.de
> Subject: Re: [PATCH net V4 2/2] igb: offer a PTP Hardware Clock instead of the
> timecompare method
>
> > How about rate limiting at the PHC class driver level? And then it
> > will work across the board for all the adapters at the device level.
>
> No, don't go there. Enough bikeshedding already. If you have a serious
> performance issue, please post a test case, and we will look for a solution.
>
This is about a case where the user does something stupid. (runs the ioctls too
fast). It appears that your answer is something like "The user did something
stupid, we shouldn't care". My answer is, "we should do what we can to prevent
this." I don't think modifying the ptp framework is necessary or even a good
idea. (Because it is a particular issue with intel parts design, not with general
PTP design.) I do think if possible we should modify igb/ixgbe patches properly
to prevent the breaking. I am currently working on a test case where the user
*does* hammer the ioctls and seeing whether that actually crashes the driver.
> Thanks,
> Richard
>
^ permalink raw reply
* Re: [net-next PATCH v0 3/5] net: add fdb generic dump routine
From: John Fastabend @ 2012-03-26 21:41 UTC (permalink / raw)
To: Roopa Prabhu
Cc: jhs, shemminger, bhutchings, davem, jeffrey.t.kirsher, netdev,
mst, chrisw, gregory.v.rose, kvm, sri, chealy
In-Reply-To: <CB94671B.49E3F%roprabhu@cisco.com>
On 3/25/2012 6:09 AM, Roopa Prabhu wrote:
>
>
>
> On 3/18/12 11:52 PM, "John Fastabend" <john.r.fastabend@intel.com> wrote:
>
>> This adds a generic dump routine drivers can call. It
>> should be sufficient to handle any bridging model that
>> uses the unicast address list. This should be most SR-IOV
>> enabled NICs.
>>
>> Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
>> ---
>>
[...]
>> +/**
>> + * ndo_dflt_fdb_dump: default netdevice operation to dump an FDB table.
>> + * @nlh: netlink message header
>> + * @dev: netdevice
>> + *
>> + * Default netdevice operation to dump the existing unicast address list.
>> + * Returns zero on success.
>> + */
>> +int ndo_dflt_fdb_dump(struct sk_buff *skb,
>> + struct netlink_callback *cb,
>> + struct net_device *dev,
>> + int idx)
>> +{
>> + struct netdev_hw_addr *ha;
>> + struct nlmsghdr *nlh;
>> + struct ndmsg *ndm;
>> + u32 pid, seq;
>> +
>> + pid = NETLINK_CB(cb->skb).pid;
>> + seq = cb->nlh->nlmsg_seq;
>> +
>> + netif_addr_lock_bh(dev);
>> + list_for_each_entry(ha, &dev->uc.list, list) {
>> + if (idx < cb->args[0])
>> + goto skip;
>
> Any reason why its only uc ?. What about mc ?
Sure this might be useful to know for embedded devices
and likely more useful for the macvlan driver. I'll add
it in the next version.
Thanks,
John
^ permalink raw reply
* Re: [PATCH] net/vlan: withdraw VLAN ID attribute from GVRP on VLAN device stop
From: David Miller @ 2012-03-26 21:42 UTC (permalink / raw)
To: david.ward; +Cc: jorge, netdev
In-Reply-To: <4F709038.20107@ll.mit.edu>
From: "Ward, David - 0663 - MITLL" <david.ward@ll.mit.edu>
Date: Mon, 26 Mar 2012 11:50:16 -0400
> If I create an interface that is initially down, then bring it up, and
> finally bring it back down, I think it should return to the state it
> was in initially. So in my opinion, either the GVRP attribute should
> exist while the interface is down, or it shouldn't.
You're whole argument breaks down because we definitely don't do this
for IPv4 addresses, we'll keep receiving traffic for IPv4 addresses
configured on that interface when received on other interfaces which
are still up, even when you bring that interface down.
Really, if you want to leave GVRP, unconfigure it.
I'm not applying this patch.
^ permalink raw reply
* RCU lock bug in 3.0.21 (bisected to: 682cb56a, fix NULL dereferences in check_peer_redir)
From: Ben Greear @ 2012-03-26 21:43 UTC (permalink / raw)
To: netdev, Eric Dumazet, Greg Kroah-Hartman
Test case is complicated...creating 100 virtual wifi devices, running DHCP,
setting up routing rules, and most likely some ipv6 stuff as well. It's all
automated by our tool, so hard to say exactly which command or set of commands
is causing this. I read the ipv6 portion of the patch several times and do
not see a problem.
This kernel has no additional patches or out-of-tree modules loaded.
Here are two samples of output from the serial console. The problem reproduces
100% of the time on this machine.
BUG: sleeping function called from invalid context at /home/greearb/git/linux-3..
0.dev.y/kernel/mutex.c:271
in_atomic(): 0, irqs_disabled(): 0, pid: 8897, name: ip
1 lock held by ip/8897:
#0: (rcu_read_lock){.+.+..}, at: [<ffffffffa01f2190>] rcu_read_lock+0x0/0x35 [[
ipv6]
Pid: 8897, comm: ip Tainted: G C 3.0.20+ #10
Call Trace:
[<ffffffffa01f24fd>] ? rcu_read_unlock+0x23/0x23 [ipv6]
[<ffffffff8103e46d>] __might_sleep+0x111/0x115
[<ffffffff81447c04>] mutex_lock_nested+0x20/0x3b
[<ffffffff8139bb59>] rtnl_lock+0x12/0x14
[<ffffffff8139bc67>] rtnetlink_rcv_msg+0xe4/0x1ec
[<ffffffff8139bb83>] ? rtnetlink_rcv+0x28/0x28
[<ffffffff813ae578>] netlink_rcv_skb+0x3e/0x8f
[<ffffffff8139bb7c>] rtnetlink_rcv+0x21/0x28
[<ffffffff813ae353>] netlink_unicast+0xe9/0x152
[<ffffffff813aeb1a>] netlink_sendmsg+0x240/0x25e
[<ffffffff8137fadc>] ? rcu_read_unlock+0x21/0x23
[<ffffffff8137aab1>] __sock_sendmsg_nosec+0x58/0x61
[<ffffffff8137c0e0>] __sock_sendmsg+0x3d/0x48
[<ffffffff8137c952>] sock_sendmsg+0xa3/0xbc
[<ffffffff8137c3b0>] ? move_addr_to_user+0x71/0x8e
[<ffffffff810fbebd>] ? fget_light+0x35/0xac
[<ffffffff8137c9d3>] ? sockfd_lookup_light+0x1b/0x53
[<ffffffff8137cf16>] sys_sendto+0xfa/0x11f
[<ffffffff810fbd9a>] ? fcheck_files+0xb7/0xee
[<ffffffff810fbebd>] ? fget_light+0x35/0xac
[<ffffffff810cfedf>] ? remove_vma+0x7a/0x82
[<ffffffff81095f21>] ? audit_syscall_entry+0x119/0x145
[<ffffffff8144df12>] system_call_fastpath+0x16/0x1b
================================================
[ BUG: lock held when returning to user space! ]
------------------------------------------------
ip/8897 is leaving the kernel with locks still held!
1 lock held by ip/8897:
#0: (rcu_read_lock){.+.+..}, at: [<ffffffffa01f2190>] rcu_read_lock+0x0/0x35 [[
ipv6]
BUG: sleeping function called from invalid context at /home/greearb/git/linux-3.0.dev.y/mm/memory.c:3904
in_atomic(): 0, irqs_disabled(): 0, pid: 4953, name: ip
1 lock held by ip/4953:
#0: (rcu_read_lock){.+.+..}, at: [<ffffffffa0154190>] rcu_read_lock+0x0/0x35 [ipv6]
Pid: 4953, comm: ip Tainted: G C 3.0.20+ #10
Call Trace:
[<ffffffff8103e46d>] __might_sleep+0x111/0x115
[<ffffffff810c977b>] might_fault+0x2f/0x9e
[<ffffffff81386032>] ? copy_from_user+0x2a/0x2c
[<ffffffff810c979a>] ? might_fault+0x4e/0x9e
[<ffffffff8137c360>] move_addr_to_user+0x21/0x8e
[<ffffffff8137c54c>] __sys_recvmsg+0x17f/0x21e
[<ffffffff810fbebd>] ? fget_light+0x35/0xac
[<ffffffff8137c9d3>] ? sockfd_lookup_light+0x1b/0x53
[<ffffffff810fbd9a>] ? fcheck_files+0xb7/0xee
[<ffffffff810fbebd>] ? fget_light+0x35/0xac
[<ffffffff810cfedf>] ? remove_vma+0x7a/0x82
[<ffffffff8137ccf0>] sys_recvmsg+0x3d/0x5b
eth1: no IPv6 routers present
[<ffffffff8144df12>] system_call_fastpath+0x16/0x1b
================================================
[ BUG: lock held when returning to user space! ]
------------------------------------------------
ip/4953 is leaving the kernel with locks still held!
1 lock held by ip/4953:
#0: (rcu_read_lock){.+.+..}, at: [<ffffffffa0154190>] rcu_read_lock+0x0/0x35 [ipv6]
ADDRCONF(NETDEV_UP): sta49: link is not ready
[greearb@fs3 linux-3.0.dev.y]$ git bisect bad
8a533666d1591cf4ea596c6bd710e2fe682cb56a is the first bad commit
commit 8a533666d1591cf4ea596c6bd710e2fe682cb56a
Author: Eric Dumazet <eric.dumazet@gmail.com>
Date: Thu Feb 9 16:13:19 2012 -0500
net: fix NULL dereferences in check_peer_redir()
[ Upstream commit d3aaeb38c40e5a6c08dd31a1b64da65c4352be36, along
with dependent backports of commits:
69cce1d1404968f78b177a0314f5822d5afdbbfb
9de79c127cccecb11ae6a21ab1499e87aa222880
218fa90f072e4aeff9003d57e390857f4f35513e
580da35a31f91a594f3090b7a2c39b85cb051a12
f7e57044eeb1841847c24aa06766c8290c202583
e049f28883126c689cf95859480d9ee4ab23b7fa ]
Gergely Kalman reported crashes in check_peer_redir().
It appears commit f39925dbde778 (ipv4: Cache learned redirect
information in inetpeer.) added a race, leading to possible NULL ptr
dereference.
Since we can now change dst neighbour, we should make sure a reader can
safely use a neighbour.
Add RCU protection to dst neighbour, and make sure check_peer_redir()
can be called safely by different cpus in parallel.
As neighbours are already freed after one RCU grace period, this patch
should not add typical RCU penalty (cache cold effects)
Many thanks to Gergely for providing a pretty report pointing to the
bug.
Reported-by: Gergely Kalman <synapse@hippy.csoma.elte.hu>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: [PATCH] net/garp: avoid infinite loop if attribute already exists
From: David Miller @ 2012-03-26 21:44 UTC (permalink / raw)
To: david.ward; +Cc: netdev
In-Reply-To: <1332715437-16278-1-git-send-email-david.ward@ll.mit.edu>
From: David Ward <david.ward@ll.mit.edu>
Date: Sun, 25 Mar 2012 18:43:56 -0400
> @@ -353,9 +361,9 @@ int garp_request_join(const struct net_device *dev,
>
> spin_lock_bh(&app->lock);
> attr = garp_attr_create(app, data, len, type);
> - if (!attr) {
> + if (IS_ERR(attr)) {
> spin_unlock_bh(&app->lock);
> - return -ENOMEM;
> + return ERR_PTR(attr);
You cannot tell me that this ERR_PTR() thing didn't emit a very loud
warning from the compiler. You want PTR_ERR() instead.
Please don't be so careless, if I can predict compiler warnings just
by reading your patches you are so doing it wrong.
^ permalink raw reply
* Re: RCU lock bug in 3.0.21 (bisected to: 682cb56a, fix NULL dereferences in check_peer_redir)
From: David Miller @ 2012-03-26 21:49 UTC (permalink / raw)
To: greearb; +Cc: netdev, eric.dumazet, gregkh
In-Reply-To: <4F70E308.7070908@candelatech.com>
Looks like all of those strange undiagnosable reported Dave Jones
has been feeding us. Something in one part of the kernel leaves
a lock held, and this shows up as a warning elsewhere.
^ permalink raw reply
* Re: RCU lock bug in 3.0.21 (bisected to: 682cb56a, fix NULL dereferences in check_peer_redir)
From: Ben Greear @ 2012-03-26 21:53 UTC (permalink / raw)
To: David Miller; +Cc: netdev, eric.dumazet, gregkh
In-Reply-To: <20120326.174945.1186427809261872546.davem@davemloft.net>
On 03/26/2012 02:49 PM, David Miller wrote:
>
> Looks like all of those strange undiagnosable reported Dave Jones
> has been feeding us. Something in one part of the kernel leaves
> a lock held, and this shows up as a warning elsewhere.
Every (initial) bug printout fingers ipv6 and the 'ip' tool on my system.
And, the bisect clearly points at this commit.
I'm (re)reading the patch top to bottom to see if something
jumps out...and will be happy to liberally sprinkle debug
code if anyone has any suggestions.
Thanks,
Ben
> --
> 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
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: [PATCH 0/1] net/hyperv: Add flow control based on hi/low watermark
From: David Miller @ 2012-03-26 22:12 UTC (permalink / raw)
To: haiyangz; +Cc: netdev, kys, olaf, linux-kernel, devel
In-Reply-To: <1332800304-5060-1-git-send-email-haiyangz@microsoft.com>
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Mon, 26 Mar 2012 15:18:23 -0700
> This patch is targeting 'net-next' tree.
The merge window is still open, and therefore the net-next tree is
not open yet.
^ permalink raw reply
* Re: [PATCH 0/7] bna: Update driver version to 3.0.23.0
From: David Miller @ 2012-03-26 22:12 UTC (permalink / raw)
To: huangj; +Cc: netdev, adapter_linux_open_src_team
In-Reply-To: <1332790673-9562-1-git-send-email-huangj@brocade.com>
From: Jing Huang <huangj@Brocade.COM>
Date: Mon, 26 Mar 2012 12:37:53 -0700
> This patch set contains fixes in adapter initialization and tx/rx cleanup path.
> It also include code cleanups by removing and renaming some functions.
>
> The driver version has been updated to 3.0.23.0 to reflect the changes.
Cleanups and such are only appropriate for net-next, which is not
open because the merge window is still ongoing.
^ permalink raw reply
* [PATCH 0/1] net/hyperv: Add flow control based on hi/low watermark
From: Haiyang Zhang @ 2012-03-26 22:18 UTC (permalink / raw)
To: davem, netdev; +Cc: devel, haiyangz, olaf, linux-kernel
This patch is targeting 'net-next' tree.
Thanks to Stephen Hemminger <shemminger@vyatta.com> for his suggestions.
Haiyang Zhang (1):
net/hyperv: Add flow control based on hi/low watermark
drivers/hv/ring_buffer.c | 15 +++++++++++++++
drivers/net/hyperv/hyperv_net.h | 3 +++
drivers/net/hyperv/netvsc.c | 23 +++++++++++++++++++----
drivers/net/hyperv/netvsc_drv.c | 16 +++++++++++++++-
include/linux/hyperv.h | 3 +++
5 files changed, 55 insertions(+), 5 deletions(-)
--
1.7.4.1
^ permalink raw reply
* [PATCH 1/1] net/hyperv: Add flow control based on hi/low watermark
From: Haiyang Zhang @ 2012-03-26 22:18 UTC (permalink / raw)
To: davem, netdev; +Cc: haiyangz, kys, olaf, linux-kernel, devel
In-Reply-To: <1332800304-5060-1-git-send-email-haiyangz@microsoft.com>
In the existing code, we only stop queue when the ringbuffer is full,
so the current packet has to be dropped or retried from upper layer.
This patch stops the tx queue when available ringbuffer is below
the low watermark. So the ringbuffer still has small amount of space
available for the current packet. This will reduce the overhead of
retries on sending.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
---
drivers/hv/ring_buffer.c | 15 +++++++++++++++
drivers/net/hyperv/hyperv_net.h | 3 +++
drivers/net/hyperv/netvsc.c | 23 +++++++++++++++++++----
drivers/net/hyperv/netvsc_drv.c | 16 +++++++++++++++-
include/linux/hyperv.h | 3 +++
5 files changed, 55 insertions(+), 5 deletions(-)
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 8af25a0..8cc3f63 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -23,6 +23,7 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/hyperv.h>
@@ -160,6 +161,20 @@ hv_get_ring_buffersize(struct hv_ring_buffer_info *ring_info)
}
/*
+ * Get the percentage of available bytes to write in the ring.
+ * The return value is in range from 0 to 100.
+ */
+u32 hv_ringbuf_avail_percent(struct hv_ring_buffer_info *ring_info)
+{
+ u32 avail_read, avail_write;
+
+ hv_get_ringbuffer_availbytes(ring_info, &avail_read, &avail_write);
+
+ return avail_write * 100 / hv_get_ring_buffersize(ring_info);
+}
+EXPORT_SYMBOL(hv_ringbuf_avail_percent);
+
+/*
*
* hv_get_ring_bufferindices()
*
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index c358245..cd234cd 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -470,6 +470,9 @@ struct nvsp_message {
#define NETVSC_PACKET_SIZE 2048
+extern uint ring_avail_percent_hiwater;
+extern uint ring_avail_percent_lowater;
+
/* Per netvsc channel-specific */
struct netvsc_device {
struct hv_device *dev;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index d025c83..fbf4f18 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -455,6 +455,8 @@ static void netvsc_send_completion(struct hv_device *device,
complete(&net_device->channel_init_wait);
} else if (nvsp_packet->hdr.msg_type ==
NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) {
+ int num_outstanding_sends;
+
/* Get the send context */
nvsc_packet = (struct hv_netvsc_packet *)(unsigned long)
packet->trans_id;
@@ -463,10 +465,14 @@ static void netvsc_send_completion(struct hv_device *device,
nvsc_packet->completion.send.send_completion(
nvsc_packet->completion.send.send_completion_ctx);
- atomic_dec(&net_device->num_outstanding_sends);
+ num_outstanding_sends =
+ atomic_dec_return(&net_device->num_outstanding_sends);
- if (netif_queue_stopped(ndev) && !net_device->start_remove)
- netif_wake_queue(ndev);
+ if (netif_queue_stopped(ndev) && !net_device->start_remove &&
+ (hv_ringbuf_avail_percent(&device->channel->outbound)
+ > ring_avail_percent_hiwater ||
+ num_outstanding_sends < 1))
+ netif_wake_queue(ndev);
} else {
netdev_err(ndev, "Unknown send completion packet type- "
"%d received!!\n", nvsp_packet->hdr.msg_type);
@@ -519,10 +525,19 @@ int netvsc_send(struct hv_device *device,
if (ret == 0) {
atomic_inc(&net_device->num_outstanding_sends);
+ if (hv_ringbuf_avail_percent(&device->channel->outbound) <
+ ring_avail_percent_lowater) {
+ netif_stop_queue(ndev);
+ if (atomic_read(&net_device->
+ num_outstanding_sends) < 1)
+ netif_wake_queue(ndev);
+ }
} else if (ret == -EAGAIN) {
netif_stop_queue(ndev);
- if (atomic_read(&net_device->num_outstanding_sends) < 1)
+ if (atomic_read(&net_device->num_outstanding_sends) < 1) {
netif_wake_queue(ndev);
+ ret = -ENOSPC;
+ }
} else {
netdev_err(ndev, "Unable to send packet %p ret %d\n",
packet, ret);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index dd29478..f13887c 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -51,6 +51,16 @@ static int ring_size = 128;
module_param(ring_size, int, S_IRUGO);
MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
+uint ring_avail_percent_hiwater = 20;
+module_param(ring_avail_percent_hiwater, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ring_avail_percent_hiwater,
+ "Ring buffer available percentiles to wake up xmit queue");
+
+uint ring_avail_percent_lowater = 10;
+module_param(ring_avail_percent_lowater, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ring_avail_percent_lowater,
+ "Ring buffer available percentiles to stop xmit queue");
+
struct set_multicast_work {
struct work_struct work;
struct net_device *net;
@@ -224,9 +234,13 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
net->stats.tx_packets++;
} else {
kfree(packet);
+ if (ret != -EAGAIN) {
+ dev_kfree_skb_any(skb);
+ net->stats.tx_dropped++;
+ }
}
- return ret ? NETDEV_TX_BUSY : NETDEV_TX_OK;
+ return (ret == -EAGAIN) ? NETDEV_TX_BUSY : NETDEV_TX_OK;
}
/*
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 5852545..e8e4c31 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -274,6 +274,9 @@ struct hv_ring_buffer_debug_info {
u32 bytes_avail_towrite;
};
+extern u32 hv_ringbuf_avail_percent(struct hv_ring_buffer_info *ring_info);
+
+
/*
* We use the same version numbering for all Hyper-V modules.
*
--
1.7.4.1
^ permalink raw reply related
* [PATCH] net: reference the ipv4 sysctl table header
From: Djalal Harouni @ 2012-03-26 22:23 UTC (permalink / raw)
To: David S. Miller, Eric W. Biederman, Al Viro; +Cc: netdev
I've been analysing some kmemleak reports of an internal module, and
found that there are false positive reports of unreferenced objects.
The following patch is just a clean up for one of those false positives,
this is for the /proc/sys/net/ipv4 sysctl table.
As I've said there are other reports but don't know if it is worth to
write patches for them.
---
From: Djalal Harouni <tixxdz@opendz.org>
Subject: [PATCH] net: reference the ipv4 sysctl table header
Reference the ipv4 sysctl table header allocated and returned by
register_sysctl_paths().
Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
---
include/net/ip.h | 2 +-
net/ipv4/af_inet.c | 12 ++++++++++--
net/ipv4/route.c | 10 ++++++++--
3 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/include/net/ip.h b/include/net/ip.h
index b53d65f..6a12687 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -235,7 +235,7 @@ extern int sysctl_ip_dynaddr;
extern void ipfrag_init(void);
-extern void ip_static_sysctl_init(void);
+extern int ip_static_sysctl_init(void);
static inline bool ip_is_fragment(const struct iphdr *iph)
{
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index fdf49fd..340d298 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1666,10 +1666,14 @@ static int __init inet_init(void)
* Tell SOCKET that we are alive...
*/
- (void)sock_register(&inet_family_ops);
+ rc = sock_register(&inet_family_ops);
+ if (rc)
+ goto out_unregister_ping_prot;
#ifdef CONFIG_SYSCTL
- ip_static_sysctl_init();
+ rc = ip_static_sysctl_init();
+ if (rc)
+ goto out_unregister_sock;
#endif
tcp_prot.sysctl_mem = init_net.ipv4.sysctl_tcp_mem;
@@ -1751,6 +1755,10 @@ static int __init inet_init(void)
rc = 0;
out:
return rc;
+out_unregister_sock:
+ sock_unregister(PF_INET);
+out_unregister_ping_prot:
+ proto_unregister(&ping_prot);
out_unregister_raw_proto:
proto_unregister(&raw_prot);
out_unregister_udp_proto:
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 12ccf88..bc899f2 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3500,12 +3500,18 @@ int __init ip_rt_init(void)
}
#ifdef CONFIG_SYSCTL
+static struct ctl_table_header *ip4_base;
+
/*
* We really need to sanitize the damn ipv4 init order, then all
* this nonsense will go away.
*/
-void __init ip_static_sysctl_init(void)
+int __init ip_static_sysctl_init(void)
{
- register_sysctl_paths(ipv4_path, ipv4_skeleton);
+ ip4_base = register_sysctl_paths(ipv4_path, ipv4_skeleton);
+ if (!ip4_base)
+ return -ENOMEM;
+
+ return 0;
}
#endif
--
1.7.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox