* Re: [PATCH] atm/br2684: netif_stop_queue() when atm device busy and netif_wake_queue() when we can send packets again.
From: David Miller @ 2009-09-03 6:27 UTC (permalink / raw)
To: chas; +Cc: netdev, karl
In-Reply-To: <200908311429.n7VETlTi000764@cmf.nrl.navy.mil>
From: "Chas Williams (CONTRACTOR)" <chas@cmf.nrl.navy.mil>
Date: Mon, 31 Aug 2009 10:29:47 -0400
> This patch removes the call to dev_kfree_skb() when the atm device is busy.
> Calling dev_kfree_skb() causes heavy packet loss then the device is under
> heavy load, the more correct behavior should be to stop the upper layers,
> then when the lower device can queue packets again wake the upper layers.
>
> Signed-off-by: Karl Hiramoto <karl@hiramoto.org>
> Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
Applied to net-next-2.6, but Chas your email client corrupted
the patch by breaking up long lines:
> @@ -142,6 +142,22 @@ static struct net_device *br2684_find_dev(const struct br
> 2684_if_spec *s)
Like that.
^ permalink raw reply
* Re: [PATCH] atm: dereference of he_dev->rbps_virt in he_init_group()
From: David Miller @ 2009-09-03 6:25 UTC (permalink / raw)
To: roel.kluin; +Cc: chas, linux-atm-general, netdev, akpm
In-Reply-To: <4A997A78.9080309@gmail.com>
From: Roel Kluin <roel.kluin@gmail.com>
Date: Sat, 29 Aug 2009 20:59:04 +0200
> he_dev->rbps_virt or he_dev->rbpl_virt allocation may fail.
>
> Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
> ---
> There was another in the same function.
These new return statements will both leak resources allocated
earlier.
All the caller is going to do is return -ENOMEM as well and
it does not cleanup actions at all.
Please fix this up.
^ permalink raw reply
* Re: [PATCH] forcedeth: updated phy errata
From: David Miller @ 2009-09-03 6:22 UTC (permalink / raw)
To: aabdulla; +Cc: manfred, akpm, netdev
In-Reply-To: <4A9C57F5.10800@nvidia.com>
From: Ayaz Abdulla <aabdulla@nvidia.com>
Date: Mon, 31 Aug 2009 19:08:37 -0400
> This patch updates the special programming (and/or errata) needed in
> order to setup the phy for various vendor models.
>
> The new models include:
> Marvell E1116
> Marvell E1111
> Marvell E1011
> Marvell E3016
> Broadcom 9507
> Broadcom AC131
> Broadcom 50610
>
> Signed-off-by: Ayaz Abdulla <aabdulla@nvidia.com>
Please document what these individual bits mean which you
are clearing, by using an individual define for each register
bit to describe it's purpose, and then define the mask as
a concatenation of these bits.
Having an opaque bitmask is not how to do this.
Thanks.
^ permalink raw reply
* [PATCH V2] net-next-2.6:can: add TI CAN (HECC) driver
From: Anant Gole @ 2009-09-03 6:21 UTC (permalink / raw)
To: socketcan-core; +Cc: netdev, anantgole
TI HECC (High End CAN Ctonroller) module is found on many TI devices.
It has 32 hardware mailboxes with full implementation of CAN protocol
version 2.0B with bus speeds up to 1Mbps. Specifications of the
module are available at TI web <http://www.ti.com>
This driver is tested on a newer OMAP device EVM.
Signed-off-by: Anant Gole <anantgole@ti.com>
---
drivers/net/can/Kconfig | 9 +
drivers/net/can/Makefile | 2 +
drivers/net/can/ti_hecc.c | 997 ++++++++++++++++++++++++++++++++++
include/linux/can/platform/ti_hecc.h | 40 ++
4 files changed, 1048 insertions(+), 0 deletions(-)
delete mode 100644 drivers/mtd/maps/sbc8240.c
create mode 100644 drivers/net/can/ti_hecc.c
create mode 100644 include/linux/can/platform/ti_hecc.h
diff --git a/drivers/mtd/maps/sbc8240.c b/drivers/mtd/maps/sbc8240.c
deleted file mode 100644
index e69de29..0000000
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 30ae55d..fae62df 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -75,6 +75,15 @@ 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_TI_HECC
+ depends on CAN_DEV
+ tristate "TI High End CAN Controller (HECC)"
+ default N
+ ---help---
+ This driver adds support for TI High End CAN Controller module
+ found on many TI devices. The specifications of this module are
+ are available from TI web (http://www.ti.com)
+
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..d923512 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -9,4 +9,6 @@ can-dev-y := dev.o
obj-$(CONFIG_CAN_SJA1000) += sja1000/
+obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
+
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
new file mode 100644
index 0000000..e8c2763
--- /dev/null
+++ b/drivers/net/can/ti_hecc.c
@@ -0,0 +1,997 @@
+/*
+ * TI HECC (CAN) device driver
+ *
+ * This driver supports TI's HECC (High End CAN Controller module) and the
+ * specs for the same is available at <http://www.ti.com>
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed as is WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ * Your platform definitions should specify module ram offsets and interrupt
+ * number to use as follows:
+ *
+ * static struct ti_hecc_platform_data omap3517_evm_hecc_pdata = {
+ * .scc_hecc_offset = 0,
+ * .scc_ram_offset = 0x3000,
+ * .hecc_ram_offset = 0x3000,
+ * .mbox_offset = 0x2000,
+ * .int_line = 0,
+ * .revision = 1,
+ * };
+ *
+ * Please see include/can/platform/ti_hecc.h for description of above fields
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+#include <linux/can/platform/ti_hecc.h>
+
+#define DRV_NAME "ti_hecc"
+#define HECC_MODULE_VERSION "0.3"
+MODULE_VERSION(HECC_MODULE_VERSION);
+#define DRV_DESC "TI High End CAN Controller Driver " HECC_MODULE_VERSION
+
+#define HECC_MAX_MAILBOXES 32 /* hardware mboxes - do not change */
+#define MAX_TX_PRIO 0x3F /* hardware value - do not change */
+
+#if (CAN_ECHO_SKB_MAX > 16)
+#define TI_HECC_MAX_TX_MBOX 16
+#else
+#define TI_HECC_MAX_TX_MBOX CAN_ECHO_SKB_MAX
+#endif
+#define TI_HECC_MAX_RX_MBOX (HECC_MAX_MAILBOXES - TI_HECC_MAX_TX_MBOX)
+
+#define TI_HECC_DEF_NAPI_WEIGHT TI_HECC_MAX_RX_MBOX
+
+/* TI HECC module registers */
+
+#define HECC_CANME 0x0 /* Mailbox enable */
+#define HECC_CANMD 0x4 /* Mailbox direction */
+#define HECC_CANTRS 0x8 /* Transmit request set */
+#define HECC_CANTRR 0xC /* Transmit request */
+#define HECC_CANTA 0x10 /* Transmission acknowledge */
+#define HECC_CANAA 0x14 /* Abort acknowledge */
+#define HECC_CANRMP 0x18 /* Receive message pending */
+#define HECC_CANRML 0x1C /* Remote message lost */
+#define HECC_CANRFP 0x20 /* Remote frame pending */
+#define HECC_CANGAM 0x24 /* SECC only:Global acceptance mask */
+#define HECC_CANMC 0x28 /* Master control */
+#define HECC_CANBTC 0x2C /* Bit timing configuration */
+#define HECC_CANES 0x30 /* Error and status */
+#define HECC_CANTEC 0x34 /* Transmit error counter */
+#define HECC_CANREC 0x38 /* Receive error counter */
+#define HECC_CANGIF0 0x3C /* Global interrupt flag 0 */
+#define HECC_CANGIM 0x40 /* Global interrupt mask */
+#define HECC_CANGIF1 0x44 /* Global interrupt flag 1 */
+#define HECC_CANMIM 0x48 /* Mailbox interrupt mask */
+#define HECC_CANMIL 0x4C /* Mailbox interrupt level */
+#define HECC_CANOPC 0x50 /* Overwrite protection control */
+#define HECC_CANTIOC 0x54 /* Transmit I/O control */
+#define HECC_CANRIOC 0x58 /* Receive I/O control */
+#define HECC_CANLNT 0x5C /* HECC only: Local network time */
+#define HECC_CANTOC 0x60 /* HECC only: Time-out control */
+#define HECC_CANTOS 0x64 /* HECC only: Time-out status */
+#define HECC_CANTIOCE 0x68 /* SCC only:Enhanced TX I/O control */
+#define HECC_CANRIOCE 0x6C /* SCC only:Enhanced RX I/O control */
+
+/* SCC only:Local acceptance registers */
+#define HECC_CANLAM0 (priv->scc_ram_offset + 0x0)
+#define HECC_CANLAM3 (priv->scc_ram_offset + 0xC)
+
+/* HECC only */
+#define HECC_CANLAM(mbxno) (priv->hecc_ram_offset + ((mbxno) * 4))
+#define HECC_CANMOTS(mbxno) (priv->hecc_ram_offset + ((mbxno) * 4) + 0x80)
+#define HECC_CANMOTO(mbxno) (priv->hecc_ram_offset + ((mbxno) * 4) + 0x100)
+
+/* Mailbox registers */
+#define HECC_CANMID(mbxno) (priv->mbox_offset + ((mbxno) * 0x10))
+#define HECC_CANMCF(mbxno) (priv->mbox_offset + ((mbxno) * 0x10) + 0x4)
+#define HECC_CANMDL(mbxno) (priv->mbox_offset + ((mbxno) * 0x10) + 0x8)
+#define HECC_CANMDH(mbxno) (priv->mbox_offset + ((mbxno) * 0x10) + 0xC)
+
+#define HECC_SET_REG 0xFFFFFFFF
+#define HECC_CANID_MASK 0x3FF /* 18 bits mask for extended id's */
+
+#define HECC_CANMC_SCM BIT(13) /* SCC compat mode */
+#define HECC_CANMC_CCR BIT(12) /* Change config request */
+#define HECC_CANMC_PDR BIT(11) /* Local Power down - for sleep mode */
+#define HECC_CANMC_ABO BIT(7) /* Auto Bus On */
+#define HECC_CANMC_STM BIT(6) /* Self test mode - loopback */
+#define HECC_CANMC_SRES BIT(5) /* Software reset */
+
+#define HECC_CANTIOC_EN BIT(3) /* Enable CAN TX I/O pin */
+#define HECC_CANRIOC_EN BIT(3) /* Enable CAN RX I/O pin */
+
+#define HECC_CANMID_IDE BIT(31) /* Extended frame format */
+#define HECC_CANMID_AME BIT(30) /* Acceptance mask enable */
+#define HECC_CANMID_AAM BIT(29) /* Auto answer mode */
+
+#define HECC_CANES_FE BIT(24) /* form error */
+#define HECC_CANES_BE BIT(23) /* bit error */
+#define HECC_CANES_SA1 BIT(22) /* stuck at dominant error */
+#define HECC_CANES_CRCE BIT(21) /* CRC error */
+#define HECC_CANES_SE BIT(20) /* stuff bit error */
+#define HECC_CANES_ACKE BIT(19) /* ack error */
+#define HECC_CANES_BO BIT(18) /* Bus off status */
+#define HECC_CANES_EP BIT(17) /* Error passive status */
+#define HECC_CANES_EW BIT(16) /* Error warning status */
+#define HECC_CANES_SMA BIT(5) /* suspend mode ack */
+#define HECC_CANES_CCE BIT(4) /* Change config enabled */
+#define HECC_CANES_PDA BIT(3) /* Power down mode ack */
+
+#define HECC_CANBTC_SAM BIT(7) /* sample points */
+
+#define HECC_BUS_ERROR (HECC_CANES_FE | HECC_CANES_BE |\
+ HECC_CANES_CRCE | HECC_CANES_SE |\
+ HECC_CANES_ACKE)
+
+#define HECC_CANMCF_RTR BIT(4) /* Remote xmit request */
+
+#define HECC_CANGIF_MAIF BIT(17) /* Message alarm interrupt */
+#define HECC_CANGIF_TCOIF BIT(16) /* Timer counter overflow int */
+#define HECC_CANGIF_GMIF BIT(15) /* Global mailbox interrupt */
+#define HECC_CANGIF_AAIF BIT(14) /* Abort ack interrupt */
+#define HECC_CANGIF_WDIF BIT(13) /* Write denied interrupt */
+#define HECC_CANGIF_WUIF BIT(12) /* Wake up interrupt */
+#define HECC_CANGIF_RMLIF BIT(11) /* Receive message lost interrupt */
+#define HECC_CANGIF_BOIF BIT(10) /* Bus off interrupt */
+#define HECC_CANGIF_EPIF BIT(9) /* Error passive interrupt */
+#define HECC_CANGIF_WLIF BIT(8) /* Warning level interrupt */
+#define HECC_CANGIF_MBOX_MASK 0x1F /* Mailbox number mask */
+#define HECC_CANGIM_I1EN BIT(1) /* Int line 1 enable */
+#define HECC_CANGIM_I0EN BIT(0) /* Int line 0 enable */
+#define HECC_CANGIM_DEF_MASK 0x700 /* only busoff/warning/passive */
+#define HECC_CANGIM_SIL BIT(2) /* system interrupts to int line 1 */
+
+/* CAN Bittiming constants as per HECC specs */
+static struct can_bittiming_const ti_hecc_bittiming_const = {
+ .name = DRV_NAME,
+ .tseg1_min = 1,
+ .tseg1_max = 16,
+ .tseg2_min = 1,
+ .tseg2_max = 8,
+ .sjw_max = 4,
+ .brp_min = 1,
+ .brp_max = 256,
+ .brp_inc = 1,
+};
+
+struct ti_hecc_priv {
+ struct can_priv can; /* MUST be first member/field */
+ struct napi_struct napi;
+ struct net_device *ndev;
+ struct clk *clk;
+ void __iomem *base;
+ u32 scc_ram_offset;
+ u32 hecc_ram_offset;
+ u32 mbox_offset;
+ u32 int_line;
+ u32 tx_mbxno;
+ u32 prio;
+ u32 stop_xmit;
+ DECLARE_BITMAP(tx_free_mbx, TI_HECC_MAX_TX_MBOX);
+ spinlock_t tx_lock; /* Protects tx_mbxno & tx_free_mbx bitmap */
+
+};
+
+static inline
+void hecc_write(struct ti_hecc_priv *priv, int reg, u32 val)
+{
+ __raw_writel(val, priv->base + reg);
+}
+
+static inline u32 hecc_read(struct ti_hecc_priv *priv, int reg)
+{
+ return __raw_readl(priv->base + reg);
+}
+
+static inline
+void hecc_set_bit(struct ti_hecc_priv *priv, int reg, unsigned bit)
+{
+ hecc_write(priv, reg, (hecc_read(priv, reg) | bit));
+}
+
+static inline
+void hecc_clear_bit(struct ti_hecc_priv *priv, int reg, unsigned bit)
+{
+ hecc_write(priv, reg, (hecc_read(priv, reg) & ~bit));
+}
+
+static inline
+u32 hecc_get_bit(struct ti_hecc_priv *priv, int reg, int bit)
+{
+ return (hecc_read(priv, reg) & bit) ? 1 : 0;
+}
+
+static int ti_hecc_get_state(const struct net_device *ndev,
+ enum can_state *state)
+{
+ struct ti_hecc_priv *priv = netdev_priv(ndev);
+ *state = priv->can.state;
+ return 0;
+}
+
+static int ti_hecc_set_bittiming(struct net_device *ndev)
+{
+ /* NOTE: TI HECC module requires bittimings to be programmed only in
+ * initialization mode - this is handled only in ti_hecc_reset() in
+ * this driver and hence this function is dummy. The can bittiming
+ * structure should be populated before hand (via ip utility)
+ */
+ return 0;
+}
+
+static int ti_hecc_set_btc(struct ti_hecc_priv *priv)
+{
+ struct can_bittiming *bit_timing = &priv->can.bittiming;
+ u32 can_btc = 0;
+
+ can_btc = ((bit_timing->phase_seg2 - 1) & 0x7);
+ can_btc |= (((bit_timing->phase_seg1 + bit_timing->prop_seg - 1)
+ & 0xF) << 3);
+ if ((bit_timing->brp > 4) &&
+ (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES))
+ can_btc |= HECC_CANBTC_SAM;
+
+ can_btc |= (((bit_timing->sjw - 1) & 0x3) << 8);
+ can_btc |= (((bit_timing->brp - 1) & 0xFF) << 16);
+
+ /* ERM being set to 0 by default meaning resync at falling edge */
+
+ hecc_write(priv, HECC_CANBTC, can_btc);
+ dev_info(priv->ndev->dev.parent, "setting CANBTC=%#x\n", can_btc);
+
+ return 0;
+}
+
+static void ti_hecc_reset(struct net_device *ndev)
+{
+#define HECC_CCE_WAIT_COUNT 100
+ u32 cnt;
+ struct ti_hecc_priv *priv = netdev_priv(ndev);
+
+ dev_dbg(ndev->dev.parent, "resetting hecc ...\n");
+ hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_SRES);
+
+ /* Set change control request and wait till enabled */
+ hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
+
+ /* INFO: It has been observed that at times CCE bit may not be
+ * set and hw seems to be ok even if this bit is not set so
+ * timing out with a timing of 1ms to respect the specs
+ */
+ cnt = HECC_CCE_WAIT_COUNT;
+ while (!hecc_get_bit(priv, HECC_CANES, HECC_CANES_CCE) && (0 != cnt)) {
+ --cnt;
+ udelay(10);
+ }
+
+ /* Note: On HECC, BTC can be programmed only in initialization mode, so
+ * it is expected that the can bittiming parameters are set via ip
+ * utility before the device is opened
+ */
+ ti_hecc_set_btc(priv);
+
+ /* Clear CCR (and CANMC register) and wait for CCE = 0 enable */
+ hecc_write(priv, HECC_CANMC, 0);
+
+ /* INFO: CAN net stack handles bus off and hence disabling auto-bus-on
+ * hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_ABO);
+ */
+
+ /* INFO: It has been observed that at times CCE bit may not be
+ * set and hw seems to be ok even if this bit is not set so
+ */
+ cnt = HECC_CCE_WAIT_COUNT;
+ while (hecc_get_bit(priv, HECC_CANES, HECC_CANES_CCE) && (0 != cnt)) {
+ --cnt;
+ udelay(10);
+ }
+
+ /* Enable TX and RX I/O Control pins */
+ hecc_write(priv, HECC_CANTIOC, HECC_CANTIOC_EN);
+ hecc_write(priv, HECC_CANRIOC, HECC_CANRIOC_EN);
+
+ /* Clear registers for clean operation */
+ hecc_write(priv, HECC_CANTA, HECC_SET_REG);
+ hecc_write(priv, HECC_CANRMP, HECC_SET_REG);
+ hecc_write(priv, HECC_CANGIF0, HECC_SET_REG);
+ hecc_write(priv, HECC_CANGIF1, HECC_SET_REG);
+ hecc_write(priv, HECC_CANME, 0);
+ hecc_write(priv, HECC_CANMD, 0);
+
+ /* SCC compat mode NOT supported (and not needed too) */
+ hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_SCM);
+}
+
+/**
+ * ti_hecc_start: Starts HECC module
+ *
+ * If CAN state is not stopped, reset the module, init bit timings
+ * and start the device for operation
+ */
+static void ti_hecc_start(struct net_device *ndev)
+{
+ struct ti_hecc_priv *priv = netdev_priv(ndev);
+ int cnt, mbxno;
+
+ /* put HECC in initialization mode and set btc */
+ ti_hecc_reset(ndev);
+ priv->tx_mbxno = TI_HECC_MAX_TX_MBOX - 1;
+ priv->prio = MAX_TX_PRIO;
+ bitmap_zero(priv->tx_free_mbx, TI_HECC_MAX_TX_MBOX);
+
+ /* Enable local and global acceptance mask registers */
+ hecc_write(priv, HECC_CANGAM, HECC_SET_REG);
+ hecc_write(priv, HECC_CANLAM0, HECC_SET_REG);
+ hecc_write(priv, HECC_CANLAM3, HECC_SET_REG);
+
+ /* Prepare configured mailboxes to receive messages */
+ for (cnt = 0; cnt < TI_HECC_MAX_RX_MBOX; cnt++) {
+ mbxno = (HECC_MAX_MAILBOXES - 1 - cnt);
+ hecc_clear_bit(priv, HECC_CANME, (1 << mbxno));
+ hecc_write(priv, HECC_CANMID(mbxno), HECC_CANMID_AME);
+ hecc_write(priv, HECC_CANLAM(mbxno), HECC_SET_REG);
+ hecc_set_bit(priv, HECC_CANMD, (1 << mbxno));
+ hecc_set_bit(priv, HECC_CANME, (1 << mbxno));
+ hecc_set_bit(priv, HECC_CANMIM, (1 << mbxno));
+ }
+
+ /* Prevent message over-write & Enable interrupts */
+ hecc_write(priv, HECC_CANTRS, 0);
+ hecc_write(priv, HECC_CANOPC, HECC_SET_REG);
+ if (priv->int_line) {
+ hecc_write(priv, HECC_CANMIL, HECC_SET_REG);
+ hecc_write(priv, HECC_CANGIM, (HECC_CANGIM_DEF_MASK |
+ HECC_CANGIM_I1EN | HECC_CANGIM_SIL));
+ } else {
+ hecc_write(priv, HECC_CANMIL, 0);
+ hecc_write(priv, HECC_CANGIM,
+ (HECC_CANGIM_DEF_MASK | HECC_CANGIM_I0EN));
+ }
+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
+}
+
+static void ti_hecc_stop(struct net_device *ndev)
+{
+ struct ti_hecc_priv *priv = netdev_priv(ndev);
+
+ /* Disable interrupts and disable mailboxes */
+ hecc_write(priv, HECC_CANGIM, 0);
+ hecc_write(priv, HECC_CANMIM, 0);
+ hecc_write(priv, HECC_CANME, 0);
+ priv->can.state = CAN_STATE_STOPPED;
+}
+
+static int ti_hecc_do_set_mode(struct net_device *ndev, enum can_mode mode)
+{
+ struct ti_hecc_priv *priv = netdev_priv(ndev);
+ int ret = 0;
+
+ switch (mode) {
+ case CAN_MODE_START:
+ dev_info(priv->ndev->dev.parent, "device (re)starting\n");
+ ++priv->can.can_stats.restarts;
+ ti_hecc_start(ndev);
+ if (netif_queue_stopped(ndev))
+ netif_wake_queue(ndev);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * ti_hecc_xmit: HECC Transmit
+ *
+ * The transmit mailboxes start from 0 to TI_HECC_MAX_TX_MBOX. In HECC the
+ * priority of the mailbox for tranmission depends upon the setting of priority
+ * field in mailbox registers. The mailbox with highest value in priority field
+ * is transmitted first. Only when two mailboxes have the same value in
+ * priority field the highest numbered mailbox is transmitted first.
+ *
+ * To utilize the HECC priority feature as described above we start with the
+ * highest numbered mailbox with highest priority level and move on to the next
+ * mailbox with the same priority level and so on. Once we loop through all the
+ * transmit mailboxes we choose the next priority level (lower) and so on
+ * untill we reach the lowest priority level on the lowest numbered mailbox
+ * when we stop transmission untill all mailboxes are transmitted and then
+ * restart at highest numbered mailbox with highest priority.
+ *
+ * To keep track of next transmit mailbox priv->tx_mbxno is used along with
+ * priv->prio for priority. priv->stop_xmit helps sync transmit complete
+ * interrupt when we re-start the queue if it was stopped after the mailbox
+ * priority roll-over.
+ */
+static int ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ struct ti_hecc_priv *priv = netdev_priv(ndev);
+ struct can_frame *cf = (struct can_frame *)skb->data;
+ u32 mbxno = 0;
+ u32 data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ mbxno = priv->tx_mbxno;
+ set_bit(mbxno, priv->tx_free_mbx);
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+
+ /* Prepare mailbox for transmission */
+ hecc_clear_bit(priv, HECC_CANME, (1 << mbxno));
+ data = cf->can_dlc & 0xF;
+ if (cf->can_id & CAN_RTR_FLAG) /* Remote transmission request */
+ data |= HECC_CANMCF_RTR;
+ data |= ((priv->prio & 0x3F) << 8); /* set tx priority level */
+ hecc_write(priv, HECC_CANMCF(mbxno), data);
+
+ if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */
+ data = ((cf->can_id & CAN_EFF_MASK) | HECC_CANMID_IDE);
+ else /* Standard frame format */
+ data = ((cf->can_id & CAN_SFF_MASK) << 18);
+
+ hecc_write(priv, HECC_CANMID(mbxno), data);
+ data = (cf->data[0] << 24) | (cf->data[1] << 16) |
+ (cf->data[2] << 8) | cf->data[3];
+ hecc_write(priv, HECC_CANMDL(mbxno), data);
+ if (cf->can_dlc > 4) {
+ data = (cf->data[4] << 24) | (cf->data[5] << 16) |
+ (cf->data[6] << 8) | cf->data[7];
+ hecc_write(priv, HECC_CANMDH(mbxno), data);
+ }
+ can_put_echo_skb(skb, ndev, mbxno);
+
+ /* check if next mailbox is free - if not hold queue */
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ if (priv->tx_mbxno)
+ --priv->tx_mbxno;
+ else {
+ priv->tx_mbxno = (TI_HECC_MAX_TX_MBOX - 1);
+ if (priv->prio)
+ --priv->prio;
+ else {
+ priv->stop_xmit = 1;
+ priv->prio = MAX_TX_PRIO;
+ }
+ }
+
+ /* Stop the queue if next transmit mailbox is not free or if there
+ * is a wrap over in priority and queue should be stopped
+ */
+ if (test_bit(priv->tx_mbxno, priv->tx_free_mbx) || priv->stop_xmit)
+ netif_stop_queue(priv->ndev);
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+
+ /* Enable interrupt for mbox and start transmission */
+ hecc_clear_bit(priv, HECC_CANMD, (1 << mbxno));
+ hecc_set_bit(priv, HECC_CANME, (1 << mbxno));
+ hecc_set_bit(priv, HECC_CANMIM, (1 << mbxno));
+ hecc_set_bit(priv, HECC_CANTRS, (1 << mbxno));
+ ndev->trans_start = jiffies;
+
+ return NETDEV_TX_OK;
+}
+
+static int ti_hecc_rx_pkt(struct ti_hecc_priv *priv, int mbxno)
+{
+ struct net_device_stats *stats = &priv->ndev->stats;
+ struct can_frame *cf;
+ struct sk_buff *skb;
+ u32 data;
+
+ skb = dev_alloc_skb(sizeof(struct can_frame));
+ if (!skb) {
+ if (printk_ratelimit())
+ dev_err(priv->ndev->dev.parent,
+ "dev_alloc_skb() failed\n");
+ return -ENOMEM;
+ }
+ skb->dev = priv->ndev;
+ skb->protocol = htons(ETH_P_CAN);
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+ memset(cf, 0, sizeof(struct can_frame));
+ data = hecc_read(priv, HECC_CANMID(mbxno));
+ if (data & HECC_CANMID_IDE)
+ cf->can_id = (data & CAN_EFF_MASK) | CAN_EFF_FLAG;
+ else
+ cf->can_id = ((data >> 18) & CAN_SFF_MASK);
+ data = hecc_read(priv, HECC_CANMCF(mbxno));
+ if (data & HECC_CANMCF_RTR)
+ cf->can_id |= CAN_RTR_FLAG;
+ cf->can_dlc = data & 0xF;
+ data = hecc_read(priv, HECC_CANMDL(mbxno));
+ /* The below statements are for readability sake */
+ cf->data[0] = ((data & 0xFF000000) >> 24);
+ cf->data[1] = ((data & 0xFF0000) >> 16);
+ cf->data[2] = ((data & 0xFF00) >> 8);
+ cf->data[3] = (data & 0xFF);
+ if (cf->can_dlc > 4) {
+ data = hecc_read(priv, HECC_CANMDH(mbxno));
+ cf->data[4] = ((data & 0xFF000000) >> 24);
+ cf->data[5] = ((data & 0xFF0000) >> 16);
+ cf->data[6] = ((data & 0xFF00) >> 8);
+ cf->data[7] = (data & 0xFF);
+ }
+
+ /* prepare mailbox for next receive */
+ hecc_clear_bit(priv, HECC_CANME, (1 << mbxno));
+ hecc_write(priv, HECC_CANMID(mbxno), HECC_CANMID_AME);
+ hecc_write(priv, HECC_CANLAM(mbxno), HECC_SET_REG);
+ hecc_set_bit(priv, HECC_CANMD, (1 << mbxno));
+ hecc_set_bit(priv, HECC_CANME, (1 << mbxno));
+
+ stats->rx_bytes += cf->can_dlc;
+ netif_receive_skb(skb);
+ stats->rx_packets++;
+ priv->ndev->last_rx = jiffies;
+
+ return 0;
+}
+
+/**
+ * ti_hecc_rx_poll - HECC receive pkts
+ *
+ * The receive mailboxes start from highest numbered mailbox till last xmit
+ * mailbox. On CAN frame reception the hardware places the data into highest
+ * numbered mailbox that matches the CAN ID filter. Since all receive mailboxes
+ * have same filtering (ALL CAN frames) we process higher numbered mailboxes
+ * first and so on to ensure packet order.
+ */
+static int ti_hecc_rx_poll(struct napi_struct *napi, int quota)
+{
+ struct net_device *ndev = napi->dev;
+ struct ti_hecc_priv *priv = netdev_priv(ndev);
+ u32 num_pkts = 0;
+ u32 mbxno, mbx_mask;
+ unsigned long pending_pkts;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ pending_pkts = hecc_read(priv, HECC_CANRMP);
+ mbx_mask = BIT(HECC_MAX_MAILBOXES - 1); /* highest numbered mailbox */
+ mbxno = (HECC_MAX_MAILBOXES - 1);
+ while (pending_pkts && (num_pkts < quota)) {
+ if (mbx_mask & pending_pkts) {
+ if (ti_hecc_rx_pkt(priv, mbxno) < 0)
+ return num_pkts;
+ clear_bit(mbxno, &pending_pkts);
+ hecc_set_bit(priv, HECC_CANRMP, (1 << mbxno));
+ ++num_pkts;
+ }
+ mbx_mask = (mbx_mask >> 1);
+ --mbxno;
+ }
+
+ /* Enable packet interrupt if all pkts are handled */
+ if (0 == hecc_read(priv, HECC_CANRMP)) {
+ napi_complete(napi);
+ /* Re-enable RX mailbox interrupts */
+ mbxno = hecc_read(priv, HECC_CANMIM);
+ mbxno |= (~((1 << TI_HECC_MAX_TX_MBOX) - 1));
+ hecc_write(priv, HECC_CANMIM, mbxno);
+ }
+
+ return num_pkts;
+}
+
+static int
+ti_hecc_error(struct net_device *ndev, int int_status, int err_status)
+{
+ struct ti_hecc_priv *priv = netdev_priv(ndev);
+ struct net_device_stats *stats = &ndev->stats;
+ struct can_frame *cf;
+ struct sk_buff *skb;
+
+ /* propogate the error condition to the can stack */
+ skb = dev_alloc_skb(sizeof(struct can_frame));
+ if (!skb) {
+ if (printk_ratelimit())
+ dev_err(priv->ndev->dev.parent,
+ "dev_alloc_skb() failed in err processing\n");
+ return -ENOMEM;
+ }
+ skb->dev = ndev;
+ skb->protocol = htons(ETH_P_CAN);
+ cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+ memset(cf, 0, sizeof(struct can_frame));
+ cf->can_id = CAN_ERR_FLAG;
+ cf->can_dlc = CAN_ERR_DLC;
+
+ if (int_status & HECC_CANGIF_WLIF) { /* warning level int */
+ if (0 == (int_status & HECC_CANGIF_BOIF)) {
+ priv->can.state = CAN_STATE_ERROR_WARNING;
+ ++priv->can.can_stats.error_warning;
+ cf->can_id |= CAN_ERR_CRTL;
+ if (hecc_read(priv, HECC_CANTEC) > 96)
+ cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
+ if (hecc_read(priv, HECC_CANREC) > 96)
+ cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
+ }
+ hecc_set_bit(priv, HECC_CANES, HECC_CANES_EW);
+ dev_dbg(priv->ndev->dev.parent, "Error Warning interrupt\n");
+ hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
+ }
+
+ if (int_status & HECC_CANGIF_EPIF) { /* error passive int */
+ if (0 == (int_status & HECC_CANGIF_BOIF)) {
+ priv->can.state = CAN_STATE_ERROR_PASSIVE;
+ ++priv->can.can_stats.error_passive;
+ cf->can_id |= CAN_ERR_CRTL;
+ if (hecc_read(priv, HECC_CANTEC) > 127)
+ cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+ if (hecc_read(priv, HECC_CANREC) > 127)
+ cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+ }
+ hecc_set_bit(priv, HECC_CANES, HECC_CANES_EP);
+ dev_dbg(priv->ndev->dev.parent, "Error passive interrupt\n");
+ hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
+ }
+
+ /* Need to check busoff condition in error status register too to
+ * ensure warning interrupts don't hog the system
+ */
+ if ((int_status & HECC_CANGIF_BOIF) || (err_status & HECC_CANES_BO)) {
+ priv->can.state = CAN_STATE_BUS_OFF;
+ cf->can_id |= CAN_ERR_BUSOFF;
+ hecc_set_bit(priv, HECC_CANES, HECC_CANES_BO);
+ hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
+ can_bus_off(ndev);
+ /* Disable all interrupts in bus-off to avoid int hog */
+ hecc_write(priv, HECC_CANGIM, 0);
+ }
+
+ if (err_status & HECC_BUS_ERROR) {
+ ++priv->can.can_stats.bus_error;
+ cf->can_id |= (CAN_ERR_BUSERROR | CAN_ERR_PROT);
+ cf->data[2] |= CAN_ERR_PROT_UNSPEC;
+ if (err_status & HECC_CANES_FE) {
+ hecc_set_bit(priv, HECC_CANES, HECC_CANES_FE);
+ cf->data[2] |= CAN_ERR_PROT_FORM;
+ }
+ if (err_status & HECC_CANES_BE) {
+ hecc_set_bit(priv, HECC_CANES, HECC_CANES_BE);
+ cf->data[2] |= CAN_ERR_PROT_BIT;
+ }
+ if (err_status & HECC_CANES_SE) {
+ hecc_set_bit(priv, HECC_CANES, HECC_CANES_SE);
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ }
+ if (err_status & HECC_CANES_CRCE) {
+ hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE);
+ cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
+ CAN_ERR_PROT_LOC_CRC_DEL);
+ }
+ if (err_status & HECC_CANES_ACKE) {
+ hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE);
+ cf->data[2] |= (CAN_ERR_PROT_LOC_ACK |
+ CAN_ERR_PROT_LOC_ACK_DEL);
+ }
+ }
+
+ netif_receive_skb(skb);
+ ndev->last_rx = jiffies;
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+ return 0;
+}
+
+
+/**
+ * ti_hecc_interrupt: TI HECC interrupt routine
+ *
+ * Handles HECC interrupts - disables interrupt if receive pkts that will
+ * be enabled when rx pkts are complete (napi_complete is done)
+ */
+static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id)
+{
+ struct net_device *ndev = (struct net_device *)dev_id;
+ struct ti_hecc_priv *priv = netdev_priv(ndev);
+ struct net_device_stats *stats = &ndev->stats;
+ u32 mbxno, int_status, err_status;
+ unsigned long flags, ack, canta_ack;
+
+ if (priv->int_line)
+ int_status = hecc_read(priv, HECC_CANGIF1);
+ else
+ int_status = hecc_read(priv, HECC_CANGIF0);
+
+ if (0 == int_status)
+ return IRQ_NONE;
+
+ err_status = hecc_read(priv, HECC_CANES);
+ if (err_status & (HECC_BUS_ERROR | HECC_CANES_BO |
+ HECC_CANES_EP | HECC_CANES_EW))
+ ti_hecc_error(ndev, int_status, err_status);
+
+ /* Handle mailbox interrupt */
+ if (int_status & HECC_CANGIF_GMIF) {
+ canta_ack = ack = hecc_read(priv, HECC_CANTA);
+ while (ack) {
+ mbxno = find_first_bit(&ack, HECC_MAX_MAILBOXES);
+ if (mbxno == HECC_MAX_MAILBOXES) {
+ break;
+ } else {
+ clear_bit(mbxno, &ack);
+ hecc_clear_bit(priv, HECC_CANME, (1 << mbxno));
+ hecc_clear_bit(priv, HECC_CANMIM, (1 << mbxno));
+ stats->tx_bytes =
+ (hecc_read(priv, HECC_CANMCF(mbxno)) &
+ 0xF);
+ can_get_echo_skb(ndev, mbxno);
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ clear_bit(mbxno, priv->tx_free_mbx);
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+ stats->tx_packets++;
+ }
+ }
+ hecc_write(priv, HECC_CANTA, canta_ack);
+ if (priv->stop_xmit) {
+ ack = hecc_read(priv, HECC_CANME);
+ if ((ack & ((1 << TI_HECC_MAX_TX_MBOX) - 1)) == 0)
+ if (netif_queue_stopped(ndev)) {
+ priv->stop_xmit = 0;
+ netif_wake_queue(ndev);
+ }
+ } else {
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ if (!test_bit(priv->tx_mbxno, priv->tx_free_mbx))
+ if (netif_queue_stopped(ndev))
+ netif_wake_queue(ndev);
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+ }
+
+ /* Disable RX mailbox interrupts and let NAPI reenable them */
+ if (hecc_read(priv, HECC_CANRMP)) {
+ ack = hecc_read(priv, HECC_CANMIM);
+ ack &= ((1 << TI_HECC_MAX_TX_MBOX) - 1);
+ hecc_write(priv, HECC_CANMIM, ack);
+ napi_schedule(&priv->napi);
+ }
+ }
+
+ /* clear all interrupt conditions - read back to avoid spurious ints */
+ if (priv->int_line) {
+ hecc_write(priv, HECC_CANGIF1, HECC_SET_REG);
+ int_status = hecc_read(priv, HECC_CANGIF1);
+ } else {
+ hecc_write(priv, HECC_CANGIF0, HECC_SET_REG);
+ int_status = hecc_read(priv, HECC_CANGIF0);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int ti_hecc_open(struct net_device *ndev)
+{
+ struct ti_hecc_priv *priv = netdev_priv(ndev);
+ int err;
+
+ err = request_irq(ndev->irq, ti_hecc_interrupt, IRQF_DISABLED,
+ ndev->name, ndev);
+ if (err) {
+ dev_err(ndev->dev.parent, "error requesting interrupt\n");
+ return err;
+ }
+
+ /* Open common can device */
+ err = open_candev(ndev);
+ if (err) {
+ dev_err(ndev->dev.parent, "open_candev() failed %08X\n", err);
+ free_irq(ndev->irq, ndev);
+ return err;
+ }
+
+ /* Initialize device and start net queue */
+ spin_lock_init(&priv->tx_lock);
+
+ clk_enable(priv->clk);
+ ti_hecc_start(ndev);
+ napi_enable(&priv->napi);
+ netif_start_queue(ndev);
+
+ dev_info(ndev->dev.parent, "device open\n");
+ return 0;
+}
+
+static int ti_hecc_close(struct net_device *ndev)
+{
+ struct ti_hecc_priv *priv = netdev_priv(ndev);
+
+ netif_stop_queue(ndev);
+ napi_disable(&priv->napi);
+ ti_hecc_stop(ndev);
+ free_irq(ndev->irq, ndev);
+ clk_disable(priv->clk);
+ close_candev(ndev);
+ dev_info(ndev->dev.parent, "device stopped\n");
+
+ return 0;
+}
+
+static const struct net_device_ops ti_hecc_netdev_ops = {
+ .ndo_open = ti_hecc_open,
+ .ndo_stop = ti_hecc_close,
+ .ndo_start_xmit = ti_hecc_xmit,
+};
+
+static int ti_hecc_probe(struct platform_device *pdev)
+{
+ struct net_device *ndev = (struct net_device *)0;
+ struct ti_hecc_priv *priv;
+ struct ti_hecc_platform_data *pdata;
+ struct resource *mem, *irq;
+ void __iomem *addr;
+ int err;
+
+ dev_dbg(&pdev->dev, " probing devices...\n");
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(&pdev->dev, "No platform data - exiting\n");
+ return -ENODEV;
+ }
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "no mem resources???\n");
+ err = -ENODEV;
+ goto probe_exit;
+ }
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq) {
+ dev_err(&pdev->dev, "no irq resourc???\n");
+ err = -ENODEV;
+ goto probe_exit;
+ }
+ if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
+ dev_err(&pdev->dev, "HECC region already claimed\n");
+ err = -EBUSY;
+ goto probe_exit;
+ }
+ addr = ioremap(mem->start, resource_size(mem));
+ if (!addr) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ err = -ENOMEM;
+ goto probe_exit_free_region;
+ }
+
+ ndev = alloc_candev(sizeof(struct ti_hecc_priv));
+ if (!ndev) {
+ dev_err(&pdev->dev, "alloc_candev failed\n");
+ err = -ENOMEM;
+ goto probe_exit_iounmap;
+ }
+
+ priv = netdev_priv(ndev);
+ priv->ndev = ndev;
+ priv->base = addr;
+ priv->scc_ram_offset = pdata->scc_ram_offset;
+ priv->hecc_ram_offset = pdata->hecc_ram_offset;
+ priv->mbox_offset = pdata->mbox_offset;
+ priv->int_line = pdata->int_line;
+
+ priv->can.bittiming_const = &ti_hecc_bittiming_const;
+ priv->can.do_set_bittiming = ti_hecc_set_bittiming;
+ priv->can.do_set_mode = ti_hecc_do_set_mode;
+ priv->can.do_get_state = ti_hecc_get_state;
+
+ ndev->irq = irq->start;
+ ndev->flags |= IFF_ECHO;
+ platform_set_drvdata(pdev, ndev);
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+ ndev->netdev_ops = &ti_hecc_netdev_ops;
+
+ /* Note: clk name would change using hecc_vbusp_ck temporarily */
+ priv->clk = clk_get(&pdev->dev, "hecc_vbusp_ck");
+ if (IS_ERR(priv->clk)) {
+ dev_err(&pdev->dev, "no clock available\n");
+ err = PTR_ERR(priv->clk);
+ priv->clk = NULL;
+ goto probe_exit_candev;
+ }
+ priv->can.clock.freq = clk_get_rate(priv->clk);
+ netif_napi_add(ndev, &priv->napi, ti_hecc_rx_poll,
+ TI_HECC_DEF_NAPI_WEIGHT);
+
+ err = register_candev(ndev);
+ if (err) {
+ dev_err(&pdev->dev, "register_candev() failed\n");
+ err = -ENODEV;
+ goto probe_exit_clk;
+ }
+ dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%u)\n",
+ priv->base, (u32) ndev->irq);
+
+ return 0;
+
+probe_exit_clk:
+ clk_put(priv->clk);
+probe_exit_candev:
+ free_candev(ndev);
+probe_exit_iounmap:
+ iounmap(addr);
+probe_exit_free_region:
+ release_mem_region(mem->start, resource_size(mem));
+probe_exit:
+ dev_err(ndev->dev.parent, "probe error = %08X\n", err);
+ return err;
+}
+
+static int __devexit ti_hecc_remove(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct ti_hecc_priv *priv = netdev_priv(ndev);
+
+ clk_put(priv->clk);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ iounmap(priv->base);
+ release_mem_region(res->start, resource_size(res));
+ unregister_candev(ndev);
+ free_candev(ndev);
+ platform_set_drvdata(pdev, NULL);
+ dev_info(ndev->dev.parent, "driver removed\n");
+
+ return 0;
+}
+
+/* TI HECC netdevice driver: platform driver structure */
+static struct platform_driver ti_hecc_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = ti_hecc_probe,
+ .remove = __devexit_p(ti_hecc_remove),
+};
+
+static int __init ti_hecc_init_driver(void)
+{
+ printk(KERN_INFO DRV_DESC "\n");
+ return platform_driver_register(&ti_hecc_driver);
+}
+module_init(ti_hecc_init_driver);
+
+static void __exit ti_hecc_exit_driver(void)
+{
+ printk(KERN_INFO DRV_DESC " :Exit\n");
+ platform_driver_unregister(&ti_hecc_driver);
+}
+module_exit(ti_hecc_exit_driver);
+
+MODULE_AUTHOR("Anant Gole <anantgole@ti.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION(DRV_DESC);
diff --git a/include/linux/can/platform/ti_hecc.h b/include/linux/can/platform/ti_hecc.h
new file mode 100644
index 0000000..9164c67
--- /dev/null
+++ b/include/linux/can/platform/ti_hecc.h
@@ -0,0 +1,40 @@
+/*
+ * TI HECC (High End CAN Controller) driver platform header
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed as is WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/**
+ * struct hecc_platform_data - HECC Platform Data
+ *
+ * @scc_hecc_offset: mostly 0 - should really never change
+ * @scc_ram_offset: SCC RAM offset
+ * @hecc_ram_offset: HECC RAM offset
+ * @mbox_offset: Mailbox RAM offset
+ * @int_line: Interrupt line to use - 0 or 1
+ * @version: version for future use
+ *
+ * Platform data structure to get all platform specific settings.
+ * this structure also accounts the fact that the IP may have different
+ * RAM and mailbox offsets for different SOC's
+ */
+struct ti_hecc_platform_data {
+ u32 scc_hecc_offset;
+ u32 scc_ram_offset;
+ u32 hecc_ram_offset;
+ u32 mbox_offset;
+ u32 int_line;
+ u32 version;
+};
+
+
--
1.6.2.4
^ permalink raw reply related
* Re: [PATCH 1/2] fec: fix recursive locking of mii_lock
From: David Miller @ 2009-09-03 6:17 UTC (permalink / raw)
To: gerg
Cc: u.kleine-koenig, linux-rt-users, ben, kaber, s.hauer, Matt.Waddel,
netdev, tim01
In-Reply-To: <4A9F18E0.3060307@snapgear.com>
From: Greg Ungerer <gerg@snapgear.com>
Date: Thu, 03 Sep 2009 11:16:16 +1000
> Hi Uwe,
>
> Uwe Kleine-König wrote:
>> mii_discover_phy is only called by fec_enet_mii (via mip->mii_func).
>> So
>> &fep->mii_lock is already held and mii_discover_phy must not call
>> mii_queue which locks &fep->mii_lock, too.
>> This was noticed by lockdep:
...
>> ...
>> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
>> Cc: Greg Ungerer <gerg@uclinux.org>
>
> Looks good too.
>
> Acked-by: Greg Ungerer <gerg@uclinux.org>
Applied to net-next-2.6
--
To unsubscribe from this list: send the line "unsubscribe linux-rt-users" 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
* Re: [PATCH 2/2] fec: don't enable irqs in hard irq context
From: David Miller @ 2009-09-03 6:17 UTC (permalink / raw)
To: gerg
Cc: u.kleine-koenig, linux-rt-users, ben, kaber, s.hauer, Matt.Waddel,
netdev, tim01
In-Reply-To: <4A9F1870.7070408@snapgear.com>
From: Greg Ungerer <gerg@snapgear.com>
Date: Thu, 03 Sep 2009 11:14:24 +1000
> Hi Uwe,
>
> Uwe Kleine-König wrote:
>> fec_enet_mii, fec_enet_rx and fec_enet_tx are both only called by
>> fec_enet_interrupt in interrupt context. So they must not use
>> spin_lock_irq/spin_unlock_irq.
>> This fixes:
>> WARNING: at kernel/lockdep.c:2140
>> trace_hardirqs_on_caller+0x130/0x194()
>> ...
>> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
>> Cc: Greg Ungerer <gerg@uclinux.org>
>
> Looks good.
>
> Acked-by: Greg Ungerer <gerg@uclinux.org>
Applied to net-next-2.6
^ permalink raw reply
* Re: [PATCH] tc35815: Disable PM capability
From: David Miller @ 2009-09-03 6:15 UTC (permalink / raw)
To: anemo; +Cc: netdev
In-Reply-To: <1251906680-5828-1-git-send-email-anemo@mba.ocn.ne.jp>
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Thu, 3 Sep 2009 00:51:20 +0900
> This chip may report existance of PM registers though they are not
> supported. Disable PM features by clearing pdev->pm_cap.
>
> Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Please handle this as a quirk in drivers/pci/quirks.c as that
is the proper place to handle these kinds of exceptions.
The patch should be submitted to the PCI subsystem maintainer.
Thanks!
^ permalink raw reply
* Re: [PATCH] WARNING: some request_irq() failures ignored in el2_open()
From: David Miller @ 2009-09-03 6:10 UTC (permalink / raw)
To: roel.kluin; +Cc: netdev, akpm
In-Reply-To: <4A9D4AD5.1010404@gmail.com>
From: Roel Kluin <roel.kluin@gmail.com>
Date: Tue, 01 Sep 2009 18:24:53 +0200
> Request_irq() may fail in different ways, handle accordingly.
>
> Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
> ---
> Don't we have to do something like this?
Looks good, applied to net-next-2.6, thanks!
^ permalink raw reply
* Re: [PATCH] NET: Fix possible corruption in bpqether driver
From: David Miller @ 2009-09-03 6:10 UTC (permalink / raw)
To: ralf; +Cc: netdev, linux-hams, thomas, jann
In-Reply-To: <20090902085841.GA5910@linux-mips.org>
From: Ralf Baechle <ralf@linux-mips.org>
Date: Wed, 2 Sep 2009 09:58:52 +0100
> The bpq ether driver is modifying the data art of the skb by first
> dropping the KISS byte (a command byte for the radio) then prepending the
> length + 4 of the remaining AX.25 packet to be transmitted as a little
> endian 16-bit number. If the high byte of the length has a different
> value than the dropped KISS byte users of clones of the skb may observe
> this as corruption. This was observed with by running listen(8) -a which
> uses a packet socket which clones transmit packets. The corruption will
> then typically be displayed for as a KISS "TX Delay" command for AX.25
> packets in the range of 252..508 bytes or any other KISS command for
> yet larger packets.
>
> Fixed by using skb_cow to create a private copy should the skb be cloned.
> Using skb_cow also allows us to cleanup the old logic to ensure sufficient
> headroom in the skb.
>
> While at it, replace a return of 0 from bpq_xmit with the proper constant
> NETDEV_TX_OK which is now being used everywhere else in this function.
>
> Affected: all 2.2, 2.4 and 2.6 kernels.
>
> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
> Reported-by: Jann Traschewski <jann@gmx.de>
Applied to net-next-2.6, thanks!
^ permalink raw reply
* Re: [PATCH][RESEND] tcp: replace hard coded GFP_KERNEL with sk_allocation
From: David Miller @ 2009-09-03 6:10 UTC (permalink / raw)
To: fengguang.wu-ral2JQCrhuEAvxtiuMwx3w
Cc: herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q,
acme-f8uhVLnGfZaxAyOMLChx1axOck334EZe,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-nfs-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20090903040407.GA20094@localhost>
From: Wu Fengguang <fengguang.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Date: Thu, 3 Sep 2009 12:04:07 +0800
> This fixed a lockdep warning which appeared when doing stress
> memory tests over NFS:
>
> inconsistent {RECLAIM_FS-ON-W} -> {IN-RECLAIM_FS-W} usage.
>
> page reclaim => nfs_writepage => tcp_sendmsg => lock sk_lock
>
> mount_root => nfs_root_data => tcp_close => lock sk_lock =>
> tcp_send_fin => alloc_skb_fclone => page reclaim
>
> David raised a concern that if the allocation fails in tcp_send_fin(), and it's
> GFP_ATOMIC, we are going to yield() (which sleeps) and loop endlessly waiting
> for the allocation to succeed.
>
> But fact is, the original GFP_KERNEL also sleeps. GFP_ATOMIC+yield() looks
> weird, but it is no worse the implicit sleep inside GFP_KERNEL. Both could
> loop endlessly under memory pressure.
>
> CC: Arnaldo Carvalho de Melo <acme-f8uhVLnGfZaxAyOMLChx1axOck334EZe@public.gmane.org>
> CC: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
> CC: Herbert Xu <herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org>
> Signed-off-by: Wu Fengguang <fengguang.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Applied to net-next-2.6, thanks!
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" 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 net-next-2.6] net/ethtool: Add support for the ethtool feature to flash firmware image from a specified file.
From: David Miller @ 2009-09-03 6:10 UTC (permalink / raw)
To: ajitk; +Cc: jgarzik, netdev
In-Reply-To: <20090903030241.GA19390@serverengines.com>
From: Ajit Khaparde <ajitk@serverengines.com>
Date: Thu, 3 Sep 2009 08:32:55 +0530
> This patch adds support to flash a firmware image to a device using ethtool.
> The driver gets the filename of the firmware image and flashes the image
> using the request firmware path.
>
> The region "on the chip" to be flashed can be specified by an option.
> It is upto the device driver to enumerate the region number passed by ethtool,
> to the region to be flashed.
>
> The default behavior is to flash all the regions on the chip.
>
> Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>
Applied to net-next-2.6, thanks.
^ permalink raw reply
* Re: [PATCH net-next-2.6] drivers: Kill now superfluous ->last_rx stores
From: David Miller @ 2009-09-03 6:09 UTC (permalink / raw)
To: eric.dumazet; +Cc: nhorman, netdev
In-Reply-To: <4A9BFBAA.10705@gmail.com>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 31 Aug 2009 18:34:50 +0200
> Eric Dumazet a écrit :
>> Neil Horman a écrit :
>>> I still see a large number of drivers that update dev->last_rx, although its
>>> not all as I look through the list, so something definately seems amiss.
>>
>> Some drivers still update dev->last_rx for their own needs, not a core
>> network concern.
>>
>> But a cleanup is certainly possible on few other drivers, about a dozen
>> if I count correctly.
>
> Well, a litle bit more if we look outside of drivers/net
>
> [PATCH net-next-2.6] drivers: Kill now superfluous ->last_rx stores
>
> The generic packet receive code takes care of setting
> netdev->last_rx when necessary, for the sake of the
> bonding ARP monitor.
>
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Applied, thanks Eric.
^ permalink raw reply
* [GIT]: Networking
From: David Miller @ 2009-09-03 6:02 UTC (permalink / raw)
To: torvalds; +Cc: akpm, netdev, linux-kernel
1) Packet scheduler classifier code can leak some uninitialized
kernel bytes to userspace. Fix from Eric Dumazet.
2) Revert tasklet_hrtimer conversions, naggling problems exist
and -rcX is not the time to be tinkering with it.
3) Sockets can leak when sk_free()'d shortly after sk_alloc()
with some protocols due to initialization order of
sk->sk_mem_alloc. Fix from Jarek Poplawski and Eric Dumazet.
4) gianfar frees netdev without unregistering it resulting in
crashes on unload. Fix from Toru UCHIYAMA.
5) ipw2200 uses large linear memory area (ie. high order allocation)
for firmware loading via DMA, which easily can (and does) fail.
Fix from Zhu Yi via John Linville.
Please pull, thanks a lot!
The following changes since commit 37d0892c5a94e208cf863e3b7bac014edee4346d:
Ian Kent (1):
autofs4 - fix missed case when changing to use struct path
are available in the git repository at:
master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git master
David S. Miller (2):
Merge branch 'master' of git://git.kernel.org/.../linville/wireless-2.6
pkt_sched: Revert tasklet_hrtimer changes.
Eric Dumazet (1):
tc: Fix unitialized kernel memory leak
Jarek Poplawski (1):
net: sk_free() should be allowed right after sk_alloc()
Toru UCHIYAMA (1):
gianfar: gfar_remove needs to call unregister_netdev()
Zhu Yi (1):
ipw2200: firmware DMA loading rework
drivers/net/gianfar.c | 1 +
drivers/net/wireless/ipw2x00/ipw2200.c | 120 ++++++++++++++++++--------------
include/net/pkt_sched.h | 4 +-
net/core/sock.c | 2 +-
net/sched/sch_api.c | 12 ++--
net/sched/sch_cbq.c | 25 +++----
6 files changed, 89 insertions(+), 75 deletions(-)
^ permalink raw reply
* Re: [PATCH net-next-2.6] net/ethtool: Add support for the ethtool feature to flash firmware image from a specified file.
From: Jeff Garzik @ 2009-09-03 5:55 UTC (permalink / raw)
To: Ajit Khaparde, davem; +Cc: netdev
In-Reply-To: <4A9F550D.1090105@pobox.com>
On 09/03/2009 01:33 AM, Jeff Garzik wrote:
>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>> index 90c4a36..15e4eb7 100644
>> --- a/include/linux/ethtool.h
>> +++ b/include/linux/ethtool.h
>> @@ -362,6 +362,18 @@ struct ethtool_rxnfc {
>> __u32 rule_locs[0];
>> };
>>
>> +#define ETHTOOL_FLASH_MAX_FILENAME 128
>> +enum ethtool_flash_op_type {
>> + ETHTOOL_FLASH_ALL_REGIONS = 0,
>> +};
>> +
>> +/* for passing firmware flashing related parameters */
>> +struct ethtool_flash {
>> + __u32 cmd;
>> + __u32 region;
>> + char data[ETHTOOL_FLASH_MAX_FILENAME];
>> +};
>
> It passes a _filepath_ directly into the kernel? That seems quite wrong...
doh, nevermind. Catching up...
Jeff
^ permalink raw reply
* Re: [PATCH] tc: Fix unitialized kernel memory leak
From: David Miller @ 2009-09-03 5:51 UTC (permalink / raw)
To: jpirko; +Cc: eric.dumazet, netdev
In-Reply-To: <20090902180935.GA2849@psychotron.redhat.com>
From: Jiri Pirko <jpirko@redhat.com>
Date: Wed, 2 Sep 2009 20:09:36 +0200
> Wed, Sep 02, 2009 at 02:40:09PM CEST, eric.dumazet@gmail.com wrote:
>>Three bytes of uninitialized kernel memory are currently leaked to user
>>
>>Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
>
> Reviewed-by: Jiri Pirko <jpirko@redhat.com>
I'll apply this to net-2.6, thanks everyone.
^ permalink raw reply
* Re: [PATCH] tc: Fix unitialized kernel memory leak
From: David Miller @ 2009-09-03 5:51 UTC (permalink / raw)
To: shemminger; +Cc: eric.dumazet, netdev
In-Reply-To: <20090902120540.34e2a198@nehalam>
From: Stephen Hemminger <shemminger@vyatta.com>
Date: Wed, 2 Sep 2009 12:05:40 -0700
> On Wed, 02 Sep 2009 14:40:09 +0200
> Eric Dumazet <eric.dumazet@gmail.com> wrote:
>
>> Three bytes of uninitialized kernel memory are currently leaked to user
>>
>> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
>> ---
>> diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
>> index 24d17ce..fdb694e 100644
>> --- a/net/sched/sch_api.c
>> +++ b/net/sched/sch_api.c
>> @@ -1456,6 +1456,8 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q,
>> nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
>> tcm = NLMSG_DATA(nlh);
>> tcm->tcm_family = AF_UNSPEC;
>> + tcm->tcm__pad1 = 0;
>> + tcm->tcm__pad2 = 0;
>> tcm->tcm_ifindex = qdisc_dev(q)->ifindex;
>> tcm->tcm_parent = q->handle;
>> tcm->tcm_handle = q->handle;
>
> Perhaps __nlmsg_put should just always call memset() for the whole
> added chunk. It is not like it is critical path in any way, and
> avoid any of this possible class of errors.
Doing it in __nlmsg_put would effect a lot of code paths. I don't
think you can say with certainty that it won't matter, tree wide.
What about things like the netfilter conntrack event monitor? Doesn't
that emit hundreds of thousands of events per second on a busy
firewall?
^ permalink raw reply
* Re: [PATCH net-next-2.6] net/ethtool: Add support for the ethtool feature to flash firmware image from a specified file.
From: David Miller @ 2009-09-03 5:43 UTC (permalink / raw)
To: jgarzik; +Cc: ajitk, netdev
In-Reply-To: <4A9F550D.1090105@pobox.com>
From: Jeff Garzik <jgarzik@pobox.com>
Date: Thu, 03 Sep 2009 01:33:01 -0400
> It passes a _filepath_ directly into the kernel? That seems quite
> wrong...
>
> we fixed kernel drivers to _not_ think they could read directly from
> the userland filesystem many years ago.
>
> Seems like passing in an mmap'd fd would be far preferable.
Jeff, it's passing in something that's going to requested via
the firmware loading infrastructure in the kernel.
It is the most appropriate way to do this.
^ permalink raw reply
* Re: [PATCH net-next-2.6] net/ethtool: Add support for the ethtool feature to flash firmware image from a specified file.
From: Jeff Garzik @ 2009-09-03 5:33 UTC (permalink / raw)
To: Ajit Khaparde; +Cc: davem, netdev
In-Reply-To: <20090903030241.GA19390@serverengines.com>
On 09/02/2009 11:02 PM, Ajit Khaparde wrote:
> This patch adds support to flash a firmware image to a device using ethtool.
> The driver gets the filename of the firmware image and flashes the image
> using the request firmware path.
>
> The region "on the chip" to be flashed can be specified by an option.
> It is upto the device driver to enumerate the region number passed by ethtool,
> to the region to be flashed.
>
> The default behavior is to flash all the regions on the chip.
>
> Signed-off-by: Ajit Khaparde<ajitk@serverengines.com>
> ---
> include/linux/ethtool.h | 14 ++++++++++++++
> net/core/ethtool.c | 16 ++++++++++++++++
> 2 files changed, 30 insertions(+), 0 deletions(-)
>
> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
> index 90c4a36..15e4eb7 100644
> --- a/include/linux/ethtool.h
> +++ b/include/linux/ethtool.h
> @@ -362,6 +362,18 @@ struct ethtool_rxnfc {
> __u32 rule_locs[0];
> };
>
> +#define ETHTOOL_FLASH_MAX_FILENAME 128
> +enum ethtool_flash_op_type {
> + ETHTOOL_FLASH_ALL_REGIONS = 0,
> +};
> +
> +/* for passing firmware flashing related parameters */
> +struct ethtool_flash {
> + __u32 cmd;
> + __u32 region;
> + char data[ETHTOOL_FLASH_MAX_FILENAME];
> +};
It passes a _filepath_ directly into the kernel? That seems quite wrong...
we fixed kernel drivers to _not_ think they could read directly from the
userland filesystem many years ago.
Seems like passing in an mmap'd fd would be far preferable.
Jeff
^ permalink raw reply
* [PATCH][RESEND] tcp: replace hard coded GFP_KERNEL with sk_allocation
From: Wu Fengguang @ 2009-09-03 4:04 UTC (permalink / raw)
To: David Miller
Cc: herbert@gondor.apana.org.au, Arnaldo Carvalho de Melo,
linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org,
netdev@vger.kernel.org
This fixed a lockdep warning which appeared when doing stress
memory tests over NFS:
inconsistent {RECLAIM_FS-ON-W} -> {IN-RECLAIM_FS-W} usage.
page reclaim => nfs_writepage => tcp_sendmsg => lock sk_lock
mount_root => nfs_root_data => tcp_close => lock sk_lock =>
tcp_send_fin => alloc_skb_fclone => page reclaim
David raised a concern that if the allocation fails in tcp_send_fin(), and it's
GFP_ATOMIC, we are going to yield() (which sleeps) and loop endlessly waiting
for the allocation to succeed.
But fact is, the original GFP_KERNEL also sleeps. GFP_ATOMIC+yield() looks
weird, but it is no worse the implicit sleep inside GFP_KERNEL. Both could
loop endlessly under memory pressure.
CC: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
CC: David S. Miller <davem@davemloft.net>
CC: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
---
net/ipv4/tcp.c | 4 ++--
net/ipv4/tcp_ipv4.c | 5 +++--
net/ipv4/tcp_output.c | 5 +++--
3 files changed, 8 insertions(+), 6 deletions(-)
--- linux.orig/net/ipv4/tcp_ipv4.c
+++ linux/net/ipv4/tcp_ipv4.c
@@ -970,8 +970,9 @@ static int tcp_v4_parse_md5_keys(struct
if (!tcp_sk(sk)->md5sig_info) {
struct tcp_sock *tp = tcp_sk(sk);
- struct tcp_md5sig_info *p = kzalloc(sizeof(*p), GFP_KERNEL);
+ struct tcp_md5sig_info *p;
+ p = kzalloc(sizeof(*p), sk->sk_allocation);
if (!p)
return -EINVAL;
@@ -979,7 +980,7 @@ static int tcp_v4_parse_md5_keys(struct
sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
}
- newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
+ newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, sk->sk_allocation);
if (!newkey)
return -ENOMEM;
return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr,
--- linux.orig/net/ipv4/tcp_output.c
+++ linux/net/ipv4/tcp_output.c
@@ -2100,7 +2100,8 @@ void tcp_send_fin(struct sock *sk)
} else {
/* Socket is locked, keep trying until memory is available. */
for (;;) {
- skb = alloc_skb_fclone(MAX_TCP_HEADER, GFP_KERNEL);
+ skb = alloc_skb_fclone(MAX_TCP_HEADER,
+ sk->sk_allocation);
if (skb)
break;
yield();
@@ -2358,7 +2359,7 @@ int tcp_connect(struct sock *sk)
sk->sk_wmem_queued += buff->truesize;
sk_mem_charge(sk, buff->truesize);
tp->packets_out += tcp_skb_pcount(buff);
- tcp_transmit_skb(sk, buff, 1, GFP_KERNEL);
+ tcp_transmit_skb(sk, buff, 1, sk->sk_allocation);
/* We change tp->snd_nxt after the tcp_transmit_skb() call
* in order to make this packet get counted in tcpOutSegs.
--- linux.orig/net/ipv4/tcp.c
+++ linux/net/ipv4/tcp.c
@@ -1834,7 +1834,7 @@ void tcp_close(struct sock *sk, long tim
/* Unread data was tossed, zap the connection. */
NET_INC_STATS_USER(sock_net(sk), LINUX_MIB_TCPABORTONCLOSE);
tcp_set_state(sk, TCP_CLOSE);
- tcp_send_active_reset(sk, GFP_KERNEL);
+ tcp_send_active_reset(sk, sk->sk_allocation);
} else if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
/* Check zero linger _after_ checking for unread data. */
sk->sk_prot->disconnect(sk, 0);
@@ -2666,7 +2666,7 @@ static struct tcp_md5sig_pool **__tcp_al
struct tcp_md5sig_pool *p;
struct crypto_hash *hash;
- p = kzalloc(sizeof(*p), GFP_KERNEL);
+ p = kzalloc(sizeof(*p), sk->sk_allocation);
if (!p)
goto out_free;
*per_cpu_ptr(pool, cpu) = p;
^ permalink raw reply
* [PATCH] ethtool: Add a new ethtool option to flash a firmware image from the specified file to a device.
From: Ajit Khaparde @ 2009-09-03 3:03 UTC (permalink / raw)
To: davem, jgarzik; +Cc: netdev
This patch adds a new "-f" option to the ethtool utility
to flash a firmware image specified by a file, to a network device.
The filename is passed to the network driver which will flash the image
on the chip using the request_firmware path.
The region "on the chip" to be flashed can be specified by an option.
It is upto the device driver to enumerate the region number passed by ethtool,
to the region to be flashed.
The default behavior is to flash all the regions on the chip.
Usage:
ethtool -f <interface name> <filename of firmware image>
ethtool -f <interface name> <filename of firmware image> [ REGION-NUMBER-TO-FLASH ]
Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>
---
ethtool-copy.h | 13 +++++++++++++
ethtool.8 | 15 +++++++++++++++
ethtool.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 82 insertions(+), 1 deletions(-)
diff --git a/ethtool-copy.h b/ethtool-copy.h
index 3ca4e2c..66429e5 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -272,6 +272,18 @@ struct ethtool_perm_addr {
__u8 data[0];
};
+#define ETHTOOL_FLASH_MAX_FILENAME 128
+enum ethtool_flash_op_type {
+ ETHTOOL_FLASH_ALL_REGIONS = 0,
+};
+
+/* for passing firmware flashing related parameters */
+struct ethtool_flash {
+ __u32 cmd;
+ __u32 region;
+ char data[ETHTOOL_FLASH_MAX_FILENAME];
+};
+
/* boolean flags controlling per-interface behavior characteristics.
* When reading, the flag indicates whether or not a certain behavior
* is enabled/present. When writing, the flag indicates whether
@@ -338,6 +350,7 @@ struct ethtool_rxnfc {
#define ETHTOOL_SRXFH 0x0000002a /* Set RX flow hash configuration */
#define ETHTOOL_GGRO 0x0000002b /* Get GRO enable (ethtool_value) */
#define ETHTOOL_SGRO 0x0000002c /* Set GRO enable (ethtool_value) */
+#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
diff --git a/ethtool.8 b/ethtool.8
index 178f6ea..e42da55 100644
--- a/ethtool.8
+++ b/ethtool.8
@@ -207,6 +207,11 @@ ethtool \- Display or change ethernet card settings
.I ethX
.RB [ rx-flow-hash \ \*(FL
.RB \ \*(HO]
+
+.B ethtool \-f|\-\-flash
+.I ethX
+.RI FILE
+.RI [ N ]
.SH DESCRIPTION
.BI ethtool
is used for querying settings of an ethernet device and changing them.
@@ -501,6 +506,16 @@ Hash on bytes 2 and 3 of the Layer 4 header of the rx packet.
Discard all packets of this flow type. When this option is set, all other options are ignored.
.PD
.RE
+.TP
+.B \-f \-\-flash \ FILE
+Flash firmware image from the specified file to a region on the adapter.
+By default this will flash all the regions on the adapter.
+.TP
+.B N
+A number to identify flash region where the image should be flashed.
+Default region is 0 which denotes all regions in the flash.
+.PD
+.RE
.SH BUGS
Not supported (in part or whole) on all ethernet drivers.
.SH AUTHOR
diff --git a/ethtool.c b/ethtool.c
index 0110682..6b21bf2 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -77,6 +77,7 @@ static char *unparse_rxfhashopts(u64 opts);
static int dump_rxfhash(int fhash, u64 val);
static int do_srxclass(int fd, struct ifreq *ifr);
static int do_grxclass(int fd, struct ifreq *ifr);
+static int do_flash(int fd, struct ifreq *ifr);
static int send_ioctl(int fd, struct ifreq *ifr);
static enum {
@@ -101,6 +102,7 @@ static enum {
MODE_GSTATS,
MODE_GNFC,
MODE_SNFC,
+ MODE_FLASHDEV,
} mode = MODE_GSET;
static struct option {
@@ -192,6 +194,9 @@ static struct option {
"classification options",
" [ rx-flow-hash tcp4|udp4|ah4|sctp4|"
"tcp6|udp6|ah6|sctp6 p|m|v|t|s|d|f|n|r... ]\n" },
+ { "-f", "--flash", MODE_FLASHDEV, "FILENAME " "Flash firmware image "
+ "from the specified file to a region on the device",
+ " [ REGION-NUMBER-TO-FLASH ]\n" },
{ "-h", "--help", MODE_HELP, "Show this help" },
{}
};
@@ -304,6 +309,9 @@ static int rx_fhash_get = 0;
static int rx_fhash_set = 0;
static u32 rx_fhash_val = 0;
static int rx_fhash_changed = 0;
+static char *flash_file = NULL;
+static int flash = -1;
+static int flash_region = -1;
static enum {
ONLINE=0,
OFFLINE,
@@ -496,7 +504,8 @@ static void parse_cmdline(int argc, char **argp)
(mode == MODE_GSTATS) ||
(mode == MODE_GNFC) ||
(mode == MODE_SNFC) ||
- (mode == MODE_PHYS_ID)) {
+ (mode == MODE_PHYS_ID) ||
+ (mode == MODE_FLASHDEV)) {
devname = argp[i];
break;
}
@@ -516,6 +525,10 @@ static void parse_cmdline(int argc, char **argp)
if (phys_id_time < 0)
show_usage(1);
break;
+ } else if (mode == MODE_FLASHDEV) {
+ flash_file = argp[i];
+ flash = 1;
+ break;
}
/* fallthrough */
default:
@@ -590,6 +603,12 @@ static void parse_cmdline(int argc, char **argp)
show_usage(1);
break;
}
+ if (mode == MODE_FLASHDEV) {
+ flash_region = strtol(argp[i], NULL, 0);
+ if ((flash_region < 0))
+ show_usage(1);
+ break;
+ }
if (mode == MODE_SNFC) {
if (!strcmp(argp[i], "rx-flow-hash")) {
i += 1;
@@ -1504,6 +1523,8 @@ static int doit(void)
return do_grxclass(fd, &ifr);
} else if (mode == MODE_SNFC) {
return do_srxclass(fd, &ifr);
+ } else if (mode == MODE_FLASHDEV) {
+ return do_flash(fd, &ifr);
}
return 69;
@@ -2398,6 +2419,38 @@ static int do_grxclass(int fd, struct ifreq *ifr)
return 0;
}
+static int do_flash(int fd, struct ifreq *ifr)
+{
+ struct ethtool_flash efl;
+ int err;
+
+ if (flash < 0) {
+ fprintf(stdout, "Missing filename argument\n");
+ show_usage(1);
+ return 98;
+ }
+
+ if (strlen(flash_file) > ETHTOOL_FLASH_MAX_FILENAME - 1) {
+ fprintf(stdout, "Filename too long\n");
+ return 99;
+ }
+
+ efl.cmd = ETHTOOL_FLASHDEV;
+ strcpy(efl.data, flash_file);
+
+ if (flash_region < 0)
+ efl.region = ETHTOOL_FLASH_ALL_REGIONS;
+ else
+ efl.region = flash_region;
+
+ ifr->ifr_data = (caddr_t)&efl;
+ err = send_ioctl(fd, ifr);
+ if (err < 0)
+ perror("Flashing failed");
+
+ return err;
+}
+
static int send_ioctl(int fd, struct ifreq *ifr)
{
return ioctl(fd, SIOCETHTOOL, ifr);
--
1.6.0.4
^ permalink raw reply related
* [PATCH net-next-2.6] net/ethtool: Add support for the ethtool feature to flash firmware image from a specified file.
From: Ajit Khaparde @ 2009-09-03 3:02 UTC (permalink / raw)
To: davem, jgarzik; +Cc: netdev
This patch adds support to flash a firmware image to a device using ethtool.
The driver gets the filename of the firmware image and flashes the image
using the request firmware path.
The region "on the chip" to be flashed can be specified by an option.
It is upto the device driver to enumerate the region number passed by ethtool,
to the region to be flashed.
The default behavior is to flash all the regions on the chip.
Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>
---
include/linux/ethtool.h | 14 ++++++++++++++
net/core/ethtool.c | 16 ++++++++++++++++
2 files changed, 30 insertions(+), 0 deletions(-)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 90c4a36..15e4eb7 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -362,6 +362,18 @@ struct ethtool_rxnfc {
__u32 rule_locs[0];
};
+#define ETHTOOL_FLASH_MAX_FILENAME 128
+enum ethtool_flash_op_type {
+ ETHTOOL_FLASH_ALL_REGIONS = 0,
+};
+
+/* for passing firmware flashing related parameters */
+struct ethtool_flash {
+ __u32 cmd;
+ __u32 region;
+ char data[ETHTOOL_FLASH_MAX_FILENAME];
+};
+
#ifdef __KERNEL__
struct net_device;
@@ -489,6 +501,7 @@ struct ethtool_ops {
int (*get_stats_count)(struct net_device *);/* use get_sset_count */
int (*get_rxnfc)(struct net_device *, struct ethtool_rxnfc *, void *);
int (*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *);
+ int (*flash_device)(struct net_device *, struct ethtool_flash *);
};
#endif /* __KERNEL__ */
@@ -545,6 +558,7 @@ struct ethtool_ops {
#define ETHTOOL_GRXCLSRLALL 0x00000030 /* Get all RX classification rule */
#define ETHTOOL_SRXCLSRLDEL 0x00000031 /* Delete RX classification rule */
#define ETHTOOL_SRXCLSRLINS 0x00000032 /* Insert RX classification rule */
+#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 44e5711..4c12ddb 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -898,6 +898,19 @@ static int ethtool_set_value(struct net_device *dev, char __user *useraddr,
return actor(dev, edata.data);
}
+static int ethtool_flash_device(struct net_device *dev, char __user *useraddr)
+{
+ struct ethtool_flash efl;
+
+ if (copy_from_user(&efl, useraddr, sizeof(efl)))
+ return -EFAULT;
+
+ if (!dev->ethtool_ops->flash_device)
+ return -EOPNOTSUPP;
+
+ return dev->ethtool_ops->flash_device(dev, &efl);
+}
+
/* The main entry point in this file. Called from net/core/dev.c */
int dev_ethtool(struct net *net, struct ifreq *ifr)
@@ -1111,6 +1124,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
case ETHTOOL_SGRO:
rc = ethtool_set_gro(dev, useraddr);
break;
+ case ETHTOOL_FLASHDEV:
+ rc = ethtool_flash_device(dev, useraddr);
+ break;
default:
rc = -EOPNOTSUPP;
}
--
1.6.0.4
^ permalink raw reply related
* Re: [RFC][PATCH][v5] net/ethtool: Add support for the ethtool feature to flash firmware image from a specified file.
From: Ajit Khaparde @ 2009-09-03 3:02 UTC (permalink / raw)
To: David Miller, jgarzik; +Cc: netdev
In-Reply-To: <20090902.144047.191136129.davem@davemloft.net>
On 02/09/09 14:40 -0700, David Miller wrote:
> From: Ajit Khaparde <ajitk@serverengines.com>
> Date: Wed, 2 Sep 2009 21:20:09 +0530
>
> > Is this patch good enough for being accepted? Please let me know if
> > any more work has to be done on this. Also, I want to send the
> > changes to the be2net driver which would use this ethtool feature.
>
> My impression was that the patch was still under review and
> people were still making change requests.
>
> I guess not :-)
>
> Please resubmit the kernel side patch, it'll get into patchwork
> and I'll apply it.
>
> Thanks.
Thanks David.
I am resending both the user space and the kernel side patches.
-Ajit
^ permalink raw reply
* Re: Crypto oops in async_chainiv_do_postponed
From: Herbert Xu @ 2009-09-03 1:53 UTC (permalink / raw)
To: Brad Bosch; +Cc: linux-crypto, netdev, offbase0
In-Reply-To: <19103.1061.50828.809996@waldo.imnotcreative.homeip.net>
On Wed, Sep 02, 2009 at 06:47:49PM -0500, Brad Bosch wrote:
>
> Assume the worker thread is executing between the dequeue in
> async_chainiv_do_postponed and the clear_bit call in
> async_chainiv_schedule_work. Further assume that we are processing
> the last item on the queue so durring this time, ctx->queue.qlen =
> 0. **INUSE is still set at this point.
>
> Meanwhile, three threads enter async_chainiv_givencrypt for the same
> ctx at about the same time.
>
> Thread one calls test_and_set_bit which returns 1 and calls
> async_cahiniv_postpone_request but suppose it has not yet enqueued.
> Now INUSE is set and qlen=0.
>
> Next, the worker thread calls clear_bit in async_chainiv_schedule_work
> but it is interrupted before it can call test_and_set_bit. Now INUSE
> is clear and qlen=0
>
> The test_and_set_bit in thread two is called at this moment and
> returns 0 and then calls async_chainiv_givencrypt_tail. Now INUSE is
> set and qlen=0.
>
> Thread one now locks the ctx and calls skcipher_enqueue_givcrypt and
> unlocks. Now INUSE is set and qlen=1.
>
> Thread three calls test_and_set_bit which returns 1 and then it clears
> INUSE since qlen=1 and it calls postpone with INUSE clear and qlen=1
How can thread three clear INUSE if test_and_set_bit returned 1?
If thread three sees it set then it will postpone. It can only
clear it if it was not set originally.
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 1/2] fec: fix recursive locking of mii_lock
From: Greg Ungerer @ 2009-09-03 1:16 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: linux-rt-users, Ben Hutchings, Patrick McHardy, Sascha Hauer,
Matt Waddel, netdev, Tim Sander
In-Reply-To: <1251882856-23549-1-git-send-email-u.kleine-koenig@pengutronix.de>
Hi Uwe,
Uwe Kleine-König wrote:
> mii_discover_phy is only called by fec_enet_mii (via mip->mii_func). So
> &fep->mii_lock is already held and mii_discover_phy must not call
> mii_queue which locks &fep->mii_lock, too.
>
> This was noticed by lockdep:
>
> =============================================
> [ INFO: possible recursive locking detected ]
> 2.6.31-rc8-00038-g37d0892 #109
> ---------------------------------------------
> swapper/1 is trying to acquire lock:
> (&fep->mii_lock){-.....}, at: [<c01569f8>] mii_queue+0x2c/0xcc
>
> but task is already holding lock:
> (&fep->mii_lock){-.....}, at: [<c0156328>] fec_enet_interrupt+0x78/0x460
>
> other info that might help us debug this:
> 2 locks held by swapper/1:
> #0: (rtnl_mutex){+.+.+.}, at: [<c0183534>] rtnl_lock+0x18/0x20
> #1: (&fep->mii_lock){-.....}, at: [<c0156328>] fec_enet_interrupt+0x78/0x460
>
> stack backtrace:
> Backtrace:
> [<c00226fc>] (dump_backtrace+0x0/0x108) from [<c01eac14>] (dump_stack+0x18/0x1c)
> r6:c781d118 r5:c03e41d8 r4:00000001
> [<c01eabfc>] (dump_stack+0x0/0x1c) from [<c005bae4>] (__lock_acquire+0x1a20/0x1a88)
> [<c005a0c4>] (__lock_acquire+0x0/0x1a88) from [<c005bbac>] (lock_acquire+0x60/0x74)
> [<c005bb4c>] (lock_acquire+0x0/0x74) from [<c01edda8>] (_spin_lock_irqsave+0x54/0x68)
> r7:60000093 r6:c01569f8 r5:c785e468 r4:00000000
> [<c01edd54>] (_spin_lock_irqsave+0x0/0x68) from [<c01569f8>] (mii_queue+0x2c/0xcc)
> r7:c785e468 r6:c0156b24 r5:600a0000 r4:c785e000
> [<c01569cc>] (mii_queue+0x0/0xcc) from [<c0156b78>] (mii_discover_phy+0x54/0xa8)
> r8:00000002 r7:00000032 r6:c785e000 r5:c785e360 r4:c785e000
> [<c0156b24>] (mii_discover_phy+0x0/0xa8) from [<c0156354>] (fec_enet_interrupt+0xa4/0x460)
> r5:c785e360 r4:c077a170
> [<c01562b0>] (fec_enet_interrupt+0x0/0x460) from [<c0066674>] (handle_IRQ_event+0x48/0x120)
> [<c006662c>] (handle_IRQ_event+0x0/0x120) from [<c0068438>] (handle_level_irq+0x94/0x11c)
> ...
>
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> Cc: Greg Ungerer <gerg@uclinux.org>
Looks good too.
Acked-by: Greg Ungerer <gerg@uclinux.org>
> Cc: Ben Hutchings <ben@decadent.org.uk>
> Cc: Patrick McHardy <kaber@trash.net>
> Cc: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Matt Waddel <Matt.Waddel@freescale.com>
> Cc: netdev@vger.kernel.org
> Cc: Tim Sander <tim01@vlsi.informatik.tu-darmstadt.de>
> ---
> drivers/net/fec.c | 22 +++++++++++++++++-----
> 1 files changed, 17 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/fec.c b/drivers/net/fec.c
> index c9fd82d..ef82606 100644
> --- a/drivers/net/fec.c
> +++ b/drivers/net/fec.c
> @@ -637,16 +637,15 @@ unlock:
> }
>
> static int
> -mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *))
> +mii_queue_unlocked(struct net_device *dev, int regval,
> + void (*func)(uint, struct net_device *))
> {
> struct fec_enet_private *fep;
> - unsigned long flags;
> mii_list_t *mip;
> int retval;
>
> /* Add PHY address to register command */
> fep = netdev_priv(dev);
> - spin_lock_irqsave(&fep->mii_lock, flags);
>
> regval |= fep->phy_addr << 23;
> retval = 0;
> @@ -667,6 +666,19 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi
> retval = 1;
> }
>
> + return retval;
> +}
> +
> +static int
> +mii_queue(struct net_device *dev, int regval,
> + void (*func)(uint, struct net_device *))
> +{
> + struct fec_enet_private *fep;
> + unsigned long flags;
> + int retval;
> + fep = netdev_priv(dev);
> + spin_lock_irqsave(&fep->mii_lock, flags);
> + retval = mii_queue_unlocked(dev, regval, func);
> spin_unlock_irqrestore(&fep->mii_lock, flags);
> return retval;
> }
> @@ -1373,11 +1385,11 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
>
> /* Got first part of ID, now get remainder */
> fep->phy_id = phytype << 16;
> - mii_queue(dev, mk_mii_read(MII_REG_PHYIR2),
> + mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR2),
> mii_discover_phy3);
> } else {
> fep->phy_addr++;
> - mii_queue(dev, mk_mii_read(MII_REG_PHYIR1),
> + mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR1),
> mii_discover_phy);
> }
> } else {
--
------------------------------------------------------------------------
Greg Ungerer -- Principal Engineer EMAIL: gerg@snapgear.com
SnapGear Group, McAfee PHONE: +61 7 3435 2888
825 Stanley St, FAX: +61 7 3891 3630
Woolloongabba, QLD, 4102, Australia WEB: http://www.SnapGear.com
^ permalink raw reply
* Re: [PATCH 2/2] fec: don't enable irqs in hard irq context
From: Greg Ungerer @ 2009-09-03 1:14 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: linux-rt-users, Ben Hutchings, Patrick McHardy, Sascha Hauer,
Matt Waddel, netdev, Tim Sander
In-Reply-To: <1251882856-23549-2-git-send-email-u.kleine-koenig@pengutronix.de>
Hi Uwe,
Uwe Kleine-König wrote:
> fec_enet_mii, fec_enet_rx and fec_enet_tx are both only called by
> fec_enet_interrupt in interrupt context. So they must not use
> spin_lock_irq/spin_unlock_irq.
>
> This fixes:
> WARNING: at kernel/lockdep.c:2140 trace_hardirqs_on_caller+0x130/0x194()
> ...
>
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> Cc: Greg Ungerer <gerg@uclinux.org>
Looks good.
Acked-by: Greg Ungerer <gerg@uclinux.org>
> Cc: Ben Hutchings <ben@decadent.org.uk>
> Cc: Patrick McHardy <kaber@trash.net>
> Cc: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Matt Waddel <Matt.Waddel@freescale.com>
> Cc: netdev@vger.kernel.org
> Cc: Tim Sander <tim01@vlsi.informatik.tu-darmstadt.de>
> ---
> drivers/net/fec.c | 12 ++++++------
> 1 files changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/fec.c b/drivers/net/fec.c
> index ef82606..9c49d56 100644
> --- a/drivers/net/fec.c
> +++ b/drivers/net/fec.c
> @@ -427,7 +427,7 @@ fec_enet_tx(struct net_device *dev)
> struct sk_buff *skb;
>
> fep = netdev_priv(dev);
> - spin_lock_irq(&fep->hw_lock);
> + spin_lock(&fep->hw_lock);
> bdp = fep->dirty_tx;
>
> while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
> @@ -486,7 +486,7 @@ fec_enet_tx(struct net_device *dev)
> }
> }
> fep->dirty_tx = bdp;
> - spin_unlock_irq(&fep->hw_lock);
> + spin_unlock(&fep->hw_lock);
> }
>
>
> @@ -509,7 +509,7 @@ fec_enet_rx(struct net_device *dev)
> flush_cache_all();
> #endif
>
> - spin_lock_irq(&fep->hw_lock);
> + spin_lock(&fep->hw_lock);
>
> /* First, grab all of the stats for the incoming packet.
> * These get messed up if we get called due to a busy condition.
> @@ -604,7 +604,7 @@ rx_processing_done:
> }
> fep->cur_rx = bdp;
>
> - spin_unlock_irq(&fep->hw_lock);
> + spin_unlock(&fep->hw_lock);
> }
>
> /* called from interrupt context */
> @@ -615,7 +615,7 @@ fec_enet_mii(struct net_device *dev)
> mii_list_t *mip;
>
> fep = netdev_priv(dev);
> - spin_lock_irq(&fep->mii_lock);
> + spin_lock(&fep->mii_lock);
>
> if ((mip = mii_head) == NULL) {
> printk("MII and no head!\n");
> @@ -633,7 +633,7 @@ fec_enet_mii(struct net_device *dev)
> writel(mip->mii_regval, fep->hwp + FEC_MII_DATA);
>
> unlock:
> - spin_unlock_irq(&fep->mii_lock);
> + spin_unlock(&fep->mii_lock);
> }
>
> static int
--
-----------------------------------------------------------------------
^ 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