Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 2 May 2008 18:02:53 +0000 (11:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 2 May 2008 18:02:53 +0000 (11:02 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-2.6:
  driver-core: add dev_name() to help transition away from using bus_id

31 files changed:
Documentation/lguest/lguest.c
arch/ia64/ia32/ia32_signal.c
arch/ia64/kernel/acpi.c
arch/ia64/kernel/irq.c
arch/ia64/kernel/palinfo.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/signal.c
arch/ia64/kernel/smp.c
arch/ia64/kernel/time.c
arch/ia64/kernel/topology.c
arch/m32r/Makefile
arch/m32r/defconfig [deleted file]
arch/m32r/kernel/vmlinux.lds.S
drivers/block/virtio_blk.c
drivers/lguest/lguest_device.c
drivers/lguest/lguest_user.c
drivers/net/virtio_net.c
drivers/virtio/virtio.c
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_pci.c
drivers/virtio/virtio_ring.c
include/asm-ia64/cpu.h
include/asm-ia64/thread_info.h
include/linux/Kbuild
include/linux/irq.h
include/linux/virtio.h
include/linux/virtio_blk.h
include/linux/virtio_config.h
include/linux/virtio_net.h
kernel/irq/manage.c
kernel/irq/spurious.c

index 4c1fc65..3be8ab2 100644 (file)
@@ -131,6 +131,9 @@ struct device
        /* Any queues attached to this device */
        struct virtqueue *vq;
 
+       /* Handle status being finalized (ie. feature bits stable). */
+       void (*ready)(struct device *me);
+
        /* Device-specific data. */
        void *priv;
 };
@@ -925,24 +928,40 @@ static void enable_fd(int fd, struct virtqueue *vq)
        write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd));
 }
 
-/* When the Guest asks us to reset a device, it's is fairly easy. */
-static void reset_device(struct device *dev)
+/* When the Guest tells us they updated the status field, we handle it. */
+static void update_device_status(struct device *dev)
 {
        struct virtqueue *vq;
 
-       verbose("Resetting device %s\n", dev->name);
-       /* Clear the status. */
-       dev->desc->status = 0;
+       /* This is a reset. */
+       if (dev->desc->status == 0) {
+               verbose("Resetting device %s\n", dev->name);
 
-       /* Clear any features they've acked. */
-       memset(get_feature_bits(dev) + dev->desc->feature_len, 0,
-              dev->desc->feature_len);
+               /* Clear any features they've acked. */
+               memset(get_feature_bits(dev) + dev->desc->feature_len, 0,
+                      dev->desc->feature_len);
 
-       /* Zero out the virtqueues. */
-       for (vq = dev->vq; vq; vq = vq->next) {
-               memset(vq->vring.desc, 0,
-                      vring_size(vq->config.num, getpagesize()));
-               vq->last_avail_idx = 0;
+               /* Zero out the virtqueues. */
+               for (vq = dev->vq; vq; vq = vq->next) {
+                       memset(vq->vring.desc, 0,
+                              vring_size(vq->config.num, getpagesize()));
+                       vq->last_avail_idx = 0;
+               }
+       } else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) {
+               warnx("Device %s configuration FAILED", dev->name);
+       } else if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK) {
+               unsigned int i;
+
+               verbose("Device %s OK: offered", dev->name);
+               for (i = 0; i < dev->desc->feature_len; i++)
+                       verbose(" %08x", get_feature_bits(dev)[i]);
+               verbose(", accepted");
+               for (i = 0; i < dev->desc->feature_len; i++)
+                       verbose(" %08x", get_feature_bits(dev)
+                               [dev->desc->feature_len+i]);
+
+               if (dev->ready)
+                       dev->ready(dev);
        }
 }
 
@@ -954,9 +973,9 @@ static void handle_output(int fd, unsigned long addr)
 
        /* Check each device and virtqueue. */
        for (i = devices.dev; i; i = i->next) {
-               /* Notifications to device descriptors reset the device. */
+               /* Notifications to device descriptors update device status. */
                if (from_guest_phys(addr) == i->desc) {
-                       reset_device(i);
+                       update_device_status(i);
                        return;
                }
 
@@ -1170,6 +1189,7 @@ static struct device *new_device(const char *name, u16 type, int fd,
        dev->handle_input = handle_input;
        dev->name = name;
        dev->vq = NULL;
+       dev->ready = NULL;
 
        /* Append to device list.  Prepending to a single-linked list is
         * easier, but the user expects the devices to be arranged on the bus
@@ -1398,7 +1418,7 @@ static bool service_io(struct device *dev)
        struct vblk_info *vblk = dev->priv;
        unsigned int head, out_num, in_num, wlen;
        int ret;
-       struct virtio_blk_inhdr *in;
+       u8 *in;
        struct virtio_blk_outhdr *out;
        struct iovec iov[dev->vq->vring.num];
        off64_t off;
@@ -1416,7 +1436,7 @@ static bool service_io(struct device *dev)
                     head, out_num, in_num);
 
        out = convert(&iov[0], struct virtio_blk_outhdr);
-       in = convert(&iov[out_num+in_num-1], struct virtio_blk_inhdr);
+       in = convert(&iov[out_num+in_num-1], u8);
        off = out->sector * 512;
 
        /* The block device implements "barriers", where the Guest indicates
@@ -1430,7 +1450,7 @@ static bool service_io(struct device *dev)
         * It'd be nice if we supported eject, for example, but we don't. */
        if (out->type & VIRTIO_BLK_T_SCSI_CMD) {
                fprintf(stderr, "Scsi commands unsupported\n");
-               in->status = VIRTIO_BLK_S_UNSUPP;
+               *in = VIRTIO_BLK_S_UNSUPP;
                wlen = sizeof(*in);
        } else if (out->type & VIRTIO_BLK_T_OUT) {
                /* Write */
@@ -1453,7 +1473,7 @@ static bool service_io(struct device *dev)
                        errx(1, "Write past end %llu+%u", off, ret);
                }
                wlen = sizeof(*in);
-               in->status = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
+               *in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
        } else {
                /* Read */
 
@@ -1466,10 +1486,10 @@ static bool service_io(struct device *dev)
                verbose("READ from sector %llu: %i\n", out->sector, ret);
                if (ret >= 0) {
                        wlen = sizeof(*in) + ret;
-                       in->status = VIRTIO_BLK_S_OK;
+                       *in = VIRTIO_BLK_S_OK;
                } else {
                        wlen = sizeof(*in);
-                       in->status = VIRTIO_BLK_S_IOERR;
+                       *in = VIRTIO_BLK_S_IOERR;
                }
        }
 
index 256a7fa..b763ca1 100644 (file)
@@ -463,7 +463,7 @@ sys32_sigsuspend (int history0, int history1, old_sigset_t mask)
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
+       set_restore_sigmask();
        return -ERESTARTNOHAND;
 }
 
index c7467f8..19709a0 100644 (file)
@@ -966,7 +966,7 @@ acpi_map_iosapics (void)
 fs_initcall(acpi_map_iosapics);
 #endif                         /* CONFIG_ACPI_NUMA */
 
-int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
+int __ref acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 {
        int err;
 
index 6dee579..7fd18f5 100644 (file)
@@ -183,10 +183,10 @@ void fixup_irqs(void)
 {
        unsigned int irq;
        extern void ia64_process_pending_intr(void);
-       extern void ia64_disable_timer(void);
        extern volatile int time_keeper_id;
 
-       ia64_disable_timer();
+       /* Mask ITV to disable timer */
+       ia64_set_itv(1 << 16);
 
        /*
         * Find a new timesync master
index 396004e..4547a20 100644 (file)
@@ -1053,7 +1053,7 @@ static int __cpuinit palinfo_cpu_callback(struct notifier_block *nfb,
        return NOTIFY_OK;
 }
 
-static struct notifier_block palinfo_cpu_notifier __cpuinitdata =
+static struct notifier_block __refdata palinfo_cpu_notifier =
 {
        .notifier_call = palinfo_cpu_callback,
        .priority = 0,
index 7fbb51e..c1ad27d 100644 (file)
@@ -867,7 +867,7 @@ pfm_rvfree(void *mem, unsigned long size)
 }
 
 static pfm_context_t *
-pfm_context_alloc(void)
+pfm_context_alloc(int ctx_flags)
 {
        pfm_context_t *ctx;
 
@@ -878,6 +878,46 @@ pfm_context_alloc(void)
        ctx = kzalloc(sizeof(pfm_context_t), GFP_KERNEL);
        if (ctx) {
                DPRINT(("alloc ctx @%p\n", ctx));
+
+               /*
+                * init context protection lock
+                */
+               spin_lock_init(&ctx->ctx_lock);
+
+               /*
+                * context is unloaded
+                */
+               ctx->ctx_state = PFM_CTX_UNLOADED;
+
+               /*
+                * initialization of context's flags
+                */
+               ctx->ctx_fl_block       = (ctx_flags & PFM_FL_NOTIFY_BLOCK) ? 1 : 0;
+               ctx->ctx_fl_system      = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0;
+               ctx->ctx_fl_no_msg      = (ctx_flags & PFM_FL_OVFL_NO_MSG) ? 1: 0;
+               /*
+                * will move to set properties
+                * ctx->ctx_fl_excl_idle   = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0;
+                */
+
+               /*
+                * init restart semaphore to locked
+                */
+               init_completion(&ctx->ctx_restart_done);
+
+               /*
+                * activation is used in SMP only
+                */
+               ctx->ctx_last_activation = PFM_INVALID_ACTIVATION;
+               SET_LAST_CPU(ctx, -1);
+
+               /*
+                * initialize notification message queue
+                */
+               ctx->ctx_msgq_head = ctx->ctx_msgq_tail = 0;
+               init_waitqueue_head(&ctx->ctx_msgq_wait);
+               init_waitqueue_head(&ctx->ctx_zombieq);
+
        }
        return ctx;
 }
@@ -2165,28 +2205,21 @@ static struct dentry_operations pfmfs_dentry_operations = {
 };
 
 
-static int
-pfm_alloc_fd(struct file **cfile)
+static struct file *
+pfm_alloc_file(pfm_context_t *ctx)
 {
-       int fd, ret = 0;
-       struct file *file = NULL;
-       struct inode * inode;
+       struct file *file;
+       struct inode *inode;
+       struct dentry *dentry;
        char name[32];
        struct qstr this;
 
-       fd = get_unused_fd();
-       if (fd < 0) return -ENFILE;
-
-       ret = -ENFILE;
-
-       file = get_empty_filp();
-       if (!file) goto out;
-
        /*
         * allocate a new inode
         */
        inode = new_inode(pfmfs_mnt->mnt_sb);
-       if (!inode) goto out;
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
 
        DPRINT(("new inode ino=%ld @%p\n", inode->i_ino, inode));
 
@@ -2199,59 +2232,28 @@ pfm_alloc_fd(struct file **cfile)
        this.len  = strlen(name);
        this.hash = inode->i_ino;
 
-       ret = -ENOMEM;
-
        /*
         * allocate a new dcache entry
         */
-       file->f_path.dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
-       if (!file->f_path.dentry) goto out;
+       dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
+       if (!dentry) {
+               iput(inode);
+               return ERR_PTR(-ENOMEM);
+       }
 
-       file->f_path.dentry->d_op = &pfmfs_dentry_operations;
+       dentry->d_op = &pfmfs_dentry_operations;
+       d_add(dentry, inode);
 
-       d_add(file->f_path.dentry, inode);
-       file->f_path.mnt = mntget(pfmfs_mnt);
-       file->f_mapping = inode->i_mapping;
+       file = alloc_file(pfmfs_mnt, dentry, FMODE_READ, &pfm_file_ops);
+       if (!file) {
+               dput(dentry);
+               return ERR_PTR(-ENFILE);
+       }
 
-       file->f_op    = &pfm_file_ops;
-       file->f_mode  = FMODE_READ;
        file->f_flags = O_RDONLY;
-       file->f_pos   = 0;
-
-       /*
-        * may have to delay until context is attached?
-        */
-       fd_install(fd, file);
-
-       /*
-        * the file structure we will use
-        */
-       *cfile = file;
-
-       return fd;
-out:
-       if (file) put_filp(file);
-       put_unused_fd(fd);
-       return ret;
-}
-
-static void
-pfm_free_fd(int fd, struct file *file)
-{
-       struct files_struct *files = current->files;
-       struct fdtable *fdt;
+       file->private_data = ctx;
 
-       /* 
-        * there ie no fd_uninstall(), so we do it here
-        */
-       spin_lock(&files->file_lock);
-       fdt = files_fdtable(files);
-       rcu_assign_pointer(fdt->fd[fd], NULL);
-       spin_unlock(&files->file_lock);
-
-       if (file)
-               put_filp(file);
-       put_unused_fd(fd);
+       return file;
 }
 
 static int
@@ -2475,6 +2477,7 @@ pfm_setup_buffer_fmt(struct task_struct *task, struct file *filp, pfm_context_t
 
        /* link buffer format and context */
        ctx->ctx_buf_fmt = fmt;
+       ctx->ctx_fl_is_sampling = 1; /* assume record() is defined */
 
        /*
         * check if buffer format wants to use perfmon buffer allocation/mapping service
@@ -2669,78 +2672,45 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
 {
        pfarg_context_t *req = (pfarg_context_t *)arg;
        struct file *filp;
+       struct path path;
        int ctx_flags;
+       int fd;
        int ret;
 
        /* let's check the arguments first */
        ret = pfarg_is_sane(current, req);
-       if (ret < 0) return ret;
+       if (ret < 0)
+               return ret;
 
        ctx_flags = req->ctx_flags;
 
        ret = -ENOMEM;
 
-       ctx = pfm_context_alloc();
-       if (!ctx) goto error;
+       fd = get_unused_fd();
+       if (fd < 0)
+               return fd;
 
-       ret = pfm_alloc_fd(&filp);
-       if (ret < 0) goto error_file;
+       ctx = pfm_context_alloc(ctx_flags);
+       if (!ctx)
+               goto error;
 
-       req->ctx_fd = ctx->ctx_fd = ret;
+       filp = pfm_alloc_file(ctx);
+       if (IS_ERR(filp)) {
+               ret = PTR_ERR(filp);
+               goto error_file;
+       }
 
-       /*
-        * attach context to file
-        */
-       filp->private_data = ctx;
+       req->ctx_fd = ctx->ctx_fd = fd;
 
        /*
         * does the user want to sample?
         */
        if (pfm_uuid_cmp(req->ctx_smpl_buf_id, pfm_null_uuid)) {
                ret = pfm_setup_buffer_fmt(current, filp, ctx, ctx_flags, 0, req);
-               if (ret) goto buffer_error;
+               if (ret)
+                       goto buffer_error;
        }
 
-       /*
-        * init context protection lock
-        */
-       spin_lock_init(&ctx->ctx_lock);
-
-       /*
-        * context is unloaded
-        */
-       ctx->ctx_state = PFM_CTX_UNLOADED;
-
-       /*
-        * initialization of context's flags
-        */
-       ctx->ctx_fl_block       = (ctx_flags & PFM_FL_NOTIFY_BLOCK) ? 1 : 0;
-       ctx->ctx_fl_system      = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0;
-       ctx->ctx_fl_is_sampling = ctx->ctx_buf_fmt ? 1 : 0; /* assume record() is defined */
-       ctx->ctx_fl_no_msg      = (ctx_flags & PFM_FL_OVFL_NO_MSG) ? 1: 0;
-       /*
-        * will move to set properties
-        * ctx->ctx_fl_excl_idle   = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0;
-        */
-
-       /*
-        * init restart semaphore to locked
-        */
-       init_completion(&ctx->ctx_restart_done);
-
-       /*
-        * activation is used in SMP only
-        */
-       ctx->ctx_last_activation = PFM_INVALID_ACTIVATION;
-       SET_LAST_CPU(ctx, -1);
-
-       /*
-        * initialize notification message queue
-        */
-       ctx->ctx_msgq_head = ctx->ctx_msgq_tail = 0;
-       init_waitqueue_head(&ctx->ctx_msgq_wait);
-       init_waitqueue_head(&ctx->ctx_zombieq);
-
        DPRINT(("ctx=%p flags=0x%x system=%d notify_block=%d excl_idle=%d no_msg=%d ctx_fd=%d \n",
                ctx,
                ctx_flags,
@@ -2755,10 +2725,14 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
         */
        pfm_reset_pmu_state(ctx);
 
+       fd_install(fd, filp);
+
        return 0;
 
 buffer_error:
-       pfm_free_fd(ctx->ctx_fd, filp);
+       path = filp->f_path;
+       put_filp(filp);
+       path_put(&path);
 
        if (ctx->ctx_buf_fmt) {
                pfm_buf_fmt_exit(ctx->ctx_buf_fmt, current, NULL, regs);
@@ -2767,6 +2741,7 @@ error_file:
        pfm_context_free(ctx);
 
 error:
+       put_unused_fd(fd);
        return ret;
 }
 
index 5740296..19c5a78 100644 (file)
@@ -464,7 +464,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
        if (!user_mode(&scr->pt))
                return;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
                oldset = &current->saved_sigmask;
        else
                oldset = &current->blocked;
@@ -530,12 +530,13 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
                 * continue to iterate in this loop so we can deliver the SIGSEGV...
                 */
                if (handle_signal(signr, &ka, &info, oldset, scr)) {
-                       /* a signal was successfully delivered; the saved
+                       /*
+                        * A signal was successfully delivered; the saved
                         * sigmask will have been stored in the signal frame,
                         * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+                        * clear the TS_RESTORE_SIGMASK flag.
+                        */
+                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
                        return;
                }
        }
@@ -566,8 +567,8 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
 
        /* if there's no signal to deliver, we just put the saved sigmask
         * back */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
+               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
        }
 }
index 9a9d4c4..983296f 100644 (file)
@@ -98,8 +98,33 @@ unlock_ipi_calllock(void)
        spin_unlock_irq(&call_lock);
 }
 
+static inline void
+handle_call_data(void)
+{
+       struct call_data_struct *data;
+       void (*func)(void *info);
+       void *info;
+       int wait;
+
+       /* release the 'pointer lock' */
+       data = (struct call_data_struct *)call_data;
+       func = data->func;
+       info = data->info;
+       wait = data->wait;
+
+       mb();
+       atomic_inc(&data->started);
+       /* At this point the structure may be gone unless wait is true. */
+       (*func)(info);
+
+       /* Notify the sending CPU that the task is done. */
+       mb();
+       if (wait)
+               atomic_inc(&data->finished);
+}
+
 static void
-stop_this_cpu (void)
+stop_this_cpu(void)
 {
        /*
         * Remove this CPU:
@@ -138,44 +163,21 @@ handle_IPI (int irq, void *dev_id)
                        ops &= ~(1 << which);
 
                        switch (which) {
-                             case IPI_CALL_FUNC:
-                             {
-                                     struct call_data_struct *data;
-                                     void (*func)(void *info);
-                                     void *info;
-                                     int wait;
-
-                                     /* release the 'pointer lock' */
-                                     data = (struct call_data_struct *) call_data;
-                                     func = data->func;
-                                     info = data->info;
-                                     wait = data->wait;
-
-                                     mb();
-                                     atomic_inc(&data->started);
-                                     /*
-                                      * At this point the structure may be gone unless
-                                      * wait is true.
-                                      */
-                                     (*func)(info);
-
-                                     /* Notify the sending CPU that the task is done.  */
-                                     mb();
-                                     if (wait)
-                                             atomic_inc(&data->finished);
-                             }
-                             break;
-
-                             case IPI_CPU_STOP:
+                       case IPI_CALL_FUNC:
+                               handle_call_data();
+                               break;
+
+                       case IPI_CPU_STOP:
                                stop_this_cpu();
                                break;
 #ifdef CONFIG_KEXEC
-                             case IPI_KDUMP_CPU_STOP:
+                       case IPI_KDUMP_CPU_STOP:
                                unw_init_running(kdump_cpu_freeze, NULL);
                                break;
 #endif
-                             default:
-                               printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which);
+                       default:
+                               printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n",
+                                               this_cpu, which);
                                break;
                        }
                } while (ops);
index 48e15a5..8c73643 100644 (file)
@@ -379,11 +379,6 @@ static struct irqaction timer_irqaction = {
        .name =         "timer"
 };
 
-void __devinit ia64_disable_timer(void)
-{
-       ia64_set_itv(1 << 16);
-}
-
 void __init
 time_init (void)
 {
index abb17a6..26228e2 100644 (file)
@@ -36,9 +36,11 @@ void arch_fix_phys_package_id(int num, u32 slot)
 }
 EXPORT_SYMBOL_GPL(arch_fix_phys_package_id);
 
-int arch_register_cpu(int num)
+
+#ifdef CONFIG_HOTPLUG_CPU
+int __ref arch_register_cpu(int num)
 {
-#if defined (CONFIG_ACPI) && defined (CONFIG_HOTPLUG_CPU)
+#ifdef CONFIG_ACPI
        /*
         * If CPEI can be re-targetted or if this is not
         * CPEI target, then it is hotpluggable
@@ -47,19 +49,21 @@ int arch_register_cpu(int num)
                sysfs_cpus[num].cpu.hotpluggable = 1;
        map_cpu_to_node(num, node_cpuid[num].nid);
 #endif
-
        return register_cpu(&sysfs_cpus[num].cpu, num);
 }
-
-#ifdef CONFIG_HOTPLUG_CPU
+EXPORT_SYMBOL(arch_register_cpu);
 
 void arch_unregister_cpu(int num)
 {
        unregister_cpu(&sysfs_cpus[num].cpu);
        unmap_cpu_from_node(num, cpu_to_node(num));
 }
-EXPORT_SYMBOL(arch_register_cpu);
 EXPORT_SYMBOL(arch_unregister_cpu);
+#else
+static int __init arch_register_cpu(int num)
+{
+       return register_cpu(&sysfs_cpus[num].cpu, num);
+}
 #endif /*CONFIG_HOTPLUG_CPU*/
 
 
index 4072a07..469766b 100644 (file)
@@ -5,6 +5,8 @@
 # architecture-specific flags and dependencies.
 #
 
+KBUILD_DEFCONFIG := m32700ut.smp_defconfig
+
 LDFLAGS                :=
 OBJCOPYFLAGS   := -O binary -R .note -R .comment -S
 LDFLAGS_vmlinux        :=
diff --git a/arch/m32r/defconfig b/arch/m32r/defconfig
deleted file mode 100644 (file)
index af3b981..0000000
+++ /dev/null
@@ -1,863 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc1
-# Wed Aug  1 17:22:35 2007
-#
-CONFIG_M32R=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_ZONE_DMA=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_NO_IOPORT=y
-CONFIG_NO_DMA=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOCK_KERNEL=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_AUDIT is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=15
-# CONFIG_CPUSETS is not set
-CONFIG_SYSFS_DEPRECATED=y
-# CONFIG_RELAY is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-# CONFIG_KALLSYMS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-# CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
-# CONFIG_EPOLL is not set
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
-# CONFIG_SLOB is not set
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-CONFIG_STOP_MACHINE=y
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-# CONFIG_BLK_DEV_BSG is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-
-#
-# Processor type and features
-#
-# CONFIG_PLAT_MAPPI is not set
-# CONFIG_PLAT_USRV is not set
-CONFIG_PLAT_M32700UT=y
-# CONFIG_PLAT_OPSPUT is not set
-# CONFIG_PLAT_OAKS32R is not set
-# CONFIG_PLAT_MAPPI2 is not set
-# CONFIG_PLAT_MAPPI3 is not set
-# CONFIG_PLAT_M32104UT is not set
-CONFIG_CHIP_M32700=y
-# CONFIG_CHIP_M32102 is not set
-# CONFIG_CHIP_M32104 is not set
-# CONFIG_CHIP_VDEC2 is not set
-# CONFIG_CHIP_OPSP is not set
-CONFIG_MMU=y
-CONFIG_TLB_ENTRIES=32
-CONFIG_ISA_M32R2=y
-CONFIG_ISA_DSP_LEVEL2=y
-CONFIG_ISA_DUAL_ISSUE=y
-CONFIG_BUS_CLOCK=50000000
-CONFIG_TIMER_DIVIDE=128
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_MEMORY_START=0x08000000
-CONFIG_MEMORY_SIZE=0x01000000
-CONFIG_NOHIGHMEM=y
-CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-# CONFIG_FLATMEM_MANUAL is not set
-CONFIG_DISCONTIGMEM_MANUAL=y
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_DISCONTIGMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-CONFIG_IRAM_START=0x00f00000
-CONFIG_IRAM_SIZE=0x00080000
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_PREEMPT=y
-CONFIG_SMP=y
-# CONFIG_CHIP_M32700_TS1 is not set
-CONFIG_NR_CPUS=2
-CONFIG_NODES_SHIFT=1
-
-#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-# CONFIG_ARCH_SUPPORTS_MSI is not set
-# CONFIG_ISA is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-# CONFIG_XFRM_MIGRATE is not set
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_IP_DCCP is not set
-# CONFIG_IP_SCTP is not set
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
-# CONFIG_RFKILL is not set
-# CONFIG_NET_9P is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-# CONFIG_SYS_HYPERVISOR is not set
-# CONFIG_CONNECTOR is not set
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
-# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-# CONFIG_MTD_CHAR is not set
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=m
-CONFIG_MTD_JEDECPROBE=m
-CONFIG_MTD_GEN_PROBE=m
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-# CONFIG_MTD_CFI_NOSWAP is not set
-CONFIG_MTD_CFI_BE_BYTE_SWAP=y
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_GEOMETRY=y
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-# CONFIG_MTD_CFI_I2 is not set
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_OTP is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=m
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=m
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
-# CONFIG_MTD_ONENAND is not set
-
-#
-# UBI - Unsorted block images
-#
-# CONFIG_MTD_UBI is not set
-# CONFIG_PARPORT is not set
-CONFIG_BLK_DEV=y
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
-CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECD=m
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_PROC_FS=y
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-# CONFIG_IDE_ARM is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-CONFIG_SCSI=m
-# CONFIG_SCSI_DMA is not set
-# CONFIG_SCSI_TGT is not set
-# CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=m
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=m
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_CHR_DEV_SG=m
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-# CONFIG_SCSI_SCAN_ASYNC is not set
-CONFIG_SCSI_WAIT_SCAN=m
-
-#
-# SCSI Transports
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_LIBSAS is not set
-CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_MD is not set
-CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_MACVLAN is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_PHYLIB is not set
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_SMC91X=y
-# CONFIG_NE2000 is not set
-CONFIG_NETDEV_1000=y
-CONFIG_NETDEV_10000=y
-
-#
-# Wireless LAN
-#
-# CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
-# CONFIG_WAN is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_ISDN is not set
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-# CONFIG_INPUT_POLLDEV is not set
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TABLET is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_SERIAL_M32R_SIO=y
-CONFIG_SERIAL_M32R_SIO_CONSOLE=y
-CONFIG_SERIAL_M32R_PLDSIO=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
-CONFIG_HW_RANDOM=y
-# CONFIG_RTC is not set
-CONFIG_DS1302=y
-# CONFIG_R3964 is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_TCG_TPM is not set
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-# CONFIG_W1 is not set
-# CONFIG_POWER_SUPPLY is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ABITUGURU3 is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-
-#
-# Multifunction device drivers
-#
-# CONFIG_MFD_SM501 is not set
-
-#
-# Multimedia devices
-#
-CONFIG_VIDEO_DEV=m
-CONFIG_VIDEO_V4L1=y
-CONFIG_VIDEO_V4L1_COMPAT=y
-CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
-# CONFIG_VIDEO_ADV_DEBUG is not set
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-# CONFIG_VIDEO_CPIA is not set
-CONFIG_VIDEO_M32R_AR=m
-CONFIG_VIDEO_M32R_AR_M64278=m
-CONFIG_RADIO_ADAPTERS=y
-# CONFIG_DVB_CORE is not set
-CONFIG_DAB=y
-
-#
-# Graphics support
-#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
-# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-CONFIG_FB=y
-CONFIG_FIRMWARE_EDID=y
-# CONFIG_FB_DDC is not set
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
-# CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-
-#
-# Frame buffer hardware drivers
-#
-CONFIG_FB_S1D13XXX=y
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_LOGO_M32R_CLUT224=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-CONFIG_USB_SUPPORT=y
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-CONFIG_MMC=y
-CONFIG_MMC_DEBUG=y
-# CONFIG_MMC_UNSAFE_RESUME is not set
-
-#
-# MMC/SD Card Drivers
-#
-CONFIG_MMC_BLOCK=y
-CONFIG_MMC_BLOCK_BOUNCE=y
-
-#
-# MMC/SD Host Controller Drivers
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# Userspace I/O
-#
-# CONFIG_UIO is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=y
-CONFIG_JBD_DEBUG=y
-CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_REISERFS_FS_XATTR is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-# CONFIG_ZISOFS is not set
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_BIND34 is not set
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
-# CONFIG_DLM is not set
-
-#
-# Profiling support
-#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_FRAME_POINTER is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-# CONFIG_CRC_ITU_T is not set
-CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_HAS_IOMEM=y
index 41b0785..15a6f36 100644 (file)
@@ -60,9 +60,6 @@ SECTIONS
   . = ALIGN(4096);
   __nosave_end = .;
 
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
   . = ALIGN(32);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
index 0cfbe8c..84e064f 100644 (file)
@@ -35,7 +35,7 @@ struct virtblk_req
        struct list_head list;
        struct request *req;
        struct virtio_blk_outhdr out_hdr;
-       struct virtio_blk_inhdr in_hdr;
+       u8 status;
 };
 
 static void blk_done(struct virtqueue *vq)
@@ -48,7 +48,7 @@ static void blk_done(struct virtqueue *vq)
        spin_lock_irqsave(&vblk->lock, flags);
        while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) {
                int uptodate;
-               switch (vbr->in_hdr.status) {
+               switch (vbr->status) {
                case VIRTIO_BLK_S_OK:
                        uptodate = 1;
                        break;
@@ -101,7 +101,7 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
        sg_init_table(vblk->sg, VIRTIO_MAX_SG);
        sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr));
        num = blk_rq_map_sg(q, vbr->req, vblk->sg+1);
-       sg_set_buf(&vblk->sg[num+1], &vbr->in_hdr, sizeof(vbr->in_hdr));
+       sg_set_buf(&vblk->sg[num+1], &vbr->status, sizeof(vbr->status));
 
        if (rq_data_dir(vbr->req) == WRITE) {
                vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
@@ -157,10 +157,25 @@ static int virtblk_ioctl(struct inode *inode, struct file *filp,
 /* We provide getgeo only to please some old bootloader/partitioning tools */
 static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
 {
-       /* some standard values, similar to sd */
-       geo->heads = 1 << 6;
-       geo->sectors = 1 << 5;
-       geo->cylinders = get_capacity(bd->bd_disk) >> 11;
+       struct virtio_blk *vblk = bd->bd_disk->private_data;
+       struct virtio_blk_geometry vgeo;
+       int err;
+
+       /* see if the host passed in geometry config */
+       err = virtio_config_val(vblk->vdev, VIRTIO_BLK_F_GEOMETRY,
+                               offsetof(struct virtio_blk_config, geometry),
+                               &vgeo);
+
+       if (!err) {
+               geo->heads = vgeo.heads;
+               geo->sectors = vgeo.sectors;
+               geo->cylinders = vgeo.cylinders;
+       } else {
+               /* some standard values, similar to sd */
+               geo->heads = 1 << 6;
+               geo->sectors = 1 << 5;
+               geo->cylinders = get_capacity(bd->bd_disk) >> 11;
+       }
        return 0;
 }
 
@@ -242,12 +257,12 @@ static int virtblk_probe(struct virtio_device *vdev)
        index++;
 
        /* If barriers are supported, tell block layer that queue is ordered */
-       if (vdev->config->feature(vdev, VIRTIO_BLK_F_BARRIER))
+       if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER))
                blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL);
 
        /* Host must always specify the capacity. */
-       __virtio_config_val(vdev, offsetof(struct virtio_blk_config, capacity),
-                           &cap);
+       vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity),
+                         &cap, sizeof(cap));
 
        /* If capacity is too big, truncate with warning. */
        if ((sector_t)cap != cap) {
@@ -289,7 +304,6 @@ out:
 static void virtblk_remove(struct virtio_device *vdev)
 {
        struct virtio_blk *vblk = vdev->priv;
-       int major = vblk->disk->major;
 
        /* Nothing should be pending. */
        BUG_ON(!list_empty(&vblk->reqs));
@@ -299,7 +313,6 @@ static void virtblk_remove(struct virtio_device *vdev)
 
        blk_cleanup_queue(vblk->disk->queue);
        put_disk(vblk->disk);
-       unregister_blkdev(major, "virtblk");
        mempool_destroy(vblk->pool);
        vdev->config->del_vq(vblk->vq);
        kfree(vblk);
@@ -310,7 +323,14 @@ static struct virtio_device_id id_table[] = {
        { 0 },
 };
 
+static unsigned int features[] = {
+       VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
+       VIRTIO_BLK_F_GEOMETRY,
+};
+
 static struct virtio_driver virtio_blk = {
+       .feature_table = features,
+       .feature_table_size = ARRAY_SIZE(features),
        .driver.name =  KBUILD_MODNAME,
        .driver.owner = THIS_MODULE,
        .id_table =     id_table,
index 2bc9bf7..8080249 100644 (file)
@@ -85,27 +85,34 @@ static unsigned desc_size(const struct lguest_device_desc *desc)
                + desc->config_len;
 }
 
-/* This tests (and acknowleges) a feature bit. */
-static bool lg_feature(struct virtio_device *vdev, unsigned fbit)
+/* This gets the device's feature bits. */
+static u32 lg_get_features(struct virtio_device *vdev)
 {
+       unsigned int i;
+       u32 features = 0;
        struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
-       u8 *features;
-
-       /* Obviously if they ask for a feature off the end of our feature
-        * bitmap, it's not set. */
-       if (fbit / 8 > desc->feature_len)
-               return false;
-
-       /* The feature bitmap comes after the virtqueues. */
-       features = lg_features(desc);
-       if (!(features[fbit / 8] & (1 << (fbit % 8))))
-               return false;
-
-       /* We set the matching bit in the other half of the bitmap to tell the
-        * Host we want to use this feature.  We don't use this yet, but we
-        * could in future. */
-       features[desc->feature_len + fbit / 8] |= (1 << (fbit % 8));
-       return true;
+       u8 *in_features = lg_features(desc);
+
+       /* We do this the slow but generic way. */
+       for (i = 0; i < min(desc->feature_len * 8, 32); i++)
+               if (in_features[i / 8] & (1 << (i % 8)))
+                       features |= (1 << i);
+
+       return features;
+}
+
+static void lg_set_features(struct virtio_device *vdev, u32 features)
+{
+       unsigned int i;
+       struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
+       /* Second half of bitmap is features we accept. */
+       u8 *out_features = lg_features(desc) + desc->feature_len;
+
+       memset(out_features, 0, desc->feature_len);
+       for (i = 0; i < min(desc->feature_len * 8, 32); i++) {
+               if (features & (1 << i))
+                       out_features[i / 8] |= (1 << (i % 8));
+       }
 }
 
 /* Once they've found a field, getting a copy of it is easy. */
@@ -137,20 +144,26 @@ static u8 lg_get_status(struct virtio_device *vdev)
        return to_lgdev(vdev)->desc->status;
 }
 
+/* To notify on status updates, we (ab)use the NOTIFY hypercall, with the
+ * descriptor address of the device.  A zero status means "reset". */
+static void set_status(struct virtio_device *vdev, u8 status)
+{
+       unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
+
+       /* We set the status. */
+       to_lgdev(vdev)->desc->status = status;
+       hcall(LHCALL_NOTIFY, (max_pfn<<PAGE_SHIFT) + offset, 0, 0);
+}
+
 static void lg_set_status(struct virtio_device *vdev, u8 status)
 {
        BUG_ON(!status);
-       to_lgdev(vdev)->desc->status = status;
+       set_status(vdev, status);
 }
 
-/* To reset the device, we (ab)use the NOTIFY hypercall, with the descriptor
- * address of the device.  The Host will zero the status and all the
- * features. */
 static void lg_reset(struct virtio_device *vdev)
 {
-       unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
-
-       hcall(LHCALL_NOTIFY, (max_pfn<<PAGE_SHIFT) + offset, 0, 0);
+       set_status(vdev, 0);
 }
 
 /*
@@ -286,7 +299,8 @@ static void lg_del_vq(struct virtqueue *vq)
 
 /* The ops structure which hooks everything together. */
 static struct virtio_config_ops lguest_config_ops = {
-       .feature = lg_feature,
+       .get_features = lg_get_features,
+       .set_features = lg_set_features,
        .get = lg_get,
        .set = lg_set,
        .get_status = lg_get_status,
index 645e6e0..e73a000 100644 (file)
@@ -102,7 +102,7 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
 static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
 {
        /* We have a limited number the number of CPUs in the lguest struct. */
-       if (id >= NR_CPUS)
+       if (id >= ARRAY_SIZE(cpu->lg->cpus))
                return -EINVAL;
 
        /* Set up this CPU's id, and pointer back to the lguest struct. */
@@ -251,8 +251,6 @@ static ssize_t write(struct file *file, const char __user *in,
                if (!lg || (cpu_id >= lg->nr_cpus))
                        return -EINVAL;
                cpu = &lg->cpus[cpu_id];
-               if (!cpu)
-                       return -EINVAL;
 
                /* Once the Guest is dead, you can only read() why it died. */
                if (lg->dead)
index 555b70c..f926b5a 100644 (file)
@@ -41,6 +41,9 @@ struct virtnet_info
        struct net_device *dev;
        struct napi_struct napi;
 
+       /* The skb we couldn't send because buffers were full. */
+       struct sk_buff *last_xmit_skb;
+
        /* Number of input buffers, and max we've ever had. */
        unsigned int num, max;
 
@@ -142,10 +145,10 @@ drop:
 static void try_fill_recv(struct virtnet_info *vi)
 {
        struct sk_buff *skb;
-       struct scatterlist sg[1+MAX_SKB_FRAGS];
+       struct scatterlist sg[2+MAX_SKB_FRAGS];
        int num, err;
 
-       sg_init_table(sg, 1+MAX_SKB_FRAGS);
+       sg_init_table(sg, 2+MAX_SKB_FRAGS);
        for (;;) {
                skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN);
                if (unlikely(!skb))
@@ -221,23 +224,22 @@ static void free_old_xmit_skbs(struct virtnet_info *vi)
        while ((skb = vi->svq->vq_ops->get_buf(vi->svq, &len)) != NULL) {
                pr_debug("Sent skb %p\n", skb);
                __skb_unlink(skb, &vi->send);
-               vi->dev->stats.tx_bytes += len;
+               vi->dev->stats.tx_bytes += skb->len;
                vi->dev->stats.tx_packets++;
                kfree_skb(skb);
        }
 }
 
-static int start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
 {
-       struct virtnet_info *vi = netdev_priv(dev);
-       int num, err;
-       struct scatterlist sg[1+MAX_SKB_FRAGS];
+       int num;
+       struct scatterlist sg[2+MAX_SKB_FRAGS];
        struct virtio_net_hdr *hdr;
        const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
 
-       sg_init_table(sg, 1+MAX_SKB_FRAGS);
+       sg_init_table(sg, 2+MAX_SKB_FRAGS);
 
-       pr_debug("%s: xmit %p " MAC_FMT "\n", dev->name, skb,
+       pr_debug("%s: xmit %p " MAC_FMT "\n", vi->dev->name, skb,
                 dest[0], dest[1], dest[2],
                 dest[3], dest[4], dest[5]);
 
@@ -272,30 +274,51 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        vnet_hdr_to_sg(sg, skb);
        num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
-       __skb_queue_head(&vi->send, skb);
+
+       return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
+}
+
+static int start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct virtnet_info *vi = netdev_priv(dev);
 
 again:
        /* Free up any pending old buffers before queueing new ones. */
        free_old_xmit_skbs(vi);
-       err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
-       if (err) {
-               pr_debug("%s: virtio not prepared to send\n", dev->name);
-               netif_stop_queue(dev);
-
-               /* Activate callback for using skbs: if this returns false it
-                * means some were used in the meantime. */
-               if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
-                       vi->svq->vq_ops->disable_cb(vi->svq);
-                       netif_start_queue(dev);
-                       goto again;
+
+       /* If we has a buffer left over from last time, send it now. */
+       if (vi->last_xmit_skb) {
+               if (xmit_skb(vi, vi->last_xmit_skb) != 0) {
+                       /* Drop this skb: we only queue one. */
+                       vi->dev->stats.tx_dropped++;
+                       kfree_skb(skb);
+                       goto stop_queue;
                }
-               __skb_unlink(skb, &vi->send);
+               vi->last_xmit_skb = NULL;
+       }
 
-               return NETDEV_TX_BUSY;
+       /* Put new one in send queue and do transmit */
+       __skb_queue_head(&vi->send, skb);
+       if (xmit_skb(vi, skb) != 0) {
+               vi->last_xmit_skb = skb;
+               goto stop_queue;
        }
+done:
        vi->svq->vq_ops->kick(vi->svq);
-
-       return 0;
+       return NETDEV_TX_OK;
+
+stop_queue:
+       pr_debug("%s: virtio not prepared to send\n", dev->name);
+       netif_stop_queue(dev);
+
+       /* Activate callback for using skbs: if this returns false it
+        * means some were used in the meantime. */
+       if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
+               vi->svq->vq_ops->disable_cb(vi->svq);
+               netif_start_queue(dev);
+               goto again;
+       }
+       goto done;
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -355,17 +378,26 @@ static int virtnet_probe(struct virtio_device *vdev)
        SET_NETDEV_DEV(dev, &vdev->dev);
 
        /* Do we support "hardware" checksums? */
-       if (csum && vdev->config->feature(vdev, VIRTIO_NET_F_CSUM)) {
+       if (csum && virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) {
                /* This opens up the world of extra features. */
                dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
-               if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_GSO)) {
+               if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
                        dev->features |= NETIF_F_TSO | NETIF_F_UFO
                                | NETIF_F_TSO_ECN | NETIF_F_TSO6;
                }
+               /* Individual feature bits: what can host handle? */
+               if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO4))
+                       dev->features |= NETIF_F_TSO;
+               if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO6))
+                       dev->features |= NETIF_F_TSO6;
+               if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN))
+                       dev->features |= NETIF_F_TSO_ECN;
+               if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO))
+                       dev->features |= NETIF_F_UFO;
        }
 
        /* Configuration may specify what MAC to use.  Otherwise random. */
