* Re: [PATCH] CAIF: Fix IPv6 support in receive path for GPRS/3G
From: David Miller @ 2011-01-11 0:12 UTC (permalink / raw)
To: sjurbren; +Cc: netdev, kumar.sanghvi, sjur.brandeland
In-Reply-To: <1294401428-2085-1-git-send-email-sjurbren@stericsson.com>
From: Sjur Brændeland <sjurbren@stericsson.com>
Date: Fri, 07 Jan 2011 12:57:08 +0100
> From: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
>
> Checks version field of IP in the receive path for GPRS/3G data
> and appropriately sets the value of skb->protocol.
>
> Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH v2] net/r8169: Update the function of parsing firmware
From: David Miller @ 2011-01-11 0:14 UTC (permalink / raw)
To: hayeswang; +Cc: romieu, netdev, linux-kernel
In-Reply-To: <1294661245-2191-1-git-send-email-hayeswang@realtek.com>
From: Hayes Wang <hayeswang@realtek.com>
Date: Mon, 10 Jan 2011 20:07:25 +0800
> Update rtl_phy_write_fw function. The new function could
> parse the complex firmware which is used by RTL8111E and later.
> The new firmware may read data and do some operations, not just
> do writing only.
>
> Signed-off-by: Hayes Wang <hayeswang@realtek.com>
Applied, thank you.
^ permalink raw reply
* Re: [PATCH v2] net: ppp: use {get,put}_unaligned_be{16,32}
From: David Miller @ 2011-01-11 0:13 UTC (permalink / raw)
To: xiaosuo; +Cc: paulus, harvey.harrison, linux-ppp, netdev
In-Reply-To: <1294357056-25889-1-git-send-email-xiaosuo@gmail.com>
From: Changli Gao <xiaosuo@gmail.com>
Date: Fri, 7 Jan 2011 07:37:36 +0800
> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH 0/2] net: Allow allocating different number RX and TX mqs
From: Tom Herbert @ 2011-01-11 0:28 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20110110.160642.146350621.davem@davemloft.net>
On Mon, Jan 10, 2011 at 4:06 PM, David Miller <davem@davemloft.net> wrote:
> From: Tom Herbert <therbert@google.com>
> Date: Sun, 9 Jan 2011 21:36:25 -0800 (PST)
>
>> Add functions so that a different number of TX and RX queues can be
>> allocated in a netdevice. Second patch modifies mlx4 driver to call
>> this function which is an example of a driver that allocates different
>> numbers for TX and RX queues.
>
> Both applied, thanks Tom.
>
Thanks. By the way I didn't see a maintainer for the mlx drivers in
the MAINTAINERS files. Who maintains these?
^ permalink raw reply
* Re: [e100] Page allocation failure warning(?) in 2.6.36.3
From: Dave, Tushar N @ 2011-01-11 0:37 UTC (permalink / raw)
To: Chris Rankin, e1000-devel@lists.sourceforge.net; +Cc: netdev@vger.kernel.org
In-Reply-To: <688142.89079.qm@web121707.mail.ne1.yahoo.com>
Chris,
The reason I asked you about bridge is because I have noticed "br0: port 1(eth1) entering learning state" in the dmesg log you sent.
I am trying to figure out exactly what sequence of commands you run that produce this message " br0: port 1(eth1) entering learning state" in log.
Also if you let me know output of
#cat /etc/network/interface
#ifconfig -a
Thanks.
-Tushar
-----Original Message-----
From: Chris Rankin [mailto:rankincj@yahoo.com]
Sent: Monday, January 10, 2011 3:42 PM
To: e1000-devel@lists.sourceforge.net; Dave, Tushar N
Cc: netdev@vger.kernel.org
Subject: RE: [E1000-devel] [e100] Page allocation failure warning(?) in 2.6.36.3
--- On Mon, 10/1/11, Dave, Tushar N <tushar.n.dave@intel.com> wrote:
> Does the issue appears only when you add a bridge?
Tushar,
I'm not sure what you mean by "add a bridge". I've been using this box ever since the late 1990s, and have had the 3 e100 port since the early 2000s, so I can't say that I "do" anything with it apart from use it.
The PCI configuration remains as it always has, and the box get rebooted only to receive stable kernel updates. Looking back through old dmesg logs, it looks like this issue also happened in 2.6.33.6 too without me ever realising. Hence I am suspecting that this problem has been happening intermittently for ages...
Is there anything else I can tell you about this ropey old P200 MMX PC before Indiana Jones finds it and tries putting it in his museum ;-)?
Cheers,
Chris
------------------------------------------------------------------------------
Gaining the trust of online customers is vital for the success of any company
that requires sensitive data to be transmitted over the Web. Learn how to
best implement a security strategy that keeps consumers' information secure
and instills the confidence they need to proceed with transactions.
http://p.sf.net/sfu/oracle-sfdevnl
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply
* [PATCH v2] cxgb3i: fixed connection problem with iscsi private ip
From: kxie @ 2011-01-11 0:45 UTC (permalink / raw)
To: netdev, linux-scsi, open-iscsi; +Cc: kxie, davem, James.Bottomley, michaelc
[PATCH v2] cxgb3i: fixed connection problem with iscsi private ip
From: Karen Xie <kxie@chelsio.com>
The last one seems to have some formatting problem. Regenerated the patch.
fixed the connection problem when the private iscsi ipv4 address is provisioned on the interface.
Signed-off-by: Karen Xie <kxie@chelsio.com>
---
drivers/scsi/cxgbi/cxgb3i/cxgb3i.h | 19 +++++++++++++++----
1 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
index 5f5e339..20593fd 100644
--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
@@ -24,10 +24,21 @@
extern cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS];
-#define cxgb3i_get_private_ipv4addr(ndev) \
- (((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr)
-#define cxgb3i_set_private_ipv4addr(ndev, addr) \
- (((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr) = addr
+static inline unsigned int cxgb3i_get_private_ipv4addr(struct net_device *ndev)
+{
+ return ((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr;
+}
+
+static inline void cxgb3i_set_private_ipv4addr(struct net_device *ndev,
+ unsigned int addr)
+{
+ struct port_info *pi = (struct port_info *)netdev_priv(ndev);
+
+ pi->iscsic.flags = addr ? 1 : 0;
+ pi->iscsi_ipv4addr = addr;
+ if (addr)
+ memcpy(pi->iscsic.mac_addr, ndev->dev_addr, ETH_ALEN);
+}
struct cpl_iscsi_hdr_norss {
union opcode_tid ot;
^ permalink raw reply related
* Re: [PATCH] UDPCP Communication Protocol
From: Hagen Paul Pfeifer @ 2011-01-11 0:49 UTC (permalink / raw)
To: stefani; +Cc: linux-kernel, akpm, davem, netdev
In-Reply-To: <1293787785-3834-1-git-send-email-stefani@seibold.net>
find_dest() via new_dest() may return NULL
* stefani@seibold.net | 2010-12-31 10:29:45 [+0100]:
>+static int udpcp_sendmsg(struct kiocb *iocb, struct sock *sk,
>+ struct msghdr *msg, size_t len)
>+{
>+ struct inet_sock *inet = inet_sk(sk);
>+ struct udpcp_sock *usk = udpcp_sk(sk);
>+ struct ipcm_cookie *ipc;
>+ struct rtable *rt = NULL;
>+ int free = 0;
>+ int connected = 0;
>+ __be32 daddr, faddr, saddr;
>+ __be16 dport;
>+ u8 tos;
>+ int err = 0;
>+ int corkreq = usk->udpsock.corkflag || msg->msg_flags & MSG_MORE;
>+ int (*getfrag) (void *, char *, int, int, int, struct sk_buff *);
>+ struct udpcp_dest *dest;
>+
>+ if (len > UDPCP_MAX_MSGSIZE)
>+ return -EMSGSIZE;
>+
>+ /*
>+ * Check the flags.
>+ */
>+ if (msg->msg_flags & MSG_OOB)
>+ return -EOPNOTSUPP;
>+
>+ /*
>+ * check if socket is binded to a port
>+ */
>+ if (!(sk->sk_userlocks & SOCK_BINDPORT_LOCK) || !inet->inet_num)
>+ return -ENOTCONN;
>+
>+ /*
>+ * Get and verify the address.
>+ */
>+ if (msg->msg_name) {
>+ struct sockaddr_in *usin = (struct sockaddr_in *)msg->msg_name;
>+ if (msg->msg_namelen < sizeof(*usin))
>+ return -EINVAL;
>+ if (usin->sin_family != AF_INET) {
>+ if (usin->sin_family != AF_UNSPEC)
>+ return -EAFNOSUPPORT;
>+ }
>+
>+ daddr = usin->sin_addr.s_addr;
>+ dport = usin->sin_port;
>+ } else {
>+ if (sk->sk_state != TCP_ESTABLISHED)
>+ return -EDESTADDRREQ;
>+ daddr = inet->inet_daddr;
>+ dport = inet->inet_dport;
>+ /* Open fast path for connected socket.
>+ Route will not be used, if at least one option is set.
>+ */
>+ connected = 1;
>+ }
>+
>+ if (dport == 0)
>+ return -EINVAL;
>+
>+ dest = find_dest(sk, daddr, dport);
if (!dest)
return -ENOBUFS;
^ permalink raw reply
* Re: [RFC] sched: CHOKe packet scheduler (v0.4)
From: Stephen Hemminger @ 2011-01-11 1:10 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1294704031.4148.2.camel@edumazet-laptop>
OK, put that in.
>
> Here we missed :
>
> q->tab = ntab;
>
--
^ permalink raw reply
* Re: panic in tg3 driver
From: Matt Carlson @ 2011-01-11 2:00 UTC (permalink / raw)
To: Stephen Clark
Cc: Matthew Carlson, Linux Kernel Network Developers, Michael Chan
In-Reply-To: <4D2B6652.7040607@earthlink.net>
On Mon, Jan 10, 2011 at 12:04:34PM -0800, Stephen Clark wrote:
> On 01/10/2011 02:22 PM, Matt Carlson wrote:
> > On Sun, Jan 09, 2011 at 02:30:50PM -0800, Stephen Clark wrote:
> >
> >> On 01/04/2011 09:54 AM, Stephen Clark wrote:
> >>
> >>> Hello,
> >>>
> >>>
> >>> The hardware is an Acrosser AR-M0898B micro box.
> >>> lspci
> >>> 00:00.0 Host bridge: VIA Technologies, Inc. CN700/VN800/P4M800CE/Pro
> >>> Host Bridge
> >>> 00:00.1 Host bridge: VIA Technologies, Inc. CN700/VN800/P4M800CE/Pro
> >>> Host Bridge
> >>> 00:00.2 Host bridge: VIA Technologies, Inc. CN700/VN800/P4M800CE/Pro
> >>> Host Bridge
> >>> 00:00.3 Host bridge: VIA Technologies, Inc. PT890 Host Bridge
> >>> 00:00.4 Host bridge: VIA Technologies, Inc. CN700/VN800/P4M800CE/Pro
> >>> Host Bridge
> >>> 00:00.7 Host bridge: VIA Technologies, Inc. CN700/VN800/P4M800CE/Pro
> >>> Host Bridge
> >>> 00:01.0 PCI bridge: VIA Technologies, Inc. VT8237/VX700 PCI Bridge
> >>> 00:0f.0 IDE interface: VIA Technologies, Inc. VT8251 Serial ATA
> >>> Controller (rev
> >>> 20)
> >>> 00:0f.1 IDE interface: VIA Technologies, Inc.
> >>> VT82C586A/B/VT82C686/A/B/VT823x/A/
> >>> C PIPC Bus Master IDE (rev 07)
> >>> 00:10.0 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1
> >>> Controller
> >>> (rev 91)
> >>> 00:10.1 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1
> >>> Controller
> >>> (rev 91)
> >>> 00:10.2 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1
> >>> Controller
> >>> (rev 91)
> >>> 00:10.3 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1
> >>> Controller
> >>> (rev 91)
> >>> 00:10.4 USB Controller: VIA Technologies, Inc. USB 2.0 (rev 90)
> >>> 00:11.0 ISA bridge: VIA Technologies, Inc. VT8251 PCI to ISA Bridge
> >>> 00:11.7 Host bridge: VIA Technologies, Inc. VT8251 Ultra VLINK Controller
> >>> 00:13.0 Host bridge: VIA Technologies, Inc. VT8251 Host Bridge
> >>> 00:13.1 PCI bridge: VIA Technologies, Inc. VT8251 PCI to PCI Bridge
> >>> 02:08.0 Ethernet controller: Broadcom Corporation BCM4401 100Base-T
> >>> (rev 02)
> >>> 02:09.0 Ethernet controller: Broadcom Corporation BCM4401 100Base-T
> >>> (rev 02)
> >>> 80:00.0 PCI bridge: VIA Technologies, Inc. VT8251 PCIE Root Port
> >>> 80:00.1 PCI bridge: VIA Technologies, Inc. VT8251 PCIE Root Port
> >>> 81:00.0 Ethernet controller: Broadcom Corporation NetLink BCM5906M
> >>> Fast Ethernet
> >>> PCI Express (rev 02)
> >>> 82:00.0 Ethernet controller: Broadcom Corporation NetLink BCM5906M
> >>> Fast Ethernet
> >>> PCI Express (rev 02)
> >>>
> >>> Kernel 2.6.36-2.el5.elrepo on an i686
> >>>
> >>> When I try to ifconfig either of the BCM5906M ports the system panics.
> >>>
> >>> Ideas, fixes ?
> >>>
> >>> [root@Z1010 ~]# modprobe tg3
> >>> [root@Z1010 ~]# ifconfig eth2 2.2.2.2/24
> >>> ------------[ cut here ]------------
> >>> kernel BUG at drivers/net/tg3.c:4365!
> >>> invalid opcode: 0000 [#1] PREEMPT SMP
> >>> last sysfs file: /sys/class/net/eth3/address
> >>> Modules linked in: tg3 xt_tcpudp ipt_LOG xt_limit xt_state
> >>> iptable_mangle af_ke]
> >>>
> >>> Pid: 20303, comm: kworker/0:2 Not tainted 2.6.36-2.el5.elrepo #1
> >>> CN700-8251/
> >>> EIP: 0060:[<e1c62f19>] EFLAGS: 00010202 CPU: 0
> >>> EIP is at tg3_tx_recover+0x1e/0x53 [tg3]
> >>> EAX: deece4c0 EBX: dfa9c000 ECX: deece4c0 EDX: ffffffff
> >>> ESI: deece4c0 EDI: deece500 EBP: c1801f38 ESP: c1801f30
> >>> DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
> >>> Process kworker/0:2 (pid: 20303, ti=c1801000 task=df0105d0
> >>> task.ti=dee62000)
> >>> Stack:
> >>> dfa9c000 00000000 c1801f6c e1c630be c1801f6c deece4c0 00000840 00000000
> >>> <0> df251cc0 00000005 00000000 df979800 deece500 deece4c0 00000040
> >>> c1801f94
> >>> <0> e1c661e5 00000000 00000040 c1801f88 e09df1d2 00000000 deece500
> >>> dfab4000
> >>> Call Trace:
> >>> [<e1c630be>] ? tg3_tx+0x157/0x1a2 [tg3]
> >>> [<e1c661e5>] ? tg3_poll_work+0x2b/0x10b [tg3]
> >>> [<e09df1d2>] ? ssb_write32+0x11/0x14 [b44]
> >>> [<e1c662f9>] ? tg3_poll+0x34/0x9a [tg3]
> >>> [<c0674058>] ? net_rx_action+0x7e/0x11c
> >>> [<c04409c9>] ? __do_softirq+0x85/0x10c
> >>> [<c0440944>] ? __do_softirq+0x0/0x10c
> >>> <IRQ>
> >>> [<c04404ef>] ? _local_bh_enable_ip+0x68/0x87
> >>> [<c044051b>] ? local_bh_enable_ip+0xd/0xf
> >>> [<c046593b>] ? __raw_spin_unlock_bh+0x1c/0x1e
> >>> [<c06fa4f2>] ? _raw_spin_unlock_bh+0xd/0xf
> >>> [<e1c6281f>] ? spin_unlock_bh+0xd/0xf [tg3]
> >>> [<e1c62cbe>] ? tg3_full_unlock+0x10/0x12 [tg3]
> >>> [<e1c664c7>] ? tg3_reset_task+0xd7/0xe3 [tg3]
> >>> [<c044ec37>] ? process_one_work+0x10b/0x1bc
> >>> [<e1c663f0>] ? tg3_reset_task+0x0/0xe3 [tg3]
> >>> [<c044fd41>] ? worker_thread+0x77/0xf9
> >>> [<c0453048>] ? kthread+0x60/0x65
> >>> [<c044fcca>] ? worker_thread+0x0/0xf9
> >>> [<c0452fe8>] ? kthread+0x0/0x65
> >>> [<c040337e>] ? kernel_thread_helper+0x6/0x10
> >>> Code: f0 e8 88 ff ff ff 8d 65 f8 5b 5e 5d c3 55 89 e5 56 53 0f 1f 44
> >>> 00 00 f6 8
> >>> EIP: [<e1c62f19>] tg3_tx_recover+0x1e/0x53 [tg3] SS:ESP 0068:c1801f30
> >>> ---[ end trace 82381e9b93e397ad ]---
> >>> Kernel panic - not syncing: Fatal exception in interrupt
> >>> Pid: 20303, comm: kworker/0:2 Tainted: G D
> >>> 2.6.36-2.el5.elrepo #1
> >>> Call Trace:
> >>> [<c043b3cd>] panic+0x62/0x15d
> >>> [<c06fb7d1>] oops_end+0x99/0xa8
> >>> [<e1c62f19>] ? tg3_tx_recover+0x1e/0x53 [tg3]
> >>> [<c0405a62>] die+0x58/0x5e
> >>>
> >>> Thanks,
> >>> Steve
> >>>
> >>>
> >> Additonal info I compiled the latest kernel 2.6.37-rc8+ and still have the problem.
> >> Also boot with noapic I see this in the dmesg log and interrupts are increasing
> >> like crazy:
> >> tg3.c:v3.115 (October 14, 2010)
> >> tg3 0000:81:00.0: PCI INT A -> Link[LNKA] -> GSI 10 (level, low) -> IRQ 10
> >> tg3 0000:81:00.0: setting latency timer to 64
> >> tg3 0000:81:00.0: PCI: Disallowing DAC for device
> >> tg3 0000:81:00.0: eth2: Tigon3 [partno(BCM95906) rev c002] (PCI Express) MAC add
> >> ress 00:02:b6:36:d1:39
> >> tg3 0000:81:00.0: eth2: attached PHY is 5906 (10/100Base-TX Ethernet) (WireSpeed
> >> [0])
> >> tg3 0000:81:00.0: eth2: RXcsums[1] LinkChgREG[0] MIirq[0] ASF[0] TSOcap[1]
> >> tg3 0000:81:00.0: eth2: dma_rwctrl[76180000] dma_mask[32-bit]
> >> tg3 0000:82:00.0: PCI INT A -> Link[LNKA] -> GSI 10 (level, low) -> IRQ 10
> >> tg3 0000:82:00.0: setting latency timer to 64
> >> tg3 0000:82:00.0: PCI: Disallowing DAC for device
> >> tg3 0000:82:00.0: eth3: Tigon3 [partno(BCM95906) rev c002] (PCI Express) MAC add
> >> ress 00:02:b6:36:d1:3a
> >> tg3 0000:82:00.0: eth3: attached PHY is 5906 (10/100Base-TX Ethernet) (WireSpeed
> >> [0])
> >> tg3 0000:82:00.0: eth3: RXcsums[1] LinkChgREG[0] MIirq[0] ASF[0] TSOcap[1]
> >> tg3 0000:82:00.0: eth3: dma_rwctrl[76180000] dma_mask[32-bit]
> >> tg3 0000:81:00.0: irq 40 for MSI/MSI-X
> >> tg3 0000:81:00.0: eth2: No interrupt was generated using MSI. Switching to INTx
> >> mode. Please report this failure to the PCI maintainer and include system chipse
> >> t information
> >> ADDRCONF(NETDEV_UP): eth2: link is not ready
> >> [root@Z1010 ~]# cat /proc/interrupts
> >> CPU0
> >> 0: 162 XT-PIC-XT-PIC timer
> >> 1: 2 XT-PIC-XT-PIC i8042
> >> 2: 0 XT-PIC-XT-PIC cascade
> >> 3: 1 XT-PIC-XT-PIC
> >> 4: 4863 XT-PIC-XT-PIC serial
> >> 6: 2 XT-PIC-XT-PIC floppy
> >> 7: 5 XT-PIC-XT-PIC ehci_hcd:usb1, uhci_hcd:usb3
> >> 8: 0 XT-PIC-XT-PIC rtc0
> >> 9: 0 XT-PIC-XT-PIC acpi
> >> 10: 2334234 XT-PIC-XT-PIC uhci_hcd:usb2, eth0, eth2
> >>
> >> [root@Z1010 ~]# cat /proc/interrupts |grep eth2
> >> 10: 18388914 XT-PIC-XT-PIC uhci_hcd:usb2, eth0, eth2
> >> [root@Z1010 ~]# cat /proc/interrupts |grep eth2
> >> 10: 18901627 XT-PIC-XT-PIC uhci_hcd:usb2, eth0, eth2
> >>
> >> --
> >>
> >> "They that give up essential liberty to obtain temporary safety,
> >> deserve neither liberty nor safety." (Ben Franklin)
> >>
> >> "The course of history shows that as a government grows, liberty
> >> decreases." (Thomas Jefferson)
> >>
> > I think drivers/net/tg3.c:4365 is at the line that reads
> > "spin_lock(&tp->lock);" in tg3_tx_recover. Can you verify?
> >
> >
>
>
> tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &phy2);
>
> in static void tg3_serdes_parallel_detect(struct tg3 *tp)
>
> The driver version is:
> #define DRV_MODULE_NAME "tg3"
> #define TG3_MAJ_NUM 3
> #define TG3_MIN_NUM 115
That doesn't look right. The line number I quoted came from the kernel
panic output from 2.6.36-2.el5.elrepo. I'm guessing you quoted me the
sources from the tg3.c file in 2.6.37-rc8+. If you don't have the
2.6.36-2.el5.elrepo sources readily available, can you give me the line
the kernel panic specifies from the tg3.c file from your 2.6.37-rc8+
sources?
It looks like there are a lot of devices on IRQ 10. Does the interrupt
count drop if you bring down eth0 (which I'm guessing is the b44 device)?
Can you tell me if you saw the following message in the syslogs?
"The system may be re-ordering memory-mapped I/O cycles to the network
device, attempting to recover. Please report the problem to the driver
maintainer and include system chipset information."
^ permalink raw reply
* Re: [PATCH v2] cxgb3i: fixed connection problem with iscsi private ip
From: Mike Christie @ 2011-01-11 2:19 UTC (permalink / raw)
To: open-iscsi; +Cc: kxie, netdev, linux-scsi, davem, James.Bottomley
In-Reply-To: <201101110045.p0B0j7vv016416@localhost6.localdomain6>
On 01/10/2011 06:45 PM, kxie@chelsio.com wrote:
> [PATCH v2] cxgb3i: fixed connection problem with iscsi private ip
>
> From: Karen Xie<kxie@chelsio.com>
>
> The last one seems to have some formatting problem. Regenerated the patch.
>
> fixed the connection problem when the private iscsi ipv4 address is provisioned on the interface.
>
> Signed-off-by: Karen Xie<kxie@chelsio.com>
> ---
> drivers/scsi/cxgbi/cxgb3i/cxgb3i.h | 19 +++++++++++++++----
> 1 files changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
> index 5f5e339..20593fd 100644
> --- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
> +++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
> @@ -24,10 +24,21 @@
>
> extern cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS];
>
> -#define cxgb3i_get_private_ipv4addr(ndev) \
> - (((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr)
> -#define cxgb3i_set_private_ipv4addr(ndev, addr) \
> - (((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr) = addr
> +static inline unsigned int cxgb3i_get_private_ipv4addr(struct net_device *ndev)
> +{
> + return ((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr;
> +}
> +
> +static inline void cxgb3i_set_private_ipv4addr(struct net_device *ndev,
> + unsigned int addr)
> +{
> + struct port_info *pi = (struct port_info *)netdev_priv(ndev);
> +
> + pi->iscsic.flags = addr ? 1 : 0;
> + pi->iscsi_ipv4addr = addr;
> + if (addr)
> + memcpy(pi->iscsic.mac_addr, ndev->dev_addr, ETH_ALEN);
> +}
>
> struct cpl_iscsi_hdr_norss {
> union opcode_tid ot;
>
Looks ok to me, and it fixes my setup here. Thanks.
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
^ permalink raw reply
* rtt calculation when retransmissions occur during handshake
From: Josh Hunt @ 2011-01-11 2:52 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 2578 bytes --]
I was wondering if someone could explain the following behavior I'm
seeing on my web server. I've instrumented the kernel to look at the
RTT during TCP handshake. I am seeing the RTTs reported by the kernel
when my initial SYN/ACK is lost to be calculated based on the original
SYN/ACK. Is this behavior correct? Below I have two cases I've seen on
my system. The first shows the client replying to the retransmitted
SYN/ACK but giving an RTT of 900 instead of around 252. The second
shows the client replying to the original SYN/ACK and reports an RTT
of 913. I have tcp_no_metrics_save enabled so there should be no RTT
caching. This is on kernel 2.6.32.20.
(I've attached these trace snippets as it might be tough to read in a
mail client)
* Reported RTT: 900 - looks like RTT should be ~252:
1294443792.878373 IP 1.2.3.4.49174 > 5.6.7.8.80: Flags [S], seq
2495182093, win 65535, options [mss 1460,nop,wscale 3,nop,nop,TS val
759815989 ecr 0,sackOK,eol], length 0
1294443792.878379 IP 5.6.7.8.80 > 1.2.3.4.49174: Flags [S.], seq
4249681570, ack 2495182094, win 5792, options [mss 1460,sackOK,TS val
760394055 ecr 759815989,nop,wscale 5], length 0
1294443793.656624 IP 5.6.7.8.80 > 1.2.3.4.49174: Flags [S.], seq
4249681570, ack 2495182094, win 5792, options [mss 1460,sackOK,TS val
760394834 ecr 759815989,nop,wscale 5], length 0
1294443793.908897 IP 1.2.3.4.49174 > 5.6.7.8.80: Flags [.], ack 1, win
65535, options [nop,nop,TS val 759816000 ecr 760394834], length 0
* Reported RTT: 913 - looks correct since it's replying to the original syn/ack:
1294443634.012920 IP 2.3.4.5.62987 > 5.6.7.8.80: Flags [S], seq
1397298575, win 65535, options [mss 1460,nop,wscale 1,nop,nop,TS val
576497055 ecr 0,sackOK,eol], length 0
1294443634.012931 IP 5.6.7.8.80 > 2.3.4.5.62987: Flags [S.], seq
1761430826, ack 1397298576, win 5792, options [mss 1460,sackOK,TS val
760235190 ecr 576497055,nop,wscale 5], length 0
1294443634.656625 IP 5.6.7.8.80 > 2.3.4.5.62987: Flags [S.], seq
1761430826, ack 1397298576, win 5792, options [mss 1460,sackOK,TS val
760235834 ecr 576497055,nop,wscale 5], length 0
1294443634.925970 IP 2.3.4.5.62987 > 5.6.7.8.80: Flags [.], ack 1, win
33304, options [nop,nop,TS val 576497064 ecr 760235190], length 0
>From what I can tell it appears that once the ACK to establish the
connection is received tcp_ack_update_rtt() is called from
tcp_rcv_state_process(). That will eventually compute the initial srtt
using tcp_time_stamp and the value in rcv_tsecr. Am I missing a
codepath because these are retransmissions?
Thanks for any help you can provide.
Josh
[-- Attachment #2: tcpdump-snippet --]
[-- Type: application/octet-stream, Size: 1484 bytes --]
* Reported RTT: 900 - looks like RTT should be ~252:
1294443792.878373 IP 1.2.3.4.49174 > 5.6.7.8.80: Flags [S], seq 2495182093, win 65535, options [mss 1460,nop,wscale 3,nop,nop,TS val 759815989 ecr 0,sackOK,eol], length 0
1294443792.878379 IP 5.6.7.8.80 > 1.2.3.4.49174: Flags [S.], seq 4249681570, ack 2495182094, win 5792, options [mss 1460,sackOK,TS val 760394055 ecr 759815989,nop,wscale 5], length 0
1294443793.656624 IP 5.6.7.8.80 > 1.2.3.4.49174: Flags [S.], seq 4249681570, ack 2495182094, win 5792, options [mss 1460,sackOK,TS val 760394834 ecr 759815989,nop,wscale 5], length 0
1294443793.908897 IP 1.2.3.4.49174 > 5.6.7.8.80: Flags [.], ack 1, win 65535, options [nop,nop,TS val 759816000 ecr 760394834], length 0
* Reported RTT: 913 - looks correct since it's replying to the original syn/ack:
1294443634.012920 IP 2.3.4.5.62987 > 5.6.7.8.80: Flags [S], seq 1397298575, win 65535, options [mss 1460,nop,wscale 1,nop,nop,TS val 576497055 ecr 0,sackOK,eol], length 0
1294443634.012931 IP 5.6.7.8.80 > 2.3.4.5.62987: Flags [S.], seq 1761430826, ack 1397298576, win 5792, options [mss 1460,sackOK,TS val 760235190 ecr 576497055,nop,wscale 5], length 0
1294443634.656625 IP 5.6.7.8.80 > 2.3.4.5.62987: Flags [S.], seq 1761430826, ack 1397298576, win 5792, options [mss 1460,sackOK,TS val 760235834 ecr 576497055,nop,wscale 5], length 0
1294443634.925970 IP 2.3.4.5.62987 > 5.6.7.8.80: Flags [.], ack 1, win 33304, options [nop,nop,TS val 576497064 ecr 760235190], length 0
^ permalink raw reply
* RE: [PATCH net-next-2.6 v3 1/1] can: c_can: Added support for Bosch C_CAN controller
From: Bhupesh SHARMA @ 2011-01-11 4:13 UTC (permalink / raw)
To: Wolfgang Grandegger, Oliver Hartkopp
Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org,
Marc Kleine-Budde, David Miller,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <4D29C8F6.5030806-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
Hi Oliver and Wolfgang,
> From: Wolfgang Grandegger [mailto:wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org]
> Hi Oliver,
>
> On 01/09/2011 12:01 PM, Oliver Hartkopp wrote:
> > On 06.01.2011 21:08, Wolfgang Grandegger wrote:
> >> Hi Marc,
> >>
> >> On 01/06/2011 08:44 PM, Marc Kleine-Budde wrote:
> >
> >>> If this driver will be merged, we'll have two drivers for the same
> can
> >>> core in the tree. The other one is the pch_can. What do you think
> should
> >>> be the mid term perspective for ccan based hardware?
> >>
> >> Yes, I know. Unfortunately, we did realize rather late the the PCH
> >> controller is a C_CAN clone and the OKI/Intel ppls did not tell us
> >> either. Therefore I asked Bhupesh to provide a SJA1000-a-like
> interface
> >> for the C_CAN, which would allow us to provide an alternative PCI
> driver
> >> "pch_pci.c" for the PCH. If that driver works well on the PCH
> hardware
> >> as well, we should merge the best of both, if necessary, and then
> >> finally remove the pch_can driver. Would that be a reasonable
> proposal.
> >
> > At least for me this looks great. The idea to have a similar approach
> as we
> > successfully implemented for the sja1000 will solve future hardware
> > implementations based on the ccan controller core.
>
> A common driver for c_can based devices will stabilize more quickly and
> does also especially reduce the maintanance effort significantly.
>
> > BTW. for the next submission of Bhupeshs patchset, i would propose to
> name the
> > driver 'ccan' instead of 'c_can', so that we have a
> >
> > linux/drivers/net/can/ccan/...
> >
> > path.
>
> You are late ;-). Bosch named the controller *C_CAN* and therefore I
> asked Bhupesh some time ago to change the file name and variable name
> prefix from ccan to c_can.
Actually V1 of this patchset used the naming convention ccan.
But as was rightly pointed out by Wolfgang and Mark, Bosch
has officially named this core as C_CAN and the naming convention
is kept as C_CAN throughout their user-manual and technical articles.
IMHO, `c_can` seems to represent this Bosch core in a better way
than ccan.
> > Checking directory names in linux/drivers with
> >
> > find . -type d | grep '_'
> >
> > driver names with underscores are pretty unusual and mostly selected
> without
> > fortune:
> >
> > ./staging/olpc_dcon
> > ./staging/wlags49_h2
> > ./staging/wlags49_h2/man
> > ./staging/serqt_usb2
> > ./staging/intel_sst
> > ./staging/quatech_usb2
> > ./staging/asus_oled
> > ./staging/wlags49_h25
> > ./staging/ath6kl/hif/sdio/linux_sdio <- Ugh!
> > ./staging/ath6kl/hif/sdio/linux_sdio/src
> > ./staging/ath6kl/hif/sdio/linux_sdio/include
> > ./net/pch_gbe
> > ./net/fs_enet
> > ./net/wireless/libertas_tf
> > ./net/ibm_newemacds
> >
> > For that reason i would prefer 'ccan' to name this driver core.
>
> Well, not really a strong argument. But well, if other people do
> *prefer* ccan I would not object against it. Bhupesh, what's your
> opinion.
I also prefer c_can :), because it makes the driver name similar to the
core name. Please let me know if you agree for the same.
Regards,
Bhupesh
^ permalink raw reply
* RE: [PATCH net-next-2.6 v3 1/1] can: c_can: Added support for Bosch C_CAN controller
From: Bhupesh SHARMA @ 2011-01-11 4:50 UTC (permalink / raw)
To: Wolfgang Grandegger
Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Marc Kleine-Budde,
David Miller, Oliver Hartkopp
In-Reply-To: <4D2829C5.5020206-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
Hi Wolfgang,
Thanks for your review.
Please see my comments inline.
> -----Original Message-----
> From: Wolfgang Grandegger [mailto:wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org]
> Hi Bhupesh,
>
> the patch already looks quite good. Just a few more issues...
>
> On 01/04/2011 10:59 AM, Bhupesh Sharma wrote:
> > Bosch C_CAN controller is a full-CAN implementation which is
> compliant
> > to CAN protocol version 2.0 part A and B. Bosch C_CAN user manual can
> be
> > obtained from:
> > http://www.semiconductors.bosch.de/pdf/Users_Manual_C_CAN.pdf
> >
> > This patch adds the support for this controller.
> > The following are the design choices made while writing the
> controller
> > driver:
> > 1. Interface Register set IF1 has be used only in the current design.
> > 2. Out of the 32 Message objects available, 16 are kept aside for RX
> > purposes and the rest for TX purposes.
> > 3. NAPI implementation is such that both the TX and RX paths function
> > in polling mode.
> >
> > Changes since V2:
> > 1. Seperately implemented a bus independent interface "c_can.c" and
> > a bus sensitive driver "c_can_platform.c". The bus sensitive
> driver
> > essentially caters to the details of registers mapping/arch
> differences
> > found on different SoCs.
> > 2. Changed RX poll method to allow *in-order packet reception*.
> > 3. Implemeneted LEC (last error code) as an enum.
> > 4. Implemented CAN_CTRLMODE_BERR_REPORTING.
> > 5. Corrected "quota" handling in RX poll routine.
> > 6. Implemented and used priv->can.do_get_berr_counter.
> > 7. Improved timeout-handling while programming IF command request
> > register.
> > 8. Corrected register offset typecasting to allow the same to work on
> > 64-bit systems.
> >
> > Signed-off-by: Bhupesh Sharma <bhupesh.sharma-qxv4g6HH51o@public.gmane.org>
> > ---
> > drivers/net/can/Kconfig | 2 +
> > drivers/net/can/Makefile | 1 +
> > drivers/net/can/c_can/Kconfig | 15 +
> > drivers/net/can/c_can/Makefile | 8 +
> > drivers/net/can/c_can/c_can.c | 960
> ++++++++++++++++++++++++++++++++
> > drivers/net/can/c_can/c_can.h | 235 ++++++++
> > drivers/net/can/c_can/c_can_platform.c | 210 +++++++
> > 7 files changed, 1431 insertions(+), 0 deletions(-)
> > create mode 100644 drivers/net/can/c_can/Kconfig
> > create mode 100644 drivers/net/can/c_can/Makefile
> > create mode 100644 drivers/net/can/c_can/c_can.c
> > create mode 100644 drivers/net/can/c_can/c_can.h
> > create mode 100644 drivers/net/can/c_can/c_can_platform.c
> >
> > diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> > index 9d9e453..50549b5 100644
> > --- a/drivers/net/can/Kconfig
> > +++ b/drivers/net/can/Kconfig
> > @@ -86,6 +86,8 @@ source "drivers/net/can/mscan/Kconfig"
> >
> > source "drivers/net/can/sja1000/Kconfig"
> >
> > +source "drivers/net/can/c_can/Kconfig"
> > +
> > source "drivers/net/can/usb/Kconfig"
> >
> > config CAN_DEBUG_DEVICES
> > diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
> > index 0057537..c3efeb3 100644
> > --- a/drivers/net/can/Makefile
> > +++ b/drivers/net/can/Makefile
> > @@ -11,6 +11,7 @@ obj-y += usb/
> >
> > obj-$(CONFIG_CAN_SJA1000) += sja1000/
> > obj-$(CONFIG_CAN_MSCAN) += mscan/
> > +obj-$(CONFIG_CAN_C_CAN) += c_can/
> > obj-$(CONFIG_CAN_AT91) += at91_can.o
> > obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
> > obj-$(CONFIG_CAN_MCP251X) += mcp251x.o
> > diff --git a/drivers/net/can/c_can/Kconfig
> b/drivers/net/can/c_can/Kconfig
> > new file mode 100644
> > index 0000000..ffb9773
> > --- /dev/null
> > +++ b/drivers/net/can/c_can/Kconfig
> > @@ -0,0 +1,15 @@
> > +menuconfig CAN_C_CAN
> > + tristate "Bosch C_CAN devices"
> > + depends on CAN_DEV && HAS_IOMEM
> > +
> > +if CAN_C_CAN
> > +
> > +config CAN_C_CAN_PLATFORM
> > + tristate "Generic Platform Bus based C_CAN driver"
> > + ---help---
> > + This driver adds support for the C_CAN chips connected to
> > + the "platform bus" (Linux abstraction for directly to the
> > + processor attached devices) which can be found on various
> > + boards from ST Microelectronics (http://www.st.com)
> > + like the SPEAr1310 and SPEAr320 evaluation boards.
> > +endif
>
> > diff --git a/drivers/net/can/c_can/Makefile
> b/drivers/net/can/c_can/Makefile
> > new file mode 100644
> > index 0000000..9273f6d
> > --- /dev/null
> > +++ b/drivers/net/can/c_can/Makefile
> > @@ -0,0 +1,8 @@
> > +#
> > +# Makefile for the Bosch C_CAN controller drivers.
> > +#
> > +
> > +obj-$(CONFIG_CAN_C_CAN) += c_can.o
> > +obj-$(CONFIG_CAN_C_CAN_PLATFORM) += c_can_platform.o
> > +
> > +ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
> > diff --git a/drivers/net/can/c_can/c_can.c
> b/drivers/net/can/c_can/c_can.c
> > new file mode 100644
> > index 0000000..206e650
> > --- /dev/null
> > +++ b/drivers/net/can/c_can/c_can.c
> > @@ -0,0 +1,960 @@
> > +/*
> > + * CAN bus driver for Bosch C_CAN controller
> > + *
> > + * Copyright (C) 2010 ST Microelectronics
> > + * Bhupesh Sharma <bhupesh.sharma-qxv4g6HH51o@public.gmane.org>
> > + *
> > + * Borrowed heavily from the C_CAN driver originally written by:
> > + * Copyright (C) 2007
> > + * - Sascha Hauer, Marc Kleine-Budde, Pengutronix
> <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> > + * - Simon Kallweit, intefo AG <simon.kallweit-+G9qxTFKJT/tRgLqZ5aouw@public.gmane.org>
> > + *
> > + * TX and RX NAPI implementation has been borrowed from at91 CAN
> driver
> > + * written by:
> > + * Copyright
> > + * (C) 2007 by Hans J. Koch <hjk-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> > + * (C) 2008, 2009 by Marc Kleine-Budde <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> > + *
> > + * Bosch C_CAN controller is compliant to CAN protocol version 2.0
> part A and B.
> > + * Bosch C_CAN user manual can be obtained from:
> > + * http://www.semiconductors.bosch.de/pdf/Users_Manual_C_CAN.pdf
>
> Unfortunately, this link is not valid any more.
Oops..
It seems they have shifted to:
http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/users_manual_c_can.pdf
> > + *
> > + * This file is licensed under the terms of the GNU General Public
> > + * License version 2. This program is licensed "as is" without any
> > + * warranty of any kind, whether express or implied.
> > + */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/version.h>
> > +#include <linux/module.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/delay.h>
> > +#include <linux/netdevice.h>
> > +#include <linux/if_arp.h>
> > +#include <linux/if_ether.h>
> > +#include <linux/list.h>
> > +#include <linux/delay.h>
> > +#include <linux/workqueue.h>
>
> Do you need that include?
I will check if this is really required.
Workqueues are no more there..
So, I will try to remove this in V4
> > +#include <linux/io.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/clk.h>
>
> ...and the upper two? They are related to platform code.
Ditto.
> > +#include <linux/can.h>
> > +#include <linux/can/dev.h>
> > +#include <linux/can/error.h>
> > +
> > +#include "c_can.h"
> > +
> > +static struct can_bittiming_const c_can_bittiming_const = {
> > + .name = KBUILD_MODNAME,
> > + .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1
> */
> > + .tseg1_max = 16,
> > + .tseg2_min = 1, /* Time segment 2 = phase_seg2 */
> > + .tseg2_max = 8,
> > + .sjw_max = 4,
> > + .brp_min = 1,
> > + .brp_max = 1024, /* 6-bit BRP field + 4-bit BRPE field*/
> > + .brp_inc = 1,
> > +};
> > +
> > +static inline int get_tx_next_msg_obj(const struct c_can_priv *priv)
> > +{
> > + return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) +
> > + C_CAN_MSG_OBJ_TX_FIRST;
> > +}
> > +
> > +static inline int get_tx_echo_msg_obj(const struct c_can_priv *priv)
> > +{
> > + return (priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) +
> > + C_CAN_MSG_OBJ_TX_FIRST;
> > +}
> > +
> > +static u32 c_can_read_reg32(struct c_can_priv *priv, void *reg)
> > +{
> > + u32 val = priv->read_reg(priv, reg);
> > + val |= ((u32) priv->read_reg(priv, reg + 2)) << 16;
> > + return val;
> > +}
> > +
> > +void c_can_enable_all_interrupts(struct c_can_priv *priv,
> > + int enable)
> > +{
> > + unsigned int cntrl_save = priv->read_reg(priv,
> > + &priv->reg_base->control);
> > +
> > + if (enable)
> > + cntrl_save |= (CONTROL_SIE | CONTROL_EIE | CONTROL_IE);
> > + else
> > + cntrl_save &= ~(CONTROL_EIE | CONTROL_IE | CONTROL_SIE);
> > +
> > + priv->write_reg(priv, &priv->reg_base->control, cntrl_save);
> > +}
> > +EXPORT_SYMBOL_GPL(c_can_enable_all_interrupts);
>
> Do you really need to export that function? More later.
Yes. The c_can_platform driver uses this routine to DISABLE
all interrupt sources when __devexit c_can_remove is called.
> > +
> > +static inline void c_can_object_get(struct net_device *dev,
> > + int iface, int objno, int mask)
> > +{
> > + struct c_can_priv *priv = netdev_priv(dev);
> > + int count = MIN_TIMEOUT_VALUE;
> > +
> > + /*
> > + * As per specs, after writting the message object number in the
> > + * IF command request register the transfer b/w interface
> > + * register and message RAM must be complete in 6 CAN-CLK
> > + * period.
> > + */
> > +
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].com_mask,
> > + IFX_WRITE_LOW_16BIT(mask));
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].com_reg,
> > + IFX_WRITE_LOW_16BIT(objno + 1));
> > +
> > + while (count) {
> > + if (!(priv->read_reg(priv,
> > + &priv->reg_base->ifreg[iface].com_reg) &
> > + IF_COMR_BUSY))
> > + break;
>
> Could be shortened to:
>
> while (count && priv->read_reg(priv,
> &priv->reg_base->ifreg[iface].com_reg) &
> IF_COMR_BUSY)
>
Ok. V4 will reflect this.
> > + count--;
> > + udelay(1);
> > + }
> > +
> > + if (!count)
> > + dev_err(dev->dev.parent, "timed out in object get\n");
> > +}
> > +
> > +static inline void c_can_object_put(struct net_device *dev,
> > + int iface, int objno, int mask)
> > +{
> > + struct c_can_priv *priv = netdev_priv(dev);
> > + int count = MIN_TIMEOUT_VALUE;
> > +
> > + /*
> > + * As per specs, after writting the message object number in the
> > + * IF command request register the transfer b/w interface
> > + * register and message RAM must be complete in 6 CAN-CLK
> > + * period.
> > + */
> > +
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].com_mask,
> > + (IF_COMM_WR | IFX_WRITE_LOW_16BIT(mask)));
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].com_reg,
> > + IFX_WRITE_LOW_16BIT(objno + 1));
> > +
> > + while (count) {
> > + if (!(priv->read_reg(priv,
> > + &priv->reg_base->ifreg[iface].com_reg) &
> > + IF_COMR_BUSY))
> > + break;
>
> Ditto. Also this is duplicated code. A (inline) function would make
> sense.
I agree. V4 will add a new *inline* function for this.
> > +
> > + count--;
> > + udelay(1);
> > + }
> > +
> > + if (!count)
> > + dev_err(dev->dev.parent, "timed out in object put\n");
> > +}
> > +
> > +int c_can_write_msg_object(struct net_device *dev,
> > + int iface, struct can_frame *frame, int objno)
> > +{
> > + int i;
> > + u16 flags = 0;
> > + unsigned int id;
> > + struct c_can_priv *priv = netdev_priv(dev);
> > +
> > + if (frame->can_id & CAN_EFF_FLAG) {
> > + id = frame->can_id & CAN_EFF_MASK;
> > + flags |= IF_ARB_MSGXTD;
> > + } else
> > + id = ((frame->can_id & CAN_SFF_MASK) << 18);
> > +
> > + if (!(frame->can_id & CAN_RTR_FLAG))
> > + flags |= IF_ARB_TRANSMIT;
> > +
> > + flags |= IF_ARB_MSGVAL;
> > +
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].arb1,
> > + IFX_WRITE_LOW_16BIT(id));
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].arb2, flags |
> > + IFX_WRITE_HIGH_16BIT(id));
> > +
> > + for (i = 0; i < frame->can_dlc; i += 2) {
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].data[i
> / 2],
> > + frame->data[i] | (frame->data[i + 1] << 8));
> > + }
> > +
> > + return frame->can_dlc;
> > +}
> > +
> > +static inline void c_can_mark_rx_msg_obj(struct net_device *dev,
> > + int iface, int ctrl_mask,
> > + int obj)
> > +{
> > + struct c_can_priv *priv = netdev_priv(dev);
> > +
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].msg_cntrl,
> > + ctrl_mask & ~(IF_MCONT_MSGLST | IF_MCONT_INTPND));
> > +
> > + c_can_object_put(dev, iface, obj, IF_COMM_CONTROL);
> > +
>
> Please remove empty line above.
Ok.
> > +}
> > +
> > +static inline void c_can_activate_all_lower_rx_msg_obj(struct
> net_device *dev,
> > + int iface,
> > + int ctrl_mask)
> > +{
> > + int i;
> > + struct c_can_priv *priv = netdev_priv(dev);
> > +
> > + for (i = 0; i < C_CAN_MSG_RX_LOW_LAST; i++) {
> > + priv->write_reg(priv, &priv->reg_base-
> >ifreg[iface].msg_cntrl,
> > + ctrl_mask & ~(IF_MCONT_MSGLST |
> > + IF_MCONT_INTPND | IF_MCONT_NEWDAT));
> > + c_can_object_put(dev, iface, i + 1, IF_COMM_CONTROL);
> > + }
> > +}
> > +
> > +static inline void c_can_activate_rx_msg_obj(struct net_device *dev,
> > + int iface, int ctrl_mask,
> > + int obj)
> > +{
> > + struct c_can_priv *priv = netdev_priv(dev);
> > +
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].msg_cntrl,
> > + ctrl_mask & ~(IF_MCONT_MSGLST |
> > + IF_MCONT_INTPND | IF_MCONT_NEWDAT));
> > +
> > + c_can_object_put(dev, iface, obj, IF_COMM_CONTROL);
>
> Ditto.
Ok.
> > +}
> > +
> > +static void c_can_handle_lost_msg_obj(struct net_device *dev,
> > + int iface, int objno)
> > +{
> > + struct c_can_priv *priv = netdev_priv(dev);
> > + struct net_device_stats *stats = &dev->stats;
> > + struct sk_buff *skb;
> > + struct can_frame *frame;
> > +
> > + dev_err(dev->dev.parent, "msg lost in buffer %d\n", objno);
> > +
> > + c_can_object_get(dev, iface, objno, IF_COMM_ALL &
> > + ~IF_COMM_TXRQST);
> > +
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].msg_cntrl,
> > + IF_MCONT_CLR_MSGLST);
> > +
> > + c_can_object_put(dev, 0, objno, IF_COMM_CONTROL);
> > +
> > + /* create an error msg */
> > + skb = alloc_can_err_skb(dev, &frame);
> > + if (unlikely(!skb))
> > + return;
> > +
> > + frame->can_id |= CAN_ERR_CRTL;
> > + frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
> > + stats->rx_errors++;
> > + stats->rx_over_errors++;
> > +
> > + netif_receive_skb(skb);
> > +}
> > +
> > +static int c_can_read_msg_object(struct net_device *dev, int iface,
> int ctrl,
> > + int objno)
> > +{
> > + u16 flags, data;
> > + int i;
> > + unsigned int val;
> > + struct c_can_priv *priv = netdev_priv(dev);
> > + struct net_device_stats *stats = &dev->stats;
> > + struct sk_buff *skb;
> > + struct can_frame *frame;
> > +
> > + skb = alloc_can_skb(dev, &frame);
> > + if (!skb) {
> > + stats->rx_dropped++;
> > + return -ENOMEM;
> > + }
> > +
> > + frame->can_dlc = get_can_dlc(ctrl & 0x0F);
> > +
> > + for (i = 0; i < frame->can_dlc; i += 2) {
> > + data = priv->read_reg(priv,
> > + &priv->reg_base->ifreg[iface].data[i / 2]);
> > + frame->data[i] = data;
> > + frame->data[i + 1] = data >> 8;
> > + }
> > +
> > + flags = priv->read_reg(priv, &priv->reg_base-
> >ifreg[iface].arb2);
> > + val = priv->read_reg(priv, &priv->reg_base->ifreg[iface].arb1) |
> > + (flags << 16);
> > +
> > + if (flags & IF_ARB_MSGXTD)
> > + frame->can_id = (val & CAN_EFF_MASK) | CAN_EFF_FLAG;
> > + else
> > + frame->can_id = (val >> 18) & CAN_SFF_MASK;
> > +
> > + if (flags & IF_ARB_TRANSMIT)
> > + frame->can_id |= CAN_RTR_FLAG;
> > +
> > + netif_receive_skb(skb);
> > +
> > + stats->rx_packets++;
> > + stats->rx_bytes += frame->can_dlc;
> > +
> > + return 0;
> > +}
> > +
> > +static void c_can_setup_receive_object(struct net_device *dev, int
> iface,
> > + int objno, unsigned int mask,
> > + unsigned int id, unsigned int mcont)
> > +{
> > + struct c_can_priv *priv = netdev_priv(dev);
> > +
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].mask1,
> > + IFX_WRITE_LOW_16BIT(mask));
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].mask2,
> > + IFX_WRITE_HIGH_16BIT(mask));
> > +
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].arb1,
> > + IFX_WRITE_LOW_16BIT(id));
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].arb2,
> > + (IF_ARB_MSGVAL | IFX_WRITE_HIGH_16BIT(id)));
> > +
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].msg_cntrl,
> mcont);
> > + c_can_object_put(dev, iface, objno, IF_COMM_ALL &
> > + ~IF_COMM_TXRQST);
>
> Should fit on one line.
Ok.
> > +
> > + dev_dbg(dev->dev.parent, "obj no:%d, msgval:0x%08x\n", objno,
> > + c_can_read_reg32(priv, &priv->reg_base->msgval1));
>
> Please remove empty line above.
Ok.
> > +}
> > +
> > +static void c_can_inval_msg_object(struct net_device *dev, int
> iface, int objno)
> > +{
> > + struct c_can_priv *priv = netdev_priv(dev);
> > +
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].arb1, 0);
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].arb2, 0);
> > + priv->write_reg(priv, &priv->reg_base->ifreg[iface].msg_cntrl,
> 0);
> > +
> > + c_can_object_put(dev, iface, objno,
> > + IF_COMM_ARB | IF_COMM_CONTROL);
> > +
> > + dev_dbg(dev->dev.parent, "obj no:%d, msgval:0x%08x\n", objno,
> > + c_can_read_reg32(priv, &priv->reg_base->msgval1));
>
> Ditto.
Ok.
> > +}
> > +
> > +static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
> > + struct net_device *dev)
> > +{
> > + u32 val;
> > + u32 msg_obj_no;
> > + struct c_can_priv *priv = netdev_priv(dev);
> > + struct can_frame *frame = (struct can_frame *)skb->data;
> > +
> > + if (can_dropped_invalid_skb(dev, skb))
> > + return NETDEV_TX_OK;
> > +
> > + msg_obj_no = get_tx_next_msg_obj(priv);
> > +
> > + /* prepare message object for transmission */
> > + val = c_can_write_msg_object(dev, 0, frame, msg_obj_no);
> > +
> > + /* enable interrupt for this message object */
> > + priv->write_reg(priv, &priv->reg_base->ifreg[0].msg_cntrl,
> > + IF_MCONT_TXIE | IF_MCONT_TXRQST | IF_MCONT_EOB |
> > + (val & 0xf));
> > + c_can_object_put(dev, 0, msg_obj_no, IF_COMM_ALL);
> > +
> > + can_put_echo_skb(skb, dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
> > +
> > + priv->tx_next++;
> > + if ((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0)
> > + netif_stop_queue(dev);
> > +
> > + return NETDEV_TX_OK;
> > +}
> > +
> > +static int c_can_set_bittiming(struct net_device *dev)
> > +{
> > + unsigned int reg_btr, reg_brpe, ctrl_save;
> > + u8 brp, brpe, sjw, tseg1, tseg2;
> > + u32 ten_bit_brp;
> > + struct c_can_priv *priv = netdev_priv(dev);
> > + const struct can_bittiming *bt = &priv->can.bittiming;
> > +
> > + /* c_can provides a 6-bit brp and 4-bit brpe fields */
> > + ten_bit_brp = bt->brp - 1;
> > + brp = ten_bit_brp & BTR_BRP_MASK;
> > + brpe = ten_bit_brp >> 6;
> > +
> > + sjw = bt->sjw - 1;
> > + tseg1 = bt->prop_seg + bt->phase_seg1 - 1;
> > + tseg2 = bt->phase_seg2 - 1;
> > +
> > + reg_btr = ((brp) | (sjw << BTR_SJW_SHIFT) | (tseg1 <<
> BTR_TSEG1_SHIFT) |
> > + (tseg2 << BTR_TSEG2_SHIFT));
>
> The outer brackets are not needed.
Ok.
> > + reg_brpe = brpe & BRP_EXT_BRPE_MASK;
> > +
> > + dev_info(dev->dev.parent,
> > + "setting BTR=%04x BRPE=%04x\n", reg_btr, reg_brpe);
> > +
> > + ctrl_save = priv->read_reg(priv, &priv->reg_base->control);
> > + priv->write_reg(priv, &priv->reg_base->control,
> > + ctrl_save | CONTROL_CCE | CONTROL_INIT);
> > + priv->write_reg(priv, &priv->reg_base->btr, reg_btr);
> > + priv->write_reg(priv, &priv->reg_base->brp_ext, reg_brpe);
> > + priv->write_reg(priv, &priv->reg_base->control, ctrl_save);
> > +
> > + return 0;
> > +}
> > +
> > +/*
> > + * Configure C_CAN message objects for Tx and Rx purposes:
> > + * C_CAN provides a total of 32 message objects that can be
> configured
> > + * either for Tx or Rx purposes. Here the first 16 message objects
> are used as
> > + * a reception FIFO. The end of reception FIFO is signified by the
> EoB bit
> > + * being SET. The remaining 16 message objects are kept aside for Tx
> purposes.
> > + * See user guide document for further details on configuring
> message
> > + * objects.
> > + */
> > +static void c_can_configure_msg_objects(struct net_device *dev)
> > +{
> > + int i;
> > +
> > + /* first invalidate all message objects */
> > + for (i = 0; i <= C_CAN_NO_OF_OBJECTS; i++)
> > + c_can_inval_msg_object(dev, 0, i);
> > +
> > + /* setup receive message objects */
> > + for (i = C_CAN_MSG_OBJ_RX_FIRST + 1 ; i < C_CAN_MSG_OBJ_RX_LAST;
> i++)
> > + c_can_setup_receive_object(dev, 0, i, 0, 0,
> > + ((IF_MCONT_RXIE | IF_MCONT_UMASK) & ~IF_MCONT_EOB));
>
> Ditto.
Ok.
> > + c_can_setup_receive_object(dev, 0, C_CAN_MSG_OBJ_RX_LAST, 0, 0,
> > + IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK);
> > +}
> > +
> > +/*
> > + * Configure C_CAN chip:
> > + * - enable/disable auto-retransmission
> > + * - set operating mode
> > + * - configure message objects
> > + */
> > +static void c_can_chip_config(struct net_device *dev)
> > +{
> > + struct c_can_priv *priv = netdev_priv(dev);
> > +
> > + if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
> > + /* disable automatic retransmission */
> > + priv->write_reg(priv, &priv->reg_base->control,
> > + CONTROL_DISABLE_AR);
> > + else
> > + /* enable automatic retransmission */
> > + priv->write_reg(priv, &priv->reg_base->control,
> > + CONTROL_ENABLE_AR);
> > +
> > + if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY &
> > + CAN_CTRLMODE_LOOPBACK)) {
> > + /* loopback + silent mode : useful for hot self-test */
> > + priv->write_reg(priv, &priv->reg_base->control,
> (CONTROL_EIE |
> > + CONTROL_SIE | CONTROL_IE | CONTROL_TEST));
>
> Outer brackets are not needed.
Ok.
> > + priv->write_reg(priv, &priv->reg_base->test,
> > + (TEST_LBACK | TEST_SILENT));
> > + } else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
> > + /* loopback mode : useful for self-test function */
> > + priv->write_reg(priv, &priv->reg_base->control,
> (CONTROL_EIE |
> > + CONTROL_SIE | CONTROL_IE | CONTROL_TEST));
>
> Ditto.
Ok.
> > + priv->write_reg(priv, &priv->reg_base->test, TEST_LBACK);
> > + } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
> > + /* silent mode : bus-monitoring mode */
> > + priv->write_reg(priv, &priv->reg_base->control,
> (CONTROL_EIE |
> > + CONTROL_SIE | CONTROL_IE | CONTROL_TEST));
>
> Ditto.
Ok.
> > + priv->write_reg(priv, &priv->reg_base->test, TEST_SILENT);
> > + } else
> > + /* normal mode*/
> > + priv->write_reg(priv, &priv->reg_base->control,
> > + (CONTROL_EIE | CONTROL_SIE | CONTROL_IE));
>
> Ditto.
Ok.
> > + /* configure message objects */
> > + c_can_configure_msg_objects(dev);
> > +}
> > +
> > +static void c_can_start(struct net_device *dev)
> > +{
> > + struct c_can_priv *priv = netdev_priv(dev);
> > +
> > + /* enable status change, error and module interrupts */
> > + c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
> > +
> > + /* basic c_can configuration */
> > + c_can_chip_config(dev);
> > +
> > + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> > +
> > + /* reset tx helper pointers */
> > + priv->tx_next = priv->tx_echo = 0;
> > +}
> > +
> > +static void c_can_stop(struct net_device *dev)
> > +{
> > + struct c_can_priv *priv = netdev_priv(dev);
> > +
> > + /* disable all interrupts */
> > + c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
> > +
> > + /* set the state as STOPPED */
> > + priv->can.state = CAN_STATE_STOPPED;
> > +}
> > +
> > +static int c_can_set_mode(struct net_device *dev, enum can_mode
> mode)
> > +{
> > + switch (mode) {
> > + case CAN_MODE_START:
> > + c_can_start(dev);
> > + netif_wake_queue(dev);
> > + break;
> > + default:
> > + return -EOPNOTSUPP;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int c_can_get_berr_counter(const struct net_device *dev,
> > + struct can_berr_counter *bec)
> > +{
> > + unsigned int reg_err_counter;
> > + struct c_can_priv *priv = netdev_priv(dev);
> > +
> > + reg_err_counter = priv->read_reg(priv, &priv->reg_base-
> >error_counter);
> > + bec->rxerr = ((reg_err_counter & ERR_COUNTER_REC_MASK) >>
> > + ERR_COUNTER_REC_SHIFT);
>
> You don't need the out brackets.
Ok.
> > + bec->txerr = (reg_err_counter & ERR_COUNTER_TEC_MASK);
>
> Ditto.
Ok.
> > + return 0;
> > +}
> > +
> > +/*
> > + * 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 c_can_do_tx(struct net_device *dev)
> > +{
> > + u32 val;
> > + u32 msg_obj_no;
> > + struct c_can_priv *priv = netdev_priv(dev);
> > + struct net_device_stats *stats = &dev->stats;
> > +
> > + for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv-
> >tx_echo++) {
> > + msg_obj_no = get_tx_echo_msg_obj(priv);
> > + c_can_inval_msg_object(dev, 0, msg_obj_no);
> > + val = c_can_read_reg32(priv, &priv->reg_base->txrqst1);
> > + if (!(val & (1 << msg_obj_no))) {
> > + can_get_echo_skb(dev,
> > + msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
> > + stats->tx_bytes += priv->read_reg(priv,
> > + &priv->reg_base->ifreg[0].msg_cntrl)
> > + & IF_MCONT_DLC_MASK;
> > + stats->tx_packets++;
> > + }
> > + }
> > +
> > + /* restart queue if wrap-up or if queue stalled on last pkt */
> > + if (((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) != 0) ||
> > + ((priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) == 0))
> > + netif_wake_queue(dev);
> > +}
> > +
> > +/*
> > + * theory of operation:
> > + *
> > + * c_can core saves a received CAN message into the first free
> message
> > + * object it finds free (starting with the lowest). Bits NEWDAT and
> > + * INTPND are set for this message object indicating that a new
> message
> > + * has arrived. To work-around this issue, we keep two groups of
> message
> > + * objects whose partitioning is defined by C_CAN_MSG_OBJ_RX_SPLIT.
> > + *
> > + * To ensure in-order frame reception we use the following
> > + * approach while re-activating a message object to receive further
> > + * frames:
> > + * - if the current message object number is lower than
> > + * C_CAN_MSG_RX_LOW_LAST, do not clear the NEWDAT bit while
> clearing
> > + * the INTPND bit.
> > + * - if the current message object number is equal to
> > + * C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of all lower
> > + * receive message objects.
> > + * - if the current message object number is greater than
> > + * C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of
> > + * only this message object.
> > + */
> > +static int c_can_do_rx_poll(struct net_device *dev, int quota)
> > +{
> > + u32 num_rx_pkts = 0;
> > + unsigned int msg_obj, msg_ctrl_save;
> > + struct c_can_priv *priv = netdev_priv(dev);
> > + u32 val = c_can_read_reg32(priv, &priv->reg_base->intpnd1);
> > +
> > + for (msg_obj = C_CAN_MSG_OBJ_RX_FIRST;
> > + msg_obj <= C_CAN_MSG_OBJ_RX_LAST && quota > 0;
> > + msg_obj++) {
> > + if (val & (1 << msg_obj)) {
> > + c_can_object_get(dev, 0, msg_obj, IF_COMM_ALL &
> > + ~IF_COMM_TXRQST);
> > + msg_ctrl_save = priv->read_reg(priv,
> > + &priv->reg_base->ifreg[0].msg_cntrl);
> > +
> > + if (msg_ctrl_save & IF_MCONT_EOB)
> > + return num_rx_pkts;
> > +
> > + if (msg_ctrl_save & IF_MCONT_MSGLST) {
> > + c_can_handle_lost_msg_obj(dev, 0, msg_obj);
> > + num_rx_pkts++;
> > + quota--;
> > + continue;
> > + }
> > +
> > + if (!(msg_ctrl_save & IF_MCONT_NEWDAT))
> > + continue;
> > +
> > + /* read the data from the message object */
> > + c_can_read_msg_object(dev, 0, msg_ctrl_save,
> msg_obj);
> > +
> > + if (msg_obj < C_CAN_MSG_RX_LOW_LAST)
> > + c_can_mark_rx_msg_obj(dev, 0,
> > + msg_ctrl_save, msg_obj);
> > + else if (msg_obj > C_CAN_MSG_RX_LOW_LAST)
> > + /* activate this msg obj */
> > + c_can_activate_rx_msg_obj(dev, 0,
> > + msg_ctrl_save, msg_obj);
> > + else if (msg_obj == C_CAN_MSG_RX_LOW_LAST)
> > + /* activate all lower message objects */
> > + c_can_activate_all_lower_rx_msg_obj(dev,
> > + 0, msg_ctrl_save);
> > +
> > + num_rx_pkts++;
> > + quota--;
> > + }
> > + val = c_can_read_reg32(priv, &priv->reg_base->intpnd1);
> > + }
> > +
> > + return num_rx_pkts;
> > +}
> > +
> > +static inline int c_can_has_and_handle_berr(struct c_can_priv *priv)
> > +{
> > + return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) &&
> > + (priv->current_status & STATUS_LEC_MASK);
> > +}
> > +
> > +static int c_can_err(struct net_device *dev,
> > + enum c_can_bus_error_types error_type,
> > + enum c_can_lec_type lec_type)
> > +{
> > + unsigned int reg_err_counter;
> > + unsigned int rx_err_passive;
> > + struct c_can_priv *priv = netdev_priv(dev);
> > + struct net_device_stats *stats = &dev->stats;
> > + struct can_frame *cf;
> > + struct sk_buff *skb;
> > + struct can_berr_counter bec;
> > +
> > + /* propogate the error condition to the CAN stack */
> > + skb = alloc_can_err_skb(dev, &cf);
> > + if (unlikely(!skb))
> > + return 0;
> > +
> > + c_can_get_berr_counter(dev, &bec);
> > + reg_err_counter = priv->read_reg(priv, &priv->reg_base-
> >error_counter);
> > + rx_err_passive = ((reg_err_counter & ERR_COUNTER_RP_MASK) >>
> > + ERR_COUNTER_RP_SHIFT);
>
> Outer brackset?
Ok. Will be removed in V4.
> > + if (error_type & C_CAN_ERROR_WARNING) {
> > + /* error warning state */
> > + priv->can.can_stats.error_warning++;
> > + priv->can.state = CAN_STATE_ERROR_WARNING;
> > + cf->can_id |= CAN_ERR_CRTL;
> > + if (bec.rxerr > 96)
> > + cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
> > + if (bec.txerr > 96)
> > + cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
> > + }
> > + if (error_type & C_CAN_ERROR_PASSIVE) {
> > + /* error passive state */
> > + priv->can.can_stats.error_passive++;
> > + priv->can.state = CAN_STATE_ERROR_PASSIVE;
> > + cf->can_id |= CAN_ERR_CRTL;
> > + if (rx_err_passive)
> > + cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
> > + if (bec.txerr > 127)
> > + cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
> > + }
> > + if (error_type & C_CAN_BUS_OFF) {
> > + /* bus-off state */
> > + priv->can.state = CAN_STATE_BUS_OFF;
> > + cf->can_id |= CAN_ERR_BUSOFF;
> > + /* disable all interrupts in bus-off mode to ensure that
> > + * the CPU is not hogged down
> > + */
>
> Please use the following style:
>
> /*
> * Comment
> */
Ok.
> > + c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
> > + can_bus_off(dev);
> > + }
> > +
> > + /*
> > + * check for 'last error code' which tells us the
> > + * type of the last error to occur on the CAN bus
> > + */
> > + switch (lec_type) {
> > + /* common for all type of bus errors */
> > + priv->can.can_stats.bus_error++;
> > + stats->rx_errors++;
> > + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
> > + cf->data[2] |= CAN_ERR_PROT_UNSPEC;
>
> Are you sure that this part is ever executed? I wonder why the compile
> does
> not complain.
I did not get any compilation error.
But I will check if the program flow enters this part or not.
> > + case LEC_STUFF_ERROR:
> > + dev_dbg(dev->dev.parent, "stuff error\n");
> > + cf->data[2] |= CAN_ERR_PROT_STUFF;
> > + break;
> > +
> > + case LEC_FORM_ERROR:
> > + dev_dbg(dev->dev.parent, "form error\n");
> > + cf->data[2] |= CAN_ERR_PROT_FORM;
> > + break;
> > +
> > + case LEC_ACK_ERROR:
> > + dev_dbg(dev->dev.parent, "ack error\n");
> > + cf->data[2] |= (CAN_ERR_PROT_LOC_ACK |
> > + CAN_ERR_PROT_LOC_ACK_DEL);
> > + break;
> > +
> > + case LEC_BIT1_ERROR:
> > + dev_dbg(dev->dev.parent, "bit1 error\n");
> > + cf->data[2] |= CAN_ERR_PROT_BIT1;
> > + break;
> > +
> > + case LEC_BIT0_ERROR:
> > + dev_dbg(dev->dev.parent, "bit0 error\n");
> > + cf->data[2] |= CAN_ERR_PROT_BIT0;
> > + break;
> > +
> > + case LEC_CRC_ERROR:
> > + dev_dbg(dev->dev.parent, "CRC error\n");
> > + cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
> > + CAN_ERR_PROT_LOC_CRC_DEL);
> > + break;
> > + }
> > +
> > + netif_receive_skb(skb);
> > + stats->rx_packets++;
> > + stats->rx_bytes += cf->can_dlc;
> > +
> > + return 1;
> > +}
> > +
> > +static int c_can_poll(struct napi_struct *napi, int quota)
> > +{
> > + u16 irqstatus;
> > + int lec_type = 0;
> > + int work_done = 0;
> > + struct net_device *dev = napi->dev;
> > + struct c_can_priv *priv = netdev_priv(dev);
> > + enum c_can_bus_error_types error_type = C_CAN_NO_ERROR;
> > +
> > + irqstatus = priv->read_reg(priv, &priv->reg_base->ir);
> > +
> > + /* status events have the highest priority */
> > + if (irqstatus == STATUS_INTERRUPT) {
> > + priv->current_status = priv->read_reg(priv,
> > + &priv->reg_base->status);
> > +
> > + /* handle Tx/Rx events */
> > + if (priv->current_status & STATUS_TXOK)
> > + priv->write_reg(priv, &priv->reg_base->status,
> > + (priv->current_status & ~STATUS_TXOK));
>
> Outer bracket are not needed. Here and in similar expressions below.
Ok. I will check for redundant outer-bracket usage globally.
> > +
> > + if (priv->current_status & STATUS_RXOK)
> > + priv->write_reg(priv, &priv->reg_base->status,
> > + (priv->current_status & ~STATUS_RXOK));
> > +
> > + /* handle bus error events */
> > + if (priv->current_status & STATUS_EWARN) {
> > + dev_dbg(dev->dev.parent,
> > + "entered error warning state\n");
> > + error_type = C_CAN_ERROR_WARNING;
> > + }
> > + if ((priv->current_status & STATUS_EPASS) &&
> > + (!(priv->last_status & STATUS_EPASS))) {
> > + dev_dbg(dev->dev.parent,
> > + "entered error passive state\n");
> > + error_type = C_CAN_ERROR_PASSIVE;
> > + }
> > + if ((priv->current_status & STATUS_BOFF) &&
> > + (!(priv->last_status & STATUS_BOFF))) {
> > + dev_dbg(dev->dev.parent,
> > + "entered bus off state\n");
> > + error_type = C_CAN_BUS_OFF;
> > + }
> > +
> > + /* handle bus recovery events */
> > + if ((!(priv->current_status & STATUS_EPASS)) &&
> > + (priv->last_status & STATUS_EPASS)) {
> > + dev_dbg(dev->dev.parent,
> > + "left error passive state\n");
> > + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> > + }
> > + if ((!(priv->current_status & STATUS_BOFF)) &&
> > + (priv->last_status & STATUS_BOFF)) {
> > + dev_dbg(dev->dev.parent,
> > + "left bus off state\n");
> > + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> > + }
> > +
> > + priv->last_status = priv->current_status;
> > +
> > + /* handle error on the bus */
> > + lec_type = c_can_has_and_handle_berr(priv);
> > + if (lec_type && (error_type != C_CAN_NO_ERROR))
> > + work_done += c_can_err(dev, error_type, lec_type);
> > + } else if ((irqstatus > C_CAN_MSG_OBJ_RX_FIRST) &&
> > + (irqstatus <= C_CAN_MSG_OBJ_RX_LAST)) {
> > + /* handle events corresponding to receive message objects
> */
> > + work_done += c_can_do_rx_poll(dev, (quota - work_done));
> > + } else if ((irqstatus > C_CAN_MSG_OBJ_TX_FIRST) &&
> > + (irqstatus <= C_CAN_MSG_OBJ_TX_LAST)) {
> > + /* handle events corresponding to transmit message objects
> */
> > + c_can_do_tx(dev);
> > + }
> > +
> > + if (work_done < quota) {
> > + napi_complete(napi);
> > + /* enable all IRQs */
> > + c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
> > + }
> > +
> > + return work_done;
> > +}
> > +
> > +static irqreturn_t c_can_isr(int irq, void *dev_id)
> > +{
> > + struct net_device *dev = (struct net_device *)dev_id;
> > + struct c_can_priv *priv = netdev_priv(dev);
> > +
> > + /* disable all interrupts and schedule the NAPI */
> > + c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
> > + napi_schedule(&priv->napi);
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int c_can_open(struct net_device *dev)
> > +{
> > + int err;
> > + struct c_can_priv *priv = netdev_priv(dev);
> > +
> > + /* open the can device */
> > + err = open_candev(dev);
> > + if (err) {
> > + dev_err(dev->dev.parent, "failed to open can device\n");
> > + return err;
> > + }
> > +
> > + /* register interrupt handler */
> > + err = request_irq(dev->irq, &c_can_isr, priv->irq_flags, dev-
> >name,
> > + dev);
> > + if (err < 0) {
> > + dev_err(dev->dev.parent, "failed to attach interrupt\n");
>
> s/attach/request/ ?
Ok.
> > + goto exit_irq_fail;
> > + }
> > +
> > + /* start the c_can controller */
> > + c_can_start(dev);
> > +
> > + napi_enable(&priv->napi);
> > + netif_start_queue(dev);
> > +
> > + return 0;
> > +
> > +exit_irq_fail:
> > + close_candev(dev);
> > + return err;
> > +}
> > +
> > +static int c_can_close(struct net_device *dev)
> > +{
> > + struct c_can_priv *priv = netdev_priv(dev);
> > +
> > + netif_stop_queue(dev);
> > + napi_disable(&priv->napi);
> > + c_can_stop(dev);
> > + free_irq(dev->irq, dev);
> > + close_candev(dev);
> > +
> > + return 0;
> > +}
> > +
> > +struct net_device *alloc_c_can_dev(void)
> > +{
> > + struct net_device *dev;
> > + struct c_can_priv *priv;
> > +
> > + dev = alloc_candev(sizeof(struct c_can_priv),
> C_CAN_MSG_OBJ_TX_NUM);
> > + if (!dev)
> > + return NULL;
> > +
> > + priv = netdev_priv(dev);
> > + netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT);
> > +
> > + priv->dev = dev;
> > + priv->can.bittiming_const = &c_can_bittiming_const;
> > + priv->can.do_set_bittiming = c_can_set_bittiming;
> > + priv->can.do_set_mode = c_can_set_mode;
> > + priv->can.do_get_berr_counter = c_can_get_berr_counter;
> > + priv->can.ctrlmode_supported = CAN_CTRLMODE_ONE_SHOT |
> > + CAN_CTRLMODE_LOOPBACK |
> > + CAN_CTRLMODE_LISTENONLY |
> > + CAN_CTRLMODE_BERR_REPORTING;
> > +
> > + return dev;
> > +}
> > +EXPORT_SYMBOL_GPL(alloc_c_can_dev);
> > +
> > +void free_c_can_dev(struct net_device *dev)
> > +{
> > + free_candev(dev);
> > +}
> > +EXPORT_SYMBOL_GPL(free_c_can_dev);
> > +
> > +static const struct net_device_ops c_can_netdev_ops = {
> > + .ndo_open = c_can_open,
> > + .ndo_stop = c_can_close,
> > + .ndo_start_xmit = c_can_start_xmit,
> > +};
> > +
> > +int register_c_can_dev(struct net_device *dev)
> > +{
> > + dev->flags |= IFF_ECHO; /* we support local echo */
> > + dev->netdev_ops = &c_can_netdev_ops;
> > +
> > + return register_candev(dev);
> > +}
> > +EXPORT_SYMBOL_GPL(register_c_can_dev);
> > +
> > +void unregister_c_can_dev(struct net_device *dev)
> > +{
> > + unregister_candev(dev);
> > +}
> > +EXPORT_SYMBOL_GPL(unregister_c_can_dev);
> > +
> > +MODULE_AUTHOR("Bhupesh Sharma <bhupesh.sharma-qxv4g6HH51o@public.gmane.org>");
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_DESCRIPTION("CAN bus driver for Bosch C_CAN controller");
> > diff --git a/drivers/net/can/c_can/c_can.h
> b/drivers/net/can/c_can/c_can.h
> > new file mode 100644
> > index 0000000..fafc5e6
> > --- /dev/null
> > +++ b/drivers/net/can/c_can/c_can.h
> > @@ -0,0 +1,235 @@
> > +/*
> > + * CAN bus driver for Bosch C_CAN controller
> > + *
> > + * Copyright (C) 2010 ST Microelectronics
> > + * Bhupesh Sharma <bhupesh.sharma-qxv4g6HH51o@public.gmane.org>
> > + *
> > + * Borrowed heavily from the C_CAN driver originally written by:
> > + * Copyright (C) 2007
> > + * - Sascha Hauer, Marc Kleine-Budde, Pengutronix
> <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> > + * - Simon Kallweit, intefo AG <simon.kallweit-+G9qxTFKJT/tRgLqZ5aouw@public.gmane.org>
> > + *
> > + * TX and RX NAPI implementation has been borrowed from at91 CAN
> driver
> > + * written by:
> > + * Copyright
> > + * (C) 2007 by Hans J. Koch <hjk-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> > + * (C) 2008, 2009 by Marc Kleine-Budde <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> > + *
> > + * Bosch C_CAN controller is compliant to CAN protocol version 2.0
> part A and B.
> > + * Bosch C_CAN user manual can be obtained from:
> > + * http://www.semiconductors.bosch.de/pdf/Users_Manual_C_CAN.pdf
> > + *
> > + * This file is licensed under the terms of the GNU General Public
> > + * License version 2. This program is licensed "as is" without any
> > + * warranty of any kind, whether express or implied.
> > + */
> > +
> > +#ifndef C_CAN_H
> > +#define C_CAN_H
> > +
> > +/* control register */
> > +#define CONTROL_TEST BIT(7)
> > +#define CONTROL_CCE BIT(6)
> > +#define CONTROL_DISABLE_AR BIT(5)
> > +#define CONTROL_ENABLE_AR (0 << 5)
> > +#define CONTROL_EIE BIT(3)
> > +#define CONTROL_SIE BIT(2)
> > +#define CONTROL_IE BIT(1)
> > +#define CONTROL_INIT BIT(0)
> > +
> > +/* test register */
> > +#define TEST_RX BIT(7)
> > +#define TEST_TX1 BIT(6)
> > +#define TEST_TX2 BIT(5)
> > +#define TEST_LBACK BIT(4)
> > +#define TEST_SILENT BIT(3)
> > +#define TEST_BASIC BIT(2)
> > +
> > +/* status register */
> > +#define STATUS_BOFF BIT(7)
> > +#define STATUS_EWARN BIT(6)
> > +#define STATUS_EPASS BIT(5)
> > +#define STATUS_RXOK BIT(4)
> > +#define STATUS_TXOK BIT(3)
> > +#define STATUS_LEC_MASK 0x07
> > +
> > +/* error counter register */
> > +#define ERR_COUNTER_TEC_MASK 0xff
> > +#define ERR_COUNTER_TEC_SHIFT 0
> > +#define ERR_COUNTER_REC_SHIFT 8
> > +#define ERR_COUNTER_REC_MASK (0x7f << ERR_COUNTER_REC_SHIFT)
> > +#define ERR_COUNTER_RP_SHIFT 15
> > +#define ERR_COUNTER_RP_MASK (0x1 << ERR_COUNTER_RP_SHIFT)
> > +
> > +/* bit-timing register */
> > +#define BTR_BRP_MASK 0x3f
> > +#define BTR_BRP_SHIFT 0
> > +#define BTR_SJW_SHIFT 6
> > +#define BTR_SJW_MASK (0x3 << BTR_SJW_SHIFT)
> > +#define BTR_TSEG1_SHIFT 8
> > +#define BTR_TSEG1_MASK (0xf << BTR_TSEG1_SHIFT)
> > +#define BTR_TSEG2_SHIFT 12
> > +#define BTR_TSEG2_MASK (0x7 << BTR_TSEG2_SHIFT)
> > +
> > +/* brp extension register */
> > +#define BRP_EXT_BRPE_MASK 0x0f
> > +#define BRP_EXT_BRPE_SHIFT 0
> > +
> > +/* IFx command request */
> > +#define IF_COMR_BUSY BIT(15)
> > +
> > +/* IFx command mask */
> > +#define IF_COMM_WR BIT(7)
> > +#define IF_COMM_MASK BIT(6)
> > +#define IF_COMM_ARB BIT(5)
> > +#define IF_COMM_CONTROL BIT(4)
> > +#define IF_COMM_CLR_INT_PND BIT(3)
> > +#define IF_COMM_TXRQST BIT(2)
> > +#define IF_COMM_DATAA BIT(1)
> > +#define IF_COMM_DATAB BIT(0)
> > +#define IF_COMM_ALL (IF_COMM_MASK | IF_COMM_ARB | \
> > + IF_COMM_CONTROL | IF_COMM_TXRQST | \
> > + IF_COMM_DATAA | IF_COMM_DATAB)
> > +
> > +/* IFx arbitration */
> > +#define IF_ARB_MSGVAL BIT(15)
> > +#define IF_ARB_MSGXTD BIT(14)
> > +#define IF_ARB_TRANSMIT BIT(13)
> > +
> > +/* IFx message control */
> > +#define IF_MCONT_NEWDAT BIT(15)
> > +#define IF_MCONT_MSGLST BIT(14)
> > +#define IF_MCONT_CLR_MSGLST (0 << 14)
> > +#define IF_MCONT_INTPND BIT(13)
> > +#define IF_MCONT_UMASK BIT(12)
> > +#define IF_MCONT_TXIE BIT(11)
> > +#define IF_MCONT_RXIE BIT(10)
> > +#define IF_MCONT_RMTEN BIT(9)
> > +#define IF_MCONT_TXRQST BIT(8)
> > +#define IF_MCONT_EOB BIT(7)
> > +#define IF_MCONT_DLC_MASK 0xf
> > +
> > +/*
> > + * IFx register masks:
> > + * allow easy operation on 16-bit registers when the
> > + * argument is 32-bit instead
> > + */
> > +#define IFX_WRITE_LOW_16BIT(x) ((x) & 0xFFFF)
> > +#define IFX_WRITE_HIGH_16BIT(x) (((x) & 0xFFFF0000) >> 16)
> > +
> > +/* message object split */
> > +#define C_CAN_NO_OF_OBJECTS 31
> > +#define C_CAN_MSG_OBJ_RX_NUM 16
> > +#define C_CAN_MSG_OBJ_TX_NUM 16
> > +
> > +#define C_CAN_MSG_OBJ_RX_FIRST 0
> > +#define C_CAN_MSG_OBJ_RX_LAST (C_CAN_MSG_OBJ_RX_FIRST + \
> > + C_CAN_MSG_OBJ_RX_NUM - 1)
> > +
> > +#define C_CAN_MSG_OBJ_TX_FIRST (C_CAN_MSG_OBJ_RX_LAST + 1)
> > +#define C_CAN_MSG_OBJ_TX_LAST (C_CAN_MSG_OBJ_TX_FIRST + \
> > + C_CAN_MSG_OBJ_TX_NUM - 1)
> > +
> > +#define C_CAN_MSG_OBJ_RX_SPLIT 8
> > +#define C_CAN_MSG_RX_LOW_LAST (C_CAN_MSG_OBJ_RX_SPLIT - 1)
> > +
> > +#define C_CAN_NEXT_MSG_OBJ_MASK (C_CAN_MSG_OBJ_TX_NUM - 1)
> > +#define RECEIVE_OBJECT_BITS 0x0000ffff
> > +
> > +/* status interrupt */
> > +#define STATUS_INTERRUPT 0x8000
> > +
> > +/* global interrupt masks */
> > +#define ENABLE_ALL_INTERRUPTS 1
> > +#define DISABLE_ALL_INTERRUPTS 0
> > +
> > +/* minimum timeout for checking BUSY status */
> > +#define MIN_TIMEOUT_VALUE 6
> > +
> > +/* napi related */
> > +#define C_CAN_NAPI_WEIGHT C_CAN_MSG_OBJ_RX_NUM
> > +
> > +/* c_can IF registers */
> > +struct c_can_if_regs {
> > + u16 com_reg;
> > + u16 com_mask;
> > + u16 mask1;
> > + u16 mask2;
> > + u16 arb1;
> > + u16 arb2;
> > + u16 msg_cntrl;
> > + u16 data[4];
> > + u16 _reserved[13];
> > +};
> > +
> > +/* c_can hardware registers */
> > +struct c_can_regs {
> > + u16 control;
> > + u16 status;
> > + u16 error_counter;
> > + u16 btr;
> > + u16 ir;
> > + u16 test;
> > + u16 brp_ext;
> > + u16 _reserved1;
> > + struct c_can_if_regs ifreg[2]; /* [0] = IF1 and [1] = IF2 */
>
> Why not just "if" instead of "ifreg"? That would also nicely shorten
> many log expressions.
Hmm.. Ok
> > + u16 _reserved2[8];
> > + u16 txrqst1;
> > + u16 txrqst2;
> > + u16 _reserved3[6];
> > + u16 newdat1;
> > + u16 newdat2;
> > + u16 _reserved4[6];
> > + u16 intpnd1;
> > + u16 intpnd2;
> > + u16 _reserved5[6];
> > + u16 msgval1;
> > + u16 msgval2;
> > + u16 _reserved6[6];
> > +};
>
> Above you use both, rather long and heavily abbreviated names, e.g.
> "error_counter" vs. "ir". Something in between would be nice.
I agree. V4 will take care of these.
> > +/* c_can lec values */
> > +enum c_can_lec_type {
> > + LEC_STUFF_ERROR = 1,
> > + LEC_FORM_ERROR,
> > + LEC_ACK_ERROR,
> > + LEC_BIT1_ERROR,
> > + LEC_BIT0_ERROR,
> > + LEC_CRC_ERROR,
> > +};
> > +
> > +/*
> > + * c_can error types:
> > + * Bus errors (BUS_OFF, ERROR_WARNING, ERROR_PASSIVE) are supported
> > + */
> > +enum c_can_bus_error_types {
> > + C_CAN_NO_ERROR = 0,
> > + C_CAN_BUS_OFF,
> > + C_CAN_ERROR_WARNING,
> > + C_CAN_ERROR_PASSIVE,
> > +};
> > +
> > +/* c_can private data structure */
> > +struct c_can_priv {
> > + struct can_priv can; /* must be the first member */
> > + struct napi_struct napi;
> > + struct net_device *dev;
> > + int tx_object;
> > + int current_status;
> > + int last_status;
> > + u16 (*read_reg) (struct c_can_priv *priv, void *reg);
> > + void (*write_reg) (struct c_can_priv *priv, void *reg, u16 val);
> > + struct c_can_regs __iomem *reg_base;
>
> s/reg_base/regs/ seems more logical to me. reg_base sounds like a "void
> *"
> member.
Ok.
> > + unsigned long irq_flags; /* for request_irq() */
> > + unsigned int tx_next;
> > + unsigned int tx_echo;
> > + struct clk *clk;
>
> clk is a platform specific variable, e.g. a PCI based drive will not
> need it.
> Therefore a member "priv" would make sense. Also it would nicely
> shorten
> many log expressions.
Ok.
> > +};
> > +
> > +void c_can_enable_all_interrupts(struct c_can_priv *priv, int
> enable);
> > +struct net_device *alloc_c_can_dev(void);
> > +void free_c_can_dev(struct net_device *dev);
> > +int register_c_can_dev(struct net_device *dev);
> > +void unregister_c_can_dev(struct net_device *dev);
> > +
> > +#endif /* C_CAN_H */
> > diff --git a/drivers/net/can/c_can/c_can_platform.c
> b/drivers/net/can/c_can/c_can_platform.c
> > new file mode 100644
> > index 0000000..482a57e
> > --- /dev/null
> > +++ b/drivers/net/can/c_can/c_can_platform.c
> > @@ -0,0 +1,210 @@
> > +/*
> > + * Platform CAN bus driver for Bosch C_CAN controller
> > + *
> > + * Copyright (C) 2010 ST Microelectronics
> > + * Bhupesh Sharma <bhupesh.sharma-qxv4g6HH51o@public.gmane.org>
> > + *
> > + * Borrowed heavily from the C_CAN driver originally written by:
> > + * Copyright (C) 2007
> > + * - Sascha Hauer, Marc Kleine-Budde, Pengutronix
> <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> > + * - Simon Kallweit, intefo AG <simon.kallweit-+G9qxTFKJT/tRgLqZ5aouw@public.gmane.org>
> > + *
> > + * Bosch C_CAN controller is compliant to CAN protocol version 2.0
> part A and B.
> > + * Bosch C_CAN user manual can be obtained from:
> > + * http://www.semiconductors.bosch.de/pdf/Users_Manual_C_CAN.pdf
> > + *
> > + * This file is licensed under the terms of the GNU General Public
> > + * License version 2. This program is licensed "as is" without any
> > + * warranty of any kind, whether express or implied.
> > + */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/version.h>
> > +#include <linux/module.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/delay.h>
> > +#include <linux/netdevice.h>
> > +#include <linux/if_arp.h>
> > +#include <linux/if_ether.h>
> > +#include <linux/list.h>
> > +#include <linux/delay.h>
> > +#include <linux/io.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/clk.h>
> > +
> > +#include <linux/can/dev.h>
> > +
> > +#include "c_can.h"
> > +
> > +/*
> > + * 16-bit c_can registers can be arranged differently in the memory
> > + * architecture of different implementations. For example: 16-bit
> > + * registers can be aligned to a 16-bit boundary or 32-bit boundary
> etc.
> > + * Handle the same by providing a common read/write interface.
> > + */
> > +static u16 c_can_plat_read_reg_aligned_to_16bit(struct c_can_priv
> *priv,
> > + void *reg)
> > +{
> > + return readw(reg);
> > +}
> > +
> > +static void c_can_plat_write_reg_aligned_to_16bit(struct c_can_priv
> *priv,
> > + void *reg, u16 val)
> > +{
> > + writew(val, reg);
> > +}
> > +
> > +static u16 c_can_plat_read_reg_aligned_to_32bit(struct c_can_priv
> *priv,
> > + void *reg)
> > +{
> > + return readw(reg + (long)reg - (long)priv->reg_base);
> > +}
> > +
> > +static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv
> *priv,
> > + void *reg, u16 val)
> > +{
> > + writew(val, reg + (long)reg - (long)priv->reg_base);
> > +}
> > +
> > +static int __devinit c_can_plat_probe(struct platform_device *pdev)
> > +{
> > + int ret;
> > + void __iomem *addr;
> > + struct net_device *dev;
> > + struct c_can_priv *priv;
> > + struct resource *mem, *irq;
> > + struct clk *clk;
> > +
> > + /* get the appropriate clk */
> > + clk = clk_get(&pdev->dev, NULL);
> > + if (IS_ERR(clk)) {
> > + dev_err(&pdev->dev, "no clock defined\n");
> > + ret = -ENODEV;
> > + goto exit;
> > + }
> > +
> > + /* get the platform data */
> > + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> > + if (!mem || (irq <= 0)) {
> > + ret = -ENODEV;
> > + goto exit_free_clk;
> > + }
> > +
> > + if (!request_mem_region(mem->start, resource_size(mem),
> > + KBUILD_MODNAME)) {
> > + dev_err(&pdev->dev, "resource unavailable\n");
> > + ret = -ENODEV;
> > + goto exit_free_clk;
> > + }
> > +
> > + addr = ioremap(mem->start, resource_size(mem));
> > + if (!addr) {
> > + dev_err(&pdev->dev, "failed to map can port\n");
> > + ret = -ENOMEM;
> > + goto exit_release_mem;
> > + }
> > +
> > + /* allocate the c_can device */
> > + dev = alloc_c_can_dev();
> > + if (!dev) {
> > + ret = -ENOMEM;
> > + goto exit_iounmap;
> > + }
> > +
> > + priv = netdev_priv(dev);
> > +
> > + dev->irq = irq->start;
> > + priv->irq_flags = irq->flags;
> > + priv->reg_base = addr;
> > + priv->can.clock.freq = clk_get_rate(clk);
> > + priv->clk = clk;
> > +
> > + switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
> > + case IORESOURCE_MEM_32BIT:
> > + priv->read_reg = c_can_plat_read_reg_aligned_to_32bit;
> > + priv->write_reg = c_can_plat_write_reg_aligned_to_32bit;
> > + break;
> > + case IORESOURCE_MEM_16BIT:
> > + default:
> > + priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;
> > + priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
> > + break;
> > + }
> > +
> > + platform_set_drvdata(pdev, dev);
> > + SET_NETDEV_DEV(dev, &pdev->dev);
> > +
> > + ret = register_c_can_dev(dev);
> > + if (ret) {
> > + dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
> > + KBUILD_MODNAME, ret);
> > + goto exit_free_device;
> > + }
> > +
> > + dev_info(&pdev->dev, "%s device registered (reg_base=%p,
> irq=%d)\n",
> > + KBUILD_MODNAME, priv->reg_base, dev->irq);
> > + return 0;
> > +
> > +exit_free_device:
> > + platform_set_drvdata(pdev, NULL);
> > + free_c_can_dev(dev);
> > +exit_iounmap:
> > + iounmap(addr);
> > +exit_release_mem:
> > + release_mem_region(mem->start, resource_size(mem));
> > +exit_free_clk:
> > + clk_put(clk);
> > +exit:
> > + dev_err(&pdev->dev, "probe failed\n");
> > +
> > + return ret;
> > +}
> > +
> > +static int __devexit c_can_plat_remove(struct platform_device *pdev)
> > +{
> > + struct net_device *dev = platform_get_drvdata(pdev);
> > + struct c_can_priv *priv = netdev_priv(dev);
> > + struct resource *mem;
> > +
> > + /* disable all interrupts */
> > + c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
>
> To avoid exportign that function, couldn't it be done at the beginning
> of
> unregister_c_can_dev()?
Yes this can be done.
But, IMHO *disabling* interrupts seems more logical as part of __devexit
Code.
> > +
> > + unregister_c_can_dev(dev);
> > + platform_set_drvdata(pdev, NULL);
> > +
> > + free_c_can_dev(dev);
> > + iounmap(priv->reg_base);
> > +
> > + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + release_mem_region(mem->start, resource_size(mem));
> > +
> > + clk_put(priv->clk);
> > +
> > + return 0;
> > +}
> > +
> > +static struct platform_driver c_can_plat_driver = {
> > + .driver = {
> > + .name = KBUILD_MODNAME,
> > + .owner = THIS_MODULE,
> > + },
> > + .probe = c_can_plat_probe,
> > + .remove = __devexit_p(c_can_plat_remove),
> > +};
> > +
> > +static int __init c_can_plat_init(void)
> > +{
> > + return platform_driver_register(&c_can_plat_driver);
> > +}
> > +module_init(c_can_plat_init);
> > +
> > +static void __exit c_can_plat_exit(void)
> > +{
> > + platform_driver_unregister(&c_can_plat_driver);
> > +}
> > +module_exit(c_can_plat_exit);
> > +
> > +MODULE_AUTHOR("Bhupesh Sharma <bhupesh.sharma-qxv4g6HH51o@public.gmane.org>");
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_DESCRIPTION("Platform CAN bus driver for Bosch C_CAN
> controller");
>
> Thanks for your contribution.
>
> Wolfgang.
Regards,
Bhupesh
^ permalink raw reply
* Re: Bug#609538: r8169: long delay during resume
From: Ben Hutchings @ 2011-01-11 5:49 UTC (permalink / raw)
To: Jarek Kamiński, 609538; +Cc: Hayes Wang, romieu, netdev
In-Reply-To: <20110110131439.GA663@rocket.almost.secure.la>
[-- Attachment #1: Type: text/plain, Size: 1483 bytes --]
On Mon, 2011-01-10 at 14:14 +0100, Jarek Kamiński wrote:
> Package: linux-2.6
> Version: 2.6.37-1~experimental.1
> Severity: normal
> File: /lib/modules/2.6.37-trunk-amd64/kernel/drivers/net/r8169.ko
> Tags: upstream
>
> Hi.
>
> 2.6.37 introduces regression in r8169. During every resume I get ~20
> seconds delay:
> Jan 10 13:57:15 rocket kernel: [36458.257780] ata1.00: configured for UDMA/100
> Jan 10 13:57:15 rocket kernel: [36517.738421] r8169 0000:13:00.0: eth0: unable to apply firmware patch
> Jan 10 13:57:15 rocket kernel: [36517.739859] PM: resume of devices complete after 61177.644 msecs
> Jan 10 13:57:15 rocket kernel: [36517.740258] PM: Finishing wakeup.
> Jan 10 13:57:15 rocket kernel: [36517.740259] Restarting tasks ... done.
>
> Bisecting leads to commit bca03d5f32c8ee9b5cfa1d32640a63fded6cb3c0
> (r8169: remove the firmware of RTL8111D.). Further debugging showed,
> that firmware.agent is not called at all, I guess that udev is not
> working before "Restarting tasks".
Right, only the kernel is running then.
> Either r8169 tries to load firmware too early, or it should keep it
> loaded in memory for use during resume.
It should. But an earlier version of this patch was also in Debian's
2.6.36 so it would have had the same problem.
Ben.
> The problem persist no matter if I have firmware-realtek installed, or
> not.
--
Ben Hutchings
Once a job is fouled up, anything done to improve it makes it worse.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]
^ permalink raw reply
* Re: [RFC] sched: CHOKe packet scheduler (v0.4)
From: Eric Dumazet @ 2011-01-11 6:18 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <20110110171047.0796b6fb@nehalam>
Le lundi 10 janvier 2011 à 17:10 -0800, Stephen Hemminger a écrit :
> OK, put that in.
Thanks !
> >
> > Here we missed :
> >
> > q->tab = ntab;
> >
We also need to change
.peek = qdisc_peek_head,
to
.peek = choke_peek_head,
static struct sk_buff *choke_peek_head(struct Qdisc *sch)
{
struct choke_sched_data *q = qdisc_priv(sch);
return (q->head != q->tail) ? q->tab[q->head] : NULL;
}
^ permalink raw reply
* Re: [GIT PULL nf-next-2.6] ipvs namespaces
From: Simon Horman @ 2011-01-11 6:21 UTC (permalink / raw)
To: netfilter-devel, lvs-devel, netdev
Cc: Patrick McHardy, Julian Anastasov, Hans Schillstrom, David Miller
In-Reply-To: <1294294578-8601-1-git-send-email-horms@verge.net.au>
On Thu, Jan 06, 2011 at 03:15:56PM +0900, Simon Horman wrote:
> Hi Patrick,
>
> please consider pulling
> git://git.kernel.org/pub/scm/linux/kernel/git/horms/lvs-test-2.6.git master
> in order to get the netns changes to IPVS from Hans Schillstrom.
>
> Thanks
Hi Dave,
Patrick seems to be rather quiet (perhaps he is on holidays?).
Could you consider taking these changes through your tree as
it would be nice to get this feature in 2.6.38?
If so I'll send you a fresh pull request as I think there
is a conflict with your tree (but not nf-next-2.6).
^ permalink raw reply
* Re: [RFC] sched: CHOKe packet scheduler (v0.4)
From: Eric Dumazet @ 2011-01-11 6:34 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <1294726715.4148.8.camel@edumazet-laptop>
Le mardi 11 janvier 2011 à 07:18 +0100, Eric Dumazet a écrit :
> Le lundi 10 janvier 2011 à 17:10 -0800, Stephen Hemminger a écrit :
> > OK, put that in.
>
> Thanks !
>
> > >
> > > Here we missed :
> > >
> > > q->tab = ntab;
> > >
>
> We also need to change
>
> .peek = qdisc_peek_head,
>
> to
>
> .peek = choke_peek_head,
>
> static struct sk_buff *choke_peek_head(struct Qdisc *sch)
> {
> struct choke_sched_data *q = qdisc_priv(sch);
>
> return (q->head != q->tail) ? q->tab[q->head] : NULL;
> }
>
>
And to correctly work with CBQ (at least...), we need to update
sch->q.qlen = choke_len(q) - q->holes;
in dequeue() and enqueue()
Here is the version I successfully tested, with 30000 packets in
queue :)
qdisc choke 11: parent 1:11 limit 70000b min 10000b max 30000b ewma 1 Plog 16 Scell_log 11
Sent 62099201 bytes 112920 pkt (dropped 367712, overlimits 282668 requeues 0)
rate 21344Kbit 4851pps backlog 39877589b 30001p requeues 0
marked 0 early 282668 pdrop 0 other 0
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index a36270a..e63ae56 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -205,6 +205,17 @@ config NET_SCH_DRR
If unsure, say N.
+config NET_SCH_CHOKE
+ tristate "CHOose and Keep responsive flow scheduler (CHOKE)"
+ help
+ Say Y here if you want to use the CHOKe packet scheduler (CHOose
+ and Keep for responsive flows, CHOose and Kill for unresponsive
+ flows). This is a variation of RED which trys to penalize flows
+ that monopolize the queue.
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_choke.
+
config NET_SCH_INGRESS
tristate "Ingress Qdisc"
depends on NET_CLS_ACT
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 960f5db..894fa3f 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_NET_SCH_MULTIQ) += sch_multiq.o
obj-$(CONFIG_NET_SCH_ATM) += sch_atm.o
obj-$(CONFIG_NET_SCH_NETEM) += sch_netem.o
obj-$(CONFIG_NET_SCH_DRR) += sch_drr.o
+obj-$(CONFIG_NET_SCH_CHOKE) += sch_choke.o
obj-$(CONFIG_NET_CLS_U32) += cls_u32.o
obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o
obj-$(CONFIG_NET_CLS_FW) += cls_fw.o
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index e69de29..b565f2a 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -0,0 +1,536 @@
+/*
+ * net/sched/sch_choke.c CHOKE scheduler
+ *
+ * Copyright (c) 2011 Stephen Hemminger <shemminger@vyatta.com>
+ * Copyright (c) 2011 Eric Dumazet <eric.dumazet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/reciprocal_div.h>
+#include <net/pkt_sched.h>
+#include <net/inet_ecn.h>
+#include <net/red.h>
+
+/* CHOKe stateless AQM for fair bandwidth allocation
+ =================================================
+
+ CHOKe (CHOose and Keep for responsive flows, CHOose and Kill for
+ unresponsive flows) is a variant of RED that penalizes misbehaving flows but
+ maintains no flow state. The difference from RED is an additional step
+ during the enqueuing process. If average queue size is over the
+ low threshold (qmin), a packet is chosen at random from the queue.
+ If both the new and chosen packet are from the same flow, both
+ are dropped. Unlike RED, CHOKe is not really a "classful" qdisc because it
+ needs to access packets in queue randomly. It has a minimal class
+ interface to allow overriding the builtin flow classifier with
+ filters.
+
+ Source:
+ R. Pan, B. Prabhakar, and K. Psounis, "CHOKe, A Stateless
+ Active Queue Management Scheme for Approximating Fair Bandwidth Allocation",
+ IEEE INFOCOM, 2000.
+
+ A. Tang, J. Wang, S. Low, "Understanding CHOKe: Throughput and Spatial
+ Characteristics", IEEE/ACM Transactions on Networking, 2004
+
+ */
+
+struct choke_sched_data {
+/* Parameters */
+ u32 limit;
+ unsigned char flags;
+
+ struct red_parms parms;
+ struct red_stats stats;
+
+/* Variables */
+ struct tcf_proto *filter_list;
+ unsigned int head;
+ unsigned int tail;
+ unsigned int holes;
+ unsigned int tab_mask; /* size - 1 */
+
+ struct sk_buff **tab;
+};
+
+static inline unsigned int choke_len(const struct choke_sched_data *q)
+{
+ return (q->tail - q->head) & q->tab_mask;
+}
+
+/* deliver a random number between 0 and N - 1 */
+static inline u32 random_N(unsigned int N)
+{
+ return reciprocal_divide(random32(), N);
+}
+
+
+/* Select a packet at random from the queue in O(1) and handle holes */
+static struct sk_buff *choke_peek_random(struct choke_sched_data *q,
+ unsigned int *pidx)
+{
+ struct sk_buff *skb;
+ int retrys = 3;
+
+ do {
+ *pidx = (q->head + random_N(choke_len(q))) & q->tab_mask;
+ skb = q->tab[*pidx];
+ if (skb)
+ return skb;
+ } while (--retrys > 0);
+
+ /* queue is has lots of holes use the head which is known to exist */
+ return q->tab[*pidx = q->head];
+}
+
+/* Is ECN parameter configured */
+static inline int use_ecn(const struct choke_sched_data *q)
+{
+ return q->flags & TC_RED_ECN;
+}
+
+/* Should packets over max just be dropped (versus marked) */
+static inline int use_harddrop(const struct choke_sched_data *q)
+{
+ return q->flags & TC_RED_HARDDROP;
+}
+
+/* Move head pointer forward to skip over holes */
+static void choke_zap_head_holes(struct choke_sched_data *q)
+{
+ while (q->holes && q->tab[q->head] == NULL) {
+ q->head = (q->head + 1) & q->tab_mask;
+ q->holes--;
+ }
+}
+
+/* Move tail pointer backwards to reuse holes */
+static void choke_zap_tail_holes(struct choke_sched_data *q)
+{
+ while (q->holes && q->tab[q->tail - 1] == NULL) {
+ q->tail = (q->tail - 1) & q->tab_mask;
+ q->holes--;
+ }
+}
+
+/* Drop packet from queue array by creating a "hole" */
+static void choke_drop_by_idx(struct choke_sched_data *q, unsigned int idx)
+{
+ q->tab[idx] = NULL;
+ q->holes++;
+
+ if (idx == q->head)
+ choke_zap_head_holes(q);
+ if (idx == q->tail)
+ choke_zap_tail_holes(q);
+}
+
+/* Classify flow using either:
+ 1. pre-existing classification result in skb
+ 2. fast internal classification
+ 3. use TC filter based classification
+*/
+static inline unsigned int choke_classify(struct sk_buff *skb,
+ struct Qdisc *sch, int *qerr)
+
+{
+ struct choke_sched_data *q = qdisc_priv(sch);
+ struct tcf_result res;
+ int result;
+
+ *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
+
+ if (TC_H_MAJ(skb->priority) == sch->handle &&
+ TC_H_MIN(skb->priority) > 0)
+ return TC_H_MIN(skb->priority);
+
+ if (!q->filter_list)
+ return skb_get_rxhash(skb);
+
+ result = tc_classify(skb, q->filter_list, &res);
+ if (result >= 0) {
+#ifdef CONFIG_NET_CLS_ACT
+ switch (result) {
+ case TC_ACT_STOLEN:
+ case TC_ACT_QUEUED:
+ *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
+ case TC_ACT_SHOT:
+ return 0;
+ }
+#endif
+ return TC_H_MIN(res.classid);
+ }
+
+ return 0;
+}
+
+static int choke_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+ struct choke_sched_data *q = qdisc_priv(sch);
+ struct red_parms *p = &q->parms;
+ unsigned int hash;
+ int uninitialized_var(ret);
+
+ hash = choke_classify(skb, sch, &ret);
+ if (unlikely(!hash)) {
+ if (ret & __NET_XMIT_BYPASS)
+ sch->qstats.drops++;
+ kfree_skb(skb);
+ return ret;
+ }
+
+ /* XXX add hash to qdisc_skb_cb? */
+ *(unsigned int *)(qdisc_skb_cb(skb)->data) = hash;
+
+ /* Compute average queue usage (see RED) */
+ p->qavg = red_calc_qavg(p, choke_len(q) - q->holes);
+ if (red_is_idling(p))
+ red_end_of_idle_period(p);
+
+ /* Is queue small? */
+ if (p->qavg <= p->qth_min)
+ p->qcount = -1;
+ else {
+ struct sk_buff *oskb;
+ unsigned int idx;
+
+ /* Draw a packet at random from queue */
+ oskb = choke_peek_random(q, &idx);
+
+ /* Both packets from same flow ? */
+ if (*(unsigned int *)(qdisc_skb_cb(oskb)->data) == hash) {
+ /* Drop both packets */
+ choke_drop_by_idx(q, idx);
+ qdisc_drop(oskb, sch);
+ goto congestion_drop;
+ }
+
+ if (p->qavg > p->qth_max) {
+ p->qcount = -1;
+
+ sch->qstats.overlimits++;
+ if (use_harddrop(q) || !use_ecn(q) ||
+ !INET_ECN_set_ce(skb)) {
+ q->stats.forced_drop++;
+ goto congestion_drop;
+ }
+
+ q->stats.forced_mark++;
+ }
+
+ if (++p->qcount) {
+ if (red_mark_probability(p, p->qavg)) {
+ p->qcount = 0;
+ p->qR = red_random(p);
+
+ sch->qstats.overlimits++;
+ if (!use_ecn(q) || !INET_ECN_set_ce(skb)) {
+ q->stats.prob_drop++;
+ goto congestion_drop;
+ }
+
+ q->stats.prob_mark++;
+ }
+ } else
+ p->qR = red_random(p);
+ }
+
+ /* Admit new packet */
+ if (likely(choke_len(q) < q->limit)) {
+ q->tab[q->tail] = skb;
+ q->tail = (q->tail + 1) & q->tab_mask;
+
+ sch->qstats.backlog += qdisc_pkt_len(skb);
+ __qdisc_update_bstats(sch, qdisc_pkt_len(skb));
+ sch->q.qlen = choke_len(q) - q->holes;
+ return NET_XMIT_SUCCESS;
+ }
+
+ q->stats.pdrop++;
+ sch->qstats.drops++;
+ kfree_skb(skb);
+ return NET_XMIT_DROP;
+
+ congestion_drop:
+ qdisc_drop(skb, sch);
+ return NET_XMIT_CN;
+}
+
+static struct sk_buff *choke_dequeue(struct Qdisc *sch)
+{
+ struct choke_sched_data *q = qdisc_priv(sch);
+ struct sk_buff *skb;
+
+ if (q->head == q->tail) {
+ if (!red_is_idling(&q->parms))
+ red_start_of_idle_period(&q->parms);
+ return NULL;
+ }
+ skb = q->tab[q->head];
+ q->tab[q->head] = NULL; /* not really needed */
+ q->head = (q->head + 1) & q->tab_mask;
+ choke_zap_head_holes(q);
+ sch->qstats.backlog -= qdisc_pkt_len(skb);
+ sch->q.qlen = choke_len(q) - q->holes;
+
+ return skb;
+}
+
+static unsigned int choke_drop(struct Qdisc *sch)
+{
+ struct choke_sched_data *q = qdisc_priv(sch);
+ unsigned int len;
+
+ len = qdisc_queue_drop(sch);
+
+ if (len > 0)
+ q->stats.other++;
+ else {
+ if (!red_is_idling(&q->parms))
+ red_start_of_idle_period(&q->parms);
+ }
+
+ return len;
+}
+
+static void choke_reset(struct Qdisc* sch)
+{
+ struct choke_sched_data *q = qdisc_priv(sch);
+
+ red_restart(&q->parms);
+}
+
+static const struct nla_policy choke_policy[TCA_RED_MAX + 1] = {
+ [TCA_RED_PARMS] = { .len = sizeof(struct tc_red_qopt) },
+ [TCA_RED_STAB] = { .len = RED_STAB_SIZE },
+};
+
+
+static void choke_free(void *addr)
+{
+ if (addr) {
+ if (is_vmalloc_addr(addr))
+ vfree(addr);
+ else
+ kfree(addr);
+ }
+}
+
+static int choke_change(struct Qdisc *sch, struct nlattr *opt)
+{
+ struct choke_sched_data *q = qdisc_priv(sch);
+ struct nlattr *tb[TCA_RED_MAX + 1];
+ struct tc_red_qopt *ctl;
+ int err;
+ struct sk_buff **old = NULL;
+ unsigned int mask;
+
+ if (opt == NULL)
+ return -EINVAL;
+
+ err = nla_parse_nested(tb, TCA_RED_MAX, opt, choke_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_RED_PARMS] == NULL ||
+ tb[TCA_RED_STAB] == NULL)
+ return -EINVAL;
+
+ ctl = nla_data(tb[TCA_RED_PARMS]);
+
+ mask = roundup_pow_of_two(ctl->limit + 1) - 1;
+ if (mask != q->tab_mask) {
+ struct sk_buff **ntab = kcalloc(mask + 1, sizeof(struct sk_buff *),
+ GFP_KERNEL);
+ if (!ntab)
+ ntab = vzalloc((mask + 1) * sizeof(struct sk_buff *));
+ if (!ntab)
+ return -ENOMEM;
+ sch_tree_lock(sch);
+ old = q->tab;
+ if (old) {
+ unsigned int tail = 0;
+
+ while (q->head != q->tail) {
+ ntab[tail++] = q->tab[q->head];
+ q->head = (q->head + 1) & q->tab_mask;
+ }
+ q->head = 0;
+ q->tail = tail;
+ }
+ q->tab_mask = mask;
+ q->tab = ntab;
+ q->holes = 0;
+ } else
+ sch_tree_lock(sch);
+ q->flags = ctl->flags;
+ q->limit = ctl->limit;
+
+ red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog,
+ ctl->Plog, ctl->Scell_log,
+ nla_data(tb[TCA_RED_STAB]));
+
+ if (q->head == q->tail)
+ red_end_of_idle_period(&q->parms);
+
+ sch_tree_unlock(sch);
+ choke_free(old);
+ return 0;
+}
+
+static int choke_init(struct Qdisc* sch, struct nlattr *opt)
+{
+ return choke_change(sch, opt);
+}
+
+static int choke_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+ struct choke_sched_data *q = qdisc_priv(sch);
+ struct nlattr *opts = NULL;
+ struct tc_red_qopt opt = {
+ .limit = q->limit,
+ .flags = q->flags,
+ .qth_min = q->parms.qth_min >> q->parms.Wlog,
+ .qth_max = q->parms.qth_max >> q->parms.Wlog,
+ .Wlog = q->parms.Wlog,
+ .Plog = q->parms.Plog,
+ .Scell_log = q->parms.Scell_log,
+ };
+
+ opts = nla_nest_start(skb, TCA_OPTIONS);
+ if (opts == NULL)
+ goto nla_put_failure;
+
+ NLA_PUT(skb, TCA_RED_PARMS, sizeof(opt), &opt);
+ return nla_nest_end(skb, opts);
+
+nla_put_failure:
+ nla_nest_cancel(skb, opts);
+ return -EMSGSIZE;
+}
+
+static int choke_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
+{
+ struct choke_sched_data *q = qdisc_priv(sch);
+ struct tc_red_xstats st = {
+ .early = q->stats.prob_drop + q->stats.forced_drop,
+ .pdrop = q->stats.pdrop,
+ .other = q->stats.other,
+ .marked = q->stats.prob_mark + q->stats.forced_mark,
+ };
+
+ return gnet_stats_copy_app(d, &st, sizeof(st));
+}
+
+static void choke_destroy(struct Qdisc *sch)
+{
+ struct choke_sched_data *q = qdisc_priv(sch);
+
+ tcf_destroy_chain(&q->filter_list);
+ choke_free(q->tab);
+}
+
+static struct Qdisc *choke_leaf(struct Qdisc *sch, unsigned long arg)
+{
+ return NULL;
+}
+
+static unsigned long choke_get(struct Qdisc *sch, u32 classid)
+{
+ return 0;
+}
+
+static void choke_put(struct Qdisc *q, unsigned long cl)
+{
+}
+
+static unsigned long choke_bind(struct Qdisc *sch, unsigned long parent,
+ u32 classid)
+{
+ return 0;
+}
+
+static struct tcf_proto **choke_find_tcf(struct Qdisc *sch, unsigned long cl)
+{
+ struct choke_sched_data *q = qdisc_priv(sch);
+
+ if (cl)
+ return NULL;
+ return &q->filter_list;
+}
+
+static int choke_dump_class(struct Qdisc *sch, unsigned long cl,
+ struct sk_buff *skb, struct tcmsg *tcm)
+{
+ tcm->tcm_handle |= TC_H_MIN(cl);
+ return 0;
+}
+
+static void choke_walk(struct Qdisc *sch, struct qdisc_walker *arg)
+{
+ if (!arg->stop) {
+ if (arg->fn(sch, 1, arg) < 0) {
+ arg->stop = 1;
+ return;
+ }
+ arg->count++;
+ }
+}
+
+static const struct Qdisc_class_ops choke_class_ops = {
+ .leaf = choke_leaf,
+ .get = choke_get,
+ .put = choke_put,
+ .tcf_chain = choke_find_tcf,
+ .bind_tcf = choke_bind,
+ .unbind_tcf = choke_put,
+ .dump = choke_dump_class,
+ .walk = choke_walk,
+};
+
+static struct sk_buff *choke_peek_head(struct Qdisc *sch)
+{
+ struct choke_sched_data *q = qdisc_priv(sch);
+
+ return (q->head != q->tail) ? q->tab[q->head] : NULL;
+}
+
+static struct Qdisc_ops choke_qdisc_ops __read_mostly = {
+ .id = "choke",
+ .priv_size = sizeof(struct choke_sched_data),
+
+ .enqueue = choke_enqueue,
+ .dequeue = choke_dequeue,
+ .peek = choke_peek_head,
+ .drop = choke_drop,
+ .init = choke_init,
+ .destroy = choke_destroy,
+ .reset = choke_reset,
+ .change = choke_change,
+ .dump = choke_dump,
+ .dump_stats = choke_dump_stats,
+ .owner = THIS_MODULE,
+};
+
+static int __init choke_module_init(void)
+{
+ return register_qdisc(&choke_qdisc_ops);
+}
+
+static void __exit choke_module_exit(void)
+{
+ unregister_qdisc(&choke_qdisc_ops);
+}
+
+module_init(choke_module_init)
+module_exit(choke_module_exit)
+
+MODULE_LICENSE("GPL");
^ permalink raw reply related
* Re: Bug#609538: r8169: long delay during resume
From: Jarek Kamiński @ 2011-01-11 7:29 UTC (permalink / raw)
To: Ben Hutchings; +Cc: 609538, Hayes Wang, romieu, netdev
In-Reply-To: <1294724952.3235.2.camel@localhost>
W dniu 11.01.2011 06:49, Ben Hutchings pisze:
> On Mon, 2011-01-10 at 14:14 +0100, Jarek Kamiński wrote:
>> Package: linux-2.6
>> Version: 2.6.37-1~experimental.1
>> 2.6.37 introduces regression in r8169. During every resume I get ~20
>> seconds delay:
>> Jan 10 13:57:15 rocket kernel: [36458.257780] ata1.00: configured for UDMA/100
>> Jan 10 13:57:15 rocket kernel: [36517.738421] r8169 0000:13:00.0: eth0: unable to apply firmware patch
>> Jan 10 13:57:15 rocket kernel: [36517.739859] PM: resume of devices complete after 61177.644 msecs
>> Jan 10 13:57:15 rocket kernel: [36517.740258] PM: Finishing wakeup.
>> Jan 10 13:57:15 rocket kernel: [36517.740259] Restarting tasks ... done.
>>
>> Bisecting leads to commit bca03d5f32c8ee9b5cfa1d32640a63fded6cb3c0
>> (r8169: remove the firmware of RTL8111D.).
>> Either r8169 tries to load firmware too early, or it should keep it
>> loaded in memory for use during resume.
>
> It should. But an earlier version of this patch was also in Debian's
> 2.6.36 so it would have had the same problem.
The last 2.6.36 I've tried was 2.6.36-1~experimental.1, I've then
passsed and returned to 2.6.32 for unrelated problems. I think it wasn't
affected, but I can re-check it and/or test later 2.6.36 versions if it
may help.
Sorry if my information was misleading.
--
pozdr(); // Jarek
^ permalink raw reply
* Re: [PATCH v4 00/10] net/fec: add dual fec support for i.MX28
From: Shawn Guo @ 2011-01-11 8:15 UTC (permalink / raw)
To: s.hauer
Cc: gerg, baruch, eric, bryan.wu, r64343, B32542, u.kleine-koenig, lw,
w.sang, jamie, netdev, linux-arm-kernel
In-Reply-To: <20110109.154409.242134862.davem@davemloft.net>
Hi Sascha,
On Sun, Jan 09, 2011 at 03:44:09PM -0800, David Miller wrote:
> From: Shawn Guo <shawn.guo@freescale.com>
> Date: Thu, 6 Jan 2011 15:13:08 +0800
>
> > This patch series is to add dual fec support for mx28, which is
> > a mxs-based soc. Some code changes related to the following commits
> > are also made in this patch set for some reasons.
> >
> > e6b043d512fa8d9a3801bf5d72bfa3b8fc3b3cc8
> > netdev/fec.c: add phylib supporting to enable carrier detection (v2)
> >
> > e3fe8558c7fc182972c3d947d88744482111f304
> > net/fec: fix pm to survive to suspend/resume
> >
> > It's been tested on mx28 evk and mx51 babbage. For mx28, it has
> > to work against the tree
> >
> > git://git.pengutronix.de/git/imx/linux-2.6.git imx-for-2.6.38
> >
> > plus patch
> >
> > [PATCH v4] ARM: mxs: Change duart device to use amba-pl011
> >
> > The 3 patches below preceding with * have changes since v3, and
> > the detailed change log can be found in individual patch.
>
> I've applied all of the "net/fec:" patches (#1 to #5) to net-2.6,
> please push the ARM changes via the appropriate ARM tree.
>
Is there anything needs to be done to get the following patches
merged?
[PATCH v4] ARM: mxs: Change duart device to use amba-pl011
[PATCH v4 00/10] net/fec: add dual fec support for i.MX28, #6 to #10.
--
Regards,
Shawn
^ permalink raw reply
* Re: [PATCH net-next-2.6 v3 1/1] can: c_can: Added support for Bosch C_CAN controller
From: Wolfgang Grandegger @ 2011-01-11 8:29 UTC (permalink / raw)
To: Bhupesh SHARMA
Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Marc Kleine-Budde,
David Miller, Oliver Hartkopp
In-Reply-To: <D5ECB3C7A6F99444980976A8C6D896384DEAFA2D9D-8vAmw3ZAcdzhJTuQ9jeba9BPR1lH4CV8@public.gmane.org>
Hi Bhupesh,
On 01/11/2011 05:50 AM, Bhupesh SHARMA wrote:
> Hi Wolfgang,
>
> Thanks for your review.
> Please see my comments inline.
>
>> -----Original Message-----
>> From: Wolfgang Grandegger [mailto:wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org]
...
>>> + * Bosch C_CAN controller is compliant to CAN protocol version 2.0
>> part A and B.
>>> + * Bosch C_CAN user manual can be obtained from:
>>> + * http://www.semiconductors.bosch.de/pdf/Users_Manual_C_CAN.pdf
>>
>> Unfortunately, this link is not valid any more.
>
> Oops..
> It seems they have shifted to:
> http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/users_manual_c_can.pdf
Ah, nice. I was not aware of that new link.
...
>>> +int c_can_write_msg_object(struct net_device *dev,
>>> + int iface, struct can_frame *frame, int objno)
>>> +{
>>> + int i;
>>> + u16 flags = 0;
>>> + unsigned int id;
>>> + struct c_can_priv *priv = netdev_priv(dev);
>>> +
>>> + if (frame->can_id & CAN_EFF_FLAG) {
>>> + id = frame->can_id & CAN_EFF_MASK;
>>> + flags |= IF_ARB_MSGXTD;
>>> + } else
>>> + id = ((frame->can_id & CAN_SFF_MASK) << 18);
I just realize that the {} for the else block is missing.
>>> + /*
>>> + * check for 'last error code' which tells us the
>>> + * type of the last error to occur on the CAN bus
>>> + */
>>> + switch (lec_type) {
>>> + /* common for all type of bus errors */
>>> + priv->can.can_stats.bus_error++;
>>> + stats->rx_errors++;
>>> + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
>>> + cf->data[2] |= CAN_ERR_PROT_UNSPEC;
>>
>> Are you sure that this part is ever executed? I wonder why the compile
>> does
>> not complain.
>
> I did not get any compilation error.
I know.
> But I will check if the program flow enters this part or not.
Good. It was *not* executed in my little user space test program.
...
>>> +static int __devexit c_can_plat_remove(struct platform_device *pdev)
>>> +{
>>> + struct net_device *dev = platform_get_drvdata(pdev);
>>> + struct c_can_priv *priv = netdev_priv(dev);
>>> + struct resource *mem;
>>> +
>>> + /* disable all interrupts */
>>> + c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
>>
>> To avoid exportign that function, couldn't it be done at the beginning
>> of
>> unregister_c_can_dev()?
>
> Yes this can be done.
> But, IMHO *disabling* interrupts seems more logical as part of __devexit
> Code.
I think the interrupts are already disabled when you unload the module
because the device must be closed (c_can_stop has been called). Anyway,
I think the above c_can_enable_all_interrupts() call is well placed in
the unregister function. I would avoid the export the function.
Wolfgang.
^ permalink raw reply
* Re: [PATCH net-next-2.6 v3 1/1] can: c_can: Added support for Bosch C_CAN controller
From: Wolfgang Grandegger @ 2011-01-11 8:31 UTC (permalink / raw)
To: Bhupesh SHARMA
Cc: Oliver Hartkopp,
Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org,
Marc Kleine-Budde, netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
David Miller
In-Reply-To: <D5ECB3C7A6F99444980976A8C6D896384DEAFA2D56-8vAmw3ZAcdzhJTuQ9jeba9BPR1lH4CV8@public.gmane.org>
On 01/11/2011 05:13 AM, Bhupesh SHARMA wrote:
> Hi Oliver and Wolfgang,
>
>> From: Wolfgang Grandegger [mailto:wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org]
>> Hi Oliver,
>>
>> On 01/09/2011 12:01 PM, Oliver Hartkopp wrote:
>>> On 06.01.2011 21:08, Wolfgang Grandegger wrote:
>>>> Hi Marc,
>>>>
>>>> On 01/06/2011 08:44 PM, Marc Kleine-Budde wrote:
>>>
>>>>> If this driver will be merged, we'll have two drivers for the same
>> can
>>>>> core in the tree. The other one is the pch_can. What do you think
>> should
>>>>> be the mid term perspective for ccan based hardware?
>>>>
>>>> Yes, I know. Unfortunately, we did realize rather late the the PCH
>>>> controller is a C_CAN clone and the OKI/Intel ppls did not tell us
>>>> either. Therefore I asked Bhupesh to provide a SJA1000-a-like
>> interface
>>>> for the C_CAN, which would allow us to provide an alternative PCI
>> driver
>>>> "pch_pci.c" for the PCH. If that driver works well on the PCH
>> hardware
>>>> as well, we should merge the best of both, if necessary, and then
>>>> finally remove the pch_can driver. Would that be a reasonable
>> proposal.
>>>
>>> At least for me this looks great. The idea to have a similar approach
>> as we
>>> successfully implemented for the sja1000 will solve future hardware
>>> implementations based on the ccan controller core.
>>
>> A common driver for c_can based devices will stabilize more quickly and
>> does also especially reduce the maintanance effort significantly.
>>
>>> BTW. for the next submission of Bhupeshs patchset, i would propose to
>> name the
>>> driver 'ccan' instead of 'c_can', so that we have a
>>>
>>> linux/drivers/net/can/ccan/...
>>>
>>> path.
>>
>> You are late ;-). Bosch named the controller *C_CAN* and therefore I
>> asked Bhupesh some time ago to change the file name and variable name
>> prefix from ccan to c_can.
>
> Actually V1 of this patchset used the naming convention ccan.
> But as was rightly pointed out by Wolfgang and Mark, Bosch
> has officially named this core as C_CAN and the naming convention
> is kept as C_CAN throughout their user-manual and technical articles.
> IMHO, `c_can` seems to represent this Bosch core in a better way
> than ccan.
>
>>> Checking directory names in linux/drivers with
>>>
>>> find . -type d | grep '_'
>>>
>>> driver names with underscores are pretty unusual and mostly selected
>> without
>>> fortune:
>>>
>>> ./staging/olpc_dcon
>>> ./staging/wlags49_h2
>>> ./staging/wlags49_h2/man
>>> ./staging/serqt_usb2
>>> ./staging/intel_sst
>>> ./staging/quatech_usb2
>>> ./staging/asus_oled
>>> ./staging/wlags49_h25
>>> ./staging/ath6kl/hif/sdio/linux_sdio <- Ugh!
>>> ./staging/ath6kl/hif/sdio/linux_sdio/src
>>> ./staging/ath6kl/hif/sdio/linux_sdio/include
>>> ./net/pch_gbe
>>> ./net/fs_enet
>>> ./net/wireless/libertas_tf
>>> ./net/ibm_newemacds
>>>
>>> For that reason i would prefer 'ccan' to name this driver core.
>>
>> Well, not really a strong argument. But well, if other people do
>> *prefer* ccan I would not object against it. Bhupesh, what's your
>> opinion.
>
> I also prefer c_can :), because it makes the driver name similar to the
> core name. Please let me know if you agree for the same.
I fully agree and if nobody else complains, we should keep "c_can".
Wolfgang.
^ permalink raw reply
* RE: [E1000-devel] [e100] Page allocation failure warning(?) in 2.6.36.3
From: Chris Rankin @ 2011-01-11 8:52 UTC (permalink / raw)
To: e1000-devel@lists.sourceforge.net, Tushar NDave; +Cc: netdev@vger.kernel.org
In-Reply-To: <F675EE07F28A0A4E933E5F9DD28672FB01197E098F@orsmsx508.amr.corp.intel.com>
--- On Tue, 11/1/11, Dave, Tushar N <tushar.n.dave@intel.com> wrote:
The reason I asked you about bridge is because I have
> noticed "br0: port 1(eth1) entering learning state" in the
> dmesg log you sent.
> I am trying to figure out exactly what sequence of commands
> you run that produce this message " br0: port 1(eth1)
> entering learning state" in log.
Tushar,
Ah, sorry. I thought you were referring to a PCI bridge, or something similar.
The br0 interface contains the eth1 and eth2 interfaces, which each connects to a PC on the private LAN. The eth0 interface connects to the ADSL router, and br0 holds the PC's internal LAN IP address. (eth0, eth1 and eth2 are all e100 interfaces, of course.)
It's impossible to state whether the problem *only* happens when I use the bridge because:
a) I've always used the bridge, and need to for the LAN to work, and
b) the problem is both rare and intermittent, even when it does happen. I certainly didn't notice it with the 2.6.36.2 kernel, nor any of the 2.6.34 or 2.6.35 kernels, although the fact that I did with the 2.6.33.6 kernel suggests it was present in all those kernels anyway.
I'll send you the bridge setup and ifconfig information later; I'm not in front of that PC right now.
Thanks,
Chris
^ permalink raw reply
* Re: [PATCH v4 05/10] net/fec: add dual fec support for mx28
From: Sascha Hauer @ 2011-01-11 10:27 UTC (permalink / raw)
To: Shawn Guo
Cc: davem, gerg, baruch, eric, bryan.wu, r64343, B32542,
u.kleine-koenig, lw, w.sang, jamie, jamie, netdev,
linux-arm-kernel
In-Reply-To: <1294297998-26930-6-git-send-email-shawn.guo@freescale.com>
On Thu, Jan 06, 2011 at 03:13:13PM +0800, Shawn Guo wrote:
> This patch is to add mx28 dual fec support. Here are some key notes
> for mx28 fec controller.
>
> - The mx28 fec controller naming ENET-MAC is a different IP from FEC
> used on other i.mx variants. But they are basically compatible
> on software interface, so it's possible to share the same driver.
> - ENET-MAC design on mx28 made an improper assumption that it runs
> on a big-endian system. As the result, driver has to swap every
> frame going to and coming from the controller.
> - The external phys can only be configured by fec0, which means fec1
> can not work independently and both phys need to be configured by
> mii_bus attached on fec0.
> - ENET-MAC reset will get mac address registers reset too.
> - ENET-MAC MII/RMII mode and 10M/100M speed are configured
> differently FEC.
> - ETHER_EN bit must be set to get ENET-MAC interrupt work.
>
> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
> ---
> Changes for v4:
> - Use #ifndef CONFIG_ARM to include ColdFire header files
> - Define quirk bits in id_entry.driver_data to handle controller
> difference, which is more scalable than using device name
> - Define fec0_mii_bus as a static function in fec_enet_mii_init
> to fold the mii_bus instance attached on fec0
> - Use cpu_to_be32 over __swab32 in function swap_buffer
>
> Changes for v3:
> - Move v2 changes into patch #3
> - Use device name to check if it's running on ENET-MAC
>
> drivers/net/Kconfig | 7 ++-
> drivers/net/fec.c | 148 +++++++++++++++++++++++++++++++++++++++++++++------
> drivers/net/fec.h | 5 +-
> 3 files changed, 139 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 4f1755b..f34629b 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -1944,18 +1944,19 @@ config 68360_ENET
> config FEC
> bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
> depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
> - MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5
> + MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5 || SOC_IMX28
> select PHYLIB
> help
> Say Y here if you want to use the built-in 10/100 Fast ethernet
> controller on some Motorola ColdFire and Freescale i.MX processors.
>
> config FEC2
> - bool "Second FEC ethernet controller (on some ColdFire CPUs)"
> + bool "Second FEC ethernet controller"
> depends on FEC
> help
> Say Y here if you want to use the second built-in 10/100 Fast
> - ethernet controller on some Motorola ColdFire processors.
> + ethernet controller on some Motorola ColdFire and Freescale
> + i.MX processors.
This option is used nowhere and should be removed. Certainly it does not
have the effect of enabling the second ethernet controller.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH 0/3] can: at91_can: fix for errata 50.2.6.3 & 50.3.5.3
From: Marc Kleine-Budde @ 2011-01-11 10:28 UTC (permalink / raw)
To: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w; +Cc: netdev-u79uwXL29TY76Z2rM5mHXA
Hello,
as promised I've implemented the proposed workaround for the errata
50.2.6.3 & 50.3.5.3:
"Contents of Mailbox 0 can be sent Even if Mailbox is Disabled"
This means under high bus load it can happen that the mailbox 0 is send
to the bus. And it does happen, even with the mainline driver where
Mailbox 0 is a receive mailbox. The errata proposes not to use mailbox 0
and load it with an unused can_id that will not disturb the bus.
The first patch cleans up the driver without any functional changes, so
that the mailbox 0 can be disabled in the second patch. The third patch
adds a sysfs parameter to the driver, so that the identifier of mailbox 0
can configured.
This series applies to net-2.6/master. It has been tested on a ronetix pm9263
board against a PCI-SJA1000 card with the canfdtest utility.
regards, Marc
---
The following changes since commit b11a25aaeccc29d5090d1ce9776af20e3ee99ab9:
qlcnic: change module parameter permissions (2011-01-10 13:34:55 -0800)
are available in the git repository at:
git://git.pengutronix.de/git/mkl/linux-2.6.git can/at91_can-for-net-2.6
Marc Kleine-Budde (3):
can: at91_can: clean up usage of AT91_MB_RX_FIRST and AT91_MB_RX_NUM
can: at91_can: don't use mailbox 0
can: at91_can: make can_id of mailbox 0 configurable
drivers/net/can/at91_can.c | 138 +++++++++++++++++++++++++++++++++++--------
1 files changed, 112 insertions(+), 26 deletions(-)
^ permalink raw reply
* [PATCH 1/3] can: at91_can: clean up usage of AT91_MB_RX_FIRST and AT91_MB_RX_NUM
From: Marc Kleine-Budde @ 2011-01-11 10:28 UTC (permalink / raw)
To: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Marc Kleine-Budde
In-Reply-To: <1294741688-22699-1-git-send-email-mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
This patch cleans up the usage of two macros which specify the mailbox
usage. AT91_MB_RX_FIRST and AT91_MB_RX_NUM define the first and the
number of RX mailboxes. The current driver uses these variables in an
unclean way; assuming that AT91_MB_RX_FIRST is 0;
This patch cleans up the usage of these macros, no longer assuming
AT91_MB_RX_FIRST == 0.
Signed-off-by: Marc Kleine-Budde <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
drivers/net/can/at91_can.c | 18 ++++++++++--------
1 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 7ef83d0..892c3d8 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -2,7 +2,7 @@
* at91_can.c - CAN network driver for AT91 SoC CAN controller
*
* (C) 2007 by Hans J. Koch <hjk-vqZO0P4V72/QD6PfKP4TzA@public.gmane.org>
- * (C) 2008, 2009, 2010 by Marc Kleine-Budde <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
+ * (C) 2008, 2009, 2010, 2011 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'
@@ -55,7 +55,8 @@
#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_RX_LOW_MASK (AT91_MB_RX_MASK(AT91_MB_RX_SPLIT) & \
+ ~AT91_MB_RX_MASK(AT91_MB_RX_FIRST))
#define AT91_MB_TX_NUM (1 << AT91_MB_TX_SHIFT)
#define AT91_MB_TX_FIRST (AT91_MB_RX_LAST + 1)
@@ -254,7 +255,8 @@ static void at91_setup_mailboxes(struct net_device *dev)
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;
+ priv->tx_next = priv->tx_echo = 0;
+ priv->rx_next = AT91_MB_RX_FIRST;
}
static int at91_set_bittiming(struct net_device *dev)
@@ -590,10 +592,10 @@ static int at91_poll_rx(struct net_device *dev, int quota)
"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;
+ for (mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, priv->rx_next);
+ mb < AT91_MB_RX_LAST + 1 && quota > 0;
reg_sr = at91_read(priv, AT91_SR),
- mb = find_next_bit(addr, AT91_MB_RX_NUM, ++priv->rx_next)) {
+ mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, ++priv->rx_next)) {
at91_read_msg(dev, mb);
/* reactivate mailboxes */
@@ -610,8 +612,8 @@ static int at91_poll_rx(struct net_device *dev, int 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;
+ quota > 0 && mb > AT91_MB_RX_LAST) {
+ priv->rx_next = AT91_MB_RX_FIRST;
goto again;
}
--
1.7.2.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox