Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Thu, 13 Oct 2005 02:07:59 +0000 (19:07 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 13 Oct 2005 02:07:59 +0000 (19:07 -0700)
30 files changed:
Documentation/dell_rbu.txt
arch/m32r/kernel/entry.S
arch/m32r/kernel/traps.c
arch/ppc/kernel/cputable.c
arch/ppc/kernel/dma-mapping.c
arch/ppc64/kernel/module.c
arch/ppc64/kernel/pSeries_pci.c
arch/sparc/Kconfig
arch/sparc/defconfig
arch/sparc64/kernel/head.S
arch/um/drivers/Makefile
arch/um/drivers/ubd_kern.c
arch/um/drivers/ubd_user.c [new file with mode: 0644]
arch/um/include/aio.h
arch/um/include/os.h
arch/um/os-Linux/aio.c
drivers/firmware/dell_rbu.c
drivers/media/video/bttv-cards.c
drivers/net/e100.c
drivers/s390/cio/device.c
drivers/scsi/sata_nv.c
drivers/serial/sunsab.c
drivers/serial/sunzilog.c
fs/9p/vfs_file.c
fs/binfmt_elf.c
fs/nfs_common/nfsacl.c
include/asm-powerpc/timex.h
include/asm-ppc/cputable.h
mm/fremap.c
mm/madvise.c

index 95d7f62..941343a 100644 (file)
@@ -35,6 +35,7 @@ The driver load creates the following directories under the /sys file system.
 /sys/class/firmware/dell_rbu/data
 /sys/devices/platform/dell_rbu/image_type
 /sys/devices/platform/dell_rbu/data
+/sys/devices/platform/dell_rbu/packet_size
 
 The driver supports two types of update mechanism; monolithic and packetized.
 These update mechanism depends upon the BIOS currently running on the system.
@@ -47,8 +48,26 @@ By default the driver uses monolithic memory for the update type. This can be
 changed to packets during the driver load time by specifying the load
 parameter image_type=packet.  This can also be changed later as below
 echo packet > /sys/devices/platform/dell_rbu/image_type
-Also echoing either mono ,packet or init in to image_type will free up the
-memory allocated by the driver.
+
+In packet update mode the packet size has to be given before any packets can
+be downloaded. It is done as below
+echo XXXX > /sys/devices/platform/dell_rbu/packet_size
+In the packet update mechanism, the user neesd to create a new file having
+packets of data arranged back to back. It can be done as follows
+The user creates packets header, gets the chunk of the BIOS image and
+placs it next to the packetheader; now, the packetheader + BIOS image chunk
+added to geather should match the specified packet_size. This makes one
+packet, the user needs to create more such packets out of the entire BIOS
+image file and then arrange all these packets back to back in to one single
+file.
+This file is then copied to /sys/class/firmware/dell_rbu/data.
+Once this file gets to the driver, the driver extracts packet_size data from
+the file and spreads it accross the physical memory in contiguous packet_sized
+space.
+This method makes sure that all the packets get to the driver in a single operation.
+
+In monolithic update the user simply get the BIOS image (.hdr file) and copies
+to the data file as is without any change to the BIOS image itself.
 
 Do the steps below to download the BIOS image.
 1) echo 1 > /sys/class/firmware/dell_rbu/loading
@@ -58,7 +77,10 @@ Do the steps below to download the BIOS image.
 The /sys/class/firmware/dell_rbu/ entries will remain till the following is
 done.
 echo -1 > /sys/class/firmware/dell_rbu/loading.
-Until this step is completed the drivr cannot be unloaded.
+Until this step is completed the driver cannot be unloaded.
+Also echoing either mono ,packet or init in to image_type will free up the
+memory allocated by the driver.
+
 If an user by accident executes steps 1 and 3 above without executing step 2;
 it will make the /sys/class/firmware/dell_rbu/ entries to disappear.
 The entries can be recreated by doing the following
@@ -66,15 +88,11 @@ echo init > /sys/devices/platform/dell_rbu/image_type
 NOTE: echoing init in image_type does not change it original value.
 
 Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to
-read back the image downloaded. This is useful in case of packet update
-mechanism where the above steps 1,2,3 will repeated for every packet.
-By reading the /sys/devices/platform/dell_rbu/data file all packet data
-downloaded can be verified in a single file.
-The packets are arranged in this file one after the other in a FIFO order.
+read back the image downloaded.
 
 NOTE:
-This driver requires a patch for firmware_class.c which has the addition
-of request_firmware_nowait_nohotplug function to wortk
+This driver requires a patch for firmware_class.c which has the modified
+request_firmware_nowait function.
 Also after updating the BIOS image an user mdoe application neeeds to execute
 code which message the BIOS update request to the BIOS. So on the next reboot
 the BIOS knows about the new image downloaded and it updates it self.
index dddbf6b..85920fb 100644 (file)
@@ -681,6 +681,15 @@ ENTRY(debug_trap)
        bl      do_debug_trap
        bra     error_code
 
+ENTRY(ill_trap)
+       /* void ill_trap(void) */
+       SWITCH_TO_KERNEL_STACK
+       SAVE_ALL
+       ldi     r1, #0                          ; error_code ; FIXME
+       mv      r0, sp                          ; pt_regs
+       bl      do_ill_trap
+       bra     error_code
+
 
 /* Cache flushing handler */
 ENTRY(cache_flushing_handler)
index 0192227..5fe8ed6 100644 (file)
@@ -5,8 +5,6 @@
  *                            Hitoshi Yamamoto
  */
 
-/* $Id$ */
-
 /*
  * 'traps.c' handles hardware traps and faults after we have saved some
  * state in 'entry.S'.
@@ -35,6 +33,7 @@ asmlinkage void ei_handler(void);
 asmlinkage void rie_handler(void);
 asmlinkage void debug_trap(void);
 asmlinkage void cache_flushing_handler(void);
+asmlinkage void ill_trap(void);
 
 #ifdef CONFIG_SMP
 extern void smp_reschedule_interrupt(void);
@@ -77,22 +76,22 @@ void        set_eit_vector_entries(void)
        eit_vector[5] = BRA_INSN(default_eit_handler, 5);
        eit_vector[8] = BRA_INSN(rie_handler, 8);
        eit_vector[12] = BRA_INSN(alignment_check, 12);
-       eit_vector[16] = 0xff000000UL;
+       eit_vector[16] = BRA_INSN(ill_trap, 16);
        eit_vector[17] = BRA_INSN(debug_trap, 17);
        eit_vector[18] = BRA_INSN(system_call, 18);
-       eit_vector[19] = 0xff000000UL;
-       eit_vector[20] = 0xff000000UL;
-       eit_vector[21] = 0xff000000UL;
-       eit_vector[22] = 0xff000000UL;
-       eit_vector[23] = 0xff000000UL;
-       eit_vector[24] = 0xff000000UL;
-       eit_vector[25] = 0xff000000UL;
-       eit_vector[26] = 0xff000000UL;
-       eit_vector[27] = 0xff000000UL;
+       eit_vector[19] = BRA_INSN(ill_trap, 19);
+       eit_vector[20] = BRA_INSN(ill_trap, 20);
+       eit_vector[21] = BRA_INSN(ill_trap, 21);
+       eit_vector[22] = BRA_INSN(ill_trap, 22);
+       eit_vector[23] = BRA_INSN(ill_trap, 23);
+       eit_vector[24] = BRA_INSN(ill_trap, 24);
+       eit_vector[25] = BRA_INSN(ill_trap, 25);
+       eit_vector[26] = BRA_INSN(ill_trap, 26);
+       eit_vector[27] = BRA_INSN(ill_trap, 27);
        eit_vector[28] = BRA_INSN(cache_flushing_handler, 28);
-       eit_vector[29] = 0xff000000UL;
-       eit_vector[30] = 0xff000000UL;
-       eit_vector[31] = 0xff000000UL;
+       eit_vector[29] = BRA_INSN(ill_trap, 29);
+       eit_vector[30] = BRA_INSN(ill_trap, 30);
+       eit_vector[31] = BRA_INSN(ill_trap, 31);
        eit_vector[32] = BRA_INSN(ei_handler, 32);
        eit_vector[64] = BRA_INSN(pie_handler, 64);
 #ifdef CONFIG_MMU
@@ -286,7 +285,8 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 
 DO_ERROR( 1, SIGTRAP, "debug trap", debug_trap)
 DO_ERROR_INFO(0x20, SIGILL,  "reserved instruction ", rie_handler, ILL_ILLOPC, regs->bpc)
-DO_ERROR_INFO(0x100, SIGILL,  "privilege instruction", pie_handler, ILL_PRVOPC, regs->bpc)
+DO_ERROR_INFO(0x100, SIGILL,  "privileged instruction", pie_handler, ILL_PRVOPC, regs->bpc)
+DO_ERROR_INFO(-1, SIGILL,  "illegal trap", ill_trap, ILL_ILLTRP, regs->bpc)
 
 extern int handle_unaligned_access(unsigned long, struct pt_regs *);
 
@@ -329,4 +329,3 @@ asmlinkage void do_alignment_check(struct pt_regs *regs, long error_code)
                set_fs(oldfs);
        }
 }
-
index 546e1ea..6b76cf5 100644 (file)
@@ -91,7 +91,7 @@ struct cpu_spec       cpu_specs[] = {
                .cpu_features           = CPU_FTR_COMMON | CPU_FTR_601 |
                        CPU_FTR_HPTE_TABLE,
                .cpu_user_features      = COMMON_PPC | PPC_FEATURE_601_INSTR |
-                       PPC_FEATURE_UNIFIED_CACHE,
+                       PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB,
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .cpu_setup              = __setup_cpu_601
@@ -745,7 +745,8 @@ struct cpu_spec     cpu_specs[] = {
                .cpu_name               = "403GCX",
                .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
                        CPU_FTR_USE_TB,
-               .cpu_user_features      = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+               .cpu_user_features      = PPC_FEATURE_32 |
+                       PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB,
                .icache_bsize           = 16,
                .dcache_bsize           = 16,
        },
index b566d98..8edee80 100644 (file)
@@ -401,10 +401,10 @@ EXPORT_SYMBOL(__dma_sync);
 static inline void __dma_sync_page_highmem(struct page *page,
                unsigned long offset, size_t size, int direction)
 {
-       size_t seg_size = min((size_t)PAGE_SIZE, size) - offset;
+       size_t seg_size = min((size_t)(PAGE_SIZE - offset), size);
        size_t cur_size = seg_size;
        unsigned long flags, start, seg_offset = offset;
-       int nr_segs = PAGE_ALIGN(size + (PAGE_SIZE - offset))/PAGE_SIZE;
+       int nr_segs = 1 + ((size - seg_size) + PAGE_SIZE - 1)/PAGE_SIZE;
        int seg_nr = 0;
 
        local_irq_save(flags);
index c683bf8..928b858 100644 (file)
@@ -341,6 +341,19 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
                        *(unsigned long *)location = my_r2(sechdrs, me);
                        break;
 
+               case R_PPC64_TOC16:
+                       /* Subtact TOC pointer */
+                       value -= my_r2(sechdrs, me);
+                       if (value + 0x8000 > 0xffff) {
+                               printk("%s: bad TOC16 relocation (%lu)\n",
+                                      me->name, value);
+                               return -ENOEXEC;
+                       }
+                       *((uint16_t *) location)
+                               = (*((uint16_t *) location) & ~0xffff)
+                               | (value & 0xffff);
+                       break;
+
                case R_PPC64_TOC16_DS:
                        /* Subtact TOC pointer */
                        value -= my_r2(sechdrs, me);
