diff options
39 files changed, 699 insertions, 874 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index f16a46e8849..97b64d7d6bf 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -614,10 +614,14 @@ config X86_PAE # Common NUMA Features config NUMA - bool "Numa Memory Allocation and Scheduler Support" - depends on SMP && HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT || X86_GENERICARCH) && ACPI) + bool "Numa Memory Allocation and Scheduler Support (EXPERIMENTAL)" + depends on SMP && HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT || X86_GENERICARCH) && ACPI) && EXPERIMENTAL default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT) + help + NUMA support for i386. This is currently high experimental + and should be only used for kernel development. It might also + cause boot failures. comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI" depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI) diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index 01ffdd4964f..fcb38e7f354 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -249,9 +249,10 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) pmd_k = pmd_offset(pud_k, address); if (!pmd_present(*pmd_k)) return NULL; - if (!pmd_present(*pmd)) + if (!pmd_present(*pmd)) { set_pmd(pmd, *pmd_k); - else + arch_flush_lazy_mmu_mode(); + } else BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k)); return pmd_k; } diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 9fb0ce5c717..114c90f8f56 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -251,6 +251,8 @@ DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8568E, quirk_fsl_pcie_transpare DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8568, quirk_fsl_pcie_transparent); DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8567E, quirk_fsl_pcie_transparent); DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8567, quirk_fsl_pcie_transparent); +DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8533E, quirk_fsl_pcie_transparent); +DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8533, quirk_fsl_pcie_transparent); DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8544E, quirk_fsl_pcie_transparent); DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8544, quirk_fsl_pcie_transparent); DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_transparent); diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index ad4ca75c0f0..5245717295b 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c @@ -60,17 +60,28 @@ static void hypfs_add_dentry(struct dentry *dentry) hypfs_last_dentry = dentry; } +static inline int hypfs_positive(struct dentry *dentry) +{ + return dentry->d_inode && !d_unhashed(dentry); +} + static void hypfs_remove(struct dentry *dentry) { struct dentry *parent; parent = dentry->d_parent; - if (S_ISDIR(dentry->d_inode->i_mode)) - simple_rmdir(parent->d_inode, dentry); - else - simple_unlink(parent->d_inode, dentry); + if (!parent || !parent->d_inode) + return; + mutex_lock(&parent->d_inode->i_mutex); + if (hypfs_positive(dentry)) { + if (S_ISDIR(dentry->d_inode->i_mode)) + simple_rmdir(parent->d_inode, dentry); + else + simple_unlink(parent->d_inode, dentry); + } d_delete(dentry); dput(dentry); + mutex_unlock(&parent->d_inode->i_mutex); } static void hypfs_delete_tree(struct dentry *root) @@ -315,6 +326,7 @@ static int hypfs_fill_super(struct super_block *sb, void *data, int silent) } hypfs_update_update(sb); sb->s_root = root_dentry; + printk(KERN_INFO "hypfs: Hypervisor filesystem mounted\n"); return 0; err_tree: @@ -356,13 +368,17 @@ static struct dentry *hypfs_create_file(struct super_block *sb, qname.name = name; qname.len = strlen(name); qname.hash = full_name_hash(name, qname.len); + mutex_lock(&parent->d_inode->i_mutex); dentry = lookup_one_len(name, parent, strlen(name)); - if (IS_ERR(dentry)) - return ERR_PTR(-ENOMEM); + if (IS_ERR(dentry)) { + dentry = ERR_PTR(-ENOMEM); + goto fail; + } inode = hypfs_make_inode(sb, mode); if (!inode) { dput(dentry); - return ERR_PTR(-ENOMEM); + dentry = ERR_PTR(-ENOMEM); + goto fail; } if (mode & S_IFREG) { inode->i_fop = &hypfs_file_ops; @@ -379,6 +395,8 @@ static struct dentry *hypfs_create_file(struct super_block *sb, inode->i_private = data; d_instantiate(dentry, inode); dget(dentry); +fail: + mutex_unlock(&parent->d_inode->i_mutex); return dentry; } @@ -391,7 +409,6 @@ struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent, if (IS_ERR(dentry)) return dentry; hypfs_add_dentry(dentry); - parent->d_inode->i_nlink++; return dentry; } diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 3195d375bd5..56cb71007cd 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional obj-y := bitmap.o traps.o time.o process.o base.o early.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ - semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o + semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o diag.o obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) diff --git a/arch/s390/kernel/diag.c b/arch/s390/kernel/diag.c new file mode 100644 index 00000000000..c032d11da8a --- /dev/null +++ b/arch/s390/kernel/diag.c @@ -0,0 +1,102 @@ +/* + * Implementation of s390 diagnose codes + * + * Copyright IBM Corp. 2007 + * Author(s): Michael Holzheu <holzheu@de.ibm.com> + */ + +#include <linux/module.h> +#include <asm/diag.h> + +/* + * Diagnose 10: Release pages + */ +void diag10(unsigned long addr) +{ + if (addr >= 0x7ff00000) + return; + asm volatile( +#ifdef CONFIG_64BIT + " sam31\n" + " diag %0,%0,0x10\n" + "0: sam64\n" +#else + " diag %0,%0,0x10\n" + "0:\n" +#endif + EX_TABLE(0b, 0b) + : : "a" (addr)); +} +EXPORT_SYMBOL(diag10); + +/* + * Diagnose 14: Input spool file manipulation + */ +int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode) +{ + register unsigned long _ry1 asm("2") = ry1; + register unsigned long _ry2 asm("3") = subcode; + int rc = 0; + + asm volatile( +#ifdef CONFIG_64BIT + " sam31\n" + " diag %2,2,0x14\n" + " sam64\n" +#else + " diag %2,2,0x14\n" +#endif + " ipm %0\n" + " srl %0,28\n" + : "=d" (rc), "+d" (_ry2) + : "d" (rx), "d" (_ry1) + : "cc"); + + return rc; +} +EXPORT_SYMBOL(diag14); + +/* + * Diagnose 210: Get information about a virtual device + */ +int diag210(struct diag210 *addr) +{ + /* + * diag 210 needs its data below the 2GB border, so we + * use a static data area to be sure + */ + static struct diag210 diag210_tmp; + static DEFINE_SPINLOCK(diag210_lock); + unsigned long flags; + int ccode; + + spin_lock_irqsave(&diag210_lock, flags); + diag210_tmp = *addr; + +#ifdef CONFIG_64BIT + asm volatile( + " lhi %0,-1\n" + " sam31\n" + " diag %1,0,0x210\n" + "0: ipm %0\n" + " srl %0,28\n" + "1: sam64\n" + EX_TABLE(0b, 1b) + : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); +#else + asm volatile( + " lhi %0,-1\n" + " diag %1,0,0x210\n" + "0: ipm %0\n" + " srl %0,28\n" + "1:\n" + EX_TABLE(0b, 1b) + : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); +#endif + + *addr = diag210_tmp; + spin_unlock_irqrestore(&diag210_lock, flags); + + return ccode; +} +EXPORT_SYMBOL(diag210); diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index d3057318f2b..50d2235df73 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c @@ -577,7 +577,7 @@ static struct insn opcode_b2[] = { { "esta", 0x4a, INSTR_RRE_RR }, { "lura", 0x4b, INSTR_RRE_RR }, { "tar", 0x4c, INSTR_RRE_AR }, - { "cpya", INSTR_RRE_AA }, + { "cpya", 0x4d, INSTR_RRE_AA }, { "sar", 0x4e, INSTR_RRE_AR }, { "ear", 0x4f, INSTR_RRE_RA }, { "csp", 0x50, INSTR_RRE_RR }, diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 358d2bbbc48..e40373d9fbc 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c @@ -85,7 +85,7 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn) ainsn->reg = (*ainsn->insn & 0xf0) >> 4; /* save the instruction length (pop 5-5) in bytes */ - switch (*(__u8 *) (ainsn->insn) >> 4) { + switch (*(__u8 *) (ainsn->insn) >> 6) { case 0: ainsn->ilen = 2; break; diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 90b5ef529eb..7234c737f82 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c @@ -25,7 +25,6 @@ EXPORT_SYMBOL(_oi_bitmap); EXPORT_SYMBOL(_ni_bitmap); EXPORT_SYMBOL(_zb_findmap); EXPORT_SYMBOL(_sb_findmap); -EXPORT_SYMBOL(diag10); /* * semaphore ops diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index c5b2f4f078b..fabc50adc46 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c @@ -20,6 +20,7 @@ #include <asm/pgalloc.h> #include <asm/uaccess.h> +#include <asm/diag.h> static char *sender = "VMRMSVM"; module_param(sender, charp, 0400); diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 9098531a267..3a25bbf2eb0 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -42,23 +42,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); -void diag10(unsigned long addr) -{ - if (addr >= 0x7ff00000) - return; - asm volatile( -#ifdef CONFIG_64BIT - " sam31\n" - " diag %0,%0,0x10\n" - "0: sam64\n" -#else - " diag %0,%0,0x10\n" - "0:\n" -#endif - EX_TABLE(0b,0b) - : : "a" (addr)); -} - void show_mem(void) { int i, total = 0, reserved = 0; diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c index b1a26e02df0..60843b3f3b6 100644 --- a/drivers/isdn/hisax/hfc_usb.c +++ b/drivers/isdn/hisax/hfc_usb.c @@ -1,12 +1,12 @@ /* * hfc_usb.c * - * $Id: hfc_usb.c,v 2.3.2.13 2006/02/17 17:17:22 mbachem Exp $ + * $Id: hfc_usb.c,v 2.3.2.20 2007/08/20 14:07:54 mbachem Exp $ * * modular HiSax ISDN driver for Colognechip HFC-S USB chip * - * Authors : Peter Sprenger (sprenger@moving-bytes.de) - * Martin Bachem (info@colognechip.com) + * Authors : Peter Sprenger (sprenger@moving-bytes.de) + * Martin Bachem (m.bachem@gmx.de, info@colognechip.com) * * based on the first hfc_usb driver of * Werner Cornelius (werner@isdn-development.de) @@ -37,24 +37,25 @@ #include <linux/kernel_stat.h> #include <linux/usb.h> #include <linux/kernel.h> +#include <linux/smp_lock.h> +#include <linux/sched.h> +#include <linux/moduleparam.h> #include "hisax.h" #include "hisax_if.h" #include "hfc_usb.h" static const char *hfcusb_revision = - "$Revision: 2.3.2.13 $ $Date: 2006/02/17 17:17:22 $ "; + "$Revision: 2.3.2.20 $ $Date: 2007/08/20 14:07:54 $ "; /* Hisax debug support -* use "modprobe debug=x" where x is bitfield of USB_DBG & ISDN_DBG +* debug flags defined in hfc_usb.h as HFCUSB_DBG_[*] */ -#ifdef CONFIG_HISAX_DEBUG -#include <linux/moduleparam.h> #define __debug_variable hfc_debug #include "hisax_debug.h" static u_int debug; module_param(debug, uint, 0); static int hfc_debug; -#endif + /* private vendor specific data */ typedef struct { @@ -63,9 +64,7 @@ typedef struct { char *vend_name; // device name } hfcsusb_vdata; -/****************************************/ -/* data defining the devices to be used */ -/****************************************/ +/* VID/PID device list */ static struct usb_device_id hfcusb_idtab[] = { { USB_DEVICE(0x0959, 0x2bd0), @@ -90,49 +89,47 @@ static struct usb_device_id hfcusb_idtab[] = { .driver_info = (unsigned long) &((hfcsusb_vdata) {LED_SCHEME1, {4, 0, 2, 1}, "Stollmann USB TA"}), - }, + }, { USB_DEVICE(0x0742, 0x2009), .driver_info = (unsigned long) &((hfcsusb_vdata) {LED_SCHEME1, {4, 0, 2, 1}, "Aceex USB ISDN TA"}), - }, + }, { USB_DEVICE(0x0742, 0x200A), .driver_info = (unsigned long) &((hfcsusb_vdata) {LED_SCHEME1, {4, 0, 2, 1}, "OEM USB ISDN TA"}), - }, + }, { USB_DEVICE(0x08e3, 0x0301), .driver_info = (unsigned long) &((hfcsusb_vdata) {LED_SCHEME1, {2, 0, 1, 4}, "Olitec USB RNIS"}), - }, + }, { USB_DEVICE(0x07fa, 0x0846), .driver_info = (unsigned long) &((hfcsusb_vdata) {LED_SCHEME1, {0x80, -64, -32, -16}, "Bewan Modem RNIS USB"}), - }, + }, { USB_DEVICE(0x07fa, 0x0847), .driver_info = (unsigned long) &((hfcsusb_vdata) {LED_SCHEME1, {0x80, -64, -32, -16}, "Djinn Numeris USB"}), - }, + }, { USB_DEVICE(0x07b0, 0x0006), .driver_info = (unsigned long) &((hfcsusb_vdata) {LED_SCHEME1, {0x80, -64, -32, -16}, "Twister ISDN TA"}), - }, + }, { } }; -/***************************************************************/ /* structure defining input+output fifos (interrupt/bulk mode) */ -/***************************************************************/ struct usb_fifo; /* forward definition */ typedef struct iso_urb_struct { struct urb *purb; @@ -140,8 +137,8 @@ typedef struct iso_urb_struct { struct usb_fifo *owner_fifo; /* pointer to owner fifo */ } iso_urb_struct; - struct hfcusb_data; /* forward definition */ + typedef struct usb_fifo { int fifonum; /* fifo index attached to this structure */ int active; /* fifo is currently active */ @@ -160,15 +157,12 @@ typedef struct usb_fifo { struct hisax_if *hif; /* hisax interface */ int delete_flg; /* only delete skbuff once */ int last_urblen; /* remember length of last packet */ - } usb_fifo; -/*********************************************/ /* structure holding all data for one device */ -/*********************************************/ typedef struct hfcusb_data { /* HiSax Interface for loadable Layer1 drivers */ - struct hisax_d_if d_if; /* see hisax_if.h */ + struct hisax_d_if d_if; /* see hisax_if.h */ struct hisax_b_if b_if[2]; /* see hisax_if.h */ int protocol; @@ -176,12 +170,13 @@ typedef struct hfcusb_data { int if_used; /* used interface number */ int alt_used; /* used alternate config */ int ctrl_paksize; /* control pipe packet size */ - int ctrl_in_pipe, ctrl_out_pipe; /* handles for control pipe */ + int ctrl_in_pipe, /* handles for control pipe */ + ctrl_out_pipe; int cfg_used; /* configuration index used */ int vend_idx; /* vendor found */ int b_mode[2]; /* B-channel mode */ int l1_activated; /* layer 1 activated */ - int disc_flag; /* 'true' if device was disonnected to avoid some USB actions */ + int disc_flag; /* TRUE if device was disonnected to avoid some USB actions */ int packet_size, iso_packet_size; /* control pipe background handling */ @@ -208,7 +203,6 @@ typedef struct hfcusb_data { static void collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish); - static inline const char * symbolic(struct hfcusb_symbolic_list list[], const int num) { @@ -219,10 +213,6 @@ symbolic(struct hfcusb_symbolic_list list[], const int num) return "<unknown ERROR>"; } - -/******************************************************/ -/* start next background transfer for control channel */ -/******************************************************/ static void ctrl_start_transfer(hfcusb_data * hfc) { @@ -240,10 +230,6 @@ ctrl_start_transfer(hfcusb_data * hfc) } } /* ctrl_start_transfer */ -/************************************/ -/* queue a control transfer request */ -/* return 0 on success. */ -/************************************/ static int queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val, int action) { @@ -260,19 +246,8 @@ queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val, int action) if (++hfc->ctrl_cnt == 1) ctrl_start_transfer(hfc); return (0); -} /* queue_control_request */ - -static int -control_action_handler(hfcusb_data * hfc, int reg, int val, int action) -{ - if (!action) - return (1); /* no action defined */ - return (0); } -/***************************************************************/ -/* control completion routine handling background control cmds */ -/***************************************************************/ static void ctrl_complete(struct urb *urb) { @@ -282,9 +257,6 @@ ctrl_complete(struct urb *urb) urb->dev = hfc->dev; if (hfc->ctrl_cnt) { buf = &hfc->ctrl_buff[hfc->ctrl_out_idx]; - control_action_handler(hfc, buf->hfc_reg, buf->reg_val, - buf->action); - hfc->ctrl_cnt--; /* decrement actual count */ if (++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE) hfc->ctrl_out_idx = 0; /* pointer wrap */ @@ -293,9 +265,7 @@ ctrl_complete(struct urb *urb) } } /* ctrl_complete */ -/***************************************************/ /* write led data to auxport & invert if necessary */ -/***************************************************/ static void write_led(hfcusb_data * hfc, __u8 led_state) { @@ -305,9 +275,6 @@ write_led(hfcusb_data * hfc, __u8 led_state) } } -/**************************/ -/* handle LED bits */ -/**************************/ static void set_led_bit(hfcusb_data * hfc, signed short led_bits, int unset) { @@ -324,9 +291,7 @@ set_led_bit(hfcusb_data * hfc, signed short led_bits, int unset) } } -/**************************/ -/* handle LED requests */ -/**************************/ +/* handle LED requests */ static void handle_led(hfcusb_data * hfc, int event) { @@ -339,85 +304,73 @@ handle_led(hfcusb_data * hfc, int event) switch (event) { case LED_POWER_ON: - set_led_bit(hfc, driver_info->led_bits[0], - 0); - set_led_bit(hfc, driver_info->led_bits[1], - 1); - set_led_bit(hfc, driver_info->led_bits[2], - 1); - set_led_bit(hfc, driver_info->led_bits[3], - 1); + set_led_bit(hfc, driver_info->led_bits[0], 0); + set_led_bit(hfc, driver_info->led_bits[1], 1); + set_led_bit(hfc, driver_info->led_bits[2], 1); + set_led_bit(hfc, driver_info->led_bits[3], 1); break; - case LED_POWER_OFF: /* no Power off handling */ + case LED_POWER_OFF: + set_led_bit(hfc, driver_info->led_bits[0], 1); + set_led_bit(hfc, driver_info->led_bits[1], 1); + set_led_bit(hfc, driver_info->led_bits[2], 1); + set_led_bit(hfc, driver_info->led_bits[3], 1); break; case LED_S0_ON: - set_led_bit(hfc, driver_info->led_bits[1], - 0); + set_led_bit(hfc, driver_info->led_bits[1], 0); break; case LED_S0_OFF: - set_led_bit(hfc, driver_info->led_bits[1], - 1); + set_led_bit(hfc, driver_info->led_bits[1], 1); break; case LED_B1_ON: - set_led_bit(hfc, driver_info->led_bits[2], - 0); + set_led_bit(hfc, driver_info->led_bits[2], 0); break; case LED_B1_OFF: - set_led_bit(hfc, driver_info->led_bits[2], - 1); + set_led_bit(hfc, driver_info->led_bits[2], 1); break; case LED_B2_ON: - set_led_bit(hfc, driver_info->led_bits[3], - 0); + set_led_bit(hfc, driver_info->led_bits[3], 0); break; case LED_B2_OFF: - set_led_bit(hfc, driver_info->led_bits[3], - 1); + set_led_bit(hfc, driver_info->led_bits[3], 1); break; } write_led(hfc, hfc->led_state); } -/********************************/ -/* called when timer t3 expires */ -/********************************/ +/* ISDN l1 timer T3 expires */ static void l1_timer_expire_t3(hfcusb_data * hfc) { hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION, NULL); -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, + + DBG(HFCUSB_DBG_STATES, "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T3 expire)"); -#endif - hfc->l1_activated = false; + + hfc->l1_activated = 0; handle_led(hfc, LED_S0_OFF); /* deactivate : */ queue_control_request(hfc, HFCUSB_STATES, 0x10, 1); queue_control_request(hfc, HFCUSB_STATES, 3, 1); } -/********************************/ -/* called when timer t4 expires */ -/********************************/ +/* ISDN l1 timer T4 expires */ static void l1_timer_expire_t4(hfcusb_data * hfc) { hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION, NULL); -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, + + DBG(HFCUSB_DBG_STATES, "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T4 expire)"); -#endif - hfc->l1_activated = false; + + hfc->l1_activated = 0; handle_led(hfc, LED_S0_OFF); } -/*****************************/ -/* handle S0 state changes */ -/*****************************/ +/* S0 state changed */ static void -state_handler(hfcusb_data * hfc, __u8 state) +s0_state_handler(hfcusb_data * hfc, __u8 state) { __u8 old_state; @@ -425,38 +378,29 @@ state_handler(hfcusb_data * hfc, __u8 state) if (state == old_state || state < 1 || state > 8) return; -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, "HFC-S USB: new S0 state:%d old_state:%d", state, - old_state); -#endif + DBG(HFCUSB_DBG_STATES, "HFC-S USB: S0 statechange(%d -> %d)", + old_state, state); + if (state < 4 || state == 7 || state == 8) { if (timer_pending(&hfc->t3_timer)) del_timer(&hfc->t3_timer); -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, "HFC-S USB: T3 deactivated"); -#endif + DBG(HFCUSB_DBG_STATES, "HFC-S USB: T3 deactivated"); } if (state >= 7) { if (timer_pending(&hfc->t4_timer)) del_timer(&hfc->t4_timer); -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, "HFC-S USB: T4 deactivated"); -#endif + DBG(HFCUSB_DBG_STATES, "HFC-S USB: T4 deactivated"); } if (state == 7 && !hfc->l1_activated) { hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_ACTIVATE | INDICATION, NULL); -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, "HFC-S USB: PH_ACTIVATE | INDICATION sent"); -#endif - hfc->l1_activated = true; + DBG(HFCUSB_DBG_STATES, "HFC-S USB: PH_ACTIVATE | INDICATION sent"); + hfc->l1_activated = 1; handle_led(hfc, LED_S0_ON); } else if (state <= 3 /* && activated */ ) { if (old_state == 7 || old_state == 8) { -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, "HFC-S USB: T4 activated"); -#endif + DBG(HFCUSB_DBG_STATES, "HFC-S USB: T4 activated"); if (!timer_pending(&hfc->t4_timer)) { hfc->t4_timer.expires = jiffies + (HFC_TIMER_T4 * HZ) / 1000; @@ -466,18 +410,15 @@ state_handler(hfcusb_data * hfc, __u8 state) hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION, NULL); -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, + DBG(HFCUSB_DBG_STATES, "HFC-S USB: PH_DEACTIVATE | INDICATION sent"); -#endif - hfc->l1_activated = false; + hfc->l1_activated = 0; handle_led(hfc, LED_S0_OFF); } } hfc->l1_state = state; } -/* prepare iso urb */ static void fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *buf, int num_packets, int packet_size, int interval, @@ -503,15 +444,16 @@ fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, } /* allocs urbs and start isoc transfer with two pending urbs to avoid - gaps in the transfer chain */ + * gaps in the transfer chain + */ static int start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb, usb_complete_t complete, int packet_size) { int i, k, errcode; - printk(KERN_INFO "HFC-S USB: starting ISO-chain for Fifo %i\n", - fifo->fifonum); + DBG(HFCUSB_DBG_INIT, "HFC-S USB: starting ISO-URBs for fifo:%d\n", + fifo->fifonum); /* allocate Memory for Iso out Urbs */ for (i = 0; i < 2; i++) { @@ -556,10 +498,9 @@ start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb, errcode = usb_submit_urb(fifo->iso[i].purb, GFP_KERNEL); fifo->active = (errcode >= 0) ? 1 : 0; - if (errcode < 0) { - printk(KERN_INFO "HFC-S USB: %s URB nr:%d\n", - symbolic(urb_errlist, errcode), i); - }; + if (errcode < 0) + printk(KERN_INFO "HFC-S USB: usb_submit_urb URB nr:%d, error(%i): '%s'\n", + i, errcode, symbolic(urb_errlist, errcode)); } return (fifo->active); } @@ -572,16 +513,15 @@ stop_isoc_chain(usb_fifo * fifo) for (i = 0; i < 2; i++) { if (fifo->iso[i].purb) { -#ifdef CONFIG_HISAX_DEBUG - DBG(USB_DBG, + DBG(HFCUSB_DBG_INIT, "HFC-S USB: Stopping iso chain for fifo %i.%i", fifo->fifonum, i); -#endif usb_kill_urb(fifo->iso[i].purb); usb_free_urb(fifo->iso[i].purb); fifo->iso[i].purb = NULL; } } + usb_kill_urb(fifo->urb); usb_free_urb(fifo->urb); fifo->urb = NULL; @@ -594,9 +534,6 @@ static int iso_packets[8] = ISOC_PACKETS_D, ISOC_PACKETS_D, ISOC_PACKETS_D, ISOC_PACKETS_D }; -/*****************************************************/ -/* transmit completion routine for all ISO tx fifos */ -/*****************************************************/ static void tx_iso_complete(struct urb *urb) { @@ -607,20 +544,38 @@ tx_iso_complete(struct urb *urb) errcode; int frame_complete, transp_mode, fifon, status; __u8 threshbit; - __u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80 }; fifon = fifo->fifonum; status = urb->status; tx_offset = 0; + /* ISO transfer only partially completed, + look at individual frame status for details */ + if (status == -EXDEV) { + DBG(HFCUSB_DBG_VERBOSE_USB, "HFC-S USB: tx_iso_complete with -EXDEV" + ", urb->status %d, fifonum %d\n", + status, fifon); + + for (k = 0; k < iso_packets[fifon]; ++k) { + errcode = urb->iso_frame_desc[k].status; + if (errcode) + DBG(HFCUSB_DBG_VERBOSE_USB, "HFC-S USB: tx_iso_complete " + "packet %i, status: %i\n", + k, errcode); + } + + // clear status, so go on with ISO transfers + status = 0; + } + if (fifo->active && !status) { transp_mode = 0; if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS) - transp_mode = true; + transp_mode = 1; /* is FifoFull-threshold set for our channel? */ - threshbit = threshtable[fifon] & hfc->threshold_mask; + threshbit = (hfc->threshold_mask & (1 << fifon)); num_isoc_packets = iso_packets[fifon]; /* predict dataflow to avoid fifo overflow */ @@ -635,8 +590,9 @@ tx_iso_complete(struct urb *urb) tx_iso_complete, urb->context); memset(context_iso_urb->buffer, 0, sizeof(context_iso_urb->buffer)); - frame_complete = false; - /* Generate next Iso Packets */ + frame_complete = 0; + + /* Generate next ISO Packets */ for (k = 0; k < num_isoc_packets; ++k) { if (fifo->skbuff) { len = fifo->skbuff->len; @@ -661,7 +617,7 @@ tx_iso_complete(struct urb *urb) /* add 2 byte flags and 16bit CRC at end of ISDN frame */ fifo->bit_line += 32; } - frame_complete = true; + frame_complete = 1; } memcpy(context_iso_urb->buffer + @@ -688,7 +644,7 @@ tx_iso_complete(struct urb *urb) } if (frame_complete) { - fifo->delete_flg = true; + fifo->delete_flg = 1; fifo->hif->l1l2(fifo->hif, PH_DATA | CONFIRM, (void *) (unsigned long) fifo->skbuff-> @@ -696,30 +652,26 @@ tx_iso_complete(struct urb *urb) if (fifo->skbuff && fifo->delete_flg) { dev_kfree_skb_any(fifo->skbuff); fifo->skbuff = NULL; - fifo->delete_flg = false; + fifo->delete_flg = 0; } - frame_complete = false; + frame_complete = 0; } } errcode = usb_submit_urb(urb, GFP_ATOMIC); if (errcode < 0) { printk(KERN_INFO - "HFC-S USB: error submitting ISO URB: %d \n", + "HFC-S USB: error submitting ISO URB: %d\n", errcode); } } else { if (status && !hfc->disc_flag) { printk(KERN_INFO - "HFC-S USB: tx_iso_complete : urb->status %s (%i), fifonum=%d\n", - symbolic(urb_errlist, status), status, - fifon); + "HFC-S USB: tx_iso_complete: error(%i): '%s', fifonum=%d\n", + status, symbolic(urb_errlist, status), fifon); } } -} /* tx_iso_complete */ +} -/*****************************************************/ -/* receive completion routine for all ISO tx fifos */ -/*****************************************************/ static void rx_iso_complete(struct urb *urb) { @@ -731,21 +683,25 @@ rx_iso_complete(struct urb *urb) unsigned int iso_status; __u8 *buf; static __u8 eof[8]; -#ifdef CONFIG_HISAX_DEBUG - __u8 i; -#endif fifon = fifo->fifonum; status = urb->status; if (urb->status == -EOVERFLOW) { -#ifdef CONFIG_HISAX_DEBUG - DBG(USB_DBG, - "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n", - fifon); -#endif + DBG(HFCUSB_DBG_VERBOSE_USB, + "HFC-USB: ignoring USB DATAOVERRUN fifo(%i)", fifon); + status = 0; + } + + /* ISO transfer only partially completed, + look at individual frame status for details */ + if (status == -EXDEV) { + DBG(HFCUSB_DBG_VERBOSE_USB, "HFC-S USB: rx_iso_complete with -EXDEV " + "urb->status %d, fifonum %d\n", + status, fifon); status = 0; } + if (fifo->active && !status) { num_isoc_packets = iso_packets[fifon]; maxlen = fifo->usb_packet_maxlen; @@ -754,40 +710,38 @@ rx_iso_complete(struct urb *urb) offset = urb->iso_frame_desc[k].offset; buf = context_iso_urb->buffer + offset; iso_status = urb->iso_frame_desc[k].status; -#ifdef CONFIG_HISAX_DEBUG + if (iso_status && !hfc->disc_flag) - DBG(USB_DBG, - "HFC-S USB: ISO packet failure - status:%x", - iso_status); + DBG(HFCUSB_DBG_VERBOSE_USB, + "HFC-S USB: rx_iso_complete " + "ISO packet %i, status: %i\n", + k, iso_status); - if ((fifon == 5) && (debug > 1)) { - printk(KERN_INFO + if (fifon == HFCUSB_D_RX) { + DBG(HFCUSB_DBG_VERBOSE_USB, "HFC-S USB: ISO-D-RX lst_urblen:%2d " - "act_urblen:%2d max-urblen:%2d " - "EOF:0x%0x DATA: ", + "act_urblen:%2d max-urblen:%2d EOF:0x%0x", fifo->last_urblen, len, maxlen, eof[5]); - for (i = 0; i < len; i++) - printk("%.2x ", buf[i]); - printk("\n"); + + DBG_PACKET(HFCUSB_DBG_VERBOSE_USB, buf, len); } -#endif + if (fifo->last_urblen != maxlen) { /* the threshold mask is in the 2nd status byte */ hfc->threshold_mask = buf[1]; /* care for L1 state only for D-Channel to avoid overlapped iso completions */ - if (fifon == 5) { + if (fifon == HFCUSB_D_RX) { /* the S0 state is in the upper half of the 1st status byte */ - state_handler(hfc, buf[0] >> 4); + s0_state_handler(hfc, buf[0] >> 4); } eof[fifon] = buf[0] & 1; if (len > 2) collect_rx_frame(fifo, buf + 2, len - 2, - (len < - maxlen) ? + (len < maxlen) ? eof[fifon] : 0); } else { collect_rx_frame(fifo, buf, len, @@ -804,41 +758,37 @@ rx_iso_complete(struct urb *urb) rx_iso_complete, urb->context); errcode = usb_submit_urb(urb, GFP_ATOMIC); if (errcode < 0) { - printk(KERN_INFO - "HFC-S USB: error submitting ISO URB: %d \n", + printk(KERN_ERR + "HFC-S USB: error submitting ISO URB: %d\n", errcode); } } else { if (status && !hfc->disc_flag) { - printk(KERN_INFO + printk(KERN_ERR "HFC-S USB: rx_iso_complete : " "urb->status %d, fifonum %d\n", status, fifon); } } -} /* rx_iso_complete */ +} -/*****************************************************/ -/* collect data from interrupt or isochron in */ -/*****************************************************/ +/* collect rx data from INT- and ISO-URBs */ static void collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish) { hfcusb_data *hfc = fifo->hfc; int transp_mode, fifon; -#ifdef CONFIG_HISAX_DEBUG - int i; -#endif + fifon = fifo->fifonum; transp_mode = 0; if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS) - transp_mode = true; + transp_mode = 1; if (!fifo->skbuff) { fifo->skbuff = dev_alloc_skb(fifo->max_size + 3); if (!fifo->skbuff) { - printk(KERN_INFO - "HFC-S USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n", + printk(KERN_ERR + "HFC-S USB: cannot allocate buffer for fifo(%d)\n", fifon); return; } @@ -847,17 +797,11 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish) if (fifo->skbuff->len + len < fifo->max_size) { memcpy(skb_put(fifo->skbuff, len), data, len); } else { -#ifdef CONFIG_HISAX_DEBUG - printk(KERN_INFO "HFC-S USB: "); - for (i = 0; i < 15; i++) - printk("%.2x ", - fifo->skbuff->data[fifo->skbuff-> - len - 15 + i]); - printk("\n"); -#endif - printk(KERN_INFO - "HCF-USB: got frame exceeded fifo->max_size:%d on fifo:%d\n", + DBG(HFCUSB_DBG_FIFO_ERR, + "HCF-USB: got frame exceeded fifo->max_size(%d) fifo(%d)", fifo->max_size, fifon); + DBG_SKB(HFCUSB_DBG_VERBOSE_USB, fifo->skbuff); + skb_trim(fifo->skbuff, 0); } } if (transp_mode && fifo->skbuff->len >= 128) { @@ -870,6 +814,13 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish) if (finish) { if ((!fifo->skbuff->data[fifo->skbuff->len - 1]) && (fifo->skbuff->len > 3)) { + + if (fifon == HFCUSB_D_RX) { + DBG(HFCUSB_DBG_DCHANNEL, + "HFC-S USB: D-RX len(%d)", fifo->skbuff->len); + DBG_SKB(HFCUSB_DBG_DCHANNEL, fifo->skbuff); + } + /* remove CRC & status */ skb_trim(fifo->skbuff, fifo->skbuff->len - 3); if (fifon == HFCUSB_PCM_RX) { @@ -882,39 +833,17 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish) fifo->skbuff); fifo->skbuff = NULL; /* buffer was freed from upper layer */ } else { - if (fifo->skbuff->len > 3) { - printk(KERN_INFO - "HFC-S USB: got frame %d bytes but CRC ERROR on fifo:%d!!!\n", - fifo->skbuff->len, fifon); -#ifdef CONFIG_HISAX_DEBUG - if (debug > 1) { - printk(KERN_INFO "HFC-S USB: "); - for (i = 0; i < 15; i++) - printk("%.2x ", - fifo->skbuff-> - data[fifo->skbuff-> - len - 15 + i]); - printk("\n"); - } -#endif - } -#ifdef CONFIG_HISAX_DEBUG - else { - printk(KERN_INFO - "HFC-S USB: frame to small (%d bytes)!!!\n", - fifo->skbuff->len); - } -#endif + DBG(HFCUSB_DBG_FIFO_ERR, + "HFC-S USB: ERROR frame len(%d) fifo(%d)", + fifo->skbuff->len, fifon); + DBG_SKB(HFCUSB_DBG_VERBOSE_USB, fifo->skbuff); skb_trim(fifo->skbuff, 0); } } } -/***********************************************/ -/* receive completion routine for all rx fifos */ -/***********************************************/ static void -rx_complete(struct urb *urb) +rx_int_complete(struct urb *urb) { int len; int status; @@ -922,18 +851,14 @@ rx_complete(struct urb *urb) usb_fifo *fifo = (usb_fifo *) urb->context; hfcusb_data *hfc = fifo->hfc; static __u8 eof[8]; -#ifdef CONFIG_HISAX_DEBUG - __u8 i; -#endif urb->dev = hfc->dev; /* security init */ fifon = fifo->fifonum; if ((!fifo->active) || (urb->status)) { -#ifdef CONFIG_HISAX_DEBUG - DBG(USB_DBG, "HFC-S USB: RX-Fifo %i is going down (%i)", + DBG(HFCUSB_DBG_INIT, "HFC-S USB: RX-Fifo %i is going down (%i)", fifon, urb->status); -#endif + fifo->urb->interval = 0; /* cancel automatic rescheduling */ if (fifo->skbuff) { dev_kfree_skb_any(fifo->skbuff); @@ -945,22 +870,20 @@ rx_complete(struct urb *urb) buf = fifo->buffer; maxlen = fifo->usb_packet_maxlen; -#ifdef CONFIG_HISAX_DEBUG - if ((fifon == 5) && (debug > 1)) { - printk(KERN_INFO - "HFC-S USB: INT-D-RX lst_urblen:%2d act_urblen:%2d max-urblen:%2d EOF:0x%0x DATA: ", - fifo->last_urblen, len, maxlen, eof[5]); - for (i = 0; i < len; i++) - printk("%.2x ", buf[i]); - printk("\n"); + if (fifon == HFCUSB_D_RX) { + DBG(HFCUSB_DBG_VERBOSE_USB, + "HFC-S USB: INT-D-RX lst_urblen:%2d " + "act_urblen:%2d max-urblen:%2d EOF:0x%0x", + fifo->last_urblen, len, maxlen, + eof[5]); + DBG_PACKET(HFCUSB_DBG_VERBOSE_USB, buf, len); } -#endif if (fifo->last_urblen != fifo->usb_packet_maxlen) { /* the threshold mask is in the 2nd status byte */ hfc->threshold_mask = buf[1]; /* the S0 state is in the upper half of the 1st status byte */ - state_handler(hfc, buf[0] >> 4); + s0_state_handler(hfc, buf[0] >> 4); eof[fifon] = buf[0] & 1; /* if we have more than the 2 status bytes -> collect data */ if (len > 2) @@ -975,20 +898,19 @@ rx_complete(struct urb *urb) status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { printk(KERN_INFO - "HFC-S USB: error resubmitting URN at rx_complete...\n"); + "HFC-S USB: %s error resubmitting URB fifo(%d)\n", + __FUNCTION__, fifon); } -} /* rx_complete */ +} -/***************************************************/ -/* start the interrupt transfer for the given fifo */ -/***************************************************/ +/* start initial INT-URB for certain fifo */ static void start_int_fifo(usb_fifo * fifo) { int errcode; - printk(KERN_INFO "HFC-S USB: starting intr IN fifo:%d\n", - fifo->fifonum); + DBG(HFCUSB_DBG_INIT, "HFC-S USB: starting RX INT-URB for fifo:%d\n", + fifo->fifonum); if (!fifo->urb) { fifo->urb = usb_alloc_urb(0, GFP_KERNEL); @@ -997,33 +919,28 @@ start_int_fifo(usb_fifo * fifo) } usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer, fifo->usb_packet_maxlen, - rx_complete, fifo, fifo->intervall); + rx_int_complete, fifo, fifo->intervall); fifo->active = 1; /* must be marked active */ errcode = usb_submit_urb(fifo->urb, GFP_KERNEL); if (errcode) { - printk(KERN_INFO + printk(KERN_ERR "HFC-S USB: submit URB error(start_int_info): status:%i\n", errcode); fifo->active = 0; fifo->skbuff = NULL; } -} /* start_int_fifo */ +} -/*****************************/ -/* set the B-channel mode */ -/*****************************/ static void -set_hfcmode(hfcusb_data * hfc, int channel, int mode) +setup_bchannel(hfcusb_data * hfc, int channel, int mode) { __u8 val, idx_table[2] = { 0, 2 }; if (hfc->disc_flag) { return; } -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, "HFC-S USB: setting channel %d to mode %d", channel, - mode); -#endif + DBG(HFCUSB_DBG_STATES, "HFC-S USB: setting channel %d to mode %d", + channel, mode); hfc->b_mode[channel] = mode; /* setup CON_HDLC */ @@ -1080,20 +997,17 @@ hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg) switch (pr) { case PH_ACTIVATE | REQUEST: if (fifo->fifonum == HFCUSB_D_TX) { -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, + DBG(HFCUSB_DBG_STATES, "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST"); -#endif + if (hfc->l1_state != 3 && hfc->l1_state != 7) { hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION, NULL); -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, + DBG(HFCUSB_DBG_STATES, "HFC-S USB: PH_DEACTIVATE | INDICATION sent (not state 3 or 7)"); -#endif } else { if (hfc->l1_state == 7) { /* l1 already active */ hfc->d_if.ifc.l1l2(&hfc-> @@ -1103,10 +1017,8 @@ hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg) | INDICATION, NULL); -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, + DBG(HFCUSB_DBG_STATES, "HFC-S USB: PH_ACTIVATE | INDICATION sent again ;)"); -#endif } else { /* force sending sending INFO1 */ queue_control_request(hfc, @@ -1132,11 +1044,9 @@ hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg) } } } else { -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, - "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST"); -#endif - set_hfcmode(hfc, + DBG(HFCUSB_DBG_STATES, + "HFC_USB: hfc_usb_d_l2l1 B-chan: PH_ACTIVATE | REQUEST"); + setup_bchannel(hfc, (fifo->fifonum == HFCUSB_B1_TX) ? 0 : 1, (long) arg); @@ -1147,18 +1057,12 @@ hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg) break; case PH_DEACTIVATE | REQUEST: if (fifo->fifonum == HFCUSB_D_TX) { -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, + DBG(HFCUSB_DBG_STATES, "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST"); -#endif - printk(KERN_INFO - "HFC-S USB: ISDN TE device should not deativate...\n"); } else { -#ifdef CONFIG_HISAX_DEBUG - DBG(ISDN_DBG, + DBG(HFCUSB_DBG_STATES, "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST"); -#endif - set_hfcmode(hfc, + setup_bchannel(hfc, (fifo->fifonum == HFCUSB_B1_TX) ? 0 : 1, (int) L1_MODE_NULL); @@ -1171,25 +1075,20 @@ hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg) if (fifo->skbuff && fifo->delete_flg) { dev_kfree_skb_any(fifo->skbuff); fifo->skbuff = NULL; - fifo->delete_flg = false; + fifo->delete_flg = 0; } fifo->skbuff = arg; /* we have a new buffer */ break; default: - printk(KERN_INFO - "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n", - pr); + DBG(HFCUSB_DBG_STATES, + "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x", pr); break; } } -/***************************************************************************/ -/* usb_init is called once when a new matching device is detected to setup */ -/* main parameters. It registers the driver at the main hisax module. */ -/* on success 0 is returned. */ -/***************************************************************************/ +/* initial init HFC-S USB chip registers, HiSax interface, USB URBs */ static int -usb_init(hfcusb_data * hfc) +hfc_usb_init(hfcusb_data * hfc) { usb_fifo *fifo; int i, err; @@ -1214,11 +1113,11 @@ usb_init(hfcusb_data * hfc) /* aux = output, reset off */ write_usb(hfc, HFCUSB_CIRM, 0x10); - /* set USB_SIZE to match the wMaxPacketSize for INT or BULK transfers */ + /* set USB_SIZE to match wMaxPacketSize for INT or BULK transfers */ write_usb(hfc, HFCUSB_USB_SIZE, (hfc->packet_size / 8) | ((hfc->packet_size / 8) << 4)); - /* set USB_SIZE_I to match the wMaxPacketSize for ISO transfers */ + /* set USB_SIZE_I to match wMaxPacketSize for ISO transfers */ write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size); /* enable PCM/GCI master mode */ @@ -1257,8 +1156,8 @@ usb_init(hfcusb_data * hfc) hfc->b_mode[0] = L1_MODE_NULL; hfc->b_mode[1] = L1_MODE_NULL; - hfc->l1_activated = false; - hfc->disc_flag = false; + hfc->l1_activated = 0; + hfc->disc_flag = 0; hfc->led_state = 0; hfc->led_new_data = 0; hfc->old_led_state = 0; @@ -1349,11 +1248,9 @@ usb_init(hfcusb_data * hfc) handle_led(hfc, LED_POWER_ON); return (0); -} /* usb_init */ +} -/*************************************************/ -/* function called to probe a new plugged device */ -/*************************************************/ +/* initial callback for each plugged USB device */ static int hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -1378,11 +1275,6 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) } } -#ifdef CONFIG_HISAX_DEBUG - DBG(USB_DBG, - "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n", ifnum, - iface->desc.bAlternateSetting, intf->minor); -#endif printk(KERN_INFO "HFC-S USB: probing interface(%d) actalt(%d) minor(%d)\n", ifnum, iface->desc.bAlternateSetting, intf->minor); @@ -1403,15 +1295,11 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) /* check for config EOL element */ while (validconf[cfg_used][0]) { - cfg_found = true; + cfg_found = 1; vcf = validconf[cfg_used]; /* first endpoint descriptor */ ep = iface->endpoint; -#ifdef CONFIG_HISAX_DEBUG - DBG(USB_DBG, - "HFC-S USB: (if=%d alt=%d cfg_used=%d)\n", - ifnum, probe_alt_setting, cfg_used); -#endif + memcpy(cmptbl, vcf, 16 * sizeof(int)); /* check for all endpoints in this alternate setting */ @@ -1425,7 +1313,7 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) idx++; attr = ep->desc.bmAttributes; if (cmptbl[idx] == EP_NUL) { - cfg_found = false; + cfg_found = 0; } if (attr == USB_ENDPOINT_XFER_INT && cmptbl[idx] == EP_INT) @@ -1438,16 +1326,9 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) cmptbl[idx] = EP_NUL; /* check if all INT endpoints match minimum interval */ - if (attr == USB_ENDPOINT_XFER_INT - && ep->desc.bInterval < - vcf[17]) { -#ifdef CONFIG_HISAX_DEBUG - if (cfg_found) - DBG(USB_DBG, - "HFC-S USB: Interrupt Endpoint interval < %d found - skipping config", - vcf[17]); -#endif - cfg_found = false; + if ((attr == USB_ENDPOINT_XFER_INT) + && (ep->desc.bInterval < vcf[17])) { + cfg_found = 0; } ep++; } @@ -1455,7 +1336,7 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) /* all entries must be EP_NOP or EP_NUL for a valid config */ if (cmptbl[i] != EP_NOP && cmptbl[i] != EP_NUL) - cfg_found = false; + cfg_found = 0; } if (cfg_found) { if (cfg_used < small_match) { @@ -1464,23 +1345,16 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) probe_alt_setting; iface_used = iface; } -#ifdef CONFIG_HISAX_DEBUG - DBG(USB_DBG, - "HFC-USB: small_match=%x %x\n", - small_match, alt_used); -#endif } cfg_used++; } alt_idx++; - } /* (alt_idx < intf->num_altsetting) */ + } /* (alt_idx < intf->num_altsetting) */ /* found a valid USB Ta Endpint config */ if (small_match != 0xffff) { iface = iface_used; - if (! - (context = - kzalloc(sizeof(hfcusb_data), GFP_KERNEL))) + if (!(context = kzalloc(sizeof(hfcusb_data), GFP_KERNEL))) return (-ENOMEM); /* got no mem */ ep = iface->endpoint; @@ -1613,20 +1487,15 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) driver_info; printk(KERN_INFO "HFC-S USB: detected \"%s\"\n", driver_info->vend_name); -#ifdef CONFIG_HISAX_DEBUG - DBG(USB_DBG, - "HFC-S USB: Endpoint-Config: %s (if=%d alt=%d)\n", + + DBG(HFCUSB_DBG_INIT, + "HFC-S USB: Endpoint-Config: %s (if=%d alt=%d), E-Channel(%d)", conf_str[small_match], context->if_used, - context->alt_used); - printk(KERN_INFO - "HFC-S USB: E-channel (\"ECHO:\") logging "); - if (validconf[small_match][18]) - printk(" possible\n"); - else - printk("NOT possible\n"); -#endif + context->alt_used, + validconf[small_match][18]); + /* init the chip and register the driver */ - if (usb_init(context)) { + if (hfc_usb_init(context)) { usb_kill_urb(context->ctrl_urb); usb_free_urb(context->ctrl_urb); context->ctrl_urb = NULL; @@ -1643,17 +1512,19 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) return (-EIO); } -/****************************************************/ -/* function called when an active device is removed */ -/****************************************************/ +/* callback for unplugged USB device */ static void hfc_usb_disconnect(struct usb_interface *intf) { hfcusb_data *context = usb_get_intfdata(intf); int i; + + handle_led(context, LED_POWER_OFF); + schedule_timeout((10 * HZ) / 1000); + printk(KERN_INFO "HFC-S USB: device disconnect\n"); - context->disc_flag = true; + context->disc_flag = 1; usb_set_intfdata(intf, NULL); if (!context) return; @@ -1661,25 +1532,22 @@ hfc_usb_disconnect(struct usb_interface del_timer(&context->t3_timer); if (timer_pending(&context->t4_timer)) del_timer(&context->t4_timer); + /* tell all fifos to terminate */ for (i = 0; i < HFCUSB_NUM_FIFOS; i++) { if (context->fifos[i].usb_transfer_mode == USB_ISOC) { if (context->fifos[i].active > 0) { stop_isoc_chain(&context->fifos[i]); -#ifdef CONFIG_HISAX_DEBUG - DBG(USB_DBG, - "HFC-S USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i", - i); -#endif + DBG(HFCUSB_DBG_INIT, + "HFC-S USB: %s stopping ISOC chain Fifo(%i)", + __FUNCTION__, i); } } else { if (context->fifos[i].active > 0) { context->fifos[i].active = 0; -#ifdef CONFIG_HISAX_DEBUG - DBG(USB_DBG, - "HFC-S USB: hfc_usb_disconnect: unlinking URB for Fifo no %i", - i); -#endif + DBG(HFCUSB_DBG_INIT, + "HFC-S USB: %s unlinking URB for Fifo(%i)", + __FUNCTION__, i); } usb_kill_urb(context->fifos[i].urb); usb_free_urb(context->fifos[i].urb); @@ -1692,34 +1560,29 @@ hfc_usb_disconnect(struct usb_interface context->ctrl_urb = NULL; hisax_unregister(&context->d_if); kfree(context); /* free our structure again */ -} /* hfc_usb_disconnect */ +} -/************************************/ -/* our driver information structure */ -/************************************/ static struct usb_driver hfc_drv = { .name = "hfc_usb", .id_table = hfcusb_idtab, .probe = hfc_usb_probe, .disconnect = hfc_usb_disconnect, }; + static void __exit -hfc_usb_exit(void) +hfc_usb_mod_exit(void) { -#ifdef CONFIG_HISAX_DEBUG - DBG(USB_DBG, "HFC-S USB: calling \"hfc_usb_exit\" ..."); -#endif - usb_deregister(&hfc_drv); /* release our driver */ + usb_deregister(&hfc_drv); /* release our driver */ printk(KERN_INFO "HFC-S USB: module removed\n"); } static int __init -hfc_usb_init(void) +hfc_usb_mod_init(void) { + char revstr[30], datestr[30], dummy[30]; #ifndef CONFIG_HISAX_DEBUG - unsigned int debug = -1; + hfc_debug = debug; #endif - char revstr[30], datestr[30], dummy[30]; sscanf(hfcusb_revision, "%s %s $ %s %s %s $ ", dummy, revstr, dummy, datestr, dummy); @@ -1734,8 +1597,8 @@ hfc_usb_init(void) return (0); } -module_init(hfc_usb_init); -module_exit(hfc_usb_exit); +module_init(hfc_usb_mod_init); +module_exit(hfc_usb_mod_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/isdn/hisax/hfc_usb.h b/drivers/isdn/hisax/hfc_usb.h index 471f2354dfd..e79f56568d3 100644 --- a/drivers/isdn/hisax/hfc_usb.h +++ b/drivers/isdn/hisax/hfc_usb.h @@ -1,8 +1,8 @@ /* -* hfc_usb.h -* -* $Id: hfc_usb.h,v 4.2 2005/04/07 15:27:17 martinb1 Exp $ -*/ + * hfc_usb.h + * + * $Id: hfc_usb.h,v 1.1.2.5 2007/08/20 14:36:03 mbachem Exp $ + */ #ifndef __HFC_USB_H__ #define __HFC_USB_H__ @@ -10,25 +10,20 @@ #define DRIVER_AUTHOR "Peter Sprenger (sprenger@moving-byters.de)" #define DRIVER_DESC "HFC-S USB based HiSAX ISDN driver" -#define VERBOSE_USB_DEBUG +#define HFC_CTRL_TIMEOUT 20 /* 5ms timeout writing/reading regs */ +#define HFC_TIMER_T3 8000 /* timeout for l1 activation timer */ +#define HFC_TIMER_T4 500 /* time for state change interval */ -/***********/ -/* defines */ -/***********/ -#define HFC_CTRL_TIMEOUT 20 /* 5ms timeout writing/reading regs */ -#define HFC_TIMER_T3 8000 /* timeout for l1 activation timer */ -#define HFC_TIMER_T4 500 /* time for state change interval */ +#define HFCUSB_L1_STATECHANGE 0 /* L1 state changed */ +#define HFCUSB_L1_DRX 1 /* D-frame received */ +#define HFCUSB_L1_ERX 2 /* E-frame received */ +#define HFCUSB_L1_DTX 4 /* D-frames completed */ -#define HFCUSB_L1_STATECHANGE 0 /* L1 state changed */ -#define HFCUSB_L1_DRX 1 /* D-frame received */ -#define HFCUSB_L1_ERX 2 /* E-frame received */ -#define HFCUSB_L1_DTX 4 /* D-frames completed */ +#define MAX_BCH_SIZE 2048 /* allowed B-channel packet size */ -#define MAX_BCH_SIZE 2048 /* allowed B-channel packet size */ - -#define HFCUSB_RX_THRESHOLD 64 /* threshold for fifo report bit rx */ -#define HFCUSB_TX_THRESHOLD 64 /* threshold for fifo report bit tx */ +#define HFCUSB_RX_THRESHOLD 64 /* threshold for fifo report bit rx */ +#define HFCUSB_TX_THRESHOLD 64 /* threshold for fifo report bit tx */ #define HFCUSB_CHIP_ID 0x16 /* Chip ID register index */ #define HFCUSB_CIRM 0x00 /* cirm register index */ @@ -52,9 +47,8 @@ #define HFCUSB_CHIPID 0x40 /* ID value of HFC-S USB */ -/******************/ + /* fifo registers */ -/******************/ #define HFCUSB_NUM_FIFOS 8 /* maximum number of fifos */ #define HFCUSB_B1_TX 0 /* index for B1 transmit bulk/int */ #define HFCUSB_B1_RX 1 /* index for B1 receive bulk/int */ @@ -66,9 +60,9 @@ #define HFCUSB_PCM_RX 7 /* -* used to switch snd_transfer_mode for different TA modes e.g. the Billion USB TA just -* supports ISO out, while the Cologne Chip EVAL TA just supports BULK out -*/ + * used to switch snd_transfer_mode for different TA modes e.g. the Billion USB TA just + * supports ISO out, while the Cologne Chip EVAL TA just supports BULK out + */ #define USB_INT 0 #define USB_BULK 1 #define USB_ISOC 2 @@ -77,49 +71,36 @@ #define ISOC_PACKETS_B 8 #define ISO_BUFFER_SIZE 128 -// ISO send definitions +/* Fifo flow Control for TX ISO */ #define SINK_MAX 68 #define SINK_MIN 48 #define SINK_DMIN 12 #define SINK_DMAX 18 #define BITLINE_INF (-64*8) - -/**********/ -/* macros */ -/**********/ +/* HFC-S USB register access by Control-URSs */ #define write_usb(a,b,c)usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),NULL,0,HFC_CTRL_TIMEOUT) #define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT) - - -/*******************/ -/* Debugging Flags */ -/*******************/ -#define USB_DBG 1 -#define ISDN_DBG 2 - - -/* *********************/ -/* USB related defines */ -/***********************/ #define HFC_CTRL_BUFSIZE 32 - - -/*************************************************/ /* entry and size of output/input control buffer */ -/*************************************************/ typedef struct { __u8 hfc_reg; /* register number */ __u8 reg_val; /* value to be written (or read) */ int action; /* data for action handler */ } ctrl_buft; +/* Debugging Flags */ +#define HFCUSB_DBG_INIT 0x0001 +#define HFCUSB_DBG_STATES 0x0002 +#define HFCUSB_DBG_DCHANNEL 0x0080 +#define HFCUSB_DBG_FIFO_ERR 0x4000 +#define HFCUSB_DBG_VERBOSE_USB 0x8000 -/********************/ -/* URB error codes: */ -/********************/ -/* Used to represent a list of values and their respective symbolic names */ +/* + * URB error codes: + * Used to represent a list of values and their respective symbolic names + */ struct hfcusb_symbolic_list { const int num; const char *name; @@ -134,20 +115,20 @@ static struct hfcusb_symbolic_list urb_errlist[] = { {-ENXIO, "URB already queued"}, {-EFBIG, "Too much ISO frames requested"}, {-ENOSR, "Buffer error (overrun)"}, - {-EPIPE, "Specified endpoint is stalled"}, + {-EPIPE, "Specified endpoint is stalled (device not responding)"}, {-EOVERFLOW, "Babble (bad cable?)"}, {-EPROTO, "Bit-stuff error (bad cable?)"}, - {-EILSEQ, "CRC or missing token"}, - {-ETIME, "Device did not respond"}, + {-EILSEQ, "CRC/Timeout"}, + {-ETIMEDOUT, "NAK (device does not respond)"}, {-ESHUTDOWN, "Device unplugged"}, {-1, NULL} }; -/*****************************************************/ -/* device dependant information to support different */ -/* ISDN Ta's using the HFC-S USB chip */ -/*****************************************************/ +/* + * device dependant information to support different + * ISDN Ta's using the HFC-S USB chip + */ /* USB descriptor need to contain one of the following EndPoint combination: */ #define CNF_4INT3ISO 1 // 4 INT IN, 3 ISO OUT @@ -155,16 +136,19 @@ static struct hfcusb_symbolic_list urb_errlist[] = { #define CNF_4ISO3ISO 3 // 4 ISO IN, 3 ISO OUT #define CNF_3ISO3ISO 4 // 3 ISO IN, 3 ISO OUT -#define EP_NUL 1 // Endpoint at this position not allowed -#define EP_NOP 2 // all type of endpoints allowed at this position -#define EP_ISO 3 // Isochron endpoint mandatory at this position -#define EP_BLK 4 // Bulk endpoint mandatory at this position -#define EP_INT 5 // Interrupt endpoint mandatory at this position +#define EP_NUL 1 // Endpoint at this position not allowed +#define EP_NOP 2 // all type of endpoints allowed at this position +#define EP_ISO 3 // Isochron endpoint mandatory at this position +#define EP_BLK 4 // Bulk endpoint mandatory at this position +#define EP_INT 5 // Interrupt endpoint mandatory at this position -/* this array represents all endpoints possible in the HCF-USB the last -* 3 entries are the configuration number, the minimum interval for -* Interrupt endpoints & boolean if E-channel logging possible -*/ +/* + * List of all supported endpoint configuration sets, used to find the + * best matching endpoint configuration within a devices' USB descriptor. + * We need at least 3 RX endpoints, and 3 TX endpoints, either + * INT-in and ISO-out, or ISO-in and ISO-out) + * with 4 RX endpoints even E-Channel logging is possible + */ static int validconf[][19] = { // INT in, ISO out config {EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NOP, EP_INT, @@ -193,7 +177,6 @@ static char *conf_str[] = { }; #endif - typedef struct { int vendor; // vendor id int prod_id; // product id @@ -202,9 +185,9 @@ typedef struct { signed short led_bits[8]; // array of 8 possible LED bitmask settings } vendor_data; -#define LED_OFF 0 // no LED support -#define LED_SCHEME1 1 // LED standard scheme -#define LED_SCHEME2 2 // not used yet... +#define LED_OFF 0 // no LED support +#define LED_SCHEME1 1 // LED standard scheme +#define LED_SCHEME2 2 // not used yet... #define LED_POWER_ON 1 #define LED_POWER_OFF 2 @@ -217,11 +200,8 @@ typedef struct { #define LED_B2_OFF 9 #define LED_B2_DATA 10 -#define LED_NORMAL 0 // LEDs are normal -#define LED_INVERTED 1 // LEDs are inverted - -/* time in ms to perform a Flashing LED when B-Channel has traffic */ -#define LED_TIME 250 +#define LED_NORMAL 0 // LEDs are normal +#define LED_INVERTED 1 // LEDs are inverted -#endif // __HFC_USB_H__ +#endif // __HFC_USB_H__ diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index ef3325b6923..9293c82ef2a 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1726,7 +1726,7 @@ ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb) } /* the decompressor still expects the A/C bytes in the hdr */ len = ppp->rcomp->decompress(ppp->rc_state, skb->data - 2, - skb->len + 2, ns->data, ppp->mru + PPP_HDRLEN); + skb->len + 2, ns->data, obuff_size); if (len < 0) { /* Pass the compressed frame to pppd as an error indication. */ diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index e7a2eadcc3b..75759243639 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -696,8 +696,8 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) int i; const u8 *addr = hw->dev[port]->dev_addr; - sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); - sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); + sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); + sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index eccac1c3b71..d32c60dbdd8 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -24,6 +24,7 @@ #include <asm/s390_ext.h> #include <asm/todclk.h> #include <asm/vtoc.h> +#include <asm/diag.h> #include "dasd_int.h" #include "dasd_diag.h" diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 4f2f81b16cf..2edd5fb6d3d 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -21,6 +21,7 @@ #include <asm/ccwdev.h> #include <asm/cio.h> #include <asm/ebcdic.h> +#include <asm/diag.h> #include "raw3270.h" diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index 04b19bdc09d..d70a6e65bf1 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c @@ -14,6 +14,7 @@ #include <asm/cio.h> #include <asm/ccwdev.h> #include <asm/debug.h> +#include <asm/diag.h> #include "vmur.h" @@ -68,8 +69,26 @@ static struct ccw_driver ur_driver = { .set_offline = ur_set_offline, }; +static DEFINE_MUTEX(vmur_mutex); + /* * Allocation, freeing, getting and putting of urdev structures + * + * Each ur device (urd) contains a reference to its corresponding ccw device + * (cdev) using the urd->cdev pointer. Each ccw device has a reference to the + * ur device using the cdev->dev.driver_data pointer. + * + * urd references: + * - ur_probe gets a urd reference, ur_remove drops the reference + * (cdev->dev.driver_data) + * - ur_open gets a urd reference, ur_relase drops the reference + * (urf->urd) + * + * cdev references: + * - urdev_alloc get a cdev reference (urd->cdev) + * - urdev_free drops the cdev reference (urd->cdev) + * + * Setting and clearing of cdev->dev.driver_data is protected by the ccwdev lock */ static struct urdev *urdev_alloc(struct ccw_device *cdev) { @@ -78,42 +97,61 @@ static struct urdev *urdev_alloc(struct ccw_device *cdev) urd = kzalloc(sizeof(struct urdev), GFP_KERNEL); if (!urd) return NULL; - urd->cdev = cdev; urd->reclen = cdev->id.driver_info; ccw_device_get_id(cdev, &urd->dev_id); mutex_init(&urd->io_mutex); mutex_init(&urd->open_mutex); + atomic_set(&urd->ref_count, 1); + urd->cdev = cdev; + get_device(&cdev->dev); return urd; } static void urdev_free(struct urdev *urd) { + TRACE("urdev_free: %p\n", urd); + if (urd->cdev) + put_device(&urd->cdev->dev); kfree(urd); } -/* - * This is how the character device driver gets a reference to a - * ur device. When this call returns successfully, a reference has - * been taken (by get_device) on the underlying kobject. The recipient - * of this urdev pointer must eventually drop it with urdev_put(urd) - * which does the corresponding put_device(). - */ +static void urdev_get(struct urdev *urd) +{ + atomic_inc(&urd->ref_count); +} + +static struct urdev *urdev_get_from_cdev(struct ccw_device *cdev) +{ + struct urdev *urd; + unsigned long flags; + + spin_lock_irqsave(get_ccwdev_lock(cdev), flags); + urd = cdev->dev.driver_data; + if (urd) + urdev_get(urd); + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + return urd; +} + static struct urdev *urdev_get_from_devno(u16 devno) { char bus_id[16]; struct ccw_device *cdev; + struct urdev *urd; sprintf(bus_id, "0.0.%04x", devno); cdev = get_ccwdev_by_busid(&ur_driver, bus_id); if (!cdev) return NULL; - - return cdev->dev.driver_data; + urd = urdev_get_from_cdev(cdev); + put_device(&cdev->dev); + return urd; } static void urdev_put(struct urdev *urd) { - put_device(&urd->cdev->dev); + if (atomic_dec_and_test(&urd->ref_count)) + urdev_free(urd); } /* @@ -245,6 +283,7 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm, return; } urd = cdev->dev.driver_data; + BUG_ON(!urd); /* On special conditions irb is an error pointer */ if (IS_ERR(irb)) urd->io_request_rc = PTR_ERR(irb); @@ -262,9 +301,15 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm, static ssize_t ur_attr_reclen_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct urdev *urd = dev->driver_data; + struct urdev *urd; + int rc; - return sprintf(buf, "%zu\n", urd->reclen); + urd = urdev_get_from_cdev(to_ccwdev(dev)); + if (!urd) + return -ENODEV; + rc = sprintf(buf, "%zu\n", urd->reclen); + urdev_put(urd); + return rc; } static DEVICE_ATTR(reclen, 0444, ur_attr_reclen_show, NULL); @@ -379,31 +424,6 @@ static ssize_t ur_write(struct file *file, const char __user *udata, return do_write(urf->urd, udata, count, urf->dev_reclen, ppos); } -static int do_diag_14(unsigned long rx, unsigned long ry1, - unsigned long subcode) -{ - register unsigned long _ry1 asm("2") = ry1; - register unsigned long _ry2 asm("3") = subcode; - int rc = 0; - - asm volatile( -#ifdef CONFIG_64BIT - " sam31\n" - " diag %2,2,0x14\n" - " sam64\n" -#else - " diag %2,2,0x14\n" -#endif - " ipm %0\n" - " srl %0,28\n" - : "=d" (rc), "+d" (_ry2) - : "d" (rx), "d" (_ry1) - : "cc"); - - TRACE("diag 14: subcode=0x%lx, cc=%i\n", subcode, rc); - return rc; -} - /* * diagnose code 0x14 subcode 0x0028 - position spool file to designated * record @@ -415,7 +435,7 @@ static int diag_position_to_record(int devno, int record) { int cc; - cc = do_diag_14(record, devno, 0x28); + cc = diag14(record, devno, 0x28); switch (cc) { case 0: return 0; @@ -440,7 +460,7 @@ static int diag_read_file(int devno, char *buf) { int cc; - cc = do_diag_14((unsigned long) buf, devno, 0x00); + cc = diag14((unsigned long) buf, devno, 0x00); switch (cc) { case 0: return 0; @@ -533,7 +553,7 @@ static int diag_read_next_file_info(struct file_control_block *buf, int spid) { int cc; - cc = do_diag_14((unsigned long) buf, spid, 0xfff); + cc = diag14((unsigned long) buf, spid, 0xfff); switch (cc) { case 0: return 0; @@ -750,64 +770,63 @@ static struct file_operations ur_fops = { /* * ccw_device infrastructure: - * ur_probe gets its own ref to the device (i.e. get_device), - * creates the struct urdev, the device attributes, sets up - * the interrupt handler and validates the virtual unit record device. - * ur_remove removes the device attributes, frees the struct urdev - * and drops (put_device) the ref to the device we got in ur_probe. + * ur_probe creates the struct urdev (with refcount = 1), the device + * attributes, sets up the interrupt handler and validates the virtual + * unit record device. + * ur_remove removes the device attributes and drops the reference to + * struct urdev. + * + * ur_probe, ur_remove, ur_set_online and ur_set_offline are serialized + * by the vmur_mutex lock. + * + * urd->char_device is used as indication that the online function has + * been completed successfully. */ static int ur_probe(struct ccw_device *cdev) { struct urdev *urd; int rc; - TRACE("ur_probe: cdev=%p state=%d\n", cdev, *(int *) cdev->private); - - if (!get_device(&cdev->dev)) - return -ENODEV; + TRACE("ur_probe: cdev=%p\n", cdev); + mutex_lock(&vmur_mutex); urd = urdev_alloc(cdev); if (!urd) { rc = -ENOMEM; - goto fail; + goto fail_unlock; } + rc = ur_create_attributes(&cdev->dev); if (rc) { rc = -ENOMEM; - goto fail; + goto fail_urdev_put; } - cdev->dev.driver_data = urd; cdev->handler = ur_int_handler; /* validate virtual unit record device */ urd->class = get_urd_class(urd); if (urd->class < 0) { rc = urd->class; - goto fail; + goto fail_remove_attr; } if ((urd->class != DEV_CLASS_UR_I) && (urd->class != DEV_CLASS_UR_O)) { rc = -ENOTSUPP; - goto fail; + goto fail_remove_attr; } + spin_lock_irq(get_ccwdev_lock(cdev)); + cdev->dev.driver_data = urd; + spin_unlock_irq(get_ccwdev_lock(cdev)); + mutex_unlock(&vmur_mutex); return 0; -fail: - urdev_free(urd); - put_device(&cdev->dev); - return rc; -} - -static void ur_remove(struct ccw_device *cdev) -{ - struct urdev *urd = cdev->dev.driver_data; - - TRACE("ur_remove\n"); - if (cdev->online) - ur_set_offline(cdev); +fail_remove_attr: ur_remove_attributes(&cdev->dev); - urdev_free(urd); - put_device(&cdev->dev); +fail_urdev_put: + urdev_put(urd); +fail_unlock: + mutex_unlock(&vmur_mutex); + return rc; } static int ur_set_online(struct ccw_device *cdev) @@ -816,20 +835,29 @@ static int ur_set_online(struct ccw_device *cdev) int minor, major, rc; char node_id[16]; - TRACE("ur_set_online: cdev=%p state=%d\n", cdev, - *(int *) cdev->private); + TRACE("ur_set_online: cdev=%p\n", cdev); - if (!try_module_get(ur_driver.owner)) - return -EINVAL; + mutex_lock(&vmur_mutex); + urd = urdev_get_from_cdev(cdev); + if (!urd) { + /* ur_remove already deleted our urd */ + rc = -ENODEV; + goto fail_unlock; + } + + if (urd->char_device) { + /* Another ur_set_online was faster */ + rc = -EBUSY; + goto fail_urdev_put; + } - urd = (struct urdev *) cdev->dev.driver_data; minor = urd->dev_id.devno; major = MAJOR(ur_first_dev_maj_min); urd->char_device = cdev_alloc(); if (!urd->char_device) { rc = -ENOMEM; - goto fail_module_put; + goto fail_urdev_put; } cdev_init(urd->char_device, &ur_fops); @@ -858,29 +886,79 @@ static int ur_set_online(struct ccw_device *cdev) TRACE("ur_set_online: device_create rc=%d\n", rc); goto fail_free_cdev; } - + urdev_put(urd); + mutex_unlock(&vmur_mutex); return 0; fail_free_cdev: cdev_del(urd->char_device); -fail_module_put: - module_put(ur_driver.owner); - + urd->char_device = NULL; +fail_urdev_put: + urdev_put(urd); +fail_unlock: + mutex_unlock(&vmur_mutex); return rc; } -static int ur_set_offline(struct ccw_device *cdev) +static int ur_set_offline_force(struct ccw_device *cdev, int force) { struct urdev *urd; + int rc; - TRACE("ur_set_offline: cdev=%p cdev->private=%p state=%d\n", - cdev, cdev->private, *(int *) cdev->private); - urd = (struct urdev *) cdev->dev.driver_data; + TRACE("ur_set_offline: cdev=%p\n", cdev); + urd = urdev_get_from_cdev(cdev); + if (!urd) + /* ur_remove already deleted our urd */ + return -ENODEV; + if (!urd->char_device) { + /* Another ur_set_offline was faster */ + rc = -EBUSY; + goto fail_urdev_put; + } + if (!force && (atomic_read(&urd->ref_count) > 2)) { + /* There is still a user of urd (e.g. ur_open) */ + TRACE("ur_set_offline: BUSY\n"); + rc = -EBUSY; + goto fail_urdev_put; + } device_destroy(vmur_class, urd->char_device->dev); cdev_del(urd->char_device); - module_put(ur_driver.owner); + urd->char_device = NULL; + rc = 0; - return 0; +fail_urdev_put: + urdev_put(urd); + return rc; +} + +static int ur_set_offline(struct ccw_device *cdev) +{ + int rc; + + mutex_lock(&vmur_mutex); + rc = ur_set_offline_force(cdev, 0); + mutex_unlock(&vmur_mutex); + return rc; +} + +static void ur_remove(struct ccw_device *cdev) +{ + unsigned long flags; + + TRACE("ur_remove\n"); + + mutex_lock(&vmur_mutex); + + if (cdev->online) + ur_set_offline_force(cdev, 1); + ur_remove_attributes(&cdev->dev); + + spin_lock_irqsave(get_ccwdev_lock(cdev), flags); + urdev_put(cdev->dev.driver_data); + cdev->dev.driver_data = NULL; + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + + mutex_unlock(&vmur_mutex); } /* diff --git a/drivers/s390/char/vmur.h b/drivers/s390/char/vmur.h index 2b3c564e047..fa959644735 100644 --- a/drivers/s390/char/vmur.h +++ b/drivers/s390/char/vmur.h @@ -70,6 +70,7 @@ struct urdev { size_t reclen; /* Record length for *write* CCWs */ int class; /* VM device class */ int io_request_rc; /* return code from I/O request */ + atomic_t ref_count; /* reference counter */ }; /* diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 02fd00b55e1..34a796913b0 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -594,6 +594,9 @@ alloc_cmb (struct ccw_device *cdev) free_pages((unsigned long)mem, get_order(size)); } else if (!mem) { /* no luck */ + printk(KERN_WARNING "cio: failed to allocate area " + "for measuring %d subchannels\n", + cmb_area.num_channels); ret = -ENOMEM; goto out; } else { @@ -1279,13 +1282,6 @@ init_cmf(void) case CMF_BASIC: format_string = "basic"; cmbops = &cmbops_basic; - if (cmb_area.num_channels > 4096 || cmb_area.num_channels < 1) { - printk(KERN_ERR "cio: Basic channel measurement " - "facility can only use 1 to 4096 devices\n" - KERN_ERR "when the cmf driver is built" - " as a loadable module\n"); - return 1; - } break; case CMF_EXTENDED: format_string = "extended"; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 297659fa0e2..e44d92eac8e 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -117,7 +117,10 @@ static int ccw_uevent(struct device *dev, char **envp, int num_envp, snprint_alias(modalias_buf, sizeof(modalias_buf), id, ""); ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, "MODALIAS=%s", modalias_buf); - return ret; + if (ret) + return ret; + envp[i] = NULL; + return 0; } struct bus_type ccw_bus_type; diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c index 60b9347f7c9..f232832f2b2 100644 --- a/drivers/s390/cio/device_id.c +++ b/drivers/s390/cio/device_id.c @@ -17,6 +17,7 @@ #include <asm/delay.h> #include <asm/cio.h> #include <asm/lowcore.h> +#include <asm/diag.h> #include "cio.h" #include "cio_debug.h" @@ -25,51 +26,6 @@ #include "ioasm.h" /* - * diag210 is used under VM to get information about a virtual device - */ -int -diag210(struct diag210 * addr) -{ - /* - * diag 210 needs its data below the 2GB border, so we - * use a static data area to be sure - */ - static struct diag210 diag210_tmp; - static DEFINE_SPINLOCK(diag210_lock); - unsigned long flags; - int ccode; - - spin_lock_irqsave(&diag210_lock, flags); - diag210_tmp = *addr; - -#ifdef CONFIG_64BIT - asm volatile( - " lhi %0,-1\n" - " sam31\n" - " diag %1,0,0x210\n" - "0: ipm %0\n" - " srl %0,28\n" - "1: sam64\n" - EX_TABLE(0b,1b) - : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); -#else - asm volatile( - " lhi %0,-1\n" - " diag %1,0,0x210\n" - "0: ipm %0\n" - " srl %0,28\n" - "1:\n" - EX_TABLE(0b,1b) - : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); -#endif - - *addr = diag210_tmp; - spin_unlock_irqrestore(&diag210_lock, flags); - - return ccode; -} - -/* * Input : * devno - device number * ps - pointer to sense ID data area @@ -349,5 +305,3 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event) break; } } - -EXPORT_SYMBOL(diag210); diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 03347aed2b3..d8d479876ec 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -195,6 +195,8 @@ qdio_do_eqbs(struct qdio_q *q, unsigned char *state, again: ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt); rc = qdio_check_ccq(q, ccq); + if ((ccq == 96) && (tmp_cnt != *cnt)) + rc = 0; if (rc == 1) { QDIO_DBF_TEXT5(1,trace,"eqAGAIN"); goto again; @@ -740,7 +742,8 @@ qdio_get_outbound_buffer_frontier(struct qdio_q *q) first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used), (QDIO_MAX_BUFFERS_PER_Q-1)); - if ((!q->is_iqdio_q)&&(!q->hydra_gives_outbound_pcis)) + if (((!q->is_iqdio_q) && (!q->hydra_gives_outbound_pcis)) || + (q->queue_type == QDIO_IQDIO_QFMT_ASYNCH)) SYNC_MEMORY; check_next: diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c4e15ed1405..35cdba10411 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -275,58 +275,6 @@ static void ehci_work(struct ehci_hcd *ehci); /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_CPU_FREQ - -#include <linux/cpufreq.h> - -static void ehci_cpufreq_pause (struct ehci_hcd *ehci) -{ - unsigned long flags; - - spin_lock_irqsave(&ehci->lock, flags); - if (!ehci->cpufreq_changing++) - qh_inactivate_split_intr_qhs(ehci); - spin_unlock_irqrestore(&ehci->lock, flags); -} - -static void ehci_cpufreq_unpause (struct ehci_hcd *ehci) -{ - unsigned long flags; - - spin_lock_irqsave(&ehci->lock, flags); - if (!--ehci->cpufreq_changing) - qh_reactivate_split_intr_qhs(ehci); - spin_unlock_irqrestore(&ehci->lock, flags); -} - -/* - * ehci_cpufreq_notifier is needed to avoid MMF errors that occur when - * EHCI controllers that don't cache many uframes get delayed trying to - * read main memory during CPU frequency transitions. This can cause - * split interrupt transactions to not be completed in the required uframe. - * This has been observed on the Broadcom/ServerWorks HT1000 controller. - */ -static int ehci_cpufreq_notifier(struct notifier_block *nb, unsigned long val, - void *data) -{ - struct ehci_hcd *ehci = container_of(nb, struct ehci_hcd, - cpufreq_transition); - - switch (val) { - case CPUFREQ_PRECHANGE: - ehci_cpufreq_pause(ehci); - break; - case CPUFREQ_POSTCHANGE: - ehci_cpufreq_unpause(ehci); - break; - } - return 0; -} - -#endif - -/*-------------------------------------------------------------------------*/ - static void ehci_watchdog (unsigned long param) { struct ehci_hcd *ehci = (struct ehci_hcd *) param; @@ -460,10 +408,6 @@ static void ehci_stop (struct usb_hcd *hcd) ehci_writel(ehci, 0, &ehci->regs->intr_enable); spin_unlock_irq(&ehci->lock); -#ifdef CONFIG_CPU_FREQ - cpufreq_unregister_notifier(&ehci->cpufreq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -#endif /* let companion controllers work when we aren't */ ehci_writel(ehci, 0, &ehci->regs->configured_flag); @@ -569,17 +513,6 @@ static int ehci_init(struct usb_hcd *hcd) } ehci->command = temp; -#ifdef CONFIG_CPU_FREQ - INIT_LIST_HEAD(&ehci->split_intr_qhs); - /* - * If the EHCI controller caches enough uframes, this probably - * isn't needed unless there are so many low/full speed devices - * that the controller's can't cache it all. - */ - ehci->cpufreq_transition.notifier_call = ehci_cpufreq_notifier; - cpufreq_register_notifier(&ehci->cpufreq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -#endif return 0; } diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index 8816d09903d..0431397836f 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c @@ -94,9 +94,6 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) qh->qh_dma = dma; // INIT_LIST_HEAD (&qh->qh_list); INIT_LIST_HEAD (&qh->qtd_list); -#ifdef CONFIG_CPU_FREQ - INIT_LIST_HEAD (&qh->split_intr_qhs); -#endif /* dummy td enables safe urb queuing */ qh->dummy = ehci_qtd_alloc (ehci, flags); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 2284028f8aa..140bfa423e0 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -312,10 +312,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) struct urb *urb; u32 token = 0; - /* ignore QHs that are currently inactive */ - if (qh->hw_info1 & __constant_cpu_to_le32(QH_INACTIVATE)) - break; - qtd = list_entry (entry, struct ehci_qtd, qtd_list); urb = qtd->urb; diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index d4a8ace4967..e682f2342ef 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -479,109 +479,6 @@ static int disable_periodic (struct ehci_hcd *ehci) } /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_CPU_FREQ - -static int safe_to_modify_i (struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - int now; /* current (frame * 8) + uframe */ - int prev_start, next_start; /* uframes from/to split start */ - int start_uframe = ffs(le32_to_cpup (&qh->hw_info2) & QH_SMASK); - int end_uframe = fls((le32_to_cpup (&qh->hw_info2) & QH_CMASK) >> 8); - int split_duration = end_uframe - start_uframe; - - now = readl(&ehci->regs->frame_index) % (ehci->periodic_size << 3); - - next_start = ((1024 << 3) + (qh->start << 3) + start_uframe - now) - % (qh->period << 3); - prev_start = (qh->period << 3) - next_start; - - /* - * Make sure there will be at least one uframe when qh is safe. - */ - if ((qh->period << 3) <= (ehci->i_thresh + 2 + split_duration)) - /* never safe */ - return -EINVAL; - - /* - * Wait 1 uframe after transaction should have started, to make - * sure controller has time to write back overlay, so we can - * check QTD_STS_STS to see if transaction is in progress. - */ - if ((next_start > ehci->i_thresh) && (prev_start > 1)) - /* safe to set "i" bit if split isn't in progress */ - return (qh->hw_token & STATUS_BIT(ehci)) ? 0 : 1; - else - return 0; -} - -/* Set inactivate bit for all the split interrupt QHs. */ -static void qh_inactivate_split_intr_qhs (struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - int not_done, safe; - u32 inactivate = INACTIVATE_BIT(ehci); - u32 active = ACTIVE_BIT(ehci); - - do { - not_done = 0; - list_for_each_entry(qh, &ehci->split_intr_qhs, - split_intr_qhs) { - if (qh->hw_info1 & inactivate) - /* already off */ - continue; - /* - * To avoid setting "I" after the start split happens, - * don't set it if the QH might be cached in the - * controller. Some HCs (Broadcom/ServerWorks HT1000) - * will stop in the middle of a split transaction when - * the "I" bit is set. - */ - safe = safe_to_modify_i(ehci, qh); - if (safe == 0) { - not_done = 1; - } else if (safe > 0) { - qh->was_active = qh->hw_token & active; - qh->hw_info1 |= inactivate; - } - } - } while (not_done); - wmb(); -} - -static void qh_reactivate_split_intr_qhs (struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - u32 token; - int not_done, safe; - u32 inactivate = INACTIVATE_BIT(ehci); - u32 active = ACTIVE_BIT(ehci); - u32 halt = HALT_BIT(ehci); - - do { - not_done = 0; - list_for_each_entry(qh, &ehci->split_intr_qhs, split_intr_qhs) { - if (!(qh->hw_info1 & inactivate)) /* already on */ - continue; - /* - * Don't reactivate if cached, or controller might - * overwrite overlay after we modify it! - */ - safe = safe_to_modify_i(ehci, qh); - if (safe == 0) { - not_done = 1; - } else if (safe > 0) { - /* See EHCI 1.0 section 4.15.2.4. */ - token = qh->hw_token; - qh->hw_token = (token | halt) & ~active; - wmb(); - qh->hw_info1 &= ~inactivate; - wmb(); - qh->hw_token = (token & ~halt) | qh->was_active; - } - } - } while (not_done); -} -#endif /* periodic schedule slots have iso tds (normal or split) first, then a * sparse tree for active interrupt transfers. @@ -599,17 +496,6 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) period, hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs); -#ifdef CONFIG_CPU_FREQ - /* - * If low/full speed interrupt QHs are inactive (because of - * cpufreq changing processor speeds), start QH with I flag set-- - * it will automatically be cleared when cpufreq is done. - */ - if (ehci->cpufreq_changing) - if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) - qh->hw_info1 |= INACTIVATE_BIT(ehci); -#endif - /* high bandwidth, or otherwise every microframe */ if (period == 0) period = 1; @@ -658,12 +544,6 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) ? ((qh->usecs + qh->c_usecs) / qh->period) : (qh->usecs * 8); -#ifdef CONFIG_CPU_FREQ - /* add qh to list of low/full speed interrupt QHs, if applicable */ - if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) { - list_add(&qh->split_intr_qhs, &ehci->split_intr_qhs); - } -#endif /* maybe enable periodic schedule processing */ if (!ehci->periodic_sched++) return enable_periodic (ehci); @@ -683,13 +563,6 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) // THEN // qh->hw_info1 |= __constant_cpu_to_hc32(1 << 7 /* "ignore" */); -#ifdef CONFIG_CPU_FREQ - /* remove qh from list of low/full speed interrupt QHs */ - if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) { - list_del_init(&qh->split_intr_qhs); - } -#endif - /* high bandwidth, or otherwise part of every microframe */ if ((period = qh->period) == 0) period = 1; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 2c68a04230c..951d69fec51 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -71,12 +71,6 @@ struct ehci_hcd { /* one per controller */ __u32 hcs_params; /* cached register copy */ spinlock_t lock; -#ifdef CONFIG_CPU_FREQ - struct notifier_block cpufreq_transition; - int cpufreq_changing; - struct list_head split_intr_qhs; -#endif - /* async schedule support */ struct ehci_qh *async; struct ehci_qh *reclaim; @@ -439,10 +433,6 @@ struct ehci_qh { __hc32 hw_next; /* see EHCI 3.6.1 */ __hc32 hw_info1; /* see EHCI 3.6.2 */ #define QH_HEAD 0x00008000 -#define QH_INACTIVATE 0x00000080 - -#define INACTIVATE_BIT(ehci) cpu_to_hc32(ehci, QH_INACTIVATE) - __hc32 hw_info2; /* see EHCI 3.6.2 */ #define QH_SMASK 0x000000ff #define QH_CMASK 0x0000ff00 @@ -492,10 +482,6 @@ struct ehci_qh { unsigned short start; /* where polling starts */ #define NO_FRAME ((unsigned short)~0) /* pick new start */ struct usb_device *dev; /* access to TT */ -#ifdef CONFIG_CPU_FREQ - struct list_head split_intr_qhs; /* list of split qhs */ - __le32 was_active; /* active bit before "i" set */ -#endif } __attribute__ ((aligned (32))); /*-------------------------------------------------------------------------*/ diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h index ea486952f77..2d184655bc5 100644 --- a/include/asm-s390/atomic.h +++ b/include/asm-s390/atomic.h @@ -67,8 +67,17 @@ typedef struct { #endif /* __GNUC__ */ -#define atomic_read(v) ((v)->counter) -#define atomic_set(v,i) (((v)->counter) = (i)) +static inline int atomic_read(const atomic_t *v) +{ + barrier(); + return v->counter; +} + +static inline void atomic_set(atomic_t *v, int i) +{ + v->counter = i; + barrier(); +} static __inline__ int atomic_add_return(int i, atomic_t * v) { @@ -182,8 +191,17 @@ typedef struct { #endif /* __GNUC__ */ -#define atomic64_read(v) ((v)->counter) -#define atomic64_set(v,i) (((v)->counter) = (i)) +static inline long long atomic64_read(const atomic64_t *v) +{ + barrier(); + return v->counter; +} + +static inline void atomic64_set(atomic64_t *v, long long i) +{ + v->counter = i; + barrier(); +} static __inline__ long long atomic64_add_return(long long i, atomic64_t * v) { diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h index f738d282758..1982fb34416 100644 --- a/include/asm-s390/cio.h +++ b/include/asm-s390/cio.h @@ -258,19 +258,6 @@ struct ciw { /* Sick revalidation of device. */ #define CIO_REVALIDATE 0x0008 -struct diag210 { - __u16 vrdcdvno : 16; /* device number (input) */ - __u16 vrdclen : 16; /* data block length (input) */ - __u32 vrdcvcla : 8; /* virtual device class (output) */ - __u32 vrdcvtyp : 8; /* virtual device type (output) */ - __u32 vrdcvsta : 8; /* virtual device status (output) */ - __u32 vrdcvfla : 8; /* virtual device flags (output) */ - __u32 vrdcrccl : 8; /* real device class (output) */ - __u32 vrdccrty : 8; /* real device type (output) */ - __u32 vrdccrmd : 8; /* real device model (output) */ - __u32 vrdccrft : 8; /* real device feature (output) */ -} __attribute__ ((packed,aligned(4))); - struct ccw_dev_id { u8 ssid; u16 devno; @@ -285,8 +272,6 @@ static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1, return 0; } -extern int diag210(struct diag210 *addr); - extern void wait_cons_dev(void); extern void css_schedule_reprobe(void); diff --git a/include/asm-s390/diag.h b/include/asm-s390/diag.h new file mode 100644 index 00000000000..72b2e2f2d32 --- /dev/null +++ b/include/asm-s390/diag.h @@ -0,0 +1,39 @@ +/* + * s390 diagnose functions + * + * Copyright IBM Corp. 2007 + * Author(s): Michael Holzheu <holzheu@de.ibm.com> + */ + +#ifndef _ASM_S390_DIAG_H +#define _ASM_S390_DIAG_H + +/* + * Diagnose 10: Release pages + */ +extern void diag10(unsigned long addr); + +/* + * Diagnose 14: Input spool file manipulation + */ +extern int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode); + +/* + * Diagnose 210: Get information about a virtual device + */ +struct diag210 { + u16 vrdcdvno; /* device number (input) */ + u16 vrdclen; /* data block length (input) */ + u8 vrdcvcla; /* virtual device class (output) */ + u8 vrdcvtyp; /* virtual device type (output) */ + u8 vrdcvsta; /* virtual device status (output) */ + u8 vrdcvfla; /* virtual device flags (output) */ + u8 vrdcrccl; /* real device class (output) */ + u8 vrdccrty; /* real device type (output) */ + u8 vrdccrmd; /* real device model (output) */ + u8 vrdccrft; /* real device feature (output) */ +} __attribute__((packed, aligned(4))); + +extern int diag210(struct diag210 *addr); + +#endif /* _ASM_S390_DIAG_H */ diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h index 56c8a6c80e2..e45d3c9a4b7 100644 --- a/include/asm-s390/pgalloc.h +++ b/include/asm-s390/pgalloc.h @@ -19,8 +19,6 @@ #define check_pgt_cache() do {} while (0) -extern void diag10(unsigned long addr); - /* * Page allocation orders. */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 07fc57429b5..8938d59013c 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2092,8 +2092,10 @@ #define PCI_DEVICE_ID_MPC8568 0x0021 #define PCI_DEVICE_ID_MPC8567E 0x0022 #define PCI_DEVICE_ID_MPC8567 0x0023 -#define PCI_DEVICE_ID_MPC8544E 0x0030 -#define PCI_DEVICE_ID_MPC8544 0x0031 +#define PCI_DEVICE_ID_MPC8533E 0x0030 +#define PCI_DEVICE_ID_MPC8533 0x0031 +#define PCI_DEVICE_ID_MPC8544E 0x0032 +#define PCI_DEVICE_ID_MPC8544 0x0033 #define PCI_DEVICE_ID_MPC8641 0x7010 #define PCI_DEVICE_ID_MPC8641D 0x7011 diff --git a/kernel/printk.c b/kernel/printk.c index 5c7c325b29c..8451dfc31d2 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1085,10 +1085,12 @@ EXPORT_SYMBOL(unregister_console); static int __init disable_boot_consoles(void) { - if (console_drivers->flags & CON_BOOT) { - printk(KERN_INFO "turn off boot console %s%d\n", - console_drivers->name, console_drivers->index); - return unregister_console(console_drivers); + if (console_drivers != NULL) { + if (console_drivers->flags & CON_BOOT) { + printk(KERN_INFO "turn off boot console %s%d\n", + console_drivers->name, console_drivers->index); + return unregister_console(console_drivers); + } } return 0; } diff --git a/net/802/psnap.c b/net/802/psnap.c index 04ee43e7538..31128cb92a2 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c @@ -55,6 +55,9 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, .type = __constant_htons(ETH_P_SNAP), }; + if (unlikely(!pskb_may_pull(skb, 5))) + goto drop; + rcu_read_lock(); proto = find_snap_client(skb_transport_header(skb)); if (proto) { @@ -62,14 +65,18 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, skb->transport_header += 5; skb_pull_rcsum(skb, 5); rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); - } else { - skb->sk = NULL; - kfree_skb(skb); - rc = 1; } - rcu_read_unlock(); + + if (unlikely(!proto)) + goto drop; + +out: return rc; + +drop: + kfree_skb(skb); + goto out; } /* diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 248d20f4c7c..d29b88fe723 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -298,7 +298,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) int rc; ccid2_pr_debug("allocating more space in history\n"); - rc = ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, GFP_KERNEL); + rc = ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, gfp_any()); BUG_ON(rc); /* XXX what do we do? */ next = hctx->ccid2hctx_seqh->ccid2s_next; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 50d86e94d9e..5dead399fe6 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -794,7 +794,7 @@ slow_path: /* * Copy a block of the IP datagram. */ - if (skb_copy_bits(skb, ptr, skb_transport_header(skb), len)) + if (skb_copy_bits(skb, ptr, skb_transport_header(frag), len)) BUG(); left -= len; diff --git a/net/irda/irmod.c b/net/irda/irmod.c index 1900937b332..8ba703da279 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c @@ -128,8 +128,8 @@ static int __init irda_init(void) out_err_3: #ifdef CONFIG_SYSCTL irda_sysctl_unregister(); -#endif out_err_2: +#endif #ifdef CONFIG_PROC_FS irda_proc_unregister(); #endif diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c index 694ea4d92fa..1e429c92973 100644 --- a/net/irda/irnetlink.c +++ b/net/irda/irnetlink.c @@ -106,7 +106,7 @@ static int irda_nl_get_mode(struct sk_buff *skb, struct genl_info *info) } if(nla_put_string(msg, IRDA_NL_ATTR_IFNAME, - dev->name)); + dev->name)) goto err_out; if(nla_put_u32(msg, IRDA_NL_ATTR_MODE, irlap->mode)) |