* [PATCH 24/45] bna: Mboxq Flush When Ioc Disabled
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- If there is a command pending in the mailbox, bfa_ioc_mbox_queue() enqueues
the mailbox command to a pending command queue. Entries in this queue are
not flushed when IOC is disabled. As a result, when IOC is re-enabled again,
the stale entries in the pending command queue are posted to the mailbox.
When these mailbox commands are processed by the FW and responses are sent,
unexpected events are received by other modules' FSMs (f.e. bfa_msgq) which
have not posted any mailbox commands after IOC was enabled.
- Flush the pending mailbox command queue when IOC is disabled. Rename
bfa_ioc_mbox_hbfail to bfa_ioc_mbox_flush. Call bfa_ioc_mbox_flush
from bfa_iocpf_sm_disabled_entry()
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_ioc.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 33776da..a38f5cd 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -69,7 +69,7 @@ static void bfa_ioc_hb_monitor(struct bfa_ioc *ioc);
static void bfa_ioc_hb_stop(struct bfa_ioc *ioc);
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_hbfail(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);
@@ -908,6 +908,7 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_disabled_entry(struct bfa_iocpf *iocpf)
{
+ bfa_ioc_mbox_flush(iocpf->ioc);
bfa_ioc_pf_disabled(iocpf->ioc);
}
@@ -1012,7 +1013,7 @@ bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf *iocpf)
/**
* Flush any queued up mailbox requests.
*/
- bfa_ioc_mbox_hbfail(iocpf->ioc);
+ bfa_ioc_mbox_flush(iocpf->ioc);
bfa_ioc_hw_sem_get(iocpf->ioc);
}
@@ -1606,7 +1607,7 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
* Cleanup any pending requests.
*/
static void
-bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc)
+bfa_ioc_mbox_flush(struct bfa_ioc *ioc)
{
struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
struct bfa_mbox_cmd *cmd;
--
1.7.1
^ permalink raw reply related
* [PATCH 25/45] bna: Move FW Init to HW Init and Disable Hang Unmapped Fix
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- Move the bfa_ioc_poll_fwinit() function call out of bfa_ioc_boot() and put
it inside the caller of bfa_ioc_boot(), which is bfa_ioc_hwinit()
- Diag memtest call bfa_ioc_boot() to download memtest specific fw code.
Inside bfa_ioc_boot(), it called bfa_ioc_poll_fwinit() which start a timer,
with a timeout duration much shorter than the memtest timer. As a result,
this poll timer expired, and cause the assert. But eventually, the
memtest complete successfully.
- Handle the case where PCI mapping goes away when IOCPF state machine is
waiting for semaphore.
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_defs.h | 1 +
drivers/net/bna/bfa_ioc.c | 91 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 89 insertions(+), 3 deletions(-)
diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index e89830f..621d50b 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -124,6 +124,7 @@ enum bfa_ioc_state {
BFA_IOC_DISABLED = 10, /*!< IOC is disabled */
BFA_IOC_FWMISMATCH = 11, /*!< IOC f/w different from drivers */
BFA_IOC_ENABLING = 12, /*!< IOC is being enabled */
+ BFA_IOC_HWFAIL = 13, /*!< PCI mapping doesn't exist */
};
/**
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index a38f5cd..216d0d1 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -79,6 +79,7 @@ static void bfa_ioc_fail_notify(struct bfa_ioc *ioc);
static void bfa_ioc_pf_enabled(struct bfa_ioc *ioc);
static void bfa_ioc_pf_disabled(struct bfa_ioc *ioc);
static void bfa_ioc_pf_failed(struct bfa_ioc *ioc);
+static void bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc);
static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc);
static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type,
u32 boot_param);
@@ -111,6 +112,7 @@ enum ioc_event {
IOC_E_HBFAIL = 9, /*!< heartbeat failure */
IOC_E_HWERROR = 10, /*!< hardware error interrupt */
IOC_E_TIMEOUT = 11, /*!< timeout */
+ IOC_E_HWFAILED = 12, /*!< PCI mapping failure notice */
};
bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc, enum ioc_event);
@@ -122,6 +124,7 @@ bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc, enum ioc_event);
static struct bfa_sm_table ioc_sm_table[] = {
{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
@@ -133,6 +136,7 @@ static struct bfa_sm_table ioc_sm_table[] = {
{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
+ {BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},
};
/**
@@ -164,6 +168,7 @@ enum iocpf_event {
IOCPF_E_GETATTRFAIL = 9, /*!< init fail notice by ioc sm */
IOCPF_E_SEMLOCKED = 10, /*!< h/w semaphore is locked */
IOCPF_E_TIMEOUT = 11, /*!< f/w response timeout */
+ IOCPF_E_SEM_ERROR = 12, /*!< h/w sem mapping error */
};
/**
@@ -303,6 +308,11 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
bfa_iocpf_initfail(ioc);
break;
+ case IOC_E_HWFAILED:
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+ break;
+
case IOC_E_DISABLE:
bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
break;
@@ -434,6 +444,11 @@ bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
bfa_iocpf_fail(ioc);
break;
+ case IOC_E_HWFAILED:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+ bfa_ioc_disable_comp(ioc);
+ break;
+
default:
bfa_sm_fault(event);
}
@@ -497,6 +512,11 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
bfa_iocpf_initfail(ioc);
break;
+ case IOC_E_HWFAILED:
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+ break;
+
case IOC_E_ENABLE:
break;
@@ -548,6 +568,36 @@ bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)
}
}
+static void
+bfa_ioc_sm_hwfail_entry(struct bfa_ioc *ioc)
+{
+}
+
+/**
+ * IOC failure.
+ */
+static void
+bfa_ioc_sm_hwfail(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+
+ case IOC_E_ENABLE:
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ break;
+
+ case IOC_E_DISABLE:
+ ioc->cbfn->disable_cbfn(ioc->bfa);
+ break;
+
+ case IOC_E_DETACH:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
/**
* IOCPF State Machine
*/
@@ -616,6 +666,11 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
}
break;
+ case IOCPF_E_SEM_ERROR:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_ioc_pf_hwfailed(ioc);
+ break;
+
case IOCPF_E_DISABLE:
bfa_ioc_hw_sem_get_cancel(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
@@ -705,6 +760,11 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)
}
break;
+ case IOCPF_E_SEM_ERROR:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_ioc_pf_hwfailed(ioc);
+ break;
+
case IOCPF_E_DISABLE:
bfa_ioc_hw_sem_get_cancel(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -894,6 +954,11 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
break;
+ case IOCPF_E_SEM_ERROR:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_ioc_pf_hwfailed(ioc);
+ break;
+
case IOCPF_E_FAIL:
break;
@@ -955,6 +1020,11 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
break;
+ case IOCPF_E_SEM_ERROR:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_ioc_pf_hwfailed(ioc);
+ break;
+
case IOCPF_E_DISABLE:
bfa_ioc_hw_sem_get_cancel(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -1044,6 +1114,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
}
break;
+ case IOCPF_E_SEM_ERROR:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_ioc_pf_hwfailed(ioc);
+ break;
+
case IOCPF_E_DISABLE:
bfa_ioc_hw_sem_get_cancel(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -1143,7 +1218,11 @@ bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
* will return 1. Semaphore is released by writing 1 to the register
*/
r32 = readl(ioc->ioc_regs.ioc_sem_reg);
- if (r32 == 0) {
+ if (r32 == ~0) {
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR);
+ return;
+ }
+ if (!(r32 & 1)) {
bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
return;
}
@@ -1334,6 +1413,7 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
if (!fwvalid) {
bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env);
+ bfa_ioc_poll_fwinit(ioc);
return;
}
@@ -1364,6 +1444,7 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
* Initialize the h/w for any other states.
*/
bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env);
+ bfa_ioc_poll_fwinit(ioc);
}
void
@@ -1645,6 +1726,12 @@ bfa_ioc_pf_failed(struct bfa_ioc *ioc)
}
static void
+bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
+}
+
+static void
bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc)
{
/**
@@ -1701,9 +1788,7 @@ bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,
bfa_ioc_msgflush(ioc);
bfa_ioc_download_fw(ioc, boot_type, boot_env);
-
bfa_ioc_lpu_start(ioc);
- bfa_ioc_poll_fwinit(ioc);
}
/**
--
1.7.1
^ permalink raw reply related
* [PATCH 26/45] bna: Ethfn LPU DMA Read Fix
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- In new HW, LPU cannot perform DMA read from host memory for PFs with
Ethernet functionality. As a result, BFI_ENET command processing (which
uses the msgq implementation and relies on LPU doing DMA read from host
memoty) will not work
- To fix this, msgq sends mailbox message to Host to request data from a
specified memory area, Host copies the data from specifies memory area
to mailbox and notifies the LPU, LPU upon receiving all fragments of
data, continues processing Enet commands
- Host processes LPU mailbox read status interrupt and schedules mailbox
poll routine. Host implements handler for BFI_MSGQ_I2H_CMDQ_COPY_REQ
message and uses BFI_MSGQ_H2I_CMDQ_COPY_RSP message to send data to LPU.
Msgq module in FW implements mailbox based cmdq read routine
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_ioc.c | 30 ++++++++++++++++++------------
drivers/net/bna/bfa_ioc.h | 5 +++++
2 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 216d0d1..beb63f9 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -2058,22 +2058,28 @@ bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc)
struct bfi_mbmsg m;
int mc;
- if (!bfa_ioc_msgget(ioc, &m))
- return;
+ if (bfa_ioc_msgget(ioc, &m)) {
+ /**
+ * Treat IOC message class as special.
+ */
+ mc = m.mh.msg_class;
+ if (mc == BFI_MC_IOC) {
+ bfa_ioc_isr(ioc, &m);
+ return;
+ }
- /**
- * Treat IOC message class as special.
- */
- mc = m.mh.msg_class;
- if (mc == BFI_MC_IOC) {
- bfa_ioc_isr(ioc, &m);
- return;
+ if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
+ return;
+
+ mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
}
- if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
- return;
+ bfa_ioc_lpu_read_stat(ioc);
- mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
+ /**
+ * Try to send pending mailbox commands
+ */
+ bfa_ioc_mbox_poll(ioc);
}
void
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index 07e1a9d..a9f24e2 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -281,6 +281,11 @@ void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
#define bfa_ioc_ownership_reset(__ioc) \
((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
+#define bfa_ioc_lpu_read_stat(__ioc) do { \
+ if ((__ioc)->ioc_hwif->ioc_lpu_read_stat) \
+ ((__ioc)->ioc_hwif->ioc_lpu_read_stat(__ioc)); \
+} while (0)
+
void bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc);
void bfa_nw_ioc_set_ct2_hwif(struct bfa_ioc *ioc);
--
1.7.1
^ permalink raw reply related
* [PATCH 27/45] bna: IOC Event Name Change
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- Changed event name IOC_E_PFAILED to IOC_E_PFFAILED
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_ioc.c | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index beb63f9..2dd19d2 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -108,7 +108,7 @@ enum ioc_event {
IOC_E_ENABLED = 5, /*!< f/w enabled */
IOC_E_FWRSP_GETATTR = 6, /*!< IOC get attribute response */
IOC_E_DISABLED = 7, /*!< f/w disabled */
- IOC_E_PFAILED = 8, /*!< failure notice by iocpf sm */
+ IOC_E_PFFAILED = 8, /*!< failure notice by iocpf sm */
IOC_E_HBFAIL = 9, /*!< heartbeat failure */
IOC_E_HWERROR = 10, /*!< hardware error interrupt */
IOC_E_TIMEOUT = 11, /*!< timeout */
@@ -299,12 +299,12 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
break;
- case IOC_E_PFAILED:
+ case IOC_E_PFFAILED:
/* !!! fall through !!! */
case IOC_E_HWERROR:
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
- if (event != IOC_E_PFAILED)
+ if (event != IOC_E_PFFAILED)
bfa_iocpf_initfail(ioc);
break;
@@ -354,14 +354,14 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
break;
- case IOC_E_PFAILED:
+ case IOC_E_PFFAILED:
case IOC_E_HWERROR:
del_timer(&ioc->ioc_timer);
/* fall through */
case IOC_E_TIMEOUT:
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
- if (event != IOC_E_PFAILED)
+ if (event != IOC_E_PFFAILED)
bfa_iocpf_getattrfail(ioc);
break;
@@ -397,7 +397,7 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
break;
- case IOC_E_PFAILED:
+ case IOC_E_PFFAILED:
case IOC_E_HWERROR:
bfa_ioc_hb_stop(ioc);
/* !!! fall through !!! */
@@ -409,7 +409,7 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
bfa_ioc_fail_notify(ioc);
- if (event != IOC_E_PFAILED)
+ if (event != IOC_E_PFFAILED)
bfa_iocpf_fail(ioc);
break;
@@ -501,14 +501,14 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
break;
- case IOC_E_PFAILED:
+ case IOC_E_PFFAILED:
case IOC_E_HWERROR:
/**
* Initialization retry failed.
*/
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
- if (event != IOC_E_PFAILED)
+ if (event != IOC_E_PFFAILED)
bfa_iocpf_initfail(ioc);
break;
@@ -1722,7 +1722,7 @@ bfa_ioc_pf_disabled(struct bfa_ioc *ioc)
static void
bfa_ioc_pf_failed(struct bfa_ioc *ioc)
{
- bfa_fsm_send_event(ioc, IOC_E_PFAILED);
+ bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
}
static void
--
1.7.1
^ permalink raw reply related
* [PATCH 28/45] bna: Add New IOC event
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- ACQ_ADDR IOC state and its state machine implementation.
- The changes related to FAA enable/disable/query in firmware
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_defs.h | 1 +
drivers/net/bna/bfa_defs_status.h | 9 +++++
drivers/net/bna/bfa_ioc.c | 69 ++++++++++++++++++++++++++++++++++++-
drivers/net/bna/bfi.h | 1 +
4 files changed, 79 insertions(+), 1 deletions(-)
diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index 621d50b..e7dd91f 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -125,6 +125,7 @@ enum bfa_ioc_state {
BFA_IOC_FWMISMATCH = 11, /*!< IOC f/w different from drivers */
BFA_IOC_ENABLING = 12, /*!< IOC is being enabled */
BFA_IOC_HWFAIL = 13, /*!< PCI mapping doesn't exist */
+ BFA_IOC_ACQ_ADDR = 14, /*!< Acquiring addr from fabric */
};
/**
diff --git a/drivers/net/bna/bfa_defs_status.h b/drivers/net/bna/bfa_defs_status.h
index 7c5fe6c..bf7f87a 100644
--- a/drivers/net/bna/bfa_defs_status.h
+++ b/drivers/net/bna/bfa_defs_status.h
@@ -205,6 +205,15 @@ enum bfa_status {
BFA_STATUS_BOOT_CODE_TIMEDOUT = 177,
BFA_STATUS_NO_VPORT_LOCK = 178,
BFA_STATUS_VPORT_NO_CNFG = 179,
+ BFA_STATUS_FEATURE_NOT_SUPPORTED = 180,
+ BFA_STATUS_ENTRY_EXISTS = 181,
+ BFA_STATUS_ENTRY_NOT_EXISTS = 182,
+ BFA_STATUS_NO_CHANGE = 183,
+ BFA_STATUS_DISABLED = 184,
+ BFA_STATUS_FAA_ENABLED = 185,
+ BFA_STATUS_FAA_DISABLED = 186,
+ BFA_STATUS_FAA_ACQUIRED = 187,
+ BFA_STATUS_FAA_ACQ_ADDR = 188,
BFA_STATUS_MAX_VAL
};
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 2dd19d2..2130b5a 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -113,6 +113,7 @@ enum ioc_event {
IOC_E_HWERROR = 10, /*!< hardware error interrupt */
IOC_E_TIMEOUT = 11, /*!< timeout */
IOC_E_HWFAILED = 12, /*!< PCI mapping failure notice */
+ IOC_E_FWRSP_ACQ_ADDR = 13, /*!< Acquiring address */
};
bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc, enum ioc_event);
@@ -125,6 +126,7 @@ bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, acq_addr, struct bfa_ioc, enum ioc_event);
static struct bfa_sm_table ioc_sm_table[] = {
{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
@@ -137,6 +139,7 @@ static struct bfa_sm_table ioc_sm_table[] = {
{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
{BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},
+ {BFA_SM(bfa_ioc_sm_acq_addr), BFA_IOC_ACQ_ADDR},
};
/**
@@ -351,9 +354,17 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event 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;
+ case IOC_E_FWRSP_ACQ_ADDR:
+ del_timer(&ioc->ioc_timer);
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_FAA_ACQ_ADDR);
+ bfa_ioc_hb_monitor(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_acq_addr);
+ break;
+
case IOC_E_PFFAILED:
case IOC_E_HWERROR:
del_timer(&ioc->ioc_timer);
@@ -378,11 +389,54 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
}
}
+/**
+ * Acquiring address from fabric (entry function)
+ */
+static void
+bfa_ioc_sm_acq_addr_entry(struct bfa_ioc *ioc)
+{
+}
+
+/**
+ * Acquiring address from the fabric
+ */
+static void
+bfa_ioc_sm_acq_addr(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_FWRSP_GETATTR:
+ bfa_ioc_check_attr_wwns(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+ break;
+
+ case IOC_E_PFFAILED:
+ case IOC_E_HWERROR:
+ bfa_ioc_hb_stop(ioc);
+ case IOC_E_HBFAIL:
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+ if (event != IOC_E_PFFAILED)
+ bfa_iocpf_getattrfail(ioc);
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_ioc_hb_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ break;
+
+ case IOC_E_ENABLE:
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
static void
bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
{
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
- bfa_ioc_hb_monitor(ioc);
+ bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
}
static void
@@ -1639,6 +1693,15 @@ bfa_ioc_getattr_reply(struct bfa_ioc *ioc)
}
/**
+ * Response from f/w that IOC attributes are not ready
+ */
+static void
+bfa_ioc_acq_addr_reply(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(ioc, IOC_E_FWRSP_ACQ_ADDR);
+}
+
+/**
* Attach time initialization of mbox logic.
*/
static void
@@ -1856,6 +1919,10 @@ bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
bfa_ioc_getattr_reply(ioc);
break;
+ case BFI_IOC_I2H_ACQ_ADDR_REPLY:
+ bfa_ioc_acq_addr_reply(ioc);
+ break;
+
default:
BUG_ON(1);
}
diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h
index d95eeb2..8d238a7 100644
--- a/drivers/net/bna/bfi.h
+++ b/drivers/net/bna/bfi.h
@@ -225,6 +225,7 @@ enum bfi_ioc_i2h_msgs {
BFI_IOC_I2H_DISABLE_REPLY = BFA_I2HM(2),
BFI_IOC_I2H_GETATTR_REPLY = BFA_I2HM(3),
BFI_IOC_I2H_HBEAT = BFA_I2HM(4),
+ BFI_IOC_I2H_ACQ_ADDR_REPLY = BFA_I2HM(5),
};
/**
--
1.7.1
^ permalink raw reply related
* [PATCH 29/45] bna: Add Sub-System Device ID Info
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- 1860 has CNA personality with SSID 22 for PCI functions.
- Preserve the same SSID numbering so that FCoE drivers claim adapters with
no-asic block (default personality).
Can we get this out?
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_defs.h | 10 ++++++++++
drivers/net/bna/bfa_ioc.c | 3 ++-
drivers/net/bna/bfa_ioc.h | 1 +
3 files changed, 13 insertions(+), 1 deletions(-)
diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index e7dd91f..3e5d096 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -261,4 +261,14 @@ enum {
#define bfa_asic_id_ctc(device) \
(bfa_asic_id_ct(device) || bfa_asic_id_ct2(device))
+/**
+ * PCI sub-system device and vendor ID information
+ */
+enum {
+ BFA_PCI_FCOE_SSDEVICE_ID = 0x14,
+ BFA_PCI_CT2_SSID_FCoE = 0x22,
+ BFA_PCI_CT2_SSID_ETH = 0x23,
+ BFA_PCI_CT2_SSID_FC = 0x24,
+};
+
#endif /* __BFA_DEFS_H__ */
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 2130b5a..78cdc2b 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -1987,7 +1987,8 @@ bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
case BFA_PCI_DEVICE_ID_CT2:
ioc->asic_gen = BFI_ASIC_GEN_CT2;
- if (clscode == BFI_PCIFN_CLASS_FC) {
+ if (clscode == BFI_PCIFN_CLASS_FC &&
+ pcidev->ssid == BFA_PCI_CT2_SSID_FC) {
ioc->asic_mode = BFI_ASIC_MODE_FC16;
ioc->fcmode = true;
} else {
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index a9f24e2..0f7dba1 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -35,6 +35,7 @@ struct bfa_pcidev {
int pci_slot;
u8 pci_func;
u16 device_id;
+ u16 ssid;
void __iomem *pci_bar_kva;
};
--
1.7.1
^ permalink raw reply related
* [PATCH 30/45] bna: Add HW Semaphore Unlock Logic
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- Added logic to unlock hw semaphore if the previos FW boot was from boot
code (flash based) and the current FW initialization attempt is from OS
driver.
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_ioc.c | 25 +++++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 78cdc2b..940c94a 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -58,6 +58,7 @@ static bool bfa_nw_auto_recover = true;
/*
* forward declarations
*/
+static void bfa_ioc_hw_sem_init(struct bfa_ioc *ioc);
static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc);
static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc);
static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force);
@@ -691,6 +692,7 @@ bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf *iocpf)
{
+ bfa_ioc_hw_sem_init(iocpf->ioc);
bfa_ioc_hw_sem_get(iocpf->ioc);
}
@@ -1263,6 +1265,29 @@ bfa_nw_ioc_sem_release(void __iomem *sem_reg)
}
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);
+
+ if (fwstate == BFI_IOC_UNINIT)
+ return;
+
+ bfa_nw_ioc_fwver_get(ioc, &fwhdr);
+
+ if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL)
+ return;
+
+ writel(BFI_IOC_UNINIT, ioc->ioc_regs.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);
+}
+
+static void
bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
{
u32 r32;
--
1.7.1
^ permalink raw reply related
* [PATCH 31/45] bna: Configuration changes
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
bnad.c:
- Set number of Tx and Rx queues bassed on underlying hardware.
- Take VLAN header into account for MTU calculation
- Default to INTx mode when pci_enable_msix() fails.
- Set a bit in Rx poll routine, check and wait for that bit to be cleared
in the cleanup routine before proceeding.
bnad.h:
- Define separate macros for maximum and supported numbers of Tx and Rx
queues based on underlying hardware
bna.h:
- Define a macro to access the supported attributes for underlying hardware
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bna.h | 4 ++
drivers/net/bna/bnad.c | 136 ++++++++++++++++++++++++++++++-----------------
drivers/net/bna/bnad.h | 23 ++++++---
3 files changed, 107 insertions(+), 56 deletions(-)
diff --git a/drivers/net/bna/bna.h b/drivers/net/bna/bna.h
index 518f3dd..66725d3 100644
--- a/drivers/net/bna/bna.h
+++ b/drivers/net/bna/bna.h
@@ -362,6 +362,8 @@ do { \
#define bna_is_prio_reconfig(_bna) ((_bna)->tx_mod.prio_reconfigured)
+#define bna_attr(_bna) (&(_bna)->ioceth.attr)
+
/**
*
* Inline functions
@@ -403,6 +405,8 @@ void bna_init(struct bna *bna, struct bnad *bnad,
struct bna_res_info *res_info);
void bna_mod_init(struct bna *bna, struct bna_res_info *res_info);
void bna_uninit(struct bna *bna);
+int bna_num_txq_set(struct bna *bna, int num_txq);
+int bna_num_rxp_set(struct bna *bna, int num_rxp);
void bna_stats_get(struct bna *bna);
void bna_get_perm_mac(struct bna *bna, u8 *mac);
void bna_hw_stats_get(struct bna *bna);
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 076f398..684ff91 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -441,9 +441,17 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
struct sk_buff *skb;
u32 flags, unmap_cons;
struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
+ struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl);
+
+ preempt_disable();
+
+ set_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
- if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))
+ if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)) {
+ clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
+ preempt_enable();
return 0;
+ }
prefetch(bnad->netdev);
BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl,
@@ -551,6 +559,10 @@ next:
bna_ib_ack(ccb->i_dbell, 0);
}
+ clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
+
+ preempt_enable();
+
return packets;
}
@@ -1259,7 +1271,7 @@ bnad_txrx_irq_free(struct bnad *bnad, struct bna_intr_info *intr_info)
/* Allocates Interrupt Descriptor List for MSIX/INT-X vectors */
static int
bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src,
- uint txrx_id, struct bna_intr_info *intr_info)
+ u32 txrx_id, struct bna_intr_info *intr_info)
{
int i, vector_start = 0;
u32 cfg_flags;
@@ -1342,7 +1354,7 @@ bnad_tx_msix_unregister(struct bnad *bnad, struct bnad_tx_info *tx_info,
*/
static int
bnad_tx_msix_register(struct bnad *bnad, struct bnad_tx_info *tx_info,
- uint tx_id, int num_txqs)
+ u32 tx_id, int num_txqs)
{
int i;
int err;
@@ -1395,7 +1407,7 @@ bnad_rx_msix_unregister(struct bnad *bnad, struct bnad_rx_info *rx_info,
*/
static int
bnad_rx_msix_register(struct bnad *bnad, struct bnad_rx_info *rx_info,
- uint rx_id, int num_rxps)
+ u32 rx_id, int num_rxps)
{
int i;
int err;
@@ -1439,7 +1451,7 @@ bnad_tx_res_free(struct bnad *bnad, struct bna_res_info *res_info)
/* Allocates memory and interrupt resources for Tx object */
static int
bnad_tx_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
- uint tx_id)
+ u32 tx_id)
{
int i, err = 0;
@@ -1733,7 +1745,7 @@ bnad_napi_disable(struct bnad *bnad, u32 rx_id)
/* Should be held with conf_lock held */
void
-bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
+bnad_cleanup_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];
@@ -1757,6 +1769,7 @@ bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
spin_unlock_irqrestore(&bnad->bna_lock, flags);
tx_info->tx = NULL;
+ tx_info->tx_id = 0;
if (0 == tx_id)
tasklet_kill(&bnad->tx_free_tasklet);
@@ -1766,7 +1779,7 @@ bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
/* Should be held with conf_lock held */
int
-bnad_setup_tx(struct bnad *bnad, uint tx_id)
+bnad_setup_tx(struct bnad *bnad, u32 tx_id)
{
int err;
struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
@@ -1778,6 +1791,8 @@ bnad_setup_tx(struct bnad *bnad, uint tx_id)
struct bna_tx *tx;
unsigned long flags;
+ tx_info->tx_id = tx_id;
+
/* Initialize the Tx object configuration */
tx_config->num_txq = bnad->num_txq_per_tx;
tx_config->txq_depth = bnad->txq_depth;
@@ -1869,7 +1884,7 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
/* Called with mutex_lock(&bnad->conf_mutex) held */
void
-bnad_cleanup_rx(struct bnad *bnad, uint rx_id)
+bnad_cleanup_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];
@@ -1912,7 +1927,7 @@ bnad_cleanup_rx(struct bnad *bnad, uint rx_id)
/* Called with mutex_lock(&bnad->conf_mutex) held */
int
-bnad_setup_rx(struct bnad *bnad, uint rx_id)
+bnad_setup_rx(struct bnad *bnad, u32 rx_id)
{
int err;
struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
@@ -1924,6 +1939,8 @@ bnad_setup_rx(struct bnad *bnad, uint rx_id)
struct bna_rx *rx;
unsigned long flags;
+ rx_info->rx_id = rx_id;
+
/* Initialize the Rx object configuration */
bnad_init_rx_config(bnad, rx_config);
@@ -2138,7 +2155,7 @@ void
bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
{
struct bfi_enet_stats_mac *mac_stats;
- u64 bmap;
+ u32 bmap;
int i;
mac_stats = &bnad->stats.bna_stats->hw_stats.mac_stats;
@@ -2253,7 +2270,7 @@ bnad_q_num_init(struct bnad *bnad)
bnad->num_rx = 1;
bnad->num_tx = 1;
bnad->num_rxp_per_rx = rxps;
- bnad->num_txq_per_tx = BNAD_TXQ_NUM;
+ bnad->num_txq_per_tx = BNAD_MAX_TXQ_PER_TX;
}
/*
@@ -2263,7 +2280,7 @@ bnad_q_num_init(struct bnad *bnad)
* Called with bnad->bna_lock held b'cos of cfg_flags access
*/
static void
-bnad_q_num_adjust(struct bnad *bnad, int msix_vectors)
+bnad_q_num_adjust(struct bnad *bnad, int msix_vectors, int temp)
{
bnad->num_txq_per_tx = 1;
if ((msix_vectors >= (bnad->num_tx * bnad->num_txq_per_tx) +
@@ -2317,12 +2334,12 @@ bnad_ioceth_enable(struct bnad *bnad)
/* Free BNA resources */
static void
-bnad_res_free(struct bnad *bnad)
+bnad_res_free(struct bnad *bnad, struct bna_res_info *res_info,
+ u32 res_val_max)
{
int i;
- struct bna_res_info *res_info = &bnad->res_info[0];
- for (i = 0; i < BNA_RES_T_MAX; i++) {
+ for (i = 0; i < res_val_max; i++) {
if (res_info[i].res_type == BNA_RES_T_MEM)
bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
else
@@ -2332,10 +2349,10 @@ bnad_res_free(struct bnad *bnad)
/* Allocates memory and interrupt resources for BNA */
static int
-bnad_res_alloc(struct bnad *bnad)
+bnad_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
+ u32 res_val_max)
{
int i, err;
- struct bna_res_info *res_info = &bnad->res_info[0];
for (i = 0; i < BNA_RES_T_MAX; i++) {
if (res_info[i].res_type == BNA_RES_T_MEM)
@@ -2349,7 +2366,7 @@ bnad_res_alloc(struct bnad *bnad)
return 0;
err_return:
- bnad_res_free(bnad);
+ bnad_res_free(bnad, res_info, res_val_max);
return err;
}
@@ -2385,7 +2402,7 @@ bnad_enable_msix(struct bnad *bnad)
spin_lock_irqsave(&bnad->bna_lock, flags);
/* ret = #of vectors that we got */
- bnad_q_num_adjust(bnad, ret);
+ bnad_q_num_adjust(bnad, ret, 0);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx)
@@ -2393,6 +2410,9 @@ bnad_enable_msix(struct bnad *bnad)
* bnad->num_rxp_per_rx) +
BNAD_MAILBOX_MSIX_VECTORS;
+ if (bnad->msix_num > ret)
+ goto intx_mode;
+
/* Try once more with adjusted numbers */
/* If this fails, fall back to INTx */
ret = pci_enable_msix(bnad->pcidev, bnad->msix_table,
@@ -2402,6 +2422,9 @@ bnad_enable_msix(struct bnad *bnad)
} else if (ret < 0)
goto intx_mode;
+
+ pci_intx(bnad->pcidev, 0);
+
return;
intx_mode:
@@ -2460,7 +2483,7 @@ bnad_open(struct net_device *netdev)
pause_config.tx_pause = 0;
pause_config.rx_pause = 0;
- mtu = ETH_HLEN + bnad->netdev->mtu + ETH_FCS_LEN;
+ mtu = ETH_HLEN + VLAN_HLEN + bnad->netdev->mtu + ETH_FCS_LEN;
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_enet_mtu_set(&bnad->bna.enet, mtu, NULL);
@@ -2534,16 +2557,15 @@ static netdev_tx_t
bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{
struct bnad *bnad = netdev_priv(netdev);
+ u32 txq_id = 0;
+ struct bna_tcb *tcb = bnad->tx_info[0].tcb[txq_id];
u16 txq_prod, vlan_tag = 0;
u32 unmap_prod, wis, wis_used, wi_range;
u32 vectors, vect_id, i, acked;
- u32 tx_id;
int err;
- struct bnad_tx_info *tx_info;
- struct bna_tcb *tcb;
- struct bnad_unmap_q *unmap_q;
+ struct bnad_unmap_q *unmap_q = tcb->unmap_q;
dma_addr_t dma_addr;
struct bna_txq_entry *txqent;
u16 flags;
@@ -2554,15 +2576,9 @@ 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.
+ * and the netif_stop_all_queue() call.
*/
if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) {
dev_kfree_skb(skb);
@@ -2576,9 +2592,8 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
}
wis = BNA_TXQ_WI_NEEDED(vectors); /* 4 vectors per work item */
acked = 0;
- if (unlikely
- (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
- vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
+ if (unlikely(wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
+ vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
if ((u16) (*tcb->hw_consumer_index) !=
tcb->consumer_index &&
!test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
@@ -3190,12 +3205,15 @@ bnad_pci_probe(struct pci_dev *pdev,
*/
netdev = alloc_etherdev(sizeof(struct bnad));
if (!netdev) {
- dev_err(&pdev->dev, "alloc_etherdev failed\n");
+ dev_err(&pdev->dev, "netdev allocation failed\n");
err = -ENOMEM;
return err;
}
bnad = netdev_priv(netdev);
+ bnad_lock_init(bnad);
+
+ mutex_lock(&bnad->conf_mutex);
/*
* PCI initialization
* Output : using_dac = 1 for 64 bit DMA
@@ -3205,7 +3223,6 @@ bnad_pci_probe(struct pci_dev *pdev,
if (err)
goto free_netdev;
- bnad_lock_init(bnad);
/*
* Initialize bnad structure
* Setup relation between pci_dev & netdev
@@ -3214,6 +3231,7 @@ bnad_pci_probe(struct pci_dev *pdev,
err = bnad_init(bnad, pdev, netdev);
if (err)
goto pci_uninit;
+
/* Initialize netdev structure, set up ethtool ops */
bnad_netdev_init(bnad, using_dac);
@@ -3223,10 +3241,12 @@ bnad_pci_probe(struct pci_dev *pdev,
bnad_enable_msix(bnad);
/* Get resource requirement form bna */
+ spin_lock_irqsave(&bnad->bna_lock, flags);
bna_res_req(&bnad->res_info[0]);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
/* Allocate resources from bna */
- err = bnad_res_alloc(bnad);
+ err = bnad_res_alloc(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
if (err)
goto free_netdev;
@@ -3238,8 +3258,6 @@ bnad_pci_probe(struct pci_dev *pdev,
pcidev_info.device_id = bnad->pcidev->device;
pcidev_info.pci_bar_kva = bnad->bar0;
- mutex_lock(&bnad->conf_mutex);
-
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_init(bna, bnad, &pcidev_info, &bnad->res_info[0]);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -3262,10 +3280,32 @@ bnad_pci_probe(struct pci_dev *pdev,
/*
* Start the chip
- * Don't care even if err != 0, bna state machine will
- * deal with it
+ * If the call back comes with error, we bail out.
+ * This is a catastrophic error.
*/
err = bnad_ioceth_enable(bnad);
+ if (err)
+ goto disable_device;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (bna_num_txq_set(bna, BNAD_NUM_TXQ + 1) ||
+ bna_num_rxp_set(bna, BNAD_NUM_RXP + 1)) {
+ bnad_q_num_adjust(bnad, bna_attr(bna)->num_txq - 1,
+ bna_attr(bna)->num_rxp - 1);
+ if (bna_num_txq_set(bna, BNAD_NUM_TXQ + 1) ||
+ bna_num_rxp_set(bna, BNAD_NUM_RXP + 1))
+ err = -EIO;
+ }
+ bna_mod_res_req(&bnad->bna, &bnad->mod_res_info[0]);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ err = bnad_res_alloc(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+ if (err)
+ goto disable_device;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_mod_init(&bnad->bna, &bnad->mod_res_info[0]);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
/* Get the burnt-in mac */
spin_lock_irqsave(&bnad->bna_lock, flags);
@@ -3273,19 +3313,17 @@ bnad_pci_probe(struct pci_dev *pdev,
bnad_set_netdev_perm_addr(bnad);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- mutex_unlock(&bnad->conf_mutex);
-
/* Finally, reguister with net_device layer */
err = register_netdev(netdev);
if (err) {
pr_err("BNA : Registering with netdev failed\n");
goto disable_device;
}
+ mutex_unlock(&bnad->conf_mutex);
return 0;
disable_device:
- mutex_lock(&bnad->conf_mutex);
bnad_ioceth_disable(bnad);
del_timer_sync(&bnad->bna.ioceth.ioc.ioc_timer);
del_timer_sync(&bnad->bna.ioceth.ioc.sem_timer);
@@ -3293,9 +3331,8 @@ disable_device:
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_uninit(bna);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- mutex_unlock(&bnad->conf_mutex);
-
- bnad_res_free(bnad);
+ bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+ bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
bnad_disable_msix(bnad);
pci_uninit:
bnad_pci_uninit(pdev);
@@ -3331,11 +3368,12 @@ bnad_pci_remove(struct pci_dev *pdev)
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_uninit(bna);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- mutex_unlock(&bnad->conf_mutex);
- bnad_res_free(bnad);
+ bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+ bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
bnad_disable_msix(bnad);
bnad_pci_uninit(pdev);
+ mutex_unlock(&bnad->conf_mutex);
bnad_lock_uninit(bnad);
bnad_uninit(bnad);
free_netdev(netdev);
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index 6a161b0..41ade02 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -38,12 +38,11 @@
#define BNAD_RXQ_DEPTH 2048
#define BNAD_MAX_TX 1
-#define BNAD_MAX_TXQ_PER_TX 8 /* 8 priority queues */
-#define BNAD_TXQ_NUM 1
+#define BNAD_MAX_TXQ_PER_TX 8
#define BNAD_MAX_RX 1
#define BNAD_MAX_RXP_PER_RX 16
-#define BNAD_MAX_RXQ_PER_RXP 2
+#define BNAD_MAX_RXQ_PER_RXP 2
/*
* Control structure pointed to ccb->ctrl, which
@@ -95,6 +94,13 @@ struct bnad_rx_ctrl {
#define BNAD_RXQ_REFILL 0
#define BNAD_RXQ_STARTED 1
+/* Resource limits */
+#define BNAD_MAX_TXQ (BNAD_MAX_TX * BNAD_MAX_TXQ_PER_TX)
+#define BNAD_MAX_RXP (BNAD_MAX_RX * BNAD_MAX_RXP_PER_RX)
+
+#define BNAD_NUM_TXQ (bnad->num_tx * bnad->num_txq_per_tx)
+#define BNAD_NUM_RXP (bnad->num_rx * bnad->num_rxp_per_rx)
+
/*
* DATA STRUCTURES
*/
@@ -179,12 +185,14 @@ struct bnad_rx_res_info {
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;
} ____cacheline_aligned;
struct bnad_rx_info {
struct bna_rx *rx; /* 1:1 between rx_info & rx */
struct bnad_rx_ctrl rx_ctrl[BNAD_MAX_RXP_PER_RX];
+ u32 rx_id;
} ____cacheline_aligned;
/* Unmap queues for Tx / Rx cleanup */
@@ -274,6 +282,7 @@ struct bnad {
/* Control path resources, memory & irq */
struct bna_res_info res_info[BNA_RES_T_MAX];
+ struct bna_res_info mod_res_info[BNA_MOD_RES_T_MAX];
struct bnad_tx_res_info tx_res_info[BNAD_MAX_TX];
struct bnad_rx_res_info rx_res_info[BNAD_MAX_RX];
@@ -311,10 +320,10 @@ extern void bnad_set_ethtool_ops(struct net_device *netdev);
extern void bnad_tx_coalescing_timeo_set(struct bnad *bnad);
extern void bnad_rx_coalescing_timeo_set(struct bnad *bnad);
-extern int bnad_setup_rx(struct bnad *bnad, uint rx_id);
-extern int bnad_setup_tx(struct bnad *bnad, uint tx_id);
-extern void bnad_cleanup_tx(struct bnad *bnad, uint tx_id);
-extern void bnad_cleanup_rx(struct bnad *bnad, uint rx_id);
+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);
/* Timer start/stop protos */
extern void bnad_dim_timer_start(struct bnad *bnad);
--
1.7.1
^ permalink raw reply related
* [PATCH 32/45] bna: TxRx Coalesce Settings Fix and Reorg PCI Probe Failure
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- The TX and Rx coalesce settings are programmed in steps of 5 us. The value
that are not divisible by 5 are rounded to the next lower number. This was
causing the value os 1 to 4 to be rounded to 0, which is an invalid setting.
- When creating Rx and Tx object, we are currently assigning the default
values of Rx and Tx coalescing_timeo. If these values are changed in
the driver to a different value, the change is lost during such
operations as MTU change. In order to avoid that, pass the configured
value of coalescing_timeo before Rx and Tx object creation.
- Fix bnad_tx_coalescing_timeo_set() so it applies to all the Tx objects.
- Fix uninitialization path in case of pci_probe failure.
- Added/Removed flags.
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bnad.c | 46 ++++++++++++++++++++++++++++++----------------
drivers/net/bna/bnad.h | 9 +++++----
2 files changed, 35 insertions(+), 20 deletions(-)
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 684ff91..6d1b82b 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -1797,6 +1797,7 @@ bnad_setup_tx(struct bnad *bnad, u32 tx_id)
tx_config->num_txq = bnad->num_txq_per_tx;
tx_config->txq_depth = bnad->txq_depth;
tx_config->tx_type = BNA_TX_T_REGULAR;
+ tx_config->coalescing_timeo = bnad->tx_coalescing_timeo;
/* Initialize the tx event handlers */
tx_cbfn.tcb_setup_cbfn = bnad_cb_tcb_setup;
@@ -1857,6 +1858,7 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
{
rx_config->rx_type = BNA_RX_T_REGULAR;
rx_config->num_paths = bnad->num_rxp_per_rx;
+ rx_config->coalescing_timeo = bnad->rx_coalescing_timeo;
if (bnad->num_rxp_per_rx > 1) {
rx_config->rss_status = BNA_STATUS_T_ENABLED;
@@ -2017,12 +2019,15 @@ void
bnad_tx_coalescing_timeo_set(struct bnad *bnad)
{
struct bnad_tx_info *tx_info;
+ int i;
- tx_info = &bnad->tx_info[0];
- if (!tx_info->tx)
- return;
-
- bna_tx_coalescing_timeo_set(tx_info->tx, bnad->tx_coalescing_timeo);
+ for (i = 0; i < bnad->num_tx; i++) {
+ tx_info = &bnad->tx_info[i];
+ if (!tx_info->tx)
+ continue;
+ bna_tx_coalescing_timeo_set(tx_info->tx,
+ bnad->tx_coalescing_timeo);
+ }
}
/* Called with conf_lock & bnad->bna_lock held */
@@ -2726,7 +2731,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
- u32 size = frag->size;
+ u16 size = frag->size;
if (++vect_id == BFI_TX_MAX_VECTORS_PER_WI) {
vect_id = 0;
@@ -3248,7 +3253,7 @@ bnad_pci_probe(struct pci_dev *pdev,
/* Allocate resources from bna */
err = bnad_res_alloc(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
if (err)
- goto free_netdev;
+ goto drv_uninit;
bna = &bnad->bna;
@@ -3284,8 +3289,11 @@ bnad_pci_probe(struct pci_dev *pdev,
* This is a catastrophic error.
*/
err = bnad_ioceth_enable(bnad);
- if (err)
- goto disable_device;
+ if (err) {
+ pr_err("BNA: Initialization failed err=%d\n",
+ err);
+ goto probe_success;
+ }
spin_lock_irqsave(&bnad->bna_lock, flags);
if (bna_num_txq_set(bna, BNAD_NUM_TXQ + 1) ||
@@ -3301,7 +3309,7 @@ bnad_pci_probe(struct pci_dev *pdev,
err = bnad_res_alloc(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
if (err)
- goto disable_device;
+ goto disable_ioceth;
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_mod_init(&bnad->bna, &bnad->mod_res_info[0]);
@@ -3317,13 +3325,17 @@ bnad_pci_probe(struct pci_dev *pdev,
err = register_netdev(netdev);
if (err) {
pr_err("BNA : Registering with netdev failed\n");
- goto disable_device;
+ goto probe_uninit;
}
- mutex_unlock(&bnad->conf_mutex);
+ set_bit(BNAD_RF_NETDEV_REGISTERED, &bnad->run_flags);
+probe_success:
+ mutex_unlock(&bnad->conf_mutex);
return 0;
-disable_device:
+probe_uninit:
+ bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+disable_ioceth:
bnad_ioceth_disable(bnad);
del_timer_sync(&bnad->bna.ioceth.ioc.ioc_timer);
del_timer_sync(&bnad->bna.ioceth.ioc.sem_timer);
@@ -3331,13 +3343,14 @@ disable_device:
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_uninit(bna);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
+drv_uninit:
bnad_disable_msix(bnad);
+ bnad_uninit(bnad);
pci_uninit:
bnad_pci_uninit(pdev);
+ mutex_unlock(&bnad->conf_mutex);
bnad_lock_uninit(bnad);
- bnad_uninit(bnad);
free_netdev:
free_netdev(netdev);
return err;
@@ -3358,7 +3371,8 @@ bnad_pci_remove(struct pci_dev *pdev)
bnad = netdev_priv(netdev);
bna = &bnad->bna;
- unregister_netdev(netdev);
+ if (test_and_clear_bit(BNAD_RF_NETDEV_REGISTERED, &bnad->run_flags))
+ unregister_netdev(netdev);
mutex_lock(&bnad->conf_mutex);
bnad_ioceth_disable(bnad);
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index 41ade02..c25e6e2 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -218,13 +218,14 @@ struct bnad_unmap_q {
/* Defines for run_flags bit-mask */
/* Set, tested & cleared using xxx_bit() functions */
/* Values indicated bit positions */
-#define BNAD_RF_CEE_RUNNING 1
+#define BNAD_RF_CEE_RUNNING 0
+#define BNAD_RF_MTU_SET 1
#define BNAD_RF_MBOX_IRQ_DISABLED 2
-#define BNAD_RF_RX_STARTED 3
+#define BNAD_RF_NETDEV_REGISTERED 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
+#define BNAD_RF_TX_PRIO_SET 6
+
/* Define for Fast Path flags */
/* Defined as bit positions */
--
1.7.1
^ permalink raw reply related
* [PATCH 33/45] bna: Device Init Fix
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- Do not return probe failure when device initialization fails so that the
driver stays loaded and the hardware is accessible for debugging.
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bnad.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 6d1b82b..2b716ed 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -3308,19 +3308,21 @@ bnad_pci_probe(struct pci_dev *pdev,
spin_unlock_irqrestore(&bnad->bna_lock, flags);
err = bnad_res_alloc(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
- if (err)
+ if (err) {
+ err = -EIO;
goto disable_ioceth;
+ }
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_mod_init(&bnad->bna, &bnad->mod_res_info[0]);
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
/* Get the burnt-in mac */
- spin_lock_irqsave(&bnad->bna_lock, flags);
bna_enet_perm_mac_get(&bna->enet, &bnad->perm_addr);
bnad_set_netdev_perm_addr(bnad);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ mutex_unlock(&bnad->conf_mutex);
+
/* Finally, reguister with net_device layer */
err = register_netdev(netdev);
if (err) {
@@ -3329,6 +3331,8 @@ bnad_pci_probe(struct pci_dev *pdev,
}
set_bit(BNAD_RF_NETDEV_REGISTERED, &bnad->run_flags);
+ return 0;
+
probe_success:
mutex_unlock(&bnad->conf_mutex);
return 0;
--
1.7.1
^ permalink raw reply related
* [PATCH 34/45] bna: Add Multiple Tx Queue Support
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- Added support for multipe Tx queues with a separate iSCSI Tx queue based
on the default value of iSCSI port number. The feature is supported based
on the underlying hardware and enabled for DCB (CEE) mode only.
- Allocate multiple TxQ resource in netdev
- Implement bnad_tx_select_queue() which enables the correct selection of
TxQ Id (and tcb). This function is called either by the kernel to channel
packets to the right TxQ
- Implement bnad_iscsi_tcb_get() and BNAD_IS_ISCSI_PKT() for iSCSI packet
inspection and retrieval of tcb corresponding to the iSCSI priority.
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bna_types.h | 2 +
drivers/net/bna/bnad.c | 146 ++++++++++++++++++++++++++++++++++---------
drivers/net/bna/bnad.h | 9 +++
3 files changed, 127 insertions(+), 30 deletions(-)
diff --git a/drivers/net/bna/bna_types.h b/drivers/net/bna/bna_types.h
index a4f71c0..7f037db 100644
--- a/drivers/net/bna/bna_types.h
+++ b/drivers/net/bna/bna_types.h
@@ -329,6 +329,7 @@ struct bna_attr {
int num_ucmac;
int num_mcmac;
int max_rit_size;
+ int max_ets_groups;
};
/**
@@ -578,6 +579,7 @@ struct bna_tx_mod {
int iscsi_over_cee;
int iscsi_prio;
int prio_reconfigured;
+ void *prio_indirection[BFI_TX_MAX_PRIO];
u32 rid_mask;
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 2b716ed..8ca1b60 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -194,8 +194,6 @@ bnad_free_txbufs(struct bnad *bnad,
while (wis) {
skb = unmap_array[unmap_cons].skb;
- unmap_array[unmap_cons].skb = NULL;
-
sent_packets++;
sent_bytes += skb->len;
wis -= BNA_TXQ_WI_NEEDED(1 + skb_shinfo(skb)->nr_frags);
@@ -245,7 +243,7 @@ bnad_tx_free_tasklet(unsigned long bnad_ptr)
{
struct bnad *bnad = (struct bnad *)bnad_ptr;
struct bna_tcb *tcb;
- u32 acked = 0;
+ u32 acked = 0, txq_id;
int i, j;
for (i = 0; i < bnad->num_tx; i++) {
@@ -264,14 +262,20 @@ bnad_tx_free_tasklet(unsigned long bnad_ptr)
smp_mb__before_clear_bit();
clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
}
+ /*
+ * Check again, because this bit can be set from another
+ * context. This is not lock protected.
+ */
if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED,
&tcb->flags)))
continue;
- if (netif_queue_stopped(bnad->netdev)) {
+ txq_id = tcb->id;
+ if (__netif_subqueue_stopped(bnad->netdev, txq_id)) {
if (acked && netif_carrier_ok(bnad->netdev) &&
BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
BNAD_NETIF_WAKE_THRESHOLD) {
- netif_wake_queue(bnad->netdev);
+ netif_wake_subqueue(bnad->netdev,
+ txq_id);
/* TODO */
/* Counters for individual TxQs? */
BNAD_UPDATE_CTR(bnad,
@@ -286,19 +290,21 @@ static u32
bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
{
struct net_device *netdev = bnad->netdev;
- u32 sent = 0;
+ u32 sent = 0, txq_id;
if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
return 0;
sent = bnad_free_txbufs(bnad, tcb);
if (sent) {
- if (netif_queue_stopped(netdev) &&
+ txq_id = tcb->id;
+
+ if (__netif_subqueue_stopped(netdev, txq_id) &&
netif_carrier_ok(netdev) &&
BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
BNAD_NETIF_WAKE_THRESHOLD) {
if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) {
- netif_wake_queue(netdev);
+ netif_wake_subqueue(netdev, txq_id);
BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
}
}
@@ -850,7 +856,9 @@ bnad_cb_tcb_setup(struct bnad *bnad, struct bna_tcb *tcb)
(struct bnad_tx_info *)tcb->txq->tx->priv;
struct bnad_unmap_q *unmap_q = tcb->unmap_q;
+ tcb->priv = tcb;
tx_info->tcb[tcb->id] = tcb;
+
unmap_q->producer_index = 0;
unmap_q->consumer_index = 0;
unmap_q->q_depth = BNAD_TX_UNMAPQ_DEPTH;
@@ -875,6 +883,7 @@ bnad_cb_tcb_destroy(struct bnad *bnad, struct bna_tcb *tcb)
clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
tx_info->tcb[tcb->id] = NULL;
+ tcb->priv = NULL;
}
static void
@@ -1777,6 +1786,29 @@ bnad_cleanup_tx(struct bnad *bnad, u32 tx_id)
bnad_tx_res_free(bnad, res_info);
}
+/*
+ * Sets up bnad->num_tx depending on the current value (already
+ * adjusted based on MSIX vectors available and ETS support in
+ * the chip
+ */
+static void
+bnad_num_txq_set(struct bnad *bnad)
+{
+ struct bna *bna = &bnad->bna;
+ struct bna_attr attr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ attr = bna->ioceth.attr;
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ if (attr.max_ets_groups < BFI_TX_MAX_PRIO)
+ bnad->num_txq_per_tx = 1;
+ else
+ bnad->num_txq_per_tx = min((u32)attr.max_ets_groups,
+ (u32)bnad->num_txq_per_tx);
+}
+
/* Should be held with conf_lock held */
int
bnad_setup_tx(struct bnad *bnad, u32 tx_id)
@@ -1793,6 +1825,8 @@ bnad_setup_tx(struct bnad *bnad, u32 tx_id)
tx_info->tx_id = tx_id;
+ bnad_num_txq_set(bnad);
+
/* Initialize the Tx object configuration */
tx_config->num_txq = bnad->num_txq_per_tx;
tx_config->txq_depth = bnad->txq_depth;
@@ -2264,38 +2298,45 @@ bnad_tso_prepare(struct bnad *bnad, struct sk_buff *skb)
static void
bnad_q_num_init(struct bnad *bnad)
{
- int rxps;
+ int rxps = min((u32)num_online_cpus(),
+ (u32)(BNAD_MAX_RXP_PER_RX));
- rxps = min((uint)num_online_cpus(),
- (uint)(BNAD_MAX_RX * BNAD_MAX_RXP_PER_RX));
+ BNA_TO_POWER_OF_2(rxps);
if (!(bnad->cfg_flags & BNAD_CF_MSIX))
rxps = 1; /* INTx */
- bnad->num_rx = 1;
- bnad->num_tx = 1;
+ bnad->num_rx = BNAD_MAX_RX;
+ bnad->num_tx = BNAD_MAX_TX;
bnad->num_rxp_per_rx = rxps;
bnad->num_txq_per_tx = BNAD_MAX_TXQ_PER_TX;
}
/*
- * Adjusts the Q numbers, given a number of msix vectors
+ * Adjusts the Q numbers, given a number of max possible queues.
* Give preference to RSS as opposed to Tx priority Queues,
* in such a case, just use 1 Tx Q
* Called with bnad->bna_lock held b'cos of cfg_flags access
*/
static void
-bnad_q_num_adjust(struct bnad *bnad, int msix_vectors, int temp)
+bnad_q_num_adjust(struct bnad *bnad, int max_txq, int max_rxq)
{
- bnad->num_txq_per_tx = 1;
- if ((msix_vectors >= (bnad->num_tx * bnad->num_txq_per_tx) +
- bnad_rxqs_per_cq + BNAD_MAILBOX_MSIX_VECTORS) &&
- (bnad->cfg_flags & BNAD_CF_MSIX)) {
- bnad->num_rxp_per_rx = msix_vectors -
- (bnad->num_tx * bnad->num_txq_per_tx) -
- BNAD_MAILBOX_MSIX_VECTORS;
- } else
- bnad->num_rxp_per_rx = 1;
+ if (!(bnad->cfg_flags & BNAD_CF_MSIX)) {
+ bnad->num_tx = bnad->num_txq_per_tx = 1;
+ bnad->num_rx = bnad->num_rxp_per_rx = 1;
+ return;
+ }
+
+ if (max_txq < BNAD_NUM_TXQ) {
+ bnad->num_txq_per_tx = 1;
+ bnad->num_tx = 1;
+ }
+
+ bnad->num_rx = 1;
+ bnad->num_rxp_per_rx = min((u32)(min((u32)num_online_cpus(),
+ (u32)(BNAD_MAX_RXP_PER_RX))),
+ (u32)max_rxq);
+ BNA_TO_POWER_OF_2(bnad->num_rxp_per_rx);
}
/* Enable / disable ioceth */
@@ -2359,7 +2400,7 @@ bnad_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
{
int i, err;
- for (i = 0; i < BNA_RES_T_MAX; i++) {
+ for (i = 0; i < res_val_max; i++) {
if (res_info[i].res_type == BNA_RES_T_MEM)
err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info);
else
@@ -2433,7 +2474,6 @@ bnad_enable_msix(struct bnad *bnad)
return;
intx_mode:
-
kfree(bnad->msix_table);
bnad->msix_table = NULL;
bnad->msix_num = 0;
@@ -2608,7 +2648,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
smp_mb__before_clear_bit();
clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
} else {
- netif_stop_queue(netdev);
+ netif_stop_subqueue(netdev, txq_id);
BNAD_UPDATE_CTR(bnad, netif_queue_stop);
}
@@ -2624,7 +2664,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
BNAD_UPDATE_CTR(bnad, netif_queue_stop);
return NETDEV_TX_BUSY;
} else {
- netif_wake_queue(netdev);
+ netif_wake_subqueue(netdev, txq_id);
BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
}
}
@@ -2649,7 +2689,8 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
}
if (test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags)) {
vlan_tag =
- (tcb->priority & 0x7) << 13 | (vlan_tag & 0x1fff);
+ ((tcb->priority & 0x7) << VLAN_PRIO_SHIFT)
+ | (vlan_tag & 0x1fff);
flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN);
}
@@ -2796,6 +2837,50 @@ bnad_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
return stats;
}
+static bool bnad_is_iscsi(struct sk_buff *skb)
+{
+ u16 proto = 0;
+ struct tcphdr *th;
+
+ if (skb->protocol == htons(ETH_P_IP))
+ proto = ip_hdr(skb)->protocol;
+ else if (skb->protocol == htons(ETH_P_IPV6))
+ /* nexthdr may not be TCP immediately. */
+ proto = ipv6_hdr(skb)->nexthdr;
+ if (proto == IPPROTO_TCP) {
+ th = tcp_hdr(skb);
+ if (BNAD_IS_ISCSI_PKT(th))
+ return true;
+ }
+
+ return false;
+}
+
+static u16
+bnad_tx_select_queue(struct net_device *netdev, struct sk_buff *skb)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ struct bna *bna = &bnad->bna;
+ u8 prio = 0;
+
+ if (bnad->num_txq_per_tx < BFI_TX_MAX_PRIO)
+ prio = 0;
+ else if (bna_is_iscsi_over_cee(&bnad->bna) && bnad_is_iscsi(skb))
+ prio = bna_iscsi_prio(bna);
+ else if (vlan_tx_tag_present(skb)) {
+ u8 pkt_vlan_prio = 0;
+ u16 pkt_vlan_tag = 0;
+ pkt_vlan_tag = (u16)vlan_tx_tag_get(skb);
+ pkt_vlan_prio = (pkt_vlan_tag & VLAN_PRIO_MASK)
+ >> VLAN_PRIO_SHIFT;
+ prio = bna_prio_allowed(bna, pkt_vlan_prio) ?
+ pkt_vlan_prio : bna_default_prio(bna);
+ } else
+ prio = bna_default_prio(bna);
+
+ return (u16)prio;
+}
+
static void
bnad_set_rx_mode(struct net_device *netdev)
{
@@ -3011,6 +3096,7 @@ bnad_netpoll(struct net_device *netdev)
static const struct net_device_ops bnad_netdev_ops = {
.ndo_open = bnad_open,
.ndo_stop = bnad_stop,
+ .ndo_select_queue = bnad_tx_select_queue,
.ndo_start_xmit = bnad_start_xmit,
.ndo_get_stats64 = bnad_get_stats64,
.ndo_set_rx_mode = bnad_set_rx_mode,
@@ -3208,7 +3294,7 @@ bnad_pci_probe(struct pci_dev *pdev,
* Allocates sizeof(struct net_device + struct bnad)
* bnad = netdev->priv
*/
- netdev = alloc_etherdev(sizeof(struct bnad));
+ netdev = alloc_etherdev_mq(sizeof(struct bnad), BNAD_MAX_TXQ);
if (!netdev) {
dev_err(&pdev->dev, "netdev allocation failed\n");
err = -ENOMEM;
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index c25e6e2..1b87b27 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -231,6 +231,15 @@ struct bnad_unmap_q {
/* Defined as bit positions */
#define BNAD_FP_IN_RX_PATH 0
+/*
+ * Deep Inspection : Checks if packet is ISCSI based on
+ * standard iSCSI port
+ */
+#define BNAD_TCP_ISCSI_PORT 3260
+#define BNAD_IS_ISCSI_PKT(_tch) \
+(((_tch)->source == ntohs(BNAD_TCP_ISCSI_PORT)) || \
+ ((_tch)->dest == ntohs(BNAD_TCP_ISCSI_PORT)))
+
struct bnad {
struct net_device *netdev;
--
1.7.1
^ permalink raw reply related
* [PATCH 35/45] bna: Change TxQ Select Logic and Interrupt Handling
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- Simplify the TxQ selection logic:
Macro BNAD_TXQ_ID_GET() calls bnad_tx_select_queue(), which returns priority.
While only a few packets during transition could have wrong priority, all
will be associated with a valid non-NULL tcb.
- Add bnad pointer to rx_ctrl structure, so that bnad can be accessed directly
from rx_ctrl in the NAPI poll routines, even if ccb is NULL
- Fix the order of init / uninit in Tx / Rx setup / teardown path:
Kill bnad tx free tasklet ahead of call to bna_tx_destroy().
Call NAPI disable only aftet call to Rx free_irq(). This makes sure Rx
interrupt does not schedule a poll when NAPI is already disabled.
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bnad.c | 70 +++++++++++++++++++++++++++++++----------------
drivers/net/bna/bnad.h | 1 +
2 files changed, 47 insertions(+), 24 deletions(-)
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 8ca1b60..3f9ddbf 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -554,16 +554,11 @@ next:
BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
- if (likely(ccb)) {
- 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 {
- if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
- bna_ib_ack(ccb->i_dbell, 0);
- }
+ 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]);
clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
@@ -613,7 +608,8 @@ bnad_msix_rx(int irq, void *data)
struct bna_ccb *ccb = (struct bna_ccb *)data;
struct bnad *bnad = ccb->bnad;
- bnad_netif_rx_schedule_poll(bnad, ccb);
+ if (ccb)
+ bnad_netif_rx_schedule_poll(bnad, ccb);
return IRQ_HANDLED;
}
@@ -652,6 +648,7 @@ bnad_isr(int irq, void *data)
struct bnad *bnad = (struct bnad *)data;
struct bnad_rx_info *rx_info;
struct bnad_rx_ctrl *rx_ctrl;
+ struct bna_tcb *tcb = NULL;
if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
return IRQ_NONE;
@@ -674,8 +671,11 @@ bnad_isr(int irq, void *data)
/* 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]);
+ 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]);
+ }
}
/* Rx processing */
for (i = 0; i < bnad->num_rx; i++) {
@@ -1773,6 +1773,9 @@ 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);
@@ -1780,9 +1783,6 @@ bnad_cleanup_tx(struct bnad *bnad, u32 tx_id)
tx_info->tx = NULL;
tx_info->tx_id = 0;
- if (0 == tx_id)
- tasklet_kill(&bnad->tx_free_tasklet);
-
bnad_tx_res_free(bnad, res_info);
}
@@ -1918,6 +1918,16 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
rx_config->vlan_strip_status = BNA_STATUS_T_ENABLED;
}
+static void
+bnad_rx_ctrl_init(struct bnad *bnad, u32 rx_id)
+{
+ struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
+ int i;
+
+ for (i = 0; i < bnad->num_rxp_per_rx; i++)
+ rx_info->rx_ctrl[i].bnad = bnad;
+}
+
/* Called with mutex_lock(&bnad->conf_mutex) held */
void
bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
@@ -1941,8 +1951,6 @@ bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
del_timer_sync(&bnad->dim_timer);
}
- bnad_napi_disable(bnad, rx_id);
-
init_completion(&bnad->bnad_completions.rx_comp);
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_rx_disable(rx_info->rx, BNA_HARD_CLEANUP, bnad_cb_rx_disabled);
@@ -1952,6 +1960,8 @@ 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);
+
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_rx_destroy(rx_info->rx);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -2005,6 +2015,8 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
if (err)
return err;
+ bnad_rx_ctrl_init(bnad, rx_id);
+
/* Ask BNA to create one Rx object, supplying required resources */
spin_lock_irqsave(&bnad->bna_lock, flags);
rx = bna_rx_create(&bnad->bna, bnad, rx_config, &rx_cbfn, res_info,
@@ -2014,6 +2026,9 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
goto err_return;
rx_info->rx = rx;
+ /* Enable NAPI */
+ bnad_napi_enable(bnad, rx_id);
+
/* Register ISR for the Rx object */
if (intr_info->intr_type == BNA_INTR_T_MSIX) {
err = bnad_rx_msix_register(bnad, rx_info, rx_id,
@@ -2022,9 +2037,6 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
goto err_return;
}
- /* Enable NAPI */
- bnad_napi_enable(bnad, rx_id);
-
spin_lock_irqsave(&bnad->bna_lock, flags);
if (0 == rx_id) {
/* Set up Dynamic Interrupt Moderation Vector */
@@ -2602,15 +2614,15 @@ static netdev_tx_t
bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{
struct bnad *bnad = netdev_priv(netdev);
- u32 txq_id = 0;
- struct bna_tcb *tcb = bnad->tx_info[0].tcb[txq_id];
+ struct bna_tcb *tcb = NULL;
+ u32 txq_id;
+ struct bnad_unmap_q *unmap_q;
u16 txq_prod, vlan_tag = 0;
u32 unmap_prod, wis, wis_used, wi_range;
u32 vectors, vect_id, i, acked;
int err;
- struct bnad_unmap_q *unmap_q = tcb->unmap_q;
dma_addr_t dma_addr;
struct bna_txq_entry *txqent;
u16 flags;
@@ -2621,6 +2633,16 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}
+ txq_id = skb_get_queue_mapping(skb);
+
+ tcb = bnad->tx_info[0].tcb[txq_id];
+
+ if (unlikely(!tcb)) {
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ unmap_q = tcb->unmap_q;
/*
* Takes care of the Tx that is scheduled between clearing the flag
* and the netif_stop_all_queue() call.
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index 1b87b27..4f9da1c 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;
+ struct bnad *bnad;
unsigned long flags;
struct napi_struct napi;
};
--
1.7.1
^ permalink raw reply related
* [PATCH 0/4] More work towards neigh-less dsts.
From: David Miller @ 2011-07-18 8:24 UTC (permalink / raw)
To: netdev
This continues the effort to divorce neighbour from dst_entry as
much as possible.
When we remove the routing cache, route entries will be fully generic
and not specific to any particular keyed destination. Therefore we'll
need to lookup neigh entries dynamically, and quickly, at packet
output time.
To that end, this series:
1) Passes an explicit neighbour to packet out neigh_ops.
2) Abstracts all dst->neighbour behind helpers to ease the
transition process.
3) Adds a new dst_ops entry, ->neigh_lookup(), to provide a transition
scheme for dst->neighbour uses outside of the packet output path.
The next set of patches after this one will deal with all of
the dst_get_neighbour() code paths, converting them over to
dst_neigh_lookup()/neigh_release() sequences.
Then there will be a little bit of fiddling around in decnet since
it's usage of dst->neighbour is still too tight in the packet output
path.
Finally, we can kill dst->neighbour and do RCU neigh lookups in the
packet output paths for all the protocols using the neighbour cache
(ipv4, ipv6, decnet).
^ permalink raw reply
* [PATCH 36/45] bna: Data Path and API Changes
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- Data path change:
Accumulate the acks in the driver upto ~32K or 15 bits (+ 64, at the max),
if poosible and then ack, otherwise ack and enable interrupts when no more
packets are there to be processed.
- Currently, mailbox MSIX vector is part of bna resources. Due to this, the
MSIX vectors need to be allocated before bna_init(). Bfa_ioc_pci_init()
called from bna_ioceth_init() called from bna_init() has MSIX vector setup.
However, bfa_ioc_pci_init() needs to be called before enabling msix &
allocating MSIX vector. Due to this, bna_init() needs to be called before
enabling & allocating MSIX vectors. Hence, removing mailbox MSIX vector as
a resource requirement for bna. Mailbox MSIX vector need not be explicitly
passed for bna_init(), since mbox MSIX vector is always going to be 0.
- Bnad_mbox_irq_alloc/free() function changes - removal of bna_intr_info
- Bnad_res_alloc/free() function changes - removal of calling
bnad_mbox_irq_alloc/free()
- Calling bnad_enable_msix(), bnad_mbox_irq_alloc() after bna_init()
- Calling bnad_mbox_irq_free() just before bnad_disable_msix()
- IOC timer : use iocpf_timer to ioc_timer.
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_ioc.c | 46 +++++++++++-------
drivers/net/bna/bfi.h | 2 +-
drivers/net/bna/bnad.c | 115 +++++++++++++++++----------------------------
drivers/net/bna/bnad.h | 1 +
drivers/net/bna/cna.h | 4 +-
5 files changed, 75 insertions(+), 93 deletions(-)
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 940c94a..d35b91b 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -85,6 +85,7 @@ static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc);
static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type,
u32 boot_param);
static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr);
+static u32 bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr);
static void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc,
char *serial_num);
static void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc,
@@ -754,7 +755,7 @@ bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf *iocpf)
bfa_ioc_pf_fwmismatch(iocpf->ioc);
iocpf->fw_mismatch_notified = true;
- mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
+ mod_timer(&iocpf->ioc->ioc_timer, jiffies +
msecs_to_jiffies(BFA_IOC_TOV));
}
@@ -772,13 +773,13 @@ bfa_iocpf_sm_mismatch(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
case IOCPF_E_DISABLE:
- del_timer(&ioc->iocpf_timer);
+ del_timer(&ioc->ioc_timer);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
bfa_ioc_pf_disabled(ioc);
break;
case IOCPF_E_STOP:
- del_timer(&ioc->iocpf_timer);
+ del_timer(&ioc->ioc_timer);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
break;
@@ -859,7 +860,7 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
case IOCPF_E_DISABLE:
- del_timer(&ioc->iocpf_timer);
+ del_timer(&ioc->ioc_timer);
bfa_ioc_sync_leave(ioc);
bfa_nw_ioc_hw_sem_release(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
@@ -873,7 +874,7 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_enabling_entry(struct bfa_iocpf *iocpf)
{
- mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
+ mod_timer(&iocpf->ioc->ioc_timer, jiffies +
msecs_to_jiffies(BFA_IOC_TOV));
/**
* Enable Interrupts before sending fw IOC ENABLE cmd.
@@ -893,13 +894,13 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_FWRSP_ENABLE:
- del_timer(&ioc->iocpf_timer);
+ del_timer(&ioc->ioc_timer);
bfa_nw_ioc_hw_sem_release(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
break;
case IOCPF_E_INITFAIL:
- del_timer(&ioc->iocpf_timer);
+ del_timer(&ioc->ioc_timer);
/*
* !!! fall through !!!
*/
@@ -911,7 +912,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
case IOCPF_E_DISABLE:
- del_timer(&ioc->iocpf_timer);
+ del_timer(&ioc->ioc_timer);
bfa_nw_ioc_hw_sem_release(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
break;
@@ -951,7 +952,7 @@ bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_disabling_entry(struct bfa_iocpf *iocpf)
{
- mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
+ mod_timer(&iocpf->ioc->ioc_timer, jiffies +
msecs_to_jiffies(BFA_IOC_TOV));
bfa_ioc_send_disable(iocpf->ioc);
}
@@ -966,12 +967,12 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_FWRSP_DISABLE:
- del_timer(&ioc->iocpf_timer);
+ del_timer(&ioc->ioc_timer);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
break;
case IOCPF_E_FAIL:
- del_timer(&ioc->iocpf_timer);
+ del_timer(&ioc->ioc_timer);
/*
* !!! fall through !!!
*/
@@ -1245,13 +1246,13 @@ bfa_nw_ioc_sem_get(void __iomem *sem_reg)
r32 = readl(sem_reg);
- while (r32 && (cnt < BFA_SEM_SPINCNT)) {
+ while ((r32 & 1) && (cnt < BFA_SEM_SPINCNT)) {
cnt++;
udelay(2);
r32 = readl(sem_reg);
}
- if (r32 == 0)
+ if (!(r32 & 1))
return true;
BUG_ON(!(cnt < BFA_SEM_SPINCNT));
@@ -1396,12 +1397,13 @@ bfa_ioc_lpu_stop(struct bfa_ioc *ioc)
void
bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
{
- u32 pgnum;
+ u32 pgnum, pgoff;
u32 loff = 0;
int i;
u32 *fwsig = (u32 *) fwhdr;
pgnum = bfa_ioc_smem_pgnum(ioc, loff);
+ pgoff = bfa_ioc_smem_pgoff(ioc, loff);
writel(pgnum, ioc->ioc_regs.host_page_num_fn);
for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr) / sizeof(u32));
@@ -1479,11 +1481,12 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
- boot_env = BFI_FWBOOT_ENV_OS;
-
if (force)
ioc_fwstate = BFI_IOC_UNINIT;
+ boot_env = BFI_FWBOOT_ENV_OS;
+
+
/**
* check if firmware is valid
*/
@@ -1636,7 +1639,7 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
u32 boot_env)
{
u32 *fwimg;
- u32 pgnum;
+ u32 pgnum, pgoff;
u32 loff = 0;
u32 chunkno = 0;
u32 i;
@@ -1650,6 +1653,7 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
pgnum = bfa_ioc_smem_pgnum(ioc, loff);
+ pgoff = bfa_ioc_smem_pgoff(ioc, loff);
writel(pgnum, ioc->ioc_regs.host_page_num_fn);
@@ -1685,7 +1689,7 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
/*
* Set boot type, env and device mode at the end.
*/
- asicmode = BFI_FWBOOT_ASICMODE(ioc->asic_gen, ioc->asic_mode,
+ asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,
ioc->port0_mode, ioc->port1_mode);
writel(asicmode, ((ioc->ioc_regs.smem_page_start)
+ BFI_FWBOOT_DEVMODE_OFF));
@@ -2086,6 +2090,12 @@ bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr)
return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr);
}
+static u32
+bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr)
+{
+ return PSS_SMEM_PGOFF(fmaddr);
+}
+
/**
* Register mailbox message handler function, to be called by common modules
*/
diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h
index 8d238a7..d422857 100644
--- a/drivers/net/bna/bfi.h
+++ b/drivers/net/bna/bfi.h
@@ -307,7 +307,7 @@ struct bfi_ioc_image_hdr {
#define BFI_FWBOOT_DEVMODE_OFF 4
#define BFI_FWBOOT_TYPE_OFF 8
#define BFI_FWBOOT_ENV_OFF 12
-#define BFI_FWBOOT_ASICMODE(__asic_gen, __asic_mode, __p0_mode, __p1_mode) \
+#define BFI_FWBOOT_DEVMODE(__asic_gen, __asic_mode, __p0_mode, __p1_mode) \
(((u32)(__asic_gen)) << 24 | \
((u32)(__asic_mode)) << 16 | \
((u32)(__p0_mode)) << 8 | \
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 3f9ddbf..f6b7401 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -554,8 +554,8 @@ next:
BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
- if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
- bna_ib_ack(ccb->i_dbell, packets);
+ rx_ctrl->pkts_to_ack += packets;
+
bnad_refill_rxq(bnad, ccb->rcb[0]);
if (ccb->rcb[1])
bnad_refill_rxq(bnad, ccb->rcb[1]);
@@ -1056,6 +1056,8 @@ bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx)
if (!ccb)
continue;
+ rx_ctrl->pkts_to_ack += 0;
+
bnad_cq_cmpl_init(bnad, ccb);
for (j = 0; j < BNAD_MAX_RXQ_PER_RXP; j++) {
@@ -1195,23 +1197,17 @@ err_return:
/* Free IRQ for Mailbox */
static void
-bnad_mbox_irq_free(struct bnad *bnad,
- struct bna_intr_info *intr_info)
+bnad_mbox_irq_free(struct bnad *bnad)
{
int irq;
unsigned long flags;
- if (intr_info->idl == NULL)
- return;
-
spin_lock_irqsave(&bnad->bna_lock, flags);
bnad_disable_mbox_irq(bnad);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
irq = BNAD_GET_MBOX_IRQ(bnad);
free_irq(irq, bnad);
-
- kfree(intr_info->idl);
}
/*
@@ -1220,32 +1216,22 @@ bnad_mbox_irq_free(struct bnad *bnad,
* from bna
*/
static int
-bnad_mbox_irq_alloc(struct bnad *bnad,
- struct bna_intr_info *intr_info)
+bnad_mbox_irq_alloc(struct bnad *bnad)
{
int err = 0;
unsigned long irq_flags, flags;
u32 irq;
irq_handler_t irq_handler;
- /* Mbox should use only 1 vector */
-
- intr_info->idl = kzalloc(sizeof(*(intr_info->idl)), GFP_KERNEL);
- if (!intr_info->idl)
- return -ENOMEM;
-
spin_lock_irqsave(&bnad->bna_lock, flags);
if (bnad->cfg_flags & BNAD_CF_MSIX) {
irq_handler = (irq_handler_t)bnad_msix_mbox_handler;
irq = bnad->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector;
irq_flags = 0;
- intr_info->intr_type = BNA_INTR_T_MSIX;
- intr_info->idl[0].vector = BNAD_MAILBOX_MSIX_INDEX;
} else {
irq_handler = (irq_handler_t)bnad_isr;
irq = bnad->pcidev->irq;
irq_flags = IRQF_SHARED;
- intr_info->intr_type = BNA_INTR_T_INTX;
}
spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -1262,11 +1248,6 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
err = request_irq(irq, irq_handler, irq_flags,
bnad->mbox_irq_name, bnad);
- if (err) {
- kfree(intr_info->idl);
- intr_info->idl = NULL;
- }
-
return err;
}
@@ -1723,6 +1704,21 @@ poll_exit:
return rcvd;
}
+#define BNAD_NAPI_POLL_QUOTA 64
+static void
+bnad_napi_init(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];
+ netif_napi_add(bnad->netdev, &rx_ctrl->napi,
+ bnad_napi_poll_rx, BNAD_NAPI_POLL_QUOTA);
+ }
+}
+
static void
bnad_napi_enable(struct bnad *bnad, u32 rx_id)
{
@@ -1786,29 +1782,6 @@ bnad_cleanup_tx(struct bnad *bnad, u32 tx_id)
bnad_tx_res_free(bnad, res_info);
}
-/*
- * Sets up bnad->num_tx depending on the current value (already
- * adjusted based on MSIX vectors available and ETS support in
- * the chip
- */
-static void
-bnad_num_txq_set(struct bnad *bnad)
-{
- struct bna *bna = &bnad->bna;
- struct bna_attr attr;
- unsigned long flags;
-
- spin_lock_irqsave(&bnad->bna_lock, flags);
- attr = bna->ioceth.attr;
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
- if (attr.max_ets_groups < BFI_TX_MAX_PRIO)
- bnad->num_txq_per_tx = 1;
- else
- bnad->num_txq_per_tx = min((u32)attr.max_ets_groups,
- (u32)bnad->num_txq_per_tx);
-}
-
/* Should be held with conf_lock held */
int
bnad_setup_tx(struct bnad *bnad, u32 tx_id)
@@ -1825,8 +1798,6 @@ bnad_setup_tx(struct bnad *bnad, u32 tx_id)
tx_info->tx_id = tx_id;
- bnad_num_txq_set(bnad);
-
/* Initialize the Tx object configuration */
tx_config->num_txq = bnad->num_txq_per_tx;
tx_config->txq_depth = bnad->txq_depth;
@@ -2026,8 +1997,11 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
goto err_return;
rx_info->rx = rx;
- /* Enable NAPI */
- bnad_napi_enable(bnad, rx_id);
+ /*
+ * 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);
/* Register ISR for the Rx object */
if (intr_info->intr_type == BNA_INTR_T_MSIX) {
@@ -2053,6 +2027,9 @@ 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:
@@ -2397,12 +2374,8 @@ bnad_res_free(struct bnad *bnad, struct bna_res_info *res_info,
{
int i;
- for (i = 0; i < res_val_max; i++) {
- if (res_info[i].res_type == BNA_RES_T_MEM)
- bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
- else
- bnad_mbox_irq_free(bnad, &res_info[i].res_u.intr_info);
- }
+ for (i = 0; i < res_val_max; i++)
+ bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
}
/* Allocates memory and interrupt resources for BNA */
@@ -2413,11 +2386,7 @@ bnad_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
int i, err;
for (i = 0; i < res_val_max; i++) {
- if (res_info[i].res_type == BNA_RES_T_MEM)
- err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info);
- else
- err = bnad_mbox_irq_alloc(bnad,
- &res_info[i].res_u.intr_info);
+ err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info);
if (err)
goto err_return;
}
@@ -2637,11 +2606,6 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
tcb = bnad->tx_info[0].tcb[txq_id];
- if (unlikely(!tcb)) {
- dev_kfree_skb(skb);
- return NETDEV_TX_OK;
- }
-
unmap_q = tcb->unmap_q;
/*
* Takes care of the Tx that is scheduled between clearing the flag
@@ -3351,8 +3315,6 @@ bnad_pci_probe(struct pci_dev *pdev,
/* Set link to down state */
netif_carrier_off(netdev);
- bnad_enable_msix(bnad);
-
/* Get resource requirement form bna */
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_res_req(&bnad->res_info[0]);
@@ -3377,6 +3339,12 @@ bnad_pci_probe(struct pci_dev *pdev,
bnad->stats.bna_stats = &bna->stats;
+ bnad_enable_msix(bnad);
+ err = bnad_mbox_irq_alloc(bnad);
+ if (err)
+ goto res_free;
+
+
/* Set up timers */
setup_timer(&bnad->bna.ioceth.ioc.ioc_timer, bnad_ioc_timeout,
((unsigned long)bnad));
@@ -3388,7 +3356,7 @@ bnad_pci_probe(struct pci_dev *pdev,
((unsigned long)bnad));
/* Now start the timer before calling IOC */
- mod_timer(&bnad->bna.ioceth.ioc.iocpf_timer,
+ mod_timer(&bnad->bna.ioceth.ioc.ioc_timer,
jiffies + msecs_to_jiffies(BNA_IOC_TIMER_FREQ));
/*
@@ -3455,9 +3423,11 @@ disable_ioceth:
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_uninit(bna);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ bnad_mbox_irq_free(bnad);
+ bnad_disable_msix(bnad);
+res_free:
bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
drv_uninit:
- bnad_disable_msix(bnad);
bnad_uninit(bnad);
pci_uninit:
bnad_pci_uninit(pdev);
@@ -3497,6 +3467,7 @@ bnad_pci_remove(struct pci_dev *pdev)
bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
+ bnad_mbox_irq_free(bnad);
bnad_disable_msix(bnad);
bnad_pci_uninit(pdev);
mutex_unlock(&bnad->conf_mutex);
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index 4f9da1c..7f0648d 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -54,6 +54,7 @@ struct bnad_rx_ctrl {
struct bnad *bnad;
unsigned long flags;
struct napi_struct napi;
+ u16 pkts_to_ack;
};
#define BNAD_RXMODE_PROMISC_DEFAULT BNA_RXMODE_PROMISC
diff --git a/drivers/net/bna/cna.h b/drivers/net/bna/cna.h
index 50fce15..94005d6 100644
--- a/drivers/net/bna/cna.h
+++ b/drivers/net/bna/cna.h
@@ -34,8 +34,8 @@
#include <linux/list.h>
#define bfa_sm_fault(__event) do { \
- pr_err("SM Assertion failure: %s: %d: event = %d", __FILE__, __LINE__, \
- __event); \
+ pr_err("SM Assertion failure: %s: %d: event = %d\n", \
+ __FILE__, __LINE__, __event); \
} while (0)
extern char bfa_version[];
--
1.7.1
^ permalink raw reply related
* [PATCH 1/4] neigh: Pass neighbour entry to output ops.
From: David Miller @ 2011-07-18 8:25 UTC (permalink / raw)
To: netdev
This will get us closer to being able to do "neigh stuff"
completely independent of the underlying dst_entry for
protocols (ipv4/ipv6) that wish to do so.
We will also be able to make dst entries neigh-less.
Signed-off-by: David S. Miller <davem@davemloft.net>
---
include/net/neighbour.h | 19 ++++++++++---------
net/atm/clip.c | 4 ++--
net/bridge/br_netfilter.c | 4 ++--
net/core/neighbour.c | 25 ++++++++++++++-----------
net/decnet/dn_neigh.c | 18 ++++++------------
net/decnet/dn_route.c | 13 ++++++++++---
net/ipv4/arp.c | 6 +++---
net/ipv6/ndisc.c | 6 +++---
8 files changed, 50 insertions(+), 45 deletions(-)
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 334e92f..4ba8521 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -109,7 +109,7 @@ struct neighbour {
seqlock_t ha_lock;
unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
struct hh_cache hh;
- int (*output)(struct sk_buff *skb);
+ int (*output)(struct neighbour *, struct sk_buff *);
const struct neigh_ops *ops;
struct rcu_head rcu;
struct net_device *dev;
@@ -118,10 +118,10 @@ struct neighbour {
struct neigh_ops {
int family;
- void (*solicit)(struct neighbour *, struct sk_buff*);
- void (*error_report)(struct neighbour *, struct sk_buff*);
- int (*output)(struct sk_buff*);
- int (*connected_output)(struct sk_buff*);
+ void (*solicit)(struct neighbour *, struct sk_buff *);
+ void (*error_report)(struct neighbour *, struct sk_buff *);
+ int (*output)(struct neighbour *, struct sk_buff *);
+ int (*connected_output)(struct neighbour *, struct sk_buff *);
};
struct pneigh_entry {
@@ -203,9 +203,10 @@ extern int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
u32 flags);
extern void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
extern int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
-extern int neigh_resolve_output(struct sk_buff *skb);
-extern int neigh_connected_output(struct sk_buff *skb);
-extern int neigh_compat_output(struct sk_buff *skb);
+extern int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb);
+extern int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb);
+extern int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb);
+extern int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb);
extern struct neighbour *neigh_event_ns(struct neigh_table *tbl,
u8 *lladdr, void *saddr,
struct net_device *dev);
@@ -348,7 +349,7 @@ static inline int neigh_output(struct neighbour *n, struct sk_buff *skb)
if ((n->nud_state & NUD_CONNECTED) && hh->hh_len)
return neigh_hh_output(hh, skb);
else
- return n->output(skb);
+ return n->output(n, skb);
}
static inline struct neighbour *
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 40d7368..c6cd531 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -271,8 +271,8 @@ static const struct neigh_ops clip_neigh_ops = {
.family = AF_INET,
.solicit = clip_neigh_solicit,
.error_report = clip_neigh_error,
- .output = dev_queue_xmit,
- .connected_output = dev_queue_xmit,
+ .output = neigh_direct_output,
+ .connected_output = neigh_direct_output,
};
static int clip_constructor(struct neighbour *neigh)
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 75ee421..1fe43fd 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -355,14 +355,14 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
neigh_hh_bridge(&neigh->hh, skb);
skb->dev = nf_bridge->physindev;
return br_handle_frame_finish(skb);
- } else if (dst->neighbour) {
+ } else {
/* the neighbour function below overwrites the complete
* MAC header, so we save the Ethernet source address and
* protocol number. */
skb_copy_from_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), skb->nf_bridge->data, ETH_HLEN-ETH_ALEN);
/* tell br_dev_xmit to continue with forwarding */
nf_bridge->mask |= BRNF_BRIDGED_DNAT;
- return dst->neighbour->output(skb);
+ return neigh->output(neigh, skb);
}
free_skb:
kfree_skb(skb);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index b031cf6..cefb8e5 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -98,7 +98,7 @@ static const struct file_operations neigh_stat_seq_fops;
static DEFINE_RWLOCK(neigh_tbl_lock);
-static int neigh_blackhole(struct sk_buff *skb)
+static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
{
kfree_skb(skb);
return -ENETDOWN;
@@ -1158,7 +1158,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
/* On shaper/eql skb->dst->neighbour != neigh :( */
if (skb_dst(skb) && skb_dst(skb)->neighbour)
n1 = skb_dst(skb)->neighbour;
- n1->output(skb);
+ n1->output(n1, skb);
write_lock_bh(&neigh->lock);
}
skb_queue_purge(&neigh->arp_queue);
@@ -1214,7 +1214,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
* but resolution is not made yet.
*/
-int neigh_compat_output(struct sk_buff *skb)
+int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
@@ -1231,13 +1231,12 @@ EXPORT_SYMBOL(neigh_compat_output);
/* Slow and careful. */
-int neigh_resolve_output(struct sk_buff *skb)
+int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
- struct neighbour *neigh;
int rc = 0;
- if (!dst || !(neigh = dst->neighbour))
+ if (!dst)
goto discard;
__skb_pull(skb, skb_network_offset(skb));
@@ -1265,7 +1264,7 @@ out:
return rc;
discard:
NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n",
- dst, dst ? dst->neighbour : NULL);
+ dst, neigh);
out_kfree_skb:
rc = -EINVAL;
kfree_skb(skb);
@@ -1275,13 +1274,11 @@ EXPORT_SYMBOL(neigh_resolve_output);
/* As fast as possible without hh cache */
-int neigh_connected_output(struct sk_buff *skb)
+int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
{
- int err;
- struct dst_entry *dst = skb_dst(skb);
- struct neighbour *neigh = dst->neighbour;
struct net_device *dev = neigh->dev;
unsigned int seq;
+ int err;
__skb_pull(skb, skb_network_offset(skb));
@@ -1301,6 +1298,12 @@ int neigh_connected_output(struct sk_buff *skb)
}
EXPORT_SYMBOL(neigh_connected_output);
+int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
+{
+ return dev_queue_xmit(skb);
+}
+EXPORT_SYMBOL(neigh_direct_output);
+
static void neigh_proxy_process(unsigned long arg)
{
struct neigh_table *tbl = (struct neigh_table *)arg;
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 84fee8a..5d61e89 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -51,9 +51,9 @@
static int dn_neigh_construct(struct neighbour *);
static void dn_long_error_report(struct neighbour *, struct sk_buff *);
static void dn_short_error_report(struct neighbour *, struct sk_buff *);
-static int dn_long_output(struct sk_buff *);
-static int dn_short_output(struct sk_buff *);
-static int dn_phase3_output(struct sk_buff *);
+static int dn_long_output(struct neighbour *, struct sk_buff *);
+static int dn_short_output(struct neighbour *, struct sk_buff *);
+static int dn_phase3_output(struct neighbour *, struct sk_buff *);
/*
@@ -218,10 +218,8 @@ static int dn_neigh_output_packet(struct sk_buff *skb)
return -EINVAL;
}
-static int dn_long_output(struct sk_buff *skb)
+static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb)
{
- struct dst_entry *dst = skb_dst(skb);
- struct neighbour *neigh = dst->neighbour;
struct net_device *dev = neigh->dev;
int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3;
unsigned char *data;
@@ -265,10 +263,8 @@ static int dn_long_output(struct sk_buff *skb)
neigh->dev, dn_neigh_output_packet);
}
-static int dn_short_output(struct sk_buff *skb)
+static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb)
{
- struct dst_entry *dst = skb_dst(skb);
- struct neighbour *neigh = dst->neighbour;
struct net_device *dev = neigh->dev;
int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
struct dn_short_packet *sp;
@@ -309,10 +305,8 @@ static int dn_short_output(struct sk_buff *skb)
* Phase 3 output is the same is short output, execpt that
* it clears the area bits before transmission.
*/
-static int dn_phase3_output(struct sk_buff *skb)
+static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb)
{
- struct dst_entry *dst = skb_dst(skb);
- struct neighbour *neigh = dst->neighbour;
struct net_device *dev = neigh->dev;
int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
struct dn_short_packet *sp;
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index fceb86c..3b6400d 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -705,6 +705,14 @@ out:
return NET_RX_DROP;
}
+static int dn_to_neigh_output(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb_dst(skb);
+ struct neighbour *n = dst->neighbour;
+
+ return n->output(n, skb);
+}
+
static int dn_output(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
@@ -733,7 +741,7 @@ static int dn_output(struct sk_buff *skb)
cb->hops = 0;
return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_OUT, skb, NULL, dev,
- neigh->output);
+ dn_to_neigh_output);
error:
if (net_ratelimit())
@@ -750,7 +758,6 @@ static int dn_forward(struct sk_buff *skb)
struct dst_entry *dst = skb_dst(skb);
struct dn_dev *dn_db = rcu_dereference(dst->dev->dn_ptr);
struct dn_route *rt;
- struct neighbour *neigh = dst->neighbour;
int header_len;
#ifdef CONFIG_NETFILTER
struct net_device *dev = skb->dev;
@@ -783,7 +790,7 @@ static int dn_forward(struct sk_buff *skb)
cb->rt_flags |= DN_RT_F_IE;
return NF_HOOK(NFPROTO_DECNET, NF_DN_FORWARD, skb, dev, skb->dev,
- neigh->output);
+ dn_to_neigh_output);
drop:
kfree_skb(skb);
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 8a21403..96a164a 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -150,8 +150,8 @@ static const struct neigh_ops arp_hh_ops = {
static const struct neigh_ops arp_direct_ops = {
.family = AF_INET,
- .output = dev_queue_xmit,
- .connected_output = dev_queue_xmit,
+ .output = neigh_direct_output,
+ .connected_output = neigh_direct_output,
};
static const struct neigh_ops arp_broken_ops = {
@@ -250,7 +250,7 @@ static int arp_constructor(struct neighbour *neigh)
if (!dev->header_ops) {
neigh->nud_state = NUD_NOARP;
neigh->ops = &arp_direct_ops;
- neigh->output = dev_queue_xmit;
+ neigh->output = neigh_direct_output;
} else {
/* Good devices (checked by reading texts, but only Ethernet is
tested)
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 482b970..e08ce55 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -120,8 +120,8 @@ static const struct neigh_ops ndisc_hh_ops = {
static const struct neigh_ops ndisc_direct_ops = {
.family = AF_INET6,
- .output = dev_queue_xmit,
- .connected_output = dev_queue_xmit,
+ .output = neigh_direct_output,
+ .connected_output = neigh_direct_output,
};
struct neigh_table nd_tbl = {
@@ -386,7 +386,7 @@ static int ndisc_constructor(struct neighbour *neigh)
if (!dev->header_ops) {
neigh->nud_state = NUD_NOARP;
neigh->ops = &ndisc_direct_ops;
- neigh->output = dev_queue_xmit;
+ neigh->output = neigh_direct_output;
} else {
if (is_multicast) {
neigh->nud_state = NUD_NOARP;
--
1.7.6
^ permalink raw reply related
* [PATCH 37/45] bna: Adpater and Port Mode Settings
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- Cache the port mode (active and configured) and capability info in
bfa_ioc_attr eliminating need to go to fw. This info will be initialize
to their default value during pci init time, and will be update during
ioc enable reply time and port mode change reply time.
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_defs.h | 25 +++++++++++++++++++++++--
drivers/net/bna/bfa_ioc.c | 35 ++++++++++++++++++++++++++++++++++-
drivers/net/bna/bfa_ioc.h | 3 +++
drivers/net/bna/bfi.h | 6 ++++--
4 files changed, 64 insertions(+), 5 deletions(-)
diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index 3e5d096..ebe5e6c 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -180,8 +180,23 @@ struct bfa_ioc_attr {
struct bfa_adapter_attr adapter_attr; /*!< HBA attributes */
struct bfa_ioc_driver_attr driver_attr; /*!< driver attr */
struct bfa_ioc_pci_attr pci_attr;
- u8 port_id; /*!< port number */
- u8 rsvd[7]; /*!< 64bit align */
+ u8 port_id; /*!< port number */
+ u8 port_mode; /*!< enum bfa_mode */
+ u8 cap_bm; /*!< capability */
+ u8 port_mode_cfg; /*!< enum bfa_mode */
+ u8 rsvd[4]; /*!< 64bit align */
+};
+
+/**
+ * Adapter capability mask definition
+ */
+enum {
+ BFA_CM_HBA = 0x01,
+ BFA_CM_CNA = 0x02,
+ BFA_CM_NIC = 0x04,
+ BFA_CM_FC16G = 0x08,
+ BFA_CM_SRIOV = 0x10,
+ BFA_CM_MEZZ = 0x20,
};
/**
@@ -271,4 +286,10 @@ enum {
BFA_PCI_CT2_SSID_FC = 0x24,
};
+enum bfa_mode {
+ BFA_MODE_HBA = 1,
+ BFA_MODE_CNA = 2,
+ BFA_MODE_NIC = 3
+};
+
#endif /* __BFA_DEFS_H__ */
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index d35b91b..6e17abd 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -1706,6 +1706,20 @@ bfa_ioc_reset(struct bfa_ioc *ioc, bool force)
}
/**
+ * BFA ioc enable reply by firmware
+ */
+static void
+bfa_ioc_enable_reply(struct bfa_ioc *ioc, enum bfa_mode port_mode,
+ u8 cap_bm)
+{
+ struct bfa_iocpf *iocpf = &ioc->iocpf;
+
+ ioc->port_mode = ioc->port_mode_cfg = port_mode;
+ ioc->ad_cap_bm = cap_bm;
+ bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
+}
+
+/**
* @brief
* Update BFA configuration from firmware configuration.
*/
@@ -1937,7 +1951,9 @@ bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
break;
case BFI_IOC_I2H_ENABLE_REPLY:
- bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
+ bfa_ioc_enable_reply(ioc,
+ (enum bfa_mode)msg->fw_event.port_mode,
+ (enum bfa_mode)msg->fw_event.cap_bm);
break;
case BFI_IOC_I2H_DISABLE_REPLY:
@@ -2012,6 +2028,8 @@ bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
ioc->asic_gen = BFI_ASIC_GEN_CT;
ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
ioc->asic_mode = BFI_ASIC_MODE_ETH;
+ ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_CNA;
+ ioc->ad_cap_bm = BFA_CM_CNA;
break;
case BFA_PCI_DEVICE_ID_CT2:
@@ -2020,9 +2038,20 @@ bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
pcidev->ssid == BFA_PCI_CT2_SSID_FC) {
ioc->asic_mode = BFI_ASIC_MODE_FC16;
ioc->fcmode = true;
+ ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
+ ioc->ad_cap_bm = BFA_CM_HBA;
} else {
ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
ioc->asic_mode = BFI_ASIC_MODE_ETH;
+ if (pcidev->ssid == BFA_PCI_CT2_SSID_FCoE) {
+ ioc->port_mode =
+ ioc->port_mode_cfg = BFA_MODE_CNA;
+ ioc->ad_cap_bm = BFA_CM_CNA;
+ } else {
+ ioc->port_mode =
+ ioc->port_mode_cfg = BFA_MODE_NIC;
+ ioc->ad_cap_bm = BFA_CM_NIC;
+ }
}
break;
@@ -2382,6 +2411,10 @@ bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr)
ioc_attr->state = bfa_ioc_get_state(ioc);
ioc_attr->port_id = ioc->port_id;
+ ioc_attr->port_mode = ioc->port_mode;
+
+ ioc_attr->port_mode_cfg = ioc->port_mode_cfg;
+ ioc_attr->cap_bm = ioc->ad_cap_bm;
ioc_attr->ioc_type = bfa_nw_ioc_get_type(ioc);
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index 0f7dba1..9ae201a 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -208,6 +208,9 @@ struct bfa_ioc {
enum bfi_asic_mode asic_mode;
enum bfi_port_mode port0_mode;
enum bfi_port_mode port1_mode;
+ enum bfa_mode port_mode;
+ u8 ad_cap_bm; /*!< adapter cap bit mask */
+ u8 port_mode_cfg; /*!< config port mode */
};
struct bfa_ioc_hwif {
diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h
index d422857..c534318 100644
--- a/drivers/net/bna/bfi.h
+++ b/drivers/net/bna/bfi.h
@@ -398,9 +398,11 @@ struct bfi_ioc_ctrl_req {
* BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
*/
struct bfi_ioc_ctrl_reply {
- struct bfi_mhdr mh; /*!< Common msg header */
+ struct bfi_mhdr mh; /*!< Common msg header */
u8 status; /*!< enable/disable status */
- u8 rsvd[3];
+ u8 port_mode; /*!< bfa_mode */
+ u8 cap_bm; /*!< capability bit mask */
+ u8 rsvd;
};
#define BFI_IOC_MSGSZ 8
--
1.7.1
^ permalink raw reply related
* [PATCH 38/45] bna: HW Error Counter Fix
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- Heartbeat failure counter is not incrementing under some scenarios.
Update hbfails and hb_count stats during hwerror event.
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_defs.h | 1 +
drivers/net/bna/bfa_ioc.c | 3 +++
drivers/net/bna/bfa_ioc.h | 2 ++
3 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index ebe5e6c..9fe2623 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -155,6 +155,7 @@ struct bfa_ioc_drv_stats {
u32 enable_reqs;
u32 disable_replies;
u32 enable_replies;
+ u32 rsvd;
};
/**
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 6e17abd..e612ca4 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -2217,6 +2217,8 @@ bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc)
void
bfa_nw_ioc_error_isr(struct bfa_ioc *ioc)
{
+ bfa_ioc_stats(ioc, ioc_hbfails);
+ bfa_ioc_stats_hb_count(ioc, ioc->hb_count);
bfa_fsm_send_event(ioc, IOC_E_HWERROR);
}
@@ -2448,6 +2450,7 @@ bfa_ioc_recover(struct bfa_ioc *ioc)
{
pr_crit("Heart Beat of IOC has failed\n");
bfa_ioc_stats(ioc, ioc_hbfails);
+ bfa_ioc_stats_hb_count(ioc, ioc->hb_count);
bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
}
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index 9ae201a..5b6cbbe 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -252,6 +252,8 @@ struct bfa_ioc_hwif {
BFI_ADAPTER_GETP(NPORTS, (__ioc)->attr->adapter_prop)
#define bfa_ioc_stats(_ioc, _stats) ((_ioc)->stats._stats++)
+#define bfa_ioc_stats_hb_count(_ioc, _hb_count) \
+ ((_ioc)->stats.hb_count = (_hb_count))
#define BFA_IOC_FWIMG_MINSZ (16 * 1024)
#define BFA_IOC_FW_SMEM_SIZE(__ioc) \
((bfa_ioc_asic_gen(__ioc) == BFI_ASIC_GEN_CB) \
--
1.7.1
^ permalink raw reply related
* [PATCH 39/45] bna: RX Path Changes
From: Rasesh Mody @ 2011-07-18 8:22 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- Disable and enable interrupts from the same polling context to prevent
reordering in Rx path.
- Set coalescing timer to 0 within bnad_poll_cq().
- Move preempt_disable()/preempt_enable() calls from bnad_poll_cq() to
bnad_napi_poll_rx() and bnad_poll().
- Add Rx NAPI debug counters.
- Add macros to drop skb and return, to unmap skb. Check and drop illegal
skbs in transmit path.
- Check for single frame TSO skbs and send them out as non-TSO.
- Put memory barrier after bna_txq_prod_indx_doorbell()
- Add tx_skb sounters for dropped frames in transmit path.
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bnad.c | 325 ++++++++++++++++++++++++------------------------
drivers/net/bna/bnad.h | 36 +++++-
2 files changed, 199 insertions(+), 162 deletions(-)
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index f6b7401..d4de429 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -73,6 +73,36 @@ do { \
#define BNAD_TXRX_SYNC_MDELAY 250 /* 250 msecs */
+#define BNAD_DROP_AND_RETURN(_counter) \
+{ \
+ dev_kfree_skb(skb); \
+ BNAD_UPDATE_CTR(bnad, _counter); \
+ return NETDEV_TX_OK; \
+}
+
+#define BNAD_DROP_AND_RETURN_IF(_condition, _counter) \
+if (unlikely(_condition)) { \
+ BNAD_DROP_AND_RETURN(_counter); \
+}
+
+#define BNAD_PCI_UNMAP_SKB(_pdev, _array, _index, _depth, _skb, _frag) \
+{ \
+ int j; \
+ (_array)[_index].skb = NULL; \
+ dma_unmap_single(_pdev, dma_unmap_addr(&(_array)[_index], dma_addr), \
+ skb_headlen(_skb), DMA_TO_DEVICE); \
+ dma_unmap_addr_set(&(_array)[_index], dma_addr, 0); \
+ BNA_QE_INDX_ADD(_index, 1, _depth); \
+ for (j = 0; j < (_frag); j++) { \
+ prefetch(&(_array)[(_index) + 1]); \
+ dma_unmap_page(_pdev, dma_unmap_addr(&(_array)[_index], \
+ dma_addr), \
+ skb_shinfo(_skb)->frags[j].size, DMA_TO_DEVICE); \
+ dma_unmap_addr_set(&(_array)[_index], dma_addr, 0); \
+ BNA_QE_INDX_ADD(_index, 1, _depth); \
+ } \
+}
+
/*
* Reinitialize completions in CQ, once Rx is taken down
*/
@@ -168,7 +198,6 @@ bnad_free_txbufs(struct bnad *bnad,
struct bnad_unmap_q *unmap_q = tcb->unmap_q;
struct bnad_skb_unmap *unmap_array;
struct sk_buff *skb;
- int i;
/*
* Just return if TX is stopped. This check is useful
@@ -198,26 +227,10 @@ bnad_free_txbufs(struct bnad *bnad,
sent_bytes += skb->len;
wis -= BNA_TXQ_WI_NEEDED(1 + skb_shinfo(skb)->nr_frags);
- dma_unmap_single(&bnad->pcidev->dev,
- dma_unmap_addr(&unmap_array[unmap_cons],
- dma_addr), skb_headlen(skb),
- DMA_TO_DEVICE);
- dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
- BNA_QE_INDX_ADD(unmap_cons, 1, unmap_q->q_depth);
+ BNAD_PCI_UNMAP_SKB(&bnad->pcidev->dev, unmap_array, unmap_cons,
+ unmap_q->q_depth, skb,
+ skb_shinfo(skb)->nr_frags);
- prefetch(&unmap_array[unmap_cons + 1]);
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- prefetch(&unmap_array[unmap_cons + 1]);
-
- dma_unmap_page(&bnad->pcidev->dev,
- dma_unmap_addr(&unmap_array[unmap_cons],
- dma_addr),
- skb_shinfo(skb)->frags[i].size,
- DMA_TO_DEVICE);
- dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
- 0);
- BNA_QE_INDX_ADD(unmap_cons, 1, unmap_q->q_depth);
- }
dev_kfree_skb_any(skb);
}
@@ -388,10 +401,9 @@ bnad_alloc_n_post_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent, wi_range);
while (to_alloc--) {
- if (!wi_range) {
+ if (!wi_range)
BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent,
wi_range);
- }
skb = netdev_alloc_skb_ip_align(bnad->netdev,
rcb->rxq->buffer_size);
if (unlikely(!skb)) {
@@ -449,13 +461,10 @@ 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);
- preempt_disable();
-
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);
- preempt_enable();
return 0;
}
@@ -521,15 +530,13 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
(flags & BNA_CQ_EF_L4_CKSUM_OK)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
- skb_checksum_none_assert(skb);
+ skb->ip_summed = CHECKSUM_NONE;
rcb->rxq->rx_packets++;
rcb->rxq->rx_bytes += skb->len;
skb->protocol = eth_type_trans(skb, bnad->netdev);
if (bnad->vlan_grp && (flags & BNA_CQ_EF_VLAN)) {
- struct bnad_rx_ctrl *rx_ctrl =
- (struct bnad_rx_ctrl *)ccb->ctrl;
if (skb->ip_summed == CHECKSUM_UNNECESSARY)
vlan_gro_receive(&rx_ctrl->napi, bnad->vlan_grp,
ntohs(cmpl->vlan_tag), skb);
@@ -539,8 +546,6 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
ntohs(cmpl->vlan_tag));
} else { /* Not VLAN tagged/stripped */
- struct bnad_rx_ctrl *rx_ctrl =
- (struct bnad_rx_ctrl *)ccb->ctrl;
if (skb->ip_summed == CHECKSUM_UNNECESSARY)
napi_gro_receive(&rx_ctrl->napi, skb);
else
@@ -554,7 +559,8 @@ next:
BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
- rx_ctrl->pkts_to_ack += packets;
+ if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
+ bna_ib_ack_disable_irq(ccb->i_dbell, packets);
bnad_refill_rxq(bnad, ccb->rcb[0]);
if (ccb->rcb[1])
@@ -562,43 +568,19 @@ next:
clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
- preempt_enable();
-
return packets;
}
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);
-}
-
-static void
-bnad_enable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
-{
- unsigned long flags;
-
- /* Because of polling context */
- spin_lock_irqsave(&bnad->bna_lock, flags);
- bnad_enable_rx_irq_unsafe(ccb);
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
-}
-
-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);
struct napi_struct *napi = &rx_ctrl->napi;
if (likely(napi_schedule_prep(napi))) {
- bnad_disable_rx_irq(bnad, ccb);
__napi_schedule(napi);
+ rx_ctrl->rx_schedule++;
}
- BNAD_UPDATE_CTR(bnad, netif_rx_schedule);
}
/* MSIX Rx Path Handler */
@@ -606,10 +588,11 @@ static irqreturn_t
bnad_msix_rx(int irq, void *data)
{
struct bna_ccb *ccb = (struct bna_ccb *)data;
- struct bnad *bnad = ccb->bnad;
- if (ccb)
- bnad_netif_rx_schedule_poll(bnad, ccb);
+ if (ccb) {
+ ((struct bnad_rx_ctrl *)(ccb->ctrl))->rx_intr_ctr++;
+ bnad_netif_rx_schedule_poll(ccb->bnad, ccb);
+ }
return IRQ_HANDLED;
}
@@ -1056,8 +1039,6 @@ bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx)
if (!ccb)
continue;
- rx_ctrl->pkts_to_ack += 0;
-
bnad_cq_cmpl_init(bnad, ccb);
for (j = 0; j < BNAD_MAX_RXQ_PER_RXP; j++) {
@@ -1680,27 +1661,30 @@ bnad_napi_poll_rx(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;
+ struct bnad *bnad = rx_ctrl->bnad;
int rcvd = 0;
+ preempt_disable();
- ccb = rx_ctrl->ccb;
-
- bnad = ccb->bnad;
+ rx_ctrl->rx_poll_ctr++;
if (!netif_carrier_ok(bnad->netdev))
goto poll_exit;
- rcvd = bnad_poll_cq(bnad, ccb, budget);
- if (rcvd == budget)
+ rcvd = bnad_poll_cq(bnad, rx_ctrl->ccb, budget);
+ if (rcvd >= budget) {
+ preempt_enable();
return rcvd;
-
+ }
poll_exit:
- napi_complete((napi));
+ napi_complete(napi);
+
+ rx_ctrl->rx_complete++;
- BNAD_UPDATE_CTR(bnad, netif_rx_complete);
+ preempt_enable();
+
+ if (rx_ctrl->ccb)
+ bnad_enable_rx_irq_unsafe(rx_ctrl->ccb);
- bnad_enable_rx_irq(bnad, ccb);
return rcvd;
}
@@ -1729,9 +1713,6 @@ bnad_napi_enable(struct bnad *bnad, u32 rx_id)
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,
- bnad_napi_poll_rx, 64);
-
napi_enable(&rx_ctrl->napi);
}
}
@@ -1907,20 +1888,14 @@ bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
struct bna_res_info *res_info = &bnad->rx_res_info[rx_id].res_info[0];
unsigned long flags;
- int dim_timer_del = 0;
if (!rx_info->rx)
return;
- if (0 == rx_id) {
- spin_lock_irqsave(&bnad->bna_lock, flags);
- dim_timer_del = bnad_dim_timer_running(bnad);
- if (dim_timer_del)
- clear_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags);
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
- if (dim_timer_del)
- del_timer_sync(&bnad->dim_timer);
- }
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (0 == rx_id)
+ bnad_dim_timer_stop(bnad, flags);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
init_completion(&bnad->bnad_completions.rx_comp);
spin_lock_irqsave(&bnad->bna_lock, flags);
@@ -2429,12 +2404,11 @@ bnad_enable_msix(struct bnad *bnad)
spin_lock_irqsave(&bnad->bna_lock, flags);
/* ret = #of vectors that we got */
- bnad_q_num_adjust(bnad, ret, 0);
+ bnad_q_num_adjust(bnad, (ret - BNAD_MAILBOX_MSIX_VECTORS) / 2,
+ (ret - BNAD_MAILBOX_MSIX_VECTORS) / 2);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx)
- + (bnad->num_rx
- * bnad->num_rxp_per_rx) +
+ bnad->msix_num = BNAD_NUM_TXQ + BNAD_NUM_RXP +
BNAD_MAILBOX_MSIX_VECTORS;
if (bnad->msix_num > ret)
@@ -2591,16 +2565,16 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
u32 unmap_prod, wis, wis_used, wi_range;
u32 vectors, vect_id, i, acked;
int err;
+ unsigned int len;
dma_addr_t dma_addr;
struct bna_txq_entry *txqent;
u16 flags;
- if (unlikely
- (skb->len <= ETH_HLEN || skb->len > BFI_TX_MAX_DATA_PER_PKT)) {
- dev_kfree_skb(skb);
- return NETDEV_TX_OK;
- }
+ BNAD_DROP_AND_RETURN_IF(skb->len <= ETH_HLEN, tx_skb_too_short);
+ BNAD_DROP_AND_RETURN_IF(skb_headlen(skb) > BFI_TX_MAX_DATA_PER_VECTOR,
+ tx_skb_headlen_too_long);
+ BNAD_DROP_AND_RETURN_IF(skb_headlen(skb) == 0, tx_skb_headlen_zero);
txq_id = skb_get_queue_mapping(skb);
@@ -2611,16 +2585,13 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
* Takes care of the Tx that is scheduled between clearing the flag
* and the netif_stop_all_queue() call.
*/
- if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) {
- dev_kfree_skb(skb);
- return NETDEV_TX_OK;
- }
+ BNAD_DROP_AND_RETURN_IF(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags),
+ tx_skb_stopping);
vectors = 1 + skb_shinfo(skb)->nr_frags;
- if (vectors > BFI_TX_MAX_VECTORS_PER_PKT) {
- dev_kfree_skb(skb);
- return NETDEV_TX_OK;
- }
+ BNAD_DROP_AND_RETURN_IF(vectors > BFI_TX_MAX_VECTORS_PER_PKT,
+ tx_skb_max_vectors);
+
wis = BNA_TXQ_WI_NEEDED(vectors); /* 4 vectors per work item */
acked = 0;
if (unlikely(wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
@@ -2656,8 +2627,6 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
}
unmap_prod = unmap_q->producer_index;
- wis_used = 1;
- vect_id = 0;
flags = 0;
txq_prod = tcb->producer_index;
@@ -2665,9 +2634,6 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
BUG_ON(!(wi_range <= tcb->q_depth));
txqent->hdr.wi.reserved = 0;
txqent->hdr.wi.num_vectors = vectors;
- txqent->hdr.wi.opcode =
- htons((skb_is_gso(skb) ? BNA_TXQ_WI_SEND_LSO :
- BNA_TXQ_WI_SEND));
if (vlan_tx_tag_present(skb)) {
vlan_tag = (u16) vlan_tx_tag_get(skb);
@@ -2683,62 +2649,74 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
txqent->hdr.wi.vlan_tag = htons(vlan_tag);
if (skb_is_gso(skb)) {
- err = bnad_tso_prepare(bnad, skb);
- if (err) {
- dev_kfree_skb(skb);
- return NETDEV_TX_OK;
+ BNAD_DROP_AND_RETURN_IF(skb_is_gso(skb) > netdev->mtu,
+ tx_skb_mss_too_long);
+ if (unlikely((skb_is_gso(skb) + skb_transport_offset(skb) +
+ tcp_hdrlen(skb)) >= skb->len)) {
+ txqent->hdr.wi.opcode =
+ __constant_htons(BNA_TXQ_WI_SEND);
+ txqent->hdr.wi.lso_mss = 0;
+ BNAD_UPDATE_CTR(bnad, tx_skb_tso_too_short);
+ } else {
+ txqent->hdr.wi.opcode =
+ __constant_htons(BNA_TXQ_WI_SEND_LSO);
+ txqent->hdr.wi.lso_mss = htons(skb_is_gso(skb));
}
- txqent->hdr.wi.lso_mss = htons(skb_is_gso(skb));
+
+ err = bnad_tso_prepare(bnad, skb);
+ BNAD_DROP_AND_RETURN_IF(err, tx_skb_tso_prepare);
flags |= (BNA_TXQ_WI_CF_IP_CKSUM | BNA_TXQ_WI_CF_TCP_CKSUM);
txqent->hdr.wi.l4_hdr_size_n_offset =
htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
(tcp_hdrlen(skb) >> 2,
skb_transport_offset(skb)));
- } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
- u8 proto = 0;
-
+ } else {
+ txqent->hdr.wi.opcode = __constant_htons(BNA_TXQ_WI_SEND);
txqent->hdr.wi.lso_mss = 0;
- if (skb->protocol == htons(ETH_P_IP))
- proto = ip_hdr(skb)->protocol;
- else if (skb->protocol == htons(ETH_P_IPV6)) {
- /* nexthdr may not be TCP immediately. */
- proto = ipv6_hdr(skb)->nexthdr;
- }
- if (proto == IPPROTO_TCP) {
- flags |= BNA_TXQ_WI_CF_TCP_CKSUM;
- txqent->hdr.wi.l4_hdr_size_n_offset =
- htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
- (0, skb_transport_offset(skb)));
-
- BNAD_UPDATE_CTR(bnad, tcpcsum_offload);
+ BNAD_DROP_AND_RETURN_IF(skb->len > (netdev->mtu + ETH_HLEN),
+ tx_skb_non_tso_too_long);
- BUG_ON(!(skb_headlen(skb) >=
- skb_transport_offset(skb) + tcp_hdrlen(skb)));
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ u8 proto = 0;
- } else if (proto == IPPROTO_UDP) {
- flags |= BNA_TXQ_WI_CF_UDP_CKSUM;
- txqent->hdr.wi.l4_hdr_size_n_offset =
- htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
- (0, skb_transport_offset(skb)));
-
- BNAD_UPDATE_CTR(bnad, udpcsum_offload);
-
- BUG_ON(!(skb_headlen(skb) >=
- skb_transport_offset(skb) +
- sizeof(struct udphdr)));
- } else {
- err = skb_checksum_help(skb);
- BNAD_UPDATE_CTR(bnad, csum_help);
- if (err) {
- dev_kfree_skb(skb);
- BNAD_UPDATE_CTR(bnad, csum_help_err);
- return NETDEV_TX_OK;
+ if (skb->protocol == __constant_htons(ETH_P_IP))
+ proto = ip_hdr(skb)->protocol;
+ else if (skb->protocol ==
+ __constant_htons(ETH_P_IPV6)) {
+ /* nexthdr may not be TCP immediately. */
+ proto = ipv6_hdr(skb)->nexthdr;
}
+ if (proto == IPPROTO_TCP) {
+ flags |= BNA_TXQ_WI_CF_TCP_CKSUM;
+ txqent->hdr.wi.l4_hdr_size_n_offset =
+ htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
+ (0, skb_transport_offset(skb)));
+
+ BNAD_UPDATE_CTR(bnad, tcpcsum_offload);
+
+ BNAD_DROP_AND_RETURN_IF(skb_headlen(skb) <
+ skb_transport_offset(skb) +
+ tcp_hdrlen(skb), tx_skb_tcp_hdr);
+
+ } else if (proto == IPPROTO_UDP) {
+ flags |= BNA_TXQ_WI_CF_UDP_CKSUM;
+ txqent->hdr.wi.l4_hdr_size_n_offset =
+ htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
+ (0, skb_transport_offset(skb)));
+
+ BNAD_UPDATE_CTR(bnad, udpcsum_offload);
+ BNAD_DROP_AND_RETURN_IF(skb_headlen(skb) <
+ skb_transport_offset(skb) +
+ sizeof(struct udphdr),
+ tx_skb_udp_hdr);
+
+ } else {
+ BNAD_DROP_AND_RETURN(tx_skb_csum_err);
+ }
+ } else {
+ txqent->hdr.wi.l4_hdr_size_n_offset = 0;
}
- } else {
- txqent->hdr.wi.lso_mss = 0;
- txqent->hdr.wi.l4_hdr_size_n_offset = 0;
}
txqent->hdr.wi.flags = htons(flags);
@@ -2746,20 +2724,36 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
txqent->hdr.wi.frame_length = htonl(skb->len);
unmap_q->unmap_array[unmap_prod].skb = skb;
- BUG_ON(!(skb_headlen(skb) <= BFI_TX_MAX_DATA_PER_VECTOR));
- txqent->vector[vect_id].length = htons(skb_headlen(skb));
+ len = skb_headlen(skb);
+ txqent->vector[0].length = htons(len);
dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data,
skb_headlen(skb), DMA_TO_DEVICE);
dma_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
dma_addr);
- BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
+ BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[0].host_addr);
BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
+ vect_id = 0;
+ wis_used = 1;
+
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
u16 size = frag->size;
+ if (unlikely(size == 0)) {
+ unmap_prod = unmap_q->producer_index;
+ prefetch(&unmap_q->unmap_array[unmap_prod + 1]);
+
+ BNAD_PCI_UNMAP_SKB(&bnad->pcidev->dev,
+ unmap_q->unmap_array,
+ unmap_prod, unmap_q->q_depth, skb,
+ i);
+ BNAD_DROP_AND_RETURN(tx_skb_frag_zero);
+ }
+
+ len += size;
+
if (++vect_id == BFI_TX_MAX_VECTORS_PER_WI) {
vect_id = 0;
if (--wi_range)
@@ -2770,10 +2764,10 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
wis_used = 0;
BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt,
txqent, wi_range);
- BUG_ON(!(wi_range <= tcb->q_depth));
}
wis_used++;
- txqent->hdr.wi_ext.opcode = htons(BNA_TXQ_WI_EXTENSION);
+ txqent->hdr.wi_ext.opcode =
+ __constant_htons(BNA_TXQ_WI_EXTENSION);
}
BUG_ON(!(size <= BFI_TX_MAX_DATA_PER_VECTOR));
@@ -2786,6 +2780,16 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
}
+ if (unlikely(len != skb->len)) {
+ unmap_prod = unmap_q->producer_index;
+ prefetch(&unmap_q->unmap_array[unmap_prod + 1]);
+
+ BNAD_PCI_UNMAP_SKB(&bnad->pcidev->dev, unmap_q->unmap_array,
+ unmap_prod, unmap_q->q_depth, skb,
+ skb_shinfo(skb)->nr_frags);
+ BNAD_DROP_AND_RETURN(tx_skb_len_mismatch);
+ }
+
unmap_q->producer_index = unmap_prod;
BNA_QE_INDX_ADD(txq_prod, wis_used, tcb->q_depth);
tcb->producer_index = txq_prod;
@@ -2796,6 +2800,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
bna_txq_prod_indx_doorbell(tcb);
+ smp_mb();
if ((u16) (*tcb->hw_consumer_index) != tcb->consumer_index)
tasklet_schedule(&bnad->tx_free_tasklet);
@@ -2906,6 +2911,9 @@ bnad_set_rx_mode(struct net_device *netdev)
}
}
+ if (bnad->rx_info[0].rx == NULL)
+ goto unlock;
+
bna_rx_mode_set(bnad->rx_info[0].rx, new_mask, valid_mask, NULL);
if (!netdev_mc_empty(netdev)) {
@@ -3067,12 +3075,9 @@ bnad_netpoll(struct net_device *netdev)
continue;
for (j = 0; j < bnad->num_rxp_per_rx; j++) {
rx_ctrl = &rx_info->rx_ctrl[j];
- if (rx_ctrl->ccb) {
- bnad_disable_rx_irq(bnad,
- rx_ctrl->ccb);
+ if (rx_ctrl->ccb)
bnad_netif_rx_schedule_poll(bnad,
rx_ctrl->ccb);
- }
}
}
}
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index 7f0648d..02c6342 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -54,7 +54,11 @@ struct bnad_rx_ctrl {
struct bnad *bnad;
unsigned long flags;
struct napi_struct napi;
- u16 pkts_to_ack;
+ u64 rx_intr_ctr;
+ u64 rx_poll_ctr;
+ u64 rx_schedule;
+ u64 rx_keep_poll;
+ u64 rx_complete;
};
#define BNAD_RXMODE_PROMISC_DEFAULT BNA_RXMODE_PROMISC
@@ -150,6 +154,20 @@ struct bnad_drv_stats {
u64 udpcsum_offload;
u64 csum_help;
u64 csum_help_err;
+ u64 tx_skb_too_short;
+ u64 tx_skb_stopping;
+ u64 tx_skb_max_vectors;
+ u64 tx_skb_mss_too_long;
+ u64 tx_skb_tso_too_short;
+ u64 tx_skb_tso_prepare;
+ u64 tx_skb_non_tso_too_long;
+ u64 tx_skb_tcp_hdr;
+ u64 tx_skb_udp_hdr;
+ u64 tx_skb_csum_err;
+ u64 tx_skb_headlen_too_long;
+ u64 tx_skb_headlen_zero;
+ u64 tx_skb_frag_zero;
+ u64 tx_skb_len_mismatch;
u64 hw_stats_updates;
u64 netif_rx_schedule;
@@ -357,7 +375,7 @@ extern void bnad_netdev_hwstats_fill(struct bnad *bnad,
#define bnad_enable_rx_irq_unsafe(_ccb) \
{ \
- if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))) {\
+ 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); \
@@ -367,5 +385,19 @@ extern void bnad_netdev_hwstats_fill(struct bnad *bnad,
#define bnad_dim_timer_running(_bnad) \
(((_bnad)->cfg_flags & BNAD_CF_DIM_ENABLED) && \
(test_bit(BNAD_RF_DIM_TIMER_RUNNING, &((_bnad)->run_flags))))
+#define bnad_dim_timer_stop(_bnad, _flags) \
+do { \
+ int to_del = 0; \
+ \
+ if ((_bnad)->cfg_flags & BNAD_CF_DIM_ENABLED && \
+ test_bit(BNAD_RF_DIM_TIMER_RUNNING, &(_bnad)->run_flags)) {\
+ clear_bit(BNAD_RF_DIM_TIMER_RUNNING, &(_bnad)->run_flags);\
+ to_del = 1; \
+ } \
+ spin_unlock_irqrestore(&(_bnad)->bna_lock, (_flags)); \
+ if (to_del) \
+ del_timer_sync(&(_bnad)->dim_timer); \
+ spin_lock_irqsave(&(_bnad)->bna_lock, (_flags));\
+} while (0)
#endif /* __BNAD_H__ */
--
1.7.1
^ permalink raw reply related
* [PATCH 2/4] ipv6: Get rid of rt6i_nexthop macro.
From: David Miller @ 2011-07-18 8:25 UTC (permalink / raw)
To: netdev
It just makes it harder to see 1) what the code is doing
and 2) grep for all users of dst{->,.}neighbour
Signed-off-by: David S. Miller <davem@davemloft.net>
---
include/net/ip6_fib.h | 1 -
net/ipv6/addrconf.c | 2 +-
net/ipv6/ip6_fib.c | 2 +-
net/ipv6/ndisc.c | 4 ++--
net/ipv6/route.c | 30 +++++++++++++++---------------
5 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 477ef75..5735a0f 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -87,7 +87,6 @@ struct rt6_info {
struct dst_entry dst;
#define rt6i_dev dst.dev
-#define rt6i_nexthop dst.neighbour
#define rt6i_expires dst.expires
/*
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index fc6d377..48cd03d 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -656,7 +656,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
* layer address of our nexhop router
*/
- if (rt->rt6i_nexthop == NULL)
+ if (rt->dst.neighbour == NULL)
ifa->flags &= ~IFA_F_OPTIMISTIC;
ifa->idev = idev;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 3030bdf..158df23 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1455,7 +1455,7 @@ static int fib6_age(struct rt6_info *rt, void *arg)
RT6_TRACE("aging clone %p\n", rt);
return -1;
} else if ((rt->rt6i_flags & RTF_GATEWAY) &&
- (!(rt->rt6i_nexthop->flags & NTF_ROUTER))) {
+ (!(rt->dst.neighbour->flags & NTF_ROUTER))) {
RT6_TRACE("purging route %p via non-router but gateway\n",
rt);
return -1;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index e08ce55..a997d41 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1238,7 +1238,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev);
if (rt)
- neigh = rt->rt6i_nexthop;
+ neigh = rt->dst.neighbour;
if (rt && lifetime == 0) {
neigh_clone(neigh);
@@ -1259,7 +1259,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
return;
}
- neigh = rt->rt6i_nexthop;
+ neigh = rt->dst.neighbour;
if (neigh == NULL) {
ND_PRINTK0(KERN_ERR
"ICMPv6 RA: %s() got default router without neighbour.\n",
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index f032d77..c1515a3 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -356,7 +356,7 @@ out:
#ifdef CONFIG_IPV6_ROUTER_PREF
static void rt6_probe(struct rt6_info *rt)
{
- struct neighbour *neigh = rt ? rt->rt6i_nexthop : NULL;
+ struct neighbour *neigh = rt ? rt->dst.neighbour : NULL;
/*
* Okay, this does not seem to be appropriate
* for now, however, we need to check if it
@@ -404,7 +404,7 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif)
static inline int rt6_check_neigh(struct rt6_info *rt)
{
- struct neighbour *neigh = rt->rt6i_nexthop;
+ struct neighbour *neigh = rt->dst.neighbour;
int m;
if (rt->rt6i_flags & RTF_NONEXTHOP ||
!(rt->rt6i_flags & RTF_GATEWAY))
@@ -745,7 +745,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add
dst_free(&rt->dst);
return NULL;
}
- rt->rt6i_nexthop = neigh;
+ rt->dst.neighbour = neigh;
}
@@ -760,7 +760,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, const struct in6_a
rt->rt6i_dst.plen = 128;
rt->rt6i_flags |= RTF_CACHE;
rt->dst.flags |= DST_HOST;
- rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop);
+ rt->dst.neighbour = neigh_clone(ort->dst.neighbour);
}
return rt;
}
@@ -794,7 +794,7 @@ restart:
dst_hold(&rt->dst);
read_unlock_bh(&table->tb6_lock);
- if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
+ if (!rt->dst.neighbour && !(rt->rt6i_flags & RTF_NONEXTHOP))
nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
else if (!(rt->dst.flags & DST_HOST))
nrt = rt6_alloc_clone(rt, &fl6->daddr);
@@ -1058,7 +1058,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
}
rt->rt6i_idev = idev;
- rt->rt6i_nexthop = neigh;
+ rt->dst.neighbour = neigh;
atomic_set(&rt->dst.__refcnt, 1);
dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
rt->dst.output = ip6_output;
@@ -1338,10 +1338,10 @@ int ip6_route_add(struct fib6_config *cfg)
rt->rt6i_prefsrc.plen = 0;
if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
- rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
- if (IS_ERR(rt->rt6i_nexthop)) {
- err = PTR_ERR(rt->rt6i_nexthop);
- rt->rt6i_nexthop = NULL;
+ rt->dst.neighbour = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
+ if (IS_ERR(rt->dst.neighbour)) {
+ err = PTR_ERR(rt->dst.neighbour);
+ rt->dst.neighbour = NULL;
goto out;
}
}
@@ -1590,7 +1590,7 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
nrt->dst.flags |= DST_HOST;
ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
- nrt->rt6i_nexthop = neigh_clone(neigh);
+ nrt->dst.neighbour = neigh_clone(neigh);
if (ip6_ins_rt(nrt))
goto out;
@@ -1670,7 +1670,7 @@ again:
1. It is connected route. Action: COW
2. It is gatewayed route or NONEXTHOP route. Action: clone it.
*/
- if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
+ if (!rt->dst.neighbour && !(rt->rt6i_flags & RTF_NONEXTHOP))
nrt = rt6_alloc_cow(rt, daddr, saddr);
else
nrt = rt6_alloc_clone(rt, daddr);
@@ -2035,7 +2035,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
return ERR_CAST(neigh);
}
- rt->rt6i_nexthop = neigh;
+ rt->dst.neighbour = neigh;
ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
rt->rt6i_dst.plen = 128;
@@ -2594,8 +2594,8 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
seq_puts(m, "00000000000000000000000000000000 00 ");
#endif
- if (rt->rt6i_nexthop) {
- seq_printf(m, "%pi6", rt->rt6i_nexthop->primary_key);
+ if (rt->dst.neighbour) {
+ seq_printf(m, "%pi6", rt->dst.neighbour->primary_key);
} else {
seq_puts(m, "00000000000000000000000000000000");
}
--
1.7.6
^ permalink raw reply related
* [PATCH 40/45] bna: Add IOC MBOX Call Back to Client
From: Rasesh Mody @ 2011-07-18 8:23 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change deatils:
- Give a callback to the client indicating that the command is sent
- Removed a typecast
- When done with IOC detach we empty the notify_q.
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_ioc.c | 24 ++++++++++++++++++------
drivers/net/bna/bfi.h | 17 +++++++++--------
2 files changed, 27 insertions(+), 14 deletions(-)
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index e612ca4..b086cd7 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -1768,7 +1768,9 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
{
struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
struct bfa_mbox_cmd *cmd;
- u32 stat;
+ bfa_mbox_cmd_cbfn_t cbfn;
+ void *cbarg;
+ u32 stat;
/**
* If no command pending, do nothing
@@ -1788,6 +1790,16 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
*/
bfa_q_deq(&mod->cmd_q, &cmd);
bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
+
+ /**
+ * Give a callback to the client, indicating that the command is sent
+ */
+ if (cmd->cbfn) {
+ cbfn = cmd->cbfn;
+ cbarg = cmd->cbarg;
+ cmd->cbfn = NULL;
+ cbfn(cbarg);
+ }
}
/**
@@ -1953,7 +1965,7 @@ bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
case BFI_IOC_I2H_ENABLE_REPLY:
bfa_ioc_enable_reply(ioc,
(enum bfa_mode)msg->fw_event.port_mode,
- (enum bfa_mode)msg->fw_event.cap_bm);
+ msg->fw_event.cap_bm);
break;
case BFI_IOC_I2H_DISABLE_REPLY:
@@ -2003,6 +2015,9 @@ void
bfa_nw_ioc_detach(struct bfa_ioc *ioc)
{
bfa_fsm_send_event(ioc, IOC_E_DETACH);
+
+ /* Done with detach, empty the notify_q. */
+ INIT_LIST_HEAD(&ioc->notify_q);
}
/**
@@ -2292,15 +2307,12 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc,
enum bfa_ioc_type
bfa_nw_ioc_get_type(struct bfa_ioc *ioc)
{
- enum bfi_port_mode mode;
-
if (ioc->clscode == BFI_PCIFN_CLASS_ETH)
return BFA_IOC_TYPE_LL;
BUG_ON(!(ioc->clscode == BFI_PCIFN_CLASS_FC));
- mode = (ioc->port_id == 0) ? ioc->port0_mode : ioc->port1_mode;
- return (mode == BFI_PORT_MODE_FC)
+ return (ioc->attr->port_mode == BFI_PORT_MODE_FC)
? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE;
}
diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h
index c534318..8dd8463 100644
--- a/drivers/net/bna/bfi.h
+++ b/drivers/net/bna/bfi.h
@@ -15,7 +15,6 @@
* All rights reserved
* www.brocade.com
*/
-
#ifndef __BFI_H__
#define __BFI_H__
@@ -38,18 +37,20 @@ struct bfi_mhdr {
union {
struct {
u8 qid;
- u8 lpu_id; /*!< msg destination */
+ u8 fn_lpu; /*!< msg destination */
} h2i;
u16 i2htok; /*!< token in msgs to host */
} mtag;
};
-#define bfi_mhdr_2_qid(_mh) ((_mh)->mtag.h2i.qid)
+#define bfi_fn_lpu(__fn, __lpu) ((__fn) << 1 | (__lpu))
+#define bfi_mhdr_2_fn(_mh) ((_mh)->mtag.h2i.fn_lpu >> 1)
+#define bfi_mhdr_2_qid(_mh) ((_mh)->mtag.h2i.qid)
-#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do { \
+#define bfi_h2i_set(_mh, _mc, _op, _fn_lpu) do { \
(_mh).msg_class = (_mc); \
(_mh).msg_id = (_op); \
- (_mh).mtag.h2i.lpu_id = (_lpuid); \
+ (_mh).mtag.h2i.fn_lpu = (_fn_lpu); \
} while (0)
#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do { \
@@ -240,7 +241,8 @@ struct bfi_ioc_attr {
u64 mfg_pwwn; /*!< Mfg port wwn */
u64 mfg_nwwn; /*!< Mfg node wwn */
mac_t mfg_mac; /*!< Mfg mac */
- u16 rsvd_a;
+ u8 port_mode; /* enum bfi_port_mode */
+ u8 rsvd_a;
u64 pwwn;
u64 nwwn;
mac_t mac; /*!< PBC or Mfg mac */
@@ -297,7 +299,6 @@ struct bfi_ioc_image_hdr {
u8 asic_mode;
u8 port0_mode; /*!< device mode for port 0 */
u8 port1_mode; /*!< device mode for port 1 */
- u8 rsvd_a;
u32 exec; /*!< exec vector */
u32 bootenv; /*!< firmware boot env */
u32 rsvd_b[4];
@@ -400,7 +401,7 @@ struct bfi_ioc_ctrl_req {
struct bfi_ioc_ctrl_reply {
struct bfi_mhdr mh; /*!< Common msg header */
u8 status; /*!< enable/disable status */
- u8 port_mode; /*!< bfa_mode */
+ u8 port_mode; /*!< enum bfa_mode */
u8 cap_bm; /*!< capability bit mask */
u8 rsvd;
};
--
1.7.1
^ permalink raw reply related
* [PATCH 3/4] net: Abstract dst->neighbour accesses behind helpers.
From: David Miller @ 2011-07-18 8:25 UTC (permalink / raw)
To: netdev
dst_{get,set}_neighbour()
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/infiniband/core/addr.c | 7 ++--
drivers/infiniband/hw/cxgb3/iwch_cm.c | 12 ++++--
drivers/infiniband/hw/cxgb4/cm.c | 42 ++++++++++++------------
drivers/infiniband/hw/nes/nes_cm.c | 2 +-
drivers/infiniband/ulp/ipoib/ipoib_main.c | 41 +++++++++++++++--------
drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 20 +++++++----
drivers/net/cxgb3/cxgb3_offload.c | 8 ++--
drivers/s390/net/qeth_l3_main.c | 25 ++++++++++----
drivers/scsi/cxgbi/cxgb3i/cxgb3i.c | 2 +-
drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 2 +-
drivers/scsi/cxgbi/libcxgbi.c | 4 +-
include/net/dst.h | 18 ++++++++--
net/atm/clip.c | 16 ++++++---
net/bridge/br_netfilter.c | 2 +-
net/core/dst.c | 10 +++---
net/core/neighbour.c | 7 ++--
net/decnet/dn_neigh.c | 2 +-
net/decnet/dn_route.c | 18 ++++++----
net/ipv4/ip_gre.c | 2 +-
net/ipv4/ip_output.c | 2 +-
net/ipv4/route.c | 25 +++++++-------
net/ipv6/addrconf.c | 2 +-
net/ipv6/ip6_fib.c | 2 +-
net/ipv6/ip6_output.c | 16 ++++++---
net/ipv6/ndisc.c | 4 +-
net/ipv6/route.c | 39 +++++++++++-----------
net/ipv6/sit.c | 4 +-
net/sched/sch_teql.c | 4 +-
net/xfrm/xfrm_policy.c | 2 +-
29 files changed, 200 insertions(+), 140 deletions(-)
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 8e21d45..236ad9a 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -215,7 +215,7 @@ static int addr4_resolve(struct sockaddr_in *src_in,
neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
if (!neigh || !(neigh->nud_state & NUD_VALID)) {
- neigh_event_send(rt->dst.neighbour, NULL);
+ neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
ret = -ENODATA;
if (neigh)
goto release;
@@ -273,9 +273,10 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
goto put;
}
- neigh = dst->neighbour;
+ neigh = dst_get_neighbour(dst);
if (!neigh || !(neigh->nud_state & NUD_VALID)) {
- neigh_event_send(dst->neighbour, NULL);
+ if (neigh)
+ neigh_event_send(neigh, NULL);
ret = -ENODATA;
goto put;
}
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 0a5008f..17bf9d9 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -1328,6 +1328,7 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
struct iwch_ep *child_ep, *parent_ep = ctx;
struct cpl_pass_accept_req *req = cplhdr(skb);
unsigned int hwtid = GET_TID(req);
+ struct neighbour *neigh;
struct dst_entry *dst;
struct l2t_entry *l2t;
struct rtable *rt;
@@ -1364,7 +1365,8 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
goto reject;
}
dst = &rt->dst;
- l2t = t3_l2t_get(tdev, dst->neighbour, dst->neighbour->dev);
+ neigh = dst_get_neighbour(dst);
+ l2t = t3_l2t_get(tdev, neigh, neigh->dev);
if (!l2t) {
printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
__func__);
@@ -1874,10 +1876,11 @@ static int is_loopback_dst(struct iw_cm_id *cm_id)
int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
{
- int err = 0;
struct iwch_dev *h = to_iwch_dev(cm_id->device);
+ struct neighbour *neigh;
struct iwch_ep *ep;
struct rtable *rt;
+ int err = 0;
if (is_loopback_dst(cm_id)) {
err = -ENOSYS;
@@ -1933,9 +1936,10 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
}
ep->dst = &rt->dst;
+ neigh = dst_get_neighbour(ep->dst);
+
/* get a l2t entry */
- ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst->neighbour,
- ep->dst->neighbour->dev);
+ ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
if (!ep->l2t) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
err = -ENOMEM;
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 31fb440..77f769d 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -1325,6 +1325,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
unsigned int stid = GET_POPEN_TID(ntohl(req->tos_stid));
struct tid_info *t = dev->rdev.lldi.tids;
unsigned int hwtid = GET_TID(req);
+ struct neighbour *neigh;
struct dst_entry *dst;
struct l2t_entry *l2t;
struct rtable *rt;
@@ -1357,11 +1358,11 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
goto reject;
}
dst = &rt->dst;
- if (dst->neighbour->dev->flags & IFF_LOOPBACK) {
+ neigh = dst_get_neighbour(dst);
+ if (neigh->dev->flags & IFF_LOOPBACK) {
pdev = ip_dev_find(&init_net, peer_ip);
BUG_ON(!pdev);
- l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour,
- pdev, 0);
+ l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, pdev, 0);
mtu = pdev->mtu;
tx_chan = cxgb4_port_chan(pdev);
smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
@@ -1372,17 +1373,16 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
rss_qid = dev->rdev.lldi.rxq_ids[cxgb4_port_idx(pdev) * step];
dev_put(pdev);
} else {
- l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour,
- dst->neighbour->dev, 0);
+ l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, neigh->dev, 0);
mtu = dst_mtu(dst);
- tx_chan = cxgb4_port_chan(dst->neighbour->dev);
- smac_idx = (cxgb4_port_viid(dst->neighbour->dev) & 0x7F) << 1;
+ tx_chan = cxgb4_port_chan(neigh->dev);
+ smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan;
- txq_idx = cxgb4_port_idx(dst->neighbour->dev) * step;
- ctrlq_idx = cxgb4_port_idx(dst->neighbour->dev);
+ txq_idx = cxgb4_port_idx(neigh->dev) * step;
+ ctrlq_idx = cxgb4_port_idx(neigh->dev);
step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
rss_qid = dev->rdev.lldi.rxq_ids[
- cxgb4_port_idx(dst->neighbour->dev) * step];
+ cxgb4_port_idx(neigh->dev) * step];
}
if (!l2t) {
printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
@@ -1847,6 +1847,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
struct c4iw_ep *ep;
struct rtable *rt;
struct net_device *pdev;
+ struct neighbour *neigh;
int step;
if ((conn_param->ord > c4iw_max_read_depth) ||
@@ -1908,14 +1909,15 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
}
ep->dst = &rt->dst;
+ neigh = dst_get_neighbour(ep->dst);
+
/* get a l2t entry */
- if (ep->dst->neighbour->dev->flags & IFF_LOOPBACK) {
+ if (neigh->dev->flags & IFF_LOOPBACK) {
PDBG("%s LOOPBACK\n", __func__);
pdev = ip_dev_find(&init_net,
cm_id->remote_addr.sin_addr.s_addr);
ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
- ep->dst->neighbour,
- pdev, 0);
+ neigh, pdev, 0);
ep->mtu = pdev->mtu;
ep->tx_chan = cxgb4_port_chan(pdev);
ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
@@ -1930,20 +1932,18 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
dev_put(pdev);
} else {
ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
- ep->dst->neighbour,
- ep->dst->neighbour->dev, 0);
+ neigh, neigh->dev, 0);
ep->mtu = dst_mtu(ep->dst);
- ep->tx_chan = cxgb4_port_chan(ep->dst->neighbour->dev);
- ep->smac_idx = (cxgb4_port_viid(ep->dst->neighbour->dev) &
- 0x7F) << 1;
+ ep->tx_chan = cxgb4_port_chan(neigh->dev);
+ ep->smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
step = ep->com.dev->rdev.lldi.ntxq /
ep->com.dev->rdev.lldi.nchan;
- ep->txq_idx = cxgb4_port_idx(ep->dst->neighbour->dev) * step;
- ep->ctrlq_idx = cxgb4_port_idx(ep->dst->neighbour->dev);
+ ep->txq_idx = cxgb4_port_idx(neigh->dev) * step;
+ ep->ctrlq_idx = cxgb4_port_idx(neigh->dev);
step = ep->com.dev->rdev.lldi.nrxq /
ep->com.dev->rdev.lldi.nchan;
ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
- cxgb4_port_idx(ep->dst->neighbour->dev) * step];
+ cxgb4_port_idx(neigh->dev) * step];
}
if (!ep->l2t) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index e74cdf9..73bc184 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -1151,7 +1151,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
}
if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
- neigh_event_send(rt->dst.neighbour, NULL);
+ neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
ip_rt_put(rt);
return rc;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 86addca..43f89ba 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -560,9 +560,11 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_path *path;
struct ipoib_neigh *neigh;
+ struct neighbour *n;
unsigned long flags;
- neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev);
+ n = dst_get_neighbour(skb_dst(skb));
+ neigh = ipoib_neigh_alloc(n, skb->dev);
if (!neigh) {
++dev->stats.tx_dropped;
dev_kfree_skb_any(skb);
@@ -571,9 +573,9 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave(&priv->lock, flags);
- path = __path_find(dev, skb_dst(skb)->neighbour->ha + 4);
+ path = __path_find(dev, n->ha + 4);
if (!path) {
- path = path_rec_create(dev, skb_dst(skb)->neighbour->ha + 4);
+ path = path_rec_create(dev, n->ha + 4);
if (!path)
goto err_path;
@@ -607,7 +609,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
}
} else {
spin_unlock_irqrestore(&priv->lock, flags);
- ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
+ ipoib_send(dev, skb, path->ah, IPOIB_QPN(n->ha));
return;
}
} else {
@@ -637,17 +639,20 @@ err_drop:
static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
+ struct dst_entry *dst = skb_dst(skb);
+ struct neighbour *n;
/* Look up path record for unicasts */
- if (skb_dst(skb)->neighbour->ha[4] != 0xff) {
+ n = dst_get_neighbour(dst);
+ if (n->ha[4] != 0xff) {
neigh_add_path(skb, dev);
return;
}
/* Add in the P_Key for multicasts */
- skb_dst(skb)->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
- skb_dst(skb)->neighbour->ha[9] = priv->pkey & 0xff;
- ipoib_mcast_send(dev, skb_dst(skb)->neighbour->ha + 4, skb);
+ n->ha[8] = (priv->pkey >> 8) & 0xff;
+ n->ha[9] = priv->pkey & 0xff;
+ ipoib_mcast_send(dev, n->ha + 4, skb);
}
static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
@@ -712,18 +717,20 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_neigh *neigh;
+ struct neighbour *n;
unsigned long flags;
- if (likely(skb_dst(skb) && skb_dst(skb)->neighbour)) {
- if (unlikely(!*to_ipoib_neigh(skb_dst(skb)->neighbour))) {
+ n = dst_get_neighbour(skb_dst(skb));
+ if (likely(skb_dst(skb) && n)) {
+ if (unlikely(!*to_ipoib_neigh(n))) {
ipoib_path_lookup(skb, dev);
return NETDEV_TX_OK;
}
- neigh = *to_ipoib_neigh(skb_dst(skb)->neighbour);
+ neigh = *to_ipoib_neigh(n);
if (unlikely((memcmp(&neigh->dgid.raw,
- skb_dst(skb)->neighbour->ha + 4,
+ n->ha + 4,
sizeof(union ib_gid))) ||
(neigh->dev != dev))) {
spin_lock_irqsave(&priv->lock, flags);
@@ -749,7 +756,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
} else if (neigh->ah) {
- ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
+ ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
return NETDEV_TX_OK;
}
@@ -812,6 +819,8 @@ static int ipoib_hard_header(struct sk_buff *skb,
const void *daddr, const void *saddr, unsigned len)
{
struct ipoib_header *header;
+ struct dst_entry *dst;
+ struct neighbour *n;
header = (struct ipoib_header *) skb_push(skb, sizeof *header);
@@ -823,7 +832,11 @@ static int ipoib_hard_header(struct sk_buff *skb,
* destination address onto the front of the skb so we can
* figure out where to send the packet later.
*/
- if ((!skb_dst(skb) || !skb_dst(skb)->neighbour) && daddr) {
+ dst = skb_dst(skb);
+ n = NULL;
+ if (dst)
+ n = dst_get_neighbour(dst);
+ if ((!dst || !n) && daddr) {
struct ipoib_pseudoheader *phdr =
(struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 3871ac6..ecea4fe 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -258,11 +258,15 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
netif_tx_lock_bh(dev);
while (!skb_queue_empty(&mcast->pkt_queue)) {
struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
+ struct dst_entry *dst = skb_dst(skb);
+ struct neighbour *n = NULL;
+
netif_tx_unlock_bh(dev);
skb->dev = dev;
-
- if (!skb_dst(skb) || !skb_dst(skb)->neighbour) {
+ if (dst)
+ n = dst_get_neighbour(dst);
+ if (!dst || !n) {
/* put pseudoheader back on for next time */
skb_push(skb, sizeof (struct ipoib_pseudoheader));
}
@@ -715,11 +719,13 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
out:
if (mcast && mcast->ah) {
- if (skb_dst(skb) &&
- skb_dst(skb)->neighbour &&
- !*to_ipoib_neigh(skb_dst(skb)->neighbour)) {
- struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour,
- skb->dev);
+ struct dst_entry *dst = skb_dst(skb);
+ struct neighbour *n = NULL;
+ if (dst)
+ n = dst_get_neighbour(dst);
+ if (n && !*to_ipoib_neigh(n)) {
+ struct ipoib_neigh *neigh = ipoib_neigh_alloc(n,
+ skb->dev);
if (neigh) {
kref_get(&mcast->ah->ref);
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index 9db9068..fa1b450 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -971,7 +971,7 @@ static int nb_callback(struct notifier_block *self, unsigned long event,
case (NETEVENT_REDIRECT):{
struct netevent_redirect *nr = ctx;
cxgb_redirect(nr->old, nr->new);
- cxgb_neigh_update(nr->new->neighbour);
+ cxgb_neigh_update(dst_get_neighbour(nr->new));
break;
}
default:
@@ -1116,8 +1116,8 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
struct l2t_entry *e;
struct t3c_tid_entry *te;
- olddev = old->neighbour->dev;
- newdev = new->neighbour->dev;
+ olddev = dst_get_neighbour(old)->dev;
+ newdev = dst_get_neighbour(new)->dev;
if (!is_offloading(olddev))
return;
if (!is_offloading(newdev)) {
@@ -1134,7 +1134,7 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
}
/* Add new L2T entry */
- e = t3_l2t_get(tdev, new->neighbour, newdev);
+ e = t3_l2t_get(tdev, dst_get_neighbour(new), newdev);
if (!e) {
printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n",
__func__);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index fd69da3..e2c9ac5 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2742,9 +2742,14 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
{
int cast_type = RTN_UNSPEC;
-
- if (skb_dst(skb) && skb_dst(skb)->neighbour) {
- cast_type = skb_dst(skb)->neighbour->type;
+ struct neighbour *n = NULL;
+ struct dst_entry *dst;
+
+ dst = skb_dst(skb);
+ if (dst)
+ n = dst_get_neighbour(dst);
+ if (n) {
+ cast_type = n->type;
if ((cast_type == RTN_BROADCAST) ||
(cast_type == RTN_MULTICAST) ||
(cast_type == RTN_ANYCAST))
@@ -2787,6 +2792,9 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb, int ipv, int cast_type)
{
+ struct neighbour *n = NULL;
+ struct dst_entry *dst;
+
memset(hdr, 0, sizeof(struct qeth_hdr));
hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
hdr->hdr.l3.ext_flags = 0;
@@ -2804,13 +2812,16 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
}
hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
+ dst = skb_dst(skb);
+ if (dst)
+ n = dst_get_neighbour(dst);
if (ipv == 4) {
/* IPv4 */
hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags4(cast_type);
memset(hdr->hdr.l3.dest_addr, 0, 12);
- if ((skb_dst(skb)) && (skb_dst(skb)->neighbour)) {
+ if (n) {
*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
- *((u32 *) skb_dst(skb)->neighbour->primary_key);
+ *((u32 *) n->primary_key);
} else {
/* fill in destination address used in ip header */
*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
@@ -2821,9 +2832,9 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags6(cast_type);
if (card->info.type == QETH_CARD_TYPE_IQD)
hdr->hdr.l3.flags &= ~QETH_HDR_PASSTHRU;
- if ((skb_dst(skb)) && (skb_dst(skb)->neighbour)) {
+ if (n) {
memcpy(hdr->hdr.l3.dest_addr,
- skb_dst(skb)->neighbour->primary_key, 16);
+ n->primary_key, 16);
} else {
/* fill in destination address used in ip header */
memcpy(hdr->hdr.l3.dest_addr,
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
index fc2cdb6..abc7b12 100644
--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -985,7 +985,7 @@ static int init_act_open(struct cxgbi_sock *csk)
csk->saddr.sin_addr.s_addr = chba->ipv4addr;
csk->rss_qid = 0;
- csk->l2t = t3_l2t_get(t3dev, dst->neighbour, ndev);
+ csk->l2t = t3_l2t_get(t3dev, dst_get_neighbour(dst), ndev);
if (!csk->l2t) {
pr_err("NO l2t available.\n");
return -EINVAL;
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index f3a4cd7..ae13c49 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -1160,7 +1160,7 @@ static int init_act_open(struct cxgbi_sock *csk)
cxgbi_sock_set_flag(csk, CTPF_HAS_ATID);
cxgbi_sock_get(csk);
- csk->l2t = cxgb4_l2t_get(lldi->l2t, csk->dst->neighbour, ndev, 0);
+ csk->l2t = cxgb4_l2t_get(lldi->l2t, dst_get_neighbour(csk->dst), ndev, 0);
if (!csk->l2t) {
pr_err("%s, cannot alloc l2t.\n", ndev->name);
goto rel_resource;
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index a2a9c7c..77ac217 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -492,7 +492,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
goto err_out;
}
dst = &rt->dst;
- ndev = dst->neighbour->dev;
+ ndev = dst_get_neighbour(dst)->dev;
if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
pr_info("multi-cast route %pI4, port %u, dev %s.\n",
@@ -506,7 +506,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
ndev = ip_dev_find(&init_net, daddr->sin_addr.s_addr);
mtu = ndev->mtu;
pr_info("rt dev %s, loopback -> %s, mtu %u.\n",
- dst->neighbour->dev->name, ndev->name, mtu);
+ dst_get_neighbour(dst)->dev->name, ndev->name, mtu);
}
cdev = cxgbi_device_find_by_netdev(ndev, &port);
diff --git a/include/net/dst.h b/include/net/dst.h
index 0dd7ccb..8147206 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -37,7 +37,7 @@ struct dst_entry {
unsigned long _metrics;
unsigned long expires;
struct dst_entry *path;
- struct neighbour *neighbour;
+ struct neighbour *_neighbour;
#ifdef CONFIG_XFRM
struct xfrm_state *xfrm;
#else
@@ -86,6 +86,16 @@ struct dst_entry {
};
};
+static inline struct neighbour *dst_get_neighbour(struct dst_entry *dst)
+{
+ return dst->_neighbour;
+}
+
+static inline void dst_set_neighbour(struct dst_entry *dst, struct neighbour *neigh)
+{
+ dst->_neighbour = neigh;
+}
+
extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
extern const u32 dst_default_metrics[RTAX_MAX];
@@ -371,8 +381,10 @@ static inline void dst_rcu_free(struct rcu_head *head)
static inline void dst_confirm(struct dst_entry *dst)
{
- if (dst)
- neigh_confirm(dst->neighbour);
+ if (dst) {
+ struct neighbour *n = dst_get_neighbour(dst);
+ neigh_confirm(n);
+ }
}
static inline void dst_link_failure(struct sk_buff *skb)
diff --git a/net/atm/clip.c b/net/atm/clip.c
index c6cd531..4bc8c67 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -362,33 +362,37 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct clip_priv *clip_priv = PRIV(dev);
+ struct dst_entry *dst = skb_dst(skb);
struct atmarp_entry *entry;
+ struct neighbour *n;
struct atm_vcc *vcc;
int old;
unsigned long flags;
pr_debug("(skb %p)\n", skb);
- if (!skb_dst(skb)) {
+ if (!dst) {
pr_err("skb_dst(skb) == NULL\n");
dev_kfree_skb(skb);
dev->stats.tx_dropped++;
return NETDEV_TX_OK;
}
- if (!skb_dst(skb)->neighbour) {
+ n = dst_get_neighbour(dst);
+ if (!n) {
#if 0
- skb_dst(skb)->neighbour = clip_find_neighbour(skb_dst(skb), 1);
- if (!skb_dst(skb)->neighbour) {
+ n = clip_find_neighbour(skb_dst(skb), 1);
+ if (!n) {
dev_kfree_skb(skb); /* lost that one */
dev->stats.tx_dropped++;
return 0;
}
+ dst_set_neighbour(dst, n);
#endif
pr_err("NO NEIGHBOUR !\n");
dev_kfree_skb(skb);
dev->stats.tx_dropped++;
return NETDEV_TX_OK;
}
- entry = NEIGH2ENTRY(skb_dst(skb)->neighbour);
+ entry = NEIGH2ENTRY(n);
if (!entry->vccs) {
if (time_after(jiffies, entry->expires)) {
/* should be resolved */
@@ -405,7 +409,7 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,
}
pr_debug("neigh %p, vccs %p\n", entry, entry->vccs);
ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
- pr_debug("using neighbour %p, vcc %p\n", skb_dst(skb)->neighbour, vcc);
+ pr_debug("using neighbour %p, vcc %p\n", n, vcc);
if (entry->vccs->encap) {
void *here;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 1fe43fd..b1a5f97 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -350,7 +350,7 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
if (!skb->dev)
goto free_skb;
dst = skb_dst(skb);
- neigh = dst->neighbour;
+ neigh = dst_get_neighbour(dst);
if (neigh->hh.hh_len) {
neigh_hh_bridge(&neigh->hh, skb);
skb->dev = nf_bridge->physindev;
diff --git a/net/core/dst.c b/net/core/dst.c
index 4aacc14..14b33baf 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -171,7 +171,7 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
dst_init_metrics(dst, dst_default_metrics, true);
dst->expires = 0UL;
dst->path = dst;
- dst->neighbour = NULL;
+ dst->_neighbour = NULL;
#ifdef CONFIG_XFRM
dst->xfrm = NULL;
#endif
@@ -229,11 +229,11 @@ struct dst_entry *dst_destroy(struct dst_entry * dst)
smp_rmb();
again:
- neigh = dst->neighbour;
+ neigh = dst->_neighbour;
child = dst->child;
if (neigh) {
- dst->neighbour = NULL;
+ dst->_neighbour = NULL;
neigh_release(neigh);
}
@@ -363,8 +363,8 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
dst->dev = dev_net(dst->dev)->loopback_dev;
dev_hold(dst->dev);
dev_put(dev);
- if (dst->neighbour && dst->neighbour->dev == dev) {
- dst->neighbour->dev = dst->dev;
+ if (dst->_neighbour && dst->_neighbour->dev == dev) {
+ dst->_neighbour->dev = dst->dev;
dev_hold(dst->dev);
dev_put(dev);
}
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index cefb8e5..8fab9b0 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1153,11 +1153,12 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
while (neigh->nud_state & NUD_VALID &&
(skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
- struct neighbour *n1 = neigh;
+ struct dst_entry *dst = skb_dst(skb);
+ struct neighbour *n2, *n1 = neigh;
write_unlock_bh(&neigh->lock);
/* On shaper/eql skb->dst->neighbour != neigh :( */
- if (skb_dst(skb) && skb_dst(skb)->neighbour)
- n1 = skb_dst(skb)->neighbour;
+ if (dst && (n2 = dst_get_neighbour(dst)) != NULL)
+ n1 = n2;
n1->output(n1, skb);
write_lock_bh(&neigh->lock);
}
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 5d61e89..0dc3fe6 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -202,7 +202,7 @@ static int dn_neigh_output_packet(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
struct dn_route *rt = (struct dn_route *)dst;
- struct neighbour *neigh = dst->neighbour;
+ struct neighbour *neigh = dst_get_neighbour(dst);
struct net_device *dev = neigh->dev;
char mac_addr[ETH_ALEN];
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 3b6400d..9bd45fc 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -241,9 +241,11 @@ static int dn_dst_gc(struct dst_ops *ops)
*/
static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu)
{
+ struct neighbour *n = dst_get_neighbour(dst);
u32 min_mtu = 230;
- struct dn_dev *dn = dst->neighbour ?
- rcu_dereference_raw(dst->neighbour->dev->dn_ptr) : NULL;
+ struct dn_dev *dn;
+
+ dn = n ? rcu_dereference_raw(n->dev->dn_ptr) : NULL;
if (dn && dn->use_long == 0)
min_mtu -= 6;
@@ -708,7 +710,7 @@ out:
static int dn_to_neigh_output(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
- struct neighbour *n = dst->neighbour;
+ struct neighbour *n = dst_get_neighbour(dst);
return n->output(n, skb);
}
@@ -723,7 +725,7 @@ static int dn_output(struct sk_buff *skb)
int err = -EINVAL;
- if ((neigh = dst->neighbour) == NULL)
+ if ((neigh = dst_get_neighbour(dst)) == NULL)
goto error;
skb->dev = dev;
@@ -840,11 +842,11 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
}
rt->rt_type = res->type;
- if (dev != NULL && rt->dst.neighbour == NULL) {
+ if (dev != NULL && dst_get_neighbour(&rt->dst) == NULL) {
n = __neigh_lookup_errno(&dn_neigh_table, &rt->rt_gateway, dev);
if (IS_ERR(n))
return PTR_ERR(n);
- rt->dst.neighbour = n;
+ dst_set_neighbour(&rt->dst, n);
}
if (dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu)
@@ -1151,7 +1153,7 @@ make_route:
rt->rt_dst_map = fld.daddr;
rt->rt_src_map = fld.saddr;
- rt->dst.neighbour = neigh;
+ dst_set_neighbour(&rt->dst, neigh);
neigh = NULL;
rt->dst.lastuse = jiffies;
@@ -1423,7 +1425,7 @@ make_route:
rt->fld.flowidn_iif = in_dev->ifindex;
rt->fld.flowidn_mark = fld.flowidn_mark;
- rt->dst.neighbour = neigh;
+ dst_set_neighbour(&rt->dst, neigh);
rt->dst.lastuse = jiffies;
rt->dst.output = dn_rt_bug;
switch (res.type) {
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 8871067..d7bb94c 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -731,9 +731,9 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
else if (skb->protocol == htons(ETH_P_IPV6)) {
+ struct neighbour *neigh = dst_get_neighbour(skb_dst(skb));
const struct in6_addr *addr6;
int addr_type;
- struct neighbour *neigh = skb_dst(skb)->neighbour;
if (neigh == NULL)
goto tx_error;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index db296a9..be27e60 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -204,7 +204,7 @@ static inline int ip_finish_output2(struct sk_buff *skb)
skb = skb2;
}
- neigh = dst->neighbour;
+ neigh = dst_get_neighbour(dst);
if (neigh)
return neigh_output(neigh, skb);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index bcf9bb5..1d4cd3b 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -412,8 +412,10 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
"HHUptod\tSpecDst");
else {
struct rtable *r = v;
+ struct neighbour *n;
int len;
+ n = dst_get_neighbour(&r->dst);
seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t"
"%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n",
r->dst.dev ? r->dst.dev->name : "*",
@@ -427,9 +429,7 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
dst_metric(&r->dst, RTAX_RTTVAR)),
r->rt_key_tos,
-1,
- (r->dst.neighbour &&
- (r->dst.neighbour->nud_state & NUD_CONNECTED)) ?
- 1 : 0,
+ (n && (n->nud_state & NUD_CONNECTED)) ? 1 : 0,
r->rt_spec_dst, &len);
seq_printf(seq, "%*s\n", 127 - len, "");
@@ -1026,7 +1026,7 @@ static int rt_bind_neighbour(struct rtable *rt)
n = ipv4_neigh_lookup(tbl, dev, nexthop);
if (IS_ERR(n))
return PTR_ERR(n);
- rt->dst.neighbour = n;
+ dst_set_neighbour(&rt->dst, n);
return 0;
}
@@ -1617,23 +1617,24 @@ static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
{
struct rtable *rt = (struct rtable *) dst;
__be32 orig_gw = rt->rt_gateway;
+ struct neighbour *n;
dst_confirm(&rt->dst);
- neigh_release(rt->dst.neighbour);
- rt->dst.neighbour = NULL;
+ neigh_release(dst_get_neighbour(&rt->dst));
+ dst_set_neighbour(&rt->dst, NULL);
rt->rt_gateway = peer->redirect_learned.a4;
- if (rt_bind_neighbour(rt) ||
- !(rt->dst.neighbour->nud_state & NUD_VALID)) {
- if (rt->dst.neighbour)
- neigh_event_send(rt->dst.neighbour, NULL);
+ rt_bind_neighbour(rt);
+ n = dst_get_neighbour(&rt->dst);
+ if (!n || !(n->nud_state & NUD_VALID)) {
+ if (n)
+ neigh_event_send(n, NULL);
rt->rt_gateway = orig_gw;
return -EAGAIN;
} else {
rt->rt_flags |= RTCF_REDIRECTED;
- call_netevent_notifiers(NETEVENT_NEIGH_UPDATE,
- rt->dst.neighbour);
+ call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
}
return 0;
}
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 48cd03d..a06c53c 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -656,7 +656,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
* layer address of our nexhop router
*/
- if (rt->dst.neighbour == NULL)
+ if (dst_get_neighbour(&rt->dst) == NULL)
ifa->flags &= ~IFA_F_OPTIMISTIC;
ifa->idev = idev;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 158df23..54a4678 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1455,7 +1455,7 @@ static int fib6_age(struct rt6_info *rt, void *arg)
RT6_TRACE("aging clone %p\n", rt);
return -1;
} else if ((rt->rt6i_flags & RTF_GATEWAY) &&
- (!(rt->dst.neighbour->flags & NTF_ROUTER))) {
+ (!(dst_get_neighbour(&rt->dst)->flags & NTF_ROUTER))) {
RT6_TRACE("purging route %p via non-router but gateway\n",
rt);
return -1;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index eb50bb0..8db0e48 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -135,7 +135,7 @@ static int ip6_finish_output2(struct sk_buff *skb)
skb->len);
}
- neigh = dst->neighbour;
+ neigh = dst_get_neighbour(dst);
if (neigh)
return neigh_output(neigh, skb);
@@ -385,6 +385,7 @@ int ip6_forward(struct sk_buff *skb)
struct ipv6hdr *hdr = ipv6_hdr(skb);
struct inet6_skb_parm *opt = IP6CB(skb);
struct net *net = dev_net(dst->dev);
+ struct neighbour *n;
u32 mtu;
if (net->ipv6.devconf_all->forwarding == 0)
@@ -459,11 +460,10 @@ int ip6_forward(struct sk_buff *skb)
send redirects to source routed frames.
We don't send redirects to frames decapsulated from IPsec.
*/
- if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0 &&
- !skb_sec_path(skb)) {
+ n = dst_get_neighbour(dst);
+ if (skb->dev == dst->dev && n && opt->srcrt == 0 && !skb_sec_path(skb)) {
struct in6_addr *target = NULL;
struct rt6_info *rt;
- struct neighbour *n = dst->neighbour;
/*
* incoming and outgoing devices are the same
@@ -920,8 +920,11 @@ out:
static int ip6_dst_lookup_tail(struct sock *sk,
struct dst_entry **dst, struct flowi6 *fl6)
{
- int err;
struct net *net = sock_net(sk);
+#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
+ struct neighbour *n;
+#endif
+ int err;
if (*dst == NULL)
*dst = ip6_route_output(net, sk, fl6);
@@ -947,7 +950,8 @@ static int ip6_dst_lookup_tail(struct sock *sk,
* dst entry and replace it instead with the
* dst entry of the nexthop router
*/
- if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) {
+ n = dst_get_neighbour(*dst);
+ if (n && !(n->nud_state & NUD_VALID)) {
struct inet6_ifaddr *ifp;
struct flowi6 fl_gw6;
int redirect;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index a997d41..9da6e02 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1238,7 +1238,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev);
if (rt)
- neigh = rt->dst.neighbour;
+ neigh = dst_get_neighbour(&rt->dst);
if (rt && lifetime == 0) {
neigh_clone(neigh);
@@ -1259,7 +1259,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
return;
}
- neigh = rt->dst.neighbour;
+ neigh = dst_get_neighbour(&rt->dst);
if (neigh == NULL) {
ND_PRINTK0(KERN_ERR
"ICMPv6 RA: %s() got default router without neighbour.\n",
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c1515a3..2998cb5 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -356,7 +356,7 @@ out:
#ifdef CONFIG_IPV6_ROUTER_PREF
static void rt6_probe(struct rt6_info *rt)
{
- struct neighbour *neigh = rt ? rt->dst.neighbour : NULL;
+ struct neighbour *neigh = rt ? dst_get_neighbour(&rt->dst) : NULL;
/*
* Okay, this does not seem to be appropriate
* for now, however, we need to check if it
@@ -404,7 +404,7 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif)
static inline int rt6_check_neigh(struct rt6_info *rt)
{
- struct neighbour *neigh = rt->dst.neighbour;
+ struct neighbour *neigh = dst_get_neighbour(&rt->dst);
int m;
if (rt->rt6i_flags & RTF_NONEXTHOP ||
!(rt->rt6i_flags & RTF_GATEWAY))
@@ -745,7 +745,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add
dst_free(&rt->dst);
return NULL;
}
- rt->dst.neighbour = neigh;
+ dst_set_neighbour(&rt->dst, neigh);
}
@@ -760,7 +760,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, const struct in6_a
rt->rt6i_dst.plen = 128;
rt->rt6i_flags |= RTF_CACHE;
rt->dst.flags |= DST_HOST;
- rt->dst.neighbour = neigh_clone(ort->dst.neighbour);
+ dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour(&ort->dst)));
}
return rt;
}
@@ -794,7 +794,7 @@ restart:
dst_hold(&rt->dst);
read_unlock_bh(&table->tb6_lock);
- if (!rt->dst.neighbour && !(rt->rt6i_flags & RTF_NONEXTHOP))
+ if (!dst_get_neighbour(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
else if (!(rt->dst.flags & DST_HOST))
nrt = rt6_alloc_clone(rt, &fl6->daddr);
@@ -1058,7 +1058,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
}
rt->rt6i_idev = idev;
- rt->dst.neighbour = neigh;
+ dst_set_neighbour(&rt->dst, neigh);
atomic_set(&rt->dst.__refcnt, 1);
dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
rt->dst.output = ip6_output;
@@ -1338,12 +1338,12 @@ int ip6_route_add(struct fib6_config *cfg)
rt->rt6i_prefsrc.plen = 0;
if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
- rt->dst.neighbour = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
- if (IS_ERR(rt->dst.neighbour)) {
- err = PTR_ERR(rt->dst.neighbour);
- rt->dst.neighbour = NULL;
+ struct neighbour *n = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
+ if (IS_ERR(n)) {
+ err = PTR_ERR(n);
goto out;
}
+ dst_set_neighbour(&rt->dst, n);
}
rt->rt6i_flags = cfg->fc_flags;
@@ -1574,7 +1574,7 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
dst_confirm(&rt->dst);
/* Duplicate redirect: silently ignore. */
- if (neigh == rt->dst.neighbour)
+ if (neigh == dst_get_neighbour(&rt->dst))
goto out;
nrt = ip6_rt_copy(rt);
@@ -1590,7 +1590,7 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
nrt->dst.flags |= DST_HOST;
ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
- nrt->dst.neighbour = neigh_clone(neigh);
+ dst_set_neighbour(&nrt->dst, neigh_clone(neigh));
if (ip6_ins_rt(nrt))
goto out;
@@ -1670,7 +1670,7 @@ again:
1. It is connected route. Action: COW
2. It is gatewayed route or NONEXTHOP route. Action: clone it.
*/
- if (!rt->dst.neighbour && !(rt->rt6i_flags & RTF_NONEXTHOP))
+ if (!dst_get_neighbour(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
nrt = rt6_alloc_cow(rt, daddr, saddr);
else
nrt = rt6_alloc_clone(rt, daddr);
@@ -2035,7 +2035,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
return ERR_CAST(neigh);
}
- rt->dst.neighbour = neigh;
+ dst_set_neighbour(&rt->dst, neigh);
ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
rt->rt6i_dst.plen = 128;
@@ -2400,8 +2400,8 @@ static int rt6_fill_node(struct net *net,
if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
goto nla_put_failure;
- if (rt->dst.neighbour)
- NLA_PUT(skb, RTA_GATEWAY, 16, &rt->dst.neighbour->primary_key);
+ if (dst_get_neighbour(&rt->dst))
+ NLA_PUT(skb, RTA_GATEWAY, 16, &dst_get_neighbour(&rt->dst)->primary_key);
if (rt->dst.dev)
NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex);
@@ -2585,6 +2585,7 @@ struct rt6_proc_arg
static int rt6_info_route(struct rt6_info *rt, void *p_arg)
{
struct seq_file *m = p_arg;
+ struct neighbour *n;
seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen);
@@ -2593,9 +2594,9 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
#else
seq_puts(m, "00000000000000000000000000000000 00 ");
#endif
-
- if (rt->dst.neighbour) {
- seq_printf(m, "%pi6", rt->dst.neighbour->primary_key);
+ n = dst_get_neighbour(&rt->dst);
+ if (n) {
+ seq_printf(m, "%pi6", n->primary_key);
} else {
seq_puts(m, "00000000000000000000000000000000");
}
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 1cca576..07bf108 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -677,7 +677,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
struct neighbour *neigh = NULL;
if (skb_dst(skb))
- neigh = skb_dst(skb)->neighbour;
+ neigh = dst_get_neighbour(skb_dst(skb));
if (neigh == NULL) {
if (net_ratelimit())
@@ -702,7 +702,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
struct neighbour *neigh = NULL;
if (skb_dst(skb))
- neigh = skb_dst(skb)->neighbour;
+ neigh = dst_get_neighbour(skb_dst(skb));
if (neigh == NULL) {
if (net_ratelimit())
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 45cd300..a3b7120 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -229,7 +229,7 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *
{
struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, 0);
struct teql_sched_data *q = qdisc_priv(dev_queue->qdisc);
- struct neighbour *mn = skb_dst(skb)->neighbour;
+ struct neighbour *mn = dst_get_neighbour(skb_dst(skb));
struct neighbour *n = q->ncache;
if (mn->tbl == NULL)
@@ -270,7 +270,7 @@ static inline int teql_resolve(struct sk_buff *skb,
if (dev->header_ops == NULL ||
skb_dst(skb) == NULL ||
- skb_dst(skb)->neighbour == NULL)
+ dst_get_neighbour(skb_dst(skb)) == NULL)
return 0;
return __teql_resolve(skb, skb_res, dev);
}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 5ce74a3..7803eb6 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1497,7 +1497,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
goto free_dst;
/* Copy neighbour for reachability confirmation */
- dst0->neighbour = neigh_clone(dst->neighbour);
+ dst_set_neighbour(dst0, neigh_clone(dst_get_neighbour(dst)));
xfrm_init_path((struct xfrm_dst *)dst0, dst, nfheader_len);
xfrm_init_pmtu(dst_prev);
--
1.7.6
^ permalink raw reply related
* [PATCH 41/45] bna: Ethtool Ring Param Set changes and Add Stats Attr
From: Rasesh Mody @ 2011-07-18 8:23 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- While setting the ring parameter restore the rx, vlan configuration and
set rx mode
- Added attributes to ethtool stats
- Indentation fix
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bnad.c | 10 ++--
drivers/net/bna/bnad.h | 6 +++
drivers/net/bna/bnad_ethtool.c | 97 ++++++++++++++++++++++++++++++++-------
3 files changed, 90 insertions(+), 23 deletions(-)
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index d4de429..6128045 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -2047,7 +2047,7 @@ bnad_rx_coalescing_timeo_set(struct bnad *bnad)
/*
* Called with bnad->bna_lock held
*/
-static int
+int
bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr)
{
int ret;
@@ -2067,7 +2067,7 @@ bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr)
}
/* Should be called with conf_lock held */
-static int
+int
bnad_enable_default_bcast(struct bnad *bnad)
{
struct bnad_rx_info *rx_info = &bnad->rx_info[0];
@@ -2092,8 +2092,8 @@ bnad_enable_default_bcast(struct bnad *bnad)
return 0;
}
-/* Called with bnad_conf_lock() held */
-static void
+/* Called with mutex_lock(&bnad->conf_mutex) held */
+void
bnad_restore_vlans(struct bnad *bnad, u32 rx_id)
{
u16 vlan_id;
@@ -2872,7 +2872,7 @@ bnad_tx_select_queue(struct net_device *netdev, struct sk_buff *skb)
return (u16)prio;
}
-static void
+void
bnad_set_rx_mode(struct net_device *netdev)
{
struct bnad *bnad = netdev_priv(netdev);
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index 02c6342..1f9bb56 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -344,6 +344,12 @@ extern u32 bnad_rxqs_per_cq;
*/
extern u32 *cna_get_firmware_buf(struct pci_dev *pdev);
/* Netdev entry point prototypes */
+extern void bnad_set_rx_mode(struct net_device *netdev);
+extern struct net_device_stats *bnad_get_netdev_stats(
+ struct net_device *netdev);
+extern int bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr);
+extern int bnad_enable_default_bcast(struct bnad *bnad);
+extern void bnad_restore_vlans(struct bnad *bnad, u32 rx_id);
extern void bnad_set_ethtool_ops(struct net_device *netdev);
/* Configuration & setup */
diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c
index 1c19dce..51fffdf 100644
--- a/drivers/net/bna/bnad_ethtool.c
+++ b/drivers/net/bna/bnad_ethtool.c
@@ -75,14 +75,25 @@ static char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
"tcpcsum_offload",
"udpcsum_offload",
"csum_help",
- "csum_help_err",
+ "tx_skb_too_short",
+ "tx_skb_stopping",
+ "tx_skb_max_vectors",
+ "tx_skb_mss_too_long",
+ "tx_skb_tso_too_short",
+ "tx_skb_tso_prepare",
+ "tx_skb_non_tso_too_long",
+ "tx_skb_tcp_hdr",
+ "tx_skb_udp_hdr",
+ "tx_skb_csum_err",
+ "tx_skb_headlen_too_long",
+ "tx_skb_headlen_zero",
+ "tx_skb_frag_zero",
+ "tx_skb_len_mismatch",
"hw_stats_updates",
- "netif_rx_schedule",
- "netif_rx_complete",
"netif_rx_dropped",
"link_toggle",
- "cee_up",
+ "cee_toggle",
"rxp_info_alloc_failed",
"mbox_intr_disabled",
@@ -201,6 +212,20 @@ static char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
"rad_rx_bcast_vlan",
"rad_rx_drops",
+ "rlb_rad_rx_frames",
+ "rlb_rad_rx_octets",
+ "rlb_rad_rx_vlan_frames",
+ "rlb_rad_rx_ucast",
+ "rlb_rad_rx_ucast_octets",
+ "rlb_rad_rx_ucast_vlan",
+ "rlb_rad_rx_mcast",
+ "rlb_rad_rx_mcast_octets",
+ "rlb_rad_rx_mcast_vlan",
+ "rlb_rad_rx_bcast",
+ "rlb_rad_rx_bcast_octets",
+ "rlb_rad_rx_bcast_vlan",
+ "rlb_rad_rx_drops",
+
"fc_rx_ucast_octets",
"fc_rx_ucast",
"fc_rx_ucast_vlan",
@@ -237,10 +262,10 @@ bnad_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
cmd->phy_address = 0;
if (netif_carrier_ok(netdev)) {
- ethtool_cmd_speed_set(cmd, SPEED_10000);
+ cmd->speed = SPEED_10000;
cmd->duplex = DUPLEX_FULL;
} else {
- ethtool_cmd_speed_set(cmd, -1);
+ cmd->speed = -1;
cmd->duplex = -1;
}
cmd->transceiver = XCVR_EXTERNAL;
@@ -255,8 +280,9 @@ bnad_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
{
/* 10G full duplex setting supported only */
if (cmd->autoneg == AUTONEG_ENABLE)
- return -EOPNOTSUPP; else {
- if ((ethtool_cmd_speed(cmd) == SPEED_10000)
+ return -EOPNOTSUPP;
+ else {
+ if ((cmd->speed == SPEED_10000)
&& (cmd->duplex == DUPLEX_FULL))
return 0;
}
@@ -321,7 +347,6 @@ bnad_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
{
struct bnad *bnad = netdev_priv(netdev);
unsigned long flags;
- int dim_timer_del = 0;
if (coalesce->rx_coalesce_usecs == 0 ||
coalesce->rx_coalesce_usecs >
@@ -348,14 +373,7 @@ bnad_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
} else {
if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) {
bnad->cfg_flags &= ~BNAD_CF_DIM_ENABLED;
- dim_timer_del = bnad_dim_timer_running(bnad);
- if (dim_timer_del) {
- clear_bit(BNAD_RF_DIM_TIMER_RUNNING,
- &bnad->run_flags);
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
- del_timer_sync(&bnad->dim_timer);
- spin_lock_irqsave(&bnad->bna_lock, flags);
- }
+ bnad_dim_timer_stop(bnad, flags);
bnad_rx_coalescing_timeo_set(bnad);
}
}
@@ -407,6 +425,7 @@ bnad_set_ringparam(struct net_device *netdev,
{
int i, current_err, err = 0;
struct bnad *bnad = netdev_priv(netdev);
+ unsigned long flags;
mutex_lock(&bnad->conf_mutex);
if (ringparam->rx_pending == bnad->rxq_depth &&
@@ -430,6 +449,11 @@ bnad_set_ringparam(struct net_device *netdev,
if (ringparam->rx_pending != bnad->rxq_depth) {
bnad->rxq_depth = ringparam->rx_pending;
+ if (!netif_running(netdev)) {
+ mutex_unlock(&bnad->conf_mutex);
+ return 0;
+ }
+
for (i = 0; i < bnad->num_rx; i++) {
if (!bnad->rx_info[i].rx)
continue;
@@ -437,10 +461,26 @@ bnad_set_ringparam(struct net_device *netdev,
current_err = bnad_setup_rx(bnad, i);
if (current_err && !err)
err = current_err;
+ if (!err)
+ bnad_restore_vlans(bnad, i);
+ }
+
+ if (!err && bnad->rx_info[0].rx) {
+ /* restore rx configuration */
+ bnad_enable_default_bcast(bnad);
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bnad_mac_addr_set_locked(bnad, netdev->dev_addr);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ bnad_set_rx_mode(netdev);
}
}
if (ringparam->tx_pending != bnad->txq_depth) {
bnad->txq_depth = ringparam->tx_pending;
+ if (!netif_running(netdev)) {
+ mutex_unlock(&bnad->conf_mutex);
+ return 0;
+ }
+
for (i = 0; i < bnad->num_tx; i++) {
if (!bnad->tx_info[i].tx)
continue;
@@ -578,6 +618,16 @@ bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
sprintf(string, "cq%d_hw_producer_index",
q_num);
string += ETH_GSTRING_LEN;
+ sprintf(string, "cq%d_intr", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "cq%d_poll", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "cq%d_schedule", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "cq%d_keep_poll", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "cq%d_complete", q_num);
+ string += ETH_GSTRING_LEN;
q_num++;
}
}
@@ -660,7 +710,7 @@ static int
bnad_get_stats_count_locked(struct net_device *netdev)
{
struct bnad *bnad = netdev_priv(netdev);
- int i, j, count, rxf_active_num = 0, txf_active_num = 0;
+ int i, j, count = 0, rxf_active_num = 0, txf_active_num = 0;
u32 bmap;
bmap = bna_tx_rid_mask(&bnad->bna);
@@ -718,6 +768,17 @@ bnad_per_q_stats_fill(struct bnad *bnad, u64 *buf, int bi)
buf[bi++] = 0; /* ccb->consumer_index */
buf[bi++] = *(bnad->rx_info[i].rx_ctrl[j].
ccb->hw_producer_index);
+
+ buf[bi++] = bnad->rx_info[i].
+ rx_ctrl[j].rx_intr_ctr;
+ buf[bi++] = bnad->rx_info[i].
+ rx_ctrl[j].rx_poll_ctr;
+ buf[bi++] = bnad->rx_info[i].
+ rx_ctrl[j].rx_schedule;
+ buf[bi++] = bnad->rx_info[i].
+ rx_ctrl[j].rx_keep_poll;
+ buf[bi++] = bnad->rx_info[i].
+ rx_ctrl[j].rx_complete;
}
}
for (i = 0; i < bnad->num_rx; i++) {
--
1.7.1
^ permalink raw reply related
* [PATCH 42/45] bna: PLL Init Fix and Add Stats Attributes
From: Rasesh Mody @ 2011-07-18 8:23 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- Fix to release soft reset in PLL init for HW
- Added Stats Attributes
- Removed some unused code
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_defs_cna.h | 8 +++++++-
drivers/net/bna/bfa_ioc.c | 19 ++++++-------------
drivers/net/bna/bfa_ioc.h | 12 ++----------
drivers/net/bna/bfa_ioc_ct.c | 9 ++++++++-
drivers/net/bna/bfi.h | 19 ++++++++++---------
5 files changed, 33 insertions(+), 34 deletions(-)
diff --git a/drivers/net/bna/bfa_defs_cna.h b/drivers/net/bna/bfa_defs_cna.h
index 7e0a918..8ab33ee 100644
--- a/drivers/net/bna/bfa_defs_cna.h
+++ b/drivers/net/bna/bfa_defs_cna.h
@@ -15,7 +15,6 @@
* All rights reserved
* www.brocade.com
*/
-
#ifndef __BFA_DEFS_CNA_H__
#define __BFA_DEFS_CNA_H__
@@ -55,6 +54,9 @@ struct bfa_port_fc_stats {
u64 bad_os_count; /*!< Invalid ordered sets */
u64 err_enc_out; /*!< Encoding err nonframe_8b10b */
u64 err_enc; /*!< Encoding err frame_8b10b */
+ u64 bbsc_frames_lost; /*!< Credit Recovery-Frames Lost */
+ u64 bbsc_credits_lost; /*!< Credit Recovery-Credits Lost */
+ u64 bbsc_link_resets; /*!< Credit Recovery-Link Resets */
};
/**
@@ -100,6 +102,10 @@ struct bfa_port_eth_stats {
u64 rx_fcoe_zero_pause; /*!< Rx FCoE zero pause */
u64 tx_fcoe_pause; /*!< Tx FCoE pause */
u64 tx_fcoe_zero_pause; /*!< Tx FCoE zero pause */
+ u64 rx_iscsi_pause; /*!< Rx iSCSI pause */
+ u64 rx_iscsi_zero_pause; /*!< Rx iSCSI zero pause */
+ u64 tx_iscsi_pause; /*!< Tx iSCSI pause */
+ u64 tx_iscsi_zero_pause; /*!< Tx iSCSI zero pause */
};
/**
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index b086cd7..36a040f 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -17,8 +17,6 @@
*/
#include "bfa_ioc.h"
-#include "cna.h"
-#include "bfi.h"
#include "bfi_reg.h"
#include "bfa_defs.h"
@@ -144,10 +142,6 @@ static struct bfa_sm_table ioc_sm_table[] = {
{BFA_SM(bfa_ioc_sm_acq_addr), BFA_IOC_ACQ_ADDR},
};
-/**
- * IOCPF state machine definitions/declarations
- */
-
/*
* Forward declareations for iocpf state machine
*/
@@ -362,7 +356,6 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
case IOC_E_FWRSP_ACQ_ADDR:
del_timer(&ioc->ioc_timer);
- ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_FAA_ACQ_ADDR);
bfa_ioc_hb_monitor(ioc);
bfa_fsm_set_state(ioc, bfa_ioc_sm_acq_addr);
break;
@@ -481,7 +474,7 @@ bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc)
}
/**
- * IOC is being desabled
+ * IOC is being disabled
*/
static void
bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
@@ -511,7 +504,7 @@ bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
}
/**
- * IOC desable completion entry.
+ * IOC disable completion entry.
*/
static void
bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc)
@@ -836,7 +829,7 @@ static void
bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf *iocpf)
{
iocpf->poll_time = 0;
- bfa_ioc_reset(iocpf->ioc, 0);
+ bfa_ioc_reset(iocpf->ioc, false);
}
/**
@@ -1825,6 +1818,9 @@ bfa_ioc_fail_notify(struct bfa_ioc *ioc)
bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
}
+/**
+ * IOCPF to IOC interface
+ */
static void
bfa_ioc_pf_enabled(struct bfa_ioc *ioc)
{
@@ -2372,9 +2368,6 @@ bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model)
ioc_attr = ioc->attr;
- /**
- * model name
- */
snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
BFA_MFG_NAME, ioc_attr->card_type);
}
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index 5b6cbbe..1195df5 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -152,16 +152,7 @@ struct bfa_ioc_notify {
};
/**
- * Heartbeat failure notification queue element.
- */
-struct bfa_ioc_hbfail_notify {
- struct list_head qe;
- bfa_ioc_hbfail_cbfn_t cbfn;
- void *cbarg;
-};
-
-/**
- * Initialize a heartbeat failure notification structure
+ * Initialize a IOC event notification structure
*/
#define bfa_ioc_notify_init(__notify, __cbfn, __cbarg) do { \
(__notify)->cbfn = (__cbfn); \
@@ -294,6 +285,7 @@ void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
void bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc);
void bfa_nw_ioc_set_ct2_hwif(struct bfa_ioc *ioc);
+void bfa_ioc_ct2_poweron(struct bfa_ioc *ioc);
void bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa,
struct bfa_ioc_cbfn *cbfn);
diff --git a/drivers/net/bna/bfa_ioc_ct.c b/drivers/net/bna/bfa_ioc_ct.c
index a615c15..43f382f 100644
--- a/drivers/net/bna/bfa_ioc_ct.c
+++ b/drivers/net/bna/bfa_ioc_ct.c
@@ -844,10 +844,17 @@ bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode asic_mode)
* release soft reset on s_clk & l_clk
*/
r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
- writel((r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET),
+ 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)) {
diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h
index 8dd8463..17522f3 100644
--- a/drivers/net/bna/bfi.h
+++ b/drivers/net/bna/bfi.h
@@ -181,16 +181,20 @@ enum bfi_mclass {
BFI_MC_SFP = 22, /*!< SFP module */
BFI_MC_MSGQ = 23, /*!< MSGQ */
BFI_MC_ENET = 24, /*!< ENET commands/responses */
- BFI_MC_MAX = 32
+ BFI_MC_PHY = 25, /*!< External PHY message class */
+ BFI_MC_NBOOT = 26, /*!< Network Boot */
+ BFI_MC_TIO_READ = 27, /*!< read IO (Target mode) */
+ BFI_MC_TIO_WRITE = 28, /*!< write IO (Target mode) */
+ BFI_MC_TIO_DATA_XFERED = 29, /*!< ds transferred (target mode) */
+ BFI_MC_TIO_IO = 30, /*!< IO (Target mode) */
+ BFI_MC_TIO = 31, /*!< IO (target mode) */
+ BFI_MC_MFG = 32, /*!< MFG/ASIC block commands */
+ BFI_MC_EDMA = 33, /*!< EDMA copy commands */
+ BFI_MC_MAX = 34
};
-#define BFI_IOC_MAX_CQS 4
-#define BFI_IOC_MAX_CQS_ASIC 8
#define BFI_IOC_MSGLEN_MAX 32 /* 32 bytes */
-#define BFI_BOOT_MEMTEST_RES_ADDR 0x900
-#define BFI_BOOT_MEMTEST_RES_SIG 0xA0A1A2A3
-
/**
*----------------------------------------------------------------------
* IOC
@@ -331,9 +335,6 @@ enum bfi_port_mode {
BFI_PORT_MODE_ETH = 2,
};
-/**
- * BFI_IOC_I2H_READY_EVENT message
- */
struct bfi_ioc_hbeat {
struct bfi_mhdr mh; /*!< common msg header */
u32 hb_count; /*!< current heart beat count */
--
1.7.1
^ permalink raw reply related
* [PATCH 4/4] net: Add ->neigh_lookup() operation to dst_ops
From: David Miller @ 2011-07-18 8:25 UTC (permalink / raw)
To: netdev
In the future dst entries will be neigh-less. In that environment we
need to have an easy transition point for current users of
dst->neighbour outside of the packet output fast path.
Signed-off-by: David S. Miller <davem@davemloft.net>
---
include/net/arp.h | 9 ---------
include/net/dst.h | 5 +++++
include/net/dst_ops.h | 1 +
net/bridge/br_netfilter.c | 6 ++++++
net/decnet/dn_route.c | 7 +++++++
net/ipv4/route.c | 26 +++++++++++++++++++-------
net/ipv6/route.c | 7 +++++++
net/xfrm/xfrm_policy.c | 7 +++++++
8 files changed, 52 insertions(+), 16 deletions(-)
diff --git a/include/net/arp.h b/include/net/arp.h
index 5e669e6..4979af8 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -38,15 +38,6 @@ static inline struct neighbour *__ipv4_neigh_lookup(struct neigh_table *tbl, str
return n;
}
-static inline struct neighbour *ipv4_neigh_lookup(struct neigh_table *tbl, struct net_device *dev, const __be32 *pkey)
-{
- struct neighbour *n = __ipv4_neigh_lookup(tbl, dev,
- *(__force u32 *)pkey);
- if (n)
- return n;
- return neigh_create(tbl, pkey, dev);
-}
-
extern void arp_init(void);
extern int arp_find(unsigned char *haddr, struct sk_buff *skb);
extern int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg);
diff --git a/include/net/dst.h b/include/net/dst.h
index 8147206..29e2557 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -387,6 +387,11 @@ static inline void dst_confirm(struct dst_entry *dst)
}
}
+static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
+{
+ return dst->ops->neigh_lookup(dst, daddr);
+}
+
static inline void dst_link_failure(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h
index dc07463..9adb998 100644
--- a/include/net/dst_ops.h
+++ b/include/net/dst_ops.h
@@ -26,6 +26,7 @@ struct dst_ops {
void (*link_failure)(struct sk_buff *);
void (*update_pmtu)(struct dst_entry *dst, u32 mtu);
int (*local_out)(struct sk_buff *skb);
+ struct neighbour * (*neigh_lookup)(const struct dst_entry *dst, const void *daddr);
struct kmem_cache *kmem_cachep;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index b1a5f97..d6ec372 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -109,11 +109,17 @@ static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old)
return NULL;
}
+static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst, const void *daddr)
+{
+ return NULL;
+}
+
static struct dst_ops fake_dst_ops = {
.family = AF_INET,
.protocol = cpu_to_be16(ETH_P_IP),
.update_pmtu = fake_update_pmtu,
.cow_metrics = fake_cow_metrics,
+ .neigh_lookup = fake_neigh_lookup,
};
/*
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 9bd45fc..43450c1 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -116,6 +116,7 @@ static void dn_dst_destroy(struct dst_entry *);
static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
static void dn_dst_link_failure(struct sk_buff *);
static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu);
+static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr);
static int dn_route_input(struct sk_buff *);
static void dn_run_flush(unsigned long dummy);
@@ -139,6 +140,7 @@ static struct dst_ops dn_dst_ops = {
.negative_advice = dn_dst_negative_advice,
.link_failure = dn_dst_link_failure,
.update_pmtu = dn_dst_update_pmtu,
+ .neigh_lookup = dn_dst_neigh_lookup,
};
static void dn_dst_destroy(struct dst_entry *dst)
@@ -827,6 +829,11 @@ static unsigned int dn_dst_default_mtu(const struct dst_entry *dst)
return dst->dev->mtu;
}
+static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
+{
+ return __neigh_lookup_errno(&dn_neigh_table, daddr, dst->dev);
+}
+
static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
{
struct dn_fib_info *fi = res->fi;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 1d4cd3b..3313730 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -185,6 +185,8 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old)
return p;
}
+static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr);
+
static struct dst_ops ipv4_dst_ops = {
.family = AF_INET,
.protocol = cpu_to_be16(ETH_P_IP),
@@ -199,6 +201,7 @@ static struct dst_ops ipv4_dst_ops = {
.link_failure = ipv4_link_failure,
.update_pmtu = ip_rt_update_pmtu,
.local_out = __ip_local_out,
+ .neigh_lookup = ipv4_neigh_lookup,
};
#define ECN_OR_COST(class) TC_PRIO_##class
@@ -1008,22 +1011,30 @@ static int slow_chain_length(const struct rtable *head)
return length >> FRACT_BITS;
}
-static int rt_bind_neighbour(struct rtable *rt)
+static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr)
{
- static const __be32 inaddr_any = 0;
- struct net_device *dev = rt->dst.dev;
struct neigh_table *tbl = &arp_tbl;
- const __be32 *nexthop;
+ static const __be32 inaddr_any = 0;
+ struct net_device *dev = dst->dev;
+ const __be32 *pkey = daddr;
struct neighbour *n;
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
if (dev->type == ARPHRD_ATM)
tbl = clip_tbl_hook;
#endif
- nexthop = &rt->rt_gateway;
if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
- nexthop = &inaddr_any;
- n = ipv4_neigh_lookup(tbl, dev, nexthop);
+ pkey = &inaddr_any;
+
+ n = __ipv4_neigh_lookup(tbl, dev, *(__force u32 *)pkey);
+ if (n)
+ return n;
+ return neigh_create(tbl, pkey, dev);
+}
+
+static int rt_bind_neighbour(struct rtable *rt)
+{
+ struct neighbour *n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
if (IS_ERR(n))
return PTR_ERR(n);
dst_set_neighbour(&rt->dst, n);
@@ -2734,6 +2745,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
.default_advmss = ipv4_default_advmss,
.update_pmtu = ipv4_rt_blackhole_update_pmtu,
.cow_metrics = ipv4_rt_blackhole_cow_metrics,
+ .neigh_lookup = ipv4_neigh_lookup,
};
struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 2998cb5..ddef80f 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -127,6 +127,11 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
return p;
}
+static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr)
+{
+ return __neigh_lookup_errno(&nd_tbl, daddr, dst->dev);
+}
+
static struct dst_ops ip6_dst_ops_template = {
.family = AF_INET6,
.protocol = cpu_to_be16(ETH_P_IPV6),
@@ -142,6 +147,7 @@ static struct dst_ops ip6_dst_ops_template = {
.link_failure = ip6_link_failure,
.update_pmtu = ip6_rt_update_pmtu,
.local_out = __ip6_local_out,
+ .neigh_lookup = ip6_neigh_lookup,
};
static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst)
@@ -168,6 +174,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
.default_advmss = ip6_default_advmss,
.update_pmtu = ip6_rt_blackhole_update_pmtu,
.cow_metrics = ip6_rt_blackhole_cow_metrics,
+ .neigh_lookup = ip6_neigh_lookup,
};
static const u32 ip6_template_metrics[RTAX_MAX] = {
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 7803eb6..94fdcc7 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2385,6 +2385,11 @@ static unsigned int xfrm_default_mtu(const struct dst_entry *dst)
return dst_mtu(dst->path);
}
+static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, const void *daddr)
+{
+ return dst_neigh_lookup(dst->path, daddr);
+}
+
int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
{
struct net *net;
@@ -2410,6 +2415,8 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
dst_ops->negative_advice = xfrm_negative_advice;
if (likely(dst_ops->link_failure == NULL))
dst_ops->link_failure = xfrm_link_failure;
+ if (likely(dst_ops->neigh_lookup == NULL))
+ dst_ops->neigh_lookup = xfrm_neigh_lookup;
if (likely(afinfo->garbage_collect == NULL))
afinfo->garbage_collect = __xfrm_garbage_collect;
xfrm_policy_afinfo[afinfo->family] = afinfo;
--
1.7.6
^ permalink raw reply related
* [PATCH 43/45] bna: Dropped BUG_ONs and Rx id init fix
From: Rasesh Mody @ 2011-07-18 8:23 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>
Change details:
- Removed some BUG_ONs and comments addition/cleanup
- Initializing rx_id to 0 for bnad_cleanup_rx
- Releasing all the locks while doing free_netdev
- Counting the Rx buffer allocation failures in bnad_alloc_n_post_rxbufs()
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bna_hw.h | 1 +
drivers/net/bna/bnad.c | 32 ++++++++++++++++++++------------
drivers/net/bna/bnad.h | 15 ++++++++-------
3 files changed, 29 insertions(+), 19 deletions(-)
diff --git a/drivers/net/bna/bna_hw.h b/drivers/net/bna/bna_hw.h
index 80b21ee..552e8b1 100644
--- a/drivers/net/bna/bna_hw.h
+++ b/drivers/net/bna/bna_hw.h
@@ -99,6 +99,7 @@
(_bna)->bits.error_status_bits = (__HFN_INT_ERR_MASK); \
(_bna)->bits.error_mask_bits = (__HFN_INT_ERR_MASK); \
(_bna)->bits.halt_status_bits = __HFN_INT_LL_HALT; \
+ (_bna)->bits.halt_mask_bits = __HFN_INT_LL_HALT; \
}
#define ct2_reg_addr_init(_bna, _pcidev) \
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 6128045..68cd328 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -408,6 +408,7 @@ bnad_alloc_n_post_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
rcb->rxq->buffer_size);
if (unlikely(!skb)) {
BNAD_UPDATE_CTR(bnad, rxbuf_alloc_failed);
+ rcb->rxq->rxbuf_alloc_failed++;
goto finishing;
}
unmap_array[unmap_prod].skb = skb;
@@ -1913,6 +1914,7 @@ bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
spin_unlock_irqrestore(&bnad->bna_lock, flags);
rx_info->rx = NULL;
+ rx_info->rx_id = 0;
bnad_rx_res_free(bnad, res_info);
}
@@ -1968,8 +1970,10 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
rx = bna_rx_create(&bnad->bna, bnad, rx_config, &rx_cbfn, res_info,
rx_info);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- if (!rx)
+ if (!rx) {
+ err = -ENOMEM;
goto err_return;
+ }
rx_info->rx = rx;
/*
@@ -2102,8 +2106,6 @@ bnad_restore_vlans(struct bnad *bnad, u32 rx_id)
if (!bnad->vlan_grp)
return;
- BUG_ON(!(VLAN_N_VID == (BFI_ENET_VLAN_ID_MAX + 1)));
-
for (vlan_id = 0; vlan_id < VLAN_N_VID; vlan_id++) {
if (!vlan_group_get_device(bnad->vlan_grp, vlan_id))
continue;
@@ -2214,9 +2216,6 @@ bnad_tso_prepare(struct bnad *bnad, struct sk_buff *skb)
{
int err;
- /* SKB_GSO_TCPV4 and SKB_GSO_TCPV6 is defined since 2.6.18. */
- BUG_ON(!(skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4 ||
- skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6));
if (skb_header_cloned(skb)) {
err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (err) {
@@ -2243,7 +2242,6 @@ bnad_tso_prepare(struct bnad *bnad, struct sk_buff *skb)
} else {
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
- BUG_ON(!(skb->protocol == htons(ETH_P_IPV6)));
ipv6h->payload_len = 0;
tcp_hdr(skb)->check =
~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, 0,
@@ -2583,7 +2581,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
unmap_q = tcb->unmap_q;
/*
* Takes care of the Tx that is scheduled between clearing the flag
- * and the netif_stop_all_queue() call.
+ * and the netif_tx_stop_all_queues() call.
*/
BNAD_DROP_AND_RETURN_IF(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags),
tx_skb_stopping);
@@ -2631,7 +2629,6 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
txq_prod = tcb->producer_index;
BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt, txqent, wi_range);
- BUG_ON(!(wi_range <= tcb->q_depth));
txqent->hdr.wi.reserved = 0;
txqent->hdr.wi.num_vectors = vectors;
@@ -2947,7 +2944,7 @@ unlock:
* conf_lock cannot be used since this call may be made
* in a non-blocking context.
*/
-static int
+int
bnad_set_mac_address(struct net_device *netdev, void *mac_addr)
{
int err;
@@ -3069,6 +3066,12 @@ bnad_netpoll(struct net_device *netdev)
bnad_isr(bnad->pcidev->irq, netdev);
bna_intx_enable(&bnad->bna, curr_mask);
} else {
+ /*
+ * Tx processing may happen in sending context, so no need
+ * to explicitly process completions here
+ */
+
+ /* Rx processing */
for (i = 0; i < bnad->num_rx; i++) {
rx_info = &bnad->rx_info[i];
if (!rx_info->rx)
@@ -3262,7 +3265,7 @@ static int __devinit
bnad_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pcidev_id)
{
- bool using_dac = false;
+ bool using_dac;
int err;
struct bnad *bnad;
struct bna *bna;
@@ -3385,6 +3388,11 @@ bnad_pci_probe(struct pci_dev *pdev,
bna_num_rxp_set(bna, BNAD_NUM_RXP + 1))
err = -EIO;
}
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ if (err)
+ goto disable_ioceth;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
bna_mod_res_req(&bnad->bna, &bnad->mod_res_info[0]);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -3436,9 +3444,9 @@ drv_uninit:
bnad_uninit(bnad);
pci_uninit:
bnad_pci_uninit(pdev);
+free_netdev:
mutex_unlock(&bnad->conf_mutex);
bnad_lock_uninit(bnad);
-free_netdev:
free_netdev(netdev);
return err;
}
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index 1f9bb56..6e14257 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -153,7 +153,6 @@ struct bnad_drv_stats {
u64 tcpcsum_offload;
u64 udpcsum_offload;
u64 csum_help;
- u64 csum_help_err;
u64 tx_skb_too_short;
u64 tx_skb_stopping;
u64 tx_skb_max_vectors;
@@ -170,13 +169,10 @@ struct bnad_drv_stats {
u64 tx_skb_len_mismatch;
u64 hw_stats_updates;
- u64 netif_rx_schedule;
- u64 netif_rx_complete;
u64 netif_rx_dropped;
u64 link_toggle;
u64 cee_toggle;
- u64 cee_up;
u64 rxp_info_alloc_failed;
u64 mbox_intr_disabled;
@@ -323,6 +319,8 @@ struct bnad {
struct tasklet_struct tx_free_tasklet;
+ u8 ref_count;
+
/* Statistics */
struct bnad_stats stats;
@@ -388,9 +386,12 @@ extern void bnad_netdev_hwstats_fill(struct bnad *bnad,
} \
}
-#define bnad_dim_timer_running(_bnad) \
- (((_bnad)->cfg_flags & BNAD_CF_DIM_ENABLED) && \
- (test_bit(BNAD_RF_DIM_TIMER_RUNNING, &((_bnad)->run_flags))))
+/*
+ * Stops the DIM timer
+ * Called with bnad->bna_lock held
+ * Implemented as macro, since we want to use
+ * the correct flags(on stack) while unlocking.
+ */
#define bnad_dim_timer_stop(_bnad, _flags) \
do { \
int to_del = 0; \
--
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