index 1f5f141..928f8fe 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "pci.h"
 
-static int __initdata s7a_workaround = -1;
+static int __devinitdata s7a_workaround = -1;
 
 #if 0
 void pcibios_name_device(struct pci_dev *dev)
@@ -60,7 +60,7 @@ void pcibios_name_device(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
 #endif
 
-static void __init check_s7a(void)
+static void __devinit check_s7a(void)
 {
        struct device_node *root;
        char *model;
index f7c51b8..6537445 100644 (file)
@@ -21,10 +21,6 @@ config GENERIC_ISA_DMA
        bool
        default y
 
-config GENERIC_IOMAP
-       bool
-       default y
-
 source "init/Kconfig"
 
 menu "General machine setup"
index 8a3aef1..a698562 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_MMU=y
 CONFIG_UID16=y
 CONFIG_HIGHMEM=y
 CONFIG_GENERIC_ISA_DMA=y
-CONFIG_GENERIC_IOMAP=y
 
 #
 # Code maturity level options
index f1dcdf8..4c942f7 100644 (file)
@@ -191,8 +191,9 @@ prom_boot_mapping_phys_low:
        stx     %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 5
        stx     %l2, [%sp + 2047 + 128 + 0x18]  ! arg1: "translate"
        stx     %l5, [%sp + 2047 + 128 + 0x20]  ! arg2: prom_mmu_ihandle_cache
-       srlx    %l0, 22, %l3
-       sllx    %l3, 22, %l3
+       /* PAGE align */
+       srlx    %l0, 13, %l3
+       sllx    %l3, 13, %l3
        stx     %l3, [%sp + 2047 + 128 + 0x28]  ! arg3: vaddr, our PC
        stx     %g0, [%sp + 2047 + 128 + 0x30]  ! res1
        stx     %g0, [%sp + 2047 + 128 + 0x38]  ! res2
@@ -211,6 +212,9 @@ prom_boot_mapping_phys_low:
        ldx     [%sp + 2047 + 128 + 0x48], %l2  ! physaddr high
        stx     %l2, [%l4 + 0x0]
        ldx     [%sp + 2047 + 128 + 0x50], %l3  ! physaddr low
+       /* 4MB align */
+       srlx    %l3, 22, %l3
+       sllx    %l3, 22, %l3
        stx     %l3, [%l4 + 0x8]
 
        /* Leave service as-is, "call-method" */
index 783e18c..de17d4c 100644 (file)
@@ -13,7 +13,7 @@ mcast-objs := mcast_kern.o mcast_user.o
 net-objs := net_kern.o net_user.o
 mconsole-objs := mconsole_kern.o mconsole_user.o
 hostaudio-objs := hostaudio_kern.o
-ubd-objs := ubd_kern.o
+ubd-objs := ubd_kern.o ubd_user.o
 port-objs := port_kern.o port_user.o
 harddog-objs := harddog_kern.o harddog_user.o
 
index e77a38d..f731343 100644 (file)
@@ -35,7 +35,6 @@
 #include "linux/blkpg.h"
 #include "linux/genhd.h"
 #include "linux/spinlock.h"
-#include "asm/atomic.h"
 #include "asm/segment.h"
 #include "asm/uaccess.h"
 #include "asm/irq.h"
 #include "mem.h"
 #include "mem_kern.h"
 #include "cow.h"
-#include "aio.h"
 
 enum ubd_req { UBD_READ, UBD_WRITE };
 
 struct io_thread_req {
-       enum aio_type op;
+       enum ubd_req op;
        int fds[2];
        unsigned long offsets[2];
        unsigned long long offset;
        unsigned long length;
        char *buffer;
        int sectorsize;
-       int bitmap_offset;
-       long bitmap_start;
-       long bitmap_end;
+       unsigned long sector_mask;
+       unsigned long long cow_offset;
+       unsigned long bitmap_words[2];
        int error;
 };
 
@@ -82,31 +80,28 @@ extern int create_cow_file(char *cow_file, char *backing_file,
                           unsigned long *bitmap_len_out,
                           int *data_offset_out);
 extern int read_cow_bitmap(int fd, void *buf, int offset, int len);
-extern void do_io(struct io_thread_req *req, struct request *r,
-                 unsigned long *bitmap);
+extern void do_io(struct io_thread_req *req);
 
-static inline int ubd_test_bit(__u64 bit, void *data)
+static inline int ubd_test_bit(__u64 bit, unsigned char *data)
 {
-       unsigned char *buffer = data;
        __u64 n;
        int bits, off;
 
-       bits = sizeof(buffer[0]) * 8;
+       bits = sizeof(data[0]) * 8;
        n = bit / bits;
        off = bit % bits;
-       return((buffer[n] & (1 << off)) != 0);
+       return((data[n] & (1 << off)) != 0);
 }
 
-static inline void ubd_set_bit(__u64 bit, void *data)
+static inline void ubd_set_bit(__u64 bit, unsigned char *data)
 {
-       unsigned char *buffer = data;
        __u64 n;
        int bits, off;
 
-       bits = sizeof(buffer[0]) * 8;
+       bits = sizeof(data[0]) * 8;
        n = bit / bits;
        off = bit % bits;
-       buffer[n] |= (1 << off);
+       data[n] |= (1 << off);
 }
 /*End stuff from ubd_user.h*/
 
@@ -115,6 +110,8 @@ static inline void ubd_set_bit(__u64 bit, void *data)
 static DEFINE_SPINLOCK(ubd_io_lock);
 static DEFINE_SPINLOCK(ubd_lock);
 
+static void (*do_ubd)(void);
+
 static int ubd_open(struct inode * inode, struct file * filp);
 static int ubd_release(struct inode * inode, struct file * file);
 static int ubd_ioctl(struct inode * inode, struct file * file,
@@ -161,8 +158,6 @@ struct cow {
         int data_offset;
 };
 
-#define MAX_SG 64
-
 struct ubd {
        char *file;
        int count;
@@ -173,7 +168,6 @@ struct ubd {
        int no_cow;
        struct cow cow;
        struct platform_device pdev;
-        struct scatterlist sg[MAX_SG];
 };
 
 #define DEFAULT_COW { \
@@ -466,114 +460,81 @@ __uml_help(fakehd,
 );
 
 static void do_ubd_request(request_queue_t * q);
-static int in_ubd;
+
+/* Only changed by ubd_init, which is an initcall. */
+int thread_fd = -1;
 
 /* Changed by ubd_handler, which is serialized because interrupts only
  * happen on CPU 0.
  */
 int intr_count = 0;
 
-static void ubd_end_request(struct request *req, int bytes, int uptodate)
+/* call ubd_finish if you need to serialize */
+static void __ubd_finish(struct request *req, int error)
 {
-       if (!end_that_request_first(req, uptodate, bytes >> 9)) {
-               add_disk_randomness(req->rq_disk);
-               end_that_request_last(req);
+       int nsect;
+
+       if(error){
+               end_request(req, 0);
+               return;
        }
+       nsect = req->current_nr_sectors;
+       req->sector += nsect;
+       req->buffer += nsect << 9;
+       req->errors = 0;
+       req->nr_sectors -= nsect;
+       req->current_nr_sectors = 0;
+       end_request(req, 1);
 }
 
-/* call ubd_finish if you need to serialize */
-static void __ubd_finish(struct request *req, int bytes)
+static inline void ubd_finish(struct request *req, int error)
 {
-       if(bytes < 0){
-               ubd_end_request(req, 0, 0);
-               return;
-       }
-
-       ubd_end_request(req, bytes, 1);
+       spin_lock(&ubd_io_lock);
+       __ubd_finish(req, error);
+       spin_unlock(&ubd_io_lock);
 }
 
-static inline void ubd_finish(struct request *req, int bytes)
+/* Called without ubd_io_lock held */
+static void ubd_handler(void)
 {
-       spin_lock(&ubd_io_lock);
-       __ubd_finish(req, bytes);
-       spin_unlock(&ubd_io_lock);
+       struct io_thread_req req;
+       struct request *rq = elv_next_request(ubd_queue);
+       int n;
+
+       do_ubd = NULL;
+       intr_count++;
+       n = os_read_file(thread_fd, &req, sizeof(req));
+       if(n != sizeof(req)){
+               printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
+                      "err = %d\n", os_getpid(), -n);
+               spin_lock(&ubd_io_lock);
+               end_request(rq, 0);
+               spin_unlock(&ubd_io_lock);
+               return;
+       }
+        
+       ubd_finish(rq, req.error);
+       reactivate_fd(thread_fd, UBD_IRQ);      
+       do_ubd_request(ubd_queue);
 }
 
-struct bitmap_io {
-        atomic_t count;
-        struct aio_context aio;
-};
-
-struct ubd_aio {
-        struct aio_context aio;
-        struct request *req;
-        int len;
-        struct bitmap_io *bitmap;
-        void *bitmap_buf;
-};
-
-static int ubd_reply_fd = -1;
-
 static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused)
 {
-       struct aio_thread_reply reply;
-       struct ubd_aio *aio;
-       struct request *req;
-       int err, n, fd = (int) (long) dev;
-
-       while(1){
-               err = os_read_file(fd, &reply, sizeof(reply));
-               if(err == -EAGAIN)
-                       break;
-               if(err < 0){
-                       printk("ubd_aio_handler - read returned err %d\n",
-                              -err);
-                       break;
-               }
-
-                aio = container_of(reply.data, struct ubd_aio, aio);
-                n = reply.err;
-
-               if(n == 0){
-                       req = aio->req;
-                       req->nr_sectors -= aio->len >> 9;
-
-                       if((aio->bitmap != NULL) &&
-                          (atomic_dec_and_test(&aio->bitmap->count))){
-                                aio->aio = aio->bitmap->aio;
-                                aio->len = 0;
-                                kfree(aio->bitmap);
-                                aio->bitmap = NULL;
-                                submit_aio(&aio->aio);
-                       }
-                       else {
-                               if((req->nr_sectors == 0) &&
-                                   (aio->bitmap == NULL)){
-                                       int len = req->hard_nr_sectors << 9;
-                                       ubd_finish(req, len);
-                               }
-
-                                if(aio->bitmap_buf != NULL)
-                                        kfree(aio->bitmap_buf);
-                               kfree(aio);
-                       }
-               }
-                else if(n < 0){
-                        ubd_finish(aio->req, n);
-                        if(aio->bitmap != NULL)
-                                kfree(aio->bitmap);
-                        if(aio->bitmap_buf != NULL)
-                                kfree(aio->bitmap_buf);
-                        kfree(aio);
-                }
-       }
-       reactivate_fd(fd, UBD_IRQ);
+       ubd_handler();
+       return(IRQ_HANDLED);
+}
 
-        do_ubd_request(ubd_queue);
+/* Only changed by ubd_init, which is an initcall. */
+static int io_pid = -1;
 
-       return(IRQ_HANDLED);
+void kill_io_thread(void)
+{
+       if(io_pid != -1) 
+               os_kill_process(io_pid, 1);
 }
 
+__uml_exitcall(kill_io_thread);
+
 static int ubd_file_size(struct ubd *dev, __u64 *size_out)
 {
        char *file;
@@ -608,7 +569,7 @@ static int ubd_open_dev(struct ubd *dev)
                                &dev->cow.data_offset, create_ptr);
 
        if((dev->fd == -ENOENT) && create_cow){
-               dev->fd = create_cow_file(dev->file, dev->cow.file,
+               dev->fd = create_cow_file(dev->file, dev->cow.file, 
                                          dev->openflags, 1 << 9, PAGE_SIZE,
                                          &dev->cow.bitmap_offset, 
                                          &dev->cow.bitmap_len,
@@ -870,10 +831,6 @@ int ubd_init(void)
 {
         int i;
 
-       ubd_reply_fd = init_aio_irq(UBD_IRQ, "ubd", ubd_intr);
-       if(ubd_reply_fd < 0)
-               printk("Setting up ubd AIO failed, err = %d\n", ubd_reply_fd);
-
        devfs_mk_dir("ubd");
        if (register_blkdev(MAJOR_NR, "ubd"))
                return -1;
@@ -884,7 +841,6 @@ int ubd_init(void)
                return -1;
        }
                
-       blk_queue_max_hw_segments(ubd_queue, MAX_SG);
        if (fake_major != MAJOR_NR) {
                char name[sizeof("ubd_nnn\0")];
 
@@ -896,12 +852,40 @@ int ubd_init(void)
        driver_register(&ubd_driver);
        for (i = 0; i < MAX_DEV; i++) 
                ubd_add(i);
-
        return 0;
 }
 
 late_initcall(ubd_init);
 
+int ubd_driver_init(void){
+       unsigned long stack;
+       int err;
+
+       /* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/
+       if(global_openflags.s){
+               printk(KERN_INFO "ubd: Synchronous mode\n");
+               /* Letting ubd=sync be like using ubd#s= instead of ubd#= is
+                * enough. So use anyway the io thread. */
+       }
+       stack = alloc_stack(0, 0);
+       io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), 
+                                &thread_fd);
+       if(io_pid < 0){
+               printk(KERN_ERR 
+                      "ubd : Failed to start I/O thread (errno = %d) - "
+                      "falling back to synchronous I/O\n", -io_pid);
+               io_pid = -1;
+               return(0);
+       }
+       err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, 
+                            SA_INTERRUPT, "ubd", ubd_dev);
+       if(err != 0)
+               printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
+       return(err);
+}
+
+device_initcall(ubd_driver_init);
+
 static int ubd_open(struct inode *inode, struct file *filp)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
@@ -939,55 +923,105 @@ static int ubd_release(struct inode * inode, struct file * file)
        return(0);
 }
 
-static void cowify_bitmap(struct io_thread_req *req, unsigned long *bitmap)
+static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
+                         __u64 *cow_offset, unsigned long *bitmap,
+                         __u64 bitmap_offset, unsigned long *bitmap_words,
+                         __u64 bitmap_len)
 {
-        __u64 sector = req->offset / req->sectorsize;
-        int i;
+       __u64 sector = io_offset >> 9;
+       int i, update_bitmap = 0;
+
+       for(i = 0; i < length >> 9; i++){
+               if(cow_mask != NULL)
+                       ubd_set_bit(i, (unsigned char *) cow_mask);
+               if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
+                       continue;
 
-        for(i = 0; i < req->length / req->sectorsize; i++){
-                if(ubd_test_bit(sector + i, bitmap))
-                        continue;
+               update_bitmap = 1;
+               ubd_set_bit(sector + i, (unsigned char *) bitmap);
+       }
+
+       if(!update_bitmap)
+               return;
 
-                if(req->bitmap_start == -1)
-                        req->bitmap_start = sector + i;
-                req->bitmap_end = sector + i + 1;
+       *cow_offset = sector / (sizeof(unsigned long) * 8);
 
-                ubd_set_bit(sector + i, bitmap);
-        }
+       /* This takes care of the case where we're exactly at the end of the
+        * device, and *cow_offset + 1 is off the end.  So, just back it up
+        * by one word.  Thanks to Lynn Kerby for the fix and James McMechan
+        * for the original diagnosis.
+        */
+       if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) /
+                          sizeof(unsigned long) - 1))
+               (*cow_offset)--;
+
+       bitmap_words[0] = bitmap[*cow_offset];
+       bitmap_words[1] = bitmap[*cow_offset + 1];
+
+       *cow_offset *= sizeof(unsigned long);
+       *cow_offset += bitmap_offset;
+}
+
+static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
+                      __u64 bitmap_offset, __u64 bitmap_len)
+{
+       __u64 sector = req->offset >> 9;
+       int i;
+
+       if(req->length > (sizeof(req->sector_mask) * 8) << 9)
+               panic("Operation too long");
+
+       if(req->op == UBD_READ) {
+               for(i = 0; i < req->length >> 9; i++){
+                       if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
+                               ubd_set_bit(i, (unsigned char *) 
+                                           &req->sector_mask);
+                }
+       }
+       else cowify_bitmap(req->offset, req->length, &req->sector_mask,
+                          &req->cow_offset, bitmap, bitmap_offset,
+                          req->bitmap_words, bitmap_len);
 }
 
 /* Called with ubd_io_lock held */
