Automatic merge of rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git branch HEAD
This commit is contained in:
commit
edb3e182b6
|
@ -1163,7 +1163,7 @@ config PCI_DIRECT
|
|||
|
||||
config PCI_MMCONFIG
|
||||
bool
|
||||
depends on PCI && (PCI_GOMMCONFIG || (PCI_GOANY && ACPI))
|
||||
depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
|
||||
select ACPI_BOOT
|
||||
default y
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ struct _cpuid4_info {
|
|||
};
|
||||
|
||||
#define MAX_CACHE_LEAVES 4
|
||||
static unsigned short __devinitdata num_cache_leaves;
|
||||
static unsigned short num_cache_leaves;
|
||||
|
||||
static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
|
||||
{
|
||||
|
|
|
@ -1074,8 +1074,10 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
|
|||
cpu_set(cpu, cpu_sibling_map[cpu]);
|
||||
}
|
||||
|
||||
if (siblings != smp_num_siblings)
|
||||
if (siblings != smp_num_siblings) {
|
||||
printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
|
||||
smp_num_siblings = siblings;
|
||||
}
|
||||
|
||||
if (c->x86_num_cores > 1) {
|
||||
for (i = 0; i < NR_CPUS; i++) {
|
||||
|
|
|
@ -1029,7 +1029,6 @@ void pcibios_penalize_isa_irq(int irq)
|
|||
static int pirq_enable_irq(struct pci_dev *dev)
|
||||
{
|
||||
u8 pin;
|
||||
extern int via_interrupt_line_quirk;
|
||||
struct pci_dev *temp_dev;
|
||||
|
||||
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
|
||||
|
@ -1084,10 +1083,6 @@ static int pirq_enable_irq(struct pci_dev *dev)
|
|||
printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
|
||||
'A' + pin, pci_name(dev), msg);
|
||||
}
|
||||
/* VIA bridges use interrupt line for apic/pci steering across
|
||||
the V-Link */
|
||||
else if (via_interrupt_line_quirk)
|
||||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq & 15);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1143,12 +1143,12 @@ config PCI_QSPAN
|
|||
|
||||
config PCI_8260
|
||||
bool
|
||||
depends on PCI && 8260 && !8272
|
||||
depends on PCI && 8260
|
||||
default y
|
||||
|
||||
config 8260_PCI9
|
||||
bool " Enable workaround for MPC826x erratum PCI 9"
|
||||
depends on PCI_8260
|
||||
depends on PCI_8260 && !ADS8272
|
||||
default y
|
||||
|
||||
choice
|
||||
|
|
|
@ -22,7 +22,8 @@ targets += uImage
|
|||
$(obj)/uImage: $(obj)/vmlinux.gz
|
||||
$(Q)rm -f $@
|
||||
$(call if_changed,uimage)
|
||||
@echo ' Image: $@' $(if $(wildcard $@),'is ready','not made')
|
||||
@echo -n ' Image: $@ '
|
||||
@if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
|
||||
|
||||
# Files generated that shall be removed upon make clean
|
||||
clean-files := sImage vmapus vmlinux* miboot* zImage* uImage
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.11-rc1
|
||||
# Thu Jan 20 01:25:35 2005
|
||||
# Linux kernel version: 2.6.12-rc4
|
||||
# Tue May 17 11:56:01 2005
|
||||
#
|
||||
CONFIG_MMU=y
|
||||
CONFIG_GENERIC_HARDIRQS=y
|
||||
|
@ -11,6 +11,7 @@ CONFIG_HAVE_DEC_LOCK=y
|
|||
CONFIG_PPC=y
|
||||
CONFIG_PPC32=y
|
||||
CONFIG_GENERIC_NVRAM=y
|
||||
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
||||
|
||||
#
|
||||
# Code maturity level options
|
||||
|
@ -18,6 +19,7 @@ CONFIG_GENERIC_NVRAM=y
|
|||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_CLEAN_COMPILE=y
|
||||
CONFIG_BROKEN_ON_SMP=y
|
||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||
|
||||
#
|
||||
# General setup
|
||||
|
@ -29,12 +31,14 @@ CONFIG_SYSVIPC=y
|
|||
# CONFIG_BSD_PROCESS_ACCT is not set
|
||||
CONFIG_SYSCTL=y
|
||||
# CONFIG_AUDIT is not set
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_HOTPLUG is not set
|
||||
CONFIG_KOBJECT_UEVENT=y
|
||||
# CONFIG_IKCONFIG is not set
|
||||
CONFIG_EMBEDDED=y
|
||||
# CONFIG_KALLSYMS is not set
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_BUG=y
|
||||
CONFIG_BASE_FULL=y
|
||||
CONFIG_FUTEX=y
|
||||
# CONFIG_EPOLL is not set
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
|
@ -44,6 +48,7 @@ CONFIG_CC_ALIGN_LABELS=0
|
|||
CONFIG_CC_ALIGN_LOOPS=0
|
||||
CONFIG_CC_ALIGN_JUMPS=0
|
||||
# CONFIG_TINY_SHMEM is not set
|
||||
CONFIG_BASE_SMALL=0
|
||||
|
||||
#
|
||||
# Loadable module support
|
||||
|
@ -62,10 +67,12 @@ CONFIG_CC_ALIGN_JUMPS=0
|
|||
CONFIG_E500=y
|
||||
CONFIG_BOOKE=y
|
||||
CONFIG_FSL_BOOKE=y
|
||||
# CONFIG_PHYS_64BIT is not set
|
||||
CONFIG_SPE=y
|
||||
CONFIG_MATH_EMULATION=y
|
||||
# CONFIG_CPU_FREQ is not set
|
||||
CONFIG_PPC_GEN550=y
|
||||
# CONFIG_PM is not set
|
||||
CONFIG_85xx=y
|
||||
CONFIG_PPC_INDIRECT_PCI_BE=y
|
||||
|
||||
|
@ -76,6 +83,7 @@ CONFIG_PPC_INDIRECT_PCI_BE=y
|
|||
CONFIG_MPC8555_CDS=y
|
||||
# CONFIG_MPC8560_ADS is not set
|
||||
# CONFIG_SBC8560 is not set
|
||||
# CONFIG_STX_GP3 is not set
|
||||
CONFIG_MPC8555=y
|
||||
CONFIG_85xx_PCI2=y
|
||||
|
||||
|
@ -90,6 +98,7 @@ CONFIG_CPM2=y
|
|||
CONFIG_BINFMT_ELF=y
|
||||
# CONFIG_BINFMT_MISC is not set
|
||||
# CONFIG_CMDLINE_BOOL is not set
|
||||
CONFIG_ISA_DMA_API=y
|
||||
|
||||
#
|
||||
# Bus options
|
||||
|
@ -104,10 +113,6 @@ CONFIG_PCI_NAMES=y
|
|||
#
|
||||
# CONFIG_PCCARD is not set
|
||||
|
||||
#
|
||||
# PC-card bridges
|
||||
#
|
||||
|
||||
#
|
||||
# Advanced setup
|
||||
#
|
||||
|
@ -180,7 +185,59 @@ CONFIG_IOSCHED_CFQ=y
|
|||
#
|
||||
# ATA/ATAPI/MFM/RLL support
|
||||
#
|
||||
# CONFIG_IDE is not set
|
||||
CONFIG_IDE=y
|
||||
CONFIG_BLK_DEV_IDE=y
|
||||
|
||||
#
|
||||
# Please see Documentation/ide.txt for help/info on IDE drives
|
||||
#
|
||||
# CONFIG_BLK_DEV_IDE_SATA is not set
|
||||
CONFIG_BLK_DEV_IDEDISK=y
|
||||
# CONFIG_IDEDISK_MULTI_MODE is not set
|
||||
# CONFIG_BLK_DEV_IDECD is not set
|
||||
# CONFIG_BLK_DEV_IDETAPE is not set
|
||||
# CONFIG_BLK_DEV_IDEFLOPPY is not set
|
||||
# CONFIG_IDE_TASK_IOCTL is not set
|
||||
|
||||
#
|
||||
# IDE chipset support/bugfixes
|
||||
#
|
||||
CONFIG_IDE_GENERIC=y
|
||||
CONFIG_BLK_DEV_IDEPCI=y
|
||||
CONFIG_IDEPCI_SHARE_IRQ=y
|
||||
# CONFIG_BLK_DEV_OFFBOARD is not set
|
||||
CONFIG_BLK_DEV_GENERIC=y
|
||||
# CONFIG_BLK_DEV_OPTI621 is not set
|
||||
# CONFIG_BLK_DEV_SL82C105 is not set
|
||||
CONFIG_BLK_DEV_IDEDMA_PCI=y
|
||||
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
|
||||
CONFIG_IDEDMA_PCI_AUTO=y
|
||||
# CONFIG_IDEDMA_ONLYDISK is not set
|
||||
# CONFIG_BLK_DEV_AEC62XX is not set
|
||||
# CONFIG_BLK_DEV_ALI15X3 is not set
|
||||
# CONFIG_BLK_DEV_AMD74XX is not set
|
||||
# CONFIG_BLK_DEV_CMD64X is not set
|
||||
# CONFIG_BLK_DEV_TRIFLEX is not set
|
||||
# CONFIG_BLK_DEV_CY82C693 is not set
|
||||
# CONFIG_BLK_DEV_CS5520 is not set
|
||||
# CONFIG_BLK_DEV_CS5530 is not set
|
||||
# CONFIG_BLK_DEV_HPT34X is not set
|
||||
# CONFIG_BLK_DEV_HPT366 is not set
|
||||
# CONFIG_BLK_DEV_SC1200 is not set
|
||||
# CONFIG_BLK_DEV_PIIX is not set
|
||||
# CONFIG_BLK_DEV_NS87415 is not set
|
||||
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
|
||||
# CONFIG_BLK_DEV_PDC202XX_NEW is not set
|
||||
# CONFIG_BLK_DEV_SVWKS is not set
|
||||
# CONFIG_BLK_DEV_SIIMAGE is not set
|
||||
# CONFIG_BLK_DEV_SLC90E66 is not set
|
||||
# CONFIG_BLK_DEV_TRM290 is not set
|
||||
CONFIG_BLK_DEV_VIA82CXXX=y
|
||||
# CONFIG_IDE_ARM is not set
|
||||
CONFIG_BLK_DEV_IDEDMA=y
|
||||
# CONFIG_IDEDMA_IVB is not set
|
||||
CONFIG_IDEDMA_AUTO=y
|
||||
# CONFIG_BLK_DEV_HD is not set
|
||||
|
||||
#
|
||||
# SCSI device support
|
||||
|
@ -220,7 +277,6 @@ CONFIG_NET=y
|
|||
#
|
||||
CONFIG_PACKET=y
|
||||
# CONFIG_PACKET_MMAP is not set
|
||||
# CONFIG_NETLINK_DEV is not set
|
||||
CONFIG_UNIX=y
|
||||
# CONFIG_NET_KEY is not set
|
||||
CONFIG_INET=y
|
||||
|
@ -369,14 +425,6 @@ CONFIG_INPUT=y
|
|||
# CONFIG_INPUT_EVDEV is not set
|
||||
# CONFIG_INPUT_EVBUG is not set
|
||||
|
||||
#
|
||||
# Input I/O drivers
|
||||
#
|
||||
# CONFIG_GAMEPORT is not set
|
||||
CONFIG_SOUND_GAMEPORT=y
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_SERIO_I8042 is not set
|
||||
|
||||
#
|
||||
# Input Device Drivers
|
||||
#
|
||||
|
@ -386,6 +434,13 @@ CONFIG_SOUND_GAMEPORT=y
|
|||
# CONFIG_INPUT_TOUCHSCREEN is not set
|
||||
# CONFIG_INPUT_MISC is not set
|
||||
|
||||
#
|
||||
# Hardware I/O ports
|
||||
#
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_GAMEPORT is not set
|
||||
CONFIG_SOUND_GAMEPORT=y
|
||||
|
||||
#
|
||||
# Character devices
|
||||
#
|
||||
|
@ -406,6 +461,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4
|
|||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
# CONFIG_SERIAL_CPM is not set
|
||||
# CONFIG_SERIAL_JSM is not set
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
CONFIG_LEGACY_PTYS=y
|
||||
CONFIG_LEGACY_PTY_COUNT=256
|
||||
|
@ -433,6 +489,11 @@ CONFIG_GEN_RTC=y
|
|||
# CONFIG_DRM is not set
|
||||
# CONFIG_RAW_DRIVER is not set
|
||||
|
||||
#
|
||||
# TPM devices
|
||||
#
|
||||
# CONFIG_TCG_TPM is not set
|
||||
|
||||
#
|
||||
# I2C support
|
||||
#
|
||||
|
@ -456,11 +517,11 @@ CONFIG_I2C_CHARDEV=y
|
|||
# CONFIG_I2C_AMD8111 is not set
|
||||
# CONFIG_I2C_I801 is not set
|
||||
# CONFIG_I2C_I810 is not set
|
||||
# CONFIG_I2C_PIIX4 is not set
|
||||
# CONFIG_I2C_ISA is not set
|
||||
CONFIG_I2C_MPC=y
|
||||
# CONFIG_I2C_NFORCE2 is not set
|
||||
# CONFIG_I2C_PARPORT_LIGHT is not set
|
||||
# CONFIG_I2C_PIIX4 is not set
|
||||
# CONFIG_I2C_PROSAVAGE is not set
|
||||
# CONFIG_I2C_SAVAGE4 is not set
|
||||
# CONFIG_SCx200_ACB is not set
|
||||
|
@ -483,7 +544,9 @@ CONFIG_I2C_MPC=y
|
|||
# CONFIG_SENSORS_ASB100 is not set
|
||||
# CONFIG_SENSORS_DS1621 is not set
|
||||
# CONFIG_SENSORS_FSCHER is not set
|
||||
# CONFIG_SENSORS_FSCPOS is not set
|
||||
# CONFIG_SENSORS_GL518SM is not set
|
||||
# CONFIG_SENSORS_GL520SM is not set
|
||||
# CONFIG_SENSORS_IT87 is not set
|
||||
# CONFIG_SENSORS_LM63 is not set
|
||||
# CONFIG_SENSORS_LM75 is not set
|
||||
|
@ -494,9 +557,11 @@ CONFIG_I2C_MPC=y
|
|||
# CONFIG_SENSORS_LM85 is not set
|
||||
# CONFIG_SENSORS_LM87 is not set
|
||||
# CONFIG_SENSORS_LM90 is not set
|
||||
# CONFIG_SENSORS_LM92 is not set
|
||||
# CONFIG_SENSORS_MAX1619 is not set
|
||||
# CONFIG_SENSORS_PC87360 is not set
|
||||
# CONFIG_SENSORS_SMSC47B397 is not set
|
||||
# CONFIG_SENSORS_SIS5595 is not set
|
||||
# CONFIG_SENSORS_SMSC47M1 is not set
|
||||
# CONFIG_SENSORS_VIA686A is not set
|
||||
# CONFIG_SENSORS_W83781D is not set
|
||||
|
@ -506,10 +571,12 @@ CONFIG_I2C_MPC=y
|
|||
#
|
||||
# Other I2C Chip support
|
||||
#
|
||||
# CONFIG_SENSORS_DS1337 is not set
|
||||
# CONFIG_SENSORS_EEPROM is not set
|
||||
# CONFIG_SENSORS_PCF8574 is not set
|
||||
# CONFIG_SENSORS_PCF8591 is not set
|
||||
# CONFIG_SENSORS_RTC8564 is not set
|
||||
# CONFIG_SENSORS_M41T00 is not set
|
||||
# CONFIG_I2C_DEBUG_CORE is not set
|
||||
# CONFIG_I2C_DEBUG_ALGO is not set
|
||||
# CONFIG_I2C_DEBUG_BUS is not set
|
||||
|
@ -538,7 +605,6 @@ CONFIG_I2C_MPC=y
|
|||
# Graphics support
|
||||
#
|
||||
# CONFIG_FB is not set
|
||||
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
|
||||
|
||||
#
|
||||
# Sound
|
||||
|
@ -548,13 +614,9 @@ CONFIG_I2C_MPC=y
|
|||
#
|
||||
# USB support
|
||||
#
|
||||
# CONFIG_USB is not set
|
||||
CONFIG_USB_ARCH_HAS_HCD=y
|
||||
CONFIG_USB_ARCH_HAS_OHCI=y
|
||||
|
||||
#
|
||||
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
|
||||
#
|
||||
# CONFIG_USB is not set
|
||||
|
||||
#
|
||||
# USB Gadget Support
|
||||
|
@ -585,6 +647,10 @@ CONFIG_JBD=y
|
|||
CONFIG_FS_MBCACHE=y
|
||||
# CONFIG_REISERFS_FS is not set
|
||||
# CONFIG_JFS_FS is not set
|
||||
|
||||
#
|
||||
# XFS support
|
||||
#
|
||||
# CONFIG_XFS_FS is not set
|
||||
# CONFIG_MINIX_FS is not set
|
||||
# CONFIG_ROMFS_FS is not set
|
||||
|
@ -646,7 +712,6 @@ CONFIG_NFS_FS=y
|
|||
# CONFIG_NFSD is not set
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_LOCKD=y
|
||||
# CONFIG_EXPORTFS is not set
|
||||
CONFIG_SUNRPC=y
|
||||
# CONFIG_RPCSEC_GSS_KRB5 is not set
|
||||
# CONFIG_RPCSEC_GSS_SPKM3 is not set
|
||||
|
@ -698,7 +763,9 @@ CONFIG_CRC32=y
|
|||
#
|
||||
# Kernel hacking
|
||||
#
|
||||
# CONFIG_PRINTK_TIME is not set
|
||||
# CONFIG_DEBUG_KERNEL is not set
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_KGDB_CONSOLE is not set
|
||||
# CONFIG_SERIAL_TEXT_DEBUG is not set
|
||||
|
||||
|
|
|
@ -232,7 +232,8 @@ skpinv: addi r6,r6,1 /* Increment */
|
|||
tlbwe
|
||||
|
||||
/* 7. Jump to KERNELBASE mapping */
|
||||
li r7,0
|
||||
lis r7,MSR_KERNEL@h
|
||||
ori r7,r7,MSR_KERNEL@l
|
||||
bl 1f /* Find our address */
|
||||
1: mflr r9
|
||||
rlwimi r6,r9,0,20,31
|
||||
|
@ -293,6 +294,18 @@ skpinv: addi r6,r6,1 /* Increment */
|
|||
mtspr SPRN_HID0, r2
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_BDI_SWITCH)
|
||||
/*
|
||||
* The Abatron BDI JTAG debugger does not tolerate others
|
||||
* mucking with the debug registers.
|
||||
*/
|
||||
lis r2,DBCR0_IDM@h
|
||||
mtspr SPRN_DBCR0,r2
|
||||
/* clear any residual debug events */
|
||||
li r2,-1
|
||||
mtspr SPRN_DBSR,r2
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is where the main kernel code starts.
|
||||
*/
|
||||
|
|
|
@ -408,12 +408,7 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
|
|||
|
||||
/* Early out if we are an invalid form of lswx */
|
||||
if ((instword & INST_STRING_MASK) == INST_LSWX)
|
||||
if ((rA >= rT) || (NB_RB >= rT) || (rT == rA) || (rT == NB_RB))
|
||||
return -EINVAL;
|
||||
|
||||
/* Early out if we are an invalid form of lswi */
|
||||
if ((instword & INST_STRING_MASK) == INST_LSWI)
|
||||
if ((rA >= rT) || (rT == rA))
|
||||
if ((rT == rA) || (rT == NB_RB))
|
||||
return -EINVAL;
|
||||
|
||||
EA = (rA == 0) ? 0 : regs->gpr[rA];
|
||||
|
|
|
@ -127,7 +127,6 @@ mpc834x_sys_map_io(void)
|
|||
{
|
||||
/* we steal the lowest ioremap addr for virt space */
|
||||
io_block_mapping(VIRT_IMMRBAR, immrbar, 1024*1024, _PAGE_IO);
|
||||
io_block_mapping(BCSR_VIRT_ADDR, BCSR_PHYS_ADDR, BCSR_SIZE, _PAGE_IO);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -26,9 +26,14 @@
|
|||
#define VIRT_IMMRBAR ((uint)0xfe000000)
|
||||
|
||||
#define BCSR_PHYS_ADDR ((uint)0xf8000000)
|
||||
#define BCSR_VIRT_ADDR ((uint)0xfe100000)
|
||||
#define BCSR_SIZE ((uint)(32 * 1024))
|
||||
|
||||
#define BCSR_MISC_REG2_OFF 0x07
|
||||
#define BCSR_MISC_REG2_PORESET 0x01
|
||||
|
||||
#define BCSR_MISC_REG3_OFF 0x08
|
||||
#define BCSR_MISC_REG3_CNFLOCK 0x80
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
/* PCI interrupt controller */
|
||||
#define PIRQA MPC83xx_IRQ_IRQ4
|
||||
|
|
|
@ -210,6 +210,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
|
|||
#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
|
||||
ppc_md.progress = gen550_progress;
|
||||
#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
|
||||
#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
|
||||
ppc_md.early_serial_map = mpc85xx_early_serial_map;
|
||||
#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc8540ads_init(): exit", 0);
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <asm/machdep.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/open_pic.h>
|
||||
#include <asm/i8259.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/mpc85xx.h>
|
||||
|
@ -181,6 +182,7 @@ void __init
|
|||
mpc85xx_cds_init_IRQ(void)
|
||||
{
|
||||
bd_t *binfo = (bd_t *) __res;
|
||||
int i;
|
||||
|
||||
/* Determine the Physical Address of the OpenPIC regs */
|
||||
phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
|
||||
|
@ -198,6 +200,15 @@ mpc85xx_cds_init_IRQ(void)
|
|||
*/
|
||||
openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
openpic_hookup_cascade(PIRQ0A, "82c59 cascade", i8259_irq);
|
||||
|
||||
for (i = 0; i < NUM_8259_INTERRUPTS; i++)
|
||||
irq_desc[i].handler = &i8259_pic;
|
||||
|
||||
i8259_init(0);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPM2
|
||||
/* Setup CPM2 PIC */
|
||||
cpm2_init_IRQ();
|
||||
|
@ -231,7 +242,7 @@ mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
|
|||
* interrupt on slot */
|
||||
{
|
||||
{ 0, 1, 2, 3 }, /* 16 - PMC */
|
||||
{ 3, 0, 0, 0 }, /* 17 P2P (Tsi320) */
|
||||
{ 0, 1, 2, 3 }, /* 17 P2P (Tsi320) */
|
||||
{ 0, 1, 2, 3 }, /* 18 - Slot 1 */
|
||||
{ 1, 2, 3, 0 }, /* 19 - Slot 2 */
|
||||
{ 2, 3, 0, 1 }, /* 20 - Slot 3 */
|
||||
|
@ -280,13 +291,135 @@ mpc85xx_exclude_device(u_char bus, u_char devfn)
|
|||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
#endif
|
||||
/* We explicitly do not go past the Tundra 320 Bridge */
|
||||
if (bus == 1)
|
||||
if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
else
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
void __init
|
||||
mpc85xx_cds_enable_via(struct pci_controller *hose)
|
||||
{
|
||||
u32 pci_class;
|
||||
u16 vid, did;
|
||||
|
||||
early_read_config_dword(hose, 0, 0x88, PCI_CLASS_REVISION, &pci_class);
|
||||
if ((pci_class >> 16) != PCI_CLASS_BRIDGE_PCI)
|
||||
return;
|
||||
|
||||
/* Configure P2P so that we can reach bus 1 */
|
||||
early_write_config_byte(hose, 0, 0x88, PCI_PRIMARY_BUS, 0);
|
||||
early_write_config_byte(hose, 0, 0x88, PCI_SECONDARY_BUS, 1);
|
||||
early_write_config_byte(hose, 0, 0x88, PCI_SUBORDINATE_BUS, 0xff);
|
||||
|
||||
early_read_config_word(hose, 1, 0x10, PCI_VENDOR_ID, &vid);
|
||||
early_read_config_word(hose, 1, 0x10, PCI_DEVICE_ID, &did);
|
||||
|
||||
if ((vid != PCI_VENDOR_ID_VIA) ||
|
||||
(did != PCI_DEVICE_ID_VIA_82C686))
|
||||
return;
|
||||
|
||||
/* Enable USB and IDE functions */
|
||||
early_write_config_byte(hose, 1, 0x10, 0x48, 0x08);
|
||||
}
|
||||
|
||||
void __init
|
||||
mpc85xx_cds_fixup_via(struct pci_controller *hose)
|
||||
{
|
||||
u32 pci_class;
|
||||
u16 vid, did;
|
||||
|
||||
early_read_config_dword(hose, 0, 0x88, PCI_CLASS_REVISION, &pci_class);
|
||||
if ((pci_class >> 16) != PCI_CLASS_BRIDGE_PCI)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Force the backplane P2P bridge to have a window
|
||||
* open from 0x00000000-0x00001fff in PCI I/O space.
|
||||
* This allows legacy I/O (i8259, etc) on the VIA
|
||||
* southbridge to be accessed.
|
||||
*/
|
||||
early_write_config_byte(hose, 0, 0x88, PCI_IO_BASE, 0x00);
|
||||
early_write_config_word(hose, 0, 0x88, PCI_IO_BASE_UPPER16, 0x0000);
|
||||
early_write_config_byte(hose, 0, 0x88, PCI_IO_LIMIT, 0x10);
|
||||
early_write_config_word(hose, 0, 0x88, PCI_IO_LIMIT_UPPER16, 0x0000);
|
||||
|
||||
early_read_config_word(hose, 1, 0x10, PCI_VENDOR_ID, &vid);
|
||||
early_read_config_word(hose, 1, 0x10, PCI_DEVICE_ID, &did);
|
||||
if ((vid != PCI_VENDOR_ID_VIA) ||
|
||||
(did != PCI_DEVICE_ID_VIA_82C686))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Since the P2P window was forced to cover the fixed
|
||||
* legacy I/O addresses, it is necessary to manually
|
||||
* place the base addresses for the IDE and USB functions
|
||||
* within this window.
|
||||
*/
|
||||
/* Function 1, IDE */
|
||||
early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_0, 0x1ff8);
|
||||
early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_1, 0x1ff4);
|
||||
early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_2, 0x1fe8);
|
||||
early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_3, 0x1fe4);
|
||||
early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_4, 0x1fd0);
|
||||
|
||||
/* Function 2, USB ports 0-1 */
|
||||
early_write_config_dword(hose, 1, 0x12, PCI_BASE_ADDRESS_4, 0x1fa0);
|
||||
|
||||
/* Function 3, USB ports 2-3 */
|
||||
early_write_config_dword(hose, 1, 0x13, PCI_BASE_ADDRESS_4, 0x1f80);
|
||||
|
||||
/* Function 5, Power Management */
|
||||
early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_0, 0x1e00);
|
||||
early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_1, 0x1dfc);
|
||||
early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_2, 0x1df8);
|
||||
|
||||
/* Function 6, AC97 Interface */
|
||||
early_write_config_dword(hose, 1, 0x16, PCI_BASE_ADDRESS_0, 0x1c00);
|
||||
}
|
||||
|
||||
void __init
|
||||
mpc85xx_cds_pcibios_fixup(void)
|
||||
{
|
||||
struct pci_dev *dev = NULL;
|
||||
u_char c;
|
||||
|
||||
if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
|
||||
/*
|
||||
* U-Boot does not set the enable bits
|
||||
* for the IDE device. Force them on here.
|
||||
*/
|
||||
pci_read_config_byte(dev, 0x40, &c);
|
||||
c |= 0x03; /* IDE: Chip Enable Bits */
|
||||
pci_write_config_byte(dev, 0x40, c);
|
||||
|
||||
/*
|
||||
* Since only primary interface works, force the
|
||||
* IDE function to standard primary IDE interrupt
|
||||
* w/ 8259 offset
|
||||
*/
|
||||
dev->irq = 14;
|
||||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Force legacy USB interrupt routing
|
||||
*/
|
||||
if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
|
||||
dev->irq = 10;
|
||||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
|
||||
}
|
||||
|
||||
if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_82C586_2, dev))) {
|
||||
dev->irq = 11;
|
||||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
TODC_ALLOC();
|
||||
|
@ -328,6 +461,9 @@ mpc85xx_cds_setup_arch(void)
|
|||
loops_per_jiffy = freq / HZ;
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
/* VIA IDE configuration */
|
||||
ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
|
||||
|
||||
/* setup PCI host bridges */
|
||||
mpc85xx_setup_hose();
|
||||
#endif
|
||||
|
@ -459,6 +595,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
|
|||
#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
|
||||
ppc_md.progress = gen550_progress;
|
||||
#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
|
||||
#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
|
||||
ppc_md.early_serial_map = mpc85xx_early_serial_map;
|
||||
#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc85xx_cds_init(): exit", 0);
|
||||
|
|
|
@ -77,4 +77,7 @@
|
|||
|
||||
#define MPC85XX_PCI2_IO_SIZE 0x01000000
|
||||
|
||||
#define NR_8259_INTS 16
|
||||
#define CPM_IRQ_OFFSET NR_8259_INTS
|
||||
|
||||
#endif /* __MACH_MPC85XX_CDS_H__ */
|
||||
|
|
|
@ -221,6 +221,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
|
|||
#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
|
||||
ppc_md.progress = gen550_progress;
|
||||
#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
|
||||
#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
|
||||
ppc_md.early_serial_map = sbc8560_early_serial_map;
|
||||
#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("sbc8560_init(): exit", 0);
|
||||
|
|
|
@ -85,14 +85,11 @@ static int no_schedule;
|
|||
static int has_cpu_l2lve;
|
||||
|
||||
|
||||
#define PMAC_CPU_LOW_SPEED 1
|
||||
#define PMAC_CPU_HIGH_SPEED 0
|
||||
|
||||
/* There are only two frequency states for each processor. Values
|
||||
* are in kHz for the time being.
|
||||
*/
|
||||
#define CPUFREQ_HIGH PMAC_CPU_HIGH_SPEED
|
||||
#define CPUFREQ_LOW PMAC_CPU_LOW_SPEED
|
||||
#define CPUFREQ_HIGH 0
|
||||
#define CPUFREQ_LOW 1
|
||||
|
||||
static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
|
||||
{CPUFREQ_HIGH, 0},
|
||||
|
@ -100,6 +97,11 @@ static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
|
|||
{0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
static struct freq_attr* pmac_cpu_freqs_attr[] = {
|
||||
&cpufreq_freq_attr_scaling_available_freqs,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static inline void local_delay(unsigned long ms)
|
||||
{
|
||||
if (no_schedule)
|
||||
|
@ -269,6 +271,8 @@ static int __pmac pmu_set_cpu_speed(int low_speed)
|
|||
#ifdef DEBUG_FREQ
|
||||
printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
|
||||
#endif
|
||||
pmu_suspend();
|
||||
|
||||
/* Disable all interrupt sources on openpic */
|
||||
pic_prio = openpic_get_priority();
|
||||
openpic_set_priority(0xf);
|
||||
|
@ -343,6 +347,8 @@ static int __pmac pmu_set_cpu_speed(int low_speed)
|
|||
debug_calc_bogomips();
|
||||
#endif
|
||||
|
||||
pmu_resume();
|
||||
|
||||
preempt_enable();
|
||||
|
||||
return 0;
|
||||
|
@ -355,7 +361,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
|
|||
static unsigned long prev_l3cr;
|
||||
|
||||
freqs.old = cur_freq;
|
||||
freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
|
||||
freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
|
||||
freqs.cpu = smp_processor_id();
|
||||
|
||||
if (freqs.old == freqs.new)
|
||||
|
@ -363,7 +369,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
|
|||
|
||||
if (notify)
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
if (speed_mode == PMAC_CPU_LOW_SPEED &&
|
||||
if (speed_mode == CPUFREQ_LOW &&
|
||||
cpu_has_feature(CPU_FTR_L3CR)) {
|
||||
l3cr = _get_L3CR();
|
||||
if (l3cr & L3CR_L3E) {
|
||||
|
@ -371,8 +377,8 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
|
|||
_set_L3CR(0);
|
||||
}
|
||||
}
|
||||
set_speed_proc(speed_mode == PMAC_CPU_LOW_SPEED);
|
||||
if (speed_mode == PMAC_CPU_HIGH_SPEED &&
|
||||
set_speed_proc(speed_mode == CPUFREQ_LOW);
|
||||
if (speed_mode == CPUFREQ_HIGH &&
|
||||
cpu_has_feature(CPU_FTR_L3CR)) {
|
||||
l3cr = _get_L3CR();
|
||||
if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr)
|
||||
|
@ -380,7 +386,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
|
|||
}
|
||||
if (notify)
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
|
||||
cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -423,7 +429,8 @@ static int __pmac pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
|||
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
|
||||
policy->cur = cur_freq;
|
||||
|
||||
return cpufreq_frequency_table_cpuinfo(policy, &pmac_cpu_freqs[0]);
|
||||
cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);
|
||||
return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);
|
||||
}
|
||||
|
||||
static u32 __pmac read_gpio(struct device_node *np)
|
||||
|
@ -457,7 +464,7 @@ static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, u32 state)
|
|||
no_schedule = 1;
|
||||
sleep_freq = cur_freq;
|
||||
if (cur_freq == low_freq)
|
||||
do_set_cpu_speed(PMAC_CPU_HIGH_SPEED, 0);
|
||||
do_set_cpu_speed(CPUFREQ_HIGH, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -473,8 +480,8 @@ static int __pmac pmac_cpufreq_resume(struct cpufreq_policy *policy)
|
|||
* is that we force a switch to whatever it was, which is
|
||||
* probably high speed due to our suspend() routine
|
||||
*/
|
||||
do_set_cpu_speed(sleep_freq == low_freq ? PMAC_CPU_LOW_SPEED
|
||||
: PMAC_CPU_HIGH_SPEED, 0);
|
||||
do_set_cpu_speed(sleep_freq == low_freq ?
|
||||
CPUFREQ_LOW : CPUFREQ_HIGH, 0);
|
||||
|
||||
no_schedule = 0;
|
||||
return 0;
|
||||
|
@ -488,6 +495,7 @@ static struct cpufreq_driver pmac_cpufreq_driver = {
|
|||
.suspend = pmac_cpufreq_suspend,
|
||||
.resume = pmac_cpufreq_resume,
|
||||
.flags = CPUFREQ_PM_NO_WARN,
|
||||
.attr = pmac_cpu_freqs_attr,
|
||||
.name = "powermac",
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
|
|
@ -49,10 +49,10 @@
|
|||
/* PCI interrupt controller */
|
||||
#define PCI_INT_STAT_REG 0xF8200000
|
||||
#define PCI_INT_MASK_REG 0xF8200004
|
||||
#define PIRQA (NR_SIU_INTS + 0)
|
||||
#define PIRQB (NR_SIU_INTS + 1)
|
||||
#define PIRQC (NR_SIU_INTS + 2)
|
||||
#define PIRQD (NR_SIU_INTS + 3)
|
||||
#define PIRQA (NR_CPM_INTS + 0)
|
||||
#define PIRQB (NR_CPM_INTS + 1)
|
||||
#define PIRQC (NR_CPM_INTS + 2)
|
||||
#define PIRQD (NR_CPM_INTS + 3)
|
||||
|
||||
/*
|
||||
* PCI memory map definitions for MPC8266ADS-PCI.
|
||||
|
@ -68,28 +68,23 @@
|
|||
* 0x00000000-0x1FFFFFFF 0x00000000-0x1FFFFFFF MPC8266 local memory
|
||||
*/
|
||||
|
||||
/* window for a PCI master to access MPC8266 memory */
|
||||
#define PCI_SLV_MEM_LOCAL 0x00000000 /* Local base */
|
||||
#define PCI_SLV_MEM_BUS 0x00000000 /* PCI base */
|
||||
/* All the other PCI memory map definitions reside at syslib/m82xx_pci.h
|
||||
Here we should redefine what is unique for this board */
|
||||
#define M82xx_PCI_SLAVE_MEM_LOCAL 0x00000000 /* Local base */
|
||||
#define M82xx_PCI_SLAVE_MEM_BUS 0x00000000 /* PCI base */
|
||||
#define M82xx_PCI_SLAVE_MEM_SIZE 0x10000000 /* 256 Mb */
|
||||
|
||||
/* window for the processor to access PCI memory with prefetching */
|
||||
#define PCI_MSTR_MEM_LOCAL 0x80000000 /* Local base */
|
||||
#define PCI_MSTR_MEM_BUS 0x80000000 /* PCI base */
|
||||
#define PCI_MSTR_MEM_SIZE 0x20000000 /* 512MB */
|
||||
#define M82xx_PCI_SLAVE_SEC_WND_SIZE ~(0x40000000 - 1U) /* 2 x 512Mb */
|
||||
#define M82xx_PCI_SLAVE_SEC_WND_BASE 0x80000000 /* PCI Memory base */
|
||||
|
||||
/* window for the processor to access PCI memory without prefetching */
|
||||
#define PCI_MSTR_MEMIO_LOCAL 0xA0000000 /* Local base */
|
||||
#define PCI_MSTR_MEMIO_BUS 0xA0000000 /* PCI base */
|
||||
#define PCI_MSTR_MEMIO_SIZE 0x20000000 /* 512MB */
|
||||
#if defined(CONFIG_ADS8272)
|
||||
#define PCI_INT_TO_SIU SIU_INT_IRQ2
|
||||
#elif defined(CONFIG_PQ2FADS)
|
||||
#define PCI_INT_TO_SIU SIU_INT_IRQ6
|
||||
#else
|
||||
#warning PCI Bridge will be without interrupts support
|
||||
#endif
|
||||
|
||||
/* window for the processor to access PCI I/O */
|
||||
#define PCI_MSTR_IO_LOCAL 0xF4000000 /* Local base */
|
||||
#define PCI_MSTR_IO_BUS 0x00000000 /* PCI base */
|
||||
#define PCI_MSTR_IO_SIZE 0x04000000 /* 64MB */
|
||||
|
||||
#define _IO_BASE PCI_MSTR_IO_LOCAL
|
||||
#define _ISA_MEM_BASE PCI_MSTR_MEMIO_LOCAL
|
||||
#define PCI_DRAM_OFFSET PCI_SLV_MEM_BUS
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
#endif /* __MACH_ADS8260_DEFS */
|
||||
|
|
|
@ -81,7 +81,7 @@ obj-$(CONFIG_SBC82xx) += todc_time.o
|
|||
obj-$(CONFIG_SPRUCE) += cpc700_pic.o indirect_pci.o pci_auto.o \
|
||||
todc_time.o
|
||||
obj-$(CONFIG_8260) += m8260_setup.o
|
||||
obj-$(CONFIG_PCI_8260) += m8260_pci.o indirect_pci.o
|
||||
obj-$(CONFIG_PCI_8260) += m82xx_pci.o indirect_pci.o pci_auto.o
|
||||
obj-$(CONFIG_8260_PCI9) += m8260_pci_erratum9.o
|
||||
obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
|
||||
ifeq ($(CONFIG_PPC_GEN550),y)
|
||||
|
@ -97,7 +97,7 @@ obj-$(CONFIG_MPC10X_OPENPIC) += open_pic.o
|
|||
obj-$(CONFIG_40x) += dcr.o
|
||||
obj-$(CONFIG_BOOKE) += dcr.o
|
||||
obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o \
|
||||
ppc_sys.o mpc85xx_sys.o \
|
||||
ppc_sys.o i8259.o mpc85xx_sys.o \
|
||||
mpc85xx_devices.o
|
||||
ifeq ($(CONFIG_85xx),y)
|
||||
obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o
|
||||
|
|
|
@ -1,193 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2004 Red Hat, Inc.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/immap_cpm2.h>
|
||||
#include <asm/mpc8260.h>
|
||||
|
||||
#include "m8260_pci.h"
|
||||
|
||||
|
||||
/* PCI bus configuration registers.
|
||||
*/
|
||||
|
||||
static void __init m8260_setup_pci(struct pci_controller *hose)
|
||||
{
|
||||
volatile cpm2_map_t *immap = cpm2_immr;
|
||||
unsigned long pocmr;
|
||||
u16 tempShort;
|
||||
|
||||
#ifndef CONFIG_ATC /* already done in U-Boot */
|
||||
/*
|
||||
* Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
|
||||
* and local bus for PCI (SIUMCR [LBPC]).
|
||||
*/
|
||||
immap->im_siu_conf.siu_82xx.sc_siumcr = 0x00640000;
|
||||
#endif
|
||||
|
||||
/* Make PCI lowest priority */
|
||||
/* Each 4 bits is a device bus request and the MS 4bits
|
||||
is highest priority */
|
||||
/* Bus 4bit value
|
||||
--- ----------
|
||||
CPM high 0b0000
|
||||
CPM middle 0b0001
|
||||
CPM low 0b0010
|
||||
PCI reguest 0b0011
|
||||
Reserved 0b0100
|
||||
Reserved 0b0101
|
||||
Internal Core 0b0110
|
||||
External Master 1 0b0111
|
||||
External Master 2 0b1000
|
||||
External Master 3 0b1001
|
||||
The rest are reserved */
|
||||
immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x61207893;
|
||||
|
||||
/* Park bus on core while modifying PCI Bus accesses */
|
||||
immap->im_siu_conf.siu_82xx.sc_ppc_acr = 0x6;
|
||||
|
||||
/*
|
||||
* Set up master window that allows the CPU to access PCI space. This
|
||||
* window is set up using the first SIU PCIBR registers.
|
||||
*/
|
||||
immap->im_memctl.memc_pcimsk0 = MPC826x_PCI_MASK;
|
||||
immap->im_memctl.memc_pcibr0 = MPC826x_PCI_BASE | PCIBR_ENABLE;
|
||||
|
||||
/* Disable machine check on no response or target abort */
|
||||
immap->im_pci.pci_emr = cpu_to_le32(0x1fe7);
|
||||
/* Release PCI RST (by default the PCI RST signal is held low) */
|
||||
immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
|
||||
|
||||
/* give it some time */
|
||||
mdelay(1);
|
||||
|
||||
/*
|
||||
* Set up master window that allows the CPU to access PCI Memory (prefetch)
|
||||
* space. This window is set up using the first set of Outbound ATU registers.
|
||||
*/
|
||||
immap->im_pci.pci_potar0 = cpu_to_le32(MPC826x_PCI_LOWER_MEM >> 12);
|
||||
immap->im_pci.pci_pobar0 = cpu_to_le32((MPC826x_PCI_LOWER_MEM - MPC826x_PCI_MEM_OFFSET) >> 12);
|
||||
pocmr = ((MPC826x_PCI_UPPER_MEM - MPC826x_PCI_LOWER_MEM) >> 12) ^ 0xfffff;
|
||||
immap->im_pci.pci_pocmr0 = cpu_to_le32(pocmr | POCMR_ENABLE | POCMR_PREFETCH_EN);
|
||||
|
||||
/*
|
||||
* Set up master window that allows the CPU to access PCI Memory (non-prefetch)
|
||||
* space. This window is set up using the second set of Outbound ATU registers.
|
||||
*/
|
||||
immap->im_pci.pci_potar1 = cpu_to_le32(MPC826x_PCI_LOWER_MMIO >> 12);
|
||||
immap->im_pci.pci_pobar1 = cpu_to_le32((MPC826x_PCI_LOWER_MMIO - MPC826x_PCI_MMIO_OFFSET) >> 12);
|
||||
pocmr = ((MPC826x_PCI_UPPER_MMIO - MPC826x_PCI_LOWER_MMIO) >> 12) ^ 0xfffff;
|
||||
immap->im_pci.pci_pocmr1 = cpu_to_le32(pocmr | POCMR_ENABLE);
|
||||
|
||||
/*
|
||||
* Set up master window that allows the CPU to access PCI IO space. This window
|
||||
* is set up using the third set of Outbound ATU registers.
|
||||
*/
|
||||
immap->im_pci.pci_potar2 = cpu_to_le32(MPC826x_PCI_IO_BASE >> 12);
|
||||
immap->im_pci.pci_pobar2 = cpu_to_le32(MPC826x_PCI_LOWER_IO >> 12);
|
||||
pocmr = ((MPC826x_PCI_UPPER_IO - MPC826x_PCI_LOWER_IO) >> 12) ^ 0xfffff;
|
||||
immap->im_pci.pci_pocmr2 = cpu_to_le32(pocmr | POCMR_ENABLE | POCMR_PCI_IO);
|
||||
|
||||
/*
|
||||
* Set up slave window that allows PCI masters to access MPC826x local memory.
|
||||
* This window is set up using the first set of Inbound ATU registers
|
||||
*/
|
||||
|
||||
immap->im_pci.pci_pitar0 = cpu_to_le32(MPC826x_PCI_SLAVE_MEM_LOCAL >> 12);
|
||||
immap->im_pci.pci_pibar0 = cpu_to_le32(MPC826x_PCI_SLAVE_MEM_BUS >> 12);
|
||||
pocmr = ((MPC826x_PCI_SLAVE_MEM_SIZE-1) >> 12) ^ 0xfffff;
|
||||
immap->im_pci.pci_picmr0 = cpu_to_le32(pocmr | PICMR_ENABLE | PICMR_PREFETCH_EN);
|
||||
|
||||
/* See above for description - puts PCI request as highest priority */
|
||||
immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567;
|
||||
|
||||
/* Park the bus on the PCI */
|
||||
immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
|
||||
|
||||
/* Host mode - specify the bridge as a host-PCI bridge */
|
||||
early_write_config_word(hose, 0, 0, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_HOST);
|
||||
|
||||
/* Enable the host bridge to be a master on the PCI bus, and to act as a PCI memory target */
|
||||
early_read_config_word(hose, 0, 0, PCI_COMMAND, &tempShort);
|
||||
early_write_config_word(hose, 0, 0, PCI_COMMAND,
|
||||
tempShort | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
|
||||
}
|
||||
|
||||
void __init m8260_find_bridges(void)
|
||||
{
|
||||
extern int pci_assign_all_busses;
|
||||
struct pci_controller * hose;
|
||||
|
||||
pci_assign_all_busses = 1;
|
||||
|
||||
hose = pcibios_alloc_controller();
|
||||
|
||||
if (!hose)
|
||||
return;
|
||||
|
||||
ppc_md.pci_swizzle = common_swizzle;
|
||||
|
||||
hose->first_busno = 0;
|
||||
hose->bus_offset = 0;
|
||||
hose->last_busno = 0xff;
|
||||
|
||||
setup_m8260_indirect_pci(hose,
|
||||
(unsigned long)&cpm2_immr->im_pci.pci_cfg_addr,
|
||||
(unsigned long)&cpm2_immr->im_pci.pci_cfg_data);
|
||||
|
||||
m8260_setup_pci(hose);
|
||||
hose->pci_mem_offset = MPC826x_PCI_MEM_OFFSET;
|
||||
|
||||
hose->io_base_virt = ioremap(MPC826x_PCI_IO_BASE,
|
||||
MPC826x_PCI_IO_SIZE);
|
||||
isa_io_base = (unsigned long) hose->io_base_virt;
|
||||
|
||||
/* setup resources */
|
||||
pci_init_resource(&hose->mem_resources[0],
|
||||
MPC826x_PCI_LOWER_MEM,
|
||||
MPC826x_PCI_UPPER_MEM,
|
||||
IORESOURCE_MEM|IORESOURCE_PREFETCH, "PCI prefetchable memory");
|
||||
|
||||
pci_init_resource(&hose->mem_resources[1],
|
||||
MPC826x_PCI_LOWER_MMIO,
|
||||
MPC826x_PCI_UPPER_MMIO,
|
||||
IORESOURCE_MEM, "PCI memory");
|
||||
|
||||
pci_init_resource(&hose->io_resource,
|
||||
MPC826x_PCI_LOWER_IO,
|
||||
MPC826x_PCI_UPPER_IO,
|
||||
IORESOURCE_IO, "PCI I/O");
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
|
||||
#ifndef _PPC_KERNEL_M8260_PCI_H
|
||||
#define _PPC_KERNEL_M8260_PCI_H
|
||||
|
||||
#include <asm/m8260_pci.h>
|
||||
|
||||
/*
|
||||
* Local->PCI map (from CPU) controlled by
|
||||
* MPC826x master window
|
||||
*
|
||||
* 0x80000000 - 0xBFFFFFFF Total CPU2PCI space PCIBR0
|
||||
*
|
||||
* 0x80000000 - 0x9FFFFFFF PCI Mem with prefetch (Outbound ATU #1)
|
||||
* 0xA0000000 - 0xAFFFFFFF PCI Mem w/o prefetch (Outbound ATU #2)
|
||||
* 0xB0000000 - 0xB0FFFFFF 32-bit PCI IO (Outbound ATU #3)
|
||||
*
|
||||
* PCI->Local map (from PCI)
|
||||
* MPC826x slave window controlled by
|
||||
*
|
||||
* 0x00000000 - 0x07FFFFFF MPC826x local memory (Inbound ATU #1)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Slave window that allows PCI masters to access MPC826x local memory.
|
||||
* This window is set up using the first set of Inbound ATU registers
|
||||
*/
|
||||
|
||||
#ifndef MPC826x_PCI_SLAVE_MEM_LOCAL
|
||||
#define MPC826x_PCI_SLAVE_MEM_LOCAL (((struct bd_info *)__res)->bi_memstart)
|
||||
#define MPC826x_PCI_SLAVE_MEM_BUS (((struct bd_info *)__res)->bi_memstart)
|
||||
#define MPC826x_PCI_SLAVE_MEM_SIZE (((struct bd_info *)__res)->bi_memsize)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is the window that allows the CPU to access PCI address space.
|
||||
* It will be setup with the SIU PCIBR0 register. All three PCI master
|
||||
* windows, which allow the CPU to access PCI prefetch, non prefetch,
|
||||
* and IO space (see below), must all fit within this window.
|
||||
*/
|
||||
#ifndef MPC826x_PCI_BASE
|
||||
#define MPC826x_PCI_BASE 0x80000000
|
||||
#define MPC826x_PCI_MASK 0xc0000000
|
||||
#endif
|
||||
|
||||
#ifndef MPC826x_PCI_LOWER_MEM
|
||||
#define MPC826x_PCI_LOWER_MEM 0x80000000
|
||||
#define MPC826x_PCI_UPPER_MEM 0x9fffffff
|
||||
#define MPC826x_PCI_MEM_OFFSET 0x00000000
|
||||
#endif
|
||||
|
||||
#ifndef MPC826x_PCI_LOWER_MMIO
|
||||
#define MPC826x_PCI_LOWER_MMIO 0xa0000000
|
||||
#define MPC826x_PCI_UPPER_MMIO 0xafffffff
|
||||
#define MPC826x_PCI_MMIO_OFFSET 0x00000000
|
||||
#endif
|
||||
|
||||
#ifndef MPC826x_PCI_LOWER_IO
|
||||
#define MPC826x_PCI_LOWER_IO 0x00000000
|
||||
#define MPC826x_PCI_UPPER_IO 0x00ffffff
|
||||
#define MPC826x_PCI_IO_BASE 0xb0000000
|
||||
#define MPC826x_PCI_IO_SIZE 0x01000000
|
||||
#endif
|
||||
|
||||
#ifndef _IO_BASE
|
||||
#define _IO_BASE isa_io_base
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_8260_PCI9
|
||||
struct pci_controller;
|
||||
extern void setup_m8260_indirect_pci(struct pci_controller* hose,
|
||||
u32 cfg_addr, u32 cfg_data);
|
||||
#else
|
||||
#define setup_m8260_indirect_pci setup_indirect_pci
|
||||
#endif
|
||||
|
||||
#endif /* _PPC_KERNEL_M8260_PCI_H */
|
|
@ -31,7 +31,7 @@
|
|||
#include <asm/immap_cpm2.h>
|
||||
#include <asm/cpm2.h>
|
||||
|
||||
#include "m8260_pci.h"
|
||||
#include "m82xx_pci.h"
|
||||
|
||||
#ifdef CONFIG_8260_PCI9
|
||||
/*#include <asm/mpc8260_pci9.h>*/ /* included in asm/io.h */
|
||||
|
@ -248,11 +248,11 @@ EXPORT_SYMBOL(idma_pci9_read_le);
|
|||
|
||||
static inline int is_pci_mem(unsigned long addr)
|
||||
{
|
||||
if (addr >= MPC826x_PCI_LOWER_MMIO &&
|
||||
addr <= MPC826x_PCI_UPPER_MMIO)
|
||||
if (addr >= M82xx_PCI_LOWER_MMIO &&
|
||||
addr <= M82xx_PCI_UPPER_MMIO)
|
||||
return 1;
|
||||
if (addr >= MPC826x_PCI_LOWER_MEM &&
|
||||
addr <= MPC826x_PCI_UPPER_MEM)
|
||||
if (addr >= M82xx_PCI_LOWER_MEM &&
|
||||
addr <= M82xx_PCI_UPPER_MEM)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
unsigned char __res[sizeof(bd_t)];
|
||||
|
||||
extern void cpm2_reset(void);
|
||||
extern void m8260_find_bridges(void);
|
||||
extern void pq2_find_bridges(void);
|
||||
extern void pq2pci_init_irq(void);
|
||||
extern void idma_pci9_init(void);
|
||||
|
||||
/* Place-holder for board-specific init */
|
||||
|
@ -56,7 +57,7 @@ m8260_setup_arch(void)
|
|||
idma_pci9_init();
|
||||
#endif
|
||||
#ifdef CONFIG_PCI_8260
|
||||
m8260_find_bridges();
|
||||
pq2_find_bridges();
|
||||
#endif
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
if (initrd_start)
|
||||
|
@ -173,6 +174,12 @@ m8260_init_IRQ(void)
|
|||
* in case the boot rom changed something on us.
|
||||
*/
|
||||
cpm2_immr->im_intctl.ic_siprr = 0x05309770;
|
||||
|
||||
#if defined(CONFIG_PCI) && (defined(CONFIG_ADS8272) || defined(CONFIG_PQ2FADS))
|
||||
/* Initialize stuff for the 82xx CPLD IC and install demux */
|
||||
pq2pci_init_irq();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,383 @@
|
|||
/*
|
||||
*
|
||||
* (C) Copyright 2003
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2004 Red Hat, Inc.
|
||||
*
|
||||
* 2005 (c) MontaVista Software, Inc.
|
||||
* Vitaly Bordug <vbordug@ru.mvista.com>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/immap_cpm2.h>
|
||||
#include <asm/mpc8260.h>
|
||||
#include <asm/cpm2.h>
|
||||
|
||||
#include "m82xx_pci.h"
|
||||
|
||||
/*
|
||||
* Interrupt routing
|
||||
*/
|
||||
|
||||
static inline int
|
||||
pq2pci_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
|
||||
{
|
||||
static char pci_irq_table[][4] =
|
||||
/*
|
||||
* PCI IDSEL/INTPIN->INTLINE
|
||||
* A B C D
|
||||
*/
|
||||
{
|
||||
{ PIRQA, PIRQB, PIRQC, PIRQD }, /* IDSEL 22 - PCI slot 0 */
|
||||
{ PIRQD, PIRQA, PIRQB, PIRQC }, /* IDSEL 23 - PCI slot 1 */
|
||||
{ PIRQC, PIRQD, PIRQA, PIRQB }, /* IDSEL 24 - PCI slot 2 */
|
||||
};
|
||||
|
||||
const long min_idsel = 22, max_idsel = 24, irqs_per_slot = 4;
|
||||
return PCI_IRQ_TABLE_LOOKUP;
|
||||
}
|
||||
|
||||
static void
|
||||
pq2pci_mask_irq(unsigned int irq)
|
||||
{
|
||||
int bit = irq - NR_CPM_INTS;
|
||||
|
||||
*(volatile unsigned long *) PCI_INT_MASK_REG |= (1 << (31 - bit));
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
pq2pci_unmask_irq(unsigned int irq)
|
||||
{
|
||||
int bit = irq - NR_CPM_INTS;
|
||||
|
||||
*(volatile unsigned long *) PCI_INT_MASK_REG &= ~(1 << (31 - bit));
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
pq2pci_mask_and_ack(unsigned int irq)
|
||||
{
|
||||
int bit = irq - NR_CPM_INTS;
|
||||
|
||||
*(volatile unsigned long *) PCI_INT_MASK_REG |= (1 << (31 - bit));
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
pq2pci_end_irq(unsigned int irq)
|
||||
{
|
||||
int bit = irq - NR_CPM_INTS;
|
||||
|
||||
*(volatile unsigned long *) PCI_INT_MASK_REG &= ~(1 << (31 - bit));
|
||||
return;
|
||||
}
|
||||
|
||||
struct hw_interrupt_type pq2pci_ic = {
|
||||
"PQ2 PCI",
|
||||
NULL,
|
||||
NULL,
|
||||
pq2pci_unmask_irq,
|
||||
pq2pci_mask_irq,
|
||||
pq2pci_mask_and_ack,
|
||||
pq2pci_end_irq,
|
||||
0
|
||||
};
|
||||
|
||||
static irqreturn_t
|
||||
pq2pci_irq_demux(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long stat, mask, pend;
|
||||
int bit;
|
||||
|
||||
for(;;) {
|
||||
stat = *(volatile unsigned long *) PCI_INT_STAT_REG;
|
||||
mask = *(volatile unsigned long *) PCI_INT_MASK_REG;
|
||||
pend = stat & ~mask & 0xf0000000;
|
||||
if (!pend)
|
||||
break;
|
||||
for (bit = 0; pend != 0; ++bit, pend <<= 1) {
|
||||
if (pend & 0x80000000)
|
||||
__do_IRQ(NR_CPM_INTS + bit, regs);
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction pq2pci_irqaction = {
|
||||
.handler = pq2pci_irq_demux,
|
||||
.flags = SA_INTERRUPT,
|
||||
.mask = CPU_MASK_NONE,
|
||||
.name = "PQ2 PCI cascade",
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
pq2pci_init_irq(void)
|
||||
{
|
||||
int irq;
|
||||
volatile cpm2_map_t *immap = cpm2_immr;
|
||||
#if defined CONFIG_ADS8272
|
||||
/* configure chip select for PCI interrupt controller */
|
||||
immap->im_memctl.memc_br3 = PCI_INT_STAT_REG | 0x00001801;
|
||||
immap->im_memctl.memc_or3 = 0xffff8010;
|
||||
#elif defined CONFIG_PQ2FADS
|
||||
immap->im_memctl.memc_br8 = PCI_INT_STAT_REG | 0x00001801;
|
||||
immap->im_memctl.memc_or8 = 0xffff8010;
|
||||
#endif
|
||||
for (irq = NR_CPM_INTS; irq < NR_CPM_INTS + 4; irq++)
|
||||
irq_desc[irq].handler = &pq2pci_ic;
|
||||
|
||||
/* make PCI IRQ level sensitive */
|
||||
immap->im_intctl.ic_siexr &=
|
||||
~(1 << (14 - (PCI_INT_TO_SIU - SIU_INT_IRQ1)));
|
||||
|
||||
/* mask all PCI interrupts */
|
||||
*(volatile unsigned long *) PCI_INT_MASK_REG |= 0xfff00000;
|
||||
|
||||
/* install the demultiplexer for the PCI cascade interrupt */
|
||||
setup_irq(PCI_INT_TO_SIU, &pq2pci_irqaction);
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
pq2pci_exclude_device(u_char bus, u_char devfn)
|
||||
{
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* PCI bus configuration registers.
|
||||
*/
|
||||
static void
|
||||
pq2ads_setup_pci(struct pci_controller *hose)
|
||||
{
|
||||
__u32 val;
|
||||
volatile cpm2_map_t *immap = cpm2_immr;
|
||||
bd_t* binfo = (bd_t*) __res;
|
||||
u32 sccr = immap->im_clkrst.car_sccr;
|
||||
uint pci_div,freq,time;
|
||||
/* PCI int lowest prio */
|
||||
/* Each 4 bits is a device bus request and the MS 4bits
|
||||
is highest priority */
|
||||
/* Bus 4bit value
|
||||
--- ----------
|
||||
CPM high 0b0000
|
||||
CPM middle 0b0001
|
||||
CPM low 0b0010
|
||||
PCI reguest 0b0011
|
||||
Reserved 0b0100
|
||||
Reserved 0b0101
|
||||
Internal Core 0b0110
|
||||
External Master 1 0b0111
|
||||
External Master 2 0b1000
|
||||
External Master 3 0b1001
|
||||
The rest are reserved
|
||||
*/
|
||||
immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x61207893;
|
||||
/* park bus on core */
|
||||
immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_CORE;
|
||||
/*
|
||||
* Set up master windows that allow the CPU to access PCI space. These
|
||||
* windows are set up using the two SIU PCIBR registers.
|
||||
*/
|
||||
|
||||
immap->im_memctl.memc_pcimsk0 = M82xx_PCI_PRIM_WND_SIZE;
|
||||
immap->im_memctl.memc_pcibr0 = M82xx_PCI_PRIM_WND_BASE | PCIBR_ENABLE;
|
||||
|
||||
#ifdef M82xx_PCI_SEC_WND_SIZE
|
||||
immap->im_memctl.memc_pcimsk1 = M82xx_PCI_SEC_WND_SIZE;
|
||||
immap->im_memctl.memc_pcibr1 = M82xx_PCI_SEC_WND_BASE | PCIBR_ENABLE;
|
||||
#endif
|
||||
|
||||
#if defined CONFIG_ADS8272
|
||||
immap->im_siu_conf.siu_82xx.sc_siumcr =
|
||||
(immap->im_siu_conf.siu_82xx.sc_siumcr &
|
||||
~(SIUMCR_BBD | SIUMCR_ESE | SIUMCR_PBSE |
|
||||
SIUMCR_CDIS | SIUMCR_DPPC11 | SIUMCR_L2CPC11 |
|
||||
SIUMCR_LBPC11 | SIUMCR_APPC11 |
|
||||
SIUMCR_CS10PC11 | SIUMCR_BCTLC11 | SIUMCR_MMR11)) |
|
||||
SIUMCR_DPPC11 | SIUMCR_L2CPC01 | SIUMCR_LBPC00 |
|
||||
SIUMCR_APPC10 | SIUMCR_CS10PC00 |
|
||||
SIUMCR_BCTLC00 | SIUMCR_MMR11 ;
|
||||
|
||||
#elif defined CONFIG_PQ2FADS
|
||||
/*
|
||||
* Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
|
||||
* and local bus for PCI (SIUMCR [LBPC]).
|
||||
*/
|
||||
immap->im_siu_conf.siu_82xx.sc_siumcr = (immap->im_siu_conf.sc_siumcr &
|
||||
~(SIUMCR_L2PC11 | SIUMCR_LBPC11 | SIUMCR_CS10PC11 | SIUMCR_APPC11) |
|
||||
SIUMCR_BBD | SIUMCR_LBPC01 | SIUMCR_DPPC11 | SIUMCR_APPC10;
|
||||
#endif
|
||||
/* Enable PCI */
|
||||
immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
|
||||
|
||||
pci_div = ( (sccr & SCCR_PCI_MODCK) ? 2 : 1) *
|
||||
( ( (sccr & SCCR_PCIDF_MSK) >> SCCR_PCIDF_SHIFT) + 1);
|
||||
freq = (uint)((2*binfo->bi_cpmfreq)/(pci_div));
|
||||
time = (int)666666/freq;
|
||||
/* due to PCI Local Bus spec, some devices needs to wait such a long
|
||||
time after RST deassertion. More specifically, 0.508s for 66MHz & twice more for 33 */
|
||||
printk("%s: The PCI bus is %d Mhz.\nWaiting %s after deasserting RST...\n",__FILE__,freq,
|
||||
(time==1) ? "0.5 seconds":"1 second" );
|
||||
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<(500*time);i++)
|
||||
udelay(1000);
|
||||
}
|
||||
|
||||
/* setup ATU registers */
|
||||
immap->im_pci.pci_pocmr0 = cpu_to_le32(POCMR_ENABLE | POCMR_PCI_IO |
|
||||
((~(M82xx_PCI_IO_SIZE - 1U)) >> POTA_ADDR_SHIFT));
|
||||
immap->im_pci.pci_potar0 = cpu_to_le32(M82xx_PCI_LOWER_IO >> POTA_ADDR_SHIFT);
|
||||
immap->im_pci.pci_pobar0 = cpu_to_le32(M82xx_PCI_IO_BASE >> POTA_ADDR_SHIFT);
|
||||
|
||||
/* Set-up non-prefetchable window */
|
||||
immap->im_pci.pci_pocmr1 = cpu_to_le32(POCMR_ENABLE | ((~(M82xx_PCI_MMIO_SIZE-1U)) >> POTA_ADDR_SHIFT));
|
||||
immap->im_pci.pci_potar1 = cpu_to_le32(M82xx_PCI_LOWER_MMIO >> POTA_ADDR_SHIFT);
|
||||
immap->im_pci.pci_pobar1 = cpu_to_le32((M82xx_PCI_LOWER_MMIO - M82xx_PCI_MMIO_OFFSET) >> POTA_ADDR_SHIFT);
|
||||
|
||||
/* Set-up prefetchable window */
|
||||
immap->im_pci.pci_pocmr2 = cpu_to_le32(POCMR_ENABLE |POCMR_PREFETCH_EN |
|
||||
(~(M82xx_PCI_MEM_SIZE-1U) >> POTA_ADDR_SHIFT));
|
||||
immap->im_pci.pci_potar2 = cpu_to_le32(M82xx_PCI_LOWER_MEM >> POTA_ADDR_SHIFT);
|
||||
immap->im_pci.pci_pobar2 = cpu_to_le32((M82xx_PCI_LOWER_MEM - M82xx_PCI_MEM_OFFSET) >> POTA_ADDR_SHIFT);
|
||||
|
||||
/* Inbound transactions from PCI memory space */
|
||||
immap->im_pci.pci_picmr0 = cpu_to_le32(PICMR_ENABLE | PICMR_PREFETCH_EN |
|
||||
((~(M82xx_PCI_SLAVE_MEM_SIZE-1U)) >> PITA_ADDR_SHIFT));
|
||||
immap->im_pci.pci_pibar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_BUS >> PITA_ADDR_SHIFT);
|
||||
immap->im_pci.pci_pitar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_LOCAL>> PITA_ADDR_SHIFT);
|
||||
|
||||
#if defined CONFIG_ADS8272
|
||||
/* PCI int highest prio */
|
||||
immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x01236745;
|
||||
#elif defined CONFIG_PQ2FADS
|
||||
immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567;
|
||||
#endif
|
||||
/* park bus on PCI */
|
||||
immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
|
||||
|
||||
/* Enable bus mastering and inbound memory transactions */
|
||||
early_read_config_dword(hose, hose->first_busno, 0, PCI_COMMAND, &val);
|
||||
val &= 0xffff0000;
|
||||
val |= PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER;
|
||||
early_write_config_dword(hose, hose->first_busno, 0, PCI_COMMAND, val);
|
||||
|
||||
}
|
||||
|
||||
void __init pq2_find_bridges(void)
|
||||
{
|
||||
extern int pci_assign_all_busses;
|
||||
struct pci_controller * hose;
|
||||
int host_bridge;
|
||||
|
||||
pci_assign_all_busses = 1;
|
||||
|
||||
hose = pcibios_alloc_controller();
|
||||
|
||||
if (!hose)
|
||||
return;
|
||||
|
||||
ppc_md.pci_swizzle = common_swizzle;
|
||||
|
||||
hose->first_busno = 0;
|
||||
hose->bus_offset = 0;
|
||||
hose->last_busno = 0xff;
|
||||
|
||||
#ifdef CONFIG_ADS8272
|
||||
hose->set_cfg_type = 1;
|
||||
#endif
|
||||
|
||||
setup_m8260_indirect_pci(hose,
|
||||
(unsigned long)&cpm2_immr->im_pci.pci_cfg_addr,
|
||||
(unsigned long)&cpm2_immr->im_pci.pci_cfg_data);
|
||||
|
||||
/* Make sure it is a supported bridge */
|
||||
early_read_config_dword(hose,
|
||||
0,
|
||||
PCI_DEVFN(0,0),
|
||||
PCI_VENDOR_ID,
|
||||
&host_bridge);
|
||||
switch (host_bridge) {
|
||||
case PCI_DEVICE_ID_MPC8265:
|
||||
break;
|
||||
case PCI_DEVICE_ID_MPC8272:
|
||||
break;
|
||||
default:
|
||||
printk("Attempting to use unrecognized host bridge ID"
|
||||
" 0x%08x.\n", host_bridge);
|
||||
break;
|
||||
}
|
||||
|
||||
pq2ads_setup_pci(hose);
|
||||
|
||||
hose->io_space.start = M82xx_PCI_LOWER_IO;
|
||||
hose->io_space.end = M82xx_PCI_UPPER_IO;
|
||||
hose->mem_space.start = M82xx_PCI_LOWER_MEM;
|
||||
hose->mem_space.end = M82xx_PCI_UPPER_MMIO;
|
||||
hose->pci_mem_offset = M82xx_PCI_MEM_OFFSET;
|
||||
|
||||
isa_io_base =
|
||||
(unsigned long) ioremap(M82xx_PCI_IO_BASE,
|
||||
M82xx_PCI_IO_SIZE);
|
||||
hose->io_base_virt = (void *) isa_io_base;
|
||||
|
||||
/* setup resources */
|
||||
pci_init_resource(&hose->mem_resources[0],
|
||||
M82xx_PCI_LOWER_MEM,
|
||||
M82xx_PCI_UPPER_MEM,
|
||||
IORESOURCE_MEM|IORESOURCE_PREFETCH, "PCI prefetchable memory");
|
||||
|
||||
pci_init_resource(&hose->mem_resources[1],
|
||||
M82xx_PCI_LOWER_MMIO,
|
||||
M82xx_PCI_UPPER_MMIO,
|
||||
IORESOURCE_MEM, "PCI memory");
|
||||
|
||||
pci_init_resource(&hose->io_resource,
|
||||
M82xx_PCI_LOWER_IO,
|
||||
M82xx_PCI_UPPER_IO,
|
||||
IORESOURCE_IO | 1, "PCI I/O");
|
||||
|
||||
ppc_md.pci_exclude_device = pq2pci_exclude_device;
|
||||
hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
|
||||
|
||||
ppc_md.pci_map_irq = pq2pci_map_irq;
|
||||
ppc_md.pcibios_fixup = NULL;
|
||||
ppc_md.pcibios_fixup_bus = NULL;
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
|
||||
#ifndef _PPC_KERNEL_M82XX_PCI_H
|
||||
#define _PPC_KERNEL_M82XX_PCI_H
|
||||
|
||||
#include <asm/m8260_pci.h>
|
||||
/*
|
||||
* Local->PCI map (from CPU) controlled by
|
||||
* MPC826x master window
|
||||
*
|
||||
* 0xF6000000 - 0xF7FFFFFF IO space
|
||||
* 0x80000000 - 0xBFFFFFFF CPU2PCI memory space PCIBR0
|
||||
*
|
||||
* 0x80000000 - 0x9FFFFFFF PCI Mem with prefetch (Outbound ATU #1)
|
||||
* 0xA0000000 - 0xBFFFFFFF PCI Mem w/o prefetch (Outbound ATU #2)
|
||||
* 0xF6000000 - 0xF7FFFFFF 32-bit PCI IO (Outbound ATU #3)
|
||||
*
|
||||
* PCI->Local map (from PCI)
|
||||
* MPC826x slave window controlled by
|
||||
*
|
||||
* 0x00000000 - 0x07FFFFFF MPC826x local memory (Inbound ATU #1)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Slave window that allows PCI masters to access MPC826x local memory.
|
||||
* This window is set up using the first set of Inbound ATU registers
|
||||
*/
|
||||
|
||||
#ifndef M82xx_PCI_SLAVE_MEM_LOCAL
|
||||
#define M82xx_PCI_SLAVE_MEM_LOCAL (((struct bd_info *)__res)->bi_memstart)
|
||||
#define M82xx_PCI_SLAVE_MEM_BUS (((struct bd_info *)__res)->bi_memstart)
|
||||
#define M82xx_PCI_SLAVE_MEM_SIZE (((struct bd_info *)__res)->bi_memsize)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is the window that allows the CPU to access PCI address space.
|
||||
* It will be setup with the SIU PCIBR0 register. All three PCI master
|
||||
* windows, which allow the CPU to access PCI prefetch, non prefetch,
|
||||
* and IO space (see below), must all fit within this window.
|
||||
*/
|
||||
|
||||
#ifndef M82xx_PCI_LOWER_MEM
|
||||
#define M82xx_PCI_LOWER_MEM 0x80000000
|
||||
#define M82xx_PCI_UPPER_MEM 0x9fffffff
|
||||
#define M82xx_PCI_MEM_OFFSET 0x00000000
|
||||
#define M82xx_PCI_MEM_SIZE 0x20000000
|
||||
#endif
|
||||
|
||||
#ifndef M82xx_PCI_LOWER_MMIO
|
||||
#define M82xx_PCI_LOWER_MMIO 0xa0000000
|
||||
#define M82xx_PCI_UPPER_MMIO 0xafffffff
|
||||
#define M82xx_PCI_MMIO_OFFSET 0x00000000
|
||||
#define M82xx_PCI_MMIO_SIZE 0x20000000
|
||||
#endif
|
||||
|
||||
#ifndef M82xx_PCI_LOWER_IO
|
||||
#define M82xx_PCI_LOWER_IO 0x00000000
|
||||
#define M82xx_PCI_UPPER_IO 0x01ffffff
|
||||
#define M82xx_PCI_IO_BASE 0xf6000000
|
||||
#define M82xx_PCI_IO_SIZE 0x02000000
|
||||
#endif
|
||||
|
||||
#ifndef M82xx_PCI_PRIM_WND_SIZE
|
||||
#define M82xx_PCI_PRIM_WND_SIZE ~(M82xx_PCI_IO_SIZE - 1U)
|
||||
#define M82xx_PCI_PRIM_WND_BASE (M82xx_PCI_IO_BASE)
|
||||
#endif
|
||||
|
||||
#ifndef M82xx_PCI_SEC_WND_SIZE
|
||||
#define M82xx_PCI_SEC_WND_SIZE ~(M82xx_PCI_MEM_SIZE + M82xx_PCI_MMIO_SIZE - 1U)
|
||||
#define M82xx_PCI_SEC_WND_BASE (M82xx_PCI_LOWER_MEM)
|
||||
#endif
|
||||
|
||||
#ifndef POTA_ADDR_SHIFT
|
||||
#define POTA_ADDR_SHIFT 12
|
||||
#endif
|
||||
|
||||
#ifndef PITA_ADDR_SHIFT
|
||||
#define PITA_ADDR_SHIFT 12
|
||||
#endif
|
||||
|
||||
#ifndef _IO_BASE
|
||||
#define _IO_BASE isa_io_base
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_8260_PCI9
|
||||
struct pci_controller;
|
||||
extern void setup_m8260_indirect_pci(struct pci_controller* hose,
|
||||
u32 cfg_addr, u32 cfg_data);
|
||||
#else
|
||||
#define setup_m8260_indirect_pci setup_indirect_pci
|
||||
#endif
|
||||
|
||||
#endif /* _PPC_KERNEL_M8260_PCI_H */
|
|
@ -275,7 +275,7 @@ static void __init openpic_enable_sie(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_EPIC_SERIAL_MODE) || defined(CONFIG_PM)
|
||||
#if defined(CONFIG_EPIC_SERIAL_MODE)
|
||||
static void openpic_reset(void)
|
||||
{
|
||||
openpic_setfield(&OpenPIC->Global.Global_Configuration0,
|
||||
|
@ -993,8 +993,6 @@ int openpic_resume(struct sys_device *sysdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
openpic_reset();
|
||||
|
||||
/* OpenPIC sometimes seem to need some time to be fully back up... */
|
||||
do {
|
||||
openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <asm/mmu.h>
|
||||
#include <asm/ppc_sys.h>
|
||||
#include <asm/kgdb.h>
|
||||
#include <asm/delay.h>
|
||||
|
||||
#include <syslib/ppc83xx_setup.h>
|
||||
|
||||
|
@ -117,7 +118,34 @@ mpc83xx_early_serial_map(void)
|
|||
void
|
||||
mpc83xx_restart(char *cmd)
|
||||
{
|
||||
volatile unsigned char __iomem *reg;
|
||||
unsigned char tmp;
|
||||
|
||||
reg = ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
/*
|
||||
* Unlock the BCSR bits so a PRST will update the contents.
|
||||
* Otherwise the reset asserts but doesn't clear.
|
||||
*/
|
||||
tmp = in_8(reg + BCSR_MISC_REG3_OFF);
|
||||
tmp |= BCSR_MISC_REG3_CNFLOCK; /* low true, high false */
|
||||
out_8(reg + BCSR_MISC_REG3_OFF, tmp);
|
||||
|
||||
/*
|
||||
* Trigger a reset via a low->high transition of the
|
||||
* PORESET bit.
|
||||
*/
|
||||
tmp = in_8(reg + BCSR_MISC_REG2_OFF);
|
||||
tmp &= ~BCSR_MISC_REG2_PORESET;
|
||||
out_8(reg + BCSR_MISC_REG2_OFF, tmp);
|
||||
|
||||
udelay(1);
|
||||
|
||||
tmp |= BCSR_MISC_REG2_PORESET;
|
||||
out_8(reg + BCSR_MISC_REG2_OFF, tmp);
|
||||
|
||||
for(;;);
|
||||
}
|
||||
|
||||
|
|
|
@ -132,6 +132,12 @@ mpc85xx_halt(void)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
#if defined(CONFIG_MPC8555_CDS)
|
||||
extern void mpc85xx_cds_enable_via(struct pci_controller *hose);
|
||||
extern void mpc85xx_cds_fixup_via(struct pci_controller *hose);
|
||||
#endif
|
||||
|
||||
static void __init
|
||||
mpc85xx_setup_pci1(struct pci_controller *hose)
|
||||
{
|
||||
|
@ -302,8 +308,18 @@ mpc85xx_setup_hose(void)
|
|||
|
||||
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
|
||||
|
||||
#if defined(CONFIG_MPC8555_CDS)
|
||||
/* Pre pciauto_bus_scan VIA init */
|
||||
mpc85xx_cds_enable_via(hose_a);
|
||||
#endif
|
||||
|
||||
hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
|
||||
|
||||
#if defined(CONFIG_MPC8555_CDS)
|
||||
/* Post pciauto_bus_scan VIA fixup */
|
||||
mpc85xx_cds_fixup_via(hose_a);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_85xx_PCI2
|
||||
hose_b = pcibios_alloc_controller();
|
||||
|
||||
|
|
|
@ -2,10 +2,6 @@ menu "Kernel hacking"
|
|||
|
||||
source "lib/Kconfig.debug"
|
||||
|
||||
config FRAME_POINTER
|
||||
bool
|
||||
default y if DEBUG_INFO
|
||||
|
||||
config PT_PROXY
|
||||
bool "Enable ptrace proxy"
|
||||
depends on XTERM_CHAN && DEBUG_INFO && MODE_TT
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
/* Much of this ripped from hw_random.c */
|
||||
|
||||
/* Copyright (C) 2005 Jeff Dike <jdike@addtoit.com> */
|
||||
/* Much of this ripped from drivers/char/hw_random.c, see there for other
|
||||
* copyright.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h>
|
||||
|
@ -12,8 +17,6 @@
|
|||
*/
|
||||
#define RNG_VERSION "1.0.0"
|
||||
#define RNG_MODULE_NAME "random"
|
||||
#define RNG_DRIVER_NAME RNG_MODULE_NAME " virtual driver " RNG_VERSION
|
||||
#define PFX RNG_MODULE_NAME ": "
|
||||
|
||||
#define RNG_MISCDEV_MINOR 183 /* official */
|
||||
|
||||
|
@ -98,7 +101,7 @@ static int __init rng_init (void)
|
|||
|
||||
err = misc_register (&rng_miscdev);
|
||||
if (err) {
|
||||
printk (KERN_ERR PFX "misc device register failed\n");
|
||||
printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n");
|
||||
goto err_out_cleanup_hw;
|
||||
}
|
||||
|
||||
|
@ -120,3 +123,6 @@ static void __exit rng_cleanup (void)
|
|||
|
||||
module_init (rng_init);
|
||||
module_exit (rng_cleanup);
|
||||
|
||||
MODULE_DESCRIPTION("UML Host Random Number Generator (RNG) driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "init.h"
|
||||
#include "irq_user.h"
|
||||
#include "mconsole_kern.h"
|
||||
#include "2_5compat.h"
|
||||
|
||||
static int ssl_version = 1;
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "irq_user.h"
|
||||
#include "mconsole_kern.h"
|
||||
#include "init.h"
|
||||
#include "2_5compat.h"
|
||||
|
||||
#define MAX_TTYS (16)
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
#include "irq_user.h"
|
||||
#include "irq_kern.h"
|
||||
#include "ubd_user.h"
|
||||
#include "2_5compat.h"
|
||||
#include "os.h"
|
||||
#include "mem.h"
|
||||
#include "mem_kern.h"
|
||||
|
@ -440,9 +439,9 @@ static int udb_setup(char *str)
|
|||
__setup("udb", udb_setup);
|
||||
__uml_help(udb_setup,
|
||||
"udb\n"
|
||||
" This option is here solely to catch ubd -> udb typos, which can be\n\n"
|
||||
" to impossible to catch visually unless you specifically look for\n\n"
|
||||
" them. The only result of any option starting with 'udb' is an error\n\n"
|
||||
" This option is here solely to catch ubd -> udb typos, which can be\n"
|
||||
" to impossible to catch visually unless you specifically look for\n"
|
||||
" them. The only result of any option starting with 'udb' is an error\n"
|
||||
" in the boot output.\n\n"
|
||||
);
|
||||
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __2_5_COMPAT_H__
|
||||
#define __2_5_COMPAT_H__
|
||||
|
||||
#define INIT_HARDSECT(arr, maj, sizes)
|
||||
|
||||
#define SET_PRI(task) do ; while(0)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef __UM_SYSRQ_H
|
||||
#define __UM_SYSRQ_H
|
||||
|
||||
extern void show_trace(unsigned long *stack);
|
||||
struct task_struct;
|
||||
extern void show_trace(struct task_struct* task, unsigned long *stack);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "kern.h"
|
||||
#include "irq_user.h"
|
||||
#include "tlb.h"
|
||||
#include "2_5compat.h"
|
||||
#include "os.h"
|
||||
#include "time_user.h"
|
||||
#include "choose-mode.h"
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#include "linux/init.h"
|
||||
#include "linux/bootmem.h"
|
||||
#include "linux/initrd.h"
|
||||
#include "asm/types.h"
|
||||
#include "user_util.h"
|
||||
#include "kern_util.h"
|
||||
#include "initrd.h"
|
||||
#include "init.h"
|
||||
#include "os.h"
|
||||
|
||||
/* Changed by uml_initrd_setup, which is a setup */
|
||||
static char *initrd __initdata = NULL;
|
||||
|
||||
static int __init read_initrd(void)
|
||||
{
|
||||
void *area;
|
||||
long long size;
|
||||
int err;
|
||||
|
||||
if(initrd == NULL) return 0;
|
||||
err = os_file_size(initrd, &size);
|
||||
if(err) return 0;
|
||||
area = alloc_bootmem(size);
|
||||
if(area == NULL) return 0;
|
||||
if(load_initrd(initrd, area, size) == -1) return 0;
|
||||
initrd_start = (unsigned long) area;
|
||||
initrd_end = initrd_start + size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__uml_postsetup(read_initrd);
|
||||
|
||||
static int __init uml_initrd_setup(char *line, int *add)
|
||||
{
|
||||
initrd = line;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__uml_setup("initrd=", uml_initrd_setup,
|
||||
"initrd=<initrd image>\n"
|
||||
" This is used to boot UML from an initrd image. The argument is the\n"
|
||||
" name of the file containing the image.\n\n"
|
||||
);
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "user_util.h"
|
||||
#include "kern_util.h"
|
||||
#include "user.h"
|
||||
#include "initrd.h"
|
||||
#include "os.h"
|
||||
|
||||
int load_initrd(char *filename, void *buf, int size)
|
||||
{
|
||||
int fd, n;
|
||||
|
||||
fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
|
||||
if(fd < 0){
|
||||
printk("Opening '%s' failed - err = %d\n", filename, -fd);
|
||||
return(-1);
|
||||
}
|
||||
n = os_read_file(fd, buf, size);
|
||||
if(n != size){
|
||||
printk("Read of %d bytes from '%s' failed, err = %d\n", size,
|
||||
filename, -n);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
os_close_file(fd);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
|
@ -71,7 +71,7 @@ static __init void do_uml_initcalls(void)
|
|||
|
||||
static void last_ditch_exit(int sig)
|
||||
{
|
||||
CHOOSE_MODE(kmalloc_ok = 0, (void) 0);
|
||||
kmalloc_ok = 0;
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGHUP, SIG_DFL);
|
||||
|
@ -87,7 +87,7 @@ int main(int argc, char **argv, char **envp)
|
|||
{
|
||||
char **new_argv;
|
||||
sigset_t mask;
|
||||
int ret, i;
|
||||
int ret, i, err;
|
||||
|
||||
/* Enable all signals except SIGIO - in some environments, we can
|
||||
* enter with some signals blocked
|
||||
|
@ -160,27 +160,29 @@ int main(int argc, char **argv, char **envp)
|
|||
*/
|
||||
change_sig(SIGPROF, 0);
|
||||
|
||||
/* This signal stuff used to be in the reboot case. However,
|
||||
* sometimes a SIGVTALRM can come in when we're halting (reproducably
|
||||
* when writing out gcov information, presumably because that takes
|
||||
* some time) and cause a segfault.
|
||||
*/
|
||||
|
||||
/* stop timers and set SIG*ALRM to be ignored */
|
||||
disable_timer();
|
||||
|
||||
/* disable SIGIO for the fds and set SIGIO to be ignored */
|
||||
err = deactivate_all_fds();
|
||||
if(err)
|
||||
printf("deactivate_all_fds failed, errno = %d\n", -err);
|
||||
|
||||
/* Let any pending signals fire now. This ensures
|
||||
* that they won't be delivered after the exec, when
|
||||
* they are definitely not expected.
|
||||
*/
|
||||
unblock_signals();
|
||||
|
||||
/* Reboot */
|
||||
if(ret){
|
||||
int err;
|
||||
|
||||
printf("\n");
|
||||
|
||||
/* stop timers and set SIG*ALRM to be ignored */
|
||||
disable_timer();
|
||||
|
||||
/* disable SIGIO for the fds and set SIGIO to be ignored */
|
||||
err = deactivate_all_fds();
|
||||
if(err)
|
||||
printf("deactivate_all_fds failed, errno = %d\n",
|
||||
-err);
|
||||
|
||||
/* Let any pending signals fire now. This ensures
|
||||
* that they won't be delivered after the exec, when
|
||||
* they are definitely not expected.
|
||||
*/
|
||||
unblock_signals();
|
||||
|
||||
execvp(new_argv[0], new_argv);
|
||||
perror("Failed to exec kernel");
|
||||
ret = 1;
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include "tlb.h"
|
||||
#include "frame_kern.h"
|
||||
#include "sigcontext.h"
|
||||
#include "2_5compat.h"
|
||||
#include "os.h"
|
||||
#include "mode.h"
|
||||
#include "mode_kern.h"
|
||||
|
@ -55,18 +54,6 @@
|
|||
*/
|
||||
struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
|
||||
|
||||
struct task_struct *get_task(int pid, int require)
|
||||
{
|
||||
struct task_struct *ret;
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
ret = find_task_by_pid(pid);
|
||||
read_unlock(&tasklist_lock);
|
||||
|
||||
if(require && (ret == NULL)) panic("get_task couldn't find a task\n");
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int external_pid(void *t)
|
||||
{
|
||||
struct task_struct *task = t ? t : current;
|
||||
|
@ -189,7 +176,6 @@ void default_idle(void)
|
|||
|
||||
while(1){
|
||||
/* endless idle loop with no priority at all */
|
||||
SET_PRI(current);
|
||||
|
||||
/*
|
||||
* although we are an idle CPU, we do not want to
|
||||
|
@ -212,11 +198,6 @@ int page_size(void)
|
|||
return(PAGE_SIZE);
|
||||
}
|
||||
|
||||
unsigned long page_mask(void)
|
||||
{
|
||||
return(PAGE_MASK);
|
||||
}
|
||||
|
||||
void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
|
||||
pte_t *pte_out)
|
||||
{
|
||||
|
@ -349,11 +330,6 @@ char *uml_strdup(char *string)
|
|||
return(new);
|
||||
}
|
||||
|
||||
void *get_init_task(void)
|
||||
{
|
||||
return(&init_thread_union.thread_info.task);
|
||||
}
|
||||
|
||||
int copy_to_user_proc(void __user *to, void *from, int size)
|
||||
{
|
||||
return(copy_to_user(to, from, size));
|
||||
|
@ -480,15 +456,3 @@ unsigned long arch_align_stack(unsigned long sp)
|
|||
return sp & ~0xf;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
|
|
|
@ -322,11 +322,9 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
|
|||
UPT_SYSCALL_ARG2(regs),
|
||||
UPT_SYSCALL_ARG3(regs),
|
||||
UPT_SYSCALL_ARG4(regs));
|
||||
else {
|
||||
int res = UPT_SYSCALL_RET(regs);
|
||||
audit_syscall_exit(current, AUDITSC_RESULT(res),
|
||||
res);
|
||||
}
|
||||
else audit_syscall_exit(current,
|
||||
AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
|
||||
UPT_SYSCALL_RET(regs));
|
||||
}
|
||||
|
||||
/* Fake a debug trap */
|
||||
|
@ -356,14 +354,3 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
|
|||
current->exit_code = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#include "linux/config.h"
|
||||
#include "linux/sched.h"
|
||||
#include "linux/kernel.h"
|
||||
#include "linux/module.h"
|
||||
|
@ -12,14 +13,14 @@
|
|||
#include "sysrq.h"
|
||||
#include "user_util.h"
|
||||
|
||||
void show_trace(unsigned long * stack)
|
||||
/* Catch non-i386 SUBARCH's. */
|
||||
#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
|
||||
void show_trace(struct task_struct *task, unsigned long * stack)
|
||||
{
|
||||
/* XXX: Copy the CONFIG_FRAME_POINTER stack-walking backtrace from
|
||||
* arch/i386/kernel/traps.c, and then move this to sys-i386/sysrq.c.*/
|
||||
unsigned long addr;
|
||||
|
||||
if (!stack) {
|
||||
stack = (unsigned long*) &stack;
|
||||
stack = (unsigned long*) &stack;
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
|
@ -35,6 +36,7 @@ void show_trace(unsigned long * stack)
|
|||
}
|
||||
printk("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* stack dumps generator - this is used by arch-independent code.
|
||||
|
@ -44,7 +46,7 @@ void dump_stack(void)
|
|||
{
|
||||
unsigned long stack;
|
||||
|
||||
show_trace(&stack);
|
||||
show_trace(current, &stack);
|
||||
}
|
||||
EXPORT_SYMBOL(dump_stack);
|
||||
|
||||
|
@ -59,7 +61,11 @@ void show_stack(struct task_struct *task, unsigned long *esp)
|
|||
int i;
|
||||
|
||||
if (esp == NULL) {
|
||||
if (task != current) {
|
||||
if (task != current && task != NULL) {
|
||||
/* XXX: Isn't this bogus? I.e. isn't this the
|
||||
* *userspace* stack of this task? If not so, use this
|
||||
* even when task == current (as in i386).
|
||||
*/
|
||||
esp = (unsigned long *) KSTK_ESP(task);
|
||||
/* Which one? No actual difference - just coding style.*/
|
||||
//esp = (unsigned long *) PT_REGS_IP(&task->thread.regs);
|
||||
|
@ -77,5 +83,6 @@ void show_stack(struct task_struct *task, unsigned long *esp)
|
|||
printk("%08lx ", *stack++);
|
||||
}
|
||||
|
||||
show_trace(esp);
|
||||
printk("Call Trace: \n");
|
||||
show_trace(current, esp);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "kern.h"
|
||||
#include "chan_kern.h"
|
||||
#include "mconsole_kern.h"
|
||||
#include "2_5compat.h"
|
||||
#include "mem.h"
|
||||
#include "mem_kern.h"
|
||||
|
||||
|
|
|
@ -32,10 +32,6 @@ void *switch_to_tt(void *prev, void *next, void *last)
|
|||
unsigned long flags;
|
||||
int err, vtalrm, alrm, prof, cpu;
|
||||
char c;
|
||||
/* jailing and SMP are incompatible, so this doesn't need to be
|
||||
* made per-cpu
|
||||
*/
|
||||
static int reading;
|
||||
|
||||
from = prev;
|
||||
to = next;
|
||||
|
@ -59,13 +55,11 @@ void *switch_to_tt(void *prev, void *next, void *last)
|
|||
c = 0;
|
||||
set_current(to);
|
||||
|
||||
reading = 0;
|
||||
err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
|
||||
if(err != sizeof(c))
|
||||
panic("write of switch_pipe failed, err = %d", -err);
|
||||
|
||||
reading = 1;
|
||||
if(from->thread.mode.tt.switch_pipe[0] == -1)
|
||||
if(from->thread.mode.tt.switch_pipe[0] == -1)
|
||||
os_kill_process(os_getpid(), 0);
|
||||
|
||||
err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c));
|
||||
|
|
|
@ -111,12 +111,6 @@ struct seq_operations cpuinfo_op = {
|
|||
.show = show_cpuinfo,
|
||||
};
|
||||
|
||||
pte_t * __bad_pagetable(void)
|
||||
{
|
||||
panic("Someone should implement __bad_pagetable");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Set in linux_main */
|
||||
unsigned long host_task_size;
|
||||
unsigned long task_size;
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#include "linux/config.h"
|
||||
#include "linux/kernel.h"
|
||||
#include "linux/smp.h"
|
||||
#include "linux/sched.h"
|
||||
#include "linux/kallsyms.h"
|
||||
#include "asm/ptrace.h"
|
||||
#include "sysrq.h"
|
||||
|
||||
/* This is declared by <linux/sched.h> */
|
||||
void show_regs(struct pt_regs *regs)
|
||||
{
|
||||
printk("\n");
|
||||
|
@ -31,5 +34,80 @@ void show_regs(struct pt_regs *regs)
|
|||
0xffff & PT_REGS_DS(regs),
|
||||
0xffff & PT_REGS_ES(regs));
|
||||
|
||||
show_trace((unsigned long *) ®s);
|
||||
show_trace(NULL, (unsigned long *) ®s);
|
||||
}
|
||||
|
||||
/* Copied from i386. */
|
||||
static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
|
||||
{
|
||||
return p > (void *)tinfo &&
|
||||
p < (void *)tinfo + THREAD_SIZE - 3;
|
||||
}
|
||||
|
||||
/* Adapted from i386 (we also print the address we read from). */
|
||||
static inline unsigned long print_context_stack(struct thread_info *tinfo,
|
||||
unsigned long *stack, unsigned long ebp)
|
||||
{
|
||||
unsigned long addr;
|
||||
|
||||
#ifdef CONFIG_FRAME_POINTER
|
||||
while (valid_stack_ptr(tinfo, (void *)ebp)) {
|
||||
addr = *(unsigned long *)(ebp + 4);
|
||||
printk("%08lx: [<%08lx>]", ebp + 4, addr);
|
||||
print_symbol(" %s", addr);
|
||||
printk("\n");
|
||||
ebp = *(unsigned long *)ebp;
|
||||
}
|
||||
#else
|
||||
while (valid_stack_ptr(tinfo, stack)) {
|
||||
addr = *stack;
|
||||
if (__kernel_text_address(addr)) {
|
||||
printk("%08lx: [<%08lx>]", (unsigned long) stack, addr);
|
||||
print_symbol(" %s", addr);
|
||||
printk("\n");
|
||||
}
|
||||
stack++;
|
||||
}
|
||||
#endif
|
||||
return ebp;
|
||||
}
|
||||
|
||||
void show_trace(struct task_struct* task, unsigned long * stack)
|
||||
{
|
||||
unsigned long ebp;
|
||||
struct thread_info *context;
|
||||
|
||||
/* Turn this into BUG_ON if possible. */
|
||||
if (!stack) {
|
||||
stack = (unsigned long*) &stack;
|
||||
printk("show_trace: got NULL stack, implicit assumption task == current");
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
if (!task)
|
||||
task = current;
|
||||
|
||||
if (task != current) {
|
||||
//ebp = (unsigned long) KSTK_EBP(task);
|
||||
/* Which one? No actual difference - just coding style.*/
|
||||
ebp = (unsigned long) PT_REGS_EBP(&task->thread.regs);
|
||||
} else {
|
||||
asm ("movl %%ebp, %0" : "=r" (ebp) : );
|
||||
}
|
||||
|
||||
context = (struct thread_info *)
|
||||
((unsigned long)stack & (~(THREAD_SIZE - 1)));
|
||||
print_context_stack(context, stack, ebp);
|
||||
|
||||
/*while (((long) stack & (THREAD_SIZE-1)) != 0) {
|
||||
addr = *stack;
|
||||
if (__kernel_text_address(addr)) {
|
||||
printk("%08lx: [<%08lx>]", (unsigned long) stack, addr);
|
||||
print_symbol(" %s", addr);
|
||||
printk("\n");
|
||||
}
|
||||
stack++;
|
||||
}*/
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -27,17 +27,5 @@ void show_regs(struct pt_regs_subarch *regs)
|
|||
0xffff & regs->xds, 0xffff & regs->xes);
|
||||
#endif
|
||||
|
||||
show_trace(®s->gpr[1]);
|
||||
show_trace(current, ®s->gpr[1]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
|
|
|
@ -133,23 +133,27 @@ static long arch_prctl_tt(int code, unsigned long addr)
|
|||
|
||||
#ifdef CONFIG_MODE_SKAS
|
||||
|
||||
/* XXX: Must also call arch_prctl in the host, beside saving the segment bases! */
|
||||
static long arch_prctl_skas(int code, unsigned long addr)
|
||||
{
|
||||
long ret = 0;
|
||||
|
||||
switch(code){
|
||||
case ARCH_SET_GS:
|
||||
current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr;
|
||||
break;
|
||||
case ARCH_SET_FS:
|
||||
current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr;
|
||||
break;
|
||||
case ARCH_SET_GS:
|
||||
current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr;
|
||||
break;
|
||||
case ARCH_GET_FS:
|
||||
ret = put_user(current->thread.regs.regs.skas.regs[GS / sizeof(unsigned long)], &addr);
|
||||
ret = put_user(current->thread.regs.regs.skas.
|
||||
regs[FS_BASE / sizeof(unsigned long)],
|
||||
(unsigned long __user *)addr);
|
||||
break;
|
||||
case ARCH_GET_GS:
|
||||
ret = put_user(current->thread.regs.regs.skas.regs[FS / sizeof(unsigned \
|
||||
long)], &addr);
|
||||
ret = put_user(current->thread.regs.regs.skas.
|
||||
regs[GS_BASE / sizeof(unsigned long)],
|
||||
(unsigned long __user *)addr);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
|
|
@ -36,14 +36,5 @@ void __show_regs(struct pt_regs * regs)
|
|||
void show_regs(struct pt_regs *regs)
|
||||
{
|
||||
__show_regs(regs);
|
||||
show_trace((unsigned long *) ®s);
|
||||
show_trace(current, (unsigned long *) ®s);
|
||||
}
|
||||
|
||||
/* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
|
|
|
@ -421,7 +421,7 @@ config PCI_DIRECT
|
|||
|
||||
config PCI_MMCONFIG
|
||||
bool "Support mmconfig PCI config space access"
|
||||
depends on PCI
|
||||
depends on PCI && ACPI
|
||||
select ACPI_BOOT
|
||||
|
||||
config UNORDERED_IO
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/i387.h>
|
||||
#include <asm/proto.h>
|
||||
#include <asm/ia32_unistd.h>
|
||||
|
||||
/* #define DEBUG_SIG 1 */
|
||||
|
||||
|
|
|
@ -40,13 +40,12 @@ config ACPI
|
|||
available at:
|
||||
<http://www.acpi.info>
|
||||
|
||||
if ACPI
|
||||
|
||||
config ACPI_BOOT
|
||||
bool
|
||||
depends on ACPI || X86_HT
|
||||
default y
|
||||
|
||||
if ACPI
|
||||
|
||||
config ACPI_INTERPRETER
|
||||
bool
|
||||
depends on !IA64_SGI_SN
|
||||
|
|
|
@ -391,7 +391,6 @@ acpi_pci_irq_enable (
|
|||
u8 pin = 0;
|
||||
int edge_level = ACPI_LEVEL_SENSITIVE;
|
||||
int active_high_low = ACPI_ACTIVE_LOW;
|
||||
extern int via_interrupt_line_quirk;
|
||||
char *link = NULL;
|
||||
|
||||
ACPI_FUNCTION_TRACE("acpi_pci_irq_enable");
|
||||
|
@ -444,9 +443,6 @@ acpi_pci_irq_enable (
|
|||
}
|
||||
}
|
||||
|
||||
if (via_interrupt_line_quirk)
|
||||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq & 15);
|
||||
|
||||
dev->irq = acpi_register_gsi(irq, edge_level, active_high_low);
|
||||
|
||||
printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ",
|
||||
|
|
|
@ -488,6 +488,20 @@ static int viocd_packet(struct cdrom_device_info *cdi,
|
|||
& (CDC_DVD_RAM | CDC_RAM)) != 0;
|
||||
}
|
||||
break;
|
||||
case GPCMD_GET_CONFIGURATION:
|
||||
if (cgc->cmd[3] == CDF_RWRT) {
|
||||
struct rwrt_feature_desc *rfd = (struct rwrt_feature_desc *)(cgc->buffer + sizeof(struct feature_header));
|
||||
|
||||
if ((buflen >=
|
||||
(sizeof(struct feature_header) + sizeof(*rfd))) &&
|
||||
(cdi->ops->capability & ~cdi->mask
|
||||
& (CDC_DVD_RAM | CDC_RAM))) {
|
||||
rfd->feature_code = cpu_to_be16(CDF_RWRT);
|
||||
rfd->curr = 1;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (cgc->sense) {
|
||||
/* indicate Unknown code */
|
||||
|
|
|
@ -1932,8 +1932,11 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
|
|||
|
||||
/*
|
||||
* check if dma is safe
|
||||
*
|
||||
* NOTE! The "len" and "addr" checks should possibly have
|
||||
* separate masks.
|
||||
*/
|
||||
if ((rq->data_len & 3) || (addr & mask))
|
||||
if ((rq->data_len & mask) || (addr & mask))
|
||||
info->dma = 0;
|
||||
}
|
||||
|
||||
|
@ -3255,16 +3258,12 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive)
|
|||
return capacity * sectors_per_frame;
|
||||
}
|
||||
|
||||
static
|
||||
int ide_cdrom_cleanup(ide_drive_t *drive)
|
||||
static int ide_cd_remove(struct device *dev)
|
||||
{
|
||||
ide_drive_t *drive = to_ide_device(dev);
|
||||
struct cdrom_info *info = drive->driver_data;
|
||||
|
||||
if (ide_unregister_subdriver(drive)) {
|
||||
printk(KERN_ERR "%s: %s: failed to ide_unregister_subdriver\n",
|
||||
__FUNCTION__, drive->name);
|
||||
return 1;
|
||||
}
|
||||
ide_unregister_subdriver(drive, info->driver);
|
||||
|
||||
del_gendisk(info->disk);
|
||||
|
||||
|
@ -3297,7 +3296,7 @@ static void ide_cd_release(struct kref *kref)
|
|||
kfree(info);
|
||||
}
|
||||
|
||||
static int ide_cdrom_attach (ide_drive_t *drive);
|
||||
static int ide_cd_probe(struct device *);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int proc_idecd_read_capacity
|
||||
|
@ -3320,19 +3319,20 @@ static ide_proc_entry_t idecd_proc[] = {
|
|||
|
||||
static ide_driver_t ide_cdrom_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "ide-cdrom",
|
||||
.gen_driver = {
|
||||
.name = "ide-cdrom",
|
||||
.bus = &ide_bus_type,
|
||||
.probe = ide_cd_probe,
|
||||
.remove = ide_cd_remove,
|
||||
},
|
||||
.version = IDECD_VERSION,
|
||||
.media = ide_cdrom,
|
||||
.busy = 0,
|
||||
.supports_dsc_overlap = 1,
|
||||
.cleanup = ide_cdrom_cleanup,
|
||||
.do_request = ide_do_rw_cdrom,
|
||||
.end_request = ide_end_request,
|
||||
.error = __ide_error,
|
||||
.abort = __ide_abort,
|
||||
.proc = idecd_proc,
|
||||
.attach = ide_cdrom_attach,
|
||||
.drives = LIST_HEAD_INIT(ide_cdrom_driver.drives),
|
||||
};
|
||||
|
||||
static int idecd_open(struct inode * inode, struct file * file)
|
||||
|
@ -3418,8 +3418,9 @@ static char *ignore = NULL;
|
|||
module_param(ignore, charp, 0400);
|
||||
MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
|
||||
|
||||
static int ide_cdrom_attach (ide_drive_t *drive)
|
||||
static int ide_cd_probe(struct device *dev)
|
||||
{
|
||||
ide_drive_t *drive = to_ide_device(dev);
|
||||
struct cdrom_info *info;
|
||||
struct gendisk *g;
|
||||
struct request_sense sense;
|
||||
|
@ -3453,11 +3454,8 @@ static int ide_cdrom_attach (ide_drive_t *drive)
|
|||
|
||||
ide_init_disk(g, drive);
|
||||
|
||||
if (ide_register_subdriver(drive, &ide_cdrom_driver)) {
|
||||
printk(KERN_ERR "%s: Failed to register the driver with ide.c\n",
|
||||
drive->name);
|
||||
goto out_put_disk;
|
||||
}
|
||||
ide_register_subdriver(drive, &ide_cdrom_driver);
|
||||
|
||||
memset(info, 0, sizeof (struct cdrom_info));
|
||||
|
||||
kref_init(&info->kref);
|
||||
|
@ -3470,7 +3468,6 @@ static int ide_cdrom_attach (ide_drive_t *drive)
|
|||
|
||||
drive->driver_data = info;
|
||||
|
||||
DRIVER(drive)->busy++;
|
||||
g->minors = 1;
|
||||
snprintf(g->devfs_name, sizeof(g->devfs_name),
|
||||
"%s/cd", drive->devfs_name);
|
||||
|
@ -3478,8 +3475,7 @@ static int ide_cdrom_attach (ide_drive_t *drive)
|
|||
g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
|
||||
if (ide_cdrom_setup(drive)) {
|
||||
struct cdrom_device_info *devinfo = &info->devinfo;
|
||||
DRIVER(drive)->busy--;
|
||||
ide_unregister_subdriver(drive);
|
||||
ide_unregister_subdriver(drive, &ide_cdrom_driver);
|
||||
if (info->buffer != NULL)
|
||||
kfree(info->buffer);
|
||||
if (info->toc != NULL)
|
||||
|
@ -3492,7 +3488,6 @@ static int ide_cdrom_attach (ide_drive_t *drive)
|
|||
drive->driver_data = NULL;
|
||||
goto failed;
|
||||
}
|
||||
DRIVER(drive)->busy--;
|
||||
|
||||
cdrom_read_toc(drive, &sense);
|
||||
g->fops = &idecd_ops;
|
||||
|
@ -3500,23 +3495,20 @@ static int ide_cdrom_attach (ide_drive_t *drive)
|
|||
add_disk(g);
|
||||
return 0;
|
||||
|
||||
out_put_disk:
|
||||
put_disk(g);
|
||||
out_free_cd:
|
||||
kfree(info);
|
||||
failed:
|
||||
return 1;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void __exit ide_cdrom_exit(void)
|
||||
{
|
||||
ide_unregister_driver(&ide_cdrom_driver);
|
||||
driver_unregister(&ide_cdrom_driver.gen_driver);
|
||||
}
|
||||
|
||||
static int ide_cdrom_init(void)
|
||||
{
|
||||
ide_register_driver(&ide_cdrom_driver);
|
||||
return 0;
|
||||
return driver_register(&ide_cdrom_driver.gen_driver);
|
||||
}
|
||||
|
||||
module_init(ide_cdrom_init);
|
||||
|
|
|
@ -1024,14 +1024,16 @@ static void ide_cacheflush_p(ide_drive_t *drive)
|
|||
printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
|
||||
}
|
||||
|
||||
static int idedisk_cleanup (ide_drive_t *drive)
|
||||
static int ide_disk_remove(struct device *dev)
|
||||
{
|
||||
ide_drive_t *drive = to_ide_device(dev);
|
||||
struct ide_disk_obj *idkp = drive->driver_data;
|
||||
struct gendisk *g = idkp->disk;
|
||||
|
||||
ide_cacheflush_p(drive);
|
||||
if (ide_unregister_subdriver(drive))
|
||||
return 1;
|
||||
|
||||
ide_unregister_subdriver(drive, idkp->driver);
|
||||
|
||||
del_gendisk(g);
|
||||
|
||||
ide_disk_put(idkp);
|
||||
|
@ -1052,7 +1054,7 @@ static void ide_disk_release(struct kref *kref)
|
|||
kfree(idkp);
|
||||
}
|
||||
|
||||
static int idedisk_attach(ide_drive_t *drive);
|
||||
static int ide_disk_probe(struct device *dev);
|
||||
|
||||
static void ide_device_shutdown(struct device *dev)
|
||||
{
|
||||
|
@ -1082,27 +1084,23 @@ static void ide_device_shutdown(struct device *dev)
|
|||
dev->bus->suspend(dev, PMSG_SUSPEND);
|
||||
}
|
||||
|
||||
/*
|
||||
* IDE subdriver functions, registered with ide.c
|
||||
*/
|
||||
static ide_driver_t idedisk_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.gen_driver = {
|
||||
.name = "ide-disk",
|
||||
.bus = &ide_bus_type,
|
||||
.probe = ide_disk_probe,
|
||||
.remove = ide_disk_remove,
|
||||
.shutdown = ide_device_shutdown,
|
||||
},
|
||||
.name = "ide-disk",
|
||||
.version = IDEDISK_VERSION,
|
||||
.media = ide_disk,
|
||||
.busy = 0,
|
||||
.supports_dsc_overlap = 0,
|
||||
.cleanup = idedisk_cleanup,
|
||||
.do_request = ide_do_rw_disk,
|
||||
.end_request = ide_end_request,
|
||||
.error = __ide_error,
|
||||
.abort = __ide_abort,
|
||||
.proc = idedisk_proc,
|
||||
.attach = idedisk_attach,
|
||||
.drives = LIST_HEAD_INIT(idedisk_driver.drives),
|
||||
};
|
||||
|
||||
static int idedisk_open(struct inode *inode, struct file *filp)
|
||||
|
@ -1199,8 +1197,9 @@ static struct block_device_operations idedisk_ops = {
|
|||
|
||||
MODULE_DESCRIPTION("ATA DISK Driver");
|
||||
|
||||
static int idedisk_attach(ide_drive_t *drive)
|
||||
static int ide_disk_probe(struct device *dev)
|
||||
{
|
||||
ide_drive_t *drive = to_ide_device(dev);
|
||||
struct ide_disk_obj *idkp;
|
||||
struct gendisk *g;
|
||||
|
||||
|
@ -1222,10 +1221,7 @@ static int idedisk_attach(ide_drive_t *drive)
|
|||
|
||||
ide_init_disk(g, drive);
|
||||
|
||||
if (ide_register_subdriver(drive, &idedisk_driver)) {
|
||||
printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
|
||||
goto out_put_disk;
|
||||
}
|
||||
ide_register_subdriver(drive, &idedisk_driver);
|
||||
|
||||
memset(idkp, 0, sizeof(*idkp));
|
||||
|
||||
|
@ -1239,7 +1235,6 @@ static int idedisk_attach(ide_drive_t *drive)
|
|||
|
||||
drive->driver_data = idkp;
|
||||
|
||||
DRIVER(drive)->busy++;
|
||||
idedisk_setup(drive);
|
||||
if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
|
||||
printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
|
||||
|
@ -1247,7 +1242,7 @@ static int idedisk_attach(ide_drive_t *drive)
|
|||
drive->attach = 0;
|
||||
} else
|
||||
drive->attach = 1;
|
||||
DRIVER(drive)->busy--;
|
||||
|
||||
g->minors = 1 << PARTN_BITS;
|
||||
strcpy(g->devfs_name, drive->devfs_name);
|
||||
g->driverfs_dev = &drive->gendev;
|
||||
|
@ -1257,22 +1252,20 @@ static int idedisk_attach(ide_drive_t *drive)
|
|||
add_disk(g);
|
||||
return 0;
|
||||
|
||||
out_put_disk:
|
||||
put_disk(g);
|
||||
out_free_idkp:
|
||||
kfree(idkp);
|
||||
failed:
|
||||
return 1;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void __exit idedisk_exit (void)
|
||||
{
|
||||
ide_unregister_driver(&idedisk_driver);
|
||||
driver_unregister(&idedisk_driver.gen_driver);
|
||||
}
|
||||
|
||||
static int idedisk_init (void)
|
||||
{
|
||||
return ide_register_driver(&idedisk_driver);
|
||||
return driver_register(&idedisk_driver.gen_driver);
|
||||
}
|
||||
|
||||
module_init(idedisk_init);
|
||||
|
|
|
@ -1865,13 +1865,13 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
|
|||
idefloppy_add_settings(drive);
|
||||
}
|
||||
|
||||
static int idefloppy_cleanup (ide_drive_t *drive)
|
||||
static int ide_floppy_remove(struct device *dev)
|
||||
{
|
||||
ide_drive_t *drive = to_ide_device(dev);
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
struct gendisk *g = floppy->disk;
|
||||
|
||||
if (ide_unregister_subdriver(drive))
|
||||
return 1;
|
||||
ide_unregister_subdriver(drive, floppy->driver);
|
||||
|
||||
del_gendisk(g);
|
||||
|
||||
|
@ -1916,26 +1916,24 @@ static ide_proc_entry_t idefloppy_proc[] = {
|
|||
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
static int idefloppy_attach(ide_drive_t *drive);
|
||||
static int ide_floppy_probe(struct device *);
|
||||
|
||||
/*
|
||||
* IDE subdriver functions, registered with ide.c
|
||||
*/
|
||||
static ide_driver_t idefloppy_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "ide-floppy",
|
||||
.gen_driver = {
|
||||
.name = "ide-floppy",
|
||||
.bus = &ide_bus_type,
|
||||
.probe = ide_floppy_probe,
|
||||
.remove = ide_floppy_remove,
|
||||
},
|
||||
.version = IDEFLOPPY_VERSION,
|
||||
.media = ide_floppy,
|
||||
.busy = 0,
|
||||
.supports_dsc_overlap = 0,
|
||||
.cleanup = idefloppy_cleanup,
|
||||
.do_request = idefloppy_do_request,
|
||||
.end_request = idefloppy_do_end_request,
|
||||
.error = __ide_error,
|
||||
.abort = __ide_abort,
|
||||
.proc = idefloppy_proc,
|
||||
.attach = idefloppy_attach,
|
||||
.drives = LIST_HEAD_INIT(idefloppy_driver.drives),
|
||||
};
|
||||
|
||||
static int idefloppy_open(struct inode *inode, struct file *filp)
|
||||
|
@ -2122,8 +2120,9 @@ static struct block_device_operations idefloppy_ops = {
|
|||
.revalidate_disk= idefloppy_revalidate_disk
|
||||
};
|
||||
|
||||
static int idefloppy_attach (ide_drive_t *drive)
|
||||
static int ide_floppy_probe(struct device *dev)
|
||||
{
|
||||
ide_drive_t *drive = to_ide_device(dev);
|
||||
idefloppy_floppy_t *floppy;
|
||||
struct gendisk *g;
|
||||
|
||||
|
@ -2152,10 +2151,7 @@ static int idefloppy_attach (ide_drive_t *drive)
|
|||
|
||||
ide_init_disk(g, drive);
|
||||
|
||||
if (ide_register_subdriver(drive, &idefloppy_driver)) {
|
||||
printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name);
|
||||
goto out_put_disk;
|
||||
}
|
||||
ide_register_subdriver(drive, &idefloppy_driver);
|
||||
|
||||
memset(floppy, 0, sizeof(*floppy));
|
||||
|
||||
|
@ -2169,9 +2165,8 @@ static int idefloppy_attach (ide_drive_t *drive)
|
|||
|
||||
drive->driver_data = floppy;
|
||||
|
||||
DRIVER(drive)->busy++;
|
||||
idefloppy_setup (drive, floppy);
|
||||
DRIVER(drive)->busy--;
|
||||
|
||||
g->minors = 1 << PARTN_BITS;
|
||||
g->driverfs_dev = &drive->gendev;
|
||||
strcpy(g->devfs_name, drive->devfs_name);
|
||||
|
@ -2181,19 +2176,17 @@ static int idefloppy_attach (ide_drive_t *drive)
|
|||
add_disk(g);
|
||||
return 0;
|
||||
|
||||
out_put_disk:
|
||||
put_disk(g);
|
||||
out_free_floppy:
|
||||
kfree(floppy);
|
||||
failed:
|
||||
return 1;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
|
||||
|
||||
static void __exit idefloppy_exit (void)
|
||||
{
|
||||
ide_unregister_driver(&idefloppy_driver);
|
||||
driver_unregister(&idefloppy_driver.gen_driver);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2202,8 +2195,7 @@ static void __exit idefloppy_exit (void)
|
|||
static int idefloppy_init (void)
|
||||
{
|
||||
printk("ide-floppy driver " IDEFLOPPY_VERSION "\n");
|
||||
ide_register_driver(&idefloppy_driver);
|
||||
return 0;
|
||||
return driver_register(&idefloppy_driver.gen_driver);
|
||||
}
|
||||
|
||||
module_init(idefloppy_init);
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ide.h>
|
||||
#include <linux/devfs_fs_kernel.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/pci.h>
|
||||
|
@ -696,13 +697,13 @@ static int wait_hwif_ready(ide_hwif_t *hwif)
|
|||
SELECT_DRIVE(&hwif->drives[0]);
|
||||
hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
|
||||
mdelay(2);
|
||||
rc = ide_wait_not_busy(hwif, 10000);
|
||||
rc = ide_wait_not_busy(hwif, 35000);
|
||||
if (rc)
|
||||
return rc;
|
||||
SELECT_DRIVE(&hwif->drives[1]);
|
||||
hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
|
||||
mdelay(2);
|
||||
rc = ide_wait_not_busy(hwif, 10000);
|
||||
rc = ide_wait_not_busy(hwif, 35000);
|
||||
|
||||
/* Exit function with master reselected (let's be sane) */
|
||||
SELECT_DRIVE(&hwif->drives[0]);
|
||||
|
@ -918,7 +919,7 @@ int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif)
|
|||
want them on default or a new "empty" class
|
||||
for hotplug reprobing ? */
|
||||
if (drive->present) {
|
||||
ata_attach(drive);
|
||||
device_register(&drive->gendev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1279,10 +1280,51 @@ void ide_init_disk(struct gendisk *disk, ide_drive_t *drive)
|
|||
|
||||
EXPORT_SYMBOL_GPL(ide_init_disk);
|
||||
|
||||
static void ide_remove_drive_from_hwgroup(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
|
||||
|
||||
if (drive == drive->next) {
|
||||
/* special case: last drive from hwgroup. */
|
||||
BUG_ON(hwgroup->drive != drive);
|
||||
hwgroup->drive = NULL;
|
||||
} else {
|
||||
ide_drive_t *walk;
|
||||
|
||||
walk = hwgroup->drive;
|
||||
while (walk->next != drive)
|
||||
walk = walk->next;
|
||||
walk->next = drive->next;
|
||||
if (hwgroup->drive == drive) {
|
||||
hwgroup->drive = drive->next;
|
||||
hwgroup->hwif = hwgroup->drive->hwif;
|
||||
}
|
||||
}
|
||||
BUG_ON(hwgroup->drive == drive);
|
||||
}
|
||||
|
||||
static void drive_release_dev (struct device *dev)
|
||||
{
|
||||
ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
|
||||
|
||||
spin_lock_irq(&ide_lock);
|
||||
if (drive->devfs_name[0] != '\0') {
|
||||
devfs_remove(drive->devfs_name);
|
||||
drive->devfs_name[0] = '\0';
|
||||
}
|
||||
ide_remove_drive_from_hwgroup(drive);
|
||||
if (drive->id != NULL) {
|
||||
kfree(drive->id);
|
||||
drive->id = NULL;
|
||||
}
|
||||
drive->present = 0;
|
||||
/* Messed up locking ... */
|
||||
spin_unlock_irq(&ide_lock);
|
||||
blk_cleanup_queue(drive->queue);
|
||||
spin_lock_irq(&ide_lock);
|
||||
drive->queue = NULL;
|
||||
spin_unlock_irq(&ide_lock);
|
||||
|
||||
up(&drive->gendev_rel_sem);
|
||||
}
|
||||
|
||||
|
@ -1306,7 +1348,6 @@ static void init_gendisk (ide_hwif_t *hwif)
|
|||
drive->gendev.driver_data = drive;
|
||||
drive->gendev.release = drive_release_dev;
|
||||
if (drive->present) {
|
||||
device_register(&drive->gendev);
|
||||
sprintf(drive->devfs_name, "ide/host%d/bus%d/target%d/lun%d",
|
||||
(hwif->channel && hwif->mate) ?
|
||||
hwif->mate->index : hwif->index,
|
||||
|
@ -1412,7 +1453,7 @@ int ideprobe_init (void)
|
|||
hwif->chipset = ide_generic;
|
||||
for (unit = 0; unit < MAX_DRIVES; ++unit)
|
||||
if (hwif->drives[unit].present)
|
||||
ata_attach(&hwif->drives[unit]);
|
||||
device_register(&hwif->drives[unit].gendev);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -307,17 +307,41 @@ static int proc_ide_read_driver
|
|||
(char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||
{
|
||||
ide_drive_t *drive = (ide_drive_t *) data;
|
||||
ide_driver_t *driver = drive->driver;
|
||||
struct device *dev = &drive->gendev;
|
||||
ide_driver_t *ide_drv;
|
||||
int len;
|
||||
|
||||
if (driver) {
|
||||
down_read(&dev->bus->subsys.rwsem);
|
||||
if (dev->driver) {
|
||||
ide_drv = container_of(dev->driver, ide_driver_t, gen_driver);
|
||||
len = sprintf(page, "%s version %s\n",
|
||||
driver->name, driver->version);
|
||||
dev->driver->name, ide_drv->version);
|
||||
} else
|
||||
len = sprintf(page, "ide-default version 0.9.newide\n");
|
||||
up_read(&dev->bus->subsys.rwsem);
|
||||
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
|
||||
}
|
||||
|
||||
static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
|
||||
{
|
||||
struct device *dev = &drive->gendev;
|
||||
int ret = 1;
|
||||
|
||||
down_write(&dev->bus->subsys.rwsem);
|
||||
device_release_driver(dev);
|
||||
/* FIXME: device can still be in use by previous driver */
|
||||
strlcpy(drive->driver_req, driver, sizeof(drive->driver_req));
|
||||
device_attach(dev);
|
||||
drive->driver_req[0] = 0;
|
||||
if (dev->driver == NULL)
|
||||
device_attach(dev);
|
||||
if (dev->driver && !strcmp(dev->driver->name, driver))
|
||||
ret = 0;
|
||||
up_write(&dev->bus->subsys.rwsem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int proc_ide_write_driver
|
||||
(struct file *file, const char __user *buffer, unsigned long count, void *data)
|
||||
{
|
||||
|
@ -488,16 +512,32 @@ void destroy_proc_ide_interface(ide_hwif_t *hwif)
|
|||
}
|
||||
}
|
||||
|
||||
extern struct seq_operations ide_drivers_op;
|
||||
static int proc_print_driver(struct device_driver *drv, void *data)
|
||||
{
|
||||
ide_driver_t *ide_drv = container_of(drv, ide_driver_t, gen_driver);
|
||||
struct seq_file *s = data;
|
||||
|
||||
seq_printf(s, "%s version %s\n", drv->name, ide_drv->version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ide_drivers_show(struct seq_file *s, void *p)
|
||||
{
|
||||
bus_for_each_drv(&ide_bus_type, NULL, s, proc_print_driver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ide_drivers_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &ide_drivers_op);
|
||||
return single_open(file, &ide_drivers_show, NULL);
|
||||
}
|
||||
|
||||
static struct file_operations ide_drivers_operations = {
|
||||
.open = ide_drivers_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
void proc_ide_create(void)
|
||||
|
|
|
@ -4681,21 +4681,12 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
|
|||
idetape_add_settings(drive);
|
||||
}
|
||||
|
||||
static int idetape_cleanup (ide_drive_t *drive)
|
||||
static int ide_tape_remove(struct device *dev)
|
||||
{
|
||||
ide_drive_t *drive = to_ide_device(dev);
|
||||
idetape_tape_t *tape = drive->driver_data;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
if (test_bit(IDETAPE_BUSY, &tape->flags) || drive->usage ||
|
||||
tape->first_stage != NULL || tape->merge_stage_size) {
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
DRIVER(drive)->busy = 0;
|
||||
(void) ide_unregister_subdriver(drive);
|
||||
ide_unregister_subdriver(drive, tape->driver);
|
||||
|
||||
ide_unregister_region(tape->disk);
|
||||
|
||||
|
@ -4710,6 +4701,8 @@ static void ide_tape_release(struct kref *kref)
|
|||
ide_drive_t *drive = tape->drive;
|
||||
struct gendisk *g = tape->disk;
|
||||
|
||||
BUG_ON(tape->first_stage != NULL || tape->merge_stage_size);
|
||||
|
||||
drive->dsc_overlap = 0;
|
||||
drive->driver_data = NULL;
|
||||
devfs_remove("%s/mt", drive->devfs_name);
|
||||
|
@ -4747,26 +4740,24 @@ static ide_proc_entry_t idetape_proc[] = {
|
|||
|
||||
#endif
|
||||
|
||||
static int idetape_attach(ide_drive_t *drive);
|
||||
static int ide_tape_probe(struct device *);
|
||||
|
||||
/*
|
||||
* IDE subdriver functions, registered with ide.c
|
||||
*/
|
||||
static ide_driver_t idetape_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "ide-tape",
|
||||
.gen_driver = {
|
||||
.name = "ide-tape",
|
||||
.bus = &ide_bus_type,
|
||||
.probe = ide_tape_probe,
|
||||
.remove = ide_tape_remove,
|
||||
},
|
||||
.version = IDETAPE_VERSION,
|
||||
.media = ide_tape,
|
||||
.busy = 1,
|
||||
.supports_dsc_overlap = 1,
|
||||
.cleanup = idetape_cleanup,
|
||||
.do_request = idetape_do_request,
|
||||
.end_request = idetape_end_request,
|
||||
.error = __ide_error,
|
||||
.abort = __ide_abort,
|
||||
.proc = idetape_proc,
|
||||
.attach = idetape_attach,
|
||||
.drives = LIST_HEAD_INIT(idetape_driver.drives),
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -4829,8 +4820,9 @@ static struct block_device_operations idetape_block_ops = {
|
|||
.ioctl = idetape_ioctl,
|
||||
};
|
||||
|
||||
static int idetape_attach (ide_drive_t *drive)
|
||||
static int ide_tape_probe(struct device *dev)
|
||||
{
|
||||
ide_drive_t *drive = to_ide_device(dev);
|
||||
idetape_tape_t *tape;
|
||||
struct gendisk *g;
|
||||
int minor;
|
||||
|
@ -4865,10 +4857,7 @@ static int idetape_attach (ide_drive_t *drive)
|
|||
|
||||
ide_init_disk(g, drive);
|
||||
|
||||
if (ide_register_subdriver(drive, &idetape_driver)) {
|
||||
printk(KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name);
|
||||
goto out_put_disk;
|
||||
}
|
||||
ide_register_subdriver(drive, &idetape_driver);
|
||||
|
||||
memset(tape, 0, sizeof(*tape));
|
||||
|
||||
|
@ -4902,12 +4891,11 @@ static int idetape_attach (ide_drive_t *drive)
|
|||
ide_register_region(g);
|
||||
|
||||
return 0;
|
||||
out_put_disk:
|
||||
put_disk(g);
|
||||
|
||||
out_free_tape:
|
||||
kfree(tape);
|
||||
failed:
|
||||
return 1;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
|
||||
|
@ -4915,7 +4903,7 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
static void __exit idetape_exit (void)
|
||||
{
|
||||
ide_unregister_driver(&idetape_driver);
|
||||
driver_unregister(&idetape_driver.gen_driver);
|
||||
unregister_chrdev(IDETAPE_MAJOR, "ht");
|
||||
}
|
||||
|
||||
|
@ -4928,8 +4916,7 @@ static int idetape_init (void)
|
|||
printk(KERN_ERR "ide-tape: Failed to register character device interface\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
ide_register_driver(&idetape_driver);
|
||||
return 0;
|
||||
return driver_register(&idetape_driver.gen_driver);
|
||||
}
|
||||
|
||||
module_init(idetape_init);
|
||||
|
|
|
@ -196,8 +196,6 @@ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
|
|||
|
||||
EXPORT_SYMBOL(ide_hwifs);
|
||||
|
||||
static struct list_head ide_drives = LIST_HEAD_INIT(ide_drives);
|
||||
|
||||
/*
|
||||
* Do not even *think* about calling this!
|
||||
*/
|
||||
|
@ -358,54 +356,6 @@ static int ide_system_bus_speed(void)
|
|||
return system_bus_speed;
|
||||
}
|
||||
|
||||
/*
|
||||
* drives_lock protects the list of drives, drivers_lock the
|
||||
* list of drivers. Currently nobody takes both at once.
|
||||
*/
|
||||
|
||||
static DEFINE_SPINLOCK(drives_lock);
|
||||
static DEFINE_SPINLOCK(drivers_lock);
|
||||
static LIST_HEAD(drivers);
|
||||
|
||||
/* Iterator for the driver list. */
|
||||
|
||||
static void *m_start(struct seq_file *m, loff_t *pos)
|
||||
{
|
||||
struct list_head *p;
|
||||
loff_t l = *pos;
|
||||
spin_lock(&drivers_lock);
|
||||
list_for_each(p, &drivers)
|
||||
if (!l--)
|
||||
return list_entry(p, ide_driver_t, drivers);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *m_next(struct seq_file *m, void *v, loff_t *pos)
|
||||
{
|
||||
struct list_head *p = ((ide_driver_t *)v)->drivers.next;
|
||||
(*pos)++;
|
||||
return p==&drivers ? NULL : list_entry(p, ide_driver_t, drivers);
|
||||
}
|
||||
|
||||
static void m_stop(struct seq_file *m, void *v)
|
||||
{
|
||||
spin_unlock(&drivers_lock);
|
||||
}
|
||||
|
||||
static int show_driver(struct seq_file *m, void *v)
|
||||
{
|
||||
ide_driver_t *driver = v;
|
||||
seq_printf(m, "%s version %s\n", driver->name, driver->version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct seq_operations ide_drivers_op = {
|
||||
.start = m_start,
|
||||
.next = m_next,
|
||||
.stop = m_stop,
|
||||
.show = show_driver
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry *proc_ide_root;
|
||||
#endif
|
||||
|
@ -630,7 +580,7 @@ void ide_unregister(unsigned int index)
|
|||
ide_hwif_t *hwif, *g;
|
||||
static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */
|
||||
ide_hwgroup_t *hwgroup;
|
||||
int irq_count = 0, unit, i;
|
||||
int irq_count = 0, unit;
|
||||
|
||||
BUG_ON(index >= MAX_HWIFS);
|
||||
|
||||
|
@ -643,23 +593,22 @@ void ide_unregister(unsigned int index)
|
|||
goto abort;
|
||||
for (unit = 0; unit < MAX_DRIVES; ++unit) {
|
||||
drive = &hwif->drives[unit];
|
||||
if (!drive->present)
|
||||
if (!drive->present) {
|
||||
if (drive->devfs_name[0] != '\0') {
|
||||
devfs_remove(drive->devfs_name);
|
||||
drive->devfs_name[0] = '\0';
|
||||
}
|
||||
continue;
|
||||
if (drive->usage || DRIVER(drive)->busy)
|
||||
goto abort;
|
||||
drive->dead = 1;
|
||||
}
|
||||
spin_unlock_irq(&ide_lock);
|
||||
device_unregister(&drive->gendev);
|
||||
down(&drive->gendev_rel_sem);
|
||||
spin_lock_irq(&ide_lock);
|
||||
}
|
||||
hwif->present = 0;
|
||||
|
||||
spin_unlock_irq(&ide_lock);
|
||||
|
||||
for (unit = 0; unit < MAX_DRIVES; ++unit) {
|
||||
drive = &hwif->drives[unit];
|
||||
if (!drive->present)
|
||||
continue;
|
||||
DRIVER(drive)->cleanup(drive);
|
||||
}
|
||||
|
||||
destroy_proc_ide_interface(hwif);
|
||||
|
||||
hwgroup = hwif->hwgroup;
|
||||
|
@ -687,44 +636,6 @@ void ide_unregister(unsigned int index)
|
|||
* Remove us from the hwgroup, and free
|
||||
* the hwgroup if we were the only member
|
||||
*/
|
||||
for (i = 0; i < MAX_DRIVES; ++i) {
|
||||
drive = &hwif->drives[i];
|
||||
if (drive->devfs_name[0] != '\0') {
|
||||
devfs_remove(drive->devfs_name);
|
||||
drive->devfs_name[0] = '\0';
|
||||
}
|
||||
if (!drive->present)
|
||||
continue;
|
||||
if (drive == drive->next) {
|
||||
/* special case: last drive from hwgroup. */
|
||||
BUG_ON(hwgroup->drive != drive);
|
||||
hwgroup->drive = NULL;
|
||||
} else {
|
||||
ide_drive_t *walk;
|
||||
|
||||
walk = hwgroup->drive;
|
||||
while (walk->next != drive)
|
||||
walk = walk->next;
|
||||
walk->next = drive->next;
|
||||
if (hwgroup->drive == drive) {
|
||||
hwgroup->drive = drive->next;
|
||||
hwgroup->hwif = HWIF(hwgroup->drive);
|
||||
}
|
||||
}
|
||||
BUG_ON(hwgroup->drive == drive);
|
||||
if (drive->id != NULL) {
|
||||
kfree(drive->id);
|
||||
drive->id = NULL;
|
||||
}
|
||||
drive->present = 0;
|
||||
/* Messed up locking ... */
|
||||
spin_unlock_irq(&ide_lock);
|
||||
blk_cleanup_queue(drive->queue);
|
||||
device_unregister(&drive->gendev);
|
||||
down(&drive->gendev_rel_sem);
|
||||
spin_lock_irq(&ide_lock);
|
||||
drive->queue = NULL;
|
||||
}
|
||||
if (hwif->next == hwif) {
|
||||
BUG_ON(hwgroup->hwif != hwif);
|
||||
kfree(hwgroup);
|
||||
|
@ -1304,73 +1215,6 @@ int system_bus_clock (void)
|
|||
|
||||
EXPORT_SYMBOL(system_bus_clock);
|
||||
|
||||
/*
|
||||
* Locking is badly broken here - since way back. That sucker is
|
||||
* root-only, but that's not an excuse... The real question is what
|
||||
* exclusion rules do we want here.
|
||||
*/
|
||||
int ide_replace_subdriver (ide_drive_t *drive, const char *driver)
|
||||
{
|
||||
if (!drive->present || drive->usage || drive->dead)
|
||||
goto abort;
|
||||
if (DRIVER(drive)->cleanup(drive))
|
||||
goto abort;
|
||||
strlcpy(drive->driver_req, driver, sizeof(drive->driver_req));
|
||||
if (ata_attach(drive)) {
|
||||
spin_lock(&drives_lock);
|
||||
list_del_init(&drive->list);
|
||||
spin_unlock(&drives_lock);
|
||||
drive->driver_req[0] = 0;
|
||||
ata_attach(drive);
|
||||
} else {
|
||||
drive->driver_req[0] = 0;
|
||||
}
|
||||
if (drive->driver && !strcmp(drive->driver->name, driver))
|
||||
return 0;
|
||||
abort:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_attach - attach an ATA/ATAPI device
|
||||
* @drive: drive to attach
|
||||
*
|
||||
* Takes a drive that is as yet not assigned to any midlayer IDE
|
||||
* driver (or is assigned to the default driver) and figures out
|
||||
* which driver would like to own it. If nobody claims the drive
|
||||
* then it is automatically attached to the default driver used for
|
||||
* unclaimed objects.
|
||||
*
|
||||
* A return of zero indicates attachment to a driver, of one
|
||||
* attachment to the default driver.
|
||||
*
|
||||
* Takes drivers_lock.
|
||||
*/
|
||||
|
||||
int ata_attach(ide_drive_t *drive)
|
||||
{
|
||||
struct list_head *p;
|
||||
spin_lock(&drivers_lock);
|
||||
list_for_each(p, &drivers) {
|
||||
ide_driver_t *driver = list_entry(p, ide_driver_t, drivers);
|
||||
if (!try_module_get(driver->owner))
|
||||
continue;
|
||||
spin_unlock(&drivers_lock);
|
||||
if (driver->attach(drive) == 0) {
|
||||
module_put(driver->owner);
|
||||
drive->gendev.driver = &driver->gen_driver;
|
||||
return 0;
|
||||
}
|
||||
spin_lock(&drivers_lock);
|
||||
module_put(driver->owner);
|
||||
}
|
||||
drive->gendev.driver = NULL;
|
||||
spin_unlock(&drivers_lock);
|
||||
if (ide_register_subdriver(drive, NULL))
|
||||
panic("ide: default attach failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int generic_ide_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
ide_drive_t *drive = dev->driver_data;
|
||||
|
@ -2013,27 +1857,11 @@ static void __init probe_for_hwifs (void)
|
|||
#endif
|
||||
}
|
||||
|
||||
int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
|
||||
void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
if (!drive->present || drive->driver != NULL ||
|
||||
drive->usage || drive->dead) {
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
return 1;
|
||||
}
|
||||
drive->driver = driver;
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
spin_lock(&drives_lock);
|
||||
list_add_tail(&drive->list, driver ? &driver->drives : &ide_drives);
|
||||
spin_unlock(&drives_lock);
|
||||
// printk(KERN_INFO "%s: attached %s driver.\n", drive->name, driver->name);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (driver)
|
||||
ide_add_proc_entries(drive->proc, driver->proc, drive);
|
||||
ide_add_proc_entries(drive->proc, driver->proc, drive);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_register_subdriver);
|
||||
|
@ -2041,136 +1869,51 @@ EXPORT_SYMBOL(ide_register_subdriver);
|
|||
/**
|
||||
* ide_unregister_subdriver - disconnect drive from driver
|
||||
* @drive: drive to unplug
|
||||
* @driver: driver
|
||||
*
|
||||
* Disconnect a drive from the driver it was attached to and then
|
||||
* clean up the various proc files and other objects attached to it.
|
||||
*
|
||||
* Takes ide_setting_sem, ide_lock and drives_lock.
|
||||
* Takes ide_setting_sem and ide_lock.
|
||||
* Caller must hold none of the locks.
|
||||
*
|
||||
* No locking versus subdriver unload because we are moving to the
|
||||
* default driver anyway. Wants double checking.
|
||||
*/
|
||||
|
||||
int ide_unregister_subdriver (ide_drive_t *drive)
|
||||
void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
down(&ide_setting_sem);
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) {
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
up(&ide_setting_sem);
|
||||
return 1;
|
||||
}
|
||||
#ifdef CONFIG_PROC_FS
|
||||
ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc);
|
||||
ide_remove_proc_entries(drive->proc, driver->proc);
|
||||
#endif
|
||||
auto_remove_settings(drive);
|
||||
drive->driver = NULL;
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
up(&ide_setting_sem);
|
||||
spin_lock(&drives_lock);
|
||||
list_del_init(&drive->list);
|
||||
spin_unlock(&drives_lock);
|
||||
/* drive will be added to &ide_drives in ata_attach() */
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_unregister_subdriver);
|
||||
|
||||
static int ide_drive_remove(struct device * dev)
|
||||
{
|
||||
ide_drive_t * drive = container_of(dev,ide_drive_t,gendev);
|
||||
DRIVER(drive)->cleanup(drive);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_register_driver - register IDE device driver
|
||||
* @driver: the IDE device driver
|
||||
*
|
||||
* Register a new device driver and then scan the devices
|
||||
* on the IDE bus in case any should be attached to the
|
||||
* driver we have just registered. If so attach them.
|
||||
*
|
||||
* Takes drivers_lock and drives_lock.
|
||||
*/
|
||||
|
||||
int ide_register_driver(ide_driver_t *driver)
|
||||
{
|
||||
struct list_head list;
|
||||
struct list_head *list_loop;
|
||||
struct list_head *tmp_storage;
|
||||
|
||||
spin_lock(&drivers_lock);
|
||||
list_add(&driver->drivers, &drivers);
|
||||
spin_unlock(&drivers_lock);
|
||||
|
||||
INIT_LIST_HEAD(&list);
|
||||
spin_lock(&drives_lock);
|
||||
list_splice_init(&ide_drives, &list);
|
||||
spin_unlock(&drives_lock);
|
||||
|
||||
list_for_each_safe(list_loop, tmp_storage, &list) {
|
||||
ide_drive_t *drive = container_of(list_loop, ide_drive_t, list);
|
||||
list_del_init(&drive->list);
|
||||
if (drive->present)
|
||||
ata_attach(drive);
|
||||
}
|
||||
driver->gen_driver.name = (char *) driver->name;
|
||||
driver->gen_driver.bus = &ide_bus_type;
|
||||
driver->gen_driver.remove = ide_drive_remove;
|
||||
return driver_register(&driver->gen_driver);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_register_driver);
|
||||
|
||||
/**
|
||||
* ide_unregister_driver - unregister IDE device driver
|
||||
* @driver: the IDE device driver
|
||||
*
|
||||
* Called when a driver module is being unloaded. We reattach any
|
||||
* devices to whatever driver claims them next (typically the default
|
||||
* driver).
|
||||
*
|
||||
* Takes drivers_lock and called functions will take ide_setting_sem.
|
||||
*/
|
||||
|
||||
void ide_unregister_driver(ide_driver_t *driver)
|
||||
{
|
||||
ide_drive_t *drive;
|
||||
|
||||
spin_lock(&drivers_lock);
|
||||
list_del(&driver->drivers);
|
||||
spin_unlock(&drivers_lock);
|
||||
|
||||
driver_unregister(&driver->gen_driver);
|
||||
|
||||
while(!list_empty(&driver->drives)) {
|
||||
drive = list_entry(driver->drives.next, ide_drive_t, list);
|
||||
if (driver->cleanup(drive)) {
|
||||
printk(KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);
|
||||
BUG();
|
||||
}
|
||||
ata_attach(drive);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_unregister_driver);
|
||||
|
||||
/*
|
||||
* Probe module
|
||||
*/
|
||||
|
||||
EXPORT_SYMBOL(ide_lock);
|
||||
|
||||
static int ide_bus_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct bus_type ide_bus_type = {
|
||||
.name = "ide",
|
||||
.match = ide_bus_match,
|
||||
.suspend = generic_ide_suspend,
|
||||
.resume = generic_ide_resume,
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_bus_type);
|
||||
|
||||
/*
|
||||
* This is gets invoked once during initialization, to set *everything* up
|
||||
*/
|
||||
|
|
|
@ -68,23 +68,3 @@ config GAMEPORT_CS461X
|
|||
depends on PCI
|
||||
|
||||
endif
|
||||
|
||||
# Yes, SOUND_GAMEPORT looks a bit odd. Yes, it ends up being turned on
|
||||
# in every .config. Please don't touch it. It is here to handle an
|
||||
# unusual dependency between GAMEPORT and sound drivers.
|
||||
#
|
||||
# Some sound drivers call gameport functions. If GAMEPORT is
|
||||
# not selected, empty stubs are provided for the functions and all is
|
||||
# well.
|
||||
# If GAMEPORT is built in, everything is fine.
|
||||
# If GAMEPORT is a module, however, it would need to be loaded for the
|
||||
# sound driver to be able to link properly. Therefore, the sound
|
||||
# driver must be a module as well in that case. Since there's no way
|
||||
# to express that directly in Kconfig, we use SOUND_GAMEPORT to
|
||||
# express it. SOUND_GAMEPORT boils down to "if GAMEPORT is 'm',
|
||||
# anything that depends on SOUND_GAMEPORT must be 'm' as well. if
|
||||
# GAMEPORT is 'y' or 'n', it can be anything".
|
||||
config SOUND_GAMEPORT
|
||||
tristate
|
||||
default m if GAMEPORT=m
|
||||
default y
|
||||
|
|
|
@ -422,7 +422,7 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
|
|||
joydev->nkey++;
|
||||
}
|
||||
|
||||
for (i = 0; i < BTN_JOYSTICK - BTN_MISC + 1; i++)
|
||||
for (i = 0; i < BTN_JOYSTICK - BTN_MISC; i++)
|
||||
if (test_bit(i + BTN_MISC, dev->keybit)) {
|
||||
joydev->keymap[i] = joydev->nkey;
|
||||
joydev->keypam[joydev->nkey] = i + BTN_MISC;
|
||||
|
|
|
@ -171,9 +171,9 @@ static struct {
|
|||
unsigned char set2;
|
||||
} atkbd_scroll_keys[] = {
|
||||
{ ATKBD_SCR_1, 0xc5 },
|
||||
{ ATKBD_SCR_2, 0xa9 },
|
||||
{ ATKBD_SCR_4, 0xb6 },
|
||||
{ ATKBD_SCR_8, 0xa7 },
|
||||
{ ATKBD_SCR_2, 0x9d },
|
||||
{ ATKBD_SCR_4, 0xa4 },
|
||||
{ ATKBD_SCR_8, 0x9b },
|
||||
{ ATKBD_SCR_CLICK, 0xe0 },
|
||||
{ ATKBD_SCR_LEFT, 0xcb },
|
||||
{ ATKBD_SCR_RIGHT, 0xd2 },
|
||||
|
|
|
@ -518,13 +518,16 @@ static int psmouse_probe(struct psmouse *psmouse)
|
|||
/*
|
||||
* First, we check if it's a mouse. It should send 0x00 or 0x03
|
||||
* in case of an IntelliMouse in 4-byte mode or 0x04 for IM Explorer.
|
||||
* Sunrex K8561 IR Keyboard/Mouse reports 0xff on second and subsequent
|
||||
* ID queries, probably due to a firmware bug.
|
||||
*/
|
||||
|
||||
param[0] = 0xa5;
|
||||
if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETID))
|
||||
return -1;
|
||||
|
||||
if (param[0] != 0x00 && param[0] != 0x03 && param[0] != 0x04)
|
||||
if (param[0] != 0x00 && param[0] != 0x03 &&
|
||||
param[0] != 0x04 && param[0] != 0xff)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
|
@ -972,7 +975,7 @@ static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
|
|||
return -EINVAL;
|
||||
|
||||
if (!strncmp(val, "any", 3)) {
|
||||
*((unsigned int *)kp->arg) = -1UL;
|
||||
*((unsigned int *)kp->arg) = -1U;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,39 +143,6 @@ static int synaptics_identify(struct psmouse *psmouse)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void print_ident(struct synaptics_data *priv)
|
||||
{
|
||||
printk(KERN_INFO "Synaptics Touchpad, model: %ld\n", SYN_ID_MODEL(priv->identity));
|
||||
printk(KERN_INFO " Firmware: %ld.%ld\n", SYN_ID_MAJOR(priv->identity),
|
||||
SYN_ID_MINOR(priv->identity));
|
||||
if (SYN_MODEL_ROT180(priv->model_id))
|
||||
printk(KERN_INFO " 180 degree mounted touchpad\n");
|
||||
if (SYN_MODEL_PORTRAIT(priv->model_id))
|
||||
printk(KERN_INFO " portrait touchpad\n");
|
||||
printk(KERN_INFO " Sensor: %ld\n", SYN_MODEL_SENSOR(priv->model_id));
|
||||
if (SYN_MODEL_NEWABS(priv->model_id))
|
||||
printk(KERN_INFO " new absolute packet format\n");
|
||||
if (SYN_MODEL_PEN(priv->model_id))
|
||||
printk(KERN_INFO " pen detection\n");
|
||||
|
||||
if (SYN_CAP_EXTENDED(priv->capabilities)) {
|
||||
printk(KERN_INFO " Touchpad has extended capability bits\n");
|
||||
if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
|
||||
printk(KERN_INFO " -> %d multi-buttons, i.e. besides standard buttons\n",
|
||||
(int)(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)));
|
||||
if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
|
||||
printk(KERN_INFO " -> middle button\n");
|
||||
if (SYN_CAP_FOUR_BUTTON(priv->capabilities))
|
||||
printk(KERN_INFO " -> four buttons\n");
|
||||
if (SYN_CAP_MULTIFINGER(priv->capabilities))
|
||||
printk(KERN_INFO " -> multifinger detection\n");
|
||||
if (SYN_CAP_PALMDETECT(priv->capabilities))
|
||||
printk(KERN_INFO " -> palm detection\n");
|
||||
if (SYN_CAP_PASS_THROUGH(priv->capabilities))
|
||||
printk(KERN_INFO " -> pass-through port\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int synaptics_query_hardware(struct psmouse *psmouse)
|
||||
{
|
||||
int retries = 0;
|
||||
|
@ -666,7 +633,11 @@ int synaptics_init(struct psmouse *psmouse)
|
|||
|
||||
priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
|
||||
|
||||
print_ident(priv);
|
||||
printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx\n",
|
||||
SYN_ID_MODEL(priv->identity),
|
||||
SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
|
||||
priv->model_id, priv->capabilities, priv->ext_cap);
|
||||
|
||||
set_input_params(&psmouse->dev, priv);
|
||||
|
||||
psmouse->protocol_handler = synaptics_process_byte;
|
||||
|
|
|
@ -101,6 +101,7 @@ struct mousedev_list {
|
|||
unsigned char ready, buffer, bufsiz;
|
||||
unsigned char imexseq, impsseq;
|
||||
enum mousedev_emul mode;
|
||||
unsigned long last_buttons;
|
||||
};
|
||||
|
||||
#define MOUSEDEV_SEQ_LEN 6
|
||||
|
@ -224,7 +225,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h
|
|||
spin_lock_irqsave(&list->packet_lock, flags);
|
||||
|
||||
p = &list->packets[list->head];
|
||||
if (list->ready && p->buttons != packet->buttons) {
|
||||
if (list->ready && p->buttons != mousedev->packet.buttons) {
|
||||
unsigned int new_head = (list->head + 1) % PACKET_QUEUE_LEN;
|
||||
if (new_head != list->tail) {
|
||||
p = &list->packets[list->head = new_head];
|
||||
|
@ -249,10 +250,13 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h
|
|||
p->dz += packet->dz;
|
||||
p->buttons = mousedev->packet.buttons;
|
||||
|
||||
list->ready = 1;
|
||||
if (p->dx || p->dy || p->dz || p->buttons != list->last_buttons)
|
||||
list->ready = 1;
|
||||
|
||||
spin_unlock_irqrestore(&list->packet_lock, flags);
|
||||
kill_fasync(&list->fasync, SIGIO, POLL_IN);
|
||||
|
||||
if (list->ready)
|
||||
kill_fasync(&list->fasync, SIGIO, POLL_IN);
|
||||
}
|
||||
|
||||
wake_up_interruptible(&mousedev->wait);
|
||||
|
@ -477,9 +481,10 @@ static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data)
|
|||
}
|
||||
|
||||
if (!p->dx && !p->dy && !p->dz) {
|
||||
if (list->tail == list->head)
|
||||
if (list->tail == list->head) {
|
||||
list->ready = 0;
|
||||
else
|
||||
list->last_buttons = p->buttons;
|
||||
} else
|
||||
list->tail = (list->tail + 1) % PACKET_QUEUE_LEN;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,9 +88,11 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
|
|||
};
|
||||
|
||||
/*
|
||||
* Some Fujitsu notebooks are ahving trouble with touhcpads if
|
||||
* Some Fujitsu notebooks are having trouble with touchpads if
|
||||
* active multiplexing mode is activated. Luckily they don't have
|
||||
* external PS/2 ports so we can safely disable it.
|
||||
* ... apparently some Toshibas don't like MUX mode either and
|
||||
* die horrible death on reboot.
|
||||
*/
|
||||
static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
|
||||
{
|
||||
|
@ -114,6 +116,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Fujitsu Lifebook S6230",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Fujitsu T70H",
|
||||
.matches = {
|
||||
|
@ -121,6 +130,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Toshiba P10",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -215,11 +231,15 @@ static struct pnp_driver i8042_pnp_aux_driver = {
|
|||
|
||||
static void i8042_pnp_exit(void)
|
||||
{
|
||||
if (i8042_pnp_kbd_registered)
|
||||
if (i8042_pnp_kbd_registered) {
|
||||
i8042_pnp_kbd_registered = 0;
|
||||
pnp_unregister_driver(&i8042_pnp_kbd_driver);
|
||||
}
|
||||
|
||||
if (i8042_pnp_aux_registered)
|
||||
if (i8042_pnp_aux_registered) {
|
||||
i8042_pnp_aux_registered = 0;
|
||||
pnp_unregister_driver(&i8042_pnp_aux_driver);
|
||||
}
|
||||
}
|
||||
|
||||
static int i8042_pnp_init(void)
|
||||
|
@ -227,7 +247,7 @@ static int i8042_pnp_init(void)
|
|||
int result_kbd, result_aux;
|
||||
|
||||
if (i8042_nopnp) {
|
||||
printk("i8042: PNP detection disabled\n");
|
||||
printk(KERN_INFO "i8042: PNP detection disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -241,7 +261,7 @@ static int i8042_pnp_init(void)
|
|||
#if defined(__ia64__)
|
||||
return -ENODEV;
|
||||
#else
|
||||
printk(KERN_WARNING "PNP: No PS/2 controller found. Probing ports directly.\n");
|
||||
printk(KERN_INFO "PNP: No PS/2 controller found. Probing ports directly.\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
@ -265,7 +285,7 @@ static int i8042_pnp_init(void)
|
|||
i8042_pnp_kbd_irq = i8042_kbd_irq;
|
||||
}
|
||||
|
||||
if (result_aux > 0 && !i8042_pnp_aux_irq) {
|
||||
if (!i8042_pnp_aux_irq) {
|
||||
printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %#x\n", i8042_aux_irq);
|
||||
i8042_pnp_aux_irq = i8042_aux_irq;
|
||||
}
|
||||
|
|
|
@ -698,6 +698,26 @@ static void i8042_timer_func(unsigned long data)
|
|||
i8042_interrupt(0, NULL, NULL);
|
||||
}
|
||||
|
||||
static int i8042_ctl_test(void)
|
||||
{
|
||||
unsigned char param;
|
||||
|
||||
if (!i8042_reset)
|
||||
return 0;
|
||||
|
||||
if (i8042_command(¶m, I8042_CMD_CTL_TEST)) {
|
||||
printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (param != I8042_RET_CTL_TEST) {
|
||||
printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
|
||||
param, I8042_RET_CTL_TEST);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* i8042_controller init initializes the i8042 controller, and,
|
||||
|
@ -719,21 +739,8 @@ static int i8042_controller_init(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (i8042_reset) {
|
||||
|
||||
unsigned char param;
|
||||
|
||||
if (i8042_command(¶m, I8042_CMD_CTL_TEST)) {
|
||||
printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (param != I8042_RET_CTL_TEST) {
|
||||
printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
|
||||
param, I8042_RET_CTL_TEST);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (i8042_ctl_test())
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Save the CTR for restoral on unload / reboot.
|
||||
|
@ -802,15 +809,11 @@ static int i8042_controller_init(void)
|
|||
*/
|
||||
static void i8042_controller_reset(void)
|
||||
{
|
||||
unsigned char param;
|
||||
|
||||
/*
|
||||
* Reset the controller if requested.
|
||||
*/
|
||||
|
||||
if (i8042_reset)
|
||||
if (i8042_command(¶m, I8042_CMD_CTL_TEST))
|
||||
printk(KERN_ERR "i8042.c: i8042 controller reset timeout.\n");
|
||||
i8042_ctl_test();
|
||||
|
||||
/*
|
||||
* Disable MUX mode if present.
|
||||
|
@ -922,8 +925,11 @@ static int i8042_resume(struct device *dev, u32 level)
|
|||
if (level != RESUME_ENABLE)
|
||||
return 0;
|
||||
|
||||
if (i8042_controller_init()) {
|
||||
printk(KERN_ERR "i8042: resume failed\n");
|
||||
if (i8042_ctl_test())
|
||||
return -1;
|
||||
|
||||
if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
|
||||
printk(KERN_ERR "i8042: Can't write CTR\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,8 +68,7 @@ static void gunze_process_packet(struct gunze* gunze, struct pt_regs *regs)
|
|||
|
||||
if (gunze->idx != GUNZE_MAX_LENGTH || gunze->data[5] != ',' ||
|
||||
(gunze->data[0] != 'T' && gunze->data[0] != 'R')) {
|
||||
gunze->data[10] = 0;
|
||||
printk(KERN_WARNING "gunze.c: bad packet: >%s<\n", gunze->data);
|
||||
printk(KERN_WARNING "gunze.c: bad packet: >%.*s<\n", GUNZE_MAX_LENGTH, gunze->data);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -2421,7 +2421,7 @@ pmac_wakeup_devices(void)
|
|||
|
||||
/* Re-enable local CPU interrupts */
|
||||
local_irq_enable();
|
||||
mdelay(100);
|
||||
mdelay(10);
|
||||
preempt_enable();
|
||||
|
||||
/* Re-enable clock spreading on some machines */
|
||||
|
@ -2549,7 +2549,9 @@ powerbook_sleep_Core99(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
|
||||
/* Stop environment and ADB interrupts */
|
||||
pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
|
||||
pmu_wait_complete(&req);
|
||||
|
||||
/* Tell PMU what events will wake us up */
|
||||
pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS,
|
||||
|
@ -2611,8 +2613,6 @@ powerbook_sleep_Core99(void)
|
|||
pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
|
||||
pmu_wait_complete(&req);
|
||||
|
||||
printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
|
||||
|
||||
pmac_wakeup_devices();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -906,22 +906,12 @@ static int dst_tone_power_cmd(struct dst_state* state)
|
|||
if (state->dst_type == DST_TYPE_IS_TERR)
|
||||
return 0;
|
||||
|
||||
if (state->voltage == SEC_VOLTAGE_OFF)
|
||||
paket[4] = 0;
|
||||
else
|
||||
paket[4] = 1;
|
||||
|
||||
if (state->tone == SEC_TONE_ON)
|
||||
paket[2] = 0x02;
|
||||
else
|
||||
paket[2] = 0;
|
||||
if (state->minicmd == SEC_MINI_A)
|
||||
paket[3] = 0x02;
|
||||
else
|
||||
paket[3] = 0;
|
||||
|
||||
paket[4] = state->tx_tuna[4];
|
||||
paket[2] = state->tx_tuna[2];
|
||||
paket[3] = state->tx_tuna[3];
|
||||
paket[7] = dst_check_sum (paket, 7);
|
||||
dst_command(state, paket, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -980,7 +970,7 @@ static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
|
|||
|
||||
static int dst_write_tuna(struct dvb_frontend* fe)
|
||||
{
|
||||
struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
|
||||
struct dst_state* state = fe->demodulator_priv;
|
||||
int retval;
|
||||
u8 reply;
|
||||
|
||||
|
@ -1048,10 +1038,10 @@ static int dst_write_tuna(struct dvb_frontend* fe)
|
|||
|
||||
static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
|
||||
{
|
||||
struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
|
||||
struct dst_state* state = fe->demodulator_priv;
|
||||
u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
|
||||
|
||||
if (state->dst_type == DST_TYPE_IS_TERR)
|
||||
if (state->dst_type != DST_TYPE_IS_SAT)
|
||||
return 0;
|
||||
|
||||
if (cmd->msg_len == 0 || cmd->msg_len > 4)
|
||||
|
@ -1064,39 +1054,32 @@ static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd*
|
|||
|
||||
static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
u8 *val;
|
||||
int need_cmd;
|
||||
struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
|
||||
struct dst_state* state = fe->demodulator_priv;
|
||||
|
||||
state->voltage = voltage;
|
||||
|
||||
if (state->dst_type == DST_TYPE_IS_TERR)
|
||||
if (state->dst_type != DST_TYPE_IS_SAT)
|
||||
return 0;
|
||||
|
||||
need_cmd = 0;
|
||||
val = &state->tx_tuna[0];
|
||||
val[8] &= ~0x40;
|
||||
switch (voltage) {
|
||||
case SEC_VOLTAGE_13:
|
||||
if ((state->diseq_flags & HAS_POWER) == 0)
|
||||
case SEC_VOLTAGE_13:
|
||||
case SEC_VOLTAGE_18:
|
||||
if ((state->diseq_flags & HAS_POWER) == 0)
|
||||
need_cmd = 1;
|
||||
state->diseq_flags |= HAS_POWER;
|
||||
state->tx_tuna[4] = 0x01;
|
||||
break;
|
||||
|
||||
case SEC_VOLTAGE_OFF:
|
||||
need_cmd = 1;
|
||||
state->diseq_flags |= HAS_POWER;
|
||||
break;
|
||||
state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
|
||||
state->tx_tuna[4] = 0x00;
|
||||
break;
|
||||
|
||||
case SEC_VOLTAGE_18:
|
||||
if ((state->diseq_flags & HAS_POWER) == 0)
|
||||
need_cmd = 1;
|
||||
state->diseq_flags |= HAS_POWER;
|
||||
val[8] |= 0x40;
|
||||
break;
|
||||
|
||||
case SEC_VOLTAGE_OFF:
|
||||
need_cmd = 1;
|
||||
state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (need_cmd)
|
||||
dst_tone_power_cmd(state);
|
||||
|
@ -1106,37 +1089,56 @@ static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
|
|||
|
||||
static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
|
||||
{
|
||||
u8 *val;
|
||||
struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
|
||||
struct dst_state* state = fe->demodulator_priv;
|
||||
|
||||
state->tone = tone;
|
||||
|
||||
if (state->dst_type == DST_TYPE_IS_TERR)
|
||||
if (state->dst_type != DST_TYPE_IS_SAT)
|
||||
return 0;
|
||||
|
||||
val = &state->tx_tuna[0];
|
||||
|
||||
val[8] &= ~0x1;
|
||||
|
||||
switch (tone) {
|
||||
case SEC_TONE_OFF:
|
||||
break;
|
||||
case SEC_TONE_OFF:
|
||||
state->tx_tuna[2] = 0xff;
|
||||
break;
|
||||
|
||||
case SEC_TONE_ON:
|
||||
val[8] |= 1;
|
||||
break;
|
||||
case SEC_TONE_ON:
|
||||
state->tx_tuna[2] = 0x02;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
dst_tone_power_cmd(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
|
||||
{
|
||||
struct dst_state *state = fe->demodulator_priv;
|
||||
|
||||
if (state->dst_type != DST_TYPE_IS_SAT)
|
||||
return 0;
|
||||
|
||||
state->minicmd = minicmd;
|
||||
|
||||
switch (minicmd) {
|
||||
case SEC_MINI_A:
|
||||
state->tx_tuna[3] = 0x02;
|
||||
break;
|
||||
case SEC_MINI_B:
|
||||
state->tx_tuna[3] = 0xff;
|
||||
break;
|
||||
}
|
||||
dst_tone_power_cmd(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int dst_init(struct dvb_frontend* fe)
|
||||
{
|
||||
struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
|
||||
struct dst_state* state = fe->demodulator_priv;
|
||||
static u8 ini_satci_tuna[] = { 9, 0, 3, 0xb6, 1, 0, 0x73, 0x21, 0, 0 };
|
||||
static u8 ini_satfta_tuna[] = { 0, 0, 3, 0xb6, 1, 0x55, 0xbd, 0x50, 0, 0 };
|
||||
static u8 ini_tvfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
|
||||
|
@ -1168,7 +1170,7 @@ static int dst_init(struct dvb_frontend* fe)
|
|||
|
||||
static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status)
|
||||
{
|
||||
struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
|
||||
struct dst_state* state = fe->demodulator_priv;
|
||||
|
||||
*status = 0;
|
||||
if (state->diseq_flags & HAS_LOCK) {
|
||||
|
@ -1182,7 +1184,7 @@ static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status)
|
|||
|
||||
static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength)
|
||||
{
|
||||
struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
|
||||
struct dst_state* state = fe->demodulator_priv;
|
||||
|
||||
dst_get_signal(state);
|
||||
*strength = state->decode_strength;
|
||||
|
@ -1192,7 +1194,7 @@ static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength)
|
|||
|
||||
static int dst_read_snr(struct dvb_frontend* fe, u16* snr)
|
||||
{
|
||||
struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
|
||||
struct dst_state* state = fe->demodulator_priv;
|
||||
|
||||
dst_get_signal(state);
|
||||
*snr = state->decode_snr;
|
||||
|
@ -1202,7 +1204,7 @@ static int dst_read_snr(struct dvb_frontend* fe, u16* snr)
|
|||
|
||||
static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
|
||||
struct dst_state* state = fe->demodulator_priv;
|
||||
|
||||
dst_set_freq(state, p->frequency);
|
||||
if (verbose > 4)
|
||||
|
@ -1228,7 +1230,7 @@ static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet
|
|||
|
||||
static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
|
||||
struct dst_state* state = fe->demodulator_priv;
|
||||
|
||||
p->frequency = state->decode_freq;
|
||||
p->inversion = state->inversion;
|
||||
|
@ -1248,7 +1250,7 @@ static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet
|
|||
|
||||
static void dst_release(struct dvb_frontend* fe)
|
||||
{
|
||||
struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
|
||||
struct dst_state* state = fe->demodulator_priv;
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
|
@ -1346,7 +1348,7 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
|
|||
.read_signal_strength = dst_read_signal_strength,
|
||||
.read_snr = dst_read_snr,
|
||||
|
||||
.diseqc_send_burst = dst_set_tone,
|
||||
.diseqc_send_burst = dst_send_burst,
|
||||
.diseqc_send_master_cmd = dst_set_diseqc,
|
||||
.set_voltage = dst_set_voltage,
|
||||
.set_tone = dst_set_tone,
|
||||
|
|
|
@ -1555,6 +1555,7 @@ config SIS900
|
|||
tristate "SiS 900/7016 PCI Fast Ethernet Adapter support"
|
||||
depends on NET_PCI && PCI
|
||||
select CRC32
|
||||
select MII
|
||||
---help---
|
||||
This is a driver for the Fast Ethernet PCI network cards based on
|
||||
the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in
|
||||
|
@ -2031,6 +2032,15 @@ config TIGON3
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called tg3. This is recommended.
|
||||
|
||||
config BNX2
|
||||
tristate "Broadcom NetXtremeII support"
|
||||
depends on PCI
|
||||
help
|
||||
This driver supports Broadcom NetXtremeII gigabit Ethernet cards.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called bnx2. This is recommended.
|
||||
|
||||
config GIANFAR
|
||||
tristate "Gianfar Ethernet"
|
||||
depends on 85xx || 83xx
|
||||
|
|
|
@ -51,6 +51,7 @@ obj-$(CONFIG_NS83820) += ns83820.o
|
|||
obj-$(CONFIG_STNIC) += stnic.o 8390.o
|
||||
obj-$(CONFIG_FEALNX) += fealnx.o
|
||||
obj-$(CONFIG_TIGON3) += tg3.o
|
||||
obj-$(CONFIG_BNX2) += bnx2.o
|
||||
obj-$(CONFIG_TC35815) += tc35815.o
|
||||
obj-$(CONFIG_SK98LIN) += sk98lin/
|
||||
obj-$(CONFIG_SKFP) += skfp/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -3037,7 +3037,7 @@ static void bond_activebackup_arp_mon(struct net_device *bond_dev)
|
|||
bond_set_slave_inactive_flags(bond->current_arp_slave);
|
||||
|
||||
/* search for next candidate */
|
||||
bond_for_each_slave_from(bond, slave, i, bond->current_arp_slave) {
|
||||
bond_for_each_slave_from(bond, slave, i, bond->current_arp_slave->next) {
|
||||
if (IS_UP(slave->dev)) {
|
||||
slave->link = BOND_LINK_BACK;
|
||||
bond_set_slave_active_flags(slave);
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
* cause DMA to kfree'd memory.
|
||||
* 0.31: 14 Nov 2004: ethtool support for getting/setting link
|
||||
* capabilities.
|
||||
* 0.32: 16 Apr 2005: RX_ERROR4 handling added.
|
||||
*
|
||||
* Known bugs:
|
||||
* We suspect that on some hardware no TX done interrupts are generated.
|
||||
|
@ -92,7 +93,7 @@
|
|||
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
|
||||
* superfluous timer interrupts from the nic.
|
||||
*/
|
||||
#define FORCEDETH_VERSION "0.31"
|
||||
#define FORCEDETH_VERSION "0.32"
|
||||
#define DRV_NAME "forcedeth"
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -109,6 +110,7 @@
|
|||
#include <linux/mii.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/if_vlan.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -1013,6 +1015,59 @@ static void nv_tx_timeout(struct net_device *dev)
|
|||
spin_unlock_irq(&np->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when the nic notices a mismatch between the actual data len on the
|
||||
* wire and the len indicated in the 802 header
|
||||
*/
|
||||
static int nv_getlen(struct net_device *dev, void *packet, int datalen)
|
||||
{
|
||||
int hdrlen; /* length of the 802 header */
|
||||
int protolen; /* length as stored in the proto field */
|
||||
|
||||
/* 1) calculate len according to header */
|
||||
if ( ((struct vlan_ethhdr *)packet)->h_vlan_proto == __constant_htons(ETH_P_8021Q)) {
|
||||
protolen = ntohs( ((struct vlan_ethhdr *)packet)->h_vlan_encapsulated_proto );
|
||||
hdrlen = VLAN_HLEN;
|
||||
} else {
|
||||
protolen = ntohs( ((struct ethhdr *)packet)->h_proto);
|
||||
hdrlen = ETH_HLEN;
|
||||
}
|
||||
dprintk(KERN_DEBUG "%s: nv_getlen: datalen %d, protolen %d, hdrlen %d\n",
|
||||
dev->name, datalen, protolen, hdrlen);
|
||||
if (protolen > ETH_DATA_LEN)
|
||||
return datalen; /* Value in proto field not a len, no checks possible */
|
||||
|
||||
protolen += hdrlen;
|
||||
/* consistency checks: */
|
||||
if (datalen > ETH_ZLEN) {
|
||||
if (datalen >= protolen) {
|
||||
/* more data on wire than in 802 header, trim of
|
||||
* additional data.
|
||||
*/
|
||||
dprintk(KERN_DEBUG "%s: nv_getlen: accepting %d bytes.\n",
|
||||
dev->name, protolen);
|
||||
return protolen;
|
||||
} else {
|
||||
/* less data on wire than mentioned in header.
|
||||
* Discard the packet.
|
||||
*/
|
||||
dprintk(KERN_DEBUG "%s: nv_getlen: discarding long packet.\n",
|
||||
dev->name);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* short packet. Accept only if 802 values are also short */
|
||||
if (protolen > ETH_ZLEN) {
|
||||
dprintk(KERN_DEBUG "%s: nv_getlen: discarding short packet.\n",
|
||||
dev->name);
|
||||
return -1;
|
||||
}
|
||||
dprintk(KERN_DEBUG "%s: nv_getlen: accepting %d bytes.\n",
|
||||
dev->name, datalen);
|
||||
return datalen;
|
||||
}
|
||||
}
|
||||
|
||||
static void nv_rx_process(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
|
@ -1064,7 +1119,7 @@ static void nv_rx_process(struct net_device *dev)
|
|||
np->stats.rx_errors++;
|
||||
goto next_pkt;
|
||||
}
|
||||
if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3|NV_RX_ERROR4)) {
|
||||
if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3)) {
|
||||
np->stats.rx_errors++;
|
||||
goto next_pkt;
|
||||
}
|
||||
|
@ -1078,22 +1133,24 @@ static void nv_rx_process(struct net_device *dev)
|
|||
np->stats.rx_errors++;
|
||||
goto next_pkt;
|
||||
}
|
||||
if (Flags & NV_RX_ERROR) {
|
||||
/* framing errors are soft errors, the rest is fatal. */
|
||||
if (Flags & NV_RX_FRAMINGERR) {
|
||||
if (Flags & NV_RX_SUBSTRACT1) {
|
||||
len--;
|
||||
}
|
||||
} else {
|
||||
if (Flags & NV_RX_ERROR4) {
|
||||
len = nv_getlen(dev, np->rx_skbuff[i]->data, len);
|
||||
if (len < 0) {
|
||||
np->stats.rx_errors++;
|
||||
goto next_pkt;
|
||||
}
|
||||
}
|
||||
/* framing errors are soft errors. */
|
||||
if (Flags & NV_RX_FRAMINGERR) {
|
||||
if (Flags & NV_RX_SUBSTRACT1) {
|
||||
len--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!(Flags & NV_RX2_DESCRIPTORVALID))
|
||||
goto next_pkt;
|
||||
|
||||
if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3|NV_RX2_ERROR4)) {
|
||||
if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) {
|
||||
np->stats.rx_errors++;
|
||||
goto next_pkt;
|
||||
}
|
||||
|
@ -1107,17 +1164,19 @@ static void nv_rx_process(struct net_device *dev)
|
|||
np->stats.rx_errors++;
|
||||
goto next_pkt;
|
||||
}
|
||||
if (Flags & NV_RX2_ERROR) {
|
||||
/* framing errors are soft errors, the rest is fatal. */
|
||||
if (Flags & NV_RX2_FRAMINGERR) {
|
||||
if (Flags & NV_RX2_SUBSTRACT1) {
|
||||
len--;
|
||||
}
|
||||
} else {
|
||||
if (Flags & NV_RX2_ERROR4) {
|
||||
len = nv_getlen(dev, np->rx_skbuff[i]->data, len);
|
||||
if (len < 0) {
|
||||
np->stats.rx_errors++;
|
||||
goto next_pkt;
|
||||
}
|
||||
}
|
||||
/* framing errors are soft errors */
|
||||
if (Flags & NV_RX2_FRAMINGERR) {
|
||||
if (Flags & NV_RX2_SUBSTRACT1) {
|
||||
len--;
|
||||
}
|
||||
}
|
||||
Flags &= NV_RX2_CHECKSUMMASK;
|
||||
if (Flags == NV_RX2_CHECKSUMOK1 ||
|
||||
Flags == NV_RX2_CHECKSUMOK2 ||
|
||||
|
@ -1480,6 +1539,13 @@ static void nv_do_nic_poll(unsigned long data)
|
|||
enable_irq(dev->irq);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
static void nv_poll_controller(struct net_device *dev)
|
||||
{
|
||||
nv_do_nic_poll((unsigned long) dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
|
@ -1962,6 +2028,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
|
|||
dev->get_stats = nv_get_stats;
|
||||
dev->change_mtu = nv_change_mtu;
|
||||
dev->set_multicast_list = nv_set_multicast;
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
dev->poll_controller = nv_poll_controller;
|
||||
#endif
|
||||
SET_ETHTOOL_OPS(dev, &ops);
|
||||
dev->tx_timeout = nv_tx_timeout;
|
||||
dev->watchdog_timeo = NV_WATCHDOG_TIMEO;
|
||||
|
|
|
@ -924,7 +924,7 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp,
|
|||
|
||||
spin_lock_irqsave(&cnx->lock, flags);
|
||||
|
||||
if (! cnx->state & VETH_STATE_READY)
|
||||
if (! (cnx->state & VETH_STATE_READY))
|
||||
goto drop;
|
||||
|
||||
if ((skb->len - 14) > VETH_MAX_MTU)
|
||||
|
@ -1023,6 +1023,8 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
|
||||
lpmask = veth_transmit_to_many(skb, lpmask, dev);
|
||||
|
||||
dev->trans_start = jiffies;
|
||||
|
||||
if (! lpmask) {
|
||||
dev_kfree_skb(skb);
|
||||
} else {
|
||||
|
@ -1262,13 +1264,18 @@ static void veth_receive(struct veth_lpar_connection *cnx,
|
|||
|
||||
vlan = skb->data[9];
|
||||
dev = veth_dev[vlan];
|
||||
if (! dev)
|
||||
/* Some earlier versions of the driver sent
|
||||
broadcasts down all connections, even to
|
||||
lpars that weren't on the relevant vlan.
|
||||
So ignore packets belonging to a vlan we're
|
||||
not on. */
|
||||
if (! dev) {
|
||||
/*
|
||||
* Some earlier versions of the driver sent
|
||||
* broadcasts down all connections, even to lpars
|
||||
* that weren't on the relevant vlan. So ignore
|
||||
* packets belonging to a vlan we're not on.
|
||||
* We can also be here if we receive packets while
|
||||
* the driver is going down, because then dev is NULL.
|
||||
*/
|
||||
dev_kfree_skb_irq(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
port = (struct veth_port *)dev->priv;
|
||||
dest = *((u64 *) skb->data) & 0xFFFFFFFFFFFF0000;
|
||||
|
@ -1381,18 +1388,25 @@ void __exit veth_module_cleanup(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
vio_unregister_driver(&veth_driver);
|
||||
/* Stop the queues first to stop any new packets being sent. */
|
||||
for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++)
|
||||
if (veth_dev[i])
|
||||
netif_stop_queue(veth_dev[i]);
|
||||
|
||||
/* Stop the connections before we unregister the driver. This
|
||||
* ensures there's no skbs lying around holding the device open. */
|
||||
for (i = 0; i < HVMAXARCHITECTEDLPS; ++i)
|
||||
veth_stop_connection(i);
|
||||
|
||||
HvLpEvent_unregisterHandler(HvLpEvent_Type_VirtualLan);
|
||||
|
||||
/* Hypervisor callbacks may have scheduled more work while we
|
||||
* were destroying connections. Now that we've disconnected from
|
||||
* were stoping connections. Now that we've disconnected from
|
||||
* the hypervisor make sure everything's finished. */
|
||||
flush_scheduled_work();
|
||||
|
||||
vio_unregister_driver(&veth_driver);
|
||||
|
||||
for (i = 0; i < HVMAXARCHITECTEDLPS; ++i)
|
||||
veth_destroy_connection(i);
|
||||
|
||||
|
|
|
@ -2433,9 +2433,9 @@ static void __set_rx_mode(struct net_device *dev)
|
|||
rx_mode = RxFilterEnable | AcceptBroadcast
|
||||
| AcceptMulticast | AcceptMyPhys;
|
||||
for (i = 0; i < 64; i += 2) {
|
||||
writew(HASH_TABLE + i, ioaddr + RxFilterAddr);
|
||||
writew((mc_filter[i+1]<<8) + mc_filter[i],
|
||||
ioaddr + RxFilterData);
|
||||
writel(HASH_TABLE + i, ioaddr + RxFilterAddr);
|
||||
writel((mc_filter[i + 1] << 8) + mc_filter[i],
|
||||
ioaddr + RxFilterData);
|
||||
}
|
||||
}
|
||||
writel(rx_mode, ioaddr + RxFilterAddr);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define _VERSION "0.20"
|
||||
#define VERSION "0.22"
|
||||
/* ns83820.c by Benjamin LaHaise with contributions.
|
||||
*
|
||||
* Questions/comments/discussion to linux-ns83820@kvack.org.
|
||||
|
@ -63,9 +63,11 @@
|
|||
* - fix missed txok introduced during performance
|
||||
* tuning
|
||||
* 0.20 - fix stupid RFEN thinko. i am such a smurf.
|
||||
*
|
||||
* 20040828 0.21 - add hardware vlan accleration
|
||||
* by Neil Horman <nhorman@redhat.com>
|
||||
* 20050406 0.22 - improved DAC ifdefs from Andi Kleen
|
||||
* - removal of dead code from Adrian Bunk
|
||||
* - fix half duplex collision behaviour
|
||||
* Driver Overview
|
||||
* ===============
|
||||
*
|
||||
|
@ -129,18 +131,6 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */
|
|||
#undef Dprintk
|
||||
#define Dprintk dprintk
|
||||
|
||||
#if defined(CONFIG_HIGHMEM64G) || defined(__ia64__)
|
||||
#define USE_64BIT_ADDR "+"
|
||||
#endif
|
||||
|
||||
#if defined(USE_64BIT_ADDR)
|
||||
#define VERSION _VERSION USE_64BIT_ADDR
|
||||
#define TRY_DAC 1
|
||||
#else
|
||||
#define VERSION _VERSION
|
||||
#define TRY_DAC 0
|
||||
#endif
|
||||
|
||||
/* tunables */
|
||||
#define RX_BUF_SIZE 1500 /* 8192 */
|
||||
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
|
||||
|
@ -386,22 +376,16 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */
|
|||
#define LINK_DOWN 0x02
|
||||
#define LINK_UP 0x04
|
||||
|
||||
#ifdef USE_64BIT_ADDR
|
||||
#define HW_ADDR_LEN 8
|
||||
#define HW_ADDR_LEN sizeof(dma_addr_t)
|
||||
#define desc_addr_set(desc, addr) \
|
||||
do { \
|
||||
u64 __addr = (addr); \
|
||||
(desc)[0] = cpu_to_le32(__addr); \
|
||||
(desc)[1] = cpu_to_le32(__addr >> 32); \
|
||||
((desc)[0] = cpu_to_le32(addr)); \
|
||||
if (HW_ADDR_LEN == 8) \
|
||||
(desc)[1] = cpu_to_le32(((u64)addr) >> 32); \
|
||||
} while(0)
|
||||
#define desc_addr_get(desc) \
|
||||
(((u64)le32_to_cpu((desc)[1]) << 32) \
|
||||
| le32_to_cpu((desc)[0]))
|
||||
#else
|
||||
#define HW_ADDR_LEN 4
|
||||
#define desc_addr_set(desc, addr) ((desc)[0] = cpu_to_le32(addr))
|
||||
#define desc_addr_get(desc) (le32_to_cpu((desc)[0]))
|
||||
#endif
|
||||
(le32_to_cpu((desc)[0]) | \
|
||||
(HW_ADDR_LEN == 8 ? ((dma_addr_t)le32_to_cpu((desc)[1]))<<32 : 0))
|
||||
|
||||
#define DESC_LINK 0
|
||||
#define DESC_BUFPTR (DESC_LINK + HW_ADDR_LEN/4)
|
||||
|
@ -727,11 +711,23 @@ static void fastcall phy_intr(struct net_device *ndev)
|
|||
speed = ((cfg / CFG_SPDSTS0) & 3);
|
||||
fullduplex = (cfg & CFG_DUPSTS);
|
||||
|
||||
if (fullduplex)
|
||||
if (fullduplex) {
|
||||
new_cfg |= CFG_SB;
|
||||
writel(readl(dev->base + TXCFG)
|
||||
| TXCFG_CSI | TXCFG_HBI,
|
||||
dev->base + TXCFG);
|
||||
writel(readl(dev->base + RXCFG) | RXCFG_RX_FD,
|
||||
dev->base + RXCFG);
|
||||
} else {
|
||||
writel(readl(dev->base + TXCFG)
|
||||
& ~(TXCFG_CSI | TXCFG_HBI),
|
||||
dev->base + TXCFG);
|
||||
writel(readl(dev->base + RXCFG) & ~(RXCFG_RX_FD),
|
||||
dev->base + RXCFG);
|
||||
}
|
||||
|
||||
if ((cfg & CFG_LNKSTS) &&
|
||||
((new_cfg ^ dev->CFG_cache) & CFG_MODE_1000)) {
|
||||
((new_cfg ^ dev->CFG_cache) != 0)) {
|
||||
writel(new_cfg, dev->base + CFG);
|
||||
dev->CFG_cache = new_cfg;
|
||||
}
|
||||
|
@ -1189,7 +1185,6 @@ again:
|
|||
|
||||
for (;;) {
|
||||
volatile u32 *desc = dev->tx_descs + (free_idx * DESC_SIZE);
|
||||
u32 residue = 0;
|
||||
|
||||
dprintk("frag[%3u]: %4u @ 0x%08Lx\n", free_idx, len,
|
||||
(unsigned long long)buf);
|
||||
|
@ -1199,17 +1194,11 @@ again:
|
|||
desc_addr_set(desc + DESC_BUFPTR, buf);
|
||||
desc[DESC_EXTSTS] = cpu_to_le32(extsts);
|
||||
|
||||
cmdsts = ((nr_frags|residue) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0);
|
||||
cmdsts = ((nr_frags) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0);
|
||||
cmdsts |= (desc == first_desc) ? 0 : CMDSTS_OWN;
|
||||
cmdsts |= len;
|
||||
desc[DESC_CMDSTS] = cpu_to_le32(cmdsts);
|
||||
|
||||
if (residue) {
|
||||
buf += len;
|
||||
len = residue;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!nr_frags)
|
||||
break;
|
||||
|
||||
|
@ -1841,7 +1830,8 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
|
|||
int using_dac = 0;
|
||||
|
||||
/* See if we can set the dma mask early on; failure is fatal. */
|
||||
if (TRY_DAC && !pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) {
|
||||
if (sizeof(dma_addr_t) == 8 &&
|
||||
!pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) {
|
||||
using_dac = 1;
|
||||
} else if (!pci_set_dma_mask(pci_dev, 0xffffffff)) {
|
||||
using_dac = 0;
|
||||
|
@ -1972,9 +1962,8 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
|
|||
/* When compiled with 64 bit addressing, we must always enable
|
||||
* the 64 bit descriptor format.
|
||||
*/
|
||||
#ifdef USE_64BIT_ADDR
|
||||
dev->CFG_cache |= CFG_M64ADDR;
|
||||
#endif
|
||||
if (sizeof(dma_addr_t) == 8)
|
||||
dev->CFG_cache |= CFG_M64ADDR;
|
||||
if (using_dac)
|
||||
dev->CFG_cache |= CFG_T64ADDR;
|
||||
|
||||
|
|
|
@ -162,6 +162,7 @@ struct sis900_private {
|
|||
struct mii_phy * mii;
|
||||
struct mii_phy * first_mii; /* record the first mii structure */
|
||||
unsigned int cur_phy;
|
||||
struct mii_if_info mii_info;
|
||||
|
||||
struct timer_list timer; /* Link status detection timer. */
|
||||
u8 autong_complete; /* 1: auto-negotiate complete */
|
||||
|
@ -203,7 +204,7 @@ static int sis900_open(struct net_device *net_dev);
|
|||
static int sis900_mii_probe (struct net_device * net_dev);
|
||||
static void sis900_init_rxfilter (struct net_device * net_dev);
|
||||
static u16 read_eeprom(long ioaddr, int location);
|
||||
static u16 mdio_read(struct net_device *net_dev, int phy_id, int location);
|
||||
static int mdio_read(struct net_device *net_dev, int phy_id, int location);
|
||||
static void mdio_write(struct net_device *net_dev, int phy_id, int location, int val);
|
||||
static void sis900_timer(unsigned long data);
|
||||
static void sis900_check_mode (struct net_device *net_dev, struct mii_phy *mii_phy);
|
||||
|
@ -478,7 +479,13 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
|
|||
sis_priv->msg_enable = sis900_debug;
|
||||
else
|
||||
sis_priv->msg_enable = SIS900_DEF_MSG;
|
||||
|
||||
|
||||
sis_priv->mii_info.dev = net_dev;
|
||||
sis_priv->mii_info.mdio_read = mdio_read;
|
||||
sis_priv->mii_info.mdio_write = mdio_write;
|
||||
sis_priv->mii_info.phy_id_mask = 0x1f;
|
||||
sis_priv->mii_info.reg_num_mask = 0x1f;
|
||||
|
||||
/* Get Mac address according to the chip revision */
|
||||
pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &(sis_priv->chipset_rev));
|
||||
if(netif_msg_probe(sis_priv))
|
||||
|
@ -725,6 +732,8 @@ static u16 sis900_default_phy(struct net_device * net_dev)
|
|||
pci_name(sis_priv->pci_dev), sis_priv->cur_phy);
|
||||
}
|
||||
|
||||
sis_priv->mii_info.phy_id = sis_priv->cur_phy;
|
||||
|
||||
status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL);
|
||||
status &= (~MII_CNTL_ISOLATE);
|
||||
|
||||
|
@ -852,7 +861,7 @@ static void mdio_reset(long mdio_addr)
|
|||
* Please see SiS7014 or ICS spec
|
||||
*/
|
||||
|
||||
static u16 mdio_read(struct net_device *net_dev, int phy_id, int location)
|
||||
static int mdio_read(struct net_device *net_dev, int phy_id, int location)
|
||||
{
|
||||
long mdio_addr = net_dev->base_addr + mear;
|
||||
int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
|
||||
|
@ -1966,10 +1975,47 @@ static void sis900_set_msglevel(struct net_device *net_dev, u32 value)
|
|||
sis_priv->msg_enable = value;
|
||||
}
|
||||
|
||||
static u32 sis900_get_link(struct net_device *net_dev)
|
||||
{
|
||||
struct sis900_private *sis_priv = net_dev->priv;
|
||||
return mii_link_ok(&sis_priv->mii_info);
|
||||
}
|
||||
|
||||
static int sis900_get_settings(struct net_device *net_dev,
|
||||
struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct sis900_private *sis_priv = net_dev->priv;
|
||||
spin_lock_irq(&sis_priv->lock);
|
||||
mii_ethtool_gset(&sis_priv->mii_info, cmd);
|
||||
spin_unlock_irq(&sis_priv->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sis900_set_settings(struct net_device *net_dev,
|
||||
struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct sis900_private *sis_priv = net_dev->priv;
|
||||
int rt;
|
||||
spin_lock_irq(&sis_priv->lock);
|
||||
rt = mii_ethtool_sset(&sis_priv->mii_info, cmd);
|
||||
spin_unlock_irq(&sis_priv->lock);
|
||||
return rt;
|
||||
}
|
||||
|
||||
static int sis900_nway_reset(struct net_device *net_dev)
|
||||
{
|
||||
struct sis900_private *sis_priv = net_dev->priv;
|
||||
return mii_nway_restart(&sis_priv->mii_info);
|
||||
}
|
||||
|
||||
static struct ethtool_ops sis900_ethtool_ops = {
|
||||
.get_drvinfo = sis900_get_drvinfo,
|
||||
.get_msglevel = sis900_get_msglevel,
|
||||
.set_msglevel = sis900_set_msglevel,
|
||||
.get_link = sis900_get_link,
|
||||
.get_settings = sis900_get_settings,
|
||||
.set_settings = sis900_set_settings,
|
||||
.nway_reset = sis900_nway_reset,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -133,6 +133,8 @@
|
|||
/* number of ETHTOOL_GSTATS u64's */
|
||||
#define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64))
|
||||
|
||||
#define TG3_NUM_TEST 6
|
||||
|
||||
static char version[] __devinitdata =
|
||||
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
|
||||
|
||||
|
@ -316,6 +318,17 @@ static struct {
|
|||
{ "nic_tx_threshold_hit" }
|
||||
};
|
||||
|
||||
static struct {
|
||||
const char string[ETH_GSTRING_LEN];
|
||||
} ethtool_test_keys[TG3_NUM_TEST] = {
|
||||
{ "nvram test (online) " },
|
||||
{ "link test (online) " },
|
||||
{ "register test (offline)" },
|
||||
{ "memory test (offline)" },
|
||||
{ "loopback test (offline)" },
|
||||
{ "interrupt test (offline)" },
|
||||
};
|
||||
|
||||
static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
|
||||
{
|
||||
if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
|
||||
|
@ -3070,7 +3083,7 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
|
|||
}
|
||||
|
||||
static int tg3_init_hw(struct tg3 *);
|
||||
static int tg3_halt(struct tg3 *, int);
|
||||
static int tg3_halt(struct tg3 *, int, int);
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
static void tg3_poll_controller(struct net_device *dev)
|
||||
|
@ -3094,7 +3107,7 @@ static void tg3_reset_task(void *_data)
|
|||
restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER;
|
||||
tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER;
|
||||
|
||||
tg3_halt(tp, 0);
|
||||
tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
|
||||
tg3_init_hw(tp);
|
||||
|
||||
tg3_netif_start(tp);
|
||||
|
@ -3440,7 +3453,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
|
|||
spin_lock_irq(&tp->lock);
|
||||
spin_lock(&tp->tx_lock);
|
||||
|
||||
tg3_halt(tp, 1);
|
||||
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
||||
|
||||
tg3_set_mtu(dev, tp, new_mtu);
|
||||
|
||||
|
@ -4131,19 +4144,19 @@ static void tg3_stop_fw(struct tg3 *tp)
|
|||
}
|
||||
|
||||
/* tp->lock is held. */
|
||||
static int tg3_halt(struct tg3 *tp, int silent)
|
||||
static int tg3_halt(struct tg3 *tp, int kind, int silent)
|
||||
{
|
||||
int err;
|
||||
|
||||
tg3_stop_fw(tp);
|
||||
|
||||
tg3_write_sig_pre_reset(tp, RESET_KIND_SHUTDOWN);
|
||||
tg3_write_sig_pre_reset(tp, kind);
|
||||
|
||||
tg3_abort_hw(tp, silent);
|
||||
err = tg3_chip_reset(tp);
|
||||
|
||||
tg3_write_sig_legacy(tp, RESET_KIND_SHUTDOWN);
|
||||
tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
|
||||
tg3_write_sig_legacy(tp, kind);
|
||||
tg3_write_sig_post_reset(tp, kind);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -4357,7 +4370,12 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
|
|||
*/
|
||||
tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
|
||||
|
||||
/* It is possible that bootcode is still loading at this point.
|
||||
* Get the nvram lock first before halting the cpu.
|
||||
*/
|
||||
tg3_nvram_lock(tp);
|
||||
err = tg3_halt_cpu(tp, cpu_base);
|
||||
tg3_nvram_unlock(tp);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -5881,6 +5899,9 @@ static int tg3_test_interrupt(struct tg3 *tp)
|
|||
int err, i;
|
||||
u32 int_mbox = 0;
|
||||
|
||||
if (!netif_running(dev))
|
||||
return -ENODEV;
|
||||
|
||||
tg3_disable_ints(tp);
|
||||
|
||||
free_irq(tp->pdev->irq, dev);
|
||||
|
@ -5984,7 +6005,7 @@ static int tg3_test_msi(struct tg3 *tp)
|
|||
spin_lock_irq(&tp->lock);
|
||||
spin_lock(&tp->tx_lock);
|
||||
|
||||
tg3_halt(tp, 1);
|
||||
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
||||
err = tg3_init_hw(tp);
|
||||
|
||||
spin_unlock(&tp->tx_lock);
|
||||
|
@ -6060,7 +6081,7 @@ static int tg3_open(struct net_device *dev)
|
|||
|
||||
err = tg3_init_hw(tp);
|
||||
if (err) {
|
||||
tg3_halt(tp, 1);
|
||||
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
||||
tg3_free_rings(tp);
|
||||
} else {
|
||||
if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
|
||||
|
@ -6104,7 +6125,7 @@ static int tg3_open(struct net_device *dev)
|
|||
pci_disable_msi(tp->pdev);
|
||||
tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
|
||||
}
|
||||
tg3_halt(tp, 1);
|
||||
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
||||
tg3_free_rings(tp);
|
||||
tg3_free_consistent(tp);
|
||||
|
||||
|
@ -6377,7 +6398,7 @@ static int tg3_close(struct net_device *dev)
|
|||
|
||||
tg3_disable_ints(tp);
|
||||
|
||||
tg3_halt(tp, 1);
|
||||
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
||||
tg3_free_rings(tp);
|
||||
tp->tg3_flags &=
|
||||
~(TG3_FLAG_INIT_COMPLETE |
|
||||
|
@ -7097,7 +7118,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
|
|||
tp->tx_pending = ering->tx_pending;
|
||||
|
||||
if (netif_running(dev)) {
|
||||
tg3_halt(tp, 1);
|
||||
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
||||
tg3_init_hw(tp);
|
||||
tg3_netif_start(tp);
|
||||
}
|
||||
|
@ -7140,7 +7161,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
|
|||
tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE;
|
||||
|
||||
if (netif_running(dev)) {
|
||||
tg3_halt(tp, 1);
|
||||
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
||||
tg3_init_hw(tp);
|
||||
tg3_netif_start(tp);
|
||||
}
|
||||
|
@ -7199,12 +7220,20 @@ static int tg3_get_stats_count (struct net_device *dev)
|
|||
return TG3_NUM_STATS;
|
||||
}
|
||||
|
||||
static int tg3_get_test_count (struct net_device *dev)
|
||||
{
|
||||
return TG3_NUM_TEST;
|
||||
}
|
||||
|
||||
static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf)
|
||||
{
|
||||
switch (stringset) {
|
||||
case ETH_SS_STATS:
|
||||
memcpy(buf, ðtool_stats_keys, sizeof(ethtool_stats_keys));
|
||||
break;
|
||||
case ETH_SS_TEST:
|
||||
memcpy(buf, ðtool_test_keys, sizeof(ethtool_test_keys));
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1); /* we need a WARN() */
|
||||
break;
|
||||
|
@ -7218,6 +7247,516 @@ static void tg3_get_ethtool_stats (struct net_device *dev,
|
|||
memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats));
|
||||
}
|
||||
|
||||
#define NVRAM_TEST_SIZE 0x100
|
||||
|
||||
static int tg3_test_nvram(struct tg3 *tp)
|
||||
{
|
||||
u32 *buf, csum;
|
||||
int i, j, err = 0;
|
||||
|
||||
buf = kmalloc(NVRAM_TEST_SIZE, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0, j = 0; i < NVRAM_TEST_SIZE; i += 4, j++) {
|
||||
u32 val;
|
||||
|
||||
if ((err = tg3_nvram_read(tp, i, &val)) != 0)
|
||||
break;
|
||||
buf[j] = cpu_to_le32(val);
|
||||
}
|
||||
if (i < NVRAM_TEST_SIZE)
|
||||
goto out;
|
||||
|
||||
err = -EIO;
|
||||
if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC)
|
||||
goto out;
|
||||
|
||||
/* Bootstrap checksum at offset 0x10 */
|
||||
csum = calc_crc((unsigned char *) buf, 0x10);
|
||||
if(csum != cpu_to_le32(buf[0x10/4]))
|
||||
goto out;
|
||||
|
||||
/* Manufacturing block starts at offset 0x74, checksum at 0xfc */
|
||||
csum = calc_crc((unsigned char *) &buf[0x74/4], 0x88);
|
||||
if (csum != cpu_to_le32(buf[0xfc/4]))
|
||||
goto out;
|
||||
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
kfree(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
#define TG3_SERDES_TIMEOUT_SEC 2
|
||||
#define TG3_COPPER_TIMEOUT_SEC 6
|
||||
|
||||
static int tg3_test_link(struct tg3 *tp)
|
||||
{
|
||||
int i, max;
|
||||
|
||||
if (!netif_running(tp->dev))
|
||||
return -ENODEV;
|
||||
|
||||
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
|
||||
max = TG3_SERDES_TIMEOUT_SEC;
|
||||
else
|
||||
max = TG3_COPPER_TIMEOUT_SEC;
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
if (netif_carrier_ok(tp->dev))
|
||||
return 0;
|
||||
|
||||
if (msleep_interruptible(1000))
|
||||
break;
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Only test the commonly used registers */
|
||||
static int tg3_test_registers(struct tg3 *tp)
|
||||
{
|
||||
int i, is_5705;
|
||||
u32 offset, read_mask, write_mask, val, save_val, read_val;
|
||||
static struct {
|
||||
u16 offset;
|
||||
u16 flags;
|
||||
#define TG3_FL_5705 0x1
|
||||
#define TG3_FL_NOT_5705 0x2
|
||||
#define TG3_FL_NOT_5788 0x4
|
||||
u32 read_mask;
|
||||
u32 write_mask;
|
||||
} reg_tbl[] = {
|
||||
/* MAC Control Registers */
|
||||
{ MAC_MODE, TG3_FL_NOT_5705,
|
||||
0x00000000, 0x00ef6f8c },
|
||||
{ MAC_MODE, TG3_FL_5705,
|
||||
0x00000000, 0x01ef6b8c },
|
||||
{ MAC_STATUS, TG3_FL_NOT_5705,
|
||||
0x03800107, 0x00000000 },
|
||||
{ MAC_STATUS, TG3_FL_5705,
|
||||
0x03800100, 0x00000000 },
|
||||
{ MAC_ADDR_0_HIGH, 0x0000,
|
||||
0x00000000, 0x0000ffff },
|
||||
{ MAC_ADDR_0_LOW, 0x0000,
|
||||
0x00000000, 0xffffffff },
|
||||
{ MAC_RX_MTU_SIZE, 0x0000,
|
||||
0x00000000, 0x0000ffff },
|
||||
{ MAC_TX_MODE, 0x0000,
|
||||
0x00000000, 0x00000070 },
|
||||
{ MAC_TX_LENGTHS, 0x0000,
|
||||
0x00000000, 0x00003fff },
|
||||
{ MAC_RX_MODE, TG3_FL_NOT_5705,
|
||||
0x00000000, 0x000007fc },
|
||||
{ MAC_RX_MODE, TG3_FL_5705,
|
||||
0x00000000, 0x000007dc },
|
||||
{ MAC_HASH_REG_0, 0x0000,
|
||||
0x00000000, 0xffffffff },
|
||||
{ MAC_HASH_REG_1, 0x0000,
|
||||
0x00000000, 0xffffffff },
|
||||
{ MAC_HASH_REG_2, 0x0000,
|
||||
0x00000000, 0xffffffff },
|
||||
{ MAC_HASH_REG_3, 0x0000,
|
||||
0x00000000, 0xffffffff },
|
||||
|
||||
/* Receive Data and Receive BD Initiator Control Registers. */
|
||||
{ RCVDBDI_JUMBO_BD+0, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ RCVDBDI_JUMBO_BD+4, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ RCVDBDI_JUMBO_BD+8, TG3_FL_NOT_5705,
|
||||
0x00000000, 0x00000003 },
|
||||
{ RCVDBDI_JUMBO_BD+0xc, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ RCVDBDI_STD_BD+0, 0x0000,
|
||||
0x00000000, 0xffffffff },
|
||||
{ RCVDBDI_STD_BD+4, 0x0000,
|
||||
0x00000000, 0xffffffff },
|
||||
{ RCVDBDI_STD_BD+8, 0x0000,
|
||||
0x00000000, 0xffff0002 },
|
||||
{ RCVDBDI_STD_BD+0xc, 0x0000,
|
||||
0x00000000, 0xffffffff },
|
||||
|
||||
/* Receive BD Initiator Control Registers. */
|
||||
{ RCVBDI_STD_THRESH, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ RCVBDI_STD_THRESH, TG3_FL_5705,
|
||||
0x00000000, 0x000003ff },
|
||||
{ RCVBDI_JUMBO_THRESH, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
|
||||
/* Host Coalescing Control Registers. */
|
||||
{ HOSTCC_MODE, TG3_FL_NOT_5705,
|
||||
0x00000000, 0x00000004 },
|
||||
{ HOSTCC_MODE, TG3_FL_5705,
|
||||
0x00000000, 0x000000f6 },
|
||||
{ HOSTCC_RXCOL_TICKS, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ HOSTCC_RXCOL_TICKS, TG3_FL_5705,
|
||||
0x00000000, 0x000003ff },
|
||||
{ HOSTCC_TXCOL_TICKS, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ HOSTCC_TXCOL_TICKS, TG3_FL_5705,
|
||||
0x00000000, 0x000003ff },
|
||||
{ HOSTCC_RXMAX_FRAMES, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ HOSTCC_RXMAX_FRAMES, TG3_FL_5705 | TG3_FL_NOT_5788,
|
||||
0x00000000, 0x000000ff },
|
||||
{ HOSTCC_TXMAX_FRAMES, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ HOSTCC_TXMAX_FRAMES, TG3_FL_5705 | TG3_FL_NOT_5788,
|
||||
0x00000000, 0x000000ff },
|
||||
{ HOSTCC_RXCOAL_TICK_INT, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ HOSTCC_TXCOAL_TICK_INT, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ HOSTCC_RXCOAL_MAXF_INT, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ HOSTCC_RXCOAL_MAXF_INT, TG3_FL_5705 | TG3_FL_NOT_5788,
|
||||
0x00000000, 0x000000ff },
|
||||
{ HOSTCC_TXCOAL_MAXF_INT, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ HOSTCC_TXCOAL_MAXF_INT, TG3_FL_5705 | TG3_FL_NOT_5788,
|
||||
0x00000000, 0x000000ff },
|
||||
{ HOSTCC_STAT_COAL_TICKS, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ HOSTCC_STATS_BLK_HOST_ADDR, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ HOSTCC_STATS_BLK_HOST_ADDR+4, TG3_FL_NOT_5705,
|
||||
0x00000000, 0xffffffff },
|
||||
{ HOSTCC_STATUS_BLK_HOST_ADDR, 0x0000,
|
||||
0x00000000, 0xffffffff },
|
||||
{ HOSTCC_STATUS_BLK_HOST_ADDR+4, 0x0000,
|
||||
0x00000000, 0xffffffff },
|
||||
{ HOSTCC_STATS_BLK_NIC_ADDR, 0x0000,
|
||||
0xffffffff, 0x00000000 },
|
||||
{ HOSTCC_STATUS_BLK_NIC_ADDR, 0x0000,
|
||||
0xffffffff, 0x00000000 },
|
||||
|
||||
/* Buffer Manager Control Registers. */
|
||||
{ BUFMGR_MB_POOL_ADDR, 0x0000,
|
||||
0x00000000, 0x007fff80 },
|
||||
{ BUFMGR_MB_POOL_SIZE, 0x0000,
|
||||
0x00000000, 0x007fffff },
|
||||
{ BUFMGR_MB_RDMA_LOW_WATER, 0x0000,
|
||||
0x00000000, 0x0000003f },
|
||||
{ BUFMGR_MB_MACRX_LOW_WATER, 0x0000,
|
||||
0x00000000, 0x000001ff },
|
||||
{ BUFMGR_MB_HIGH_WATER, 0x0000,
|
||||
0x00000000, 0x000001ff },
|
||||
{ BUFMGR_DMA_DESC_POOL_ADDR, TG3_FL_NOT_5705,
|
||||
0xffffffff, 0x00000000 },
|
||||
{ BUFMGR_DMA_DESC_POOL_SIZE, TG3_FL_NOT_5705,
|
||||
0xffffffff, 0x00000000 },
|
||||
|
||||
/* Mailbox Registers */
|
||||
{ GRCMBOX_RCVSTD_PROD_IDX+4, 0x0000,
|
||||
0x00000000, 0x000001ff },
|
||||
{ GRCMBOX_RCVJUMBO_PROD_IDX+4, TG3_FL_NOT_5705,
|
||||
0x00000000, 0x000001ff },
|
||||
{ GRCMBOX_RCVRET_CON_IDX_0+4, 0x0000,
|
||||
0x00000000, 0x000007ff },
|
||||
{ GRCMBOX_SNDHOST_PROD_IDX_0+4, 0x0000,
|
||||
0x00000000, 0x000001ff },
|
||||
|
||||
{ 0xffff, 0x0000, 0x00000000, 0x00000000 },
|
||||
};
|
||||
|
||||
if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
|
||||
is_5705 = 1;
|
||||
else
|
||||
is_5705 = 0;
|
||||
|
||||
for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
|
||||
if (is_5705 && (reg_tbl[i].flags & TG3_FL_NOT_5705))
|
||||
continue;
|
||||
|
||||
if (!is_5705 && (reg_tbl[i].flags & TG3_FL_5705))
|
||||
continue;
|
||||
|
||||
if ((tp->tg3_flags2 & TG3_FLG2_IS_5788) &&
|
||||
(reg_tbl[i].flags & TG3_FL_NOT_5788))
|
||||
continue;
|
||||
|
||||
offset = (u32) reg_tbl[i].offset;
|
||||
read_mask = reg_tbl[i].read_mask;
|
||||
write_mask = reg_tbl[i].write_mask;
|
||||
|
||||
/* Save the original register content */
|
||||
save_val = tr32(offset);
|
||||
|
||||
/* Determine the read-only value. */
|
||||
read_val = save_val & read_mask;
|
||||
|
||||
/* Write zero to the register, then make sure the read-only bits
|
||||
* are not changed and the read/write bits are all zeros.
|
||||
*/
|
||||
tw32(offset, 0);
|
||||
|
||||
val = tr32(offset);
|
||||
|
||||
/* Test the read-only and read/write bits. */
|
||||
if (((val & read_mask) != read_val) || (val & write_mask))
|
||||
goto out;
|
||||
|
||||
/* Write ones to all the bits defined by RdMask and WrMask, then
|
||||
* make sure the read-only bits are not changed and the
|
||||
* read/write bits are all ones.
|
||||
*/
|
||||
tw32(offset, read_mask | write_mask);
|
||||
|
||||
val = tr32(offset);
|
||||
|
||||
/* Test the read-only bits. */
|
||||
if ((val & read_mask) != read_val)
|
||||
goto out;
|
||||
|
||||
/* Test the read/write bits. */
|
||||
if ((val & write_mask) != write_mask)
|
||||
goto out;
|
||||
|
||||
tw32(offset, save_val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
printk(KERN_ERR PFX "Register test failed at offset %x\n", offset);
|
||||
tw32(offset, save_val);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len)
|
||||
{
|
||||
static u32 test_pattern[] = { 0x00000000, 0xffffffff, 0xaa55a55a };
|
||||
int i;
|
||||
u32 j;
|
||||
|
||||
for (i = 0; i < sizeof(test_pattern)/sizeof(u32); i++) {
|
||||
for (j = 0; j < len; j += 4) {
|
||||
u32 val;
|
||||
|
||||
tg3_write_mem(tp, offset + j, test_pattern[i]);
|
||||
tg3_read_mem(tp, offset + j, &val);
|
||||
if (val != test_pattern[i])
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tg3_test_memory(struct tg3 *tp)
|
||||
{
|
||||
static struct mem_entry {
|
||||
u32 offset;
|
||||
u32 len;
|
||||
} mem_tbl_570x[] = {
|
||||
{ 0x00000000, 0x01000},
|
||||
{ 0x00002000, 0x1c000},
|
||||
{ 0xffffffff, 0x00000}
|
||||
}, mem_tbl_5705[] = {
|
||||
{ 0x00000100, 0x0000c},
|
||||
{ 0x00000200, 0x00008},
|
||||
{ 0x00000b50, 0x00400},
|
||||
{ 0x00004000, 0x00800},
|
||||
{ 0x00006000, 0x01000},
|
||||
{ 0x00008000, 0x02000},
|
||||
{ 0x00010000, 0x0e000},
|
||||
{ 0xffffffff, 0x00000}
|
||||
};
|
||||
struct mem_entry *mem_tbl;
|
||||
int err = 0;
|
||||
int i;
|
||||
|
||||
if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
|
||||
mem_tbl = mem_tbl_5705;
|
||||
else
|
||||
mem_tbl = mem_tbl_570x;
|
||||
|
||||
for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) {
|
||||
if ((err = tg3_do_mem_test(tp, mem_tbl[i].offset,
|
||||
mem_tbl[i].len)) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tg3_test_loopback(struct tg3 *tp)
|
||||
{
|
||||
u32 mac_mode, send_idx, rx_start_idx, rx_idx, tx_idx, opaque_key;
|
||||
u32 desc_idx;
|
||||
struct sk_buff *skb, *rx_skb;
|
||||
u8 *tx_data;
|
||||
dma_addr_t map;
|
||||
int num_pkts, tx_len, rx_len, i, err;
|
||||
struct tg3_rx_buffer_desc *desc;
|
||||
|
||||
if (!netif_running(tp->dev))
|
||||
return -ENODEV;
|
||||
|
||||
err = -EIO;
|
||||
|
||||
tg3_abort_hw(tp, 1);
|
||||
|
||||
/* Clearing this flag to keep interrupts disabled */
|
||||
tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
|
||||
tg3_reset_hw(tp);
|
||||
|
||||
mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
|
||||
MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
|
||||
MAC_MODE_PORT_MODE_GMII;
|
||||
tw32(MAC_MODE, mac_mode);
|
||||
|
||||
tx_len = 1514;
|
||||
skb = dev_alloc_skb(tx_len);
|
||||
tx_data = skb_put(skb, tx_len);
|
||||
memcpy(tx_data, tp->dev->dev_addr, 6);
|
||||
memset(tx_data + 6, 0x0, 8);
|
||||
|
||||
tw32(MAC_RX_MTU_SIZE, tx_len + 4);
|
||||
|
||||
for (i = 14; i < tx_len; i++)
|
||||
tx_data[i] = (u8) (i & 0xff);
|
||||
|
||||
map = pci_map_single(tp->pdev, skb->data, tx_len, PCI_DMA_TODEVICE);
|
||||
|
||||
tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
|
||||
HOSTCC_MODE_NOW);
|
||||
|
||||
udelay(10);
|
||||
|
||||
rx_start_idx = tp->hw_status->idx[0].rx_producer;
|
||||
|
||||
send_idx = 0;
|
||||
num_pkts = 0;
|
||||
|
||||
tg3_set_txd(tp, send_idx, map, tx_len, 0, 1);
|
||||
|
||||
send_idx++;
|
||||
num_pkts++;
|
||||
|
||||
tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, send_idx);
|
||||
tr32(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW);
|
||||
|
||||
udelay(10);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
|
||||
HOSTCC_MODE_NOW);
|
||||
|
||||
udelay(10);
|
||||
|
||||
tx_idx = tp->hw_status->idx[0].tx_consumer;
|
||||
rx_idx = tp->hw_status->idx[0].rx_producer;
|
||||
if ((tx_idx == send_idx) &&
|
||||
(rx_idx == (rx_start_idx + num_pkts)))
|
||||
break;
|
||||
}
|
||||
|
||||
pci_unmap_single(tp->pdev, map, tx_len, PCI_DMA_TODEVICE);
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
if (tx_idx != send_idx)
|
||||
goto out;
|
||||
|
||||
if (rx_idx != rx_start_idx + num_pkts)
|
||||
goto out;
|
||||
|
||||
desc = &tp->rx_rcb[rx_start_idx];
|
||||
desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
|
||||
opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
|
||||
if (opaque_key != RXD_OPAQUE_RING_STD)
|
||||
goto out;
|
||||
|
||||
if ((desc->err_vlan & RXD_ERR_MASK) != 0 &&
|
||||
(desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII))
|
||||
goto out;
|
||||
|
||||
rx_len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4;
|
||||
if (rx_len != tx_len)
|
||||
goto out;
|
||||
|
||||
rx_skb = tp->rx_std_buffers[desc_idx].skb;
|
||||
|
||||
map = pci_unmap_addr(&tp->rx_std_buffers[desc_idx], mapping);
|
||||
pci_dma_sync_single_for_cpu(tp->pdev, map, rx_len, PCI_DMA_FROMDEVICE);
|
||||
|
||||
for (i = 14; i < tx_len; i++) {
|
||||
if (*(rx_skb->data + i) != (u8) (i & 0xff))
|
||||
goto out;
|
||||
}
|
||||
err = 0;
|
||||
|
||||
/* tg3_free_rings will unmap and free the rx_skb */
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
|
||||
u64 *data)
|
||||
{
|
||||
struct tg3 *tp = netdev_priv(dev);
|
||||
|
||||
memset(data, 0, sizeof(u64) * TG3_NUM_TEST);
|
||||
|
||||
if (tg3_test_nvram(tp) != 0) {
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
data[0] = 1;
|
||||
}
|
||||
if (tg3_test_link(tp) != 0) {
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
data[1] = 1;
|
||||
}
|
||||
if (etest->flags & ETH_TEST_FL_OFFLINE) {
|
||||
if (netif_running(dev))
|
||||
tg3_netif_stop(tp);
|
||||
|
||||
spin_lock_irq(&tp->lock);
|
||||
spin_lock(&tp->tx_lock);
|
||||
|
||||
tg3_halt(tp, RESET_KIND_SUSPEND, 1);
|
||||
tg3_nvram_lock(tp);
|
||||
tg3_halt_cpu(tp, RX_CPU_BASE);
|
||||
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
|
||||
tg3_halt_cpu(tp, TX_CPU_BASE);
|
||||
tg3_nvram_unlock(tp);
|
||||
|
||||
if (tg3_test_registers(tp) != 0) {
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
data[2] = 1;
|
||||
}
|
||||
if (tg3_test_memory(tp) != 0) {
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
data[3] = 1;
|
||||
}
|
||||
if (tg3_test_loopback(tp) != 0) {
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
data[4] = 1;
|
||||
}
|
||||
|
||||
spin_unlock(&tp->tx_lock);
|
||||
spin_unlock_irq(&tp->lock);
|
||||
if (tg3_test_interrupt(tp) != 0) {
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
data[5] = 1;
|
||||
}
|
||||
spin_lock_irq(&tp->lock);
|
||||
spin_lock(&tp->tx_lock);
|
||||
|
||||
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
||||
if (netif_running(dev)) {
|
||||
tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
|
||||
tg3_init_hw(tp);
|
||||
tg3_netif_start(tp);
|
||||
}
|
||||
spin_unlock(&tp->tx_lock);
|
||||
spin_unlock_irq(&tp->lock);
|
||||
}
|
||||
}
|
||||
|
||||
static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
struct mii_ioctl_data *data = if_mii(ifr);
|
||||
|
@ -7331,6 +7870,8 @@ static struct ethtool_ops tg3_ethtool_ops = {
|
|||
.get_tso = ethtool_op_get_tso,
|
||||
.set_tso = tg3_set_tso,
|
||||
#endif
|
||||
.self_test_count = tg3_get_test_count,
|
||||
.self_test = tg3_self_test,
|
||||
.get_strings = tg3_get_strings,
|
||||
.get_stats_count = tg3_get_stats_count,
|
||||
.get_ethtool_stats = tg3_get_ethtool_stats,
|
||||
|
@ -9478,7 +10019,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
|
|||
(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
|
||||
pci_save_state(tp->pdev);
|
||||
tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
|
||||
tg3_halt(tp, 1);
|
||||
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
||||
}
|
||||
|
||||
err = tg3_test_dma(tp);
|
||||
|
@ -9605,7 +10146,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
|
|||
|
||||
spin_lock_irq(&tp->lock);
|
||||
spin_lock(&tp->tx_lock);
|
||||
tg3_halt(tp, 1);
|
||||
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
||||
spin_unlock(&tp->tx_lock);
|
||||
spin_unlock_irq(&tp->lock);
|
||||
|
||||
|
|
|
@ -193,6 +193,12 @@ static int aui[MAX_TLAN_BOARDS];
|
|||
static int duplex[MAX_TLAN_BOARDS];
|
||||
static int speed[MAX_TLAN_BOARDS];
|
||||
static int boards_found;
|
||||
module_param_array(aui, int, NULL, 0);
|
||||
module_param_array(duplex, int, NULL, 0);
|
||||
module_param_array(speed, int, NULL, 0);
|
||||
MODULE_PARM_DESC(aui, "ThunderLAN use AUI port(s) (0-1)");
|
||||
MODULE_PARM_DESC(duplex, "ThunderLAN duplex setting(s) (0-default, 1-half, 2-full)");
|
||||
MODULE_PARM_DESC(speed, "ThunderLAN port speen setting(s) (0,10,100)");
|
||||
|
||||
MODULE_AUTHOR("Maintainer: Samuel Chessman <chessman@tux.org>");
|
||||
MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters");
|
||||
|
@ -204,8 +210,13 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
/* Turn on debugging. See Documentation/networking/tlan.txt for details */
|
||||
static int debug;
|
||||
module_param(debug, int, 0);
|
||||
MODULE_PARM_DESC(debug, "ThunderLAN debug mask");
|
||||
|
||||
static int bbuf;
|
||||
module_param(bbuf, int, 0);
|
||||
MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)");
|
||||
|
||||
static u8 *TLanPadBuffer;
|
||||
static dma_addr_t TLanPadBufferDMA;
|
||||
static char TLanSignature[] = "TLAN";
|
||||
|
@ -2381,6 +2392,7 @@ TLan_FinishReset( struct net_device *dev )
|
|||
TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_FINISH_RESET );
|
||||
return;
|
||||
}
|
||||
TLan_SetMulticastList(dev);
|
||||
|
||||
} /* TLan_FinishReset */
|
||||
|
||||
|
|
|
@ -754,7 +754,7 @@ typedef struct {
|
|||
u8 zero;
|
||||
u8 ssidLen;
|
||||
u8 ssid[32];
|
||||
u16 rssi;
|
||||
u16 dBm;
|
||||
#define CAP_ESS (1<<0)
|
||||
#define CAP_IBSS (1<<1)
|
||||
#define CAP_PRIVACY (1<<4)
|
||||
|
@ -1125,6 +1125,9 @@ static int micsetup(struct airo_info *ai);
|
|||
static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len);
|
||||
static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen);
|
||||
|
||||
static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi);
|
||||
static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm);
|
||||
|
||||
#include <linux/crypto.h>
|
||||
#endif
|
||||
|
||||
|
@ -1713,6 +1716,7 @@ static int readBSSListRid(struct airo_info *ai, int first,
|
|||
list->fh.dwell = le16_to_cpu(list->fh.dwell);
|
||||
list->dsChannel = le16_to_cpu(list->dsChannel);
|
||||
list->atimWindow = le16_to_cpu(list->atimWindow);
|
||||
list->dBm = le16_to_cpu(list->dBm);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -3245,7 +3249,10 @@ badrx:
|
|||
wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;
|
||||
else
|
||||
wstats.level = (hdr.rssi[1] + 321) / 2;
|
||||
wstats.updated = 3;
|
||||
wstats.noise = apriv->wstats.qual.noise;
|
||||
wstats.updated = IW_QUAL_LEVEL_UPDATED
|
||||
| IW_QUAL_QUAL_UPDATED
|
||||
| IW_QUAL_NOISE_UPDATED;
|
||||
/* Update spy records */
|
||||
wireless_spy_update(dev, sa, &wstats);
|
||||
}
|
||||
|
@ -3588,7 +3595,10 @@ void mpi_receive_802_11 (struct airo_info *ai)
|
|||
wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm;
|
||||
else
|
||||
wstats.level = (hdr.rssi[1] + 321) / 2;
|
||||
wstats.updated = 3;
|
||||
wstats.noise = ai->wstats.qual.noise;
|
||||
wstats.updated = IW_QUAL_QUAL_UPDATED
|
||||
| IW_QUAL_LEVEL_UPDATED
|
||||
| IW_QUAL_NOISE_UPDATED;
|
||||
/* Update spy records */
|
||||
wireless_spy_update(ai->dev, sa, &wstats);
|
||||
}
|
||||
|
@ -3679,7 +3689,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
|
|||
status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock);
|
||||
if ( status == SUCCESS ) {
|
||||
if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
|
||||
memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512);
|
||||
memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */
|
||||
}
|
||||
else {
|
||||
if (ai->rssi) {
|
||||
|
@ -5348,7 +5358,7 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
|
|||
(int)BSSList_rid.bssid[5],
|
||||
(int)BSSList_rid.ssidLen,
|
||||
BSSList_rid.ssid,
|
||||
(int)BSSList_rid.rssi);
|
||||
(int)BSSList_rid.dBm);
|
||||
ptr += sprintf(ptr, " channel = %d %s %s %s %s\n",
|
||||
(int)BSSList_rid.dsChannel,
|
||||
BSSList_rid.cap & CAP_ESS ? "ESS" : "",
|
||||
|
@ -5593,6 +5603,29 @@ static void __exit airo_cleanup_module( void )
|
|||
* would not work at all... - Jean II
|
||||
*/
|
||||
|
||||
static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi)
|
||||
{
|
||||
if( !rssi_rid )
|
||||
return 0;
|
||||
|
||||
return (0x100 - rssi_rid[rssi].rssidBm);
|
||||
}
|
||||
|
||||
static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm)
|
||||
{
|
||||
int i;
|
||||
|
||||
if( !rssi_rid )
|
||||
return 0;
|
||||
|
||||
for( i = 0; i < 256; i++ )
|
||||
if (rssi_rid[i].rssidBm == dbm)
|
||||
return rssi_rid[i].rssipct;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
|
||||
{
|
||||
int quality = 0;
|
||||
|
@ -6443,12 +6476,30 @@ static int airo_get_range(struct net_device *dev,
|
|||
}
|
||||
range->num_frequency = k;
|
||||
|
||||
/* Hum... Should put the right values there */
|
||||
range->max_qual.qual = airo_get_max_quality(&cap_rid);
|
||||
range->max_qual.level = 0x100 - 120; /* -120 dBm */
|
||||
range->max_qual.noise = 0;
|
||||
range->sensitivity = 65535;
|
||||
|
||||
/* Hum... Should put the right values there */
|
||||
if (local->rssi)
|
||||
range->max_qual.qual = 100; /* % */
|
||||
else
|
||||
range->max_qual.qual = airo_get_max_quality(&cap_rid);
|
||||
range->max_qual.level = 0; /* 0 means we use dBm */
|
||||
range->max_qual.noise = 0;
|
||||
range->max_qual.updated = 0;
|
||||
|
||||
/* Experimental measurements - boundary 11/5.5 Mb/s */
|
||||
/* Note : with or without the (local->rssi), results
|
||||
* are somewhat different. - Jean II */
|
||||
if (local->rssi) {
|
||||
range->avg_qual.qual = 50; /* % */
|
||||
range->avg_qual.level = 186; /* -70 dBm */
|
||||
} else {
|
||||
range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
|
||||
range->avg_qual.level = 176; /* -80 dBm */
|
||||
}
|
||||
range->avg_qual.noise = 0;
|
||||
range->avg_qual.updated = 0;
|
||||
|
||||
for(i = 0 ; i < 8 ; i++) {
|
||||
range->bitrate[i] = cap_rid.supportedRates[i] * 500000;
|
||||
if(range->bitrate[i] == 0)
|
||||
|
@ -6508,15 +6559,6 @@ static int airo_get_range(struct net_device *dev,
|
|||
range->max_retry = 65535;
|
||||
range->min_r_time = 1024;
|
||||
range->max_r_time = 65535 * 1024;
|
||||
/* Experimental measurements - boundary 11/5.5 Mb/s */
|
||||
/* Note : with or without the (local->rssi), results
|
||||
* are somewhat different. - Jean II */
|
||||
range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
|
||||
if (local->rssi)
|
||||
range->avg_qual.level = 186; /* -70 dBm */
|
||||
else
|
||||
range->avg_qual.level = 176; /* -80 dBm */
|
||||
range->avg_qual.noise = 0;
|
||||
|
||||
/* Event capability (kernel + driver) */
|
||||
range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
|
||||
|
@ -6676,12 +6718,18 @@ static int airo_get_aplist(struct net_device *dev,
|
|||
loseSync = 0;
|
||||
memcpy(address[i].sa_data, BSSList.bssid, ETH_ALEN);
|
||||
address[i].sa_family = ARPHRD_ETHER;
|
||||
if (local->rssi)
|
||||
qual[i].level = 0x100 - local->rssi[BSSList.rssi].rssidBm;
|
||||
else
|
||||
qual[i].level = (BSSList.rssi + 321) / 2;
|
||||
qual[i].qual = qual[i].noise = 0;
|
||||
qual[i].updated = 2;
|
||||
if (local->rssi) {
|
||||
qual[i].level = 0x100 - BSSList.dBm;
|
||||
qual[i].qual = airo_dbm_to_pct( local->rssi, BSSList.dBm );
|
||||
qual[i].updated = IW_QUAL_QUAL_UPDATED;
|
||||
} else {
|
||||
qual[i].level = (BSSList.dBm + 321) / 2;
|
||||
qual[i].qual = 0;
|
||||
qual[i].updated = IW_QUAL_QUAL_INVALID;
|
||||
}
|
||||
qual[i].noise = local->wstats.qual.noise;
|
||||
qual[i].updated = IW_QUAL_LEVEL_UPDATED
|
||||
| IW_QUAL_NOISE_UPDATED;
|
||||
if (BSSList.index == 0xffff)
|
||||
break;
|
||||
}
|
||||
|
@ -6760,7 +6808,7 @@ static int airo_set_scan(struct net_device *dev,
|
|||
static inline char *airo_translate_scan(struct net_device *dev,
|
||||
char *current_ev,
|
||||
char *end_buf,
|
||||
BSSListRid *list)
|
||||
BSSListRid *bss)
|
||||
{
|
||||
struct airo_info *ai = dev->priv;
|
||||
struct iw_event iwe; /* Temporary buffer */
|
||||
|
@ -6771,22 +6819,22 @@ static inline char *airo_translate_scan(struct net_device *dev,
|
|||
/* First entry *MUST* be the AP MAC address */
|
||||
iwe.cmd = SIOCGIWAP;
|
||||
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
|
||||
memcpy(iwe.u.ap_addr.sa_data, list->bssid, ETH_ALEN);
|
||||
memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
|
||||
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
|
||||
|
||||
/* Other entries will be displayed in the order we give them */
|
||||
|
||||
/* Add the ESSID */
|
||||
iwe.u.data.length = list->ssidLen;
|
||||
iwe.u.data.length = bss->ssidLen;
|
||||
if(iwe.u.data.length > 32)
|
||||
iwe.u.data.length = 32;
|
||||
iwe.cmd = SIOCGIWESSID;
|
||||
iwe.u.data.flags = 1;
|
||||
current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid);
|
||||
current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid);
|
||||
|
||||
/* Add mode */
|
||||
iwe.cmd = SIOCGIWMODE;
|
||||
capabilities = le16_to_cpu(list->cap);
|
||||
capabilities = le16_to_cpu(bss->cap);
|
||||
if(capabilities & (CAP_ESS | CAP_IBSS)) {
|
||||
if(capabilities & CAP_ESS)
|
||||
iwe.u.mode = IW_MODE_MASTER;
|
||||
|
@ -6797,19 +6845,25 @@ static inline char *airo_translate_scan(struct net_device *dev,
|
|||
|
||||
/* Add frequency */
|
||||
iwe.cmd = SIOCGIWFREQ;
|
||||
iwe.u.freq.m = le16_to_cpu(list->dsChannel);
|
||||
iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
|
||||
iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000;
|
||||
iwe.u.freq.e = 1;
|
||||
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
|
||||
|
||||
/* Add quality statistics */
|
||||
iwe.cmd = IWEVQUAL;
|
||||
if (ai->rssi)
|
||||
iwe.u.qual.level = 0x100 - ai->rssi[list->rssi].rssidBm;
|
||||
else
|
||||
iwe.u.qual.level = (list->rssi + 321) / 2;
|
||||
iwe.u.qual.noise = 0;
|
||||
iwe.u.qual.qual = 0;
|
||||
if (ai->rssi) {
|
||||
iwe.u.qual.level = 0x100 - bss->dBm;
|
||||
iwe.u.qual.qual = airo_dbm_to_pct( ai->rssi, bss->dBm );
|
||||
iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED;
|
||||
} else {
|
||||
iwe.u.qual.level = (bss->dBm + 321) / 2;
|
||||
iwe.u.qual.qual = 0;
|
||||
iwe.u.qual.updated = IW_QUAL_QUAL_INVALID;
|
||||
}
|
||||
iwe.u.qual.noise = ai->wstats.qual.noise;
|
||||
iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
|
||||
| IW_QUAL_NOISE_UPDATED;
|
||||
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
|
||||
|
||||
/* Add encryption capability */
|
||||
|
@ -6819,7 +6873,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
|
|||
else
|
||||
iwe.u.data.flags = IW_ENCODE_DISABLED;
|
||||
iwe.u.data.length = 0;
|
||||
current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid);
|
||||
current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid);
|
||||
|
||||
/* Rate : stuffing multiple values in a single event require a bit
|
||||
* more of magic - Jean II */
|
||||
|
@ -6831,10 +6885,10 @@ static inline char *airo_translate_scan(struct net_device *dev,
|
|||
/* Max 8 values */
|
||||
for(i = 0 ; i < 8 ; i++) {
|
||||
/* NULL terminated */
|
||||
if(list->rates[i] == 0)
|
||||
if(bss->rates[i] == 0)
|
||||
break;
|
||||
/* Bit rate given in 500 kb/s units (+ 0x80) */
|
||||
iwe.u.bitrate.value = ((list->rates[i] & 0x7f) * 500000);
|
||||
iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000);
|
||||
/* Add new value to event */
|
||||
current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
|
||||
}
|
||||
|
@ -7153,18 +7207,22 @@ static void airo_read_wireless_stats(struct airo_info *local)
|
|||
/* The status */
|
||||
local->wstats.status = status_rid.mode;
|
||||
|
||||
/* Signal quality and co. But where is the noise level ??? */
|
||||
local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
|
||||
if (local->rssi)
|
||||
local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm;
|
||||
else
|
||||
/* Signal quality and co */
|
||||
if (local->rssi) {
|
||||
local->wstats.qual.level = airo_rssi_to_dbm( local->rssi, status_rid.sigQuality );
|
||||
/* normalizedSignalStrength appears to be a percentage */
|
||||
local->wstats.qual.qual = status_rid.normalizedSignalStrength;
|
||||
} else {
|
||||
local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
|
||||
local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
|
||||
}
|
||||
local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED;
|
||||
if (status_rid.len >= 124) {
|
||||
local->wstats.qual.noise = 256 - status_rid.noisedBm;
|
||||
local->wstats.qual.updated = 7;
|
||||
local->wstats.qual.noise = 0x100 - status_rid.noisedBm;
|
||||
local->wstats.qual.updated |= IW_QUAL_NOISE_UPDATED;
|
||||
} else {
|
||||
local->wstats.qual.noise = 0;
|
||||
local->wstats.qual.updated = 3;
|
||||
local->wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
|
||||
}
|
||||
|
||||
/* Packets discarded in the wireless adapter due to wireless
|
||||
|
|
|
@ -321,6 +321,7 @@ static struct {
|
|||
{ 0x01bf, 0x3302, NULL, ATMEL_FW_TYPE_502E, "Belkin F5D6020-V2" },
|
||||
{ 0, 0, "BT/Voyager 1020 Laptop Adapter", ATMEL_FW_TYPE_502, "BT Voyager 1020" },
|
||||
{ 0, 0, "IEEE 802.11b/Wireless LAN PC Card", ATMEL_FW_TYPE_502, "Siemens Gigaset PC Card II" },
|
||||
{ 0, 0, "IEEE 802.11b/Wireless LAN Card S", ATMEL_FW_TYPE_504_2958, "Siemens Gigaset PC Card II" },
|
||||
{ 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", ATMEL_FW_TYPE_502E, "CNet CNWLC-811ARL" },
|
||||
{ 0, 0, "Wireless/PC_CARD", ATMEL_FW_TYPE_502D, "Planet WL-3552" },
|
||||
{ 0, 0, "OEM/11Mbps Wireless LAN PC Card V-3", ATMEL_FW_TYPE_502, "OEM 11Mbps WLAN PCMCIA Card" },
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/acpi.h>
|
||||
#include "pci.h"
|
||||
|
||||
/* Deal with broken BIOS'es that neglect to enable passive release,
|
||||
|
@ -467,9 +468,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC,
|
|||
* non-x86 architectures (yes Via exists on PPC among other places),
|
||||
* we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
|
||||
* interrupts delivered properly.
|
||||
*
|
||||
* TODO: When we have device-specific interrupt routers,
|
||||
* quirk_via_irqpic will go away from quirks.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -494,6 +492,29 @@ static void __devinit quirk_via_acpi(struct pci_dev *d)
|
|||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi );
|
||||
|
||||
static void quirk_via_irqpic(struct pci_dev *dev)
|
||||
{
|
||||
u8 irq, new_irq;
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
if (nr_ioapics && !skip_ioapic_setup)
|
||||
return;
|
||||
#endif
|
||||
#ifdef CONFIG_ACPI
|
||||
if (acpi_irq_model != ACPI_IRQ_MODEL_PIC)
|
||||
return;
|
||||
#endif
|
||||
new_irq = dev->irq & 0xf;
|
||||
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
|
||||
if (new_irq != irq) {
|
||||
printk(KERN_INFO "PCI: Via PIC IRQ fixup for %s, from %d to %d\n",
|
||||
pci_name(dev), irq, new_irq);
|
||||
udelay(15); /* unknown if delay really needed */
|
||||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irqpic);
|
||||
|
||||
/*
|
||||
* PIIX3 USB: We have to disable USB interrupts that are
|
||||
* hardwired to PIRQD# and may be shared with an
|
||||
|
@ -683,19 +704,6 @@ static void __init quirk_disable_pxb(struct pci_dev *pdev)
|
|||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb );
|
||||
|
||||
/*
|
||||
* VIA northbridges care about PCI_INTERRUPT_LINE
|
||||
*/
|
||||
int via_interrupt_line_quirk;
|
||||
|
||||
static void __devinit quirk_via_bridge(struct pci_dev *pdev)
|
||||
{
|
||||
if(pdev->devfn == 0) {
|
||||
printk(KERN_INFO "PCI: Via IRQ fixup\n");
|
||||
via_interrupt_line_quirk = 1;
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_bridge );
|
||||
|
||||
/*
|
||||
* Serverworks CSB5 IDE does not fully support native mode
|
||||
|
|
|
@ -9,6 +9,7 @@ obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
|
|||
obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
|
||||
obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
|
||||
obj-$(CONFIG_LCS) += lcs.o cu3088.o
|
||||
qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o qeth_tso.o
|
||||
obj-$(CONFIG_CLAW) += claw.o cu3088.o
|
||||
qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o
|
||||
qeth-$(CONFIG_PROC_FS) += qeth_proc.o
|
||||
obj-$(CONFIG_QETH) += qeth.o
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* linux/drivers/s390/net/ctcdbug.h ($Revision: 1.4 $)
|
||||
* linux/drivers/s390/net/ctcdbug.h ($Revision: 1.5 $)
|
||||
*
|
||||
* CTC / ESCON network driver - s390 dbf exploit.
|
||||
*
|
||||
|
@ -9,7 +9,7 @@
|
|||
* Author(s): Original Code written by
|
||||
* Peter Tiedemann (ptiedem@de.ibm.com)
|
||||
*
|
||||
* $Revision: 1.4 $ $Date: 2004/10/15 09:26:58 $
|
||||
* $Revision: 1.5 $ $Date: 2005/02/27 19:46:44 $
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -25,9 +25,11 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _CTCDBUG_H_
|
||||
#define _CTCDBUG_H_
|
||||
|
||||
#include <asm/debug.h>
|
||||
#include "ctcmain.h"
|
||||
/**
|
||||
* Debug Facility stuff
|
||||
*/
|
||||
|
@ -41,7 +43,7 @@
|
|||
#define CTC_DBF_DATA_LEN 128
|
||||
#define CTC_DBF_DATA_INDEX 3
|
||||
#define CTC_DBF_DATA_NR_AREAS 1
|
||||
#define CTC_DBF_DATA_LEVEL 2
|
||||
#define CTC_DBF_DATA_LEVEL 3
|
||||
|
||||
#define CTC_DBF_TRACE_NAME "ctc_trace"
|
||||
#define CTC_DBF_TRACE_LEN 16
|
||||
|
@ -121,3 +123,5 @@ hex_dump(unsigned char *buf, size_t len)
|
|||
printk("\n");
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* $Id: ctcmain.c,v 1.72 2005/03/17 10:51:52 ptiedem Exp $
|
||||
* $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $
|
||||
*
|
||||
* CTC / ESCON network driver
|
||||
*
|
||||
|
@ -37,12 +37,11 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* RELEASE-TAG: CTC/ESCON network driver $Revision: 1.72 $
|
||||
* RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $
|
||||
*
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -74,288 +73,13 @@
|
|||
#include "ctctty.h"
|
||||
#include "fsm.h"
|
||||
#include "cu3088.h"
|
||||
|
||||
#include "ctcdbug.h"
|
||||
#include "ctcmain.h"
|
||||
|
||||
MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
|
||||
MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/**
|
||||
* CCW commands, used in this driver.
|
||||
*/
|
||||
#define CCW_CMD_WRITE 0x01
|
||||
#define CCW_CMD_READ 0x02
|
||||
#define CCW_CMD_SET_EXTENDED 0xc3
|
||||
#define CCW_CMD_PREPARE 0xe3
|
||||
|
||||
#define CTC_PROTO_S390 0
|
||||
#define CTC_PROTO_LINUX 1
|
||||
#define CTC_PROTO_LINUX_TTY 2
|
||||
#define CTC_PROTO_OS390 3
|
||||
#define CTC_PROTO_MAX 3
|
||||
|
||||
#define CTC_BUFSIZE_LIMIT 65535
|
||||
#define CTC_BUFSIZE_DEFAULT 32768
|
||||
|
||||
#define CTC_TIMEOUT_5SEC 5000
|
||||
|
||||
#define CTC_INITIAL_BLOCKLEN 2
|
||||
|
||||
#define READ 0
|
||||
#define WRITE 1
|
||||
|
||||
#define CTC_ID_SIZE BUS_ID_SIZE+3
|
||||
|
||||
|
||||
struct ctc_profile {
|
||||
unsigned long maxmulti;
|
||||
unsigned long maxcqueue;
|
||||
unsigned long doios_single;
|
||||
unsigned long doios_multi;
|
||||
unsigned long txlen;
|
||||
unsigned long tx_time;
|
||||
struct timespec send_stamp;
|
||||
};
|
||||
|
||||
/**
|
||||
* Definition of one channel
|
||||
*/
|
||||
struct channel {
|
||||
|
||||
/**
|
||||
* Pointer to next channel in list.
|
||||
*/
|
||||
struct channel *next;
|
||||
char id[CTC_ID_SIZE];
|
||||
struct ccw_device *cdev;
|
||||
|
||||
/**
|
||||
* Type of this channel.
|
||||
* CTC/A or Escon for valid channels.
|
||||
*/
|
||||
enum channel_types type;
|
||||
|
||||
/**
|
||||
* Misc. flags. See CHANNEL_FLAGS_... below
|
||||
*/
|
||||
__u32 flags;
|
||||
|
||||
/**
|
||||
* The protocol of this channel
|
||||
*/
|
||||
__u16 protocol;
|
||||
|
||||
/**
|
||||
* I/O and irq related stuff
|
||||
*/
|
||||
struct ccw1 *ccw;
|
||||
struct irb *irb;
|
||||
|
||||
/**
|
||||
* RX/TX buffer size
|
||||
*/
|
||||
int max_bufsize;
|
||||
|
||||
/**
|
||||
* Transmit/Receive buffer.
|
||||
*/
|
||||
struct sk_buff *trans_skb;
|
||||
|
||||
/**
|
||||
* Universal I/O queue.
|
||||
*/
|
||||
struct sk_buff_head io_queue;
|
||||
|
||||
/**
|
||||
* TX queue for collecting skb's during busy.
|
||||
*/
|
||||
struct sk_buff_head collect_queue;
|
||||
|
||||
/**
|
||||
* Amount of data in collect_queue.
|
||||
*/
|
||||
int collect_len;
|
||||
|
||||
/**
|
||||
* spinlock for collect_queue and collect_len
|
||||
*/
|
||||
spinlock_t collect_lock;
|
||||
|
||||
/**
|
||||
* Timer for detecting unresposive
|
||||
* I/O operations.
|
||||
*/
|
||||
fsm_timer timer;
|
||||
|
||||
/**
|
||||
* Retry counter for misc. operations.
|
||||
*/
|
||||
int retry;
|
||||
|
||||
/**
|
||||
* The finite state machine of this channel
|
||||
*/
|
||||
fsm_instance *fsm;
|
||||
|
||||
/**
|
||||
* The corresponding net_device this channel
|
||||
* belongs to.
|
||||
*/
|
||||
struct net_device *netdev;
|
||||
|
||||
struct ctc_profile prof;
|
||||
|
||||
unsigned char *trans_skb_data;
|
||||
|
||||
__u16 logflags;
|
||||
};
|
||||
|
||||
#define CHANNEL_FLAGS_READ 0
|
||||
#define CHANNEL_FLAGS_WRITE 1
|
||||
#define CHANNEL_FLAGS_INUSE 2
|
||||
#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4
|
||||
#define CHANNEL_FLAGS_FAILED 8
|
||||
#define CHANNEL_FLAGS_WAITIRQ 16
|
||||
#define CHANNEL_FLAGS_RWMASK 1
|
||||
#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
|
||||
|
||||
#define LOG_FLAG_ILLEGALPKT 1
|
||||
#define LOG_FLAG_ILLEGALSIZE 2
|
||||
#define LOG_FLAG_OVERRUN 4
|
||||
#define LOG_FLAG_NOMEM 8
|
||||
|
||||
#define CTC_LOGLEVEL_INFO 1
|
||||
#define CTC_LOGLEVEL_NOTICE 2
|
||||
#define CTC_LOGLEVEL_WARN 4
|
||||
#define CTC_LOGLEVEL_EMERG 8
|
||||
#define CTC_LOGLEVEL_ERR 16
|
||||
#define CTC_LOGLEVEL_DEBUG 32
|
||||
#define CTC_LOGLEVEL_CRIT 64
|
||||
|
||||
#define CTC_LOGLEVEL_DEFAULT \
|
||||
(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT)
|
||||
|
||||
#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1)
|
||||
|
||||
static int loglevel = CTC_LOGLEVEL_DEFAULT;
|
||||
|
||||
#define ctc_pr_debug(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0)
|
||||
|
||||
#define ctc_pr_info(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0)
|
||||
|
||||
#define ctc_pr_notice(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0)
|
||||
|
||||
#define ctc_pr_warn(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0)
|
||||
|
||||
#define ctc_pr_emerg(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0)
|
||||
|
||||
#define ctc_pr_err(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0)
|
||||
|
||||
#define ctc_pr_crit(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0)
|
||||
|
||||
/**
|
||||
* Linked list of all detected channels.
|
||||
*/
|
||||
static struct channel *channels = NULL;
|
||||
|
||||
struct ctc_priv {
|
||||
struct net_device_stats stats;
|
||||
unsigned long tbusy;
|
||||
/**
|
||||
* The finite state machine of this interface.
|
||||
*/
|
||||
fsm_instance *fsm;
|
||||
/**
|
||||
* The protocol of this device
|
||||
*/
|
||||
__u16 protocol;
|
||||
/**
|
||||
* Timer for restarting after I/O Errors
|
||||
*/
|
||||
fsm_timer restart_timer;
|
||||
|
||||
int buffer_size;
|
||||
|
||||
struct channel *channel[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* Definition of our link level header.
|
||||
*/
|
||||
struct ll_header {
|
||||
__u16 length;
|
||||
__u16 type;
|
||||
__u16 unused;
|
||||
};
|
||||
#define LL_HEADER_LENGTH (sizeof(struct ll_header))
|
||||
|
||||
/**
|
||||
* Compatibility macros for busy handling
|
||||
* of network devices.
|
||||
*/
|
||||
static __inline__ void
|
||||
ctc_clear_busy(struct net_device * dev)
|
||||
{
|
||||
clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
|
||||
if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
ctc_test_and_set_busy(struct net_device * dev)
|
||||
{
|
||||
if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
|
||||
netif_stop_queue(dev);
|
||||
return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print Banner.
|
||||
*/
|
||||
static void
|
||||
print_banner(void)
|
||||
{
|
||||
static int printed = 0;
|
||||
char vbuf[] = "$Revision: 1.72 $";
|
||||
char *version = vbuf;
|
||||
|
||||
if (printed)
|
||||
return;
|
||||
if ((version = strchr(version, ':'))) {
|
||||
char *p = strchr(version + 1, '$');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
} else
|
||||
version = " ??? ";
|
||||
printk(KERN_INFO "CTC driver Version%s"
|
||||
#ifdef DEBUG
|
||||
" (DEBUG-VERSION, " __DATE__ __TIME__ ")"
|
||||
#endif
|
||||
" initialized\n", version);
|
||||
printed = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return type of a detected device.
|
||||
*/
|
||||
static enum channel_types
|
||||
get_channel_type(struct ccw_device_id *id)
|
||||
{
|
||||
enum channel_types type = (enum channel_types) id->driver_info;
|
||||
|
||||
if (type == channel_type_ficon)
|
||||
type = channel_type_escon;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* States of the interface statemachine.
|
||||
*/
|
||||
|
@ -371,7 +95,7 @@ enum dev_states {
|
|||
/**
|
||||
* MUST be always the last element!!
|
||||
*/
|
||||
NR_DEV_STATES
|
||||
CTC_NR_DEV_STATES
|
||||
};
|
||||
|
||||
static const char *dev_state_names[] = {
|
||||
|
@ -399,7 +123,7 @@ enum dev_events {
|
|||
/**
|
||||
* MUST be always the last element!!
|
||||
*/
|
||||
NR_DEV_EVENTS
|
||||
CTC_NR_DEV_EVENTS
|
||||
};
|
||||
|
||||
static const char *dev_event_names[] = {
|
||||
|
@ -476,40 +200,6 @@ enum ch_events {
|
|||
NR_CH_EVENTS,
|
||||
};
|
||||
|
||||
static const char *ch_event_names[] = {
|
||||
"ccw_device success",
|
||||
"ccw_device busy",
|
||||
"ccw_device enodev",
|
||||
"ccw_device ioerr",
|
||||
"ccw_device unknown",
|
||||
|
||||
"Status ATTN & BUSY",
|
||||
"Status ATTN",
|
||||
"Status BUSY",
|
||||
|
||||
"Unit check remote reset",
|
||||
"Unit check remote system reset",
|
||||
"Unit check TX timeout",
|
||||
"Unit check TX parity",
|
||||
"Unit check Hardware failure",
|
||||
"Unit check RX parity",
|
||||
"Unit check ZERO",
|
||||
"Unit check Unknown",
|
||||
|
||||
"SubChannel check Unknown",
|
||||
|
||||
"Machine check failure",
|
||||
"Machine check operational",
|
||||
|
||||
"IRQ normal",
|
||||
"IRQ final",
|
||||
|
||||
"Timer",
|
||||
|
||||
"Start",
|
||||
"Stop",
|
||||
};
|
||||
|
||||
/**
|
||||
* States of the channel statemachine.
|
||||
*/
|
||||
|
@ -545,6 +235,87 @@ enum ch_states {
|
|||
NR_CH_STATES,
|
||||
};
|
||||
|
||||
static int loglevel = CTC_LOGLEVEL_DEFAULT;
|
||||
|
||||
/**
|
||||
* Linked list of all detected channels.
|
||||
*/
|
||||
static struct channel *channels = NULL;
|
||||
|
||||
/**
|
||||
* Print Banner.
|
||||
*/
|
||||
static void
|
||||
print_banner(void)
|
||||
{
|
||||
static int printed = 0;
|
||||
char vbuf[] = "$Revision: 1.74 $";
|
||||
char *version = vbuf;
|
||||
|
||||
if (printed)
|
||||
return;
|
||||
if ((version = strchr(version, ':'))) {
|
||||
char *p = strchr(version + 1, '$');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
} else
|
||||
version = " ??? ";
|
||||
printk(KERN_INFO "CTC driver Version%s"
|
||||
#ifdef DEBUG
|
||||
" (DEBUG-VERSION, " __DATE__ __TIME__ ")"
|
||||
#endif
|
||||
" initialized\n", version);
|
||||
printed = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return type of a detected device.
|
||||
*/
|
||||
static enum channel_types
|
||||
get_channel_type(struct ccw_device_id *id)
|
||||
{
|
||||
enum channel_types type = (enum channel_types) id->driver_info;
|
||||
|
||||
if (type == channel_type_ficon)
|
||||
type = channel_type_escon;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static const char *ch_event_names[] = {
|
||||
"ccw_device success",
|
||||
"ccw_device busy",
|
||||
"ccw_device enodev",
|
||||
"ccw_device ioerr",
|
||||
"ccw_device unknown",
|
||||
|
||||
"Status ATTN & BUSY",
|
||||
"Status ATTN",
|
||||
"Status BUSY",
|
||||
|
||||
"Unit check remote reset",
|
||||
"Unit check remote system reset",
|
||||
"Unit check TX timeout",
|
||||
"Unit check TX parity",
|
||||
"Unit check Hardware failure",
|
||||
"Unit check RX parity",
|
||||
"Unit check ZERO",
|
||||
"Unit check Unknown",
|
||||
|
||||
"SubChannel check Unknown",
|
||||
|
||||
"Machine check failure",
|
||||
"Machine check operational",
|
||||
|
||||
"IRQ normal",
|
||||
"IRQ final",
|
||||
|
||||
"Timer",
|
||||
|
||||
"Start",
|
||||
"Stop",
|
||||
};
|
||||
|
||||
static const char *ch_state_names[] = {
|
||||
"Idle",
|
||||
"Stopped",
|
||||
|
@ -1934,7 +1705,6 @@ add_channel(struct ccw_device *cdev, enum channel_types type)
|
|||
ch->cdev = cdev;
|
||||
snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id);
|
||||
ch->type = type;
|
||||
loglevel = CTC_LOGLEVEL_DEFAULT;
|
||||
ch->fsm = init_fsm(ch->id, ch_state_names,
|
||||
ch_event_names, NR_CH_STATES, NR_CH_EVENTS,
|
||||
ch_fsm, CH_FSM_LEN, GFP_KERNEL);
|
||||
|
@ -2697,6 +2467,7 @@ ctc_stats(struct net_device * dev)
|
|||
/*
|
||||
* sysfs attributes
|
||||
*/
|
||||
|
||||
static ssize_t
|
||||
buffer_show(struct device *dev, char *buf)
|
||||
{
|
||||
|
@ -2715,57 +2486,61 @@ buffer_write(struct device *dev, const char *buf, size_t count)
|
|||
struct ctc_priv *priv;
|
||||
struct net_device *ndev;
|
||||
int bs1;
|
||||
char buffer[16];
|
||||
|
||||
DBF_TEXT(trace, 3, __FUNCTION__);
|
||||
DBF_TEXT(trace, 3, buf);
|
||||
priv = dev->driver_data;
|
||||
if (!priv)
|
||||
if (!priv) {
|
||||
DBF_TEXT(trace, 3, "bfnopriv");
|
||||
return -ENODEV;
|
||||
ndev = priv->channel[READ]->netdev;
|
||||
if (!ndev)
|
||||
return -ENODEV;
|
||||
sscanf(buf, "%u", &bs1);
|
||||
}
|
||||
|
||||
sscanf(buf, "%u", &bs1);
|
||||
if (bs1 > CTC_BUFSIZE_LIMIT)
|
||||
return -EINVAL;
|
||||
goto einval;
|
||||
if (bs1 < (576 + LL_HEADER_LENGTH + 2))
|
||||
goto einval;
|
||||
priv->buffer_size = bs1; // just to overwrite the default
|
||||
|
||||
ndev = priv->channel[READ]->netdev;
|
||||
if (!ndev) {
|
||||
DBF_TEXT(trace, 3, "bfnondev");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if ((ndev->flags & IFF_RUNNING) &&
|
||||
(bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
|
||||
return -EINVAL;
|
||||
if (bs1 < (576 + LL_HEADER_LENGTH + 2))
|
||||
return -EINVAL;
|
||||
goto einval;
|
||||
|
||||
priv->buffer_size = bs1;
|
||||
priv->channel[READ]->max_bufsize =
|
||||
priv->channel[WRITE]->max_bufsize = bs1;
|
||||
priv->channel[READ]->max_bufsize = bs1;
|
||||
priv->channel[WRITE]->max_bufsize = bs1;
|
||||
if (!(ndev->flags & IFF_RUNNING))
|
||||
ndev->mtu = bs1 - LL_HEADER_LENGTH - 2;
|
||||
priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
|
||||
priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
|
||||
|
||||
sprintf(buffer, "%d",priv->buffer_size);
|
||||
DBF_TEXT(trace, 3, buffer);
|
||||
return count;
|
||||
|
||||
einval:
|
||||
DBF_TEXT(trace, 3, "buff_err");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
loglevel_show(struct device *dev, char *buf)
|
||||
{
|
||||
struct ctc_priv *priv;
|
||||
|
||||
priv = dev->driver_data;
|
||||
if (!priv)
|
||||
return -ENODEV;
|
||||
return sprintf(buf, "%d\n", loglevel);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
loglevel_write(struct device *dev, const char *buf, size_t count)
|
||||
{
|
||||
struct ctc_priv *priv;
|
||||
int ll1;
|
||||
|
||||
DBF_TEXT(trace, 5, __FUNCTION__);
|
||||
priv = dev->driver_data;
|
||||
if (!priv)
|
||||
return -ENODEV;
|
||||
sscanf(buf, "%i", &ll1);
|
||||
|
||||
if ((ll1 > CTC_LOGLEVEL_MAX) || (ll1 < 0))
|
||||
|
@ -2835,27 +2610,6 @@ stats_write(struct device *dev, const char *buf, size_t count)
|
|||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
|
||||
static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write);
|
||||
static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
|
||||
|
||||
static int
|
||||
ctc_add_attributes(struct device *dev)
|
||||
{
|
||||
// device_create_file(dev, &dev_attr_buffer);
|
||||
device_create_file(dev, &dev_attr_loglevel);
|
||||
device_create_file(dev, &dev_attr_stats);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ctc_remove_attributes(struct device *dev)
|
||||
{
|
||||
device_remove_file(dev, &dev_attr_stats);
|
||||
device_remove_file(dev, &dev_attr_loglevel);
|
||||
// device_remove_file(dev, &dev_attr_buffer);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ctc_netdev_unregister(struct net_device * dev)
|
||||
|
@ -2899,52 +2653,6 @@ ctc_free_netdevice(struct net_device * dev, int free_dev)
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize everything of the net device except the name and the
|
||||
* channel structs.
|
||||
*/
|
||||
static struct net_device *
|
||||
ctc_init_netdevice(struct net_device * dev, int alloc_device,
|
||||
struct ctc_priv *privptr)
|
||||
{
|
||||
if (!privptr)
|
||||
return NULL;
|
||||
|
||||
DBF_TEXT(setup, 3, __FUNCTION__);
|
||||
if (alloc_device) {
|
||||
dev = kmalloc(sizeof (struct net_device), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
memset(dev, 0, sizeof (struct net_device));
|
||||
}
|
||||
|
||||
dev->priv = privptr;
|
||||
privptr->fsm = init_fsm("ctcdev", dev_state_names,
|
||||
dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS,
|
||||
dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
|
||||
if (privptr->fsm == NULL) {
|
||||
if (alloc_device)
|
||||
kfree(dev);
|
||||
return NULL;
|
||||
}
|
||||
fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
|
||||
fsm_settimer(privptr->fsm, &privptr->restart_timer);
|
||||
if (dev->mtu == 0)
|
||||
dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
|
||||
dev->hard_start_xmit = ctc_tx;
|
||||
dev->open = ctc_open;
|
||||
dev->stop = ctc_close;
|
||||
dev->get_stats = ctc_stats;
|
||||
dev->change_mtu = ctc_change_mtu;
|
||||
dev->hard_header_len = LL_HEADER_LENGTH + 2;
|
||||
dev->addr_len = 0;
|
||||
dev->type = ARPHRD_SLIP;
|
||||
dev->tx_queue_len = 100;
|
||||
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
|
||||
SET_MODULE_OWNER(dev);
|
||||
return dev;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
ctc_proto_show(struct device *dev, char *buf)
|
||||
{
|
||||
|
@ -2977,7 +2685,6 @@ ctc_proto_store(struct device *dev, const char *buf, size_t count)
|
|||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(protocol, 0644, ctc_proto_show, ctc_proto_store);
|
||||
|
||||
static ssize_t
|
||||
ctc_type_show(struct device *dev, char *buf)
|
||||
|
@ -2991,8 +2698,13 @@ ctc_type_show(struct device *dev, char *buf)
|
|||
return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
|
||||
static DEVICE_ATTR(protocol, 0644, ctc_proto_show, ctc_proto_store);
|
||||
static DEVICE_ATTR(type, 0444, ctc_type_show, NULL);
|
||||
|
||||
static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write);
|
||||
static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
|
||||
|
||||
static struct attribute *ctc_attr[] = {
|
||||
&dev_attr_protocol.attr,
|
||||
&dev_attr_type.attr,
|
||||
|
@ -3004,6 +2716,21 @@ static struct attribute_group ctc_attr_group = {
|
|||
.attrs = ctc_attr,
|
||||
};
|
||||
|
||||
static int
|
||||
ctc_add_attributes(struct device *dev)
|
||||
{
|
||||
device_create_file(dev, &dev_attr_loglevel);
|
||||
device_create_file(dev, &dev_attr_stats);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ctc_remove_attributes(struct device *dev)
|
||||
{
|
||||
device_remove_file(dev, &dev_attr_stats);
|
||||
device_remove_file(dev, &dev_attr_loglevel);
|
||||
}
|
||||
|
||||
static int
|
||||
ctc_add_files(struct device *dev)
|
||||
{
|
||||
|
@ -3028,15 +2755,15 @@ ctc_remove_files(struct device *dev)
|
|||
*
|
||||
* @returns 0 on success, !0 on failure.
|
||||
*/
|
||||
|
||||
static int
|
||||
ctc_probe_device(struct ccwgroup_device *cgdev)
|
||||
{
|
||||
struct ctc_priv *priv;
|
||||
int rc;
|
||||
char buffer[16];
|
||||
|
||||
pr_debug("%s() called\n", __FUNCTION__);
|
||||
DBF_TEXT(trace, 3, __FUNCTION__);
|
||||
DBF_TEXT(setup, 3, __FUNCTION__);
|
||||
|
||||
if (!get_device(&cgdev->dev))
|
||||
return -ENODEV;
|
||||
|
@ -3060,9 +2787,69 @@ ctc_probe_device(struct ccwgroup_device *cgdev)
|
|||
cgdev->cdev[1]->handler = ctc_irq_handler;
|
||||
cgdev->dev.driver_data = priv;
|
||||
|
||||
sprintf(buffer, "%p", priv);
|
||||
DBF_TEXT(data, 3, buffer);
|
||||
|
||||
sprintf(buffer, "%u", (unsigned int)sizeof(struct ctc_priv));
|
||||
DBF_TEXT(data, 3, buffer);
|
||||
|
||||
sprintf(buffer, "%p", &channels);
|
||||
DBF_TEXT(data, 3, buffer);
|
||||
|
||||
sprintf(buffer, "%u", (unsigned int)sizeof(struct channel));
|
||||
DBF_TEXT(data, 3, buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize everything of the net device except the name and the
|
||||
* channel structs.
|
||||
*/
|
||||
static struct net_device *
|
||||
ctc_init_netdevice(struct net_device * dev, int alloc_device,
|
||||
struct ctc_priv *privptr)
|
||||
{
|
||||
if (!privptr)
|
||||
return NULL;
|
||||
|
||||
DBF_TEXT(setup, 3, __FUNCTION__);
|
||||
|
||||
if (alloc_device) {
|
||||
dev = kmalloc(sizeof (struct net_device), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
memset(dev, 0, sizeof (struct net_device));
|
||||
}
|
||||
|
||||
dev->priv = privptr;
|
||||
privptr->fsm = init_fsm("ctcdev", dev_state_names,
|
||||
dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS,
|
||||
dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
|
||||
if (privptr->fsm == NULL) {
|
||||
if (alloc_device)
|
||||
kfree(dev);
|
||||
return NULL;
|
||||
}
|
||||
fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
|
||||
fsm_settimer(privptr->fsm, &privptr->restart_timer);
|
||||
if (dev->mtu == 0)
|
||||
dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
|
||||
dev->hard_start_xmit = ctc_tx;
|
||||
dev->open = ctc_open;
|
||||
dev->stop = ctc_close;
|
||||
dev->get_stats = ctc_stats;
|
||||
dev->change_mtu = ctc_change_mtu;
|
||||
dev->hard_header_len = LL_HEADER_LENGTH + 2;
|
||||
dev->addr_len = 0;
|
||||
dev->type = ARPHRD_SLIP;
|
||||
dev->tx_queue_len = 100;
|
||||
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
|
||||
SET_MODULE_OWNER(dev);
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Setup an interface.
|
||||
|
@ -3081,6 +2868,7 @@ ctc_new_device(struct ccwgroup_device *cgdev)
|
|||
struct ctc_priv *privptr;
|
||||
struct net_device *dev;
|
||||
int ret;
|
||||
char buffer[16];
|
||||
|
||||
pr_debug("%s() called\n", __FUNCTION__);
|
||||
DBF_TEXT(setup, 3, __FUNCTION__);
|
||||
|
@ -3089,6 +2877,9 @@ ctc_new_device(struct ccwgroup_device *cgdev)
|
|||
if (!privptr)
|
||||
return -ENODEV;
|
||||
|
||||
sprintf(buffer, "%d", privptr->buffer_size);
|
||||
DBF_TEXT(setup, 3, buffer);
|
||||
|
||||
type = get_channel_type(&cgdev->cdev[0]->id);
|
||||
|
||||
snprintf(read_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
|
||||
|
@ -3177,9 +2968,10 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev)
|
|||
struct ctc_priv *priv;
|
||||
struct net_device *ndev;
|
||||
|
||||
DBF_TEXT(trace, 3, __FUNCTION__);
|
||||
DBF_TEXT(setup, 3, __FUNCTION__);
|
||||
pr_debug("%s() called\n", __FUNCTION__);
|
||||
|
||||
|
||||
priv = cgdev->dev.driver_data;
|
||||
ndev = NULL;
|
||||
if (!priv)
|
||||
|
@ -3215,7 +3007,6 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev)
|
|||
channel_remove(priv->channel[READ]);
|
||||
if (priv->channel[WRITE])
|
||||
channel_remove(priv->channel[WRITE]);
|
||||
|
||||
priv->channel[READ] = priv->channel[WRITE] = NULL;
|
||||
|
||||
return 0;
|
||||
|
@ -3228,7 +3019,7 @@ ctc_remove_device(struct ccwgroup_device *cgdev)
|
|||
struct ctc_priv *priv;
|
||||
|
||||
pr_debug("%s() called\n", __FUNCTION__);
|
||||
DBF_TEXT(trace, 3, __FUNCTION__);
|
||||
DBF_TEXT(setup, 3, __FUNCTION__);
|
||||
|
||||
priv = cgdev->dev.driver_data;
|
||||
if (!priv)
|
||||
|
@ -3265,6 +3056,7 @@ static struct ccwgroup_driver ctc_group_driver = {
|
|||
static void __exit
|
||||
ctc_exit(void)
|
||||
{
|
||||
DBF_TEXT(setup, 3, __FUNCTION__);
|
||||
unregister_cu3088_discipline(&ctc_group_driver);
|
||||
ctc_tty_cleanup();
|
||||
ctc_unregister_dbf_views();
|
||||
|
@ -3282,6 +3074,10 @@ ctc_init(void)
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
loglevel = CTC_LOGLEVEL_DEFAULT;
|
||||
|
||||
DBF_TEXT(setup, 3, __FUNCTION__);
|
||||
|
||||
print_banner();
|
||||
|
||||
ret = ctc_register_dbf_views();
|
||||
|
|
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* $Id: ctcmain.h,v 1.4 2005/03/24 09:04:17 mschwide Exp $
|
||||
*
|
||||
* CTC / ESCON network driver
|
||||
*
|
||||
* Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
|
||||
* Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
|
||||
Peter Tiedemann (ptiedem@de.ibm.com)
|
||||
*
|
||||
*
|
||||
* Documentation used:
|
||||
* - Principles of Operation (IBM doc#: SA22-7201-06)
|
||||
* - Common IO/-Device Commands and Self Description (IBM doc#: SA22-7204-02)
|
||||
* - Common IO/-Device Commands and Self Description (IBM doc#: SN22-5535)
|
||||
* - ESCON Channel-to-Channel Adapter (IBM doc#: SA22-7203-00)
|
||||
* - ESCON I/O Interface (IBM doc#: SA22-7202-029
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* RELEASE-TAG: CTC/ESCON network driver $Revision: 1.4 $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CTCMAIN_H_
|
||||
#define _CTCMAIN_H_
|
||||
|
||||
#include <asm/ccwdev.h>
|
||||
#include <asm/ccwgroup.h>
|
||||
|
||||
#include "ctctty.h"
|
||||
#include "fsm.h"
|
||||
#include "cu3088.h"
|
||||
|
||||
|
||||
/**
|
||||
* CCW commands, used in this driver.
|
||||
*/
|
||||
#define CCW_CMD_WRITE 0x01
|
||||
#define CCW_CMD_READ 0x02
|
||||
#define CCW_CMD_SET_EXTENDED 0xc3
|
||||
#define CCW_CMD_PREPARE 0xe3
|
||||
|
||||
#define CTC_PROTO_S390 0
|
||||
#define CTC_PROTO_LINUX 1
|
||||
#define CTC_PROTO_LINUX_TTY 2
|
||||
#define CTC_PROTO_OS390 3
|
||||
#define CTC_PROTO_MAX 3
|
||||
|
||||
#define CTC_BUFSIZE_LIMIT 65535
|
||||
#define CTC_BUFSIZE_DEFAULT 32768
|
||||
|
||||
#define CTC_TIMEOUT_5SEC 5000
|
||||
|
||||
#define CTC_INITIAL_BLOCKLEN 2
|
||||
|
||||
#define READ 0
|
||||
#define WRITE 1
|
||||
|
||||
#define CTC_ID_SIZE BUS_ID_SIZE+3
|
||||
|
||||
|
||||
struct ctc_profile {
|
||||
unsigned long maxmulti;
|
||||
unsigned long maxcqueue;
|
||||
unsigned long doios_single;
|
||||
unsigned long doios_multi;
|
||||
unsigned long txlen;
|
||||
unsigned long tx_time;
|
||||
struct timespec send_stamp;
|
||||
};
|
||||
|
||||
/**
|
||||
* Definition of one channel
|
||||
*/
|
||||
struct channel {
|
||||
|
||||
/**
|
||||
* Pointer to next channel in list.
|
||||
*/
|
||||
struct channel *next;
|
||||
char id[CTC_ID_SIZE];
|
||||
struct ccw_device *cdev;
|
||||
|
||||
/**
|
||||
* Type of this channel.
|
||||
* CTC/A or Escon for valid channels.
|
||||
*/
|
||||
enum channel_types type;
|
||||
|
||||
/**
|
||||
* Misc. flags. See CHANNEL_FLAGS_... below
|
||||
*/
|
||||
__u32 flags;
|
||||
|
||||
/**
|
||||
* The protocol of this channel
|
||||
*/
|
||||
__u16 protocol;
|
||||
|
||||
/**
|
||||
* I/O and irq related stuff
|
||||
*/
|
||||
struct ccw1 *ccw;
|
||||
struct irb *irb;
|
||||
|
||||
/**
|
||||
* RX/TX buffer size
|
||||
*/
|
||||
int max_bufsize;
|
||||
|
||||
/**
|
||||
* Transmit/Receive buffer.
|
||||
*/
|
||||
struct sk_buff *trans_skb;
|
||||
|
||||
/**
|
||||
* Universal I/O queue.
|
||||
*/
|
||||
struct sk_buff_head io_queue;
|
||||
|
||||
/**
|
||||
* TX queue for collecting skb's during busy.
|
||||
*/
|
||||
struct sk_buff_head collect_queue;
|
||||
|
||||
/**
|
||||
* Amount of data in collect_queue.
|
||||
*/
|
||||
int collect_len;
|
||||
|
||||
/**
|
||||
* spinlock for collect_queue and collect_len
|
||||
*/
|
||||
spinlock_t collect_lock;
|
||||
|
||||
/**
|
||||
* Timer for detecting unresposive
|
||||
* I/O operations.
|
||||
*/
|
||||
fsm_timer timer;
|
||||
|
||||
/**
|
||||
* Retry counter for misc. operations.
|
||||
*/
|
||||
int retry;
|
||||
|
||||
/**
|
||||
* The finite state machine of this channel
|
||||
*/
|
||||
fsm_instance *fsm;
|
||||
|
||||
/**
|
||||
* The corresponding net_device this channel
|
||||
* belongs to.
|
||||
*/
|
||||
struct net_device *netdev;
|
||||
|
||||
struct ctc_profile prof;
|
||||
|
||||
unsigned char *trans_skb_data;
|
||||
|
||||
__u16 logflags;
|
||||
};
|
||||
|
||||
#define CHANNEL_FLAGS_READ 0
|
||||
#define CHANNEL_FLAGS_WRITE 1
|
||||
#define CHANNEL_FLAGS_INUSE 2
|
||||
#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4
|
||||
#define CHANNEL_FLAGS_FAILED 8
|
||||
#define CHANNEL_FLAGS_WAITIRQ 16
|
||||
#define CHANNEL_FLAGS_RWMASK 1
|
||||
#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
|
||||
|
||||
#define LOG_FLAG_ILLEGALPKT 1
|
||||
#define LOG_FLAG_ILLEGALSIZE 2
|
||||
#define LOG_FLAG_OVERRUN 4
|
||||
#define LOG_FLAG_NOMEM 8
|
||||
|
||||
#define CTC_LOGLEVEL_INFO 1
|
||||
#define CTC_LOGLEVEL_NOTICE 2
|
||||
#define CTC_LOGLEVEL_WARN 4
|
||||
#define CTC_LOGLEVEL_EMERG 8
|
||||
#define CTC_LOGLEVEL_ERR 16
|
||||
#define CTC_LOGLEVEL_DEBUG 32
|
||||
#define CTC_LOGLEVEL_CRIT 64
|
||||
|
||||
#define CTC_LOGLEVEL_DEFAULT \
|
||||
(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT)
|
||||
|
||||
#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1)
|
||||
|
||||
#define ctc_pr_debug(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0)
|
||||
|
||||
#define ctc_pr_info(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0)
|
||||
|
||||
#define ctc_pr_notice(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0)
|
||||
|
||||
#define ctc_pr_warn(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0)
|
||||
|
||||
#define ctc_pr_emerg(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0)
|
||||
|
||||
#define ctc_pr_err(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0)
|
||||
|
||||
#define ctc_pr_crit(fmt, arg...) \
|
||||
do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0)
|
||||
|
||||
struct ctc_priv {
|
||||
struct net_device_stats stats;
|
||||
unsigned long tbusy;
|
||||
/**
|
||||
* The finite state machine of this interface.
|
||||
*/
|
||||
fsm_instance *fsm;
|
||||
/**
|
||||
* The protocol of this device
|
||||
*/
|
||||
__u16 protocol;
|
||||
/**
|
||||
* Timer for restarting after I/O Errors
|
||||
*/
|
||||
fsm_timer restart_timer;
|
||||
|
||||
int buffer_size;
|
||||
|
||||
struct channel *channel[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* Definition of our link level header.
|
||||
*/
|
||||
struct ll_header {
|
||||
__u16 length;
|
||||
__u16 type;
|
||||
__u16 unused;
|
||||
};
|
||||
#define LL_HEADER_LENGTH (sizeof(struct ll_header))
|
||||
|
||||
/**
|
||||
* Compatibility macros for busy handling
|
||||
* of network devices.
|
||||
*/
|
||||
static __inline__ void
|
||||
ctc_clear_busy(struct net_device * dev)
|
||||
{
|
||||
clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
|
||||
if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
ctc_test_and_set_busy(struct net_device * dev)
|
||||
{
|
||||
if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
|
||||
netif_stop_queue(dev);
|
||||
return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* $Id: ctctty.c,v 1.26 2004/08/04 11:06:55 mschwide Exp $
|
||||
* $Id: ctctty.c,v 1.29 2005/04/05 08:50:44 mschwide Exp $
|
||||
*
|
||||
* CTC / ESCON network driver, tty interface.
|
||||
*
|
||||
|
@ -1056,8 +1056,7 @@ ctc_tty_close(struct tty_struct *tty, struct file *filp)
|
|||
info->tty = 0;
|
||||
tty->closing = 0;
|
||||
if (info->blocked_open) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(HZ/2);
|
||||
msleep_interruptible(500);
|
||||
wake_up_interruptible(&info->open_wait);
|
||||
}
|
||||
info->flags &= ~(CTC_ASYNC_NORMAL_ACTIVE | CTC_ASYNC_CLOSING);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* $Id: cu3088.c,v 1.34 2004/06/15 13:16:27 pavlic Exp $
|
||||
* $Id: cu3088.c,v 1.35 2005/03/30 19:28:52 richtera Exp $
|
||||
*
|
||||
* CTC / LCS ccw_device driver
|
||||
*
|
||||
|
@ -39,6 +39,7 @@ const char *cu3088_type[] = {
|
|||
"FICON channel",
|
||||
"P390 LCS card",
|
||||
"OSA LCS card",
|
||||
"CLAW channel device",
|
||||
"unknown channel type",
|
||||
"unsupported channel type",
|
||||
};
|
||||
|
@ -51,6 +52,7 @@ static struct ccw_device_id cu3088_ids[] = {
|
|||
{ CCW_DEVICE(0x3088, 0x1e), .driver_info = channel_type_ficon },
|
||||
{ CCW_DEVICE(0x3088, 0x01), .driver_info = channel_type_p390 },
|
||||
{ CCW_DEVICE(0x3088, 0x60), .driver_info = channel_type_osa2 },
|
||||
{ CCW_DEVICE(0x3088, 0x61), .driver_info = channel_type_claw },
|
||||
{ /* end of list */ }
|
||||
};
|
||||
|
||||
|
|
|
@ -23,6 +23,9 @@ enum channel_types {
|
|||
/* Device is a OSA2 card */
|
||||
channel_type_osa2,
|
||||
|
||||
/* Device is a CLAW channel device */
|
||||
channel_type_claw,
|
||||
|
||||
/* Device is a channel, but we don't know
|
||||
* anything about it */
|
||||
channel_type_unknown,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* $Id: iucv.c,v 1.43 2005/02/09 14:47:43 braunu Exp $
|
||||
* $Id: iucv.c,v 1.45 2005/04/26 22:59:06 braunu Exp $
|
||||
*
|
||||
* IUCV network driver
|
||||
*
|
||||
|
@ -29,7 +29,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* RELEASE-TAG: IUCV lowlevel driver $Revision: 1.43 $
|
||||
* RELEASE-TAG: IUCV lowlevel driver $Revision: 1.45 $
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -355,7 +355,7 @@ do { \
|
|||
static void
|
||||
iucv_banner(void)
|
||||
{
|
||||
char vbuf[] = "$Revision: 1.43 $";
|
||||
char vbuf[] = "$Revision: 1.45 $";
|
||||
char *version = vbuf;
|
||||
|
||||
if ((version = strchr(version, ':'))) {
|
||||
|
@ -2553,12 +2553,12 @@ EXPORT_SYMBOL (iucv_resume);
|
|||
#endif
|
||||
EXPORT_SYMBOL (iucv_reply_prmmsg);
|
||||
EXPORT_SYMBOL (iucv_send);
|
||||
#if 0
|
||||
EXPORT_SYMBOL (iucv_send2way);
|
||||
EXPORT_SYMBOL (iucv_send2way_array);
|
||||
EXPORT_SYMBOL (iucv_send_array);
|
||||
EXPORT_SYMBOL (iucv_send2way_prmmsg);
|
||||
EXPORT_SYMBOL (iucv_send2way_prmmsg_array);
|
||||
#if 0
|
||||
EXPORT_SYMBOL (iucv_send_array);
|
||||
EXPORT_SYMBOL (iucv_send_prmmsg);
|
||||
EXPORT_SYMBOL (iucv_setmask);
|
||||
#endif
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* Frank Pavlic (pavlic@de.ibm.com) and
|
||||
* Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
*
|
||||
* $Revision: 1.96 $ $Date: 2004/11/11 13:42:33 $
|
||||
* $Revision: 1.98 $ $Date: 2005/04/18 13:41:29 $
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -59,7 +59,7 @@
|
|||
/**
|
||||
* initialization string for output
|
||||
*/
|
||||
#define VERSION_LCS_C "$Revision: 1.96 $"
|
||||
#define VERSION_LCS_C "$Revision: 1.98 $"
|
||||
|
||||
static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
|
||||
static char debug_buffer[255];
|
||||
|
@ -1098,14 +1098,6 @@ lcs_check_multicast_support(struct lcs_card *card)
|
|||
PRINT_ERR("Query IPAssist failed. Assuming unsupported!\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
/* Print out supported assists: IPv6 */
|
||||
PRINT_INFO("LCS device %s %s IPv6 support\n", card->dev->name,
|
||||
(card->ip_assists_supported & LCS_IPASS_IPV6_SUPPORT) ?
|
||||
"with" : "without");
|
||||
/* Print out supported assist: Multicast */
|
||||
PRINT_INFO("LCS device %s %s Multicast support\n", card->dev->name,
|
||||
(card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT) ?
|
||||
"with" : "without");
|
||||
if (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT)
|
||||
return 0;
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -1160,7 +1152,7 @@ list_modified:
|
|||
}
|
||||
}
|
||||
/* re-insert all entries from the failed_list into ipm_list */
|
||||
list_for_each_entry(ipm, &failed_list, list) {
|
||||
list_for_each_entry_safe(ipm, tmp, &failed_list, list) {
|
||||
list_del_init(&ipm->list);
|
||||
list_add_tail(&ipm->list, &card->ipm_list);
|
||||
}
|
||||
|
@ -2198,30 +2190,39 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
|
|||
if (!dev)
|
||||
goto out;
|
||||
card->dev = dev;
|
||||
netdev_out:
|
||||
card->dev->priv = card;
|
||||
card->dev->open = lcs_open_device;
|
||||
card->dev->stop = lcs_stop_device;
|
||||
card->dev->hard_start_xmit = lcs_start_xmit;
|
||||
card->dev->get_stats = lcs_getstats;
|
||||
SET_MODULE_OWNER(dev);
|
||||
if (lcs_register_netdev(ccwgdev) != 0)
|
||||
goto out;
|
||||
memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH);
|
||||
#ifdef CONFIG_IP_MULTICAST
|
||||
if (!lcs_check_multicast_support(card))
|
||||
card->dev->set_multicast_list = lcs_set_multicast_list;
|
||||
#endif
|
||||
netif_stop_queue(card->dev);
|
||||
netdev_out:
|
||||
lcs_set_allowed_threads(card,0xffffffff);
|
||||
if (recover_state == DEV_STATE_RECOVER) {
|
||||
lcs_set_multicast_list(card->dev);
|
||||
card->dev->flags |= IFF_UP;
|
||||
netif_wake_queue(card->dev);
|
||||
card->state = DEV_STATE_UP;
|
||||
} else
|
||||
} else {
|
||||
lcs_stopcard(card);
|
||||
}
|
||||
|
||||
if (lcs_register_netdev(ccwgdev) != 0)
|
||||
goto out;
|
||||
|
||||
/* Print out supported assists: IPv6 */
|
||||
PRINT_INFO("LCS device %s %s IPv6 support\n", card->dev->name,
|
||||
(card->ip_assists_supported & LCS_IPASS_IPV6_SUPPORT) ?
|
||||
"with" : "without");
|
||||
/* Print out supported assist: Multicast */
|
||||
PRINT_INFO("LCS device %s %s Multicast support\n", card->dev->name,
|
||||
(card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT) ?
|
||||
"with" : "without");
|
||||
return 0;
|
||||
out:
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#include "qeth_mpc.h"
|
||||
|
||||
#define VERSION_QETH_H "$Revision: 1.135 $"
|
||||
#define VERSION_QETH_H "$Revision: 1.139 $"
|
||||
|
||||
#ifdef CONFIG_QETH_IPV6
|
||||
#define QETH_VERSION_IPV6 ":IPv6"
|
||||
|
@ -288,7 +288,8 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
|
|||
#define QETH_TX_TIMEOUT 100 * HZ
|
||||
#define QETH_HEADER_SIZE 32
|
||||
#define MAX_PORTNO 15
|
||||
#define QETH_FAKE_LL_LEN ETH_HLEN
|
||||
#define QETH_FAKE_LL_LEN_ETH ETH_HLEN
|
||||
#define QETH_FAKE_LL_LEN_TR (sizeof(struct trh_hdr)-TR_MAXRIFLEN+sizeof(struct trllc))
|
||||
#define QETH_FAKE_LL_V6_ADDR_POS 24
|
||||
|
||||
/*IPv6 address autoconfiguration stuff*/
|
||||
|
@ -369,6 +370,25 @@ struct qeth_hdr {
|
|||
} hdr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*TCP Segmentation Offload header*/
|
||||
struct qeth_hdr_ext_tso {
|
||||
__u16 hdr_tot_len;
|
||||
__u8 imb_hdr_no;
|
||||
__u8 reserved;
|
||||
__u8 hdr_type;
|
||||
__u8 hdr_version;
|
||||
__u16 hdr_len;
|
||||
__u32 payload_len;
|
||||
__u16 mss;
|
||||
__u16 dg_hdr_len;
|
||||
__u8 padding[16];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct qeth_hdr_tso {
|
||||
struct qeth_hdr hdr; /*hdr->hdr.l3.xxx*/
|
||||
struct qeth_hdr_ext_tso ext;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* flags for qeth_hdr.flags */
|
||||
#define QETH_HDR_PASSTHRU 0x10
|
||||
|
@ -866,6 +886,7 @@ qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size)
|
|||
return hdr;
|
||||
}
|
||||
|
||||
|
||||
inline static int
|
||||
qeth_get_hlen(__u8 link_type)
|
||||
{
|
||||
|
@ -873,19 +894,19 @@ qeth_get_hlen(__u8 link_type)
|
|||
switch (link_type) {
|
||||
case QETH_LINK_TYPE_HSTR:
|
||||
case QETH_LINK_TYPE_LANE_TR:
|
||||
return sizeof(struct qeth_hdr) + TR_HLEN;
|
||||
return sizeof(struct qeth_hdr_tso) + TR_HLEN;
|
||||
default:
|
||||
#ifdef CONFIG_QETH_VLAN
|
||||
return sizeof(struct qeth_hdr) + VLAN_ETH_HLEN;
|
||||
return sizeof(struct qeth_hdr_tso) + VLAN_ETH_HLEN;
|
||||
#else
|
||||
return sizeof(struct qeth_hdr) + ETH_HLEN;
|
||||
return sizeof(struct qeth_hdr_tso) + ETH_HLEN;
|
||||
#endif
|
||||
}
|
||||
#else /* CONFIG_QETH_IPV6 */
|
||||
#ifdef CONFIG_QETH_VLAN
|
||||
return sizeof(struct qeth_hdr) + VLAN_HLEN;
|
||||
return sizeof(struct qeth_hdr_tso) + VLAN_HLEN;
|
||||
#else
|
||||
return sizeof(struct qeth_hdr);
|
||||
return sizeof(struct qeth_hdr_tso);
|
||||
#endif
|
||||
#endif /* CONFIG_QETH_IPV6 */
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.11 $)
|
||||
* linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.13 $)
|
||||
*
|
||||
* Enhanced Device Driver Packing (EDDP) support for the qeth driver.
|
||||
*
|
||||
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
* Author(s): Thomas Spatzier <tspat@de.ibm.com>
|
||||
*
|
||||
* $Revision: 1.11 $ $Date: 2005/03/24 09:04:18 $
|
||||
* $Revision: 1.13 $ $Date: 2005/05/04 20:19:18 $
|
||||
*
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
|
@ -85,7 +85,7 @@ void
|
|||
qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
|
||||
{
|
||||
struct qeth_eddp_context_reference *ref;
|
||||
|
||||
|
||||
QETH_DBF_TEXT(trace, 6, "eddprctx");
|
||||
while (!list_empty(&buf->ctx_list)){
|
||||
ref = list_entry(buf->ctx_list.next,
|
||||
|
@ -139,7 +139,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
|
|||
"buffer!\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* check if the whole next skb fits into current buffer */
|
||||
if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) -
|
||||
buf->next_element_to_fill)
|
||||
|
@ -152,7 +152,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
|
|||
* and increment ctx's refcnt */
|
||||
must_refcnt = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (must_refcnt){
|
||||
must_refcnt = 0;
|
||||
if (qeth_eddp_buf_ref_context(buf, ctx)){
|
||||
|
@ -202,40 +202,29 @@ out:
|
|||
return flush_cnt;
|
||||
}
|
||||
|
||||
static inline int
|
||||
qeth_get_skb_data_len(struct sk_buff *skb)
|
||||
{
|
||||
int len = skb->len;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i)
|
||||
len -= skb_shinfo(skb)->frags[i].size;
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline void
|
||||
qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
|
||||
struct qeth_eddp_data *eddp)
|
||||
struct qeth_eddp_data *eddp, int data_len)
|
||||
{
|
||||
u8 *page;
|
||||
int page_remainder;
|
||||
int page_offset;
|
||||
int hdr_len;
|
||||
int pkt_len;
|
||||
struct qeth_eddp_element *element;
|
||||
|
||||
QETH_DBF_TEXT(trace, 5, "eddpcrsh");
|
||||
page = ctx->pages[ctx->offset >> PAGE_SHIFT];
|
||||
page_offset = ctx->offset % PAGE_SIZE;
|
||||
element = &ctx->elements[ctx->num_elements];
|
||||
hdr_len = eddp->nhl + eddp->thl;
|
||||
pkt_len = eddp->nhl + eddp->thl + data_len;
|
||||
/* FIXME: layer2 and VLAN !!! */
|
||||
if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
|
||||
hdr_len += ETH_HLEN;
|
||||
pkt_len += ETH_HLEN;
|
||||
if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
|
||||
hdr_len += VLAN_HLEN;
|
||||
/* does complete header fit in current page ? */
|
||||
pkt_len += VLAN_HLEN;
|
||||
/* does complete packet fit in current page ? */
|
||||
page_remainder = PAGE_SIZE - page_offset;
|
||||
if (page_remainder < (sizeof(struct qeth_hdr) + hdr_len)){
|
||||
if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)){
|
||||
/* no -> go to start of next page */
|
||||
ctx->offset += page_remainder;
|
||||
page = ctx->pages[ctx->offset >> PAGE_SHIFT];
|
||||
|
@ -281,7 +270,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
|
|||
int left_in_frag;
|
||||
int copy_len;
|
||||
u8 *src;
|
||||
|
||||
|
||||
QETH_DBF_TEXT(trace, 5, "eddpcdtc");
|
||||
if (skb_shinfo(eddp->skb)->nr_frags == 0) {
|
||||
memcpy(dst, eddp->skb->data + eddp->skb_offset, len);
|
||||
|
@ -292,7 +281,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
|
|||
while (len > 0) {
|
||||
if (eddp->frag < 0) {
|
||||
/* we're in skb->data */
|
||||
left_in_frag = qeth_get_skb_data_len(eddp->skb)
|
||||
left_in_frag = (eddp->skb->len - eddp->skb->data_len)
|
||||
- eddp->skb_offset;
|
||||
src = eddp->skb->data + eddp->skb_offset;
|
||||
} else {
|
||||
|
@ -424,7 +413,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
|
|||
struct tcphdr *tcph;
|
||||
int data_len;
|
||||
u32 hcsum;
|
||||
|
||||
|
||||
QETH_DBF_TEXT(trace, 5, "eddpftcp");
|
||||
eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
|
||||
tcph = eddp->skb->h.th;
|
||||
|
@ -464,7 +453,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
|
|||
else
|
||||
hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len);
|
||||
/* fill the next segment into the context */
|
||||
qeth_eddp_create_segment_hdrs(ctx, eddp);
|
||||
qeth_eddp_create_segment_hdrs(ctx, eddp, data_len);
|
||||
qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum);
|
||||
if (eddp->skb_offset >= eddp->skb->len)
|
||||
break;
|
||||
|
@ -474,13 +463,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
|
|||
eddp->th.tcp.h.seq += data_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
|
||||
struct sk_buff *skb, struct qeth_hdr *qhdr)
|
||||
{
|
||||
struct qeth_eddp_data *eddp = NULL;
|
||||
|
||||
|
||||
QETH_DBF_TEXT(trace, 5, "eddpficx");
|
||||
/* create our segmentation headers and copy original headers */
|
||||
if (skb->protocol == ETH_P_IP)
|
||||
|
@ -520,7 +509,7 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
|
|||
int hdr_len)
|
||||
{
|
||||
int skbs_per_page;
|
||||
|
||||
|
||||
QETH_DBF_TEXT(trace, 5, "eddpcanp");
|
||||
/* can we put multiple skbs in one page? */
|
||||
skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
|
||||
|
@ -600,7 +589,7 @@ qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
|
|||
struct qeth_hdr *qhdr)
|
||||
{
|
||||
struct qeth_eddp_context *ctx = NULL;
|
||||
|
||||
|
||||
QETH_DBF_TEXT(trace, 5, "creddpct");
|
||||
if (skb->protocol == ETH_P_IP)
|
||||
ctx = qeth_eddp_create_context_generic(card, skb,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* linux/drivers/s390/net/qeth_main.c ($Revision: 1.206 $)
|
||||
* linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $)
|
||||
*
|
||||
* Linux on zSeries OSA Express and HiperSockets support
|
||||
*
|
||||
|
@ -12,7 +12,7 @@
|
|||
* Frank Pavlic (pavlic@de.ibm.com) and
|
||||
* Thomas Spatzier <tspat@de.ibm.com>
|
||||
*
|
||||
* $Revision: 1.206 $ $Date: 2005/03/24 09:04:18 $
|
||||
* $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -80,7 +80,7 @@ qeth_eyecatcher(void)
|
|||
#include "qeth_eddp.h"
|
||||
#include "qeth_tso.h"
|
||||
|
||||
#define VERSION_QETH_C "$Revision: 1.206 $"
|
||||
#define VERSION_QETH_C "$Revision: 1.214 $"
|
||||
static const char *version = "qeth S/390 OSA-Express driver";
|
||||
|
||||
/**
|
||||
|
@ -158,6 +158,9 @@ qeth_irq_tasklet(unsigned long);
|
|||
static int
|
||||
qeth_set_online(struct ccwgroup_device *);
|
||||
|
||||
static int
|
||||
__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode);
|
||||
|
||||
static struct qeth_ipaddr *
|
||||
qeth_get_addr_buffer(enum qeth_prot_versions);
|
||||
|
||||
|
@ -510,10 +513,10 @@ qeth_irq_tasklet(unsigned long data)
|
|||
wake_up(&card->wait_q);
|
||||
}
|
||||
|
||||
static int qeth_stop_card(struct qeth_card *);
|
||||
static int qeth_stop_card(struct qeth_card *, int);
|
||||
|
||||
static int
|
||||
qeth_set_offline(struct ccwgroup_device *cgdev)
|
||||
__qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
|
||||
{
|
||||
struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
|
||||
int rc = 0;
|
||||
|
@ -523,7 +526,7 @@ qeth_set_offline(struct ccwgroup_device *cgdev)
|
|||
QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
|
||||
|
||||
recover_flag = card->state;
|
||||
if (qeth_stop_card(card) == -ERESTARTSYS){
|
||||
if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){
|
||||
PRINT_WARN("Stopping card %s interrupted by user!\n",
|
||||
CARD_BUS_ID(card));
|
||||
return -ERESTARTSYS;
|
||||
|
@ -539,6 +542,12 @@ qeth_set_offline(struct ccwgroup_device *cgdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qeth_set_offline(struct ccwgroup_device *cgdev)
|
||||
{
|
||||
return __qeth_set_offline(cgdev, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
qeth_wait_for_threads(struct qeth_card *card, unsigned long threads);
|
||||
|
||||
|
@ -953,8 +962,8 @@ qeth_recover(void *ptr)
|
|||
PRINT_WARN("Recovery of device %s started ...\n",
|
||||
CARD_BUS_ID(card));
|
||||
card->use_hard_stop = 1;
|
||||
qeth_set_offline(card->gdev);
|
||||
rc = qeth_set_online(card->gdev);
|
||||
__qeth_set_offline(card->gdev,1);
|
||||
rc = __qeth_set_online(card->gdev,1);
|
||||
if (!rc)
|
||||
PRINT_INFO("Device %s successfully recovered!\n",
|
||||
CARD_BUS_ID(card));
|
||||
|
@ -2152,9 +2161,15 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
|
|||
if (!skb_len)
|
||||
return NULL;
|
||||
if (card->options.fake_ll){
|
||||
if (!(skb = qeth_get_skb(skb_len + QETH_FAKE_LL_LEN)))
|
||||
goto no_mem;
|
||||
skb_pull(skb, QETH_FAKE_LL_LEN);
|
||||
if(card->dev->type == ARPHRD_IEEE802_TR){
|
||||
if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR)))
|
||||
goto no_mem;
|
||||
skb_reserve(skb,QETH_FAKE_LL_LEN_TR);
|
||||
} else {
|
||||
if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH)))
|
||||
goto no_mem;
|
||||
skb_reserve(skb,QETH_FAKE_LL_LEN_ETH);
|
||||
}
|
||||
} else if (!(skb = qeth_get_skb(skb_len)))
|
||||
goto no_mem;
|
||||
data_ptr = element->addr + offset;
|
||||
|
@ -2229,14 +2244,68 @@ qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
|
|||
}
|
||||
|
||||
static inline void
|
||||
qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
|
||||
qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb,
|
||||
struct qeth_hdr *hdr)
|
||||
{
|
||||
struct trh_hdr *fake_hdr;
|
||||
struct trllc *fake_llc;
|
||||
struct iphdr *ip_hdr;
|
||||
|
||||
QETH_DBF_TEXT(trace,5,"skbfktr");
|
||||
skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_TR;
|
||||
/* this is a fake ethernet header */
|
||||
fake_hdr = (struct trh_hdr *) skb->mac.raw;
|
||||
|
||||
/* the destination MAC address */
|
||||
switch (skb->pkt_type){
|
||||
case PACKET_MULTICAST:
|
||||
switch (skb->protocol){
|
||||
#ifdef CONFIG_QETH_IPV6
|
||||
case __constant_htons(ETH_P_IPV6):
|
||||
ndisc_mc_map((struct in6_addr *)
|
||||
skb->data + QETH_FAKE_LL_V6_ADDR_POS,
|
||||
fake_hdr->daddr, card->dev, 0);
|
||||
break;
|
||||
#endif /* CONFIG_QETH_IPV6 */
|
||||
case __constant_htons(ETH_P_IP):
|
||||
ip_hdr = (struct iphdr *)skb->data;
|
||||
ip_tr_mc_map(ip_hdr->daddr, fake_hdr->daddr);
|
||||
break;
|
||||
default:
|
||||
memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
|
||||
}
|
||||
break;
|
||||
case PACKET_BROADCAST:
|
||||
memset(fake_hdr->daddr, 0xff, TR_ALEN);
|
||||
break;
|
||||
default:
|
||||
memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
|
||||
}
|
||||
/* the source MAC address */
|
||||
if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
|
||||
memcpy(fake_hdr->saddr, &hdr->hdr.l3.dest_addr[2], TR_ALEN);
|
||||
else
|
||||
memset(fake_hdr->saddr, 0, TR_ALEN);
|
||||
fake_hdr->rcf=0;
|
||||
fake_llc = (struct trllc*)&(fake_hdr->rcf);
|
||||
fake_llc->dsap = EXTENDED_SAP;
|
||||
fake_llc->ssap = EXTENDED_SAP;
|
||||
fake_llc->llc = UI_CMD;
|
||||
fake_llc->protid[0] = 0;
|
||||
fake_llc->protid[1] = 0;
|
||||
fake_llc->protid[2] = 0;
|
||||
fake_llc->ethertype = ETH_P_IP;
|
||||
}
|
||||
|
||||
static inline void
|
||||
qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb,
|
||||
struct qeth_hdr *hdr)
|
||||
{
|
||||
struct ethhdr *fake_hdr;
|
||||
struct iphdr *ip_hdr;
|
||||
|
||||
QETH_DBF_TEXT(trace,5,"skbfake");
|
||||
skb->mac.raw = skb->data - QETH_FAKE_LL_LEN;
|
||||
QETH_DBF_TEXT(trace,5,"skbfketh");
|
||||
skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_ETH;
|
||||
/* this is a fake ethernet header */
|
||||
fake_hdr = (struct ethhdr *) skb->mac.raw;
|
||||
|
||||
|
@ -2253,10 +2322,7 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
|
|||
#endif /* CONFIG_QETH_IPV6 */
|
||||
case __constant_htons(ETH_P_IP):
|
||||
ip_hdr = (struct iphdr *)skb->data;
|
||||
if (card->dev->type == ARPHRD_IEEE802_TR)
|
||||
ip_tr_mc_map(ip_hdr->daddr, fake_hdr->h_dest);
|
||||
else
|
||||
ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest);
|
||||
ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest);
|
||||
break;
|
||||
default:
|
||||
memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN);
|
||||
|
@ -2277,6 +2343,16 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
|
|||
fake_hdr->h_proto = skb->protocol;
|
||||
}
|
||||
|
||||
static inline void
|
||||
qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
|
||||
struct qeth_hdr *hdr)
|
||||
{
|
||||
if (card->dev->type == ARPHRD_IEEE802_TR)
|
||||
qeth_rebuild_skb_fake_ll_tr(card, skb, hdr);
|
||||
else
|
||||
qeth_rebuild_skb_fake_ll_eth(card, skb, hdr);
|
||||
}
|
||||
|
||||
static inline void
|
||||
qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb,
|
||||
struct qeth_hdr *hdr)
|
||||
|
@ -3440,16 +3516,25 @@ qeth_fake_header(struct sk_buff *skb, struct net_device *dev,
|
|||
unsigned short type, void *daddr, void *saddr,
|
||||
unsigned len)
|
||||
{
|
||||
struct ethhdr *hdr;
|
||||
if(dev->type == ARPHRD_IEEE802_TR){
|
||||
struct trh_hdr *hdr;
|
||||
hdr = (struct trh_hdr *)skb_push(skb, QETH_FAKE_LL_LEN_TR);
|
||||
memcpy(hdr->saddr, dev->dev_addr, TR_ALEN);
|
||||
memcpy(hdr->daddr, "FAKELL", TR_ALEN);
|
||||
return QETH_FAKE_LL_LEN_TR;
|
||||
|
||||
hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN);
|
||||
memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN);
|
||||
memcpy(hdr->h_dest, "FAKELL", ETH_ALEN);
|
||||
if (type != ETH_P_802_3)
|
||||
hdr->h_proto = htons(type);
|
||||
else
|
||||
hdr->h_proto = htons(len);
|
||||
return QETH_FAKE_LL_LEN;
|
||||
} else {
|
||||
struct ethhdr *hdr;
|
||||
hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN_ETH);
|
||||
memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN);
|
||||
memcpy(hdr->h_dest, "FAKELL", ETH_ALEN);
|
||||
if (type != ETH_P_802_3)
|
||||
hdr->h_proto = htons(type);
|
||||
else
|
||||
hdr->h_proto = htons(len);
|
||||
return QETH_FAKE_LL_LEN_ETH;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
@ -3710,16 +3795,12 @@ static inline int
|
|||
qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
|
||||
struct qeth_hdr **hdr, int ipv)
|
||||
{
|
||||
int rc = 0;
|
||||
#ifdef CONFIG_QETH_VLAN
|
||||
u16 *tag;
|
||||
#endif
|
||||
|
||||
QETH_DBF_TEXT(trace, 6, "prepskb");
|
||||
|
||||
rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
|
||||
if (rc)
|
||||
return rc;
|
||||
#ifdef CONFIG_QETH_VLAN
|
||||
if (card->vlangrp && vlan_tx_tag_present(*skb) &&
|
||||
((ipv == 6) || card->options.layer2) ) {
|
||||
|
@ -3882,9 +3963,15 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
|
|||
memcpy(hdr->hdr.l3.dest_addr, &skb->nh.ipv6h->daddr, 16);
|
||||
}
|
||||
} else { /* passthrough */
|
||||
if (!memcmp(skb->data + sizeof(struct qeth_hdr),
|
||||
if((skb->dev->type == ARPHRD_IEEE802_TR) &&
|
||||
!memcmp(skb->data + sizeof(struct qeth_hdr) +
|
||||
sizeof(__u16), skb->dev->broadcast, 6)) {
|
||||
hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
|
||||
QETH_HDR_PASSTHRU;
|
||||
} else if (!memcmp(skb->data + sizeof(struct qeth_hdr),
|
||||
skb->dev->broadcast, 6)) { /* broadcast? */
|
||||
hdr->hdr.l3.flags = QETH_CAST_BROADCAST | QETH_HDR_PASSTHRU;
|
||||
hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
|
||||
QETH_HDR_PASSTHRU;
|
||||
} else {
|
||||
hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ?
|
||||
QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU :
|
||||
|
@ -3893,68 +3980,30 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
|
||||
int *next_element_to_fill)
|
||||
{
|
||||
int length = skb->len;
|
||||
struct skb_frag_struct *frag;
|
||||
int fragno;
|
||||
unsigned long addr;
|
||||
int element;
|
||||
int first_lap = 1;
|
||||
|
||||
fragno = skb_shinfo(skb)->nr_frags; /* start with last frag */
|
||||
element = *next_element_to_fill + fragno;
|
||||
while (length > 0) {
|
||||
if (fragno > 0) {
|
||||
frag = &skb_shinfo(skb)->frags[fragno - 1];
|
||||
addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
|
||||
frag->page_offset;
|
||||
buffer->element[element].addr = (char *)addr;
|
||||
buffer->element[element].length = frag->size;
|
||||
length -= frag->size;
|
||||
if (first_lap)
|
||||
buffer->element[element].flags =
|
||||
SBAL_FLAGS_LAST_FRAG;
|
||||
else
|
||||
buffer->element[element].flags =
|
||||
SBAL_FLAGS_MIDDLE_FRAG;
|
||||
} else {
|
||||
buffer->element[element].addr = skb->data;
|
||||
buffer->element[element].length = length;
|
||||
length = 0;
|
||||
buffer->element[element].flags =
|
||||
SBAL_FLAGS_FIRST_FRAG;
|
||||
}
|
||||
element--;
|
||||
fragno--;
|
||||
first_lap = 0;
|
||||
}
|
||||
*next_element_to_fill += skb_shinfo(skb)->nr_frags + 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
|
||||
int *next_element_to_fill)
|
||||
int is_tso, int *next_element_to_fill)
|
||||
{
|
||||
int length = skb->len;
|
||||
int length_here;
|
||||
int element;
|
||||
char *data;
|
||||
int first_lap = 1;
|
||||
int first_lap ;
|
||||
|
||||
element = *next_element_to_fill;
|
||||
data = skb->data;
|
||||
first_lap = (is_tso == 0 ? 1 : 0);
|
||||
|
||||
while (length > 0) {
|
||||
/* length_here is the remaining amount of data in this page */
|
||||
length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
|
||||
if (length < length_here)
|
||||
length_here = length;
|
||||
|
||||
buffer->element[element].addr = data;
|
||||
buffer->element[element].length = length_here;
|
||||
length -= length_here;
|
||||
if (!length){
|
||||
if (!length) {
|
||||
if (first_lap)
|
||||
buffer->element[element].flags = 0;
|
||||
else
|
||||
|
@ -3981,17 +4030,35 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue,
|
|||
struct sk_buff *skb)
|
||||
{
|
||||
struct qdio_buffer *buffer;
|
||||
int flush_cnt = 0;
|
||||
struct qeth_hdr_tso *hdr;
|
||||
int flush_cnt = 0, hdr_len, large_send = 0;
|
||||
|
||||
QETH_DBF_TEXT(trace, 6, "qdfillbf");
|
||||
|
||||
buffer = buf->buffer;
|
||||
atomic_inc(&skb->users);
|
||||
skb_queue_tail(&buf->skb_list, skb);
|
||||
|
||||
hdr = (struct qeth_hdr_tso *) skb->data;
|
||||
/*check first on TSO ....*/
|
||||
if (hdr->hdr.hdr.l3.id == QETH_HEADER_TYPE_TSO) {
|
||||
int element = buf->next_element_to_fill;
|
||||
|
||||
hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
|
||||
/*fill first buffer entry only with header information */
|
||||
buffer->element[element].addr = skb->data;
|
||||
buffer->element[element].length = hdr_len;
|
||||
buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
|
||||
buf->next_element_to_fill++;
|
||||
skb->data += hdr_len;
|
||||
skb->len -= hdr_len;
|
||||
large_send = 1;
|
||||
}
|
||||
if (skb_shinfo(skb)->nr_frags == 0)
|
||||
__qeth_fill_buffer(skb, buffer,
|
||||
__qeth_fill_buffer(skb, buffer, large_send,
|
||||
(int *)&buf->next_element_to_fill);
|
||||
else
|
||||
__qeth_fill_buffer_frag(skb, buffer,
|
||||
__qeth_fill_buffer_frag(skb, buffer, large_send,
|
||||
(int *)&buf->next_element_to_fill);
|
||||
|
||||
if (!queue->do_pack) {
|
||||
|
@ -4183,6 +4250,25 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static inline int
|
||||
qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
|
||||
{
|
||||
int elements_needed = 0;
|
||||
|
||||
if (skb_shinfo(skb)->nr_frags > 0) {
|
||||
elements_needed = (skb_shinfo(skb)->nr_frags + 1);
|
||||
}
|
||||
if (elements_needed == 0 )
|
||||
elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
|
||||
+ skb->len) >> PAGE_SHIFT);
|
||||
if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
|
||||
PRINT_ERR("qeth_do_send_packet: invalid size of "
|
||||
"IP packet. Discarded.");
|
||||
return 0;
|
||||
}
|
||||
return elements_needed;
|
||||
}
|
||||
|
||||
static inline int
|
||||
qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
|
||||
{
|
||||
|
@ -4205,7 +4291,11 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
|
|||
dev_kfree_skb_irq(skb);
|
||||
return 0;
|
||||
}
|
||||
skb_pull(skb, QETH_FAKE_LL_LEN);
|
||||
if(card->dev->type == ARPHRD_IEEE802_TR){
|
||||
skb_pull(skb, QETH_FAKE_LL_LEN_TR);
|
||||
} else {
|
||||
skb_pull(skb, QETH_FAKE_LL_LEN_ETH);
|
||||
}
|
||||
}
|
||||
}
|
||||
cast_type = qeth_get_cast_type(card, skb);
|
||||
|
@ -4221,19 +4311,25 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
|
|||
if (skb_shinfo(skb)->tso_size)
|
||||
large_send = card->options.large_send;
|
||||
|
||||
if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))){
|
||||
QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc);
|
||||
return rc;
|
||||
}
|
||||
/*are we able to do TSO ? If so ,prepare and send it from here */
|
||||
if ((large_send == QETH_LARGE_SEND_TSO) &&
|
||||
(cast_type == RTN_UNSPEC)) {
|
||||
rc = qeth_tso_send_packet(card, skb, queue,
|
||||
ipv, cast_type);
|
||||
goto do_statistics;
|
||||
rc = qeth_tso_prepare_packet(card, skb, ipv, cast_type);
|
||||
if (rc) {
|
||||
card->stats.tx_dropped++;
|
||||
card->stats.tx_errors++;
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
elements_needed++;
|
||||
} else {
|
||||
if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))) {
|
||||
QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc);
|
||||
return rc;
|
||||
}
|
||||
qeth_fill_header(card, hdr, skb, ipv, cast_type);
|
||||
}
|
||||
|
||||
qeth_fill_header(card, hdr, skb, ipv, cast_type);
|
||||
if (large_send == QETH_LARGE_SEND_EDDP) {
|
||||
ctx = qeth_eddp_create_context(card, skb, hdr);
|
||||
if (ctx == NULL) {
|
||||
|
@ -4241,7 +4337,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
|
|||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
elements_needed = qeth_get_elements_no(card,(void*) hdr, skb);
|
||||
elements_needed += qeth_get_elements_no(card,(void*) hdr, skb);
|
||||
if (!elements_needed)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -4252,12 +4348,12 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
|
|||
else
|
||||
rc = qeth_do_send_packet_fast(card, queue, skb, hdr,
|
||||
elements_needed, ctx);
|
||||
do_statistics:
|
||||
if (!rc){
|
||||
card->stats.tx_packets++;
|
||||
card->stats.tx_bytes += skb->len;
|
||||
#ifdef CONFIG_QETH_PERF_STATS
|
||||
if (skb_shinfo(skb)->tso_size) {
|
||||
if (skb_shinfo(skb)->tso_size &&
|
||||
!(large_send == QETH_LARGE_SEND_NO)) {
|
||||
card->perf_stats.large_send_bytes += skb->len;
|
||||
card->perf_stats.large_send_cnt++;
|
||||
}
|
||||
|
@ -7154,7 +7250,7 @@ qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
|
|||
}
|
||||
|
||||
static int
|
||||
qeth_stop_card(struct qeth_card *card)
|
||||
qeth_stop_card(struct qeth_card *card, int recovery_mode)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
|
@ -7167,9 +7263,13 @@ qeth_stop_card(struct qeth_card *card)
|
|||
if (card->read.state == CH_STATE_UP &&
|
||||
card->write.state == CH_STATE_UP &&
|
||||
(card->state == CARD_STATE_UP)) {
|
||||
rtnl_lock();
|
||||
dev_close(card->dev);
|
||||
rtnl_unlock();
|
||||
if(recovery_mode) {
|
||||
qeth_stop(card->dev);
|
||||
} else {
|
||||
rtnl_lock();
|
||||
dev_close(card->dev);
|
||||
rtnl_unlock();
|
||||
}
|
||||
if (!card->use_hard_stop) {
|
||||
__u8 *mac = &card->dev->dev_addr[0];
|
||||
rc = qeth_layer2_send_delmac(card, mac);
|
||||
|
@ -7341,13 +7441,17 @@ qeth_register_netdev(struct qeth_card *card)
|
|||
}
|
||||
|
||||
static void
|
||||
qeth_start_again(struct qeth_card *card)
|
||||
qeth_start_again(struct qeth_card *card, int recovery_mode)
|
||||
{
|
||||
QETH_DBF_TEXT(setup ,2, "startag");
|
||||
|
||||
rtnl_lock();
|
||||
dev_open(card->dev);
|
||||
rtnl_unlock();
|
||||
if(recovery_mode) {
|
||||
qeth_open(card->dev);
|
||||
} else {
|
||||
rtnl_lock();
|
||||
dev_open(card->dev);
|
||||
rtnl_unlock();
|
||||
}
|
||||
/* this also sets saved unicast addresses */
|
||||
qeth_set_multicast_list(card->dev);
|
||||
}
|
||||
|
@ -7404,7 +7508,7 @@ static void qeth_make_parameters_consistent(struct qeth_card *card)
|
|||
|
||||
|
||||
static int
|
||||
qeth_set_online(struct ccwgroup_device *gdev)
|
||||
__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
||||
{
|
||||
struct qeth_card *card = gdev->dev.driver_data;
|
||||
int rc = 0;
|
||||
|
@ -7464,12 +7568,12 @@ qeth_set_online(struct ccwgroup_device *gdev)
|
|||
* we can also use this state for recovery purposes*/
|
||||
qeth_set_allowed_threads(card, 0xffffffff, 0);
|
||||
if (recover_flag == CARD_STATE_RECOVER)
|
||||
qeth_start_again(card);
|
||||
qeth_start_again(card, recovery_mode);
|
||||
qeth_notify_processes();
|
||||
return 0;
|
||||
out_remove:
|
||||
card->use_hard_stop = 1;
|
||||
qeth_stop_card(card);
|
||||
qeth_stop_card(card, 0);
|
||||
ccw_device_set_offline(CARD_DDEV(card));
|
||||
ccw_device_set_offline(CARD_WDEV(card));
|
||||
ccw_device_set_offline(CARD_RDEV(card));
|
||||
|
@ -7480,6 +7584,12 @@ out_remove:
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int
|
||||
qeth_set_online(struct ccwgroup_device *gdev)
|
||||
{
|
||||
return __qeth_set_online(gdev, 0);
|
||||
}
|
||||
|
||||
static struct ccw_device_id qeth_ids[] = {
|
||||
{CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE},
|
||||
{CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD},
|
||||
|
|
|
@ -1,285 +0,0 @@
|
|||
/*
|
||||
* linux/drivers/s390/net/qeth_tso.c ($Revision: 1.6 $)
|
||||
*
|
||||
* Header file for qeth TCP Segmentation Offload support.
|
||||
*
|
||||
* Copyright 2004 IBM Corporation
|
||||
*
|
||||
* Author(s): Frank Pavlic <pavlic@de.ibm.com>
|
||||
*
|
||||
* $Revision: 1.6 $ $Date: 2005/03/24 09:04:18 $
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <net/ip6_checksum.h>
|
||||
#include "qeth.h"
|
||||
#include "qeth_mpc.h"
|
||||
#include "qeth_tso.h"
|
||||
|
||||
/**
|
||||
* skb already partially prepared
|
||||
* classic qdio header in skb->data
|
||||
* */
|
||||
static inline struct qeth_hdr_tso *
|
||||
qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
QETH_DBF_TEXT(trace, 5, "tsoprsk");
|
||||
rc = qeth_realloc_headroom(card, skb,sizeof(struct qeth_hdr_ext_tso));
|
||||
if (rc)
|
||||
return NULL;
|
||||
|
||||
return qeth_push_skb(card, skb, sizeof(struct qeth_hdr_ext_tso));
|
||||
}
|
||||
|
||||
/**
|
||||
* fill header for a TSO packet
|
||||
*/
|
||||
static inline void
|
||||
qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb)
|
||||
{
|
||||
struct qeth_hdr_tso *hdr;
|
||||
struct tcphdr *tcph;
|
||||
struct iphdr *iph;
|
||||
|
||||
QETH_DBF_TEXT(trace, 5, "tsofhdr");
|
||||
|
||||
hdr = (struct qeth_hdr_tso *) skb->data;
|
||||
iph = skb->nh.iph;
|
||||
tcph = skb->h.th;
|
||||
/*fix header to TSO values ...*/
|
||||
hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
|
||||
/*set values which are fix for the first approach ...*/
|
||||
hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
|
||||
hdr->ext.imb_hdr_no = 1;
|
||||
hdr->ext.hdr_type = 1;
|
||||
hdr->ext.hdr_version = 1;
|
||||
hdr->ext.hdr_len = 28;
|
||||
/*insert non-fix values */
|
||||
hdr->ext.mss = skb_shinfo(skb)->tso_size;
|
||||
hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
|
||||
hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
|
||||
sizeof(struct qeth_hdr_tso));
|
||||
}
|
||||
|
||||
/**
|
||||
* change some header values as requested by hardware
|
||||
*/
|
||||
static inline void
|
||||
qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb)
|
||||
{
|
||||
struct iphdr *iph;
|
||||
struct ipv6hdr *ip6h;
|
||||
struct tcphdr *tcph;
|
||||
|
||||
iph = skb->nh.iph;
|
||||
ip6h = skb->nh.ipv6h;
|
||||
tcph = skb->h.th;
|
||||
|
||||
tcph->check = 0;
|
||||
if (skb->protocol == ETH_P_IPV6) {
|
||||
ip6h->payload_len = 0;
|
||||
tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
|
||||
0, IPPROTO_TCP, 0);
|
||||
return;
|
||||
}
|
||||
/*OSA want us to set these values ...*/
|
||||
tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
|
||||
0, IPPROTO_TCP, 0);
|
||||
iph->tot_len = 0;
|
||||
iph->check = 0;
|
||||
}
|
||||
|
||||
static inline struct qeth_hdr_tso *
|
||||
qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb,
|
||||
int ipv, int cast_type)
|
||||
{
|
||||
struct qeth_hdr_tso *hdr;
|
||||
int rc = 0;
|
||||
|
||||
QETH_DBF_TEXT(trace, 5, "tsoprep");
|
||||
|
||||
/*get headroom for tso qdio header */
|
||||
hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb);
|
||||
if (hdr == NULL) {
|
||||
QETH_DBF_TEXT_(trace, 4, "2err%d", rc);
|
||||
return NULL;
|
||||
}
|
||||
memset(hdr, 0, sizeof(struct qeth_hdr_tso));
|
||||
/*fill first 32 bytes of qdio header as used
|
||||
*FIXME: TSO has two struct members
|
||||
* with different names but same size
|
||||
* */
|
||||
qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type);
|
||||
qeth_tso_fill_header(card, skb);
|
||||
qeth_tso_set_tcpip_header(card, skb);
|
||||
return hdr;
|
||||
}
|
||||
|
||||
static inline int
|
||||
qeth_tso_get_queue_buffer(struct qeth_qdio_out_q *queue)
|
||||
{
|
||||
struct qeth_qdio_out_buffer *buffer;
|
||||
int flush_cnt = 0;
|
||||
|
||||
QETH_DBF_TEXT(trace, 5, "tsobuf");
|
||||
|
||||
/* force to non-packing*/
|
||||
if (queue->do_pack)
|
||||
queue->do_pack = 0;
|
||||
buffer = &queue->bufs[queue->next_buf_to_fill];
|
||||
/* get a new buffer if current is already in use*/
|
||||
if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
|
||||
(buffer->next_element_to_fill > 0)) {
|
||||
atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
|
||||
queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
|
||||
QDIO_MAX_BUFFERS_PER_Q;
|
||||
flush_cnt++;
|
||||
}
|
||||
return flush_cnt;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__qeth_tso_fill_buffer_frag(struct qeth_qdio_out_buffer *buf,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct skb_frag_struct *frag;
|
||||
struct qdio_buffer *buffer;
|
||||
int fragno, cnt, element;
|
||||
unsigned long addr;
|
||||
|
||||
QETH_DBF_TEXT(trace, 6, "tsfilfrg");
|
||||
|
||||
/*initialize variables ...*/
|
||||
fragno = skb_shinfo(skb)->nr_frags;
|
||||
buffer = buf->buffer;
|
||||
element = buf->next_element_to_fill;
|
||||
/*fill buffer elements .....*/
|
||||
for (cnt = 0; cnt < fragno; cnt++) {
|
||||
frag = &skb_shinfo(skb)->frags[cnt];
|
||||
addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
|
||||
frag->page_offset;
|
||||
buffer->element[element].addr = (char *)addr;
|
||||
buffer->element[element].length = frag->size;
|
||||
if (cnt < (fragno - 1))
|
||||
buffer->element[element].flags =
|
||||
SBAL_FLAGS_MIDDLE_FRAG;
|
||||
else
|
||||
buffer->element[element].flags =
|
||||
SBAL_FLAGS_LAST_FRAG;
|
||||
element++;
|
||||
}
|
||||
buf->next_element_to_fill = element;
|
||||
}
|
||||
|
||||
static inline int
|
||||
qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int length, length_here, element;
|
||||
int hdr_len;
|
||||
struct qdio_buffer *buffer;
|
||||
struct qeth_hdr_tso *hdr;
|
||||
char *data;
|
||||
|
||||
QETH_DBF_TEXT(trace, 3, "tsfilbuf");
|
||||
|
||||
/*increment user count and queue skb ...*/
|
||||
atomic_inc(&skb->users);
|
||||
skb_queue_tail(&buf->skb_list, skb);
|
||||
|
||||
/*initialize all variables...*/
|
||||
buffer = buf->buffer;
|
||||
hdr = (struct qeth_hdr_tso *)skb->data;
|
||||
hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
|
||||
data = skb->data + hdr_len;
|
||||
length = skb->len - hdr_len;
|
||||
element = buf->next_element_to_fill;
|
||||
/*fill first buffer entry only with header information */
|
||||
buffer->element[element].addr = skb->data;
|
||||
buffer->element[element].length = hdr_len;
|
||||
buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
|
||||
buf->next_element_to_fill++;
|
||||
|
||||
if (skb_shinfo(skb)->nr_frags > 0) {
|
||||
__qeth_tso_fill_buffer_frag(buf, skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*start filling buffer entries ...*/
|
||||
element++;
|
||||
while (length > 0) {
|
||||
/* length_here is the remaining amount of data in this page */
|
||||
length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
|
||||
if (length < length_here)
|
||||
length_here = length;
|
||||
buffer->element[element].addr = data;
|
||||
buffer->element[element].length = length_here;
|
||||
length -= length_here;
|
||||
if (!length)
|
||||
buffer->element[element].flags =
|
||||
SBAL_FLAGS_LAST_FRAG;
|
||||
else
|
||||
buffer->element[element].flags =
|
||||
SBAL_FLAGS_MIDDLE_FRAG;
|
||||
data += length_here;
|
||||
element++;
|
||||
}
|
||||
/*set the buffer to primed ...*/
|
||||
buf->next_element_to_fill = element;
|
||||
out:
|
||||
atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
qeth_tso_send_packet(struct qeth_card *card, struct sk_buff *skb,
|
||||
struct qeth_qdio_out_q *queue, int ipv, int cast_type)
|
||||
{
|
||||
int flush_cnt = 0;
|
||||
struct qeth_hdr_tso *hdr;
|
||||
struct qeth_qdio_out_buffer *buffer;
|
||||
int start_index;
|
||||
|
||||
QETH_DBF_TEXT(trace, 3, "tsosend");
|
||||
|
||||
if (!(hdr = qeth_tso_prepare_packet(card, skb, ipv, cast_type)))
|
||||
return -ENOMEM;
|
||||
/*check if skb fits in one SBAL ...*/
|
||||
if (!(qeth_get_elements_no(card, (void*)hdr, skb)))
|
||||
return -EINVAL;
|
||||
/*lock queue, force switching to non-packing and send it ...*/
|
||||
while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED,
|
||||
QETH_OUT_Q_LOCKED,
|
||||
&queue->state));
|
||||
start_index = queue->next_buf_to_fill;
|
||||
buffer = &queue->bufs[queue->next_buf_to_fill];
|
||||
/*check if card is too busy ...*/
|
||||
if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){
|
||||
card->stats.tx_dropped++;
|
||||
goto out;
|
||||
}
|
||||
/*let's force to non-packing and get a new SBAL*/
|
||||
flush_cnt += qeth_tso_get_queue_buffer(queue);
|
||||
buffer = &queue->bufs[queue->next_buf_to_fill];
|
||||
if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) {
|
||||
card->stats.tx_dropped++;
|
||||
goto out;
|
||||
}
|
||||
flush_cnt += qeth_tso_fill_buffer(buffer, skb);
|
||||
queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
|
||||
QDIO_MAX_BUFFERS_PER_Q;
|
||||
out:
|
||||
atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
|
||||
if (flush_cnt)
|
||||
qeth_flush_buffers(queue, 0, start_index, flush_cnt);
|
||||
/*do some statistics */
|
||||
card->stats.tx_packets++;
|
||||
card->stats.tx_bytes += skb->len;
|
||||
return 0;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue