Merge branch 'sh/urgent' into sh-latest

This commit is contained in:
Paul Mundt 2011-02-01 19:38:49 +09:00
commit 17292ecc07
292 changed files with 4856 additions and 2351 deletions

View file

@ -0,0 +1,25 @@
What: /sys/devices/platform/at91_can/net/<iface>/mb0_id
Date: January 2011
KernelVersion: 2.6.38
Contact: Marc Kleine-Budde <kernel@pengutronix.de>
Description:
Value representing the can_id of mailbox 0.
Default: 0x7ff (standard frame)
Due to a chip bug (errata 50.2.6.3 & 50.3.5.3 in
"AT91SAM9263 Preliminary 6249H-ATARM-27-Jul-09") the
contents of mailbox 0 may be send under certain
conditions (even if disabled or in rx mode).
The workaround in the errata suggests not to use the
mailbox and load it with an unused identifier.
In order to use an extended can_id add the
CAN_EFF_FLAG (0x80000000U) to the can_id. Example:
- standard id 0x7ff:
echo 0x7ff > /sys/class/net/can0/mb0_id
- extended id 0x1fffffff:
echo 0x9fffffff > /sys/class/net/can0/mb0_id

View file

@ -460,6 +460,8 @@ Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.1.30:
- Fix writev() (it kept writing the first segment over and over again
instead of moving onto subsequent segments).
- Fix crash in ntfs_mft_record_alloc() when mapping the new extent mft
record failed.
2.1.29:
- Fix a deadlock when mounting read-write.
2.1.28:

View file

@ -49,7 +49,8 @@ Table of Contents
3.3 Configuring Bonding Manually with Ifenslave
3.3.1 Configuring Multiple Bonds Manually
3.4 Configuring Bonding Manually via Sysfs
3.5 Overriding Configuration for Special Cases
3.5 Configuration with Interfaces Support
3.6 Overriding Configuration for Special Cases
4. Querying Bonding Configuration
4.1 Bonding Configuration
@ -161,8 +162,8 @@ onwards) do not have /usr/include/linux symbolically linked to the
default kernel source include directory.
SECOND IMPORTANT NOTE:
If you plan to configure bonding using sysfs, you do not need
to use ifenslave.
If you plan to configure bonding using sysfs or using the
/etc/network/interfaces file, you do not need to use ifenslave.
2. Bonding Driver Options
=========================
@ -779,22 +780,26 @@ resend_igmp
You can configure bonding using either your distro's network
initialization scripts, or manually using either ifenslave or the
sysfs interface. Distros generally use one of two packages for the
network initialization scripts: initscripts or sysconfig. Recent
versions of these packages have support for bonding, while older
sysfs interface. Distros generally use one of three packages for the
network initialization scripts: initscripts, sysconfig or interfaces.
Recent versions of these packages have support for bonding, while older
versions do not.
We will first describe the options for configuring bonding for
distros using versions of initscripts and sysconfig with full or
partial support for bonding, then provide information on enabling
distros using versions of initscripts, sysconfig and interfaces with full
or partial support for bonding, then provide information on enabling
bonding without support from the network initialization scripts (i.e.,
older versions of initscripts or sysconfig).
If you're unsure whether your distro uses sysconfig or
initscripts, or don't know if it's new enough, have no fear.
If you're unsure whether your distro uses sysconfig,
initscripts or interfaces, or don't know if it's new enough, have no fear.
Determining this is fairly straightforward.
First, issue the command:
First, look for a file called interfaces in /etc/network directory.
If this file is present in your system, then your system use interfaces. See
Configuration with Interfaces Support.
Else, issue the command:
$ rpm -qf /sbin/ifup
@ -1327,8 +1332,62 @@ echo 2000 > /sys/class/net/bond1/bonding/arp_interval
echo +eth2 > /sys/class/net/bond1/bonding/slaves
echo +eth3 > /sys/class/net/bond1/bonding/slaves
3.5 Overriding Configuration for Special Cases
3.5 Configuration with Interfaces Support
-----------------------------------------
This section applies to distros which use /etc/network/interfaces file
to describe network interface configuration, most notably Debian and it's
derivatives.
The ifup and ifdown commands on Debian don't support bonding out of
the box. The ifenslave-2.6 package should be installed to provide bonding
support. Once installed, this package will provide bond-* options to be used
into /etc/network/interfaces.
Note that ifenslave-2.6 package will load the bonding module and use
the ifenslave command when appropriate.
Example Configurations
----------------------
In /etc/network/interfaces, the following stanza will configure bond0, in
active-backup mode, with eth0 and eth1 as slaves.
auto bond0
iface bond0 inet dhcp
bond-slaves eth0 eth1
bond-mode active-backup
bond-miimon 100
bond-primary eth0 eth1
If the above configuration doesn't work, you might have a system using
upstart for system startup. This is most notably true for recent
Ubuntu versions. The following stanza in /etc/network/interfaces will
produce the same result on those systems.
auto bond0
iface bond0 inet dhcp
bond-slaves none
bond-mode active-backup
bond-miimon 100
auto eth0
iface eth0 inet manual
bond-master bond0
bond-primary eth0 eth1
auto eth1
iface eth1 inet manual
bond-master bond0
bond-primary eth0 eth1
For a full list of bond-* supported options in /etc/network/interfaces and some
more advanced examples tailored to you particular distros, see the files in
/usr/share/doc/ifenslave-2.6.
3.6 Overriding Configuration for Special Cases
----------------------------------------------
When using the bonding driver, the physical port which transmits a frame is
typically selected by the bonding driver, and is not relevant to the user or
system administrator. The output port is simply selected using the policies of

View file

@ -3139,6 +3139,12 @@ S: Maintained
F: net/ieee802154/
F: drivers/ieee802154/
IKANOS/ADI EAGLE ADSL USB DRIVER
M: Matthieu Castet <castet.matthieu@free.fr>
M: Stanislaw Gruszka <stf_xl@wp.pl>
S: Maintained
F: drivers/usb/atm/ueagle-atm.c
INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
M: Mimi Zohar <zohar@us.ibm.com>
S: Supported
@ -3327,7 +3333,6 @@ F: drivers/net/wimax/i2400m/
F: include/linux/wimax/i2400m.h
INTEL WIRELESS WIFI LINK (iwlwifi)
M: Reinette Chatre <reinette.chatre@intel.com>
M: Wey-Yi Guy <wey-yi.w.guy@intel.com>
M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org
@ -6595,6 +6600,16 @@ S: Maintained
F: drivers/char/virtio_console.c
F: include/linux/virtio_console.h
VIRTIO CORE, NET AND BLOCK DRIVERS
M: Rusty Russell <rusty@rustcorp.com.au>
M: "Michael S. Tsirkin" <mst@redhat.com>
L: virtualization@lists.linux-foundation.org
S: Maintained
F: drivers/virtio/
F: drivers/net/virtio_net.c
F: drivers/block/virtio_blk.c
F: include/linux/virtio_*.h
VIRTIO HOST (VHOST)
M: "Michael S. Tsirkin" <mst@redhat.com>
L: kvm@vger.kernel.org

View file

@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 38
EXTRAVERSION = -rc2
EXTRAVERSION = -rc3
NAME = Flesh-Eating Bats with Fangs
# *DOCUMENTATION*

View file

@ -95,6 +95,15 @@ static inline void __iomem *__typesafe_io(unsigned long addr)
return (void __iomem *)addr;
}
/* IO barriers */
#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
#define __iormb() rmb()
#define __iowmb() wmb()
#else
#define __iormb() do { } while (0)
#define __iowmb() do { } while (0)
#endif
/*
* Now, pick up the machine-defined IO definitions
*/
@ -125,17 +134,17 @@ static inline void __iomem *__typesafe_io(unsigned long addr)
* The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space.
*/
#ifdef __io
#define outb(v,p) __raw_writeb(v,__io(p))
#define outw(v,p) __raw_writew((__force __u16) \
cpu_to_le16(v),__io(p))
#define outl(v,p) __raw_writel((__force __u32) \
cpu_to_le32(v),__io(p))
#define outb(v,p) ({ __iowmb(); __raw_writeb(v,__io(p)); })
#define outw(v,p) ({ __iowmb(); __raw_writew((__force __u16) \
cpu_to_le16(v),__io(p)); })
#define outl(v,p) ({ __iowmb(); __raw_writel((__force __u32) \
cpu_to_le32(v),__io(p)); })
#define inb(p) ({ __u8 __v = __raw_readb(__io(p)); __v; })
#define inb(p) ({ __u8 __v = __raw_readb(__io(p)); __iormb(); __v; })
#define inw(p) ({ __u16 __v = le16_to_cpu((__force __le16) \
__raw_readw(__io(p))); __v; })
__raw_readw(__io(p))); __iormb(); __v; })
#define inl(p) ({ __u32 __v = le32_to_cpu((__force __le32) \
__raw_readl(__io(p))); __v; })
__raw_readl(__io(p))); __iormb(); __v; })
#define outsb(p,d,l) __raw_writesb(__io(p),d,l)
#define outsw(p,d,l) __raw_writesw(__io(p),d,l)
@ -192,14 +201,6 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
#define writel_relaxed(v,c) ((void)__raw_writel((__force u32) \
cpu_to_le32(v),__mem_pci(c)))
#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
#define __iormb() rmb()
#define __iowmb() wmb()
#else
#define __iormb() do { } while (0)
#define __iowmb() do { } while (0)
#endif
#define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; })
#define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; })
#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; })

View file

@ -392,24 +392,22 @@ ENDPROC(__turn_mmu_on)
#ifdef CONFIG_SMP_ON_UP
__fixup_smp:
mov r4, #0x00070000
orr r3, r4, #0xff000000 @ mask 0xff070000
orr r4, r4, #0x41000000 @ val 0x41070000
and r0, r9, r3
teq r0, r4 @ ARM CPU and ARMv6/v7?
and r3, r9, #0x000f0000 @ architecture version
teq r3, #0x000f0000 @ CPU ID supported?
bne __fixup_smp_on_up @ no, assume UP
orr r3, r3, #0x0000ff00
orr r3, r3, #0x000000f0 @ mask 0xff07fff0
bic r3, r9, #0x00ff0000
bic r3, r3, #0x0000000f @ mask 0xff00fff0
mov r4, #0x41000000
orr r4, r4, #0x0000b000
orr r4, r4, #0x00000020 @ val 0x4107b020
and r0, r9, r3
teq r0, r4 @ ARM 11MPCore?
orr r4, r4, #0x00000020 @ val 0x4100b020
teq r3, r4 @ ARM 11MPCore?
moveq pc, lr @ yes, assume SMP
mrc p15, 0, r0, c0, c0, 5 @ read MPIDR
tst r0, #1 << 31
movne pc, lr @ bit 31 => SMP
and r0, r0, #0xc0000000 @ multiprocessing extensions and
teq r0, #0x80000000 @ not part of a uniprocessor system?
moveq pc, lr @ yes, assume SMP
__fixup_smp_on_up:
adr r0, 1f

View file

@ -17,8 +17,8 @@
/* For NetWinder debugging */
.macro addruart, rp, rv
mov \rp, #0x000003f8
orr \rv, \rp, #0x7c000000 @ physical
orr \rp, \rp, #0xff000000 @ virtual
orr \rv, \rp, #0xff000000 @ virtual
orr \rp, \rp, #0x7c000000 @ physical
.endm
#define UART_SHIFT 0

View file

@ -14,19 +14,6 @@
#include <mach/irqs.h>
#include <asm/hardware/gic.h>
/*
* We use __glue to avoid errors with multiple definitions of
* .globl omap_irq_flags as it's included from entry-armv.S but not
* from entry-common.S.
*/
#ifdef __glue
.pushsection .data
.globl omap_irq_flags
omap_irq_flags:
.word 0
.popsection
#endif
.macro disable_fiq
.endm

View file

@ -57,6 +57,7 @@ struct omap_irq_bank {
unsigned long wake_enable;
};
u32 omap_irq_flags;
static unsigned int irq_bank_count;
static struct omap_irq_bank *irq_banks;
@ -176,7 +177,6 @@ static struct irq_chip omap_irq_chip = {
void __init omap_init_irq(void)
{
extern unsigned int omap_irq_flags;
int i, j;
#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)

View file

@ -264,7 +264,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
if (IS_ERR(od)) {
pr_err("%s: Cant build omap_device for %s:%s.\n",
__func__, name, oh->name);
return IS_ERR(od);
return PTR_ERR(od);
}
mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0);

View file

@ -38,20 +38,6 @@
*/
#ifdef MULTI_OMAP2
/*
* We use __glue to avoid errors with multiple definitions of
* .globl omap_irq_base as it's included from entry-armv.S but not
* from entry-common.S.
*/
#ifdef __glue
.pushsection .data
.globl omap_irq_base
omap_irq_base:
.word 0
.popsection
#endif
/*
* Configure the interrupt base on the first interrupt.
* See also omap_irq_base_init for setting omap_irq_base.

View file

@ -314,14 +314,13 @@ static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data)
return omap_hwmod_set_postsetup_state(oh, *(u8 *)data);
}
void __iomem *omap_irq_base;
/*
* Initialize asm_irq_base for entry-macro.S
*/
static inline void omap_irq_base_init(void)
{
extern void __iomem *omap_irq_base;
#ifdef MULTI_OMAP2
if (cpu_is_omap24xx())
omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE);
else if (cpu_is_omap34xx())
@ -330,7 +329,6 @@ static inline void omap_irq_base_init(void)
omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP44XX_GIC_CPU_BASE);
else
pr_err("Could not initialize omap_irq_base\n");
#endif
}
void __init omap2_init_common_infrastructure(void)

View file

@ -160,7 +160,7 @@ static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
struct omap_mux *mux = NULL;
struct omap_mux_entry *e;
const char *mode_name;
int found = 0, found_mode, mode0_len = 0;
int found = 0, found_mode = 0, mode0_len = 0;
struct list_head *muxmodes = &partition->muxmodes;
mode_name = strchr(muxname, '.');

View file

@ -207,9 +207,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
__set_irq_handler_unlocked(irq, handle_level_irq);
__set_irq_handler_unlocked(d->irq, handle_level_irq);
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
__set_irq_handler_unlocked(irq, handle_edge_irq);
__set_irq_handler_unlocked(d->irq, handle_edge_irq);
return 0;
}

View file

@ -20,6 +20,8 @@
#ifndef __MACH_CLK_H
#define __MACH_CLK_H
struct clk;
void tegra_periph_reset_deassert(struct clk *c);
void tegra_periph_reset_assert(struct clk *c);

View file

@ -20,6 +20,8 @@
#ifndef __MACH_CLKDEV_H
#define __MACH_CLKDEV_H
struct clk;
static inline int __clk_get(struct clk *clk)
{
return 1;

View file

@ -46,24 +46,24 @@
#define ICTLR_COP_IER_CLR 0x38
#define ICTLR_COP_IEP_CLASS 0x3c
static void (*gic_mask_irq)(struct irq_data *d);
static void (*gic_unmask_irq)(struct irq_data *d);
static void (*tegra_gic_mask_irq)(struct irq_data *d);
static void (*tegra_gic_unmask_irq)(struct irq_data *d);
#define irq_to_ictlr(irq) (((irq)-32) >> 5)
#define irq_to_ictlr(irq) (((irq) - 32) >> 5)
static void __iomem *tegra_ictlr_base = IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE);
#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr)*0x100)
#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr) * 0x100)
static void tegra_mask(struct irq_data *d)
{
void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq));
gic_mask_irq(d);
writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_CLR);
tegra_gic_mask_irq(d);
writel(1 << (d->irq & 31), addr+ICTLR_CPU_IER_CLR);
}
static void tegra_unmask(struct irq_data *d)
{
void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq));
gic_unmask_irq(d);
tegra_gic_unmask_irq(d);
writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_SET);
}
@ -98,8 +98,8 @@ void __init tegra_init_irq(void)
IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
gic = get_irq_chip(29);
gic_unmask_irq = gic->irq_unmask;
gic_mask_irq = gic->irq_mask;
tegra_gic_unmask_irq = gic->irq_unmask;
tegra_gic_mask_irq = gic->irq_mask;
tegra_irq.irq_ack = gic->irq_ack;
#ifdef CONFIG_SMP
tegra_irq.irq_set_affinity = gic->irq_set_affinity;

View file

@ -297,6 +297,12 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
memblock_reserve(__pa(_stext), _end - _stext);
#endif
#ifdef CONFIG_BLK_DEV_INITRD
if (phys_initrd_size &&
memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) {
pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region - disabling initrd\n",
phys_initrd_start, phys_initrd_size);
phys_initrd_start = phys_initrd_size = 0;
}
if (phys_initrd_size) {
memblock_reserve(phys_initrd_start, phys_initrd_size);

View file

@ -8,6 +8,7 @@
#ifndef __ASM_AVR32_PGALLOC_H
#define __ASM_AVR32_PGALLOC_H
#include <linux/mm.h>
#include <linux/quicklist.h>
#include <asm/page.h>
#include <asm/pgtable.h>

View file

@ -14,7 +14,7 @@
#include <linux/io.h>
#include <linux/sh_timer.h>
#include <linux/serial_sci.h>
#include <asm/machtypes.h>
#include <generated/machtypes.h>
static struct resource rtc_resources[] = {
[0] = {
@ -255,12 +255,17 @@ static struct platform_device *sh7750_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
struct platform_device *dev[1];
if (mach_is_rts7751r2d()) {
scif_platform_data.scscr |= SCSCR_CKE1;
early_platform_add_devices(&scif_device, 1);
dev[0] = &scif_device;
early_platform_add_devices(dev, 1);
} else {
early_platform_add_devices(&sci_device, 1);
early_platform_add_devices(&scif_device, 1);
dev[0] = &sci_device;
early_platform_add_devices(dev, 1);
dev[0] = &scif_device;
early_platform_add_devices(dev, 1);
}
early_platform_add_devices(sh7750_early_devices,

View file

@ -273,34 +273,34 @@ do { \
typeof(var) pxo_new__ = (nval); \
switch (sizeof(var)) { \
case 1: \
asm("\n1:mov "__percpu_arg(1)",%%al" \
"\n\tcmpxchgb %2, "__percpu_arg(1) \
asm("\n\tmov "__percpu_arg(1)",%%al" \
"\n1:\tcmpxchgb %2, "__percpu_arg(1) \
"\n\tjnz 1b" \
: "=a" (pxo_ret__), "+m" (var) \
: "=&a" (pxo_ret__), "+m" (var) \
: "q" (pxo_new__) \
: "memory"); \
break; \
case 2: \
asm("\n1:mov "__percpu_arg(1)",%%ax" \
"\n\tcmpxchgw %2, "__percpu_arg(1) \
asm("\n\tmov "__percpu_arg(1)",%%ax" \
"\n1:\tcmpxchgw %2, "__percpu_arg(1) \
"\n\tjnz 1b" \
: "=a" (pxo_ret__), "+m" (var) \
: "=&a" (pxo_ret__), "+m" (var) \
: "r" (pxo_new__) \
: "memory"); \
break; \
case 4: \
asm("\n1:mov "__percpu_arg(1)",%%eax" \
"\n\tcmpxchgl %2, "__percpu_arg(1) \
asm("\n\tmov "__percpu_arg(1)",%%eax" \
"\n1:\tcmpxchgl %2, "__percpu_arg(1) \
"\n\tjnz 1b" \
: "=a" (pxo_ret__), "+m" (var) \
: "=&a" (pxo_ret__), "+m" (var) \
: "r" (pxo_new__) \
: "memory"); \
break; \
case 8: \
asm("\n1:mov "__percpu_arg(1)",%%rax" \
"\n\tcmpxchgq %2, "__percpu_arg(1) \
asm("\n\tmov "__percpu_arg(1)",%%rax" \
"\n1:\tcmpxchgq %2, "__percpu_arg(1) \
"\n\tjnz 1b" \
: "=a" (pxo_ret__), "+m" (var) \
: "=&a" (pxo_ret__), "+m" (var) \
: "r" (pxo_new__) \
: "memory"); \
break; \

View file

@ -1,22 +0,0 @@
#ifndef _ASM_X86_SYSTEM_64_H
#define _ASM_X86_SYSTEM_64_H
#include <asm/segment.h>
#include <asm/cmpxchg.h>
static inline unsigned long read_cr8(void)
{
unsigned long cr8;
asm volatile("movq %%cr8,%0" : "=r" (cr8));
return cr8;
}
static inline void write_cr8(unsigned long val)
{
asm volatile("movq %0,%%cr8" :: "r" (val) : "memory");
}
#include <linux/irqflags.h>
#endif /* _ASM_X86_SYSTEM_64_H */

View file

@ -149,13 +149,13 @@ void dump_trace(struct task_struct *task,
unsigned used = 0;
struct thread_info *tinfo;
int graph = 0;
unsigned long dummy;
unsigned long bp;
if (!task)
task = current;
if (!stack) {
unsigned long dummy;
stack = &dummy;
if (task && task != current)
stack = (unsigned long *)task->thread.sp;

View file

@ -241,21 +241,15 @@ void __init xen_build_dynamic_phys_to_machine(void)
* As long as the mfn_list has enough entries to completely
* fill a p2m page, pointing into the array is ok. But if
* not the entries beyond the last pfn will be undefined.
* And guessing that the 'what-ever-there-is' does not take it
* too kindly when changing it to invalid markers, a new page
* is allocated, initialized and filled with the valid part.
*/
if (unlikely(pfn + P2M_PER_PAGE > max_pfn)) {
unsigned long p2midx;
unsigned long *p2m = extend_brk(PAGE_SIZE, PAGE_SIZE);
p2m_init(p2m);
for (p2midx = 0; pfn + p2midx < max_pfn; p2midx++) {
p2m[p2midx] = mfn_list[pfn + p2midx];
}
p2m_top[topidx][mididx] = p2m;
} else
p2m_top[topidx][mididx] = &mfn_list[pfn];
p2midx = max_pfn % P2M_PER_PAGE;
for ( ; p2midx < P2M_PER_PAGE; p2midx++)
mfn_list[pfn + p2midx] = INVALID_P2M_ENTRY;
}
p2m_top[topidx][mididx] = &mfn_list[pfn];
}
m2p_override_init();

View file

@ -179,8 +179,13 @@ char * __init xen_memory_setup(void)
e820.nr_map = 0;
xen_extra_mem_start = mem_end;
for (i = 0; i < memmap.nr_entries; i++) {
unsigned long long end = map[i].addr + map[i].size;
unsigned long long end;
/* Guard against non-page aligned E820 entries. */
if (map[i].type == E820_RAM)
map[i].size -= (map[i].size + map[i].addr) % PAGE_SIZE;
end = map[i].addr + map[i].size;
if (map[i].type == E820_RAM && end > mem_end) {
/* RAM off the end - may be partially included */
u64 delta = min(map[i].size, end - mem_end);
@ -350,6 +355,7 @@ void __init xen_arch_setup(void)
boot_cpu_data.hlt_works_ok = 1;
#endif
pm_idle = default_idle;
boot_option_idle_override = IDLE_HALT;
fiddle_vdso();
}

View file

@ -260,6 +260,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@ -379,6 +380,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */
{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */
{ PCI_DEVICE(0x1b4b, 0x9123),
.class = PCI_CLASS_STORAGE_SATA_AHCI,
.class_mask = 0xffffff,
.driver_data = board_ahci_yes_fbs }, /* 88se9128 */
/* Promise */

View file

@ -4138,6 +4138,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
* device and controller are SATA.
*/
{ "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER },
{ "PIONEER DVD-RW DVR-212D", "1.28", ATA_HORKAGE_NOSETXFER },
/* End Marker */
{ }

View file

@ -1099,9 +1099,9 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
struct request_queue *q = sdev->request_queue;
void *buf;
/* set the min alignment and padding */
blk_queue_update_dma_alignment(sdev->request_queue,
ATA_DMA_PAD_SZ - 1);
sdev->sector_size = ATA_SECT_SIZE;
/* set DMA padding */
blk_queue_update_dma_pad(sdev->request_queue,
ATA_DMA_PAD_SZ - 1);
@ -1115,13 +1115,25 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN);
} else {
/* ATA devices must be sector aligned */
sdev->sector_size = ata_id_logical_sector_size(dev->id);
blk_queue_update_dma_alignment(sdev->request_queue,
sdev->sector_size - 1);
sdev->manage_start_stop = 1;
}
/*
* ata_pio_sectors() expects buffer for each sector to not cross
* page boundary. Enforce it by requiring buffers to be sector
* aligned, which works iff sector_size is not larger than
* PAGE_SIZE. ATAPI devices also need the alignment as
* IDENTIFY_PACKET is executed as ATA_PROT_PIO.
*/
if (sdev->sector_size > PAGE_SIZE)
ata_dev_printk(dev, KERN_WARNING,
"sector_size=%u > PAGE_SIZE, PIO may malfunction\n",
sdev->sector_size);
blk_queue_update_dma_alignment(sdev->request_queue,
sdev->sector_size - 1);
if (dev->flags & ATA_DFLAG_AN)
set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events);

View file

@ -25,7 +25,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt366"
#define DRV_VERSION "0.6.9"
#define DRV_VERSION "0.6.10"
struct hpt_clock {
u8 xfer_mode;
@ -160,8 +160,8 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr,
while (list[i] != NULL) {
if (!strcmp(list[i], model_num)) {
printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n",
modestr, list[i]);
pr_warning(DRV_NAME ": %s is not supported for %s.\n",
modestr, list[i]);
return 1;
}
i++;

View file

@ -24,7 +24,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt37x"
#define DRV_VERSION "0.6.18"
#define DRV_VERSION "0.6.22"
struct hpt_clock {
u8 xfer_speed;
@ -229,8 +229,8 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr,
while (list[i] != NULL) {
if (!strcmp(list[i], model_num)) {
printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n",
modestr, list[i]);
pr_warning(DRV_NAME ": %s is not supported for %s.\n",
modestr, list[i]);
return 1;
}
i++;
@ -642,7 +642,6 @@ static struct ata_port_operations hpt372_port_ops = {
static struct ata_port_operations hpt374_fn1_port_ops = {
.inherits = &hpt372_port_ops,
.cable_detect = hpt374_fn1_cable_detect,
.prereset = hpt37x_pre_reset,
};
/**
@ -803,7 +802,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
.udma_mask = ATA_UDMA6,
.port_ops = &hpt302_port_ops
};
/* HPT374 - UDMA100, function 1 uses different prereset method */
/* HPT374 - UDMA100, function 1 uses different cable_detect method */
static const struct ata_port_info info_hpt374_fn0 = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
@ -838,7 +837,8 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
if (rc)
return rc;
if (dev->device == PCI_DEVICE_ID_TTI_HPT366) {
switch (dev->device) {
case PCI_DEVICE_ID_TTI_HPT366:
/* May be a later chip in disguise. Check */
/* Older chips are in the HPT366 driver. Ignore them */
if (rev < 3)
@ -863,54 +863,50 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
chip_table = &hpt372;
break;
default:
printk(KERN_ERR "pata_hpt37x: Unknown HPT366 subtype, "
pr_err(DRV_NAME ": Unknown HPT366 subtype, "
"please report (%d).\n", rev);
return -ENODEV;
}
} else {
switch (dev->device) {
case PCI_DEVICE_ID_TTI_HPT372:
/* 372N if rev >= 2 */
if (rev >= 2)
return -ENODEV;
ppi[0] = &info_hpt372;
chip_table = &hpt372a;
break;
case PCI_DEVICE_ID_TTI_HPT302:
/* 302N if rev > 1 */
if (rev > 1)
return -ENODEV;
ppi[0] = &info_hpt302;
/* Check this */
chip_table = &hpt302;
break;
case PCI_DEVICE_ID_TTI_HPT371:
if (rev > 1)
return -ENODEV;
ppi[0] = &info_hpt302;
chip_table = &hpt371;
/*
* Single channel device, master is not present
* but the BIOS (or us for non x86) must mark it
* absent
*/
pci_read_config_byte(dev, 0x50, &mcr1);
mcr1 &= ~0x04;
pci_write_config_byte(dev, 0x50, mcr1);
break;
case PCI_DEVICE_ID_TTI_HPT374:
chip_table = &hpt374;
if (!(PCI_FUNC(dev->devfn) & 1))
*ppi = &info_hpt374_fn0;
else
*ppi = &info_hpt374_fn1;
break;
default:
printk(KERN_ERR
"pata_hpt37x: PCI table is bogus, please report (%d).\n",
dev->device);
return -ENODEV;
}
break;
case PCI_DEVICE_ID_TTI_HPT372:
/* 372N if rev >= 2 */
if (rev >= 2)
return -ENODEV;
ppi[0] = &info_hpt372;
chip_table = &hpt372a;
break;
case PCI_DEVICE_ID_TTI_HPT302:
/* 302N if rev > 1 */
if (rev > 1)
return -ENODEV;
ppi[0] = &info_hpt302;
/* Check this */
chip_table = &hpt302;
break;
case PCI_DEVICE_ID_TTI_HPT371:
if (rev > 1)
return -ENODEV;
ppi[0] = &info_hpt302;
chip_table = &hpt371;
/*
* Single channel device, master is not present but the BIOS
* (or us for non x86) must mark it absent
*/
pci_read_config_byte(dev, 0x50, &mcr1);
mcr1 &= ~0x04;
pci_write_config_byte(dev, 0x50, mcr1);
break;
case PCI_DEVICE_ID_TTI_HPT374:
chip_table = &hpt374;
if (!(PCI_FUNC(dev->devfn) & 1))
*ppi = &info_hpt374_fn0;
else
*ppi = &info_hpt374_fn1;
break;
default:
pr_err(DRV_NAME ": PCI table is bogus, please report (%d).\n",
dev->device);
return -ENODEV;
}
/* Ok so this is a chip we support */
@ -957,8 +953,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
u8 sr;
u32 total = 0;
printk(KERN_WARNING
"pata_hpt37x: BIOS has not set timing clocks.\n");
pr_warning(DRV_NAME ": BIOS has not set timing clocks.\n");
/* This is the process the HPT371 BIOS is reported to use */
for (i = 0; i < 128; i++) {
@ -1014,7 +1009,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
(f_high << 16) | f_low | 0x100);
}
if (adjust == 8) {
printk(KERN_ERR "pata_hpt37x: DPLL did not stabilize!\n");
pr_err(DRV_NAME ": DPLL did not stabilize!\n");
return -ENODEV;
}
if (dpll == 3)
@ -1022,8 +1017,8 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
else
private_data = (void *)hpt37x_timings_50;
printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using %dMHz DPLL.\n",
MHz[clock_slot], MHz[dpll]);
pr_info(DRV_NAME ": bus clock %dMHz, using %dMHz DPLL.\n",
MHz[clock_slot], MHz[dpll]);
} else {
private_data = (void *)chip_table->clocks[clock_slot];
/*
@ -1036,8 +1031,9 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
ppi[0] = &info_hpt370_33;
if (clock_slot < 2 && ppi[0] == &info_hpt370a)
ppi[0] = &info_hpt370a_33;
printk(KERN_INFO "pata_hpt37x: %s using %dMHz bus clock.\n",
chip_table->name, MHz[clock_slot]);
pr_info(DRV_NAME ": %s using %dMHz bus clock.\n",
chip_table->name, MHz[clock_slot]);
}
/* Now kick off ATA set up */

View file

@ -25,7 +25,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt3x2n"
#define DRV_VERSION "0.3.13"
#define DRV_VERSION "0.3.14"
enum {
HPT_PCI_FAST = (1 << 31),
@ -418,7 +418,7 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev)
u16 sr;
u32 total = 0;
printk(KERN_WARNING "pata_hpt3x2n: BIOS clock data not set.\n");
pr_warning(DRV_NAME ": BIOS clock data not set.\n");
/* This is the process the HPT371 BIOS is reported to use */
for (i = 0; i < 128; i++) {
@ -528,8 +528,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
ppi[0] = &info_hpt372n;
break;
default:
printk(KERN_ERR
"pata_hpt3x2n: PCI table is bogus please report (%d).\n",
pr_err(DRV_NAME ": PCI table is bogus, please report (%d).\n",
dev->device);
return -ENODEV;
}
@ -579,12 +578,11 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low);
}
if (adjust == 8) {
printk(KERN_ERR "pata_hpt3x2n: DPLL did not stabilize!\n");
pr_err(DRV_NAME ": DPLL did not stabilize!\n");
return -ENODEV;
}
printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using 66MHz DPLL.\n",
pci_mhz);
pr_info(DRV_NAME ": bus clock %dMHz, using 66MHz DPLL.\n", pci_mhz);
/*
* Set our private data up. We only need a few flags

View file

@ -610,7 +610,7 @@ static struct scsi_host_template mpc52xx_ata_sht = {
};
static struct ata_port_operations mpc52xx_ata_port_ops = {
.inherits = &ata_sff_port_ops,
.inherits = &ata_bmdma_port_ops,
.sff_dev_select = mpc52xx_ata_dev_select,
.set_piomode = mpc52xx_ata_set_piomode,
.set_dmamode = mpc52xx_ata_set_dmamode,

View file

@ -151,7 +151,7 @@ static int fetch_stats(struct atm_dev *dev,struct idt77105_stats __user *arg,int
spin_unlock_irqrestore(&idt77105_priv_lock, flags);
if (arg == NULL)
return 0;
return copy_to_user(arg, &PRIV(dev)->stats,
return copy_to_user(arg, &stats,
sizeof(struct idt77105_stats)) ? -EFAULT : 0;
}

View file

@ -407,12 +407,15 @@ static int rpm_suspend(struct device *dev, int rpmflags)
goto out;
}
/* Maybe the parent is now able to suspend. */
if (parent && !parent->power.ignore_children && !dev->power.irq_safe) {
spin_unlock_irq(&dev->power.lock);
spin_unlock(&dev->power.lock);
pm_request_idle(parent);
spin_lock(&parent->power.lock);
rpm_idle(parent, RPM_ASYNC);
spin_unlock(&parent->power.lock);
spin_lock_irq(&dev->power.lock);
spin_lock(&dev->power.lock);
}
out:

View file

@ -47,33 +47,16 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);
#define USB_REQ_DFU_DNLOAD 1
#define BULK_SIZE 4096
struct ath3k_data {
struct usb_device *udev;
u8 *fw_data;
u32 fw_size;
u32 fw_sent;
};
static int ath3k_load_firmware(struct ath3k_data *data,
unsigned char *firmware,
int count)
static int ath3k_load_firmware(struct usb_device *udev,
const struct firmware *firmware)
{
u8 *send_buf;
int err, pipe, len, size, sent = 0;
int count = firmware->size;
BT_DBG("ath3k %p udev %p", data, data->udev);
BT_DBG("udev %p", udev);
pipe = usb_sndctrlpipe(data->udev, 0);
if ((usb_control_msg(data->udev, pipe,
USB_REQ_DFU_DNLOAD,
USB_TYPE_VENDOR, 0, 0,
firmware, 20, USB_CTRL_SET_TIMEOUT)) < 0) {
BT_ERR("Can't change to loading configuration err");
return -EBUSY;
}
sent += 20;
count -= 20;
pipe = usb_sndctrlpipe(udev, 0);
send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
if (!send_buf) {
@ -81,12 +64,23 @@ static int ath3k_load_firmware(struct ath3k_data *data,
return -ENOMEM;
}
memcpy(send_buf, firmware->data, 20);
if ((err = usb_control_msg(udev, pipe,
USB_REQ_DFU_DNLOAD,
USB_TYPE_VENDOR, 0, 0,
send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) {
BT_ERR("Can't change to loading configuration err");
goto error;
}
sent += 20;
count -= 20;
while (count) {
size = min_t(uint, count, BULK_SIZE);
pipe = usb_sndbulkpipe(data->udev, 0x02);
memcpy(send_buf, firmware + sent, size);
pipe = usb_sndbulkpipe(udev, 0x02);
memcpy(send_buf, firmware->data + sent, size);
err = usb_bulk_msg(data->udev, pipe, send_buf, size,
err = usb_bulk_msg(udev, pipe, send_buf, size,
&len, 3000);
if (err || (len != size)) {
@ -112,57 +106,28 @@ static int ath3k_probe(struct usb_interface *intf,
{
const struct firmware *firmware;
struct usb_device *udev = interface_to_usbdev(intf);
struct ath3k_data *data;
int size;
BT_DBG("intf %p id %p", intf, id);
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
return -ENODEV;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->udev = udev;
if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) {
kfree(data);
return -EIO;
}
size = max_t(uint, firmware->size, 4096);
data->fw_data = kmalloc(size, GFP_KERNEL);
if (!data->fw_data) {
if (ath3k_load_firmware(udev, firmware)) {
release_firmware(firmware);
kfree(data);
return -ENOMEM;
}
memcpy(data->fw_data, firmware->data, firmware->size);
data->fw_size = firmware->size;
data->fw_sent = 0;
release_firmware(firmware);
usb_set_intfdata(intf, data);
if (ath3k_load_firmware(data, data->fw_data, data->fw_size)) {
usb_set_intfdata(intf, NULL);
kfree(data->fw_data);
kfree(data);
return -EIO;
}
release_firmware(firmware);
return 0;
}
static void ath3k_disconnect(struct usb_interface *intf)
{
struct ath3k_data *data = usb_get_intfdata(intf);
BT_DBG("ath3k_disconnect intf %p", intf);
kfree(data->fw_data);
kfree(data);
}
static struct usb_driver ath3k_driver = {

View file

@ -6310,6 +6310,9 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb)
static bool
apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct dcb_table *dcb = &dev_priv->vbios.dcb;
/* Dell Precision M6300
* DCB entry 2: 02025312 00000010
* DCB entry 3: 02026312 00000020
@ -6327,6 +6330,18 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
return false;
}
/* GeForce3 Ti 200
*
* DCB reports an LVDS output that should be TMDS:
* DCB entry 1: f2005014 ffffffff
*/
if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) {
if (*conn == 0xf2005014 && *conf == 0xffffffff) {
fabricate_dcb_output(dcb, OUTPUT_TMDS, 1, 1, 1);
return false;
}
}
return true;
}

View file

@ -848,9 +848,6 @@ extern void nv10_mem_put_tile_region(struct drm_device *dev,
struct nouveau_fence *fence);
extern const struct ttm_mem_type_manager_func nouveau_vram_manager;
/* nvc0_vram.c */
extern const struct ttm_mem_type_manager_func nvc0_vram_manager;
/* nouveau_notifier.c */
extern int nouveau_notifier_init_channel(struct nouveau_channel *);
extern void nouveau_notifier_takedown_channel(struct nouveau_channel *);

View file

@ -265,8 +265,8 @@ nouveau_temp_probe_i2c(struct drm_device *dev)
struct i2c_board_info info[] = {
{ I2C_BOARD_INFO("w83l785ts", 0x2d) },
{ I2C_BOARD_INFO("w83781d", 0x2d) },
{ I2C_BOARD_INFO("f75375", 0x2e) },
{ I2C_BOARD_INFO("adt7473", 0x2e) },
{ I2C_BOARD_INFO("f75375", 0x2e) },
{ I2C_BOARD_INFO("lm99", 0x4c) },
{ }
};

View file

@ -256,6 +256,7 @@ nv50_graph_destroy_context(struct nouveau_channel *chan)
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20;
unsigned long flags;
@ -265,6 +266,7 @@ nv50_graph_destroy_context(struct nouveau_channel *chan)
return;
spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
pfifo->reassign(dev, false);
pgraph->fifo_access(dev, false);
if (pgraph->channel(dev) == chan)
@ -275,6 +277,7 @@ nv50_graph_destroy_context(struct nouveau_channel *chan)
dev_priv->engine.instmem.flush(dev);
pgraph->fifo_access(dev, true);
pfifo->reassign(dev, true);
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
nouveau_gpuobj_ref(NULL, &chan->ramin_grctx);

View file

@ -45,11 +45,6 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
}
if (phys & 1) {
if (dev_priv->vram_sys_base) {
phys += dev_priv->vram_sys_base;
phys |= 0x30;
}
if (coverage <= 32 * 1024 * 1024)
phys |= 0x60;
else if (coverage <= 64 * 1024 * 1024)

View file

@ -31,6 +31,7 @@
#include "nvc0_graph.h"
static void nvc0_graph_isr(struct drm_device *);
static void nvc0_runk140_isr(struct drm_device *);
static int nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan);
void
@ -281,6 +282,7 @@ nvc0_graph_destroy(struct drm_device *dev)
return;
nouveau_irq_unregister(dev, 12);
nouveau_irq_unregister(dev, 25);
nouveau_gpuobj_ref(NULL, &priv->unk4188b8);
nouveau_gpuobj_ref(NULL, &priv->unk4188b4);
@ -390,6 +392,7 @@ nvc0_graph_create(struct drm_device *dev)
}
nouveau_irq_register(dev, 12, nvc0_graph_isr);
nouveau_irq_register(dev, 25, nvc0_runk140_isr);
NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */
NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */
NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */
@ -512,8 +515,8 @@ nvc0_graph_init_gpc_1(struct drm_device *dev)
nv_wr32(dev, TP_UNIT(gpc, tp, 0x224), 0xc0000000);
nv_wr32(dev, TP_UNIT(gpc, tp, 0x48c), 0xc0000000);
nv_wr32(dev, TP_UNIT(gpc, tp, 0x084), 0xc0000000);
nv_wr32(dev, TP_UNIT(gpc, tp, 0xe44), 0x001ffffe);
nv_wr32(dev, TP_UNIT(gpc, tp, 0xe4c), 0x0000000f);
nv_wr32(dev, TP_UNIT(gpc, tp, 0x644), 0x001ffffe);
nv_wr32(dev, TP_UNIT(gpc, tp, 0x64c), 0x0000000f);
}
nv_wr32(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
@ -777,3 +780,19 @@ nvc0_graph_isr(struct drm_device *dev)
nv_wr32(dev, 0x400500, 0x00010001);
}
static void
nvc0_runk140_isr(struct drm_device *dev)
{
u32 units = nv_rd32(dev, 0x00017c) & 0x1f;
while (units) {
u32 unit = ffs(units) - 1;
u32 reg = 0x140000 + unit * 0x2000;
u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0);
u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0);
NV_INFO(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1);
units &= ~(1 << unit);
}
}

View file

@ -1830,7 +1830,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
for (tp = 0, id = 0; tp < 4; tp++) {
for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
if (tp <= priv->tp_nr[gpc]) {
if (tp < priv->tp_nr[gpc]) {
nv_wr32(dev, TP_UNIT(gpc, tp, 0x698), id);
nv_wr32(dev, TP_UNIT(gpc, tp, 0x4e8), id);
nv_wr32(dev, GPC_UNIT(gpc, 0x0c10 + tp * 4), id);

View file

@ -994,6 +994,7 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc,
struct radeon_bo *rbo;
uint64_t fb_location;
uint32_t fb_format, fb_pitch_pixels, tiling_flags;
u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE);
int r;
/* no fb bound */
@ -1045,11 +1046,17 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc,
case 16:
fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565));
#ifdef __BIG_ENDIAN
fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
#endif
break;
case 24:
case 32:
fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888));
#ifdef __BIG_ENDIAN
fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);
#endif
break;
default:
DRM_ERROR("Unsupported screen depth %d\n",
@ -1094,6 +1101,7 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
(u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);
WREG32(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
WREG32(EVERGREEN_GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap);
WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
@ -1150,6 +1158,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
struct drm_framebuffer *target_fb;
uint64_t fb_location;
uint32_t fb_format, fb_pitch_pixels, tiling_flags;
u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
int r;
/* no fb bound */
@ -1203,12 +1212,18 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
fb_format =
AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
AVIVO_D1GRPH_CONTROL_16BPP_RGB565;
#ifdef __BIG_ENDIAN
fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT;
#endif
break;
case 24:
case 32:
fb_format =
AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |
AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;
#ifdef __BIG_ENDIAN
fb_swap = R600_D1GRPH_SWAP_ENDIAN_32BIT;
#endif
break;
default:
DRM_ERROR("Unsupported screen depth %d\n",
@ -1248,6 +1263,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS +
radeon_crtc->crtc_offset, (u32) fb_location);
WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
if (rdev->family >= CHIP_R600)
WREG32(R600_D1GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap);
WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);

View file

@ -187,9 +187,9 @@ static int dp_link_clock_for_mode_clock(u8 dpcd[DP_DPCD_SIZE], int mode_clock)
int dp_mode_valid(u8 dpcd[DP_DPCD_SIZE], int mode_clock)
{
int lanes = dp_lanes_for_mode_clock(dpcd, mode_clock);
int bw = dp_lanes_for_mode_clock(dpcd, mode_clock);
int dp_clock = dp_link_clock_for_mode_clock(dpcd, mode_clock);
if ((lanes == 0) || (bw == 0))
if ((lanes == 0) || (dp_clock == 0))
return MODE_CLOCK_HIGH;
return MODE_OK;

View file

@ -232,7 +232,7 @@ draw_auto(struct radeon_device *rdev)
}
/* emits 30 */
/* emits 34 */
static void
set_default_state(struct radeon_device *rdev)
{
@ -245,6 +245,8 @@ set_default_state(struct radeon_device *rdev)
int num_hs_threads, num_ls_threads;
int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries;
int num_hs_stack_entries, num_ls_stack_entries;
u64 gpu_addr;
int dwords;
switch (rdev->family) {
case CHIP_CEDAR:
@ -497,6 +499,14 @@ set_default_state(struct radeon_device *rdev)
radeon_ring_write(rdev, 0x00000000);
radeon_ring_write(rdev, 0x00000000);
/* emit an IB pointing at default state */
dwords = ALIGN(rdev->r600_blit.state_len, 0x10);
gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset;
radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
radeon_ring_write(rdev, gpu_addr & 0xFFFFFFFC);
radeon_ring_write(rdev, upper_32_bits(gpu_addr) & 0xFF);
radeon_ring_write(rdev, dwords);
}
static inline uint32_t i2f(uint32_t input)
@ -527,8 +537,10 @@ static inline uint32_t i2f(uint32_t input)
int evergreen_blit_init(struct radeon_device *rdev)
{
u32 obj_size;
int r;
int r, dwords;
void *ptr;
u32 packet2s[16];
int num_packet2s = 0;
/* pin copy shader into vram if already initialized */
if (rdev->r600_blit.shader_obj)
@ -536,8 +548,17 @@ int evergreen_blit_init(struct radeon_device *rdev)
mutex_init(&rdev->r600_blit.mutex);
rdev->r600_blit.state_offset = 0;
rdev->r600_blit.state_len = 0;
obj_size = 0;
rdev->r600_blit.state_len = evergreen_default_size;
dwords = rdev->r600_blit.state_len;
while (dwords & 0xf) {
packet2s[num_packet2s++] = PACKET2(0);
dwords++;
}
obj_size = dwords * 4;
obj_size = ALIGN(obj_size, 256);
rdev->r600_blit.vs_offset = obj_size;
obj_size += evergreen_vs_size * 4;
@ -567,6 +588,12 @@ int evergreen_blit_init(struct radeon_device *rdev)
return r;
}
memcpy_toio(ptr + rdev->r600_blit.state_offset,
evergreen_default_state, rdev->r600_blit.state_len * 4);
if (num_packet2s)
memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4),
packet2s, num_packet2s * 4);
memcpy(ptr + rdev->r600_blit.vs_offset, evergreen_vs, evergreen_vs_size * 4);
memcpy(ptr + rdev->r600_blit.ps_offset, evergreen_ps, evergreen_ps_size * 4);
radeon_bo_kunmap(rdev->r600_blit.shader_obj);
@ -652,7 +679,7 @@ int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)
/* calculate number of loops correctly */
ring_size = num_loops * dwords_per_loop;
/* set default + shaders */
ring_size += 46; /* shaders + def state */
ring_size += 50; /* shaders + def state */
ring_size += 10; /* fence emit for VB IB */
ring_size += 5; /* done copy */
ring_size += 10; /* fence emit for done copy */
@ -660,7 +687,7 @@ int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)
if (r)
return r;
set_default_state(rdev); /* 30 */
set_default_state(rdev); /* 34 */
set_shaders(rdev); /* 16 */
return 0;
}

View file

@ -1031,8 +1031,8 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
WREG32(RADEON_CP_CSQ_MODE,
REG_SET(RADEON_INDIRECT2_START, indirect2_start) |
REG_SET(RADEON_INDIRECT1_START, indirect1_start));
WREG32(0x718, 0);
WREG32(0x744, 0x00004D4D);
WREG32(RADEON_CP_RB_WPTR_DELAY, 0);
WREG32(RADEON_CP_CSQ_MODE, 0x00004D4D);
WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM);
radeon_ring_start(rdev);
r = radeon_ring_test(rdev);
@ -2347,10 +2347,10 @@ void r100_vga_set_state(struct radeon_device *rdev, bool state)
temp = RREG32(RADEON_CONFIG_CNTL);
if (state == false) {
temp &= ~(1<<8);
temp |= (1<<9);
temp &= ~RADEON_CFG_VGA_RAM_EN;
temp |= RADEON_CFG_VGA_IO_DIS;
} else {
temp &= ~(1<<9);
temp &= ~RADEON_CFG_VGA_IO_DIS;
}
WREG32(RADEON_CONFIG_CNTL, temp);
}

View file

@ -69,6 +69,9 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev)
mb();
}
#define R300_PTE_WRITEABLE (1 << 2)
#define R300_PTE_READABLE (1 << 3)
int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
{
void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
@ -78,7 +81,7 @@ int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
}
addr = (lower_32_bits(addr) >> 8) |
((upper_32_bits(addr) & 0xff) << 24) |
0xc;
R300_PTE_WRITEABLE | R300_PTE_READABLE;
/* on x86 we want this to be CPU endian, on powerpc
* on powerpc without HW swappers, it'll get swapped on way
* into VRAM - so no need for cpu_to_le32 on VRAM tables */
@ -135,7 +138,7 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev)
WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_start);
WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0);
/* Clear error */
WREG32_PCIE(0x18, 0);
WREG32_PCIE(RADEON_PCIE_TX_GART_ERROR, 0);
tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
tmp |= RADEON_PCIE_TX_GART_EN;
tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;

View file

@ -96,7 +96,7 @@ void r420_pipes_init(struct radeon_device *rdev)
"programming pipes. Bad things might happen.\n");
}
/* get max number of pipes */
gb_pipe_select = RREG32(0x402C);
gb_pipe_select = RREG32(R400_GB_PIPE_SELECT);
num_pipes = ((gb_pipe_select >> 12) & 3) + 1;
/* SE chips have 1 pipe */

View file

@ -79,8 +79,8 @@ static void r520_gpu_init(struct radeon_device *rdev)
WREG32(0x4128, 0xFF);
}
r420_pipes_init(rdev);
gb_pipe_select = RREG32(0x402C);
tmp = RREG32(0x170C);
gb_pipe_select = RREG32(R400_GB_PIPE_SELECT);
tmp = RREG32(R300_DST_PIPE_CONFIG);
pipe_select_current = (tmp >> 2) & 3;
tmp = (1 << pipe_select_current) |
(((gb_pipe_select >> 8) & 0xF) << 4);

View file

@ -81,7 +81,11 @@
#define R600_MEDIUM_VID_LOWER_GPIO_CNTL 0x720
#define R600_LOW_VID_LOWER_GPIO_CNTL 0x724
#define R600_D1GRPH_SWAP_CONTROL 0x610C
# define R600_D1GRPH_SWAP_ENDIAN_NONE (0 << 0)
# define R600_D1GRPH_SWAP_ENDIAN_16BIT (1 << 0)
# define R600_D1GRPH_SWAP_ENDIAN_32BIT (2 << 0)
# define R600_D1GRPH_SWAP_ENDIAN_64BIT (3 << 0)
#define R600_HDP_NONSURFACE_BASE 0x2c04

View file

@ -641,7 +641,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
switch (connector->connector_type) {
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
if (drm_detect_monitor_audio(radeon_connector->edid)) {
if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
/* fix me */
if (ASIC_IS_DCE4(rdev))
return ATOM_ENCODER_MODE_DVI;
@ -655,7 +655,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
case DRM_MODE_CONNECTOR_DVID:
case DRM_MODE_CONNECTOR_HDMIA:
default:
if (drm_detect_monitor_audio(radeon_connector->edid)) {
if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
/* fix me */
if (ASIC_IS_DCE4(rdev))
return ATOM_ENCODER_MODE_DVI;
@ -673,7 +673,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
return ATOM_ENCODER_MODE_DP;
else if (drm_detect_monitor_audio(radeon_connector->edid)) {
else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
/* fix me */
if (ASIC_IS_DCE4(rdev))
return ATOM_ENCODER_MODE_DVI;

View file

@ -247,6 +247,8 @@ void radeon_driver_preclose_kms(struct drm_device *dev,
struct radeon_device *rdev = dev->dev_private;
if (rdev->hyperz_filp == file_priv)
rdev->hyperz_filp = NULL;
if (rdev->cmask_filp == file_priv)
rdev->cmask_filp = NULL;
}
/*

View file

@ -375,6 +375,8 @@
#define RADEON_CONFIG_APER_SIZE 0x0108
#define RADEON_CONFIG_BONDS 0x00e8
#define RADEON_CONFIG_CNTL 0x00e0
# define RADEON_CFG_VGA_RAM_EN (1 << 8)
# define RADEON_CFG_VGA_IO_DIS (1 << 9)
# define RADEON_CFG_ATI_REV_A11 (0 << 16)
# define RADEON_CFG_ATI_REV_A12 (1 << 16)
# define RADEON_CFG_ATI_REV_A13 (2 << 16)

View file

@ -203,6 +203,9 @@ void rs400_gart_fini(struct radeon_device *rdev)
radeon_gart_table_ram_free(rdev);
}
#define RS400_PTE_WRITEABLE (1 << 2)
#define RS400_PTE_READABLE (1 << 3)
int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
{
uint32_t entry;
@ -213,7 +216,7 @@ int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
entry = (lower_32_bits(addr) & PAGE_MASK) |
((upper_32_bits(addr) & 0xff) << 4) |
0xc;
RS400_PTE_WRITEABLE | RS400_PTE_READABLE;
entry = cpu_to_le32(entry);
rdev->gart.table.ram.ptr[i] = entry;
return 0;
@ -226,8 +229,8 @@ int rs400_mc_wait_for_idle(struct radeon_device *rdev)
for (i = 0; i < rdev->usec_timeout; i++) {
/* read MC_STATUS */
tmp = RREG32(0x0150);
if (tmp & (1 << 2)) {
tmp = RREG32(RADEON_MC_STATUS);
if (tmp & RADEON_MC_IDLE) {
return 0;
}
DRM_UDELAY(1);
@ -241,7 +244,7 @@ void rs400_gpu_init(struct radeon_device *rdev)
r420_pipes_init(rdev);
if (rs400_mc_wait_for_idle(rdev)) {
printk(KERN_WARNING "rs400: Failed to wait MC idle while "
"programming pipes. Bad things might happen. %08x\n", RREG32(0x150));
"programming pipes. Bad things might happen. %08x\n", RREG32(RADEON_MC_STATUS));
}
}
@ -300,9 +303,9 @@ static int rs400_debugfs_gart_info(struct seq_file *m, void *data)
seq_printf(m, "MCCFG_AGP_BASE_2 0x%08x\n", tmp);
tmp = RREG32_MC(RS690_MCCFG_AGP_LOCATION);
seq_printf(m, "MCCFG_AGP_LOCATION 0x%08x\n", tmp);
tmp = RREG32_MC(0x100);
tmp = RREG32_MC(RS690_MCCFG_FB_LOCATION);
seq_printf(m, "MCCFG_FB_LOCATION 0x%08x\n", tmp);
tmp = RREG32(0x134);
tmp = RREG32(RS690_HDP_FB_LOCATION);
seq_printf(m, "HDP_FB_LOCATION 0x%08x\n", tmp);
} else {
tmp = RREG32(RADEON_AGP_BASE);

View file

@ -69,13 +69,13 @@ void rv515_ring_start(struct radeon_device *rdev)
ISYNC_CPSCRATCH_IDLEGUI);
radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0));
radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN);
radeon_ring_write(rdev, PACKET0(0x170C, 0));
radeon_ring_write(rdev, 1 << 31);
radeon_ring_write(rdev, PACKET0(R300_DST_PIPE_CONFIG, 0));
radeon_ring_write(rdev, R300_PIPE_AUTO_CONFIG);
radeon_ring_write(rdev, PACKET0(GB_SELECT, 0));
radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, PACKET0(GB_ENABLE, 0));
radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, PACKET0(0x42C8, 0));
radeon_ring_write(rdev, PACKET0(R500_SU_REG_DEST, 0));
radeon_ring_write(rdev, (1 << rdev->num_gb_pipes) - 1);
radeon_ring_write(rdev, PACKET0(VAP_INDEX_OFFSET, 0));
radeon_ring_write(rdev, 0);
@ -153,8 +153,8 @@ void rv515_gpu_init(struct radeon_device *rdev)
}
rv515_vga_render_disable(rdev);
r420_pipes_init(rdev);
gb_pipe_select = RREG32(0x402C);
tmp = RREG32(0x170C);
gb_pipe_select = RREG32(R400_GB_PIPE_SELECT);
tmp = RREG32(R300_DST_PIPE_CONFIG);
pipe_select_current = (tmp >> 2) & 3;
tmp = (1 << pipe_select_current) |
(((gb_pipe_select >> 8) & 0xF) << 4);

View file

@ -1072,6 +1072,7 @@ static int applesmc_create_nodes(struct applesmc_node_group *groups, int num)
node->sda.dev_attr.show = grp->show;
node->sda.dev_attr.store = grp->store;
attr = &node->sda.dev_attr.attr;
sysfs_attr_init(attr);
attr->name = node->name;
attr->mode = S_IRUGO | (grp->store ? S_IWUSR : 0);
ret = sysfs_create_file(&pdev->dev.kobj, attr);

View file

@ -13,6 +13,7 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/dmi.h>
#include <acpi/acpi.h>
#include <acpi/acpixf.h>
@ -22,6 +23,21 @@
#define ATK_HID "ATK0110"
static bool new_if;
module_param(new_if, bool, 0);
MODULE_PARM_DESC(new_if, "Override detection heuristic and force the use of the new ATK0110 interface");
static const struct dmi_system_id __initconst atk_force_new_if[] = {
{
/* Old interface has broken MCH temp monitoring */
.ident = "Asus Sabertooth X58",
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "SABERTOOTH X58")
}
},
{ }
};
/* Minimum time between readings, enforced in order to avoid
* hogging the CPU.
*/
@ -1302,7 +1318,9 @@ static int atk_probe_if(struct atk_data *data)
* analysis of multiple DSDTs indicates that when both interfaces
* are present the new one (GGRP/GITM) is not functional.
*/
if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle)
if (new_if)
dev_info(dev, "Overriding interface detection\n");
if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle && !new_if)
data->old_interface = true;
else if (data->enumerate_handle && data->read_handle &&
data->write_handle)
@ -1420,6 +1438,9 @@ static int __init atk0110_init(void)
return -EBUSY;
}
if (dmi_check_system(atk_force_new_if))
new_if = true;
ret = acpi_bus_register_driver(&atk_driver);
if (ret)
pr_info("acpi_bus_register_driver failed: %d\n", ret);

View file

@ -957,7 +957,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
/* bail if we did not get an IRQ from the bus layer */
if (!dev->irq) {
pr_err("No IRQ. Disabling /dev/freefall\n");
pr_debug("No IRQ. Disabling /dev/freefall\n");
goto out;
}

View file

@ -86,7 +86,7 @@ static const u32 tegra_kbc_default_keymap[] = {
KEY(0, 5, KEY_Z),
KEY(0, 7, KEY_FN),
KEY(1, 7, KEY_MENU),
KEY(1, 7, KEY_LEFTMETA),
KEY(2, 6, KEY_RIGHTALT),
KEY(2, 7, KEY_LEFTALT),
@ -355,8 +355,8 @@ static void tegra_kbc_config_pins(struct tegra_kbc *kbc)
for (i = 0; i < KBC_MAX_GPIO; i++) {
u32 r_shft = 5 * (i % 6);
u32 c_shft = 4 * (i % 8);
u32 r_mask = 0x1f << r_shift;
u32 c_mask = 0x0f << c_shift;
u32 r_mask = 0x1f << r_shft;
u32 c_mask = 0x0f << c_shft;
u32 r_offs = (i / 6) * 4 + KBC_ROW_CFG0_0;
u32 c_offs = (i / 8) * 4 + KBC_COL_CFG0_0;
u32 row_cfg = readl(kbc->mmio + r_offs);

View file

@ -755,23 +755,26 @@ static int synaptics_reconnect(struct psmouse *psmouse)
{
struct synaptics_data *priv = psmouse->private;
struct synaptics_data old_priv = *priv;
int retry = 0;
int error;
psmouse_reset(psmouse);
do {
psmouse_reset(psmouse);
error = synaptics_detect(psmouse, 0);
} while (error && ++retry < 3);
if (synaptics_detect(psmouse, 0))
if (error)
return -1;
if (retry > 1)
printk(KERN_DEBUG "Synaptics reconnected after %d tries\n",
retry);
if (synaptics_query_hardware(psmouse)) {
printk(KERN_ERR "Unable to query Synaptics hardware.\n");
return -1;
}
if (old_priv.identity != priv->identity ||
old_priv.model_id != priv->model_id ||
old_priv.capabilities != priv->capabilities ||
old_priv.ext_cap != priv->ext_cap)
return -1;
if (synaptics_set_absolute_mode(psmouse)) {
printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
return -1;
@ -782,6 +785,19 @@ static int synaptics_reconnect(struct psmouse *psmouse)
return -1;
}
if (old_priv.identity != priv->identity ||
old_priv.model_id != priv->model_id ||
old_priv.capabilities != priv->capabilities ||
old_priv.ext_cap != priv->ext_cap) {
printk(KERN_ERR "Synaptics hardware appears to be different: "
"id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n",
old_priv.identity, priv->identity,
old_priv.model_id, priv->model_id,
old_priv.capabilities, priv->capabilities,
old_priv.ext_cap, priv->ext_cap);
return -1;
}
return 0;
}

View file

@ -458,21 +458,27 @@ static int ir_getkeycode(struct input_dev *idev,
index = ir_lookup_by_scancode(rc_map, scancode);
}
if (index >= rc_map->len) {
if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
IR_dprintk(1, "unknown key for scancode 0x%04x\n",
scancode);
if (index < rc_map->len) {
entry = &rc_map->scan[index];
ke->index = index;
ke->keycode = entry->keycode;
ke->len = sizeof(entry->scancode);
memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode));
} else if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) {
/*
* We do not really know the valid range of scancodes
* so let's respond with KEY_RESERVED to anything we
* do not have mapping for [yet].
*/
ke->index = index;
ke->keycode = KEY_RESERVED;
} else {
retval = -EINVAL;
goto out;
}
entry = &rc_map->scan[index];
ke->index = index;
ke->keycode = entry->keycode;
ke->len = sizeof(entry->scancode);
memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode));
retval = 0;
out:

View file

@ -462,7 +462,7 @@ static int __devinit sdh_probe(struct platform_device *pdev)
goto out;
}
mmc = mmc_alloc_host(sizeof(*mmc), &pdev->dev);
mmc = mmc_alloc_host(sizeof(struct sdh_host), &pdev->dev);
if (!mmc) {
ret = -ENOMEM;
goto out;

View file

@ -14,6 +14,7 @@
*/
#include <linux/mmc/host.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
@ -827,8 +828,8 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev)
}
host->clk = clk_get(&pdev->dev, "mmc");
if (!host->clk) {
ret = -ENOENT;
if (IS_ERR(host->clk)) {
ret = PTR_ERR(host->clk);
dev_err(&pdev->dev, "Failed to get mmc clock\n");
goto err_free_host;
}

View file

@ -14,6 +14,7 @@
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/highmem.h>
@ -283,19 +284,19 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
u32 remain, success;
/* Calculate how far we are into the transfer */
remain = readl(host->base + MMCIDATACNT) << 2;
remain = readl(host->base + MMCIDATACNT);
success = data->blksz * data->blocks - remain;
dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status);
if (status & MCI_DATACRCFAIL) {
/* Last block was not successful */
host->data_xfered = ((success / data->blksz) - 1 * data->blksz);
host->data_xfered = round_down(success - 1, data->blksz);
data->error = -EILSEQ;
} else if (status & MCI_DATATIMEOUT) {
host->data_xfered = success;
host->data_xfered = round_down(success, data->blksz);
data->error = -ETIMEDOUT;
} else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
host->data_xfered = success;
host->data_xfered = round_down(success, data->blksz);
data->error = -EIO;
}
@ -319,7 +320,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
if (status & MCI_DATABLOCKEND)
dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n");
if (status & MCI_DATAEND) {
if (status & MCI_DATAEND || data->error) {
mmci_stop_data(host);
if (!data->error)
@ -342,15 +343,15 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
host->cmd = NULL;
cmd->resp[0] = readl(base + MMCIRESPONSE0);
cmd->resp[1] = readl(base + MMCIRESPONSE1);
cmd->resp[2] = readl(base + MMCIRESPONSE2);
cmd->resp[3] = readl(base + MMCIRESPONSE3);
if (status & MCI_CMDTIMEOUT) {
cmd->error = -ETIMEDOUT;
} else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) {
cmd->error = -EILSEQ;
} else {
cmd->resp[0] = readl(base + MMCIRESPONSE0);
cmd->resp[1] = readl(base + MMCIRESPONSE1);
cmd->resp[2] = readl(base + MMCIRESPONSE2);
cmd->resp[3] = readl(base + MMCIRESPONSE3);
}
if (!cmd->data || cmd->error) {

View file

@ -277,10 +277,43 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
host->clock = clock;
}
/**
* sdhci_s3c_platform_8bit_width - support 8bit buswidth
* @host: The SDHCI host being queried
* @width: MMC_BUS_WIDTH_ macro for the bus width being requested
*
* We have 8-bit width support but is not a v3 controller.
* So we add platform_8bit_width() and support 8bit width.
*/
static int sdhci_s3c_platform_8bit_width(struct sdhci_host *host, int width)
{
u8 ctrl;
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
switch (width) {
case MMC_BUS_WIDTH_8:
ctrl |= SDHCI_CTRL_8BITBUS;
ctrl &= ~SDHCI_CTRL_4BITBUS;
break;
case MMC_BUS_WIDTH_4:
ctrl |= SDHCI_CTRL_4BITBUS;
ctrl &= ~SDHCI_CTRL_8BITBUS;
break;
default:
break;
}
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
return 0;
}
static struct sdhci_ops sdhci_s3c_ops = {
.get_max_clock = sdhci_s3c_get_max_clk,
.set_clock = sdhci_s3c_set_clock,
.get_min_clock = sdhci_s3c_get_min_clock,
.platform_8bit_width = sdhci_s3c_platform_8bit_width,
};
static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
@ -473,6 +506,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT)
host->mmc->caps = MMC_CAP_NONREMOVABLE;
if (pdata->host_caps)
host->mmc->caps |= pdata->host_caps;
host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR |
SDHCI_QUIRK_32BIT_DMA_SIZE);

View file

@ -19,7 +19,6 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/kernel.h>
#include <linux/usb.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/mmc/host.h>

View file

@ -672,33 +672,7 @@ static int io_init(struct ubi_device *ubi)
ubi->nor_flash = 1;
}
/*
* Set UBI min. I/O size (@ubi->min_io_size). We use @mtd->writebufsize
* for these purposes, not @mtd->writesize. At the moment this does not
* matter for NAND, because currently @mtd->writebufsize is equivalent to
* @mtd->writesize for all NANDs. However, some CFI NOR flashes may
* have @mtd->writebufsize which is multiple of @mtd->writesize.
*
* The reason we use @mtd->writebufsize for @ubi->min_io_size is that
* UBI and UBIFS recovery algorithms rely on the fact that if there was
* an unclean power cut, then we can find offset of the last corrupted
* node, align the offset to @ubi->min_io_size, read the rest of the
* eraseblock starting from this offset, and check whether there are
* only 0xFF bytes. If yes, then we are probably dealing with a
* corruption caused by a power cut, if not, then this is probably some
* severe corruption.
*
* Thus, we have to use the maximum write unit size of the flash, which
* is @mtd->writebufsize, because @mtd->writesize is the minimum write
* size, not the maximum.
*/
if (ubi->mtd->type == MTD_NANDFLASH)
ubi_assert(ubi->mtd->writebufsize == ubi->mtd->writesize);
else if (ubi->mtd->type == MTD_NORFLASH)
ubi_assert(ubi->mtd->writebufsize % ubi->mtd->writesize == 0);
ubi->min_io_size = ubi->mtd->writebufsize;
ubi->min_io_size = ubi->mtd->writesize;
ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
/*

View file

@ -7553,6 +7553,10 @@ bnx2_set_flags(struct net_device *dev, u32 data)
!(data & ETH_FLAG_RXVLAN))
return -EINVAL;
/* TSO with VLAN tag won't work with current firmware */
if (!(data & ETH_FLAG_TXVLAN))
return -EINVAL;
rc = ethtool_op_set_flags(dev, data, ETH_FLAG_RXHASH | ETH_FLAG_RXVLAN |
ETH_FLAG_TXVLAN);
if (rc)
@ -7962,11 +7966,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
/* AER (Advanced Error Reporting) hooks */
err = pci_enable_pcie_error_reporting(pdev);
if (err) {
dev_err(&pdev->dev, "pci_enable_pcie_error_reporting "
"failed 0x%x\n", err);
/* non-fatal, continue */
}
if (!err)
bp->flags |= BNX2_FLAG_AER_ENABLED;
} else {
bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
@ -8229,8 +8230,10 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
return 0;
err_out_unmap:
if (bp->flags & BNX2_FLAG_PCIE)
if (bp->flags & BNX2_FLAG_AER_ENABLED) {
pci_disable_pcie_error_reporting(pdev);
bp->flags &= ~BNX2_FLAG_AER_ENABLED;
}
if (bp->regview) {
iounmap(bp->regview);
@ -8418,8 +8421,10 @@ bnx2_remove_one(struct pci_dev *pdev)
kfree(bp->temp_stats_blk);
if (bp->flags & BNX2_FLAG_PCIE)
if (bp->flags & BNX2_FLAG_AER_ENABLED) {
pci_disable_pcie_error_reporting(pdev);
bp->flags &= ~BNX2_FLAG_AER_ENABLED;
}
free_netdev(dev);
@ -8535,7 +8540,7 @@ static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev)
}
rtnl_unlock();
if (!(bp->flags & BNX2_FLAG_PCIE))
if (!(bp->flags & BNX2_FLAG_AER_ENABLED))
return result;
err = pci_cleanup_aer_uncorrect_error_status(pdev);

View file

@ -6741,6 +6741,7 @@ struct bnx2 {
#define BNX2_FLAG_JUMBO_BROKEN 0x00000800
#define BNX2_FLAG_CAN_KEEP_VLAN 0x00001000
#define BNX2_FLAG_BROKEN_STATS 0x00002000
#define BNX2_FLAG_AER_ENABLED 0x00004000
struct bnx2_napi bnx2_napi[BNX2_MAX_MSIX_VEC];

View file

@ -2470,6 +2470,10 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac
if (!(dev->flags & IFF_MASTER))
goto out;
skb = skb_share_check(skb, GFP_ATOMIC);
if (!skb)
goto out;
if (!pskb_may_pull(skb, sizeof(struct lacpdu)))
goto out;

View file

@ -326,6 +326,10 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct
goto out;
}
skb = skb_share_check(skb, GFP_ATOMIC);
if (!skb)
goto out;
if (!pskb_may_pull(skb, arp_hdr_len(bond_dev)))
goto out;

View file

@ -2733,6 +2733,10 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
if (!slave || !slave_do_arp_validate(bond, slave))
goto out_unlock;
skb = skb_share_check(skb, GFP_ATOMIC);
if (!skb)
goto out_unlock;
if (!pskb_may_pull(skb, arp_hdr_len(dev)))
goto out_unlock;

View file

@ -117,6 +117,8 @@ source "drivers/net/can/sja1000/Kconfig"
source "drivers/net/can/usb/Kconfig"
source "drivers/net/can/softing/Kconfig"
config CAN_DEBUG_DEVICES
bool "CAN devices debugging messages"
depends on CAN

View file

@ -9,6 +9,7 @@ obj-$(CONFIG_CAN_DEV) += can-dev.o
can-dev-y := dev.o
obj-y += usb/
obj-y += softing/
obj-$(CONFIG_CAN_SJA1000) += sja1000/
obj-$(CONFIG_CAN_MSCAN) += mscan/

View file

@ -2,7 +2,7 @@
* at91_can.c - CAN network driver for AT91 SoC CAN controller
*
* (C) 2007 by Hans J. Koch <hjk@hansjkoch.de>
* (C) 2008, 2009, 2010 by Marc Kleine-Budde <kernel@pengutronix.de>
* (C) 2008, 2009, 2010, 2011 by Marc Kleine-Budde <kernel@pengutronix.de>
*
* This software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2 as distributed in the 'COPYING'
@ -30,6 +30,7 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/platform_device.h>
#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/string.h>
@ -40,22 +41,23 @@
#include <mach/board.h>
#define AT91_NAPI_WEIGHT 12
#define AT91_NAPI_WEIGHT 11
/*
* RX/TX Mailbox split
* don't dare to touch
*/
#define AT91_MB_RX_NUM 12
#define AT91_MB_RX_NUM 11
#define AT91_MB_TX_SHIFT 2
#define AT91_MB_RX_FIRST 0
#define AT91_MB_RX_FIRST 1
#define AT91_MB_RX_LAST (AT91_MB_RX_FIRST + AT91_MB_RX_NUM - 1)
#define AT91_MB_RX_MASK(i) ((1 << (i)) - 1)
#define AT91_MB_RX_SPLIT 8
#define AT91_MB_RX_LOW_LAST (AT91_MB_RX_SPLIT - 1)
#define AT91_MB_RX_LOW_MASK (AT91_MB_RX_MASK(AT91_MB_RX_SPLIT))
#define AT91_MB_RX_LOW_MASK (AT91_MB_RX_MASK(AT91_MB_RX_SPLIT) & \
~AT91_MB_RX_MASK(AT91_MB_RX_FIRST))
#define AT91_MB_TX_NUM (1 << AT91_MB_TX_SHIFT)
#define AT91_MB_TX_FIRST (AT91_MB_RX_LAST + 1)
@ -168,6 +170,8 @@ struct at91_priv {
struct clk *clk;
struct at91_can_data *pdata;
canid_t mb0_id;
};
static struct can_bittiming_const at91_bittiming_const = {
@ -220,6 +224,18 @@ static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb,
set_mb_mode_prio(priv, mb, mode, 0);
}
static inline u32 at91_can_id_to_reg_mid(canid_t can_id)
{
u32 reg_mid;
if (can_id & CAN_EFF_FLAG)
reg_mid = (can_id & CAN_EFF_MASK) | AT91_MID_MIDE;
else
reg_mid = (can_id & CAN_SFF_MASK) << 18;
return reg_mid;
}
/*
* Swtich transceiver on or off
*/
@ -233,12 +249,22 @@ static void at91_setup_mailboxes(struct net_device *dev)
{
struct at91_priv *priv = netdev_priv(dev);
unsigned int i;
u32 reg_mid;
/*
* The first 12 mailboxes are used as a reception FIFO. The
* last mailbox is configured with overwrite option. The
* overwrite flag indicates a FIFO overflow.
* Due to a chip bug (errata 50.2.6.3 & 50.3.5.3) the first
* mailbox is disabled. The next 11 mailboxes are used as a
* reception FIFO. The last mailbox is configured with
* overwrite option. The overwrite flag indicates a FIFO
* overflow.
*/
reg_mid = at91_can_id_to_reg_mid(priv->mb0_id);
for (i = 0; i < AT91_MB_RX_FIRST; i++) {
set_mb_mode(priv, i, AT91_MB_MODE_DISABLED);
at91_write(priv, AT91_MID(i), reg_mid);
at91_write(priv, AT91_MCR(i), 0x0); /* clear dlc */
}
for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++)
set_mb_mode(priv, i, AT91_MB_MODE_RX);
set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR);
@ -254,7 +280,8 @@ static void at91_setup_mailboxes(struct net_device *dev)
set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0);
/* Reset tx and rx helper pointers */
priv->tx_next = priv->tx_echo = priv->rx_next = 0;
priv->tx_next = priv->tx_echo = 0;
priv->rx_next = AT91_MB_RX_FIRST;
}
static int at91_set_bittiming(struct net_device *dev)
@ -372,12 +399,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_err(dev, "BUG! TX buffer full when queue awake!\n");
return NETDEV_TX_BUSY;
}
if (cf->can_id & CAN_EFF_FLAG)
reg_mid = (cf->can_id & CAN_EFF_MASK) | AT91_MID_MIDE;
else
reg_mid = (cf->can_id & CAN_SFF_MASK) << 18;
reg_mid = at91_can_id_to_reg_mid(cf->can_id);
reg_mcr = ((cf->can_id & CAN_RTR_FLAG) ? AT91_MCR_MRTR : 0) |
(cf->can_dlc << 16) | AT91_MCR_MTCR;
@ -539,27 +561,31 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb)
*
* Theory of Operation:
*
* 12 of the 16 mailboxes on the chip are reserved for RX. we split
* them into 2 groups. The lower group holds 8 and upper 4 mailboxes.
* 11 of the 16 mailboxes on the chip are reserved for RX. we split
* them into 2 groups. The lower group holds 7 and upper 4 mailboxes.
*
* Like it or not, but the chip always saves a received CAN message
* into the first free mailbox it finds (starting with the
* lowest). This makes it very difficult to read the messages in the
* right order from the chip. This is how we work around that problem:
*
* The first message goes into mb nr. 0 and issues an interrupt. All
* The first message goes into mb nr. 1 and issues an interrupt. All
* rx ints are disabled in the interrupt handler and a napi poll is
* scheduled. We read the mailbox, but do _not_ reenable the mb (to
* receive another message).
*
* lower mbxs upper
* ______^______ __^__
* / \ / \
* ____^______ __^__
* / \ / \
* +-+-+-+-+-+-+-+-++-+-+-+-+
* |x|x|x|x|x|x|x|x|| | | | |
* | |x|x|x|x|x|x|x|| | | | |
* +-+-+-+-+-+-+-+-++-+-+-+-+
* 0 0 0 0 0 0 0 0 0 0 1 1 \ mail
* 0 1 2 3 4 5 6 7 8 9 0 1 / box
* ^
* |
* \
* unused, due to chip bug
*
* The variable priv->rx_next points to the next mailbox to read a
* message from. As long we're in the lower mailboxes we just read the
@ -590,10 +616,10 @@ static int at91_poll_rx(struct net_device *dev, int quota)
"order of incoming frames cannot be guaranteed\n");
again:
for (mb = find_next_bit(addr, AT91_MB_RX_NUM, priv->rx_next);
mb < AT91_MB_RX_NUM && quota > 0;
for (mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, priv->rx_next);
mb < AT91_MB_RX_LAST + 1 && quota > 0;
reg_sr = at91_read(priv, AT91_SR),
mb = find_next_bit(addr, AT91_MB_RX_NUM, ++priv->rx_next)) {
mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, ++priv->rx_next)) {
at91_read_msg(dev, mb);
/* reactivate mailboxes */
@ -610,8 +636,8 @@ static int at91_poll_rx(struct net_device *dev, int quota)
/* upper group completed, look again in lower */
if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
quota > 0 && mb >= AT91_MB_RX_NUM) {
priv->rx_next = 0;
quota > 0 && mb > AT91_MB_RX_LAST) {
priv->rx_next = AT91_MB_RX_FIRST;
goto again;
}
@ -1037,6 +1063,64 @@ static const struct net_device_ops at91_netdev_ops = {
.ndo_start_xmit = at91_start_xmit,
};
static ssize_t at91_sysfs_show_mb0_id(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct at91_priv *priv = netdev_priv(to_net_dev(dev));
if (priv->mb0_id & CAN_EFF_FLAG)
return snprintf(buf, PAGE_SIZE, "0x%08x\n", priv->mb0_id);
else
return snprintf(buf, PAGE_SIZE, "0x%03x\n", priv->mb0_id);
}
static ssize_t at91_sysfs_set_mb0_id(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct net_device *ndev = to_net_dev(dev);
struct at91_priv *priv = netdev_priv(ndev);
unsigned long can_id;
ssize_t ret;
int err;
rtnl_lock();
if (ndev->flags & IFF_UP) {
ret = -EBUSY;
goto out;
}
err = strict_strtoul(buf, 0, &can_id);
if (err) {
ret = err;
goto out;
}
if (can_id & CAN_EFF_FLAG)
can_id &= CAN_EFF_MASK | CAN_EFF_FLAG;
else
can_id &= CAN_SFF_MASK;
priv->mb0_id = can_id;
ret = count;
out:
rtnl_unlock();
return ret;
}
static DEVICE_ATTR(mb0_id, S_IWUGO | S_IRUGO,
at91_sysfs_show_mb0_id, at91_sysfs_set_mb0_id);
static struct attribute *at91_sysfs_attrs[] = {
&dev_attr_mb0_id.attr,
NULL,
};
static struct attribute_group at91_sysfs_attr_group = {
.attrs = at91_sysfs_attrs,
};
static int __devinit at91_can_probe(struct platform_device *pdev)
{
struct net_device *dev;
@ -1082,6 +1166,7 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
dev->netdev_ops = &at91_netdev_ops;
dev->irq = irq;
dev->flags |= IFF_ECHO;
dev->sysfs_groups[0] = &at91_sysfs_attr_group;
priv = netdev_priv(dev);
priv->can.clock.freq = clk_get_rate(clk);
@ -1093,6 +1178,7 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
priv->dev = dev;
priv->clk = clk;
priv->pdata = pdev->dev.platform_data;
priv->mb0_id = 0x7ff;
netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT);

View file

@ -0,0 +1,30 @@
config CAN_SOFTING
tristate "Softing Gmbh CAN generic support"
depends on CAN_DEV
---help---
Support for CAN cards from Softing Gmbh & some cards
from Vector Gmbh.
Softing Gmbh CAN cards come with 1 or 2 physical busses.
Those cards typically use Dual Port RAM to communicate
with the host CPU. The interface is then identical for PCI
and PCMCIA cards. This driver operates on a platform device,
which has been created by softing_cs or softing_pci driver.
Warning:
The API of the card does not allow fine control per bus, but
controls the 2 busses on the card together.
As such, some actions (start/stop/busoff recovery) on 1 bus
must bring down the other bus too temporarily.
config CAN_SOFTING_CS
tristate "Softing Gmbh CAN pcmcia cards"
depends on PCMCIA
select CAN_SOFTING
---help---
Support for PCMCIA cards from Softing Gmbh & some cards
from Vector Gmbh.
You need firmware for these, which you can get at
http://developer.berlios.de/projects/socketcan/
This version of the driver is written against
firmware version 4.6 (softing-fw-4.6-binaries.tar.gz)
In order to use the card as CAN device, you need the Softing generic
support too.

View file

@ -0,0 +1,6 @@
softing-y := softing_main.o softing_fw.o
obj-$(CONFIG_CAN_SOFTING) += softing.o
obj-$(CONFIG_CAN_SOFTING_CS) += softing_cs.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG

View file

@ -0,0 +1,167 @@
/*
* softing common interfaces
*
* by Kurt Van Dijck, 2008-2010
*/
#include <linux/atomic.h>
#include <linux/netdevice.h>
#include <linux/ktime.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include "softing_platform.h"
struct softing;
struct softing_priv {
struct can_priv can; /* must be the first member! */
struct net_device *netdev;
struct softing *card;
struct {
int pending;
/* variables wich hold the circular buffer */
int echo_put;
int echo_get;
} tx;
struct can_bittiming_const btr_const;
int index;
uint8_t output;
uint16_t chip;
};
#define netdev2softing(netdev) ((struct softing_priv *)netdev_priv(netdev))
struct softing {
const struct softing_platform_data *pdat;
struct platform_device *pdev;
struct net_device *net[2];
spinlock_t spin; /* protect this structure & DPRAM access */
ktime_t ts_ref;
ktime_t ts_overflow; /* timestamp overflow value, in ktime */
struct {
/* indication of firmware status */
int up;
/* protection of the 'up' variable */
struct mutex lock;
} fw;
struct {
int nr;
int requested;
int svc_count;
unsigned int dpram_position;
} irq;
struct {
int pending;
int last_bus;
/*
* keep the bus that last tx'd a message,
* in order to let every netdev queue resume
*/
} tx;
__iomem uint8_t *dpram;
unsigned long dpram_phys;
unsigned long dpram_size;
struct {
uint16_t fw_version, hw_version, license, serial;
uint16_t chip[2];
unsigned int freq; /* remote cpu's operating frequency */
} id;
};
extern int softing_default_output(struct net_device *netdev);
extern ktime_t softing_raw2ktime(struct softing *card, u32 raw);
extern int softing_chip_poweron(struct softing *card);
extern int softing_bootloader_command(struct softing *card, int16_t cmd,
const char *msg);
/* Load firmware after reset */
extern int softing_load_fw(const char *file, struct softing *card,
__iomem uint8_t *virt, unsigned int size, int offset);
/* Load final application firmware after bootloader */
extern int softing_load_app_fw(const char *file, struct softing *card);
/*
* enable or disable irq
* only called with fw.lock locked
*/
extern int softing_enable_irq(struct softing *card, int enable);
/* start/stop 1 bus on card */
extern int softing_startstop(struct net_device *netdev, int up);
/* netif_rx() */
extern int softing_netdev_rx(struct net_device *netdev,
const struct can_frame *msg, ktime_t ktime);
/* SOFTING DPRAM mappings */
#define DPRAM_RX 0x0000
#define DPRAM_RX_SIZE 32
#define DPRAM_RX_CNT 16
#define DPRAM_RX_RD 0x0201 /* uint8_t */
#define DPRAM_RX_WR 0x0205 /* uint8_t */
#define DPRAM_RX_LOST 0x0207 /* uint8_t */
#define DPRAM_FCT_PARAM 0x0300 /* int16_t [20] */
#define DPRAM_FCT_RESULT 0x0328 /* int16_t */
#define DPRAM_FCT_HOST 0x032b /* uint16_t */
#define DPRAM_INFO_BUSSTATE 0x0331 /* uint16_t */
#define DPRAM_INFO_BUSSTATE2 0x0335 /* uint16_t */
#define DPRAM_INFO_ERRSTATE 0x0339 /* uint16_t */
#define DPRAM_INFO_ERRSTATE2 0x033d /* uint16_t */
#define DPRAM_RESET 0x0341 /* uint16_t */
#define DPRAM_CLR_RECV_FIFO 0x0345 /* uint16_t */
#define DPRAM_RESET_TIME 0x034d /* uint16_t */
#define DPRAM_TIME 0x0350 /* uint64_t */
#define DPRAM_WR_START 0x0358 /* uint8_t */
#define DPRAM_WR_END 0x0359 /* uint8_t */
#define DPRAM_RESET_RX_FIFO 0x0361 /* uint16_t */
#define DPRAM_RESET_TX_FIFO 0x0364 /* uint8_t */
#define DPRAM_READ_FIFO_LEVEL 0x0365 /* uint8_t */
#define DPRAM_RX_FIFO_LEVEL 0x0366 /* uint16_t */
#define DPRAM_TX_FIFO_LEVEL 0x0366 /* uint16_t */
#define DPRAM_TX 0x0400 /* uint16_t */
#define DPRAM_TX_SIZE 16
#define DPRAM_TX_CNT 32
#define DPRAM_TX_RD 0x0601 /* uint8_t */
#define DPRAM_TX_WR 0x0605 /* uint8_t */
#define DPRAM_COMMAND 0x07e0 /* uint16_t */
#define DPRAM_RECEIPT 0x07f0 /* uint16_t */
#define DPRAM_IRQ_TOHOST 0x07fe /* uint8_t */
#define DPRAM_IRQ_TOCARD 0x07ff /* uint8_t */
#define DPRAM_V2_RESET 0x0e00 /* uint8_t */
#define DPRAM_V2_IRQ_TOHOST 0x0e02 /* uint8_t */
#define TXMAX (DPRAM_TX_CNT - 1)
/* DPRAM return codes */
#define RES_NONE 0
#define RES_OK 1
#define RES_NOK 2
#define RES_UNKNOWN 3
/* DPRAM flags */
#define CMD_TX 0x01
#define CMD_ACK 0x02
#define CMD_XTD 0x04
#define CMD_RTR 0x08
#define CMD_ERR 0x10
#define CMD_BUS2 0x80
/* returned fifo entry bus state masks */
#define SF_MASK_BUSOFF 0x80
#define SF_MASK_EPASSIVE 0x60
/* bus states */
#define STATE_BUSOFF 2
#define STATE_EPASSIVE 1
#define STATE_EACTIVE 0

View file

@ -0,0 +1,359 @@
/*
* Copyright (C) 2008-2010
*
* - Kurt Van Dijck, EIA Electronics
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the version 2 of the GNU General Public License
* as published by the Free Software Foundation
*
* 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/module.h>
#include <linux/kernel.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include "softing_platform.h"
static int softingcs_index;
static spinlock_t softingcs_index_lock;
static int softingcs_reset(struct platform_device *pdev, int v);
static int softingcs_enable_irq(struct platform_device *pdev, int v);
/*
* platform_data descriptions
*/
#define MHZ (1000*1000)
static const struct softing_platform_data softingcs_platform_data[] = {
{
.name = "CANcard",
.manf = 0x0168, .prod = 0x001,
.generation = 1,
.nbus = 2,
.freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,
.dpram_size = 0x0800,
.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
.reset = softingcs_reset,
.enable_irq = softingcs_enable_irq,
}, {
.name = "CANcard-NEC",
.manf = 0x0168, .prod = 0x002,
.generation = 1,
.nbus = 2,
.freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,
.dpram_size = 0x0800,
.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
.reset = softingcs_reset,
.enable_irq = softingcs_enable_irq,
}, {
.name = "CANcard-SJA",
.manf = 0x0168, .prod = 0x004,
.generation = 1,
.nbus = 2,
.freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,
.dpram_size = 0x0800,
.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
.app = {0x0010, 0x0d0000, fw_dir "cansja.bin",},
.reset = softingcs_reset,
.enable_irq = softingcs_enable_irq,
}, {
.name = "CANcard-2",
.manf = 0x0168, .prod = 0x005,
.generation = 2,
.nbus = 2,
.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
.dpram_size = 0x1000,
.boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
.load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
.app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
.reset = softingcs_reset,
.enable_irq = NULL,
}, {
.name = "Vector-CANcard",
.manf = 0x0168, .prod = 0x081,
.generation = 1,
.nbus = 2,
.freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,
.dpram_size = 0x0800,
.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
.reset = softingcs_reset,
.enable_irq = softingcs_enable_irq,
}, {
.name = "Vector-CANcard-SJA",
.manf = 0x0168, .prod = 0x084,
.generation = 1,
.nbus = 2,
.freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,
.dpram_size = 0x0800,
.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
.app = {0x0010, 0x0d0000, fw_dir "cansja.bin",},
.reset = softingcs_reset,
.enable_irq = softingcs_enable_irq,
}, {
.name = "Vector-CANcard-2",
.manf = 0x0168, .prod = 0x085,
.generation = 2,
.nbus = 2,
.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
.dpram_size = 0x1000,
.boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
.load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
.app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
.reset = softingcs_reset,
.enable_irq = NULL,
}, {
.name = "EDICcard-NEC",
.manf = 0x0168, .prod = 0x102,
.generation = 1,
.nbus = 2,
.freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,
.dpram_size = 0x0800,
.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
.reset = softingcs_reset,
.enable_irq = softingcs_enable_irq,
}, {
.name = "EDICcard-2",
.manf = 0x0168, .prod = 0x105,
.generation = 2,
.nbus = 2,
.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
.dpram_size = 0x1000,
.boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
.load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
.app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
.reset = softingcs_reset,
.enable_irq = NULL,
}, {
0, 0,
},
};
MODULE_FIRMWARE(fw_dir "bcard.bin");
MODULE_FIRMWARE(fw_dir "ldcard.bin");
MODULE_FIRMWARE(fw_dir "cancard.bin");
MODULE_FIRMWARE(fw_dir "cansja.bin");
MODULE_FIRMWARE(fw_dir "bcard2.bin");
MODULE_FIRMWARE(fw_dir "ldcard2.bin");
MODULE_FIRMWARE(fw_dir "cancrd2.bin");
static __devinit const struct softing_platform_data
*softingcs_find_platform_data(unsigned int manf, unsigned int prod)
{
const struct softing_platform_data *lp;
for (lp = softingcs_platform_data; lp->manf; ++lp) {
if ((lp->manf == manf) && (lp->prod == prod))
return lp;
}
return NULL;
}
/*
* platformdata callbacks
*/
static int softingcs_reset(struct platform_device *pdev, int v)
{
struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent);
dev_dbg(&pdev->dev, "pcmcia config [2] %02x\n", v ? 0 : 0x20);
return pcmcia_write_config_byte(pcmcia, 2, v ? 0 : 0x20);
}
static int softingcs_enable_irq(struct platform_device *pdev, int v)
{
struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent);
dev_dbg(&pdev->dev, "pcmcia config [0] %02x\n", v ? 0x60 : 0);
return pcmcia_write_config_byte(pcmcia, 0, v ? 0x60 : 0);
}
/*
* pcmcia check
*/
static __devinit int softingcs_probe_config(struct pcmcia_device *pcmcia,
void *priv_data)
{
struct softing_platform_data *pdat = priv_data;
struct resource *pres;
int memspeed = 0;
WARN_ON(!pdat);
pres = pcmcia->resource[PCMCIA_IOMEM_0];
if (resource_size(pres) < 0x1000)
return -ERANGE;
pres->flags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE;
if (pdat->generation < 2) {
pres->flags |= WIN_USE_WAIT | WIN_DATA_WIDTH_8;
memspeed = 3;
} else {
pres->flags |= WIN_DATA_WIDTH_16;
}
return pcmcia_request_window(pcmcia, pres, memspeed);
}
static __devexit void softingcs_remove(struct pcmcia_device *pcmcia)
{
struct platform_device *pdev = pcmcia->priv;
/* free bits */
platform_device_unregister(pdev);
/* release pcmcia stuff */
pcmcia_disable_device(pcmcia);
}
/*
* platform_device wrapper
* pdev->resource has 2 entries: io & irq
*/
static void softingcs_pdev_release(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
kfree(pdev);
}
static __devinit int softingcs_probe(struct pcmcia_device *pcmcia)
{
int ret;
struct platform_device *pdev;
const struct softing_platform_data *pdat;
struct resource *pres;
struct dev {
struct platform_device pdev;
struct resource res[2];
} *dev;
/* find matching platform_data */
pdat = softingcs_find_platform_data(pcmcia->manf_id, pcmcia->card_id);
if (!pdat)
return -ENOTTY;
/* setup pcmcia device */
pcmcia->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IOMEM |
CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
ret = pcmcia_loop_config(pcmcia, softingcs_probe_config, (void *)pdat);
if (ret)
goto pcmcia_failed;
ret = pcmcia_enable_device(pcmcia);
if (ret < 0)
goto pcmcia_failed;
pres = pcmcia->resource[PCMCIA_IOMEM_0];
if (!pres) {
ret = -EBADF;
goto pcmcia_bad;
}
/* create softing platform device */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
ret = -ENOMEM;
goto mem_failed;
}
dev->pdev.resource = dev->res;
dev->pdev.num_resources = ARRAY_SIZE(dev->res);
dev->pdev.dev.release = softingcs_pdev_release;
pdev = &dev->pdev;
pdev->dev.platform_data = (void *)pdat;
pdev->dev.parent = &pcmcia->dev;
pcmcia->priv = pdev;
/* platform device resources */
pdev->resource[0].flags = IORESOURCE_MEM;
pdev->resource[0].start = pres->start;
pdev->resource[0].end = pres->end;
pdev->resource[1].flags = IORESOURCE_IRQ;
pdev->resource[1].start = pcmcia->irq;
pdev->resource[1].end = pdev->resource[1].start;
/* platform device setup */
spin_lock(&softingcs_index_lock);
pdev->id = softingcs_index++;
spin_unlock(&softingcs_index_lock);
pdev->name = "softing";
dev_set_name(&pdev->dev, "softingcs.%i", pdev->id);
ret = platform_device_register(pdev);
if (ret < 0)
goto platform_failed;
dev_info(&pcmcia->dev, "created %s\n", dev_name(&pdev->dev));
return 0;
platform_failed:
kfree(dev);
mem_failed:
pcmcia_bad:
pcmcia_failed:
pcmcia_disable_device(pcmcia);
pcmcia->priv = NULL;
return ret ?: -ENODEV;
}
static /*const*/ struct pcmcia_device_id softingcs_ids[] = {
/* softing */
PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0001),
PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0002),
PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0004),
PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0005),
/* vector, manufacturer? */
PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0081),
PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0084),
PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0085),
/* EDIC */
PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0102),
PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0105),
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, softingcs_ids);
static struct pcmcia_driver softingcs_driver = {
.owner = THIS_MODULE,
.name = "softingcs",
.id_table = softingcs_ids,
.probe = softingcs_probe,
.remove = __devexit_p(softingcs_remove),
};
static int __init softingcs_start(void)
{
spin_lock_init(&softingcs_index_lock);
return pcmcia_register_driver(&softingcs_driver);
}
static void __exit softingcs_stop(void)
{
pcmcia_unregister_driver(&softingcs_driver);
}
module_init(softingcs_start);
module_exit(softingcs_stop);
MODULE_DESCRIPTION("softing CANcard driver"
", links PCMCIA card to softing driver");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,691 @@
/*
* Copyright (C) 2008-2010
*
* - Kurt Van Dijck, EIA Electronics
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the version 2 of the GNU General Public License
* as published by the Free Software Foundation
*
* 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/firmware.h>
#include <linux/sched.h>
#include <asm/div64.h>
#include "softing.h"
/*
* low level DPRAM command.
* Make sure that card->dpram[DPRAM_FCT_HOST] is preset
*/
static int _softing_fct_cmd(struct softing *card, int16_t cmd, uint16_t vector,
const char *msg)
{
int ret;
unsigned long stamp;
iowrite16(cmd, &card->dpram[DPRAM_FCT_PARAM]);
iowrite8(vector >> 8, &card->dpram[DPRAM_FCT_HOST + 1]);
iowrite8(vector, &card->dpram[DPRAM_FCT_HOST]);
/* be sure to flush this to the card */
wmb();
stamp = jiffies + 1 * HZ;
/* wait for card */
do {
/* DPRAM_FCT_HOST is _not_ aligned */
ret = ioread8(&card->dpram[DPRAM_FCT_HOST]) +
(ioread8(&card->dpram[DPRAM_FCT_HOST + 1]) << 8);
/* don't have any cached variables */
rmb();
if (ret == RES_OK)
/* read return-value now */
return ioread16(&card->dpram[DPRAM_FCT_RESULT]);
if ((ret != vector) || time_after(jiffies, stamp))
break;
/* process context => relax */
usleep_range(500, 10000);
} while (1);
ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED;
dev_alert(&card->pdev->dev, "firmware %s failed (%i)\n", msg, ret);
return ret;
}
static int softing_fct_cmd(struct softing *card, int16_t cmd, const char *msg)
{
int ret;
ret = _softing_fct_cmd(card, cmd, 0, msg);
if (ret > 0) {
dev_alert(&card->pdev->dev, "%s returned %u\n", msg, ret);
ret = -EIO;
}
return ret;
}
int softing_bootloader_command(struct softing *card, int16_t cmd,
const char *msg)
{
int ret;
unsigned long stamp;
iowrite16(RES_NONE, &card->dpram[DPRAM_RECEIPT]);
iowrite16(cmd, &card->dpram[DPRAM_COMMAND]);
/* be sure to flush this to the card */
wmb();
stamp = jiffies + 3 * HZ;
/* wait for card */
do {
ret = ioread16(&card->dpram[DPRAM_RECEIPT]);
/* don't have any cached variables */
rmb();
if (ret == RES_OK)
return 0;
if (time_after(jiffies, stamp))
break;
/* process context => relax */
usleep_range(500, 10000);
} while (!signal_pending(current));
ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED;
dev_alert(&card->pdev->dev, "bootloader %s failed (%i)\n", msg, ret);
return ret;
}
static int fw_parse(const uint8_t **pmem, uint16_t *ptype, uint32_t *paddr,
uint16_t *plen, const uint8_t **pdat)
{
uint16_t checksum[2];
const uint8_t *mem;
const uint8_t *end;
/*
* firmware records are a binary, unaligned stream composed of:
* uint16_t type;
* uint32_t addr;
* uint16_t len;
* uint8_t dat[len];
* uint16_t checksum;
* all values in little endian.
* We could define a struct for this, with __attribute__((packed)),
* but would that solve the alignment in _all_ cases (cfr. the
* struct itself may be an odd address)?
*
* I chose to use leXX_to_cpup() since this solves both
* endianness & alignment.
*/
mem = *pmem;
*ptype = le16_to_cpup((void *)&mem[0]);
*paddr = le32_to_cpup((void *)&mem[2]);
*plen = le16_to_cpup((void *)&mem[6]);
*pdat = &mem[8];
/* verify checksum */
end = &mem[8 + *plen];
checksum[0] = le16_to_cpup((void *)end);
for (checksum[1] = 0; mem < end; ++mem)
checksum[1] += *mem;
if (checksum[0] != checksum[1])
return -EINVAL;
/* increment */
*pmem += 10 + *plen;
return 0;
}
int softing_load_fw(const char *file, struct softing *card,
__iomem uint8_t *dpram, unsigned int size, int offset)
{
const struct firmware *fw;
int ret;
const uint8_t *mem, *end, *dat;
uint16_t type, len;
uint32_t addr;
uint8_t *buf = NULL;
int buflen = 0;
int8_t type_end = 0;
ret = request_firmware(&fw, file, &card->pdev->dev);
if (ret < 0)
return ret;
dev_dbg(&card->pdev->dev, "%s, firmware(%s) got %u bytes"
", offset %c0x%04x\n",
card->pdat->name, file, (unsigned int)fw->size,
(offset >= 0) ? '+' : '-', (unsigned int)abs(offset));
/* parse the firmware */
mem = fw->data;
end = &mem[fw->size];
/* look for header record */
ret = fw_parse(&mem, &type, &addr, &len, &dat);
if (ret < 0)
goto failed;
if (type != 0xffff)
goto failed;
if (strncmp("Structured Binary Format, Softing GmbH" , dat, len)) {
ret = -EINVAL;
goto failed;
}
/* ok, we had a header */
while (mem < end) {
ret = fw_parse(&mem, &type, &addr, &len, &dat);
if (ret < 0)
goto failed;
if (type == 3) {
/* start address, not used here */
continue;
} else if (type == 1) {
/* eof */
type_end = 1;
break;
} else if (type != 0) {
ret = -EINVAL;
goto failed;
}
if ((addr + len + offset) > size)
goto failed;
memcpy_toio(&dpram[addr + offset], dat, len);
/* be sure to flush caches from IO space */
mb();
if (len > buflen) {
/* align buflen */
buflen = (len + (1024-1)) & ~(1024-1);
buf = krealloc(buf, buflen, GFP_KERNEL);
if (!buf) {
ret = -ENOMEM;
goto failed;
}
}
/* verify record data */
memcpy_fromio(buf, &dpram[addr + offset], len);
if (memcmp(buf, dat, len)) {
/* is not ok */
dev_alert(&card->pdev->dev, "DPRAM readback failed\n");
ret = -EIO;
goto failed;
}
}
if (!type_end)
/* no end record seen */
goto failed;
ret = 0;
failed:
kfree(buf);
release_firmware(fw);
if (ret < 0)
dev_info(&card->pdev->dev, "firmware %s failed\n", file);
return ret;
}
int softing_load_app_fw(const char *file, struct softing *card)
{
const struct firmware *fw;
const uint8_t *mem, *end, *dat;
int ret, j;
uint16_t type, len;
uint32_t addr, start_addr = 0;
unsigned int sum, rx_sum;
int8_t type_end = 0, type_entrypoint = 0;
ret = request_firmware(&fw, file, &card->pdev->dev);
if (ret) {
dev_alert(&card->pdev->dev, "request_firmware(%s) got %i\n",
file, ret);
return ret;
}
dev_dbg(&card->pdev->dev, "firmware(%s) got %lu bytes\n",
file, (unsigned long)fw->size);
/* parse the firmware */
mem = fw->data;
end = &mem[fw->size];
/* look for header record */
ret = fw_parse(&mem, &type, &addr, &len, &dat);
if (ret)
goto failed;
ret = -EINVAL;
if (type != 0xffff) {
dev_alert(&card->pdev->dev, "firmware starts with type 0x%x\n",
type);
goto failed;
}
if (strncmp("Structured Binary Format, Softing GmbH", dat, len)) {
dev_alert(&card->pdev->dev, "firmware string '%.*s' fault\n",
len, dat);
goto failed;
}
/* ok, we had a header */
while (mem < end) {
ret = fw_parse(&mem, &type, &addr, &len, &dat);
if (ret)
goto failed;
if (type == 3) {
/* start address */
start_addr = addr;
type_entrypoint = 1;
continue;
} else if (type == 1) {
/* eof */
type_end = 1;
break;
} else if (type != 0) {
dev_alert(&card->pdev->dev,
"unknown record type 0x%04x\n", type);
ret = -EINVAL;
goto failed;
}
/* regualar data */
for (sum = 0, j = 0; j < len; ++j)
sum += dat[j];
/* work in 16bit (target) */
sum &= 0xffff;
memcpy_toio(&card->dpram[card->pdat->app.offs], dat, len);
iowrite32(card->pdat->app.offs + card->pdat->app.addr,
&card->dpram[DPRAM_COMMAND + 2]);
iowrite32(addr, &card->dpram[DPRAM_COMMAND + 6]);
iowrite16(len, &card->dpram[DPRAM_COMMAND + 10]);
iowrite8(1, &card->dpram[DPRAM_COMMAND + 12]);
ret = softing_bootloader_command(card, 1, "loading app.");
if (ret < 0)
goto failed;
/* verify checksum */
rx_sum = ioread16(&card->dpram[DPRAM_RECEIPT + 2]);
if (rx_sum != sum) {
dev_alert(&card->pdev->dev, "SRAM seems to be damaged"
", wanted 0x%04x, got 0x%04x\n", sum, rx_sum);
ret = -EIO;
goto failed;
}
}
if (!type_end || !type_entrypoint)
goto failed;
/* start application in card */
iowrite32(start_addr, &card->dpram[DPRAM_COMMAND + 2]);
iowrite8(1, &card->dpram[DPRAM_COMMAND + 6]);
ret = softing_bootloader_command(card, 3, "start app.");
if (ret < 0)
goto failed;
ret = 0;
failed:
release_firmware(fw);
if (ret < 0)
dev_info(&card->pdev->dev, "firmware %s failed\n", file);
return ret;
}
static int softing_reset_chip(struct softing *card)
{
int ret;
do {
/* reset chip */
iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO]);
iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO+1]);
iowrite8(1, &card->dpram[DPRAM_RESET]);
iowrite8(0, &card->dpram[DPRAM_RESET+1]);
ret = softing_fct_cmd(card, 0, "reset_can");
if (!ret)
break;
if (signal_pending(current))
/* don't wait any longer */
break;
} while (1);
card->tx.pending = 0;
return ret;
}
int softing_chip_poweron(struct softing *card)
{
int ret;
/* sync */
ret = _softing_fct_cmd(card, 99, 0x55, "sync-a");
if (ret < 0)
goto failed;
ret = _softing_fct_cmd(card, 99, 0xaa, "sync-b");
if (ret < 0)
goto failed;
ret = softing_reset_chip(card);
if (ret < 0)
goto failed;
/* get_serial */
ret = softing_fct_cmd(card, 43, "get_serial_number");
if (ret < 0)
goto failed;
card->id.serial = ioread32(&card->dpram[DPRAM_FCT_PARAM]);
/* get_version */
ret = softing_fct_cmd(card, 12, "get_version");
if (ret < 0)
goto failed;
card->id.fw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 2]);
card->id.hw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 4]);
card->id.license = ioread16(&card->dpram[DPRAM_FCT_PARAM + 6]);
card->id.chip[0] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 8]);
card->id.chip[1] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 10]);
return 0;
failed:
return ret;
}
static void softing_initialize_timestamp(struct softing *card)
{
uint64_t ovf;
card->ts_ref = ktime_get();
/* 16MHz is the reference */
ovf = 0x100000000ULL * 16;
do_div(ovf, card->pdat->freq ?: 16);
card->ts_overflow = ktime_add_us(ktime_set(0, 0), ovf);
}
ktime_t softing_raw2ktime(struct softing *card, u32 raw)
{
uint64_t rawl;
ktime_t now, real_offset;
ktime_t target;
ktime_t tmp;
now = ktime_get();
real_offset = ktime_sub(ktime_get_real(), now);
/* find nsec from card */
rawl = raw * 16;
do_div(rawl, card->pdat->freq ?: 16);
target = ktime_add_us(card->ts_ref, rawl);
/* test for overflows */
tmp = ktime_add(target, card->ts_overflow);
while (unlikely(ktime_to_ns(tmp) > ktime_to_ns(now))) {
card->ts_ref = ktime_add(card->ts_ref, card->ts_overflow);
target = tmp;
tmp = ktime_add(target, card->ts_overflow);
}
return ktime_add(target, real_offset);
}
static inline int softing_error_reporting(struct net_device *netdev)
{
struct softing_priv *priv = netdev_priv(netdev);
return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
? 1 : 0;
}
int softing_startstop(struct net_device *dev, int up)
{
int ret;
struct softing *card;
struct softing_priv *priv;
struct net_device *netdev;
int bus_bitmask_start;
int j, error_reporting;
struct can_frame msg;
const struct can_bittiming *bt;
priv = netdev_priv(dev);
card = priv->card;
if (!card->fw.up)
return -EIO;
ret = mutex_lock_interruptible(&card->fw.lock);
if (ret)
return ret;
bus_bitmask_start = 0;
if (dev && up)
/* prepare to start this bus as well */
bus_bitmask_start |= (1 << priv->index);
/* bring netdevs down */
for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
netdev = card->net[j];
if (!netdev)
continue;
priv = netdev_priv(netdev);
if (dev != netdev)
netif_stop_queue(netdev);
if (netif_running(netdev)) {
if (dev != netdev)
bus_bitmask_start |= (1 << j);
priv->tx.pending = 0;
priv->tx.echo_put = 0;
priv->tx.echo_get = 0;
/*
* this bus' may just have called open_candev()
* which is rather stupid to call close_candev()
* already
* but we may come here from busoff recovery too
* in which case the echo_skb _needs_ flushing too.
* just be sure to call open_candev() again
*/
close_candev(netdev);
}
priv->can.state = CAN_STATE_STOPPED;
}
card->tx.pending = 0;
softing_enable_irq(card, 0);
ret = softing_reset_chip(card);
if (ret)
goto failed;
if (!bus_bitmask_start)
/* no busses to be brought up */
goto card_done;
if ((bus_bitmask_start & 1) && (bus_bitmask_start & 2)
&& (softing_error_reporting(card->net[0])
!= softing_error_reporting(card->net[1]))) {
dev_alert(&card->pdev->dev,
"err_reporting flag differs for busses\n");
goto invalid;
}
error_reporting = 0;
if (bus_bitmask_start & 1) {
netdev = card->net[0];
priv = netdev_priv(netdev);
error_reporting += softing_error_reporting(netdev);
/* init chip 1 */
bt = &priv->can.bittiming;
iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]);
iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]);
iowrite16(bt->phase_seg1 + bt->prop_seg,
&card->dpram[DPRAM_FCT_PARAM + 6]);
iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]);
iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0,
&card->dpram[DPRAM_FCT_PARAM + 10]);
ret = softing_fct_cmd(card, 1, "initialize_chip[0]");
if (ret < 0)
goto failed;
/* set mode */
iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]);
iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]);
ret = softing_fct_cmd(card, 3, "set_mode[0]");
if (ret < 0)
goto failed;
/* set filter */
/* 11bit id & mask */
iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]);
iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]);
/* 29bit id.lo & mask.lo & id.hi & mask.hi */
iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]);
iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]);
iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]);
iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]);
ret = softing_fct_cmd(card, 7, "set_filter[0]");
if (ret < 0)
goto failed;
/* set output control */
iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]);
ret = softing_fct_cmd(card, 5, "set_output[0]");
if (ret < 0)
goto failed;
}
if (bus_bitmask_start & 2) {
netdev = card->net[1];
priv = netdev_priv(netdev);
error_reporting += softing_error_reporting(netdev);
/* init chip2 */
bt = &priv->can.bittiming;
iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]);
iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]);
iowrite16(bt->phase_seg1 + bt->prop_seg,
&card->dpram[DPRAM_FCT_PARAM + 6]);
iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]);
iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0,
&card->dpram[DPRAM_FCT_PARAM + 10]);
ret = softing_fct_cmd(card, 2, "initialize_chip[1]");
if (ret < 0)
goto failed;
/* set mode2 */
iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]);
iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]);
ret = softing_fct_cmd(card, 4, "set_mode[1]");
if (ret < 0)
goto failed;
/* set filter2 */
/* 11bit id & mask */
iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]);
iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]);
/* 29bit id.lo & mask.lo & id.hi & mask.hi */
iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]);
iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]);
iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]);
iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]);
ret = softing_fct_cmd(card, 8, "set_filter[1]");
if (ret < 0)
goto failed;
/* set output control2 */
iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]);
ret = softing_fct_cmd(card, 6, "set_output[1]");
if (ret < 0)
goto failed;
}
/* enable_error_frame */
/*
* Error reporting is switched off at the moment since
* the receiving of them is not yet 100% verified
* This should be enabled sooner or later
*
if (error_reporting) {
ret = softing_fct_cmd(card, 51, "enable_error_frame");
if (ret < 0)
goto failed;
}
*/
/* initialize interface */
iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 2]);
iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 4]);
iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 6]);
iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 8]);
iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 10]);
iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 12]);
iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 14]);
iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 16]);
iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 18]);
iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 20]);
ret = softing_fct_cmd(card, 17, "initialize_interface");
if (ret < 0)
goto failed;
/* enable_fifo */
ret = softing_fct_cmd(card, 36, "enable_fifo");
if (ret < 0)
goto failed;
/* enable fifo tx ack */
ret = softing_fct_cmd(card, 13, "fifo_tx_ack[0]");
if (ret < 0)
goto failed;
/* enable fifo tx ack2 */
ret = softing_fct_cmd(card, 14, "fifo_tx_ack[1]");
if (ret < 0)
goto failed;
/* start_chip */
ret = softing_fct_cmd(card, 11, "start_chip");
if (ret < 0)
goto failed;
iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE]);
iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE2]);
if (card->pdat->generation < 2) {
iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]);
/* flush the DPRAM caches */
wmb();
}
softing_initialize_timestamp(card);
/*
* do socketcan notifications/status changes
* from here, no errors should occur, or the failed: part
* must be reviewed
*/
memset(&msg, 0, sizeof(msg));
msg.can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED;
msg.can_dlc = CAN_ERR_DLC;
for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
if (!(bus_bitmask_start & (1 << j)))
continue;
netdev = card->net[j];
if (!netdev)
continue;
priv = netdev_priv(netdev);
priv->can.state = CAN_STATE_ERROR_ACTIVE;
open_candev(netdev);
if (dev != netdev) {
/* notify other busses on the restart */
softing_netdev_rx(netdev, &msg, ktime_set(0, 0));
++priv->can.can_stats.restarts;
}
netif_wake_queue(netdev);
}
/* enable interrupts */
ret = softing_enable_irq(card, 1);
if (ret)
goto failed;
card_done:
mutex_unlock(&card->fw.lock);
return 0;
invalid:
ret = -EINVAL;
failed:
softing_enable_irq(card, 0);
softing_reset_chip(card);
mutex_unlock(&card->fw.lock);
/* bring all other interfaces down */
for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
netdev = card->net[j];
if (!netdev)
continue;
dev_close(netdev);
}
return ret;
}
int softing_default_output(struct net_device *netdev)
{
struct softing_priv *priv = netdev_priv(netdev);
struct softing *card = priv->card;
switch (priv->chip) {
case 1000:
return (card->pdat->generation < 2) ? 0xfb : 0xfa;
case 5:
return 0x60;
default:
return 0x40;
}
}

View file

@ -0,0 +1,893 @@
/*
* Copyright (C) 2008-2010
*
* - Kurt Van Dijck, EIA Electronics
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the version 2 of the GNU General Public License
* as published by the Free Software Foundation
*
* 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/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include "softing.h"
#define TX_ECHO_SKB_MAX (((TXMAX+1)/2)-1)
/*
* test is a specific CAN netdev
* is online (ie. up 'n running, not sleeping, not busoff
*/
static inline int canif_is_active(struct net_device *netdev)
{
struct can_priv *can = netdev_priv(netdev);
if (!netif_running(netdev))
return 0;
return (can->state <= CAN_STATE_ERROR_PASSIVE);
}
/* reset DPRAM */
static inline void softing_set_reset_dpram(struct softing *card)
{
if (card->pdat->generation >= 2) {
spin_lock_bh(&card->spin);
iowrite8(ioread8(&card->dpram[DPRAM_V2_RESET]) & ~1,
&card->dpram[DPRAM_V2_RESET]);
spin_unlock_bh(&card->spin);
}
}
static inline void softing_clr_reset_dpram(struct softing *card)
{
if (card->pdat->generation >= 2) {
spin_lock_bh(&card->spin);
iowrite8(ioread8(&card->dpram[DPRAM_V2_RESET]) | 1,
&card->dpram[DPRAM_V2_RESET]);
spin_unlock_bh(&card->spin);
}
}
/* trigger the tx queue-ing */
static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct softing_priv *priv = netdev_priv(dev);
struct softing *card = priv->card;
int ret;
uint8_t *ptr;
uint8_t fifo_wr, fifo_rd;
struct can_frame *cf = (struct can_frame *)skb->data;
uint8_t buf[DPRAM_TX_SIZE];
if (can_dropped_invalid_skb(dev, skb))
return NETDEV_TX_OK;
spin_lock(&card->spin);
ret = NETDEV_TX_BUSY;
if (!card->fw.up ||
(card->tx.pending >= TXMAX) ||
(priv->tx.pending >= TX_ECHO_SKB_MAX))
goto xmit_done;
fifo_wr = ioread8(&card->dpram[DPRAM_TX_WR]);
fifo_rd = ioread8(&card->dpram[DPRAM_TX_RD]);
if (fifo_wr == fifo_rd)
/* fifo full */
goto xmit_done;
memset(buf, 0, sizeof(buf));
ptr = buf;
*ptr = CMD_TX;
if (cf->can_id & CAN_RTR_FLAG)
*ptr |= CMD_RTR;
if (cf->can_id & CAN_EFF_FLAG)
*ptr |= CMD_XTD;
if (priv->index)
*ptr |= CMD_BUS2;
++ptr;
*ptr++ = cf->can_dlc;
*ptr++ = (cf->can_id >> 0);
*ptr++ = (cf->can_id >> 8);
if (cf->can_id & CAN_EFF_FLAG) {
*ptr++ = (cf->can_id >> 16);
*ptr++ = (cf->can_id >> 24);
} else {
/* increment 1, not 2 as you might think */
ptr += 1;
}
if (!(cf->can_id & CAN_RTR_FLAG))
memcpy(ptr, &cf->data[0], cf->can_dlc);
memcpy_toio(&card->dpram[DPRAM_TX + DPRAM_TX_SIZE * fifo_wr],
buf, DPRAM_TX_SIZE);
if (++fifo_wr >= DPRAM_TX_CNT)
fifo_wr = 0;
iowrite8(fifo_wr, &card->dpram[DPRAM_TX_WR]);
card->tx.last_bus = priv->index;
++card->tx.pending;
++priv->tx.pending;
can_put_echo_skb(skb, dev, priv->tx.echo_put);
++priv->tx.echo_put;
if (priv->tx.echo_put >= TX_ECHO_SKB_MAX)
priv->tx.echo_put = 0;
/* can_put_echo_skb() saves the skb, safe to return TX_OK */
ret = NETDEV_TX_OK;
xmit_done:
spin_unlock(&card->spin);
if (card->tx.pending >= TXMAX) {
int j;
for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
if (card->net[j])
netif_stop_queue(card->net[j]);
}
}
if (ret != NETDEV_TX_OK)
netif_stop_queue(dev);
return ret;
}
/*
* shortcut for skb delivery
*/
int softing_netdev_rx(struct net_device *netdev, const struct can_frame *msg,
ktime_t ktime)
{
struct sk_buff *skb;
struct can_frame *cf;
skb = alloc_can_skb(netdev, &cf);
if (!skb)
return -ENOMEM;
memcpy(cf, msg, sizeof(*msg));
skb->tstamp = ktime;
return netif_rx(skb);
}
/*
* softing_handle_1
* pop 1 entry from the DPRAM queue, and process
*/
static int softing_handle_1(struct softing *card)
{
struct net_device *netdev;
struct softing_priv *priv;
ktime_t ktime;
struct can_frame msg;
int cnt = 0, lost_msg;
uint8_t fifo_rd, fifo_wr, cmd;
uint8_t *ptr;
uint32_t tmp_u32;
uint8_t buf[DPRAM_RX_SIZE];
memset(&msg, 0, sizeof(msg));
/* test for lost msgs */
lost_msg = ioread8(&card->dpram[DPRAM_RX_LOST]);
if (lost_msg) {
int j;
/* reset condition */
iowrite8(0, &card->dpram[DPRAM_RX_LOST]);
/* prepare msg */
msg.can_id = CAN_ERR_FLAG | CAN_ERR_CRTL;
msg.can_dlc = CAN_ERR_DLC;
msg.data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
/*
* service to all busses, we don't know which it was applicable
* but only service busses that are online
*/
for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
netdev = card->net[j];
if (!netdev)
continue;
if (!canif_is_active(netdev))
/* a dead bus has no overflows */
continue;
++netdev->stats.rx_over_errors;
softing_netdev_rx(netdev, &msg, ktime_set(0, 0));
}
/* prepare for other use */
memset(&msg, 0, sizeof(msg));
++cnt;
}
fifo_rd = ioread8(&card->dpram[DPRAM_RX_RD]);
fifo_wr = ioread8(&card->dpram[DPRAM_RX_WR]);
if (++fifo_rd >= DPRAM_RX_CNT)
fifo_rd = 0;
if (fifo_wr == fifo_rd)
return cnt;
memcpy_fromio(buf, &card->dpram[DPRAM_RX + DPRAM_RX_SIZE*fifo_rd],
DPRAM_RX_SIZE);
mb();
/* trigger dual port RAM */
iowrite8(fifo_rd, &card->dpram[DPRAM_RX_RD]);
ptr = buf;
cmd = *ptr++;
if (cmd == 0xff)
/* not quite usefull, probably the card has got out */
return 0;
netdev = card->net[0];
if (cmd & CMD_BUS2)
netdev = card->net[1];
priv = netdev_priv(netdev);
if (cmd & CMD_ERR) {
uint8_t can_state, state;
state = *ptr++;
msg.can_id = CAN_ERR_FLAG;
msg.can_dlc = CAN_ERR_DLC;
if (state & SF_MASK_BUSOFF) {
can_state = CAN_STATE_BUS_OFF;
msg.can_id |= CAN_ERR_BUSOFF;
state = STATE_BUSOFF;
} else if (state & SF_MASK_EPASSIVE) {
can_state = CAN_STATE_ERROR_PASSIVE;
msg.can_id |= CAN_ERR_CRTL;
msg.data[1] = CAN_ERR_CRTL_TX_PASSIVE;
state = STATE_EPASSIVE;
} else {
can_state = CAN_STATE_ERROR_ACTIVE;
msg.can_id |= CAN_ERR_CRTL;
state = STATE_EACTIVE;
}
/* update DPRAM */
iowrite8(state, &card->dpram[priv->index ?
DPRAM_INFO_BUSSTATE2 : DPRAM_INFO_BUSSTATE]);
/* timestamp */
tmp_u32 = le32_to_cpup((void *)ptr);
ptr += 4;
ktime = softing_raw2ktime(card, tmp_u32);
++netdev->stats.rx_errors;
/* update internal status */
if (can_state != priv->can.state) {
priv->can.state = can_state;
if (can_state == CAN_STATE_ERROR_PASSIVE)
++priv->can.can_stats.error_passive;
else if (can_state == CAN_STATE_BUS_OFF) {
/* this calls can_close_cleanup() */
can_bus_off(netdev);
netif_stop_queue(netdev);
}
/* trigger socketcan */
softing_netdev_rx(netdev, &msg, ktime);
}
} else {
if (cmd & CMD_RTR)
msg.can_id |= CAN_RTR_FLAG;
msg.can_dlc = get_can_dlc(*ptr++);
if (cmd & CMD_XTD) {
msg.can_id |= CAN_EFF_FLAG;
msg.can_id |= le32_to_cpup((void *)ptr);
ptr += 4;
} else {
msg.can_id |= le16_to_cpup((void *)ptr);
ptr += 2;
}
/* timestamp */
tmp_u32 = le32_to_cpup((void *)ptr);
ptr += 4;
ktime = softing_raw2ktime(card, tmp_u32);
if (!(msg.can_id & CAN_RTR_FLAG))
memcpy(&msg.data[0], ptr, 8);
ptr += 8;
/* update socket */
if (cmd & CMD_ACK) {
/* acknowledge, was tx msg */
struct sk_buff *skb;
skb = priv->can.echo_skb[priv->tx.echo_get];
if (skb)
skb->tstamp = ktime;
can_get_echo_skb(netdev, priv->tx.echo_get);
++priv->tx.echo_get;
if (priv->tx.echo_get >= TX_ECHO_SKB_MAX)
priv->tx.echo_get = 0;
if (priv->tx.pending)
--priv->tx.pending;
if (card->tx.pending)
--card->tx.pending;
++netdev->stats.tx_packets;
if (!(msg.can_id & CAN_RTR_FLAG))
netdev->stats.tx_bytes += msg.can_dlc;
} else {
int ret;
ret = softing_netdev_rx(netdev, &msg, ktime);
if (ret == NET_RX_SUCCESS) {
++netdev->stats.rx_packets;
if (!(msg.can_id & CAN_RTR_FLAG))
netdev->stats.rx_bytes += msg.can_dlc;
} else {
++netdev->stats.rx_dropped;
}
}
}
++cnt;
return cnt;
}
/*
* real interrupt handler
*/
static irqreturn_t softing_irq_thread(int irq, void *dev_id)
{
struct softing *card = (struct softing *)dev_id;
struct net_device *netdev;
struct softing_priv *priv;
int j, offset, work_done;
work_done = 0;
spin_lock_bh(&card->spin);
while (softing_handle_1(card) > 0) {
++card->irq.svc_count;
++work_done;
}
spin_unlock_bh(&card->spin);
/* resume tx queue's */
offset = card->tx.last_bus;
for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
if (card->tx.pending >= TXMAX)
break;
netdev = card->net[(j + offset + 1) % card->pdat->nbus];
if (!netdev)
continue;
priv = netdev_priv(netdev);
if (!canif_is_active(netdev))
/* it makes no sense to wake dead busses */
continue;
if (priv->tx.pending >= TX_ECHO_SKB_MAX)
continue;
++work_done;
netif_wake_queue(netdev);
}
return work_done ? IRQ_HANDLED : IRQ_NONE;
}
/*
* interrupt routines:
* schedule the 'real interrupt handler'
*/
static irqreturn_t softing_irq_v2(int irq, void *dev_id)
{
struct softing *card = (struct softing *)dev_id;
uint8_t ir;
ir = ioread8(&card->dpram[DPRAM_V2_IRQ_TOHOST]);
iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]);
return (1 == ir) ? IRQ_WAKE_THREAD : IRQ_NONE;
}
static irqreturn_t softing_irq_v1(int irq, void *dev_id)
{
struct softing *card = (struct softing *)dev_id;
uint8_t ir;
ir = ioread8(&card->dpram[DPRAM_IRQ_TOHOST]);
iowrite8(0, &card->dpram[DPRAM_IRQ_TOHOST]);
return ir ? IRQ_WAKE_THREAD : IRQ_NONE;
}
/*
* netdev/candev inter-operability
*/
static int softing_netdev_open(struct net_device *ndev)
{
int ret;
/* check or determine and set bittime */
ret = open_candev(ndev);
if (!ret)
ret = softing_startstop(ndev, 1);
return ret;
}
static int softing_netdev_stop(struct net_device *ndev)
{
int ret;
netif_stop_queue(ndev);
/* softing cycle does close_candev() */
ret = softing_startstop(ndev, 0);
return ret;
}
static int softing_candev_set_mode(struct net_device *ndev, enum can_mode mode)
{
int ret;
switch (mode) {
case CAN_MODE_START:
/* softing_startstop does close_candev() */
ret = softing_startstop(ndev, 1);
return ret;
case CAN_MODE_STOP:
case CAN_MODE_SLEEP:
return -EOPNOTSUPP;
}
return 0;
}
/*
* Softing device management helpers
*/
int softing_enable_irq(struct softing *card, int enable)
{
int ret;
if (!card->irq.nr) {
return 0;
} else if (card->irq.requested && !enable) {
free_irq(card->irq.nr, card);
card->irq.requested = 0;
} else if (!card->irq.requested && enable) {
ret = request_threaded_irq(card->irq.nr,
(card->pdat->generation >= 2) ?
softing_irq_v2 : softing_irq_v1,
softing_irq_thread, IRQF_SHARED,
dev_name(&card->pdev->dev), card);
if (ret) {
dev_alert(&card->pdev->dev,
"request_threaded_irq(%u) failed\n",
card->irq.nr);
return ret;
}
card->irq.requested = 1;
}
return 0;
}
static void softing_card_shutdown(struct softing *card)
{
int fw_up = 0;
if (mutex_lock_interruptible(&card->fw.lock))
/* return -ERESTARTSYS */;
fw_up = card->fw.up;
card->fw.up = 0;
if (card->irq.requested && card->irq.nr) {
free_irq(card->irq.nr, card);
card->irq.requested = 0;
}
if (fw_up) {
if (card->pdat->enable_irq)
card->pdat->enable_irq(card->pdev, 0);
softing_set_reset_dpram(card);
if (card->pdat->reset)
card->pdat->reset(card->pdev, 1);
}
mutex_unlock(&card->fw.lock);
}
static __devinit int softing_card_boot(struct softing *card)
{
int ret, j;
static const uint8_t stream[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, };
unsigned char back[sizeof(stream)];
if (mutex_lock_interruptible(&card->fw.lock))
return -ERESTARTSYS;
if (card->fw.up) {
mutex_unlock(&card->fw.lock);
return 0;
}
/* reset board */
if (card->pdat->enable_irq)
card->pdat->enable_irq(card->pdev, 1);
/* boot card */
softing_set_reset_dpram(card);
if (card->pdat->reset)
card->pdat->reset(card->pdev, 1);
for (j = 0; (j + sizeof(stream)) < card->dpram_size;
j += sizeof(stream)) {
memcpy_toio(&card->dpram[j], stream, sizeof(stream));
/* flush IO cache */
mb();
memcpy_fromio(back, &card->dpram[j], sizeof(stream));
if (!memcmp(back, stream, sizeof(stream)))
continue;
/* memory is not equal */
dev_alert(&card->pdev->dev, "dpram failed at 0x%04x\n", j);
ret = -EIO;
goto failed;
}
wmb();
/* load boot firmware */
ret = softing_load_fw(card->pdat->boot.fw, card, card->dpram,
card->dpram_size,
card->pdat->boot.offs - card->pdat->boot.addr);
if (ret < 0)
goto failed;
/* load loader firmware */
ret = softing_load_fw(card->pdat->load.fw, card, card->dpram,
card->dpram_size,
card->pdat->load.offs - card->pdat->load.addr);
if (ret < 0)
goto failed;
if (card->pdat->reset)
card->pdat->reset(card->pdev, 0);
softing_clr_reset_dpram(card);
ret = softing_bootloader_command(card, 0, "card boot");
if (ret < 0)
goto failed;
ret = softing_load_app_fw(card->pdat->app.fw, card);
if (ret < 0)
goto failed;
ret = softing_chip_poweron(card);
if (ret < 0)
goto failed;
card->fw.up = 1;
mutex_unlock(&card->fw.lock);
return 0;
failed:
card->fw.up = 0;
if (card->pdat->enable_irq)
card->pdat->enable_irq(card->pdev, 0);
softing_set_reset_dpram(card);
if (card->pdat->reset)
card->pdat->reset(card->pdev, 1);
mutex_unlock(&card->fw.lock);
return ret;
}
/*
* netdev sysfs
*/
static ssize_t show_channel(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct net_device *ndev = to_net_dev(dev);
struct softing_priv *priv = netdev2softing(ndev);
return sprintf(buf, "%i\n", priv->index);
}
static ssize_t show_chip(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct net_device *ndev = to_net_dev(dev);
struct softing_priv *priv = netdev2softing(ndev);
return sprintf(buf, "%i\n", priv->chip);
}
static ssize_t show_output(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct net_device *ndev = to_net_dev(dev);
struct softing_priv *priv = netdev2softing(ndev);
return sprintf(buf, "0x%02x\n", priv->output);
}
static ssize_t store_output(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct net_device *ndev = to_net_dev(dev);
struct softing_priv *priv = netdev2softing(ndev);
struct softing *card = priv->card;
unsigned long val;
int ret;
ret = strict_strtoul(buf, 0, &val);
if (ret < 0)
return ret;
val &= 0xFF;
ret = mutex_lock_interruptible(&card->fw.lock);
if (ret)
return -ERESTARTSYS;
if (netif_running(ndev)) {
mutex_unlock(&card->fw.lock);
return -EBUSY;
}
priv->output = val;
mutex_unlock(&card->fw.lock);
return count;
}
static const DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL);
static const DEVICE_ATTR(chip, S_IRUGO, show_chip, NULL);
static const DEVICE_ATTR(output, S_IRUGO | S_IWUSR, show_output, store_output);
static const struct attribute *const netdev_sysfs_attrs[] = {
&dev_attr_channel.attr,
&dev_attr_chip.attr,
&dev_attr_output.attr,
NULL,
};
static const struct attribute_group netdev_sysfs_group = {
.name = NULL,
.attrs = (struct attribute **)netdev_sysfs_attrs,
};
static const struct net_device_ops softing_netdev_ops = {
.ndo_open = softing_netdev_open,
.ndo_stop = softing_netdev_stop,
.ndo_start_xmit = softing_netdev_start_xmit,
};
static const struct can_bittiming_const softing_btr_const = {
.tseg1_min = 1,
.tseg1_max = 16,
.tseg2_min = 1,
.tseg2_max = 8,
.sjw_max = 4, /* overruled */
.brp_min = 1,
.brp_max = 32, /* overruled */
.brp_inc = 1,
};
static __devinit struct net_device *softing_netdev_create(struct softing *card,
uint16_t chip_id)
{
struct net_device *netdev;
struct softing_priv *priv;
netdev = alloc_candev(sizeof(*priv), TX_ECHO_SKB_MAX);
if (!netdev) {
dev_alert(&card->pdev->dev, "alloc_candev failed\n");
return NULL;
}
priv = netdev_priv(netdev);
priv->netdev = netdev;
priv->card = card;
memcpy(&priv->btr_const, &softing_btr_const, sizeof(priv->btr_const));
priv->btr_const.brp_max = card->pdat->max_brp;
priv->btr_const.sjw_max = card->pdat->max_sjw;
priv->can.bittiming_const = &priv->btr_const;
priv->can.clock.freq = 8000000;
priv->chip = chip_id;
priv->output = softing_default_output(netdev);
SET_NETDEV_DEV(netdev, &card->pdev->dev);
netdev->flags |= IFF_ECHO;
netdev->netdev_ops = &softing_netdev_ops;
priv->can.do_set_mode = softing_candev_set_mode;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
return netdev;
}
static __devinit int softing_netdev_register(struct net_device *netdev)
{
int ret;
netdev->sysfs_groups[0] = &netdev_sysfs_group;
ret = register_candev(netdev);
if (ret) {
dev_alert(&netdev->dev, "register failed\n");
return ret;
}
return 0;
}
static void softing_netdev_cleanup(struct net_device *netdev)
{
unregister_candev(netdev);
free_candev(netdev);
}
/*
* sysfs for Platform device
*/
#define DEV_ATTR_RO(name, member) \
static ssize_t show_##name(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct softing *card = platform_get_drvdata(to_platform_device(dev)); \
return sprintf(buf, "%u\n", card->member); \
} \
static DEVICE_ATTR(name, 0444, show_##name, NULL)
#define DEV_ATTR_RO_STR(name, member) \
static ssize_t show_##name(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct softing *card = platform_get_drvdata(to_platform_device(dev)); \
return sprintf(buf, "%s\n", card->member); \
} \
static DEVICE_ATTR(name, 0444, show_##name, NULL)
DEV_ATTR_RO(serial, id.serial);
DEV_ATTR_RO_STR(firmware, pdat->app.fw);
DEV_ATTR_RO(firmware_version, id.fw_version);
DEV_ATTR_RO_STR(hardware, pdat->name);
DEV_ATTR_RO(hardware_version, id.hw_version);
DEV_ATTR_RO(license, id.license);
DEV_ATTR_RO(frequency, id.freq);
DEV_ATTR_RO(txpending, tx.pending);
static struct attribute *softing_pdev_attrs[] = {
&dev_attr_serial.attr,
&dev_attr_firmware.attr,
&dev_attr_firmware_version.attr,
&dev_attr_hardware.attr,
&dev_attr_hardware_version.attr,
&dev_attr_license.attr,
&dev_attr_frequency.attr,
&dev_attr_txpending.attr,
NULL,
};
static const struct attribute_group softing_pdev_group = {
.name = NULL,
.attrs = softing_pdev_attrs,
};
/*
* platform driver
*/
static __devexit int softing_pdev_remove(struct platform_device *pdev)
{
struct softing *card = platform_get_drvdata(pdev);
int j;
/* first, disable card*/
softing_card_shutdown(card);
for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
if (!card->net[j])
continue;
softing_netdev_cleanup(card->net[j]);
card->net[j] = NULL;
}
sysfs_remove_group(&pdev->dev.kobj, &softing_pdev_group);
iounmap(card->dpram);
kfree(card);
return 0;
}
static __devinit int softing_pdev_probe(struct platform_device *pdev)
{
const struct softing_platform_data *pdat = pdev->dev.platform_data;
struct softing *card;
struct net_device *netdev;
struct softing_priv *priv;
struct resource *pres;
int ret;
int j;
if (!pdat) {
dev_warn(&pdev->dev, "no platform data\n");
return -EINVAL;
}
if (pdat->nbus > ARRAY_SIZE(card->net)) {
dev_warn(&pdev->dev, "%u nets??\n", pdat->nbus);
return -EINVAL;
}
card = kzalloc(sizeof(*card), GFP_KERNEL);
if (!card)
return -ENOMEM;
card->pdat = pdat;
card->pdev = pdev;
platform_set_drvdata(pdev, card);
mutex_init(&card->fw.lock);
spin_lock_init(&card->spin);
ret = -EINVAL;
pres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!pres)
goto platform_resource_failed;;
card->dpram_phys = pres->start;
card->dpram_size = pres->end - pres->start + 1;
card->dpram = ioremap_nocache(card->dpram_phys, card->dpram_size);
if (!card->dpram) {
dev_alert(&card->pdev->dev, "dpram ioremap failed\n");
goto ioremap_failed;
}
pres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (pres)
card->irq.nr = pres->start;
/* reset card */
ret = softing_card_boot(card);
if (ret < 0) {
dev_alert(&pdev->dev, "failed to boot\n");
goto boot_failed;
}
/* only now, the chip's are known */
card->id.freq = card->pdat->freq;
ret = sysfs_create_group(&pdev->dev.kobj, &softing_pdev_group);
if (ret < 0) {
dev_alert(&card->pdev->dev, "sysfs failed\n");
goto sysfs_failed;
}
ret = -ENOMEM;
for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
card->net[j] = netdev =
softing_netdev_create(card, card->id.chip[j]);
if (!netdev) {
dev_alert(&pdev->dev, "failed to make can[%i]", j);
goto netdev_failed;
}
priv = netdev_priv(card->net[j]);
priv->index = j;
ret = softing_netdev_register(netdev);
if (ret) {
free_candev(netdev);
card->net[j] = NULL;
dev_alert(&card->pdev->dev,
"failed to register can[%i]\n", j);
goto netdev_failed;
}
}
dev_info(&card->pdev->dev, "%s ready.\n", card->pdat->name);
return 0;
netdev_failed:
for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
if (!card->net[j])
continue;
softing_netdev_cleanup(card->net[j]);
}
sysfs_remove_group(&pdev->dev.kobj, &softing_pdev_group);
sysfs_failed:
softing_card_shutdown(card);
boot_failed:
iounmap(card->dpram);
ioremap_failed:
platform_resource_failed:
kfree(card);
return ret;
}
static struct platform_driver softing_driver = {
.driver = {
.name = "softing",
.owner = THIS_MODULE,
},
.probe = softing_pdev_probe,
.remove = __devexit_p(softing_pdev_remove),
};
MODULE_ALIAS("platform:softing");
static int __init softing_start(void)
{
return platform_driver_register(&softing_driver);
}
static void __exit softing_stop(void)
{
platform_driver_unregister(&softing_driver);
}
module_init(softing_start);
module_exit(softing_stop);
MODULE_DESCRIPTION("Softing DPRAM CAN driver");
MODULE_AUTHOR("Kurt Van Dijck <kurt.van.dijck@eia.be>");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,40 @@
#include <linux/platform_device.h>
#ifndef _SOFTING_DEVICE_H_
#define _SOFTING_DEVICE_H_
/* softing firmware directory prefix */
#define fw_dir "softing-4.6/"
struct softing_platform_data {
unsigned int manf;
unsigned int prod;
/*
* generation
* 1st with NEC or SJA1000
* 8bit, exclusive interrupt, ...
* 2nd only SJA1000
* 16bit, shared interrupt
*/
int generation;
int nbus; /* # busses on device */
unsigned int freq; /* operating frequency in Hz */
unsigned int max_brp;
unsigned int max_sjw;
unsigned long dpram_size;
const char *name;
struct {
unsigned long offs;
unsigned long addr;
const char *fw;
} boot, load, app;
/*
* reset() function
* bring pdev in or out of reset, depending on value
*/
int (*reset)(struct platform_device *pdev, int value);
int (*enable_irq)(struct platform_device *pdev, int value);
};
#endif

View file

@ -699,13 +699,13 @@ static void cnic_free_dma(struct cnic_dev *dev, struct cnic_dma *dma)
static void cnic_setup_page_tbl(struct cnic_dev *dev, struct cnic_dma *dma)
{
int i;
u32 *page_table = dma->pgtbl;
__le32 *page_table = (__le32 *) dma->pgtbl;
for (i = 0; i < dma->num_pages; i++) {
/* Each entry needs to be in big endian format. */
*page_table = (u32) ((u64) dma->pg_map_arr[i] >> 32);
*page_table = cpu_to_le32((u64) dma->pg_map_arr[i] >> 32);
page_table++;
*page_table = (u32) dma->pg_map_arr[i];
*page_table = cpu_to_le32(dma->pg_map_arr[i] & 0xffffffff);
page_table++;
}
}
@ -713,13 +713,13 @@ static void cnic_setup_page_tbl(struct cnic_dev *dev, struct cnic_dma *dma)
static void cnic_setup_page_tbl_le(struct cnic_dev *dev, struct cnic_dma *dma)
{
int i;
u32 *page_table = dma->pgtbl;
__le32 *page_table = (__le32 *) dma->pgtbl;
for (i = 0; i < dma->num_pages; i++) {
/* Each entry needs to be in little endian format. */
*page_table = dma->pg_map_arr[i] & 0xffffffff;
*page_table = cpu_to_le32(dma->pg_map_arr[i] & 0xffffffff);
page_table++;
*page_table = (u32) ((u64) dma->pg_map_arr[i] >> 32);
*page_table = cpu_to_le32((u64) dma->pg_map_arr[i] >> 32);
page_table++;
}
}

View file

@ -2710,6 +2710,8 @@ static int cxgb_open(struct net_device *dev)
struct port_info *pi = netdev_priv(dev);
struct adapter *adapter = pi->adapter;
netif_carrier_off(dev);
if (!(adapter->flags & FULL_INIT_DONE)) {
err = cxgb_up(adapter);
if (err < 0)
@ -3661,7 +3663,6 @@ static int __devinit init_one(struct pci_dev *pdev,
pi->xact_addr_filt = -1;
pi->rx_offload = RX_CSO;
pi->port_id = i;
netif_carrier_off(netdev);
netdev->irq = pdev->irq;
netdev->features |= NETIF_F_SG | TSO_FLAGS;

View file

@ -2247,7 +2247,7 @@ static void pch_gbe_remove(struct pci_dev *pdev)
struct net_device *netdev = pci_get_drvdata(pdev);
struct pch_gbe_adapter *adapter = netdev_priv(netdev);
flush_scheduled_work();
cancel_work_sync(&adapter->reset_task);
unregister_netdev(netdev);
pch_gbe_hal_phy_hw_reset(&adapter->hw);

View file

@ -60,12 +60,6 @@
#define BAR_0 0
#define BAR_2 2
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#define TG3_VLAN_TAG_USED 1
#else
#define TG3_VLAN_TAG_USED 0
#endif
#include "tg3.h"
#define DRV_MODULE_NAME "tg3"
@ -134,9 +128,6 @@
TG3_TX_RING_SIZE)
#define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1))
#define TG3_RX_DMA_ALIGN 16
#define TG3_RX_HEADROOM ALIGN(VLAN_HLEN, TG3_RX_DMA_ALIGN)
#define TG3_DMA_BYTE_ENAB 64
#define TG3_RX_STD_DMA_SZ 1536
@ -4722,8 +4713,6 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
struct sk_buff *skb;
dma_addr_t dma_addr;
u32 opaque_key, desc_idx, *post_ptr;
bool hw_vlan __maybe_unused = false;
u16 vtag __maybe_unused = 0;
desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
@ -4782,12 +4771,12 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
tg3_recycle_rx(tnapi, tpr, opaque_key,
desc_idx, *post_ptr);
copy_skb = netdev_alloc_skb(tp->dev, len + VLAN_HLEN +
copy_skb = netdev_alloc_skb(tp->dev, len +
TG3_RAW_IP_ALIGN);
if (copy_skb == NULL)
goto drop_it_no_recycle;
skb_reserve(copy_skb, TG3_RAW_IP_ALIGN + VLAN_HLEN);
skb_reserve(copy_skb, TG3_RAW_IP_ALIGN);
skb_put(copy_skb, len);
pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE);
skb_copy_from_linear_data(skb, copy_skb->data, len);
@ -4814,30 +4803,11 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
}
if (desc->type_flags & RXD_FLAG_VLAN &&
!(tp->rx_mode & RX_MODE_KEEP_VLAN_TAG)) {
vtag = desc->err_vlan & RXD_VLAN_MASK;
#if TG3_VLAN_TAG_USED
if (tp->vlgrp)
hw_vlan = true;
else
#endif
{
struct vlan_ethhdr *ve = (struct vlan_ethhdr *)
__skb_push(skb, VLAN_HLEN);
!(tp->rx_mode & RX_MODE_KEEP_VLAN_TAG))
__vlan_hwaccel_put_tag(skb,
desc->err_vlan & RXD_VLAN_MASK);
memmove(ve, skb->data + VLAN_HLEN,
ETH_ALEN * 2);
ve->h_vlan_proto = htons(ETH_P_8021Q);
ve->h_vlan_TCI = htons(vtag);
}
}
#if TG3_VLAN_TAG_USED
if (hw_vlan)
vlan_gro_receive(&tnapi->napi, tp->vlgrp, vtag, skb);
else
#endif
napi_gro_receive(&tnapi->napi, skb);
napi_gro_receive(&tnapi->napi, skb);
received++;
budget--;
@ -5740,11 +5710,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
base_flags |= TXD_FLAG_TCPUDP_CSUM;
}
#if TG3_VLAN_TAG_USED
if (vlan_tx_tag_present(skb))
base_flags |= (TXD_FLAG_VLAN |
(vlan_tx_tag_get(skb) << 16));
#endif
len = skb_headlen(skb);
@ -5986,11 +5954,10 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
}
}
}
#if TG3_VLAN_TAG_USED
if (vlan_tx_tag_present(skb))
base_flags |= (TXD_FLAG_VLAN |
(vlan_tx_tag_get(skb) << 16));
#endif
if ((tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) &&
!mss && skb->len > VLAN_ETH_FRAME_LEN)
@ -9532,17 +9499,10 @@ static void __tg3_set_rx_mode(struct net_device *dev)
rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC |
RX_MODE_KEEP_VLAN_TAG);
#if !defined(CONFIG_VLAN_8021Q) && !defined(CONFIG_VLAN_8021Q_MODULE)
/* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG
* flag clear.
*/
#if TG3_VLAN_TAG_USED
if (!tp->vlgrp &&
!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
rx_mode |= RX_MODE_KEEP_VLAN_TAG;
#else
/* By definition, VLAN is disabled always in this
* case.
*/
if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
rx_mode |= RX_MODE_KEEP_VLAN_TAG;
#endif
@ -11230,31 +11190,6 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EOPNOTSUPP;
}
#if TG3_VLAN_TAG_USED
static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
{
struct tg3 *tp = netdev_priv(dev);
if (!netif_running(dev)) {
tp->vlgrp = grp;
return;
}
tg3_netif_stop(tp);
tg3_full_lock(tp, 0);
tp->vlgrp = grp;
/* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */
__tg3_set_rx_mode(dev);
tg3_netif_start(tp);
tg3_full_unlock(tp);
}
#endif
static int tg3_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
{
struct tg3 *tp = netdev_priv(dev);
@ -13066,9 +13001,7 @@ static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
static void inline vlan_features_add(struct net_device *dev, unsigned long flags)
{
#if TG3_VLAN_TAG_USED
dev->vlan_features |= flags;
#endif
}
static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp)
@ -13861,11 +13794,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
else
tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
tp->rx_offset = NET_IP_ALIGN + TG3_RX_HEADROOM;
tp->rx_offset = NET_IP_ALIGN;
tp->rx_copy_thresh = TG3_RX_COPY_THRESHOLD;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
(tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) {
tp->rx_offset -= NET_IP_ALIGN;
tp->rx_offset = 0;
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
tp->rx_copy_thresh = ~(u16)0;
#endif
@ -14629,9 +14562,6 @@ static const struct net_device_ops tg3_netdev_ops = {
.ndo_do_ioctl = tg3_ioctl,
.ndo_tx_timeout = tg3_tx_timeout,
.ndo_change_mtu = tg3_change_mtu,
#if TG3_VLAN_TAG_USED
.ndo_vlan_rx_register = tg3_vlan_rx_register,
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = tg3_poll_controller,
#endif
@ -14648,9 +14578,6 @@ static const struct net_device_ops tg3_netdev_ops_dma_bug = {
.ndo_do_ioctl = tg3_ioctl,
.ndo_tx_timeout = tg3_tx_timeout,
.ndo_change_mtu = tg3_change_mtu,
#if TG3_VLAN_TAG_USED
.ndo_vlan_rx_register = tg3_vlan_rx_register,
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = tg3_poll_controller,
#endif
@ -14700,9 +14627,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
SET_NETDEV_DEV(dev, &pdev->dev);
#if TG3_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
#endif
tp = netdev_priv(dev);
tp->pdev = pdev;

View file

@ -2808,9 +2808,6 @@ struct tg3 {
u32 rx_std_max_post;
u32 rx_offset;
u32 rx_pkt_map_sz;
#if TG3_VLAN_TAG_USED
struct vlan_group *vlgrp;
#endif
/* begin "everything else" cacheline(s) section */

View file

@ -406,6 +406,7 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth,
if (fw->size > KAWETH_FIRMWARE_BUF_SIZE) {
err("Firmware too big: %zu", fw->size);
release_firmware(fw);
return -ENOSPC;
}
data_len = fw->size;

View file

@ -369,6 +369,9 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
else
ah->config.ht_enable = 0;
/* PAPRD needs some more work to be enabled */
ah->config.paprd_disable = 1;
ah->config.rx_intr_mitigation = true;
ah->config.pcieSerDesWrite = true;
@ -1933,7 +1936,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->rx_status_len = sizeof(struct ar9003_rxs);
pCap->tx_desc_len = sizeof(struct ar9003_txc);
pCap->txs_len = sizeof(struct ar9003_txs);
if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
if (!ah->config.paprd_disable &&
ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
} else {
pCap->tx_desc_len = sizeof(struct ath_desc);

View file

@ -225,6 +225,7 @@ struct ath9k_ops_config {
u32 pcie_waen;
u8 analog_shiftreg;
u8 ht_enable;
u8 paprd_disable;
u32 ofdm_trig_low;
u32 ofdm_trig_high;
u32 cck_trig_high;

View file

@ -592,14 +592,12 @@ void ath9k_tasklet(unsigned long data)
u32 status = sc->intrstatus;
u32 rxmask;
ath9k_ps_wakeup(sc);
if (status & ATH9K_INT_FATAL) {
ath_reset(sc, true);
ath9k_ps_restore(sc);
return;
}
ath9k_ps_wakeup(sc);
spin_lock(&sc->sc_pcu_lock);
if (!ath9k_hw_check_alive(ah))
@ -969,6 +967,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
/* Stop ANI */
del_timer_sync(&common->ani.timer);
ath9k_ps_wakeup(sc);
spin_lock_bh(&sc->sc_pcu_lock);
ieee80211_stop_queues(hw);
@ -1015,6 +1014,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
/* Start ANI */
ath_start_ani(common);
ath9k_ps_restore(sc);
return r;
}
@ -1701,7 +1701,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
skip_chan_change:
if (changed & IEEE80211_CONF_CHANGE_POWER) {
sc->config.txpowlimit = 2 * conf->power_level;
ath9k_ps_wakeup(sc);
ath_update_txpow(sc);
ath9k_ps_restore(sc);
}
spin_lock_bh(&sc->wiphy_lock);

View file

@ -2113,9 +2113,7 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
if (needreset) {
ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
"tx hung, resetting the chip\n");
ath9k_ps_wakeup(sc);
ath_reset(sc, true);
ath9k_ps_restore(sc);
}
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,

View file

@ -2624,6 +2624,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
.fw_name_pre = IWL4965_FW_PRE,
.ucode_api_max = IWL4965_UCODE_API_MAX,
.ucode_api_min = IWL4965_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.valid_tx_ant = ANT_AB,
.valid_rx_ant = ANT_ABC,
.eeprom_ver = EEPROM_4965_EEPROM_VERSION,

View file

@ -152,11 +152,14 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv)
eeprom_sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
priv->cfg->sku = ((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >>
if (!priv->cfg->sku) {
/* not using sku overwrite */
priv->cfg->sku =
((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >>
EEPROM_SKU_CAP_BAND_POS);
if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE)
priv->cfg->sku |= IWL_SKU_N;
if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE)
priv->cfg->sku |= IWL_SKU_N;
}
if (!priv->cfg->sku) {
IWL_ERR(priv, "Invalid device sku\n");
return -EINVAL;

View file

@ -2446,6 +2446,7 @@ static struct usb_device_id rt73usb_device_table[] = {
{ USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0812, 0x3101), USB_DEVICE_DATA(&rt73usb_ops) },
/* Qcom */
{ USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) },

View file

@ -619,6 +619,13 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
struct sk_buff *uskb = NULL;
u8 *pdata;
uskb = dev_alloc_skb(skb->len + 128);
if (!uskb) {
RT_TRACE(rtlpriv,
(COMP_INTR | COMP_RECV),
DBG_EMERG,
("can't alloc rx skb\n"));
goto done;
}
memcpy(IEEE80211_SKB_RXCB(uskb),
&rx_status,
sizeof(rx_status));
@ -641,7 +648,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
if (unlikely(!new_skb)) {
RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
DBG_DMESG,
DBG_EMERG,
("can't alloc skb for rx\n"));
goto done;
}
@ -1066,9 +1073,9 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw)
struct sk_buff *skb =
dev_alloc_skb(rtlpci->rxbuffersize);
u32 bufferaddress;
entry = &rtlpci->rx_ring[rx_queue_idx].desc[i];
if (!skb)
return 0;
entry = &rtlpci->rx_ring[rx_queue_idx].desc[i];
/*skb->dev = dev; */

View file

@ -26,7 +26,6 @@
#include <linux/sfi.h>
#include <asm/mrst.h>
#include <asm/intel_scu_ipc.h>
#include <asm/mrst.h>
/* IPC defines the following message types */
#define IPCMSG_WATCHDOG_TIMER 0xF8 /* Set Kernel Watchdog Threshold */

View file

@ -360,8 +360,8 @@ int PSSendOps(void *arg)
status = 1;
goto complete;
}
len = (firmware->size > MAX_BDADDR_FORMAT_LENGTH)? MAX_BDADDR_FORMAT_LENGTH: firmware->size;
memcpy(config_bdaddr, firmware->data,len);
len = min(firmware->size, MAX_BDADDR_FORMAT_LENGTH - 1);
memcpy(config_bdaddr, firmware->data, len);
config_bdaddr[len] = '\0';
write_bdaddr(hdev,config_bdaddr,BDADDR_TYPE_STRING);
A_RELEASE_FIRMWARE(firmware);

View file

@ -209,11 +209,8 @@ static void wl_ops_stop(struct ieee80211_hw *hw)
struct wl_info *wl = hw->priv;
ASSERT(wl);
WL_LOCK(wl);
wl_down(wl);
ieee80211_stop_queues(hw);
WL_UNLOCK(wl);
return;
}
static int
@ -246,7 +243,14 @@ wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
static void
wl_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
return;
struct wl_info *wl;
wl = HW_TO_WL(hw);
/* put driver in down state */
WL_LOCK(wl);
wl_down(wl);
WL_UNLOCK(wl);
}
static int
@ -779,7 +783,7 @@ static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
wl_found++;
return wl;
fail:
fail:
wl_free(wl);
fail1:
return NULL;
@ -1090,7 +1094,6 @@ wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
}
#ifdef LINUXSTA_PS
static int wl_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct wl_info *wl;
@ -1105,11 +1108,12 @@ static int wl_suspend(struct pci_dev *pdev, pm_message_t state)
return -ENODEV;
}
/* only need to flag hw is down for proper resume */
WL_LOCK(wl);
wl_down(wl);
wl->pub->hw_up = false;
WL_UNLOCK(wl);
pci_save_state(pdev, wl->pci_psstate);
pci_save_state(pdev);
pci_disable_device(pdev);
return pci_set_power_state(pdev, PCI_D3hot);
}
@ -1133,7 +1137,7 @@ static int wl_resume(struct pci_dev *pdev)
if (err)
return err;
pci_restore_state(pdev, wl->pci_psstate);
pci_restore_state(pdev);
err = pci_enable_device(pdev);
if (err)
@ -1145,13 +1149,12 @@ static int wl_resume(struct pci_dev *pdev)
if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
WL_LOCK(wl);
err = wl_up(wl);
WL_UNLOCK(wl);
/*
* done. driver will be put in up state
* in wl_ops_add_interface() call.
*/
return err;
}
#endif /* LINUXSTA_PS */
static void wl_remove(struct pci_dev *pdev)
{
@ -1184,14 +1187,12 @@ static void wl_remove(struct pci_dev *pdev)
}
static struct pci_driver wl_pci_driver = {
.name = "brcm80211",
.probe = wl_pci_probe,
#ifdef LINUXSTA_PS
.suspend = wl_suspend,
.resume = wl_resume,
#endif /* LINUXSTA_PS */
.remove = __devexit_p(wl_remove),
.id_table = wl_id_table,
.name = "brcm80211",
.probe = wl_pci_probe,
.suspend = wl_suspend,
.resume = wl_resume,
.remove = __devexit_p(wl_remove),
.id_table = wl_id_table,
};
/**

Some files were not shown because too many files have changed in this diff Show more