* [STACK] >3k call path in ide
@ 2004-06-09 12:29 Jörn Engel
2004-06-09 15:23 ` Michael Clark
2004-06-15 23:34 ` [PATCH] " Randy.Dunlap
0 siblings, 2 replies; 21+ messages in thread
From: Jörn Engel @ 2004-06-09 12:29 UTC (permalink / raw)
To: B.Zolnierkiewicz, linux-ide; +Cc: linux-kernel
Bartlomiej, can you put ide_config on a diet?
stackframes for call path too long (3052):
size function
0 client_reg_t->event_handler
1168 ide_config
12 ide_register_hw
44 ide_unregister
12 ide_unregister_subdriver
0 pnpide_init
0 pnp_register_driver
0 driver_register
20 bus_add_driver
16 driver_attach
72 tty_register_device
0 class_simple_device_add
0 class_device_register
16 class_device_add
0 kobject_add
0 kobject_hotplug
132 call_usermodehelper
80 wait_for_completion
84 schedule
16 __put_task_struct
20 audit_free
36 audit_log_start
16 __kmalloc
0 __get_free_pages
28 __alloc_pages
284 try_to_free_pages
0 out_of_memory
0 mmput
16 exit_aio
0 __put_ioctx
16 do_munmap
0 split_vma
36 vma_adjust
0 fput
0 __fput
0 locks_remove_flock
12 panic
0 sys_sync
0 sync_inodes
308 sync_inodes_sb
0 do_writepages
128 mpage_writepages
4 write_boundary_block
0 ll_rw_block
28 submit_bh
0 bio_alloc
88 mempool_alloc
256 wakeup_bdflush
20 pdflush_operation
0 printk
0 preempt_schedule
84 schedule
Jörn
--
When you close your hand, you own nothing. When you open it up, you
own the whole world.
-- Li Mu Bai in Tiger & Dragon
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [STACK] >3k call path in ide 2004-06-09 12:29 [STACK] >3k call path in ide Jörn Engel @ 2004-06-09 15:23 ` Michael Clark 2004-06-09 16:29 ` Jörn Engel 2004-06-15 23:34 ` [PATCH] " Randy.Dunlap 1 sibling, 1 reply; 21+ messages in thread From: Michael Clark @ 2004-06-09 15:23 UTC (permalink / raw) To: Jörn Engel, linux-kernel Hi Jorn, Noticed that try_to_free_pages, sync_inodes_sb and wakeup_bdflush features in almost all of these traces and although at 284, 308 and 256 respectively their not huge but together their neither that small (considering they occur all in the same stack trace). This is consumed mostly by a struct page_state which is 148 bytes big although looking at the code get_page_state(struct page_state *ret) only populates the first 6 fields or 24 bytes. get_full_page_state which is hardly used updates these other fields. Is this a candidate for splitting into 2 structs? 1 containing just the first 6 fields needed by the majority of users: try_to_free_pages, shrink_all_memory, kswapd, get_dirty_limits, wakeup_bdflush, sync_inodes_sb mclark@monty:/usr/src/linux$ find . -name '*.c' | xargs grep get_page_state ./fs/proc/proc_misc.c: get_page_state(&ps); ./fs/fs-writeback.c: get_page_state(&ps); ./mm/page_alloc.c:void __get_page_state(struct page_state *ret, int nr) ./mm/page_alloc.c:void get_page_state(struct page_state *ret) ./mm/page_alloc.c: __get_page_state(ret, nr + 1); ./mm/page_alloc.c: __get_page_state(ret, sizeof(*ret) / sizeof(unsigned long)); ./mm/page_alloc.c: get_page_state(&ps); ./mm/vmscan.c: get_page_state(&ps); ./mm/vmscan.c: get_page_state(&ps); ./mm/vmscan.c: get_page_state(&ps); ./mm/page-writeback.c: get_page_state(ps); ./mm/page-writeback.c: * On really big machines, get_page_state is expensive, so try to avoid calling ./mm/page-writeback.c: get_page_state(&ps); ./mm/page-writeback.c: get_page_state(&ps); ./mm/page-writeback.c: * If it is too low then SMP machines will call the (expensive) get_page_state mclark@monty:/usr/src/linux$ find . -name '*.c' | xargs grep get_full_page_state ./drivers/parisc/led.c: get_full_page_state(&pgstat); /* get no of sectors in & out */ ./arch/s390/appldata/appldata_base.c:void get_full_page_state(struct page_state *ps) ./arch/s390/appldata/appldata_base.c:EXPORT_SYMBOL_GPL(get_full_page_state); ./arch/s390/appldata/appldata_mem.c: get_full_page_state(&ps); ./mm/page_alloc.c:void get_full_page_state(struct page_state *ret) ./mm/page_alloc.c: get_full_page_state(ps); ~mc On 06/09/04 20:29, Jörn Engel wrote: > Bartlomiej, can you put ide_config on a diet? > > stackframes for call path too long (3052): > size function > 0 client_reg_t->event_handler > 1168 ide_config > 12 ide_register_hw > 44 ide_unregister > 12 ide_unregister_subdriver > 0 pnpide_init > 0 pnp_register_driver > 0 driver_register > 20 bus_add_driver > 16 driver_attach > 72 tty_register_device > 0 class_simple_device_add > 0 class_device_register > 16 class_device_add > 0 kobject_add > 0 kobject_hotplug > 132 call_usermodehelper > 80 wait_for_completion > 84 schedule > 16 __put_task_struct > 20 audit_free > 36 audit_log_start > 16 __kmalloc > 0 __get_free_pages > 28 __alloc_pages > 284 try_to_free_pages > 0 out_of_memory > 0 mmput > 16 exit_aio > 0 __put_ioctx > 16 do_munmap > 0 split_vma > 36 vma_adjust > 0 fput > 0 __fput > 0 locks_remove_flock > 12 panic > 0 sys_sync > 0 sync_inodes > 308 sync_inodes_sb > 0 do_writepages > 128 mpage_writepages > 4 write_boundary_block > 0 ll_rw_block > 28 submit_bh > 0 bio_alloc > 88 mempool_alloc > 256 wakeup_bdflush > 20 pdflush_operation > 0 printk > 0 preempt_schedule > 84 schedule > > Jörn > -- Michael Clark, . . . . . . . . . . . . michael@metaparadigm.com Managing Director, . . . . . . . . . http://www.metaparadigm.com Metaparadigm Pte. Ltd. . . . . . . . . . . phone: +65 6395 6277 25F Paterson Road, . . . . . . . . . . . . mobile: +65 9645 9612 Singapore 238515 . . . . . . . . . . . . . . fax: +65 6234 4043 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [STACK] >3k call path in ide 2004-06-09 15:23 ` Michael Clark @ 2004-06-09 16:29 ` Jörn Engel 2004-06-09 19:27 ` Andrew Morton 0 siblings, 1 reply; 21+ messages in thread From: Jörn Engel @ 2004-06-09 16:29 UTC (permalink / raw) To: Michael Clark; +Cc: linux-kernel, Hugh Dickins, Andrew Morton On Wed, 9 June 2004 23:23:20 +0800, Michael Clark wrote: > > Noticed that try_to_free_pages, sync_inodes_sb and wakeup_bdflush features > in almost all of these traces and although at 284, 308 and 256 respectively > their not huge but together their neither that small (considering they > occur all in the same stack trace). > > This is consumed mostly by a struct page_state which is 148 bytes big > although looking at the code get_page_state(struct page_state *ret) > only populates the first 6 fields or 24 bytes. get_full_page_state > which is hardly used updates these other fields. > > Is this a candidate for splitting into 2 structs? 1 containing just the > first 6 fields needed by the majority of users: try_to_free_pages, > shrink_all_memory, kswapd, get_dirty_limits, wakeup_bdflush, sync_inodes_sb Well noticed, although Hugh and Andrew have already exchanged some patches, see http://www.uwsg.indiana.edu/hypermail/linux/kernel/0406.1/0134.html For the moment I consider try_to_free_pages() fixed. Andrew, what do you thing about the patch below for sync_inodes_sb()? It's stack consumption is reduced from 308 to 64, at the cost of one more function call. Jörn -- Premature optimization is the root of all evil. -- Donald Knuth Move a struct page_state into it's own function. This reduces the stack consumption for sync_inodes_sb(), as the stack is already partially rolled back before other functions get called. Signed-off-by: Jörn Engel <joern@wohnheim.fh-wedel.de> fs-writeback.c | 15 ++++++++++----- 1 files changed, 10 insertions(+), 5 deletions(-) --- linux-2.6.6cow/fs/fs-writeback.c~sync_inodes_sb 2004-06-09 18:19:25.000000000 +0200 +++ linux-2.6.6cow/fs/fs-writeback.c 2004-06-09 18:23:44.000000000 +0200 @@ -396,6 +396,15 @@ spin_unlock(&inode_lock); } +static long get_nr_to_write(void) +{ + struct page_state ps; + + get_page_state(&ps); + return ps.nr_dirty + ps.nr_unstable + ps.nr_dirty + ps.nr_unstable + + (inodes_stat.nr_inodes - inodes_stat.nr_unused); +} + /* * writeback and wait upon the filesystem's dirty inodes. The caller will * do this in two passes - one to write, and one to wait. WB_SYNC_HOLD is @@ -409,7 +418,6 @@ */ void sync_inodes_sb(struct super_block *sb, int wait) { - struct page_state ps; struct writeback_control wbc = { .bdi = NULL, .sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_HOLD, @@ -417,10 +425,7 @@ .nr_to_write = 0, }; - get_page_state(&ps); - wbc.nr_to_write = ps.nr_dirty + ps.nr_unstable + - (inodes_stat.nr_inodes - inodes_stat.nr_unused) + - ps.nr_dirty + ps.nr_unstable; + wbc.nr_to_write = get_nr_to_write(); wbc.nr_to_write += wbc.nr_to_write / 2; /* Bit more for luck */ spin_lock(&inode_lock); sync_sb_inodes(sb, &wbc); ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [STACK] >3k call path in ide 2004-06-09 16:29 ` Jörn Engel @ 2004-06-09 19:27 ` Andrew Morton 2004-06-10 22:59 ` Jörn Engel 0 siblings, 1 reply; 21+ messages in thread From: Andrew Morton @ 2004-06-09 19:27 UTC (permalink / raw) To: Jörn Engel; +Cc: michael, linux-kernel, hugh Jörn Engel <joern@wohnheim.fh-wedel.de> wrote: > > Andrew, what do you thing about the patch below for sync_inodes_sb()? > It's stack consumption is reduced from 308 to 64, at the cost of one > more function call. Like this: --- 25/fs/fs-writeback.c~sync_inodes_sb-stack-reduction 2004-06-09 12:25:57.111389456 -0700 +++ 25-akpm/fs/fs-writeback.c 2004-06-09 12:25:57.115388848 -0700 @@ -433,15 +433,15 @@ restart: */ void sync_inodes_sb(struct super_block *sb, int wait) { - struct page_state ps; struct writeback_control wbc = { .sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_HOLD, }; + unsigned long nr_dirty = read_page_state(nr_dirty); + unsigned long nr_unstable = read_page_state(nr_unstable); - get_page_state(&ps); - wbc.nr_to_write = ps.nr_dirty + ps.nr_unstable + + wbc.nr_to_write = nr_dirty + nr_unstable + (inodes_stat.nr_inodes - inodes_stat.nr_unused) + - ps.nr_dirty + ps.nr_unstable; + nr_dirty + nr_unstable; wbc.nr_to_write += wbc.nr_to_write / 2; /* Bit more for luck */ spin_lock(&inode_lock); sync_sb_inodes(sb, &wbc); _ ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [STACK] >3k call path in ide 2004-06-09 19:27 ` Andrew Morton @ 2004-06-10 22:59 ` Jörn Engel 2004-06-10 23:10 ` Andrew Morton 0 siblings, 1 reply; 21+ messages in thread From: Jörn Engel @ 2004-06-10 22:59 UTC (permalink / raw) To: Andrew Morton; +Cc: michael, linux-kernel, hugh On Wed, 9 June 2004 12:27:21 -0700, Andrew Morton wrote: > Jörn Engel <joern@wohnheim.fh-wedel.de> wrote: > > > > Andrew, what do you thing about the patch below for sync_inodes_sb()? > > It's stack consumption is reduced from 308 to 64, at the cost of one > > more function call. > > Like this: > > --- 25/fs/fs-writeback.c~sync_inodes_sb-stack-reduction 2004-06-09 12:25:57.111389456 -0700 > +++ 25-akpm/fs/fs-writeback.c 2004-06-09 12:25:57.115388848 -0700 > @@ -433,15 +433,15 @@ restart: > */ > void sync_inodes_sb(struct super_block *sb, int wait) > { > - struct page_state ps; > struct writeback_control wbc = { > .sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_HOLD, > }; > + unsigned long nr_dirty = read_page_state(nr_dirty); > + unsigned long nr_unstable = read_page_state(nr_unstable); read_page_state doesn't exist in 2.6.7-rc3 or 2.6.6-mm5. How is it defined? If it is just a simple macro to access the right fields, then the patch looks fine to me. > - get_page_state(&ps); > - wbc.nr_to_write = ps.nr_dirty + ps.nr_unstable + > + wbc.nr_to_write = nr_dirty + nr_unstable + > (inodes_stat.nr_inodes - inodes_stat.nr_unused) + > - ps.nr_dirty + ps.nr_unstable; > + nr_dirty + nr_unstable; > wbc.nr_to_write += wbc.nr_to_write / 2; /* Bit more for luck */ > spin_lock(&inode_lock); > sync_sb_inodes(sb, &wbc); > _ Jörn -- Fantasy is more important than knowledge. Knowledge is limited, while fantasy embraces the whole world. -- Albert Einstein ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [STACK] >3k call path in ide 2004-06-10 22:59 ` Jörn Engel @ 2004-06-10 23:10 ` Andrew Morton 2004-06-11 10:53 ` Jörn Engel 2004-10-15 1:58 ` Rusty Russell 0 siblings, 2 replies; 21+ messages in thread From: Andrew Morton @ 2004-06-10 23:10 UTC (permalink / raw) To: Jörn Engel; +Cc: michael, linux-kernel, hugh Jörn Engel <joern@wohnheim.fh-wedel.de> wrote: > > read_page_state doesn't exist in 2.6.7-rc3 or 2.6.6-mm5. How is it > defined? It was in 2.6.7-rc3-mm1. struct page_state is large (148 bytes) and we put them on the stack in awkward code paths (page reclaim...) So implement a simple read_page_state() which can be used to pluck out a single member from the all-cpus page_state accumulators. Signed-off-by: Andrew Morton <akpm@osdl.org> --- 25-akpm/include/linux/page-flags.h | 4 ++++ 25-akpm/mm/page_alloc.c | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff -puN include/linux/page-flags.h~read_page_state include/linux/page-flags.h --- 25/include/linux/page-flags.h~read_page_state Wed Jun 9 17:06:33 2004 +++ 25-akpm/include/linux/page-flags.h Wed Jun 9 17:06:33 2004 @@ -139,6 +139,10 @@ DECLARE_PER_CPU(struct page_state, page_ extern void get_page_state(struct page_state *ret); extern void get_full_page_state(struct page_state *ret); +extern unsigned long __read_page_state(unsigned offset); + +#define read_page_state(member) \ + __read_page_state(offsetof(struct page_state, member)) #define mod_page_state(member, delta) \ do { \ diff -puN mm/page_alloc.c~read_page_state mm/page_alloc.c --- 25/mm/page_alloc.c~read_page_state Wed Jun 9 17:06:33 2004 +++ 25-akpm/mm/page_alloc.c Wed Jun 9 17:11:57 2004 @@ -947,6 +947,23 @@ void get_full_page_state(struct page_sta __get_page_state(ret, sizeof(*ret) / sizeof(unsigned long)); } +unsigned long __read_page_state(unsigned offset) +{ + unsigned long ret = 0; + int cpu; + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + unsigned long in; + + if (!cpu_possible(cpu)) + continue; + + in = (unsigned long)&per_cpu(page_states, cpu) + offset; + ret += *((unsigned long *)in); + } + return ret; +} + void get_zone_counts(unsigned long *active, unsigned long *inactive, unsigned long *free) { _ ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [STACK] >3k call path in ide 2004-06-10 23:10 ` Andrew Morton @ 2004-06-11 10:53 ` Jörn Engel 2004-10-15 1:58 ` Rusty Russell 1 sibling, 0 replies; 21+ messages in thread From: Jörn Engel @ 2004-06-11 10:53 UTC (permalink / raw) To: Andrew Morton; +Cc: michael, linux-kernel, hugh On Thu, 10 June 2004 16:10:21 -0700, Andrew Morton wrote: > Jörn Engel <joern@wohnheim.fh-wedel.de> wrote: > > > > read_page_state doesn't exist in 2.6.7-rc3 or 2.6.6-mm5. How is it > > defined? > > It was in 2.6.7-rc3-mm1. A beauty! Your trick about submitting an ugly patch and waiting for others to do something better really works. :) Jörn -- My second remark is that our intellectual powers are rather geared to master static relations and that our powers to visualize processes evolving in time are relatively poorly developed. -- Edsger W. Dijkstra ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [STACK] >3k call path in ide 2004-06-10 23:10 ` Andrew Morton 2004-06-11 10:53 ` Jörn Engel @ 2004-10-15 1:58 ` Rusty Russell 1 sibling, 0 replies; 21+ messages in thread From: Rusty Russell @ 2004-10-15 1:58 UTC (permalink / raw) To: Andrew Morton; +Cc: Jörn Engel, michael, lkml - Kernel Mailing List, hugh On Fri, 2004-06-11 at 09:10, Andrew Morton wrote: > Jörn Engel <joern@wohnheim.fh-wedel.de> wrote: > > > > read_page_state doesn't exist in 2.6.7-rc3 or 2.6.6-mm5. How is it > > defined? > > It was in 2.6.7-rc3-mm1. > > > > struct page_state is large (148 bytes) and we put them on the stack in awkward > code paths (page reclaim...) > > So implement a simple read_page_state() which can be used to pluck out a > single member from the all-cpus page_state accumulators. > > Signed-off-by: Andrew Morton <akpm@osdl.org> ... > +unsigned long __read_page_state(unsigned offset) > +{ > + unsigned long ret = 0; > + int cpu; > + > + for (cpu = 0; cpu < NR_CPUS; cpu++) { > + unsigned long in; > + > + if (!cpu_possible(cpu)) > + continue; for_each_cpu(cpu) here perhaps? Rusty. -- Anyone who quotes me in their signature is an idiot -- Rusty Russell ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH] [STACK] >3k call path in ide 2004-06-09 12:29 [STACK] >3k call path in ide Jörn Engel 2004-06-09 15:23 ` Michael Clark @ 2004-06-15 23:34 ` Randy.Dunlap 2004-06-16 7:11 ` Florian Schirmer 1 sibling, 1 reply; 21+ messages in thread From: Randy.Dunlap @ 2004-06-15 23:34 UTC (permalink / raw) To: Jörn Engel, akpm; +Cc: B.Zolnierkiewicz, linux-ide, linux-kernel On Wed, 9 Jun 2004 14:29:21 +0200 Jörn Engel wrote: | Bartlomiej, can you put ide_config on a diet? | | stackframes for call path too long (3052): | size function | 0 client_reg_t->event_handler | 1168 ide_config Here's a patch for ide_config(), the worst offender in this call chain. Reduce large stack usage in ide_config() by using kmalloc(), down from 0x4a4 bytes to 0x74 bytes (x86-32). Little whitespace cleanup. Move function comment block to immediately above the function. Module loaded and unloaded, otherwise not tested (no hardware). Signed-off-by: Randy Dunlap <rddunlap@osdl.org> diffstat:= drivers/ide/legacy/ide-cs.c | 137 ++++++++++++++++++++++++++------------------ 1 files changed, 81 insertions(+), 56 deletions(-) diff -Naurp ./drivers/ide/legacy/ide-cs.c~idecs_stack ./drivers/ide/legacy/ide-cs.c --- ./drivers/ide/legacy/ide-cs.c~idecs_stack 2004-05-09 19:32:53.000000000 -0700 +++ ./drivers/ide/legacy/ide-cs.c 2004-06-15 15:32:42.000000000 -0700 @@ -199,6 +199,16 @@ static void ide_detach(dev_link_t *link) } /* ide_detach */ +static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) +{ + hw_regs_t hw; + memset(&hw, 0, sizeof(hw)); + ide_init_hwif_ports(&hw, io, ctl, NULL); + hw.irq = irq; + hw.chipset = ide_pci; + return ide_register_hw(&hw, NULL); +} + /*====================================================================== ide_config() is scheduled to run after a CARD_INSERTION event @@ -210,84 +220,86 @@ static void ide_detach(dev_link_t *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) -{ - hw_regs_t hw; - memset(&hw, 0, sizeof(hw)); - ide_init_hwif_ports(&hw, io, ctl, NULL); - hw.irq = irq; - hw.chipset = ide_pci; - return ide_register_hw(&hw, NULL); -} - void ide_config(dev_link_t *link) { client_handle_t handle = link->handle; ide_info_t *info = link->priv; tuple_t tuple; - u_short buf[128]; - cisparse_t parse; - config_info_t conf; - cistpl_cftable_entry_t *cfg = &parse.cftable_entry; - cistpl_cftable_entry_t dflt = { 0 }; - int i, pass, last_ret, last_fn, hd, is_kme = 0; + u_short *tbuf; + cisparse_t *cisparse; + config_info_t *cfginfo = 0; + cistpl_cftable_entry_t *cfg; + cistpl_cftable_entry_t *def_cte = 0; + int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0; unsigned long io_base, ctl_base; DEBUG(0, "ide_config(0x%p)\n", link); - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + + tbuf = kmalloc(128 * sizeof(u_short), GFP_KERNEL); + if (!tbuf) goto err_tbuf; + def_cte = kmalloc(sizeof(*def_cte), GFP_KERNEL); + if (!def_cte) goto err_def_cte; + memset(def_cte, 0, sizeof(*def_cte)); + cfginfo = kmalloc(sizeof(*cfginfo), GFP_KERNEL); + if (!cfginfo) goto err_cfginfo; + cisparse = kmalloc(sizeof(*cisparse), GFP_KERNEL); + if (!cisparse) goto err_cisparse; + cfg = &cisparse->cftable_entry; + + tuple.TupleData = (cisdata_t *)tbuf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, cisparse)); + link->conf.ConfigBase = cisparse->config.base; + link->conf.Present = cisparse->config.rmask[0]; tuple.DesiredTuple = CISTPL_MANFID; if (!pcmcia_get_first_tuple(handle, &tuple) && !pcmcia_get_tuple_data(handle, &tuple) && - !pcmcia_parse_tuple(handle, &tuple, &parse)) - is_kme = ((parse.manfid.manf == MANFID_KME) && - ((parse.manfid.card == PRODID_KME_KXLC005_A) || - (parse.manfid.card == PRODID_KME_KXLC005_B))); + !pcmcia_parse_tuple(handle, &tuple, cisparse)) + is_kme = ((cisparse->manfid.manf == MANFID_KME) && + ((cisparse->manfid.card == PRODID_KME_KXLC005_A) || + (cisparse->manfid.card == PRODID_KME_KXLC005_B))); /* Configure card */ link->state |= DEV_CONFIG; /* Not sure if this is right... look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; - + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, cfginfo)); + link->conf.Vcc = cfginfo->Vcc; + pass = io_base = ctl_base = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); while (1) { if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry; - if (pcmcia_parse_tuple(handle, &tuple, &parse) != 0) goto next_entry; + if (pcmcia_parse_tuple(handle, &tuple, cisparse) != 0) goto next_entry; /* Check for matching Vcc, unless we're desperate */ if (!pass) { - if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) + if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (cfginfo->Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; - } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) + } else if (def_cte->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (cfginfo->Vcc != def_cte->vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; } } - - if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) + + if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = - cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) + cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; + else if (def_cte->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = - dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; - - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + def_cte->vpp1.param[CISTPL_POWER_VNOM] / 10000; + + if ((cfg->io.nwin > 0) || (def_cte->io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &def_cte->io; link->conf.ConfigIndex = cfg->index; link->io.BasePort1 = io->win[0].base; link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; @@ -307,23 +319,24 @@ void ide_config(dev_link_t *link) if (pcmcia_request_io(link->handle, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; - ctl_base = link->io.BasePort1+0x0e; + ctl_base = link->io.BasePort1 + 0x0e; } else goto next_entry; /* If we've got this far, we're done */ break; } - + next_entry: - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + memcpy(def_cte, cfg, sizeof(*def_cte)); if (pass) { CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) { CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - memset(&dflt, 0, sizeof(dflt)); + memset(def_cte, 0, sizeof(*def_cte)); pass++; } } - + CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); @@ -336,25 +349,27 @@ void ide_config(dev_link_t *link) outb(0x02, ctl_base); /* special setup for KXLC005 card */ - if (is_kme) outb(0x81, ctl_base+1); + if (is_kme) + outb(0x81, ctl_base+1); /* retry registration in case device is still spinning up */ for (hd = -1, i = 0; i < 10; i++) { hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ); if (hd >= 0) break; if (link->io.NumPorts1 == 0x20) { - outb(0x02, ctl_base+0x10); - hd = idecs_register(io_base+0x10, ctl_base+0x10, + outb(0x02, ctl_base + 0x10); + hd = idecs_register(io_base + 0x10, ctl_base + 0x10, link->irq.AssignedIRQ); if (hd >= 0) { - io_base += 0x10; ctl_base += 0x10; + io_base += 0x10; + ctl_base += 0x10; break; } } __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); } - + if (hd < 0) { printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx" ", irq %u failed\n", io_base, ctl_base, @@ -363,24 +378,34 @@ void ide_config(dev_link_t *link) } info->ndev = 1; - sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2)); + sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2)); info->node.major = ide_major[hd]; info->node.minor = 0; info->hd = hd; link->dev = &info->node; printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", - info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10, - link->conf.Vpp1/10, link->conf.Vpp1%10); + info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10, + link->conf.Vpp1 / 10, link->conf.Vpp1 % 10); link->state &= ~DEV_CONFIG_PENDING; return; - + cs_failed: cs_error(link->handle, last_fn, last_ret); failed: ide_release(link); link->state &= ~DEV_CONFIG_PENDING; + /* memory allocation errors */ +err_cisparse: + kfree(cfginfo); +err_cfginfo: + kfree(def_cte); +err_def_cte: + kfree(tbuf); +err_tbuf: + printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); + goto failed; } /* ide_config */ /*====================================================================== ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] [STACK] >3k call path in ide 2004-06-15 23:34 ` [PATCH] " Randy.Dunlap @ 2004-06-16 7:11 ` Florian Schirmer 2004-06-16 9:47 ` Jörn Engel 0 siblings, 1 reply; 21+ messages in thread From: Florian Schirmer @ 2004-06-16 7:11 UTC (permalink / raw) To: Randy.Dunlap Cc: Jörn Engel, akpm, B.Zolnierkiewicz, linux-ide, linux-kernel Hi, > failed: > ide_release(link); > link->state &= ~DEV_CONFIG_PENDING; > > + /* memory allocation errors */ > +err_cisparse: > + kfree(cfginfo); > +err_cfginfo: > + kfree(def_cte); > +err_def_cte: > + kfree(tbuf); > +err_tbuf: > + printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); > + goto failed; > } /* ide_config */ Huh? This will either leak memory (non alloc error case) or deadlock (mem alloc error case). I'm missing something? Best, Florian ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] [STACK] >3k call path in ide 2004-06-16 7:11 ` Florian Schirmer @ 2004-06-16 9:47 ` Jörn Engel 2004-06-16 9:55 ` Florian Schirmer 0 siblings, 1 reply; 21+ messages in thread From: Jörn Engel @ 2004-06-16 9:47 UTC (permalink / raw) To: Florian Schirmer Cc: Randy.Dunlap, akpm, B.Zolnierkiewicz, linux-ide, linux-kernel On Wed, 16 June 2004 09:11:11 +0200, Florian Schirmer wrote: > > > failed: > > ide_release(link); > > link->state &= ~DEV_CONFIG_PENDING; > > > > + /* memory allocation errors */ > > +err_cisparse: > > + kfree(cfginfo); > > +err_cfginfo: > > + kfree(def_cte); > > +err_def_cte: > > + kfree(tbuf); > > +err_tbuf: > > + printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); > > + goto failed; > > } /* ide_config */ > > Huh? This will either leak memory (non alloc error case) or deadlock (mem > alloc error case). I'm missing something? Leak memory. I also tend to depend on the fact that kfree(NULL) works just fine: err_kfree: kfree(cfginfo); kfree(def_cte); kfree(tbuf); printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); goto failed; Makes the error path a little simpler. Jörn -- The strong give up and move away, while the weak give up and stay. -- unknown ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] [STACK] >3k call path in ide 2004-06-16 9:47 ` Jörn Engel @ 2004-06-16 9:55 ` Florian Schirmer 2004-06-16 10:00 ` Jörn Engel 0 siblings, 1 reply; 21+ messages in thread From: Florian Schirmer @ 2004-06-16 9:55 UTC (permalink / raw) To: Jörn Engel Cc: Randy.Dunlap, akpm, B.Zolnierkiewicz, linux-ide, linux-kernel Hi, >Leak memory. I also tend to depend on the fact that kfree(NULL) works >just fine: > >err_kfree: > kfree(cfginfo); > kfree(def_cte); > kfree(tbuf); > printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); > goto failed; > >Makes the error path a little simpler. > > Nope. It will deadlock just like the original patch because failed falls through to err_kfree which then will jump to failed... Regards, Florian ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] [STACK] >3k call path in ide 2004-06-16 9:55 ` Florian Schirmer @ 2004-06-16 10:00 ` Jörn Engel 2004-06-16 17:37 ` [PATCH] [STACK] reduce " Randy.Dunlap 0 siblings, 1 reply; 21+ messages in thread From: Jörn Engel @ 2004-06-16 10:00 UTC (permalink / raw) To: Florian Schirmer Cc: Randy.Dunlap, akpm, B.Zolnierkiewicz, linux-ide, linux-kernel On Wed, 16 June 2004 11:55:52 +0200, Florian Schirmer wrote: > > >Leak memory. > > Nope. It will deadlock just like the original patch because failed falls > through to err_kfree which then will jump to failed... Both, leak memory on good path, deadlock on error path. Fun patch. :) Jörn -- It is better to die of hunger having lived without grief and fear, than to live with a troubled spirit amid abundance. -- Epictetus ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH] [STACK] reduce >3k call path in ide 2004-06-16 10:00 ` Jörn Engel @ 2004-06-16 17:37 ` Randy.Dunlap 2004-06-16 17:57 ` Jörn Engel 2004-06-16 18:58 ` Brian Gerst 0 siblings, 2 replies; 21+ messages in thread From: Randy.Dunlap @ 2004-06-16 17:37 UTC (permalink / raw) To: Jörn Engel; +Cc: jolt, akpm, B.Zolnierkiewicz, linux-ide, linux-kernel Thanks for the helpful comments. Here's a corrected patch. Reduce large stack usage in ide_config() by using kmalloc(). Little whitespace cleanup. Move function comment block to immediately above the function. Module loaded and unloaded, otherwise not tested (no hardware). Signed-off-by: Randy Dunlap <rddunlap@osdl.org> diffstat:= drivers/ide/legacy/ide-cs.c | 135 +++++++++++++++++++++++++------------------- 1 files changed, 79 insertions(+), 56 deletions(-) diff -Naurp ./drivers/ide/legacy/ide-cs.c~idecs_stack ./drivers/ide/legacy/ide-cs.c --- ./drivers/ide/legacy/ide-cs.c~idecs_stack 2004-05-09 19:32:53.000000000 -0700 +++ ./drivers/ide/legacy/ide-cs.c 2004-06-16 09:11:14.431098048 -0700 @@ -199,6 +199,16 @@ static void ide_detach(dev_link_t *link) } /* ide_detach */ +static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) +{ + hw_regs_t hw; + memset(&hw, 0, sizeof(hw)); + ide_init_hwif_ports(&hw, io, ctl, NULL); + hw.irq = irq; + hw.chipset = ide_pci; + return ide_register_hw(&hw, NULL); +} + /*====================================================================== ide_config() is scheduled to run after a CARD_INSERTION event @@ -210,84 +220,86 @@ static void ide_detach(dev_link_t *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) -{ - hw_regs_t hw; - memset(&hw, 0, sizeof(hw)); - ide_init_hwif_ports(&hw, io, ctl, NULL); - hw.irq = irq; - hw.chipset = ide_pci; - return ide_register_hw(&hw, NULL); -} - void ide_config(dev_link_t *link) { client_handle_t handle = link->handle; ide_info_t *info = link->priv; tuple_t tuple; - u_short buf[128]; - cisparse_t parse; - config_info_t conf; - cistpl_cftable_entry_t *cfg = &parse.cftable_entry; - cistpl_cftable_entry_t dflt = { 0 }; - int i, pass, last_ret, last_fn, hd, is_kme = 0; + u_short *tbuf = 0; + cisparse_t *cisparse = 0; + config_info_t *cfginfo = 0; + cistpl_cftable_entry_t *cfg; + cistpl_cftable_entry_t *def_cte = 0; + int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0; unsigned long io_base, ctl_base; DEBUG(0, "ide_config(0x%p)\n", link); - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + + tbuf = kmalloc(128 * sizeof(u_short), GFP_KERNEL); + if (!tbuf) goto err_kfree; + def_cte = kmalloc(sizeof(*def_cte), GFP_KERNEL); + if (!def_cte) goto err_kfree; + memset(def_cte, 0, sizeof(*def_cte)); + cfginfo = kmalloc(sizeof(*cfginfo), GFP_KERNEL); + if (!cfginfo) goto err_kfree; + cisparse = kmalloc(sizeof(*cisparse), GFP_KERNEL); + if (!cisparse) goto err_kfree; + cfg = &cisparse->cftable_entry; + + tuple.TupleData = (cisdata_t *)tbuf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, cisparse)); + link->conf.ConfigBase = cisparse->config.base; + link->conf.Present = cisparse->config.rmask[0]; tuple.DesiredTuple = CISTPL_MANFID; if (!pcmcia_get_first_tuple(handle, &tuple) && !pcmcia_get_tuple_data(handle, &tuple) && - !pcmcia_parse_tuple(handle, &tuple, &parse)) - is_kme = ((parse.manfid.manf == MANFID_KME) && - ((parse.manfid.card == PRODID_KME_KXLC005_A) || - (parse.manfid.card == PRODID_KME_KXLC005_B))); + !pcmcia_parse_tuple(handle, &tuple, cisparse)) + is_kme = ((cisparse->manfid.manf == MANFID_KME) && + ((cisparse->manfid.card == PRODID_KME_KXLC005_A) || + (cisparse->manfid.card == PRODID_KME_KXLC005_B))); /* Configure card */ link->state |= DEV_CONFIG; /* Not sure if this is right... look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; - + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, cfginfo)); + link->conf.Vcc = cfginfo->Vcc; + pass = io_base = ctl_base = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); while (1) { if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry; - if (pcmcia_parse_tuple(handle, &tuple, &parse) != 0) goto next_entry; + if (pcmcia_parse_tuple(handle, &tuple, cisparse) != 0) goto next_entry; /* Check for matching Vcc, unless we're desperate */ if (!pass) { - if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) + if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (cfginfo->Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; - } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) + } else if (def_cte->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (cfginfo->Vcc != def_cte->vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; } } - - if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) + + if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = - cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) + cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; + else if (def_cte->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = - dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; - - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + def_cte->vpp1.param[CISTPL_POWER_VNOM] / 10000; + + if ((cfg->io.nwin > 0) || (def_cte->io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &def_cte->io; link->conf.ConfigIndex = cfg->index; link->io.BasePort1 = io->win[0].base; link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; @@ -307,23 +319,24 @@ void ide_config(dev_link_t *link) if (pcmcia_request_io(link->handle, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; - ctl_base = link->io.BasePort1+0x0e; + ctl_base = link->io.BasePort1 + 0x0e; } else goto next_entry; /* If we've got this far, we're done */ break; } - + next_entry: - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + memcpy(def_cte, cfg, sizeof(*def_cte)); if (pass) { CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) { CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - memset(&dflt, 0, sizeof(dflt)); + memset(def_cte, 0, sizeof(*def_cte)); pass++; } } - + CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); @@ -336,25 +349,27 @@ void ide_config(dev_link_t *link) outb(0x02, ctl_base); /* special setup for KXLC005 card */ - if (is_kme) outb(0x81, ctl_base+1); + if (is_kme) + outb(0x81, ctl_base+1); /* retry registration in case device is still spinning up */ for (hd = -1, i = 0; i < 10; i++) { hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ); if (hd >= 0) break; if (link->io.NumPorts1 == 0x20) { - outb(0x02, ctl_base+0x10); - hd = idecs_register(io_base+0x10, ctl_base+0x10, + outb(0x02, ctl_base + 0x10); + hd = idecs_register(io_base + 0x10, ctl_base + 0x10, link->irq.AssignedIRQ); if (hd >= 0) { - io_base += 0x10; ctl_base += 0x10; + io_base += 0x10; + ctl_base += 0x10; break; } } __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); } - + if (hd < 0) { printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx" ", irq %u failed\n", io_base, ctl_base, @@ -363,24 +378,32 @@ void ide_config(dev_link_t *link) } info->ndev = 1; - sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2)); + sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2)); info->node.major = ide_major[hd]; info->node.minor = 0; info->hd = hd; link->dev = &info->node; printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", - info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10, - link->conf.Vpp1/10, link->conf.Vpp1%10); + info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10, + link->conf.Vpp1 / 10, link->conf.Vpp1 % 10); link->state &= ~DEV_CONFIG_PENDING; return; - + cs_failed: cs_error(link->handle, last_fn, last_ret); failed: ide_release(link); link->state &= ~DEV_CONFIG_PENDING; + return; + /* memory allocation errors */ +err_kfree: + kfree(cfginfo); + kfree(def_cte); + kfree(tbuf); + printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); + goto failed; } /* ide_config */ /*====================================================================== ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] [STACK] reduce >3k call path in ide 2004-06-16 17:37 ` [PATCH] [STACK] reduce " Randy.Dunlap @ 2004-06-16 17:57 ` Jörn Engel 2004-06-16 18:16 ` Randy.Dunlap 2004-06-16 18:58 ` Brian Gerst 1 sibling, 1 reply; 21+ messages in thread From: Jörn Engel @ 2004-06-16 17:57 UTC (permalink / raw) To: Randy.Dunlap; +Cc: jolt, akpm, B.Zolnierkiewicz, linux-ide, linux-kernel On Wed, 16 June 2004 10:37:41 -0700, Randy.Dunlap wrote: > > Thanks for the helpful comments. Here's a corrected patch. Looks, as if it still leaks memory: > > link->state &= ~DEV_CONFIG_PENDING; about here. > return; > - > + > cs_failed: > cs_error(link->handle, last_fn, last_ret); > failed: > ide_release(link); > link->state &= ~DEV_CONFIG_PENDING; > + return; > > + /* memory allocation errors */ > +err_kfree: > + kfree(cfginfo); > + kfree(def_cte); > + kfree(tbuf); > + printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); > + goto failed; > } /* ide_config */ > > /*====================================================================== Jörn -- Schrödinger's cat is <BLINK>not</BLINK> dead. -- Illiad ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] [STACK] reduce >3k call path in ide 2004-06-16 17:57 ` Jörn Engel @ 2004-06-16 18:16 ` Randy.Dunlap 2004-06-16 18:29 ` Jörn Engel 0 siblings, 1 reply; 21+ messages in thread From: Randy.Dunlap @ 2004-06-16 18:16 UTC (permalink / raw) To: Jörn Engel; +Cc: jolt, akpm, B.Zolnierkiewicz, linux-ide, linux-kernel On Wed, 16 Jun 2004 19:57:30 +0200 Jörn Engel wrote: | On Wed, 16 June 2004 10:37:41 -0700, Randy.Dunlap wrote: | > | > Thanks for the helpful comments. Here's a corrected patch. | | Looks, as if it still leaks memory: duh. fudge. Thanks. How's this one? Reduce large stack usage in ide_config() by using kmalloc(), down from 0x4a4 bytes to 0x74 bytes (x86-32). Little whitespace cleanup. Move function comment block to immediately above the function. Module loaded and unloaded, otherwise not tested (no hardware). Signed-off-by: Randy Dunlap <rddunlap@osdl.org> diffstat:= drivers/ide/legacy/ide-cs.c | 137 +++++++++++++++++++++++++------------------- 1 files changed, 80 insertions(+), 57 deletions(-) diff -Naurp ./drivers/ide/legacy/ide-cs.c~idecs_stack ./drivers/ide/legacy/ide-cs.c --- ./drivers/ide/legacy/ide-cs.c~idecs_stack 2004-05-09 19:32:53.000000000 -0700 +++ ./drivers/ide/legacy/ide-cs.c 2004-06-16 10:42:00.554161496 -0700 @@ -199,6 +199,16 @@ static void ide_detach(dev_link_t *link) } /* ide_detach */ +static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) +{ + hw_regs_t hw; + memset(&hw, 0, sizeof(hw)); + ide_init_hwif_ports(&hw, io, ctl, NULL); + hw.irq = irq; + hw.chipset = ide_pci; + return ide_register_hw(&hw, NULL); +} + /*====================================================================== ide_config() is scheduled to run after a CARD_INSERTION event @@ -210,84 +220,86 @@ static void ide_detach(dev_link_t *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) -{ - hw_regs_t hw; - memset(&hw, 0, sizeof(hw)); - ide_init_hwif_ports(&hw, io, ctl, NULL); - hw.irq = irq; - hw.chipset = ide_pci; - return ide_register_hw(&hw, NULL); -} - void ide_config(dev_link_t *link) { client_handle_t handle = link->handle; ide_info_t *info = link->priv; tuple_t tuple; - u_short buf[128]; - cisparse_t parse; - config_info_t conf; - cistpl_cftable_entry_t *cfg = &parse.cftable_entry; - cistpl_cftable_entry_t dflt = { 0 }; - int i, pass, last_ret, last_fn, hd, is_kme = 0; + u_short *tbuf = 0; + cisparse_t *cisparse = 0; + config_info_t *cfginfo = 0; + cistpl_cftable_entry_t *cfg; + cistpl_cftable_entry_t *def_cte = 0; + int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0; unsigned long io_base, ctl_base; DEBUG(0, "ide_config(0x%p)\n", link); - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + + tbuf = kmalloc(128 * sizeof(u_short), GFP_KERNEL); + if (!tbuf) goto err_mem; + def_cte = kmalloc(sizeof(*def_cte), GFP_KERNEL); + if (!def_cte) goto err_mem; + memset(def_cte, 0, sizeof(*def_cte)); + cfginfo = kmalloc(sizeof(*cfginfo), GFP_KERNEL); + if (!cfginfo) goto err_mem; + cisparse = kmalloc(sizeof(*cisparse), GFP_KERNEL); + if (!cisparse) goto err_mem; + cfg = &cisparse->cftable_entry; + + tuple.TupleData = (cisdata_t *)tbuf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, cisparse)); + link->conf.ConfigBase = cisparse->config.base; + link->conf.Present = cisparse->config.rmask[0]; tuple.DesiredTuple = CISTPL_MANFID; if (!pcmcia_get_first_tuple(handle, &tuple) && !pcmcia_get_tuple_data(handle, &tuple) && - !pcmcia_parse_tuple(handle, &tuple, &parse)) - is_kme = ((parse.manfid.manf == MANFID_KME) && - ((parse.manfid.card == PRODID_KME_KXLC005_A) || - (parse.manfid.card == PRODID_KME_KXLC005_B))); + !pcmcia_parse_tuple(handle, &tuple, cisparse)) + is_kme = ((cisparse->manfid.manf == MANFID_KME) && + ((cisparse->manfid.card == PRODID_KME_KXLC005_A) || + (cisparse->manfid.card == PRODID_KME_KXLC005_B))); /* Configure card */ link->state |= DEV_CONFIG; /* Not sure if this is right... look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; - + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, cfginfo)); + link->conf.Vcc = cfginfo->Vcc; + pass = io_base = ctl_base = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); while (1) { if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry; - if (pcmcia_parse_tuple(handle, &tuple, &parse) != 0) goto next_entry; + if (pcmcia_parse_tuple(handle, &tuple, cisparse) != 0) goto next_entry; /* Check for matching Vcc, unless we're desperate */ if (!pass) { - if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) + if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (cfginfo->Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; - } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) + } else if (def_cte->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (cfginfo->Vcc != def_cte->vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; } } - - if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) + + if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = - cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) + cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; + else if (def_cte->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = - dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; - - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + def_cte->vpp1.param[CISTPL_POWER_VNOM] / 10000; + + if ((cfg->io.nwin > 0) || (def_cte->io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &def_cte->io; link->conf.ConfigIndex = cfg->index; link->io.BasePort1 = io->win[0].base; link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; @@ -307,23 +319,24 @@ void ide_config(dev_link_t *link) if (pcmcia_request_io(link->handle, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; - ctl_base = link->io.BasePort1+0x0e; + ctl_base = link->io.BasePort1 + 0x0e; } else goto next_entry; /* If we've got this far, we're done */ break; } - + next_entry: - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + memcpy(def_cte, cfg, sizeof(*def_cte)); if (pass) { CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) { CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - memset(&dflt, 0, sizeof(dflt)); + memset(def_cte, 0, sizeof(*def_cte)); pass++; } } - + CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); @@ -336,25 +349,27 @@ void ide_config(dev_link_t *link) outb(0x02, ctl_base); /* special setup for KXLC005 card */ - if (is_kme) outb(0x81, ctl_base+1); + if (is_kme) + outb(0x81, ctl_base+1); /* retry registration in case device is still spinning up */ for (hd = -1, i = 0; i < 10; i++) { hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ); if (hd >= 0) break; if (link->io.NumPorts1 == 0x20) { - outb(0x02, ctl_base+0x10); - hd = idecs_register(io_base+0x10, ctl_base+0x10, + outb(0x02, ctl_base + 0x10); + hd = idecs_register(io_base + 0x10, ctl_base + 0x10, link->irq.AssignedIRQ); if (hd >= 0) { - io_base += 0x10; ctl_base += 0x10; + io_base += 0x10; + ctl_base += 0x10; break; } } __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); } - + if (hd < 0) { printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx" ", irq %u failed\n", io_base, ctl_base, @@ -363,24 +378,32 @@ void ide_config(dev_link_t *link) } info->ndev = 1; - sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2)); + sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2)); info->node.major = ide_major[hd]; info->node.minor = 0; info->hd = hd; link->dev = &info->node; printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", - info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10, - link->conf.Vpp1/10, link->conf.Vpp1%10); + info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10, + link->conf.Vpp1 / 10, link->conf.Vpp1 % 10); link->state &= ~DEV_CONFIG_PENDING; return; - + +err_mem: + printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); + goto failed; + cs_failed: cs_error(link->handle, last_fn, last_ret); failed: + kfree(cisparse); + kfree(cfginfo); + kfree(def_cte); + kfree(tbuf); + ide_release(link); link->state &= ~DEV_CONFIG_PENDING; - } /* ide_config */ /*====================================================================== ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] [STACK] reduce >3k call path in ide 2004-06-16 18:16 ` Randy.Dunlap @ 2004-06-16 18:29 ` Jörn Engel 2004-06-16 18:49 ` Randy.Dunlap 0 siblings, 1 reply; 21+ messages in thread From: Jörn Engel @ 2004-06-16 18:29 UTC (permalink / raw) To: Randy.Dunlap; +Cc: jolt, akpm, B.Zolnierkiewicz, linux-ide, linux-kernel On Wed, 16 June 2004 11:16:21 -0700, Randy.Dunlap wrote: > On Wed, 16 Jun 2004 19:57:30 +0200 Jörn Engel wrote: > > | On Wed, 16 June 2004 10:37:41 -0700, Randy.Dunlap wrote: > | > > | > Thanks for the helpful comments. Here's a corrected patch. > | > | Looks, as if it still leaks memory: > > duh. fudge. Thanks. How's this one? Just four more lines? > link->dev = &info->node; > printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", > - info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10, > - link->conf.Vpp1/10, link->conf.Vpp1%10); > + info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10, > + link->conf.Vpp1 / 10, link->conf.Vpp1 % 10); > > link->state &= ~DEV_CONFIG_PENDING; + kfree(cisparse); + kfree(cfginfo); + kfree(def_cte); + kfree(tbuf); > return; > - > + > +err_mem: > + printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); > + goto failed; > + > cs_failed: > cs_error(link->handle, last_fn, last_ret); > failed: > + kfree(cisparse); > + kfree(cfginfo); > + kfree(def_cte); > + kfree(tbuf); > + > ide_release(link); > link->state &= ~DEV_CONFIG_PENDING; > - > } /* ide_config */ > > /*====================================================================== Jörn -- Fancy algorithms are slow when n is small, and n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don't get fancy. -- Rob Pike ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] [STACK] reduce >3k call path in ide 2004-06-16 18:29 ` Jörn Engel @ 2004-06-16 18:49 ` Randy.Dunlap 0 siblings, 0 replies; 21+ messages in thread From: Randy.Dunlap @ 2004-06-16 18:49 UTC (permalink / raw) To: Jörn Engel; +Cc: jolt, akpm, B.Zolnierkiewicz, linux-ide, linux-kernel On Wed, 16 Jun 2004 20:29:10 +0200 Jörn Engel wrote: | On Wed, 16 June 2004 11:16:21 -0700, Randy.Dunlap wrote: | > On Wed, 16 Jun 2004 19:57:30 +0200 Jörn Engel wrote: | > | > | On Wed, 16 June 2004 10:37:41 -0700, Randy.Dunlap wrote: | > | > | > | > Thanks for the helpful comments. Here's a corrected patch. | > | | > | Looks, as if it still leaks memory: | > | > duh. fudge. Thanks. How's this one? | | Just four more lines? OK, Randy, slow down and go to lunch. Thanks, Jörn. Reduce large stack usage in ide_config() by using kmalloc(), down from 0x4a4 bytes to 0x74 bytes (x86-32). Little whitespace cleanup. Move function comment block to immediately above the function. Module loaded and unloaded, otherwise not tested (no hardware). Signed-off-by: Randy Dunlap <rddunlap@osdl.org> diffstat:= drivers/ide/legacy/ide-cs.c | 141 ++++++++++++++++++++++++++------------------ 1 files changed, 84 insertions(+), 57 deletions(-) diff -Naurp ./drivers/ide/legacy/ide-cs.c~idecs_stack ./drivers/ide/legacy/ide-cs.c --- ./drivers/ide/legacy/ide-cs.c~idecs_stack 2004-05-09 19:32:53.000000000 -0700 +++ ./drivers/ide/legacy/ide-cs.c 2004-06-16 11:01:43.000000000 -0700 @@ -199,6 +199,16 @@ static void ide_detach(dev_link_t *link) } /* ide_detach */ +static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) +{ + hw_regs_t hw; + memset(&hw, 0, sizeof(hw)); + ide_init_hwif_ports(&hw, io, ctl, NULL); + hw.irq = irq; + hw.chipset = ide_pci; + return ide_register_hw(&hw, NULL); +} + /*====================================================================== ide_config() is scheduled to run after a CARD_INSERTION event @@ -210,84 +220,86 @@ static void ide_detach(dev_link_t *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) -{ - hw_regs_t hw; - memset(&hw, 0, sizeof(hw)); - ide_init_hwif_ports(&hw, io, ctl, NULL); - hw.irq = irq; - hw.chipset = ide_pci; - return ide_register_hw(&hw, NULL); -} - void ide_config(dev_link_t *link) { client_handle_t handle = link->handle; ide_info_t *info = link->priv; tuple_t tuple; - u_short buf[128]; - cisparse_t parse; - config_info_t conf; - cistpl_cftable_entry_t *cfg = &parse.cftable_entry; - cistpl_cftable_entry_t dflt = { 0 }; - int i, pass, last_ret, last_fn, hd, is_kme = 0; + u_short *tbuf = 0; + cisparse_t *cisparse = 0; + config_info_t *cfginfo = 0; + cistpl_cftable_entry_t *cfg; + cistpl_cftable_entry_t *def_cte = 0; + int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0; unsigned long io_base, ctl_base; DEBUG(0, "ide_config(0x%p)\n", link); - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + + tbuf = kmalloc(128 * sizeof(u_short), GFP_KERNEL); + if (!tbuf) goto err_mem; + def_cte = kmalloc(sizeof(*def_cte), GFP_KERNEL); + if (!def_cte) goto err_mem; + memset(def_cte, 0, sizeof(*def_cte)); + cfginfo = kmalloc(sizeof(*cfginfo), GFP_KERNEL); + if (!cfginfo) goto err_mem; + cisparse = kmalloc(sizeof(*cisparse), GFP_KERNEL); + if (!cisparse) goto err_mem; + cfg = &cisparse->cftable_entry; + + tuple.TupleData = (cisdata_t *)tbuf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, cisparse)); + link->conf.ConfigBase = cisparse->config.base; + link->conf.Present = cisparse->config.rmask[0]; tuple.DesiredTuple = CISTPL_MANFID; if (!pcmcia_get_first_tuple(handle, &tuple) && !pcmcia_get_tuple_data(handle, &tuple) && - !pcmcia_parse_tuple(handle, &tuple, &parse)) - is_kme = ((parse.manfid.manf == MANFID_KME) && - ((parse.manfid.card == PRODID_KME_KXLC005_A) || - (parse.manfid.card == PRODID_KME_KXLC005_B))); + !pcmcia_parse_tuple(handle, &tuple, cisparse)) + is_kme = ((cisparse->manfid.manf == MANFID_KME) && + ((cisparse->manfid.card == PRODID_KME_KXLC005_A) || + (cisparse->manfid.card == PRODID_KME_KXLC005_B))); /* Configure card */ link->state |= DEV_CONFIG; /* Not sure if this is right... look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; - + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, cfginfo)); + link->conf.Vcc = cfginfo->Vcc; + pass = io_base = ctl_base = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); while (1) { if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry; - if (pcmcia_parse_tuple(handle, &tuple, &parse) != 0) goto next_entry; + if (pcmcia_parse_tuple(handle, &tuple, cisparse) != 0) goto next_entry; /* Check for matching Vcc, unless we're desperate */ if (!pass) { - if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) + if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (cfginfo->Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; - } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) + } else if (def_cte->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (cfginfo->Vcc != def_cte->vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; } } - - if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) + + if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = - cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) + cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; + else if (def_cte->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = - dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; - - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + def_cte->vpp1.param[CISTPL_POWER_VNOM] / 10000; + + if ((cfg->io.nwin > 0) || (def_cte->io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &def_cte->io; link->conf.ConfigIndex = cfg->index; link->io.BasePort1 = io->win[0].base; link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; @@ -307,23 +319,24 @@ void ide_config(dev_link_t *link) if (pcmcia_request_io(link->handle, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; - ctl_base = link->io.BasePort1+0x0e; + ctl_base = link->io.BasePort1 + 0x0e; } else goto next_entry; /* If we've got this far, we're done */ break; } - + next_entry: - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + memcpy(def_cte, cfg, sizeof(*def_cte)); if (pass) { CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) { CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - memset(&dflt, 0, sizeof(dflt)); + memset(def_cte, 0, sizeof(*def_cte)); pass++; } } - + CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); @@ -336,25 +349,27 @@ void ide_config(dev_link_t *link) outb(0x02, ctl_base); /* special setup for KXLC005 card */ - if (is_kme) outb(0x81, ctl_base+1); + if (is_kme) + outb(0x81, ctl_base+1); /* retry registration in case device is still spinning up */ for (hd = -1, i = 0; i < 10; i++) { hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ); if (hd >= 0) break; if (link->io.NumPorts1 == 0x20) { - outb(0x02, ctl_base+0x10); - hd = idecs_register(io_base+0x10, ctl_base+0x10, + outb(0x02, ctl_base + 0x10); + hd = idecs_register(io_base + 0x10, ctl_base + 0x10, link->irq.AssignedIRQ); if (hd >= 0) { - io_base += 0x10; ctl_base += 0x10; + io_base += 0x10; + ctl_base += 0x10; break; } } __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); } - + if (hd < 0) { printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx" ", irq %u failed\n", io_base, ctl_base, @@ -363,24 +378,36 @@ void ide_config(dev_link_t *link) } info->ndev = 1; - sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2)); + sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2)); info->node.major = ide_major[hd]; info->node.minor = 0; info->hd = hd; link->dev = &info->node; printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", - info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10, - link->conf.Vpp1/10, link->conf.Vpp1%10); + info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10, + link->conf.Vpp1 / 10, link->conf.Vpp1 % 10); link->state &= ~DEV_CONFIG_PENDING; + kfree(cisparse); + kfree(cfginfo); + kfree(def_cte); + kfree(tbuf); return; - + +err_mem: + printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); + goto failed; + cs_failed: cs_error(link->handle, last_fn, last_ret); failed: + kfree(cisparse); + kfree(cfginfo); + kfree(def_cte); + kfree(tbuf); + ide_release(link); link->state &= ~DEV_CONFIG_PENDING; - } /* ide_config */ /*====================================================================== ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] [STACK] reduce >3k call path in ide 2004-06-16 17:37 ` [PATCH] [STACK] reduce " Randy.Dunlap 2004-06-16 17:57 ` Jörn Engel @ 2004-06-16 18:58 ` Brian Gerst 2004-06-16 19:52 ` Randy.Dunlap 1 sibling, 1 reply; 21+ messages in thread From: Brian Gerst @ 2004-06-16 18:58 UTC (permalink / raw) To: Randy.Dunlap Cc: Jörn Engel, jolt, akpm, B.Zolnierkiewicz, linux-ide, linux-kernel Randy.Dunlap wrote: > + tbuf = kmalloc(128 * sizeof(u_short), GFP_KERNEL); > + if (!tbuf) goto err_kfree; > + def_cte = kmalloc(sizeof(*def_cte), GFP_KERNEL); > + if (!def_cte) goto err_kfree; > + memset(def_cte, 0, sizeof(*def_cte)); > + cfginfo = kmalloc(sizeof(*cfginfo), GFP_KERNEL); > + if (!cfginfo) goto err_kfree; > + cisparse = kmalloc(sizeof(*cisparse), GFP_KERNEL); > + if (!cisparse) goto err_kfree; This can be condensed into a single kmalloc. Define a struct that contains these variables and kmalloc the whole struct in one call. -- Brian Gerst ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] [STACK] reduce >3k call path in ide 2004-06-16 18:58 ` Brian Gerst @ 2004-06-16 19:52 ` Randy.Dunlap 2004-06-16 22:53 ` Randy.Dunlap 0 siblings, 1 reply; 21+ messages in thread From: Randy.Dunlap @ 2004-06-16 19:52 UTC (permalink / raw) To: Brian Gerst; +Cc: joern, jolt, akpm, B.Zolnierkiewicz, linux-ide, linux-kernel On Wed, 16 Jun 2004 14:58:19 -0400 Brian Gerst wrote: | Randy.Dunlap wrote: | > + tbuf = kmalloc(128 * sizeof(u_short), GFP_KERNEL); | > + if (!tbuf) goto err_kfree; | > + def_cte = kmalloc(sizeof(*def_cte), GFP_KERNEL); | > + if (!def_cte) goto err_kfree; | > + memset(def_cte, 0, sizeof(*def_cte)); | > + cfginfo = kmalloc(sizeof(*cfginfo), GFP_KERNEL); | > + if (!cfginfo) goto err_kfree; | > + cisparse = kmalloc(sizeof(*cisparse), GFP_KERNEL); | > + if (!cisparse) goto err_kfree; | | This can be condensed into a single kmalloc. Define a struct that | contains these variables and kmalloc the whole struct in one call. OK, how's this one? and thanks. Reduce large stack usage in ide_config() by using kmalloc(), down from 0x4a4 bytes to 0x64 bytes (x86-32). Little whitespace cleanup. Move function comment block to immediately above the function. Module loaded and unloaded, otherwise not tested (no hardware). Signed-off-by: Randy Dunlap <rddunlap@osdl.org> diffstat:= drivers/ide/legacy/ide-cs.c | 130 +++++++++++++++++++++++++------------------- 1 files changed, 74 insertions(+), 56 deletions(-) diff -Naurp ./drivers/ide/legacy/ide-cs.c~idecs_stack ./drivers/ide/legacy/ide-cs.c --- ./drivers/ide/legacy/ide-cs.c~idecs_stack 2004-05-09 19:32:53.000000000 -0700 +++ ./drivers/ide/legacy/ide-cs.c 2004-06-16 11:59:58.728659752 -0700 @@ -199,6 +199,16 @@ static void ide_detach(dev_link_t *link) } /* ide_detach */ +static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) +{ + hw_regs_t hw; + memset(&hw, 0, sizeof(hw)); + ide_init_hwif_ports(&hw, io, ctl, NULL); + hw.irq = irq; + hw.chipset = ide_pci; + return ide_register_hw(&hw, NULL); +} + /*====================================================================== ide_config() is scheduled to run after a CARD_INSERTION event @@ -210,84 +220,84 @@ static void ide_detach(dev_link_t *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) -{ - hw_regs_t hw; - memset(&hw, 0, sizeof(hw)); - ide_init_hwif_ports(&hw, io, ctl, NULL); - hw.irq = irq; - hw.chipset = ide_pci; - return ide_register_hw(&hw, NULL); -} +struct stk { + u_short buf[128]; + cisparse_t parse; + config_info_t conf; + cistpl_cftable_entry_t dflt; +}; void ide_config(dev_link_t *link) { client_handle_t handle = link->handle; ide_info_t *info = link->priv; tuple_t tuple; - u_short buf[128]; - cisparse_t parse; - config_info_t conf; - cistpl_cftable_entry_t *cfg = &parse.cftable_entry; - cistpl_cftable_entry_t dflt = { 0 }; - int i, pass, last_ret, last_fn, hd, is_kme = 0; + struct stk *stk = 0; + cistpl_cftable_entry_t *cfg; + int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0; unsigned long io_base, ctl_base; DEBUG(0, "ide_config(0x%p)\n", link); - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + + stk = kmalloc(sizeof(*stk), GFP_KERNEL); + if (!stk) goto err_mem; + memset(stk, 0, sizeof(*stk)); + cfg = &stk->parse.cftable_entry; + + tuple.TupleData = (cisdata_t *)&stk->buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse)); + link->conf.ConfigBase = stk->parse.config.base; + link->conf.Present = stk->parse.config.rmask[0]; tuple.DesiredTuple = CISTPL_MANFID; if (!pcmcia_get_first_tuple(handle, &tuple) && !pcmcia_get_tuple_data(handle, &tuple) && - !pcmcia_parse_tuple(handle, &tuple, &parse)) - is_kme = ((parse.manfid.manf == MANFID_KME) && - ((parse.manfid.card == PRODID_KME_KXLC005_A) || - (parse.manfid.card == PRODID_KME_KXLC005_B))); + !pcmcia_parse_tuple(handle, &tuple, &stk->parse)) + is_kme = ((stk->parse.manfid.manf == MANFID_KME) && + ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || + (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); /* Configure card */ link->state |= DEV_CONFIG; /* Not sure if this is right... look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; - + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf)); + link->conf.Vcc = stk->conf.Vcc; + pass = io_base = ctl_base = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); while (1) { if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry; - if (pcmcia_parse_tuple(handle, &tuple, &parse) != 0) goto next_entry; + if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry; /* Check for matching Vcc, unless we're desperate */ if (!pass) { - if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) + if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; - } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) + } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; } } - - if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) + + if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = - cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) + cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; + else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = - dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; - - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; + + if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io; link->conf.ConfigIndex = cfg->index; link->io.BasePort1 = io->win[0].base; link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; @@ -307,23 +317,24 @@ void ide_config(dev_link_t *link) if (pcmcia_request_io(link->handle, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; - ctl_base = link->io.BasePort1+0x0e; + ctl_base = link->io.BasePort1 + 0x0e; } else goto next_entry; /* If we've got this far, we're done */ break; } - + next_entry: - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + memcpy(&stk->dflt, cfg, sizeof(stk->dflt)); if (pass) { CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) { CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - memset(&dflt, 0, sizeof(dflt)); + memset(&stk->dflt, 0, sizeof(stk->dflt)); pass++; } } - + CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); @@ -336,25 +347,27 @@ void ide_config(dev_link_t *link) outb(0x02, ctl_base); /* special setup for KXLC005 card */ - if (is_kme) outb(0x81, ctl_base+1); + if (is_kme) + outb(0x81, ctl_base+1); /* retry registration in case device is still spinning up */ for (hd = -1, i = 0; i < 10; i++) { hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ); if (hd >= 0) break; if (link->io.NumPorts1 == 0x20) { - outb(0x02, ctl_base+0x10); - hd = idecs_register(io_base+0x10, ctl_base+0x10, + outb(0x02, ctl_base + 0x10); + hd = idecs_register(io_base + 0x10, ctl_base + 0x10, link->irq.AssignedIRQ); if (hd >= 0) { - io_base += 0x10; ctl_base += 0x10; + io_base += 0x10; + ctl_base += 0x10; break; } } __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); } - + if (hd < 0) { printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx" ", irq %u failed\n", io_base, ctl_base, @@ -363,24 +376,29 @@ void ide_config(dev_link_t *link) } info->ndev = 1; - sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2)); + sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2)); info->node.major = ide_major[hd]; info->node.minor = 0; info->hd = hd; link->dev = &info->node; printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", - info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10, - link->conf.Vpp1/10, link->conf.Vpp1%10); + info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10, + link->conf.Vpp1 / 10, link->conf.Vpp1 % 10); link->state &= ~DEV_CONFIG_PENDING; + kfree(stk); return; - + +err_mem: + printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); + goto failed; + cs_failed: cs_error(link->handle, last_fn, last_ret); failed: + kfree(stk); ide_release(link); link->state &= ~DEV_CONFIG_PENDING; - } /* ide_config */ /*====================================================================== ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] [STACK] reduce >3k call path in ide 2004-06-16 19:52 ` Randy.Dunlap @ 2004-06-16 22:53 ` Randy.Dunlap 0 siblings, 0 replies; 21+ messages in thread From: Randy.Dunlap @ 2004-06-16 22:53 UTC (permalink / raw) To: lkml; +Cc: bgerst, joern, jolt, akpm, B.Zolnierkiewicz, linux-ide This version moves the stack structure "stk" inside the ide_config() function as an anonymous struct. I hope this is the last one.... :) Reduce large stack usage in ide_config() by using kmalloc(), down from 0x4a4 bytes to 0x64 bytes (x86-32). Little whitespace cleanup. Move function comment block to immediately above the function. Module loaded and unloaded, otherwise not tested (no hardware). Signed-off-by: Randy Dunlap <rddunlap@osdl.org> diffstat:= drivers/ide/legacy/ide-cs.c | 130 ++++++++++++++++++++++++-------------------- 1 files changed, 73 insertions(+), 57 deletions(-) diff -Naurp ./drivers/ide/legacy/ide-cs.c~idecs_stack ./drivers/ide/legacy/ide-cs.c --- ./drivers/ide/legacy/ide-cs.c~idecs_stack 2004-05-09 19:32:53.000000000 -0700 +++ ./drivers/ide/legacy/ide-cs.c 2004-06-16 13:31:08.285160776 -0700 @@ -199,6 +199,16 @@ static void ide_detach(dev_link_t *link) } /* ide_detach */ +static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) +{ + hw_regs_t hw; + memset(&hw, 0, sizeof(hw)); + ide_init_hwif_ports(&hw, io, ctl, NULL); + hw.irq = irq; + hw.chipset = ide_pci; + return ide_register_hw(&hw, NULL); +} + /*====================================================================== ide_config() is scheduled to run after a CARD_INSERTION event @@ -210,84 +220,82 @@ static void ide_detach(dev_link_t *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) -{ - hw_regs_t hw; - memset(&hw, 0, sizeof(hw)); - ide_init_hwif_ports(&hw, io, ctl, NULL); - hw.irq = irq; - hw.chipset = ide_pci; - return ide_register_hw(&hw, NULL); -} - void ide_config(dev_link_t *link) { client_handle_t handle = link->handle; ide_info_t *info = link->priv; tuple_t tuple; - u_short buf[128]; - cisparse_t parse; - config_info_t conf; - cistpl_cftable_entry_t *cfg = &parse.cftable_entry; - cistpl_cftable_entry_t dflt = { 0 }; - int i, pass, last_ret, last_fn, hd, is_kme = 0; + struct { + u_short buf[128]; + cisparse_t parse; + config_info_t conf; + cistpl_cftable_entry_t dflt; + } *stk = 0; + cistpl_cftable_entry_t *cfg; + int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0; unsigned long io_base, ctl_base; DEBUG(0, "ide_config(0x%p)\n", link); - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + + stk = kmalloc(sizeof(*stk), GFP_KERNEL); + if (!stk) goto err_mem; + memset(stk, 0, sizeof(*stk)); + cfg = &stk->parse.cftable_entry; + + tuple.TupleData = (cisdata_t *)&stk->buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse)); + link->conf.ConfigBase = stk->parse.config.base; + link->conf.Present = stk->parse.config.rmask[0]; tuple.DesiredTuple = CISTPL_MANFID; if (!pcmcia_get_first_tuple(handle, &tuple) && !pcmcia_get_tuple_data(handle, &tuple) && - !pcmcia_parse_tuple(handle, &tuple, &parse)) - is_kme = ((parse.manfid.manf == MANFID_KME) && - ((parse.manfid.card == PRODID_KME_KXLC005_A) || - (parse.manfid.card == PRODID_KME_KXLC005_B))); + !pcmcia_parse_tuple(handle, &tuple, &stk->parse)) + is_kme = ((stk->parse.manfid.manf == MANFID_KME) && + ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || + (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); /* Configure card */ link->state |= DEV_CONFIG; /* Not sure if this is right... look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; - + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf)); + link->conf.Vcc = stk->conf.Vcc; + pass = io_base = ctl_base = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); while (1) { if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry; - if (pcmcia_parse_tuple(handle, &tuple, &parse) != 0) goto next_entry; + if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry; /* Check for matching Vcc, unless we're desperate */ if (!pass) { - if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) + if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; - } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) + } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; } } - - if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) + + if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = - cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) + cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; + else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = - dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; - - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; + + if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io; link->conf.ConfigIndex = cfg->index; link->io.BasePort1 = io->win[0].base; link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; @@ -307,23 +315,24 @@ void ide_config(dev_link_t *link) if (pcmcia_request_io(link->handle, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; - ctl_base = link->io.BasePort1+0x0e; + ctl_base = link->io.BasePort1 + 0x0e; } else goto next_entry; /* If we've got this far, we're done */ break; } - + next_entry: - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + memcpy(&stk->dflt, cfg, sizeof(stk->dflt)); if (pass) { CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) { CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - memset(&dflt, 0, sizeof(dflt)); + memset(&stk->dflt, 0, sizeof(stk->dflt)); pass++; } } - + CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); @@ -336,25 +345,27 @@ void ide_config(dev_link_t *link) outb(0x02, ctl_base); /* special setup for KXLC005 card */ - if (is_kme) outb(0x81, ctl_base+1); + if (is_kme) + outb(0x81, ctl_base+1); /* retry registration in case device is still spinning up */ for (hd = -1, i = 0; i < 10; i++) { hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ); if (hd >= 0) break; if (link->io.NumPorts1 == 0x20) { - outb(0x02, ctl_base+0x10); - hd = idecs_register(io_base+0x10, ctl_base+0x10, + outb(0x02, ctl_base + 0x10); + hd = idecs_register(io_base + 0x10, ctl_base + 0x10, link->irq.AssignedIRQ); if (hd >= 0) { - io_base += 0x10; ctl_base += 0x10; + io_base += 0x10; + ctl_base += 0x10; break; } } __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); } - + if (hd < 0) { printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx" ", irq %u failed\n", io_base, ctl_base, @@ -363,24 +374,29 @@ void ide_config(dev_link_t *link) } info->ndev = 1; - sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2)); + sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2)); info->node.major = ide_major[hd]; info->node.minor = 0; info->hd = hd; link->dev = &info->node; printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", - info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10, - link->conf.Vpp1/10, link->conf.Vpp1%10); + info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10, + link->conf.Vpp1 / 10, link->conf.Vpp1 % 10); link->state &= ~DEV_CONFIG_PENDING; + kfree(stk); return; - + +err_mem: + printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); + goto failed; + cs_failed: cs_error(link->handle, last_fn, last_ret); failed: + kfree(stk); ide_release(link); link->state &= ~DEV_CONFIG_PENDING; - } /* ide_config */ /*====================================================================== ^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2004-10-15 1:58 UTC | newest] Thread overview: 21+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2004-06-09 12:29 [STACK] >3k call path in ide Jörn Engel 2004-06-09 15:23 ` Michael Clark 2004-06-09 16:29 ` Jörn Engel 2004-06-09 19:27 ` Andrew Morton 2004-06-10 22:59 ` Jörn Engel 2004-06-10 23:10 ` Andrew Morton 2004-06-11 10:53 ` Jörn Engel 2004-10-15 1:58 ` Rusty Russell 2004-06-15 23:34 ` [PATCH] " Randy.Dunlap 2004-06-16 7:11 ` Florian Schirmer 2004-06-16 9:47 ` Jörn Engel 2004-06-16 9:55 ` Florian Schirmer 2004-06-16 10:00 ` Jörn Engel 2004-06-16 17:37 ` [PATCH] [STACK] reduce " Randy.Dunlap 2004-06-16 17:57 ` Jörn Engel 2004-06-16 18:16 ` Randy.Dunlap 2004-06-16 18:29 ` Jörn Engel 2004-06-16 18:49 ` Randy.Dunlap 2004-06-16 18:58 ` Brian Gerst 2004-06-16 19:52 ` Randy.Dunlap 2004-06-16 22:53 ` Randy.Dunlap
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox