* Re: [PATCH kernel 2.6.32-rc5] pcnet_cs: add cis of PreMax PE-200 ethernet pcmcia card
From: Ken Kawasaki @ 2009-10-25 2:10 UTC (permalink / raw)
To: netdev; +Cc: ben
Hi,
>> > Random question: are CIS files copyrightable?
>>
>> The CIS contains the IRQ, ioport-range, voltage information etc
>> like the PCI config space.
>> So I think it is not copyrightable.
>> but Sierra Wireless provided this CIS by GPL.
>[...]
>If it is subject to copyright - which apparently they think it is - then
>when redistributing under GPL we must be able to provide the 'preferred
>form for modification'. So that leads to the question, is this blob or
>hex file the preferred form?
(1)The CIS contains data only,
does not contain the code to be executed.
(2)Sierra Wireless provided the binary of the CIS only.
(3)These CIS are stable and does not need to be modified.
(3)The content of the CIS can be seen by the dump_cis utility.
So if someone want to modify the CIS , I think it is OK
to use hex editor.
Best Regards
Ken
^ permalink raw reply
* Re: [PATCH kernel 2.6.32-rc5] pcnet_cs: add cis of PreMax PE-200 ethernet pcmcia card
From: Ben Hutchings @ 2009-10-25 2:13 UTC (permalink / raw)
To: Ken Kawasaki; +Cc: netdev
In-Reply-To: <20091025111000.2d97e595.ken_kawasaki@spring.nifty.jp>
[-- Attachment #1: Type: text/plain, Size: 1180 bytes --]
On Sun, 2009-10-25 at 11:10 +0900, Ken Kawasaki wrote:
> Hi,
>
> >> > Random question: are CIS files copyrightable?
> >>
> >> The CIS contains the IRQ, ioport-range, voltage information etc
> >> like the PCI config space.
> >> So I think it is not copyrightable.
> >> but Sierra Wireless provided this CIS by GPL.
> >[...]
>
> >If it is subject to copyright - which apparently they think it is - then
> >when redistributing under GPL we must be able to provide the 'preferred
> >form for modification'. So that leads to the question, is this blob or
> >hex file the preferred form?
>
>
> (1)The CIS contains data only,
> does not contain the code to be executed.
> (2)Sierra Wireless provided the binary of the CIS only.
> (3)These CIS are stable and does not need to be modified.
> (3)The content of the CIS can be seen by the dump_cis utility.
>
> So if someone want to modify the CIS , I think it is OK
> to use hex editor.
That sounds reasonable. Thanks.
Ben.
--
Ben Hutchings
The obvious mathematical breakthrough [to break modern encryption] would be
development of an easy way to factor large prime numbers. - Bill Gates
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]
^ permalink raw reply
* Re: [PATCH] net: allow netdev_wait_allrefs() to run faster
From: Paul E. McKenney @ 2009-10-25 4:47 UTC (permalink / raw)
To: Octavian Purdila; +Cc: Eric Dumazet, Benjamin LaHaise, netdev, Cosmin Ratiu
In-Reply-To: <200910250249.00382.opurdila@ixiacom.com>
On Sun, Oct 25, 2009 at 02:49:00AM +0300, Octavian Purdila wrote:
> On Saturday 24 October 2009 17:24:27 you wrote:
> > Paul E. McKenney a écrit :
> > > On Sat, Oct 24, 2009 at 10:49:55AM +0200, Eric Dumazet wrote:
> > >> On my dev machine, a synchronize_rcu() lasts between 2 an 12 ms
> > >
> > > That sounds like the right range, depending on what else is happening
> > > on the machine at the time.
> > >
> > > The synchronize_rcu_expedited() primitive would run in the 10s-100s
> > > of microseconds. It involves a pair of wakeups and a pair of context
> > > switches on each CPU.
> >
> > Hmm... I'll make some experiments Monday and post results, but it seems
> > very promising.
> >
>
> Got some time today and did some experiments myself. The test is deleting 1000
> dummy interfaces (interface status down, no IP/IPv6 addresses assigned) on a
> UP non-preempt ppc750 @800Mhz system.
>
> 1. Ben's patch:
>
> real 0m 3.42s
> user 0m 0.00s
> sys 0m 0.00s
>
> 2. Eric's schedule_timeout_uninterruptible(1);
>
> real 0m 3.00s
> user 0m 0.00s
> sys 0m 0.00s
>
> 3. Simple synchronize_rcu_expedited()
>
> This doesn't seem to work well with the UP non-preempt case since
> synchronize_rcu_expedited() is a noop in this case - turning
> netdev_wait_allrefs() into a while(1) loop.
Indeed -- but then again, in the UP case, synchronize_rcu() itself
is pretty much a no-op. So if your main target is UP, you should
be able to have seriously fast RCU updates.
(I know, I know, you want SMP to run fast as well...)
Thanx, Paul
^ permalink raw reply
* Re: [PATCH 02/31] swap over network documentation
From: Pavel Machek @ 2009-10-25 6:30 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: Linus Torvalds, Andrew Morton, linux-kernel, linux-mm, netdev,
Neil Brown, Miklos Szeredi, Wouter Verhelst, Peter Zijlstra,
trond.myklebust
In-Reply-To: <1254405891-15724-1-git-send-email-sjayaraman@suse.de>
Hi!
> From: Neil Brown <neilb@suse.de>
>
> Document describing the problem and proposed solution
> +Problem:
> + When Linux needs to allocate memory it may find that there is
> + insufficient free memory so it needs to reclaim space that is in
> + use but not needed at the moment. There are several options:
...
> + 3/ Write out some dirty page-cache pages so that they become clean.
> + The VM limits the number of dirty page-cache pages to e.g. 40%
> + of available memory so that (among other reasons) a "sync" will
> + not take excessively long. So there should never be excessive
> + amounts of dirty pagecache.
I'd say "So it is not common to have excessive...". Yes, we try to
limit it, but IIRC malicious users would still be able to dirty
arbitrary ammounts...
....
> + So anon pages tend to be left until last to be cleaned, and may
> + be the only cleanable pages while there are still some dirty
> + page-cache pages (which are waiting on a GFP_NOFS allocation).
Are you sure? Because this is saying 'Linux is broken without swap'
(and swap-less configs are more and more common).
> + For memory allocated using slab/slub: If a page that is added to a
> + kmem_cache is found to have page->reserve set, then a s->reserve
> + flag is set for the whole kmem_cache. Further allocations will only
> + be returned from that page (or any other page in the cache) if they
> + are emergency allocation (i.e. PF_MEMALLOC or GFP_MEMALLOC is set).
> + Non-emergency allocations will block in alloc_page until a
> + non-reserve page is available. Once a non-reserve page has been
> + added to the cache, the s->reserve flag on the cache is removed.
Does this greatly increase probability of GFP_ATOMIC allocations
failing?
> + Similarly, if an skb is ever queued for delivery to user-space for
> + example by netfilter, the ->emergency flag is tested and the skb is
> + released if ->emergency is set. (so obviously the storage route may
> + not pass through a userspace helper, otherwise the packets will never
> + arrive and we'll deadlock)
(So -- .)
> + pages_emergency can be changed dynamically based on need. When
> + swapout over the network is required, pages_emergency is increased
> + to cover the maximum expected load. When network swapout is
> + disabled, pages_emergency is decreased.
Hmm, increasing pages_emergency is pretty interesting
operation.... right?
> +Thanks for reading this far. I hope it made sense :-)
> +
> +Neil Brown (with updates from Peter Zijlstra)
Well, some warnings are misssing.
For example... swap over nfs over openvpn will do bad bad things,
right? ... and I guess that should be documented.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH] net: allow netdev_wait_allrefs() to run faster
From: Eric Dumazet @ 2009-10-25 8:35 UTC (permalink / raw)
To: Octavian Purdila; +Cc: paulmck, Benjamin LaHaise, netdev, Cosmin Ratiu
In-Reply-To: <200910250249.00382.opurdila@ixiacom.com>
Octavian Purdila a écrit :
>
> Got some time today and did some experiments myself. The test is deleting 1000
> dummy interfaces (interface status down, no IP/IPv6 addresses assigned) on a
> UP non-preempt ppc750 @800Mhz system.
>
> 1. Ben's patch:
>
> real 0m 3.42s
> user 0m 0.00s
> sys 0m 0.00s
>
> 2. Eric's schedule_timeout_uninterruptible(1);
>
> real 0m 3.00s
> user 0m 0.00s
> sys 0m 0.00s
>
> 3. Simple synchronize_rcu_expedited()
>
> This doesn't seem to work well with the UP non-preempt case since
> synchronize_rcu_expedited() is a noop in this case - turning
> netdev_wait_allrefs() into a while(1) loop.
>
Thanks for these numbers. I presume HZ value is 1000 on this platform ?
Could you give us your scripts so that we can use same "benchmark" ?
BTW, I found I could not use IPV6 with many devices on x86_32, because of
the huge per_cpu allocations (on IPV6, each device has percpu SNMP counters)
^ permalink raw reply
* Re: [PATCH v2 1/8] Only parse time stamp TCP option in time wait sock
From: Gilad Ben-Yossef @ 2009-10-25 8:41 UTC (permalink / raw)
To: William Allen Simpson; +Cc: netdev
In-Reply-To: <4ADF5A2F.9010309@gmail.com>
Hello William,
William Allen Simpson wrote:
>> If you examine the specific context where tcp_parse_options is being
>> called here,
>> the only TCP option which is of interest is the time stamp option,
>> and this code path
>> is only being taken when we already know that the original socket had
>> used the time stamp option.
>>
>> So while I agree that in general you are right, I do believe that in
>> the specific context
>> of this patch we should call tcp_parse_options with the established
>> flag on and let it
>> know we are expecting to see a time stamp option, which is what I was
>> referring to.
>>
> No, a major reason for time-wait is rebooted systems. We don't "know"
> anything about them, and they certainly don't know anything about us.
>
> As I mentioned, this is about edge cases.
I just read thoroughly the code in question again -
We use tcp_parse_option to check if there is a time stamp option in the
packet and if so, get the time stamp from it. We do this only when the
time wait minisocket has information of time stamp from the original
connection. We don't use any other TCP option or other inoformation from
the options read via that call.
The above statements are true both for the original code and my patch.
If there is any corner case with my code it is true for the original
code as well.
>
> My suggestion, as this patch is not essential to the other patches in the
> series, is to separate it. As I'm relatively new to this list, I don't
> know the best practice. But I'd like to support the others and delay
> this for further consideration.
I have no objection to separate or drop it altogether if there is a
specific technical reason why you think the code is wrong. It certainly
is possible I've done some done mistake. In that case, I would love
nothing more to hearing what it is and hopefully fixing it.
But "Maybe there are edge cases we didn't think about" is not specific
enough to work upon :-)
Thanks for all the feedback,
Gilad
--
Gilad Ben-Yossef
Chief Coffee Drinker & CTO
Codefidence Ltd.
Web: http://codefidence.com
Cell: +972-52-8260388
Skype: gilad_codefidence
Tel: +972-8-9316883 ext. 201
Fax: +972-8-9316884
Email: gilad@codefidence.com
Check out our Open Source technology and training blog - http://tuxology.net
"Sorry cannot parse this, its too long to be true :)"
-- Eric Dumazet on netdev mailing list
^ permalink raw reply
* Re: [PATCH v2 5/8] Allow disabling TCP timestamp options per route
From: Gilad Ben-Yossef @ 2009-10-25 8:43 UTC (permalink / raw)
To: William Allen Simpson; +Cc: netdev
In-Reply-To: <4ADF5F5A.5090403@gmail.com>
Hi,
William Allen Simpson wrote:
>
>> diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
>> index 9c802a6..2ab8c75 100644
>> --- a/include/linux/rtnetlink.h
>> +++ b/include/linux/rtnetlink.h
>> @@ -378,7 +378,7 @@ enum
>>
>> #define RTAX_FEATURE_ECN 0x00000001
>> #define RTAX_FEATURE_NO_SACK 0x00000002
>> -#define RTAX_FEATURE_TIMESTAMP 0x00000004
>> +#define RTAX_FEATURE_NO_TSTAMP 0x00000004
>> #define RTAX_FEATURE_ALLFRAG 0x00000008
>>
> I just realized that unlike NO_WSCALE, this change assumes removing the
> sysctl and defaulting on.
No, it doesn't. This patch does not change the sysctl behavior in any
way. The RTAX_FEATURE_TIMESTAMP define is a currently a dead code not
used anywhere AFAIK.
Gilad
--
Gilad Ben-Yossef
Chief Coffee Drinker & CTO
Codefidence Ltd.
Web: http://codefidence.com
Cell: +972-52-8260388
Skype: gilad_codefidence
Tel: +972-8-9316883 ext. 201
Fax: +972-8-9316884
Email: gilad@codefidence.com
Check out our Open Source technology and training blog - http://tuxology.net
"Sorry cannot parse this, its too long to be true :)"
-- Eric Dumazet on netdev mailing list
^ permalink raw reply
* Re: [PATCH v2 4/8] Add the no SACK route option feature
From: Gilad Ben-Yossef @ 2009-10-25 8:44 UTC (permalink / raw)
To: William Allen Simpson; +Cc: netdev
In-Reply-To: <4ADF5F77.6050407@gmail.com>
William Allen Simpson wrote:
> Gilad Ben-Yossef wrote:
>> Implement querying and acting upon the no sack bit in the features
>> field.
>>
>> #define RTAX_FEATURE_ECN 0x00000001
>> -#define RTAX_FEATURE_SACK 0x00000002
>> +#define RTAX_FEATURE_NO_SACK 0x00000002
>> #define RTAX_FEATURE_TIMESTAMP 0x00000004
>> #define RTAX_FEATURE_ALLFRAG 0x00000008
>>
> I just realized that unlike NO_DSACK, this change assumes removing the
> sysctl and defaulting on.
Once again, no it does not do no such thing. The sysctl and semantics
stays here just the same.
The RTAX_FEATURE_SACK is not sued AFAIK in current code at all.
Gilad
--
Gilad Ben-Yossef
Chief Coffee Drinker & CTO
Codefidence Ltd.
Web: http://codefidence.com
Cell: +972-52-8260388
Skype: gilad_codefidence
Tel: +972-8-9316883 ext. 201
Fax: +972-8-9316884
Email: gilad@codefidence.com
Check out our Open Source technology and training blog - http://tuxology.net
"Sorry cannot parse this, its too long to be true :)"
-- Eric Dumazet on netdev mailing list
^ permalink raw reply
* Re: [PATCH v2 8/8] Document future removal of sysctl_tcp_* options
From: Gilad Ben-Yossef @ 2009-10-25 8:45 UTC (permalink / raw)
To: William Allen Simpson; +Cc: netdev
In-Reply-To: <4ADF616B.1090405@gmail.com>
William Allen Simpson wrote:
> Gilad Ben-Yossef wrote:
>> I have no issue with leaving those, if everyone thinks we're better off.
>>
>> BTW, while we're talking about OS envy, I do believe that Windows do let
>> you specify on a per route basis. Not that this is really a good
>> ground for
>> technical decision, but still... :-)
>>
> I'm not concerned with "envy", I'm concerned with training operators, and
> consistency across platforms.
>
> I'm in favor of per route configuration, it seems reasonably clean, as
> long as it's done consistently with other systems. I don't permit
> Windows
> systems to be used here (except under controlled security
> circumstances), so
> I'm not familiar with their configuration. However, doing things
> similarly
> across platforms will ease documentation and training.
>
I have no objection leaving the current sysctl as is. Personally, I
think it's useless when you have route level options but I don't care
all that much.
The powers that be are more then welcome to ACK the first 7 patches and
NACK the documentation of the sysctl as deprecated. :-)
Gilad
--
Gilad Ben-Yossef
Chief Coffee Drinker & CTO
Codefidence Ltd.
Web: http://codefidence.com
Cell: +972-52-8260388
Skype: gilad_codefidence
Tel: +972-8-9316883 ext. 201
Fax: +972-8-9316884
Email: gilad@codefidence.com
Check out our Open Source technology and training blog - http://tuxology.net
"Sorry cannot parse this, its too long to be true :)"
-- Eric Dumazet on netdev mailing list
^ permalink raw reply
* Re: [PATCH v2 8/8] Document future removal of sysctl_tcp_* options
From: Gilad Ben-Yossef @ 2009-10-25 9:09 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Bill Fink, William Allen Simpson, netdev
In-Reply-To: <4ADFE635.4020109@gmail.com>
Hi,
Eric Dumazet wrote:
> Bill Fink a écrit :
>
>
>> And as mentioned previously, the global options can be quite useful
>> in certain test scenarios. I also agree the per route settings are
>> a very useful addition. I think the global and per route settings
>> are complementary and shouldn't be thought of as in conflict with
>> one another.
>>
> Absolutely, global setting is a must when an admin wants a quick path.
>
> The more flexible would be to have two bits per route, plus
> 2 bits on the global configuration.
>
> global conf:
> 00 : timestamps OFF, unless a route setting is not 00
> 01 : timestamps ON, unless a route setting is not 00
> 10 : Force timestamps OFF, ignore route settings (emergency sysadmin request)
> 11 : Force timestamps ON, ignore route settings
>
> Route settings (used *only* if global setting is 0Y)
> 00 : global conf is used
> 01 : Force timestamps being OFF for this route
> 10 : Force timestamps being ON for this route
> 11 : complement global conf
> --
>
Hey, I have no issue to re-spin the patch with this suggestion, if you
truly think this is valuable, but would you please consider the
nightmare of having to just explain this to someone?
It sounds to me way too complicated for what it does.
I still think having a global kill switch and per route options better
(basically use the exiting patch but not retire the global kill
switch|), but if you must Hgow about we leave the global sysctl as they
are and just have a two bit route option:
0 Use global default
1 Off
2 On
It's kind of funny, because this is what the original patch from
Comsleep does and I thought it needlessly complicates things.
So, what do you say - which will it be?
Gilad
--
Gilad Ben-Yossef
Chief Coffee Drinker & CTO
Codefidence Ltd.
Web: http://codefidence.com
Cell: +972-52-8260388
Skype: gilad_codefidence
Tel: +972-8-9316883 ext. 201
Fax: +972-8-9316884
Email: gilad@codefidence.com
Check out our Open Source technology and training blog - http://tuxology.net
"Sorry cannot parse this, its too long to be true :)"
-- Eric Dumazet on netdev mailing list
^ permalink raw reply
* [PATCH] sky2: Refactor sky2_get_regs into two functions
From: Mike McCormack @ 2009-10-25 9:42 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
Separate code deciding which registers can be accessed out of sky2_get_regs.
Signed-off-by: Mike McCormack <mikem@ring3k.org>
---
drivers/net/sky2.c | 94 ++++++++++++++++++++++++++-------------------------
1 files changed, 48 insertions(+), 46 deletions(-)
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 2ab5c39..9713527 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -3730,6 +3730,50 @@ static int sky2_get_regs_len(struct net_device *dev)
return 0x4000;
}
+static int sky2_reg_access_ok(struct sky2_hw *hw, unsigned int b)
+{
+ /* This complicated switch statement is to make sure and
+ * only access regions that are unreserved.
+ * Some blocks are only valid on dual port cards.
+ */
+ switch (b) {
+ /* second port */
+ case 5: /* Tx Arbiter 2 */
+ case 9: /* RX2 */
+ case 14 ... 15: /* TX2 */
+ case 17: case 19: /* Ram Buffer 2 */
+ case 22 ... 23: /* Tx Ram Buffer 2 */
+ case 25: /* Rx MAC Fifo 1 */
+ case 27: /* Tx MAC Fifo 2 */
+ case 31: /* GPHY 2 */
+ case 40 ... 47: /* Pattern Ram 2 */
+ case 52: case 54: /* TCP Segmentation 2 */
+ case 112 ... 116: /* GMAC 2 */
+ return hw->ports > 1;
+
+ case 0: /* Control */
+ case 2: /* Mac address */
+ case 4: /* Tx Arbiter 1 */
+ case 7: /* PCI express reg */
+ case 8: /* RX1 */
+ case 12 ... 13: /* TX1 */
+ case 16: case 18:/* Rx Ram Buffer 1 */
+ case 20 ... 21: /* Tx Ram Buffer 1 */
+ case 24: /* Rx MAC Fifo 1 */
+ case 26: /* Tx MAC Fifo 1 */
+ case 28 ... 29: /* Descriptor and status unit */
+ case 30: /* GPHY 1*/
+ case 32 ... 39: /* Pattern Ram 1 */
+ case 48: case 50: /* TCP Segmentation 1 */
+ case 56 ... 60: /* PCI space */
+ case 80 ... 84: /* GMAC 1 */
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
/*
* Returns copy of control register region
* Note: ethtool_get_regs always provides full size (16k) buffer
@@ -3744,55 +3788,13 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
regs->version = 1;
for (b = 0; b < 128; b++) {
- /* This complicated switch statement is to make sure and
- * only access regions that are unreserved.
- * Some blocks are only valid on dual port cards.
- * and block 3 has some special diagnostic registers that
- * are poison.
- */
- switch (b) {
- case 3:
- /* skip diagnostic ram region */
+ /* skip poisonous diagnostic ram region in block 3 */
+ if (b == 3)
memcpy_fromio(p + 0x10, io + 0x10, 128 - 0x10);
- break;
-
- /* dual port cards only */
- case 5: /* Tx Arbiter 2 */
- case 9: /* RX2 */
- case 14 ... 15: /* TX2 */
- case 17: case 19: /* Ram Buffer 2 */
- case 22 ... 23: /* Tx Ram Buffer 2 */
- case 25: /* Rx MAC Fifo 1 */
- case 27: /* Tx MAC Fifo 2 */
- case 31: /* GPHY 2 */
- case 40 ... 47: /* Pattern Ram 2 */
- case 52: case 54: /* TCP Segmentation 2 */
- case 112 ... 116: /* GMAC 2 */
- if (sky2->hw->ports == 1)
- goto reserved;
- /* fall through */
- case 0: /* Control */
- case 2: /* Mac address */
- case 4: /* Tx Arbiter 1 */
- case 7: /* PCI express reg */
- case 8: /* RX1 */
- case 12 ... 13: /* TX1 */
- case 16: case 18:/* Rx Ram Buffer 1 */
- case 20 ... 21: /* Tx Ram Buffer 1 */
- case 24: /* Rx MAC Fifo 1 */
- case 26: /* Tx MAC Fifo 1 */
- case 28 ... 29: /* Descriptor and status unit */
- case 30: /* GPHY 1*/
- case 32 ... 39: /* Pattern Ram 1 */
- case 48: case 50: /* TCP Segmentation 1 */
- case 56 ... 60: /* PCI space */
- case 80 ... 84: /* GMAC 1 */
+ else if (sky2_reg_access_ok(sky2->hw, b))
memcpy_fromio(p, io, 128);
- break;
- default:
-reserved:
+ else
memset(p, 0, 128);
- }
p += 128;
io += 128;
--
1.5.6.5
^ permalink raw reply related
* Re: [PATCH 00/13] TProxy IPv6 support 2nd round
From: Harald Welte @ 2009-10-25 10:16 UTC (permalink / raw)
To: Balazs Scheidler; +Cc: netfilter-devel, netdev
In-Reply-To: <1253548300.12519.20.camel@bzorp.balabit>
Dear Balazs,
as you might have read from other mails (and by the long period of silence),
Patrick McHardy is currently unavailable to perform his usual maintainer
role.
I personally am too much out of touch with recent developments in
netfitler-land to be able to confidently review your patches...
So unless somebody else from the team (Jozsef?, Pablo?) feels confident in
ACKing your patchset, I will have to ask for your patience until Patrick is
back and can do it by himself.
Regards,
Harald
--
- Harald Welte <laforge@netfilter.org> http://netfilter.org/
============================================================================
"Fragmentation is like classful addressing -- an interesting early
architectural error that shows how much experimentation was going
on while IP was being designed." -- Paul Vixie
^ permalink raw reply
* [PATCH net-next] bnx2x: Do Tx handling in a separate tasklet.
From: Vladislav Zolotarov @ 2009-10-25 12:19 UTC (permalink / raw)
To: David S. Miller; +Cc: Eilon Greenstein, Netdev
This patch moves the 'Tx interrupt work' of each Tx queue from the hardIRQ
context to the separate low-latency tasklet. Otherwise there is a possibility
of a software lockup situation in a Tx softIRQ as it handles freeing all skb's
'freed' in (hard)IRQ context.
Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
drivers/net/bnx2x.h | 5 ++
drivers/net/bnx2x_main.c | 160 +++++++++++++++++++++++++++++-----------------
2 files changed, 105 insertions(+), 60 deletions(-)
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h
index c3b32f7..b29680e 100644
--- a/drivers/net/bnx2x.h
+++ b/drivers/net/bnx2x.h
@@ -259,6 +259,11 @@ struct bnx2x_eth_q_stats {
struct bnx2x_fastpath {
struct napi_struct napi;
+/*
+ * Tx tasklet should not run for more than 1 tick. Then it
+ * should reschedule itself.
+ */
+ struct tasklet_struct tx_int_task;
u8 is_rx_queue;
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index 59b58d8..0e2c1cb 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -56,8 +56,8 @@
#include "bnx2x_init_ops.h"
#include "bnx2x_dump.h"
-#define DRV_MODULE_VERSION "1.52.1-1"
-#define DRV_MODULE_RELDATE "2009/10/13"
+#define DRV_MODULE_VERSION "1.52.1-2"
+#define DRV_MODULE_RELDATE "2009/10/25"
#define BNX2X_BC_VER 0x040200
#include <linux/firmware.h>
@@ -784,21 +784,13 @@ static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id,
barrier();
}
-static inline u16 bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
+static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
{
struct host_status_block *fpsb = fp->status_blk;
- u16 rc = 0;
barrier(); /* status block is written to by the chip */
- if (fp->fp_c_idx != fpsb->c_status_block.status_block_index) {
- fp->fp_c_idx = fpsb->c_status_block.status_block_index;
- rc |= 1;
- }
- if (fp->fp_u_idx != fpsb->u_status_block.status_block_index) {
- fp->fp_u_idx = fpsb->u_status_block.status_block_index;
- rc |= 2;
- }
- return rc;
+ fp->fp_c_idx = fpsb->c_status_block.status_block_index;
+ fp->fp_u_idx = fpsb->u_status_block.status_block_index;
}
static u16 bnx2x_ack_int(struct bnx2x *bp)
@@ -838,6 +830,9 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons;
int nbd;
+ /* prefetch skb end pointer to speedup dev_kfree_skb() */
+ prefetch(&skb->end);
+
DP(BNX2X_MSG_OFF, "pkt_idx %d buff @(%p)->skb %p\n",
idx, tx_buf, skb);
@@ -882,7 +877,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
/* release skb */
WARN_ON(!skb);
- dev_kfree_skb_any(skb);
+ dev_kfree_skb(skb);
tx_buf->first_bd = 0;
tx_buf->skb = NULL;
@@ -912,12 +907,23 @@ static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
return (s16)(fp->bp->tx_ring_size) - used;
}
-static void bnx2x_tx_int(struct bnx2x_fastpath *fp)
+static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp, u16 sw_cons)
+{
+ u16 hw_cons;
+
+ /* Tell compiler that status block fields can change */
+ barrier();
+ hw_cons = le16_to_cpu(*fp->tx_cons_sb);
+ return hw_cons != sw_cons;
+}
+
+static void bnx2x_tx_int(unsigned long data)
{
+ struct bnx2x_fastpath *fp = (struct bnx2x_fastpath *)data;
struct bnx2x *bp = fp->bp;
struct netdev_queue *txq;
u16 hw_cons, sw_cons, bd_cons = fp->tx_bd_cons;
- int done = 0;
+ unsigned long start_time = jiffies;
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
@@ -928,7 +934,8 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp)
hw_cons = le16_to_cpu(*fp->tx_cons_sb);
sw_cons = fp->tx_pkt_cons;
- while (sw_cons != hw_cons) {
+ while ((sw_cons != hw_cons) &&
+ (start_time == jiffies)) {
u16 pkt_cons;
pkt_cons = TX_BD(sw_cons);
@@ -945,7 +952,6 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp)
*/
bd_cons = bnx2x_free_tx_pkt(bp, fp, pkt_cons);
sw_cons++;
- done++;
}
fp->tx_pkt_cons = sw_cons;
@@ -954,7 +960,8 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp)
/* TBD need a thresh? */
if (unlikely(netif_tx_queue_stopped(txq))) {
- /* Need to make the tx_bd_cons update visible to start_xmit()
+ /*
+ * Need to make the tx_bd_cons update visible to start_xmit()
* before checking for netif_tx_queue_stopped(). Without the
* memory barrier, there is a small possibility that
* start_xmit() will miss it and cause the queue to be stopped
@@ -967,6 +974,32 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp)
(bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3))
netif_tx_wake_queue(txq);
}
+
+ /*
+ * If the loop was broken by the timeout or/and there is more
+ * Tx work to do, reschedule the task, otherwise reenable interrupts.
+ * Do not restart the task if interrupts are disabled.
+ */
+ if (likely(atomic_read(&bp->intr_sem) == 0)) {
+ if (bnx2x_has_tx_work(fp, sw_cons))
+ tasklet_hi_schedule(&fp->tx_int_task);
+ else {
+ fp->fp_c_idx =
+ fp->status_blk->c_status_block.status_block_index;
+ /*
+ * Ensure that IGU status block is actually read and
+ * the read value is written to the memory before we
+ * check the Tx work.
+ */
+ rmb();
+ if (bnx2x_has_tx_work(fp, sw_cons))
+ tasklet_hi_schedule(&fp->tx_int_task);
+ else
+ bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID,
+ le16_to_cpu(fp->fp_c_idx),
+ IGU_INT_ENABLE, 1);
+ }
+ }
}
#ifdef BCM_CNIC
@@ -1734,6 +1767,7 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
if (unlikely(bp->panic))
return IRQ_HANDLED;
#endif
+
/* Handle Rx or Tx according to MSI-X vector */
if (fp->is_rx_queue) {
prefetch(fp->rx_cons_sb);
@@ -1745,15 +1779,7 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
prefetch(fp->tx_cons_sb);
prefetch(&fp->status_blk->c_status_block.status_block_index);
- bnx2x_update_fpsb_idx(fp);
- rmb();
- bnx2x_tx_int(fp);
-
- /* Re-enable interrupts */
- bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID,
- le16_to_cpu(fp->fp_u_idx), IGU_INT_NOP, 1);
- bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID,
- le16_to_cpu(fp->fp_c_idx), IGU_INT_ENABLE, 1);
+ tasklet_hi_schedule(&fp->tx_int_task);
}
return IRQ_HANDLED;
@@ -1802,17 +1828,7 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
prefetch(&fp->status_blk->c_status_block.
status_block_index);
- bnx2x_update_fpsb_idx(fp);
- rmb();
- bnx2x_tx_int(fp);
-
- /* Re-enable interrupts */
- bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID,
- le16_to_cpu(fp->fp_u_idx),
- IGU_INT_NOP, 1);
- bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID,
- le16_to_cpu(fp->fp_c_idx),
- IGU_INT_ENABLE, 1);
+ tasklet_hi_schedule(&fp->tx_int_task);
}
status &= ~mask;
}
@@ -4673,7 +4689,7 @@ static void bnx2x_timer(unsigned long data)
struct bnx2x_fastpath *fp = &bp->fp[0];
int rc;
- bnx2x_tx_int(fp);
+ tasklet_hi_schedule(&fp->tx_int_task);
rc = bnx2x_rx_int(fp, 1000);
}
@@ -5117,6 +5133,8 @@ static void bnx2x_init_tx_ring(struct bnx2x *bp)
for_each_tx_queue(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j];
+ tasklet_init(&fp->tx_int_task, bnx2x_tx_int, (unsigned long)fp);
+
for (i = 1; i <= NUM_TX_RINGS; i++) {
struct eth_tx_next_bd *tx_next_bd =
&fp->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd;
@@ -7119,20 +7137,38 @@ static void bnx2x_netif_start(struct bnx2x *bp)
if (intr_sem) {
if (netif_running(bp->dev)) {
+ int i;
+
bnx2x_napi_enable(bp);
bnx2x_int_enable(bp);
if (bp->state == BNX2X_STATE_OPEN)
netif_tx_wake_all_queues(bp->dev);
+
+ /* Enable Tx tasklets */
+ for_each_tx_queue(bp, i)
+ tasklet_enable(&bp->fp[i].tx_int_task);
}
}
}
static void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
{
+ int i;
+
bnx2x_int_disable_sync(bp, disable_hw);
bnx2x_napi_disable(bp);
netif_tx_disable(bp->dev);
bp->dev->trans_start = jiffies; /* prevent tx timeout */
+
+ /* Stop Tx tasklet */
+ for_each_tx_queue(bp, i) {
+ struct bnx2x_fastpath *fp = &bp->fp[i];
+
+ /* Stop */
+ tasklet_disable(&fp->tx_int_task);
+ /* Kill */
+ tasklet_kill(&fp->tx_int_task);
+ }
}
/*
@@ -7931,7 +7967,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
cnt = 1000;
while (bnx2x_has_tx_work_unload(fp)) {
- bnx2x_tx_int(fp);
+ bnx2x_tx_int((unsigned long)fp);
if (!cnt) {
BNX2X_ERR("timeout waiting for queue[%d]\n",
i);
@@ -11004,8 +11040,6 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
prefetch(fp->rx_buf_ring[RX_BD(fp->rx_bd_cons)].skb);
prefetch((char *)(fp->rx_buf_ring[RX_BD(fp->rx_bd_cons)].skb) + 256);
- bnx2x_update_fpsb_idx(fp);
-
if (bnx2x_has_rx_work(fp)) {
work_done = bnx2x_rx_int(fp, budget);
@@ -11014,28 +11048,34 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
goto poll_again;
}
- /* bnx2x_has_rx_work() reads the status block, thus we need to
- * ensure that status block indices have been actually read
- * (bnx2x_update_fpsb_idx) prior to this check (bnx2x_has_rx_work)
- * so that we won't write the "newer" value of the status block to IGU
- * (if there was a DMA right after bnx2x_has_rx_work and
- * if there is no rmb, the memory reading (bnx2x_update_fpsb_idx)
- * may be postponed to right before bnx2x_ack_sb). In this case
- * there will never be another interrupt until there is another update
- * of the status block, while there is still unhandled work.
- */
- rmb();
-
+ /* Fall out from the NAPI loop if needed */
if (!bnx2x_has_rx_work(fp)) {
#ifdef BNX2X_STOP_ON_ERROR
poll_panic:
#endif
- napi_complete(napi);
+ fp->fp_u_idx =
+ fp->status_blk->u_status_block.status_block_index;
+ /*
+ * bnx2x_has_rx_work() reads the status block, thus we need
+ * to ensure that status block indices have been actually read
+ * (bnx2x_update_fpsb_idx) prior to this check
+ * (bnx2x_has_rx_work) so that we won't write the "newer"
+ * value of the status block to IGU (if there was a DMA right
+ * after bnx2x_has_rx_work and if there is no rmb, the memory
+ * reading (bnx2x_update_fpsb_idx) may be postponed to right
+ * before bnx2x_ack_sb). In this case there will never be
+ * another interrupt until there is another update of the
+ * status block, while there is still unhandled work.
+ */
+ rmb();
- bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID,
- le16_to_cpu(fp->fp_u_idx), IGU_INT_NOP, 1);
- bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID,
- le16_to_cpu(fp->fp_c_idx), IGU_INT_ENABLE, 1);
+ if (!bnx2x_has_rx_work(fp)) {
+ napi_complete(napi);
+ /* Re-enable interrupts */
+ bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID,
+ le16_to_cpu(fp->fp_u_idx),
+ IGU_INT_ENABLE, 1);
+ }
}
poll_again:
--
1.6.0.4
^ permalink raw reply related
* Re: [PATCH 2/5] page allocator: Do not allow interrupts to use ALLOC_HARDER
From: Stephan von Krawczynski @ 2009-10-25 12:57 UTC (permalink / raw)
To: Mel Gorman
Cc: Frans Pop, Jiri Kosina, Sven Geggus, Karol Lewandowski,
Tobias Oetiker, Rafael J. Wysocki, David Miller, Reinette Chatre,
Kalle Valo, David Rientjes, KOSAKI Motohiro, Mohamed Abbas,
Jens Axboe, John W. Linville, Pekka Enberg,
Bartlomiej Zolnierkiewicz, Greg Kroah-Hartman,
Kernel Testers List, netdev, linux-kernel, linux-mm@kvack.org
In-Reply-To: <20091022163752.GU11778@csn.ul.ie>
On Thu, 22 Oct 2009 17:37:52 +0100
Mel Gorman <mel@csn.ul.ie> wrote:
> In this case, it's ok. It's just a harmless heads-up that the kernel
> looks slightly different than expected. I posted a 2.6.31.4 version of
> the two patches that cause real problems.
After around 12 hours of runtime with patch 1/5 and 2/5 on 2.6.31.4 I can see
no page allocation failure messages so far. I'll keep you informed.
[Update]
After 2 days I still see no failure messages.
[/update]
--
Regards,
Stephan
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH] net: allow netdev_wait_allrefs() to run faster
From: Octavian Purdila @ 2009-10-25 15:19 UTC (permalink / raw)
To: Eric Dumazet; +Cc: paulmck, Benjamin LaHaise, netdev, Cosmin Ratiu
In-Reply-To: <4AE40DBE.8050505@gmail.com>
[-- Attachment #1: Type: Text/Plain, Size: 1468 bytes --]
On Sunday 25 October 2009 10:35:10 you wrote:
> > Got some time today and did some experiments myself. The test is deleting
> > 1000 dummy interfaces (interface status down, no IP/IPv6 addresses
> > assigned) on a UP non-preempt ppc750 @800Mhz system.
> >
> > 1. Ben's patch:
> >
> > real 0m 3.42s
> > user 0m 0.00s
> > sys 0m 0.00s
> >
> > 2. Eric's schedule_timeout_uninterruptible(1);
> >
> > real 0m 3.00s
> > user 0m 0.00s
> > sys 0m 0.00s
> >
> > 3. Simple synchronize_rcu_expedited()
> >
> > This doesn't seem to work well with the UP non-preempt case since
> > synchronize_rcu_expedited() is a noop in this case - turning
> > netdev_wait_allrefs() into a while(1) loop.
>
> Thanks for these numbers. I presume HZ value is 1000 on this platform ?
>
Yes. I've attach the full config to this email as well.
> Could you give us your scripts so that we can use same "benchmark" ?
>
Sure, I've attached the hack module code I've used.
For creating interfaces: echo 1000 > /proc/sys/net/ndst/add
For deleting interface echo start_ifindex stop_ifindex > /proc/sys/net/ndst/del
Some more information:
- on our old and optimized kernel I am getting 0.4s for creating 128000
interfaces and 0.57s for deleting them
- the 2.6.31 kernel I got the 3s numbers does have some patches to speed-up
interface creating and deletion (removal of per device sysctl and dev_snmp6
entries)
I'll start posting the patches we have as RFC.
Thanks,
tavi
[-- Attachment #2: ndst.c --]
[-- Type: text/x-csrc, Size: 4494 bytes --]
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/if_arp.h>
#include <linux/inetdevice.h>
#include <linux/rtnetlink.h>
#include <linux/ip.h>
#include <net/route.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/version.h>
#include <net/ip.h>
#include <net/flow.h>
#include <net/ipv6.h>
#include <linux/netfilter_ipv6.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
#define __INIT_NET(x) x
#else
#include <net/net_namespace.h>
#define __INIT_NET(x) &init_net,x
#endif
#ifndef CONFIG_IXIA_CONSOLE
static inline void
netdev_set_header_ops(struct net_device *dev, const struct header_ops *hops)
{
dev->header_ops = hops;
}
static inline void
netdev_set_ops(struct net_device *dev, const struct net_device_ops *ops)
{
dev->netdev_ops = ops;
}
#endif
static struct net_device_ops ndst_ops = {
};
int ndst_add(int n)
{
int err, i;
struct net_device * dev = NULL;
char name[IFNAMSIZ];
for(i = 0; i < n; i++) {
/* temporary hack until we fix __dev_alloc_name - it is O(n) ! */
rtnl_lock();
do {
static unsigned counter = 1;
snprintf(name, IFNAMSIZ, "ixtest%d", counter++);
} while(__dev_get_by_name(__INIT_NET(name)));
rtnl_unlock();
dev = alloc_netdev(0, name, ether_setup);
if (dev == NULL) {
err = -ENOMEM;
goto err;
}
netdev_set_ops(dev, &ndst_ops);
netdev_set_header_ops(dev, NULL);
err = register_netdev(dev);
if (err)
goto err;
}
return 0;
// Error handling.
err:
if (dev)
free_netdev(dev);
module_put(THIS_MODULE);
printk(KERN_ERR "%s: failed to register netdev: %d\n", __func__, err);
return err;
}
int ndst_del(int start, int stop)
{
struct net_device *dev;
int i;
for(i = start; i <= stop; i++) {
rtnl_lock();
dev = __dev_get_by_index(__INIT_NET(i));
if (!dev) {
rtnl_unlock();
return -EINVAL;
}
unregister_netdevice(dev);
rtnl_unlock();
free_netdev(dev);
}
return 0;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
static int proc_do_add(struct ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp)
#else
static int proc_do_add(struct ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
#endif
{
int ret = 0;
uint32_t data;
ctl->data = &data;
if (write) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
ret = proc_dointvec(ctl, write, filp, buffer, lenp);
#else
ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
#endif
ndst_add(data);
}
return ret;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
static int proc_do_del(struct ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp)
#else
static int proc_do_del(struct ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
#endif
{
int ret = 0;
uint32_t data[2];
ctl->data = data;
if (write) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
ret = proc_dointvec(ctl, write, filp, buffer, lenp);
#else
ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
#endif
ndst_del(data[0], data[1]);
}
return ret;
}
static ctl_table ndst_sysctl_table[] = {
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
.ctl_name = 1,
#endif
.procname = "add",
.maxlen = sizeof(uint32_t),
.mode = 0200,
.proc_handler = &proc_do_add,
},
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
.ctl_name = 2,
#endif
.procname = "del",
.maxlen = 2*sizeof(uint32_t),
.mode = 0200,
.proc_handler = &proc_do_del,
},
{}
};
static ctl_table ndst_sysctl_net_table[] = {
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
.ctl_name = 1024,
#endif
.procname = "ndst",
.data = NULL,
.maxlen = 0,
.mode = 0555,
.child = ndst_sysctl_table
},
{}
};
static ctl_table ndst_sysctl_root[] = {
{
.ctl_name = CTL_NET,
.procname = "net",
.data = NULL,
.maxlen = 0,
.mode = 0555,
.child = ndst_sysctl_net_table
},
{}
};
static struct ctl_table_header *ndst_sysctl_hdr;
int ndst_init(void)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
ndst_sysctl_hdr = register_sysctl_table(ndst_sysctl_root, 0);
#else
ndst_sysctl_hdr = register_sysctl_table(ndst_sysctl_root);
#endif
if (ndst_sysctl_hdr == NULL)
return -EINVAL;
return 0;
}
void ndst_cleanup(void)
{
unregister_sysctl_table(ndst_sysctl_hdr);
}
module_init(ndst_init);
module_exit(ndst_cleanup);
[-- Attachment #3: .config --]
[-- Type: text/plain, Size: 22178 bytes --]
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.31
# Sat Oct 24 20:54:34 2009
#
# CONFIG_PPC64 is not set
#
# Processor support
#
CONFIG_PPC_BOOK3S_32=y
# CONFIG_PPC_85xx is not set
# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_PPC_BOOK3S=y
CONFIG_6xx=y
CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_PPC_HAVE_PMU_SUPPORT=y
# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
# CONFIG_PPC_UDBG_16550 is not set
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
CONFIG_DTC=y
# CONFIG_DEFAULT_UIMAGE is not set
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
CONFIG_CONSTRUCTORS=y
#
# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
#
# RCU Subsystem
#
CONFIG_CLASSIC_RCU=y
# CONFIG_TREE_RCU is not set
# CONFIG_PREEMPT_RCU is not set
# CONFIG_TREE_RCU_TRACE is not set
# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
# CONFIG_SIGNALFD is not set
CONFIG_TIMERFD=y
# CONFIG_EVENTFD is not set
# CONFIG_SHMEM is not set
# CONFIG_AIO is not set
CONFIG_HAVE_PERF_COUNTERS=y
#
# Performance Counters
#
# CONFIG_PERF_COUNTERS is not set
CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_PCI_QUIRKS is not set
# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
CONFIG_TRACEPOINTS=y
CONFIG_MARKERS=y
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
#
# GCOV-based kernel profiling
#
# CONFIG_GCOV_KERNEL is not set
# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_BLOCK is not set
# CONFIG_FREEZER is not set
#
# Platform support
#
# CONFIG_PPC_CHRP is not set
# CONFIG_MPC5121_ADS is not set
# CONFIG_MPC5121_GENERIC is not set
# CONFIG_PPC_MPC52xx is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_AMIGAONE is not set
CONFIG_PPC_IXIA=y
# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# CONFIG_MPIC_WEIRD is not set
# CONFIG_PPC_I8259 is not set
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
# CONFIG_PPC_MPC106 is not set
# CONFIG_PPC_970_NAP is not set
# CONFIG_PPC_INDIRECT_IO is not set
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_TAU is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
#
# CONFIG_HIGHMEM is not set
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
CONFIG_HZ_1000=y
CONFIG_HZ=1000
CONFIG_SCHED_HRTICK=y
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_IOMMU_HELPER is not set
# CONFIG_SWIOTLB is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_MIGRATION is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
CONFIG_HAVE_MLOCK=y
CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
CONFIG_PPC_4K_PAGES=y
# CONFIG_PPC_16K_PAGES is not set
# CONFIG_PPC_64K_PAGES is not set
# CONFIG_PPC_256K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyS0 rootfstype=ramfs powersave=off"
CONFIG_EXTRA_TARGETS=""
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_SYSCALL=y
# CONFIG_PCIEPORTBUS is not set
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCI_IOV is not set
# CONFIG_HAS_RAPIDIO is not set
#
# Advanced setup
#
CONFIG_ADVANCED_OPTIONS=y
CONFIG_LOWMEM_SIZE_BOOL=y
CONFIG_LOWMEM_SIZE=0x70000000
CONFIG_PAGE_OFFSET_BOOL=y
CONFIG_PAGE_OFFSET=0x80000000
CONFIG_KERNEL_START_BOOL=y
CONFIG_KERNEL_START=0x80000000
CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE_BOOL=y
CONFIG_TASK_SIZE=0x70000000
CONFIG_NET=y
#
# Networking options
#
# CONFIG_NET_SYSCTL_DEV is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
# CONFIG_XFRM_STATISTICS is not set
CONFIG_XFRM_IPCOMP=m
CONFIG_NET_KEY=m
# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_ASK_IP_FIB_HASH=y
# CONFIG_IP_FIB_TRIE is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_IXIA_ROUTING=y
# CONFIG_IP_ROUTE_MULTIPATH is not set
# CONFIG_IP_ROUTE_VERBOSE is not set
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_IPV6_OPTIMISTIC_DAD is not set
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
# CONFIG_INET6_IPCOMP is not set
# CONFIG_IPV6_MIP6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
CONFIG_INET6_XFRM_MODE_TRANSPORT=y
CONFIG_INET6_XFRM_MODE_TUNNEL=y
CONFIG_INET6_XFRM_MODE_BEET=y
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
CONFIG_IPV6_SIT=y
CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_IPV6_MROUTE is not set
# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
# CONFIG_NETFILTER_ADVANCED is not set
#
# Core Netfilter Configuration
#
# CONFIG_NETFILTER_NETLINK_LOG is not set
# CONFIG_NF_CONNTRACK is not set
CONFIG_NETFILTER_XTABLES=m
# CONFIG_NETFILTER_XT_TARGET_MARK is not set
# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
# CONFIG_NETFILTER_XT_MATCH_MARK is not set
# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
# CONFIG_NF_DEFRAG_IPV4 is not set
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_FILTER=m
# CONFIG_IP_NF_TARGET_REJECT is not set
# CONFIG_IP_NF_TARGET_LOG is not set
# CONFIG_IP_NF_TARGET_ULOG is not set
# CONFIG_IP_NF_MANGLE is not set
#
# IPv6: Netfilter Configuration
#
CONFIG_IP6_NF_IPTABLES=m
# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
# CONFIG_IP6_NF_TARGET_LOG is not set
CONFIG_IP6_NF_FILTER=m
# CONFIG_IP6_NF_TARGET_REJECT is not set
# CONFIG_IP6_NF_MANGLE is not set
# CONFIG_IP_DCCP is not set
# CONFIG_IP_SCTP is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=y
CONFIG_LLC2=y
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_PHONET is not set
# CONFIG_IEEE802154 is not set
CONFIG_NET_SCHED=y
#
# Queueing/Scheduling
#
# CONFIG_NET_SCH_CBQ is not set
# CONFIG_NET_SCH_HTB is not set
# CONFIG_NET_SCH_HFSC is not set
# CONFIG_NET_SCH_PRIO is not set
# CONFIG_NET_SCH_MULTIQ is not set
# CONFIG_NET_SCH_RED is not set
# CONFIG_NET_SCH_SFQ is not set
# CONFIG_NET_SCH_TEQL is not set
CONFIG_NET_SCH_TBF=m
# CONFIG_NET_SCH_GRED is not set
# CONFIG_NET_SCH_DSMARK is not set
# CONFIG_NET_SCH_NETEM is not set
# CONFIG_NET_SCH_DRR is not set
CONFIG_NET_SCH_INGRESS=m
#
# Classification
#
CONFIG_NET_CLS=y
# CONFIG_NET_CLS_BASIC is not set
CONFIG_NET_CLS_TCINDEX=m
CONFIG_NET_CLS_ROUTE4=m
CONFIG_NET_CLS_ROUTE=y
CONFIG_NET_CLS_FW=m
CONFIG_NET_CLS_U32=m
# CONFIG_CLS_U32_PERF is not set
# CONFIG_CLS_U32_MARK is not set
# CONFIG_NET_CLS_RSVP is not set
# CONFIG_NET_CLS_RSVP6 is not set
# CONFIG_NET_CLS_FLOW is not set
# CONFIG_NET_EMATCH is not set
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
# CONFIG_NET_ACT_GACT is not set
# CONFIG_NET_ACT_MIRRED is not set
# CONFIG_NET_ACT_IPT is not set
# CONFIG_NET_ACT_NAT is not set
# CONFIG_NET_ACT_PEDIT is not set
# CONFIG_NET_ACT_SIMP is not set
# CONFIG_NET_ACT_SKBEDIT is not set
# CONFIG_NET_CLS_IND is not set
CONFIG_NET_SCH_FIFO=y
# CONFIG_DCB is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_DROP_MONITOR is not set
CONFIG_NET_TXTIMESTAMP=y
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
CONFIG_FIB_RULES=y
# CONFIG_WIRELESS is not set
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
#
# Device Drivers
#
#
# Generic Driver Options
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
# CONFIG_MTD is not set
CONFIG_OF_DEVICE=y
# CONFIG_PARPORT is not set
# CONFIG_MISC_DEVICES is not set
CONFIG_HAVE_IDE=y
#
# SCSI device support
#
# CONFIG_SCSI_DMA is not set
# CONFIG_SCSI_NETLINK is not set
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
#
# You can enable one or both FireWire driver stacks.
#
#
# See the help texts for more information.
#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
# CONFIG_IFB is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
# CONFIG_ARCNET is not set
# CONFIG_NET_ETHERNET is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
#
# Wireless LAN
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_ISDN is not set
# CONFIG_PHONE is not set
#
# Input device support
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
#
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
#
# Hardware I/O ports
#
# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
# Character devices
#
# CONFIG_VT is not set
CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_NOZOMI is not set
#
# Serial drivers
#
# CONFIG_SERIAL_8250 is not set
#
# Non-8250 serial port support
#
# CONFIG_SERIAL_UARTLITE is not set
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m
# CONFIG_HW_RANDOM_TIMERIOMEM is not set
# CONFIG_NVRAM is not set
# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
CONFIG_IXIA_CONSOLE=y
# CONFIG_I2C is not set
# CONFIG_SPI is not set
#
# PPS support
#
# CONFIG_PPS is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_REGULATOR is not set
# CONFIG_MEDIA_SUPPORT is not set
#
# Graphics support
#
# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
# CONFIG_FB is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
# CONFIG_SOUND is not set
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
# CONFIG_EDAC is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
#
# TI VLYNQ
#
# CONFIG_STAGING is not set
#
# File systems
#
CONFIG_FILE_LOCKING=y
CONFIG_FSNOTIFY=y
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY is not set
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
#
# Caches
#
# CONFIG_FSCACHE is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
# CONFIG_PROC_PAGE_MONITOR is not set
# CONFIG_SYSFS is not set
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_MISC_FILESYSTEMS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
# CONFIG_NLS is not set
CONFIG_BINARY_PRINTF=y
#
# Library routines
#
CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
# CONFIG_CRC32 is not set
# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_DECOMPRESS_GZIP=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_HAVE_LMB=y
CONFIG_NLATTR=y
CONFIG_GENERIC_ATOMIC64=y
#
# Kernel hacking
#
CONFIG_PRINTK_TIME=y
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
# CONFIG_DETECT_SOFTLOCKUP is not set
# CONFIG_DETECT_HUNG_TASK is not set
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_LOCK_ALLOC is not set
# CONFIG_PROVE_LOCKING is not set
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_EVENT_TRACING=y
CONFIG_CONTEXT_SWITCH_TRACER=y
CONFIG_TRACING=y
CONFIG_TRACING_SUPPORT=y
# CONFIG_FTRACE is not set
# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
# CONFIG_KMEMCHECK is not set
# CONFIG_PPC_DISABLE_WERROR is not set
CONFIG_PPC_WERROR=y
CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_PPC_EMULATED_STATS is not set
# CONFIG_CODE_PATCHING_SELFTEST is not set
# CONFIG_FTR_FIXUP_SELFTEST is not set
# CONFIG_MSI_BITMAP_SELFTEST is not set
# CONFIG_XMON is not set
# CONFIG_IRQSTACKS is not set
# CONFIG_VIRQ_DEBUG is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=m
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_AUTHENC=m
# CONFIG_CRYPTO_TEST is not set
#
# Authenticated Encryption with Associated Data
#
# CONFIG_CRYPTO_CCM is not set
# CONFIG_CRYPTO_GCM is not set
# CONFIG_CRYPTO_SEQIV is not set
#
# Block modes
#
CONFIG_CRYPTO_CBC=y
# CONFIG_CRYPTO_CTR is not set
# CONFIG_CRYPTO_CTS is not set
# CONFIG_CRYPTO_ECB is not set
# CONFIG_CRYPTO_LRW is not set
# CONFIG_CRYPTO_PCBC is not set
# CONFIG_CRYPTO_XTS is not set
#
# Hash modes
#
CONFIG_CRYPTO_HMAC=y
# CONFIG_CRYPTO_XCBC is not set
#
# Digest
#
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_RMD128 is not set
# CONFIG_CRYPTO_RMD160 is not set
# CONFIG_CRYPTO_RMD256 is not set
# CONFIG_CRYPTO_RMD320 is not set
CONFIG_CRYPTO_SHA1=y
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_TGR192 is not set
# CONFIG_CRYPTO_WP512 is not set
#
# Ciphers
#
# CONFIG_CRYPTO_AES is not set
# CONFIG_CRYPTO_ANUBIS is not set
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_SALSA20 is not set
# CONFIG_CRYPTO_SEED is not set
# CONFIG_CRYPTO_SERPENT is not set
# CONFIG_CRYPTO_TEA is not set
# CONFIG_CRYPTO_TWOFISH is not set
#
# Compression
#
CONFIG_CRYPTO_DEFLATE=y
# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
#
# Random Number Generation
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
# CONFIG_PPC_CLOCK is not set
# CONFIG_VIRTUALIZATION is not set
^ permalink raw reply
* Re: [PATCH] sky2: Refactor sky2_get_regs into two functions
From: Stephen Hemminger @ 2009-10-25 16:46 UTC (permalink / raw)
To: Mike McCormack; +Cc: netdev
In-Reply-To: <4AE41D88.4000100@ring3k.org>
On Sun, 25 Oct 2009 18:42:32 +0900
Mike McCormack <mikem@ring3k.org> wrote:
> Separate code deciding which registers can be accessed out of sky2_get_regs.
>
> Signed-off-by: Mike McCormack <mikem@ring3k.org>
> ---
> drivers/net/sky2.c | 94 ++++++++++++++++++++++++++-------------------------
> 1 files changed, 48 insertions(+), 46 deletions(-)
Ok, but hold off applying upstream, since I have new version (support for
additional chip type), and want to not worry about patch conflict.
Acked-by: Stephen Hemminger <shemminger@vyatta.com>
--
^ permalink raw reply
* [RFC] make per interface sysctl entries configurable
From: Octavian Purdila @ 2009-10-25 17:54 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Benjamin LaHaise, Stephen Hemminger, Cosmin Ratiu, netdev
[-- Attachment #1: Type: text/plain, Size: 436 bytes --]
RFC patches are attached.
Another possible approach: add an interface flag and use it to decide whether
we want per interface sysctl entries or not.
Benchmarks for creating 1000 interface (with the ndst module previously posted
on the list, ppc750 @800Mhz machine):
- without the patches:
real 4m 38.27s
user 0m 0.00s
sys 2m 18.90s
- with the patches:
real 0m 0.10s
user 0m 0.00s
sys 0m 0.05s
Thanks,
tavi
[-- Attachment #2: 818108.diff --]
[-- Type: text/x-patch, Size: 2756 bytes --]
net: CONFIG_NET_SYSCTL_DEV: make per interface dev_snmp6 proc entries optional
Use same CONFIG_NET_SYSCTL_DEV config option (we should probably
rename it to a better name) to enable/disable per interface dev_snmp6
proc entries.
--- //packages/linux_2.6.31/rc7/src/arch/powerpc/configs/ixia_ppc750_defconfig
+++ //packages/linux_2.6.31/rc7/src/arch/powerpc/configs/ixia_ppc750_defconfig
@@ -287,6 +287,7 @@
#
# Networking options
#
+# CONFIG_NET_SYSCTL_DEV is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
--- //packages/linux_2.6.31/rc7/src/net/Kconfig
+++ //packages/linux_2.6.31/rc7/src/net/Kconfig
@@ -25,6 +25,15 @@
menu "Networking options"
+config NET_SYSCTL_DEV
+ bool "Per device sysctl entries"
+ default y
+ depends on SYSCTL
+ help
+ Enables per device sysctl entries. You want this enabled unless
+ your system has a large number of interfaces and you want to reduce
+ memory usage.
+
source "net/packet/Kconfig"
source "net/unix/Kconfig"
source "net/xfrm/Kconfig"
--- //packages/linux_2.6.31/rc7/src/net/ipv4/devinet.c
+++ //packages/linux_2.6.31/rc7/src/net/ipv4/devinet.c
@@ -97,7 +97,7 @@
static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
int destroy);
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NET_SYSCTL_DEV
static void devinet_sysctl_register(struct in_device *idev);
static void devinet_sysctl_unregister(struct in_device *idev);
#else
@@ -1397,7 +1397,6 @@
return ret;
}
-
#define DEVINET_SYSCTL_ENTRY(attr, name, mval, proc, sysctl) \
{ \
.ctl_name = NET_IPV4_CONF_ ## attr, \
@@ -1531,6 +1530,7 @@
kfree(t);
}
+#ifdef CONFIG_NET_SYSCTL_DEV
static void devinet_sysctl_register(struct in_device *idev)
{
neigh_sysctl_register(idev->dev, idev->arp_parms, NET_IPV4,
@@ -1544,6 +1544,7 @@
__devinet_sysctl_unregister(&idev->cnf);
neigh_sysctl_unregister(idev->arp_parms);
}
+#endif
static struct ctl_table ctl_forward_entry[] = {
{
--- //packages/linux_2.6.31/rc7/src/net/ipv6/addrconf.c
+++ //packages/linux_2.6.31/rc7/src/net/ipv6/addrconf.c
@@ -100,7 +100,7 @@
#define INFINITY_LIFE_TIME 0xFFFFFFFF
#define TIME_DELTA(a,b) ((unsigned long)((long)(a) - (long)(b)))
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NET_SYSCTL_DEV
static void addrconf_sysctl_register(struct inet6_dev *idev);
static void addrconf_sysctl_unregister(struct inet6_dev *idev);
#else
@@ -4412,6 +4412,7 @@
kfree(t);
}
+#ifdef CONFIG_NET_SYSCTL_DEV
static void addrconf_sysctl_register(struct inet6_dev *idev)
{
neigh_sysctl_register(idev->dev, idev->nd_parms, NET_IPV6,
@@ -4427,7 +4428,7 @@
__addrconf_sysctl_unregister(&idev->cnf);
neigh_sysctl_unregister(idev->nd_parms);
}
-
+#endif
#endif
[-- Attachment #3: 818110.diff --]
[-- Type: text/x-patch, Size: 1277 bytes --]
net: CONFIG_NET_SYSCTL_DEV: make per interface dev_snmp6 proc entries optional
Use same CONFIG_NET_SYSCTL_DEV config option (we should probably
rename it to a better name) to enable/disable per interface dev_snmp6
proc entries.
--- //packages/linux_2.6.31/rc7/src/include/net/ipv6.h
+++ //packages/linux_2.6.31/rc7/src/include/net/ipv6.h
@@ -604,8 +604,14 @@
extern void udplite6_proc_exit(void);
extern int ipv6_misc_proc_init(void);
extern void ipv6_misc_proc_exit(void);
+
+#ifdef CONFIG_NET_SYSCTL_DEV
extern int snmp6_register_dev(struct inet6_dev *idev);
extern int snmp6_unregister_dev(struct inet6_dev *idev);
+#else
+static inline int snmp6_register_dev(struct inet6_dev *idev) { return 0; }
+static inline int snmp6_unregister_dev(struct inet6_dev *idev) { return 0; }
+#endif
#else
static inline int ac6_proc_init(struct net *net) { return 0; }
--- //packages/linux_2.6.31/rc7/src/net/ipv6/proc.c
+++ //packages/linux_2.6.31/rc7/src/net/ipv6/proc.c
@@ -232,6 +232,7 @@
.release = single_release,
};
+#ifdef CONFIG_NET_SYSCTL_DEV
int snmp6_register_dev(struct inet6_dev *idev)
{
struct proc_dir_entry *p;
@@ -266,6 +267,7 @@
idev->stats.proc_dir_entry = NULL;
return 0;
}
+#endif
static int ipv6_proc_init_net(struct net *net)
{
^ permalink raw reply
* Re: [RFC] make per interface sysctl entries configurable
From: Denys Fedoryschenko @ 2009-10-25 18:07 UTC (permalink / raw)
To: Octavian Purdila
Cc: Eric Dumazet, Benjamin LaHaise, Stephen Hemminger, Cosmin Ratiu,
netdev
In-Reply-To: <200910251954.49700.opurdila@ixiacom.com>
Very interesting patch, because i have PPPoE and sysctl locking issue my issue
N1(accorting to perf and oprofile) on massive pppoe login and during
operation.
Probably i will try to apply it on one of loaded (but redundant, in case it
will crash) pppoe.
On Sunday 25 October 2009 19:54:49 Octavian Purdila wrote:
> RFC patches are attached.
>
> Another possible approach: add an interface flag and use it to decide
> whether we want per interface sysctl entries or not.
>
> Benchmarks for creating 1000 interface (with the ndst module previously
> posted on the list, ppc750 @800Mhz machine):
>
> - without the patches:
>
> real 4m 38.27s
> user 0m 0.00s
> sys 2m 18.90s
>
> - with the patches:
>
> real 0m 0.10s
> user 0m 0.00s
> sys 0m 0.05s
>
> Thanks,
> tavi
^ permalink raw reply
* Re: kernel panic in latest vanilla stable, while using nameif with "alive" pppoe interfaces
From: Denys Fedoryschenko @ 2009-10-25 18:10 UTC (permalink / raw)
To: Cyrill Gorcunov
Cc: netdev, Michal Ostrowski, Eric Dumazet, linux-ppp, paulus,
mostrows
In-Reply-To: <20091023151837.GB5394@lenovo>
On Friday 23 October 2009 18:18:37 Cyrill Gorcunov wrote:
> [Cyrill Gorcunov - Tue, Oct 20, 2009 at 11:08:21PM +0400]
> ...
>
> | Just to update status of the issue. The key moment is that
> | pppoe_flush_dev may be called asynchronously (especially via sysfs on dev
> | entry, for example we retrieve mtu of device and while we at it other
> | process may update mtu via sysfs). So I'm returning pppoe_hash_lock back
> | which should eliminate a number of lock complains and make locking scheme
> | easier. All-in-one: I'm working on it. Just need some more time.
> |
> | -- Cyrill
>
> Another status update -- the patch is under testing stage. Hope we will
> reveal proper patch soon (in a few days I guess).
>
> -- Cyrill
During normal operation till now no issues (2 days uptime, 100-150 users
online on this pppoe). Testing more some stress scenarios.
^ permalink raw reply
* Re: [PATCH] net: allow netdev_wait_allrefs() to run faster
From: Eric Dumazet @ 2009-10-25 19:28 UTC (permalink / raw)
To: Octavian Purdila; +Cc: paulmck, Benjamin LaHaise, netdev, Cosmin Ratiu
In-Reply-To: <200910251719.13748.opurdila@ixiacom.com>
Octavian Purdila a écrit :
> On Sunday 25 October 2009 10:35:10 you wrote:
>>> Got some time today and did some experiments myself. The test is deleting
>>> 1000 dummy interfaces (interface status down, no IP/IPv6 addresses
>>> assigned) on a UP non-preempt ppc750 @800Mhz system.
>>>
>>> 1. Ben's patch:
>>>
>>> real 0m 3.42s
>>> user 0m 0.00s
>>> sys 0m 0.00s
>>>
>>> 2. Eric's schedule_timeout_uninterruptible(1);
>>>
>>> real 0m 3.00s
>>> user 0m 0.00s
>>> sys 0m 0.00s
>>>
>>> 3. Simple synchronize_rcu_expedited()
>>>
>>> This doesn't seem to work well with the UP non-preempt case since
>>> synchronize_rcu_expedited() is a noop in this case - turning
>>> netdev_wait_allrefs() into a while(1) loop.
>> Thanks for these numbers. I presume HZ value is 1000 on this platform ?
>>
>
> Yes. I've attach the full config to this email as well.
>
>> Could you give us your scripts so that we can use same "benchmark" ?
>>
>
> Sure, I've attached the hack module code I've used.
>
> For creating interfaces: echo 1000 > /proc/sys/net/ndst/add
> For deleting interface echo start_ifindex stop_ifindex > /proc/sys/net/ndst/del
>
> Some more information:
>
> - on our old and optimized kernel I am getting 0.4s for creating 128000
> interfaces and 0.57s for deleting them
>
> - the 2.6.31 kernel I got the 3s numbers does have some patches to speed-up
> interface creating and deletion (removal of per device sysctl and dev_snmp6
> entries)
>
> I'll start posting the patches we have as RFC.
>
OK thanks, I thought you were using dummy module
$ time insmod drivers/net/dummy.ko numdummies=100
real 0m2.493s
user 0m0.001s
sys 0m0.021s
$ time rmmod dummy
real 0m1.610s
user 0m0.000s
sys 0m0.001s
$ time insmod drivers/net/dummy.ko numdummies=200
real 0m10.118s
user 0m0.000s
sys 0m0.015s
$ time rmmod dummy
real 0m3.218s
user 0m0.000s
sys 0m0.001s
$ time insmod drivers/net/dummy.ko numdummies=300
real 0m22.564s
user 0m0.000s
sys 0m0.034s
$ time rmmod dummy
real 0m4.755s
user 0m0.000s
sys 0m0.006s
$ perf record -f insmod drivers/net/dummy.ko numdummies=300
$ perf report
# Samples: 898
#
# Overhead Command Shared Object Symbol
# ........ ....... ...................... ......
#
41.65% insmod [kernel] [k] __register_sysctl_paths
22.83% insmod [kernel] [k] strcmp
5.46% insmod [kernel] [k] pcpu_alloc
2.23% insmod [kernel] [k] sysfs_find_dirent
1.56% insmod [kernel] [k] __sysfs_add_one
1.11% insmod [kernel] [k] pcpu_alloc_area
1.11% insmod [kernel] [k] _spin_lock
1.00% insmod [kernel] [k] kmemdup
1.00% insmod [kernel] [k] kmem_cache_alloc
0.67% insmod [kernel] [k] find_symbol_in_section
0.67% insmod [kernel] [k] find_next_zero_bit
0.67% insmod [kernel] [k] idr_get_empty_slot
0.67% insmod [kernel] [k] mutex_lock
0.67% insmod [kernel] [k] mutex_unlock
0.56% insmod [kernel] [k] vunmap_page_range
0.56% insmod [kernel] [k] __slab_alloc
^ permalink raw reply
* [PATCH 0/9] Gigaset driver patches for 2.6.33
From: Tilman Schmidt @ 2009-10-25 19:29 UTC (permalink / raw)
To: David Miller, Karsten Keil
Cc: Hansjoerg Lipp, netdev, linux-kernel, isdn4linux, i4ldeveloper
David, Karsten,
here's a series of patches that should be applied on top of those
currently in net-next. I'm sending them now to leave you enough time
before the next merge window to decide who wants to handle them.
In particular, patch 3 provides an important bugfix to the new CAPI
interface which is necessary for using it with pppd capiplugin.
Thanks,
Tilman
^ permalink raw reply
* [PATCH 1/9] gigaset: CAPI module readability improvements
From: Tilman Schmidt @ 2009-10-25 19:29 UTC (permalink / raw)
To: David Miller, Karsten Keil
Cc: Hansjoerg Lipp, netdev, linux-kernel, isdn4linux, i4ldeveloper
In-Reply-To: <20091023-patch-gigaset-00.tilman@imap.cc>
Replace the "ignoring Additional Info" warning message by better
readable ones citing the specific subparameters being ignored.
Make parts of the code more readable by using a local cmsg
pointer variable.
Impact: readability improvement
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
---
drivers/isdn/gigaset/capi.c | 144 ++++++++++++++++++++++++-------------------
1 files changed, 81 insertions(+), 63 deletions(-)
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index c276a92..ac0a2da 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -168,14 +168,6 @@ static inline void ignore_cstruct_param(struct cardstate *cs, _cstruct param,
msgname, paramname);
}
-static inline void ignore_cmstruct_param(struct cardstate *cs, _cmstruct param,
- char *msgname, char *paramname)
-{
- if (param != CAPI_DEFAULT)
- dev_warn(cs->dev, "%s: ignoring unsupported parameter: %s\n",
- msgname, paramname);
-}
-
/*
* check for legal hex digit
*/
@@ -1062,6 +1054,7 @@ static void do_facility_req(struct gigaset_capi_ctr *iif,
struct sk_buff *skb)
{
struct cardstate *cs = iif->ctr.driverdata;
+ _cmsg *cmsg = &iif->acmsg;
struct sk_buff *cskb;
u8 *pparam;
unsigned int msgsize = CAPI_FACILITY_CONF_BASELEN;
@@ -1069,14 +1062,14 @@ static void do_facility_req(struct gigaset_capi_ctr *iif,
static u8 confparam[10]; /* max. 9 octets + length byte */
/* decode message */
- capi_message2cmsg(&iif->acmsg, skb->data);
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
+ capi_message2cmsg(cmsg, skb->data);
+ dump_cmsg(DEBUG_CMD, __func__, cmsg);
/*
* Facility Request Parameter is not decoded by capi_message2cmsg()
* encoding depends on Facility Selector
*/
- switch (iif->acmsg.FacilitySelector) {
+ switch (cmsg->FacilitySelector) {
case CAPI_FACILITY_DTMF: /* ToDo */
info = CapiFacilityNotSupported;
confparam[0] = 2; /* length */
@@ -1093,7 +1086,7 @@ static void do_facility_req(struct gigaset_capi_ctr *iif,
case CAPI_FACILITY_SUPPSVC:
/* decode Function parameter */
- pparam = iif->acmsg.FacilityRequestParameter;
+ pparam = cmsg->FacilityRequestParameter;
if (pparam == NULL || *pparam < 2) {
dev_notice(cs->dev, "%s: %s missing\n", "FACILITY_REQ",
"Facility Request Parameter");
@@ -1141,18 +1134,18 @@ static void do_facility_req(struct gigaset_capi_ctr *iif,
}
/* send FACILITY_CONF with given Info and confirmation parameter */
- capi_cmsg_answer(&iif->acmsg);
- iif->acmsg.Info = info;
- iif->acmsg.FacilityConfirmationParameter = confparam;
+ capi_cmsg_answer(cmsg);
+ cmsg->Info = info;
+ cmsg->FacilityConfirmationParameter = confparam;
msgsize += confparam[0]; /* length */
cskb = alloc_skb(msgsize, GFP_ATOMIC);
if (!cskb) {
dev_err(cs->dev, "%s: out of memory\n", __func__);
return;
}
- capi_cmsg2message(&iif->acmsg, __skb_put(cskb, msgsize));
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
- capi_ctr_handle_message(&iif->ctr, ap->id, cskb);
+ capi_cmsg2message(cmsg, __skb_put(cskb, msgsize));
+ dump_cmsg(DEBUG_CMD, __func__, cmsg);
+ capi_ctr_handle_message(&iif->ctr, ap->id, cskb);
}
@@ -1207,8 +1200,8 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
u16 info;
/* decode message */
- capi_message2cmsg(&iif->acmsg, skb->data);
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
+ capi_message2cmsg(cmsg, skb->data);
+ dump_cmsg(DEBUG_CMD, __func__, cmsg);
/* get free B channel & construct PLCI */
bcs = gigaset_get_free_channel(cs);
@@ -1411,8 +1404,16 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
"CONNECT_REQ", "Calling pty subaddr");
ignore_cstruct_param(cs, cmsg->LLC,
"CONNECT_REQ", "LLC");
- ignore_cmstruct_param(cs, cmsg->AdditionalInfo,
- "CONNECT_REQ", "Additional Info");
+ if (cmsg->AdditionalInfo != CAPI_DEFAULT) {
+ ignore_cstruct_param(cs, cmsg->BChannelinformation,
+ "CONNECT_REQ", "B Channel Information");
+ ignore_cstruct_param(cs, cmsg->Keypadfacility,
+ "CONNECT_REQ", "Keypad Facility");
+ ignore_cstruct_param(cs, cmsg->Useruserdata,
+ "CONNECT_REQ", "User-User Data");
+ ignore_cstruct_param(cs, cmsg->Facilitydataarray,
+ "CONNECT_REQ", "Facility Data Array");
+ }
/* encode parameter: B channel to use */
commands[AT_ISO] = kmalloc(9, GFP_KERNEL);
@@ -1458,8 +1459,8 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
int channel;
/* decode message */
- capi_message2cmsg(&iif->acmsg, skb->data);
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
+ capi_message2cmsg(cmsg, skb->data);
+ dump_cmsg(DEBUG_CMD, __func__, cmsg);
dev_kfree_skb(skb);
/* extract and check channel number from PLCI */
@@ -1524,8 +1525,16 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
"CONNECT_RESP", "Connected Subaddress");
ignore_cstruct_param(cs, cmsg->LLC,
"CONNECT_RESP", "LLC");
- ignore_cmstruct_param(cs, cmsg->AdditionalInfo,
- "CONNECT_RESP", "Additional Info");
+ if (cmsg->AdditionalInfo != CAPI_DEFAULT) {
+ ignore_cstruct_param(cs, cmsg->BChannelinformation,
+ "CONNECT_RESP", "BChannel Information");
+ ignore_cstruct_param(cs, cmsg->Keypadfacility,
+ "CONNECT_RESP", "Keypad Facility");
+ ignore_cstruct_param(cs, cmsg->Useruserdata,
+ "CONNECT_RESP", "User-User Data");
+ ignore_cstruct_param(cs, cmsg->Facilitydataarray,
+ "CONNECT_RESP", "Facility Data Array");
+ }
/* Accept call */
if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state,
@@ -1587,17 +1596,18 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,
struct sk_buff *skb)
{
struct cardstate *cs = iif->ctr.driverdata;
+ _cmsg *cmsg = &iif->acmsg;
int channel;
/* decode message */
- capi_message2cmsg(&iif->acmsg, skb->data);
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
+ capi_message2cmsg(cmsg, skb->data);
+ dump_cmsg(DEBUG_CMD, __func__, cmsg);
/* extract and check channel number from PLCI */
- channel = (iif->acmsg.adr.adrPLCI >> 8) & 0xff;
+ channel = (cmsg->adr.adrPLCI >> 8) & 0xff;
if (!channel || channel > cs->channels) {
dev_notice(cs->dev, "%s: invalid %s 0x%02x\n",
- "CONNECT_B3_REQ", "PLCI", iif->acmsg.adr.adrPLCI);
+ "CONNECT_B3_REQ", "PLCI", cmsg->adr.adrPLCI);
send_conf(iif, ap, skb, CapiIllContrPlciNcci);
return;
}
@@ -1606,14 +1616,12 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,
ap->connected = APCONN_ACTIVE;
/* build NCCI: always 1 (one B3 connection only) */
- iif->acmsg.adr.adrNCCI |= 1 << 16;
+ cmsg->adr.adrNCCI |= 1 << 16;
/* NCPI parameter: not applicable for B3 Transparent */
- ignore_cstruct_param(cs, iif->acmsg.NCPI,
- "CONNECT_B3_REQ", "NCPI");
- send_conf(iif, ap, skb,
- (iif->acmsg.NCPI && iif->acmsg.NCPI[0]) ?
- CapiNcpiNotSupportedByProtocol : CapiSuccess);
+ ignore_cstruct_param(cs, cmsg->NCPI, "CONNECT_B3_REQ", "NCPI");
+ send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ?
+ CapiNcpiNotSupportedByProtocol : CapiSuccess);
}
/*
@@ -1628,27 +1636,28 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif,
struct sk_buff *skb)
{
struct cardstate *cs = iif->ctr.driverdata;
- struct bc_state *bcs = NULL;
+ _cmsg *cmsg = &iif->acmsg;
+ struct bc_state *bcs;
int channel;
unsigned int msgsize;
u8 command;
/* decode message */
- capi_message2cmsg(&iif->acmsg, skb->data);
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
+ capi_message2cmsg(cmsg, skb->data);
+ dump_cmsg(DEBUG_CMD, __func__, cmsg);
/* extract and check channel number and NCCI */
- channel = (iif->acmsg.adr.adrNCCI >> 8) & 0xff;
+ channel = (cmsg->adr.adrNCCI >> 8) & 0xff;
if (!channel || channel > cs->channels ||
- ((iif->acmsg.adr.adrNCCI >> 16) & 0xffff) != 1) {
+ ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) {
dev_notice(cs->dev, "%s: invalid %s 0x%02x\n",
- "CONNECT_B3_RESP", "NCCI", iif->acmsg.adr.adrNCCI);
+ "CONNECT_B3_RESP", "NCCI", cmsg->adr.adrNCCI);
dev_kfree_skb(skb);
return;
}
bcs = &cs->bcs[channel-1];
- if (iif->acmsg.Reject) {
+ if (cmsg->Reject) {
/* Reject: clear B3 connect received flag */
ap->connected = APCONN_SETUP;
@@ -1673,11 +1682,11 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif,
command = CAPI_CONNECT_B3_ACTIVE;
msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN;
}
- capi_cmsg_header(&iif->acmsg, ap->id, command, CAPI_IND,
- ap->nextMessageNumber++, iif->acmsg.adr.adrNCCI);
+ capi_cmsg_header(cmsg, ap->id, command, CAPI_IND,
+ ap->nextMessageNumber++, cmsg->adr.adrNCCI);
__skb_trim(skb, msgsize);
- capi_cmsg2message(&iif->acmsg, skb->data);
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
+ capi_cmsg2message(cmsg, skb->data);
+ dump_cmsg(DEBUG_CMD, __func__, cmsg);
capi_ctr_handle_message(&iif->ctr, ap->id, skb);
}
@@ -1691,28 +1700,37 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
struct sk_buff *skb)
{
struct cardstate *cs = iif->ctr.driverdata;
+ _cmsg *cmsg = &iif->acmsg;
struct bc_state *bcs;
_cmsg *b3cmsg;
struct sk_buff *b3skb;
int channel;
/* decode message */
- capi_message2cmsg(&iif->acmsg, skb->data);
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
+ capi_message2cmsg(cmsg, skb->data);
+ dump_cmsg(DEBUG_CMD, __func__, cmsg);
/* extract and check channel number from PLCI */
- channel = (iif->acmsg.adr.adrPLCI >> 8) & 0xff;
+ channel = (cmsg->adr.adrPLCI >> 8) & 0xff;
if (!channel || channel > cs->channels) {
dev_notice(cs->dev, "%s: invalid %s 0x%02x\n",
- "DISCONNECT_REQ", "PLCI", iif->acmsg.adr.adrPLCI);
+ "DISCONNECT_REQ", "PLCI", cmsg->adr.adrPLCI);
send_conf(iif, ap, skb, CapiIllContrPlciNcci);
return;
}
bcs = cs->bcs + channel - 1;
/* ToDo: process parameter: Additional info */
- ignore_cmstruct_param(cs, iif->acmsg.AdditionalInfo,
- "DISCONNECT_REQ", "Additional Info");
+ if (cmsg->AdditionalInfo != CAPI_DEFAULT) {
+ ignore_cstruct_param(cs, cmsg->BChannelinformation,
+ "DISCONNECT_REQ", "B Channel Information");
+ ignore_cstruct_param(cs, cmsg->Keypadfacility,
+ "DISCONNECT_REQ", "Keypad Facility");
+ ignore_cstruct_param(cs, cmsg->Useruserdata,
+ "DISCONNECT_REQ", "User-User Data");
+ ignore_cstruct_param(cs, cmsg->Facilitydataarray,
+ "DISCONNECT_REQ", "Facility Data Array");
+ }
/* skip if DISCONNECT_IND already sent */
if (!ap->connected)
@@ -1733,7 +1751,7 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
}
capi_cmsg_header(b3cmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND,
ap->nextMessageNumber++,
- iif->acmsg.adr.adrPLCI | (1 << 16));
+ cmsg->adr.adrPLCI | (1 << 16));
b3cmsg->Reason_B3 = CapiProtocolErrorLayer1;
b3skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_KERNEL);
if (b3skb == NULL) {
@@ -1769,18 +1787,19 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
struct sk_buff *skb)
{
struct cardstate *cs = iif->ctr.driverdata;
+ _cmsg *cmsg = &iif->acmsg;
int channel;
/* decode message */
- capi_message2cmsg(&iif->acmsg, skb->data);
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
+ capi_message2cmsg(cmsg, skb->data);
+ dump_cmsg(DEBUG_CMD, __func__, cmsg);
/* extract and check channel number and NCCI */
- channel = (iif->acmsg.adr.adrNCCI >> 8) & 0xff;
+ channel = (cmsg->adr.adrNCCI >> 8) & 0xff;
if (!channel || channel > cs->channels ||
- ((iif->acmsg.adr.adrNCCI >> 16) & 0xffff) != 1) {
+ ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) {
dev_notice(cs->dev, "%s: invalid %s 0x%02x\n",
- "DISCONNECT_B3_REQ", "NCCI", iif->acmsg.adr.adrNCCI);
+ "DISCONNECT_B3_REQ", "NCCI", cmsg->adr.adrNCCI);
send_conf(iif, ap, skb, CapiIllContrPlciNcci);
return;
}
@@ -1803,11 +1822,10 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
gigaset_schedule_event(cs);
/* NCPI parameter: not applicable for B3 Transparent */
- ignore_cstruct_param(cs, iif->acmsg.NCPI,
+ ignore_cstruct_param(cs, cmsg->NCPI,
"DISCONNECT_B3_REQ", "NCPI");
- send_conf(iif, ap, skb,
- (iif->acmsg.NCPI && iif->acmsg.NCPI[0]) ?
- CapiNcpiNotSupportedByProtocol : CapiSuccess);
+ send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ?
+ CapiNcpiNotSupportedByProtocol : CapiSuccess);
}
/*
--
1.6.2.1.214.ge986c
^ permalink raw reply related
* [PATCH 2/9] gigaset: fix format string typo in CAPI dial command
From: Tilman Schmidt @ 2009-10-25 19:29 UTC (permalink / raw)
To: David Miller, Karsten Keil
Cc: Hansjoerg Lipp, netdev, linux-kernel, isdn4linux, i4ldeveloper
In-Reply-To: <20091023-patch-gigaset-00.tilman@imap.cc>
A missing dot lead to garbage characters being included in the
dial command generated from a CAPI CONNECT_REQ message, which
interestingly enough worked anyway, illustrating the resilience
of the device.
Impact: bugfix
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
---
drivers/isdn/gigaset/capi.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index ac0a2da..d1afac2 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -1254,7 +1254,7 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
commands[AT_DIAL] = kmalloc(l+3, GFP_KERNEL);
if (!commands[AT_DIAL])
goto oom;
- snprintf(commands[AT_DIAL], l+3, "D%*s\r", l, pp);
+ snprintf(commands[AT_DIAL], l+3, "D%.*s\r", l, pp);
/* encode parameter: Calling party number */
pp = cmsg->CallingPartyNumber;
--
1.6.2.1.214.ge986c
^ permalink raw reply related
* [PATCH 3/9] gigaset: fix bad assumptions about CAPI skbuffs
From: Tilman Schmidt @ 2009-10-25 19:29 UTC (permalink / raw)
To: David Miller, Karsten Keil
Cc: Hansjoerg Lipp, netdev, linux-kernel, isdn4linux, i4ldeveloper
In-Reply-To: <20091023-patch-gigaset-00.tilman@imap.cc>
The CAPI interface incorrectly assumed that CAPI messages would always
start at the beginning of the data buffer: fix by treating DATA_B3
messages as the link layer header to their payload data. This fix
changes the way acknowledgement information is propagated through the
hardware specific modules and thereby impacts the ISDN4Linux variant
of the driver, too.
Also some assumptions about methods not being called from interrupt
context turned out to be unwarranted; fix by using dev_kfree_skb_any()
wherever non-interrupt context isn't guaranteed.
Impact: bugfix
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
---
drivers/isdn/gigaset/asyncdata.c | 55 +++++++++++++++++++++----------------
drivers/isdn/gigaset/capi.c | 29 ++++++++++---------
drivers/isdn/gigaset/gigaset.h | 2 +-
drivers/isdn/gigaset/i4l.c | 28 ++++++++++++++-----
drivers/isdn/gigaset/isocdata.c | 6 ++--
5 files changed, 70 insertions(+), 50 deletions(-)
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index a25216b..256fc48 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -156,7 +156,7 @@ byte_stuff:
/* end of frame */
gigaset_isdn_rcv_err(bcs);
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
} else if (!(inputstate & INS_have_data)) { /* 7E 7E */
#ifdef CONFIG_GIGASET_DEBUG
++bcs->emptycount;
@@ -172,7 +172,7 @@ byte_stuff:
"Checksum failed, %u bytes corrupted!\n",
skb->len);
gigaset_isdn_rcv_err(bcs);
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
} else if (likely(skb->len > 2)) {
__skb_trim(skb, skb->len - 2);
gigaset_skb_rcvd(bcs, skb);
@@ -182,7 +182,7 @@ byte_stuff:
"invalid packet size (%d)\n", skb->len);
gigaset_isdn_rcv_err(bcs);
}
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
}
}
@@ -430,11 +430,11 @@ EXPORT_SYMBOL_GPL(gigaset_m10x_input);
* opening and closing flags, preserving headroom data.
* parameters:
* skb skb containing original packet (freed upon return)
- * headroom number of headroom bytes to preserve
* Return value:
* pointer to newly allocated skb containing the result frame
+ * and the original link layer header, NULL on error
*/
-static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom)
+static struct sk_buff *HDLC_Encode(struct sk_buff *skb)
{
struct sk_buff *hdlc_skb;
__u16 fcs;
@@ -456,17 +456,19 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom)
/* size of new buffer: original size + number of stuffing bytes
* + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
- * + room for acknowledgement header
+ * + room for link layer header
*/
- hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + headroom);
+ hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + skb->mac_len);
if (!hdlc_skb) {
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return NULL;
}
- /* Copy acknowledgement header into new skb */
- skb_reserve(hdlc_skb, headroom);
- memcpy(hdlc_skb->head, skb->head, headroom);
+ /* Copy link layer header into new skb */
+ skb_reset_mac_header(hdlc_skb);
+ skb_reserve(hdlc_skb, skb->mac_len);
+ memcpy(skb_mac_header(hdlc_skb), skb_mac_header(skb), skb->mac_len);
+ hdlc_skb->mac_len = skb->mac_len;
/* Add flag sequence in front of everything.. */
*(skb_put(hdlc_skb, 1)) = PPP_FLAG;
@@ -497,7 +499,7 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom)
*(skb_put(hdlc_skb, 1)) = PPP_FLAG;
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return hdlc_skb;
}
@@ -506,28 +508,33 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom)
* preserving headroom data.
* parameters:
* skb skb containing original packet (freed upon return)
- * headroom number of headroom bytes to preserve
* Return value:
* pointer to newly allocated skb containing the result frame
+ * and the original link layer header, NULL on error
*/
-static struct sk_buff *iraw_encode(struct sk_buff *skb, int headroom)
+static struct sk_buff *iraw_encode(struct sk_buff *skb)
{
struct sk_buff *iraw_skb;
unsigned char c;
unsigned char *cp;
int len;
- /* worst case: every byte must be stuffed */
- iraw_skb = dev_alloc_skb(2*skb->len + headroom);
+ /* size of new buffer (worst case = every byte must be stuffed):
+ * 2 * original size + room for link layer header
+ */
+ iraw_skb = dev_alloc_skb(2*skb->len + skb->mac_len);
if (!iraw_skb) {
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return NULL;
}
- /* Copy acknowledgement header into new skb */
- skb_reserve(iraw_skb, headroom);
- memcpy(iraw_skb->head, skb->head, headroom);
+ /* copy link layer header into new skb */
+ skb_reset_mac_header(iraw_skb);
+ skb_reserve(iraw_skb, skb->mac_len);
+ memcpy(skb_mac_header(iraw_skb), skb_mac_header(skb), skb->mac_len);
+ iraw_skb->mac_len = skb->mac_len;
+ /* copy and stuff data */
cp = skb->data;
len = skb->len;
while (len--) {
@@ -536,7 +543,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int headroom)
*(skb_put(iraw_skb, 1)) = c;
*(skb_put(iraw_skb, 1)) = c;
}
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return iraw_skb;
}
@@ -548,7 +555,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int headroom)
* Called by LL to encode and queue an skb for sending, and start
* transmission if necessary.
* Once the payload data has been transmitted completely, gigaset_skb_sent()
- * will be called with the first cs->hw_hdr_len bytes of skb->head preserved.
+ * will be called with the skb's link layer header preserved.
*
* Return value:
* number of bytes accepted for sending (skb->len) if ok,
@@ -560,9 +567,9 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
unsigned long flags;
if (bcs->proto2 == L2_HDLC)
- skb = HDLC_Encode(skb, bcs->cs->hw_hdr_len);
+ skb = HDLC_Encode(skb);
else
- skb = iraw_encode(skb, bcs->cs->hw_hdr_len);
+ skb = iraw_encode(skb);
if (!skb) {
dev_err(bcs->cs->dev,
"unable to allocate memory for encoding!\n");
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index d1afac2..3f5cd06 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -362,6 +362,7 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
struct cardstate *cs = bcs->cs;
struct gigaset_capi_ctr *iif = cs->iif;
struct gigaset_capi_appl *ap = bcs->ap;
+ unsigned char *req = skb_mac_header(dskb);
struct sk_buff *cskb;
u16 flags;
@@ -380,7 +381,7 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
}
/* ToDo: honor unset "delivery confirmation" bit */
- flags = CAPIMSG_FLAGS(dskb->head);
+ flags = CAPIMSG_FLAGS(req);
/* build DATA_B3_CONF message */
cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC);
@@ -393,11 +394,11 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
CAPIMSG_SETAPPID(cskb->data, ap->id);
CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3);
CAPIMSG_SETSUBCOMMAND(cskb->data, CAPI_CONF);
- CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(dskb->head));
+ CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(req));
CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr);
CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1);
CAPIMSG_SETNCCI_PART(cskb->data, 1);
- CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(dskb->head));
+ CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(req));
if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION)
CAPIMSG_SETINFO_CONF(cskb->data,
CapiFlagsNotSupportedByProtocol);
@@ -437,7 +438,7 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
/* don't send further B3 messages if disconnected */
if (ap->connected < APCONN_ACTIVE) {
gig_dbg(DEBUG_LLDATA, "disconnected, discarding data");
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return;
}
@@ -1461,7 +1462,7 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
/* decode message */
capi_message2cmsg(cmsg, skb->data);
dump_cmsg(DEBUG_CMD, __func__, cmsg);
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
/* extract and check channel number from PLCI */
channel = (cmsg->adr.adrPLCI >> 8) & 0xff;
@@ -1652,7 +1653,7 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif,
((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) {
dev_notice(cs->dev, "%s: invalid %s 0x%02x\n",
"CONNECT_B3_RESP", "NCCI", cmsg->adr.adrNCCI);
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return;
}
bcs = &cs->bcs[channel-1];
@@ -1665,7 +1666,7 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif,
if (!gigaset_add_event(cs, &bcs->at_state,
EV_HUP, NULL, 0, NULL)) {
dev_err(cs->dev, "%s: out of memory\n", __func__);
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return;
}
gig_dbg(DEBUG_CMD, "scheduling HUP");
@@ -1880,12 +1881,12 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
return;
}
- /*
- * pull CAPI message from skb,
- * pass payload data to device-specific module
- * CAPI message will be preserved in headroom
- */
+ /* pull CAPI message into link layer header */
+ skb_reset_mac_header(skb);
+ skb->mac_len = msglen;
skb_pull(skb, msglen);
+
+ /* pass to device-specific module */
if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) {
send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
return;
@@ -1946,7 +1947,7 @@ static void do_nothing(struct gigaset_capi_ctr *iif,
capi_message2cmsg(&iif->acmsg, skb->data);
dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
}
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
}
static void do_data_b3_resp(struct gigaset_capi_ctr *iif,
@@ -1954,7 +1955,7 @@ static void do_data_b3_resp(struct gigaset_capi_ctr *iif,
struct sk_buff *skb)
{
dump_rawmsg(DEBUG_LLDATA, __func__, skb->data);
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
}
/* table of outgoing CAPI message handlers with lookup function */
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 4749ef1..c59216b 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -625,7 +625,7 @@ struct gigaset_ops {
/* Called from LL interface to put an skb into the send-queue.
* After sending is completed, gigaset_skb_sent() must be called
- * with the first cs->hw_hdr_len bytes of skb->head preserved. */
+ * with the skb's link layer header preserved. */
int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb);
/* Called from ev-layer.c to process a block of data
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index aca72a0..828824f 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -41,8 +41,8 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
{
struct cardstate *cs;
struct bc_state *bcs;
+ unsigned char *ack_header;
unsigned len;
- unsigned skblen;
if (!(cs = gigaset_get_cs_by_id(driverID))) {
pr_err("%s: invalid driver ID (%d)\n", __func__, driverID);
@@ -78,11 +78,23 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
return -EINVAL;
}
- skblen = ack ? len : 0;
- skb->head[0] = skblen & 0xff;
- skb->head[1] = skblen >> 8;
- gig_dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x",
- len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]);
+ /* set up acknowledgement header */
+ if (skb_headroom(skb) < HW_HDR_LEN) {
+ /* should never happen */
+ dev_err(cs->dev, "%s: insufficient skb headroom\n", __func__);
+ return -ENOMEM;
+ }
+ skb_set_mac_header(skb, -HW_HDR_LEN);
+ skb->mac_len = HW_HDR_LEN;
+ ack_header = skb_mac_header(skb);
+ if (ack) {
+ ack_header[0] = len & 0xff;
+ ack_header[1] = len >> 8;
+ } else {
+ ack_header[0] = ack_header[1] = 0;
+ }
+ gig_dbg(DEBUG_MCMD, "skb: len=%u, ack=%d: %02x %02x",
+ len, ack, ack_header[0], ack_header[1]);
/* pass to device-specific module */
return cs->ops->send_skb(bcs, skb);
@@ -99,6 +111,7 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
{
isdn_if *iif = bcs->cs->iif;
+ unsigned char *ack_header = skb_mac_header(skb);
unsigned len;
isdn_ctrl response;
@@ -108,8 +121,7 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
dev_warn(bcs->cs->dev, "%s: skb->len==%d\n",
__func__, skb->len);
- len = (unsigned char) skb->head[0] |
- (unsigned) (unsigned char) skb->head[1] << 8;
+ len = ack_header[0] + ((unsigned) ack_header[1] << 8);
if (len) {
gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)",
bcs->cs->myid, bcs->channel, len);
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 7dabfd3..bc41611 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -576,12 +576,12 @@ static inline void hdlc_done(struct bc_state *bcs)
dev_notice(cs->dev, "received short frame (%d octets)\n",
procskb->len);
bcs->hw.bas->runts++;
- dev_kfree_skb(procskb);
+ dev_kfree_skb_any(procskb);
gigaset_isdn_rcv_err(bcs);
} else if (bcs->fcs != PPP_GOODFCS) {
dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs);
bcs->hw.bas->fcserrs++;
- dev_kfree_skb(procskb);
+ dev_kfree_skb_any(procskb);
gigaset_isdn_rcv_err(bcs);
} else {
len = procskb->len;
@@ -985,7 +985,7 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
* Called by LL to queue an skb for sending, and start transmission if
* necessary.
* Once the payload data has been transmitted completely, gigaset_skb_sent()
- * will be called with the first cs->hw_hdr_len bytes of skb->head preserved.
+ * will be called with the skb's link layer header preserved.
*
* Return value:
* number of bytes accepted for sending (skb->len) if ok,
--
1.6.2.1.214.ge986c
^ permalink raw reply related
* [PATCH 4/9] usb_gigaset: code cleanup
From: Tilman Schmidt @ 2009-10-25 19:30 UTC (permalink / raw)
To: David Miller, Karsten Keil
Cc: Hansjoerg Lipp, netdev, linux-kernel, isdn4linux, i4ldeveloper
In-Reply-To: <20091023-patch-gigaset-00.tilman@imap.cc>
Reorganize the code of the Gigaset M10x driver to make it more
readable, less redundant, better aligned to the style of other
parts of the driver, and cause fewer checkpatch.pl complaints.
Impact: code reorganization, no functional change
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
---
drivers/isdn/gigaset/asyncdata.c | 573 +++++++++++++++++++-----------------
drivers/isdn/gigaset/common.c | 34 +--
drivers/isdn/gigaset/gigaset.h | 13 +-
drivers/isdn/gigaset/usb-gigaset.c | 69 +++---
4 files changed, 358 insertions(+), 331 deletions(-)
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index 256fc48..ccb2a7b 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -19,7 +19,7 @@
/* check if byte must be stuffed/escaped
* I'm not sure which data should be encoded.
- * Therefore I will go the hard way and decode every value
+ * Therefore I will go the hard way and encode every value
* less than 0x20, the flag sequence and the control escape char.
*/
static inline int muststuff(unsigned char c)
@@ -35,288 +35,383 @@ static inline int muststuff(unsigned char c)
/* == data input =========================================================== */
-/* process a block of received bytes in command mode (modem response)
+/* process a block of received bytes in command mode
+ * (mstate != MS_LOCKED && (inputstate & INS_command))
+ * Append received bytes to the command response buffer and forward them
+ * line by line to the response handler. Exit whenever a mode/state change
+ * might have occurred.
* Return value:
* number of processed bytes
*/
-static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
- struct inbuf_t *inbuf)
+static unsigned cmd_loop(unsigned numbytes, struct inbuf_t *inbuf)
{
+ unsigned char *src = inbuf->data + inbuf->head;
struct cardstate *cs = inbuf->cs;
- unsigned cbytes = cs->cbytes;
- int inputstate = inbuf->inputstate;
- int startbytes = numbytes;
-
- for (;;) {
- cs->respdata[cbytes] = c;
- if (c == 10 || c == 13) {
- gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
+ unsigned cbytes = cs->cbytes;
+ unsigned procbytes = 0;
+ unsigned char c;
+
+ while (procbytes < numbytes) {
+ c = *src++;
+ procbytes++;
+
+ switch (c) {
+ case '\n':
+ if (cbytes == 0 && cs->respdata[0] == '\r') {
+ /* collapse LF with preceding CR */
+ cs->respdata[0] = 0;
+ break;
+ }
+ /* --v-- fall through --v-- */
+ case '\r':
+ /* end of message line, pass to response handler */
+ gig_dbg(DEBUG_TRANSCMD, "%s: End of Message (%d Bytes)",
__func__, cbytes);
+ if (cbytes >= MAX_RESP_SIZE) {
+ dev_warn(cs->dev, "response too large (%d)\n",
+ cbytes);
+ cbytes = MAX_RESP_SIZE;
+ }
cs->cbytes = cbytes;
- gigaset_handle_modem_response(cs); /* can change
- cs->dle */
+ gigaset_handle_modem_response(cs);
cbytes = 0;
- if (cs->dle &&
- !(inputstate & INS_DLE_command)) {
- inputstate &= ~INS_command;
- break;
- }
- } else {
- /* advance in line buffer, checking for overflow */
- if (cbytes < MAX_RESP_SIZE - 1)
- cbytes++;
- else
- dev_warn(cs->dev, "response too large\n");
- }
+ /* store EOL byte for CRLF collapsing */
+ cs->respdata[0] = c;
- if (!numbytes)
- break;
- c = *src++;
- --numbytes;
- if (c == DLE_FLAG &&
- (cs->dle || inputstate & INS_DLE_command)) {
- inputstate |= INS_DLE_char;
- break;
+ /* cs->dle may have changed */
+ if (cs->dle && !(inbuf->inputstate & INS_DLE_command))
+ inbuf->inputstate &= ~INS_command;
+
+ /* return for reevaluating state */
+ goto exit;
+
+ case DLE_FLAG:
+ if (inbuf->inputstate & INS_DLE_char) {
+ /* quoted DLE: clear quote flag */
+ inbuf->inputstate &= ~INS_DLE_char;
+ } else if (cs->dle ||
+ (inbuf->inputstate & INS_DLE_command)) {
+ /* DLE escape, pass up for handling */
+ inbuf->inputstate |= INS_DLE_char;
+ goto exit;
+ }
+ /* quoted or not in DLE mode: treat as regular data */
+ /* --v-- fall through --v-- */
+ default:
+ /* append to line buffer if possible */
+ if (cbytes < MAX_RESP_SIZE)
+ cs->respdata[cbytes] = c;
+ cbytes++;
}
}
-
+exit:
cs->cbytes = cbytes;
- inbuf->inputstate = inputstate;
-
- return startbytes - numbytes;
+ return procbytes;
}
-/* process a block of received bytes in lock mode (tty i/f)
+/* process a block of received bytes in lock mode
+ * All received bytes are passed unmodified to the tty i/f.
* Return value:
* number of processed bytes
*/
-static inline int lock_loop(unsigned char *src, int numbytes,
- struct inbuf_t *inbuf)
+static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf)
{
- struct cardstate *cs = inbuf->cs;
-
- gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
- numbytes, src);
- gigaset_if_receive(cs, src, numbytes);
+ unsigned char *src = inbuf->data + inbuf->head;
+ gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src);
+ gigaset_if_receive(inbuf->cs, src, numbytes);
return numbytes;
}
+/* set up next receive skb for data mode
+ */
+static void new_rcv_skb(struct bc_state *bcs)
+{
+ struct cardstate *cs = bcs->cs;
+ unsigned short hw_hdr_len = cs->hw_hdr_len;
+
+ if (bcs->ignore) {
+ bcs->skb = NULL;
+ return;
+ }
+
+ bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len);
+ if (bcs->skb == NULL) {
+ dev_warn(cs->dev, "could not allocate new skb\n");
+ return;
+ }
+ skb_reserve(bcs->skb, hw_hdr_len);
+}
+
/* process a block of received bytes in HDLC data mode
+ * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC)
* Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
* When a frame is complete, check the FCS and pass valid frames to the LL.
* If DLE is encountered, return immediately to let the caller handle it.
* Return value:
* number of processed bytes
- * numbytes (all bytes processed) on error --FIXME
*/
-static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
- struct inbuf_t *inbuf)
+static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
{
struct cardstate *cs = inbuf->cs;
- struct bc_state *bcs = inbuf->bcs;
+ struct bc_state *bcs = cs->bcs;
int inputstate = bcs->inputstate;
__u16 fcs = bcs->fcs;
struct sk_buff *skb = bcs->skb;
- int startbytes = numbytes;
+ unsigned char *src = inbuf->data + inbuf->head;
+ unsigned procbytes = 0;
+ unsigned char c;
- if (unlikely(inputstate & INS_byte_stuff)) {
+ if (inputstate & INS_byte_stuff) {
+ if (!numbytes)
+ return 0;
inputstate &= ~INS_byte_stuff;
goto byte_stuff;
}
- for (;;) {
- if (unlikely(c == PPP_ESCAPE)) {
- if (unlikely(!numbytes)) {
- inputstate |= INS_byte_stuff;
+
+ while (procbytes < numbytes) {
+ c = *src++;
+ procbytes++;
+ if (c == DLE_FLAG) {
+ if (inputstate & INS_DLE_char) {
+ /* quoted DLE: clear quote flag */
+ inputstate &= ~INS_DLE_char;
+ } else if (cs->dle || (inputstate & INS_DLE_command)) {
+ /* DLE escape, pass up for handling */
+ inputstate |= INS_DLE_char;
break;
}
- c = *src++;
- --numbytes;
- if (unlikely(c == DLE_FLAG &&
- (cs->dle ||
- inbuf->inputstate & INS_DLE_command))) {
- inbuf->inputstate |= INS_DLE_char;
+ }
+
+ if (c == PPP_ESCAPE) {
+ /* byte stuffing indicator: pull in next byte */
+ if (procbytes >= numbytes) {
+ /* end of buffer, save for later processing */
inputstate |= INS_byte_stuff;
break;
}
byte_stuff:
+ c = *src++;
+ procbytes++;
+ if (c == DLE_FLAG) {
+ if (inputstate & INS_DLE_char) {
+ /* quoted DLE: clear quote flag */
+ inputstate &= ~INS_DLE_char;
+ } else if (cs->dle ||
+ (inputstate & INS_DLE_command)) {
+ /* DLE escape, pass up for handling */
+ inputstate |=
+ INS_DLE_char | INS_byte_stuff;
+ break;
+ }
+ }
c ^= PPP_TRANS;
- if (unlikely(!muststuff(c)))
- gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
- } else if (unlikely(c == PPP_FLAG)) {
- if (unlikely(inputstate & INS_skip_frame)) {
#ifdef CONFIG_GIGASET_DEBUG
- if (!(inputstate & INS_have_data)) { /* 7E 7E */
- ++bcs->emptycount;
- } else
- gig_dbg(DEBUG_HDLC,
- "7e----------------------------");
-#endif
-
- /* end of frame */
- gigaset_isdn_rcv_err(bcs);
- dev_kfree_skb_any(skb);
- } else if (!(inputstate & INS_have_data)) { /* 7E 7E */
-#ifdef CONFIG_GIGASET_DEBUG
- ++bcs->emptycount;
+ if (!muststuff(c))
+ gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
#endif
- break;
- } else {
+ } else if (c == PPP_FLAG) {
+ /* end of frame: process content if any */
+ if (inputstate & INS_have_data) {
gig_dbg(DEBUG_HDLC,
"7e----------------------------");
- /* end of frame */
- if (unlikely(fcs != PPP_GOODFCS)) {
+ /* check and pass received frame */
+ if (!skb) {
+ /* skipped frame */
+ gigaset_isdn_rcv_err(bcs);
+ } else if (skb->len < 2) {
+ /* frame too short for FCS */
+ dev_warn(cs->dev,
+ "short frame (%d)\n",
+ skb->len);
+ gigaset_isdn_rcv_err(bcs);
+ dev_kfree_skb_any(skb);
+ } else if (fcs != PPP_GOODFCS) {
+ /* frame check error */
dev_err(cs->dev,
"Checksum failed, %u bytes corrupted!\n",
skb->len);
gigaset_isdn_rcv_err(bcs);
dev_kfree_skb_any(skb);
- } else if (likely(skb->len > 2)) {
+ } else {
+ /* good frame */
__skb_trim(skb, skb->len - 2);
gigaset_skb_rcvd(bcs, skb);
- } else {
- if (skb->len) {
- dev_err(cs->dev,
- "invalid packet size (%d)\n", skb->len);
- gigaset_isdn_rcv_err(bcs);
- }
- dev_kfree_skb_any(skb);
}
- }
- fcs = PPP_INITFCS;
- inputstate &= ~(INS_have_data | INS_skip_frame);
- if (unlikely(bcs->ignore)) {
- inputstate |= INS_skip_frame;
- skb = NULL;
+ /* prepare reception of next frame */
+ inputstate &= ~INS_have_data;
+ new_rcv_skb(bcs);
+ skb = bcs->skb;
} else {
- skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (skb != NULL) {
- skb_reserve(skb, cs->hw_hdr_len);
- } else {
- dev_warn(cs->dev,
- "could not allocate new skb\n");
- inputstate |= INS_skip_frame;
+ /* empty frame (7E 7E) */
+#ifdef CONFIG_GIGASET_DEBUG
+ ++bcs->emptycount;
+#endif
+ if (!skb) {
+ /* skipped (?) */
+ gigaset_isdn_rcv_err(bcs);
+ new_rcv_skb(bcs);
+ skb = bcs->skb;
}
}
- break;
- } else if (unlikely(muststuff(c))) {
+ fcs = PPP_INITFCS;
+ continue;
+#ifdef CONFIG_GIGASET_DEBUG
+ } else if (muststuff(c)) {
/* Should not happen. Possible after ZDLE=1<CR><LF>. */
gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
+#endif
}
- /* add character */
-
+ /* regular data byte, append to skb */
#ifdef CONFIG_GIGASET_DEBUG
- if (unlikely(!(inputstate & INS_have_data))) {
+ if (!(inputstate & INS_have_data)) {
gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
bcs->emptycount);
bcs->emptycount = 0;
}
#endif
-
inputstate |= INS_have_data;
-
- if (likely(!(inputstate & INS_skip_frame))) {
- if (unlikely(skb->len == SBUFSIZE)) {
+ if (skb) {
+ if (skb->len == SBUFSIZE) {
dev_warn(cs->dev, "received packet too long\n");
dev_kfree_skb_any(skb);
- skb = NULL;
- inputstate |= INS_skip_frame;
- break;
+ /* skip remainder of packet */
+ bcs->skb = skb = NULL;
+ } else {
+ *__skb_put(skb, 1) = c;
+ fcs = crc_ccitt_byte(fcs, c);
}
- *__skb_put(skb, 1) = c;
- fcs = crc_ccitt_byte(fcs, c);
- }
-
- if (unlikely(!numbytes))
- break;
- c = *src++;
- --numbytes;
- if (unlikely(c == DLE_FLAG &&
- (cs->dle ||
- inbuf->inputstate & INS_DLE_command))) {
- inbuf->inputstate |= INS_DLE_char;
- break;
}
}
+
bcs->inputstate = inputstate;
bcs->fcs = fcs;
- bcs->skb = skb;
- return startbytes - numbytes;
+ return procbytes;
}
/* process a block of received bytes in transparent data mode
+ * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 != L2_HDLC)
* Invert bytes, undoing byte stuffing and watching for DLE escapes.
* If DLE is encountered, return immediately to let the caller handle it.
* Return value:
* number of processed bytes
- * numbytes (all bytes processed) on error --FIXME
*/
-static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
- struct inbuf_t *inbuf)
+static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
{
struct cardstate *cs = inbuf->cs;
- struct bc_state *bcs = inbuf->bcs;
+ struct bc_state *bcs = cs->bcs;
int inputstate = bcs->inputstate;
struct sk_buff *skb = bcs->skb;
- int startbytes = numbytes;
+ unsigned char *src = inbuf->data + inbuf->head;
+ unsigned procbytes = 0;
+ unsigned char c;
- for (;;) {
- /* add character */
- inputstate |= INS_have_data;
+ if (!skb) {
+ /* skip this block */
+ new_rcv_skb(bcs);
+ return numbytes;
+ }
- if (likely(!(inputstate & INS_skip_frame))) {
- if (unlikely(skb->len == SBUFSIZE)) {
- //FIXME just pass skb up and allocate a new one
- dev_warn(cs->dev, "received packet too long\n");
- dev_kfree_skb_any(skb);
- skb = NULL;
- inputstate |= INS_skip_frame;
+ while (procbytes < numbytes && skb->len < SBUFSIZE) {
+ c = *src++;
+ procbytes++;
+
+ if (c == DLE_FLAG) {
+ if (inputstate & INS_DLE_char) {
+ /* quoted DLE: clear quote flag */
+ inputstate &= ~INS_DLE_char;
+ } else if (cs->dle || (inputstate & INS_DLE_command)) {
+ /* DLE escape, pass up for handling */
+ inputstate |= INS_DLE_char;
break;
}
- *__skb_put(skb, 1) = bitrev8(c);
}
- if (unlikely(!numbytes))
- break;
- c = *src++;
- --numbytes;
- if (unlikely(c == DLE_FLAG &&
- (cs->dle ||
- inbuf->inputstate & INS_DLE_command))) {
- inbuf->inputstate |= INS_DLE_char;
- break;
- }
+ /* regular data byte: append to current skb */
+ inputstate |= INS_have_data;
+ *__skb_put(skb, 1) = bitrev8(c);
}
/* pass data up */
- if (likely(inputstate & INS_have_data)) {
- if (likely(!(inputstate & INS_skip_frame))) {
- gigaset_skb_rcvd(bcs, skb);
- }
- inputstate &= ~(INS_have_data | INS_skip_frame);
- if (unlikely(bcs->ignore)) {
- inputstate |= INS_skip_frame;
- skb = NULL;
- } else {
- skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (skb != NULL) {
- skb_reserve(skb, cs->hw_hdr_len);
- } else {
- dev_warn(cs->dev,
- "could not allocate new skb\n");
- inputstate |= INS_skip_frame;
+ if (inputstate & INS_have_data) {
+ gigaset_skb_rcvd(bcs, skb);
+ inputstate &= ~INS_have_data;
+ new_rcv_skb(bcs);
+ }
+
+ bcs->inputstate = inputstate;
+ return procbytes;
+}
+
+/* process DLE escapes
+ * Called whenever a DLE sequence might be encountered in the input stream.
+ * Either processes the entire DLE sequence or, if that isn't possible,
+ * notes the fact that an initial DLE has been received in the INS_DLE_char
+ * inputstate flag and resumes processing of the sequence on the next call.
+ */
+static void handle_dle(struct inbuf_t *inbuf)
+{
+ struct cardstate *cs = inbuf->cs;
+
+ if (cs->mstate == MS_LOCKED)
+ return; /* no DLE processing in lock mode */
+
+ if (!(inbuf->inputstate & INS_DLE_char)) {
+ /* no DLE pending */
+ if (inbuf->data[inbuf->head] == DLE_FLAG &&
+ (cs->dle || inbuf->inputstate & INS_DLE_command)) {
+ /* start of DLE sequence */
+ inbuf->head++;
+ if (inbuf->head == inbuf->tail ||
+ inbuf->head == RBUFSIZE) {
+ /* end of buffer, save for later processing */
+ inbuf->inputstate |= INS_DLE_char;
+ return;
}
+ } else {
+ /* regular data byte */
+ return;
}
}
- bcs->inputstate = inputstate;
- bcs->skb = skb;
- return startbytes - numbytes;
+ /* consume pending DLE */
+ inbuf->inputstate &= ~INS_DLE_char;
+
+ switch (inbuf->data[inbuf->head]) {
+ case 'X': /* begin of event message */
+ if (inbuf->inputstate & INS_command)
+ dev_notice(cs->dev,
+ "received <DLE>X in command mode\n");
+ inbuf->inputstate |= INS_command | INS_DLE_command;
+ inbuf->head++; /* byte consumed */
+ break;
+ case '.': /* end of event message */
+ if (!(inbuf->inputstate & INS_DLE_command))
+ dev_notice(cs->dev,
+ "received <DLE>. without <DLE>X\n");
+ inbuf->inputstate &= ~INS_DLE_command;
+ /* return to data mode if in DLE mode */
+ if (cs->dle)
+ inbuf->inputstate &= ~INS_command;
+ inbuf->head++; /* byte consumed */
+ break;
+ case DLE_FLAG: /* DLE in data stream */
+ /* mark as quoted */
+ inbuf->inputstate |= INS_DLE_char;
+ if (!(cs->dle || inbuf->inputstate & INS_DLE_command))
+ dev_notice(cs->dev,
+ "received <DLE><DLE> not in DLE mode\n");
+ break; /* quoted byte left in buffer */
+ default:
+ dev_notice(cs->dev, "received <DLE><%02x>\n",
+ inbuf->data[inbuf->head]);
+ /* quoted byte left in buffer */
+ }
}
/**
@@ -330,94 +425,39 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
*/
void gigaset_m10x_input(struct inbuf_t *inbuf)
{
- struct cardstate *cs;
- unsigned tail, head, numbytes;
- unsigned char *src, c;
- int procbytes;
-
- head = inbuf->head;
- tail = inbuf->tail;
- gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
-
- if (head != tail) {
- cs = inbuf->cs;
- src = inbuf->data + head;
- numbytes = (head > tail ? RBUFSIZE : tail) - head;
- gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
+ struct cardstate *cs = inbuf->cs;
+ unsigned numbytes, procbytes;
- while (numbytes) {
- if (cs->mstate == MS_LOCKED) {
- procbytes = lock_loop(src, numbytes, inbuf);
- src += procbytes;
- numbytes -= procbytes;
- } else {
- c = *src++;
- --numbytes;
- if (c == DLE_FLAG && (cs->dle ||
- inbuf->inputstate & INS_DLE_command)) {
- if (!(inbuf->inputstate & INS_DLE_char)) {
- inbuf->inputstate |= INS_DLE_char;
- goto nextbyte;
- }
- /* <DLE> <DLE> => <DLE> in data stream */
- inbuf->inputstate &= ~INS_DLE_char;
- }
+ gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", inbuf->head, inbuf->tail);
- if (!(inbuf->inputstate & INS_DLE_char)) {
-
- /* FIXME use function pointers? */
- if (inbuf->inputstate & INS_command)
- procbytes = cmd_loop(c, src, numbytes, inbuf);
- else if (inbuf->bcs->proto2 == L2_HDLC)
- procbytes = hdlc_loop(c, src, numbytes, inbuf);
- else
- procbytes = iraw_loop(c, src, numbytes, inbuf);
-
- src += procbytes;
- numbytes -= procbytes;
- } else { /* DLE char */
- inbuf->inputstate &= ~INS_DLE_char;
- switch (c) {
- case 'X': /*begin of command*/
- if (inbuf->inputstate & INS_command)
- dev_warn(cs->dev,
- "received <DLE> 'X' in command mode\n");
- inbuf->inputstate |=
- INS_command | INS_DLE_command;
- break;
- case '.': /*end of command*/
- if (!(inbuf->inputstate & INS_command))
- dev_warn(cs->dev,
- "received <DLE> '.' in hdlc mode\n");
- inbuf->inputstate &= cs->dle ?
- ~(INS_DLE_command|INS_command)
- : ~INS_DLE_command;
- break;
- //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
- default:
- dev_err(cs->dev,
- "received 0x10 0x%02x!\n",
- (int) c);
- /* FIXME: reset driver?? */
- }
- }
- }
-nextbyte:
- if (!numbytes) {
- /* end of buffer, check for wrap */
- if (head > tail) {
- head = 0;
- src = inbuf->data;
- numbytes = tail;
- } else {
- head = tail;
- break;
- }
- }
- }
+ while (inbuf->head != inbuf->tail) {
+ /* check for DLE escape */
+ handle_dle(inbuf);
- gig_dbg(DEBUG_INTR, "setting head to %u", head);
- inbuf->head = head;
+ /* process a contiguous block of bytes */
+ numbytes = (inbuf->head > inbuf->tail ?
+ RBUFSIZE : inbuf->tail) - inbuf->head;
+ gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
+ /*
+ * numbytes may be 0 if handle_dle() ate the last byte.
+ * This does no harm, *_loop() will just return 0 immediately.
+ */
+
+ if (cs->mstate == MS_LOCKED)
+ procbytes = lock_loop(numbytes, inbuf);
+ else if (inbuf->inputstate & INS_command)
+ procbytes = cmd_loop(numbytes, inbuf);
+ else if (cs->bcs->proto2 == L2_HDLC)
+ procbytes = hdlc_loop(numbytes, inbuf);
+ else
+ procbytes = iraw_loop(numbytes, inbuf);
+ inbuf->head += procbytes;
+
+ /* check for buffer wraparound */
+ if (inbuf->head >= RBUFSIZE)
+ inbuf->head = 0;
+
+ gig_dbg(DEBUG_INTR, "head set to %u", inbuf->head);
}
}
EXPORT_SYMBOL_GPL(gigaset_m10x_input);
@@ -563,6 +603,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb)
*/
int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
{
+ struct cardstate *cs = bcs->cs;
unsigned len = skb->len;
unsigned long flags;
@@ -571,16 +612,16 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
else
skb = iraw_encode(skb);
if (!skb) {
- dev_err(bcs->cs->dev,
+ dev_err(cs->dev,
"unable to allocate memory for encoding!\n");
return -ENOMEM;
}
skb_queue_tail(&bcs->squeue, skb);
- spin_lock_irqsave(&bcs->cs->lock, flags);
- if (bcs->cs->connected)
- tasklet_schedule(&bcs->cs->write_tasklet);
- spin_unlock_irqrestore(&bcs->cs->lock, flags);
+ spin_lock_irqsave(&cs->lock, flags);
+ if (cs->connected)
+ tasklet_schedule(&cs->write_tasklet);
+ spin_unlock_irqrestore(&cs->lock, flags);
return len; /* ok so far */
}
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 1d2ae2e..690ac74 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -400,9 +400,9 @@ static void gigaset_freebcs(struct bc_state *bcs)
gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
clear_at_state(&bcs->at_state);
gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
+ dev_kfree_skb(bcs->skb);
+ bcs->skb = NULL;
- if (bcs->skb)
- dev_kfree_skb(bcs->skb);
for (i = 0; i < AT_NUM; ++i) {
kfree(bcs->commands[i]);
bcs->commands[i] = NULL;
@@ -560,16 +560,13 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
}
-static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs,
- struct cardstate *cs, int inputstate)
+static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs)
/* inbuf->read must be allocated before! */
{
inbuf->head = 0;
inbuf->tail = 0;
inbuf->cs = cs;
- inbuf->bcs = bcs; /*base driver: NULL*/
- inbuf->rcvbuf = NULL;
- inbuf->inputstate = inputstate;
+ inbuf->inputstate = INS_command;
}
/**
@@ -644,16 +641,13 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
bcs->fcs = PPP_INITFCS;
bcs->inputstate = 0;
if (cs->ignoreframes) {
- bcs->inputstate |= INS_skip_frame;
bcs->skb = NULL;
} else {
bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
if (bcs->skb != NULL)
skb_reserve(bcs->skb, cs->hw_hdr_len);
- else {
+ else
pr_err("out of memory\n");
- bcs->inputstate |= INS_skip_frame;
- }
}
bcs->channel = channel;
@@ -674,8 +668,8 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
gig_dbg(DEBUG_INIT, " failed");
gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel);
- if (bcs->skb)
- dev_kfree_skb(bcs->skb);
+ dev_kfree_skb(bcs->skb);
+ bcs->skb = NULL;
return NULL;
}
@@ -764,10 +758,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
cs->cbytes = 0;
gig_dbg(DEBUG_INIT, "setting up inbuf");
- if (onechannel) { //FIXME distinction necessary?
- gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command);
- } else
- gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command);
+ gigaset_inbuf_init(cs->inbuf, cs);
cs->connected = 0;
cs->isdn_up = 0;
@@ -854,9 +845,10 @@ void gigaset_bcs_reinit(struct bc_state *bcs)
bcs->chstate = 0;
bcs->ignore = cs->ignoreframes;
- if (bcs->ignore)
- bcs->inputstate |= INS_skip_frame;
-
+ if (bcs->ignore) {
+ dev_kfree_skb(bcs->skb);
+ bcs->skb = NULL;
+ }
cs->ops->reinitbcshw(bcs);
}
@@ -877,8 +869,6 @@ static void cleanup_cs(struct cardstate *cs)
free_strings(&cs->at_state);
gigaset_at_init(&cs->at_state, NULL, cs, 0);
- kfree(cs->inbuf->rcvbuf);
- cs->inbuf->rcvbuf = NULL;
cs->inbuf->inputstate = INS_command;
cs->inbuf->head = 0;
cs->inbuf->tail = 0;
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index c59216b..18bff9f 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -223,12 +223,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define EV_BC_CLOSED -118
/* input state */
-#define INS_command 0x0001
-#define INS_DLE_char 0x0002
+#define INS_command 0x0001 /* receiving messages (not payload data) */
+#define INS_DLE_char 0x0002 /* DLE flag received (in DLE mode) */
#define INS_byte_stuff 0x0004
#define INS_have_data 0x0008
-#define INS_skip_frame 0x0010
-#define INS_DLE_command 0x0020
+#define INS_DLE_command 0x0020 /* DLE message start (<DLE> X) received */
#define INS_flag_hunt 0x0040
/* channel state */
@@ -290,8 +289,6 @@ extern struct reply_t gigaset_tab_cid[];
extern struct reply_t gigaset_tab_nocid[];
struct inbuf_t {
- unsigned char *rcvbuf; /* usb-gigaset receive buffer */
- struct bc_state *bcs;
struct cardstate *cs;
int inputstate;
int head, tail;
@@ -483,8 +480,8 @@ struct cardstate {
struct timer_list timer;
int retry_count;
- int dle; /* !=0 if modem commands/responses are
- dle encoded */
+ int dle; /* !=0 if DLE mode is active
+ (ZDLE=1 received -- M10x only) */
int cur_at_seq; /* sequence of AT commands being
processed */
int curchannel; /* channel those commands are meant
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index 4deb1ab..f56b2a8 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -43,14 +43,14 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode");
#define GIGASET_MODULENAME "usb_gigaset"
#define GIGASET_DEVNAME "ttyGU"
-#define IF_WRITEBUF 2000 //FIXME // WAKEUP_CHARS: 256
+#define IF_WRITEBUF 2000 /* arbitrary limit */
/* Values for the Gigaset M105 Data */
#define USB_M105_VENDOR_ID 0x0681
#define USB_M105_PRODUCT_ID 0x0009
/* table of devices that work with this driver */
-static const struct usb_device_id gigaset_table [] = {
+static const struct usb_device_id gigaset_table[] = {
{ USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) },
{ } /* Terminating entry */
};
@@ -97,8 +97,8 @@ MODULE_DEVICE_TABLE(usb, gigaset_table);
* 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13
* Used after every "configuration sequence" (RQ 12, RQs 01/03/13).
* xx is usually 0x00 but was 0x7e before starting data transfer
- * in unimodem mode. So, this might be an array of characters that need
- * special treatment ("commit all bufferd data"?), 11=^Q, 13=^S.
+ * in unimodem mode. So, this might be an array of characters that
+ * need special treatment ("commit all bufferd data"?), 11=^Q, 13=^S.
*
* Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two
* flags per packet.
@@ -114,7 +114,7 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message);
static int gigaset_resume(struct usb_interface *intf);
static int gigaset_pre_reset(struct usb_interface *intf);
-static struct gigaset_driver *driver = NULL;
+static struct gigaset_driver *driver;
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver gigaset_usb_driver = {
@@ -141,6 +141,7 @@ struct usb_cardstate {
struct urb *bulk_out_urb;
/* Input buffer */
+ unsigned char *rcvbuf;
int rcvbuf_size;
struct urb *read_urb;
__u8 int_in_endpointAddr;
@@ -164,13 +165,11 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
val = tiocm_to_gigaset(new_state);
gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask);
- // don't use this in an interrupt/BH
r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41,
(val & 0xff) | ((mask & 0xff) << 8), 0,
NULL, 0, 2000 /* timeout? */);
if (r < 0)
return r;
- //..
return 0;
}
@@ -220,7 +219,6 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
cflag &= CBAUD;
switch (cflag) {
- //FIXME more values?
case B300: rate = 300; break;
case B600: rate = 600; break;
case B1200: rate = 1200; break;
@@ -273,7 +271,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
/* set the number of stop bits */
if (cflag & CSTOPB) {
if ((cflag & CSIZE) == CS5)
- val |= 1; /* 1.5 stop bits */ //FIXME is this okay?
+ val |= 1; /* 1.5 stop bits */
else
val |= 2; /* 2 stop bits */
}
@@ -282,7 +280,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
}
- /*================================================================================================================*/
+/*============================================================================*/
static int gigaset_init_bchannel(struct bc_state *bcs)
{
/* nothing to do for M10x */
@@ -344,7 +342,6 @@ static void gigaset_modem_fill(unsigned long data)
if (write_modem(cs) < 0) {
gig_dbg(DEBUG_OUTPUT,
"modem_fill: write_modem failed");
- // FIXME should we tell the LL?
again = 1; /* no callback will be called! */
}
}
@@ -356,8 +353,8 @@ static void gigaset_modem_fill(unsigned long data)
*/
static void gigaset_read_int_callback(struct urb *urb)
{
- struct inbuf_t *inbuf = urb->context;
- struct cardstate *cs = inbuf->cs;
+ struct cardstate *cs = urb->context;
+ struct inbuf_t *inbuf = cs->inbuf;
int status = urb->status;
int r;
unsigned numbytes;
@@ -368,7 +365,7 @@ static void gigaset_read_int_callback(struct urb *urb)
numbytes = urb->actual_length;
if (numbytes) {
- src = inbuf->rcvbuf;
+ src = cs->hw.usb->rcvbuf;
if (unlikely(*src))
dev_warn(cs->dev,
"%s: There was no leading 0, but 0x%02x!\n",
@@ -440,7 +437,7 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
struct cmdbuf_t *tcb;
unsigned long flags;
int count;
- int status = -ENOENT; // FIXME
+ int status = -ENOENT;
struct usb_cardstate *ucs = cs->hw.usb;
do {
@@ -480,7 +477,9 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
ucs->busy = 1;
spin_lock_irqsave(&cs->lock, flags);
- status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV;
+ status = cs->connected ?
+ usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) :
+ -ENODEV;
spin_unlock_irqrestore(&cs->lock, flags);
if (status) {
@@ -510,8 +509,8 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
if (len <= 0)
return 0;
-
- if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
+ cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
+ if (!cb) {
dev_err(cs->dev, "%s: out of memory\n", __func__);
return -ENOMEM;
}
@@ -637,9 +636,7 @@ static int write_modem(struct cardstate *cs)
return -EINVAL;
}
- /* Copy data to bulk out buffer and // FIXME copying not necessary
- * transmit data
- */
+ /* Copy data to bulk out buffer and transmit data */
count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size);
skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count);
skb_pull(bcs->tx_skb, count);
@@ -650,7 +647,8 @@ static int write_modem(struct cardstate *cs)
if (cs->connected) {
usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
usb_sndbulkpipe(ucs->udev,
- ucs->bulk_out_endpointAddr & 0x0f),
+ ucs->bulk_out_endpointAddr &
+ 0x0f),
ucs->bulk_out_buffer, count,
gigaset_write_bulk_callback, cs);
ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC);
@@ -666,7 +664,7 @@ static int write_modem(struct cardstate *cs)
if (!bcs->tx_skb->len) {
/* skb sent completely */
- gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0?
+ gigaset_skb_sent(bcs, bcs->tx_skb);
gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!",
(unsigned long) bcs->tx_skb);
@@ -763,8 +761,8 @@ static int gigaset_probe(struct usb_interface *interface,
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
ucs->rcvbuf_size = buffer_size;
ucs->int_in_endpointAddr = endpoint->bEndpointAddress;
- cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL);
- if (!cs->inbuf[0].rcvbuf) {
+ ucs->rcvbuf = kmalloc(buffer_size, GFP_KERNEL);
+ if (!ucs->rcvbuf) {
dev_err(cs->dev, "Couldn't allocate rcvbuf\n");
retval = -ENOMEM;
goto error;
@@ -773,9 +771,9 @@ static int gigaset_probe(struct usb_interface *interface,
usb_fill_int_urb(ucs->read_urb, udev,
usb_rcvintpipe(udev,
endpoint->bEndpointAddress & 0x0f),
- cs->inbuf[0].rcvbuf, buffer_size,
+ ucs->rcvbuf, buffer_size,
gigaset_read_int_callback,
- cs->inbuf + 0, endpoint->bInterval);
+ cs, endpoint->bInterval);
retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL);
if (retval) {
@@ -789,7 +787,7 @@ static int gigaset_probe(struct usb_interface *interface,
if (!gigaset_start(cs)) {
tasklet_kill(&cs->write_tasklet);
- retval = -ENODEV; //FIXME
+ retval = -ENODEV;
goto error;
}
return 0;
@@ -798,11 +796,11 @@ error:
usb_kill_urb(ucs->read_urb);
kfree(ucs->bulk_out_buffer);
usb_free_urb(ucs->bulk_out_urb);
- kfree(cs->inbuf[0].rcvbuf);
+ kfree(ucs->rcvbuf);
usb_free_urb(ucs->read_urb);
usb_set_intfdata(interface, NULL);
ucs->read_urb = ucs->bulk_out_urb = NULL;
- cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
+ ucs->rcvbuf = ucs->bulk_out_buffer = NULL;
usb_put_dev(ucs->udev);
ucs->udev = NULL;
ucs->interface = NULL;
@@ -831,10 +829,10 @@ static void gigaset_disconnect(struct usb_interface *interface)
kfree(ucs->bulk_out_buffer);
usb_free_urb(ucs->bulk_out_urb);
- kfree(cs->inbuf[0].rcvbuf);
+ kfree(ucs->rcvbuf);
usb_free_urb(ucs->read_urb);
ucs->read_urb = ucs->bulk_out_urb = NULL;
- cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
+ ucs->rcvbuf = ucs->bulk_out_buffer = NULL;
usb_put_dev(ucs->udev);
ucs->interface = NULL;
@@ -916,9 +914,10 @@ static int __init usb_gigaset_init(void)
int result;
/* allocate memory for our driver state and intialize it */
- if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
- GIGASET_MODULENAME, GIGASET_DEVNAME,
- &ops, THIS_MODULE)) == NULL)
+ driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
+ GIGASET_MODULENAME, GIGASET_DEVNAME,
+ &ops, THIS_MODULE);
+ if (driver == NULL)
goto error;
/* register this driver with the USB subsystem */
--
1.6.2.1.214.ge986c
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox