[PATCH] smc91c92_cs: Reduce stack usage in smc91c92_event()
This patch reduces the stack usage of the function smc91c92_event() in smc91c92_cs driver from 3540 to 132. Currently this is the highest stack user in linux-2.6.12-rc2-mm3. I used a patched version of gcc 3.4.3 on i386 with -fno-unit-at-a-time disabled. The patch has only been compile tested. Acked-by: Jrn Engel <joern@wohnheim.fh-wedel.de> Acked-by: Randy Dunlap <rddunlap@osdl.org> Signed-off-by: Yum Rayan <yum.rayan@gmail.com> Cc: Jeff Garzik <jgarzik@pobox.com> Signed-off-by: Andrew Morton <akpm@osdl.org>
This commit is contained in:
parent
54d06c3184
commit
4638aef40b
|
@ -127,6 +127,12 @@ struct smc_private {
|
|||
int rx_ovrn;
|
||||
};
|
||||
|
||||
struct smc_cfg_mem {
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
u_char buf[255];
|
||||
};
|
||||
|
||||
/* Special definitions for Megahertz multifunction cards */
|
||||
#define MEGAHERTZ_ISR 0x0380
|
||||
|
||||
|
@ -498,14 +504,24 @@ static int mhz_mfc_config(dev_link_t *link)
|
|||
{
|
||||
struct net_device *dev = link->priv;
|
||||
struct smc_private *smc = netdev_priv(dev);
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
u_char buf[255];
|
||||
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
|
||||
struct smc_cfg_mem *cfg_mem;
|
||||
tuple_t *tuple;
|
||||
cisparse_t *parse;
|
||||
cistpl_cftable_entry_t *cf;
|
||||
u_char *buf;
|
||||
win_req_t req;
|
||||
memreq_t mem;
|
||||
int i, k;
|
||||
|
||||
cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
|
||||
if (!cfg_mem)
|
||||
return CS_OUT_OF_RESOURCE;
|
||||
|
||||
tuple = &cfg_mem->tuple;
|
||||
parse = &cfg_mem->parse;
|
||||
cf = &parse->cftable_entry;
|
||||
buf = cfg_mem->buf;
|
||||
|
||||
link->conf.Attributes |= CONF_ENABLE_SPKR;
|
||||
link->conf.Status = CCSR_AUDIO_ENA;
|
||||
link->irq.Attributes =
|
||||
|
@ -514,12 +530,12 @@ static int mhz_mfc_config(dev_link_t *link)
|
|||
link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
|
||||
link->io.NumPorts2 = 8;
|
||||
|
||||
tuple.Attributes = tuple.TupleOffset = 0;
|
||||
tuple.TupleData = (cisdata_t *)buf;
|
||||
tuple.TupleDataMax = sizeof(buf);
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
tuple->Attributes = tuple->TupleOffset = 0;
|
||||
tuple->TupleData = (cisdata_t *)buf;
|
||||
tuple->TupleDataMax = 255;
|
||||
tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
|
||||
i = first_tuple(link->handle, &tuple, &parse);
|
||||
i = first_tuple(link->handle, tuple, parse);
|
||||
/* The Megahertz combo cards have modem-like CIS entries, so
|
||||
we have to explicitly try a bunch of port combinations. */
|
||||
while (i == CS_SUCCESS) {
|
||||
|
@ -532,10 +548,10 @@ static int mhz_mfc_config(dev_link_t *link)
|
|||
if (i == CS_SUCCESS) break;
|
||||
}
|
||||
if (i == CS_SUCCESS) break;
|
||||
i = next_tuple(link->handle, &tuple, &parse);
|
||||
i = next_tuple(link->handle, tuple, parse);
|
||||
}
|
||||
if (i != CS_SUCCESS)
|
||||
return i;
|
||||
goto free_cfg_mem;
|
||||
dev->base_addr = link->io.BasePort1;
|
||||
|
||||
/* Allocate a memory window, for accessing the ISR */
|
||||
|
@ -544,7 +560,7 @@ static int mhz_mfc_config(dev_link_t *link)
|
|||
req.AccessSpeed = 0;
|
||||
i = pcmcia_request_window(&link->handle, &req, &link->win);
|
||||
if (i != CS_SUCCESS)
|
||||
return i;
|
||||
goto free_cfg_mem;
|
||||
smc->base = ioremap(req.Base, req.Size);
|
||||
mem.CardOffset = mem.Page = 0;
|
||||
if (smc->manfid == MANFID_MOTOROLA)
|
||||
|
@ -556,6 +572,8 @@ static int mhz_mfc_config(dev_link_t *link)
|
|||
&& (smc->cardid == PRODID_MEGAHERTZ_EM3288))
|
||||
mhz_3288_power(link);
|
||||
|
||||
free_cfg_mem:
|
||||
kfree(cfg_mem);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -563,39 +581,61 @@ static int mhz_setup(dev_link_t *link)
|
|||
{
|
||||
client_handle_t handle = link->handle;
|
||||
struct net_device *dev = link->priv;
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
u_char buf[255], *station_addr;
|
||||
struct smc_cfg_mem *cfg_mem;
|
||||
tuple_t *tuple;
|
||||
cisparse_t *parse;
|
||||
u_char *buf, *station_addr;
|
||||
int rc;
|
||||
|
||||
tuple.Attributes = tuple.TupleOffset = 0;
|
||||
tuple.TupleData = buf;
|
||||
tuple.TupleDataMax = sizeof(buf);
|
||||
cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
|
||||
if (!cfg_mem)
|
||||
return -1;
|
||||
|
||||
tuple = &cfg_mem->tuple;
|
||||
parse = &cfg_mem->parse;
|
||||
buf = cfg_mem->buf;
|
||||
|
||||
tuple->Attributes = tuple->TupleOffset = 0;
|
||||
tuple->TupleData = (cisdata_t *)buf;
|
||||
tuple->TupleDataMax = 255;
|
||||
|
||||
/* Read the station address from the CIS. It is stored as the last
|
||||
(fourth) string in the Version 1 Version/ID tuple. */
|
||||
tuple.DesiredTuple = CISTPL_VERS_1;
|
||||
if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS)
|
||||
return -1;
|
||||
tuple->DesiredTuple = CISTPL_VERS_1;
|
||||
if (first_tuple(handle, tuple, parse) != CS_SUCCESS) {
|
||||
rc = -1;
|
||||
goto free_cfg_mem;
|
||||
}
|
||||
/* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
|
||||
if (next_tuple(handle, &tuple, &parse) != CS_SUCCESS)
|
||||
first_tuple(handle, &tuple, &parse);
|
||||
if (parse.version_1.ns > 3) {
|
||||
station_addr = parse.version_1.str + parse.version_1.ofs[3];
|
||||
if (cvt_ascii_address(dev, station_addr) == 0)
|
||||
return 0;
|
||||
if (next_tuple(handle, tuple, parse) != CS_SUCCESS)
|
||||
first_tuple(handle, tuple, parse);
|
||||
if (parse->version_1.ns > 3) {
|
||||
station_addr = parse->version_1.str + parse->version_1.ofs[3];
|
||||
if (cvt_ascii_address(dev, station_addr) == 0) {
|
||||
rc = 0;
|
||||
goto free_cfg_mem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Another possibility: for the EM3288, in a special tuple */
|
||||
tuple.DesiredTuple = 0x81;
|
||||
if (pcmcia_get_first_tuple(handle, &tuple) != CS_SUCCESS)
|
||||
return -1;
|
||||
if (pcmcia_get_tuple_data(handle, &tuple) != CS_SUCCESS)
|
||||
return -1;
|
||||
tuple->DesiredTuple = 0x81;
|
||||
if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) {
|
||||
rc = -1;
|
||||
goto free_cfg_mem;
|
||||
}
|
||||
if (pcmcia_get_tuple_data(handle, tuple) != CS_SUCCESS) {
|
||||
rc = -1;
|
||||
goto free_cfg_mem;
|
||||
}
|
||||
buf[12] = '\0';
|
||||
if (cvt_ascii_address(dev, buf) == 0)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
if (cvt_ascii_address(dev, buf) == 0) {
|
||||
rc = 0;
|
||||
goto free_cfg_mem;
|
||||
}
|
||||
rc = -1;
|
||||
free_cfg_mem:
|
||||
kfree(cfg_mem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*======================================================================
|
||||
|
@ -665,19 +705,29 @@ static int mot_setup(dev_link_t *link)
|
|||
static int smc_config(dev_link_t *link)
|
||||
{
|
||||
struct net_device *dev = link->priv;
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
u_char buf[255];
|
||||
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
|
||||
struct smc_cfg_mem *cfg_mem;
|
||||
tuple_t *tuple;
|
||||
cisparse_t *parse;
|
||||
cistpl_cftable_entry_t *cf;
|
||||
u_char *buf;
|
||||
int i;
|
||||
|
||||
tuple.Attributes = tuple.TupleOffset = 0;
|
||||
tuple.TupleData = (cisdata_t *)buf;
|
||||
tuple.TupleDataMax = sizeof(buf);
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
|
||||
if (!cfg_mem)
|
||||
return CS_OUT_OF_RESOURCE;
|
||||
|
||||
tuple = &cfg_mem->tuple;
|
||||
parse = &cfg_mem->parse;
|
||||
cf = &parse->cftable_entry;
|
||||
buf = cfg_mem->buf;
|
||||
|
||||
tuple->Attributes = tuple->TupleOffset = 0;
|
||||
tuple->TupleData = (cisdata_t *)buf;
|
||||
tuple->TupleDataMax = 255;
|
||||
tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
|
||||
link->io.NumPorts1 = 16;
|
||||
i = first_tuple(link->handle, &tuple, &parse);
|
||||
i = first_tuple(link->handle, tuple, parse);
|
||||
while (i != CS_NO_MORE_ITEMS) {
|
||||
if (i == CS_SUCCESS) {
|
||||
link->conf.ConfigIndex = cf->index;
|
||||
|
@ -686,10 +736,12 @@ static int smc_config(dev_link_t *link)
|
|||
i = pcmcia_request_io(link->handle, &link->io);
|
||||
if (i == CS_SUCCESS) break;
|
||||
}
|
||||
i = next_tuple(link->handle, &tuple, &parse);
|
||||
i = next_tuple(link->handle, tuple, parse);
|
||||
}
|
||||
if (i == CS_SUCCESS)
|
||||
dev->base_addr = link->io.BasePort1;
|
||||
|
||||
kfree(cfg_mem);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -697,41 +749,58 @@ static int smc_setup(dev_link_t *link)
|
|||
{
|
||||
client_handle_t handle = link->handle;
|
||||
struct net_device *dev = link->priv;
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
struct smc_cfg_mem *cfg_mem;
|
||||
tuple_t *tuple;
|
||||
cisparse_t *parse;
|
||||
cistpl_lan_node_id_t *node_id;
|
||||
u_char buf[255], *station_addr;
|
||||
int i;
|
||||
u_char *buf, *station_addr;
|
||||
int i, rc;
|
||||
|
||||
tuple.Attributes = tuple.TupleOffset = 0;
|
||||
tuple.TupleData = buf;
|
||||
tuple.TupleDataMax = sizeof(buf);
|
||||
cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
|
||||
if (!cfg_mem)
|
||||
return CS_OUT_OF_RESOURCE;
|
||||
|
||||
tuple = &cfg_mem->tuple;
|
||||
parse = &cfg_mem->parse;
|
||||
buf = cfg_mem->buf;
|
||||
|
||||
tuple->Attributes = tuple->TupleOffset = 0;
|
||||
tuple->TupleData = (cisdata_t *)buf;
|
||||
tuple->TupleDataMax = 255;
|
||||
|
||||
/* Check for a LAN function extension tuple */
|
||||
tuple.DesiredTuple = CISTPL_FUNCE;
|
||||
i = first_tuple(handle, &tuple, &parse);
|
||||
tuple->DesiredTuple = CISTPL_FUNCE;
|
||||
i = first_tuple(handle, tuple, parse);
|
||||
while (i == CS_SUCCESS) {
|
||||
if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID)
|
||||
if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID)
|
||||
break;
|
||||
i = next_tuple(handle, &tuple, &parse);
|
||||
i = next_tuple(handle, tuple, parse);
|
||||
}
|
||||
if (i == CS_SUCCESS) {
|
||||
node_id = (cistpl_lan_node_id_t *)parse.funce.data;
|
||||
node_id = (cistpl_lan_node_id_t *)parse->funce.data;
|
||||
if (node_id->nb == 6) {
|
||||
for (i = 0; i < 6; i++)
|
||||
dev->dev_addr[i] = node_id->id[i];
|
||||
return 0;
|
||||
rc = 0;
|
||||
goto free_cfg_mem;
|
||||
}
|
||||
}
|
||||
/* Try the third string in the Version 1 Version/ID tuple. */
|
||||
tuple.DesiredTuple = CISTPL_VERS_1;
|
||||
if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS)
|
||||
return -1;
|
||||
station_addr = parse.version_1.str + parse.version_1.ofs[2];
|
||||
if (cvt_ascii_address(dev, station_addr) == 0)
|
||||
return 0;
|
||||
tuple->DesiredTuple = CISTPL_VERS_1;
|
||||
if (first_tuple(handle, tuple, parse) != CS_SUCCESS) {
|
||||
rc = -1;
|
||||
goto free_cfg_mem;
|
||||
}
|
||||
station_addr = parse->version_1.str + parse->version_1.ofs[2];
|
||||
if (cvt_ascii_address(dev, station_addr) == 0) {
|
||||
rc = 0;
|
||||
goto free_cfg_mem;
|
||||
}
|
||||
|
||||
return -1;
|
||||
rc = -1;
|
||||
free_cfg_mem:
|
||||
kfree(cfg_mem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*====================================================================*/
|
||||
|
@ -773,26 +842,36 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
|
|||
{
|
||||
client_handle_t handle = link->handle;
|
||||
struct net_device *dev = link->priv;
|
||||
tuple_t tuple;
|
||||
u_char buf[255];
|
||||
int i;
|
||||
struct smc_cfg_mem *cfg_mem;
|
||||
tuple_t *tuple;
|
||||
u_char *buf;
|
||||
int i, rc;
|
||||
|
||||
tuple.Attributes = TUPLE_RETURN_COMMON;
|
||||
tuple.TupleData = buf;
|
||||
tuple.TupleDataMax = sizeof(buf);
|
||||
tuple.TupleOffset = 0;
|
||||
cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
|
||||
if (!cfg_mem)
|
||||
return -1;
|
||||
|
||||
tuple = &cfg_mem->tuple;
|
||||
buf = cfg_mem->buf;
|
||||
|
||||
tuple->Attributes = TUPLE_RETURN_COMMON;
|
||||
tuple->TupleData = (cisdata_t *)buf;
|
||||
tuple->TupleDataMax = 255;
|
||||
tuple->TupleOffset = 0;
|
||||
|
||||
/* Read the station address from tuple 0x90, subtuple 0x04 */
|
||||
tuple.DesiredTuple = 0x90;
|
||||
i = pcmcia_get_first_tuple(handle, &tuple);
|
||||
tuple->DesiredTuple = 0x90;
|
||||
i = pcmcia_get_first_tuple(handle, tuple);
|
||||
while (i == CS_SUCCESS) {
|
||||
i = pcmcia_get_tuple_data(handle, &tuple);
|
||||
i = pcmcia_get_tuple_data(handle, tuple);
|
||||
if ((i != CS_SUCCESS) || (buf[0] == 0x04))
|
||||
break;
|
||||
i = pcmcia_get_next_tuple(handle, &tuple);
|
||||
i = pcmcia_get_next_tuple(handle, tuple);
|
||||
}
|
||||
if (i != CS_SUCCESS) {
|
||||
rc = -1;
|
||||
goto free_cfg_mem;
|
||||
}
|
||||
if (i != CS_SUCCESS)
|
||||
return -1;
|
||||
for (i = 0; i < 6; i++)
|
||||
dev->dev_addr[i] = buf[i+2];
|
||||
|
||||
|
@ -814,8 +893,10 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
|
|||
inw(link->io.BasePort1 + OSITECH_AUI_PWR),
|
||||
inw(link->io.BasePort1 + OSITECH_RESET_ISR));
|
||||
}
|
||||
|
||||
return 0;
|
||||
rc = 0;
|
||||
free_cfg_mem:
|
||||
kfree(cfg_mem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*======================================================================
|
||||
|
@ -887,9 +968,10 @@ static void smc91c92_config(dev_link_t *link)
|
|||
client_handle_t handle = link->handle;
|
||||
struct net_device *dev = link->priv;
|
||||
struct smc_private *smc = netdev_priv(dev);
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
u_short buf[32];
|
||||
struct smc_cfg_mem *cfg_mem;
|
||||
tuple_t *tuple;
|
||||
cisparse_t *parse;
|
||||
u_char *buf;
|
||||
char *name;
|
||||
int i, j, rev;
|
||||
kio_addr_t ioaddr;
|
||||
|
@ -897,21 +979,29 @@ static void smc91c92_config(dev_link_t *link)
|
|||
|
||||
DEBUG(0, "smc91c92_config(0x%p)\n", link);
|
||||
|
||||
tuple.Attributes = tuple.TupleOffset = 0;
|
||||
tuple.TupleData = (cisdata_t *)buf;
|
||||
tuple.TupleDataMax = sizeof(buf);
|
||||
cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
|
||||
if (!cfg_mem)
|
||||
goto config_failed;
|
||||
|
||||
tuple.DesiredTuple = CISTPL_CONFIG;
|
||||
i = first_tuple(handle, &tuple, &parse);
|
||||
tuple = &cfg_mem->tuple;
|
||||
parse = &cfg_mem->parse;
|
||||
buf = cfg_mem->buf;
|
||||
|
||||
tuple->Attributes = tuple->TupleOffset = 0;
|
||||
tuple->TupleData = (cisdata_t *)buf;
|
||||
tuple->TupleDataMax = 64;
|
||||
|
||||
tuple->DesiredTuple = CISTPL_CONFIG;
|
||||
i = first_tuple(handle, tuple, parse);
|
||||
CS_EXIT_TEST(i, ParseTuple, config_failed);
|
||||
link->conf.ConfigBase = parse.config.base;
|
||||
link->conf.Present = parse.config.rmask[0];
|
||||
link->conf.ConfigBase = parse->config.base;
|
||||
link->conf.Present = parse->config.rmask[0];
|
||||
|
||||
tuple.DesiredTuple = CISTPL_MANFID;
|
||||
tuple.Attributes = TUPLE_RETURN_COMMON;
|
||||
if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
|
||||
smc->manfid = parse.manfid.manf;
|
||||
smc->cardid = parse.manfid.card;
|
||||
tuple->DesiredTuple = CISTPL_MANFID;
|
||||
tuple->Attributes = TUPLE_RETURN_COMMON;
|
||||
if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
|
||||
smc->manfid = parse->manfid.manf;
|
||||
smc->cardid = parse->manfid.card;
|
||||
}
|
||||
|
||||
/* Configure card */
|
||||
|
@ -1046,7 +1136,7 @@ static void smc91c92_config(dev_link_t *link)
|
|||
printk(KERN_NOTICE " No MII transceivers found!\n");
|
||||
}
|
||||
}
|
||||
|
||||
kfree(cfg_mem);
|
||||
return;
|
||||
|
||||
config_undo:
|
||||
|
@ -1054,6 +1144,7 @@ config_undo:
|
|||
config_failed: /* CS_EXIT_TEST() calls jump to here... */
|
||||
smc91c92_release(link);
|
||||
link->state &= ~DEV_CONFIG_PENDING;
|
||||
kfree(cfg_mem);
|
||||
|
||||
} /* smc91c92_config */
|
||||
|
||||
|
|
Loading…
Reference in New Issue