-       if (vdev->config->feature(vdev, VIRTIO_NET_F_MAC)) {
+       if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) {
                vdev->config->get(vdev,
                                  offsetof(struct virtio_net_config, mac),
                                  dev->dev_addr, dev->addr_len);
@@ -454,7 +486,15 @@ static struct virtio_device_id id_table[] = {
        { 0 },
 };
 
+static unsigned int features[] = {
+       VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC,
+       VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
+       VIRTIO_NET_F_HOST_ECN,
+};
+
 static struct virtio_driver virtio_net = {
+       .feature_table = features,
+       .feature_table_size = ARRAY_SIZE(features),
        .driver.name =  KBUILD_MODNAME,
        .driver.owner = THIS_MODULE,
        .id_table =     id_table,
index b535483..1386678 100644 (file)
@@ -80,19 +80,51 @@ static void add_status(struct virtio_device *dev, unsigned status)
        dev->config->set_status(dev, dev->config->get_status(dev) | status);
 }
 
+void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
+                                        unsigned int fbit)
+{
+       unsigned int i;
+       struct virtio_driver *drv = container_of(vdev->dev.driver,
+                                                struct virtio_driver, driver);
+
+       for (i = 0; i < drv->feature_table_size; i++)
+               if (drv->feature_table[i] == fbit)
+                       return;
+       BUG();
+}
+EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature);
+
 static int virtio_dev_probe(struct device *_d)
 {
-       int err;
+       int err, i;
        struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
        struct virtio_driver *drv = container_of(dev->dev.driver,
                                                 struct virtio_driver, driver);
+       u32 device_features;
 
+       /* We have a driver! */
        add_status(dev, VIRTIO_CONFIG_S_DRIVER);
+
+       /* Figure out what features the device supports. */
+       device_features = dev->config->get_features(dev);
+
+       /* Features supported by both device and driver into dev->features. */
+       memset(dev->features, 0, sizeof(dev->features));
+       for (i = 0; i < drv->feature_table_size; i++) {
+               unsigned int f = drv->feature_table[i];
+               BUG_ON(f >= 32);
+               if (device_features & (1 << f))
+                       set_bit(f, dev->features);
+       }
+
        err = drv->probe(dev);
        if (err)
                add_status(dev, VIRTIO_CONFIG_S_FAILED);
-       else
+       else {
                add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
+               /* They should never have set feature bits beyond 32 */
+               dev->config->set_features(dev, dev->features[0]);
+       }
        return err;
 }
 
@@ -114,6 +146,8 @@ static int virtio_dev_remove(struct device *_d)
 
 int register_virtio_driver(struct virtio_driver *driver)
 {
+       /* Catch this early. */
+       BUG_ON(driver->feature_table_size && !driver->feature_table);
        driver->driver.bus = &virtio_bus;
        driver->driver.probe = virtio_dev_probe;
        driver->driver.remove = virtio_dev_remove;
index 0b3efc3..bfef604 100644 (file)
@@ -155,9 +155,9 @@ static void virtballoon_changed(struct virtio_device *vdev)
 static inline s64 towards_target(struct virtio_balloon *vb)
 {
        u32 v;
-       __virtio_config_val(vb->vdev,
-                           offsetof(struct virtio_balloon_config, num_pages),
-                           &v);
+       vb->vdev->config->get(vb->vdev,
+                             offsetof(struct virtio_balloon_config, num_pages),
+                             &v, sizeof(v));
        return v - vb->num_pages;
 }
 
@@ -227,7 +227,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
        }
 
        vb->tell_host_first
-               = vdev->config->feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST);
+               = virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST);
 
        return 0;
 
@@ -259,7 +259,11 @@ static void virtballoon_remove(struct virtio_device *vdev)
        kfree(vb);
 }
 
+static unsigned int features[] = { VIRTIO_BALLOON_F_MUST_TELL_HOST };
+
 static struct virtio_driver virtio_balloon = {
+       .feature_table = features,
+       .feature_table_size = ARRAY_SIZE(features),
        .driver.name =  KBUILD_MODNAME,
        .driver.owner = THIS_MODULE,
        .id_table =     id_table,
index c0df924..27e9fc9 100644 (file)
@@ -87,23 +87,22 @@ static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev)
        return container_of(vdev, struct virtio_pci_device, vdev);
 }
 
-/* virtio config->feature() implementation */
-static bool vp_feature(struct virtio_device *vdev, unsigned bit)
+/* virtio config->get_features() implementation */
+static u32 vp_get_features(struct virtio_device *vdev)
+{
+       struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+
+       /* When someone needs more than 32 feature bits, we'll need to
+        * steal a bit to indicate that the rest are somewhere else. */
+       return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES);
+}
+
+/* virtio config->set_features() implementation */
+static void vp_set_features(struct virtio_device *vdev, u32 features)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
-       u32 mask;
-
-       /* Since this function is supposed to have the side effect of
-        * enabling a queried feature, we simulate that by doing a read
-        * from the host feature bitmask and then writing to the guest
-        * feature bitmask */
-       mask = ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES);
-       if (mask & (1 << bit)) {
-               mask |= (1 << bit);
-               iowrite32(mask, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
-       }
 
-       return !!(mask & (1 << bit));
+       iowrite32(features, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
 }
 
 /* virtio config->get() implementation */
@@ -145,14 +144,14 @@ static void vp_set_status(struct virtio_device *vdev, u8 status)
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        /* We should never be setting status to 0. */
        BUG_ON(status == 0);
-       return iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
+       iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
 }
 
 static void vp_reset(struct virtio_device *vdev)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        /* 0 status means a reset. */
-       return iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
+       iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
 }
 
 /* the notify function used when creating a virt queue */
