Commit 6dd32126 authored by Bartlomiej Zolnierkiewicz's avatar Bartlomiej Zolnierkiewicz Committed by Linus Torvalds

[PATCH] ide: reduce > 3kb call path in ide-cs

 - 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: default avatarRandy Dunlap <rddunlap@osdl.org>
Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@elka.pw.edu.pl>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 7709dda4
...@@ -199,6 +199,16 @@ static void ide_detach(dev_link_t *link) ...@@ -199,6 +199,16 @@ static void ide_detach(dev_link_t *link)
} /* ide_detach */ } /* 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 ide_config() is scheduled to run after a CARD_INSERTION event
...@@ -210,84 +220,82 @@ static void ide_detach(dev_link_t *link) ...@@ -210,84 +220,82 @@ static void ide_detach(dev_link_t *link)
#define CS_CHECK(fn, ret) \ #define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 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) void ide_config(dev_link_t *link)
{ {
client_handle_t handle = link->handle; client_handle_t handle = link->handle;
ide_info_t *info = link->priv; ide_info_t *info = link->priv;
tuple_t tuple; tuple_t tuple;
u_short buf[128]; struct {
cisparse_t parse; u_short buf[128];
config_info_t conf; cisparse_t parse;
cistpl_cftable_entry_t *cfg = &parse.cftable_entry; config_info_t conf;
cistpl_cftable_entry_t dflt = { 0 }; cistpl_cftable_entry_t dflt;
int i, pass, last_ret, last_fn, hd, is_kme = 0; } *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; unsigned long io_base, ctl_base;
DEBUG(0, "ide_config(0x%p)\n", link); DEBUG(0, "ide_config(0x%p)\n", link);
tuple.TupleData = (cisdata_t *)buf; stk = kmalloc(sizeof(*stk), GFP_KERNEL);
tuple.TupleOffset = 0; tuple.TupleDataMax = 255; 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.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG; tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse));
link->conf.ConfigBase = parse.config.base; link->conf.ConfigBase = stk->parse.config.base;
link->conf.Present = parse.config.rmask[0]; link->conf.Present = stk->parse.config.rmask[0];
tuple.DesiredTuple = CISTPL_MANFID; tuple.DesiredTuple = CISTPL_MANFID;
if (!pcmcia_get_first_tuple(handle, &tuple) && if (!pcmcia_get_first_tuple(handle, &tuple) &&
!pcmcia_get_tuple_data(handle, &tuple) && !pcmcia_get_tuple_data(handle, &tuple) &&
!pcmcia_parse_tuple(handle, &tuple, &parse)) !pcmcia_parse_tuple(handle, &tuple, &stk->parse))
is_kme = ((parse.manfid.manf == MANFID_KME) && is_kme = ((stk->parse.manfid.manf == MANFID_KME) &&
((parse.manfid.card == PRODID_KME_KXLC005_A) || ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) ||
(parse.manfid.card == PRODID_KME_KXLC005_B))); (stk->parse.manfid.card == PRODID_KME_KXLC005_B)));
/* Configure card */ /* Configure card */
link->state |= DEV_CONFIG; link->state |= DEV_CONFIG;
/* Not sure if this is right... look up the current Vcc */ /* Not sure if this is right... look up the current Vcc */
CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf));
link->conf.Vcc = conf.Vcc; link->conf.Vcc = stk->conf.Vcc;
pass = io_base = ctl_base = 0; pass = io_base = ctl_base = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0; tuple.Attributes = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
while (1) { while (1) {
if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry; 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 */ /* Check for matching Vcc, unless we're desperate */
if (!pass) { if (!pass) {
if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
goto next_entry; goto next_entry;
} else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
goto next_entry; 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 = link->conf.Vpp1 = link->conf.Vpp2 =
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
link->conf.Vpp1 = link->conf.Vpp2 = link->conf.Vpp1 = link->conf.Vpp2 =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
link->conf.ConfigIndex = cfg->index; link->conf.ConfigIndex = cfg->index;
link->io.BasePort1 = io->win[0].base; link->io.BasePort1 = io->win[0].base;
link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
...@@ -307,23 +315,24 @@ void ide_config(dev_link_t *link) ...@@ -307,23 +315,24 @@ void ide_config(dev_link_t *link)
if (pcmcia_request_io(link->handle, &link->io) != 0) if (pcmcia_request_io(link->handle, &link->io) != 0)
goto next_entry; goto next_entry;
io_base = link->io.BasePort1; io_base = link->io.BasePort1;
ctl_base = link->io.BasePort1+0x0e; ctl_base = link->io.BasePort1 + 0x0e;
} else goto next_entry; } else goto next_entry;
/* If we've got this far, we're done */ /* If we've got this far, we're done */
break; break;
} }
next_entry: 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) { if (pass) {
CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
} else if (pcmcia_get_next_tuple(handle, &tuple) != 0) { } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) {
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
memset(&dflt, 0, sizeof(dflt)); memset(&stk->dflt, 0, sizeof(stk->dflt));
pass++; pass++;
} }
} }
CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
...@@ -336,25 +345,27 @@ void ide_config(dev_link_t *link) ...@@ -336,25 +345,27 @@ void ide_config(dev_link_t *link)
outb(0x02, ctl_base); outb(0x02, ctl_base);
/* special setup for KXLC005 card */ /* 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 */ /* retry registration in case device is still spinning up */
for (hd = -1, i = 0; i < 10; i++) { for (hd = -1, i = 0; i < 10; i++) {
hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ); hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ);
if (hd >= 0) break; if (hd >= 0) break;
if (link->io.NumPorts1 == 0x20) { if (link->io.NumPorts1 == 0x20) {
outb(0x02, ctl_base+0x10); outb(0x02, ctl_base + 0x10);
hd = idecs_register(io_base+0x10, ctl_base+0x10, hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
link->irq.AssignedIRQ); link->irq.AssignedIRQ);
if (hd >= 0) { if (hd >= 0) {
io_base += 0x10; ctl_base += 0x10; io_base += 0x10;
ctl_base += 0x10;
break; break;
} }
} }
__set_current_state(TASK_UNINTERRUPTIBLE); __set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/10); schedule_timeout(HZ/10);
} }
if (hd < 0) { if (hd < 0) {
printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx" printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx"
", irq %u failed\n", io_base, ctl_base, ", irq %u failed\n", io_base, ctl_base,
...@@ -363,24 +374,29 @@ void ide_config(dev_link_t *link) ...@@ -363,24 +374,29 @@ void ide_config(dev_link_t *link)
} }
info->ndev = 1; 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.major = ide_major[hd];
info->node.minor = 0; info->node.minor = 0;
info->hd = hd; info->hd = hd;
link->dev = &info->node; link->dev = &info->node;
printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", 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, info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10,
link->conf.Vpp1/10, link->conf.Vpp1%10); link->conf.Vpp1 / 10, link->conf.Vpp1 % 10);
link->state &= ~DEV_CONFIG_PENDING; link->state &= ~DEV_CONFIG_PENDING;
kfree(stk);
return; return;
err_mem:
printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
goto failed;
cs_failed: cs_failed:
cs_error(link->handle, last_fn, last_ret); cs_error(link->handle, last_fn, last_ret);
failed: failed:
kfree(stk);
ide_release(link); ide_release(link);
link->state &= ~DEV_CONFIG_PENDING; link->state &= ~DEV_CONFIG_PENDING;
} /* ide_config */ } /* ide_config */
/*====================================================================== /*======================================================================
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment