* Re: Help: major pppoe regression since 2.6.35 (panic on first ppp conection)?
From: Jarek Poplawski @ 2010-12-23 20:25 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Joel Soete, Andrew Morton, Linux Kernel, netdev
In-Reply-To: <1293106348.7789.5.camel@edumazet-laptop>
On Thu, Dec 23, 2010 at 01:12:28PM +0100, Eric Dumazet wrote:
> Le jeudi 23 décembre 2010 ?? 11:02 +0000, Joel Soete a écrit :
...
> > Sorry for delay but I have good news, I am sending this answer from:
> > $ uname -a
> > Linux sidh2 2.6.37-rc7-amd64-t1 #1 SMP Thu Dec 23 10:30:27 GMT 2010 x86_64 GNU/Linux
> >
> > with your tips ;<) (without kernel had already died)
> >
> > That said how can find stuff overflowing skb head? (all I say, is that this issue started with 2.6.34-git6???)
Hi Joel,
2.6.34-git6 or 7 is almost a whole netdev batch for 2.6.35 so still
a lot of guessing. One such guess could be e.g. this one:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=18e8c134f4e984e6639e62846345192816f06d5c
I've added to Eric's patch some debugging. After taking several
warnings (might a lot) revert this patch and apply Eric's again.
Btw, could you send your pppoe config (without any personal data,
of course), and mention if there are other changes like mtu etc.
> I am taking holidays right now for about 5 days, I guess someone else
> might find the bug before me ;)
Good job, Eric, we can try. Have a nice rest!
Thanks,
Jarek P.
--- (a debugging patch, apply to clean 2.6.37-rc)
drivers/net/pppoe.c | 8 ++++++++
include/linux/skbuff.h | 6 ++++++
net/core/dev.c | 8 ++++++++
net/core/skbuff.c | 9 +++++++++
4 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index d72fb05..0d41a04 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -385,6 +385,7 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
* can't change.
*/
+ DEBUG_SKB_POISON(skb);
if (sk->sk_state & PPPOX_BOUND) {
ppp_input(&po->chan, skb);
} else if (sk->sk_state & PPPOX_RELAY) {
@@ -430,6 +431,7 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
if (!skb)
goto out;
+ DEBUG_SKB_POISON(skb);
if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
goto drop;
@@ -452,6 +454,7 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
if (!po)
goto drop;
+ DEBUG_SKB_POISON(skb);
return sk_receive_skb(sk_pppox(po), skb, 0);
drop:
@@ -485,6 +488,7 @@ static int pppoe_disc_rcv(struct sk_buff *skb, struct net_device *dev,
if (ph->code != PADT_CODE)
goto abort;
+ DEBUG_SKB_POISON(skb);
pn = pppoe_pernet(dev_net(dev));
po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
if (po) {
@@ -888,6 +892,7 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock,
ph->length = htons(total_len);
+ DEBUG_SKB_POISON(skb);
dev_queue_xmit(skb);
end:
@@ -921,6 +926,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
if (!dev)
goto abort;
+ DEBUG_SKB_POISON(skb);
/* Copy the data if there is no space for the header or if it's
* read-only.
*/
@@ -943,6 +949,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
dev_hard_header(skb, dev, ETH_P_PPP_SES,
po->pppoe_pa.remote, NULL, data_len);
+ DEBUG_SKB_POISON(skb);
dev_queue_xmit(skb);
return 1;
@@ -987,6 +994,7 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
m->msg_namelen = 0;
if (skb) {
+ DEBUG_SKB_POISON(skb);
total_len = min_t(size_t, total_len, skb->len);
error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len);
if (error == 0)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index e6ba898..706f182 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -187,6 +187,12 @@ enum {
* the end of the header data, ie. at skb->end.
*/
struct skb_shared_info {
+#define SKB_POISON 0xe2e4e7e5
+#define SET_SKB_POISON(skb) skb_shinfo(skb)->poison = SKB_POISON
+#define DEBUG_SKB_POISON(skb) WARN_ON(skb_shinfo(skb)->poison != SKB_POISON)
+
+ unsigned int poison;
+ char filler[60];
unsigned short nr_frags;
unsigned short gso_size;
/* Warning: this field is not always filled in (UFO)! */
diff --git a/net/core/dev.c b/net/core/dev.c
index 0dd54a6..01ca7de 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1994,6 +1994,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
const struct net_device_ops *ops = dev->netdev_ops;
int rc = NETDEV_TX_OK;
+ DEBUG_SKB_POISON(skb);
if (likely(!skb->next)) {
if (!list_empty(&ptype_all))
dev_queue_xmit_nit(skb, dev);
@@ -2026,6 +2027,8 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
__skb_linearize(skb))
goto out_kfree_skb;
+ DEBUG_SKB_POISON(skb);
+
/* If packet is not checksummed and device does not
* support checksumming for this protocol, complete
* checksumming here.
@@ -2039,6 +2042,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
}
}
+ DEBUG_SKB_POISON(skb);
rc = ops->ndo_start_xmit(skb, dev);
trace_net_dev_xmit(skb, rc);
if (rc == NETDEV_TX_OK)
@@ -2243,6 +2247,7 @@ int dev_queue_xmit(struct sk_buff *skb)
struct Qdisc *q;
int rc = -ENOMEM;
+ DEBUG_SKB_POISON(skb);
/* Disable soft irqs for various locks below. Also
* stops preemption for RCU.
*/
@@ -2604,6 +2609,7 @@ int netif_rx(struct sk_buff *skb)
{
int ret;
+ DEBUG_SKB_POISON(skb);
/* if netpoll wants it, pretend we never saw it */
if (netpoll_rx(skb))
return NET_RX_DROP;
@@ -2898,6 +2904,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
int ret = NET_RX_DROP;
__be16 type;
+ DEBUG_SKB_POISON(skb);
if (!netdev_tstamp_prequeue)
net_timestamp_check(skb);
@@ -3043,6 +3050,7 @@ out:
*/
int netif_receive_skb(struct sk_buff *skb)
{
+ DEBUG_SKB_POISON(skb);
if (netdev_tstamp_prequeue)
net_timestamp_check(skb);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 104f844..b112c7d 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -210,6 +210,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
shinfo = skb_shinfo(skb);
memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
atomic_set(&shinfo->dataref, 1);
+ SET_SKB_POISON(skb);
if (fclone) {
struct sk_buff *child = skb + 1;
@@ -412,6 +413,7 @@ static void skb_release_all(struct sk_buff *skb)
void __kfree_skb(struct sk_buff *skb)
{
+ DEBUG_SKB_POISON(skb);
skb_release_all(skb);
kfree_skbmem(skb);
}
@@ -428,6 +430,7 @@ void kfree_skb(struct sk_buff *skb)
{
if (unlikely(!skb))
return;
+ DEBUG_SKB_POISON(skb);
if (likely(atomic_read(&skb->users) == 1))
smp_rmb();
else if (likely(!atomic_dec_and_test(&skb->users)))
@@ -449,6 +452,7 @@ void consume_skb(struct sk_buff *skb)
{
if (unlikely(!skb))
return;
+ DEBUG_SKB_POISON(skb);
if (likely(atomic_read(&skb->users) == 1))
smp_rmb();
else if (likely(!atomic_dec_and_test(&skb->users)))
@@ -487,11 +491,13 @@ bool skb_recycle_check(struct sk_buff *skb, int skb_size)
if (skb_shared(skb) || skb_cloned(skb))
return false;
+ DEBUG_SKB_POISON(skb);
skb_release_head_state(skb);
shinfo = skb_shinfo(skb);
memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
atomic_set(&shinfo->dataref, 1);
+ SET_SKB_POISON(skb);
memset(skb, 0, offsetof(struct sk_buff, tail));
skb->data = skb->head + NET_SKB_PAD;
@@ -571,6 +577,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
atomic_inc(&(skb_shinfo(skb)->dataref));
skb->cloned = 1;
+ DEBUG_SKB_POISON(skb);
return n;
#undef C
@@ -772,6 +779,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
bool fastpath;
BUG_ON(nhead < 0);
+ DEBUG_SKB_POISON(skb);
if (skb_shared(skb))
BUG();
@@ -836,6 +844,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
skb->hdr_len = 0;
skb->nohdr = 0;
atomic_set(&skb_shinfo(skb)->dataref, 1);
+ SET_SKB_POISON(skb);
return 0;
nodata:
^ permalink raw reply related
* Re: [PATCH net-next-2.6 1/2] can: add driver for Softing card
From: Oliver Hartkopp @ 2010-12-23 20:33 UTC (permalink / raw)
To: Marc Kleine-Budde, Kurt Van Dijck; +Cc: socketcan-core, netdev
In-Reply-To: <4D135BC3.6070707@pengutronix.de>
Hello Kurt,
thanks for the effort to make this driver available in Mainline!
>> +
>> +MODULE_DESCRIPTION("socketcan softing driver");
MODULE_DESCRIPTION("Softing CAN driver");
MODULE_DESCRIPTION("Softing DPRAM CAN driver");
???
>> diff --git a/drivers/net/can/softing/softing_platform.h b/drivers/net/can/softing/softing_platform.h
>> new file mode 100644
>> index 0000000..9ff69a1
>> --- /dev/null
>> +++ b/drivers/net/can/softing/softing_platform.h
Shouldn't this file be placed in include/linux/can/platform/softing.h ??
Regards,
Oliver
^ permalink raw reply
* Re: [PATCH net-2.6] net_sched: always clone skbs
From: Jarek Poplawski @ 2010-12-23 23:04 UTC (permalink / raw)
To: jamal; +Cc: Changli Gao, Eric Dumazet, David S. Miller, netdev,
Pawel Staszewski
In-Reply-To: <1293111333.11306.170.camel@mojatatu>
On Thu, Dec 23, 2010 at 08:35:33AM -0500, jamal wrote:
> On Tue, 2010-12-21 at 23:37 +0100, Jarek Poplawski wrote:
>
> > Actually, when dumb isn't a good principle? ;->
> >
> > Speaking about wrong things like optimizing this 1st commandment: it
> > seems, if we're stealing not shared skb it's not unreasonable to tell
> > others not to touch it anymore, and skip kfree_skb() in handle_ing(),
> > unless I miss something?
>
> I dont know how much cycles it will save you vs the code you add
> but it is not unreasonable. Of course it would mean we are moving
> beyond KISSes[1] now Jarek;->
Hmm... seeing all those multiqued multiques I thought everybody was
beyond, but no problem, let's go back to KISSes[2] ;-)
> > > In order to make my trick work. We need to assure dev_queue_xmit() and
> > > dev_hard_start_xmit() accept shared skbs. As Eric pointed, pktgen also
> > > need dev->netdev_ops->ndo_start_xmit() accept shared skbs. We need to
> > > fix every ndo_start_xmit() one by one, then dev_hard_start_xmit(), and
> > > when dev_queue_xmit() is also fixed, my trick can be added back.
> > > :)
> >
> > I'm not sure pktgen is right - even if it's safe in its case, it seems
> > to break some older rules, and drivers should really own the things.
> > So it needs reviewing first.
>
> The idea we always try to keep is that the caller is responsible for the
> fate of the skb it sent. The callee will do things like make a copy or
> clone if it needed to make changes or keep the skb. Same should be
> expected of a driver.
Well, I'm not sure we talk about the same thing. I mean e.g. the
comment above dev_queue_xmit(); the caller passes all control to the
callee here.
Cheers,
Jarek P.
> [1] Jarek - so you dont misunderstand this as an overture - it means
> Keep It Simple Silly (or the principle of dumb we talked about) ;->
OK, I can remember the seventies too ;-)
^ permalink raw reply
* [PATCH 1/1] netfilter: ebtables: make broute table work again
From: Florian Westphal @ 2010-12-24 0:27 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev, netfilter-devel, Florian Westphal
broute table init hook sets up the "br_should_route_hook" pointer,
which then gets called from br_input.
commit a386f99025f13b32502fe5dedf223c20d7283826
(bridge: add proper RCU annotation to should_route_hook)
introduced a typedef, and then changed this to:
br_should_route_hook_t *rhook;
[..]
rhook = rcu_dereference(br_should_route_hook);
if (*rhook(skb))
problem is that "br_should_route_hook" contains the address of the function,
so calling *rhook() results in kernel panic.
Can't simply use "if (rhook(skb)", because br_should_route_hook_t *rhook
is not a function.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/linux/if_bridge.h | 2 +-
net/bridge/br_input.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index f7e73c3..dd3f201 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -103,7 +103,7 @@ struct __fdb_entry {
extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
-typedef int (*br_should_route_hook_t)(struct sk_buff *skb);
+typedef int br_should_route_hook_t(struct sk_buff *skb);
extern br_should_route_hook_t __rcu *br_should_route_hook;
#endif
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 6f6d8e1..1d677bf 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -178,7 +178,7 @@ forward:
case BR_STATE_FORWARDING:
rhook = rcu_dereference(br_should_route_hook);
if (rhook) {
- if ((*rhook)(skb))
+ if (rhook(skb))
return skb;
dest = eth_hdr(skb)->h_dest;
}
--
1.7.2.2
^ permalink raw reply related
* Re: [PATCH 1/1] netfilter: ebtables: make broute table work again
From: Changli Gao @ 2010-12-24 0:47 UTC (permalink / raw)
To: Florian Westphal; +Cc: eric.dumazet, netdev, netfilter-devel
In-Reply-To: <1293150436-12092-1-git-send-email-fw@strlen.de>
On Fri, Dec 24, 2010 at 8:27 AM, Florian Westphal <fw@strlen.de> wrote:
> broute table init hook sets up the "br_should_route_hook" pointer,
> which then gets called from br_input.
>
> commit a386f99025f13b32502fe5dedf223c20d7283826
> (bridge: add proper RCU annotation to should_route_hook)
> introduced a typedef, and then changed this to:
>
> br_should_route_hook_t *rhook;
> [..]
> rhook = rcu_dereference(br_should_route_hook);
> if (*rhook(skb))
>
> problem is that "br_should_route_hook" contains the address of the function,
> so calling *rhook() results in kernel panic.
>
> Can't simply use "if (rhook(skb)", because br_should_route_hook_t *rhook
> is not a function.
>
> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
>
> include/linux/if_bridge.h | 2 +-
> net/bridge/br_input.c | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
> index f7e73c3..dd3f201 100644
> --- a/include/linux/if_bridge.h
> +++ b/include/linux/if_bridge.h
> @@ -103,7 +103,7 @@ struct __fdb_entry {
>
> extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
>
> -typedef int (*br_should_route_hook_t)(struct sk_buff *skb);
> +typedef int br_should_route_hook_t(struct sk_buff *skb);
> extern br_should_route_hook_t __rcu *br_should_route_hook;
>
> #endif
> diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
> index 6f6d8e1..1d677bf 100644
> --- a/net/bridge/br_input.c
> +++ b/net/bridge/br_input.c
> @@ -178,7 +178,7 @@ forward:
> case BR_STATE_FORWARDING:
> rhook = rcu_dereference(br_should_route_hook);
> if (rhook) {
> - if ((*rhook)(skb))
> + if (rhook(skb))
I don't think this change is necessary. Would you like to remove this
change and test again?
> return skb;
> dest = eth_hdr(skb)->h_dest;
> }
--
Regards,
Changli Gao(xiaosuo@gmail.com)
^ permalink raw reply
* Re: [PATCH 1/1] netfilter: ebtables: make broute table work again
From: Florian Westphal @ 2010-12-24 0:55 UTC (permalink / raw)
To: Changli Gao; +Cc: eric.dumazet, netdev, netfilter-devel
In-Reply-To: <AANLkTikgoc6xzx-0xn4cXsVuWVETOG1=dpE_1kZKBVnM@mail.gmail.com>
Changli Gao <xiaosuo@gmail.com> wrote:
> > diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
> > index 6f6d8e1..1d677bf 100644
> > --- a/net/bridge/br_input.c
> > +++ b/net/bridge/br_input.c
> > @@ -178,7 +178,7 @@ forward:
> > case BR_STATE_FORWARDING:
> > rhook = rcu_dereference(br_should_route_hook);
> > if (rhook) {
> > - if ((*rhook)(skb))
> > + if (rhook(skb))
>
> I don't think this change is necessary. Would you like to remove this
> change and test again?
Its not needed, but i consider it less confusing.
I do not have a strong preference, though.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] smsc911x: add disable and re-enable Rx int to de-assert interrupt pin
From: Jason Wang @ 2010-12-24 2:18 UTC (permalink / raw)
To: David Miller; +Cc: jason77.wang, netdev, steve.glendinning, linux-omap
In-Reply-To: <20101223.095917.59696176.davem@davemloft.net>
David Miller wrote:
> From: Jason Wang <jason77.wang@gmail.com>
> Date: Thu, 23 Dec 2010 18:43:13 +0800
>
>
>> When kernel enters irqhanlder, it will check the Rx interrupt status
>> bit, if Rx status is set but can't call napi_schedule(), it will do
>> nothing and directly return form irqhandler. This situation is prone
>> to be produced when we repeatly call irqhandler through netpoll
>> interface(i.e kgdboe connecting).
>>
>> This is a potential risk for those level triggered platforms(i.e
>> ti_omap3evm), because if we don't handle Rx int and just return from
>> irqhandler, the irq pin will be keeping asserted, the level triggered
>> platforms will have no chance to jump out from the Rx irq. The whole
>> system will hung into the irq subsystem.
>>
>> To solve it, we add a disable/re-enable Rx int operation for this
>> situation, this operation can de-assert interrupt pin for this time
>> and will leave the received data and status in the FIFO for later
>> interrupts to handle.
>>
>> Signed-off-by: Jason Wang <jason77.wang@gmail.com>
>>
>
>
Hi David,
Thanks for your comments.
> You absolutely cannot do this.
>
> You now can race with the NAPI completion code turning the RX
> interrupts back on, and you'll leave the chip with RX interrupts
> disabled.
>
I think my modification almost have the same execution path as the
original design and don't produce the race condition with NAPI threads.
The original design is:
If (can call napi_schedule) {
disable rx int;
call napi_schedule()
} else {
keep rx int enabled;
return;
}
my modification is:
disable rx int;
if (can call napi_schedule) {
call napi_schedule();
} else {
re-enable rx int; // this will de-assert interrupt pin for this time
return;
}
So my modification is: if we can call napi_schedule(), we will disable
the rx int until the NAPI thread re-enable it. if we can't call
napi_schedule(), the rx int will keep enabled. This logic is almost same
as the original design. I can't figure out why original design is safe
while my modification is risky.
Add more info:
the Freescale imx31pdk, imx51pdk and ti_omap3evm boards all use this
driver, before apply this modification, their kgdboe connecting is not
stable. After applied this patch, their nfs root is as good as before
and their kgdboe connecting is stable.
Thanks,
Jason.
> You must solve your level triggered interrupt some other way, every
> NAPI based device must manage the interrupt disabling carefully and
> only when the napi POLL is successfully scheduled in order to avoid
> races.
>
> And especially you must not make a crazy hack like this for obscure
> things like kgdboe.
>
>
^ permalink raw reply
* [PATCH net-next 1/2] bnx2: Free IRQ before freeing status block memory
From: Michael Chan @ 2010-12-24 2:21 UTC (permalink / raw)
To: davem; +Cc: netdev
When changing ring size, we free all memory including status block
memory. If we're in INTA mode and sharing IRQ, the IRQ handler can
be called and it will reference the NULL status block pointer.
Because of the lockless design of the IRQ handler, there is no simple
way to synchronize and prevent this. So we avoid this problem by
freeing the IRQ handler before freeing the status block memory.
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
drivers/net/bnx2.c | 13 ++++++++++++-
1 files changed, 12 insertions(+), 1 deletions(-)
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 6fa7984..44aed3b 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -6096,7 +6096,7 @@ bnx2_request_irq(struct bnx2 *bp)
}
static void
-bnx2_free_irq(struct bnx2 *bp)
+__bnx2_free_irq(struct bnx2 *bp)
{
struct bnx2_irq *irq;
int i;
@@ -6107,6 +6107,13 @@ bnx2_free_irq(struct bnx2 *bp)
free_irq(irq->vector, &bp->bnx2_napi[i]);
irq->requested = 0;
}
+}
+
+static void
+bnx2_free_irq(struct bnx2 *bp)
+{
+
+ __bnx2_free_irq(bp);
if (bp->flags & BNX2_FLAG_USING_MSI)
pci_disable_msi(bp->pdev);
else if (bp->flags & BNX2_FLAG_USING_MSIX)
@@ -7092,6 +7099,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
bnx2_netif_stop(bp, true);
bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
+ __bnx2_free_irq(bp);
bnx2_free_skbs(bp);
bnx2_free_mem(bp);
}
@@ -7104,6 +7112,9 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
rc = bnx2_alloc_mem(bp);
if (!rc)
+ rc = bnx2_request_irq(bp);
+
+ if (!rc)
rc = bnx2_init_nic(bp, 0);
if (rc) {
--
1.6.4.GIT
^ permalink raw reply related
* [patch] skfp: testing the wrong variable in skfp_driver_init()
From: Dan Carpenter @ 2010-12-24 5:17 UTC (permalink / raw)
To: netdev
Cc: Jiri Pirko, Eric Dumazet, H Hartley Sweeten, David S. Miller,
kernel-janitors
The intent here was to test if the allocation failed but we tested
"SharedMemSize" instead of "SharedMemAddr" by mistake.
Signed-off-by: Dan Carpenter <error27@gmail.com>
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index 0a66fed..16c6265 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -412,7 +412,7 @@ static int skfp_driver_init(struct net_device *dev)
bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev,
bp->SharedMemSize,
&bp->SharedMemDMA);
- if (!bp->SharedMemSize) {
+ if (!bp->SharedMemAddr) {
printk("could not allocate mem for ");
printk("hardware module: %ld byte\n",
bp->SharedMemSize);
^ permalink raw reply related
* [patch] vxge: remove duplicated part of check
From: Dan Carpenter @ 2010-12-24 6:15 UTC (permalink / raw)
To: Ramkrishna Vepa
Cc: Sivakumar Subramani, Sreenivasa Honnur, Jon Mason, netdev,
kernel-janitors
This is just a cleanup to make the static checkers happy. We don't need
to check "own" twice.
Signed-off-by: Dan Carpenter <error27@gmail.com>
diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c
index 42cc298..4c10d6c 100644
--- a/drivers/net/vxge/vxge-traffic.c
+++ b/drivers/net/vxge/vxge-traffic.c
@@ -1240,7 +1240,7 @@ enum vxge_hw_status vxge_hw_ring_rxd_next_completed(
*t_code = (u8)VXGE_HW_RING_RXD_T_CODE_GET(control_0);
/* check whether it is not the end */
- if (!own || ((*t_code == VXGE_HW_RING_T_CODE_FRM_DROP) && own)) {
+ if (!own || *t_code == VXGE_HW_RING_T_CODE_FRM_DROP) {
vxge_assert(((struct vxge_hw_ring_rxd_1 *)rxdp)->host_control !=
0);
^ permalink raw reply related
* [PATCH 00/10] bna: Update Brocade BNA Ethernet driver to v2.3.2.3
From: Rasesh Mody @ 2010-12-24 7:45 UTC (permalink / raw)
To: netdev; +Cc: huangj, Rasesh Mody
The following patch set updates the Brocade BNA driver to v2.3.2.3.
The patches are generated, compiled and tested against net-next-2.6 (2.6.37-rc1).
Rasesh Mody (10):
bna: TxRx and datapath fix
bna: Port enable disable sync and txq priority fix
bna: Fix ethtool register dump and reordered an API
bna: Enable pure priority tagged packet reception and rxf uninit
cleanup fix
bna: Fix for TX queue
bna: IOC uninit check and misc cleanup
bna: Removed unused code
bna: Restore VLAN filter table
bna: IOC failure auto recovery fix
bna: Update the driver version to 2.3.2.3
drivers/net/bna/bfa_defs.h | 22 +-
drivers/net/bna/bfa_defs_mfg_comm.h | 22 -
drivers/net/bna/bfa_ioc.c | 1219 +++++++++++++++++++++++++----------
drivers/net/bna/bfa_ioc.h | 49 +-
drivers/net/bna/bfa_ioc_ct.c | 102 +++-
drivers/net/bna/bfi_ctreg.h | 41 +-
drivers/net/bna/bna.h | 6 +-
drivers/net/bna/bna_ctrl.c | 377 +++--------
drivers/net/bna/bna_txrx.c | 44 +-
drivers/net/bna/bna_types.h | 11 +-
drivers/net/bna/bnad.c | 427 +++++++------
drivers/net/bna/bnad.h | 31 +-
drivers/net/bna/bnad_ethtool.c | 8 +-
13 files changed, 1439 insertions(+), 920 deletions(-)
^ permalink raw reply
* [PATCH 01/10] bna: TxRx and datapath fix
From: Rasesh Mody @ 2010-12-24 7:45 UTC (permalink / raw)
To: netdev; +Cc: huangj, Rasesh Mody, Debashis Dutt
In-Reply-To: <1293176710-21335-1-git-send-email-rmody@brocade.com>
Change Details:
- Check HW ready condition before accessing h/w register in data-path
- Postpone clean-up of data buffers to the data-path restart path and
wait in the cleanup routines for in-flight DMA to complete
- Separate out Tx completion processing from Rx poll routine
Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bnad.c | 353 ++++++++++++++++++++++-------------------------
drivers/net/bna/bnad.h | 22 ++--
2 files changed, 178 insertions(+), 197 deletions(-)
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 7e839b9..3c40502 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -70,6 +70,8 @@ do { \
(sizeof(struct bnad_skb_unmap) * ((_depth) - 1)); \
} while (0)
+#define BNAD_TXRX_SYNC_MDELAY 250 /* 250 msecs */
+
/*
* Reinitialize completions in CQ, once Rx is taken down
*/
@@ -130,7 +132,9 @@ bnad_free_all_txbufs(struct bnad *bnad,
PCI_DMA_TODEVICE);
pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
- unmap_cons++;
+ if (++unmap_cons >= unmap_q->q_depth)
+ break;
+
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
pci_unmap_page(bnad->pcidev,
pci_unmap_addr(&unmap_array[unmap_cons],
@@ -139,7 +143,8 @@ bnad_free_all_txbufs(struct bnad *bnad,
PCI_DMA_TODEVICE);
pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
0);
- unmap_cons++;
+ if (++unmap_cons >= unmap_q->q_depth)
+ break;
}
dev_kfree_skb_any(skb);
}
@@ -167,11 +172,11 @@ bnad_free_txbufs(struct bnad *bnad,
/*
* Just return if TX is stopped. This check is useful
* when bnad_free_txbufs() runs out of a tasklet scheduled
- * before bnad_cb_tx_cleanup() cleared BNAD_RF_TX_STARTED bit
+ * before bnad_cb_tx_cleanup() cleared BNAD_TXQ_TX_STARTED bit
* but this routine runs actually after the cleanup has been
* executed.
*/
- if (!test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))
+ if (!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
return 0;
updated_hw_cons = *(tcb->hw_consumer_index);
@@ -252,7 +257,9 @@ bnad_tx_free_tasklet(unsigned long bnad_ptr)
(!test_and_set_bit(BNAD_TXQ_FREE_SENT,
&tcb->flags))) {
acked = bnad_free_txbufs(bnad, tcb);
- bna_ib_ack(tcb->i_dbell, acked);
+ if (likely(test_bit(BNAD_TXQ_TX_STARTED,
+ &tcb->flags)))
+ bna_ib_ack(tcb->i_dbell, acked);
smp_mb__before_clear_bit();
clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
}
@@ -264,7 +271,7 @@ static u32
bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
{
struct net_device *netdev = bnad->netdev;
- u32 sent;
+ u32 sent = 0;
if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
return 0;
@@ -275,12 +282,15 @@ bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
netif_carrier_ok(netdev) &&
BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
BNAD_NETIF_WAKE_THRESHOLD) {
- netif_wake_queue(netdev);
- BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+ if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) {
+ netif_wake_queue(netdev);
+ BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+ }
}
+ }
+
+ if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
bna_ib_ack(tcb->i_dbell, sent);
- } else
- bna_ib_ack(tcb->i_dbell, 0);
smp_mb__before_clear_bit();
clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
@@ -313,25 +323,26 @@ bnad_reset_rcb(struct bnad *bnad, struct bna_rcb *rcb)
}
static void
-bnad_free_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
+bnad_free_all_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
{
struct bnad_unmap_q *unmap_q;
struct sk_buff *skb;
+ int unmap_cons;
unmap_q = rcb->unmap_q;
- while (BNA_QE_IN_USE_CNT(unmap_q, unmap_q->q_depth)) {
- skb = unmap_q->unmap_array[unmap_q->consumer_index].skb;
- BUG_ON(!(skb));
- unmap_q->unmap_array[unmap_q->consumer_index].skb = NULL;
+ for (unmap_cons = 0; unmap_cons < unmap_q->q_depth; unmap_cons++) {
+ skb = unmap_q->unmap_array[unmap_cons].skb;
+ if (!skb)
+ continue;
+ BUG_ON(!(pci_unmap_addr(
+ &unmap_q->unmap_array[unmap_cons], dma_addr)));
+ unmap_q->unmap_array[unmap_cons].skb = NULL;
pci_unmap_single(bnad->pcidev, pci_unmap_addr(&unmap_q->
- unmap_array[unmap_q->consumer_index],
- dma_addr), rcb->rxq->buffer_size +
- NET_IP_ALIGN, PCI_DMA_FROMDEVICE);
+ unmap_array[unmap_cons],
+ dma_addr), rcb->rxq->buffer_size,
+ PCI_DMA_FROMDEVICE);
dev_kfree_skb(skb);
- BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth);
- BNA_QE_INDX_ADD(rcb->consumer_index, 1, rcb->q_depth);
}
-
bnad_reset_rcb(bnad, rcb);
}
@@ -385,41 +396,9 @@ finishing:
unmap_q->producer_index = unmap_prod;
rcb->producer_index = unmap_prod;
smp_mb();
- bna_rxq_prod_indx_doorbell(rcb);
- }
-}
-
-/*
- * Locking is required in the enable path
- * because it is called from a napi poll
- * context, where the bna_lock is not held
- * unlike the IRQ context.
- */
-static void
-bnad_enable_txrx_irqs(struct bnad *bnad)
-{
- struct bna_tcb *tcb;
- struct bna_ccb *ccb;
- int i, j;
- unsigned long flags;
-
- spin_lock_irqsave(&bnad->bna_lock, flags);
- for (i = 0; i < bnad->num_tx; i++) {
- for (j = 0; j < bnad->num_txq_per_tx; j++) {
- tcb = bnad->tx_info[i].tcb[j];
- bna_ib_coalescing_timer_set(tcb->i_dbell,
- tcb->txq->ib->ib_config.coalescing_timeo);
- bna_ib_ack(tcb->i_dbell, 0);
- }
- }
-
- for (i = 0; i < bnad->num_rx; i++) {
- for (j = 0; j < bnad->num_rxp_per_rx; j++) {
- ccb = bnad->rx_info[i].rx_ctrl[j].ccb;
- bnad_enable_rx_irq_unsafe(ccb);
- }
+ if (likely(test_bit(BNAD_RXQ_STARTED, &rcb->flags)))
+ bna_rxq_prod_indx_doorbell(rcb);
}
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
}
static inline void
@@ -448,6 +427,9 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
u32 qid0 = ccb->rcb[0]->rxq->rxq_id;
struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
+ if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))
+ return 0;
+
prefetch(bnad->netdev);
BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl,
wi_range);
@@ -544,12 +526,15 @@ next:
BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
if (likely(ccb)) {
- bna_ib_ack(ccb->i_dbell, packets);
+ if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
+ bna_ib_ack(ccb->i_dbell, packets);
bnad_refill_rxq(bnad, ccb->rcb[0]);
if (ccb->rcb[1])
bnad_refill_rxq(bnad, ccb->rcb[1]);
- } else
- bna_ib_ack(ccb->i_dbell, 0);
+ } else {
+ if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
+ bna_ib_ack(ccb->i_dbell, 0);
+ }
return packets;
}
@@ -557,6 +542,9 @@ next:
static void
bnad_disable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
{
+ if (unlikely(!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
+ return;
+
bna_ib_coalescing_timer_set(ccb->i_dbell, 0);
bna_ib_ack(ccb->i_dbell, 0);
}
@@ -575,9 +563,11 @@ static void
bnad_netif_rx_schedule_poll(struct bnad *bnad, struct bna_ccb *ccb)
{
struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl);
- if (likely(napi_schedule_prep((&rx_ctrl->napi)))) {
+ struct napi_struct *napi = &rx_ctrl->napi;
+
+ if (likely(napi_schedule_prep(napi))) {
bnad_disable_rx_irq(bnad, ccb);
- __napi_schedule((&rx_ctrl->napi));
+ __napi_schedule(napi);
}
BNAD_UPDATE_CTR(bnad, netif_rx_schedule);
}
@@ -602,12 +592,11 @@ bnad_msix_mbox_handler(int irq, void *data)
{
u32 intr_status;
unsigned long flags;
- struct net_device *netdev = data;
- struct bnad *bnad;
+ struct bnad *bnad = (struct bnad *)data;
- bnad = netdev_priv(netdev);
+ if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
+ return IRQ_HANDLED;
- /* BNA_ISR_GET(bnad); Inc Ref count */
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_intr_status_get(&bnad->bna, intr_status);
@@ -617,7 +606,6 @@ bnad_msix_mbox_handler(int irq, void *data)
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- /* BNAD_ISR_PUT(bnad); Dec Ref count */
return IRQ_HANDLED;
}
@@ -627,8 +615,7 @@ bnad_isr(int irq, void *data)
int i, j;
u32 intr_status;
unsigned long flags;
- struct net_device *netdev = data;
- struct bnad *bnad = netdev_priv(netdev);
+ struct bnad *bnad = (struct bnad *)data;
struct bnad_rx_info *rx_info;
struct bnad_rx_ctrl *rx_ctrl;
@@ -642,16 +629,21 @@ bnad_isr(int irq, void *data)
spin_lock_irqsave(&bnad->bna_lock, flags);
- if (BNA_IS_MBOX_ERR_INTR(intr_status)) {
+ if (BNA_IS_MBOX_ERR_INTR(intr_status))
bna_mbox_handler(&bnad->bna, intr_status);
- if (!BNA_IS_INTX_DATA_INTR(intr_status)) {
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
- goto done;
- }
- }
+
spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ if (!BNA_IS_INTX_DATA_INTR(intr_status))
+ return IRQ_HANDLED;
+
/* Process data interrupts */
+ /* Tx processing */
+ for (i = 0; i < bnad->num_tx; i++) {
+ for (j = 0; j < bnad->num_txq_per_tx; j++)
+ bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
+ }
+ /* Rx processing */
for (i = 0; i < bnad->num_rx; i++) {
rx_info = &bnad->rx_info[i];
if (!rx_info->rx)
@@ -663,7 +655,6 @@ bnad_isr(int irq, void *data)
rx_ctrl->ccb);
}
}
-done:
return IRQ_HANDLED;
}
@@ -674,11 +665,7 @@ done:
static void
bnad_enable_mbox_irq(struct bnad *bnad)
{
- int irq = BNAD_GET_MBOX_IRQ(bnad);
-
- if (test_and_clear_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))
- if (bnad->cfg_flags & BNAD_CF_MSIX)
- enable_irq(irq);
+ clear_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
BNAD_UPDATE_CTR(bnad, mbox_intr_enabled);
}
@@ -690,14 +677,19 @@ bnad_enable_mbox_irq(struct bnad *bnad)
static void
bnad_disable_mbox_irq(struct bnad *bnad)
{
- int irq = BNAD_GET_MBOX_IRQ(bnad);
+ set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
+ BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
+}
- if (!test_and_set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))
- if (bnad->cfg_flags & BNAD_CF_MSIX)
- disable_irq_nosync(irq);
+static void
+bnad_set_netdev_perm_addr(struct bnad *bnad)
+{
+ struct net_device *netdev = bnad->netdev;
- BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
+ memcpy(netdev->perm_addr, &bnad->perm_addr, netdev->addr_len);
+ if (is_zero_ether_addr(netdev->dev_addr))
+ memcpy(netdev->dev_addr, &bnad->perm_addr, netdev->addr_len);
}
/* Control Path Handlers */
@@ -755,11 +747,14 @@ bnad_cb_port_link_status(struct bnad *bnad,
if (link_up) {
if (!netif_carrier_ok(bnad->netdev)) {
+ struct bna_tcb *tcb = bnad->tx_info[0].tcb[0];
+ if (!tcb)
+ return;
pr_warn("bna: %s link up\n",
bnad->netdev->name);
netif_carrier_on(bnad->netdev);
BNAD_UPDATE_CTR(bnad, link_toggle);
- if (test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags)) {
+ if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) {
/* Force an immediate Transmit Schedule */
pr_info("bna: %s TX_STARTED\n",
bnad->netdev->name);
@@ -807,6 +802,18 @@ bnad_cb_tcb_destroy(struct bnad *bnad, struct bna_tcb *tcb)
{
struct bnad_tx_info *tx_info =
(struct bnad_tx_info *)tcb->txq->tx->priv;
+ struct bnad_unmap_q *unmap_q = tcb->unmap_q;
+
+ while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
+ cpu_relax();
+
+ bnad_free_all_txbufs(bnad, tcb);
+
+ unmap_q->producer_index = 0;
+ unmap_q->consumer_index = 0;
+
+ smp_mb__before_clear_bit();
+ clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
tx_info->tcb[tcb->id] = NULL;
}
@@ -822,6 +829,12 @@ bnad_cb_rcb_setup(struct bnad *bnad, struct bna_rcb *rcb)
}
static void
+bnad_cb_rcb_destroy(struct bnad *bnad, struct bna_rcb *rcb)
+{
+ bnad_free_all_rxbufs(bnad, rcb);
+}
+
+static void
bnad_cb_ccb_setup(struct bnad *bnad, struct bna_ccb *ccb)
{
struct bnad_rx_info *rx_info =
@@ -849,7 +862,7 @@ bnad_cb_tx_stall(struct bnad *bnad, struct bna_tcb *tcb)
if (tx_info != &bnad->tx_info[0])
return;
- clear_bit(BNAD_RF_TX_STARTED, &bnad->run_flags);
+ clear_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
netif_stop_queue(bnad->netdev);
pr_info("bna: %s TX_STOPPED\n", bnad->netdev->name);
}
@@ -857,30 +870,15 @@ bnad_cb_tx_stall(struct bnad *bnad, struct bna_tcb *tcb)
static void
bnad_cb_tx_resume(struct bnad *bnad, struct bna_tcb *tcb)
{
- if (test_and_set_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))
- return;
-
- if (netif_carrier_ok(bnad->netdev)) {
- pr_info("bna: %s TX_STARTED\n", bnad->netdev->name);
- netif_wake_queue(bnad->netdev);
- BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
- }
-}
-
-static void
-bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
-{
- struct bnad_unmap_q *unmap_q;
+ struct bnad_unmap_q *unmap_q = tcb->unmap_q;
- if (!tcb || (!tcb->unmap_q))
+ if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
return;
- unmap_q = tcb->unmap_q;
- if (!unmap_q->unmap_array)
- return;
+ clear_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags);
- if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
- return;
+ while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
+ cpu_relax();
bnad_free_all_txbufs(bnad, tcb);
@@ -889,21 +887,45 @@ bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
smp_mb__before_clear_bit();
clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+
+ /*
+ * Workaround for first device enable failure & we
+ * get a 0 MAC address. We try to get the MAC address
+ * again here.
+ */
+ if (is_zero_ether_addr(&bnad->perm_addr.mac[0])) {
+ bna_port_mac_get(&bnad->bna.port, &bnad->perm_addr);
+ bnad_set_netdev_perm_addr(bnad);
+ }
+
+ set_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
+
+ if (netif_carrier_ok(bnad->netdev)) {
+ pr_info("bna: %s TX_STARTED\n", bnad->netdev->name);
+ netif_wake_queue(bnad->netdev);
+ BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+ }
+}
+
+static void
+bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
+{
+ /* Delay only once for the whole Tx Path Shutdown */
+ if (!test_and_set_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags))
+ mdelay(BNAD_TXRX_SYNC_MDELAY);
}
static void
bnad_cb_rx_cleanup(struct bnad *bnad,
struct bna_ccb *ccb)
{
- bnad_cq_cmpl_init(bnad, ccb);
-
- bnad_free_rxbufs(bnad, ccb->rcb[0]);
clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags);
- if (ccb->rcb[1]) {
- bnad_free_rxbufs(bnad, ccb->rcb[1]);
+ if (ccb->rcb[1])
clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags);
- }
+
+ if (!test_and_set_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags))
+ mdelay(BNAD_TXRX_SYNC_MDELAY);
}
static void
@@ -911,6 +933,13 @@ bnad_cb_rx_post(struct bnad *bnad, struct bna_rcb *rcb)
{
struct bnad_unmap_q *unmap_q = rcb->unmap_q;
+ clear_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags);
+
+ if (rcb == rcb->cq->ccb->rcb[0])
+ bnad_cq_cmpl_init(bnad, rcb->cq->ccb);
+
+ bnad_free_all_rxbufs(bnad, rcb);
+
set_bit(BNAD_RXQ_STARTED, &rcb->flags);
/* Now allocate & post buffers for this RCB */
@@ -1047,7 +1076,7 @@ bnad_mbox_irq_free(struct bnad *bnad,
spin_unlock_irqrestore(&bnad->bna_lock, flags);
irq = BNAD_GET_MBOX_IRQ(bnad);
- free_irq(irq, bnad->netdev);
+ free_irq(irq, bnad);
kfree(intr_info->idl);
}
@@ -1061,7 +1090,7 @@ static int
bnad_mbox_irq_alloc(struct bnad *bnad,
struct bna_intr_info *intr_info)
{
- int err;
+ int err = 0;
unsigned long flags;
u32 irq;
irq_handler_t irq_handler;
@@ -1096,22 +1125,17 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
*/
set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
+ BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
+
err = request_irq(irq, irq_handler, flags,
- bnad->mbox_irq_name, bnad->netdev);
+ bnad->mbox_irq_name, bnad);
if (err) {
kfree(intr_info->idl);
intr_info->idl = NULL;
- return err;
}
- spin_lock_irqsave(&bnad->bna_lock, flags);
-
- if (bnad->cfg_flags & BNAD_CF_MSIX)
- disable_irq_nosync(irq);
-
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
- return 0;
+ return err;
}
static void
@@ -1555,62 +1579,19 @@ poll_exit:
return rcvd;
}
-static int
-bnad_napi_poll_txrx(struct napi_struct *napi, int budget)
-{
- struct bnad_rx_ctrl *rx_ctrl =
- container_of(napi, struct bnad_rx_ctrl, napi);
- struct bna_ccb *ccb;
- struct bnad *bnad;
- int rcvd = 0;
- int i, j;
-
- ccb = rx_ctrl->ccb;
-
- bnad = ccb->bnad;
-
- if (!netif_carrier_ok(bnad->netdev))
- goto poll_exit;
-
- /* Handle Tx Completions, if any */
- for (i = 0; i < bnad->num_tx; i++) {
- for (j = 0; j < bnad->num_txq_per_tx; j++)
- bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
- }
-
- /* Handle Rx Completions */
- rcvd = bnad_poll_cq(bnad, ccb, budget);
- if (rcvd == budget)
- return rcvd;
-poll_exit:
- napi_complete((napi));
-
- BNAD_UPDATE_CTR(bnad, netif_rx_complete);
-
- bnad_enable_txrx_irqs(bnad);
- return rcvd;
-}
-
static void
bnad_napi_enable(struct bnad *bnad, u32 rx_id)
{
- int (*napi_poll) (struct napi_struct *, int);
struct bnad_rx_ctrl *rx_ctrl;
int i;
- unsigned long flags;
-
- spin_lock_irqsave(&bnad->bna_lock, flags);
- if (bnad->cfg_flags & BNAD_CF_MSIX)
- napi_poll = bnad_napi_poll_rx;
- else
- napi_poll = bnad_napi_poll_txrx;
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
/* Initialize & enable NAPI */
for (i = 0; i < bnad->num_rxp_per_rx; i++) {
rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i];
+
netif_napi_add(bnad->netdev, &rx_ctrl->napi,
- napi_poll, 64);
+ bnad_napi_poll_rx, 64);
+
napi_enable(&rx_ctrl->napi);
}
}
@@ -1825,6 +1806,7 @@ bnad_setup_rx(struct bnad *bnad, uint rx_id)
/* Initialize the Rx event handlers */
rx_cbfn.rcb_setup_cbfn = bnad_cb_rcb_setup;
+ rx_cbfn.rcb_destroy_cbfn = bnad_cb_rcb_destroy;
rx_cbfn.rcb_destroy_cbfn = NULL;
rx_cbfn.ccb_setup_cbfn = bnad_cb_ccb_setup;
rx_cbfn.ccb_destroy_cbfn = bnad_cb_ccb_destroy;
@@ -2152,16 +2134,6 @@ bnad_q_num_adjust(struct bnad *bnad, int msix_vectors)
bnad->num_rxp_per_rx = 1;
}
-static void
-bnad_set_netdev_perm_addr(struct bnad *bnad)
-{
- struct net_device *netdev = bnad->netdev;
-
- memcpy(netdev->perm_addr, &bnad->perm_addr, netdev->addr_len);
- if (is_zero_ether_addr(netdev->dev_addr))
- memcpy(netdev->dev_addr, &bnad->perm_addr, netdev->addr_len);
-}
-
/* Enable / disable device */
static void
bnad_device_disable(struct bnad *bnad)
@@ -2433,21 +2405,21 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}
+ tx_id = 0;
+
+ tx_info = &bnad->tx_info[tx_id];
+ tcb = tx_info->tcb[tx_id];
+ unmap_q = tcb->unmap_q;
+
/*
* Takes care of the Tx that is scheduled between clearing the flag
* and the netif_stop_queue() call.
*/
- if (unlikely(!test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))) {
+ if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) {
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
- tx_id = 0;
-
- tx_info = &bnad->tx_info[tx_id];
- tcb = tx_info->tcb[tx_id];
- unmap_q = tcb->unmap_q;
-
vectors = 1 + skb_shinfo(skb)->nr_frags;
if (vectors > BFI_TX_MAX_VECTORS_PER_PKT) {
dev_kfree_skb(skb);
@@ -2462,7 +2434,8 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
tcb->consumer_index &&
!test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
acked = bnad_free_txbufs(bnad, tcb);
- bna_ib_ack(tcb->i_dbell, acked);
+ if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
+ bna_ib_ack(tcb->i_dbell, acked);
smp_mb__before_clear_bit();
clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
} else {
@@ -2624,6 +2597,10 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
tcb->producer_index = txq_prod;
smp_mb();
+
+ if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
+ return NETDEV_TX_OK;
+
bna_txq_prod_indx_doorbell(tcb);
if ((u16) (*tcb->hw_consumer_index) != tcb->consumer_index)
@@ -3066,7 +3043,7 @@ bnad_pci_probe(struct pci_dev *pdev,
/*
* PCI initialization
* Output : using_dac = 1 for 64 bit DMA
- * = 0 for 32 bit DMA
+ * = 0 for 32 bit DMA
*/
err = bnad_pci_init(bnad, pdev, &using_dac);
if (err)
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index ebc3a90..f59685a 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -51,6 +51,7 @@
*/
struct bnad_rx_ctrl {
struct bna_ccb *ccb;
+ unsigned long flags;
struct napi_struct napi;
};
@@ -82,6 +83,7 @@ struct bnad_rx_ctrl {
/* Bit positions for tcb->flags */
#define BNAD_TXQ_FREE_SENT 0
+#define BNAD_TXQ_TX_STARTED 1
/* Bit positions for rcb->flags */
#define BNAD_RXQ_REFILL 0
@@ -199,12 +201,12 @@ struct bnad_unmap_q {
/* Set, tested & cleared using xxx_bit() functions */
/* Values indicated bit positions */
#define BNAD_RF_CEE_RUNNING 1
-#define BNAD_RF_HW_ERROR 2
-#define BNAD_RF_MBOX_IRQ_DISABLED 3
-#define BNAD_RF_TX_STARTED 4
-#define BNAD_RF_RX_STARTED 5
-#define BNAD_RF_DIM_TIMER_RUNNING 6
-#define BNAD_RF_STATS_TIMER_RUNNING 7
+#define BNAD_RF_MBOX_IRQ_DISABLED 2
+#define BNAD_RF_RX_STARTED 3
+#define BNAD_RF_DIM_TIMER_RUNNING 4
+#define BNAD_RF_STATS_TIMER_RUNNING 5
+#define BNAD_RF_TX_SHUTDOWN_DELAYED 6
+#define BNAD_RF_RX_SHUTDOWN_DELAYED 7
struct bnad {
struct net_device *netdev;
@@ -320,9 +322,11 @@ extern void bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64
#define bnad_enable_rx_irq_unsafe(_ccb) \
{ \
- bna_ib_coalescing_timer_set((_ccb)->i_dbell, \
- (_ccb)->rx_coalescing_timeo); \
- bna_ib_ack((_ccb)->i_dbell, 0); \
+ if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))) {\
+ bna_ib_coalescing_timer_set((_ccb)->i_dbell, \
+ (_ccb)->rx_coalescing_timeo); \
+ bna_ib_ack((_ccb)->i_dbell, 0); \
+ } \
}
#define bnad_dim_timer_running(_bnad) \
--
1.7.1
^ permalink raw reply related
* [PATCH 02/10] bna: Port enable disable sync and txq priority fix
From: Rasesh Mody @ 2010-12-24 7:45 UTC (permalink / raw)
To: netdev; +Cc: huangj, Rasesh Mody, Debashis Dutt
In-Reply-To: <1293176710-21335-1-git-send-email-rmody@brocade.com>
Change Details:
- Fixed port enable/disable sync through a change in LL port state
machine
- Change txq->priority masking to 0x7 (3 bits) from 0x3 (2 bits)
Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bna.h | 4 +-
drivers/net/bna/bna_ctrl.c | 136 +++++++++++++++++++++++++++++++++----------
drivers/net/bna/bna_txrx.c | 8 +-
drivers/net/bna/bna_types.h | 7 +-
4 files changed, 116 insertions(+), 39 deletions(-)
diff --git a/drivers/net/bna/bna.h b/drivers/net/bna/bna.h
index df6676b..fd93f76 100644
--- a/drivers/net/bna/bna.h
+++ b/drivers/net/bna/bna.h
@@ -390,8 +390,8 @@ void bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe);
/* API for RX */
int bna_port_mtu_get(struct bna_port *port);
-void bna_llport_admin_up(struct bna_llport *llport);
-void bna_llport_admin_down(struct bna_llport *llport);
+void bna_llport_rx_started(struct bna_llport *llport);
+void bna_llport_rx_stopped(struct bna_llport *llport);
/* API for BNAD */
void bna_port_enable(struct bna_port *port);
diff --git a/drivers/net/bna/bna_ctrl.c b/drivers/net/bna/bna_ctrl.c
index 07b2659..68e4c5e 100644
--- a/drivers/net/bna/bna_ctrl.c
+++ b/drivers/net/bna/bna_ctrl.c
@@ -59,14 +59,70 @@ bna_port_cb_link_down(struct bna_port *port, int status)
port->link_cbfn(port->bna->bnad, BNA_LINK_DOWN);
}
+static inline int
+llport_can_be_up(struct bna_llport *llport)
+{
+ int ready = 0;
+ if (llport->type == BNA_PORT_T_REGULAR)
+ ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) &&
+ (llport->flags & BNA_LLPORT_F_RX_STARTED) &&
+ (llport->flags & BNA_LLPORT_F_PORT_ENABLED));
+ else
+ ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) &&
+ (llport->flags & BNA_LLPORT_F_RX_STARTED) &&
+ !(llport->flags & BNA_LLPORT_F_PORT_ENABLED));
+ return ready;
+}
+
+#define llport_is_up llport_can_be_up
+
+enum bna_llport_event {
+ LLPORT_E_START = 1,
+ LLPORT_E_STOP = 2,
+ LLPORT_E_FAIL = 3,
+ LLPORT_E_UP = 4,
+ LLPORT_E_DOWN = 5,
+ LLPORT_E_FWRESP_UP_OK = 6,
+ LLPORT_E_FWRESP_UP_FAIL = 7,
+ LLPORT_E_FWRESP_DOWN = 8
+};
+
+static void
+bna_llport_cb_port_enabled(struct bna_llport *llport)
+{
+ llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
+
+ if (llport_can_be_up(llport))
+ bfa_fsm_send_event(llport, LLPORT_E_UP);
+}
+
+static void
+bna_llport_cb_port_disabled(struct bna_llport *llport)
+{
+ int llport_up = llport_is_up(llport);
+
+ llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
+
+ if (llport_up)
+ bfa_fsm_send_event(llport, LLPORT_E_DOWN);
+}
+
/**
* MBOX
*/
static int
bna_is_aen(u8 msg_id)
{
- return msg_id == BFI_LL_I2H_LINK_DOWN_AEN ||
- msg_id == BFI_LL_I2H_LINK_UP_AEN;
+ switch (msg_id) {
+ case BFI_LL_I2H_LINK_DOWN_AEN:
+ case BFI_LL_I2H_LINK_UP_AEN:
+ case BFI_LL_I2H_PORT_ENABLE_AEN:
+ case BFI_LL_I2H_PORT_DISABLE_AEN:
+ return 1;
+
+ default:
+ return 0;
+ }
}
static void
@@ -81,6 +137,12 @@ bna_mbox_aen_callback(struct bna *bna, struct bfi_mbmsg *msg)
case BFI_LL_I2H_LINK_DOWN_AEN:
bna_port_cb_link_down(&bna->port, aen->reason);
break;
+ case BFI_LL_I2H_PORT_ENABLE_AEN:
+ bna_llport_cb_port_enabled(&bna->port.llport);
+ break;
+ case BFI_LL_I2H_PORT_DISABLE_AEN:
+ bna_llport_cb_port_disabled(&bna->port.llport);
+ break;
default:
break;
}
@@ -251,16 +313,6 @@ static void bna_llport_start(struct bna_llport *llport);
static void bna_llport_stop(struct bna_llport *llport);
static void bna_llport_fail(struct bna_llport *llport);
-enum bna_llport_event {
- LLPORT_E_START = 1,
- LLPORT_E_STOP = 2,
- LLPORT_E_FAIL = 3,
- LLPORT_E_UP = 4,
- LLPORT_E_DOWN = 5,
- LLPORT_E_FWRESP_UP = 6,
- LLPORT_E_FWRESP_DOWN = 7
-};
-
enum bna_llport_state {
BNA_LLPORT_STOPPED = 1,
BNA_LLPORT_DOWN = 2,
@@ -320,7 +372,7 @@ bna_llport_sm_stopped(struct bna_llport *llport,
/* No-op */
break;
- case LLPORT_E_FWRESP_UP:
+ case LLPORT_E_FWRESP_UP_OK:
case LLPORT_E_FWRESP_DOWN:
/**
* These events are received due to flushing of mbox when
@@ -366,6 +418,7 @@ bna_llport_sm_down(struct bna_llport *llport,
static void
bna_llport_sm_up_resp_wait_entry(struct bna_llport *llport)
{
+ BUG_ON(!llport_can_be_up(llport));
/**
* NOTE: Do not call bna_fw_llport_up() here. That will over step
* mbox due to down_resp_wait -> up_resp_wait transition on event
@@ -390,10 +443,14 @@ bna_llport_sm_up_resp_wait(struct bna_llport *llport,
bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait);
break;
- case LLPORT_E_FWRESP_UP:
+ case LLPORT_E_FWRESP_UP_OK:
bfa_fsm_set_state(llport, bna_llport_sm_up);
break;
+ case LLPORT_E_FWRESP_UP_FAIL:
+ bfa_fsm_set_state(llport, bna_llport_sm_down);
+ break;
+
case LLPORT_E_FWRESP_DOWN:
/* down_resp_wait -> up_resp_wait transition on LLPORT_E_UP */
bna_fw_llport_up(llport);
@@ -431,11 +488,12 @@ bna_llport_sm_down_resp_wait(struct bna_llport *llport,
bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait);
break;
- case LLPORT_E_FWRESP_UP:
+ case LLPORT_E_FWRESP_UP_OK:
/* up_resp_wait->down_resp_wait transition on LLPORT_E_DOWN */
bna_fw_llport_down(llport);
break;
+ case LLPORT_E_FWRESP_UP_FAIL:
case LLPORT_E_FWRESP_DOWN:
bfa_fsm_set_state(llport, bna_llport_sm_down);
break;
@@ -496,11 +554,12 @@ bna_llport_sm_last_resp_wait(struct bna_llport *llport,
/* No-op */
break;
- case LLPORT_E_FWRESP_UP:
+ case LLPORT_E_FWRESP_UP_OK:
/* up_resp_wait->last_resp_wait transition on LLPORT_T_STOP */
bna_fw_llport_down(llport);
break;
+ case LLPORT_E_FWRESP_UP_FAIL:
case LLPORT_E_FWRESP_DOWN:
bfa_fsm_set_state(llport, bna_llport_sm_stopped);
break;
@@ -541,7 +600,14 @@ bna_fw_cb_llport_up(void *arg, int status)
struct bna_llport *llport = (struct bna_llport *)arg;
bfa_q_qe_init(&llport->mbox_qe.qe);
- bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP);
+ if (status == BFI_LL_CMD_FAIL) {
+ if (llport->type == BNA_PORT_T_REGULAR)
+ llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
+ else
+ llport->flags &= ~BNA_LLPORT_F_ADMIN_UP;
+ bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_FAIL);
+ } else
+ bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_OK);
}
static void
@@ -588,13 +654,14 @@ bna_port_cb_llport_stopped(struct bna_port *port,
static void
bna_llport_init(struct bna_llport *llport, struct bna *bna)
{
- llport->flags |= BNA_LLPORT_F_ENABLED;
+ llport->flags |= BNA_LLPORT_F_ADMIN_UP;
+ llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
llport->type = BNA_PORT_T_REGULAR;
llport->bna = bna;
llport->link_status = BNA_LINK_DOWN;
- llport->admin_up_count = 0;
+ llport->rx_started_count = 0;
llport->stop_cbfn = NULL;
@@ -606,7 +673,8 @@ bna_llport_init(struct bna_llport *llport, struct bna *bna)
static void
bna_llport_uninit(struct bna_llport *llport)
{
- llport->flags &= ~BNA_LLPORT_F_ENABLED;
+ llport->flags &= ~BNA_LLPORT_F_ADMIN_UP;
+ llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
llport->bna = NULL;
}
@@ -628,6 +696,8 @@ bna_llport_stop(struct bna_llport *llport)
static void
bna_llport_fail(struct bna_llport *llport)
{
+ /* Reset the physical port status to enabled */
+ llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
bfa_fsm_send_event(llport, LLPORT_E_FAIL);
}
@@ -638,25 +708,31 @@ bna_llport_state_get(struct bna_llport *llport)
}
void
-bna_llport_admin_up(struct bna_llport *llport)
+bna_llport_rx_started(struct bna_llport *llport)
{
- llport->admin_up_count++;
+ llport->rx_started_count++;
+
+ if (llport->rx_started_count == 1) {
+
+ llport->flags |= BNA_LLPORT_F_RX_STARTED;
- if (llport->admin_up_count == 1) {
- llport->flags |= BNA_LLPORT_F_RX_ENABLED;
- if (llport->flags & BNA_LLPORT_F_ENABLED)
+ if (llport_can_be_up(llport))
bfa_fsm_send_event(llport, LLPORT_E_UP);
}
}
void
-bna_llport_admin_down(struct bna_llport *llport)
+bna_llport_rx_stopped(struct bna_llport *llport)
{
- llport->admin_up_count--;
+ int llport_up = llport_is_up(llport);
+
+ llport->rx_started_count--;
+
+ if (llport->rx_started_count == 0) {
+
+ llport->flags &= ~BNA_LLPORT_F_RX_STARTED;
- if (llport->admin_up_count == 0) {
- llport->flags &= ~BNA_LLPORT_F_RX_ENABLED;
- if (llport->flags & BNA_LLPORT_F_ENABLED)
+ if (llport_up)
bfa_fsm_send_event(llport, LLPORT_E_DOWN);
}
}
diff --git a/drivers/net/bna/bna_txrx.c b/drivers/net/bna/bna_txrx.c
index ad93fdb..fb6cf1f 100644
--- a/drivers/net/bna/bna_txrx.c
+++ b/drivers/net/bna/bna_txrx.c
@@ -1947,7 +1947,7 @@ bna_rx_sm_started_entry(struct bna_rx *rx)
bna_ib_ack(&rxp->cq.ib->door_bell, 0);
}
- bna_llport_admin_up(&rx->bna->port.llport);
+ bna_llport_rx_started(&rx->bna->port.llport);
}
void
@@ -1955,13 +1955,13 @@ bna_rx_sm_started(struct bna_rx *rx, enum bna_rx_event event)
{
switch (event) {
case RX_E_FAIL:
- bna_llport_admin_down(&rx->bna->port.llport);
+ bna_llport_rx_stopped(&rx->bna->port.llport);
bfa_fsm_set_state(rx, bna_rx_sm_stopped);
rx_ib_fail(rx);
bna_rxf_fail(&rx->rxf);
break;
case RX_E_STOP:
- bna_llport_admin_down(&rx->bna->port.llport);
+ bna_llport_rx_stopped(&rx->bna->port.llport);
bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
break;
default:
@@ -3373,7 +3373,7 @@ __bna_txq_start(struct bna_tx *tx, struct bna_txq *txq)
txq_cfg.cns_ptr2_n_q_state = BNA_Q_IDLE_STATE;
txq_cfg.nxt_qid_n_fid_n_pri = (((tx->txf.txf_id & 0x3f) << 3) |
- (txq->priority & 0x3));
+ (txq->priority & 0x7));
txq_cfg.wvc_n_cquota_n_rquota =
((((u32)BFI_TX_MAX_WRR_QUOTA & 0xfff) << 12) |
(BFI_TX_MAX_WRR_QUOTA & 0xfff));
diff --git a/drivers/net/bna/bna_types.h b/drivers/net/bna/bna_types.h
index 6877310..d79fd98 100644
--- a/drivers/net/bna/bna_types.h
+++ b/drivers/net/bna/bna_types.h
@@ -249,8 +249,9 @@ enum bna_link_status {
};
enum bna_llport_flags {
- BNA_LLPORT_F_ENABLED = 1,
- BNA_LLPORT_F_RX_ENABLED = 2
+ BNA_LLPORT_F_ADMIN_UP = 1,
+ BNA_LLPORT_F_PORT_ENABLED = 2,
+ BNA_LLPORT_F_RX_STARTED = 4
};
enum bna_port_flags {
@@ -405,7 +406,7 @@ struct bna_llport {
enum bna_link_status link_status;
- int admin_up_count;
+ int rx_started_count;
void (*stop_cbfn)(struct bna_port *, enum bna_cb_status);
--
1.7.1
^ permalink raw reply related
* [PATCH 03/10] bna: Fix ethtool register dump and reordered an API
From: Rasesh Mody @ 2010-12-24 7:45 UTC (permalink / raw)
To: netdev; +Cc: huangj, Rasesh Mody, Debashis Dutt
In-Reply-To: <1293176710-21335-1-git-send-email-rmody@brocade.com>
Change Details:
- Removed semaphore register dump from ethtool
- Moved netif_carrier_off() call to before calling bna_init()
Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bnad.c | 8 +++-----
drivers/net/bna/bnad_ethtool.c | 4 ----
2 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 3c40502..5e7a030 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -3061,6 +3061,9 @@ bnad_pci_probe(struct pci_dev *pdev,
/* Initialize netdev structure, set up ethtool ops */
bnad_netdev_init(bnad, using_dac);
+ /* Set link to down state */
+ netif_carrier_off(netdev);
+
bnad_enable_msix(bnad);
/* Get resource requirement form bna */
@@ -3114,11 +3117,6 @@ bnad_pci_probe(struct pci_dev *pdev,
mutex_unlock(&bnad->conf_mutex);
- /*
- * Make sure the link appears down to the stack
- */
- netif_carrier_off(netdev);
-
/* Finally, reguister with net_device layer */
err = register_netdev(netdev);
if (err) {
diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c
index 11fa2ea..3011110 100644
--- a/drivers/net/bna/bnad_ethtool.c
+++ b/drivers/net/bna/bnad_ethtool.c
@@ -330,10 +330,6 @@ do { \
BNAD_GET_REG(PCIE_MISC_REG);
- BNAD_GET_REG(HOST_SEM0_REG);
- BNAD_GET_REG(HOST_SEM1_REG);
- BNAD_GET_REG(HOST_SEM2_REG);
- BNAD_GET_REG(HOST_SEM3_REG);
BNAD_GET_REG(HOST_SEM0_INFO_REG);
BNAD_GET_REG(HOST_SEM1_INFO_REG);
BNAD_GET_REG(HOST_SEM2_INFO_REG);
--
1.7.1
^ permalink raw reply related
* [PATCH 04/10] bna: Enable pure priority tagged packet reception and rxf uninit cleanup fix
From: Rasesh Mody @ 2010-12-24 7:45 UTC (permalink / raw)
To: netdev; +Cc: huangj, Rasesh Mody, Debashis Dutt
In-Reply-To: <1293176710-21335-1-git-send-email-rmody@brocade.com>
Change Details:
- Enable reception of pure priority tagged packets by default by
turning on VLAN Id = 0
- Clear the promiscuous mode, all multicast mode flags when
bna_rxf_uninit is called
Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bna_txrx.c | 25 +++++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/drivers/net/bna/bna_txrx.c b/drivers/net/bna/bna_txrx.c
index fb6cf1f..5076618 100644
--- a/drivers/net/bna/bna_txrx.c
+++ b/drivers/net/bna/bna_txrx.c
@@ -1441,12 +1441,16 @@ bna_rxf_init(struct bna_rxf *rxf,
memset(rxf->vlan_filter_table, 0,
(sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32)));
+ /* Set up VLAN 0 for pure priority tagged packets */
+ rxf->vlan_filter_table[0] |= 1;
+
bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
}
static void
bna_rxf_uninit(struct bna_rxf *rxf)
{
+ struct bna *bna = rxf->rx->bna;
struct bna_mac *mac;
bna_rit_mod_seg_put(&rxf->rx->bna->rit_mod, rxf->rit_segment);
@@ -1473,6 +1477,27 @@ bna_rxf_uninit(struct bna_rxf *rxf)
bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
}
+ /* Turn off pending promisc mode */
+ if (is_promisc_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* system promisc state should be pending */
+ BUG_ON(!(bna->rxf_promisc_id == rxf->rxf_id));
+ promisc_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ bna->rxf_promisc_id = BFI_MAX_RXF;
+ }
+ /* Promisc mode should not be active */
+ BUG_ON(rxf->rxmode_active & BNA_RXMODE_PROMISC);
+
+ /* Turn off pending all-multi mode */
+ if (is_allmulti_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ allmulti_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ }
+ /* Allmulti mode should not be active */
+ BUG_ON(rxf->rxmode_active & BNA_RXMODE_ALLMULTI);
+
rxf->rx = NULL;
}
--
1.7.1
^ permalink raw reply related
* [PATCH 05/10] bna: Fix for TX queue
From: Rasesh Mody @ 2010-12-24 7:45 UTC (permalink / raw)
To: netdev; +Cc: huangj, Rasesh Mody, Debashis Dutt
In-Reply-To: <1293176710-21335-1-git-send-email-rmody@brocade.com>
Change Details:
- Call netif_wake_queue() if we have freed up sufficient elements
at the end of completion processing
- Add netif_queue_stopped counter back to bnad_drv_stats {}
- Get netif_queue_stopped value from stack
- Remove BUG_ON() on value returned by pci_unmap_addr()
Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bnad.c | 20 ++++++++++++++++----
drivers/net/bna/bnad.h | 7 +++++--
drivers/net/bna/bnad_ethtool.c | 4 ++++
3 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 5e7a030..f775936 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -109,7 +109,7 @@ static void
bnad_free_all_txbufs(struct bnad *bnad,
struct bna_tcb *tcb)
{
- u16 unmap_cons;
+ u32 unmap_cons;
struct bnad_unmap_q *unmap_q = tcb->unmap_q;
struct bnad_skb_unmap *unmap_array;
struct sk_buff *skb = NULL;
@@ -244,7 +244,7 @@ bnad_tx_free_tasklet(unsigned long bnad_ptr)
{
struct bnad *bnad = (struct bnad *)bnad_ptr;
struct bna_tcb *tcb;
- u32 acked;
+ u32 acked = 0;
int i, j;
for (i = 0; i < bnad->num_tx; i++) {
@@ -263,6 +263,20 @@ bnad_tx_free_tasklet(unsigned long bnad_ptr)
smp_mb__before_clear_bit();
clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
}
+ if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED,
+ &tcb->flags)))
+ continue;
+ if (netif_queue_stopped(bnad->netdev)) {
+ if (acked && netif_carrier_ok(bnad->netdev) &&
+ BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
+ BNAD_NETIF_WAKE_THRESHOLD) {
+ netif_wake_queue(bnad->netdev);
+ /* TODO */
+ /* Counters for individual TxQs? */
+ BNAD_UPDATE_CTR(bnad,
+ netif_queue_wakeup);
+ }
+ }
}
}
}
@@ -334,8 +348,6 @@ bnad_free_all_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
skb = unmap_q->unmap_array[unmap_cons].skb;
if (!skb)
continue;
- BUG_ON(!(pci_unmap_addr(
- &unmap_q->unmap_array[unmap_cons], dma_addr)));
unmap_q->unmap_array[unmap_cons].skb = NULL;
pci_unmap_single(bnad->pcidev, pci_unmap_addr(&unmap_q->
unmap_array[unmap_cons],
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index f59685a..1954dea 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -126,6 +126,7 @@ struct bnad_completion {
struct bnad_drv_stats {
u64 netif_queue_stop;
u64 netif_queue_wakeup;
+ u64 netif_queue_stopped;
u64 tso4;
u64 tso6;
u64 tso_err;
@@ -308,8 +309,10 @@ extern void bnad_cleanup_rx(struct bnad *bnad, uint rx_id);
extern void bnad_dim_timer_start(struct bnad *bnad);
/* Statistics */
-extern void bnad_netdev_qstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats);
-extern void bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats);
+extern void bnad_netdev_qstats_fill(struct bnad *bnad,
+ struct rtnl_link_stats64 *stats);
+extern void bnad_netdev_hwstats_fill(struct bnad *bnad,
+ struct rtnl_link_stats64 *stats);
/**
* MACROS
diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c
index 3011110..99be5ae 100644
--- a/drivers/net/bna/bnad_ethtool.c
+++ b/drivers/net/bna/bnad_ethtool.c
@@ -68,6 +68,7 @@ static char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
"netif_queue_stop",
"netif_queue_wakeup",
+ "netif_queue_stopped",
"tso4",
"tso6",
"tso_err",
@@ -1180,6 +1181,9 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats,
bi = sizeof(*net_stats64) / sizeof(u64);
+ /* Get netif_queue_stopped from stack */
+ bnad->stats.drv_stats.netif_queue_stopped = netif_queue_stopped(netdev);
+
/* Fill driver stats into ethtool buffers */
stats64 = (u64 *)&bnad->stats.drv_stats;
for (i = 0; i < sizeof(struct bnad_drv_stats) / sizeof(u64); i++)
--
1.7.1
^ permalink raw reply related
* [PATCH 06/10] bna: IOC uninit check and misc cleanup
From: Rasesh Mody @ 2010-12-24 7:45 UTC (permalink / raw)
To: netdev; +Cc: huangj, Rasesh Mody, Debashis Dutt
In-Reply-To: <1293176710-21335-1-git-send-email-rmody@brocade.com>
Change Details:
- Added a check in ioc firmware lock function to see if IOC is
in BFI_IOC_UNINIT state or not. If it is not in UNINIT state
and the last IOC boot was not done by OS driver, force IOC state
to BFI_IOC_UNINIT
- Unused macro and API cleanup
Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_defs_mfg_comm.h | 22 -----------------
drivers/net/bna/bfa_ioc.c | 45 +---------------------------------
2 files changed, 2 insertions(+), 65 deletions(-)
diff --git a/drivers/net/bna/bfa_defs_mfg_comm.h b/drivers/net/bna/bfa_defs_mfg_comm.h
index 987978f..fdd6776 100644
--- a/drivers/net/bna/bfa_defs_mfg_comm.h
+++ b/drivers/net/bna/bfa_defs_mfg_comm.h
@@ -95,28 +95,6 @@ enum {
(type) == BFA_MFG_TYPE_CNA10P1 || \
bfa_mfg_is_mezz(type)))
-/**
- * Check if the card having old wwn/mac handling
- */
-#define bfa_mfg_is_old_wwn_mac_model(type) (( \
- (type) == BFA_MFG_TYPE_FC8P2 || \
- (type) == BFA_MFG_TYPE_FC8P1 || \
- (type) == BFA_MFG_TYPE_FC4P2 || \
- (type) == BFA_MFG_TYPE_FC4P1 || \
- (type) == BFA_MFG_TYPE_CNA10P2 || \
- (type) == BFA_MFG_TYPE_CNA10P1 || \
- (type) == BFA_MFG_TYPE_JAYHAWK || \
- (type) == BFA_MFG_TYPE_WANCHESE))
-
-#define bfa_mfg_increment_wwn_mac(m, i) \
-do { \
- u32 t = ((m)[0] << 16) | ((m)[1] << 8) | (m)[2]; \
- t += (i); \
- (m)[0] = (t >> 16) & 0xFF; \
- (m)[1] = (t >> 8) & 0xFF; \
- (m)[2] = t & 0xFF; \
-} while (0)
-
#define bfa_mfg_adapter_prop_init_flash(card_type, prop) \
do { \
switch ((card_type)) { \
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index e94e5aa..8ed147e 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -58,9 +58,6 @@
#define bfa_ioc_notify_hbfail(__ioc) \
((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc))
-#define bfa_ioc_is_optrom(__ioc) \
- (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
-
#define bfa_ioc_mbox_cmd_pending(__ioc) \
(!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
readl((__ioc)->ioc_regs.hfn_mbox_cmd))
@@ -101,7 +98,6 @@ static void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc,
char *manufacturer);
static void bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model);
static u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc);
-static mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc);
/**
* IOC state machine events
@@ -865,12 +861,6 @@ bfa_ioc_fwver_valid(struct bfa_ioc *ioc)
{
struct bfi_ioc_image_hdr fwhdr, *drv_fwhdr;
- /**
- * If bios/efi boot (flash based) -- return true
- */
- if (bfa_ioc_is_optrom(ioc))
- return true;
-
bfa_nw_ioc_fwver_get(ioc, &fwhdr);
drv_fwhdr = (struct bfi_ioc_image_hdr *)
bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
@@ -934,13 +924,8 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
/**
* If IOC function is disabled and firmware version is same,
* just re-enable IOC.
- *
- * If option rom, IOC must not be in operational state. With
- * convergence, IOC will be in operational state when 2nd driver
- * is loaded.
*/
- if (ioc_fwstate == BFI_IOC_DISABLED ||
- (!bfa_ioc_is_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
+ if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {
/**
* When using MSI-X any pending firmware ready event should
* be flushed. Otherwise MSI-X interrupts are not delivered.
@@ -1078,11 +1063,6 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
*/
bfa_ioc_lmem_init(ioc);
- /**
- * Flash based firmware boot
- */
- if (bfa_ioc_is_optrom(ioc))
- boot_type = BFI_BOOT_TYPE_FLASH;
fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
pgnum = bfa_ioc_smem_pgnum(ioc, loff);
@@ -1689,28 +1669,7 @@ bfa_ioc_get_pwwn(struct bfa_ioc *ioc)
mac_t
bfa_nw_ioc_get_mac(struct bfa_ioc *ioc)
{
- /*
- * Currently mfg mac is used as FCoE enode mac (not configured by PBC)
- */
- if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
- return bfa_ioc_get_mfg_mac(ioc);
- else
- return ioc->attr->mac;
-}
-
-static mac_t
-bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc)
-{
- mac_t m;
-
- m = ioc->attr->mfg_mac;
- if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
- m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
- else
- bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
- bfa_ioc_pcifn(ioc));
-
- return m;
+ return ioc->attr->mac;
}
/**
--
1.7.1
^ permalink raw reply related
* [PATCH 07/10] bna: Removed unused code
From: Rasesh Mody @ 2010-12-24 7:45 UTC (permalink / raw)
To: netdev; +Cc: huangj, Rasesh Mody, Debashis Dutt
In-Reply-To: <1293176710-21335-1-git-send-email-rmody@brocade.com>
Change Details:
- Remove unused APIs and code cleanup
Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bna_ctrl.c | 241 +------------------------------------------
drivers/net/bna/bna_txrx.c | 11 +--
drivers/net/bna/bna_types.h | 4 +-
3 files changed, 3 insertions(+), 253 deletions(-)
diff --git a/drivers/net/bna/bna_ctrl.c b/drivers/net/bna/bna_ctrl.c
index 68e4c5e..e152747 100644
--- a/drivers/net/bna/bna_ctrl.c
+++ b/drivers/net/bna/bna_ctrl.c
@@ -2132,37 +2132,6 @@ rxf_fltr_mbox_cmd(struct bna_rxf *rxf, u8 cmd, enum bna_status status)
bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
}
-static void
-__rxf_default_function_config(struct bna_rxf *rxf, enum bna_status status)
-{
- struct bna_rx_fndb_ram *rx_fndb_ram;
- u32 ctrl_flags;
- int i;
-
- rx_fndb_ram = (struct bna_rx_fndb_ram *)
- BNA_GET_MEM_BASE_ADDR(rxf->rx->bna->pcidev.pci_bar_kva,
- RX_FNDB_RAM_BASE_OFFSET);
-
- for (i = 0; i < BFI_MAX_RXF; i++) {
- if (status == BNA_STATUS_T_ENABLED) {
- if (i == rxf->rxf_id)
- continue;
-
- ctrl_flags =
- readl(&rx_fndb_ram[i].control_flags);
- ctrl_flags |= BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE;
- writel(ctrl_flags,
- &rx_fndb_ram[i].control_flags);
- } else {
- ctrl_flags =
- readl(&rx_fndb_ram[i].control_flags);
- ctrl_flags &= ~BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE;
- writel(ctrl_flags,
- &rx_fndb_ram[i].control_flags);
- }
- }
-}
-
int
rxf_process_packet_filter_ucast(struct bna_rxf *rxf)
{
@@ -2229,46 +2198,6 @@ rxf_process_packet_filter_promisc(struct bna_rxf *rxf)
}
int
-rxf_process_packet_filter_default(struct bna_rxf *rxf)
-{
- struct bna *bna = rxf->rx->bna;
-
- /* Enable/disable default mode */
- if (is_default_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- /* move default configuration from pending -> active */
- default_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active |= BNA_RXMODE_DEFAULT;
-
- /* Disable VLAN filter to allow all VLANs */
- __rxf_vlan_filter_set(rxf, BNA_STATUS_T_DISABLED);
- /* Redirect all other RxF vlan filtering to this one */
- __rxf_default_function_config(rxf, BNA_STATUS_T_ENABLED);
- rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
- BNA_STATUS_T_ENABLED);
- return 1;
- } else if (is_default_disable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- /* move default configuration from pending -> active */
- default_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
- bna->rxf_default_id = BFI_MAX_RXF;
-
- /* Revert VLAN filter */
- __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
- /* Stop RxF vlan filter table redirection */
- __rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED);
- rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
- BNA_STATUS_T_DISABLED);
- return 1;
- }
-
- return 0;
-}
-
-int
rxf_process_packet_filter_allmulti(struct bna_rxf *rxf)
{
/* Enable/disable allmulti mode */
@@ -2365,48 +2294,6 @@ rxf_clear_packet_filter_promisc(struct bna_rxf *rxf)
}
int
-rxf_clear_packet_filter_default(struct bna_rxf *rxf)
-{
- struct bna *bna = rxf->rx->bna;
-
- /* 8. Execute pending default mode disable command */
- if (is_default_disable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- /* move default configuration from pending -> active */
- default_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
- bna->rxf_default_id = BFI_MAX_RXF;
-
- /* Revert VLAN filter */
- __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
- /* Stop RxF vlan filter table redirection */
- __rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED);
- rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
- BNA_STATUS_T_DISABLED);
- return 1;
- }
-
- /* 9. Clear active default mode; move it to pending enable */
- if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) {
- /* move default configuration from active -> pending */
- default_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
-
- /* Revert VLAN filter */
- __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
- /* Stop RxF vlan filter table redirection */
- __rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED);
- rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
- BNA_STATUS_T_DISABLED);
- return 1;
- }
-
- return 0;
-}
-
-int
rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf)
{
/* 10. Execute pending allmulti mode disable command */
@@ -2481,28 +2368,6 @@ rxf_reset_packet_filter_promisc(struct bna_rxf *rxf)
}
void
-rxf_reset_packet_filter_default(struct bna_rxf *rxf)
-{
- struct bna *bna = rxf->rx->bna;
-
- /* 8. Clear pending default mode disable */
- if (is_default_disable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- default_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
- bna->rxf_default_id = BFI_MAX_RXF;
- }
-
- /* 9. Move default mode config from active -> pending */
- if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) {
- default_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
- }
-}
-
-void
rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf)
{
/* 10. Clear pending allmulti mode disable */
@@ -2599,76 +2464,6 @@ rxf_promisc_disable(struct bna_rxf *rxf)
* 1 = need h/w change
*/
static int
-rxf_default_enable(struct bna_rxf *rxf)
-{
- struct bna *bna = rxf->rx->bna;
- int ret = 0;
-
- /* There can not be any pending disable command */
-
- /* Do nothing if pending enable or already enabled */
- if (is_default_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask) ||
- (rxf->rxmode_active & BNA_RXMODE_DEFAULT)) {
- /* Schedule enable */
- } else {
- /* Default mode should not be active in the system */
- default_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- bna->rxf_default_id = rxf->rxf_id;
- ret = 1;
- }
-
- return ret;
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- * Returns:
- * 0 = no h/w change
- * 1 = need h/w change
- */
-static int
-rxf_default_disable(struct bna_rxf *rxf)
-{
- struct bna *bna = rxf->rx->bna;
- int ret = 0;
-
- /* There can not be any pending disable */
-
- /* Turn off pending enable command , if any */
- if (is_default_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- /* Promisc mode should not be active */
- /* system default state should be pending */
- default_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- /* Remove the default state from the system */
- bna->rxf_default_id = BFI_MAX_RXF;
-
- /* Schedule disable */
- } else if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) {
- /* Default mode should be active in the system */
- default_disable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- ret = 1;
-
- /* Do nothing if already disabled */
- } else {
- }
-
- return ret;
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- * Returns:
- * 0 = no h/w change
- * 1 = need h/w change
- */
-static int
rxf_allmulti_enable(struct bna_rxf *rxf)
{
int ret = 0;
@@ -2730,38 +2525,13 @@ bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode new_mode,
struct bna_rxf *rxf = &rx->rxf;
int need_hw_config = 0;
- /* Error checks */
+ /* Process the commands */
if (is_promisc_enable(new_mode, bitmask)) {
/* If promisc mode is already enabled elsewhere in the system */
if ((rx->bna->rxf_promisc_id != BFI_MAX_RXF) &&
(rx->bna->rxf_promisc_id != rxf->rxf_id))
goto err_return;
-
- /* If default mode is already enabled in the system */
- if (rx->bna->rxf_default_id != BFI_MAX_RXF)
- goto err_return;
-
- /* Trying to enable promiscuous and default mode together */
- if (is_default_enable(new_mode, bitmask))
- goto err_return;
- }
-
- if (is_default_enable(new_mode, bitmask)) {
- /* If default mode is already enabled elsewhere in the system */
- if ((rx->bna->rxf_default_id != BFI_MAX_RXF) &&
- (rx->bna->rxf_default_id != rxf->rxf_id)) {
- goto err_return;
- }
-
- /* If promiscuous mode is already enabled in the system */
- if (rx->bna->rxf_promisc_id != BFI_MAX_RXF)
- goto err_return;
- }
-
- /* Process the commands */
-
- if (is_promisc_enable(new_mode, bitmask)) {
if (rxf_promisc_enable(rxf))
need_hw_config = 1;
} else if (is_promisc_disable(new_mode, bitmask)) {
@@ -2769,14 +2539,6 @@ bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode new_mode,
need_hw_config = 1;
}
- if (is_default_enable(new_mode, bitmask)) {
- if (rxf_default_enable(rxf))
- need_hw_config = 1;
- } else if (is_default_disable(new_mode, bitmask)) {
- if (rxf_default_disable(rxf))
- need_hw_config = 1;
- }
-
if (is_allmulti_enable(new_mode, bitmask)) {
if (rxf_allmulti_enable(rxf))
need_hw_config = 1;
@@ -3202,7 +2964,6 @@ bna_init(struct bna *bna, struct bnad *bnad, struct bfa_pcidev *pcidev,
bna_mcam_mod_init(&bna->mcam_mod, bna, res_info);
- bna->rxf_default_id = BFI_MAX_RXF;
bna->rxf_promisc_id = BFI_MAX_RXF;
/* Mbox q element for posting stat request to f/w */
diff --git a/drivers/net/bna/bna_txrx.c b/drivers/net/bna/bna_txrx.c
index 5076618..58c7664 100644
--- a/drivers/net/bna/bna_txrx.c
+++ b/drivers/net/bna/bna_txrx.c
@@ -1226,8 +1226,7 @@ rxf_process_packet_filter_vlan(struct bna_rxf *rxf)
/* Apply the VLAN filter */
if (rxf->rxf_flags & BNA_RXF_FL_VLAN_CONFIG_PENDING) {
rxf->rxf_flags &= ~BNA_RXF_FL_VLAN_CONFIG_PENDING;
- if (!(rxf->rxmode_active & BNA_RXMODE_PROMISC) &&
- !(rxf->rxmode_active & BNA_RXMODE_DEFAULT))
+ if (!(rxf->rxmode_active & BNA_RXMODE_PROMISC))
__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
}
@@ -1276,9 +1275,6 @@ rxf_process_packet_filter(struct bna_rxf *rxf)
if (rxf_process_packet_filter_promisc(rxf))
return 1;
- if (rxf_process_packet_filter_default(rxf))
- return 1;
-
if (rxf_process_packet_filter_allmulti(rxf))
return 1;
@@ -1340,9 +1336,6 @@ rxf_clear_packet_filter(struct bna_rxf *rxf)
if (rxf_clear_packet_filter_promisc(rxf))
return 1;
- if (rxf_clear_packet_filter_default(rxf))
- return 1;
-
if (rxf_clear_packet_filter_allmulti(rxf))
return 1;
@@ -1389,8 +1382,6 @@ rxf_reset_packet_filter(struct bna_rxf *rxf)
rxf_reset_packet_filter_promisc(rxf);
- rxf_reset_packet_filter_default(rxf);
-
rxf_reset_packet_filter_allmulti(rxf);
}
diff --git a/drivers/net/bna/bna_types.h b/drivers/net/bna/bna_types.h
index d79fd98..b9c134f 100644
--- a/drivers/net/bna/bna_types.h
+++ b/drivers/net/bna/bna_types.h
@@ -165,8 +165,7 @@ enum bna_rxp_type {
enum bna_rxmode {
BNA_RXMODE_PROMISC = 1,
- BNA_RXMODE_DEFAULT = 2,
- BNA_RXMODE_ALLMULTI = 4
+ BNA_RXMODE_ALLMULTI = 2
};
enum bna_rx_event {
@@ -1118,7 +1117,6 @@ struct bna {
struct bna_rit_mod rit_mod;
- int rxf_default_id;
int rxf_promisc_id;
struct bna_mbox_qe mbox_qe;
--
1.7.1
^ permalink raw reply related
* [PATCH 08/10] bna: Restore VLAN filter table
From: Rasesh Mody @ 2010-12-24 7:45 UTC (permalink / raw)
To: netdev; +Cc: huangj, Rasesh Mody, Debashis Dutt
In-Reply-To: <1293176710-21335-1-git-send-email-rmody@brocade.com>
Change Details:
- Retrieve the VLAN configuration from the networking stack
and apply it to the base interface during ifconfig up
Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bnad.c | 29 +++++++++++++++++++++++++++--
1 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index f775936..140ea95 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -566,7 +566,8 @@ bnad_enable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
{
unsigned long flags;
- spin_lock_irqsave(&bnad->bna_lock, flags); /* Because of polling context */
+ /* Because of polling context */
+ spin_lock_irqsave(&bnad->bna_lock, flags);
bnad_enable_rx_irq_unsafe(ccb);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
}
@@ -1962,6 +1963,27 @@ bnad_enable_default_bcast(struct bnad *bnad)
return 0;
}
+/* Called with bnad_conf_lock() held */
+static void
+bnad_restore_vlans(struct bnad *bnad, u32 rx_id)
+{
+ u16 vlan_id;
+ unsigned long flags;
+
+ if (!bnad->vlan_grp)
+ return;
+
+ BUG_ON(!(VLAN_N_VID == (BFI_MAX_VLAN + 1)));
+
+ for (vlan_id = 0; vlan_id < VLAN_N_VID; vlan_id++) {
+ if (!vlan_group_get_device(bnad->vlan_grp, vlan_id))
+ continue;
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_rx_vlan_add(bnad->rx_info[rx_id].rx, vlan_id);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ }
+}
+
/* Statistics utilities */
void
bnad_netdev_qstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
@@ -2337,6 +2359,9 @@ bnad_open(struct net_device *netdev)
/* Enable broadcast */
bnad_enable_default_bcast(bnad);
+ /* Restore VLANs, if any */
+ bnad_restore_vlans(bnad, 0);
+
/* Set the UCAST address */
spin_lock_irqsave(&bnad->bna_lock, flags);
bnad_mac_addr_set_locked(bnad, netdev->dev_addr);
@@ -3021,7 +3046,7 @@ static int __devinit
bnad_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pcidev_id)
{
- bool using_dac;
+ bool using_dac = false;
int err;
struct bnad *bnad;
struct bna *bna;
--
1.7.1
^ permalink raw reply related
* [PATCH 09/10] bna: IOC failure auto recovery fix
From: Rasesh Mody @ 2010-12-24 7:45 UTC (permalink / raw)
To: netdev; +Cc: huangj, Rasesh Mody, Debashis Dutt
In-Reply-To: <1293176710-21335-1-git-send-email-rmody@brocade.com>
Change Details:
- Made IOC auto_recovery synchronized and not timer based.
- Only one PCI function will attempt to recover and reinitialize
the ASIC on a failure, that too after all the active PCI
functions acknowledge the IOC failure.
Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bfa_defs.h | 22 +-
drivers/net/bna/bfa_ioc.c | 1174 ++++++++++++++++++++++++++++++++----------
drivers/net/bna/bfa_ioc.h | 49 +-
drivers/net/bna/bfa_ioc_ct.c | 102 ++++-
drivers/net/bna/bfi_ctreg.h | 41 +-
drivers/net/bna/bna.h | 2 -
drivers/net/bna/bnad.c | 21 +-
7 files changed, 1061 insertions(+), 350 deletions(-)
diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index 29c1b8d..2ea0dfe 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -112,16 +112,18 @@ struct bfa_ioc_pci_attr {
* IOC states
*/
enum bfa_ioc_state {
- BFA_IOC_RESET = 1, /*!< IOC is in reset state */
- BFA_IOC_SEMWAIT = 2, /*!< Waiting for IOC h/w semaphore */
- BFA_IOC_HWINIT = 3, /*!< IOC h/w is being initialized */
- BFA_IOC_GETATTR = 4, /*!< IOC is being configured */
- BFA_IOC_OPERATIONAL = 5, /*!< IOC is operational */
- BFA_IOC_INITFAIL = 6, /*!< IOC hardware failure */
- BFA_IOC_HBFAIL = 7, /*!< IOC heart-beat failure */
- BFA_IOC_DISABLING = 8, /*!< IOC is being disabled */
- BFA_IOC_DISABLED = 9, /*!< IOC is disabled */
- BFA_IOC_FWMISMATCH = 10, /*!< IOC f/w different from drivers */
+ BFA_IOC_UNINIT = 1, /*!< IOC is in uninit state */
+ BFA_IOC_RESET = 2, /*!< IOC is in reset state */
+ BFA_IOC_SEMWAIT = 3, /*!< Waiting for IOC h/w semaphore */
+ BFA_IOC_HWINIT = 4, /*!< IOC h/w is being initialized */
+ BFA_IOC_GETATTR = 5, /*!< IOC is being configured */
+ BFA_IOC_OPERATIONAL = 6, /*!< IOC is operational */
+ BFA_IOC_INITFAIL = 7, /*!< IOC hardware failure */
+ BFA_IOC_FAIL = 8, /*!< IOC heart-beat failure */
+ BFA_IOC_DISABLING = 9, /*!< IOC is being disabled */
+ 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 */
};
/**
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 8ed147e..34933cb 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -26,25 +26,6 @@
* IOC local definitions
*/
-#define bfa_ioc_timer_start(__ioc) \
- mod_timer(&(__ioc)->ioc_timer, jiffies + \
- msecs_to_jiffies(BFA_IOC_TOV))
-#define bfa_ioc_timer_stop(__ioc) del_timer(&(__ioc)->ioc_timer)
-
-#define bfa_ioc_recovery_timer_start(__ioc) \
- mod_timer(&(__ioc)->ioc_timer, jiffies + \
- msecs_to_jiffies(BFA_IOC_TOV_RECOVER))
-
-#define bfa_sem_timer_start(__ioc) \
- mod_timer(&(__ioc)->sem_timer, jiffies + \
- msecs_to_jiffies(BFA_IOC_HWSEM_TOV))
-#define bfa_sem_timer_stop(__ioc) del_timer(&(__ioc)->sem_timer)
-
-#define bfa_hb_timer_start(__ioc) \
- mod_timer(&(__ioc)->hb_timer, jiffies + \
- msecs_to_jiffies(BFA_IOC_HB_TOV))
-#define bfa_hb_timer_stop(__ioc) del_timer(&(__ioc)->hb_timer)
-
/**
* Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
*/
@@ -55,8 +36,16 @@
((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
-#define bfa_ioc_notify_hbfail(__ioc) \
- ((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc))
+#define bfa_ioc_notify_fail(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc))
+#define bfa_ioc_sync_join(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_sync_join(__ioc))
+#define bfa_ioc_sync_leave(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_sync_leave(__ioc))
+#define bfa_ioc_sync_ack(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_sync_ack(__ioc))
+#define bfa_ioc_sync_complete(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_sync_complete(__ioc))
#define bfa_ioc_mbox_cmd_pending(__ioc) \
(!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
@@ -82,6 +71,12 @@ static void bfa_ioc_recover(struct bfa_ioc *ioc);
static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc);
static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);
static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
+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_initfailed(struct bfa_ioc *ioc);
+static void bfa_ioc_pf_failed(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);
static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr);
@@ -100,69 +95,171 @@ static void bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model);
static u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc);
/**
- * IOC state machine events
+ * IOC state machine definitions/declarations
*/
enum ioc_event {
- IOC_E_ENABLE = 1, /*!< IOC enable request */
- IOC_E_DISABLE = 2, /*!< IOC disable request */
- IOC_E_TIMEOUT = 3, /*!< f/w response timeout */
- IOC_E_FWREADY = 4, /*!< f/w initialization done */
- IOC_E_FWRSP_GETATTR = 5, /*!< IOC get attribute response */
- IOC_E_FWRSP_ENABLE = 6, /*!< enable f/w response */
- IOC_E_FWRSP_DISABLE = 7, /*!< disable f/w response */
- IOC_E_HBFAIL = 8, /*!< heartbeat failure */
- IOC_E_HWERROR = 9, /*!< hardware error interrupt */
- IOC_E_SEMLOCKED = 10, /*!< h/w semaphore is locked */
- IOC_E_DETACH = 11, /*!< driver detach cleanup */
+ IOC_E_RESET = 1, /*!< IOC reset request */
+ IOC_E_ENABLE = 2, /*!< IOC enable request */
+ IOC_E_DISABLE = 3, /*!< IOC disable request */
+ IOC_E_DETACH = 4, /*!< driver detach cleanup */
+ 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_INITFAILED = 8, /*!< failure notice by iocpf sm */
+ IOC_E_PFAILED = 9, /*!< failure notice by iocpf sm */
+ IOC_E_HBFAIL = 10, /*!< heartbeat failure */
+ IOC_E_HWERROR = 11, /*!< hardware error interrupt */
+ IOC_E_TIMEOUT = 12, /*!< timeout */
};
+bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, fwcheck, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, mismatch, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, semwait, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, hwinit, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, hbfail, struct bfa_ioc, enum ioc_event);
+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);
static struct bfa_sm_table ioc_sm_table[] = {
+ {BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
{BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
- {BFA_SM(bfa_ioc_sm_fwcheck), BFA_IOC_FWMISMATCH},
- {BFA_SM(bfa_ioc_sm_mismatch), BFA_IOC_FWMISMATCH},
- {BFA_SM(bfa_ioc_sm_semwait), BFA_IOC_SEMWAIT},
- {BFA_SM(bfa_ioc_sm_hwinit), BFA_IOC_HWINIT},
- {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_HWINIT},
+ {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
- {BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
- {BFA_SM(bfa_ioc_sm_hbfail), BFA_IOC_HBFAIL},
+ {BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL},
+ {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},
};
/**
+ * IOCPF state machine definitions/declarations
+ */
+
+/*
+ * Forward declareations for iocpf state machine
+ */
+static void bfa_iocpf_enable(struct bfa_ioc *ioc);
+static void bfa_iocpf_disable(struct bfa_ioc *ioc);
+static void bfa_iocpf_fail(struct bfa_ioc *ioc);
+static void bfa_iocpf_initfail(struct bfa_ioc *ioc);
+static void bfa_iocpf_getattrfail(struct bfa_ioc *ioc);
+static void bfa_iocpf_stop(struct bfa_ioc *ioc);
+
+/**
+ * IOCPF state machine events
+ */
+enum iocpf_event {
+ IOCPF_E_ENABLE = 1, /*!< IOCPF enable request */
+ IOCPF_E_DISABLE = 2, /*!< IOCPF disable request */
+ IOCPF_E_STOP = 3, /*!< stop on driver detach */
+ IOCPF_E_FWREADY = 4, /*!< f/w initialization done */
+ IOCPF_E_FWRSP_ENABLE = 5, /*!< enable f/w response */
+ IOCPF_E_FWRSP_DISABLE = 6, /*!< disable f/w response */
+ IOCPF_E_FAIL = 7, /*!< failure notice by ioc sm */
+ IOCPF_E_INITFAIL = 8, /*!< init fail notice by ioc sm */
+ 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 states
+ */
+enum bfa_iocpf_state {
+ BFA_IOCPF_RESET = 1, /*!< IOC is in reset state */
+ BFA_IOCPF_SEMWAIT = 2, /*!< Waiting for IOC h/w semaphore */
+ BFA_IOCPF_HWINIT = 3, /*!< IOC h/w is being initialized */
+ BFA_IOCPF_READY = 4, /*!< IOCPF is initialized */
+ BFA_IOCPF_INITFAIL = 5, /*!< IOCPF failed */
+ BFA_IOCPF_FAIL = 6, /*!< IOCPF failed */
+ BFA_IOCPF_DISABLING = 7, /*!< IOCPF is being disabled */
+ BFA_IOCPF_DISABLED = 8, /*!< IOCPF is disabled */
+ BFA_IOCPF_FWMISMATCH = 9, /*!< IOC f/w different from drivers */
+};
+
+bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf,
+ enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf,
+ enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf, enum iocpf_event);
+
+static struct bfa_sm_table iocpf_sm_table[] = {
+ {BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
+ {BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
+ {BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
+ {BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},
+ {BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
+ {BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
+ {BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
+ {BFA_SM(bfa_iocpf_sm_initfail_sync), BFA_IOCPF_INITFAIL},
+ {BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
+ {BFA_SM(bfa_iocpf_sm_fail_sync), BFA_IOCPF_FAIL},
+ {BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
+ {BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
+ {BFA_SM(bfa_iocpf_sm_disabling_sync), BFA_IOCPF_DISABLING},
+ {BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
+};
+
+/**
+ * IOC State Machine
+ */
+
+/**
+ * Beginning state. IOC uninit state.
+ */
+static void
+bfa_ioc_sm_uninit_entry(struct bfa_ioc *ioc)
+{
+}
+
+/**
+ * IOC is in uninit state.
+ */
+static void
+bfa_ioc_sm_uninit(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_RESET:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+/**
* Reset entry actions -- initialize state machine
*/
static void
bfa_ioc_sm_reset_entry(struct bfa_ioc *ioc)
{
- ioc->retry_count = 0;
- ioc->auto_recover = bfa_nw_auto_recover;
+ bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);
}
/**
- * Beginning state. IOC is in reset state.
+ * IOC is in reset state.
*/
static void
bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event)
{
switch (event) {
case IOC_E_ENABLE:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
break;
case IOC_E_DISABLE:
@@ -170,6 +267,7 @@ bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event)
break;
case IOC_E_DETACH:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
break;
default:
@@ -177,42 +275,43 @@ bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event)
}
}
-/**
- * Semaphore should be acquired for version check.
- */
static void
-bfa_ioc_sm_fwcheck_entry(struct bfa_ioc *ioc)
+bfa_ioc_sm_enabling_entry(struct bfa_ioc *ioc)
{
- bfa_ioc_hw_sem_get(ioc);
+ bfa_iocpf_enable(ioc);
}
/**
- * Awaiting h/w semaphore to continue with version check.
+ * Host IOC function is being enabled, awaiting response from firmware.
+ * Semaphore is acquired.
*/
static void
-bfa_ioc_sm_fwcheck(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
{
switch (event) {
- case IOC_E_SEMLOCKED:
- if (bfa_ioc_firmware_lock(ioc)) {
- ioc->retry_count = 0;
- bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
- } else {
- bfa_nw_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch);
- }
+ case IOC_E_ENABLED:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+ break;
+
+ case IOC_E_PFAILED:
+ /* !!! 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_retry);
+ if (event != IOC_E_PFAILED)
+ bfa_iocpf_initfail(ioc);
break;
case IOC_E_DISABLE:
- bfa_ioc_disable_comp(ioc);
- /* fall through */
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ break;
case IOC_E_DETACH:
- bfa_ioc_hw_sem_get_cancel(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+ bfa_iocpf_stop(ioc);
break;
- case IOC_E_FWREADY:
+ case IOC_E_ENABLE:
break;
default:
@@ -221,41 +320,85 @@ bfa_ioc_sm_fwcheck(struct bfa_ioc *ioc, enum ioc_event event)
}
/**
- * Notify enable completion callback and generate mismatch AEN.
+ * Semaphore should be acquired for version check.
*/
static void
-bfa_ioc_sm_mismatch_entry(struct bfa_ioc *ioc)
+bfa_ioc_sm_getattr_entry(struct bfa_ioc *ioc)
{
- /**
- * Provide enable completion callback and AEN notification only once.
- */
- if (ioc->retry_count == 0)
- ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
- ioc->retry_count++;
- bfa_ioc_timer_start(ioc);
+ mod_timer(&ioc->ioc_timer, jiffies +
+ msecs_to_jiffies(BFA_IOC_TOV));
+ bfa_ioc_send_getattr(ioc);
}
/**
- * Awaiting firmware version match.
+ * IOC configuration in progress. Timer is active.
*/
static void
-bfa_ioc_sm_mismatch(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
{
switch (event) {
+ case IOC_E_FWRSP_GETATTR:
+ del_timer(&ioc->ioc_timer);
+ bfa_ioc_check_attr_wwns(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+ break;
+
+ case IOC_E_PFAILED:
+ case IOC_E_HWERROR:
+ del_timer(&ioc->ioc_timer);
+ /* fall through */
case IOC_E_TIMEOUT:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+ if (event != IOC_E_PFAILED)
+ bfa_iocpf_getattrfail(ioc);
break;
case IOC_E_DISABLE:
- bfa_ioc_disable_comp(ioc);
- /* fall through */
+ del_timer(&ioc->ioc_timer);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ break;
- case IOC_E_DETACH:
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ case IOC_E_ENABLE:
+ break;
+
+ default:
+ bfa_sm_fault(ioc, 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);
+}
+
+static void
+bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_ENABLE:
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_ioc_hb_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
break;
- case IOC_E_FWREADY:
+ case IOC_E_PFAILED:
+ case IOC_E_HWERROR:
+ bfa_ioc_hb_stop(ioc);
+ /* !!! fall through !!! */
+ case IOC_E_HBFAIL:
+ bfa_ioc_fail_notify(ioc);
+ if (ioc->iocpf.auto_recover)
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+ else
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+
+ if (event != IOC_E_PFAILED)
+ bfa_iocpf_fail(ioc);
break;
default:
@@ -263,30 +406,61 @@ bfa_ioc_sm_mismatch(struct bfa_ioc *ioc, enum ioc_event event)
}
}
+static void
+bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc)
+{
+ bfa_iocpf_disable(ioc);
+}
+
/**
- * Request for semaphore.
+ * IOC is being desabled
*/
static void
-bfa_ioc_sm_semwait_entry(struct bfa_ioc *ioc)
+bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
{
- bfa_ioc_hw_sem_get(ioc);
+ switch (event) {
+ case IOC_E_DISABLED:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ break;
+
+ case IOC_E_HWERROR:
+ /*
+ * No state change. Will move to disabled state
+ * after iocpf sm completes failure processing and
+ * moves to disabled state.
+ */
+ bfa_iocpf_fail(ioc);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
}
/**
- * Awaiting semaphore for h/w initialzation.
+ * IOC desable completion entry.
*/
static void
-bfa_ioc_sm_semwait(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc)
+{
+ bfa_ioc_disable_comp(ioc);
+}
+
+static void
+bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event)
{
switch (event) {
- case IOC_E_SEMLOCKED:
- ioc->retry_count = 0;
- bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+ case IOC_E_ENABLE:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
break;
case IOC_E_DISABLE:
- bfa_ioc_hw_sem_get_cancel(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ ioc->cbfn->disable_cbfn(ioc->bfa);
+ break;
+
+ case IOC_E_DETACH:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+ bfa_iocpf_stop(ioc);
break;
default:
@@ -295,46 +469,45 @@ bfa_ioc_sm_semwait(struct bfa_ioc *ioc, enum ioc_event event)
}
static void
-bfa_ioc_sm_hwinit_entry(struct bfa_ioc *ioc)
+bfa_ioc_sm_fail_retry_entry(struct bfa_ioc *ioc)
{
- bfa_ioc_timer_start(ioc);
- bfa_ioc_reset(ioc, false);
}
/**
- * @brief
- * Hardware is being initialized. Interrupts are enabled.
- * Holding hardware semaphore lock.
+ * Hardware initialization retry.
*/
static void
-bfa_ioc_sm_hwinit(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
{
switch (event) {
- case IOC_E_FWREADY:
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
+ case IOC_E_ENABLED:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
break;
+ case IOC_E_PFAILED:
case IOC_E_HWERROR:
- bfa_ioc_timer_stop(ioc);
- /* fall through */
+ /**
+ * Initialization retry failed.
+ */
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ if (event != IOC_E_PFAILED)
+ bfa_iocpf_initfail(ioc);
+ break;
- case IOC_E_TIMEOUT:
- ioc->retry_count++;
- if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
- bfa_ioc_timer_start(ioc);
- bfa_ioc_reset(ioc, true);
- break;
- }
+ case IOC_E_INITFAILED:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+ break;
- bfa_nw_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+ case IOC_E_ENABLE:
break;
case IOC_E_DISABLE:
- bfa_nw_ioc_hw_sem_release(ioc);
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ break;
+
+ case IOC_E_DETACH:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+ bfa_iocpf_stop(ioc);
break;
default:
@@ -343,51 +516,248 @@ bfa_ioc_sm_hwinit(struct bfa_ioc *ioc, enum ioc_event event)
}
static void
-bfa_ioc_sm_enabling_entry(struct bfa_ioc *ioc)
+bfa_ioc_sm_fail_entry(struct bfa_ioc *ioc)
{
- bfa_ioc_timer_start(ioc);
- bfa_ioc_send_enable(ioc);
}
/**
- * Host IOC function is being enabled, awaiting response from firmware.
- * Semaphore is acquired.
+ * IOC failure.
*/
static void
-bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)
{
switch (event) {
- case IOC_E_FWRSP_ENABLE:
- bfa_ioc_timer_stop(ioc);
- bfa_nw_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+ case IOC_E_ENABLE:
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ break;
+
+ case IOC_E_DETACH:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+ bfa_iocpf_stop(ioc);
break;
case IOC_E_HWERROR:
- bfa_ioc_timer_stop(ioc);
- /* fall through */
+ /* HB failure notification, ignore. */
+ break;
- case IOC_E_TIMEOUT:
- ioc->retry_count++;
- if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
- writel(BFI_IOC_UNINIT,
- ioc->ioc_regs.ioc_fwstate);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
- break;
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+/**
+ * IOCPF State Machine
+ */
+
+/**
+ * Reset entry actions -- initialize state machine
+ */
+static void
+bfa_iocpf_sm_reset_entry(struct bfa_iocpf *iocpf)
+{
+ iocpf->retry_count = 0;
+ iocpf->auto_recover = bfa_nw_auto_recover;
+}
+
+/**
+ * Beginning state. IOC is in reset state.
+ */
+static void
+bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+ switch (event) {
+ case IOCPF_E_ENABLE:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
+ break;
+
+ case IOCPF_E_STOP:
+ break;
+
+ default:
+ bfa_sm_fault(iocpf->ioc, event);
+ }
+}
+
+/**
+ * Semaphore should be acquired for version check.
+ */
+static void
+bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf *iocpf)
+{
+ bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+/**
+ * Awaiting h/w semaphore to continue with version check.
+ */
+static void
+bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+ struct bfa_ioc *ioc = iocpf->ioc;
+
+ switch (event) {
+ case IOCPF_E_SEMLOCKED:
+ if (bfa_ioc_firmware_lock(ioc)) {
+ if (bfa_ioc_sync_complete(ioc)) {
+ iocpf->retry_count = 0;
+ bfa_ioc_sync_join(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+ } else {
+ bfa_ioc_firmware_unlock(ioc);
+ bfa_nw_ioc_hw_sem_release(ioc);
+ mod_timer(&ioc->sem_timer, jiffies +
+ msecs_to_jiffies(BFA_IOC_HWSEM_TOV));
+ }
+ } else {
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
}
+ break;
- bfa_nw_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+ case IOCPF_E_DISABLE:
+ bfa_ioc_hw_sem_get_cancel(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+ bfa_ioc_pf_disabled(ioc);
break;
- case IOC_E_DISABLE:
- bfa_ioc_timer_stop(ioc);
+ case IOCPF_E_STOP:
+ bfa_ioc_hw_sem_get_cancel(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+/**
+ * Notify enable completion callback
+ */
+static void
+bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf *iocpf)
+{
+ /* Call only the first time sm enters fwmismatch state. */
+ if (iocpf->retry_count == 0)
+ bfa_ioc_pf_fwmismatch(iocpf->ioc);
+
+ iocpf->retry_count++;
+ mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
+ msecs_to_jiffies(BFA_IOC_TOV));
+}
+
+/**
+ * Awaiting firmware version match.
+ */
+static void
+bfa_iocpf_sm_mismatch(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+ struct bfa_ioc *ioc = iocpf->ioc;
+
+ switch (event) {
+ case IOCPF_E_TIMEOUT:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
+ break;
+
+ case IOCPF_E_DISABLE:
+ del_timer(&ioc->iocpf_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);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+/**
+ * Request for semaphore.
+ */
+static void
+bfa_iocpf_sm_semwait_entry(struct bfa_iocpf *iocpf)
+{
+ bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+/**
+ * Awaiting semaphore for h/w initialzation.
+ */
+static void
+bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+ struct bfa_ioc *ioc = iocpf->ioc;
+
+ switch (event) {
+ case IOCPF_E_SEMLOCKED:
+ if (bfa_ioc_sync_complete(ioc)) {
+ bfa_ioc_sync_join(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+ } else {
+ bfa_nw_ioc_hw_sem_release(ioc);
+ mod_timer(&ioc->sem_timer, jiffies +
+ msecs_to_jiffies(BFA_IOC_HWSEM_TOV));
+ }
+ break;
+
+ case IOCPF_E_DISABLE:
+ bfa_ioc_hw_sem_get_cancel(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+static void
+bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf *iocpf)
+{
+ mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
+ msecs_to_jiffies(BFA_IOC_TOV));
+ bfa_ioc_reset(iocpf->ioc, 0);
+}
+
+/**
+ * Hardware is being initialized. Interrupts are enabled.
+ * Holding hardware semaphore lock.
+ */
+static void
+bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+ struct bfa_ioc *ioc = iocpf->ioc;
+
+ switch (event) {
+ case IOCPF_E_FWREADY:
+ del_timer(&ioc->iocpf_timer);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
+ break;
+
+ case IOCPF_E_INITFAIL:
+ del_timer(&ioc->iocpf_timer);
+ /*
+ * !!! fall through !!!
+ */
+
+ case IOCPF_E_TIMEOUT:
bfa_nw_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ if (event == IOCPF_E_TIMEOUT)
+ bfa_ioc_pf_failed(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
break;
- case IOC_E_FWREADY:
- bfa_ioc_send_enable(ioc);
+ case IOCPF_E_DISABLE:
+ del_timer(&ioc->iocpf_timer);
+ bfa_ioc_sync_leave(ioc);
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
break;
default:
@@ -396,37 +766,49 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
}
static void
-bfa_ioc_sm_getattr_entry(struct bfa_ioc *ioc)
+bfa_iocpf_sm_enabling_entry(struct bfa_iocpf *iocpf)
{
- bfa_ioc_timer_start(ioc);
- bfa_ioc_send_getattr(ioc);
+ mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
+ msecs_to_jiffies(BFA_IOC_TOV));
+ bfa_ioc_send_enable(iocpf->ioc);
}
/**
- * @brief
- * IOC configuration in progress. Timer is active.
+ * Host IOC function is being enabled, awaiting response from firmware.
+ * Semaphore is acquired.
*/
static void
-bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc *ioc = iocpf->ioc;
+
switch (event) {
- case IOC_E_FWRSP_GETATTR:
- bfa_ioc_timer_stop(ioc);
- bfa_ioc_check_attr_wwns(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+ case IOCPF_E_FWRSP_ENABLE:
+ del_timer(&ioc->iocpf_timer);
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
break;
- case IOC_E_HWERROR:
- bfa_ioc_timer_stop(ioc);
- /* fall through */
+ case IOCPF_E_INITFAIL:
+ del_timer(&ioc->iocpf_timer);
+ /*
+ * !!! fall through !!!
+ */
+ case IOCPF_E_TIMEOUT:
+ bfa_nw_ioc_hw_sem_release(ioc);
+ if (event == IOCPF_E_TIMEOUT)
+ bfa_ioc_pf_failed(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
+ break;
- case IOC_E_TIMEOUT:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+ case IOCPF_E_DISABLE:
+ del_timer(&ioc->iocpf_timer);
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
break;
- case IOC_E_DISABLE:
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ case IOCPF_E_FWREADY:
+ bfa_ioc_send_enable(ioc);
break;
default:
@@ -434,36 +816,42 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
}
}
+static bool
+bfa_nw_ioc_is_operational(struct bfa_ioc *ioc)
+{
+ return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
+}
+
static void
-bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
+bfa_iocpf_sm_ready_entry(struct bfa_iocpf *iocpf)
{
- ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
- bfa_ioc_hb_monitor(ioc);
+ bfa_ioc_pf_enabled(iocpf->ioc);
}
static void
-bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc *ioc = iocpf->ioc;
+
switch (event) {
- case IOC_E_ENABLE:
+ case IOCPF_E_DISABLE:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
break;
- case IOC_E_DISABLE:
- bfa_ioc_hb_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ case IOCPF_E_GETATTRFAIL:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
break;
- case IOC_E_HWERROR:
- case IOC_E_FWREADY:
- /**
- * Hard error or IOC recovery by other function.
- * Treat it same as heartbeat failure.
- */
- bfa_ioc_hb_stop(ioc);
- /* !!! fall through !!! */
+ case IOCPF_E_FAIL:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
+ break;
- case IOC_E_HBFAIL:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_hbfail);
+ case IOCPF_E_FWREADY:
+ bfa_ioc_pf_failed(ioc);
+ if (bfa_nw_ioc_is_operational(ioc))
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
+ else
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
break;
default:
@@ -472,33 +860,40 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
}
static void
-bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc)
+bfa_iocpf_sm_disabling_entry(struct bfa_iocpf *iocpf)
{
- bfa_ioc_timer_start(ioc);
- bfa_ioc_send_disable(ioc);
+ mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
+ msecs_to_jiffies(BFA_IOC_TOV));
+ bfa_ioc_send_disable(iocpf->ioc);
}
/**
* IOC is being disabled
*/
static void
-bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc *ioc = iocpf->ioc;
+
switch (event) {
- case IOC_E_FWRSP_DISABLE:
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ case IOCPF_E_FWRSP_DISABLE:
+ case IOCPF_E_FWREADY:
+ del_timer(&ioc->iocpf_timer);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
break;
- case IOC_E_HWERROR:
- bfa_ioc_timer_stop(ioc);
+ case IOCPF_E_FAIL:
+ del_timer(&ioc->iocpf_timer);
/*
* !!! fall through !!!
*/
- case IOC_E_TIMEOUT:
+ case IOCPF_E_TIMEOUT:
writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
+ break;
+
+ case IOCPF_E_FWRSP_ENABLE:
break;
default:
@@ -506,33 +901,58 @@ bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
}
}
-/**
- * IOC disable completion entry.
- */
static void
-bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc)
+bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf *iocpf)
{
- bfa_ioc_disable_comp(ioc);
+ bfa_ioc_hw_sem_get(iocpf->ioc);
}
+/**
+ * IOC hb ack request is being removed.
+ */
static void
-bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc *ioc = iocpf->ioc;
+
switch (event) {
- case IOC_E_ENABLE:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+ case IOCPF_E_SEMLOCKED:
+ bfa_ioc_sync_leave(ioc);
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
break;
- case IOC_E_DISABLE:
- ioc->cbfn->disable_cbfn(ioc->bfa);
+ case IOCPF_E_FAIL:
break;
- case IOC_E_FWREADY:
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+/**
+ * IOC disable completion entry.
+ */
+static void
+bfa_iocpf_sm_disabled_entry(struct bfa_iocpf *iocpf)
+{
+ bfa_ioc_pf_disabled(iocpf->ioc);
+}
+
+static void
+bfa_iocpf_sm_disabled(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+ struct bfa_ioc *ioc = iocpf->ioc;
+
+ switch (event) {
+ case IOCPF_E_ENABLE:
+ iocpf->retry_count = 0;
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
break;
- case IOC_E_DETACH:
+ case IOCPF_E_STOP:
bfa_ioc_firmware_unlock(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
break;
default:
@@ -541,33 +961,50 @@ bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event)
}
static void
-bfa_ioc_sm_initfail_entry(struct bfa_ioc *ioc)
+bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf *iocpf)
{
- ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
- bfa_ioc_timer_start(ioc);
+ bfa_ioc_hw_sem_get(iocpf->ioc);
}
/**
- * @brief
* Hardware initialization failed.
*/
static void
-bfa_ioc_sm_initfail(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc *ioc = iocpf->ioc;
+
switch (event) {
- case IOC_E_DISABLE:
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ case IOCPF_E_SEMLOCKED:
+ bfa_ioc_notify_fail(ioc);
+ bfa_ioc_sync_ack(ioc);
+ iocpf->retry_count++;
+ if (iocpf->retry_count >= BFA_IOC_HWINIT_MAX) {
+ bfa_ioc_sync_leave(ioc);
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+ } else {
+ if (bfa_ioc_sync_complete(ioc))
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+ else {
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+ }
+ }
break;
- case IOC_E_DETACH:
- bfa_ioc_timer_stop(ioc);
+ case IOCPF_E_DISABLE:
+ bfa_ioc_hw_sem_get_cancel(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
+ break;
+
+ case IOCPF_E_STOP:
+ bfa_ioc_hw_sem_get_cancel(ioc);
bfa_ioc_firmware_unlock(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
break;
- case IOC_E_TIMEOUT:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+ case IOCPF_E_FAIL:
break;
default:
@@ -576,80 +1013,108 @@ bfa_ioc_sm_initfail(struct bfa_ioc *ioc, enum ioc_event event)
}
static void
-bfa_ioc_sm_hbfail_entry(struct bfa_ioc *ioc)
+bfa_iocpf_sm_initfail_entry(struct bfa_iocpf *iocpf)
{
- struct list_head *qe;
- struct bfa_ioc_hbfail_notify *notify;
+ bfa_ioc_pf_initfailed(iocpf->ioc);
+}
- /**
- * Mark IOC as failed in hardware and stop firmware.
- */
- bfa_ioc_lpu_stop(ioc);
- writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+/**
+ * Hardware initialization failed.
+ */
+static void
+bfa_iocpf_sm_initfail(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+ struct bfa_ioc *ioc = iocpf->ioc;
- /**
- * Notify other functions on HB failure.
- */
- bfa_ioc_notify_hbfail(ioc);
+ switch (event) {
+ case IOCPF_E_DISABLE:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+ break;
- /**
- * Notify driver and common modules registered for notification.
- */
- ioc->cbfn->hbfail_cbfn(ioc->bfa);
- list_for_each(qe, &ioc->hb_notify_q) {
- notify = (struct bfa_ioc_hbfail_notify *) qe;
- notify->cbfn(notify->cbarg);
+ case IOCPF_E_STOP:
+ bfa_ioc_firmware_unlock(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
}
+}
+static void
+bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf *iocpf)
+{
/**
- * Flush any queued up mailbox requests.
+ * Mark IOC as failed in hardware and stop firmware.
*/
- bfa_ioc_mbox_hbfail(ioc);
+ bfa_ioc_lpu_stop(iocpf->ioc);
/**
- * Trigger auto-recovery after a delay.
+ * Flush any queued up mailbox requests.
*/
- if (ioc->auto_recover)
- mod_timer(&ioc->ioc_timer, jiffies +
- msecs_to_jiffies(BFA_IOC_TOV_RECOVER));
+ bfa_ioc_mbox_hbfail(iocpf->ioc);
+ bfa_ioc_hw_sem_get(iocpf->ioc);
}
/**
- * @brief
- * IOC heartbeat failure.
+ * IOC is in failed state.
*/
static void
-bfa_ioc_sm_hbfail(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
{
- switch (event) {
+ struct bfa_ioc *ioc = iocpf->ioc;
- case IOC_E_ENABLE:
- ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ switch (event) {
+ case IOCPF_E_SEMLOCKED:
+ iocpf->retry_count = 0;
+ bfa_ioc_sync_ack(ioc);
+ bfa_ioc_notify_fail(ioc);
+ if (!iocpf->auto_recover) {
+ bfa_ioc_sync_leave(ioc);
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ } else {
+ if (bfa_ioc_sync_complete(ioc))
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+ else {
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+ }
+ }
break;
- case IOC_E_DISABLE:
- if (ioc->auto_recover)
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ case IOCPF_E_DISABLE:
+ bfa_ioc_hw_sem_get_cancel(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
break;
- case IOC_E_TIMEOUT:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+ case IOCPF_E_FAIL:
break;
- case IOC_E_FWREADY:
- /**
- * Recovery is already initiated by other function.
- */
- break;
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
- case IOC_E_HWERROR:
- /*
- * HB failure notification, ignore.
- */
+static void
+bfa_iocpf_sm_fail_entry(struct bfa_iocpf *iocpf)
+{
+}
+
+/**
+ * @brief
+ * IOC is in failed state.
+ */
+static void
+bfa_iocpf_sm_fail(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+ switch (event) {
+ case IOCPF_E_DISABLE:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
break;
+
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(iocpf->ioc, event);
}
}
@@ -674,14 +1139,6 @@ bfa_ioc_disable_comp(struct bfa_ioc *ioc)
}
}
-void
-bfa_nw_ioc_sem_timeout(void *ioc_arg)
-{
- struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
-
- bfa_ioc_hw_sem_get(ioc);
-}
-
bool
bfa_nw_ioc_sem_get(void __iomem *sem_reg)
{
@@ -721,7 +1178,7 @@ bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
*/
r32 = readl(ioc->ioc_regs.ioc_sem_reg);
if (r32 == 0) {
- bfa_fsm_send_event(ioc, IOC_E_SEMLOCKED);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
return;
}
@@ -932,7 +1389,7 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
*/
bfa_ioc_msgflush(ioc);
ioc->cbfn->reset_cbfn(ioc->bfa);
- bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
return;
}
@@ -1018,7 +1475,6 @@ bfa_nw_ioc_hb_check(void *cbarg)
hb_count = readl(ioc->ioc_regs.heartbeat);
if (ioc->hb_count == hb_count) {
- pr_crit("Firmware heartbeat failure at %d", hb_count);
bfa_ioc_recover(ioc);
return;
} else {
@@ -1189,6 +1645,55 @@ bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc)
bfa_q_deq(&mod->cmd_q, &cmd);
}
+static void
+bfa_ioc_fail_notify(struct bfa_ioc *ioc)
+{
+ struct list_head *qe;
+ struct bfa_ioc_hbfail_notify *notify;
+
+ /**
+ * Notify driver and common modules registered for notification.
+ */
+ ioc->cbfn->hbfail_cbfn(ioc->bfa);
+ list_for_each(qe, &ioc->hb_notify_q) {
+ notify = (struct bfa_ioc_hbfail_notify *) qe;
+ notify->cbfn(notify->cbarg);
+ }
+}
+
+static void
+bfa_ioc_pf_enabled(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(ioc, IOC_E_ENABLED);
+}
+
+static void
+bfa_ioc_pf_disabled(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(ioc, IOC_E_DISABLED);
+}
+
+static void
+bfa_ioc_pf_initfailed(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(ioc, IOC_E_INITFAILED);
+}
+
+static void
+bfa_ioc_pf_failed(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(ioc, IOC_E_PFAILED);
+}
+
+static void
+bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc)
+{
+ /**
+ * Provide enable completion callback and AEN notification.
+ */
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+}
+
/**
* IOC public
*/
@@ -1284,6 +1789,7 @@ static void
bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
{
union bfi_ioc_i2h_msg_u *msg;
+ struct bfa_iocpf *iocpf = &ioc->iocpf;
msg = (union bfi_ioc_i2h_msg_u *) m;
@@ -1294,15 +1800,15 @@ bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
break;
case BFI_IOC_I2H_READY_EVENT:
- bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+ bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
break;
case BFI_IOC_I2H_ENABLE_REPLY:
- bfa_fsm_send_event(ioc, IOC_E_FWRSP_ENABLE);
+ bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
break;
case BFI_IOC_I2H_DISABLE_REPLY:
- bfa_fsm_send_event(ioc, IOC_E_FWRSP_DISABLE);
+ bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);
break;
case BFI_IOC_I2H_GETATTR_REPLY:
@@ -1328,11 +1834,13 @@ bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn)
ioc->fcmode = false;
ioc->pllinit = false;
ioc->dbg_fwsave_once = true;
+ ioc->iocpf.ioc = ioc;
bfa_ioc_mbox_attach(ioc);
INIT_LIST_HEAD(&ioc->hb_notify_q);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+ bfa_fsm_send_event(ioc, IOC_E_RESET);
}
/**
@@ -1637,7 +2145,40 @@ bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model)
static enum bfa_ioc_state
bfa_ioc_get_state(struct bfa_ioc *ioc)
{
- return bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+ enum bfa_iocpf_state iocpf_st;
+ enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+
+ if (ioc_st == BFA_IOC_ENABLING ||
+ ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {
+
+ iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
+
+ switch (iocpf_st) {
+ case BFA_IOCPF_SEMWAIT:
+ ioc_st = BFA_IOC_SEMWAIT;
+ break;
+
+ case BFA_IOCPF_HWINIT:
+ ioc_st = BFA_IOC_HWINIT;
+ break;
+
+ case BFA_IOCPF_FWMISMATCH:
+ ioc_st = BFA_IOC_FWMISMATCH;
+ break;
+
+ case BFA_IOCPF_FAIL:
+ ioc_st = BFA_IOC_FAIL;
+ break;
+
+ case BFA_IOCPF_INITFAIL:
+ ioc_st = BFA_IOC_INITFAIL;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return ioc_st;
}
void
@@ -1678,8 +2219,13 @@ bfa_nw_ioc_get_mac(struct bfa_ioc *ioc)
static void
bfa_ioc_recover(struct bfa_ioc *ioc)
{
- bfa_ioc_stats(ioc, ioc_hbfails);
- bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
+ u16 bdf;
+
+ bdf = (ioc->pcidev.pci_slot << 8 | ioc->pcidev.pci_func << 3 |
+ ioc->pcidev.device_id);
+
+ pr_crit("Firmware heartbeat failure at %d", bdf);
+ BUG_ON(1);
}
static void
@@ -1687,5 +2233,61 @@ bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc)
{
if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
return;
+}
+
+/**
+ * @dg hal_iocpf_pvt BFA IOC PF private functions
+ * @{
+ */
+
+static void
+bfa_iocpf_enable(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
+}
+static void
+bfa_iocpf_disable(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
+}
+
+static void
+bfa_iocpf_fail(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
+}
+
+static void
+bfa_iocpf_initfail(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
+}
+
+static void
+bfa_iocpf_getattrfail(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
+}
+
+static void
+bfa_iocpf_stop(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
+}
+
+void
+bfa_nw_iocpf_timeout(void *ioc_arg)
+{
+ struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
+
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
+}
+
+void
+bfa_nw_iocpf_sem_timeout(void *ioc_arg)
+{
+ struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
+
+ bfa_ioc_hw_sem_get(ioc);
}
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index a73d84e..e4974bc 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -26,16 +26,7 @@
#define BFA_IOC_TOV 3000 /* msecs */
#define BFA_IOC_HWSEM_TOV 500 /* msecs */
#define BFA_IOC_HB_TOV 500 /* msecs */
-#define BFA_IOC_HWINIT_MAX 2
-#define BFA_IOC_TOV_RECOVER BFA_IOC_HB_TOV
-
-/**
- * Generic Scatter Gather Element used by driver
- */
-struct bfa_sge {
- u32 sg_len;
- void *sg_addr;
-};
+#define BFA_IOC_HWINIT_MAX 5
/**
* PCI device information required by IOC
@@ -65,19 +56,6 @@ struct bfa_dma {
#define BFI_SMEM_CT_SIZE 0x280000U /* ! 2.5MB for catapult */
/**
- * @brief BFA dma address assignment macro
- */
-#define bfa_dma_addr_set(dma_addr, pa) \
- __bfa_dma_addr_set(&dma_addr, (u64)pa)
-
-static inline void
-__bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa)
-{
- dma_addr->a32.addr_lo = (u32) pa;
- dma_addr->a32.addr_hi = (u32) (upper_32_bits(pa));
-}
-
-/**
* @brief BFA dma address assignment macro. (big endian format)
*/
#define bfa_dma_be_addr_set(dma_addr, pa) \
@@ -105,8 +83,11 @@ struct bfa_ioc_regs {
void __iomem *host_page_num_fn;
void __iomem *heartbeat;
void __iomem *ioc_fwstate;
+ void __iomem *alt_ioc_fwstate;
void __iomem *ll_halt;
+ void __iomem *alt_ll_halt;
void __iomem *err_set;
+ void __iomem *ioc_fail_sync;
void __iomem *shirq_isr_next;
void __iomem *shirq_msk_next;
void __iomem *smem_page_start;
@@ -165,16 +146,22 @@ struct bfa_ioc_hbfail_notify {
(__notify)->cbarg = (__cbarg); \
} while (0)
+struct bfa_iocpf {
+ bfa_fsm_t fsm;
+ struct bfa_ioc *ioc;
+ u32 retry_count;
+ bool auto_recover;
+};
+
struct bfa_ioc {
bfa_fsm_t fsm;
struct bfa *bfa;
struct bfa_pcidev pcidev;
- struct bfa_timer_mod *timer_mod;
struct timer_list ioc_timer;
+ struct timer_list iocpf_timer;
struct timer_list sem_timer;
struct timer_list hb_timer;
u32 hb_count;
- u32 retry_count;
struct list_head hb_notify_q;
void *dbg_fwsave;
int dbg_fwsave_len;
@@ -182,7 +169,6 @@ struct bfa_ioc {
enum bfi_mclass ioc_mc;
struct bfa_ioc_regs ioc_regs;
struct bfa_ioc_drv_stats stats;
- bool auto_recover;
bool fcmode;
bool ctdev;
bool cna;
@@ -195,6 +181,7 @@ struct bfa_ioc {
struct bfa_ioc_cbfn *cbfn;
struct bfa_ioc_mbox_mod mbox_mod;
struct bfa_ioc_hwif *ioc_hwif;
+ struct bfa_iocpf iocpf;
};
struct bfa_ioc_hwif {
@@ -205,8 +192,12 @@ struct bfa_ioc_hwif {
void (*ioc_map_port) (struct bfa_ioc *ioc);
void (*ioc_isr_mode_set) (struct bfa_ioc *ioc,
bool msix);
- void (*ioc_notify_hbfail) (struct bfa_ioc *ioc);
+ void (*ioc_notify_fail) (struct bfa_ioc *ioc);
void (*ioc_ownership_reset) (struct bfa_ioc *ioc);
+ void (*ioc_sync_join) (struct bfa_ioc *ioc);
+ void (*ioc_sync_leave) (struct bfa_ioc *ioc);
+ void (*ioc_sync_ack) (struct bfa_ioc *ioc);
+ bool (*ioc_sync_complete) (struct bfa_ioc *ioc);
};
#define bfa_ioc_pcifn(__ioc) ((__ioc)->pcidev.pci_func)
@@ -271,7 +262,6 @@ void bfa_nw_ioc_enable(struct bfa_ioc *ioc);
void bfa_nw_ioc_disable(struct bfa_ioc *ioc);
void bfa_nw_ioc_error_isr(struct bfa_ioc *ioc);
-
void bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr);
void bfa_nw_ioc_hbfail_register(struct bfa_ioc *ioc,
struct bfa_ioc_hbfail_notify *notify);
@@ -289,7 +279,8 @@ mac_t bfa_nw_ioc_get_mac(struct bfa_ioc *ioc);
*/
void bfa_nw_ioc_timeout(void *ioc);
void bfa_nw_ioc_hb_check(void *ioc);
-void bfa_nw_ioc_sem_timeout(void *ioc);
+void bfa_nw_iocpf_timeout(void *ioc);
+void bfa_nw_iocpf_sem_timeout(void *ioc);
/*
* F/W Image Size & Chunk
diff --git a/drivers/net/bna/bfa_ioc_ct.c b/drivers/net/bna/bfa_ioc_ct.c
index 121cfd6..469997c 100644
--- a/drivers/net/bna/bfa_ioc_ct.c
+++ b/drivers/net/bna/bfa_ioc_ct.c
@@ -22,6 +22,15 @@
#include "bfi_ctreg.h"
#include "bfa_defs.h"
+#define bfa_ioc_ct_sync_pos(__ioc) \
+ ((u32) (1 << bfa_ioc_pcifn(__ioc)))
+#define BFA_IOC_SYNC_REQD_SH 16
+#define bfa_ioc_ct_get_sync_ackd(__val) (__val & 0x0000ffff)
+#define bfa_ioc_ct_clear_sync_ackd(__val) (__val & 0xffff0000)
+#define bfa_ioc_ct_get_sync_reqd(__val) (__val >> BFA_IOC_SYNC_REQD_SH)
+#define bfa_ioc_ct_sync_reqd_pos(__ioc) \
+ (bfa_ioc_ct_sync_pos(__ioc) << BFA_IOC_SYNC_REQD_SH)
+
/*
* forward declarations
*/
@@ -30,8 +39,12 @@ static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc);
static void bfa_ioc_ct_reg_init(struct bfa_ioc *ioc);
static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc);
static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix);
-static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc);
static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_sync_join(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc);
+static bool bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc);
static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode);
static struct bfa_ioc_hwif nw_hwif_ct;
@@ -48,8 +61,12 @@ bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc)
nw_hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
nw_hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
nw_hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
- nw_hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail;
+ nw_hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail;
nw_hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
+ nw_hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join;
+ nw_hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave;
+ nw_hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack;
+ nw_hwif_ct.ioc_sync_complete = bfa_ioc_ct_sync_complete;
ioc->ioc_hwif = &nw_hwif_ct;
}
@@ -86,6 +103,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc)
if (usecnt == 0) {
writel(1, ioc->ioc_regs.ioc_usage_reg);
bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ writel(0, ioc->ioc_regs.ioc_fail_sync);
return true;
}
@@ -149,12 +167,14 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc)
* Notify other functions on HB failure.
*/
static void
-bfa_ioc_ct_notify_hbfail(struct bfa_ioc *ioc)
+bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc)
{
if (ioc->cna) {
writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
+ writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt);
/* Wait for halt to take effect */
readl(ioc->ioc_regs.ll_halt);
+ readl(ioc->ioc_regs.alt_ll_halt);
} else {
writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
readl(ioc->ioc_regs.err_set);
@@ -206,15 +226,19 @@ bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
if (ioc->port_id == 0) {
ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
+ ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;
ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
+ ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
} else {
ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
+ ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG;
ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
+ ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
}
/*
@@ -232,6 +256,7 @@ bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);
ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT);
+ ioc->ioc_regs.ioc_fail_sync = (rb + BFA_IOC_FAIL_SYNC);
/**
* sram memory access
@@ -317,6 +342,77 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc)
bfa_nw_ioc_hw_sem_release(ioc);
}
+/**
+ * Synchronized IOC failure processing routines
+ */
+static void
+bfa_ioc_ct_sync_join(struct bfa_ioc *ioc)
+{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+ u32 sync_pos = bfa_ioc_ct_sync_reqd_pos(ioc);
+
+ writel((r32 | sync_pos), ioc->ioc_regs.ioc_fail_sync);
+}
+
+static void
+bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc)
+{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+ u32 sync_msk = bfa_ioc_ct_sync_reqd_pos(ioc) |
+ bfa_ioc_ct_sync_pos(ioc);
+
+ writel((r32 & ~sync_msk), ioc->ioc_regs.ioc_fail_sync);
+}
+
+static void
+bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc)
+{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+
+ writel((r32 | bfa_ioc_ct_sync_pos(ioc)), ioc->ioc_regs.ioc_fail_sync);
+}
+
+static bool
+bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc)
+{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+ u32 sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
+ u32 sync_ackd = bfa_ioc_ct_get_sync_ackd(r32);
+ u32 tmp_ackd;
+
+ if (sync_ackd == 0)
+ return true;
+
+ /**
+ * The check below is to see whether any other PCI fn
+ * has reinitialized the ASIC (reset sync_ackd bits)
+ * and failed again while this IOC was waiting for hw
+ * semaphore (in bfa_iocpf_sm_semwait()).
+ */
+ tmp_ackd = sync_ackd;
+ if ((sync_reqd & bfa_ioc_ct_sync_pos(ioc)) &&
+ !(sync_ackd & bfa_ioc_ct_sync_pos(ioc)))
+ sync_ackd |= bfa_ioc_ct_sync_pos(ioc);
+
+ if (sync_reqd == sync_ackd) {
+ writel(bfa_ioc_ct_clear_sync_ackd(r32),
+ ioc->ioc_regs.ioc_fail_sync);
+ writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ writel(BFI_IOC_FAIL, ioc->ioc_regs.alt_ioc_fwstate);
+ return true;
+ }
+
+ /**
+ * If another PCI fn reinitialized and failed again while
+ * this IOC was waiting for hw sem, the sync_ackd bit for
+ * this IOC need to be set again to allow reinitialization.
+ */
+ if (tmp_ackd != sync_ackd)
+ writel((r32 | sync_ackd), ioc->ioc_regs.ioc_fail_sync);
+
+ return false;
+}
+
static enum bfa_status
bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode)
{
diff --git a/drivers/net/bna/bfi_ctreg.h b/drivers/net/bna/bfi_ctreg.h
index 404ea35..5130d79 100644
--- a/drivers/net/bna/bfi_ctreg.h
+++ b/drivers/net/bna/bfi_ctreg.h
@@ -535,6 +535,7 @@ enum {
#define BFA_IOC1_HBEAT_REG HOST_SEM2_INFO_REG
#define BFA_IOC1_STATE_REG HOST_SEM3_INFO_REG
#define BFA_FW_USE_COUNT HOST_SEM4_INFO_REG
+#define BFA_IOC_FAIL_SYNC HOST_SEM5_INFO_REG
#define CPE_DEPTH_Q(__n) \
(CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
@@ -552,22 +553,30 @@ enum {
(RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
#define RME_CI_PTR_Q(__n) \
(RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
-#define HQM_QSET_RXQ_DRBL_P0(__n) (HQM_QSET0_RXQ_DRBL_P0 + (__n) \
- * (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
-#define HQM_QSET_TXQ_DRBL_P0(__n) (HQM_QSET0_TXQ_DRBL_P0 + (__n) \
- * (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
-#define HQM_QSET_IB_DRBL_1_P0(__n) (HQM_QSET0_IB_DRBL_1_P0 + (__n) \
- * (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
-#define HQM_QSET_IB_DRBL_2_P0(__n) (HQM_QSET0_IB_DRBL_2_P0 + (__n) \
- * (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
-#define HQM_QSET_RXQ_DRBL_P1(__n) (HQM_QSET0_RXQ_DRBL_P1 + (__n) \
- * (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
-#define HQM_QSET_TXQ_DRBL_P1(__n) (HQM_QSET0_TXQ_DRBL_P1 + (__n) \
- * (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
-#define HQM_QSET_IB_DRBL_1_P1(__n) (HQM_QSET0_IB_DRBL_1_P1 + (__n) \
- * (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
-#define HQM_QSET_IB_DRBL_2_P1(__n) (HQM_QSET0_IB_DRBL_2_P1 + (__n) \
- * (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
+#define HQM_QSET_RXQ_DRBL_P0(__n) \
+ (HQM_QSET0_RXQ_DRBL_P0 + (__n) * \
+ (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
+#define HQM_QSET_TXQ_DRBL_P0(__n) \
+ (HQM_QSET0_TXQ_DRBL_P0 + (__n) * \
+ (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
+#define HQM_QSET_IB_DRBL_1_P0(__n) \
+ (HQM_QSET0_IB_DRBL_1_P0 + (__n) * \
+ (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
+#define HQM_QSET_IB_DRBL_2_P0(__n) \
+ (HQM_QSET0_IB_DRBL_2_P0 + (__n) * \
+ (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
+#define HQM_QSET_RXQ_DRBL_P1(__n) \
+ (HQM_QSET0_RXQ_DRBL_P1 + (__n) * \
+ (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
+#define HQM_QSET_TXQ_DRBL_P1(__n) \
+ (HQM_QSET0_TXQ_DRBL_P1 + (__n) * \
+ (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
+#define HQM_QSET_IB_DRBL_1_P1(__n) \
+ (HQM_QSET0_IB_DRBL_1_P1 + (__n) * \
+ (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
+#define HQM_QSET_IB_DRBL_2_P1(__n) \
+ (HQM_QSET0_IB_DRBL_2_P1 + (__n) * \
+ (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
diff --git a/drivers/net/bna/bna.h b/drivers/net/bna/bna.h
index fd93f76..a287f89 100644
--- a/drivers/net/bna/bna.h
+++ b/drivers/net/bna/bna.h
@@ -32,8 +32,6 @@ extern const u32 bna_napi_dim_vector[][BNA_BIAS_T_MAX];
/* Log string size */
#define BNA_MESSAGE_SIZE 256
-#define bna_device_timer(_dev) bfa_timer_beat(&((_dev)->timer_mod))
-
/* MBOX API for PORT, TX, RX */
#define bna_mbox_qe_fill(_qe, _cmd, _cmd_len, _cbfn, _cbarg) \
do { \
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 140ea95..fad9126 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -1425,13 +1425,24 @@ bnad_ioc_hb_check(unsigned long data)
}
static void
-bnad_ioc_sem_timeout(unsigned long data)
+bnad_iocpf_timeout(unsigned long data)
{
struct bnad *bnad = (struct bnad *)data;
unsigned long flags;
spin_lock_irqsave(&bnad->bna_lock, flags);
- bfa_nw_ioc_sem_timeout((void *) &bnad->bna.device.ioc);
+ bfa_nw_iocpf_timeout((void *) &bnad->bna.device.ioc);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+static void
+bnad_iocpf_sem_timeout(unsigned long data)
+{
+ struct bnad *bnad = (struct bnad *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bfa_nw_iocpf_sem_timeout((void *) &bnad->bna.device.ioc);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
}
@@ -3132,11 +3143,13 @@ bnad_pci_probe(struct pci_dev *pdev,
((unsigned long)bnad));
setup_timer(&bnad->bna.device.ioc.hb_timer, bnad_ioc_hb_check,
((unsigned long)bnad));
- setup_timer(&bnad->bna.device.ioc.sem_timer, bnad_ioc_sem_timeout,
+ setup_timer(&bnad->bna.device.ioc.iocpf_timer, bnad_iocpf_timeout,
+ ((unsigned long)bnad));
+ setup_timer(&bnad->bna.device.ioc.sem_timer, bnad_iocpf_sem_timeout,
((unsigned long)bnad));
/* Now start the timer before calling IOC */
- mod_timer(&bnad->bna.device.ioc.ioc_timer,
+ mod_timer(&bnad->bna.device.ioc.iocpf_timer,
jiffies + msecs_to_jiffies(BNA_IOC_TIMER_FREQ));
/*
--
1.7.1
^ permalink raw reply related
* [PATCH 10/10] bna: Update the driver version to 2.3.2.3
From: Rasesh Mody @ 2010-12-24 7:45 UTC (permalink / raw)
To: netdev; +Cc: huangj, Rasesh Mody, Debashis Dutt
In-Reply-To: <1293176710-21335-1-git-send-email-rmody@brocade.com>
Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/bna/bnad.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index 1954dea..8b1d515 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -65,7 +65,7 @@ struct bnad_rx_ctrl {
#define BNAD_NAME "bna"
#define BNAD_NAME_LEN 64
-#define BNAD_VERSION "2.3.2.0"
+#define BNAD_VERSION "2.3.2.3"
#define BNAD_MAILBOX_MSIX_VECTORS 1
--
1.7.1
^ permalink raw reply related
* Re: [patch] skfp: testing the wrong variable in skfp_driver_init()
From: Jiri Pirko @ 2010-12-24 8:45 UTC (permalink / raw)
To: Dan Carpenter
Cc: netdev, Eric Dumazet, H Hartley Sweeten, David S. Miller,
kernel-janitors
In-Reply-To: <20101224051734.GO1936@bicker>
Fri, Dec 24, 2010 at 06:17:34AM CET, error27@gmail.com wrote:
>The intent here was to test if the allocation failed but we tested
>"SharedMemSize" instead of "SharedMemAddr" by mistake.
>
>Signed-off-by: Dan Carpenter <error27@gmail.com>
>
>diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
>index 0a66fed..16c6265 100644
>--- a/drivers/net/skfp/skfddi.c
>+++ b/drivers/net/skfp/skfddi.c
>@@ -412,7 +412,7 @@ static int skfp_driver_init(struct net_device *dev)
> bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev,
> bp->SharedMemSize,
> &bp->SharedMemDMA);
>- if (!bp->SharedMemSize) {
>+ if (!bp->SharedMemAddr) {
> printk("could not allocate mem for ");
> printk("hardware module: %ld byte\n",
> bp->SharedMemSize);
Looks obvious.
Reviewed-by: Jiri Pirko <jpirko@redhat.com>
^ permalink raw reply
* Re: [PATCH 1/4] net: phy: balance disable/enable irq on change
From: Jean-Michel Hautbois @ 2010-12-24 8:46 UTC (permalink / raw)
To: David Miller
Cc: richard.cochran, shemminger, tj, randy.dunlap, netdev,
linux-kernel
In-Reply-To: <20101223.112450.246547841.davem@davemloft.net>
2010/12/23 David Miller <davem@davemloft.net>:
> From: Jean-Michel Hautbois <jhautbois@gmail.com>
> Date: Sun, 19 Dec 2010 11:58:48 +0100
>
>> When phy interface changes its status, it calls phy_change() function.
>> This function calls the interrupt disabling functions for the driver
>> registered, but if this driver doesn't implement it, there is no IRQ
>> disabling. After doing the work, we call enable_irq and not the
>> respective driver function. This fixes it, as it could lead to an
>> unbalanced IRQ. Error code changed to EOPNOTSUPP.
>>
>> Signed-off-by: Jean-Michel Hautbois <jhautbois@gmail.com>
>
> This is completely bogus.
>
> First of all, there are 5 call sites for phy_change_interrupt() but
> you've only implemented the new semantics for two of those.
>
> Therefore, if we even wanted this, we should implement the behavior in
> phy_change_interrupt() itself instead of duplicating the logic at
> each and every call site.
>
> But we don't want this.
OK, I understand that point.
> It's not appropriate at all. If a device lacks a way to turn
> interrupt off and on, using disable_irq() and enable_irq() is not
> necessarily correct.
>
> If the interrupt line is shared, for example, this will break
> everything.
>
OK, well, maybe is there at least one thing we could do : in
phy_change, instead of calling phy_disable_interrupts(), balanced by
enable_irq, we probably should use phy_enable_interrupts().
^ permalink raw reply
* Re: [PATCH net-next-2.6 1/2] can: add driver for Softing card
From: Kurt Van Dijck @ 2010-12-24 9:14 UTC (permalink / raw)
To: Marc Kleine-Budde
Cc: socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <4D135BC3.6070707-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Marc,
A lot of your remarks do make sense, without further comment.
Some however, I'm not completely sure ...
On Thu, Dec 23, 2010 at 03:25:07PM +0100, Marc Kleine-Budde wrote:
> >
> > obj-y += usb/
> > +obj-y += softing/
>
> I think it will (at least marginally) speed up the Kernel build process
> only to dive into the softing subdir if Softing is enabled in Kconfig.
Due to the independant driver design, I should
(CONFIG_CAN_SOFTING || CONFIG_CAN_SOFTINGCS)
>
> > + ktime_t ts_ref;
> > + ktime_t ts_overflow; /* timestamp overflow value, in ktime */
> > +
> > + struct {
> > + /* indication of firmware status */
> > + int up;
> > + /* protection of the 'up' variable */
> > + struct mutex lock;
> > + } fw;
>
> what about using an atomic_t for the firmware status?
for 'up', yes, but the lock stays. It protects the startup/shutdown
sequence too, ie. only 1 process enters the shutdown sequence.
>
> > +/* SOFTING DPRAM mappings */
> > +struct softing_rx {
> > + u8 fifo[16][32];
> > + u8 dummy1;
>
> Just curious, why did they put a padding byte here, that makes the rest
> unaligned?
I did not design the DPRAM layout. It's just the way it is ...
I did prefer to use structs in virtual memory, and this is the consequence.
>
> > + u32 time;
> > + u32 time_wrap;
> > + u8 wr_start;
> > + u8 wr_end;
> > + u8 dummy10;
> > + u16 dummy12;
> > + u16 dummy12x;
> > + u16 dummy13;
> > + u16 reset_rcv_fifo;
> > + u8 dummy14;
> > + u8 reset_xmt_fifo;
> > + u8 read_fifo_levels;
> > + u16 rcv_fifo_level;
> > + u16 xmt_fifo_level;
> > +} __attribute__((packed));
>
> Can you renumber the dummy variables (there are some "x" in there), or
> does it correspond to some datasheet?
no, there's no datasheet. I started from code released by Softing.
>
> > +
> > diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c
> > +
[...]
> > +int softing_fct_cmd(struct softing *card, int cmd, int vector, const char *msg)
> > +{
> > + int ret;
> > + unsigned long stamp;
> > + if (vector == RES_OK)
> > + vector = RES_NONE;
> > + card->dpram.fct->param[0] = cmd;
>
> param[] is an array of s16 and cmd is an int.
Is this a problem? Is it usefull to define the function with s16 arguments then?
>
> hmmm..all stuff behind dpram is __iomem, isn't it? I think it should
> only be accessed with via the ioread/iowrite operators. Please check
I did an ioremap_nocache. Since it is unaligned, ioread/iowrite would render
a lot of statements.
> your code with sparse (compile with "make C=2").
(?)
>
> > + }
> > + if ((jiffies - stamp) >= 1 * HZ)
>
> That's not good. I don't remember the name, but there are some
> functions/defines to do this kind of things properly.
I'll do a search
>
> > + break;
> > + if (in_interrupt())
> > + /* go as fast as possible */
>
> In the worst case this means you lock up the system for one second. Does
> the card issue an interrupt if it's finished? Another option is to write
> a threaded interrupt handler.
Yep, threaded interrupt handler is something to look at ... later.
>
>
> > +{
> > + int ret;
> > + unsigned long stamp;
> > + card->dpram.receipt[0] = RES_NONE;
> > + card->dpram.command[0] = command;
> > + /* be sure to flush this to the card */
> > + wmb();
> > + stamp = jiffies;
> > + /*wait for card */
> > + do {
> > + ret = card->dpram.receipt[0];
> > + /* don't have any cached variables */
> > + rmb();
> > + if (ret == RES_OK)
> > + return 0;
> > + if ((jiffies - stamp) >= (3 * HZ))
> > + break;
> > + schedule();
>
> same applies here, too. Although this command seems not to be called
> from interrupt context, what about using a msleep() instead of a schedule?
Not calling schedule was really annoying.
>
Thanks for your review,
Kurt
^ permalink raw reply
* Re: [patch] vxge: remove duplicated part of check
From: Julia Lawall @ 2010-12-24 9:34 UTC (permalink / raw)
To: Dan Carpenter
Cc: Ramkrishna Vepa, Sivakumar Subramani, Sreenivasa Honnur,
Jon Mason, netdev, kernel-janitors
In-Reply-To: <20101224061539.GP1936@bicker>
On Fri, 24 Dec 2010, Dan Carpenter wrote:
> This is just a cleanup to make the static checkers happy. We don't need
> to check "own" twice.
It's indeed probably pretty pointless to put if (!A || (B && A)) because
then B, which may rely on A being true, has already occurred. Would
anyone find if (!A || (A && B)) to be useful for readability? I found
20-some other occurrences, mostly of the latter type.
julia
> Signed-off-by: Dan Carpenter <error27@gmail.com>
>
> diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c
> index 42cc298..4c10d6c 100644
> --- a/drivers/net/vxge/vxge-traffic.c
> +++ b/drivers/net/vxge/vxge-traffic.c
> @@ -1240,7 +1240,7 @@ enum vxge_hw_status vxge_hw_ring_rxd_next_completed(
> *t_code = (u8)VXGE_HW_RING_RXD_T_CODE_GET(control_0);
>
> /* check whether it is not the end */
> - if (!own || ((*t_code == VXGE_HW_RING_T_CODE_FRM_DROP) && own)) {
> + if (!own || *t_code == VXGE_HW_RING_T_CODE_FRM_DROP) {
>
> vxge_assert(((struct vxge_hw_ring_rxd_1 *)rxdp)->host_control !=
> 0);
> --
> To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
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