* [PATCH] fealnx: Write outside array bounds
From: Roel Kluin @ 2009-07-24 11:49 UTC (permalink / raw)
To: David S. Miller, netdev, Andrew Morton
phy_idx is checked to be < 4, but np->phys[] is 2 elements long
Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
---
Or should the number of elements be increased?
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index 48385c4..100badd 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -584,7 +584,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
if (np->flags == HAS_MII_XCVR) {
int phy, phy_idx = 0;
- for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
+ for (phy = 1; phy < 32 && phy_idx < 2; phy++) {
int mii_status = mdio_read(dev, phy, 1);
if (mii_status != 0xffff && mii_status != 0x0000) {
^ permalink raw reply related
* Re: [PATCH] USB host CDC Phonet network interface driver
From: Oliver Neukum @ 2009-07-24 12:01 UTC (permalink / raw)
To: Marcel Holtmann
Cc: Alan Cox, Rémi Denis-Courmont, ext Dan Williams,
netdev@vger.kernel.org, linux-usb@vger.kernel.org
In-Reply-To: <1248254134.28545.111.camel@violet>
Am Mittwoch, 22. Juli 2009 11:15:34 schrieb Marcel Holtmann:
> > > The AT stuff is really problematic. Look at the hoops ISDN and software
> > > modem drivers go through to emulate AT commands. I know even of a
> > > CDC-ACM modem which can't deal with AT commands inline (that's within
> > > spec). It seems to me we should have a modem API in kernel.
> >
> > For devices which don't deal in AT commands probably but for devices
> > whose firmware provides an AT command interface over serial I would
> > disagree.
>
> I fully agree here. Even if you think you get AT commands under control,
> you really won't in the end. That standard is so wildly mis-interpreted
> that it is not even funny anymore.
For these devices we could at least separate the data channel from the
control channel.
Regards
Oliver
^ permalink raw reply
* Re: [PATCH] USB host CDC Phonet network interface driver
From: Rémi Denis-Courmont @ 2009-07-24 12:14 UTC (permalink / raw)
To: ext Oliver Neukum
Cc: Marcel Holtmann, Alan Cox, ext Dan Williams,
netdev@vger.kernel.org, linux-usb@vger.kernel.org
In-Reply-To: <200907241401.20262.oliver@neukum.org>
On Friday 24 July 2009 15:01:19 ext Oliver Neukum wrote:
> Am Mittwoch, 22. Juli 2009 11:15:34 schrieb Marcel Holtmann:
> > > > The AT stuff is really problematic. Look at the hoops ISDN and
> > > > software modem drivers go through to emulate AT commands. I know even
> > > > of a CDC-ACM modem which can't deal with AT commands inline (that's
> > > > within spec). It seems to me we should have a modem API in kernel.
> > >
> > > For devices which don't deal in AT commands probably but for devices
> > > whose firmware provides an AT command interface over serial I would
> > > disagree.
> >
> > I fully agree here. Even if you think you get AT commands under control,
> > you really won't in the end. That standard is so wildly mis-interpreted
> > that it is not even funny anymore.
>
> For these devices we could at least separate the data channel from the
> control channel.
"These" as in AT devices? You want a line discipline to multiplex AT commands
inspite of PPP? I wonder if that'd work.
--
Rémi Denis-Courmont
Nokia Devices R&D, Maemo Software, Helsinki
^ permalink raw reply
* Re: [PATCH] USB host CDC Phonet network interface driver
From: Oliver Neukum @ 2009-07-24 12:31 UTC (permalink / raw)
To: Rémi Denis-Courmont
Cc: Marcel Holtmann, Alan Cox, ext Dan Williams,
netdev@vger.kernel.org, linux-usb@vger.kernel.org
In-Reply-To: <200907241514.18871.remi.denis-courmont@nokia.com>
Am Freitag, 24. Juli 2009 14:14:17 schrieb Rémi Denis-Courmont:
> On Friday 24 July 2009 15:01:19 ext Oliver Neukum wrote:
> > Am Mittwoch, 22. Juli 2009 11:15:34 schrieb Marcel Holtmann:
> > > > > The AT stuff is really problematic. Look at the hoops ISDN and
> > > > > software modem drivers go through to emulate AT commands. I know
> > > > > even of a CDC-ACM modem which can't deal with AT commands inline
> > > > > (that's within spec). It seems to me we should have a modem API in
> > > > > kernel.
> > > >
> > > > For devices which don't deal in AT commands probably but for devices
> > > > whose firmware provides an AT command interface over serial I would
> > > > disagree.
> > >
> > > I fully agree here. Even if you think you get AT commands under
> > > control, you really won't in the end. That standard is so wildly
> > > mis-interpreted that it is not even funny anymore.
> >
> > For these devices we could at least separate the data channel from the
> > control channel.
>
> "These" as in AT devices? You want a line discipline to multiplex AT
> commands inspite of PPP? I wonder if that'd work.
No, I was thinking of having two full devices, a data channel and a control
channel for devices that really talk AT commands natively.
Regards
Oliver
^ permalink raw reply
* Re: [RFC] [PATCH] Don't run __qdisc_run() on a stopped TX queue
From: Eric Dumazet @ 2009-07-24 12:46 UTC (permalink / raw)
To: Krishna Kumar; +Cc: davem, herbert, netdev, Jarek Poplawski, Herbert Xu
In-Reply-To: <20090720074607.32463.23013.sendpatchset@localhost.localdomain>
Krishna Kumar a écrit :
> From: Krishna Kumar <krkumar2@in.ibm.com>
> diff -ruNp org/net/sched/sch_generic.c new/net/sched/sch_generic.c
> --- org/net/sched/sch_generic.c 2009-05-25 07:48:07.000000000 +0530
> +++ new/net/sched/sch_generic.c 2009-07-20 13:09:18.000000000 +0530
> @@ -56,12 +56,8 @@ static inline struct sk_buff *dequeue_sk
> struct sk_buff *skb = q->gso_skb;
>
> if (unlikely(skb)) {
> - struct net_device *dev = qdisc_dev(q);
> - struct netdev_queue *txq;
> -
> /* check the reason of requeuing without tx lock first */
> - txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
> - if (!netif_tx_queue_stopped(txq) && !netif_tx_queue_frozen(txq))
> + if (!netif_tx_queue_frozen(q->dev_queue))
> q->gso_skb = NULL;
This part might be a separate patch...
Are we sure these are equivalent ?
OLD)
struct net_device *dev = qdisc_dev(q);
struct netdev_queue *txq;
txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
NEW)
struct netdev_queue *txq = q->dev_queue;
^ permalink raw reply
* Re: [PATCH] USB host CDC Phonet network interface driver
From: Alan Cox @ 2009-07-24 12:48 UTC (permalink / raw)
To: Oliver Neukum
Cc: Rémi Denis-Courmont, Marcel Holtmann, ext Dan Williams,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <200907241431.08858.oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>
> No, I was thinking of having two full devices, a data channel and a control
> channel for devices that really talk AT commands natively.
If the hardware does it great, however for things like a 3G modem you
have the problem that the PPP is over the AT command channel which may
itself be multiplexed. And the muxing in question is *ugly* - sort of
HDLC and LAP-B done wrong.
Alan
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] USB host CDC Phonet network interface driver
From: Rémi Denis-Courmont @ 2009-07-24 12:58 UTC (permalink / raw)
To: ext Dan Williams, netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: ext Marcel Holtmann,
linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <1248359692.774.22.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
On Thursday 23 July 2009 17:34:52 ext Dan Williams wrote:
> There are any number of devices that expose only one AT port (which of
> course gets used by PPP for data) and then a proprietary port. The
> proprietary port usually uses a custom USB protocol that can also handle
> SMS, status, RSSI, etc while the AT/PPP port is being used by ppp.
>
> So if that's the case for phonet, maybe you just want to provide either
> (a) documentation of the setup/status/sms/etc protocols, or (b) a shim
> library implementation for them that handles communication with the
> device itself.
Eventually, Ofono should get the missing bits for GPRS-via-Phonet.
> But IMHO, the call setup stuff is probably better done from userspace.
I was referring to cellular data connectivity. Indeed, I wouldn't propose
Netlink for network selection and circuit-switched services like SMS or voice
calls :)
> It's a really hard API to abstract. I guess you could write a netlink
> API for it like we have for 802.11, but with GSM/CDMA the standards are
> so widely ignored that it's just going to be impossible to get a stable
> kernel API for anything like this.
Really, you only need a way to:
- create a device, e.g. like IPIP tunnel devices,
- set it up: access point name, and optionally username and password,
- bring it up, get IP and DNS configurations from the network,
- watch for context suspend events: IFF_NOCARRIER could do that,
- and eventually tear down.
In fact, it seems much simpler than 802.11. Well OK, I ignored "details" such
as secondary contexts and quality of service.
--
Rémi Denis-Courmont
Nokia Devices R&D, Maemo Software, Helsinki
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] USB host CDC Phonet network interface driver
From: Rémi Denis-Courmont @ 2009-07-24 13:00 UTC (permalink / raw)
To: ext Alan Cox
Cc: Oliver Neukum, Marcel Holtmann, ext Dan Williams,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <20090724134805.0d9496be-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
On Friday 24 July 2009 15:48:05 ext Alan Cox wrote:
> > No, I was thinking of having two full devices, a data channel and a
> > control channel for devices that really talk AT commands natively.
>
> If the hardware does it great, however for things like a 3G modem you
> have the problem that the PPP is over the AT command channel which may
> itself be multiplexed. And the muxing in question is *ugly* - sort of
> HDLC and LAP-B done wrong.
I guess he meant that AT commands could be sent out-of-band, for those USB
modems that fully implement the ACM profile of CDC, if any.
--
Rémi Denis-Courmont
Nokia Devices R&D, Maemo Software, Helsinki
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] Add Support for Freescale FlexCAN CAN controller
From: Sascha Hauer @ 2009-07-24 13:19 UTC (permalink / raw)
To: Linux Netdev List; +Cc: Socketcan-core
Hi,
This patch adds support for the Freescale FlexCAN CAN controller.
The driver has been tested on an i.MX25 SoC with bitrates up to
1Mbit, remote frames and standard and extenden frames.
Please review and consider for inclusion.
Sascha
>From 94a607390f0d7b181e2ffdfe16a05f3aaca15ab9 Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer@pengutronix.de>
Date: Tue, 21 Jul 2009 10:47:19 +0200
Subject: [PATCH] Add Flexcan CAN driver
This core is found on some Freescale SoCs and also some Coldfire
SoCs. Support for Coldfire is missing though at the moment as
they have an older revision of the core which does not have RX FIFO
support.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/net/can/Kconfig | 6 +
drivers/net/can/Makefile | 1 +
drivers/net/can/flexcan.c | 696 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 703 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/can/flexcan.c
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 33821a8..99c6da4 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -74,6 +74,12 @@ config CAN_KVASER_PCI
This driver is for the the PCIcanx and PCIcan cards (1, 2 or
4 channel) from Kvaser (http://www.kvaser.com).
+config CAN_FLEXCAN
+ tristate "Support for Freescale FLEXCAN based chips"
+ depends on CAN_DEV
+ ---help---
+ Say Y here if you want to support for Freescale FlexCAN.
+
config CAN_DEBUG_DEVICES
bool "CAN devices debugging messages"
depends on CAN
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 523a941..25f2032 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -8,5 +8,6 @@ obj-$(CONFIG_CAN_DEV) += can-dev.o
can-dev-y := dev.o
obj-$(CONFIG_CAN_SJA1000) += sja1000/
+obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
new file mode 100644
index 0000000..3738898
--- /dev/null
+++ b/drivers/net/can/flexcan.c
@@ -0,0 +1,696 @@
+/*
+ * flexcan.c - FLEXCAN CAN controller driver
+ *
+ * Copyright (c) 2005-2006 Varma Electronics Oy
+ * Copyright (c) 2009 Sascha Hauer, Pengutronix
+ *
+ * Based on code originally by Andrey Volkov <avolkov@varma-el.com>
+ *
+ * LICENCE:
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/can/netlink.h>
+#include <linux/can/error.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/if_ether.h>
+#include <linux/can/dev.h>
+#include <linux/if_arp.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/can.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#define DRIVER_NAME "flexcan"
+
+/* FLEXCAN module configuration register (CANMCR) bits */
+#define CANMCR_MDIS (1 << 31)
+#define CANMCR_FRZ (1 << 30)
+#define CANMCR_FEN (1 << 29)
+#define CANMCR_HALT (1 << 28)
+#define CANMCR_SOFTRST (1 << 25)
+#define CANMCR_FRZACK (1 << 24)
+#define CANMCR_SUPV (1 << 23)
+#define CANMCR_SRX_DIS (1 << 17)
+#define CANMCR_MAXMB(x) ((x) & 0x0f)
+#define CANMCR_IDAM_A (0 << 8)
+#define CANMCR_IDAM_B (1 << 8)
+#define CANMCR_IDAM_C (2 << 8)
+
+/* FLEXCAN control register (CANCTRL) bits */
+#define CANCTRL_PRESDIV(x) (((x) & 0xff) << 24)
+#define CANCTRL_RJW(x) (((x) & 0x03) << 22)
+#define CANCTRL_PSEG1(x) (((x) & 0x07) << 19)
+#define CANCTRL_PSEG2(x) (((x) & 0x07) << 16)
+#define CANCTRL_BOFFMSK (1 << 15)
+#define CANCTRL_ERRMSK (1 << 14)
+#define CANCTRL_CLKSRC (1 << 13)
+#define CANCTRL_LPB (1 << 12)
+#define CANCTRL_TWRN_MSK (1 << 11)
+#define CANCTRL_RWRN_MSK (1 << 10)
+#define CANCTRL_SAMP (1 << 7)
+#define CANCTRL_BOFFREC (1 << 6)
+#define CANCTRL_TSYNC (1 << 5)
+#define CANCTRL_LBUF (1 << 4)
+#define CANCTRL_LOM (1 << 3)
+#define CANCTRL_PROPSEG(x) ((x) & 0x07)
+
+/* FLEXCAN error counter register (ERRCNT) bits */
+#define ERRCNT_REXECTR(x) (((x) & 0xff) << 8)
+#define ERRCNT_TXECTR(x) ((x) & 0xff)
+
+/* FLEXCAN error and status register (ERRSTAT) bits */
+#define ERRSTAT_TWRNINT (1 << 17)
+#define ERRSTAT_RWRNINT (1 << 16)
+#define ERRSTAT_BIT1ERR (1 << 15)
+#define ERRSTAT_BIT0ERR (1 << 14)
+#define ERRSTAT_ACKERR (1 << 13)
+#define ERRSTAT_CRCERR (1 << 12)
+#define ERRSTAT_FRMERR (1 << 11)
+#define ERRSTAT_STFERR (1 << 10)
+#define ERRSTAT_TXWRN (1 << 9)
+#define ERRSTAT_RXWRN (1 << 8)
+#define ERRSTAT_IDLE (1 << 7)
+#define ERRSTAT_TXRX (1 << 6)
+#define ERRSTAT_FLTCONF_MASK (3 << 4)
+#define ERRSTAT_FLTCONF_ERROR_ACTIVE (0 << 4)
+#define ERRSTAT_FLTCONF_ERROR_PASSIVE (1 << 4)
+#define ERRSTAT_FLTCONF_ERROR_BUS_OFF (2 << 4)
+#define ERRSTAT_BOFFINT (1 << 2)
+#define ERRSTAT_ERRINT (1 << 1)
+#define ERRSTAT_WAKINT (1 << 0)
+#define ERRSTAT_INT (ERRSTAT_BOFFINT | ERRSTAT_ERRINT | ERRSTAT_TWRNINT | \
+ ERRSTAT_RWRNINT)
+
+/* FLEXCAN interrupt flag register (IFLAG) bits */
+#define IFLAG_BUF(x) (1 << (x))
+#define IFLAG_RX_FIFO_OVERFLOW (1 << 7)
+#define IFLAG_RX_FIFO_WARN (1 << 6)
+#define IFLAG_RX_FIFO_AVAILABLE (1 << 5)
+
+/* FLEXCAN message buffers */
+#define MB_CNT_CODE(x) (((x) & 0xf) << 24)
+#define MB_CNT_SRR (1 << 22)
+#define MB_CNT_IDE (1 << 21)
+#define MB_CNT_RTR (1 << 20)
+#define MB_CNT_LENGTH(x) (((x) & 0xf) << 16)
+#define MB_CNT_TIMESTAMP(x) ((x) & 0xffff)
+
+#define MB_ID_STD (0x7ff << 18)
+#define MB_ID_EXT 0x1fffffff
+#define MB_CODE_MASK 0xf0ffffff
+
+/* Structure of the message buffer */
+struct flexcan_mb {
+ u32 can_dlc;
+ u32 can_id;
+ u32 data[2];
+};
+
+/* Structure of the hardware registers */
+struct flexcan_regs {
+ u32 canmcr; /* 0x00 */
+ u32 canctrl; /* 0x04 */
+ u32 timer; /* 0x08 */
+ u32 reserved1; /* 0x0c */
+ u32 rxgmask; /* 0x10 */
+ u32 rx14mask; /* 0x14 */
+ u32 rx15mask; /* 0x18 */
+ u32 errcnt; /* 0x1c */
+ u32 errstat; /* 0x20 */
+ u32 imask2; /* 0x24 */
+ u32 imask1; /* 0x28 */
+ u32 iflag2; /* 0x2c */
+ u32 iflag1; /* 0x30 */
+ u32 reserved4[19];
+ struct flexcan_mb cantxfg[64];
+};
+
+struct flexcan_priv {
+ struct can_priv can;
+ void __iomem *base;
+
+ struct net_device *dev;
+ struct clk *clk;
+};
+
+static struct can_bittiming_const flexcan_bittiming_const = {
+ .name = DRIVER_NAME,
+ .tseg1_min = 1,
+ .tseg1_max = 16,
+ .tseg2_min = 2,
+ .tseg2_max = 8,
+ .sjw_max = 4,
+ .brp_min = 1,
+ .brp_max = 256,
+ .brp_inc = 1,
+};
+
+#define TX_BUF_ID 8
+
+static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct can_frame *frame = (struct can_frame *)skb->data;
+ struct flexcan_priv *priv = netdev_priv(dev);
+ struct flexcan_regs __iomem *regs = priv->base;
+ u32 can_id;
+ u32 dlc = MB_CNT_CODE(0xc) | (frame->can_dlc << 16);
+ u32 *can_data;
+
+ netif_stop_queue(dev);
+
+ if (frame->can_id & CAN_EFF_FLAG) {
+ can_id = frame->can_id & MB_ID_EXT;
+ dlc |= MB_CNT_IDE | MB_CNT_SRR;
+ } else {
+ can_id = (frame->can_id & CAN_SFF_MASK) << 18;
+ }
+
+ if (frame->can_id & CAN_RTR_FLAG)
+ dlc |= MB_CNT_RTR;
+
+ writel(dlc, ®s->cantxfg[TX_BUF_ID].can_dlc);
+ writel(can_id, ®s->cantxfg[TX_BUF_ID].can_id);
+
+ can_data = (u32 *)frame->data;
+ writel(cpu_to_be32(*can_data), ®s->cantxfg[TX_BUF_ID].data[0]);
+ writel(cpu_to_be32(*(can_data + 1)), ®s->cantxfg[TX_BUF_ID].data[1]);
+
+ writel(dlc, ®s->cantxfg[TX_BUF_ID].can_dlc);
+
+ kfree_skb(skb);
+
+ return NETDEV_TX_OK;
+}
+
+static void flexcan_rx_frame(struct net_device *ndev,
+ struct flexcan_mb __iomem *mb)
+{
+ struct net_device_stats *stats = &ndev->stats;
+ struct sk_buff *skb;
+ struct can_frame *frame;
+ int ctrl = readl(&mb->can_dlc);
+ int length = (ctrl >> 16) & 0x0f;
+ u32 id;
+
+ skb = dev_alloc_skb(sizeof(struct can_frame));
+ if (!skb) {
+ stats->rx_dropped++;
+ return;
+ }
+
+ frame = (struct can_frame *)skb_put(skb,
+ sizeof(struct can_frame));
+
+ frame->can_dlc = length;
+ id = readl(&mb->can_id) & MB_ID_EXT;
+
+ if (ctrl & MB_CNT_IDE) {
+ frame->can_id = id & CAN_EFF_MASK;
+ frame->can_id |= CAN_EFF_FLAG;
+ if (ctrl & MB_CNT_RTR)
+ frame->can_id |= CAN_RTR_FLAG;
+ } else {
+ frame->can_id = id >> 18;
+ if (ctrl & MB_CNT_RTR)
+ frame->can_id |= CAN_RTR_FLAG;
+ }
+
+ *(u32 *)frame->data = be32_to_cpu(readl(&mb->data[0]));
+ *((u32 *)frame->data + 1) = be32_to_cpu(readl(&mb->data[1]));
+
+ stats->rx_packets++;
+ stats->rx_bytes += frame->can_dlc;
+ skb->dev = ndev;
+ skb->protocol = __constant_htons(ETH_P_CAN);
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ netif_rx(skb);
+}
+
+static void flexcan_error(struct net_device *ndev, u32 stat)
+{
+ struct can_frame *cf;
+ struct sk_buff *skb;
+ struct flexcan_priv *priv = netdev_priv(ndev);
+ struct net_device_stats *stats = &ndev->stats;
+ enum can_state state = priv->can.state;
+ int error_warning = 0, rx_errors = 0;
+
+ skb = dev_alloc_skb(sizeof(struct can_frame));
+ if (!skb)
+ return;
+
+ skb->dev = ndev;
+ skb->protocol = htons(ETH_P_CAN);
+
+ cf = (struct can_frame *)skb_put(skb, sizeof(*cf));
+ memset(cf, 0, sizeof(*cf));
+
+ cf->can_id = CAN_ERR_FLAG;
+ cf->can_dlc = CAN_ERR_DLC;
+
+ if (stat & ERRSTAT_RWRNINT) {
+ error_warning = 1;
+ state = CAN_STATE_ERROR_WARNING;
+ cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
+ }
+
+ if (stat & ERRSTAT_TWRNINT) {
+ error_warning = 1;
+ state = CAN_STATE_ERROR_WARNING;
+ cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
+ }
+
+ switch ((stat >> 4) & 0x3) {
+ case 0:
+ state = CAN_STATE_ERROR_ACTIVE;
+ break;
+ case 1:
+ state = CAN_STATE_ERROR_PASSIVE;
+ break;
+ default:
+ state = CAN_STATE_BUS_OFF;
+ break;
+ }
+
+ if (stat & ERRSTAT_BOFFINT) {
+ cf->can_id |= CAN_ERR_BUSOFF;
+ can_bus_off(ndev);
+ }
+
+ if (stat & ERRSTAT_BIT1ERR) {
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+ cf->data[2] |= CAN_ERR_PROT_BIT1;
+ }
+
+ if (stat & ERRSTAT_BIT0ERR) {
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+ cf->data[2] |= CAN_ERR_PROT_BIT0;
+ }
+
+ if (stat & ERRSTAT_FRMERR) {
+ rx_errors = 1;
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+ cf->data[2] |= CAN_ERR_PROT_FORM;
+ }
+
+ if (stat & ERRSTAT_STFERR) {
+ rx_errors = 1;
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ }
+
+
+ if (stat & ERRSTAT_ACKERR) {
+ rx_errors = 1;
+ cf->can_id |= CAN_ERR_ACK;
+ }
+
+ if (error_warning)
+ priv->can.can_stats.error_warning++;
+ if (rx_errors)
+ stats->rx_errors++;
+ if (cf->can_id & CAN_ERR_BUSERROR)
+ priv->can.can_stats.bus_error++;
+
+ priv->can.state = state;
+
+ netif_rx(skb);
+
+ ndev->last_rx = jiffies;
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+}
+
+static irqreturn_t flexcan_isr(int irq, void *dev_id)
+{
+ struct net_device *ndev = dev_id;
+ struct net_device_stats *stats = &ndev->stats;
+ struct flexcan_priv *priv = netdev_priv(ndev);
+ struct flexcan_regs __iomem *regs = priv->base;
+ u32 iflags, errstat;
+
+ errstat = readl(®s->errstat);
+ if (errstat & ERRSTAT_INT) {
+ flexcan_error(ndev, errstat);
+ writel(errstat & ERRSTAT_INT, ®s->errstat);
+ }
+
+ iflags = readl(®s->iflag1);
+
+ if (iflags & IFLAG_RX_FIFO_OVERFLOW) {
+ writel(IFLAG_RX_FIFO_OVERFLOW, ®s->iflag1);
+ stats->rx_over_errors++;
+ }
+
+ while (iflags & IFLAG_RX_FIFO_AVAILABLE) {
+ struct flexcan_mb __iomem *mb = ®s->cantxfg[0];
+
+ flexcan_rx_frame(ndev, mb);
+ writel(IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1);
+ readl(®s->timer);
+ iflags = readl(®s->iflag1);
+ }
+
+ if (iflags & (1 << TX_BUF_ID)) {
+ stats->tx_packets++;
+ writel((1 << TX_BUF_ID), ®s->iflag1);
+ netif_wake_queue(ndev);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int flexcan_set_bittiming(struct net_device *ndev)
+{
+ struct flexcan_priv *priv = netdev_priv(ndev);
+ struct can_bittiming *bt = &priv->can.bittiming;
+ struct flexcan_regs __iomem *regs = priv->base;
+ int ret = 0;
+ u32 reg;
+
+ dev_dbg(&ndev->dev, "%s: infreq: %ld brp: %d p1: %d p2: %d sample: %d"
+ " sjw: %d prop: %d\n",
+ __func__, clk_get_rate(priv->clk), bt->brp,
+ bt->phase_seg1, bt->phase_seg2, bt->sample_point,
+ bt->sjw, bt->prop_seg);
+
+ reg = readl(®s->canctrl);
+ reg &= ~(CANCTRL_SAMP | CANCTRL_PRESDIV(0xff) |
+ CANCTRL_PSEG1(7) | CANCTRL_PSEG2(7));
+ reg |= CANCTRL_PRESDIV(bt->brp - 1) |
+ CANCTRL_PSEG1(bt->phase_seg1 - 1) |
+ CANCTRL_PSEG2(bt->phase_seg2 - 1) |
+ CANCTRL_RJW(3) |
+ CANCTRL_PROPSEG(bt->prop_seg - 1);
+ if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+ reg |= CANCTRL_SAMP;
+ writel(reg, ®s->canctrl);
+
+ return ret;
+}
+
+
+static int flexcan_open(struct net_device *ndev)
+{
+ int ret, i;
+ struct flexcan_priv *priv = netdev_priv(ndev);
+ struct flexcan_regs __iomem *regs = priv->base;
+ u32 reg;
+
+ ret = open_candev(ndev);
+ if (ret)
+ return ret;
+
+ ret = request_irq(ndev->irq, flexcan_isr, IRQF_DISABLED,
+ DRIVER_NAME, ndev);
+ if (ret)
+ goto err_irq;
+
+ clk_enable(priv->clk);
+
+ reg = CANMCR_SOFTRST | CANMCR_HALT;
+ writel(CANMCR_SOFTRST, ®s->canmcr);
+ udelay(10);
+
+ if (readl(®s->canmcr) & CANMCR_SOFTRST) {
+ dev_err(&ndev->dev, "Failed to softreset can module.\n");
+ ret = -ENODEV;
+ goto err_reset;
+ }
+
+ /* Enable error and bus off interrupt */
+ reg = readl(®s->canctrl);
+ reg |= CANCTRL_CLKSRC | CANCTRL_ERRMSK | CANCTRL_BOFFMSK |
+ CANCTRL_BOFFREC | CANCTRL_TWRN_MSK | CANCTRL_TWRN_MSK;
+ writel(reg, ®s->canctrl);
+
+ /* Set lowest buffer transmitted first */
+ reg |= CANCTRL_LBUF;
+ writel(reg, ®s->canctrl);
+
+ for (i = 0; i < 64; i++) {
+ writel(0, ®s->cantxfg[i].can_dlc);
+ writel(0, ®s->cantxfg[i].can_id);
+ writel(0, ®s->cantxfg[i].data[0]);
+ writel(0, ®s->cantxfg[i].data[1]);
+
+ /* Put MB into rx queue */
+ writel(MB_CNT_CODE(0x04), ®s->cantxfg[i].can_dlc);
+ }
+
+ /* acceptance mask/acceptance code (accept everything) */
+ writel(0x0, ®s->rxgmask);
+ writel(0x0, ®s->rx14mask);
+ writel(0x0, ®s->rx15mask);
+
+ /* Enable flexcan module */
+ reg = readl(®s->canmcr);
+ reg &= ~(CANMCR_MDIS | CANMCR_FRZ);
+ reg |= CANMCR_IDAM_C | CANMCR_FEN;
+ writel(reg, ®s->canmcr);
+
+ /* Synchronize with the can bus */
+ reg &= ~CANMCR_HALT;
+ writel(reg, ®s->canmcr);
+
+ /* Enable interrupts */
+ writel(IFLAG_RX_FIFO_OVERFLOW | IFLAG_RX_FIFO_AVAILABLE |
+ IFLAG_BUF(TX_BUF_ID),
+ ®s->imask1);
+
+ netif_start_queue(ndev);
+
+ return 0;
+
+err_reset:
+ free_irq(ndev->irq, ndev);
+err_irq:
+ close_candev(ndev);
+
+ return ret;
+}
+
+static int flexcan_close(struct net_device *ndev)
+{
+ struct flexcan_priv *priv = netdev_priv(ndev);
+ struct flexcan_regs __iomem *regs = priv->base;
+
+ netif_stop_queue(ndev);
+
+ /* Disable all interrupts */
+ writel(0, ®s->imask1);
+ free_irq(ndev->irq, ndev);
+
+ close_candev(ndev);
+
+ /* Disable module */
+ writel(CANMCR_MDIS, ®s->canmcr);
+ clk_disable(priv->clk);
+ return 0;
+}
+
+static int flexcan_set_mode(struct net_device *ndev, enum can_mode mode)
+{
+ struct flexcan_priv *priv = netdev_priv(ndev);
+ struct flexcan_regs __iomem *regs = priv->base;
+ u32 reg;
+
+ switch (mode) {
+ case CAN_MODE_START:
+ reg = readl(®s->canctrl);
+ reg &= ~CANCTRL_BOFFREC;
+ writel(reg, ®s->canctrl);
+ reg |= CANCTRL_BOFFREC;
+ writel(reg, ®s->canctrl);
+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+ if (netif_queue_stopped(ndev))
+ netif_wake_queue(ndev);
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static const struct net_device_ops flexcan_netdev_ops = {
+ .ndo_open = flexcan_open,
+ .ndo_stop = flexcan_close,
+ .ndo_start_xmit = flexcan_start_xmit,
+};
+
+static int register_flexcandev(struct net_device *ndev)
+{
+ struct flexcan_priv *priv = netdev_priv(ndev);
+ struct flexcan_regs __iomem *regs = priv->base;
+ u32 reg;
+
+ reg = readl(®s->canmcr);
+ reg &= ~CANMCR_MDIS;
+ writel(reg, ®s->canmcr);
+ udelay(100);
+ reg |= CANMCR_FRZ | CANMCR_HALT | CANMCR_FEN;
+ writel(reg, ®s->canmcr);
+
+ reg = readl(®s->canmcr);
+
+ /* Currently we only support newer versions of this core featuring
+ * a RX FIFO. Older cores found on some Coldfire derivates are not
+ * yet supported.
+ */
+ if (!(reg & CANMCR_FEN)) {
+ dev_err(&ndev->dev, "Could not enable RX FIFO, unsupported core");
+ return -ENODEV;
+ }
+
+ ndev->flags |= IFF_ECHO; /* we support local echo in hardware */
+ ndev->netdev_ops = &flexcan_netdev_ops;
+
+ return register_candev(ndev);
+}
+
+static void unregister_flexcandev(struct net_device *ndev)
+{
+ struct flexcan_priv *priv = netdev_priv(ndev);
+ struct flexcan_regs __iomem *regs = priv->base;
+ u32 reg;
+
+ reg = readl(®s->canmcr);
+ reg |= CANMCR_FRZ | CANMCR_HALT | CANMCR_MDIS;
+ writel(reg, ®s->canmcr);
+
+ unregister_candev(ndev);
+}
+
+static int __devinit flexcan_probe(struct platform_device *pdev)
+{
+ struct resource *mem;
+ struct net_device *ndev;
+ struct flexcan_priv *priv;
+ u32 mem_size;
+ int ret;
+
+ ndev = alloc_candev(sizeof(struct flexcan_priv));
+ if (!ndev)
+ return -ENOMEM;
+
+ priv = netdev_priv(ndev);
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ ndev->irq = platform_get_irq(pdev, 0);
+ if (!mem || !ndev->irq) {
+ ret = -ENODEV;
+ goto failed_req;
+ }
+
+ mem_size = resource_size(mem);
+
+ if (!request_mem_region(mem->start, mem_size, DRIVER_NAME)) {
+ ret = -EBUSY;
+ goto failed_req;
+ }
+
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+
+ priv->base = ioremap(mem->start, mem_size);
+ if (!priv->base) {
+ ret = -ENOMEM;
+ goto failed_map;
+ }
+
+ priv->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ ret = PTR_ERR(priv->clk);
+ goto failed_clock;
+ }
+ priv->can.clock.freq = clk_get_rate(priv->clk);
+
+ platform_set_drvdata(pdev, ndev);
+
+ priv->can.do_set_bittiming = flexcan_set_bittiming;
+ priv->can.bittiming_const = &flexcan_bittiming_const;
+ priv->can.do_set_mode = flexcan_set_mode;
+
+ ret = register_flexcandev(ndev);
+ if (ret)
+ goto failed_register;
+
+ return 0;
+
+failed_register:
+ clk_put(priv->clk);
+failed_clock:
+ iounmap(priv->base);
+failed_map:
+ release_mem_region(mem->start, mem_size);
+failed_req:
+ free_candev(ndev);
+
+ return ret;
+}
+
+static int __devexit flexcan_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct flexcan_priv *priv = netdev_priv(ndev);
+ struct resource *mem;
+
+ unregister_flexcandev(ndev);
+ platform_set_drvdata(pdev, NULL);
+ iounmap(priv->base);
+ clk_put(priv->clk);
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(mem->start, resource_size(mem));
+ free_candev(ndev);
+
+ return 0;
+}
+
+static struct platform_driver flexcan_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+ .probe = flexcan_probe,
+ .remove = __devexit_p(flexcan_remove),
+};
+
+static int __init flexcan_init(void)
+{
+ return platform_driver_register(&flexcan_driver);
+}
+
+static void __exit flexcan_exit(void)
+{
+ platform_driver_unregister(&flexcan_driver);
+}
+
+module_init(flexcan_init);
+module_exit(flexcan_exit);
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CAN port driver for flexcan based chip");
--
1.6.3.3
--
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 related
* Re: [PATCH] USB host CDC Phonet network interface driver
From: Oliver Neukum @ 2009-07-24 14:12 UTC (permalink / raw)
To: Alan Cox
Cc: Rémi Denis-Courmont, Marcel Holtmann, ext Dan Williams,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <20090724134805.0d9496be-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
Am Freitag, 24. Juli 2009 14:48:05 schrieb Alan Cox:
> > No, I was thinking of having two full devices, a data channel and a
> > control channel for devices that really talk AT commands natively.
>
> If the hardware does it great, however for things like a 3G modem you
> have the problem that the PPP is over the AT command channel which may
> itself be multiplexed. And the muxing in question is *ugly* - sort of
> HDLC and LAP-B done wrong.
Well, yes, but we would really like a separate control channel, so we
can query parameters like signal strength, while we do PPP over the data
channel.
Regards
Oliver
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] USB host CDC Phonet network interface driver
From: Alan Cox @ 2009-07-24 14:19 UTC (permalink / raw)
To: Oliver Neukum
Cc: Rémi Denis-Courmont, Marcel Holtmann, ext Dan Williams,
netdev@vger.kernel.org, linux-usb@vger.kernel.org
In-Reply-To: <200907241612.41871.oliver@neukum.org>
On Fri, 24 Jul 2009 16:12:41 +0200
Oliver Neukum <oliver@neukum.org> wrote:
> Am Freitag, 24. Juli 2009 14:48:05 schrieb Alan Cox:
> > > No, I was thinking of having two full devices, a data channel and a
> > > control channel for devices that really talk AT commands natively.
> >
> > If the hardware does it great, however for things like a 3G modem you
> > have the problem that the PPP is over the AT command channel which may
> > itself be multiplexed. And the muxing in question is *ugly* - sort of
> > HDLC and LAP-B done wrong.
>
> Well, yes, but we would really like a separate control channel, so we
> can query parameters like signal strength, while we do PPP over the data
> channel.
Thats the notion of the AT mux stuff - you get multiple AT channels and
you can stuff PPP down one of them. It's still butt ugly.
^ permalink raw reply
* Re: [RFC] [PATCH] Don't run __qdisc_run() on a stopped TX queue
From: Herbert Xu @ 2009-07-24 14:54 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Krishna Kumar, davem, netdev, Jarek Poplawski
In-Reply-To: <4A69AD0E.4020701@cosmosbay.com>
On Fri, Jul 24, 2009 at 02:46:06PM +0200, Eric Dumazet wrote:
> Krishna Kumar a écrit :
> > From: Krishna Kumar <krkumar2@in.ibm.com>
> > diff -ruNp org/net/sched/sch_generic.c new/net/sched/sch_generic.c
> > --- org/net/sched/sch_generic.c 2009-05-25 07:48:07.000000000 +0530
> > +++ new/net/sched/sch_generic.c 2009-07-20 13:09:18.000000000 +0530
> > @@ -56,12 +56,8 @@ static inline struct sk_buff *dequeue_sk
> > struct sk_buff *skb = q->gso_skb;
> >
> > if (unlikely(skb)) {
> > - struct net_device *dev = qdisc_dev(q);
> > - struct netdev_queue *txq;
> > -
> > /* check the reason of requeuing without tx lock first */
> > - txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
> > - if (!netif_tx_queue_stopped(txq) && !netif_tx_queue_frozen(txq))
> > + if (!netif_tx_queue_frozen(q->dev_queue))
> > q->gso_skb = NULL;
>
> This part might be a separate patch...
>
> Are we sure these are equivalent ?
I think the only thing that can change this is act_skbedit. But
really any queue that changes the skb queue mapping should physically
move the packet to that qdisc.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH] Add Support for Freescale FlexCAN CAN controller
From: Wolfgang Grandegger @ 2009-07-24 14:55 UTC (permalink / raw)
To: Sascha Hauer; +Cc: Linux Netdev List, Socketcan-core
In-Reply-To: <20090724131933.GL2714@pengutronix.de>
Hi Sascha,
Sascha Hauer wrote:
> Hi,
>
> This patch adds support for the Freescale FlexCAN CAN controller.
> The driver has been tested on an i.MX25 SoC with bitrates up to
> 1Mbit, remote frames and standard and extenden frames.
>
> Please review and consider for inclusion.
See below...
>
> Sascha
>
>
>>From 94a607390f0d7b181e2ffdfe16a05f3aaca15ab9 Mon Sep 17 00:00:00 2001
> From: Sascha Hauer <s.hauer@pengutronix.de>
> Date: Tue, 21 Jul 2009 10:47:19 +0200
> Subject: [PATCH] Add Flexcan CAN driver
The prefix "can:" would be nice here.
> This core is found on some Freescale SoCs and also some Coldfire
> SoCs. Support for Coldfire is missing though at the moment as
> they have an older revision of the core which does not have RX FIFO
> support.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> drivers/net/can/Kconfig | 6 +
> drivers/net/can/Makefile | 1 +
> drivers/net/can/flexcan.c | 696 +++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 703 insertions(+), 0 deletions(-)
> create mode 100644 drivers/net/can/flexcan.c
>
> diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> index 33821a8..99c6da4 100644
> --- a/drivers/net/can/Kconfig
> +++ b/drivers/net/can/Kconfig
> @@ -74,6 +74,12 @@ config CAN_KVASER_PCI
> This driver is for the the PCIcanx and PCIcan cards (1, 2 or
> 4 channel) from Kvaser (http://www.kvaser.com).
>
> +config CAN_FLEXCAN
> + tristate "Support for Freescale FLEXCAN based chips"
> + depends on CAN_DEV
> + ---help---
> + Say Y here if you want to support for Freescale FlexCAN.
> +
> config CAN_DEBUG_DEVICES
> bool "CAN devices debugging messages"
> depends on CAN
> diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
> index 523a941..25f2032 100644
> --- a/drivers/net/can/Makefile
> +++ b/drivers/net/can/Makefile
> @@ -8,5 +8,6 @@ obj-$(CONFIG_CAN_DEV) += can-dev.o
> can-dev-y := dev.o
>
> obj-$(CONFIG_CAN_SJA1000) += sja1000/
> +obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o
>
> ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
> diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
> new file mode 100644
> index 0000000..3738898
> --- /dev/null
> +++ b/drivers/net/can/flexcan.c
> @@ -0,0 +1,696 @@
> +/*
> + * flexcan.c - FLEXCAN CAN controller driver
> + *
> + * Copyright (c) 2005-2006 Varma Electronics Oy
> + * Copyright (c) 2009 Sascha Hauer, Pengutronix
> + *
> + * Based on code originally by Andrey Volkov <avolkov@varma-el.com>
> + *
> + * LICENCE:
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + *
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/can/netlink.h>
> +#include <linux/can/error.h>
> +#include <linux/interrupt.h>
> +#include <linux/netdevice.h>
> +#include <linux/if_ether.h>
> +#include <linux/can/dev.h>
> +#include <linux/if_arp.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/list.h>
> +#include <linux/can.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +
> +#define DRIVER_NAME "flexcan"
> +
> +/* FLEXCAN module configuration register (CANMCR) bits */
> +#define CANMCR_MDIS (1 << 31)
> +#define CANMCR_FRZ (1 << 30)
> +#define CANMCR_FEN (1 << 29)
> +#define CANMCR_HALT (1 << 28)
> +#define CANMCR_SOFTRST (1 << 25)
> +#define CANMCR_FRZACK (1 << 24)
> +#define CANMCR_SUPV (1 << 23)
> +#define CANMCR_SRX_DIS (1 << 17)
> +#define CANMCR_MAXMB(x) ((x) & 0x0f)
> +#define CANMCR_IDAM_A (0 << 8)
> +#define CANMCR_IDAM_B (1 << 8)
> +#define CANMCR_IDAM_C (2 << 8)
> +
> +/* FLEXCAN control register (CANCTRL) bits */
> +#define CANCTRL_PRESDIV(x) (((x) & 0xff) << 24)
> +#define CANCTRL_RJW(x) (((x) & 0x03) << 22)
> +#define CANCTRL_PSEG1(x) (((x) & 0x07) << 19)
> +#define CANCTRL_PSEG2(x) (((x) & 0x07) << 16)
> +#define CANCTRL_BOFFMSK (1 << 15)
> +#define CANCTRL_ERRMSK (1 << 14)
> +#define CANCTRL_CLKSRC (1 << 13)
> +#define CANCTRL_LPB (1 << 12)
> +#define CANCTRL_TWRN_MSK (1 << 11)
> +#define CANCTRL_RWRN_MSK (1 << 10)
> +#define CANCTRL_SAMP (1 << 7)
> +#define CANCTRL_BOFFREC (1 << 6)
> +#define CANCTRL_TSYNC (1 << 5)
> +#define CANCTRL_LBUF (1 << 4)
> +#define CANCTRL_LOM (1 << 3)
> +#define CANCTRL_PROPSEG(x) ((x) & 0x07)
> +
> +/* FLEXCAN error counter register (ERRCNT) bits */
> +#define ERRCNT_REXECTR(x) (((x) & 0xff) << 8)
> +#define ERRCNT_TXECTR(x) ((x) & 0xff)
> +
> +/* FLEXCAN error and status register (ERRSTAT) bits */
> +#define ERRSTAT_TWRNINT (1 << 17)
> +#define ERRSTAT_RWRNINT (1 << 16)
> +#define ERRSTAT_BIT1ERR (1 << 15)
> +#define ERRSTAT_BIT0ERR (1 << 14)
> +#define ERRSTAT_ACKERR (1 << 13)
> +#define ERRSTAT_CRCERR (1 << 12)
> +#define ERRSTAT_FRMERR (1 << 11)
> +#define ERRSTAT_STFERR (1 << 10)
> +#define ERRSTAT_TXWRN (1 << 9)
> +#define ERRSTAT_RXWRN (1 << 8)
> +#define ERRSTAT_IDLE (1 << 7)
> +#define ERRSTAT_TXRX (1 << 6)
> +#define ERRSTAT_FLTCONF_MASK (3 << 4)
> +#define ERRSTAT_FLTCONF_ERROR_ACTIVE (0 << 4)
> +#define ERRSTAT_FLTCONF_ERROR_PASSIVE (1 << 4)
> +#define ERRSTAT_FLTCONF_ERROR_BUS_OFF (2 << 4)
> +#define ERRSTAT_BOFFINT (1 << 2)
> +#define ERRSTAT_ERRINT (1 << 1)
> +#define ERRSTAT_WAKINT (1 << 0)
> +#define ERRSTAT_INT (ERRSTAT_BOFFINT | ERRSTAT_ERRINT | ERRSTAT_TWRNINT | \
> + ERRSTAT_RWRNINT)
> +
> +/* FLEXCAN interrupt flag register (IFLAG) bits */
> +#define IFLAG_BUF(x) (1 << (x))
> +#define IFLAG_RX_FIFO_OVERFLOW (1 << 7)
> +#define IFLAG_RX_FIFO_WARN (1 << 6)
> +#define IFLAG_RX_FIFO_AVAILABLE (1 << 5)
> +Cou
> +/* FLEXCAN message buffers */
> +#define MB_CNT_CODE(x) (((x) & 0xf) << 24)
> +#define MB_CNT_SRR (1 << 22)
> +#define MB_CNT_IDE (1 << 21)
> +#define MB_CNT_RTR (1 << 20)
> +#define MB_CNT_LENGTH(x) (((x) & 0xf) << 16)
> +#define MB_CNT_TIMESTAMP(x) ((x) & 0xffff)
> +
> +#define MB_ID_STD (0x7ff << 18)
> +#define MB_ID_EXT 0x1fffffff
> +#define MB_CODE_MASK 0xf0ffffff
> +
> +/* Structure of the message buffer */
> +struct flexcan_mb {
> + u32 can_dlc;
> + u32 can_id;
> + u32 data[2];
> +};
> +
> +/* Structure of the hardware registers */
> +struct flexcan_regs {
> + u32 canmcr; /* 0x00 */
> + u32 canctrl; /* 0x04 */
> + u32 timer; /* 0x08 */
> + u32 reserved1; /* 0x0c */
> + u32 rxgmask; /* 0x10 */
> + u32 rx14mask; /* 0x14 */
> + u32 rx15mask; /* 0x18 */
> + u32 errcnt; /* 0x1c */
> + u32 errstat; /* 0x20 */
> + u32 imask2; /* 0x24 */
> + u32 imask1; /* 0x28 */
> + u32 iflag2; /* 0x2c */
> + u32 iflag1; /* 0x30 */
> + u32 reserved4[19];
> + struct flexcan_mb cantxfg[64];
> +};
> +
> +struct flexcan_priv {
> + struct can_priv can;
> + void __iomem *base;
> +
> + struct net_device *dev;
> + struct clk *clk;
> +};
> +
> +static struct can_bittiming_const flexcan_bittiming_const = {
> + .name = DRIVER_NAME,
> + .tseg1_min = 1,
> + .tseg1_max = 16,
> + .tseg2_min = 2,
> + .tseg2_max = 8,
> + .sjw_max = 4,
> + .brp_min = 1,
> + .brp_max = 256,
> + .brp_inc = 1,
> +};
> +
> +#define TX_BUF_ID 8
> +
> +static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> + struct can_frame *frame = (struct can_frame *)skb->data;
> + struct flexcan_priv *priv = netdev_priv(dev);
> + struct flexcan_regs __iomem *regs = priv->base;
> + u32 can_id;
> + u32 dlc = MB_CNT_CODE(0xc) | (frame->can_dlc << 16);
> + u32 *can_data;
> +
> + netif_stop_queue(dev);
> +
> + if (frame->can_id & CAN_EFF_FLAG) {
> + can_id = frame->can_id & MB_ID_EXT;
> + dlc |= MB_CNT_IDE | MB_CNT_SRR;
> + } else {
> + can_id = (frame->can_id & CAN_SFF_MASK) << 18;
> + }
> +
> + if (frame->can_id & CAN_RTR_FLAG)
> + dlc |= MB_CNT_RTR;
> +
> + writel(dlc, ®s->cantxfg[TX_BUF_ID].can_dlc);
> + writel(can_id, ®s->cantxfg[TX_BUF_ID].can_id);
> +
> + can_data = (u32 *)frame->data;
> + writel(cpu_to_be32(*can_data), ®s->cantxfg[TX_BUF_ID].data[0]);
> + writel(cpu_to_be32(*(can_data + 1)), ®s->cantxfg[TX_BUF_ID].data[1]);
> +
> + writel(dlc, ®s->cantxfg[TX_BUF_ID].can_dlc);
> +
> + kfree_skb(skb);
Support for echo skb using can_put/get_echo_skb() is missing. It should
not be a big deal to add it.
> +
> + return NETDEV_TX_OK;
> +}
> +
> +static void flexcan_rx_frame(struct net_device *ndev,
> + struct flexcan_mb __iomem *mb)
> +{
> + struct net_device_stats *stats = &ndev->stats;
> + struct sk_buff *skb;
> + struct can_frame *frame;
> + int ctrl = readl(&mb->can_dlc);
> + int length = (ctrl >> 16) & 0x0f;
> + u32 id;
> +
> + skb = dev_alloc_skb(sizeof(struct can_frame));
> + if (!skb) {
> + stats->rx_dropped++;
> + return;
> + }
> +
> + frame = (struct can_frame *)skb_put(skb,
> + sizeof(struct can_frame));
> +
> + frame->can_dlc = length;
> + id = readl(&mb->can_id) & MB_ID_EXT;
> +
> + if (ctrl & MB_CNT_IDE) {
> + frame->can_id = id & CAN_EFF_MASK;
> + frame->can_id |= CAN_EFF_FLAG;
> + if (ctrl & MB_CNT_RTR)
> + frame->can_id |= CAN_RTR_FLAG;
> + } else {
> + frame->can_id = id >> 18;
> + if (ctrl & MB_CNT_RTR)
> + frame->can_id |= CAN_RTR_FLAG;
> + }
> +
> + *(u32 *)frame->data = be32_to_cpu(readl(&mb->data[0]));
> + *((u32 *)frame->data + 1) = be32_to_cpu(readl(&mb->data[1]));
> +
> + stats->rx_packets++;
> + stats->rx_bytes += frame->can_dlc;
> + skb->dev = ndev;
> + skb->protocol = __constant_htons(ETH_P_CAN);
> + skb->ip_summed = CHECKSUM_UNNECESSARY;
> +
> + netif_rx(skb);
> +}
> +
> +static void flexcan_error(struct net_device *ndev, u32 stat)
> +{
> + struct can_frame *cf;
> + struct sk_buff *skb;
> + struct flexcan_priv *priv = netdev_priv(ndev);
> + struct net_device_stats *stats = &ndev->stats;
> + enum can_state state = priv->can.state;
> + int error_warning = 0, rx_errors = 0;
> +
> + skb = dev_alloc_skb(sizeof(struct can_frame));
> + if (!skb)
> + return;
> +
> + skb->dev = ndev;
> + skb->protocol = htons(ETH_P_CAN);
skb->protocol = __constant_htons(ETH_P_CAN);
skb->ip_summed = CHECKSUM_UNNECESSARY;
as above?!
> +
> + cf = (struct can_frame *)skb_put(skb, sizeof(*cf));
> + memset(cf, 0, sizeof(*cf));
> +
> + cf->can_id = CAN_ERR_FLAG;
> + cf->can_dlc = CAN_ERR_DLC;
> +
> + if (stat & ERRSTAT_RWRNINT) {
> + error_warning = 1;
> + state = CAN_STATE_ERROR_WARNING;
> + cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
> + }
> +
> + if (stat & ERRSTAT_TWRNINT) {
> + error_warning = 1;
> + state = CAN_STATE_ERROR_WARNING;
> + cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
> + }
> +
> + switch ((stat >> 4) & 0x3) {
> + case 0:
> + state = CAN_STATE_ERROR_ACTIVE;
> + break;
Does the device recover autmatically from the bus-off state? Can
automatic recovery be configured (switched off?).
> + case 1:
> + state = CAN_STATE_ERROR_PASSIVE;
> + break;
> + default:
> + state = CAN_STATE_BUS_OFF;
> + break;
> + }
You seem to handle a state change to error passive like a change to
error warning.
> + if (stat & ERRSTAT_BOFFINT) {
> + cf->can_id |= CAN_ERR_BUSOFF;
> + can_bus_off(ndev);
> + }
> +
> + if (stat & ERRSTAT_BIT1ERR) {
rx_error = 1; ???
> + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
> + cf->data[2] |= CAN_ERR_PROT_BIT1;
> + }
> +
> + if (stat & ERRSTAT_BIT0ERR) {
rx_error = 1; ???
> + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
> + cf->data[2] |= CAN_ERR_PROT_BIT0;
> + }
> +
> + if (stat & ERRSTAT_FRMERR) {
> + rx_errors = 1;
> + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
> + cf->data[2] |= CAN_ERR_PROT_FORM;
> + }
> +
> + if (stat & ERRSTAT_STFERR) {
> + rx_errors = 1;
> + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
> + cf->data[2] |= CAN_ERR_PROT_STUFF;
> + }
> +
> +
> + if (stat & ERRSTAT_ACKERR) {
> + rx_errors = 1;
> + cf->can_id |= CAN_ERR_ACK;
Is ACK error a RX error?
> + }
> +
> + if (error_warning)
> + priv->can.can_stats.error_warning++;
What about priv->can.can_stats.error_passive;
> + if (rx_errors)
> + stats->rx_errors++;
> + if (cf->can_id & CAN_ERR_BUSERROR)
> + priv->can.can_stats.bus_error++;
It gets incremented in can_bus_off() already!
> + priv->can.state = state;
> +
> + netif_rx(skb);
> +
> + ndev->last_rx = jiffies;
> + stats->rx_packets++;
> + stats->rx_bytes += cf->can_dlc;
> +}
> +
> +static irqreturn_t flexcan_isr(int irq, void *dev_id)
> +{
> + struct net_device *ndev = dev_id;
> + struct net_device_stats *stats = &ndev->stats;
> + struct flexcan_priv *priv = netdev_priv(ndev);
> + struct flexcan_regs __iomem *regs = priv->base;
> + u32 iflags, errstat;
> +
> + errstat = readl(®s->errstat);
> + if (errstat & ERRSTAT_INT) {
> + flexcan_error(ndev, errstat);
> + writel(errstat & ERRSTAT_INT, ®s->errstat);
> + }
> +
> + iflags = readl(®s->iflag1);
> +
> + if (iflags & IFLAG_RX_FIFO_OVERFLOW) {
> + writel(IFLAG_RX_FIFO_OVERFLOW, ®s->iflag1);
> + stats->rx_over_errors++;
stats->rx_errors++; ???
> + }
> +
> + while (iflags & IFLAG_RX_FIFO_AVAILABLE) {
> + struct flexcan_mb __iomem *mb = ®s->cantxfg[0];
> +
> + flexcan_rx_frame(ndev, mb);
> + writel(IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1);
> + readl(®s->timer);
> + iflags = readl(®s->iflag1);
> + }
> +
> + if (iflags & (1 << TX_BUF_ID)) {
> + stats->tx_packets++;
> + writel((1 << TX_BUF_ID), ®s->iflag1);
> + netif_wake_queue(ndev);
> + }
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int flexcan_set_bittiming(struct net_device *ndev)
> +{
> + struct flexcan_priv *priv = netdev_priv(ndev);
> + struct can_bittiming *bt = &priv->can.bittiming;
> + struct flexcan_regs __iomem *regs = priv->base;
> + int ret = 0;
> + u32 reg;
> +
> + dev_dbg(&ndev->dev, "%s: infreq: %ld brp: %d p1: %d p2: %d sample: %d"
> + " sjw: %d prop: %d\n",
> + __func__, clk_get_rate(priv->clk), bt->brp,
> + bt->phase_seg1, bt->phase_seg2, bt->sample_point,
> + bt->sjw, bt->prop_seg);
Could you replace this dev_dbg() in favor of a
dev_info(dev->dev.parent, "setting CANCTRL=0x%x\n", reg);
before returning.
> + reg = readl(®s->canctrl);
> + reg &= ~(CANCTRL_SAMP | CANCTRL_PRESDIV(0xff) |
> + CANCTRL_PSEG1(7) | CANCTRL_PSEG2(7));
> + reg |= CANCTRL_PRESDIV(bt->brp - 1) |
> + CANCTRL_PSEG1(bt->phase_seg1 - 1) |
> + CANCTRL_PSEG2(bt->phase_seg2 - 1) |
> + CANCTRL_RJW(3) |
> + CANCTRL_PROPSEG(bt->prop_seg - 1);
> + if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
> + reg |= CANCTRL_SAMP;
> + writel(reg, ®s->canctrl);
> +
> + return ret;
> +}
> +
> +
Two empty lines!
> +static int flexcan_open(struct net_device *ndev)
> +{
> + int ret, i;
> + struct flexcan_priv *priv = netdev_priv(ndev);
> + struct flexcan_regs __iomem *regs = priv->base;
> + u32 reg;
> +
> + ret = open_candev(ndev);
> + if (ret)
> + return ret;
> +
> + ret = request_irq(ndev->irq, flexcan_isr, IRQF_DISABLED,
> + DRIVER_NAME, ndev);
Do you really need IRQF_DISABLED?
> + if (ret)
> + goto err_irq;
> +
> + clk_enable(priv->clk);
> +
> + reg = CANMCR_SOFTRST | CANMCR_HALT;
> + writel(CANMCR_SOFTRST, ®s->canmcr);
> + udelay(10);
> +
> + if (readl(®s->canmcr) & CANMCR_SOFTRST) {
> + dev_err(&ndev->dev, "Failed to softreset can module.\n");
> + ret = -ENODEV;
> + goto err_reset;
> + }
> +
> + /* Enable error and bus off interrupt */
> + reg = readl(®s->canctrl);
> + reg |= CANCTRL_CLKSRC | CANCTRL_ERRMSK | CANCTRL_BOFFMSK |
> + CANCTRL_BOFFREC | CANCTRL_TWRN_MSK | CANCTRL_TWRN_MSK;
> + writel(reg, ®s->canctrl);
> +
> + /* Set lowest buffer transmitted first */
> + reg |= CANCTRL_LBUF;
> + writel(reg, ®s->canctrl);
> +
> + for (i = 0; i < 64; i++) {
> + writel(0, ®s->cantxfg[i].can_dlc);
> + writel(0, ®s->cantxfg[i].can_id);
> + writel(0, ®s->cantxfg[i].data[0]);
> + writel(0, ®s->cantxfg[i].data[1]);
> +
> + /* Put MB into rx queue */
> + writel(MB_CNT_CODE(0x04), ®s->cantxfg[i].can_dlc);
> + }
> +
> + /* acceptance mask/acceptance code (accept everything) */
> + writel(0x0, ®s->rxgmask);
> + writel(0x0, ®s->rx14mask);
> + writel(0x0, ®s->rx15mask);
> +
> + /* Enable flexcan module */
> + reg = readl(®s->canmcr);
> + reg &= ~(CANMCR_MDIS | CANMCR_FRZ);
> + reg |= CANMCR_IDAM_C | CANMCR_FEN;
> + writel(reg, ®s->canmcr);
> +
> + /* Synchronize with the can bus */
> + reg &= ~CANMCR_HALT;
> + writel(reg, ®s->canmcr);
> +
> + /* Enable interrupts */
> + writel(IFLAG_RX_FIFO_OVERFLOW | IFLAG_RX_FIFO_AVAILABLE |
> + IFLAG_BUF(TX_BUF_ID),
> + ®s->imask1);
> +
> + netif_start_queue(ndev);
> +
> + return 0;
> +
> +err_reset:
> + free_irq(ndev->irq, ndev);
> +err_irq:
> + close_candev(ndev);
> +
> + return ret;
> +}
> +
> +static int flexcan_close(struct net_device *ndev)
> +{
> + struct flexcan_priv *priv = netdev_priv(ndev);
> + struct flexcan_regs __iomem *regs = priv->base;
> +
> + netif_stop_queue(ndev);
> +
> + /* Disable all interrupts */
> + writel(0, ®s->imask1);
> + free_irq(ndev->irq, ndev);
> +
> + close_candev(ndev);
> +
> + /* Disable module */
> + writel(CANMCR_MDIS, ®s->canmcr);
> + clk_disable(priv->clk);
> + return 0;
> +}
> +
> +static int flexcan_set_mode(struct net_device *ndev, enum can_mode mode)
> +{
> + struct flexcan_priv *priv = netdev_priv(ndev);
> + struct flexcan_regs __iomem *regs = priv->base;
> + u32 reg;
> +
> + switch (mode) {
> + case CAN_MODE_START:
> + reg = readl(®s->canctrl);
> + reg &= ~CANCTRL_BOFFREC;
> + writel(reg, ®s->canctrl);
> + reg |= CANCTRL_BOFFREC;
> + writel(reg, ®s->canctrl);
> + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> +
> + if (netif_queue_stopped(ndev))
> + netif_wake_queue(ndev);
> + break;
> +
> + default:
> + return -EOPNOTSUPP;
> + }
> +
> + return 0;
> +}
> +
> +static const struct net_device_ops flexcan_netdev_ops = {
> + .ndo_open = flexcan_open,
> + .ndo_stop = flexcan_close,
> + .ndo_start_xmit = flexcan_start_xmit,
> +};
> +
> +static int register_flexcandev(struct net_device *ndev)
> +{
> + struct flexcan_priv *priv = netdev_priv(ndev);
> + struct flexcan_regs __iomem *regs = priv->base;
> + u32 reg;
> +
> + reg = readl(®s->canmcr);
> + reg &= ~CANMCR_MDIS;
> + writel(reg, ®s->canmcr);
> + udelay(100);
> + reg |= CANMCR_FRZ | CANMCR_HALT | CANMCR_FEN;
> + writel(reg, ®s->canmcr);
> +
> + reg = readl(®s->canmcr);
> +
> + /* Currently we only support newer versions of this core featuring
> + * a RX FIFO. Older cores found on some Coldfire derivates are not
> + * yet supported.
> + */
> + if (!(reg & CANMCR_FEN)) {
> + dev_err(&ndev->dev, "Could not enable RX FIFO, unsupported core");
Line too long!
> + return -ENODEV;
> + }
> +
> + ndev->flags |= IFF_ECHO; /* we support local echo in hardware */
> + ndev->netdev_ops = &flexcan_netdev_ops;
> +
> + return register_candev(ndev);
> +}
> +
> +static void unregister_flexcandev(struct net_device *ndev)
> +{
> + struct flexcan_priv *priv = netdev_priv(ndev);
> + struct flexcan_regs __iomem *regs = priv->base;
> + u32 reg;
> +
> + reg = readl(®s->canmcr);
> + reg |= CANMCR_FRZ | CANMCR_HALT | CANMCR_MDIS;
> + writel(reg, ®s->canmcr);
> +
> + unregister_candev(ndev);
> +}
> +
> +static int __devinit flexcan_probe(struct platform_device *pdev)
> +{
> + struct resource *mem;
> + struct net_device *ndev;
> + struct flexcan_priv *priv;
> + u32 mem_size;
> + int ret;
> +
> + ndev = alloc_candev(sizeof(struct flexcan_priv));
> + if (!ndev)
> + return -ENOMEM;
> +
> + priv = netdev_priv(ndev);
> +
> + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> + ndev->irq = platform_get_irq(pdev, 0);
> + if (!mem || !ndev->irq) {
> + ret = -ENODEV;
> + goto failed_req;
> + }
> +
> + mem_size = resource_size(mem);
> +
> + if (!request_mem_region(mem->start, mem_size, DRIVER_NAME)) {
> + ret = -EBUSY;
> + goto failed_req;
> + }
> +
> + SET_NETDEV_DEV(ndev, &pdev->dev);
> +
> + priv->base = ioremap(mem->start, mem_size);
> + if (!priv->base) {
> + ret = -ENOMEM;
> + goto failed_map;
> + }
> +
> + priv->clk = clk_get(&pdev->dev, NULL);
> + if (IS_ERR(priv->clk)) {
> + ret = PTR_ERR(priv->clk);
> + goto failed_clock;
> + }
> + priv->can.clock.freq = clk_get_rate(priv->clk);
> +
> + platform_set_drvdata(pdev, ndev);
> +
> + priv->can.do_set_bittiming = flexcan_set_bittiming;
> + priv->can.bittiming_const = &flexcan_bittiming_const;
> + priv->can.do_set_mode = flexcan_set_mode;
> +
> + ret = register_flexcandev(ndev);
> + if (ret)
> + goto failed_register;
> +
> + return 0;
> +
> +failed_register:
> + clk_put(priv->clk);
> +failed_clock:
> + iounmap(priv->base);
> +failed_map:
> + release_mem_region(mem->start, mem_size);
> +failed_req:
> + free_candev(ndev);
> +
> + return ret;
> +}
> +
> +static int __devexit flexcan_remove(struct platform_device *pdev)
> +{
> + struct net_device *ndev = platform_get_drvdata(pdev);
> + struct flexcan_priv *priv = netdev_priv(ndev);
> + struct resource *mem;
> +
> + unregister_flexcandev(ndev);
> + platform_set_drvdata(pdev, NULL);
> + iounmap(priv->base);
> + clk_put(priv->clk);
> +
> + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + release_mem_region(mem->start, resource_size(mem));
> + free_candev(ndev);
> +
> + return 0;
> +}
> +
> +static struct platform_driver flexcan_driver = {
> + .driver = {
> + .name = DRIVER_NAME,
> + },
> + .probe = flexcan_probe,
> + .remove = __devexit_p(flexcan_remove),
> +};
> +
> +static int __init flexcan_init(void)
> +{
> + return platform_driver_register(&flexcan_driver);
> +}
> +
> +static void __exit flexcan_exit(void)
> +{
> + platform_driver_unregister(&flexcan_driver);
> +}
> +
> +module_init(flexcan_init);
> +module_exit(flexcan_exit);
> +
> +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("CAN port driver for flexcan based chip");
Apart from that, it already looks quite good.
Thanks for your contribution.
Wolfgang.
^ permalink raw reply
* Re: [PATCH] net/bridge: use kobject_put to release kobject in br_add_if error path
From: Stephen Hemminger @ 2009-07-24 15:36 UTC (permalink / raw)
To: Xiaotian Feng; +Cc: davem, bridge, netdev, linux-kernel, Xiaotian Feng
In-Reply-To: <1248426392-30777-1-git-send-email-dfeng@redhat.com>
On Fri, 24 Jul 2009 17:06:32 +0800
Xiaotian Feng <dfeng@redhat.com> wrote:
> kobject_init_and_add will alloc memory for kobj->name, so in br_add_if
> error path, simply use kobject_del will not free memory for kobj->name.
> Fix by using kobject_put instead, kobject_put will internally calls
> kobject_del and frees memory for kobj->name.
>
> Signed-off-by: Xiaotian Feng <dfeng@redhat.com>
> ---
> net/bridge/br_if.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
> index 8a96672..eb404dc 100644
> --- a/net/bridge/br_if.c
> +++ b/net/bridge/br_if.c
> @@ -424,7 +424,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
> err2:
> br_fdb_delete_by_port(br, p, 1);
> err1:
> - kobject_del(&p->kobj);
> + kobject_put(&p->kobj);
> err0:
> dev_set_promiscuity(dev, -1);
> put_back:
I assume you tested this by doing something like adding two interfaces
with the same MAC address to a bridge.
Acked-by: Stephen Hemminger <shemminger@vyatta.com>
--
^ permalink raw reply
* Jumbo frame question...
From: Robin Getz @ 2009-07-24 15:41 UTC (permalink / raw)
To: netdev
Should a gigabit card, configured as 100, be sending jumbo UDP frames?
My understanding, is no - this is a spec violation..
Settings for eth0:
Supported ports: [ MII ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Half 1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Half 1000baseT/Full
Advertised auto-negotiation: Yes
Speed: 100Mb/s
Duplex: Half
Port: Twisted Pair
PHYAD: 1
Transceiver: internal
Auto-negotiation: on
Supports Wake-on: g
Wake-on: d
Current message level: 0x000000ff (255)
Link detected: no
happly sends UDP packets over 1500 bytes in length.
Tested with TFTP, and 2.6.27 (as the tftp server).
If tftp requests block sizes that are 4096 bytes, the sent packet is a single
4096 byte packet (not multiple MTU sized packets).
?
Thanks
-Robin
^ permalink raw reply
* [PATCH 12/13] ISDN: ARRAY_SIZE changes
From: Karsten Keil @ 2009-07-24 16:26 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, David Miller,
i4ldeveloper-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp
In-Reply-To: <cover.1248546896.git.keil-shG/GajIFYqbacvFa/9K2g@public.gmane.org>
These changes were a direct result of using a semantic patch
More information can be found at http://www.emn.fr/x-info/coccinelle/
Modified some of the changes to avoid the extra define.
Signed-off-by: Stoyan Gaydarov <sgayda2-e94Sedi4moU@public.gmane.org>
Signed-off-by: Karsten Keil <keil-shG/GajIFYqbacvFa/9K2g@public.gmane.org>
---
drivers/isdn/act2000/capi.c | 3 +--
drivers/isdn/act2000/module.c | 31 +++++++++++++++----------------
drivers/isdn/hardware/eicon/message.c | 4 +---
drivers/isdn/hardware/eicon/os_4bri.c | 3 +--
drivers/isdn/hisax/callc.c | 4 +---
drivers/isdn/hisax/isdnl1.c | 12 +++---------
drivers/isdn/hisax/isdnl2.c | 4 +---
drivers/isdn/hisax/isdnl3.c | 4 +---
drivers/isdn/hisax/l3_1tr6.c | 20 ++++++--------------
drivers/isdn/hisax/l3dss1.c | 26 ++++++++------------------
drivers/isdn/hisax/l3ni1.c | 26 ++++++++------------------
drivers/isdn/hisax/q931.c | 24 ++++++++++++------------
drivers/isdn/hisax/tei.c | 4 +---
drivers/isdn/mISDN/layer2.c | 2 --
14 files changed, 59 insertions(+), 108 deletions(-)
diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c
index 946c38c..1f0a949 100644
--- a/drivers/isdn/act2000/capi.c
+++ b/drivers/isdn/act2000/capi.c
@@ -78,7 +78,6 @@ static actcapi_msgdsc valid_msg[] = {
#endif
{{ 0x00, 0x00}, NULL},
};
-#define num_valid_msg (sizeof(valid_msg)/sizeof(actcapi_msgdsc))
#define num_valid_imsg 27 /* MANUFACTURER_IND */
/*
@@ -1025,7 +1024,7 @@ actcapi_debug_msg(struct sk_buff *skb, int direction)
#ifdef DEBUG_DUMP_SKB
dump_skb(skb);
#endif
- for (i = 0; i < num_valid_msg; i++)
+ for (i = 0; i < ARRAY_SIZE(valid_msg); i++)
if ((msg->hdr.cmd.cmd == valid_msg[i].cmd.cmd) &&
(msg->hdr.cmd.subcmd == valid_msg[i].cmd.subcmd)) {
descr = valid_msg[i].description;
diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c
index 8325022..f774e12 100644
--- a/drivers/isdn/act2000/module.c
+++ b/drivers/isdn/act2000/module.c
@@ -23,7 +23,6 @@ static unsigned short act2000_isa_ports[] =
0x0200, 0x0240, 0x0280, 0x02c0, 0x0300, 0x0340, 0x0380,
0xcfe0, 0xcfa0, 0xcf60, 0xcf20, 0xcee0, 0xcea0, 0xce60,
};
-#define ISA_NRPORTS (sizeof(act2000_isa_ports)/sizeof(unsigned short))
static act2000_card *cards = (act2000_card *) NULL;
@@ -686,21 +685,21 @@ act2000_addcard(int bus, int port, int irq, char *id)
* This may result in more than one card detected.
*/
switch (bus) {
- case ACT2000_BUS_ISA:
- for (i = 0; i < ISA_NRPORTS; i++)
- if (act2000_isa_detect(act2000_isa_ports[i])) {
- printk(KERN_INFO
- "act2000: Detected ISA card at port 0x%x\n",
- act2000_isa_ports[i]);
- act2000_alloccard(bus, act2000_isa_ports[i], irq, id);
- }
- break;
- case ACT2000_BUS_MCA:
- case ACT2000_BUS_PCMCIA:
- default:
- printk(KERN_WARNING
- "act2000: addcard: Invalid BUS type %d\n",
- bus);
+ case ACT2000_BUS_ISA:
+ for (i = 0; i < ARRAY_SIZE(act2000_isa_ports); i++)
+ if (act2000_isa_detect(act2000_isa_ports[i])) {
+ printk(KERN_INFO "act2000: Detected "
+ "ISA card at port 0x%x\n",
+ act2000_isa_ports[i]);
+ act2000_alloccard(bus,
+ act2000_isa_ports[i], irq, id);
+ }
+ break;
+ case ACT2000_BUS_MCA:
+ case ACT2000_BUS_PCMCIA:
+ default:
+ printk(KERN_WARNING
+ "act2000: addcard: Invalid BUS type %d\n", bus);
}
}
if (!cards)
diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c
index 31f91c1..27d5dd6 100644
--- a/drivers/isdn/hardware/eicon/message.c
+++ b/drivers/isdn/hardware/eicon/message.c
@@ -551,9 +551,7 @@ word api_put(APPL * appl, CAPI_MSG * msg)
dbug(1,dprintf("com=%x",msg->header.command));
for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
- for(i=0, ret = _BAD_MSG;
- i<(sizeof(ftable)/sizeof(struct _ftable));
- i++) {
+ for(i=0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
if(ftable[i].command==msg->header.command) {
/* break loop if the message is correct, otherwise continue scan */
diff --git a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c
index c964b8d..cb7616c 100644
--- a/drivers/isdn/hardware/eicon/os_4bri.c
+++ b/drivers/isdn/hardware/eicon/os_4bri.c
@@ -149,8 +149,7 @@ int diva_4bri_init_card(diva_os_xdi_adapter_t * a)
diva_os_xdi_adapter_t *diva_current;
diva_os_xdi_adapter_t *adapter_list[4];
PISDN_ADAPTER Slave;
- unsigned long bar_length[sizeof(_4bri_bar_length) /
- sizeof(_4bri_bar_length[0])];
+ unsigned long bar_length[ARRAY_SIZE(_4bri_bar_length)];
int v2 = _4bri_is_rev_2_card(a->CardOrdinal);
int tasks = _4bri_is_rev_2_bri_card(a->CardOrdinal) ? 1 : MQ_INSTANCE_COUNT;
int factor = (tasks == 1) ? 1 : 2;
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index 025a20d..475b1a0 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -833,8 +833,6 @@ static struct FsmNode fnlist[] __initdata =
};
/* *INDENT-ON* */
-#define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode))
-
int __init
CallcNew(void)
{
@@ -842,7 +840,7 @@ CallcNew(void)
callcfsm.event_count = EVENT_COUNT;
callcfsm.strEvent = strEvent;
callcfsm.strState = strState;
- return FsmNew(&callcfsm, fnlist, FNCOUNT);
+ return FsmNew(&callcfsm, fnlist, ARRAY_SIZE(fnlist));
}
void
diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
index 317f16f..9ce6abe 100644
--- a/drivers/isdn/hisax/isdnl1.c
+++ b/drivers/isdn/hisax/isdnl1.c
@@ -647,8 +647,6 @@ static struct FsmNode L1SFnList[] __initdata =
{ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact},
};
-#define L1S_FN_COUNT (sizeof(L1SFnList)/sizeof(struct FsmNode))
-
#ifdef HISAX_UINTERFACE
static void
l1_deact_req_u(struct FsmInst *fi, int event, void *arg)
@@ -706,8 +704,6 @@ static struct FsmNode L1UFnList[] __initdata =
{ST_L1_RESET, EV_TIMER_DEACT, l1_timer_deact},
};
-#define L1U_FN_COUNT (sizeof(L1UFnList)/sizeof(struct FsmNode))
-
#endif
static void
@@ -754,8 +750,6 @@ static struct FsmNode L1BFnList[] __initdata =
{ST_L1_WAIT_DEACT, EV_TIMER_DEACT, l1b_timer_deact},
};
-#define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode))
-
int __init
Isdnl1New(void)
{
@@ -765,7 +759,7 @@ Isdnl1New(void)
l1fsm_s.event_count = L1_EVENT_COUNT;
l1fsm_s.strEvent = strL1Event;
l1fsm_s.strState = strL1SState;
- retval = FsmNew(&l1fsm_s, L1SFnList, L1S_FN_COUNT);
+ retval = FsmNew(&l1fsm_s, L1SFnList, ARRAY_SIZE(L1SFnList));
if (retval)
return retval;
@@ -773,7 +767,7 @@ Isdnl1New(void)
l1fsm_b.event_count = L1_EVENT_COUNT;
l1fsm_b.strEvent = strL1Event;
l1fsm_b.strState = strL1BState;
- retval = FsmNew(&l1fsm_b, L1BFnList, L1B_FN_COUNT);
+ retval = FsmNew(&l1fsm_b, L1BFnList, ARRAY_SIZE(L1BFnList));
if (retval) {
FsmFree(&l1fsm_s);
return retval;
@@ -783,7 +777,7 @@ Isdnl1New(void)
l1fsm_u.event_count = L1_EVENT_COUNT;
l1fsm_u.strEvent = strL1Event;
l1fsm_u.strState = strL1UState;
- retval = FsmNew(&l1fsm_u, L1UFnList, L1U_FN_COUNT);
+ retval = FsmNew(&l1fsm_u, L1UFnList, ARRAY_SIZE(L1UFnList));
if (retval) {
FsmFree(&l1fsm_s);
FsmFree(&l1fsm_b);
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
index 3446f24..7b9496a 100644
--- a/drivers/isdn/hisax/isdnl2.c
+++ b/drivers/isdn/hisax/isdnl2.c
@@ -1623,8 +1623,6 @@ static struct FsmNode L2FnList[] __initdata =
{ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da},
};
-#define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode))
-
static void
isdnl2_l1l2(struct PStack *st, int pr, void *arg)
{
@@ -1836,7 +1834,7 @@ Isdnl2New(void)
l2fsm.event_count = L2_EVENT_COUNT;
l2fsm.strEvent = strL2Event;
l2fsm.strState = strL2State;
- return FsmNew(&l2fsm, L2FnList, L2_FN_COUNT);
+ return FsmNew(&l2fsm, L2FnList, ARRAY_SIZE(L2FnList));
}
void
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
index 935f233..0676602 100644
--- a/drivers/isdn/hisax/isdnl3.c
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -543,8 +543,6 @@ static struct FsmNode L3FnList[] __initdata =
};
/* *INDENT-ON* */
-#define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode))
-
void
l3_msg(struct PStack *st, int pr, void *arg)
{
@@ -587,7 +585,7 @@ Isdnl3New(void)
l3fsm.event_count = L3_EVENT_COUNT;
l3fsm.strEvent = strL3Event;
l3fsm.strState = strL3State;
- return FsmNew(&l3fsm, L3FnList, L3_FN_COUNT);
+ return FsmNew(&l3fsm, L3FnList, ARRAY_SIZE(L3FnList));
}
void
diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c
index c5c36ee..b0554f8 100644
--- a/drivers/isdn/hisax/l3_1tr6.c
+++ b/drivers/isdn/hisax/l3_1tr6.c
@@ -698,9 +698,6 @@ static struct stateentry downstl[] =
CC_T308_2, l3_1tr6_t308_2},
};
-#define DOWNSTL_LEN \
- (sizeof(downstl) / sizeof(struct stateentry))
-
static struct stateentry datastln1[] =
{
{SBIT(0),
@@ -735,9 +732,6 @@ static struct stateentry datastln1[] =
MT_N1_REL_ACK, l3_1tr6_rel_ack}
};
-#define DATASTLN1_LEN \
- (sizeof(datastln1) / sizeof(struct stateentry))
-
static struct stateentry manstatelist[] =
{
{SBIT(2),
@@ -746,8 +740,6 @@ static struct stateentry manstatelist[] =
DL_RELEASE | INDICATION, l3_1tr6_dl_release},
};
-#define MANSLLEN \
- (sizeof(manstatelist) / sizeof(struct stateentry))
/* *INDENT-ON* */
static void
@@ -840,11 +832,11 @@ up1tr6(struct PStack *st, int pr, void *arg)
mt = MT_N1_INVALID;
}
}
- for (i = 0; i < DATASTLN1_LEN; i++)
+ for (i = 0; i < ARRAY_SIZE(datastln1); i++)
if ((mt == datastln1[i].primitive) &&
((1 << proc->state) & datastln1[i].state))
break;
- if (i == DATASTLN1_LEN) {
+ if (i == ARRAY_SIZE(datastln1)) {
dev_kfree_skb(skb);
if (st->l3.debug & L3_DEB_STATE) {
sprintf(tmp, "up1tr6%sstate %d mt %x unhandled",
@@ -892,11 +884,11 @@ down1tr6(struct PStack *st, int pr, void *arg)
proc = arg;
}
- for (i = 0; i < DOWNSTL_LEN; i++)
+ for (i = 0; i < ARRAY_SIZE(downstl); i++)
if ((pr == downstl[i].primitive) &&
((1 << proc->state) & downstl[i].state))
break;
- if (i == DOWNSTL_LEN) {
+ if (i == ARRAY_SIZE(downstl)) {
if (st->l3.debug & L3_DEB_STATE) {
sprintf(tmp, "down1tr6 state %d prim %d unhandled",
proc->state, pr);
@@ -922,11 +914,11 @@ man1tr6(struct PStack *st, int pr, void *arg)
printk(KERN_ERR "HiSax man1tr6 without proc pr=%04x\n", pr);
return;
}
- for (i = 0; i < MANSLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(manstatelist); i++)
if ((pr == manstatelist[i].primitive) &&
((1 << proc->state) & manstatelist[i].state))
break;
- if (i == MANSLLEN) {
+ if (i == ARRAY_SIZE(manstatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "cr %d man1tr6 state %d prim %d unhandled",
proc->callref & 0x7f, proc->state, pr);
diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c
index 99feae8..a12fa4d 100644
--- a/drivers/isdn/hisax/l3dss1.c
+++ b/drivers/isdn/hisax/l3dss1.c
@@ -2820,9 +2820,6 @@ static struct stateentry downstatelist[] =
CC_T309, l3dss1_dl_release},
};
-#define DOWNSLLEN \
- (sizeof(downstatelist) / sizeof(struct stateentry))
-
static struct stateentry datastatelist[] =
{
{ALL_STATES,
@@ -2875,9 +2872,6 @@ static struct stateentry datastatelist[] =
MT_RESUME_REJECT, l3dss1_resume_rej},
};
-#define DATASLLEN \
- (sizeof(datastatelist) / sizeof(struct stateentry))
-
static struct stateentry globalmes_list[] =
{
{ALL_STATES,
@@ -2888,8 +2882,6 @@ static struct stateentry globalmes_list[] =
MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},
*/
};
-#define GLOBALM_LEN \
- (sizeof(globalmes_list) / sizeof(struct stateentry))
static struct stateentry manstatelist[] =
{
@@ -2903,8 +2895,6 @@ static struct stateentry manstatelist[] =
DL_RELEASE | INDICATION, l3dss1_dl_release},
};
-#define MANSLLEN \
- (sizeof(manstatelist) / sizeof(struct stateentry))
/* *INDENT-ON* */
@@ -2918,11 +2908,11 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb)
struct l3_process *proc = st->l3.global;
proc->callref = skb->data[2]; /* cr flag */
- for (i = 0; i < GLOBALM_LEN; i++)
+ for (i = 0; i < ARRAY_SIZE(globalmes_list); i++)
if ((mt == globalmes_list[i].primitive) &&
((1 << proc->state) & globalmes_list[i].state))
break;
- if (i == GLOBALM_LEN) {
+ if (i == ARRAY_SIZE(globalmes_list)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "dss1 global state %d mt %x unhandled",
proc->state, mt);
@@ -3097,11 +3087,11 @@ dss1up(struct PStack *st, int pr, void *arg)
}
if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL)
l3dss1_deliver_display(proc, pr, p); /* Display IE included */
- for (i = 0; i < DATASLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(datastatelist); i++)
if ((mt == datastatelist[i].primitive) &&
((1 << proc->state) & datastatelist[i].state))
break;
- if (i == DATASLLEN) {
+ if (i == ARRAY_SIZE(datastatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "dss1up%sstate %d mt %#x unhandled",
(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
@@ -3156,11 +3146,11 @@ dss1down(struct PStack *st, int pr, void *arg)
return;
}
- for (i = 0; i < DOWNSLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(downstatelist); i++)
if ((pr == downstatelist[i].primitive) &&
((1 << proc->state) & downstatelist[i].state))
break;
- if (i == DOWNSLLEN) {
+ if (i == ARRAY_SIZE(downstatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "dss1down state %d prim %#x unhandled",
proc->state, pr);
@@ -3184,11 +3174,11 @@ dss1man(struct PStack *st, int pr, void *arg)
printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr);
return;
}
- for (i = 0; i < MANSLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(manstatelist); i++)
if ((pr == manstatelist[i].primitive) &&
((1 << proc->state) & manstatelist[i].state))
break;
- if (i == MANSLLEN) {
+ if (i == ARRAY_SIZE(manstatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "cr %d dss1man state %d prim %#x unhandled",
proc->callref & 0x7f, proc->state, pr);
diff --git a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c
index f7041d5..4622d43 100644
--- a/drivers/isdn/hisax/l3ni1.c
+++ b/drivers/isdn/hisax/l3ni1.c
@@ -2755,9 +2755,6 @@ static struct stateentry downstatelist[] =
CC_TSPID, l3ni1_spid_tout },
};
-#define DOWNSLLEN \
- (sizeof(downstatelist) / sizeof(struct stateentry))
-
static struct stateentry datastatelist[] =
{
{ALL_STATES,
@@ -2810,9 +2807,6 @@ static struct stateentry datastatelist[] =
MT_RESUME_REJECT, l3ni1_resume_rej},
};
-#define DATASLLEN \
- (sizeof(datastatelist) / sizeof(struct stateentry))
-
static struct stateentry globalmes_list[] =
{
{ALL_STATES,
@@ -2825,8 +2819,6 @@ static struct stateentry globalmes_list[] =
{ SBIT( 0 ), MT_DL_ESTABLISHED, l3ni1_spid_send },
{ SBIT( 20 ) | SBIT( 21 ) | SBIT( 22 ), MT_INFORMATION, l3ni1_spid_epid },
};
-#define GLOBALM_LEN \
- (sizeof(globalmes_list) / sizeof(struct stateentry))
static struct stateentry manstatelist[] =
{
@@ -2840,8 +2832,6 @@ static struct stateentry manstatelist[] =
DL_RELEASE | INDICATION, l3ni1_dl_release},
};
-#define MANSLLEN \
- (sizeof(manstatelist) / sizeof(struct stateentry))
/* *INDENT-ON* */
@@ -2858,11 +2848,11 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb)
proc->callref = skb->data[2]; /* cr flag */
else
proc->callref = 0;
- for (i = 0; i < GLOBALM_LEN; i++)
+ for (i = 0; i < ARRAY_SIZE(globalmes_list); i++)
if ((mt == globalmes_list[i].primitive) &&
((1 << proc->state) & globalmes_list[i].state))
break;
- if (i == GLOBALM_LEN) {
+ if (i == ARRAY_SIZE(globalmes_list)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "ni1 global state %d mt %x unhandled",
proc->state, mt);
@@ -3049,11 +3039,11 @@ ni1up(struct PStack *st, int pr, void *arg)
}
if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL)
l3ni1_deliver_display(proc, pr, p); /* Display IE included */
- for (i = 0; i < DATASLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(datastatelist); i++)
if ((mt == datastatelist[i].primitive) &&
((1 << proc->state) & datastatelist[i].state))
break;
- if (i == DATASLLEN) {
+ if (i == ARRAY_SIZE(datastatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "ni1up%sstate %d mt %#x unhandled",
(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
@@ -3108,11 +3098,11 @@ ni1down(struct PStack *st, int pr, void *arg)
return;
}
- for (i = 0; i < DOWNSLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(downstatelist); i++)
if ((pr == downstatelist[i].primitive) &&
((1 << proc->state) & downstatelist[i].state))
break;
- if (i == DOWNSLLEN) {
+ if (i == ARRAY_SIZE(downstatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "ni1down state %d prim %#x unhandled",
proc->state, pr);
@@ -3136,11 +3126,11 @@ ni1man(struct PStack *st, int pr, void *arg)
printk(KERN_ERR "HiSax ni1man without proc pr=%04x\n", pr);
return;
}
- for (i = 0; i < MANSLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(manstatelist); i++)
if ((pr == manstatelist[i].primitive) &&
((1 << proc->state) & manstatelist[i].state))
break;
- if (i == MANSLLEN) {
+ if (i == ARRAY_SIZE(manstatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "cr %d ni1man state %d prim %#x unhandled",
proc->callref & 0x7f, proc->state, pr);
diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c
index aacbf0d..8b853d5 100644
--- a/drivers/isdn/hisax/q931.c
+++ b/drivers/isdn/hisax/q931.c
@@ -140,7 +140,7 @@ struct MessageType {
}
};
-#define MTSIZE sizeof(mtlist)/sizeof(struct MessageType)
+#define MTSIZE ARRAY_SIZE(mtlist)
static
struct MessageType mt_n0[] =
@@ -157,7 +157,7 @@ struct MessageType mt_n0[] =
{MT_N0_CLO_ACK, "CLOse ACKnowledge"}
};
-#define MT_N0_LEN (sizeof(mt_n0) / sizeof(struct MessageType))
+#define MT_N0_LEN ARRAY_SIZE(mt_n0)
static
struct MessageType mt_n1[] =
@@ -194,7 +194,7 @@ struct MessageType mt_n1[] =
{MT_N1_STAT, "STATus"}
};
-#define MT_N1_LEN (sizeof(mt_n1) / sizeof(struct MessageType))
+#define MT_N1_LEN ARRAY_SIZE(mt_n1)
static int
@@ -438,7 +438,7 @@ struct CauseValue {
},
};
-#define CVSIZE sizeof(cvlist)/sizeof(struct CauseValue)
+#define CVSIZE ARRAY_SIZE(cvlist)
static
int
@@ -516,7 +516,7 @@ struct MessageType cause_1tr6[] =
{CAUSE_UserInfoDiscarded, "User Info Discarded"}
};
-static int cause_1tr6_len = (sizeof(cause_1tr6) / sizeof(struct MessageType));
+static int cause_1tr6_len = ARRAY_SIZE(cause_1tr6);
static int
prcause_1tr6(char *dest, u_char * p)
@@ -865,7 +865,7 @@ struct DTag { /* Display tags */
{ 0x96, "Redirection name" },
{ 0x9e, "Text" },
};
-#define DTAGSIZE sizeof(dtaglist)/sizeof(struct DTag)
+#define DTAGSIZE ARRAY_SIZE(dtaglist)
static int
disptext_ni1(char *dest, u_char * p)
@@ -1074,7 +1074,7 @@ struct InformationElement {
};
-#define IESIZE sizeof(ielist)/sizeof(struct InformationElement)
+#define IESIZE ARRAY_SIZE(ielist)
static
struct InformationElement ielist_ni1[] = {
@@ -1102,7 +1102,7 @@ struct InformationElement ielist_ni1[] = {
};
-#define IESIZE_NI1 sizeof(ielist_ni1)/sizeof(struct InformationElement)
+#define IESIZE_NI1 ARRAY_SIZE(ielist_ni1)
static
struct InformationElement ielist_ni1_cs5[] = {
@@ -1110,14 +1110,14 @@ struct InformationElement ielist_ni1_cs5[] = {
{ 0x2a, "Display text", disptext_ni1 },
};
-#define IESIZE_NI1_CS5 sizeof(ielist_ni1_cs5)/sizeof(struct InformationElement)
+#define IESIZE_NI1_CS5 ARRAY_SIZE(ielist_ni1_cs5)
static
struct InformationElement ielist_ni1_cs6[] = {
{ 0x7b, "Call appearance", general_ni1 },
};
-#define IESIZE_NI1_CS6 sizeof(ielist_ni1_cs6)/sizeof(struct InformationElement)
+#define IESIZE_NI1_CS6 ARRAY_SIZE(ielist_ni1_cs6)
static struct InformationElement we_0[] =
{
@@ -1133,7 +1133,7 @@ static struct InformationElement we_0[] =
{WE0_userInfo, "User Info", general}
};
-#define WE_0_LEN (sizeof(we_0) / sizeof(struct InformationElement))
+#define WE_0_LEN ARRAY_SIZE(we_0)
static struct InformationElement we_6[] =
{
@@ -1145,7 +1145,7 @@ static struct InformationElement we_6[] =
{WE6_statusCalled, "Status Called", general},
{WE6_addTransAttr, "Additional Transmission Attributes", general}
};
-#define WE_6_LEN (sizeof(we_6) / sizeof(struct InformationElement))
+#define WE_6_LEN ARRAY_SIZE(we_6)
int
QuickHex(char *txt, u_char * p, int cnt)
diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c
index ceb0df9..6e65424 100644
--- a/drivers/isdn/hisax/tei.c
+++ b/drivers/isdn/hisax/tei.c
@@ -447,8 +447,6 @@ static struct FsmNode TeiFnList[] __initdata =
{ST_TEI_IDVERIFY, EV_CHKREQ, tei_id_chk_req},
};
-#define TEI_FN_COUNT (sizeof(TeiFnList)/sizeof(struct FsmNode))
-
int __init
TeiNew(void)
{
@@ -456,7 +454,7 @@ TeiNew(void)
teifsm.event_count = TEI_EVENT_COUNT;
teifsm.strEvent = strTeiEvent;
teifsm.strState = strTeiState;
- return FsmNew(&teifsm, TeiFnList, TEI_FN_COUNT);
+ return FsmNew(&teifsm, TeiFnList, ARRAY_SIZE(TeiFnList));
}
void
diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c
index 9c2589e..e17f004 100644
--- a/drivers/isdn/mISDN/layer2.c
+++ b/drivers/isdn/mISDN/layer2.c
@@ -1832,8 +1832,6 @@ static struct FsmNode L2FnList[] =
{ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da},
};
-#define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode))
-
static int
ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
{
--
1.6.0.2
^ permalink raw reply related
* Re: Jumbo frame question...
From: David Miller @ 2009-07-24 16:32 UTC (permalink / raw)
To: rgetz; +Cc: netdev
In-Reply-To: <200907241141.55097.rgetz@blackfin.uclinux.org>
From: Robin Getz <rgetz@blackfin.uclinux.org>
Date: Fri, 24 Jul 2009 11:41:55 -0400
> Should a gigabit card, configured as 100, be sending jumbo UDP frames?
>
> My understanding, is no - this is a spec violation..
There is nothing wrong with supporting jumbo frames
when the speed is lower than 1GB.
If you configure the MTU to be jumbo size, it should
be no surprise to you that this is what gets used.
^ permalink raw reply
* Re: Jumbo frame question...
From: Rick Jones @ 2009-07-24 16:39 UTC (permalink / raw)
To: David Miller; +Cc: rgetz, netdev
In-Reply-To: <20090724.093243.201296391.davem@davemloft.net>
David Miller wrote:
> From: Robin Getz <rgetz@blackfin.uclinux.org>
> Date: Fri, 24 Jul 2009 11:41:55 -0400
>
>>Should a gigabit card, configured as 100, be sending jumbo UDP frames?
>>
>>My understanding, is no - this is a spec violation..
In so far as there is no de jure spec for Jumbo Frames, it is rather difficult
to have a spec violation :).
> There is nothing wrong with supporting jumbo frames
> when the speed is lower than 1GB.
>
> If you configure the MTU to be jumbo size, it should
> be no surprise to you that this is what gets used.
Not a case of too much rope? Given that (IIRC) Jumbo Frame was not introduced
in Ethernet NICs until Gigabit came along (eg Alteon), the chances a (legacy)
100 Mbit/s network would have JF-capable NICs is epsilon.
rick jones
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 13/13] mISDN: hfcmulti display real PCI ids for not supported cards
From: Karsten Keil @ 2009-07-24 16:41 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, David Miller,
i4ldeveloper-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp
In-Reply-To: <cover.1248546896.git.keil-shG/GajIFYqbacvFa/9K2g@public.gmane.org>
In the PCI probe function struct pci_device_id points to the matched
entry of the ID table, but for devices which are matched with
PCI_ANY_ID sub IDs we want display the IDs of the device itself.
Signed-off-by: Karsten Keil <keil-shG/GajIFYqbacvFa/9K2g@public.gmane.org>
---
drivers/isdn/hardware/mISDN/hfcmulti.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index fd77bb1..faed794 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -5370,9 +5370,10 @@ hfcmulti_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ent->device == PCI_DEVICE_ID_CCD_HFC8S ||
ent->device == PCI_DEVICE_ID_CCD_HFCE1)) {
printk(KERN_ERR
- "Unknown HFC multiport controller (vendor:%x device:%x "
- "subvendor:%x subdevice:%x)\n", ent->vendor, ent->device,
- ent->subvendor, ent->subdevice);
+ "Unknown HFC multiport controller (vendor:%04x device:%04x "
+ "subvendor:%04x subdevice:%04x)\n", pdev->vendor,
+ pdev->device, pdev->subsystem_vendor,
+ pdev->subsystem_device);
printk(KERN_ERR
"Please contact the driver maintainer for support.\n");
return -ENODEV;
--
1.6.0.2
^ permalink raw reply related
* Re: accelerated vlan gives pcap tagged packets untagged
From: Malcolm Scott @ 2009-07-24 16:50 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Pierre Ossman, Francois Romieu, netdev
In-Reply-To: <4A689159.2010807@trash.net>
At 18:35 yesterday, Patrick McHardy wrote:
> Malcolm Scott wrote:
>
>> So to clarify: as of 2.6.28, an app (e.g. dhcpd) listening on eth0 will
>> by default see packets from all VLANs with tags removed; if it wishes to
>> do otherwise, it should query the kernel for the VLAN tag of every
>> packet and discard those with a tag?
>
> No, exactly the opposite. Starting with 2.6.28 and a recent libpcap,
> VLAN tags are present in userspace independant of whether the driver
> uses VLAN acceleration or not.
Sorry, I meant that the 802.1q header is removed from the packet, not
discarded entirely.
>> In my case, this is manifesting as the DHCP misbehaviour which Pierre
>> mentioned. (ISC dhcp3d does not use libpcap, and does not query the
>> packet socket for the VLAN tag, so it treats every VLAN's packets as for
>> the default VLAN.)
>
> It needs to get the VLAN tag from the auxilliary data.
Right. But backwards compatibility with older apps is the issue. An app
which doesn't go looking for a VLAN tag in the auxiliary data -- because it
didn't have to do so prior to 2.6.28 -- will start seeing packets from all
VLANs rather than just the untagged ones.
Perhaps what's actually needed is another interface which sees _just_ the
untagged packets, e.g. eth0.0 (0 being a reserved VLAN ID meaning 'no VLAN',
i.e. equivalent to no 802.1q tag).
Malcolm
--
Malcolm Scott
University of Cambridge Computer Laboratory
^ permalink raw reply
* Re: [PATCH] USB host CDC Phonet network interface driver
From: Marcel Holtmann @ 2009-07-24 18:00 UTC (permalink / raw)
To: Oliver Neukum
Cc: Alan Cox, Rémi Denis-Courmont, ext Dan Williams,
netdev@vger.kernel.org, linux-usb@vger.kernel.org
In-Reply-To: <200907241612.41871.oliver@neukum.org>
Hi Oliver,
> > > No, I was thinking of having two full devices, a data channel and a
> > > control channel for devices that really talk AT commands natively.
> >
> > If the hardware does it great, however for things like a 3G modem you
> > have the problem that the PPP is over the AT command channel which may
> > itself be multiplexed. And the muxing in question is *ugly* - sort of
> > HDLC and LAP-B done wrong.
>
> Well, yes, but we would really like a separate control channel, so we
> can query parameters like signal strength, while we do PPP over the data
> channel.
we don't want PPP at all. It is just plain stupid and a total braindead
idea. Non of the GSM/UMTS networks talk PPP over the air interface or
actually anywhere in their stack. The PPP is just between the host OS
and the card. It is a pointless encapsulation of IP packets that comes
from the POTS stuff where PPP over a telephone line made sense.
And on top of that we have these magic *99# phone numbers to establish a
PDP context, because the OS still sees them as POTS modem. All stupid
and braindead. I am so happy that Ericsson and Option moved to proper
high speed network devices and that Nokia Phonet had this all along.
So besides the GPRS data access, the other problem with AT command
control channels is that they are by no means async. Every single
command is essentially blocking and so you need the TTY mux anyway so
you can do scanning, text messaging and network monitoring at the same
time without having your application look like a total dork.
Regards
Marcel
^ permalink raw reply
* Re: Jumbo frame question...
From: Robin Getz @ 2009-07-24 18:21 UTC (permalink / raw)
To: Rick Jones; +Cc: David Miller, netdev
In-Reply-To: <4A69E3CF.1040805@hp.com>
On Fri 24 Jul 2009 12:39, Rick Jones pondered:
> David Miller wrote:
> > From: Robin Getz <rgetz@blackfin.uclinux.org>
> > Date: Fri, 24 Jul 2009 11:41:55 -0400
> >
> >>Should a gigabit card, configured as 100, be sending jumbo UDP frames?
> >>
> >>My understanding, is no - this is a spec violation..
>
> In so far as there is no de jure spec for Jumbo Frames, it is rather
> difficult to have a spec violation :).
The spec I was talking about was the MTU...
rgetz@pinky:~> /sbin/ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:11:11:B0:A5:D4
inet addr:192.168.0.10 Bcast:192.168.0.255 Mask:255.255.255.0
inet6 addr: fe80::211:11ff:feb0:a5d4/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:45978 errors:5 dropped:0 overruns:0 frame:0
TX packets:44536 errors:0 dropped:0 overruns:0 carrier:0
collisions:3193 txqueuelen:1000
RX bytes:11583575 (11.0 Mb) TX bytes:20025122 (19.0 Mb)
Interrupt:16
My MTU is 1500, but when tftp requests a block size of over that - the host
does not fragment it (like I thought it should).
> > There is nothing wrong with supporting jumbo frames
> > when the speed is lower than 1GB.
I would agree - if you had the MTU set up that big.
> > If you configure the MTU to be jumbo size, it should
> > be no surprise to you that this is what gets used.
Which it is not.
> Not a case of too much rope? Given that (IIRC) Jumbo Frame was not
> introduced in Ethernet NICs until Gigabit came along (eg Alteon), the
> chances a (legacy) 100 Mbit/s network would have JF-capable NICs is epsilon.
Yeah - I think that this is the issue - my old hub (which is what I normally
use for ethernet testing is only transferring it's MTU (1500 bytes), and
dropping the rest...
Isn't there a MTU max size discovery that should be done somewhere before the
host sends jumbo packets?
http://tools.ietf.org/html/rfc1191
And -- in the UDP/TFTP case - isn't the server responsible for determining
this? (since it need to determine if fragmentation needs to happen or not?)
-Robin
^ permalink raw reply
* Re: [PATCH] USB host CDC Phonet network interface driver
From: Oliver Neukum @ 2009-07-24 16:59 UTC (permalink / raw)
To: Alan Cox
Cc: Rémi Denis-Courmont, Marcel Holtmann, ext Dan Williams,
netdev@vger.kernel.org, linux-usb@vger.kernel.org
In-Reply-To: <20090724151941.40dba19d@lxorguk.ukuu.org.uk>
Am Freitag, 24. Juli 2009 16:19:41 schrieb Alan Cox:
> On Fri, 24 Jul 2009 16:12:41 +0200
>
> Oliver Neukum <oliver@neukum.org> wrote:
> > Am Freitag, 24. Juli 2009 14:48:05 schrieb Alan Cox:
> > > > No, I was thinking of having two full devices, a data channel and a
> > > > control channel for devices that really talk AT commands natively.
> > >
> > > If the hardware does it great, however for things like a 3G modem you
> > > have the problem that the PPP is over the AT command channel which may
> > > itself be multiplexed. And the muxing in question is *ugly* - sort of
> > > HDLC and LAP-B done wrong.
> >
> > Well, yes, but we would really like a separate control channel, so we
> > can query parameters like signal strength, while we do PPP over the data
> > channel.
>
> Thats the notion of the AT mux stuff - you get multiple AT channels and
> you can stuff PPP down one of them. It's still butt ugly.
That is a problem. But is it so ugly that we'd forgo the added functionality
rather than implement it in the kernel?
If not, I maintain that we should not maintain several different control channel
interfaces, like some devices use cdc-wdm, others a ttyUSB and the AT mux
stuff shall use yet a different method.
Regards
Oliver
^ permalink raw reply
* Re: Jumbo frame question...
From: Rick Jones @ 2009-07-24 18:44 UTC (permalink / raw)
To: Robin Getz; +Cc: David Miller, netdev
In-Reply-To: <200907241421.55986.rgetz@blackfin.uclinux.org>
Robin Getz wrote:
> On Fri 24 Jul 2009 12:39, Rick Jones pondered:
>
>>David Miller wrote:
>>
>>>From: Robin Getz <rgetz@blackfin.uclinux.org>
>>>Date: Fri, 24 Jul 2009 11:41:55 -0400
>>>
>>>
>>>>Should a gigabit card, configured as 100, be sending jumbo UDP frames?
>>>>
>>>>My understanding, is no - this is a spec violation..
>>
>>In so far as there is no de jure spec for Jumbo Frames, it is rather
>>difficult to have a spec violation :).
>
>
> The spec I was talking about was the MTU...
>
> rgetz@pinky:~> /sbin/ifconfig eth0
> eth0 Link encap:Ethernet HWaddr 00:11:11:B0:A5:D4
> inet addr:192.168.0.10 Bcast:192.168.0.255 Mask:255.255.255.0
> inet6 addr: fe80::211:11ff:feb0:a5d4/64 Scope:Link
> UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
> RX packets:45978 errors:5 dropped:0 overruns:0 frame:0
> TX packets:44536 errors:0 dropped:0 overruns:0 carrier:0
> collisions:3193 txqueuelen:1000
> RX bytes:11583575 (11.0 Mb) TX bytes:20025122 (19.0 Mb)
> Interrupt:16
>
>
> My MTU is 1500, but when tftp requests a block size of over that - the host
> does not fragment it (like I thought it should).
Well, you should have said that to begin with!-) Saying "Jumbo Frames" makes
people think you have enabled JumboFrames - ie increased the MTU to something
like 9000 bytes.
>>Not a case of too much rope? Given that (IIRC) Jumbo Frame was not
>>introduced in Ethernet NICs until Gigabit came along (eg Alteon), the
>>chances a (legacy) 100 Mbit/s network would have JF-capable NICs is epsilon.
>
>
> Yeah - I think that this is the issue - my old hub (which is what I normally
> use for ethernet testing is only transferring it's MTU (1500 bytes), and
> dropping the rest...
>
> Isn't there a MTU max size discovery that should be done somewhere before the
> host sends jumbo packets?
>
> http://tools.ietf.org/html/rfc1191
>
> And -- in the UDP/TFTP case - isn't the server responsible for determining
> this? (since it need to determine if fragmentation needs to happen or not?)
PathMTU discovery is based on the receipt of ICMP messages saying in essence
"this datagram was too big to forwared without fragmenting and the don't
fragment bit was set, please send nothing larger than <foo> this way"
That only happens when crossing routers, so if this TFTP transfer is over the
local LAN, there is no router to say so, leaving the choice of fragment size to
the sending system.
Does this NIC offer UDP Fragmentation Offload but perhaps only in GbE mode, but
the driver doesn't clear that bit when the speed is 100 Mbit, or perhaps
something up the stack cached knowledge that changed on it?
rick jones
^ permalink raw reply
* Re: Jumbo frame question...
From: Lennart Sorensen @ 2009-07-24 18:45 UTC (permalink / raw)
To: Rick Jones; +Cc: David Miller, rgetz, netdev
In-Reply-To: <4A69E3CF.1040805@hp.com>
On Fri, Jul 24, 2009 at 09:39:43AM -0700, Rick Jones wrote:
> In so far as there is no de jure spec for Jumbo Frames, it is rather
> difficult to have a spec violation :).
>
> Not a case of too much rope? Given that (IIRC) Jumbo Frame was not
> introduced in Ethernet NICs until Gigabit came along (eg Alteon), the
> chances a (legacy) 100 Mbit/s network would have JF-capable NICs is
> epsilon.
Nothing would prevent you from using a 100Mbit fiber PHY on a gigabit
capable network port, so you could have a 100Mbit port that supported
jumbo frames.
--
Len Sorensen
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox