diff --git a/[refs] b/[refs] index 78c975426f86..1e9157490cfb 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 66120005e65eed8a05b14a36ab448bdec42f0d6b +refs/heads/master: 18d6522b86d21a04c8ac1ea79747e2e434a956d9 diff --git a/trunk/arch/arm/include/asm/cnt32_to_63.h b/trunk/arch/arm/include/asm/cnt32_to_63.h new file mode 100644 index 000000000000..480c873fa746 --- /dev/null +++ b/trunk/arch/arm/include/asm/cnt32_to_63.h @@ -0,0 +1,78 @@ +/* + * include/asm/cnt32_to_63.h -- extend a 32-bit counter to 63 bits + * + * Author: Nicolas Pitre + * Created: December 3, 2006 + * Copyright: MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + */ + +#ifndef __INCLUDE_CNT32_TO_63_H__ +#define __INCLUDE_CNT32_TO_63_H__ + +#include +#include +#include + +/* + * Prototype: u64 cnt32_to_63(u32 cnt) + * Many hardware clock counters are only 32 bits wide and therefore have + * a relatively short period making wrap-arounds rather frequent. This + * is a problem when implementing sched_clock() for example, where a 64-bit + * non-wrapping monotonic value is expected to be returned. + * + * To overcome that limitation, let's extend a 32-bit counter to 63 bits + * in a completely lock free fashion. Bits 0 to 31 of the clock are provided + * by the hardware while bits 32 to 62 are stored in memory. The top bit in + * memory is used to synchronize with the hardware clock half-period. When + * the top bit of both counters (hardware and in memory) differ then the + * memory is updated with a new value, incrementing it when the hardware + * counter wraps around. + * + * Because a word store in memory is atomic then the incremented value will + * always be in synch with the top bit indicating to any potential concurrent + * reader if the value in memory is up to date or not with regards to the + * needed increment. And any race in updating the value in memory is harmless + * as the same value would simply be stored more than once. + * + * The only restriction for the algorithm to work properly is that this + * code must be executed at least once per each half period of the 32-bit + * counter to properly update the state bit in memory. This is usually not a + * problem in practice, but if it is then a kernel timer could be scheduled + * to manage for this code to be executed often enough. + * + * Note that the top bit (bit 63) in the returned value should be considered + * as garbage. It is not cleared here because callers are likely to use a + * multiplier on the returned value which can get rid of the top bit + * implicitly by making the multiplier even, therefore saving on a runtime + * clear-bit instruction. Otherwise caller must remember to clear the top + * bit explicitly. + */ + +/* this is used only to give gcc a clue about good code generation */ +typedef union { + struct { +#if defined(__LITTLE_ENDIAN) + u32 lo, hi; +#elif defined(__BIG_ENDIAN) + u32 hi, lo; +#endif + }; + u64 val; +} cnt32_to_63_t; + +#define cnt32_to_63(cnt_lo) \ +({ \ + static volatile u32 __m_cnt_hi = 0; \ + cnt32_to_63_t __x; \ + __x.hi = __m_cnt_hi; \ + __x.lo = (cnt_lo); \ + if (unlikely((s32)(__x.hi ^ __x.lo) < 0)) \ + __m_cnt_hi = __x.hi = (__x.hi ^ 0x80000000) + (__x.hi >> 31); \ + __x.val; \ +}) + +#endif diff --git a/trunk/drivers/ata/sata_nv.c b/trunk/drivers/ata/sata_nv.c index 14601dc05e41..1e1f3f3757ae 100644 --- a/trunk/drivers/ata/sata_nv.c +++ b/trunk/drivers/ata/sata_nv.c @@ -309,8 +309,6 @@ static void nv_nf2_freeze(struct ata_port *ap); static void nv_nf2_thaw(struct ata_port *ap); static void nv_ck804_freeze(struct ata_port *ap); static void nv_ck804_thaw(struct ata_port *ap); -static int nv_hardreset(struct ata_link *link, unsigned int *class, - unsigned long deadline); static int nv_adma_slave_config(struct scsi_device *sdev); static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc); static void nv_adma_qc_prep(struct ata_queued_cmd *qc); @@ -405,45 +403,28 @@ static struct scsi_host_template nv_swncq_sht = { .slave_configure = nv_swncq_slave_config, }; -/* OSDL bz3352 reports that some nv controllers can't determine device - * signature reliably and nv_hardreset is implemented to work around - * the problem. This was reported on nf3 and it's unclear whether any - * other controllers are affected. However, the workaround has been - * applied to all variants and there isn't much to gain by trying to - * find out exactly which ones are affected at this point especially - * because NV has moved over to ahci for newer controllers. - */ -static struct ata_port_operations nv_common_ops = { +static struct ata_port_operations nv_generic_ops = { .inherits = &ata_bmdma_port_ops, - .hardreset = nv_hardreset, + .hardreset = ATA_OP_NULL, .scr_read = nv_scr_read, .scr_write = nv_scr_write, }; -/* OSDL bz11195 reports that link doesn't come online after hardreset - * on generic nv's and there have been several other similar reports - * on linux-ide. Disable hardreset for generic nv's. - */ -static struct ata_port_operations nv_generic_ops = { - .inherits = &nv_common_ops, - .hardreset = ATA_OP_NULL, -}; - static struct ata_port_operations nv_nf2_ops = { - .inherits = &nv_common_ops, + .inherits = &nv_generic_ops, .freeze = nv_nf2_freeze, .thaw = nv_nf2_thaw, }; static struct ata_port_operations nv_ck804_ops = { - .inherits = &nv_common_ops, + .inherits = &nv_generic_ops, .freeze = nv_ck804_freeze, .thaw = nv_ck804_thaw, .host_stop = nv_ck804_host_stop, }; static struct ata_port_operations nv_adma_ops = { - .inherits = &nv_common_ops, + .inherits = &nv_generic_ops, .check_atapi_dma = nv_adma_check_atapi_dma, .sff_tf_read = nv_adma_tf_read, @@ -467,7 +448,7 @@ static struct ata_port_operations nv_adma_ops = { }; static struct ata_port_operations nv_swncq_ops = { - .inherits = &nv_common_ops, + .inherits = &nv_generic_ops, .qc_defer = ata_std_qc_defer, .qc_prep = nv_swncq_qc_prep, @@ -1605,21 +1586,6 @@ static void nv_mcp55_thaw(struct ata_port *ap) ata_sff_thaw(ap); } -static int nv_hardreset(struct ata_link *link, unsigned int *class, - unsigned long deadline) -{ - int rc; - - /* SATA hardreset fails to retrieve proper device signature on - * some controllers. Request follow up SRST. For more info, - * see http://bugzilla.kernel.org/show_bug.cgi?id=3352 - */ - rc = sata_sff_hardreset(link, class, deadline); - if (rc) - return rc; - return -EAGAIN; -} - static void nv_adma_error_handler(struct ata_port *ap) { struct nv_adma_port_priv *pp = ap->private_data; diff --git a/trunk/drivers/scsi/qla2xxx/qla_isr.c b/trunk/drivers/scsi/qla2xxx/qla_isr.c index bf41887cdd65..45a3b93eed57 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_isr.c +++ b/trunk/drivers/scsi/qla2xxx/qla_isr.c @@ -1834,6 +1834,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha) WRT_REG_WORD(®->isp.hccr, HCCR_CLR_HOST_INT); } spin_unlock_irq(&ha->hardware_lock); + ha->isp_ops->enable_intrs(ha); fail: return ret; diff --git a/trunk/drivers/scsi/qla2xxx/qla_os.c b/trunk/drivers/scsi/qla2xxx/qla_os.c index 6d0f0e5f2827..26afe44265c7 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_os.c +++ b/trunk/drivers/scsi/qla2xxx/qla_os.c @@ -1740,8 +1740,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) goto probe_failed; - ha->isp_ops->enable_intrs(ha); - scsi_scan_host(host); qla2x00_alloc_sysfs_attr(ha); diff --git a/trunk/drivers/scsi/qlogicpti.c b/trunk/drivers/scsi/qlogicpti.c index 905350896725..4a1cf6377f6c 100644 --- a/trunk/drivers/scsi/qlogicpti.c +++ b/trunk/drivers/scsi/qlogicpti.c @@ -914,7 +914,6 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd, ds[i].d_count = sg_dma_len(s); } sg_count -= n; - sg = s; } } else { cmd->dataseg[0].d_base = 0; diff --git a/trunk/drivers/scsi/scsi_lib.c b/trunk/drivers/scsi/scsi_lib.c index 62307bd794a9..ff5d56b3ee4d 100644 --- a/trunk/drivers/scsi/scsi_lib.c +++ b/trunk/drivers/scsi/scsi_lib.c @@ -852,7 +852,7 @@ static void scsi_end_bidi_request(struct scsi_cmnd *cmd) void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) { int result = cmd->result; - int this_count; + int this_count = scsi_bufflen(cmd); struct request_queue *q = cmd->device->request_queue; struct request *req = cmd->request; int error = 0; @@ -908,7 +908,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) */ if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL) return; - this_count = blk_rq_bytes(req); /* good_bytes = 0, or (inclusive) there were leftovers and * result = 0, so scsi_end_request couldn't retry. diff --git a/trunk/fs/dcache.c b/trunk/fs/dcache.c index e7a1a99b7464..80e93956aced 100644 --- a/trunk/fs/dcache.c +++ b/trunk/fs/dcache.c @@ -1395,10 +1395,6 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) if (dentry->d_parent != parent) goto next; - /* non-existing due to RCU? */ - if (d_unhashed(dentry)) - goto next; - /* * It is safe to compare names since d_move() cannot * change the qstr (protected by d_lock). @@ -1414,8 +1410,10 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) goto next; } - atomic_inc(&dentry->d_count); - found = dentry; + if (!d_unhashed(dentry)) { + atomic_inc(&dentry->d_count); + found = dentry; + } spin_unlock(&dentry->d_lock); break; next: diff --git a/trunk/fs/ubifs/debug.c b/trunk/fs/ubifs/debug.c index d7f7645779f2..b9cb77473758 100644 --- a/trunk/fs/ubifs/debug.c +++ b/trunk/fs/ubifs/debug.c @@ -538,7 +538,7 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node) printk(KERN_DEBUG "\t%d orphan inode numbers:\n", n); for (i = 0; i < n; i++) printk(KERN_DEBUG "\t ino %llu\n", - (unsigned long long)le64_to_cpu(orph->inos[i])); + le64_to_cpu(orph->inos[i])); break; } default: diff --git a/trunk/fs/ubifs/dir.c b/trunk/fs/ubifs/dir.c index 526c01ec8003..2b267c9a1806 100644 --- a/trunk/fs/ubifs/dir.c +++ b/trunk/fs/ubifs/dir.c @@ -426,7 +426,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) while (1) { dbg_gen("feed '%s', ino %llu, new f_pos %#x", - dent->name, (unsigned long long)le64_to_cpu(dent->inum), + dent->name, le64_to_cpu(dent->inum), key_hash_flash(c, &dent->key)); ubifs_assert(dent->ch.sqnum > ubifs_inode(dir)->creat_sqnum); diff --git a/trunk/fs/ubifs/find.c b/trunk/fs/ubifs/find.c index 47814cde2407..e045c8b55423 100644 --- a/trunk/fs/ubifs/find.c +++ b/trunk/fs/ubifs/find.c @@ -507,6 +507,7 @@ int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *free, rsvd_idx_lebs = 0; lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - c->lst.taken_empty_lebs; + ubifs_assert(lebs + c->lst.idx_lebs >= c->min_idx_lebs); if (rsvd_idx_lebs < lebs) /* * OK to allocate an empty LEB, but we still don't want to go diff --git a/trunk/fs/ubifs/gc.c b/trunk/fs/ubifs/gc.c index 02aba36fe3d4..13f1019c859f 100644 --- a/trunk/fs/ubifs/gc.c +++ b/trunk/fs/ubifs/gc.c @@ -334,15 +334,15 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) err = move_nodes(c, sleb); if (err) - goto out_inc_seq; + goto out; err = gc_sync_wbufs(c); if (err) - goto out_inc_seq; + goto out; err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, 0, 0); if (err) - goto out_inc_seq; + goto out; /* Allow for races with TNC */ c->gced_lnum = lnum; @@ -369,14 +369,6 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) out: ubifs_scan_destroy(sleb); return err; - -out_inc_seq: - /* We may have moved at least some nodes so allow for races with TNC */ - c->gced_lnum = lnum; - smp_wmb(); - c->gc_seq += 1; - smp_wmb(); - goto out; } /** diff --git a/trunk/fs/ubifs/super.c b/trunk/fs/ubifs/super.c index 3f4902060c7a..7562464ac83f 100644 --- a/trunk/fs/ubifs/super.c +++ b/trunk/fs/ubifs/super.c @@ -1024,13 +1024,14 @@ static int mount_ubifs(struct ubifs_info *c) goto out_dereg; } - sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id); if (!mounted_read_only) { err = alloc_wbufs(c); if (err) goto out_cbuf; /* Create background thread */ + sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, + c->vi.vol_id); c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name); if (!c->bgt) c->bgt = ERR_PTR(-EINVAL); diff --git a/trunk/fs/ubifs/tnc.c b/trunk/fs/ubifs/tnc.c index 7634c5970887..7da209ab9378 100644 --- a/trunk/fs/ubifs/tnc.c +++ b/trunk/fs/ubifs/tnc.c @@ -1476,7 +1476,7 @@ int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, } err = fallible_read_node(c, key, &zbr, node); - if (err <= 0 || maybe_leb_gced(c, zbr.lnum, gc_seq1)) { + if (maybe_leb_gced(c, zbr.lnum, gc_seq1)) { /* * The node may have been GC'ed out from under us so try again * while keeping the TNC mutex locked. diff --git a/trunk/fs/xfs/xfs_inode.c b/trunk/fs/xfs/xfs_inode.c index dbd9cef852ec..00e80df9dd9d 100644 --- a/trunk/fs/xfs/xfs_inode.c +++ b/trunk/fs/xfs/xfs_inode.c @@ -4118,7 +4118,7 @@ xfs_iext_indirect_to_direct( ASSERT(nextents <= XFS_LINEAR_EXTS); size = nextents * sizeof(xfs_bmbt_rec_t); - xfs_iext_irec_compact_pages(ifp); + xfs_iext_irec_compact_full(ifp); ASSERT(ifp->if_real_bytes == XFS_IEXT_BUFSZ); ep = ifp->if_u1.if_ext_irec->er_extbuf; @@ -4449,7 +4449,8 @@ xfs_iext_irec_remove( * compaction policy is as follows: * * Full Compaction: Extents fit into a single page (or inline buffer) - * Partial Compaction: Extents occupy less than 50% of allocated space + * Full Compaction: Extents occupy less than 10% of allocated space + * Partial Compaction: Extents occupy > 10% and < 50% of allocated space * No Compaction: Extents occupy at least 50% of allocated space */ void @@ -4470,6 +4471,8 @@ xfs_iext_irec_compact( xfs_iext_direct_to_inline(ifp, nextents); } else if (nextents <= XFS_LINEAR_EXTS) { xfs_iext_indirect_to_direct(ifp); + } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 3) { + xfs_iext_irec_compact_full(ifp); } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 1) { xfs_iext_irec_compact_pages(ifp); } @@ -4493,7 +4496,7 @@ xfs_iext_irec_compact_pages( erp_next = erp + 1; if (erp_next->er_extcount <= (XFS_LINEAR_EXTS - erp->er_extcount)) { - memcpy(&erp->er_extbuf[erp->er_extcount], + memmove(&erp->er_extbuf[erp->er_extcount], erp_next->er_extbuf, erp_next->er_extcount * sizeof(xfs_bmbt_rec_t)); erp->er_extcount += erp_next->er_extcount; @@ -4512,6 +4515,91 @@ xfs_iext_irec_compact_pages( } } +/* + * Fully compact the extent records managed by the indirection array. + */ +void +xfs_iext_irec_compact_full( + xfs_ifork_t *ifp) /* inode fork pointer */ +{ + xfs_bmbt_rec_host_t *ep, *ep_next; /* extent record pointers */ + xfs_ext_irec_t *erp, *erp_next; /* extent irec pointers */ + int erp_idx = 0; /* extent irec index */ + int ext_avail; /* empty entries in ex list */ + int ext_diff; /* number of exts to add */ + int nlists; /* number of irec's (ex lists) */ + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + erp = ifp->if_u1.if_ext_irec; + ep = &erp->er_extbuf[erp->er_extcount]; + erp_next = erp + 1; + ep_next = erp_next->er_extbuf; + + while (erp_idx < nlists - 1) { + /* + * Check how many extent records are available in this irec. + * If there is none skip the whole exercise. + */ + ext_avail = XFS_LINEAR_EXTS - erp->er_extcount; + if (ext_avail) { + + /* + * Copy over as many as possible extent records into + * the previous page. + */ + ext_diff = MIN(ext_avail, erp_next->er_extcount); + memcpy(ep, ep_next, ext_diff * sizeof(xfs_bmbt_rec_t)); + erp->er_extcount += ext_diff; + erp_next->er_extcount -= ext_diff; + + /* + * If the next irec is empty now we can simply + * remove it. + */ + if (erp_next->er_extcount == 0) { + /* + * Free page before removing extent record + * so er_extoffs don't get modified in + * xfs_iext_irec_remove. + */ + kmem_free(erp_next->er_extbuf); + erp_next->er_extbuf = NULL; + xfs_iext_irec_remove(ifp, erp_idx + 1); + erp = &ifp->if_u1.if_ext_irec[erp_idx]; + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + + /* + * If the next irec is not empty move up the content + * that has not been copied to the previous page to + * the beggining of this one. + */ + } else { + memmove(erp_next->er_extbuf, &ep_next[ext_diff], + erp_next->er_extcount * + sizeof(xfs_bmbt_rec_t)); + ep_next = erp_next->er_extbuf; + memset(&ep_next[erp_next->er_extcount], 0, + (XFS_LINEAR_EXTS - + erp_next->er_extcount) * + sizeof(xfs_bmbt_rec_t)); + } + } + + if (erp->er_extcount == XFS_LINEAR_EXTS) { + erp_idx++; + if (erp_idx < nlists) + erp = &ifp->if_u1.if_ext_irec[erp_idx]; + else + break; + } + ep = &erp->er_extbuf[erp->er_extcount]; + erp_next = erp + 1; + ep_next = erp_next->er_extbuf; + } +} + /* * This is called to update the er_extoff field in the indirection * array when extents have been added or removed from one of the diff --git a/trunk/kernel/kgdb.c b/trunk/kernel/kgdb.c index eaa21fc9ad1d..949806ab67de 100644 --- a/trunk/kernel/kgdb.c +++ b/trunk/kernel/kgdb.c @@ -488,7 +488,7 @@ static int write_mem_msg(int binary) if (err) return err; if (CACHE_FLUSH_IS_SAFE) - flush_icache_range(addr, addr + length + 1); + flush_icache_range(addr, addr + length); return 0; } diff --git a/trunk/scripts/kconfig/conf.c b/trunk/scripts/kconfig/conf.c index 3e1057f885c6..36b5eedcdc75 100644 --- a/trunk/scripts/kconfig/conf.c +++ b/trunk/scripts/kconfig/conf.c @@ -32,7 +32,6 @@ char *defconfig_file; static int indent = 1; static int valid_stdin = 1; -static int sync_kconfig; static int conf_cnt; static char line[128]; static struct menu *rootEntry; @@ -66,7 +65,7 @@ static void strip(char *str) static void check_stdin(void) { - if (!valid_stdin) { + if (!valid_stdin && input_mode == ask_silent) { printf(_("aborted!\n\n")); printf(_("Console input/output is redirected. ")); printf(_("Run 'make oldconfig' to update configuration.\n\n")); @@ -428,6 +427,43 @@ static void check_conf(struct menu *menu) check_conf(child); } +static void conf_do_update(void) +{ + /* Update until a loop caused no more changes */ + do { + conf_cnt = 0; + check_conf(&rootmenu); + } while (conf_cnt); +} + +static int conf_silent_update(void) +{ + const char *name; + + if (conf_get_changed()) { + name = getenv("KCONFIG_NOSILENTUPDATE"); + if (name && *name) { + fprintf(stderr, + _("\n*** Kernel configuration requires explicit update.\n\n")); + return 1; + } + conf_do_update(); + } + return 0; +} + +static int conf_update(void) +{ + rootEntry = &rootmenu; + conf(&rootmenu); + if (input_mode == ask_all) { + input_mode = ask_silent; + valid_stdin = 1; + } + conf_do_update(); + return 0; +} + int main(int ac, char **av) { int opt; @@ -441,11 +477,11 @@ int main(int ac, char **av) while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) { switch (opt) { case 'o': - input_mode = ask_silent; + input_mode = ask_new; break; case 's': input_mode = ask_silent; - sync_kconfig = 1; + valid_stdin = isatty(0) && isatty(1) && isatty(2); break; case 'd': input_mode = set_default; @@ -483,19 +519,6 @@ int main(int ac, char **av) name = av[optind]; conf_parse(name); //zconfdump(stdout); - if (sync_kconfig) { - if (stat(".config", &tmpstat)) { - fprintf(stderr, _("***\n" - "*** You have not yet configured your kernel!\n" - "*** (missing kernel .config file)\n" - "***\n" - "*** Please run some configurator (e.g. \"make oldconfig\" or\n" - "*** \"make menuconfig\" or \"make xconfig\").\n" - "***\n")); - exit(1); - } - } - switch (input_mode) { case set_default: if (!defconfig_file) @@ -508,6 +531,16 @@ int main(int ac, char **av) } break; case ask_silent: + if (stat(".config", &tmpstat)) { + printf(_("***\n" + "*** You have not yet configured your kernel!\n" + "*** (missing kernel .config file)\n" + "***\n" + "*** Please run some configurator (e.g. \"make oldconfig\" or\n" + "*** \"make menuconfig\" or \"make xconfig\").\n" + "***\n")); + exit(1); + } case ask_all: case ask_new: conf_read(NULL); @@ -536,19 +569,6 @@ int main(int ac, char **av) default: break; } - - if (sync_kconfig) { - if (conf_get_changed()) { - name = getenv("KCONFIG_NOSILENTUPDATE"); - if (name && *name) { - fprintf(stderr, - _("\n*** Kernel configuration requires explicit update.\n\n")); - return 1; - } - } - valid_stdin = isatty(0) && isatty(1) && isatty(2); - } - switch (input_mode) { case set_no: conf_set_all_new_symbols(def_no); @@ -565,38 +585,27 @@ int main(int ac, char **av) case set_default: conf_set_all_new_symbols(def_default); break; + case ask_silent: case ask_new: + if (conf_silent_update()) + exit(1); + break; case ask_all: - rootEntry = &rootmenu; - conf(&rootmenu); - input_mode = ask_silent; - /* fall through */ - case ask_silent: - /* Update until a loop caused no more changes */ - do { - conf_cnt = 0; - check_conf(&rootmenu); - } while (conf_cnt); + if (conf_update()) + exit(1); break; } - if (sync_kconfig) { - /* silentoldconfig is used during the build so we shall update autoconf. - * All other commands are only used to generate a config. - */ - if (conf_get_changed() && conf_write(NULL)) { - fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n")); - exit(1); - } - if (conf_write_autoconf()) { - fprintf(stderr, _("\n*** Error during update of the kernel configuration.\n\n")); - return 1; - } - } else { - if (conf_write(NULL)) { - fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n")); - exit(1); - } + if (conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n")); + exit(1); + } + /* ask_silent is used during the build so we shall update autoconf. + * All other commands are only used to generate a config. + */ + if (input_mode == ask_silent && conf_write_autoconf()) { + fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n")); + return 1; } return 0; } diff --git a/trunk/scripts/kconfig/confdata.c b/trunk/scripts/kconfig/confdata.c index b91cf241a539..df6a188b9930 100644 --- a/trunk/scripts/kconfig/confdata.c +++ b/trunk/scripts/kconfig/confdata.c @@ -222,10 +222,8 @@ int conf_read_simple(const char *name, int def) continue; if (def == S_DEF_USER) { sym = sym_find(line + 9); - if (!sym) { - sym_add_change_count(1); + if (!sym) break; - } } else { sym = sym_lookup(line + 9, 0); if (sym->type == S_UNKNOWN) @@ -261,10 +259,8 @@ int conf_read_simple(const char *name, int def) } if (def == S_DEF_USER) { sym = sym_find(line + 7); - if (!sym) { - sym_add_change_count(1); + if (!sym) break; - } } else { sym = sym_lookup(line + 7, 0); if (sym->type == S_UNKNOWN) diff --git a/trunk/sound/core/pcm.c b/trunk/sound/core/pcm.c index ece25c718e95..9dd9bc73fe1d 100644 --- a/trunk/sound/core/pcm.c +++ b/trunk/sound/core/pcm.c @@ -781,7 +781,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, return -ENODEV; card = pcm->card; - read_lock(&card->ctl_files_rwlock); + down_read(&card->controls_rwsem); list_for_each_entry(kctl, &card->ctl_files, list) { if (kctl->pid == current->pid) { prefer_subdevice = kctl->prefer_pcm_subdevice; @@ -789,7 +789,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, break; } } - read_unlock(&card->ctl_files_rwlock); + up_read(&card->controls_rwsem); switch (stream) { case SNDRV_PCM_STREAM_PLAYBACK: diff --git a/trunk/sound/core/pcm_native.c b/trunk/sound/core/pcm_native.c index c487025d3457..c49b9d9e303c 100644 --- a/trunk/sound/core/pcm_native.c +++ b/trunk/sound/core/pcm_native.c @@ -1546,10 +1546,16 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) card = substream->pcm->card; if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) + runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; + snd_power_lock(card); + if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { + result = snd_power_wait(card, SNDRV_CTL_POWER_D0); + if (result < 0) + goto _unlock; + } + snd_pcm_stream_lock_irq(substream); /* resume pause */ if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) @@ -1558,7 +1564,8 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); /* runtime->control->appl_ptr = runtime->status->hw_ptr; */ snd_pcm_stream_unlock_irq(substream); - + _unlock: + snd_power_unlock(card); return result; } diff --git a/trunk/sound/core/rawmidi.c b/trunk/sound/core/rawmidi.c index b917a9f981c7..f7ea7287c59c 100644 --- a/trunk/sound/core/rawmidi.c +++ b/trunk/sound/core/rawmidi.c @@ -418,7 +418,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) mutex_lock(&rmidi->open_mutex); while (1) { subdevice = -1; - read_lock(&card->ctl_files_rwlock); + down_read(&card->controls_rwsem); list_for_each_entry(kctl, &card->ctl_files, list) { if (kctl->pid == current->pid) { subdevice = kctl->prefer_rawmidi_subdevice; @@ -426,7 +426,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) break; } } - read_unlock(&card->ctl_files_rwlock); + up_read(&card->controls_rwsem); err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device, subdevice, fflags, rawmidi_file); if (err >= 0) diff --git a/trunk/sound/soc/codecs/cs4270.c b/trunk/sound/soc/codecs/cs4270.c index d68650de39bc..9deb8c74fdfd 100644 --- a/trunk/sound/soc/codecs/cs4270.c +++ b/trunk/sound/soc/codecs/cs4270.c @@ -490,7 +490,34 @@ static int cs4270_mute(struct snd_soc_dai *dai, int mute) #endif -static int cs4270_i2c_probe(struct i2c_client *, const struct i2c_device_id *); +static int cs4270_i2c_probe(struct i2c_adapter *adap, int addr, int kind); + +/* + * Notify the driver that a new I2C bus has been found. + * + * This function is called for each I2C bus in the system. The function + * then asks the I2C subsystem to probe that bus at the addresses on which + * our device (the CS4270) could exist. If a device is found at one of + * those addresses, then our probe function (cs4270_i2c_probe) is called. + */ +static int cs4270_i2c_attach(struct i2c_adapter *adapter) +{ + return i2c_probe(adapter, &addr_data, cs4270_i2c_probe); +} + +static int cs4270_i2c_detach(struct i2c_client *client) +{ + struct snd_soc_codec *codec = i2c_get_clientdata(client); + + i2c_detach_client(client); + codec->control_data = NULL; + + kfree(codec->reg_cache); + codec->reg_cache = NULL; + + kfree(client); + return 0; +} /* A list of non-DAPM controls that the CS4270 supports */ static const struct snd_kcontrol_new cs4270_snd_controls[] = { @@ -498,19 +525,14 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = { CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1) }; -static const struct i2c_device_id cs4270_id[] = { - {"cs4270", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, cs4270_id); - static struct i2c_driver cs4270_i2c_driver = { .driver = { .name = "CS4270 I2C", .owner = THIS_MODULE, }, - .id_table = cs4270_id, - .probe = cs4270_i2c_probe, + .id = I2C_DRIVERID_CS4270, + .attach_adapter = cs4270_i2c_attach, + .detach_client = cs4270_i2c_detach, }; /* @@ -539,11 +561,11 @@ static struct snd_soc_device *cs4270_socdev; * Note: snd_soc_new_pcms() must be called before this function can be called, * because of snd_ctl_add(). */ -static int cs4270_i2c_probe(struct i2c_client *i2c_client, - const struct i2c_device_id *id) +static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind) { struct snd_soc_device *socdev = cs4270_socdev; struct snd_soc_codec *codec = socdev->codec; + struct i2c_client *i2c_client = NULL; int i; int ret = 0; @@ -556,6 +578,12 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, /* Note: codec_dai->codec is NULL here */ + i2c_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!i2c_client) { + printk(KERN_ERR "cs4270: could not allocate I2C client\n"); + return -ENOMEM; + } + codec->reg_cache = kzalloc(CS4270_NUMREGS, GFP_KERNEL); if (!codec->reg_cache) { printk(KERN_ERR "cs4270: could not allocate register cache\n"); @@ -563,6 +591,13 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, goto error; } + i2c_set_clientdata(i2c_client, codec); + strcpy(i2c_client->name, "CS4270"); + + i2c_client->driver = &cs4270_i2c_driver; + i2c_client->adapter = adapter; + i2c_client->addr = addr; + /* Verify that we have a CS4270 */ ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); @@ -577,10 +612,18 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, goto error; } - printk(KERN_INFO "cs4270: found device at I2C address %X\n", - i2c_client->addr); + printk(KERN_INFO "cs4270: found device at I2C address %X\n", addr); printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF); + /* Tell the I2C layer a new client has arrived */ + + ret = i2c_attach_client(i2c_client); + if (ret) { + printk(KERN_ERR "cs4270: could not attach codec, " + "I2C address %x, error code %i\n", addr, ret); + goto error; + } + codec->control_data = i2c_client; codec->read = cs4270_read_reg_cache; codec->write = cs4270_i2c_write; @@ -605,17 +648,20 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, goto error; } - i2c_set_clientdata(i2c_client, codec); - return 0; error: - codec->control_data = NULL; + if (codec->control_data) { + i2c_detach_client(i2c_client); + codec->control_data = NULL; + } kfree(codec->reg_cache); codec->reg_cache = NULL; codec->reg_cache_size = 0; + kfree(i2c_client); + return ret; }