-static int prepare_request(struct request *req, struct io_thread_req *io_req,
-                           unsigned long long offset, int page_offset,
-                           int len, struct page *page)
+static int prepare_request(struct request *req, struct io_thread_req *io_req)
 {
        struct gendisk *disk = req->rq_disk;
        struct ubd *dev = disk->private_data;
+       __u64 offset;
+       int len;
+
+       if(req->rq_status == RQ_INACTIVE) return(1);
 
        /* This should be impossible now */
        if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
                printk("Write attempted on readonly ubd device %s\n", 
                       disk->disk_name);
-                ubd_end_request(req, 0, 0);
+               end_request(req, 0);
                return(1);
        }
 
+       offset = ((__u64) req->sector) << 9;
+       len = req->current_nr_sectors << 9;
+
        io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
        io_req->fds[1] = dev->fd;
+       io_req->cow_offset = -1;
        io_req->offset = offset;
        io_req->length = len;
        io_req->error = 0;
-       io_req->op = (rq_data_dir(req) == READ) ? AIO_READ : AIO_WRITE;
+       io_req->sector_mask = 0;
+
+       io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
        io_req->offsets[0] = 0;
        io_req->offsets[1] = dev->cow.data_offset;
-        io_req->buffer = page_address(page) + page_offset;
+       io_req->buffer = req->buffer;
        io_req->sectorsize = 1 << 9;
-        io_req->bitmap_offset = dev->cow.bitmap_offset;
-        io_req->bitmap_start = -1;
-        io_req->bitmap_end = -1;
 
-        if((dev->cow.file != NULL) && (io_req->op == UBD_WRITE))
-                cowify_bitmap(io_req, dev->cow.bitmap);
+       if(dev->cow.file != NULL)
+               cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset,
+                          dev->cow.bitmap_len);
+
        return(0);
 }
 
@@ -996,36 +1030,30 @@ static void do_ubd_request(request_queue_t *q)
 {
        struct io_thread_req io_req;
        struct request *req;
-       __u64 sector;
-       int err;
-
-       if(in_ubd)
-               return;
-       in_ubd = 1;
-       while((req = elv_next_request(q)) != NULL){
-               struct gendisk *disk = req->rq_disk;
-               struct ubd *dev = disk->private_data;
-               int n, i;
-
-               blkdev_dequeue_request(req);
-
-               sector = req->sector;
-               n = blk_rq_map_sg(q, req, dev->sg);
-
-               for(i = 0; i < n; i++){
-                       struct scatterlist *sg = &dev->sg[i];
-
-                       err = prepare_request(req, &io_req, sector << 9,
-                                             sg->offset, sg->length,
-                                             sg->page);
-                       if(err)
-                               continue;
-
-                       sector += sg->length >> 9;
-                       do_io(&io_req, req, dev->cow.bitmap);
+       int err, n;
+
+       if(thread_fd == -1){
+               while((req = elv_next_request(q)) != NULL){
+                       err = prepare_request(req, &io_req);
+                       if(!err){
+                               do_io(&io_req);
+                               __ubd_finish(req, io_req.error);
+                       }
+               }
+       }
+       else {
+               if(do_ubd || (req = elv_next_request(q)) == NULL)
+                       return;
+               err = prepare_request(req, &io_req);
+               if(!err){
+                       do_ubd = ubd_handler;
+                       n = os_write_file(thread_fd, (char *) &io_req,
+                                        sizeof(io_req));
+                       if(n != sizeof(io_req))
+                               printk("write to io thread failed, "
+                                      "errno = %d\n", -n);
                }
        }
-       in_ubd = 0;
 }
 
 static int ubd_ioctl(struct inode * inode, struct file * file,
@@ -1241,95 +1269,131 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
        return(err);
 }
 
-void do_io(struct io_thread_req *req, struct request *r, unsigned long *bitmap)
+static int update_bitmap(struct io_thread_req *req)
 {
-        struct ubd_aio *aio;
-        struct bitmap_io *bitmap_io = NULL;
-        char *buf;
-        void *bitmap_buf = NULL;
-        unsigned long len, sector;
-        int nsectors, start, end, bit, err;
-        __u64 off;
-
-        if(req->bitmap_start != -1){
-                /* Round up to the nearest word */
-                int round = sizeof(unsigned long);
-                len = (req->bitmap_end - req->bitmap_start +
-                       round * 8 - 1) / (round * 8);
-                len *= round;
-
-                off = req->bitmap_start / (8 * round);
-                off *= round;
-
-                bitmap_io = kmalloc(sizeof(*bitmap_io), GFP_KERNEL);
-                if(bitmap_io == NULL){
-                        printk("Failed to kmalloc bitmap IO\n");
-                        req->error = 1;
-                        return;
-                }
+       int n;
 
-                bitmap_buf = kmalloc(len, GFP_KERNEL);
-                if(bitmap_buf == NULL){
-                        printk("do_io : kmalloc of bitmap chunk "
-                               "failed\n");
-                        kfree(bitmap_io);
-                        req->error = 1;
-                        return;
-                }
-                memcpy(bitmap_buf, &bitmap[off / sizeof(bitmap[0])], len);
-
-                *bitmap_io = ((struct bitmap_io)
-                        { .count       = ATOMIC_INIT(0),
-                          .aio         = INIT_AIO(AIO_WRITE, req->fds[1],
-                                                   bitmap_buf, len,
-                                                   req->bitmap_offset + off,
-                                                   ubd_reply_fd) } );
-        }
+       if(req->cow_offset == -1)
+               return(0);
 
-        nsectors = req->length / req->sectorsize;
-        start = 0;
-        end = nsectors;
-        bit = 0;
-        do {
-                if(bitmap != NULL){
-                        sector = req->offset / req->sectorsize;
-                        bit = ubd_test_bit(sector + start, bitmap);
-                        end = start;
-                        while((end < nsectors) &&
-                              (ubd_test_bit(sector + end, bitmap) == bit))
-                                end++;
-                }
+       n = os_seek_file(req->fds[1], req->cow_offset);
+       if(n < 0){
+               printk("do_io - bitmap lseek failed : err = %d\n", -n);
+               return(1);
+       }
 
-                off = req->offsets[bit] + req->offset +
-                        start * req->sectorsize;
-                len = (end - start) * req->sectorsize;
-                buf = &req->buffer[start * req->sectorsize];
+       n = os_write_file(req->fds[1], &req->bitmap_words,
+                         sizeof(req->bitmap_words));
+       if(n != sizeof(req->bitmap_words)){
+               printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
+                      req->fds[1]);
+               return(1);
+       }
 
-                aio = kmalloc(sizeof(*aio), GFP_KERNEL);
-                if(aio == NULL){
-                        req->error = 1;
-                        return;
-                }
+       return(0);
+}
 
-                *aio = ((struct ubd_aio)
-                        { .aio         = INIT_AIO(req->op, req->fds[bit], buf,
-                                                   len, off, ubd_reply_fd),
-                          .len         = len,
-                          .req         = r,
-                          .bitmap      = bitmap_io,
-                          .bitmap_buf  = bitmap_buf });
-
-                if(aio->bitmap != NULL)
-                        atomic_inc(&aio->bitmap->count);
-
-                err = submit_aio(&aio->aio);
-                if(err){
-                        printk("do_io - submit_aio failed, "
-                               "err = %d\n", err);
-                        req->error = 1;
-                        return;
-                }
+void do_io(struct io_thread_req *req)
+{
+       char *buf;
+       unsigned long len;
+       int n, nsectors, start, end, bit;
+       int err;
+       __u64 off;
+
+       nsectors = req->length / req->sectorsize;
+       start = 0;
+       do {
+               bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask);
+               end = start;
+               while((end < nsectors) &&
+                     (ubd_test_bit(end, (unsigned char *)
+                                   &req->sector_mask) == bit))
+                       end++;
+
+               off = req->offset + req->offsets[bit] +
+                       start * req->sectorsize;
+               len = (end - start) * req->sectorsize;
+               buf = &req->buffer[start * req->sectorsize];
+
+               err = os_seek_file(req->fds[bit], off);
+               if(err < 0){
+                       printk("do_io - lseek failed : err = %d\n", -err);
+                       req->error = 1;
+                       return;
+               }
+               if(req->op == UBD_READ){
+                       n = 0;
+                       do {
+                               buf = &buf[n];
+                               len -= n;
+                               n = os_read_file(req->fds[bit], buf, len);
+                               if (n < 0) {
+                                       printk("do_io - read failed, err = %d "
+                                              "fd = %d\n", -n, req->fds[bit]);
+                                       req->error = 1;
+                                       return;
+                               }
+                       } while((n < len) && (n != 0));
+                       if (n < len) memset(&buf[n], 0, len - n);
+               } else {
+                       n = os_write_file(req->fds[bit], buf, len);
+                       if(n != len){
+                               printk("do_io - write failed err = %d "
+                                      "fd = %d\n", -n, req->fds[bit]);
+                               req->error = 1;
+                               return;
+                       }
+               }
+
+               start = end;
+       } while(start < nsectors);
 
-                start = end;
-        } while(start < nsectors);
+       req->error = update_bitmap(req);
 }
+
+/* Changed in start_io_thread, which is serialized by being called only
+ * from ubd_init, which is an initcall.
+ */
+int kernel_fd = -1;
+
+/* Only changed by the io thread */
+int io_count = 0;
+
+int io_thread(void *arg)
+{
+       struct io_thread_req req;
+       int n;
+
+       ignore_sigwinch_sig();
+       while(1){
+               n = os_read_file(kernel_fd, &req, sizeof(req));
+               if(n != sizeof(req)){
+                       if(n < 0)
+                               printk("io_thread - read failed, fd = %d, "
+                                      "err = %d\n", kernel_fd, -n);
+                       else {
+                               printk("io_thread - short read, fd = %d, "
+                                      "length = %d\n", kernel_fd, n);
+                       }
+                       continue;
+               }
+               io_count++;
+               do_io(&req);
+               n = os_write_file(kernel_fd, &req, sizeof(req));
+               if(n != sizeof(req))
+                       printk("io_thread - write failed, fd = %d, err = %d\n",
+                              kernel_fd, -n);
+       }
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
new file mode 100644 (file)
index 0000000..b94d2bc
--- /dev/null
@@ -0,0 +1,75 @@
+/* 
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com)
+ * Licensed under the GPL
+ */
+
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sched.h>
+#include <signal.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include "asm/types.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "user.h"
+#include "ubd_user.h"
+#include "os.h"
+#include "cow.h"
+
+#include <endian.h>
+#include <byteswap.h>
+
+void ignore_sigwinch_sig(void)
+{
+       signal(SIGWINCH, SIG_IGN);
+}
+
+int start_io_thread(unsigned long sp, int *fd_out)
+{
+       int pid, fds[2], err;
+
+       err = os_pipe(fds, 1, 1);
+       if(err < 0){
+               printk("start_io_thread - os_pipe failed, err = %d\n", -err);
+               goto out;
+       }
+
+       kernel_fd = fds[0];
+       *fd_out = fds[1];
+
+       pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
+                   NULL);
+       if(pid < 0){
+               printk("start_io_thread - clone failed : errno = %d\n", errno);
+               err = -errno;
+               goto out_close;
+       }
+
+       return(pid);
+
+ out_close:
+       os_close_file(fds[0]);
+       os_close_file(fds[1]);
+       kernel_fd = -1;
+       *fd_out = -1;
+ out:
+       return(err);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
index 83f1687..423bae9 100644 (file)
@@ -14,27 +14,15 @@ struct aio_thread_reply {
 };
 
 struct aio_context {
-       enum aio_type type;
-       int fd;
-       void *data;
-       int len;
-       unsigned long long offset;
        int reply_fd;
        struct aio_context *next;
 };
 
-#define INIT_AIO(aio_type, aio_fd, aio_data, aio_len, aio_offset, \
-                aio_reply_fd) \
-       { .type         = aio_type, \
-         .fd           = aio_fd, \
-         .data         = aio_data, \
-         .len          = aio_len, \
-         .offset       = aio_offset, \
-         .reply_fd     = aio_reply_fd }
-
 #define INIT_AIO_CONTEXT { .reply_fd   = -1, \
                           .next        = NULL }
 
-extern int submit_aio(struct aio_context *aio);
+extern int submit_aio(enum aio_type type, int fd, char *buf, int len,
+                     unsigned long long offset, int reply_fd,
+                      struct aio_context *aio);
 
 #endif
index 6f766e1..2e58e30 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef __OS_H__
 #define __OS_H__
 
+#include "uml-config.h"
 #include "asm/types.h"
 #include "../os/include/file.h"
 
@@ -159,7 +160,11 @@ extern int can_do_skas(void);
 
 /* Make sure they are clear when running in TT mode. Required by
  * SEGV_MAYBE_FIXABLE */
+#ifdef UML_CONFIG_MODE_SKAS
 #define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
+#else
+#define clear_can_do_skas() do {} while (0)
+#endif
 
 /* mem.c */
 extern int create_mem_file(unsigned long len);
index f6e6402..41cfb09 100644 (file)
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <signal.h>
-#include <string.h>
 #include <errno.h>
 #include <sched.h>
 #include <sys/syscall.h>
 #include "user.h"
 #include "mode.h"
 
+struct aio_thread_req {
+        enum aio_type type;
+        int io_fd;
+        unsigned long long offset;
+        char *buf;
+        int len;
+        struct aio_context *aio;
+};
+
 static int aio_req_fd_r = -1;
 static int aio_req_fd_w = -1;
 
-static int update_aio(struct aio_context *aio, int res)
-{
-        if(res < 0)
-                aio->len = res;
-        else if((res == 0) && (aio->type == AIO_READ)){
-                /* This is the EOF case - we have hit the end of the file
-                 * and it ends in a partial block, so we fill the end of
-                 * the block with zeros and claim success.
-                 */
-                memset(aio->data, 0, aio->len);
-                aio->len = 0;
-        }
-        else if(res > 0){
-                aio->len -= res;
-                aio->data += res;
-                aio->offset += res;
-                return aio->len;
-        }
-
-        return 0;
-}
-
 #if defined(HAVE_AIO_ABI)
 #include <linux/aio_abi.h>
 
@@ -80,7 +66,8 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
  * that it now backs the mmapped area.
  */
 
-static int do_aio(aio_context_t ctx, struct aio_context *aio)
+static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
+                  int len, unsigned long long offset, struct aio_context *aio)
 {
         struct iocb iocb, *iocbp = &iocb;
         char c;
@@ -88,39 +75,40 @@ static int do_aio(aio_context_t ctx, struct aio_context *aio)
 
         iocb = ((struct iocb) { .aio_data      = (unsigned long) aio,
                                 .aio_reqprio   = 0,
-                                .aio_fildes    = aio->fd,
-                                .aio_buf       = (unsigned long) aio->data,
-                                .aio_nbytes    = aio->len,
-                                .aio_offset    = aio->offset,
+                                .aio_fildes    = fd,
+                                .aio_buf       = (unsigned long) buf,
+                                .aio_nbytes    = len,
+                                .aio_offset    = offset,
                                 .aio_reserved1 = 0,
                                 .aio_reserved2 = 0,
                                 .aio_reserved3 = 0 });
 
-        switch(aio->type){
+        switch(type){
         case AIO_READ:
                 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
+                err = io_submit(ctx, 1, &iocbp);
                 break;
         case AIO_WRITE:
                 iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
+                err = io_submit(ctx, 1, &iocbp);
                 break;
         case AIO_MMAP:
                 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
                 iocb.aio_buf = (unsigned long) &c;
                 iocb.aio_nbytes = sizeof(c);
+                err = io_submit(ctx, 1, &iocbp);
                 break;
         default:
-                printk("Bogus op in do_aio - %d\n", aio->type);
+                printk("Bogus op in do_aio - %d\n", type);
                 err = -EINVAL;
-                goto out;
+                break;
         }
 
-        err = io_submit(ctx, 1, &iocbp);
         if(err > 0)
                 err = 0;
        else
                err = -errno;
 
- out:
         return err;
 }
 
@@ -129,9 +117,8 @@ static aio_context_t ctx = 0;
 static int aio_thread(void *arg)
 {
         struct aio_thread_reply reply;
-        struct aio_context *aio;
         struct io_event event;
-        int err, n;
+        int err, n, reply_fd;
 
         signal(SIGWINCH, SIG_IGN);
 
@@ -144,22 +131,14 @@ static int aio_thread(void *arg)
                                "errno = %d\n", errno);
                 }
                 else {
-                       /* This is safe as we've just a pointer here. */
-                       aio = (struct aio_context *) (long) event.data;
-                       if(update_aio(aio, event.res)){
-                               do_aio(ctx, aio);
-                               continue;
-                       }
-
                         reply = ((struct aio_thread_reply)
-                               { .data = aio,
-                                 .err  = aio->len });
-                       err = os_write_file(aio->reply_fd, &reply,
-                                           sizeof(reply));
+                                { .data = (void *) (long) event.data,
+                                  .err = event.res });
+                       reply_fd = ((struct aio_context *) reply.data)->reply_fd;
+                       err = os_write_file(reply_fd, &reply, sizeof(reply));
                         if(err != sizeof(reply))
-                               printk("aio_thread - write failed, "
-                                      "fd = %d, err = %d\n", aio->reply_fd,
-                                      -err);
+                               printk("aio_thread - write failed, fd = %d, "
+                                       "err = %d\n", aio_req_fd_r, -err);
                 }
         }
         return 0;
@@ -167,35 +146,35 @@ static int aio_thread(void *arg)
 
 #endif
 
-static int do_not_aio(struct aio_context *aio)
+static int do_not_aio(struct aio_thread_req *req)
 {
         char c;
         int err;
 
-        switch(aio->type){
+        switch(req->type){
         case AIO_READ:
-                err = os_seek_file(aio->fd, aio->offset);
+                err = os_seek_file(req->io_fd, req->offset);
                 if(err)
                         goto out;
 
-                err = os_read_file(aio->fd, aio->data, aio->len);
+                err = os_read_file(req->io_fd, req->buf, req->len);
                 break;
         case AIO_WRITE:
-                err = os_seek_file(aio->fd, aio->offset);
+                err = os_seek_file(req->io_fd, req->offset);
                 if(err)
                         goto out;
 
-                err = os_write_file(aio->fd, aio->data, aio->len);
+                err = os_write_file(req->io_fd, req->buf, req->len);
                 break;
         case AIO_MMAP:
-                err = os_seek_file(aio->fd, aio->offset);
+                err = os_seek_file(req->io_fd, req->offset);
                 if(err)
                         goto out;
 
-                err = os_read_file(aio->fd, &c, sizeof(c));
+                err = os_read_file(req->io_fd, &c, sizeof(c));
                 break;
         default:
-                printk("do_not_aio - bad request type : %d\n", aio->type);
+                printk("do_not_aio - bad request type : %d\n", req->type);
                 err = -EINVAL;
                 break;
         }
@@ -206,14 +185,14 @@ static int do_not_aio(struct aio_context *aio)
 
 static int not_aio_thread(void *arg)
 {
-        struct aio_context *aio;
+        struct aio_thread_req req;
         struct aio_thread_reply reply;
         int err;
 
         signal(SIGWINCH, SIG_IGN);
         while(1){
-                err = os_read_file(aio_req_fd_r, &aio, sizeof(aio));
-                if(err != sizeof(aio)){
+                err = os_read_file(aio_req_fd_r, &req, sizeof(req));
+                if(err != sizeof(req)){
                         if(err < 0)
                                 printk("not_aio_thread - read failed, "
                                        "fd = %d, err = %d\n", aio_req_fd_r,
@@ -224,34 +203,17 @@ static int not_aio_thread(void *arg)
                         }
                         continue;
                 }
- again:
-                err = do_not_aio(aio);
-
-                if(update_aio(aio, err))
-                        goto again;
-
-                reply = ((struct aio_thread_reply) { .data     = aio,
-                                                     .err      = aio->len });
-                err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
+                err = do_not_aio(&req);
+                reply = ((struct aio_thread_reply) { .data     = req.aio,
+                                                     .err      = err });
+                err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply));
                 if(err != sizeof(reply))
                         printk("not_aio_thread - write failed, fd = %d, "
                                "err = %d\n", aio_req_fd_r, -err);
         }
 }
 
-static int submit_aio_24(struct aio_context *aio)
-{
-        int err;
-
-        err = os_write_file(aio_req_fd_w, &aio, sizeof(aio));
-        if(err == sizeof(aio))
-                err = 0;
-
-        return err;
-}
-
 static int aio_pid = -1;
-static int (*submit_proc)(struct aio_context *aio);
 
 static int init_aio_24(void)
 {
@@ -283,33 +245,11 @@ static int init_aio_24(void)
 #endif
        printk("2.6 host AIO support not used - falling back to I/O "
               "thread\n");
-
-       submit_proc = submit_aio_24;
-
         return 0;
 }
 
 #ifdef HAVE_AIO_ABI
 #define DEFAULT_24_AIO 0
-static int submit_aio_26(struct aio_context *aio)
-{
-       struct aio_thread_reply reply;
-       int err;
-
-       err = do_aio(ctx, aio);
-       if(err){
-               reply = ((struct aio_thread_reply) { .data = aio,
-                                                    .err  = err });
-               err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
-               if(err != sizeof(reply))
-                       printk("submit_aio_26 - write failed, "
-                              "fd = %d, err = %d\n", aio->reply_fd, -err);
-               else err = 0;
-       }
-
-       return err;
-}
-
 static int init_aio_26(void)
 {
         unsigned long stack;
@@ -330,22 +270,39 @@ static int init_aio_26(void)
         aio_pid = err;
 
        printk("Using 2.6 host AIO\n");
+        return 0;
+}
+
+static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
+                        unsigned long long offset, struct aio_context *aio)
+{
+        struct aio_thread_reply reply;
+        int err;
 
-       submit_proc = submit_aio_26;
+        err = do_aio(ctx, type, io_fd, buf, len, offset, aio);
+        if(err){
+                reply = ((struct aio_thread_reply) { .data = aio,
+                                                     .err  = err });
+                err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
+                if(err != sizeof(reply))
+                        printk("submit_aio_26 - write failed, "
+                               "fd = %d, err = %d\n", aio->reply_fd, -err);
+                else err = 0;
+        }
 
-        return 0;
+        return err;
 }
 
 #else
 #define DEFAULT_24_AIO 1
-static int submit_aio_26(struct aio_context *aio)
+static int init_aio_26(void)
 {
         return -ENOSYS;
 }
 
-static int init_aio_26(void)
+static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
+                        unsigned long long offset, struct aio_context *aio)
 {
-       submit_proc = submit_aio_26;
         return -ENOSYS;
 }
 #endif
@@ -412,7 +369,33 @@ static void exit_aio(void)
 
 __uml_exitcall(exit_aio);
 
-int submit_aio(struct aio_context *aio)
+static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
+                        unsigned long long offset, struct aio_context *aio)
 {
-       return (*submit_proc)(aio);
+        struct aio_thread_req req = { .type            = type,
+                                      .io_fd           = io_fd,
+                                      .offset          = offset,
+                                      .buf             = buf,
+                                      .len             = len,
+                                      .aio             = aio,
+        };
+        int err;
+
+        err = os_write_file(aio_req_fd_w, &req, sizeof(req));
+        if(err == sizeof(req))
+                err = 0;
+
+        return err;
+}
+
+int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
+               unsigned long long offset, int reply_fd,
+               struct aio_context *aio)
+{
+        aio->reply_fd = reply_fd;
+        if(aio_24)
+                return submit_aio_24(type, io_fd, buf, len, offset, aio);
+        else {
+                return submit_aio_26(type, io_fd, buf, len, offset, aio);
+        }
 }
index b667823..4f4ba9b 100644 (file)
@@ -50,7 +50,7 @@
 MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
 MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("2.0");
+MODULE_VERSION("3.0");
 
 #define BIOS_SCAN_LIMIT 0xffffffff
 #define MAX_IMAGE_LENGTH 16
@@ -62,15 +62,16 @@ static struct _rbu_data {
        int dma_alloc;
        spinlock_t lock;
        unsigned long packet_read_count;
-       unsigned long packet_write_count;
        unsigned long num_packets;
        unsigned long packetsize;
+       unsigned long imagesize;
        int entry_created;
 } rbu_data;
 
 static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";
 module_param_string(image_type, image_type, sizeof (image_type), 0);
-MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet");
+MODULE_PARM_DESC(image_type,
+       "BIOS image type. choose- mono or packet or init");
 
 struct packet_data {
        struct list_head list;
@@ -88,55 +89,13 @@ static dma_addr_t dell_rbu_dmaaddr;
 static void init_packet_head(void)
 {
        INIT_LIST_HEAD(&packet_data_head.list);
-       rbu_data.packet_write_count = 0;
        rbu_data.packet_read_count = 0;
        rbu_data.num_packets = 0;
        rbu_data.packetsize = 0;
+       rbu_data.imagesize = 0;
 }
 
-static int fill_last_packet(void *data, size_t length)
-{
-       struct list_head *ptemp_list;
-       struct packet_data *packet = NULL;
-       int packet_count = 0;
-
-       pr_debug("fill_last_packet: entry \n");
-
-       if (!rbu_data.num_packets) {
-               pr_debug("fill_last_packet: num_packets=0\n");
-               return -ENOMEM;
-       }
-
-       packet_count = rbu_data.num_packets;
-
-       ptemp_list = (&packet_data_head.list)->prev;
-
-       packet = list_entry(ptemp_list, struct packet_data, list);
-
-       if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) {
-               pr_debug("dell_rbu:%s: packet size data "
-                       "overrun\n", __FUNCTION__);
-               return -EINVAL;
-       }
-
-       pr_debug("fill_last_packet : buffer = %p\n", packet->data);
-
-       memcpy((packet->data + rbu_data.packet_write_count), data, length);
-
-       if ((rbu_data.packet_write_count + length) == rbu_data.packetsize) {
-               /*
-                * this was the last data chunk in the packet
-                * so reinitialize the packet data counter to zero
-                */
-               rbu_data.packet_write_count = 0;
-       } else
-               rbu_data.packet_write_count += length;
-
-       pr_debug("fill_last_packet: exit \n");
-       return 0;
-}
-
-static int create_packet(size_t length)
+static int create_packet(void *data, size_t length)
 {
        struct packet_data *newpacket;
        int ordernum = 0;
@@ -186,9 +145,11 @@ static int create_packet(size_t length)
        INIT_LIST_HEAD(&newpacket->list);
        list_add_tail(&newpacket->list, &packet_data_head.list);
        /*
-        * packets have fixed size
+        * packets may not have fixed size
         */
-       newpacket->length = rbu_data.packetsize;
+       newpacket->length = length;
+
+       memcpy(newpacket->data, data, length);
 
        pr_debug("create_packet: exit \n");
 
@@ -198,13 +159,37 @@ static int create_packet(size_t length)
 static int packetize_data(void *data, size_t length)
 {
        int rc = 0;
+       int done = 0;
+       int packet_length;
+       u8 *temp;
+       u8 *end = (u8 *) data + length;
+       pr_debug("packetize_data: data length %d\n", length);
+       if (!rbu_data.packetsize) {
+               printk(KERN_WARNING
+                       "dell_rbu: packetsize not specified\n");
+               return -EIO;
+       }
 
-       if (!rbu_data.packet_write_count) {
-               if ((rc = create_packet(length)))
+       temp = (u8 *) data;
+
+       /* packetize the hunk */
+       while (!done) {
+               if ((temp + rbu_data.packetsize) < end)
+                       packet_length = rbu_data.packetsize;
+               else {
+                       /* this is the last packet */
+                       packet_length = end - temp;
+                       done = 1;
+               }
+
+               if ((rc = create_packet(temp, packet_length)))
                        return rc;
+
+               pr_debug("%lu:%lu\n", temp, (end - temp));
+               temp += packet_length;
        }
-       if ((rc = fill_last_packet(data, length)))
-               return rc;
+
+       rbu_data.imagesize = length;
 
        return rc;
 }
@@ -243,7 +228,7 @@ static int do_packet_read(char *data, struct list_head *ptemp_list,
        return bytes_copied;
 }
 
-static int packet_read_list(char *data, size_t *pread_length)
+static int packet_read_list(char *data, size_t * pread_length)
 {
        struct list_head *ptemp_list;
        int temp_count = 0;
@@ -303,10 +288,9 @@ static void packet_empty_list(void)
                        newpacket->ordernum);
                kfree(newpacket);
        }
-       rbu_data.packet_write_count = 0;
        rbu_data.packet_read_count = 0;
        rbu_data.num_packets = 0;
-       rbu_data.packetsize = 0;
+       rbu_data.imagesize = 0;
 }
 
 /*
@@ -425,7 +409,6 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
        size_t bytes_left;
        size_t data_length;
        char *ptempBuf = buffer;
-       unsigned long imagesize;
 
        /* check to see if we have something to return */
        if (rbu_data.num_packets == 0) {
@@ -434,22 +417,20 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
                goto read_rbu_data_exit;
        }
 
-       imagesize = rbu_data.num_packets * rbu_data.packetsize;
-
-       if (pos > imagesize) {
+       if (pos > rbu_data.imagesize) {
                retval = 0;
                printk(KERN_WARNING "dell_rbu:read_packet_data: "
                        "data underrun\n");
                goto read_rbu_data_exit;
        }
 
-       bytes_left = imagesize - pos;
+       bytes_left = rbu_data.imagesize - pos;
        data_length = min(bytes_left, count);
 
        if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)
                goto read_rbu_data_exit;
 
-       if ((pos + count) > imagesize) {
+       if ((pos + count) > rbu_data.imagesize) {
                rbu_data.packet_read_count = 0;
                /* this was the last copy */
                retval = bytes_left;
@@ -499,7 +480,7 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
 }
 
 static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
-                       loff_t pos, size_t count)
+       loff_t pos, size_t count)
 {
        ssize_t ret_count = 0;
 
@@ -531,13 +512,18 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
                        memcpy(rbu_data.image_update_buffer,
                                fw->data, fw->size);
        } else if (!strcmp(image_type, "packet")) {
-               if (!rbu_data.packetsize)
-                       rbu_data.packetsize = fw->size;
-               else if (rbu_data.packetsize != fw->size) {
+               /*
+                * we need to free previous packets if a
+                * new hunk of packets needs to be downloaded
+                */
+               packet_empty_list();
+               if (packetize_data(fw->data, fw->size))
+                       /* Incase something goes wrong when we are
+                        * in middle of packetizing the data, we
+                        * need to free up whatever packets might
+                        * have been created before we quit.
+                        */
                        packet_empty_list();
-                       rbu_data.packetsize = fw->size;
-               }
-               packetize_data(fw->data, fw->size);
        } else
                pr_debug("invalid image type specified.\n");
        spin_unlock(&rbu_data.lock);
@@ -553,7 +539,7 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
 }
 
 static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
-                       loff_t pos, size_t count)
+       loff_t pos, size_t count)
 {
        int size = 0;
        if (!pos)
@@ -562,7 +548,7 @@ static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
 }
 
 static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
-                       loff_t pos, size_t count)
+       loff_t pos, size_t count)
 {
        int rc = count;
        int req_firm_rc = 0;
@@ -621,25 +607,49 @@ static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
        return rc;
 }
 
+static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer,
+       loff_t pos, size_t count)
+{
+       int size = 0;
+       if (!pos) {
+               spin_lock(&rbu_data.lock);
+               size = sprintf(buffer, "%lu\n", rbu_data.packetsize);
+               spin_unlock(&rbu_data.lock);
+       }
+       return size;
+}
+
+static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer,
+       loff_t pos, size_t count)
+{
+       unsigned long temp;
+       spin_lock(&rbu_data.lock);
+       packet_empty_list();
+       sscanf(buffer, "%lu", &temp);
+       if (temp < 0xffffffff)
+               rbu_data.packetsize = temp;
+
+       spin_unlock(&rbu_data.lock);
+       return count;
+}
+
 static struct bin_attribute rbu_data_attr = {
-       .attr = {
-               .name = "data",
-               .owner = THIS_MODULE,
-               .mode = 0444,
-       },
+       .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
        .read = read_rbu_data,
 };
 
 static struct bin_attribute rbu_image_type_attr = {
-       .attr = {
-               .name = "image_type",
-               .owner = THIS_MODULE,
-               .mode = 0644,
-       },
+       .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
        .read = read_rbu_image_type,
        .write = write_rbu_image_type,
 };
 
+static struct bin_attribute rbu_packet_size_attr = {
+       .attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644},
+       .read = read_rbu_packet_size,
+       .write = write_rbu_packet_size,
+};
+
 static int __init dcdrbu_init(void)
 {
        int rc = 0;
@@ -657,6 +667,8 @@ static int __init dcdrbu_init(void)
 
        sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
        sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
+       sysfs_create_bin_file(&rbu_device->dev.kobj,
+               &rbu_packet_size_attr);
 
        rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
                "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);
index 6c33280..0881a17 100644 (file)
@@ -2393,10 +2393,10 @@ struct tvcard bttv_tvcards[] = {
        .tuner          = 0,
        .tuner_type     = TUNER_LG_TDVS_H062F,
        .tuner_addr     = ADDR_UNSET,
-       .video_inputs   = 2,
+       .video_inputs   = 3,
        .audio_inputs   = 1,
        .svhs           = 2,
-       .muxsel         = { 2, 3 },
+       .muxsel         = { 2, 3, 1 },
        .gpiomask       = 0x00e00007,
        .audiomux       = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 },
        .no_msp34xx     = 1,
index fbf1c06..40887f0 100644 (file)
@@ -903,8 +903,8 @@ static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
 
 static void e100_get_defaults(struct nic *nic)
 {
-       struct param_range rfds = { .min = 16, .max = 256, .count = 256 };
-       struct param_range cbs  = { .min = 64, .max = 256, .count = 128 };
+       struct param_range rfds = { .min = 16, .max = 256, .count = 64 };
+       struct param_range cbs  = { .min = 64, .max = 256, .count = 64 };
 
        pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id);
        /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
@@ -1007,213 +1007,25 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
                c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
 }
 
-/********************************************************/
-/*  Micro code for 8086:1229 Rev 8                      */
-/********************************************************/
-
-/*  Parameter values for the D101M B-step  */
-#define D101M_CPUSAVER_TIMER_DWORD             78
-#define D101M_CPUSAVER_BUNDLE_DWORD            65
-#define D101M_CPUSAVER_MIN_SIZE_DWORD          126
-
-#define D101M_B_RCVBUNDLE_UCODE \
-{\
-0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \
-0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \
-0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \
-0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \
-0x00380438, 0x00000000, 0x00140000, 0x00380555, \
-0x00308000, 0x00100662, 0x00100561, 0x000E0408, \
-0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
-0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
-0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \
-0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \
-0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \
-0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \
-0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \
-0x00041000, 0x00010004, 0x00130826, 0x000C0006, \
-0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
-0x00101210, 0x00380C34, 0x00000000, 0x00000000, \
-0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \
-0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \
-0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \
-0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \
-0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \
-0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \
-0x00130826, 0x000C0001, 0x00220559, 0x00101313, \
-0x00380559, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00130831, 0x0010090B, 0x00124813, \
-0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \
-0x003806A8, 0x00000000, 0x00000000, 0x00000000, \
-}
-
-/********************************************************/
-/*  Micro code for 8086:1229 Rev 9                      */
-/********************************************************/
-
-/*  Parameter values for the D101S  */
-#define D101S_CPUSAVER_TIMER_DWORD             78
-#define D101S_CPUSAVER_BUNDLE_DWORD            67
-#define D101S_CPUSAVER_MIN_SIZE_DWORD          128
-
-#define D101S_RCVBUNDLE_UCODE \
-{\
-0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \
-0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \
-0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \
-0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \
-0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \
-0x00308000, 0x00100610, 0x00100561, 0x000E0408, \
-0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
-0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
-0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \
-0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \
-0x003A047E, 0x00044010, 0x00380819, 0x00000000, \
-0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \
-0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \
-0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \
-0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \
-0x00101313, 0x00380700, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
-0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \
-0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \
-0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \
-0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \
-0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \
-0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \
-0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \
-0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \
-0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00130831, \
-0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \
-0x00041000, 0x00010004, 0x00380700  \
-}
-
-/********************************************************/
-/*  Micro code for the 8086:1229 Rev F/10               */
-/********************************************************/
-
-/*  Parameter values for the D102 E-step  */
-#define D102_E_CPUSAVER_TIMER_DWORD            42
-#define D102_E_CPUSAVER_BUNDLE_DWORD           54
-#define D102_E_CPUSAVER_MIN_SIZE_DWORD         46
-
-#define     D102_E_RCVBUNDLE_UCODE \
-{\
-0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \
-0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \
-0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \
-0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \
-0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \
-0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \
-0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-}
-
 static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
 {
-/* *INDENT-OFF* */
-       static struct {
-               u32 ucode[UCODE_SIZE + 1];
-               u8 mac;
-               u8 timer_dword;
-               u8 bundle_dword;
-               u8 min_size_dword;
-       } ucode_opts[] = {
-               { D101M_B_RCVBUNDLE_UCODE,
-                 mac_82559_D101M,
-                 D101M_CPUSAVER_TIMER_DWORD,
-                 D101M_CPUSAVER_BUNDLE_DWORD,
-                 D101M_CPUSAVER_MIN_SIZE_DWORD },
-               { D101S_RCVBUNDLE_UCODE,
-                 mac_82559_D101S,
-                 D101S_CPUSAVER_TIMER_DWORD,
-                 D101S_CPUSAVER_BUNDLE_DWORD,
-                 D101S_CPUSAVER_MIN_SIZE_DWORD },
-               { D102_E_RCVBUNDLE_UCODE,
-                 mac_82551_F,
-                 D102_E_CPUSAVER_TIMER_DWORD,
-                 D102_E_CPUSAVER_BUNDLE_DWORD,
-                 D102_E_CPUSAVER_MIN_SIZE_DWORD },
-               { D102_E_RCVBUNDLE_UCODE,
-                 mac_82551_10,
-                 D102_E_CPUSAVER_TIMER_DWORD,
-                 D102_E_CPUSAVER_BUNDLE_DWORD,
-                 D102_E_CPUSAVER_MIN_SIZE_DWORD },
-               { {0}, 0, 0, 0, 0}
-       }, *opts;
-/* *INDENT-ON* */
-
-#define BUNDLESMALL 1
-#define BUNDLEMAX 50
-#define INTDELAY 15000
-
-       opts = ucode_opts;
-
-       /* do not load u-code for ICH devices */
-       if (nic->flags & ich)
-               return;
-
-       /* Search for ucode match against h/w rev_id */
-       while (opts->mac) {
-               if (nic->mac == opts->mac) {
-                       int i;
-                       u32 *ucode = opts->ucode;
-
-                       /* Insert user-tunable settings */
-                       ucode[opts->timer_dword] &= 0xFFFF0000;
-                       ucode[opts->timer_dword] |=
-                               (u16) INTDELAY;
-                       ucode[opts->bundle_dword] &= 0xFFFF0000;
-                       ucode[opts->bundle_dword] |= (u16) BUNDLEMAX;
-                       ucode[opts->min_size_dword] &= 0xFFFF0000;
-                       ucode[opts->min_size_dword] |=
-                               (BUNDLESMALL) ?  0xFFFF : 0xFF80;
-
-                       for(i = 0; i < UCODE_SIZE; i++)
-                               cb->u.ucode[i] = cpu_to_le32(ucode[i]);
-                       cb->command = cpu_to_le16(cb_ucode);
-                       return;
-               }
-               opts++;
-       }
+       int i;
+       static const u32 ucode[UCODE_SIZE] = {
+               /* NFS packets are misinterpreted as TCO packets and
+                * incorrectly routed to the BMC over SMBus.  This
+                * microcode patch checks the fragmented IP bit in the
+                * NFS/UDP header to distinguish between NFS and TCO. */
+               0x0EF70E36, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF,
+               0x1FFF1FFF, 0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000,
+               0x00906EFD, 0x00900EFD, 0x00E00EF8,
+       };
 
-       cb->command = cpu_to_le16(cb_nop);
+       if(nic->mac == mac_82551_F || nic->mac == mac_82551_10) {
+               for(i = 0; i < UCODE_SIZE; i++)
+                       cb->u.ucode[i] = cpu_to_le32(ucode[i]);
+               cb->command = cpu_to_le16(cb_ucode);
+       } else
+               cb->command = cpu_to_le16(cb_nop);
 }
 
 static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
index 14c76f5..9adc11e 100644 (file)
@@ -544,7 +544,7 @@ get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
                .sibling = sibling,
        };
 
-       dev = bus_find_device(&css_bus_type, NULL, &data, match_devno);
+       dev = bus_find_device(&ccw_bus_type, NULL, &data, match_devno);
 
        return dev ? to_ccwdev(dev) : NULL;
 }
index c05653c..cb832b0 100644 (file)
@@ -29,6 +29,8 @@
  *  NV-specific details such as register offsets, SATA phy location,
  *  hotplug info, etc.
  *
+ *  0.09
+ *     - Fixed bug introduced by 0.08's MCP51 and MCP55 support.
  *
  *  0.08
  *     - Added support for MCP51 and MCP55.
@@ -132,9 +134,7 @@ enum nv_host_type
        GENERIC,
        NFORCE2,
        NFORCE3,
-       CK804,
-       MCP51,
-       MCP55
+       CK804
 };
 
 static struct pci_device_id nv_pci_tbl[] = {
@@ -153,13 +153,13 @@ static struct pci_device_id nv_pci_tbl[] = {
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 },
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 },
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP55 },
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP55 },
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
        { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
                PCI_ANY_ID, PCI_ANY_ID,
                PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
index e971156..ba9381f 100644 (file)
@@ -274,7 +274,6 @@ static void transmit_chars(struct uart_sunsab_port *up,
        if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
                up->interrupt_mask1 |= SAB82532_IMR1_XPR;
                writeb(up->interrupt_mask1, &up->regs->w.imr1);
-               uart_write_wakeup(&up->port);
                return;
        }
 
index d754457..7653d6c 100644 (file)
@@ -517,10 +517,9 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
        if (up->port.info == NULL)
                goto ack_tx_int;
        xmit = &up->port.info->xmit;
-       if (uart_circ_empty(xmit)) {
-               uart_write_wakeup(&up->port);
+       if (uart_circ_empty(xmit))
                goto ack_tx_int;
-       }
+
        if (uart_tx_stopped(&up->port))
                goto ack_tx_int;
 
index a4799e9..bbc3cc6 100644 (file)
@@ -175,16 +175,16 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
 }
 
 /**
- * v9fs_read - read from a file (internal)
+ * v9fs_file_read - read from a file
  * @filep: file pointer to read
  * @data: data buffer to read data into
  * @count: size of buffer
  * @offset: offset at which to read data
  *
  */
-
 static ssize_t
-v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset)
+v9fs_file_read(struct file *filp, char __user * data, size_t count,
+              loff_t * offset)
 {
        struct inode *inode = filp->f_dentry->d_inode;
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
@@ -194,6 +194,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset)
        int rsize = 0;
        int result = 0;
        int total = 0;
+       int n;
 
        dprintk(DEBUG_VFS, "\n");
 
@@ -216,10 +217,15 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset)
                } else
                        *offset += result;
 
-               /* XXX - extra copy */
-               memcpy(buffer, fcall->params.rread.data, result);
+               n = copy_to_user(data, fcall->params.rread.data, result);
+               if (n) {
+                       dprintk(DEBUG_ERROR, "Problem copying to user %d\n", n);
+                       kfree(fcall);
+                       return -EFAULT;
+               }
+
                count -= result;
-               buffer += result;
+               data += result;
                total += result;
 
                kfree(fcall);
@@ -232,42 +238,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset)
 }
 
 /**
- * v9fs_file_read - read from a file
- * @filep: file pointer to read
- * @data: data buffer to read data into
- * @count: size of buffer
- * @offset: offset at which to read data
- *
- */
-
-static ssize_t
-v9fs_file_read(struct file *filp, char __user * data, size_t count,
-              loff_t * offset)
-{
-       int retval = -1;
-       int ret = 0;
-       char *buffer;
-
-       buffer = kmalloc(count, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
-       retval = v9fs_read(filp, buffer, count, offset);
-       if (retval > 0) {
-               if ((ret = copy_to_user(data, buffer, retval)) != 0) {
-                       dprintk(DEBUG_ERROR, "Problem copying to user %d\n",
-                               ret);
-                       retval = ret;
-               }
-       }
-
-       kfree(buffer);
-
-       return retval;
-}
-
-/**
- * v9fs_write - write to a file
+ * v9fs_file_write - write to a file
  * @filep: file pointer to write
  * @data: data buffer to write data from
  * @count: size of buffer
@@ -276,7 +247,8 @@ v9fs_file_read(struct file *filp, char __user * data, size_t count,
  */
 
 static ssize_t
-v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset)
+v9fs_file_write(struct file *filp, const char __user * data,
+               size_t count, loff_t * offset)
 {
        struct inode *inode = filp->f_dentry->d_inode;
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
@@ -286,30 +258,42 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset)
        int result = -EIO;
        int rsize = 0;
        int total = 0;
+       char *buf;
 
-       dprintk(DEBUG_VFS, "data %p count %d offset %x\n", buffer, (int)count,
+       dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count,
                (int)*offset);
        rsize = v9ses->maxdata - V9FS_IOHDRSZ;
        if (v9fid->iounit != 0 && rsize > v9fid->iounit)
                rsize = v9fid->iounit;
 
-       dump_data(buffer, count);
+       buf = kmalloc(v9ses->maxdata - V9FS_IOHDRSZ, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
 
        do {
                if (count < rsize)
                        rsize = count;
 
-               result =
-                   v9fs_t_write(v9ses, fid, *offset, rsize, buffer, &fcall);
+               result = copy_from_user(buf, data, rsize);
+               if (result) {
+                       dprintk(DEBUG_ERROR, "Problem copying from user\n");
+                       kfree(buf);
+                       return -EFAULT;
+               }
+
+               dump_data(buf, rsize);
+               result = v9fs_t_write(v9ses, fid, *offset, rsize, buf, &fcall);
                if (result < 0) {
                        eprintk(KERN_ERR, "error while writing: %s(%d)\n",
                                FCALL_ERROR(fcall), result);
                        kfree(fcall);
+                       kfree(buf);
                        return result;
                } else
                        *offset += result;
 
                kfree(fcall);
+               fcall = NULL;
 
                if (result != rsize) {
                        eprintk(KERN_ERR,
@@ -319,46 +303,14 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset)
                }
 
                count -= result;
-               buffer += result;
+               data += result;
                total += result;
        } while (count);
 
+       kfree(buf);
        return total;
 }
 
-/**
- * v9fs_file_write - write to a file
- * @filep: file pointer to write
- * @data: data buffer to write data from
- * @count: size of buffer
- * @offset: offset at which to write data
- *
- */
-
-static ssize_t
-v9fs_file_write(struct file *filp, const char __user * data,
-               size_t count, loff_t * offset)
-{
-       int ret = -1;
-       char *buffer;
-
-       buffer = kmalloc(count, GFP_KERNEL);
-       if (buffer == NULL)
-               return -ENOMEM;
-
-       ret = copy_from_user(buffer, data, count);
-       if (ret) {
-               dprintk(DEBUG_ERROR, "Problem copying from user\n");
-               ret = -EFAULT;
-       } else {
-               ret = v9fs_write(filp, buffer, count, offset);
-       }
-
-       kfree(buffer);
-
-       return ret;
-}
-
 struct file_operations v9fs_file_operations = {
        .llseek = generic_file_llseek,
        .read = v9fs_file_read,
index 7976a23..d4b1557 100644 (file)
@@ -905,7 +905,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                send_sig(SIGKILL, current, 0);
                goto out_free_dentry;
        }
-       if (padzero(elf_bss)) {
+       if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) {
                send_sig(SIGSEGV, current, 0);
                retval = -EFAULT; /* Nobody gets to see this, but.. */
                goto out_free_dentry;
index 251e5a1..0c2be8c 100644 (file)
@@ -48,43 +48,26 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem)
                (struct nfsacl_encode_desc *) desc;
        u32 *p = (u32 *) elem;
 
-       if (nfsacl_desc->count < nfsacl_desc->acl->a_count) {
-               struct posix_acl_entry *entry =
-                       &nfsacl_desc->acl->a_entries[nfsacl_desc->count++];
+       struct posix_acl_entry *entry =
+               &nfsacl_desc->acl->a_entries[nfsacl_desc->count++];
 
-               *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag);
-               switch(entry->e_tag) {
-                       case ACL_USER_OBJ:
-                               *p++ = htonl(nfsacl_desc->uid);
-                               break;
-                       case ACL_GROUP_OBJ:
-                               *p++ = htonl(nfsacl_desc->gid);
-                               break;
-                       case ACL_USER:
-                       case ACL_GROUP:
-                               *p++ = htonl(entry->e_id);
-                               break;
-                       default:  /* Solaris depends on that! */
-                               *p++ = 0;
-                               break;
-               }
-               *p++ = htonl(entry->e_perm & S_IRWXO);
-       } else {
-               const struct posix_acl_entry *pa, *pe;
-               int group_obj_perm = ACL_READ|ACL_WRITE|ACL_EXECUTE;
-
-               FOREACH_ACL_ENTRY(pa, nfsacl_desc->acl, pe) {
-                       if (pa->e_tag == ACL_GROUP_OBJ) {
-                               group_obj_perm = pa->e_perm & S_IRWXO;
-                               break;
-                       }
-               }
-               /* fake up ACL_MASK entry */
-               *p++ = htonl(ACL_MASK | nfsacl_desc->typeflag);
-               *p++ = htonl(0);
-               *p++ = htonl(group_obj_perm);
+       *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag);
+       switch(entry->e_tag) {
+               case ACL_USER_OBJ:
+                       *p++ = htonl(nfsacl_desc->uid);
+                       break;
+               case ACL_GROUP_OBJ:
+                       *p++ = htonl(nfsacl_desc->gid);
+                       break;
+               case ACL_USER:
+               case ACL_GROUP:
+                       *p++ = htonl(entry->e_id);
+                       break;
+               default:  /* Solaris depends on that! */
+                       *p++ = 0;
+                       break;
        }
-
+       *p++ = htonl(entry->e_perm & S_IRWXO);
        return 0;
 }
 
@@ -105,11 +88,28 @@ nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode,
                .gid = inode->i_gid,
        };
        int err;
+       struct posix_acl *acl2 = NULL;
 
        if (entries > NFS_ACL_MAX_ENTRIES ||
            xdr_encode_word(buf, base, entries))
                return -EINVAL;
+       if (encode_entries && acl && acl->a_count == 3) {
+               /* Fake up an ACL_MASK entry. */
+               acl2 = posix_acl_alloc(4, GFP_KERNEL);
+               if (!acl2)
+                       return -ENOMEM;
+               /* Insert entries in canonical order: other orders seem
+                to confuse Solaris VxFS. */
+               acl2->a_entries[0] = acl->a_entries[0];  /* ACL_USER_OBJ */
+               acl2->a_entries[1] = acl->a_entries[1];  /* ACL_GROUP_OBJ */
+               acl2->a_entries[2] = acl->a_entries[1];  /* ACL_MASK */
+               acl2->a_entries[2].e_tag = ACL_MASK;
+               acl2->a_entries[3] = acl->a_entries[2];  /* ACL_OTHER */
+               nfsacl_desc.acl = acl2;
+       }
        err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc);
+       if (acl2)
+               posix_acl_release(acl2);
        if (!err)
                err = 8 + nfsacl_desc.desc.elem_size *
                          nfsacl_desc.desc.array_len;
index 51c5b31..c02d15a 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/config.h>
 #include <asm/cputable.h>
 
-#define CLOCK_TICK_RATE        1193180 /* Underlying HZ */
+#define CLOCK_TICK_RATE        1024000 /* Underlying HZ */
 
 typedef unsigned long cycles_t;
 
index 41d8f84..e17c492 100644 (file)
@@ -24,6 +24,7 @@
 #define PPC_FEATURE_HAS_SPE            0x00800000
 #define PPC_FEATURE_HAS_EFP_SINGLE     0x00400000
 #define PPC_FEATURE_HAS_EFP_DOUBLE     0x00200000
+#define PPC_FEATURE_NO_TB              0x00100000
 
 #ifdef __KERNEL__
 
index 3235fb7..ab23a06 100644 (file)
@@ -89,6 +89,9 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma,
        size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
        if (!page->mapping || page->index >= size)
                goto err_unlock;
+       err = -ENOMEM;
+       if (page_mapcount(page) > INT_MAX/2)
+               goto err_unlock;
 
        zap_pte(mm, vma, addr, pte);
 
index 4454936..20e075d 100644 (file)
@@ -83,6 +83,9 @@ static long madvise_willneed(struct vm_area_struct * vma,
 {
        struct file *file = vma->vm_file;
 
+       if (!file)
+               return -EBADF;
+
        if (file->f_mapping->a_ops->get_xip_page) {
                /* no bad return value, but ignore advice */
                return 0;
@@ -141,11 +144,7 @@ static long
 madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
                unsigned long start, unsigned long end, int behavior)
 {
-       struct file *filp = vma->vm_file;
-       long error = -EBADF;
-
-       if (!filp)
-               goto  out;
+       long error;
 
        switch (behavior) {
        case MADV_NORMAL:
@@ -166,8 +165,6 @@ madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
                error = -EINVAL;
                break;
        }
-               
-out:
        return error;
 }