Netdev List
 help / color / mirror / Atom feed
* [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: jie.yang @ 2009-09-16  7:23 UTC (permalink / raw)
  To: davem; +Cc: miles.lane, chris.snook, jcliburn, netdev, linux-kernel, Jie Yang

[   25.059969] WARNING: at lib/dma-debug.c:816 check_unmap+0x383/0x55c()
[   25.059976] Hardware name: 1000HE
[   25.059984] ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
     memory with wrong function [device address=0x0000000036b92802]
     [size=90 bytes] [mapped as single] [unmapped as page]

use the wrong API when free dma. So when map dma use a flag to 
demostrate whether it is 'pci_map_single' or 'pci_map_page'. When free 
the dma, check the flags to select the right APIs('pci_unmap_single' or 'pci_unmap_page').

set the flags type to u16  instead of unsigned long  on David's comments.

Signed-off-by: Jie Yang <jie.yang@atheros.com>
---

diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/atl1e/atl1e.h
index ba48220..490d3b3 100644
--- a/drivers/net/atl1e/atl1e.h
+++ b/drivers/net/atl1e/atl1e.h
@@ -377,10 +377,19 @@ struct atl1e_hw {
  */
 struct atl1e_tx_buffer {
    struct sk_buff *skb;
+   u16 flags;
+#define ATL1E_TX_PCIMAP_SINGLE     0x0001
+#define ATL1E_TX_PCIMAP_PAGE       0x0002
+#define ATL1E_TX_PCIMAP_TYPE_MASK  0x0003
    u16 length;
    dma_addr_t dma;
 };
 
+#define ATL1E_SET_PCIMAP_TYPE(tx_buff, type) do {      \
+   ((tx_buff)->flags) &= ~ATL1E_TX_PCIMAP_TYPE_MASK;   \
+   ((tx_buff)->flags) |= (type);               \
+   } while (0)
+
 struct atl1e_rx_page {
    dma_addr_t  dma;    /* receive rage DMA address */
    u8      *addr;   /* receive rage virtual address */
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index 69b830f..955da73 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -635,7 +635,11 @@ static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter)
    for (index = 0; index < ring_count; index++) {
        tx_buffer = &tx_ring->tx_buffer[index];
        if (tx_buffer->dma) {
-           pci_unmap_page(pdev, tx_buffer->dma,
+           if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
+               pci_unmap_single(pdev, tx_buffer->dma,
+                   tx_buffer->length, PCI_DMA_TODEVICE);
+           else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
+               pci_unmap_page(pdev, tx_buffer->dma,
                    tx_buffer->length, PCI_DMA_TODEVICE);
            tx_buffer->dma = 0;
        }
@@ -1220,7 +1224,11 @@ static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter)
    while (next_to_clean != hw_next_to_clean) {
        tx_buffer = &tx_ring->tx_buffer[next_to_clean];
        if (tx_buffer->dma) {
-           pci_unmap_page(adapter->pdev, tx_buffer->dma,
+           if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
+               pci_unmap_single(adapter->pdev, tx_buffer->dma,
+                   tx_buffer->length, PCI_DMA_TODEVICE);
+           else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
+               pci_unmap_page(adapter->pdev, tx_buffer->dma,
                    tx_buffer->length, PCI_DMA_TODEVICE);
            tx_buffer->dma = 0;
        }
@@ -1741,6 +1749,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
        tx_buffer->length = map_len;
        tx_buffer->dma = pci_map_single(adapter->pdev,
                    skb->data, hdr_len, PCI_DMA_TODEVICE);
+       ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
        mapped_len += map_len;
        use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
        use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
@@ -1766,6 +1775,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
        tx_buffer->dma =
            pci_map_single(adapter->pdev, skb->data + mapped_len,
                    map_len, PCI_DMA_TODEVICE);
+       ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
        mapped_len  += map_len;
        use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
        use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
@@ -1801,6 +1811,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
                        (i * MAX_TX_BUF_LEN),
                        tx_buffer->length,
                        PCI_DMA_TODEVICE);
+           ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE);
            use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
            use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
                    ((cpu_to_le32(tx_buffer->length) &

^ permalink raw reply related

* [PATCH] cpmac: fix compilation errors against undeclared BUS_ID_SIZE
From: Florian Fainelli @ 2009-09-16  7:44 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Ralf Baechle, linux-mips

Hi David,

This is relevant for 2.6.32-rc0, thanks !
--
From: Florian Fainelli <florian@openwrt.org>
Subject: [PATCH] cpmac: fix compilation errors against undeclared BUS_ID_SIZE

With the removal of BUS_ID_SIZE, cpmac was not fully
converted to use MII_BUS_ID_SIZE as it ought to. This
patch fixes the following cpmac build failure:
 CC      drivers/net/cpmac.o
drivers/net/cpmac.c: In function 'cpmac_start_xmit':
drivers/net/cpmac.c:563: warning: comparison of distinct pointer types lacks a cast
drivers/net/cpmac.c: In function 'cpmac_probe':
drivers/net/cpmac.c:1112: error: 'BUS_ID_SIZE' undeclared (first use in this function)
drivers/net/cpmac.c:1112: error: (Each undeclared identifier is reported only once
drivers/net/cpmac.c:1112: error: for each function it appears in.)

Reported-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index 3e3fab8..61f9da2 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -1109,7 +1109,7 @@ static int external_switch;
 static int __devinit cpmac_probe(struct platform_device *pdev)
 {
 	int rc, phy_id;
-	char mdio_bus_id[BUS_ID_SIZE];
+	char mdio_bus_id[MII_BUS_ID_SIZE];
 	struct resource *mem;
 	struct cpmac_priv *priv;
 	struct net_device *dev;
@@ -1118,7 +1118,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
 	pdata = pdev->dev.platform_data;
 
 	if (external_switch || dumb_switch) {
-		strncpy(mdio_bus_id, "0", BUS_ID_SIZE); /* fixed phys bus */
+		strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */
 		phy_id = pdev->id;
 	} else {
 		for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
@@ -1126,7 +1126,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
 				continue;
 			if (!cpmac_mii->phy_map[phy_id])
 				continue;
-			strncpy(mdio_bus_id, cpmac_mii->id, BUS_ID_SIZE);
+			strncpy(mdio_bus_id, cpmac_mii->id, MII_BUS_ID_SIZE);
 			break;
 		}
 	}
@@ -1167,7 +1167,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
 	priv->msg_enable = netif_msg_init(debug_level, 0xff);
 	memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
 
-	snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
+	snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
 
 	priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0,
 						PHY_INTERFACE_MODE_MII);



^ permalink raw reply related

* Re: [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: David Miller @ 2009-09-16  7:44 UTC (permalink / raw)
  To: jie.yang; +Cc: miles.lane, chris.snook, jcliburn, netdev, linux-kernel
In-Reply-To: <12530857843502-git-send-email-jie.yang@atheros.com>

From: <jie.yang@atheros.com>
Date: Wed, 16 Sep 2009 15:23:04 +0800

> [   25.059969] WARNING: at lib/dma-debug.c:816 check_unmap+0x383/0x55c()
> [   25.059976] Hardware name: 1000HE
> [   25.059984] ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
>      memory with wrong function [device address=0x0000000036b92802]
>      [size=90 bytes] [mapped as single] [unmapped as page]
> 
> use the wrong API when free dma. So when map dma use a flag to 
> demostrate whether it is 'pci_map_single' or 'pci_map_page'. When free 
> the dma, check the flags to select the right APIs('pci_unmap_single' or 'pci_unmap_page').
> 
> set the flags type to u16  instead of unsigned long  on David's comments.
> 
> Signed-off-by: Jie Yang <jie.yang@atheros.com>

Your email client has corrupted this patch (turning tab characters
into spaces, etc.) making it unusable.

^ permalink raw reply

* Re: fanotify as syscalls
From: Jamie Lokier @ 2009-09-16  7:52 UTC (permalink / raw)
  To: Eric Paris
  Cc: Linus Torvalds, Evgeniy Polyakov, David Miller, linux-kernel,
	linux-fsdevel, netdev, viro, alan, hch
In-Reply-To: <1253064391.5213.37.camel@dhcp231-106.rdu.redhat.com>

Eric Paris wrote:
> On Tue, 2009-09-15 at 16:49 -0700, Linus Torvalds wrote:
> > And btw, I still want to know what's so wonderful about fanotify that we 
> > would actually want yet-another-filesystem-notification-interface. So I'm 
> > not sayying that I'll take a system call interface.
> 
> The real thing that fanotify provides is an open fd with the event
> rather than some arbitrary 'watch descriptor' that userspace must
> somehow magically map back to data on disk.  This means that it could be
> used to provide subtree notification, which inotify is completely
> incapable of doing.

That's a bit of a spurious claim.

- fanotify does not provide subtree notification in it's
  present form.  When it is extended to do that, why wouldn't
  inotify be as well?  That's an fsnotify feature, common to both.

- fanotify does not provide notification at all for some events that
  you get with inotify.  It is not a superset, so you can't use
  fanotify to provide a subtree-capable equivalent to inotify.  What
  a mess when you need the combination of both features!

- fanotify requires you call readlink(/proc/fd/N) for every event to
  get the path.  It's not a particularly efficient way to get it,
  especially when an apps wants to know if it's something in it's
  region of interest but doesn't care about the actual path.
  When an apps knows it needs the map back to to path, why make it
  slow to get it?  That "extensible data format" is being
  underutilised...

- fanotify's descriptor may be race-prone as a way to get the subtree
  used for access, because any of the parent directories could have
  moved and even been deleted before the app calls
  readlink(/proc/fd/N).  I don't know if a _reliable_ way to track
  changes in a subtree can be built on it.  Maybe it can but it
  appears this hasn't been analysed.  It depends on
  readlink(/proc/fd/N)'s behaviour when the dentry's have been
  changed, among other things.

- Does the descriptor cause umount to fail when user does "do some
  stuff in baz; umount baz", or does it serialise nicely?  That's one
  of inotify's nice features - it doesn't cause umounts to fail.

> And it can be used to provide system wide notification.  We all know
> who wants that.

People who want to break out of chroot/namespace jails using the
conveniently provided open file descriptor? :-)

Seriously, what does system-wide fanotify do when run from a
chroot/namespace/cgroup, and a file outside them is accessed?

If the event is delivered with file desciptor, that's a security hole.
If it's not delivered, that sounds like working subtree support?

I'd expect anti-malware to want to be run inside VMs quite often...

Note that there's no such thing as "the real system root" any more.

> It provides an extensible data format which allows growth impossible in
> inotify.  I don't know if anyone remember the inotify patches which
> wanted to overload the inotify cookie field for some other information,
> but inotify information extension is not reasonable or backwards
> compatible.

I agree with this (although that's what flags are for -- see clone).

I don't have a problem with the next interface being fanotify (despite
arguing a lot); I just want to see the next one being useful for the
things I would otherwise be proposing my own yet-another-interface
for.  So we don't need a fourth one soon after the third due to
easily foreseen limitations.

> I've got private commitments for two very large anti malware companies,
> both of which unprotect and hack syscall tables in their customer's
> kernels, that they would like to move to an fanotify interface.  Both
> Red Hat and Suse have expressed interest in these patches and have
> contributed to the patch set.
> 
> The patch set is actually rather small (entire set of about 20 patches
> is 1800 lines) as it builds on the fsnotify work already in 2.6.31 to
> reuse code from inotify rather than reimplement the same things over and
> over (like we previously had with inotify and dnotify)

I don't have any problem with either of these, and _fs_notify
generally seems like an improvement.  I don't have a problem with
fanotify either.  For what it does, it's ok.

> Don't know what else to say.....

Answer questions about use-cases that you're not interested in?  Why
block them?  What about Evigny's request for an event without an open
fd - because he needs the pid information (inotify doesn't provide)
but not the fd?

Sorry to be so harsh.  I'm really trying to make sure we don't repeat
the mistakes of dnotify and inotify, and end up with a third interface
which also is too restrictive (because it's good enough for your
anti-malware and HSM customers) so that a fourth interface will be
needed soon after.

I'd like to be able to use it from some applications to accelerate
userspace caching of things (faster Make, faster Samba) without
penalising all other applications touching unrelated parts of the
filesystem.  The attitude "you can live with 10% slowdown" worries me.
I'm sure that can be fixed with a bit of care.

If the intention is to maintain fanotify and inotify side-by-side for
different uses (because fanotify returns open descriptors and blocks
the accessing process until acked), that's ok with me.  It makes
sense.  But then it's messy that neither offers a superset of the
other regarding which files and events are tracked.

If it's right that inotify has no room for extensibility (I'm not sure
about this), than it appears we already made a mess with dnotify and
inotify, so it would be a shame to repeat the same mistakes again.
Let's get the next one right, even it takes a bit longer, ok?

-- Jamie

^ permalink raw reply

* Re: [PATCHv5 3/3] vhost_net: a kernel-level virtio server
From: Avi Kivity @ 2009-09-16  8:23 UTC (permalink / raw)
  To: Gregory Haskins
  Cc: Michael S. Tsirkin, Ira W. Snyder, netdev, virtualization, kvm,
	linux-kernel, mingo, linux-mm, akpm, hpa, Rusty Russell, s.hetze,
	alacrityvm-devel
In-Reply-To: <4AAFF437.7060100@gmail.com>

On 09/15/2009 11:08 PM, Gregory Haskins wrote:
>
>> There's virtio-console, virtio-blk etc.  None of these have kernel-mode
>> servers, but these could be implemented if/when needed.
>>      
> IIUC, Ira already needs at least ethernet and console capability.
>
>    

He's welcome to pick up the necessary code from qemu.

>>> b) what do you suppose this protocol to aggregate the connections would
>>> look like? (hint: this is what a vbus-connector does).
>>>
>>>        
>> You mean multilink?  You expose the device as a multiqueue.
>>      
> No, what I mean is how do you surface multiple ethernet and consoles to
> the guests?  For Ira's case, I think he needs at minimum at least one of
> each, and he mentioned possibly having two unique ethernets at one point.
>    

You instantiate multiple vhost-nets.  Multiple ethernet NICs is a 
supported configuration for kvm.

> His slave boards surface themselves as PCI devices to the x86
> host.  So how do you use that to make multiple vhost-based devices (say
> two virtio-nets, and a virtio-console) communicate across the transport?
>    

I don't really see the difference between 1 and N here.

> There are multiple ways to do this, but what I am saying is that
> whatever is conceived will start to look eerily like a vbus-connector,
> since this is one of its primary purposes ;)
>    

I'm not sure if you're talking about the configuration interface or data 
path here.

>>> c) how do you manage the configuration, especially on a per-board basis?
>>>
>>>        
>> pci (for kvm/x86).
>>      
> Ok, for kvm understood (and I would also add "qemu" to that mix).  But
> we are talking about vhost's application in a non-kvm environment here,
> right?.
>
> So if the vhost-X devices are in the "guest",

They aren't in the "guest".  The best way to look at it is

- a device side, with a dma engine: vhost-net
- a driver side, only accessing its own memory: virtio-net

Given that Ira's config has the dma engine in the ppc boards, that's 
where vhost-net would live (the ppc boards acting as NICs to the x86 
board, essentially).

> and the x86 board is just
> a slave...How do you tell each ppc board how many devices and what
> config (e.g. MACs, etc) to instantiate?  Do you assume that they should
> all be symmetric and based on positional (e.g. slot) data?  What if you
> want asymmetric configurations (if not here, perhaps in a different
> environment)?
>    

I have no idea, that's for Ira to solve.  If he could fake the PCI 
config space as seen by the x86 board, he would just show the normal pci 
config and use virtio-pci (multiple channels would show up as a 
multifunction device).  Given he can't, he needs to tunnel the virtio 
config space some other way.

>> Yes.  virtio is really virtualization oriented.
>>      
> I would say that its vhost in particular that is virtualization
> oriented.  virtio, as a concept, generally should work in physical
> systems, if perhaps with some minor modifications.  The biggest "limit"
> is having "virt" in its name ;)
>    

Let me rephrase.  The virtio developers are virtualization oriented.  If 
it works for non-virt applications, that's good, but not a design goal.

-- 
error compiling committee.c: too many arguments to function

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* [GIT]: Networking
From: David Miller @ 2009-09-16  8:42 UTC (permalink / raw)
  To: torvalds; +Cc: akpm, netdev, linux-kernel


1) The idea to use ->close() and then a ->open() to refresh multicast
   addresses in the bonding driver was a bad idea and breaks a bunch
   of stuff.  Better scheme from Moni Shoua.

2) Some TCP code still assuming ssthresh was a u16, oops.  Fix from
   Ilpo Järvinen.

3) RXRPC updates from David Howells.

4) genetlink table locking busted with netns, fix from Johannes Berg.

5) Several fixes for multiq packet scheduler fallout from Jarek Poplawski.

6) can receives packets in wrong context eliciting warnings from
   local_softirq_pending(), fix from Oliver Hartkopp.

7) TCP MD5 code has preempt level imbalance, fix from Robert Varga.

8) SKY2 bug fixes from Stephen Hemminger.

9) Alexey Dobriyan is constificated, he should probably see a doctor
   about that. :-)

There is a pktgen OOPS regression reported by Ingo, someone replied
with a patch for him to test out so we'll monitor that very closely.

There are some wireless bugs that have been reported with some patches
in the queue as well.  Hopefully John Linville will review those and
get them to me soon.

Please pull, thanks a lot!

The following changes since commit 4142e0d1def2c0176c27fd2e810243045a62eb6d:
  Linus Torvalds (1):
        Merge branch 'osync_cleanup' of git://git.kernel.org/.../jack/linux-fs-2.6

are available in the git repository at:

  master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git master

Alexander Duyck (2):
      igb: reset sgmii phy at start of init
      igb: do not allow phy sw reset code to make calls to null pointers

Alexey Dobriyan (3):
      net: constify struct net_protocol
      net: constify struct inet6_protocol
      net: constify remaining proto_ops

David Howells (5):
      RxRPC: Declare the security index constants symbolically
      RxRPC: Allow key payloads to be passed in XDR form
      RxRPC: Allow RxRPC keys to be read
      RxRPC: Parse security index 5 keys (Kerberos 5)
      RxRPC: Use uX/sX rather than uintX_t/intX_t types

Eric Dumazet (1):
      net: kmemcheck annotation in struct socket

Gerrit Renker (1):
      net-next-2.6 [PATCH 1/1] dccp: ccids whitespace-cleanup / CodingStyle

Ilpo Järvinen (1):
      tcp: fix ssthresh u16 leftover

Jarek Poplawski (3):
      pkt_sched: Fix qdisc_graft WRT ingress qdisc
      pkt_sched: Fix tx queue selection in tc_modify_qdisc
      pkt_sched: Fix qdisc_create on stab error handling

Johannes Berg (1):
      genetlink: fix netns vs. netlink table locking

Ken Kawasaki (1):
      pcnet_cs: add cis of Linksys multifunction pcmcia card

Mark Smith (1):
      Have atalk_route_packet() return NET_RX_SUCCESS not NET_XMIT_SUCCESS

Michael Hennerich (1):
      netdev: smc91x: drop Blackfin cruft

Moni Shoua (1):
      bonding: remap muticast addresses without using dev_close() and dev_open()

Oliver Hartkopp (1):
      can: fix NOHZ local_softirq_pending 08 warning

Peter P Waskiewicz Jr (3):
      ixgbe: Properly disable packet split per-ring when globally disabled
      ixgbe: Add support for 82599-based CX4 adapters
      ixgbe: Create separate media type for CX4 adapters

Robert Varga (1):
      tcp: fix CONFIG_TCP_MD5SIG + CONFIG_PREEMPT timer BUG()

Rémi Denis-Courmont (2):
      Phonet: Netlink event for autoconfigured addresses
      cdc-phonet: remove noisy debug statement

Stephen Hemminger (2):
      sky2: transmit ring accounting
      sky2: Make sure both ports initialize correctly

Vitaliy Gusev (1):
      mlx4: Fix access to freed memory

 drivers/net/bonding/bond_main.c     |    9 +-
 drivers/net/can/vcan.c              |    2 +-
 drivers/net/igb/e1000_82575.c       |  198 ++++----
 drivers/net/igb/e1000_82575.h       |    2 +-
 drivers/net/igb/e1000_defines.h     |    2 +-
 drivers/net/igb/e1000_phy.c         |    5 +-
 drivers/net/igb/igb_main.c          |    2 +-
 drivers/net/ixgbe/ixgbe_82598.c     |    6 +-
 drivers/net/ixgbe/ixgbe_82599.c     |    3 +
 drivers/net/ixgbe/ixgbe_main.c      |    4 +
 drivers/net/ixgbe/ixgbe_type.h      |    2 +
 drivers/net/mlx4/catas.c            |   11 +-
 drivers/net/pcmcia/pcnet_cs.c       |   10 +-
 drivers/net/pppol2tp.c              |    4 +-
 drivers/net/sky2.c                  |   24 +-
 drivers/net/smc91x.h                |   28 --
 drivers/net/usb/cdc-phonet.c        |    1 -
 drivers/serial/serial_cs.c          |   14 +-
 firmware/Makefile                   |    3 +-
 firmware/WHENCE                     |   12 +
 firmware/cis/MT5634ZLX.cis.ihex     |   11 +
 firmware/cis/PCMLM28.cis.ihex       |   18 +
 firmware/cis/RS-COM-2P.cis.ihex     |   10 +
 include/keys/rxrpc-type.h           |  107 ++++
 include/linux/igmp.h                |    2 +
 include/linux/net.h                 |    5 +
 include/linux/netdevice.h           |    3 +-
 include/linux/netlink.h             |    4 +
 include/linux/notifier.h            |    2 +
 include/linux/rxrpc.h               |    7 +
 include/net/addrconf.h              |    2 +
 include/net/protocol.h              |   13 +-
 include/net/sch_generic.h           |    2 +-
 include/net/tcp.h                   |    7 +
 net/appletalk/ddp.c                 |    2 +-
 net/can/af_can.c                    |    4 +-
 net/core/dev.c                      |    4 +-
 net/dccp/ccids/Kconfig              |    6 +-
 net/dccp/ccids/ccid2.c              |    2 -
 net/dccp/ccids/ccid2.h              |    8 +-
 net/dccp/ccids/ccid3.c              |    5 +-
 net/dccp/ccids/ccid3.h              |   50 +-
 net/dccp/ccids/lib/loss_interval.c  |    7 +-
 net/dccp/ccids/lib/loss_interval.h  |    2 -
 net/dccp/ccids/lib/packet_history.c |    4 +-
 net/dccp/ccids/lib/packet_history.h |    1 -
 net/dccp/ccids/lib/tfrc.h           |    4 +-
 net/dccp/ccids/lib/tfrc_equation.c  |   26 +-
 net/dccp/ipv4.c                     |    2 +-
 net/dccp/ipv6.c                     |    4 +-
 net/ipv4/af_inet.c                  |   18 +-
 net/ipv4/ah4.c                      |    2 +-
 net/ipv4/devinet.c                  |    6 +
 net/ipv4/esp4.c                     |    2 +-
 net/ipv4/icmp.c                     |    2 +-
 net/ipv4/igmp.c                     |   22 +
 net/ipv4/ip_gre.c                   |    2 +-
 net/ipv4/ip_input.c                 |    2 +-
 net/ipv4/ipcomp.c                   |    2 +-
 net/ipv4/ipmr.c                     |    6 +-
 net/ipv4/protocol.c                 |    6 +-
 net/ipv4/tcp.c                      |    2 +-
 net/ipv4/tcp_input.c                |    2 +-
 net/ipv4/tcp_ipv4.c                 |    4 +-
 net/ipv4/tcp_minisocks.c            |    4 +-
 net/ipv4/tunnel4.c                  |    4 +-
 net/ipv4/udplite.c                  |    2 +-
 net/ipv6/addrconf.c                 |   19 +
 net/ipv6/af_inet6.c                 |   10 +-
 net/ipv6/ah6.c                      |    2 +-
 net/ipv6/esp6.c                     |    2 +-
 net/ipv6/exthdrs.c                  |    6 +-
 net/ipv6/icmp.c                     |    4 +-
 net/ipv6/ip6_input.c                |    2 +-
 net/ipv6/ip6mr.c                    |    6 +-
 net/ipv6/ipcomp6.c                  |    2 +-
 net/ipv6/mcast.c                    |   19 +
 net/ipv6/protocol.c                 |    6 +-
 net/ipv6/reassembly.c               |    2 +-
 net/ipv6/tcp_ipv6.c                 |    7 +-
 net/ipv6/tunnel6.c                  |    4 +-
 net/ipv6/udp.c                      |    2 +-
 net/ipv6/udplite.c                  |    2 +-
 net/iucv/af_iucv.c                  |    4 +-
 net/netlink/af_netlink.c            |   51 ++-
 net/netlink/genetlink.c             |    5 +-
 net/phonet/pn_dev.c                 |    9 +-
 net/rds/af_rds.c                    |    2 +-
 net/rose/af_rose.c                  |    4 +-
 net/rxrpc/ar-ack.c                  |    6 +-
 net/rxrpc/ar-internal.h             |   32 +-
 net/rxrpc/ar-key.c                  |  914 +++++++++++++++++++++++++++++++++--
 net/rxrpc/ar-security.c             |    8 +-
 net/rxrpc/rxkad.c                   |   47 +-
 net/sched/sch_api.c                 |   29 +-
 net/sched/sch_mq.c                  |   13 +-
 net/sctp/ipv6.c                     |    2 +-
 net/sctp/protocol.c                 |    2 +-
 net/socket.c                        |    1 +
 99 files changed, 1526 insertions(+), 452 deletions(-)
 create mode 100644 firmware/cis/MT5634ZLX.cis.ihex
 create mode 100644 firmware/cis/PCMLM28.cis.ihex
 create mode 100644 firmware/cis/RS-COM-2P.cis.ihex

^ permalink raw reply

* bonding...
From: David Miller @ 2009-09-16  8:44 UTC (permalink / raw)
  To: fubar; +Cc: netdev


Jay, there is quite a backlog of bonding patches in the queue right
now.

I'd like to know when you'll get to processing them because it's more
then two weeks (!!) for some of them and these folks are going to miss
the merge window out of no fault of their own.

^ permalink raw reply

* [PATCH V2 0/2 -next] ems_usb: Added support for EMS CPC-USB/ARM7 CAN interface
From: Sebastian Haas @ 2009-09-16  9:04 UTC (permalink / raw)
  To: netdev; +Cc: davem, greg, wg, oliver, socketcan-core, oliver, eric.dumazet

The following series replaces the staging driver cpc-usb with the newly written
ems_usb CAN driver.

---

Sebastian Haas (2):
      ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface
      cpc-usb: Removed driver from staging tree


 drivers/net/can/Kconfig               |    7 
 drivers/net/can/Makefile              |    2 
 drivers/net/can/usb/Makefile          |    5 
 drivers/net/can/usb/ems_usb.c         | 1151 ++++++++++++++++++++++++++++++++
 drivers/staging/Kconfig               |    2 
 drivers/staging/Makefile              |    1 
 drivers/staging/cpc-usb/Kconfig       |    4 
 drivers/staging/cpc-usb/Makefile      |    3 
 drivers/staging/cpc-usb/TODO          |    9 
 drivers/staging/cpc-usb/cpc-usb_drv.c | 1185 ---------------------------------
 drivers/staging/cpc-usb/cpc.h         |  440 ------------
 drivers/staging/cpc-usb/cpc_int.h     |   83 --
 drivers/staging/cpc-usb/cpcusb.h      |   86 --
 drivers/staging/cpc-usb/sja2m16c.h    |   41 -
 drivers/staging/cpc-usb/sja2m16c_2.c  |  452 -------------
 15 files changed, 1165 insertions(+), 2306 deletions(-)
 create mode 100644 drivers/net/can/usb/Makefile
 create mode 100644 drivers/net/can/usb/ems_usb.c
 delete mode 100644 drivers/staging/cpc-usb/Kconfig
 delete mode 100644 drivers/staging/cpc-usb/Makefile
 delete mode 100644 drivers/staging/cpc-usb/TODO
 delete mode 100644 drivers/staging/cpc-usb/cpc-usb_drv.c
 delete mode 100644 drivers/staging/cpc-usb/cpc.h
 delete mode 100644 drivers/staging/cpc-usb/cpc_int.h
 delete mode 100644 drivers/staging/cpc-usb/cpcusb.h
 delete mode 100644 drivers/staging/cpc-usb/sja2m16c.h
 delete mode 100644 drivers/staging/cpc-usb/sja2m16c_2.c

-- 
Cheers, Sebastian
-- 
EMS Dr. Thomas Wuensche e.K.
Sonnenhang 3
85304 Ilmmuenster
HRA Neuburg a.d. Donau, HR-Nr. 70.106
Phone: +49-8441-490260
Fax  : +49-8441-81860
http://www.ems-wuensche.com

^ permalink raw reply

* [PATCH V2 1/2] cpc-usb: Removed driver from staging tree
From: Sebastian Haas @ 2009-09-16  9:04 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w, greg-U8xfFu+wG4EAvxtiuMwx3w,
	oliver-GvhC2dPhHPQdnm+yROfE0A,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	oliver-fJ+pQTUTwRTk1uMJSBkQmQ, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	wg-5Yr1BZd7O62+XT7JhA+gdA
In-Reply-To: <20090916090408.12370.94680.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>

This patch prepares replacing the staging driver cpc-usb with the new
developed ems_usb CAN driver.

Signed-off-by: Sebastian Haas <haas-zsNKPWJ8Pib6hrUXjxyGrA@public.gmane.org>
Acked-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org>
---

 drivers/staging/Kconfig               |    2 
 drivers/staging/Makefile              |    1 
 drivers/staging/cpc-usb/Kconfig       |    4 
 drivers/staging/cpc-usb/Makefile      |    3 
 drivers/staging/cpc-usb/TODO          |    9 
 drivers/staging/cpc-usb/cpc-usb_drv.c | 1185 ---------------------------------
 drivers/staging/cpc-usb/cpc.h         |  440 ------------
 drivers/staging/cpc-usb/cpc_int.h     |   83 --
 drivers/staging/cpc-usb/cpcusb.h      |   86 --
 drivers/staging/cpc-usb/sja2m16c.h    |   41 -
 drivers/staging/cpc-usb/sja2m16c_2.c  |  452 -------------
 11 files changed, 0 insertions(+), 2306 deletions(-)
 delete mode 100644 drivers/staging/cpc-usb/Kconfig
 delete mode 100644 drivers/staging/cpc-usb/Makefile
 delete mode 100644 drivers/staging/cpc-usb/TODO
 delete mode 100644 drivers/staging/cpc-usb/cpc-usb_drv.c
 delete mode 100644 drivers/staging/cpc-usb/cpc.h
 delete mode 100644 drivers/staging/cpc-usb/cpc_int.h
 delete mode 100644 drivers/staging/cpc-usb/cpcusb.h
 delete mode 100644 drivers/staging/cpc-usb/sja2m16c.h
 delete mode 100644 drivers/staging/cpc-usb/sja2m16c_2.c

diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 975ecdd..5e4b865 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -121,8 +121,6 @@ source "drivers/staging/serqt_usb2/Kconfig"
 
 source "drivers/staging/vt6655/Kconfig"
 
-source "drivers/staging/cpc-usb/Kconfig"
-
 source "drivers/staging/pata_rdc/Kconfig"
 
 source "drivers/staging/udlfb/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 2241ae1..ede1599 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -42,6 +42,5 @@ obj-$(CONFIG_LINE6_USB)		+= line6/
 obj-$(CONFIG_USB_SERIAL_QUATECH2)	+= serqt_usb2/
 obj-$(CONFIG_OCTEON_ETHERNET)	+= octeon/
 obj-$(CONFIG_VT6655)		+= vt6655/
-obj-$(CONFIG_USB_CPC)		+= cpc-usb/
 obj-$(CONFIG_RDC_17F3101X)	+= pata_rdc/
 obj-$(CONFIG_FB_UDL)		+= udlfb/
