diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/processor_perflib.c | 4 | ||||
-rw-r--r-- | drivers/firmware/efivars.c | 29 | ||||
-rw-r--r-- | drivers/isdn/gigaset/common.c | 61 | ||||
-rw-r--r-- | drivers/kvm/kvm.h | 1 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 17 | ||||
-rw-r--r-- | drivers/kvm/mmu.c | 16 | ||||
-rw-r--r-- | drivers/kvm/paging_tmpl.h | 77 | ||||
-rw-r--r-- | drivers/kvm/svm.c | 23 | ||||
-rw-r--r-- | drivers/md/bitmap.c | 12 | ||||
-rw-r--r-- | drivers/md/dm.c | 27 | ||||
-rw-r--r-- | drivers/md/md.c | 32 | ||||
-rw-r--r-- | drivers/md/raid1.c | 7 | ||||
-rw-r--r-- | drivers/md/raid5.c | 5 | ||||
-rw-r--r-- | drivers/rtc/rtc-sysfs.c | 2 | ||||
-rw-r--r-- | drivers/spi/pxa2xx_spi.c | 5 | ||||
-rw-r--r-- | drivers/spi/spi.c | 23 | ||||
-rw-r--r-- | drivers/spi/spi_s3c24xx.c | 28 |
17 files changed, 235 insertions, 134 deletions
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 5207f9e4b44..cbb6f0814ce 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -322,10 +322,6 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr) if (result) return result; - result = acpi_processor_get_platform_limit(pr); - if (result) - return result; - return 0; } diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 5ab5e393b88..c6281ccd4fe 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -122,8 +122,6 @@ struct efivar_entry { struct kobject kobj; }; -#define get_efivar_entry(n) list_entry(n, struct efivar_entry, list) - struct efivar_attribute { struct attribute attr; ssize_t (*show) (struct efivar_entry *entry, char *buf); @@ -386,9 +384,6 @@ static struct sysfs_ops efivar_attr_ops = { static void efivar_release(struct kobject *kobj) { struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj); - spin_lock(&efivars_lock); - list_del(&var->list); - spin_unlock(&efivars_lock); kfree(var); } @@ -430,9 +425,8 @@ static ssize_t efivar_create(struct subsystem *sub, const char *buf, size_t count) { struct efi_variable *new_var = (struct efi_variable *)buf; - struct efivar_entry *search_efivar = NULL; + struct efivar_entry *search_efivar, *n; unsigned long strsize1, strsize2; - struct list_head *pos, *n; efi_status_t status = EFI_NOT_FOUND; int found = 0; @@ -444,8 +438,7 @@ efivar_create(struct subsystem *sub, const char *buf, size_t count) /* * Does this variable already exist? */ - list_for_each_safe(pos, n, &efivar_list) { - search_efivar = get_efivar_entry(pos); + list_for_each_entry_safe(search_efivar, n, &efivar_list, list) { strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024); strsize2 = utf8_strsize(new_var->VariableName, 1024); if (strsize1 == strsize2 && @@ -490,9 +483,8 @@ static ssize_t efivar_delete(struct subsystem *sub, const char *buf, size_t count) { struct efi_variable *del_var = (struct efi_variable *)buf; - struct efivar_entry *search_efivar = NULL; + struct efivar_entry *search_efivar, *n; unsigned long strsize1, strsize2; - struct list_head *pos, *n; efi_status_t status = EFI_NOT_FOUND; int found = 0; @@ -504,8 +496,7 @@ efivar_delete(struct subsystem *sub, const char *buf, size_t count) /* * Does this variable already exist? */ - list_for_each_safe(pos, n, &efivar_list) { - search_efivar = get_efivar_entry(pos); + list_for_each_entry_safe(search_efivar, n, &efivar_list, list) { strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024); strsize2 = utf8_strsize(del_var->VariableName, 1024); if (strsize1 == strsize2 && @@ -537,9 +528,9 @@ efivar_delete(struct subsystem *sub, const char *buf, size_t count) spin_unlock(&efivars_lock); return -EIO; } + list_del(&search_efivar->list); /* We need to release this lock before unregistering. */ spin_unlock(&efivars_lock); - efivar_unregister(search_efivar); /* It's dead Jim.... */ @@ -768,10 +759,14 @@ out_free: static void __exit efivars_exit(void) { - struct list_head *pos, *n; + struct efivar_entry *entry, *n; - list_for_each_safe(pos, n, &efivar_list) - efivar_unregister(get_efivar_entry(pos)); + list_for_each_entry_safe(entry, n, &efivar_list, list) { + spin_lock(&efivars_lock); + list_del(&entry->list); + spin_unlock(&efivars_lock); + efivar_unregister(entry); + } subsystem_unregister(&vars_subsys); firmware_unregister(&efi_subsys); diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 95eff3b2917..4f75cce6fdf 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -356,16 +356,17 @@ static struct cardstate *alloc_cs(struct gigaset_driver *drv) { unsigned long flags; unsigned i; - static struct cardstate *ret = NULL; + struct cardstate *ret = NULL; spin_lock_irqsave(&drv->lock, flags); for (i = 0; i < drv->minors; ++i) { if (!(drv->flags[i] & VALID_MINOR)) { - drv->flags[i] = VALID_MINOR; - ret = drv->cs + i; - } - if (ret) + if (try_module_get(drv->owner)) { + drv->flags[i] = VALID_MINOR; + ret = drv->cs + i; + } break; + } } spin_unlock_irqrestore(&drv->lock, flags); return ret; @@ -376,6 +377,8 @@ static void free_cs(struct cardstate *cs) unsigned long flags; struct gigaset_driver *drv = cs->driver; spin_lock_irqsave(&drv->lock, flags); + if (drv->flags[cs->minor_index] & VALID_MINOR) + module_put(drv->owner); drv->flags[cs->minor_index] = 0; spin_unlock_irqrestore(&drv->lock, flags); } @@ -579,7 +582,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) skb_reserve(bcs->skb, HW_HDR_LEN); else { - warn("could not allocate skb\n"); + warn("could not allocate skb"); bcs->inputstate |= INS_skip_frame; } @@ -632,17 +635,25 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, int i; gig_dbg(DEBUG_INIT, "allocating cs"); - cs = alloc_cs(drv); - if (!cs) - goto error; + if (!(cs = alloc_cs(drv))) { + err("maximum number of devices exceeded"); + return NULL; + } + mutex_init(&cs->mutex); + mutex_lock(&cs->mutex); + gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1); cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL); - if (!cs->bcs) + if (!cs->bcs) { + err("out of memory"); goto error; + } gig_dbg(DEBUG_INIT, "allocating inbuf"); cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL); - if (!cs->inbuf) + if (!cs->inbuf) { + err("out of memory"); goto error; + } cs->cs_init = 0; cs->channels = channels; @@ -654,8 +665,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, spin_lock_init(&cs->ev_lock); cs->ev_tail = 0; cs->ev_head = 0; - mutex_init(&cs->mutex); - mutex_lock(&cs->mutex); tasklet_init(&cs->event_tasklet, &gigaset_handle_event, (unsigned long) cs); @@ -684,8 +693,10 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, for (i = 0; i < channels; ++i) { gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); - if (!gigaset_initbcs(cs->bcs + i, cs, i)) + if (!gigaset_initbcs(cs->bcs + i, cs, i)) { + err("could not allocate channel %d data", i); goto error; + } } ++cs->cs_init; @@ -720,8 +731,10 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, make_valid(cs, VALID_ID); ++cs->cs_init; gig_dbg(DEBUG_INIT, "setting up hw"); - if (!cs->ops->initcshw(cs)) + if (!cs->ops->initcshw(cs)) { + err("could not allocate device specific data"); goto error; + } ++cs->cs_init; @@ -743,8 +756,8 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, mutex_unlock(&cs->mutex); return cs; -error: if (cs) - mutex_unlock(&cs->mutex); +error: + mutex_unlock(&cs->mutex); gig_dbg(DEBUG_INIT, "failed"); gigaset_freecs(cs); return NULL; @@ -1040,7 +1053,6 @@ void gigaset_freedriver(struct gigaset_driver *drv) spin_unlock_irqrestore(&driver_lock, flags); gigaset_if_freedriver(drv); - module_put(drv->owner); kfree(drv->cs); kfree(drv->flags); @@ -1072,10 +1084,6 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, if (!drv) return NULL; - if (!try_module_get(owner)) - goto out1; - - drv->cs = NULL; drv->have_tty = 0; drv->minor = minor; drv->minors = minors; @@ -1087,11 +1095,11 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL); if (!drv->cs) - goto out2; + goto error; drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL); if (!drv->flags) - goto out3; + goto error; for (i = 0; i < minors; ++i) { drv->flags[i] = 0; @@ -1108,11 +1116,8 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, return drv; -out3: +error: kfree(drv->cs); -out2: - module_put(owner); -out1: kfree(drv); return NULL; } diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index 91e0c75aca8..2db1ca4c680 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h @@ -242,6 +242,7 @@ struct kvm_vcpu { u64 pdptrs[4]; /* pae */ u64 shadow_efer; u64 apic_base; + u64 ia32_misc_enable_msr; int nmsrs; struct vmx_msr_entry *guest_msrs; struct vmx_msr_entry *host_msrs; diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index be4651abe72..b10972ed0c9 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c @@ -1226,6 +1226,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) case MSR_IA32_APICBASE: data = vcpu->apic_base; break; + case MSR_IA32_MISC_ENABLE: + data = vcpu->ia32_misc_enable_msr; + break; #ifdef CONFIG_X86_64 case MSR_EFER: data = vcpu->shadow_efer; @@ -1297,6 +1300,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) case MSR_IA32_APICBASE: vcpu->apic_base = data; break; + case MSR_IA32_MISC_ENABLE: + vcpu->ia32_misc_enable_msr = data; + break; default: printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr); return 1; @@ -1600,6 +1606,10 @@ static u32 msrs_to_save[] = { static unsigned num_msrs_to_save; +static u32 emulated_msrs[] = { + MSR_IA32_MISC_ENABLE, +}; + static __init void kvm_init_msr_list(void) { u32 dummy[2]; @@ -1925,7 +1935,7 @@ static long kvm_dev_ioctl(struct file *filp, if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list)) goto out; n = msr_list.nmsrs; - msr_list.nmsrs = num_msrs_to_save; + msr_list.nmsrs = num_msrs_to_save + ARRAY_SIZE(emulated_msrs); if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list)) goto out; r = -E2BIG; @@ -1935,6 +1945,11 @@ static long kvm_dev_ioctl(struct file *filp, if (copy_to_user(user_msr_list->indices, &msrs_to_save, num_msrs_to_save * sizeof(u32))) goto out; + if (copy_to_user(user_msr_list->indices + + num_msrs_to_save * sizeof(u32), + &emulated_msrs, + ARRAY_SIZE(emulated_msrs) * sizeof(u32))) + goto out; r = 0; break; } diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c index c6f972914f0..22c426cd8cb 100644 --- a/drivers/kvm/mmu.c +++ b/drivers/kvm/mmu.c @@ -143,6 +143,7 @@ static int dbg = 1; #define PFERR_PRESENT_MASK (1U << 0) #define PFERR_WRITE_MASK (1U << 1) #define PFERR_USER_MASK (1U << 2) +#define PFERR_FETCH_MASK (1U << 4) #define PT64_ROOT_LEVEL 4 #define PT32_ROOT_LEVEL 2 @@ -168,6 +169,11 @@ static int is_cpuid_PSE36(void) return 1; } +static int is_nx(struct kvm_vcpu *vcpu) +{ + return vcpu->shadow_efer & EFER_NX; +} + static int is_present_pte(unsigned long pte) { return pte & PT_PRESENT_MASK; @@ -992,16 +998,6 @@ static inline int fix_read_pf(u64 *shadow_ent) return 0; } -static int may_access(u64 pte, int write, int user) -{ - - if (user && !(pte & PT_USER_MASK)) - return 0; - if (write && !(pte & PT_WRITABLE_MASK)) - return 0; - return 1; -} - static void paging_free(struct kvm_vcpu *vcpu) { nonpaging_free(vcpu); diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h index 6bc41950fbb..149fa45fd9a 100644 --- a/drivers/kvm/paging_tmpl.h +++ b/drivers/kvm/paging_tmpl.h @@ -63,13 +63,15 @@ struct guest_walker { pt_element_t *ptep; pt_element_t inherited_ar; gfn_t gfn; + u32 error_code; }; /* * Fetch a guest pte for a guest virtual address */ -static void FNAME(walk_addr)(struct guest_walker *walker, - struct kvm_vcpu *vcpu, gva_t addr) +static int FNAME(walk_addr)(struct guest_walker *walker, + struct kvm_vcpu *vcpu, gva_t addr, + int write_fault, int user_fault, int fetch_fault) { hpa_t hpa; struct kvm_memory_slot *slot; @@ -86,7 +88,7 @@ static void FNAME(walk_addr)(struct guest_walker *walker, walker->ptep = &vcpu->pdptrs[(addr >> 30) & 3]; root = *walker->ptep; if (!(root & PT_PRESENT_MASK)) - return; + goto not_present; --walker->level; } #endif @@ -111,11 +113,23 @@ static void FNAME(walk_addr)(struct guest_walker *walker, ASSERT(((unsigned long)walker->table & PAGE_MASK) == ((unsigned long)ptep & PAGE_MASK)); - if (is_present_pte(*ptep) && !(*ptep & PT_ACCESSED_MASK)) - *ptep |= PT_ACCESSED_MASK; - if (!is_present_pte(*ptep)) - break; + goto not_present; + + if (write_fault && !is_writeble_pte(*ptep)) + if (user_fault || is_write_protection(vcpu)) + goto access_error; + + if (user_fault && !(*ptep & PT_USER_MASK)) + goto access_error; + +#if PTTYPE == 64 + if (fetch_fault && is_nx(vcpu) && (*ptep & PT64_NX_MASK)) + goto access_error; +#endif + + if (!(*ptep & PT_ACCESSED_MASK)) + *ptep |= PT_ACCESSED_MASK; /* avoid rmw */ if (walker->level == PT_PAGE_TABLE_LEVEL) { walker->gfn = (*ptep & PT_BASE_ADDR_MASK) @@ -146,6 +160,23 @@ static void FNAME(walk_addr)(struct guest_walker *walker, } walker->ptep = ptep; pgprintk("%s: pte %llx\n", __FUNCTION__, (u64)*ptep); + return 1; + +not_present: + walker->error_code = 0; + goto err; + +access_error: + walker->error_code = PFERR_PRESENT_MASK; + +err: + if (write_fault) + walker->error_code |= PFERR_WRITE_MASK; + if (user_fault) + walker->error_code |= PFERR_USER_MASK; + if (fetch_fault) + walker->error_code |= PFERR_FETCH_MASK; + return 0; } static void FNAME(release_walker)(struct guest_walker *walker) @@ -347,8 +378,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code) { int write_fault = error_code & PFERR_WRITE_MASK; - int pte_present = error_code & PFERR_PRESENT_MASK; int user_fault = error_code & PFERR_USER_MASK; + int fetch_fault = error_code & PFERR_FETCH_MASK; struct guest_walker walker; u64 *shadow_pte; int fixed; @@ -365,19 +396,20 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, /* * Look up the shadow pte for the faulting address. */ - FNAME(walk_addr)(&walker, vcpu, addr); - shadow_pte = FNAME(fetch)(vcpu, addr, &walker); + r = FNAME(walk_addr)(&walker, vcpu, addr, write_fault, user_fault, + fetch_fault); /* * The page is not mapped by the guest. Let the guest handle it. */ - if (!shadow_pte) { - pgprintk("%s: not mapped\n", __FUNCTION__); - inject_page_fault(vcpu, addr, error_code); + if (!r) { + pgprintk("%s: guest page fault\n", __FUNCTION__); + inject_page_fault(vcpu, addr, walker.error_code); FNAME(release_walker)(&walker); return 0; } + shadow_pte = FNAME(fetch)(vcpu, addr, &walker); pgprintk("%s: shadow pte %p %llx\n", __FUNCTION__, shadow_pte, *shadow_pte); @@ -399,22 +431,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, * mmio: emulate if accessible, otherwise its a guest fault. */ if (is_io_pte(*shadow_pte)) { - if (may_access(*shadow_pte, write_fault, user_fault)) - return 1; - pgprintk("%s: io work, no access\n", __FUNCTION__); - inject_page_fault(vcpu, addr, - error_code | PFERR_PRESENT_MASK); - kvm_mmu_audit(vcpu, "post page fault (io)"); - return 0; - } - - /* - * pte not present, guest page fault. - */ - if (pte_present && !fixed && !write_pt) { - inject_page_fault(vcpu, addr, error_code); - kvm_mmu_audit(vcpu, "post page fault (guest)"); - return 0; + return 1; } ++kvm_stat.pf_fixed; @@ -429,7 +446,7 @@ static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr) pt_element_t guest_pte; gpa_t gpa; - FNAME(walk_addr)(&walker, vcpu, vaddr); + FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0); guest_pte = *walker.ptep; FNAME(release_walker)(&walker); diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 7397bfbbcb1..9c70ff65e6b 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c @@ -502,6 +502,7 @@ static void init_vmcb(struct vmcb *vmcb) (1ULL << INTERCEPT_IOIO_PROT) | (1ULL << INTERCEPT_MSR_PROT) | (1ULL << INTERCEPT_TASK_SWITCH) | + (1ULL << INTERCEPT_SHUTDOWN) | (1ULL << INTERCEPT_VMRUN) | (1ULL << INTERCEPT_VMMCALL) | (1ULL << INTERCEPT_VMLOAD) | @@ -680,14 +681,14 @@ static void svm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l) static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) { - dt->limit = vcpu->svm->vmcb->save.ldtr.limit; - dt->base = vcpu->svm->vmcb->save.ldtr.base; + dt->limit = vcpu->svm->vmcb->save.idtr.limit; + dt->base = vcpu->svm->vmcb->save.idtr.base; } static void svm_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) { - vcpu->svm->vmcb->save.ldtr.limit = dt->limit; - vcpu->svm->vmcb->save.ldtr.base = dt->base ; + vcpu->svm->vmcb->save.idtr.limit = dt->limit; + vcpu->svm->vmcb->save.idtr.base = dt->base ; } static void svm_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) @@ -892,6 +893,19 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) return 0; } +static int shutdown_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) +{ + /* + * VMCB is undefined after a SHUTDOWN intercept + * so reinitialize it. + */ + memset(vcpu->svm->vmcb, 0, PAGE_SIZE); + init_vmcb(vcpu->svm->vmcb); + + kvm_run->exit_reason = KVM_EXIT_SHUTDOWN; + return 0; +} + static int io_get_override(struct kvm_vcpu *vcpu, struct vmcb_seg **seg, int *addr_override) @@ -1249,6 +1263,7 @@ static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu, [SVM_EXIT_IOIO] = io_interception, [SVM_EXIT_MSR] = msr_interception, [SVM_EXIT_TASK_SWITCH] = task_switch_interception, + [SVM_EXIT_SHUTDOWN] = shutdown_interception, [SVM_EXIT_VMRUN] = invalid_op_interception, [SVM_EXIT_VMMCALL] = invalid_op_interception, [SVM_EXIT_VMLOAD] = invalid_op_interception, diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 5432d07c074..11108165e26 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -479,9 +479,12 @@ static int bitmap_read_sb(struct bitmap *bitmap) int err = -EINVAL; /* page 0 is the superblock, read it... */ - if (bitmap->file) - bitmap->sb_page = read_page(bitmap->file, 0, bitmap, PAGE_SIZE); - else { + if (bitmap->file) { + loff_t isize = i_size_read(bitmap->file->f_mapping->host); + int bytes = isize > PAGE_SIZE ? PAGE_SIZE : isize; + + bitmap->sb_page = read_page(bitmap->file, 0, bitmap, bytes); + } else { bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0); } if (IS_ERR(bitmap->sb_page)) { @@ -877,7 +880,8 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) int count; /* unmap the old page, we're done with it */ if (index == num_pages-1) - count = bytes - index * PAGE_SIZE; + count = bytes + sizeof(bitmap_super_t) + - index * PAGE_SIZE; else count = PAGE_SIZE; if (index == 0) { diff --git a/drivers/md/dm.c b/drivers/md/dm.c index fe7c56e1043..3668b170ea6 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1116,7 +1116,8 @@ static int __bind(struct mapped_device *md, struct dm_table *t) if (size != get_capacity(md->disk)) memset(&md->geometry, 0, sizeof(md->geometry)); - __set_size(md, size); + if (md->suspended_bdev) + __set_size(md, size); if (size == 0) return 0; @@ -1264,6 +1265,11 @@ int dm_swap_table(struct mapped_device *md, struct dm_table *table) if (!dm_suspended(md)) goto out; + /* without bdev, the device size cannot be changed */ + if (!md->suspended_bdev) + if (get_capacity(md->disk) != dm_table_get_size(table)) + goto out; + __unbind(md); r = __bind(md, table); @@ -1341,11 +1347,14 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) /* This does not get reverted if there's an error later. */ dm_table_presuspend_targets(map); - md->suspended_bdev = bdget_disk(md->disk, 0); - if (!md->suspended_bdev) { - DMWARN("bdget failed in dm_suspend"); - r = -ENOMEM; - goto flush_and_out; + /* bdget() can stall if the pending I/Os are not flushed */ + if (!noflush) { + md->suspended_bdev = bdget_disk(md->disk, 0); + if (!md->suspended_bdev) { + DMWARN("bdget failed in dm_suspend"); + r = -ENOMEM; + goto flush_and_out; + } } /* @@ -1473,8 +1482,10 @@ int dm_resume(struct mapped_device *md) unlock_fs(md); - bdput(md->suspended_bdev); - md->suspended_bdev = NULL; + if (md->suspended_bdev) { + bdput(md->suspended_bdev); + md->suspended_bdev = NULL; + } clear_bit(DMF_SUSPENDED, &md->flags); diff --git a/drivers/md/md.c b/drivers/md/md.c index d1cb45f6d6a..e8807ea5377 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1633,7 +1633,8 @@ repeat: * and 'events' is odd, we can roll back to the previous clean state */ if (nospares && (mddev->in_sync && mddev->recovery_cp == MaxSector) - && (mddev->events & 1)) + && (mddev->events & 1) + && mddev->events != 1) mddev->events--; else { /* otherwise we have to go forward and ... */ @@ -3563,6 +3564,8 @@ static int get_bitmap_file(mddev_t * mddev, void __user * arg) char *ptr, *buf = NULL; int err = -ENOMEM; + md_allow_write(mddev); + file = kmalloc(sizeof(*file), GFP_KERNEL); if (!file) goto out; @@ -5031,6 +5034,33 @@ void md_write_end(mddev_t *mddev) } } +/* md_allow_write(mddev) + * Calling this ensures that the array is marked 'active' so that writes + * may proceed without blocking. It is important to call this before + * attempting a GFP_KERNEL allocation while holding the mddev lock. + * Must be called with mddev_lock held. + */ +void md_allow_write(mddev_t *mddev) +{ + if (!mddev->pers) + return; + if (mddev->ro) + return; + + spin_lock_irq(&mddev->write_lock); + if (mddev->in_sync) { + mddev->in_sync = 0; + set_bit(MD_CHANGE_CLEAN, &mddev->flags); + if (mddev->safemode_delay && + mddev->safemode == 0) + mddev->safemode = 1; + spin_unlock_irq(&mddev->write_lock); + md_update_sb(mddev, 0); + } else + spin_unlock_irq(&mddev->write_lock); +} +EXPORT_SYMBOL_GPL(md_allow_write); + static DECLARE_WAIT_QUEUE_HEAD(resync_wait); #define SYNC_MARKS 10 diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 164b25dca10..97ee870b265 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1266,6 +1266,11 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) sbio->bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset; sbio->bi_bdev = conf->mirrors[i].rdev->bdev; + for (j = 0; j < vcnt ; j++) + memcpy(page_address(sbio->bi_io_vec[j].bv_page), + page_address(pbio->bi_io_vec[j].bv_page), + PAGE_SIZE); + } } } @@ -2099,6 +2104,8 @@ static int raid1_reshape(mddev_t *mddev) return -EINVAL; } + md_allow_write(mddev); + raid_disks = mddev->raid_disks + mddev->delta_disks; if (raid_disks < conf->raid_disks) { diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index be008f034ad..467c16982d0 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -405,6 +405,8 @@ static int resize_stripes(raid5_conf_t *conf, int newsize) if (newsize <= conf->pool_size) return 0; /* never bother to shrink */ + md_allow_write(conf->mddev); + /* Step 1 */ sc = kmem_cache_create(conf->cache_name[1-conf->active_name], sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev), @@ -2678,7 +2680,7 @@ static int chunk_aligned_read(request_queue_t *q, struct bio * raid_bio) mdk_rdev_t *rdev; if (!in_chunk_boundary(mddev, raid_bio)) { - printk("chunk_aligned_read : non aligned\n"); + PRINTK("chunk_aligned_read : non aligned\n"); return 0; } /* @@ -3250,6 +3252,7 @@ raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len) else break; } + md_allow_write(mddev); while (new > conf->max_nr_stripes) { if (grow_one_stripe(conf)) conf->max_nr_stripes++; diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 9418a59fb36..2ddd0cf0714 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c @@ -78,7 +78,7 @@ static struct attribute_group rtc_attr_group = { .attrs = rtc_attrs, }; -static int __devinit rtc_sysfs_add_device(struct class_device *class_dev, +static int rtc_sysfs_add_device(struct class_device *class_dev, struct class_interface *class_intf) { int err; diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 6ed3f1da929..8b41f9cc256 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -1169,8 +1169,9 @@ static int setup(struct spi_device *spi) spi->bits_per_word - 16 : spi->bits_per_word) | SSCR0_SSE | (spi->bits_per_word > 16 ? SSCR0_EDSS : 0); - chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) << 4) - | (((spi->mode & SPI_CPOL) != 0) << 3); + chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH); + chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0) + | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0); /* NOTE: PXA25x_SSP _could_ use external clocking ... */ if (drv_data->ssp_type != PXA25x_SSP) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 270e6211c2e..6307428d2c9 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -366,7 +366,6 @@ spi_alloc_master(struct device *dev, unsigned size) class_device_initialize(&master->cdev); master->cdev.class = &spi_master_class; - kobj_set_kset_s(&master->cdev, spi_master_class.subsys); master->cdev.dev = get_device(dev); spi_master_set_devdata(master, &master[1]); @@ -466,14 +465,20 @@ EXPORT_SYMBOL_GPL(spi_unregister_master); */ struct spi_master *spi_busnum_to_master(u16 bus_num) { - char name[9]; - struct kobject *bus; - - snprintf(name, sizeof name, "spi%u", bus_num); - bus = kset_find_obj(&spi_master_class.subsys.kset, name); - if (bus) - return container_of(bus, struct spi_master, cdev.kobj); - return NULL; + struct class_device *cdev; + struct spi_master *master = NULL; + struct spi_master *m; + + down(&spi_master_class.sem); + list_for_each_entry(cdev, &spi_master_class.children, node) { + m = container_of(cdev, struct spi_master, cdev); + if (m->bus_num == bus_num) { + master = spi_master_get(m); + break; + } + } + up(&spi_master_class.sem); + return master; } EXPORT_SYMBOL_GPL(spi_busnum_to_master); diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index 8ca08713528..651379c51ae 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c @@ -10,9 +10,6 @@ * */ - -//#define DEBUG - #include <linux/init.h> #include <linux/spinlock.h> #include <linux/workqueue.h> @@ -44,6 +41,9 @@ struct s3c24xx_spi { int len; int count; + int (*set_cs)(struct s3c2410_spi_info *spi, + int cs, int pol); + /* data buffers */ const unsigned char *tx; unsigned char *rx; @@ -64,6 +64,11 @@ static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev) return spi_master_get_devdata(sdev->master); } +static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol) +{ + s3c2410_gpio_setpin(spi->pin_cs, pol); +} + static void s3c24xx_spi_chipsel(struct spi_device *spi, int value) { struct s3c24xx_spi *hw = to_hw(spi); @@ -72,10 +77,7 @@ static void s3c24xx_spi_chipsel(struct spi_device *spi, int value) switch (value) { case BITBANG_CS_INACTIVE: - if (hw->pdata->set_cs) - hw->pdata->set_cs(hw->pdata, value, cspol); - else - s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol ^ 1); + hw->pdata->set_cs(hw->pdata, spi->chip_select, cspol^1); break; case BITBANG_CS_ACTIVE: @@ -96,14 +98,9 @@ static void s3c24xx_spi_chipsel(struct spi_device *spi, int value) /* write new configration */ writeb(spcon, hw->regs + S3C2410_SPCON); - - if (hw->pdata->set_cs) - hw->pdata->set_cs(hw->pdata, value, cspol); - else - s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol); + hw->pdata->set_cs(hw->pdata, spi->chip_select, cspol); break; - } } @@ -330,9 +327,12 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) /* setup any gpio we can */ if (!hw->pdata->set_cs) { + hw->set_cs = s3c24xx_spi_gpiocs; + s3c2410_gpio_setpin(hw->pdata->pin_cs, 1); s3c2410_gpio_cfgpin(hw->pdata->pin_cs, S3C2410_GPIO_OUTPUT); - } + } else + hw->set_cs = hw->pdata->set_cs; /* register our spi controller */ |