@@ -293,7 +292,6 @@ static void vp_del_vq(struct virtqueue *vq)
 }
 
 static struct virtio_config_ops virtio_pci_config_ops = {
-       .feature        = vp_feature,
        .get            = vp_get,
        .set            = vp_set,
        .get_status     = vp_get_status,
@@ -301,6 +299,8 @@ static struct virtio_config_ops virtio_pci_config_ops = {
        .reset          = vp_reset,
        .find_vq        = vp_find_vq,
        .del_vq         = vp_del_vq,
+       .get_features   = vp_get_features,
+       .set_features   = vp_set_features,
 };
 
 /* the PCI probing function */
index c2fa5c6..937a49d 100644 (file)
@@ -184,6 +184,11 @@ static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len)
 
        START_USE(vq);
 
+       if (unlikely(vq->broken)) {
+               END_USE(vq);
+               return NULL;
+       }
+
        if (!more_used(vq)) {
                pr_debug("No more buffers in queue\n");
                END_USE(vq);
index e87fa32..fcca30b 100644 (file)
@@ -14,8 +14,8 @@ DECLARE_PER_CPU(struct ia64_cpu, cpu_devices);
 
 DECLARE_PER_CPU(int, cpu_state);
 
-extern int arch_register_cpu(int num);
 #ifdef CONFIG_HOTPLUG_CPU
+extern int arch_register_cpu(int num);
 extern void arch_unregister_cpu(int);
 #endif
 
index f30e055..2422ac6 100644 (file)
@@ -108,13 +108,11 @@ extern void tsk_clear_notify_resume(struct task_struct *tsk);
 #define TIF_DB_DISABLED                19      /* debug trap disabled for fsyscall */
 #define TIF_FREEZE             20      /* is freezing for suspend */
 #define TIF_RESTORE_RSE                21      /* user RBS is newer than kernel RBS */
-#define TIF_RESTORE_SIGMASK    22      /* restore signal mask in do_signal() */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLESTEP                (1 << TIF_SINGLESTEP)
 #define _TIF_SYSCALL_TRACEAUDIT        (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP)
-#define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
@@ -131,7 +129,18 @@ extern void tsk_clear_notify_resume(struct task_struct *tsk);
 #define TIF_WORK_MASK          (TIF_ALLWORK_MASK&~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT))
 
 #define TS_POLLING             1       /* true if in idle loop and not sleeping */
+#define TS_RESTORE_SIGMASK     2       /* restore signal mask in do_signal() */
 
 #define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
 
+#ifndef __ASSEMBLY__
+#define HAVE_SET_RESTORE_SIGMASK       1
+static inline void set_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       ti->status |= TS_RESTORE_SIGMASK;
+       set_bit(TIF_SIGPENDING, &ti->flags);
+}
+#endif /* !__ASSEMBLY__ */
+
 #endif /* _ASM_IA64_THREAD_INFO_H */
index 78fade0..b7d81b2 100644 (file)
@@ -346,6 +346,11 @@ unifdef-y += videodev.h
 unifdef-y += virtio_config.h
 unifdef-y += virtio_blk.h
 unifdef-y += virtio_net.h
+unifdef-y += virtio_9p.h
+unifdef-y += virtio_balloon.h
+unifdef-y += virtio_console.h
+unifdef-y += virtio_pci.h
+unifdef-y += virtio_ring.h
 unifdef-y += vt.h
 unifdef-y += wait.h
 unifdef-y += wanrouter.h
index 1883a85..552e0ec 100644 (file)
@@ -61,6 +61,7 @@ typedef       void (*irq_flow_handler_t)(unsigned int irq,
 #define IRQ_WAKEUP             0x00100000      /* IRQ triggers system wakeup */
 #define IRQ_MOVE_PENDING       0x00200000      /* need to re-target IRQ destination */
 #define IRQ_NO_BALANCING       0x00400000      /* IRQ is excluded from balancing */
+#define IRQ_SPURIOUS_DISABLED  0x00800000      /* IRQ was disabled by the spurious trap */
 
 #ifdef CONFIG_IRQ_PER_CPU
 # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
index e7d1084..06005fa 100644 (file)
@@ -76,6 +76,7 @@ struct virtqueue_ops {
  * @dev: underlying device.
  * @id: the device type identification (used to match it with a driver).
  * @config: the configuration ops for this device.
+ * @features: the features supported by both driver and device.
  * @priv: private pointer for the driver's use.
  */
 struct virtio_device
@@ -84,6 +85,8 @@ struct virtio_device
        struct device dev;
        struct virtio_device_id id;
        struct virtio_config_ops *config;
+       /* Note that this is a Linux set_bit-style bitmap. */
+       unsigned long features[1];
        void *priv;
 };
 
@@ -94,6 +97,8 @@ void unregister_virtio_device(struct virtio_device *dev);
  * virtio_driver - operations for a virtio I/O driver
  * @driver: underlying device driver (populate name and owner).
  * @id_table: the ids serviced by this driver.
+ * @feature_table: an array of feature numbers supported by this device.
+ * @feature_table_size: number of entries in the feature table array.
  * @probe: the function to call when a device is found.  Returns a token for
  *    remove, or PTR_ERR().
  * @remove: the function when a device is removed.
@@ -103,6 +108,8 @@ void unregister_virtio_device(struct virtio_device *dev);
 struct virtio_driver {
        struct device_driver driver;
        const struct virtio_device_id *id_table;
+       const unsigned int *feature_table;
+       unsigned int feature_table_size;
        int (*probe)(struct virtio_device *dev);
        void (*remove)(struct virtio_device *dev);
        void (*config_changed)(struct virtio_device *dev);
index bca0b10..d4695a3 100644 (file)
@@ -9,6 +9,7 @@
 #define VIRTIO_BLK_F_BARRIER   0       /* Does host support barriers? */
 #define VIRTIO_BLK_F_SIZE_MAX  1       /* Indicates maximum segment size */
 #define VIRTIO_BLK_F_SEG_MAX   2       /* Indicates maximum # of segments */
+#define VIRTIO_BLK_F_GEOMETRY  4       /* Legacy geometry available  */
 
 struct virtio_blk_config
 {
@@ -18,6 +19,12 @@ struct virtio_blk_config
        __le32 size_max;
        /* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */
        __le32 seg_max;
+       /* geometry the device (if VIRTIO_BLK_F_GEOMETRY) */
+       struct virtio_blk_geometry {
+               __le16 cylinders;
+               __u8 heads;
+               __u8 sectors;
+       } geometry;
 } __attribute__((packed));
 
 /* These two define direction. */
@@ -41,13 +48,8 @@ struct virtio_blk_outhdr
        __u64 sector;
 };
 
+/* And this is the final byte of the write scatter-gather list. */
 #define VIRTIO_BLK_S_OK                0
 #define VIRTIO_BLK_S_IOERR     1
 #define VIRTIO_BLK_S_UNSUPP    2
-
-/* This is the first element of the write scatter-gather list */
-struct virtio_blk_inhdr
-{
-       unsigned char status;
-};
 #endif /* _LINUX_VIRTIO_BLK_H */
index d581b29..50db245 100644 (file)
 #define VIRTIO_CONFIG_S_FAILED         0x80
 
 #ifdef __KERNEL__
-struct virtio_device;
+#include <linux/virtio.h>
 
 /**
  * virtio_config_ops - operations for configuring a virtio device
- * @feature: search for a feature in this config
- *     vdev: the virtio_device
- *     bit: the feature bit
- *     Returns true if the feature is supported.  Acknowledges the feature
- *     so the host can see it.
  * @get: read the value of a configuration field
  *     vdev: the virtio_device
  *     offset: the offset of the configuration field
  *     buf: the buffer to write the field value into.
  *     len: the length of the buffer
- *     Note that contents are conventionally little-endian.
  * @set: write the value of a configuration field
  *     vdev: the virtio_device
  *     offset: the offset of the configuration field
  *     buf: the buffer to read the field value from.
  *     len: the length of the buffer
- *     Note that contents are conventionally little-endian.
  * @get_status: read the status byte
  *     vdev: the virtio_device
  *     Returns the status byte
@@ -52,10 +45,15 @@ struct virtio_device;
  *     callback: the virqtueue callback
  *     Returns the new virtqueue or ERR_PTR() (eg. -ENOENT).
  * @del_vq: free a virtqueue found by find_vq().
+ * @get_features: get the array of feature bits for this device.
+ *     vdev: the virtio_device
+ *     Returns the first 32 feature bits (all we currently need).
+ * @set_features: confirm what device features we'll be using.
+ *     vdev: the virtio_device
+ *     feature: the first 32 feature bits
  */
 struct virtio_config_ops
 {
-       bool (*feature)(struct virtio_device *vdev, unsigned bit);
        void (*get)(struct virtio_device *vdev, unsigned offset,
                    void *buf, unsigned len);
        void (*set)(struct virtio_device *vdev, unsigned offset,
@@ -67,43 +65,52 @@ struct virtio_config_ops
                                     unsigned index,
                                     void (*callback)(struct virtqueue *));
        void (*del_vq)(struct virtqueue *vq);
+       u32 (*get_features)(struct virtio_device *vdev);
+       void (*set_features)(struct virtio_device *vdev, u32 features);
 };
 
+/* If driver didn't advertise the feature, it will never appear. */
+void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
+                                        unsigned int fbit);
+
 /**
- * virtio_config_val - look for a feature and get a single virtio config.
- * @vdev: the virtio device
+ * virtio_has_feature - helper to determine if this device has this feature.
+ * @vdev: the device
  * @fbit: the feature bit
- * @offset: the type to search for.
- * @val: a pointer to the value to fill in.
- *
- * The return value is -ENOENT if the feature doesn't exist.  Otherwise
- * the value is endian-corrected and returned in v. */
-#define virtio_config_val(vdev, fbit, offset, v) ({                    \
-       int _err;                                                       \
-       if ((vdev)->config->feature((vdev), (fbit))) {                  \
-               __virtio_config_val((vdev), (offset), (v));             \
-               _err = 0;                                               \
-       } else                                                          \
-               _err = -ENOENT;                                         \
-       _err;                                                           \
-})
+ */
+static inline bool virtio_has_feature(const struct virtio_device *vdev,
+                                     unsigned int fbit)
+{
+       /* Did you forget to fix assumptions on max features? */
+       if (__builtin_constant_p(fbit))
+               BUILD_BUG_ON(fbit >= 32);
+
+       virtio_check_driver_offered_feature(vdev, fbit);
+       return test_bit(fbit, vdev->features);
+}
 
 /**
- * __virtio_config_val - get a single virtio config without feature check.
+ * virtio_config_val - look for a feature and get a virtio config entry.
  * @vdev: the virtio device
+ * @fbit: the feature bit
  * @offset: the type to search for.
  * @val: a pointer to the value to fill in.
  *
- * The value is endian-corrected and returned in v. */
-#define __virtio_config_val(vdev, offset, v) do {                      \
-       BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2             \
-                    && sizeof(*(v)) != 4 && sizeof(*(v)) != 8);        \
-       (vdev)->config->get((vdev), (offset), (v), sizeof(*(v)));       \
-       switch (sizeof(*(v))) {                                         \
-       case 2: le16_to_cpus((__u16 *) v); break;                       \
-       case 4: le32_to_cpus((__u32 *) v); break;                       \
-       case 8: le64_to_cpus((__u64 *) v); break;                       \
-       }                                                               \
-} while(0)
+ * The return value is -ENOENT if the feature doesn't exist.  Otherwise
+ * the config value is copied into whatever is pointed to by v. */
+#define virtio_config_val(vdev, fbit, offset, v) \
+       virtio_config_buf((vdev), (fbit), (offset), (v), sizeof(v))
+
+static inline int virtio_config_buf(struct virtio_device *vdev,
+                                   unsigned int fbit,
+                                   unsigned int offset,
+                                   void *buf, unsigned len)
+{
+       if (!virtio_has_feature(vdev, fbit))
+               return -ENOENT;
+
+       vdev->config->get(vdev, offset, buf, len);
+       return 0;
+}
 #endif /* __KERNEL__ */
 #endif /* _LINUX_VIRTIO_CONFIG_H */
index 1ea3351..9405aa6 100644 (file)
@@ -6,9 +6,18 @@
 #define VIRTIO_ID_NET  1
 
 /* The feature bitmap for virtio net */
-#define VIRTIO_NET_F_CSUM      0       /* Can handle pkts w/ partial csum */
+#define VIRTIO_NET_F_CSUM      0       /* Host handles pkts w/ partial csum */
+#define VIRTIO_NET_F_GUEST_CSUM        1       /* Guest handles pkts w/ partial csum */
 #define VIRTIO_NET_F_MAC       5       /* Host has given MAC address. */
-#define VIRTIO_NET_F_GSO       6       /* Can handle pkts w/ any GSO type */
+#define VIRTIO_NET_F_GSO       6       /* Host handles pkts w/ any GSO type */
+#define VIRTIO_NET_F_GUEST_TSO4        7       /* Guest can handle TSOv4 in. */
+#define VIRTIO_NET_F_GUEST_TSO6        8       /* Guest can handle TSOv6 in. */
+#define VIRTIO_NET_F_GUEST_ECN 9       /* Guest can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_GUEST_UFO 10      /* Guest can handle UFO in. */
+#define VIRTIO_NET_F_HOST_TSO4 11      /* Host can handle TSOv4 in. */
+#define VIRTIO_NET_F_HOST_TSO6 12      /* Host can handle TSOv6 in. */
+#define VIRTIO_NET_F_HOST_ECN  13      /* Host can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_HOST_UFO  14      /* Host can handle UFO in. */
 
 struct virtio_net_config
 {
index 46e4ad1..46d6611 100644 (file)
@@ -150,6 +150,26 @@ void disable_irq(unsigned int irq)
 }
 EXPORT_SYMBOL(disable_irq);
 
+static void __enable_irq(struct irq_desc *desc, unsigned int irq)
+{
+       switch (desc->depth) {
+       case 0:
+               printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
+               WARN_ON(1);
+               break;
+       case 1: {
+               unsigned int status = desc->status & ~IRQ_DISABLED;
+
+               /* Prevent probing on this irq: */
+               desc->status = status | IRQ_NOPROBE;
+               check_irq_resend(desc, irq);
+               /* fall-through */
+       }
+       default:
+               desc->depth--;
+       }
+}
+
 /**
  *     enable_irq - enable handling of an irq
  *     @irq: Interrupt to enable
@@ -169,22 +189,7 @@ void enable_irq(unsigned int irq)
                return;
 
        spin_lock_irqsave(&desc->lock, flags);
-       switch (desc->depth) {
-       case 0:
-               printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
-               WARN_ON(1);
-               break;
-       case 1: {
-               unsigned int status = desc->status & ~IRQ_DISABLED;
-
-               /* Prevent probing on this irq: */
-               desc->status = status | IRQ_NOPROBE;
-               check_irq_resend(desc, irq);
-               /* fall-through */
-       }
-       default:
-               desc->depth--;
-       }
+       __enable_irq(desc, irq);
        spin_unlock_irqrestore(&desc->lock, flags);
 }
 EXPORT_SYMBOL(enable_irq);
@@ -365,7 +370,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
                        compat_irq_chip_set_default_handler(desc);
 
                desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING |
-                                 IRQ_INPROGRESS);
+                                 IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);
 
                if (!(desc->status & IRQ_NOAUTOEN)) {
                        desc->depth = 0;
@@ -381,6 +386,16 @@ int setup_irq(unsigned int irq, struct irqaction *new)
        /* Reset broken irq detection when installing new handler */
        desc->irq_count = 0;
        desc->irqs_unhandled = 0;
+
+       /*
+        * Check whether we disabled the irq via the spurious handler
+        * before. Reenable it and give it another chance.
+        */
+       if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) {
+               desc->status &= ~IRQ_SPURIOUS_DISABLED;
+               __enable_irq(desc, irq);
+       }
+
        spin_unlock_irqrestore(&desc->lock, flags);
 
        new->irq = irq;
index 088dabb..c66d3f1 100644 (file)
@@ -209,8 +209,8 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
                 * Now kill the IRQ
                 */
                printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
-               desc->status |= IRQ_DISABLED;
-               desc->depth = 1;
+               desc->status |= IRQ_DISABLED | IRQ_SPURIOUS_DISABLED;
+               desc->depth++;
                desc->chip->disable(irq);
        }
        desc->irqs_unhandled = 0;