diff --git a/drivers/staging/cpc-usb/Kconfig b/drivers/staging/cpc-usb/Kconfig
deleted file mode 100644
index 2be0bc9..0000000
--- a/drivers/staging/cpc-usb/Kconfig
+++ /dev/null
@@ -1,4 +0,0 @@
-config USB_CPC
-	tristate "CPC CAN USB driver"
-	depends on USB && PROC_FS
-	default n
diff --git a/drivers/staging/cpc-usb/Makefile b/drivers/staging/cpc-usb/Makefile
deleted file mode 100644
index 3f83170..0000000
--- a/drivers/staging/cpc-usb/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_USB_CPC)	+= cpc-usb.o
-
-cpc-usb-y := cpc-usb_drv.o sja2m16c_2.o
diff --git a/drivers/staging/cpc-usb/TODO b/drivers/staging/cpc-usb/TODO
deleted file mode 100644
index 000e8bb..0000000
--- a/drivers/staging/cpc-usb/TODO
+++ /dev/null
@@ -1,9 +0,0 @@
-Things to do for this driver to get merged into the main portion of the
-kernel:
-	- checkpatch cleanups
-	- sparse clean
-	- remove proc code
-	- tie into CAN socket interfaces if possible
-	- figure out sane userspace api
-
-Send patches to Greg Kroah-Hartman <greg-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
diff --git a/drivers/staging/cpc-usb/cpc-usb_drv.c b/drivers/staging/cpc-usb/cpc-usb_drv.c
deleted file mode 100644
index 9bf3f98..0000000
--- a/drivers/staging/cpc-usb/cpc-usb_drv.c
+++ /dev/null
@@ -1,1185 +0,0 @@
-/*
- * CPC-USB CAN Interface Kernel Driver
- *
- * Copyright (C) 2004-2009 EMS Dr. Thomas Wuensche
- *
- * 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; 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
-#include <asm/uaccess.h>
-#include <linux/usb.h>
-
-#include <linux/version.h>
-
-#include <linux/proc_fs.h>
-
-#include "cpc.h"
-
-#include "cpc_int.h"
-#include "cpcusb.h"
-
-#include "sja2m16c.h"
-
-/* Version Information */
-#define DRIVER_AUTHOR  "Sebastian Haas <haas-zsNKPWJ8Pib6hrUXjxyGrA@public.gmane.org>"
-#define DRIVER_DESC    "CPC-USB Driver for Linux Kernel 2.6"
-#define DRIVER_VERSION CPC_DRIVER_VERSION
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL v2");
-
-/* Define these values to match your devices */
-#define USB_CPCUSB_VENDOR_ID	0x12D6
-
-#define USB_CPCUSB_M16C_PRODUCT_ID    0x0888
-#define USB_CPCUSB_LPC2119_PRODUCT_ID 0x0444
-
-#define CPC_USB_PROC_DIR     CPC_PROC_DIR "cpc-usb"
-
-static struct proc_dir_entry *procDir;
-static struct proc_dir_entry *procEntry;
-
-/* Module parameters */
-static int debug;
-module_param(debug, int, S_IRUGO);
-
-/* table of devices that work with this driver */
-static struct usb_device_id cpcusb_table[] = {
-	{USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_M16C_PRODUCT_ID)},
-	{USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_LPC2119_PRODUCT_ID)},
-	{}			/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, cpcusb_table);
-
-/* use to prevent kernel panic if driver is unloaded
- * while a programm has still open the device
- */
-DECLARE_WAIT_QUEUE_HEAD(rmmodWq);
-atomic_t useCount;
-
-static CPC_USB_T *CPCUSB_Table[CPC_USB_CARD_CNT] = { 0 };
-static unsigned int CPCUsbCnt;
-
-/* prevent races between open() and disconnect() */
-static DECLARE_MUTEX(disconnect_sem);
-
-/* local function prototypes */
-static ssize_t cpcusb_read(struct file *file, char *buffer, size_t count,
-			   loff_t *ppos);
-static ssize_t cpcusb_write(struct file *file, const char *buffer,
-			    size_t count, loff_t *ppos);
-static unsigned int cpcusb_poll(struct file *file, poll_table * wait);
-static int cpcusb_open(struct inode *inode, struct file *file);
-static int cpcusb_release(struct inode *inode, struct file *file);
-
-static int cpcusb_probe(struct usb_interface *interface,
-			const struct usb_device_id *id);
-static void cpcusb_disconnect(struct usb_interface *interface);
-
-static void cpcusb_read_bulk_callback(struct urb *urb);
-static void cpcusb_write_bulk_callback(struct urb *urb);
-static void cpcusb_read_interrupt_callback(struct urb *urb);
-
-static int cpcusb_setup_intrep(CPC_USB_T *card);
-
-static struct file_operations cpcusb_fops = {
-	/*
-	 * The owner field is part of the module-locking
-	 * mechanism. The idea is that the kernel knows
-	 * which module to increment the use-counter of
-	 * BEFORE it calls the device's open() function.
-	 * This also means that the kernel can decrement
-	 * the use-counter again before calling release()
-	 * or should the open() function fail.
-	 */
-	.owner = THIS_MODULE,
-
-	.read = cpcusb_read,
-	.write = cpcusb_write,
-	.poll = cpcusb_poll,
-	.open = cpcusb_open,
-	.release = cpcusb_release,
-};
-
-/*
- * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
- */
-static struct usb_class_driver cpcusb_class = {
-	.name = "usb/cpc_usb%d",
-	.fops = &cpcusb_fops,
-	.minor_base = CPC_USB_BASE_MNR,
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver cpcusb_driver = {
-	.name = "cpc-usb",
-	.probe = cpcusb_probe,
-	.disconnect = cpcusb_disconnect,
-	.id_table = cpcusb_table,
-};
-
-static int cpcusb_create_info_output(char *buf)
-{
-	int i = 0, j;
-
-	for (j = 0; j < CPC_USB_CARD_CNT; j++) {
-		if (CPCUSB_Table[j]) {
-			CPC_USB_T *card = CPCUSB_Table[j];
-			CPC_CHAN_T *chan = card->chan;
-
-			/* MINOR CHANNELNO BUSNO SLOTNO */
-			i += sprintf(&buf[i], "%d %s\n", chan->minor,
-				     card->serialNumber);
-		}
-	}
-
-	return i;
-}
-
-static int cpcusb_proc_read_info(char *page, char **start, off_t off,
-				 int count, int *eof, void *data)
-{
-	int len = cpcusb_create_info_output(page);
-
-	if (len <= off + count)
-		*eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len > count)
-		len = count;
-	if (len < 0)
-		len = 0;
-
-	return len;
-}
-
-/*
- * Remove CPC-USB and cleanup
- */
-static inline void cpcusb_delete(CPC_USB_T *card)
-{
-	if (card) {
-		if (card->chan) {
-			if (card->chan->buf)
-				vfree(card->chan->buf);
-
-			if (card->chan->CPCWait_q)
-				kfree(card->chan->CPCWait_q);
-
-			kfree(card->chan);
-		}
-
-		CPCUSB_Table[card->idx] = NULL;
-		kfree(card);
-	}
-}
-
-/*
- * setup the interrupt IN endpoint of a specific CPC-USB device
- */
-static int cpcusb_setup_intrep(CPC_USB_T *card)
-{
-	int retval = 0;
-	struct usb_endpoint_descriptor *ep;
-
-	ep = &card->interface->altsetting[0].endpoint[card->num_intr_in].desc;
-
-	card->intr_in_buffer[0] = 0;
-	card->free_slots = 15;	/* initial size */
-
-	/* setup the urb */
-	usb_fill_int_urb(card->intr_in_urb, card->udev,
-			 usb_rcvintpipe(card->udev, card->num_intr_in),
-			 card->intr_in_buffer,
-			 sizeof(card->intr_in_buffer),
-			 cpcusb_read_interrupt_callback,
-			 card,
-			 ep->bInterval);
-
-	card->intr_in_urb->status = 0;	/* needed! */
-
-	/* submit the urb */
-	retval = usb_submit_urb(card->intr_in_urb, GFP_KERNEL);
-
-	if (retval)
-		err("%s - failed submitting intr urb, error %d", __func__,
-		    retval);
-
-	return retval;
-}
-
-static int cpcusb_open(struct inode *inode, struct file *file)
-{
-	CPC_USB_T *card = NULL;
-	struct usb_interface *interface;
-	int subminor;
-	int j, retval = 0;
-
-	subminor = iminor(inode);
-
-	/* prevent disconnects */
-	down(&disconnect_sem);
-
-	interface = usb_find_interface(&cpcusb_driver, subminor);
-	if (!interface) {
-		err("%s - error, can't find device for minor %d",
-				__func__, subminor);
-		retval = CPC_ERR_NO_INTERFACE_PRESENT;
-		goto exit_no_device;
-	}
-
-	card = usb_get_intfdata(interface);
-	if (!card) {
-		retval = CPC_ERR_NO_INTERFACE_PRESENT;
-		goto exit_no_device;
-	}
-
-	/* lock this device */
-	down(&card->sem);
-
-	/* increment our usage count for the driver */
-	if (card->open) {
-		dbg("device already opened");
-		retval = CPC_ERR_CHANNEL_ALREADY_OPEN;
-		goto exit_on_error;
-	}
-
-	/* save our object in the file's private structure */
-	file->private_data = card;
-	for (j = 0; j < CPC_USB_URB_CNT; j++) {
-		usb_fill_bulk_urb(card->urbs[j].urb, card->udev,
-				  usb_rcvbulkpipe(card->udev, card->num_bulk_in),
-				  card->urbs[j].buffer, card->urbs[j].size,
-				  cpcusb_read_bulk_callback, card);
-
-		retval = usb_submit_urb(card->urbs[j].urb, GFP_KERNEL);
-
-		if (retval) {
-			err("%s - failed submitting read urb, error %d",
-			    __func__, retval);
-			retval = CPC_ERR_TRANSMISSION_FAILED;
-			goto exit_on_error;
-		}
-	}
-
-	info("%s - %d URB's submitted", __func__, j);
-
-	ResetBuffer(card->chan);
-
-	cpcusb_setup_intrep(card);
-	card->open = 1;
-
-	atomic_inc(&useCount);
-
-exit_on_error:
-	/* unlock this device */
-	up(&card->sem);
-
-exit_no_device:
-	up(&disconnect_sem);
-
-	return retval;
-}
-
-static unsigned int cpcusb_poll(struct file *file, poll_table * wait)
-{
-	CPC_USB_T *card = (CPC_USB_T *) file->private_data;
-	unsigned int retval = 0;
-
-	if (!card) {
-		err("%s - device object lost", __func__);
-		return -EIO;
-	}
-
-	poll_wait(file, card->chan->CPCWait_q, wait);
-
-	if (IsBufferNotEmpty(card->chan) || !(card->present))
-		retval |= (POLLIN | POLLRDNORM);
-
-	if (card->free_slots)
-		retval |= (POLLOUT | POLLWRNORM);
-
-	return retval;
-}
-
-static int cpcusb_release(struct inode *inode, struct file *file)
-{
-	CPC_USB_T *card = (CPC_USB_T *) file->private_data;
-	int j, retval = 0;
-
-	if (card == NULL) {
-		dbg("%s - object is NULL", __func__);
-		return CPC_ERR_NO_INTERFACE_PRESENT;
-	}
-
-	/* lock our device */
-	down(&card->sem);
-
-	if (!card->open) {
-		dbg("%s - device not opened", __func__);
-		retval = CPC_ERR_NO_INTERFACE_PRESENT;
-		goto exit_not_opened;
-	}
-
-	/* if device wasn't unplugged kill all urbs */
-	if (card->present) {
-		/* kill read urbs */
-		for (j = 0; j < CPC_USB_URB_CNT; j++) {
-			usb_kill_urb(card->urbs[j].urb);
-		}
-
-		/* kill irq urb */
-		usb_kill_urb(card->intr_in_urb);
-
-		/* kill write urbs */
-		for (j = 0; j < CPC_USB_URB_CNT; j++) {
-			if (atomic_read(&card->wrUrbs[j].busy)) {
-				usb_kill_urb(card->wrUrbs[j].urb);
-				wait_for_completion(&card->wrUrbs[j].finished);
-			}
-		}
-	}
-
-	atomic_dec(&useCount);
-
-	/* last process detached */
-	if (atomic_read(&useCount) == 0) {
-		wake_up(&rmmodWq);
-	}
-
-	if (!card->present && card->open) {
-		/* the device was unplugged before the file was released */
-		up(&card->sem);
-		cpcusb_delete(card);
-		return 0;
-	}
-
-	card->open = 0;
-
-exit_not_opened:
-	up(&card->sem);
-
-	return 0;
-}
-
-static ssize_t cpcusb_read(struct file *file, char *buffer, size_t count,
-			   loff_t *ppos)
-{
-	CPC_USB_T *card = (CPC_USB_T *) file->private_data;
-	CPC_CHAN_T *chan;
-	int retval = 0;
-
-	if (count < sizeof(CPC_MSG_T))
-		return CPC_ERR_UNKNOWN;
-
-	/* check if can read from the given address */
-	if (!access_ok(VERIFY_WRITE, buffer, count))
-		return CPC_ERR_UNKNOWN;
-
-	/* lock this object */
-	down(&card->sem);
-
-	/* verify that the device wasn't unplugged */
-	if (!card->present) {
-		up(&card->sem);
-		return CPC_ERR_NO_INTERFACE_PRESENT;
-	}
-
-	if (IsBufferEmpty(card->chan)) {
-		retval = 0;
-	} else {
-		chan = card->chan;
-
-#if 0
-		/* convert LPC2119 params back to SJA1000 params */
-		if (card->deviceRevision >= 0x0200
-		    && chan->buf[chan->oidx].type == CPC_MSG_T_CAN_PRMS) {
-			LPC2119_TO_SJA1000_Params(&chan->buf[chan->oidx]);
-		}
-#endif
-
-		if (copy_to_user(buffer, &chan->buf[chan->oidx], count) != 0) {
-			retval = CPC_ERR_IO_TRANSFER;
-		} else {
-			chan->oidx = (chan->oidx + 1) % CPC_MSG_BUF_CNT;
-			chan->WnR = 1;
-			retval = sizeof(CPC_MSG_T);
-		}
-	}
-/*	spin_unlock_irqrestore(&card->slock, flags); */
-
-	/* unlock the device */
-	up(&card->sem);
-
-	return retval;
-}
-
-#define SHIFT  1
-static inline void cpcusb_align_buffer_alignment(unsigned char *buf)
-{
-	/* CPC-USB uploads packed bytes. */
-	CPC_MSG_T *cpc = (CPC_MSG_T *) buf;
-	unsigned int i;
-
-	for (i = 0; i < cpc->length + (2 * sizeof(unsigned long)); i++) {
-		((unsigned char *) &cpc->msgid)[1 + i] =
-		    ((unsigned char *) &cpc->msgid)[1 + SHIFT + i];
-	}
-}
-
-static int cpc_get_buffer_count(CPC_CHAN_T *chan)
-{
-	/* check the buffer parameters */
-	if (chan->iidx == chan->oidx)
-		return !chan->WnR ? CPC_MSG_BUF_CNT : 0;
-	else if (chan->iidx >= chan->oidx)
-		return (chan->iidx - chan->oidx) % CPC_MSG_BUF_CNT;
-
-	return (chan->iidx + CPC_MSG_BUF_CNT - chan->oidx) % CPC_MSG_BUF_CNT;
-}
-
-static ssize_t cpcusb_write(struct file *file, const char *buffer,
-			    size_t count, loff_t *ppos)
-{
-	CPC_USB_T *card = (CPC_USB_T *) file->private_data;
-	CPC_USB_WRITE_URB_T *wrUrb = NULL;
-
-	ssize_t bytes_written = 0;
-	int retval = 0;
-	int j;
-
-	unsigned char *obuf = NULL;
-	unsigned char type = 0;
-	CPC_MSG_T *info = NULL;
-
-	dbg("%s - entered minor %d, count = %zu, present = %d",
-	    __func__, card->minor, count, card->present);
-
-	if (count > sizeof(CPC_MSG_T))
-		return CPC_ERR_UNKNOWN;
-
-	/* check if can read from the given address */
-	if (!access_ok(VERIFY_READ, buffer, count))
-		return CPC_ERR_UNKNOWN;
-
-	/* lock this object */
-	down(&card->sem);
-
-	/* verify that the device wasn't unplugged */
-	if (!card->present) {
-		retval = CPC_ERR_NO_INTERFACE_PRESENT;
-		goto exit;
-	}
-
-	/* verify that we actually have some data to write */
-	if (count == 0) {
-		dbg("%s - write request of 0 bytes", __func__);
-		goto exit;
-	}
-
-	if (card->free_slots <= 5) {
-		info = (CPC_MSG_T *) buffer;
-
-		if (info->type != CPC_CMD_T_CLEAR_CMD_QUEUE
-		    || card->free_slots <= 0) {
-			dbg("%s - send buffer full please try again %d",
-			    __func__, card->free_slots);
-			retval = CPC_ERR_CAN_NO_TRANSMIT_BUF;
-			goto exit;
-		}
-	}
-
-	/* Find a free write urb */
-	for (j = 0; j < CPC_USB_URB_CNT; j++) {
-		if (!atomic_read(&card->wrUrbs[j].busy)) {
-			wrUrb = &card->wrUrbs[j];	/* remember found URB */
-			atomic_set(&wrUrb->busy, 1);	/* lock this URB      */
-			init_completion(&wrUrb->finished);	/* init completion    */
-			dbg("WR URB no. %d started", j);
-			break;
-		}
-	}
-
-	/* don't found write urb say error */
-	if (!wrUrb) {
-		dbg("%s - no free send urb available", __func__);
-		retval = CPC_ERR_CAN_NO_TRANSMIT_BUF;
-		goto exit;
-	}
-	dbg("URB write req");
-
-	obuf = (unsigned char *) wrUrb->urb->transfer_buffer;
-
-	/* copy the data from userspace into our transfer buffer;
-	 * this is the only copy required.
-	 */
-	if (copy_from_user(&obuf[4], buffer, count) != 0) {
-		atomic_set(&wrUrb->busy, 0);	/* release urb */
-		retval = CPC_ERR_IO_TRANSFER;
-		goto exit;
-	}
-
-	/* check if it is a DRIVER information message, so we can
-	 * response to that message and not the USB
-	 */
-	info = (CPC_MSG_T *) &obuf[4];
-
-	bytes_written = 11 + info->length;
-	if (bytes_written >= wrUrb->size) {
-		retval = CPC_ERR_IO_TRANSFER;
-		goto exit;
-	}
-
-	switch (info->type) {
-	case CPC_CMD_T_CLEAR_MSG_QUEUE:
-		ResetBuffer(card->chan);
-		break;
-
-	case CPC_CMD_T_INQ_MSG_QUEUE_CNT:
-		retval = cpc_get_buffer_count(card->chan);
-		atomic_set(&wrUrb->busy, 0);
-
-		goto exit;
-
-	case CPC_CMD_T_INQ_INFO:
-		if (info->msg.info.source == CPC_INFOMSG_T_DRIVER) {
-			/* release urb cause we'll use it for driver
-			 * information
-			 */
-			atomic_set(&wrUrb->busy, 0);
-			if (IsBufferFull(card->chan)) {
-				retval = CPC_ERR_IO_TRANSFER;
-				goto exit;
-			}
-
-			/* it is a driver information request message and we have
-			 * free rx slots to store the response
-			 */
-			type = info->msg.info.type;
-			info = &card->chan->buf[card->chan->iidx];
-
-			info->type = CPC_MSG_T_INFO;
-			info->msg.info.source = CPC_INFOMSG_T_DRIVER;
-			info->msg.info.type = type;
-
-			switch (type) {
-			case CPC_INFOMSG_T_VERSION:
-				info->length = strlen(CPC_DRIVER_VERSION) + 2;
-				sprintf(info->msg.info.msg, "%s\n",
-					CPC_DRIVER_VERSION);
-				break;
-
-			case CPC_INFOMSG_T_SERIAL:
-				info->length = strlen(CPC_DRIVER_SERIAL) + 2;
-				sprintf(info->msg.info.msg, "%s\n",
-					CPC_DRIVER_SERIAL);
-				break;
-
-			default:
-				info->length = 2;
-				info->msg.info.type =
-				    CPC_INFOMSG_T_UNKNOWN_TYPE;
-			}
-
-			card->chan->WnR = 0;
-			card->chan->iidx =
-			    (card->chan->iidx + 1) % CPC_MSG_BUF_CNT;
-
-			retval = info->length;
-			goto exit;
-		}
-		break;
-	case CPC_CMD_T_CAN_PRMS:
-		/* Check the controller type. If it's the new CPC-USB, make sure if these are SJA1000 params */
-		if (info->msg.canparams.cc_type != SJA1000
-		    && info->msg.canparams.cc_type != M16C_BASIC
-		    && (card->productId == USB_CPCUSB_LPC2119_PRODUCT_ID
-			&& info->msg.canparams.cc_type != SJA1000)) {
-			/* don't forget to release the urb */
-			atomic_set(&wrUrb->busy, 0);
-			retval = CPC_ERR_WRONG_CONTROLLER_TYPE;
-			goto exit;
-		}
-		break;
-	}
-
-	/* just convert the params if it is an old CPC-USB with M16C controller */
-	if (card->productId == USB_CPCUSB_M16C_PRODUCT_ID) {
-		/* if it is a parameter message convert it from SJA1000 controller
-		 * settings to M16C Basic controller settings
-		 */
-		SJA1000_TO_M16C_BASIC_Params((CPC_MSG_T *) &obuf[4]);
-	}
-
-	/* don't forget the byte alignment */
-	cpcusb_align_buffer_alignment(&obuf[4]);
-
-	/* setup a the 4 byte header */
-	obuf[0] = obuf[1] = obuf[2] = obuf[3] = 0;
-
-	/* this urb was already set up, except for this write size */
-	wrUrb->urb->transfer_buffer_length = bytes_written + 4;
-
-	/* send the data out the bulk port */
-	/* a character device write uses GFP_KERNEL,
-	   unless a spinlock is held */
-	retval = usb_submit_urb(wrUrb->urb, GFP_KERNEL);
-	if (retval) {
-		atomic_set(&wrUrb->busy, 0);	/* release urb */
-		err("%s - failed submitting write urb, error %d",
-		    __func__, retval);
-	} else {
-		retval = bytes_written;
-	}
-
-exit:
-	/* unlock the device */
-	up(&card->sem);
-
-	dbg("%s - leaved", __func__);
-
-	return retval;
-}
-
-/*
- * callback for interrupt IN urb
- */
-static void cpcusb_read_interrupt_callback(struct urb *urb)
-{
-	CPC_USB_T *card = (CPC_USB_T *) urb->context;
-	int retval;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->slock, flags);
-
-	if (!card->present) {
-		spin_unlock_irqrestore(&card->slock, flags);
-		info("%s - no such device", __func__);
-		return;
-	}
-
-	switch (urb->status) {
-	case 0: /* success */
-		card->free_slots = card->intr_in_buffer[1];
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* urb was killed */
-		spin_unlock_irqrestore(&card->slock, flags);
-		dbg("%s - intr urb killed", __func__);
-		return;
-	default:
-		info("%s - nonzero urb status %d", __func__, urb->status);
-		break;
-	}
-
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-	if (retval) {
-		err("%s - failed resubmitting intr urb, error %d",
-		    __func__, retval);
-	}
-
-	spin_unlock_irqrestore(&card->slock, flags);
-	wake_up_interruptible(card->chan->CPCWait_q);
-
-	return;
-}
-
-#define UN_SHIFT  1
-#define CPCMSG_HEADER_LEN_FIRMWARE   11
-static inline int cpcusb_unalign_and_copy_buffy(unsigned char *out,
-						unsigned char *in)
-{
-	unsigned int i, j;
-
-	for (i = 0; i < 3; i++)
-		out[i] = in[i];
-
-	for (j = 0; j < (in[1] + (CPCMSG_HEADER_LEN_FIRMWARE - 3)); j++)
-		out[j + i + UN_SHIFT] = in[j + i];
-
-	return i + j;
-}
-
-/*
- * callback for bulk IN urb
- */
-static void cpcusb_read_bulk_callback(struct urb *urb)
-{
-	CPC_USB_T *card = (CPC_USB_T *) urb->context;
-	CPC_CHAN_T *chan;
-	unsigned char *ibuf = urb->transfer_buffer;
-	int retval, msgCnt, start, again = 0;
-	unsigned long flags;
-
-	if (!card) {
-		err("%s - device object lost", __func__);
-		return;
-	}
-
-	spin_lock_irqsave(&card->slock, flags);
-
-	if (!card->present) {
-		spin_unlock_irqrestore(&card->slock, flags);
-		info("%s - no such device", __func__);
-		return;
-	}
-
-	switch (urb->status) {
-	case 0:		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* urb was killed */
-		spin_unlock_irqrestore(&card->slock, flags);
-		dbg("%s - read urb killed", __func__);
-		return;
-	default:
-		info("%s - nonzero urb status %d", __func__, urb->status);
-		break;
-	}
-
-	if (urb->actual_length) {
-		msgCnt = ibuf[0] & ~0x80;
-		again = ibuf[0] & 0x80;
-
-		/* we have a 4 byte header */
-		start = 4;
-		chan = card->chan;
-		while (msgCnt) {
-			if (!(IsBufferFull(card->chan))) {
-				start +=
-				    cpcusb_unalign_and_copy_buffy((unsigned char *)
-							  &chan->buf[chan->iidx], &ibuf[start]);
-
-				if (start > urb->transfer_buffer_length) {
-					err("%d > %d", start, urb->transfer_buffer_length);
-					break;
-				}
-
-				chan->WnR = 0;
-				chan->iidx = (chan->iidx + 1) % CPC_MSG_BUF_CNT;
-				msgCnt--;
-			} else {
-				break;
-			}
-		}
-	}
-
-	usb_fill_bulk_urb(urb, card->udev,
-			  usb_rcvbulkpipe(card->udev, card->num_bulk_in),
-			  urb->transfer_buffer,
-			  urb->transfer_buffer_length,
-			  cpcusb_read_bulk_callback, card);
-
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-
-	if (retval) {
-		err("%s - failed resubmitting read urb, error %d", __func__, retval);
-	}
-
-	spin_unlock_irqrestore(&card->slock, flags);
-
-	wake_up_interruptible(card->chan->CPCWait_q);
-}
-
-/*
- * callback for bulk IN urb
- */
-static void cpcusb_write_bulk_callback(struct urb *urb)
-{
-	CPC_USB_T *card = (CPC_USB_T *) urb->context;
-	unsigned long flags;
-	int j;
-
-	spin_lock_irqsave(&card->slock, flags);
-
-	/* find this urb */
-	for (j = 0; j < CPC_USB_URB_CNT; j++) {
-		if (card->wrUrbs[j].urb == urb) {
-			dbg("URB found no. %d", j);
-			/* notify anyone waiting that the write has finished */
-			complete(&card->wrUrbs[j].finished);
-			atomic_set(&card->wrUrbs[j].busy, 0);
-			break;
-		}
-	}
-
-	switch (urb->status) {
-	case 0:		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* urb was killed */
-		spin_unlock_irqrestore(&card->slock, flags);
-		dbg("%s - write urb no. %d killed", __func__, j);
-		return;
-	default:
-		info("%s - nonzero urb status %d", __func__, urb->status);
-		break;
-	}
-
-	spin_unlock_irqrestore(&card->slock, flags);
-
-	wake_up_interruptible(card->chan->CPCWait_q);
-}
-
-static inline int cpcusb_get_free_slot(void)
-{
-	int i;
-
-	for (i = 0; i < CPC_USB_CARD_CNT; i++) {
-		if (!CPCUSB_Table[i])
-			return i;
-	}
-
-	return -1;
-}
-
-/*
- * probe function for new CPC-USB devices
- */
-static int cpcusb_probe(struct usb_interface *interface,
-			const struct usb_device_id *id)
-{
-	CPC_USB_T *card = NULL;
-	CPC_CHAN_T *chan = NULL;
-
-	struct usb_device *udev = interface_to_usbdev(interface);
-	struct usb_host_interface *iface_desc;
-	struct usb_endpoint_descriptor *endpoint;
-
-	int i, j, retval = -ENOMEM, slot;
-
-	slot = cpcusb_get_free_slot();
-	if (slot < 0) {
-		info("No more devices supported");
-		return -ENOMEM;
-	}
-
-	/* allocate memory for our device state and initialize it */
-	card = kzalloc(sizeof(CPC_USB_T), GFP_KERNEL);
-	if (!card) {
-		err("Out of memory");
-		return -ENOMEM;
-	}
-	CPCUSB_Table[slot] = card;
-
-	/* allocate and initialize the channel struct */
-	card->chan = kmalloc(sizeof(CPC_CHAN_T), GFP_KERNEL);
-	if (!card->chan) {
-		kfree(card);
-		err("Out of memory");
-		return -ENOMEM;
-	}
-
-	chan = card->chan;
-	memset(chan, 0, sizeof(CPC_CHAN_T));
-	ResetBuffer(chan);
-
-	init_MUTEX(&card->sem);
-	spin_lock_init(&card->slock);
-
-	card->udev = udev;
-	card->interface = interface;
-	if (udev->descriptor.iSerialNumber) {
-		usb_string(udev, udev->descriptor.iSerialNumber, card->serialNumber,
-				   128);
-		info("Serial %s", card->serialNumber);
-	}
-
-	card->productId = udev->descriptor.idProduct;
-	info("Product %s",
-	     card->productId == USB_CPCUSB_LPC2119_PRODUCT_ID ?
-			 "CPC-USB/ARM7" : "CPC-USB/M16C");
-
-	/* set up the endpoint information */
-	/* check out the endpoints */
-	/* use only the first bulk-in and bulk-out endpoints */
-	iface_desc = &interface->altsetting[0];
-	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-		endpoint = &iface_desc->endpoint[i].desc;
-
-		if (!card->num_intr_in &&
-		    (endpoint->bEndpointAddress & USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-		     == USB_ENDPOINT_XFER_INT)) {
-			card->intr_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-			card->num_intr_in = 1;
-
-			if (!card->intr_in_urb) {
-				err("No free urbs available");
-				goto error;
-			}
-
-			dbg("intr_in urb %d", card->num_intr_in);
-		}
-
-		if (!card->num_bulk_in &&
-		    (endpoint->bEndpointAddress & USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-		     == USB_ENDPOINT_XFER_BULK)) {
-			card->num_bulk_in = 2;
-			for (j = 0; j < CPC_USB_URB_CNT; j++) {
-				card->urbs[j].size = endpoint->wMaxPacketSize;
-				card->urbs[j].urb = usb_alloc_urb(0, GFP_KERNEL);
-				if (!card->urbs[j].urb) {
-					err("No free urbs available");
-					goto error;
-				}
-				card->urbs[j].buffer =
-				    usb_buffer_alloc(udev,
-						     card->urbs[j].size,
-						     GFP_KERNEL,
-						     &card->urbs[j].urb->transfer_dma);
-				if (!card->urbs[j].buffer) {
-					err("Couldn't allocate bulk_in_buffer");
-					goto error;
-				}
-			}
-			info("%s - %d reading URB's allocated",
-			     __func__, CPC_USB_URB_CNT);
-		}
-
-		if (!card->num_bulk_out &&
-		    !(endpoint->bEndpointAddress & USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-		     == USB_ENDPOINT_XFER_BULK)) {
-
-			card->num_bulk_out = 2;
-
-			for (j = 0; j < CPC_USB_URB_CNT; j++) {
-				card->wrUrbs[j].size =
-				    endpoint->wMaxPacketSize;
-				card->wrUrbs[j].urb =
-				    usb_alloc_urb(0, GFP_KERNEL);
-				if (!card->wrUrbs[j].urb) {
-					err("No free urbs available");
-					goto error;
-				}
-				card->wrUrbs[j].buffer = usb_buffer_alloc(udev,
-							       card->wrUrbs[j].size, GFP_KERNEL,
-							       &card->wrUrbs[j].urb->transfer_dma);
-
-				if (!card->wrUrbs[j].buffer) {
-					err("Couldn't allocate bulk_out_buffer");
-					goto error;
-				}
-
-				usb_fill_bulk_urb(card->wrUrbs[j].urb, udev,
-						usb_sndbulkpipe(udev, endpoint->bEndpointAddress),
-						card->wrUrbs[j].buffer,
-						card->wrUrbs[j].size,
-						cpcusb_write_bulk_callback,
-						card);
-			}
-
-			info("%s - %d writing URB's allocated", __func__, CPC_USB_URB_CNT);
-		}
-	}
-
-	if (!(card->num_bulk_in && card->num_bulk_out)) {
-		err("Couldn't find both bulk-in and bulk-out endpoints");
-		goto error;
-	}
-
-	/* allow device read, write and ioctl */
-	card->present = 1;
-
-	/* we can register the device now, as it is ready */
-	usb_set_intfdata(interface, card);
-	retval = usb_register_dev(interface, &cpcusb_class);
-
-	if (retval) {
-		/* something prevented us from registering this driver */
-		err("Not able to get a minor for this device.");
-		usb_set_intfdata(interface, NULL);
-		goto error;
-	}
-
-	card->chan->minor = card->minor = interface->minor;
-
-	chan->buf = vmalloc(sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT);
-	if (chan->buf == NULL) {
-		err("Out of memory");
-		retval = -ENOMEM;
-		goto error;
-	}
-	info("Allocated memory for %d messages (%lu kbytes)",
-	     CPC_MSG_BUF_CNT, (long unsigned int)(sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT) / 1000);
-	memset(chan->buf, 0, sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT);
-
-	ResetBuffer(chan);
-
-	card->chan->CPCWait_q = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
-	if (!card->chan->CPCWait_q) {
-		err("Out of memory");
-		retval = -ENOMEM;
-		goto error;
-	}
-	init_waitqueue_head(card->chan->CPCWait_q);
-
-	CPCUSB_Table[slot] = card;
-	card->idx = slot;
-	CPCUsbCnt++;
-
-	/* let the user know what node this device is now attached to */
-	info("Device now attached to USB-%d", card->minor);
-	return 0;
-
-error:
-	for (j = 0; j < CPC_USB_URB_CNT; j++) {
-		if (card->urbs[j].buffer) {
-			usb_buffer_free(card->udev, card->urbs[j].size,
-					card->urbs[j].buffer,
-					card->urbs[j].urb->transfer_dma);
-			card->urbs[j].buffer = NULL;
-		}
-		if (card->urbs[j].urb) {
-			usb_free_urb(card->urbs[j].urb);
-			card->urbs[j].urb = NULL;
-		}
-	}
-
-	cpcusb_delete(card);
-	return retval;
-}
-
-/*
- * called by the usb core when the device is removed from the system
- */
-static void cpcusb_disconnect(struct usb_interface *interface)
-{
-	CPC_USB_T *card = NULL;
-	int minor, j;
-
-	/* prevent races with open() */
-	down(&disconnect_sem);
-
-	card = usb_get_intfdata(interface);
-	usb_set_intfdata(interface, NULL);
-
-	down(&card->sem);
-
-	/* prevent device read, write and ioctl */
-	card->present = 0;
-
-	minor = card->minor;
-
-	/* free all urbs and their buffers */
-	for (j = 0; j < CPC_USB_URB_CNT; j++) {
-		/* terminate an ongoing write */
-		if (atomic_read(&card->wrUrbs[j].busy)) {
-			usb_kill_urb(card->wrUrbs[j].urb);
-			wait_for_completion(&card->wrUrbs[j].finished);
-		}
-		usb_buffer_free(card->udev, card->wrUrbs[j].size,
-				card->wrUrbs[j].buffer,
-				card->wrUrbs[j].urb->transfer_dma);
-		usb_free_urb(card->wrUrbs[j].urb);
-	}
-	info("%d write URBs freed", CPC_USB_URB_CNT);
-
-	/* free all urbs and their buffers */
-	for (j = 0; j < CPC_USB_URB_CNT; j++) {
-		usb_buffer_free(card->udev, card->urbs[j].size,
-				card->urbs[j].buffer,
-				card->urbs[j].urb->transfer_dma);
-		usb_free_urb(card->urbs[j].urb);
-	}
-	info("%d read URBs freed", CPC_USB_URB_CNT);
-	usb_free_urb(card->intr_in_urb);
-
-	/* give back our minor */
-	usb_deregister_dev(interface, &cpcusb_class);
-
-	up(&card->sem);
-
-	/* if the device is opened, cpcusb_release will clean this up */
-	if (!card->open)
-		cpcusb_delete(card);
-	else
-		wake_up_interruptible(card->chan->CPCWait_q);
-
-	up(&disconnect_sem);
-
-	CPCUsbCnt--;
-	info("USB-%d now disconnected", minor);
-}
-
-static int __init CPCUsb_Init(void)
-{
-	int result, i;
-
-	info(DRIVER_DESC " v" DRIVER_VERSION);
-	info("Build on " __DATE__ " at " __TIME__);
-
-	for (i = 0; i < CPC_USB_CARD_CNT; i++)
-		CPCUSB_Table[i] = 0;
-
-	/* register this driver with the USB subsystem */
-	result = usb_register(&cpcusb_driver);
-	if (result) {
-		err("usb_register failed. Error number %d", result);
-		return result;
-	}
-
-	procDir = proc_mkdir(CPC_USB_PROC_DIR, NULL);
-	if (!procDir) {
-		err("Could not create proc entry");
-	} else {
-		procEntry = create_proc_read_entry("info", 0444, procDir,
-						   cpcusb_proc_read_info,
-						   NULL);
-		if (!procEntry) {
-			err("Could not create proc entry %s", CPC_USB_PROC_DIR "/info");
-			remove_proc_entry(CPC_USB_PROC_DIR, NULL);
-			procDir = NULL;
-		}
-	}
-
-	return 0;
-}
-
-static void __exit CPCUsb_Exit(void)
-{
-	wait_event(rmmodWq, !atomic_read(&useCount));
-
-	/* deregister this driver with the USB subsystem */
-	usb_deregister(&cpcusb_driver);
-
-	if (procDir) {
-		if (procEntry)
-			remove_proc_entry("info", procDir);
-		remove_proc_entry(CPC_USB_PROC_DIR, NULL);
-	}
-}
-
-module_init(CPCUsb_Init);
-module_exit(CPCUsb_Exit);
diff --git a/drivers/staging/cpc-usb/cpc.h b/drivers/staging/cpc-usb/cpc.h
deleted file mode 100644
index ed8cb34..0000000
--- a/drivers/staging/cpc-usb/cpc.h
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * CPC CAN Interface Definitions
- *
- * Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche
- *
- * 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.
- */
-#ifndef CPC_HEADER
-#define CPC_HEADER
-
-// the maximum length of the union members within a CPC_MSG
-// this value can be defined by the customer, but has to be
-// >= 64 bytes
-// however, if not defined before, we set a length of 64 byte
-#if !defined(CPC_MSG_LEN) || (CPC_MSG_LEN < 64)
-#undef CPC_MSG_LEN
-#define CPC_MSG_LEN 64
-#endif
-
-// check the operating system used
-#ifdef _WIN32 // running a Windows OS
-
-// define basic types on Windows platforms
-#ifdef _MSC_VER // Visual Studio
-	typedef unsigned __int8 u8;
-	typedef unsigned __int16 u16;
-	typedef unsigned __int32 u32;
-#else // Borland Compiler
-	typedef unsigned char u8;
-	typedef unsigned short u16;
-	typedef unsigned int u32;
-#endif
-	// on Windows OS we use a byte alignment of 1
-	#pragma pack(push, 1)
-
-	// set the calling conventions for the library function calls
-	#define CALL_CONV __stdcall
-#else
-	// Kernel headers already define this types
-	#ifndef __KERNEL__
-		// define basic types
-		typedef unsigned char u8;
-		typedef unsigned short u16;
-		typedef unsigned int u32;
-	#endif
-
-	// Linux does not use this calling convention
-	#define CALL_CONV
-#endif
-
-// Transmission of events from CPC interfaces to PC can be individually
-// controlled per event type. Default state is: don't transmit
-// Control values are constructed by bit-or of Subject and Action
-// and passed to CPC_Control()
-
-// Control-Values for CPC_Control() Command Subject Selection
-#define CONTR_CAN_Message 0x04
-#define CONTR_Busload	  0x08
-#define	CONTR_CAN_State	  0x0C
-#define	CONTR_SendAck	  0x10
-#define	CONTR_Filter	  0x14
-#define CONTR_CmdQueue    0x18	// reserved, do not use
-#define CONTR_BusError    0x1C
-
-// Control Command Actions
-#define CONTR_CONT_OFF    0
-#define CONTR_CONT_ON     1
-#define CONTR_SING_ON     2
-// CONTR_SING_ON doesn't change CONTR_CONT_ON state, so it should be
-// read as: transmit at least once
-
-// defines for confirmed request
-#define DO_NOT_CONFIRM 0
-#define DO_CONFIRM     1
-
-// event flags
-#define EVENT_READ 0x01
-#define EVENT_WRITE 0x02
-
-// Messages from CPC to PC contain a message object type field.
-// The following message types are sent by CPC and can be used in
-// handlers, others should be ignored.
-#define CPC_MSG_T_RESYNC        0 // Normally to be ignored
-#define CPC_MSG_T_CAN           1 // CAN data frame
-#define CPC_MSG_T_BUSLOAD       2 // Busload message
-#define CPC_MSG_T_STRING        3 // Normally to be ignored
-#define CPC_MSG_T_CONTI         4 // Normally to be ignored
-#define CPC_MSG_T_MEM           7 // Normally not to be handled
-#define	CPC_MSG_T_RTR           8 // CAN remote frame
-#define CPC_MSG_T_TXACK	        9 // Send acknowledge
-#define CPC_MSG_T_POWERUP      10 // Power-up message
-#define	CPC_MSG_T_CMD_NO       11 // Normally to be ignored
-#define	CPC_MSG_T_CAN_PRMS     12 // Actual CAN parameters
-#define	CPC_MSG_T_ABORTED      13 // Command aborted message
-#define	CPC_MSG_T_CANSTATE     14 // CAN state message
-#define CPC_MSG_T_RESET        15 // used to reset CAN-Controller
-#define	CPC_MSG_T_XCAN         16 // XCAN data frame
-#define CPC_MSG_T_XRTR         17 // XCAN remote frame
-#define CPC_MSG_T_INFO         18 // information strings
-#define CPC_MSG_T_CONTROL      19 // used for control of interface/driver behaviour
-#define CPC_MSG_T_CONFIRM      20 // response type for confirmed requests
-#define CPC_MSG_T_OVERRUN      21 // response type for overrun conditions
-#define CPC_MSG_T_KEEPALIVE    22 // response type for keep alive conditions
-#define CPC_MSG_T_CANERROR     23 // response type for bus error conditions
-#define CPC_MSG_T_DISCONNECTED 24 // response type for a disconnected interface
-#define CPC_MSG_T_ERR_COUNTER  25 // RX/TX error counter of CAN controller
-
-#define CPC_MSG_T_FIRMWARE    100 // response type for USB firmware download
-
-// Messages from the PC to the CPC interface contain a command field
-// Most of the command types are wrapped by the library functions and have therefore
-// normally not to be used.
-// However, programmers who wish to circumvent the library and talk directly
-// to the drivers (mainly Linux programmers) can use the following
-// command types:
-
-#define CPC_CMD_T_CAN                 1	// CAN data frame
-#define CPC_CMD_T_CONTROL             3	// used for control of interface/driver behaviour
-#define	CPC_CMD_T_CAN_PRMS            6	// set CAN parameters
-#define	CPC_CMD_T_CLEARBUF            8	// clears input queue; this is depricated, use CPC_CMD_T_CLEAR_MSG_QUEUE instead
-#define	CPC_CMD_T_INQ_CAN_PARMS      11	// inquire actual CAN parameters
-#define	CPC_CMD_T_FILTER_PRMS        12	// set filter parameter
-#define	CPC_CMD_T_RTR                13	// CAN remote frame
-#define	CPC_CMD_T_CANSTATE           14	// CAN state message
-#define	CPC_CMD_T_XCAN               15	// XCAN data frame
-#define CPC_CMD_T_XRTR               16	// XCAN remote frame
-#define CPC_CMD_T_RESET              17	// used to reset CAN-Controller
-#define CPC_CMD_T_INQ_INFO           18	// miscellanous information strings
-#define CPC_CMD_T_OPEN_CHAN          19	// open a channel
-#define CPC_CMD_T_CLOSE_CHAN         20	// close a channel
-#define CPC_CMD_T_CNTBUF             21	// this is depricated, use CPC_CMD_T_INQ_MSG_QUEUE_CNT instead
-#define CPC_CMD_T_CAN_EXIT          200 // exit the CAN (disable interrupts; reset bootrate; reset output_cntr; mode = 1)
-
-#define CPC_CMD_T_INQ_MSG_QUEUE_CNT  CPC_CMD_T_CNTBUF   // inquires the count of elements in the message queue
-#define CPC_CMD_T_INQ_ERR_COUNTER    25	                // request the CAN controllers error counter
-#define	CPC_CMD_T_CLEAR_MSG_QUEUE    CPC_CMD_T_CLEARBUF // clear CPC_MSG queue
-#define	CPC_CMD_T_CLEAR_CMD_QUEUE    28	                // clear CPC_CMD queue
-#define CPC_CMD_T_FIRMWARE          100                 // reserved, must not be used
-#define CPC_CMD_T_USB_RESET         101                 // reserved, must not be used
-#define CPC_CMD_T_WAIT_NOTIFY       102                 // reserved, must not be used
-#define CPC_CMD_T_WAIT_SETUP        103                 // reserved, must not be used
-#define	CPC_CMD_T_ABORT             255                 // Normally not to be used
-
-// definitions for CPC_MSG_T_INFO
-// information sources
-#define CPC_INFOMSG_T_UNKNOWN_SOURCE 0
-#define CPC_INFOMSG_T_INTERFACE      1
-#define CPC_INFOMSG_T_DRIVER         2
-#define CPC_INFOMSG_T_LIBRARY        3
-
-// information types
-#define CPC_INFOMSG_T_UNKNOWN_TYPE   0
-#define CPC_INFOMSG_T_VERSION        1
-#define CPC_INFOMSG_T_SERIAL         2
-
-// definitions for controller types
-#define PCA82C200   1 // Philips basic CAN controller, replaced by SJA1000
-#define SJA1000     2 // Philips basic CAN controller
-#define AN82527     3 // Intel full CAN controller
-#define M16C_BASIC  4 // M16C controller running in basic CAN (not full CAN) mode
-
-// channel open error codes
-#define CPC_ERR_NO_FREE_CHANNEL            -1	// no more free space within the channel array
-#define CPC_ERR_CHANNEL_ALREADY_OPEN       -2	// the channel is already open
-#define CPC_ERR_CHANNEL_NOT_ACTIVE         -3	// access to a channel not active failed
-#define CPC_ERR_NO_DRIVER_PRESENT          -4	// no driver at the location searched by the library
-#define CPC_ERR_NO_INIFILE_PRESENT         -5	// the library could not find the inifile
-#define CPC_ERR_WRONG_PARAMETERS           -6	// wrong parameters in the inifile
-#define CPC_ERR_NO_INTERFACE_PRESENT       -7	// 1. The specified interface is not connected
-						// 2. The interface (mostly CPC-USB) was disconnected upon operation
-#define CPC_ERR_NO_MATCHING_CHANNEL        -8	// the driver couldn't find a matching channel
-#define CPC_ERR_NO_BUFFER_AVAILABLE        -9	// the driver couldn't allocate buffer for messages
-#define CPC_ERR_NO_INTERRUPT               -10	// the requested interrupt couldn't be claimed
-#define CPC_ERR_NO_MATCHING_INTERFACE      -11	// no interface type related to this channel was found
-#define CPC_ERR_NO_RESOURCES               -12	// the requested resources could not be claimed
-#define CPC_ERR_SOCKET                     -13	// error concerning TCP sockets
-
-// init error codes
-#define CPC_ERR_WRONG_CONTROLLER_TYPE      -14	// wrong CAN controller type within initialization
-#define CPC_ERR_NO_RESET_MODE              -15	// the controller could not be set into reset mode
-#define CPC_ERR_NO_CAN_ACCESS              -16	// the CAN controller could not be accessed
-
-// transmit error codes
-#define CPC_ERR_CAN_WRONG_ID               -20	// the provided CAN id is too big
-#define CPC_ERR_CAN_WRONG_LENGTH           -21	// the provided CAN length is too long
-#define CPC_ERR_CAN_NO_TRANSMIT_BUF        -22	// the transmit buffer was occupied
-#define CPC_ERR_CAN_TRANSMIT_TIMEOUT       -23	// The message could not be sent within a
-						// specified time
-
-// other error codes
-#define CPC_ERR_SERVICE_NOT_SUPPORTED      -30	// the requested service is not supported by the interface
-#define CPC_ERR_IO_TRANSFER                -31	// a transmission error down to the driver occurred
-#define CPC_ERR_TRANSMISSION_FAILED        -32	// a transmission error down to the interface occurred
-#define CPC_ERR_TRANSMISSION_TIMEOUT       -33	// a timeout occurred within transmission to the interface
-#define CPC_ERR_OP_SYS_NOT_SUPPORTED       -35	// the operating system is not supported
-#define CPC_ERR_UNKNOWN                    -40	// an unknown error ocurred (mostly IOCTL errors)
-
-#define CPC_ERR_LOADING_DLL                -50	// the library 'cpcwin.dll' could not be loaded
-#define CPC_ERR_ASSIGNING_FUNCTION         -51	// the specified function could not be assigned
-#define CPC_ERR_DLL_INITIALIZATION         -52	// the DLL was not initialized correctly
-#define CPC_ERR_MISSING_LICFILE            -55	// the file containing the licenses does not exist
-#define CPC_ERR_MISSING_LICENSE            -56	// a required license was not found
-
-// CAN state bit values. Ignore any bits not listed
-#define CPC_CAN_STATE_BUSOFF     0x80
-#define CPC_CAN_STATE_ERROR      0x40
-
-// Mask to help ignore undefined bits
-#define CPC_CAN_STATE_MASK       0xc0
-
-// CAN-Message representation in a CPC_MSG
-// Message object type is CPC_MSG_T_CAN or CPC_MSG_T_RTR
-// or CPC_MSG_T_XCAN or CPC_MSG_T_XRTR
-typedef struct CPC_CAN_MSG {
-	u32 id;
-	u8 length;
-	u8 msg[8];
-} CPC_CAN_MSG_T;
-
-
-// representation of the CAN parameters for the PCA82C200 controller
-typedef struct CPC_PCA82C200_PARAMS {
-	u8 acc_code;	// Acceptance-code for receive, Standard: 0
-	u8 acc_mask;	// Acceptance-mask for receive, Standard: 0xff (everything)
-	u8 btr0;	// Bus-timing register 0
-	u8 btr1;	// Bus-timing register 1
-	u8 outp_contr;	// Output-control register
-} CPC_PCA82C200_PARAMS_T;
-
-// representation of the CAN parameters for the SJA1000 controller
-typedef struct CPC_SJA1000_PARAMS {
-	u8 mode;	// enables single or dual acceptance filtering
-	u8 acc_code0;	// Acceptance-code for receive, Standard: 0
-	u8 acc_code1;
-	u8 acc_code2;
-	u8 acc_code3;
-	u8 acc_mask0;	// Acceptance-mask for receive, Standard: 0xff (everything)
-	u8 acc_mask1;
-	u8 acc_mask2;
-	u8 acc_mask3;
-	u8 btr0;	// Bus-timing register 0
-	u8 btr1;	// Bus-timing register 1
-	u8 outp_contr;	// Output-control register
-} CPC_SJA1000_PARAMS_T;
-
-// representation of the CAN parameters for the M16C controller
-// in basic CAN mode (means no full CAN)
-typedef struct CPC_M16C_BASIC_PARAMS {
-	u8 con0;
-	u8 con1;
-	u8 ctlr0;
-	u8 ctlr1;
-	u8 clk;
-	u8 acc_std_code0;
-	u8 acc_std_code1;
-	u8 acc_ext_code0;
-	u8 acc_ext_code1;
-	u8 acc_ext_code2;
-	u8 acc_ext_code3;
-	u8 acc_std_mask0;
-	u8 acc_std_mask1;
-	u8 acc_ext_mask0;
-	u8 acc_ext_mask1;
-	u8 acc_ext_mask2;
-	u8 acc_ext_mask3;
-} CPC_M16C_BASIC_PARAMS_T;
-
-// CAN params message representation
-typedef struct CPC_CAN_PARAMS {
-	u8 cc_type;	// represents the controller type
-	union {
-		CPC_M16C_BASIC_PARAMS_T m16c_basic;
-		CPC_SJA1000_PARAMS_T sja1000;
-		CPC_PCA82C200_PARAMS_T pca82c200;
-	} cc_params;
-} CPC_CAN_PARAMS_T;
-
-// the following structures are slightly different for Windows and Linux
-// To be able to use the 'Select' mechanism with Linux the application
-// needs to know the devices file desciptor.
-// This mechanism is not implemented within Windows and the file descriptor
-// is therefore not needed
-#ifdef _WIN32
-
-// CAN init params message representation
-typedef struct CPC_INIT_PARAMS {
-	CPC_CAN_PARAMS_T canparams;
-} CPC_INIT_PARAMS_T;
-
-#else// Linux
-
-// CHAN init params representation
-typedef struct CPC_CHAN_PARAMS {
-	int fd;
-} CPC_CHAN_PARAMS_T;
-
-// CAN init params message representation
-typedef struct CPC_INIT_PARAMS {
-	CPC_CHAN_PARAMS_T chanparams;
-	CPC_CAN_PARAMS_T canparams;
-} CPC_INIT_PARAMS_T;
-
-#endif
-
-// structure for confirmed message handling
-typedef struct CPC_CONFIRM {
-	u8 result; // error code
-} CPC_CONFIRM_T;
-
-// structure for information requests
-typedef struct CPC_INFO {
-	u8 source;                 // interface, driver or library
-	u8 type;                   // version or serial number
-	char msg[CPC_MSG_LEN - 2]; // string holding the requested information
-} CPC_INFO_T;
-
-// OVERRUN ///////////////////////////////////////
-// In general two types of overrun may occur.
-// A hardware overrun, where the CAN controller
-// lost a message, because the interrupt was
-// not handled before the next messgae comes in.
-// Or a software overrun, where i.e. a received
-// message could not be stored in the CPC_MSG
-// buffer.
-
-// After a software overrun has occurred
-// we wait until we have CPC_OVR_GAP slots
-// free in the CPC_MSG buffer.
-#define CPC_OVR_GAP               10
-
-// Two types of software overrun may occur.
-// A received CAN message or a CAN state event
-// can cause an overrun.
-// Note: A CPC_CMD which would normally store
-// its result immediately in the CPC_MSG
-// queue may fail, because the message queue is full.
-// This will not generate an overrun message, but
-// will halt command execution, until this command
-// is able to store its message in the message queue.
-#define CPC_OVR_EVENT_CAN       0x01
-#define CPC_OVR_EVENT_CANSTATE  0x02
-#define CPC_OVR_EVENT_BUSERROR  0x04
-
-// If the CAN controller lost a message
-// we indicate it with the highest bit
-// set in the count field.
-#define CPC_OVR_HW              0x80
-
-// structure for overrun conditions
-typedef struct {
-	u8 event;
-	u8 count;
-} CPC_OVERRUN_T;
-
-// CAN errors ////////////////////////////////////
-// Each CAN controller type has different
-// registers to record errors.
-// Therefor a structure containing the specific
-// errors is set up for each controller here
-
-// SJA1000 error structure
-// see the SJA1000 datasheet for detailed
-// explanation of the registers
-typedef struct CPC_SJA1000_CAN_ERROR {
-	u8 ecc;   // error capture code register
-	u8 rxerr; // RX error counter register
-	u8 txerr; // TX error counter register
-} CPC_SJA1000_CAN_ERROR_T;
-
-// M16C error structure
-// see the M16C datasheet for detailed
-// explanation of the registers
-typedef struct CPC_M16C_CAN_ERROR {
-	u8 tbd;	// to be defined
-} CPC_M16C_CAN_ERROR_T;
-
-// structure for CAN error conditions
-#define  CPC_CAN_ECODE_ERRFRAME   0x01
-typedef struct CPC_CAN_ERROR {
-	u8 ecode;
-	struct {
-		u8 cc_type; // CAN controller type
-		union {
-			CPC_SJA1000_CAN_ERROR_T sja1000;
-			CPC_M16C_CAN_ERROR_T m16c;
-		} regs;
-	} cc;
-} CPC_CAN_ERROR_T;
-
-// Structure containing RX/TX error counter.
-// This structure is used to request the
-// values of the CAN controllers TX and RX
-// error counter.
-typedef struct CPC_CAN_ERR_COUNTER {
-	u8 rx;
-	u8 tx;
-} CPC_CAN_ERR_COUNTER_T;
-
-// If this flag is set, transmissions from PC to CPC are protected against loss
-#define CPC_SECURE_TO_CPC	0x01
-
-// If this flag is set, transmissions from CPC to PC are protected against loss
-#define CPC_SECURE_TO_PC	0x02
-
-// If this flag is set, the CAN-transmit buffer is checked to be free before sending a message
-#define CPC_SECURE_SEND		0x04
-
-// If this flag is set, the transmission complete flag is checked
-// after sending a message
-// THIS IS CURRENTLY ONLY IMPLEMENTED IN THE PASSIVE INTERFACE DRIVERS
-#define CPC_SECURE_TRANSMIT	0x08
-
-// main message type used between library and application
-typedef struct CPC_MSG {
-	u8 type;	// type of message
-	u8 length;	// length of data within union 'msg'
-	u8 msgid;	// confirmation handle
-	u32 ts_sec;	// timestamp in seconds
-	u32 ts_nsec;	// timestamp in nano seconds
-	union {
-		u8 generic[CPC_MSG_LEN];
-		CPC_CAN_MSG_T canmsg;
-		CPC_CAN_PARAMS_T canparams;
-		CPC_CONFIRM_T confirmation;
-		CPC_INFO_T info;
-		CPC_OVERRUN_T overrun;
-		CPC_CAN_ERROR_T error;
-		CPC_CAN_ERR_COUNTER_T err_counter;
-		u8 busload;
-		u8 canstate;
-	} msg;
-} CPC_MSG_T;
-
-#ifdef _WIN32
-#pragma pack(pop)		// reset the byte alignment
-#endif
-
-#endif				// CPC_HEADER
diff --git a/drivers/staging/cpc-usb/cpc_int.h b/drivers/staging/cpc-usb/cpc_int.h
deleted file mode 100644
index a0d60c0..0000000
--- a/drivers/staging/cpc-usb/cpc_int.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * CPCLIB
- *
- * Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche
- *
- * 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.
- *
- */
-#ifndef CPC_INT_H
-#define CPC_INT_H
-
-#include <linux/wait.h>
-
-#define CPC_MSG_BUF_CNT	1500
-
-#define CPC_PROC_DIR "driver/"
-
-#undef dbg
-#undef err
-#undef info
-
-/* Use our own dbg macro */
-#define dbg(format, arg...) do { if (debug) printk( KERN_INFO format "\n" , ## arg); } while (0)
-#define err(format, arg...) do { printk( KERN_INFO "ERROR " format "\n" , ## arg); } while (0)
-#define info(format, arg...) do { printk( KERN_INFO format "\n" , ## arg); } while (0)
-
-/* Macros help using of our buffers */
-#define IsBufferFull(x)     (!(x)->WnR) && ((x)->iidx == (x)->oidx)
-#define IsBufferEmpty(x)    ((x)->WnR) && ((x)->iidx == (x)->oidx)
-#define IsBufferNotEmpty(x) (!(x)->WnR) || ((x)->iidx != (x)->oidx)
-#define ResetBuffer(x)      do { (x)->oidx = (x)->iidx=0; (x)->WnR = 1; } while(0);
-
-#define CPC_BufWriteAllowed ((chan->oidx != chan->iidx) || chan->WnR)
-
-typedef void (*chan_write_byte_t) (void *chan, unsigned int reg,
-				   unsigned char val);
-typedef unsigned char (*chan_read_byte_t) (void *chan, unsigned int reg);
-
-typedef struct CPC_CHAN {
-	void __iomem * canBase;	// base address of SJA1000
-	chan_read_byte_t read_byte;	// CAN controller read access routine
-	chan_write_byte_t write_byte;	// CAN controller write access routine
-	CPC_MSG_T *buf;		// buffer for CPC msg
-	unsigned int iidx;
-	unsigned int oidx;
-	unsigned int WnR;
-	unsigned int minor;
-	unsigned int locked;
-	unsigned int irqDisabled;
-
-	unsigned char cpcCtrlCANMessage;
-	unsigned char cpcCtrlCANState;
-	unsigned char cpcCtrlBUSState;
-
-	unsigned char controllerType;
-
-	unsigned long ovrTimeSec;
-	unsigned long ovrTimeNSec;
-	unsigned long ovrLockedBuffer;
-	CPC_OVERRUN_T ovr;
-
-	/* for debugging only */
-	unsigned int handledIrqs;
-	unsigned int lostMessages;
-
-	unsigned int sentStdCan;
-	unsigned int sentExtCan;
-	unsigned int sentStdRtr;
-	unsigned int sentExtRtr;
-
-	unsigned int recvStdCan;
-	unsigned int recvExtCan;
-	unsigned int recvStdRtr;
-	unsigned int recvExtRtr;
-
-	wait_queue_head_t *CPCWait_q;
-
-	void *private;
-} CPC_CHAN_T;
-
-#endif
diff --git a/drivers/staging/cpc-usb/cpcusb.h b/drivers/staging/cpc-usb/cpcusb.h
deleted file mode 100644
index e5273dd..0000000
--- a/drivers/staging/cpc-usb/cpcusb.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Header for CPC-USB Driver ********************
- * Copyright 1999, 2000, 2001
- *
- * Company:  EMS Dr. Thomas Wuensche
- *           Sonnenhang 3
- *           85304 Ilmmuenster
- *           Phone: +49-8441-490260
- *           Fax:   +49-8441-81860
- *           email: support-zsNKPWJ8Pib6hrUXjxyGrA@public.gmane.org
- *           WWW:   www.ems-wuensche.com
- */
-
-#ifndef CPCUSB_H
-#define CPCUSB_H
-
-#undef err
-#undef dbg
-#undef info
-
-/* Use our own dbg macro */
-#define dbg(format, arg...) do { if (debug) printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0)
-#define info(format, arg...) do { printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0)
-#define err(format, arg...) do { printk(KERN_INFO "CPC-USB(ERROR): " format "\n" , ## arg); } while (0)
-
-#define CPC_USB_CARD_CNT      4
-
-typedef struct CPC_USB_READ_URB {
-	unsigned char *buffer;	/* the buffer to send data */
-	size_t size;		/* the size of the send buffer */
-	struct urb *urb;	/* the urb used to send data */
-} CPC_USB_READ_URB_T;
-
-typedef struct CPC_USB_WRITE_URB {
-	unsigned char *buffer;	/* the buffer to send data */
-	size_t size;		/* the size of the send buffer */
-	struct urb *urb;	/* the urb used to send data */
-	atomic_t busy;		/* true if write urb is busy */
-	struct completion finished;	/* wait for the write to finish */
-} CPC_USB_WRITE_URB_T;
-
-#define CPC_USB_URB_CNT  10
-
-typedef struct CPC_USB {
-	struct usb_device *udev;	/* save off the usb device pointer */
-	struct usb_interface *interface;	/* the interface for this device */
-	unsigned char minor;	/* the starting minor number for this device */
-	unsigned char num_ports;	/* the number of ports this device has */
-	int num_intr_in;	/* number of interrupt in endpoints we have */
-	int num_bulk_in;	/* number of bulk in endpoints we have */
-	int num_bulk_out;	/* number of bulk out endpoints we have */
-
-	CPC_USB_READ_URB_T urbs[CPC_USB_URB_CNT];
-
-	unsigned char intr_in_buffer[4];	/* interrupt transfer buffer */
-	struct urb *intr_in_urb;	/* interrupt transfer urb */
-
-	CPC_USB_WRITE_URB_T wrUrbs[CPC_USB_URB_CNT];
-
-	int open;		/* if the port is open or not */
-	int present;		/* if the device is not disconnected */
-	struct semaphore sem;	/* locks this structure */
-
-	int free_slots;		/* free send slots of CPC-USB */
-	int idx;
-
-	spinlock_t slock;
-
-	char serialNumber[128];	/* serial number */
-	int productId;		/* product id to differ between M16C and LPC2119 */
-	CPC_CHAN_T *chan;
-} CPC_USB_T;
-
-#define CPCTable               CPCUSB_Table
-
-#define CPC_DRIVER_VERSION "0.724"
-#define CPC_DRIVER_SERIAL  "not applicable"
-
-#define OBUF_SIZE 255		// 4096
-
-/* read timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */
-#define RD_NAK_TIMEOUT (10*HZ)	/* Default number of X seconds to wait */
-#define RD_EXPIRE 12		/* Number of attempts to wait X seconds */
-
-#define CPC_USB_BASE_MNR 0	/* CPC-USB start at minor 0  */
-
-#endif
diff --git a/drivers/staging/cpc-usb/sja2m16c.h b/drivers/staging/cpc-usb/sja2m16c.h
deleted file mode 100644
index 654bd3f..0000000
--- a/drivers/staging/cpc-usb/sja2m16c.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef _SJA2M16C_H
-#define _SJA2M16C_H
-
-#include "cpc.h"
-
-#define BAUDRATE_TOLERANCE_PERCENT	1
-#define SAMPLEPOINT_TOLERANCE_PERCENT	5
-#define SAMPLEPOINT_UPPER_LIMIT		88
-
-/* M16C parameters */
-struct FIELD_C0CONR {
-	unsigned int brp:4;
-	unsigned int sam:1;
-	unsigned int pr:3;
-	unsigned int dummy:8;
-};
-struct FIELD_C1CONR {
-	unsigned int ph1:3;
-	unsigned int ph2:3;
-	unsigned int sjw:2;
-	unsigned int dummy:8;
-};
-typedef union C0CONR {
-	unsigned char c0con;
-	struct FIELD_C0CONR bc0con;
-} C0CONR_T;
-typedef union C1CONR {
-	unsigned char c1con;
-	struct FIELD_C1CONR bc1con;
-} C1CONR_T;
-
-#define SJA_TSEG1	((pParams->btr1 & 0x0f)+1)
-#define SJA_TSEG2	(((pParams->btr1 & 0x70)>>4)+1)
-#define SJA_BRP		((pParams->btr0 & 0x3f)+1)
-#define SJA_SJW		((pParams->btr0 & 0xc0)>>6)
-#define SJA_SAM		((pParams->btr1 & 0x80)>>7)
-int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2);
-int samplepoint_m16c(int brp, int pr, int ph1, int ph2);
-int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T *pMsg);
-
-#endif
diff --git a/drivers/staging/cpc-usb/sja2m16c_2.c b/drivers/staging/cpc-usb/sja2m16c_2.c
deleted file mode 100644
index bf0230f..0000000
--- a/drivers/staging/cpc-usb/sja2m16c_2.c
+++ /dev/null
@@ -1,452 +0,0 @@
-/****************************************************************************
-*
-*      Copyright (c) 2003,2004 by EMS Dr. Thomas Wuensche
-*
-*                  - All rights reserved -
-*
-* This code is provided "as is" without warranty of any kind, either
-* expressed or implied, including but not limited to the liability
-* concerning the freedom from material defects, the fitness for parti-
-* cular purposes or the freedom of proprietary rights of third parties.
-*
-*****************************************************************************
-* Module name.: cpcusb
-*****************************************************************************
-* Include file: cpc.h
-*****************************************************************************
-* Project.....: Windows Driver Development Kit
-* Filename....: sja2m16c.cpp
-* Authors.....: (GU) Gerhard Uttenthaler
-*               (CS) Christian Schoett
-*****************************************************************************
-* Short descr.: converts baudrate between SJA1000 and M16C
-*****************************************************************************
-* Description.: handles the baudrate conversion from SJA1000 parameters to
-*               M16C parameters
-*****************************************************************************
-* Address     : EMS Dr. Thomas Wuensche
-*               Sonnenhang 3
-*               D-85304 Ilmmuenster
-*               Tel. : +49-8441-490260
-*               Fax. : +49-8441-81860
-*               email: support-zsNKPWJ8Pib6hrUXjxyGrA@public.gmane.org
-*****************************************************************************
-*                            History
-*****************************************************************************
-* Version  Date        Auth Remark
-*
-* 01.00    ??          GU   - initial release
-* 01.10    ??????????  CS   - adapted to fit into the USB Windows driver
-* 02.00    18.08.2004  GU   - improved the baudrate calculating algorithm
-*                           - implemented acceptance filtering
-* 02.10    10.09.2004  CS   - adapted to fit into the USB Windows driver
-*****************************************************************************
-*                            ToDo's
-*****************************************************************************
-*/
-
-/****************************************************************************/
-/*     I N C L U D E S
-*/
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
-#include <asm/uaccess.h>
-#include <linux/usb.h>
-
-#include "cpc.h"
-#include "cpc_int.h"
-#include "cpcusb.h"
-
-#include "sja2m16c.h"
-
-/*********************************************************************/
-int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2)
-{
-	return (16000000 / (1 << clk)) / 2 / (brp + 1) / (1 + pr + 1 +
-							    ph1 + 1 + ph2 +
-							    1);
-}
-
-
-/*********************************************************************/
-int samplepoint_m16c(int brp, int pr, int ph1, int ph2)
-{
-	return (100 * (1 + pr + 1 + ph1 + 1)) / (1 + pr + 1 + ph1 + 1 +
-						  ph2 + 1);
-}
-
-
-/****************************************************************************
-* Function.....: SJA1000_TO_M16C_BASIC_Params
-*
-* Task.........: This routine converts SJA1000 CAN btr parameters into M16C
-*                parameters based on the sample point and the error. In
-*                addition it converts the acceptance filter parameters to
-*                suit the M16C parameters
-*
-* Parameters...: None
-*
-* Return values: None
-*
-* Comments.....:
-*****************************************************************************
-*                History
-*****************************************************************************
-* 19.01.2005  CS   - modifed the conversion of SJA1000 filter params into
-*                    M16C params. Due to compatibility reasons with the
-*                    older 82C200 CAN controller the SJA1000
-****************************************************************************/
-int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T * in)
-{
-	int sjaBaudrate;
-	int sjaSamplepoint;
-	int *baudrate_error;	// BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
-	int *samplepoint_error;	// BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
-	int baudrate_error_merk;
-	int clk, brp, pr, ph1, ph2;
-	int clk_merk, brp_merk, pr_merk, ph1_merk, ph2_merk;
-	int index;
-	unsigned char acc_code0, acc_code1, acc_code2, acc_code3;
-	unsigned char acc_mask0, acc_mask1, acc_mask2, acc_mask3;
-	CPC_MSG_T * out;
-	C0CONR_T c0con;
-	C1CONR_T c1con;
-	int tmpAccCode;
-	int tmpAccMask;
-
-	    // we have to convert the parameters into M16C parameters
-	    CPC_SJA1000_PARAMS_T * pParams;
-
-	    // check if the type is CAN parameters and if we have to convert the given params
-	    if (in->type != CPC_CMD_T_CAN_PRMS
-		|| in->msg.canparams.cc_type != SJA1000)
-		return 0;
-	pParams =
-	    (CPC_SJA1000_PARAMS_T *) & in->msg.canparams.cc_params.sja1000;
-	acc_code0 = pParams->acc_code0;
-	acc_code1 = pParams->acc_code1;
-	acc_code2 = pParams->acc_code2;
-	acc_code3 = pParams->acc_code3;
-	acc_mask0 = pParams->acc_mask0;
-	acc_mask1 = pParams->acc_mask1;
-	acc_mask2 = pParams->acc_mask2;
-	acc_mask3 = pParams->acc_mask3;
-
-#ifdef _DEBUG_OUTPUT_CAN_PARAMS
-	    info("acc_code0: %2.2Xh\n", acc_code0);
-	info("acc_code1: %2.2Xh\n", acc_code1);
-	info("acc_code2: %2.2Xh\n", acc_code2);
-	info("acc_code3: %2.2Xh\n", acc_code3);
-	info("acc_mask0: %2.2Xh\n", acc_mask0);
-	info("acc_mask1: %2.2Xh\n", acc_mask1);
-	info("acc_mask2: %2.2Xh\n", acc_mask2);
-	info("acc_mask3: %2.2Xh\n", acc_mask3);
-
-#endif	/*  */
-	    if (!
-		 (baudrate_error =
-		  (int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
-		err("Could not allocate memory\n");
-		return -3;
-	}
-	if (!
-	      (samplepoint_error =
-	       (int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
-		err("Could not allocate memory\n");
-		vfree(baudrate_error);
-		return -3;
-	}
-	memset(baudrate_error, 0xff, sizeof(baudrate_error));
-	memset(samplepoint_error, 0xff, sizeof(baudrate_error));
-	sjaBaudrate =
-	    16000000 / 2 / SJA_BRP / (1 + SJA_TSEG1 + SJA_TSEG2);
-	sjaSamplepoint =
-	    100 * (1 + SJA_TSEG1) / (1 + SJA_TSEG1 + SJA_TSEG2);
-	if (sjaBaudrate == 0) {
-		vfree(baudrate_error);
-		vfree(samplepoint_error);
-		return -2;
-	}
-
-#ifdef _DEBUG_OUTPUT_CAN_PARAMS
-	    info("\nStarting SJA CAN params\n");
-	info("-------------------------\n");
-	info("TS1     : %2.2Xh TS2 : %2.2Xh\n", SJA_TSEG1, SJA_TSEG2);
-	info("BTR0    : %2.2Xh BTR1: %2.2Xh\n", pParams->btr0,
-	      pParams->btr1);
-	info("Baudrate: %d.%dkBaud\n", sjaBaudrate / 1000,
-	      sjaBaudrate % 1000);
-	info("Sample P: 0.%d\n", sjaSamplepoint);
-	info("\n");
-
-#endif	/*  */
-	    c0con.bc0con.sam = SJA_SAM;
-	c1con.bc1con.sjw = SJA_SJW;
-
-	    // calculate errors for all baudrates
-	    index = 0;
-	for (clk = 0; clk < 5; clk++) {
-		for (brp = 0; brp < 16; brp++) {
-			for (pr = 0; pr < 8; pr++) {
-				for (ph1 = 0; ph1 < 8; ph1++) {
-					for (ph2 = 0; ph2 < 8; ph2++) {
-						baudrate_error[index] =
-						    100 *
-						    abs(baudrate_m16c
-							(clk, brp, pr, ph1,
-							 ph2) -
-							sjaBaudrate) /
-						    sjaBaudrate;
-						samplepoint_error[index] =
-						    abs(samplepoint_m16c
-							(brp, pr, ph1,
-							 ph2) -
-							sjaSamplepoint);
-
-#if 0
-						    info
-						    ("Baudrate      : %d kBaud\n",
-						     baudrate_m16c(clk,
-								   brp, pr,
-								   ph1,
-								   ph2));
-						info
-						    ("Baudrate Error: %d\n",
-						     baudrate_error
-						     [index]);
-						info
-						    ("Sample P Error: %d\n",
-						     samplepoint_error
-						     [index]);
-						info
-						    ("clk           : %d\n",
-						     clk);
-
-#endif	/*  */
-						    index++;
-					}
-				}
-			}
-		}
-	}
-
-	    // mark all baudrate_error entries which are outer limits
-	    index = 0;
-	for (clk = 0; clk < 5; clk++) {
-		for (brp = 0; brp < 16; brp++) {
-			for (pr = 0; pr < 8; pr++) {
-				for (ph1 = 0; ph1 < 8; ph1++) {
-					for (ph2 = 0; ph2 < 8; ph2++) {
-						if ((baudrate_error[index]
-						      >
-						      BAUDRATE_TOLERANCE_PERCENT)
-						     ||
-						     (samplepoint_error
-						       [index] >
-						       SAMPLEPOINT_TOLERANCE_PERCENT)
-						     ||
-						     (samplepoint_m16c
-						       (brp, pr, ph1,
-							ph2) >
-						       SAMPLEPOINT_UPPER_LIMIT))
-						{
-							baudrate_error
-							    [index] = -1;
-						} else
-						    if (((1 + pr + 1 +
-							  ph1 + 1 + ph2 +
-							  1) < 8)
-							||
-							((1 + pr + 1 +
-							  ph1 + 1 + ph2 +
-							  1) > 25)) {
-							baudrate_error
-							    [index] = -1;
-						}
-
-#if 0
-						    else {
-							info
-							    ("Baudrate      : %d kBaud\n",
-							     baudrate_m16c
-							     (clk, brp, pr,
-							      ph1, ph2));
-							info
-							    ("Baudrate Error: %d\n",
-							     baudrate_error
-							     [index]);
-							info
-							    ("Sample P Error: %d\n",
-							     samplepoint_error
-							     [index]);
-						}
-
-#endif	/*  */
-						    index++;
-					}
-				}
-			}
-		}
-	}
-
-	    // find list of minimum of baudrate_error within unmarked entries
-	    clk_merk = brp_merk = pr_merk = ph1_merk = ph2_merk = 0;
-	baudrate_error_merk = 100;
-	index = 0;
-	for (clk = 0; clk < 5; clk++) {
-		for (brp = 0; brp < 16; brp++) {
-			for (pr = 0; pr < 8; pr++) {
-				for (ph1 = 0; ph1 < 8; ph1++) {
-					for (ph2 = 0; ph2 < 8; ph2++) {
-						if (baudrate_error[index]
-						     != -1) {
-							if (baudrate_error
-							     [index] <
-							     baudrate_error_merk)
-							{
-								baudrate_error_merk
-								    =
-								    baudrate_error
-								    [index];
-								brp_merk =
-								    brp;
-								pr_merk =
-								    pr;
-								ph1_merk =
-								    ph1;
-								ph2_merk =
-								    ph2;
-								clk_merk =
-								    clk;
-
-#if 0
-								    info
-								    ("brp: %2.2Xh pr: %2.2Xh ph1: %2.2Xh ph2: %2.2Xh\n",
-								     brp,
-								     pr,
-								     ph1,
-								     ph2);
-								info
-								    ("Baudrate      : %d kBaud\n",
-								     baudrate_m16c
-								     (clk,
-								      brp,
-								      pr,
-								      ph1,
-								      ph2));
-								info
-								    ("Baudrate Error: %d\n",
-								     baudrate_error
-								     [index]);
-								info
-								    ("Sample P Error: %d\n",
-								     samplepoint_error
-								     [index]);
-
-#endif	/*  */
-							}
-						}
-						index++;
-					}
-				}
-			}
-		}
-	}
-	if (baudrate_error_merk == 100) {
-		info("ERROR: Could not convert CAN init parameter\n");
-		vfree(baudrate_error);
-		vfree(samplepoint_error);
-		return -1;
-	}
-
-	    // setting m16c CAN parameter
-	    c0con.bc0con.brp = brp_merk;
-	c0con.bc0con.pr = pr_merk;
-	c1con.bc1con.ph1 = ph1_merk;
-	c1con.bc1con.ph2 = ph2_merk;
-
-#ifdef _DEBUG_OUTPUT_CAN_PARAMS
-	    info("\nResulting M16C CAN params\n");
-	info("-------------------------\n");
-	info("clk     : %2.2Xh\n", clk_merk);
-	info("ph1     : %2.2Xh ph2: %2.2Xh\n", c1con.bc1con.ph1 + 1,
-	      c1con.bc1con.ph2 + 1);
-	info("pr      : %2.2Xh brp: %2.2Xh\n", c0con.bc0con.pr + 1,
-	      c0con.bc0con.brp + 1);
-	info("sjw     : %2.2Xh sam: %2.2Xh\n", c1con.bc1con.sjw,
-	      c0con.bc0con.sam);
-	info("co1     : %2.2Xh co0: %2.2Xh\n", c1con.c1con, c0con.c0con);
-	info("Baudrate: %d.%dBaud\n",
-	       baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
-			     c1con.bc1con.ph1, c1con.bc1con.ph2) / 1000,
-	       baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
-			      c1con.bc1con.ph1, c1con.bc1con.ph2) % 1000);
-	info("Sample P: 0.%d\n",
-	      samplepoint_m16c(c0con.bc0con.brp, c0con.bc0con.pr,
-			       c1con.bc1con.ph1, c1con.bc1con.ph2));
-	info("\n");
-
-#endif	/*  */
-	    out = in;
-	out->type = 6;
-	out->length = sizeof(CPC_M16C_BASIC_PARAMS_T) + 1;
-	out->msg.canparams.cc_type = M16C_BASIC;
-	out->msg.canparams.cc_params.m16c_basic.con0 = c0con.c0con;
-	out->msg.canparams.cc_params.m16c_basic.con1 = c1con.c1con;
-	out->msg.canparams.cc_params.m16c_basic.ctlr0 = 0x4C;
-	out->msg.canparams.cc_params.m16c_basic.ctlr1 = 0x00;
-	out->msg.canparams.cc_params.m16c_basic.clk = clk_merk;
-	out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
-	    acc_code0;
-	out->msg.canparams.cc_params.m16c_basic.acc_std_code1 = acc_code1;
-
-//      info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
-	    tmpAccCode = (acc_code1 >> 5) + (acc_code0 << 3);
-	out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
-	    (unsigned char) tmpAccCode;
-	out->msg.canparams.cc_params.m16c_basic.acc_std_code1 =
-	    (unsigned char) (tmpAccCode >> 8);
-
-//      info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
-	    out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
-	    ~acc_mask0;
-	out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
-	    ~acc_mask1;
-
-//      info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
-	    tmpAccMask = ((acc_mask1) >> 5) + ((acc_mask0) << 3);
-
-//      info("tmpAccMask: 0x%4.4X\n", tmpAccMask);
-	    out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
-	    (unsigned char) ~tmpAccMask;
-	out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
-	    (unsigned char) ~(tmpAccMask >> 8);
-
-//      info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
-	    out->msg.canparams.cc_params.m16c_basic.acc_ext_code0 =
-	    (unsigned char) tmpAccCode;
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_code1 =
-	    (unsigned char) (tmpAccCode >> 8);
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_code2 = acc_code2;
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_code3 = acc_code3;
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_mask0 =
-	    (unsigned char) ~tmpAccMask;
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_mask1 =
-	    (unsigned char) ~(tmpAccMask >> 8);
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_mask2 =
-	    ~acc_mask2;
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_mask3 =
-	    ~acc_mask3;
-	vfree(baudrate_error);
-	vfree(samplepoint_error);
-	return 0;
-}
-
-

-- 
EMS Dr. Thomas Wuensche e.K.
Sonnenhang 3
85304 Ilmmuenster
HRA Neuburg a.d. Donau, HR-Nr. 70.106
Phone: +49-8441-490260
Fax  : +49-8441-81860
http://www.ems-wuensche.com

^ permalink raw reply related

* [PATCH V2 2/2] ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface
From: Sebastian Haas @ 2009-09-16  9:04 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w, greg-U8xfFu+wG4EAvxtiuMwx3w,
	oliver-GvhC2dPhHPQdnm+yROfE0A,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	oliver-fJ+pQTUTwRTk1uMJSBkQmQ, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	wg-5Yr1BZd7O62+XT7JhA+gdA
In-Reply-To: <20090916090408.12370.94680.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>

This patch adds support for one channel CAN/USB interace CPC-USB/ARM7 from
EMS Dr. Thomas Wuensche (http://www.ems-wuensche.com).

Signed-off-by: Sebastian Haas <haas-zsNKPWJ8Pib6hrUXjxyGrA@public.gmane.org>
---

 drivers/net/can/Kconfig       |    7 
 drivers/net/can/Makefile      |    2 
 drivers/net/can/usb/Makefile  |    5 
 drivers/net/can/usb/ems_usb.c | 1151 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1165 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/can/usb/Makefile
 create mode 100644 drivers/net/can/usb/ems_usb.c

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 0900743..6ac5aa5 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -75,6 +75,13 @@ config CAN_EMS_PCI
 	  CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
 	  (http://www.ems-wuensche.de).
 
+config CAN_EMS_USB
+	tristate "EMS CPC-USB/ARM7 CAN/USB interface"
+	depends on USB && CAN_DEV
+	---help---
+	  This driver is for the one channel CPC-USB/ARM7 CAN/USB interface
+	  from from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
+
 config CAN_KVASER_PCI
 	tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
 	depends on PCI && CAN_SJA1000
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 523a941..9b035ec 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_CAN_VCAN)		+= vcan.o
 obj-$(CONFIG_CAN_DEV)		+= can-dev.o
 can-dev-y			:= dev.o
 
+obj-y				+= usb/
+
 obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
 
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile
new file mode 100644
index 0000000..c3f75ba
--- /dev/null
+++ b/drivers/net/can/usb/Makefile
@@ -0,0 +1,5 @@
+#
+#  Makefile for the Linux Controller Area Network USB drivers.
+#
+
+obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
new file mode 100644
index 0000000..3d9032f
--- /dev/null
+++ b/drivers/net/can/usb/ems_usb.c
@@ -0,0 +1,1151 @@
+/*
+ * CAN driver for EMS Dr. Thomas Wuensche CPC-USB/ARM7
+ *
+ * Copyright (C) 2004-2009 EMS Dr. Thomas Wuensche
+ *
+ * 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; 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <linux/init.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/usb.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+MODULE_AUTHOR("Sebastian Haas <haas-zsNKPWJ8Pib6hrUXjxyGrA@public.gmane.org>");
+MODULE_DESCRIPTION("CAN driver for EMS Dr. Thomas Wuensche CAN/USB interfaces");
+MODULE_LICENSE("GPL v2");
+
+/* Control-Values for CPC_Control() Command Subject Selection */
+#define CONTR_CAN_MESSAGE 0x04
+#define CONTR_CAN_STATE   0x0C
+#define CONTR_BUS_ERROR   0x1C
+
+/* Control Command Actions */
+#define CONTR_CONT_OFF 0
+#define CONTR_CONT_ON  1
+#define CONTR_ONCE     2
+
+/* Messages from CPC to PC */
+#define CPC_MSG_TYPE_CAN_FRAME       1  /* CAN data frame */
+#define CPC_MSG_TYPE_RTR_FRAME       8  /* CAN remote frame */
+#define CPC_MSG_TYPE_CAN_PARAMS      12 /* Actual CAN parameters */
+#define CPC_MSG_TYPE_CAN_STATE       14 /* CAN state message */
+#define CPC_MSG_TYPE_EXT_CAN_FRAME   16 /* Extended CAN data frame */
+#define CPC_MSG_TYPE_EXT_RTR_FRAME   17 /* Extended remote frame */
+#define CPC_MSG_TYPE_CONTROL         19 /* change interface behavior */
+#define CPC_MSG_TYPE_CONFIRM         20 /* command processed confirmation */
+#define CPC_MSG_TYPE_OVERRUN         21 /* overrun events */
+#define CPC_MSG_TYPE_CAN_FRAME_ERROR 23 /* detected bus errors */
+#define CPC_MSG_TYPE_ERR_COUNTER     25 /* RX/TX error counter */
+
+/* Messages from the PC to the CPC interface  */
+#define CPC_CMD_TYPE_CAN_FRAME     1   /* CAN data frame */
+#define CPC_CMD_TYPE_CONTROL       3   /* control of interface behavior */
+#define CPC_CMD_TYPE_CAN_PARAMS    6   /* set CAN parameters */
+#define CPC_CMD_TYPE_RTR_FRAME     13  /* CAN remote frame */
+#define CPC_CMD_TYPE_CAN_STATE     14  /* CAN state message */
+#define CPC_CMD_TYPE_EXT_CAN_FRAME 15  /* Extended CAN data frame */
+#define CPC_CMD_TYPE_EXT_RTR_FRAME 16  /* Extended CAN remote frame */
+#define CPC_CMD_TYPE_CAN_EXIT      200 /* exit the CAN */
+
+#define CPC_CMD_TYPE_INQ_ERR_COUNTER 25 /* request the CAN error counters */
+#define CPC_CMD_TYPE_CLEAR_MSG_QUEUE 8  /* clear CPC_MSG queue */
+#define CPC_CMD_TYPE_CLEAR_CMD_QUEUE 28 /* clear CPC_CMD queue */
+
+#define CPC_CC_TYPE_SJA1000 2 /* Philips basic CAN controller */
+
+#define CPC_CAN_ECODE_ERRFRAME 0x01 /* Ecode type */
+
+/* Overrun types */
+#define CPC_OVR_EVENT_CAN       0x01
+#define CPC_OVR_EVENT_CANSTATE  0x02
+#define CPC_OVR_EVENT_BUSERROR  0x04
+
+/*
+ * If the CAN controller lost a message we indicate it with the highest bit
+ * set in the count field.
+ */
+#define CPC_OVR_HW 0x80
+
+/* Size of the "struct ems_cpc_msg" without the union */
+#define CPC_MSG_HEADER_LEN   11
+#define CPC_CAN_MSG_MIN_SIZE 5
+
+/* Define these values to match your devices */
+#define USB_CPCUSB_VENDOR_ID 0x12D6
+
+#define USB_CPCUSB_ARM7_PRODUCT_ID 0x0444
+
+/* Mode register NXP LPC2119/SJA1000 CAN Controller */
+#define SJA1000_MOD_NORMAL 0x00
+#define SJA1000_MOD_RM     0x01
+
+/* ECC register NXP LPC2119/SJA1000 CAN Controller */
+#define SJA1000_ECC_SEG   0x1F
+#define SJA1000_ECC_DIR   0x20
+#define SJA1000_ECC_ERR   0x06
+#define SJA1000_ECC_BIT   0x00
+#define SJA1000_ECC_FORM  0x40
+#define SJA1000_ECC_STUFF 0x80
+#define SJA1000_ECC_MASK  0xc0
+
+/* Status register content */
+#define SJA1000_SR_BS 0x80
+#define SJA1000_SR_ES 0x40
+
+#define SJA1000_DEFAULT_OUTPUT_CONTROL 0xDA
+
+#define EMS_USB_ARM7_CLOCK 8000000
+
+/*
+ * CAN-Message representation in a CPC_MSG. Message object type is
+ * CPC_MSG_TYPE_CAN_FRAME or CPC_MSG_TYPE_RTR_FRAME or
+ * CPC_MSG_TYPE_EXT_CAN_FRAME or CPC_MSG_TYPE_EXT_RTR_FRAME.
+ */
+struct cpc_can_msg {
+	u32 id;
+	u8 length;
+	u8 msg[8];
+};
+
+/* Representation of the CAN parameters for the SJA1000 controller */
+struct cpc_sja1000_params {
+	u8 mode;
+	u8 acc_code0;
+	u8 acc_code1;
+	u8 acc_code2;
+	u8 acc_code3;
+	u8 acc_mask0;
+	u8 acc_mask1;
+	u8 acc_mask2;
+	u8 acc_mask3;
+	u8 btr0;
+	u8 btr1;
+	u8 outp_contr;
+};
+
+/* CAN params message representation */
+struct cpc_can_params {
+	u8 cc_type;
+
+	/* Will support M16C CAN controller in the future */
+	union {
+		struct cpc_sja1000_params sja1000;
+	} cc_params;
+};
+
+/* Structure for confirmed message handling */
+struct cpc_confirm {
+	u8 error; /* error code */
+};
+
+/* Structure for overrun conditions */
+struct cpc_overrun {
+	u8 event;
+	u8 count;
+};
+
+/* SJA1000 CAN errors (compatible to NXP LPC2119) */
+struct cpc_sja1000_can_error {
+	u8 ecc;
+	u8 rxerr;
+	u8 txerr;
+};
+
+/* structure for CAN error conditions */
+struct cpc_can_error {
+	u8 ecode;
+
+	struct {
+		u8 cc_type;
+
+		/* Other controllers may also provide error code capture regs */
+		union {
+			struct cpc_sja1000_can_error sja1000;
+		} regs;
+	} cc;
+};
+
+/*
+ * Structure containing RX/TX error counter. This structure is used to request
+ * the values of the CAN controllers TX and RX error counter.
+ */
+struct cpc_can_err_counter {
+	u8 rx;
+	u8 tx;
+};
+
+/* Main message type used between library and application */
+struct __attribute__ ((packed)) ems_cpc_msg {
+	u8 type;	/* type of message */
+	u8 length;	/* length of data within union 'msg' */
+	u8 msgid;	/* confirmation handle */
+	u32 ts_sec;	/* timestamp in seconds */
+	u32 ts_nsec;	/* timestamp in nano seconds */
+
+	union {
+		u8 generic[64];
+		struct cpc_can_msg can_msg;
+		struct cpc_can_params can_params;
+		struct cpc_confirm confirmation;
+		struct cpc_overrun overrun;
+		struct cpc_can_error error;
+		struct cpc_can_err_counter err_counter;
+		u8 can_state;
+	} msg;
+};
+
+/*
+ * Table of devices that work with this driver
+ * NOTE: This driver supports only CPC-USB/ARM7 (LPC2119) yet.
+ */
+static struct usb_device_id ems_usb_table[] = {
+	{USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_ARM7_PRODUCT_ID)},
+	{} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, ems_usb_table);
+
+#define RX_BUFFER_SIZE      64
+#define CPC_HEADER_SIZE     4
+#define INTR_IN_BUFFER_SIZE 4
+
+#define MAX_RX_URBS 10
+#define MAX_TX_URBS CAN_ECHO_SKB_MAX
+
+struct ems_usb;
+
+struct ems_tx_urb_context {
+	struct ems_usb *dev;
+
+	u32 echo_index;
+	u8 dlc;
+};
+
+struct ems_usb {
+	struct can_priv can; /* must be the first member */
+	int open_time;
+
+	struct sk_buff *echo_skb[MAX_TX_URBS];
+
+	struct usb_device *udev;
+	struct net_device *netdev;
+
+	atomic_t active_tx_urbs;
+	struct usb_anchor tx_submitted;
+	struct ems_tx_urb_context tx_contexts[MAX_TX_URBS];
+
+	struct usb_anchor rx_submitted;
+
+	struct urb *intr_urb;
+
+	u8 *tx_msg_buffer;
+
+	u8 *intr_in_buffer;
+	unsigned int free_slots; /* remember number of available slots */
+
+	struct ems_cpc_msg active_params; /* active controller parameters */
+};
+
+static void ems_usb_read_interrupt_callback(struct urb *urb)
+{
+	struct ems_usb *dev = urb->context;
+	struct net_device *netdev = dev->netdev;
+	int err;
+
+	if (!netif_device_present(netdev))
+		return;
+
+	switch (urb->status) {
+	case 0:
+		dev->free_slots = dev->intr_in_buffer[1];
+		break;
+
+	case -ECONNRESET: /* unlink */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+
+	default:
+		dev_info(netdev->dev.parent, "Rx interrupt aborted %d\n",
+			 urb->status);
+		break;
+	}
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+
+	if (err == -ENODEV)
+		netif_device_detach(netdev);
+	else if (err)
+		dev_err(netdev->dev.parent,
+			"failed resubmitting intr urb: %d\n", err);
+
+	return;
+}
+
+static void ems_usb_rx_can_msg(struct ems_usb *dev, struct ems_cpc_msg *msg)
+{
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	int i;
+	struct net_device_stats *stats = &dev->netdev->stats;
+
+	skb = netdev_alloc_skb(dev->netdev, sizeof(struct can_frame));
+	if (skb == NULL)
+		return;
+
+	skb->protocol = htons(ETH_P_CAN);
+
+	cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+
+	cf->can_id = msg->msg.can_msg.id;
+	cf->can_dlc = min_t(u8, msg->msg.can_msg.length, 8);
+
+	if (msg->type == CPC_MSG_TYPE_EXT_CAN_FRAME
+	    || msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME)
+		cf->can_id |= CAN_EFF_FLAG;
+
+	if (msg->type == CPC_MSG_TYPE_RTR_FRAME
+	    || msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME) {
+		cf->can_id |= CAN_RTR_FLAG;
+	} else {
+		for (i = 0; i < cf->can_dlc; i++)
+			cf->data[i] = msg->msg.can_msg.msg[i];
+	}
+
+	netif_rx(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+}
+
+static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
+{
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	struct net_device_stats *stats = &dev->netdev->stats;
+
+	skb = netdev_alloc_skb(dev->netdev, sizeof(struct can_frame));
+	if (skb == NULL)
+		return;
+
+	skb->protocol = htons(ETH_P_CAN);
+
+	cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+	memset(cf, 0, sizeof(struct can_frame));
+
+	cf->can_id = CAN_ERR_FLAG;
+	cf->can_dlc = CAN_ERR_DLC;
+
+	if (msg->type == CPC_MSG_TYPE_CAN_STATE) {
+		u8 state = msg->msg.can_state;
+
+		if (state & SJA1000_SR_BS) {
+			dev->can.state = CAN_STATE_BUS_OFF;
+			cf->can_id |= CAN_ERR_BUSOFF;
+
+			can_bus_off(dev->netdev);
+		} else if (state & SJA1000_SR_ES) {
+			dev->can.state = CAN_STATE_ERROR_WARNING;
+			dev->can.can_stats.error_warning++;
+		} else {
+			dev->can.state = CAN_STATE_ERROR_ACTIVE;
+			dev->can.can_stats.error_passive++;
+		}
+	} else if (msg->type == CPC_MSG_TYPE_CAN_FRAME_ERROR) {
+		u8 ecc = msg->msg.error.cc.regs.sja1000.ecc;
+		u8 txerr = msg->msg.error.cc.regs.sja1000.txerr;
+		u8 rxerr = msg->msg.error.cc.regs.sja1000.rxerr;
+
+		/* bus error interrupt */
+		dev->can.can_stats.bus_error++;
+		stats->rx_errors++;
+
+		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+		switch (ecc & SJA1000_ECC_MASK) {
+		case SJA1000_ECC_BIT:
+			cf->data[2] |= CAN_ERR_PROT_BIT;
+			break;
+		case SJA1000_ECC_FORM:
+			cf->data[2] |= CAN_ERR_PROT_FORM;
+			break;
+		case SJA1000_ECC_STUFF:
+			cf->data[2] |= CAN_ERR_PROT_STUFF;
+			break;
+		default:
+			cf->data[2] |= CAN_ERR_PROT_UNSPEC;
+			cf->data[3] = ecc & SJA1000_ECC_SEG;
+			break;
+		}
+
+		/* Error occured during transmission? */
+		if ((ecc & SJA1000_ECC_DIR) == 0)
+			cf->data[2] |= CAN_ERR_PROT_TX;
+
+		if (dev->can.state == CAN_STATE_ERROR_WARNING ||
+		    dev->can.state == CAN_STATE_ERROR_PASSIVE) {
+			cf->data[1] = (txerr > rxerr) ?
+			    CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE;
+		}
+	} else if (msg->type == CPC_MSG_TYPE_OVERRUN) {
+		cf->can_id |= CAN_ERR_CRTL;
+		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+
+		stats->rx_over_errors++;
+		stats->rx_errors++;
+	}
+
+	netif_rx(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+}
+
+/*
+ * callback for bulk IN urb
+ */
+static void ems_usb_read_bulk_callback(struct urb *urb)
+{
+	struct ems_usb *dev = urb->context;
+	struct net_device *netdev;
+	int retval;
+
+	netdev = dev->netdev;
+
+	if (!netif_device_present(netdev))
+		return;
+
+	switch (urb->status) {
+	case 0: /* success */
+		break;
+
+	case -ENOENT:
+		return;
+
+	default:
+		dev_info(netdev->dev.parent, "Rx URB aborted (%d)\n",
+			 urb->status);
+		goto resubmit_urb;
+	}
+
+	if (urb->actual_length > CPC_HEADER_SIZE) {
+		struct ems_cpc_msg *msg;
+		u8 *ibuf = urb->transfer_buffer;
+		u8 msg_count, again, start;
+
+		msg_count = ibuf[0] & ~0x80;
+		again = ibuf[0] & 0x80;
+
+		start = CPC_HEADER_SIZE;
+
+		while (msg_count) {
+			msg = (struct ems_cpc_msg *)&ibuf[start];
+
+			switch (msg->type) {
+			case CPC_MSG_TYPE_CAN_STATE:
+				/* Process CAN state changes */
+				ems_usb_rx_err(dev, msg);
+				break;
+
+			case CPC_MSG_TYPE_CAN_FRAME:
+			case CPC_MSG_TYPE_EXT_CAN_FRAME:
+			case CPC_MSG_TYPE_RTR_FRAME:
+			case CPC_MSG_TYPE_EXT_RTR_FRAME:
+				ems_usb_rx_can_msg(dev, msg);
+				break;
+
+			case CPC_MSG_TYPE_CAN_FRAME_ERROR:
+				/* Process errorframe */
+				ems_usb_rx_err(dev, msg);
+				break;
+
+			case CPC_MSG_TYPE_OVERRUN:
+				/* Message lost while receiving */
+				ems_usb_rx_err(dev, msg);
+				break;
+			}
+
+			start += CPC_MSG_HEADER_LEN + msg->length;
+			msg_count--;
+
+			if (start > urb->transfer_buffer_length) {
+				dev_err(netdev->dev.parent, "format error\n");
+				break;
+			}
+		}
+	}
+
+resubmit_urb:
+	usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2),
+			  urb->transfer_buffer, RX_BUFFER_SIZE,
+			  ems_usb_read_bulk_callback, dev);
+
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+
+	if (retval == -ENODEV)
+		netif_device_detach(netdev);
+	else if (retval)
+		dev_err(netdev->dev.parent,
+			"failed resubmitting read bulk urb: %d\n", retval);
+
+	return;
+}
+
+/*
+ * callback for bulk IN urb
+ */
+static void ems_usb_write_bulk_callback(struct urb *urb)
+{
+	struct ems_tx_urb_context *context = urb->context;
+	struct ems_usb *dev;
+	struct net_device *netdev;
+
+	BUG_ON(!context);
+
+	dev = context->dev;
+	netdev = dev->netdev;
+
+	/* free up our allocated buffer */
+	usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+			urb->transfer_buffer, urb->transfer_dma);
+
+	atomic_dec(&dev->active_tx_urbs);
+
+	if (!netif_device_present(netdev))
+		return;
+
+	if (urb->status)
+		dev_info(netdev->dev.parent, "Tx URB aborted (%d)\n",
+			 urb->status);
+
+	netdev->trans_start = jiffies;
+
+	/* transmission complete interrupt */
+	netdev->stats.tx_packets++;
+	netdev->stats.tx_bytes += context->dlc;
+
+	can_get_echo_skb(netdev, context->echo_index);
+
+	/* Release context */
+	context->echo_index = MAX_TX_URBS;
+
+	if (netif_queue_stopped(netdev))
+		netif_wake_queue(netdev);
+}
+
+/*
+ * Send the given CPC command synchronously
+ */
+static int ems_usb_command_msg(struct ems_usb *dev, struct ems_cpc_msg *msg)
+{
+	int actual_length;
+
+	/* Copy payload */
+	memcpy(&dev->tx_msg_buffer[CPC_HEADER_SIZE], msg,
+	       msg->length + CPC_MSG_HEADER_LEN);
+
+	/* Clear header */
+	memset(&dev->tx_msg_buffer[0], 0, CPC_HEADER_SIZE);
+
+	return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
+			    &dev->tx_msg_buffer[0],
+			    msg->length + CPC_MSG_HEADER_LEN + CPC_HEADER_SIZE,
+			    &actual_length, 1000);
+}
+
+/*
+ * Change CAN controllers' mode register
+ */
+static int ems_usb_write_mode(struct ems_usb *dev, u8 mode)
+{
+	dev->active_params.msg.can_params.cc_params.sja1000.mode = mode;
+
+	return ems_usb_command_msg(dev, &dev->active_params);
+}
+
+/*
+ * Send a CPC_Control command to change behaviour when interface receives a CAN
+ * message, bus error or CAN state changed notifications.
+ */
+static int ems_usb_control_cmd(struct ems_usb *dev, u8 val)
+{
+	struct ems_cpc_msg cmd;
+
+	cmd.type = CPC_CMD_TYPE_CONTROL;
+	cmd.length = CPC_MSG_HEADER_LEN + 1;
+
+	cmd.msgid = 0;
+
+	cmd.msg.generic[0] = val;
+
+	return ems_usb_command_msg(dev, &cmd);
+}
+
+/*
+ * Start interface
+ */
+static int ems_usb_start(struct ems_usb *dev)
+{
+	struct net_device *netdev = dev->netdev;
+	int err, i;
+
+	dev->intr_in_buffer[0] = 0;
+	dev->free_slots = 15; /* initial size */
+
+	for (i = 0; i < MAX_RX_URBS; i++) {
+		struct urb *urb = NULL;
+		u8 *buf = NULL;
+
+		/* create a URB, and a buffer for it */
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			dev_err(netdev->dev.parent,
+				"No memory left for URBs\n");
+			return -ENOMEM;
+		}
+
+		buf = usb_buffer_alloc(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
+				       &urb->transfer_dma);
+		if (!buf) {
+			dev_err(netdev->dev.parent,
+				"No memory left for USB buffer\n");
+			usb_free_urb(urb);
+			return -ENOMEM;
+		}
+
+		usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2),
+				  buf, RX_BUFFER_SIZE,
+				  ems_usb_read_bulk_callback, dev);
+		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+		usb_anchor_urb(urb, &dev->rx_submitted);
+
+		err = usb_submit_urb(urb, GFP_KERNEL);
+		if (err) {
+			if (err == -ENODEV)
+				netif_device_detach(dev->netdev);
+
+			usb_unanchor_urb(urb);
+			usb_buffer_free(dev->udev, RX_BUFFER_SIZE, buf,
+					urb->transfer_dma);
+			break;
+		}
+
+		/* Drop reference, USB core will take care of freeing it */
+		usb_free_urb(urb);
+	}
+
+	/* Did we submit any URBs */
+	if (i == 0) {
+		dev_warn(netdev->dev.parent, "couldn't setup read URBs\n");
+		return err;
+	}
+
+	/* Warn if we've couldn't transmit all the URBs */
+	if (i < MAX_RX_URBS)
+		dev_warn(netdev->dev.parent, "rx performance may be slow\n");
+
+	/* Setup and start interrupt URB */
+	usb_fill_int_urb(dev->intr_urb, dev->udev,
+			 usb_rcvintpipe(dev->udev, 1),
+			 dev->intr_in_buffer,
+			 INTR_IN_BUFFER_SIZE,
+			 ems_usb_read_interrupt_callback, dev, 1);
+
+	err = usb_submit_urb(dev->intr_urb, GFP_KERNEL);
+	if (err) {
+		if (err == -ENODEV)
+			netif_device_detach(dev->netdev);
+
+		dev_warn(netdev->dev.parent, "intr URB submit failed: %d\n",
+			 err);
+
+		return err;
+	}
+
+	/* CPC-USB will transfer received message to host */
+	err = ems_usb_control_cmd(dev, CONTR_CAN_MESSAGE | CONTR_CONT_ON);
+	if (err)
+		goto failed;
+
+	/* CPC-USB will transfer CAN state changes to host */
+	err = ems_usb_control_cmd(dev, CONTR_CAN_STATE | CONTR_CONT_ON);
+	if (err)
+		goto failed;
+
+	/* CPC-USB will transfer bus errors to host */
+	err = ems_usb_control_cmd(dev, CONTR_BUS_ERROR | CONTR_CONT_ON);
+	if (err)
+		goto failed;
+
+	err = ems_usb_write_mode(dev, SJA1000_MOD_NORMAL);
+	if (err)
+		goto failed;
+
+	dev->can.state = CAN_STATE_ERROR_ACTIVE;
+
+	return 0;
+
+failed:
+	if (err == -ENODEV)
+		netif_device_detach(dev->netdev);
+
+	dev_warn(netdev->dev.parent, "couldn't submit control: %d\n", err);
+
+	return err;
+}
+
+static void unlink_all_urbs(struct ems_usb *dev)
+{
+	int i;
+
+	usb_unlink_urb(dev->intr_urb);
+
+	usb_kill_anchored_urbs(&dev->rx_submitted);
+
+	usb_kill_anchored_urbs(&dev->tx_submitted);
+	atomic_set(&dev->active_tx_urbs, 0);
+
+	for (i = 0; i < MAX_TX_URBS; i++)
+		dev->tx_contexts[i].echo_index = MAX_TX_URBS;
+}
+
+static int ems_usb_open(struct net_device *netdev)
+{
+	struct ems_usb *dev = netdev_priv(netdev);
+	int err;
+
+	err = ems_usb_write_mode(dev, SJA1000_MOD_RM);
+	if (err)
+		return err;
+
+	/* common open */
+	err = open_candev(netdev);
+	if (err)
+		return err;
+
+	/* finally start device */
+	err = ems_usb_start(dev);
+	if (err) {
+		if (err == -ENODEV)
+			netif_device_detach(dev->netdev);
+
+		dev_warn(netdev->dev.parent, "couldn't start device: %d\n",
+			 err);
+
+		close_candev(netdev);
+
+		return err;
+	}
+
+	dev->open_time = jiffies;
+
+	netif_start_queue(netdev);
+
+	return 0;
+}
+
+static int ems_usb_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct ems_usb *dev = netdev_priv(netdev);
+	struct ems_tx_urb_context *context = NULL;
+	struct net_device_stats *stats = &netdev->stats;
+	struct can_frame *cf = (struct can_frame *)skb->data;
+	struct ems_cpc_msg *msg;
+	struct urb *urb;
+	u8 *buf;
+	int i, err;
+	size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN
+			+ sizeof(struct cpc_can_msg);
+
+	/* create a URB, and a buffer for it, and copy the data to the URB */
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		dev_err(netdev->dev.parent, "No memory left for URBs\n");
+		goto nomem;
+	}
+
+	buf = usb_buffer_alloc(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma);
+	if (!buf) {
+		dev_err(netdev->dev.parent, "No memory left for USB buffer\n");
+		usb_free_urb(urb);
+		goto nomem;
+	}
+
+	msg = (struct ems_cpc_msg *)&buf[CPC_HEADER_SIZE];
+
+	msg->msg.can_msg.id = cf->can_id & CAN_ERR_MASK;
+	msg->msg.can_msg.length = cf->can_dlc;
+
+	if (cf->can_id & CAN_RTR_FLAG) {
+		msg->type = cf->can_id & CAN_EFF_FLAG ?
+			CPC_CMD_TYPE_EXT_RTR_FRAME : CPC_CMD_TYPE_RTR_FRAME;
+
+		msg->length = CPC_CAN_MSG_MIN_SIZE;
+	} else {
+		msg->type = cf->can_id & CAN_EFF_FLAG ?
+			CPC_CMD_TYPE_EXT_CAN_FRAME : CPC_CMD_TYPE_CAN_FRAME;
+
+		for (i = 0; i < cf->can_dlc; i++)
+			msg->msg.can_msg.msg[i] = cf->data[i];
+
+		msg->length = CPC_CAN_MSG_MIN_SIZE + cf->can_dlc;
+	}
+
+	for (i = 0; i < MAX_TX_URBS; i++) {
+		if (dev->tx_contexts[i].echo_index == MAX_TX_URBS) {
+			context = &dev->tx_contexts[i];
+			break;
+		}
+	}
+
+	/*
+	 * May never happen! When this happens we'd more URBs in flight as
+	 * allowed (MAX_TX_URBS).
+	 */
+	if (!context) {
+		usb_unanchor_urb(urb);
+		usb_buffer_free(dev->udev, size, buf, urb->transfer_dma);
+
+		dev_warn(netdev->dev.parent, "couldn't find free context\n");
+
+		return NETDEV_TX_BUSY;
+	}
+
+	context->dev = dev;
+	context->echo_index = i;
+	context->dlc = cf->can_dlc;
+
+	usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf,
+			  size, ems_usb_write_bulk_callback, context);
+	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	usb_anchor_urb(urb, &dev->tx_submitted);
+
+	can_put_echo_skb(skb, netdev, context->echo_index);
+
+	atomic_inc(&dev->active_tx_urbs);
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (unlikely(err)) {
+		can_free_echo_skb(netdev, context->echo_index);
+
+		usb_unanchor_urb(urb);
+		usb_buffer_free(dev->udev, size, buf, urb->transfer_dma);
+		dev_kfree_skb(skb);
+
+		atomic_dec(&dev->active_tx_urbs);
+
+		if (err == -ENODEV) {
+			netif_device_detach(netdev);
+		} else {
+			dev_warn(netdev->dev.parent, "failed tx_urb %d\n", err);
+
+			stats->tx_dropped++;
+		}
+	} else {
+		netdev->trans_start = jiffies;
+
+		/* Slow down tx path */
+		if (atomic_read(&dev->active_tx_urbs) >= MAX_TX_URBS ||
+		    dev->free_slots < 5) {
+			netif_stop_queue(netdev);
+		}
+	}
+
+	/*
+	 * Release our reference to this URB, the USB core will eventually free
+	 * it entirely.
+	 */
+	usb_free_urb(urb);
+
+	return NETDEV_TX_OK;
+
+nomem:
+	if (skb)
+		dev_kfree_skb(skb);
+
+	stats->tx_dropped++;
+
+	return NETDEV_TX_OK;
+}
+
+static int ems_usb_close(struct net_device *netdev)
+{
+	struct ems_usb *dev = netdev_priv(netdev);
+
+	/* Stop polling */
+	unlink_all_urbs(dev);
+
+	netif_stop_queue(netdev);
+
+	/* Set CAN controller to reset mode */
+	if (ems_usb_write_mode(dev, SJA1000_MOD_RM))
+		dev_warn(netdev->dev.parent, "couldn't stop device");
+
+	close_candev(netdev);
+
+	dev->open_time = 0;
+
+	return 0;
+}
+
+static const struct net_device_ops ems_usb_netdev_ops = {
+	.ndo_open = ems_usb_open,
+	.ndo_stop = ems_usb_close,
+	.ndo_start_xmit = ems_usb_start_xmit,
+};
+
+static struct can_bittiming_const ems_usb_bittiming_const = {
+	.name = "ems_usb",
+	.tseg1_min = 1,
+	.tseg1_max = 16,
+	.tseg2_min = 1,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 64,
+	.brp_inc = 1,
+};
+
+static int ems_usb_set_mode(struct net_device *netdev, enum can_mode mode)
+{
+	struct ems_usb *dev = netdev_priv(netdev);
+
+	if (!dev->open_time)
+		return -EINVAL;
+
+	switch (mode) {
+	case CAN_MODE_START:
+		if (ems_usb_write_mode(dev, SJA1000_MOD_NORMAL))
+			dev_warn(netdev->dev.parent, "couldn't start device");
+
+		if (netif_queue_stopped(netdev))
+			netif_wake_queue(netdev);
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int ems_usb_set_bittiming(struct net_device *netdev)
+{
+	struct ems_usb *dev = netdev_priv(netdev);
+	struct can_bittiming *bt = &dev->can.bittiming;
+	u8 btr0, btr1;
+
+	btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
+	btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
+		(((bt->phase_seg2 - 1) & 0x7) << 4);
+	if (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+		btr1 |= 0x80;
+
+	dev_info(netdev->dev.parent, "setting BTR0=0x%02x BTR1=0x%02x\n",
+		 btr0, btr1);
+
+	dev->active_params.msg.can_params.cc_params.sja1000.btr0 = btr0;
+	dev->active_params.msg.can_params.cc_params.sja1000.btr1 = btr1;
+
+	return ems_usb_command_msg(dev, &dev->active_params);
+}
+
+static void init_params_sja1000(struct ems_cpc_msg *msg)
+{
+	struct cpc_sja1000_params *sja1000 =
+		&msg->msg.can_params.cc_params.sja1000;
+
+	msg->type = CPC_CMD_TYPE_CAN_PARAMS;
+	msg->length = sizeof(struct cpc_can_params);
+	msg->msgid = 0;
+
+	msg->msg.can_params.cc_type = CPC_CC_TYPE_SJA1000;
+
+	/* Acceptance filter open */
+	sja1000->acc_code0 = 0x00;
+	sja1000->acc_code1 = 0x00;
+	sja1000->acc_code2 = 0x00;
+	sja1000->acc_code3 = 0x00;
+
+	/* Acceptance filter open */
+	sja1000->acc_mask0 = 0xFF;
+	sja1000->acc_mask1 = 0xFF;
+	sja1000->acc_mask2 = 0xFF;
+	sja1000->acc_mask3 = 0xFF;
+
+	sja1000->btr0 = 0;
+	sja1000->btr1 = 0;
+
+	sja1000->outp_contr = SJA1000_DEFAULT_OUTPUT_CONTROL;
+	sja1000->mode = SJA1000_MOD_RM;
+}
+
+/*
+ * probe function for new CPC-USB devices
+ */
+static int ems_usb_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct net_device *netdev;
+	struct ems_usb *dev;
+	int i, err;
+	int retval = -ENOMEM;
+
+	netdev = alloc_candev(sizeof(struct ems_usb));
+	if (!netdev) {
+		dev_err(netdev->dev.parent, "Couldn't alloc candev\n");
+		return -ENOMEM;
+	}
+
+	dev = netdev_priv(netdev);
+
+	dev->udev = interface_to_usbdev(intf);
+	dev->netdev = netdev;
+
+	dev->can.state = CAN_STATE_STOPPED;
+	dev->can.clock.freq = EMS_USB_ARM7_CLOCK;
+	dev->can.bittiming_const = &ems_usb_bittiming_const;
+	dev->can.do_set_bittiming = ems_usb_set_bittiming;
+	dev->can.do_set_mode = ems_usb_set_mode;
+
+	netdev->flags |= IFF_ECHO; /* we support local echo */
+
+	/*
+	 * The device actually uses a 16MHz clock to generate the CAN clock
+	 * but it expects SJA1000 bit settings based on 8MHz (is internally
+	 * converted).
+	 */
+
+	netdev->netdev_ops = &ems_usb_netdev_ops;
+
+	netdev->flags |= IFF_ECHO; /* we support local echo */
+
+	init_usb_anchor(&dev->rx_submitted);
+
+	init_usb_anchor(&dev->tx_submitted);
+	atomic_set(&dev->active_tx_urbs, 0);
+
+	for (i = 0; i < MAX_TX_URBS; i++)
+		dev->tx_contexts[i].echo_index = MAX_TX_URBS;
+
+	dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->intr_urb) {
+		dev_err(netdev->dev.parent, "Couldn't alloc intr URB\n");
+		goto cleanup_candev;
+	}
+
+	dev->intr_in_buffer = kzalloc(INTR_IN_BUFFER_SIZE, GFP_KERNEL);
+	if (!dev->intr_in_buffer) {
+		dev_err(netdev->dev.parent, "Couldn't alloc Intr buffer\n");
+		goto cleanup_intr_urb;
+	}
+
+	dev->tx_msg_buffer = kzalloc(CPC_HEADER_SIZE +
+				     sizeof(struct ems_cpc_msg), GFP_KERNEL);
+	if (!dev->tx_msg_buffer) {
+		dev_err(netdev->dev.parent, "Couldn't alloc Tx buffer\n");
+		goto cleanup_intr_in_buffer;
+	}
+
+	usb_set_intfdata(intf, dev);
+
+	SET_NETDEV_DEV(netdev, &intf->dev);
+
+	init_params_sja1000(&dev->active_params);
+
+	err = ems_usb_command_msg(dev, &dev->active_params);
+	if (err) {
+		dev_err(netdev->dev.parent,
+			"couldn't initialize controller: %d\n", err);
+		retval = err;
+		goto cleanup_tx_msg_buffer;
+	}
+
+	return register_candev(netdev);
+
+cleanup_tx_msg_buffer:
+	kfree(dev->tx_msg_buffer);
+
+cleanup_intr_in_buffer:
+	kfree(dev->intr_in_buffer);
+
+cleanup_intr_urb:
+	usb_free_urb(dev->intr_urb);
+
+cleanup_candev:
+	free_candev(netdev);
+
+	return retval;
+}
+
+/*
+ * called by the usb core when the device is removed from the system
+ */
+static void ems_usb_disconnect(struct usb_interface *intf)
+{
+	struct ems_usb *dev = usb_get_intfdata(intf);
+
+	usb_set_intfdata(intf, NULL);
+
+	if (dev) {
+		unregister_netdev(dev->netdev);
+		free_candev(dev->netdev);
+
+		unlink_all_urbs(dev);
+
+		usb_free_urb(dev->intr_urb);
+
+		kfree(dev->intr_in_buffer);
+	}
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver ems_usb_driver = {
+	.name = "ems_usb",
+	.probe = ems_usb_probe,
+	.disconnect = ems_usb_disconnect,
+	.id_table = ems_usb_table,
+};
+
+static int __init ems_usb_init(void)
+{
+	int err;
+
+	printk(KERN_INFO "CPC-USB kernel driver loaded\n");
+
+	/* register this driver with the USB subsystem */
+	err = usb_register(&ems_usb_driver);
+
+	if (err) {
+		err("usb_register failed. Error number %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static void __exit ems_usb_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&ems_usb_driver);
+}
+
+module_init(ems_usb_init);
+module_exit(ems_usb_exit);

-- 
EMS Dr. Thomas Wuensche e.K.
Sonnenhang 3
85304 Ilmmuenster
HRA Neuburg a.d. Donau, HR-Nr. 70.106
Phone: +49-8441-490260
Fax  : +49-8441-81860
http://www.ems-wuensche.com

^ permalink raw reply related

* hello dearest
From: vera_dona4 @ 2009-09-16  9:04 UTC (permalink / raw)


How are you ? I guess you are fine and living good. my name is vera a beautiful young girl I find you and i'm interesting to know you and establish a serious relationship with you. I wanna be your friend for first friendship cannot be seen or even be touched, it must be felt within the heart.Hoping you feel just the way i do. Wow! friends are like clothes without them you feel naked!I guess am right.I will tell you more about me, my family and all that maybe necessary in this relationship, If this is okay by you feel free to contact me as to enable us get to know each other better. Have a wonderful day with lot of happiness.
best regards

^ permalink raw reply

* Re: [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: Daniel Walker @ 2009-09-16  9:10 UTC (permalink / raw)
  To: jie.yang; +Cc: davem, miles.lane, chris.snook, jcliburn, netdev, linux-kernel
In-Reply-To: <12530821133392-git-send-email-jie.yang@atheros.com>

On Wed, 2009-09-16 at 14:21 +0800, jie.yang@atheros.com wrote:
> -           pci_unmap_page(pdev, tx_buffer->dma,
> +           if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
> +               pci_unmap_single(pdev, tx_buffer->dma,
> +                   tx_buffer->length, PCI_DMA_TODEVICE);
> +           else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
> +               pci_unmap_page(pdev, tx_buffer->dma,

Could you run this through checkpatch, and fix any errors if find? It
looks like you uses spaces for tabs in the code above, maybe in the
other block too..

Daniel

^ permalink raw reply

* Re: [E1000-devel] [BUG 2.6.30+] e100 sometimes causes oops during resume
From: Karol Lewandowski @ 2009-09-16  9:19 UTC (permalink / raw)
  To: Karol Lewandowski
  Cc: Graham, David, Rafael J. Wysocki, linux-kernel@vger.kernel.org,
	e1000-devel@lists.sourceforge.net, netdev@vger.kernel.org
In-Reply-To: <20090916014448.GA1070@bizet.domek.prywatny>

On Wed, Sep 16, 2009 at 03:44:48AM +0200, Karol Lewandowski wrote:
> On Tue, Sep 15, 2009 at 03:54:20PM -0700, Graham, David wrote:
> 
> > A v2.6.30..v2.6.31 diff shows that this is probably exposed by
> > Rafael Wysocki's commit 6905b1f1, which now allows systems with e100
> > to sleep. If I understand correctly, it looks like these systems
> > simply couldn't sleep before. Is that right Rafael?.
> 
> Probably true, but that wasn't the case for my (I guess
> ACPI-controlled) system.
> 
> 
> > I don't think its likely that the commit is a direct cause of the
> > problem, but that the suspend/resume cycle now allows us to see
> > another issue.
> 
> From my (very limited) understanding commit message is at least in
> conflict with patch body.

No, it isn't, I must just go to bed earlier than 4AM. :/

Sorry for noise.

^ permalink raw reply

* Re: [PATCH V2 2/2] ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface
From: Wolfgang Grandegger @ 2009-09-16  9:26 UTC (permalink / raw)
  To: Sebastian Haas
  Cc: eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
	netdev-u79uwXL29TY76Z2rM5mHXA, oliver-GvhC2dPhHPQdnm+yROfE0A,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	oliver-fJ+pQTUTwRTk1uMJSBkQmQ, greg-U8xfFu+wG4EAvxtiuMwx3w,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <20090916090418.12370.16510.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>

Sebastian Haas wrote:
> This patch adds support for one channel CAN/USB interace CPC-USB/ARM7 from
> EMS Dr. Thomas Wuensche (http://www.ems-wuensche.com).
> 
> Signed-off-by: Sebastian Haas <haas-zsNKPWJ8Pib6hrUXjxyGrA@public.gmane.org>

The cleanup in the probe function is still not OK :-(.

> ---
> 
>  drivers/net/can/Kconfig       |    7 
>  drivers/net/can/Makefile      |    2 
>  drivers/net/can/usb/Makefile  |    5 
>  drivers/net/can/usb/ems_usb.c | 1151 +++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 1165 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/can/usb/Makefile
>  create mode 100644 drivers/net/can/usb/ems_usb.c
> 
> diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> index 0900743..6ac5aa5 100644
> --- a/drivers/net/can/Kconfig
> +++ b/drivers/net/can/Kconfig
> @@ -75,6 +75,13 @@ config CAN_EMS_PCI
>  	  CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
>  	  (http://www.ems-wuensche.de).
>  
> +config CAN_EMS_USB
> +	tristate "EMS CPC-USB/ARM7 CAN/USB interface"
> +	depends on USB && CAN_DEV
> +	---help---
> +	  This driver is for the one channel CPC-USB/ARM7 CAN/USB interface
> +	  from from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
> +
>  config CAN_KVASER_PCI
>  	tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
>  	depends on PCI && CAN_SJA1000
> diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
> index 523a941..9b035ec 100644
> --- a/drivers/net/can/Makefile
> +++ b/drivers/net/can/Makefile
> @@ -7,6 +7,8 @@ obj-$(CONFIG_CAN_VCAN)		+= vcan.o
>  obj-$(CONFIG_CAN_DEV)		+= can-dev.o
>  can-dev-y			:= dev.o
>  
> +obj-y				+= usb/
> +
>  obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
>  
>  ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
> diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile
> new file mode 100644
> index 0000000..c3f75ba
> --- /dev/null
> +++ b/drivers/net/can/usb/Makefile
> @@ -0,0 +1,5 @@
> +#
> +#  Makefile for the Linux Controller Area Network USB drivers.
> +#
> +
> +obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
> diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
[snip]
> +/*
> + * probe function for new CPC-USB devices
> + */
> +static int ems_usb_probe(struct usb_interface *intf,
> +			 const struct usb_device_id *id)
> +{
> +	struct net_device *netdev;
> +	struct ems_usb *dev;
> +	int i, err;
> +	int retval = -ENOMEM;

Why do you need an extra variable here.

	int err = -ENOMEM;

Should work fine!?

> +
> +	netdev = alloc_candev(sizeof(struct ems_usb));
> +	if (!netdev) {
> +		dev_err(netdev->dev.parent, "Couldn't alloc candev\n");
> +		return -ENOMEM;
> +	}
> +
> +	dev = netdev_priv(netdev);
> +
> +	dev->udev = interface_to_usbdev(intf);
> +	dev->netdev = netdev;
> +
> +	dev->can.state = CAN_STATE_STOPPED;
> +	dev->can.clock.freq = EMS_USB_ARM7_CLOCK;
> +	dev->can.bittiming_const = &ems_usb_bittiming_const;
> +	dev->can.do_set_bittiming = ems_usb_set_bittiming;
> +	dev->can.do_set_mode = ems_usb_set_mode;
> +
> +	netdev->flags |= IFF_ECHO; /* we support local echo */
> +
> +	/*
> +	 * The device actually uses a 16MHz clock to generate the CAN clock
> +	 * but it expects SJA1000 bit settings based on 8MHz (is internally
> +	 * converted).
> +	 */
> +
> +	netdev->netdev_ops = &ems_usb_netdev_ops;
> +
> +	netdev->flags |= IFF_ECHO; /* we support local echo */
> +
> +	init_usb_anchor(&dev->rx_submitted);
> +
> +	init_usb_anchor(&dev->tx_submitted);
> +	atomic_set(&dev->active_tx_urbs, 0);
> +
> +	for (i = 0; i < MAX_TX_URBS; i++)
> +		dev->tx_contexts[i].echo_index = MAX_TX_URBS;
> +
> +	dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
> +	if (!dev->intr_urb) {
> +		dev_err(netdev->dev.parent, "Couldn't alloc intr URB\n");
> +		goto cleanup_candev;
> +	}
> +
> +	dev->intr_in_buffer = kzalloc(INTR_IN_BUFFER_SIZE, GFP_KERNEL);
> +	if (!dev->intr_in_buffer) {
> +		dev_err(netdev->dev.parent, "Couldn't alloc Intr buffer\n");
> +		goto cleanup_intr_urb;
> +	}
> +
> +	dev->tx_msg_buffer = kzalloc(CPC_HEADER_SIZE +
> +				     sizeof(struct ems_cpc_msg), GFP_KERNEL);
> +	if (!dev->tx_msg_buffer) {
> +		dev_err(netdev->dev.parent, "Couldn't alloc Tx buffer\n");
> +		goto cleanup_intr_in_buffer;
> +	}
> +
> +	usb_set_intfdata(intf, dev);
> +
> +	SET_NETDEV_DEV(netdev, &intf->dev);
> +
> +	init_params_sja1000(&dev->active_params);
> +
> +	err = ems_usb_command_msg(dev, &dev->active_params);
> +	if (err) {
> +		dev_err(netdev->dev.parent,
> +			"couldn't initialize controller: %d\n", err);
> +		retval = err;

Could be removed then.

> +		goto cleanup_tx_msg_buffer;
> +	}
> +
> +	return register_candev(netdev);

Cleanup is missing if register_candev() fails!

> +
> +cleanup_tx_msg_buffer:
> +	kfree(dev->tx_msg_buffer);
> +
> +cleanup_intr_in_buffer:
> +	kfree(dev->intr_in_buffer);
> +
> +cleanup_intr_urb:
> +	usb_free_urb(dev->intr_urb);
> +
> +cleanup_candev:
> +	free_candev(netdev);
> +
> +	return retval;
> +}

Wolfgang.

^ permalink raw reply

* [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: jie.yang @ 2009-09-16  9:28 UTC (permalink / raw)
  To: davem; +Cc: miles.lane, chris.snook, jcliburn, netdev, linux-kernel, Jie Yang

use the wrong API when free dma. So when map dma use a flag to demostrate whether it is 'pci_map_single' or 'pci_map_page'. When free the dma, check the flags to select the right APIs('pci_unmap_single' or 'pci_unmap_page').

set the flags type to u16  instead of unsigned long  on David's comments.

Signed-off-by: Jie Yang <jie.yang@atheros.com>
---

diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/atl1e/atl1e.h
index ba48220..490d3b3 100644
--- a/drivers/net/atl1e/atl1e.h
+++ b/drivers/net/atl1e/atl1e.h
@@ -377,10 +377,19 @@ struct atl1e_hw {
  */
 struct atl1e_tx_buffer {
 	struct sk_buff *skb;
+	u16 flags;
+#define ATL1E_TX_PCIMAP_SINGLE		0x0001
+#define ATL1E_TX_PCIMAP_PAGE		0x0002
+#define ATL1E_TX_PCIMAP_TYPE_MASK	0x0003
 	u16 length;
 	dma_addr_t dma;
 };
 
+#define ATL1E_SET_PCIMAP_TYPE(tx_buff, type) do {		\
+	((tx_buff)->flags) &= ~ATL1E_TX_PCIMAP_TYPE_MASK;	\
+	((tx_buff)->flags) |= (type);				\
+	} while (0)
+
 struct atl1e_rx_page {
 	dma_addr_t	dma;    /* receive rage DMA address */
 	u8		*addr;   /* receive rage virtual address */
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index 69b830f..955da73 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -635,7 +635,11 @@ static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter)
 	for (index = 0; index < ring_count; index++) {
 		tx_buffer = &tx_ring->tx_buffer[index];
 		if (tx_buffer->dma) {
-			pci_unmap_page(pdev, tx_buffer->dma,
+			if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
+				pci_unmap_single(pdev, tx_buffer->dma,
+					tx_buffer->length, PCI_DMA_TODEVICE);
+			else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
+				pci_unmap_page(pdev, tx_buffer->dma,
 					tx_buffer->length, PCI_DMA_TODEVICE);
 			tx_buffer->dma = 0;
 		}
@@ -1220,7 +1224,11 @@ static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter)
 	while (next_to_clean != hw_next_to_clean) {
 		tx_buffer = &tx_ring->tx_buffer[next_to_clean];
 		if (tx_buffer->dma) {
-			pci_unmap_page(adapter->pdev, tx_buffer->dma,
+			if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
+				pci_unmap_single(adapter->pdev, tx_buffer->dma,
+					tx_buffer->length, PCI_DMA_TODEVICE);
+			else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
+				pci_unmap_page(adapter->pdev, tx_buffer->dma,
 					tx_buffer->length, PCI_DMA_TODEVICE);
 			tx_buffer->dma = 0;
 		}
@@ -1741,6 +1749,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
 		tx_buffer->length = map_len;
 		tx_buffer->dma = pci_map_single(adapter->pdev,
 					skb->data, hdr_len, PCI_DMA_TODEVICE);
+		ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
 		mapped_len += map_len;
 		use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
 		use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
@@ -1766,6 +1775,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
 		tx_buffer->dma =
 			pci_map_single(adapter->pdev, skb->data + mapped_len,
 					map_len, PCI_DMA_TODEVICE);
+		ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
 		mapped_len  += map_len;
 		use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
 		use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
@@ -1801,6 +1811,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
 						(i * MAX_TX_BUF_LEN),
 						tx_buffer->length,
 						PCI_DMA_TODEVICE);
+			ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE);
 			use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
 			use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
 					((cpu_to_le32(tx_buffer->length) &

^ permalink raw reply related

* RE: [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: Jie Yang @ 2009-09-16  9:31 UTC (permalink / raw)
  To: Daniel Walker
  Cc: davem@davemloft.net, miles.lane@gmail.com, chris.snook@gmail.com,
	jcliburn@gmail.com, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <1253092251.11643.569.camel@desktop>

On Wednesday, September 16, 2009 5:11 PM
Daniel Walker <dwalker@fifo99.com> wrote:

> On Wed, 2009-09-16 at 14:21 +0800, jie.yang@atheros.com wrote:
> > -           pci_unmap_page(pdev, tx_buffer->dma,
> > +           if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
> > +               pci_unmap_single(pdev, tx_buffer->dma,
> > +                   tx_buffer->length, PCI_DMA_TODEVICE);
> > +           else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
> > +               pci_unmap_page(pdev, tx_buffer->dma,
>
> Could you run this through checkpatch, and fix any errors if
> find? It looks like you uses spaces for tabs in the code
> above, maybe in the other block too..
>
> Daniel
>
>

ou, my mistake, just resend.

Best  wishes
jie

^ permalink raw reply

* [PATCH 0/3] at91_can: add support for Atmel's CAN controller on AT91SAM9263
From: Marc Kleine-Budde @ 2009-09-16  9:46 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

This patch series add support for Atmels's CAN controller as found
on the AT91SAM9263.

Marc Kleine-Budde (3):
      at91sam9263: add at91_can device to generic device definition
      at91sam9263ek: activate at91 CAN controller
      at91_can: add driver for Atmel's CAN controller on AT91SAM9263

 arch/arm/mach-at91/at91sam9263_devices.c |   36 +
 arch/arm/mach-at91/board-sam9263ek.c     |   19 +
 arch/arm/mach-at91/include/mach/board.h  |    6 +
 drivers/net/can/Kconfig                  |    6 +
 drivers/net/can/Makefile                 |    1 +
 drivers/net/can/at91_can.c               | 1177 ++++++++++++++++++++++++++++++
 6 files changed, 1245 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/can/at91_can.c

^ permalink raw reply

* [PATCH 2/3] at91sam9263ek: activate at91 CAN controller
From: Marc Kleine-Budde @ 2009-09-16  9:46 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Marc Kleine-Budde,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1253094405-3216-2-git-send-email-mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

This patch activates the at91 CAN controller for the at91sam9263ek
development board.

Signed-off-by: Hans J. Koch <hjk-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Signed-off-by: Marc Kleine-Budde <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 arch/arm/mach-at91/board-sam9263ek.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 57d5252..e6268b3 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -400,6 +400,23 @@ static struct gpio_led ek_pwm_led[] = {
 	}
 };
 
+/*
+ * CAN
+ */
+static void sam9263ek_transceiver_switch(int on)
+{
+	if (on) {
+		at91_set_gpio_output(AT91_PIN_PA18, 1); /* CANRXEN */
+		at91_set_gpio_output(AT91_PIN_PA19, 0); /* CANRS */
+	} else {
+		at91_set_gpio_output(AT91_PIN_PA18, 0); /* CANRXEN */
+		at91_set_gpio_output(AT91_PIN_PA19, 1); /* CANRS */
+	}
+}
+
+static struct at91_can_data ek_can_data = {
+	.transceiver_switch = sam9263ek_transceiver_switch,
+};
 
 static void __init ek_board_init(void)
 {
@@ -431,6 +448,8 @@ static void __init ek_board_init(void)
 	/* LEDs */
 	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
 	at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
+	/* CAN */
+	at91_add_device_can(&ek_can_data);
 }
 
 MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 1/3] at91sam9263: add at91_can device to generic device definition
From: Marc Kleine-Budde @ 2009-09-16  9:46 UTC (permalink / raw)
  To: netdev; +Cc: linux-arm-kernel, Socketcan-core, Marc Kleine-Budde, Hans J. Koch
In-Reply-To: <1253094405-3216-1-git-send-email-mkl@pengutronix.de>

This patch adds the device definition for the at91_can device to
the generic device definiton file for the at91sam9263.

Signed-off-by: Hans J. Koch <hjk@linutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 arch/arm/mach-at91/at91sam9263_devices.c |   36 ++++++++++++++++++++++++++++++
 arch/arm/mach-at91/include/mach/board.h  |    6 +++++
 2 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index b7f2332..6026c2e 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -757,6 +757,42 @@ void __init at91_add_device_ac97(struct atmel_ac97_data *data)
 void __init at91_add_device_ac97(struct atmel_ac97_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  CAN Controller
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_CAN_AT91) || defined(CONFIG_CAN_AT91_MODULE)
+static struct resource can_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_BASE_CAN,
+		.end	= AT91SAM9263_BASE_CAN + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_CAN,
+		.end	= AT91SAM9263_ID_CAN,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9263_can_device = {
+	.name		= "at91_can",
+	.id		= -1,
+	.resource	= can_resources,
+	.num_resources	= ARRAY_SIZE(can_resources),
+};
+
+void __init at91_add_device_can(struct at91_can_data *data)
+{
+	at91_set_A_periph(AT91_PIN_PA13, 0);	/* CANTX */
+	at91_set_A_periph(AT91_PIN_PA14, 0);	/* CANRX */
+	at91sam9263_can_device.dev.platform_data = data;
+
+	platform_device_register(&at91sam9263_can_device);
+}
+#else
+void __init at91_add_device_can(struct at91_can_data *data) {}
+#endif
 
 /* --------------------------------------------------------------------
  *  LCD Controller
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index e6afff8..134731c 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -179,6 +179,12 @@ extern void __init at91_add_device_isi(void);
  /* Touchscreen Controller */
 extern void __init at91_add_device_tsadcc(void);
 
+/* CAN */
+struct at91_can_data {
+	void (*transceiver_switch)(int on);
+};
+extern void __init at91_add_device_can(struct at91_can_data *data);
+
  /* LEDs */
 extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
 extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 3/3] at91_can: add driver for Atmel's CAN controller on AT91SAM9263
From: Marc Kleine-Budde @ 2009-09-16  9:46 UTC (permalink / raw)
  To: netdev; +Cc: linux-arm-kernel, Socketcan-core, Marc Kleine-Budde
In-Reply-To: <1253094405-3216-3-git-send-email-mkl@pengutronix.de>

This patch add the driver for the SoC CAN controller in Atmel's AT91SAM9263.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/Kconfig    |    6 +
 drivers/net/can/Makefile   |    1 +
 drivers/net/can/at91_can.c | 1177 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1184 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/can/at91_can.c

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 0900743..b6d2af1 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -82,6 +82,12 @@ config CAN_KVASER_PCI
 	  This driver is for the the PCIcanx and PCIcan cards (1, 2 or
 	  4 channel) from Kvaser (http://www.kvaser.com).
 
+config CAN_AT91
+	tristate "Atmel AT91 onchip CAN controller"
+	depends on CAN && ARCH_AT91SAM9263
+	---help---
+	  This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
+
 config CAN_DEBUG_DEVICES
 	bool "CAN devices debugging messages"
 	depends on CAN
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 523a941..3a54a12 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -8,5 +8,6 @@ obj-$(CONFIG_CAN_DEV)		+= can-dev.o
 can-dev-y			:= dev.o
 
 obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
+obj-$(CONFIG_CAN_AT91)		+= at91_can.o
 
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
new file mode 100644
index 0000000..cd1e8cb
--- /dev/null
+++ b/drivers/net/can/at91_can.c
@@ -0,0 +1,1177 @@
+/*
+ * at91_can.c - CAN network driver for AT91 SoC CAN controller
+ *
+ * (C) 2007 by Hans J. Koch <hjk@linutronix.de>
+ * (C) 2008, 2009 by Marc Kleine-Budde <kernel@pengutronix.de>
+ *
+ * This software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2 as distributed in the 'COPYING'
+ * file from the main directory of the linux kernel source.
+ *
+ * Send feedback to <socketcan-users@lists.berlios.de>
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+#include <mach/board.h>
+
+#define DRV_NAME		"at91_can"
+#define AT91_NAPI_WEIGHT	12
+
+/*
+ * RX/TX Mailbox split
+ * don't dare to touch
+ */
+#define AT91_MB_RX_NUM		12
+#define AT91_MB_TX_SHIFT	2
+
+#define AT91_MB_RX_FIRST	0
+#define AT91_MB_RX_LAST		(AT91_MB_RX_FIRST + AT91_MB_RX_NUM - 1)
+
+#define AT91_MB_RX_MASK(i)	((1 << (i)) - 1)
+#define AT91_MB_RX_SPLIT	8
+#define AT91_MB_RX_LOW_LAST	(AT91_MB_RX_SPLIT - 1)
+#define AT91_MB_RX_LOW_MASK	(AT91_MB_RX_MASK(AT91_MB_RX_SPLIT))
+
+#define AT91_MB_TX_NUM		(1 << AT91_MB_TX_SHIFT)
+#define AT91_MB_TX_FIRST	(AT91_MB_RX_LAST + 1)
+#define AT91_MB_TX_LAST		(AT91_MB_TX_FIRST + AT91_MB_TX_NUM - 1)
+
+#define AT91_NEXT_PRIO_SHIFT	(AT91_MB_TX_SHIFT)
+#define AT91_NEXT_PRIO_MASK	(0xf << AT91_MB_TX_SHIFT)
+#define AT91_NEXT_MB_MASK	(AT91_MB_TX_NUM - 1)
+#define AT91_NEXT_MASK		((AT91_MB_TX_NUM - 1) | AT91_NEXT_PRIO_MASK)
+
+/* Common registers */
+enum at91_reg {
+	AT91_MR		= 0x000,
+	AT91_IER	= 0x004,
+	AT91_IDR	= 0x008,
+	AT91_IMR	= 0x00C,
+	AT91_SR		= 0x010,
+	AT91_BR		= 0x014,
+	AT91_TIM	= 0x018,
+	AT91_TIMESTP	= 0x01C,
+	AT91_ECR	= 0x020,
+	AT91_TCR	= 0x024,
+	AT91_ACR	= 0x028,
+};
+
+/* Mailbox registers (0 <= i <= 15) */
+#define AT91_MMR(i)		(enum at91_reg)(0x200 + ((i) * 0x20))
+#define AT91_MAM(i)		(enum at91_reg)(0x204 + ((i) * 0x20))
+#define AT91_MID(i)		(enum at91_reg)(0x208 + ((i) * 0x20))
+#define AT91_MFID(i)		(enum at91_reg)(0x20C + ((i) * 0x20))
+#define AT91_MSR(i)		(enum at91_reg)(0x210 + ((i) * 0x20))
+#define AT91_MDL(i)		(enum at91_reg)(0x214 + ((i) * 0x20))
+#define AT91_MDH(i)		(enum at91_reg)(0x218 + ((i) * 0x20))
+#define AT91_MCR(i)		(enum at91_reg)(0x21C + ((i) * 0x20))
+
+/* Register bits */
+#define AT91_MR_CANEN		BIT(0)
+#define AT91_MR_LPM		BIT(1)
+#define AT91_MR_ABM		BIT(2)
+#define AT91_MR_OVL		BIT(3)
+#define AT91_MR_TEOF		BIT(4)
+#define AT91_MR_TTM		BIT(5)
+#define AT91_MR_TIMFRZ		BIT(6)
+#define AT91_MR_DRPT		BIT(7)
+
+#define AT91_SR_RBSY		BIT(29)
+
+#define AT91_MMR_PRIO_SHIFT	(16)
+
+#define AT91_MID_MIDE		BIT(29)
+
+#define AT91_MSR_MRTR		BIT(20)
+#define AT91_MSR_MABT		BIT(22)
+#define AT91_MSR_MRDY		BIT(23)
+#define AT91_MSR_MMI		BIT(24)
+
+#define AT91_MCR_MRTR		BIT(20)
+#define AT91_MCR_MTCR		BIT(23)
+
+/* Mailbox Modes */
+enum at91_mb_mode {
+	AT91_MB_MODE_DISABLED	= 0,
+	AT91_MB_MODE_RX		= 1,
+	AT91_MB_MODE_RX_OVRWR	= 2,
+	AT91_MB_MODE_TX		= 3,
+	AT91_MB_MODE_CONSUMER	= 4,
+	AT91_MB_MODE_PRODUCER	= 5,
+};
+
+/* Interrupt mask bits */
+#define AT91_IRQ_MB_RX		((1 << (AT91_MB_RX_LAST + 1)) \
+				 - (1 << AT91_MB_RX_FIRST))
+#define AT91_IRQ_MB_TX		((1 << (AT91_MB_TX_LAST + 1)) \
+				 - (1 << AT91_MB_TX_FIRST))
+#define AT91_IRQ_MB_ALL		(AT91_IRQ_MB_RX | AT91_IRQ_MB_TX)
+
+#define AT91_IRQ_ERRA		(1 << 16)
+#define AT91_IRQ_WARN		(1 << 17)
+#define AT91_IRQ_ERRP		(1 << 18)
+#define AT91_IRQ_BOFF		(1 << 19)
+#define AT91_IRQ_SLEEP		(1 << 20)
+#define AT91_IRQ_WAKEUP		(1 << 21)
+#define AT91_IRQ_TOVF		(1 << 22)
+#define AT91_IRQ_TSTP		(1 << 23)
+#define AT91_IRQ_CERR		(1 << 24)
+#define AT91_IRQ_SERR		(1 << 25)
+#define AT91_IRQ_AERR		(1 << 26)
+#define AT91_IRQ_FERR		(1 << 27)
+#define AT91_IRQ_BERR		(1 << 28)
+
+#define AT91_IRQ_ERR_ALL	(0x1fff0000)
+#define AT91_IRQ_ERR_FRAME	(AT91_IRQ_CERR | AT91_IRQ_SERR | \
+				 AT91_IRQ_AERR | AT91_IRQ_FERR | AT91_IRQ_BERR)
+#define AT91_IRQ_ERR_LINE	(AT91_IRQ_ERRA | AT91_IRQ_WARN | \
+				 AT91_IRQ_ERRP | AT91_IRQ_BOFF)
+
+#define AT91_IRQ_ALL		(0x1fffffff)
+
+struct at91_priv {
+	struct can_priv		can;	   /* must be the first member! */
+	struct net_device	*dev;
+	struct napi_struct	napi;
+
+	void __iomem		*reg_base;
+
+	u32			reg_sr;
+	unsigned int		tx_next;
+	unsigned int		tx_echo;
+	unsigned int		rx_next;
+
+	struct clk		*clk;
+	struct at91_can_data	*pdata;
+};
+
+static struct can_bittiming_const at91_bittiming_const = {
+	.tseg1_min	= 4,
+	.tseg1_max	= 16,
+	.tseg2_min	= 2,
+	.tseg2_max	= 8,
+	.sjw_max	= 4,
+	.brp_min 	= 2,
+	.brp_max	= 128,
+	.brp_inc	= 1,
+};
+
+static inline int get_tx_next_mb(const struct at91_priv *priv)
+{
+	return (priv->tx_next & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST;
+}
+
+static inline int get_tx_next_prio(const struct at91_priv *priv)
+{
+	return (priv->tx_next >> AT91_NEXT_PRIO_SHIFT) & 0xf;
+}
+
+static inline int get_tx_echo_mb(const struct at91_priv *priv)
+{
+	return (priv->tx_echo & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST;
+}
+
+static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg)
+{
+	return readl(priv->reg_base + reg);
+}
+
+static inline void at91_write(const struct at91_priv *priv, enum at91_reg reg,
+		u32 value)
+{
+	writel(value, priv->reg_base + reg);
+}
+
+static inline void set_mb_mode_prio(const struct at91_priv *priv,
+		unsigned int mb, enum at91_mb_mode mode, int prio)
+{
+	at91_write(priv, AT91_MMR(mb), (mode << 24) | (prio << 16));
+}
+
+static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb,
+		enum at91_mb_mode mode)
+{
+	set_mb_mode_prio(priv, mb, mode, 0);
+}
+
+static struct sk_buff *alloc_can_skb(struct net_device *dev,
+		struct can_frame **cf)
+{
+	struct sk_buff *skb;
+
+	skb = netdev_alloc_skb(dev, sizeof(struct can_frame));
+	if (unlikely(!skb))
+		return NULL;
+
+	skb->protocol = htons(ETH_P_CAN);
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+	*cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+
+	return skb;
+}
+
+static struct sk_buff *alloc_can_err_skb(struct net_device *dev,
+		struct can_frame **cf)
+{
+	struct sk_buff *skb;
+
+	skb = alloc_can_skb(dev, cf);
+	if (unlikely(!skb))
+		return NULL;
+
+	memset(*cf, 0, sizeof(struct can_frame));
+	(*cf)->can_id = CAN_ERR_FLAG;
+	(*cf)->can_dlc = CAN_ERR_DLC;
+
+	return skb;
+}
+
+/*
+ * Swtich transceiver on or off
+ */
+static void at91_transceiver_switch(const struct at91_priv *priv, int on)
+{
+	if (priv->pdata && priv->pdata->transceiver_switch)
+		priv->pdata->transceiver_switch(on);
+}
+
+static void at91_setup_mailboxes(struct net_device *dev)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	unsigned int i;
+
+	/*
+	 * The first 12 mailboxes are used as a reception FIFO. The
+	 * last mailbox is configured with overwrite option. The
+	 * overwrite flag indicates a FIFO overflow.
+	 */
+	for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++)
+		set_mb_mode(priv, i, AT91_MB_MODE_RX);
+	set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR);
+
+	/* The last 4 mailboxes are used for transmitting. */
+	for (i = AT91_MB_TX_FIRST; i <= AT91_MB_TX_LAST; i++)
+		set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0);
+
+	/* Reset tx and rx helper pointers */
+	priv->tx_next = priv->tx_echo = priv->rx_next = 0;
+}
+
+static int at91_set_bittiming(struct net_device *dev)
+{
+	const struct at91_priv *priv = netdev_priv(dev);
+	const struct can_bittiming *bt = &priv->can.bittiming;
+	u32 reg_br;
+
+	reg_br = ((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) << 24) |
+		((bt->brp - 1) << 16) |	((bt->sjw - 1) << 12) |
+		((bt->prop_seg - 1) << 8) | ((bt->phase_seg1 - 1) << 4) |
+		((bt->phase_seg2 - 1) << 0);
+
+	dev_info(dev->dev.parent, "writing AT91_BR: 0x%08x\n", reg_br);
+
+	at91_write(priv, AT91_BR, reg_br);
+
+	return 0;
+}
+
+static void at91_chip_start(struct net_device *dev)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_mr, reg_ier;
+
+	/* disable interrupts */
+	at91_write(priv, AT91_IDR, AT91_IRQ_ALL);
+
+	/* disable chip */
+	reg_mr = at91_read(priv, AT91_MR);
+	at91_write(priv, AT91_MR, reg_mr & ~AT91_MR_CANEN);
+
+	at91_setup_mailboxes(dev);
+	at91_transceiver_switch(priv, 1);
+
+	/* enable chip */
+	at91_write(priv, AT91_MR, AT91_MR_CANEN);
+
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+	/* Enable interrupts */
+	reg_ier = AT91_IRQ_MB_RX | AT91_IRQ_ERRP | AT91_IRQ_ERR_FRAME;
+	at91_write(priv, AT91_IDR, AT91_IRQ_ALL);
+	at91_write(priv, AT91_IER, reg_ier);
+}
+
+static void at91_chip_stop(struct net_device *dev, enum can_state state)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_mr;
+
+	/* disable interrupts */
+	at91_write(priv, AT91_IDR, AT91_IRQ_ALL);
+
+	reg_mr = at91_read(priv, AT91_MR);
+	at91_write(priv, AT91_MR, reg_mr & ~AT91_MR_CANEN);
+
+	at91_transceiver_switch(priv, 0);
+	priv->can.state = state;
+}
+
+/*
+ * theory of operation:
+ *
+ * According to the datasheet priority 0 is the highest priority, 15
+ * is the lowest. If two mailboxes have the same priority level the
+ * message of the mailbox with the lowest number is sent first.
+ *
+ * We use the first TX mailbox (AT91_MB_TX_FIRST) with prio 0, then
+ * the next mailbox with prio 0, and so on, until all mailboxes are
+ * used. Then we start from the beginning with mailbox
+ * AT91_MB_TX_FIRST, but with prio 1, mailbox AT91_MB_TX_FIRST + 1
+ * prio 1. When we reach the last mailbox with prio 15, we have to
+ * stop sending, waiting for all messages to be delivered, then start
+ * again with mailbox AT91_MB_TX_FIRST prio 0.
+ *
+ * We use the priv->tx_next as counter for the next transmission
+ * mailbox, but without the offset AT91_MB_TX_FIRST. The lower bits
+ * encode the mailbox number, the upper 4 bits the mailbox priority:
+ *
+ * priv->tx_next = (prio << AT91_NEXT_PRIO_SHIFT) ||
+ *                 (mb - AT91_MB_TX_FIRST);
+ *
+ */
+static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf = (struct can_frame *)skb->data;
+	unsigned int mb, prio;
+	u32 reg_mid, reg_mcr;
+
+	mb = get_tx_next_mb(priv);
+	prio = get_tx_next_prio(priv);
+
+	if (unlikely(!(at91_read(priv, AT91_MSR(mb)) & AT91_MSR_MRDY))) {
+		netif_stop_queue(dev);
+
+		dev_err(dev->dev.parent,
+			"BUG! TX buffer full when queue awake!\n");
+		return NETDEV_TX_BUSY;
+	}
+
+	if (cf->can_id & CAN_EFF_FLAG)
+		reg_mid = (cf->can_id & CAN_EFF_MASK) | AT91_MID_MIDE;
+	else
+		reg_mid = (cf->can_id & CAN_SFF_MASK) << 18;
+
+	reg_mcr = ((cf->can_id & CAN_RTR_FLAG) ? AT91_MCR_MRTR : 0) |
+		(cf->can_dlc << 16) | AT91_MCR_MTCR;
+
+	/* disable MB while writing ID (see datasheet) */
+	set_mb_mode(priv, mb, AT91_MB_MODE_DISABLED);
+	at91_write(priv, AT91_MID(mb), reg_mid);
+	set_mb_mode_prio(priv, mb, AT91_MB_MODE_TX, prio);
+
+	at91_write(priv, AT91_MDL(mb), *(u32 *)(cf->data + 0));
+	at91_write(priv, AT91_MDH(mb), *(u32 *)(cf->data + 4));
+
+	/* This triggers transmission */
+	at91_write(priv, AT91_MCR(mb), reg_mcr);
+
+	stats->tx_bytes += cf->can_dlc;
+	dev->trans_start = jiffies;
+
+	/* _NOTE_: substract AT91_MB_TX_FIRST offset from mb! */
+	can_put_echo_skb(skb, dev, mb - AT91_MB_TX_FIRST);
+
+	/*
+	 * we have to stop the queue and deliver all messages in case
+	 * of a prio+mb counter wrap around. This is the case if
+	 * tx_next buffer prio and mailbox equals 0.
+	 *
+	 * also stop the queue if next buffer is still in use
+	 * (== not ready)
+	 */
+	priv->tx_next++;
+	if (!(at91_read(priv, AT91_MSR(get_tx_next_mb(priv))) &
+	      AT91_MSR_MRDY) ||
+	    (priv->tx_next & AT91_NEXT_MASK) == 0)
+		netif_stop_queue(dev);
+
+	/* Enable interrupt for this mailbox */
+	at91_write(priv, AT91_IER, 1 << mb);
+
+	return NETDEV_TX_OK;
+}
+
+/**
+ * at91_activate_rx_low - activate lower rx mailboxes
+ * @priv: a91 context
+ *
+ * Reenables the lower mailboxes for reception of new CAN messages
+ */
+static inline void at91_activate_rx_low(const struct at91_priv *priv)
+{
+	u32 mask = AT91_MB_RX_LOW_MASK;
+	at91_write(priv, AT91_TCR, mask);
+}
+
+/**
+ * at91_activate_rx_mb - reactive single rx mailbox
+ * @priv: a91 context
+ * @mb: mailbox to reactivate
+ *
+ * Reenables given mailbox for reception of new CAN messages
+ */
+static inline void at91_activate_rx_mb(const struct at91_priv *priv,
+		unsigned int mb)
+{
+	u32 mask = 1 << mb;
+	at91_write(priv, AT91_TCR, mask);
+}
+
+/**
+ * at91_rx_overflow_err - send error frame due to rx overflow
+ * @dev: net device
+ */
+static void at91_rx_overflow_err(struct net_device *dev)
+{
+	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *skb;
+	struct can_frame *cf;
+
+	dev_dbg(dev->dev.parent, "RX buffer overflow\n");
+	stats->rx_over_errors++;
+	stats->rx_errors++;
+
+	skb = alloc_can_err_skb(dev, &cf);
+	if (unlikely(!skb))
+		return;
+
+	cf->can_id |= CAN_ERR_CRTL;
+	cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+	netif_receive_skb(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+}
+
+/**
+ * at91_read_mb - read CAN msg from mailbox (lowlevel impl)
+ * @dev: net device
+ * @mb: mailbox number to read from
+ * @cf: can frame where to store message
+ *
+ * Reads a CAN message from the given mailbox and stores data into
+ * given can frame. "mb" and "cf" must be valid.
+ */
+static void at91_read_mb(struct net_device *dev, unsigned int mb,
+		struct can_frame *cf)
+{
+	const struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_msr, reg_mid;
+
+	reg_mid = at91_read(priv, AT91_MID(mb));
+	if (reg_mid & AT91_MID_MIDE)
+		cf->can_id = ((reg_mid >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
+	else
+		cf->can_id = (reg_mid >> 18) & CAN_SFF_MASK;
+
+	reg_msr = at91_read(priv, AT91_MSR(mb));
+	if (reg_msr & AT91_MSR_MRTR)
+		cf->can_id |= CAN_RTR_FLAG;
+	cf->can_dlc = min_t(__u8, (reg_msr >> 16) & 0xf, 8);
+
+	*(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb));
+	*(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb));
+
+	if (unlikely(mb == AT91_MB_RX_LAST && reg_msr & AT91_MSR_MMI))
+		at91_rx_overflow_err(dev);
+}
+
+/**
+ * at91_read_msg - read CAN message from mailbox
+ * @dev: net device
+ * @mb: mail box to read from
+ *
+ * Reads a CAN message from given mailbox, and put into linux network
+ * RX queue, does all housekeeping chores (stats, ...)
+ */
+static void at91_read_msg(struct net_device *dev, unsigned int mb)
+{
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+
+	skb = alloc_can_skb(dev, &cf);
+	if (unlikely(!skb)) {
+		stats->rx_dropped++;
+		return;
+	}
+
+	at91_read_mb(dev, mb, cf);
+	netif_receive_skb(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+}
+
+/**
+ * at91_poll_rx - read multiple CAN messages from mailboxes
+ * @dev: net device
+ * @quota: max number of pkgs we're allowed to receive
+ *
+ * Theory of Operation:
+ *
+ * 12 of the 16 mailboxes on the chip are reserved for RX. we split
+ * them into 2 groups. The lower group holds 8 and upper 4 mailboxes.
+ *
+ * Like it or not, but the chip always saves a received CAN message
+ * into the first free mailbox it finds (starting with the
+ * lowest). This makes it very difficult to read the messages in the
+ * right order from the chip. This is how we work around that problem:
+ *
+ * The first message goes into mb nr. 0 and issues an interrupt. All
+ * rx ints are disabled in the interrupt handler and a napi poll is
+ * scheduled. We read the mailbox, but do _not_ reenable the mb (to
+ * receive another message).
+ *
+ *    lower mbxs      upper
+ *   ______^______    __^__
+ *  /             \  /     \
+ * +-+-+-+-+-+-+-+-++-+-+-+-+
+ * |x|x|x|x|x|x|x|x|| | | | |
+ * +-+-+-+-+-+-+-+-++-+-+-+-+
+ *  0 0 0 0 0 0  0 0 0 0 1 1  \ mail
+ *  0 1 2 3 4 5  6 7 8 9 0 1  / box
+ *
+ * The variable priv->rx_next points to the next mailbox to read a
+ * message from. As long we're in the lower mailboxes we just read the
+ * mailbox but not reenable it.
+ *
+ * With completion of the last of the lower mailboxes, we reenable the
+ * whole first group, but continue to look for filled mailboxes in the
+ * upper mailboxes. Imagine the second group like overflow mailboxes,
+ * which takes CAN messages if the lower goup is full. While in the
+ * upper group we reenable the mailbox right after reading it. Giving
+ * the chip more room to store messages.
+ *
+ * After finishing we look again in the lower group if we've still
+ * quota.
+ *
+ */
+static int at91_poll_rx(struct net_device *dev, int quota)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_sr = at91_read(priv, AT91_SR);
+	const unsigned long *addr = (unsigned long *)&reg_sr;
+	unsigned int mb;
+	int received = 0;
+
+	if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
+	    reg_sr & AT91_MB_RX_LOW_MASK)
+		dev_info(dev->dev.parent,
+			 "order of incoming frames cannot be guaranteed\n");
+
+ again:
+	for (mb = find_next_bit(addr, AT91_MB_RX_NUM, priv->rx_next);
+	     mb < AT91_MB_RX_NUM && quota > 0;
+	     reg_sr = at91_read(priv, AT91_SR),
+	     mb = find_next_bit(addr, AT91_MB_RX_NUM, ++priv->rx_next)) {
+		at91_read_msg(dev, mb);
+
+		/* reactivate mailboxes */
+		if (mb == AT91_MB_RX_LOW_LAST)
+			/* all lower mailboxed, if just finished it */
+			at91_activate_rx_low(priv);
+		else if (mb > AT91_MB_RX_LOW_LAST)
+			/* only the mailbox we read */
+			at91_activate_rx_mb(priv, mb);
+
+		received++;
+		quota--;
+	}
+
+	/* upper group completed, look again in lower */
+	if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
+	    quota > 0 && mb >= AT91_MB_RX_NUM) {
+		priv->rx_next = 0;
+		goto again;
+	}
+
+	return received;
+}
+
+static void at91_poll_err_frame(struct net_device *dev,
+		struct can_frame *cf, u32 reg_sr)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+
+	/* CRC error */
+	if (reg_sr & AT91_IRQ_CERR) {
+		dev_dbg(dev->dev.parent, "CERR irq\n");
+		dev->stats.rx_errors++;
+		priv->can.can_stats.bus_error++;
+		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+	}
+
+	/* Stuffing Error */
+	if (reg_sr & AT91_IRQ_SERR) {
+		dev_dbg(dev->dev.parent, "SERR irq\n");
+		dev->stats.rx_errors++;
+		priv->can.can_stats.bus_error++;
+		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+		cf->data[2] |= CAN_ERR_PROT_STUFF;
+	}
+
+	/* Acknowledgement Error */
+	if (reg_sr & AT91_IRQ_AERR) {
+		dev_dbg(dev->dev.parent, "AERR irq\n");
+		dev->stats.tx_errors++;
+		cf->can_id |= CAN_ERR_ACK;
+	}
+
+	/* Form error */
+	if (reg_sr & AT91_IRQ_FERR) {
+		dev_dbg(dev->dev.parent, "FERR irq\n");
+		dev->stats.rx_errors++;
+		priv->can.can_stats.bus_error++;
+		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+		cf->data[2] |= CAN_ERR_PROT_FORM;
+	}
+
+	/* Bit Error */
+	if (reg_sr & AT91_IRQ_BERR) {
+		dev_dbg(dev->dev.parent, "BERR irq\n");
+		dev->stats.tx_errors++;
+		priv->can.can_stats.bus_error++;
+		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+		cf->data[2] |= CAN_ERR_PROT_BIT;
+	}
+}
+
+static int at91_poll_err(struct net_device *dev, int quota, u32 reg_sr)
+{
+	struct sk_buff *skb;
+	struct can_frame *cf;
+
+	if (quota == 0)
+		return 0;
+
+	skb = alloc_can_err_skb(dev, &cf);
+	if (unlikely(!skb))
+		return 0;
+
+	at91_poll_err_frame(dev, cf, reg_sr);
+	netif_receive_skb(skb);
+
+	dev->last_rx = jiffies;
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += cf->can_dlc;
+
+	return 1;
+}
+
+static int at91_poll(struct napi_struct *napi, int quota)
+{
+	struct net_device *dev = napi->dev;
+	const struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_sr = at91_read(priv, AT91_SR);
+	int work_done = 0;
+
+	if (reg_sr & AT91_IRQ_MB_RX)
+		work_done += at91_poll_rx(dev, quota - work_done);
+
+	/*
+	 * The error bits are clear on read,
+	 * so use saved value from irq handler.
+	 */
+	reg_sr |= priv->reg_sr;
+	if (reg_sr & AT91_IRQ_ERR_FRAME)
+		work_done += at91_poll_err(dev, quota - work_done, reg_sr);
+
+	if (work_done < quota) {
+		/* enable IRQs for frame errors and all mailboxes >= rx_next */
+		u32 reg_ier = AT91_IRQ_ERR_FRAME;
+		reg_ier |= AT91_IRQ_MB_RX & ~AT91_MB_RX_MASK(priv->rx_next);
+
+		napi_complete(napi);
+		at91_write(priv, AT91_IER, reg_ier);
+	}
+
+	return work_done;
+}
+
+/*
+ * theory of operation:
+ *
+ * priv->tx_echo holds the number of the oldest can_frame put for
+ * transmission into the hardware, but not yet ACKed by the CAN tx
+ * complete IRQ.
+ *
+ * We iterate from priv->tx_echo to priv->tx_next and check if the
+ * packet has been transmitted, echo it back to the CAN framework. If
+ * we discover a not yet transmitted package, stop looking for more.
+ *
+ */
+static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_msr;
+	unsigned int mb;
+
+	/* masking of reg_sr not needed, already done by at91_irq */
+
+	for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
+		mb = get_tx_echo_mb(priv);
+
+		/* no event in mailbox? */
+		if (!(reg_sr & (1 << mb)))
+			break;
+
+		/* Disable irq for this TX mailbox */
+		at91_write(priv, AT91_IDR, 1 << mb);
+
+		/*
+		 * only echo if mailbox signals us a transfer
+		 * complete (MSR_MRDY). Otherwise it's a tansfer
+		 * abort. "can_bus_off()" takes care about the skbs
+		 * parked in the echo queue.
+		 */
+		reg_msr = at91_read(priv, AT91_MSR(mb));
+		if (likely(reg_msr & AT91_MSR_MRDY &&
+			   ~reg_msr & AT91_MSR_MABT)) {
+			/* _NOTE_: substract AT91_MB_TX_FIRST offset from mb! */
+			can_get_echo_skb(dev, mb - AT91_MB_TX_FIRST);
+			dev->stats.tx_packets++;
+		}
+	}
+
+	/*
+	 * restart queue if we don't have a wrap around but restart if
+	 * we get a TX int for the last can frame directly before a
+	 * wrap around.
+	 */
+	if ((priv->tx_next & AT91_NEXT_MASK) != 0 ||
+	    (priv->tx_echo & AT91_NEXT_MASK) == 0)
+		netif_wake_queue(dev);
+}
+
+static void at91_irq_err_state(struct net_device *dev,
+		struct can_frame *cf, enum can_state new_state)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_idr, reg_ier, reg_ecr;
+	u8 tec, rec;
+
+	reg_ecr = at91_read(priv, AT91_ECR);
+	rec = reg_ecr & 0xff;
+	tec = reg_ecr >> 16;
+
+	switch (priv->can.state) {
+	case CAN_STATE_ERROR_ACTIVE:
+		/*
+		 * from: ERROR_ACTIVE
+		 * to  : ERROR_WARNING, ERROR_PASSIVE, BUS_OFF
+		 * =>  : there was a warning int
+		 */
+		if (new_state >= CAN_STATE_ERROR_WARNING &&
+		    new_state <= CAN_STATE_BUS_OFF) {
+			dev_dbg(dev->dev.parent, "Error Warning IRQ\n");
+			priv->can.can_stats.error_warning++;
+
+			cf->can_id |= CAN_ERR_CRTL;
+			cf->data[1] = (tec > rec) ?
+				CAN_ERR_CRTL_TX_WARNING :
+				CAN_ERR_CRTL_RX_WARNING;
+		}
+	case CAN_STATE_ERROR_WARNING:	/* fallthrough */
+		/*
+		 * from: ERROR_ACTIVE, ERROR_WARNING
+		 * to  : ERROR_PASSIVE, BUS_OFF
+		 * =>  : error passive int
+		 */
+		if (new_state >= CAN_STATE_ERROR_PASSIVE &&
+		    new_state <= CAN_STATE_BUS_OFF) {
+			dev_dbg(dev->dev.parent, "Error Passive IRQ\n");
+			priv->can.can_stats.error_passive++;
+
+			cf->can_id |= CAN_ERR_CRTL;
+			cf->data[1] = (tec > rec) ?
+				CAN_ERR_CRTL_TX_PASSIVE :
+				CAN_ERR_CRTL_RX_PASSIVE;
+		}
+		break;
+	case CAN_STATE_BUS_OFF:
+		/*
+		 * from: BUS_OFF
+		 * to  : ERROR_ACTIVE, ERROR_WARNING, ERROR_PASSIVE
+		 */
+		if (new_state <= CAN_STATE_ERROR_PASSIVE) {
+			cf->can_id |= CAN_ERR_RESTARTED;
+
+			dev_dbg(dev->dev.parent, "restarted\n");
+			priv->can.can_stats.restarts++;
+
+			netif_carrier_on(dev);
+			netif_wake_queue(dev);
+		}
+		break;
+	default:
+		break;
+	}
+
+
+	/* process state changes depending on the new state */
+	switch (new_state) {
+	case CAN_STATE_ERROR_ACTIVE:
+		/*
+		 * actually we want to enable AT91_IRQ_WARN here, but
+		 * it screws up the system under certain
+		 * circumstances. so just enable AT91_IRQ_ERRP, thus
+		 * the "fallthrough"
+		 */
+		dev_dbg(dev->dev.parent, "Error Active\n");
+		cf->can_id |= CAN_ERR_PROT;
+		cf->data[2] = CAN_ERR_PROT_ACTIVE;
+	case CAN_STATE_ERROR_WARNING:	/* fallthrough */
+		reg_idr = AT91_IRQ_ERRA | AT91_IRQ_WARN | AT91_IRQ_BOFF;
+		reg_ier = AT91_IRQ_ERRP;
+		break;
+	case CAN_STATE_ERROR_PASSIVE:
+		reg_idr = AT91_IRQ_ERRA | AT91_IRQ_WARN | AT91_IRQ_ERRP;
+		reg_ier = AT91_IRQ_BOFF;
+		break;
+	case CAN_STATE_BUS_OFF:
+		reg_idr = AT91_IRQ_ERRA | AT91_IRQ_ERRP |
+			AT91_IRQ_WARN | AT91_IRQ_BOFF;
+		reg_ier = 0;
+
+		cf->can_id |= CAN_ERR_BUSOFF;
+
+		dev_dbg(dev->dev.parent, "bus-off\n");
+		netif_carrier_off(dev);
+		priv->can.can_stats.bus_off++;
+
+		/* turn off chip, if restart is disabled */
+		if (!priv->can.restart_ms) {
+			at91_chip_stop(dev, CAN_STATE_BUS_OFF);
+			return;
+		}
+		break;
+	default:
+		break;
+	}
+
+	at91_write(priv, AT91_IDR, reg_idr);
+	at91_write(priv, AT91_IER, reg_ier);
+}
+
+static void at91_irq_err(struct net_device *dev)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	struct sk_buff *skb;
+	struct can_frame *cf;
+	enum can_state new_state;
+	u32 reg_sr;
+
+	reg_sr = at91_read(priv, AT91_SR);
+
+	/* we need to look at the unmasked reg_sr */
+	if (unlikely(reg_sr & AT91_IRQ_BOFF))
+		new_state = CAN_STATE_BUS_OFF;
+	else if (unlikely(reg_sr & AT91_IRQ_ERRP))
+		new_state = CAN_STATE_ERROR_PASSIVE;
+	else if (unlikely(reg_sr & AT91_IRQ_WARN))
+		new_state = CAN_STATE_ERROR_WARNING;
+	else if (likely(reg_sr & AT91_IRQ_ERRA))
+		new_state = CAN_STATE_ERROR_ACTIVE;
+	else {
+		dev_err(dev->dev.parent, "BUG! hardware in undefined state\n");
+		return;
+	}
+
+	/* state hasn't changed */
+	if (likely(new_state == priv->can.state))
+		return;
+
+	skb = alloc_can_err_skb(dev, &cf);
+	if (unlikely(!skb))
+		return;
+
+	at91_irq_err_state(dev, cf, new_state);
+	netif_rx(skb);
+
+	dev->last_rx = jiffies;
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += cf->can_dlc;
+
+	priv->can.state = new_state;
+}
+
+/*
+ * interrupt handler
+ */
+static irqreturn_t at91_irq(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct at91_priv *priv = netdev_priv(dev);
+	irqreturn_t handled = IRQ_NONE;
+	u32 reg_sr, reg_imr;
+
+	reg_sr = at91_read(priv, AT91_SR);
+	reg_imr = at91_read(priv, AT91_IMR);
+
+	/* Ignore masked interrupts */
+	reg_sr &= reg_imr;
+	if (!reg_sr)
+		goto exit;
+
+	handled = IRQ_HANDLED;
+
+	/* Receive or error interrupt? -> napi */
+	if (reg_sr & (AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME)) {
+		/*
+		 * The error bits are clear on read,
+		 * save for later use.
+		 */
+		priv->reg_sr = reg_sr;
+		at91_write(priv, AT91_IDR,
+			   AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME);
+		napi_schedule(&priv->napi);
+	}
+
+	/* Transmission complete interrupt */
+	if (reg_sr & AT91_IRQ_MB_TX)
+		at91_irq_tx(dev, reg_sr);
+
+	at91_irq_err(dev);
+
+ exit:
+	return handled;
+}
+
+static int at91_open(struct net_device *dev)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	int err;
+
+	clk_enable(priv->clk);
+
+	/* check or determine and set bittime */
+	err = open_candev(dev);
+	if (err)
+		goto out;
+
+	/* register interrupt handler */
+	if (request_irq(dev->irq, at91_irq, IRQF_SHARED,
+			dev->name, dev)) {
+		err = -EAGAIN;
+		goto out_close;
+	}
+
+	/* start chip and queuing */
+	at91_chip_start(dev);
+	napi_enable(&priv->napi);
+	netif_start_queue(dev);
+
+	return 0;
+
+ out_close:
+	close_candev(dev);
+ out:
+	clk_disable(priv->clk);
+
+	return err;
+}
+
+/*
+ * stop CAN bus activity
+ */
+static int at91_close(struct net_device *dev)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+	napi_disable(&priv->napi);
+	at91_chip_stop(dev, CAN_STATE_STOPPED);
+
+	free_irq(dev->irq, dev);
+	clk_disable(priv->clk);
+
+	close_candev(dev);
+
+	return 0;
+}
+
+static int at91_set_mode(struct net_device *dev, enum can_mode mode)
+{
+	switch (mode) {
+	case CAN_MODE_START:
+		at91_chip_start(dev);
+		netif_wake_queue(dev);
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static const struct net_device_ops at91_netdev_ops = {
+	.ndo_open	= at91_open,
+	.ndo_stop	= at91_close,
+	.ndo_start_xmit	= at91_start_xmit,
+};
+
+static int __init at91_can_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	struct at91_priv *priv;
+	struct resource *res;
+	struct clk *clk;
+	void __iomem *addr;
+	int err, irq;
+
+	clk = clk_get(&pdev->dev, "can_clk");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "no clock defined\n");
+		err = -ENODEV;
+		goto exit;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irq = platform_get_irq(pdev, 0);
+	if (!res || !irq) {
+		err = -ENODEV;
+		goto exit_put;
+	}
+
+	if (!request_mem_region(res->start,
+				resource_size(res),
+				pdev->name)) {
+		err = -EBUSY;
+		goto exit_put;
+	}
+
+	addr = ioremap_nocache(res->start, resource_size(res));
+	if (!addr) {
+		err = -ENOMEM;
+		goto exit_release;
+	}
+
+	dev = alloc_candev(sizeof(struct at91_priv));
+	if (!dev) {
+		err = -ENOMEM;
+		goto exit_iounmap;
+	}
+
+	dev->netdev_ops	= &at91_netdev_ops;
+	dev->irq = irq;
+	dev->flags |= IFF_ECHO;
+
+	priv = netdev_priv(dev);
+	priv->can.clock.freq = clk_get_rate(clk);
+	priv->can.bittiming_const = &at91_bittiming_const;
+	priv->can.do_set_bittiming = at91_set_bittiming;
+	priv->can.do_set_mode = at91_set_mode;
+	priv->reg_base = addr;
+	priv->dev = dev;
+	priv->clk = clk;
+	priv->pdata = pdev->dev.platform_data;
+
+	netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT);
+
+	dev_set_drvdata(&pdev->dev, dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	err = register_candev(dev);
+	if (err) {
+		dev_err(&pdev->dev, "registering netdev failed\n");
+		goto exit_free;
+	}
+
+	dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
+		 priv->reg_base, dev->irq);
+
+	return 0;
+
+ exit_free:
+	free_netdev(dev);
+ exit_iounmap:
+	iounmap(addr);
+ exit_release:
+	release_mem_region(res->start, resource_size(res));
+ exit_put:
+	clk_put(clk);
+ exit:
+	return err;
+}
+
+static int __devexit at91_can_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct at91_priv *priv = netdev_priv(dev);
+	struct resource *res;
+
+	unregister_netdev(dev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	free_netdev(dev);
+
+	iounmap(priv->reg_base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	clk_put(priv->clk);
+
+	return 0;
+}
+
+static struct platform_driver at91_can_driver = {
+	.probe		= at91_can_probe,
+	.remove		= __devexit_p(at91_can_remove),
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init at91_can_module_init(void)
+{
+	printk(KERN_INFO "%s netdevice driver\n", DRV_NAME);
+	return platform_driver_register(&at91_can_driver);
+}
+
+static void __exit at91_can_module_exit(void)
+{
+	platform_driver_unregister(&at91_can_driver);
+	printk(KERN_INFO "%s: driver removed\n", DRV_NAME);
+}
+
+module_init(at91_can_module_init);
+module_exit(at91_can_module_exit);
+
+MODULE_AUTHOR("Marc Kleine-Budde <mkl@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION(DRV_NAME " CAN netdevice driver");
-- 
1.6.3.3


^ permalink raw reply related

* Re: [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: David Miller @ 2009-09-16  9:47 UTC (permalink / raw)
  To: dwalker; +Cc: jie.yang, miles.lane, chris.snook, jcliburn, netdev, linux-kernel
In-Reply-To: <1253092251.11643.569.camel@desktop>

From: Daniel Walker <dwalker@fifo99.com>
Date: Wed, 16 Sep 2009 02:10:51 -0700

> On Wed, 2009-09-16 at 14:21 +0800, jie.yang@atheros.com wrote:
>> -           pci_unmap_page(pdev, tx_buffer->dma,
>> +           if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
>> +               pci_unmap_single(pdev, tx_buffer->dma,
>> +                   tx_buffer->length, PCI_DMA_TODEVICE);
>> +           else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
>> +               pci_unmap_page(pdev, tx_buffer->dma,
> 
> Could you run this through checkpatch, and fix any errors if find? It
> looks like you uses spaces for tabs in the code above, maybe in the
> other block too..
> 

It's because of his email client, it corrupted the whole patch
like that.

^ permalink raw reply

* Re: fanotify as syscalls
From: Eric Paris @ 2009-09-16  9:48 UTC (permalink / raw)
  To: Jamie Lokier
  Cc: Linus Torvalds, Evgeniy Polyakov, David Miller, linux-kernel,
	linux-fsdevel, netdev, viro, alan, hch
In-Reply-To: <20090916075219.GA22024@shareable.org>

On Wed, 2009-09-16 at 08:52 +0100, Jamie Lokier wrote:
> Eric Paris wrote:
> > On Tue, 2009-09-15 at 16:49 -0700, Linus Torvalds wrote:
> > > And btw, I still want to know what's so wonderful about fanotify that we 
> > > would actually want yet-another-filesystem-notification-interface. So I'm 
> > > not sayying that I'll take a system call interface.
> > 
> > The real thing that fanotify provides is an open fd with the event
> > rather than some arbitrary 'watch descriptor' that userspace must
> > somehow magically map back to data on disk.  This means that it could be
> > used to provide subtree notification, which inotify is completely
> > incapable of doing.
> 
> That's a bit of a spurious claim.

My claim that a watch descriptor plus pathname segment sucks is
spurious?  You've got to be kidding me.  You think that a number which
represents the pathname of an object at some point in the past is a
reasonable piece of information?  If a watch descriptor actually
provided any information about the object on which an event just
happened it would be useful.  Sadly, it doesn't.

> - fanotify does not provide subtree notification in it's
>   present form.  When it is extended to do that, why wouldn't
>   inotify be as well?  That's an fsnotify feature, common to both.

Because I don't believe inotify can be reasonably extended in this way.
It's already clear that an arbitrary watch descriptor which userspace
has to somehow know how to correctly map back to an object (impossible
task) is difficult to use and I personally don't see how watch
descriptor + long path name component is somehow better or even
reasonable.  Path names are such crap and passing a pathname to
userspace is really just telling userspace, something happened to
something that used to be at this location but is possibly long since
gone.  I don't believe that's a good interface or one we should be
allowing to be {ab,}used.

> - fanotify does not provide notification at all for some events that
>   you get with inotify.  It is not a superset, so you can't use
>   fanotify to provide a subtree-capable equivalent to inotify.  What
>   a mess when you need the combination of both features!

This is true, although where possible I plan to rectify this situation
on an ongoing basis.  Absolutely nothing preventing that from happening.

> - fanotify requires you call readlink(/proc/fd/N) for every event to
>   get the path.

And inotify requires magic.  Which one sounds better?

>   It's not a particularly efficient way to get it,

What is?

>   especially when an apps wants to know if it's something in it's
>   region of interest but doesn't care about the actual path.
>   When an apps knows it needs the map back to to path, why make it
>   slow to get it?  That "extensible data format" is being
>   underutilised...

You convince Al Viro that the vfs should give us a path name for an
arbitrary object that honestly might not have one and I'll consider
giving it to userspace in the event notification.  Probably should read
some of the AppArmour arguments before you do though.  You're asking for
something that's impossible and is at best incredibly race prone crap.
At worst is a total lie.

> - fanotify's descriptor may be race-prone as a way to get the subtree
>   used for access, because any of the parent directories could have
>   moved and even been deleted before the app calls
>   readlink(/proc/fd/N).  I don't know if a _reliable_ way to track
>   changes in a subtree can be built on it.  Maybe it can but it
>   appears this hasn't been analysed.  It depends on
>   readlink(/proc/fd/N)'s behaviour when the dentry's have been
>   changed, among other things.

Huh?  Your saying that by the time userspace deals with an event it
might have moved?  True.  So what?  Spurious and irrelevant.  You got an
event that happened to this object.  If subtree notification is added at
some later point you may get an event for an object that was in the
subtree and is now not in the subtree.  That sounds fine to me....

> - Does the descriptor cause umount to fail when user does "do some
>   stuff in baz; umount baz", or does it serialise nicely?  That's one
>   of inotify's nice features - it doesn't cause umounts to fail.

Ah yes, you didn't read the code.  Seeing as how that's an fsnotify
property and fanotify notify is built on fsnotify....

> Seriously, what does system-wide fanotify do when run from a
> chroot/namespace/cgroup, and a file outside them is accessed?

At the moment an fanotify global listener is system wide.  Truely system
wide.  A gentleman from suse is looking rectify the problem so that if
run inside a namespace it stays inside the namespace.  Note that this
particular little tidbit is not in the 8 patches I proposed.  At the
moment those just include the UI and basic notification.

> If the event is delivered with file desciptor, that's a security hole.
> If it's not delivered, that sounds like working subtree support?

What?

> I'd expect anti-malware to want to be run inside VMs quite often...

What?

> Answer questions about use-cases that you're not interested in?  Why
> block them?  What about Evigny's request for an event without an open
> fd - because he needs the pid information (inotify doesn't provide)
> but not the fd?

It's not blocked, it's on the list of things to look at.  It's a
relatively simple change to have the mark add code return a watch
descriptor and use that value instead of an fd.  I believe I already
said that.  It certainly doesn't seem like a merge blocker that some
other feature might come along one day.  There's nothing preventing it
from coming out.  "Here is a patch which implements TCP."  "No, don't
merge that, it doesn't implement UDP as well."  "WTF?"

> I'd like to be able to use it from some applications to accelerate
> userspace caching of things (faster Make, faster Samba) without
> penalising all other applications touching unrelated parts of the
> filesystem.  The attitude "you can live with 10% slowdown" worries me.
> I'm sure that can be fixed with a bit of care.

I've said that using ANYTHING which allows userspace to arbitrate access
decisions for an entries system is going to eat performance.  If you
can't handle that, don't build that damn userspace decision making
portion into your kernel!  Don't buy anti-malware snake oil.  

fanotify as a notification system isn't some performance monster here to
eat your babies.  fanotify as an access control system is, and I can't
really do anything about that, it's the nature of that part of the
horrible beast.  Lets not confuse things...

> If the intention is to maintain fanotify and inotify side-by-side for
> different uses (because fanotify returns open descriptors and blocks
> the accessing process until acked)

I know I've told you this before.  fanotify provides TWO separate
things.  Notification with a fd.  A method to provide access control and
blocking.  Lets not lead people to believe you can't you one without the
other.  They are very distinct.

> , that's ok with me.  It makes
> sense.  But then it's messy that neither offers a superset of the
> other regarding which files and events are tracked.

inotify isn't going away any time soon....

> If it's right that inotify has no room for extensibility (I'm not sure
> about this), than it appears we already made a mess with dnotify and
> inotify, so it would be a shame to repeat the same mistakes again.
> Let's get the next one right, even it takes a bit longer, ok?

Calling inotify a "mess" or "completely inextensible" would probably be
too harsh.  There are ways with inotify_init1() that we could provide a
better or more forward looking data format.  But you are still left with
inotify's fatal flaw: userspace is required to map a random number to an
object in the filesystem.  inotify starts with a reasonably impossible
premise and builds from there.

You show me anything about my proposal that limits any use case you have
in mind and I'll fix it.  I'll fix it today.  My proposal does what it
does very well and leaves the door open to build upon it for whatever
has been mentioned over the last 1.25 years I've been trying to get
comments.  I'm certainly not going to wait until fanotify can leap out
of my computer and make a pot of coffee before I ask for it to be merged
(and no, it doesn't have that forward looking extensibility, I'll add a
syscall flag for it right now, O_COFFEE)

-Eric

^ permalink raw reply

* Re: [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: Cyrill Gorcunov @ 2009-09-16  9:51 UTC (permalink / raw)
  To: David Miller
  Cc: dwalker, jie.yang, miles.lane, chris.snook, jcliburn, netdev,
	linux-kernel
In-Reply-To: <20090916.024759.51103835.davem@davemloft.net>

[David Miller - Wed, Sep 16, 2009 at 02:47:59AM -0700]
| From: Daniel Walker <dwalker@fifo99.com>
| Date: Wed, 16 Sep 2009 02:10:51 -0700
| 
| > On Wed, 2009-09-16 at 14:21 +0800, jie.yang@atheros.com wrote:
| >> -           pci_unmap_page(pdev, tx_buffer->dma,
| >> +           if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
| >> +               pci_unmap_single(pdev, tx_buffer->dma,
| >> +                   tx_buffer->length, PCI_DMA_TODEVICE);
| >> +           else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
| >> +               pci_unmap_page(pdev, tx_buffer->dma,
| > 
| > Could you run this through checkpatch, and fix any errors if find? It
| > looks like you uses spaces for tabs in the code above, maybe in the
| > other block too..
| > 
| 
| It's because of his email client, it corrupted the whole patch
| like that.

well, client seems to be

| X-Mailer: git-send-email 1.5.2.2

more probably the text editor is the reason.

	-- Cyrill

^ permalink raw reply

* RE: [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: Jie Yang @ 2009-09-16  9:54 UTC (permalink / raw)
  To: Cyrill Gorcunov, David Miller
  Cc: dwalker@fifo99.com, miles.lane@gmail.com, chris.snook@gmail.com,
	jcliburn@gmail.com, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <20090916095138.GH5094@lenovo>

On Wednesday, September 16, 2009 5:52 PM
Cyrill Gorcunov <gorcunov@gmail.com>  wrote:

> [David Miller - Wed, Sep 16, 2009 at 02:47:59AM -0700]
> | From: Daniel Walker <dwalker@fifo99.com>
> | Date: Wed, 16 Sep 2009 02:10:51 -0700
> |
> | > On Wed, 2009-09-16 at 14:21 +0800, jie.yang@atheros.com wrote:
> | >> -           pci_unmap_page(pdev, tx_buffer->dma,
> | >> +           if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
> | >> +               pci_unmap_single(pdev, tx_buffer->dma,
> | >> +                   tx_buffer->length, PCI_DMA_TODEVICE);
> | >> +           else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
> | >> +               pci_unmap_page(pdev, tx_buffer->dma,
> | >
> | > Could you run this through checkpatch, and fix any errors
> if find?
> | > It looks like you uses spaces for tabs in the code above,
> maybe in
> | > the other block too..
> | >
> |
> | It's because of his email client, it corrupted the whole patch like
> | that.
>
> well, client seems to be
>
> | X-Mailer: git-send-email 1.5.2.2
>
> more probably the text editor is the reason.
>
>         -- Cyrill
>

yes, the editor 'vi' have configed "set expandtab".

^ permalink raw reply

* Re: [PATCH 3/3] at91_can: add driver for Atmel's CAN controller on AT91SAM9263
From: Wolfgang Grandegger @ 2009-09-16 10:07 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1253094405-3216-4-git-send-email-mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Marc Kleine-Budde wrote:
> This patch add the driver for the SoC CAN controller in Atmel's AT91SAM9263.
> 
> Signed-off-by: Marc Kleine-Budde <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

I already reviewed at91_can.c on the Socket-CAN ML and it's almost OK
from the Socket-CAN point of view. I just realized two minor issues:

> ---
>  drivers/net/can/Kconfig    |    6 +
>  drivers/net/can/Makefile   |    1 +
>  drivers/net/can/at91_can.c | 1177 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 1184 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/can/at91_can.c
> 
> diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> index 0900743..b6d2af1 100644
> --- a/drivers/net/can/Kconfig
> +++ b/drivers/net/can/Kconfig
> @@ -82,6 +82,12 @@ config CAN_KVASER_PCI
>  	  This driver is for the the PCIcanx and PCIcan cards (1, 2 or
>  	  4 channel) from Kvaser (http://www.kvaser.com).
>  
> +config CAN_AT91
> +	tristate "Atmel AT91 onchip CAN controller"
> +	depends on CAN && ARCH_AT91SAM9263

It should depend on CAN_DEV because it used the CAN device driver interface.

> +	---help---
> +	  This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
> +
>  config CAN_DEBUG_DEVICES
>  	bool "CAN devices debugging messages"
>  	depends on CAN
> diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
> index 523a941..3a54a12 100644
> --- a/drivers/net/can/Makefile
> +++ b/drivers/net/can/Makefile
> @@ -8,5 +8,6 @@ obj-$(CONFIG_CAN_DEV)		+= can-dev.o
>  can-dev-y			:= dev.o
>  
>  obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
> +obj-$(CONFIG_CAN_AT91)		+= at91_can.o
>  
>  ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
> diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
> new file mode 100644
> index 0000000..cd1e8cb
> --- /dev/null
> +++ b/drivers/net/can/at91_can.c
> @@ -0,0 +1,1177 @@
> +/*
> + * at91_can.c - CAN network driver for AT91 SoC CAN controller
> + *
> + * (C) 2007 by Hans J. Koch <hjk-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> + * (C) 2008, 2009 by Marc Kleine-Budde <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> + *
> + * This software may be distributed under the terms of the GNU General
> + * Public License ("GPL") version 2 as distributed in the 'COPYING'
> + * file from the main directory of the linux kernel source.
> + *
> + * Send feedback to <socketcan-users-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org>

This driver uses platform data. Could you please add some description on
how they should be used, e.g. like for the MCP251x:

 * Your platform definition file should specify something like:
 *
 * static struct mcp251x_platform_data mcp251x_info = {
 *         .oscillator_frequency = 8000000,
 *         .board_specific_setup = &mcp251x_setup,
 *         .model = CAN_MCP251X_MCP2510,
 *         .power_enable = mcp251x_power_enable,
 *         .transceiver_enable = NULL,
 * };
 *
 * static struct spi_board_info spi_board_info[] = {
 *         {
 *                 .modalias      = "mcp251x",
 *                 .platform_data = &mcp251x_info,
 *                 .irq           = IRQ_EINT13,
 *                 .max_speed_hz  = 2*1000*1000,
 *                 .chip_select   = 2,
 *         },
 * };
 *
 * Please see mcp251x.h for a description of the fields in
 * struct mcp251x_platform_data.

I find that really useful.

Wolfgang.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox