Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 May 2013 00:51:54 +0000 (17:51 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 May 2013 00:51:54 +0000 (17:51 -0700)
Pull VFS updates from Al Viro,

Misc cleanups all over the place, mainly wrt /proc interfaces (switch
create_proc_entry to proc_create(), get rid of the deprecated
create_proc_read_entry() in favor of using proc_create_data() and
seq_file etc).

7kloc removed.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (204 commits)
  don't bother with deferred freeing of fdtables
  proc: Move non-public stuff from linux/proc_fs.h to fs/proc/internal.h
  proc: Make the PROC_I() and PDE() macros internal to procfs
  proc: Supply a function to remove a proc entry by PDE
  take cgroup_open() and cpuset_open() to fs/proc/base.c
  ppc: Clean up scanlog
  ppc: Clean up rtas_flash driver somewhat
  hostap: proc: Use remove_proc_subtree()
  drm: proc: Use remove_proc_subtree()
  drm: proc: Use minor->index to label things, not PDE->name
  drm: Constify drm_proc_list[]
  zoran: Don't print proc_dir_entry data in debug
  reiserfs: Don't access the proc_dir_entry in r_open(), r_start() r_show()
  proc: Supply an accessor for getting the data from a PDE's parent
  airo: Use remove_proc_subtree()
  rtl8192u: Don't need to save device proc dir PDE
  rtl8187se: Use a dir under /proc/net/r8180/
  proc: Add proc_mkdir_data()
  proc: Move some bits from linux/proc_fs.h to linux/{of.h,signal.h,tty.h}
  proc: Move PDE_NET() to fs/proc/proc_net.c
  ...

103 files changed:
1  2 
arch/arm/mach-omap1/pm.c
arch/mips/mm/init.c
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/irq.c
arch/s390/kernel/syscalls.S
arch/score/mm/init.c
arch/x86/ia32/ia32_aout.c
arch/x86/mm/init_64.c
arch/x86/platform/efi/efi.c
drivers/acpi/battery.c
drivers/acpi/button.c
drivers/block/cciss.c
drivers/block/loop.c
drivers/firmware/efi/efi-pstore.c
drivers/firmware/efi/efivars.c
drivers/media/dvb-core/dvb_frontend.c
drivers/media/dvb-core/dvb_net.c
drivers/media/pci/cx25821/cx25821-audio-upstream.c
drivers/media/rc/ir-lirc-codec.c
drivers/net/wireless/ath/wil6210/debugfs.c
drivers/net/wireless/ray_cs.c
drivers/of/base.c
drivers/platform/x86/thinkpad_acpi.c
drivers/pnp/pnpbios/proc.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/qla2xxx/qla_os.c
drivers/staging/csr/drv.c
drivers/staging/dgrp/dgrp_common.h
drivers/staging/dgrp/dgrp_dpa_ops.c
drivers/staging/dgrp/dgrp_net_ops.c
drivers/staging/rts5139/rts51x_scsi.c
drivers/staging/rts5139/rts51x_scsi.h
drivers/staging/silicom/bpctl_mod.c
drivers/staging/vt6655/device_main.c
drivers/staging/vt6656/main_usb.c
drivers/tty/serial/serial_core.c
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/lpc32xx_udc.c
drivers/usb/host/sl811-hcd.c
drivers/usb/storage/scsiglue.c
fs/Makefile
fs/aio.c
fs/binfmt_aout.c
fs/binfmt_elf_fdpic.c
fs/btrfs/file.c
fs/compat.c
fs/coredump.c
fs/efivarfs/file.c
fs/efivarfs/inode.c
fs/efivarfs/super.c
fs/exec.c
fs/ext4/mballoc.c
fs/ext4/super.c
fs/inode.c
fs/jbd2/journal.c
fs/namespace.c
fs/notify/inotify/inotify_user.c
fs/pnode.c
fs/pnode.h
fs/proc/base.c
fs/proc/internal.h
fs/proc/kcore.c
fs/proc/root.c
fs/read_write.c
fs/read_write.h
fs/splice.c
include/linux/cgroup.h
include/linux/cpuset.h
include/linux/fs.h
include/linux/pid_namespace.h
include/linux/signal.h
include/linux/tty.h
include/net/bluetooth/bluetooth.h
ipc/msgutil.c
ipc/util.c
kernel/cgroup.c
kernel/cpuset.c
kernel/exit.c
kernel/pid.c
kernel/pid_namespace.c
kernel/user.c
kernel/user_namespace.c
mm/filemap.c
mm/vmalloc.c
net/bluetooth/af_bluetooth.c
net/bluetooth/bnep/sock.c
net/bluetooth/cmtp/sock.c
net/bluetooth/hci_sock.c
net/bluetooth/hidp/sock.c
net/bluetooth/l2cap_sock.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/sco.c
net/core/neighbour.c
net/core/pktgen.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv6/proc.c
net/netfilter/x_tables.c
net/netfilter/xt_hashlimit.c
net/socket.c
net/sunrpc/cache.c

diff --combined arch/arm/mach-omap1/pm.c
index db37f49da5ace388fd304b7b4492249f01ac7ccd,ff72d297a172550a83faaba10502ff49f495f3c6..dd712f10973888b0952b80bd15c4f903b48b748b
  
  #include <linux/suspend.h>
  #include <linux/sched.h>
- #include <linux/proc_fs.h>
+ #include <linux/debugfs.h>
+ #include <linux/seq_file.h>
  #include <linux/interrupt.h>
  #include <linux/sysfs.h>
  #include <linux/module.h>
  #include <linux/io.h>
  #include <linux/atomic.h>
 +#include <linux/cpu.h>
  
  #include <asm/fncpy.h>
  #include <asm/system_misc.h>
@@@ -423,23 -423,12 +424,12 @@@ void omap1_pm_suspend(void
                omap_rev());
  }
  
- #if defined(DEBUG) && defined(CONFIG_PROC_FS)
- static int g_read_completed;
+ #ifdef CONFIG_DEBUG_FS
  /*
   * Read system PM registers for debugging
   */
- static int omap_pm_read_proc(
-       char *page_buffer,
-       char **my_first_byte,
-       off_t virtual_start,
-       int length,
-       int *eof,
-       void *data)
+ static int omap_pm_debug_show(struct seq_file *m, void *v)
  {
-       int my_buffer_offset = 0;
-       char * const my_base = page_buffer;
        ARM_SAVE(ARM_CKCTL);
        ARM_SAVE(ARM_IDLECT1);
        ARM_SAVE(ARM_IDLECT2);
                MPUI1610_SAVE(EMIFS_CONFIG);
        }
  
-       if (virtual_start == 0) {
-               g_read_completed = 0;
-               my_buffer_offset += sprintf(my_base + my_buffer_offset,
+       seq_printf(m,
                   "ARM_CKCTL_REG:            0x%-8x     \n"
                   "ARM_IDLECT1_REG:          0x%-8x     \n"
                   "ARM_IDLECT2_REG:          0x%-8x     \n"
                   ULPD_SHOW(ULPD_STATUS_REQ),
                   ULPD_SHOW(ULPD_POWER_CTRL));
  
-               if (cpu_is_omap7xx()) {
-                       my_buffer_offset += sprintf(my_base + my_buffer_offset,
+       if (cpu_is_omap7xx()) {
+               seq_printf(m,
                           "MPUI7XX_CTRL_REG         0x%-8x \n"
                           "MPUI7XX_DSP_STATUS_REG:      0x%-8x \n"
                           "MPUI7XX_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
                           MPUI7XX_SHOW(MPUI_DSP_API_CONFIG),
                           MPUI7XX_SHOW(EMIFF_SDRAM_CONFIG),
                           MPUI7XX_SHOW(EMIFS_CONFIG));
-               } else if (cpu_is_omap15xx()) {
-                       my_buffer_offset += sprintf(my_base + my_buffer_offset,
+       } else if (cpu_is_omap15xx()) {
+               seq_printf(m,
                           "MPUI1510_CTRL_REG             0x%-8x \n"
                           "MPUI1510_DSP_STATUS_REG:      0x%-8x \n"
                           "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
                           MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
                           MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
                           MPUI1510_SHOW(EMIFS_CONFIG));
-               } else if (cpu_is_omap16xx()) {
-                       my_buffer_offset += sprintf(my_base + my_buffer_offset,
+       } else if (cpu_is_omap16xx()) {
+               seq_printf(m,
                           "MPUI1610_CTRL_REG             0x%-8x \n"
                           "MPUI1610_DSP_STATUS_REG:      0x%-8x \n"
                           "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
                           MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
                           MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
                           MPUI1610_SHOW(EMIFS_CONFIG));
-               }
-               g_read_completed++;
-       } else if (g_read_completed >= 1) {
-                *eof = 1;
-                return 0;
        }
-       g_read_completed++;
  
-       *my_first_byte = page_buffer;
-       return  my_buffer_offset;
+       return 0;
+ }
+ static int omap_pm_debug_open(struct inode *inode, struct file *file)
+ {
+       return single_open(file, omap_pm_debug_show,
+                               &inode->i_private);
  }
  
- static void omap_pm_init_proc(void)
+ static const struct file_operations omap_pm_debug_fops = {
+       .open           = omap_pm_debug_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+ };
+ static void omap_pm_init_debugfs(void)
  {
-       /* XXX Appears to leak memory */
-       create_proc_read_entry("driver/omap_pm",
-                              S_IWUSR | S_IRUGO, NULL,
-                              omap_pm_read_proc, NULL);
+       struct dentry *d;
+       d = debugfs_create_dir("pm_debug", NULL);
+       if (!d)
+               return;
+       (void) debugfs_create_file("omap_pm", S_IWUSR | S_IRUGO,
+                                       d, NULL, &omap_pm_debug_fops);
  }
  
- #endif /* DEBUG && CONFIG_PROC_FS */
+ #endif /* CONFIG_DEBUG_FS */
  
  /*
   *    omap_pm_prepare - Do preliminary suspend work.
  static int omap_pm_prepare(void)
  {
        /* We cannot sleep in idle until we have resumed */
 -      disable_hlt();
 -
 +      cpu_idle_poll_ctrl(true);
        return 0;
  }
  
@@@ -621,7 -617,7 +617,7 @@@ static int omap_pm_enter(suspend_state_
  
  static void omap_pm_finish(void)
  {
 -      enable_hlt();
 +      cpu_idle_poll_ctrl(false);
  }
  
  
@@@ -701,8 -697,8 +697,8 @@@ static int __init omap_pm_init(void
  
        suspend_set_ops(&omap_pm_ops);
  
- #if defined(DEBUG) && defined(CONFIG_PROC_FS)
-       omap_pm_init_proc();
+ #ifdef CONFIG_DEBUG_FS
+       omap_pm_init_debugfs();
  #endif
  
  #ifdef CONFIG_OMAP_32K_TIMER
diff --combined arch/mips/mm/init.c
index 3d0346dbccf42c6d1c0b4007120c684c5fbc6c85,60547b7fe2ff97778e49ca5c86eb4bca10a45bf4..9b973e0af9cbbd2ba7c164fcfea8d9ac93265d36
@@@ -29,6 -29,7 +29,7 @@@
  #include <linux/pfn.h>
  #include <linux/hardirq.h>
  #include <linux/gfp.h>
+ #include <linux/kcore.h>
  
  #include <asm/asm-offsets.h>
  #include <asm/bootinfo.h>
@@@ -77,9 -78,10 +78,9 @@@ EXPORT_SYMBOL_GPL(empty_zero_page)
  /*
   * Not static inline because used by IP27 special magic initialization code
   */
 -unsigned long setup_zero_pages(void)
 +void setup_zero_pages(void)
  {
 -      unsigned int order;
 -      unsigned long size;
 +      unsigned int order, i;
        struct page *page;
  
        if (cpu_has_vce)
  
        page = virt_to_page((void *)empty_zero_page);
        split_page(page, order);
 -      while (page < virt_to_page((void *)(empty_zero_page + (PAGE_SIZE << order)))) {
 -              SetPageReserved(page);
 -              page++;
 -      }
 -
 -      size = PAGE_SIZE << order;
 -      zero_page_mask = (size - 1) & PAGE_MASK;
 +      for (i = 0; i < (1 << order); i++, page++)
 +              mark_page_reserved(page);
  
 -      return 1UL << order;
 +      zero_page_mask = ((PAGE_SIZE << order) - 1) & PAGE_MASK;
  }
  
  #ifdef CONFIG_MIPS_MT_SMTC
@@@ -374,7 -381,7 +375,7 @@@ void __init mem_init(void
        high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
  
        totalram_pages += free_all_bootmem();
 -      totalram_pages -= setup_zero_pages();   /* Setup zeroed pages.  */
 +      setup_zero_pages();     /* Setup zeroed pages.  */
  
        reservedpages = ram = 0;
        for (tmp = 0; tmp < max_low_pfn; tmp++)
                        SetPageReserved(page);
                        continue;
                }
 -              ClearPageReserved(page);
 -              init_page_count(page);
 -              __free_page(page);
 -              totalhigh_pages++;
 +              free_highmem_page(page);
        }
 -      totalram_pages += totalhigh_pages;
        num_physpages += totalhigh_pages;
  #endif
  
@@@ -430,8 -441,11 +431,8 @@@ void free_init_pages(const char *what, 
                struct page *page = pfn_to_page(pfn);
                void *addr = phys_to_virt(PFN_PHYS(pfn));
  
 -              ClearPageReserved(page);
 -              init_page_count(page);
                memset(addr, POISON_FREE_INITMEM, PAGE_SIZE);
 -              __free_page(page);
 -              totalram_pages++;
 +              free_reserved_page(page);
        }
        printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
  }
  #ifdef CONFIG_BLK_DEV_INITRD
  void free_initrd_mem(unsigned long start, unsigned long end)
  {
 -      free_init_pages("initrd memory",
 -                      virt_to_phys((void *)start),
 -                      virt_to_phys((void *)end));
 +      free_reserved_area(start, end, POISON_FREE_INITMEM, "initrd");
  }
  #endif
  
  void __init_refok free_initmem(void)
  {
        prom_free_prom_memory();
 -      free_init_pages("unused kernel memory",
 -                      __pa_symbol(&__init_begin),
 -                      __pa_symbol(&__init_end));
 +      free_initmem_default(POISON_FREE_INITMEM);
  }
  
  #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
index 17644c8e10e189856b902fbf4fc38320680217ce,4d720a6a6b25f47ace76c6d84355f18a99d21fe6..2d72d9e96c153b360ae5eb13d68c7d0370b9139e
@@@ -258,6 -258,11 +258,6 @@@ ENTRY(sys32_mmap2_wrapper
        llgtr   %r2,%r2                 # struct mmap_arg_struct_emu31 *
        jg      sys32_mmap2                     # branch to system call
  
 -ENTRY(compat_sys_getrusage_wrapper)
 -      lgfr    %r2,%r2                 # int
 -      llgtr   %r3,%r3                 # struct rusage_emu31 *
 -      jg      compat_sys_getrusage    # branch to system call
 -
  ENTRY(compat_sys_gettimeofday_wrapper)
        llgtr   %r2,%r2                 # struct timeval_emu31 *
        llgtr   %r3,%r3                 # struct timezone *
@@@ -388,6 -393,14 +388,6 @@@ ENTRY(compat_sys_sysinfo_wrapper
        llgtr   %r2,%r2                 # struct sysinfo_emu31 *
        jg      compat_sys_sysinfo      # branch to system call
  
 -ENTRY(sys32_ipc_wrapper)
 -      llgfr   %r2,%r2                 # uint
 -      lgfr    %r3,%r3                 # int
 -      lgfr    %r4,%r4                 # int
 -      lgfr    %r5,%r5                 # int
 -      llgfr   %r6,%r6                 # u32
 -      jg      sys32_ipc               # branch to system call
 -
  ENTRY(sys32_fsync_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_fsync               # branch to system call
@@@ -653,6 -666,13 +653,6 @@@ ENTRY(sys32_capset_wrapper
        llgtr   %r3,%r3                 # const cap_user_data_t
        jg      sys_capset              # branch to system call
  
 -ENTRY(sys32_sendfile_wrapper)
 -      lgfr    %r2,%r2                 # int
 -      lgfr    %r3,%r3                 # int
 -      llgtr   %r4,%r4                 # __kernel_off_emu31_t *
 -      llgfr   %r5,%r5                 # size_t
 -      jg      sys32_sendfile          # branch to system call
 -
  #sys32_vfork_wrapper                  # done in vfork_glue
  
  ENTRY(sys32_truncate64_wrapper)
@@@ -918,6 -938,13 +918,6 @@@ ENTRY(sys_epoll_wait_wrapper
        lgfr    %r5,%r5                 # int
        jg      sys_epoll_wait          # branch to system call
  
 -ENTRY(sys32_lookup_dcookie_wrapper)
 -      sllg    %r2,%r2,32              # get high word of 64bit dcookie
 -      or      %r2,%r3                 # get low word of 64bit dcookie
 -      llgtr   %r3,%r4                 # char *
 -      llgfr   %r4,%r5                 # size_t
 -      jg      sys_lookup_dcookie
 -
  ENTRY(sys32_fadvise64_wrapper)
        lgfr    %r2,%r2                 # int
        sllg    %r3,%r3,32              # get high word of 64bit loff_t
@@@ -1237,12 -1264,29 +1237,12 @@@ ENTRY(sys_tee_wrapper
        llgfr   %r5,%r5                 # unsigned int
        jg      sys_tee
  
 -ENTRY(compat_sys_vmsplice_wrapper)
 -      lgfr    %r2,%r2                 # int
 -      llgtr   %r3,%r3                 # compat_iovec *
 -      llgfr   %r4,%r4                 # unsigned int
 -      llgfr   %r5,%r5                 # unsigned int
 -      jg      compat_sys_vmsplice
 -
  ENTRY(sys_getcpu_wrapper)
        llgtr   %r2,%r2                 # unsigned *
        llgtr   %r3,%r3                 # unsigned *
        llgtr   %r4,%r4                 # struct getcpu_cache *
        jg      sys_getcpu
  
 -ENTRY(compat_sys_epoll_pwait_wrapper)
 -      lgfr    %r2,%r2                 # int
 -      llgtr   %r3,%r3                 # struct compat_epoll_event *
 -      lgfr    %r4,%r4                 # int
 -      lgfr    %r5,%r5                 # int
 -      llgtr   %r6,%r6                 # compat_sigset_t *
 -      llgf    %r0,164(%r15)           # compat_size_t
 -      stg     %r0,160(%r15)
 -      jg      compat_sys_epoll_pwait
 -
  ENTRY(compat_sys_utimes_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # struct compat_timeval *
@@@ -1255,6 -1299,12 +1255,6 @@@ ENTRY(compat_sys_utimensat_wrapper
        lgfr    %r5,%r5                 # int
        jg      compat_sys_utimensat
  
 -ENTRY(compat_sys_signalfd_wrapper)
 -      lgfr    %r2,%r2                 # int
 -      llgtr   %r3,%r3                 # compat_sigset_t *
 -      llgfr   %r4,%r4                 # compat_size_t
 -      jg      compat_sys_signalfd
 -
  ENTRY(sys_eventfd_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_eventfd
@@@ -1273,6 -1323,13 +1273,6 @@@ ENTRY(sys_timerfd_create_wrapper
        lgfr    %r3,%r3                 # int
        jg      sys_timerfd_create
  
 -ENTRY(compat_sys_signalfd4_wrapper)
 -      lgfr    %r2,%r2                 # int
 -      llgtr   %r3,%r3                 # compat_sigset_t *
 -      llgfr   %r4,%r4                 # compat_size_t
 -      lgfr    %r5,%r5                 # int
 -      jg      compat_sys_signalfd4
 -
  ENTRY(sys_eventfd2_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        lgfr    %r3,%r3                 # int
@@@ -1304,6 -1361,13 +1304,6 @@@ ENTRY(sys32_readahead_wrapper
        lgfr    %r5,%r5                 # s32
        jg      sys32_readahead         # branch to system call
  
 -ENTRY(sys32_sendfile64_wrapper)
 -      lgfr    %r2,%r2                 # int
 -      lgfr    %r3,%r3                 # int
 -      llgtr   %r4,%r4                 # compat_loff_t *
 -      lgfr    %r5,%r5                 # s32
 -      jg      sys32_sendfile64        # branch to system call
 -
  ENTRY(sys_tkill_wrapper)
        lgfr    %r2,%r2                 # pid_t
        lgfr    %r3,%r3                 # int
@@@ -1323,22 -1387,6 +1323,6 @@@ ENTRY(compat_sys_keyctl_wrapper
        llgfr   %r6,%r6                 # u32
        jg      compat_sys_keyctl       # branch to system call
  
- ENTRY(compat_sys_preadv_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgtr   %r3,%r3                 # compat_iovec *
-       llgfr   %r4,%r4                 # unsigned long
-       llgfr   %r5,%r5                 # u32
-       llgfr   %r6,%r6                 # u32
-       jg      compat_sys_preadv       # branch to system call
- ENTRY(compat_sys_pwritev_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgtr   %r3,%r3                 # compat_iovec *
-       llgfr   %r4,%r4                 # unsigned long
-       llgfr   %r5,%r5                 # u32
-       llgfr   %r6,%r6                 # u32
-       jg      compat_sys_pwritev      # branch to system call
  ENTRY(sys_perf_event_open_wrapper)
        llgtr   %r2,%r2                 # const struct perf_event_attr *
        lgfr    %r3,%r3                 # pid_t
diff --combined arch/s390/kernel/irq.c
index 4f5ef62934a4d5b59565ae0b71a4f948e576f16c,1580af3db31ae3bc49b33451e1c2e7e3a137e9d1..f7fb58903f6aa67d6d78b409286827614ac70a5c
@@@ -33,7 -33,7 +33,7 @@@ struct irq_class 
  };
  
  /*
 - * The list of "main" irq classes on s390. This is the list of interrrupts
 + * The list of "main" irq classes on s390. This is the list of interrupts
   * that appear both in /proc/stat ("intr" line) and /proc/interrupts.
   * Historically only external and I/O interrupts have been part of /proc/stat.
   * We can't add the split external and I/O sub classes since the first field
@@@ -162,10 -162,8 +162,8 @@@ asmlinkage void do_softirq(void
  #ifdef CONFIG_PROC_FS
  void init_irq_proc(void)
  {
-       struct proc_dir_entry *root_irq_dir;
-       root_irq_dir = proc_mkdir("irq", NULL);
-       create_prof_cpu_mask(root_irq_dir);
+       if (proc_mkdir("irq", NULL))
+               create_prof_cpu_mask();
  }
  #endif
  
index d2baabed7148b22adef307256f823043c7aa2f93,84e8b1a6bfcba5426f3de9aa28536945072b54e0..9f214e992eed2bbbdfbd2bb77a278a92de2dddf5
@@@ -85,7 -85,7 +85,7 @@@ SYSCALL(sys_sigpending,sys_sigpending,c
  SYSCALL(sys_sethostname,sys_sethostname,sys32_sethostname_wrapper)
  SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper)     /* 75 */
  SYSCALL(sys_old_getrlimit,sys_getrlimit,compat_sys_old_getrlimit_wrapper)
 -SYSCALL(sys_getrusage,sys_getrusage,compat_sys_getrusage_wrapper)
 +SYSCALL(sys_getrusage,sys_getrusage,compat_sys_getrusage)
  SYSCALL(sys_gettimeofday,sys_gettimeofday,compat_sys_gettimeofday_wrapper)
  SYSCALL(sys_settimeofday,sys_settimeofday,compat_sys_settimeofday_wrapper)
  SYSCALL(sys_getgroups16,sys_ni_syscall,sys32_getgroups16_wrapper)     /* 80 old getgroups16 syscall */
@@@ -118,14 -118,14 +118,14 @@@ SYSCALL(sys_newstat,sys_newstat,compat_
  SYSCALL(sys_newlstat,sys_newlstat,compat_sys_newlstat_wrapper)
  SYSCALL(sys_newfstat,sys_newfstat,compat_sys_newfstat_wrapper)
  NI_SYSCALL                                                    /* old uname syscall */
 -SYSCALL(sys_lookup_dcookie,sys_lookup_dcookie,sys32_lookup_dcookie_wrapper)   /* 110 */
 +SYSCALL(sys_lookup_dcookie,sys_lookup_dcookie,compat_sys_lookup_dcookie)      /* 110 */
  SYSCALL(sys_vhangup,sys_vhangup,sys_vhangup)
  NI_SYSCALL                                                    /* old "idle" system call */
  NI_SYSCALL                                                    /* vm86old for i386 */
  SYSCALL(sys_wait4,sys_wait4,compat_sys_wait4)
  SYSCALL(sys_swapoff,sys_swapoff,sys32_swapoff_wrapper)                /* 115 */
  SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper)
 -SYSCALL(sys_s390_ipc,sys_s390_ipc,sys32_ipc_wrapper)
 +SYSCALL(sys_s390_ipc,sys_s390_ipc,compat_sys_s390_ipc)
  SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper)
  SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn)
  SYSCALL(sys_clone,sys_clone,sys_clone_wrapper)                        /* 120 */
@@@ -195,7 -195,7 +195,7 @@@ SYSCALL(sys_getcwd,sys_getcwd,sys32_get
  SYSCALL(sys_capget,sys_capget,sys32_capget_wrapper)
  SYSCALL(sys_capset,sys_capset,sys32_capset_wrapper)           /* 185 */
  SYSCALL(sys_sigaltstack,sys_sigaltstack,compat_sys_sigaltstack)
 -SYSCALL(sys_sendfile,sys_sendfile64,sys32_sendfile_wrapper)
 +SYSCALL(sys_sendfile,sys_sendfile64,compat_sys_sendfile)
  NI_SYSCALL                                                    /* streams1 */
  NI_SYSCALL                                                    /* streams2 */
  SYSCALL(sys_vfork,sys_vfork,sys_vfork)                                /* 190 */
@@@ -231,7 -231,7 +231,7 @@@ SYSCALL(sys_madvise,sys_madvise,sys32_m
  SYSCALL(sys_getdents64,sys_getdents64,sys32_getdents64_wrapper)       /* 220 */
  SYSCALL(sys_fcntl64,sys_ni_syscall,compat_sys_fcntl64_wrapper)
  SYSCALL(sys_readahead,sys_readahead,sys32_readahead_wrapper)
 -SYSCALL(sys_sendfile64,sys_ni_syscall,sys32_sendfile64_wrapper)
 +SYSCALL(sys_sendfile64,sys_ni_syscall,compat_sys_sendfile64)
  SYSCALL(sys_setxattr,sys_setxattr,sys32_setxattr_wrapper)
  SYSCALL(sys_lsetxattr,sys_lsetxattr,sys32_lsetxattr_wrapper)  /* 225 */
  SYSCALL(sys_fsetxattr,sys_fsetxattr,sys32_fsetxattr_wrapper)
@@@ -317,27 -317,27 +317,27 @@@ SYSCALL(sys_get_robust_list,sys_get_rob
  SYSCALL(sys_splice,sys_splice,sys_splice_wrapper)
  SYSCALL(sys_sync_file_range,sys_sync_file_range,sys_sync_file_range_wrapper)
  SYSCALL(sys_tee,sys_tee,sys_tee_wrapper)
 -SYSCALL(sys_vmsplice,sys_vmsplice,compat_sys_vmsplice_wrapper)
 +SYSCALL(sys_vmsplice,sys_vmsplice,compat_sys_vmsplice)
  NI_SYSCALL                                                    /* 310 sys_move_pages */
  SYSCALL(sys_getcpu,sys_getcpu,sys_getcpu_wrapper)
 -SYSCALL(sys_epoll_pwait,sys_epoll_pwait,compat_sys_epoll_pwait_wrapper)
 +SYSCALL(sys_epoll_pwait,sys_epoll_pwait,compat_sys_epoll_pwait)
  SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes_wrapper)
  SYSCALL(sys_s390_fallocate,sys_fallocate,sys_fallocate_wrapper)
  SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper)     /* 315 */
 -SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper)
 +SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd)
  NI_SYSCALL                                            /* 317 old sys_timer_fd */
  SYSCALL(sys_eventfd,sys_eventfd,sys_eventfd_wrapper)
  SYSCALL(sys_timerfd_create,sys_timerfd_create,sys_timerfd_create_wrapper)
  SYSCALL(sys_timerfd_settime,sys_timerfd_settime,compat_sys_timerfd_settime) /* 320 */
  SYSCALL(sys_timerfd_gettime,sys_timerfd_gettime,compat_sys_timerfd_gettime)
 -SYSCALL(sys_signalfd4,sys_signalfd4,compat_sys_signalfd4_wrapper)
 +SYSCALL(sys_signalfd4,sys_signalfd4,compat_sys_signalfd4)
  SYSCALL(sys_eventfd2,sys_eventfd2,sys_eventfd2_wrapper)
  SYSCALL(sys_inotify_init1,sys_inotify_init1,sys_inotify_init1_wrapper)
  SYSCALL(sys_pipe2,sys_pipe2,sys_pipe2_wrapper) /* 325 */
  SYSCALL(sys_dup3,sys_dup3,sys_dup3_wrapper)
  SYSCALL(sys_epoll_create1,sys_epoll_create1,sys_epoll_create1_wrapper)
- SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper)
- SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper)
+ SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv)
+ SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev)
  SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo) /* 330 */
  SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper)
  SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper)
diff --combined arch/score/mm/init.c
index 1592aad7dbc4ade31b94314cfd3dc15915a3a288,8b6f796c6ade537965b2df1706820cb6492c3b1e..d8f988a37d16a59518bac5e612a6d19d2bb0ad95
@@@ -31,7 -31,7 +31,7 @@@
  #include <linux/mm.h>
  #include <linux/mman.h>
  #include <linux/pagemap.h>
- #include <linux/proc_fs.h>
+ #include <linux/kcore.h>
  #include <linux/sched.h>
  #include <linux/initrd.h>
  
@@@ -43,7 -43,7 +43,7 @@@ EXPORT_SYMBOL_GPL(empty_zero_page)
  
  static struct kcore_list kcore_mem, kcore_vmalloc;
  
 -static unsigned long setup_zero_page(void)
 +static void setup_zero_page(void)
  {
        struct page *page;
  
@@@ -52,7 -52,9 +52,7 @@@
                panic("Oh boy, that early out of memory?");
  
        page = virt_to_page((void *) empty_zero_page);
 -      SetPageReserved(page);
 -
 -      return 1UL;
 +      mark_page_reserved(page);
  }
  
  #ifndef CONFIG_NEED_MULTIPLE_NODES
@@@ -82,7 -84,7 +82,7 @@@ void __init mem_init(void
  
        high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
        totalram_pages += free_all_bootmem();
 -      totalram_pages -= setup_zero_page();    /* Setup zeroed pages. */
 +      setup_zero_page();      /* Setup zeroed pages. */
        reservedpages = 0;
  
        for (tmp = 0; tmp < max_low_pfn; tmp++)
  }
  #endif /* !CONFIG_NEED_MULTIPLE_NODES */
  
 -static void free_init_pages(const char *what, unsigned long begin, unsigned long end)
 -{
 -      unsigned long pfn;
 -
 -      for (pfn = PFN_UP(begin); pfn < PFN_DOWN(end); pfn++) {
 -              struct page *page = pfn_to_page(pfn);
 -              void *addr = phys_to_virt(PFN_PHYS(pfn));
 -
 -              ClearPageReserved(page);
 -              init_page_count(page);
 -              memset(addr, POISON_FREE_INITMEM, PAGE_SIZE);
 -              __free_page(page);
 -              totalram_pages++;
 -      }
 -      printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
 -}
 -
  #ifdef CONFIG_BLK_DEV_INITRD
  void free_initrd_mem(unsigned long start, unsigned long end)
  {
 -      free_init_pages("initrd memory",
 -              virt_to_phys((void *) start),
 -              virt_to_phys((void *) end));
 +      free_reserved_area(start, end, POISON_FREE_INITMEM, "initrd");
  }
  #endif
  
  void __init_refok free_initmem(void)
  {
 -      free_init_pages("unused kernel memory",
 -      __pa(&__init_begin),
 -      __pa(&__init_end));
 +      free_initmem_default(POISON_FREE_INITMEM);
  }
  
  unsigned long pgd_current;
index 81e94d972f1b521a37a0c143d3b1930c25edacea,03d721cbbc32c13c1d14f55fc978af949165a546..805078e080133bbdb1eab29f9ff742ba55a54955
@@@ -162,6 -162,7 +162,6 @@@ static int aout_core_dump(long signr, s
        fs = get_fs();
        set_fs(KERNEL_DS);
        has_dumped = 1;
 -      current->flags |= PF_DUMPCORE;
        strncpy(dump.u_comm, current->comm, sizeof(current->comm));
        dump.u_ar0 = offsetof(struct user32, regs);
        dump.signal = signr;
@@@ -322,11 -323,8 +322,8 @@@ static int load_aout_binary(struct linu
  
        if (N_MAGIC(ex) == OMAGIC) {
                unsigned long text_addr, map_size;
-               loff_t pos;
  
                text_addr = N_TXTADDR(ex);
-               pos = 32;
                map_size = ex.a_text+ex.a_data;
  
                error = vm_brk(text_addr & PAGE_MASK, map_size);
                        return error;
                }
  
-               error = bprm->file->f_op->read(bprm->file,
-                        (char __user *)text_addr,
-                         ex.a_text+ex.a_data, &pos);
+               error = read_code(bprm->file, text_addr, 32,
+                                 ex.a_text + ex.a_data);
                if ((signed long)error < 0) {
                        send_sig(SIGKILL, current, 0);
                        return error;
                }
-               flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
        } else {
  #ifdef WARN_OLD
                static unsigned long error_time, error_time2;
  #endif
  
                if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) {
-                       loff_t pos = fd_offset;
                        vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
-                       bprm->file->f_op->read(bprm->file,
-                                       (char __user *)N_TXTADDR(ex),
-                                       ex.a_text+ex.a_data, &pos);
-                       flush_icache_range((unsigned long) N_TXTADDR(ex),
-                                          (unsigned long) N_TXTADDR(ex) +
-                                          ex.a_text+ex.a_data);
+                       read_code(bprm->file, N_TXTADDR(ex), fd_offset,
+                                       ex.a_text+ex.a_data);
                        goto beyond_if;
                }
  
@@@ -451,8 -440,6 +439,6 @@@ static int load_aout_library(struct fil
        start_addr =  ex.a_entry & 0xfffff000;
  
        if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
-               loff_t pos = N_TXTOFF(ex);
  #ifdef WARN_OLD
                static unsigned long error_time;
                if (time_after(jiffies, error_time + 5*HZ)) {
  #endif
                vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
  
-               file->f_op->read(file, (char __user *)start_addr,
-                       ex.a_text + ex.a_data, &pos);
-               flush_icache_range((unsigned long) start_addr,
-                                  (unsigned long) start_addr + ex.a_text +
-                                  ex.a_data);
+               read_code(file, start_addr, N_TXTOFF(ex),
+                         ex.a_text + ex.a_data);
                retval = 0;
                goto out;
        }
diff --combined arch/x86/mm/init_64.c
index caad9a0ee19fefb24563353954c1df51fe7f8ecd,24ceda0101bb65e8147cbc921f578c441c436bc8..bb00c4672ad64462b6b3a4e687df6174e68e8ed9
@@@ -32,6 -32,7 +32,7 @@@
  #include <linux/memory_hotplug.h>
  #include <linux/nmi.h>
  #include <linux/gfp.h>
+ #include <linux/kcore.h>
  
  #include <asm/processor.h>
  #include <asm/bios_ebda.h>
@@@ -1011,12 -1012,14 +1012,12 @@@ remove_pagetable(unsigned long start, u
        flush_tlb_all();
  }
  
 -void __ref vmemmap_free(struct page *memmap, unsigned long nr_pages)
 +void __ref vmemmap_free(unsigned long start, unsigned long end)
  {
 -      unsigned long start = (unsigned long)memmap;
 -      unsigned long end = (unsigned long)(memmap + nr_pages);
 -
        remove_pagetable(start, end, false);
  }
  
 +#ifdef CONFIG_MEMORY_HOTREMOVE
  static void __meminit
  kernel_physical_mapping_remove(unsigned long start, unsigned long end)
  {
        remove_pagetable(start, end, true);
  }
  
 -#ifdef CONFIG_MEMORY_HOTREMOVE
  int __ref arch_remove_memory(u64 start, u64 size)
  {
        unsigned long start_pfn = start >> PAGE_SHIFT;
@@@ -1064,9 -1068,10 +1065,9 @@@ void __init mem_init(void
  
        /* clear_bss() already clear the empty_zero_page */
  
 -      reservedpages = 0;
 -
 -      /* this will put all low memory onto the freelists */
        register_page_bootmem_info();
 +
 +      /* this will put all memory onto the freelists */
        totalram_pages = free_all_bootmem();
  
        absent_pages = absent_pages_in_range(0, max_pfn);
@@@ -1281,17 -1286,18 +1282,17 @@@ static long __meminitdata addr_start, a
  static void __meminitdata *p_start, *p_end;
  static int __meminitdata node_start;
  
 -int __meminit
 -vmemmap_populate(struct page *start_page, unsigned long size, int node)
 +static int __meminit vmemmap_populate_hugepages(unsigned long start,
 +                                              unsigned long end, int node)
  {
 -      unsigned long addr = (unsigned long)start_page;
 -      unsigned long end = (unsigned long)(start_page + size);
 +      unsigned long addr;
        unsigned long next;
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
  
 -      for (; addr < end; addr = next) {
 -              void *p = NULL;
 +      for (addr = start; addr < end; addr = next) {
 +              next = pmd_addr_end(addr, end);
  
                pgd = vmemmap_pgd_populate(addr, node);
                if (!pgd)
                if (!pud)
                        return -ENOMEM;
  
 -              if (!cpu_has_pse) {
 -                      next = (addr + PAGE_SIZE) & PAGE_MASK;
 -                      pmd = vmemmap_pmd_populate(pud, addr, node);
 -
 -                      if (!pmd)
 -                              return -ENOMEM;
 -
 -                      p = vmemmap_pte_populate(pmd, addr, node);
 -
 -                      if (!p)
 -                              return -ENOMEM;
 +              pmd = pmd_offset(pud, addr);
 +              if (pmd_none(*pmd)) {
 +                      void *p;
  
 -                      addr_end = addr + PAGE_SIZE;
 -                      p_end = p + PAGE_SIZE;
 -              } else {
 -                      next = pmd_addr_end(addr, end);
 -
 -                      pmd = pmd_offset(pud, addr);
 -                      if (pmd_none(*pmd)) {
 +                      p = vmemmap_alloc_block_buf(PMD_SIZE, node);
 +                      if (p) {
                                pte_t entry;
  
 -                              p = vmemmap_alloc_block_buf(PMD_SIZE, node);
 -                              if (!p)
 -                                      return -ENOMEM;
 -
                                entry = pfn_pte(__pa(p) >> PAGE_SHIFT,
                                                PAGE_KERNEL_LARGE);
                                set_pmd(pmd, __pmd(pte_val(entry)));
  
                                addr_end = addr + PMD_SIZE;
                                p_end = p + PMD_SIZE;
 -                      } else
 -                              vmemmap_verify((pte_t *)pmd, node, addr, next);
 +                              continue;
 +                      }
 +              } else if (pmd_large(*pmd)) {
 +                      vmemmap_verify((pte_t *)pmd, node, addr, next);
 +                      continue;
                }
 -
 +              pr_warn_once("vmemmap: falling back to regular page backing\n");
 +              if (vmemmap_populate_basepages(addr, next, node))
 +                      return -ENOMEM;
        }
 -      sync_global_pgds((unsigned long)start_page, end - 1);
        return 0;
  }
  
 +int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
 +{
 +      int err;
 +
 +      if (cpu_has_pse)
 +              err = vmemmap_populate_hugepages(start, end, node);
 +      else
 +              err = vmemmap_populate_basepages(start, end, node);
 +      if (!err)
 +              sync_global_pgds(start, end - 1);
 +      return err;
 +}
 +
  #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_HAVE_BOOTMEM_INFO_NODE)
  void register_page_bootmem_memmap(unsigned long section_nr,
                                  struct page *start_page, unsigned long size)
index 6b85db0a7ccc3a9070ab4eeafce2db2abd58c08e,55ea7dfb5b3c65e229a046400b2eb9ef8a82ba19..55856b2310d37d76240a2af47140f2deb97e8482
@@@ -34,6 -34,7 +34,7 @@@
  #include <linux/efi-bgrt.h>
  #include <linux/export.h>
  #include <linux/bootmem.h>
+ #include <linux/slab.h>
  #include <linux/memblock.h>
  #include <linux/spinlock.h>
  #include <linux/uaccess.h>
@@@ -41,7 -42,6 +42,7 @@@
  #include <linux/io.h>
  #include <linux/reboot.h>
  #include <linux/bcd.h>
 +#include <linux/ucs2_string.h>
  
  #include <asm/setup.h>
  #include <asm/efi.h>
  #include <asm/cacheflush.h>
  #include <asm/tlbflush.h>
  #include <asm/x86_init.h>
 +#include <asm/rtc.h>
  
  #define EFI_DEBUG     1
  
 +/*
 + * There's some additional metadata associated with each
 + * variable. Intel's reference implementation is 60 bytes - bump that
 + * to account for potential alignment constraints
 + */
 +#define VAR_METADATA_SIZE 64
 +
  struct efi __read_mostly efi = {
        .mps        = EFI_INVALID_TABLE_ADDR,
        .acpi       = EFI_INVALID_TABLE_ADDR,
@@@ -78,13 -70,6 +79,13 @@@ struct efi_memory_map memmap
  static struct efi efi_phys __initdata;
  static efi_system_table_t efi_systab __initdata;
  
 +static u64 efi_var_store_size;
 +static u64 efi_var_remaining_size;
 +static u64 efi_var_max_var_size;
 +static u64 boot_used_size;
 +static u64 boot_var_size;
 +static u64 active_size;
 +
  unsigned long x86_efi_facility;
  
  /*
@@@ -114,15 -99,6 +115,15 @@@ static int __init setup_add_efi_memmap(
  }
  early_param("add_efi_memmap", setup_add_efi_memmap);
  
 +static bool efi_no_storage_paranoia;
 +
 +static int __init setup_storage_paranoia(char *arg)
 +{
 +      efi_no_storage_paranoia = true;
 +      return 0;
 +}
 +early_param("efi_no_storage_paranoia", setup_storage_paranoia);
 +
  
  static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
  {
@@@ -187,53 -163,8 +188,53 @@@ static efi_status_t virt_efi_get_next_v
                                               efi_char16_t *name,
                                               efi_guid_t *vendor)
  {
 -      return efi_call_virt3(get_next_variable,
 -                            name_size, name, vendor);
 +      efi_status_t status;
 +      static bool finished = false;
 +      static u64 var_size;
 +
 +      status = efi_call_virt3(get_next_variable,
 +                              name_size, name, vendor);
 +
 +      if (status == EFI_NOT_FOUND) {
 +              finished = true;
 +              if (var_size < boot_used_size) {
 +                      boot_var_size = boot_used_size - var_size;
 +                      active_size += boot_var_size;
 +              } else {
 +                      printk(KERN_WARNING FW_BUG  "efi: Inconsistent initial sizes\n");
 +              }
 +      }
 +
 +      if (boot_used_size && !finished) {
 +              unsigned long size;
 +              u32 attr;
 +              efi_status_t s;
 +              void *tmp;
 +
 +              s = virt_efi_get_variable(name, vendor, &attr, &size, NULL);
 +
 +              if (s != EFI_BUFFER_TOO_SMALL || !size)
 +                      return status;
 +
 +              tmp = kmalloc(size, GFP_ATOMIC);
 +
 +              if (!tmp)
 +                      return status;
 +
 +              s = virt_efi_get_variable(name, vendor, &attr, &size, tmp);
 +
 +              if (s == EFI_SUCCESS && (attr & EFI_VARIABLE_NON_VOLATILE)) {
 +                      var_size += size;
 +                      var_size += ucs2_strsize(name, 1024);
 +                      active_size += size;
 +                      active_size += VAR_METADATA_SIZE;
 +                      active_size += ucs2_strsize(name, 1024);
 +              }
 +
 +              kfree(tmp);
 +      }
 +
 +      return status;
  }
  
  static efi_status_t virt_efi_set_variable(efi_char16_t *name,
                                          unsigned long data_size,
                                          void *data)
  {
 -      return efi_call_virt5(set_variable,
 -                            name, vendor, attr,
 -                            data_size, data);
 +      efi_status_t status;
 +      u32 orig_attr = 0;
 +      unsigned long orig_size = 0;
 +
 +      status = virt_efi_get_variable(name, vendor, &orig_attr, &orig_size,
 +                                     NULL);
 +
 +      if (status != EFI_BUFFER_TOO_SMALL)
 +              orig_size = 0;
 +
 +      status = efi_call_virt5(set_variable,
 +                              name, vendor, attr,
 +                              data_size, data);
 +
 +      if (status == EFI_SUCCESS) {
 +              if (orig_size) {
 +                      active_size -= orig_size;
 +                      active_size -= ucs2_strsize(name, 1024);
 +                      active_size -= VAR_METADATA_SIZE;
 +              }
 +              if (data_size) {
 +                      active_size += data_size;
 +                      active_size += ucs2_strsize(name, 1024);
 +                      active_size += VAR_METADATA_SIZE;
 +              }
 +      }
 +
 +      return status;
  }
  
  static efi_status_t virt_efi_query_variable_info(u32 attr,
@@@ -353,10 -259,10 +354,10 @@@ static efi_status_t __init phys_efi_get
  
  int efi_set_rtc_mmss(unsigned long nowtime)
  {
 -      int real_seconds, real_minutes;
        efi_status_t    status;
        efi_time_t      eft;
        efi_time_cap_t  cap;
 +      struct rtc_time tm;
  
        status = efi.get_time(&eft, &cap);
        if (status != EFI_SUCCESS) {
                return -1;
        }
  
 -      real_seconds = nowtime % 60;
 -      real_minutes = nowtime / 60;
 -      if (((abs(real_minutes - eft.minute) + 15)/30) & 1)
 -              real_minutes += 30;
 -      real_minutes %= 60;
 -      eft.minute = real_minutes;
 -      eft.second = real_seconds;
 +      rtc_time_to_tm(nowtime, &tm);
 +      if (!rtc_valid_tm(&tm)) {
 +              eft.year = tm.tm_year + 1900;
 +              eft.month = tm.tm_mon + 1;
 +              eft.day = tm.tm_mday;
 +              eft.minute = tm.tm_min;
 +              eft.second = tm.tm_sec;
 +              eft.nanosecond = 0;
 +      } else {
 +              printk(KERN_ERR
 +                     "%s: Invalid EFI RTC value: write of %lx to EFI RTC failed\n",
 +                     __FUNCTION__, nowtime);
 +              return -1;
 +      }
  
        status = efi.set_time(&eft);
        if (status != EFI_SUCCESS) {
@@@ -453,25 -352,24 +454,25 @@@ static void __init do_add_efi_memmap(vo
  
  int __init efi_memblock_x86_reserve_range(void)
  {
 +      struct efi_info *e = &boot_params.efi_info;
        unsigned long pmap;
  
  #ifdef CONFIG_X86_32
        /* Can't handle data above 4GB at this time */
 -      if (boot_params.efi_info.efi_memmap_hi) {
 +      if (e->efi_memmap_hi) {
                pr_err("Memory map is above 4GB, disabling EFI.\n");
                return -EINVAL;
        }
 -      pmap = boot_params.efi_info.efi_memmap;
 +      pmap =  e->efi_memmap;
  #else
 -      pmap = (boot_params.efi_info.efi_memmap |
 -              ((__u64)boot_params.efi_info.efi_memmap_hi<<32));
 +      pmap = (e->efi_memmap | ((__u64)e->efi_memmap_hi << 32));
  #endif
 -      memmap.phys_map = (void *)pmap;
 -      memmap.nr_map = boot_params.efi_info.efi_memmap_size /
 -              boot_params.efi_info.efi_memdesc_size;
 -      memmap.desc_version = boot_params.efi_info.efi_memdesc_version;
 -      memmap.desc_size = boot_params.efi_info.efi_memdesc_size;
 +      memmap.phys_map         = (void *)pmap;
 +      memmap.nr_map           = e->efi_memmap_size /
 +                                e->efi_memdesc_size;
 +      memmap.desc_size        = e->efi_memdesc_size;
 +      memmap.desc_version     = e->efi_memdesc_version;
 +
        memblock_reserve(pmap, memmap.nr_map * memmap.desc_size);
  
        return 0;
@@@ -785,9 -683,6 +786,9 @@@ void __init efi_init(void
        char vendor[100] = "unknown";
        int i = 0;
        void *tmp;
 +      struct setup_data *data;
 +      struct efi_var_bootdata *efi_var_data;
 +      u64 pa_data;
  
  #ifdef CONFIG_X86_32
        if (boot_params.efi_info.efi_systab_hi ||
        if (efi_systab_init(efi_phys.systab))
                return;
  
 +      pa_data = boot_params.hdr.setup_data;
 +      while (pa_data) {
 +              data = early_ioremap(pa_data, sizeof(*efi_var_data));
 +              if (data->type == SETUP_EFI_VARS) {
 +                      efi_var_data = (struct efi_var_bootdata *)data;
 +
 +                      efi_var_store_size = efi_var_data->store_size;
 +                      efi_var_remaining_size = efi_var_data->remaining_size;
 +                      efi_var_max_var_size = efi_var_data->max_var_size;
 +              }
 +              pa_data = data->next;
 +              early_iounmap(data, sizeof(*efi_var_data));
 +      }
 +
 +      boot_used_size = efi_var_store_size - efi_var_remaining_size;
 +
        set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility);
  
        /*
@@@ -1121,48 -1000,3 +1122,48 @@@ u64 efi_mem_attributes(unsigned long ph
        }
        return 0;
  }
 +
 +/*
 + * Some firmware has serious problems when using more than 50% of the EFI
 + * variable store, i.e. it triggers bugs that can brick machines. Ensure that
 + * we never use more than this safe limit.
 + *
 + * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
 + * store.
 + */
 +efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
 +{
 +      efi_status_t status;
 +      u64 storage_size, remaining_size, max_size;
 +
 +      status = efi.query_variable_info(attributes, &storage_size,
 +                                       &remaining_size, &max_size);
 +      if (status != EFI_SUCCESS)
 +              return status;
 +
 +      if (!max_size && remaining_size > size)
 +              printk_once(KERN_ERR FW_BUG "Broken EFI implementation"
 +                          " is returning MaxVariableSize=0\n");
 +      /*
 +       * Some firmware implementations refuse to boot if there's insufficient
 +       * space in the variable store. We account for that by refusing the
 +       * write if permitting it would reduce the available space to under
 +       * 50%. However, some firmware won't reclaim variable space until
 +       * after the used (not merely the actively used) space drops below
 +       * a threshold. We can approximate that case with the value calculated
 +       * above. If both the firmware and our calculations indicate that the
 +       * available space would drop below 50%, refuse the write.
 +       */
 +
 +      if (!storage_size || size > remaining_size ||
 +          (max_size && size > max_size))
 +              return EFI_OUT_OF_RESOURCES;
 +
 +      if (!efi_no_storage_paranoia &&
 +          ((active_size + size + VAR_METADATA_SIZE > storage_size / 2) &&
 +           (remaining_size - size < storage_size / 2)))
 +              return EFI_OUT_OF_RESOURCES;
 +
 +      return EFI_SUCCESS;
 +}
 +EXPORT_SYMBOL_GPL(efi_query_variable_store);
diff --combined drivers/acpi/battery.c
index 0cc384b72943a0b5e3eacd811de149b788a887b2,169ced7e540da86374c5e85bdadf81ffd99a722f..e7100459ac4ad0ab8432e3912841fa0da2988245
@@@ -146,7 -146,7 +146,7 @@@ struct acpi_battery 
  
  #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
  
 -inline int acpi_battery_present(struct acpi_battery *battery)
 +static inline int acpi_battery_present(struct acpi_battery *battery)
  {
        return battery->device->status.battery_present;
  }
@@@ -929,7 -929,7 +929,7 @@@ static int acpi_battery_read_##_name(st
  } \
  static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
  { \
-       return single_open(file, acpi_battery_read_##_name, PDE(inode)->data); \
+       return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \
  }
  
  DECLARE_FILE_FUNCTIONS(info);
diff --combined drivers/acpi/button.c
index 92a659aa639635534c83580dd35d3cb53edbfcd5,5d57cd513f4faf3ac4b6bc4da04e042728a1a00f..d2e617b5b3f661c8d0effd34628eb4225875d0f4
@@@ -33,7 -33,6 +33,7 @@@
  #include <linux/slab.h>
  #include <acpi/acpi_bus.h>
  #include <acpi/acpi_drivers.h>
 +#include <acpi/button.h>
  
  #define PREFIX "ACPI: "
  
@@@ -129,7 -128,7 +129,7 @@@ static int acpi_button_state_seq_show(s
  
  static int acpi_button_state_open_fs(struct inode *inode, struct file *file)
  {
-       return single_open(file, acpi_button_state_seq_show, PDE(inode)->data);
+       return single_open(file, acpi_button_state_seq_show, PDE_DATA(inode));
  }
  
  static const struct file_operations acpi_button_state_fops = {
diff --combined drivers/block/cciss.c
index 1c1b8e544aa250d38710b47c19353c9ef5773c6c,d150fe1248bf7dd1d99c147b19a6f6178144f099..e18c99140c0aa37e2df84c0dd718ed794f9c2265
@@@ -493,7 -493,7 +493,7 @@@ static int cciss_seq_open(struct inode 
        struct seq_file *seq = file->private_data;
  
        if (!ret)
-               seq->private = PDE(inode)->data;
+               seq->private = PDE_DATA(inode);
  
        return ret;
  }
@@@ -4206,7 -4206,7 +4206,7 @@@ static int cciss_find_cfgtables(ctlr_in
        if (rc)
                return rc;
        h->cfgtable = remap_pci_mem(pci_resource_start(h->pdev,
 -              cfg_base_addr_index) + cfg_offset, sizeof(h->cfgtable));
 +              cfg_base_addr_index) + cfg_offset, sizeof(*h->cfgtable));
        if (!h->cfgtable)
                return -ENOMEM;
        rc = write_driver_ver_to_cfgtable(h->cfgtable);
diff --combined drivers/block/loop.c
index dfe758382eafe71861f244f3436ce2db06f5f541,cd1e17460f03642179add8c92beff4c1ce2a2776..b2955b3f2cbc1bb43e19f1e379a5cc976730216d
@@@ -230,9 -230,11 +230,11 @@@ static int __do_lo_send_write(struct fi
        ssize_t bw;
        mm_segment_t old_fs = get_fs();
  
+       file_start_write(file);
        set_fs(get_ds());
        bw = file->f_op->write(file, buf, len, &pos);
        set_fs(old_fs);
+       file_end_write(file);
        if (likely(bw == len))
                return 0;
        printk(KERN_ERR "loop: Write error at byte offset %llu, length %i.\n",
@@@ -922,11 -924,6 +924,11 @@@ static int loop_set_fd(struct loop_devi
                lo->lo_flags |= LO_FLAGS_PARTSCAN;
        if (lo->lo_flags & LO_FLAGS_PARTSCAN)
                ioctl_by_bdev(bdev, BLKRRPART, 0);
 +
 +      /* Grab the block_device to prevent its destruction after we
 +       * put /dev/loopXX inode. Later in loop_clr_fd() we bdput(bdev).
 +       */
 +      bdgrab(bdev);
        return 0;
  
  out_clr:
@@@ -1036,10 -1033,8 +1038,10 @@@ static int loop_clr_fd(struct loop_devi
        memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
        memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
        memset(lo->lo_file_name, 0, LO_NAME_SIZE);
 -      if (bdev)
 +      if (bdev) {
 +              bdput(bdev);
                invalidate_bdev(bdev);
 +      }
        set_capacity(lo->lo_disk, 0);
        loop_sysfs_exit(lo);
        if (bdev) {
@@@ -1630,7 -1625,6 +1632,7 @@@ static int loop_add(struct loop_device 
                goto out_free_dev;
        i = err;
  
 +      err = -ENOMEM;
        lo->lo_queue = blk_alloc_queue(GFP_KERNEL);
        if (!lo->lo_queue)
                goto out_free_dev;
index 67615d6d038df7a21a1454566cd86698e85c5d19,0000000000000000000000000000000000000000..202d2c85ba2e79e2db866e78a03dffa240967f25
mode 100644,000000..100644
--- /dev/null
@@@ -1,251 -1,0 +1,252 @@@
 +#include <linux/efi.h>
 +#include <linux/module.h>
 +#include <linux/pstore.h>
++#include <linux/slab.h>
 +#include <linux/ucs2_string.h>
 +
 +#define DUMP_NAME_LEN 52
 +
 +static bool efivars_pstore_disable =
 +      IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE);
 +
 +module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);
 +
 +#define PSTORE_EFI_ATTRIBUTES \
 +      (EFI_VARIABLE_NON_VOLATILE | \
 +       EFI_VARIABLE_BOOTSERVICE_ACCESS | \
 +       EFI_VARIABLE_RUNTIME_ACCESS)
 +
 +static int efi_pstore_open(struct pstore_info *psi)
 +{
 +      efivar_entry_iter_begin();
 +      psi->data = NULL;
 +      return 0;
 +}
 +
 +static int efi_pstore_close(struct pstore_info *psi)
 +{
 +      efivar_entry_iter_end();
 +      psi->data = NULL;
 +      return 0;
 +}
 +
 +struct pstore_read_data {
 +      u64 *id;
 +      enum pstore_type_id *type;
 +      int *count;
 +      struct timespec *timespec;
 +      char **buf;
 +};
 +
 +static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
 +{
 +      efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
 +      struct pstore_read_data *cb_data = data;
 +      char name[DUMP_NAME_LEN];
 +      int i;
 +      int cnt;
 +      unsigned int part;
 +      unsigned long time, size;
 +
 +      if (efi_guidcmp(entry->var.VendorGuid, vendor))
 +              return 0;
 +
 +      for (i = 0; i < DUMP_NAME_LEN; i++)
 +              name[i] = entry->var.VariableName[i];
 +
 +      if (sscanf(name, "dump-type%u-%u-%d-%lu",
 +                 cb_data->type, &part, &cnt, &time) == 4) {
 +              *cb_data->id = part;
 +              *cb_data->count = cnt;
 +              cb_data->timespec->tv_sec = time;
 +              cb_data->timespec->tv_nsec = 0;
 +      } else if (sscanf(name, "dump-type%u-%u-%lu",
 +                        cb_data->type, &part, &time) == 3) {
 +              /*
 +               * Check if an old format,
 +               * which doesn't support holding
 +               * multiple logs, remains.
 +               */
 +              *cb_data->id = part;
 +              *cb_data->count = 0;
 +              cb_data->timespec->tv_sec = time;
 +              cb_data->timespec->tv_nsec = 0;
 +      } else
 +              return 0;
 +
 +      entry->var.DataSize = 1024;
 +      __efivar_entry_get(entry, &entry->var.Attributes,
 +                         &entry->var.DataSize, entry->var.Data);
 +      size = entry->var.DataSize;
 +
 +      *cb_data->buf = kmalloc(size, GFP_KERNEL);
 +      if (*cb_data->buf == NULL)
 +              return -ENOMEM;
 +      memcpy(*cb_data->buf, entry->var.Data, size);
 +      return size;
 +}
 +
 +static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
 +                             int *count, struct timespec *timespec,
 +                             char **buf, struct pstore_info *psi)
 +{
 +      struct pstore_read_data data;
 +
 +      data.id = id;
 +      data.type = type;
 +      data.count = count;
 +      data.timespec = timespec;
 +      data.buf = buf;
 +
 +      return __efivar_entry_iter(efi_pstore_read_func, &efivar_sysfs_list, &data,
 +                                 (struct efivar_entry **)&psi->data);
 +}
 +
 +static int efi_pstore_write(enum pstore_type_id type,
 +              enum kmsg_dump_reason reason, u64 *id,
 +              unsigned int part, int count, size_t size,
 +              struct pstore_info *psi)
 +{
 +      char name[DUMP_NAME_LEN];
 +      efi_char16_t efi_name[DUMP_NAME_LEN];
 +      efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
 +      int i, ret = 0;
 +
 +      sprintf(name, "dump-type%u-%u-%d-%lu", type, part, count,
 +              get_seconds());
 +
 +      for (i = 0; i < DUMP_NAME_LEN; i++)
 +              efi_name[i] = name[i];
 +
 +      efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES,
 +                            !pstore_cannot_block_path(reason),
 +                            size, psi->buf);
 +
 +      if (reason == KMSG_DUMP_OOPS)
 +              efivar_run_worker();
 +
 +      *id = part;
 +      return ret;
 +};
 +
 +struct pstore_erase_data {
 +      u64 id;
 +      enum pstore_type_id type;
 +      int count;
 +      struct timespec time;
 +      efi_char16_t *name;
 +};
 +
 +/*
 + * Clean up an entry with the same name
 + */
 +static int efi_pstore_erase_func(struct efivar_entry *entry, void *data)
 +{
 +      struct pstore_erase_data *ed = data;
 +      efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
 +      efi_char16_t efi_name_old[DUMP_NAME_LEN];
 +      efi_char16_t *efi_name = ed->name;
 +      unsigned long ucs2_len = ucs2_strlen(ed->name);
 +      char name_old[DUMP_NAME_LEN];
 +      int i;
 +
 +      if (efi_guidcmp(entry->var.VendorGuid, vendor))
 +              return 0;
 +
 +      if (ucs2_strncmp(entry->var.VariableName,
 +                        efi_name, (size_t)ucs2_len)) {
 +              /*
 +               * Check if an old format, which doesn't support
 +               * holding multiple logs, remains.
 +               */
 +              sprintf(name_old, "dump-type%u-%u-%lu", ed->type,
 +                      (unsigned int)ed->id, ed->time.tv_sec);
 +
 +              for (i = 0; i < DUMP_NAME_LEN; i++)
 +                      efi_name_old[i] = name_old[i];
 +
 +              if (ucs2_strncmp(entry->var.VariableName, efi_name_old,
 +                                ucs2_strlen(efi_name_old)))
 +                      return 0;
 +      }
 +
 +      /* found */
 +      __efivar_entry_delete(entry);
 +      list_del(&entry->list);
 +
 +      return 1;
 +}
 +
 +static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
 +                          struct timespec time, struct pstore_info *psi)
 +{
 +      struct pstore_erase_data edata;
 +      struct efivar_entry *entry = NULL;
 +      char name[DUMP_NAME_LEN];
 +      efi_char16_t efi_name[DUMP_NAME_LEN];
 +      int found, i;
 +
 +      sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count,
 +              time.tv_sec);
 +
 +      for (i = 0; i < DUMP_NAME_LEN; i++)
 +              efi_name[i] = name[i];
 +
 +      edata.id = id;
 +      edata.type = type;
 +      edata.count = count;
 +      edata.time = time;
 +      edata.name = efi_name;
 +
 +      efivar_entry_iter_begin();
 +      found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, &edata, &entry);
 +      efivar_entry_iter_end();
 +
 +      if (found)
 +              efivar_unregister(entry);
 +
 +      return 0;
 +}
 +
 +static struct pstore_info efi_pstore_info = {
 +      .owner          = THIS_MODULE,
 +      .name           = "efi",
 +      .open           = efi_pstore_open,
 +      .close          = efi_pstore_close,
 +      .read           = efi_pstore_read,
 +      .write          = efi_pstore_write,
 +      .erase          = efi_pstore_erase,
 +};
 +
 +static __init int efivars_pstore_init(void)
 +{
 +      if (!efi_enabled(EFI_RUNTIME_SERVICES))
 +              return 0;
 +
 +      if (!efivars_kobject())
 +              return 0;
 +
 +      if (efivars_pstore_disable)
 +              return 0;
 +
 +      efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
 +      if (!efi_pstore_info.buf)
 +              return -ENOMEM;
 +
 +      efi_pstore_info.bufsize = 1024;
 +      spin_lock_init(&efi_pstore_info.buf_lock);
 +
 +      pstore_register(&efi_pstore_info);
 +
 +      return 0;
 +}
 +
 +static __exit void efivars_pstore_exit(void)
 +{
 +}
 +
 +module_init(efivars_pstore_init);
 +module_exit(efivars_pstore_exit);
 +
 +MODULE_DESCRIPTION("EFI variable backend for pstore");
 +MODULE_LICENSE("GPL");
index 5e94897244cff22f56d83d97411a4df36e78a89f,0000000000000000000000000000000000000000..b623c599e572975fd30db879da54194ef025dcf7
mode 100644,000000..100644
--- /dev/null
@@@ -1,616 -1,0 +1,617 @@@
 +/*
 + * Originally from efivars.c,
 + *
 + * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
 + * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
 + *
 + * This code takes all variables accessible from EFI runtime and
 + *  exports them via sysfs
 + *
 + *  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
 + *
 + * Changelog:
 + *
 + *  17 May 2004 - Matt Domsch <Matt_Domsch@dell.com>
 + *   remove check for efi_enabled in exit
 + *   add MODULE_VERSION
 + *
 + *  26 Apr 2004 - Matt Domsch <Matt_Domsch@dell.com>
 + *   minor bug fixes
 + *
 + *  21 Apr 2004 - Matt Tolentino <matthew.e.tolentino@intel.com)
 + *   converted driver to export variable information via sysfs
 + *   and moved to drivers/firmware directory
 + *   bumped revision number to v0.07 to reflect conversion & move
 + *
 + *  10 Dec 2002 - Matt Domsch <Matt_Domsch@dell.com>
 + *   fix locking per Peter Chubb's findings
 + *
 + *  25 Mar 2002 - Matt Domsch <Matt_Domsch@dell.com>
 + *   move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_unparse()
 + *
 + *  12 Feb 2002 - Matt Domsch <Matt_Domsch@dell.com>
 + *   use list_for_each_safe when deleting vars.
 + *   remove ifdef CONFIG_SMP around include <linux/smp.h>
 + *   v0.04 release to linux-ia64@linuxia64.org
 + *
 + *  20 April 2001 - Matt Domsch <Matt_Domsch@dell.com>
 + *   Moved vars from /proc/efi to /proc/efi/vars, and made
 + *   efi.c own the /proc/efi directory.
 + *   v0.03 release to linux-ia64@linuxia64.org
 + *
 + *  26 March 2001 - Matt Domsch <Matt_Domsch@dell.com>
 + *   At the request of Stephane, moved ownership of /proc/efi
 + *   to efi.c, and now efivars lives under /proc/efi/vars.
 + *
 + *  12 March 2001 - Matt Domsch <Matt_Domsch@dell.com>
 + *   Feedback received from Stephane Eranian incorporated.
 + *   efivar_write() checks copy_from_user() return value.
 + *   efivar_read/write() returns proper errno.
 + *   v0.02 release to linux-ia64@linuxia64.org
 + *
 + *  26 February 2001 - Matt Domsch <Matt_Domsch@dell.com>
 + *   v0.01 release to linux-ia64@linuxia64.org
 + */
 +
 +#include <linux/efi.h>
 +#include <linux/module.h>
++#include <linux/slab.h>
 +#include <linux/ucs2_string.h>
 +
 +#define EFIVARS_VERSION "0.08"
 +#define EFIVARS_DATE "2004-May-17"
 +
 +MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
 +MODULE_DESCRIPTION("sysfs interface to EFI Variables");
 +MODULE_LICENSE("GPL");
 +MODULE_VERSION(EFIVARS_VERSION);
 +
 +LIST_HEAD(efivar_sysfs_list);
 +EXPORT_SYMBOL_GPL(efivar_sysfs_list);
 +
 +static struct kset *efivars_kset;
 +
 +static struct bin_attribute *efivars_new_var;
 +static struct bin_attribute *efivars_del_var;
 +
 +struct efivar_attribute {
 +      struct attribute attr;
 +      ssize_t (*show) (struct efivar_entry *entry, char *buf);
 +      ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
 +};
 +
 +#define EFIVAR_ATTR(_name, _mode, _show, _store) \
 +struct efivar_attribute efivar_attr_##_name = { \
 +      .attr = {.name = __stringify(_name), .mode = _mode}, \
 +      .show = _show, \
 +      .store = _store, \
 +};
 +
 +#define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr)
 +#define to_efivar_entry(obj)  container_of(obj, struct efivar_entry, kobj)
 +
 +/*
 + * Prototype for sysfs creation function
 + */
 +static int
 +efivar_create_sysfs_entry(struct efivar_entry *new_var);
 +
 +static ssize_t
 +efivar_guid_read(struct efivar_entry *entry, char *buf)
 +{
 +      struct efi_variable *var = &entry->var;
 +      char *str = buf;
 +
 +      if (!entry || !buf)
 +              return 0;
 +
 +      efi_guid_unparse(&var->VendorGuid, str);
 +      str += strlen(str);
 +      str += sprintf(str, "\n");
 +
 +      return str - buf;
 +}
 +
 +static ssize_t
 +efivar_attr_read(struct efivar_entry *entry, char *buf)
 +{
 +      struct efi_variable *var = &entry->var;
 +      char *str = buf;
 +
 +      if (!entry || !buf)
 +              return -EINVAL;
 +
 +      var->DataSize = 1024;
 +      if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
 +              return -EIO;
 +
 +      if (var->Attributes & EFI_VARIABLE_NON_VOLATILE)
 +              str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n");
 +      if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)
 +              str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n");
 +      if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)
 +              str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n");
 +      if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD)
 +              str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n");
 +      if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
 +              str += sprintf(str,
 +                      "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n");
 +      if (var->Attributes &
 +                      EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
 +              str += sprintf(str,
 +                      "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n");
 +      if (var->Attributes & EFI_VARIABLE_APPEND_WRITE)
 +              str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n");
 +      return str - buf;
 +}
 +
 +static ssize_t
 +efivar_size_read(struct efivar_entry *entry, char *buf)
 +{
 +      struct efi_variable *var = &entry->var;
 +      char *str = buf;
 +
 +      if (!entry || !buf)
 +              return -EINVAL;
 +
 +      var->DataSize = 1024;
 +      if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
 +              return -EIO;
 +
 +      str += sprintf(str, "0x%lx\n", var->DataSize);
 +      return str - buf;
 +}
 +
 +static ssize_t
 +efivar_data_read(struct efivar_entry *entry, char *buf)
 +{
 +      struct efi_variable *var = &entry->var;
 +
 +      if (!entry || !buf)
 +              return -EINVAL;
 +
 +      var->DataSize = 1024;
 +      if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
 +              return -EIO;
 +
 +      memcpy(buf, var->Data, var->DataSize);
 +      return var->DataSize;
 +}
 +/*
 + * We allow each variable to be edited via rewriting the
 + * entire efi variable structure.
 + */
 +static ssize_t
 +efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
 +{
 +      struct efi_variable *new_var, *var = &entry->var;
 +      int err;
 +
 +      if (count != sizeof(struct efi_variable))
 +              return -EINVAL;
 +
 +      new_var = (struct efi_variable *)buf;
 +      /*
 +       * If only updating the variable data, then the name
 +       * and guid should remain the same
 +       */
 +      if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) ||
 +              efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) {
 +              printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n");
 +              return -EINVAL;
 +      }
 +
 +      if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){
 +              printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n");
 +              return -EINVAL;
 +      }
 +
 +      if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
 +          efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) {
 +              printk(KERN_ERR "efivars: Malformed variable content\n");
 +              return -EINVAL;
 +      }
 +
 +      memcpy(&entry->var, new_var, count);
 +
 +      err = efivar_entry_set(entry, new_var->Attributes,
 +                             new_var->DataSize, new_var->Data, false);
 +      if (err) {
 +              printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err);
 +              return -EIO;
 +      }
 +
 +      return count;
 +}
 +
 +static ssize_t
 +efivar_show_raw(struct efivar_entry *entry, char *buf)
 +{
 +      struct efi_variable *var = &entry->var;
 +
 +      if (!entry || !buf)
 +              return 0;
 +
 +      var->DataSize = 1024;
 +      if (efivar_entry_get(entry, &entry->var.Attributes,
 +                           &entry->var.DataSize, entry->var.Data))
 +              return -EIO;
 +
 +      memcpy(buf, var, sizeof(*var));
 +
 +      return sizeof(*var);
 +}
 +
 +/*
 + * Generic read/write functions that call the specific functions of
 + * the attributes...
 + */
 +static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr,
 +                              char *buf)
 +{
 +      struct efivar_entry *var = to_efivar_entry(kobj);
 +      struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
 +      ssize_t ret = -EIO;
 +
 +      if (!capable(CAP_SYS_ADMIN))
 +              return -EACCES;
 +
 +      if (efivar_attr->show) {
 +              ret = efivar_attr->show(var, buf);
 +      }
 +      return ret;
 +}
 +
 +static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr,
 +                              const char *buf, size_t count)
 +{
 +      struct efivar_entry *var = to_efivar_entry(kobj);
 +      struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
 +      ssize_t ret = -EIO;
 +
 +      if (!capable(CAP_SYS_ADMIN))
 +              return -EACCES;
 +
 +      if (efivar_attr->store)
 +              ret = efivar_attr->store(var, buf, count);
 +
 +      return ret;
 +}
 +
 +static const struct sysfs_ops efivar_attr_ops = {
 +      .show = efivar_attr_show,
 +      .store = efivar_attr_store,
 +};
 +
 +static void efivar_release(struct kobject *kobj)
 +{
 +      struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj);
 +      kfree(var);
 +}
 +
 +static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL);
 +static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL);
 +static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL);
 +static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL);
 +static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw);
 +
 +static struct attribute *def_attrs[] = {
 +      &efivar_attr_guid.attr,
 +      &efivar_attr_size.attr,
 +      &efivar_attr_attributes.attr,
 +      &efivar_attr_data.attr,
 +      &efivar_attr_raw_var.attr,
 +      NULL,
 +};
 +
 +static struct kobj_type efivar_ktype = {
 +      .release = efivar_release,
 +      .sysfs_ops = &efivar_attr_ops,
 +      .default_attrs = def_attrs,
 +};
 +
 +static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
 +                           struct bin_attribute *bin_attr,
 +                           char *buf, loff_t pos, size_t count)
 +{
 +      struct efi_variable *new_var = (struct efi_variable *)buf;
 +      struct efivar_entry *new_entry;
 +      int err;
 +
 +      if (!capable(CAP_SYS_ADMIN))
 +              return -EACCES;
 +
 +      if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
 +          efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) {
 +              printk(KERN_ERR "efivars: Malformed variable content\n");
 +              return -EINVAL;
 +      }
 +
 +      new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
 +      if (!new_entry)
 +              return -ENOMEM;
 +
 +      memcpy(&new_entry->var, new_var, sizeof(*new_var));
 +
 +      err = efivar_entry_set(new_entry, new_var->Attributes, new_var->DataSize,
 +                             new_var->Data, &efivar_sysfs_list);
 +      if (err) {
 +              if (err == -EEXIST)
 +                      err = -EINVAL;
 +              goto out;
 +      }
 +
 +      if (efivar_create_sysfs_entry(new_entry)) {
 +              printk(KERN_WARNING "efivars: failed to create sysfs entry.\n");
 +              kfree(new_entry);
 +      }
 +      return count;
 +
 +out:
 +      kfree(new_entry);
 +      return err;
 +}
 +
 +static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
 +                           struct bin_attribute *bin_attr,
 +                           char *buf, loff_t pos, size_t count)
 +{
 +      struct efi_variable *del_var = (struct efi_variable *)buf;
 +      struct efivar_entry *entry;
 +      int err = 0;
 +
 +      if (!capable(CAP_SYS_ADMIN))
 +              return -EACCES;
 +
 +      efivar_entry_iter_begin();
 +      entry = efivar_entry_find(del_var->VariableName, del_var->VendorGuid,
 +                                &efivar_sysfs_list, true);
 +      if (!entry)
 +              err = -EINVAL;
 +      else if (__efivar_entry_delete(entry))
 +              err = -EIO;
 +
 +      efivar_entry_iter_end();
 +
 +      if (err)
 +              return err;
 +
 +      efivar_unregister(entry);
 +
 +      /* It's dead Jim.... */
 +      return count;
 +}
 +
 +/**
 + * efivar_create_sysfs_entry - create a new entry in sysfs
 + * @new_var: efivar entry to create
 + *
 + * Returns 1 on failure, 0 on success
 + */
 +static int
 +efivar_create_sysfs_entry(struct efivar_entry *new_var)
 +{
 +      int i, short_name_size;
 +      char *short_name;
 +      unsigned long variable_name_size;
 +      efi_char16_t *variable_name;
 +
 +      variable_name = new_var->var.VariableName;
 +      variable_name_size = ucs2_strlen(variable_name) * sizeof(efi_char16_t);
 +
 +      /*
 +       * Length of the variable bytes in ASCII, plus the '-' separator,
 +       * plus the GUID, plus trailing NUL
 +       */
 +      short_name_size = variable_name_size / sizeof(efi_char16_t)
 +                              + 1 + EFI_VARIABLE_GUID_LEN + 1;
 +
 +      short_name = kzalloc(short_name_size, GFP_KERNEL);
 +
 +      if (!short_name)
 +              return 1;
 +
 +      /* Convert Unicode to normal chars (assume top bits are 0),
 +         ala UTF-8 */
 +      for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) {
 +              short_name[i] = variable_name[i] & 0xFF;
 +      }
 +      /* This is ugly, but necessary to separate one vendor's
 +         private variables from another's.         */
 +
 +      *(short_name + strlen(short_name)) = '-';
 +      efi_guid_unparse(&new_var->var.VendorGuid,
 +                       short_name + strlen(short_name));
 +
 +      new_var->kobj.kset = efivars_kset;
 +
 +      i = kobject_init_and_add(&new_var->kobj, &efivar_ktype,
 +                                 NULL, "%s", short_name);
 +      kfree(short_name);
 +      if (i)
 +              return 1;
 +
 +      kobject_uevent(&new_var->kobj, KOBJ_ADD);
 +      efivar_entry_add(new_var, &efivar_sysfs_list);
 +
 +      return 0;
 +}
 +
 +static int
 +create_efivars_bin_attributes(void)
 +{
 +      struct bin_attribute *attr;
 +      int error;
 +
 +      /* new_var */
 +      attr = kzalloc(sizeof(*attr), GFP_KERNEL);
 +      if (!attr)
 +              return -ENOMEM;
 +
 +      attr->attr.name = "new_var";
 +      attr->attr.mode = 0200;
 +      attr->write = efivar_create;
 +      efivars_new_var = attr;
 +
 +      /* del_var */
 +      attr = kzalloc(sizeof(*attr), GFP_KERNEL);
 +      if (!attr) {
 +              error = -ENOMEM;
 +              goto out_free;
 +      }
 +      attr->attr.name = "del_var";
 +      attr->attr.mode = 0200;
 +      attr->write = efivar_delete;
 +      efivars_del_var = attr;
 +
 +      sysfs_bin_attr_init(efivars_new_var);
 +      sysfs_bin_attr_init(efivars_del_var);
 +
 +      /* Register */
 +      error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_new_var);
 +      if (error) {
 +              printk(KERN_ERR "efivars: unable to create new_var sysfs file"
 +                      " due to error %d\n", error);
 +              goto out_free;
 +      }
 +
 +      error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_del_var);
 +      if (error) {
 +              printk(KERN_ERR "efivars: unable to create del_var sysfs file"
 +                      " due to error %d\n", error);
 +              sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var);
 +              goto out_free;
 +      }
 +
 +      return 0;
 +out_free:
 +      kfree(efivars_del_var);
 +      efivars_del_var = NULL;
 +      kfree(efivars_new_var);
 +      efivars_new_var = NULL;
 +      return error;
 +}
 +
 +static int efivar_update_sysfs_entry(efi_char16_t *name, efi_guid_t vendor,
 +                                   unsigned long name_size, void *data)
 +{
 +      struct efivar_entry *entry = data;
 +
 +      if (efivar_entry_find(name, vendor, &efivar_sysfs_list, false))
 +              return 0;
 +
 +      memcpy(entry->var.VariableName, name, name_size);
 +      memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
 +
 +      return 1;
 +}
 +
 +static void efivar_update_sysfs_entries(struct work_struct *work)
 +{
 +      struct efivar_entry *entry;
 +      int err;
 +
 +      entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 +      if (!entry)
 +              return;
 +
 +      /* Add new sysfs entries */
 +      while (1) {
 +              memset(entry, 0, sizeof(*entry));
 +
 +              err = efivar_init(efivar_update_sysfs_entry, entry,
 +                                true, false, &efivar_sysfs_list);
 +              if (!err)
 +                      break;
 +
 +              efivar_create_sysfs_entry(entry);
 +      }
 +
 +      kfree(entry);
 +}
 +
 +static int efivars_sysfs_callback(efi_char16_t *name, efi_guid_t vendor,
 +                                unsigned long name_size, void *data)
 +{
 +      struct efivar_entry *entry;
 +
 +      entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 +      if (!entry)
 +              return -ENOMEM;
 +
 +      memcpy(entry->var.VariableName, name, name_size);
 +      memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
 +
 +      efivar_create_sysfs_entry(entry);
 +
 +      return 0;
 +}
 +
 +static int efivar_sysfs_destroy(struct efivar_entry *entry, void *data)
 +{
 +      efivar_entry_remove(entry);
 +      efivar_unregister(entry);
 +      return 0;
 +}
 +
 +void efivars_sysfs_exit(void)
 +{
 +      /* Remove all entries and destroy */
 +      __efivar_entry_iter(efivar_sysfs_destroy, &efivar_sysfs_list, NULL, NULL);
 +
 +      if (efivars_new_var)
 +              sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var);
 +      if (efivars_del_var)
 +              sysfs_remove_bin_file(&efivars_kset->kobj, efivars_del_var);
 +      kfree(efivars_new_var);
 +      kfree(efivars_del_var);
 +      kset_unregister(efivars_kset);
 +}
 +
 +int efivars_sysfs_init(void)
 +{
 +      struct kobject *parent_kobj = efivars_kobject();
 +      int error = 0;
 +
 +      /* No efivars has been registered yet */
 +      if (!parent_kobj)
 +              return 0;
 +
 +      printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
 +             EFIVARS_DATE);
 +
 +      efivars_kset = kset_create_and_add("vars", NULL, parent_kobj);
 +      if (!efivars_kset) {
 +              printk(KERN_ERR "efivars: Subsystem registration failed.\n");
 +              return -ENOMEM;
 +      }
 +
 +      efivar_init(efivars_sysfs_callback, NULL, false,
 +                  true, &efivar_sysfs_list);
 +
 +      error = create_efivars_bin_attributes();
 +      if (error) {
 +              efivars_sysfs_exit();
 +              return error;
 +      }
 +
 +      INIT_WORK(&efivar_work, efivar_update_sysfs_entries);
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(efivars_sysfs_init);
 +
 +module_init(efivars_sysfs_init);
 +module_exit(efivars_sysfs_exit);
index 57601c0704c1694637d4a8b15b3da1d1dc7bdb16,73fc7fe007511e722cf905fc4fc6202bc9d4dad9..1f925e856974936914a7fdb5299bda2a4a84bd59
@@@ -920,7 -920,7 +920,7 @@@ static int dvb_frontend_clear_cache(str
        u32 delsys;
  
        delsys = c->delivery_system;
 -      memset(c, 0, sizeof(struct dtv_frontend_properties));
 +      memset(c, 0, offsetof(struct dtv_frontend_properties, strength));
        c->delivery_system = delsys;
  
        c->state = DTV_CLEAR;
@@@ -1509,74 -1509,9 +1509,74 @@@ static bool is_dvbv3_delsys(u32 delsys
        return status;
  }
  
 -static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
 +/**
 + * emulate_delivery_system - emulate a DVBv5 delivery system with a DVBv3 type
 + * @fe:                       struct frontend;
 + * @delsys:                   DVBv5 type that will be used for emulation
 + *
 + * Provides emulation for delivery systems that are compatible with the old
 + * DVBv3 call. Among its usages, it provices support for ISDB-T, and allows
 + * using a DVB-S2 only frontend just like it were a DVB-S, if the frontent
 + * parameters are compatible with DVB-S spec.
 + */
 +static int emulate_delivery_system(struct dvb_frontend *fe, u32 delsys)
  {
 -      int ncaps, i;
 +      int i;
 +      struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 +
 +      c->delivery_system = delsys;
 +
 +      /*
 +       * If the call is for ISDB-T, put it into full-seg, auto mode, TV
 +       */
 +      if (c->delivery_system == SYS_ISDBT) {
 +              dev_dbg(fe->dvb->device,
 +                      "%s: Using defaults for SYS_ISDBT\n",
 +                      __func__);
 +
 +              if (!c->bandwidth_hz)
 +                      c->bandwidth_hz = 6000000;
 +
 +              c->isdbt_partial_reception = 0;
 +              c->isdbt_sb_mode = 0;
 +              c->isdbt_sb_subchannel = 0;
 +              c->isdbt_sb_segment_idx = 0;
 +              c->isdbt_sb_segment_count = 0;
 +              c->isdbt_layer_enabled = 7;
 +              for (i = 0; i < 3; i++) {
 +                      c->layer[i].fec = FEC_AUTO;
 +                      c->layer[i].modulation = QAM_AUTO;
 +                      c->layer[i].interleaving = 0;
 +                      c->layer[i].segment_count = 0;
 +              }
 +      }
 +      dev_dbg(fe->dvb->device, "%s: change delivery system on cache to %d\n",
 +              __func__, c->delivery_system);
 +
 +      return 0;
 +}
 +
 +/**
 + * dvbv5_set_delivery_system - Sets the delivery system for a DVBv5 API call
 + * @fe:                       frontend struct
 + * @desired_system:   delivery system requested by the user
 + *
 + * A DVBv5 call know what's the desired system it wants. So, set it.
 + *
 + * There are, however, a few known issues with early DVBv5 applications that
 + * are also handled by this logic:
 + *
 + * 1) Some early apps use SYS_UNDEFINED as the desired delivery system.
 + *    This is an API violation, but, as we don't want to break userspace,
 + *    convert it to the first supported delivery system.
 + * 2) Some apps might be using a DVBv5 call in a wrong way, passing, for
 + *    example, SYS_DVBT instead of SYS_ISDBT. This is because early usage of
 + *    ISDB-T provided backward compat with DVB-T.
 + */
 +static int dvbv5_set_delivery_system(struct dvb_frontend *fe,
 +                                   u32 desired_system)
 +{
 +      int ncaps;
        u32 delsys = SYS_UNDEFINED;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        enum dvbv3_emulation_type type;
         * assume that the application wants to use the first supported
         * delivery system.
         */
 -      if (c->delivery_system == SYS_UNDEFINED)
 -              c->delivery_system = fe->ops.delsys[0];
 +      if (desired_system == SYS_UNDEFINED)
 +              desired_system = fe->ops.delsys[0];
  
 -      if (desired_system == SYS_UNDEFINED) {
 -              /*
 -               * A DVBv3 call doesn't know what's the desired system.
 -               * Also, DVBv3 applications don't know that ops.info->type
 -               * could be changed, and they simply dies when it doesn't
 -               * match.
 -               * So, don't change the current delivery system, as it
 -               * may be trying to do the wrong thing, like setting an
 -               * ISDB-T frontend as DVB-T. Instead, find the closest
 -               * DVBv3 system that matches the delivery system.
 -               */
 -              if (is_dvbv3_delsys(c->delivery_system)) {
 +      /*
 +       * This is a DVBv5 call. So, it likely knows the supported
 +       * delivery systems. So, check if the desired delivery system is
 +       * supported
 +       */
 +      ncaps = 0;
 +      while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
 +              if (fe->ops.delsys[ncaps] == desired_system) {
 +                      c->delivery_system = desired_system;
                        dev_dbg(fe->dvb->device,
 -                                      "%s: Using delivery system to %d\n",
 -                                      __func__, c->delivery_system);
 -                      return 0;
 -              }
 -              type = dvbv3_type(c->delivery_system);
 -              switch (type) {
 -              case DVBV3_QPSK:
 -                      desired_system = SYS_DVBS;
 -                      break;
 -              case DVBV3_QAM:
 -                      desired_system = SYS_DVBC_ANNEX_A;
 -                      break;
 -              case DVBV3_ATSC:
 -                      desired_system = SYS_ATSC;
 -                      break;
 -              case DVBV3_OFDM:
 -                      desired_system = SYS_DVBT;
 -                      break;
 -              default:
 -                      dev_dbg(fe->dvb->device, "%s: This frontend doesn't support DVBv3 calls\n",
 -                                      __func__);
 -                      return -EINVAL;
 -              }
 -              /*
 -               * Get a delivery system that is compatible with DVBv3
 -               * NOTE: in order for this to work with softwares like Kaffeine that
 -               *      uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
 -               *      DVB-S, drivers that support both should put the SYS_DVBS entry
 -               *      before the SYS_DVBS2, otherwise it won't switch back to DVB-S.
 -               *      The real fix is that userspace applications should not use DVBv3
 -               *      and not trust on calling FE_SET_FRONTEND to switch the delivery
 -               *      system.
 -               */
 -              ncaps = 0;
 -              while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
 -                      if (fe->ops.delsys[ncaps] == desired_system) {
 -                              delsys = desired_system;
 -                              break;
 -                      }
 -                      ncaps++;
 -              }
 -              if (delsys == SYS_UNDEFINED) {
 -                      dev_dbg(fe->dvb->device, "%s: Couldn't find a delivery system that matches %d\n",
 +                                      "%s: Changing delivery system to %d\n",
                                        __func__, desired_system);
 +                      return 0;
                }
 -      } else {
 -              /*
 -               * This is a DVBv5 call. So, it likely knows the supported
 -               * delivery systems.
 -               */
 +              ncaps++;
 +      }
  
 -              /* Check if the desired delivery system is supported */
 -              ncaps = 0;
 -              while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
 -                      if (fe->ops.delsys[ncaps] == desired_system) {
 -                              c->delivery_system = desired_system;
 -                              dev_dbg(fe->dvb->device,
 -                                              "%s: Changing delivery system to %d\n",
 -                                              __func__, desired_system);
 -                              return 0;
 -                      }
 -                      ncaps++;
 -              }
 -              type = dvbv3_type(desired_system);
 +      /*
 +       * The requested delivery system isn't supported. Maybe userspace
 +       * is requesting a DVBv3 compatible delivery system.
 +       *
 +       * The emulation only works if the desired system is one of the
 +       * delivery systems supported by DVBv3 API
 +       */
 +      if (!is_dvbv3_delsys(desired_system)) {
 +              dev_dbg(fe->dvb->device,
 +                      "%s: Delivery system %d not supported.\n",
 +                      __func__, desired_system);
 +              return -EINVAL;
 +      }
  
 -              /*
 -               * The delivery system is not supported. See if it can be
 -               * emulated.
 -               * The emulation only works if the desired system is one of the
 -               * DVBv3 delivery systems
 -               */
 -              if (!is_dvbv3_delsys(desired_system)) {
 -                      dev_dbg(fe->dvb->device,
 -                                      "%s: can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n",
 -                                      __func__);
 -                      return -EINVAL;
 -              }
 +      type = dvbv3_type(desired_system);
  
 -              /*
 -               * Get the last non-DVBv3 delivery system that has the same type
 -               * of the desired system
 -               */
 -              ncaps = 0;
 -              while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
 -                      if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) &&
 -                          !is_dvbv3_delsys(fe->ops.delsys[ncaps]))
 -                              delsys = fe->ops.delsys[ncaps];
 -                      ncaps++;
 -              }
 -              /* There's nothing compatible with the desired delivery system */
 -              if (delsys == SYS_UNDEFINED) {
 -                      dev_dbg(fe->dvb->device,
 -                                      "%s: Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n",
 -                                      __func__);
 -                      return -EINVAL;
 -              }
 +      /*
 +      * Get the last non-DVBv3 delivery system that has the same type
 +      * of the desired system
 +      */
 +      ncaps = 0;
 +      while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
 +              if (dvbv3_type(fe->ops.delsys[ncaps]) == type)
 +                      delsys = fe->ops.delsys[ncaps];
 +              ncaps++;
        }
  
 -      c->delivery_system = delsys;
 +      /* There's nothing compatible with the desired delivery system */
 +      if (delsys == SYS_UNDEFINED) {
 +              dev_dbg(fe->dvb->device,
 +                      "%s: Delivery system %d not supported on emulation mode.\n",
 +                      __func__, desired_system);
 +              return -EINVAL;
 +      }
 +
 +      dev_dbg(fe->dvb->device,
 +              "%s: Using delivery system %d emulated as if it were %d\n",
 +              __func__, delsys, desired_system);
 +
 +      return emulate_delivery_system(fe, desired_system);
 +}
 +
 +/**
 + * dvbv3_set_delivery_system - Sets the delivery system for a DVBv3 API call
 + * @fe:       frontend struct
 + *
 + * A DVBv3 call doesn't know what's the desired system it wants. It also
 + * doesn't allow to switch between different types. Due to that, userspace
 + * should use DVBv5 instead.
 + * However, in order to avoid breaking userspace API, limited backward
 + * compatibility support is provided.
 + *
 + * There are some delivery systems that are incompatible with DVBv3 calls.
 + *
 + * This routine should work fine for frontends that support just one delivery
 + * system.
 + *
 + * For frontends that support multiple frontends:
 + * 1) It defaults to use the first supported delivery system. There's an
 + *    userspace application that allows changing it at runtime;
 + *
 + * 2) If the current delivery system is not compatible with DVBv3, it gets
 + *    the first one that it is compatible.
 + *
 + * NOTE: in order for this to work with applications like Kaffeine that
 + *    uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
 + *    DVB-S, drivers that support both DVB-S and DVB-S2 should have the
 + *    SYS_DVBS entry before the SYS_DVBS2, otherwise it won't switch back
 + *    to DVB-S.
 + */
 +static int dvbv3_set_delivery_system(struct dvb_frontend *fe)
 +{
 +      int ncaps;
 +      u32 delsys = SYS_UNDEFINED;
 +      struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 +
 +      /* If not set yet, defaults to the first supported delivery system */
 +      if (c->delivery_system == SYS_UNDEFINED)
 +              c->delivery_system = fe->ops.delsys[0];
  
        /*
 -       * The DVBv3 or DVBv5 call is requesting a different system. So,
 -       * emulation is needed.
 -       *
 -       * Emulate newer delivery systems like ISDBT, DVBT and DTMB
 -       * for older DVBv5 applications. The emulation will try to use
 -       * the auto mode for most things, and will assume that the desired
 -       * delivery system is the last one at the ops.delsys[] array
 +       * Trivial case: just use the current one, if it already a DVBv3
 +       * delivery system
         */
 -      dev_dbg(fe->dvb->device,
 -                      "%s: Using delivery system %d emulated as if it were a %d\n",
 -                      __func__, delsys, desired_system);
 +      if (is_dvbv3_delsys(c->delivery_system)) {
 +              dev_dbg(fe->dvb->device,
 +                              "%s: Using delivery system to %d\n",
 +                              __func__, c->delivery_system);
 +              return 0;
 +      }
  
        /*
 -       * For now, handles ISDB-T calls. More code may be needed here for the
 -       * other emulated stuff
 +       * Seek for the first delivery system that it is compatible with a
 +       * DVBv3 standard
         */
 -      if (type == DVBV3_OFDM) {
 -              if (c->delivery_system == SYS_ISDBT) {
 -                      dev_dbg(fe->dvb->device,
 -                                      "%s: Using defaults for SYS_ISDBT\n",
 -                                      __func__);
 -
 -                      if (!c->bandwidth_hz)
 -                              c->bandwidth_hz = 6000000;
 -
 -                      c->isdbt_partial_reception = 0;
 -                      c->isdbt_sb_mode = 0;
 -                      c->isdbt_sb_subchannel = 0;
 -                      c->isdbt_sb_segment_idx = 0;
 -                      c->isdbt_sb_segment_count = 0;
 -                      c->isdbt_layer_enabled = 0;
 -                      for (i = 0; i < 3; i++) {
 -                              c->layer[i].fec = FEC_AUTO;
 -                              c->layer[i].modulation = QAM_AUTO;
 -                              c->layer[i].interleaving = 0;
 -                              c->layer[i].segment_count = 0;
 -                      }
 +      ncaps = 0;
 +      while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
 +              if (dvbv3_type(fe->ops.delsys[ncaps]) != DVBV3_UNKNOWN) {
 +                      delsys = fe->ops.delsys[ncaps];
 +                      break;
                }
 +              ncaps++;
        }
 -      dev_dbg(fe->dvb->device, "%s: change delivery system on cache to %d\n",
 -                      __func__, c->delivery_system);
 -
 -      return 0;
 +      if (delsys == SYS_UNDEFINED) {
 +              dev_dbg(fe->dvb->device,
 +                      "%s: Couldn't find a delivery system that works with FE_SET_FRONTEND\n",
 +                      __func__);
 +              return -EINVAL;
 +      }
 +      return emulate_delivery_system(fe, delsys);
  }
  
  static int dtv_property_process_set(struct dvb_frontend *fe,
                c->rolloff = tvp->u.data;
                break;
        case DTV_DELIVERY_SYSTEM:
 -              r = set_delivery_system(fe, tvp->u.data);
 +              r = dvbv5_set_delivery_system(fe, tvp->u.data);
                break;
        case DTV_VOLTAGE:
                c->voltage = tvp->u.data;
@@@ -2370,7 -2335,7 +2370,7 @@@ static int dvb_frontend_ioctl_legacy(st
                break;
  
        case FE_SET_FRONTEND:
 -              err = set_delivery_system(fe, SYS_UNDEFINED);
 +              err = dvbv3_set_delivery_system(fe);
                if (err)
                        break;
  
@@@ -2527,11 -2492,8 +2527,8 @@@ static int dvb_frontend_release(struct 
  
        if (dvbdev->users == -1) {
                wake_up(&fepriv->wait_queue);
-               if (fepriv->exit != DVB_FE_NO_EXIT) {
-                       fops_put(file->f_op);
-                       file->f_op = NULL;
+               if (fepriv->exit != DVB_FE_NO_EXIT)
                        wake_up(&dvbdev->wait_queue);
-               }
                if (fe->ops.ts_bus_ctrl)
                        fe->ops.ts_bus_ctrl(fe, 0);
        }
@@@ -2629,7 -2591,7 +2626,7 @@@ int dvb_register_frontend(struct dvb_ad
         * first supported delivery system (ops->delsys[0])
         */
  
 -        fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
 +      fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
        dvb_frontend_clear_cache(fe);
  
        mutex_unlock(&frontend_mutex);
index c3cc3b52662b30f260b41b044e71de685ca0c299,59ba60659a3e7b38f182bdcdc581fbb58855af75..f91c80c0e9ec0899816ea177dc616e4aa2b2755d
@@@ -185,7 -185,7 +185,7 @@@ static __be16 dvb_net_eth_type_trans(st
                        skb->pkt_type=PACKET_MULTICAST;
        }
  
 -      if (ntohs(eth->h_proto) >= 1536)
 +      if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
                return eth->h_proto;
  
        rawp = skb->data;
@@@ -228,9 -228,9 +228,9 @@@ static int ule_test_sndu( struct dvb_ne
  static int ule_bridged_sndu( struct dvb_net_priv *p )
  {
        struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr;
 -      if(ntohs(hdr->h_proto) < 1536) {
 +      if(ntohs(hdr->h_proto) < ETH_P_802_3_MIN) {
                int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data);
 -              /* A frame Type < 1536 for a bridged frame, introduces a LLC Length field. */
 +              /* A frame Type < ETH_P_802_3_MIN for a bridged frame, introduces a LLC Length field. */
                if(framelen != ntohs(hdr->h_proto)) {
                        return -1;
                }
@@@ -320,7 -320,7 +320,7 @@@ static int handle_ule_extensions( struc
                        (int) p->ule_sndu_type, l, total_ext_len);
  #endif
  
 -      } while (p->ule_sndu_type < 1536);
 +      } while (p->ule_sndu_type < ETH_P_802_3_MIN);
  
        return total_ext_len;
  }
@@@ -712,7 -712,7 +712,7 @@@ static void dvb_net_ule( struct net_dev
                                }
  
                                /* Handle ULE Extension Headers. */
 -                              if (priv->ule_sndu_type < 1536) {
 +                              if (priv->ule_sndu_type < ETH_P_802_3_MIN) {
                                        /* There is an extension header.  Handle it accordingly. */
                                        int l = handle_ule_extensions(priv);
                                        if (l < 0) {
@@@ -1044,7 -1044,7 +1044,7 @@@ static int dvb_net_feed_start(struct ne
                ret = priv->tsfeed->set(priv->tsfeed,
                                        priv->pid, /* pid */
                                        TS_PACKET, /* type */
 -                                      DMX_TS_PES_OTHER, /* pes type */
 +                                      DMX_PES_OTHER, /* pes type */
                                        32768,     /* circular buffer size */
                                        timeout    /* timeout */
                                        );
@@@ -1479,11 -1479,8 +1479,8 @@@ static int dvb_net_close(struct inode *
  
        dvb_generic_release(inode, file);
  
-       if(dvbdev->users == 1 && dvbnet->exit == 1) {
-               fops_put(file->f_op);
-               file->f_op = NULL;
+       if(dvbdev->users == 1 && dvbnet->exit == 1)
                wake_up(&dvbdev->wait_queue);
-       }
        return 0;
  }
  
index b9be535e32b82f36469ff0ad57a0473e8b368eba,d6dfb5765d0ba3006fef715cde707b455b89b11e..68dbc2dbc9825c5ee3f3de4202fd6e35631e4afc
@@@ -45,7 -45,7 +45,7 @@@ static int _intr_msk = FLD_AUD_SRC_RISC
                        FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR;
  
  static int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev,
 -                                            struct sram_channel *ch,
 +                                            const struct sram_channel *ch,
                                              unsigned int bpl, u32 risc)
  {
        unsigned int i, lines;
@@@ -106,7 -106,7 +106,7 @@@ static __le32 *cx25821_risc_field_upstr
                                                 int fifo_enable)
  {
        unsigned int line;
 -      struct sram_channel *sram_ch =
 +      const struct sram_channel *sram_ch =
                dev->channels[dev->_audio_upstream_channel].sram_channels;
        int offset = 0;
  
@@@ -215,7 -215,7 +215,7 @@@ static void cx25821_free_memory_audio(s
  
  void cx25821_stop_upstream_audio(struct cx25821_dev *dev)
  {
 -      struct sram_channel *sram_ch =
 +      const struct sram_channel *sram_ch =
                dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels;
        u32 tmp = 0;
  
@@@ -257,81 -257,48 +257,48 @@@ void cx25821_free_mem_upstream_audio(st
  }
  
  static int cx25821_get_audio_data(struct cx25821_dev *dev,
 -                         struct sram_channel *sram_ch)
 +                         const struct sram_channel *sram_ch)
  {
-       struct file *myfile;
+       struct file *file;
        int frame_index_temp = dev->_audioframe_index;
        int i = 0;
-       int line_size = AUDIO_LINE_SIZE;
        int frame_size = AUDIO_DATA_BUF_SZ;
        int frame_offset = frame_size * frame_index_temp;
-       ssize_t vfs_read_retval = 0;
-       char mybuf[line_size];
+       char mybuf[AUDIO_LINE_SIZE];
        loff_t file_offset = dev->_audioframe_count * frame_size;
-       loff_t pos;
-       mm_segment_t old_fs;
+       char *p = NULL;
  
        if (dev->_audiofile_status == END_OF_FILE)
                return 0;
  
-       myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+       file = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+       if (IS_ERR(file)) {
+               pr_err("%s(): ERROR opening file(%s) with errno = %ld!\n",
+                      __func__, dev->_audiofilename, -PTR_ERR(file));
+               return PTR_ERR(file);
+       }
  
-       if (IS_ERR(myfile)) {
-               const int open_errno = -PTR_ERR(myfile);
-               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
-                      __func__, dev->_audiofilename, open_errno);
-               return PTR_ERR(myfile);
-       } else {
-               if (!(myfile->f_op)) {
-                       pr_err("%s(): File has no file operations registered!\n",
-                               __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
+       if (dev->_audiodata_buf_virt_addr)
+               p = (char *)dev->_audiodata_buf_virt_addr + frame_offset;
  
-               if (!myfile->f_op->read) {
-                       pr_err("%s(): File has no READ operations registered!\n",
+       for (i = 0; i < dev->_audio_lines_count; i++) {
+               int n = kernel_read(file, file_offset, mybuf, AUDIO_LINE_SIZE);
+               if (n < AUDIO_LINE_SIZE) {
+                       pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
                                __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
+                       dev->_audiofile_status = END_OF_FILE;
+                       fput(file);
+                       return 0;
                }
-               pos = myfile->f_pos;
-               old_fs = get_fs();
-               set_fs(KERNEL_DS);
-               for (i = 0; i < dev->_audio_lines_count; i++) {
-                       pos = file_offset;
-                       vfs_read_retval = vfs_read(myfile, mybuf, line_size,
-                                                                       &pos);
-                       if (vfs_read_retval > 0 && vfs_read_retval == line_size
-                           && dev->_audiodata_buf_virt_addr != NULL) {
-                               memcpy((void *)(dev->_audiodata_buf_virt_addr +
-                                               frame_offset / 4), mybuf,
-                                       vfs_read_retval);
-                       }
-                       file_offset += vfs_read_retval;
-                       frame_offset += vfs_read_retval;
-                       if (vfs_read_retval < line_size) {
-                               pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
-                                       __func__);
-                               break;
-                       }
+               dev->_audiofile_status = IN_PROGRESS;
+               if (p) {
+                       memcpy(p, mybuf, n);
+                       p += n;
                }
-               if (i > 0)
-                       dev->_audioframe_count++;
-               dev->_audiofile_status = (vfs_read_retval == line_size) ?
-                                               IN_PROGRESS : END_OF_FILE;
-               set_fs(old_fs);
-               filp_close(myfile, NULL);
+               file_offset += n;
        }
+       dev->_audioframe_count++;
+       fput(file);
  
        return 0;
  }
@@@ -352,88 -319,48 +319,48 @@@ static void cx25821_audioups_handler(st
  }
  
  static int cx25821_openfile_audio(struct cx25821_dev *dev,
 -                         struct sram_channel *sram_ch)
 +                         const struct sram_channel *sram_ch)
  {
-       struct file *myfile;
-       int i = 0, j = 0;
-       int line_size = AUDIO_LINE_SIZE;
-       ssize_t vfs_read_retval = 0;
-       char mybuf[line_size];
-       loff_t pos;
-       loff_t offset = (unsigned long)0;
-       mm_segment_t old_fs;
-       myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
-       if (IS_ERR(myfile)) {
-               const int open_errno = -PTR_ERR(myfile);
-               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
-                       __func__, dev->_audiofilename, open_errno);
-               return PTR_ERR(myfile);
-       } else {
-               if (!(myfile->f_op)) {
-                       pr_err("%s(): File has no file operations registered!\n",
-                               __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
+       char *p = (void *)dev->_audiodata_buf_virt_addr;
+       struct file *file;
+       loff_t offset;
+       int i, j;
+       file = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+       if (IS_ERR(file)) {
+               pr_err("%s(): ERROR opening file(%s) with errno = %ld!\n",
+                       __func__, dev->_audiofilename, PTR_ERR(file));
+               return PTR_ERR(file);
+       }
  
-               if (!myfile->f_op->read) {
-                       pr_err("%s(): File has no READ operations registered!\n",
-                               __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
+       for (j = 0, offset = 0; j < NUM_AUDIO_FRAMES; j++) {
+               for (i = 0; i < dev->_audio_lines_count; i++) {
+                       char buf[AUDIO_LINE_SIZE];
+                       int n = kernel_read(file, offset, buf,
+                                               AUDIO_LINE_SIZE);
  
-               pos = myfile->f_pos;
-               old_fs = get_fs();
-               set_fs(KERNEL_DS);
-               for (j = 0; j < NUM_AUDIO_FRAMES; j++) {
-                       for (i = 0; i < dev->_audio_lines_count; i++) {
-                               pos = offset;
-                               vfs_read_retval = vfs_read(myfile, mybuf,
-                                               line_size, &pos);
-                               if (vfs_read_retval > 0 &&
-                                   vfs_read_retval == line_size &&
-                                   dev->_audiodata_buf_virt_addr != NULL) {
-                                       memcpy((void *)(dev->
-                                                       _audiodata_buf_virt_addr
-                                                       + offset / 4), mybuf,
-                                              vfs_read_retval);
-                               }
-                               offset += vfs_read_retval;
-                               if (vfs_read_retval < line_size) {
-                                       pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
-                                               __func__);
-                                       break;
-                               }
+                       if (n < AUDIO_LINE_SIZE) {
+                               pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
+                                       __func__);
+                               dev->_audiofile_status = END_OF_FILE;
+                               fput(file);
+                               return 0;
                        }
  
-                       if (i > 0)
-                               dev->_audioframe_count++;
+                       if (p)
+                               memcpy(p + offset, buf, n);
  
-                       if (vfs_read_retval < line_size)
-                               break;
+                       offset += n;
                }
-               dev->_audiofile_status = (vfs_read_retval == line_size) ?
-                                               IN_PROGRESS : END_OF_FILE;
-               set_fs(old_fs);
-               myfile->f_pos = 0;
-               filp_close(myfile, NULL);
+               dev->_audioframe_count++;
        }
+       dev->_audiofile_status = IN_PROGRESS;
+       fput(file);
        return 0;
  }
  
  static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,
 -                                               struct sram_channel *sram_ch,
 +                                               const struct sram_channel *sram_ch,
                                                 int bpl)
  {
        int ret = 0;
@@@ -495,7 -422,7 +422,7 @@@ static int cx25821_audio_upstream_irq(s
  {
        int i = 0;
        u32 int_msk_tmp;
 -      struct sram_channel *channel = dev->channels[chan_num].sram_channels;
 +      const struct sram_channel *channel = dev->channels[chan_num].sram_channels;
        dma_addr_t risc_phys_jump_addr;
        __le32 *rp;
  
@@@ -587,7 -514,7 +514,7 @@@ static irqreturn_t cx25821_upstream_irq
        struct cx25821_dev *dev = dev_id;
        u32 audio_status;
        int handled = 0;
 -      struct sram_channel *sram_ch;
 +      const struct sram_channel *sram_ch;
  
        if (!dev)
                return -1;
  }
  
  static void cx25821_wait_fifo_enable(struct cx25821_dev *dev,
 -                                   struct sram_channel *sram_ch)
 +                                   const struct sram_channel *sram_ch)
  {
        int count = 0;
        u32 tmp;
  }
  
  static int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
 -                                          struct sram_channel *sram_ch)
 +                                          const struct sram_channel *sram_ch)
  {
        u32 tmp = 0;
        int err = 0;
@@@ -699,7 -626,7 +626,7 @@@ fail_irq
  
  int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
  {
 -      struct sram_channel *sram_ch;
 +      const struct sram_channel *sram_ch;
        int err = 0;
  
        if (dev->_audio_is_running) {
        dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER;
        _line_size = AUDIO_LINE_SIZE;
  
 -      if (dev->input_audiofilename) {
 +      if ((dev->input_audiofilename) &&
 +          (strcmp(dev->input_audiofilename, "") != 0))
                dev->_audiofilename = kstrdup(dev->input_audiofilename,
                                              GFP_KERNEL);
 -
 -              if (!dev->_audiofilename) {
 -                      err = -ENOMEM;
 -                      goto error;
 -              }
 -
 -              /* Default if filename is empty string */
 -              if (strcmp(dev->input_audiofilename, "") == 0)
 -                      dev->_audiofilename = "/root/audioGOOD.wav";
 -      } else {
 +      else
                dev->_audiofilename = kstrdup(_defaultAudioName,
                                              GFP_KERNEL);
  
 -              if (!dev->_audiofilename) {
 -                      err = -ENOMEM;
 -                      goto error;
 -              }
 +      if (!dev->_audiofilename) {
 +              err = -ENOMEM;
 +              goto error;
        }
  
        cx25821_sram_channel_setup_upstream_audio(dev, sram_ch,
index ff4d93d1907fb372c1d93306a780e593d7576e36,8ee080ef2f2c636cc743f1c28c0f978b0871fc4c..e4561264e12439a8f24f2a63e94ac2572b0d47a0
@@@ -35,7 -35,7 +35,7 @@@ static int ir_lirc_decode(struct rc_de
        struct lirc_codec *lirc = &dev->raw->lirc;
        int sample;
  
 -      if (!(dev->raw->enabled_protocols & RC_BIT_LIRC))
 +      if (!(dev->enabled_protocols & RC_BIT_LIRC))
                return 0;
  
        if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf)
@@@ -307,7 -307,7 +307,7 @@@ static void ir_lirc_close(void *data
        return;
  }
  
- static struct file_operations lirc_fops = {
+ static const struct file_operations lirc_fops = {
        .owner          = THIS_MODULE,
        .write          = ir_lirc_transmit_ir,
        .unlocked_ioctl = ir_lirc_ioctl,
index 4be07f5e22b991b6223caadf99ff2c6faf3db664,76c7694518d9303ebcf6590c149b91db86fd5af2..727b1f53e6adac700cc744b5450ffc49979cb6f4
@@@ -216,7 -216,7 +216,7 @@@ DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32
                        wil_debugfs_iomem_x32_set, "0x%08llx\n");
  
  static struct dentry *wil_debugfs_create_iomem_x32(const char *name,
-                                                  mode_t mode,
+                                                  umode_t mode,
                                                   struct dentry *parent,
                                                   void __iomem *value)
  {
@@@ -312,6 -312,14 +312,6 @@@ static const struct file_operations fop
        .llseek         = seq_lseek,
  };
  
 -static int wil_default_open(struct inode *inode, struct file *file)
 -{
 -      if (inode->i_private)
 -              file->private_data = inode->i_private;
 -
 -      return 0;
 -}
 -
  static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
                                size_t count, loff_t *ppos)
  {
  
  static const struct file_operations fops_ioblob = {
        .read =         wil_read_file_ioblob,
 -      .open =         wil_default_open,
 +      .open =         simple_open,
        .llseek =       default_llseek,
  };
  
  static
  struct dentry *wil_debugfs_create_ioblob(const char *name,
-                                        mode_t mode,
+                                        umode_t mode,
                                         struct dentry *parent,
                                         struct debugfs_blob_wrapper *blob)
  {
@@@ -388,7 -396,7 +388,7 @@@ static ssize_t wil_write_file_reset(str
  
  static const struct file_operations fops_reset = {
        .write = wil_write_file_reset,
 -      .open  = wil_default_open,
 +      .open  = simple_open,
  };
  /*---------Tx descriptor------------*/
  
@@@ -518,50 -526,7 +518,50 @@@ static ssize_t wil_write_file_ssid(stru
  static const struct file_operations fops_ssid = {
        .read = wil_read_file_ssid,
        .write = wil_write_file_ssid,
 -      .open  = wil_default_open,
 +      .open  = simple_open,
 +};
 +
 +/*---------temp------------*/
 +static void print_temp(struct seq_file *s, const char *prefix, u32 t)
 +{
 +      switch (t) {
 +      case 0:
 +      case ~(u32)0:
 +              seq_printf(s, "%s N/A\n", prefix);
 +      break;
 +      default:
 +              seq_printf(s, "%s %d.%03d\n", prefix, t / 1000, t % 1000);
 +              break;
 +      }
 +}
 +
 +static int wil_temp_debugfs_show(struct seq_file *s, void *data)
 +{
 +      struct wil6210_priv *wil = s->private;
 +      u32 t_m, t_r;
 +
 +      int rc = wmi_get_temperature(wil, &t_m, &t_r);
 +      if (rc) {
 +              seq_printf(s, "Failed\n");
 +              return 0;
 +      }
 +
 +      print_temp(s, "MAC temperature   :", t_m);
 +      print_temp(s, "Radio temperature :", t_r);
 +
 +      return 0;
 +}
 +
 +static int wil_temp_seq_open(struct inode *inode, struct file *file)
 +{
 +      return single_open(file, wil_temp_debugfs_show, inode->i_private);
 +}
 +
 +static const struct file_operations fops_temp = {
 +      .open           = wil_temp_seq_open,
 +      .release        = single_release,
 +      .read           = seq_read,
 +      .llseek         = seq_lseek,
  };
  
  /*----------------*/
@@@ -598,7 -563,6 +598,7 @@@ int wil6210_debugfs_init(struct wil6210
        debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread);
  
        debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset);
 +      debugfs_create_file("temp", S_IRUGO, dbg, wil, &fops_temp);
  
        wil->rgf_blob.data = (void * __force)wil->csr + 0;
        wil->rgf_blob.size = 0xa000;
index ebada812b3a5695a10574155cc4f1304bea20862,a6f660c0190248a0095053b6a04087f138a1a325..9b557a1bb7f81e6b785778b6ee7bc8f4f629b1a3
@@@ -144,7 -144,7 +144,7 @@@ static int psm
  static char *essid;
  
  /* Default to encapsulation unless translation requested */
 -static int translate = 1;
 +static bool translate = 1;
  
  static int country = USA;
  
@@@ -178,7 -178,7 +178,7 @@@ module_param(hop_dwell, int, 0)
  module_param(beacon_period, int, 0);
  module_param(psm, int, 0);
  module_param(essid, charp, 0);
 -module_param(translate, int, 0);
 +module_param(translate, bool, 0);
  module_param(country, int, 0);
  module_param(sniffer, int, 0);
  module_param(bc, int, 0);
@@@ -953,7 -953,7 +953,7 @@@ static int translate_frame(ray_dev_t *l
                           unsigned char *data, int len)
  {
        __be16 proto = ((struct ethhdr *)data)->h_proto;
 -      if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */
 +      if (ntohs(proto) >= ETH_P_802_3_MIN) { /* DIX II ethernet frame */
                pr_debug("ray_cs translate_frame DIX II\n");
                /* Copy LLC header to card buffer */
                memcpy_toio(&ptx->var, eth2_llc, sizeof(eth2_llc));
@@@ -1353,7 -1353,7 +1353,7 @@@ static int ray_get_range(struct net_dev
  static int ray_set_framing(struct net_device *dev, struct iw_request_info *info,
                           union iwreq_data *wrqu, char *extra)
  {
 -      translate = *(extra);   /* Set framing mode */
 +      translate = !!*(extra); /* Set framing mode */
  
        return 0;
  }
@@@ -2778,7 -2778,7 +2778,7 @@@ static ssize_t int_proc_write(struct fi
                nr = nr * 10 + c;
                p++;
        } while (--len);
-       *(int *)PDE(file_inode(file))->data = nr;
+       *(int *)PDE_DATA(file_inode(file)) = nr;
        return count;
  }
  
diff --combined drivers/of/base.c
index 1733081eb87310172eddc17b9e691d385ff95926,9c704369eda858644b49d39166205883bb0789a6..0a2bdd106b237f72fc3ca84f55e6c7f49bf1c8d8
@@@ -382,7 -382,6 +382,7 @@@ struct device_node *of_get_next_parent(
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return parent;
  }
 +EXPORT_SYMBOL(of_get_next_parent);
  
  /**
   *    of_get_next_child - Iterate a node childs
@@@ -1453,16 -1452,7 +1453,7 @@@ int of_attach_node(struct device_node *
  #ifdef CONFIG_PROC_DEVICETREE
  static void of_remove_proc_dt_entry(struct device_node *dn)
  {
-       struct device_node *parent = dn->parent;
-       struct property *prop = dn->properties;
-       while (prop) {
-               remove_proc_entry(prop->name, dn->pde);
-               prop = prop->next;
-       }
-       if (dn->pde)
-               remove_proc_entry(dn->pde->name, parent->pde);
+       proc_remove(dn->pde);
  }
  #else
  static void of_remove_proc_dt_entry(struct device_node *dn)
index edec135b1685d0525149bc21c724833398424cb1,05272e676a2813f6cf5ac6ec0ec6ae5388633985..54d31c0a9840b45e34e910af232137d4d349d711
@@@ -844,14 -844,14 +844,14 @@@ static int dispatch_proc_show(struct se
  
  static int dispatch_proc_open(struct inode *inode, struct file *file)
  {
-       return single_open(file, dispatch_proc_show, PDE(inode)->data);
+       return single_open(file, dispatch_proc_show, PDE_DATA(inode));
  }
  
  static ssize_t dispatch_proc_write(struct file *file,
                        const char __user *userbuf,
                        size_t count, loff_t *pos)
  {
-       struct ibm_struct *ibm = PDE(file_inode(file))->data;
+       struct ibm_struct *ibm = PDE_DATA(file_inode(file));
        char *kernbuf;
        int ret;
  
@@@ -1964,6 -1964,9 +1964,6 @@@ struct tp_nvram_state 
  /* kthread for the hotkey poller */
  static struct task_struct *tpacpi_hotkey_task;
  
 -/* Acquired while the poller kthread is running, use to sync start/stop */
 -static struct mutex hotkey_thread_mutex;
 -
  /*
   * Acquire mutex to write poller control variables as an
   * atomic block.
@@@ -2459,6 -2462,8 +2459,6 @@@ static int hotkey_kthread(void *data
        unsigned int poll_freq;
        bool was_frozen;
  
 -      mutex_lock(&hotkey_thread_mutex);
 -
        if (tpacpi_lifecycle == TPACPI_LIFE_EXITING)
                goto exit;
  
        }
  
  exit:
 -      mutex_unlock(&hotkey_thread_mutex);
        return 0;
  }
  
@@@ -2527,6 -2533,9 +2527,6 @@@ static void hotkey_poll_stop_sync(void
        if (tpacpi_hotkey_task) {
                kthread_stop(tpacpi_hotkey_task);
                tpacpi_hotkey_task = NULL;
 -              mutex_lock(&hotkey_thread_mutex);
 -              /* at this point, the thread did exit */
 -              mutex_unlock(&hotkey_thread_mutex);
        }
  }
  
@@@ -3225,6 -3234,7 +3225,6 @@@ static int __init hotkey_init(struct ib
        mutex_init(&hotkey_mutex);
  
  #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
 -      mutex_init(&hotkey_thread_mutex);
        mutex_init(&hotkey_thread_data_mutex);
  #endif
  
index 1c03ee822e5075e544fc469afa1211d3d7996f5d,8dafd65d475874ba0d8b8d174cb6abc70fb5c618..c212db0fc65de583e749d7cabaac54a2849133a6
@@@ -185,9 -185,10 +185,9 @@@ static int pnp_devices_proc_show(struc
  
                if (pnp_bios_get_dev_node(&nodenum, PNPMODE_DYNAMIC, node))
                        break;
 -              seq_printf(m, "%02x\t%08x\t%02x:%02x:%02x\t%04x\n",
 +              seq_printf(m, "%02x\t%08x\t%3phC\t%04x\n",
                             node->handle, node->eisa_id,
 -                           node->type_code[0], node->type_code[1],
 -                           node->type_code[2], node->flags);
 +                           node->type_code, node->flags);
                if (nodenum <= thisnodenum) {
                        printk(KERN_ERR
                               "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n",
@@@ -237,13 -238,13 +237,13 @@@ static int pnpbios_proc_show(struct seq
  
  static int pnpbios_proc_open(struct inode *inode, struct file *file)
  {
-       return single_open(file, pnpbios_proc_show, PDE(inode)->data);
+       return single_open(file, pnpbios_proc_show, PDE_DATA(inode));
  }
  
  static ssize_t pnpbios_proc_write(struct file *file, const char __user *buf,
                                  size_t count, loff_t *pos)
  {
-       void *data = PDE(file_inode(file))->data;
+       void *data = PDE_DATA(file_inode(file));
        struct pnp_bios_node *node;
        int boot = (long)data >> 8;
        u8 nodenum = (long)data;
index 5da297290262c82754e92cd5014820304ca64fde,8b9c191a70198bda139e4f58afe9cec8e0303385..90b8b0515e23d7c0ee0f309d640c5fb6e94e8988
@@@ -839,6 -839,7 +839,6 @@@ lpfc_hba_down_post_s3(struct lpfc_hba *
                 * way, nothing should be on txcmplq as it will NEVER complete.
                 */
                list_splice_init(&pring->txcmplq, &completions);
 -              pring->txcmplq_cnt = 0;
                spin_unlock_irq(&phba->hbalock);
  
                /* Cancel all the IOCBs from the completions list */
@@@ -2914,9 -2915,9 +2914,9 @@@ lpfc_sli4_xri_sgl_update(struct lpfc_hb
                        sglq_entry->state = SGL_FREED;
                        list_add_tail(&sglq_entry->list, &els_sgl_list);
                }
 -              spin_lock(&phba->hbalock);
 +              spin_lock_irq(&phba->hbalock);
                list_splice_init(&els_sgl_list, &phba->sli4_hba.lpfc_sgl_list);
 -              spin_unlock(&phba->hbalock);
 +              spin_unlock_irq(&phba->hbalock);
        } else if (els_xri_cnt < phba->sli4_hba.els_xri_cnt) {
                /* els xri-sgl shrinked */
                xri_cnt = phba->sli4_hba.els_xri_cnt - els_xri_cnt;
                psb->cur_iocbq.sli4_lxritag = lxri;
                psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri];
        }
 -      spin_lock(&phba->scsi_buf_list_lock);
 +      spin_lock_irq(&phba->scsi_buf_list_lock);
        list_splice_init(&scsi_sgl_list, &phba->lpfc_scsi_buf_list);
 -      spin_unlock(&phba->scsi_buf_list_lock);
 +      spin_unlock_irq(&phba->scsi_buf_list_lock);
  
        return 0;
  
@@@ -4002,52 -4003,6 +4002,52 @@@ lpfc_sli4_perform_all_vport_cvl(struct 
        lpfc_destroy_vport_work_array(phba, vports);
  }
  
 +/**
 + * lpfc_sli4_perform_inuse_fcf_recovery - Perform inuse fcf recovery
 + * @vport: pointer to lpfc hba data structure.
 + *
 + * This routine is to perform FCF recovery when the in-use FCF either dead or
 + * got modified.
 + **/
 +static void
 +lpfc_sli4_perform_inuse_fcf_recovery(struct lpfc_hba *phba,
 +                                   struct lpfc_acqe_fip *acqe_fip)
 +{
 +      int rc;
 +
 +      spin_lock_irq(&phba->hbalock);
 +      /* Mark the fast failover process in progress */
 +      phba->fcf.fcf_flag |= FCF_DEAD_DISC;
 +      spin_unlock_irq(&phba->hbalock);
 +
 +      lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY,
 +                      "2771 Start FCF fast failover process due to in-use "
 +                      "FCF DEAD/MODIFIED event: evt_tag:x%x, index:x%x\n",
 +                      acqe_fip->event_tag, acqe_fip->index);
 +      rc = lpfc_sli4_redisc_fcf_table(phba);
 +      if (rc) {
 +              lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
 +                              "2772 Issue FCF rediscover mabilbox command "
 +                              "failed, fail through to FCF dead event\n");
 +              spin_lock_irq(&phba->hbalock);
 +              phba->fcf.fcf_flag &= ~FCF_DEAD_DISC;
 +              spin_unlock_irq(&phba->hbalock);
 +              /*
 +               * Last resort will fail over by treating this as a link
 +               * down to FCF registration.
 +               */
 +              lpfc_sli4_fcf_dead_failthrough(phba);
 +      } else {
 +              /* Reset FCF roundrobin bmask for new discovery */
 +              lpfc_sli4_clear_fcf_rr_bmask(phba);
 +              /*
 +               * Handling fast FCF failover to a DEAD FCF event is
 +               * considered equalivant to receiving CVL to all vports.
 +               */
 +              lpfc_sli4_perform_all_vport_cvl(phba);
 +      }
 +}
 +
  /**
   * lpfc_sli4_async_fip_evt - Process the asynchronous FCoE FIP event
   * @phba: pointer to lpfc hba data structure.
@@@ -4113,22 -4068,9 +4113,22 @@@ lpfc_sli4_async_fip_evt(struct lpfc_hb
                        break;
                }
  
 -              /* If the FCF has been in discovered state, do nothing. */
 -              if (phba->fcf.fcf_flag & FCF_SCAN_DONE) {
 +              /* If FCF has been in discovered state, perform rediscovery
 +               * only if the FCF with the same index of the in-use FCF got
 +               * modified during normal operation. Otherwise, do nothing.
 +               */
 +              if (phba->pport->port_state > LPFC_FLOGI) {
                        spin_unlock_irq(&phba->hbalock);
 +                      if (phba->fcf.current_rec.fcf_indx ==
 +                          acqe_fip->index) {
 +                              lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
 +                                              "3300 In-use FCF (%d) "
 +                                              "modified, perform FCF "
 +                                              "rediscovery\n",
 +                                              acqe_fip->index);
 +                              lpfc_sli4_perform_inuse_fcf_recovery(phba,
 +                                                                   acqe_fip);
 +                      }
                        break;
                }
                spin_unlock_irq(&phba->hbalock);
                 * is no longer valid as we are not in the middle of FCF
                 * failover process already.
                 */
 -              spin_lock_irq(&phba->hbalock);
 -              /* Mark the fast failover process in progress */
 -              phba->fcf.fcf_flag |= FCF_DEAD_DISC;
 -              spin_unlock_irq(&phba->hbalock);
 -
 -              lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY,
 -                              "2771 Start FCF fast failover process due to "
 -                              "FCF DEAD event: evt_tag:x%x, fcf_index:x%x "
 -                              "\n", acqe_fip->event_tag, acqe_fip->index);
 -              rc = lpfc_sli4_redisc_fcf_table(phba);
 -              if (rc) {
 -                      lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
 -                                      LOG_DISCOVERY,
 -                                      "2772 Issue FCF rediscover mabilbox "
 -                                      "command failed, fail through to FCF "
 -                                      "dead event\n");
 -                      spin_lock_irq(&phba->hbalock);
 -                      phba->fcf.fcf_flag &= ~FCF_DEAD_DISC;
 -                      spin_unlock_irq(&phba->hbalock);
 -                      /*
 -                       * Last resort will fail over by treating this
 -                       * as a link down to FCF registration.
 -                       */
 -                      lpfc_sli4_fcf_dead_failthrough(phba);
 -              } else {
 -                      /* Reset FCF roundrobin bmask for new discovery */
 -                      lpfc_sli4_clear_fcf_rr_bmask(phba);
 -                      /*
 -                       * Handling fast FCF failover to a DEAD FCF event is
 -                       * considered equalivant to receiving CVL to all vports.
 -                       */
 -                      lpfc_sli4_perform_all_vport_cvl(phba);
 -              }
 +              lpfc_sli4_perform_inuse_fcf_recovery(phba, acqe_fip);
                break;
        case LPFC_FIP_EVENT_TYPE_CVL:
                phba->fcoe_cvl_eventtag = acqe_fip->event_tag;
@@@ -10394,36 -10368,6 +10394,6 @@@ lpfc_io_resume(struct pci_dev *pdev
        return;
  }
  
- /**
-  * lpfc_mgmt_open - method called when 'lpfcmgmt' is opened from userspace
-  * @inode: pointer to the inode representing the lpfcmgmt device
-  * @filep: pointer to the file representing the open lpfcmgmt device
-  *
-  * This routine puts a reference count on the lpfc module whenever the
-  * character device is opened
-  **/
- static int
- lpfc_mgmt_open(struct inode *inode, struct file *filep)
- {
-       try_module_get(THIS_MODULE);
-       return 0;
- }
- /**
-  * lpfc_mgmt_release - method called when 'lpfcmgmt' is closed in userspace
-  * @inode: pointer to the inode representing the lpfcmgmt device
-  * @filep: pointer to the file representing the open lpfcmgmt device
-  *
-  * This routine removes a reference count from the lpfc module when the
-  * character device is closed
-  **/
- static int
- lpfc_mgmt_release(struct inode *inode, struct file *filep)
- {
-       module_put(THIS_MODULE);
-       return 0;
- }
  static struct pci_device_id lpfc_id_table[] = {
        {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER,
                PCI_ANY_ID, PCI_ANY_ID, },
@@@ -10541,8 -10485,7 +10511,7 @@@ static struct pci_driver lpfc_driver = 
  };
  
  static const struct file_operations lpfc_mgmt_fop = {
-       .open = lpfc_mgmt_open,
-       .release = lpfc_mgmt_release,
+       .owner = THIS_MODULE,
  };
  
  static struct miscdevice lpfc_mgmt_dev = {
index a083715843bdca6b55cdd449641c02b6eb2ef4bb,ccb5e6404d09a85a026ac2c03c1470433b2937ba..5307bf86d5e08d453be2f8d3bd3ca781607b640c
@@@ -47,7 -47,6 +47,7 @@@ MODULE_PARM_DESC(ql2xenableclass2
                "Specify if Class 2 operations are supported from the very "
                "beginning. Default is 0 - class 2 not supported.");
  
 +
  int ql2xlogintimeout = 20;
  module_param(ql2xlogintimeout, int, S_IRUGO);
  MODULE_PARM_DESC(ql2xlogintimeout,
@@@ -355,12 -354,7 +355,12 @@@ fail_req_map
  
  static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
  {
 -      if (req && req->ring)
 +      if (IS_QLAFX00(ha)) {
 +              if (req && req->ring_fx00)
 +                      dma_free_coherent(&ha->pdev->dev,
 +                          (req->length_fx00 + 1) * sizeof(request_t),
 +                          req->ring_fx00, req->dma_fx00);
 +      } else if (req && req->ring)
                dma_free_coherent(&ha->pdev->dev,
                (req->length + 1) * sizeof(request_t),
                req->ring, req->dma);
  
  static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
  {
 -      if (rsp && rsp->ring)
 +      if (IS_QLAFX00(ha)) {
 +              if (rsp && rsp->ring)
 +                      dma_free_coherent(&ha->pdev->dev,
 +                          (rsp->length_fx00 + 1) * sizeof(request_t),
 +                          rsp->ring_fx00, rsp->dma_fx00);
 +      } else if (rsp && rsp->ring) {
                dma_free_coherent(&ha->pdev->dev,
                (rsp->length + 1) * sizeof(response_t),
                rsp->ring, rsp->dma);
 -
 +      }
        kfree(rsp);
        rsp = NULL;
  }
@@@ -644,7 -633,7 +644,7 @@@ qla2x00_sp_free_dma(void *vha, void *pt
        qla2x00_rel_sp(sp->fcport->vha, sp);
  }
  
 -static void
 +void
  qla2x00_sp_compl(void *data, void *ptr, int res)
  {
        struct qla_hw_data *ha = (struct qla_hw_data *)data;
        cmd->scsi_done(cmd);
  }
  
 +/* If we are SP1 here, we need to still take and release the host_lock as SP1
 + * does not have the changes necessary to avoid taking host->host_lock.
 + */
  static int
  qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
  {
@@@ -1318,9 -1304,6 +1318,9 @@@ qla2x00_loop_reset(scsi_qla_host_t *vha
                }
        }
  
 +      if (IS_QLAFX00(ha))
 +              return QLA_SUCCESS;
 +
        if (ha->flags.enable_lip_full_login && !IS_CNA_CAPABLE(ha)) {
                atomic_set(&vha->loop_state, LOOP_DOWN);
                atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
@@@ -1875,7 -1858,6 +1875,7 @@@ static struct isp_operations qla2100_is
        .start_scsi             = qla2x00_start_scsi,
        .abort_isp              = qla2x00_abort_isp,
        .iospace_config         = qla2x00_iospace_config,
 +      .initialize_adapter     = qla2x00_initialize_adapter,
  };
  
  static struct isp_operations qla2300_isp_ops = {
        .start_scsi             = qla2x00_start_scsi,
        .abort_isp              = qla2x00_abort_isp,
        .iospace_config         = qla2x00_iospace_config,
 +      .initialize_adapter     = qla2x00_initialize_adapter,
  };
  
  static struct isp_operations qla24xx_isp_ops = {
        .start_scsi             = qla24xx_start_scsi,
        .abort_isp              = qla2x00_abort_isp,
        .iospace_config         = qla2x00_iospace_config,
 +      .initialize_adapter     = qla2x00_initialize_adapter,
  };
  
  static struct isp_operations qla25xx_isp_ops = {
        .start_scsi             = qla24xx_dif_start_scsi,
        .abort_isp              = qla2x00_abort_isp,
        .iospace_config         = qla2x00_iospace_config,
 +      .initialize_adapter     = qla2x00_initialize_adapter,
  };
  
  static struct isp_operations qla81xx_isp_ops = {
        .start_scsi             = qla24xx_dif_start_scsi,
        .abort_isp              = qla2x00_abort_isp,
        .iospace_config         = qla2x00_iospace_config,
 +      .initialize_adapter     = qla2x00_initialize_adapter,
  };
  
  static struct isp_operations qla82xx_isp_ops = {
        .start_scsi             = qla82xx_start_scsi,
        .abort_isp              = qla82xx_abort_isp,
        .iospace_config         = qla82xx_iospace_config,
 +      .initialize_adapter     = qla2x00_initialize_adapter,
  };
  
  static struct isp_operations qla83xx_isp_ops = {
        .start_scsi             = qla24xx_dif_start_scsi,
        .abort_isp              = qla2x00_abort_isp,
        .iospace_config         = qla83xx_iospace_config,
 +      .initialize_adapter     = qla2x00_initialize_adapter,
 +};
 +
 +static struct isp_operations qlafx00_isp_ops = {
 +      .pci_config             = qlafx00_pci_config,
 +      .reset_chip             = qlafx00_soft_reset,
 +      .chip_diag              = qlafx00_chip_diag,
 +      .config_rings           = qlafx00_config_rings,
 +      .reset_adapter          = qlafx00_soft_reset,
 +      .nvram_config           = NULL,
 +      .update_fw_options      = NULL,
 +      .load_risc              = NULL,
 +      .pci_info_str           = qlafx00_pci_info_str,
 +      .fw_version_str         = qlafx00_fw_version_str,
 +      .intr_handler           = qlafx00_intr_handler,
 +      .enable_intrs           = qlafx00_enable_intrs,
 +      .disable_intrs          = qlafx00_disable_intrs,
 +      .abort_command          = qlafx00_abort_command,
 +      .target_reset           = qlafx00_abort_target,
 +      .lun_reset              = qlafx00_lun_reset,
 +      .fabric_login           = NULL,
 +      .fabric_logout          = NULL,
 +      .calc_req_entries       = NULL,
 +      .build_iocbs            = NULL,
 +      .prep_ms_iocb           = qla24xx_prep_ms_iocb,
 +      .prep_ms_fdmi_iocb      = qla24xx_prep_ms_fdmi_iocb,
 +      .read_nvram             = qla24xx_read_nvram_data,
 +      .write_nvram            = qla24xx_write_nvram_data,
 +      .fw_dump                = NULL,
 +      .beacon_on              = qla24xx_beacon_on,
 +      .beacon_off             = qla24xx_beacon_off,
 +      .beacon_blink           = NULL,
 +      .read_optrom            = qla24xx_read_optrom_data,
 +      .write_optrom           = qla24xx_write_optrom_data,
 +      .get_flash_version      = qla24xx_get_flash_version,
 +      .start_scsi             = qlafx00_start_scsi,
 +      .abort_isp              = qlafx00_abort_isp,
 +      .iospace_config         = qlafx00_iospace_config,
 +      .initialize_adapter     = qlafx00_initialize_adapter,
  };
  
  static inline void
@@@ -2254,9 -2192,6 +2254,9 @@@ qla2x00_set_isp_flags(struct qla_hw_dat
                ha->device_type |= DT_T10_PI;
                ha->fw_srisc_address = RISC_START_ADDRESS_2400;
                break;
 +      case PCI_DEVICE_ID_QLOGIC_ISPF001:
 +              ha->device_type |= DT_ISPFX00;
 +              break;
        }
  
        if (IS_QLA82XX(ha))
@@@ -2330,8 -2265,7 +2330,8 @@@ qla2x00_probe_one(struct pci_dev *pdev
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8021 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2031 ||
 -          pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8031) {
 +          pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8031 ||
 +          pdev->device == PCI_DEVICE_ID_QLOGIC_ISPF001) {
                bars = pci_select_bars(pdev, IORESOURCE_MEM);
                mem_only = 1;
                ql_dbg_pci(ql_dbg_init, pdev, 0x0007,
                ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX;
                ha->nvram_conf_off = ~0;
                ha->nvram_data_off = ~0;
 +      }  else if (IS_QLAFX00(ha)) {
 +              ha->max_fibre_devices = MAX_FIBRE_DEVICES_FX00;
 +              ha->mbx_count = MAILBOX_REGISTER_COUNT_FX00;
 +              ha->aen_mbx_count = AEN_MAILBOX_REGISTER_COUNT_FX00;
 +              req_length = REQUEST_ENTRY_CNT_FX00;
 +              rsp_length = RESPONSE_ENTRY_CNT_FX00;
 +              ha->init_cb_size = sizeof(struct init_cb_fx);
 +              ha->isp_ops = &qlafx00_isp_ops;
 +              ha->port_down_retry_count = 30; /* default value */
 +              ha->mr.fw_hbt_cnt = QLAFX00_HEARTBEAT_INTERVAL;
 +              ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL;
 +              ha->mr.fw_hbt_en = 1;
        }
  
        ql_dbg_pci(ql_dbg_init, pdev, 0x001e,
  
        host = base_vha->host;
        base_vha->req = req;
 -      host->can_queue = req->length + 128;
 +      if (IS_QLAFX00(ha))
 +              host->can_queue = 1024;
 +      else
 +              host->can_queue = req->length + 128;
        if (IS_QLA2XXX_MIDTYPE(ha))
                base_vha->mgmt_svr_loop_id = 10 + base_vha->vp_idx;
        else
                base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER +
                                                base_vha->vp_idx;
  
 +      /* Setup fcport template structure. */
 +      ha->mr.fcport.vha = base_vha;
 +      ha->mr.fcport.port_type = FCT_UNKNOWN;
 +      ha->mr.fcport.loop_id = FC_NO_LOOP_ID;
 +      qla2x00_set_fcport_state(&ha->mr.fcport, FCS_UNCONFIGURED);
 +      ha->mr.fcport.supported_classes = FC_COS_UNSPECIFIED;
 +      ha->mr.fcport.scan_state = 1;
 +
        /* Set the SG table size based on ISP type */
        if (!IS_FWI2_CAPABLE(ha)) {
                if (IS_QLA2100(ha))
@@@ -2651,13 -2562,6 +2651,13 @@@ que_init
        rsp->req = req;
        req->rsp = rsp;
  
 +      if (IS_QLAFX00(ha)) {
 +              ha->rsp_q_map[0] = rsp;
 +              ha->req_q_map[0] = req;
 +              set_bit(0, ha->req_qid_map);
 +              set_bit(0, ha->rsp_qid_map);
 +      }
 +
        /* FWI2-capable only. */
        req->req_q_in = &ha->iobase->isp24.req_q_in;
        req->req_q_out = &ha->iobase->isp24.req_q_out;
                rsp->rsp_q_out =  &ha->mqiobase->isp25mq.rsp_q_out;
        }
  
 +      if (IS_QLAFX00(ha)) {
 +              req->req_q_in = &ha->iobase->ispfx00.req_q_in;
 +              req->req_q_out = &ha->iobase->ispfx00.req_q_out;
 +              rsp->rsp_q_in = &ha->iobase->ispfx00.rsp_q_in;
 +              rsp->rsp_q_out = &ha->iobase->ispfx00.rsp_q_out;
 +      }
 +
        if (IS_QLA82XX(ha)) {
                req->req_q_out = &ha->iobase->isp82.req_q_out[0];
                rsp->rsp_q_in = &ha->iobase->isp82.rsp_q_in[0];
            "req->req_q_in=%p req->req_q_out=%p rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n",
            req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out);
  
 -      if (qla2x00_initialize_adapter(base_vha)) {
 +      if (ha->isp_ops->initialize_adapter(base_vha)) {
                ql_log(ql_log_fatal, base_vha, 0x00d6,
                    "Failed to initialize adapter - Adapter flags %x.\n",
                    base_vha->device_flags);
@@@ -2823,18 -2720,6 +2823,18 @@@ skip_dpc
  
        qla2x00_alloc_sysfs_attr(base_vha);
  
 +      if (IS_QLAFX00(ha)) {
 +              ret = qlafx00_fx_disc(base_vha,
 +                      &base_vha->hw->mr.fcport, FXDISC_GET_CONFIG_INFO);
 +
 +              ret = qlafx00_fx_disc(base_vha,
 +                      &base_vha->hw->mr.fcport, FXDISC_GET_PORT_INFO);
 +
 +              /* Register system information */
 +              ret =  qlafx00_fx_disc(base_vha,
 +                      &base_vha->hw->mr.fcport, FXDISC_REG_HOST_INFO);
 +      }
 +
        qla2x00_init_host_attr(base_vha);
  
        qla2x00_dfs_setup(base_vha);
@@@ -2892,8 -2777,6 +2892,8 @@@ iospace_config_failed
        } else {
                if (ha->iobase)
                        iounmap(ha->iobase);
 +              if (ha->cregbase)
 +                      iounmap(ha->cregbase);
        }
        pci_release_selected_regions(ha->pdev, ha->bars);
        kfree(ha);
@@@ -3077,9 -2960,6 +3077,9 @@@ qla2x00_remove_one(struct pci_dev *pdev
                if (ha->iobase)
                        iounmap(ha->iobase);
  
 +              if (ha->cregbase)
 +                      iounmap(ha->cregbase);
 +
                if (ha->mqiobase)
                        iounmap(ha->mqiobase);
  
@@@ -3188,12 -3068,6 +3188,12 @@@ qla2x00_schedule_rport_del(struct scsi_
  void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
      int do_login, int defer)
  {
 +      if (IS_QLAFX00(vha->hw)) {
 +              qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
 +              qla2x00_schedule_rport_del(vha, fcport, defer);
 +              return;
 +      }
 +
        if (atomic_read(&fcport->state) == FCS_ONLINE &&
            vha->vp_idx == fcport->vha->vp_idx) {
                qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
@@@ -3836,22 -3710,6 +3836,22 @@@ qla2x00_uevent_emit(struct scsi_qla_hos
        kobject_uevent_env(&vha->hw->pdev->dev.kobj, KOBJ_CHANGE, envp);
  }
  
 +int
 +qlafx00_post_aenfx_work(struct scsi_qla_host *vha,  uint32_t evtcode,
 +                      uint32_t *data, int cnt)
 +{
 +      struct qla_work_evt *e;
 +
 +      e = qla2x00_alloc_work(vha, QLA_EVT_AENFX);
 +      if (!e)
 +              return QLA_FUNCTION_FAILED;
 +
 +      e->u.aenfx.evtcode = evtcode;
 +      e->u.aenfx.count = cnt;
 +      memcpy(e->u.aenfx.mbx, data, sizeof(*data) * cnt);
 +      return qla2x00_post_work(vha, e);
 +}
 +
  void
  qla2x00_do_work(struct scsi_qla_host *vha)
  {
                case QLA_EVT_UEVENT:
                        qla2x00_uevent_emit(vha, e->u.uevent.code);
                        break;
 +              case QLA_EVT_AENFX:
 +                      qlafx00_process_aen(vha, e);
 +                      break;
                }
                if (e->flags & QLA_EVT_FLAG_FREE)
                        kfree(e);
@@@ -4737,38 -4592,6 +4737,38 @@@ qla2x00_do_dpc(void *data
                                ql_dbg(ql_dbg_dpc, base_vha, 0x4006,
                                    "FCoE context reset end.\n");
                        }
 +              } else if (IS_QLAFX00(ha)) {
 +                      if (test_and_clear_bit(ISP_UNRECOVERABLE,
 +                              &base_vha->dpc_flags)) {
 +                              ql_dbg(ql_dbg_dpc, base_vha, 0x4020,
 +                                  "Firmware Reset Recovery\n");
 +                              if (qlafx00_reset_initialize(base_vha)) {
 +                                      /* Failed. Abort isp later. */
 +                                      if (!test_bit(UNLOADING,
 +                                          &base_vha->dpc_flags))
 +                                              set_bit(ISP_UNRECOVERABLE,
 +                                                  &base_vha->dpc_flags);
 +                                              ql_dbg(ql_dbg_dpc, base_vha,
 +                                                  0x4021,
 +                                                  "Reset Recovery Failed\n");
 +                              }
 +                      }
 +
 +                      if (test_and_clear_bit(FX00_TARGET_SCAN,
 +                              &base_vha->dpc_flags)) {
 +                              ql_dbg(ql_dbg_dpc, base_vha, 0x4022,
 +                                  "ISPFx00 Target Scan scheduled\n");
 +                              if (qlafx00_rescan_isp(base_vha)) {
 +                                      if (!test_bit(UNLOADING,
 +                                          &base_vha->dpc_flags))
 +                                              set_bit(ISP_UNRECOVERABLE,
 +                                                  &base_vha->dpc_flags);
 +                                      ql_dbg(ql_dbg_dpc, base_vha, 0x401e,
 +                                          "ISPFx00 Target Scan Failed\n");
 +                              }
 +                              ql_dbg(ql_dbg_dpc, base_vha, 0x401f,
 +                                  "ISPFx00 Target Scan End\n");
 +                      }
                }
  
                if (test_and_clear_bit(ISP_ABORT_NEEDED,
                        clear_bit(SCR_PENDING, &base_vha->dpc_flags);
                }
  
 +              if (IS_QLAFX00(ha))
 +                      goto loop_resync_check;
 +
                if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) {
                        ql_dbg(ql_dbg_dpc, base_vha, 0x4009,
                            "Quiescence mode scheduled.\n");
                }
  
                if (test_and_clear_bit(RESET_MARKER_NEEDED,
 -                                                      &base_vha->dpc_flags) &&
 +                              &base_vha->dpc_flags) &&
                    (!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) {
  
                        ql_dbg(ql_dbg_dpc, base_vha, 0x400b,
                        ql_dbg(ql_dbg_dpc, base_vha, 0x400e,
                            "Relogin end.\n");
                }
 -
 +loop_resync_check:
                if (test_and_clear_bit(LOOP_RESYNC_NEEDED,
 -                                                      &base_vha->dpc_flags)) {
 +                  &base_vha->dpc_flags)) {
  
                        ql_dbg(ql_dbg_dpc, base_vha, 0x400f,
                            "Loop resync scheduled.\n");
                            "Loop resync end.\n");
                }
  
 +              if (IS_QLAFX00(ha))
 +                      goto intr_on_check;
 +
                if (test_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags) &&
                    atomic_read(&base_vha->loop_state) == LOOP_READY) {
                        clear_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags);
                if (test_and_clear_bit(HOST_RAMP_UP_QUEUE_DEPTH,
                    &base_vha->dpc_flags))
                        qla2x00_host_ramp_up_queuedepth(base_vha);
 -
 +intr_on_check:
                if (!ha->interrupts_on)
                        ha->isp_ops->enable_intrs(ha);
  
                                        &base_vha->dpc_flags))
                        ha->isp_ops->beacon_blink(base_vha);
  
 -              qla2x00_do_dpc_all_vps(base_vha);
 +              if (!IS_QLAFX00(ha))
 +                      qla2x00_do_dpc_all_vps(base_vha);
  
                ha->dpc_active = 0;
  end_loop:
@@@ -5002,9 -4818,6 +5002,9 @@@ qla2x00_timer(scsi_qla_host_t *vha
                qla82xx_watchdog(vha);
        }
  
 +      if (!vha->vp_idx && IS_QLAFX00(ha))
 +              qlafx00_timer_routine(vha);
 +
        /* Loop down handler. */
        if (atomic_read(&vha->loop_down_timer) > 0 &&
            !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) &&
@@@ -5522,7 -5335,6 +5522,7 @@@ static struct pci_device_id qla2xxx_pci
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) },
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8021) },
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8031) },
 +      { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISPF001) },
        { 0 },
  };
  MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
@@@ -5539,7 -5351,7 +5539,7 @@@ static struct pci_driver qla2xxx_pci_dr
        .err_handler    = &qla2xxx_err_handler,
  };
  
- static struct file_operations apidev_fops = {
+ static const struct file_operations apidev_fops = {
        .owner = THIS_MODULE,
        .llseek = noop_llseek,
  };
index 5520d6539f77256c67f7cfbf1c0afd8b92bc1c43,33742ba13779bc0d539f35ced50c92efb67b3585..bdc25236ab008e8b21e43e071bf09a616bf212eb
@@@ -1815,7 -1815,7 +1815,7 @@@ udi_log_event(ul_client_t *pcli
      }
  
      /* Allocate log structure plus actual signal. */
 -    logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL);
 +    logptr = kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL);
  
      if (logptr == NULL) {
          printk(KERN_ERR
@@@ -1890,7 -1890,7 +1890,7 @@@ uf_sme_queue_message(unifi_priv_t *priv
      }
  
      /* Allocate log structure plus actual signal. */
 -    logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + length, GFP_ATOMIC);
 +    logptr = kmalloc(sizeof(udi_log_t) + length, GFP_ATOMIC);
      if (logptr == NULL) {
          unifi_error(priv, "Failed to allocate %d bytes for an SME message\n",
                      sizeof(udi_log_t) + length);
   *
   ****************************************************************************
   */
- static struct file_operations unifi_fops = {
+ static const struct file_operations unifi_fops = {
      .owner      = THIS_MODULE,
      .open       = unifi_open,
      .release    = unifi_release,
@@@ -2041,7 -2041,7 +2041,7 @@@ void uf_destroy_device_nodes(unifi_priv
   * ----------------------------------------------------------------
   */
  static int
- uf_create_debug_device(struct file_operations *fops)
+ uf_create_debug_device(const struct file_operations *fops)
  {
      int ret;
  
index 2832b8e26c4b65c59043cb1249d5941fb65c1dac,076dd6bc5ac40157130ac3c9030f8d3775433cb8..23aba6c4d22c77c02e941d3918261882dc51a40a
@@@ -49,24 -49,24 +49,24 @@@ extern struct dgrp_poll_data dgrp_poll_
  extern void dgrp_poll_handler(unsigned long arg);
  
  /* from dgrp_mon_ops.c */
- extern void dgrp_register_mon_hook(struct proc_dir_entry *de);
+ extern const struct file_operations dgrp_mon_ops;
  
  /* from dgrp_tty.c */
  extern int dgrp_tty_init(struct nd_struct *nd);
  extern void dgrp_tty_uninit(struct nd_struct *nd);
  
  /* from dgrp_ports_ops.c */
- extern void dgrp_register_ports_hook(struct proc_dir_entry *de);
+ extern const struct file_operations dgrp_ports_ops;
  
  /* from dgrp_net_ops.c */
- extern void dgrp_register_net_hook(struct proc_dir_entry *de);
+ extern const struct file_operations dgrp_net_ops;
  
  /* from dgrp_dpa_ops.c */
- extern void dgrp_register_dpa_hook(struct proc_dir_entry *de);
+ extern const struct file_operations dgrp_dpa_ops;
  extern void dgrp_dpa_data(struct nd_struct *, int, u8 *, int);
  
  /* from dgrp_sysfs.c */
 -extern void dgrp_create_class_sysfs_files(void);
 +extern int dgrp_create_class_sysfs_files(void);
  extern void dgrp_remove_class_sysfs_files(void);
  
  extern void dgrp_create_node_class_sysfs_files(struct nd_struct *nd);
@@@ -76,61 -76,6 +76,6 @@@ extern void dgrp_create_tty_sysfs(struc
  extern void dgrp_remove_tty_sysfs(struct device *c);
  
  /* from dgrp_specproc.c */
- /*
-  *  The list of DGRP entries with r/w capabilities.  These
-  *  magic numbers are used for identification purposes.
-  */
- enum {
-       DGRP_CONFIG = 1,        /* Configure portservers */
-       DGRP_NETDIR = 2,        /* Directory for "net" devices */
-       DGRP_MONDIR = 3,        /* Directory for "mon" devices */
-       DGRP_PORTSDIR = 4,      /* Directory for "ports" devices */
-       DGRP_INFO = 5,          /* Get info. about the running module */
-       DGRP_NODEINFO = 6,      /* Get info. about the configured nodes */
-       DGRP_DPADIR = 7,        /* Directory for the "dpa" devices */
- };
- /*
-  *  Directions for proc handlers
-  */
- enum {
-       INBOUND = 1,            /* Data being written to kernel */
-       OUTBOUND = 2,           /* Data being read from the kernel */
- };
- /**
-  * dgrp_proc_entry: structure for dgrp proc dirs
-  * @id: ID number associated with this particular entry.  Should be
-  *    unique across all of DGRP.
-  * @name: text name associated with the /proc entry
-  * @mode: file access permisssions for the /proc entry
-  * @child: pointer to table describing a subdirectory for this entry
-  * @de: pointer to directory entry for this object once registered.  Used
-  *    to grab the handle of the object for unregistration
-  * @excl_sem: semaphore to provide exclusive to struct
-  * @excl_cnt: counter of current accesses
-  *
-  *  Each entry in a DGRP proc directory is described with a
-  *  dgrp_proc_entry structure.  A collection of these
-  *  entries (in an array) represents the members associated
-  *  with a particular /proc directory, and is referred to
-  *  as a table.  All tables are terminated by an entry with
-  *  zeros for every member.
-  */
- struct dgrp_proc_entry {
-       int                  id;          /* Integer identifier */
-       const char        *name;          /* ASCII identifier */
-       mode_t             mode;          /* File access permissions */
-       struct dgrp_proc_entry *child;    /* Child pointer */
-       /* file ops to use, pass NULL to use default */
-       struct file_operations *proc_file_ops;
-       struct proc_dir_entry *de;        /* proc entry pointer */
-       struct semaphore   excl_sem;      /* Protects exclusive access var */
-       int                excl_cnt;      /* Counts number of curr accesses */
- };
  extern void dgrp_unregister_proc(void);
  extern void dgrp_register_proc(void);
  
   *-----------------------------------------------------------------------*/
  
  void dgrp_carrier(struct ch_struct *ch);
- extern int dgrp_inode_permission(struct inode *inode, int op);
- extern int dgrp_chk_perm(int mode, int op);
  
  
  /*
index ca10a3362e299206c762e5f19b9eaa17c09a2279,1fc13de4bdd699a6a38dec3146d8ee749395da62..114799cddd85659899c092117cf95050e005f652
@@@ -40,6 -40,7 +40,7 @@@
  #include <linux/cred.h>
  #include <linux/sched.h>
  #include <linux/ratelimit.h>
+ #include <linux/slab.h>
  #include <asm/unaligned.h>
  
  #include "dgrp_common.h"
@@@ -52,7 -53,7 +53,7 @@@ static long dgrp_dpa_ioctl(struct file 
                           unsigned long arg);
  static unsigned int dgrp_dpa_select(struct file *, struct poll_table_struct *);
  
static const struct file_operations dpa_ops = {
const struct file_operations dgrp_dpa_ops = {
        .owner   =  THIS_MODULE,
        .read    =  dgrp_dpa_read,
        .poll    =  dgrp_dpa_select,
        .release =  dgrp_dpa_release,
  };
  
- static struct inode_operations dpa_inode_ops = {
-       .permission = dgrp_inode_permission
- };
  struct digi_node {
        uint    nd_state;               /* Node state: 1 = up, 0 = down. */
        uint    nd_chan_count;          /* Number of channels found */
@@@ -111,17 -106,6 +106,6 @@@ struct digi_debug 
  #define DIGI_SETDEBUG      (('d'<<8) | 247)   /* set debug info */
  
  
- void dgrp_register_dpa_hook(struct proc_dir_entry *de)
- {
-       struct nd_struct *node = de->data;
-       de->proc_iops = &dpa_inode_ops;
-       rcu_assign_pointer(de->proc_fops, &dpa_ops);
-       node->nd_dpa_de = de;
-       spin_lock_init(&node->nd_dpa_lock);
- }
  /*
   * dgrp_dpa_open -- open the DPA device for a particular PortServer
   */
@@@ -130,8 -114,6 +114,6 @@@ static int dgrp_dpa_open(struct inode *
        struct nd_struct *nd;
        int rtn = 0;
  
-       struct proc_dir_entry *de;
        rtn = try_module_get(THIS_MODULE);
        if (!rtn)
                return -ENXIO;
        /*
         *  Get the node pointer, and fail if it doesn't exist.
         */
-       de = PDE(inode);
-       if (!de) {
-               rtn = -ENXIO;
-               goto done;
-       }
-       nd = (struct nd_struct *)de->data;
+       nd = PDE_DATA(inode);
        if (!nd) {
                rtn = -ENXIO;
                goto done;
@@@ -432,7 -409,6 +409,7 @@@ static long dgrp_dpa_ioctl(struct file 
  
  
        case DIGI_GETVPD:
 +              memset(&vpd, 0, sizeof(vpd));
                if (nd->nd_vpd_len > 0) {
                        vpd.vpd_len = nd->nd_vpd_len;
                        memcpy(&vpd.vpd_data, &nd->nd_vpd, nd->nd_vpd_len);
index 64f48ffb9d4e70a7f89f2d13d8ff8214f247708e,9914f1c5bcd36011e1874e52a16812858988544a..5b7833f593ff7a8909ca74a7a10a43d638626004
@@@ -35,7 -35,7 +35,7 @@@
  
  #include <linux/module.h>
  #include <linux/proc_fs.h>
- #include <linux/types.h>
+ #include <linux/slab.h>
  #include <linux/string.h>
  #include <linux/device.h>
  #include <linux/tty.h>
@@@ -72,7 -72,7 +72,7 @@@ static long dgrp_net_ioctl(struct file 
  static unsigned int dgrp_net_select(struct file *file,
                                    struct poll_table_struct *table);
  
static const struct file_operations net_ops = {
const struct file_operations dgrp_net_ops = {
        .owner   =  THIS_MODULE,
        .read    =  dgrp_net_read,
        .write   =  dgrp_net_write,
        .release =  dgrp_net_release,
  };
  
- static struct inode_operations net_inode_ops = {
-       .permission = dgrp_inode_permission
- };
- void dgrp_register_net_hook(struct proc_dir_entry *de)
- {
-       struct nd_struct *node = de->data;
-       de->proc_iops = &net_inode_ops;
-       rcu_assign_pointer(de->proc_fops, &net_ops);
-       node->nd_net_de = de;
-       sema_init(&node->nd_net_semaphore, 1);
-       node->nd_state = NS_CLOSED;
-       dgrp_create_node_class_sysfs_files(node);
- }
  /**
   * dgrp_dump() -- prints memory for debugging purposes.
   * @mem: Memory location which should be printed to the console
@@@ -801,7 -784,6 +784,6 @@@ out_err
  static int dgrp_net_open(struct inode *inode, struct file *file)
  {
        struct nd_struct *nd;
-       struct proc_dir_entry *de;
        ulong  lock_flags;
        int rtn;
  
        /*
         *  Get the node pointer, and fail if it doesn't exist.
         */
-       de = PDE(inode);
-       if (!de) {
-               rtn = -ENXIO;
-               goto done;
-       }
-       nd = (struct nd_struct *) de->data;
+       nd = PDE_DATA(inode);
        if (!nd) {
                rtn = -ENXIO;
                goto done;
@@@ -3405,7 -3381,7 +3381,7 @@@ static long dgrp_net_ioctl(struct file 
                if (size != sizeof(struct link_struct))
                        return -EINVAL;
  
 -              if (copy_from_user((void *)(&link), (void __user *) arg, size))
 +              if (copy_from_user(&link, (void __user *)arg, size))
                        return -EFAULT;
  
                if (link.lk_fast_rate < 9600)
index b58f1dfe006df46aaacec6bb8d59c72855e1a000,2ac3fe647ee60ca87da4e8381485876bbb66e266..61087054640676ba8b734dda3aa5570f81ae61bb
@@@ -1968,18 -1968,16 +1968,16 @@@ int slave_configure(struct scsi_device 
  
  /* we use this macro to help us write into the buffer */
  #undef SPRINTF
- #define SPRINTF(args...) \
-       do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
+ #define SPRINTF(args...) seq_printf(m, ##args)
  
- int proc_info(struct Scsi_Host *host, char *buffer,
-             char **start, off_t offset, int length, int inout)
+ static int write_info(struct Scsi_Host *host, char *buffer, int length)
  {
-       char *pos = buffer;
        /* if someone is sending us data, just throw it away */
-       if (inout)
-               return length;
+       return length;
+ }
  
+ static int show_info(struct seq_file *m, struct Scsi_Host *host)
+ {
        /* print the controller name */
        SPRINTF("   Host scsi%d: %s\n", host->host_no, RTS51X_NAME);
  
        SPRINTF("      Product: RTS51xx USB Card Reader\n");
        SPRINTF("      Version: %s\n", DRIVER_VERSION);
        SPRINTF("        Build: %s\n", __TIME__);
-       /*
-        * Calculate start of next buffer, and return value.
-        */
-       *start = buffer + offset;
-       if ((pos - buffer) < offset)
-               return 0;
-       else if ((pos - buffer - offset) < length)
-               return pos - buffer - offset;
-       else
-               return length;
+       return 0;
  }
  
  /* queue a command */
@@@ -2072,7 -2059,7 +2059,7 @@@ int command_abort(struct scsi_cmnd *srb
  
  /* This invokes the transport reset mechanism to reset the state of the
   * device */
 -int device_reset(struct scsi_cmnd *srb)
 +static int device_reset(struct scsi_cmnd *srb)
  {
        int result = 0;
  
@@@ -2100,7 -2087,8 +2087,8 @@@ struct scsi_host_template rts51x_host_t
        /* basic userland interface stuff */
        .name = RTS51X_NAME,
        .proc_name = RTS51X_NAME,
-       .proc_info = proc_info,
+       .show_info = show_info,
+       .write_info = write_info,
        .info = rts5139_info,
  
        /* command interface -- queued only */
index 3a5213611d21e745cb6b718a3f752fb060658ec6,c2446d02d328a6846b5b35395c609f972d027ae4..1a0d705661863558bb86a87509ca116ad23097db
@@@ -147,10 -147,9 +147,8 @@@ struct scsi_cmnd
  
  int slave_alloc(struct scsi_device *sdev);
  int slave_configure(struct scsi_device *sdev);
- int proc_info(struct Scsi_Host *host, char *buffer,
-             char **start, off_t offset, int length, int inout);
  int queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
  int command_abort(struct scsi_cmnd *srb);
 -int device_reset(struct scsi_cmnd *srb);
  int bus_reset(struct scsi_cmnd *srb);
  
  #endif /* __RTS51X_SCSI_H */
index 0000000000000000000000000000000000000000,3117559c041b25111380276d66653a2732371e88..b7e570ccb759dd4514a17206238b87dbe0299282
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,7909 +1,7907 @@@
 -/*    spin_unlock_irqrestore(&bpvm_lock, flags);        
+ /******************************************************************************/
+ /*                                                                            */
+ /* Bypass Control utility, Copyright (c) 2005-20011 Silicom                   */
+ /*                                                                            */
+ /* 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, located in the file LICENSE.                 */
+ /*  Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.          */
+ /*                                                                            */
+ /*                                                                            */
+ /******************************************************************************/
+ #include <linux/kernel.h>     /* We're doing kernel work */
+ #include <linux/module.h>     /* Specifically, a module */
+ #include <linux/fs.h>
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+ #include <linux/netdevice.h>
+ #include <linux/rtnetlink.h>
+ #include <linux/rcupdate.h>
+ #include <linux/etherdevice.h>
+ #include <linux/uaccess.h>    /* for get_user and put_user */
+ #include <linux/sched.h>
+ #include <linux/ethtool.h>
+ #include <linux/proc_fs.h>
+ #include "bp_ioctl.h"
+ #include "bp_mod.h"
+ #include "bypass.h"
+ #include "libbp_sd.h"
+ #define SUCCESS 0
+ #define BP_MOD_VER  "9.0.4"
+ #define BP_MOD_DESCR "Silicom Bypass-SD Control driver"
+ #define BP_SYNC_FLAG 1
+ static int major_num = 0;
+ MODULE_AUTHOR("Anna Lukin, annal@silicom.co.il");
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION(BP_MOD_DESCR);
+ MODULE_VERSION(BP_MOD_VER);
+ spinlock_t bpvm_lock;
+ #define lock_bpctl()                                  \
+ if (down_interruptible(&bpctl_sema)) {                        \
+       return -ERESTARTSYS;                            \
+ }                                                     \
+ #define unlock_bpctl()                                        \
+       up(&bpctl_sema);
+ /* Media Types */
+ typedef enum {
+       bp_copper = 0,
+       bp_fiber,
+       bp_cx4,
+       bp_none,
+ } bp_media_type;
+ struct bypass_pfs_sd {
+       char dir_name[32];
+       struct proc_dir_entry *bypass_entry;
+ };
+ typedef struct _bpctl_dev {
+       char *name;
+       char *desc;
+       struct pci_dev *pdev;   /* PCI device */
+       struct net_device *ndev;        /* net device */
+       unsigned long mem_map;
+       uint8_t bus;
+       uint8_t slot;
+       uint8_t func;
+       u_int32_t device;
+       u_int32_t vendor;
+       u_int32_t subvendor;
+       u_int32_t subdevice;
+       int ifindex;
+       uint32_t bp_caps;
+       uint32_t bp_caps_ex;
+       uint8_t bp_fw_ver;
+       int bp_ext_ver;
+       int wdt_status;
+       unsigned long bypass_wdt_on_time;
+       uint32_t bypass_timer_interval;
+       struct timer_list bp_timer;
+       uint32_t reset_time;
+       uint8_t bp_status_un;
+       atomic_t wdt_busy;
+       bp_media_type media_type;
+       int bp_tpl_flag;
+       struct timer_list bp_tpl_timer;
+       spinlock_t bypass_wr_lock;
+       int bp_10g;
+       int bp_10gb;
+       int bp_fiber5;
+       int bp_10g9;
+       int bp_i80;
+       int bp_540;
+       int (*hard_start_xmit_save) (struct sk_buff *skb,
+                                    struct net_device *dev);
+       const struct net_device_ops *old_ops;
+       struct net_device_ops new_ops;
+       int bp_self_test_flag;
+       char *bp_tx_data;
+       struct bypass_pfs_sd bypass_pfs_set;
+ } bpctl_dev_t;
+ static bpctl_dev_t *bpctl_dev_arr;
+ static struct semaphore bpctl_sema;
+ static int device_num = 0;
+ static int get_dev_idx(int ifindex);
+ static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev);
+ static int disc_status(bpctl_dev_t *pbpctl_dev);
+ static int bypass_status(bpctl_dev_t *pbpctl_dev);
+ static int wdt_timer(bpctl_dev_t *pbpctl_dev, int *time_left);
+ static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev);
+ static void if_scan_init(void);
+ int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block);
+ int bypass_proc_remove_dev_sd(bpctl_dev_t *pbp_device_block);
+ int bp_proc_create(void);
+ int is_bypass_fn(bpctl_dev_t *pbpctl_dev);
+ int get_dev_idx_bsf(int bus, int slot, int func);
+ static unsigned long str_to_hex(char *p);
+ static int bp_device_event(struct notifier_block *unused,
+                          unsigned long event, void *ptr)
+ {
+       struct net_device *dev = ptr;
+       static bpctl_dev_t *pbpctl_dev = NULL, *pbpctl_dev_m = NULL;
+       int dev_num = 0, ret = 0, ret_d = 0, time_left = 0;
+       /* printk("BP_PROC_SUPPORT event =%d %s %d\n", event,dev->name, dev->ifindex ); */
+       /* return NOTIFY_DONE; */
+       if (!dev)
+               return NOTIFY_DONE;
+       if (event == NETDEV_REGISTER) {
+               {
+                       struct ethtool_drvinfo drvinfo;
+                       char cbuf[32];
+                       char *buf = NULL;
+                       char res[10];
+                       int i = 0, ifindex, idx_dev = 0;
+                       int bus = 0, slot = 0, func = 0;
+                       ifindex = dev->ifindex;
+                       memset(res, 0, 10);
+                       memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo));
+                       if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo) {
+                               memset(&drvinfo, 0, sizeof(drvinfo));
+                               dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
+                       } else
+                               return NOTIFY_DONE;
+                       if (!drvinfo.bus_info)
+                               return NOTIFY_DONE;
+                       if (!strcmp(drvinfo.bus_info, "N/A"))
+                               return NOTIFY_DONE;
+                       memcpy(&cbuf, drvinfo.bus_info, 32);
+                       buf = &cbuf[0];
+                       while (*buf++ != ':') ;
+                       for (i = 0; i < 10; i++, buf++) {
+                               if (*buf == ':')
+                                       break;
+                               res[i] = *buf;
+                       }
+                       buf++;
+                       bus = str_to_hex(res);
+                       memset(res, 0, 10);
+                       for (i = 0; i < 10; i++, buf++) {
+                               if (*buf == '.')
+                                       break;
+                               res[i] = *buf;
+                       }
+                       buf++;
+                       slot = str_to_hex(res);
+                       func = str_to_hex(buf);
+                       idx_dev = get_dev_idx_bsf(bus, slot, func);
+                       if (idx_dev != -1) {
+                               bpctl_dev_arr[idx_dev].ifindex = ifindex;
+                               bpctl_dev_arr[idx_dev].ndev = dev;
+                               bypass_proc_remove_dev_sd(&bpctl_dev_arr
+                                                         [idx_dev]);
+                               bypass_proc_create_dev_sd(&bpctl_dev_arr
+                                                         [idx_dev]);
+                       }
+               }
+               return NOTIFY_DONE;
+       }
+       if (event == NETDEV_UNREGISTER) {
+               int idx_dev = 0;
+               for (idx_dev = 0;
+                    ((bpctl_dev_arr[idx_dev].pdev != NULL)
+                     && (idx_dev < device_num)); idx_dev++) {
+                       if (bpctl_dev_arr[idx_dev].ndev == dev) {
+                               bypass_proc_remove_dev_sd(&bpctl_dev_arr
+                                                         [idx_dev]);
+                               bpctl_dev_arr[idx_dev].ndev = NULL;
+                               return NOTIFY_DONE;
+                       }
+               }
+               return NOTIFY_DONE;
+       }
+       if (event == NETDEV_CHANGENAME) {
+               int idx_dev = 0;
+               for (idx_dev = 0;
+                    ((bpctl_dev_arr[idx_dev].pdev != NULL)
+                     && (idx_dev < device_num)); idx_dev++) {
+                       if (bpctl_dev_arr[idx_dev].ndev == dev) {
+                               bypass_proc_remove_dev_sd(&bpctl_dev_arr
+                                                         [idx_dev]);
+                               bypass_proc_create_dev_sd(&bpctl_dev_arr
+                                                         [idx_dev]);
+                               return NOTIFY_DONE;
+                       }
+               }
+               return NOTIFY_DONE;
+       }
+       switch (event) {
+       case NETDEV_CHANGE:{
+                       if (netif_carrier_ok(dev))
+                               return NOTIFY_DONE;
+                       if (((dev_num = get_dev_idx(dev->ifindex)) == -1) ||
+                           (!(pbpctl_dev = &bpctl_dev_arr[dev_num])))
+                               return NOTIFY_DONE;
+                       if ((is_bypass_fn(pbpctl_dev)) == 1)
+                               pbpctl_dev_m = pbpctl_dev;
+                       else
+                               pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
+                       if (!pbpctl_dev_m)
+                               return NOTIFY_DONE;
+                       ret = bypass_status(pbpctl_dev_m);
+                       if (ret == 1)
+                               printk("bpmod: %s is in the Bypass mode now",
+                                      dev->name);
+                       ret_d = disc_status(pbpctl_dev_m);
+                       if (ret_d == 1)
+                               printk
+                                   ("bpmod: %s is in the Disconnect mode now",
+                                    dev->name);
+                       if (ret || ret_d) {
+                               wdt_timer(pbpctl_dev_m, &time_left);
+                               if (time_left == -1)
+                                       printk("; WDT has expired");
+                               printk(".\n");
+                       }
+                       return NOTIFY_DONE;
+               }
+       default:
+               return NOTIFY_DONE;
+       }
+       return NOTIFY_DONE;
+ }
+ static struct notifier_block bp_notifier_block = {
+       .notifier_call = bp_device_event,
+ };
+ int is_bypass_fn(bpctl_dev_t *pbpctl_dev);
+ int wdt_time_left(bpctl_dev_t *pbpctl_dev);
+ static void write_pulse(bpctl_dev_t *pbpctl_dev,
+                       unsigned int ctrl_ext,
+                       unsigned char value, unsigned char len)
+ {
+       unsigned char ctrl_val = 0;
+       unsigned int i = len;
+       unsigned int ctrl = 0;
+       bpctl_dev_t *pbpctl_dev_c = NULL;
+       if (pbpctl_dev->bp_i80)
+               ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+       if (pbpctl_dev->bp_540)
+               ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+       if (pbpctl_dev->bp_10g9) {
+               if (!(pbpctl_dev_c = get_status_port_fn(pbpctl_dev)))
+                       return;
+               ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP);
+       }
+       while (i--) {
+               ctrl_val = (value >> i) & 0x1;
+               if (ctrl_val) {
+                       if (pbpctl_dev->bp_10g9) {
+                               /* To start management : MCLK 1, MDIO 1, output */
+                               /* DATA 1 CLK 1 */
+                               /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext|BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9)); */
+                               BP10G_WRITE_REG(pbpctl_dev, I2CCTL,
+                                               ctrl_ext |
+                                               BP10G_MDIO_DATA_OUT9);
+                               BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                                               (ctrl | BP10G_MCLK_DATA_OUT9 |
+                                                BP10G_MCLK_DIR_OUT9));
+                       } else if (pbpctl_dev->bp_fiber5) {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, (ctrl_ext |
+                                                                     BPCTLI_CTRL_EXT_MCLK_DIR5
+                                                                     |
+                                                                     BPCTLI_CTRL_EXT_MDIO_DIR5
+                                                                     |
+                                                                     BPCTLI_CTRL_EXT_MDIO_DATA5
+                                                                     |
+                                                                     BPCTLI_CTRL_EXT_MCLK_DATA5));
+                       } else if (pbpctl_dev->bp_i80) {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, (ctrl_ext |
+                                                                     BPCTLI_CTRL_EXT_MDIO_DIR80
+                                                                     |
+                                                                     BPCTLI_CTRL_EXT_MDIO_DATA80));
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, (ctrl |
+                                                                         BPCTLI_CTRL_EXT_MCLK_DIR80
+                                                                         |
+                                                                         BPCTLI_CTRL_EXT_MCLK_DATA80));
+                       } else if (pbpctl_dev->bp_540) {
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP, (ctrl |
+                                                                  BP540_MDIO_DIR
+                                                                  |
+                                                                  BP540_MDIO_DATA
+                                                                  |
+                                                                  BP540_MCLK_DIR
+                                                                  |
+                                                                  BP540_MCLK_DATA));
+                       } else if (pbpctl_dev->bp_10gb) {
+                               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                                (ctrl_ext | BP10GB_MDIO_SET |
+                                                 BP10GB_MCLK_SET) &
+                                                ~(BP10GB_MCLK_DIR |
+                                                  BP10GB_MDIO_DIR |
+                                                  BP10GB_MDIO_CLR |
+                                                  BP10GB_MCLK_CLR));
+                       } else if (!pbpctl_dev->bp_10g)
+                               /* To start management : MCLK 1, MDIO 1, output */
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                                  (ctrl_ext |
+                                                   BPCTLI_CTRL_EXT_MCLK_DIR |
+                                                   BPCTLI_CTRL_EXT_MDIO_DIR |
+                                                   BPCTLI_CTRL_EXT_MDIO_DATA |
+                                                   BPCTLI_CTRL_EXT_MCLK_DATA));
+                       else {
+                               /* To start management : MCLK 1, MDIO 1, output*/
+                               BP10G_WRITE_REG(pbpctl_dev, EODSDP,
+                                               (ctrl_ext | BP10G_MCLK_DATA_OUT
+                                                | BP10G_MDIO_DATA_OUT));
+                       }
+                       usec_delay(PULSE_TIME);
+                       if (pbpctl_dev->bp_10g9) {
+                               /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, ((ctrl_ext|BP10G_MDIO_DATA_OUT9)&~(BP10G_MCLK_DATA_OUT9))); */
+                               /* DATA 1 CLK 0 */
+                               BP10G_WRITE_REG(pbpctl_dev, I2CCTL,
+                                               ctrl_ext |
+                                               BP10G_MDIO_DATA_OUT9);
+                               BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                                               (ctrl | BP10G_MCLK_DIR_OUT9) &
+                                               ~BP10G_MCLK_DATA_OUT9);
+                       } else if (pbpctl_dev->bp_fiber5) {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                                  ((ctrl_ext |
+                                                    BPCTLI_CTRL_EXT_MCLK_DIR5 |
+                                                    BPCTLI_CTRL_EXT_MDIO_DIR5 |
+                                                    BPCTLI_CTRL_EXT_MDIO_DATA5)
+                                                   &
+                                                   ~
+                                                   (BPCTLI_CTRL_EXT_MCLK_DATA5)));
+                       } else if (pbpctl_dev->bp_i80) {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, (ctrl_ext |
+                                                                     BPCTLI_CTRL_EXT_MDIO_DIR80
+                                                                     |
+                                                                     BPCTLI_CTRL_EXT_MDIO_DATA80));
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                                  ((ctrl |
+                                                    BPCTLI_CTRL_EXT_MCLK_DIR80)
+                                                   &
+                                                   ~
+                                                   (BPCTLI_CTRL_EXT_MCLK_DATA80)));
+                       } else if (pbpctl_dev->bp_540) {
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                               (ctrl | BP540_MDIO_DIR |
+                                                BP540_MDIO_DATA |
+                                                BP540_MCLK_DIR) &
+                                               ~(BP540_MCLK_DATA));
+                       } else if (pbpctl_dev->bp_10gb) {
+                               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                                (ctrl_ext | BP10GB_MDIO_SET |
+                                                 BP10GB_MCLK_CLR) &
+                                                ~(BP10GB_MCLK_DIR |
+                                                  BP10GB_MDIO_DIR |
+                                                  BP10GB_MDIO_CLR |
+                                                  BP10GB_MCLK_SET));
+                       } else if (!pbpctl_dev->bp_10g)
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                                  ((ctrl_ext |
+                                                    BPCTLI_CTRL_EXT_MCLK_DIR |
+                                                    BPCTLI_CTRL_EXT_MDIO_DIR |
+                                                    BPCTLI_CTRL_EXT_MDIO_DATA)
+                                                   &
+                                                   ~
+                                                   (BPCTLI_CTRL_EXT_MCLK_DATA)));
+                       else {
+                               BP10G_WRITE_REG(pbpctl_dev, EODSDP,
+                                               ((ctrl_ext |
+                                                 BP10G_MDIO_DATA_OUT) &
+                                                ~(BP10G_MCLK_DATA_OUT)));
+                       }
+                       usec_delay(PULSE_TIME);
+               } else {
+                       if (pbpctl_dev->bp_10g9) {
+                               /* DATA 0 CLK 1 */
+                               /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, ((ctrl_ext|BP10G_MCLK_DATA_OUT9)&~BP10G_MDIO_DATA_OUT9)); */
+                               BP10G_WRITE_REG(pbpctl_dev, I2CCTL,
+                                               (ctrl_ext &
+                                                ~BP10G_MDIO_DATA_OUT9));
+                               BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                                               (ctrl | BP10G_MCLK_DATA_OUT9 |
+                                                BP10G_MCLK_DIR_OUT9));
+                       } else if (pbpctl_dev->bp_fiber5) {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                                  ((ctrl_ext |
+                                                    BPCTLI_CTRL_EXT_MCLK_DIR5 |
+                                                    BPCTLI_CTRL_EXT_MDIO_DIR5 |
+                                                    BPCTLI_CTRL_EXT_MCLK_DATA5)
+                                                   &
+                                                   ~
+                                                   (BPCTLI_CTRL_EXT_MDIO_DATA5)));
+                       } else if (pbpctl_dev->bp_i80) {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                                  ((ctrl_ext |
+                                                    BPCTLI_CTRL_EXT_MDIO_DIR80)
+                                                   &
+                                                   ~
+                                                   (BPCTLI_CTRL_EXT_MDIO_DATA80)));
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                                  (ctrl |
+                                                   BPCTLI_CTRL_EXT_MCLK_DIR80 |
+                                                   BPCTLI_CTRL_EXT_MCLK_DATA80));
+                       } else if (pbpctl_dev->bp_540) {
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                               ((ctrl | BP540_MCLK_DIR |
+                                                 BP540_MCLK_DATA |
+                                                 BP540_MDIO_DIR) &
+                                                ~(BP540_MDIO_DATA)));
+                       } else if (pbpctl_dev->bp_10gb) {
+                               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                                (ctrl_ext | BP10GB_MDIO_CLR |
+                                                 BP10GB_MCLK_SET) &
+                                                ~(BP10GB_MCLK_DIR |
+                                                  BP10GB_MDIO_DIR |
+                                                  BP10GB_MDIO_SET |
+                                                  BP10GB_MCLK_CLR));
+                       } else if (!pbpctl_dev->bp_10g)
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                                  ((ctrl_ext |
+                                                    BPCTLI_CTRL_EXT_MCLK_DIR |
+                                                    BPCTLI_CTRL_EXT_MDIO_DIR |
+                                                    BPCTLI_CTRL_EXT_MCLK_DATA)
+                                                   &
+                                                   ~
+                                                   (BPCTLI_CTRL_EXT_MDIO_DATA)));
+                       else {
+                               BP10G_WRITE_REG(pbpctl_dev, EODSDP,
+                                               ((ctrl_ext |
+                                                 BP10G_MCLK_DATA_OUT) &
+                                                ~BP10G_MDIO_DATA_OUT));
+                       }
+                       usec_delay(PULSE_TIME);
+                       if (pbpctl_dev->bp_10g9) {
+                               /* DATA 0 CLK 0 */
+                               /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */
+                               BP10G_WRITE_REG(pbpctl_dev, I2CCTL,
+                                               (ctrl_ext &
+                                                ~BP10G_MDIO_DATA_OUT9));
+                               BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                                               ((ctrl | BP10G_MCLK_DIR_OUT9) &
+                                                ~(BP10G_MCLK_DATA_OUT9)));
+                       } else if (pbpctl_dev->bp_fiber5) {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                                  ((ctrl_ext |
+                                                    BPCTLI_CTRL_EXT_MCLK_DIR5 |
+                                                    BPCTLI_CTRL_EXT_MDIO_DIR5)
+                                                   &
+                                                   ~(BPCTLI_CTRL_EXT_MCLK_DATA5
+                                                     |
+                                                     BPCTLI_CTRL_EXT_MDIO_DATA5)));
+                       } else if (pbpctl_dev->bp_i80) {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                                  ((ctrl_ext |
+                                                    BPCTLI_CTRL_EXT_MDIO_DIR80)
+                                                   &
+                                                   ~BPCTLI_CTRL_EXT_MDIO_DATA80));
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                                  ((ctrl |
+                                                    BPCTLI_CTRL_EXT_MCLK_DIR80)
+                                                   &
+                                                   ~
+                                                   (BPCTLI_CTRL_EXT_MCLK_DATA80)));
+                       } else if (pbpctl_dev->bp_540) {
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                               ((ctrl | BP540_MCLK_DIR |
+                                                 BP540_MDIO_DIR) &
+                                                ~(BP540_MDIO_DATA |
+                                                  BP540_MCLK_DATA)));
+                       } else if (pbpctl_dev->bp_10gb) {
+                               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                                (ctrl_ext | BP10GB_MDIO_CLR |
+                                                 BP10GB_MCLK_CLR) &
+                                                ~(BP10GB_MCLK_DIR |
+                                                  BP10GB_MDIO_DIR |
+                                                  BP10GB_MDIO_SET |
+                                                  BP10GB_MCLK_SET));
+                       } else if (!pbpctl_dev->bp_10g)
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                                  ((ctrl_ext |
+                                                    BPCTLI_CTRL_EXT_MCLK_DIR |
+                                                    BPCTLI_CTRL_EXT_MDIO_DIR) &
+                                                   ~(BPCTLI_CTRL_EXT_MCLK_DATA
+                                                     |
+                                                     BPCTLI_CTRL_EXT_MDIO_DATA)));
+                       else {
+                               BP10G_WRITE_REG(pbpctl_dev, EODSDP,
+                                               (ctrl_ext &
+                                                ~(BP10G_MCLK_DATA_OUT |
+                                                  BP10G_MDIO_DATA_OUT)));
+                       }
+                       usec_delay(PULSE_TIME);
+               }
+       }
+ }
+ static int read_pulse(bpctl_dev_t *pbpctl_dev, unsigned int ctrl_ext,
+                     unsigned char len)
+ {
+       unsigned char ctrl_val = 0;
+       unsigned int i = len;
+       unsigned int ctrl = 0;
+       bpctl_dev_t *pbpctl_dev_c = NULL;
+       if (pbpctl_dev->bp_i80)
+               ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+       if (pbpctl_dev->bp_540)
+               ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+       if (pbpctl_dev->bp_10g9) {
+               if (!(pbpctl_dev_c = get_status_port_fn(pbpctl_dev)))
+                       return -1;
+               ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP);
+       }
+       while (i--) {
+               if (pbpctl_dev->bp_10g9) {
+                       /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, ((ctrl_ext|BP10G_MDIO_DATA_OUT9)&~BP10G_MCLK_DATA_OUT9)); */
+                       /* DATA ? CLK 0 */
+                       BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                                       ((ctrl | BP10G_MCLK_DIR_OUT9) &
+                                        ~(BP10G_MCLK_DATA_OUT9)));
+               } else if (pbpctl_dev->bp_fiber5) {
+                       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                              BPCTLI_CTRL_EXT_MCLK_DIR5)
+                                                             &
+                                                             ~
+                                                             (BPCTLI_CTRL_EXT_MDIO_DIR5
+                                                              |
+                                                              BPCTLI_CTRL_EXT_MCLK_DATA5)));
+               } else if (pbpctl_dev->bp_i80) {
+                       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                          (ctrl_ext &
+                                           ~BPCTLI_CTRL_EXT_MDIO_DIR80));
+                       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                          ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80)
+                                           & ~(BPCTLI_CTRL_EXT_MCLK_DATA80)));
+               } else if (pbpctl_dev->bp_540) {
+                       BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                       ((ctrl | BP540_MCLK_DIR) &
+                                        ~(BP540_MDIO_DIR | BP540_MCLK_DATA)));
+               } else if (pbpctl_dev->bp_10gb) {
+                       BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                        (ctrl_ext | BP10GB_MDIO_DIR |
+                                         BP10GB_MCLK_CLR) & ~(BP10GB_MCLK_DIR |
+                                                              BP10GB_MDIO_CLR |
+                                                              BP10GB_MDIO_SET |
+                                                              BP10GB_MCLK_SET));
+               } else if (!pbpctl_dev->bp_10g)
+                       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                                  BPCTLI_CTRL_EXT_MCLK_DIR)
+                                                                 &
+                                                                 ~
+                                                                 (BPCTLI_CTRL_EXT_MDIO_DIR
+                                                                  |
+                                                                  BPCTLI_CTRL_EXT_MCLK_DATA)));
+               else {
+                       BP10G_WRITE_REG(pbpctl_dev, EODSDP, ((ctrl_ext | BP10G_MDIO_DATA_OUT) & ~BP10G_MCLK_DATA_OUT)); /* ? */
+                       /*    printk("0x28=0x%x\n",BP10G_READ_REG(pbpctl_dev,EODSDP);); */
+               }
+               usec_delay(PULSE_TIME);
+               if (pbpctl_dev->bp_10g9) {
+                       /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext|BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9)); */
+                       /* DATA ? CLK 1 */
+                       BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                                       (ctrl | BP10G_MCLK_DATA_OUT9 |
+                                        BP10G_MCLK_DIR_OUT9));
+               } else if (pbpctl_dev->bp_fiber5) {
+                       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                              BPCTLI_CTRL_EXT_MCLK_DIR5
+                                                              |
+                                                              BPCTLI_CTRL_EXT_MCLK_DATA5)
+                                                             &
+                                                             ~
+                                                             (BPCTLI_CTRL_EXT_MDIO_DIR5)));
+               } else if (pbpctl_dev->bp_i80) {
+                       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                          (ctrl_ext &
+                                           ~(BPCTLI_CTRL_EXT_MDIO_DIR80)));
+                       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                          (ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80 |
+                                           BPCTLI_CTRL_EXT_MCLK_DATA80));
+               } else if (pbpctl_dev->bp_540) {
+                       BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                       ((ctrl | BP540_MCLK_DIR |
+                                         BP540_MCLK_DATA) &
+                                        ~(BP540_MDIO_DIR)));
+               } else if (pbpctl_dev->bp_10gb) {
+                       BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                        (ctrl_ext | BP10GB_MDIO_DIR |
+                                         BP10GB_MCLK_SET) & ~(BP10GB_MCLK_DIR |
+                                                              BP10GB_MDIO_CLR |
+                                                              BP10GB_MDIO_SET |
+                                                              BP10GB_MCLK_CLR));
+               } else if (!pbpctl_dev->bp_10g)
+                       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                                  BPCTLI_CTRL_EXT_MCLK_DIR
+                                                                  |
+                                                                  BPCTLI_CTRL_EXT_MCLK_DATA)
+                                                                 &
+                                                                 ~
+                                                                 (BPCTLI_CTRL_EXT_MDIO_DIR)));
+               else {
+                       BP10G_WRITE_REG(pbpctl_dev, EODSDP,
+                                       (ctrl_ext | BP10G_MCLK_DATA_OUT |
+                                        BP10G_MDIO_DATA_OUT));
+               }
+               if (pbpctl_dev->bp_10g9) {
+                       ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL);
+               } else if ((pbpctl_dev->bp_fiber5) || (pbpctl_dev->bp_i80)) {
+                       ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL);
+               } else if (pbpctl_dev->bp_540) {
+                       ctrl_ext = BP10G_READ_REG(pbpctl_dev, ESDP);
+               } else if (pbpctl_dev->bp_10gb)
+                       ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO);
+               else if (!pbpctl_dev->bp_10g)
+                       ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+               else
+                       ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP);
+               usec_delay(PULSE_TIME);
+               if (pbpctl_dev->bp_10g9) {
+                       if (ctrl_ext & BP10G_MDIO_DATA_IN9)
+                               ctrl_val |= 1 << i;
+               } else if (pbpctl_dev->bp_fiber5) {
+                       if (ctrl_ext & BPCTLI_CTRL_EXT_MDIO_DATA5)
+                               ctrl_val |= 1 << i;
+               } else if (pbpctl_dev->bp_i80) {
+                       if (ctrl_ext & BPCTLI_CTRL_EXT_MDIO_DATA80)
+                               ctrl_val |= 1 << i;
+               } else if (pbpctl_dev->bp_540) {
+                       if (ctrl_ext & BP540_MDIO_DATA)
+                               ctrl_val |= 1 << i;
+               } else if (pbpctl_dev->bp_10gb) {
+                       if (ctrl_ext & BP10GB_MDIO_DATA)
+                               ctrl_val |= 1 << i;
+               } else if (!pbpctl_dev->bp_10g) {
+                       if (ctrl_ext & BPCTLI_CTRL_EXT_MDIO_DATA)
+                               ctrl_val |= 1 << i;
+               } else {
+                       if (ctrl_ext & BP10G_MDIO_DATA_IN)
+                               ctrl_val |= 1 << i;
+               }
+       }
+       return ctrl_val;
+ }
+ static void write_reg(bpctl_dev_t *pbpctl_dev, unsigned char value,
+                     unsigned char addr)
+ {
+       uint32_t ctrl_ext = 0, ctrl = 0;
+       bpctl_dev_t *pbpctl_dev_c = NULL;
+       unsigned long flags;
+       if (pbpctl_dev->bp_10g9) {
+               if (!(pbpctl_dev_c = get_status_port_fn(pbpctl_dev)))
+                       return;
+       }
+       if ((pbpctl_dev->wdt_status == WDT_STATUS_EN) &&
+           (pbpctl_dev->bp_ext_ver < PXG4BPFI_VER))
+               wdt_time_left(pbpctl_dev);
+ #ifdef BP_SYNC_FLAG
+       spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags);
+ #else
+       atomic_set(&pbpctl_dev->wdt_busy, 1);
+ #endif
+       if (pbpctl_dev->bp_10g9) {
+               ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL);
+               ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP);
+               /* DATA 0 CLK 0 */
+               /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */
+               BP10G_WRITE_REG(pbpctl_dev, I2CCTL,
+                               (ctrl_ext & ~BP10G_MDIO_DATA_OUT9));
+               BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                               ((ctrl | BP10G_MCLK_DIR_OUT9) &
+                                ~(BP10G_MCLK_DATA_OUT9)));
+       } else if (pbpctl_dev->bp_fiber5) {
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL);
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MCLK_DIR5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR5)
+                                                     &
+                                                     ~
+                                                     (BPCTLI_CTRL_EXT_MDIO_DATA5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MCLK_DATA5)));
+       } else if (pbpctl_dev->bp_i80) {
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL);
+               ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR80)
+                                                     &
+                                                     ~BPCTLI_CTRL_EXT_MDIO_DATA80));
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                  ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) &
+                                   ~BPCTLI_CTRL_EXT_MCLK_DATA80));
+       } else if (pbpctl_dev->bp_540) {
+               ctrl = ctrl_ext = BP10G_READ_REG(pbpctl_dev, ESDP);
+               BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl |
+                                                   BP540_MDIO_DIR |
+                                                   BP540_MCLK_DIR) &
+                                                  ~(BP540_MDIO_DATA |
+                                                    BP540_MCLK_DATA)));
+       } else if (pbpctl_dev->bp_10gb) {
+               ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO);
+               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR)
+                                & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR |
+                                    BP10GB_MDIO_SET | BP10GB_MCLK_SET));
+       } else if (!pbpctl_dev->bp_10g) {
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                          BPCTLI_CTRL_EXT_MCLK_DIR
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MDIO_DIR)
+                                                         &
+                                                         ~
+                                                         (BPCTLI_CTRL_EXT_MDIO_DATA
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MCLK_DATA)));
+       } else {
+               ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+               ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP);
+               BP10G_WRITE_REG(pbpctl_dev, EODSDP,
+                               (ctrl_ext &
+                                ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT)));
+       }
+       usec_delay(CMND_INTERVAL);
+       /*send sync cmd */
+       write_pulse(pbpctl_dev, ctrl_ext, SYNC_CMD_VAL, SYNC_CMD_LEN);
+       /*send wr cmd */
+       write_pulse(pbpctl_dev, ctrl_ext, WR_CMD_VAL, WR_CMD_LEN);
+       write_pulse(pbpctl_dev, ctrl_ext, addr, ADDR_CMD_LEN);
+       /*write data */
+       write_pulse(pbpctl_dev, ctrl_ext, value, WR_DATA_LEN);
+       if (pbpctl_dev->bp_10g9) {
+               /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */
+               /* DATA 0 CLK 0 */
+               BP10G_WRITE_REG(pbpctl_dev, I2CCTL,
+                               (ctrl_ext & ~BP10G_MDIO_DATA_OUT9));
+               BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                               ((ctrl | BP10G_MCLK_DIR_OUT9) &
+                                ~(BP10G_MCLK_DATA_OUT9)));
+       } else if (pbpctl_dev->bp_fiber5) {
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MCLK_DIR5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR5)
+                                                     &
+                                                     ~
+                                                     (BPCTLI_CTRL_EXT_MDIO_DATA5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MCLK_DATA5)));
+       } else if (pbpctl_dev->bp_i80) {
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR80)
+                                                     &
+                                                     ~BPCTLI_CTRL_EXT_MDIO_DATA80));
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                  ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) &
+                                   ~BPCTLI_CTRL_EXT_MCLK_DATA80));
+       } else if (pbpctl_dev->bp_540) {
+               BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl |
+                                                   BP540_MDIO_DIR |
+                                                   BP540_MCLK_DIR) &
+                                                  ~(BP540_MDIO_DATA |
+                                                    BP540_MCLK_DATA)));
+       } else if (pbpctl_dev->bp_10gb) {
+               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR)
+                                & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR |
+                                    BP10GB_MDIO_SET | BP10GB_MCLK_SET));
+       } else if (!pbpctl_dev->bp_10g)
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                          BPCTLI_CTRL_EXT_MCLK_DIR
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MDIO_DIR)
+                                                         &
+                                                         ~
+                                                         (BPCTLI_CTRL_EXT_MDIO_DATA
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MCLK_DATA)));
+       else {
+               BP10G_WRITE_REG(pbpctl_dev, EODSDP,
+                               (ctrl_ext &
+                                ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT)));
+       }
+       usec_delay(CMND_INTERVAL * 4);
+       if ((pbpctl_dev->wdt_status == WDT_STATUS_EN) &&
+           (pbpctl_dev->bp_ext_ver < PXG4BPFI_VER) && (addr == CMND_REG_ADDR))
+               pbpctl_dev->bypass_wdt_on_time = jiffies;
+ #ifdef BP_SYNC_FLAG
+       spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags);
+ #else
+       atomic_set(&pbpctl_dev->wdt_busy, 0);
+ #endif
+ }
+ static void write_data(bpctl_dev_t *pbpctl_dev, unsigned char value)
+ {
+       write_reg(pbpctl_dev, value, CMND_REG_ADDR);
+ }
+ static int read_reg(bpctl_dev_t *pbpctl_dev, unsigned char addr)
+ {
+       uint32_t ctrl_ext = 0, ctrl = 0, ctrl_value = 0;
+       bpctl_dev_t *pbpctl_dev_c = NULL;
+ #ifdef BP_SYNC_FLAG
+       unsigned long flags;
+       spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags);
+ #else
+       atomic_set(&pbpctl_dev->wdt_busy, 1);
+ #endif
+       if (pbpctl_dev->bp_10g9) {
+               if (!(pbpctl_dev_c = get_status_port_fn(pbpctl_dev)))
+                       return -1;
+       }
+       if (pbpctl_dev->bp_10g9) {
+               ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL);
+               ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP);
+               /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */
+               /* DATA 0 CLK 0 */
+               BP10G_WRITE_REG(pbpctl_dev, I2CCTL,
+                               (ctrl_ext & ~BP10G_MDIO_DATA_OUT9));
+               BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                               ((ctrl | BP10G_MCLK_DIR_OUT9) &
+                                ~(BP10G_MCLK_DATA_OUT9)));
+       } else if (pbpctl_dev->bp_fiber5) {
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL);
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MCLK_DIR5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR5)
+                                                     &
+                                                     ~
+                                                     (BPCTLI_CTRL_EXT_MDIO_DATA5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MCLK_DATA5)));
+       } else if (pbpctl_dev->bp_i80) {
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL);
+               ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR80)
+                                                     &
+                                                     ~BPCTLI_CTRL_EXT_MDIO_DATA80));
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                  ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) &
+                                   ~BPCTLI_CTRL_EXT_MCLK_DATA80));
+       } else if (pbpctl_dev->bp_540) {
+               ctrl_ext = BP10G_READ_REG(pbpctl_dev, ESDP);
+               ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+               BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | BP540_MCLK_DIR |
+                                                   BP540_MDIO_DIR) &
+                                                  ~(BP540_MDIO_DATA |
+                                                    BP540_MCLK_DATA)));
+       } else if (pbpctl_dev->bp_10gb) {
+               ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO);
+               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR)
+                                & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR |
+                                    BP10GB_MDIO_SET | BP10GB_MCLK_SET));
+ #if 0
+               /*BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, (ctrl_ext | BP10GB_MCLK_DIR | BP10GB_MDIO_DIR|
+                  BP10GB_MCLK_CLR|BP10GB_MDIO_CLR));
+                  ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO);
+                  printk("1reg=%x\n", ctrl_ext); */
+               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, ((ctrl_ext |
+                                                             BP10GB_MCLK_SET |
+                                                             BP10GB_MDIO_CLR))
+                                & ~(BP10GB_MCLK_CLR | BP10GB_MDIO_SET |
+                                    BP10GB_MCLK_DIR | BP10GB_MDIO_DIR));
+               /*   bnx2x_set_spio(pbpctl_dev, 5, MISC_REGISTERS_SPIO_OUTPUT_LOW);
+                  bnx2x_set_spio(pbpctl_dev, 4, MISC_REGISTERS_SPIO_OUTPUT_LOW);
+                  bnx2x_set_spio(pbpctl_dev, 4, MISC_REGISTERS_SPIO_INPUT_HI_Z); */
+               ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO);
+               printk("2reg=%x\n", ctrl_ext);
+ #ifdef BP_SYNC_FLAG
+               spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags);
+ #else
+               atomic_set(&pbpctl_dev->wdt_busy, 0);
+ #endif
+               return 0;
+ #endif
+       } else if (!pbpctl_dev->bp_10g) {
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                          BPCTLI_CTRL_EXT_MCLK_DIR
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MDIO_DIR)
+                                                         &
+                                                         ~
+                                                         (BPCTLI_CTRL_EXT_MDIO_DATA
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MCLK_DATA)));
+       } else {
+               ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+               ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP);
+               BP10G_WRITE_REG(pbpctl_dev, EODSDP,
+                               (ctrl_ext &
+                                ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT)));
+       }
+       usec_delay(CMND_INTERVAL);
+       /*send sync cmd */
+       write_pulse(pbpctl_dev, ctrl_ext, SYNC_CMD_VAL, SYNC_CMD_LEN);
+       /*send rd cmd */
+       write_pulse(pbpctl_dev, ctrl_ext, RD_CMD_VAL, RD_CMD_LEN);
+       /*send addr */
+       write_pulse(pbpctl_dev, ctrl_ext, addr, ADDR_CMD_LEN);
+       /*read data */
+       /* zero */
+       if (pbpctl_dev->bp_10g9) {
+               /* DATA 0 CLK 1 */
+               /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext|BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9)); */
+               BP10G_WRITE_REG(pbpctl_dev, I2CCTL,
+                               (ctrl_ext | BP10G_MDIO_DATA_OUT9));
+               BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                               (ctrl | BP10G_MCLK_DATA_OUT9 |
+                                BP10G_MCLK_DIR_OUT9));
+       } else if (pbpctl_dev->bp_fiber5) {
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MCLK_DIR5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MCLK_DATA5)
+                                                     &
+                                                     ~
+                                                     (BPCTLI_CTRL_EXT_MDIO_DIR5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MDIO_DATA5)));
+       } else if (pbpctl_dev->bp_i80) {
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                  (ctrl_ext &
+                                   ~(BPCTLI_CTRL_EXT_MDIO_DATA80 |
+                                     BPCTLI_CTRL_EXT_MDIO_DIR80)));
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                  (ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80 |
+                                   BPCTLI_CTRL_EXT_MCLK_DATA80));
+       } else if (pbpctl_dev->bp_540) {
+               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                               (((ctrl | BP540_MDIO_DIR | BP540_MCLK_DIR |
+                                  BP540_MCLK_DATA) & ~BP540_MDIO_DATA)));
+       } else if (pbpctl_dev->bp_10gb) {
+               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                (ctrl_ext | BP10GB_MDIO_DIR | BP10GB_MCLK_SET)
+                                & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_SET |
+                                    BP10GB_MDIO_CLR | BP10GB_MCLK_CLR));
+       } else if (!pbpctl_dev->bp_10g)
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                          BPCTLI_CTRL_EXT_MCLK_DIR
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MCLK_DATA)
+                                                         &
+                                                         ~
+                                                         (BPCTLI_CTRL_EXT_MDIO_DIR
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MDIO_DATA)));
+       else {
+               BP10G_WRITE_REG(pbpctl_dev, EODSDP,
+                               (ctrl_ext | BP10G_MCLK_DATA_OUT |
+                                BP10G_MDIO_DATA_OUT));
+       }
+       usec_delay(PULSE_TIME);
+       ctrl_value = read_pulse(pbpctl_dev, ctrl_ext, RD_DATA_LEN);
+       if (pbpctl_dev->bp_10g9) {
+               ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL);
+               ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP);
+               /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */
+               /* DATA 0 CLK 0 */
+               BP10G_WRITE_REG(pbpctl_dev, I2CCTL,
+                               (ctrl_ext & ~BP10G_MDIO_DATA_OUT9));
+               BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                               ((ctrl | BP10G_MCLK_DIR_OUT9) &
+                                ~(BP10G_MCLK_DATA_OUT9)));
+       } else if (pbpctl_dev->bp_fiber5) {
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MCLK_DIR5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR5)
+                                                     &
+                                                     ~
+                                                     (BPCTLI_CTRL_EXT_MDIO_DATA5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MCLK_DATA5)));
+       } else if (pbpctl_dev->bp_i80) {
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR80)
+                                                     &
+                                                     ~BPCTLI_CTRL_EXT_MDIO_DATA80));
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                  ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) &
+                                   ~BPCTLI_CTRL_EXT_MCLK_DATA80));
+       } else if (pbpctl_dev->bp_540) {
+               ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+               BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | BP540_MCLK_DIR |
+                                                   BP540_MDIO_DIR) &
+                                                  ~(BP540_MDIO_DATA |
+                                                    BP540_MCLK_DATA)));
+       } else if (pbpctl_dev->bp_10gb) {
+               ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO);
+               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR)
+                                & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR |
+                                    BP10GB_MDIO_SET | BP10GB_MCLK_SET));
+       } else if (!pbpctl_dev->bp_10g) {
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                          BPCTLI_CTRL_EXT_MCLK_DIR
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MDIO_DIR)
+                                                         &
+                                                         ~
+                                                         (BPCTLI_CTRL_EXT_MDIO_DATA
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MCLK_DATA)));
+       } else {
+               ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+               ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP);
+               BP10G_WRITE_REG(pbpctl_dev, EODSDP,
+                               (ctrl_ext &
+                                ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT)));
+       }
+       usec_delay(CMND_INTERVAL * 4);
+ #ifdef BP_SYNC_FLAG
+       spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags);
+ #else
+       atomic_set(&pbpctl_dev->wdt_busy, 0);
+ #endif
+       return ctrl_value;
+ }
+ static int wdt_pulse(bpctl_dev_t *pbpctl_dev)
+ {
+       uint32_t ctrl_ext = 0, ctrl = 0;
+       bpctl_dev_t *pbpctl_dev_c = NULL;
+ #ifdef BP_SYNC_FLAG
+       unsigned long flags;
+       spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags);
+ #else
+       if ((atomic_read(&pbpctl_dev->wdt_busy)) == 1)
+               return -1;
+ #endif
+       if (pbpctl_dev->bp_10g9) {
+               if (!(pbpctl_dev_c = get_status_port_fn(pbpctl_dev)))
+                       return -1;
+       }
+       if (pbpctl_dev->bp_10g9) {
+               ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL);
+               ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP);
+               /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */
+               /* DATA 0 CLK 0 */
+               BP10G_WRITE_REG(pbpctl_dev, I2CCTL,
+                               (ctrl_ext & ~BP10G_MDIO_DATA_OUT9));
+               BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                               ((ctrl | BP10G_MCLK_DIR_OUT9) &
+                                ~(BP10G_MCLK_DATA_OUT9)));
+       } else if (pbpctl_dev->bp_fiber5) {
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL);
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MCLK_DIR5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR5)
+                                                     &
+                                                     ~
+                                                     (BPCTLI_CTRL_EXT_MDIO_DATA5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MCLK_DATA5)));
+       } else if (pbpctl_dev->bp_i80) {
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL);
+               ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR80)
+                                                     &
+                                                     ~BPCTLI_CTRL_EXT_MDIO_DATA80));
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                  ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) &
+                                   ~BPCTLI_CTRL_EXT_MCLK_DATA80));
+       } else if (pbpctl_dev->bp_540) {
+               ctrl_ext = ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+               BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | BP540_MCLK_DIR |
+                                                   BP540_MDIO_DIR) &
+                                                  ~(BP540_MDIO_DATA |
+                                                    BP540_MCLK_DATA)));
+       } else if (pbpctl_dev->bp_10gb) {
+               ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO);
+               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR)
+                                & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR |
+                                    BP10GB_MDIO_SET | BP10GB_MCLK_SET));
+       } else if (!pbpctl_dev->bp_10g) {
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                          BPCTLI_CTRL_EXT_MCLK_DIR
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MDIO_DIR)
+                                                         &
+                                                         ~
+                                                         (BPCTLI_CTRL_EXT_MDIO_DATA
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MCLK_DATA)));
+       } else {
+               ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+               ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP);
+               BP10G_WRITE_REG(pbpctl_dev, EODSDP,
+                               (ctrl_ext &
+                                ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT)));
+       }
+       if (pbpctl_dev->bp_10g9) {
+               /*   BP10G_WRITE_REG(pbpctl_dev, I2CCTL, ((ctrl_ext|BP10G_MCLK_DATA_OUT9)&~BP10G_MDIO_DATA_OUT9)); */
+               /* DATA 0 CLK 1 */
+               BP10G_WRITE_REG(pbpctl_dev, I2CCTL,
+                               (ctrl_ext & ~BP10G_MDIO_DATA_OUT9));
+               BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                               (ctrl | BP10G_MCLK_DATA_OUT9 |
+                                BP10G_MCLK_DIR_OUT9));
+       } else if (pbpctl_dev->bp_fiber5) {
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MCLK_DIR5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MCLK_DATA5)
+                                                     &
+                                                     ~
+                                                     (BPCTLI_CTRL_EXT_MDIO_DATA5)));
+       } else if (pbpctl_dev->bp_i80) {
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR80)
+                                                     &
+                                                     ~BPCTLI_CTRL_EXT_MDIO_DATA80));
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                  (ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80 |
+                                   BPCTLI_CTRL_EXT_MCLK_DATA80));
+       } else if (pbpctl_dev->bp_540) {
+               BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl |
+                                                   BP540_MDIO_DIR |
+                                                   BP540_MCLK_DIR |
+                                                   BP540_MCLK_DATA) &
+                                                  ~BP540_MDIO_DATA));
+       } else if (pbpctl_dev->bp_10gb) {
+               ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO);
+               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_SET)
+                                & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR |
+                                    BP10GB_MDIO_SET | BP10GB_MCLK_CLR));
+       } else if (!pbpctl_dev->bp_10g)
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                          BPCTLI_CTRL_EXT_MCLK_DIR
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MDIO_DIR
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MCLK_DATA)
+                                                         &
+                                                         ~
+                                                         (BPCTLI_CTRL_EXT_MDIO_DATA)));
+       else {
+               BP10G_WRITE_REG(pbpctl_dev, EODSDP,
+                               ((ctrl_ext | BP10G_MCLK_DATA_OUT) &
+                                ~BP10G_MDIO_DATA_OUT));
+       }
+       usec_delay(WDT_INTERVAL);
+       if (pbpctl_dev->bp_10g9) {
+               /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */
+               /* DATA 0 CLK 0 */
+               BP10G_WRITE_REG(pbpctl_dev, I2CCTL,
+                               (ctrl_ext & ~BP10G_MDIO_DATA_OUT9));
+               BP10G_WRITE_REG(pbpctl_dev_c, ESDP,
+                               ((ctrl | BP10G_MCLK_DIR_OUT9) &
+                                ~(BP10G_MCLK_DATA_OUT9)));
+       } else if (pbpctl_dev->bp_fiber5) {
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MCLK_DIR5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR5)
+                                                     &
+                                                     ~
+                                                     (BPCTLI_CTRL_EXT_MCLK_DATA5
+                                                      |
+                                                      BPCTLI_CTRL_EXT_MDIO_DATA5)));
+       } else if (pbpctl_dev->bp_i80) {
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext |
+                                                      BPCTLI_CTRL_EXT_MDIO_DIR80)
+                                                     &
+                                                     ~BPCTLI_CTRL_EXT_MDIO_DATA80));
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                  ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) &
+                                   ~BPCTLI_CTRL_EXT_MCLK_DATA80));
+       } else if (pbpctl_dev->bp_540) {
+               BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | BP540_MCLK_DIR |
+                                                   BP540_MDIO_DIR) &
+                                                  ~(BP540_MDIO_DATA |
+                                                    BP540_MCLK_DATA)));
+       } else if (pbpctl_dev->bp_10gb) {
+               ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO);
+               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO,
+                                (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR)
+                                & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR |
+                                    BP10GB_MDIO_SET | BP10GB_MCLK_SET));
+       } else if (!pbpctl_dev->bp_10g)
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                          BPCTLI_CTRL_EXT_MCLK_DIR
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MDIO_DIR)
+                                                         &
+                                                         ~
+                                                         (BPCTLI_CTRL_EXT_MCLK_DATA
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MDIO_DATA)));
+       else {
+               BP10G_WRITE_REG(pbpctl_dev, EODSDP,
+                               (ctrl_ext &
+                                ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT)));
+       }
+       if ((pbpctl_dev->wdt_status == WDT_STATUS_EN)   /*&&
+                                                          (pbpctl_dev->bp_ext_ver<PXG4BPFI_VER) */ )
+               pbpctl_dev->bypass_wdt_on_time = jiffies;
+ #ifdef BP_SYNC_FLAG
+       spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags);
+ #endif
+       usec_delay(CMND_INTERVAL * 4);
+       return 0;
+ }
+ static void data_pulse(bpctl_dev_t *pbpctl_dev, unsigned char value)
+ {
+       uint32_t ctrl_ext = 0;
+ #ifdef BP_SYNC_FLAG
+       unsigned long flags;
+ #endif
+       wdt_time_left(pbpctl_dev);
+ #ifdef BP_SYNC_FLAG
+       spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags);
+ #else
+       atomic_set(&pbpctl_dev->wdt_busy, 1);
+ #endif
+       ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                  BPCTLI_CTRL_EXT_SDP6_DIR |
+                                                  BPCTLI_CTRL_EXT_SDP7_DIR) &
+                                                 ~(BPCTLI_CTRL_EXT_SDP6_DATA |
+                                                   BPCTLI_CTRL_EXT_SDP7_DATA)));
+       usec_delay(INIT_CMND_INTERVAL);
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                  BPCTLI_CTRL_EXT_SDP6_DIR |
+                                                  BPCTLI_CTRL_EXT_SDP7_DIR |
+                                                  BPCTLI_CTRL_EXT_SDP6_DATA) &
+                                                 ~
+                                                 (BPCTLI_CTRL_EXT_SDP7_DATA)));
+       usec_delay(INIT_CMND_INTERVAL);
+       while (value) {
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext |
+                                  BPCTLI_CTRL_EXT_SDP6_DIR |
+                                  BPCTLI_CTRL_EXT_SDP7_DIR |
+                                  BPCTLI_CTRL_EXT_SDP6_DATA |
+                                  BPCTLI_CTRL_EXT_SDP7_DATA);
+               usec_delay(PULSE_INTERVAL);
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                          BPCTLI_CTRL_EXT_SDP6_DIR
+                                                          |
+                                                          BPCTLI_CTRL_EXT_SDP7_DIR
+                                                          |
+                                                          BPCTLI_CTRL_EXT_SDP6_DATA)
+                                                         &
+                                                         ~BPCTLI_CTRL_EXT_SDP7_DATA));
+               usec_delay(PULSE_INTERVAL);
+               value--;
+       }
+       usec_delay(INIT_CMND_INTERVAL - PULSE_INTERVAL);
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                  BPCTLI_CTRL_EXT_SDP6_DIR |
+                                                  BPCTLI_CTRL_EXT_SDP7_DIR) &
+                                                 ~(BPCTLI_CTRL_EXT_SDP6_DATA |
+                                                   BPCTLI_CTRL_EXT_SDP7_DATA)));
+       usec_delay(WDT_TIME_CNT);
+       if (pbpctl_dev->wdt_status == WDT_STATUS_EN)
+               pbpctl_dev->bypass_wdt_on_time = jiffies;
+ #ifdef BP_SYNC_FLAG
+       spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags);
+ #else
+       atomic_set(&pbpctl_dev->wdt_busy, 0);
+ #endif
+ }
+ static int send_wdt_pulse(bpctl_dev_t *pbpctl_dev)
+ {
+       uint32_t ctrl_ext = 0;
+ #ifdef BP_SYNC_FLAG
+       unsigned long flags;
+       spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags);
+ #else
+       if ((atomic_read(&pbpctl_dev->wdt_busy)) == 1)
+               return -1;
+ #endif
+       wdt_time_left(pbpctl_dev);
+       ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext |     /* 1 */
+                          BPCTLI_CTRL_EXT_SDP7_DIR |
+                          BPCTLI_CTRL_EXT_SDP7_DATA);
+       usec_delay(PULSE_INTERVAL);
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |   /* 0 */
+                                                  BPCTLI_CTRL_EXT_SDP7_DIR) &
+                                                 ~BPCTLI_CTRL_EXT_SDP7_DATA));
+       usec_delay(PULSE_INTERVAL);
+       if (pbpctl_dev->wdt_status == WDT_STATUS_EN)
+               pbpctl_dev->bypass_wdt_on_time = jiffies;
+ #ifdef BP_SYNC_FLAG
+       spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags);
+ #endif
+       return 0;
+ }
+ void send_bypass_clear_pulse(bpctl_dev_t *pbpctl_dev, unsigned int value)
+ {
+       uint32_t ctrl_ext = 0;
+       ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |   /* 0 */
+                                                  BPCTLI_CTRL_EXT_SDP6_DIR) &
+                                                 ~BPCTLI_CTRL_EXT_SDP6_DATA));
+       usec_delay(PULSE_INTERVAL);
+       while (value) {
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext |     /* 1 */
+                                  BPCTLI_CTRL_EXT_SDP6_DIR |
+                                  BPCTLI_CTRL_EXT_SDP6_DATA);
+               usec_delay(PULSE_INTERVAL);
+               value--;
+       }
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |   /* 0 */
+                                                  BPCTLI_CTRL_EXT_SDP6_DIR) &
+                                                 ~BPCTLI_CTRL_EXT_SDP6_DATA));
+       usec_delay(PULSE_INTERVAL);
+ }
+ /*  #endif  OLD_FW */
+ #ifdef BYPASS_DEBUG
+ int pulse_set_fn(bpctl_dev_t *pbpctl_dev, unsigned int counter)
+ {
+       uint32_t ctrl_ext = 0;
+       if (!pbpctl_dev)
+               return -1;
+       ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+       write_pulse_1(pbpctl_dev, ctrl_ext, counter, counter);
+       pbpctl_dev->bypass_wdt_status = 0;
+       if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+               write_pulse_1(pbpctl_dev, ctrl_ext, counter, counter);
+       } else {
+               wdt_time_left(pbpctl_dev);
+               if (pbpctl_dev->wdt_status == WDT_STATUS_EN) {
+                       pbpctl_dev->wdt_status = 0;
+                       data_pulse(pbpctl_dev, counter);
+                       pbpctl_dev->wdt_status = WDT_STATUS_EN;
+                       pbpctl_dev->bypass_wdt_on_time = jiffies;
+               } else
+                       data_pulse(pbpctl_dev, counter);
+       }
+       return 0;
+ }
+ int zero_set_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       uint32_t ctrl_ext = 0, ctrl_value = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+               printk("zero_set");
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                          BPCTLI_CTRL_EXT_MCLK_DIR)
+                                                         &
+                                                         ~
+                                                         (BPCTLI_CTRL_EXT_MCLK_DATA
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MDIO_DIR
+                                                          |
+                                                          BPCTLI_CTRL_EXT_MDIO_DATA)));
+       }
+       return ctrl_value;
+ }
+ int pulse_get2_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       uint32_t ctrl_ext = 0, ctrl_value = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+               printk("pulse_get_fn\n");
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+               ctrl_value = read_pulse_2(pbpctl_dev, ctrl_ext);
+               printk("read:%d\n", ctrl_value);
+       }
+       return ctrl_value;
+ }
+ int pulse_get1_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       uint32_t ctrl_ext = 0, ctrl_value = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+               printk("pulse_get_fn\n");
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+               ctrl_value = read_pulse_1(pbpctl_dev, ctrl_ext);
+               printk("read:%d\n", ctrl_value);
+       }
+       return ctrl_value;
+ }
+ int gpio6_set_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       uint32_t ctrl_ext = 0;
+       ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext |
+                          BPCTLI_CTRL_EXT_SDP6_DIR |
+                          BPCTLI_CTRL_EXT_SDP6_DATA);
+       return 0;
+ }
+ int gpio7_set_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       uint32_t ctrl_ext = 0;
+       ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext |
+                          BPCTLI_CTRL_EXT_SDP7_DIR |
+                          BPCTLI_CTRL_EXT_SDP7_DATA);
+       return 0;
+ }
+ int gpio7_clear_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       uint32_t ctrl_ext = 0;
+       ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                  BPCTLI_CTRL_EXT_SDP7_DIR) &
+                                                 ~BPCTLI_CTRL_EXT_SDP7_DATA));
+       return 0;
+ }
+ int gpio6_clear_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       uint32_t ctrl_ext = 0;
+       ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext |
+                                                  BPCTLI_CTRL_EXT_SDP6_DIR) &
+                                                 ~BPCTLI_CTRL_EXT_SDP6_DATA));
+       return 0;
+ }
+ #endif                                /*BYPASS_DEBUG */
+ static bpctl_dev_t *lookup_port(bpctl_dev_t *dev)
+ {
+       bpctl_dev_t *p;
+       int n;
+       for (n = 0, p = bpctl_dev_arr; n < device_num && p->pdev; n++) {
+               if (p->bus == dev->bus
+                   && p->slot == dev->slot
+                   && p->func == (dev->func ^ 1))
+                       return p;
+       }
+       return NULL;
+ }
+ static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev) {
+               if (pbpctl_dev->func == 0 || pbpctl_dev->func == 2)
+                       return lookup_port(pbpctl_dev);
+       }
+       return NULL;
+ }
+ static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev) {
+               if (pbpctl_dev->func == 1 || pbpctl_dev->func == 3)
+                       return lookup_port(pbpctl_dev);
+       }
+       return NULL;
+ }
+ /**************************************/
+ /**************INTEL API***************/
+ /**************************************/
+ static void write_data_port_int(bpctl_dev_t *pbpctl_dev,
+                               unsigned char ctrl_value)
+ {
+       uint32_t value;
+       value = BPCTL_READ_REG(pbpctl_dev, CTRL);
+ /* Make SDP0 Pin Directonality to Output */
+       value |= BPCTLI_CTRL_SDP0_DIR;
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, value);
+       value &= ~BPCTLI_CTRL_SDP0_DATA;
+       value |= ((ctrl_value & 0x1) << BPCTLI_CTRL_SDP0_SHIFT);
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, value);
+       value = (BPCTL_READ_REG(pbpctl_dev, CTRL_EXT));
+ /* Make SDP2 Pin Directonality to Output */
+       value |= BPCTLI_CTRL_EXT_SDP6_DIR;
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, value);
+       value &= ~BPCTLI_CTRL_EXT_SDP6_DATA;
+       value |= (((ctrl_value & 0x2) >> 1) << BPCTLI_CTRL_EXT_SDP6_SHIFT);
+       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, value);
+ }
+ static int write_data_int(bpctl_dev_t *pbpctl_dev, unsigned char value)
+ {
+       bpctl_dev_t *pbpctl_dev_b = NULL;
+       if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev)))
+               return -1;
+       atomic_set(&pbpctl_dev->wdt_busy, 1);
+       write_data_port_int(pbpctl_dev, value & 0x3);
+       write_data_port_int(pbpctl_dev_b, ((value & 0xc) >> 2));
+       atomic_set(&pbpctl_dev->wdt_busy, 0);
+       return 0;
+ }
+ static int wdt_pulse_int(bpctl_dev_t *pbpctl_dev)
+ {
+       if ((atomic_read(&pbpctl_dev->wdt_busy)) == 1)
+               return -1;
+       if ((write_data_int(pbpctl_dev, RESET_WDT_INT)) < 0)
+               return -1;
+       msec_delay_bp(CMND_INTERVAL_INT);
+       if ((write_data_int(pbpctl_dev, CMND_OFF_INT)) < 0)
+               return -1;
+       msec_delay_bp(CMND_INTERVAL_INT);
+       if (pbpctl_dev->wdt_status == WDT_STATUS_EN)
+               pbpctl_dev->bypass_wdt_on_time = jiffies;
+       return 0;
+ }
+ /*************************************/
+ /************* COMMANDS **************/
+ /*************************************/
+ /* CMND_ON  0x4 (100)*/
+ int cmnd_on(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice))
+                       return 0;
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER)
+                       write_data(pbpctl_dev, CMND_ON);
+               else
+                       data_pulse(pbpctl_dev, CMND_ON);
+               ret = 0;
+       }
+       return ret;
+ }
+ /* CMND_OFF  0x2 (10)*/
+ int cmnd_off(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) {
+                       write_data_int(pbpctl_dev, CMND_OFF_INT);
+                       msec_delay_bp(CMND_INTERVAL_INT);
+               } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER)
+                       write_data(pbpctl_dev, CMND_OFF);
+               else
+                       data_pulse(pbpctl_dev, CMND_OFF);
+               ret = 0;
+       };
+       return ret;
+ }
+ /* BYPASS_ON (0xa)*/
+ int bypass_on(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       if (pbpctl_dev->bp_caps & BP_CAP) {
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) {
+                       write_data_int(pbpctl_dev, BYPASS_ON_INT);
+                       msec_delay_bp(BYPASS_DELAY_INT);
+                       pbpctl_dev->bp_status_un = 0;
+               } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       write_data(pbpctl_dev, BYPASS_ON);
+                       if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)
+                               msec_delay_bp(LATCH_DELAY);
+               } else
+                       data_pulse(pbpctl_dev, BYPASS_ON);
+               ret = 0;
+       };
+       return ret;
+ }
+ /* BYPASS_OFF (0x8 111)*/
+ int bypass_off(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       if (pbpctl_dev->bp_caps & BP_CAP) {
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) {
+                       write_data_int(pbpctl_dev, DIS_BYPASS_CAP_INT);
+                       msec_delay_bp(BYPASS_DELAY_INT);
+                       write_data_int(pbpctl_dev, PWROFF_BYPASS_ON_INT);
+                       msec_delay_bp(BYPASS_DELAY_INT);
+                       pbpctl_dev->bp_status_un = 0;
+               } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       write_data(pbpctl_dev, BYPASS_OFF);
+                       if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)
+                               msec_delay_bp(LATCH_DELAY);
+               } else
+                       data_pulse(pbpctl_dev, BYPASS_OFF);
+               ret = 0;
+       }
+       return ret;
+ }
+ /* TAP_OFF (0x9)*/
+ int tap_off(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       if ((pbpctl_dev->bp_caps & TAP_CAP)
+           && (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)) {
+               write_data(pbpctl_dev, TAP_OFF);
+               msec_delay_bp(LATCH_DELAY);
+               ret = 0;
+       };
+       return ret;
+ }
+ /* TAP_ON (0xb)*/
+ int tap_on(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       if ((pbpctl_dev->bp_caps & TAP_CAP)
+           && (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)) {
+               write_data(pbpctl_dev, TAP_ON);
+               msec_delay_bp(LATCH_DELAY);
+               ret = 0;
+       };
+       return ret;
+ }
+ /* DISC_OFF (0x9)*/
+ int disc_off(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if ((pbpctl_dev->bp_caps & DISC_CAP) && (pbpctl_dev->bp_ext_ver >= 0x8)) {
+               write_data(pbpctl_dev, DISC_OFF);
+               msec_delay_bp(LATCH_DELAY);
+       } else
+               ret = BP_NOT_CAP;
+       return ret;
+ }
+ /* DISC_ON (0xb)*/
+ int disc_on(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if ((pbpctl_dev->bp_caps & DISC_CAP) && (pbpctl_dev->bp_ext_ver >= 0x8)) {
+               write_data(pbpctl_dev, /*DISC_ON */ 0x85);
+               msec_delay_bp(LATCH_DELAY);
+       } else
+               ret = BP_NOT_CAP;
+       return ret;
+ }
+ /* DISC_PORT_ON */
+ int disc_port_on(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       bpctl_dev_t *pbpctl_dev_m;
+       if ((is_bypass_fn(pbpctl_dev)) == 1)
+               pbpctl_dev_m = pbpctl_dev;
+       else
+               pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
+       if (pbpctl_dev_m == NULL)
+               return BP_NOT_CAP;
+       if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
+               if (is_bypass_fn(pbpctl_dev) == 1) {
+                       write_data(pbpctl_dev_m, TX_DISA);
+               } else {
+                       write_data(pbpctl_dev_m, TX_DISB);
+               }
+               msec_delay_bp(LATCH_DELAY);
+       }
+       return ret;
+ }
+ /* DISC_PORT_OFF */
+ int disc_port_off(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       bpctl_dev_t *pbpctl_dev_m;
+       if ((is_bypass_fn(pbpctl_dev)) == 1)
+               pbpctl_dev_m = pbpctl_dev;
+       else
+               pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
+       if (pbpctl_dev_m == NULL)
+               return BP_NOT_CAP;
+       if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
+               if (is_bypass_fn(pbpctl_dev) == 1)
+                       write_data(pbpctl_dev_m, TX_ENA);
+               else
+                       write_data(pbpctl_dev_m, TX_ENB);
+               msec_delay_bp(LATCH_DELAY);
+       }
+       return ret;
+ }
+ /*TWO_PORT_LINK_HW_EN (0xe)*/
+ int tpl_hw_on(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0, ctrl = 0;
+       bpctl_dev_t *pbpctl_dev_b = NULL;
+       if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev)))
+               return BP_NOT_CAP;
+       if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) {
+               cmnd_on(pbpctl_dev);
+               write_data(pbpctl_dev, TPL2_ON);
+               msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+               cmnd_off(pbpctl_dev);
+               return ret;
+       }
+       if (TPL_IF_SERIES(pbpctl_dev->subdevice)) {
+               ctrl = BPCTL_READ_REG(pbpctl_dev_b, CTRL);
+               BPCTL_BP_WRITE_REG(pbpctl_dev_b, CTRL,
+                                  ((ctrl | BPCTLI_CTRL_SWDPIO0) &
+                                   ~BPCTLI_CTRL_SWDPIN0));
+       } else
+               ret = BP_NOT_CAP;
+       return ret;
+ }
+ /*TWO_PORT_LINK_HW_DIS (0xc)*/
+ int tpl_hw_off(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0, ctrl = 0;
+       bpctl_dev_t *pbpctl_dev_b = NULL;
+       if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev)))
+               return BP_NOT_CAP;
+       if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) {
+               cmnd_on(pbpctl_dev);
+               write_data(pbpctl_dev, TPL2_OFF);
+               msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+               cmnd_off(pbpctl_dev);
+               return ret;
+       }
+       if (TPL_IF_SERIES(pbpctl_dev->subdevice)) {
+               ctrl = BPCTL_READ_REG(pbpctl_dev_b, CTRL);
+               BPCTL_BP_WRITE_REG(pbpctl_dev_b, CTRL,
+                                  (ctrl | BPCTLI_CTRL_SWDPIO0 |
+                                   BPCTLI_CTRL_SWDPIN0));
+       } else
+               ret = BP_NOT_CAP;
+       return ret;
+ }
+ /* WDT_OFF (0x6 110)*/
+ int wdt_off(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) {
+                       bypass_off(pbpctl_dev);
+               } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER)
+                       write_data(pbpctl_dev, WDT_OFF);
+               else
+                       data_pulse(pbpctl_dev, WDT_OFF);
+               pbpctl_dev->wdt_status = WDT_STATUS_DIS;
+               ret = 0;
+       };
+       return ret;
+ }
+ /* WDT_ON (0x10)*/
+ /***Global***/
+ static unsigned int
+     wdt_val_array[] = { 1000, 1500, 2000, 3000, 4000, 8000, 16000, 32000, 0 };
+ int wdt_on(bpctl_dev_t *pbpctl_dev, unsigned int timeout)
+ {
+       if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
+               unsigned int pulse = 0, temp_value = 0, temp_cnt = 0;
+               pbpctl_dev->wdt_status = 0;
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) {
+                       for (; wdt_val_array[temp_cnt]; temp_cnt++)
+                               if (timeout <= wdt_val_array[temp_cnt])
+                                       break;
+                       if (!wdt_val_array[temp_cnt])
+                               temp_cnt--;
+                       timeout = wdt_val_array[temp_cnt];
+                       temp_cnt += 0x7;
+                       write_data_int(pbpctl_dev, DIS_BYPASS_CAP_INT);
+                       msec_delay_bp(BYPASS_DELAY_INT);
+                       pbpctl_dev->bp_status_un = 0;
+                       write_data_int(pbpctl_dev, temp_cnt);
+                       pbpctl_dev->bypass_wdt_on_time = jiffies;
+                       msec_delay_bp(CMND_INTERVAL_INT);
+                       pbpctl_dev->bypass_timer_interval = timeout;
+               } else {
+                       timeout =
+                           (timeout <
+                            TIMEOUT_UNIT ? TIMEOUT_UNIT : (timeout >
+                                                           WDT_TIMEOUT_MAX ?
+                                                           WDT_TIMEOUT_MAX :
+                                                           timeout));
+                       temp_value = timeout / 100;
+                       while ((temp_value >>= 1))
+                               temp_cnt++;
+                       if (timeout > ((1 << temp_cnt) * 100))
+                               temp_cnt++;
+                       pbpctl_dev->bypass_wdt_on_time = jiffies;
+                       pulse = (WDT_ON | temp_cnt);
+                       if (pbpctl_dev->bp_ext_ver == OLD_IF_VER)
+                               data_pulse(pbpctl_dev, pulse);
+                       else
+                               write_data(pbpctl_dev, pulse);
+                       pbpctl_dev->bypass_timer_interval =
+                           (1 << temp_cnt) * 100;
+               }
+               pbpctl_dev->wdt_status = WDT_STATUS_EN;
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ void bp75_put_hw_semaphore_generic(bpctl_dev_t *pbpctl_dev)
+ {
+       u32 swsm;
+       swsm = BPCTL_READ_REG(pbpctl_dev, SWSM);
+       swsm &= ~(BPCTLI_SWSM_SMBI | BPCTLI_SWSM_SWESMBI);
+       BPCTL_WRITE_REG(pbpctl_dev, SWSM, swsm);
+ }
+ s32 bp75_get_hw_semaphore_generic(bpctl_dev_t *pbpctl_dev)
+ {
+       u32 swsm;
+       s32 ret_val = 0;
+       s32 timeout = 8192 + 1;
+       s32 i = 0;
+       /* Get the SW semaphore */
+       while (i < timeout) {
+               swsm = BPCTL_READ_REG(pbpctl_dev, SWSM);
+               if (!(swsm & BPCTLI_SWSM_SMBI))
+                       break;
+               usec_delay(50);
+               i++;
+       }
+       if (i == timeout) {
+               printk
+                   ("bpctl_mod: Driver can't access device - SMBI bit is set.\n");
+               ret_val = -1;
+               goto out;
+       }
+       /* Get the FW semaphore. */
+       for (i = 0; i < timeout; i++) {
+               swsm = BPCTL_READ_REG(pbpctl_dev, SWSM);
+               BPCTL_WRITE_REG(pbpctl_dev, SWSM, swsm | BPCTLI_SWSM_SWESMBI);
+               /* Semaphore acquired if bit latched */
+               if (BPCTL_READ_REG(pbpctl_dev, SWSM) & BPCTLI_SWSM_SWESMBI)
+                       break;
+               usec_delay(50);
+       }
+       if (i == timeout) {
+               /* Release semaphores */
+               bp75_put_hw_semaphore_generic(pbpctl_dev);
+               printk("bpctl_mod: Driver can't access the NVM\n");
+               ret_val = -1;
+               goto out;
+       }
+  out:
+       return ret_val;
+ }
+ static void bp75_release_phy(bpctl_dev_t *pbpctl_dev)
+ {
+       u16 mask = BPCTLI_SWFW_PHY0_SM;
+       u32 swfw_sync;
+       if ((pbpctl_dev->func == 1) || (pbpctl_dev->func == 3))
+               mask = BPCTLI_SWFW_PHY1_SM;
+       while (bp75_get_hw_semaphore_generic(pbpctl_dev) != 0) ;
+       /* Empty */
+       swfw_sync = BPCTL_READ_REG(pbpctl_dev, SW_FW_SYNC);
+       swfw_sync &= ~mask;
+       BPCTL_WRITE_REG(pbpctl_dev, SW_FW_SYNC, swfw_sync);
+       bp75_put_hw_semaphore_generic(pbpctl_dev);
+ }
+ static s32 bp75_acquire_phy(bpctl_dev_t *pbpctl_dev)
+ {
+       u16 mask = BPCTLI_SWFW_PHY0_SM;
+       u32 swfw_sync;
+       u32 swmask;
+       u32 fwmask;
+       s32 ret_val = 0;
+       s32 i = 0, timeout = 200;
+       if ((pbpctl_dev->func == 1) || (pbpctl_dev->func == 3))
+               mask = BPCTLI_SWFW_PHY1_SM;
+       swmask = mask;
+       fwmask = mask << 16;
+       while (i < timeout) {
+               if (bp75_get_hw_semaphore_generic(pbpctl_dev)) {
+                       ret_val = -1;
+                       goto out;
+               }
+               swfw_sync = BPCTL_READ_REG(pbpctl_dev, SW_FW_SYNC);
+               if (!(swfw_sync & (fwmask | swmask)))
+                       break;
+               bp75_put_hw_semaphore_generic(pbpctl_dev);
+               mdelay(5);
+               i++;
+       }
+       if (i == timeout) {
+               printk
+                   ("bpctl_mod: Driver can't access resource, SW_FW_SYNC timeout.\n");
+               ret_val = -1;
+               goto out;
+       }
+       swfw_sync |= swmask;
+       BPCTL_WRITE_REG(pbpctl_dev, SW_FW_SYNC, swfw_sync);
+       bp75_put_hw_semaphore_generic(pbpctl_dev);
+  out:
+       return ret_val;
+ }
+ s32 bp75_read_phy_reg_mdic(bpctl_dev_t *pbpctl_dev, u32 offset, u16 *data)
+ {
+       u32 i, mdic = 0;
+       s32 ret_val = 0;
+       u32 phy_addr = 1;
+       mdic = ((offset << BPCTLI_MDIC_REG_SHIFT) |
+               (phy_addr << BPCTLI_MDIC_PHY_SHIFT) | (BPCTLI_MDIC_OP_READ));
+       BPCTL_WRITE_REG(pbpctl_dev, MDIC, mdic);
+       for (i = 0; i < (BPCTLI_GEN_POLL_TIMEOUT * 3); i++) {
+               usec_delay(50);
+               mdic = BPCTL_READ_REG(pbpctl_dev, MDIC);
+               if (mdic & BPCTLI_MDIC_READY)
+                       break;
+       }
+       if (!(mdic & BPCTLI_MDIC_READY)) {
+               printk("bpctl_mod: MDI Read did not complete\n");
+               ret_val = -1;
+               goto out;
+       }
+       if (mdic & BPCTLI_MDIC_ERROR) {
+               printk("bpctl_mod: MDI Error\n");
+               ret_val = -1;
+               goto out;
+       }
+       *data = (u16) mdic;
+  out:
+       return ret_val;
+ }
+ s32 bp75_write_phy_reg_mdic(bpctl_dev_t *pbpctl_dev, u32 offset, u16 data)
+ {
+       u32 i, mdic = 0;
+       s32 ret_val = 0;
+       u32 phy_addr = 1;
+       mdic = (((u32) data) |
+               (offset << BPCTLI_MDIC_REG_SHIFT) |
+               (phy_addr << BPCTLI_MDIC_PHY_SHIFT) | (BPCTLI_MDIC_OP_WRITE));
+       BPCTL_WRITE_REG(pbpctl_dev, MDIC, mdic);
+       for (i = 0; i < (BPCTLI_GEN_POLL_TIMEOUT * 3); i++) {
+               usec_delay(50);
+               mdic = BPCTL_READ_REG(pbpctl_dev, MDIC);
+               if (mdic & BPCTLI_MDIC_READY)
+                       break;
+       }
+       if (!(mdic & BPCTLI_MDIC_READY)) {
+               printk("bpctl_mod: MDI Write did not complete\n");
+               ret_val = -1;
+               goto out;
+       }
+       if (mdic & BPCTLI_MDIC_ERROR) {
+               printk("bpctl_mod: MDI Error\n");
+               ret_val = -1;
+               goto out;
+       }
+  out:
+       return ret_val;
+ }
+ static s32 bp75_read_phy_reg(bpctl_dev_t *pbpctl_dev, u32 offset, u16 *data)
+ {
+       s32 ret_val = 0;
+       ret_val = bp75_acquire_phy(pbpctl_dev);
+       if (ret_val)
+               goto out;
+       if (offset > BPCTLI_MAX_PHY_MULTI_PAGE_REG) {
+               ret_val = bp75_write_phy_reg_mdic(pbpctl_dev,
+                                                 BPCTLI_IGP01E1000_PHY_PAGE_SELECT,
+                                                 (u16) offset);
+               if (ret_val)
+                       goto release;
+       }
+       ret_val =
+           bp75_read_phy_reg_mdic(pbpctl_dev,
+                                  BPCTLI_MAX_PHY_REG_ADDRESS & offset, data);
+  release:
+       bp75_release_phy(pbpctl_dev);
+  out:
+       return ret_val;
+ }
+ static s32 bp75_write_phy_reg(bpctl_dev_t *pbpctl_dev, u32 offset, u16 data)
+ {
+       s32 ret_val = 0;
+       ret_val = bp75_acquire_phy(pbpctl_dev);
+       if (ret_val)
+               goto out;
+       if (offset > BPCTLI_MAX_PHY_MULTI_PAGE_REG) {
+               ret_val = bp75_write_phy_reg_mdic(pbpctl_dev,
+                                                 BPCTLI_IGP01E1000_PHY_PAGE_SELECT,
+                                                 (u16) offset);
+               if (ret_val)
+                       goto release;
+       }
+       ret_val =
+           bp75_write_phy_reg_mdic(pbpctl_dev,
+                                   BPCTLI_MAX_PHY_REG_ADDRESS & offset, data);
+  release:
+       bp75_release_phy(pbpctl_dev);
+  out:
+       return ret_val;
+ }
+ /* SET_TX  (non-Bypass command :)) */
+ static int set_tx(bpctl_dev_t *pbpctl_dev, int tx_state)
+ {
+       int ret = 0, ctrl = 0;
+       bpctl_dev_t *pbpctl_dev_m;
+       if ((is_bypass_fn(pbpctl_dev)) == 1)
+               pbpctl_dev_m = pbpctl_dev;
+       else
+               pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
+       if (pbpctl_dev_m == NULL)
+               return BP_NOT_CAP;
+       if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
+               ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL);
+               if (!tx_state) {
+                       if (pbpctl_dev->bp_540) {
+                               ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                               (ctrl | BP10G_SDP1_DIR |
+                                                BP10G_SDP1_DATA));
+                       } else {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                                  (ctrl | BPCTLI_CTRL_SDP1_DIR
+                                                   | BPCTLI_CTRL_SWDPIN1));
+                       }
+               } else {
+                       if (pbpctl_dev->bp_540) {
+                               ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                               ((ctrl | BP10G_SDP1_DIR) &
+                                                ~BP10G_SDP1_DATA));
+                       } else {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                                  ((ctrl |
+                                                    BPCTLI_CTRL_SDP1_DIR) &
+                                                   ~BPCTLI_CTRL_SWDPIN1));
+                       }
+                       return ret;
+               }
+       } else if (pbpctl_dev->bp_caps & TX_CTL_CAP) {
+               if (PEG5_IF_SERIES(pbpctl_dev->subdevice)) {
+                       if (tx_state) {
+                               uint16_t mii_reg;
+                               if (!
+                                   (ret =
+                                    bp75_read_phy_reg(pbpctl_dev,
+                                                      BPCTLI_PHY_CONTROL,
+                                                      &mii_reg))) {
+                                       if (mii_reg & BPCTLI_MII_CR_POWER_DOWN) {
+                                               ret =
+                                                   bp75_write_phy_reg
+                                                   (pbpctl_dev,
+                                                    BPCTLI_PHY_CONTROL,
+                                                    mii_reg &
+                                                    ~BPCTLI_MII_CR_POWER_DOWN);
+                                       }
+                               }
+                       } else {
+                               uint16_t mii_reg;
+                               if (!
+                                   (ret =
+                                    bp75_read_phy_reg(pbpctl_dev,
+                                                      BPCTLI_PHY_CONTROL,
+                                                      &mii_reg))) {
+                                       mii_reg |= BPCTLI_MII_CR_POWER_DOWN;
+                                       ret =
+                                           bp75_write_phy_reg(pbpctl_dev,
+                                                              BPCTLI_PHY_CONTROL,
+                                                              mii_reg);
+                               }
+                       }
+               }
+               if (pbpctl_dev->bp_fiber5) {
+                       ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+               } else if (pbpctl_dev->bp_10gb)
+                       ctrl = BP10GB_READ_REG(pbpctl_dev, MISC_REG_GPIO);
+               else if (!pbpctl_dev->bp_10g)
+                       ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL);
+               else
+                       ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+               if (!tx_state)
+                       if (pbpctl_dev->bp_10g9) {
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                               (ctrl | BP10G_SDP3_DATA |
+                                                BP10G_SDP3_DIR));
+                       } else if (pbpctl_dev->bp_fiber5) {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                                  (ctrl |
+                                                   BPCTLI_CTRL_EXT_SDP6_DIR |
+                                                   BPCTLI_CTRL_EXT_SDP6_DATA));
+                       } else if (pbpctl_dev->bp_10gb) {
+                               if ((pbpctl_dev->func == 1)
+                                   || (pbpctl_dev->func == 3))
+                                       BP10GB_WRITE_REG(pbpctl_dev,
+                                                        MISC_REG_GPIO,
+                                                        (ctrl |
+                                                         BP10GB_GPIO0_SET_P1) &
+                                                        ~(BP10GB_GPIO0_CLR_P1 |
+                                                          BP10GB_GPIO0_OE_P1));
+                               else
+                                       BP10GB_WRITE_REG(pbpctl_dev,
+                                                        MISC_REG_GPIO,
+                                                        (ctrl |
+                                                         BP10GB_GPIO0_OE_P0 |
+                                                         BP10GB_GPIO0_SET_P0));
+                       } else if (pbpctl_dev->bp_i80) {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                                  (ctrl | BPCTLI_CTRL_SDP1_DIR
+                                                   | BPCTLI_CTRL_SWDPIN1));
+                       } else if (pbpctl_dev->bp_540) {
+                               ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                               (ctrl | BP10G_SDP1_DIR |
+                                                BP10G_SDP1_DATA));
+                       }
+                       else if (!pbpctl_dev->bp_10g)
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                                  (ctrl | BPCTLI_CTRL_SWDPIO0 |
+                                                   BPCTLI_CTRL_SWDPIN0));
+                       else
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                               (ctrl | BP10G_SDP0_DATA |
+                                                BP10G_SDP0_DIR));
+               else {
+                       if (pbpctl_dev->bp_10g9) {
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                               ((ctrl | BP10G_SDP3_DIR) &
+                                                ~BP10G_SDP3_DATA));
+                       } else if (pbpctl_dev->bp_fiber5) {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT,
+                                                  ((ctrl |
+                                                    BPCTLI_CTRL_EXT_SDP6_DIR) &
+                                                   ~BPCTLI_CTRL_EXT_SDP6_DATA));
+                       } else if (pbpctl_dev->bp_10gb) {
+                               if ((bpctl_dev_arr->func == 1)
+                                   || (bpctl_dev_arr->func == 3))
+                                       BP10GB_WRITE_REG(pbpctl_dev,
+                                                        MISC_REG_GPIO,
+                                                        (ctrl |
+                                                         BP10GB_GPIO0_CLR_P1) &
+                                                        ~(BP10GB_GPIO0_SET_P1 |
+                                                          BP10GB_GPIO0_OE_P1));
+                               else
+                                       BP10GB_WRITE_REG(pbpctl_dev,
+                                                        MISC_REG_GPIO,
+                                                        (ctrl |
+                                                         BP10GB_GPIO0_OE_P0 |
+                                                         BP10GB_GPIO0_CLR_P0));
+                       } else if (pbpctl_dev->bp_i80) {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                                  ((ctrl |
+                                                    BPCTLI_CTRL_SDP1_DIR) &
+                                                   ~BPCTLI_CTRL_SWDPIN1));
+                       } else if (pbpctl_dev->bp_540) {
+                               ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                               ((ctrl | BP10G_SDP1_DIR) &
+                                                ~BP10G_SDP1_DATA));
+                       }
+                       else if (!pbpctl_dev->bp_10g) {
+                               BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                                  ((ctrl | BPCTLI_CTRL_SWDPIO0)
+                                                   & ~BPCTLI_CTRL_SWDPIN0));
+                               if (!PEGF_IF_SERIES(pbpctl_dev->subdevice)) {
+                                       BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL,
+                                                          (ctrl &
+                                                           ~
+                                                           (BPCTLI_CTRL_SDP0_DATA
+                                                            |
+                                                            BPCTLI_CTRL_SDP0_DIR)));
+                               }
+                       } else
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                               ((ctrl | BP10G_SDP0_DIR) &
+                                                ~BP10G_SDP0_DATA));
+               }
+       } else
+               ret = BP_NOT_CAP;
+       return ret;
+ }
+ /* SET_FORCE_LINK  (non-Bypass command :)) */
+ static int set_bp_force_link(bpctl_dev_t *pbpctl_dev, int tx_state)
+ {
+       int ret = 0, ctrl = 0;
+       if (DBI_IF_SERIES(pbpctl_dev->subdevice)) {
+               if ((pbpctl_dev->bp_10g) || (pbpctl_dev->bp_10g9)) {
+                       ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL);
+                       if (!tx_state)
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                               ctrl & ~BP10G_SDP1_DIR);
+                       else
+                               BP10G_WRITE_REG(pbpctl_dev, ESDP,
+                                               ((ctrl | BP10G_SDP1_DIR) &
+                                                ~BP10G_SDP1_DATA));
+                       return ret;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ /*RESET_CONT 0x20 */
+ int reset_cont(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice))
+                       return BP_NOT_CAP;
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER)
+                       write_data(pbpctl_dev, RESET_CONT);
+               else
+                       data_pulse(pbpctl_dev, RESET_CONT);
+               ret = 0;
+       };
+       return ret;
+ }
+ /*DIS_BYPASS_CAP 0x22 */
+ int dis_bypass_cap(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & BP_DIS_CAP) {
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) {
+                       write_data_int(pbpctl_dev, DIS_BYPASS_CAP_INT);
+                       msec_delay_bp(BYPASS_DELAY_INT);
+               } else {
+                       write_data(pbpctl_dev, BYPASS_OFF);
+                       msec_delay_bp(LATCH_DELAY);
+                       write_data(pbpctl_dev, DIS_BYPASS_CAP);
+                       msec_delay_bp(BYPASS_CAP_DELAY);
+               }
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ /*EN_BYPASS_CAP 0x24 */
+ int en_bypass_cap(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & BP_DIS_CAP) {
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) {
+                       write_data_int(pbpctl_dev, PWROFF_BYPASS_ON_INT);
+                       msec_delay_bp(BYPASS_DELAY_INT);
+               } else {
+                       write_data(pbpctl_dev, EN_BYPASS_CAP);
+                       msec_delay_bp(BYPASS_CAP_DELAY);
+               }
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ /* BYPASS_STATE_PWRON 0x26*/
+ int bypass_state_pwron(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) {
+               write_data(pbpctl_dev, BYPASS_STATE_PWRON);
+               if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER)
+                       msec_delay_bp(DFLT_PWRON_DELAY);
+               else
+                       msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ /* NORMAL_STATE_PWRON 0x28*/
+ int normal_state_pwron(bpctl_dev_t *pbpctl_dev)
+ {
+       if ((pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP)
+           || (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP)) {
+               write_data(pbpctl_dev, NORMAL_STATE_PWRON);
+               if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER)
+                       msec_delay_bp(DFLT_PWRON_DELAY);
+               else
+                       msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ /* BYPASS_STATE_PWROFF 0x27*/
+ int bypass_state_pwroff(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP) {
+               write_data(pbpctl_dev, BYPASS_STATE_PWROFF);
+               msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ /* NORMAL_STATE_PWROFF 0x29*/
+ int normal_state_pwroff(bpctl_dev_t *pbpctl_dev)
+ {
+       if ((pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP)) {
+               write_data(pbpctl_dev, NORMAL_STATE_PWROFF);
+               msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ /*TAP_STATE_PWRON 0x2a*/
+ int tap_state_pwron(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) {
+               write_data(pbpctl_dev, TAP_STATE_PWRON);
+               msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ /*DIS_TAP_CAP 0x2c*/
+ int dis_tap_cap(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & TAP_DIS_CAP) {
+               write_data(pbpctl_dev, DIS_TAP_CAP);
+               msec_delay_bp(BYPASS_CAP_DELAY);
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ /*EN_TAP_CAP 0x2e*/
+ int en_tap_cap(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & TAP_DIS_CAP) {
+               write_data(pbpctl_dev, EN_TAP_CAP);
+               msec_delay_bp(BYPASS_CAP_DELAY);
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ /*DISC_STATE_PWRON 0x2a*/
+ int disc_state_pwron(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= 0x8) {
+                       write_data(pbpctl_dev, DISC_STATE_PWRON);
+                       msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+                       return BP_OK;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ /*DIS_DISC_CAP 0x2c*/
+ int dis_disc_cap(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & DISC_DIS_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= 0x8) {
+                       write_data(pbpctl_dev, DIS_DISC_CAP);
+                       msec_delay_bp(BYPASS_CAP_DELAY);
+                       return BP_OK;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ /*DISC_STATE_PWRON 0x2a*/
+ int disc_port_state_pwron(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       bpctl_dev_t *pbpctl_dev_m;
+       return BP_NOT_CAP;
+       if ((is_bypass_fn(pbpctl_dev)) == 1)
+               pbpctl_dev_m = pbpctl_dev;
+       else
+               pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
+       if (pbpctl_dev_m == NULL)
+               return BP_NOT_CAP;
+       if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
+               if (is_bypass_fn(pbpctl_dev) == 1)
+                       write_data(pbpctl_dev_m, TX_DISA_PWRUP);
+               else
+                       write_data(pbpctl_dev_m, TX_DISB_PWRUP);
+               msec_delay_bp(LATCH_DELAY);
+       }
+       return ret;
+ }
+ int normal_port_state_pwron(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       bpctl_dev_t *pbpctl_dev_m;
+       return BP_NOT_CAP;
+       if ((is_bypass_fn(pbpctl_dev)) == 1)
+               pbpctl_dev_m = pbpctl_dev;
+       else
+               pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
+       if (pbpctl_dev_m == NULL)
+               return BP_NOT_CAP;
+       if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
+               if (is_bypass_fn(pbpctl_dev) == 1)
+                       write_data(pbpctl_dev_m, TX_ENA_PWRUP);
+               else
+                       write_data(pbpctl_dev_m, TX_ENB_PWRUP);
+               msec_delay_bp(LATCH_DELAY);
+       }
+       return ret;
+ }
+ /*EN_TAP_CAP 0x2e*/
+ int en_disc_cap(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & DISC_DIS_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= 0x8) {
+                       write_data(pbpctl_dev, EN_DISC_CAP);
+                       msec_delay_bp(BYPASS_CAP_DELAY);
+                       return BP_OK;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int std_nic_on(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & STD_NIC_CAP) {
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) {
+                       write_data_int(pbpctl_dev, DIS_BYPASS_CAP_INT);
+                       msec_delay_bp(BYPASS_DELAY_INT);
+                       pbpctl_dev->bp_status_un = 0;
+                       return BP_OK;
+               }
+               if (pbpctl_dev->bp_ext_ver >= 0x8) {
+                       write_data(pbpctl_dev, STD_NIC_ON);
+                       msec_delay_bp(BYPASS_CAP_DELAY);
+                       return BP_OK;
+               }
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       wdt_off(pbpctl_dev);
+                       if (pbpctl_dev->bp_caps & BP_CAP) {
+                               write_data(pbpctl_dev, BYPASS_OFF);
+                               msec_delay_bp(LATCH_DELAY);
+                       }
+                       if (pbpctl_dev->bp_caps & TAP_CAP) {
+                               write_data(pbpctl_dev, TAP_OFF);
+                               msec_delay_bp(LATCH_DELAY);
+                       }
+                       write_data(pbpctl_dev, NORMAL_STATE_PWRON);
+                       if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER)
+                               msec_delay_bp(DFLT_PWRON_DELAY);
+                       else
+                               msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+                       if (pbpctl_dev->bp_caps & BP_DIS_CAP) {
+                               write_data(pbpctl_dev, DIS_BYPASS_CAP);
+                               msec_delay_bp(BYPASS_CAP_DELAY);
+                       }
+                       if (pbpctl_dev->bp_caps & TAP_DIS_CAP) {
+                               write_data(pbpctl_dev, DIS_TAP_CAP);
+                               msec_delay_bp(BYPASS_CAP_DELAY);
+                       }
+                       return 0;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int std_nic_off(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & STD_NIC_CAP) {
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) {
+                       write_data_int(pbpctl_dev, PWROFF_BYPASS_ON_INT);
+                       msec_delay_bp(BYPASS_DELAY_INT);
+                       return BP_OK;
+               }
+               if (pbpctl_dev->bp_ext_ver >= 0x8) {
+                       write_data(pbpctl_dev, STD_NIC_OFF);
+                       msec_delay_bp(BYPASS_CAP_DELAY);
+                       return BP_OK;
+               }
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) {
+                               write_data(pbpctl_dev, TAP_STATE_PWRON);
+                               msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+                       }
+                       if (pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) {
+                               write_data(pbpctl_dev, BYPASS_STATE_PWRON);
+                               if (pbpctl_dev->bp_ext_ver > PXG2BPI_VER)
+                                       msec_delay_bp(LATCH_DELAY +
+                                                     EEPROM_WR_DELAY);
+                               else
+                                       msec_delay_bp(DFLT_PWRON_DELAY);
+                       }
+                       if (pbpctl_dev->bp_caps & TAP_DIS_CAP) {
+                               write_data(pbpctl_dev, EN_TAP_CAP);
+                               msec_delay_bp(BYPASS_CAP_DELAY);
+                       }
+                       if (pbpctl_dev->bp_caps & DISC_DIS_CAP) {
+                               write_data(pbpctl_dev, EN_DISC_CAP);
+                               msec_delay_bp(BYPASS_CAP_DELAY);
+                       }
+                       if (pbpctl_dev->bp_caps & BP_DIS_CAP) {
+                               write_data(pbpctl_dev, EN_BYPASS_CAP);
+                               msec_delay_bp(BYPASS_CAP_DELAY);
+                       }
+                       return 0;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int wdt_time_left(bpctl_dev_t *pbpctl_dev)
+ {
+       /* unsigned long curr_time=((long long)(jiffies*1000))/HZ, delta_time=0,wdt_on_time=((long long)(pbpctl_dev->bypass_wdt_on_time*1000))/HZ; */
+       unsigned long curr_time = jiffies, delta_time = 0, wdt_on_time =
+           pbpctl_dev->bypass_wdt_on_time, delta_time_msec = 0;
+       int time_left = 0;
+       switch (pbpctl_dev->wdt_status) {
+       case WDT_STATUS_DIS:
+               time_left = 0;
+               break;
+       case WDT_STATUS_EN:
+               delta_time =
+                   (curr_time >=
+                    wdt_on_time) ? (curr_time - wdt_on_time) : (~wdt_on_time +
+                                                                curr_time);
+               delta_time_msec = jiffies_to_msecs(delta_time);
+               time_left = pbpctl_dev->bypass_timer_interval - delta_time_msec;
+               if (time_left < 0) {
+                       time_left = -1;
+                       pbpctl_dev->wdt_status = WDT_STATUS_EXP;
+               }
+               break;
+       case WDT_STATUS_EXP:
+               time_left = -1;
+               break;
+       }
+       return time_left;
+ }
+ static int wdt_timer(bpctl_dev_t *pbpctl_dev, int *time_left)
+ {
+       int ret = 0;
+       if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
+               {
+                       if (pbpctl_dev->wdt_status == WDT_STATUS_UNKNOWN)
+                               ret = BP_NOT_CAP;
+                       else
+                               *time_left = wdt_time_left(pbpctl_dev);
+               }
+       } else
+               ret = BP_NOT_CAP;
+       return ret;
+ }
+ static int wdt_timer_reload(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if ((pbpctl_dev->bp_caps & WD_CTL_CAP) &&
+           (pbpctl_dev->wdt_status != WDT_STATUS_UNKNOWN)) {
+               if (pbpctl_dev->wdt_status == WDT_STATUS_DIS)
+                       return 0;
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER)
+                       ret = wdt_pulse(pbpctl_dev);
+               else if (INTEL_IF_SERIES(pbpctl_dev->subdevice))
+                       ret = wdt_pulse_int(pbpctl_dev);
+               else
+                       ret = send_wdt_pulse(pbpctl_dev);
+               /* if (ret==-1)
+                   mod_timer(&pbpctl_dev->bp_timer, jiffies+1);*/
+               return 1;
+       }
+       return BP_NOT_CAP;
+ }
+ static void wd_reset_timer(unsigned long param)
+ {
+       bpctl_dev_t *pbpctl_dev = (bpctl_dev_t *) param;
+ #ifdef BP_SELF_TEST
+       struct sk_buff *skb_tmp;
+ #endif
+       if ((pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) &&
+           ((atomic_read(&pbpctl_dev->wdt_busy)) == 1)) {
+               mod_timer(&pbpctl_dev->bp_timer, jiffies + 1);
+               return;
+       }
+ #ifdef BP_SELF_TEST
+       if (pbpctl_dev->bp_self_test_flag == 1) {
+               skb_tmp = dev_alloc_skb(BPTEST_DATA_LEN + 2);
+               if ((skb_tmp) && (pbpctl_dev->ndev) && (pbpctl_dev->bp_tx_data)) {
+                       memcpy(skb_put(skb_tmp, BPTEST_DATA_LEN),
+                              pbpctl_dev->bp_tx_data, BPTEST_DATA_LEN);
+                       skb_tmp->dev = pbpctl_dev->ndev;
+                       skb_tmp->protocol =
+                           eth_type_trans(skb_tmp, pbpctl_dev->ndev);
+                       skb_tmp->ip_summed = CHECKSUM_UNNECESSARY;
+                       netif_receive_skb(skb_tmp);
+                       goto bp_timer_reload;
+                       return;
+               }
+       }
+ #endif
+       wdt_timer_reload(pbpctl_dev);
+ #ifdef BP_SELF_TEST
+  bp_timer_reload:
+ #endif
+       if (pbpctl_dev->reset_time) {
+               mod_timer(&pbpctl_dev->bp_timer,
+                         jiffies + (HZ * pbpctl_dev->reset_time) / 1000);
+       }
+ }
+ /*WAIT_AT_PWRUP 0x80   */
+ int bp_wait_at_pwup_en(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) {
+                       write_data(pbpctl_dev, BP_WAIT_AT_PWUP_EN);
+                       msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+                       return BP_OK;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ /*DIS_WAIT_AT_PWRUP       0x81 */
+ int bp_wait_at_pwup_dis(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) {
+                       write_data(pbpctl_dev, BP_WAIT_AT_PWUP_DIS);
+                       msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+                       return BP_OK;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ /*EN_HW_RESET  0x82   */
+ int bp_hw_reset_en(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) {
+                       write_data(pbpctl_dev, BP_HW_RESET_EN);
+                       msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+                       return BP_OK;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ /*DIS_HW_RESET             0x83   */
+ int bp_hw_reset_dis(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) {
+                       write_data(pbpctl_dev, BP_HW_RESET_DIS);
+                       msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY);
+                       return BP_OK;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int wdt_exp_mode(bpctl_dev_t *pbpctl_dev, int mode)
+ {
+       uint32_t status_reg = 0, status_reg1 = 0;
+       if ((pbpctl_dev->bp_caps & (TAP_STATUS_CAP | DISC_CAP)) &&
+           (pbpctl_dev->bp_caps & BP_CAP)) {
+               if (pbpctl_dev->bp_ext_ver >= PXE2TBPI_VER) {
+                       if ((pbpctl_dev->bp_ext_ver >= 0x8) &&
+                           (mode == 2) && (pbpctl_dev->bp_caps & DISC_CAP)) {
+                               status_reg1 =
+                                   read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR);
+                               if (!(status_reg1 & WDTE_DISC_BPN_MASK))
+                                       write_reg(pbpctl_dev,
+                                                 status_reg1 |
+                                                 WDTE_DISC_BPN_MASK,
+                                                 STATUS_DISC_REG_ADDR);
+                               return BP_OK;
+                       }
+               }
+               status_reg = read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR);
+               if ((mode == 0) && (pbpctl_dev->bp_caps & BP_CAP)) {
+                       if (pbpctl_dev->bp_ext_ver >= 0x8) {
+                               status_reg1 =
+                                   read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR);
+                               if (status_reg1 & WDTE_DISC_BPN_MASK)
+                                       write_reg(pbpctl_dev,
+                                                 status_reg1 &
+                                                 ~WDTE_DISC_BPN_MASK,
+                                                 STATUS_DISC_REG_ADDR);
+                       }
+                       if (status_reg & WDTE_TAP_BPN_MASK)
+                               write_reg(pbpctl_dev,
+                                         status_reg & ~WDTE_TAP_BPN_MASK,
+                                         STATUS_TAP_REG_ADDR);
+                       return BP_OK;
+               } else if ((mode == 1) && (pbpctl_dev->bp_caps & TAP_CAP)) {
+                       if (!(status_reg & WDTE_TAP_BPN_MASK))
+                               write_reg(pbpctl_dev,
+                                         status_reg | WDTE_TAP_BPN_MASK,
+                                         STATUS_TAP_REG_ADDR);
+                       /*else return BP_NOT_CAP; */
+                       return BP_OK;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int bypass_fw_ver(bpctl_dev_t *pbpctl_dev)
+ {
+       if (is_bypass_fn(pbpctl_dev))
+               return read_reg(pbpctl_dev, VER_REG_ADDR);
+       else
+               return BP_NOT_CAP;
+ }
+ int bypass_sign_check(bpctl_dev_t *pbpctl_dev)
+ {
+       if (is_bypass_fn(pbpctl_dev))
+               return (((read_reg(pbpctl_dev, PIC_SIGN_REG_ADDR)) ==
+                        PIC_SIGN_VALUE) ? 1 : 0);
+       else
+               return BP_NOT_CAP;
+ }
+ static int tx_status(bpctl_dev_t *pbpctl_dev)
+ {
+       uint32_t ctrl = 0;
+       bpctl_dev_t *pbpctl_dev_m;
+       if ((is_bypass_fn(pbpctl_dev)) == 1)
+               pbpctl_dev_m = pbpctl_dev;
+       else
+               pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
+       if (pbpctl_dev_m == NULL)
+               return BP_NOT_CAP;
+       if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
+               ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL);
+               if (pbpctl_dev->bp_i80)
+                       return ((ctrl & BPCTLI_CTRL_SWDPIN1) != 0 ? 0 : 1);
+               if (pbpctl_dev->bp_540) {
+                       ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+                       return ((ctrl & BP10G_SDP1_DATA) != 0 ? 0 : 1);
+               }
+       }
+       if (pbpctl_dev->bp_caps & TX_CTL_CAP) {
+               if (PEG5_IF_SERIES(pbpctl_dev->subdevice)) {
+                       uint16_t mii_reg;
+                       if (!
+                           (bp75_read_phy_reg
+                            (pbpctl_dev, BPCTLI_PHY_CONTROL, &mii_reg))) {
+                               if (mii_reg & BPCTLI_MII_CR_POWER_DOWN)
+                                       return 0;
+                               else
+                                       return 1;
+                       }
+                       return -1;
+               }
+               if (pbpctl_dev->bp_10g9) {
+                       return ((BP10G_READ_REG(pbpctl_dev, ESDP) &
+                                BP10G_SDP3_DATA) != 0 ? 0 : 1);
+               } else if (pbpctl_dev->bp_fiber5) {
+                       ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+                       if (ctrl & BPCTLI_CTRL_EXT_SDP6_DATA)
+                               return 0;
+                       return 1;
+               } else if (pbpctl_dev->bp_10gb) {
+                       ctrl = BP10GB_READ_REG(pbpctl_dev, MISC_REG_GPIO);
+                       BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_GPIO,
+                                        (ctrl | BP10GB_GPIO0_OE_P1) &
+                                        ~(BP10GB_GPIO0_SET_P1 |
+                                          BP10GB_GPIO0_CLR_P1));
+                       if ((pbpctl_dev->func == 1) || (pbpctl_dev->func == 3))
+                               return (((BP10GB_READ_REG
+                                         (pbpctl_dev,
+                                          MISC_REG_GPIO)) & BP10GB_GPIO0_P1) !=
+                                       0 ? 0 : 1);
+                       else
+                               return (((BP10GB_READ_REG
+                                         (pbpctl_dev,
+                                          MISC_REG_GPIO)) & BP10GB_GPIO0_P0) !=
+                                       0 ? 0 : 1);
+               }
+               if (!pbpctl_dev->bp_10g) {
+                       ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL);
+                       if (pbpctl_dev->bp_i80)
+                               return ((ctrl & BPCTLI_CTRL_SWDPIN1) !=
+                                       0 ? 0 : 1);
+                       if (pbpctl_dev->bp_540) {
+                               ctrl = BP10G_READ_REG(pbpctl_dev, ESDP);
+                               return ((ctrl & BP10G_SDP1_DATA) != 0 ? 0 : 1);
+                       }
+                       return ((ctrl & BPCTLI_CTRL_SWDPIN0) != 0 ? 0 : 1);
+               } else
+                       return ((BP10G_READ_REG(pbpctl_dev, ESDP) &
+                                BP10G_SDP0_DATA) != 0 ? 0 : 1);
+       }
+       return BP_NOT_CAP;
+ }
+ static int bp_force_link_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (DBI_IF_SERIES(pbpctl_dev->subdevice)) {
+               if ((pbpctl_dev->bp_10g) || (pbpctl_dev->bp_10g9)) {
+                       return ((BP10G_READ_REG(pbpctl_dev, ESDP) &
+                                BP10G_SDP1_DIR) != 0 ? 1 : 0);
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int bypass_from_last_read(bpctl_dev_t *pbpctl_dev)
+ {
+       uint32_t ctrl_ext = 0;
+       bpctl_dev_t *pbpctl_dev_b = NULL;
+       if ((pbpctl_dev->bp_caps & SW_CTL_CAP)
+           && (pbpctl_dev_b = get_status_port_fn(pbpctl_dev))) {
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev_b, CTRL_EXT);
+               BPCTL_BP_WRITE_REG(pbpctl_dev_b, CTRL_EXT,
+                                  (ctrl_ext & ~BPCTLI_CTRL_EXT_SDP7_DIR));
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev_b, CTRL_EXT);
+               if (ctrl_ext & BPCTLI_CTRL_EXT_SDP7_DATA)
+                       return 0;
+               return 1;
+       } else
+               return BP_NOT_CAP;
+ }
+ int bypass_status_clear(bpctl_dev_t *pbpctl_dev)
+ {
+       bpctl_dev_t *pbpctl_dev_b = NULL;
+       if ((pbpctl_dev->bp_caps & SW_CTL_CAP)
+           && (pbpctl_dev_b = get_status_port_fn(pbpctl_dev))) {
+               send_bypass_clear_pulse(pbpctl_dev_b, 1);
+               return 0;
+       } else
+               return BP_NOT_CAP;
+ }
+ int bypass_flag_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if ((pbpctl_dev->bp_caps & BP_CAP)) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) &
+                                 BYPASS_FLAG_MASK) ==
+                                BYPASS_FLAG_MASK) ? 1 : 0);
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int bypass_flag_status_clear(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & BP_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       uint32_t status_reg = 0;
+                       status_reg = read_reg(pbpctl_dev, STATUS_REG_ADDR);
+                       write_reg(pbpctl_dev, status_reg & ~BYPASS_FLAG_MASK,
+                                 STATUS_REG_ADDR);
+                       return 0;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int bypass_change_status(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       if (pbpctl_dev->bp_caps & BP_STATUS_CHANGE_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= 0x8) {
+                       ret = bypass_flag_status(pbpctl_dev);
+                       bypass_flag_status_clear(pbpctl_dev);
+               } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       ret = bypass_flag_status(pbpctl_dev);
+                       bypass_flag_status_clear(pbpctl_dev);
+               } else {
+                       ret = bypass_from_last_read(pbpctl_dev);
+                       bypass_status_clear(pbpctl_dev);
+               }
+       }
+       return ret;
+ }
+ int bypass_off_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & BP_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) &
+                                 BYPASS_OFF_MASK) == BYPASS_OFF_MASK) ? 1 : 0);
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ static int bypass_status(bpctl_dev_t *pbpctl_dev)
+ {
+       u32 ctrl_ext = 0;
+       if (pbpctl_dev->bp_caps & BP_CAP) {
+               bpctl_dev_t *pbpctl_dev_b = NULL;
+               if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev)))
+                       return BP_NOT_CAP;
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) {
+                       if (!pbpctl_dev->bp_status_un)
+                               return (((BPCTL_READ_REG
+                                         (pbpctl_dev_b,
+                                          CTRL_EXT)) &
+                                        BPCTLI_CTRL_EXT_SDP7_DATA) !=
+                                       0 ? 1 : 0);
+                       else
+                               return BP_NOT_CAP;
+               }
+               if (pbpctl_dev->bp_ext_ver >= 0x8) {
+                       if (pbpctl_dev->bp_10g9) {
+                               ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, I2CCTL);
+                               BP10G_WRITE_REG(pbpctl_dev_b, I2CCTL,
+                                               (ctrl_ext | BP10G_I2C_CLK_OUT));
+                               return ((BP10G_READ_REG(pbpctl_dev_b, I2CCTL) &
+                                        BP10G_I2C_CLK_IN) != 0 ? 0 : 1);
+                       } else if (pbpctl_dev->bp_540) {
+                               return (((BP10G_READ_REG(pbpctl_dev_b, ESDP)) &
+                                        BP10G_SDP0_DATA) != 0 ? 0 : 1);
+                       }
+                       else if ((pbpctl_dev->bp_fiber5)
+                                || (pbpctl_dev->bp_i80)) {
+                               return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL)) &
+                                        BPCTLI_CTRL_SWDPIN0) != 0 ? 0 : 1);
+                       } else if (pbpctl_dev->bp_10gb) {
+                               ctrl_ext =
+                                   BP10GB_READ_REG(pbpctl_dev, MISC_REG_GPIO);
+                               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_GPIO,
+                                                (ctrl_ext | BP10GB_GPIO3_OE_P0)
+                                                & ~(BP10GB_GPIO3_SET_P0 |
+                                                    BP10GB_GPIO3_CLR_P0));
+                               return (((BP10GB_READ_REG
+                                         (pbpctl_dev,
+                                          MISC_REG_GPIO)) & BP10GB_GPIO3_P0) !=
+                                       0 ? 0 : 1);
+                       }
+                       else if (!pbpctl_dev->bp_10g)
+                               return (((BPCTL_READ_REG
+                                         (pbpctl_dev_b,
+                                          CTRL_EXT)) &
+                                        BPCTLI_CTRL_EXT_SDP7_DATA) !=
+                                       0 ? 0 : 1);
+                       else {
+                               ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, EODSDP);
+                               BP10G_WRITE_REG(pbpctl_dev_b, EODSDP,
+                                               (ctrl_ext |
+                                                BP10G_SDP7_DATA_OUT));
+                               return ((BP10G_READ_REG(pbpctl_dev_b, EODSDP) &
+                                        BP10G_SDP7_DATA_IN) != 0 ? 0 : 1);
+                       }
+               } else if (pbpctl_dev->media_type == bp_copper) {
+                       return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL)) &
+                                BPCTLI_CTRL_SWDPIN1) != 0 ? 1 : 0);
+               } else {
+                       if ((bypass_status_clear(pbpctl_dev)) >= 0)
+                               return bypass_from_last_read(pbpctl_dev);
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int default_pwron_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) {
+                       if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                               return ((((read_reg
+                                          (pbpctl_dev,
+                                           STATUS_REG_ADDR)) & DFLT_PWRON_MASK)
+                                        == DFLT_PWRON_MASK) ? 0 : 1);
+                       }
+               }               /*else if ((!pbpctl_dev->bp_caps&BP_DIS_CAP)&&
+                                  (pbpctl_dev->bp_caps&BP_PWUP_ON_CAP))
+                                  return 1; */
+       }
+       return BP_NOT_CAP;
+ }
+ static int default_pwroff_status(bpctl_dev_t *pbpctl_dev)
+ {
+       /*if ((!pbpctl_dev->bp_caps&BP_DIS_CAP)&&
+          (pbpctl_dev->bp_caps&BP_PWOFF_ON_CAP))
+          return 1; */
+       if ((pbpctl_dev->bp_caps & SW_CTL_CAP)
+           && (pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP)) {
+               return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) &
+                         DFLT_PWROFF_MASK) == DFLT_PWROFF_MASK) ? 0 : 1);
+       }
+       return BP_NOT_CAP;
+ }
+ int dis_bypass_cap_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & BP_DIS_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) &
+                                 DIS_BYPASS_CAP_MASK) ==
+                                DIS_BYPASS_CAP_MASK) ? 1 : 0);
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int cmd_en_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) &
+                                 CMND_EN_MASK) == CMND_EN_MASK) ? 1 : 0);
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int wdt_en_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) &
+                                 WDT_EN_MASK) == WDT_EN_MASK) ? 1 : 0);
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int wdt_programmed(bpctl_dev_t *pbpctl_dev, int *timeout)
+ {
+       int ret = 0;
+       if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       if ((read_reg(pbpctl_dev, STATUS_REG_ADDR)) &
+                           WDT_EN_MASK) {
+                               u8 wdt_val;
+                               wdt_val = read_reg(pbpctl_dev, WDT_REG_ADDR);
+                               *timeout = (1 << wdt_val) * 100;
+                       } else
+                               *timeout = 0;
+               } else {
+                       int curr_wdt_status = pbpctl_dev->wdt_status;
+                       if (curr_wdt_status == WDT_STATUS_UNKNOWN)
+                               *timeout = -1;
+                       else
+                               *timeout =
+                                   curr_wdt_status ==
+                                   0 ? 0 : pbpctl_dev->bypass_timer_interval;
+               };
+       } else
+               ret = BP_NOT_CAP;
+       return ret;
+ }
+ int bypass_support(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) {
+                       ret =
+                           ((((read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR)) &
+                              BYPASS_SUPPORT_MASK) ==
+                             BYPASS_SUPPORT_MASK) ? 1 : 0);
+               } else if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER)
+                       ret = 1;
+       } else
+               ret = BP_NOT_CAP;
+       return ret;
+ }
+ int tap_support(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) {
+                       ret =
+                           ((((read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR)) &
+                              TAP_SUPPORT_MASK) == TAP_SUPPORT_MASK) ? 1 : 0);
+               } else if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER)
+                       ret = 0;
+       } else
+               ret = BP_NOT_CAP;
+       return ret;
+ }
+ int normal_support(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) {
+                       ret =
+                           ((((read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR)) &
+                              NORMAL_UNSUPPORT_MASK) ==
+                             NORMAL_UNSUPPORT_MASK) ? 0 : 1);
+               } else
+                       ret = 1;
+       };
+       return ret;
+ }
+ int get_bp_prod_caps(bpctl_dev_t *pbpctl_dev)
+ {
+       if ((pbpctl_dev->bp_caps & SW_CTL_CAP) &&
+           (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER))
+               return read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR);
+       return BP_NOT_CAP;
+ }
+ int tap_flag_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & TAP_STATUS_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)
+                       return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) &
+                                 TAP_FLAG_MASK) == TAP_FLAG_MASK) ? 1 : 0);
+       }
+       return BP_NOT_CAP;
+ }
+ int tap_flag_status_clear(bpctl_dev_t *pbpctl_dev)
+ {
+       uint32_t status_reg = 0;
+       if (pbpctl_dev->bp_caps & TAP_STATUS_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) {
+                       status_reg = read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR);
+                       write_reg(pbpctl_dev, status_reg & ~TAP_FLAG_MASK,
+                                 STATUS_TAP_REG_ADDR);
+                       return 0;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int tap_change_status(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) {
+               if (pbpctl_dev->bp_caps & TAP_CAP) {
+                       if (pbpctl_dev->bp_caps & BP_CAP) {
+                               ret = tap_flag_status(pbpctl_dev);
+                               tap_flag_status_clear(pbpctl_dev);
+                       } else {
+                               ret = bypass_from_last_read(pbpctl_dev);
+                               bypass_status_clear(pbpctl_dev);
+                       }
+               }
+       }
+       return ret;
+ }
+ int tap_off_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & TAP_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)
+                       return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) &
+                                 TAP_OFF_MASK) == TAP_OFF_MASK) ? 1 : 0);
+       }
+       return BP_NOT_CAP;
+ }
+ int tap_status(bpctl_dev_t *pbpctl_dev)
+ {
+       u32 ctrl_ext = 0;
+       if (pbpctl_dev->bp_caps & TAP_CAP) {
+               bpctl_dev_t *pbpctl_dev_b = NULL;
+               if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev)))
+                       return BP_NOT_CAP;
+               if (pbpctl_dev->bp_ext_ver >= 0x8) {
+                       if (!pbpctl_dev->bp_10g)
+                               return (((BPCTL_READ_REG
+                                         (pbpctl_dev_b,
+                                          CTRL_EXT)) &
+                                        BPCTLI_CTRL_EXT_SDP6_DATA) !=
+                                       0 ? 0 : 1);
+                       else {
+                               ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, EODSDP);
+                               BP10G_WRITE_REG(pbpctl_dev_b, EODSDP,
+                                               (ctrl_ext |
+                                                BP10G_SDP6_DATA_OUT));
+                               return ((BP10G_READ_REG(pbpctl_dev_b, EODSDP) &
+                                        BP10G_SDP6_DATA_IN) != 0 ? 0 : 1);
+                       }
+               } else if (pbpctl_dev->media_type == bp_copper)
+                       return (((BPCTL_READ_REG(pbpctl_dev, CTRL)) &
+                                BPCTLI_CTRL_SWDPIN0) != 0 ? 1 : 0);
+               else {
+                       if ((bypass_status_clear(pbpctl_dev)) >= 0)
+                               return bypass_from_last_read(pbpctl_dev);
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int default_pwron_tap_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)
+                       return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) &
+                                 DFLT_PWRON_TAP_MASK) ==
+                                DFLT_PWRON_TAP_MASK) ? 1 : 0);
+       }
+       return BP_NOT_CAP;
+ }
+ int dis_tap_cap_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)
+                       return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) &
+                                 DIS_TAP_CAP_MASK) ==
+                                DIS_TAP_CAP_MASK) ? 1 : 0);
+       }
+       return BP_NOT_CAP;
+ }
+ int disc_flag_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & DISC_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= 0x8)
+                       return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) &
+                                 DISC_FLAG_MASK) == DISC_FLAG_MASK) ? 1 : 0);
+       }
+       return BP_NOT_CAP;
+ }
+ int disc_flag_status_clear(bpctl_dev_t *pbpctl_dev)
+ {
+       uint32_t status_reg = 0;
+       if (pbpctl_dev->bp_caps & DISC_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= 0x8) {
+                       status_reg = read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR);
+                       write_reg(pbpctl_dev, status_reg & ~DISC_FLAG_MASK,
+                                 STATUS_DISC_REG_ADDR);
+                       return BP_OK;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int disc_change_status(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       if (pbpctl_dev->bp_caps & DISC_CAP) {
+               ret = disc_flag_status(pbpctl_dev);
+               disc_flag_status_clear(pbpctl_dev);
+               return ret;
+       }
+       return BP_NOT_CAP;
+ }
+ int disc_off_status(bpctl_dev_t *pbpctl_dev)
+ {
+       bpctl_dev_t *pbpctl_dev_b = NULL;
+       u32 ctrl_ext = 0;
+       if (pbpctl_dev->bp_caps & DISC_CAP) {
+               if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev)))
+                       return BP_NOT_CAP;
+               if (DISCF_IF_SERIES(pbpctl_dev->subdevice))
+                       return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) &
+                                 DISC_OFF_MASK) == DISC_OFF_MASK) ? 1 : 0);
+               if (pbpctl_dev->bp_i80) {
+                       return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL_EXT)) &
+                                BPCTLI_CTRL_EXT_SDP6_DATA) != 0 ? 1 : 0);
+               }
+               if (pbpctl_dev->bp_540) {
+                       ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, ESDP);
+                       return ((BP10G_READ_REG(pbpctl_dev_b, ESDP) &
+                                BP10G_SDP2_DATA) != 0 ? 1 : 0);
+               }
+               if (pbpctl_dev->media_type == bp_copper) {
+ #if 0
+                       return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) &
+                                 DISC_OFF_MASK) == DISC_OFF_MASK) ? 1 : 0);
+ #endif
+                       if (!pbpctl_dev->bp_10g)
+                               return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL)) &
+                                        BPCTLI_CTRL_SWDPIN1) != 0 ? 1 : 0);
+                       else
+                               return ((BP10G_READ_REG(pbpctl_dev_b, ESDP) &
+                                        BP10G_SDP1_DATA) != 0 ? 1 : 0);
+               } else {
+                       if (pbpctl_dev->bp_10g9) {
+                               ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, I2CCTL);
+                               BP10G_WRITE_REG(pbpctl_dev_b, I2CCTL,
+                                               (ctrl_ext |
+                                                BP10G_I2C_DATA_OUT));
+                               return ((BP10G_READ_REG(pbpctl_dev_b, I2CCTL) &
+                                        BP10G_I2C_DATA_IN) != 0 ? 1 : 0);
+                       } else if (pbpctl_dev->bp_fiber5) {
+                               return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL)) &
+                                        BPCTLI_CTRL_SWDPIN1) != 0 ? 1 : 0);
+                       } else if (pbpctl_dev->bp_10gb) {
+                               ctrl_ext =
+                                   BP10GB_READ_REG(pbpctl_dev, MISC_REG_GPIO);
+                               BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_GPIO,
+                                                (ctrl_ext | BP10GB_GPIO3_OE_P1)
+                                                & ~(BP10GB_GPIO3_SET_P1 |
+                                                    BP10GB_GPIO3_CLR_P1));
+                               return (((BP10GB_READ_REG
+                                         (pbpctl_dev,
+                                          MISC_REG_GPIO)) & BP10GB_GPIO3_P1) !=
+                                       0 ? 1 : 0);
+                       }
+                       if (!pbpctl_dev->bp_10g) {
+                               return (((BPCTL_READ_REG
+                                         (pbpctl_dev_b,
+                                          CTRL_EXT)) &
+                                        BPCTLI_CTRL_EXT_SDP6_DATA) !=
+                                       0 ? 1 : 0);
+                       } else {
+                               ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, EODSDP);
+                               BP10G_WRITE_REG(pbpctl_dev_b, EODSDP,
+                                               (ctrl_ext |
+                                                BP10G_SDP6_DATA_OUT));
+                               return (((BP10G_READ_REG(pbpctl_dev_b, EODSDP))
+                                        & BP10G_SDP6_DATA_IN) != 0 ? 1 : 0);
+                       }
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ static int disc_status(bpctl_dev_t *pbpctl_dev)
+ {
+       int ctrl = 0;
+       if (pbpctl_dev->bp_caps & DISC_CAP) {
+               if ((ctrl = disc_off_status(pbpctl_dev)) < 0)
+                       return ctrl;
+               return ((ctrl == 0) ? 1 : 0);
+       }
+       return BP_NOT_CAP;
+ }
+ int default_pwron_disc_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= 0x8)
+                       return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) &
+                                 DFLT_PWRON_DISC_MASK) ==
+                                DFLT_PWRON_DISC_MASK) ? 1 : 0);
+       }
+       return BP_NOT_CAP;
+ }
+ int dis_disc_cap_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & DIS_DISC_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= 0x8)
+                       return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) &
+                                 DIS_DISC_CAP_MASK) ==
+                                DIS_DISC_CAP_MASK) ? 1 : 0);
+       }
+       return BP_NOT_CAP;
+ }
+ int disc_port_status(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       bpctl_dev_t *pbpctl_dev_m;
+       if ((is_bypass_fn(pbpctl_dev)) == 1)
+               pbpctl_dev_m = pbpctl_dev;
+       else
+               pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
+       if (pbpctl_dev_m == NULL)
+               return BP_NOT_CAP;
+       if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
+               if (is_bypass_fn(pbpctl_dev) == 1) {
+                       return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) &
+                                 TX_DISA_MASK) == TX_DISA_MASK) ? 1 : 0);
+               } else
+                       return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) &
+                                 TX_DISB_MASK) == TX_DISB_MASK) ? 1 : 0);
+       }
+       return ret;
+ }
+ int default_pwron_disc_port_status(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       bpctl_dev_t *pbpctl_dev_m;
+       if ((is_bypass_fn(pbpctl_dev)) == 1)
+               pbpctl_dev_m = pbpctl_dev;
+       else
+               pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
+       if (pbpctl_dev_m == NULL)
+               return BP_NOT_CAP;
+       if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
+               if (is_bypass_fn(pbpctl_dev) == 1)
+                       return ret;
+               /*  return((((read_reg(pbpctl_dev,STATUS_TAP_REG_ADDR)) & TX_DISA_MASK)==TX_DISA_MASK)?1:0); */
+               else
+                       return ret;
+               /*   return((((read_reg(pbpctl_dev,STATUS_TAP_REG_ADDR)) & TX_DISA_MASK)==TX_DISA_MASK)?1:0); */
+       }
+       return ret;
+ }
+ int wdt_exp_mode_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver <= PXG2BPI_VER)
+                       return 0;       /* bypass mode */
+               else if (pbpctl_dev->bp_ext_ver == PXG2TBPI_VER)
+                       return 1;       /* tap mode */
+               else if (pbpctl_dev->bp_ext_ver >= PXE2TBPI_VER) {
+                       if (pbpctl_dev->bp_ext_ver >= 0x8) {
+                               if (((read_reg
+                                     (pbpctl_dev,
+                                      STATUS_DISC_REG_ADDR)) &
+                                    WDTE_DISC_BPN_MASK) == WDTE_DISC_BPN_MASK)
+                                       return 2;
+                       }
+                       return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) &
+                                 WDTE_TAP_BPN_MASK) ==
+                                WDTE_TAP_BPN_MASK) ? 1 : 0);
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ int tpl2_flag_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) {
+               return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) &
+                         TPL2_FLAG_MASK) == TPL2_FLAG_MASK) ? 1 : 0);
+       }
+       return BP_NOT_CAP;
+ }
+ int tpl_hw_status(bpctl_dev_t *pbpctl_dev)
+ {
+       bpctl_dev_t *pbpctl_dev_b = NULL;
+       if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev)))
+               return BP_NOT_CAP;
+       if (TPL_IF_SERIES(pbpctl_dev->subdevice))
+               return (((BPCTL_READ_REG(pbpctl_dev, CTRL)) &
+                        BPCTLI_CTRL_SWDPIN0) != 0 ? 1 : 0);
+       return BP_NOT_CAP;
+ }
+ int bp_wait_at_pwup_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= 0x8)
+                       return ((((read_reg(pbpctl_dev, CONT_CONFIG_REG_ADDR)) &
+                                 WAIT_AT_PWUP_MASK) ==
+                                WAIT_AT_PWUP_MASK) ? 1 : 0);
+       }
+       return BP_NOT_CAP;
+ }
+ int bp_hw_reset_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               if (pbpctl_dev->bp_ext_ver >= 0x8)
+                       return ((((read_reg(pbpctl_dev, CONT_CONFIG_REG_ADDR)) &
+                                 EN_HW_RESET_MASK) ==
+                                EN_HW_RESET_MASK) ? 1 : 0);
+       }
+       return BP_NOT_CAP;
+ }
+ int std_nic_status(bpctl_dev_t *pbpctl_dev)
+ {
+       int status_val = 0;
+       if (pbpctl_dev->bp_caps & STD_NIC_CAP) {
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice))
+                       return BP_NOT_CAP;
+               if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) {
+                       return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) &
+                                 STD_NIC_ON_MASK) == STD_NIC_ON_MASK) ? 1 : 0);
+               }
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       if (pbpctl_dev->bp_caps & BP_CAP) {
+                               status_val =
+                                   read_reg(pbpctl_dev, STATUS_REG_ADDR);
+                               if (((!(status_val & WDT_EN_MASK))
+                                    && ((status_val & STD_NIC_MASK) ==
+                                        STD_NIC_MASK)))
+                                       status_val = 1;
+                               else
+                                       return 0;
+                       }
+                       if (pbpctl_dev->bp_caps & TAP_CAP) {
+                               status_val =
+                                   read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR);
+                               if ((status_val & STD_NIC_TAP_MASK) ==
+                                   STD_NIC_TAP_MASK)
+                                       status_val = 1;
+                               else
+                                       return 0;
+                       }
+                       if (pbpctl_dev->bp_caps & TAP_CAP) {
+                               if ((disc_off_status(pbpctl_dev)))
+                                       status_val = 1;
+                               else
+                                       return 0;
+                       }
+                       return status_val;
+               }
+       }
+       return BP_NOT_CAP;
+ }
+ /******************************************************/
+ /**************SW_INIT*********************************/
+ /******************************************************/
+ void bypass_caps_init(bpctl_dev_t *pbpctl_dev)
+ {
+       u_int32_t ctrl_ext = 0;
+       bpctl_dev_t *pbpctl_dev_m = NULL;
+ #ifdef BYPASS_DEBUG
+       int ret = 0;
+       if (!(INTEL_IF_SERIES(adapter->bp_device_block.subdevice))) {
+               ret = read_reg(pbpctl_dev, VER_REG_ADDR);
+               printk("VER_REG reg1=%x\n", ret);
+               ret = read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR);
+               printk("PRODUCT_CAP reg=%x\n", ret);
+               ret = read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR);
+               printk("STATUS_TAP reg1=%x\n", ret);
+               ret = read_reg(pbpctl_dev, 0x7);
+               printk("SIG_REG reg1=%x\n", ret);
+               ret = read_reg(pbpctl_dev, STATUS_REG_ADDR);
+               printk("STATUS_REG_ADDR=%x\n", ret);
+               ret = read_reg(pbpctl_dev, WDT_REG_ADDR);
+               printk("WDT_REG_ADDR=%x\n", ret);
+               ret = read_reg(pbpctl_dev, TMRL_REG_ADDR);
+               printk("TMRL_REG_ADDR=%x\n", ret);
+               ret = read_reg(pbpctl_dev, TMRH_REG_ADDR);
+               printk("TMRH_REG_ADDR=%x\n", ret);
+       }
+ #endif
+       if ((pbpctl_dev->bp_fiber5) || (pbpctl_dev->bp_10g9)) {
+               pbpctl_dev->media_type = bp_fiber;
+       } else if (pbpctl_dev->bp_10gb) {
+               if (BP10GB_CX4_SERIES(pbpctl_dev->subdevice))
+                       pbpctl_dev->media_type = bp_cx4;
+               else
+                       pbpctl_dev->media_type = bp_fiber;
+       }
+       else if (pbpctl_dev->bp_540)
+               pbpctl_dev->media_type = bp_none;
+       else if (!pbpctl_dev->bp_10g) {
+               ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
+               if ((ctrl_ext & BPCTLI_CTRL_EXT_LINK_MODE_MASK) == 0x0)
+                       pbpctl_dev->media_type = bp_copper;
+               else
+                       pbpctl_dev->media_type = bp_fiber;
+       } else {
+               if (BP10G_CX4_SERIES(pbpctl_dev->subdevice))
+                       pbpctl_dev->media_type = bp_cx4;
+               else
+                       pbpctl_dev->media_type = bp_fiber;
+       }
+       if (is_bypass_fn(pbpctl_dev)) {
+               pbpctl_dev->bp_caps |= BP_PWOFF_ON_CAP;
+               if (pbpctl_dev->media_type == bp_fiber)
+                       pbpctl_dev->bp_caps |=
+                           (TX_CTL_CAP | TX_STATUS_CAP | TPL_CAP);
+               if (TPL_IF_SERIES(pbpctl_dev->subdevice)) {
+                       pbpctl_dev->bp_caps |= TPL_CAP;
+               }
+               if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) {
+                       pbpctl_dev->bp_caps |=
+                           (BP_CAP | BP_STATUS_CAP | SW_CTL_CAP |
+                            BP_PWUP_ON_CAP | BP_PWUP_OFF_CAP | BP_PWOFF_OFF_CAP
+                            | WD_CTL_CAP | WD_STATUS_CAP | STD_NIC_CAP |
+                            WD_TIMEOUT_CAP);
+                       pbpctl_dev->bp_ext_ver = OLD_IF_VER;
+                       return;
+               }
+               if ((pbpctl_dev->bp_fw_ver == 0xff) &&
+                   OLD_IF_SERIES(pbpctl_dev->subdevice)) {
+                       pbpctl_dev->bp_caps |=
+                           (BP_CAP | BP_STATUS_CAP | BP_STATUS_CHANGE_CAP |
+                            SW_CTL_CAP | BP_PWUP_ON_CAP | WD_CTL_CAP |
+                            WD_STATUS_CAP | WD_TIMEOUT_CAP);
+                       pbpctl_dev->bp_ext_ver = OLD_IF_VER;
+                       return;
+               }
+               else {
+                       switch (pbpctl_dev->bp_fw_ver) {
+                       case BP_FW_VER_A0:
+                       case BP_FW_VER_A1:{
+                                       pbpctl_dev->bp_ext_ver =
+                                           (pbpctl_dev->
+                                            bp_fw_ver & EXT_VER_MASK);
+                                       break;
+                               }
+                       default:{
+                                       if ((bypass_sign_check(pbpctl_dev)) !=
+                                           1) {
+                                               pbpctl_dev->bp_caps = 0;
+                                               return;
+                                       }
+                                       pbpctl_dev->bp_ext_ver =
+                                           (pbpctl_dev->
+                                            bp_fw_ver & EXT_VER_MASK);
+                               }
+                       }
+               }
+               if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER)
+                       pbpctl_dev->bp_caps |=
+                           (BP_CAP | BP_STATUS_CAP | BP_STATUS_CHANGE_CAP |
+                            SW_CTL_CAP | BP_DIS_CAP | BP_DIS_STATUS_CAP |
+                            BP_PWUP_ON_CAP | BP_PWUP_OFF_CAP | BP_PWUP_CTL_CAP
+                            | WD_CTL_CAP | STD_NIC_CAP | WD_STATUS_CAP |
+                            WD_TIMEOUT_CAP);
+               else if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) {
+                       int cap_reg;
+                       pbpctl_dev->bp_caps |=
+                           (SW_CTL_CAP | WD_CTL_CAP | WD_STATUS_CAP |
+                            WD_TIMEOUT_CAP);
+                       cap_reg = get_bp_prod_caps(pbpctl_dev);
+                       if ((cap_reg & NORMAL_UNSUPPORT_MASK) ==
+                           NORMAL_UNSUPPORT_MASK)
+                               pbpctl_dev->bp_caps |= NIC_CAP_NEG;
+                       else
+                               pbpctl_dev->bp_caps |= STD_NIC_CAP;
+                       if ((normal_support(pbpctl_dev)) == 1)
+                               pbpctl_dev->bp_caps |= STD_NIC_CAP;
+                       else
+                               pbpctl_dev->bp_caps |= NIC_CAP_NEG;
+                       if ((cap_reg & BYPASS_SUPPORT_MASK) ==
+                           BYPASS_SUPPORT_MASK) {
+                               pbpctl_dev->bp_caps |=
+                                   (BP_CAP | BP_STATUS_CAP |
+                                    BP_STATUS_CHANGE_CAP | BP_DIS_CAP |
+                                    BP_DIS_STATUS_CAP | BP_PWUP_ON_CAP |
+                                    BP_PWUP_OFF_CAP | BP_PWUP_CTL_CAP);
+                               if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER7)
+                                       pbpctl_dev->bp_caps |=
+                                           BP_PWOFF_ON_CAP | BP_PWOFF_OFF_CAP |
+                                           BP_PWOFF_CTL_CAP;
+                       }
+                       if ((cap_reg & TAP_SUPPORT_MASK) == TAP_SUPPORT_MASK) {
+                               pbpctl_dev->bp_caps |=
+                                   (TAP_CAP | TAP_STATUS_CAP |
+                                    TAP_STATUS_CHANGE_CAP | TAP_DIS_CAP |
+                                    TAP_DIS_STATUS_CAP | TAP_PWUP_ON_CAP |
+                                    TAP_PWUP_OFF_CAP | TAP_PWUP_CTL_CAP);
+                       }
+                       if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) {
+                               if ((cap_reg & DISC_SUPPORT_MASK) ==
+                                   DISC_SUPPORT_MASK)
+                                       pbpctl_dev->bp_caps |=
+                                           (DISC_CAP | DISC_DIS_CAP |
+                                            DISC_PWUP_CTL_CAP);
+                               if ((cap_reg & TPL2_SUPPORT_MASK) ==
+                                   TPL2_SUPPORT_MASK) {
+                                       pbpctl_dev->bp_caps_ex |= TPL2_CAP_EX;
+                                       pbpctl_dev->bp_caps |= TPL_CAP;
+                                       pbpctl_dev->bp_tpl_flag =
+                                           tpl2_flag_status(pbpctl_dev);
+                               }
+                       }
+                       if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER9) {
+                               if ((cap_reg & DISC_PORT_SUPPORT_MASK) ==
+                                   DISC_PORT_SUPPORT_MASK) {
+                                       pbpctl_dev->bp_caps_ex |=
+                                           DISC_PORT_CAP_EX;
+                                       pbpctl_dev->bp_caps |=
+                                           (TX_CTL_CAP | TX_STATUS_CAP);
+                               }
+                       }
+               }
+               if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
+                       if ((read_reg(pbpctl_dev, STATUS_REG_ADDR)) &
+                           WDT_EN_MASK)
+                               pbpctl_dev->wdt_status = WDT_STATUS_EN;
+                       else
+                               pbpctl_dev->wdt_status = WDT_STATUS_DIS;
+               }
+       } else if ((P2BPFI_IF_SERIES(pbpctl_dev->subdevice)) ||
+                  (PEGF5_IF_SERIES(pbpctl_dev->subdevice)) ||
+                  (PEGF80_IF_SERIES(pbpctl_dev->subdevice)) ||
+                  (BP10G9_IF_SERIES(pbpctl_dev->subdevice))) {
+               pbpctl_dev->bp_caps |= (TX_CTL_CAP | TX_STATUS_CAP);
+       }
+       if ((pbpctl_dev->subdevice & 0xa00) == 0xa00)
+               pbpctl_dev->bp_caps |= (TX_CTL_CAP | TX_STATUS_CAP);
+       if (PEG5_IF_SERIES(pbpctl_dev->subdevice))
+               pbpctl_dev->bp_caps |= (TX_CTL_CAP | TX_STATUS_CAP);
+       if (BP10GB_IF_SERIES(pbpctl_dev->subdevice)) {
+               pbpctl_dev->bp_caps &= ~(TX_CTL_CAP | TX_STATUS_CAP);
+       }
+       pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
+       if (pbpctl_dev_m != NULL) {
+               int cap_reg = 0;
+               if (pbpctl_dev_m->bp_ext_ver >= 0x9) {
+                       cap_reg = get_bp_prod_caps(pbpctl_dev_m);
+                       if ((cap_reg & DISC_PORT_SUPPORT_MASK) ==
+                           DISC_PORT_SUPPORT_MASK)
+                               pbpctl_dev->bp_caps |=
+                                   (TX_CTL_CAP | TX_STATUS_CAP);
+                       pbpctl_dev->bp_caps_ex |= DISC_PORT_CAP_EX;
+               }
+       }
+ }
+ int bypass_off_init(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if ((ret = cmnd_on(pbpctl_dev)) < 0)
+               return ret;
+       if (INTEL_IF_SERIES(pbpctl_dev->subdevice))
+               return dis_bypass_cap(pbpctl_dev);
+       wdt_off(pbpctl_dev);
+       if (pbpctl_dev->bp_caps & BP_CAP)
+               bypass_off(pbpctl_dev);
+       if (pbpctl_dev->bp_caps & TAP_CAP)
+               tap_off(pbpctl_dev);
+       cmnd_off(pbpctl_dev);
+       return 0;
+ }
+ void remove_bypass_wd_auto(bpctl_dev_t *pbpctl_dev)
+ {
+ #ifdef BP_SELF_TEST
+       bpctl_dev_t *pbpctl_dev_sl = NULL;
+ #endif
+       if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
+               del_timer_sync(&pbpctl_dev->bp_timer);
+ #ifdef BP_SELF_TEST
+               pbpctl_dev_sl = get_status_port_fn(pbpctl_dev);
+               if (pbpctl_dev_sl && (pbpctl_dev_sl->ndev)) {
+                       if ((pbpctl_dev_sl->ndev->netdev_ops)
+                           && (pbpctl_dev_sl->old_ops)) {
+                               rtnl_lock();
+                               pbpctl_dev_sl->ndev->netdev_ops =
+                                   pbpctl_dev_sl->old_ops;
+                               pbpctl_dev_sl->old_ops = NULL;
+                               rtnl_unlock();
+                       }
+               }
+ #endif
+       }
+ }
+ int init_bypass_wd_auto(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
+               init_timer(&pbpctl_dev->bp_timer);
+               pbpctl_dev->bp_timer.function = &wd_reset_timer;
+               pbpctl_dev->bp_timer.data = (unsigned long)pbpctl_dev;
+               return 1;
+       }
+       return BP_NOT_CAP;
+ }
+ #ifdef BP_SELF_TEST
+ int bp_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+       bpctl_dev_t *pbpctl_dev = NULL, *pbpctl_dev_m = NULL;
+       int idx_dev = 0;
+       struct ethhdr *eth = (struct ethhdr *)skb->data;
+       for (idx_dev = 0;
+            ((bpctl_dev_arr[idx_dev].ndev != NULL) && (idx_dev < device_num));
+            idx_dev++) {
+               if (bpctl_dev_arr[idx_dev].ndev == dev) {
+                       pbpctl_dev = &bpctl_dev_arr[idx_dev];
+                       break;
+               }
+       }
+       if (!pbpctl_dev)
+               return 1;
+       if ((htons(ETH_P_BPTEST) == eth->h_proto)) {
+               pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
+               if (pbpctl_dev_m) {
+                       if (bypass_status(pbpctl_dev_m)) {
+                               cmnd_on(pbpctl_dev_m);
+                               bypass_off(pbpctl_dev_m);
+                               cmnd_off(pbpctl_dev_m);
+                       }
+                       wdt_timer_reload(pbpctl_dev_m);
+               }
+               dev_kfree_skb_irq(skb);
+               return 0;
+       }
+       return pbpctl_dev->hard_start_xmit_save(skb, dev);
+ }
+ #endif
+ int set_bypass_wd_auto(bpctl_dev_t *pbpctl_dev, unsigned int param)
+ {
+       if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
+               if (pbpctl_dev->reset_time != param) {
+                       if (INTEL_IF_SERIES(pbpctl_dev->subdevice))
+                               pbpctl_dev->reset_time =
+                                   (param <
+                                    WDT_AUTO_MIN_INT) ? WDT_AUTO_MIN_INT :
+                                   param;
+                       else
+                               pbpctl_dev->reset_time = param;
+                       if (param)
+                               mod_timer(&pbpctl_dev->bp_timer, jiffies);
+               }
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ int get_bypass_wd_auto(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
+               return pbpctl_dev->reset_time;
+       }
+       return BP_NOT_CAP;
+ }
+ #ifdef  BP_SELF_TEST
+ int set_bp_self_test(bpctl_dev_t *pbpctl_dev, unsigned int param)
+ {
+       bpctl_dev_t *pbpctl_dev_sl = NULL;
+       if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
+               pbpctl_dev->bp_self_test_flag = param == 0 ? 0 : 1;
+               pbpctl_dev_sl = get_status_port_fn(pbpctl_dev);
+               if ((pbpctl_dev_sl->ndev) && (pbpctl_dev_sl->ndev->netdev_ops)) {
+                       rtnl_lock();
+                       if (pbpctl_dev->bp_self_test_flag == 1) {
+                               pbpctl_dev_sl->old_ops =
+                                   pbpctl_dev_sl->ndev->netdev_ops;
+                               pbpctl_dev_sl->new_ops =
+                                   *pbpctl_dev_sl->old_ops;
+                               pbpctl_dev_sl->new_ops.ndo_start_xmit =
+                                   bp_hard_start_xmit;
+                               pbpctl_dev_sl->ndev->netdev_ops =
+                                   &pbpctl_dev_sl->new_ops;
+                       } else if (pbpctl_dev_sl->old_ops) {
+                               pbpctl_dev_sl->ndev->netdev_ops =
+                                   pbpctl_dev_sl->old_ops;
+                               pbpctl_dev_sl->old_ops = NULL;
+                       }
+                       rtnl_unlock();
+               }
+               set_bypass_wd_auto(pbpctl_dev, param);
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ int get_bp_self_test(bpctl_dev_t *pbpctl_dev)
+ {
+       if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
+               if (pbpctl_dev->bp_self_test_flag == 1)
+                       return pbpctl_dev->reset_time;
+               else
+                       return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ #endif
+ /**************************************************************/
+ /************************* API ********************************/
+ /**************************************************************/
+ int is_bypass_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return (((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) ? 1 : 0);
+ }
+ int set_bypass_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode)
+ {
+       int ret = 0;
+       if (!(pbpctl_dev->bp_caps & BP_CAP))
+               return BP_NOT_CAP;
+       if ((ret = cmnd_on(pbpctl_dev)) < 0)
+               return ret;
+       if (!bypass_mode)
+               ret = bypass_off(pbpctl_dev);
+       else
+               ret = bypass_on(pbpctl_dev);
+       cmnd_off(pbpctl_dev);
+       return ret;
+ }
+ int get_bypass_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       return bypass_status(pbpctl_dev);
+ }
+ int get_bypass_change_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return bypass_change_status(pbpctl_dev);
+ }
+ int set_dis_bypass_fn(bpctl_dev_t *pbpctl_dev, int dis_param)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if (!(pbpctl_dev->bp_caps & BP_DIS_CAP))
+               return BP_NOT_CAP;
+       if ((ret = cmnd_on(pbpctl_dev)) < 0)
+               return ret;
+       if (dis_param)
+               ret = dis_bypass_cap(pbpctl_dev);
+       else
+               ret = en_bypass_cap(pbpctl_dev);
+       cmnd_off(pbpctl_dev);
+       return ret;
+ }
+ int get_dis_bypass_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return dis_bypass_cap_status(pbpctl_dev);
+ }
+ int set_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if (!(pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP))
+               return BP_NOT_CAP;
+       if ((ret = cmnd_on(pbpctl_dev)) < 0)
+               return ret;
+       if (bypass_mode)
+               ret = bypass_state_pwroff(pbpctl_dev);
+       else
+               ret = normal_state_pwroff(pbpctl_dev);
+       cmnd_off(pbpctl_dev);
+       return ret;
+ }
+ int get_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return default_pwroff_status(pbpctl_dev);
+ }
+ int set_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if (!(pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP))
+               return BP_NOT_CAP;
+       if ((ret = cmnd_on(pbpctl_dev)) < 0)
+               return ret;
+       if (bypass_mode)
+               ret = bypass_state_pwron(pbpctl_dev);
+       else
+               ret = normal_state_pwron(pbpctl_dev);
+       cmnd_off(pbpctl_dev);
+       return ret;
+ }
+ int get_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return default_pwron_status(pbpctl_dev);
+ }
+ int set_bypass_wd_fn(bpctl_dev_t *pbpctl_dev, int timeout)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if (!(pbpctl_dev->bp_caps & WD_CTL_CAP))
+               return BP_NOT_CAP;
+       if ((ret = cmnd_on(pbpctl_dev)) < 0)
+               return ret;
+       if (!timeout)
+               ret = wdt_off(pbpctl_dev);
+       else {
+               wdt_on(pbpctl_dev, timeout);
+               ret = pbpctl_dev->bypass_timer_interval;
+       }
+       cmnd_off(pbpctl_dev);
+       return ret;
+ }
+ int get_bypass_wd_fn(bpctl_dev_t *pbpctl_dev, int *timeout)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return wdt_programmed(pbpctl_dev, timeout);
+ }
+ int get_wd_expire_time_fn(bpctl_dev_t *pbpctl_dev, int *time_left)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return wdt_timer(pbpctl_dev, time_left);
+ }
+ int reset_bypass_wd_timer_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return wdt_timer_reload(pbpctl_dev);
+ }
+ int get_wd_set_caps_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       int bp_status = 0;
+       unsigned int step_value = TIMEOUT_MAX_STEP + 1, bit_cnt = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if (INTEL_IF_SERIES(pbpctl_dev->subdevice))
+               return BP_NOT_CAP;
+       while ((step_value >>= 1))
+               bit_cnt++;
+       if (is_bypass_fn(pbpctl_dev)) {
+               bp_status =
+                   WD_STEP_COUNT_MASK(bit_cnt) | WDT_STEP_TIME |
+                   WD_MIN_TIME_MASK(TIMEOUT_UNIT / 100);
+       } else
+               return -1;
+       return bp_status;
+ }
+ int set_std_nic_fn(bpctl_dev_t *pbpctl_dev, int nic_mode)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if (!(pbpctl_dev->bp_caps & STD_NIC_CAP))
+               return BP_NOT_CAP;
+       if ((ret = cmnd_on(pbpctl_dev)) < 0)
+               return ret;
+       if (nic_mode)
+               ret = std_nic_on(pbpctl_dev);
+       else
+               ret = std_nic_off(pbpctl_dev);
+       cmnd_off(pbpctl_dev);
+       return ret;
+ }
+ int get_std_nic_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return std_nic_status(pbpctl_dev);
+ }
+ int set_tap_fn(bpctl_dev_t *pbpctl_dev, int tap_mode)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       if ((pbpctl_dev->bp_caps & TAP_CAP) && ((cmnd_on(pbpctl_dev)) >= 0)) {
+               if (!tap_mode)
+                       tap_off(pbpctl_dev);
+               else
+                       tap_on(pbpctl_dev);
+               cmnd_off(pbpctl_dev);
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ int get_tap_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return tap_status(pbpctl_dev);
+ }
+ int set_tap_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if ((pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP)
+           && ((cmnd_on(pbpctl_dev)) >= 0)) {
+               if (tap_mode)
+                       ret = tap_state_pwron(pbpctl_dev);
+               else
+                       ret = normal_state_pwron(pbpctl_dev);
+               cmnd_off(pbpctl_dev);
+       } else
+               ret = BP_NOT_CAP;
+       return ret;
+ }
+ int get_tap_pwup_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if ((ret = default_pwron_tap_status(pbpctl_dev)) < 0)
+               return ret;
+       return ((ret == 0) ? 1 : 0);
+ }
+ int get_tap_change_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return tap_change_status(pbpctl_dev);
+ }
+ int set_dis_tap_fn(bpctl_dev_t *pbpctl_dev, int dis_param)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if ((pbpctl_dev->bp_caps & TAP_DIS_CAP) && ((cmnd_on(pbpctl_dev)) >= 0)) {
+               if (dis_param)
+                       ret = dis_tap_cap(pbpctl_dev);
+               else
+                       ret = en_tap_cap(pbpctl_dev);
+               cmnd_off(pbpctl_dev);
+               return ret;
+       } else
+               return BP_NOT_CAP;
+ }
+ int get_dis_tap_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return dis_tap_cap_status(pbpctl_dev);
+ }
+ int set_disc_fn(bpctl_dev_t *pbpctl_dev, int disc_mode)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       if ((pbpctl_dev->bp_caps & DISC_CAP) && ((cmnd_on(pbpctl_dev)) >= 0)) {
+               if (!disc_mode)
+                       disc_off(pbpctl_dev);
+               else
+                       disc_on(pbpctl_dev);
+               cmnd_off(pbpctl_dev);
+               return BP_OK;
+       }
+       return BP_NOT_CAP;
+ }
+ int get_disc_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       ret = disc_status(pbpctl_dev);
+       return ret;
+ }
+ int set_disc_pwup_fn(bpctl_dev_t *pbpctl_dev, int disc_mode)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if ((pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP)
+           && ((cmnd_on(pbpctl_dev)) >= 0)) {
+               if (disc_mode)
+                       ret = disc_state_pwron(pbpctl_dev);
+               else
+                       ret = normal_state_pwron(pbpctl_dev);
+               cmnd_off(pbpctl_dev);
+       } else
+               ret = BP_NOT_CAP;
+       return ret;
+ }
+ int get_disc_pwup_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       ret = default_pwron_disc_status(pbpctl_dev);
+       return (ret == 0 ? 1 : (ret < 0 ? BP_NOT_CAP : 0));
+ }
+ int get_disc_change_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       ret = disc_change_status(pbpctl_dev);
+       return ret;
+ }
+ int set_dis_disc_fn(bpctl_dev_t *pbpctl_dev, int dis_param)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if ((pbpctl_dev->bp_caps & DISC_DIS_CAP)
+           && ((cmnd_on(pbpctl_dev)) >= 0)) {
+               if (dis_param)
+                       ret = dis_disc_cap(pbpctl_dev);
+               else
+                       ret = en_disc_cap(pbpctl_dev);
+               cmnd_off(pbpctl_dev);
+               return ret;
+       } else
+               return BP_NOT_CAP;
+ }
+ int get_dis_disc_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       ret = dis_disc_cap_status(pbpctl_dev);
+       return ret;
+ }
+ int set_disc_port_fn(bpctl_dev_t *pbpctl_dev, int disc_mode)
+ {
+       int ret = BP_NOT_CAP;
+       if (!pbpctl_dev)
+               return -1;
+       if (!disc_mode)
+               ret = disc_port_off(pbpctl_dev);
+       else
+               ret = disc_port_on(pbpctl_dev);
+       return ret;
+ }
+ int get_disc_port_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return disc_port_status(pbpctl_dev);
+ }
+ int set_disc_port_pwup_fn(bpctl_dev_t *pbpctl_dev, int disc_mode)
+ {
+       int ret = BP_NOT_CAP;
+       if (!pbpctl_dev)
+               return -1;
+       if (!disc_mode)
+               ret = normal_port_state_pwron(pbpctl_dev);
+       else
+               ret = disc_port_state_pwron(pbpctl_dev);
+       return ret;
+ }
+ int get_disc_port_pwup_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if ((ret = default_pwron_disc_port_status(pbpctl_dev)) < 0)
+               return ret;
+       return ((ret == 0) ? 1 : 0);
+ }
+ int get_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return wdt_exp_mode_status(pbpctl_dev);
+ }
+ int set_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev, int param)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return wdt_exp_mode(pbpctl_dev, param);
+ }
+ int reset_cont_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if ((ret = cmnd_on(pbpctl_dev)) < 0)
+               return ret;
+       return reset_cont(pbpctl_dev);
+ }
+ int set_tx_fn(bpctl_dev_t *pbpctl_dev, int tx_state)
+ {
+       bpctl_dev_t *pbpctl_dev_b = NULL;
+       if (!pbpctl_dev)
+               return -1;
+       if ((pbpctl_dev->bp_caps & TPL_CAP) &&
+           (pbpctl_dev->bp_caps & SW_CTL_CAP)) {
+               if ((pbpctl_dev->bp_tpl_flag))
+                       return BP_NOT_CAP;
+       } else if ((pbpctl_dev_b = get_master_port_fn(pbpctl_dev))) {
+               if ((pbpctl_dev_b->bp_caps & TPL_CAP) &&
+                   (pbpctl_dev_b->bp_tpl_flag))
+                       return BP_NOT_CAP;
+       }
+       return set_tx(pbpctl_dev, tx_state);
+ }
+ int set_bp_force_link_fn(int dev_num, int tx_state)
+ {
+       static bpctl_dev_t *bpctl_dev_curr;
+       if ((dev_num < 0) || (dev_num > device_num)
+           || (bpctl_dev_arr[dev_num].pdev == NULL))
+               return -1;
+       bpctl_dev_curr = &bpctl_dev_arr[dev_num];
+       return set_bp_force_link(bpctl_dev_curr, tx_state);
+ }
+ int set_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev, int param)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return set_bypass_wd_auto(pbpctl_dev, param);
+ }
+ int get_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return get_bypass_wd_auto(pbpctl_dev);
+ }
+ #ifdef BP_SELF_TEST
+ int set_bp_self_test_fn(bpctl_dev_t *pbpctl_dev, int param)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return set_bp_self_test(pbpctl_dev, param);
+ }
+ int get_bp_self_test_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return get_bp_self_test(pbpctl_dev);
+ }
+ #endif
+ int get_bypass_caps_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       return pbpctl_dev->bp_caps;
+ }
+ int get_bypass_slave_fn(bpctl_dev_t *pbpctl_dev, bpctl_dev_t **pbpctl_dev_out)
+ {
+       int idx_dev = 0;
+       if (!pbpctl_dev)
+               return -1;
+       if ((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) {
+               for (idx_dev = 0;
+                    ((bpctl_dev_arr[idx_dev].pdev != NULL)
+                     && (idx_dev < device_num)); idx_dev++) {
+                       if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus)
+                           && (bpctl_dev_arr[idx_dev].slot ==
+                               pbpctl_dev->slot)) {
+                               if ((pbpctl_dev->func == 0)
+                                   && (bpctl_dev_arr[idx_dev].func == 1)) {
+                                       *pbpctl_dev_out =
+                                           &bpctl_dev_arr[idx_dev];
+                                       return 1;
+                               }
+                               if ((pbpctl_dev->func == 2) &&
+                                   (bpctl_dev_arr[idx_dev].func == 3)) {
+                                       *pbpctl_dev_out =
+                                           &bpctl_dev_arr[idx_dev];
+                                       return 1;
+                               }
+                       }
+               }
+               return -1;
+       } else
+               return 0;
+ }
+ int is_bypass(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       if ((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2))
+               return 1;
+       else
+               return 0;
+ }
+ int get_tx_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       bpctl_dev_t *pbpctl_dev_b = NULL;
+       if (!pbpctl_dev)
+               return -1;
+       if ((pbpctl_dev->bp_caps & TPL_CAP) &&
+           (pbpctl_dev->bp_caps & SW_CTL_CAP)) {
+               if ((pbpctl_dev->bp_tpl_flag))
+                       return BP_NOT_CAP;
+       } else if ((pbpctl_dev_b = get_master_port_fn(pbpctl_dev))) {
+               if ((pbpctl_dev_b->bp_caps & TPL_CAP) &&
+                   (pbpctl_dev_b->bp_tpl_flag))
+                       return BP_NOT_CAP;
+       }
+       return tx_status(pbpctl_dev);
+ }
+ int get_bp_force_link_fn(int dev_num)
+ {
+       static bpctl_dev_t *bpctl_dev_curr;
+       if ((dev_num < 0) || (dev_num > device_num)
+           || (bpctl_dev_arr[dev_num].pdev == NULL))
+               return -1;
+       bpctl_dev_curr = &bpctl_dev_arr[dev_num];
+       return bp_force_link_status(bpctl_dev_curr);
+ }
+ static int get_bypass_link_status(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       if (pbpctl_dev->media_type == bp_fiber)
+               return ((BPCTL_READ_REG(pbpctl_dev, CTRL) &
+                        BPCTLI_CTRL_SWDPIN1));
+       else
+               return ((BPCTL_READ_REG(pbpctl_dev, STATUS) &
+                        BPCTLI_STATUS_LU));
+ }
+ static void bp_tpl_timer_fn(unsigned long param)
+ {
+       bpctl_dev_t *pbpctl_dev = (bpctl_dev_t *) param;
+       uint32_t link1, link2;
+       bpctl_dev_t *pbpctl_dev_b = NULL;
+       if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev)))
+               return;
+       if (!pbpctl_dev->bp_tpl_flag) {
+               set_tx(pbpctl_dev_b, 1);
+               set_tx(pbpctl_dev, 1);
+               return;
+       }
+       link1 = get_bypass_link_status(pbpctl_dev);
+       link2 = get_bypass_link_status(pbpctl_dev_b);
+       if ((link1) && (tx_status(pbpctl_dev))) {
+               if ((!link2) && (tx_status(pbpctl_dev_b))) {
+                       set_tx(pbpctl_dev, 0);
+               } else if (!tx_status(pbpctl_dev_b)) {
+                       set_tx(pbpctl_dev_b, 1);
+               }
+       } else if ((!link1) && (tx_status(pbpctl_dev))) {
+               if ((link2) && (tx_status(pbpctl_dev_b))) {
+                       set_tx(pbpctl_dev_b, 0);
+               }
+       } else if ((link1) && (!tx_status(pbpctl_dev))) {
+               if ((link2) && (tx_status(pbpctl_dev_b))) {
+                       set_tx(pbpctl_dev, 1);
+               }
+       } else if ((!link1) && (!tx_status(pbpctl_dev))) {
+               if ((link2) && (tx_status(pbpctl_dev_b))) {
+                       set_tx(pbpctl_dev, 1);
+               }
+       }
+       mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies + BP_LINK_MON_DELAY * HZ);
+ }
+ void remove_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev)
+ {
+       bpctl_dev_t *pbpctl_dev_b = NULL;
+       if (!pbpctl_dev)
+               return;
+       pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
+       if (pbpctl_dev->bp_caps & TPL_CAP) {
+               del_timer_sync(&pbpctl_dev->bp_tpl_timer);
+               pbpctl_dev->bp_tpl_flag = 0;
+               pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
+               if (pbpctl_dev_b)
+                       set_tx(pbpctl_dev_b, 1);
+               set_tx(pbpctl_dev, 1);
+       }
+       return;
+ }
+ int init_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       if (pbpctl_dev->bp_caps & TPL_CAP) {
+               init_timer(&pbpctl_dev->bp_tpl_timer);
+               pbpctl_dev->bp_tpl_timer.function = &bp_tpl_timer_fn;
+               pbpctl_dev->bp_tpl_timer.data = (unsigned long)pbpctl_dev;
+               return BP_OK;
+       }
+       return BP_NOT_CAP;
+ }
+ int set_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev, unsigned int param)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       if (pbpctl_dev->bp_caps & TPL_CAP) {
+               if ((param) && (!pbpctl_dev->bp_tpl_flag)) {
+                       pbpctl_dev->bp_tpl_flag = param;
+                       mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies + 1);
+                       return BP_OK;
+               };
+               if ((!param) && (pbpctl_dev->bp_tpl_flag))
+                       remove_bypass_tpl_auto(pbpctl_dev);
+               return BP_OK;
+       }
+       return BP_NOT_CAP;
+ }
+ int get_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       if (pbpctl_dev->bp_caps & TPL_CAP) {
+               return pbpctl_dev->bp_tpl_flag;
+       }
+       return BP_NOT_CAP;
+ }
+ int set_tpl_fn(bpctl_dev_t *pbpctl_dev, int tpl_mode)
+ {
+       bpctl_dev_t *pbpctl_dev_b = NULL;
+       if (!pbpctl_dev)
+               return -1;
+       pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
+       if (pbpctl_dev->bp_caps & TPL_CAP) {
+               if (tpl_mode) {
+                       if ((pbpctl_dev_b = get_status_port_fn(pbpctl_dev)))
+                               set_tx(pbpctl_dev_b, 1);
+                       set_tx(pbpctl_dev, 1);
+               }
+               if ((TPL_IF_SERIES(pbpctl_dev->subdevice)) ||
+                   (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX)) {
+                       pbpctl_dev->bp_tpl_flag = tpl_mode;
+                       if (!tpl_mode)
+                               tpl_hw_off(pbpctl_dev);
+                       else
+                               tpl_hw_on(pbpctl_dev);
+               } else
+                       set_bypass_tpl_auto(pbpctl_dev, tpl_mode);
+               return 0;
+       }
+       return BP_NOT_CAP;
+ }
+ int get_tpl_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = BP_NOT_CAP;
+       if (!pbpctl_dev)
+               return -1;
+       if (pbpctl_dev->bp_caps & TPL_CAP) {
+               if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX)
+                       return tpl2_flag_status(pbpctl_dev);
+               ret = pbpctl_dev->bp_tpl_flag;
+       }
+       return ret;
+ }
+ int set_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               /* bp_lock(pbp_device_block); */
+               cmnd_on(pbpctl_dev);
+               if (!tap_mode)
+                       bp_wait_at_pwup_dis(pbpctl_dev);
+               else
+                       bp_wait_at_pwup_en(pbpctl_dev);
+               cmnd_off(pbpctl_dev);
+               /* bp_unlock(pbp_device_block); */
+               return BP_OK;
+       }
+       return BP_NOT_CAP;
+ }
+ int get_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       /* bp_lock(pbp_device_block); */
+       ret = bp_wait_at_pwup_status(pbpctl_dev);
+       /* bp_unlock(pbp_device_block); */
+       return ret;
+ }
+ int set_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev, int tap_mode)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
+               /*   bp_lock(pbp_device_block); */
+               cmnd_on(pbpctl_dev);
+               if (!tap_mode)
+                       bp_hw_reset_dis(pbpctl_dev);
+               else
+                       bp_hw_reset_en(pbpctl_dev);
+               cmnd_off(pbpctl_dev);
+               /*    bp_unlock(pbp_device_block); */
+               return BP_OK;
+       }
+       return BP_NOT_CAP;
+ }
+ int get_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev)
+ {
+       int ret = 0;
+       if (!pbpctl_dev)
+               return -1;
+       /* bp_lock(pbp_device_block); */
+       ret = bp_hw_reset_status(pbpctl_dev);
+       /* bp_unlock(pbp_device_block); */
+       return ret;
+ }
+ int get_bypass_info_fn(bpctl_dev_t *pbpctl_dev, char *dev_name,
+                      char *add_param)
+ {
+       if (!pbpctl_dev)
+               return -1;
+       if (!is_bypass_fn(pbpctl_dev))
+               return -1;
+       strcpy(dev_name, pbpctl_dev->name);
+       *add_param = pbpctl_dev->bp_fw_ver;
+       return 0;
+ }
+ int get_dev_idx_bsf(int bus, int slot, int func)
+ {
+       int idx_dev = 0;
+       for (idx_dev = 0;
+            ((bpctl_dev_arr[idx_dev].pdev != NULL) && (idx_dev < device_num));
+            idx_dev++) {
+               if ((bus == bpctl_dev_arr[idx_dev].bus)
+                   && (slot == bpctl_dev_arr[idx_dev].slot)
+                   && (func == bpctl_dev_arr[idx_dev].func))
+                       return idx_dev;
+       }
+       return -1;
+ }
+ static void str_low(char *str)
+ {
+       int i;
+       for (i = 0; i < strlen(str); i++)
+               if ((str[i] >= 65) && (str[i] <= 90))
+                       str[i] += 32;
+ }
+ static unsigned long str_to_hex(char *p)
+ {
+       unsigned long hex = 0;
+       unsigned long length = strlen(p), shift = 0;
+       unsigned char dig = 0;
+       str_low(p);
+       length = strlen(p);
+       if (length == 0)
+               return 0;
+       do {
+               dig = p[--length];
+               dig = dig < 'a' ? (dig - '0') : (dig - 'a' + 0xa);
+               hex |= (dig << shift);
+               shift += 4;
+       } while (length);
+       return hex;
+ }
+ static int get_dev_idx(int ifindex)
+ {
+       int idx_dev = 0;
+       for (idx_dev = 0;
+            ((bpctl_dev_arr[idx_dev].pdev != NULL) && (idx_dev < device_num));
+            idx_dev++) {
+               if (ifindex == bpctl_dev_arr[idx_dev].ifindex)
+                       return idx_dev;
+       }
+       return -1;
+ }
+ static bpctl_dev_t *get_dev_idx_p(int ifindex)
+ {
+       int idx_dev = 0;
+       for (idx_dev = 0;
+            ((bpctl_dev_arr[idx_dev].pdev != NULL) && (idx_dev < device_num));
+            idx_dev++) {
+               if (ifindex == bpctl_dev_arr[idx_dev].ifindex)
+                       return &bpctl_dev_arr[idx_dev];
+       }
+       return NULL;
+ }
+ static void if_scan_init(void)
+ {
+       int idx_dev = 0;
+       struct net_device *dev;
+       int ifindex;
+       /* rcu_read_lock(); */
+       /* rtnl_lock();     */
+       /* rcu_read_lock(); */
+       for_each_netdev(&init_net, dev) {
+               struct ethtool_drvinfo drvinfo;
+               char cbuf[32];
+               char *buf = NULL;
+               char res[10];
+               int i = 0;
+               int bus = 0, slot = 0, func = 0;
+               ifindex = dev->ifindex;
+               memset(res, 0, 10);
+               memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo));
+               if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo) {
+                       memset(&drvinfo, 0, sizeof(drvinfo));
+                       dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
+               } else
+                       continue;
+               if (!strcmp(drvinfo.bus_info, "N/A"))
+                       continue;
+               memcpy(&cbuf, drvinfo.bus_info, 32);
+               buf = &cbuf[0];
+               while (*buf++ != ':') ;
+               for (i = 0; i < 10; i++, buf++) {
+                       if (*buf == ':')
+                               break;
+                       res[i] = *buf;
+               }
+               buf++;
+               bus = str_to_hex(res);
+               memset(res, 0, 10);
+               for (i = 0; i < 10; i++, buf++) {
+                       if (*buf == '.')
+                               break;
+                       res[i] = *buf;
+               }
+               buf++;
+               slot = str_to_hex(res);
+               func = str_to_hex(buf);
+               idx_dev = get_dev_idx_bsf(bus, slot, func);
+               if (idx_dev != -1) {
+                       bpctl_dev_arr[idx_dev].ifindex = ifindex;
+                       bpctl_dev_arr[idx_dev].ndev = dev;
+               }
+       }
+       /* rtnl_unlock();     */
+       /* rcu_read_unlock(); */
+ }
+ static long device_ioctl(struct file *file,   /* see include/linux/fs.h */
+                        unsigned int ioctl_num,        /* number and param for ioctl */
+                        unsigned long ioctl_param)
+ {
+       struct bpctl_cmd bpctl_cmd;
+       int dev_idx = 0;
+       bpctl_dev_t *pbpctl_dev_out;
+       void __user *argp = (void __user *)ioctl_param;
+       int ret = 0;
+       unsigned long flags;
+       static bpctl_dev_t *pbpctl_dev;
+       /* lock_kernel(); */
+       lock_bpctl();
+       /* local_irq_save(flags); */
+       /* if(!spin_trylock_irqsave(&bpvm_lock)){
+          local_irq_restore(flags);
+          unlock_bpctl();
+          unlock_kernel();
+          return -1;
+          } */
+       /* spin_lock_irqsave(&bpvm_lock, flags); */
+ /*
+ * Switch according to the ioctl called
+ */
+       if (ioctl_num == IOCTL_TX_MSG(IF_SCAN)) {
+               if_scan_init();
+               ret = SUCCESS;
+               goto bp_exit;
+       }
+       if (copy_from_user(&bpctl_cmd, argp, sizeof(struct bpctl_cmd))) {
+               ret = -EFAULT;
+               goto bp_exit;
+       }
+       if (ioctl_num == IOCTL_TX_MSG(GET_DEV_NUM)) {
+               bpctl_cmd.out_param[0] = device_num;
+               if (copy_to_user
+                   (argp, (void *)&bpctl_cmd, sizeof(struct bpctl_cmd))) {
+                       ret = -EFAULT;
+                       goto bp_exit;
+               }
+               ret = SUCCESS;
+               goto bp_exit;
+       }
+       /* lock_bpctl();      */
+       /* preempt_disable(); */
+       local_irq_save(flags);
+       if (!spin_trylock(&bpvm_lock)) {
+               local_irq_restore(flags);
+               unlock_bpctl();
+               return -1;
+       }
+ /*            preempt_disable();
+       rcu_read_lock();
+               spin_lock_irqsave(&bpvm_lock, flags);
+ */
+       if ((bpctl_cmd.in_param[5]) ||
+           (bpctl_cmd.in_param[6]) || (bpctl_cmd.in_param[7]))
+               dev_idx = get_dev_idx_bsf(bpctl_cmd.in_param[5],
+                                         bpctl_cmd.in_param[6],
+                                         bpctl_cmd.in_param[7]);
+       else if (bpctl_cmd.in_param[1] == 0)
+               dev_idx = bpctl_cmd.in_param[0];
+       else
+               dev_idx = get_dev_idx(bpctl_cmd.in_param[1]);
+       if (dev_idx < 0 || dev_idx > device_num) {
+               /* unlock_bpctl();
+                  preempt_enable(); */
+               ret = -EOPNOTSUPP;
+               /* preempt_enable();
+                  rcu_read_unlock();  */
+               spin_unlock_irqrestore(&bpvm_lock, flags);
+               goto bp_exit;
+       }
+       bpctl_cmd.out_param[0] = bpctl_dev_arr[dev_idx].bus;
+       bpctl_cmd.out_param[1] = bpctl_dev_arr[dev_idx].slot;
+       bpctl_cmd.out_param[2] = bpctl_dev_arr[dev_idx].func;
+       bpctl_cmd.out_param[3] = bpctl_dev_arr[dev_idx].ifindex;
+       if ((bpctl_dev_arr[dev_idx].bp_10gb)
+           && (!(bpctl_dev_arr[dev_idx].ifindex))) {
+               printk("Please load network driver for %s adapter!\n",
+                      bpctl_dev_arr[dev_idx].name);
+               bpctl_cmd.status = -1;
+               ret = SUCCESS;
+               /* preempt_enable(); */
+               /* rcu_read_unlock(); */
+               spin_unlock_irqrestore(&bpvm_lock, flags);
+               goto bp_exit;
+       }
+       if ((bpctl_dev_arr[dev_idx].bp_10gb) && (bpctl_dev_arr[dev_idx].ndev)) {
+               if (!(bpctl_dev_arr[dev_idx].ndev->flags & IFF_UP)) {
+                       if (!(bpctl_dev_arr[dev_idx].ndev->flags & IFF_UP)) {
+                               printk
+                                   ("Please bring up network interfaces for %s adapter!\n",
+                                    bpctl_dev_arr[dev_idx].name);
+                               bpctl_cmd.status = -1;
+                               ret = SUCCESS;
+                               /* preempt_enable(); */
+                               /* rcu_read_unlock(); */
+                               spin_unlock_irqrestore(&bpvm_lock, flags);
+                               goto bp_exit;
+                       }
+               }
+       }
+       if ((dev_idx < 0) || (dev_idx > device_num)
+           || (bpctl_dev_arr[dev_idx].pdev == NULL)) {
+               bpctl_cmd.status = -1;
+               goto bpcmd_exit;
+       }
+       pbpctl_dev = &bpctl_dev_arr[dev_idx];
+       switch (ioctl_num) {
+       case IOCTL_TX_MSG(SET_BYPASS_PWOFF):
+               bpctl_cmd.status =
+                   set_bypass_pwoff_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_BYPASS_PWOFF):
+               bpctl_cmd.status = get_bypass_pwoff_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_BYPASS_PWUP):
+               bpctl_cmd.status =
+                   set_bypass_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_BYPASS_PWUP):
+               bpctl_cmd.status = get_bypass_pwup_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_BYPASS_WD):
+               bpctl_cmd.status =
+                   set_bypass_wd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_BYPASS_WD):
+               bpctl_cmd.status =
+                   get_bypass_wd_fn(pbpctl_dev, (int *)&(bpctl_cmd.data[0]));
+               break;
+       case IOCTL_TX_MSG(GET_WD_EXPIRE_TIME):
+               bpctl_cmd.status =
+                   get_wd_expire_time_fn(pbpctl_dev,
+                                         (int *)&(bpctl_cmd.data[0]));
+               break;
+       case IOCTL_TX_MSG(RESET_BYPASS_WD_TIMER):
+               bpctl_cmd.status = reset_bypass_wd_timer_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(GET_WD_SET_CAPS):
+               bpctl_cmd.status = get_wd_set_caps_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_STD_NIC):
+               bpctl_cmd.status =
+                   set_std_nic_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_STD_NIC):
+               bpctl_cmd.status = get_std_nic_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_TAP):
+               bpctl_cmd.status =
+                   set_tap_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_TAP):
+               bpctl_cmd.status = get_tap_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(GET_TAP_CHANGE):
+               bpctl_cmd.status = get_tap_change_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_DIS_TAP):
+               bpctl_cmd.status =
+                   set_dis_tap_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_DIS_TAP):
+               bpctl_cmd.status = get_dis_tap_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_TAP_PWUP):
+               bpctl_cmd.status =
+                   set_tap_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_TAP_PWUP):
+               bpctl_cmd.status = get_tap_pwup_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_WD_EXP_MODE):
+               bpctl_cmd.status =
+                   set_wd_exp_mode_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_WD_EXP_MODE):
+               bpctl_cmd.status = get_wd_exp_mode_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(GET_DIS_BYPASS):
+               bpctl_cmd.status = get_dis_bypass_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_DIS_BYPASS):
+               bpctl_cmd.status =
+                   set_dis_bypass_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_BYPASS_CHANGE):
+               bpctl_cmd.status = get_bypass_change_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(GET_BYPASS):
+               bpctl_cmd.status = get_bypass_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_BYPASS):
+               bpctl_cmd.status =
+                   set_bypass_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_BYPASS_CAPS):
+               bpctl_cmd.status = get_bypass_caps_fn(pbpctl_dev);
+               /*preempt_enable(); */
+               /*rcu_read_unlock();*/
+               spin_unlock_irqrestore(&bpvm_lock, flags);
+               if (copy_to_user
+                   (argp, (void *)&bpctl_cmd, sizeof(struct bpctl_cmd))) {
+                       /*unlock_bpctl();   */
+                       /*preempt_enable(); */
+                       ret = -EFAULT;
+                       goto bp_exit;
+               }
+               goto bp_exit;
+       case IOCTL_TX_MSG(GET_BYPASS_SLAVE):
+               bpctl_cmd.status =
+                   get_bypass_slave_fn(pbpctl_dev, &pbpctl_dev_out);
+               if (bpctl_cmd.status == 1) {
+                       bpctl_cmd.out_param[4] = pbpctl_dev_out->bus;
+                       bpctl_cmd.out_param[5] = pbpctl_dev_out->slot;
+                       bpctl_cmd.out_param[6] = pbpctl_dev_out->func;
+                       bpctl_cmd.out_param[7] = pbpctl_dev_out->ifindex;
+               }
+               break;
+       case IOCTL_TX_MSG(IS_BYPASS):
+               bpctl_cmd.status = is_bypass(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_TX):
+               bpctl_cmd.status = set_tx_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_TX):
+               bpctl_cmd.status = get_tx_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_WD_AUTORESET):
+               bpctl_cmd.status =
+                   set_wd_autoreset_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_WD_AUTORESET):
+               bpctl_cmd.status = get_wd_autoreset_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_DISC):
+               bpctl_cmd.status =
+                   set_disc_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_DISC):
+               bpctl_cmd.status = get_disc_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(GET_DISC_CHANGE):
+               bpctl_cmd.status = get_disc_change_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_DIS_DISC):
+               bpctl_cmd.status =
+                   set_dis_disc_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_DIS_DISC):
+               bpctl_cmd.status = get_dis_disc_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_DISC_PWUP):
+               bpctl_cmd.status =
+                   set_disc_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_DISC_PWUP):
+               bpctl_cmd.status = get_disc_pwup_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(GET_BYPASS_INFO):
+               bpctl_cmd.status =
+                   get_bypass_info_fn(pbpctl_dev, (char *)&bpctl_cmd.data,
+                                      (char *)&bpctl_cmd.out_param[4]);
+               break;
+       case IOCTL_TX_MSG(SET_TPL):
+               bpctl_cmd.status =
+                   set_tpl_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_TPL):
+               bpctl_cmd.status = get_tpl_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_BP_WAIT_AT_PWUP):
+               bpctl_cmd.status =
+                   set_bp_wait_at_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_BP_WAIT_AT_PWUP):
+               bpctl_cmd.status = get_bp_wait_at_pwup_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_BP_HW_RESET):
+               bpctl_cmd.status =
+                   set_bp_hw_reset_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_BP_HW_RESET):
+               bpctl_cmd.status = get_bp_hw_reset_fn(pbpctl_dev);
+               break;
+ #ifdef BP_SELF_TEST
+       case IOCTL_TX_MSG(SET_BP_SELF_TEST):
+               bpctl_cmd.status =
+                   set_bp_self_test_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_BP_SELF_TEST):
+               bpctl_cmd.status = get_bp_self_test_fn(pbpctl_dev);
+               break;
+ #endif
+ #if 0
+       case IOCTL_TX_MSG(SET_DISC_PORT):
+               bpctl_cmd.status =
+                   set_disc_port_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_DISC_PORT):
+               bpctl_cmd.status = get_disc_port_fn(pbpctl_dev);
+               break;
+       case IOCTL_TX_MSG(SET_DISC_PORT_PWUP):
+               bpctl_cmd.status =
+                   set_disc_port_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_DISC_PORT_PWUP):
+               bpctl_cmd.status = get_disc_port_pwup_fn(pbpctl_dev);
+               break;
+ #endif
+       case IOCTL_TX_MSG(SET_BP_FORCE_LINK):
+               bpctl_cmd.status =
+                   set_bp_force_link_fn(dev_idx, bpctl_cmd.in_param[2]);
+               break;
+       case IOCTL_TX_MSG(GET_BP_FORCE_LINK):
+               bpctl_cmd.status = get_bp_force_link_fn(dev_idx);
+               break;
+       default:
+               /*    unlock_bpctl(); */
+               ret = -EOPNOTSUPP;
+               /* preempt_enable(); */
+               /* rcu_read_unlock();*/
+               spin_unlock_irqrestore(&bpvm_lock, flags);
+               goto bp_exit;
+       }
+       /* unlock_bpctl();   */
+       /* preempt_enable(); */
+  bpcmd_exit:
+       /* rcu_read_unlock(); */
+       spin_unlock_irqrestore(&bpvm_lock, flags);
+       if (copy_to_user(argp, (void *)&bpctl_cmd, sizeof(struct bpctl_cmd)))
+               ret = -EFAULT;
+       ret = SUCCESS;
+  bp_exit:
+       /* unlock_kernel(); */
+       /* spin_unlock_irqrestore(&bpvm_lock, flags); */
+       unlock_bpctl();
+       /* unlock_kernel(); */
+       return ret;
+ }
+ static const struct file_operations Fops = {
+       .owner = THIS_MODULE,
+       .unlocked_ioctl = device_ioctl,
+ };
+ #ifndef PCI_DEVICE
+ #define PCI_DEVICE(vend,dev) \
+       .vendor = (vend), .device = (dev), \
+       .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
+ #endif
+ #define SILICOM_E1000BP_ETHERNET_DEVICE(device_id) {\
+       PCI_DEVICE(SILICOM_VID, device_id)}
+ typedef enum {
+       PXG2BPFI,
+       PXG2BPFIL,
+       PXG2BPFILX,
+       PXG2BPFILLX,
+       PXGBPI,
+       PXGBPIG,
+       PXG2TBFI,
+       PXG4BPI,
+       PXG4BPFI,
+       PEG4BPI,
+       PEG2BPI,
+       PEG4BPIN,
+       PEG2BPFI,
+       PEG2BPFILX,
+       PMCXG2BPFI,
+       PMCXG2BPFIN,
+       PEG4BPII,
+       PEG4BPFII,
+       PXG4BPFILX,
+       PMCXG2BPIN,
+       PMCXG4BPIN,
+       PXG2BISC1,
+       PEG2TBFI,
+       PXG2TBI,
+       PXG4BPFID,
+       PEG4BPFI,
+       PEG4BPIPT,
+       PXG6BPI,
+       PEG4BPIL,
+       PMCXG2BPIN2,
+       PMCXG4BPIN2,
+       PMCX2BPI,
+       PEG2BPFID,
+       PEG2BPFIDLX,
+       PMCX4BPI,
+       MEG2BPFILN,
+       MEG2BPFINX,
+       PEG4BPFILX,
+       PE10G2BPISR,
+       PE10G2BPILR,
+       MHIO8AD,
+       PE10G2BPICX4,
+       PEG2BPI5,
+       PEG6BPI,
+       PEG4BPFI5,
+       PEG4BPFI5LX,
+       MEG2BPFILXLN,
+       PEG2BPIX1,
+       MEG2BPFILXNX,
+       XE10G2BPIT,
+       XE10G2BPICX4,
+       XE10G2BPISR,
+       XE10G2BPILR,
+       PEG4BPIIO,
+       XE10G2BPIXR,
+       PE10GDBISR,
+       PE10GDBILR,
+       PEG2BISC6,
+       PEG6BPIFC,
+       PE10G2BPTCX4,
+       PE10G2BPTSR,
+       PE10G2BPTLR,
+       PE10G2BPTT,
+       PEG4BPI6,
+       PEG4BPFI6,
+       PEG4BPFI6LX,
+       PEG4BPFI6ZX,
+       PEG2BPI6,
+       PEG2BPFI6,
+       PEG2BPFI6LX,
+       PEG2BPFI6ZX,
+       PEG2BPFI6FLXM,
+       PEG4BPI6FC,
+       PEG4BPFI6FC,
+       PEG4BPFI6FCLX,
+       PEG4BPFI6FCZX,
+       PEG6BPI6,
+       PEG2BPI6SC6,
+       MEG2BPI6,
+       XEG2BPI6,
+       MEG4BPI6,
+       PEG2BPFI5,
+       PEG2BPFI5LX,
+       PXEG4BPFI,
+       M1EG2BPI6,
+       M1EG2BPFI6,
+       M1EG2BPFI6LX,
+       M1EG2BPFI6ZX,
+       M1EG4BPI6,
+       M1EG4BPFI6,
+       M1EG4BPFI6LX,
+       M1EG4BPFI6ZX,
+       M1EG6BPI6,
+       M1E2G4BPi80,
+       M1E2G4BPFi80,
+       M1E2G4BPFi80LX,
+       M1E2G4BPFi80ZX,
+       PE210G2SPI9,
+       M1E10G2BPI9CX4,
+       M1E10G2BPI9SR,
+       M1E10G2BPI9LR,
+       M1E10G2BPI9T,
+       PE210G2BPI9CX4,
+       PE210G2BPI9SR,
+       PE210G2BPI9LR,
+       PE210G2BPI9T,
+       M2EG2BPFI6,
+       M2EG2BPFI6LX,
+       M2EG2BPFI6ZX,
+       M2EG4BPI6,
+       M2EG4BPFI6,
+       M2EG4BPFI6LX,
+       M2EG4BPFI6ZX,
+       M2EG6BPI6,
+       PEG2DBI6,
+       PEG2DBFI6,
+       PEG2DBFI6LX,
+       PEG2DBFI6ZX,
+       PE2G4BPi80,
+       PE2G4BPFi80,
+       PE2G4BPFi80LX,
+       PE2G4BPFi80ZX,
+       PE2G4BPi80L,
+       M6E2G8BPi80A,
+       PE2G2BPi35,
+       PAC1200BPi35,
+       PE2G2BPFi35,
+       PE2G2BPFi35LX,
+       PE2G2BPFi35ZX,
+       PE2G4BPi35,
+       PE2G4BPi35L,
+       PE2G4BPFi35,
+       PE2G4BPFi35LX,
+       PE2G4BPFi35ZX,
+       PE2G6BPi35,
+       PE2G6BPi35CX,
+       PE2G2BPi80,
+       PE2G2BPFi80,
+       PE2G2BPFi80LX,
+       PE2G2BPFi80ZX,
+       M2E10G2BPI9CX4,
+       M2E10G2BPI9SR,
+       M2E10G2BPI9LR,
+       M2E10G2BPI9T,
+       M6E2G8BPi80,
+       PE210G2DBi9SR,
+       PE210G2DBi9SRRB,
+       PE210G2DBi9LR,
+       PE210G2DBi9LRRB,
+       PE310G4DBi940SR,
+       PE310G4BPi9T,
+       PE310G4BPi9SR,
+       PE310G4BPi9LR,
+       PE210G2BPi40,
+ } board_t;
+ typedef struct _bpmod_info_t {
+       unsigned int vendor;
+       unsigned int device;
+       unsigned int subvendor;
+       unsigned int subdevice;
+       unsigned int index;
+       char *bp_name;
+ } bpmod_info_t;
+ typedef struct _dev_desc {
+       char *name;
+ } dev_desc_t;
+ dev_desc_t dev_desc[] = {
+       {"Silicom Bypass PXG2BPFI-SD series adapter"},
+       {"Silicom Bypass PXG2BPFIL-SD series adapter"},
+       {"Silicom Bypass PXG2BPFILX-SD series adapter"},
+       {"Silicom Bypass PXG2BPFILLX-SD series adapter"},
+       {"Silicom Bypass PXG2BPI-SD series adapter"},
+       {"Silicom Bypass PXG2BPIG-SD series adapter"},
+       {"Silicom Bypass PXG2TBFI-SD series adapter"},
+       {"Silicom Bypass PXG4BPI-SD series adapter"},
+       {"Silicom Bypass PXG4BPFI-SD series adapter"},
+       {"Silicom Bypass PEG4BPI-SD series adapter"},
+       {"Silicom Bypass PEG2BPI-SD series adapter"},
+       {"Silicom Bypass PEG4BPIN-SD series adapter"},
+       {"Silicom Bypass PEG2BPFI-SD series adapter"},
+       {"Silicom Bypass PEG2BPFI-LX-SD series adapter"},
+       {"Silicom Bypass PMCX2BPFI-SD series adapter"},
+       {"Silicom Bypass PMCX2BPFI-N series adapter"},
+       {"Intel Bypass PEG2BPII series adapter"},
+       {"Intel Bypass PEG2BPFII series adapter"},
+       {"Silicom Bypass PXG4BPFILX-SD series adapter"},
+       {"Silicom Bypass PMCX2BPI-N series adapter"},
+       {"Silicom Bypass PMCX4BPI-N series adapter"},
+       {"Silicom Bypass PXG2BISC1-SD series adapter"},
+       {"Silicom Bypass PEG2TBFI-SD series adapter"},
+       {"Silicom Bypass PXG2TBI-SD series adapter"},
+       {"Silicom Bypass PXG4BPFID-SD series adapter"},
+       {"Silicom Bypass PEG4BPFI-SD series adapter"},
+       {"Silicom Bypass PEG4BPIPT-SD series adapter"},
+       {"Silicom Bypass PXG6BPI-SD series adapter"},
+       {"Silicom Bypass PEG4BPIL-SD series adapter"},
+       {"Silicom Bypass PMCX2BPI-N2 series adapter"},
+       {"Silicom Bypass PMCX4BPI-N2 series adapter"},
+       {"Silicom Bypass PMCX2BPI-SD series adapter"},
+       {"Silicom Bypass PEG2BPFID-SD series adapter"},
+       {"Silicom Bypass PEG2BPFIDLX-SD series adapter"},
+       {"Silicom Bypass PMCX4BPI-SD series adapter"},
+       {"Silicom Bypass MEG2BPFILN-SD series adapter"},
+       {"Silicom Bypass MEG2BPFINX-SD series adapter"},
+       {"Silicom Bypass PEG4BPFILX-SD series adapter"},
+       {"Silicom Bypass PE10G2BPISR-SD series adapter"},
+       {"Silicom Bypass PE10G2BPILR-SD series adapter"},
+       {"Silicom Bypass MHIO8AD-SD series adapter"},
+       {"Silicom Bypass PE10G2BPICX4-SD series adapter"},
+       {"Silicom Bypass PEG2BPI5-SD series adapter"},
+       {"Silicom Bypass PEG6BPI5-SD series adapter"},
+       {"Silicom Bypass PEG4BPFI5-SD series adapter"},
+       {"Silicom Bypass PEG4BPFI5LX-SD series adapter"},
+       {"Silicom Bypass MEG2BPFILXLN-SD series adapter"},
+       {"Silicom Bypass PEG2BPIX1-SD series adapter"},
+       {"Silicom Bypass MEG2BPFILXNX-SD series adapter"},
+       {"Silicom Bypass XE10G2BPIT-SD series adapter"},
+       {"Silicom Bypass XE10G2BPICX4-SD series adapter"},
+       {"Silicom Bypass XE10G2BPISR-SD series adapter"},
+       {"Silicom Bypass XE10G2BPILR-SD series adapter"},
+       {"Intel Bypass PEG2BPFII0 series adapter"},
+       {"Silicom Bypass XE10G2BPIXR series adapter"},
+       {"Silicom Bypass PE10G2DBISR series adapter"},
+       {"Silicom Bypass PEG2BI5SC6 series adapter"},
+       {"Silicom Bypass PEG6BPI5FC series adapter"},
+       {"Silicom Bypass PE10G2BPTCX4 series adapter"},
+       {"Silicom Bypass PE10G2BPTSR series adapter"},
+       {"Silicom Bypass PE10G2BPTLR series adapter"},
+       {"Silicom Bypass PE10G2BPTT series adapter"},
+       {"Silicom Bypass PEG4BPI6 series adapter"},
+       {"Silicom Bypass PEG4BPFI6 series adapter"},
+       {"Silicom Bypass PEG4BPFI6LX series adapter"},
+       {"Silicom Bypass PEG4BPFI6ZX series adapter"},
+       {"Silicom Bypass PEG2BPI6 series adapter"},
+       {"Silicom Bypass PEG2BPFI6 series adapter"},
+       {"Silicom Bypass PEG2BPFI6LX series adapter"},
+       {"Silicom Bypass PEG2BPFI6ZX series adapter"},
+       {"Silicom Bypass PEG2BPFI6FLXM series adapter"},
+       {"Silicom Bypass PEG4BPI6FC series adapter"},
+       {"Silicom Bypass PEG4BPFI6FC series adapter"},
+       {"Silicom Bypass PEG4BPFI6FCLX series adapter"},
+       {"Silicom Bypass PEG4BPFI6FCZX series adapter"},
+       {"Silicom Bypass PEG6BPI6 series adapter"},
+       {"Silicom Bypass PEG2BPI6SC6 series adapter"},
+       {"Silicom Bypass MEG2BPI6 series adapter"},
+       {"Silicom Bypass XEG2BPI6 series adapter"},
+       {"Silicom Bypass MEG4BPI6 series adapter"},
+       {"Silicom Bypass PEG2BPFI5-SD series adapter"},
+       {"Silicom Bypass PEG2BPFI5LX-SD series adapter"},
+       {"Silicom Bypass PXEG4BPFI-SD series adapter"},
+       {"Silicom Bypass MxEG2BPI6 series adapter"},
+       {"Silicom Bypass MxEG2BPFI6 series adapter"},
+       {"Silicom Bypass MxEG2BPFI6LX series adapter"},
+       {"Silicom Bypass MxEG2BPFI6ZX series adapter"},
+       {"Silicom Bypass MxEG4BPI6 series adapter"},
+       {"Silicom Bypass MxEG4BPFI6 series adapter"},
+       {"Silicom Bypass MxEG4BPFI6LX series adapter"},
+       {"Silicom Bypass MxEG4BPFI6ZX series adapter"},
+       {"Silicom Bypass MxEG6BPI6 series adapter"},
+       {"Silicom Bypass MxE2G4BPi80 series adapter"},
+       {"Silicom Bypass MxE2G4BPFi80 series adapter"},
+       {"Silicom Bypass MxE2G4BPFi80LX series adapter"},
+       {"Silicom Bypass MxE2G4BPFi80ZX series adapter"},
+       {"Silicom Bypass PE210G2SPI9 series adapter"},
+       {"Silicom Bypass MxE210G2BPI9CX4 series adapter"},
+       {"Silicom Bypass MxE210G2BPI9SR series adapter"},
+       {"Silicom Bypass MxE210G2BPI9LR series adapter"},
+       {"Silicom Bypass MxE210G2BPI9T series adapter"},
+       {"Silicom Bypass PE210G2BPI9CX4 series adapter"},
+       {"Silicom Bypass PE210G2BPI9SR series adapter"},
+       {"Silicom Bypass PE210G2BPI9LR series adapter"},
+       {"Silicom Bypass PE210G2BPI9T series adapter"},
+       {"Silicom Bypass M2EG2BPFI6 series adapter"},
+       {"Silicom Bypass M2EG2BPFI6LX series adapter"},
+       {"Silicom Bypass M2EG2BPFI6ZX series adapter"},
+       {"Silicom Bypass M2EG4BPI6 series adapter"},
+       {"Silicom Bypass M2EG4BPFI6 series adapter"},
+       {"Silicom Bypass M2EG4BPFI6LX series adapter"},
+       {"Silicom Bypass M2EG4BPFI6ZX series adapter"},
+       {"Silicom Bypass M2EG6BPI6 series adapter"},
+       {"Silicom Bypass PEG2DBI6    series adapter"},
+       {"Silicom Bypass PEG2DBFI6   series adapter"},
+       {"Silicom Bypass PEG2DBFI6LX series adapter"},
+       {"Silicom Bypass PEG2DBFI6ZX series adapter"},
+       {"Silicom Bypass PE2G4BPi80 series adapter"},
+       {"Silicom Bypass PE2G4BPFi80 series adapter"},
+       {"Silicom Bypass PE2G4BPFi80LX series adapter"},
+       {"Silicom Bypass PE2G4BPFi80ZX series adapter"},
+       {"Silicom Bypass PE2G4BPi80L series adapter"},
+       {"Silicom Bypass MxE2G8BPi80A series adapter"},
+       {"Silicom Bypass PE2G2BPi35 series adapter"},
+       {"Silicom Bypass PAC1200BPi35 series adapter"},
+       {"Silicom Bypass PE2G2BPFi35 series adapter"},
+       {"Silicom Bypass PE2G2BPFi35LX series adapter"},
+       {"Silicom Bypass PE2G2BPFi35ZX series adapter"},
+       {"Silicom Bypass PE2G4BPi35 series adapter"},
+       {"Silicom Bypass PE2G4BPi35L series adapter"},
+       {"Silicom Bypass PE2G4BPFi35 series adapter"},
+       {"Silicom Bypass PE2G4BPFi35LX series adapter"},
+       {"Silicom Bypass PE2G4BPFi35ZX series adapter"},
+       {"Silicom Bypass PE2G6BPi35 series adapter"},
+       {"Silicom Bypass PE2G6BPi35CX series adapter"},
+       {"Silicom Bypass PE2G2BPi80 series adapter"},
+       {"Silicom Bypass PE2G2BPFi80 series adapter"},
+       {"Silicom Bypass PE2G2BPFi80LX series adapter"},
+       {"Silicom Bypass PE2G2BPFi80ZX series adapter"},
+       {"Silicom Bypass M2E10G2BPI9CX4 series adapter"},
+       {"Silicom Bypass M2E10G2BPI9SR series adapter"},
+       {"Silicom Bypass M2E10G2BPI9LR series adapter"},
+       {"Silicom Bypass M2E10G2BPI9T series adapter"},
+       {"Silicom Bypass MxE2G8BPi80 series adapter"},
+       {"Silicom Bypass PE210G2DBi9SR series adapter"},
+       {"Silicom Bypass PE210G2DBi9SRRB series adapter"},
+       {"Silicom Bypass PE210G2DBi9LR series adapter"},
+       {"Silicom Bypass PE210G2DBi9LRRB series adapter"},
+       {"Silicom Bypass PE310G4DBi9-SR series adapter"},
+       {"Silicom Bypass PE310G4BPi9T series adapter"},
+       {"Silicom Bypass PE310G4BPi9SR series adapter"},
+       {"Silicom Bypass PE310G4BPi9LR series adapter"},
+       {"Silicom Bypass PE210G2BPi40T series adapter"},
+       {0},
+ };
+ static bpmod_info_t tx_ctl_pci_tbl[] = {
+       {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFI_SSID, PXG2BPFI,
+        "PXG2BPFI-SD"},
+       {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFIL_SSID, PXG2BPFIL,
+        "PXG2BPFIL-SD"},
+       {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFILX_SSID, PXG2BPFILX,
+        "PXG2BPFILX-SD"},
+       {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFILLX_SSID, PXG2BPFILLX,
+        "PXG2BPFILLXSD"},
+       {0x8086, 0x1010, SILICOM_SVID, SILICOM_PXGBPI_SSID, PXGBPI,
+        "PXG2BPI-SD"},
+       {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXGBPIG_SSID, PXGBPIG,
+        "PXG2BPIG-SD"},
+       {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2TBFI_SSID, PXG2TBFI,
+        "PXG2TBFI-SD"},
+       {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXG4BPI_SSID, PXG4BPI,
+        "PXG4BPI-SD"},
+       {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG4BPFI_SSID, PXG4BPFI,
+        "PXG4BPFI-SD"},
+       {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG4BPFILX_SSID, PXG4BPFILX,
+        "PXG4BPFILX-SD"},
+       {0x8086, 0x1079, SILICOM_SVID, SILICOM_PEG4BPI_SSID, PEG4BPI,
+        "PEXG4BPI-SD"},
+       {0x8086, 0x105e, SILICOM_SVID, SILICOM_PEG2BPI_SSID, PEG2BPI,
+        "PEG2BPI-SD"},
+       {0x8086, 0x105e, SILICOM_SVID, SILICOM_PEG4BPIN_SSID, PEG4BPIN,
+        "PEG4BPI-SD"},
+       {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2BPFI_SSID, PEG2BPFI,
+        "PEG2BPFI-SD"},
+       {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2BPFILX_SSID, PEG2BPFILX,
+        "PEG2BPFILX-SD"},
+       {0x8086, 0x107a, SILICOM_SVID, SILICOM_PMCXG2BPFI_SSID, PMCXG2BPFI,
+        "PMCX2BPFI-SD"},
+       {0x8086, 0x107a, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG2BPFIN_SSID,
+        PMCXG2BPFIN, "PMCX2BPFI-N"},
+       {0x8086, INTEL_PEG4BPII_PID, 0x8086, INTEL_PEG4BPII_SSID, PEG4BPII,
+        "PEG4BPII"},
+       {0x8086, INTEL_PEG4BPIIO_PID, 0x8086, INTEL_PEG4BPIIO_SSID, PEG4BPIIO,
+        "PEG4BPII0"},
+       {0x8086, INTEL_PEG4BPFII_PID, 0x8086, INTEL_PEG4BPFII_SSID, PEG4BPFII,
+        "PEG4BPFII"},
+       {0x8086, 0x1079, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG2BPIN_SSID,
+        PMCXG2BPIN, "PMCX2BPI-N"},
+       {0x8086, 0x1079, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG4BPIN_SSID,
+        PMCXG4BPIN, "PMCX4BPI-N"},
+       {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXG2BISC1_SSID, PXG2BISC1,
+        "PXG2BISC1-SD"},
+       {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2TBFI_SSID, PEG2TBFI,
+        "PEG2TBFI-SD"},
+       {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXG2TBI_SSID, PXG2TBI,
+        "PXG2TBI-SD"},
+       {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG4BPFID_SSID, PXG4BPFID,
+        "PXG4BPFID-SD"},
+       {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG4BPFI_SSID, PEG4BPFI,
+        "PEG4BPFI-SD"},
+       {0x8086, 0x105e, SILICOM_SVID, SILICOM_PEG4BPIPT_SSID, PEG4BPIPT,
+        "PEG4BPIPT-SD"},
+       {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXG6BPI_SSID, PXG6BPI,
+        "PXG6BPI-SD"},
+       {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG4BPIL_SSID /*PCI_ANY_ID */ , PEG4BPIL, "PEG4BPIL-SD"},
+       {0x8086, 0x1079, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG2BPIN2_SSID,
+        PMCXG2BPIN2, "PMCX2BPI-N2"},
+       {0x8086, 0x1079, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG4BPIN2_SSID,
+        PMCXG4BPIN2, "PMCX4BPI-N2"},
+       {0x8086, 0x1079, SILICOM_SVID, SILICOM_PMCX2BPI_SSID, PMCX2BPI,
+        "PMCX2BPI-SD"},
+       {0x8086, 0x1079, SILICOM_SVID, SILICOM_PMCX4BPI_SSID, PMCX4BPI,
+        "PMCX4BPI-SD"},
+       {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2BPFID_SSID, PEG2BPFID,
+        "PEG2BPFID-SD"},
+       {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2BPFIDLX_SSID, PEG2BPFIDLX,
+        "PEG2BPFIDLXSD"},
+       {0x8086, 0x105f, SILICOM_SVID, SILICOM_MEG2BPFILN_SSID, MEG2BPFILN,
+        "MEG2BPFILN-SD"},
+       {0x8086, 0x105f, SILICOM_SVID, SILICOM_MEG2BPFINX_SSID, MEG2BPFINX,
+        "MEG2BPFINX-SD"},
+       {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG4BPFILX_SSID, PEG4BPFILX,
+        "PEG4BPFILX-SD"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_PE10G2BPISR_SSID,
+        PE10G2BPISR, "PE10G2BPISR"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_PE10G2BPILR_SSID,
+        PE10G2BPILR, "PE10G2BPILR"},
+       {0x8086, 0x10a9, SILICOM_SVID, SILICOM_MHIO8AD_SSID, MHIO8AD,
+        "MHIO8AD-SD"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_PE10G2BPICX4_SSID,
+        PE10G2BPISR, "PE10G2BPICX4"},
+       {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG2BPI5_SSID /*PCI_ANY_ID */ , PEG2BPI5, "PEG2BPI5-SD"},
+       {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG6BPI_SSID /*PCI_ANY_ID */ , PEG6BPI, "PEG6BPI5"},
+       {0x8086, 0x10a9, SILICOM_SVID /*PCI_ANY_ID */ , SILICOM_PEG4BPFI5_SSID,
+        PEG4BPFI5, "PEG4BPFI5"},
+       {0x8086, 0x10a9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG4BPFI5LX_SSID, PEG4BPFI5LX, "PEG4BPFI5LX"},
+       {0x8086, 0x105f, SILICOM_SVID, SILICOM_MEG2BPFILXLN_SSID, MEG2BPFILXLN,
+        "MEG2BPFILXLN"},
+       {0x8086, 0x105e, SILICOM_SVID, SILICOM_PEG2BPIX1_SSID, PEG2BPIX1,
+        "PEG2BPIX1-SD"},
+       {0x8086, 0x105f, SILICOM_SVID, SILICOM_MEG2BPFILXNX_SSID, MEG2BPFILXNX,
+        "MEG2BPFILXNX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_XE10G2BPIT_SSID, XE10G2BPIT,
+        "XE10G2BPIT"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_XE10G2BPICX4_SSID,
+        XE10G2BPICX4, "XE10G2BPICX4"},
+       {0x8086, 0x10C6, SILICOM_SVID, SILICOM_XE10G2BPISR_SSID, XE10G2BPISR,
+        "XE10G2BPISR"},
+       {0x8086, 0x10C6, SILICOM_SVID, SILICOM_XE10G2BPILR_SSID, XE10G2BPILR,
+        "XE10G2BPILR"},
+       {0x8086, 0x10C6, NOKIA_XE10G2BPIXR_SVID, NOKIA_XE10G2BPIXR_SSID,
+        XE10G2BPIXR, "XE10G2BPIXR"},
+       {0x8086, 0x10C6, SILICOM_SVID, SILICOM_PE10GDBISR_SSID, PE10GDBISR,
+        "PE10G2DBISR"},
+       {0x8086, 0x10C6, SILICOM_SVID, SILICOM_PE10GDBILR_SSID, PE10GDBILR,
+        "PE10G2DBILR"},
+       {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG2BISC6_SSID /*PCI_ANY_ID */ , PEG2BISC6, "PEG2BI5SC6"},
+       {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG6BPIFC_SSID /*PCI_ANY_ID */ , PEG6BPIFC, "PEG6BPI5FC"},
+       {BROADCOM_VID, BROADCOM_PE10G2_PID, SILICOM_SVID,
+        SILICOM_PE10G2BPTCX4_SSID, PE10G2BPTCX4, "PE10G2BPTCX4"},
+       {BROADCOM_VID, BROADCOM_PE10G2_PID, SILICOM_SVID,
+        SILICOM_PE10G2BPTSR_SSID, PE10G2BPTSR, "PE10G2BPTSR"},
+       {BROADCOM_VID, BROADCOM_PE10G2_PID, SILICOM_SVID,
+        SILICOM_PE10G2BPTLR_SSID, PE10G2BPTLR, "PE10G2BPTLR"},
+       {BROADCOM_VID, BROADCOM_PE10G2_PID, SILICOM_SVID,
+        SILICOM_PE10G2BPTT_SSID, PE10G2BPTT, "PE10G2BPTT"},
+       /* {BROADCOM_VID, BROADCOM_PE10G2_PID, PCI_ANY_ID, PCI_ANY_ID, PE10G2BPTCX4, "PE10G2BPTCX4"}, */
+       {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG4BPI6_SSID /*PCI_ANY_ID */ , PEG4BPI6, "PEG4BPI6"},
+       {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG4BPFI6_SSID /*PCI_ANY_ID */ , PEG4BPFI6, "PEG4BPFI6"},
+       {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG4BPFI6LX_SSID /*PCI_ANY_ID */ , PEG4BPFI6LX, "PEG4BPFI6LX"},
+       {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG4BPFI6ZX_SSID /*PCI_ANY_ID */ , PEG4BPFI6ZX, "PEG4BPFI6ZX"},
+       {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG2BPI6_SSID /*PCI_ANY_ID */ , PEG2BPI6, "PEG2BPI6"},
+       {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG2BPFI6_SSID /*PCI_ANY_ID */ , PEG2BPFI6, "PEG2BPFI6"},
+       {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG2BPFI6LX_SSID /*PCI_ANY_ID */ , PEG2BPFI6LX, "PEG2BPFI6LX"},
+       {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG2BPFI6ZX_SSID /*PCI_ANY_ID */ , PEG2BPFI6ZX, "PEG2BPFI6ZX"},
+       {0x8086, 0x10e7, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG2BPFI6FLXM_SSID /*PCI_ANY_ID */ , PEG2BPFI6FLXM,
+        "PEG2BPFI6FLXM"},
+       {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG4BPI6FC_SSID /*PCI_ANY_ID */ , PEG4BPI6FC, "PEG4BPI6FC"},
+       {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG4BPFI6FC_SSID /*PCI_ANY_ID */ , PEG4BPFI6FC, "PEG4BPFI6FC"},
+       {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG4BPFI6FCLX_SSID /*PCI_ANY_ID */ , PEG4BPFI6FCLX,
+        "PEG4BPFI6FCLX"},
+       {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG4BPFI6FCZX_SSID /*PCI_ANY_ID */ , PEG4BPFI6FCZX,
+        "PEG4BPFI6FCZX"},
+       {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG6BPI6_SSID /*PCI_ANY_ID */ , PEG6BPI6, "PEG6BPI6"},
+       {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG2BPI6SC6_SSID /*PCI_ANY_ID */ , PEG2BPI6SC6,
+        "PEG6BPI62SC6"},
+       {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_MEG2BPI6_SSID /*PCI_ANY_ID */ , MEG2BPI6, "MEG2BPI6"},
+       {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_XEG2BPI6_SSID /*PCI_ANY_ID */ , XEG2BPI6, "XEG2BPI6"},
+       {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_MEG4BPI6_SSID /*PCI_ANY_ID */ , MEG4BPI6, "MEG4BPI6"},
+       {0x8086, 0x10a9, SILICOM_SVID /*PCI_ANY_ID */ , SILICOM_PEG2BPFI5_SSID,
+        PEG2BPFI5, "PEG2BPFI5"},
+       {0x8086, 0x10a9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG2BPFI5LX_SSID, PEG2BPFI5LX, "PEG2BPFI5LX"},
+       {0x8086, 0x105f, SILICOM_SVID, SILICOM_PXEG4BPFI_SSID, PXEG4BPFI,
+        "PXEG4BPFI-SD"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1EG2BPI6_SSID /*PCI_ANY_ID */ , M1EG2BPI6, "MxEG2BPI6"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1EG2BPFI6_SSID /*PCI_ANY_ID */ , M1EG2BPFI6, "MxEG2BPFI6"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1EG2BPFI6LX_SSID /*PCI_ANY_ID */ , M1EG2BPFI6LX,
+        "MxEG2BPFI6LX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1EG2BPFI6ZX_SSID /*PCI_ANY_ID */ , M1EG2BPFI6ZX,
+        "MxEG2BPFI6ZX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1EG4BPI6_SSID /*PCI_ANY_ID */ , M1EG4BPI6, "MxEG4BPI6"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1EG4BPFI6_SSID /*PCI_ANY_ID */ , M1EG4BPFI6, "MxEG4BPFI6"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1EG4BPFI6LX_SSID /*PCI_ANY_ID */ , M1EG4BPFI6LX,
+        "MxEG4BPFI6LX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1EG4BPFI6ZX_SSID /*PCI_ANY_ID */ , M1EG4BPFI6ZX,
+        "MxEG4BPFI6ZX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1EG6BPI6_SSID /*PCI_ANY_ID */ , M1EG6BPI6, "MxEG6BPI6"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1E2G4BPi80_SSID /*PCI_ANY_ID */ , M1E2G4BPi80, "MxE2G4BPi80"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1E2G4BPFi80_SSID /*PCI_ANY_ID */ , M1E2G4BPFi80,
+        "MxE2G4BPFi80"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1E2G4BPFi80LX_SSID /*PCI_ANY_ID */ , M1E2G4BPFi80LX,
+        "MxE2G4BPFi80LX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1E2G4BPFi80ZX_SSID /*PCI_ANY_ID */ , M1E2G4BPFi80ZX,
+        "MxE2G4BPFi80ZX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M2EG2BPFI6_SSID /*PCI_ANY_ID */ , M2EG2BPFI6, "M2EG2BPFI6"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M2EG2BPFI6LX_SSID /*PCI_ANY_ID */ , M2EG2BPFI6LX,
+        "M2EG2BPFI6LX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M2EG2BPFI6ZX_SSID /*PCI_ANY_ID */ , M2EG2BPFI6ZX,
+        "M2EG2BPFI6ZX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M2EG4BPI6_SSID /*PCI_ANY_ID */ , M2EG4BPI6, "M2EG4BPI6"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M2EG4BPFI6_SSID /*PCI_ANY_ID */ , M2EG4BPFI6, "M2EG4BPFI6"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M2EG4BPFI6LX_SSID /*PCI_ANY_ID */ , M2EG4BPFI6LX,
+        "M2EG4BPFI6LX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M2EG4BPFI6ZX_SSID /*PCI_ANY_ID */ , M2EG4BPFI6ZX,
+        "M2EG4BPFI6ZX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M2EG6BPI6_SSID /*PCI_ANY_ID */ , M2EG6BPI6, "M2EG6BPI6"},
+       {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG2DBI6_SSID /*PCI_ANY_ID */ , PEG2DBI6, "PEG2DBI6"},
+       {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG2DBFI6_SSID /*PCI_ANY_ID */ , PEG2DBFI6, "PEG2DBFI6"},
+       {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG2DBFI6LX_SSID /*PCI_ANY_ID */ , PEG2DBFI6LX, "PEG2DBFI6LX"},
+       {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PEG2DBFI6ZX_SSID /*PCI_ANY_ID */ , PEG2DBFI6ZX, "PEG2DBFI6ZX"},
+       {0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE210G2DBi9SR_SSID, PE210G2DBi9SR, "PE210G2DBi9SR"},
+       {0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE210G2DBi9LR_SSID, PE210G2DBi9LR, "PE210G2DBi9LR"},
+       {0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE310G4DBi940SR_SSID, PE310G4DBi940SR, "PE310G4DBi9SR"},
+       {0x8086, 0x10Fb, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE310G4BPi9T_SSID, PE310G4BPi9T, "PE310G4BPi9T"},
+       {0x8086, 0x10Fb, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE310G4BPi9SR_SSID, PE310G4BPi9SR, "PE310G4BPi9SR"},
+       {0x8086, 0x10Fb, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE310G4BPi9LR_SSID, PE310G4BPi9LR, "PE310G4BPi9LR"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G4BPi80_SSID /*PCI_ANY_ID */ , PE2G4BPi80, "PE2G4BPi80"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G4BPFi80_SSID /*PCI_ANY_ID */ , PE2G4BPFi80, "PE2G4BPFi80"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G4BPFi80LX_SSID /*PCI_ANY_ID */ , PE2G4BPFi80LX,
+        "PE2G4BPFi80LX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G4BPFi80ZX_SSID /*PCI_ANY_ID */ , PE2G4BPFi80ZX,
+        "PE2G4BPFi80ZX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G4BPi80L_SSID /*PCI_ANY_ID */ , PE2G4BPi80L, "PE2G4BPi80L"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M6E2G8BPi80A_SSID /*PCI_ANY_ID */ , M6E2G8BPi80A,
+        "MxE2G8BPi80A"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G2BPi35_SSID /*PCI_ANY_ID */ , PE2G2BPi35, "PE2G2BPi35"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PAC1200BPi35_SSID /*PCI_ANY_ID */ , PAC1200BPi35,
+        "PAC1200BPi35"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G2BPFi35_SSID /*PCI_ANY_ID */ , PE2G2BPFi35, "PE2G2BPFi35"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G2BPFi35LX_SSID /*PCI_ANY_ID */ , PE2G2BPFi35LX,
+        "PE2G2BPFi35LX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G2BPFi35ZX_SSID /*PCI_ANY_ID */ , PE2G2BPFi35ZX,
+        "PE2G2BPFi35ZX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G4BPi35_SSID /*PCI_ANY_ID */ , PE2G4BPi35, "PE2G4BPi35"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G4BPi35L_SSID /*PCI_ANY_ID */ , PE2G4BPi35L, "PE2G4BPi35L"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G4BPFi35_SSID /*PCI_ANY_ID */ , PE2G4BPFi35, "PE2G4BPFi35"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G4BPFi35LX_SSID /*PCI_ANY_ID */ , PE2G4BPFi35LX,
+        "PE2G4BPFi35LX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G4BPFi35ZX_SSID /*PCI_ANY_ID */ , PE2G4BPFi35ZX,
+        "PE2G4BPFi35ZX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G6BPi35_SSID /*PCI_ANY_ID */ , PE2G6BPi35, "PE2G6BPi35"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa0, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa1, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa2, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa3, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa4, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa5, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa6, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa7, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa8, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa9, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaaa, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaab, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaac, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaad, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaae, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaaf, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab0, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab1, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab2, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab3, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab4, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab5, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab6, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab7, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab8, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab9, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaba, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabb, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabc, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabd, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabe, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabf, PE2G6BPi35CX,
+        "PE2G6BPi35CX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G2BPi80_SSID /*PCI_ANY_ID */ , PE2G2BPi80, "PE2G2BPi80"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G2BPFi80_SSID /*PCI_ANY_ID */ , PE2G2BPFi80, "PE2G2BPFi80"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G2BPFi80LX_SSID /*PCI_ANY_ID */ , PE2G2BPFi80LX,
+        "PE2G2BPFi80LX"},
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE2G2BPFi80ZX_SSID /*PCI_ANY_ID */ , PE2G2BPFi80ZX,
+        "PE2G2BPFi80ZX"},
+       {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_MEG2BPI6_SSID /*PCI_ANY_ID */ , MEG2BPI6, "MEG2BPI6"},
+       {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_XEG2BPI6_SSID /*PCI_ANY_ID */ , XEG2BPI6, "XEG2BPI6"},
+ #if 0
+       {0x8086, 0x10fb, 0x8086, INTEL_PE210G2SPI9_SSID, PE210G2SPI9,
+        "PE210G2SPI9"},
+ #endif
+       {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1E10G2BPI9CX4_SSID /*PCI_ANY_ID */ , M1E10G2BPI9CX4,
+        "MxE210G2BPI9CX4"},
+       {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1E10G2BPI9SR_SSID /*PCI_ANY_ID */ , M1E10G2BPI9SR,
+        "MxE210G2BPI9SR"},
+       {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1E10G2BPI9LR_SSID /*PCI_ANY_ID */ , M1E10G2BPI9LR,
+        "MxE210G2BPI9LR"},
+       {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M1E10G2BPI9T_SSID /*PCI_ANY_ID */ , M1E10G2BPI9T,
+        "MxE210G2BPI9T"},
+       {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M2E10G2BPI9CX4_SSID /*PCI_ANY_ID */ , M2E10G2BPI9CX4,
+        "M2E10G2BPI9CX4"},
+       {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M2E10G2BPI9SR_SSID /*PCI_ANY_ID */ , M2E10G2BPI9SR,
+        "M2E10G2BPI9SR"},
+       {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M2E10G2BPI9LR_SSID /*PCI_ANY_ID */ , M2E10G2BPI9LR,
+        "M2E10G2BPI9LR"},
+       {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M2E10G2BPI9T_SSID /*PCI_ANY_ID */ , M2E10G2BPI9T,
+        "M2E10G2BPI9T"},
+       {0x8086, 0x10fb, SILICOM_SVID, SILICOM_PE210G2BPI9CX4_SSID,
+        PE210G2BPI9CX4, "PE210G2BPI9CX4"},
+       {0x8086, 0x10fb, SILICOM_SVID, SILICOM_PE210G2BPI9SR_SSID,
+        PE210G2BPI9SR, "PE210G2BPI9SR"},
+       {0x8086, 0x10fb, SILICOM_SVID, SILICOM_PE210G2BPI9LR_SSID,
+        PE210G2BPI9LR, "PE210G2BPI9LR"},
+       {0x8086, 0x10fb, SILICOM_SVID, SILICOM_PE210G2BPI9T_SSID, PE210G2BPI9T,
+        "PE210G2BPI9T"},
+ #if 0
+       {0x1374, 0x2c, SILICOM_SVID, SILICOM_PXG4BPI_SSID, PXG4BPI,
+        "PXG4BPI-SD"},
+       {0x1374, 0x2d, SILICOM_SVID, SILICOM_PXG4BPFI_SSID, PXG4BPFI,
+        "PXG4BPFI-SD"},
+       {0x1374, 0x3f, SILICOM_SVID, SILICOM_PXG2TBI_SSID, PXG2TBI,
+        "PXG2TBI-SD"},
+       {0x1374, 0x3d, SILICOM_SVID, SILICOM_PXG2BISC1_SSID, PXG2BISC1,
+        "PXG2BISC1-SD"},
+       {0x1374, 0x40, SILICOM_SVID, SILICOM_PEG4BPFI_SSID, PEG4BPFI,
+        "PEG4BPFI-SD"},
+ #ifdef BP_SELF_TEST
+       {0x1374, 0x28, SILICOM_SVID, 0x28, PXGBPI, "PXG2BPI-SD"},
+ #endif
+ #endif
+       {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_M6E2G8BPi80_SSID /*PCI_ANY_ID */ , M6E2G8BPi80, "MxE2G8BPi80"},
+       {0x8086, 0x1528, SILICOM_SVID /*PCI_ANY_ID */ ,
+        SILICOM_PE210G2BPi40_SSID /*PCI_ANY_ID */ , PE210G2BPi40,
+        "PE210G2BPi40T"},
+       /* required last entry */
+       {0,}
+ };
+ static void find_fw(bpctl_dev_t *dev)
+ {
+       unsigned long mmio_start, mmio_len;
+       struct pci_dev *pdev1 = dev->pdev;
+       if ((OLD_IF_SERIES(dev->subdevice)) ||
+           (INTEL_IF_SERIES(dev->subdevice)))
+               dev->bp_fw_ver = 0xff;
+       else
+               dev->bp_fw_ver = bypass_fw_ver(dev);
+       if (dev->bp_10gb == 1 && dev->bp_fw_ver == 0xff) {
+               int cnt = 100;
+               while (cnt--) {
+                       iounmap((void *)dev->mem_map);
+                       mmio_start = pci_resource_start(pdev1, 0);
+                       mmio_len = pci_resource_len(pdev1, 0);
+                       dev->mem_map = (unsigned long)
+                           ioremap(mmio_start, mmio_len);
+                       dev->bp_fw_ver = bypass_fw_ver(dev);
+                       if (dev-> bp_fw_ver == 0xa8)
+                               break;
+               }
+       }
+       /* dev->bp_fw_ver=0xa8; */
+       printk("firmware version: 0x%x\n", dev->bp_fw_ver);
+ }
+ static int init_one(bpctl_dev_t *dev, bpmod_info_t *info, struct pci_dev *pdev1)
+ {
+       unsigned long mmio_start, mmio_len;
+       dev->pdev = pdev1;
+       mmio_start = pci_resource_start(pdev1, 0);
+       mmio_len = pci_resource_len(pdev1, 0);
+       dev->desc = dev_desc[info->index].name;
+       dev->name = info->bp_name;
+       dev->device = info->device;
+       dev->vendor = info->vendor;
+       dev->subdevice = info->subdevice;
+       dev->subvendor = info->subvendor;
+       dev->func = PCI_FUNC(pdev1->devfn);
+       dev->slot = PCI_SLOT(pdev1->devfn);
+       dev->bus = pdev1->bus->number;
+       dev->mem_map = (unsigned long)ioremap(mmio_start, mmio_len);
+ #ifdef BP_SYNC_FLAG
+       spin_lock_init(&dev->bypass_wr_lock);
+ #endif
+       if (BP10G9_IF_SERIES(dev->subdevice))
+               dev->bp_10g9 = 1;
+       if (BP10G_IF_SERIES(dev->subdevice))
+               dev->bp_10g = 1;
+       if (PEG540_IF_SERIES(dev->subdevice))
+               dev->bp_540 = 1;
+       if (PEGF5_IF_SERIES(dev->subdevice))
+               dev->bp_fiber5 = 1;
+       if (PEG80_IF_SERIES(dev->subdevice))
+               dev->bp_i80 = 1;
+       if (PEGF80_IF_SERIES(dev->subdevice))
+               dev->bp_i80 = 1;
+       if ((dev->subdevice & 0xa00) == 0xa00)
+               dev->bp_i80 = 1;
+       if (BP10GB_IF_SERIES(dev->subdevice)) {
+               if (dev->ifindex == 0) {
+                       unregister_chrdev(major_num, DEVICE_NAME);
+                       printk("Please load network driver for %s adapter!\n",
+                            dev->name);
+                       return -1;
+               }
+               if (dev->ndev && !(dev->ndev->flags & IFF_UP)) {
+                       unregister_chrdev(major_num, DEVICE_NAME);
+                       printk("Please bring up network interfaces for %s adapter!\n",
+                            dev->name);
+                       return -1;
+               }
+               dev->bp_10gb = 1;
+       }
+       if (!dev->bp_10g9) {
+               if (is_bypass_fn(dev)) {
+                       printk(KERN_INFO "%s found, ",
+                              dev->name);
+                       find_fw(dev);
+               }
+               dev->wdt_status = WDT_STATUS_UNKNOWN;
+               dev->reset_time = 0;
+               atomic_set(&dev->wdt_busy, 0);
+               dev->bp_status_un = 1;
+               bypass_caps_init(dev);
+               init_bypass_wd_auto(dev);
+               init_bypass_tpl_auto(dev);
+               if (NOKIA_SERIES(dev->subdevice))
+                       reset_cont(dev);
+       }
+ #ifdef BP_SELF_TEST
+       if ((dev->bp_tx_data = kzalloc(BPTEST_DATA_LEN, GFP_KERNEL))) {
+               memset(dev->bp_tx_data, 0xff, 6);
+               memset(dev->bp_tx_data + 6, 0x0, 1);
+               memset(dev->bp_tx_data + 7, 0xaa, 5);
+               *(__be16 *)(dev->bp_tx_data + 12) = htons(ETH_P_BPTEST);
+       } else
+               printk("bp_ctl: Memory allocation error!\n");
+ #endif
+       return 0;
+ }
+ /*
+ * Initialize the module - Register the character device
+ */
+ static int __init bypass_init_module(void)
+ {
+       int ret_val, idx, idx_dev = 0;
+       struct pci_dev *pdev1 = NULL;
+       bpctl_dev_t *dev;
+       printk(BP_MOD_DESCR " v" BP_MOD_VER "\n");
+       ret_val = register_chrdev(major_num, DEVICE_NAME, &Fops);
+       if (ret_val < 0) {
+               printk("%s failed with %d\n", DEVICE_NAME, ret_val);
+               return ret_val;
+       }
+       major_num = ret_val;    /* dynamic */
+       for (idx = 0; tx_ctl_pci_tbl[idx].vendor; idx++) {
+               while ((pdev1 = pci_get_subsys(tx_ctl_pci_tbl[idx].vendor,
+                                              tx_ctl_pci_tbl[idx].device,
+                                              tx_ctl_pci_tbl[idx].subvendor,
+                                              tx_ctl_pci_tbl[idx].subdevice,
+                                              pdev1))) {
+                       device_num++;
+               }
+       }
+       if (!device_num) {
+               printk("No such device\n");
+               unregister_chrdev(major_num, DEVICE_NAME);
+               return -1;
+       }
+       bpctl_dev_arr = kmalloc((device_num) * sizeof(bpctl_dev_t), GFP_KERNEL);
+       if (!bpctl_dev_arr) {
+               printk("Allocation error\n");
+               unregister_chrdev(major_num, DEVICE_NAME);
+               return -1;
+       }
+       memset(bpctl_dev_arr, 0, ((device_num) * sizeof(bpctl_dev_t)));
+       pdev1 = NULL;
+       dev = bpctl_dev_arr;
+       for (idx = 0; tx_ctl_pci_tbl[idx].vendor; idx++) {
+               while ((pdev1 = pci_get_subsys(tx_ctl_pci_tbl[idx].vendor,
+                                              tx_ctl_pci_tbl[idx].device,
+                                              tx_ctl_pci_tbl[idx].subvendor,
+                                              tx_ctl_pci_tbl[idx].subdevice,
+                                              pdev1))) {
+                       if (init_one(dev, &tx_ctl_pci_tbl[idx], pdev1) < 0)
+                               return -1;
+                       dev++;
+               }
+       }
+       if_scan_init();
+       sema_init(&bpctl_sema, 1);
+       spin_lock_init(&bpvm_lock);
+       {
+               bpctl_dev_t *pbpctl_dev_c = NULL;
+               for (idx_dev = 0, dev = bpctl_dev_arr;
+                    idx_dev < device_num && dev->pdev;
+                    idx_dev++, dev++) {
+                       if (dev->bp_10g9) {
+                               pbpctl_dev_c = get_status_port_fn(dev);
+                               if (is_bypass_fn(dev)) {
+                                       printk(KERN_INFO "%s found, ",
+                                              dev->name);
+                                       dev->bp_fw_ver = bypass_fw_ver(dev);
+                                       printk("firmware version: 0x%x\n",
+                                              dev->bp_fw_ver);
+                               }
+                               dev->wdt_status = WDT_STATUS_UNKNOWN;
+                               dev->reset_time = 0;
+                               atomic_set(&dev->wdt_busy, 0);
+                               dev->bp_status_un = 1;
+                               bypass_caps_init(dev);
+                               init_bypass_wd_auto(dev);
+                               init_bypass_tpl_auto(dev);
+                       }
+               }
+       }
+       register_netdevice_notifier(&bp_notifier_block);
+ #ifdef BP_PROC_SUPPORT
+       {
+               int i = 0;
+               /* unsigned long flags; */
+               /* rcu_read_lock(); */
+               bp_proc_create();
+               for (i = 0; i < device_num; i++) {
+                       if (bpctl_dev_arr[i].ifindex) {
+                               /* spin_lock_irqsave(&bpvm_lock, flags); */
+                               bypass_proc_remove_dev_sd(&bpctl_dev_arr[i]);
+                               bypass_proc_create_dev_sd(&bpctl_dev_arr[i]);
+                               /* spin_unlock_irqrestore(&bpvm_lock, flags); */
+                       }
+               }
+               /* rcu_read_unlock(); */
+       }
+ #endif
+       return 0;
+ }
+ /*
+ * Cleanup - unregister the appropriate file from /proc
+ */
+ static void __exit bypass_cleanup_module(void)
+ {
+       int i;
+       unregister_netdevice_notifier(&bp_notifier_block);
+       for (i = 0; i < device_num; i++) {
+               /* unsigned long flags; */
+ #ifdef BP_PROC_SUPPORT
+ /*    spin_lock_irqsave(&bpvm_lock, flags);
+       rcu_read_lock(); */
+               bypass_proc_remove_dev_sd(&bpctl_dev_arr[i]);
 -              if (bpctl_dev_arr[i].bp_tx_data)
 -                      kfree(bpctl_dev_arr[i].bp_tx_data);
++/*    spin_unlock_irqrestore(&bpvm_lock, flags);
+       rcu_read_unlock(); */
+ #endif
+               remove_bypass_wd_auto(&bpctl_dev_arr[i]);
+               bpctl_dev_arr[i].reset_time = 0;
+               remove_bypass_tpl_auto(&bpctl_dev_arr[i]);
+       }
+       /* unmap all devices */
+       for (i = 0; i < device_num; i++) {
+ #ifdef BP_SELF_TEST
 -      if (bpctl_dev_arr)
 -              kfree(bpctl_dev_arr);
++              kfree(bpctl_dev_arr[i].bp_tx_data);
+ #endif
+               iounmap((void *)(bpctl_dev_arr[i].mem_map));
+       }
+       /* free all devices space */
 -* Unregister the device                             
++      kfree(bpctl_dev_arr);
+ /*
++* Unregister the device
+ */
+       unregister_chrdev(major_num, DEVICE_NAME);
+ }
+ module_init(bypass_init_module);
+ module_exit(bypass_cleanup_module);
+ int is_bypass_sd(int ifindex)
+ {
+       return is_bypass(get_dev_idx_p(ifindex));
+ }
+ int set_bypass_sd(int ifindex, int bypass_mode)
+ {
+       return set_bypass_fn(get_dev_idx_p(ifindex), bypass_mode);
+ }
+ int get_bypass_sd(int ifindex)
+ {
+       return get_bypass_fn(get_dev_idx_p(ifindex));
+ }
+ int get_bypass_change_sd(int ifindex)
+ {
+       return get_bypass_change_fn(get_dev_idx_p(ifindex));
+ }
+ int set_dis_bypass_sd(int ifindex, int dis_param)
+ {
+       return set_dis_bypass_fn(get_dev_idx_p(ifindex), dis_param);
+ }
+ int get_dis_bypass_sd(int ifindex)
+ {
+       return get_dis_bypass_fn(get_dev_idx_p(ifindex));
+ }
+ int set_bypass_pwoff_sd(int ifindex, int bypass_mode)
+ {
+       return set_bypass_pwoff_fn(get_dev_idx_p(ifindex), bypass_mode);
+ }
+ int get_bypass_pwoff_sd(int ifindex)
+ {
+       return get_bypass_pwoff_fn(get_dev_idx_p(ifindex));
+ }
+ int set_bypass_pwup_sd(int ifindex, int bypass_mode)
+ {
+       return set_bypass_pwup_fn(get_dev_idx_p(ifindex), bypass_mode);
+ }
+ int get_bypass_pwup_sd(int ifindex)
+ {
+       return get_bypass_pwup_fn(get_dev_idx_p(ifindex));
+ }
+ int set_bypass_wd_sd(int if_index, int ms_timeout, int *ms_timeout_set)
+ {
+       if ((is_bypass(get_dev_idx_p(if_index))) <= 0)
+               return BP_NOT_CAP;
+       *ms_timeout_set = set_bypass_wd_fn(get_dev_idx_p(if_index), ms_timeout);
+       return 0;
+ }
+ int get_bypass_wd_sd(int ifindex, int *timeout)
+ {
+       return get_bypass_wd_fn(get_dev_idx_p(ifindex), timeout);
+ }
+ int get_wd_expire_time_sd(int ifindex, int *time_left)
+ {
+       return get_wd_expire_time_fn(get_dev_idx_p(ifindex), time_left);
+ }
+ int reset_bypass_wd_timer_sd(int ifindex)
+ {
+       return reset_bypass_wd_timer_fn(get_dev_idx_p(ifindex));
+ }
+ int get_wd_set_caps_sd(int ifindex)
+ {
+       return get_wd_set_caps_fn(get_dev_idx_p(ifindex));
+ }
+ int set_std_nic_sd(int ifindex, int nic_mode)
+ {
+       return set_std_nic_fn(get_dev_idx_p(ifindex), nic_mode);
+ }
+ int get_std_nic_sd(int ifindex)
+ {
+       return get_std_nic_fn(get_dev_idx_p(ifindex));
+ }
+ int set_tap_sd(int ifindex, int tap_mode)
+ {
+       return set_tap_fn(get_dev_idx_p(ifindex), tap_mode);
+ }
+ int get_tap_sd(int ifindex)
+ {
+       return get_tap_fn(get_dev_idx_p(ifindex));
+ }
+ int set_tap_pwup_sd(int ifindex, int tap_mode)
+ {
+       return set_tap_pwup_fn(get_dev_idx_p(ifindex), tap_mode);
+ }
+ int get_tap_pwup_sd(int ifindex)
+ {
+       return get_tap_pwup_fn(get_dev_idx_p(ifindex));
+ }
+ int get_tap_change_sd(int ifindex)
+ {
+       return get_tap_change_fn(get_dev_idx_p(ifindex));
+ }
+ int set_dis_tap_sd(int ifindex, int dis_param)
+ {
+       return set_dis_tap_fn(get_dev_idx_p(ifindex), dis_param);
+ }
+ int get_dis_tap_sd(int ifindex)
+ {
+       return get_dis_tap_fn(get_dev_idx_p(ifindex));
+ }
+ int set_bp_disc_sd(int ifindex, int disc_mode)
+ {
+       return set_disc_fn(get_dev_idx_p(ifindex), disc_mode);
+ }
+ int get_bp_disc_sd(int ifindex)
+ {
+       return get_disc_fn(get_dev_idx_p(ifindex));
+ }
+ int set_bp_disc_pwup_sd(int ifindex, int disc_mode)
+ {
+       return set_disc_pwup_fn(get_dev_idx_p(ifindex), disc_mode);
+ }
+ int get_bp_disc_pwup_sd(int ifindex)
+ {
+       return get_disc_pwup_fn(get_dev_idx_p(ifindex));
+ }
+ int get_bp_disc_change_sd(int ifindex)
+ {
+       return get_disc_change_fn(get_dev_idx_p(ifindex));
+ }
+ int set_bp_dis_disc_sd(int ifindex, int dis_param)
+ {
+       return set_dis_disc_fn(get_dev_idx_p(ifindex), dis_param);
+ }
+ int get_bp_dis_disc_sd(int ifindex)
+ {
+       return get_dis_disc_fn(get_dev_idx_p(ifindex));
+ }
+ int get_wd_exp_mode_sd(int ifindex)
+ {
+       return get_wd_exp_mode_fn(get_dev_idx_p(ifindex));
+ }
+ int set_wd_exp_mode_sd(int ifindex, int param)
+ {
+       return set_wd_exp_mode_fn(get_dev_idx_p(ifindex), param);
+ }
+ int reset_cont_sd(int ifindex)
+ {
+       return reset_cont_fn(get_dev_idx_p(ifindex));
+ }
+ int set_tx_sd(int ifindex, int tx_state)
+ {
+       return set_tx_fn(get_dev_idx_p(ifindex), tx_state);
+ }
+ int set_tpl_sd(int ifindex, int tpl_state)
+ {
+       return set_tpl_fn(get_dev_idx_p(ifindex), tpl_state);
+ }
+ int set_bp_hw_reset_sd(int ifindex, int status)
+ {
+       return set_bp_hw_reset_fn(get_dev_idx_p(ifindex), status);
+ }
+ int set_wd_autoreset_sd(int ifindex, int param)
+ {
+       return set_wd_autoreset_fn(get_dev_idx_p(ifindex), param);
+ }
+ int get_wd_autoreset_sd(int ifindex)
+ {
+       return get_wd_autoreset_fn(get_dev_idx_p(ifindex));
+ }
+ int get_bypass_caps_sd(int ifindex)
+ {
+       return get_bypass_caps_fn(get_dev_idx_p(ifindex));
+ }
+ int get_bypass_slave_sd(int ifindex)
+ {
+       bpctl_dev_t *pbpctl_dev_out;
+       int ret = get_bypass_slave_fn(get_dev_idx_p(ifindex), &pbpctl_dev_out);
+       if (ret == 1)
+               return pbpctl_dev_out->ifindex;
+       return -1;
+ }
+ int get_tx_sd(int ifindex)
+ {
+       return get_tx_fn(get_dev_idx_p(ifindex));
+ }
+ int get_tpl_sd(int ifindex)
+ {
+       return get_tpl_fn(get_dev_idx_p(ifindex));
+ }
+ int get_bp_hw_reset_sd(int ifindex)
+ {
+       return get_bp_hw_reset_fn(get_dev_idx_p(ifindex));
+ }
+ int get_bypass_info_sd(int ifindex, struct bp_info *bp_info)
+ {
+       return get_bypass_info_fn(get_dev_idx_p(ifindex), bp_info->prod_name, &bp_info->fw_ver);
+ }
+ int bp_if_scan_sd(void)
+ {
+       if_scan_init();
+       return 0;
+ }
+ EXPORT_SYMBOL_NOVERS(is_bypass_sd);
+ EXPORT_SYMBOL_NOVERS(get_bypass_slave_sd);
+ EXPORT_SYMBOL_NOVERS(get_bypass_caps_sd);
+ EXPORT_SYMBOL_NOVERS(get_wd_set_caps_sd);
+ EXPORT_SYMBOL_NOVERS(set_bypass_sd);
+ EXPORT_SYMBOL_NOVERS(get_bypass_sd);
+ EXPORT_SYMBOL_NOVERS(get_bypass_change_sd);
+ EXPORT_SYMBOL_NOVERS(set_dis_bypass_sd);
+ EXPORT_SYMBOL_NOVERS(get_dis_bypass_sd);
+ EXPORT_SYMBOL_NOVERS(set_bypass_pwoff_sd);
+ EXPORT_SYMBOL_NOVERS(get_bypass_pwoff_sd);
+ EXPORT_SYMBOL_NOVERS(set_bypass_pwup_sd);
+ EXPORT_SYMBOL_NOVERS(get_bypass_pwup_sd);
+ EXPORT_SYMBOL_NOVERS(set_bypass_wd_sd);
+ EXPORT_SYMBOL_NOVERS(get_bypass_wd_sd);
+ EXPORT_SYMBOL_NOVERS(get_wd_expire_time_sd);
+ EXPORT_SYMBOL_NOVERS(reset_bypass_wd_timer_sd);
+ EXPORT_SYMBOL_NOVERS(set_std_nic_sd);
+ EXPORT_SYMBOL_NOVERS(get_std_nic_sd);
+ EXPORT_SYMBOL_NOVERS(set_tx_sd);
+ EXPORT_SYMBOL_NOVERS(get_tx_sd);
+ EXPORT_SYMBOL_NOVERS(set_tpl_sd);
+ EXPORT_SYMBOL_NOVERS(get_tpl_sd);
+ EXPORT_SYMBOL_NOVERS(set_bp_hw_reset_sd);
+ EXPORT_SYMBOL_NOVERS(get_bp_hw_reset_sd);
+ EXPORT_SYMBOL_NOVERS(set_tap_sd);
+ EXPORT_SYMBOL_NOVERS(get_tap_sd);
+ EXPORT_SYMBOL_NOVERS(get_tap_change_sd);
+ EXPORT_SYMBOL_NOVERS(set_dis_tap_sd);
+ EXPORT_SYMBOL_NOVERS(get_dis_tap_sd);
+ EXPORT_SYMBOL_NOVERS(set_tap_pwup_sd);
+ EXPORT_SYMBOL_NOVERS(get_tap_pwup_sd);
+ EXPORT_SYMBOL_NOVERS(set_wd_exp_mode_sd);
+ EXPORT_SYMBOL_NOVERS(get_wd_exp_mode_sd);
+ EXPORT_SYMBOL_NOVERS(set_wd_autoreset_sd);
+ EXPORT_SYMBOL_NOVERS(get_wd_autoreset_sd);
+ EXPORT_SYMBOL_NOVERS(set_bp_disc_sd);
+ EXPORT_SYMBOL_NOVERS(get_bp_disc_sd);
+ EXPORT_SYMBOL_NOVERS(get_bp_disc_change_sd);
+ EXPORT_SYMBOL_NOVERS(set_bp_dis_disc_sd);
+ EXPORT_SYMBOL_NOVERS(get_bp_dis_disc_sd);
+ EXPORT_SYMBOL_NOVERS(set_bp_disc_pwup_sd);
+ EXPORT_SYMBOL_NOVERS(get_bp_disc_pwup_sd);
+ EXPORT_SYMBOL_NOVERS(get_bypass_info_sd);
+ EXPORT_SYMBOL_NOVERS(bp_if_scan_sd);
+ #define BP_PROC_DIR "bypass"
+ static struct proc_dir_entry *bp_procfs_dir;
+ int bp_proc_create(void)
+ {
+       bp_procfs_dir = proc_mkdir(BP_PROC_DIR, init_net.proc_net);
+       if (bp_procfs_dir == (struct proc_dir_entry *)0) {
+               printk(KERN_DEBUG
+                      "Could not create procfs nicinfo directory %s\n",
+                      BP_PROC_DIR);
+               return -1;
+       }
+       return 0;
+ }
+ static int procfs_add(char *proc_name, const struct file_operations *fops,
+                     bpctl_dev_t *dev)
+ {
+       struct bypass_pfs_sd *pfs = &dev->bypass_pfs_set;
+       if (!proc_create_data(proc_name, 0644, pfs->bypass_entry, fops, dev))
+               return -1;
+       return 0;
+ }
+ #define RO_FOPS(name) \
+ static int name##_open(struct inode *inode, struct file *file)        \
+ {                                                             \
+       return single_open(file, show_##name, PDE_DATA(inode));\
+ }                                                             \
+ static const struct file_operations name##_ops = {            \
+       .open = name##_open,                                    \
+       .read = seq_read,                                       \
+       .llseek = seq_lseek,                                    \
+       .release = single_release,                              \
+ };
+ #define RW_FOPS(name) \
+ static int name##_open(struct inode *inode, struct file *file)        \
+ {                                                             \
+       return single_open(file, show_##name, PDE_DATA(inode));\
+ }                                                             \
+ static const struct file_operations name##_ops = {            \
+       .open = name##_open,                                    \
+       .read = seq_read,                                       \
+       .write = name##_write,                                  \
+       .llseek = seq_lseek,                                    \
+       .release = single_release,                              \
+ };
+ static int show_bypass_info(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       seq_printf(m, "Name\t\t\t%s\n", dev->name);
+       seq_printf(m, "Firmware version\t0x%x\n", dev->bp_fw_ver);
+       return 0;
+ }
+ RO_FOPS(bypass_info)
+ static int show_bypass_slave(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       bpctl_dev_t *slave = get_status_port_fn(dev);
+       if (!slave)
+               slave = dev;
+       if (!slave)
+               seq_printf(m, "fail\n");
+       else if (slave->ndev)
+               seq_printf(m, "%s\n", slave->ndev->name);
+       return 0;
+ }
+ RO_FOPS(bypass_slave)
+ static int show_bypass_caps(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_bypass_caps_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "-1\n");
+       else
+               seq_printf(m, "0x%x\n", ret);
+       return 0;
+ }
+ RO_FOPS(bypass_caps)
+ static int show_wd_set_caps(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_wd_set_caps_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "-1\n");
+       else
+               seq_printf(m, "0x%x\n", ret);
+       return 0;
+ }
+ RO_FOPS(wd_set_caps)
+ static int user_on_off(const void __user *buffer, size_t count)
+ {
+       char kbuf[256];
+       int length = 0;
+       if (count > (sizeof(kbuf) - 1))
+               return -1;
+       if (copy_from_user(&kbuf, buffer, count))
+               return -1;
+       kbuf[count] = '\0';
+       length = strlen(kbuf);
+       if (kbuf[length - 1] == '\n')
+               kbuf[--length] = '\0';
+       if (strcmp(kbuf, "on") == 0)
+               return 1;
+       if (strcmp(kbuf, "off") == 0)
+               return 0;
+       return 0;
+ }
+ static ssize_t bypass_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       int bypass_param = user_on_off(buffer, count);
+       if (bypass_param < 0)
+               return -1;
+       set_bypass_fn(PDE_DATA(file_inode(file)), bypass_param);
+       return count;
+ }
+ static int show_bypass(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_bypass_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 1)
+               seq_printf(m, "on\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       return 0;
+ }
+ RW_FOPS(bypass)
+ static ssize_t tap_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       int tap_param = user_on_off(buffer, count);
+       if (tap_param < 0)
+               return -1;
+       set_tap_fn(PDE_DATA(file_inode(file)), tap_param);
+       return count;
+ }
+ static int show_tap(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_tap_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 1)
+               seq_printf(m, "on\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       return 0;
+ }
+ RW_FOPS(tap)
+ static ssize_t disc_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       int tap_param = user_on_off(buffer, count);
+       if (tap_param < 0)
+               return -1;
+       set_disc_fn(PDE_DATA(file_inode(file)), tap_param);
+       return count;
+ }
+ static int show_disc(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_disc_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 1)
+               seq_printf(m, "on\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       return 0;
+ }
+ RW_FOPS(disc)
+ static int show_bypass_change(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_bypass_change_fn(dev);
+       if (ret == 1)
+               seq_printf(m, "on\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       else
+               seq_printf(m, "fail\n");
+       return 0;
+ }
+ RO_FOPS(bypass_change)
+ static int show_tap_change(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_tap_change_fn(dev);
+       if (ret == 1)
+               seq_printf(m, "on\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       else
+               seq_printf(m, "fail\n");
+       return 0;
+ }
+ RO_FOPS(tap_change)
+ static int show_disc_change(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_disc_change_fn(dev);
+       if (ret == 1)
+               seq_printf(m, "on\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       else
+               seq_printf(m, "fail\n");
+       return 0;
+ }
+ RO_FOPS(disc_change)
+ static ssize_t bypass_wd_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+       int timeout;
+       int ret = kstrtoint_from_user(buffer, count, 10, &timeout);
+       if (ret)
+               return ret;
+       set_bypass_wd_fn(dev, timeout);
+       return count;
+ }
+ static int show_bypass_wd(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = 0, timeout = 0;
+       ret = get_bypass_wd_fn(dev, &timeout);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m,  "fail\n");
+       else if (timeout == -1)
+               seq_printf(m,  "unknown\n");
+       else if (timeout == 0)
+               seq_printf(m,  "disable\n");
+       else
+               seq_printf(m, "%d\n", timeout);
+       return 0;
+ }
+ RW_FOPS(bypass_wd)
+ static int show_wd_expire_time(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = 0, timeout = 0;
+       ret = get_wd_expire_time_fn(dev, &timeout);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (timeout == -1)
+               seq_printf(m, "expire\n");
+       else if (timeout == 0)
+               seq_printf(m, "disable\n");
+       else
+               seq_printf(m, "%d\n", timeout);
+       return 0;
+ }
+ RO_FOPS(wd_expire_time)
+ static ssize_t tpl_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+       int tpl_param = user_on_off(buffer, count);
+       if (tpl_param < 0)
+               return -1;
+       set_tpl_fn(dev, tpl_param);
+       return count;
+ }
+ static int show_tpl(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_tpl_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 1)
+               seq_printf(m, "on\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       return 0;
+ }
+ RW_FOPS(tpl)
+ #ifdef PMC_FIX_FLAG
+ static ssize_t wait_at_pwup_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+       int tpl_param = user_on_off(buffer, count);
+       if (tpl_param < 0)
+               return -1;
+       set_bp_wait_at_pwup_fn(dev, tpl_param);
+       return count;
+ }
+ static int show_wait_at_pwup(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_bp_wait_at_pwup_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 1)
+               seq_printf(m, "on\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       return 0;
+ }
+ RW_FOPS(wait_at_pwup)
+ static ssize_t hw_reset_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+       int tpl_param = user_on_off(buffer, count);
+       if (tpl_param < 0)
+               return -1;
+       set_bp_hw_reset_fn(dev, tpl_param);
+       return count;
+ }
+ static int show_hw_reset(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_bp_hw_reset_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 1)
+               seq_printf(m, "on\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       return 0;
+ }
+ RW_FOPS(hw_reset)
+ #endif                                /*PMC_WAIT_FLAG */
+ static int show_reset_bypass_wd(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = reset_bypass_wd_timer_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 0)
+               seq_printf(m, "disable\n");
+       else if (ret == 1)
+               seq_printf(m, "success\n");
+       return 0;
+ }
+ RO_FOPS(reset_bypass_wd)
+ static ssize_t dis_bypass_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       int bypass_param = user_on_off(buffer, count);
+       if (bypass_param < 0)
+               return -EINVAL;
+       set_dis_bypass_fn(PDE_DATA(file_inode(file)), bypass_param);
+       return count;
+ }
+ static int show_dis_bypass(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_dis_bypass_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       else
+               seq_printf(m, "on\n");
+       return 0;
+ }
+ RW_FOPS(dis_bypass)
+ static ssize_t dis_tap_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       int tap_param = user_on_off(buffer, count);
+       if (tap_param < 0)
+               return -EINVAL;
+       set_dis_tap_fn(PDE_DATA(file_inode(file)), tap_param);
+       return count;
+ }
+ static int show_dis_tap(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_dis_tap_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       else
+               seq_printf(m, "on\n");
+       return 0;
+ }
+ RW_FOPS(dis_tap)
+ static ssize_t dis_disc_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       int tap_param = user_on_off(buffer, count);
+       if (tap_param < 0)
+               return -EINVAL;
+       set_dis_disc_fn(PDE_DATA(file_inode(file)), tap_param);
+       return count;
+ }
+ static int show_dis_disc(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_dis_disc_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       else
+               seq_printf(m, "on\n");
+       return 0;
+ }
+ RW_FOPS(dis_disc)
+ static ssize_t bypass_pwup_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       int bypass_param = user_on_off(buffer, count);
+       if (bypass_param < 0)
+               return -EINVAL;
+       set_bypass_pwup_fn(PDE_DATA(file_inode(file)), bypass_param);
+       return count;
+ }
+ static int show_bypass_pwup(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_bypass_pwup_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       else
+               seq_printf(m, "on\n");
+       return 0;
+ }
+ RW_FOPS(bypass_pwup)
+ static ssize_t bypass_pwoff_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       int bypass_param = user_on_off(buffer, count);
+       if (bypass_param < 0)
+               return -EINVAL;
+       set_bypass_pwoff_fn(PDE_DATA(file_inode(file)), bypass_param);
+       return count;
+ }
+ static int show_bypass_pwoff(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_bypass_pwoff_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       else
+               seq_printf(m, "on\n");
+       return 0;
+ }
+ RW_FOPS(bypass_pwoff)
+ static ssize_t tap_pwup_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       int tap_param = user_on_off(buffer, count);
+       if (tap_param < 0)
+               return -EINVAL;
+       set_tap_pwup_fn(PDE_DATA(file_inode(file)), tap_param);
+       return count;
+ }
+ static int show_tap_pwup(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_tap_pwup_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       else
+               seq_printf(m, "on\n");
+       return 0;
+ }
+ RW_FOPS(tap_pwup)
+ static ssize_t disc_pwup_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       int tap_param = user_on_off(buffer, count);
+       if (tap_param < 0)
+               return -EINVAL;
+       set_disc_pwup_fn(PDE_DATA(file_inode(file)), tap_param);
+       return count;
+ }
+ static int show_disc_pwup(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_disc_pwup_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       else
+               seq_printf(m, "on\n");
+       return 0;
+ }
+ RW_FOPS(disc_pwup)
+ static ssize_t std_nic_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       int bypass_param = user_on_off(buffer, count);
+       if (bypass_param < 0)
+               return -EINVAL;
+       set_std_nic_fn(PDE_DATA(file_inode(file)), bypass_param);
+       return count;
+ }
+ static int show_std_nic(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_std_nic_fn(dev);
+       if (ret == BP_NOT_CAP)
+               seq_printf(m, "fail\n");
+       else if (ret == 0)
+               seq_printf(m, "off\n");
+       else
+               seq_printf(m, "on\n");
+       return 0;
+ }
+ RW_FOPS(std_nic)
+ static ssize_t wd_exp_mode_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       char kbuf[256];
+       int bypass_param = 0, length = 0;
+       if (count > (sizeof(kbuf) - 1))
+               return -1;
+       if (copy_from_user(&kbuf, buffer, count))
+               return -1;
+       kbuf[count] = '\0';
+       length = strlen(kbuf);
+       if (kbuf[length - 1] == '\n')
+               kbuf[--length] = '\0';
+       if (strcmp(kbuf, "tap") == 0)
+               bypass_param = 1;
+       else if (strcmp(kbuf, "bypass") == 0)
+               bypass_param = 0;
+       else if (strcmp(kbuf, "disc") == 0)
+               bypass_param = 2;
+       set_wd_exp_mode_fn(PDE_DATA(file_inode(file)), bypass_param);
+       return count;
+ }
+ static int show_wd_exp_mode(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_wd_exp_mode_fn(dev);
+       if (ret == 1)
+               seq_printf(m, "tap\n");
+       else if (ret == 0)
+               seq_printf(m, "bypass\n");
+       else if (ret == 2)
+               seq_printf(m, "disc\n");
+       else
+               seq_printf(m, "fail\n");
+       return 0;
+ }
+ RW_FOPS(wd_exp_mode)
+ static ssize_t wd_autoreset_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
+ {
+       int timeout;
+       int ret = kstrtoint_from_user(buffer, count, 10, &timeout);
+       if (ret)
+               return ret;
+       set_wd_autoreset_fn(PDE_DATA(file_inode(file)), timeout);
+       return count;
+ }
+ static int show_wd_autoreset(struct seq_file *m, void *v)
+ {
+       bpctl_dev_t *dev = m->private;
+       int ret = get_wd_autoreset_fn(dev);
+       if (ret >= 0)
+               seq_printf(m, "%d\n", ret);
+       else
+               seq_printf(m, "fail\n");
+       return 0;
+ }
+ RW_FOPS(wd_autoreset)
+ int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block)
+ {
+       struct bypass_pfs_sd *current_pfs = &(pbp_device_block->bypass_pfs_set);
+       static struct proc_dir_entry *procfs_dir = NULL;
+       int ret = 0;
+       if (!pbp_device_block->ndev)
+               return -1;
+       sprintf(current_pfs->dir_name, "bypass_%s",
+               pbp_device_block->ndev->name);
+       if (!bp_procfs_dir)
+               return -1;
+       /* create device proc dir */
+       procfs_dir = proc_mkdir(current_pfs->dir_name, bp_procfs_dir);
+       if (!procfs_dir) {
+               printk(KERN_DEBUG "Could not create procfs directory %s\n",
+                      current_pfs->dir_name);
+               return -1;
+       }
+       current_pfs->bypass_entry = procfs_dir;
+ #define ENTRY(x) ret |= procfs_add(#x, &x##_ops, pbp_device_block)
+       ENTRY(bypass_info);
+       if (pbp_device_block->bp_caps & SW_CTL_CAP) {
+               /* Create set param proc's */
+               ENTRY(bypass_slave);
+               ENTRY(bypass_caps);
+               ENTRY(wd_set_caps);
+               ENTRY(bypass_wd);
+               ENTRY(wd_expire_time);
+               ENTRY(reset_bypass_wd);
+               ENTRY(std_nic);
+               if (pbp_device_block->bp_caps & BP_CAP) {
+                       ENTRY(bypass);
+                       ENTRY(dis_bypass);
+                       ENTRY(bypass_pwup);
+                       ENTRY(bypass_pwoff);
+                       ENTRY(bypass_change);
+               }
+               if (pbp_device_block->bp_caps & TAP_CAP) {
+                       ENTRY(tap);
+                       ENTRY(dis_tap);
+                       ENTRY(tap_pwup);
+                       ENTRY(tap_change);
+               }
+               if (pbp_device_block->bp_caps & DISC_CAP) {
+                       ENTRY(disc);
+                       ENTRY(dis_disc);
+                       ENTRY(disc_pwup);
+                       ENTRY(disc_change);
+               }
+               ENTRY(wd_exp_mode);
+               ENTRY(wd_autoreset);
+               ENTRY(tpl);
+ #ifdef PMC_FIX_FLAG
+               ENTRY(wait_at_pwup);
+               ENTRY(hw_reset);
+ #endif
+       }
+ #undef ENTRY
+       if (ret < 0)
+               printk(KERN_DEBUG "Create proc entry failed\n");
+       return ret;
+ }
+ int bypass_proc_remove_dev_sd(bpctl_dev_t *pbp_device_block)
+ {
+       struct bypass_pfs_sd *current_pfs = &pbp_device_block->bypass_pfs_set;
+       remove_proc_subtree(current_pfs->dir_name, bp_procfs_dir);
+       current_pfs->bypass_entry = NULL;
+       return 0;
+ }
index be4f6c2ca3ff8c3df8ebcf222312f754b5c5ffb1,a89ab9bf38e45946c0dfbb2fd5fe807d7abfa807..08b250f01dae6e7fd2f323cf9f7a06920266fe11
@@@ -60,6 -60,7 +60,7 @@@
   */
  #undef __NO_VERSION__
  
+ #include <linux/file.h>
  #include "device.h"
  #include "card.h"
  #include "channel.h"
@@@ -98,50 -99,52 +99,50 @@@ MODULE_AUTHOR("VIA Networking Technolog
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver");
  
 -      static int mlme_kill;
 -      //static  struct task_struct * mlme_task;
 +static int mlme_kill;
 +//static  struct task_struct * mlme_task;
  
 -#define DEVICE_PARAM(N,D)
 +#define DEVICE_PARAM(N, D)
  /*
 -        static const int N[MAX_UINTS]=OPTION_DEFAULT;\
 -        MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UINTS) "i");\
 -        MODULE_PARM_DESC(N, D);
 +  static const int N[MAX_UINTS]=OPTION_DEFAULT;\
 +  MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UINTS) "i");\
 +  MODULE_PARM_DESC(N, D);
  */
  
  #define RX_DESC_MIN0     16
  #define RX_DESC_MAX0     128
  #define RX_DESC_DEF0     32
 -DEVICE_PARAM(RxDescriptors0,"Number of receive descriptors0");
 +DEVICE_PARAM(RxDescriptors0, "Number of receive descriptors0");
  
  #define RX_DESC_MIN1     16
  #define RX_DESC_MAX1     128
  #define RX_DESC_DEF1     32
 -DEVICE_PARAM(RxDescriptors1,"Number of receive descriptors1");
 +DEVICE_PARAM(RxDescriptors1, "Number of receive descriptors1");
  
  #define TX_DESC_MIN0     16
  #define TX_DESC_MAX0     128
  #define TX_DESC_DEF0     32
 -DEVICE_PARAM(TxDescriptors0,"Number of transmit descriptors0");
 +DEVICE_PARAM(TxDescriptors0, "Number of transmit descriptors0");
  
  #define TX_DESC_MIN1     16
  #define TX_DESC_MAX1     128
  #define TX_DESC_DEF1     64
 -DEVICE_PARAM(TxDescriptors1,"Number of transmit descriptors1");
 -
 +DEVICE_PARAM(TxDescriptors1, "Number of transmit descriptors1");
  
  #define IP_ALIG_DEF     0
  /* IP_byte_align[] is used for IP header unsigned long byte aligned
     0: indicate the IP header won't be unsigned long byte aligned.(Default) .
     1: indicate the IP header will be unsigned long byte aligned.
 -      In some environment, the IP header should be unsigned long byte aligned,
 -      or the packet will be droped when we receive it. (eg: IPVS)
 +   In some environment, the IP header should be unsigned long byte aligned,
 +   or the packet will be droped when we receive it. (eg: IPVS)
  */
 -DEVICE_PARAM(IP_byte_align,"Enable IP header dword aligned");
 -
 +DEVICE_PARAM(IP_byte_align, "Enable IP header dword aligned");
  
  #define INT_WORKS_DEF   20
  #define INT_WORKS_MIN   10
  #define INT_WORKS_MAX   64
  
 -DEVICE_PARAM(int_works,"Number of packets per interrupt services");
 +DEVICE_PARAM(int_works, "Number of packets per interrupt services");
  
  #define CHANNEL_MIN     1
  #define CHANNEL_MAX     14
  
  DEVICE_PARAM(Channel, "Channel number");
  
 -
  /* PreambleType[] is the preamble length used for transmit.
     0: indicate allows long preamble type
     1: indicate allows short preamble type
  
  DEVICE_PARAM(PreambleType, "Preamble Type");
  
 -
  #define RTS_THRESH_MIN     512
  #define RTS_THRESH_MAX     2347
  #define RTS_THRESH_DEF     2347
  
  DEVICE_PARAM(RTSThreshold, "RTS threshold");
  
 -
  #define FRAG_THRESH_MIN     256
  #define FRAG_THRESH_MAX     2346
  #define FRAG_THRESH_DEF     2346
  
  DEVICE_PARAM(FragThreshold, "Fragmentation threshold");
  
 -
  #define DATA_RATE_MIN     0
  #define DATA_RATE_MAX     13
  #define DATA_RATE_DEF     13
     7: indicate 18 Mbps  0x24
     8: indicate 24 Mbps  0x30
     9: indicate 36 Mbps  0x48
 -  10: indicate 48 Mbps  0x60
 -  11: indicate 54 Mbps  0x6c
 -  12: indicate 72 Mbps  0x90
 -  13: indicate auto rate
 +   10: indicate 48 Mbps  0x60
 +   11: indicate 54 Mbps  0x6c
 +   12: indicate 72 Mbps  0x90
 +   13: indicate auto rate
  */
  
  DEVICE_PARAM(ConnectionRate, "Connection data rate");
@@@ -202,6 -209,7 +203,6 @@@ DEVICE_PARAM(OPMode, "Infrastruct, adho
     2: indicate AP mode used
  */
  
 -
  /* PSMode[]
     0: indicate disable power saving mode
     1: indicate enable power saving mode
  
  DEVICE_PARAM(PSMode, "Power saving mode");
  
 -
  #define SHORT_RETRY_MIN     0
  #define SHORT_RETRY_MAX     31
  #define SHORT_RETRY_DEF     8
  
 -
  DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits");
  
  #define LONG_RETRY_MIN     0
  #define LONG_RETRY_MAX     15
  #define LONG_RETRY_DEF     4
  
 -
  DEVICE_PARAM(LongRetryLimit, "long frame retry limits");
  
 -
  /* BasebandType[] baseband type selected
     0: indicate 802.11a type
     1: indicate 802.11b type
  
  DEVICE_PARAM(BasebandType, "baseband type");
  
 -
 -
  /* 80211hEnable[]
     0: indicate disable 802.11h
     1: indicate enable 802.11h
@@@ -252,18 -266,20 +253,18 @@@ DEVICE_PARAM(b80211hEnable, "802.11h mo
  
  DEVICE_PARAM(bDiversityANTEnable, "ANT diversity mode");
  
 -
  //
  // Static vars definitions
  //
  
 -
 -static int          device_nics             =0;
 -static PSDevice     pDevice_Infos           =NULL;
 +static int          device_nics             = 0;
 +static PSDevice     pDevice_Infos           = NULL;
  static struct net_device *root_device_dev = NULL;
  
 -static CHIP_INFO chip_info_table[]= {
 -    { VT3253,       "VIA Networking Solomon-A/B/G Wireless LAN Adapter ",
 -        256, 1,     DEVICE_FLAGS_IP_ALIGN|DEVICE_FLAGS_TX_ALIGN },
 -    {0,NULL}
 +static CHIP_INFO chip_info_table[] = {
 +      { VT3253,       "VIA Networking Solomon-A/B/G Wireless LAN Adapter ",
 +        256, 1,     DEVICE_FLAGS_IP_ALIGN|DEVICE_FLAGS_TX_ALIGN },
 +      {0, NULL}
  };
  
  DEFINE_PCI_DEVICE_TABLE(vt6655_pci_id_table) = {
  
  /*---------------------  Static Functions  --------------------------*/
  
 -
  static int  vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent);
 -static void vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice, PCHIP_INFO);
 +static void vt6655_init_info(struct pci_dev *pcid, PSDevice *ppDevice, PCHIP_INFO);
  static void device_free_info(PSDevice pDevice);
 -static bool device_get_pci_info(PSDevice, struct pci_devpcid);
 +static bool device_get_pci_info(PSDevice, struct pci_dev *pcid);
  static void device_print_info(PSDevice pDevice);
  static struct net_device_stats *device_get_stats(struct net_device *dev);
  static void device_init_diversity_timer(PSDevice pDevice);
  static int  device_open(struct net_device *dev);
  static int  device_xmit(struct sk_buff *skb, struct net_device *dev);
 -static  irqreturn_t  device_intr(int irq,  void*dev_instance);
 +static  irqreturn_t  device_intr(int irq,  void *dev_instance);
  static void device_set_multi(struct net_device *dev);
  static int  device_close(struct net_device *dev);
  static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@@ -298,6 -315,7 +299,6 @@@ struct notifier_block device_notifier 
  };
  #endif
  
 -
  static void device_init_rd0_ring(PSDevice pDevice);
  static void device_init_rd1_ring(PSDevice pDevice);
  static void device_init_defrag_cb(PSDevice pDevice);
@@@ -321,13 -339,16 +322,13 @@@ static void device_free_rd1_ring(PSDevi
  static void device_free_rings(PSDevice pDevice);
  static void device_free_frag_buf(PSDevice pDevice);
  static int Config_FileGetParameter(unsigned char *string,
 -              unsigned char *dest, unsigned char *source);
 -
 +                                 unsigned char *dest, unsigned char *source);
  
  /*---------------------  Export Variables  --------------------------*/
  
  /*---------------------  Export Functions  --------------------------*/
  
 -
 -
 -static char* get_chip_name(int chip_id)
 +static char *get_chip_name(int chip_id)
  {
        int i;
        for (i = 0; chip_info_table[i].name != NULL; i++)
@@@ -343,41 -364,42 +344,41 @@@ static void vt6655_remove(struct pci_de
        if (pDevice == NULL)
                return;
        device_free_info(pDevice);
 -
  }
  
  /*
 -static void
 -device_set_int_opt(int *opt, int val, int min, int max, int def,char* name,char* devname) {
 -    if (val==-1)
 -        *opt=def;
 -    else if (val<min || val>max) {
 -        DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n" ,
 -            devname,name, min,max);
 -        *opt=def;
 -    } else {
 -        DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: set value of parameter %s to %d\n",
 -            devname, name, val);
 -        *opt=val;
 -    }
 -}
 +  static void
 +  device_set_int_opt(int *opt, int val, int min, int max, int def,char* name,char* devname) {
 +  if (val==-1)
 +  *opt=def;
 +  else if (val<min || val>max) {
 +  DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n" ,
 +  devname,name, min,max);
 +  *opt=def;
 +  } else {
 +  DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: set value of parameter %s to %d\n",
 +  devname, name, val);
 +  *opt=val;
 +  }
 +  }
  
 -static void
 -device_set_bool_opt(unsigned int *opt, int val,bool def,u32 flag, char* name,char* devname) {
 -    (*opt)&=(~flag);
 -    if (val==-1)
 -        *opt|=(def ? flag : 0);
 -    else if (val<0 || val>1) {
 -        DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE
 -            "%s: the value of parameter %s is invalid, the valid range is (0-1)\n",devname,name);
 -        *opt|=(def ? flag : 0);
 -    } else {
 -        DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: set parameter %s to %s\n",
 -            devname,name , val ? "true" : "false");
 -        *opt|=(val ? flag : 0);
 -    }
 -}
 +  static void
 +  device_set_bool_opt(unsigned int *opt, int val,bool def,u32 flag, char* name,char* devname) {
 +  (*opt)&=(~flag);
 +  if (val==-1)
 +  *opt|=(def ? flag : 0);
 +  else if (val<0 || val>1) {
 +  DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE
 +  "%s: the value of parameter %s is invalid, the valid range is (0-1)\n",devname,name);
 +  *opt|=(def ? flag : 0);
 +  } else {
 +  DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: set parameter %s to %s\n",
 +  devname,name , val ? "true" : "false");
 +  *opt|=(val ? flag : 0);
 +  }
 +  }
  */
 -static void device_get_options(PSDevice pDevice, int index, chardevname)
 +static void device_get_options(PSDevice pDevice, int index, char *devname)
  {
        POPTIONS pOpts = &(pDevice->sOpts);
  
  
  static void
  device_set_options(PSDevice pDevice) {
 -
 -    unsigned char abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 -    unsigned char abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
 -    unsigned char abySNAP_Bridgetunnel[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8};
 -
 -
 -    memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN);
 -    memcpy(pDevice->abySNAP_RFC1042, abySNAP_RFC1042, ETH_ALEN);
 -    memcpy(pDevice->abySNAP_Bridgetunnel, abySNAP_Bridgetunnel, ETH_ALEN);
 -
 -    pDevice->uChannel = pDevice->sOpts.channel_num;
 -    pDevice->wRTSThreshold = pDevice->sOpts.rts_thresh;
 -    pDevice->wFragmentationThreshold = pDevice->sOpts.frag_thresh;
 -    pDevice->byShortRetryLimit = pDevice->sOpts.short_retry;
 -    pDevice->byLongRetryLimit = pDevice->sOpts.long_retry;
 -    pDevice->wMaxTransmitMSDULifetime = DEFAULT_MSDU_LIFETIME;
 -    pDevice->byShortPreamble = (pDevice->sOpts.flags & DEVICE_FLAGS_PREAMBLE_TYPE) ? 1 : 0;
 -    pDevice->byOpMode = (pDevice->sOpts.flags & DEVICE_FLAGS_OP_MODE) ? 1 : 0;
 -    pDevice->ePSMode = (pDevice->sOpts.flags & DEVICE_FLAGS_PS_MODE) ? 1 : 0;
 -    pDevice->b11hEnable = (pDevice->sOpts.flags & DEVICE_FLAGS_80211h_MODE) ? 1 : 0;
 -    pDevice->bDiversityRegCtlON = (pDevice->sOpts.flags & DEVICE_FLAGS_DiversityANT) ? 1 : 0;
 -    pDevice->uConnectionRate = pDevice->sOpts.data_rate;
 -    if (pDevice->uConnectionRate < RATE_AUTO) pDevice->bFixRate = true;
 -    pDevice->byBBType = pDevice->sOpts.bbp_type;
 -    pDevice->byPacketType = pDevice->byBBType;
 +      unsigned char abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 +      unsigned char abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
 +      unsigned char abySNAP_Bridgetunnel[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8};
 +
 +      memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN);
 +      memcpy(pDevice->abySNAP_RFC1042, abySNAP_RFC1042, ETH_ALEN);
 +      memcpy(pDevice->abySNAP_Bridgetunnel, abySNAP_Bridgetunnel, ETH_ALEN);
 +
 +      pDevice->uChannel = pDevice->sOpts.channel_num;
 +      pDevice->wRTSThreshold = pDevice->sOpts.rts_thresh;
 +      pDevice->wFragmentationThreshold = pDevice->sOpts.frag_thresh;
 +      pDevice->byShortRetryLimit = pDevice->sOpts.short_retry;
 +      pDevice->byLongRetryLimit = pDevice->sOpts.long_retry;
 +      pDevice->wMaxTransmitMSDULifetime = DEFAULT_MSDU_LIFETIME;
 +      pDevice->byShortPreamble = (pDevice->sOpts.flags & DEVICE_FLAGS_PREAMBLE_TYPE) ? 1 : 0;
 +      pDevice->byOpMode = (pDevice->sOpts.flags & DEVICE_FLAGS_OP_MODE) ? 1 : 0;
 +      pDevice->ePSMode = (pDevice->sOpts.flags & DEVICE_FLAGS_PS_MODE) ? 1 : 0;
 +      pDevice->b11hEnable = (pDevice->sOpts.flags & DEVICE_FLAGS_80211h_MODE) ? 1 : 0;
 +      pDevice->bDiversityRegCtlON = (pDevice->sOpts.flags & DEVICE_FLAGS_DiversityANT) ? 1 : 0;
 +      pDevice->uConnectionRate = pDevice->sOpts.data_rate;
 +      if (pDevice->uConnectionRate < RATE_AUTO) pDevice->bFixRate = true;
 +      pDevice->byBBType = pDevice->sOpts.bbp_type;
 +      pDevice->byPacketType = pDevice->byBBType;
  
  //PLICE_DEBUG->
        pDevice->byAutoFBCtrl = AUTO_FB_0;
        //pDevice->byAutoFBCtrl = AUTO_FB_1;
  //PLICE_DEBUG<-
 -pDevice->bUpdateBBVGA = true;
 -    pDevice->byFOETuning = 0;
 -    pDevice->wCTSDuration = 0;
 -    pDevice->byPreambleType = 0;
 -
 -
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" uChannel= %d\n",(int)pDevice->uChannel);
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byOpMode= %d\n",(int)pDevice->byOpMode);
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" ePSMode= %d\n",(int)pDevice->ePSMode);
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" wRTSThreshold= %d\n",(int)pDevice->wRTSThreshold);
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byShortRetryLimit= %d\n",(int)pDevice->byShortRetryLimit);
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byLongRetryLimit= %d\n",(int)pDevice->byLongRetryLimit);
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byPreambleType= %d\n",(int)pDevice->byPreambleType);
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byShortPreamble= %d\n",(int)pDevice->byShortPreamble);
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" uConnectionRate= %d\n",(int)pDevice->uConnectionRate);
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byBBType= %d\n",(int)pDevice->byBBType);
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->b11hEnable= %d\n",(int)pDevice->b11hEnable);
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->bDiversityRegCtlON= %d\n",(int)pDevice->bDiversityRegCtlON);
 +      pDevice->bUpdateBBVGA = true;
 +      pDevice->byFOETuning = 0;
 +      pDevice->wCTSDuration = 0;
 +      pDevice->byPreambleType = 0;
 +
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " uChannel= %d\n", (int)pDevice->uChannel);
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byOpMode= %d\n", (int)pDevice->byOpMode);
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " ePSMode= %d\n", (int)pDevice->ePSMode);
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " wRTSThreshold= %d\n", (int)pDevice->wRTSThreshold);
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byShortRetryLimit= %d\n", (int)pDevice->byShortRetryLimit);
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byLongRetryLimit= %d\n", (int)pDevice->byLongRetryLimit);
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byPreambleType= %d\n", (int)pDevice->byPreambleType);
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byShortPreamble= %d\n", (int)pDevice->byShortPreamble);
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " uConnectionRate= %d\n", (int)pDevice->uConnectionRate);
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byBBType= %d\n", (int)pDevice->byBBType);
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " pDevice->b11hEnable= %d\n", (int)pDevice->b11hEnable);
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " pDevice->bDiversityRegCtlON= %d\n", (int)pDevice->bDiversityRegCtlON);
  }
  
 -static void s_vCompleteCurrentMeasure (PSDevice pDevice, unsigned char byResult)
 +static void s_vCompleteCurrentMeasure(PSDevice pDevice, unsigned char byResult)
  {
 -    unsigned int ii;
 -    unsigned long dwDuration = 0;
 -    unsigned char byRPI0 = 0;
 -
 -    for(ii=1;ii<8;ii++) {
 -        pDevice->dwRPIs[ii] *= 255;
 -        dwDuration |= *((unsigned short *) (pDevice->pCurrMeasureEID->sReq.abyDuration));
 -        dwDuration <<= 10;
 -        pDevice->dwRPIs[ii] /= dwDuration;
 -        pDevice->abyRPIs[ii] = (unsigned char) pDevice->dwRPIs[ii];
 -        byRPI0 += pDevice->abyRPIs[ii];
 -    }
 -    pDevice->abyRPIs[0] = (0xFF - byRPI0);
 -
 -     if (pDevice->uNumOfMeasureEIDs == 0) {
 -        VNTWIFIbMeasureReport(  pDevice->pMgmt,
 -                                true,
 -                                pDevice->pCurrMeasureEID,
 -                                byResult,
 -                                pDevice->byBasicMap,
 -                                pDevice->byCCAFraction,
 -                                pDevice->abyRPIs
 -                                );
 -    } else {
 -        VNTWIFIbMeasureReport(  pDevice->pMgmt,
 -                                false,
 -                                pDevice->pCurrMeasureEID,
 -                                byResult,
 -                                pDevice->byBasicMap,
 -                                pDevice->byCCAFraction,
 -                                pDevice->abyRPIs
 -                                );
 -        CARDbStartMeasure (pDevice, pDevice->pCurrMeasureEID++, pDevice->uNumOfMeasureEIDs);
 -    }
 -
 +      unsigned int ii;
 +      unsigned long dwDuration = 0;
 +      unsigned char byRPI0 = 0;
 +
 +      for (ii = 1; ii < 8; ii++) {
 +              pDevice->dwRPIs[ii] *= 255;
 +              dwDuration |= *((unsigned short *)(pDevice->pCurrMeasureEID->sReq.abyDuration));
 +              dwDuration <<= 10;
 +              pDevice->dwRPIs[ii] /= dwDuration;
 +              pDevice->abyRPIs[ii] = (unsigned char)pDevice->dwRPIs[ii];
 +              byRPI0 += pDevice->abyRPIs[ii];
 +      }
 +      pDevice->abyRPIs[0] = (0xFF - byRPI0);
 +
 +      if (pDevice->uNumOfMeasureEIDs == 0) {
 +              VNTWIFIbMeasureReport(pDevice->pMgmt,
 +                                    true,
 +                                    pDevice->pCurrMeasureEID,
 +                                    byResult,
 +                                    pDevice->byBasicMap,
 +                                    pDevice->byCCAFraction,
 +                                    pDevice->abyRPIs
 +                      );
 +      } else {
 +              VNTWIFIbMeasureReport(pDevice->pMgmt,
 +                                    false,
 +                                    pDevice->pCurrMeasureEID,
 +                                    byResult,
 +                                    pDevice->byBasicMap,
 +                                    pDevice->byCCAFraction,
 +                                    pDevice->abyRPIs
 +                      );
 +              CARDbStartMeasure(pDevice, pDevice->pCurrMeasureEID++, pDevice->uNumOfMeasureEIDs);
 +      }
  }
  
 -
 -
  //
  // Initialisation of MAC & BBP registers
  //
  
  static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType)
  {
 -    unsigned int ii;
 -    unsigned char byValue;
 -    unsigned char byValue1;
 -    unsigned char byCCKPwrdBm = 0;
 -    unsigned char byOFDMPwrdBm = 0;
 -    int zonetype=0;
 -     PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
 -    MACbShutdown(pDevice->PortOffset);
 -    BBvSoftwareReset(pDevice->PortOffset);
 -
 -    if ((InitType == DEVICE_INIT_COLD) ||
 -        (InitType == DEVICE_INIT_DXPL)) {
 -        // Do MACbSoftwareReset in MACvInitialize
 -        MACbSoftwareReset(pDevice->PortOffset);
 -        // force CCK
 -        pDevice->bCCK = true;
 -        pDevice->bAES = false;
 -        pDevice->bProtectMode = false;      //Only used in 11g type, sync with ERP IE
 -        pDevice->bNonERPPresent = false;
 -        pDevice->bBarkerPreambleMd = false;
 -        pDevice->wCurrentRate = RATE_1M;
 -        pDevice->byTopOFDMBasicRate = RATE_24M;
 -        pDevice->byTopCCKBasicRate = RATE_1M;
 -
 -        pDevice->byRevId = 0;                   //Target to IF pin while programming to RF chip.
 -
 -        // init MAC
 -        MACvInitialize(pDevice->PortOffset);
 -
 -        // Get Local ID
 -        VNSvInPortB(pDevice->PortOffset + MAC_REG_LOCALID, &(pDevice->byLocalID));
 -
 -           spin_lock_irq(&pDevice->lock);
 -       SROMvReadAllContents(pDevice->PortOffset,pDevice->abyEEPROM);
 -
 -           spin_unlock_irq(&pDevice->lock);
 -
 -        // Get Channel range
 -
 -        pDevice->byMinChannel = 1;
 -        pDevice->byMaxChannel = CB_MAX_CHANNEL;
 -
 -        // Get Antena
 -        byValue = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA);
 -        if (byValue & EEP_ANTINV)
 -            pDevice->bTxRxAntInv = true;
 -        else
 -            pDevice->bTxRxAntInv = false;
 -#ifdef        PLICE_DEBUG
 -      //printk("init_register:TxRxAntInv is %d,byValue is %d\n",pDevice->bTxRxAntInv,byValue);
 -#endif
 -
 -        byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
 -        if (byValue == 0) // if not set default is All
 -            byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
 -#ifdef        PLICE_DEBUG
 -      //printk("init_register:byValue is %d\n",byValue);
 -#endif
 -        pDevice->ulDiversityNValue = 100*260;//100*SROMbyReadEmbedded(pDevice->PortOffset, 0x51);
 -        pDevice->ulDiversityMValue = 100*16;//SROMbyReadEmbedded(pDevice->PortOffset, 0x52);
 -        pDevice->byTMax = 1;//SROMbyReadEmbedded(pDevice->PortOffset, 0x53);
 -        pDevice->byTMax2 = 4;//SROMbyReadEmbedded(pDevice->PortOffset, 0x54);
 -        pDevice->ulSQ3TH = 0;//(unsigned long) SROMbyReadEmbedded(pDevice->PortOffset, 0x55);
 -        pDevice->byTMax3 = 64;//SROMbyReadEmbedded(pDevice->PortOffset, 0x56);
 -
 -        if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) {
 -            pDevice->byAntennaCount = 2;
 -            pDevice->byTxAntennaMode = ANT_B;
 -            pDevice->dwTxAntennaSel = 1;
 -            pDevice->dwRxAntennaSel = 1;
 -            if (pDevice->bTxRxAntInv == true)
 -                pDevice->byRxAntennaMode = ANT_A;
 -            else
 -                pDevice->byRxAntennaMode = ANT_B;
 -                // chester for antenna
 -byValue1 = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA);
 -          //  if (pDevice->bDiversityRegCtlON)
 -          if((byValue1&0x08)==0)
 -                pDevice->bDiversityEnable = false;//SROMbyReadEmbedded(pDevice->PortOffset, 0x50);
 -            else
 -                pDevice->bDiversityEnable = true;
 -#ifdef        PLICE_DEBUG
 -              //printk("aux |main antenna: RxAntennaMode is %d\n",pDevice->byRxAntennaMode);
 -#endif
 -      } else  {
 -            pDevice->bDiversityEnable = false;
 -            pDevice->byAntennaCount = 1;
 -            pDevice->dwTxAntennaSel = 0;
 -            pDevice->dwRxAntennaSel = 0;
 -            if (byValue & EEP_ANTENNA_AUX) {
 -                pDevice->byTxAntennaMode = ANT_A;
 -                if (pDevice->bTxRxAntInv == true)
 -                    pDevice->byRxAntennaMode = ANT_B;
 -                else
 -                    pDevice->byRxAntennaMode = ANT_A;
 -            } else {
 -                pDevice->byTxAntennaMode = ANT_B;
 -                if (pDevice->bTxRxAntInv == true)
 -                    pDevice->byRxAntennaMode = ANT_A;
 -                else
 -                    pDevice->byRxAntennaMode = ANT_B;
 -            }
 -        }
 -#ifdef        PLICE_DEBUG
 -      //printk("init registers: TxAntennaMode is %d\n",pDevice->byTxAntennaMode);
 -#endif
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bDiversityEnable=[%d],NValue=[%d],MValue=[%d],TMax=[%d],TMax2=[%d]\n",
 -            pDevice->bDiversityEnable,(int)pDevice->ulDiversityNValue,(int)pDevice->ulDiversityMValue,pDevice->byTMax,pDevice->byTMax2);
 -
 -//#ifdef ZoneType_DefaultSetting
 -//2008-8-4 <add> by chester
 -//zonetype initial
 - pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE];
 - zonetype = Config_FileOperation(pDevice,false,NULL);
 - if (zonetype >= 0) {         //read zonetype file ok!
 -  if ((zonetype == 0)&&
 -        (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] !=0x00)){          //for USA
 -    pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0;
 -    pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0B;
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Init Zone Type :USA\n");
 -  }
 - else if((zonetype == 1)&&
 -           (pDevice->abyEEPROM[EEP_OFS_ZONETYPE]!=0x01)){   //for Japan
 -    pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x01;
 -    pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D;
 -  }
 - else if((zonetype == 2)&&
 -           (pDevice->abyEEPROM[EEP_OFS_ZONETYPE]!=0x02)){   //for Europe
 -    pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x02;
 -    pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D;
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Init Zone Type :Europe\n");
 -  }
 +      unsigned int ii;
 +      unsigned char byValue;
 +      unsigned char byValue1;
 +      unsigned char byCCKPwrdBm = 0;
 +      unsigned char byOFDMPwrdBm = 0;
 +      int zonetype = 0;
 +      PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
 +      MACbShutdown(pDevice->PortOffset);
 +      BBvSoftwareReset(pDevice->PortOffset);
 +
 +      if ((InitType == DEVICE_INIT_COLD) ||
 +          (InitType == DEVICE_INIT_DXPL)) {
 +              // Do MACbSoftwareReset in MACvInitialize
 +              MACbSoftwareReset(pDevice->PortOffset);
 +              // force CCK
 +              pDevice->bCCK = true;
 +              pDevice->bAES = false;
 +              pDevice->bProtectMode = false;      //Only used in 11g type, sync with ERP IE
 +              pDevice->bNonERPPresent = false;
 +              pDevice->bBarkerPreambleMd = false;
 +              pDevice->wCurrentRate = RATE_1M;
 +              pDevice->byTopOFDMBasicRate = RATE_24M;
 +              pDevice->byTopCCKBasicRate = RATE_1M;
 +
 +              pDevice->byRevId = 0;                   //Target to IF pin while programming to RF chip.
 +
 +              // init MAC
 +              MACvInitialize(pDevice->PortOffset);
 +
 +              // Get Local ID
 +              VNSvInPortB(pDevice->PortOffset + MAC_REG_LOCALID, &(pDevice->byLocalID));
  
 -else
 -{
 -   if(zonetype!=pDevice->abyEEPROM[EEP_OFS_ZONETYPE])
 -      printk("zonetype in file[%02x] mismatch with in EEPROM[%02x]\n",zonetype,pDevice->abyEEPROM[EEP_OFS_ZONETYPE]);
 -   else
 -      printk("Read Zonetype file success,use default zonetype setting[%02x]\n",zonetype);
 - }
 -      }
 -  else
 -    printk("Read Zonetype file fail,use default zonetype setting[%02x]\n",SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ZONETYPE));
 -
 -        // Get RFType
 -        pDevice->byRFType = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RFTYPE);
 -
 -        if ((pDevice->byRFType & RF_EMU) != 0) {
 -            // force change RevID for VT3253 emu
 -            pDevice->byRevId = 0x80;
 -        }
 -
 -        pDevice->byRFType &= RF_MASK;
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRFType = %x\n", pDevice->byRFType);
 -
 -        if (pDevice->bZoneRegExist == false) {
 -            pDevice->byZoneType = pDevice->abyEEPROM[EEP_OFS_ZONETYPE];
 -        }
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byZoneType = %x\n", pDevice->byZoneType);
 -
 -        //Init RF module
 -        RFbInit(pDevice);
 -
 -        //Get Desire Power Value
 -        pDevice->byCurPwr = 0xFF;
 -        pDevice->byCCKPwr = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_CCK);
 -        pDevice->byOFDMPwrG = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_OFDMG);
 -        //byCCKPwrdBm = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_CCK_PWR_dBm);
 -
 -      //byOFDMPwrdBm = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_OFDM_PWR_dBm);
 -//printk("CCKPwrdBm is 0x%x,byOFDMPwrdBm is 0x%x\n",byCCKPwrdBm,byOFDMPwrdBm);
 -              // Load power Table
 +              spin_lock_irq(&pDevice->lock);
 +              SROMvReadAllContents(pDevice->PortOffset, pDevice->abyEEPROM);
  
 +              spin_unlock_irq(&pDevice->lock);
  
 -        for (ii=0;ii<CB_MAX_CHANNEL_24G;ii++) {
 -            pDevice->abyCCKPwrTbl[ii+1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_CCK_PWR_TBL));
 -            if (pDevice->abyCCKPwrTbl[ii+1] == 0) {
 -                pDevice->abyCCKPwrTbl[ii+1] = pDevice->byCCKPwr;
 -            }
 -            pDevice->abyOFDMPwrTbl[ii+1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDM_PWR_TBL));
 -            if (pDevice->abyOFDMPwrTbl[ii+1] == 0) {
 -                pDevice->abyOFDMPwrTbl[ii+1] = pDevice->byOFDMPwrG;
 -            }
 -            pDevice->abyCCKDefaultPwr[ii+1] = byCCKPwrdBm;
 -            pDevice->abyOFDMDefaultPwr[ii+1] = byOFDMPwrdBm;
 -        }
 -              //2008-8-4 <add> by chester
 -        //recover 12,13 ,14channel for EUROPE by 11 channel
 -          if(((pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Japan) ||
 -              (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Europe))&&
 -           (pDevice->byOriginalZonetype == ZoneType_USA)) {
 -          for(ii=11;ii<14;ii++) {
 -                pDevice->abyCCKPwrTbl[ii] = pDevice->abyCCKPwrTbl[10];
 -             pDevice->abyOFDMPwrTbl[ii] = pDevice->abyOFDMPwrTbl[10];
 +              // Get Channel range
  
 -          }
 -        }
 +              pDevice->byMinChannel = 1;
 +              pDevice->byMaxChannel = CB_MAX_CHANNEL;
  
 +              // Get Antena
 +              byValue = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA);
 +              if (byValue & EEP_ANTINV)
 +                      pDevice->bTxRxAntInv = true;
 +              else
 +                      pDevice->bTxRxAntInv = false;
 +
 +              byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
 +              if (byValue == 0) // if not set default is All
 +                      byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
 +
 +              pDevice->ulDiversityNValue = 100*260;//100*SROMbyReadEmbedded(pDevice->PortOffset, 0x51);
 +              pDevice->ulDiversityMValue = 100*16;//SROMbyReadEmbedded(pDevice->PortOffset, 0x52);
 +              pDevice->byTMax = 1;//SROMbyReadEmbedded(pDevice->PortOffset, 0x53);
 +              pDevice->byTMax2 = 4;//SROMbyReadEmbedded(pDevice->PortOffset, 0x54);
 +              pDevice->ulSQ3TH = 0;//(unsigned long) SROMbyReadEmbedded(pDevice->PortOffset, 0x55);
 +              pDevice->byTMax3 = 64;//SROMbyReadEmbedded(pDevice->PortOffset, 0x56);
 +
 +              if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) {
 +                      pDevice->byAntennaCount = 2;
 +                      pDevice->byTxAntennaMode = ANT_B;
 +                      pDevice->dwTxAntennaSel = 1;
 +                      pDevice->dwRxAntennaSel = 1;
 +                      if (pDevice->bTxRxAntInv == true)
 +                              pDevice->byRxAntennaMode = ANT_A;
 +                      else
 +                              pDevice->byRxAntennaMode = ANT_B;
 +                      // chester for antenna
 +                      byValue1 = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA);
 +                      if ((byValue1 & 0x08) == 0)
 +                              pDevice->bDiversityEnable = false;//SROMbyReadEmbedded(pDevice->PortOffset, 0x50);
 +                      else
 +                              pDevice->bDiversityEnable = true;
 +              } else  {
 +                      pDevice->bDiversityEnable = false;
 +                      pDevice->byAntennaCount = 1;
 +                      pDevice->dwTxAntennaSel = 0;
 +                      pDevice->dwRxAntennaSel = 0;
 +                      if (byValue & EEP_ANTENNA_AUX) {
 +                              pDevice->byTxAntennaMode = ANT_A;
 +                              if (pDevice->bTxRxAntInv == true)
 +                                      pDevice->byRxAntennaMode = ANT_B;
 +                              else
 +                                      pDevice->byRxAntennaMode = ANT_A;
 +                      } else {
 +                              pDevice->byTxAntennaMode = ANT_B;
 +                              if (pDevice->bTxRxAntInv == true)
 +                                      pDevice->byRxAntennaMode = ANT_A;
 +                              else
 +                                      pDevice->byRxAntennaMode = ANT_B;
 +                      }
 +              }
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bDiversityEnable=[%d],NValue=[%d],MValue=[%d],TMax=[%d],TMax2=[%d]\n",
 +                      pDevice->bDiversityEnable, (int)pDevice->ulDiversityNValue, (int)pDevice->ulDiversityMValue, pDevice->byTMax, pDevice->byTMax2);
  
 -        // Load OFDM A Power Table
 -        for (ii=0;ii<CB_MAX_CHANNEL_5G;ii++) { //RobertYu:20041224, bug using CB_MAX_CHANNEL
 -            pDevice->abyOFDMPwrTbl[ii+CB_MAX_CHANNEL_24G+1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDMA_PWR_TBL));
 -            pDevice->abyOFDMDefaultPwr[ii+CB_MAX_CHANNEL_24G+1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDMA_PWR_dBm));
 -        }
 -        init_channel_table((void *)pDevice);
 +//#ifdef ZoneType_DefaultSetting
 +//2008-8-4 <add> by chester
 +//zonetype initial
 +              pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE];
 +              zonetype = Config_FileOperation(pDevice, false, NULL);
 +              if (zonetype >= 0) {         //read zonetype file ok!
 +                      if ((zonetype == 0) &&
 +                          (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] != 0x00)) {          //for USA
 +                              pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0;
 +                              pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0B;
 +                              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Init Zone Type :USA\n");
 +                      } else if ((zonetype == 1) &&
 +                               (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] != 0x01)) {   //for Japan
 +                              pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x01;
 +                              pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D;
 +                      } else if ((zonetype == 2) &&
 +                               (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] != 0x02)) {   //for Europe
 +                              pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x02;
 +                              pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D;
 +                              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Init Zone Type :Europe\n");
 +                      }
  
 +                      else {
 +                              if (zonetype != pDevice->abyEEPROM[EEP_OFS_ZONETYPE])
 +                                      printk("zonetype in file[%02x] mismatch with in EEPROM[%02x]\n", zonetype, pDevice->abyEEPROM[EEP_OFS_ZONETYPE]);
 +                              else
 +                                      printk("Read Zonetype file success,use default zonetype setting[%02x]\n", zonetype);
 +                      }
 +              } else
 +                      printk("Read Zonetype file fail,use default zonetype setting[%02x]\n", SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ZONETYPE));
  
 -        if (pDevice->byLocalID > REV_ID_VT3253_B1) {
 -            MACvSelectPage1(pDevice->PortOffset);
 -            VNSvOutPortB(pDevice->PortOffset + MAC_REG_MSRCTL + 1, (MSRCTL1_TXPWR | MSRCTL1_CSAPAREN));
 -            MACvSelectPage0(pDevice->PortOffset);
 -        }
 +              // Get RFType
 +              pDevice->byRFType = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RFTYPE);
  
 +              if ((pDevice->byRFType & RF_EMU) != 0) {
 +                      // force change RevID for VT3253 emu
 +                      pDevice->byRevId = 0x80;
 +              }
  
 -         // use relative tx timeout and 802.11i D4
 -        MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_CFG, (CFG_TKIPOPT | CFG_NOTXTIMEOUT));
 +              pDevice->byRFType &= RF_MASK;
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRFType = %x\n", pDevice->byRFType);
  
 -        // set performance parameter by registry
 -        MACvSetShortRetryLimit(pDevice->PortOffset, pDevice->byShortRetryLimit);
 -        MACvSetLongRetryLimit(pDevice->PortOffset, pDevice->byLongRetryLimit);
 +              if (pDevice->bZoneRegExist == false) {
 +                      pDevice->byZoneType = pDevice->abyEEPROM[EEP_OFS_ZONETYPE];
 +              }
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byZoneType = %x\n", pDevice->byZoneType);
  
 -        // reset TSF counter
 -        VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
 -        // enable TSF counter
 -        VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
 +              //Init RF module
 +              RFbInit(pDevice);
  
 -        // initialize BBP registers
 -        BBbVT3253Init(pDevice);
 +              //Get Desire Power Value
 +              pDevice->byCurPwr = 0xFF;
 +              pDevice->byCCKPwr = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_CCK);
 +              pDevice->byOFDMPwrG = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_OFDMG);
 +              //byCCKPwrdBm = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_CCK_PWR_dBm);
  
 -        if (pDevice->bUpdateBBVGA) {
 -            pDevice->byBBVGACurrent = pDevice->abyBBVGA[0];
 -            pDevice->byBBVGANew = pDevice->byBBVGACurrent;
 -            BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]);
 -        }
 -#ifdef        PLICE_DEBUG
 -      //printk("init registers:RxAntennaMode is %x,TxAntennaMode is %x\n",pDevice->byRxAntennaMode,pDevice->byTxAntennaMode);
 -#endif
 -        BBvSetRxAntennaMode(pDevice->PortOffset, pDevice->byRxAntennaMode);
 -        BBvSetTxAntennaMode(pDevice->PortOffset, pDevice->byTxAntennaMode);
 +              //byOFDMPwrdBm = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_OFDM_PWR_dBm);
  
 -        pDevice->byCurrentCh = 0;
 +              // Load power Table
  
 -        //pDevice->NetworkType = Ndis802_11Automode;
 -        // Set BB and packet type at the same time.
 -        // Set Short Slot Time, xIFS, and RSPINF.
 -        if (pDevice->uConnectionRate == RATE_AUTO) {
 -            pDevice->wCurrentRate = RATE_54M;
 -        } else {
 -            pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
 -        }
 +              for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) {
 +                      pDevice->abyCCKPwrTbl[ii + 1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_CCK_PWR_TBL));
 +                      if (pDevice->abyCCKPwrTbl[ii + 1] == 0) {
 +                              pDevice->abyCCKPwrTbl[ii+1] = pDevice->byCCKPwr;
 +                      }
 +                      pDevice->abyOFDMPwrTbl[ii + 1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDM_PWR_TBL));
 +                      if (pDevice->abyOFDMPwrTbl[ii + 1] == 0) {
 +                              pDevice->abyOFDMPwrTbl[ii + 1] = pDevice->byOFDMPwrG;
 +                      }
 +                      pDevice->abyCCKDefaultPwr[ii + 1] = byCCKPwrdBm;
 +                      pDevice->abyOFDMDefaultPwr[ii + 1] = byOFDMPwrdBm;
 +              }
 +              //2008-8-4 <add> by chester
 +              //recover 12,13 ,14channel for EUROPE by 11 channel
 +              if (((pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Japan) ||
 +                   (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Europe)) &&
 +                  (pDevice->byOriginalZonetype == ZoneType_USA)) {
 +                      for (ii = 11; ii < 14; ii++) {
 +                              pDevice->abyCCKPwrTbl[ii] = pDevice->abyCCKPwrTbl[10];
 +                              pDevice->abyOFDMPwrTbl[ii] = pDevice->abyOFDMPwrTbl[10];
  
 -        // default G Mode
 -        VNTWIFIbConfigPhyMode(pDevice->pMgmt, PHY_TYPE_11G);
 -        VNTWIFIbConfigPhyMode(pDevice->pMgmt, PHY_TYPE_AUTO);
 +                      }
 +              }
  
 -        pDevice->bRadioOff = false;
 +              // Load OFDM A Power Table
 +              for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) { //RobertYu:20041224, bug using CB_MAX_CHANNEL
 +                      pDevice->abyOFDMPwrTbl[ii + CB_MAX_CHANNEL_24G + 1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDMA_PWR_TBL));
 +                      pDevice->abyOFDMDefaultPwr[ii + CB_MAX_CHANNEL_24G + 1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDMA_PWR_dBm));
 +              }
 +              init_channel_table((void *)pDevice);
  
 -        pDevice->byRadioCtl = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RADIOCTL);
 -        pDevice->bHWRadioOff = false;
 +              if (pDevice->byLocalID > REV_ID_VT3253_B1) {
 +                      MACvSelectPage1(pDevice->PortOffset);
 +                      VNSvOutPortB(pDevice->PortOffset + MAC_REG_MSRCTL + 1, (MSRCTL1_TXPWR | MSRCTL1_CSAPAREN));
 +                      MACvSelectPage0(pDevice->PortOffset);
 +              }
  
 -        if (pDevice->byRadioCtl & EEP_RADIOCTL_ENABLE) {
 -            // Get GPIO
 -            MACvGPIOIn(pDevice->PortOffset, &pDevice->byGPIO);
 -//2008-4-14 <add> by chester for led issue
 - #ifdef FOR_LED_ON_NOTEBOOK
 -if (pDevice->byGPIO & GPIO0_DATA){pDevice->bHWRadioOff = true;}
 -if ( !(pDevice->byGPIO & GPIO0_DATA)){pDevice->bHWRadioOff = false;}
 -
 -            }
 -        if ( (pDevice->bRadioControlOff == true)) {
 -            CARDbRadioPowerOff(pDevice);
 -        }
 -else  CARDbRadioPowerOn(pDevice);
 -#else
 -            if (((pDevice->byGPIO & GPIO0_DATA) && !(pDevice->byRadioCtl & EEP_RADIOCTL_INV)) ||
 -                ( !(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV))) {
 -                pDevice->bHWRadioOff = true;
 -            }
 -        }
 -        if ((pDevice->bHWRadioOff == true) || (pDevice->bRadioControlOff == true)) {
 -            CARDbRadioPowerOff(pDevice);
 -        }
 +              // use relative tx timeout and 802.11i D4
 +              MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_CFG, (CFG_TKIPOPT | CFG_NOTXTIMEOUT));
  
 -#endif
 -    }
 -            pMgmt->eScanType = WMAC_SCAN_PASSIVE;
 -    // get Permanent network address
 -    SROMvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr);
 -      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %pM\n",
 -              pDevice->abyCurrentNetAddr);
 +              // set performance parameter by registry
 +              MACvSetShortRetryLimit(pDevice->PortOffset, pDevice->byShortRetryLimit);
 +              MACvSetLongRetryLimit(pDevice->PortOffset, pDevice->byLongRetryLimit);
  
 -    // reset Tx pointer
 -    CARDvSafeResetRx(pDevice);
 -    // reset Rx pointer
 -    CARDvSafeResetTx(pDevice);
 +              // reset TSF counter
 +              VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
 +              // enable TSF counter
 +              VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
  
 -    if (pDevice->byLocalID <= REV_ID_VT3253_A1) {
 -        MACvRegBitsOn(pDevice->PortOffset, MAC_REG_RCR, RCR_WPAERR);
 -    }
 +              // initialize BBP registers
 +              BBbVT3253Init(pDevice);
  
 -    pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
 +              if (pDevice->bUpdateBBVGA) {
 +                      pDevice->byBBVGACurrent = pDevice->abyBBVGA[0];
 +                      pDevice->byBBVGANew = pDevice->byBBVGACurrent;
 +                      BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]);
 +              }
 +              BBvSetRxAntennaMode(pDevice->PortOffset, pDevice->byRxAntennaMode);
 +              BBvSetTxAntennaMode(pDevice->PortOffset, pDevice->byTxAntennaMode);
  
 -    // Turn On Rx DMA
 -    MACvReceive0(pDevice->PortOffset);
 -    MACvReceive1(pDevice->PortOffset);
 +              pDevice->byCurrentCh = 0;
  
 -    // start the adapter
 -    MACvStart(pDevice->PortOffset);
 +              //pDevice->NetworkType = Ndis802_11Automode;
 +              // Set BB and packet type at the same time.
 +              // Set Short Slot Time, xIFS, and RSPINF.
 +              if (pDevice->uConnectionRate == RATE_AUTO) {
 +                      pDevice->wCurrentRate = RATE_54M;
 +              } else {
 +                      pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
 +              }
  
 -    netif_stop_queue(pDevice->dev);
 +              // default G Mode
 +              VNTWIFIbConfigPhyMode(pDevice->pMgmt, PHY_TYPE_11G);
 +              VNTWIFIbConfigPhyMode(pDevice->pMgmt, PHY_TYPE_AUTO);
  
 +              pDevice->bRadioOff = false;
  
 -}
 +              pDevice->byRadioCtl = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RADIOCTL);
 +              pDevice->bHWRadioOff = false;
  
 +              if (pDevice->byRadioCtl & EEP_RADIOCTL_ENABLE) {
 +                      // Get GPIO
 +                      MACvGPIOIn(pDevice->PortOffset, &pDevice->byGPIO);
 +//2008-4-14 <add> by chester for led issue
 +#ifdef FOR_LED_ON_NOTEBOOK
 +                      if (pDevice->byGPIO & GPIO0_DATA) { pDevice->bHWRadioOff = true; }
 +                      if (!(pDevice->byGPIO & GPIO0_DATA)) { pDevice->bHWRadioOff = false; }
  
 +              }
 +              if ((pDevice->bRadioControlOff == true)) {
 +                      CARDbRadioPowerOff(pDevice);
 +              } else  CARDbRadioPowerOn(pDevice);
 +#else
 +              if (((pDevice->byGPIO & GPIO0_DATA) && !(pDevice->byRadioCtl & EEP_RADIOCTL_INV)) ||
 +                  (!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV))) {
 +                      pDevice->bHWRadioOff = true;
 +              }
 +      }
 +      if ((pDevice->bHWRadioOff == true) || (pDevice->bRadioControlOff == true)) {
 +              CARDbRadioPowerOff(pDevice);
 +      }
  
 -static void device_init_diversity_timer(PSDevice pDevice) {
 +#endif
 +}
 +pMgmt->eScanType = WMAC_SCAN_PASSIVE;
 +// get Permanent network address
 +SROMvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr);
 +DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Network address = %pM\n",
 +      pDevice->abyCurrentNetAddr);
 +
 +// reset Tx pointer
 +CARDvSafeResetRx(pDevice);
 +// reset Rx pointer
 +CARDvSafeResetTx(pDevice);
 +
 +if (pDevice->byLocalID <= REV_ID_VT3253_A1) {
 +      MACvRegBitsOn(pDevice->PortOffset, MAC_REG_RCR, RCR_WPAERR);
 +}
  
 -    init_timer(&pDevice->TimerSQ3Tmax1);
 -    pDevice->TimerSQ3Tmax1.data = (unsigned long) pDevice;
 -    pDevice->TimerSQ3Tmax1.function = (TimerFunction)TimerSQ3CallBack;
 -    pDevice->TimerSQ3Tmax1.expires = RUN_AT(HZ);
 +pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
  
 -    init_timer(&pDevice->TimerSQ3Tmax2);
 -    pDevice->TimerSQ3Tmax2.data = (unsigned long) pDevice;
 -    pDevice->TimerSQ3Tmax2.function = (TimerFunction)TimerSQ3CallBack;
 -    pDevice->TimerSQ3Tmax2.expires = RUN_AT(HZ);
 +// Turn On Rx DMA
 +MACvReceive0(pDevice->PortOffset);
 +MACvReceive1(pDevice->PortOffset);
  
 -    init_timer(&pDevice->TimerSQ3Tmax3);
 -    pDevice->TimerSQ3Tmax3.data = (unsigned long) pDevice;
 -    pDevice->TimerSQ3Tmax3.function = (TimerFunction)TimerState1CallBack;
 -    pDevice->TimerSQ3Tmax3.expires = RUN_AT(HZ);
 +// start the adapter
 +MACvStart(pDevice->PortOffset);
  
 -    return;
 +netif_stop_queue(pDevice->dev);
  }
  
 +static void device_init_diversity_timer(PSDevice pDevice) {
 +      init_timer(&pDevice->TimerSQ3Tmax1);
 +      pDevice->TimerSQ3Tmax1.data = (unsigned long) pDevice;
 +      pDevice->TimerSQ3Tmax1.function = (TimerFunction)TimerSQ3CallBack;
 +      pDevice->TimerSQ3Tmax1.expires = RUN_AT(HZ);
 +
 +      init_timer(&pDevice->TimerSQ3Tmax2);
 +      pDevice->TimerSQ3Tmax2.data = (unsigned long) pDevice;
 +      pDevice->TimerSQ3Tmax2.function = (TimerFunction)TimerSQ3CallBack;
 +      pDevice->TimerSQ3Tmax2.expires = RUN_AT(HZ);
 +
 +      init_timer(&pDevice->TimerSQ3Tmax3);
 +      pDevice->TimerSQ3Tmax3.data = (unsigned long) pDevice;
 +      pDevice->TimerSQ3Tmax3.function = (TimerFunction)TimerState1CallBack;
 +      pDevice->TimerSQ3Tmax3.expires = RUN_AT(HZ);
 +
 +      return;
 +}
  
  static bool device_release_WPADEV(PSDevice pDevice)
  {
 -  viawget_wpa_header *wpahdr;
 -  int ii=0;
 - // wait_queue_head_t Set_wait;
 -  //send device close to wpa_supplicnat layer
 -    if (pDevice->bWPADEVUp==true) {
 -                 wpahdr = (viawget_wpa_header *)pDevice->skb->data;
 -                 wpahdr->type = VIAWGET_DEVICECLOSE_MSG;
 -                 wpahdr->resp_ie_len = 0;
 -                 wpahdr->req_ie_len = 0;
 -                 skb_put(pDevice->skb, sizeof(viawget_wpa_header));
 -                 pDevice->skb->dev = pDevice->wpadev;
 -               skb_reset_mac_header(pDevice->skb);
 -                 pDevice->skb->pkt_type = PACKET_HOST;
 -                 pDevice->skb->protocol = htons(ETH_P_802_2);
 -                 memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
 -                 netif_rx(pDevice->skb);
 -                 pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
 -
 - //wait release WPADEV
 -              //    init_waitqueue_head(&Set_wait);
 -              //    wait_event_timeout(Set_wait, ((pDevice->wpadev==NULL)&&(pDevice->skb == NULL)),5*HZ);    //1s wait
 -              while((pDevice->bWPADEVUp==true)) {
 -              set_current_state(TASK_UNINTERRUPTIBLE);
 -                 schedule_timeout (HZ/20);          //wait 50ms
 -                 ii++;
 -              if(ii>20)
 -                break;
 -              }
 -           }
 -    return true;
 +      viawget_wpa_header *wpahdr;
 +      int ii = 0;
 +      // wait_queue_head_t    Set_wait;
 +      //send device close to wpa_supplicnat layer
 +      if (pDevice->bWPADEVUp == true) {
 +              wpahdr = (viawget_wpa_header *)pDevice->skb->data;
 +              wpahdr->type = VIAWGET_DEVICECLOSE_MSG;
 +              wpahdr->resp_ie_len = 0;
 +              wpahdr->req_ie_len = 0;
 +              skb_put(pDevice->skb, sizeof(viawget_wpa_header));
 +              pDevice->skb->dev = pDevice->wpadev;
 +              skb_reset_mac_header(pDevice->skb);
 +              pDevice->skb->pkt_type = PACKET_HOST;
 +              pDevice->skb->protocol = htons(ETH_P_802_2);
 +              memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
 +              netif_rx(pDevice->skb);
 +              pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
 +
 +              //wait release WPADEV
 +              //    init_waitqueue_head(&Set_wait);
 +              //    wait_event_timeout(Set_wait, ((pDevice->wpadev==NULL)&&(pDevice->skb == NULL)),5*HZ);    //1s wait
 +              while ((pDevice->bWPADEVUp == true)) {
 +                      set_current_state(TASK_UNINTERRUPTIBLE);
 +                      schedule_timeout(HZ / 20);          //wait 50ms
 +                      ii++;
 +                      if (ii > 20)
 +                              break;
 +              }
 +      }
 +      return true;
  }
  
  static const struct net_device_ops device_netdev_ops = {
  static int
  vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
  {
 -    static bool bFirst = true;
 -    struct net_device*  dev = NULL;
 -    PCHIP_INFO  pChip_info = (PCHIP_INFO)ent->driver_data;
 -    PSDevice    pDevice;
 -    int         rc;
 -    if (device_nics ++>= MAX_UINTS) {
 -        printk(KERN_NOTICE DEVICE_NAME ": already found %d NICs\n", device_nics);
 -        return -ENODEV;
 -    }
 -
 -
 -    dev = alloc_etherdev(sizeof(DEVICE_INFO));
 -
 -    pDevice = (PSDevice) netdev_priv(dev);
 -
 -    if (dev == NULL) {
 -        printk(KERN_ERR DEVICE_NAME ": allocate net device failed \n");
 -        return -ENOMEM;
 -    }
 -
 -    // Chain it all together
 -   // SET_MODULE_OWNER(dev);
 -    SET_NETDEV_DEV(dev, &pcid->dev);
 -
 -    if (bFirst) {
 -        printk(KERN_NOTICE "%s Ver. %s\n",DEVICE_FULL_DRV_NAM, DEVICE_VERSION);
 -        printk(KERN_NOTICE "Copyright (c) 2003 VIA Networking Technologies, Inc.\n");
 -        bFirst=false;
 -    }
 -
 -    vt6655_init_info(pcid, &pDevice, pChip_info);
 -    pDevice->dev = dev;
 -    pDevice->next_module = root_device_dev;
 -    root_device_dev = dev;
 -
 -    if (pci_enable_device(pcid)) {
 -        device_free_info(pDevice);
 -        return -ENODEV;
 -    }
 -    dev->irq = pcid->irq;
 +      static bool bFirst = true;
 +      struct net_device *dev = NULL;
 +      PCHIP_INFO  pChip_info = (PCHIP_INFO)ent->driver_data;
 +      PSDevice    pDevice;
 +      int         rc;
 +      if (device_nics++ >= MAX_UINTS) {
 +              printk(KERN_NOTICE DEVICE_NAME ": already found %d NICs\n", device_nics);
 +              return -ENODEV;
 +      }
 +
 +      dev = alloc_etherdev(sizeof(DEVICE_INFO));
 +
 +      pDevice = (PSDevice) netdev_priv(dev);
 +
 +      if (dev == NULL) {
 +              printk(KERN_ERR DEVICE_NAME ": allocate net device failed \n");
 +              return -ENOMEM;
 +      }
 +
 +      // Chain it all together
 +      // SET_MODULE_OWNER(dev);
 +      SET_NETDEV_DEV(dev, &pcid->dev);
 +
 +      if (bFirst) {
 +              printk(KERN_NOTICE "%s Ver. %s\n", DEVICE_FULL_DRV_NAM, DEVICE_VERSION);
 +              printk(KERN_NOTICE "Copyright (c) 2003 VIA Networking Technologies, Inc.\n");
 +              bFirst = false;
 +      }
 +
 +      vt6655_init_info(pcid, &pDevice, pChip_info);
 +      pDevice->dev = dev;
 +      pDevice->next_module = root_device_dev;
 +      root_device_dev = dev;
 +
 +      if (pci_enable_device(pcid)) {
 +              device_free_info(pDevice);
 +              return -ENODEV;
 +      }
 +      dev->irq = pcid->irq;
  
  #ifdef        DEBUG
 -      printk("Before get pci_info memaddr is %x\n",pDevice->memaddr);
 +      printk("Before get pci_info memaddr is %x\n", pDevice->memaddr);
  #endif
 -    if (device_get_pci_info(pDevice,pcid) == false) {
 -        printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device.\n");
 -        device_free_info(pDevice);
 -        return -ENODEV;
 -    }
 +      if (device_get_pci_info(pDevice, pcid) == false) {
 +              printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device.\n");
 +              device_free_info(pDevice);
 +              return -ENODEV;
 +      }
  
  #if 1
  
  #ifdef        DEBUG
  
        //pci_read_config_byte(pcid, PCI_BASE_ADDRESS_0, &pDevice->byRevId);
 -      printk("after get pci_info memaddr is %x, io addr is %x,io_size is %d\n",pDevice->memaddr,pDevice->ioaddr,pDevice->io_size);
 +      printk("after get pci_info memaddr is %x, io addr is %x,io_size is %d\n", pDevice->memaddr, pDevice->ioaddr, pDevice->io_size);
        {
                int i;
 -              u32                     bar,len;
 +              u32 bar, len;
                u32 address[] = {
 -              PCI_BASE_ADDRESS_0,
 -              PCI_BASE_ADDRESS_1,
 -              PCI_BASE_ADDRESS_2,
 -              PCI_BASE_ADDRESS_3,
 -              PCI_BASE_ADDRESS_4,
 -              PCI_BASE_ADDRESS_5,
 -              0};
 -              for (i=0;address[i];i++)
 -              {
 +                      PCI_BASE_ADDRESS_0,
 +                      PCI_BASE_ADDRESS_1,
 +                      PCI_BASE_ADDRESS_2,
 +                      PCI_BASE_ADDRESS_3,
 +                      PCI_BASE_ADDRESS_4,
 +                      PCI_BASE_ADDRESS_5,
 +                      0};
 +              for (i = 0; address[i]; i++) {
                        //pci_write_config_dword(pcid,address[i], 0xFFFFFFFF);
                        pci_read_config_dword(pcid, address[i], &bar);
 -                      printk("bar %d is %x\n",i,bar);
 -                      if (!bar)
 -                      {
 -                              printk("bar %d not implemented\n",i);
 +                      printk("bar %d is %x\n", i, bar);
 +                      if (!bar) {
 +                              printk("bar %d not implemented\n", i);
                                continue;
                        }
                        if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
 -                      /* This is IO */
 +                              /* This is IO */
  
 -                      len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
 -                      len = len & ~(len - 1);
 +                              len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
 +                              len = len & ~(len - 1);
  
 -                      printk("IO space:  len in IO %x, BAR %d\n", len, i);
 -                      }
 -                      else
 -                      {
 +                              printk("IO space:  len in IO %x, BAR %d\n", len, i);
 +                      } else {
                                len = bar & 0xFFFFFFF0;
                                len = ~len + 1;
  
        }
  #endif
  
 -
  #endif
  
  #ifdef        DEBUG
 -      //return  0  ;
 +      //return  0;
  #endif
 -    pDevice->PortOffset = (unsigned long)ioremap(pDevice->memaddr & PCI_BASE_ADDRESS_MEM_MASK, pDevice->io_size);
 +      pDevice->PortOffset = (unsigned long)ioremap(pDevice->memaddr & PCI_BASE_ADDRESS_MEM_MASK, pDevice->io_size);
        //pDevice->PortOffset = (unsigned long)ioremap(pDevice->ioaddr & PCI_BASE_ADDRESS_IO_MASK, pDevice->io_size);
  
 -      if(pDevice->PortOffset == 0) {
 -       printk(KERN_ERR DEVICE_NAME ": Failed to IO remapping ..\n");
 -       device_free_info(pDevice);
 -        return -ENODEV;
 -    }
 -
 -
 -
 +      if (pDevice->PortOffset == 0) {
 +              printk(KERN_ERR DEVICE_NAME ": Failed to IO remapping ..\n");
 +              device_free_info(pDevice);
 +              return -ENODEV;
 +      }
  
 -    rc = pci_request_regions(pcid, DEVICE_NAME);
 -    if (rc) {
 -        printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device\n");
 -        device_free_info(pDevice);
 -        return -ENODEV;
 -    }
 +      rc = pci_request_regions(pcid, DEVICE_NAME);
 +      if (rc) {
 +              printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device\n");
 +              device_free_info(pDevice);
 +              return -ENODEV;
 +      }
  
 -    dev->base_addr = pDevice->ioaddr;
 +      dev->base_addr = pDevice->ioaddr;
  #ifdef        PLICE_DEBUG
 -      unsigned char   value;
 +      unsigned char value;
  
        VNSvInPortB(pDevice->PortOffset+0x4F, &value);
 -      printk("Before write: value is %x\n",value);
 +      printk("Before write: value is %x\n", value);
        //VNSvInPortB(pDevice->PortOffset+0x3F, 0x00);
 -      VNSvOutPortB(pDevice->PortOffset,value);
 +      VNSvOutPortB(pDevice->PortOffset, value);
        VNSvInPortB(pDevice->PortOffset+0x4F, &value);
 -      printk("After write: value is %x\n",value);
 +      printk("After write: value is %x\n", value);
  #endif
  
 -
 -
  #ifdef IO_MAP
 -    pDevice->PortOffset = pDevice->ioaddr;
 +      pDevice->PortOffset = pDevice->ioaddr;
  #endif
 -    // do reset
 -    if (!MACbSoftwareReset(pDevice->PortOffset)) {
 -        printk(KERN_ERR DEVICE_NAME ": Failed to access MAC hardware..\n");
 -        device_free_info(pDevice);
 -        return -ENODEV;
 -    }
 -    // initial to reload eeprom
 -    MACvInitialize(pDevice->PortOffset);
 -    MACvReadEtherAddress(pDevice->PortOffset, dev->dev_addr);
 -
 -    device_get_options(pDevice, device_nics-1, dev->name);
 -    device_set_options(pDevice);
 -    //Mask out the options cannot be set to the chip
 -    pDevice->sOpts.flags &= pChip_info->flags;
 -
 -    //Enable the chip specified capabilities
 -    pDevice->flags = pDevice->sOpts.flags | (pChip_info->flags & 0xFF000000UL);
 -    pDevice->tx_80211 = device_dma0_tx_80211;
 -    pDevice->sMgmtObj.pAdapter = (void *)pDevice;
 -    pDevice->pMgmt = &(pDevice->sMgmtObj);
 -
 -    dev->irq                = pcid->irq;
 -    dev->netdev_ops         = &device_netdev_ops;
 +      // do reset
 +      if (!MACbSoftwareReset(pDevice->PortOffset)) {
 +              printk(KERN_ERR DEVICE_NAME ": Failed to access MAC hardware..\n");
 +              device_free_info(pDevice);
 +              return -ENODEV;
 +      }
 +      // initial to reload eeprom
 +      MACvInitialize(pDevice->PortOffset);
 +      MACvReadEtherAddress(pDevice->PortOffset, dev->dev_addr);
  
 -      dev->wireless_handlers = (struct iw_handler_def *)&iwctl_handler_def;
 +      device_get_options(pDevice, device_nics-1, dev->name);
 +      device_set_options(pDevice);
 +      //Mask out the options cannot be set to the chip
 +      pDevice->sOpts.flags &= pChip_info->flags;
 +
 +      //Enable the chip specified capabilities
 +      pDevice->flags = pDevice->sOpts.flags | (pChip_info->flags & 0xFF000000UL);
 +      pDevice->tx_80211 = device_dma0_tx_80211;
 +      pDevice->sMgmtObj.pAdapter = (void *)pDevice;
 +      pDevice->pMgmt = &(pDevice->sMgmtObj);
  
 -    rc = register_netdev(dev);
 -    if (rc)
 -    {
 -        printk(KERN_ERR DEVICE_NAME " Failed to register netdev\n");
 -        device_free_info(pDevice);
 -        return -ENODEV;
 -    }
 -    device_print_info(pDevice);
 -    pci_set_drvdata(pcid, pDevice);
 -    return 0;
 +      dev->irq                = pcid->irq;
 +      dev->netdev_ops         = &device_netdev_ops;
 +
 +      dev->wireless_handlers = (struct iw_handler_def *)&iwctl_handler_def;
  
 +      rc = register_netdev(dev);
 +      if (rc) {
 +              printk(KERN_ERR DEVICE_NAME " Failed to register netdev\n");
 +              device_free_info(pDevice);
 +              return -ENODEV;
 +      }
 +      device_print_info(pDevice);
 +      pci_set_drvdata(pcid, pDevice);
 +      return 0;
  }
  
  static void device_print_info(PSDevice pDevice)
  {
 -    struct net_device* dev=pDevice->dev;
 +      struct net_device *dev = pDevice->dev;
  
 -    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: %s\n",dev->name, get_chip_name(pDevice->chip_id));
 -    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: MAC=%pM", dev->name, dev->dev_addr);
 +      DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: %s\n", dev->name, get_chip_name(pDevice->chip_id));
 +      DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: MAC=%pM", dev->name, dev->dev_addr);
  #ifdef IO_MAP
 -    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IO=0x%lx  ",(unsigned long) pDevice->ioaddr);
 -    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IRQ=%d \n", pDevice->dev->irq);
 +      DBG_PRT(MSG_LEVEL_INFO, KERN_INFO " IO=0x%lx  ", (unsigned long)pDevice->ioaddr);
 +      DBG_PRT(MSG_LEVEL_INFO, KERN_INFO " IRQ=%d \n", pDevice->dev->irq);
  #else
 -    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IO=0x%lx Mem=0x%lx ",
 -                  (unsigned long) pDevice->ioaddr,(unsigned long) pDevice->PortOffset);
 -    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IRQ=%d \n", pDevice->dev->irq);
 +      DBG_PRT(MSG_LEVEL_INFO, KERN_INFO " IO=0x%lx Mem=0x%lx ",
 +              (unsigned long)pDevice->ioaddr, (unsigned long)pDevice->PortOffset);
 +      DBG_PRT(MSG_LEVEL_INFO, KERN_INFO " IRQ=%d \n", pDevice->dev->irq);
  #endif
 -
  }
  
 -static void vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice,
 -    PCHIP_INFO pChip_info) {
 -
 -    PSDevice p;
 +static void vt6655_init_info(struct pci_dev *pcid, PSDevice *ppDevice,
 +                           PCHIP_INFO pChip_info) {
 +      PSDevice p;
  
 -    memset(*ppDevice,0,sizeof(DEVICE_INFO));
 +      memset(*ppDevice, 0, sizeof(DEVICE_INFO));
  
 -    if (pDevice_Infos == NULL) {
 -        pDevice_Infos =*ppDevice;
 -    }
 -    else {
 -        for (p=pDevice_Infos;p->next!=NULL;p=p->next)
 -            do {} while (0);
 -        p->next = *ppDevice;
 -        (*ppDevice)->prev = p;
 -    }
 +      if (pDevice_Infos == NULL) {
 +              pDevice_Infos = *ppDevice;
 +      } else {
 +              for (p = pDevice_Infos; p->next != NULL; p = p->next)
 +                      do {} while (0);
 +              p->next = *ppDevice;
 +              (*ppDevice)->prev = p;
 +      }
  
 -    (*ppDevice)->pcid = pcid;
 -    (*ppDevice)->chip_id = pChip_info->chip_id;
 -    (*ppDevice)->io_size = pChip_info->io_size;
 -    (*ppDevice)->nTxQueues = pChip_info->nTxQueue;
 -    (*ppDevice)->multicast_limit =32;
 +      (*ppDevice)->pcid = pcid;
 +      (*ppDevice)->chip_id = pChip_info->chip_id;
 +      (*ppDevice)->io_size = pChip_info->io_size;
 +      (*ppDevice)->nTxQueues = pChip_info->nTxQueue;
 +      (*ppDevice)->multicast_limit = 32;
  
 -    spin_lock_init(&((*ppDevice)->lock));
 +      spin_lock_init(&((*ppDevice)->lock));
  }
  
 -static bool device_get_pci_info(PSDevice pDevice, struct pci_dev* pcid) {
 -
 -    u16 pci_cmd;
 -    u8  b;
 -    unsigned int cis_addr;
 +static bool device_get_pci_info(PSDevice pDevice, struct pci_dev *pcid) {
 +      u16 pci_cmd;
 +      u8  b;
 +      unsigned int cis_addr;
  #ifdef        PLICE_DEBUG
        unsigned char pci_config[256];
 -      unsigned char   value =0x00;
 -      int             ii,j;
 -      u16     max_lat=0x0000;
 -      memset(pci_config,0x00,256);
 +      unsigned char value = 0x00;
 +      int             ii, j;
 +      u16     max_lat = 0x0000;
 +      memset(pci_config, 0x00, 256);
  #endif
  
 -    pci_read_config_byte(pcid, PCI_REVISION_ID, &pDevice->byRevId);
 -    pci_read_config_word(pcid, PCI_SUBSYSTEM_ID,&pDevice->SubSystemID);
 -    pci_read_config_word(pcid, PCI_SUBSYSTEM_VENDOR_ID, &pDevice->SubVendorID);
 -    pci_read_config_word(pcid, PCI_COMMAND, (u16 *) & (pci_cmd));
 +      pci_read_config_byte(pcid, PCI_REVISION_ID, &pDevice->byRevId);
 +      pci_read_config_word(pcid, PCI_SUBSYSTEM_ID, &pDevice->SubSystemID);
 +      pci_read_config_word(pcid, PCI_SUBSYSTEM_VENDOR_ID, &pDevice->SubVendorID);
 +      pci_read_config_word(pcid, PCI_COMMAND, (u16 *)&(pci_cmd));
  
 -    pci_set_master(pcid);
 +      pci_set_master(pcid);
  
 -    pDevice->memaddr = pci_resource_start(pcid,0);
 -    pDevice->ioaddr = pci_resource_start(pcid,1);
 +      pDevice->memaddr = pci_resource_start(pcid, 0);
 +      pDevice->ioaddr = pci_resource_start(pcid, 1);
  
  #ifdef        DEBUG
  //    pDevice->ioaddr = pci_resource_start(pcid, 0);
  //    pDevice->memaddr = pci_resource_start(pcid,1);
  #endif
  
 -    cis_addr = pci_resource_start(pcid,2);
 +      cis_addr = pci_resource_start(pcid, 2);
  
 -    pDevice->pcid = pcid;
 +      pDevice->pcid = pcid;
  
 -    pci_read_config_byte(pcid, PCI_COMMAND, &b);
 -    pci_write_config_byte(pcid, PCI_COMMAND, (b|PCI_COMMAND_MASTER));
 +      pci_read_config_byte(pcid, PCI_COMMAND, &b);
 +      pci_write_config_byte(pcid, PCI_COMMAND, (b|PCI_COMMAND_MASTER));
  
  #ifdef        PLICE_DEBUG
 -      //pci_read_config_word(pcid,PCI_MAX_LAT,&max_lat);
 -      //printk("max lat is %x,SubSystemID is %x\n",max_lat,pDevice->SubSystemID);
 +      //pci_read_config_word(pcid,PCI_MAX_LAT,&max_lat);
        //for (ii=0;ii<0xFF;ii++)
        //pci_read_config_word(pcid,PCI_MAX_LAT,&max_lat);
        //max_lat  = 0x20;
        //pci_write_config_word(pcid,PCI_MAX_LAT,max_lat);
        //pci_read_config_word(pcid,PCI_MAX_LAT,&max_lat);
 -      //printk("max lat is %x\n",max_lat);
  
 -      for (ii=0;ii<0xFF;ii++)
 -      {
 -              pci_read_config_byte(pcid,ii,&value);
 +      for (ii = 0; ii < 0xFF; ii++) {
 +              pci_read_config_byte(pcid, ii, &value);
                pci_config[ii] = value;
        }
 -      for (ii=0,j=1;ii<0x100;ii++,j++)
 -      {
 -              if (j %16 == 0)
 -              {
 -                      printk("%x:",pci_config[ii]);
 +      for (ii = 0, j = 1; ii < 0x100; ii++, j++) {
 +              if (j % 16 == 0) {
 +                      printk("%x:", pci_config[ii]);
                        printk("\n");
 -              }
 -              else
 -              {
 -                      printk("%x:",pci_config[ii]);
 +              } else {
 +                      printk("%x:", pci_config[ii]);
                }
        }
  #endif
 -    return true;
 +      return true;
  }
  
  static void device_free_info(PSDevice pDevice) {
 -    PSDevice         ptr;
 -    struct net_device*  dev=pDevice->dev;
 +      PSDevice         ptr;
 +      struct net_device *dev = pDevice->dev;
  
 -    ASSERT(pDevice);
 +      ASSERT(pDevice);
  //2008-0714-01<Add>by chester
 -device_release_WPADEV(pDevice);
 +      device_release_WPADEV(pDevice);
  
  //2008-07-21-01<Add>by MikeLiu
  //unregister wpadev
 -   if(wpa_set_wpadev(pDevice, 0)!=0)
 -     printk("unregister wpadev fail?\n");
 -
 -    if (pDevice_Infos==NULL)
 -        return;
 -
 -    for (ptr=pDevice_Infos;ptr && (ptr!=pDevice);ptr=ptr->next)
 -            do {} while (0);
 -
 -    if (ptr==pDevice) {
 -        if (ptr==pDevice_Infos)
 -            pDevice_Infos=ptr->next;
 -        else
 -            ptr->prev->next=ptr->next;
 -    }
 -    else {
 -        DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "info struct not found\n");
 -        return;
 -    }
 +      if (wpa_set_wpadev(pDevice, 0) != 0)
 +              printk("unregister wpadev fail?\n");
 +
 +      if (pDevice_Infos == NULL)
 +              return;
 +
 +      for (ptr = pDevice_Infos; ptr && (ptr != pDevice); ptr = ptr->next)
 +              do {} while (0);
 +
 +      if (ptr == pDevice) {
 +              if (ptr == pDevice_Infos)
 +                      pDevice_Infos = ptr->next;
 +              else
 +                      ptr->prev->next = ptr->next;
 +      } else {
 +              DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "info struct not found\n");
 +              return;
 +      }
  #ifdef HOSTAP
 -    if (dev)
 -        vt6655_hostap_set_hostapd(pDevice, 0, 0);
 +      if (dev)
 +              vt6655_hostap_set_hostapd(pDevice, 0, 0);
  #endif
 -    if (dev)
 -        unregister_netdev(dev);
 +      if (dev)
 +              unregister_netdev(dev);
  
 -    if (pDevice->PortOffset)
 -        iounmap((void *)pDevice->PortOffset);
 +      if (pDevice->PortOffset)
 +              iounmap((void *)pDevice->PortOffset);
  
 -    if (pDevice->pcid)
 -        pci_release_regions(pDevice->pcid);
 -    if (dev)
 -        free_netdev(dev);
 +      if (pDevice->pcid)
 +              pci_release_regions(pDevice->pcid);
 +      if (dev)
 +              free_netdev(dev);
  
 -    if (pDevice->pcid) {
 -        pci_set_drvdata(pDevice->pcid,NULL);
 -    }
 +      if (pDevice->pcid) {
 +              pci_set_drvdata(pDevice->pcid, NULL);
 +      }
  }
  
  static bool device_init_rings(PSDevice pDevice) {
 -    void*   vir_pool;
 -
 -
 -    /*allocate all RD/TD rings a single pool*/
 -    vir_pool = pci_alloc_consistent(pDevice->pcid,
 -                    pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
 -                    pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
 -                    pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
 -                    pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
 -                    &pDevice->pool_dma);
 -
 -    if (vir_pool == NULL) {
 -        DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : allocate desc dma memory failed\n", pDevice->dev->name);
 -        return false;
 -    }
 -
 -    memset(vir_pool, 0,
 -            pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
 -            pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
 -            pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
 -            pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc)
 -          );
 -
 -    pDevice->aRD0Ring = vir_pool;
 -    pDevice->aRD1Ring = vir_pool +
 -                        pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc);
 -
 -
 -    pDevice->rd0_pool_dma = pDevice->pool_dma;
 -    pDevice->rd1_pool_dma = pDevice->rd0_pool_dma +
 -                            pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc);
 -
 -    pDevice->tx0_bufs = pci_alloc_consistent(pDevice->pcid,
 -                    pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
 -                    pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
 -                    CB_BEACON_BUF_SIZE +
 -                    CB_MAX_BUF_SIZE,
 -                    &pDevice->tx_bufs_dma0);
 -
 -    if (pDevice->tx0_bufs == NULL) {
 -        DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: allocate buf dma memory failed\n", pDevice->dev->name);
 -        pci_free_consistent(pDevice->pcid,
 -            pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
 -            pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
 -            pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
 -            pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
 -            vir_pool, pDevice->pool_dma
 -            );
 -        return false;
 -    }
 -
 -    memset(pDevice->tx0_bufs, 0,
 -           pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
 -           pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
 -           CB_BEACON_BUF_SIZE +
 -           CB_MAX_BUF_SIZE
 -          );
 -
 -    pDevice->td0_pool_dma = pDevice->rd1_pool_dma +
 -            pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc);
 -
 -    pDevice->td1_pool_dma = pDevice->td0_pool_dma +
 -            pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
 -
 +      void *vir_pool;
 +
 +      /*allocate all RD/TD rings a single pool*/
 +      vir_pool = pci_alloc_consistent(pDevice->pcid,
 +                                      pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
 +                                      pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
 +                                      pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
 +                                      pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
 +                                      &pDevice->pool_dma);
 +
 +      if (vir_pool == NULL) {
 +              DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s : allocate desc dma memory failed\n", pDevice->dev->name);
 +              return false;
 +      }
  
 -    // vir_pool: pvoid type
 -    pDevice->apTD0Rings = vir_pool
 -                          + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc)
 -                          + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc);
 +      memset(vir_pool, 0,
 +             pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
 +             pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
 +             pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
 +             pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc)
 +              );
 +
 +      pDevice->aRD0Ring = vir_pool;
 +      pDevice->aRD1Ring = vir_pool +
 +              pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc);
 +
 +      pDevice->rd0_pool_dma = pDevice->pool_dma;
 +      pDevice->rd1_pool_dma = pDevice->rd0_pool_dma +
 +              pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc);
 +
 +      pDevice->tx0_bufs = pci_alloc_consistent(pDevice->pcid,
 +                                               pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
 +                                               pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
 +                                               CB_BEACON_BUF_SIZE +
 +                                               CB_MAX_BUF_SIZE,
 +                                               &pDevice->tx_bufs_dma0);
 +
 +      if (pDevice->tx0_bufs == NULL) {
 +              DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: allocate buf dma memory failed\n", pDevice->dev->name);
 +              pci_free_consistent(pDevice->pcid,
 +                                  pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
 +                                  pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
 +                                  pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
 +                                  pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
 +                                  vir_pool, pDevice->pool_dma
 +                      );
 +              return false;
 +      }
  
 -    pDevice->apTD1Rings = vir_pool
 -            + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc)
 -            + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc)
 -            + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
 +      memset(pDevice->tx0_bufs, 0,
 +             pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
 +             pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
 +             CB_BEACON_BUF_SIZE +
 +             CB_MAX_BUF_SIZE
 +              );
  
 +      pDevice->td0_pool_dma = pDevice->rd1_pool_dma +
 +              pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc);
  
 -    pDevice->tx1_bufs = pDevice->tx0_bufs +
 -            pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ;
 +      pDevice->td1_pool_dma = pDevice->td0_pool_dma +
 +              pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
  
 +      // vir_pool: pvoid type
 +      pDevice->apTD0Rings = vir_pool
 +              + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc)
 +              + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc);
  
 -    pDevice->tx_beacon_bufs = pDevice->tx1_bufs +
 -            pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ;
 +      pDevice->apTD1Rings = vir_pool
 +              + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc)
 +              + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc)
 +              + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
  
 -    pDevice->pbyTmpBuff = pDevice->tx_beacon_bufs +
 -            CB_BEACON_BUF_SIZE;
 +      pDevice->tx1_bufs = pDevice->tx0_bufs +
 +              pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ;
  
 -    pDevice->tx_bufs_dma1 = pDevice->tx_bufs_dma0 +
 -            pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ;
 +      pDevice->tx_beacon_bufs = pDevice->tx1_bufs +
 +              pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ;
  
 +      pDevice->pbyTmpBuff = pDevice->tx_beacon_bufs +
 +              CB_BEACON_BUF_SIZE;
  
 -    pDevice->tx_beacon_dma = pDevice->tx_bufs_dma1 +
 -            pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ;
 +      pDevice->tx_bufs_dma1 = pDevice->tx_bufs_dma0 +
 +              pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ;
  
 +      pDevice->tx_beacon_dma = pDevice->tx_bufs_dma1 +
 +              pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ;
  
 -    return true;
 +      return true;
  }
  
  static void device_free_rings(PSDevice pDevice) {
 -
 -    pci_free_consistent(pDevice->pcid,
 -            pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
 -            pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
 -            pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
 -            pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc)
 -            ,
 -            pDevice->aRD0Ring, pDevice->pool_dma
 -        );
 -
 -    if (pDevice->tx0_bufs)
 -        pci_free_consistent(pDevice->pcid,
 -           pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
 -           pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
 -           CB_BEACON_BUF_SIZE +
 -           CB_MAX_BUF_SIZE,
 -           pDevice->tx0_bufs, pDevice->tx_bufs_dma0
 -        );
 +      pci_free_consistent(pDevice->pcid,
 +                          pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
 +                          pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
 +                          pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
 +                          pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc)
 +                          ,
 +                          pDevice->aRD0Ring, pDevice->pool_dma
 +              );
 +
 +      if (pDevice->tx0_bufs)
 +              pci_free_consistent(pDevice->pcid,
 +                                  pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
 +                                  pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
 +                                  CB_BEACON_BUF_SIZE +
 +                                  CB_MAX_BUF_SIZE,
 +                                  pDevice->tx0_bufs, pDevice->tx_bufs_dma0
 +                      );
  }
  
  static void device_init_rd0_ring(PSDevice pDevice) {
 -    int i;
 -    dma_addr_t      curr = pDevice->rd0_pool_dma;
 -    PSRxDesc        pDesc;
 -
 -    /* Init the RD0 ring entries */
 -    for (i = 0; i < pDevice->sOpts.nRxDescs0; i ++, curr += sizeof(SRxDesc)) {
 -        pDesc = &(pDevice->aRD0Ring[i]);
 -        pDesc->pRDInfo = alloc_rd_info();
 -        ASSERT(pDesc->pRDInfo);
 -        if (!device_alloc_rx_buf(pDevice, pDesc)) {
 -            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc rx bufs\n",
 -            pDevice->dev->name);
 -        }
 -        pDesc->next = &(pDevice->aRD0Ring[(i+1) % pDevice->sOpts.nRxDescs0]);
 -        pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
 -        pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
 -    }
 -
 -    if (i > 0)
 -        pDevice->aRD0Ring[i-1].next_desc = cpu_to_le32(pDevice->rd0_pool_dma);
 -    pDevice->pCurrRD[0] = &(pDevice->aRD0Ring[0]);
 -}
 +      int i;
 +      dma_addr_t      curr = pDevice->rd0_pool_dma;
 +      PSRxDesc        pDesc;
 +
 +      /* Init the RD0 ring entries */
 +      for (i = 0; i < pDevice->sOpts.nRxDescs0; i ++, curr += sizeof(SRxDesc)) {
 +              pDesc = &(pDevice->aRD0Ring[i]);
 +              pDesc->pRDInfo = alloc_rd_info();
 +              ASSERT(pDesc->pRDInfo);
 +              if (!device_alloc_rx_buf(pDevice, pDesc)) {
 +                      DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc rx bufs\n",
 +                              pDevice->dev->name);
 +              }
 +              pDesc->next = &(pDevice->aRD0Ring[(i+1) % pDevice->sOpts.nRxDescs0]);
 +              pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
 +              pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
 +      }
  
 +      if (i > 0)
 +              pDevice->aRD0Ring[i-1].next_desc = cpu_to_le32(pDevice->rd0_pool_dma);
 +      pDevice->pCurrRD[0] = &(pDevice->aRD0Ring[0]);
 +}
  
  static void device_init_rd1_ring(PSDevice pDevice) {
 -    int i;
 -    dma_addr_t      curr = pDevice->rd1_pool_dma;
 -    PSRxDesc        pDesc;
 -
 -    /* Init the RD1 ring entries */
 -    for (i = 0; i < pDevice->sOpts.nRxDescs1; i ++, curr += sizeof(SRxDesc)) {
 -        pDesc = &(pDevice->aRD1Ring[i]);
 -        pDesc->pRDInfo = alloc_rd_info();
 -        ASSERT(pDesc->pRDInfo);
 -        if (!device_alloc_rx_buf(pDevice, pDesc)) {
 -            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc rx bufs\n",
 -            pDevice->dev->name);
 -        }
 -        pDesc->next = &(pDevice->aRD1Ring[(i+1) % pDevice->sOpts.nRxDescs1]);
 -        pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
 -        pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
 -    }
 -
 -    if (i > 0)
 -        pDevice->aRD1Ring[i-1].next_desc = cpu_to_le32(pDevice->rd1_pool_dma);
 -    pDevice->pCurrRD[1] = &(pDevice->aRD1Ring[0]);
 -}
 +      int i;
 +      dma_addr_t      curr = pDevice->rd1_pool_dma;
 +      PSRxDesc        pDesc;
 +
 +      /* Init the RD1 ring entries */
 +      for (i = 0; i < pDevice->sOpts.nRxDescs1; i ++, curr += sizeof(SRxDesc)) {
 +              pDesc = &(pDevice->aRD1Ring[i]);
 +              pDesc->pRDInfo = alloc_rd_info();
 +              ASSERT(pDesc->pRDInfo);
 +              if (!device_alloc_rx_buf(pDevice, pDesc)) {
 +                      DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc rx bufs\n",
 +                              pDevice->dev->name);
 +              }
 +              pDesc->next = &(pDevice->aRD1Ring[(i+1) % pDevice->sOpts.nRxDescs1]);
 +              pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
 +              pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
 +      }
  
 +      if (i > 0)
 +              pDevice->aRD1Ring[i-1].next_desc = cpu_to_le32(pDevice->rd1_pool_dma);
 +      pDevice->pCurrRD[1] = &(pDevice->aRD1Ring[0]);
 +}
  
  static void device_init_defrag_cb(PSDevice pDevice) {
 -    int i;
 -    PSDeFragControlBlock pDeF;
 -
 -    /* Init the fragment ctl entries */
 -    for (i = 0; i < CB_MAX_RX_FRAG; i++) {
 -        pDeF = &(pDevice->sRxDFCB[i]);
 -        if (!device_alloc_frag_buf(pDevice, pDeF)) {
 -            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc frag bufs\n",
 -                pDevice->dev->name);
 -        }
 -    }
 -    pDevice->cbDFCB = CB_MAX_RX_FRAG;
 -    pDevice->cbFreeDFCB = pDevice->cbDFCB;
 +      int i;
 +      PSDeFragControlBlock pDeF;
 +
 +      /* Init the fragment ctl entries */
 +      for (i = 0; i < CB_MAX_RX_FRAG; i++) {
 +              pDeF = &(pDevice->sRxDFCB[i]);
 +              if (!device_alloc_frag_buf(pDevice, pDeF)) {
 +                      DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc frag bufs\n",
 +                              pDevice->dev->name);
 +              }
 +      }
 +      pDevice->cbDFCB = CB_MAX_RX_FRAG;
 +      pDevice->cbFreeDFCB = pDevice->cbDFCB;
  }
  
 -
 -
 -
  static void device_free_rd0_ring(PSDevice pDevice) {
 -    int i;
 -
 -    for (i = 0; i < pDevice->sOpts.nRxDescs0; i++) {
 -        PSRxDesc        pDesc =&(pDevice->aRD0Ring[i]);
 -        PDEVICE_RD_INFO  pRDInfo =pDesc->pRDInfo;
 +      int i;
  
 -        pci_unmap_single(pDevice->pcid,pRDInfo->skb_dma,
 -           pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
 +      for (i = 0; i < pDevice->sOpts.nRxDescs0; i++) {
 +              PSRxDesc        pDesc = &(pDevice->aRD0Ring[i]);
 +              PDEVICE_RD_INFO  pRDInfo = pDesc->pRDInfo;
  
 -        dev_kfree_skb(pRDInfo->skb);
 +              pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma,
 +                               pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
  
 -        kfree((void *)pDesc->pRDInfo);
 -    }
 +              dev_kfree_skb(pRDInfo->skb);
  
 +              kfree((void *)pDesc->pRDInfo);
 +      }
  }
  
  static void device_free_rd1_ring(PSDevice pDevice) {
 -    int i;
 -
 -
 -    for (i = 0; i < pDevice->sOpts.nRxDescs1; i++) {
 -        PSRxDesc        pDesc=&(pDevice->aRD1Ring[i]);
 -        PDEVICE_RD_INFO  pRDInfo=pDesc->pRDInfo;
 +      int i;
  
 -        pci_unmap_single(pDevice->pcid,pRDInfo->skb_dma,
 -           pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
 +      for (i = 0; i < pDevice->sOpts.nRxDescs1; i++) {
 +              PSRxDesc        pDesc = &(pDevice->aRD1Ring[i]);
 +              PDEVICE_RD_INFO  pRDInfo = pDesc->pRDInfo;
  
 -        dev_kfree_skb(pRDInfo->skb);
 +              pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma,
 +                               pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
  
 -        kfree((void *)pDesc->pRDInfo);
 -    }
 +              dev_kfree_skb(pRDInfo->skb);
  
 +              kfree((void *)pDesc->pRDInfo);
 +      }
  }
  
  static void device_free_frag_buf(PSDevice pDevice) {
 -    PSDeFragControlBlock pDeF;
 -    int i;
 -
 -    for (i = 0; i < CB_MAX_RX_FRAG; i++) {
 -
 -        pDeF = &(pDevice->sRxDFCB[i]);
 +      PSDeFragControlBlock pDeF;
 +      int i;
  
 -        if (pDeF->skb)
 -            dev_kfree_skb(pDeF->skb);
 +      for (i = 0; i < CB_MAX_RX_FRAG; i++) {
 +              pDeF = &(pDevice->sRxDFCB[i]);
  
 -    }
 +              if (pDeF->skb)
 +                      dev_kfree_skb(pDeF->skb);
  
 +      }
  }
  
  static void device_init_td0_ring(PSDevice pDevice) {
 -    int i;
 -    dma_addr_t  curr;
 -    PSTxDesc        pDesc;
 -
 -    curr = pDevice->td0_pool_dma;
 -    for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++, curr += sizeof(STxDesc)) {
 -        pDesc = &(pDevice->apTD0Rings[i]);
 -        pDesc->pTDInfo = alloc_td_info();
 -        ASSERT(pDesc->pTDInfo);
 -        if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
 -            pDesc->pTDInfo->buf = pDevice->tx0_bufs + (i)*PKT_BUF_SZ;
 -            pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma0 + (i)*PKT_BUF_SZ;
 -        }
 -        pDesc->next =&(pDevice->apTD0Rings[(i+1) % pDevice->sOpts.nTxDescs[0]]);
 -        pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
 -        pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
 -    }
 -
 -    if (i > 0)
 -        pDevice->apTD0Rings[i-1].next_desc = cpu_to_le32(pDevice->td0_pool_dma);
 -    pDevice->apTailTD[0] = pDevice->apCurrTD[0] =&(pDevice->apTD0Rings[0]);
 +      int i;
 +      dma_addr_t  curr;
 +      PSTxDesc        pDesc;
 +
 +      curr = pDevice->td0_pool_dma;
 +      for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++, curr += sizeof(STxDesc)) {
 +              pDesc = &(pDevice->apTD0Rings[i]);
 +              pDesc->pTDInfo = alloc_td_info();
 +              ASSERT(pDesc->pTDInfo);
 +              if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
 +                      pDesc->pTDInfo->buf = pDevice->tx0_bufs + (i)*PKT_BUF_SZ;
 +                      pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma0 + (i)*PKT_BUF_SZ;
 +              }
 +              pDesc->next = &(pDevice->apTD0Rings[(i+1) % pDevice->sOpts.nTxDescs[0]]);
 +              pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
 +              pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
 +      }
  
 +      if (i > 0)
 +              pDevice->apTD0Rings[i-1].next_desc = cpu_to_le32(pDevice->td0_pool_dma);
 +      pDevice->apTailTD[0] = pDevice->apCurrTD[0] = &(pDevice->apTD0Rings[0]);
  }
  
  static void device_init_td1_ring(PSDevice pDevice) {
 -    int i;
 -    dma_addr_t  curr;
 -    PSTxDesc    pDesc;
 -
 -    /* Init the TD ring entries */
 -    curr=pDevice->td1_pool_dma;
 -    for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++, curr+=sizeof(STxDesc)) {
 -        pDesc=&(pDevice->apTD1Rings[i]);
 -        pDesc->pTDInfo = alloc_td_info();
 -        ASSERT(pDesc->pTDInfo);
 -        if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
 -            pDesc->pTDInfo->buf=pDevice->tx1_bufs+(i)*PKT_BUF_SZ;
 -            pDesc->pTDInfo->buf_dma=pDevice->tx_bufs_dma1+(i)*PKT_BUF_SZ;
 -        }
 -        pDesc->next=&(pDevice->apTD1Rings[(i+1) % pDevice->sOpts.nTxDescs[1]]);
 -        pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
 -        pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
 -    }
 -
 -    if (i > 0)
 -        pDevice->apTD1Rings[i-1].next_desc = cpu_to_le32(pDevice->td1_pool_dma);
 -    pDevice->apTailTD[1] = pDevice->apCurrTD[1] = &(pDevice->apTD1Rings[0]);
 -}
 -
 +      int i;
 +      dma_addr_t  curr;
 +      PSTxDesc    pDesc;
 +
 +      /* Init the TD ring entries */
 +      curr = pDevice->td1_pool_dma;
 +      for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++, curr += sizeof(STxDesc)) {
 +              pDesc = &(pDevice->apTD1Rings[i]);
 +              pDesc->pTDInfo = alloc_td_info();
 +              ASSERT(pDesc->pTDInfo);
 +              if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
 +                      pDesc->pTDInfo->buf = pDevice->tx1_bufs + (i) * PKT_BUF_SZ;
 +                      pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma1 + (i) * PKT_BUF_SZ;
 +              }
 +              pDesc->next = &(pDevice->apTD1Rings[(i + 1) % pDevice->sOpts.nTxDescs[1]]);
 +              pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
 +              pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
 +      }
  
 +      if (i > 0)
 +              pDevice->apTD1Rings[i-1].next_desc = cpu_to_le32(pDevice->td1_pool_dma);
 +      pDevice->apTailTD[1] = pDevice->apCurrTD[1] = &(pDevice->apTD1Rings[0]);
 +}
  
  static void device_free_td0_ring(PSDevice pDevice) {
 -    int i;
 -    for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++) {
 -        PSTxDesc        pDesc=&(pDevice->apTD0Rings[i]);
 -        PDEVICE_TD_INFO  pTDInfo=pDesc->pTDInfo;
 +      int i;
 +      for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++) {
 +              PSTxDesc        pDesc = &(pDevice->apTD0Rings[i]);
 +              PDEVICE_TD_INFO  pTDInfo = pDesc->pTDInfo;
  
 -        if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
 -            pci_unmap_single(pDevice->pcid,pTDInfo->skb_dma,
 -               pTDInfo->skb->len, PCI_DMA_TODEVICE);
 +              if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
 +                      pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma,
 +                                       pTDInfo->skb->len, PCI_DMA_TODEVICE);
  
 -        if (pTDInfo->skb)
 -            dev_kfree_skb(pTDInfo->skb);
 +              if (pTDInfo->skb)
 +                      dev_kfree_skb(pTDInfo->skb);
  
 -        kfree((void *)pDesc->pTDInfo);
 -    }
 +              kfree((void *)pDesc->pTDInfo);
 +      }
  }
  
  static void device_free_td1_ring(PSDevice pDevice) {
 -    int i;
 -
 -    for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++) {
 -        PSTxDesc        pDesc=&(pDevice->apTD1Rings[i]);
 -        PDEVICE_TD_INFO  pTDInfo=pDesc->pTDInfo;
 +      int i;
  
 -        if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
 -            pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma,
 -               pTDInfo->skb->len, PCI_DMA_TODEVICE);
 +      for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++) {
 +              PSTxDesc        pDesc = &(pDevice->apTD1Rings[i]);
 +              PDEVICE_TD_INFO  pTDInfo = pDesc->pTDInfo;
  
 -        if (pTDInfo->skb)
 -            dev_kfree_skb(pTDInfo->skb);
 +              if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
 +                      pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma,
 +                                       pTDInfo->skb->len, PCI_DMA_TODEVICE);
  
 -        kfree((void *)pDesc->pTDInfo);
 -    }
 +              if (pTDInfo->skb)
 +                      dev_kfree_skb(pTDInfo->skb);
  
 +              kfree((void *)pDesc->pTDInfo);
 +      }
  }
  
 -
 -
  /*-----------------------------------------------------------------*/
  
  static int device_rx_srv(PSDevice pDevice, unsigned int uIdx) {
 -    PSRxDesc    pRD;
 -    int works = 0;
 -
 +      PSRxDesc    pRD;
 +      int works = 0;
  
 -    for (pRD = pDevice->pCurrRD[uIdx];
 -         pRD->m_rd0RD0.f1Owner == OWNED_BY_HOST;
 -         pRD = pRD->next) {
 +      for (pRD = pDevice->pCurrRD[uIdx];
 +           pRD->m_rd0RD0.f1Owner == OWNED_BY_HOST;
 +           pRD = pRD->next) {
  //        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->pCurrRD = %x, works = %d\n", pRD, works);
 -        if (works++>15)
 -            break;
 -        if (device_receive_frame(pDevice, pRD)) {
 -            if (!device_alloc_rx_buf(pDevice,pRD)) {
 -                    DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
 -                    "%s: can not allocate rx buf\n", pDevice->dev->name);
 -                    break;
 -            }
 -        }
 -        pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC;
 -        pDevice->dev->last_rx = jiffies;
 -    }
 -
 -    pDevice->pCurrRD[uIdx]=pRD;
 -
 -    return works;
 -}
 +              if (works++ > 15)
 +                      break;
 +              if (device_receive_frame(pDevice, pRD)) {
 +                      if (!device_alloc_rx_buf(pDevice, pRD)) {
 +                              DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
 +                                      "%s: can not allocate rx buf\n", pDevice->dev->name);
 +                              break;
 +                      }
 +              }
 +              pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC;
 +              pDevice->dev->last_rx = jiffies;
 +      }
  
 +      pDevice->pCurrRD[uIdx] = pRD;
  
 -static bool device_alloc_rx_buf(PSDevice pDevice, PSRxDesc pRD) {
 +      return works;
 +}
  
 -    PDEVICE_RD_INFO pRDInfo=pRD->pRDInfo;
 +static bool device_alloc_rx_buf(PSDevice pDevice, PSRxDesc pRD) {
 +      PDEVICE_RD_INFO pRDInfo = pRD->pRDInfo;
 +
 +      pRDInfo->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
 +      if (pRDInfo->skb == NULL)
 +              return false;
 +      ASSERT(pRDInfo->skb);
 +      pRDInfo->skb->dev = pDevice->dev;
 +      pRDInfo->skb_dma = pci_map_single(pDevice->pcid, skb_tail_pointer(pRDInfo->skb),
 +                                        pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
 +      *((unsigned int *)&(pRD->m_rd0RD0)) = 0; /* FIX cast */
 +
 +      pRD->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz);
 +      pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC;
 +      pRD->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz);
 +      pRD->buff_addr = cpu_to_le32(pRDInfo->skb_dma);
 +
 +      return true;
 +}
  
 +bool device_alloc_frag_buf(PSDevice pDevice, PSDeFragControlBlock pDeF) {
 +      pDeF->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
 +      if (pDeF->skb == NULL)
 +              return false;
 +      ASSERT(pDeF->skb);
 +      pDeF->skb->dev = pDevice->dev;
  
 -    pRDInfo->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
 -#ifdef        PLICE_DEBUG
 -      //printk("device_alloc_rx_buf:skb is %x\n",pRDInfo->skb);
 -#endif
 -    if (pRDInfo->skb==NULL)
 -        return false;
 -    ASSERT(pRDInfo->skb);
 -    pRDInfo->skb->dev = pDevice->dev;
 -    pRDInfo->skb_dma = pci_map_single(pDevice->pcid, skb_tail_pointer(pRDInfo->skb),
 -                                    pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
 -    *((unsigned int *) &(pRD->m_rd0RD0)) = 0; /* FIX cast */
 -
 -    pRD->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz);
 -    pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC;
 -    pRD->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz);
 -    pRD->buff_addr = cpu_to_le32(pRDInfo->skb_dma);
 -
 -    return true;
 +      return true;
  }
  
 +static int device_tx_srv(PSDevice pDevice, unsigned int uIdx) {
 +      PSTxDesc                 pTD;
 +      bool bFull = false;
 +      int                      works = 0;
 +      unsigned char byTsr0;
 +      unsigned char byTsr1;
 +      unsigned int    uFrameSize, uFIFOHeaderSize;
 +      PSTxBufHead              pTxBufHead;
 +      struct net_device_stats *pStats = &pDevice->stats;
 +      struct sk_buff *skb;
 +      unsigned int    uNodeIndex;
 +      PSMgmtObject             pMgmt = pDevice->pMgmt;
 +
 +      for (pTD = pDevice->apTailTD[uIdx]; pDevice->iTDUsed[uIdx] > 0; pTD = pTD->next) {
 +              if (pTD->m_td0TD0.f1Owner == OWNED_BY_NIC)
 +                      break;
 +              if (works++ > 15)
 +                      break;
  
 +              byTsr0 = pTD->m_td0TD0.byTSR0;
 +              byTsr1 = pTD->m_td0TD0.byTSR1;
 +
 +              //Only the status of first TD in the chain is correct
 +              if (pTD->m_td1TD1.byTCR & TCR_STP) {
 +                      if ((pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0) {
 +                              uFIFOHeaderSize = pTD->pTDInfo->dwHeaderLength;
 +                              uFrameSize = pTD->pTDInfo->dwReqCount - uFIFOHeaderSize;
 +                              pTxBufHead = (PSTxBufHead) (pTD->pTDInfo->buf);
 +                              // Update the statistics based on the Transmit status
 +                              // now, we DONT check TSR0_CDH
 +
 +                              STAvUpdateTDStatCounter(&pDevice->scStatistic,
 +                                                      byTsr0, byTsr1,
 +                                                      (unsigned char *)(pTD->pTDInfo->buf + uFIFOHeaderSize),
 +                                                      uFrameSize, uIdx);
 +
 +                              BSSvUpdateNodeTxCounter(pDevice,
 +                                                      byTsr0, byTsr1,
 +                                                      (unsigned char *)(pTD->pTDInfo->buf),
 +                                                      uFIFOHeaderSize
 +                                      );
 +
 +                              if (!(byTsr1 & TSR1_TERR)) {
 +                                      if (byTsr0 != 0) {
 +                                              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X].\n",
 +                                                      (int)uIdx, byTsr1, byTsr0);
 +                                      }
 +                                      if ((pTxBufHead->wFragCtl & FRAGCTL_ENDFRAG) != FRAGCTL_NONFRAG) {
 +                                              pDevice->s802_11Counter.TransmittedFragmentCount++;
 +                                      }
 +                                      pStats->tx_packets++;
 +                                      pStats->tx_bytes += pTD->pTDInfo->skb->len;
 +                              } else {
 +                                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Tx[%d] dropped & tsr1[%02X] tsr0[%02X].\n",
 +                                              (int)uIdx, byTsr1, byTsr0);
 +                                      pStats->tx_errors++;
 +                                      pStats->tx_dropped++;
 +                              }
 +                      }
  
 -bool device_alloc_frag_buf(PSDevice pDevice, PSDeFragControlBlock pDeF) {
 +                      if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) {
 +                              if (pDevice->bEnableHostapd) {
 +                                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "tx call back netif.. \n");
 +                                      skb = pTD->pTDInfo->skb;
 +                                      skb->dev = pDevice->apdev;
 +                                      skb_reset_mac_header(skb);
 +                                      skb->pkt_type = PACKET_OTHERHOST;
 +                                      //skb->protocol = htons(ETH_P_802_2);
 +                                      memset(skb->cb, 0, sizeof(skb->cb));
 +                                      netif_rx(skb);
 +                              }
 +                      }
  
 -    pDeF->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
 -    if (pDeF->skb == NULL)
 -        return false;
 -    ASSERT(pDeF->skb);
 -    pDeF->skb->dev = pDevice->dev;
 +                      if (byTsr1 & TSR1_TERR) {
 +                              if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) {
 +                                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n",
 +                                              (int)uIdx, byTsr1, byTsr0);
 +                              }
  
 -    return true;
 -}
 +//                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n",
 +//                          (int)uIdx, byTsr1, byTsr0);
  
 +                              if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) &&
 +                                  (pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)) {
 +                                      unsigned short wAID;
 +                                      unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
 +
 +                                      skb = pTD->pTDInfo->skb;
 +                                      if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data), &uNodeIndex)) {
 +                                              if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) {
 +                                                      skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb);
 +                                                      pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++;
 +                                                      // set tx map
 +                                                      wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID;
 +                                                      pMgmt->abyPSTxMap[wAID >> 3] |=  byMask[wAID & 7];
 +                                                      pTD->pTDInfo->byFlags &= ~(TD_FLAGS_NETIF_SKB);
 +                                                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "tx_srv:tx fail re-queue sta index= %d, QueCnt= %d\n"
 +                                                              , (int)uNodeIndex, pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt);
 +                                                      pStats->tx_errors--;
 +                                                      pStats->tx_dropped--;
 +                                              }
 +                                      }
 +                              }
 +                      }
 +                      device_free_tx_buf(pDevice, pTD);
 +                      pDevice->iTDUsed[uIdx]--;
 +              }
 +      }
  
 +      if (uIdx == TYPE_AC0DMA) {
 +              // RESERV_AC0DMA reserved for relay
  
 -static int device_tx_srv(PSDevice pDevice, unsigned int uIdx) {
 -    PSTxDesc                 pTD;
 -    bool bFull=false;
 -    int                      works = 0;
 -    unsigned char byTsr0;
 -    unsigned char byTsr1;
 -    unsigned int      uFrameSize, uFIFOHeaderSize;
 -    PSTxBufHead              pTxBufHead;
 -    struct net_device_stats* pStats = &pDevice->stats;
 -    struct sk_buff*          skb;
 -    unsigned int      uNodeIndex;
 -    PSMgmtObject             pMgmt = pDevice->pMgmt;
 -
 -
 -    for (pTD = pDevice->apTailTD[uIdx]; pDevice->iTDUsed[uIdx] >0; pTD = pTD->next) {
 -
 -        if (pTD->m_td0TD0.f1Owner == OWNED_BY_NIC)
 -            break;
 -        if (works++>15)
 -            break;
 -
 -        byTsr0 = pTD->m_td0TD0.byTSR0;
 -        byTsr1 = pTD->m_td0TD0.byTSR1;
 -
 -        //Only the status of first TD in the chain is correct
 -        if (pTD->m_td1TD1.byTCR & TCR_STP) {
 -
 -            if ((pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0) {
 -                uFIFOHeaderSize = pTD->pTDInfo->dwHeaderLength;
 -                uFrameSize = pTD->pTDInfo->dwReqCount - uFIFOHeaderSize;
 -                pTxBufHead = (PSTxBufHead) (pTD->pTDInfo->buf);
 -                // Update the statistics based on the Transmit status
 -                // now, we DONT check TSR0_CDH
 -
 -                STAvUpdateTDStatCounter(&pDevice->scStatistic,
 -                        byTsr0, byTsr1,
 -                        (unsigned char *)(pTD->pTDInfo->buf + uFIFOHeaderSize),
 -                        uFrameSize, uIdx);
 -
 -
 -                BSSvUpdateNodeTxCounter(pDevice,
 -                         byTsr0, byTsr1,
 -                         (unsigned char *)(pTD->pTDInfo->buf),
 -                         uFIFOHeaderSize
 -                         );
 -
 -                if ( !(byTsr1 & TSR1_TERR)) {
 -                    if (byTsr0 != 0) {
 -                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X].\n",
 -                           (int)uIdx, byTsr1, byTsr0);
 -                    }
 -                    if ((pTxBufHead->wFragCtl & FRAGCTL_ENDFRAG) != FRAGCTL_NONFRAG) {
 -                        pDevice->s802_11Counter.TransmittedFragmentCount ++;
 -                    }
 -                    pStats->tx_packets++;
 -                    pStats->tx_bytes += pTD->pTDInfo->skb->len;
 -                }
 -                else {
 -                     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] dropped & tsr1[%02X] tsr0[%02X].\n",
 -                           (int)uIdx, byTsr1, byTsr0);
 -                    pStats->tx_errors++;
 -                    pStats->tx_dropped++;
 -                }
 -            }
 -
 -            if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) {
 -                if (pDevice->bEnableHostapd) {
 -                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "tx call back netif.. \n");
 -                    skb = pTD->pTDInfo->skb;
 -                      skb->dev = pDevice->apdev;
 -                      skb_reset_mac_header(skb);
 -                      skb->pkt_type = PACKET_OTHERHOST;
 -                  //skb->protocol = htons(ETH_P_802_2);
 -                      memset(skb->cb, 0, sizeof(skb->cb));
 -                      netif_rx(skb);
 -                  }
 -            }
 -
 -            if (byTsr1 & TSR1_TERR) {
 -            if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) {
 -                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n",
 -                          (int)uIdx, byTsr1, byTsr0);
 -            }
 -
 -//                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n",
 -//                          (int)uIdx, byTsr1, byTsr0);
 +              if (AVAIL_TD(pDevice, uIdx) < RESERV_AC0DMA) {
 +                      bFull = true;
 +                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " AC0DMA is Full = %d\n", pDevice->iTDUsed[uIdx]);
 +              }
 +              if (netif_queue_stopped(pDevice->dev) && (bFull == false)) {
 +                      netif_wake_queue(pDevice->dev);
 +              }
 +      }
  
 -                if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) &&
 -                    (pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)) {
 -                    unsigned short wAID;
 -                    unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
 -
 -                    skb = pTD->pTDInfo->skb;
 -                    if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data), &uNodeIndex)) {
 -                        if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) {
 -                            skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb);
 -                            pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++;
 -                            // set tx map
 -                            wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID;
 -                            pMgmt->abyPSTxMap[wAID >> 3] |=  byMask[wAID & 7];
 -                            pTD->pTDInfo->byFlags &= ~(TD_FLAGS_NETIF_SKB);
 -                            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "tx_srv:tx fail re-queue sta index= %d, QueCnt= %d\n"
 -                                    ,(int)uNodeIndex, pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt);
 -                            pStats->tx_errors--;
 -                            pStats->tx_dropped--;
 -                        }
 -                    }
 -                }
 -            }
 -            device_free_tx_buf(pDevice,pTD);
 -            pDevice->iTDUsed[uIdx]--;
 -        }
 -    }
 -
 -
 -    if (uIdx == TYPE_AC0DMA) {
 -        // RESERV_AC0DMA reserved for relay
 -
 -        if (AVAIL_TD(pDevice, uIdx) < RESERV_AC0DMA) {
 -            bFull = true;
 -            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " AC0DMA is Full = %d\n", pDevice->iTDUsed[uIdx]);
 -        }
 -        if (netif_queue_stopped(pDevice->dev) && (bFull==false)){
 -            netif_wake_queue(pDevice->dev);
 -        }
 -    }
 -
 -
 -    pDevice->apTailTD[uIdx] = pTD;
 -
 -    return works;
 -}
 +      pDevice->apTailTD[uIdx] = pTD;
  
 +      return works;
 +}
  
  static void device_error(PSDevice pDevice, unsigned short status) {
 -
 -    if (status & ISR_FETALERR) {
 -        DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
 -            "%s: Hardware fatal error.\n",
 -            pDevice->dev->name);
 -        netif_stop_queue(pDevice->dev);
 -        del_timer(&pDevice->sTimerCommand);
 -        del_timer(&(pDevice->pMgmt->sTimerSecondCallback));
 -        pDevice->bCmdRunning = false;
 -        MACbShutdown(pDevice->PortOffset);
 -        return;
 -    }
 -
 +      if (status & ISR_FETALERR) {
 +              DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
 +                      "%s: Hardware fatal error.\n",
 +                      pDevice->dev->name);
 +              netif_stop_queue(pDevice->dev);
 +              del_timer(&pDevice->sTimerCommand);
 +              del_timer(&(pDevice->pMgmt->sTimerSecondCallback));
 +              pDevice->bCmdRunning = false;
 +              MACbShutdown(pDevice->PortOffset);
 +              return;
 +      }
  }
  
  static void device_free_tx_buf(PSDevice pDevice, PSTxDesc pDesc) {
 -    PDEVICE_TD_INFO  pTDInfo=pDesc->pTDInfo;
 -    struct sk_buff* skb=pTDInfo->skb;
 +      PDEVICE_TD_INFO  pTDInfo = pDesc->pTDInfo;
 +      struct sk_buff *skb = pTDInfo->skb;
  
 -    // pre-allocated buf_dma can't be unmapped.
 -    if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) {
 -        pci_unmap_single(pDevice->pcid,pTDInfo->skb_dma,skb->len,
 -              PCI_DMA_TODEVICE);
 -    }
 +      // pre-allocated buf_dma can't be unmapped.
 +      if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) {
 +              pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma, skb->len,
 +                               PCI_DMA_TODEVICE);
 +      }
  
 -    if ((pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0)
 -        dev_kfree_skb_irq(skb);
 +      if ((pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0)
 +              dev_kfree_skb_irq(skb);
  
 -    pTDInfo->skb_dma = 0;
 -    pTDInfo->skb = 0;
 -    pTDInfo->byFlags = 0;
 +      pTDInfo->skb_dma = 0;
 +      pTDInfo->skb = 0;
 +      pTDInfo->byFlags = 0;
  }
  
 -
 -
  //PLICE_DEBUG ->
  void  InitRxManagementQueue(PSDevice  pDevice)
  {
  }
  //PLICE_DEBUG<-
  
 -
 -
 -
 -
  //PLICE_DEBUG ->
  int MlmeThread(
 -     void * Context)
 +      void *Context)
  {
        PSDevice        pDevice =  (PSDevice) Context;
        PSRxMgmtPacket                  pRxMgmtPacket;
 -      // int i ;
 +      // int i;
        //complete(&pDevice->notify);
 -//printk("Enter MngWorkItem,Queue packet num is %d\n",pDevice->rxManeQueue.packet_num);
  
 -      //printk("Enter MlmeThread,packet _num is %d\n",pDevice->rxManeQueue.packet_num);
        //i = 0;
  #if 1
 -      while (1)
 -      {
 -
 -      //printk("DDDD\n");
 -      //down(&pDevice->mlme_semaphore);
 -        // pRxMgmtPacket =  DeQueue(pDevice);
 +      while (1) {
 +              //down(&pDevice->mlme_semaphore);
 +              // pRxMgmtPacket =  DeQueue(pDevice);
  #if 1
                spin_lock_irq(&pDevice->lock);
 -               while(pDevice->rxManeQueue.packet_num != 0)
 -              {
 -                       pRxMgmtPacket =  DeQueue(pDevice);
 -                              //pDevice;
 -                              //DequeueManageObject(pDevice->FirstRecvMngList, pDevice->LastRecvMngList);
 +              while (pDevice->rxManeQueue.packet_num != 0) {
 +                      pRxMgmtPacket = DeQueue(pDevice);
 +                      //pDevice;
 +                      //DequeueManageObject(pDevice->FirstRecvMngList, pDevice->LastRecvMngList);
                        vMgrRxManagePacket(pDevice, pDevice->pMgmt, pRxMgmtPacket);
 -                      //printk("packet_num is %d\n",pDevice->rxManeQueue.packet_num);
 -
 -               }
 +              }
                spin_unlock_irq(&pDevice->lock);
                if (mlme_kill == 0)
 -              break;
 +                      break;
                //udelay(200);
  #endif
 -      //printk("Before schedule thread jiffies is %x\n",jiffies);
 -      schedule();
 -      //printk("after schedule thread jiffies is %x\n",jiffies);
 -      if (mlme_kill == 0)
 -              break;
 -      //printk("i is %d\n",i);
 +              schedule();
 +              if (mlme_kill == 0)
 +                      break;
        }
  
  #endif
        return 0;
 -
  }
  
 -
 -
  static int  device_open(struct net_device *dev) {
 -    PSDevice    pDevice=(PSDevice) netdev_priv(dev);
 -    int i;
 +      PSDevice pDevice = (PSDevice)netdev_priv(dev);
 +      int i;
  #ifdef WPA_SM_Transtatus
 -    extern SWPAResult wpa_Result;
 +      extern SWPAResult wpa_Result;
  #endif
  
 -    pDevice->rx_buf_sz = PKT_BUF_SZ;
 -    if (!device_init_rings(pDevice)) {
 -        return -ENOMEM;
 -    }
 +      pDevice->rx_buf_sz = PKT_BUF_SZ;
 +      if (!device_init_rings(pDevice)) {
 +              return -ENOMEM;
 +      }
  //2008-5-13 <add> by chester
 -    i=request_irq(pDevice->pcid->irq, &device_intr, IRQF_SHARED, dev->name, dev);
 -    if (i)
 -        return i;
 -      //printk("DEBUG1\n");
 +      i = request_irq(pDevice->pcid->irq, &device_intr, IRQF_SHARED, dev->name, dev);
 +      if (i)
 +              return i;
 +
  #ifdef WPA_SM_Transtatus
 -     memset(wpa_Result.ifname,0,sizeof(wpa_Result.ifname));
 -     wpa_Result.proto = 0;
 -     wpa_Result.key_mgmt = 0;
 -     wpa_Result.eap_type = 0;
 -     wpa_Result.authenticated = false;
 -     pDevice->fWPA_Authened = false;
 +      memset(wpa_Result.ifname, 0, sizeof(wpa_Result.ifname));
 +      wpa_Result.proto = 0;
 +      wpa_Result.key_mgmt = 0;
 +      wpa_Result.eap_type = 0;
 +      wpa_Result.authenticated = false;
 +      pDevice->fWPA_Authened = false;
  #endif
 -DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call device init rd0 ring\n");
 -device_init_rd0_ring(pDevice);
 -    device_init_rd1_ring(pDevice);
 -    device_init_defrag_cb(pDevice);
 -    device_init_td0_ring(pDevice);
 -    device_init_td1_ring(pDevice);
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call device init rd0 ring\n");
 +      device_init_rd0_ring(pDevice);
 +      device_init_rd1_ring(pDevice);
 +      device_init_defrag_cb(pDevice);
 +      device_init_td0_ring(pDevice);
 +      device_init_td1_ring(pDevice);
  //    VNTWIFIvSet11h(pDevice->pMgmt, pDevice->b11hEnable);
  
 -
 -    if (pDevice->bDiversityRegCtlON) {
 -        device_init_diversity_timer(pDevice);
 -    }
 -    vMgrObjectInit(pDevice);
 -    vMgrTimerInit(pDevice);
 +      if (pDevice->bDiversityRegCtlON) {
 +              device_init_diversity_timer(pDevice);
 +      }
 +      vMgrObjectInit(pDevice);
 +      vMgrTimerInit(pDevice);
  
  //PLICE_DEBUG->
  #ifdef        TASK_LET
 -      tasklet_init (&pDevice->RxMngWorkItem,(void *)MngWorkItem,(unsigned long )pDevice);
 +      tasklet_init(&pDevice->RxMngWorkItem, (void *)MngWorkItem, (unsigned long)pDevice);
  #endif
  #ifdef        THREAD
        InitRxManagementQueue(pDevice);
        mlme_kill = 0;
 -      mlme_task = kthread_run(MlmeThread,(void *) pDevice, "MLME");
 +      mlme_task = kthread_run(MlmeThread, (void *)pDevice, "MLME");
        if (IS_ERR(mlme_task)) {
                printk("thread create fail\n");
                return -1;
        mlme_kill = 1;
  #endif
  
 -
 -
 -      //printk("thread id is %d\n",pDevice->MLMEThr_pid);
 -      //printk("Create thread time is %x\n",jiffies);
        //wait_for_completion(&pDevice->notify);
  
 -
 -
 -
 -  // if (( SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RADIOCTL)&0x06)==0x04)
 -    //    return -ENOMEM;
 -DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call device_init_registers\n");
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call device_init_registers\n");
        device_init_registers(pDevice, DEVICE_INIT_COLD);
 -    MACvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr);
 -    memcpy(pDevice->pMgmt->abyMACAddr, pDevice->abyCurrentNetAddr, ETH_ALEN);
 -    device_set_multi(pDevice->dev);
 +      MACvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr);
 +      memcpy(pDevice->pMgmt->abyMACAddr, pDevice->abyCurrentNetAddr, ETH_ALEN);
 +      device_set_multi(pDevice->dev);
  
 -    // Init for Key Management
 -    KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
 -    add_timer(&(pDevice->pMgmt->sTimerSecondCallback));
 +      // Init for Key Management
 +      KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
 +      add_timer(&(pDevice->pMgmt->sTimerSecondCallback));
  
 -      #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
        /*
 -     pDevice->bwextstep0 = false;
 -     pDevice->bwextstep1 = false;
 -     pDevice->bwextstep2 = false;
 -     pDevice->bwextstep3 = false;
 -     */
 -       pDevice->bwextcount=0;
 -     pDevice->bWPASuppWextEnabled = false;
 +        pDevice->bwextstep0 = false;
 +        pDevice->bwextstep1 = false;
 +        pDevice->bwextstep2 = false;
 +        pDevice->bwextstep3 = false;
 +      */
 +      pDevice->bwextcount = 0;
 +      pDevice->bWPASuppWextEnabled = false;
  #endif
 -    pDevice->byReAssocCount = 0;
 -   pDevice->bWPADEVUp = false;
 -    // Patch: if WEP key already set by iwconfig but device not yet open
 -    if ((pDevice->bEncryptionEnable == true) && (pDevice->bTransmitKey == true)) {
 -        KeybSetDefaultKey(&(pDevice->sKey),
 -                            (unsigned long)(pDevice->byKeyIndex | (1 << 31)),
 -                            pDevice->uKeyLength,
 -                            NULL,
 -                            pDevice->abyKey,
 -                            KEY_CTL_WEP,
 -                            pDevice->PortOffset,
 -                            pDevice->byLocalID
 -                          );
 -         pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
 -    }
 -
 -//printk("DEBUG2\n");
 -
 -
 -DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call MACvIntEnable\n");
 +      pDevice->byReAssocCount = 0;
 +      pDevice->bWPADEVUp = false;
 +      // Patch: if WEP key already set by iwconfig but device not yet open
 +      if ((pDevice->bEncryptionEnable == true) && (pDevice->bTransmitKey == true)) {
 +              KeybSetDefaultKey(&(pDevice->sKey),
 +                                (unsigned long)(pDevice->byKeyIndex | (1 << 31)),
 +                                pDevice->uKeyLength,
 +                                NULL,
 +                                pDevice->abyKey,
 +                                KEY_CTL_WEP,
 +                                pDevice->PortOffset,
 +                                pDevice->byLocalID
 +                      );
 +              pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
 +      }
 +
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call MACvIntEnable\n");
        MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
  
 -    if (pDevice->pMgmt->eConfigMode == WMAC_CONFIG_AP) {
 -        bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL);
 +      if (pDevice->pMgmt->eConfigMode == WMAC_CONFIG_AP) {
 +              bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL);
 +      } else {
 +              bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
 +              bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
        }
 -      else {
 -        bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
 -        bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
 -    }
 -    pDevice->flags |=DEVICE_FLAGS_OPENED;
 +      pDevice->flags |= DEVICE_FLAGS_OPENED;
  
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open success.. \n");
 -    return 0;
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open success.. \n");
 +      return 0;
  }
  
 -
  static int  device_close(struct net_device *dev) {
 -    PSDevice  pDevice=(PSDevice) netdev_priv(dev);
 -    PSMgmtObject     pMgmt = pDevice->pMgmt;
 - //PLICE_DEBUG->
 +      PSDevice  pDevice = (PSDevice)netdev_priv(dev);
 +      PSMgmtObject     pMgmt = pDevice->pMgmt;
 +      //PLICE_DEBUG->
  #ifdef        THREAD
        mlme_kill = 0;
  #endif
  //PLICE_DEBUG<-
  //2007-1121-02<Add>by EinsnLiu
 -    if (pDevice->bLinkPass) {
 -      bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL);
 -        mdelay(30);
 -    }
 +      if (pDevice->bLinkPass) {
 +              bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL);
 +              mdelay(30);
 +      }
  #ifdef TxInSleep
 -    del_timer(&pDevice->sTimerTxData);
 +      del_timer(&pDevice->sTimerTxData);
  #endif
 -    del_timer(&pDevice->sTimerCommand);
 -    del_timer(&pMgmt->sTimerSecondCallback);
 -    if (pDevice->bDiversityRegCtlON) {
 -        del_timer(&pDevice->TimerSQ3Tmax1);
 -        del_timer(&pDevice->TimerSQ3Tmax2);
 -        del_timer(&pDevice->TimerSQ3Tmax3);
 -    }
 +      del_timer(&pDevice->sTimerCommand);
 +      del_timer(&pMgmt->sTimerSecondCallback);
 +      if (pDevice->bDiversityRegCtlON) {
 +              del_timer(&pDevice->TimerSQ3Tmax1);
 +              del_timer(&pDevice->TimerSQ3Tmax2);
 +              del_timer(&pDevice->TimerSQ3Tmax3);
 +      }
  
  #ifdef        TASK_LET
        tasklet_kill(&pDevice->RxMngWorkItem);
  #endif
 -     netif_stop_queue(dev);
 -    pDevice->bCmdRunning = false;
 -    MACbShutdown(pDevice->PortOffset);
 -    MACbSoftwareReset(pDevice->PortOffset);
 -    CARDbRadioPowerOff(pDevice);
 -
 -    pDevice->bLinkPass = false;
 -    memset(pMgmt->abyCurrBSSID, 0, 6);
 -    pMgmt->eCurrState = WMAC_STATE_IDLE;
 -    device_free_td0_ring(pDevice);
 -    device_free_td1_ring(pDevice);
 -    device_free_rd0_ring(pDevice);
 -    device_free_rd1_ring(pDevice);
 -    device_free_frag_buf(pDevice);
 -    device_free_rings(pDevice);
 -    BSSvClearNodeDBTable(pDevice, 0);
 -    free_irq(dev->irq, dev);
 -    pDevice->flags &=(~DEVICE_FLAGS_OPENED);
 +      netif_stop_queue(dev);
 +      pDevice->bCmdRunning = false;
 +      MACbShutdown(pDevice->PortOffset);
 +      MACbSoftwareReset(pDevice->PortOffset);
 +      CARDbRadioPowerOff(pDevice);
 +
 +      pDevice->bLinkPass = false;
 +      memset(pMgmt->abyCurrBSSID, 0, 6);
 +      pMgmt->eCurrState = WMAC_STATE_IDLE;
 +      device_free_td0_ring(pDevice);
 +      device_free_td1_ring(pDevice);
 +      device_free_rd0_ring(pDevice);
 +      device_free_rd1_ring(pDevice);
 +      device_free_frag_buf(pDevice);
 +      device_free_rings(pDevice);
 +      BSSvClearNodeDBTable(pDevice, 0);
 +      free_irq(dev->irq, dev);
 +      pDevice->flags &= (~DEVICE_FLAGS_OPENED);
        //2008-0714-01<Add>by chester
 -device_release_WPADEV(pDevice);
 +      device_release_WPADEV(pDevice);
  //PLICE_DEBUG->
        //tasklet_kill(&pDevice->RxMngWorkItem);
  //PLICE_DEBUG<-
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close.. \n");
 -    return 0;
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close.. \n");
 +      return 0;
  }
  
 +static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev) {
 +      PSDevice pDevice = netdev_priv(dev);
 +      unsigned char *pbMPDU;
 +      unsigned int cbMPDULen = 0;
  
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_tx_80211\n");
 +      spin_lock_irq(&pDevice->lock);
  
 -static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev) {
 -    PSDevice        pDevice=netdev_priv(dev);
 -    unsigned char *pbMPDU;
 -    unsigned int cbMPDULen = 0;
 +      if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) {
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_tx_80211, td0 <=0\n");
 +              dev_kfree_skb_irq(skb);
 +              spin_unlock_irq(&pDevice->lock);
 +              return 0;
 +      }
  
 +      if (pDevice->bStopTx0Pkt == true) {
 +              dev_kfree_skb_irq(skb);
 +              spin_unlock_irq(&pDevice->lock);
 +              return 0;
 +      }
  
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_tx_80211\n");
 -    spin_lock_irq(&pDevice->lock);
 +      cbMPDULen = skb->len;
 +      pbMPDU = skb->data;
  
 -    if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) {
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_tx_80211, td0 <=0\n");
 -        dev_kfree_skb_irq(skb);
 -        spin_unlock_irq(&pDevice->lock);
 -        return 0;
 -    }
 +      vDMA0_tx_80211(pDevice, skb, pbMPDU, cbMPDULen);
  
 -    if (pDevice->bStopTx0Pkt == true) {
 -        dev_kfree_skb_irq(skb);
 -        spin_unlock_irq(&pDevice->lock);
 -        return 0;
 -    }
 +      spin_unlock_irq(&pDevice->lock);
  
 -    cbMPDULen = skb->len;
 -    pbMPDU = skb->data;
 +      return 0;
 +}
  
 -    vDMA0_tx_80211(pDevice, skb, pbMPDU, cbMPDULen);
 +bool device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, unsigned int uNodeIndex) {
 +      PSMgmtObject    pMgmt = pDevice->pMgmt;
 +      PSTxDesc        pHeadTD, pLastTD;
 +      unsigned int cbFrameBodySize;
 +      unsigned int uMACfragNum;
 +      unsigned char byPktType;
 +      bool bNeedEncryption = false;
 +      PSKeyItem       pTransmitKey = NULL;
 +      unsigned int cbHeaderSize;
 +      unsigned int ii;
 +      SKeyItem        STempKey;
 +//    unsigned char byKeyIndex = 0;
  
 -    spin_unlock_irq(&pDevice->lock);
 +      if (pDevice->bStopTx0Pkt == true) {
 +              dev_kfree_skb_irq(skb);
 +              return false;
 +      }
  
 -    return 0;
 +      if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) {
 +              dev_kfree_skb_irq(skb);
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_xmit, td0 <=0\n");
 +              return false;
 +      }
  
 -}
 +      if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
 +              if (pDevice->uAssocCount == 0) {
 +                      dev_kfree_skb_irq(skb);
 +                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_xmit, assocCount = 0\n");
 +                      return false;
 +              }
 +      }
  
 +      pHeadTD = pDevice->apCurrTD[TYPE_TXDMA0];
  
 +      pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP);
  
 -bool device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, unsigned int uNodeIndex) {
 -    PSMgmtObject    pMgmt = pDevice->pMgmt;
 -    PSTxDesc        pHeadTD, pLastTD;
 -    unsigned int cbFrameBodySize;
 -    unsigned int uMACfragNum;
 -    unsigned char byPktType;
 -    bool bNeedEncryption = false;
 -    PSKeyItem       pTransmitKey = NULL;
 -    unsigned int cbHeaderSize;
 -    unsigned int ii;
 -    SKeyItem        STempKey;
 -//    unsigned char byKeyIndex = 0;
 +      memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)(skb->data), ETH_HLEN);
 +      cbFrameBodySize = skb->len - ETH_HLEN;
  
 +      // 802.1H
 +      if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN) {
 +              cbFrameBodySize += 8;
 +      }
 +      uMACfragNum = cbGetFragCount(pDevice, pTransmitKey, cbFrameBodySize, &pDevice->sTxEthHeader);
  
 -    if (pDevice->bStopTx0Pkt == true) {
 -        dev_kfree_skb_irq(skb);
 -        return false;
 -    }
 -
 -    if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) {
 -        dev_kfree_skb_irq(skb);
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_xmit, td0 <=0\n");
 -        return false;
 -    }
 -
 -    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
 -        if (pDevice->uAssocCount == 0) {
 -            dev_kfree_skb_irq(skb);
 -            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_xmit, assocCount = 0\n");
 -            return false;
 -        }
 -    }
 -
 -    pHeadTD = pDevice->apCurrTD[TYPE_TXDMA0];
 -
 -    pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP);
 -
 -    memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)(skb->data), ETH_HLEN);
 -    cbFrameBodySize = skb->len - ETH_HLEN;
 -
 -    // 802.1H
 -    if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN) {
 -        cbFrameBodySize += 8;
 -    }
 -    uMACfragNum = cbGetFragCount(pDevice, pTransmitKey, cbFrameBodySize, &pDevice->sTxEthHeader);
 -
 -    if ( uMACfragNum > AVAIL_TD(pDevice, TYPE_TXDMA0)) {
 -        dev_kfree_skb_irq(skb);
 -        return false;
 -    }
 -    byPktType = (unsigned char)pDevice->byPacketType;
 -
 -
 -    if (pDevice->bFixRate) {
 -        if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
 -            if (pDevice->uConnectionRate >= RATE_11M) {
 -                pDevice->wCurrentRate = RATE_11M;
 -            } else {
 -                pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
 -            }
 -        } else {
 -            if (pDevice->uConnectionRate >= RATE_54M)
 -                pDevice->wCurrentRate = RATE_54M;
 -            else
 -                pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
 -        }
 -    }
 -    else {
 -        pDevice->wCurrentRate = pDevice->pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate;
 -    }
 -
 -    //preamble type
 -    if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) {
 -        pDevice->byPreambleType = pDevice->byShortPreamble;
 -    }
 -    else {
 -        pDevice->byPreambleType = PREAMBLE_LONG;
 -    }
 -
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dma0: pDevice->wCurrentRate = %d \n", pDevice->wCurrentRate);
 -
 -
 -    if (pDevice->wCurrentRate <= RATE_11M) {
 -        byPktType = PK_TYPE_11B;
 -    } else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
 -        byPktType = PK_TYPE_11A;
 -    } else {
 -        if (pDevice->bProtectMode == true) {
 -            byPktType = PK_TYPE_11GB;
 -        } else {
 -            byPktType = PK_TYPE_11GA;
 -        }
 -    }
 -
 -    if (pDevice->bEncryptionEnable == true)
 -        bNeedEncryption = true;
 -
 -    if (pDevice->bEnableHostWEP) {
 -        pTransmitKey = &STempKey;
 -        pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
 -        pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
 -        pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
 -        pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
 -        pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
 -        memcpy(pTransmitKey->abyKey,
 -            &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
 -            pTransmitKey->uKeyLength
 -            );
 -    }
 -    vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption,
 -                        cbFrameBodySize, TYPE_TXDMA0, pHeadTD,
 -                        &pDevice->sTxEthHeader, (unsigned char *)skb->data, pTransmitKey, uNodeIndex,
 -                        &uMACfragNum,
 -                        &cbHeaderSize
 -                        );
 -
 -    if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
 -        // Disable PS
 -        MACbPSWakeup(pDevice->PortOffset);
 -    }
 -
 -    pDevice->bPWBitOn = false;
 -
 -    pLastTD = pHeadTD;
 -    for (ii = 0; ii < uMACfragNum; ii++) {
 -        // Poll Transmit the adapter
 -        wmb();
 -        pHeadTD->m_td0TD0.f1Owner=OWNED_BY_NIC;
 -        wmb();
 -        if (ii == (uMACfragNum - 1))
 -            pLastTD = pHeadTD;
 -        pHeadTD = pHeadTD->next;
 -    }
 -
 -    // Save the information needed by the tx interrupt handler
 -    // to complete the Send request
 -    pLastTD->pTDInfo->skb = skb;
 -    pLastTD->pTDInfo->byFlags = 0;
 -    pLastTD->pTDInfo->byFlags |= TD_FLAGS_NETIF_SKB;
 -
 -    pDevice->apCurrTD[TYPE_TXDMA0] = pHeadTD;
 -
 -    MACvTransmit0(pDevice->PortOffset);
 -
 -
 -    return true;
 +      if (uMACfragNum > AVAIL_TD(pDevice, TYPE_TXDMA0)) {
 +              dev_kfree_skb_irq(skb);
 +              return false;
 +      }
 +      byPktType = (unsigned char)pDevice->byPacketType;
 +
 +      if (pDevice->bFixRate) {
 +              if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
 +                      if (pDevice->uConnectionRate >= RATE_11M) {
 +                              pDevice->wCurrentRate = RATE_11M;
 +                      } else {
 +                              pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
 +                      }
 +              } else {
 +                      if (pDevice->uConnectionRate >= RATE_54M)
 +                              pDevice->wCurrentRate = RATE_54M;
 +                      else
 +                              pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
 +              }
 +      } else {
 +              pDevice->wCurrentRate = pDevice->pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate;
 +      }
 +
 +      //preamble type
 +      if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) {
 +              pDevice->byPreambleType = pDevice->byShortPreamble;
 +      } else {
 +              pDevice->byPreambleType = PREAMBLE_LONG;
 +      }
 +
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dma0: pDevice->wCurrentRate = %d \n", pDevice->wCurrentRate);
 +
 +      if (pDevice->wCurrentRate <= RATE_11M) {
 +              byPktType = PK_TYPE_11B;
 +      } else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
 +              byPktType = PK_TYPE_11A;
 +      } else {
 +              if (pDevice->bProtectMode == true) {
 +                      byPktType = PK_TYPE_11GB;
 +              } else {
 +                      byPktType = PK_TYPE_11GA;
 +              }
 +      }
 +
 +      if (pDevice->bEncryptionEnable == true)
 +              bNeedEncryption = true;
 +
 +      if (pDevice->bEnableHostWEP) {
 +              pTransmitKey = &STempKey;
 +              pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
 +              pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
 +              pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
 +              pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
 +              pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
 +              memcpy(pTransmitKey->abyKey,
 +                     &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
 +                     pTransmitKey->uKeyLength
 +                      );
 +      }
 +      vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption,
 +                          cbFrameBodySize, TYPE_TXDMA0, pHeadTD,
 +                          &pDevice->sTxEthHeader, (unsigned char *)skb->data, pTransmitKey, uNodeIndex,
 +                          &uMACfragNum,
 +                          &cbHeaderSize
 +              );
 +
 +      if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
 +              // Disable PS
 +              MACbPSWakeup(pDevice->PortOffset);
 +      }
 +
 +      pDevice->bPWBitOn = false;
 +
 +      pLastTD = pHeadTD;
 +      for (ii = 0; ii < uMACfragNum; ii++) {
 +              // Poll Transmit the adapter
 +              wmb();
 +              pHeadTD->m_td0TD0.f1Owner = OWNED_BY_NIC;
 +              wmb();
 +              if (ii == (uMACfragNum - 1))
 +                      pLastTD = pHeadTD;
 +              pHeadTD = pHeadTD->next;
 +      }
 +
 +      // Save the information needed by the tx interrupt handler
 +      // to complete the Send request
 +      pLastTD->pTDInfo->skb = skb;
 +      pLastTD->pTDInfo->byFlags = 0;
 +      pLastTD->pTDInfo->byFlags |= TD_FLAGS_NETIF_SKB;
 +
 +      pDevice->apCurrTD[TYPE_TXDMA0] = pHeadTD;
 +
 +      MACvTransmit0(pDevice->PortOffset);
 +
 +      return true;
  }
  
  //TYPE_AC0DMA data tx
  static int  device_xmit(struct sk_buff *skb, struct net_device *dev) {
 -    PSDevice pDevice=netdev_priv(dev);
 -
 -    PSMgmtObject    pMgmt = pDevice->pMgmt;
 -    PSTxDesc        pHeadTD, pLastTD;
 -    unsigned int uNodeIndex = 0;
 -    unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
 -    unsigned short wAID;
 -    unsigned int uMACfragNum = 1;
 -    unsigned int cbFrameBodySize;
 -    unsigned char byPktType;
 -    unsigned int cbHeaderSize;
 -    bool bNeedEncryption = false;
 -    PSKeyItem       pTransmitKey = NULL;
 -    SKeyItem        STempKey;
 -    unsigned int ii;
 -    bool bTKIP_UseGTK = false;
 -    bool bNeedDeAuth = false;
 -    unsigned char *pbyBSSID;
 -    bool bNodeExist = false;
 -
 -
 -
 -    spin_lock_irq(&pDevice->lock);
 -    if (pDevice->bLinkPass == false) {
 -        dev_kfree_skb_irq(skb);
 -        spin_unlock_irq(&pDevice->lock);
 -        return 0;
 -    }
 -
 -    if (pDevice->bStopDataPkt) {
 -        dev_kfree_skb_irq(skb);
 -        spin_unlock_irq(&pDevice->lock);
 -        return 0;
 -    }
 -
 -
 -    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
 -        if (pDevice->uAssocCount == 0) {
 -            dev_kfree_skb_irq(skb);
 -            spin_unlock_irq(&pDevice->lock);
 -            return 0;
 -        }
 -        if (is_multicast_ether_addr((unsigned char *)(skb->data))) {
 -            uNodeIndex = 0;
 -            bNodeExist = true;
 -            if (pMgmt->sNodeDBTable[0].bPSEnable) {
 -                skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skb);
 -                pMgmt->sNodeDBTable[0].wEnQueueCnt++;
 -                // set tx map
 -                pMgmt->abyPSTxMap[0] |= byMask[0];
 -                spin_unlock_irq(&pDevice->lock);
 -                return 0;
 -            }
 -}else {
 -            if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data), &uNodeIndex)) {
 -                if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) {
 -                    skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb);
 -                    pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++;
 -                    // set tx map
 -                    wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID;
 -                    pMgmt->abyPSTxMap[wAID >> 3] |=  byMask[wAID & 7];
 -                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set:pMgmt->abyPSTxMap[%d]= %d\n",
 -                             (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]);
 -                    spin_unlock_irq(&pDevice->lock);
 -                    return 0;
 -                }
 -
 -                if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) {
 -                    pDevice->byPreambleType = pDevice->byShortPreamble;
 -
 -                }else {
 -                    pDevice->byPreambleType = PREAMBLE_LONG;
 -                }
 -                bNodeExist = true;
 -
 -            }
 -        }
 -
 -        if (bNodeExist == false) {
 -            DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Unknown STA not found in node DB \n");
 -            dev_kfree_skb_irq(skb);
 -            spin_unlock_irq(&pDevice->lock);
 -            return 0;
 -        }
 -    }
 -
 -    pHeadTD = pDevice->apCurrTD[TYPE_AC0DMA];
 -
 -    pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP);
 -
 -
 -    memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)(skb->data), ETH_HLEN);
 -    cbFrameBodySize = skb->len - ETH_HLEN;
 -    // 802.1H
 -    if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN) {
 -        cbFrameBodySize += 8;
 -    }
 -
 -
 -    if (pDevice->bEncryptionEnable == true) {
 -        bNeedEncryption = true;
 -        // get Transmit key
 -        do {
 -            if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
 -                (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
 -                pbyBSSID = pDevice->abyBSSID;
 -                // get pairwise key
 -                if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) {
 -                    // get group key
 -                    if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) {
 -                        bTKIP_UseGTK = true;
 -                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n");
 -                        break;
 -                    }
 -                } else {
 -                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get PTK.\n");
 -                    break;
 -                }
 -            }else if (pDevice->pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
 -
 -                pbyBSSID = pDevice->sTxEthHeader.abyDstAddr;  //TO_DS = 0 and FROM_DS = 0 --> 802.11 MAC Address1
 -                DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS Serach Key: \n");
 -                for (ii = 0; ii< 6; ii++)
 -                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"%x \n", *(pbyBSSID+ii));
 -                DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"\n");
 -
 -                // get pairwise key
 -                if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == true)
 -                    break;
 -            }
 -            // get group key
 -            pbyBSSID = pDevice->abyBroadcastAddr;
 -            if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
 -                pTransmitKey = NULL;
 -                if (pDevice->pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
 -                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS and KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode);
 -                }
 -                else
 -                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"NOT IBSS and KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode);
 -            } else {
 -                bTKIP_UseGTK = true;
 -                DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n");
 -            }
 -        } while(false);
 -    }
 -
 -    if (pDevice->bEnableHostWEP) {
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"acdma0: STA index %d\n", uNodeIndex);
 -        if (pDevice->bEncryptionEnable == true) {
 -            pTransmitKey = &STempKey;
 -            pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
 -            pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
 -            pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
 -            pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
 -            pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
 -            memcpy(pTransmitKey->abyKey,
 -                &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
 -                pTransmitKey->uKeyLength
 -                );
 -         }
 -    }
 -
 -    uMACfragNum = cbGetFragCount(pDevice, pTransmitKey, cbFrameBodySize, &pDevice->sTxEthHeader);
 -
 -    if (uMACfragNum > AVAIL_TD(pDevice, TYPE_AC0DMA)) {
 -        DBG_PRT(MSG_LEVEL_ERR, KERN_DEBUG "uMACfragNum > AVAIL_TD(TYPE_AC0DMA) = %d\n", uMACfragNum);
 -        dev_kfree_skb_irq(skb);
 -        spin_unlock_irq(&pDevice->lock);
 -        return 0;
 -    }
 -
 -    if (pTransmitKey != NULL) {
 -        if ((pTransmitKey->byCipherSuite == KEY_CTL_WEP) &&
 -            (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN)) {
 -            uMACfragNum = 1; //WEP256 doesn't support fragment
 -        }
 -    }
 -
 -    byPktType = (unsigned char)pDevice->byPacketType;
 -
 -    if (pDevice->bFixRate) {
 +      PSDevice pDevice = netdev_priv(dev);
 +
 +      PSMgmtObject    pMgmt = pDevice->pMgmt;
 +      PSTxDesc        pHeadTD, pLastTD;
 +      unsigned int uNodeIndex = 0;
 +      unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
 +      unsigned short wAID;
 +      unsigned int uMACfragNum = 1;
 +      unsigned int cbFrameBodySize;
 +      unsigned char byPktType;
 +      unsigned int cbHeaderSize;
 +      bool bNeedEncryption = false;
 +      PSKeyItem       pTransmitKey = NULL;
 +      SKeyItem        STempKey;
 +      unsigned int ii;
 +      bool bTKIP_UseGTK = false;
 +      bool bNeedDeAuth = false;
 +      unsigned char *pbyBSSID;
 +      bool bNodeExist = false;
 +
 +      spin_lock_irq(&pDevice->lock);
 +      if (pDevice->bLinkPass == false) {
 +              dev_kfree_skb_irq(skb);
 +              spin_unlock_irq(&pDevice->lock);
 +              return 0;
 +      }
 +
 +      if (pDevice->bStopDataPkt) {
 +              dev_kfree_skb_irq(skb);
 +              spin_unlock_irq(&pDevice->lock);
 +              return 0;
 +      }
 +
 +      if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
 +              if (pDevice->uAssocCount == 0) {
 +                      dev_kfree_skb_irq(skb);
 +                      spin_unlock_irq(&pDevice->lock);
 +                      return 0;
 +              }
 +              if (is_multicast_ether_addr((unsigned char *)(skb->data))) {
 +                      uNodeIndex = 0;
 +                      bNodeExist = true;
 +                      if (pMgmt->sNodeDBTable[0].bPSEnable) {
 +                              skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skb);
 +                              pMgmt->sNodeDBTable[0].wEnQueueCnt++;
 +                              // set tx map
 +                              pMgmt->abyPSTxMap[0] |= byMask[0];
 +                              spin_unlock_irq(&pDevice->lock);
 +                              return 0;
 +                      }
 +              } else {
 +                      if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data), &uNodeIndex)) {
 +                              if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) {
 +                                      skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb);
 +                                      pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++;
 +                                      // set tx map
 +                                      wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID;
 +                                      pMgmt->abyPSTxMap[wAID >> 3] |=  byMask[wAID & 7];
 +                                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set:pMgmt->abyPSTxMap[%d]= %d\n",
 +                                              (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]);
 +                                      spin_unlock_irq(&pDevice->lock);
 +                                      return 0;
 +                              }
 +
 +                              if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) {
 +                                      pDevice->byPreambleType = pDevice->byShortPreamble;
 +
 +                              } else {
 +                                      pDevice->byPreambleType = PREAMBLE_LONG;
 +                              }
 +                              bNodeExist = true;
 +
 +                      }
 +              }
 +
 +              if (bNodeExist == false) {
 +                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Unknown STA not found in node DB \n");
 +                      dev_kfree_skb_irq(skb);
 +                      spin_unlock_irq(&pDevice->lock);
 +                      return 0;
 +              }
 +      }
 +
 +      pHeadTD = pDevice->apCurrTD[TYPE_AC0DMA];
 +
 +      pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP);
 +
 +      memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)(skb->data), ETH_HLEN);
 +      cbFrameBodySize = skb->len - ETH_HLEN;
 +      // 802.1H
 +      if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN) {
 +              cbFrameBodySize += 8;
 +      }
 +
 +      if (pDevice->bEncryptionEnable == true) {
 +              bNeedEncryption = true;
 +              // get Transmit key
 +              do {
 +                      if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
 +                          (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
 +                              pbyBSSID = pDevice->abyBSSID;
 +                              // get pairwise key
 +                              if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) {
 +                                      // get group key
 +                                      if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) {
 +                                              bTKIP_UseGTK = true;
 +                                              DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Get GTK.\n");
 +                                              break;
 +                                      }
 +                              } else {
 +                                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Get PTK.\n");
 +                                      break;
 +                              }
 +                      } else if (pDevice->pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
 +                              pbyBSSID = pDevice->sTxEthHeader.abyDstAddr;  //TO_DS = 0 and FROM_DS = 0 --> 802.11 MAC Address1
 +                              DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "IBSS Serach Key: \n");
 +                              for (ii = 0; ii < 6; ii++)
 +                                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "%x \n", *(pbyBSSID+ii));
 +                              DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "\n");
 +
 +                              // get pairwise key
 +                              if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == true)
 +                                      break;
 +                      }
 +                      // get group key
 +                      pbyBSSID = pDevice->abyBroadcastAddr;
 +                      if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
 +                              pTransmitKey = NULL;
 +                              if (pDevice->pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
 +                                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "IBSS and KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode);
 +                              } else
 +                                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "NOT IBSS and KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode);
 +                      } else {
 +                              bTKIP_UseGTK = true;
 +                              DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Get GTK.\n");
 +                      }
 +              } while (false);
 +      }
 +
 +      if (pDevice->bEnableHostWEP) {
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "acdma0: STA index %d\n", uNodeIndex);
 +              if (pDevice->bEncryptionEnable == true) {
 +                      pTransmitKey = &STempKey;
 +                      pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
 +                      pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
 +                      pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
 +                      pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
 +                      pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
 +                      memcpy(pTransmitKey->abyKey,
 +                             &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
 +                             pTransmitKey->uKeyLength
 +                              );
 +              }
 +      }
 +
 +      uMACfragNum = cbGetFragCount(pDevice, pTransmitKey, cbFrameBodySize, &pDevice->sTxEthHeader);
 +
 +      if (uMACfragNum > AVAIL_TD(pDevice, TYPE_AC0DMA)) {
 +              DBG_PRT(MSG_LEVEL_ERR, KERN_DEBUG "uMACfragNum > AVAIL_TD(TYPE_AC0DMA) = %d\n", uMACfragNum);
 +              dev_kfree_skb_irq(skb);
 +              spin_unlock_irq(&pDevice->lock);
 +              return 0;
 +      }
 +
 +      if (pTransmitKey != NULL) {
 +              if ((pTransmitKey->byCipherSuite == KEY_CTL_WEP) &&
 +                  (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN)) {
 +                      uMACfragNum = 1; //WEP256 doesn't support fragment
 +              }
 +      }
 +
 +      byPktType = (unsigned char)pDevice->byPacketType;
 +
 +      if (pDevice->bFixRate) {
  #ifdef        PLICE_DEBUG
 -      printk("Fix Rate: PhyType is %d,ConnectionRate is %d\n",pDevice->eCurrentPHYType,pDevice->uConnectionRate);
 +              printk("Fix Rate: PhyType is %d,ConnectionRate is %d\n", pDevice->eCurrentPHYType, pDevice->uConnectionRate);
  #endif
  
 -        if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
 -            if (pDevice->uConnectionRate >= RATE_11M) {
 -                pDevice->wCurrentRate = RATE_11M;
 -            } else {
 -                pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
 -            }
 -        } else {
 -            if ((pDevice->eCurrentPHYType == PHY_TYPE_11A) &&
 -                (pDevice->uConnectionRate <= RATE_6M)) {
 -                pDevice->wCurrentRate = RATE_6M;
 -            } else {
 -                if (pDevice->uConnectionRate >= RATE_54M)
 -                    pDevice->wCurrentRate = RATE_54M;
 -                else
 -                    pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
 -
 -            }
 -        }
 -        pDevice->byACKRate = (unsigned char) pDevice->wCurrentRate;
 -        pDevice->byTopCCKBasicRate = RATE_1M;
 -        pDevice->byTopOFDMBasicRate = RATE_6M;
 -    }
 -    else {
 -        //auto rate
 -    if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) {
 -            if (pDevice->eCurrentPHYType != PHY_TYPE_11A) {
 -                pDevice->wCurrentRate = RATE_1M;
 -                pDevice->byACKRate = RATE_1M;
 -                pDevice->byTopCCKBasicRate = RATE_1M;
 -                pDevice->byTopOFDMBasicRate = RATE_6M;
 -            } else {
 -                pDevice->wCurrentRate = RATE_6M;
 -                pDevice->byACKRate = RATE_6M;
 -                pDevice->byTopCCKBasicRate = RATE_1M;
 -                pDevice->byTopOFDMBasicRate = RATE_6M;
 -            }
 -        }
 -        else {
 -              VNTWIFIvGetTxRate(  pDevice->pMgmt,
 -                                pDevice->sTxEthHeader.abyDstAddr,
 -                                &(pDevice->wCurrentRate),
 -                                &(pDevice->byACKRate),
 -                                &(pDevice->byTopCCKBasicRate),
 -                                &(pDevice->byTopOFDMBasicRate));
 +              if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
 +                      if (pDevice->uConnectionRate >= RATE_11M) {
 +                              pDevice->wCurrentRate = RATE_11M;
 +                      } else {
 +                              pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
 +                      }
 +              } else {
 +                      if ((pDevice->eCurrentPHYType == PHY_TYPE_11A) &&
 +                          (pDevice->uConnectionRate <= RATE_6M)) {
 +                              pDevice->wCurrentRate = RATE_6M;
 +                      } else {
 +                              if (pDevice->uConnectionRate >= RATE_54M)
 +                                      pDevice->wCurrentRate = RATE_54M;
 +                              else
 +                                      pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
  
 +                      }
 +              }
 +              pDevice->byACKRate = (unsigned char) pDevice->wCurrentRate;
 +              pDevice->byTopCCKBasicRate = RATE_1M;
 +              pDevice->byTopOFDMBasicRate = RATE_6M;
 +      } else {
 +              //auto rate
 +              if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) {
 +                      if (pDevice->eCurrentPHYType != PHY_TYPE_11A) {
 +                              pDevice->wCurrentRate = RATE_1M;
 +                              pDevice->byACKRate = RATE_1M;
 +                              pDevice->byTopCCKBasicRate = RATE_1M;
 +                              pDevice->byTopOFDMBasicRate = RATE_6M;
 +                      } else {
 +                              pDevice->wCurrentRate = RATE_6M;
 +                              pDevice->byACKRate = RATE_6M;
 +                              pDevice->byTopCCKBasicRate = RATE_1M;
 +                              pDevice->byTopOFDMBasicRate = RATE_6M;
 +                      }
 +              } else {
 +                      VNTWIFIvGetTxRate(pDevice->pMgmt,
 +                                        pDevice->sTxEthHeader.abyDstAddr,
 +                                        &(pDevice->wCurrentRate),
 +                                        &(pDevice->byACKRate),
 +                                        &(pDevice->byTopCCKBasicRate),
 +                                        &(pDevice->byTopOFDMBasicRate));
  
                }
 -    }
 +      }
  
  //    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "acdma0: pDevice->wCurrentRate = %d \n", pDevice->wCurrentRate);
  
 -    if (pDevice->wCurrentRate <= RATE_11M) {
 -        byPktType = PK_TYPE_11B;
 -    } else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
 -        byPktType = PK_TYPE_11A;
 -    } else {
 -        if (pDevice->bProtectMode == true) {
 -            byPktType = PK_TYPE_11GB;
 -        } else {
 -            byPktType = PK_TYPE_11GA;
 -        }
 -    }
 +      if (pDevice->wCurrentRate <= RATE_11M) {
 +              byPktType = PK_TYPE_11B;
 +      } else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
 +              byPktType = PK_TYPE_11A;
 +      } else {
 +              if (pDevice->bProtectMode == true) {
 +                      byPktType = PK_TYPE_11GB;
 +              } else {
 +                      byPktType = PK_TYPE_11GA;
 +              }
 +      }
  
  //#ifdef      PLICE_DEBUG
  //    printk("FIX RATE:CurrentRate is %d");
  //#endif
  
 -    if (bNeedEncryption == true) {
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType));
 -        if ((pDevice->sTxEthHeader.wType) == TYPE_PKT_802_1x) {
 -            bNeedEncryption = false;
 -            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType));
 -            if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
 -                if (pTransmitKey == NULL) {
 -                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Don't Find TX KEY\n");
 -                }
 -                else {
 -                    if (bTKIP_UseGTK == true) {
 -                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"error: KEY is GTK!!~~\n");
 -                    }
 -                    else {
 -                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex);
 -                        bNeedEncryption = true;
 -                    }
 -                }
 -            }
 -
 -            if (pDevice->byCntMeasure == 2) {
 -                bNeedDeAuth = true;
 -                pDevice->s802_11Counter.TKIPCounterMeasuresInvoked++;
 -            }
 -
 -            if (pDevice->bEnableHostWEP) {
 -                if ((uNodeIndex != 0) &&
 -                    (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) {
 -                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex);
 -                    bNeedEncryption = true;
 -                 }
 -             }
 -        }
 -        else {
 -            if (pTransmitKey == NULL) {
 -                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"return no tx key\n");
 -                dev_kfree_skb_irq(skb);
 -                spin_unlock_irq(&pDevice->lock);
 -                return 0;
 -            }
 -        }
 -    }
 +      if (bNeedEncryption == true) {
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType));
 +              if ((pDevice->sTxEthHeader.wType) == TYPE_PKT_802_1x) {
 +                      bNeedEncryption = false;
 +                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType));
 +                      if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
 +                              if (pTransmitKey == NULL) {
 +                                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Don't Find TX KEY\n");
 +                              } else {
 +                                      if (bTKIP_UseGTK == true) {
 +                                              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "error: KEY is GTK!!~~\n");
 +                                      } else {
 +                                              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Find PTK [%lX]\n", pTransmitKey->dwKeyIndex);
 +                                              bNeedEncryption = true;
 +                                      }
 +                              }
 +                      }
  
 +                      if (pDevice->byCntMeasure == 2) {
 +                              bNeedDeAuth = true;
 +                              pDevice->s802_11Counter.TKIPCounterMeasuresInvoked++;
 +                      }
  
 -#ifdef        PLICE_DEBUG
 -      //if (skb->len == 98)
 -      //{
 -      //      printk("ping:len is %d\n");
 -      //}
 -#endif
 -    vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption,
 -                        cbFrameBodySize, TYPE_AC0DMA, pHeadTD,
 -                        &pDevice->sTxEthHeader, (unsigned char *)skb->data, pTransmitKey, uNodeIndex,
 -                        &uMACfragNum,
 -                        &cbHeaderSize
 -                        );
 -
 -    if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
 -        // Disable PS
 -        MACbPSWakeup(pDevice->PortOffset);
 -    }
 -    pDevice->bPWBitOn = false;
 -
 -    pLastTD = pHeadTD;
 -    for (ii = 0; ii < uMACfragNum; ii++) {
 -        // Poll Transmit the adapter
 -        wmb();
 -        pHeadTD->m_td0TD0.f1Owner=OWNED_BY_NIC;
 -        wmb();
 -        if (ii == uMACfragNum - 1)
 -            pLastTD = pHeadTD;
 -        pHeadTD = pHeadTD->next;
 -    }
 -
 -    // Save the information needed by the tx interrupt handler
 -    // to complete the Send request
 -    pLastTD->pTDInfo->skb = skb;
 -    pLastTD->pTDInfo->byFlags = 0;
 -    pLastTD->pTDInfo->byFlags |= TD_FLAGS_NETIF_SKB;
 +                      if (pDevice->bEnableHostWEP) {
 +                              if ((uNodeIndex != 0) &&
 +                                  (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) {
 +                                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Find PTK [%lX]\n", pTransmitKey->dwKeyIndex);
 +                                      bNeedEncryption = true;
 +                              }
 +                      }
 +              } else {
 +                      if (pTransmitKey == NULL) {
 +                              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return no tx key\n");
 +                              dev_kfree_skb_irq(skb);
 +                              spin_unlock_irq(&pDevice->lock);
 +                              return 0;
 +                      }
 +              }
 +      }
 +
 +      vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption,
 +                          cbFrameBodySize, TYPE_AC0DMA, pHeadTD,
 +                          &pDevice->sTxEthHeader, (unsigned char *)skb->data, pTransmitKey, uNodeIndex,
 +                          &uMACfragNum,
 +                          &cbHeaderSize
 +              );
 +
 +      if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
 +              // Disable PS
 +              MACbPSWakeup(pDevice->PortOffset);
 +      }
 +      pDevice->bPWBitOn = false;
 +
 +      pLastTD = pHeadTD;
 +      for (ii = 0; ii < uMACfragNum; ii++) {
 +              // Poll Transmit the adapter
 +              wmb();
 +              pHeadTD->m_td0TD0.f1Owner = OWNED_BY_NIC;
 +              wmb();
 +              if (ii == uMACfragNum - 1)
 +                      pLastTD = pHeadTD;
 +              pHeadTD = pHeadTD->next;
 +      }
 +
 +      // Save the information needed by the tx interrupt handler
 +      // to complete the Send request
 +      pLastTD->pTDInfo->skb = skb;
 +      pLastTD->pTDInfo->byFlags = 0;
 +      pLastTD->pTDInfo->byFlags |= TD_FLAGS_NETIF_SKB;
  #ifdef TxInSleep
 -  pDevice->nTxDataTimeCout=0; //2008-8-21 chester <add> for send null packet
 -  #endif
 -    if (AVAIL_TD(pDevice, TYPE_AC0DMA) <= 1) {
 -        netif_stop_queue(dev);
 -    }
 +      pDevice->nTxDataTimeCout = 0; //2008-8-21 chester <add> for send null packet
 +#endif
 +      if (AVAIL_TD(pDevice, TYPE_AC0DMA) <= 1) {
 +              netif_stop_queue(dev);
 +      }
  
 -    pDevice->apCurrTD[TYPE_AC0DMA] = pHeadTD;
 +      pDevice->apCurrTD[TYPE_AC0DMA] = pHeadTD;
  //#ifdef      PLICE_DEBUG
 -      if (pDevice->bFixRate)
 -      {
 -              printk("FixRate:Rate is %d,TxPower is %d\n",pDevice->wCurrentRate,pDevice->byCurPwr);
 -      }
 -      else
 -      {
 -              //printk("Auto Rate:Rate is %d,TxPower is %d\n",pDevice->wCurrentRate,pDevice->byCurPwr);
 +      if (pDevice->bFixRate) {
 +              printk("FixRate:Rate is %d,TxPower is %d\n", pDevice->wCurrentRate, pDevice->byCurPwr);
 +      } else {
        }
  //#endif
  
 -{
 -    unsigned char Protocol_Version;    //802.1x Authentication
 -    unsigned char Packet_Type;           //802.1x Authentication
 -    unsigned char Descriptor_type;
 -    unsigned short Key_info;
 -bool bTxeapol_key = false;
 -    Protocol_Version = skb->data[ETH_HLEN];
 -    Packet_Type = skb->data[ETH_HLEN+1];
 -    Descriptor_type = skb->data[ETH_HLEN+1+1+2];
 -    Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]);
 -   if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) {
 -           if(((Protocol_Version==1) ||(Protocol_Version==2)) &&
 -              (Packet_Type==3)) {  //802.1x OR eapol-key challenge frame transfer
 -                        bTxeapol_key = true;
 -              if((Descriptor_type==254)||(Descriptor_type==2)) {       //WPA or RSN
 -                       if(!(Key_info & BIT3) &&   //group-key challenge
 -                         (Key_info & BIT8) && (Key_info & BIT9)) {    //send 2/2 key
 -                        pDevice->fWPA_Authened = true;
 -                        if(Descriptor_type==254)
 -                            printk("WPA ");
 -                        else
 -                            printk("WPA2 ");
 -                        printk("Authentication completed!!\n");
 -                        }
 -               }
 -             }
 -   }
 -}
 +      {
 +              unsigned char Protocol_Version;    //802.1x Authentication
 +              unsigned char Packet_Type;           //802.1x Authentication
 +              unsigned char Descriptor_type;
 +              unsigned short Key_info;
 +              bool bTxeapol_key = false;
 +              Protocol_Version = skb->data[ETH_HLEN];
 +              Packet_Type = skb->data[ETH_HLEN+1];
 +              Descriptor_type = skb->data[ETH_HLEN+1+1+2];
 +              Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]);
 +              if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) {
 +                      if (((Protocol_Version == 1) || (Protocol_Version == 2)) &&
 +                          (Packet_Type == 3)) {  //802.1x OR eapol-key challenge frame transfer
 +                              bTxeapol_key = true;
 +                              if ((Descriptor_type == 254) || (Descriptor_type == 2)) {       //WPA or RSN
 +                                      if (!(Key_info & BIT3) &&   //group-key challenge
 +                                          (Key_info & BIT8) && (Key_info & BIT9)) {    //send 2/2 key
 +                                              pDevice->fWPA_Authened = true;
 +                                              if (Descriptor_type == 254)
 +                                                      printk("WPA ");
 +                                              else
 +                                                      printk("WPA2 ");
 +                                              printk("Authentication completed!!\n");
 +                                      }
 +                              }
 +                      }
 +              }
 +      }
  
 -    MACvTransmitAC0(pDevice->PortOffset);
 +      MACvTransmitAC0(pDevice->PortOffset);
  //    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "acdma0:pDevice->apCurrTD= %p\n", pHeadTD);
  
 -    dev->trans_start = jiffies;
 -
 -    spin_unlock_irq(&pDevice->lock);
 -    return 0;
 +      dev->trans_start = jiffies;
  
 +      spin_unlock_irq(&pDevice->lock);
 +      return 0;
  }
  
  static  irqreturn_t  device_intr(int irq,  void *dev_instance) {
 -    struct net_device* dev=dev_instance;
 -    PSDevice     pDevice=(PSDevice) netdev_priv(dev);
 -
 -    int             max_count=0;
 -    unsigned long dwMIBCounter=0;
 -    PSMgmtObject    pMgmt = pDevice->pMgmt;
 -    unsigned char byOrgPageSel=0;
 -    int             handled = 0;
 -    unsigned char byData = 0;
 -    int             ii= 0;
 +      struct net_device *dev = dev_instance;
 +      PSDevice     pDevice = (PSDevice)netdev_priv(dev);
 +
 +      int             max_count = 0;
 +      unsigned long dwMIBCounter = 0;
 +      PSMgmtObject    pMgmt = pDevice->pMgmt;
 +      unsigned char byOrgPageSel = 0;
 +      int             handled = 0;
 +      unsigned char byData = 0;
 +      int             ii = 0;
  //    unsigned char byRSSI;
  
 +      MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr);
  
 -    MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr);
 -
 -    if (pDevice->dwIsr == 0)
 -        return IRQ_RETVAL(handled);
 -
 -    if (pDevice->dwIsr == 0xffffffff) {
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dwIsr = 0xffff\n");
 -        return IRQ_RETVAL(handled);
 -    }
 -    /*
 -      // 2008-05-21 <mark> by Richardtai, we can't read RSSI here, because no packet bound with RSSI
 -
 -      if ((pDevice->dwIsr & ISR_RXDMA0) &&
 -        (pDevice->byLocalID != REV_ID_VT3253_B0) &&
 -        (pDevice->bBSSIDFilter == true)) {
 -        // update RSSI
 -        //BBbReadEmbedded(pDevice->PortOffset, 0x3E, &byRSSI);
 -        //pDevice->uCurrRSSI = byRSSI;
 -    }
 -    */
 -
 -    handled = 1;
 -    MACvIntDisable(pDevice->PortOffset);
 -    spin_lock_irq(&pDevice->lock);
 -
 -    //Make sure current page is 0
 -    VNSvInPortB(pDevice->PortOffset + MAC_REG_PAGE1SEL, &byOrgPageSel);
 -    if (byOrgPageSel == 1) {
 -        MACvSelectPage0(pDevice->PortOffset);
 -    }
 -    else
 -        byOrgPageSel = 0;
 -
 -    MACvReadMIBCounter(pDevice->PortOffset, &dwMIBCounter);
 -    // TBD....
 -    // Must do this after doing rx/tx, cause ISR bit is slow
 -    // than RD/TD write back
 -    // update ISR counter
 -    STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic , dwMIBCounter);
 -    while (pDevice->dwIsr != 0) {
 -
 -        STAvUpdateIsrStatCounter(&pDevice->scStatistic, pDevice->dwIsr);
 -        MACvWriteISR(pDevice->PortOffset, pDevice->dwIsr);
 -
 -        if (pDevice->dwIsr & ISR_FETALERR){
 -            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " ISR_FETALERR \n");
 -            VNSvOutPortB(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, 0);
 -            VNSvOutPortW(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPECTI);
 -            device_error(pDevice, pDevice->dwIsr);
 -        }
 -
 -        if (pDevice->byLocalID > REV_ID_VT3253_B1) {
 -
 -            if (pDevice->dwIsr & ISR_MEASURESTART) {
 -                // 802.11h measure start
 -                pDevice->byOrgChannel = pDevice->byCurrentCh;
 -                VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byOrgRCR));
 -                VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, (RCR_RXALLTYPE | RCR_UNICAST | RCR_BROADCAST | RCR_MULTICAST | RCR_WPAERR));
 -                MACvSelectPage1(pDevice->PortOffset);
 -                VNSvInPortD(pDevice->PortOffset + MAC_REG_MAR0, &(pDevice->dwOrgMAR0));
 -                VNSvInPortD(pDevice->PortOffset + MAC_REG_MAR4, &(pDevice->dwOrgMAR4));
 -                MACvSelectPage0(pDevice->PortOffset);
 -               //xxxx
 -               // WCMDbFlushCommandQueue(pDevice->pMgmt, true);
 -                if (set_channel(pDevice, pDevice->pCurrMeasureEID->sReq.byChannel) == true) {
 -                    pDevice->bMeasureInProgress = true;
 -                    MACvSelectPage1(pDevice->PortOffset);
 -                    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_READY);
 -                    MACvSelectPage0(pDevice->PortOffset);
 -                    pDevice->byBasicMap = 0;
 -                    pDevice->byCCAFraction = 0;
 -                    for(ii=0;ii<8;ii++) {
 -                        pDevice->dwRPIs[ii] = 0;
 -                    }
 -                } else {
 -                    // can not measure because set channel fail
 -                   // WCMDbResetCommandQueue(pDevice->pMgmt);
 -                    // clear measure control
 -                    MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN);
 -                    s_vCompleteCurrentMeasure(pDevice, MEASURE_MODE_INCAPABLE);
 -                    MACvSelectPage1(pDevice->PortOffset);
 -                    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
 -                    MACvSelectPage0(pDevice->PortOffset);
 -                }
 -            }
 -            if (pDevice->dwIsr & ISR_MEASUREEND) {
 -                // 802.11h measure end
 -                pDevice->bMeasureInProgress = false;
 -                VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byOrgRCR);
 -                MACvSelectPage1(pDevice->PortOffset);
 -                VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, pDevice->dwOrgMAR0);
 -                VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR4, pDevice->dwOrgMAR4);
 -                VNSvInPortB(pDevice->PortOffset + MAC_REG_MSRBBSTS, &byData);
 -                pDevice->byBasicMap |= (byData >> 4);
 -                VNSvInPortB(pDevice->PortOffset + MAC_REG_CCAFRACTION, &pDevice->byCCAFraction);
 -                VNSvInPortB(pDevice->PortOffset + MAC_REG_MSRCTL, &byData);
 -                // clear measure control
 -                MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN);
 -                MACvSelectPage0(pDevice->PortOffset);
 -                set_channel(pDevice, pDevice->byOrgChannel);
 -                // WCMDbResetCommandQueue(pDevice->pMgmt);
 -                MACvSelectPage1(pDevice->PortOffset);
 -                MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
 -                MACvSelectPage0(pDevice->PortOffset);
 -                if (byData & MSRCTL_FINISH) {
 -                    // measure success
 -                    s_vCompleteCurrentMeasure(pDevice, 0);
 -                } else {
 -                    // can not measure because not ready before end of measure time
 -                    s_vCompleteCurrentMeasure(pDevice, MEASURE_MODE_LATE);
 -                }
 -            }
 -            if (pDevice->dwIsr & ISR_QUIETSTART) {
 -                do {
 -                    ;
 -                } while (CARDbStartQuiet(pDevice) == false);
 -            }
 -        }
 -
 -        if (pDevice->dwIsr & ISR_TBTT) {
 -            if (pDevice->bEnableFirstQuiet == true) {
 -                pDevice->byQuietStartCount--;
 -                if (pDevice->byQuietStartCount == 0) {
 -                    pDevice->bEnableFirstQuiet = false;
 -                    MACvSelectPage1(pDevice->PortOffset);
 -                    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN));
 -                    MACvSelectPage0(pDevice->PortOffset);
 -                }
 -            }
 -            if ((pDevice->bChannelSwitch == true) &&
 -                (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE)) {
 -                pDevice->byChannelSwitchCount--;
 -                if (pDevice->byChannelSwitchCount == 0) {
 -                    pDevice->bChannelSwitch = false;
 -                    set_channel(pDevice, pDevice->byNewChannel);
 -                    VNTWIFIbChannelSwitch(pDevice->pMgmt, pDevice->byNewChannel);
 -                    MACvSelectPage1(pDevice->PortOffset);
 -                    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
 -                    MACvSelectPage0(pDevice->PortOffset);
 -                    CARDbStartTxPacket(pDevice, PKT_TYPE_802_11_ALL);
 -
 -                }
 -            }
 -            if (pDevice->eOPMode == OP_MODE_ADHOC) {
 -                //pDevice->bBeaconSent = false;
 -            } else {
 -                if ((pDevice->bUpdateBBVGA) && (pDevice->bLinkPass == true) && (pDevice->uCurrRSSI != 0)) {
 -                    long            ldBm;
 -
 -                    RFvRSSITodBm(pDevice, (unsigned char) pDevice->uCurrRSSI, &ldBm);
 -                    for (ii=0;ii<BB_VGA_LEVEL;ii++) {
 -                        if (ldBm < pDevice->ldBmThreshold[ii]) {
 -                            pDevice->byBBVGANew = pDevice->abyBBVGA[ii];
 -                            break;
 -                        }
 -                    }
 -                    if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) {
 -                        pDevice->uBBVGADiffCount++;
 -                        if (pDevice->uBBVGADiffCount == 1) {
 -                            // first VGA diff gain
 -                            BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew);
 -                            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
 -                                            (int)ldBm, pDevice->byBBVGANew, pDevice->byBBVGACurrent, (int)pDevice->uBBVGADiffCount);
 -                        }
 -                        if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) {
 -                            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
 -                                            (int)ldBm, pDevice->byBBVGANew, pDevice->byBBVGACurrent, (int)pDevice->uBBVGADiffCount);
 -                            BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew);
 -                        }
 -                    } else {
 -                        pDevice->uBBVGADiffCount = 1;
 -                    }
 -                }
 -            }
 -
 -            pDevice->bBeaconSent = false;
 -            if (pDevice->bEnablePSMode) {
 -                PSbIsNextTBTTWakeUp((void *)pDevice);
 -            }
 -
 -            if ((pDevice->eOPMode == OP_MODE_AP) ||
 -                (pDevice->eOPMode == OP_MODE_ADHOC)) {
 -
 -                MACvOneShotTimer1MicroSec(pDevice->PortOffset,
 -                        (pMgmt->wIBSSBeaconPeriod - MAKE_BEACON_RESERVED) << 10);
 -            }
 -
 -            if (pDevice->eOPMode == OP_MODE_ADHOC && pDevice->pMgmt->wCurrATIMWindow > 0) {
 -                // todo adhoc PS mode
 -            }
 -
 -        }
 -
 -        if (pDevice->dwIsr & ISR_BNTX) {
 -
 -            if (pDevice->eOPMode == OP_MODE_ADHOC) {
 -                pDevice->bIsBeaconBufReadySet = false;
 -                pDevice->cbBeaconBufReadySetCnt = 0;
 -            }
 -
 -            if (pDevice->eOPMode == OP_MODE_AP) {
 -                if(pMgmt->byDTIMCount > 0) {
 -                   pMgmt->byDTIMCount --;
 -                   pMgmt->sNodeDBTable[0].bRxPSPoll = false;
 -                }
 -                else {
 -                    if(pMgmt->byDTIMCount == 0) {
 -                        // check if mutltcast tx bufferring
 -                        pMgmt->byDTIMCount = pMgmt->byDTIMPeriod - 1;
 -                        pMgmt->sNodeDBTable[0].bRxPSPoll = true;
 -                        bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL);
 -                    }
 -                }
 -            }
 -            pDevice->bBeaconSent = true;
 -
 -            if (pDevice->bChannelSwitch == true) {
 -                pDevice->byChannelSwitchCount--;
 -                if (pDevice->byChannelSwitchCount == 0) {
 -                    pDevice->bChannelSwitch = false;
 -                    set_channel(pDevice, pDevice->byNewChannel);
 -                    VNTWIFIbChannelSwitch(pDevice->pMgmt, pDevice->byNewChannel);
 -                    MACvSelectPage1(pDevice->PortOffset);
 -                    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
 -                    MACvSelectPage0(pDevice->PortOffset);
 -                    //VNTWIFIbSendBeacon(pDevice->pMgmt);
 -                    CARDbStartTxPacket(pDevice, PKT_TYPE_802_11_ALL);
 -                }
 -            }
 -
 -        }
 -
 -        if (pDevice->dwIsr & ISR_RXDMA0) {
 -            max_count += device_rx_srv(pDevice, TYPE_RXDMA0);
 -        }
 -        if (pDevice->dwIsr & ISR_RXDMA1) {
 -            max_count += device_rx_srv(pDevice, TYPE_RXDMA1);
 -        }
 -        if (pDevice->dwIsr & ISR_TXDMA0){
 -            max_count += device_tx_srv(pDevice, TYPE_TXDMA0);
 -        }
 -        if (pDevice->dwIsr & ISR_AC0DMA){
 -            max_count += device_tx_srv(pDevice, TYPE_AC0DMA);
 -        }
 -        if (pDevice->dwIsr & ISR_SOFTTIMER) {
 -
 -        }
 -        if (pDevice->dwIsr & ISR_SOFTTIMER1) {
 -            if (pDevice->eOPMode == OP_MODE_AP) {
 -               if (pDevice->bShortSlotTime)
 -                   pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1);
 -               else
 -                   pMgmt->wCurrCapInfo &= ~(WLAN_SET_CAP_INFO_SHORTSLOTTIME(1));
 -            }
 -            bMgrPrepareBeaconToSend(pDevice, pMgmt);
 -            pDevice->byCntMeasure = 0;
 -        }
 -
 -        MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr);
 -
 -        MACvReceive0(pDevice->PortOffset);
 -        MACvReceive1(pDevice->PortOffset);
 -
 -        if (max_count>pDevice->sOpts.int_works)
 -            break;
 -    }
 -
 -    if (byOrgPageSel == 1) {
 -        MACvSelectPage1(pDevice->PortOffset);
 -    }
 -
 -    spin_unlock_irq(&pDevice->lock);
 -    MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
 -
 -    return IRQ_RETVAL(handled);
 -}
 +      if (pDevice->dwIsr == 0)
 +              return IRQ_RETVAL(handled);
  
 +      if (pDevice->dwIsr == 0xffffffff) {
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dwIsr = 0xffff\n");
 +              return IRQ_RETVAL(handled);
 +      }
 +      /*
 +      // 2008-05-21 <mark> by Richardtai, we can't read RSSI here, because no packet bound with RSSI
 +
 +      if ((pDevice->dwIsr & ISR_RXDMA0) &&
 +      (pDevice->byLocalID != REV_ID_VT3253_B0) &&
 +      (pDevice->bBSSIDFilter == true)) {
 +      // update RSSI
 +      //BBbReadEmbedded(pDevice->PortOffset, 0x3E, &byRSSI);
 +      //pDevice->uCurrRSSI = byRSSI;
 +      }
 +      */
 +
 +      handled = 1;
 +      MACvIntDisable(pDevice->PortOffset);
 +      spin_lock_irq(&pDevice->lock);
 +
 +      //Make sure current page is 0
 +      VNSvInPortB(pDevice->PortOffset + MAC_REG_PAGE1SEL, &byOrgPageSel);
 +      if (byOrgPageSel == 1) {
 +              MACvSelectPage0(pDevice->PortOffset);
 +      } else
 +              byOrgPageSel = 0;
 +
 +      MACvReadMIBCounter(pDevice->PortOffset, &dwMIBCounter);
 +      // TBD....
 +      // Must do this after doing rx/tx, cause ISR bit is slow
 +      // than RD/TD write back
 +      // update ISR counter
 +      STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic , dwMIBCounter);
 +      while (pDevice->dwIsr != 0) {
 +              STAvUpdateIsrStatCounter(&pDevice->scStatistic, pDevice->dwIsr);
 +              MACvWriteISR(pDevice->PortOffset, pDevice->dwIsr);
 +
 +              if (pDevice->dwIsr & ISR_FETALERR) {
 +                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " ISR_FETALERR \n");
 +                      VNSvOutPortB(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, 0);
 +                      VNSvOutPortW(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPECTI);
 +                      device_error(pDevice, pDevice->dwIsr);
 +              }
 +
 +              if (pDevice->byLocalID > REV_ID_VT3253_B1) {
 +                      if (pDevice->dwIsr & ISR_MEASURESTART) {
 +                              // 802.11h measure start
 +                              pDevice->byOrgChannel = pDevice->byCurrentCh;
 +                              VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byOrgRCR));
 +                              VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, (RCR_RXALLTYPE | RCR_UNICAST | RCR_BROADCAST | RCR_MULTICAST | RCR_WPAERR));
 +                              MACvSelectPage1(pDevice->PortOffset);
 +                              VNSvInPortD(pDevice->PortOffset + MAC_REG_MAR0, &(pDevice->dwOrgMAR0));
 +                              VNSvInPortD(pDevice->PortOffset + MAC_REG_MAR4, &(pDevice->dwOrgMAR4));
 +                              MACvSelectPage0(pDevice->PortOffset);
 +                              //xxxx
 +                              // WCMDbFlushCommandQueue(pDevice->pMgmt, true);
 +                              if (set_channel(pDevice, pDevice->pCurrMeasureEID->sReq.byChannel) == true) {
 +                                      pDevice->bMeasureInProgress = true;
 +                                      MACvSelectPage1(pDevice->PortOffset);
 +                                      MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_READY);
 +                                      MACvSelectPage0(pDevice->PortOffset);
 +                                      pDevice->byBasicMap = 0;
 +                                      pDevice->byCCAFraction = 0;
 +                                      for (ii = 0; ii < 8; ii++) {
 +                                              pDevice->dwRPIs[ii] = 0;
 +                                      }
 +                              } else {
 +                                      // can not measure because set channel fail
 +                                      // WCMDbResetCommandQueue(pDevice->pMgmt);
 +                                      // clear measure control
 +                                      MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN);
 +                                      s_vCompleteCurrentMeasure(pDevice, MEASURE_MODE_INCAPABLE);
 +                                      MACvSelectPage1(pDevice->PortOffset);
 +                                      MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
 +                                      MACvSelectPage0(pDevice->PortOffset);
 +                              }
 +                      }
 +                      if (pDevice->dwIsr & ISR_MEASUREEND) {
 +                              // 802.11h measure end
 +                              pDevice->bMeasureInProgress = false;
 +                              VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byOrgRCR);
 +                              MACvSelectPage1(pDevice->PortOffset);
 +                              VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, pDevice->dwOrgMAR0);
 +                              VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR4, pDevice->dwOrgMAR4);
 +                              VNSvInPortB(pDevice->PortOffset + MAC_REG_MSRBBSTS, &byData);
 +                              pDevice->byBasicMap |= (byData >> 4);
 +                              VNSvInPortB(pDevice->PortOffset + MAC_REG_CCAFRACTION, &pDevice->byCCAFraction);
 +                              VNSvInPortB(pDevice->PortOffset + MAC_REG_MSRCTL, &byData);
 +                              // clear measure control
 +                              MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN);
 +                              MACvSelectPage0(pDevice->PortOffset);
 +                              set_channel(pDevice, pDevice->byOrgChannel);
 +                              // WCMDbResetCommandQueue(pDevice->pMgmt);
 +                              MACvSelectPage1(pDevice->PortOffset);
 +                              MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
 +                              MACvSelectPage0(pDevice->PortOffset);
 +                              if (byData & MSRCTL_FINISH) {
 +                                      // measure success
 +                                      s_vCompleteCurrentMeasure(pDevice, 0);
 +                              } else {
 +                                      // can not measure because not ready before end of measure time
 +                                      s_vCompleteCurrentMeasure(pDevice, MEASURE_MODE_LATE);
 +                              }
 +                      }
 +                      if (pDevice->dwIsr & ISR_QUIETSTART) {
 +                              do {
 +                                      ;
 +                              } while (CARDbStartQuiet(pDevice) == false);
 +                      }
 +              }
 +
 +              if (pDevice->dwIsr & ISR_TBTT) {
 +                      if (pDevice->bEnableFirstQuiet == true) {
 +                              pDevice->byQuietStartCount--;
 +                              if (pDevice->byQuietStartCount == 0) {
 +                                      pDevice->bEnableFirstQuiet = false;
 +                                      MACvSelectPage1(pDevice->PortOffset);
 +                                      MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN));
 +                                      MACvSelectPage0(pDevice->PortOffset);
 +                              }
 +                      }
 +                      if ((pDevice->bChannelSwitch == true) &&
 +                          (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE)) {
 +                              pDevice->byChannelSwitchCount--;
 +                              if (pDevice->byChannelSwitchCount == 0) {
 +                                      pDevice->bChannelSwitch = false;
 +                                      set_channel(pDevice, pDevice->byNewChannel);
 +                                      VNTWIFIbChannelSwitch(pDevice->pMgmt, pDevice->byNewChannel);
 +                                      MACvSelectPage1(pDevice->PortOffset);
 +                                      MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
 +                                      MACvSelectPage0(pDevice->PortOffset);
 +                                      CARDbStartTxPacket(pDevice, PKT_TYPE_802_11_ALL);
 +
 +                              }
 +                      }
 +                      if (pDevice->eOPMode == OP_MODE_ADHOC) {
 +                              //pDevice->bBeaconSent = false;
 +                      } else {
 +                              if ((pDevice->bUpdateBBVGA) && (pDevice->bLinkPass == true) && (pDevice->uCurrRSSI != 0)) {
 +                                      long            ldBm;
 +
 +                                      RFvRSSITodBm(pDevice, (unsigned char) pDevice->uCurrRSSI, &ldBm);
 +                                      for (ii = 0; ii < BB_VGA_LEVEL; ii++) {
 +                                              if (ldBm < pDevice->ldBmThreshold[ii]) {
 +                                                      pDevice->byBBVGANew = pDevice->abyBBVGA[ii];
 +                                                      break;
 +                                              }
 +                                      }
 +                                      if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) {
 +                                              pDevice->uBBVGADiffCount++;
 +                                              if (pDevice->uBBVGADiffCount == 1) {
 +                                                      // first VGA diff gain
 +                                                      BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew);
 +                                                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
 +                                                              (int)ldBm, pDevice->byBBVGANew, pDevice->byBBVGACurrent, (int)pDevice->uBBVGADiffCount);
 +                                              }
 +                                              if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) {
 +                                                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
 +                                                              (int)ldBm, pDevice->byBBVGANew, pDevice->byBBVGACurrent, (int)pDevice->uBBVGADiffCount);
 +                                                      BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew);
 +                                              }
 +                                      } else {
 +                                              pDevice->uBBVGADiffCount = 1;
 +                                      }
 +                              }
 +                      }
 +
 +                      pDevice->bBeaconSent = false;
 +                      if (pDevice->bEnablePSMode) {
 +                              PSbIsNextTBTTWakeUp((void *)pDevice);
 +                      }
 +
 +                      if ((pDevice->eOPMode == OP_MODE_AP) ||
 +                          (pDevice->eOPMode == OP_MODE_ADHOC)) {
 +                              MACvOneShotTimer1MicroSec(pDevice->PortOffset,
 +                                                        (pMgmt->wIBSSBeaconPeriod - MAKE_BEACON_RESERVED) << 10);
 +                      }
 +
 +                      if (pDevice->eOPMode == OP_MODE_ADHOC && pDevice->pMgmt->wCurrATIMWindow > 0) {
 +                              // todo adhoc PS mode
 +                      }
 +
 +              }
 +
 +              if (pDevice->dwIsr & ISR_BNTX) {
 +                      if (pDevice->eOPMode == OP_MODE_ADHOC) {
 +                              pDevice->bIsBeaconBufReadySet = false;
 +                              pDevice->cbBeaconBufReadySetCnt = 0;
 +                      }
 +
 +                      if (pDevice->eOPMode == OP_MODE_AP) {
 +                              if (pMgmt->byDTIMCount > 0) {
 +                                      pMgmt->byDTIMCount--;
 +                                      pMgmt->sNodeDBTable[0].bRxPSPoll = false;
 +                              } else {
 +                                      if (pMgmt->byDTIMCount == 0) {
 +                                              // check if mutltcast tx bufferring
 +                                              pMgmt->byDTIMCount = pMgmt->byDTIMPeriod - 1;
 +                                              pMgmt->sNodeDBTable[0].bRxPSPoll = true;
 +                                              bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL);
 +                                      }
 +                              }
 +                      }
 +                      pDevice->bBeaconSent = true;
 +
 +                      if (pDevice->bChannelSwitch == true) {
 +                              pDevice->byChannelSwitchCount--;
 +                              if (pDevice->byChannelSwitchCount == 0) {
 +                                      pDevice->bChannelSwitch = false;
 +                                      set_channel(pDevice, pDevice->byNewChannel);
 +                                      VNTWIFIbChannelSwitch(pDevice->pMgmt, pDevice->byNewChannel);
 +                                      MACvSelectPage1(pDevice->PortOffset);
 +                                      MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
 +                                      MACvSelectPage0(pDevice->PortOffset);
 +                                      //VNTWIFIbSendBeacon(pDevice->pMgmt);
 +                                      CARDbStartTxPacket(pDevice, PKT_TYPE_802_11_ALL);
 +                              }
 +                      }
 +
 +              }
 +
 +              if (pDevice->dwIsr & ISR_RXDMA0) {
 +                      max_count += device_rx_srv(pDevice, TYPE_RXDMA0);
 +              }
 +              if (pDevice->dwIsr & ISR_RXDMA1) {
 +                      max_count += device_rx_srv(pDevice, TYPE_RXDMA1);
 +              }
 +              if (pDevice->dwIsr & ISR_TXDMA0) {
 +                      max_count += device_tx_srv(pDevice, TYPE_TXDMA0);
 +              }
 +              if (pDevice->dwIsr & ISR_AC0DMA) {
 +                      max_count += device_tx_srv(pDevice, TYPE_AC0DMA);
 +              }
 +              if (pDevice->dwIsr & ISR_SOFTTIMER) {
 +              }
 +              if (pDevice->dwIsr & ISR_SOFTTIMER1) {
 +                      if (pDevice->eOPMode == OP_MODE_AP) {
 +                              if (pDevice->bShortSlotTime)
 +                                      pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1);
 +                              else
 +                                      pMgmt->wCurrCapInfo &= ~(WLAN_SET_CAP_INFO_SHORTSLOTTIME(1));
 +                      }
 +                      bMgrPrepareBeaconToSend(pDevice, pMgmt);
 +                      pDevice->byCntMeasure = 0;
 +              }
 +
 +              MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr);
 +
 +              MACvReceive0(pDevice->PortOffset);
 +              MACvReceive1(pDevice->PortOffset);
 +
 +              if (max_count > pDevice->sOpts.int_works)
 +                      break;
 +      }
 +
 +      if (byOrgPageSel == 1) {
 +              MACvSelectPage1(pDevice->PortOffset);
 +      }
 +
 +      spin_unlock_irq(&pDevice->lock);
 +      MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
 +
 +      return IRQ_RETVAL(handled);
 +}
  
  static unsigned const ethernet_polynomial = 0x04c11db7U;
  static inline u32 ether_crc(int length, unsigned char *data)
  {
 -    int crc = -1;
 -
 -    while(--length >= 0) {
 -        unsigned char current_octet = *data++;
 -        int bit;
 -        for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
 -            crc = (crc << 1) ^
 -                ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
 -        }
 -    }
 -    return crc;
 +      int crc = -1;
 +
 +      while (--length >= 0) {
 +              unsigned char current_octet = *data++;
 +              int bit;
 +              for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
 +                      crc = (crc << 1) ^
 +                              ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
 +              }
 +      }
 +      return crc;
  }
  
  //2008-8-4 <add> by chester
  static int Config_FileGetParameter(unsigned char *string,
 -              unsigned char *dest, unsigned char *source)
 +                                 unsigned char *dest, unsigned char *source)
  {
 -  unsigned char buf1[100];
 -  int source_len = strlen(source);
 +      unsigned char buf1[100];
 +      int source_len = strlen(source);
  
 -    memset(buf1,0,100);
 -    strcat(buf1, string);
 -    strcat(buf1, "=");
 -    source+=strlen(buf1);
 +      memset(buf1, 0, 100);
 +      strcat(buf1, string);
 +      strcat(buf1, "=");
 +      source += strlen(buf1);
  
 -   memcpy(dest,source,source_len-strlen(buf1));
 - return true;
 +      memcpy(dest, source, source_len - strlen(buf1));
 +      return true;
  }
  
- int Config_FileOperation(PSDevice pDevice, bool fwrite, unsigned char *Parameter) {
-       unsigned char *config_path = CONFIG_PATH;
-       unsigned char *buffer = NULL;
+ int Config_FileOperation(PSDevice pDevice,bool fwrite,unsigned char *Parameter)
+ {
+       unsigned char *buffer = kmalloc(1024, GFP_KERNEL);
        unsigned char tmpbuffer[20];
-       struct file   *filp = NULL;
-       mm_segment_t old_fs = get_fs();
-       //int oldfsuid=0,oldfsgid=0;
-       int result = 0;
-       set_fs(KERNEL_DS);
-       /* Can't do this anymore, so we rely on correct filesystem permissions:
-       //Make sure a caller can read or write power as root
-       oldfsuid=current->cred->fsuid;
-       oldfsgid=current->cred->fsgid;
-       current->cred->fsuid = 0;
-       current->cred->fsgid = 0;
-       */
-       //open file
-       filp = filp_open(config_path, O_RDWR, 0);
-       if (IS_ERR(filp)) {
-               printk("Config_FileOperation:open file fail?\n");
-               result = -1;
-               goto error2;
-       }
+       struct file *file;
+       int result=0;
  
-       if (!(filp->f_op) || !(filp->f_op->read) || !(filp->f_op->write)) {
-               printk("file %s cann't readable or writable?\n", config_path);
-               result = -1;
-               goto error1;
-       }
-       buffer = kmalloc(1024, GFP_KERNEL);
-       if (buffer == NULL) {
+       if (!buffer) {
                printk("allocate mem for file fail?\n");
-               result = -1;
-               goto error1;
+               return -1;
+       }
+       file = filp_open(CONFIG_PATH, O_RDONLY, 0);
+       if (IS_ERR(file)) {
+               kfree(buffer);
+               printk("Config_FileOperation:open file fail?\n");
+               return -1;
        }
  
-       if (filp->f_op->read(filp, buffer, 1024, &filp->f_pos) < 0) {
+       if (kernel_read(file, 0, buffer, 1024) < 0) {
                printk("read file error?\n");
                result = -1;
                goto error1;
        }
  
-       if (Config_FileGetParameter("ZONETYPE", tmpbuffer, buffer) != true) {
+       if (Config_FileGetParameter("ZONETYPE",tmpbuffer,buffer)!=true) {
                printk("get parameter error?\n");
                result = -1;
                goto error1;
        }
  
-       if (memcmp(tmpbuffer, "USA", 3) == 0) {
+       if (memcmp(tmpbuffer,"USA",3)==0) {
                result = ZoneType_USA;
-       } else if (memcmp(tmpbuffer, "JAPAN", 5) == 0) {
+       } else if(memcmp(tmpbuffer,"JAPAN",5)==0) {
                result = ZoneType_Japan;
-       } else if (memcmp(tmpbuffer, "EUROPE", 5) == 0) {
+       } else if(memcmp(tmpbuffer,"EUROPE",5)==0) {
                result = ZoneType_Europe;
        } else {
                result = -1;
-               printk("Unknown Zonetype[%s]?\n", tmpbuffer);
+               printk("Unknown Zonetype[%s]?\n",tmpbuffer);
        }
  
  error1:
        kfree(buffer);
-       if (filp_close(filp, NULL))
-               printk("Config_FileOperation:close file fail\n");
- error2:
-       set_fs(old_fs);
-       /*
-         current->cred->fsuid=oldfsuid;
-         current->cred->fsgid=oldfsgid;
-       */
+       fput(file);
        return result;
  }
  
 +static void device_set_multi(struct net_device *dev) {
 +      PSDevice         pDevice = (PSDevice)netdev_priv(dev);
 +
 +      PSMgmtObject     pMgmt = pDevice->pMgmt;
 +      u32              mc_filter[2];
 +      struct netdev_hw_addr *ha;
 +
 +      VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode));
 +
 +      if (dev->flags & IFF_PROMISC) {         /* Set promiscuous. */
 +              DBG_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
 +              /* Unconditionally log net taps. */
 +              pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST|RCR_UNICAST);
 +      } else if ((netdev_mc_count(dev) > pDevice->multicast_limit)
 +               ||  (dev->flags & IFF_ALLMULTI)) {
 +              MACvSelectPage1(pDevice->PortOffset);
 +              VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, 0xffffffff);
 +              VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0 + 4, 0xffffffff);
 +              MACvSelectPage0(pDevice->PortOffset);
 +              pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
 +      } else {
 +              memset(mc_filter, 0, sizeof(mc_filter));
 +              netdev_for_each_mc_addr(ha, dev) {
 +                      int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
 +                      mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31));
 +              }
 +              MACvSelectPage1(pDevice->PortOffset);
 +              VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, mc_filter[0]);
 +              VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0 + 4, mc_filter[1]);
 +              MACvSelectPage0(pDevice->PortOffset);
 +              pDevice->byRxMode &= ~(RCR_UNICAST);
 +              pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
 +      }
  
 +      if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
 +              // If AP mode, don't enable RCR_UNICAST. Since hw only compare addr1 with local mac.
 +              pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
 +              pDevice->byRxMode &= ~(RCR_UNICAST);
 +      }
  
 -static void device_set_multi(struct net_device *dev) {
 -    PSDevice         pDevice = (PSDevice) netdev_priv(dev);
 -
 -    PSMgmtObject     pMgmt = pDevice->pMgmt;
 -    u32              mc_filter[2];
 -    struct netdev_hw_addr *ha;
 -
 -
 -    VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode));
 -
 -    if (dev->flags & IFF_PROMISC) {         /* Set promiscuous. */
 -        DBG_PRT(MSG_LEVEL_ERR,KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
 -        /* Unconditionally log net taps. */
 -        pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST|RCR_UNICAST);
 -    }
 -    else if ((netdev_mc_count(dev) > pDevice->multicast_limit)
 -        ||  (dev->flags & IFF_ALLMULTI)) {
 -        MACvSelectPage1(pDevice->PortOffset);
 -        VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, 0xffffffff);
 -        VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0 + 4, 0xffffffff);
 -        MACvSelectPage0(pDevice->PortOffset);
 -        pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
 -    }
 -    else {
 -        memset(mc_filter, 0, sizeof(mc_filter));
 -      netdev_for_each_mc_addr(ha, dev) {
 -            int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
 -            mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31));
 -        }
 -        MACvSelectPage1(pDevice->PortOffset);
 -        VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, mc_filter[0]);
 -        VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0 + 4, mc_filter[1]);
 -        MACvSelectPage0(pDevice->PortOffset);
 -        pDevice->byRxMode &= ~(RCR_UNICAST);
 -        pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
 -    }
 -
 -    if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
 -        // If AP mode, don't enable RCR_UNICAST. Since hw only compare addr1 with local mac.
 -        pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
 -        pDevice->byRxMode &= ~(RCR_UNICAST);
 -    }
 -
 -    VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byRxMode);
 -    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRxMode = %x\n", pDevice->byRxMode );
 +      VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byRxMode);
 +      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRxMode = %x\n", pDevice->byRxMode);
  }
  
 -
  static struct net_device_stats *device_get_stats(struct net_device *dev) {
 -    PSDevice pDevice=(PSDevice) netdev_priv(dev);
 +      PSDevice pDevice = (PSDevice)netdev_priv(dev);
  
 -    return &pDevice->stats;
 +      return &pDevice->stats;
  }
  
 -
 -
  static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
        PSDevice                pDevice = (PSDevice)netdev_priv(dev);
  
 -      struct iwreq *wrq = (struct iwreq *) rq;
 -      int                 rc =0;
 -    PSMgmtObject        pMgmt = pDevice->pMgmt;
 -    PSCmdRequest        pReq;
 -
 -
 -    if (pMgmt == NULL) {
 -        rc = -EFAULT;
 -        return rc;
 -    }
 +      struct iwreq *wrq = (struct iwreq *)rq;
 +      int rc = 0;
 +      PSMgmtObject pMgmt = pDevice->pMgmt;
 +      PSCmdRequest pReq;
  
 -    switch(cmd) {
 +      if (pMgmt == NULL) {
 +              rc = -EFAULT;
 +              return rc;
 +      }
  
 +      switch (cmd) {
        case SIOCGIWNAME:
                rc = iwctl_giwname(dev, NULL, (char *)&(wrq->u.name), NULL);
                break;
  
                // Set frequency/channel
        case SIOCSIWFREQ:
 -          rc = iwctl_siwfreq(dev, NULL, &(wrq->u.freq), NULL);
 +              rc = iwctl_siwfreq(dev, NULL, &(wrq->u.freq), NULL);
                break;
  
                // Get frequency/channel
                // Set desired network name (ESSID)
        case SIOCSIWESSID:
  
 -              {
 -                      char essid[IW_ESSID_MAX_SIZE+1];
 -                      if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) {
 -                              rc = -E2BIG;
 -                              break;
 -                      }
 -                      if (copy_from_user(essid, wrq->u.essid.pointer,
 -                                         wrq->u.essid.length)) {
 -                              rc = -EFAULT;
 -                              break;
 -                      }
 -                      rc = iwctl_siwessid(dev, NULL,
 -                                          &(wrq->u.essid), essid);
 +      {
 +              char essid[IW_ESSID_MAX_SIZE+1];
 +              if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) {
 +                      rc = -E2BIG;
 +                      break;
                }
 -              break;
 -
 +              if (copy_from_user(essid, wrq->u.essid.pointer,
 +                                 wrq->u.essid.length)) {
 +                      rc = -EFAULT;
 +                      break;
 +              }
 +              rc = iwctl_siwessid(dev, NULL,
 +                                  &(wrq->u.essid), essid);
 +      }
 +      break;
  
 -              // Get current network name (ESSID)
 +      // Get current network name (ESSID)
        case SIOCGIWESSID:
  
 -              {
 -                      char essid[IW_ESSID_MAX_SIZE+1];
 -                      if (wrq->u.essid.pointer)
 -                              rc = iwctl_giwessid(dev, NULL,
 -                                                  &(wrq->u.essid), essid);
 -                              if (copy_to_user(wrq->u.essid.pointer,
 -                                                       essid,
 -                                                       wrq->u.essid.length) )
 -                                      rc = -EFAULT;
 -              }
 -              break;
 +      {
 +              char essid[IW_ESSID_MAX_SIZE+1];
 +              if (wrq->u.essid.pointer)
 +                      rc = iwctl_giwessid(dev, NULL,
 +                                          &(wrq->u.essid), essid);
 +              if (copy_to_user(wrq->u.essid.pointer,
 +                               essid,
 +                               wrq->u.essid.length))
 +                      rc = -EFAULT;
 +      }
 +      break;
  
        case SIOCSIWAP:
  
                rc = iwctl_siwap(dev, NULL, &(wrq->u.ap_addr), NULL);
                break;
  
 -
                // Get current Access Point (BSSID)
        case SIOCGIWAP:
                rc = iwctl_giwap(dev, NULL, &(wrq->u.ap_addr), NULL);
                break;
  
 -
                // Set desired station name
        case SIOCSIWNICKN:
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWNICKN \n");
 -        rc = -EOPNOTSUPP;
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWNICKN \n");
 +              rc = -EOPNOTSUPP;
                break;
  
                // Get current station name
        case SIOCGIWNICKN:
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWNICKN \n");
 -        rc = -EOPNOTSUPP;
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWNICKN \n");
 +              rc = -EOPNOTSUPP;
                break;
  
                // Set the desired bit-rate
                rc = iwctl_siwrate(dev, NULL, &(wrq->u.bitrate), NULL);
                break;
  
 -      // Get the current bit-rate
 +              // Get the current bit-rate
        case SIOCGIWRATE:
  
                rc = iwctl_giwrate(dev, NULL, &(wrq->u.bitrate), NULL);
                break;
  
 -      // Set the desired RTS threshold
 +              // Set the desired RTS threshold
        case SIOCSIWRTS:
  
                rc = iwctl_siwrts(dev, NULL, &(wrq->u.rts), NULL);
                break;
  
 -      // Get the current RTS threshold
 +              // Get the current RTS threshold
        case SIOCGIWRTS:
  
                rc = iwctl_giwrts(dev, NULL, &(wrq->u.rts), NULL);
        case SIOCSIWFRAG:
  
                rc = iwctl_siwfrag(dev, NULL, &(wrq->u.frag), NULL);
 -          break;
 +              break;
  
 -      // Get the current fragmentation threshold
 +              // Get the current fragmentation threshold
        case SIOCGIWFRAG:
  
                rc = iwctl_giwfrag(dev, NULL, &(wrq->u.frag), NULL);
  
                // Set mode of operation
        case SIOCSIWMODE:
 -      rc = iwctl_siwmode(dev, NULL, &(wrq->u.mode), NULL);
 +              rc = iwctl_siwmode(dev, NULL, &(wrq->u.mode), NULL);
                break;
  
                // Get mode of operation
                break;
  
                // Set WEP keys and mode
 -      case SIOCSIWENCODE:
 -              {
 -            char abyKey[WLAN_WEP232_KEYLEN];
 -
 -                      if (wrq->u.encoding.pointer) {
 +      case SIOCSIWENCODE: {
 +              char abyKey[WLAN_WEP232_KEYLEN];
  
 -
 -                              if (wrq->u.encoding.length > WLAN_WEP232_KEYLEN) {
 -                                      rc = -E2BIG;
 -                                      break;
 -                              }
 -                              memset(abyKey, 0, WLAN_WEP232_KEYLEN);
 -                              if (copy_from_user(abyKey,
 -                                                wrq->u.encoding.pointer,
 -                                                wrq->u.encoding.length)) {
 -                                      rc = -EFAULT;
 -                                      break;
 -                              }
 -                      } else if (wrq->u.encoding.length != 0) {
 -                              rc = -EINVAL;
 +              if (wrq->u.encoding.pointer) {
 +                      if (wrq->u.encoding.length > WLAN_WEP232_KEYLEN) {
 +                              rc = -E2BIG;
 +                              break;
 +                      }
 +                      memset(abyKey, 0, WLAN_WEP232_KEYLEN);
 +                      if (copy_from_user(abyKey,
 +                                         wrq->u.encoding.pointer,
 +                                         wrq->u.encoding.length)) {
 +                              rc = -EFAULT;
                                break;
                        }
 -                      rc = iwctl_siwencode(dev, NULL, &(wrq->u.encoding), abyKey);
 +              } else if (wrq->u.encoding.length != 0) {
 +                      rc = -EINVAL;
 +                      break;
                }
 -              break;
 +              rc = iwctl_siwencode(dev, NULL, &(wrq->u.encoding), abyKey);
 +      }
 +      break;
  
 -              // Get the WEP keys and mode
 +      // Get the WEP keys and mode
        case SIOCGIWENCODE:
  
                if (!capable(CAP_NET_ADMIN)) {
                        break;
                }
                {
 -                  char abyKey[WLAN_WEP232_KEYLEN];
 +                      char abyKey[WLAN_WEP232_KEYLEN];
  
 -                  rc = iwctl_giwencode(dev, NULL, &(wrq->u.encoding), abyKey);
 -                  if (rc != 0) break;
 +                      rc = iwctl_giwencode(dev, NULL, &(wrq->u.encoding), abyKey);
 +                      if (rc != 0) break;
                        if (wrq->u.encoding.pointer) {
                                if (copy_to_user(wrq->u.encoding.pointer,
 -                                                      abyKey,
 -                                                      wrq->u.encoding.length))
 +                                               abyKey,
 +                                               wrq->u.encoding.length))
                                        rc = -EFAULT;
                        }
                }
  
                // Get the current Tx-Power
        case SIOCGIWTXPOW:
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWTXPOW \n");
 -        rc = -EOPNOTSUPP;
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWTXPOW \n");
 +              rc = -EOPNOTSUPP;
                break;
  
        case SIOCSIWTXPOW:
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWTXPOW \n");
 -        rc = -EOPNOTSUPP;
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWTXPOW \n");
 +              rc = -EOPNOTSUPP;
                break;
  
        case SIOCSIWRETRY:
                // Get range of parameters
        case SIOCGIWRANGE:
  
 -              {
 -                      struct iw_range range;
 +      {
 +              struct iw_range range;
  
 -                      rc = iwctl_giwrange(dev, NULL, &(wrq->u.data), (char *) &range);
 -                      if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range)))
 -                              rc = -EFAULT;
 -              }
 +              rc = iwctl_giwrange(dev, NULL, &(wrq->u.data), (char *)&range);
 +              if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range)))
 +                      rc = -EFAULT;
 +      }
  
 -              break;
 +      break;
  
        case SIOCGIWPOWER:
  
                rc = iwctl_giwpower(dev, NULL, &(wrq->u.power), NULL);
                break;
  
 -
        case SIOCSIWPOWER:
  
                rc = iwctl_siwpower(dev, NULL, &(wrq->u.power), NULL);
                break;
  
 -
        case SIOCGIWSENS:
  
 -          rc = iwctl_giwsens(dev, NULL, &(wrq->u.sens), NULL);
 +              rc = iwctl_giwsens(dev, NULL, &(wrq->u.sens), NULL);
                break;
  
        case SIOCSIWSENS:
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSENS \n");
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSENS \n");
                rc = -EOPNOTSUPP;
                break;
  
 -      case SIOCGIWAPLIST:
 -          {
 -            char buffer[IW_MAX_AP * (sizeof(struct sockaddr) + sizeof(struct iw_quality))];
 -
 -                  if (wrq->u.data.pointer) {
 -                      rc = iwctl_giwaplist(dev, NULL, &(wrq->u.data), buffer);
 -                      if (rc == 0) {
 -                    if (copy_to_user(wrq->u.data.pointer,
 -                                                      buffer,
 -                                                     (wrq->u.data.length * (sizeof(struct sockaddr) +  sizeof(struct iw_quality)))
 -                                      ))
 -                                  rc = -EFAULT;
 -                      }
 -            }
 -        }
 -              break;
 +      case SIOCGIWAPLIST: {
 +              char buffer[IW_MAX_AP * (sizeof(struct sockaddr) + sizeof(struct iw_quality))];
  
 +              if (wrq->u.data.pointer) {
 +                      rc = iwctl_giwaplist(dev, NULL, &(wrq->u.data), buffer);
 +                      if (rc == 0) {
 +                              if (copy_to_user(wrq->u.data.pointer,
 +                                               buffer,
 +                                               (wrq->u.data.length * (sizeof(struct sockaddr) +  sizeof(struct iw_quality)))
 +                                          ))
 +                                      rc = -EFAULT;
 +                      }
 +              }
 +      }
 +      break;
  
  #ifdef WIRELESS_SPY
 -              // Set the spy list
 +      // Set the spy list
        case SIOCSIWSPY:
  
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSPY \n");
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSPY \n");
                rc = -EOPNOTSUPP;
                break;
  
                // Get the spy list
        case SIOCGIWSPY:
  
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSPY \n");
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSPY \n");
                rc = -EOPNOTSUPP;
                break;
  
  #endif // WIRELESS_SPY
  
        case SIOCGIWPRIV:
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPRIV \n");
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPRIV \n");
                rc = -EOPNOTSUPP;
  /*
 -              if(wrq->u.data.pointer) {
 -                      wrq->u.data.length = sizeof(iwctl_private_args) / sizeof( iwctl_private_args[0]);
 +  if (wrq->u.data.pointer) {
 +  wrq->u.data.length = sizeof(iwctl_private_args) / sizeof(iwctl_private_args[0]);
  
 -                      if(copy_to_user(wrq->u.data.pointer,
 -                                      (u_char *) iwctl_private_args,
 -                                      sizeof(iwctl_private_args)))
 -                              rc = -EFAULT;
 -              }
 +  if (copy_to_user(wrq->u.data.pointer,
 +  (u_char *) iwctl_private_args,
 +  sizeof(iwctl_private_args)))
 +  rc = -EFAULT;
 +  }
  */
                break;
  
 -
  //2008-0409-07, <Add> by Einsn Liu
 -#ifdef  WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
        case SIOCSIWAUTH:
                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAUTH \n");
                rc = iwctl_siwauth(dev, NULL, &(wrq->u.param), NULL);
                rc = iwctl_giwgenie(dev, NULL, &(wrq->u.data), wrq->u.data.pointer);
                break;
  
 -      case SIOCSIWENCODEEXT:
 -              {
 -                      char extra[sizeof(struct iw_encode_ext)+MAX_KEY_LEN+1];
 -                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODEEXT \n");
 -                      if(wrq->u.encoding.pointer){
 -                              memset(extra, 0, sizeof(struct iw_encode_ext)+MAX_KEY_LEN+1);
 -                              if(wrq->u.encoding.length > (sizeof(struct iw_encode_ext)+ MAX_KEY_LEN)){
 -                                      rc = -E2BIG;
 -                                      break;
 -                              }
 -                              if(copy_from_user(extra, wrq->u.encoding.pointer,wrq->u.encoding.length)){
 -                                      rc = -EFAULT;
 -                                      break;
 -                              }
 -                      }else if(wrq->u.encoding.length != 0){
 -                              rc = -EINVAL;
 +      case SIOCSIWENCODEEXT: {
 +              char extra[sizeof(struct iw_encode_ext)+MAX_KEY_LEN+1];
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODEEXT \n");
 +              if (wrq->u.encoding.pointer) {
 +                      memset(extra, 0, sizeof(struct iw_encode_ext)+MAX_KEY_LEN + 1);
 +                      if (wrq->u.encoding.length > (sizeof(struct iw_encode_ext) + MAX_KEY_LEN)) {
 +                              rc = -E2BIG;
 +                              break;
 +                      }
 +                      if (copy_from_user(extra, wrq->u.encoding.pointer, wrq->u.encoding.length)) {
 +                              rc = -EFAULT;
                                break;
                        }
 -                      rc = iwctl_siwencodeext(dev, NULL, &(wrq->u.encoding), extra);
 +              } else if (wrq->u.encoding.length != 0) {
 +                      rc = -EINVAL;
 +                      break;
                }
 -              break;
 +              rc = iwctl_siwencodeext(dev, NULL, &(wrq->u.encoding), extra);
 +      }
 +      break;
  
        case SIOCGIWENCODEEXT:
                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODEEXT \n");
  #endif // #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
  //End Add -- //2008-0409-07, <Add> by Einsn Liu
  
 -    case IOCTL_CMD_TEST:
 +      case IOCTL_CMD_TEST:
  
                if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) {
 -                  rc = -EFAULT;
 -                  break;
 -              } else {
 -                  rc = 0;
 -              }
 -        pReq = (PSCmdRequest)rq;
 -        pReq->wResult = MAGIC_CODE;
 -        break;
 -
 -    case IOCTL_CMD_SET:
 -
 -               #ifdef SndEvt_ToAPI
 -                  if((((PSCmdRequest)rq)->wCmdCode !=WLAN_CMD_SET_EVT) &&
 -                     !(pDevice->flags & DEVICE_FLAGS_OPENED))
 -            #else
 -              if (!(pDevice->flags & DEVICE_FLAGS_OPENED) &&
 -                     (((PSCmdRequest)rq)->wCmdCode !=WLAN_CMD_SET_WPA))
 -            #endif
 -              {
 -                  rc = -EFAULT;
 -                  break;
 +                      rc = -EFAULT;
 +                      break;
                } else {
 -                  rc = 0;
 +                      rc = 0;
                }
 +              pReq = (PSCmdRequest)rq;
 +              pReq->wResult = MAGIC_CODE;
 +              break;
  
 -          if (test_and_set_bit( 0, (void*)&(pMgmt->uCmdBusy))) {
 -                  return -EBUSY;
 -          }
 -        rc = private_ioctl(pDevice, rq);
 -        clear_bit( 0, (void*)&(pMgmt->uCmdBusy));
 -        break;
 +      case IOCTL_CMD_SET:
  
 -    case IOCTL_CMD_HOSTAPD:
 +#ifdef SndEvt_ToAPI
 +              if ((((PSCmdRequest)rq)->wCmdCode != WLAN_CMD_SET_EVT) &&
 +                  !(pDevice->flags & DEVICE_FLAGS_OPENED))
 +#else
 +                      if (!(pDevice->flags & DEVICE_FLAGS_OPENED) &&
 +                          (((PSCmdRequest)rq)->wCmdCode != WLAN_CMD_SET_WPA))
 +#endif
 +                      {
 +                              rc = -EFAULT;
 +                              break;
 +                      } else {
 +                              rc = 0;
 +                      }
  
 +              if (test_and_set_bit(0, (void *)&(pMgmt->uCmdBusy))) {
 +                      return -EBUSY;
 +              }
 +              rc = private_ioctl(pDevice, rq);
 +              clear_bit(0, (void *)&(pMgmt->uCmdBusy));
 +              break;
  
 -      rc = vt6655_hostap_ioctl(pDevice, &wrq->u.data);
 -        break;
 +      case IOCTL_CMD_HOSTAPD:
  
 -    case IOCTL_CMD_WPA:
 +              rc = vt6655_hostap_ioctl(pDevice, &wrq->u.data);
 +              break;
  
 -      rc = wpa_ioctl(pDevice, &wrq->u.data);
 -        break;
 +      case IOCTL_CMD_WPA:
 +
 +              rc = wpa_ioctl(pDevice, &wrq->u.data);
 +              break;
  
        case SIOCETHTOOL:
 -        return ethtool_ioctl(dev, (void *) rq->ifr_data);
 -      // All other calls are currently unsupported
 +              return ethtool_ioctl(dev, (void *)rq->ifr_data);
 +              // All other calls are currently unsupported
  
        default:
                rc = -EOPNOTSUPP;
 -        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Ioctl command not support..%x\n", cmd);
 -
 -
 -    }
 -
 -    if (pDevice->bCommit) {
 -       if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
 -           netif_stop_queue(pDevice->dev);
 -           spin_lock_irq(&pDevice->lock);
 -           bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL);
 -           spin_unlock_irq(&pDevice->lock);
 -       }
 -       else {
 -           DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Commit the settings\n");
 -           spin_lock_irq(&pDevice->lock);
 -           pDevice->bLinkPass = false;
 -           memset(pMgmt->abyCurrBSSID, 0, 6);
 -           pMgmt->eCurrState = WMAC_STATE_IDLE;
 -           netif_stop_queue(pDevice->dev);
 -      #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 -            pMgmt->eScanType = WMAC_SCAN_ACTIVE;
 -       if(pDevice->bWPASuppWextEnabled !=true)
 -       #endif
 -           bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
 -           bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL);
 -           spin_unlock_irq(&pDevice->lock);
 -      }
 -      pDevice->bCommit = false;
 -    }
 -
 -    return rc;
 -}
 +              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Ioctl command not support..%x\n", cmd);
  
 +      }
 +
 +      if (pDevice->bCommit) {
 +              if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
 +                      netif_stop_queue(pDevice->dev);
 +                      spin_lock_irq(&pDevice->lock);
 +                      bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL);
 +                      spin_unlock_irq(&pDevice->lock);
 +              } else {
 +                      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Commit the settings\n");
 +                      spin_lock_irq(&pDevice->lock);
 +                      pDevice->bLinkPass = false;
 +                      memset(pMgmt->abyCurrBSSID, 0, 6);
 +                      pMgmt->eCurrState = WMAC_STATE_IDLE;
 +                      netif_stop_queue(pDevice->dev);
 +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 +                      pMgmt->eScanType = WMAC_SCAN_ACTIVE;
 +                      if (pDevice->bWPASuppWextEnabled != true)
 +#endif
 +                              bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
 +                      bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
 +                      spin_unlock_irq(&pDevice->lock);
 +              }
 +              pDevice->bCommit = false;
 +      }
 +
 +      return rc;
 +}
  
  static int ethtool_ioctl(struct net_device *dev, void *useraddr)
  {
        if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
                return -EFAULT;
  
 -        switch (ethcmd) {
 +      switch (ethcmd) {
        case ETHTOOL_GDRVINFO: {
                struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
                strncpy(info.driver, DEVICE_NAME, sizeof(info.driver)-1);
                return 0;
        }
  
 -        }
 +      }
  
        return -EOPNOTSUPP;
  }
@@@ -3324,111 -3527,122 +3292,111 @@@ static struct pci_driver device_driver 
  
  static int __init vt6655_init_module(void)
  {
 -    int ret;
 -
 +      int ret;
  
  //    ret=pci_module_init(&device_driver);
        //ret = pcie_port_service_register(&device_driver);
        ret = pci_register_driver(&device_driver);
  #ifdef CONFIG_PM
 -    if(ret >= 0)
 -        register_reboot_notifier(&device_notifier);
 +      if (ret >= 0)
 +              register_reboot_notifier(&device_notifier);
  #endif
  
 -    return ret;
 +      return ret;
  }
  
  static void __exit vt6655_cleanup_module(void)
  {
 -
 -
  #ifdef CONFIG_PM
 -    unregister_reboot_notifier(&device_notifier);
 +      unregister_reboot_notifier(&device_notifier);
  #endif
 -    pci_unregister_driver(&device_driver);
 -
 +      pci_unregister_driver(&device_driver);
  }
  
  module_init(vt6655_init_module);
  module_exit(vt6655_cleanup_module);
  
 -
  #ifdef CONFIG_PM
  static int
  device_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
  {
 -    struct pci_dev *pdev = NULL;
 -    switch(event) {
 -    case SYS_DOWN:
 -    case SYS_HALT:
 -    case SYS_POWER_OFF:
 -      for_each_pci_dev(pdev) {
 -            if(pci_dev_driver(pdev) == &device_driver) {
 -                if (pci_get_drvdata(pdev))
 -                    viawget_suspend(pdev, PMSG_HIBERNATE);
 -            }
 -        }
 -    }
 -    return NOTIFY_DONE;
 +      struct pci_dev *pdev = NULL;
 +      switch (event) {
 +      case SYS_DOWN:
 +      case SYS_HALT:
 +      case SYS_POWER_OFF:
 +              for_each_pci_dev(pdev) {
 +                      if (pci_dev_driver(pdev) == &device_driver) {
 +                              if (pci_get_drvdata(pdev))
 +                                      viawget_suspend(pdev, PMSG_HIBERNATE);
 +                      }
 +              }
 +      }
 +      return NOTIFY_DONE;
  }
  
  static int
  viawget_suspend(struct pci_dev *pcid, pm_message_t state)
  {
 -    int power_status;   // to silence the compiler
 -
 -    PSDevice pDevice=pci_get_drvdata(pcid);
 -    PSMgmtObject  pMgmt = pDevice->pMgmt;
 -
 -    netif_stop_queue(pDevice->dev);
 -    spin_lock_irq(&pDevice->lock);
 -    pci_save_state(pcid);
 -    del_timer(&pDevice->sTimerCommand);
 -    del_timer(&pMgmt->sTimerSecondCallback);
 -    pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
 -    pDevice->uCmdDequeueIdx = 0;
 -    pDevice->uCmdEnqueueIdx = 0;
 -    pDevice->bCmdRunning = false;
 -    MACbShutdown(pDevice->PortOffset);
 -    MACvSaveContext(pDevice->PortOffset, pDevice->abyMacContext);
 -    pDevice->bLinkPass = false;
 -    memset(pMgmt->abyCurrBSSID, 0, 6);
 -    pMgmt->eCurrState = WMAC_STATE_IDLE;
 -    pci_disable_device(pcid);
 -    power_status = pci_set_power_state(pcid, pci_choose_state(pcid, state));
 -    spin_unlock_irq(&pDevice->lock);
 -    return 0;
 +      int power_status;   // to silence the compiler
 +
 +      PSDevice pDevice = pci_get_drvdata(pcid);
 +      PSMgmtObject  pMgmt = pDevice->pMgmt;
 +
 +      netif_stop_queue(pDevice->dev);
 +      spin_lock_irq(&pDevice->lock);
 +      pci_save_state(pcid);
 +      del_timer(&pDevice->sTimerCommand);
 +      del_timer(&pMgmt->sTimerSecondCallback);
 +      pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
 +      pDevice->uCmdDequeueIdx = 0;
 +      pDevice->uCmdEnqueueIdx = 0;
 +      pDevice->bCmdRunning = false;
 +      MACbShutdown(pDevice->PortOffset);
 +      MACvSaveContext(pDevice->PortOffset, pDevice->abyMacContext);
 +      pDevice->bLinkPass = false;
 +      memset(pMgmt->abyCurrBSSID, 0, 6);
 +      pMgmt->eCurrState = WMAC_STATE_IDLE;
 +      pci_disable_device(pcid);
 +      power_status = pci_set_power_state(pcid, pci_choose_state(pcid, state));
 +      spin_unlock_irq(&pDevice->lock);
 +      return 0;
  }
  
  static int
  viawget_resume(struct pci_dev *pcid)
  {
 -    PSDevice  pDevice=pci_get_drvdata(pcid);
 -    PSMgmtObject  pMgmt = pDevice->pMgmt;
 -    int power_status;   // to silence the compiler
 -
 -
 -    power_status = pci_set_power_state(pcid, 0);
 -    power_status = pci_enable_wake(pcid, 0, 0);
 -    pci_restore_state(pcid);
 -    if (netif_running(pDevice->dev)) {
 -        spin_lock_irq(&pDevice->lock);
 -        MACvRestoreContext(pDevice->PortOffset, pDevice->abyMacContext);
 -        device_init_registers(pDevice, DEVICE_INIT_DXPL);
 -        if (pMgmt->sNodeDBTable[0].bActive == true) { // Assoc with BSS
 -            pMgmt->sNodeDBTable[0].bActive = false;
 -            pDevice->bLinkPass = false;
 -            if(pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
 -                // In Adhoc, BSS state set back to started.
 -                pMgmt->eCurrState = WMAC_STATE_STARTED;
 -           }
 -            else {
 -                pMgmt->eCurrMode = WMAC_MODE_STANDBY;
 -                pMgmt->eCurrState = WMAC_STATE_IDLE;
 -            }
 -        }
 -        init_timer(&pMgmt->sTimerSecondCallback);
 -        init_timer(&pDevice->sTimerCommand);
 -        MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
 -        BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
 -        bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
 -        bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL);
 -        spin_unlock_irq(&pDevice->lock);
 -    }
 -    return 0;
 +      PSDevice  pDevice = pci_get_drvdata(pcid);
 +      PSMgmtObject  pMgmt = pDevice->pMgmt;
 +      int power_status;   // to silence the compiler
 +
 +      power_status = pci_set_power_state(pcid, 0);
 +      power_status = pci_enable_wake(pcid, 0, 0);
 +      pci_restore_state(pcid);
 +      if (netif_running(pDevice->dev)) {
 +              spin_lock_irq(&pDevice->lock);
 +              MACvRestoreContext(pDevice->PortOffset, pDevice->abyMacContext);
 +              device_init_registers(pDevice, DEVICE_INIT_DXPL);
 +              if (pMgmt->sNodeDBTable[0].bActive == true) { // Assoc with BSS
 +                      pMgmt->sNodeDBTable[0].bActive = false;
 +                      pDevice->bLinkPass = false;
 +                      if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
 +                              // In Adhoc, BSS state set back to started.
 +                              pMgmt->eCurrState = WMAC_STATE_STARTED;
 +                      } else {
 +                              pMgmt->eCurrMode = WMAC_MODE_STANDBY;
 +                              pMgmt->eCurrState = WMAC_STATE_IDLE;
 +                      }
 +              }
 +              init_timer(&pMgmt->sTimerSecondCallback);
 +              init_timer(&pDevice->sTimerCommand);
 +              MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
 +              BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
 +              bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
 +              bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
 +              spin_unlock_irq(&pDevice->lock);
 +      }
 +      return 0;
  }
  
  #endif
 -
 -
 -
 -
index 2161af83eaa0a04a6696bd5c58b5563ee26b222b,457d91c1325d5ec1f4e43c76496bf4cb94962302..3a3fdc58b6da1028032c5c742e76edccd89ab91b
@@@ -46,6 -46,7 +46,7 @@@
   */
  #undef __NO_VERSION__
  
+ #include <linux/file.h>
  #include "device.h"
  #include "card.h"
  #include "baseband.h"
@@@ -72,6 -73,7 +73,6 @@@
  #include "int.h"
  #include "iowpa.h"
  
 -/*---------------------  Static Definitions -------------------------*/
  /* static int msglevel = MSG_LEVEL_DEBUG; */
  static int          msglevel                =MSG_LEVEL_INFO;
  
@@@ -94,12 -96,14 +95,12 @@@ MODULE_DESCRIPTION(DEVICE_FULL_DRV_NAM)
  #define RX_DESC_DEF0     64
  DEVICE_PARAM(RxDescriptors0,"Number of receive usb desc buffer");
  
 -
  #define TX_DESC_DEF0     64
  DEVICE_PARAM(TxDescriptors0,"Number of transmit usb desc buffer");
  
  #define CHANNEL_DEF     6
  DEVICE_PARAM(Channel, "Channel number");
  
 -
  /* PreambleType[] is the preamble length used for transmit.
     0: indicate allows long preamble type
     1: indicate allows short preamble type
@@@ -115,6 -119,7 +116,6 @@@ DEVICE_PARAM(RTSThreshold, "RTS thresho
  #define FRAG_THRESH_DEF     2346
  DEVICE_PARAM(FragThreshold, "Fragmentation threshold");
  
 -
  #define DATA_RATE_DEF     13
  /* datarate[] index
     0: indicate 1 Mbps   0x02
@@@ -144,6 -149,7 +145,6 @@@ DEVICE_PARAM(OPMode, "Infrastruct, adho
     2: indicate AP mode used
  */
  
 -
  /* PSMode[]
     0: indicate disable power saving mode
     1: indicate enable power saving mode
  #define PS_MODE_DEF     0
  DEVICE_PARAM(PSMode, "Power saving mode");
  
 -
  #define SHORT_RETRY_DEF     8
  DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits");
  
@@@ -167,6 -174,8 +168,6 @@@ DEVICE_PARAM(LongRetryLimit, "long fram
  #define BBP_TYPE_DEF     2
  DEVICE_PARAM(BasebandType, "baseband type");
  
 -
 -
  /* 80211hEnable[]
     0: indicate disable 802.11h
     1: indicate enable 802.11h
  
  DEVICE_PARAM(b80211hEnable, "802.11h mode");
  
 -
  /*
   * Static vars definitions
   */
@@@ -195,9 -205,12 +196,9 @@@ static const long frequency_list[] = 
      5700, 5745, 5765, 5785, 5805, 5825
        };
  
 -
  static const struct iw_handler_def    iwctl_handler_def;
  */
  
 -/*---------------------  Static Functions  --------------------------*/
 -
  static int vt6656_probe(struct usb_interface *intf,
                        const struct usb_device_id *id);
  static void vt6656_disconnect(struct usb_interface *intf);
@@@ -233,13 -246,21 +234,13 @@@ static int Config_FileGetParameter(unsi
                                   unsigned char *dest,
                                   unsigned char *source);
  
 -
  static void usb_device_reset(struct vnt_private *pDevice);
  
 -
 -
 -/*---------------------  Export Variables  --------------------------*/
 -
 -/*---------------------  Export Functions  --------------------------*/
 -
 -
  static void
  device_set_options(struct vnt_private *pDevice) {
  
 -    BYTE    abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 -    BYTE    abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
 +    u8    abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 +    u8    abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
      u8 abySNAP_Bridgetunnel[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8};
  
      memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN);
      pDevice->bDiversityRegCtlON = false;
  }
  
 -
  static void device_init_diversity_timer(struct vnt_private *pDevice)
  {
      init_timer(&pDevice->TimerSQ3Tmax1);
      return;
  }
  
 -
  /*
   * initialization of MAC & BBP registers
   */
@@@ -344,8 -367,8 +345,8 @@@ static int device_init_registers(struc
          }
      }
  
 -    sInitCmd.byInitClass = (BYTE)InitType;
 -    sInitCmd.bExistSWNetAddr = (BYTE) pDevice->bExistSWNetAddr;
 +    sInitCmd.byInitClass = (u8)InitType;
 +    sInitCmd.bExistSWNetAddr = (u8) pDevice->bExistSWNetAddr;
      for (ii = 0; ii < 6; ii++)
        sInitCmd.bySWNetAddr[ii] = pDevice->abyCurrentNetAddr[ii];
      sInitCmd.byShortRetryLimit = pDevice->byShortRetryLimit;
                                      0,
                                      0,
                                      sizeof(CMD_CARD_INIT),
 -                                    (PBYTE) &(sInitCmd));
 +                                    (u8 *) &(sInitCmd));
  
      if ( ntStatus != STATUS_SUCCESS ) {
          DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Issue Card init fail \n");
      }
      if (InitType == DEVICE_INIT_COLD) {
  
 -        ntStatus = CONTROLnsRequestIn(pDevice,MESSAGE_TYPE_INIT_RSP,0,0,sizeof(RSP_CARD_INIT), (PBYTE) &(sInitRsp));
 +        ntStatus = CONTROLnsRequestIn(pDevice,MESSAGE_TYPE_INIT_RSP,0,0,sizeof(RSP_CARD_INIT), (u8 *) &(sInitRsp));
  
          if (ntStatus != STATUS_SUCCESS) {
              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Cardinit request in status fail!\n");
          pDevice->bNonERPPresent = false;
          pDevice->bBarkerPreambleMd = false;
          if ( pDevice->bFixRate ) {
 -            pDevice->wCurrentRate = (WORD) pDevice->uConnectionRate;
 +            pDevice->wCurrentRate = (u16) pDevice->uConnectionRate;
          } else {
              if ( pDevice->byBBType == BB_TYPE_11B )
                  pDevice->wCurrentRate = RATE_11M;
@@@ -749,6 -772,7 +750,6 @@@ static void device_free_tx_bufs(struct 
      return;
  }
  
 -
  static void device_free_rx_bufs(struct vnt_private *pDevice)
  {
      PRCB pRCB;
@@@ -786,6 -810,7 +787,6 @@@ static void device_free_int_bufs(struc
      return;
  }
  
 -
  static bool device_alloc_bufs(struct vnt_private *pDevice)
  {
  
      PRCB pRCB;
      int ii;
  
 -
      for (ii = 0; ii < pDevice->cbTD; ii++) {
  
          pTxContext = kmalloc(sizeof(USB_SEND_CONTEXT), GFP_KERNEL);
          goto free_tx;
      }
  
 -
      pDevice->FirstRecvFreeList = NULL;
      pDevice->LastRecvFreeList = NULL;
      pDevice->FirstRecvMngList = NULL;
          pRCB++;
      }
  
 -
        pDevice->pControlURB = usb_alloc_urb(0, GFP_ATOMIC);
        if (pDevice->pControlURB == NULL) {
            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc control urb\n");
@@@ -880,6 -908,9 +881,6 @@@ free_tx
        return false;
  }
  
 -
 -
 -
  static bool device_init_defrag_cb(struct vnt_private *pDevice)
  {
        int i;
@@@ -903,6 -934,8 +904,6 @@@ free_frag
      return false;
  }
  
 -
 -
  static void device_free_frag_bufs(struct vnt_private *pDevice)
  {
        PSDeFragControlBlock pDeF;
      }
  }
  
 -
 -
  int device_alloc_frag_buf(struct vnt_private *pDevice,
                PSDeFragControlBlock pDeF)
  {
      return true;
  }
  
 -
 -/*-----------------------------------------------------------------*/
 -
  static int  device_open(struct net_device *dev)
  {
        struct vnt_private *pDevice = netdev_priv(dev);
  
      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " device_open...\n");
  
 -
      pDevice->rx_buf_sz = MAX_TOTAL_SIZE_WITH_ALL_HEADERS;
  
      if (device_alloc_bufs(pDevice) == false) {
        else
                bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
  
 -
      netif_stop_queue(pDevice->dev);
      pDevice->flags |= DEVICE_FLAGS_OPENED;
  
@@@ -1044,6 -1084,8 +1045,6 @@@ free_rx_tx
      return -ENOMEM;
  }
  
 -
 -
  static int device_close(struct net_device *dev)
  {
        struct vnt_private *pDevice = netdev_priv(dev);
          mdelay(30);
      }
  
 -
          memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
          pMgmt->bShareKeyAlgorithm = false;
          pDevice->bEncryptionEnable = false;
@@@ -1123,6 -1166,7 +1124,6 @@@ static void vt6656_disconnect(struct us
        if (!device)
                return;
  
 -
        usb_set_intfdata(intf, NULL);
        usb_put_dev(interface_to_usbdev(intf));
  
@@@ -1273,53 -1317,29 +1274,29 @@@ static int Config_FileGetParameter(unsi
  /* if read fails, return NULL, or return data pointer */
  static unsigned char *Config_FileOperation(struct vnt_private *pDevice)
  {
-     unsigned char *config_path = CONFIG_PATH;
-     unsigned char *buffer = NULL;
-     struct file   *filp=NULL;
-     mm_segment_t old_fs = get_fs();
+       unsigned char *buffer = kmalloc(1024, GFP_KERNEL);
+       struct file   *file;
  
-     int result = 0;
-     set_fs (KERNEL_DS);
-     /* open file */
-       filp = filp_open(config_path, O_RDWR, 0);
-         if (IS_ERR(filp)) {
-            printk("Config_FileOperation file Not exist\n");
-            result=-1;
-              goto error2;
-         }
-      if(!(filp->f_op) || !(filp->f_op->read) ||!(filp->f_op->write)) {
-            printk("file %s is not read or writeable?\n",config_path);
-         result = -1;
-         goto error1;
-       }
-     buffer = kmalloc(1024, GFP_KERNEL);
-     if(buffer==NULL) {
-       printk("allocate mem for file fail?\n");
-       result = -1;
-       goto error1;
-     }
-     if(filp->f_op->read(filp, buffer, 1024, &filp->f_pos)<0) {
-      printk("read file error?\n");
-      result = -1;
-     }
+       if (!buffer) {
+               printk("allocate mem for file fail?\n");
+               return NULL;
+       }
  
- error1:
-   if(filp_close(filp,NULL))
-        printk("Config_FileOperation:close file fail\n");
+       file = filp_open(CONFIG_PATH, O_RDONLY, 0);
+       if (IS_ERR(file)) {
+               kfree(buffer);
+               printk("Config_FileOperation file Not exist\n");
+               return NULL;
+       }
  
- error2:
-   set_fs (old_fs);
+       if (kernel_read(file, 0, buffer, 1024) < 0) {
+               printk("read file error?\n");
+               kfree(buffer);
+               buffer = NULL;
+       }
  
- if(result!=0) {
-     kfree(buffer);
-     buffer=NULL;
- }
-   return buffer;
+       fput(file);
+       return buffer;
  }
  
  /* return --->-1:fail; >=0:successful */
@@@ -1387,6 -1407,7 +1364,6 @@@ static void device_set_multi(struct net
        u8 byTmpMode = 0;
        int rc;
  
 -
        spin_lock_irq(&pDevice->lock);
      rc = CONTROLnsRequestIn(pDevice,
                              MESSAGE_TYPE_READ,
              mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31));
          }
          for (ii = 0; ii < 4; ii++) {
 -             MACvWriteMultiAddr(pDevice, ii, *((PBYTE)&mc_filter[0] + ii));
 -             MACvWriteMultiAddr(pDevice, ii+ 4, *((PBYTE)&mc_filter[1] + ii));
 +             MACvWriteMultiAddr(pDevice, ii, *((u8 *)&mc_filter[0] + ii));
 +             MACvWriteMultiAddr(pDevice, ii+ 4, *((u8 *)&mc_filter[1] + ii));
          }
          pDevice->byRxMode &= ~(RCR_UNICAST);
          pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
@@@ -1474,6 -1495,7 +1451,6 @@@ static int device_ioctl(struct net_devi
        return rc;
  }
  
 -
  static int ethtool_ioctl(struct net_device *dev, void *useraddr)
  {
        u32 ethcmd;
index 8fbb6d22cdc802fb73c0dc1b40342f7a4cc5044a,19cc749f83863ec451b91c6910114255a0334f56..f87dbfd3277047a9c9d6d2ef6fdd7c3487a32f93
@@@ -1711,7 -1711,7 +1711,7 @@@ static int uart_proc_show(struct seq_fi
  
  static int uart_proc_open(struct inode *inode, struct file *file)
  {
-       return single_open(file, uart_proc_show, PDE(inode)->data);
+       return single_open(file, uart_proc_show, PDE_DATA(inode));
  }
  
  static const struct file_operations uart_proc_fops = {
@@@ -1941,8 -1941,6 +1941,8 @@@ int uart_suspend_port(struct uart_drive
                mutex_unlock(&port->mutex);
                return 0;
        }
 +      put_device(tty_dev);
 +
        if (console_suspend_enabled || !uart_console(uport))
                uport->suspended = 1;
  
@@@ -2008,11 -2006,9 +2008,11 @@@ int uart_resume_port(struct uart_drive
                        disable_irq_wake(uport->irq);
                        uport->irq_wake = 0;
                }
 +              put_device(tty_dev);
                mutex_unlock(&port->mutex);
                return 0;
        }
 +      put_device(tty_dev);
        uport->suspended = 0;
  
        /*
index a690d64217f403599d00c078bc91cec1b79dcf11,88966e0508a5a28f556310498452dce318e96912..073b938f913546793d24443a89dc928982eecaaa
@@@ -221,7 -221,7 +221,7 @@@ static int proc_udc_show(struct seq_fil
  
  static int proc_udc_open(struct inode *inode, struct file *file)
  {
-       return single_open(file, proc_udc_show, PDE(inode)->data);
+       return single_open(file, proc_udc_show, PDE_DATA(inode));
  }
  
  static const struct file_operations proc_ops = {
@@@ -1631,6 -1631,7 +1631,6 @@@ static int at91_start(struct usb_gadge
  
        udc = container_of(gadget, struct at91_udc, gadget);
        udc->driver = driver;
 -      udc->gadget.dev.driver = &driver->driver;
        udc->gadget.dev.of_node = udc->pdev->dev.of_node;
        udc->enabled = 1;
        udc->selfpowered = 1;
@@@ -1651,6 -1652,7 +1651,6 @@@ static int at91_stop(struct usb_gadget 
        at91_udp_write(udc, AT91_UDP_IDR, ~0);
        spin_unlock_irqrestore(&udc->lock, flags);
  
 -      udc->gadget.dev.driver = NULL;
        udc->driver = NULL;
  
        DBG("unbound from %s\n", driver->driver.name);
@@@ -1778,7 -1780,13 +1778,7 @@@ static int at91udc_probe(struct platfor
                DBG("clocks missing\n");
                retval = -ENODEV;
                /* NOTE: we "know" here that refcounts on these are NOPs */
 -              goto fail0b;
 -      }
 -
 -      retval = device_register(&udc->gadget.dev);
 -      if (retval < 0) {
 -              put_device(&udc->gadget.dev);
 -              goto fail0b;
 +              goto fail1;
        }
  
        /* don't do anything until we have both gadget driver and VBUS */
@@@ -1849,6 -1857,8 +1849,6 @@@ fail3
  fail2:
        free_irq(udc->udp_irq, udc);
  fail1:
 -      device_unregister(&udc->gadget.dev);
 -fail0b:
        iounmap(udc->udp_baseaddr);
  fail0a:
        if (cpu_is_at91rm9200())
@@@ -1882,6 -1892,8 +1882,6 @@@ static int __exit at91udc_remove(struc
                gpio_free(udc->board.vbus_pin);
        }
        free_irq(udc->udp_irq, udc);
 -      device_unregister(&udc->gadget.dev);
 -
        iounmap(udc->udp_baseaddr);
  
        if (cpu_is_at91rm9200())
index 7c2a101d19acfd9702aab4f0505db25226a0b79b,ede70ffe1ab49934f995f86287f178746f1b3420..2d8c1cfea6993fc53ec2ad34f3f128aa6d4fad16
@@@ -185,7 -185,20 +185,7 @@@ static void done(struct fsl_ep *ep, str
                dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
        }
  
 -      if (req->mapped) {
 -              dma_unmap_single(ep->udc->gadget.dev.parent,
 -                      req->req.dma, req->req.length,
 -                      ep_is_in(ep)
 -                              ? DMA_TO_DEVICE
 -                              : DMA_FROM_DEVICE);
 -              req->req.dma = DMA_ADDR_INVALID;
 -              req->mapped = 0;
 -      } else
 -              dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
 -                      req->req.dma, req->req.length,
 -                      ep_is_in(ep)
 -                              ? DMA_TO_DEVICE
 -                              : DMA_FROM_DEVICE);
 +      usb_gadget_unmap_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
  
        if (status && (status != -ESHUTDOWN))
                VDBG("complete %s req %p stat %d len %u/%u",
@@@ -875,7 -888,6 +875,7 @@@ fsl_ep_queue(struct usb_ep *_ep, struc
        struct fsl_req *req = container_of(_req, struct fsl_req, req);
        struct fsl_udc *udc;
        unsigned long flags;
 +      int ret;
  
        /* catch various bogus parameters */
        if (!_req || !req->req.complete || !req->req.buf
  
        req->ep = ep;
  
 -      /* map virtual address to hardware */
 -      if (req->req.dma == DMA_ADDR_INVALID) {
 -              req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
 -                                      req->req.buf,
 -                                      req->req.length, ep_is_in(ep)
 -                                              ? DMA_TO_DEVICE
 -                                              : DMA_FROM_DEVICE);
 -              req->mapped = 1;
 -      } else {
 -              dma_sync_single_for_device(ep->udc->gadget.dev.parent,
 -                                      req->req.dma, req->req.length,
 -                                      ep_is_in(ep)
 -                                              ? DMA_TO_DEVICE
 -                                              : DMA_FROM_DEVICE);
 -              req->mapped = 0;
 -      }
 +      ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
 +      if (ret)
 +              return ret;
  
        req->req.status = -EINPROGRESS;
        req->req.actual = 0;
@@@ -1265,7 -1290,6 +1265,7 @@@ static int ep0_prime_status(struct fsl_
  {
        struct fsl_req *req = udc->status_req;
        struct fsl_ep *ep;
 +      int ret;
  
        if (direction == EP_DIR_IN)
                udc->ep0_dir = USB_DIR_IN;
        req->req.complete = NULL;
        req->dtd_count = 0;
  
 -      req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
 -                      req->req.buf, req->req.length,
 -                      ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 -      req->mapped = 1;
 +      ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
 +      if (ret)
 +              return ret;
  
        if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
                fsl_queue_td(ep, req);
@@@ -1328,7 -1353,6 +1328,7 @@@ static void ch9getstatus(struct fsl_ud
        u16 tmp = 0;            /* Status, cpu endian */
        struct fsl_req *req;
        struct fsl_ep *ep;
 +      int ret;
  
        ep = &udc->eps[0];
  
        req->req.complete = NULL;
        req->dtd_count = 0;
  
 -      req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
 -                              req->req.buf, req->req.length,
 -                              ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 -      req->mapped = 1;
 +      ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
 +      if (ret)
 +              goto stall;
  
        /* prime the data phase */
        if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
@@@ -1939,6 -1964,7 +1939,6 @@@ static int fsl_udc_start(struct usb_gad
        driver->driver.bus = NULL;
        /* hook up the driver */
        udc_controller->driver = driver;
 -      udc_controller->gadget.dev.driver = &driver->driver;
        spin_unlock_irqrestore(&udc_controller->lock, flags);
  
        if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
                        if (retval < 0) {
                                ERR("can't bind to transceiver\n");
                                driver->unbind(&udc_controller->gadget);
 -                              udc_controller->gadget.dev.driver = 0;
                                udc_controller->driver = 0;
                                return retval;
                        }
@@@ -1996,6 -2023,7 +1996,6 @@@ static int fsl_udc_stop(struct usb_gadg
                nuke(loop_ep, -ESHUTDOWN);
        spin_unlock_irqrestore(&udc_controller->lock, flags);
  
 -      udc_controller->gadget.dev.driver = NULL;
        udc_controller->driver = NULL;
  
        return 0;
  
  static const char proc_filename[] = "driver/fsl_usb2_udc";
  
- static int fsl_proc_read(char *page, char **start, off_t off, int count,
-               int *eof, void *_dev)
+ static int fsl_proc_read(struct seq_file *m, void *v)
  {
-       char *buf = page;
-       char *next = buf;
-       unsigned size = count;
        unsigned long flags;
-       int t, i;
+       int i;
        u32 tmp_reg;
        struct fsl_ep *ep = NULL;
        struct fsl_req *req;
  
        struct fsl_udc *udc = udc_controller;
-       if (off != 0)
-               return 0;
  
        spin_lock_irqsave(&udc->lock, flags);
  
        /* ------basic driver information ---- */
-       t = scnprintf(next, size,
+       seq_printf(m,
                        DRIVER_DESC "\n"
                        "%s version: %s\n"
                        "Gadget driver: %s\n\n",
                        driver_name, DRIVER_VERSION,
                        udc->driver ? udc->driver->driver.name : "(none)");
-       size -= t;
-       next += t;
  
        /* ------ DR Registers ----- */
        tmp_reg = fsl_readl(&dr_regs->usbcmd);
-       t = scnprintf(next, size,
+       seq_printf(m,
                        "USBCMD reg:\n"
                        "SetupTW: %d\n"
                        "Run/Stop: %s\n\n",
                        (tmp_reg & USB_CMD_SUTW) ? 1 : 0,
                        (tmp_reg & USB_CMD_RUN_STOP) ? "Run" : "Stop");
-       size -= t;
-       next += t;
  
        tmp_reg = fsl_readl(&dr_regs->usbsts);
-       t = scnprintf(next, size,
+       seq_printf(m,
                        "USB Status Reg:\n"
                        "Dr Suspend: %d Reset Received: %d System Error: %s "
                        "USB Error Interrupt: %s\n\n",
                        (tmp_reg & USB_STS_RESET) ? 1 : 0,
                        (tmp_reg & USB_STS_SYS_ERR) ? "Err" : "Normal",
                        (tmp_reg & USB_STS_ERR) ? "Err detected" : "No err");
-       size -= t;
-       next += t;
  
        tmp_reg = fsl_readl(&dr_regs->usbintr);
-       t = scnprintf(next, size,
+       seq_printf(m,
                        "USB Interrupt Enable Reg:\n"
                        "Sleep Enable: %d SOF Received Enable: %d "
                        "Reset Enable: %d\n"
                        (tmp_reg & USB_INTR_PTC_DETECT_EN) ? 1 : 0,
                        (tmp_reg & USB_INTR_ERR_INT_EN) ? 1 : 0,
                        (tmp_reg & USB_INTR_INT_EN) ? 1 : 0);
-       size -= t;
-       next += t;
  
        tmp_reg = fsl_readl(&dr_regs->frindex);
-       t = scnprintf(next, size,
+       seq_printf(m,
                        "USB Frame Index Reg: Frame Number is 0x%x\n\n",
                        (tmp_reg & USB_FRINDEX_MASKS));
-       size -= t;
-       next += t;
  
        tmp_reg = fsl_readl(&dr_regs->deviceaddr);
-       t = scnprintf(next, size,
+       seq_printf(m,
                        "USB Device Address Reg: Device Addr is 0x%x\n\n",
                        (tmp_reg & USB_DEVICE_ADDRESS_MASK));
-       size -= t;
-       next += t;
  
        tmp_reg = fsl_readl(&dr_regs->endpointlistaddr);
-       t = scnprintf(next, size,
+       seq_printf(m,
                        "USB Endpoint List Address Reg: "
                        "Device Addr is 0x%x\n\n",
                        (tmp_reg & USB_EP_LIST_ADDRESS_MASK));
-       size -= t;
-       next += t;
  
        tmp_reg = fsl_readl(&dr_regs->portsc1);
-       t = scnprintf(next, size,
+       seq_printf(m,
                "USB Port Status&Control Reg:\n"
                "Port Transceiver Type : %s Port Speed: %s\n"
                "PHY Low Power Suspend: %s Port Reset: %s "
                "Port Enable/Disable Change: %s\n"
                "Port Enabled/Disabled: %s "
                "Current Connect Status: %s\n\n", ( {
-                       char *s;
+                       const char *s;
                        switch (tmp_reg & PORTSCX_PTS_FSLS) {
                        case PORTSCX_PTS_UTMI:
                                s = "UTMI"; break;
                "Not correct",
                (tmp_reg & PORTSCX_CURRENT_CONNECT_STATUS) ?
                "Attached" : "Not-Att");
-       size -= t;
-       next += t;
  
        tmp_reg = fsl_readl(&dr_regs->usbmode);
-       t = scnprintf(next, size,
+       seq_printf(m,
                        "USB Mode Reg: Controller Mode is: %s\n\n", ( {
-                               char *s;
+                               const char *s;
                                switch (tmp_reg & USB_MODE_CTRL_MODE_HOST) {
                                case USB_MODE_CTRL_MODE_IDLE:
                                        s = "Idle"; break;
                                }
                                s;
                        } ));
-       size -= t;
-       next += t;
  
        tmp_reg = fsl_readl(&dr_regs->endptsetupstat);
-       t = scnprintf(next, size,
+       seq_printf(m,
                        "Endpoint Setup Status Reg: SETUP on ep 0x%x\n\n",
                        (tmp_reg & EP_SETUP_STATUS_MASK));
-       size -= t;
-       next += t;
  
        for (i = 0; i < udc->max_ep / 2; i++) {
                tmp_reg = fsl_readl(&dr_regs->endptctrl[i]);
-               t = scnprintf(next, size, "EP Ctrl Reg [0x%x]: = [0x%x]\n",
-                               i, tmp_reg);
-               size -= t;
-               next += t;
+               seq_printf(m, "EP Ctrl Reg [0x%x]: = [0x%x]\n", i, tmp_reg);
        }
        tmp_reg = fsl_readl(&dr_regs->endpointprime);
-       t = scnprintf(next, size, "EP Prime Reg = [0x%x]\n\n", tmp_reg);
-       size -= t;
-       next += t;
+       seq_printf(m, "EP Prime Reg = [0x%x]\n\n", tmp_reg);
  
  #ifndef CONFIG_ARCH_MXC
        if (udc->pdata->have_sysif_regs) {
                tmp_reg = usb_sys_regs->snoop1;
-               t = scnprintf(next, size, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg);
-               size -= t;
-               next += t;
+               seq_printf(m, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg);
  
                tmp_reg = usb_sys_regs->control;
-               t = scnprintf(next, size, "General Control Reg : = [0x%x]\n\n",
-                               tmp_reg);
-               size -= t;
-               next += t;
+               seq_printf(m, "General Control Reg : = [0x%x]\n\n", tmp_reg);
        }
  #endif
  
        /* ------fsl_udc, fsl_ep, fsl_request structure information ----- */
        ep = &udc->eps[0];
-       t = scnprintf(next, size, "For %s Maxpkt is 0x%x index is 0x%x\n",
+       seq_printf(m, "For %s Maxpkt is 0x%x index is 0x%x\n",
                        ep->ep.name, ep_maxpacket(ep), ep_index(ep));
-       size -= t;
-       next += t;
  
        if (list_empty(&ep->queue)) {
-               t = scnprintf(next, size, "its req queue is empty\n\n");
-               size -= t;
-               next += t;
+               seq_puts(m, "its req queue is empty\n\n");
        } else {
                list_for_each_entry(req, &ep->queue, queue) {
-                       t = scnprintf(next, size,
+                       seq_printf(m,
                                "req %p actual 0x%x length 0x%x buf %p\n",
                                &req->req, req->req.actual,
                                req->req.length, req->req.buf);
-                       size -= t;
-                       next += t;
                }
        }
        /* other gadget->eplist ep */
        list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
                if (ep->ep.desc) {
-                       t = scnprintf(next, size,
+                       seq_printf(m,
                                        "\nFor %s Maxpkt is 0x%x "
                                        "index is 0x%x\n",
                                        ep->ep.name, ep_maxpacket(ep),
                                        ep_index(ep));
-                       size -= t;
-                       next += t;
  
                        if (list_empty(&ep->queue)) {
-                               t = scnprintf(next, size,
-                                               "its req queue is empty\n\n");
-                               size -= t;
-                               next += t;
+                               seq_puts(m, "its req queue is empty\n\n");
                        } else {
                                list_for_each_entry(req, &ep->queue, queue) {
-                                       t = scnprintf(next, size,
+                                       seq_printf(m,
                                                "req %p actual 0x%x length "
                                                "0x%x  buf %p\n",
                                                &req->req, req->req.actual,
                                                req->req.length, req->req.buf);
-                                       size -= t;
-                                       next += t;
-                                       }       /* end for each_entry of ep req */
-                               }       /* end for else */
-                       }       /* end for if(ep->queue) */
-               }               /* end (ep->desc) */
+                               }       /* end for each_entry of ep req */
+                       }       /* end for else */
+               }       /* end for if(ep->queue) */
+       }       /* end (ep->desc) */
  
        spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+ }
  
-       *eof = 1;
-       return count - size;
+ /*
+  * seq_file wrappers for procfile show routines.
+  */
+ static int fsl_proc_open(struct inode *inode, struct file *file)
+ {
+       return single_open(file, fsl_proc_read, NULL);
  }
  
- #define create_proc_file()    create_proc_read_entry(proc_filename, \
-                               0, NULL, fsl_proc_read, NULL)
+ static const struct file_operations fsl_proc_fops = {
+       .open           = fsl_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+ };
  
+ #define create_proc_file()    proc_create(proc_filename, 0, NULL, &fsl_proc_fops)
  #define remove_proc_file()    remove_proc_entry(proc_filename, NULL)
  
  #else                         /* !CONFIG_USB_GADGET_DEBUG_FILES */
@@@ -2493,7 -2483,12 +2455,7 @@@ static int __init fsl_udc_probe(struct 
  
        /* Setup gadget.dev and register with kernel */
        dev_set_name(&udc_controller->gadget.dev, "gadget");
 -      udc_controller->gadget.dev.release = fsl_udc_release;
 -      udc_controller->gadget.dev.parent = &pdev->dev;
        udc_controller->gadget.dev.of_node = pdev->dev.of_node;
 -      ret = device_register(&udc_controller->gadget.dev);
 -      if (ret < 0)
 -              goto err_free_irq;
  
        if (!IS_ERR_OR_NULL(udc_controller->transceiver))
                udc_controller->gadget.is_otg = 1;
                        DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
        if (udc_controller->td_pool == NULL) {
                ret = -ENOMEM;
 -              goto err_unregister;
 +              goto err_free_irq;
        }
  
 -      ret = usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget);
 +      ret = usb_add_gadget_udc_release(&pdev->dev, &udc_controller->gadget,
 +                      fsl_udc_release);
        if (ret)
                goto err_del_udc;
  
  
  err_del_udc:
        dma_pool_destroy(udc_controller->td_pool);
 -err_unregister:
 -      device_unregister(&udc_controller->gadget.dev);
  err_free_irq:
        free_irq(udc_controller->irq, udc_controller);
  err_iounmap:
@@@ -2588,6 -2584,7 +2550,6 @@@ static int __exit fsl_udc_remove(struc
        if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
                release_mem_region(res->start, resource_size(res));
  
 -      device_unregister(&udc_controller->gadget.dev);
        /* free udc --wait for the release() finished */
        wait_for_completion(&done);
  
@@@ -2712,7 -2709,21 +2674,7 @@@ static struct platform_driver udc_drive
        },
  };
  
 -static int __init udc_init(void)
 -{
 -      printk(KERN_INFO "%s (%s)\n", driver_desc, DRIVER_VERSION);
 -      return platform_driver_probe(&udc_driver, fsl_udc_probe);
 -}
 -
 -module_init(udc_init);
 -
 -static void __exit udc_exit(void)
 -{
 -      platform_driver_unregister(&udc_driver);
 -      printk(KERN_WARNING "%s unregistered\n", driver_desc);
 -}
 -
 -module_exit(udc_exit);
 +module_platform_driver_probe(udc_driver, fsl_udc_probe);
  
  MODULE_DESCRIPTION(DRIVER_DESC);
  MODULE_AUTHOR(DRIVER_AUTHOR);
index 991aba390d9d3e34fc967e3aeeda3e582a8eeaa3,57a547049df57a828f838892a003bf36577ceb4c..480eeb7cfd92d9a9010c804ca932da44dc17ec20
@@@ -35,6 -35,7 +35,7 @@@
  #include <linux/list.h>
  #include <linux/interrupt.h>
  #include <linux/proc_fs.h>
+ #include <linux/seq_file.h>
  #include <linux/device.h>
  #include <linux/usb/ch9.h>
  #include <linux/usb/gadget.h>
@@@ -51,6 -52,8 +52,6 @@@
  #define       DRIVER_DESC             "TC86C001 USB Device Controller"
  #define       DRIVER_VERSION          "30-Oct 2003"
  
 -#define       DMA_ADDR_INVALID        (~(dma_addr_t)0)
 -
  static const char driver_name [] = "goku_udc";
  static const char driver_desc [] = DRIVER_DESC;
  
@@@ -273,6 -276,7 +274,6 @@@ goku_alloc_request(struct usb_ep *_ep, 
        if (!req)
                return NULL;
  
 -      req->req.dma = DMA_ADDR_INVALID;
        INIT_LIST_HEAD(&req->queue);
        return &req->req;
  }
@@@ -1005,7 -1009,7 +1006,7 @@@ static const struct usb_gadget_ops goku
  
  /*-------------------------------------------------------------------------*/
  
- static inline char *dmastr(void)
+ static inline const char *dmastr(void)
  {
        if (use_dma == 0)
                return "(dma disabled)";
@@@ -1022,13 -1026,10 +1023,10 @@@ static const char proc_node_name [] = "
  #define FOURBITS "%s%s%s%s"
  #define EIGHTBITS FOURBITS FOURBITS
  
- static void
- dump_intmask(const char *label, u32 mask, char **next, unsigned *size)
+ static void dump_intmask(struct seq_file *m, const char *label, u32 mask)
  {
-       int t;
        /* int_status is the same format ... */
-       t = scnprintf(*next, *size,
+       seq_printf(m,
                "%s %05X =" FOURBITS EIGHTBITS EIGHTBITS "\n",
                label, mask,
                (mask & INT_PWRDETECT) ? " power" : "",
                (mask & INT_ENDPOINT0) ? " ep0" : "",
                (mask & INT_USBRESET) ? " reset" : "",
                (mask & INT_SUSPEND) ? " suspend" : "");
-       *size -= t;
-       *next += t;
  }
  
  
- static int
- udc_proc_read(char *buffer, char **start, off_t off, int count,
-               int *eof, void *_dev)
+ static int udc_proc_read(struct seq_file *m, void *v)
  {
-       char                            *buf = buffer;
-       struct goku_udc                 *dev = _dev;
+       struct goku_udc                 *dev = m->private;
        struct goku_udc_regs __iomem    *regs = dev->regs;
-       char                            *next = buf;
-       unsigned                        size = count;
        unsigned long                   flags;
-       int                             i, t, is_usb_connected;
+       int                             i, is_usb_connected;
        u32                             tmp;
  
-       if (off != 0)
-               return 0;
        local_irq_save(flags);
  
        /* basic device status */
        tmp = readl(&regs->power_detect);
        is_usb_connected = tmp & PW_DETECT;
-       t = scnprintf(next, size,
+       seq_printf(m,
                "%s - %s\n"
                "%s version: %s %s\n"
                "Gadget driver: %s\n"
                is_usb_connected
                        ? ((tmp & PW_PULLUP) ? "full speed" : "powered")
                        : "disconnected",
-               ({char *state;
+               ({const char *state;
                switch(dev->ep0state){
                case EP0_DISCONNECT:    state = "ep0_disconnect"; break;
                case EP0_IDLE:          state = "ep0_idle"; break;
                default:                state = "ep0_?"; break;
                } state; })
                );
-       size -= t;
-       next += t;
  
-       dump_intmask("int_status", readl(&regs->int_status), &next, &size);
-       dump_intmask("int_enable", readl(&regs->int_enable), &next, &size);
+       dump_intmask(m, "int_status", readl(&regs->int_status));
+       dump_intmask(m, "int_enable", readl(&regs->int_enable));
  
        if (!is_usb_connected || !dev->driver || (tmp & PW_PULLUP) == 0)
                goto done;
  
        /* registers for (active) device and ep0 */
-       t = scnprintf(next, size, "\nirqs %lu\ndataset %02x "
+       if (seq_printf(m, "\nirqs %lu\ndataset %02x "
                        "single.bcs %02x.%02x state %x addr %u\n",
                        dev->irqs, readl(&regs->DataSet),
                        readl(&regs->EPxSingle), readl(&regs->EPxBCS),
                        readl(&regs->UsbState),
-                       readl(&regs->address));
-       size -= t;
-       next += t;
+                       readl(&regs->address)) < 0)
+               goto done;
  
        tmp = readl(&regs->dma_master);
-       t = scnprintf(next, size,
+       if (seq_printf(m,
                "dma %03X =" EIGHTBITS "%s %s\n", tmp,
                (tmp & MST_EOPB_DIS) ? " eopb-" : "",
                (tmp & MST_EOPB_ENA) ? " eopb+" : "",
                (tmp & MST_WR_ENA) ? " OUT" : "",
                (tmp & MST_CONNECTION)
                        ? "ep1in/ep2out"
-                       : "ep1out/ep2in");
-       size -= t;
-       next += t;
+                       : "ep1out/ep2in") < 0)
+               goto done;
  
        /* dump endpoint queues */
        for (i = 0; i < 4; i++) {
                        continue;
  
                tmp = readl(ep->reg_status);
-               t = scnprintf(next, size,
+               if (seq_printf(m,
                        "%s %s max %u %s, irqs %lu, "
                        "status %02x (%s) " FOURBITS "\n",
                        ep->ep.name,
                        (tmp & EPxSTATUS_SUSPEND) ? " suspend" : "",
                        (tmp & EPxSTATUS_FIFO_DISABLE) ? " disable" : "",
                        (tmp & EPxSTATUS_STAGE_ERROR) ? " ep0stat" : ""
-                       );
-               if (t <= 0 || t > size)
+                       ) < 0)
                        goto done;
-               size -= t;
-               next += t;
  
                if (list_empty(&ep->queue)) {
-                       t = scnprintf(next, size, "\t(nothing queued)\n");
-                       if (t <= 0 || t > size)
+                       if (seq_puts(m, "\t(nothing queued)\n") < 0)
                                goto done;
-                       size -= t;
-                       next += t;
                        continue;
                }
                list_for_each_entry(req, &ep->queue, queue) {
                        } else
                                tmp = req->req.actual;
  
-                       t = scnprintf(next, size,
+                       if (seq_printf(m,
                                "\treq %p len %u/%u buf %p\n",
                                &req->req, tmp, req->req.length,
-                               req->req.buf);
-                       if (t <= 0 || t > size)
+                               req->req.buf) < 0)
                                goto done;
-                       size -= t;
-                       next += t;
                }
        }
  
  done:
        local_irq_restore(flags);
-       *eof = 1;
-       return count - size;
+       return 0;
+ }
+ /*
+  * seq_file wrappers for procfile show routines.
+  */
+ static int udc_proc_open(struct inode *inode, struct file *file)
+ {
+       return single_open(file, udc_proc_read, PDE_DATA(file_inode(file)));
  }
  
+ static const struct file_operations udc_proc_fops = {
+       .open           = udc_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+ };
  #endif        /* CONFIG_USB_GADGET_DEBUG_FILES */
  
  /*-------------------------------------------------------------------------*/
@@@ -1351,6 -1343,7 +1340,6 @@@ static int goku_udc_start(struct usb_ga
        /* hook up the driver */
        driver->driver.bus = NULL;
        dev->driver = driver;
 -      dev->gadget.dev.driver = &driver->driver;
  
        /*
         * then enable host detection and ep0; and we're ready
@@@ -1390,6 -1383,7 +1379,6 @@@ static int goku_udc_stop(struct usb_gad
        dev->driver = NULL;
        stop_activity(dev, driver);
        spin_unlock_irqrestore(&dev->lock, flags);
 -      dev->gadget.dev.driver = NULL;
  
        return 0;
  }
@@@ -1711,6 -1705,8 +1700,6 @@@ static void goku_remove(struct pci_dev 
                                pci_resource_len (pdev, 0));
        if (dev->enabled)
                pci_disable_device(pdev);
 -      if (dev->registered)
 -              device_unregister(&dev->gadget.dev);
  
        pci_set_drvdata(pdev, NULL);
        dev->regs = NULL;
@@@ -1749,6 -1745,10 +1738,6 @@@ static int goku_probe(struct pci_dev *p
        dev->gadget.max_speed = USB_SPEED_FULL;
  
        /* the "gadget" abstracts/virtualizes the controller */
 -      dev_set_name(&dev->gadget.dev, "gadget");
 -      dev->gadget.dev.parent = &pdev->dev;
 -      dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 -      dev->gadget.dev.release = gadget_release;
        dev->gadget.name = driver_name;
  
        /* now all the pci goodies ... */
  
  
  #ifdef CONFIG_USB_GADGET_DEBUG_FILES
-       create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
+       proc_create_data(proc_node_name, 0, NULL, &udc_proc_fops, dev);
  #endif
  
 -      retval = device_register(&dev->gadget.dev);
 -      if (retval) {
 -              put_device(&dev->gadget.dev);
 -              goto err;
 -      }
 -      dev->registered = 1;
 -      retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
 +      retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
 +                      gadget_release);
        if (retval)
                goto err;
  
index b943d8cdfbf75d056eb50cba2899ace0fbdb55a5,1049d3745d7af39452824f5474af6e40ce3ee147..67128be1e1b70f25b29f8cc571b1b916a9c35f2c
@@@ -565,7 -565,7 +565,7 @@@ static int proc_udc_show(struct seq_fil
  
  static int proc_udc_open(struct inode *inode, struct file *file)
  {
-       return single_open(file, proc_udc_show, PDE(inode)->data);
+       return single_open(file, proc_udc_show, PDE_DATA(inode));
  }
  
  static const struct file_operations proc_ops = {
@@@ -1469,7 -1469,23 +1469,7 @@@ static void done(struct lpc32xx_ep *ep
                status = req->req.status;
  
        if (ep->lep) {
 -              enum dma_data_direction direction;
 -
 -              if (ep->is_in)
 -                      direction = DMA_TO_DEVICE;
 -              else
 -                      direction = DMA_FROM_DEVICE;
 -
 -              if (req->mapped) {
 -                      dma_unmap_single(ep->udc->gadget.dev.parent,
 -                                      req->req.dma, req->req.length,
 -                                      direction);
 -                      req->req.dma = 0;
 -                      req->mapped = 0;
 -              } else
 -                      dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
 -                                              req->req.dma, req->req.length,
 -                                              direction);
 +              usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
  
                /* Free DDs */
                udc_dd_free(udc, req->dd_desc_ptr);
@@@ -1825,11 -1841,26 +1825,11 @@@ static int lpc32xx_ep_queue(struct usb_
        }
  
        if (ep->lep) {
 -              enum dma_data_direction direction;
                struct lpc32xx_usbd_dd_gad *dd;
  
 -              /* Map DMA pointer */
 -              if (ep->is_in)
 -                      direction = DMA_TO_DEVICE;
 -              else
 -                      direction = DMA_FROM_DEVICE;
 -
 -              if (req->req.dma == 0) {
 -                      req->req.dma = dma_map_single(
 -                              ep->udc->gadget.dev.parent,
 -                              req->req.buf, req->req.length, direction);
 -                      req->mapped = 1;
 -              } else {
 -                      dma_sync_single_for_device(
 -                              ep->udc->gadget.dev.parent, req->req.dma,
 -                              req->req.length, direction);
 -                      req->mapped = 0;
 -              }
 +              status = usb_gadget_map_request(&udc->gadget, _req, ep->is_in);
 +              if (status)
 +                      return status;
  
                /* For the request, build a list of DDs */
                dd = udc_dd_alloc(udc);
@@@ -2946,6 -2977,7 +2946,6 @@@ static int lpc32xx_start(struct usb_gad
        }
  
        udc->driver = driver;
 -      udc->gadget.dev.driver = &driver->driver;
        udc->gadget.dev.of_node = udc->dev->of_node;
        udc->enabled = 1;
        udc->selfpowered = 1;
@@@ -2994,6 -3026,7 +2994,6 @@@ static int lpc32xx_stop(struct usb_gadg
        }
  
        udc->enabled = 0;
 -      udc->gadget.dev.driver = NULL;
        udc->driver = NULL;
  
        return 0;
@@@ -3215,6 -3248,12 +3215,6 @@@ static int __init lpc32xx_udc_probe(str
        udc_disable(udc);
        udc_reinit(udc);
  
 -      retval = device_register(&udc->gadget.dev);
 -      if (retval < 0) {
 -              dev_err(udc->dev, "Device registration failure\n");
 -              goto dev_register_fail;
 -      }
 -
        /* Request IRQs - low and high priority USB device IRQs are routed to
         * the same handler, while the DMA interrupt is routed elsewhere */
        retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq,
@@@ -3281,6 -3320,8 +3281,6 @@@ irq_dev_fail
  irq_hp_fail:
        free_irq(udc->udp_irq[IRQ_USB_LP], udc);
  irq_lp_fail:
 -      device_unregister(&udc->gadget.dev);
 -dev_register_fail:
        dma_pool_destroy(udc->dd_cache);
  dma_alloc_fail:
        dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
@@@ -3335,6 -3376,8 +3335,6 @@@ static int lpc32xx_udc_remove(struct pl
        free_irq(udc->udp_irq[IRQ_USB_HP], udc);
        free_irq(udc->udp_irq[IRQ_USB_LP], udc);
  
 -      device_unregister(&udc->gadget.dev);
 -
        clk_disable(udc->usb_otg_clk);
        clk_put(udc->usb_otg_clk);
        clk_disable(udc->usb_slv_clk);
index 15ed7e8d887f6897781715ca42a0b12018e0e99a,313d0bbfff29a098dbd87bc5e088f6f7351762b7..ad4483efb6d602cad2a841d8747b5983c16fc33c
@@@ -1494,7 -1494,7 +1494,7 @@@ static int proc_sl811h_show(struct seq_
  
  static int proc_sl811h_open(struct inode *inode, struct file *file)
  {
-       return single_open(file, proc_sl811h_show, PDE(inode)->data);
+       return single_open(file, proc_sl811h_show, PDE_DATA(inode));
  }
  
  static const struct file_operations proc_ops = {
@@@ -1755,7 -1755,7 +1755,7 @@@ sl811h_probe(struct platform_device *de
  
  /* for this device there's no useful distinction between the controller
   * and its root hub, except that the root hub only gets direct PM calls
 - * when CONFIG_USB_SUSPEND is enabled.
 + * when CONFIG_PM_RUNTIME is enabled.
   */
  
  static int
index 4faa982807f237c57183c68b307851629a51c376,615c66eaedebb7f05e25f50a6c0f9c88f96a2de3..92b05d95ec5e41d70ef48383b53f045da0e42694
@@@ -313,6 -313,8 +313,6 @@@ static int queuecommand_lck(struct scsi
  {
        struct us_data *us = host_to_us(srb->device->host);
  
 -      US_DEBUGP("%s called\n", __func__);
 -
        /* check for state-transition errors */
        if (us->srb != NULL) {
                printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n",
  
        /* fail the command if we are disconnecting */
        if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
 -              US_DEBUGP("Fail command during disconnect\n");
 +              usb_stor_dbg(us, "Fail command during disconnect\n");
                srb->result = DID_NO_CONNECT << 16;
                done(srb);
                return 0;
@@@ -347,7 -349,7 +347,7 @@@ static int command_abort(struct scsi_cm
  {
        struct us_data *us = host_to_us(srb->device->host);
  
 -      US_DEBUGP("%s called\n", __func__);
 +      usb_stor_dbg(us, "%s called\n", __func__);
  
        /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
         * bits are protected by the host lock. */
        /* Is this command still active? */
        if (us->srb != srb) {
                scsi_unlock(us_to_host(us));
 -              US_DEBUGP ("-- nothing to abort\n");
 +              usb_stor_dbg(us, "-- nothing to abort\n");
                return FAILED;
        }
  
@@@ -384,7 -386,7 +384,7 @@@ static int device_reset(struct scsi_cmn
        struct us_data *us = host_to_us(srb->device->host);
        int result;
  
 -      US_DEBUGP("%s called\n", __func__);
 +      usb_stor_dbg(us, "%s called\n", __func__);
  
        /* lock the device pointers and do the reset */
        mutex_lock(&(us->dev_mutex));
@@@ -400,8 -402,7 +400,8 @@@ static int bus_reset(struct scsi_cmnd *
        struct us_data *us = host_to_us(srb->device->host);
        int result;
  
 -      US_DEBUGP("%s called\n", __func__);
 +      usb_stor_dbg(us, "%s called\n", __func__);
 +
        result = usb_stor_port_reset(us);
        return result < 0 ? FAILED : SUCCESS;
  }
@@@ -437,22 -438,21 +437,21 @@@ void usb_stor_report_bus_reset(struct u
   * /proc/scsi/ functions
   ***********************************************************************/
  
+ static int write_info(struct Scsi_Host *host, char *buffer, int length)
+ {
+       /* if someone is sending us data, just throw it away */
+       return length;
+ }
  /* we use this macro to help us write into the buffer */
  #undef SPRINTF
- #define SPRINTF(args...) \
-       do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
+ #define SPRINTF(args...) seq_printf(m, ## args)
  
- static int proc_info (struct Scsi_Host *host, char *buffer,
-               char **start, off_t offset, int length, int inout)
+ static int show_info (struct seq_file *m, struct Scsi_Host *host)
  {
        struct us_data *us = host_to_us(host);
-       char *pos = buffer;
        const char *string;
  
-       /* if someone is sending us data, just throw it away */
-       if (inout)
-               return length;
        /* print the controller name */
        SPRINTF("   Host scsi%d: usb-storage\n", host->host_no);
  
        SPRINTF("    Transport: %s\n", us->transport_name);
  
        /* show the device flags */
-       if (pos < buffer + length) {
-               pos += sprintf(pos, "       Quirks:");
+       SPRINTF("       Quirks:");
  
  #define US_FLAG(name, value) \
-       if (us->fflags & value) pos += sprintf(pos, " " #name);
+       if (us->fflags & value) seq_printf(m, " " #name);
  US_DO_ALL_FLAGS
  #undef US_FLAG
-               *(pos++) = '\n';
-       }
-       /*
-        * Calculate start of next buffer, and return value.
-        */
-       *start = buffer + offset;
-       if ((pos - buffer) < offset)
-               return (0);
-       else if ((pos - buffer - offset) < length)
-               return (pos - buffer - offset);
-       else
-               return (length);
+       seq_putc(m, '\n');
+       return 0;
  }
  
  /***********************************************************************
@@@ -548,7 -534,8 +533,8 @@@ struct scsi_host_template usb_stor_host
        /* basic userland interface stuff */
        .name =                         "usb-storage",
        .proc_name =                    "usb-storage",
-       .proc_info =                    proc_info,
+       .show_info =                    show_info,
+       .write_info =                   write_info,
        .info =                         host_info,
  
        /* command interface -- queued only */
diff --combined fs/Makefile
index f0db9c941a5f0e03269471eb1189766ca34b59f0,b691a965dc1a6c6dc3bc1860697ed24805b4335f..4fe6df3ec28fe5392b680e853b0fbfef6313179a
@@@ -7,10 -7,10 +7,10 @@@
  
  obj-y :=      open.o read_write.o file_table.o super.o \
                char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
-               ioctl.o readdir.o select.o fifo.o dcache.o inode.o \
+               ioctl.o readdir.o select.o dcache.o inode.o \
                attr.o bad_inode.o file.o filesystems.o namespace.o \
                seq_file.o xattr.o libfs.o fs-writeback.o \
 -              pnode.o drop_caches.o splice.o sync.o utimes.o \
 +              pnode.o splice.o sync.o utimes.o \
                stack.o fs_struct.o statfs.o
  
  ifeq ($(CONFIG_BLOCK),y)
@@@ -34,7 -34,10 +34,7 @@@ obj-$(CONFIG_COMPAT)         += compat.o compa
  obj-$(CONFIG_BINFMT_AOUT)     += binfmt_aout.o
  obj-$(CONFIG_BINFMT_EM86)     += binfmt_em86.o
  obj-$(CONFIG_BINFMT_MISC)     += binfmt_misc.o
 -
 -# binfmt_script is always there
 -obj-y                         += binfmt_script.o
 -
 +obj-$(CONFIG_BINFMT_SCRIPT)   += binfmt_script.o
  obj-$(CONFIG_BINFMT_ELF)      += binfmt_elf.o
  obj-$(CONFIG_COMPAT_BINFMT_ELF)       += compat_binfmt_elf.o
  obj-$(CONFIG_BINFMT_ELF_FDPIC)        += binfmt_elf_fdpic.o
@@@ -46,7 -49,6 +46,7 @@@ obj-$(CONFIG_FS_POSIX_ACL)    += posix_acl
  obj-$(CONFIG_NFS_COMMON)      += nfs_common/
  obj-$(CONFIG_GENERIC_ACL)     += generic_acl.o
  obj-$(CONFIG_COREDUMP)                += coredump.o
 +obj-$(CONFIG_SYSCTL)          += drop_caches.o
  
  obj-$(CONFIG_FHANDLE)         += fhandle.o
  
@@@ -125,4 -127,3 +125,4 @@@ obj-$(CONFIG_F2FS_FS)              += f2fs
  obj-y                         += exofs/ # Multiple modules
  obj-$(CONFIG_CEPH_FS)         += ceph/
  obj-$(CONFIG_PSTORE)          += pstore/
 +obj-$(CONFIG_EFIVAR_FS)               += efivarfs/
diff --combined fs/aio.c
index 6db8745c2edd7b8c5143531df9c9cd21e7a7dbb5,4ec28f13a92eac078bda9e468954bf1f87d75b2d..351afe7ac78ebbed1dc331716c5c2ba46c16faf2
+++ b/fs/aio.c
@@@ -1029,9 -1029,9 +1029,9 @@@ static int aio_read_evt(struct kioctx *
        spin_unlock(&info->ring_lock);
  
  out:
 -      kunmap_atomic(ring);
        dprintk("leaving aio_read_evt: %d  h%lu t%lu\n", ret,
                 (unsigned long)ring->head, (unsigned long)ring->tail);
 +      kunmap_atomic(ring);
        return ret;
  }
  
@@@ -1324,6 -1324,8 +1324,8 @@@ static ssize_t aio_rw_vect_retry(struc
        if (iocb->ki_pos < 0)
                return -EINVAL;
  
+       if (opcode == IOCB_CMD_PWRITEV)
+               file_start_write(file);
        do {
                ret = rw_op(iocb, &iocb->ki_iovec[iocb->ki_cur_seg],
                            iocb->ki_nr_segs - iocb->ki_cur_seg,
        } while (ret > 0 && iocb->ki_left > 0 &&
                 (opcode == IOCB_CMD_PWRITEV ||
                  (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode))));
+       if (opcode == IOCB_CMD_PWRITEV)
+               file_end_write(file);
  
        /* This means we must have transferred all that we could */
        /* No need to retry anymore */
@@@ -1790,5 -1794,7 +1794,5 @@@ SYSCALL_DEFINE5(io_getevents, aio_conte
                        ret = read_events(ioctx, min_nr, nr, events, timeout);
                put_ioctx(ioctx);
        }
 -
 -      asmlinkage_protect(5, ret, ctx_id, min_nr, nr, events, timeout);
        return ret;
  }
diff --combined fs/binfmt_aout.c
index 02fe378fc506218e980e3e016132718e88fadd63,b23253df87568b783fcbea09110fb138ee57fa8f..bce87694f7b022b15ca92904d0a6b44875d1ad84
@@@ -62,6 -62,7 +62,6 @@@ static int aout_core_dump(struct coredu
        fs = get_fs();
        set_fs(KERNEL_DS);
        has_dumped = 1;
 -      current->flags |= PF_DUMPCORE;
                strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm));
        dump.u_ar0 = offsetof(struct user, regs);
        dump.signal = cprm->siginfo->si_signo;
@@@ -286,15 -287,12 +286,12 @@@ static int load_aout_binary(struct linu
                        return error;
                }
  
-               error = bprm->file->f_op->read(bprm->file,
-                         (char __user *)text_addr,
-                         ex.a_text+ex.a_data, &pos);
+               error = read_code(bprm->file, text_addr, pos,
+                                 ex.a_text+ex.a_data);
                if ((signed long)error < 0) {
                        send_sig(SIGKILL, current, 0);
                        return error;
                }
-                        
-               flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
        } else {
                if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
                    (N_MAGIC(ex) != NMAGIC) && printk_ratelimit())
                }
  
                if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
-                       loff_t pos = fd_offset;
                        vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
-                       bprm->file->f_op->read(bprm->file,
-                                       (char __user *)N_TXTADDR(ex),
-                                       ex.a_text+ex.a_data, &pos);
-                       flush_icache_range((unsigned long) N_TXTADDR(ex),
-                                          (unsigned long) N_TXTADDR(ex) +
-                                          ex.a_text+ex.a_data);
+                       read_code(bprm->file, N_TXTADDR(ex), fd_offset,
+                                 ex.a_text + ex.a_data);
                        goto beyond_if;
                }
  
@@@ -396,8 -389,6 +388,6 @@@ static int load_aout_library(struct fil
        start_addr =  ex.a_entry & 0xfffff000;
  
        if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
-               loff_t pos = N_TXTOFF(ex);
                if (printk_ratelimit())
                {
                        printk(KERN_WARNING 
                }
                vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
                
-               file->f_op->read(file, (char __user *)start_addr,
-                       ex.a_text + ex.a_data, &pos);
-               flush_icache_range((unsigned long) start_addr,
-                                  (unsigned long) start_addr + ex.a_text + ex.a_data);
+               read_code(file, start_addr, N_TXTOFF(ex),
+                         ex.a_text + ex.a_data);
                retval = 0;
                goto out;
        }
diff --combined fs/binfmt_elf_fdpic.c
index c1cc06aed601a791a6d46ca5d0ffcae18cecec06,2711d990163241a973e2443d7c9e0a9be0cd94ae..9dac212fc6f9e1c90459d407c5f2d3def019df3f
@@@ -926,7 -926,6 +926,6 @@@ static int elf_fdpic_map_file_constdisp
        struct elf32_fdpic_loadseg *seg;
        struct elf32_phdr *phdr;
        unsigned long load_addr, base = ULONG_MAX, top = 0, maddr = 0, mflags;
-       loff_t fpos;
        int loop, ret;
  
        load_addr = params->load_addr;
                if (params->phdrs[loop].p_type != PT_LOAD)
                        continue;
  
-               fpos = phdr->p_offset;
                seg->addr = maddr + (phdr->p_vaddr - base);
                seg->p_vaddr = phdr->p_vaddr;
                seg->p_memsz = phdr->p_memsz;
  
-               ret = file->f_op->read(file, (void *) seg->addr,
-                                      phdr->p_filesz, &fpos);
+               ret = read_code(file, seg->addr, phdr->p_offset,
+                                      phdr->p_filesz);
                if (ret < 0)
                        return ret;
  
@@@ -1687,6 -1684,8 +1684,6 @@@ static int elf_fdpic_core_dump(struct c
        fill_elf_fdpic_header(elf, e_phnum);
  
        has_dumped = 1;
 -      current->flags |= PF_DUMPCORE;
 -
        /*
         * Set up the notes in similar form to SVR4 core dumps made
         * with info from their /proc.
diff --combined fs/btrfs/file.c
index ade03e6f7bd2706bbaac3406f1bcc31cf70cb578,254aeb72915ff5ba16ff1bc5460f03da8a06da73..bb8b7a0e28a6b80bd5907f02233ec9c831723912
@@@ -1514,8 -1514,6 +1514,6 @@@ static ssize_t btrfs_file_aio_write(str
        size_t count, ocount;
        bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host);
  
-       sb_start_write(inode->i_sb);
        mutex_lock(&inode->i_mutex);
  
        err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
        if (sync)
                atomic_dec(&BTRFS_I(inode)->sync_writers);
  out:
-       sb_end_write(inode->i_sb);
        current->backing_dev_info = NULL;
        return num_written ? num_written : err;
  }
@@@ -2142,7 -2139,6 +2139,7 @@@ static long btrfs_fallocate(struct fil
  {
        struct inode *inode = file_inode(file);
        struct extent_state *cached_state = NULL;
 +      struct btrfs_root *root = BTRFS_I(inode)->root;
        u64 cur_offset;
        u64 last_byte;
        u64 alloc_start;
        ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start);
        if (ret)
                return ret;
 +      if (root->fs_info->quota_enabled) {
 +              ret = btrfs_qgroup_reserve(root, alloc_end - alloc_start);
 +              if (ret)
 +                      goto out_reserve_fail;
 +      }
  
        /*
         * wait for ordered IO before we have any locks.  We'll loop again
                             &cached_state, GFP_NOFS);
  out:
        mutex_unlock(&inode->i_mutex);
 +      if (root->fs_info->quota_enabled)
 +              btrfs_qgroup_free(root, alloc_end - alloc_start);
 +out_reserve_fail:
        /* Let go of our reservation. */
        btrfs_free_reserved_data_space(inode, alloc_end - alloc_start);
        return ret;
diff --combined fs/compat.c
index 5f83ffa421154c862fb1fbc0a649f77b1a6b9558,5058345dc27975931f280b8660a78281793ea171..d0560c93973d90a76f81a8ecb5d5b10a76a19d69
@@@ -44,6 -44,7 +44,6 @@@
  #include <linux/signal.h>
  #include <linux/poll.h>
  #include <linux/mm.h>
 -#include <linux/eventpoll.h>
  #include <linux/fs_struct.h>
  #include <linux/slab.h>
  #include <linux/pagemap.h>
@@@ -1068,190 -1069,26 +1068,6 @@@ asmlinkage long compat_sys_getdents64(u
  }
  #endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */
  
- static ssize_t compat_do_readv_writev(int type, struct file *file,
-                              const struct compat_iovec __user *uvector,
-                              unsigned long nr_segs, loff_t *pos)
- {
-       compat_ssize_t tot_len;
-       struct iovec iovstack[UIO_FASTIOV];
-       struct iovec *iov = iovstack;
-       ssize_t ret;
-       io_fn_t fn;
-       iov_fn_t fnv;
-       ret = -EINVAL;
-       if (!file->f_op)
-               goto out;
-       ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
-                                              UIO_FASTIOV, iovstack, &iov);
-       if (ret <= 0)
-               goto out;
-       tot_len = ret;
-       ret = rw_verify_area(type, file, pos, tot_len);
-       if (ret < 0)
-               goto out;
-       fnv = NULL;
-       if (type == READ) {
-               fn = file->f_op->read;
-               fnv = file->f_op->aio_read;
-       } else {
-               fn = (io_fn_t)file->f_op->write;
-               fnv = file->f_op->aio_write;
-       }
-       if (fnv)
-               ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
-                                               pos, fnv);
-       else
-               ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
- out:
-       if (iov != iovstack)
-               kfree(iov);
-       if ((ret + (type == READ)) > 0) {
-               if (type == READ)
-                       fsnotify_access(file);
-               else
-                       fsnotify_modify(file);
-       }
-       return ret;
- }
- static size_t compat_readv(struct file *file,
-                          const struct compat_iovec __user *vec,
-                          unsigned long vlen, loff_t *pos)
- {
-       ssize_t ret = -EBADF;
-       if (!(file->f_mode & FMODE_READ))
-               goto out;
-       ret = -EINVAL;
-       if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
-               goto out;
-       ret = compat_do_readv_writev(READ, file, vec, vlen, pos);
- out:
-       if (ret > 0)
-               add_rchar(current, ret);
-       inc_syscr(current);
-       return ret;
- }
- asmlinkage ssize_t
- compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,
-                unsigned long vlen)
- {
-       struct fd f = fdget(fd);
-       ssize_t ret;
-       loff_t pos;
-       if (!f.file)
-               return -EBADF;
-       pos = f.file->f_pos;
-       ret = compat_readv(f.file, vec, vlen, &pos);
-       f.file->f_pos = pos;
-       fdput(f);
-       return ret;
- }
- asmlinkage ssize_t
- compat_sys_preadv64(unsigned long fd, const struct compat_iovec __user *vec,
-                   unsigned long vlen, loff_t pos)
- {
-       struct fd f;
-       ssize_t ret;
-       if (pos < 0)
-               return -EINVAL;
-       f = fdget(fd);
-       if (!f.file)
-               return -EBADF;
-       ret = -ESPIPE;
-       if (f.file->f_mode & FMODE_PREAD)
-               ret = compat_readv(f.file, vec, vlen, &pos);
-       fdput(f);
-       return ret;
- }
- asmlinkage ssize_t
- compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec,
-                 unsigned long vlen, u32 pos_low, u32 pos_high)
- {
-       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
-       return compat_sys_preadv64(fd, vec, vlen, pos);
- }
- static size_t compat_writev(struct file *file,
-                           const struct compat_iovec __user *vec,
-                           unsigned long vlen, loff_t *pos)
- {
-       ssize_t ret = -EBADF;
-       if (!(file->f_mode & FMODE_WRITE))
-               goto out;
-       ret = -EINVAL;
-       if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
-               goto out;
-       ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos);
- out:
-       if (ret > 0)
-               add_wchar(current, ret);
-       inc_syscw(current);
-       return ret;
- }
- asmlinkage ssize_t
- compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec,
-                 unsigned long vlen)
- {
-       struct fd f = fdget(fd);
-       ssize_t ret;
-       loff_t pos;
-       if (!f.file)
-               return -EBADF;
-       pos = f.file->f_pos;
-       ret = compat_writev(f.file, vec, vlen, &pos);
-       f.file->f_pos = pos;
-       fdput(f);
-       return ret;
- }
- asmlinkage ssize_t
- compat_sys_pwritev64(unsigned long fd, const struct compat_iovec __user *vec,
-                    unsigned long vlen, loff_t pos)
 -asmlinkage long
 -compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32,
 -                  unsigned int nr_segs, unsigned int flags)
--{
-       struct fd f;
-       ssize_t ret;
-       if (pos < 0)
 -      unsigned i;
 -      struct iovec __user *iov;
 -      if (nr_segs > UIO_MAXIOV)
--              return -EINVAL;
-       f = fdget(fd);
-       if (!f.file)
-               return -EBADF;
-       ret = -ESPIPE;
-       if (f.file->f_mode & FMODE_PWRITE)
-               ret = compat_writev(f.file, vec, vlen, &pos);
-       fdput(f);
-       return ret;
- }
- asmlinkage ssize_t
- compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec,
-                  unsigned long vlen, u32 pos_low, u32 pos_high)
- {
-       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
-       return compat_sys_pwritev64(fd, vec, vlen, pos);
 -      iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
 -      for (i = 0; i < nr_segs; i++) {
 -              struct compat_iovec v;
 -              if (get_user(v.iov_base, &iov32[i].iov_base) ||
 -                  get_user(v.iov_len, &iov32[i].iov_len) ||
 -                  put_user(compat_ptr(v.iov_base), &iov[i].iov_base) ||
 -                  put_user(v.iov_len, &iov[i].iov_len))
 -                      return -EFAULT;
 -      }
 -      return sys_vmsplice(fd, iov, nr_segs, flags);
--}
--
  /*
   * Exactly like fs/open.c:sys_open(), except that it doesn't set the
   * O_LARGEFILE flag.
@@@ -1637,6 -1474,84 +1453,6 @@@ asmlinkage long compat_sys_ppoll(struc
        return ret;
  }
  
 -#ifdef CONFIG_EPOLL
 -
 -asmlinkage long compat_sys_epoll_pwait(int epfd,
 -                      struct compat_epoll_event __user *events,
 -                      int maxevents, int timeout,
 -                      const compat_sigset_t __user *sigmask,
 -                      compat_size_t sigsetsize)
 -{
 -      long err;
 -      compat_sigset_t csigmask;
 -      sigset_t ksigmask, sigsaved;
 -
 -      /*
 -       * If the caller wants a certain signal mask to be set during the wait,
 -       * we apply it here.
 -       */
 -      if (sigmask) {
 -              if (sigsetsize != sizeof(compat_sigset_t))
 -                      return -EINVAL;
 -              if (copy_from_user(&csigmask, sigmask, sizeof(csigmask)))
 -                      return -EFAULT;
 -              sigset_from_compat(&ksigmask, &csigmask);
 -              sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
 -              sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
 -      }
 -
 -      err = sys_epoll_wait(epfd, events, maxevents, timeout);
 -
 -      /*
 -       * If we changed the signal mask, we need to restore the original one.
 -       * In case we've got a signal while waiting, we do not restore the
 -       * signal mask yet, and we allow do_signal() to deliver the signal on
 -       * the way back to userspace, before the signal mask is restored.
 -       */
 -      if (sigmask) {
 -              if (err == -EINTR) {
 -                      memcpy(&current->saved_sigmask, &sigsaved,
 -                             sizeof(sigsaved));
 -                      set_restore_sigmask();
 -              } else
 -                      sigprocmask(SIG_SETMASK, &sigsaved, NULL);
 -      }
 -
 -      return err;
 -}
 -
 -#endif /* CONFIG_EPOLL */
 -
 -#ifdef CONFIG_SIGNALFD
 -
 -asmlinkage long compat_sys_signalfd4(int ufd,
 -                                   const compat_sigset_t __user *sigmask,
 -                                   compat_size_t sigsetsize, int flags)
 -{
 -      compat_sigset_t ss32;
 -      sigset_t tmp;
 -      sigset_t __user *ksigmask;
 -
 -      if (sigsetsize != sizeof(compat_sigset_t))
 -              return -EINVAL;
 -      if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
 -              return -EFAULT;
 -      sigset_from_compat(&tmp, &ss32);
 -      ksigmask = compat_alloc_user_space(sizeof(sigset_t));
 -      if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
 -              return -EFAULT;
 -
 -      return sys_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags);
 -}
 -
 -asmlinkage long compat_sys_signalfd(int ufd,
 -                                  const compat_sigset_t __user *sigmask,
 -                                  compat_size_t sigsetsize)
 -{
 -      return compat_sys_signalfd4(ufd, sigmask, sigsetsize, 0);
 -}
 -#endif /* CONFIG_SIGNALFD */
 -
  #ifdef CONFIG_FHANDLE
  /*
   * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
@@@ -1648,3 -1563,25 +1464,3 @@@ COMPAT_SYSCALL_DEFINE3(open_by_handle_a
        return do_handle_open(mountdirfd, handle, flags);
  }
  #endif
 -
 -#ifdef __ARCH_WANT_COMPAT_SYS_SENDFILE
 -asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
 -                                  compat_off_t __user *offset, compat_size_t count)
 -{
 -      loff_t pos;
 -      off_t off;
 -      ssize_t ret;
 -
 -      if (offset) {
 -              if (unlikely(get_user(off, offset)))
 -                      return -EFAULT;
 -              pos = off;
 -              ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
 -              if (unlikely(put_user(pos, offset)))
 -                      return -EFAULT;
 -              return ret;
 -      }
 -
 -      return do_sendfile(out_fd, in_fd, NULL, count, 0);
 -}
 -#endif /* __ARCH_WANT_COMPAT_SYS_SENDFILE */
diff --combined fs/coredump.c
index ec306cc9a28acf6804ea8b974ddf445f25450109,a987f3d39d93cbc1b0fe82d8cd08ad6bb2898226..a9abe313e8d5a48622bd3328787db8c099bee942
@@@ -263,6 -263,7 +263,6 @@@ static int zap_process(struct task_stru
        struct task_struct *t;
        int nr = 0;
  
 -      start->signal->flags = SIGNAL_GROUP_EXIT;
        start->signal->group_exit_code = exit_code;
        start->signal->group_stop_count = 0;
  
        return nr;
  }
  
 -static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
 -                              struct core_state *core_state, int exit_code)
 +static int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
 +                      struct core_state *core_state, int exit_code)
  {
        struct task_struct *g, *p;
        unsigned long flags;
        if (!signal_group_exit(tsk->signal)) {
                mm->core_state = core_state;
                nr = zap_process(tsk, exit_code);
 +              tsk->signal->group_exit_task = tsk;
 +              /* ignore all signals except SIGKILL, see prepare_signal() */
 +              tsk->signal->flags = SIGNAL_GROUP_COREDUMP;
 +              clear_tsk_thread_flag(tsk, TIF_SIGPENDING);
        }
        spin_unlock_irq(&tsk->sighand->siglock);
        if (unlikely(nr < 0))
                return nr;
  
 +      tsk->flags = PF_DUMPCORE;
        if (atomic_read(&mm->mm_users) == nr + 1)
                goto done;
        /*
                                if (unlikely(p->mm == mm)) {
                                        lock_task_sighand(p, &flags);
                                        nr += zap_process(p, exit_code);
 +                                      p->signal->flags = SIGNAL_GROUP_EXIT;
                                        unlock_task_sighand(p, &flags);
                                }
                                break;
@@@ -391,18 -386,11 +391,18 @@@ static int coredump_wait(int exit_code
        return core_waiters;
  }
  
 -static void coredump_finish(struct mm_struct *mm)
 +static void coredump_finish(struct mm_struct *mm, bool core_dumped)
  {
        struct core_thread *curr, *next;
        struct task_struct *task;
  
 +      spin_lock_irq(&current->sighand->siglock);
 +      if (core_dumped && !__fatal_signal_pending(current))
 +              current->signal->group_exit_code |= 0x80;
 +      current->signal->group_exit_task = NULL;
 +      current->signal->flags = SIGNAL_GROUP_EXIT;
 +      spin_unlock_irq(&current->sighand->siglock);
 +
        next = mm->core_state->dumper.next;
        while ((curr = next) != NULL) {
                next = curr->next;
        mm->core_state = NULL;
  }
  
 +static bool dump_interrupted(void)
 +{
 +      /*
 +       * SIGKILL or freezing() interrupt the coredumping. Perhaps we
 +       * can do try_to_freeze() and check __fatal_signal_pending(),
 +       * but then we need to teach dump_write() to restart and clear
 +       * TIF_SIGPENDING.
 +       */
 +      return signal_pending(current);
 +}
 +
  static void wait_for_dump_helpers(struct file *file)
  {
-       struct pipe_inode_info *pipe;
-       pipe = file_inode(file)->i_pipe;
+       struct pipe_inode_info *pipe = file->private_data;
  
        pipe_lock(pipe);
        pipe->readers++;
        pipe->writers--;
 +      wake_up_interruptible_sync(&pipe->wait);
 +      kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
 +      pipe_unlock(pipe);
  
 -      while ((pipe->readers > 1) && (!signal_pending(current))) {
 -              wake_up_interruptible_sync(&pipe->wait);
 -              kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
 -              pipe_wait(pipe);
 -      }
 +      /*
 +       * We actually want wait_event_freezable() but then we need
 +       * to clear TIF_SIGPENDING and improve dump_interrupted().
 +       */
 +      wait_event_interruptible(pipe->wait, pipe->readers == 1);
  
 +      pipe_lock(pipe);
        pipe->readers--;
        pipe->writers++;
        pipe_unlock(pipe);
 -
  }
  
  /*
@@@ -497,7 -469,6 +495,7 @@@ void do_coredump(siginfo_t *siginfo
        int ispipe;
        struct files_struct *displaced;
        bool need_nonrelative = false;
 +      bool core_dumped = false;
        static atomic_t core_dump_count = ATOMIC_INIT(0);
        struct coredump_params cprm = {
                .siginfo = siginfo,
  
        old_cred = override_creds(cred);
  
 -      /*
 -       * Clear any false indication of pending signals that might
 -       * be seen by the filesystem code called to write the core file.
 -       */
 -      clear_thread_flag(TIF_SIGPENDING);
 -
        ispipe = format_corename(&cn, &cprm);
  
 -      if (ispipe) {
 +      if (ispipe) {
                int dump_count;
                char **helper_argv;
 +              struct subprocess_info *sub_info;
  
                if (ispipe < 0) {
                        printk(KERN_WARNING "format_corename failed\n");
                        goto fail_dropcount;
                }
  
 -              retval = call_usermodehelper_fns(helper_argv[0], helper_argv,
 -                                      NULL, UMH_WAIT_EXEC, umh_pipe_setup,
 -                                      NULL, &cprm);
 +              retval = -ENOMEM;
 +              sub_info = call_usermodehelper_setup(helper_argv[0],
 +                                              helper_argv, NULL, GFP_KERNEL,
 +                                              umh_pipe_setup, NULL, &cprm);
 +              if (sub_info)
 +                      retval = call_usermodehelper_exec(sub_info,
 +                                                        UMH_WAIT_EXEC);
 +
                argv_free(helper_argv);
                if (retval) {
 -                      printk(KERN_INFO "Core dump to %s pipe failed\n",
 +                      printk(KERN_INFO "Core dump to %s pipe failed\n",
                               cn.corename);
                        goto close_fail;
 -              }
 +              }
        } else {
                struct inode *inode;
  
                goto close_fail;
        if (displaced)
                put_files_struct(displaced);
 -      retval = binfmt->core_dump(&cprm);
 -      if (retval)
 -              current->signal->group_exit_code |= 0x80;
+       file_start_write(cprm.file);
 +      core_dumped = !dump_interrupted() && binfmt->core_dump(&cprm);
+       file_end_write(cprm.file);
  
        if (ispipe && core_pipe_limit)
                wait_for_dump_helpers(cprm.file);
@@@ -669,7 -644,7 +669,7 @@@ fail_dropcount
  fail_unlock:
        kfree(cn.corename);
  fail_corename:
 -      coredump_finish(mm);
 +      coredump_finish(mm, core_dumped);
        revert_creds(old_cred);
  fail_creds:
        put_cred(cred);
@@@ -684,9 -659,7 +684,9 @@@ fail
   */
  int dump_write(struct file *file, const void *addr, int nr)
  {
 -      return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr;
 +      return !dump_interrupted() &&
 +              access_ok(VERIFY_READ, addr, nr) &&
 +              file->f_op->write(file, addr, nr, &file->f_pos) == nr;
  }
  EXPORT_SYMBOL(dump_write);
  
@@@ -695,8 -668,7 +695,8 @@@ int dump_seek(struct file *file, loff_
        int ret = 1;
  
        if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
 -              if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
 +              if (dump_interrupted() ||
 +                  file->f_op->llseek(file, off, SEEK_CUR) < 0)
                        return 0;
        } else {
                char *buf = (char *)get_zeroed_page(GFP_KERNEL);
diff --combined fs/efivarfs/file.c
index ede07fc7309f8b16ab0a69941d5391d394a27550,0000000000000000000000000000000000000000..bfb531564319608be19b63885142eb6b5c7648d9
mode 100644,000000..100644
--- /dev/null
@@@ -1,105 -1,0 +1,106 @@@
 +/*
 + * Copyright (C) 2012 Red Hat, Inc.
 + * Copyright (C) 2012 Jeremy Kerr <jeremy.kerr@canonical.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/efi.h>
 +#include <linux/fs.h>
++#include <linux/slab.h>
 +
 +#include "internal.h"
 +
 +static ssize_t efivarfs_file_write(struct file *file,
 +              const char __user *userbuf, size_t count, loff_t *ppos)
 +{
 +      struct efivar_entry *var = file->private_data;
 +      void *data;
 +      u32 attributes;
 +      struct inode *inode = file->f_mapping->host;
 +      unsigned long datasize = count - sizeof(attributes);
 +      ssize_t bytes = 0;
 +      bool set = false;
 +
 +      if (count < sizeof(attributes))
 +              return -EINVAL;
 +
 +      if (copy_from_user(&attributes, userbuf, sizeof(attributes)))
 +              return -EFAULT;
 +
 +      if (attributes & ~(EFI_VARIABLE_MASK))
 +              return -EINVAL;
 +
 +      data = kmalloc(datasize, GFP_KERNEL);
 +      if (!data)
 +              return -ENOMEM;
 +
 +      if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) {
 +              bytes = -EFAULT;
 +              goto out;
 +      }
 +
 +      bytes = efivar_entry_set_get_size(var, attributes, &datasize,
 +                                        data, &set);
 +      if (!set && bytes)
 +              goto out;
 +
 +      if (bytes == -ENOENT) {
 +              drop_nlink(inode);
 +              d_delete(file->f_dentry);
 +              dput(file->f_dentry);
 +      } else {
 +              mutex_lock(&inode->i_mutex);
 +              i_size_write(inode, datasize + sizeof(attributes));
 +              mutex_unlock(&inode->i_mutex);
 +      }
 +
 +      bytes = count;
 +
 +out:
 +      kfree(data);
 +
 +      return bytes;
 +}
 +
 +static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
 +              size_t count, loff_t *ppos)
 +{
 +      struct efivar_entry *var = file->private_data;
 +      unsigned long datasize = 0;
 +      u32 attributes;
 +      void *data;
 +      ssize_t size = 0;
 +      int err;
 +
 +      err = efivar_entry_size(var, &datasize);
 +      if (err)
 +              return err;
 +
 +      data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL);
 +
 +      if (!data)
 +              return -ENOMEM;
 +
 +      size = efivar_entry_get(var, &attributes, &datasize,
 +                              data + sizeof(attributes));
 +      if (size)
 +              goto out_free;
 +
 +      memcpy(data, &attributes, sizeof(attributes));
 +      size = simple_read_from_buffer(userbuf, count, ppos,
 +                                     data, datasize + sizeof(attributes));
 +out_free:
 +      kfree(data);
 +
 +      return size;
 +}
 +
 +const struct file_operations efivarfs_file_operations = {
 +      .open   = simple_open,
 +      .read   = efivarfs_file_read,
 +      .write  = efivarfs_file_write,
 +      .llseek = no_llseek,
 +};
diff --combined fs/efivarfs/inode.c
index 640e289d522e460a007f730cc481993140c06e5f,0000000000000000000000000000000000000000..7e787fb90293ecd920998d37f227533bab371833
mode 100644,000000..100644
--- /dev/null
@@@ -1,173 -1,0 +1,174 @@@
 +/*
 + * Copyright (C) 2012 Red Hat, Inc.
 + * Copyright (C) 2012 Jeremy Kerr <jeremy.kerr@canonical.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/efi.h>
 +#include <linux/fs.h>
 +#include <linux/ctype.h>
++#include <linux/slab.h>
 +
 +#include "internal.h"
 +
 +struct inode *efivarfs_get_inode(struct super_block *sb,
 +                              const struct inode *dir, int mode, dev_t dev)
 +{
 +      struct inode *inode = new_inode(sb);
 +
 +      if (inode) {
 +              inode->i_ino = get_next_ino();
 +              inode->i_mode = mode;
 +              inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 +              switch (mode & S_IFMT) {
 +              case S_IFREG:
 +                      inode->i_fop = &efivarfs_file_operations;
 +                      break;
 +              case S_IFDIR:
 +                      inode->i_op = &efivarfs_dir_inode_operations;
 +                      inode->i_fop = &simple_dir_operations;
 +                      inc_nlink(inode);
 +                      break;
 +              }
 +      }
 +      return inode;
 +}
 +
 +/*
 + * Return true if 'str' is a valid efivarfs filename of the form,
 + *
 + *    VariableName-12345678-1234-1234-1234-1234567891bc
 + */
 +bool efivarfs_valid_name(const char *str, int len)
 +{
 +      static const char dashes[EFI_VARIABLE_GUID_LEN] = {
 +              [8] = 1, [13] = 1, [18] = 1, [23] = 1
 +      };
 +      const char *s = str + len - EFI_VARIABLE_GUID_LEN;
 +      int i;
 +
 +      /*
 +       * We need a GUID, plus at least one letter for the variable name,
 +       * plus the '-' separator
 +       */
 +      if (len < EFI_VARIABLE_GUID_LEN + 2)
 +              return false;
 +
 +      /* GUID must be preceded by a '-' */
 +      if (*(s - 1) != '-')
 +              return false;
 +
 +      /*
 +       * Validate that 's' is of the correct format, e.g.
 +       *
 +       *      12345678-1234-1234-1234-123456789abc
 +       */
 +      for (i = 0; i < EFI_VARIABLE_GUID_LEN; i++) {
 +              if (dashes[i]) {
 +                      if (*s++ != '-')
 +                              return false;
 +              } else {
 +                      if (!isxdigit(*s++))
 +                              return false;
 +              }
 +      }
 +
 +      return true;
 +}
 +
 +static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid)
 +{
 +      guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]);
 +      guid->b[1] = hex_to_bin(str[4]) << 4 | hex_to_bin(str[5]);
 +      guid->b[2] = hex_to_bin(str[2]) << 4 | hex_to_bin(str[3]);
 +      guid->b[3] = hex_to_bin(str[0]) << 4 | hex_to_bin(str[1]);
 +      guid->b[4] = hex_to_bin(str[11]) << 4 | hex_to_bin(str[12]);
 +      guid->b[5] = hex_to_bin(str[9]) << 4 | hex_to_bin(str[10]);
 +      guid->b[6] = hex_to_bin(str[16]) << 4 | hex_to_bin(str[17]);
 +      guid->b[7] = hex_to_bin(str[14]) << 4 | hex_to_bin(str[15]);
 +      guid->b[8] = hex_to_bin(str[19]) << 4 | hex_to_bin(str[20]);
 +      guid->b[9] = hex_to_bin(str[21]) << 4 | hex_to_bin(str[22]);
 +      guid->b[10] = hex_to_bin(str[24]) << 4 | hex_to_bin(str[25]);
 +      guid->b[11] = hex_to_bin(str[26]) << 4 | hex_to_bin(str[27]);
 +      guid->b[12] = hex_to_bin(str[28]) << 4 | hex_to_bin(str[29]);
 +      guid->b[13] = hex_to_bin(str[30]) << 4 | hex_to_bin(str[31]);
 +      guid->b[14] = hex_to_bin(str[32]) << 4 | hex_to_bin(str[33]);
 +      guid->b[15] = hex_to_bin(str[34]) << 4 | hex_to_bin(str[35]);
 +}
 +
 +static int efivarfs_create(struct inode *dir, struct dentry *dentry,
 +                        umode_t mode, bool excl)
 +{
 +      struct inode *inode;
 +      struct efivar_entry *var;
 +      int namelen, i = 0, err = 0;
 +
 +      if (!efivarfs_valid_name(dentry->d_name.name, dentry->d_name.len))
 +              return -EINVAL;
 +
 +      inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
 +      if (!inode)
 +              return -ENOMEM;
 +
 +      var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
 +      if (!var) {
 +              err = -ENOMEM;
 +              goto out;
 +      }
 +
 +      /* length of the variable name itself: remove GUID and separator */
 +      namelen = dentry->d_name.len - EFI_VARIABLE_GUID_LEN - 1;
 +
 +      efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1,
 +                      &var->var.VendorGuid);
 +
 +      for (i = 0; i < namelen; i++)
 +              var->var.VariableName[i] = dentry->d_name.name[i];
 +
 +      var->var.VariableName[i] = '\0';
 +
 +      inode->i_private = var;
 +
 +      efivar_entry_add(var, &efivarfs_list);
 +      d_instantiate(dentry, inode);
 +      dget(dentry);
 +out:
 +      if (err) {
 +              kfree(var);
 +              iput(inode);
 +      }
 +      return err;
 +}
 +
 +static int efivarfs_unlink(struct inode *dir, struct dentry *dentry)
 +{
 +      struct efivar_entry *var = dentry->d_inode->i_private;
 +
 +      if (efivar_entry_delete(var))
 +              return -EINVAL;
 +
 +      drop_nlink(dentry->d_inode);
 +      dput(dentry);
 +      return 0;
 +};
 +
 +/*
 + * Handle negative dentry.
 + */
 +static struct dentry *efivarfs_lookup(struct inode *dir, struct dentry *dentry,
 +                                    unsigned int flags)
 +{
 +      if (dentry->d_name.len > NAME_MAX)
 +              return ERR_PTR(-ENAMETOOLONG);
 +      d_add(dentry, NULL);
 +      return NULL;
 +}
 +
 +const struct inode_operations efivarfs_dir_inode_operations = {
 +      .lookup = efivarfs_lookup,
 +      .unlink = efivarfs_unlink,
 +      .create = efivarfs_create,
 +};
diff --combined fs/efivarfs/super.c
index 525a2a1ac16c965cd64efb174f387094cbca36de,0000000000000000000000000000000000000000..141aee31884fffd06c7903b442ebbd7a03c6a704
mode 100644,000000..100644
--- /dev/null
@@@ -1,268 -1,0 +1,270 @@@
 +/*
 + * Copyright (C) 2012 Red Hat, Inc.
 + * Copyright (C) 2012 Jeremy Kerr <jeremy.kerr@canonical.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/ctype.h>
 +#include <linux/efi.h>
 +#include <linux/fs.h>
 +#include <linux/module.h>
 +#include <linux/pagemap.h>
 +#include <linux/ucs2_string.h>
++#include <linux/slab.h>
++#include <linux/magic.h>
 +
 +#include "internal.h"
 +
 +LIST_HEAD(efivarfs_list);
 +
 +static void efivarfs_evict_inode(struct inode *inode)
 +{
 +      clear_inode(inode);
 +}
 +
 +static const struct super_operations efivarfs_ops = {
 +      .statfs = simple_statfs,
 +      .drop_inode = generic_delete_inode,
 +      .evict_inode = efivarfs_evict_inode,
 +      .show_options = generic_show_options,
 +};
 +
 +static struct super_block *efivarfs_sb;
 +
 +/*
 + * Compare two efivarfs file names.
 + *
 + * An efivarfs filename is composed of two parts,
 + *
 + *    1. A case-sensitive variable name
 + *    2. A case-insensitive GUID
 + *
 + * So we need to perform a case-sensitive match on part 1 and a
 + * case-insensitive match on part 2.
 + */
 +static int efivarfs_d_compare(const struct dentry *parent, const struct inode *pinode,
 +                            const struct dentry *dentry, const struct inode *inode,
 +                            unsigned int len, const char *str,
 +                            const struct qstr *name)
 +{
 +      int guid = len - EFI_VARIABLE_GUID_LEN;
 +
 +      if (name->len != len)
 +              return 1;
 +
 +      /* Case-sensitive compare for the variable name */
 +      if (memcmp(str, name->name, guid))
 +              return 1;
 +
 +      /* Case-insensitive compare for the GUID */
 +      return strncasecmp(name->name + guid, str + guid, EFI_VARIABLE_GUID_LEN);
 +}
 +
 +static int efivarfs_d_hash(const struct dentry *dentry,
 +                         const struct inode *inode, struct qstr *qstr)
 +{
 +      unsigned long hash = init_name_hash();
 +      const unsigned char *s = qstr->name;
 +      unsigned int len = qstr->len;
 +
 +      if (!efivarfs_valid_name(s, len))
 +              return -EINVAL;
 +
 +      while (len-- > EFI_VARIABLE_GUID_LEN)
 +              hash = partial_name_hash(*s++, hash);
 +
 +      /* GUID is case-insensitive. */
 +      while (len--)
 +              hash = partial_name_hash(tolower(*s++), hash);
 +
 +      qstr->hash = end_name_hash(hash);
 +      return 0;
 +}
 +
 +/*
 + * Retaining negative dentries for an in-memory filesystem just wastes
 + * memory and lookup time: arrange for them to be deleted immediately.
 + */
 +static int efivarfs_delete_dentry(const struct dentry *dentry)
 +{
 +      return 1;
 +}
 +
 +static struct dentry_operations efivarfs_d_ops = {
 +      .d_compare = efivarfs_d_compare,
 +      .d_hash = efivarfs_d_hash,
 +      .d_delete = efivarfs_delete_dentry,
 +};
 +
 +static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
 +{
 +      struct dentry *d;
 +      struct qstr q;
 +      int err;
 +
 +      q.name = name;
 +      q.len = strlen(name);
 +
 +      err = efivarfs_d_hash(NULL, NULL, &q);
 +      if (err)
 +              return ERR_PTR(err);
 +
 +      d = d_alloc(parent, &q);
 +      if (d)
 +              return d;
 +
 +      return ERR_PTR(-ENOMEM);
 +}
 +
 +static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
 +                           unsigned long name_size, void *data)
 +{
 +      struct super_block *sb = (struct super_block *)data;
 +      struct efivar_entry *entry;
 +      struct inode *inode = NULL;
 +      struct dentry *dentry, *root = sb->s_root;
 +      unsigned long size = 0;
 +      char *name;
 +      int len, i;
 +      int err = -ENOMEM;
 +
 +      entry = kmalloc(sizeof(*entry), GFP_KERNEL);
 +      if (!entry)
 +              return err;
 +
 +      memcpy(entry->var.VariableName, name16, name_size);
 +      memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
 +
 +      len = ucs2_strlen(entry->var.VariableName);
 +
 +      /* name, plus '-', plus GUID, plus NUL*/
 +      name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL);
 +      if (!name)
 +              goto fail;
 +
 +      for (i = 0; i < len; i++)
 +              name[i] = entry->var.VariableName[i] & 0xFF;
 +
 +      name[len] = '-';
 +
 +      efi_guid_unparse(&entry->var.VendorGuid, name + len + 1);
 +
 +      name[len + EFI_VARIABLE_GUID_LEN+1] = '\0';
 +
 +      inode = efivarfs_get_inode(sb, root->d_inode, S_IFREG | 0644, 0);
 +      if (!inode)
 +              goto fail_name;
 +
 +      dentry = efivarfs_alloc_dentry(root, name);
 +      if (IS_ERR(dentry)) {
 +              err = PTR_ERR(dentry);
 +              goto fail_inode;
 +      }
 +
 +      /* copied by the above to local storage in the dentry. */
 +      kfree(name);
 +
 +      efivar_entry_size(entry, &size);
 +      efivar_entry_add(entry, &efivarfs_list);
 +
 +      mutex_lock(&inode->i_mutex);
 +      inode->i_private = entry;
 +      i_size_write(inode, size + sizeof(entry->var.Attributes));
 +      mutex_unlock(&inode->i_mutex);
 +      d_add(dentry, inode);
 +
 +      return 0;
 +
 +fail_inode:
 +      iput(inode);
 +fail_name:
 +      kfree(name);
 +fail:
 +      kfree(entry);
 +      return err;
 +}
 +
 +static int efivarfs_destroy(struct efivar_entry *entry, void *data)
 +{
 +      efivar_entry_remove(entry);
 +      kfree(entry);
 +      return 0;
 +}
 +
 +static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
 +{
 +      struct inode *inode = NULL;
 +      struct dentry *root;
 +      int err;
 +
 +      efivarfs_sb = sb;
 +
 +      sb->s_maxbytes          = MAX_LFS_FILESIZE;
 +      sb->s_blocksize         = PAGE_CACHE_SIZE;
 +      sb->s_blocksize_bits    = PAGE_CACHE_SHIFT;
 +      sb->s_magic             = EFIVARFS_MAGIC;
 +      sb->s_op                = &efivarfs_ops;
 +      sb->s_d_op              = &efivarfs_d_ops;
 +      sb->s_time_gran         = 1;
 +
 +      inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
 +      if (!inode)
 +              return -ENOMEM;
 +      inode->i_op = &efivarfs_dir_inode_operations;
 +
 +      root = d_make_root(inode);
 +      sb->s_root = root;
 +      if (!root)
 +              return -ENOMEM;
 +
 +      INIT_LIST_HEAD(&efivarfs_list);
 +
 +      err = efivar_init(efivarfs_callback, (void *)sb, false,
 +                        true, &efivarfs_list);
 +      if (err)
 +              __efivar_entry_iter(efivarfs_destroy, &efivarfs_list, NULL, NULL);
 +
 +      return err;
 +}
 +
 +static struct dentry *efivarfs_mount(struct file_system_type *fs_type,
 +                                  int flags, const char *dev_name, void *data)
 +{
 +      return mount_single(fs_type, flags, data, efivarfs_fill_super);
 +}
 +
 +static void efivarfs_kill_sb(struct super_block *sb)
 +{
 +      kill_litter_super(sb);
 +      efivarfs_sb = NULL;
 +
 +      /* Remove all entries and destroy */
 +      __efivar_entry_iter(efivarfs_destroy, &efivarfs_list, NULL, NULL);
 +}
 +
 +static struct file_system_type efivarfs_type = {
 +      .name    = "efivarfs",
 +      .mount   = efivarfs_mount,
 +      .kill_sb = efivarfs_kill_sb,
 +};
 +
 +static __init int efivarfs_init(void)
 +{
 +      if (!efi_enabled(EFI_RUNTIME_SERVICES))
 +              return 0;
 +
 +      if (!efivars_kobject())
 +              return 0;
 +
 +      return register_filesystem(&efivarfs_type);
 +}
 +
 +MODULE_AUTHOR("Matthew Garrett, Jeremy Kerr");
 +MODULE_DESCRIPTION("EFI Variable Filesystem");
 +MODULE_LICENSE("GPL");
 +MODULE_ALIAS_FS("efivarfs");
 +
 +module_init(efivarfs_init);
diff --combined fs/exec.c
index 963f510a25ab50013e9b0fbeac055570dc8af235,77dc9096440fbd8ec7aefe695bcb0d763431e51e..643019585574956f44bdca47c52c3993046db069
+++ b/fs/exec.c
@@@ -613,7 -613,7 +613,7 @@@ static int shift_arg_pages(struct vm_ar
                 * when the old and new regions overlap clear from new_end.
                 */
                free_pgd_range(&tlb, new_end, old_end, new_end,
 -                      vma->vm_next ? vma->vm_next->vm_start : 0);
 +                      vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING);
        } else {
                /*
                 * otherwise, clean from old_start; this is done to not touch
                 * for the others its just a little faster.
                 */
                free_pgd_range(&tlb, old_start, old_end, new_end,
 -                      vma->vm_next ? vma->vm_next->vm_start : 0);
 +                      vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING);
        }
        tlb_finish_mmu(&tlb, new_end, old_end);
  
@@@ -802,6 -802,15 +802,15 @@@ int kernel_read(struct file *file, loff
  
  EXPORT_SYMBOL(kernel_read);
  
+ ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
+ {
+       ssize_t res = file->f_op->read(file, (void __user *)addr, len, &pos);
+       if (res > 0)
+               flush_icache_range(addr, addr + len);
+       return res;
+ }
+ EXPORT_SYMBOL(read_code);
  static int exec_mmap(struct mm_struct *mm)
  {
        struct task_struct *tsk;
@@@ -898,13 -907,11 +907,13 @@@ static int de_thread(struct task_struc
  
                sig->notify_count = -1; /* for exit_notify() */
                for (;;) {
 +                      threadgroup_change_begin(tsk);
                        write_lock_irq(&tasklist_lock);
                        if (likely(leader->exit_state))
                                break;
                        __set_current_state(TASK_KILLABLE);
                        write_unlock_irq(&tasklist_lock);
 +                      threadgroup_change_end(tsk);
                        schedule();
                        if (unlikely(__fatal_signal_pending(tsk)))
                                goto killed;
                if (unlikely(leader->ptrace))
                        __wake_up_parent(leader, leader->parent);
                write_unlock_irq(&tasklist_lock);
 +              threadgroup_change_end(tsk);
  
                release_task(leader);
        }
@@@ -1030,7 -1036,17 +1039,7 @@@ EXPORT_SYMBOL_GPL(get_task_comm)
  void set_task_comm(struct task_struct *tsk, char *buf)
  {
        task_lock(tsk);
 -
        trace_task_rename(tsk, buf);
 -
 -      /*
 -       * Threads may access current->comm without holding
 -       * the task lock, so write the string carefully.
 -       * Readers without a lock may see incomplete new
 -       * names but are safe from non-terminating string reads.
 -       */
 -      memset(tsk->comm, 0, TASK_COMM_LEN);
 -      wmb();
        strlcpy(tsk->comm, buf, sizeof(tsk->comm));
        task_unlock(tsk);
        perf_event_comm(tsk);
diff --combined fs/ext4/mballoc.c
index a11ea4d6164c2593411517473d6543160cec1f6e,28e421c208a5fd8c259ef24243c32f87a51290bc..b1ed9e07434ba4a15d86d1a538e6b808917901d6
@@@ -405,12 -405,6 +405,12 @@@ static inline void mb_clear_bit(int bit
        ext4_clear_bit(bit, addr);
  }
  
 +static inline int mb_test_and_clear_bit(int bit, void *addr)
 +{
 +      addr = mb_correct_addr_and_bit(&bit, addr);
 +      return ext4_test_and_clear_bit(bit, addr);
 +}
 +
  static inline int mb_find_next_zero_bit(void *addr, int max, int start)
  {
        int fix = 0, ret, tmpmax;
@@@ -770,24 -764,6 +770,24 @@@ void ext4_mb_generate_buddy(struct supe
        spin_unlock(&EXT4_SB(sb)->s_bal_lock);
  }
  
 +static void mb_regenerate_buddy(struct ext4_buddy *e4b)
 +{
 +      int count;
 +      int order = 1;
 +      void *buddy;
 +
 +      while ((buddy = mb_find_buddy(e4b, order++, &count))) {
 +              ext4_set_bits(buddy, 0, count);
 +      }
 +      e4b->bd_info->bb_fragments = 0;
 +      memset(e4b->bd_info->bb_counters, 0,
 +              sizeof(*e4b->bd_info->bb_counters) *
 +              (e4b->bd_sb->s_blocksize_bits + 2));
 +
 +      ext4_mb_generate_buddy(e4b->bd_sb, e4b->bd_buddy,
 +              e4b->bd_bitmap, e4b->bd_group);
 +}
 +
  /* The buddy information is attached the buddy cache inode
   * for convenience. The information regarding each group
   * is loaded via ext4_mb_load_buddy. The information involve
@@@ -884,6 -860,8 +884,6 @@@ static int ext4_mb_init_cache(struct pa
  
        first_block = page->index * blocks_per_page;
        for (i = 0; i < blocks_per_page; i++) {
 -              int group;
 -
                group = (first_block + i) >> 1;
                if (group >= ngroups)
                        break;
@@@ -1033,7 -1011,6 +1033,7 @@@ int ext4_mb_init_group(struct super_blo
        struct page *page;
        int ret = 0;
  
 +      might_sleep();
        mb_debug(1, "init group %u\n", group);
        this_grp = ext4_get_group_info(sb, group);
        /*
@@@ -1105,7 -1082,6 +1105,7 @@@ ext4_mb_load_buddy(struct super_block *
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct inode *inode = sbi->s_buddy_cache;
  
 +      might_sleep();
        mb_debug(1, "load group %u\n", group);
  
        blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
@@@ -1268,33 -1244,6 +1268,33 @@@ static void mb_clear_bits(void *bm, in
        }
  }
  
 +/* clear bits in given range
 + * will return first found zero bit if any, -1 otherwise
 + */
 +static int mb_test_and_clear_bits(void *bm, int cur, int len)
 +{
 +      __u32 *addr;
 +      int zero_bit = -1;
 +
 +      len = cur + len;
 +      while (cur < len) {
 +              if ((cur & 31) == 0 && (len - cur) >= 32) {
 +                      /* fast path: clear whole word at once */
 +                      addr = bm + (cur >> 3);
 +                      if (*addr != (__u32)(-1) && zero_bit == -1)
 +                              zero_bit = cur + mb_find_next_zero_bit(addr, 32, 0);
 +                      *addr = 0;
 +                      cur += 32;
 +                      continue;
 +              }
 +              if (!mb_test_and_clear_bit(cur, bm) && zero_bit == -1)
 +                      zero_bit = cur;
 +              cur++;
 +      }
 +
 +      return zero_bit;
 +}
 +
  void ext4_set_bits(void *bm, int cur, int len)
  {
        __u32 *addr;
        }
  }
  
 +/*
 + * _________________________________________________________________ */
 +
 +static inline int mb_buddy_adjust_border(int* bit, void* bitmap, int side)
 +{
 +      if (mb_test_bit(*bit + side, bitmap)) {
 +              mb_clear_bit(*bit, bitmap);
 +              (*bit) -= side;
 +              return 1;
 +      }
 +      else {
 +              (*bit) += side;
 +              mb_set_bit(*bit, bitmap);
 +              return -1;
 +      }
 +}
 +
 +static void mb_buddy_mark_free(struct ext4_buddy *e4b, int first, int last)
 +{
 +      int max;
 +      int order = 1;
 +      void *buddy = mb_find_buddy(e4b, order, &max);
 +
 +      while (buddy) {
 +              void *buddy2;
 +
 +              /* Bits in range [first; last] are known to be set since
 +               * corresponding blocks were allocated. Bits in range
 +               * (first; last) will stay set because they form buddies on
 +               * upper layer. We just deal with borders if they don't
 +               * align with upper layer and then go up.
 +               * Releasing entire group is all about clearing
 +               * single bit of highest order buddy.
 +               */
 +
 +              /* Example:
 +               * ---------------------------------
 +               * |   1   |   1   |   1   |   1   |
 +               * ---------------------------------
 +               * | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
 +               * ---------------------------------
 +               *   0   1   2   3   4   5   6   7
 +               *      \_____________________/
 +               *
 +               * Neither [1] nor [6] is aligned to above layer.
 +               * Left neighbour [0] is free, so mark it busy,
 +               * decrease bb_counters and extend range to
 +               * [0; 6]
 +               * Right neighbour [7] is busy. It can't be coaleasced with [6], so
 +               * mark [6] free, increase bb_counters and shrink range to
 +               * [0; 5].
 +               * Then shift range to [0; 2], go up and do the same.
 +               */
 +
 +
 +              if (first & 1)
 +                      e4b->bd_info->bb_counters[order] += mb_buddy_adjust_border(&first, buddy, -1);
 +              if (!(last & 1))
 +                      e4b->bd_info->bb_counters[order] += mb_buddy_adjust_border(&last, buddy, 1);
 +              if (first > last)
 +                      break;
 +              order++;
 +
 +              if (first == last || !(buddy2 = mb_find_buddy(e4b, order, &max))) {
 +                      mb_clear_bits(buddy, first, last - first + 1);
 +                      e4b->bd_info->bb_counters[order - 1] += last - first + 1;
 +                      break;
 +              }
 +              first >>= 1;
 +              last >>= 1;
 +              buddy = buddy2;
 +      }
 +}
 +
  static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
 -                        int first, int count)
 +                         int first, int count)
  {
 -      int block = 0;
 -      int max = 0;
 -      int order;
 -      void *buddy;
 -      void *buddy2;
 +      int left_is_free = 0;
 +      int right_is_free = 0;
 +      int block;
 +      int last = first + count - 1;
        struct super_block *sb = e4b->bd_sb;
  
 -      BUG_ON(first + count > (sb->s_blocksize << 3));
 +      BUG_ON(last >= (sb->s_blocksize << 3));
        assert_spin_locked(ext4_group_lock_ptr(sb, e4b->bd_group));
        mb_check_buddy(e4b);
        mb_free_blocks_double(inode, e4b, first, count);
        if (first < e4b->bd_info->bb_first_free)
                e4b->bd_info->bb_first_free = first;
  
 -      /* let's maintain fragments counter */
 +      /* access memory sequentially: check left neighbour,
 +       * clear range and then check right neighbour
 +       */
        if (first != 0)
 -              block = !mb_test_bit(first - 1, e4b->bd_bitmap);
 -      if (first + count < EXT4_SB(sb)->s_mb_maxs[0])
 -              max = !mb_test_bit(first + count, e4b->bd_bitmap);
 -      if (block && max)
 -              e4b->bd_info->bb_fragments--;
 -      else if (!block && !max)
 -              e4b->bd_info->bb_fragments++;
 +              left_is_free = !mb_test_bit(first - 1, e4b->bd_bitmap);
 +      block = mb_test_and_clear_bits(e4b->bd_bitmap, first, count);
 +      if (last + 1 < EXT4_SB(sb)->s_mb_maxs[0])
 +              right_is_free = !mb_test_bit(last + 1, e4b->bd_bitmap);
  
 -      /* let's maintain buddy itself */
 -      while (count-- > 0) {
 -              block = first++;
 -              order = 0;
 +      if (unlikely(block != -1)) {
 +              ext4_fsblk_t blocknr;
  
 -              if (!mb_test_bit(block, e4b->bd_bitmap)) {
 -                      ext4_fsblk_t blocknr;
 -
 -                      blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
 -                      blocknr += EXT4_C2B(EXT4_SB(sb), block);
 -                      ext4_grp_locked_error(sb, e4b->bd_group,
 -                                            inode ? inode->i_ino : 0,
 -                                            blocknr,
 -                                            "freeing already freed block "
 -                                            "(bit %u)", block);
 -              }
 -              mb_clear_bit(block, e4b->bd_bitmap);
 -              e4b->bd_info->bb_counters[order]++;
 -
 -              /* start of the buddy */
 -              buddy = mb_find_buddy(e4b, order, &max);
 -
 -              do {
 -                      block &= ~1UL;
 -                      if (mb_test_bit(block, buddy) ||
 -                                      mb_test_bit(block + 1, buddy))
 -                              break;
 -
 -                      /* both the buddies are free, try to coalesce them */
 -                      buddy2 = mb_find_buddy(e4b, order + 1, &max);
 +              blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
 +              blocknr += EXT4_C2B(EXT4_SB(sb), block);
 +              ext4_grp_locked_error(sb, e4b->bd_group,
 +                                    inode ? inode->i_ino : 0,
 +                                    blocknr,
 +                                    "freeing already freed block "
 +                                    "(bit %u)", block);
 +              mb_regenerate_buddy(e4b);
 +              goto done;
 +      }
  
 -                      if (!buddy2)
 -                              break;
 +      /* let's maintain fragments counter */
 +      if (left_is_free && right_is_free)
 +              e4b->bd_info->bb_fragments--;
 +      else if (!left_is_free && !right_is_free)
 +              e4b->bd_info->bb_fragments++;
  
 -                      if (order > 0) {
 -                              /* for special purposes, we don't set
 -                               * free bits in bitmap */
 -                              mb_set_bit(block, buddy);
 -                              mb_set_bit(block + 1, buddy);
 -                      }
 -                      e4b->bd_info->bb_counters[order]--;
 -                      e4b->bd_info->bb_counters[order]--;
 +      /* buddy[0] == bd_bitmap is a special case, so handle
 +       * it right away and let mb_buddy_mark_free stay free of
 +       * zero order checks.
 +       * Check if neighbours are to be coaleasced,
 +       * adjust bitmap bb_counters and borders appropriately.
 +       */
 +      if (first & 1) {
 +              first += !left_is_free;
 +              e4b->bd_info->bb_counters[0] += left_is_free ? -1 : 1;
 +      }
 +      if (!(last & 1)) {
 +              last -= !right_is_free;
 +              e4b->bd_info->bb_counters[0] += right_is_free ? -1 : 1;
 +      }
  
 -                      block = block >> 1;
 -                      order++;
 -                      e4b->bd_info->bb_counters[order]++;
 +      if (first <= last)
 +              mb_buddy_mark_free(e4b, first >> 1, last >> 1);
  
 -                      mb_clear_bit(block, buddy2);
 -                      buddy = buddy2;
 -              } while (1);
 -      }
 +done:
        mb_set_largest_free_order(sb, e4b->bd_info);
        mb_check_buddy(e4b);
  }
@@@ -2260,7 -2149,7 +2260,7 @@@ static const struct seq_operations ext4
  
  static int ext4_mb_seq_groups_open(struct inode *inode, struct file *file)
  {
-       struct super_block *sb = PDE(inode)->data;
+       struct super_block *sb = PDE_DATA(inode);
        int rc;
  
        rc = seq_open(file, &ext4_mb_seq_groups_ops);
@@@ -3453,7 -3342,7 +3453,7 @@@ static void ext4_mb_put_pa(struct ext4_
        if (pa->pa_type == MB_GROUP_PA)
                grp_blk--;
  
 -      ext4_get_group_no_and_offset(sb, grp_blk, &grp, NULL);
 +      grp = ext4_get_group_number(sb, grp_blk);
  
        /*
         * possible race:
@@@ -3918,7 -3807,7 +3918,7 @@@ repeat
  
        list_for_each_entry_safe(pa, tmp, &list, u.pa_tmp_list) {
                BUG_ON(pa->pa_type != MB_INODE_PA);
 -              ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, NULL);
 +              group = ext4_get_group_number(sb, pa->pa_pstart);
  
                err = ext4_mb_load_buddy(sb, group, &e4b);
                if (err) {
@@@ -4180,7 -4069,7 +4180,7 @@@ ext4_mb_discard_lg_preallocations(struc
  
        list_for_each_entry_safe(pa, tmp, &discard_list, u.pa_tmp_list) {
  
 -              ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, NULL);
 +              group = ext4_get_group_number(sb, pa->pa_pstart);
                if (ext4_mb_load_buddy(sb, group, &e4b)) {
                        ext4_error(sb, "Error loading buddy information for %u",
                                        group);
@@@ -4328,7 -4217,6 +4328,7 @@@ ext4_fsblk_t ext4_mb_new_blocks(handle_
        unsigned int inquota = 0;
        unsigned int reserv_clstrs = 0;
  
 +      might_sleep();
        sb = ar->inode->i_sb;
        sbi = EXT4_SB(sb);
  
@@@ -4532,11 -4420,11 +4532,11 @@@ ext4_mb_free_metadata(handle_t *handle
        node = rb_prev(new_node);
        if (node) {
                entry = rb_entry(node, struct ext4_free_data, efd_node);
 -              if (can_merge(entry, new_entry)) {
 +              if (can_merge(entry, new_entry) &&
 +                  ext4_journal_callback_try_del(handle, &entry->efd_jce)) {
                        new_entry->efd_start_cluster = entry->efd_start_cluster;
                        new_entry->efd_count += entry->efd_count;
                        rb_erase(node, &(db->bb_free_root));
 -                      ext4_journal_callback_del(handle, &entry->efd_jce);
                        kmem_cache_free(ext4_free_data_cachep, entry);
                }
        }
        node = rb_next(new_node);
        if (node) {
                entry = rb_entry(node, struct ext4_free_data, efd_node);
 -              if (can_merge(new_entry, entry)) {
 +              if (can_merge(new_entry, entry) &&
 +                  ext4_journal_callback_try_del(handle, &entry->efd_jce)) {
                        new_entry->efd_count += entry->efd_count;
                        rb_erase(node, &(db->bb_free_root));
 -                      ext4_journal_callback_del(handle, &entry->efd_jce);
                        kmem_cache_free(ext4_free_data_cachep, entry);
                }
        }
@@@ -4582,7 -4470,6 +4582,7 @@@ void ext4_free_blocks(handle_t *handle
        int err = 0;
        int ret;
  
 +      might_sleep();
        if (bh) {
                if (block)
                        BUG_ON(block != bh->b_blocknr);
diff --combined fs/ext4/super.c
index dbc7c090c13a782a9976fcbe9a8500e6158f6412,c65510548355470daf817b24f80b00a8ef4fd669..24a146bde742be9683cea9f13be9e30a1324b9c5
@@@ -81,7 -81,6 +81,7 @@@ static int ext4_feature_set_ok(struct s
  static void ext4_destroy_lazyinit_thread(void);
  static void ext4_unregister_li_request(struct super_block *sb);
  static void ext4_clear_request_list(void);
 +static int ext4_reserve_clusters(struct ext4_sb_info *, ext4_fsblk_t);
  
  #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
  static struct file_system_type ext2_fs_type = {
@@@ -354,13 -353,10 +354,13 @@@ static void ext4_journal_commit_callbac
        struct super_block              *sb = journal->j_private;
        struct ext4_sb_info             *sbi = EXT4_SB(sb);
        int                             error = is_journal_aborted(journal);
 -      struct ext4_journal_cb_entry    *jce, *tmp;
 +      struct ext4_journal_cb_entry    *jce;
  
 +      BUG_ON(txn->t_state == T_FINISHED);
        spin_lock(&sbi->s_md_lock);
 -      list_for_each_entry_safe(jce, tmp, &txn->t_private_list, jce_list) {
 +      while (!list_empty(&txn->t_private_list)) {
 +              jce = list_entry(txn->t_private_list.next,
 +                               struct ext4_journal_cb_entry, jce_list);
                list_del_init(&jce->jce_list);
                spin_unlock(&sbi->s_md_lock);
                jce->jce_func(sb, jce, error);
@@@ -1806,7 -1802,7 +1806,7 @@@ static int options_seq_show(struct seq_
  
  static int options_open_fs(struct inode *inode, struct file *file)
  {
-       return single_open(file, options_seq_show, PDE(inode)->data);
+       return single_open(file, options_seq_show, PDE_DATA(inode));
  }
  
  static const struct file_operations ext4_seq_options_fops = {
@@@ -1952,16 -1948,16 +1952,16 @@@ static __le16 ext4_group_desc_csum(stru
        if ((sbi->s_es->s_feature_ro_compat &
             cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))) {
                /* Use new metadata_csum algorithm */
 -              __u16 old_csum;
 +              __le16 save_csum;
                __u32 csum32;
  
 -              old_csum = gdp->bg_checksum;
 +              save_csum = gdp->bg_checksum;
                gdp->bg_checksum = 0;
                csum32 = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&le_group,
                                     sizeof(le_group));
                csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp,
                                     sbi->s_desc_size);
 -              gdp->bg_checksum = old_csum;
 +              gdp->bg_checksum = save_csum;
  
                crc = csum32 & 0xFFFF;
                goto out;
@@@ -2383,15 -2379,17 +2383,15 @@@ struct ext4_attr 
        int offset;
  };
  
 -static int parse_strtoul(const char *buf,
 -              unsigned long max, unsigned long *value)
 +static int parse_strtoull(const char *buf,
 +              unsigned long long max, unsigned long long *value)
  {
 -      char *endp;
 -
 -      *value = simple_strtoul(skip_spaces(buf), &endp, 0);
 -      endp = skip_spaces(endp);
 -      if (*endp || *value > max)
 -              return -EINVAL;
 +      int ret;
  
 -      return 0;
 +      ret = kstrtoull(skip_spaces(buf), 0, value);
 +      if (!ret && *value > max)
 +              ret = -EINVAL;
 +      return ret;
  }
  
  static ssize_t delayed_allocation_blocks_show(struct ext4_attr *a,
@@@ -2433,13 -2431,11 +2433,13 @@@ static ssize_t inode_readahead_blks_sto
                                          const char *buf, size_t count)
  {
        unsigned long t;
 +      int ret;
  
 -      if (parse_strtoul(buf, 0x40000000, &t))
 -              return -EINVAL;
 +      ret = kstrtoul(skip_spaces(buf), 0, &t);
 +      if (ret)
 +              return ret;
  
 -      if (t && !is_power_of_2(t))
 +      if (t && (!is_power_of_2(t) || t > 0x40000000))
                return -EINVAL;
  
        sbi->s_inode_readahead_blks = t;
@@@ -2460,36 -2456,13 +2460,36 @@@ static ssize_t sbi_ui_store(struct ext4
  {
        unsigned int *ui = (unsigned int *) (((char *) sbi) + a->offset);
        unsigned long t;
 +      int ret;
  
 -      if (parse_strtoul(buf, 0xffffffff, &t))
 -              return -EINVAL;
 +      ret = kstrtoul(skip_spaces(buf), 0, &t);
 +      if (ret)
 +              return ret;
        *ui = t;
        return count;
  }
  
 +static ssize_t reserved_clusters_show(struct ext4_attr *a,
 +                                struct ext4_sb_info *sbi, char *buf)
 +{
 +      return snprintf(buf, PAGE_SIZE, "%llu\n",
 +              (unsigned long long) atomic64_read(&sbi->s_resv_clusters));
 +}
 +
 +static ssize_t reserved_clusters_store(struct ext4_attr *a,
 +                                 struct ext4_sb_info *sbi,
 +                                 const char *buf, size_t count)
 +{
 +      unsigned long long val;
 +      int ret;
 +
 +      if (parse_strtoull(buf, -1ULL, &val))
 +              return -EINVAL;
 +      ret = ext4_reserve_clusters(sbi, val);
 +
 +      return ret ? ret : count;
 +}
 +
  static ssize_t trigger_test_error(struct ext4_attr *a,
                                  struct ext4_sb_info *sbi,
                                  const char *buf, size_t count)
@@@ -2527,7 -2500,6 +2527,7 @@@ static struct ext4_attr ext4_attr_##nam
  EXT4_RO_ATTR(delayed_allocation_blocks);
  EXT4_RO_ATTR(session_write_kbytes);
  EXT4_RO_ATTR(lifetime_write_kbytes);
 +EXT4_RW_ATTR(reserved_clusters);
  EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
                 inode_readahead_blks_store, s_inode_readahead_blks);
  EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
@@@ -2545,7 -2517,6 +2545,7 @@@ static struct attribute *ext4_attrs[] 
        ATTR_LIST(delayed_allocation_blocks),
        ATTR_LIST(session_write_kbytes),
        ATTR_LIST(lifetime_write_kbytes),
 +      ATTR_LIST(reserved_clusters),
        ATTR_LIST(inode_readahead_blks),
        ATTR_LIST(inode_goal),
        ATTR_LIST(mb_stats),
@@@ -3221,40 -3192,6 +3221,40 @@@ int ext4_calculate_overhead(struct supe
        return 0;
  }
  
 +
 +static ext4_fsblk_t ext4_calculate_resv_clusters(struct ext4_sb_info *sbi)
 +{
 +      ext4_fsblk_t resv_clusters;
 +
 +      /*
 +       * By default we reserve 2% or 4096 clusters, whichever is smaller.
 +       * This should cover the situations where we can not afford to run
 +       * out of space like for example punch hole, or converting
 +       * uninitialized extents in delalloc path. In most cases such
 +       * allocation would require 1, or 2 blocks, higher numbers are
 +       * very rare.
 +       */
 +      resv_clusters = ext4_blocks_count(sbi->s_es) >> sbi->s_cluster_bits;
 +
 +      do_div(resv_clusters, 50);
 +      resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096);
 +
 +      return resv_clusters;
 +}
 +
 +
 +static int ext4_reserve_clusters(struct ext4_sb_info *sbi, ext4_fsblk_t count)
 +{
 +      ext4_fsblk_t clusters = ext4_blocks_count(sbi->s_es) >>
 +                              sbi->s_cluster_bits;
 +
 +      if (count >= clusters)
 +              return -EINVAL;
 +
 +      atomic64_set(&sbi->s_resv_clusters, count);
 +      return 0;
 +}
 +
  static int ext4_fill_super(struct super_block *sb, void *data, int silent)
  {
        char *orig_data = kstrdup(data, GFP_KERNEL);
        sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
        sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
  
 +      /* Do we have standard group size of blocksize * 8 blocks ? */
 +      if (sbi->s_blocks_per_group == blocksize << 3)
 +              set_opt2(sb, STD_GROUP_SIZE);
 +
        for (i = 0; i < 4; i++)
                sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
        sbi->s_def_hash_version = es->s_def_hash_version;
        sbi->s_err_report.function = print_daily_error_info;
        sbi->s_err_report.data = (unsigned long) sb;
  
 +      /* Register extent status tree shrinker */
 +      ext4_es_register_shrinker(sb);
 +
        err = percpu_counter_init(&sbi->s_freeclusters_counter,
                        ext4_count_free_clusters(sb));
        if (!err) {
        sbi->s_max_writeback_mb_bump = 128;
        sbi->s_extent_max_zeroout_kb = 32;
  
 -      /* Register extent status tree shrinker */
 -      ext4_es_register_shrinker(sb);
 -
        /*
         * set up enough so that it can read an inode
         */
@@@ -3978,13 -3911,6 +3978,13 @@@ no_journal
                         "available");
        }
  
 +      err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sbi));
 +      if (err) {
 +              ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
 +                       "reserved pool", ext4_calculate_resv_clusters(sbi));
 +              goto failed_mount4a;
 +      }
 +
        err = ext4_setup_system_zone(sb);
        if (err) {
                ext4_msg(sb, KERN_ERR, "failed to initialize system "
@@@ -4084,7 -4010,6 +4084,7 @@@ failed_mount_wq
                sbi->s_journal = NULL;
        }
  failed_mount3:
 +      ext4_es_unregister_shrinker(sb);
        del_timer(&sbi->s_err_report);
        if (sbi->s_flex_groups)
                ext4_kvfree(sbi->s_flex_groups);
@@@ -4252,7 -4177,7 +4252,7 @@@ static journal_t *ext4_get_dev_journal(
                goto out_bdev;
        }
        journal->j_private = sb;
 -      ll_rw_block(READ, 1, &journal->j_sb_buffer);
 +      ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &journal->j_sb_buffer);
        wait_on_buffer(journal->j_sb_buffer);
        if (!buffer_uptodate(journal->j_sb_buffer)) {
                ext4_msg(sb, KERN_ERR, "I/O error on journal device");
@@@ -4817,10 -4742,9 +4817,10 @@@ static int ext4_statfs(struct dentry *d
        struct super_block *sb = dentry->d_sb;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_super_block *es = sbi->s_es;
 -      ext4_fsblk_t overhead = 0;
 +      ext4_fsblk_t overhead = 0, resv_blocks;
        u64 fsid;
        s64 bfree;
 +      resv_blocks = EXT4_C2B(sbi, atomic64_read(&sbi->s_resv_clusters));
  
        if (!test_opt(sb, MINIX_DF))
                overhead = sbi->s_overhead;
                percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter);
        /* prevent underflow in case that few free space is available */
        buf->f_bfree = EXT4_C2B(sbi, max_t(s64, bfree, 0));
 -      buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
 -      if (buf->f_bfree < ext4_r_blocks_count(es))
 +      buf->f_bavail = buf->f_bfree -
 +                      (ext4_r_blocks_count(es) + resv_blocks);
 +      if (buf->f_bfree < (ext4_r_blocks_count(es) + resv_blocks))
                buf->f_bavail = 0;
        buf->f_files = le32_to_cpu(es->s_inodes_count);
        buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);
@@@ -5022,8 -4945,6 +5022,8 @@@ static int ext4_quota_enable(struct sup
                return PTR_ERR(qf_inode);
        }
  
 +      /* Don't account quota for quota files to avoid recursion */
 +      qf_inode->i_flags |= S_NOQUOTA;
        err = dquot_enable(qf_inode, type, format_id, flags);
        iput(qf_inode);
  
diff --combined fs/inode.c
index a898b3d43ccf3990986d51be3305bdc3e6d665ef,5b76d9b1a8843887845d1e3d095cbf7d33286653..00d5fc3b86e12419d2d350032b173009bddcd2cd
@@@ -725,7 -725,7 +725,7 @@@ void prune_icache_sb(struct super_bloc
                 * inode to the back of the list so we don't spin on it.
                 */
                if (!spin_trylock(&inode->i_lock)) {
 -                      list_move_tail(&inode->i_lru, &sb->s_inode_lru);
 +                      list_move(&inode->i_lru, &sb->s_inode_lru);
                        continue;
                }
  
@@@ -1803,7 -1803,7 +1803,7 @@@ void init_special_inode(struct inode *i
                inode->i_fop = &def_blk_fops;
                inode->i_rdev = rdev;
        } else if (S_ISFIFO(mode))
-               inode->i_fop = &def_fifo_fops;
+               inode->i_fop = &pipefifo_fops;
        else if (S_ISSOCK(mode))
                inode->i_fop = &bad_sock_fops;
        else
diff --combined fs/jbd2/journal.c
index f6c5ba027f4f613f655f703de222449a45c6c9c3,154592ea56322a40516f6e302af9b7dcf9cac398..95457576e434b2624475bbdab2758974eefbd9d5
@@@ -367,6 -367,8 +367,6 @@@ retry_alloc
        }
  
        /* keep subsequent assertions sane */
 -      new_bh->b_state = 0;
 -      init_buffer(new_bh, NULL, NULL);
        atomic_set(&new_bh->b_count, 1);
        new_jh = jbd2_journal_add_journal_head(new_bh); /* This sleeps */
  
@@@ -707,37 -709,6 +707,37 @@@ int jbd2_log_wait_commit(journal_t *jou
        return err;
  }
  
 +/*
 + * When this function returns the transaction corresponding to tid
 + * will be completed.  If the transaction has currently running, start
 + * committing that transaction before waiting for it to complete.  If
 + * the transaction id is stale, it is by definition already completed,
 + * so just return SUCCESS.
 + */
 +int jbd2_complete_transaction(journal_t *journal, tid_t tid)
 +{
 +      int     need_to_wait = 1;
 +
 +      read_lock(&journal->j_state_lock);
 +      if (journal->j_running_transaction &&
 +          journal->j_running_transaction->t_tid == tid) {
 +              if (journal->j_commit_request != tid) {
 +                      /* transaction not yet started, so request it */
 +                      read_unlock(&journal->j_state_lock);
 +                      jbd2_log_start_commit(journal, tid);
 +                      goto wait_commit;
 +              }
 +      } else if (!(journal->j_committing_transaction &&
 +                   journal->j_committing_transaction->t_tid == tid))
 +              need_to_wait = 0;
 +      read_unlock(&journal->j_state_lock);
 +      if (!need_to_wait)
 +              return 0;
 +wait_commit:
 +      return jbd2_log_wait_commit(journal, tid);
 +}
 +EXPORT_SYMBOL(jbd2_complete_transaction);
 +
  /*
   * Log buffer allocation routines:
   */
@@@ -979,7 -950,7 +979,7 @@@ static const struct seq_operations jbd2
  
  static int jbd2_seq_info_open(struct inode *inode, struct file *file)
  {
-       journal_t *journal = PDE(inode)->data;
+       journal_t *journal = PDE_DATA(inode);
        struct jbd2_stats_proc_session *s;
        int rc, size;
  
diff --combined fs/namespace.c
index 341d3f564082f2367a7f1538255e90bdfbfd8cd2,0f0cf9379c9eed3d3d636fed3df56350a435c897..b4f96a5230a3874ebde148f42eedba02207e0c20
@@@ -21,7 -21,7 +21,8 @@@
  #include <linux/fs_struct.h>  /* get_fs_root et.al. */
  #include <linux/fsnotify.h>   /* fsnotify_vfsmount_delete */
  #include <linux/uaccess.h>
- #include <linux/proc_fs.h>
+ #include <linux/proc_ns.h>
++#include <linux/magic.h>
  #include "pnode.h"
  #include "internal.h"
  
@@@ -36,6 -36,7 +37,7 @@@ static int mnt_id_start = 0
  static int mnt_group_start = 1;
  
  static struct list_head *mount_hashtable __read_mostly;
+ static struct list_head *mountpoint_hashtable __read_mostly;
  static struct kmem_cache *mnt_cache __read_mostly;
  static struct rw_semaphore namespace_sem;
  
@@@ -605,6 -606,51 +607,51 @@@ struct vfsmount *lookup_mnt(struct pat
        }
  }
  
+ static struct mountpoint *new_mountpoint(struct dentry *dentry)
+ {
+       struct list_head *chain = mountpoint_hashtable + hash(NULL, dentry);
+       struct mountpoint *mp;
+       list_for_each_entry(mp, chain, m_hash) {
+               if (mp->m_dentry == dentry) {
+                       /* might be worth a WARN_ON() */
+                       if (d_unlinked(dentry))
+                               return ERR_PTR(-ENOENT);
+                       mp->m_count++;
+                       return mp;
+               }
+       }
+       mp = kmalloc(sizeof(struct mountpoint), GFP_KERNEL);
+       if (!mp)
+               return ERR_PTR(-ENOMEM);
+       spin_lock(&dentry->d_lock);
+       if (d_unlinked(dentry)) {
+               spin_unlock(&dentry->d_lock);
+               kfree(mp);
+               return ERR_PTR(-ENOENT);
+       }
+       dentry->d_flags |= DCACHE_MOUNTED;
+       spin_unlock(&dentry->d_lock);
+       mp->m_dentry = dentry;
+       mp->m_count = 1;
+       list_add(&mp->m_hash, chain);
+       return mp;
+ }
+ static void put_mountpoint(struct mountpoint *mp)
+ {
+       if (!--mp->m_count) {
+               struct dentry *dentry = mp->m_dentry;
+               spin_lock(&dentry->d_lock);
+               dentry->d_flags &= ~DCACHE_MOUNTED;
+               spin_unlock(&dentry->d_lock);
+               list_del(&mp->m_hash);
+               kfree(mp);
+       }
+ }
  static inline int check_mnt(struct mount *mnt)
  {
        return mnt->mnt_ns == current->nsproxy->mnt_ns;
@@@ -632,27 -678,6 +679,6 @@@ static void __touch_mnt_namespace(struc
        }
  }
  
- /*
-  * Clear dentry's mounted state if it has no remaining mounts.
-  * vfsmount_lock must be held for write.
-  */
- static void dentry_reset_mounted(struct dentry *dentry)
- {
-       unsigned u;
-       for (u = 0; u < HASH_SIZE; u++) {
-               struct mount *p;
-               list_for_each_entry(p, &mount_hashtable[u], mnt_hash) {
-                       if (p->mnt_mountpoint == dentry)
-                               return;
-               }
-       }
-       spin_lock(&dentry->d_lock);
-       dentry->d_flags &= ~DCACHE_MOUNTED;
-       spin_unlock(&dentry->d_lock);
- }
  /*
   * vfsmount lock must be held for write
   */
@@@ -664,32 -689,35 +690,35 @@@ static void detach_mnt(struct mount *mn
        mnt->mnt_mountpoint = mnt->mnt.mnt_root;
        list_del_init(&mnt->mnt_child);
        list_del_init(&mnt->mnt_hash);
-       dentry_reset_mounted(old_path->dentry);
+       put_mountpoint(mnt->mnt_mp);
+       mnt->mnt_mp = NULL;
  }
  
  /*
   * vfsmount lock must be held for write
   */
- void mnt_set_mountpoint(struct mount *mnt, struct dentry *dentry,
+ void mnt_set_mountpoint(struct mount *mnt,
+                       struct mountpoint *mp,
                        struct mount *child_mnt)
  {
+       mp->m_count++;
        mnt_add_count(mnt, 1);  /* essentially, that's mntget */
-       child_mnt->mnt_mountpoint = dget(dentry);
+       child_mnt->mnt_mountpoint = dget(mp->m_dentry);
        child_mnt->mnt_parent = mnt;
-       spin_lock(&dentry->d_lock);
-       dentry->d_flags |= DCACHE_MOUNTED;
-       spin_unlock(&dentry->d_lock);
+       child_mnt->mnt_mp = mp;
  }
  
  /*
   * vfsmount lock must be held for write
   */
- static void attach_mnt(struct mount *mnt, struct path *path)
+ static void attach_mnt(struct mount *mnt,
+                       struct mount *parent,
+                       struct mountpoint *mp)
  {
-       mnt_set_mountpoint(real_mount(path->mnt), path->dentry, mnt);
+       mnt_set_mountpoint(parent, mp, mnt);
        list_add_tail(&mnt->mnt_hash, mount_hashtable +
-                       hash(path->mnt, path->dentry));
-       list_add_tail(&mnt->mnt_child, &real_mount(path->mnt)->mnt_mounts);
+                       hash(&parent->mnt, mp->m_dentry));
+       list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
  }
  
  /*
@@@ -798,10 -826,6 +827,10 @@@ static struct mount *clone_mnt(struct m
        }
  
        mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD;
 +      /* Don't allow unprivileged users to change mount flags */
 +      if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY))
 +              mnt->mnt.mnt_flags |= MNT_LOCK_READONLY;
 +
        atomic_inc(&sb->s_active);
        mnt->mnt.mnt_sb = sb;
        mnt->mnt.mnt_root = dget(root);
@@@ -1095,11 -1119,23 +1124,23 @@@ int may_umount(struct vfsmount *mnt
  
  EXPORT_SYMBOL(may_umount);
  
- void release_mounts(struct list_head *head)
+ static LIST_HEAD(unmounted);  /* protected by namespace_sem */
+ static void namespace_unlock(void)
  {
        struct mount *mnt;
-       while (!list_empty(head)) {
-               mnt = list_first_entry(head, struct mount, mnt_hash);
+       LIST_HEAD(head);
+       if (likely(list_empty(&unmounted))) {
+               up_write(&namespace_sem);
+               return;
+       }
+       list_splice_init(&unmounted, &head);
+       up_write(&namespace_sem);
+       while (!list_empty(&head)) {
+               mnt = list_first_entry(&head, struct mount, mnt_hash);
                list_del_init(&mnt->mnt_hash);
                if (mnt_has_parent(mnt)) {
                        struct dentry *dentry;
        }
  }
  
+ static inline void namespace_lock(void)
+ {
+       down_write(&namespace_sem);
+ }
  /*
   * vfsmount lock must be held for write
   * namespace_sem must be held for write
   */
- void umount_tree(struct mount *mnt, int propagate, struct list_head *kill)
+ void umount_tree(struct mount *mnt, int propagate)
  {
        LIST_HEAD(tmp_list);
        struct mount *p;
                list_del_init(&p->mnt_child);
                if (mnt_has_parent(p)) {
                        p->mnt_parent->mnt_ghosts++;
-                       dentry_reset_mounted(p->mnt_mountpoint);
+                       put_mountpoint(p->mnt_mp);
+                       p->mnt_mp = NULL;
                }
                change_mnt_propagation(p, MS_PRIVATE);
        }
-       list_splice(&tmp_list, kill);
+       list_splice(&tmp_list, &unmounted);
  }
  
- static void shrink_submounts(struct mount *mnt, struct list_head *umounts);
+ static void shrink_submounts(struct mount *mnt);
  
  static int do_umount(struct mount *mnt, int flags)
  {
        struct super_block *sb = mnt->mnt.mnt_sb;
        int retval;
-       LIST_HEAD(umount_list);
  
        retval = security_sb_umount(&mnt->mnt, flags);
        if (retval)
                return retval;
        }
  
-       down_write(&namespace_sem);
+       namespace_lock();
        br_write_lock(&vfsmount_lock);
        event++;
  
        if (!(flags & MNT_DETACH))
-               shrink_submounts(mnt, &umount_list);
+               shrink_submounts(mnt);
  
        retval = -EBUSY;
        if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
                if (!list_empty(&mnt->mnt_list))
-                       umount_tree(mnt, 1, &umount_list);
+                       umount_tree(mnt, 1);
                retval = 0;
        }
        br_write_unlock(&vfsmount_lock);
-       up_write(&namespace_sem);
-       release_mounts(&umount_list);
+       namespace_unlock();
        return retval;
  }
  
@@@ -1310,13 -1350,13 +1355,13 @@@ static bool mnt_ns_loop(struct path *pa
         * mount namespace loop?
         */
        struct inode *inode = path->dentry->d_inode;
-       struct proc_inode *ei;
+       struct proc_ns *ei;
        struct mnt_namespace *mnt_ns;
  
        if (!proc_ns_inode(inode))
                return false;
  
-       ei = PROC_I(inode);
+       ei = get_proc_ns(inode);
        if (ei->ns_ops != &mntns_operations)
                return false;
  
  struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
                                        int flag)
  {
-       struct mount *res, *p, *q, *r;
-       struct path path;
+       struct mount *res, *p, *q, *r, *parent;
  
        if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt))
                return ERR_PTR(-EINVAL);
                                q = q->mnt_parent;
                        }
                        p = s;
-                       path.mnt = &q->mnt;
-                       path.dentry = p->mnt_mountpoint;
+                       parent = q;
                        q = clone_mnt(p, p->mnt.mnt_root, flag);
                        if (IS_ERR(q))
                                goto out;
                        br_write_lock(&vfsmount_lock);
                        list_add_tail(&q->mnt_list, &res->mnt_list);
-                       attach_mnt(q, &path);
+                       attach_mnt(q, parent, p->mnt_mp);
                        br_write_unlock(&vfsmount_lock);
                }
        }
        return res;
  out:
        if (res) {
-               LIST_HEAD(umount_list);
                br_write_lock(&vfsmount_lock);
-               umount_tree(res, 0, &umount_list);
+               umount_tree(res, 0);
                br_write_unlock(&vfsmount_lock);
-               release_mounts(&umount_list);
        }
        return q;
  }
  struct vfsmount *collect_mounts(struct path *path)
  {
        struct mount *tree;
-       down_write(&namespace_sem);
+       namespace_lock();
        tree = copy_tree(real_mount(path->mnt), path->dentry,
                         CL_COPY_ALL | CL_PRIVATE);
-       up_write(&namespace_sem);
+       namespace_unlock();
        if (IS_ERR(tree))
                return NULL;
        return &tree->mnt;
  
  void drop_collected_mounts(struct vfsmount *mnt)
  {
-       LIST_HEAD(umount_list);
-       down_write(&namespace_sem);
+       namespace_lock();
        br_write_lock(&vfsmount_lock);
-       umount_tree(real_mount(mnt), 0, &umount_list);
+       umount_tree(real_mount(mnt), 0);
        br_write_unlock(&vfsmount_lock);
-       up_write(&namespace_sem);
-       release_mounts(&umount_list);
+       namespace_unlock();
  }
  
  int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
@@@ -1509,11 -1543,11 +1548,11 @@@ static int invent_group_ids(struct moun
   * in allocations.
   */
  static int attach_recursive_mnt(struct mount *source_mnt,
-                       struct path *path, struct path *parent_path)
+                       struct mount *dest_mnt,
+                       struct mountpoint *dest_mp,
+                       struct path *parent_path)
  {
        LIST_HEAD(tree_list);
-       struct mount *dest_mnt = real_mount(path->mnt);
-       struct dentry *dest_dentry = path->dentry;
        struct mount *child, *p;
        int err;
  
                if (err)
                        goto out;
        }
-       err = propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list);
+       err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
        if (err)
                goto out_cleanup_ids;
  
        }
        if (parent_path) {
                detach_mnt(source_mnt, parent_path);
-               attach_mnt(source_mnt, path);
+               attach_mnt(source_mnt, dest_mnt, dest_mp);
                touch_mnt_namespace(source_mnt->mnt_ns);
        } else {
-               mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt);
+               mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt);
                commit_tree(source_mnt);
        }
  
        return err;
  }
  
- static int lock_mount(struct path *path)
+ static struct mountpoint *lock_mount(struct path *path)
  {
        struct vfsmount *mnt;
+       struct dentry *dentry = path->dentry;
  retry:
-       mutex_lock(&path->dentry->d_inode->i_mutex);
-       if (unlikely(cant_mount(path->dentry))) {
-               mutex_unlock(&path->dentry->d_inode->i_mutex);
-               return -ENOENT;
+       mutex_lock(&dentry->d_inode->i_mutex);
+       if (unlikely(cant_mount(dentry))) {
+               mutex_unlock(&dentry->d_inode->i_mutex);
+               return ERR_PTR(-ENOENT);
        }
-       down_write(&namespace_sem);
+       namespace_lock();
        mnt = lookup_mnt(path);
-       if (likely(!mnt))
-               return 0;
-       up_write(&namespace_sem);
+       if (likely(!mnt)) {
+               struct mountpoint *mp = new_mountpoint(dentry);
+               if (IS_ERR(mp)) {
+                       namespace_unlock();
+                       mutex_unlock(&dentry->d_inode->i_mutex);
+                       return mp;
+               }
+               return mp;
+       }
+       namespace_unlock();
        mutex_unlock(&path->dentry->d_inode->i_mutex);
        path_put(path);
        path->mnt = mnt;
-       path->dentry = dget(mnt->mnt_root);
+       dentry = path->dentry = dget(mnt->mnt_root);
        goto retry;
  }
  
- static void unlock_mount(struct path *path)
+ static void unlock_mount(struct mountpoint *where)
  {
-       up_write(&namespace_sem);
-       mutex_unlock(&path->dentry->d_inode->i_mutex);
+       struct dentry *dentry = where->m_dentry;
+       put_mountpoint(where);
+       namespace_unlock();
+       mutex_unlock(&dentry->d_inode->i_mutex);
  }
  
- static int graft_tree(struct mount *mnt, struct path *path)
+ static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp)
  {
        if (mnt->mnt.mnt_sb->s_flags & MS_NOUSER)
                return -EINVAL;
  
-       if (S_ISDIR(path->dentry->d_inode->i_mode) !=
+       if (S_ISDIR(mp->m_dentry->d_inode->i_mode) !=
              S_ISDIR(mnt->mnt.mnt_root->d_inode->i_mode))
                return -ENOTDIR;
  
-       if (d_unlinked(path->dentry))
-               return -ENOENT;
-       return attach_recursive_mnt(mnt, path, NULL);
+       return attach_recursive_mnt(mnt, p, mp, NULL);
  }
  
  /*
@@@ -1633,7 -1674,7 +1679,7 @@@ static int do_change_type(struct path *
        if (!type)
                return -EINVAL;
  
-       down_write(&namespace_sem);
+       namespace_lock();
        if (type == MS_SHARED) {
                err = invent_group_ids(mnt, recurse);
                if (err)
        br_write_unlock(&vfsmount_lock);
  
   out_unlock:
-       up_write(&namespace_sem);
+       namespace_unlock();
        return err;
  }
  
  static int do_loopback(struct path *path, const char *old_name,
                                int recurse)
  {
-       LIST_HEAD(umount_list);
        struct path old_path;
-       struct mount *mnt = NULL, *old;
+       struct mount *mnt = NULL, *old, *parent;
+       struct mountpoint *mp;
        int err;
        if (!old_name || !*old_name)
                return -EINVAL;
        if (mnt_ns_loop(&old_path))
                goto out; 
  
-       err = lock_mount(path);
-       if (err)
+       mp = lock_mount(path);
+       err = PTR_ERR(mp);
+       if (IS_ERR(mp))
                goto out;
  
        old = real_mount(old_path.mnt);
+       parent = real_mount(path->mnt);
  
        err = -EINVAL;
        if (IS_MNT_UNBINDABLE(old))
                goto out2;
  
-       if (!check_mnt(real_mount(path->mnt)) || !check_mnt(old))
+       if (!check_mnt(parent) || !check_mnt(old))
                goto out2;
  
        if (recurse)
                goto out2;
        }
  
-       err = graft_tree(mnt, path);
+       err = graft_tree(mnt, parent, mp);
        if (err) {
                br_write_lock(&vfsmount_lock);
-               umount_tree(mnt, 0, &umount_list);
+               umount_tree(mnt, 0);
                br_write_unlock(&vfsmount_lock);
        }
  out2:
-       unlock_mount(path);
-       release_mounts(&umount_list);
+       unlock_mount(mp);
  out:
        path_put(&old_path);
        return err;
@@@ -1717,9 -1759,6 +1764,9 @@@ static int change_mount_flags(struct vf
        if (readonly_request == __mnt_is_readonly(mnt))
                return 0;
  
 +      if (mnt->mnt_flags & MNT_LOCK_READONLY)
 +              return -EPERM;
 +
        if (readonly_request)
                error = mnt_make_readonly(real_mount(mnt));
        else
@@@ -1786,6 -1825,7 +1833,7 @@@ static int do_move_mount(struct path *p
        struct path old_path, parent_path;
        struct mount *p;
        struct mount *old;
+       struct mountpoint *mp;
        int err;
        if (!old_name || !*old_name)
                return -EINVAL;
        if (err)
                return err;
  
-       err = lock_mount(path);
-       if (err < 0)
+       mp = lock_mount(path);
+       err = PTR_ERR(mp);
+       if (IS_ERR(mp))
                goto out;
  
        old = real_mount(old_path.mnt);
        if (!check_mnt(p) || !check_mnt(old))
                goto out1;
  
-       if (d_unlinked(path->dentry))
-               goto out1;
        err = -EINVAL;
        if (old_path.dentry != old_path.mnt->mnt_root)
                goto out1;
                if (p == old)
                        goto out1;
  
-       err = attach_recursive_mnt(old, path, &parent_path);
+       err = attach_recursive_mnt(old, real_mount(path->mnt), mp, &parent_path);
        if (err)
                goto out1;
  
         * automatically */
        list_del_init(&old->mnt_expire);
  out1:
-       unlock_mount(path);
+       unlock_mount(mp);
  out:
        if (!err)
                path_put(&parent_path);
@@@ -1877,21 -1915,24 +1923,24 @@@ static struct vfsmount *fs_set_subtype(
   */
  static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
  {
+       struct mountpoint *mp;
+       struct mount *parent;
        int err;
  
        mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);
  
-       err = lock_mount(path);
-       if (err)
-               return err;
+       mp = lock_mount(path);
+       if (IS_ERR(mp))
+               return PTR_ERR(mp);
  
+       parent = real_mount(path->mnt);
        err = -EINVAL;
-       if (unlikely(!check_mnt(real_mount(path->mnt)))) {
+       if (unlikely(!check_mnt(parent))) {
                /* that's acceptable only for automounts done in private ns */
                if (!(mnt_flags & MNT_SHRINKABLE))
                        goto unlock;
                /* ... and for those we'd better have mountpoint still alive */
-               if (!real_mount(path->mnt)->mnt_ns)
+               if (!parent->mnt_ns)
                        goto unlock;
        }
  
                goto unlock;
  
        newmnt->mnt.mnt_flags = mnt_flags;
-       err = graft_tree(newmnt, path);
+       err = graft_tree(newmnt, parent, mp);
  
  unlock:
-       unlock_mount(path);
+       unlock_mount(mp);
        return err;
  }
  
@@@ -1982,11 -2023,11 +2031,11 @@@ int finish_automount(struct vfsmount *m
  fail:
        /* remove m from any expiration list it may be on */
        if (!list_empty(&mnt->mnt_expire)) {
-               down_write(&namespace_sem);
+               namespace_lock();
                br_write_lock(&vfsmount_lock);
                list_del_init(&mnt->mnt_expire);
                br_write_unlock(&vfsmount_lock);
-               up_write(&namespace_sem);
+               namespace_unlock();
        }
        mntput(m);
        mntput(m);
   */
  void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list)
  {
-       down_write(&namespace_sem);
+       namespace_lock();
        br_write_lock(&vfsmount_lock);
  
        list_add_tail(&real_mount(mnt)->mnt_expire, expiry_list);
  
        br_write_unlock(&vfsmount_lock);
-       up_write(&namespace_sem);
+       namespace_unlock();
  }
  EXPORT_SYMBOL(mnt_set_expiry);
  
@@@ -2019,12 -2060,11 +2068,11 @@@ void mark_mounts_for_expiry(struct list
  {
        struct mount *mnt, *next;
        LIST_HEAD(graveyard);
-       LIST_HEAD(umounts);
  
        if (list_empty(mounts))
                return;
  
-       down_write(&namespace_sem);
+       namespace_lock();
        br_write_lock(&vfsmount_lock);
  
        /* extract from the expiration list every vfsmount that matches the
        while (!list_empty(&graveyard)) {
                mnt = list_first_entry(&graveyard, struct mount, mnt_expire);
                touch_mnt_namespace(mnt->mnt_ns);
-               umount_tree(mnt, 1, &umounts);
+               umount_tree(mnt, 1);
        }
        br_write_unlock(&vfsmount_lock);
-       up_write(&namespace_sem);
-       release_mounts(&umounts);
+       namespace_unlock();
  }
  
  EXPORT_SYMBOL_GPL(mark_mounts_for_expiry);
@@@ -2104,7 -2142,7 +2150,7 @@@ resume
   *
   * vfsmount_lock must be held for write
   */
- static void shrink_submounts(struct mount *mnt, struct list_head *umounts)
+ static void shrink_submounts(struct mount *mnt)
  {
        LIST_HEAD(graveyard);
        struct mount *m;
                        m = list_first_entry(&graveyard, struct mount,
                                                mnt_expire);
                        touch_mnt_namespace(m->mnt_ns);
-                       umount_tree(m, 1, umounts);
+                       umount_tree(m, 1);
                }
        }
  }
@@@ -2342,14 -2380,14 +2388,14 @@@ static struct mnt_namespace *dup_mnt_ns
        if (IS_ERR(new_ns))
                return new_ns;
  
-       down_write(&namespace_sem);
+       namespace_lock();
        /* First pass: copy the tree topology */
        copy_flags = CL_COPY_ALL | CL_EXPIRE;
        if (user_ns != mnt_ns->user_ns)
 -              copy_flags |= CL_SHARED_TO_SLAVE;
 +              copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;
        new = copy_tree(old, old->mnt.mnt_root, copy_flags);
        if (IS_ERR(new)) {
-               up_write(&namespace_sem);
+               namespace_unlock();
                free_mnt_ns(new_ns);
                return ERR_CAST(new);
        }
                p = next_mnt(p, old);
                q = next_mnt(q, new);
        }
-       up_write(&namespace_sem);
+       namespace_unlock();
  
        if (rootmnt)
                mntput(rootmnt);
@@@ -2550,7 -2588,8 +2596,8 @@@ SYSCALL_DEFINE2(pivot_root, const char 
                const char __user *, put_old)
  {
        struct path new, old, parent_path, root_parent, root;
-       struct mount *new_mnt, *root_mnt;
+       struct mount *new_mnt, *root_mnt, *old_mnt;
+       struct mountpoint *old_mp, *root_mp;
        int error;
  
        if (!may_mount())
                goto out2;
  
        get_fs_root(current->fs, &root);
-       error = lock_mount(&old);
-       if (error)
+       old_mp = lock_mount(&old);
+       error = PTR_ERR(old_mp);
+       if (IS_ERR(old_mp))
                goto out3;
  
        error = -EINVAL;
        new_mnt = real_mount(new.mnt);
        root_mnt = real_mount(root.mnt);
-       if (IS_MNT_SHARED(real_mount(old.mnt)) ||
+       old_mnt = real_mount(old.mnt);
+       if (IS_MNT_SHARED(old_mnt) ||
                IS_MNT_SHARED(new_mnt->mnt_parent) ||
                IS_MNT_SHARED(root_mnt->mnt_parent))
                goto out4;
        error = -ENOENT;
        if (d_unlinked(new.dentry))
                goto out4;
-       if (d_unlinked(old.dentry))
-               goto out4;
        error = -EBUSY;
-       if (new.mnt == root.mnt ||
-           old.mnt == root.mnt)
+       if (new_mnt == root_mnt || old_mnt == root_mnt)
                goto out4; /* loop, on the same file system  */
        error = -EINVAL;
        if (root.mnt->mnt_root != root.dentry)
                goto out4; /* not a mountpoint */
        if (!mnt_has_parent(root_mnt))
                goto out4; /* not attached */
+       root_mp = root_mnt->mnt_mp;
        if (new.mnt->mnt_root != new.dentry)
                goto out4; /* not a mountpoint */
        if (!mnt_has_parent(new_mnt))
                goto out4; /* not attached */
        /* make sure we can reach put_old from new_root */
-       if (!is_path_reachable(real_mount(old.mnt), old.dentry, &new))
+       if (!is_path_reachable(old_mnt, old.dentry, &new))
                goto out4;
+       root_mp->m_count++; /* pin it so it won't go away */
        br_write_lock(&vfsmount_lock);
        detach_mnt(new_mnt, &parent_path);
        detach_mnt(root_mnt, &root_parent);
        /* mount old root on put_old */
-       attach_mnt(root_mnt, &old);
+       attach_mnt(root_mnt, old_mnt, old_mp);
        /* mount new_root on / */
-       attach_mnt(new_mnt, &root_parent);
+       attach_mnt(new_mnt, real_mount(root_parent.mnt), root_mp);
        touch_mnt_namespace(current->nsproxy->mnt_ns);
        br_write_unlock(&vfsmount_lock);
        chroot_fs_refs(&root, &new);
+       put_mountpoint(root_mp);
        error = 0;
  out4:
-       unlock_mount(&old);
+       unlock_mount(old_mp);
        if (!error) {
                path_put(&root_parent);
                path_put(&parent_path);
@@@ -2670,14 -2711,17 +2719,17 @@@ void __init mnt_init(void
                        0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
  
        mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);
+       mountpoint_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);
  
-       if (!mount_hashtable)
+       if (!mount_hashtable || !mountpoint_hashtable)
                panic("Failed to allocate mount hash table\n");
  
        printk(KERN_INFO "Mount-cache hash table entries: %lu\n", HASH_SIZE);
  
        for (u = 0; u < HASH_SIZE; u++)
                INIT_LIST_HEAD(&mount_hashtable[u]);
+       for (u = 0; u < HASH_SIZE; u++)
+               INIT_LIST_HEAD(&mountpoint_hashtable[u]);
  
        br_lock_init(&vfsmount_lock);
  
  
  void put_mnt_ns(struct mnt_namespace *ns)
  {
-       LIST_HEAD(umount_list);
        if (!atomic_dec_and_test(&ns->count))
                return;
-       down_write(&namespace_sem);
+       namespace_lock();
        br_write_lock(&vfsmount_lock);
-       umount_tree(ns->root, 0, &umount_list);
+       umount_tree(ns->root, 0);
        br_write_unlock(&vfsmount_lock);
-       up_write(&namespace_sem);
-       release_mounts(&umount_list);
+       namespace_unlock();
        free_mnt_ns(ns);
  }
  
@@@ -2739,51 -2780,6 +2788,51 @@@ bool our_mnt(struct vfsmount *mnt
        return check_mnt(real_mount(mnt));
  }
  
 +bool current_chrooted(void)
 +{
 +      /* Does the current process have a non-standard root */
 +      struct path ns_root;
 +      struct path fs_root;
 +      bool chrooted;
 +
 +      /* Find the namespace root */
 +      ns_root.mnt = &current->nsproxy->mnt_ns->root->mnt;
 +      ns_root.dentry = ns_root.mnt->mnt_root;
 +      path_get(&ns_root);
 +      while (d_mountpoint(ns_root.dentry) && follow_down_one(&ns_root))
 +              ;
 +
 +      get_fs_root(current->fs, &fs_root);
 +
 +      chrooted = !path_equal(&fs_root, &ns_root);
 +
 +      path_put(&fs_root);
 +      path_put(&ns_root);
 +
 +      return chrooted;
 +}
 +
 +void update_mnt_policy(struct user_namespace *userns)
 +{
 +      struct mnt_namespace *ns = current->nsproxy->mnt_ns;
 +      struct mount *mnt;
 +
 +      down_read(&namespace_sem);
 +      list_for_each_entry(mnt, &ns->list, mnt_list) {
 +              switch (mnt->mnt.mnt_sb->s_magic) {
 +              case SYSFS_MAGIC:
 +                      userns->may_mount_sysfs = true;
 +                      break;
 +              case PROC_SUPER_MAGIC:
 +                      userns->may_mount_proc = true;
 +                      break;
 +              }
 +              if (userns->may_mount_sysfs && userns->may_mount_proc)
 +                      break;
 +      }
 +      up_read(&namespace_sem);
 +}
 +
  static void *mntns_get(struct task_struct *task)
  {
        struct mnt_namespace *ns = NULL;
index c616a70e8cf964a5f1ef5b50b34948b6f0191fa7,1db6d886cbf25f472b1aaeb18eb554ccacbbe059..959815c1e0176139a3531623149fab04d3820697
@@@ -287,9 -287,6 +287,6 @@@ static int inotify_release(struct inod
  
        pr_debug("%s: group=%p\n", __func__, group);
  
-       if (file->f_flags & FASYNC)
-               fsnotify_fasync(-1, file, 0);
        /* free this group, matching get was inotify_init->fsnotify_obtain_group */
        fsnotify_destroy_group(group);
  
@@@ -359,6 -356,7 +356,6 @@@ static int inotify_find_inode(const cha
  }
  
  static int inotify_add_to_idr(struct idr *idr, spinlock_t *idr_lock,
 -                            int *last_wd,
                              struct inotify_inode_mark *i_mark)
  {
        int ret;
        idr_preload(GFP_KERNEL);
        spin_lock(idr_lock);
  
 -      ret = idr_alloc(idr, i_mark, *last_wd + 1, 0, GFP_NOWAIT);
 +      ret = idr_alloc_cyclic(idr, i_mark, 1, 0, GFP_NOWAIT);
        if (ret >= 0) {
                /* we added the mark to the idr, take a reference */
                i_mark->wd = ret;
 -              *last_wd = i_mark->wd;
                fsnotify_get_mark(&i_mark->fsn_mark);
        }
  
@@@ -570,6 -569,7 +567,6 @@@ static int inotify_update_existing_watc
        int add = (arg & IN_MASK_ADD);
        int ret;
  
 -      /* don't allow invalid bits: we don't want flags set */
        mask = inotify_arg_to_mask(arg);
  
        fsn_mark = fsnotify_find_inode_mark(group, inode);
@@@ -620,6 -620,7 +617,6 @@@ static int inotify_new_watch(struct fsn
        struct idr *idr = &group->inotify_data.idr;
        spinlock_t *idr_lock = &group->inotify_data.idr_lock;
  
 -      /* don't allow invalid bits: we don't want flags set */
        mask = inotify_arg_to_mask(arg);
  
        tmp_i_mark = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL);
        if (atomic_read(&group->inotify_data.user->inotify_watches) >= inotify_max_user_watches)
                goto out_err;
  
 -      ret = inotify_add_to_idr(idr, idr_lock, &group->inotify_data.last_wd,
 -                               tmp_i_mark);
 +      ret = inotify_add_to_idr(idr, idr_lock, tmp_i_mark);
        if (ret)
                goto out_err;
  
@@@ -692,6 -694,7 +689,6 @@@ static struct fsnotify_group *inotify_n
  
        spin_lock_init(&group->inotify_data.idr_lock);
        idr_init(&group->inotify_data.idr);
 -      group->inotify_data.last_wd = 0;
        group->inotify_data.user = get_current_user();
  
        if (atomic_inc_return(&group->inotify_data.user->inotify_devs) >
@@@ -745,10 -748,6 +742,10 @@@ SYSCALL_DEFINE3(inotify_add_watch, int
        int ret;
        unsigned flags = 0;
  
 +      /* don't allow invalid bits: we don't want flags set */
 +      if (unlikely(!(mask & ALL_INOTIFY_BITS)))
 +              return -EINVAL;
 +
        f = fdget(fd);
        if (unlikely(!f.file))
                return -EBADF;
diff --combined fs/pnode.c
index 8b29d2164da6aef6edb88b9872368c849e658530,43617258fa6aab3bb9623b9509167f538bdc7386..3d2a7141b87a4b38a1aea383a68810ada1271404
@@@ -9,7 -9,6 +9,7 @@@
  #include <linux/mnt_namespace.h>
  #include <linux/mount.h>
  #include <linux/fs.h>
 +#include <linux/nsproxy.h>
  #include "internal.h"
  #include "pnode.h"
  
@@@ -218,16 -217,14 +218,15 @@@ static struct mount *get_source(struct 
   * @source_mnt: source mount.
   * @tree_list : list of heads of trees to be attached.
   */
- int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
+ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
                    struct mount *source_mnt, struct list_head *tree_list)
  {
 +      struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
        struct mount *m, *child;
        int ret = 0;
        struct mount *prev_dest_mnt = dest_mnt;
        struct mount *prev_src_mnt  = source_mnt;
        LIST_HEAD(tmp_list);
-       LIST_HEAD(umount_list);
  
        for (m = propagation_next(dest_mnt, dest_mnt); m;
                        m = propagation_next(m, dest_mnt)) {
  
                source =  get_source(m, prev_dest_mnt, prev_src_mnt, &type);
  
 +              /* Notice when we are propagating across user namespaces */
 +              if (m->mnt_ns->user_ns != user_ns)
 +                      type |= CL_UNPRIVILEGED;
 +
                child = copy_tree(source, source->mnt.mnt_root, type);
                if (IS_ERR(child)) {
                        ret = PTR_ERR(child);
                        goto out;
                }
  
-               if (is_subdir(dest_dentry, m->mnt.mnt_root)) {
-                       mnt_set_mountpoint(m, dest_dentry, child);
+               if (is_subdir(dest_mp->m_dentry, m->mnt.mnt_root)) {
+                       mnt_set_mountpoint(m, dest_mp, child);
                        list_add_tail(&child->mnt_hash, tree_list);
                } else {
                        /*
@@@ -267,10 -260,9 +266,9 @@@ out
        br_write_lock(&vfsmount_lock);
        while (!list_empty(&tmp_list)) {
                child = list_first_entry(&tmp_list, struct mount, mnt_hash);
-               umount_tree(child, 0, &umount_list);
+               umount_tree(child, 0);
        }
        br_write_unlock(&vfsmount_lock);
-       release_mounts(&umount_list);
        return ret;
  }
  
diff --combined fs/pnode.h
index a0493d5ebfbf52be2eb07a794df459ab2a32cd6a,9eb00ee65bbe42de026bf030def2609f94a2626d..b091445c1c4ac4472c09adb54496f7af98060a42
@@@ -23,7 -23,6 +23,7 @@@
  #define CL_MAKE_SHARED                0x08
  #define CL_PRIVATE            0x10
  #define CL_SHARED_TO_SLAVE    0x20
 +#define CL_UNPRIVILEGED               0x40
  
  static inline void set_mnt_shared(struct mount *mnt)
  {
  }
  
  void change_mnt_propagation(struct mount *, int);
- int propagate_mnt(struct mount *, struct dentry *, struct mount *,
+ int propagate_mnt(struct mount *, struct mountpoint *, struct mount *,
                struct list_head *);
  int propagate_umount(struct list_head *);
  int propagate_mount_busy(struct mount *, int);
  void mnt_release_group_id(struct mount *);
  int get_dominating_id(struct mount *mnt, const struct path *root);
  unsigned int mnt_get_count(struct mount *mnt);
- void mnt_set_mountpoint(struct mount *, struct dentry *,
+ void mnt_set_mountpoint(struct mount *, struct mountpoint *,
                        struct mount *);
- void release_mounts(struct list_head *);
- void umount_tree(struct mount *, int, struct list_head *);
+ void umount_tree(struct mount *, int);
  struct mount *copy_tree(struct mount *, struct dentry *, int);
  bool is_path_reachable(struct mount *, struct dentry *,
                         const struct path *root);
diff --combined fs/proc/base.c
index 3861bcec41ff99e26d4fd80d7ed78448a7169610,8281986693be137530e1cc7f8e063e892e4b3568..dd51e50001fe7aff4e51ffac502d39158ae5581d
@@@ -86,7 -86,6 +86,7 @@@
  #include <linux/fs_struct.h>
  #include <linux/slab.h>
  #include <linux/flex_array.h>
 +#include <linux/posix-timers.h>
  #ifdef CONFIG_HARDWALL
  #include <asm/hardwall.h>
  #endif
@@@ -405,6 -404,37 +405,37 @@@ static const struct file_operations pro
  
  #endif
  
+ #ifdef CONFIG_CGROUPS
+ static int cgroup_open(struct inode *inode, struct file *file)
+ {
+       struct pid *pid = PROC_I(inode)->pid;
+       return single_open(file, proc_cgroup_show, pid);
+ }
+ static const struct file_operations proc_cgroup_operations = {
+       .open           = cgroup_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+ };
+ #endif
+ #ifdef CONFIG_PROC_PID_CPUSET
+ static int cpuset_open(struct inode *inode, struct file *file)
+ {
+       struct pid *pid = PROC_I(inode)->pid;
+       return single_open(file, proc_cpuset_show, pid);
+ }
+ static const struct file_operations proc_cpuset_operations = {
+       .open           = cpuset_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+ };
+ #endif
  static int proc_oom_score(struct task_struct *task, char *buffer)
  {
        unsigned long totalpages = totalram_pages + total_swap_pages;
@@@ -1348,10 -1378,11 +1379,10 @@@ static ssize_t comm_write(struct file *
        struct inode *inode = file_inode(file);
        struct task_struct *p;
        char buffer[TASK_COMM_LEN];
 +      const size_t maxlen = sizeof(buffer) - 1;
  
        memset(buffer, 0, sizeof(buffer));
 -      if (count > sizeof(buffer) - 1)
 -              count = sizeof(buffer) - 1;
 -      if (copy_from_user(buffer, buf, count))
 +      if (copy_from_user(buffer, buf, count > maxlen ? maxlen : count))
                return -EFAULT;
  
        p = get_proc_task(inode);
@@@ -1621,6 -1652,15 +1652,15 @@@ int pid_revalidate(struct dentry *dentr
        return 0;
  }
  
+ int pid_delete_dentry(const struct dentry *dentry)
+ {
+       /* Is the task we represent dead?
+        * If so, then don't put the dentry on the lru list,
+        * kill it immediately.
+        */
+       return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first;
+ }
  const struct dentry_operations pid_dentry_operations =
  {
        .d_revalidate   = pid_revalidate,
@@@ -2013,102 -2053,6 +2053,102 @@@ static const struct file_operations pro
        .llseek         = default_llseek,
  };
  
 +struct timers_private {
 +      struct pid *pid;
 +      struct task_struct *task;
 +      struct sighand_struct *sighand;
 +      struct pid_namespace *ns;
 +      unsigned long flags;
 +};
 +
 +static void *timers_start(struct seq_file *m, loff_t *pos)
 +{
 +      struct timers_private *tp = m->private;
 +
 +      tp->task = get_pid_task(tp->pid, PIDTYPE_PID);
 +      if (!tp->task)
 +              return ERR_PTR(-ESRCH);
 +
 +      tp->sighand = lock_task_sighand(tp->task, &tp->flags);
 +      if (!tp->sighand)
 +              return ERR_PTR(-ESRCH);
 +
 +      return seq_list_start(&tp->task->signal->posix_timers, *pos);
 +}
 +
 +static void *timers_next(struct seq_file *m, void *v, loff_t *pos)
 +{
 +      struct timers_private *tp = m->private;
 +      return seq_list_next(v, &tp->task->signal->posix_timers, pos);
 +}
 +
 +static void timers_stop(struct seq_file *m, void *v)
 +{
 +      struct timers_private *tp = m->private;
 +
 +      if (tp->sighand) {
 +              unlock_task_sighand(tp->task, &tp->flags);
 +              tp->sighand = NULL;
 +      }
 +
 +      if (tp->task) {
 +              put_task_struct(tp->task);
 +              tp->task = NULL;
 +      }
 +}
 +
 +static int show_timer(struct seq_file *m, void *v)
 +{
 +      struct k_itimer *timer;
 +      struct timers_private *tp = m->private;
 +      int notify;
 +      static char *nstr[] = {
 +              [SIGEV_SIGNAL] = "signal",
 +              [SIGEV_NONE] = "none",
 +              [SIGEV_THREAD] = "thread",
 +      };
 +
 +      timer = list_entry((struct list_head *)v, struct k_itimer, list);
 +      notify = timer->it_sigev_notify;
 +
 +      seq_printf(m, "ID: %d\n", timer->it_id);
 +      seq_printf(m, "signal: %d/%p\n", timer->sigq->info.si_signo,
 +                      timer->sigq->info.si_value.sival_ptr);
 +      seq_printf(m, "notify: %s/%s.%d\n",
 +              nstr[notify & ~SIGEV_THREAD_ID],
 +              (notify & SIGEV_THREAD_ID) ? "tid" : "pid",
 +              pid_nr_ns(timer->it_pid, tp->ns));
 +
 +      return 0;
 +}
 +
 +static const struct seq_operations proc_timers_seq_ops = {
 +      .start  = timers_start,
 +      .next   = timers_next,
 +      .stop   = timers_stop,
 +      .show   = show_timer,
 +};
 +
 +static int proc_timers_open(struct inode *inode, struct file *file)
 +{
 +      struct timers_private *tp;
 +
 +      tp = __seq_open_private(file, &proc_timers_seq_ops,
 +                      sizeof(struct timers_private));
 +      if (!tp)
 +              return -ENOMEM;
 +
 +      tp->pid = proc_pid(inode);
 +      tp->ns = inode->i_sb->s_fs_info;
 +      return 0;
 +}
 +
 +static const struct file_operations proc_timers_operations = {
 +      .open           = proc_timers_open,
 +      .read           = seq_read,
 +      .llseek         = seq_lseek,
 +      .release        = seq_release_private,
 +};
  #endif /* CONFIG_CHECKPOINT_RESTORE */
  
  static struct dentry *proc_pident_instantiate(struct inode *dir,
@@@ -2679,9 -2623,6 +2719,9 @@@ static const struct pid_entry tgid_base
        REG("gid_map",    S_IRUGO|S_IWUSR, proc_gid_map_operations),
        REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
  #endif
 +#ifdef CONFIG_CHECKPOINT_RESTORE
 +      REG("timers",     S_IRUGO, proc_timers_operations),
 +#endif
  };
  
  static int proc_tgid_base_readdir(struct file * filp,
@@@ -2893,7 -2834,7 +2933,7 @@@ retry
        return iter;
  }
  
- #define TGID_OFFSET (FIRST_PROCESS_ENTRY)
+ #define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1)
  
  static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
        struct tgid_iter iter)
@@@ -2916,13 -2857,21 +2956,21 @@@ int proc_pid_readdir(struct file * filp
        struct tgid_iter iter;
        struct pid_namespace *ns;
        filldir_t __filldir;
+       loff_t pos = filp->f_pos;
  
-       if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET)
+       if (pos >= PID_MAX_LIMIT + TGID_OFFSET)
                goto out;
  
-       ns = filp->f_dentry->d_sb->s_fs_info;
+       if (pos == TGID_OFFSET - 1) {
+               if (proc_fill_cache(filp, dirent, filldir, "self", 4,
+                                       NULL, NULL, NULL) < 0)
+                       goto out;
+               iter.tgid = 0;
+       } else {
+               iter.tgid = pos - TGID_OFFSET;
+       }
        iter.task = NULL;
-       iter.tgid = filp->f_pos - TGID_OFFSET;
+       ns = filp->f_dentry->d_sb->s_fs_info;
        for (iter = next_tgid(ns, iter);
             iter.task;
             iter.tgid += 1, iter = next_tgid(ns, iter)) {
diff --combined fs/proc/internal.h
index 75710357a51713b78144ca256cef6a785a3cc0f1,04255b6e96b77def4c2fa8ba5b5780868e0bb3d6..d600fb098b6ad3ad51d227709d43161d8a9d0abc
@@@ -1,4 -1,4 +1,4 @@@
- /* internal.h: internal procfs definitions
+ /* Internal procfs definitions
   *
   * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
@@@ -9,62 -9,83 +9,83 @@@
   * 2 of the License, or (at your option) any later version.
   */
  
- #include <linux/sched.h>
  #include <linux/proc_fs.h>
+ #include <linux/proc_ns.h>
+ #include <linux/spinlock.h>
+ #include <linux/atomic.h>
  #include <linux/binfmts.h>
- struct  ctl_table_header;
- struct  mempolicy;
  
- extern struct proc_dir_entry proc_root;
- extern void proc_self_init(void);
- #ifdef CONFIG_PROC_SYSCTL
- extern int proc_sys_init(void);
- extern void sysctl_head_put(struct ctl_table_header *head);
- #else
- static inline void proc_sys_init(void) { }
- static inline void sysctl_head_put(struct ctl_table_header *head) { }
- #endif
- #ifdef CONFIG_NET
- extern int proc_net_init(void);
- #else
- static inline int proc_net_init(void) { return 0; }
- #endif
+ struct ctl_table_header;
+ struct mempolicy;
  
- extern int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
-                               struct pid *pid, struct task_struct *task);
- extern int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
-                               struct pid *pid, struct task_struct *task);
- extern int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
-                               struct pid *pid, struct task_struct *task);
- extern int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
-                               struct pid *pid, struct task_struct *task);
- extern loff_t mem_lseek(struct file *file, loff_t offset, int orig);
+ /*
+  * This is not completely implemented yet. The idea is to
+  * create an in-memory tree (like the actual /proc filesystem
+  * tree) of these proc_dir_entries, so that we can dynamically
+  * add new files to /proc.
+  *
+  * The "next" pointer creates a linked list of one /proc directory,
+  * while parent/subdir create the directory structure (every
+  * /proc file has a parent, but "subdir" is NULL for all
+  * non-directory entries).
+  */
+ struct proc_dir_entry {
+       unsigned int low_ino;
+       umode_t mode;
+       nlink_t nlink;
+       kuid_t uid;
+       kgid_t gid;
+       loff_t size;
+       const struct inode_operations *proc_iops;
+       const struct file_operations *proc_fops;
+       struct proc_dir_entry *next, *parent, *subdir;
+       void *data;
+       atomic_t count;         /* use count */
+       atomic_t in_use;        /* number of callers into module in progress; */
+                       /* negative -> it's going away RSN */
+       struct completion *pde_unload_completion;
+       struct list_head pde_openers;   /* who did ->open, but not ->release */
+       spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
+       u8 namelen;
+       char name[];
+ };
  
- extern const struct file_operations proc_tid_children_operations;
- extern const struct file_operations proc_pid_maps_operations;
- extern const struct file_operations proc_tid_maps_operations;
- extern const struct file_operations proc_pid_numa_maps_operations;
- extern const struct file_operations proc_tid_numa_maps_operations;
- extern const struct file_operations proc_pid_smaps_operations;
- extern const struct file_operations proc_tid_smaps_operations;
- extern const struct file_operations proc_clear_refs_operations;
- extern const struct file_operations proc_pagemap_operations;
- extern const struct file_operations proc_net_operations;
- extern const struct inode_operations proc_net_inode_operations;
- extern const struct inode_operations proc_pid_link_inode_operations;
+ union proc_op {
+       int (*proc_get_link)(struct dentry *, struct path *);
+       int (*proc_read)(struct task_struct *task, char *page);
+       int (*proc_show)(struct seq_file *m,
+               struct pid_namespace *ns, struct pid *pid,
+               struct task_struct *task);
+ };
  
- struct proc_maps_private {
+ struct proc_inode {
        struct pid *pid;
-       struct task_struct *task;
- #ifdef CONFIG_MMU
-       struct vm_area_struct *tail_vma;
- #endif
- #ifdef CONFIG_NUMA
-       struct mempolicy *task_mempolicy;
- #endif
+       int fd;
+       union proc_op op;
+       struct proc_dir_entry *pde;
+       struct ctl_table_header *sysctl;
+       struct ctl_table *sysctl_entry;
+       struct proc_ns ns;
+       struct inode vfs_inode;
  };
  
- void proc_init_inodecache(void);
+ /*
+  * General functions
+  */
+ static inline struct proc_inode *PROC_I(const struct inode *inode)
+ {
+       return container_of(inode, struct proc_inode, vfs_inode);
+ }
+ static inline struct proc_dir_entry *PDE(const struct inode *inode)
+ {
+       return PROC_I(inode)->pde;
+ }
+ static inline void *__PDE_DATA(const struct inode *inode)
+ {
+       return PDE(inode)->data;
+ }
  
  static inline struct pid *proc_pid(struct inode *inode)
  {
@@@ -76,11 -97,6 +97,6 @@@ static inline struct task_struct *get_p
        return get_pid_task(proc_pid(inode), PIDTYPE_PID);
  }
  
- static inline int proc_fd(struct inode *inode)
- {
-       return PROC_I(inode)->fd;
- }
  static inline int task_dumpable(struct task_struct *task)
  {
        int dumpable = 0;
        return 0;
  }
  
- static inline int pid_delete_dentry(const struct dentry * dentry)
- {
-       /* Is the task we represent dead?
-        * If so, then don't put the dentry on the lru list,
-        * kill it immediately.
-        */
-       return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first;
- }
  static inline unsigned name_to_int(struct dentry *dentry)
  {
        const char *name = dentry->d_name.name;
        return ~0U;
  }
  
- struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *ino,
-               struct dentry *dentry);
- int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
-               filldir_t filldir);
+ /*
+  * Offset of the first process in the /proc root directory..
+  */
+ #define FIRST_PROCESS_ENTRY 256
+ /* Worst case buffer size needed for holding an integer. */
+ #define PROC_NUMBUF 13
  
- struct pde_opener {
-       struct inode *inode;
-       struct file *file;
-       int (*release)(struct inode *, struct file *);
-       struct list_head lh;
- };
- void pde_users_dec(struct proc_dir_entry *pde);
+ /*
+  * array.c
+  */
+ extern const struct file_operations proc_tid_children_operations;
  
+ extern int proc_tid_stat(struct seq_file *, struct pid_namespace *,
+                        struct pid *, struct task_struct *);
+ extern int proc_tgid_stat(struct seq_file *, struct pid_namespace *,
+                         struct pid *, struct task_struct *);
+ extern int proc_pid_status(struct seq_file *, struct pid_namespace *,
+                          struct pid *, struct task_struct *);
+ extern int proc_pid_statm(struct seq_file *, struct pid_namespace *,
+                         struct pid *, struct task_struct *);
+ /*
+  * base.c
+  */
+ extern const struct dentry_operations pid_dentry_operations;
+ extern int pid_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+ extern int proc_setattr(struct dentry *, struct iattr *);
+ extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *);
+ extern int pid_revalidate(struct dentry *, unsigned int);
+ extern int pid_delete_dentry(const struct dentry *);
+ extern int proc_pid_readdir(struct file *, void *, filldir_t);
+ extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int);
+ extern loff_t mem_lseek(struct file *, loff_t, int);
+ /* Lookups */
+ typedef struct dentry *instantiate_t(struct inode *, struct dentry *,
+                                    struct task_struct *, const void *);
+ extern int proc_fill_cache(struct file *, void *, filldir_t, const char *, int,
+                          instantiate_t, struct task_struct *, const void *);
+ /*
+  * generic.c
+  */
  extern spinlock_t proc_subdir_lock;
  
- struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int);
- int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
- unsigned long task_vsize(struct mm_struct *);
- unsigned long task_statm(struct mm_struct *,
-       unsigned long *, unsigned long *, unsigned long *, unsigned long *);
- void task_mem(struct seq_file *, struct mm_struct *);
+ extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int);
+ extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *,
+                                    struct dentry *);
+ extern int proc_readdir(struct file *, void *, filldir_t);
+ extern int proc_readdir_de(struct proc_dir_entry *, struct file *, void *, filldir_t);
  
  static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde)
  {
        atomic_inc(&pde->count);
        return pde;
  }
- void pde_put(struct proc_dir_entry *pde);
- int proc_fill_super(struct super_block *);
- struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *);
- int proc_remount(struct super_block *sb, int *flags, char *data);
+ extern void pde_put(struct proc_dir_entry *);
  
  /*
-  * These are generic /proc routines that use the internal
-  * "struct proc_dir_entry" tree to traverse the filesystem.
-  *
-  * The /proc root directory has extended versions to take care
-  * of the /proc/<pid> subdirectories.
+  * inode.c
   */
- int proc_readdir(struct file *, void *, filldir_t);
- struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int);
+ struct pde_opener {
+       struct file *file;
+       struct list_head lh;
+       int closing;
+       struct completion *c;
+ };
  
+ extern const struct inode_operations proc_pid_link_inode_operations;
  
+ extern void proc_init_inodecache(void);
+ extern struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *);
+ extern int proc_fill_super(struct super_block *);
+ extern void proc_entry_rundown(struct proc_dir_entry *);
  
- /* Lookups */
- typedef struct dentry *instantiate_t(struct inode *, struct dentry *,
-                               struct task_struct *, const void *);
- int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
-       const char *name, int len,
-       instantiate_t instantiate, struct task_struct *task, const void *ptr);
- int pid_revalidate(struct dentry *dentry, unsigned int flags);
- struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task);
- extern const struct dentry_operations pid_dentry_operations;
- int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
- int proc_setattr(struct dentry *dentry, struct iattr *attr);
 -/*
 - * mmu.c
 - */
 -struct vmalloc_info {
 -      unsigned long   used;
 -      unsigned long   largest_chunk;
 -};
 -
 -#ifdef CONFIG_MMU
 -#define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START)
 -extern void get_vmalloc_info(struct vmalloc_info *);
 -
 -#else
 -#define VMALLOC_TOTAL 0UL
 -static inline void get_vmalloc_info(struct vmalloc_info *vmi)
 -{
 -      vmi->used = 0;
 -      vmi->largest_chunk = 0;
 -}
 -#endif
 -
+ /*
+  * proc_devtree.c
+  */
+ #ifdef CONFIG_PROC_DEVICETREE
+ extern void proc_device_tree_init(void);
+ #endif
  
+ /*
+  * proc_namespaces.c
+  */
  extern const struct inode_operations proc_ns_dir_inode_operations;
  extern const struct file_operations proc_ns_dir_operations;
  
+ /*
+  * proc_net.c
+  */
+ extern const struct file_operations proc_net_operations;
+ extern const struct inode_operations proc_net_inode_operations;
+ #ifdef CONFIG_NET
+ extern int proc_net_init(void);
+ #else
+ static inline int proc_net_init(void) { return 0; }
+ #endif
+ /*
+  * proc_self.c
+  */
+ extern int proc_setup_self(struct super_block *);
+ /*
+  * proc_sysctl.c
+  */
+ #ifdef CONFIG_PROC_SYSCTL
+ extern int proc_sys_init(void);
+ extern void sysctl_head_put(struct ctl_table_header *);
+ #else
+ static inline void proc_sys_init(void) { }
+ static inline void sysctl_head_put(struct ctl_table_header *head) { }
+ #endif
+ /*
+  * proc_tty.c
+  */
+ #ifdef CONFIG_TTY
+ extern void proc_tty_init(void);
+ #else
+ static inline void proc_tty_init(void) {}
+ #endif
+ /*
+  * root.c
+  */
+ extern struct proc_dir_entry proc_root;
+ extern void proc_self_init(void);
+ extern int proc_remount(struct super_block *, int *, char *);
+ /*
+  * task_[no]mmu.c
+  */
+ struct proc_maps_private {
+       struct pid *pid;
+       struct task_struct *task;
+ #ifdef CONFIG_MMU
+       struct vm_area_struct *tail_vma;
+ #endif
+ #ifdef CONFIG_NUMA
+       struct mempolicy *task_mempolicy;
+ #endif
+ };
+ extern const struct file_operations proc_pid_maps_operations;
+ extern const struct file_operations proc_tid_maps_operations;
+ extern const struct file_operations proc_pid_numa_maps_operations;
+ extern const struct file_operations proc_tid_numa_maps_operations;
+ extern const struct file_operations proc_pid_smaps_operations;
+ extern const struct file_operations proc_tid_smaps_operations;
+ extern const struct file_operations proc_clear_refs_operations;
+ extern const struct file_operations proc_pagemap_operations;
+ extern unsigned long task_vsize(struct mm_struct *);
+ extern unsigned long task_statm(struct mm_struct *,
+                               unsigned long *, unsigned long *,
+                               unsigned long *, unsigned long *);
+ extern void task_mem(struct seq_file *, struct mm_struct *);
diff --combined fs/proc/kcore.c
index f6a13f489e305a673fd2717f16146aa6184b7ab1,13cf87c4686fccd1a29fe10f229172e9927cdade..0a22194e5d586f2dc3e7488702475746ed5f9da4
  
  #include <linux/mm.h>
  #include <linux/proc_fs.h>
+ #include <linux/kcore.h>
  #include <linux/user.h>
  #include <linux/capability.h>
  #include <linux/elf.h>
  #include <linux/elfcore.h>
 +#include <linux/notifier.h>
  #include <linux/vmalloc.h>
  #include <linux/highmem.h>
  #include <linux/printk.h>
@@@ -28,6 -28,7 +29,7 @@@
  #include <linux/ioport.h>
  #include <linux/memory.h>
  #include <asm/sections.h>
+ #include "internal.h"
  
  #define CORE_STR "CORE"
  
@@@ -565,6 -566,7 +567,6 @@@ static const struct file_operations pro
        .llseek         = default_llseek,
  };
  
 -#ifdef CONFIG_MEMORY_HOTPLUG
  /* just remember that we have to update kcore */
  static int __meminit kcore_callback(struct notifier_block *self,
                                    unsigned long action, void *arg)
        }
        return NOTIFY_OK;
  }
 -#endif
  
 +static struct notifier_block kcore_callback_nb __meminitdata = {
 +      .notifier_call = kcore_callback,
 +      .priority = 0,
 +};
  
  static struct kcore_list kcore_vmalloc;
  
@@@ -634,7 -633,7 +636,7 @@@ static int __init proc_kcore_init(void
        add_modules_range();
        /* Store direct-map area from physical memory map */
        kcore_update_ram();
 -      hotplug_memory_notifier(kcore_callback, 0);
 +      register_hotmemory_notifier(&kcore_callback_nb);
  
        return 0;
  }
diff --combined fs/proc/root.c
index 9c7fab1d23f0d17d68446bf3d46ce1a906ae0907,20834b3c8ea3e312dbaffe5347d99dbfb3eef154..41a6ea93f486ff81b6b112821339a66f0b020324
@@@ -16,7 -16,6 +16,7 @@@
  #include <linux/sched.h>
  #include <linux/module.h>
  #include <linux/bitops.h>
 +#include <linux/user_namespace.h>
  #include <linux/mount.h>
  #include <linux/pid_namespace.h>
  #include <linux/parser.h>
@@@ -109,9 -108,6 +109,9 @@@ static struct dentry *proc_mount(struc
        } else {
                ns = task_active_pid_ns(current);
                options = data;
 +
 +              if (!current_user_ns()->may_mount_proc)
 +                      return ERR_PTR(-EPERM);
        }
  
        sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns);
@@@ -141,6 -137,8 +141,8 @@@ static void proc_kill_sb(struct super_b
        struct pid_namespace *ns;
  
        ns = (struct pid_namespace *)sb->s_fs_info;
+       if (ns->proc_self)
+               dput(ns->proc_self);
        kill_anon_super(sb);
        put_pid_ns(ns);
  }
diff --combined fs/read_write.c
index 8274a794253b65b55369ca64f9e2872c77c315c3,a1f4d44cbc03e4ab9e64bcc4f035d8702a8104c6..605dbbcb19734363150668f2dd37e9a9fbf65276
@@@ -128,7 -128,7 +128,7 @@@ EXPORT_SYMBOL(generic_file_llseek_size)
   *
   * This is a generic implemenation of ->llseek useable for all normal local
   * filesystems.  It just updates the file offset to the value specified by
 - * @offset and @whence under i_mutex.
 + * @offset and @whence.
   */
  loff_t generic_file_llseek(struct file *file, loff_t offset, int whence)
  {
@@@ -424,9 -424,6 +424,9 @@@ ssize_t __kernel_write(struct file *fil
        const char __user *p;
        ssize_t ret;
  
 +      if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))
 +              return -EINVAL;
 +
        old_fs = get_fs();
        set_fs(get_ds());
        p = (__force const char __user *)buf;
@@@ -459,6 -456,7 +459,7 @@@ ssize_t vfs_write(struct file *file, co
        ret = rw_verify_area(WRITE, file, pos, count);
        if (ret >= 0) {
                count = ret;
+               file_start_write(file);
                if (file->f_op->write)
                        ret = file->f_op->write(file, buf, count, pos);
                else
                        add_wchar(current, ret);
                }
                inc_syscw(current);
+               file_end_write(file);
        }
  
        return ret;
@@@ -515,8 -514,8 +517,8 @@@ SYSCALL_DEFINE3(write, unsigned int, fd
        return ret;
  }
  
 -SYSCALL_DEFINE(pread64)(unsigned int fd, char __user *buf,
 -                      size_t count, loff_t pos)
 +SYSCALL_DEFINE4(pread64, unsigned int, fd, char __user *, buf,
 +                      size_t, count, loff_t, pos)
  {
        struct fd f;
        ssize_t ret = -EBADF;
  
        return ret;
  }
 -#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
 -asmlinkage long SyS_pread64(long fd, long buf, long count, loff_t pos)
 -{
 -      return SYSC_pread64((unsigned int) fd, (char __user *) buf,
 -                          (size_t) count, pos);
 -}
 -SYSCALL_ALIAS(sys_pread64, SyS_pread64);
 -#endif
  
 -SYSCALL_DEFINE(pwrite64)(unsigned int fd, const char __user *buf,
 -                       size_t count, loff_t pos)
 +SYSCALL_DEFINE4(pwrite64, unsigned int, fd, const char __user *, buf,
 +                       size_t, count, loff_t, pos)
  {
        struct fd f;
        ssize_t ret = -EBADF;
  
        return ret;
  }
 -#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
 -asmlinkage long SyS_pwrite64(long fd, long buf, long count, loff_t pos)
 -{
 -      return SYSC_pwrite64((unsigned int) fd, (const char __user *) buf,
 -                           (size_t) count, pos);
 -}
 -SYSCALL_ALIAS(sys_pwrite64, SyS_pwrite64);
 -#endif
  
  /*
   * Reduce an iovec's length in-place.  Return the resulting number of segments
@@@ -576,7 -591,7 +578,7 @@@ unsigned long iov_shorten(struct iovec 
  }
  EXPORT_SYMBOL(iov_shorten);
  
- ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
+ static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
                unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
  {
        struct kiocb kiocb;
  }
  
  /* Do it by hand, with file-ops */
- ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
+ static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
                unsigned long nr_segs, loff_t *ppos, io_fn_t fn)
  {
        struct iovec *vector = iov;
@@@ -743,6 -758,7 +745,7 @@@ static ssize_t do_readv_writev(int type
        } else {
                fn = (io_fn_t)file->f_op->write;
                fnv = file->f_op->aio_write;
+               file_start_write(file);
        }
  
        if (fnv)
        else
                ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
  
+       if (type != READ)
+               file_end_write(file);
  out:
        if (iov != iovstack)
                kfree(iov);
@@@ -881,8 -900,203 +887,203 @@@ SYSCALL_DEFINE5(pwritev, unsigned long
        return ret;
  }
  
 -ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, size_t count,
 -                  loff_t max)
+ #ifdef CONFIG_COMPAT
+ static ssize_t compat_do_readv_writev(int type, struct file *file,
+                              const struct compat_iovec __user *uvector,
+                              unsigned long nr_segs, loff_t *pos)
+ {
+       compat_ssize_t tot_len;
+       struct iovec iovstack[UIO_FASTIOV];
+       struct iovec *iov = iovstack;
+       ssize_t ret;
+       io_fn_t fn;
+       iov_fn_t fnv;
+       ret = -EINVAL;
+       if (!file->f_op)
+               goto out;
+       ret = -EFAULT;
+       if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
+               goto out;
+       ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
+                                              UIO_FASTIOV, iovstack, &iov);
+       if (ret <= 0)
+               goto out;
+       tot_len = ret;
+       ret = rw_verify_area(type, file, pos, tot_len);
+       if (ret < 0)
+               goto out;
+       fnv = NULL;
+       if (type == READ) {
+               fn = file->f_op->read;
+               fnv = file->f_op->aio_read;
+       } else {
+               fn = (io_fn_t)file->f_op->write;
+               fnv = file->f_op->aio_write;
+               file_start_write(file);
+       }
+       if (fnv)
+               ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
+                                               pos, fnv);
+       else
+               ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
+       if (type != READ)
+               file_end_write(file);
+ out:
+       if (iov != iovstack)
+               kfree(iov);
+       if ((ret + (type == READ)) > 0) {
+               if (type == READ)
+                       fsnotify_access(file);
+               else
+                       fsnotify_modify(file);
+       }
+       return ret;
+ }
+ static size_t compat_readv(struct file *file,
+                          const struct compat_iovec __user *vec,
+                          unsigned long vlen, loff_t *pos)
+ {
+       ssize_t ret = -EBADF;
+       if (!(file->f_mode & FMODE_READ))
+               goto out;
+       ret = -EINVAL;
+       if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
+               goto out;
+       ret = compat_do_readv_writev(READ, file, vec, vlen, pos);
+ out:
+       if (ret > 0)
+               add_rchar(current, ret);
+       inc_syscr(current);
+       return ret;
+ }
+ COMPAT_SYSCALL_DEFINE3(readv, unsigned long, fd,
+               const struct compat_iovec __user *,vec,
+               unsigned long, vlen)
+ {
+       struct fd f = fdget(fd);
+       ssize_t ret;
+       loff_t pos;
+       if (!f.file)
+               return -EBADF;
+       pos = f.file->f_pos;
+       ret = compat_readv(f.file, vec, vlen, &pos);
+       f.file->f_pos = pos;
+       fdput(f);
+       return ret;
+ }
+ COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
+               const struct compat_iovec __user *,vec,
+               unsigned long, vlen, loff_t, pos)
+ {
+       struct fd f;
+       ssize_t ret;
+       if (pos < 0)
+               return -EINVAL;
+       f = fdget(fd);
+       if (!f.file)
+               return -EBADF;
+       ret = -ESPIPE;
+       if (f.file->f_mode & FMODE_PREAD)
+               ret = compat_readv(f.file, vec, vlen, &pos);
+       fdput(f);
+       return ret;
+ }
+ COMPAT_SYSCALL_DEFINE5(preadv, unsigned long, fd,
+               const struct compat_iovec __user *,vec,
+               unsigned long, vlen, u32, pos_low, u32, pos_high)
+ {
+       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
+       return compat_sys_preadv64(fd, vec, vlen, pos);
+ }
+ static size_t compat_writev(struct file *file,
+                           const struct compat_iovec __user *vec,
+                           unsigned long vlen, loff_t *pos)
+ {
+       ssize_t ret = -EBADF;
+       if (!(file->f_mode & FMODE_WRITE))
+               goto out;
+       ret = -EINVAL;
+       if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
+               goto out;
+       ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos);
+ out:
+       if (ret > 0)
+               add_wchar(current, ret);
+       inc_syscw(current);
+       return ret;
+ }
+ COMPAT_SYSCALL_DEFINE3(writev, unsigned long, fd,
+               const struct compat_iovec __user *, vec,
+               unsigned long, vlen)
+ {
+       struct fd f = fdget(fd);
+       ssize_t ret;
+       loff_t pos;
+       if (!f.file)
+               return -EBADF;
+       pos = f.file->f_pos;
+       ret = compat_writev(f.file, vec, vlen, &pos);
+       f.file->f_pos = pos;
+       fdput(f);
+       return ret;
+ }
+ COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
+               const struct compat_iovec __user *,vec,
+               unsigned long, vlen, loff_t, pos)
+ {
+       struct fd f;
+       ssize_t ret;
+       if (pos < 0)
+               return -EINVAL;
+       f = fdget(fd);
+       if (!f.file)
+               return -EBADF;
+       ret = -ESPIPE;
+       if (f.file->f_mode & FMODE_PWRITE)
+               ret = compat_writev(f.file, vec, vlen, &pos);
+       fdput(f);
+       return ret;
+ }
+ COMPAT_SYSCALL_DEFINE5(pwritev, unsigned long, fd,
+               const struct compat_iovec __user *,vec,
+               unsigned long, vlen, u32, pos_low, u32, pos_high)
+ {
+       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
+       return compat_sys_pwritev64(fd, vec, vlen, pos);
+ }
+ #endif
 +static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
 +                         size_t count, loff_t max)
  {
        struct fd in, out;
        struct inode *in_inode, *out_inode;
@@@ -1006,43 -1220,3 +1207,43 @@@ SYSCALL_DEFINE4(sendfile64, int, out_fd
  
        return do_sendfile(out_fd, in_fd, NULL, count, 0);
  }
 +
 +#ifdef CONFIG_COMPAT
 +COMPAT_SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd,
 +              compat_off_t __user *, offset, compat_size_t, count)
 +{
 +      loff_t pos;
 +      off_t off;
 +      ssize_t ret;
 +
 +      if (offset) {
 +              if (unlikely(get_user(off, offset)))
 +                      return -EFAULT;
 +              pos = off;
 +              ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
 +              if (unlikely(put_user(pos, offset)))
 +                      return -EFAULT;
 +              return ret;
 +      }
 +
 +      return do_sendfile(out_fd, in_fd, NULL, count, 0);
 +}
 +
 +COMPAT_SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd,
 +              compat_loff_t __user *, offset, compat_size_t, count)
 +{
 +      loff_t pos;
 +      ssize_t ret;
 +
 +      if (offset) {
 +              if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
 +                      return -EFAULT;
 +              ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
 +              if (unlikely(put_user(pos, offset)))
 +                      return -EFAULT;
 +              return ret;
 +      }
 +
 +      return do_sendfile(out_fd, in_fd, NULL, count, 0);
 +}
 +#endif
diff --combined fs/read_write.h
index d07b954c6e0c39afc06f99b40eb5bbcb2f0cc60b,b98780664ffa7dd3bf89d62711f5f2988cb6053c..0ec530d9305b458fde80f94078e57d5f00d93dbd
@@@ -7,8 -7,6 +7,3 @@@
  typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
  typedef ssize_t (*iov_fn_t)(struct kiocb *, const struct iovec *,
                unsigned long, loff_t);
--
- ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
-               unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn);
- ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
-               unsigned long nr_segs, loff_t *ppos, io_fn_t fn);
 -ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, size_t count,
 -                  loff_t max);
diff --combined fs/splice.c
index 6b485b8753bdb9dd09f17fd122f0cdc3f44a9c3a,45e645b15d9271bb43485d8946303aeb3a32cd4e..e6b25598c8c413d66026f96e6d6d1b351e28b62c
@@@ -31,7 -31,6 +31,7 @@@
  #include <linux/security.h>
  #include <linux/gfp.h>
  #include <linux/socket.h>
 +#include <linux/compat.h>
  #include "internal.h"
  
  /*
@@@ -219,7 -218,7 +219,7 @@@ ssize_t splice_to_pipe(struct pipe_inod
                        page_nr++;
                        ret += buf->len;
  
-                       if (pipe->inode)
+                       if (pipe->files)
                                do_wakeup = 1;
  
                        if (!--spd->nr_pages)
@@@ -829,7 -828,7 +829,7 @@@ int splice_from_pipe_feed(struct pipe_i
                        ops->release(pipe, buf);
                        pipe->curbuf = (pipe->curbuf + 1) & (pipe->buffers - 1);
                        pipe->nrbufs--;
-                       if (pipe->inode)
+                       if (pipe->files)
                                sd->need_wakeup = true;
                }
  
@@@ -1001,8 -1000,6 +1001,6 @@@ generic_file_splice_write(struct pipe_i
        };
        ssize_t ret;
  
-       sb_start_write(inode->i_sb);
        pipe_lock(pipe);
  
        splice_from_pipe_begin(&sd);
                        *ppos += ret;
                balance_dirty_pages_ratelimited(mapping);
        }
-       sb_end_write(inode->i_sb);
  
        return ret;
  }
@@@ -1118,7 -1114,10 +1115,10 @@@ static long do_splice_from(struct pipe_
        else
                splice_write = default_file_splice_write;
  
-       return splice_write(pipe, out, ppos, len, flags);
+       file_start_write(out);
+       ret = splice_write(pipe, out, ppos, len, flags);
+       file_end_write(out);
+       return ret;
  }
  
  /*
@@@ -1184,7 -1183,7 +1184,7 @@@ ssize_t splice_direct_to_actor(struct f
         */
        pipe = current->splice_pipe;
        if (unlikely(!pipe)) {
-               pipe = alloc_pipe_info(NULL);
+               pipe = alloc_pipe_info();
                if (!pipe)
                        return -ENOMEM;
  
@@@ -1691,27 -1690,6 +1691,27 @@@ SYSCALL_DEFINE4(vmsplice, int, fd, cons
        return error;
  }
  
 +#ifdef CONFIG_COMPAT
 +COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, iov32,
 +                  unsigned int, nr_segs, unsigned int, flags)
 +{
 +      unsigned i;
 +      struct iovec __user *iov;
 +      if (nr_segs > UIO_MAXIOV)
 +              return -EINVAL;
 +      iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
 +      for (i = 0; i < nr_segs; i++) {
 +              struct compat_iovec v;
 +              if (get_user(v.iov_base, &iov32[i].iov_base) ||
 +                  get_user(v.iov_len, &iov32[i].iov_len) ||
 +                  put_user(compat_ptr(v.iov_base), &iov[i].iov_base) ||
 +                  put_user(v.iov_len, &iov[i].iov_len))
 +                      return -EFAULT;
 +      }
 +      return sys_vmsplice(fd, iov, nr_segs, flags);
 +}
 +#endif
 +
  SYSCALL_DEFINE6(splice, int, fd_in, loff_t __user *, off_in,
                int, fd_out, loff_t __user *, off_out,
                size_t, len, unsigned int, flags)
diff --combined include/linux/cgroup.h
index 646ab9d15e4249f70784290a4f50ec5ad0de9811,68f2157b71d4376dd9a08327dc358b71a0301fff..3bff9ce09cf7b92fcd04fb06c19864b0a07df91b
@@@ -19,7 -19,6 +19,7 @@@
  #include <linux/idr.h>
  #include <linux/workqueue.h>
  #include <linux/xattr.h>
 +#include <linux/fs.h>
  
  #ifdef CONFIG_CGROUPS
  
@@@ -31,6 -30,10 +31,6 @@@ struct css_id
  
  extern int cgroup_init_early(void);
  extern int cgroup_init(void);
 -extern void cgroup_lock(void);
 -extern int cgroup_lock_is_held(void);
 -extern bool cgroup_lock_live_group(struct cgroup *cgrp);
 -extern void cgroup_unlock(void);
  extern void cgroup_fork(struct task_struct *p);
  extern void cgroup_post_fork(struct task_struct *p);
  extern void cgroup_exit(struct task_struct *p, int run_callbacks);
@@@ -39,27 -42,16 +39,27 @@@ extern int cgroupstats_build(struct cgr
  extern int cgroup_load_subsys(struct cgroup_subsys *ss);
  extern void cgroup_unload_subsys(struct cgroup_subsys *ss);
  
- extern const struct file_operations proc_cgroup_operations;
+ extern int proc_cgroup_show(struct seq_file *, void *);
  
 -/* Define the enumeration of all builtin cgroup subsystems */
 +/*
 + * Define the enumeration of all cgroup subsystems.
 + *
 + * We define ids for builtin subsystems and then modular ones.
 + */
  #define SUBSYS(_x) _x ## _subsys_id,
 -#define IS_SUBSYS_ENABLED(option) IS_ENABLED(option)
  enum cgroup_subsys_id {
 +#define IS_SUBSYS_ENABLED(option) IS_BUILTIN(option)
  #include <linux/cgroup_subsys.h>
 +#undef IS_SUBSYS_ENABLED
 +      CGROUP_BUILTIN_SUBSYS_COUNT,
 +
 +      __CGROUP_SUBSYS_TEMP_PLACEHOLDER = CGROUP_BUILTIN_SUBSYS_COUNT - 1,
 +
 +#define IS_SUBSYS_ENABLED(option) IS_MODULE(option)
 +#include <linux/cgroup_subsys.h>
 +#undef IS_SUBSYS_ENABLED
        CGROUP_SUBSYS_COUNT,
  };
 -#undef IS_SUBSYS_ENABLED
  #undef SUBSYS
  
  /* Per-subsystem/per-cgroup state maintained by the system. */
@@@ -156,13 -148,6 +156,13 @@@ enum 
         * specified at mount time and thus is implemented here.
         */
        CGRP_CPUSET_CLONE_CHILDREN,
 +      /* see the comment above CGRP_ROOT_SANE_BEHAVIOR for details */
 +      CGRP_SANE_BEHAVIOR,
 +};
 +
 +struct cgroup_name {
 +      struct rcu_head rcu_head;
 +      char name[];
  };
  
  struct cgroup {
        struct cgroup *parent;          /* my parent */
        struct dentry *dentry;          /* cgroup fs entry, RCU protected */
  
 +      /*
 +       * This is a copy of dentry->d_name, and it's needed because
 +       * we can't use dentry->d_name in cgroup_path().
 +       *
 +       * You must acquire rcu_read_lock() to access cgrp->name, and
 +       * the only place that can change it is rename(), which is
 +       * protected by parent dir's i_mutex.
 +       *
 +       * Normally you should use cgroup_name() wrapper rather than
 +       * access it directly.
 +       */
 +      struct cgroup_name __rcu *name;
 +
        /* Private pointers for each registered subsystem */
        struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
  
        struct cgroupfs_root *root;
 -      struct cgroup *top_cgroup;
  
        /*
         * List of cg_cgroup_links pointing at css_sets with
        struct simple_xattrs xattrs;
  };
  
 +#define MAX_CGROUP_ROOT_NAMELEN 64
 +
 +/* cgroupfs_root->flags */
 +enum {
 +      /*
 +       * Unfortunately, cgroup core and various controllers are riddled
 +       * with idiosyncrasies and pointless options.  The following flag,
 +       * when set, will force sane behavior - some options are forced on,
 +       * others are disallowed, and some controllers will change their
 +       * hierarchical or other behaviors.
 +       *
 +       * The set of behaviors affected by this flag are still being
 +       * determined and developed and the mount option for this flag is
 +       * prefixed with __DEVEL__.  The prefix will be dropped once we
 +       * reach the point where all behaviors are compatible with the
 +       * planned unified hierarchy, which will automatically turn on this
 +       * flag.
 +       *
 +       * The followings are the behaviors currently affected this flag.
 +       *
 +       * - Mount options "noprefix" and "clone_children" are disallowed.
 +       *   Also, cgroupfs file cgroup.clone_children is not created.
 +       *
 +       * - When mounting an existing superblock, mount options should
 +       *   match.
 +       *
 +       * - Remount is disallowed.
 +       *
 +       * - memcg: use_hierarchy is on by default and the cgroup file for
 +       *   the flag is not created.
 +       *
 +       * The followings are planned changes.
 +       *
 +       * - release_agent will be disallowed once replacement notification
 +       *   mechanism is implemented.
 +       */
 +      CGRP_ROOT_SANE_BEHAVIOR = (1 << 0),
 +
 +      CGRP_ROOT_NOPREFIX      = (1 << 1), /* mounted subsystems have no named prefix */
 +      CGRP_ROOT_XATTR         = (1 << 2), /* supports extended attributes */
 +};
 +
 +/*
 + * A cgroupfs_root represents the root of a cgroup hierarchy, and may be
 + * associated with a superblock to form an active hierarchy.  This is
 + * internal to cgroup core.  Don't access directly from controllers.
 + */
 +struct cgroupfs_root {
 +      struct super_block *sb;
 +
 +      /*
 +       * The bitmask of subsystems intended to be attached to this
 +       * hierarchy
 +       */
 +      unsigned long subsys_mask;
 +
 +      /* Unique id for this hierarchy. */
 +      int hierarchy_id;
 +
 +      /* The bitmask of subsystems currently attached to this hierarchy */
 +      unsigned long actual_subsys_mask;
 +
 +      /* A list running through the attached subsystems */
 +      struct list_head subsys_list;
 +
 +      /* The root cgroup for this hierarchy */
 +      struct cgroup top_cgroup;
 +
 +      /* Tracks how many cgroups are currently defined in hierarchy.*/
 +      int number_of_cgroups;
 +
 +      /* A list running through the active hierarchies */
 +      struct list_head root_list;
 +
 +      /* All cgroups on this root, cgroup_mutex protected */
 +      struct list_head allcg_list;
 +
 +      /* Hierarchy-specific flags */
 +      unsigned long flags;
 +
 +      /* IDs for cgroups in this hierarchy */
 +      struct ida cgroup_ida;
 +
 +      /* The path to use for release notifications. */
 +      char release_agent_path[PATH_MAX];
 +
 +      /* The name for this hierarchy - may be empty */
 +      char name[MAX_CGROUP_ROOT_NAMELEN];
 +};
 +
  /*
   * A css_set is a structure holding pointers to a set of
   * cgroup_subsys_state objects. This saves space in the task struct
@@@ -395,7 -278,6 +395,7 @@@ struct cgroup_map_cb 
  /* cftype->flags */
  #define CFTYPE_ONLY_ON_ROOT   (1U << 0)       /* only create on root cg */
  #define CFTYPE_NOT_ON_ROOT    (1U << 1)       /* don't create on root cg */
 +#define CFTYPE_INSANE         (1U << 2)       /* don't create if sane_behavior */
  
  #define MAX_CFTYPE_NAME               64
  
@@@ -422,6 -304,9 +422,6 @@@ struct cftype 
        /* CFTYPE_* flags */
        unsigned int flags;
  
 -      /* file xattrs */
 -      struct simple_xattrs xattrs;
 -
        int (*open)(struct inode *inode, struct file *file);
        ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft,
                        struct file *file,
@@@ -519,31 -404,18 +519,31 @@@ struct cgroup_scanner 
        void *data;
  };
  
 +/*
 + * See the comment above CGRP_ROOT_SANE_BEHAVIOR for details.  This
 + * function can be called as long as @cgrp is accessible.
 + */
 +static inline bool cgroup_sane_behavior(const struct cgroup *cgrp)
 +{
 +      return cgrp->root->flags & CGRP_ROOT_SANE_BEHAVIOR;
 +}
 +
 +/* Caller should hold rcu_read_lock() */
 +static inline const char *cgroup_name(const struct cgroup *cgrp)
 +{
 +      return rcu_dereference(cgrp->name)->name;
 +}
 +
  int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
  int cgroup_rm_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
  
  int cgroup_is_removed(const struct cgroup *cgrp);
 +bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor);
  
  int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen);
  
  int cgroup_task_count(const struct cgroup *cgrp);
  
 -/* Return true if cgrp is a descendant of the task's cgroup */
 -int cgroup_is_descendant(const struct cgroup *cgrp, struct task_struct *task);
 -
  /*
   * Control Group taskset, used to pass around set of tasks to cgroup_subsys
   * methods.
@@@ -586,6 -458,7 +586,6 @@@ struct cgroup_subsys 
        void (*bind)(struct cgroup *root);
  
        int subsys_id;
 -      int active;
        int disabled;
        int early_init;
        /*
@@@ -650,16 -523,10 +650,16 @@@ static inline struct cgroup_subsys_stat
   * rcu_dereference_check() conditions, such as locks used during the
   * cgroup_subsys::attach() methods.
   */
 +#ifdef CONFIG_PROVE_RCU
 +extern struct mutex cgroup_mutex;
  #define task_subsys_state_check(task, subsys_id, __c)                 \
 -      rcu_dereference_check(task->cgroups->subsys[subsys_id],         \
 -                            lockdep_is_held(&task->alloc_lock) ||     \
 -                            cgroup_lock_is_held() || (__c))
 +      rcu_dereference_check((task)->cgroups->subsys[(subsys_id)],     \
 +                            lockdep_is_held(&(task)->alloc_lock) ||   \
 +                            lockdep_is_held(&cgroup_mutex) || (__c))
 +#else
 +#define task_subsys_state_check(task, subsys_id, __c)                 \
 +      rcu_dereference((task)->cgroups->subsys[(subsys_id)])
 +#endif
  
  static inline struct cgroup_subsys_state *
  task_subsys_state(struct task_struct *task, int subsys_id)
@@@ -794,8 -661,8 +794,8 @@@ struct task_struct *cgroup_iter_next(st
                                        struct cgroup_iter *it);
  void cgroup_iter_end(struct cgroup *cgrp, struct cgroup_iter *it);
  int cgroup_scan_tasks(struct cgroup_scanner *scan);
 -int cgroup_attach_task(struct cgroup *, struct task_struct *);
  int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
 +int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from);
  
  /*
   * CSS ID is ID for cgroup_subsys_state structs under subsys. This only works
@@@ -820,6 -687,13 +820,6 @@@ void free_css_id(struct cgroup_subsys *
  
  struct cgroup_subsys_state *css_lookup(struct cgroup_subsys *ss, int id);
  
 -/*
 - * Get a cgroup whose id is greater than or equal to id under tree of root.
 - * Returning a cgroup_subsys_state or NULL.
 - */
 -struct cgroup_subsys_state *css_get_next(struct cgroup_subsys *ss, int id,
 -              struct cgroup_subsys_state *root, int *foundid);
 -
  /* Returns true if root is ancestor of cg */
  bool css_is_ancestor(struct cgroup_subsys_state *cg,
                     const struct cgroup_subsys_state *root);
diff --combined include/linux/cpuset.h
index ccd1de8ad8229ad33417573cef8fa6a49abea634,22b637c5ecae5b6ebad60953d38bf373329a4f41..cc1b01cf2035bced50bfc5d0015d1b6de7a7781b
@@@ -11,6 -11,7 +11,6 @@@
  #include <linux/sched.h>
  #include <linux/cpumask.h>
  #include <linux/nodemask.h>
 -#include <linux/cgroup.h>
  #include <linux/mm.h>
  
  #ifdef CONFIG_CPUSETS
@@@ -63,10 -64,9 +63,9 @@@ extern int cpuset_mems_allowed_intersec
  extern int cpuset_memory_pressure_enabled;
  extern void __cpuset_memory_pressure_bump(void);
  
- extern const struct file_operations proc_cpuset_operations;
- struct seq_file;
  extern void cpuset_task_status_allowed(struct seq_file *m,
                                        struct task_struct *task);
+ extern int proc_cpuset_show(struct seq_file *, void *);
  
  extern int cpuset_mem_spread_node(void);
  extern int cpuset_slab_spread_node(void);
diff --combined include/linux/fs.h
index 17d8b15962156ef12488107d6b2190b1ac9c8177,b1f28b02ede60b309311523e711de6445896c052..e8cd6b8396753901227a34659cedca367beb0926
@@@ -675,11 -675,9 +675,11 @@@ static inline loff_t i_size_read(const 
  static inline void i_size_write(struct inode *inode, loff_t i_size)
  {
  #if BITS_PER_LONG==32 && defined(CONFIG_SMP)
 +      preempt_disable();
        write_seqcount_begin(&inode->i_size_seqcount);
        inode->i_size = i_size;
        write_seqcount_end(&inode->i_size_seqcount);
 +      preempt_enable();
  #elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
        preempt_disable();
        inode->i_size = i_size;
@@@ -2082,7 -2080,6 +2082,6 @@@ extern int sync_filesystem(struct super
  extern const struct file_operations def_blk_fops;
  extern const struct file_operations def_chr_fops;
  extern const struct file_operations bad_sock_fops;
- extern const struct file_operations def_fifo_fops;
  #ifdef CONFIG_BLOCK
  extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
  extern int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
@@@ -2154,10 -2151,6 +2153,6 @@@ extern void init_special_inode(struct i
  extern void make_bad_inode(struct inode *);
  extern int is_bad_inode(struct inode *);
  
- extern const struct file_operations read_pipefifo_fops;
- extern const struct file_operations write_pipefifo_fops;
- extern const struct file_operations rdwr_pipefifo_fops;
  #ifdef CONFIG_BLOCK
  /*
   * return READ, READA, or WRITE
@@@ -2225,6 -2218,20 +2220,20 @@@ static inline struct inode *file_inode(
        return f->f_inode;
  }
  
+ static inline void file_start_write(struct file *file)
+ {
+       if (!S_ISREG(file_inode(file)->i_mode))
+               return;
+       __sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, true);
+ }
+ static inline void file_end_write(struct file *file)
+ {
+       if (!S_ISREG(file_inode(file)->i_mode))
+               return;
+       __sb_end_write(file_inode(file)->i_sb, SB_FREEZE_WRITE);
+ }
  /*
   * get_write_access() gets write permission for a file.
   * put_write_access() releases this write permission.
index 8ac32836690e3a50ce25d89187ac7c42193e8835,5524f8cfa95052843ca5fc74e2e4c168661aa183..731e4ecee3bd59186b780253bb3bde660593a2f5
@@@ -13,9 -13,7 +13,9 @@@ struct pidmap 
         void *page;
  };
  
 -#define PIDMAP_ENTRIES         ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8)
 +#define BITS_PER_PAGE         (PAGE_SIZE * 8)
 +#define BITS_PER_PAGE_MASK    (BITS_PER_PAGE-1)
 +#define PIDMAP_ENTRIES                ((PID_MAX_LIMIT+BITS_PER_PAGE-1)/BITS_PER_PAGE)
  
  struct bsd_acct_struct;
  
@@@ -30,6 -28,7 +30,7 @@@ struct pid_namespace 
        struct pid_namespace *parent;
  #ifdef CONFIG_PROC_FS
        struct vfsmount *proc_mnt;
+       struct dentry *proc_self;
  #endif
  #ifdef CONFIG_BSD_PROCESS_ACCT
        struct bsd_acct_struct *bacct;
diff --combined include/linux/signal.h
index 9475c5cb28bcc82827e9ed8c540fa59acd5067e9,1135e3696e8187298b19eb14cb0c0892d39b6d53..d897484730c0e0853c45785c5d070538252b2049
@@@ -250,11 -250,11 +250,11 @@@ extern int show_unhandled_signals
  extern int sigsuspend(sigset_t *);
  
  struct sigaction {
 -#ifndef __ARCH_HAS_ODD_SIGACTION
 +#ifndef __ARCH_HAS_IRIX_SIGACTION
        __sighandler_t  sa_handler;
        unsigned long   sa_flags;
  #else
 -      unsigned long   sa_flags;
 +      unsigned int    sa_flags;
        __sighandler_t  sa_handler;
  #endif
  #ifdef __ARCH_HAS_SA_RESTORER
@@@ -434,4 -434,9 +434,9 @@@ void signals_init(void)
  int restore_altstack(const stack_t __user *);
  int __save_altstack(stack_t __user *, unsigned long);
  
+ #ifdef CONFIG_PROC_FS
+ struct seq_file;
+ extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
+ #endif
  #endif /* _LINUX_SIGNAL_H */
diff --combined include/linux/tty.h
index 367a9dfc4ea2464c35ffe8c773c5cb8f04e3df86,e014fb1a84bd1a27658d69f09c2eeef1b51988fd..7e92bd86a808cfbdf31bf38f1165ab30fe93c2ff
@@@ -255,9 -255,9 +255,9 @@@ struct tty_struct 
        int count;
        struct winsize winsize;         /* termios mutex */
        unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
 -      unsigned char warned:1;
        unsigned char ctrl_status;      /* ctrl_lock */
        unsigned int receive_room;      /* Bytes free for queue */
 +      int flow_change;
  
        struct tty_struct *link;
        struct fasync_struct *fasync;
@@@ -315,25 -315,9 +315,25 @@@ struct tty_file_private 
  #define TTY_NO_WRITE_SPLIT    17      /* Preserve write boundaries to driver */
  #define TTY_HUPPED            18      /* Post driver->hangup() */
  #define TTY_HUPPING           21      /* ->hangup() in progress */
 +#define TTY_LDISC_HALTED      22      /* Line discipline is halted */
  
  #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
  
 +/* Values for tty->flow_change */
 +#define TTY_THROTTLE_SAFE 1
 +#define TTY_UNTHROTTLE_SAFE 2
 +
 +static inline void __tty_set_flow_change(struct tty_struct *tty, int val)
 +{
 +      tty->flow_change = val;
 +}
 +
 +static inline void tty_set_flow_change(struct tty_struct *tty, int val)
 +{
 +      tty->flow_change = val;
 +      smp_mb();
 +}
 +
  #ifdef CONFIG_TTY
  extern void console_init(void);
  extern void tty_kref_put(struct tty_struct *tty);
@@@ -416,8 -400,6 +416,8 @@@ extern int tty_write_room(struct tty_st
  extern void tty_driver_flush_buffer(struct tty_struct *tty);
  extern void tty_throttle(struct tty_struct *tty);
  extern void tty_unthrottle(struct tty_struct *tty);
 +extern int tty_throttle_safe(struct tty_struct *tty);
 +extern int tty_unthrottle_safe(struct tty_struct *tty);
  extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
  extern void tty_driver_remove_tty(struct tty_driver *driver,
                                  struct tty_struct *tty);
@@@ -437,28 -419,13 +437,28 @@@ extern void tty_flush_to_ldisc(struct t
  extern void tty_buffer_free_all(struct tty_port *port);
  extern void tty_buffer_flush(struct tty_struct *tty);
  extern void tty_buffer_init(struct tty_port *port);
 -extern speed_t tty_get_baud_rate(struct tty_struct *tty);
  extern speed_t tty_termios_baud_rate(struct ktermios *termios);
  extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
  extern void tty_termios_encode_baud_rate(struct ktermios *termios,
                                                speed_t ibaud, speed_t obaud);
  extern void tty_encode_baud_rate(struct tty_struct *tty,
                                                speed_t ibaud, speed_t obaud);
 +
 +/**
 + *    tty_get_baud_rate       -       get tty bit rates
 + *    @tty: tty to query
 + *
 + *    Returns the baud rate as an integer for this terminal. The
 + *    termios lock must be held by the caller and the terminal bit
 + *    flags may be updated.
 + *
 + *    Locking: none
 + */
 +static inline speed_t tty_get_baud_rate(struct tty_struct *tty)
 +{
 +      return tty_termios_baud_rate(&tty->termios);
 +}
 +
  extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
  extern int tty_termios_hw_change(struct ktermios *a, struct ktermios *b);
  extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
@@@ -535,8 -502,6 +535,8 @@@ extern int tty_port_carrier_raised(stru
  extern void tty_port_raise_dtr_rts(struct tty_port *port);
  extern void tty_port_lower_dtr_rts(struct tty_port *port);
  extern void tty_port_hangup(struct tty_port *port);
 +extern void tty_port_tty_hangup(struct tty_port *port, bool check_clocal);
 +extern void tty_port_tty_wakeup(struct tty_port *port);
  extern int tty_port_block_til_ready(struct tty_port *port,
                                struct tty_struct *tty, struct file *filp);
  extern int tty_port_close_start(struct tty_port *port,
@@@ -561,6 -526,8 +561,6 @@@ extern void tty_ldisc_release(struct tt
  extern void tty_ldisc_init(struct tty_struct *tty);
  extern void tty_ldisc_deinit(struct tty_struct *tty);
  extern void tty_ldisc_begin(void);
 -/* This last one is just for the tty layer internals and shouldn't be used elsewhere */
 -extern void tty_ldisc_enable(struct tty_struct *tty);
  
  
  /* n_tty.c */
@@@ -691,5 -658,12 +691,12 @@@ do {                                                                     
        finish_wait(&wq, &__wait);                                      \
  } while (0)
  
+ #ifdef CONFIG_PROC_FS
+ extern void proc_tty_register_driver(struct tty_driver *);
+ extern void proc_tty_unregister_driver(struct tty_driver *);
+ #else
+ static inline void proc_tty_register_driver(struct tty_driver *d) {}
+ static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
+ #endif
  
  #endif
index 6912ef9a1881bc9a678be2b6a28dd9dfdc0f8177,ea81f0ef649227c2bd0991d715aa95bef964be58..10eb9b389014259617de84924a297634fe9b61d4
@@@ -193,11 -193,11 +193,11 @@@ static inline bool bdaddr_type_is_le(__
  #define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff} })
  
  /* Copy, swap, convert BD Address */
 -static inline int bacmp(bdaddr_t *ba1, bdaddr_t *ba2)
 +static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
  {
        return memcmp(ba1, ba2, sizeof(bdaddr_t));
  }
 -static inline void bacpy(bdaddr_t *dst, bdaddr_t *src)
 +static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src)
  {
        memcpy(dst, src, sizeof(bdaddr_t));
  }
@@@ -226,13 -226,12 +226,12 @@@ struct bt_sock_list 
        struct hlist_head head;
        rwlock_t          lock;
  #ifdef CONFIG_PROC_FS
-         struct file_operations   fops;
          int (* custom_seq_show)(struct seq_file *, void *);
  #endif
  };
  
  int  bt_sock_register(int proto, const struct net_proto_family *ops);
 -int  bt_sock_unregister(int proto);
 +void bt_sock_unregister(int proto);
  void bt_sock_link(struct bt_sock_list *l, struct sock *s);
  void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
  int  bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
@@@ -260,23 -259,12 +259,23 @@@ struct l2cap_ctrl 
        __u8            retries;
  };
  
 +struct hci_dev;
 +
 +typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status);
 +
 +struct hci_req_ctrl {
 +      bool                    start;
 +      u8                      event;
 +      hci_req_complete_t      complete;
 +};
 +
  struct bt_skb_cb {
        __u8 pkt_type;
        __u8 incoming;
        __u16 expect;
        __u8 force_active;
        struct l2cap_ctrl control;
 +      struct hci_req_ctrl req;
  };
  #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
  
@@@ -330,7 -318,7 +329,7 @@@ extern void hci_sock_cleanup(void)
  extern int bt_sysfs_init(void);
  extern void bt_sysfs_cleanup(void);
  
- extern int  bt_procfs_init(struct module* module, struct net *net, const char *name,
+ extern int  bt_procfs_init(struct net *net, const char *name,
                           struct bt_sock_list* sk_list,
                           int (* seq_show)(struct seq_file *, void *));
  extern void bt_procfs_cleanup(struct net *net, const char *name);
diff --combined ipc/msgutil.c
index d43439e6eb47bc4064d664c01bcde7be4cbf81e5,8f0201735f16c6ceaf6b8eda9b4840c76b5e18bd..491e71f2a1b862a72e78a54e7b16e08812a13f3d
@@@ -16,8 -16,8 +16,8 @@@
  #include <linux/msg.h>
  #include <linux/ipc_namespace.h>
  #include <linux/utsname.h>
- #include <linux/proc_fs.h>
+ #include <linux/proc_ns.h>
 -#include <asm/uaccess.h>
 +#include <linux/uaccess.h>
  
  #include "util.h"
  
@@@ -37,70 -37,59 +37,70 @@@ struct ipc_namespace init_ipc_ns = 
  atomic_t nr_ipc_ns = ATOMIC_INIT(1);
  
  struct msg_msgseg {
 -      struct msg_msgsegnext;
 +      struct msg_msgseg *next;
        /* the next part of the message follows immediately */
  };
  
 -#define DATALEN_MSG   (PAGE_SIZE-sizeof(struct msg_msg))
 -#define DATALEN_SEG   (PAGE_SIZE-sizeof(struct msg_msgseg))
 +#define DATALEN_MSG   (int)(PAGE_SIZE-sizeof(struct msg_msg))
 +#define DATALEN_SEG   (int)(PAGE_SIZE-sizeof(struct msg_msgseg))
  
 -struct msg_msg *load_msg(const void __user *src, int len)
 +
 +static struct msg_msg *alloc_msg(int len)
  {
        struct msg_msg *msg;
        struct msg_msgseg **pseg;
 -      int err;
        int alen;
  
 -      alen = len;
 -      if (alen > DATALEN_MSG)
 -              alen = DATALEN_MSG;
 -
 +      alen = min(len, DATALEN_MSG);
        msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
        if (msg == NULL)
 -              return ERR_PTR(-ENOMEM);
 +              return NULL;
  
        msg->next = NULL;
        msg->security = NULL;
  
 -      if (copy_from_user(msg + 1, src, alen)) {
 -              err = -EFAULT;
 -              goto out_err;
 -      }
 -
        len -= alen;
 -      src = ((char __user *)src) + alen;
        pseg = &msg->next;
        while (len > 0) {
                struct msg_msgseg *seg;
 -              alen = len;
 -              if (alen > DATALEN_SEG)
 -                      alen = DATALEN_SEG;
 -              seg = kmalloc(sizeof(*seg) + alen,
 -                                               GFP_KERNEL);
 -              if (seg == NULL) {
 -                      err = -ENOMEM;
 +              alen = min(len, DATALEN_SEG);
 +              seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL);
 +              if (seg == NULL)
                        goto out_err;
 -              }
                *pseg = seg;
                seg->next = NULL;
 -              if (copy_from_user(seg + 1, src, alen)) {
 -                      err = -EFAULT;
 -                      goto out_err;
 -              }
                pseg = &seg->next;
                len -= alen;
 -              src = ((char __user *)src) + alen;
 +      }
 +
 +      return msg;
 +
 +out_err:
 +      free_msg(msg);
 +      return NULL;
 +}
 +
 +struct msg_msg *load_msg(const void __user *src, int len)
 +{
 +      struct msg_msg *msg;
 +      struct msg_msgseg *seg;
 +      int err = -EFAULT;
 +      int alen;
 +
 +      msg = alloc_msg(len);
 +      if (msg == NULL)
 +              return ERR_PTR(-ENOMEM);
 +
 +      alen = min(len, DATALEN_MSG);
 +      if (copy_from_user(msg + 1, src, alen))
 +              goto out_err;
 +
 +      for (seg = msg->next; seg != NULL; seg = seg->next) {
 +              len -= alen;
 +              src = (char __user *)src + alen;
 +              alen = min(len, DATALEN_SEG);
 +              if (copy_from_user(seg + 1, src, alen))
 +                      goto out_err;
        }
  
        err = security_msg_msg_alloc(msg);
@@@ -124,16 -113,23 +124,16 @@@ struct msg_msg *copy_msg(struct msg_ms
        if (src->m_ts > dst->m_ts)
                return ERR_PTR(-EINVAL);
  
 -      alen = len;
 -      if (alen > DATALEN_MSG)
 -              alen = DATALEN_MSG;
 -
 +      alen = min(len, DATALEN_MSG);
        memcpy(dst + 1, src + 1, alen);
  
 -      len -= alen;
 -      dst_pseg = dst->next;
 -      src_pseg = src->next;
 -      while (len > 0) {
 -              alen = len;
 -              if (alen > DATALEN_SEG)
 -                      alen = DATALEN_SEG;
 -              memcpy(dst_pseg + 1, src_pseg + 1, alen);
 -              dst_pseg = dst_pseg->next;
 +      for (dst_pseg = dst->next, src_pseg = src->next;
 +           src_pseg != NULL;
 +           dst_pseg = dst_pseg->next, src_pseg = src_pseg->next) {
 +
                len -= alen;
 -              src_pseg = src_pseg->next;
 +              alen = min(len, DATALEN_SEG);
 +              memcpy(dst_pseg + 1, src_pseg + 1, alen);
        }
  
        dst->m_type = src->m_type;
@@@ -152,16 -148,24 +152,16 @@@ int store_msg(void __user *dest, struc
        int alen;
        struct msg_msgseg *seg;
  
 -      alen = len;
 -      if (alen > DATALEN_MSG)
 -              alen = DATALEN_MSG;
 +      alen = min(len, DATALEN_MSG);
        if (copy_to_user(dest, msg + 1, alen))
                return -1;
  
 -      len -= alen;
 -      dest = ((char __user *)dest) + alen;
 -      seg = msg->next;
 -      while (len > 0) {
 -              alen = len;
 -              if (alen > DATALEN_SEG)
 -                      alen = DATALEN_SEG;
 +      for (seg = msg->next; seg != NULL; seg = seg->next) {
 +              len -= alen;
 +              dest = (char __user *)dest + alen;
 +              alen = min(len, DATALEN_SEG);
                if (copy_to_user(dest, seg + 1, alen))
                        return -1;
 -              len -= alen;
 -              dest = ((char __user *)dest) + alen;
 -              seg = seg->next;
        }
        return 0;
  }
diff --combined ipc/util.c
index 579201e4bc019027f7a3c94c2536451223ee7cf3,b6db68131a0e937182a100124b8396caacb73151..abfc13e8677f58ad667ce0c32a9e82c9c25ef247
@@@ -23,7 -23,6 +23,7 @@@
  #include <linux/msg.h>
  #include <linux/vmalloc.h>
  #include <linux/slab.h>
 +#include <linux/notifier.h>
  #include <linux/capability.h>
  #include <linux/highuid.h>
  #include <linux/security.h>
@@@ -48,16 -47,19 +48,16 @@@ struct ipc_proc_iface 
        int (*show)(struct seq_file *, void *);
  };
  
 -#ifdef CONFIG_MEMORY_HOTPLUG
 -
  static void ipc_memory_notifier(struct work_struct *work)
  {
        ipcns_notify(IPCNS_MEMCHANGED);
  }
  
 -static DECLARE_WORK(ipc_memory_wq, ipc_memory_notifier);
 -
 -
  static int ipc_memory_callback(struct notifier_block *self,
                                unsigned long action, void *arg)
  {
 +      static DECLARE_WORK(ipc_memory_wq, ipc_memory_notifier);
 +
        switch (action) {
        case MEM_ONLINE:    /* memory successfully brought online */
        case MEM_OFFLINE:   /* or offline: it's time to recompute msgmni */
        return NOTIFY_OK;
  }
  
 -#endif /* CONFIG_MEMORY_HOTPLUG */
 +static struct notifier_block ipc_memory_nb = {
 +      .notifier_call = ipc_memory_callback,
 +      .priority = IPC_CALLBACK_PRI,
 +};
  
  /**
   *    ipc_init        -       initialise IPC subsystem
@@@ -103,7 -102,7 +103,7 @@@ static int __init ipc_init(void
        sem_init();
        msg_init();
        shm_init();
 -      hotplug_memory_notifier(ipc_memory_callback, IPC_CALLBACK_PRI);
 +      register_hotmemory_notifier(&ipc_memory_nb);
        register_ipcns_notifier(&init_ipc_ns);
        return 0;
  }
@@@ -439,9 -438,9 +439,9 @@@ void ipc_rmid(struct ipc_ids *ids, stru
   *    NULL is returned if the allocation fails
   */
   
 -voidipc_alloc(int size)
 +void *ipc_alloc(int size)
  {
 -      voidout;
 +      void *out;
        if(size > PAGE_SIZE)
                out = vmalloc(size);
        else
@@@ -478,7 -477,7 +478,7 @@@ void ipc_free(void* ptr, int size
   */
  struct ipc_rcu_hdr
  {
 -      int refcount;
 +      atomic_t refcount;
        int is_vmalloc;
        void *data[0];
  };
@@@ -516,41 -515,39 +516,41 @@@ static inline int rcu_use_vmalloc(int s
   *    @size: size desired
   *
   *    Allocate memory for the rcu header structure +  the object.
 - *    Returns the pointer to the object.
 - *    NULL is returned if the allocation fails. 
 + *    Returns the pointer to the object or NULL upon failure.
   */
 - 
 -void* ipc_rcu_alloc(int size)
 +void *ipc_rcu_alloc(int size)
  {
 -      void* out;
 -      /* 
 +      void *out;
 +
 +      /*
         * We prepend the allocation with the rcu struct, and
 -       * workqueue if necessary (for vmalloc). 
 +       * workqueue if necessary (for vmalloc).
         */
        if (rcu_use_vmalloc(size)) {
                out = vmalloc(HDRLEN_VMALLOC + size);
 -              if (out) {
 -                      out += HDRLEN_VMALLOC;
 -                      container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 1;
 -                      container_of(out, struct ipc_rcu_hdr, data)->refcount = 1;
 -              }
 +              if (!out)
 +                      goto done;
 +
 +              out += HDRLEN_VMALLOC;
 +              container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 1;
        } else {
                out = kmalloc(HDRLEN_KMALLOC + size, GFP_KERNEL);
 -              if (out) {
 -                      out += HDRLEN_KMALLOC;
 -                      container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 0;
 -                      container_of(out, struct ipc_rcu_hdr, data)->refcount = 1;
 -              }
 +              if (!out)
 +                      goto done;
 +
 +              out += HDRLEN_KMALLOC;
 +              container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 0;
        }
  
 +      /* set reference counter no matter what kind of allocation was done */
 +      atomic_set(&container_of(out, struct ipc_rcu_hdr, data)->refcount, 1);
 +done:
        return out;
  }
  
 -void ipc_rcu_getref(void *ptr)
 +int ipc_rcu_getref(void *ptr)
  {
 -      container_of(ptr, struct ipc_rcu_hdr, data)->refcount++;
 +      return atomic_inc_not_zero(&container_of(ptr, struct ipc_rcu_hdr, data)->refcount);
  }
  
  static void ipc_do_vfree(struct work_struct *work)
@@@ -580,7 -577,7 +580,7 @@@ static void ipc_schedule_free(struct rc
  
  void ipc_rcu_putref(void *ptr)
  {
 -      if (--container_of(ptr, struct ipc_rcu_hdr, data)->refcount > 0)
 +      if (!atomic_dec_and_test(&container_of(ptr, struct ipc_rcu_hdr, data)->refcount))
                return;
  
        if (container_of(ptr, struct ipc_rcu_hdr, data)->is_vmalloc) {
@@@ -670,28 -667,6 +670,28 @@@ void ipc64_perm_to_ipc_perm (struct ipc
        out->seq        = in->seq;
  }
  
 +/**
 + * ipc_obtain_object
 + * @ids: ipc identifier set
 + * @id: ipc id to look for
 + *
 + * Look for an id in the ipc ids idr and return associated ipc object.
 + *
 + * Call inside the RCU critical section.
 + * The ipc object is *not* locked on exit.
 + */
 +struct kern_ipc_perm *ipc_obtain_object(struct ipc_ids *ids, int id)
 +{
 +      struct kern_ipc_perm *out;
 +      int lid = ipcid_to_idx(id);
 +
 +      out = idr_find(&ids->ipcs_idr, lid);
 +      if (!out)
 +              return ERR_PTR(-EINVAL);
 +
 +      return out;
 +}
 +
  /**
   * ipc_lock - Lock an ipc structure without rw_mutex held
   * @ids: IPC identifier set
   *
   * Look for an id in the ipc ids idr and lock the associated ipc object.
   *
 - * The ipc object is locked on exit.
 + * The ipc object is locked on successful exit.
   */
 -
  struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
  {
        struct kern_ipc_perm *out;
 -      int lid = ipcid_to_idx(id);
  
        rcu_read_lock();
 -      out = idr_find(&ids->ipcs_idr, lid);
 -      if (out == NULL) {
 -              rcu_read_unlock();
 -              return ERR_PTR(-EINVAL);
 -      }
 +      out = ipc_obtain_object(ids, id);
 +      if (IS_ERR(out))
 +              goto err1;
  
        spin_lock(&out->lock);
 -      
 +
        /* ipc_rmid() may have already freed the ID while ipc_lock
         * was spinning: here verify that the structure is still valid
         */
 -      if (out->deleted) {
 -              spin_unlock(&out->lock);
 -              rcu_read_unlock();
 -              return ERR_PTR(-EINVAL);
 -      }
 +      if (!out->deleted)
 +              return out;
 +
 +      spin_unlock(&out->lock);
 +      out = ERR_PTR(-EINVAL);
 +err1:
 +      rcu_read_unlock();
 +      return out;
 +}
 +
 +/**
 + * ipc_obtain_object_check
 + * @ids: ipc identifier set
 + * @id: ipc id to look for
 + *
 + * Similar to ipc_obtain_object() but also checks
 + * the ipc object reference counter.
 + *
 + * Call inside the RCU critical section.
 + * The ipc object is *not* locked on exit.
 + */
 +struct kern_ipc_perm *ipc_obtain_object_check(struct ipc_ids *ids, int id)
 +{
 +      struct kern_ipc_perm *out = ipc_obtain_object(ids, id);
 +
 +      if (IS_ERR(out))
 +              goto out;
  
 +      if (ipc_checkid(out, id))
 +              return ERR_PTR(-EIDRM);
 +out:
        return out;
  }
  
@@@ -826,28 -780,11 +826,28 @@@ struct kern_ipc_perm *ipcctl_pre_down(s
                                      struct ipc64_perm *perm, int extra_perm)
  {
        struct kern_ipc_perm *ipcp;
 +
 +      ipcp = ipcctl_pre_down_nolock(ns, ids, id, cmd, perm, extra_perm);
 +      if (IS_ERR(ipcp))
 +              goto out;
 +
 +      spin_lock(&ipcp->lock);
 +out:
 +      return ipcp;
 +}
 +
 +struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
 +                                           struct ipc_ids *ids, int id, int cmd,
 +                                           struct ipc64_perm *perm, int extra_perm)
 +{
        kuid_t euid;
 -      int err;
 +      int err = -EPERM;
 +      struct kern_ipc_perm *ipcp;
  
        down_write(&ids->rw_mutex);
 -      ipcp = ipc_lock_check(ids, id);
 +      rcu_read_lock();
 +
 +      ipcp = ipc_obtain_object_check(ids, id);
        if (IS_ERR(ipcp)) {
                err = PTR_ERR(ipcp);
                goto out_up;
        audit_ipc_obj(ipcp);
        if (cmd == IPC_SET)
                audit_ipc_set_perm(extra_perm, perm->uid,
 -                                       perm->gid, perm->mode);
 +                                 perm->gid, perm->mode);
  
        euid = current_euid();
        if (uid_eq(euid, ipcp->cuid) || uid_eq(euid, ipcp->uid)  ||
            ns_capable(ns->user_ns, CAP_SYS_ADMIN))
                return ipcp;
  
 -      err = -EPERM;
 -      ipc_unlock(ipcp);
  out_up:
 +      /*
 +       * Unsuccessful lookup, unlock and return
 +       * the corresponding error.
 +       */
 +      rcu_read_unlock();
        up_write(&ids->rw_mutex);
 +
        return ERR_PTR(err);
  }
  
@@@ -1031,7 -964,7 +1031,7 @@@ static int sysvipc_proc_open(struct ino
        seq = file->private_data;
        seq->private = iter;
  
-       iter->iface = PDE(inode)->data;
+       iter->iface = PDE_DATA(inode);
        iter->ns    = get_ipc_ns(current->nsproxy->ipc_ns);
  out:
        return ret;
diff --combined kernel/cgroup.c
index d3abce2d645503685b6b9eadec5685ee9d219a07,d5cffe80b4697c8c70acc0643d109a410547e299..2a9926275f806f41e7c15b6eed584acaf8796bc0
@@@ -30,6 -30,7 +30,6 @@@
  #include <linux/cred.h>
  #include <linux/ctype.h>
  #include <linux/errno.h>
 -#include <linux/fs.h>
  #include <linux/init_task.h>
  #include <linux/kernel.h>
  #include <linux/list.h>
@@@ -58,7 -59,7 +58,7 @@@
  #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
  #include <linux/eventfd.h>
  #include <linux/poll.h>
 -#include <linux/flex_array.h> /* used in cgroup_attach_proc */
 +#include <linux/flex_array.h> /* used in cgroup_attach_task */
  #include <linux/kthread.h>
  
  #include <linux/atomic.h>
   * B happens only through cgroup_show_options() and using cgroup_root_mutex
   * breaks it.
   */
 +#ifdef CONFIG_PROVE_RCU
 +DEFINE_MUTEX(cgroup_mutex);
 +EXPORT_SYMBOL_GPL(cgroup_mutex);      /* only for task_subsys_state_check() */
 +#else
  static DEFINE_MUTEX(cgroup_mutex);
 +#endif
 +
  static DEFINE_MUTEX(cgroup_root_mutex);
  
  /*
@@@ -103,6 -98,56 +103,6 @@@ static struct cgroup_subsys *subsys[CGR
  #include <linux/cgroup_subsys.h>
  };
  
 -#define MAX_CGROUP_ROOT_NAMELEN 64
 -
 -/*
 - * A cgroupfs_root represents the root of a cgroup hierarchy,
 - * and may be associated with a superblock to form an active
 - * hierarchy
 - */
 -struct cgroupfs_root {
 -      struct super_block *sb;
 -
 -      /*
 -       * The bitmask of subsystems intended to be attached to this
 -       * hierarchy
 -       */
 -      unsigned long subsys_mask;
 -
 -      /* Unique id for this hierarchy. */
 -      int hierarchy_id;
 -
 -      /* The bitmask of subsystems currently attached to this hierarchy */
 -      unsigned long actual_subsys_mask;
 -
 -      /* A list running through the attached subsystems */
 -      struct list_head subsys_list;
 -
 -      /* The root cgroup for this hierarchy */
 -      struct cgroup top_cgroup;
 -
 -      /* Tracks how many cgroups are currently defined in hierarchy.*/
 -      int number_of_cgroups;
 -
 -      /* A list running through the active hierarchies */
 -      struct list_head root_list;
 -
 -      /* All cgroups on this root, cgroup_mutex protected */
 -      struct list_head allcg_list;
 -
 -      /* Hierarchy-specific flags */
 -      unsigned long flags;
 -
 -      /* IDs for cgroups in this hierarchy */
 -      struct ida cgroup_ida;
 -
 -      /* The path to use for release notifications. */
 -      char release_agent_path[PATH_MAX];
 -
 -      /* The name for this hierarchy - may be empty */
 -      char name[MAX_CGROUP_ROOT_NAMELEN];
 -};
 -
  /*
   * The "rootnode" hierarchy is the "dummy hierarchy", reserved for the
   * subsystems that are otherwise unattached - it never has more than a
@@@ -117,9 -162,6 +117,9 @@@ struct cfent 
        struct list_head                node;
        struct dentry                   *dentry;
        struct cftype                   *type;
 +
 +      /* file xattrs */
 +      struct simple_xattrs            xattrs;
  };
  
  /*
@@@ -196,8 -238,6 +196,8 @@@ static DEFINE_SPINLOCK(hierarchy_id_loc
  /* dummytop is a shorthand for the dummy hierarchy's top cgroup */
  #define dummytop (&rootnode.top_cgroup)
  
 +static struct cgroup_name root_cgroup_name = { .name = "/" };
 +
  /* This flag indicates whether tasks in the fork and exit paths should
   * check for fork/exit handlers to call. This avoids us having to do
   * extra work in the fork/exit path if none of the subsystems need to
@@@ -209,6 -249,20 +209,6 @@@ static int cgroup_destroy_locked(struc
  static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
                              struct cftype cfts[], bool is_add);
  
 -#ifdef CONFIG_PROVE_LOCKING
 -int cgroup_lock_is_held(void)
 -{
 -      return lockdep_is_held(&cgroup_mutex);
 -}
 -#else /* #ifdef CONFIG_PROVE_LOCKING */
 -int cgroup_lock_is_held(void)
 -{
 -      return mutex_is_locked(&cgroup_mutex);
 -}
 -#endif /* #else #ifdef CONFIG_PROVE_LOCKING */
 -
 -EXPORT_SYMBOL_GPL(cgroup_lock_is_held);
 -
  static int css_unbias_refcnt(int refcnt)
  {
        return refcnt >= 0 ? refcnt : refcnt - CSS_DEACT_BIAS;
@@@ -228,25 -282,11 +228,25 @@@ inline int cgroup_is_removed(const stru
        return test_bit(CGRP_REMOVED, &cgrp->flags);
  }
  
 -/* bits in struct cgroupfs_root flags field */
 -enum {
 -      ROOT_NOPREFIX,  /* mounted subsystems have no named prefix */
 -      ROOT_XATTR,     /* supports extended attributes */
 -};
 +/**
 + * cgroup_is_descendant - test ancestry
 + * @cgrp: the cgroup to be tested
 + * @ancestor: possible ancestor of @cgrp
 + *
 + * Test whether @cgrp is a descendant of @ancestor.  It also returns %true
 + * if @cgrp == @ancestor.  This function is safe to call as long as @cgrp
 + * and @ancestor are accessible.
 + */
 +bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor)
 +{
 +      while (cgrp) {
 +              if (cgrp == ancestor)
 +                      return true;
 +              cgrp = cgrp->parent;
 +      }
 +      return false;
 +}
 +EXPORT_SYMBOL_GPL(cgroup_is_descendant);
  
  static int cgroup_is_releasable(const struct cgroup *cgrp)
  {
@@@ -287,23 -327,6 +287,23 @@@ static inline struct cftype *__d_cft(st
        return __d_cfe(dentry)->type;
  }
  
 +/**
 + * cgroup_lock_live_group - take cgroup_mutex and check that cgrp is alive.
 + * @cgrp: the cgroup to be checked for liveness
 + *
 + * On success, returns true; the mutex should be later unlocked.  On
 + * failure returns false with no lock held.
 + */
 +static bool cgroup_lock_live_group(struct cgroup *cgrp)
 +{
 +      mutex_lock(&cgroup_mutex);
 +      if (cgroup_is_removed(cgrp)) {
 +              mutex_unlock(&cgroup_mutex);
 +              return false;
 +      }
 +      return true;
 +}
 +
  /* the list of cgroups eligible for automatic release. Protected by
   * release_list_lock */
  static LIST_HEAD(release_list);
@@@ -777,6 -800,27 +777,6 @@@ static struct cgroup *task_cgroup_from_
   * update of a tasks cgroup pointer by cgroup_attach_task()
   */
  
 -/**
 - * cgroup_lock - lock out any changes to cgroup structures
 - *
 - */
 -void cgroup_lock(void)
 -{
 -      mutex_lock(&cgroup_mutex);
 -}
 -EXPORT_SYMBOL_GPL(cgroup_lock);
 -
 -/**
 - * cgroup_unlock - release lock on cgroup changes
 - *
 - * Undo the lock taken in a previous cgroup_lock() call.
 - */
 -void cgroup_unlock(void)
 -{
 -      mutex_unlock(&cgroup_mutex);
 -}
 -EXPORT_SYMBOL_GPL(cgroup_unlock);
 -
  /*
   * A couple of forward declarations required, due to cyclic reference loop:
   * cgroup_mkdir -> cgroup_create -> cgroup_populate_dir ->
@@@ -815,17 -859,6 +815,17 @@@ static struct inode *cgroup_new_inode(u
        return inode;
  }
  
 +static struct cgroup_name *cgroup_alloc_name(struct dentry *dentry)
 +{
 +      struct cgroup_name *name;
 +
 +      name = kmalloc(sizeof(*name) + dentry->d_name.len + 1, GFP_KERNEL);
 +      if (!name)
 +              return NULL;
 +      strcpy(name->name, dentry->d_name.name);
 +      return name;
 +}
 +
  static void cgroup_free_fn(struct work_struct *work)
  {
        struct cgroup *cgrp = container_of(work, struct cgroup, free_work);
        cgrp->root->number_of_cgroups--;
        mutex_unlock(&cgroup_mutex);
  
 +      /*
 +       * We get a ref to the parent's dentry, and put the ref when
 +       * this cgroup is being freed, so it's guaranteed that the
 +       * parent won't be destroyed before its children.
 +       */
 +      dput(cgrp->parent->dentry);
 +
 +      ida_simple_remove(&cgrp->root->cgroup_ida, cgrp->id);
 +
        /*
         * Drop the active superblock reference that we took when we
 -       * created the cgroup
 +       * created the cgroup. This will free cgrp->root, if we are
 +       * holding the last reference to @sb.
         */
        deactivate_super(cgrp->root->sb);
  
  
        simple_xattrs_free(&cgrp->xattrs);
  
 -      ida_simple_remove(&cgrp->root->cgroup_ida, cgrp->id);
 +      kfree(rcu_dereference_raw(cgrp->name));
        kfree(cgrp);
  }
  
@@@ -887,12 -910,13 +887,12 @@@ static void cgroup_diput(struct dentry 
        } else {
                struct cfent *cfe = __d_cfe(dentry);
                struct cgroup *cgrp = dentry->d_parent->d_fsdata;
 -              struct cftype *cft = cfe->type;
  
                WARN_ONCE(!list_empty(&cfe->node) &&
                          cgrp != &cgrp->root->top_cgroup,
                          "cfe still linked for %s\n", cfe->type->name);
 +              simple_xattrs_free(&cfe->xattrs);
                kfree(cfe);
 -              simple_xattrs_free(&cft->xattrs);
        }
        iput(inode);
  }
@@@ -1084,11 -1108,9 +1084,11 @@@ static int cgroup_show_options(struct s
        mutex_lock(&cgroup_root_mutex);
        for_each_subsys(root, ss)
                seq_printf(seq, ",%s", ss->name);
 -      if (test_bit(ROOT_NOPREFIX, &root->flags))
 +      if (root->flags & CGRP_ROOT_SANE_BEHAVIOR)
 +              seq_puts(seq, ",sane_behavior");
 +      if (root->flags & CGRP_ROOT_NOPREFIX)
                seq_puts(seq, ",noprefix");
 -      if (test_bit(ROOT_XATTR, &root->flags))
 +      if (root->flags & CGRP_ROOT_XATTR)
                seq_puts(seq, ",xattr");
        if (strlen(root->release_agent_path))
                seq_printf(seq, ",release_agent=%s", root->release_agent_path);
@@@ -1150,12 -1172,8 +1150,12 @@@ static int parse_cgroupfs_options(char 
                        all_ss = true;
                        continue;
                }
 +              if (!strcmp(token, "__DEVEL__sane_behavior")) {
 +                      opts->flags |= CGRP_ROOT_SANE_BEHAVIOR;
 +                      continue;
 +              }
                if (!strcmp(token, "noprefix")) {
 -                      set_bit(ROOT_NOPREFIX, &opts->flags);
 +                      opts->flags |= CGRP_ROOT_NOPREFIX;
                        continue;
                }
                if (!strcmp(token, "clone_children")) {
                        continue;
                }
                if (!strcmp(token, "xattr")) {
 -                      set_bit(ROOT_XATTR, &opts->flags);
 +                      opts->flags |= CGRP_ROOT_XATTR;
                        continue;
                }
                if (!strncmp(token, "release_agent=", 14)) {
  
        /* Consistency checks */
  
 +      if (opts->flags & CGRP_ROOT_SANE_BEHAVIOR) {
 +              pr_warning("cgroup: sane_behavior: this is still under development and its behaviors will change, proceed at your own risk\n");
 +
 +              if (opts->flags & CGRP_ROOT_NOPREFIX) {
 +                      pr_err("cgroup: sane_behavior: noprefix is not allowed\n");
 +                      return -EINVAL;
 +              }
 +
 +              if (opts->cpuset_clone_children) {
 +                      pr_err("cgroup: sane_behavior: clone_children is not allowed\n");
 +                      return -EINVAL;
 +              }
 +      }
 +
        /*
         * Option noprefix was introduced just for backward compatibility
         * with the old cpuset, so we allow noprefix only if mounting just
         * the cpuset subsystem.
         */
 -      if (test_bit(ROOT_NOPREFIX, &opts->flags) &&
 -          (opts->subsys_mask & mask))
 +      if ((opts->flags & CGRP_ROOT_NOPREFIX) && (opts->subsys_mask & mask))
                return -EINVAL;
  
  
@@@ -1331,11 -1336,6 +1331,11 @@@ static int cgroup_remount(struct super_
        struct cgroup_sb_opts opts;
        unsigned long added_mask, removed_mask;
  
 +      if (root->flags & CGRP_ROOT_SANE_BEHAVIOR) {
 +              pr_err("cgroup: sane_behavior: remount is not allowed\n");
 +              return -EINVAL;
 +      }
 +
        mutex_lock(&cgrp->dentry->d_inode->i_mutex);
        mutex_lock(&cgroup_mutex);
        mutex_lock(&cgroup_root_mutex);
@@@ -1421,7 -1421,7 +1421,7 @@@ static void init_cgroup_root(struct cgr
        INIT_LIST_HEAD(&root->allcg_list);
        root->number_of_cgroups = 1;
        cgrp->root = root;
 -      cgrp->top_cgroup = cgrp;
 +      cgrp->name = &root_cgroup_name;
        init_cgroup_housekeeping(cgrp);
        list_add_tail(&cgrp->allcg_node, &root->allcg_list);
  }
@@@ -1685,14 -1685,6 +1685,14 @@@ static struct dentry *cgroup_mount(stru
                 * any) is not needed
                 */
                cgroup_drop_root(opts.new_root);
 +
 +              if (((root->flags | opts.flags) & CGRP_ROOT_SANE_BEHAVIOR) &&
 +                  root->flags != opts.flags) {
 +                      pr_err("cgroup: sane_behavior: new mount options should match the existing superblock\n");
 +                      ret = -EINVAL;
 +                      goto drop_new_super;
 +              }
 +
                /* no subsys rebinding, so refcounts don't change */
                drop_parsed_module_refcounts(opts.subsys_mask);
        }
@@@ -1777,48 -1769,49 +1777,48 @@@ static struct kobject *cgroup_kobj
   * @buf: the buffer to write the path into
   * @buflen: the length of the buffer
   *
 - * Called with cgroup_mutex held or else with an RCU-protected cgroup
 - * reference.  Writes path of cgroup into buf.  Returns 0 on success,
 - * -errno on error.
 + * Writes path of cgroup into buf.  Returns 0 on success, -errno on error.
 + *
 + * We can't generate cgroup path using dentry->d_name, as accessing
 + * dentry->name must be protected by irq-unsafe dentry->d_lock or parent
 + * inode's i_mutex, while on the other hand cgroup_path() can be called
 + * with some irq-safe spinlocks held.
   */
  int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
  {
 -      struct dentry *dentry = cgrp->dentry;
 +      int ret = -ENAMETOOLONG;
        char *start;
  
 -      rcu_lockdep_assert(rcu_read_lock_held() || cgroup_lock_is_held(),
 -                         "cgroup_path() called without proper locking");
 -
 -      if (cgrp == dummytop) {
 -              /*
 -               * Inactive subsystems have no dentry for their root
 -               * cgroup
 -               */
 -              strcpy(buf, "/");
 +      if (!cgrp->parent) {
 +              if (strlcpy(buf, "/", buflen) >= buflen)
 +                      return -ENAMETOOLONG;
                return 0;
        }
  
        start = buf + buflen - 1;
 -
        *start = '\0';
 -      for (;;) {
 -              int len = dentry->d_name.len;
  
 +      rcu_read_lock();
 +      do {
 +              const char *name = cgroup_name(cgrp);
 +              int len;
 +
 +              len = strlen(name);
                if ((start -= len) < buf)
 -                      return -ENAMETOOLONG;
 -              memcpy(start, dentry->d_name.name, len);
 -              cgrp = cgrp->parent;
 -              if (!cgrp)
 -                      break;
 +                      goto out;
 +              memcpy(start, name, len);
  
 -              dentry = cgrp->dentry;
 -              if (!cgrp->parent)
 -                      continue;
                if (--start < buf)
 -                      return -ENAMETOOLONG;
 +                      goto out;
                *start = '/';
 -      }
 +
 +              cgrp = cgrp->parent;
 +      } while (cgrp->parent);
 +      ret = 0;
        memmove(buf, start, buf + buflen - start);
 -      return 0;
 +out:
 +      rcu_read_unlock();
 +      return ret;
  }
  EXPORT_SYMBOL_GPL(cgroup_path);
  
@@@ -1907,7 -1900,7 +1907,7 @@@ EXPORT_SYMBOL_GPL(cgroup_taskset_size)
   *
   * Must be called with cgroup_mutex and threadgroup locked.
   */
 -static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp,
 +static void cgroup_task_migrate(struct cgroup *oldcgrp,
                                struct task_struct *tsk, struct css_set *newcg)
  {
        struct css_set *oldcg;
  }
  
  /**
 - * cgroup_attach_task - attach task 'tsk' to cgroup 'cgrp'
 - * @cgrp: the cgroup the task is attaching to
 - * @tsk: the task to be attached
 - *
 - * Call with cgroup_mutex and threadgroup locked. May take task_lock of
 - * @tsk during call.
 - */
 -int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
 -{
 -      int retval = 0;
 -      struct cgroup_subsys *ss, *failed_ss = NULL;
 -      struct cgroup *oldcgrp;
 -      struct cgroupfs_root *root = cgrp->root;
 -      struct cgroup_taskset tset = { };
 -      struct css_set *newcg;
 -
 -      /* @tsk either already exited or can't exit until the end */
 -      if (tsk->flags & PF_EXITING)
 -              return -ESRCH;
 -
 -      /* Nothing to do if the task is already in that cgroup */
 -      oldcgrp = task_cgroup_from_root(tsk, root);
 -      if (cgrp == oldcgrp)
 -              return 0;
 -
 -      tset.single.task = tsk;
 -      tset.single.cgrp = oldcgrp;
 -
 -      for_each_subsys(root, ss) {
 -              if (ss->can_attach) {
 -                      retval = ss->can_attach(cgrp, &tset);
 -                      if (retval) {
 -                              /*
 -                               * Remember on which subsystem the can_attach()
 -                               * failed, so that we only call cancel_attach()
 -                               * against the subsystems whose can_attach()
 -                               * succeeded. (See below)
 -                               */
 -                              failed_ss = ss;
 -                              goto out;
 -                      }
 -              }
 -      }
 -
 -      newcg = find_css_set(tsk->cgroups, cgrp);
 -      if (!newcg) {
 -              retval = -ENOMEM;
 -              goto out;
 -      }
 -
 -      cgroup_task_migrate(cgrp, oldcgrp, tsk, newcg);
 -
 -      for_each_subsys(root, ss) {
 -              if (ss->attach)
 -                      ss->attach(cgrp, &tset);
 -      }
 -
 -out:
 -      if (retval) {
 -              for_each_subsys(root, ss) {
 -                      if (ss == failed_ss)
 -                              /*
 -                               * This subsystem was the one that failed the
 -                               * can_attach() check earlier, so we don't need
 -                               * to call cancel_attach() against it or any
 -                               * remaining subsystems.
 -                               */
 -                              break;
 -                      if (ss->cancel_attach)
 -                              ss->cancel_attach(cgrp, &tset);
 -              }
 -      }
 -      return retval;
 -}
 -
 -/**
 - * cgroup_attach_task_all - attach task 'tsk' to all cgroups of task 'from'
 - * @from: attach to all cgroups of a given task
 - * @tsk: the task to be attached
 - */
 -int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
 -{
 -      struct cgroupfs_root *root;
 -      int retval = 0;
 -
 -      cgroup_lock();
 -      for_each_active_root(root) {
 -              struct cgroup *from_cg = task_cgroup_from_root(from, root);
 -
 -              retval = cgroup_attach_task(from_cg, tsk);
 -              if (retval)
 -                      break;
 -      }
 -      cgroup_unlock();
 -
 -      return retval;
 -}
 -EXPORT_SYMBOL_GPL(cgroup_attach_task_all);
 -
 -/**
 - * cgroup_attach_proc - attach all threads in a threadgroup to a cgroup
 + * cgroup_attach_task - attach a task or a whole threadgroup to a cgroup
   * @cgrp: the cgroup to attach to
 - * @leader: the threadgroup leader task_struct of the group to be attached
 + * @tsk: the task or the leader of the threadgroup to be attached
 + * @threadgroup: attach the whole threadgroup?
   *
   * Call holding cgroup_mutex and the group_rwsem of the leader. Will take
 - * task_lock of each thread in leader's threadgroup individually in turn.
 + * task_lock of @tsk or each thread in the threadgroup individually in turn.
   */
 -static int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
 +static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
 +                            bool threadgroup)
  {
        int retval, i, group_size;
        struct cgroup_subsys *ss, *failed_ss = NULL;
 -      /* guaranteed to be initialized later, but the compiler needs this */
        struct cgroupfs_root *root = cgrp->root;
        /* threadgroup list cursor and array */
 -      struct task_struct *tsk;
 +      struct task_struct *leader = tsk;
        struct task_and_cgroup *tc;
        struct flex_array *group;
        struct cgroup_taskset tset = { };
         * group - group_rwsem prevents new threads from appearing, and if
         * threads exit, this will just be an over-estimate.
         */
 -      group_size = get_nr_threads(leader);
 +      if (threadgroup)
 +              group_size = get_nr_threads(tsk);
 +      else
 +              group_size = 1;
        /* flex_array supports very large thread-groups better than kmalloc. */
        group = flex_array_alloc(sizeof(*tc), group_size, GFP_KERNEL);
        if (!group)
                return -ENOMEM;
        /* pre-allocate to guarantee space while iterating in rcu read-side. */
 -      retval = flex_array_prealloc(group, 0, group_size - 1, GFP_KERNEL);
 +      retval = flex_array_prealloc(group, 0, group_size, GFP_KERNEL);
        if (retval)
                goto out_free_group_list;
  
 -      tsk = leader;
        i = 0;
        /*
         * Prevent freeing of tasks while we take a snapshot. Tasks that are
                retval = flex_array_put(group, i, &ent, GFP_ATOMIC);
                BUG_ON(retval != 0);
                i++;
 +
 +              if (!threadgroup)
 +                      break;
        } while_each_thread(leader, tsk);
        rcu_read_unlock();
        /* remember the number of threads in the array for later. */
         */
        for (i = 0; i < group_size; i++) {
                tc = flex_array_get(group, i);
 -              cgroup_task_migrate(cgrp, tc->cgrp, tc->task, tc->cg);
 +              cgroup_task_migrate(tc->cgrp, tc->task, tc->cg);
        }
        /* nothing is sensitive to fork() after this point. */
  
@@@ -2137,11 -2224,11 +2137,11 @@@ retry_find_task
                tsk = tsk->group_leader;
  
        /*
 -       * Workqueue threads may acquire PF_THREAD_BOUND and become
 +       * Workqueue threads may acquire PF_NO_SETAFFINITY and become
         * trapped in a cpuset, or RT worker may be born in a cgroup
         * with no rt_runtime allocated.  Just say no.
         */
 -      if (tsk == kthreadd_task || (tsk->flags & PF_THREAD_BOUND)) {
 +      if (tsk == kthreadd_task || (tsk->flags & PF_NO_SETAFFINITY)) {
                ret = -EINVAL;
                rcu_read_unlock();
                goto out_unlock_cgroup;
                        put_task_struct(tsk);
                        goto retry_find_task;
                }
 -              ret = cgroup_attach_proc(cgrp, tsk);
 -      } else
 -              ret = cgroup_attach_task(cgrp, tsk);
 +      }
 +
 +      ret = cgroup_attach_task(cgrp, tsk, threadgroup);
 +
        threadgroup_unlock(tsk);
  
        put_task_struct(tsk);
  out_unlock_cgroup:
 -      cgroup_unlock();
 +      mutex_unlock(&cgroup_mutex);
        return ret;
  }
  
 +/**
 + * cgroup_attach_task_all - attach task 'tsk' to all cgroups of task 'from'
 + * @from: attach to all cgroups of a given task
 + * @tsk: the task to be attached
 + */
 +int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
 +{
 +      struct cgroupfs_root *root;
 +      int retval = 0;
 +
 +      mutex_lock(&cgroup_mutex);
 +      for_each_active_root(root) {
 +              struct cgroup *from_cg = task_cgroup_from_root(from, root);
 +
 +              retval = cgroup_attach_task(from_cg, tsk, false);
 +              if (retval)
 +                      break;
 +      }
 +      mutex_unlock(&cgroup_mutex);
 +
 +      return retval;
 +}
 +EXPORT_SYMBOL_GPL(cgroup_attach_task_all);
 +
  static int cgroup_tasks_write(struct cgroup *cgrp, struct cftype *cft, u64 pid)
  {
        return attach_task_by_pid(cgrp, pid, false);
@@@ -2210,6 -2272,24 +2210,6 @@@ static int cgroup_procs_write(struct cg
        return attach_task_by_pid(cgrp, tgid, true);
  }
  
 -/**
 - * cgroup_lock_live_group - take cgroup_mutex and check that cgrp is alive.
 - * @cgrp: the cgroup to be checked for liveness
 - *
 - * On success, returns true; the lock should be later released with
 - * cgroup_unlock(). On failure returns false with no lock held.
 - */
 -bool cgroup_lock_live_group(struct cgroup *cgrp)
 -{
 -      mutex_lock(&cgroup_mutex);
 -      if (cgroup_is_removed(cgrp)) {
 -              mutex_unlock(&cgroup_mutex);
 -              return false;
 -      }
 -      return true;
 -}
 -EXPORT_SYMBOL_GPL(cgroup_lock_live_group);
 -
  static int cgroup_release_agent_write(struct cgroup *cgrp, struct cftype *cft,
                                      const char *buffer)
  {
        mutex_lock(&cgroup_root_mutex);
        strcpy(cgrp->root->release_agent_path, buffer);
        mutex_unlock(&cgroup_root_mutex);
 -      cgroup_unlock();
 +      mutex_unlock(&cgroup_mutex);
        return 0;
  }
  
@@@ -2232,14 -2312,7 +2232,14 @@@ static int cgroup_release_agent_show(st
                return -ENODEV;
        seq_puts(seq, cgrp->root->release_agent_path);
        seq_putc(seq, '\n');
 -      cgroup_unlock();
 +      mutex_unlock(&cgroup_mutex);
 +      return 0;
 +}
 +
 +static int cgroup_sane_behavior_show(struct cgroup *cgrp, struct cftype *cft,
 +                                   struct seq_file *seq)
 +{
 +      seq_printf(seq, "%d\n", cgroup_sane_behavior(cgrp));
        return 0;
  }
  
@@@ -2464,40 -2537,13 +2464,40 @@@ static int cgroup_file_release(struct i
  static int cgroup_rename(struct inode *old_dir, struct dentry *old_dentry,
                            struct inode *new_dir, struct dentry *new_dentry)
  {
 +      int ret;
 +      struct cgroup_name *name, *old_name;
 +      struct cgroup *cgrp;
 +
 +      /*
 +       * It's convinient to use parent dir's i_mutex to protected
 +       * cgrp->name.
 +       */
 +      lockdep_assert_held(&old_dir->i_mutex);
 +
        if (!S_ISDIR(old_dentry->d_inode->i_mode))
                return -ENOTDIR;
        if (new_dentry->d_inode)
                return -EEXIST;
        if (old_dir != new_dir)
                return -EIO;
 -      return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
 +
 +      cgrp = __d_cgrp(old_dentry);
 +
 +      name = cgroup_alloc_name(new_dentry);
 +      if (!name)
 +              return -ENOMEM;
 +
 +      ret = simple_rename(old_dir, old_dentry, new_dir, new_dentry);
 +      if (ret) {
 +              kfree(name);
 +              return ret;
 +      }
 +
 +      old_name = cgrp->name;
 +      rcu_assign_pointer(cgrp->name, name);
 +
 +      kfree_rcu(old_name, rcu_head);
 +      return 0;
  }
  
  static struct simple_xattrs *__d_xattrs(struct dentry *dentry)
        if (S_ISDIR(dentry->d_inode->i_mode))
                return &__d_cgrp(dentry)->xattrs;
        else
 -              return &__d_cft(dentry)->xattrs;
 +              return &__d_cfe(dentry)->xattrs;
  }
  
  static inline int xattr_enabled(struct dentry *dentry)
  {
        struct cgroupfs_root *root = dentry->d_sb->s_fs_info;
 -      return test_bit(ROOT_XATTR, &root->flags);
 +      return root->flags & CGRP_ROOT_XATTR;
  }
  
  static bool is_valid_xattr(const char *name)
@@@ -2681,7 -2727,9 +2681,7 @@@ static int cgroup_add_file(struct cgrou
        umode_t mode;
        char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 };
  
 -      simple_xattrs_init(&cft->xattrs);
 -
 -      if (subsys && !test_bit(ROOT_NOPREFIX, &cgrp->root->flags)) {
 +      if (subsys && !(cgrp->root->flags & CGRP_ROOT_NOPREFIX)) {
                strcpy(name, subsys->name);
                strcat(name, ".");
        }
                cfe->type = (void *)cft;
                cfe->dentry = dentry;
                dentry->d_fsdata = cfe;
 +              simple_xattrs_init(&cfe->xattrs);
                list_add_tail(&cfe->node, &parent->files);
                cfe = NULL;
        }
@@@ -2723,8 -2770,6 +2723,8 @@@ static int cgroup_addrm_files(struct cg
  
        for (cft = cfts; cft->name[0] != '\0'; cft++) {
                /* does cft->flags tell us to skip this file on @cgrp? */
 +              if ((cft->flags & CFTYPE_INSANE) && cgroup_sane_behavior(cgrp))
 +                      continue;
                if ((cft->flags & CFTYPE_NOT_ON_ROOT) && !cgrp->parent)
                        continue;
                if ((cft->flags & CFTYPE_ONLY_ON_ROOT) && cgrp->parent)
@@@ -3255,34 -3300,6 +3255,34 @@@ int cgroup_scan_tasks(struct cgroup_sca
        return 0;
  }
  
 +static void cgroup_transfer_one_task(struct task_struct *task,
 +                                   struct cgroup_scanner *scan)
 +{
 +      struct cgroup *new_cgroup = scan->data;
 +
 +      mutex_lock(&cgroup_mutex);
 +      cgroup_attach_task(new_cgroup, task, false);
 +      mutex_unlock(&cgroup_mutex);
 +}
 +
 +/**
 + * cgroup_trasnsfer_tasks - move tasks from one cgroup to another
 + * @to: cgroup to which the tasks will be moved
 + * @from: cgroup in which the tasks currently reside
 + */
 +int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
 +{
 +      struct cgroup_scanner scan;
 +
 +      scan.cg = from;
 +      scan.test_task = NULL; /* select all tasks in cgroup */
 +      scan.process_task = cgroup_transfer_one_task;
 +      scan.heap = NULL;
 +      scan.data = to;
 +
 +      return cgroup_scan_tasks(&scan);
 +}
 +
  /*
   * Stuff for reading the 'tasks'/'procs' files.
   *
@@@ -3345,14 -3362,35 +3345,14 @@@ static void pidlist_free(void *p
        else
                kfree(p);
  }
 -static void *pidlist_resize(void *p, int newcount)
 -{
 -      void *newlist;
 -      /* note: if new alloc fails, old p will still be valid either way */
 -      if (is_vmalloc_addr(p)) {
 -              newlist = vmalloc(newcount * sizeof(pid_t));
 -              if (!newlist)
 -                      return NULL;
 -              memcpy(newlist, p, newcount * sizeof(pid_t));
 -              vfree(p);
 -      } else {
 -              newlist = krealloc(p, newcount * sizeof(pid_t), GFP_KERNEL);
 -      }
 -      return newlist;
 -}
  
  /*
   * pidlist_uniq - given a kmalloc()ed list, strip out all duplicate entries
 - * If the new stripped list is sufficiently smaller and there's enough memory
 - * to allocate a new buffer, will let go of the unneeded memory. Returns the
 - * number of unique elements.
 + * Returns the number of unique elements.
   */
 -/* is the size difference enough that we should re-allocate the array? */
 -#define PIDLIST_REALLOC_DIFFERENCE(old, new) ((old) - PAGE_SIZE >= (new))
 -static int pidlist_uniq(pid_t **p, int length)
 +static int pidlist_uniq(pid_t *list, int length)
  {
        int src, dest = 1;
 -      pid_t *list = *p;
 -      pid_t *newlist;
  
        /*
         * we presume the 0th element is unique, so i starts at 1. trivial
                dest++;
        }
  after:
 -      /*
 -       * if the length difference is large enough, we want to allocate a
 -       * smaller buffer to save memory. if this fails due to out of memory,
 -       * we'll just stay with what we've got.
 -       */
 -      if (PIDLIST_REALLOC_DIFFERENCE(length, dest)) {
 -              newlist = pidlist_resize(list, dest);
 -              if (newlist)
 -                      *p = newlist;
 -      }
        return dest;
  }
  
@@@ -3468,7 -3516,7 +3468,7 @@@ static int pidlist_array_load(struct cg
        /* now sort & (if procs) strip out duplicates */
        sort(array, length, sizeof(pid_t), cmppid, NULL);
        if (type == CGROUP_FILE_PROCS)
 -              length = pidlist_uniq(&array, length);
 +              length = pidlist_uniq(array, length);
        l = cgroup_pidlist_find(cgrp, type);
        if (!l) {
                pidlist_free(array);
@@@ -3882,7 -3930,11 +3882,7 @@@ static int cgroup_write_event_control(s
        if (ret)
                goto fail;
  
 -      if (efile->f_op->poll(efile, &event->pt) & POLLHUP) {
 -              event->cft->unregister_event(cgrp, event->cft, event->eventfd);
 -              ret = 0;
 -              goto fail;
 -      }
 +      efile->f_op->poll(efile, &event->pt);
  
        /*
         * Events should be removed after rmdir of cgroup directory, but before
@@@ -3964,15 -4016,9 +3964,15 @@@ static struct cftype files[] = 
        },
        {
                .name = "cgroup.clone_children",
 +              .flags = CFTYPE_INSANE,
                .read_u64 = cgroup_clone_children_read,
                .write_u64 = cgroup_clone_children_write,
        },
 +      {
 +              .name = "cgroup.sane_behavior",
 +              .flags = CFTYPE_ONLY_ON_ROOT,
 +              .read_seq_string = cgroup_sane_behavior_show,
 +      },
        {
                .name = "release_agent",
                .flags = CFTYPE_ONLY_ON_ROOT,
@@@ -4085,8 -4131,17 +4085,8 @@@ static void offline_css(struct cgroup_s
        if (!(css->flags & CSS_ONLINE))
                return;
  
 -      /*
 -       * css_offline() should be called with cgroup_mutex unlocked.  See
 -       * 3fa59dfbc3 ("cgroup: fix potential deadlock in pre_destroy") for
 -       * details.  This temporary unlocking should go away once
 -       * cgroup_mutex is unexported from controllers.
 -       */
 -      if (ss->css_offline) {
 -              mutex_unlock(&cgroup_mutex);
 +      if (ss->css_offline)
                ss->css_offline(cgrp);
 -              mutex_lock(&cgroup_mutex);
 -      }
  
        cgrp->subsys[ss->subsys_id]->flags &= ~CSS_ONLINE;
  }
@@@ -4103,7 -4158,6 +4103,7 @@@ static long cgroup_create(struct cgrou
                             umode_t mode)
  {
        struct cgroup *cgrp;
 +      struct cgroup_name *name;
        struct cgroupfs_root *root = parent->root;
        int err = 0;
        struct cgroup_subsys *ss;
        if (!cgrp)
                return -ENOMEM;
  
 +      name = cgroup_alloc_name(dentry);
 +      if (!name)
 +              goto err_free_cgrp;
 +      rcu_assign_pointer(cgrp->name, name);
 +
        cgrp->id = ida_simple_get(&root->cgroup_ida, 1, 0, GFP_KERNEL);
        if (cgrp->id < 0)
 -              goto err_free_cgrp;
 +              goto err_free_name;
  
        /*
         * Only live parents can have children.  Note that the liveliness
  
        cgrp->parent = parent;
        cgrp->root = parent->root;
 -      cgrp->top_cgroup = parent->top_cgroup;
  
        if (notify_on_release(parent))
                set_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
        for_each_subsys(root, ss)
                dget(dentry);
  
 +      /* hold a ref to the parent's dentry */
 +      dget(parent->dentry);
 +
        /* creation succeeded, notify subsystems */
        for_each_subsys(root, ss) {
                err = online_css(ss, cgrp);
@@@ -4229,8 -4276,6 +4229,8 @@@ err_free_all
        deactivate_super(sb);
  err_free_id:
        ida_simple_remove(&root->cgroup_ida, cgrp->id);
 +err_free_name:
 +      kfree(rcu_dereference_raw(cgrp->name));
  err_free_cgrp:
        kfree(cgrp);
        return err;
@@@ -4250,13 -4295,56 +4250,13 @@@ static int cgroup_mkdir(struct inode *d
        return cgroup_create(c_parent, dentry, mode | S_IFDIR);
  }
  
 -/*
 - * Check the reference count on each subsystem. Since we already
 - * established that there are no tasks in the cgroup, if the css refcount
 - * is also 1, then there should be no outstanding references, so the
 - * subsystem is safe to destroy. We scan across all subsystems rather than
 - * using the per-hierarchy linked list of mounted subsystems since we can
 - * be called via check_for_release() with no synchronization other than
 - * RCU, and the subsystem linked list isn't RCU-safe.
 - */
 -static int cgroup_has_css_refs(struct cgroup *cgrp)
 -{
 -      int i;
 -
 -      /*
 -       * We won't need to lock the subsys array, because the subsystems
 -       * we're concerned about aren't going anywhere since our cgroup root
 -       * has a reference on them.
 -       */
 -      for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
 -              struct cgroup_subsys *ss = subsys[i];
 -              struct cgroup_subsys_state *css;
 -
 -              /* Skip subsystems not present or not in this hierarchy */
 -              if (ss == NULL || ss->root != cgrp->root)
 -                      continue;
 -
 -              css = cgrp->subsys[ss->subsys_id];
 -              /*
 -               * When called from check_for_release() it's possible
 -               * that by this point the cgroup has been removed
 -               * and the css deleted. But a false-positive doesn't
 -               * matter, since it can only happen if the cgroup
 -               * has been deleted and hence no longer needs the
 -               * release agent to be called anyway.
 -               */
 -              if (css && css_refcnt(css) > 1)
 -                      return 1;
 -      }
 -      return 0;
 -}
 -
  static int cgroup_destroy_locked(struct cgroup *cgrp)
        __releases(&cgroup_mutex) __acquires(&cgroup_mutex)
  {
        struct dentry *d = cgrp->dentry;
        struct cgroup *parent = cgrp->parent;
 -      DEFINE_WAIT(wait);
        struct cgroup_event *event, *tmp;
        struct cgroup_subsys *ss;
 -      LIST_HEAD(tmp_list);
  
        lockdep_assert_held(&d->d_inode->i_mutex);
        lockdep_assert_held(&cgroup_mutex);
@@@ -4380,6 -4468,7 +4380,6 @@@ static void __init cgroup_init_subsys(s
         * need to invoke fork callbacks here. */
        BUG_ON(!list_empty(&init_task.tasks));
  
 -      ss->active = 1;
        BUG_ON(online_css(ss, dummytop));
  
        mutex_unlock(&cgroup_mutex);
@@@ -4484,6 -4573,7 +4484,6 @@@ int __init_or_module cgroup_load_subsys
        }
        write_unlock(&css_set_lock);
  
 -      ss->active = 1;
        ret = online_css(ss, dummytop);
        if (ret)
                goto err_unload;
@@@ -4524,6 -4614,7 +4524,6 @@@ void cgroup_unload_subsys(struct cgroup
        mutex_lock(&cgroup_mutex);
  
        offline_css(ss, dummytop);
 -      ss->active = 0;
  
        if (ss->use_id)
                idr_destroy(&ss->idr);
@@@ -4678,7 -4769,7 +4678,7 @@@ out
   */
  
  /* TODO: Use a proper seq_file iterator */
static int proc_cgroup_show(struct seq_file *m, void *v)
+ int proc_cgroup_show(struct seq_file *m, void *v)
  {
        struct pid *pid;
        struct task_struct *tsk;
@@@ -4730,19 -4821,6 +4730,6 @@@ out
        return retval;
  }
  
- static int cgroup_open(struct inode *inode, struct file *file)
- {
-       struct pid *pid = PROC_I(inode)->pid;
-       return single_open(file, proc_cgroup_show, pid);
- }
- const struct file_operations proc_cgroup_operations = {
-       .open           = cgroup_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
- };
  /* Display information about each subsystem and each hierarchy */
  static int proc_cgroupstats_show(struct seq_file *m, void *v)
  {
@@@ -4844,17 -4922,17 +4831,17 @@@ void cgroup_post_fork(struct task_struc
         * and addition to css_set.
         */
        if (need_forkexit_callback) {
 -              for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
 +              /*
 +               * fork/exit callbacks are supported only for builtin
 +               * subsystems, and the builtin section of the subsys
 +               * array is immutable, so we don't need to lock the
 +               * subsys array here. On the other hand, modular section
 +               * of the array can be freed at module unload, so we
 +               * can't touch that.
 +               */
 +              for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
                        struct cgroup_subsys *ss = subsys[i];
  
 -                      /*
 -                       * fork/exit callbacks are supported only for
 -                       * builtin subsystems and we don't need further
 -                       * synchronization as they never go away.
 -                       */
 -                      if (!ss || ss->module)
 -                              continue;
 -
                        if (ss->fork)
                                ss->fork(child);
                }
@@@ -4919,13 -4997,13 +4906,13 @@@ void cgroup_exit(struct task_struct *ts
        tsk->cgroups = &init_css_set;
  
        if (run_callbacks && need_forkexit_callback) {
 -              for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
 +              /*
 +               * fork/exit callbacks are supported only for builtin
 +               * subsystems, see cgroup_post_fork() for details.
 +               */
 +              for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
                        struct cgroup_subsys *ss = subsys[i];
  
 -                      /* modular subsystems can't use callbacks */
 -                      if (!ss || ss->module)
 -                              continue;
 -
                        if (ss->exit) {
                                struct cgroup *old_cgrp =
                                        rcu_dereference_raw(cg->subsys[i])->cgroup;
        put_css_set_taskexit(cg);
  }
  
 -/**
 - * cgroup_is_descendant - see if @cgrp is a descendant of @task's cgrp
 - * @cgrp: the cgroup in question
 - * @task: the task in question
 - *
 - * See if @cgrp is a descendant of @task's cgroup in the appropriate
 - * hierarchy.
 - *
 - * If we are sending in dummytop, then presumably we are creating
 - * the top cgroup in the subsystem.
 - *
 - * Called only by the ns (nsproxy) cgroup.
 - */
 -int cgroup_is_descendant(const struct cgroup *cgrp, struct task_struct *task)
 -{
 -      int ret;
 -      struct cgroup *target;
 -
 -      if (cgrp == dummytop)
 -              return 1;
 -
 -      target = task_cgroup_from_root(task, cgrp->root);
 -      while (cgrp != target && cgrp!= cgrp->top_cgroup)
 -              cgrp = cgrp->parent;
 -      ret = (cgrp == target);
 -      return ret;
 -}
 -
  static void check_for_release(struct cgroup *cgrp)
  {
        /* All of these checks rely on RCU to keep the cgroup
         * structure alive */
 -      if (cgroup_is_releasable(cgrp) && !atomic_read(&cgrp->count)
 -          && list_empty(&cgrp->children) && !cgroup_has_css_refs(cgrp)) {
 -              /* Control Group is currently removeable. If it's not
 +      if (cgroup_is_releasable(cgrp) &&
 +          !atomic_read(&cgrp->count) && list_empty(&cgrp->children)) {
 +              /*
 +               * Control Group is currently removeable. If it's not
                 * already queued for a userspace notification, queue
 -               * it now */
 +               * it now
 +               */
                int need_schedule_work = 0;
 +
                raw_spin_lock(&release_list_lock);
                if (!cgroup_is_removed(cgrp) &&
                    list_empty(&cgrp->release_list)) {
@@@ -4984,11 -5087,24 +4971,11 @@@ EXPORT_SYMBOL_GPL(__css_tryget)
  /* Caller must verify that the css is not for root cgroup */
  void __css_put(struct cgroup_subsys_state *css)
  {
 -      struct cgroup *cgrp = css->cgroup;
        int v;
  
 -      rcu_read_lock();
        v = css_unbias_refcnt(atomic_dec_return(&css->refcnt));
 -
 -      switch (v) {
 -      case 1:
 -              if (notify_on_release(cgrp)) {
 -                      set_bit(CGRP_RELEASABLE, &cgrp->flags);
 -                      check_for_release(cgrp);
 -              }
 -              break;
 -      case 0:
 +      if (v == 0)
                schedule_work(&css->dput_work);
 -              break;
 -      }
 -      rcu_read_unlock();
  }
  EXPORT_SYMBOL_GPL(__css_put);
  
@@@ -5287,6 -5403,55 +5274,6 @@@ struct cgroup_subsys_state *css_lookup(
  }
  EXPORT_SYMBOL_GPL(css_lookup);
  
 -/**
 - * css_get_next - lookup next cgroup under specified hierarchy.
 - * @ss: pointer to subsystem
 - * @id: current position of iteration.
 - * @root: pointer to css. search tree under this.
 - * @foundid: position of found object.
 - *
 - * Search next css under the specified hierarchy of rootid. Calling under
 - * rcu_read_lock() is necessary. Returns NULL if it reaches the end.
 - */
 -struct cgroup_subsys_state *
 -css_get_next(struct cgroup_subsys *ss, int id,
 -           struct cgroup_subsys_state *root, int *foundid)
 -{
 -      struct cgroup_subsys_state *ret = NULL;
 -      struct css_id *tmp;
 -      int tmpid;
 -      int rootid = css_id(root);
 -      int depth = css_depth(root);
 -
 -      if (!rootid)
 -              return NULL;
 -
 -      BUG_ON(!ss->use_id);
 -      WARN_ON_ONCE(!rcu_read_lock_held());
 -
 -      /* fill start point for scan */
 -      tmpid = id;
 -      while (1) {
 -              /*
 -               * scan next entry from bitmap(tree), tmpid is updated after
 -               * idr_get_next().
 -               */
 -              tmp = idr_get_next(&ss->idr, &tmpid);
 -              if (!tmp)
 -                      break;
 -              if (tmp->depth >= depth && tmp->stack[depth] == rootid) {
 -                      ret = rcu_dereference(tmp->css);
 -                      if (ret) {
 -                              *foundid = tmpid;
 -                              break;
 -                      }
 -              }
 -              /* continue to scan from next id */
 -              tmpid = tmpid + 1;
 -      }
 -      return ret;
 -}
 -
  /*
   * get corresponding css from file open on cgroupfs directory
   */
diff --combined kernel/cpuset.c
index 12331120767ca7ebdfe0e1cede044280c042c6db,1b6f615be58727c30f38546dee58f91d3e683037..64b3f791bbe595905b00e9cf8ecbee763cbacf7d
@@@ -264,6 -264,17 +264,6 @@@ static struct cpuset top_cpuset = 
  static DEFINE_MUTEX(cpuset_mutex);
  static DEFINE_MUTEX(callback_mutex);
  
 -/*
 - * cpuset_buffer_lock protects both the cpuset_name and cpuset_nodelist
 - * buffers.  They are statically allocated to prevent using excess stack
 - * when calling cpuset_print_task_mems_allowed().
 - */
 -#define CPUSET_NAME_LEN               (128)
 -#define       CPUSET_NODELIST_LEN     (256)
 -static char cpuset_name[CPUSET_NAME_LEN];
 -static char cpuset_nodelist[CPUSET_NODELIST_LEN];
 -static DEFINE_SPINLOCK(cpuset_buffer_lock);
 -
  /*
   * CPU / memory hotplug is handled asynchronously.
   */
@@@ -769,26 -780,25 +769,26 @@@ static void rebuild_sched_domains_locke
        lockdep_assert_held(&cpuset_mutex);
        get_online_cpus();
  
 +      /*
 +       * We have raced with CPU hotplug. Don't do anything to avoid
 +       * passing doms with offlined cpu to partition_sched_domains().
 +       * Anyways, hotplug work item will rebuild sched domains.
 +       */
 +      if (!cpumask_equal(top_cpuset.cpus_allowed, cpu_active_mask))
 +              goto out;
 +
        /* Generate domain masks and attrs */
        ndoms = generate_sched_domains(&doms, &attr);
  
        /* Have scheduler rebuild the domains */
        partition_sched_domains(ndoms, doms, attr);
 -
 +out:
        put_online_cpus();
  }
  #else /* !CONFIG_SMP */
  static void rebuild_sched_domains_locked(void)
  {
  }
 -
 -static int generate_sched_domains(cpumask_var_t **domains,
 -                      struct sched_domain_attr **attributes)
 -{
 -      *domains = NULL;
 -      return 1;
 -}
  #endif /* CONFIG_SMP */
  
  void rebuild_sched_domains(void)
@@@ -1378,16 -1388,16 +1378,16 @@@ static int cpuset_can_attach(struct cgr
  
        cgroup_taskset_for_each(task, cgrp, tset) {
                /*
 -               * Kthreads bound to specific cpus cannot be moved to a new
 -               * cpuset; we cannot change their cpu affinity and
 -               * isolating such threads by their set of allowed nodes is
 -               * unnecessary.  Thus, cpusets are not applicable for such
 -               * threads.  This prevents checking for success of
 -               * set_cpus_allowed_ptr() on all attached tasks before
 -               * cpus_allowed may be changed.
 +               * Kthreads which disallow setaffinity shouldn't be moved
 +               * to a new cpuset; we don't want to change their cpu
 +               * affinity and isolating such threads by their set of
 +               * allowed nodes is unnecessary.  Thus, cpusets are not
 +               * applicable for such threads.  This prevents checking for
 +               * success of set_cpus_allowed_ptr() on all attached tasks
 +               * before cpus_allowed may be changed.
                 */
                ret = -EINVAL;
 -              if (task->flags & PF_THREAD_BOUND)
 +              if (task->flags & PF_NO_SETAFFINITY)
                        goto out_unlock;
                ret = security_task_setscheduler(task);
                if (ret)
@@@ -1995,6 -2005,50 +1995,6 @@@ int __init cpuset_init(void
        return 0;
  }
  
 -/**
 - * cpuset_do_move_task - move a given task to another cpuset
 - * @tsk: pointer to task_struct the task to move
 - * @scan: struct cgroup_scanner contained in its struct cpuset_hotplug_scanner
 - *
 - * Called by cgroup_scan_tasks() for each task in a cgroup.
 - * Return nonzero to stop the walk through the tasks.
 - */
 -static void cpuset_do_move_task(struct task_struct *tsk,
 -                              struct cgroup_scanner *scan)
 -{
 -      struct cgroup *new_cgroup = scan->data;
 -
 -      cgroup_lock();
 -      cgroup_attach_task(new_cgroup, tsk);
 -      cgroup_unlock();
 -}
 -
 -/**
 - * move_member_tasks_to_cpuset - move tasks from one cpuset to another
 - * @from: cpuset in which the tasks currently reside
 - * @to: cpuset to which the tasks will be moved
 - *
 - * Called with cpuset_mutex held
 - * callback_mutex must not be held, as cpuset_attach() will take it.
 - *
 - * The cgroup_scan_tasks() function will scan all the tasks in a cgroup,
 - * calling callback functions for each.
 - */
 -static void move_member_tasks_to_cpuset(struct cpuset *from, struct cpuset *to)
 -{
 -      struct cgroup_scanner scan;
 -
 -      scan.cg = from->css.cgroup;
 -      scan.test_task = NULL; /* select all tasks in cgroup */
 -      scan.process_task = cpuset_do_move_task;
 -      scan.heap = NULL;
 -      scan.data = to->css.cgroup;
 -
 -      if (cgroup_scan_tasks(&scan))
 -              printk(KERN_ERR "move_member_tasks_to_cpuset: "
 -                              "cgroup_scan_tasks failed\n");
 -}
 -
  /*
   * If CPU and/or memory hotplug handlers, below, unplug any CPUs
   * or memory nodes, we need to walk over the cpuset hierarchy,
@@@ -2015,12 -2069,7 +2015,12 @@@ static void remove_tasks_in_empty_cpuse
                        nodes_empty(parent->mems_allowed))
                parent = parent_cs(parent);
  
 -      move_member_tasks_to_cpuset(cs, parent);
 +      if (cgroup_transfer_tasks(parent->css.cgroup, cs->css.cgroup)) {
 +              rcu_read_lock();
 +              printk(KERN_ERR "cpuset: failed to transfer tasks out of empty cpuset %s\n",
 +                     cgroup_name(cs->css.cgroup));
 +              rcu_read_unlock();
 +      }
  }
  
  /**
@@@ -2173,8 -2222,17 +2173,8 @@@ static void cpuset_hotplug_workfn(struc
        flush_workqueue(cpuset_propagate_hotplug_wq);
  
        /* rebuild sched domains if cpus_allowed has changed */
 -      if (cpus_updated) {
 -              struct sched_domain_attr *attr;
 -              cpumask_var_t *doms;
 -              int ndoms;
 -
 -              mutex_lock(&cpuset_mutex);
 -              ndoms = generate_sched_domains(&doms, &attr);
 -              mutex_unlock(&cpuset_mutex);
 -
 -              partition_sched_domains(ndoms, doms, attr);
 -      }
 +      if (cpus_updated)
 +              rebuild_sched_domains();
  }
  
  void cpuset_update_active_cpus(bool cpu_online)
        schedule_work(&cpuset_hotplug_work);
  }
  
 -#ifdef CONFIG_MEMORY_HOTPLUG
  /*
   * Keep top_cpuset.mems_allowed tracking node_states[N_MEMORY].
   * Call this routine anytime after node_states[N_MEMORY] changes.
@@@ -2204,23 -2263,20 +2204,23 @@@ static int cpuset_track_online_nodes(st
        schedule_work(&cpuset_hotplug_work);
        return NOTIFY_OK;
  }
 -#endif
 +
 +static struct notifier_block cpuset_track_online_nodes_nb = {
 +      .notifier_call = cpuset_track_online_nodes,
 +      .priority = 10,         /* ??! */
 +};
  
  /**
   * cpuset_init_smp - initialize cpus_allowed
   *
   * Description: Finish top cpuset after cpu, node maps are initialized
 - **/
 -
 + */
  void __init cpuset_init_smp(void)
  {
        cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask);
        top_cpuset.mems_allowed = node_states[N_MEMORY];
  
 -      hotplug_memory_notifier(cpuset_track_online_nodes, 10);
 +      register_hotmemory_notifier(&cpuset_track_online_nodes_nb);
  
        cpuset_propagate_hotplug_wq =
                alloc_ordered_workqueue("cpuset_hotplug", 0);
@@@ -2536,8 -2592,6 +2536,8 @@@ int cpuset_mems_allowed_intersects(cons
        return nodes_intersects(tsk1->mems_allowed, tsk2->mems_allowed);
  }
  
 +#define CPUSET_NODELIST_LEN   (256)
 +
  /**
   * cpuset_print_task_mems_allowed - prints task's cpuset and mems_allowed
   * @task: pointer to task_struct of some task.
   */
  void cpuset_print_task_mems_allowed(struct task_struct *tsk)
  {
 -      struct dentry *dentry;
 +       /* Statically allocated to prevent using excess stack. */
 +      static char cpuset_nodelist[CPUSET_NODELIST_LEN];
 +      static DEFINE_SPINLOCK(cpuset_buffer_lock);
  
 -      dentry = task_cs(tsk)->css.cgroup->dentry;
 -      spin_lock(&cpuset_buffer_lock);
 +      struct cgroup *cgrp = task_cs(tsk)->css.cgroup;
  
 -      if (!dentry) {
 -              strcpy(cpuset_name, "/");
 -      } else {
 -              spin_lock(&dentry->d_lock);
 -              strlcpy(cpuset_name, (const char *)dentry->d_name.name,
 -                      CPUSET_NAME_LEN);
 -              spin_unlock(&dentry->d_lock);
 -      }
 +      rcu_read_lock();
 +      spin_lock(&cpuset_buffer_lock);
  
        nodelist_scnprintf(cpuset_nodelist, CPUSET_NODELIST_LEN,
                           tsk->mems_allowed);
        printk(KERN_INFO "%s cpuset=%s mems_allowed=%s\n",
 -             tsk->comm, cpuset_name, cpuset_nodelist);
 +             tsk->comm, cgroup_name(cgrp), cpuset_nodelist);
 +
        spin_unlock(&cpuset_buffer_lock);
 +      rcu_read_unlock();
  }
  
  /*
@@@ -2609,7 -2666,7 +2609,7 @@@ void __cpuset_memory_pressure_bump(void
   *    and we take cpuset_mutex, keeping cpuset_attach() from changing it
   *    anyway.
   */
static int proc_cpuset_show(struct seq_file *m, void *unused_v)
+ int proc_cpuset_show(struct seq_file *m, void *unused_v)
  {
        struct pid *pid;
        struct task_struct *tsk;
@@@ -2643,19 -2700,6 +2643,6 @@@ out_free
  out:
        return retval;
  }
- static int cpuset_open(struct inode *inode, struct file *file)
- {
-       struct pid *pid = PROC_I(inode)->pid;
-       return single_open(file, proc_cpuset_show, pid);
- }
- const struct file_operations proc_cpuset_operations = {
-       .open           = cpuset_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
- };
  #endif /* CONFIG_PROC_PID_CPUSET */
  
  /* Display task mems_allowed in /proc/<pid>/status file. */
diff --combined kernel/exit.c
index 6e3151ec900ff16396fadec757ccf6a5a1878d0a,cd9e9e799bd2db051b37b65a37122095e3732933..af2eb3cbd499305c3d418c7f8280c2d7f0f9437d
@@@ -835,7 -835,7 +835,7 @@@ void do_exit(long code
        /*
         * Make sure we are holding no locks:
         */
 -      debug_check_no_locks_held();
 +      debug_check_no_locks_held(tsk);
        /*
         * We can do this unlocked here. The futex code uses this flag
         * just to verify whether the pi state cleanup has been done
                exit_io_context(tsk);
  
        if (tsk->splice_pipe)
-               __free_pipe_info(tsk->splice_pipe);
+               free_pipe_info(tsk->splice_pipe);
  
        if (tsk->task_frag.page)
                put_page(tsk->task_frag.page);
@@@ -1629,6 -1629,9 +1629,6 @@@ SYSCALL_DEFINE5(waitid, int, which, pid
        }
  
        put_pid(pid);
 -
 -      /* avoid REGPARM breakage on x86: */
 -      asmlinkage_protect(5, ret, which, upid, infop, options, ru);
        return ret;
  }
  
@@@ -1666,6 -1669,8 +1666,6 @@@ SYSCALL_DEFINE4(wait4, pid_t, upid, in
        ret = do_wait(&wo);
        put_pid(pid);
  
 -      /* avoid REGPARM breakage on x86: */
 -      asmlinkage_protect(4, ret, upid, stat_addr, options, ru);
        return ret;
  }
  
diff --combined kernel/pid.c
index 6283d6412affd58763657141aeec206cb1a32d02,686255e2c39e4874a13d78051afc8f54c7d4ae63..0db3e791a06d48594606bc4789bc8fbe0fd5a4f0
@@@ -36,6 -36,7 +36,7 @@@
  #include <linux/pid_namespace.h>
  #include <linux/init_task.h>
  #include <linux/syscalls.h>
+ #include <linux/proc_ns.h>
  #include <linux/proc_fs.h>
  
  #define pid_hashfn(nr, ns)    \
@@@ -51,6 -52,9 +52,6 @@@ int pid_max = PID_MAX_DEFAULT
  int pid_max_min = RESERVED_PIDS + 1;
  int pid_max_max = PID_MAX_LIMIT;
  
 -#define BITS_PER_PAGE         (PAGE_SIZE*8)
 -#define BITS_PER_PAGE_MASK    (BITS_PER_PAGE-1)
 -
  static inline int mk_pid(struct pid_namespace *pid_ns,
                struct pidmap *map, int off)
  {
@@@ -180,19 -184,15 +181,19 @@@ static int alloc_pidmap(struct pid_name
                                break;
                }
                if (likely(atomic_read(&map->nr_free))) {
 -                      do {
 +                      for ( ; ; ) {
                                if (!test_and_set_bit(offset, map->page)) {
                                        atomic_dec(&map->nr_free);
                                        set_last_pid(pid_ns, last, pid);
                                        return pid;
                                }
                                offset = find_next_offset(map, offset);
 +                              if (offset >= BITS_PER_PAGE)
 +                                      break;
                                pid = mk_pid(pid_ns, map, offset);
 -                      } while (offset < BITS_PER_PAGE && pid < pid_max);
 +                              if (pid >= pid_max)
 +                                      break;
 +                      }
                }
                if (map < &pid_ns->pidmap[(pid_max-1)/BITS_PER_PAGE]) {
                        ++map;
diff --combined kernel/pid_namespace.c
index 69473c4a653f72e47affee5bc71e832336da7f60,4af28a84906545765c1429461e166c4d362e765c..6917e8edb48e7702714041737657f1e3949bc849
  #include <linux/err.h>
  #include <linux/acct.h>
  #include <linux/slab.h>
- #include <linux/proc_fs.h>
+ #include <linux/proc_ns.h>
  #include <linux/reboot.h>
  #include <linux/export.h>
  
 -#define BITS_PER_PAGE         (PAGE_SIZE*8)
 -
  struct pid_cache {
        int nr_ids;
        char name[16];
@@@ -179,7 -181,6 +179,7 @@@ void zap_pid_ns_processes(struct pid_na
        int nr;
        int rc;
        struct task_struct *task, *me = current;
 +      int init_pids = thread_group_leader(me) ? 1 : 2;
  
        /* Don't allow any more processes into the pid namespace */
        disable_pid_allocation(pid_ns);
         */
        for (;;) {
                set_current_state(TASK_UNINTERRUPTIBLE);
 -              if (pid_ns->nr_hashed == 1)
 +              if (pid_ns->nr_hashed == init_pids)
                        break;
                schedule();
        }
diff --combined kernel/user.c
index 8e635a18ab521e48cfc4195cfb9f199de5e0c3b3,5bbb91988e69278f2cd012896db29688c9234476..69b4c3d48cdee20fc94be4d2869e2e330ba0a7b2
@@@ -16,7 -16,7 +16,7 @@@
  #include <linux/interrupt.h>
  #include <linux/export.h>
  #include <linux/user_namespace.h>
- #include <linux/proc_fs.h>
+ #include <linux/proc_ns.h>
  
  /*
   * userns count is 1 for root user, 1 for init_uts_ns,
@@@ -51,8 -51,6 +51,8 @@@ struct user_namespace init_user_ns = 
        .owner = GLOBAL_ROOT_UID,
        .group = GLOBAL_ROOT_GID,
        .proc_inum = PROC_USER_INIT_INO,
 +      .may_mount_sysfs = true,
 +      .may_mount_proc = true,
  };
  EXPORT_SYMBOL_GPL(init_user_ns);
  
diff --combined kernel/user_namespace.c
index e134d8f365ddea425ac6a8df541875038928298d,51855f5f6311211c785373d52e990f879ec959fe..d8c30db06c5b75456098fe2f1a26785e9a9110ee
@@@ -9,7 -9,7 +9,7 @@@
  #include <linux/nsproxy.h>
  #include <linux/slab.h>
  #include <linux/user_namespace.h>
- #include <linux/proc_fs.h>
+ #include <linux/proc_ns.h>
  #include <linux/highuid.h>
  #include <linux/cred.h>
  #include <linux/securebits.h>
@@@ -25,8 -25,7 +25,8 @@@
  
  static struct kmem_cache *user_ns_cachep __read_mostly;
  
 -static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
 +static bool new_idmap_permitted(const struct file *file,
 +                              struct user_namespace *ns, int cap_setid,
                                struct uid_gid_map *map);
  
  static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns)
@@@ -62,15 -61,6 +62,15 @@@ int create_user_ns(struct cred *new
        kgid_t group = new->egid;
        int ret;
  
 +      /*
 +       * Verify that we can not violate the policy of which files
 +       * may be accessed that is specified by the root directory,
 +       * by verifing that the root directory is at the root of the
 +       * mount namespace which allows all files to be accessed.
 +       */
 +      if (current_chrooted())
 +              return -EPERM;
 +
        /* The creator needs a mapping in the parent user namespace
         * or else we won't be able to reasonably tell userspace who
         * created a user_namespace.
@@@ -97,8 -87,6 +97,8 @@@
  
        set_cred_user_ns(new, ns);
  
 +      update_mnt_policy(ns);
 +
        return 0;
  }
  
@@@ -613,10 -601,10 +613,10 @@@ static ssize_t map_write(struct file *f
        if (map->nr_extents != 0)
                goto out;
  
 -      /* Require the appropriate privilege CAP_SETUID or CAP_SETGID
 -       * over the user namespace in order to set the id mapping.
 +      /*
 +       * Adjusting namespace settings requires capabilities on the target.
         */
 -      if (cap_valid(cap_setid) && !ns_capable(ns, cap_setid))
 +      if (cap_valid(cap_setid) && !file_ns_capable(file, ns, CAP_SYS_ADMIN))
                goto out;
  
        /* Get a buffer */
  
        ret = -EPERM;
        /* Validate the user is allowed to use user id's mapped to. */
 -      if (!new_idmap_permitted(ns, cap_setid, &new_map))
 +      if (!new_idmap_permitted(file, ns, cap_setid, &new_map))
                goto out;
  
        /* Map the lower ids from the parent user namespace to the
@@@ -788,8 -776,7 +788,8 @@@ ssize_t proc_projid_map_write(struct fi
                         &ns->projid_map, &ns->parent->projid_map);
  }
  
 -static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
 +static bool new_idmap_permitted(const struct file *file, 
 +                              struct user_namespace *ns, int cap_setid,
                                struct uid_gid_map *new_map)
  {
        /* Allow mapping to your own filesystem ids */
                u32 id = new_map->extent[0].lower_first;
                if (cap_setid == CAP_SETUID) {
                        kuid_t uid = make_kuid(ns->parent, id);
 -                      if (uid_eq(uid, current_fsuid()))
 +                      if (uid_eq(uid, file->f_cred->fsuid))
                                return true;
                }
                else if (cap_setid == CAP_SETGID) {
                        kgid_t gid = make_kgid(ns->parent, id);
 -                      if (gid_eq(gid, current_fsgid()))
 +                      if (gid_eq(gid, file->f_cred->fsgid))
                                return true;
                }
        }
  
        /* Allow the specified ids if we have the appropriate capability
         * (CAP_SETUID or CAP_SETGID) over the parent user namespace.
 +       * And the opener of the id file also had the approprpiate capability.
         */
 -      if (ns_capable(ns->parent, cap_setid))
 +      if (ns_capable(ns->parent, cap_setid) &&
 +          file_ns_capable(file, ns->parent, cap_setid))
                return true;
  
        return false;
diff --combined mm/filemap.c
index e989fb1eaa72ba33bc7ed1526d49f13d84249748,cbde8842a37458ec87f6fef57c7cadd59c8b98e1..7905fe721aa8ab3db06c957c9f2cc63cea1fee5f
@@@ -35,9 -35,6 +35,9 @@@
  #include <linux/cleancache.h>
  #include "internal.h"
  
 +#define CREATE_TRACE_POINTS
 +#include <trace/events/filemap.h>
 +
  /*
   * FIXME: remove all knowledge of the buffer layer from the core VM
   */
@@@ -116,7 -113,6 +116,7 @@@ void __delete_from_page_cache(struct pa
  {
        struct address_space *mapping = page->mapping;
  
 +      trace_mm_filemap_delete_from_page_cache(page);
        /*
         * if we're uptodate, flush out into the cleancache, otherwise
         * invalidate any existing cleancache entries.  We can't leave
@@@ -188,17 -184,6 +188,17 @@@ static int sleep_on_page_killable(void 
        return fatal_signal_pending(current) ? -EINTR : 0;
  }
  
 +static int filemap_check_errors(struct address_space *mapping)
 +{
 +      int ret = 0;
 +      /* Check for outstanding write errors */
 +      if (test_and_clear_bit(AS_ENOSPC, &mapping->flags))
 +              ret = -ENOSPC;
 +      if (test_and_clear_bit(AS_EIO, &mapping->flags))
 +              ret = -EIO;
 +      return ret;
 +}
 +
  /**
   * __filemap_fdatawrite_range - start writeback on mapping dirty pages in range
   * @mapping:  address space structure to write
@@@ -280,10 -265,10 +280,10 @@@ int filemap_fdatawait_range(struct addr
        pgoff_t end = end_byte >> PAGE_CACHE_SHIFT;
        struct pagevec pvec;
        int nr_pages;
 -      int ret = 0;
 +      int ret2, ret = 0;
  
        if (end_byte < start_byte)
 -              return 0;
 +              goto out;
  
        pagevec_init(&pvec, 0);
        while ((index <= end) &&
                pagevec_release(&pvec);
                cond_resched();
        }
 -
 -      /* Check for outstanding write errors */
 -      if (test_and_clear_bit(AS_ENOSPC, &mapping->flags))
 -              ret = -ENOSPC;
 -      if (test_and_clear_bit(AS_EIO, &mapping->flags))
 -              ret = -EIO;
 +out:
 +      ret2 = filemap_check_errors(mapping);
 +      if (!ret)
 +              ret = ret2;
  
        return ret;
  }
@@@ -350,8 -337,6 +350,8 @@@ int filemap_write_and_wait(struct addre
                        if (!err)
                                err = err2;
                }
 +      } else {
 +              err = filemap_check_errors(mapping);
        }
        return err;
  }
@@@ -383,8 -368,6 +383,8 @@@ int filemap_write_and_wait_range(struc
                        if (!err)
                                err = err2;
                }
 +      } else {
 +              err = filemap_check_errors(mapping);
        }
        return err;
  }
@@@ -481,7 -464,6 +481,7 @@@ int add_to_page_cache_locked(struct pag
                        mapping->nrpages++;
                        __inc_zone_page_state(page, NR_FILE_PAGES);
                        spin_unlock_irq(&mapping->tree_lock);
 +                      trace_mm_filemap_add_to_page_cache(page);
                } else {
                        page->mapping = NULL;
                        /* Leave page->index set: truncation relies upon it */
@@@ -2546,7 -2528,6 +2546,6 @@@ ssize_t generic_file_aio_write(struct k
  
        BUG_ON(iocb->ki_pos != pos);
  
-       sb_start_write(inode->i_sb);
        mutex_lock(&inode->i_mutex);
        ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
        mutex_unlock(&inode->i_mutex);
                if (err < 0 && ret > 0)
                        ret = err;
        }
-       sb_end_write(inode->i_sb);
        return ret;
  }
  EXPORT_SYMBOL(generic_file_aio_write);
diff --combined mm/vmalloc.c
index 72043d6c88c09c16b581c571cb6b79ee12a34b68,ef9bdf74227364b8a32b847df5b1f6968a781921..b12fd8612604f26bfca3006fd07bcbad27d73040
  #include <linux/pfn.h>
  #include <linux/kmemleak.h>
  #include <linux/atomic.h>
+ #include <linux/llist.h>
  #include <asm/uaccess.h>
  #include <asm/tlbflush.h>
  #include <asm/shmparam.h>
  
+ struct vfree_deferred {
+       struct llist_head list;
+       struct work_struct wq;
+ };
+ static DEFINE_PER_CPU(struct vfree_deferred, vfree_deferred);
+ static void __vunmap(const void *, int);
+ static void free_work(struct work_struct *w)
+ {
+       struct vfree_deferred *p = container_of(w, struct vfree_deferred, wq);
+       struct llist_node *llnode = llist_del_all(&p->list);
+       while (llnode) {
+               void *p = llnode;
+               llnode = llist_next(llnode);
+               __vunmap(p, 1);
+       }
+ }
  /*** Page table manipulation functions ***/
  
  static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end)
@@@ -249,9 -269,19 +269,9 @@@ EXPORT_SYMBOL(vmalloc_to_pfn)
  #define VM_LAZY_FREEING       0x02
  #define VM_VM_AREA    0x04
  
 -struct vmap_area {
 -      unsigned long va_start;
 -      unsigned long va_end;
 -      unsigned long flags;
 -      struct rb_node rb_node;         /* address sorted rbtree */
 -      struct list_head list;          /* address sorted list */
 -      struct list_head purge_list;    /* "lazy purge" list */
 -      struct vm_struct *vm;
 -      struct rcu_head rcu_head;
 -};
 -
  static DEFINE_SPINLOCK(vmap_area_lock);
 -static LIST_HEAD(vmap_area_list);
 +/* Export for kexec only */
 +LIST_HEAD(vmap_area_list);
  static struct rb_root vmap_area_root = RB_ROOT;
  
  /* The vmap cache globals are protected by vmap_area_lock */
@@@ -303,7 -333,7 +323,7 @@@ static void __insert_vmap_area(struct v
        rb_link_node(&va->rb_node, parent, p);
        rb_insert_color(&va->rb_node, &vmap_area_root);
  
 -      /* address-sort this list so it is usable like the vmlist */
 +      /* address-sort this list */
        tmp = rb_prev(&va->rb_node);
        if (tmp) {
                struct vmap_area *prev;
@@@ -1115,7 -1145,6 +1135,7 @@@ void *vm_map_ram(struct page **pages, u
  }
  EXPORT_SYMBOL(vm_map_ram);
  
 +static struct vm_struct *vmlist __initdata;
  /**
   * vm_area_add_early - add vmap area early during boot
   * @vm: vm_struct to add
@@@ -1175,10 -1204,14 +1195,14 @@@ void __init vmalloc_init(void
  
        for_each_possible_cpu(i) {
                struct vmap_block_queue *vbq;
+               struct vfree_deferred *p;
  
                vbq = &per_cpu(vmap_block_queue, i);
                spin_lock_init(&vbq->lock);
                INIT_LIST_HEAD(&vbq->free);
+               p = &per_cpu(vfree_deferred, i);
+               init_llist_head(&p->list);
+               INIT_WORK(&p->wq, free_work);
        }
  
        /* Import existing vmlist entries. */
@@@ -1274,35 -1307,41 +1298,35 @@@ int map_vm_area(struct vm_struct *area
  }
  EXPORT_SYMBOL_GPL(map_vm_area);
  
 -/*** Old vmalloc interfaces ***/
 -DEFINE_RWLOCK(vmlist_lock);
 -struct vm_struct *vmlist;
 -
  static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
                              unsigned long flags, const void *caller)
  {
 +      spin_lock(&vmap_area_lock);
        vm->flags = flags;
        vm->addr = (void *)va->va_start;
        vm->size = va->va_end - va->va_start;
        vm->caller = caller;
        va->vm = vm;
        va->flags |= VM_VM_AREA;
 +      spin_unlock(&vmap_area_lock);
  }
  
 -static void insert_vmalloc_vmlist(struct vm_struct *vm)
 +static void clear_vm_unlist(struct vm_struct *vm)
  {
 -      struct vm_struct *tmp, **p;
 -
 +      /*
 +       * Before removing VM_UNLIST,
 +       * we should make sure that vm has proper values.
 +       * Pair with smp_rmb() in show_numa_info().
 +       */
 +      smp_wmb();
        vm->flags &= ~VM_UNLIST;
 -      write_lock(&vmlist_lock);
 -      for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) {
 -              if (tmp->addr >= vm->addr)
 -                      break;
 -      }
 -      vm->next = *p;
 -      *p = vm;
 -      write_unlock(&vmlist_lock);
  }
  
  static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
                              unsigned long flags, const void *caller)
  {
        setup_vmalloc_vm(vm, va, flags, caller);
 -      insert_vmalloc_vmlist(vm);
 +      clear_vm_unlist(vm);
  }
  
  static struct vm_struct *__get_vm_area_node(unsigned long size,
  
        /*
         * When this function is called from __vmalloc_node_range,
 -       * we do not add vm_struct to vmlist here to avoid
 -       * accessing uninitialized members of vm_struct such as
 -       * pages and nr_pages fields. They will be set later.
 -       * To distinguish it from others, we use a VM_UNLIST flag.
 +       * we add VM_UNLIST flag to avoid accessing uninitialized
 +       * members of vm_struct such as pages and nr_pages fields.
 +       * They will be set later.
         */
        if (flags & VM_UNLIST)
                setup_vmalloc_vm(area, va, flags, caller);
@@@ -1431,10 -1471,19 +1455,10 @@@ struct vm_struct *remove_vm_area(const 
        if (va && va->flags & VM_VM_AREA) {
                struct vm_struct *vm = va->vm;
  
 -              if (!(vm->flags & VM_UNLIST)) {
 -                      struct vm_struct *tmp, **p;
 -                      /*
 -                       * remove from list and disallow access to
 -                       * this vm_struct before unmap. (address range
 -                       * confliction is maintained by vmap.)
 -                       */
 -                      write_lock(&vmlist_lock);
 -                      for (p = &vmlist; (tmp = *p) != vm; p = &tmp->next)
 -                              ;
 -                      *p = tmp->next;
 -                      write_unlock(&vmlist_lock);
 -              }
 +              spin_lock(&vmap_area_lock);
 +              va->vm = NULL;
 +              va->flags &= ~VM_VM_AREA;
 +              spin_unlock(&vmap_area_lock);
  
                vmap_debug_free_range(va->va_start, va->va_end);
                free_unmap_vmap_area(va);
@@@ -1486,7 -1535,7 +1510,7 @@@ static void __vunmap(const void *addr, 
        kfree(area);
        return;
  }
+  
  /**
   *    vfree  -  release memory allocated by vmalloc()
   *    @addr:          memory base address
   *    obtained from vmalloc(), vmalloc_32() or __vmalloc(). If @addr is
   *    NULL, no operation is performed.
   *
-  *    Must not be called in interrupt context.
+  *    Must not be called in NMI context (strictly speaking, only if we don't
+  *    have CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG, but making the calling
+  *    conventions for vfree() arch-depenedent would be a really bad idea)
+  *    
   */
  void vfree(const void *addr)
  {
-       BUG_ON(in_interrupt());
+       BUG_ON(in_nmi());
  
        kmemleak_free(addr);
  
-       __vunmap(addr, 1);
+       if (!addr)
+               return;
+       if (unlikely(in_interrupt())) {
+               struct vfree_deferred *p = &__get_cpu_var(vfree_deferred);
+               llist_add((struct llist_node *)addr, &p->list);
+               schedule_work(&p->wq);
+       } else
+               __vunmap(addr, 1);
  }
  EXPORT_SYMBOL(vfree);
  
@@@ -1520,7 -1579,8 +1554,8 @@@ void vunmap(const void *addr
  {
        BUG_ON(in_interrupt());
        might_sleep();
-       __vunmap(addr, 0);
+       if (addr)
+               __vunmap(addr, 0);
  }
  EXPORT_SYMBOL(vunmap);
  
@@@ -1655,11 -1715,10 +1690,11 @@@ void *__vmalloc_node_range(unsigned lon
                return NULL;
  
        /*
 -       * In this function, newly allocated vm_struct is not added
 -       * to vmlist at __get_vm_area_node(). so, it is added here.
 +       * In this function, newly allocated vm_struct has VM_UNLIST flag.
 +       * It means that vm_struct is not fully initialized.
 +       * Now, it is fully initialized, so remove this flag here.
         */
 -      insert_vmalloc_vmlist(area);
 +      clear_vm_unlist(area);
  
        /*
         * A ref_count = 3 is needed because the vm_struct and vmap_area
@@@ -1981,8 -2040,7 +2016,8 @@@ static int aligned_vwrite(char *buf, ch
  
  long vread(char *buf, char *addr, unsigned long count)
  {
 -      struct vm_struct *tmp;
 +      struct vmap_area *va;
 +      struct vm_struct *vm;
        char *vaddr, *buf_start = buf;
        unsigned long buflen = count;
        unsigned long n;
        if ((unsigned long) addr + count < count)
                count = -(unsigned long) addr;
  
 -      read_lock(&vmlist_lock);
 -      for (tmp = vmlist; count && tmp; tmp = tmp->next) {
 -              vaddr = (char *) tmp->addr;
 -              if (addr >= vaddr + tmp->size - PAGE_SIZE)
 +      spin_lock(&vmap_area_lock);
 +      list_for_each_entry(va, &vmap_area_list, list) {
 +              if (!count)
 +                      break;
 +
 +              if (!(va->flags & VM_VM_AREA))
 +                      continue;
 +
 +              vm = va->vm;
 +              vaddr = (char *) vm->addr;
 +              if (addr >= vaddr + vm->size - PAGE_SIZE)
                        continue;
                while (addr < vaddr) {
                        if (count == 0)
                        addr++;
                        count--;
                }
 -              n = vaddr + tmp->size - PAGE_SIZE - addr;
 +              n = vaddr + vm->size - PAGE_SIZE - addr;
                if (n > count)
                        n = count;
 -              if (!(tmp->flags & VM_IOREMAP))
 +              if (!(vm->flags & VM_IOREMAP))
                        aligned_vread(buf, addr, n);
                else /* IOREMAP area is treated as memory hole */
                        memset(buf, 0, n);
                count -= n;
        }
  finished:
 -      read_unlock(&vmlist_lock);
 +      spin_unlock(&vmap_area_lock);
  
        if (buf == buf_start)
                return 0;
  
  long vwrite(char *buf, char *addr, unsigned long count)
  {
 -      struct vm_struct *tmp;
 +      struct vmap_area *va;
 +      struct vm_struct *vm;
        char *vaddr;
        unsigned long n, buflen;
        int copied = 0;
                count = -(unsigned long) addr;
        buflen = count;
  
 -      read_lock(&vmlist_lock);
 -      for (tmp = vmlist; count && tmp; tmp = tmp->next) {
 -              vaddr = (char *) tmp->addr;
 -              if (addr >= vaddr + tmp->size - PAGE_SIZE)
 +      spin_lock(&vmap_area_lock);
 +      list_for_each_entry(va, &vmap_area_list, list) {
 +              if (!count)
 +                      break;
 +
 +              if (!(va->flags & VM_VM_AREA))
 +                      continue;
 +
 +              vm = va->vm;
 +              vaddr = (char *) vm->addr;
 +              if (addr >= vaddr + vm->size - PAGE_SIZE)
                        continue;
                while (addr < vaddr) {
                        if (count == 0)
                        addr++;
                        count--;
                }
 -              n = vaddr + tmp->size - PAGE_SIZE - addr;
 +              n = vaddr + vm->size - PAGE_SIZE - addr;
                if (n > count)
                        n = count;
 -              if (!(tmp->flags & VM_IOREMAP)) {
 +              if (!(vm->flags & VM_IOREMAP)) {
                        aligned_vwrite(buf, addr, n);
                        copied++;
                }
                count -= n;
        }
  finished:
 -      read_unlock(&vmlist_lock);
 +      spin_unlock(&vmap_area_lock);
        if (!copied)
                return 0;
        return buflen;
@@@ -2511,19 -2554,19 +2546,19 @@@ void pcpu_free_vm_areas(struct vm_struc
  
  #ifdef CONFIG_PROC_FS
  static void *s_start(struct seq_file *m, loff_t *pos)
 -      __acquires(&vmlist_lock)
 +      __acquires(&vmap_area_lock)
  {
        loff_t n = *pos;
 -      struct vm_struct *v;
 +      struct vmap_area *va;
  
 -      read_lock(&vmlist_lock);
 -      v = vmlist;
 -      while (n > 0 && v) {
 +      spin_lock(&vmap_area_lock);
 +      va = list_entry((&vmap_area_list)->next, typeof(*va), list);
 +      while (n > 0 && &va->list != &vmap_area_list) {
                n--;
 -              v = v->next;
 +              va = list_entry(va->list.next, typeof(*va), list);
        }
 -      if (!n)
 -              return v;
 +      if (!n && &va->list != &vmap_area_list)
 +              return va;
  
        return NULL;
  
  
  static void *s_next(struct seq_file *m, void *p, loff_t *pos)
  {
 -      struct vm_struct *v = p;
 +      struct vmap_area *va = p, *next;
  
        ++*pos;
 -      return v->next;
 +      next = list_entry(va->list.next, typeof(*va), list);
 +      if (&next->list != &vmap_area_list)
 +              return next;
 +
 +      return NULL;
  }
  
  static void s_stop(struct seq_file *m, void *p)
 -      __releases(&vmlist_lock)
 +      __releases(&vmap_area_lock)
  {
 -      read_unlock(&vmlist_lock);
 +      spin_unlock(&vmap_area_lock);
  }
  
  static void show_numa_info(struct seq_file *m, struct vm_struct *v)
                if (!counters)
                        return;
  
 +              /* Pair with smp_wmb() in clear_vm_unlist() */
 +              smp_rmb();
 +              if (v->flags & VM_UNLIST)
 +                      return;
 +
                memset(counters, 0, nr_node_ids * sizeof(unsigned int));
  
                for (nr = 0; nr < v->nr_pages; nr++)
  
  static int s_show(struct seq_file *m, void *p)
  {
 -      struct vm_struct *v = p;
 +      struct vmap_area *va = p;
 +      struct vm_struct *v;
 +
 +      if (va->flags & (VM_LAZY_FREE | VM_LAZY_FREEING))
 +              return 0;
 +
 +      if (!(va->flags & VM_VM_AREA)) {
 +              seq_printf(m, "0x%pK-0x%pK %7ld vm_map_ram\n",
 +                      (void *)va->va_start, (void *)va->va_end,
 +                                      va->va_end - va->va_start);
 +              return 0;
 +      }
 +
 +      v = va->vm;
  
        seq_printf(m, "0x%pK-0x%pK %7ld",
                v->addr, v->addr + v->size, v->size);
@@@ -2659,53 -2680,5 +2694,53 @@@ static int __init proc_vmalloc_init(voi
        return 0;
  }
  module_init(proc_vmalloc_init);
 +
 +void get_vmalloc_info(struct vmalloc_info *vmi)
 +{
 +      struct vmap_area *va;
 +      unsigned long free_area_size;
 +      unsigned long prev_end;
 +
 +      vmi->used = 0;
 +      vmi->largest_chunk = 0;
 +
 +      prev_end = VMALLOC_START;
 +
 +      spin_lock(&vmap_area_lock);
 +
 +      if (list_empty(&vmap_area_list)) {
 +              vmi->largest_chunk = VMALLOC_TOTAL;
 +              goto out;
 +      }
 +
 +      list_for_each_entry(va, &vmap_area_list, list) {
 +              unsigned long addr = va->va_start;
 +
 +              /*
 +               * Some archs keep another range for modules in vmalloc space
 +               */
 +              if (addr < VMALLOC_START)
 +                      continue;
 +              if (addr >= VMALLOC_END)
 +                      break;
 +
 +              if (va->flags & (VM_LAZY_FREE | VM_LAZY_FREEING))
 +                      continue;
 +
 +              vmi->used += (va->va_end - va->va_start);
 +
 +              free_area_size = addr - prev_end;
 +              if (vmi->largest_chunk < free_area_size)
 +                      vmi->largest_chunk = free_area_size;
 +
 +              prev_end = va->va_end;
 +      }
 +
 +      if (VMALLOC_END - prev_end > vmi->largest_chunk)
 +              vmi->largest_chunk = VMALLOC_END - prev_end;
 +
 +out:
 +      spin_unlock(&vmap_area_lock);
 +}
  #endif
  
index e5338f787d68e18c6b0db191094eeed61425e21d,438a8c56938e7f8162055f0c3310855838be993e..9096137c889c4857507fcb60828b8d7ad581f424
@@@ -92,14 -92,23 +92,14 @@@ int bt_sock_register(int proto, const s
  }
  EXPORT_SYMBOL(bt_sock_register);
  
 -int bt_sock_unregister(int proto)
 +void bt_sock_unregister(int proto)
  {
 -      int err = 0;
 -
        if (proto < 0 || proto >= BT_MAX_PROTO)
 -              return -EINVAL;
 +              return;
  
        write_lock(&bt_proto_lock);
 -
 -      if (!bt_proto[proto])
 -              err = -ENOENT;
 -      else
 -              bt_proto[proto] = NULL;
 -
 +      bt_proto[proto] = NULL;
        write_unlock(&bt_proto_lock);
 -
 -      return err;
  }
  EXPORT_SYMBOL(bt_sock_unregister);
  
@@@ -221,8 -230,6 +221,8 @@@ int bt_sock_recvmsg(struct kiocb *iocb
        if (flags & (MSG_OOB))
                return -EOPNOTSUPP;
  
 +      msg->msg_namelen = 0;
 +
        skb = skb_recv_datagram(sk, flags, noblock, &err);
        if (!skb) {
                if (sk->sk_shutdown & RCV_SHUTDOWN)
                return err;
        }
  
 -      msg->msg_namelen = 0;
 -
        copied = skb->len;
        if (len < copied) {
                msg->msg_flags |= MSG_TRUNC;
@@@ -413,8 -422,7 +413,8 @@@ unsigned int bt_sock_poll(struct file *
                return bt_accept_poll(sk);
  
        if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
 -              mask |= POLLERR;
 +              mask |= POLLERR |
 +                      (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0);
  
        if (sk->sk_shutdown & RCV_SHUTDOWN)
                mask |= POLLRDHUP | POLLIN | POLLRDNORM;
@@@ -609,7 -617,7 +609,7 @@@ static int bt_seq_open(struct inode *in
        struct bt_sock_list *sk_list;
        struct bt_seq_state *s;
  
-       sk_list = PDE(inode)->data;
+       sk_list = PDE_DATA(inode);
        s = __seq_open_private(file, &bt_seq_ops,
                               sizeof(struct bt_seq_state));
        if (!s)
        return 0;
  }
  
- int bt_procfs_init(struct module* module, struct net *net, const char *name,
+ static const struct file_operations bt_fops = {
+       .open = bt_seq_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release_private
+ };
+ int bt_procfs_init(struct net *net, const char *name,
                   struct bt_sock_list* sk_list,
                   int (* seq_show)(struct seq_file *, void *))
  {
-       struct proc_dir_entry * pde;
        sk_list->custom_seq_show = seq_show;
  
-       sk_list->fops.owner     = module;
-       sk_list->fops.open      = bt_seq_open;
-       sk_list->fops.read      = seq_read;
-       sk_list->fops.llseek    = seq_lseek;
-       sk_list->fops.release   = seq_release_private;
-       pde = proc_create(name, 0, net->proc_net, &sk_list->fops);
-       if (!pde)
+       if (!proc_create_data(name, 0, net->proc_net, &bt_fops, sk_list))
                return -ENOMEM;
-       pde->data = sk_list;
        return 0;
  }
  
@@@ -647,7 -650,7 +642,7 @@@ void bt_procfs_cleanup(struct net *net
        remove_proc_entry(name, net->proc_net);
  }
  #else
- int bt_procfs_init(struct module* module, struct net *net, const char *name,
+ int bt_procfs_init(struct net *net, const char *name,
                   struct bt_sock_list* sk_list,
                   int (* seq_show)(struct seq_file *, void *))
  {
index 5b1c04e2882188c73031415144a8130995b27a3d,d4686fb7e95747bcc219331b1323022e28328c3d..5f051290dabab83ec76422dbb7cd44732b22eb6e
@@@ -234,7 -234,7 +234,7 @@@ int __init bnep_sock_init(void
                goto error;
        }
  
-       err = bt_procfs_init(THIS_MODULE, &init_net, "bnep", &bnep_sk_list, NULL);
+       err = bt_procfs_init(&init_net, "bnep", &bnep_sk_list, NULL);
        if (err < 0) {
                BT_ERR("Failed to create BNEP proc file");
                bt_sock_unregister(BTPROTO_BNEP);
@@@ -253,6 -253,8 +253,6 @@@ error
  void __exit bnep_sock_cleanup(void)
  {
        bt_procfs_cleanup(&init_net, "bnep");
 -      if (bt_sock_unregister(BTPROTO_BNEP) < 0)
 -              BT_ERR("Can't unregister BNEP socket");
 -
 +      bt_sock_unregister(BTPROTO_BNEP);
        proto_unregister(&bnep_proto);
  }
index 58d9edebab4b02d6cfa242d5f450fc6a2a4060cb,03f26bf85d74f187d1d2ba5fb3e0766a27d22662..d82787d417bdc242483de3ab4bac4bc7a91eca62
@@@ -245,7 -245,7 +245,7 @@@ int cmtp_init_sockets(void
                goto error;
        }
  
-       err = bt_procfs_init(THIS_MODULE, &init_net, "cmtp", &cmtp_sk_list, NULL);
+       err = bt_procfs_init(&init_net, "cmtp", &cmtp_sk_list, NULL);
        if (err < 0) {
                BT_ERR("Failed to create CMTP proc file");
                bt_sock_unregister(BTPROTO_HIDP);
@@@ -264,6 -264,8 +264,6 @@@ error
  void cmtp_cleanup_sockets(void)
  {
        bt_procfs_cleanup(&init_net, "cmtp");
 -      if (bt_sock_unregister(BTPROTO_CMTP) < 0)
 -              BT_ERR("Can't unregister CMTP socket");
 -
 +      bt_sock_unregister(BTPROTO_CMTP);
        proto_unregister(&cmtp_proto);
  }
diff --combined net/bluetooth/hci_sock.c
index aa4354fca77c76b2282f81d86114c2698088d273,6ad23951c13359ed01c31b59669115909a155102..9bd7d959e384c74504a06ed27e0eef0d61dbf70e
@@@ -854,11 -854,6 +854,11 @@@ static int hci_sock_sendmsg(struct kioc
                        skb_queue_tail(&hdev->raw_q, skb);
                        queue_work(hdev->workqueue, &hdev->tx_work);
                } else {
 +                      /* Stand-alone HCI commands must be flaged as
 +                       * single-command requests.
 +                       */
 +                      bt_cb(skb)->req.start = true;
 +
                        skb_queue_tail(&hdev->cmd_q, skb);
                        queue_work(hdev->workqueue, &hdev->cmd_work);
                }
@@@ -1107,7 -1102,7 +1107,7 @@@ int __init hci_sock_init(void
                goto error;
        }
  
-       err = bt_procfs_init(THIS_MODULE, &init_net, "hci", &hci_sk_list, NULL);
+       err = bt_procfs_init(&init_net, "hci", &hci_sk_list, NULL);
        if (err < 0) {
                BT_ERR("Failed to create HCI proc file");
                bt_sock_unregister(BTPROTO_HCI);
@@@ -1126,6 -1121,8 +1126,6 @@@ error
  void hci_sock_cleanup(void)
  {
        bt_procfs_cleanup(&init_net, "hci");
 -      if (bt_sock_unregister(BTPROTO_HCI) < 0)
 -              BT_ERR("HCI socket unregistration failed");
 -
 +      bt_sock_unregister(BTPROTO_HCI);
        proto_unregister(&hci_sk_proto);
  }
index 2f4cbb0865ca883649e3ed4787b3e1ddbbf1da16,e7e04d4b9d99b8b6f4c23f89080e80693f806bbe..cb3fdde1968a0fabafe038382dbdf9dacd3e331f
@@@ -77,12 -77,21 +77,12 @@@ static int hidp_sock_ioctl(struct socke
                        return err;
                }
  
 -              if (csock->sk->sk_state != BT_CONNECTED ||
 -                              isock->sk->sk_state != BT_CONNECTED) {
 -                      sockfd_put(csock);
 -                      sockfd_put(isock);
 -                      return -EBADFD;
 -              }
 +              err = hidp_connection_add(&ca, csock, isock);
 +              if (!err && copy_to_user(argp, &ca, sizeof(ca)))
 +                      err = -EFAULT;
  
 -              err = hidp_add_connection(&ca, csock, isock);
 -              if (!err) {
 -                      if (copy_to_user(argp, &ca, sizeof(ca)))
 -                              err = -EFAULT;
 -              } else {
 -                      sockfd_put(csock);
 -                      sockfd_put(isock);
 -              }
 +              sockfd_put(csock);
 +              sockfd_put(isock);
  
                return err;
  
                if (copy_from_user(&cd, argp, sizeof(cd)))
                        return -EFAULT;
  
 -              return hidp_del_connection(&cd);
 +              return hidp_connection_del(&cd);
  
        case HIDPGETCONNLIST:
                if (copy_from_user(&cl, argp, sizeof(cl)))
@@@ -275,7 -284,7 +275,7 @@@ int __init hidp_init_sockets(void
                goto error;
        }
  
-       err = bt_procfs_init(THIS_MODULE, &init_net, "hidp", &hidp_sk_list, NULL);
+       err = bt_procfs_init(&init_net, "hidp", &hidp_sk_list, NULL);
        if (err < 0) {
                BT_ERR("Failed to create HIDP proc file");
                bt_sock_unregister(BTPROTO_HIDP);
        return 0;
  
  error:
 -      BT_ERR("Can't register HIDP socket");
        proto_unregister(&hidp_proto);
        return err;
  }
  void __exit hidp_cleanup_sockets(void)
  {
        bt_procfs_cleanup(&init_net, "hidp");
 -      if (bt_sock_unregister(BTPROTO_HIDP) < 0)
 -              BT_ERR("Can't unregister HIDP socket");
 -
 +      bt_sock_unregister(BTPROTO_HIDP);
        proto_unregister(&hidp_proto);
  }
index 141e7b058b7e897e71114a01864942361f31b322,fe15960c02c35e05b807b03475b08fae0ac3a4e9..36fed40c162cff5361c9dbdf9cfd5f313e47743a
@@@ -43,12 -43,6 +43,12 @@@ static void l2cap_sock_init(struct soc
  static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
                                     int proto, gfp_t prio);
  
 +bool l2cap_is_socket(struct socket *sock)
 +{
 +      return sock && sock->ops == &l2cap_sock_ops;
 +}
 +EXPORT_SYMBOL(l2cap_is_socket);
 +
  static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
  {
        struct sock *sk = sock->sk;
@@@ -1298,7 -1292,7 +1298,7 @@@ int __init l2cap_init_sockets(void
                goto error;
        }
  
-       err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list,
+       err = bt_procfs_init(&init_net, "l2cap", &l2cap_sk_list,
                             NULL);
        if (err < 0) {
                BT_ERR("Failed to create L2CAP proc file");
@@@ -1318,6 -1312,8 +1318,6 @@@ error
  void l2cap_cleanup_sockets(void)
  {
        bt_procfs_cleanup(&init_net, "l2cap");
 -      if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
 -              BT_ERR("L2CAP socket unregistration failed");
 -
 +      bt_sock_unregister(BTPROTO_L2CAP);
        proto_unregister(&l2cap_proto);
  }
index a8638b58c4bf28e13298fb66e50edfca08741d2f,fda3bb4019a35e625c0d219a3c9418560058b340..30b3721dc6d77d96be4bdb412ee90c49b8976dc9
@@@ -608,7 -608,6 +608,7 @@@ static int rfcomm_sock_recvmsg(struct k
  
        if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
                rfcomm_dlc_accept(d);
 +              msg->msg_namelen = 0;
                return 0;
        }
  
@@@ -1037,7 -1036,7 +1037,7 @@@ int __init rfcomm_init_sockets(void
                goto error;
        }
  
-       err = bt_procfs_init(THIS_MODULE, &init_net, "rfcomm", &rfcomm_sk_list, NULL);
+       err = bt_procfs_init(&init_net, "rfcomm", &rfcomm_sk_list, NULL);
        if (err < 0) {
                BT_ERR("Failed to create RFCOMM proc file");
                bt_sock_unregister(BTPROTO_RFCOMM);
@@@ -1066,7 -1065,8 +1066,7 @@@ void __exit rfcomm_cleanup_sockets(void
  
        debugfs_remove(rfcomm_sock_debugfs);
  
 -      if (bt_sock_unregister(BTPROTO_RFCOMM) < 0)
 -              BT_ERR("RFCOMM socket layer unregistration failed");
 +      bt_sock_unregister(BTPROTO_RFCOMM);
  
        proto_unregister(&rfcomm_proto);
  }
diff --combined net/bluetooth/sco.c
index 373d81e6e8f0af0a6cc33bbdf0d7c6e905726db5,7e8dbaf8bc1064638c000a93de618b8a831fe6df..e7bd4eea575cff782401430147c9cdcc1a1ad6b0
@@@ -83,7 -83,7 +83,7 @@@ static struct sco_conn *sco_conn_add(st
        if (conn)
                return conn;
  
 -      conn = kzalloc(sizeof(struct sco_conn), GFP_ATOMIC);
 +      conn = kzalloc(sizeof(struct sco_conn), GFP_KERNEL);
        if (!conn)
                return NULL;
  
@@@ -185,7 -185,7 +185,7 @@@ static int sco_connect(struct sock *sk
  
        conn = sco_conn_add(hcon);
        if (!conn) {
 -              hci_conn_put(hcon);
 +              hci_conn_drop(hcon);
                err = -ENOMEM;
                goto done;
        }
@@@ -353,7 -353,7 +353,7 @@@ static void __sco_sock_close(struct soc
                if (sco_pi(sk)->conn->hcon) {
                        sk->sk_state = BT_DISCONN;
                        sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
 -                      hci_conn_put(sco_pi(sk)->conn->hcon);
 +                      hci_conn_drop(sco_pi(sk)->conn->hcon);
                        sco_pi(sk)->conn->hcon = NULL;
                } else
                        sco_chan_del(sk, ECONNRESET);
@@@ -481,7 -481,8 +481,7 @@@ static int sco_sock_connect(struct sock
  {
        struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
        struct sock *sk = sock->sk;
 -      int err = 0;
 -
 +      int err;
  
        BT_DBG("sk %p", sk);
  
@@@ -652,42 -653,6 +652,42 @@@ static int sco_sock_sendmsg(struct kioc
        return err;
  }
  
 +static void sco_conn_defer_accept(struct hci_conn *conn, int mask)
 +{
 +      struct hci_dev *hdev = conn->hdev;
 +
 +      BT_DBG("conn %p", conn);
 +
 +      conn->state = BT_CONFIG;
 +
 +      if (!lmp_esco_capable(hdev)) {
 +              struct hci_cp_accept_conn_req cp;
 +
 +              bacpy(&cp.bdaddr, &conn->dst);
 +
 +              if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
 +                      cp.role = 0x00; /* Become master */
 +              else
 +                      cp.role = 0x01; /* Remain slave */
 +
 +              hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
 +      } else {
 +              struct hci_cp_accept_sync_conn_req cp;
 +
 +              bacpy(&cp.bdaddr, &conn->dst);
 +              cp.pkt_type = cpu_to_le16(conn->pkt_type);
 +
 +              cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
 +              cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
 +              cp.max_latency    = __constant_cpu_to_le16(0xffff);
 +              cp.content_format = cpu_to_le16(hdev->voice_setting);
 +              cp.retrans_effort = 0xff;
 +
 +              hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
 +                           sizeof(cp), &cp);
 +      }
 +}
 +
  static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                            struct msghdr *msg, size_t len, int flags)
  {
  
        if (sk->sk_state == BT_CONNECT2 &&
            test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
 -              hci_conn_accept(pi->conn->hcon, 0);
 +              sco_conn_defer_accept(pi->conn->hcon, 0);
                sk->sk_state = BT_CONFIG;
 +              msg->msg_namelen = 0;
  
                release_sock(sk);
                return 0;
@@@ -918,7 -882,7 +918,7 @@@ static void sco_chan_del(struct sock *s
                sco_conn_unlock(conn);
  
                if (conn->hcon)
 -                      hci_conn_put(conn->hcon);
 +                      hci_conn_drop(conn->hcon);
        }
  
        sk->sk_state = BT_CLOSED;
@@@ -1119,7 -1083,7 +1119,7 @@@ int __init sco_init(void
                goto error;
        }
  
-       err = bt_procfs_init(THIS_MODULE, &init_net, "sco", &sco_sk_list, NULL);
+       err = bt_procfs_init(&init_net, "sco", &sco_sk_list, NULL);
        if (err < 0) {
                BT_ERR("Failed to create SCO proc file");
                bt_sock_unregister(BTPROTO_SCO);
@@@ -1148,7 -1112,8 +1148,7 @@@ void __exit sco_exit(void
  
        debugfs_remove(sco_debugfs);
  
 -      if (bt_sock_unregister(BTPROTO_SCO) < 0)
 -              BT_ERR("SCO socket unregistration failed");
 +      bt_sock_unregister(BTPROTO_SCO);
  
        proto_unregister(&sco_proto);
  }
diff --combined net/core/neighbour.c
index 89a3a07d85fbd3318ff03c255a51cf0aaeacbe7b,537301a2c31fa1c1045c57ddef7e4dcf76eaa96f..5c56b217b999d114ea7954a9e6060a77d906ceff
  #include <linux/string.h>
  #include <linux/log2.h>
  
 +#define DEBUG
  #define NEIGH_DEBUG 1
 -
 -#define NEIGH_PRINTK(x...) printk(x)
 -#define NEIGH_NOPRINTK(x...) do { ; } while(0)
 -#define NEIGH_PRINTK1 NEIGH_NOPRINTK
 -#define NEIGH_PRINTK2 NEIGH_NOPRINTK
 -
 -#if NEIGH_DEBUG >= 1
 -#undef NEIGH_PRINTK1
 -#define NEIGH_PRINTK1 NEIGH_PRINTK
 -#endif
 -#if NEIGH_DEBUG >= 2
 -#undef NEIGH_PRINTK2
 -#define NEIGH_PRINTK2 NEIGH_PRINTK
 -#endif
 +#define neigh_dbg(level, fmt, ...)            \
 +do {                                          \
 +      if (level <= NEIGH_DEBUG)               \
 +              pr_debug(fmt, ##__VA_ARGS__);   \
 +} while (0)
  
  #define PNEIGH_HASHMASK               0xF
  
@@@ -238,7 -246,7 +238,7 @@@ static void neigh_flush_dev(struct neig
                                        n->nud_state = NUD_NOARP;
                                else
                                        n->nud_state = NUD_NONE;
 -                              NEIGH_PRINTK2("neigh %p is stray.\n", n);
 +                              neigh_dbg(2, "neigh %p is stray\n", n);
                        }
                        write_unlock(&n->lock);
                        neigh_cleanup_and_release(n);
@@@ -534,7 -542,7 +534,7 @@@ struct neighbour *__neigh_create(struc
                                                     lockdep_is_held(&tbl->lock)));
        rcu_assign_pointer(nht->hash_buckets[hash_val], n);
        write_unlock_bh(&tbl->lock);
 -      NEIGH_PRINTK2("neigh %p is created.\n", n);
 +      neigh_dbg(2, "neigh %p is created\n", n);
        rc = n;
  out:
        return rc;
@@@ -717,7 -725,7 +717,7 @@@ void neigh_destroy(struct neighbour *ne
        dev_put(dev);
        neigh_parms_put(neigh->parms);
  
 -      NEIGH_PRINTK2("neigh %p is destroyed.\n", neigh);
 +      neigh_dbg(2, "neigh %p is destroyed\n", neigh);
  
        atomic_dec(&neigh->tbl->entries);
        kfree_rcu(neigh, rcu);
@@@ -731,7 -739,7 +731,7 @@@ EXPORT_SYMBOL(neigh_destroy)
   */
  static void neigh_suspect(struct neighbour *neigh)
  {
 -      NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
 +      neigh_dbg(2, "neigh %p is suspected\n", neigh);
  
        neigh->output = neigh->ops->output;
  }
   */
  static void neigh_connect(struct neighbour *neigh)
  {
 -      NEIGH_PRINTK2("neigh %p is connected.\n", neigh);
 +      neigh_dbg(2, "neigh %p is connected\n", neigh);
  
        neigh->output = neigh->ops->connected_output;
  }
@@@ -844,7 -852,7 +844,7 @@@ static void neigh_invalidate(struct nei
        struct sk_buff *skb;
  
        NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
 -      NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
 +      neigh_dbg(2, "neigh %p is failed\n", neigh);
        neigh->updated = jiffies;
  
        /* It is very thin place. report_unreachable is very complicated
@@@ -896,17 -904,17 +896,17 @@@ static void neigh_timer_handler(unsigne
        if (state & NUD_REACHABLE) {
                if (time_before_eq(now,
                                   neigh->confirmed + neigh->parms->reachable_time)) {
 -                      NEIGH_PRINTK2("neigh %p is still alive.\n", neigh);
 +                      neigh_dbg(2, "neigh %p is still alive\n", neigh);
                        next = neigh->confirmed + neigh->parms->reachable_time;
                } else if (time_before_eq(now,
                                          neigh->used + neigh->parms->delay_probe_time)) {
 -                      NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
 +                      neigh_dbg(2, "neigh %p is delayed\n", neigh);
                        neigh->nud_state = NUD_DELAY;
                        neigh->updated = jiffies;
                        neigh_suspect(neigh);
                        next = now + neigh->parms->delay_probe_time;
                } else {
 -                      NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
 +                      neigh_dbg(2, "neigh %p is suspected\n", neigh);
                        neigh->nud_state = NUD_STALE;
                        neigh->updated = jiffies;
                        neigh_suspect(neigh);
        } else if (state & NUD_DELAY) {
                if (time_before_eq(now,
                                   neigh->confirmed + neigh->parms->delay_probe_time)) {
 -                      NEIGH_PRINTK2("neigh %p is now reachable.\n", neigh);
 +                      neigh_dbg(2, "neigh %p is now reachable\n", neigh);
                        neigh->nud_state = NUD_REACHABLE;
                        neigh->updated = jiffies;
                        neigh_connect(neigh);
                        notify = 1;
                        next = neigh->confirmed + neigh->parms->reachable_time;
                } else {
 -                      NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
 +                      neigh_dbg(2, "neigh %p is probed\n", neigh);
                        neigh->nud_state = NUD_PROBE;
                        neigh->updated = jiffies;
                        atomic_set(&neigh->probes, 0);
@@@ -989,7 -997,7 +989,7 @@@ int __neigh_event_send(struct neighbou
                        return 1;
                }
        } else if (neigh->nud_state & NUD_STALE) {
 -              NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
 +              neigh_dbg(2, "neigh %p is delayed\n", neigh);
                neigh->nud_state = NUD_DELAY;
                neigh->updated = jiffies;
                neigh_add_timer(neigh,
@@@ -1312,7 -1320,8 +1312,7 @@@ int neigh_resolve_output(struct neighbo
  out:
        return rc;
  discard:
 -      NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n",
 -                    dst, neigh);
 +      neigh_dbg(1, "%s: dst=%p neigh=%p\n", __func__, dst, neigh);
  out_kfree_skb:
        rc = -EINVAL;
        kfree_skb(skb);
@@@ -1489,7 -1498,7 +1489,7 @@@ void neigh_parms_release(struct neigh_t
                }
        }
        write_unlock_bh(&tbl->lock);
 -      NEIGH_PRINTK1("neigh_parms_release: not found\n");
 +      neigh_dbg(1, "%s: not found\n", __func__);
  }
  EXPORT_SYMBOL(neigh_parms_release);
  
@@@ -1604,7 -1613,7 +1604,7 @@@ int neigh_table_clear(struct neigh_tabl
  }
  EXPORT_SYMBOL(neigh_table_clear);
  
 -static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 +static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
  {
        struct net *net = sock_net(skb->sk);
        struct ndmsg *ndm;
@@@ -1668,7 -1677,7 +1668,7 @@@ out
        return err;
  }
  
 -static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 +static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
  {
        struct net *net = sock_net(skb->sk);
        struct ndmsg *ndm;
@@@ -1946,7 -1955,7 +1946,7 @@@ static const struct nla_policy nl_ntbl_
        [NDTPA_LOCKTIME]                = { .type = NLA_U64 },
  };
  
 -static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 +static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
  {
        struct net *net = sock_net(skb->sk);
        struct neigh_table *tbl;
@@@ -2705,7 -2714,7 +2705,7 @@@ static int neigh_stat_seq_open(struct i
  
        if (!ret) {
                struct seq_file *sf = file->private_data;
-               sf->private = PDE(inode)->data;
+               sf->private = PDE_DATA(inode);
        }
        return ret;
  };
diff --combined net/core/pktgen.c
index 5c217427a669391d2ba372ad23e479d52bb331af,6c41e979dc884b7b34d79d03f2cb396669680773..11f2704c3810d54b3539daddea36d50ef230636f
@@@ -508,7 -508,7 +508,7 @@@ out
  
  static int pgctrl_open(struct inode *inode, struct file *file)
  {
-       return single_open(file, pgctrl_show, PDE(inode)->data);
+       return single_open(file, pgctrl_show, PDE_DATA(inode));
  }
  
  static const struct file_operations pktgen_fops = {
@@@ -1685,7 -1685,7 +1685,7 @@@ static ssize_t pktgen_if_write(struct f
  
  static int pktgen_if_open(struct inode *inode, struct file *file)
  {
-       return single_open(file, pktgen_if_show, PDE(inode)->data);
+       return single_open(file, pktgen_if_show, PDE_DATA(inode));
  }
  
  static const struct file_operations pktgen_if_fops = {
@@@ -1823,7 -1823,7 +1823,7 @@@ out
  
  static int pktgen_thread_open(struct inode *inode, struct file *file)
  {
-       return single_open(file, pktgen_thread_show, PDE(inode)->data);
+       return single_open(file, pktgen_thread_show, PDE_DATA(inode));
  }
  
  static const struct file_operations pktgen_thread_fops = {
@@@ -1904,7 -1904,7 +1904,7 @@@ static void pktgen_change_name(const st
                        if (pkt_dev->odev != dev)
                                continue;
  
-                       remove_proc_entry(pkt_dev->entry->name, pn->proc_dir);
+                       proc_remove(pkt_dev->entry);
  
                        pkt_dev->entry = proc_create_data(dev->name, 0600,
                                                          pn->proc_dir,
@@@ -2198,7 -2198,7 +2198,7 @@@ static inline int f_pick(struct pktgen_
                                pkt_dev->curfl = 0; /*reset */
                }
        } else {
 -              flow = random32() % pkt_dev->cflows;
 +              flow = prandom_u32() % pkt_dev->cflows;
                pkt_dev->curfl = flow;
  
                if (pkt_dev->flows[flow].count > pkt_dev->lflow) {
@@@ -2246,7 -2246,7 +2246,7 @@@ static void set_cur_queue_map(struct pk
        else if (pkt_dev->queue_map_min <= pkt_dev->queue_map_max) {
                __u16 t;
                if (pkt_dev->flags & F_QUEUE_MAP_RND) {
 -                      t = random32() %
 +                      t = prandom_u32() %
                                (pkt_dev->queue_map_max -
                                 pkt_dev->queue_map_min + 1)
                                + pkt_dev->queue_map_min;
@@@ -2278,7 -2278,7 +2278,7 @@@ static void mod_cur_headers(struct pktg
                __u32 tmp;
  
                if (pkt_dev->flags & F_MACSRC_RND)
 -                      mc = random32() % pkt_dev->src_mac_count;
 +                      mc = prandom_u32() % pkt_dev->src_mac_count;
                else {
                        mc = pkt_dev->cur_src_mac_offset++;
                        if (pkt_dev->cur_src_mac_offset >=
                __u32 tmp;
  
                if (pkt_dev->flags & F_MACDST_RND)
 -                      mc = random32() % pkt_dev->dst_mac_count;
 +                      mc = prandom_u32() % pkt_dev->dst_mac_count;
  
                else {
                        mc = pkt_dev->cur_dst_mac_offset++;
                for (i = 0; i < pkt_dev->nr_labels; i++)
                        if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM)
                                pkt_dev->labels[i] = MPLS_STACK_BOTTOM |
 -                                           ((__force __be32)random32() &
 +                                           ((__force __be32)prandom_u32() &
                                                      htonl(0x000fffff));
        }
  
        if ((pkt_dev->flags & F_VID_RND) && (pkt_dev->vlan_id != 0xffff)) {
 -              pkt_dev->vlan_id = random32() & (4096-1);
 +              pkt_dev->vlan_id = prandom_u32() & (4096 - 1);
        }
  
        if ((pkt_dev->flags & F_SVID_RND) && (pkt_dev->svlan_id != 0xffff)) {
 -              pkt_dev->svlan_id = random32() & (4096 - 1);
 +              pkt_dev->svlan_id = prandom_u32() & (4096 - 1);
        }
  
        if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
                if (pkt_dev->flags & F_UDPSRC_RND)
 -                      pkt_dev->cur_udp_src = random32() %
 +                      pkt_dev->cur_udp_src = prandom_u32() %
                                (pkt_dev->udp_src_max - pkt_dev->udp_src_min)
                                + pkt_dev->udp_src_min;
  
  
        if (pkt_dev->udp_dst_min < pkt_dev->udp_dst_max) {
                if (pkt_dev->flags & F_UDPDST_RND) {
 -                      pkt_dev->cur_udp_dst = random32() %
 +                      pkt_dev->cur_udp_dst = prandom_u32() %
                                (pkt_dev->udp_dst_max - pkt_dev->udp_dst_min)
                                + pkt_dev->udp_dst_min;
                } else {
                if (imn < imx) {
                        __u32 t;
                        if (pkt_dev->flags & F_IPSRC_RND)
 -                              t = random32() % (imx - imn) + imn;
 +                              t = prandom_u32() % (imx - imn) + imn;
                        else {
                                t = ntohl(pkt_dev->cur_saddr);
                                t++;
                                __be32 s;
                                if (pkt_dev->flags & F_IPDST_RND) {
  
 -                                      t = random32() % (imx - imn) + imn;
 -                                      s = htonl(t);
 -
 -                                      while (ipv4_is_loopback(s) ||
 -                                             ipv4_is_multicast(s) ||
 -                                             ipv4_is_lbcast(s) ||
 -                                             ipv4_is_zeronet(s) ||
 -                                             ipv4_is_local_multicast(s)) {
 -                                              t = random32() % (imx - imn) + imn;
 +                                      do {
 +                                              t = prandom_u32() %
 +                                                      (imx - imn) + imn;
                                                s = htonl(t);
 -                                      }
 +                                      } while (ipv4_is_loopback(s) ||
 +                                              ipv4_is_multicast(s) ||
 +                                              ipv4_is_lbcast(s) ||
 +                                              ipv4_is_zeronet(s) ||
 +                                              ipv4_is_local_multicast(s));
                                        pkt_dev->cur_daddr = s;
                                } else {
                                        t = ntohl(pkt_dev->cur_daddr);
  
                        for (i = 0; i < 4; i++) {
                                pkt_dev->cur_in6_daddr.s6_addr32[i] =
 -                                  (((__force __be32)random32() |
 +                                  (((__force __be32)prandom_u32() |
                                      pkt_dev->min_in6_daddr.s6_addr32[i]) &
                                     pkt_dev->max_in6_daddr.s6_addr32[i]);
                        }
        if (pkt_dev->min_pkt_size < pkt_dev->max_pkt_size) {
                __u32 t;
                if (pkt_dev->flags & F_TXSIZE_RND) {
 -                      t = random32() %
 +                      t = prandom_u32() %
                                (pkt_dev->max_pkt_size - pkt_dev->min_pkt_size)
                                + pkt_dev->min_pkt_size;
                } else {
@@@ -3574,8 -3576,6 +3574,6 @@@ static void _rem_dev_from_if_list(struc
  static int pktgen_remove_device(struct pktgen_thread *t,
                                struct pktgen_dev *pkt_dev)
  {
-       struct pktgen_net *pn = t->net;
        pr_debug("remove_device pkt_dev=%p\n", pkt_dev);
  
        if (pkt_dev->running) {
        _rem_dev_from_if_list(t, pkt_dev);
  
        if (pkt_dev->entry)
-               remove_proc_entry(pkt_dev->entry->name, pn->proc_dir);
+               proc_remove(pkt_dev->entry);
  
  #ifdef CONFIG_XFRM
        free_SAs(pkt_dev);
diff --combined net/ipv4/tcp_ipv4.c
index d979657b8a122fe869c807f8d3e796651f668781,fc55a1c79bd9a5a21288af2584fc78542325a105..719652305a2950a3407804136bf7f42dc1d18e15
@@@ -838,6 -838,7 +838,6 @@@ static void tcp_v4_reqsk_send_ack(struc
   */
  static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
                              struct request_sock *req,
 -                            struct request_values *rvp,
                              u16 queue_mapping,
                              bool nocache)
  {
        if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL)
                return -1;
  
 -      skb = tcp_make_synack(sk, dst, req, rvp, NULL);
 +      skb = tcp_make_synack(sk, dst, req, NULL);
  
        if (skb) {
                __tcp_v4_send_check(skb, ireq->loc_addr, ireq->rmt_addr);
        return err;
  }
  
 -static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req,
 -                           struct request_values *rvp)
 +static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req)
  {
 -      int res = tcp_v4_send_synack(sk, NULL, req, rvp, 0, false);
 +      int res = tcp_v4_send_synack(sk, NULL, req, 0, false);
  
        if (!res)
                TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
@@@ -1369,7 -1371,8 +1369,7 @@@ static bool tcp_fastopen_check(struct s
  static int tcp_v4_conn_req_fastopen(struct sock *sk,
                                    struct sk_buff *skb,
                                    struct sk_buff *skb_synack,
 -                                  struct request_sock *req,
 -                                  struct request_values *rvp)
 +                                  struct request_sock *req)
  {
        struct tcp_sock *tp = tcp_sk(sk);
        struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;
  
  int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
  {
 -      struct tcp_extend_values tmp_ext;
        struct tcp_options_received tmp_opt;
 -      const u8 *hash_location;
        struct request_sock *req;
        struct inet_request_sock *ireq;
        struct tcp_sock *tp = tcp_sk(sk);
        tcp_clear_options(&tmp_opt);
        tmp_opt.mss_clamp = TCP_MSS_DEFAULT;
        tmp_opt.user_mss  = tp->rx_opt.user_mss;
 -      tcp_parse_options(skb, &tmp_opt, &hash_location, 0,
 -          want_cookie ? NULL : &foc);
 -
 -      if (tmp_opt.cookie_plus > 0 &&
 -          tmp_opt.saw_tstamp &&
 -          !tp->rx_opt.cookie_out_never &&
 -          (sysctl_tcp_cookie_size > 0 ||
 -           (tp->cookie_values != NULL &&
 -            tp->cookie_values->cookie_desired > 0))) {
 -              u8 *c;
 -              u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS];
 -              int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE;
 -
 -              if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0)
 -                      goto drop_and_release;
 -
 -              /* Secret recipe starts with IP addresses */
 -              *mess++ ^= (__force u32)daddr;
 -              *mess++ ^= (__force u32)saddr;
 -
 -              /* plus variable length Initiator Cookie */
 -              c = (u8 *)mess;
 -              while (l-- > 0)
 -                      *c++ ^= *hash_location++;
 -
 -              want_cookie = false;    /* not our kind of cookie */
 -              tmp_ext.cookie_out_never = 0; /* false */
 -              tmp_ext.cookie_plus = tmp_opt.cookie_plus;
 -      } else if (!tp->rx_opt.cookie_in_always) {
 -              /* redundant indications, but ensure initialization. */
 -              tmp_ext.cookie_out_never = 1; /* true */
 -              tmp_ext.cookie_plus = 0;
 -      } else {
 -              goto drop_and_release;
 -      }
 -      tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always;
 +      tcp_parse_options(skb, &tmp_opt, 0, want_cookie ? NULL : &foc);
  
        if (want_cookie && !tmp_opt.saw_tstamp)
                tcp_clear_options(&tmp_opt);
         * of tcp_v4_send_synack()->tcp_select_initial_window().
         */
        skb_synack = tcp_make_synack(sk, dst, req,
 -          (struct request_values *)&tmp_ext,
            fastopen_cookie_present(&valid_foc) ? &valid_foc : NULL);
  
        if (skb_synack) {
                if (fastopen_cookie_present(&foc) && foc.len != 0)
                        NET_INC_STATS_BH(sock_net(sk),
                            LINUX_MIB_TCPFASTOPENPASSIVEFAIL);
 -      } else if (tcp_v4_conn_req_fastopen(sk, skb, skb_synack, req,
 -          (struct request_values *)&tmp_ext))
 +      } else if (tcp_v4_conn_req_fastopen(sk, skb, skb_synack, req))
                goto drop_and_free;
  
        return 0;
@@@ -1866,7 -1908,6 +1866,7 @@@ discard
        return 0;
  
  csum_err:
 +      TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS);
        TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
        goto discard;
  }
@@@ -1909,51 -1950,6 +1909,51 @@@ void tcp_v4_early_demux(struct sk_buff 
        }
  }
  
 +/* Packet is added to VJ-style prequeue for processing in process
 + * context, if a reader task is waiting. Apparently, this exciting
 + * idea (VJ's mail "Re: query about TCP header on tcp-ip" of 07 Sep 93)
 + * failed somewhere. Latency? Burstiness? Well, at least now we will
 + * see, why it failed. 8)8)                             --ANK
 + *
 + */
 +bool tcp_prequeue(struct sock *sk, struct sk_buff *skb)
 +{
 +      struct tcp_sock *tp = tcp_sk(sk);
 +
 +      if (sysctl_tcp_low_latency || !tp->ucopy.task)
 +              return false;
 +
 +      if (skb->len <= tcp_hdrlen(skb) &&
 +          skb_queue_len(&tp->ucopy.prequeue) == 0)
 +              return false;
 +
 +      skb_dst_force(skb);
 +      __skb_queue_tail(&tp->ucopy.prequeue, skb);
 +      tp->ucopy.memory += skb->truesize;
 +      if (tp->ucopy.memory > sk->sk_rcvbuf) {
 +              struct sk_buff *skb1;
 +
 +              BUG_ON(sock_owned_by_user(sk));
 +
 +              while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL) {
 +                      sk_backlog_rcv(sk, skb1);
 +                      NET_INC_STATS_BH(sock_net(sk),
 +                                       LINUX_MIB_TCPPREQUEUEDROPPED);
 +              }
 +
 +              tp->ucopy.memory = 0;
 +      } else if (skb_queue_len(&tp->ucopy.prequeue) == 1) {
 +              wake_up_interruptible_sync_poll(sk_sleep(sk),
 +                                         POLLIN | POLLRDNORM | POLLRDBAND);
 +              if (!inet_csk_ack_scheduled(sk))
 +                      inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
 +                                                (3 * tcp_rto_min(sk)) / 4,
 +                                                TCP_RTO_MAX);
 +      }
 +      return true;
 +}
 +EXPORT_SYMBOL(tcp_prequeue);
 +
  /*
   *    From tcp_input.c
   */
@@@ -1987,7 -1983,7 +1987,7 @@@ int tcp_v4_rcv(struct sk_buff *skb
         * provided case of th->doff==0 is eliminated.
         * So, we defer the checks. */
        if (!skb_csum_unnecessary(skb) && tcp_v4_checksum_init(skb))
 -              goto bad_packet;
 +              goto csum_error;
  
        th = tcp_hdr(skb);
        iph = ip_hdr(skb);
@@@ -2053,8 -2049,6 +2053,8 @@@ no_tcp_socket
                goto discard_it;
  
        if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
 +csum_error:
 +              TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS);
  bad_packet:
                TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
        } else {
@@@ -2076,13 -2070,10 +2076,13 @@@ do_time_wait
                goto discard_it;
        }
  
 -      if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
 -              TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
 +      if (skb->len < (th->doff << 2)) {
                inet_twsk_put(inet_twsk(sk));
 -              goto discard_it;
 +              goto bad_packet;
 +      }
 +      if (tcp_checksum_complete(skb)) {
 +              inet_twsk_put(inet_twsk(sk));
 +              goto csum_error;
        }
        switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
        case TCP_TW_SYN: {
@@@ -2206,6 -2197,12 +2206,6 @@@ void tcp_v4_destroy_sock(struct sock *s
        if (inet_csk(sk)->icsk_bind_hash)
                inet_put_port(sk);
  
 -      /* TCP Cookie Transactions */
 -      if (tp->cookie_values != NULL) {
 -              kref_put(&tp->cookie_values->kref,
 -                       tcp_cookie_values_release);
 -              tp->cookie_values = NULL;
 -      }
        BUG_ON(tp->fastopen_rsk != NULL);
  
        /* If socket is aborted during connect operation */
@@@ -2583,7 -2580,7 +2583,7 @@@ static void tcp_seq_stop(struct seq_fil
  
  int tcp_seq_open(struct inode *inode, struct file *file)
  {
-       struct tcp_seq_afinfo *afinfo = PDE(inode)->data;
+       struct tcp_seq_afinfo *afinfo = PDE_DATA(inode);
        struct tcp_iter_state *s;
        int err;
  
@@@ -2662,9 -2659,7 +2662,9 @@@ static void get_tcp4_sock(struct sock *
        __u16 srcp = ntohs(inet->inet_sport);
        int rx_queue;
  
 -      if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
 +      if (icsk->icsk_pending == ICSK_TIME_RETRANS ||
 +          icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
 +          icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
                timer_active    = 1;
                timer_expires   = icsk->icsk_timeout;
        } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
diff --combined net/ipv4/udp.c
index 3159d16441d0c87d1bba9673bb48c8a4b804cc4c,d27264318315371d64bf6f1732d20ceb0ec1c06e..6abbe6455129d6639e35e735e78866d0c16ebc73
@@@ -902,9 -902,9 +902,9 @@@ int udp_sendmsg(struct kiocb *iocb, str
        ipc.addr = inet->inet_saddr;
  
        ipc.oif = sk->sk_bound_dev_if;
 -      err = sock_tx_timestamp(sk, &ipc.tx_flags);
 -      if (err)
 -              return err;
 +
 +      sock_tx_timestamp(sk, &ipc.tx_flags);
 +
        if (msg->msg_controllen) {
                err = ip_cmsg_send(sock_net(sk), msg, &ipc);
                if (err)
@@@ -1131,8 -1131,6 +1131,8 @@@ static unsigned int first_packet_length
        spin_lock_bh(&rcvq->lock);
        while ((skb = skb_peek(rcvq)) != NULL &&
                udp_lib_checksum_complete(skb)) {
 +              UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS,
 +                               IS_UDPLITE(sk));
                UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS,
                                 IS_UDPLITE(sk));
                atomic_inc(&sk->sk_drops);
  
  csum_copy_err:
        slow = lock_sock_fast(sk);
 -      if (!skb_kill_datagram(sk, skb, flags))
 +      if (!skb_kill_datagram(sk, skb, flags)) {
 +              UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
                UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
 +      }
        unlock_sock_fast(sk, slow);
  
        if (noblock)
@@@ -1517,7 -1513,7 +1517,7 @@@ int udp_queue_rcv_skb(struct sock *sk, 
  
        if (rcu_access_pointer(sk->sk_filter) &&
            udp_lib_checksum_complete(skb))
 -              goto drop;
 +              goto csum_error;
  
  
        if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf))
  
        return rc;
  
 +csum_error:
 +      UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
  drop:
        UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
        atomic_inc(&sk->sk_drops);
@@@ -1755,7 -1749,6 +1755,7 @@@ csum_error
                       proto == IPPROTO_UDPLITE ? "Lite" : "",
                       &saddr, ntohs(uh->source), &daddr, ntohs(uh->dest),
                       ulen);
 +      UDP_INC_STATS_BH(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE);
  drop:
        UDP_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE);
        kfree_skb(skb);
@@@ -2100,7 -2093,7 +2100,7 @@@ static void udp_seq_stop(struct seq_fil
  
  int udp_seq_open(struct inode *inode, struct file *file)
  {
-       struct udp_seq_afinfo *afinfo = PDE(inode)->data;
+       struct udp_seq_afinfo *afinfo = PDE_DATA(inode);
        struct udp_iter_state *s;
        int err;
  
@@@ -2286,88 -2279,31 +2286,88 @@@ void __init udp_init(void
  
  int udp4_ufo_send_check(struct sk_buff *skb)
  {
 -      const struct iphdr *iph;
 -      struct udphdr *uh;
 -
 -      if (!pskb_may_pull(skb, sizeof(*uh)))
 +      if (!pskb_may_pull(skb, sizeof(struct udphdr)))
                return -EINVAL;
  
 -      iph = ip_hdr(skb);
 -      uh = udp_hdr(skb);
 +      if (likely(!skb->encapsulation)) {
 +              const struct iphdr *iph;
 +              struct udphdr *uh;
 +
 +              iph = ip_hdr(skb);
 +              uh = udp_hdr(skb);
  
 -      uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len,
 -                                     IPPROTO_UDP, 0);
 -      skb->csum_start = skb_transport_header(skb) - skb->head;
 -      skb->csum_offset = offsetof(struct udphdr, check);
 -      skb->ip_summed = CHECKSUM_PARTIAL;
 +              uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len,
 +                              IPPROTO_UDP, 0);
 +              skb->csum_start = skb_transport_header(skb) - skb->head;
 +              skb->csum_offset = offsetof(struct udphdr, check);
 +              skb->ip_summed = CHECKSUM_PARTIAL;
 +      }
        return 0;
  }
  
 +static struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
 +              netdev_features_t features)
 +{
 +      struct sk_buff *segs = ERR_PTR(-EINVAL);
 +      int mac_len = skb->mac_len;
 +      int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
 +      int outer_hlen;
 +      netdev_features_t enc_features;
 +
 +      if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
 +              goto out;
 +
 +      skb->encapsulation = 0;
 +      __skb_pull(skb, tnl_hlen);
 +      skb_reset_mac_header(skb);
 +      skb_set_network_header(skb, skb_inner_network_offset(skb));
 +      skb->mac_len = skb_inner_network_offset(skb);
 +
 +      /* segment inner packet. */
 +      enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
 +      segs = skb_mac_gso_segment(skb, enc_features);
 +      if (!segs || IS_ERR(segs))
 +              goto out;
 +
 +      outer_hlen = skb_tnl_header_len(skb);
 +      skb = segs;
 +      do {
 +              struct udphdr *uh;
 +              int udp_offset = outer_hlen - tnl_hlen;
 +
 +              skb->mac_len = mac_len;
 +
 +              skb_push(skb, outer_hlen);
 +              skb_reset_mac_header(skb);
 +              skb_set_network_header(skb, mac_len);
 +              skb_set_transport_header(skb, udp_offset);
 +              uh = udp_hdr(skb);
 +              uh->len = htons(skb->len - udp_offset);
 +
 +              /* csum segment if tunnel sets skb with csum. */
 +              if (unlikely(uh->check)) {
 +                      struct iphdr *iph = ip_hdr(skb);
 +
 +                      uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
 +                                                     skb->len - udp_offset,
 +                                                     IPPROTO_UDP, 0);
 +                      uh->check = csum_fold(skb_checksum(skb, udp_offset,
 +                                                         skb->len - udp_offset, 0));
 +                      if (uh->check == 0)
 +                              uh->check = CSUM_MANGLED_0;
 +
 +              }
 +              skb->ip_summed = CHECKSUM_NONE;
 +      } while ((skb = skb->next));
 +out:
 +      return segs;
 +}
 +
  struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
        netdev_features_t features)
  {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        unsigned int mss;
 -      int offset;
 -      __wsum csum;
 -
        mss = skb_shinfo(skb)->gso_size;
        if (unlikely(skb->len <= mss))
                goto out;
                int type = skb_shinfo(skb)->gso_type;
  
                if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY |
 +                                    SKB_GSO_UDP_TUNNEL |
                                      SKB_GSO_GRE) ||
                             !(type & (SKB_GSO_UDP))))
                        goto out;
                goto out;
        }
  
 -      /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
 -       * do checksum of UDP packets sent as multiple IP fragments.
 -       */
 -      offset = skb_checksum_start_offset(skb);
 -      csum = skb_checksum(skb, offset, skb->len - offset, 0);
 -      offset += skb->csum_offset;
 -      *(__sum16 *)(skb->data + offset) = csum_fold(csum);
 -      skb->ip_summed = CHECKSUM_NONE;
 -
        /* Fragment the skb. IP headers of the fragments are updated in
         * inet_gso_segment()
         */
 -      segs = skb_segment(skb, features);
 +      if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL)
 +              segs = skb_udp_tunnel_segment(skb, features);
 +      else {
 +              int offset;
 +              __wsum csum;
 +
 +              /* Do software UFO. Complete and fill in the UDP checksum as
 +               * HW cannot do checksum of UDP packets sent as multiple
 +               * IP fragments.
 +               */
 +              offset = skb_checksum_start_offset(skb);
 +              csum = skb_checksum(skb, offset, skb->len - offset, 0);
 +              offset += skb->csum_offset;
 +              *(__sum16 *)(skb->data + offset) = csum_fold(csum);
 +              skb->ip_summed = CHECKSUM_NONE;
 +
 +              segs = skb_segment(skb, features);
 +      }
  out:
        return segs;
  }
 -
diff --combined net/ipv6/proc.c
index 115cc58898f5ab2e500037408185db62308465f3,537d9ee7209f91254d6b75446b8495a9679d1bf1..f3c1ff4357ff1ac91f5e69c704e03b1e83c0192d
@@@ -90,7 -90,6 +90,7 @@@ static const struct snmp_mib snmp6_ipst
        SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
        SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS),
        SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS),
 +      SNMP_MIB_ITEM("InCsumErrors", IPSTATS_MIB_CSUMERRORS),
        SNMP_MIB_SENTINEL
  };
  
@@@ -100,7 -99,6 +100,7 @@@ static const struct snmp_mib snmp6_icmp
        SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS),
        SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS),
        SNMP_MIB_ITEM("Icmp6OutErrors", ICMP6_MIB_OUTERRORS),
 +      SNMP_MIB_ITEM("Icmp6InCsumErrors", ICMP6_MIB_CSUMERRORS),
        SNMP_MIB_SENTINEL
  };
  
@@@ -131,7 -129,6 +131,7 @@@ static const struct snmp_mib snmp6_udp6
        SNMP_MIB_ITEM("Udp6OutDatagrams", UDP_MIB_OUTDATAGRAMS),
        SNMP_MIB_ITEM("Udp6RcvbufErrors", UDP_MIB_RCVBUFERRORS),
        SNMP_MIB_ITEM("Udp6SndbufErrors", UDP_MIB_SNDBUFERRORS),
 +      SNMP_MIB_ITEM("Udp6InCsumErrors", UDP_MIB_CSUMERRORS),
        SNMP_MIB_SENTINEL
  };
  
@@@ -142,7 -139,6 +142,7 @@@ static const struct snmp_mib snmp6_udpl
        SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS),
        SNMP_MIB_ITEM("UdpLite6RcvbufErrors", UDP_MIB_RCVBUFERRORS),
        SNMP_MIB_ITEM("UdpLite6SndbufErrors", UDP_MIB_SNDBUFERRORS),
 +      SNMP_MIB_ITEM("UdpLite6InCsumErrors", UDP_MIB_CSUMERRORS),
        SNMP_MIB_SENTINEL
  };
  
@@@ -251,7 -247,7 +251,7 @@@ static int snmp6_dev_seq_show(struct se
  
  static int snmp6_dev_seq_open(struct inode *inode, struct file *file)
  {
-       return single_open(file, snmp6_dev_seq_show, PDE(inode)->data);
+       return single_open(file, snmp6_dev_seq_show, PDE_DATA(inode));
  }
  
  static const struct file_operations snmp6_dev_seq_fops = {
@@@ -291,8 -287,7 +291,7 @@@ int snmp6_unregister_dev(struct inet6_d
                return -ENOENT;
        if (!idev->stats.proc_dir_entry)
                return -EINVAL;
-       remove_proc_entry(idev->stats.proc_dir_entry->name,
-                         net->mib.proc_net_devsnmp6);
+       proc_remove(idev->stats.proc_dir_entry);
        idev->stats.proc_dir_entry = NULL;
        return 0;
  }
diff --combined net/netfilter/x_tables.c
index 1a73b18683b6d9f037d891a830b302613a974c47,67fb7bff9bbc7041d383394610f4d9fc6a6303ca..8b03028cca69b616df298e0ffbfdeb247441a341
@@@ -2,7 -2,6 +2,7 @@@
   * x_tables core - Backend for {ip,ip6,arp}_tables
   *
   * Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org>
 + * Copyright (C) 2006-2012 Patrick McHardy <kaber@trash.net>
   *
   * Based on existing ip_tables code which is
   *   Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
@@@ -1000,7 -999,7 +1000,7 @@@ static int xt_table_open(struct inode *
                           sizeof(struct xt_names_priv));
        if (!ret) {
                priv = ((struct seq_file *)file->private_data)->private;
-               priv->af = (unsigned long)PDE(inode)->data;
+               priv->af = (unsigned long)PDE_DATA(inode);
        }
        return ret;
  }
@@@ -1148,7 -1147,7 +1148,7 @@@ static int xt_match_open(struct inode *
  
        seq = file->private_data;
        seq->private = trav;
-       trav->nfproto = (unsigned long)PDE(inode)->data;
+       trav->nfproto = (unsigned long)PDE_DATA(inode);
        return 0;
  }
  
@@@ -1212,7 -1211,7 +1212,7 @@@ static int xt_target_open(struct inode 
  
        seq = file->private_data;
        seq->private = trav;
-       trav->nfproto = (unsigned long)PDE(inode)->data;
+       trav->nfproto = (unsigned long)PDE_DATA(inode);
        return 0;
  }
  
index 0199e7bb8f818ec856f6413f44e43e2a780b0bd7,905c328ed5a821873ebcc24f85c6d778015f0502..9ff035c7140324632965fbf82764d532d4d0a284
@@@ -3,7 -3,6 +3,7 @@@
   *    separately for each hashbucket (sourceip/sourceport/dstip/dstport)
   *
   *    (C) 2003-2004 by Harald Welte <laforge@netfilter.org>
 + *    (C) 2006-2012 Patrick McHardy <kaber@trash.net>
   *    Copyright © CC Computer Consultants GmbH, 2007 - 2008
   *
   * Development of this code was funded by Astaro AG, http://www.astaro.com/
@@@ -108,6 -107,7 +108,7 @@@ struct xt_hashlimit_htable 
  
        /* seq_file stuff */
        struct proc_dir_entry *pde;
+       const char *name;
        struct net *net;
  
        struct hlist_head hash[0];      /* hashtable itself */
@@@ -254,6 -254,11 +255,11 @@@ static int htable_create(struct net *ne
        hinfo->count = 0;
        hinfo->family = family;
        hinfo->rnd_initialized = false;
+       hinfo->name = kstrdup(minfo->name, GFP_KERNEL);
+       if (!hinfo->name) {
+               vfree(hinfo);
+               return -ENOMEM;
+       }
        spin_lock_init(&hinfo->lock);
  
        hinfo->pde = proc_create_data(minfo->name, 0,
                hashlimit_net->ipt_hashlimit : hashlimit_net->ip6t_hashlimit,
                &dl_file_ops, hinfo);
        if (hinfo->pde == NULL) {
+               kfree(hinfo->name);
                vfree(hinfo);
                return -ENOMEM;
        }
@@@ -331,9 -337,10 +338,10 @@@ static void htable_destroy(struct xt_ha
                parent = hashlimit_net->ip6t_hashlimit;
  
        if(parent != NULL)
-               remove_proc_entry(hinfo->pde->name, parent);
+               remove_proc_entry(hinfo->name, parent);
  
        htable_selective_cleanup(hinfo, select_all);
+       kfree(hinfo->name);
        vfree(hinfo);
  }
  
@@@ -345,7 -352,7 +353,7 @@@ static struct xt_hashlimit_htable *htab
        struct xt_hashlimit_htable *hinfo;
  
        hlist_for_each_entry(hinfo, &hashlimit_net->htables, node) {
-               if (!strcmp(name, hinfo->pde->name) &&
+               if (!strcmp(name, hinfo->name) &&
                    hinfo->family == family) {
                        hinfo->use++;
                        return hinfo;
@@@ -842,7 -849,7 +850,7 @@@ static int dl_proc_open(struct inode *i
  
        if (!ret) {
                struct seq_file *sf = file->private_data;
-               sf->private = PDE(inode)->data;
+               sf->private = PDE_DATA(inode);
        }
        return ret;
  }
@@@ -888,7 -895,7 +896,7 @@@ static void __net_exit hashlimit_proc_n
                pde = hashlimit_net->ip6t_hashlimit;
  
        hlist_for_each_entry(hinfo, &hashlimit_net->htables, node)
-               remove_proc_entry(hinfo->pde->name, pde);
+               remove_proc_entry(hinfo->name, pde);
  
        hashlimit_net->ipt_hashlimit = NULL;
        hashlimit_net->ip6t_hashlimit = NULL;
diff --combined net/socket.c
index 280283f03cccee4c23055103a5586bb94a49809b,9663df63e3d166534cbfa71099110fbf89f00478..b416093997dafcf528204be9c99a9986dfe7965d
@@@ -600,7 -600,7 +600,7 @@@ void sock_release(struct socket *sock
  }
  EXPORT_SYMBOL(sock_release);
  
 -int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
 +void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
  {
        *tx_flags = 0;
        if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
                *tx_flags |= SKBTX_SW_TSTAMP;
        if (sock_flag(sk, SOCK_WIFI_STATUS))
                *tx_flags |= SKBTX_WIFI_STATUS;
 -      return 0;
  }
  EXPORT_SYMBOL(sock_tx_timestamp);
  
@@@ -681,6 -682,16 +681,6 @@@ int kernel_sendmsg(struct socket *sock
  }
  EXPORT_SYMBOL(kernel_sendmsg);
  
 -static int ktime2ts(ktime_t kt, struct timespec *ts)
 -{
 -      if (kt.tv64) {
 -              *ts = ktime_to_timespec(kt);
 -              return 1;
 -      } else {
 -              return 0;
 -      }
 -}
 -
  /*
   * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
   */
@@@ -713,15 -724,17 +713,15 @@@ void __sock_recv_timestamp(struct msghd
  
  
        memset(ts, 0, sizeof(ts));
 -      if (skb->tstamp.tv64 &&
 -          sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) {
 -              skb_get_timestampns(skb, ts + 0);
 +      if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) &&
 +          ktime_to_timespec_cond(skb->tstamp, ts + 0))
                empty = 0;
 -      }
        if (shhwtstamps) {
                if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
 -                  ktime2ts(shhwtstamps->syststamp, ts + 1))
 +                  ktime_to_timespec_cond(shhwtstamps->syststamp, ts + 1))
                        empty = 0;
                if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
 -                  ktime2ts(shhwtstamps->hwtstamp, ts + 2))
 +                  ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts + 2))
                        empty = 0;
        }
        if (!empty)
@@@ -1160,15 -1173,6 +1160,6 @@@ static int sock_mmap(struct file *file
  
  static int sock_close(struct inode *inode, struct file *filp)
  {
-       /*
-        *      It was possible the inode is NULL we were
-        *      closing an unfinished socket.
-        */
-       if (!inode) {
-               printk(KERN_DEBUG "sock_close: NULL inode\n");
-               return 0;
-       }
        sock_release(SOCKET_I(inode));
        return 0;
  }
diff --combined net/sunrpc/cache.c
index ce2d180d05a472cdc2fa0951902aa538839417f1,d9828b6799a3a17f424d5a119a9915f50c5b4601..f1889be80912508d27ba473122097d6636090900
@@@ -1208,6 -1208,7 +1208,6 @@@ EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upc
   * key and content are both parsed by cache
   */
  
 -#define isodigit(c) (isdigit(c) && c <= '7')
  int qword_get(char **bpp, char *dest, int bufsize)
  {
        /* return bytes copied, or -1 on error */
@@@ -1460,7 -1461,7 +1460,7 @@@ static ssize_t write_flush(struct file 
  static ssize_t cache_read_procfs(struct file *filp, char __user *buf,
                                 size_t count, loff_t *ppos)
  {
-       struct cache_detail *cd = PDE(file_inode(filp))->data;
+       struct cache_detail *cd = PDE_DATA(file_inode(filp));
  
        return cache_read(filp, buf, count, ppos, cd);
  }
  static ssize_t cache_write_procfs(struct file *filp, const char __user *buf,
                                  size_t count, loff_t *ppos)
  {
-       struct cache_detail *cd = PDE(file_inode(filp))->data;
+       struct cache_detail *cd = PDE_DATA(file_inode(filp));
  
        return cache_write(filp, buf, count, ppos, cd);
  }
  
  static unsigned int cache_poll_procfs(struct file *filp, poll_table *wait)
  {
-       struct cache_detail *cd = PDE(file_inode(filp))->data;
+       struct cache_detail *cd = PDE_DATA(file_inode(filp));
  
        return cache_poll(filp, wait, cd);
  }
@@@ -1484,21 -1485,21 +1484,21 @@@ static long cache_ioctl_procfs(struct f
                               unsigned int cmd, unsigned long arg)
  {
        struct inode *inode = file_inode(filp);
-       struct cache_detail *cd = PDE(inode)->data;
+       struct cache_detail *cd = PDE_DATA(inode);
  
        return cache_ioctl(inode, filp, cmd, arg, cd);
  }
  
  static int cache_open_procfs(struct inode *inode, struct file *filp)
  {
-       struct cache_detail *cd = PDE(inode)->data;
+       struct cache_detail *cd = PDE_DATA(inode);
  
        return cache_open(inode, filp, cd);
  }
  
  static int cache_release_procfs(struct inode *inode, struct file *filp)
  {
-       struct cache_detail *cd = PDE(inode)->data;
+       struct cache_detail *cd = PDE_DATA(inode);
  
        return cache_release(inode, filp, cd);
  }
@@@ -1516,14 -1517,14 +1516,14 @@@ static const struct file_operations cac
  
  static int content_open_procfs(struct inode *inode, struct file *filp)
  {
-       struct cache_detail *cd = PDE(inode)->data;
+       struct cache_detail *cd = PDE_DATA(inode);
  
        return content_open(inode, filp, cd);
  }
  
  static int content_release_procfs(struct inode *inode, struct file *filp)
  {
-       struct cache_detail *cd = PDE(inode)->data;
+       struct cache_detail *cd = PDE_DATA(inode);
  
        return content_release(inode, filp, cd);
  }
@@@ -1537,14 -1538,14 +1537,14 @@@ static const struct file_operations con
  
  static int open_flush_procfs(struct inode *inode, struct file *filp)
  {
-       struct cache_detail *cd = PDE(inode)->data;
+       struct cache_detail *cd = PDE_DATA(inode);
  
        return open_flush(inode, filp, cd);
  }
  
  static int release_flush_procfs(struct inode *inode, struct file *filp)
  {
-       struct cache_detail *cd = PDE(inode)->data;
+       struct cache_detail *cd = PDE_DATA(inode);
  
        return release_flush(inode, filp, cd);
  }
  static ssize_t read_flush_procfs(struct file *filp, char __user *buf,
                            size_t count, loff_t *ppos)
  {
-       struct cache_detail *cd = PDE(file_inode(filp))->data;
+       struct cache_detail *cd = PDE_DATA(file_inode(filp));
  
        return read_flush(filp, buf, count, ppos, cd);
  }
@@@ -1561,7 -1562,7 +1561,7 @@@ static ssize_t write_flush_procfs(struc
                                  const char __user *buf,
                                  size_t count, loff_t *ppos)
  {
-       struct cache_detail *cd = PDE(file_inode(filp))->data;
+       struct cache_detail *cd = PDE_DATA(file_inode(filp));
  
        return write_flush(filp, buf, count, ppos, cd);
  }