* Re: net-2.6.24 build broken (allyesconfig)
From: Johannes Berg @ 2007-08-27 12:52 UTC (permalink / raw)
To: Ilpo Järvinen; +Cc: John W. Linville, David S. Miller, Netdev
In-Reply-To: <Pine.LNX.4.64.0708271522400.16245@kivilampi-30.cs.helsinki.fi>
On Mon, 2007-08-27 at 15:32 +0300, Ilpo Järvinen wrote:
> drivers/net/82596.c:1618:1: error: unterminated argument list invoking
> macro "DEB"
> Hmm, I would guess that "[NET]: Introduce MAC_FMT/MAC_ARG" broken it,
> though didn't verify it.
>
> The fix is left as an exercise of the reader (i.e., the solution wasn't
> too obvious for me :-) )...
Yup, my fault, sorry about that.
From: Johannes Berg <johannes@sipsolutions.net>
Subject: fix MAC_FMT/MAC_ARG in 82596.c
This fixes a typo in commit f98d4ca4986fec.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
drivers/net/82596.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- netdev-2.6.orig/drivers/net/82596.c 2007-08-27 14:48:19.674646075 +0200
+++ netdev-2.6/drivers/net/82596.c 2007-08-27 14:48:21.674646075 +0200
@@ -1562,7 +1562,7 @@ static void set_multicast_list(struct ne
memcpy(cp, dmi->dmi_addr, 6);
if (i596_debug > 1)
DEB(DEB_MULTI,printk(KERN_INFO "%s: Adding address " MAC_FMT "\n",
- dev->name, MAC_ARG(cp));
+ dev->name, MAC_ARG(cp)));
}
i596_add_cmd(dev, &cmd->cmd);
}
^ permalink raw reply
* Re: PROBLEM: 2.6.23-rc "NETDEV WATCHDOG: eth0: transmit timed out"
From: Jarek Poplawski @ 2007-08-27 12:50 UTC (permalink / raw)
To: Karl Meyer; +Cc: Francois Romieu, linux-kernel, netdev
In-Reply-To: <be1b757c0708210356s633db6c0m67601b250121ea0d@mail.gmail.com>
On 21-08-2007 12:56, Karl Meyer wrote:
> fyi:
> I do not know whether it is related to the problem, but since using
> the version you told me there are these entries is my log:
> frege Hangcheck: hangcheck value past margin!
...
BTW, I don't know wheter it's related too, but I think you should try
first to get rid of these errors:
> Freeing unused kernel memory: 220k freed
> usb_id[1320]: segfault at 00000000 eip b7e25db2 esp bfd1d734 error 4
> usb_id[1329]: segfault at 00000000 eip b7e1bdb2 esp bf9c9224 error 4
> usb_id[1322]: segfault at 00000000 eip b7df3db2 esp bfcb66c4 error 4
> usb_id[1321]: segfault at 00000000 eip b7e11db2 esp bf8f4b04 error 4
Regards,
Jarek P.
^ permalink raw reply
* [NET] 82596: Add missing parenthesis
From: Thomas Graf @ 2007-08-27 12:48 UTC (permalink / raw)
To: davem, ilpo.jarvinen; +Cc: Johannes Berg, John W. Linville, netdev
In-Reply-To: <Pine.LNX.4.64.0708271522400.16245@kivilampi-30.cs.helsinki.fi>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Index: net-2.6.24/drivers/net/82596.c
===================================================================
--- net-2.6.24.orig/drivers/net/82596.c 2007-08-27 14:43:16.000000000 +0200
+++ net-2.6.24/drivers/net/82596.c 2007-08-27 14:43:51.000000000 +0200
@@ -1562,7 +1562,7 @@ static void set_multicast_list(struct ne
memcpy(cp, dmi->dmi_addr, 6);
if (i596_debug > 1)
DEB(DEB_MULTI,printk(KERN_INFO "%s: Adding address " MAC_FMT "\n",
- dev->name, MAC_ARG(cp));
+ dev->name, MAC_ARG(cp)));
}
i596_add_cmd(dev, &cmd->cmd);
}
^ permalink raw reply
* net-2.6.24 build broken (allyesconfig)
From: Ilpo Järvinen @ 2007-08-27 12:32 UTC (permalink / raw)
To: Johannes Berg, John W. Linville, David S. Miller; +Cc: Netdev
Hi,
$ git-reset --hard net-2.6.24-origin
HEAD is now at e2eb35e... [ATM]: Fix build errors after conversion to pr_debug()
$ make allyesconfig
...
$ make bzImage
...
CC drivers/net/82596.o
drivers/net/82596.c:1618:1: error: unterminated argument list invoking
macro "DEB"
drivers/net/82596.c: In function 'set_multicast_list':
drivers/net/82596.c:1564: error: 'DEB' undeclared (first use in this
function)
drivers/net/82596.c:1564: error: (Each undeclared identifier is reported
only once
drivers/net/82596.c:1564: error: for each function it appears in.)
drivers/net/82596.c:1564: error: expected ';' at end of input
make[1]: *** [drivers/net/82596.o] Error 1
make: *** [drivers/net/82596.o] Error 2
Hmm, I would guess that "[NET]: Introduce MAC_FMT/MAC_ARG" broken it,
though didn't verify it.
The fix is left as an exercise of the reader (i.e., the solution wasn't
too obvious for me :-) )...
--
i.
^ permalink raw reply
* Re: [PATCH] netdevice: kernel docbook addition
From: Jarek Poplawski @ 2007-08-27 12:18 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David S. Miller, netdev
In-Reply-To: <20070822123314.785dea2a@freepuppy.rosehill.hemminger.net>
On 22-08-2007 21:33, Stephen Hemminger wrote:
> Add more kernel doc's for part of the network device API.
> This is only a start, and needs more work.
>
> Applies against net-2.6.24
...
> +/**
> + * napi_disable - prevent NAPI from scheduling
> + * @n: napi context
> + *
> + * Resume NAPI from being scheduled on this context.
> + * Must be paired with napi_disable.
> + */
> static inline void napi_enable(struct napi_struct *n)
> {
It looks like small fix is needed here (I hope it would be faster
without my patch, thanks).
Jarek P.
^ permalink raw reply
* Re: [Devel] [PATCH 1/1] Dynamically allocate the loopback device
From: Eric W. Biederman @ 2007-08-27 12:12 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Denis V. Lunev, dlezcano, davem, containers, netdev
In-Reply-To: <20070824104301.2f4ff34e@localhost>
Stephen Hemminger <shemminger@linux-foundation.org> writes:
> On Fri, 24 Aug 2007 19:55:47 +0400
> "Denis V. Lunev" <dlunev@gmail.com> wrote:
>
>> dlezcano@fr.ibm.com wrote:
>> > From: Daniel Lezcano <dlezcano@fr.ibm.com>
>> >
>> > Doing this makes loopback.c a better example of how to do a
>> > simple network device, and it removes the special case
>> > single static allocation of a struct net_device, hopefully
>> > making maintenance easier.
>> >
>> > Applies against net-2.6.24
>> >
>> > Tested on i386, x86_64
>> > Compiled on ia64, sparc
>>
>> I think that a small note, that initialization order is changed will be
>> good to record. After this, loopback MUST be allocated before any other
>> networking subsystem initialization. And this is an important change.
>>
>> Regards,
>> Den
>
> Yes, this code would break when other drivers are directly linked
> in.
No. Other drivers don't care at all about the loopback device,
and it isn't a requirement that the loopback device be initialized
before other devices.
The requirement is that the loopback device is allocated before
we start using it. Which means networking subsystems like
ipv4 and ipv6 care not other network drivers. In practices this means
before we get very far into the ipv4 subsystem initialization as
ipv4 is always compiled in and is initialized early.
To get the initialization order correct I used fs_initcall instead of
module_init.
When I reflect on it. I'm not really comfortable with the fact
that we currently start using the loopback device before we
finish initializing and register it. Although it has worked
for over a decade so I guess early on we don't care about
much more then the address of the loopback device.
>From what I can tell the initialization order dependency seems much
less subtle and much more robust then separate rules for allocating
the loopback device. We have had several patchs recently that
broke (including one merged upstream). The only way I can see
to break an initialization order dependency is to go deliberately
messing around with initialization order.
Eric
p.s. My apologies for the late reply some one dropped me off the cc.
And I have been under the weather all week.
^ permalink raw reply
* Re: [PATCH] isdn capi driver broken on 64 bit.
From: Karsten Keil @ 2007-08-27 11:02 UTC (permalink / raw)
To: isdn4linux, netdev
In-Reply-To: <20070824110811.32f266f8@freepuppy.rosehill.hemminger.net>
On Fri, Aug 24, 2007 at 11:08:11AM -0700, Stephen Hemminger wrote:
> The following driver API is broken on any architecture with 64 bit addresses.
> because of cast that loses high bits.
>
> Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
>
>
> --- a/drivers/isdn/capi/capidrv.c 2007-06-25 09:03:12.000000000 -0700
> +++ b/drivers/isdn/capi/capidrv.c 2007-08-24 11:06:46.000000000 -0700
> @@ -1855,6 +1855,9 @@ static int if_sendbuf(int id, int channe
> return 0;
> }
> datahandle = nccip->datahandle;
> +
> + /* This won't work on 64 bit! */
> + BUILD_BUG_ON(sizeof(skb->data) > sizeof(u32));
> capi_fill_DATA_B3_REQ(&sendcmsg, global.ap.applid, card->msgid++,
> nccip->ncci, /* adr */
> (u32) skb->data, /* Data */
NACK.
It is not a BUG.
This is OK, since this field must have a value and on 32 it has the correct
one) On 64 bit this field is ignored (but also need a value, random data is
bad as well).
^ permalink raw reply
* Re: [PATCH net-2.6.24] introduce MAC_FMT/MAC_ARG
From: Johannes Berg @ 2007-08-27 10:54 UTC (permalink / raw)
To: Joe Perches; +Cc: David S. Miller, netdev
In-Reply-To: <1188086976.18004.5.camel@localhost>
[-- Attachment #1: Type: text/plain, Size: 1455 bytes --]
On Sat, 2007-08-25 at 17:09 -0700, Joe Perches wrote:
>
> @@ -747,22 +741,15 @@ static int ariadne_rx(struct net_device *dev)
> skb_copy_to_linear_data(skb, (char *)priv->rx_buff[entry],
> pkt_len);
> skb->protocol=eth_type_trans(skb,dev);
> #if 0
> (int)skb->len);
> +{
> + printk(KERN_DEBUG "RX pkt type 0x%04x"
> + " from " MAC_FMT " to " MAC_FMT
> + " data 0x%08x len %d\n",
> + ((u_short *)skb->data)[6],
> + MAC_ARG(((u_char *)skb->data)+6),
> + MAC_ARG((u_char *)skb->data),
> + (int)skb->data, (int)skb->len);
> +}
> #endif
You could drop the braces since there are no variables there any more.
Thanks for this patch though, I'd have done it otherwise.
I was rereading your original conversion and noticed that it is now
trivial to make the kernel smaller like you originally wanted by doing
something like this
-- define this function somewhere --
print_mac(u8 *mac, char *buf)
{
sprintf(buf, "%02x:...", mac[0], mac[1], ...);
}
EXPORT_SYMBOL(print_mac)
-- change macros to --
#define MAC_FMT "%s"
#define MAC_ARG(a) ({char __buf[18]; print_mac(a, buf); __buf})
I'm not sure we'd want that, but at the time you said it made the kernel
significantly smaller and I doubt there's a performance problem with it
(who prints mac addresses regularly?)
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]
^ permalink raw reply
* Re: RFC: issues concerning the next NAPI interface
From: Jan-Bernd Themann @ 2007-08-27 9:47 UTC (permalink / raw)
To: David Miller
Cc: jchapman, shemminger, akepner, netdev, raisch, themann,
linux-kernel, linuxppc-dev, meder, tklein, stefan.roscher
In-Reply-To: <20070826.185815.93042514.davem@davemloft.net>
On Monday 27 August 2007 03:58, David Miller wrote:
> From: James Chapman <jchapman@katalix.com>
> Date: Sun, 26 Aug 2007 20:36:20 +0100
>
> > David Miller wrote:
> > > From: James Chapman <jchapman@katalix.com>
> > > Date: Fri, 24 Aug 2007 18:16:45 +0100
> > >
> > >> Does hardware interrupt mitigation really interact well with NAPI?
> > >
> > > It interacts quite excellently.
> >
> > If NAPI disables interrupts and keeps them disabled while there are more
> > packets arriving or more transmits being completed, why do hardware
> > interrupt mitigation / coalescing features of the network silicon help?
>
> Because if your packet rate is low enough such that the cpu can
> process the interrupt fast enough and thus only one packet gets
> processed per NAPI poll, the cost of going into and out of NAPI mode
> dominates the packet processing costs.
As far as I understand your argumentation, NAPI is supposed to work well only
for HW with coalescing features (concerning dropping the interrupt rate).
NAPI itself does not provide a reliable functionality to reduce the
number of interrupts, especially not for systems with only 1 NIC.
NAPI will only wait for some time when the budget is exceeded
and the softIRQs don't call net_rx_action again. This seems to be the case
after 10 rounds. That means NAPI really waits after 300 x 10 packets
have been processed in a row (worst case).
As a matter of fact there is HW that does not have this feature. There seems
to be HW which does not work well with plain NAPI.
This HW performs well if the operation system supports HP timers
(and when they are used either in the device driver or polling engine).
So the question is simply: Do we want drivers that need (benefit from)
a timer based polling support to implement their own timers each,
or should there be a generic support?
Thanks,
Jan-Bernd
^ permalink raw reply
* pktgen multiqueue oops
From: Robert Olsson @ 2007-08-27 9:16 UTC (permalink / raw)
To: David Miller; +Cc: Robert.Olsson, netdev
Hello,
Initially pkt_dev can be NULL this causes netif_subqueue_stopped to
oops. The patch below should cure it. But maybe the pktgen TX logic
should be reworked to better support the new multiqueue support.
Cheers
--ro
Signed-off-by: Robert Olsson <robert.olsson@its.uu.se>
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 7bae576..a0db4d1 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3331,8 +3331,9 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
}
if ((netif_queue_stopped(odev) ||
- netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) ||
- need_resched()) {
+ (pkt_dev->skb &&
+ netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping))) ||
+ need_resched()) {
idle_start = getCurUs();
if (!netif_running(odev)) {
^ permalink raw reply related
* Re: [NET] atm: Fix build errors after conversion to pr_debug()
From: David Miller @ 2007-08-27 8:13 UTC (permalink / raw)
To: tgraf; +Cc: netdev
In-Reply-To: <20070827080536.GC894@postel.suug.ch>
From: Thomas Graf <tgraf@suug.ch>
Date: Mon, 27 Aug 2007 10:05:37 +0200
> Fixes ancient ATM debug code to at least compile again.
>
> Signed-off-by: Thomas Graf <tgraf@suug.ch>
Patch applied, thanks Thomas!
^ permalink raw reply
* [NET] atm: Fix build errors after conversion to pr_debug()
From: Thomas Graf @ 2007-08-27 8:05 UTC (permalink / raw)
To: davem; +Cc: netdev
Fixes ancient ATM debug code to at least compile again.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Index: net-2.6.24/net/atm/signaling.c
===================================================================
--- net-2.6.24.orig/net/atm/signaling.c 2007-08-27 09:53:40.000000000 +0200
+++ net-2.6.24/net/atm/signaling.c 2007-08-27 09:55:16.000000000 +0200
@@ -89,9 +89,9 @@ static int sigd_send(struct atm_vcc *vcc
msg = (struct atmsvc_msg *) skb->data;
atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
- pr_debug("sigd_send %d (0x%lx)\n",(int) msg->type,
- (unsigned long) msg->vcc);
vcc = *(struct atm_vcc **) &msg->vcc;
+ pr_debug("sigd_send %d (0x%lx)\n",(int) msg->type,
+ (unsigned long) vcc);
sk = sk_atm(vcc);
switch (msg->type) {
Index: net-2.6.24/net/atm/common.c
===================================================================
--- net-2.6.24.orig/net/atm/common.c 2007-08-27 09:56:06.000000000 +0200
+++ net-2.6.24/net/atm/common.c 2007-08-27 09:56:16.000000000 +0200
@@ -497,7 +497,7 @@ int vcc_recvmsg(struct kiocb *iocb, stru
if (error)
return error;
sock_recv_timestamp(msg, sk, skb);
- pr_debug("RcvM %d -= %d\n", atomic_read(&sk->rmem_alloc), skb->truesize);
+ pr_debug("RcvM %d -= %d\n", atomic_read(&sk->sk_rmem_alloc), skb->truesize);
atm_return(vcc, skb->truesize);
skb_free_datagram(sk, skb);
return copied;
Index: net-2.6.24/net/atm/raw.c
===================================================================
--- net-2.6.24.orig/net/atm/raw.c 2007-08-27 09:57:56.000000000 +0200
+++ net-2.6.24/net/atm/raw.c 2007-08-27 09:58:09.000000000 +0200
@@ -32,8 +32,8 @@ static void atm_pop_raw(struct atm_vcc *
{
struct sock *sk = sk_atm(vcc);
- pr_debug("APopR (%d) %d -= %d\n", vcc->vci, sk->sk_wmem_alloc,
- skb->truesize);
+ pr_debug("APopR (%d) %d -= %d\n", vcc->vci,
+ atomic_read(&sk->sk_wmem_alloc), skb->truesize);
atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
dev_kfree_skb_any(skb);
sk->sk_write_space(sk);
Index: net-2.6.24/net/atm/pppoatm.c
===================================================================
--- net-2.6.24.orig/net/atm/pppoatm.c 2007-08-27 10:01:34.000000000 +0200
+++ net-2.6.24/net/atm/pppoatm.c 2007-08-27 10:02:05.000000000 +0200
@@ -165,9 +165,8 @@ static void pppoatm_push(struct atm_vcc
pvcc->chan.mtu += LLC_LEN;
break;
}
- pr_debug("(unit %d): Couldn't autodetect yet "
+ pr_debug("Couldn't autodetect yet "
"(skb: %02X %02X %02X %02X %02X %02X)\n",
- pvcc->chan.unit,
skb->data[0], skb->data[1], skb->data[2],
skb->data[3], skb->data[4], skb->data[5]);
goto error;
@@ -195,8 +194,7 @@ static int pppoatm_send(struct ppp_chann
{
struct pppoatm_vcc *pvcc = chan_to_pvcc(chan);
ATM_SKB(skb)->vcc = pvcc->atmvcc;
- pr_debug("(unit %d): pppoatm_send (skb=0x%p, vcc=0x%p)\n",
- pvcc->chan.unit, skb, pvcc->atmvcc);
+ pr_debug("pppoatm_send (skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc);
if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT))
(void) skb_pull(skb, 1);
switch (pvcc->encaps) { /* LLC encapsulation needed */
@@ -221,16 +219,14 @@ static int pppoatm_send(struct ppp_chann
goto nospace;
break;
case e_autodetect:
- pr_debug("(unit %d): Trying to send without setting encaps!\n",
- pvcc->chan.unit);
+ pr_debug("Trying to send without setting encaps!\n");
kfree_skb(skb);
return 1;
}
atomic_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc);
ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
- pr_debug("(unit %d): atm_skb(%p)->vcc(%p)->dev(%p)\n",
- pvcc->chan.unit, skb, ATM_SKB(skb)->vcc,
+ pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, ATM_SKB(skb)->vcc,
ATM_SKB(skb)->vcc->dev);
return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
? DROP_PACKET : 1;
^ permalink raw reply
* Re: [PATCH 1/2] [DM9000] Added support for big-endian hosts
From: Laurent Pinchart @ 2007-08-27 7:51 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev, Ben Dooks
In-Reply-To: <46CFB0BE.4030301@garzik.org>
On Saturday 25 August 2007 06:31, Jeff Garzik wrote:
> Laurent Pinchart wrote:
> > This patch splits the receive status in 8bit wide fields and convert the
> > packet length from little endian to CPU byte order.
> >
> > Signed-off-by: Laurent Pinchart <laurentp@cse-semaphore.com>
> > ---
> > drivers/net/dm9000.c | 13 +++++++------
> > 1 files changed, 7 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
> > index c3de81b..a424810 100644
> > --- a/drivers/net/dm9000.c
> > +++ b/drivers/net/dm9000.c
> > @@ -894,7 +894,8 @@ dm9000_timer(unsigned long data)
> > }
> >
> > struct dm9000_rxhdr {
> > - u16 RxStatus;
> > + u8 RxPktReady;
> > + u8 RxStatus;
> > u16 RxLen;
> > } __attribute__((__packed__));
>
> why does this not need endian conversions as well?
>
> Jeff
The rx header is a 4-byte structure layed out as above (packet ready, status
and length). The first two fields are 8-bit wide so don't need endian
conversion. The length field is a 16-bit big endian value which is converted
to CPU order in dm9000_rx().
Before this patch, the driver accessed the status and packet ready fields as a
16-bit value, which was obviously endianess-dependant.
Best regards,
--
Laurent Pinchart
CSE Semaphore Belgium
Chaussée de Bruxelles, 732A
B-1410 Waterloo
Belgium
T +32 (2) 387 42 59
F +32 (2) 387 42 75
^ permalink raw reply
* Re: [ANNOUNCE] iproute2-2.6.23-rc3
From: Jarek Poplawski @ 2007-08-27 7:10 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20070824122628.0305f98e@freepuppy.rosehill.hemminger.net>
On Fri, Aug 24, 2007 at 12:26:28PM -0700, Stephen Hemminger wrote:
> On Fri, 24 Aug 2007 12:10:44 +0200
> Jarek Poplawski <jarkao2@o2.pl> wrote:
>
> > On 22-08-2007 20:08, Stephen Hemminger wrote:
> > > There have been a lot of changes for 2.6.23, so here is a test release
> > > of iproute2 that should capture all the submitted patches
> > >
> > >
> > > http://developer.osdl.org/shemminger/iproute2/download/iproute2-2.6.23-rc3.tar.gz
> >
> > But... isn't it forged, btw?!
>
> No, I just didn't sign a temporary testing version. A final version
> will be out after 2.6.23
So, I'm calmer now... On the other hand with kernel testing versions
there seems to be more afraid of?
Jarek P.
^ permalink raw reply
* Re: net/ipv4/fib_trie.c - compile error (Re: 2.6.23-rc3-mm1)
From: Jarek Poplawski @ 2007-08-27 6:36 UTC (permalink / raw)
To: paulmck; +Cc: Adrian Bunk, Gabriel C, Andrew Morton, linux-kernel, netdev
In-Reply-To: <20070822170302.GC8786@linux.vnet.ibm.com>
On 22-08-2007 19:03, Paul E. McKenney wrote:
> On Wed, Aug 22, 2007 at 05:41:11PM +0200, Adrian Bunk wrote:
>> On Wed, Aug 22, 2007 at 05:30:13PM +0200, Gabriel C wrote:
>>> Got it with a randconfig ( http://194.231.229.228/kernel/mm/2.6.23-rc3-mm1/r/randconfig-8 )
>>>
>>> ...
>>>
>>> net/ipv4/fib_trie.c: In function 'trie_rebalance':
>>> net/ipv4/fib_trie.c:969: error: lvalue required as unary '&' operand
>>> net/ipv4/fib_trie.c:971: error: lvalue required as unary '&' operand
>>> net/ipv4/fib_trie.c:977: error: lvalue required as unary '&' operand
>>> net/ipv4/fib_trie.c:980: error: lvalue required as unary '&' operand
>>> ...
>> Side effect of the git-net removal, temporarily removing
>> immunize-rcu_dereference-against-crazy-compiler-writers.patch should
>> work around it.
>
> Alternatively, the following one-line patch to net/ipv4/fib_trie.c could
> be used.
>
> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
> ---
>
> fib_trie.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff -urpNa -X dontdiff linux-2.6.23-rc3-mm1/net/ipv4/fib_trie.c linux-2.6.23-rc3-mm1.compile/net/ipv4/fib_trie.c
> --- linux-2.6.23-rc3-mm1/net/ipv4/fib_trie.c 2007-08-22 09:20:33.000000000 -0700
> +++ linux-2.6.23-rc3-mm1.compile/net/ipv4/fib_trie.c 2007-08-22 09:47:33.000000000 -0700
> @@ -94,7 +94,7 @@ typedef unsigned int t_key;
> #define T_LEAF 1
> #define NODE_TYPE_MASK 0x1UL
> #define NODE_PARENT(node) \
> - ((struct tnode *)rcu_dereference(((node)->parent & ~NODE_TYPE_MASK)))
> + ((struct tnode *)(rcu_dereference((node)->parent) & ~NODE_TYPE_MASK))
...
After first reading of this thread I've had an impression it's about
compiler's behavior, but now it seems to me this patch is not an
alternative, but a 'must be' and only proper way of calling
rcu_dereference (with a variable instead of an expression)? Am I
right?
Regards,
Jarek P.
^ permalink raw reply
* Re: [PATCH 2.6.23-rc3-mm1] request_irq fix DEBUG_SHIRQ handling Re: 2.6.23-rc2-mm1: rtl8139 inconsistent lock state
From: Jarek Poplawski @ 2007-08-27 5:54 UTC (permalink / raw)
To: Mariusz Kozlowski
Cc: Andrew Morton, netdev, Jeff Garzik, David Woodhouse, Ingo Molnar,
Thomas Gleixner, linux-kernel
In-Reply-To: <200708251143.09425.m.kozlowski@tuxland.pl>
On Sat, Aug 25, 2007 at 11:43:08AM +0200, Mariusz Kozlowski wrote:
> > > =================================
> > > [ INFO: inconsistent lock state ]
> > > 2.6.23-rc2-mm1 #7
> > > ---------------------------------
> > > inconsistent {in-hardirq-W} -> {hardirq-on-W} usage.
> > > ifconfig/5492 [HC0[0]:SC0[0]:HE1:SE1] takes:
> > > (&tp->lock){+...}, at: [<de8706e0>] rtl8139_interrupt+0x27/0x46b [8139too]
...
> I tested your patch and it still happens. Dmesg info from patched kernel attached.
> I coulnd't reproduce that on 2.6.23-rc3-mm1 - but on 2.6.23-rc2-mm2 it is easily
> reproducible.
>
> If you need more info, test some patches, etc. - just mail me.
>
...
> =========================================================
> [ INFO: possible irq lock inversion dependency detected ]
> 2.6.23-rc2-mm2 #2
> ---------------------------------------------------------
> runscript.sh/5065 just changed the state of lock:
> (_xmit_ETHER){-+..}, at: [<c03cb659>] dev_watchdog+0x17/0xcc
> but this lock took another, soft-irq-unsafe lock in the past:
> (&tp->lock){--..}
>
> and interrupts could create inverse lock ordering between them.
It's OK! These're 2 different warnings. As a matter of fact, my patch
wasn't supposed to fix any of them, but something similar to the first
one, which was possible, but for some reason wasn't reported by
lockdep.
The first warning was fixed by Andrew Morton's patch to free_irq(),
so it shouldn't happen in -rc3-mm. The second warning could have been
fixed too, I don't know, but since it's quite long, I would prefer to
think about it only if it still happens in current -mm's.
Thanks,
Jarek P.
^ permalink raw reply
* Re: ps3 gelic network driver doesn't restart properly
From: Masakazu Mokuno @ 2007-08-27 5:12 UTC (permalink / raw)
To: Michael Lothian
Cc: Stefan Assmann, Geert Uytterhoeven, netdev, cbe-oss-dev, ppc
In-Reply-To: <fc94aae90708221812w60ba7c30rf2669ae74401ee22@mail.gmail.com>
Sorry for late reply. I was on holiday last week.
On Thu, 23 Aug 2007 02:12:47 +0100
"Michael Lothian" <mike@fireburn.co.uk> wrote:
> I can confirm this behaviour
>
> It could also be worth mentioning I'm using gcc 4.2.1
>
> Cheers
I also reproduced the symptom now. I'll investigate.
Thanks, Stefan and Mike.
--
Masakazu MOKUNO
^ permalink raw reply
* [PATCH] pcnet32: add suspend and resume capability
From: Don Fry @ 2007-08-27 4:22 UTC (permalink / raw)
To: jgarzik; +Cc: netdev
Add suspend and resume capability to the driver.
Tested both to ram and to disk on x86_64 platform.
Signed-off-by: Don Fry <pcnet32@verizon.net>
---
--- linux-2.6.23-rc3/drivers/net/pcnet32.c.orig 2007-08-14 13:52:24.000000000 -0700
+++ linux-2.6.23-rc3/drivers/net/pcnet32.c 2007-08-14 14:16:55.000000000 -0700
@@ -23,11 +23,11 @@
#define DRV_NAME "pcnet32"
#ifdef CONFIG_PCNET32_NAPI
-#define DRV_VERSION "1.33-NAPI"
+#define DRV_VERSION "1.34-NAPI"
#else
-#define DRV_VERSION "1.33"
+#define DRV_VERSION "1.34"
#endif
-#define DRV_RELDATE "27.Jun.2006"
+#define DRV_RELDATE "14.Aug.2007"
#define PFX DRV_NAME ": "
static const char *const version =
@@ -2943,6 +2943,33 @@ static void pcnet32_watchdog(struct net_
mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
}
+static int pcnet32_pm_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ if (netif_running(dev)) {
+ netif_device_detach(dev);
+ pcnet32_close(dev);
+ }
+ pci_save_state(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ return 0;
+}
+
+static int pcnet32_pm_resume(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ if (netif_running(dev)) {
+ pcnet32_open(dev);
+ netif_device_attach(dev);
+ }
+ return 0;
+}
+
static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -2966,6 +2993,8 @@ static struct pci_driver pcnet32_driver
.probe = pcnet32_probe_pci,
.remove = __devexit_p(pcnet32_remove_one),
.id_table = pcnet32_pci_tbl,
+ .suspend = pcnet32_pm_suspend,
+ .resume = pcnet32_pm_resume,
};
/* An additional parameter that may be passed in... */
^ permalink raw reply
* Re: [PATCH 0/9 Rev3] Implement batching skb API and support in IPoIB
From: David Miller @ 2007-08-27 2:04 UTC (permalink / raw)
To: jheffner
Cc: billfink, rick.jones2, hadi, krkumar2, gaagaan, general, herbert,
jagana, jeff, johnpol, kaber, mcarlson, mchan, netdev,
peter.p.waskiewicz.jr, rdreier, Robert.Olsson, shemminger, sri,
tgraf, xma
In-Reply-To: <46D229AA.6020900@psc.edu>
From: John Heffner <jheffner@psc.edu>
Date: Sun, 26 Aug 2007 21:32:26 -0400
> There are a few interesting things here. For one, the bursts caused by
> TSO seem to be causing the receiver to do stretch acks. This may have a
> negative impact on flow performance, but it's hard to say for sure how
> much. Interestingly, it will even further reduce the CPU load on the
> sender, since it has to process fewer acks.
>
> As I suspected, in the non-TSO case the receiver gets lots of packets
> directly queued to user. This should result in somewhat lower CPU
> utilization on the receiver. I don't know if it can account for all the
> difference you see.
I had completely forgotten these stretch ACK and ucopy issues.
When the receiver gets inundated with a backlog of receive
queue packets, it just spins there copying into userspace
_every_ _single_ packet in that queue, then spits out one ACK.
Meanwhile the sender has to pause long enough for the pipe to empty
slightly.
The transfer is much better behaved if we ACK every two full sized
frames we copy into the receiver, and therefore don't stretch ACK, but
at the cost of cpu utilization.
These effects are particularly pronounced on systems where the
bus bandwidth is also one of the limiting factors.
^ permalink raw reply
* Re: RFC: issues concerning the next NAPI interface
From: David Miller @ 2007-08-27 1:58 UTC (permalink / raw)
To: jchapman
Cc: shemminger, ossthema, akepner, netdev, raisch, themann,
linux-kernel, linuxppc-dev, meder, tklein, stefan.roscher
In-Reply-To: <46D1D634.7060007@katalix.com>
From: James Chapman <jchapman@katalix.com>
Date: Sun, 26 Aug 2007 20:36:20 +0100
> David Miller wrote:
> > From: James Chapman <jchapman@katalix.com>
> > Date: Fri, 24 Aug 2007 18:16:45 +0100
> >
> >> Does hardware interrupt mitigation really interact well with NAPI?
> >
> > It interacts quite excellently.
>
> If NAPI disables interrupts and keeps them disabled while there are more
> packets arriving or more transmits being completed, why do hardware
> interrupt mitigation / coalescing features of the network silicon help?
Because if your packet rate is low enough such that the cpu can
process the interrupt fast enough and thus only one packet gets
processed per NAPI poll, the cost of going into and out of NAPI mode
dominates the packet processing costs.
^ permalink raw reply
* Re: [PATCH 0/9 Rev3] Implement batching skb API and support in IPoIB
From: John Heffner @ 2007-08-27 1:32 UTC (permalink / raw)
To: Bill Fink
Cc: Rick Jones, hadi, David Miller, krkumar2, gaagaan, general,
herbert, jagana, jeff, johnpol, kaber, mcarlson, mchan, netdev,
peter.p.waskiewicz.jr, rdreier, Robert.Olsson, shemminger, sri,
tgraf, xma
In-Reply-To: <20070826044134.eabd18cf.billfink@mindspring.com>
Bill Fink wrote:
> Here's the beforeafter delta of the receiver's "netstat -s"
> statistics for the TSO enabled case:
>
> Ip:
> 3659898 total packets received
> 3659898 incoming packets delivered
> 80050 requests sent out
> Tcp:
> 2 passive connection openings
> 3659897 segments received
> 80050 segments send out
> TcpExt:
> 33 packets directly queued to recvmsg prequeue.
> 104956 packets directly received from backlog
> 705528 packets directly received from prequeue
> 3654842 packets header predicted
> 193 packets header predicted and directly queued to user
> 4 acknowledgments not containing data received
> 6 predicted acknowledgments
>
> And here it is for the TSO disabled case (GSO also disabled):
>
> Ip:
> 4107083 total packets received
> 4107083 incoming packets delivered
> 1401376 requests sent out
> Tcp:
> 2 passive connection openings
> 4107083 segments received
> 1401376 segments send out
> TcpExt:
> 2 TCP sockets finished time wait in fast timer
> 48486 packets directly queued to recvmsg prequeue.
> 1056111048 packets directly received from backlog
> 2273357712 packets directly received from prequeue
> 1819317 packets header predicted
> 2287497 packets header predicted and directly queued to user
> 4 acknowledgments not containing data received
> 10 predicted acknowledgments
>
> For the TSO disabled case, there are a huge amount more TCP segments
> sent out (1401376 versus 80050), which I assume are ACKs, and which
> could possibly contribute to the higher throughput for the TSO disabled
> case due to faster feedback, but not explain the lower CPU utilization.
> There are many more packets directly queued to recvmsg prequeue
> (48486 versus 33). The numbers for packets directly received from
> backlog and prequeue in the TCP disabled case seem bogus to me so
> I don't know how to interpret that. There are only about half as
> many packets header predicted (1819317 versus 3654842), but there
> are many more packets header predicted and directly queued to user
> (2287497 versus 193). I'll leave the analysis of all this to those
> who might actually know what it all means.
There are a few interesting things here. For one, the bursts caused by
TSO seem to be causing the receiver to do stretch acks. This may have a
negative impact on flow performance, but it's hard to say for sure how
much. Interestingly, it will even further reduce the CPU load on the
sender, since it has to process fewer acks.
As I suspected, in the non-TSO case the receiver gets lots of packets
directly queued to user. This should result in somewhat lower CPU
utilization on the receiver. I don't know if it can account for all the
difference you see.
The backlog and prequeue values are probably correct, but netstat's
description is wrong. A quick look at the code reveals these values are
in units of bytes, not packets.
-John
^ permalink raw reply
* SCTP: Fix dead loop while received unexpected chunk with length set to zero
From: Wei Yongjun @ 2007-08-27 1:06 UTC (permalink / raw)
To: lksctp-developers, netdev, Vlad Yasevich
A ootb chunk such as data in close state or init-ack in estab state will
cause SCTP to enter dead loop. Look like this:
(1)
Endpoint A Endpoint B
(Closed) (Closed)
DATA -----------------> Kernel dead loop
(With Length set to zero)
(2)
Endpoint A Endpoint B
(Established) (Established)
INIT-ACK -----------------> Kernel dead loop
(With Length set to zero)
This is beacuse when process chunks, chunk->chunk_end is set to the
chunk->chunk_hdr plus chunk length, if chunk length is set to zero,
chunk->chunk_end will be never changed and process enter dead loop.
Following is the patch.
Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
--- a/net/sctp/inqueue.c 2007-08-25 10:53:45.000000000 -0400
+++ b/net/sctp/inqueue.c 2007-08-26 05:45:57.000000000 -0400
@@ -165,10 +165,8 @@ struct sctp_chunk *sctp_inq_pop(struct s
skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t));
chunk->subh.v = NULL; /* Subheader is no longer valid. */
- if (chunk->chunk_end < skb_tail_pointer(chunk->skb)) {
- /* This is not a singleton */
- chunk->singleton = 0;
- } else if (chunk->chunk_end > skb_tail_pointer(chunk->skb)) {
+ if (chunk->chunk_end > skb_tail_pointer(chunk->skb) ||
+ chunk->chunk_end == chunk->chunk_hdr) {
/* RFC 2960, Section 6.10 Bundling
*
* Partial chunks MUST NOT be placed in an SCTP packet.
@@ -183,6 +181,9 @@ struct sctp_chunk *sctp_inq_pop(struct s
chunk = queue->in_progress = NULL;
return NULL;
+ } else if (chunk->chunk_end < skb_tail_pointer(chunk->skb)) {
+ /* This is not a singleton */
+ chunk->singleton = 0;
} else {
/* We are at the end of the packet, so mark the chunk
* in case we need to send a SACK.
^ permalink raw reply
* [PATCH 2/3] [IrDA] Kingsun Dazzle IrDA USB driver
From: Samuel Ortiz @ 2007-08-26 22:15 UTC (permalink / raw)
To: davem; +Cc: netdev, irda-users, Alex Villacís Lasso
In-Reply-To: <20070826221514.036436030@sortiz.org>
[-- Attachment #1: ksdazzle-irda-try2.diff --]
[-- Type: TEXT/PLAIN, Size: 27943 bytes --]
This dongle does not follow the usb-irda specification, so it needs its own
special driver. Just like the Kingsun/Donshine dongle, it exposes two
interrupt endpoints. Reception is performed through direct reads from the
input endpoint. Transmission requires splitting the IrDA frames into 8-byte
segments, in which the first byte encodes how many of the remaining 7 bytes
are used as data. Speed change is made with a control URB just like the one
in cypress_m8, and it seems to support up to 115200 bps.
On plugin, this dongle reports vendor and device IDs: 0x07d0:0x4100
Signed-off-by: Alex VillacÃs Lasso <a_villacis@palosanto.com>
Signed-off-by: Samuel Ortiz <samuel@sortiz.org>
---
drivers/net/irda/Kconfig | 12
drivers/net/irda/Makefile | 1
drivers/net/irda/ksdazzle-sir.c | 823 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 836 insertions(+)
Index: net-2.6.24-quilt/drivers/net/irda/Kconfig
===================================================================
--- net-2.6.24-quilt.orig/drivers/net/irda/Kconfig 2007-08-24 14:55:19.000000000 +0300
+++ net-2.6.24-quilt/drivers/net/irda/Kconfig 2007-08-25 02:43:16.000000000 +0300
@@ -162,7 +162,19 @@
Say Y here if you want to build support for the Cirrus logic
EP7211 chipset's infrared module.
+config KSDAZZLE_DONGLE
+ tristate "KingSun Dazzle IrDA-USB dongle (EXPERIMENTAL)"
+ depends on IRDA && USB && EXPERIMENTAL
+ help
+ Say Y or M here if you want to build support for the KingSun Dazzle
+ IrDA-USB bridge device driver.
+ This USB bridge does not conform to the IrDA-USB device class
+ specification, and therefore needs its own specific driver. This
+ dongle supports SIR speeds only (9600 through 115200 bps).
+
+ To compile it as a module, choose M here: the module will be called
+ ksdazzle-sir.
comment "Old SIR device drivers"
Index: net-2.6.24-quilt/drivers/net/irda/ksdazzle-sir.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ net-2.6.24-quilt/drivers/net/irda/ksdazzle-sir.c 2007-08-25 02:42:20.000000000 +0300
@@ -0,0 +1,823 @@
+/*****************************************************************************
+*
+* Filename: ksdazzle.c
+* Version: 0.1.1
+* Description: Irda KingSun Dazzle USB Dongle
+* Status: Experimental
+* Author: Alex VillacÃs Lasso <a_villacis@palosanto.com>
+*
+* Based on stir4200, mcs7780, kingsun-sir drivers.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+/*
+ * Following is my most current (2007-07-26) understanding of how the Kingsun
+ * 07D0:4100 dongle (sometimes known as the MA-660) is supposed to work. This
+ * information was deduced by examining the USB traffic captured with USBSnoopy
+ * from the WinXP driver. Feel free to update here as more of the dongle is
+ * known.
+ *
+ * General: This dongle exposes one interface with two interrupt endpoints, one
+ * IN and one OUT. In this regard, it is similar to what the Kingsun/Donshine
+ * dongle (07c0:4200) exposes. Traffic is raw and needs to be wrapped and
+ * unwrapped manually as in stir4200, kingsun-sir, and ks959-sir.
+ *
+ * Transmission: To transmit an IrDA frame, it is necessary to wrap it, then
+ * split it into multiple segments of up to 7 bytes each, and transmit each in
+ * sequence. It seems that sending a single big block (like kingsun-sir does)
+ * won't work with this dongle. Each segment needs to be prefixed with a value
+ * equal to (unsigned char)0xF8 + <number of bytes in segment>, inside a payload
+ * of exactly 8 bytes. For example, a segment of 1 byte gets prefixed by 0xF9,
+ * and one of 7 bytes gets prefixed by 0xFF. The bytes at the end of the
+ * payload, not considered by the prefix, are ignored (set to 0 by this
+ * implementation).
+ *
+ * Reception: To receive data, the driver must poll the dongle regularly (like
+ * kingsun-sir.c) with interrupt URBs. If data is available, it will be returned
+ * in payloads from 0 to 8 bytes long. When concatenated, these payloads form
+ * a raw IrDA stream that needs to be unwrapped as in stir4200 and kingsun-sir
+ *
+ * Speed change: To change the speed of the dongle, the driver prepares a
+ * control URB with the following as a setup packet:
+ * bRequestType USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE
+ * bRequest 0x09
+ * wValue 0x0200
+ * wIndex 0x0001
+ * wLength 0x0008 (length of the payload)
+ * The payload is a 8-byte record, apparently identical to the one used in
+ * drivers/usb/serial/cypress_m8.c to change speed:
+ * __u32 baudSpeed;
+ * unsigned int dataBits : 2; // 0 - 5 bits 3 - 8 bits
+ * unsigned int : 1;
+ * unsigned int stopBits : 1;
+ * unsigned int parityEnable : 1;
+ * unsigned int parityType : 1;
+ * unsigned int : 1;
+ * unsigned int reset : 1;
+ * unsigned char reserved[3]; // set to 0
+ *
+ * For now only SIR speeds have been observed with this dongle. Therefore,
+ * nothing is known on what changes (if any) must be done to frame wrapping /
+ * unwrapping for higher than SIR speeds. This driver assumes no change is
+ * necessary and announces support for all the way to 115200 bps.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/usb.h>
+#include <linux/device.h>
+#include <linux/crc32.h>
+
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/crc.h>
+
+#define KSDAZZLE_VENDOR_ID 0x07d0
+#define KSDAZZLE_PRODUCT_ID 0x4100
+
+/* These are the currently known USB ids */
+static struct usb_device_id dongles[] = {
+ /* KingSun Co,Ltd IrDA/USB Bridge */
+ {USB_DEVICE(KSDAZZLE_VENDOR_ID, KSDAZZLE_PRODUCT_ID)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(usb, dongles);
+
+#define KINGSUN_MTT 0x07
+#define KINGSUN_REQ_RECV 0x01
+#define KINGSUN_REQ_SEND 0x09
+
+#define KINGSUN_SND_FIFO_SIZE 2048 /* Max packet we can send */
+
+struct ksdazzle_speedparams {
+ __le32 baudrate; /* baud rate, little endian */
+ __u8 flags;
+ __u8 reserved[3];
+} __attribute__ ((packed));
+
+#define KS_DATA_5_BITS 0x00
+#define KS_DATA_6_BITS 0x01
+#define KS_DATA_7_BITS 0x02
+#define KS_DATA_8_BITS 0x03
+
+#define KS_STOP_BITS_1 0x00
+#define KS_STOP_BITS_2 0x08
+
+#define KS_PAR_DISABLE 0x00
+#define KS_PAR_EVEN 0x10
+#define KS_PAR_ODD 0x30
+#define KS_RESET 0x80
+
+#define KINGSUN_EP_IN 0
+#define KINGSUN_EP_OUT 1
+
+struct ksdazzle_cb {
+ struct usb_device *usbdev; /* init: probe_irda */
+ struct net_device *netdev; /* network layer */
+ struct irlap_cb *irlap; /* The link layer we are binded to */
+ struct net_device_stats stats; /* network statistics */
+ struct qos_info qos;
+
+ struct urb *tx_urb;
+ __u8 *tx_buf_clear;
+ unsigned int tx_buf_clear_used;
+ unsigned int tx_buf_clear_sent;
+ __u8 tx_payload[8];
+
+ struct urb *rx_urb;
+ __u8 rx_payload[8];
+ iobuff_t rx_unwrap_buff;
+
+ struct usb_ctrlrequest *speed_setuprequest;
+ struct urb *speed_urb;
+ struct ksdazzle_speedparams speedparams;
+ unsigned int new_speed;
+
+ __u8 ep_in;
+ __u8 ep_out;
+
+ spinlock_t lock;
+ int receiving;
+};
+
+/* Callback transmission routine */
+static void ksdazzle_speed_irq(struct urb *urb)
+{
+ /* unlink, shutdown, unplug, other nasties */
+ if (urb->status != 0) {
+ err("ksdazzle_speed_irq: urb asynchronously failed - %d",
+ urb->status);
+ }
+}
+
+/* Send a control request to change speed of the dongle */
+static int ksdazzle_change_speed(struct ksdazzle_cb *kingsun, unsigned speed)
+{
+ static unsigned int supported_speeds[] = { 2400, 9600, 19200, 38400,
+ 57600, 115200, 576000, 1152000, 4000000, 0
+ };
+ int err;
+ unsigned int i;
+
+ if (kingsun->speed_setuprequest == NULL || kingsun->speed_urb == NULL)
+ return -ENOMEM;
+
+ /* Check that requested speed is among the supported ones */
+ for (i = 0; supported_speeds[i] && supported_speeds[i] != speed; i++) ;
+ if (supported_speeds[i] == 0)
+ return -EOPNOTSUPP;
+
+ memset(&(kingsun->speedparams), 0, sizeof(struct ksdazzle_speedparams));
+ kingsun->speedparams.baudrate = cpu_to_le32(speed);
+ kingsun->speedparams.flags = KS_DATA_8_BITS;
+
+ /* speed_setuprequest pre-filled in ksdazzle_probe */
+ usb_fill_control_urb(kingsun->speed_urb, kingsun->usbdev,
+ usb_sndctrlpipe(kingsun->usbdev, 0),
+ (unsigned char *)kingsun->speed_setuprequest,
+ &(kingsun->speedparams),
+ sizeof(struct ksdazzle_speedparams),
+ ksdazzle_speed_irq, kingsun);
+ kingsun->speed_urb->status = 0;
+ err = usb_submit_urb(kingsun->speed_urb, GFP_ATOMIC);
+
+ return err;
+}
+
+/* Submit one fragment of an IrDA frame to the dongle */
+static void ksdazzle_send_irq(struct urb *urb);
+static int ksdazzle_submit_tx_fragment(struct ksdazzle_cb *kingsun)
+{
+ unsigned int wraplen;
+ int ret;
+
+ /* We can send at most 7 bytes of payload at a time */
+ wraplen = 7;
+ if (wraplen > kingsun->tx_buf_clear_used)
+ wraplen = kingsun->tx_buf_clear_used;
+
+ /* Prepare payload prefix with used length */
+ memset(kingsun->tx_payload, 0, 8);
+ kingsun->tx_payload[0] = (unsigned char)0xf8 + wraplen;
+ memcpy(kingsun->tx_payload + 1, kingsun->tx_buf_clear, wraplen);
+
+ usb_fill_int_urb(kingsun->tx_urb, kingsun->usbdev,
+ usb_sndintpipe(kingsun->usbdev, kingsun->ep_out),
+ kingsun->tx_payload, 8, ksdazzle_send_irq, kingsun, 1);
+ kingsun->tx_urb->status = 0;
+ ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC);
+
+ /* Remember how much data was sent, in order to update at callback */
+ kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0;
+ return ret;
+}
+
+/* Callback transmission routine */
+static void ksdazzle_send_irq(struct urb *urb)
+{
+ struct ksdazzle_cb *kingsun = urb->context;
+ struct net_device *netdev = kingsun->netdev;
+ int ret = 0;
+
+ /* in process of stopping, just drop data */
+ if (!netif_running(kingsun->netdev)) {
+ err("ksdazzle_send_irq: Network not running!");
+ return;
+ }
+
+ /* unlink, shutdown, unplug, other nasties */
+ if (urb->status != 0) {
+ err("ksdazzle_send_irq: urb asynchronously failed - %d",
+ urb->status);
+ return;
+ }
+
+ if (kingsun->tx_buf_clear_used > 0) {
+ /* Update data remaining to be sent */
+ if (kingsun->tx_buf_clear_sent < kingsun->tx_buf_clear_used) {
+ memmove(kingsun->tx_buf_clear,
+ kingsun->tx_buf_clear +
+ kingsun->tx_buf_clear_sent,
+ kingsun->tx_buf_clear_used -
+ kingsun->tx_buf_clear_sent);
+ }
+ kingsun->tx_buf_clear_used -= kingsun->tx_buf_clear_sent;
+ kingsun->tx_buf_clear_sent = 0;
+
+ if (kingsun->tx_buf_clear_used > 0) {
+ /* There is more data to be sent */
+ if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) {
+ err("ksdazzle_send_irq: failed tx_urb submit: %d", ret);
+ switch (ret) {
+ case -ENODEV:
+ case -EPIPE:
+ break;
+ default:
+ kingsun->stats.tx_errors++;
+ netif_start_queue(netdev);
+ }
+ }
+ } else {
+ /* All data sent, send next speed && wake network queue */
+ if (kingsun->new_speed != -1 &&
+ cpu_to_le32(kingsun->new_speed) !=
+ kingsun->speedparams.baudrate)
+ ksdazzle_change_speed(kingsun,
+ kingsun->new_speed);
+
+ netif_wake_queue(netdev);
+ }
+ }
+}
+
+/*
+ * Called from net/core when new frame is available.
+ */
+static int ksdazzle_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct ksdazzle_cb *kingsun;
+ unsigned int wraplen;
+ int ret = 0;
+
+ if (skb == NULL || netdev == NULL)
+ return -EINVAL;
+
+ netif_stop_queue(netdev);
+
+ /* the IRDA wrapping routines don't deal with non linear skb */
+ SKB_LINEAR_ASSERT(skb);
+
+ kingsun = netdev_priv(netdev);
+
+ spin_lock(&kingsun->lock);
+ kingsun->new_speed = irda_get_next_speed(skb);
+
+ /* Append data to the end of whatever data remains to be transmitted */
+ wraplen =
+ async_wrap_skb(skb, kingsun->tx_buf_clear, KINGSUN_SND_FIFO_SIZE);
+ kingsun->tx_buf_clear_used = wraplen;
+
+ if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) {
+ err("ksdazzle_hard_xmit: failed tx_urb submit: %d", ret);
+ switch (ret) {
+ case -ENODEV:
+ case -EPIPE:
+ break;
+ default:
+ kingsun->stats.tx_errors++;
+ netif_start_queue(netdev);
+ }
+ } else {
+ kingsun->stats.tx_packets++;
+ kingsun->stats.tx_bytes += skb->len;
+
+ }
+
+ dev_kfree_skb(skb);
+ spin_unlock(&kingsun->lock);
+
+ return ret;
+}
+
+/* Receive callback function */
+static void ksdazzle_rcv_irq(struct urb *urb)
+{
+ struct ksdazzle_cb *kingsun = urb->context;
+
+ /* in process of stopping, just drop data */
+ if (!netif_running(kingsun->netdev)) {
+ kingsun->receiving = 0;
+ return;
+ }
+
+ /* unlink, shutdown, unplug, other nasties */
+ if (urb->status != 0) {
+ err("ksdazzle_rcv_irq: urb asynchronously failed - %d",
+ urb->status);
+ kingsun->receiving = 0;
+ return;
+ }
+
+ if (urb->actual_length > 0) {
+ __u8 *bytes = urb->transfer_buffer;
+ unsigned int i;
+
+ for (i = 0; i < urb->actual_length; i++) {
+ async_unwrap_char(kingsun->netdev, &kingsun->stats,
+ &kingsun->rx_unwrap_buff, bytes[i]);
+ }
+ kingsun->netdev->last_rx = jiffies;
+ kingsun->receiving =
+ (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
+ }
+
+ /* This urb has already been filled in ksdazzle_net_open. It is assumed that
+ urb keeps the pointer to the payload buffer.
+ */
+ urb->status = 0;
+ usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+/*
+ * Function ksdazzle_net_open (dev)
+ *
+ * Network device is taken up. Usually this is done by "ifconfig irda0 up"
+ */
+static int ksdazzle_net_open(struct net_device *netdev)
+{
+ struct ksdazzle_cb *kingsun = netdev_priv(netdev);
+ int err = -ENOMEM;
+ char hwname[16];
+
+ /* At this point, urbs are NULL, and skb is NULL (see ksdazzle_probe) */
+ kingsun->receiving = 0;
+
+ /* Initialize for SIR to copy data directly into skb. */
+ kingsun->rx_unwrap_buff.in_frame = FALSE;
+ kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
+ kingsun->rx_unwrap_buff.truesize = IRDA_SKB_MAX_MTU;
+ kingsun->rx_unwrap_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
+ if (!kingsun->rx_unwrap_buff.skb)
+ goto free_mem;
+
+ skb_reserve(kingsun->rx_unwrap_buff.skb, 1);
+ kingsun->rx_unwrap_buff.head = kingsun->rx_unwrap_buff.skb->data;
+
+ kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!kingsun->rx_urb)
+ goto free_mem;
+
+ kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!kingsun->tx_urb)
+ goto free_mem;
+
+ kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!kingsun->speed_urb)
+ goto free_mem;
+
+ /* Initialize speed for dongle */
+ kingsun->new_speed = 9600;
+ err = ksdazzle_change_speed(kingsun, 9600);
+ if (err < 0)
+ goto free_mem;
+
+ /*
+ * Now that everything should be initialized properly,
+ * Open new IrLAP layer instance to take care of us...
+ */
+ sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
+ kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
+ if (!kingsun->irlap) {
+ err("ksdazzle-sir: irlap_open failed");
+ goto free_mem;
+ }
+
+ /* Start reception. */
+ usb_fill_int_urb(kingsun->rx_urb, kingsun->usbdev,
+ usb_rcvintpipe(kingsun->usbdev, kingsun->ep_in),
+ kingsun->rx_payload, 8, ksdazzle_rcv_irq, kingsun, 1);
+ kingsun->rx_urb->status = 0;
+ err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
+ if (err) {
+ err("ksdazzle-sir: first urb-submit failed: %d", err);
+ goto close_irlap;
+ }
+
+ netif_start_queue(netdev);
+
+ /* Situation at this point:
+ - all work buffers allocated
+ - urbs allocated and ready to fill
+ - max rx packet known (in max_rx)
+ - unwrap state machine initialized, in state outside of any frame
+ - receive request in progress
+ - IrLAP layer started, about to hand over packets to send
+ */
+
+ return 0;
+
+ close_irlap:
+ irlap_close(kingsun->irlap);
+ free_mem:
+ usb_free_urb(kingsun->speed_urb);
+ kingsun->speed_urb = NULL;
+ usb_free_urb(kingsun->tx_urb);
+ kingsun->tx_urb = NULL;
+ usb_free_urb(kingsun->rx_urb);
+ kingsun->rx_urb = NULL;
+ if (kingsun->rx_unwrap_buff.skb) {
+ kfree_skb(kingsun->rx_unwrap_buff.skb);
+ kingsun->rx_unwrap_buff.skb = NULL;
+ kingsun->rx_unwrap_buff.head = NULL;
+ }
+ return err;
+}
+
+/*
+ * Function ksdazzle_net_close (dev)
+ *
+ * Network device is taken down. Usually this is done by
+ * "ifconfig irda0 down"
+ */
+static int ksdazzle_net_close(struct net_device *netdev)
+{
+ struct ksdazzle_cb *kingsun = netdev_priv(netdev);
+
+ /* Stop transmit processing */
+ netif_stop_queue(netdev);
+
+ /* Mop up receive && transmit urb's */
+ usb_kill_urb(kingsun->tx_urb);
+ usb_free_urb(kingsun->tx_urb);
+ kingsun->tx_urb = NULL;
+
+ usb_kill_urb(kingsun->speed_urb);
+ usb_free_urb(kingsun->speed_urb);
+ kingsun->speed_urb = NULL;
+
+ usb_kill_urb(kingsun->rx_urb);
+ usb_free_urb(kingsun->rx_urb);
+ kingsun->rx_urb = NULL;
+
+ kfree_skb(kingsun->rx_unwrap_buff.skb);
+ kingsun->rx_unwrap_buff.skb = NULL;
+ kingsun->rx_unwrap_buff.head = NULL;
+ kingsun->rx_unwrap_buff.in_frame = FALSE;
+ kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
+ kingsun->receiving = 0;
+
+ /* Stop and remove instance of IrLAP */
+ irlap_close(kingsun->irlap);
+
+ kingsun->irlap = NULL;
+
+ return 0;
+}
+
+/*
+ * IOCTLs : Extra out-of-band network commands...
+ */
+static int ksdazzle_net_ioctl(struct net_device *netdev, struct ifreq *rq,
+ int cmd)
+{
+ struct if_irda_req *irq = (struct if_irda_req *)rq;
+ struct ksdazzle_cb *kingsun = netdev_priv(netdev);
+ int ret = 0;
+
+ switch (cmd) {
+ case SIOCSBANDWIDTH: /* Set bandwidth */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ /* Check if the device is still there */
+ if (netif_device_present(kingsun->netdev))
+ return ksdazzle_change_speed(kingsun,
+ irq->ifr_baudrate);
+ break;
+
+ case SIOCSMEDIABUSY: /* Set media busy */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ /* Check if the IrDA stack is still there */
+ if (netif_running(kingsun->netdev))
+ irda_device_set_media_busy(kingsun->netdev, TRUE);
+ break;
+
+ case SIOCGRECEIVING:
+ /* Only approximately true */
+ irq->ifr_receiving = kingsun->receiving;
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+/*
+ * Get device stats (for /proc/net/dev and ifconfig)
+ */
+static struct net_device_stats *ksdazzle_net_get_stats(struct net_device
+ *netdev)
+{
+ struct ksdazzle_cb *kingsun = netdev_priv(netdev);
+ return &kingsun->stats;
+}
+
+/*
+ * This routine is called by the USB subsystem for each new device
+ * in the system. We need to check if the device is ours, and in
+ * this case start handling it.
+ */
+static int ksdazzle_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_host_interface *interface;
+ struct usb_endpoint_descriptor *endpoint;
+
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct ksdazzle_cb *kingsun = NULL;
+ struct net_device *net = NULL;
+ int ret = -ENOMEM;
+ int pipe, maxp_in, maxp_out;
+ __u8 ep_in;
+ __u8 ep_out;
+
+ /* Check that there really are two interrupt endpoints. Check based on the
+ one in drivers/usb/input/usbmouse.c
+ */
+ interface = intf->cur_altsetting;
+ if (interface->desc.bNumEndpoints != 2) {
+ err("ksdazzle: expected 2 endpoints, found %d",
+ interface->desc.bNumEndpoints);
+ return -ENODEV;
+ }
+ endpoint = &interface->endpoint[KINGSUN_EP_IN].desc;
+ if (!usb_endpoint_is_int_in(endpoint)) {
+ err("ksdazzle: endpoint 0 is not interrupt IN");
+ return -ENODEV;
+ }
+
+ ep_in = endpoint->bEndpointAddress;
+ pipe = usb_rcvintpipe(dev, ep_in);
+ maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+ if (maxp_in > 255 || maxp_in <= 1) {
+ err("ksdazzle: endpoint 0 has max packet size %d not in range [2..255]", maxp_in);
+ return -ENODEV;
+ }
+
+ endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc;
+ if (!usb_endpoint_is_int_out(endpoint)) {
+ err("ksdazzle: endpoint 1 is not interrupt OUT");
+ return -ENODEV;
+ }
+
+ ep_out = endpoint->bEndpointAddress;
+ pipe = usb_sndintpipe(dev, ep_out);
+ maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+ /* Allocate network device container. */
+ net = alloc_irdadev(sizeof(*kingsun));
+ if (!net)
+ goto err_out1;
+
+ SET_MODULE_OWNER(net);
+ SET_NETDEV_DEV(net, &intf->dev);
+ kingsun = netdev_priv(net);
+ kingsun->netdev = net;
+ kingsun->usbdev = dev;
+ kingsun->ep_in = ep_in;
+ kingsun->ep_out = ep_out;
+ kingsun->irlap = NULL;
+ kingsun->tx_urb = NULL;
+ kingsun->tx_buf_clear = NULL;
+ kingsun->tx_buf_clear_used = 0;
+ kingsun->tx_buf_clear_sent = 0;
+
+ kingsun->rx_urb = NULL;
+ kingsun->rx_unwrap_buff.in_frame = FALSE;
+ kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
+ kingsun->rx_unwrap_buff.skb = NULL;
+ kingsun->receiving = 0;
+ spin_lock_init(&kingsun->lock);
+
+ kingsun->speed_setuprequest = NULL;
+ kingsun->speed_urb = NULL;
+ kingsun->speedparams.baudrate = 0;
+
+ /* Allocate output buffer */
+ kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL);
+ if (!kingsun->tx_buf_clear)
+ goto free_mem;
+
+ /* Allocate and initialize speed setup packet */
+ kingsun->speed_setuprequest =
+ kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
+ if (!kingsun->speed_setuprequest)
+ goto free_mem;
+ kingsun->speed_setuprequest->bRequestType =
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND;
+ kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200);
+ kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001);
+ kingsun->speed_setuprequest->wLength =
+ cpu_to_le16(sizeof(struct ksdazzle_speedparams));
+
+ printk(KERN_INFO "KingSun/Dazzle IRDA/USB found at address %d, "
+ "Vendor: %x, Product: %x\n",
+ dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
+
+ /* Initialize QoS for this device */
+ irda_init_max_qos_capabilies(&kingsun->qos);
+
+ /* Baud rates known to be supported. Please uncomment if devices (other
+ than a SonyEriccson K300 phone) can be shown to support higher speeds
+ with this dongle.
+ */
+ kingsun->qos.baud_rate.bits =
+ IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200;
+ kingsun->qos.min_turn_time.bits &= KINGSUN_MTT;
+ irda_qos_bits_to_value(&kingsun->qos);
+
+ /* Override the network functions we need to use */
+ net->hard_start_xmit = ksdazzle_hard_xmit;
+ net->open = ksdazzle_net_open;
+ net->stop = ksdazzle_net_close;
+ net->get_stats = ksdazzle_net_get_stats;
+ net->do_ioctl = ksdazzle_net_ioctl;
+
+ ret = register_netdev(net);
+ if (ret != 0)
+ goto free_mem;
+
+ info("IrDA: Registered KingSun/Dazzle device %s", net->name);
+
+ usb_set_intfdata(intf, kingsun);
+
+ /* Situation at this point:
+ - all work buffers allocated
+ - setup requests pre-filled
+ - urbs not allocated, set to NULL
+ - max rx packet known (is KINGSUN_FIFO_SIZE)
+ - unwrap state machine (partially) initialized, but skb == NULL
+ */
+
+ return 0;
+
+ free_mem:
+ kfree(kingsun->speed_setuprequest);
+ kfree(kingsun->tx_buf_clear);
+ free_netdev(net);
+ err_out1:
+ return ret;
+}
+
+/*
+ * The current device is removed, the USB layer tell us to shut it down...
+ */
+static void ksdazzle_disconnect(struct usb_interface *intf)
+{
+ struct ksdazzle_cb *kingsun = usb_get_intfdata(intf);
+
+ if (!kingsun)
+ return;
+
+ unregister_netdev(kingsun->netdev);
+
+ /* Mop up receive && transmit urb's */
+ usb_kill_urb(kingsun->speed_urb);
+ usb_free_urb(kingsun->speed_urb);
+ kingsun->speed_urb = NULL;
+
+ usb_kill_urb(kingsun->tx_urb);
+ usb_free_urb(kingsun->tx_urb);
+ kingsun->tx_urb = NULL;
+
+ usb_kill_urb(kingsun->rx_urb);
+ usb_free_urb(kingsun->rx_urb);
+ kingsun->rx_urb = NULL;
+
+ kfree(kingsun->speed_setuprequest);
+ kfree(kingsun->tx_buf_clear);
+ free_netdev(kingsun->netdev);
+
+ usb_set_intfdata(intf, NULL);
+}
+
+#ifdef CONFIG_PM
+/* USB suspend, so power off the transmitter/receiver */
+static int ksdazzle_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct ksdazzle_cb *kingsun = usb_get_intfdata(intf);
+
+ netif_device_detach(kingsun->netdev);
+ if (kingsun->speed_urb != NULL)
+ usb_kill_urb(kingsun->speed_urb);
+ if (kingsun->tx_urb != NULL)
+ usb_kill_urb(kingsun->tx_urb);
+ if (kingsun->rx_urb != NULL)
+ usb_kill_urb(kingsun->rx_urb);
+ return 0;
+}
+
+/* Coming out of suspend, so reset hardware */
+static int ksdazzle_resume(struct usb_interface *intf)
+{
+ struct ksdazzle_cb *kingsun = usb_get_intfdata(intf);
+
+ if (kingsun->rx_urb != NULL) {
+ /* Setup request already filled in ksdazzle_probe */
+ usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
+ }
+ netif_device_attach(kingsun->netdev);
+
+ return 0;
+}
+#endif
+
+/*
+ * USB device callbacks
+ */
+static struct usb_driver irda_driver = {
+ .name = "ksdazzle-sir",
+ .probe = ksdazzle_probe,
+ .disconnect = ksdazzle_disconnect,
+ .id_table = dongles,
+#ifdef CONFIG_PM
+ .suspend = ksdazzle_suspend,
+ .resume = ksdazzle_resume,
+#endif
+};
+
+/*
+ * Module insertion
+ */
+static int __init ksdazzle_init(void)
+{
+ return usb_register(&irda_driver);
+}
+
+module_init(ksdazzle_init);
+
+/*
+ * Module removal
+ */
+static void __exit ksdazzle_cleanup(void)
+{
+ /* Deregister the driver and remove all pending instances */
+ usb_deregister(&irda_driver);
+}
+
+module_exit(ksdazzle_cleanup);
+
+MODULE_AUTHOR("Alex VillacÃs Lasso <a_villacis@palosanto.com>");
+MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun Dazzle");
+MODULE_LICENSE("GPL");
Index: net-2.6.24-quilt/drivers/net/irda/Makefile
===================================================================
--- net-2.6.24-quilt.orig/drivers/net/irda/Makefile 2007-08-24 14:55:19.000000000 +0300
+++ net-2.6.24-quilt/drivers/net/irda/Makefile 2007-08-25 02:42:20.000000000 +0300
@@ -47,6 +47,7 @@
obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o
obj-$(CONFIG_EP7211_DONGLE) += ep7211-sir.o
obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o
+obj-$(CONFIG_KSDAZZLE_DONGLE) += ksdazzle-sir.o
# The SIR helper module
sir-dev-objs := sir_dev.o sir_dongle.o
--
^ permalink raw reply
* [PATCH 1/3] [IrDA] MSG_NOSIGNAL support for IrDA sockets
From: Samuel Ortiz @ 2007-08-26 22:15 UTC (permalink / raw)
To: davem; +Cc: netdev, irda-users
In-Reply-To: <20070826221514.036436030@sortiz.org>
[-- Attachment #1: irda_socket_msg_nosignal --]
[-- Type: text/plain, Size: 1819 bytes --]
Signed-off-by: Samuel Ortiz <samuel@sortiz.org>
---
net/irda/af_irda.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
Index: net-2.6.24-quilt/net/irda/af_irda.c
===================================================================
--- net-2.6.24-quilt.orig/net/irda/af_irda.c 2007-08-25 02:41:39.000000000 +0300
+++ net-2.6.24-quilt/net/irda/af_irda.c 2007-08-25 02:41:41.000000000 +0300
@@ -1245,18 +1245,17 @@
struct sock *sk = sock->sk;
struct irda_sock *self;
struct sk_buff *skb;
- int err;
+ int err = -EPIPE;
IRDA_DEBUG(4, "%s(), len=%zd\n", __FUNCTION__, len);
/* Note : socket.c set MSG_EOR on SEQPACKET sockets */
- if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT))
+ if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT |
+ MSG_NOSIGNAL))
return -EINVAL;
- if (sk->sk_shutdown & SEND_SHUTDOWN) {
- send_sig(SIGPIPE, current, 0);
- return -EPIPE;
- }
+ if (sk->sk_shutdown & SEND_SHUTDOWN)
+ goto out_err;
if (sk->sk_state != TCP_ESTABLISHED)
return -ENOTCONN;
@@ -1283,7 +1282,7 @@
skb = sock_alloc_send_skb(sk, len + self->max_header_size + 16,
msg->msg_flags & MSG_DONTWAIT, &err);
if (!skb)
- return -ENOBUFS;
+ goto out_err;
skb_reserve(skb, self->max_header_size + 16);
skb_reset_transport_header(skb);
@@ -1291,7 +1290,7 @@
err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
if (err) {
kfree_skb(skb);
- return err;
+ goto out_err;
}
/*
@@ -1301,10 +1300,14 @@
err = irttp_data_request(self->tsap, skb);
if (err) {
IRDA_DEBUG(0, "%s(), err=%d\n", __FUNCTION__, err);
- return err;
+ goto out_err;
}
/* Tell client how much data we actually sent */
return len;
+
+ out_err:
+ return sk_stream_error(sk, msg->msg_flags, err);
+
}
/*
--
^ permalink raw reply
* [PATCH 3/3] [IrDA] Kingsun KS-959 IrDA USB driver
From: Samuel Ortiz @ 2007-08-26 22:15 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Alex Villacís Lasso,
irda-users-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <20070826221514.036436030@sortiz.org>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: ks959-irda-tryN.diff --]
[-- Type: text/plain, Size: 32906 bytes --]
This dongle does not follow the usb-irda specification, so it needs its own
special driver. First, it uses control URBs for data transfer, instead of
bulk or interrupt transfers; the only interrupt endpoint exposed seems to
be a dummy to prevent the interface from being rejected. Second, it uses
obfuscation and padding at the USB traffic level, for no apparent reason
other than to make reverse engineering harder (full details on obfuscation
in comments at beginning of source). Although it is advertised as a "4 Mbps
FIR dongle", it apparently loses packets at speeds greater than 57600 bps.
On plugin, this dongle reports vendor and device IDs: 0x07d0:0x4959 .
The Windows driver that is used normally to control this dongle has a
filename of KS-959.SYS .
Signed-off-by: Alex Villacís Lasso <a_villacis-5itmuRygkZmgSpxsJD1C4w@public.gmane.org>
Signed-off-by: Samuel Ortiz <samuel-jcdQHdrhKHMdnm+yROfE0A@public.gmane.org>
---
drivers/net/irda/Kconfig | 14
drivers/net/irda/Makefile | 1
drivers/net/irda/ks959-sir.c | 939 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 954 insertions(+)
Index: net-2.6.24-quilt/drivers/net/irda/Kconfig
===================================================================
--- net-2.6.24-quilt.orig/drivers/net/irda/Kconfig 2007-08-25 02:43:16.000000000 +0300
+++ net-2.6.24-quilt/drivers/net/irda/Kconfig 2007-08-25 03:05:15.000000000 +0300
@@ -176,6 +176,20 @@
To compile it as a module, choose M here: the module will be called
ksdazzle-sir.
+config KS959_DONGLE
+ tristate "KingSun KS-959 IrDA-USB dongle (EXPERIMENTAL)"
+ depends on IRDA && USB && EXPERIMENTAL
+ help
+ Say Y or M here if you want to build support for the KingSun KS-959
+ IrDA-USB bridge device driver.
+
+ This USB bridge does not conform to the IrDA-USB device class
+ specification, and therefore needs its own specific driver. This
+ dongle supports SIR speeds only (9600 through 57600 bps).
+
+ To compile it as a module, choose M here: the module will be called
+ ks959-sir.
+
comment "Old SIR device drivers"
config IRPORT_SIR
Index: net-2.6.24-quilt/drivers/net/irda/ks959-sir.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ net-2.6.24-quilt/drivers/net/irda/ks959-sir.c 2007-08-25 03:04:30.000000000 +0300
@@ -0,0 +1,939 @@
+/*****************************************************************************
+*
+* Filename: ks959-sir.c
+* Version: 0.1.2
+* Description: Irda KingSun KS-959 USB Dongle
+* Status: Experimental
+* Author: Alex Villacís Lasso <a_villacis-5itmuRygkZmgSpxsJD1C4w@public.gmane.org>
+* with help from Domen Puncer <domen-CvScVCPLwOZg9hUCZPvPmw@public.gmane.org>
+*
+* Based on stir4200, mcs7780, kingsun-sir drivers.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+/*
+ * Following is my most current (2007-07-17) understanding of how the Kingsun
+ * KS-959 dongle is supposed to work. This information was deduced by
+ * reverse-engineering and examining the USB traffic captured with USBSnoopy
+ * from the WinXP driver. Feel free to update here as more of the dongle is
+ * known.
+ *
+ * My most sincere thanks must go to Domen Puncer <domen-CvScVCPLwOZg9hUCZPvPmw@public.gmane.org> for
+ * invaluable help in cracking the obfuscation and padding required for this
+ * dongle.
+ *
+ * General: This dongle exposes one interface with one interrupt IN endpoint.
+ * However, the interrupt endpoint is NOT used at all for this dongle. Instead,
+ * this dongle uses control transfers for everything, including sending and
+ * receiving the IrDA frame data. Apparently the interrupt endpoint is just a
+ * dummy to ensure the dongle has a valid interface to present to the PC.And I
+ * thought the DonShine dongle was weird... In addition, this dongle uses
+ * obfuscation (?!?!), applied at the USB level, to hide the traffic, both sent
+ * and received, from the dongle. I call it obfuscation because the XOR keying
+ * and padding required to produce an USB traffic acceptable for the dongle can
+ * not be explained by any other technical requirement.
+ *
+ * Transmission: To transmit an IrDA frame, the driver must prepare a control
+ * URB with the following as a setup packet:
+ * bRequestType USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE
+ * bRequest 0x09
+ * wValue <length of valid data before padding, little endian>
+ * wIndex 0x0000
+ * wLength <length of padded data>
+ * The payload packet must be manually wrapped and escaped (as in stir4200.c),
+ * then padded and obfuscated before being sent. Both padding and obfuscation
+ * are implemented in the procedure obfuscate_tx_buffer(). Suffice to say, the
+ * designer/programmer of the dongle used his name as a source for the
+ * obfuscation. WTF?!
+ * Apparently the dongle cannot handle payloads larger than 256 bytes. The
+ * driver has to perform fragmentation in order to send anything larger than
+ * this limit.
+ *
+ * Reception: To receive data, the driver must poll the dongle regularly (like
+ * kingsun-sir.c) with control URBs and the following as a setup packet:
+ * bRequestType USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE
+ * bRequest 0x01
+ * wValue 0x0200
+ * wIndex 0x0000
+ * wLength 0x0800 (size of available buffer)
+ * If there is data to be read, it will be returned as the response payload.
+ * This data is (apparently) not padded, but it is obfuscated. To de-obfuscate
+ * it, the driver must XOR every byte, in sequence, with a value that starts at
+ * 1 and is incremented with each byte processed, and then with 0x55. The value
+ * incremented with each byte processed overflows as an unsigned char. The
+ * resulting bytes form a wrapped SIR frame that is unwrapped and unescaped
+ * as in stir4200.c The incremented value is NOT reset with each frame, but is
+ * kept across the entire session with the dongle. Also, the dongle inserts an
+ * extra garbage byte with value 0x95 (after decoding) every 0xff bytes, which
+ * must be skipped.
+ *
+ * Speed change: To change the speed of the dongle, the driver prepares a
+ * control URB with the following as a setup packet:
+ * bRequestType USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE
+ * bRequest 0x09
+ * wValue 0x0200
+ * wIndex 0x0001
+ * wLength 0x0008 (length of the payload)
+ * The payload is a 8-byte record, apparently identical to the one used in
+ * drivers/usb/serial/cypress_m8.c to change speed:
+ * __u32 baudSpeed;
+ * unsigned int dataBits : 2; // 0 - 5 bits 3 - 8 bits
+ * unsigned int : 1;
+ * unsigned int stopBits : 1;
+ * unsigned int parityEnable : 1;
+ * unsigned int parityType : 1;
+ * unsigned int : 1;
+ * unsigned int reset : 1;
+ * unsigned char reserved[3]; // set to 0
+ *
+ * For now only SIR speeds have been observed with this dongle. Therefore,
+ * nothing is known on what changes (if any) must be done to frame wrapping /
+ * unwrapping for higher than SIR speeds. This driver assumes no change is
+ * necessary and announces support for all the way to 57600 bps. Although the
+ * package announces support for up to 4MBps, tests with a Sony Ericcson K300
+ * phone show corruption when receiving large frames at 115200 bps, the highest
+ * speed announced by the phone. However, transmission at 115200 bps is OK. Go
+ * figure. Since I don't know whether the phone or the dongle is at fault, max
+ * announced speed is 57600 bps until someone produces a device that can run
+ * at higher speeds with this dongle.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/usb.h>
+#include <linux/device.h>
+#include <linux/crc32.h>
+
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/crc.h>
+
+#define KS959_VENDOR_ID 0x07d0
+#define KS959_PRODUCT_ID 0x4959
+
+/* These are the currently known USB ids */
+static struct usb_device_id dongles[] = {
+ /* KingSun Co,Ltd IrDA/USB Bridge */
+ {USB_DEVICE(KS959_VENDOR_ID, KS959_PRODUCT_ID)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(usb, dongles);
+
+#define KINGSUN_MTT 0x07
+#define KINGSUN_REQ_RECV 0x01
+#define KINGSUN_REQ_SEND 0x09
+
+#define KINGSUN_RCV_FIFO_SIZE 2048 /* Max length we can receive */
+#define KINGSUN_SND_FIFO_SIZE 2048 /* Max packet we can send */
+#define KINGSUN_SND_PACKET_SIZE 256 /* Max packet dongle can handle */
+
+struct ks959_speedparams {
+ __le32 baudrate; /* baud rate, little endian */
+ __u8 flags;
+ __u8 reserved[3];
+} __attribute__ ((packed));
+
+#define KS_DATA_5_BITS 0x00
+#define KS_DATA_6_BITS 0x01
+#define KS_DATA_7_BITS 0x02
+#define KS_DATA_8_BITS 0x03
+
+#define KS_STOP_BITS_1 0x00
+#define KS_STOP_BITS_2 0x08
+
+#define KS_PAR_DISABLE 0x00
+#define KS_PAR_EVEN 0x10
+#define KS_PAR_ODD 0x30
+#define KS_RESET 0x80
+
+struct ks959_cb {
+ struct usb_device *usbdev; /* init: probe_irda */
+ struct net_device *netdev; /* network layer */
+ struct irlap_cb *irlap; /* The link layer we are binded to */
+ struct net_device_stats stats; /* network statistics */
+ struct qos_info qos;
+
+ struct usb_ctrlrequest *tx_setuprequest;
+ struct urb *tx_urb;
+ __u8 *tx_buf_clear;
+ unsigned int tx_buf_clear_used;
+ unsigned int tx_buf_clear_sent;
+ __u8 *tx_buf_xored;
+
+ struct usb_ctrlrequest *rx_setuprequest;
+ struct urb *rx_urb;
+ __u8 *rx_buf;
+ __u8 rx_variable_xormask;
+ iobuff_t rx_unwrap_buff;
+ struct timeval rx_time;
+
+ struct usb_ctrlrequest *speed_setuprequest;
+ struct urb *speed_urb;
+ struct ks959_speedparams speedparams;
+ unsigned int new_speed;
+
+ spinlock_t lock;
+ int receiving;
+};
+
+/* Procedure to perform the obfuscation/padding expected by the dongle
+ *
+ * buf_cleartext (IN) Cleartext version of the IrDA frame to transmit
+ * len_cleartext (IN) Length of the cleartext version of IrDA frame
+ * buf_xoredtext (OUT) Obfuscated version of frame built by proc
+ * len_maxbuf (OUT) Maximum space available at buf_xoredtext
+ *
+ * (return) length of obfuscated frame with padding
+ *
+ * If not enough space (as indicated by len_maxbuf vs. required padding),
+ * zero is returned
+ *
+ * The value of lookup_string is actually a required portion of the algorithm.
+ * Seems the designer of the dongle wanted to state who exactly is responsible
+ * for implementing obfuscation. Send your best (or other) wishes to him ]:-)
+ */
+static unsigned int obfuscate_tx_buffer(const __u8 * buf_cleartext,
+ unsigned int len_cleartext,
+ __u8 * buf_xoredtext,
+ unsigned int len_maxbuf)
+{
+ unsigned int len_xoredtext;
+
+ /* Calculate required length with padding, check for necessary space */
+ len_xoredtext = ((len_cleartext + 7) & ~0x7) + 0x10;
+ if (len_xoredtext <= len_maxbuf) {
+ static const __u8 lookup_string[] = "wangshuofei19710";
+ __u8 xor_mask;
+
+ /* Unlike the WinXP driver, we *do* clear out the padding */
+ memset(buf_xoredtext, 0, len_xoredtext);
+
+ xor_mask = lookup_string[(len_cleartext & 0x0f) ^ 0x06] ^ 0x55;
+
+ while (len_cleartext-- > 0) {
+ *buf_xoredtext++ = *buf_cleartext++ ^ xor_mask;
+ }
+ } else {
+ len_xoredtext = 0;
+ }
+ return len_xoredtext;
+}
+
+/* Callback transmission routine */
+static void ks959_speed_irq(struct urb *urb)
+{
+ /* unlink, shutdown, unplug, other nasties */
+ if (urb->status != 0) {
+ err("ks959_speed_irq: urb asynchronously failed - %d",
+ urb->status);
+ }
+}
+
+/* Send a control request to change speed of the dongle */
+static int ks959_change_speed(struct ks959_cb *kingsun, unsigned speed)
+{
+ static unsigned int supported_speeds[] = { 2400, 9600, 19200, 38400,
+ 57600, 115200, 576000, 1152000, 4000000, 0
+ };
+ int err;
+ unsigned int i;
+
+ if (kingsun->speed_setuprequest == NULL || kingsun->speed_urb == NULL)
+ return -ENOMEM;
+
+ /* Check that requested speed is among the supported ones */
+ for (i = 0; supported_speeds[i] && supported_speeds[i] != speed; i++) ;
+ if (supported_speeds[i] == 0)
+ return -EOPNOTSUPP;
+
+ memset(&(kingsun->speedparams), 0, sizeof(struct ks959_speedparams));
+ kingsun->speedparams.baudrate = cpu_to_le32(speed);
+ kingsun->speedparams.flags = KS_DATA_8_BITS;
+
+ /* speed_setuprequest pre-filled in ks959_probe */
+ usb_fill_control_urb(kingsun->speed_urb, kingsun->usbdev,
+ usb_sndctrlpipe(kingsun->usbdev, 0),
+ (unsigned char *)kingsun->speed_setuprequest,
+ &(kingsun->speedparams),
+ sizeof(struct ks959_speedparams), ks959_speed_irq,
+ kingsun);
+ kingsun->speed_urb->status = 0;
+ err = usb_submit_urb(kingsun->speed_urb, GFP_ATOMIC);
+
+ return err;
+}
+
+/* Submit one fragment of an IrDA frame to the dongle */
+static void ks959_send_irq(struct urb *urb);
+static int ks959_submit_tx_fragment(struct ks959_cb *kingsun)
+{
+ unsigned int padlen;
+ unsigned int wraplen;
+ int ret;
+
+ /* Check whether current plaintext can produce a padded buffer that fits
+ within the range handled by the dongle */
+ wraplen = (KINGSUN_SND_PACKET_SIZE & ~0x7) - 0x10;
+ if (wraplen > kingsun->tx_buf_clear_used)
+ wraplen = kingsun->tx_buf_clear_used;
+
+ /* Perform dongle obfuscation. Also remove the portion of the frame that
+ was just obfuscated and will now be sent to the dongle. */
+ padlen = obfuscate_tx_buffer(kingsun->tx_buf_clear, wraplen,
+ kingsun->tx_buf_xored,
+ KINGSUN_SND_PACKET_SIZE);
+
+ /* Calculate how much data can be transmitted in this urb */
+ kingsun->tx_setuprequest->wValue = cpu_to_le16(wraplen);
+ kingsun->tx_setuprequest->wLength = cpu_to_le16(padlen);
+ /* Rest of the fields were filled in ks959_probe */
+ usb_fill_control_urb(kingsun->tx_urb, kingsun->usbdev,
+ usb_sndctrlpipe(kingsun->usbdev, 0),
+ (unsigned char *)kingsun->tx_setuprequest,
+ kingsun->tx_buf_xored, padlen,
+ ks959_send_irq, kingsun);
+ kingsun->tx_urb->status = 0;
+ ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC);
+
+ /* Remember how much data was sent, in order to update at callback */
+ kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0;
+ return ret;
+}
+
+/* Callback transmission routine */
+static void ks959_send_irq(struct urb *urb)
+{
+ struct ks959_cb *kingsun = urb->context;
+ struct net_device *netdev = kingsun->netdev;
+ int ret = 0;
+
+ /* in process of stopping, just drop data */
+ if (!netif_running(kingsun->netdev)) {
+ err("ks959_send_irq: Network not running!");
+ return;
+ }
+
+ /* unlink, shutdown, unplug, other nasties */
+ if (urb->status != 0) {
+ err("ks959_send_irq: urb asynchronously failed - %d",
+ urb->status);
+ return;
+ }
+
+ if (kingsun->tx_buf_clear_used > 0) {
+ /* Update data remaining to be sent */
+ if (kingsun->tx_buf_clear_sent < kingsun->tx_buf_clear_used) {
+ memmove(kingsun->tx_buf_clear,
+ kingsun->tx_buf_clear +
+ kingsun->tx_buf_clear_sent,
+ kingsun->tx_buf_clear_used -
+ kingsun->tx_buf_clear_sent);
+ }
+ kingsun->tx_buf_clear_used -= kingsun->tx_buf_clear_sent;
+ kingsun->tx_buf_clear_sent = 0;
+
+ if (kingsun->tx_buf_clear_used > 0) {
+ /* There is more data to be sent */
+ if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) {
+ err("ks959_send_irq: failed tx_urb submit: %d",
+ ret);
+ switch (ret) {
+ case -ENODEV:
+ case -EPIPE:
+ break;
+ default:
+ kingsun->stats.tx_errors++;
+ netif_start_queue(netdev);
+ }
+ }
+ } else {
+ /* All data sent, send next speed && wake network queue */
+ if (kingsun->new_speed != -1 &&
+ cpu_to_le32(kingsun->new_speed) !=
+ kingsun->speedparams.baudrate)
+ ks959_change_speed(kingsun, kingsun->new_speed);
+
+ netif_wake_queue(netdev);
+ }
+ }
+}
+
+/*
+ * Called from net/core when new frame is available.
+ */
+static int ks959_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct ks959_cb *kingsun;
+ unsigned int wraplen;
+ int ret = 0;
+
+ if (skb == NULL || netdev == NULL)
+ return -EINVAL;
+
+ netif_stop_queue(netdev);
+
+ /* the IRDA wrapping routines don't deal with non linear skb */
+ SKB_LINEAR_ASSERT(skb);
+
+ kingsun = netdev_priv(netdev);
+
+ spin_lock(&kingsun->lock);
+ kingsun->new_speed = irda_get_next_speed(skb);
+
+ /* Append data to the end of whatever data remains to be transmitted */
+ wraplen =
+ async_wrap_skb(skb, kingsun->tx_buf_clear, KINGSUN_SND_FIFO_SIZE);
+ kingsun->tx_buf_clear_used = wraplen;
+
+ if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) {
+ err("ks959_hard_xmit: failed tx_urb submit: %d", ret);
+ switch (ret) {
+ case -ENODEV:
+ case -EPIPE:
+ break;
+ default:
+ kingsun->stats.tx_errors++;
+ netif_start_queue(netdev);
+ }
+ } else {
+ kingsun->stats.tx_packets++;
+ kingsun->stats.tx_bytes += skb->len;
+
+ }
+
+ dev_kfree_skb(skb);
+ spin_unlock(&kingsun->lock);
+
+ return ret;
+}
+
+/* Receive callback function */
+static void ks959_rcv_irq(struct urb *urb)
+{
+ struct ks959_cb *kingsun = urb->context;
+ int ret;
+
+ /* in process of stopping, just drop data */
+ if (!netif_running(kingsun->netdev)) {
+ kingsun->receiving = 0;
+ return;
+ }
+
+ /* unlink, shutdown, unplug, other nasties */
+ if (urb->status != 0) {
+ err("kingsun_rcv_irq: urb asynchronously failed - %d",
+ urb->status);
+ kingsun->receiving = 0;
+ return;
+ }
+
+ if (urb->actual_length > 0) {
+ __u8 *bytes = urb->transfer_buffer;
+ unsigned int i;
+
+ for (i = 0; i < urb->actual_length; i++) {
+ /* De-obfuscation implemented here: variable portion of
+ xormask is incremented, and then used with the encoded
+ byte for the XOR. The result of the operation is used
+ to unwrap the SIR frame. */
+ kingsun->rx_variable_xormask++;
+ bytes[i] =
+ bytes[i] ^ kingsun->rx_variable_xormask ^ 0x55u;
+
+ /* rx_variable_xormask doubles as an index counter so we
+ can skip the byte at 0xff (wrapped around to 0).
+ */
+ if (kingsun->rx_variable_xormask != 0) {
+ async_unwrap_char(kingsun->netdev,
+ &kingsun->stats,
+ &kingsun->rx_unwrap_buff,
+ bytes[i]);
+ }
+ }
+ kingsun->netdev->last_rx = jiffies;
+ do_gettimeofday(&kingsun->rx_time);
+ kingsun->receiving =
+ (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
+ }
+
+ /* This urb has already been filled in kingsun_net_open. Setup
+ packet must be re-filled, but it is assumed that urb keeps the
+ pointer to the initial setup packet, as well as the payload buffer.
+ Setup packet is already pre-filled at ks959_probe.
+ */
+ urb->status = 0;
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+/*
+ * Function kingsun_net_open (dev)
+ *
+ * Network device is taken up. Usually this is done by "ifconfig irda0 up"
+ */
+static int ks959_net_open(struct net_device *netdev)
+{
+ struct ks959_cb *kingsun = netdev_priv(netdev);
+ int err = -ENOMEM;
+ char hwname[16];
+
+ /* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */
+ kingsun->receiving = 0;
+
+ /* Initialize for SIR to copy data directly into skb. */
+ kingsun->rx_unwrap_buff.in_frame = FALSE;
+ kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
+ kingsun->rx_unwrap_buff.truesize = IRDA_SKB_MAX_MTU;
+ kingsun->rx_unwrap_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
+ if (!kingsun->rx_unwrap_buff.skb)
+ goto free_mem;
+
+ skb_reserve(kingsun->rx_unwrap_buff.skb, 1);
+ kingsun->rx_unwrap_buff.head = kingsun->rx_unwrap_buff.skb->data;
+ do_gettimeofday(&kingsun->rx_time);
+
+ kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!kingsun->rx_urb)
+ goto free_mem;
+
+ kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!kingsun->tx_urb)
+ goto free_mem;
+
+ kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!kingsun->speed_urb)
+ goto free_mem;
+
+ /* Initialize speed for dongle */
+ kingsun->new_speed = 9600;
+ err = ks959_change_speed(kingsun, 9600);
+ if (err < 0)
+ goto free_mem;
+
+ /*
+ * Now that everything should be initialized properly,
+ * Open new IrLAP layer instance to take care of us...
+ */
+ sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
+ kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
+ if (!kingsun->irlap) {
+ err("ks959-sir: irlap_open failed");
+ goto free_mem;
+ }
+
+ /* Start reception. Setup request already pre-filled in ks959_probe */
+ usb_fill_control_urb(kingsun->rx_urb, kingsun->usbdev,
+ usb_rcvctrlpipe(kingsun->usbdev, 0),
+ (unsigned char *)kingsun->rx_setuprequest,
+ kingsun->rx_buf, KINGSUN_RCV_FIFO_SIZE,
+ ks959_rcv_irq, kingsun);
+ kingsun->rx_urb->status = 0;
+ err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
+ if (err) {
+ err("ks959-sir: first urb-submit failed: %d", err);
+ goto close_irlap;
+ }
+
+ netif_start_queue(netdev);
+
+ /* Situation at this point:
+ - all work buffers allocated
+ - urbs allocated and ready to fill
+ - max rx packet known (in max_rx)
+ - unwrap state machine initialized, in state outside of any frame
+ - receive request in progress
+ - IrLAP layer started, about to hand over packets to send
+ */
+
+ return 0;
+
+ close_irlap:
+ irlap_close(kingsun->irlap);
+ free_mem:
+ usb_free_urb(kingsun->speed_urb);
+ kingsun->speed_urb = NULL;
+ usb_free_urb(kingsun->tx_urb);
+ kingsun->tx_urb = NULL;
+ usb_free_urb(kingsun->rx_urb);
+ kingsun->rx_urb = NULL;
+ if (kingsun->rx_unwrap_buff.skb) {
+ kfree_skb(kingsun->rx_unwrap_buff.skb);
+ kingsun->rx_unwrap_buff.skb = NULL;
+ kingsun->rx_unwrap_buff.head = NULL;
+ }
+ return err;
+}
+
+/*
+ * Function kingsun_net_close (kingsun)
+ *
+ * Network device is taken down. Usually this is done by
+ * "ifconfig irda0 down"
+ */
+static int ks959_net_close(struct net_device *netdev)
+{
+ struct ks959_cb *kingsun = netdev_priv(netdev);
+
+ /* Stop transmit processing */
+ netif_stop_queue(netdev);
+
+ /* Mop up receive && transmit urb's */
+ usb_kill_urb(kingsun->tx_urb);
+ usb_free_urb(kingsun->tx_urb);
+ kingsun->tx_urb = NULL;
+
+ usb_kill_urb(kingsun->speed_urb);
+ usb_free_urb(kingsun->speed_urb);
+ kingsun->speed_urb = NULL;
+
+ usb_kill_urb(kingsun->rx_urb);
+ usb_free_urb(kingsun->rx_urb);
+ kingsun->rx_urb = NULL;
+
+ kfree_skb(kingsun->rx_unwrap_buff.skb);
+ kingsun->rx_unwrap_buff.skb = NULL;
+ kingsun->rx_unwrap_buff.head = NULL;
+ kingsun->rx_unwrap_buff.in_frame = FALSE;
+ kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
+ kingsun->receiving = 0;
+
+ /* Stop and remove instance of IrLAP */
+ if (kingsun->irlap)
+ irlap_close(kingsun->irlap);
+
+ kingsun->irlap = NULL;
+
+ return 0;
+}
+
+/*
+ * IOCTLs : Extra out-of-band network commands...
+ */
+static int ks959_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
+{
+ struct if_irda_req *irq = (struct if_irda_req *)rq;
+ struct ks959_cb *kingsun = netdev_priv(netdev);
+ int ret = 0;
+
+ switch (cmd) {
+ case SIOCSBANDWIDTH: /* Set bandwidth */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ /* Check if the device is still there */
+ if (netif_device_present(kingsun->netdev))
+ return ks959_change_speed(kingsun, irq->ifr_baudrate);
+ break;
+
+ case SIOCSMEDIABUSY: /* Set media busy */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ /* Check if the IrDA stack is still there */
+ if (netif_running(kingsun->netdev))
+ irda_device_set_media_busy(kingsun->netdev, TRUE);
+ break;
+
+ case SIOCGRECEIVING:
+ /* Only approximately true */
+ irq->ifr_receiving = kingsun->receiving;
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+/*
+ * Get device stats (for /proc/net/dev and ifconfig)
+ */
+static struct net_device_stats *ks959_net_get_stats(struct net_device *netdev)
+{
+ struct ks959_cb *kingsun = netdev_priv(netdev);
+ return &kingsun->stats;
+}
+
+/*
+ * This routine is called by the USB subsystem for each new device
+ * in the system. We need to check if the device is ours, and in
+ * this case start handling it.
+ */
+static int ks959_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct ks959_cb *kingsun = NULL;
+ struct net_device *net = NULL;
+ int ret = -ENOMEM;
+
+ /* Allocate network device container. */
+ net = alloc_irdadev(sizeof(*kingsun));
+ if (!net)
+ goto err_out1;
+
+ SET_MODULE_OWNER(net);
+ SET_NETDEV_DEV(net, &intf->dev);
+ kingsun = netdev_priv(net);
+ kingsun->netdev = net;
+ kingsun->usbdev = dev;
+ kingsun->irlap = NULL;
+ kingsun->tx_setuprequest = NULL;
+ kingsun->tx_urb = NULL;
+ kingsun->tx_buf_clear = NULL;
+ kingsun->tx_buf_xored = NULL;
+ kingsun->tx_buf_clear_used = 0;
+ kingsun->tx_buf_clear_sent = 0;
+
+ kingsun->rx_setuprequest = NULL;
+ kingsun->rx_urb = NULL;
+ kingsun->rx_buf = NULL;
+ kingsun->rx_variable_xormask = 0;
+ kingsun->rx_unwrap_buff.in_frame = FALSE;
+ kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
+ kingsun->rx_unwrap_buff.skb = NULL;
+ kingsun->receiving = 0;
+ spin_lock_init(&kingsun->lock);
+
+ kingsun->speed_setuprequest = NULL;
+ kingsun->speed_urb = NULL;
+ kingsun->speedparams.baudrate = 0;
+
+ /* Allocate input buffer */
+ kingsun->rx_buf = kmalloc(KINGSUN_RCV_FIFO_SIZE, GFP_KERNEL);
+ if (!kingsun->rx_buf)
+ goto free_mem;
+
+ /* Allocate input setup packet */
+ kingsun->rx_setuprequest =
+ kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
+ if (!kingsun->rx_setuprequest)
+ goto free_mem;
+ kingsun->rx_setuprequest->bRequestType =
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ kingsun->rx_setuprequest->bRequest = KINGSUN_REQ_RECV;
+ kingsun->rx_setuprequest->wValue = cpu_to_le16(0x0200);
+ kingsun->rx_setuprequest->wIndex = 0;
+ kingsun->rx_setuprequest->wLength = cpu_to_le16(KINGSUN_RCV_FIFO_SIZE);
+
+ /* Allocate output buffer */
+ kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL);
+ if (!kingsun->tx_buf_clear)
+ goto free_mem;
+ kingsun->tx_buf_xored = kmalloc(KINGSUN_SND_PACKET_SIZE, GFP_KERNEL);
+ if (!kingsun->tx_buf_xored)
+ goto free_mem;
+
+ /* Allocate and initialize output setup packet */
+ kingsun->tx_setuprequest =
+ kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
+ if (!kingsun->tx_setuprequest)
+ goto free_mem;
+ kingsun->tx_setuprequest->bRequestType =
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ kingsun->tx_setuprequest->bRequest = KINGSUN_REQ_SEND;
+ kingsun->tx_setuprequest->wValue = 0;
+ kingsun->tx_setuprequest->wIndex = 0;
+ kingsun->tx_setuprequest->wLength = 0;
+
+ /* Allocate and initialize speed setup packet */
+ kingsun->speed_setuprequest =
+ kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
+ if (!kingsun->speed_setuprequest)
+ goto free_mem;
+ kingsun->speed_setuprequest->bRequestType =
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND;
+ kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200);
+ kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001);
+ kingsun->speed_setuprequest->wLength =
+ cpu_to_le16(sizeof(struct ks959_speedparams));
+
+ printk(KERN_INFO "KingSun KS-959 IRDA/USB found at address %d, "
+ "Vendor: %x, Product: %x\n",
+ dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
+
+ /* Initialize QoS for this device */
+ irda_init_max_qos_capabilies(&kingsun->qos);
+
+ /* Baud rates known to be supported. Please uncomment if devices (other
+ than a SonyEriccson K300 phone) can be shown to support higher speed
+ with this dongle.
+ */
+ kingsun->qos.baud_rate.bits =
+ IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600;
+ kingsun->qos.min_turn_time.bits &= KINGSUN_MTT;
+ irda_qos_bits_to_value(&kingsun->qos);
+
+ /* Override the network functions we need to use */
+ net->hard_start_xmit = ks959_hard_xmit;
+ net->open = ks959_net_open;
+ net->stop = ks959_net_close;
+ net->get_stats = ks959_net_get_stats;
+ net->do_ioctl = ks959_net_ioctl;
+
+ ret = register_netdev(net);
+ if (ret != 0)
+ goto free_mem;
+
+ info("IrDA: Registered KingSun KS-959 device %s", net->name);
+
+ usb_set_intfdata(intf, kingsun);
+
+ /* Situation at this point:
+ - all work buffers allocated
+ - setup requests pre-filled
+ - urbs not allocated, set to NULL
+ - max rx packet known (is KINGSUN_FIFO_SIZE)
+ - unwrap state machine (partially) initialized, but skb == NULL
+ */
+
+ return 0;
+
+ free_mem:
+ kfree(kingsun->speed_setuprequest);
+ kfree(kingsun->tx_setuprequest);
+ kfree(kingsun->tx_buf_xored);
+ kfree(kingsun->tx_buf_clear);
+ kfree(kingsun->rx_setuprequest);
+ kfree(kingsun->rx_buf);
+ free_netdev(net);
+ err_out1:
+ return ret;
+}
+
+/*
+ * The current device is removed, the USB layer tell us to shut it down...
+ */
+static void ks959_disconnect(struct usb_interface *intf)
+{
+ struct ks959_cb *kingsun = usb_get_intfdata(intf);
+
+ if (!kingsun)
+ return;
+
+ unregister_netdev(kingsun->netdev);
+
+ /* Mop up receive && transmit urb's */
+ if (kingsun->speed_urb != NULL) {
+ usb_kill_urb(kingsun->speed_urb);
+ usb_free_urb(kingsun->speed_urb);
+ kingsun->speed_urb = NULL;
+ }
+ if (kingsun->tx_urb != NULL) {
+ usb_kill_urb(kingsun->tx_urb);
+ usb_free_urb(kingsun->tx_urb);
+ kingsun->tx_urb = NULL;
+ }
+ if (kingsun->rx_urb != NULL) {
+ usb_kill_urb(kingsun->rx_urb);
+ usb_free_urb(kingsun->rx_urb);
+ kingsun->rx_urb = NULL;
+ }
+
+ kfree(kingsun->speed_setuprequest);
+ kfree(kingsun->tx_setuprequest);
+ kfree(kingsun->tx_buf_xored);
+ kfree(kingsun->tx_buf_clear);
+ kfree(kingsun->rx_setuprequest);
+ kfree(kingsun->rx_buf);
+ free_netdev(kingsun->netdev);
+
+ usb_set_intfdata(intf, NULL);
+}
+
+#ifdef CONFIG_PM
+/* USB suspend, so power off the transmitter/receiver */
+static int ks959_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct ks959_cb *kingsun = usb_get_intfdata(intf);
+
+ netif_device_detach(kingsun->netdev);
+ if (kingsun->speed_urb != NULL)
+ usb_kill_urb(kingsun->speed_urb);
+ if (kingsun->tx_urb != NULL)
+ usb_kill_urb(kingsun->tx_urb);
+ if (kingsun->rx_urb != NULL)
+ usb_kill_urb(kingsun->rx_urb);
+ return 0;
+}
+
+/* Coming out of suspend, so reset hardware */
+static int ks959_resume(struct usb_interface *intf)
+{
+ struct ks959_cb *kingsun = usb_get_intfdata(intf);
+
+ if (kingsun->rx_urb != NULL) {
+ /* Setup request already filled in ks959_probe */
+ usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
+ }
+ netif_device_attach(kingsun->netdev);
+
+ return 0;
+}
+#endif
+
+/*
+ * USB device callbacks
+ */
+static struct usb_driver irda_driver = {
+ .name = "ks959-sir",
+ .probe = ks959_probe,
+ .disconnect = ks959_disconnect,
+ .id_table = dongles,
+#ifdef CONFIG_PM
+ .suspend = ks959_suspend,
+ .resume = ks959_resume,
+#endif
+};
+
+/*
+ * Module insertion
+ */
+static int __init ks959_init(void)
+{
+ return usb_register(&irda_driver);
+}
+
+module_init(ks959_init);
+
+/*
+ * Module removal
+ */
+static void __exit ks959_cleanup(void)
+{
+ /* Deregister the driver and remove all pending instances */
+ usb_deregister(&irda_driver);
+}
+
+module_exit(ks959_cleanup);
+
+MODULE_AUTHOR("Alex Villacís Lasso <a_villacis-5itmuRygkZmgSpxsJD1C4w@public.gmane.org>");
+MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun KS-959");
+MODULE_LICENSE("GPL");
Index: net-2.6.24-quilt/drivers/net/irda/Makefile
===================================================================
--- net-2.6.24-quilt.orig/drivers/net/irda/Makefile 2007-08-25 02:42:20.000000000 +0300
+++ net-2.6.24-quilt/drivers/net/irda/Makefile 2007-08-25 02:54:09.000000000 +0300
@@ -48,6 +48,7 @@
obj-$(CONFIG_EP7211_DONGLE) += ep7211-sir.o
obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o
obj-$(CONFIG_KSDAZZLE_DONGLE) += ksdazzle-sir.o
+obj-$(CONFIG_KS959_DONGLE) += ks959-sir.o
# The SIR helper module
sir-dev-objs := sir_dev.o sir_dongle.o
--
[-- Attachment #2: Type: text/plain, Size: 315 bytes --]
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
[-- Attachment #3: Type: text/plain, Size: 188 bytes --]
_______________________________________________
irda-users mailing list
irda-users-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
http://lists.sourceforge.net/lists/listinfo/irda-users
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox