mirror of
https://github.com/torvalds/linux.git
synced 2024-11-17 09:31:50 +00:00
Merge branch 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6
* 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6: pcmcia pcnet_cs: try setting io_lines to 16 if card setup fails pcmcia: per-device, not per-socket debug messages pcmcia serial_cs.c: fix multifunction card handling
This commit is contained in:
commit
bd12e5c3a1
@ -508,7 +508,8 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev,
|
||||
unsigned int vcc,
|
||||
void *priv_data)
|
||||
{
|
||||
int *has_shmem = priv_data;
|
||||
int *priv = priv_data;
|
||||
int try = (*priv & 0x1);
|
||||
int i;
|
||||
cistpl_io_t *io = &cfg->io;
|
||||
|
||||
@ -525,33 +526,39 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev,
|
||||
i = p_dev->resource[1]->end = 0;
|
||||
}
|
||||
|
||||
*has_shmem = ((cfg->mem.nwin == 1) &&
|
||||
(cfg->mem.win[0].len >= 0x4000));
|
||||
*priv &= ((cfg->mem.nwin == 1) &&
|
||||
(cfg->mem.win[0].len >= 0x4000)) ? 0x10 : ~0x10;
|
||||
|
||||
p_dev->resource[0]->start = io->win[i].base;
|
||||
p_dev->resource[0]->end = io->win[i].len;
|
||||
if (!try)
|
||||
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
|
||||
else
|
||||
p_dev->io_lines = 16;
|
||||
if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
|
||||
return try_io_port(p_dev);
|
||||
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int pcnet_config(struct pcmcia_device *link)
|
||||
static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
|
||||
int *has_shmem, int try)
|
||||
{
|
||||
struct net_device *dev = link->priv;
|
||||
pcnet_dev_t *info = PRIV(dev);
|
||||
int ret, start_pg, stop_pg, cm_offset;
|
||||
int has_shmem = 0;
|
||||
hw_info_t *local_hw_info;
|
||||
pcnet_dev_t *info = PRIV(dev);
|
||||
int priv = try;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&link->dev, "pcnet_config\n");
|
||||
|
||||
ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem);
|
||||
if (ret)
|
||||
goto failed;
|
||||
ret = pcmcia_loop_config(link, pcnet_confcheck, &priv);
|
||||
if (ret) {
|
||||
dev_warn(&link->dev, "no useable port range found\n");
|
||||
return NULL;
|
||||
}
|
||||
*has_shmem = (priv & 0x10);
|
||||
|
||||
if (!link->irq)
|
||||
goto failed;
|
||||
return NULL;
|
||||
|
||||
if (resource_size(link->resource[1]) == 8) {
|
||||
link->conf.Attributes |= CONF_ENABLE_SPKR;
|
||||
@ -563,40 +570,60 @@ static int pcnet_config(struct pcmcia_device *link)
|
||||
|
||||
ret = pcmcia_request_configuration(link, &link->conf);
|
||||
if (ret)
|
||||
goto failed;
|
||||
return NULL;
|
||||
|
||||
dev->irq = link->irq;
|
||||
dev->base_addr = link->resource[0]->start;
|
||||
|
||||
if (info->flags & HAS_MISC_REG) {
|
||||
if ((if_port == 1) || (if_port == 2))
|
||||
dev->if_port = if_port;
|
||||
else
|
||||
printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n");
|
||||
} else {
|
||||
dev_notice(&link->dev, "invalid if_port requested\n");
|
||||
} else
|
||||
dev->if_port = 0;
|
||||
}
|
||||
|
||||
if ((link->conf.ConfigBase == 0x03c0) &&
|
||||
(link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
|
||||
printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n");
|
||||
printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n");
|
||||
goto failed;
|
||||
dev_info(&link->dev,
|
||||
"this is an AX88190 card - use axnet_cs instead.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
local_hw_info = get_hwinfo(link);
|
||||
if (local_hw_info == NULL)
|
||||
if (!local_hw_info)
|
||||
local_hw_info = get_prom(link);
|
||||
if (local_hw_info == NULL)
|
||||
if (!local_hw_info)
|
||||
local_hw_info = get_dl10019(link);
|
||||
if (local_hw_info == NULL)
|
||||
if (!local_hw_info)
|
||||
local_hw_info = get_ax88190(link);
|
||||
if (local_hw_info == NULL)
|
||||
if (!local_hw_info)
|
||||
local_hw_info = get_hwired(link);
|
||||
|
||||
return local_hw_info;
|
||||
}
|
||||
|
||||
static int pcnet_config(struct pcmcia_device *link)
|
||||
{
|
||||
struct net_device *dev = link->priv;
|
||||
pcnet_dev_t *info = PRIV(dev);
|
||||
int start_pg, stop_pg, cm_offset;
|
||||
int has_shmem = 0;
|
||||
hw_info_t *local_hw_info;
|
||||
|
||||
dev_dbg(&link->dev, "pcnet_config\n");
|
||||
|
||||
local_hw_info = pcnet_try_config(link, &has_shmem, 0);
|
||||
if (!local_hw_info) {
|
||||
/* check whether forcing io_lines to 16 helps... */
|
||||
pcmcia_disable_device(link);
|
||||
local_hw_info = pcnet_try_config(link, &has_shmem, 1);
|
||||
if (local_hw_info == NULL) {
|
||||
printk(KERN_NOTICE "pcnet_cs: unable to read hardware net"
|
||||
dev_notice(&link->dev, "unable to read hardware net"
|
||||
" address for io base %#3lx\n", dev->base_addr);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
info->flags = local_hw_info->flags;
|
||||
/* Check for user overrides */
|
||||
|
@ -163,7 +163,7 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev,
|
||||
c = p_dev->function_config;
|
||||
|
||||
if (!(c->state & CONFIG_LOCKED)) {
|
||||
dev_dbg(&s->dev, "Configuration isnt't locked\n");
|
||||
dev_dbg(&p_dev->dev, "Configuration isnt't locked\n");
|
||||
mutex_unlock(&s->ops_mutex);
|
||||
return -EACCES;
|
||||
}
|
||||
@ -220,7 +220,7 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
|
||||
s->win[w].card_start = offset;
|
||||
ret = s->ops->set_mem_map(s, &s->win[w]);
|
||||
if (ret)
|
||||
dev_warn(&s->dev, "failed to set_mem_map\n");
|
||||
dev_warn(&p_dev->dev, "failed to set_mem_map\n");
|
||||
mutex_unlock(&s->ops_mutex);
|
||||
return ret;
|
||||
} /* pcmcia_map_mem_page */
|
||||
@ -244,18 +244,18 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
|
||||
c = p_dev->function_config;
|
||||
|
||||
if (!(s->state & SOCKET_PRESENT)) {
|
||||
dev_dbg(&s->dev, "No card present\n");
|
||||
dev_dbg(&p_dev->dev, "No card present\n");
|
||||
ret = -ENODEV;
|
||||
goto unlock;
|
||||
}
|
||||
if (!(c->state & CONFIG_LOCKED)) {
|
||||
dev_dbg(&s->dev, "Configuration isnt't locked\n");
|
||||
dev_dbg(&p_dev->dev, "Configuration isnt't locked\n");
|
||||
ret = -EACCES;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) {
|
||||
dev_dbg(&s->dev,
|
||||
dev_dbg(&p_dev->dev,
|
||||
"changing Vcc or IRQ is not allowed at this time\n");
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
@ -265,20 +265,22 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
|
||||
if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
|
||||
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
|
||||
if (mod->Vpp1 != mod->Vpp2) {
|
||||
dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n");
|
||||
dev_dbg(&p_dev->dev,
|
||||
"Vpp1 and Vpp2 must be the same\n");
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
s->socket.Vpp = mod->Vpp1;
|
||||
if (s->ops->set_socket(s, &s->socket)) {
|
||||
dev_printk(KERN_WARNING, &s->dev,
|
||||
dev_printk(KERN_WARNING, &p_dev->dev,
|
||||
"Unable to set VPP\n");
|
||||
ret = -EIO;
|
||||
goto unlock;
|
||||
}
|
||||
} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
|
||||
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
|
||||
dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n");
|
||||
dev_dbg(&p_dev->dev,
|
||||
"changing Vcc is not allowed at this time\n");
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
@ -401,7 +403,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
|
||||
win = &s->win[w];
|
||||
|
||||
if (!(p_dev->_win & CLIENT_WIN_REQ(w))) {
|
||||
dev_dbg(&s->dev, "not releasing unknown window\n");
|
||||
dev_dbg(&p_dev->dev, "not releasing unknown window\n");
|
||||
mutex_unlock(&s->ops_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -439,7 +441,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
|
||||
return -ENODEV;
|
||||
|
||||
if (req->IntType & INT_CARDBUS) {
|
||||
dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n");
|
||||
dev_dbg(&p_dev->dev, "IntType may not be INT_CARDBUS\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -447,7 +449,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
|
||||
c = p_dev->function_config;
|
||||
if (c->state & CONFIG_LOCKED) {
|
||||
mutex_unlock(&s->ops_mutex);
|
||||
dev_dbg(&s->dev, "Configuration is locked\n");
|
||||
dev_dbg(&p_dev->dev, "Configuration is locked\n");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
@ -455,7 +457,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
|
||||
s->socket.Vpp = req->Vpp;
|
||||
if (s->ops->set_socket(s, &s->socket)) {
|
||||
mutex_unlock(&s->ops_mutex);
|
||||
dev_printk(KERN_WARNING, &s->dev,
|
||||
dev_printk(KERN_WARNING, &p_dev->dev,
|
||||
"Unable to set socket state\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -569,19 +571,20 @@ int pcmcia_request_io(struct pcmcia_device *p_dev)
|
||||
int ret = -EINVAL;
|
||||
|
||||
mutex_lock(&s->ops_mutex);
|
||||
dev_dbg(&s->dev, "pcmcia_request_io: %pR , %pR", &c->io[0], &c->io[1]);
|
||||
dev_dbg(&p_dev->dev, "pcmcia_request_io: %pR , %pR",
|
||||
&c->io[0], &c->io[1]);
|
||||
|
||||
if (!(s->state & SOCKET_PRESENT)) {
|
||||
dev_dbg(&s->dev, "pcmcia_request_io: No card present\n");
|
||||
dev_dbg(&p_dev->dev, "pcmcia_request_io: No card present\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->state & CONFIG_LOCKED) {
|
||||
dev_dbg(&s->dev, "Configuration is locked\n");
|
||||
dev_dbg(&p_dev->dev, "Configuration is locked\n");
|
||||
goto out;
|
||||
}
|
||||
if (c->state & CONFIG_IO_REQ) {
|
||||
dev_dbg(&s->dev, "IO already configured\n");
|
||||
dev_dbg(&p_dev->dev, "IO already configured\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -601,7 +604,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev)
|
||||
c->state |= CONFIG_IO_REQ;
|
||||
p_dev->_io = 1;
|
||||
|
||||
dev_dbg(&s->dev, "pcmcia_request_io succeeded: %pR , %pR",
|
||||
dev_dbg(&p_dev->dev, "pcmcia_request_io succeeded: %pR , %pR",
|
||||
&c->io[0], &c->io[1]);
|
||||
out:
|
||||
mutex_unlock(&s->ops_mutex);
|
||||
@ -800,7 +803,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
||||
int w;
|
||||
|
||||
if (!(s->state & SOCKET_PRESENT)) {
|
||||
dev_dbg(&s->dev, "No card present\n");
|
||||
dev_dbg(&p_dev->dev, "No card present\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -809,12 +812,12 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
||||
req->Size = s->map_size;
|
||||
align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size;
|
||||
if (req->Size & (s->map_size-1)) {
|
||||
dev_dbg(&s->dev, "invalid map size\n");
|
||||
dev_dbg(&p_dev->dev, "invalid map size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
|
||||
(req->Base & (align-1))) {
|
||||
dev_dbg(&s->dev, "invalid base address\n");
|
||||
dev_dbg(&p_dev->dev, "invalid base address\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (req->Base)
|
||||
@ -826,7 +829,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
||||
if (!(s->state & SOCKET_WIN_REQ(w)))
|
||||
break;
|
||||
if (w == MAX_WIN) {
|
||||
dev_dbg(&s->dev, "all windows are used already\n");
|
||||
dev_dbg(&p_dev->dev, "all windows are used already\n");
|
||||
mutex_unlock(&s->ops_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -837,7 +840,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
||||
win->res = pcmcia_find_mem_region(req->Base, req->Size, align,
|
||||
0, s);
|
||||
if (!win->res) {
|
||||
dev_dbg(&s->dev, "allocating mem region failed\n");
|
||||
dev_dbg(&p_dev->dev, "allocating mem region failed\n");
|
||||
mutex_unlock(&s->ops_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -851,7 +854,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
||||
win->card_start = 0;
|
||||
|
||||
if (s->ops->set_mem_map(s, win) != 0) {
|
||||
dev_dbg(&s->dev, "failed to set memory mapping\n");
|
||||
dev_dbg(&p_dev->dev, "failed to set memory mapping\n");
|
||||
mutex_unlock(&s->ops_mutex);
|
||||
return -EIO;
|
||||
}
|
||||
@ -874,7 +877,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
||||
if (win->res)
|
||||
request_resource(&iomem_resource, res);
|
||||
|
||||
dev_dbg(&s->dev, "request_window results in %pR\n", res);
|
||||
dev_dbg(&p_dev->dev, "request_window results in %pR\n", res);
|
||||
|
||||
mutex_unlock(&s->ops_mutex);
|
||||
*wh = res;
|
||||
|
@ -335,8 +335,6 @@ static int serial_probe(struct pcmcia_device *link)
|
||||
info->p_dev = link;
|
||||
link->priv = info;
|
||||
|
||||
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
|
||||
link->resource[0]->end = 8;
|
||||
link->conf.Attributes = CONF_ENABLE_IRQ;
|
||||
if (do_sound) {
|
||||
link->conf.Attributes |= CONF_ENABLE_SPKR;
|
||||
@ -411,6 +409,27 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static int pfc_config(struct pcmcia_device *p_dev)
|
||||
{
|
||||
unsigned int port = 0;
|
||||
struct serial_info *info = p_dev->priv;
|
||||
|
||||
if ((p_dev->resource[1]->end != 0) &&
|
||||
(resource_size(p_dev->resource[1]) == 8)) {
|
||||
port = p_dev->resource[1]->start;
|
||||
info->slave = 1;
|
||||
} else if ((info->manfid == MANFID_OSITECH) &&
|
||||
(resource_size(p_dev->resource[0]) == 0x40)) {
|
||||
port = p_dev->resource[0]->start + 0x28;
|
||||
info->slave = 1;
|
||||
}
|
||||
if (info->slave)
|
||||
return setup_serial(p_dev, info, port, p_dev->irq);
|
||||
|
||||
dev_warn(&p_dev->dev, "no usable port range found, giving up\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int simple_config_check(struct pcmcia_device *p_dev,
|
||||
cistpl_cftable_entry_t *cf,
|
||||
cistpl_cftable_entry_t *dflt,
|
||||
@ -461,23 +480,8 @@ static int simple_config(struct pcmcia_device *link)
|
||||
struct serial_info *info = link->priv;
|
||||
int i = -ENODEV, try;
|
||||
|
||||
/* If the card is already configured, look up the port and irq */
|
||||
if (link->function_config) {
|
||||
unsigned int port = 0;
|
||||
if ((link->resource[1]->end != 0) &&
|
||||
(resource_size(link->resource[1]) == 8)) {
|
||||
port = link->resource[1]->end;
|
||||
info->slave = 1;
|
||||
} else if ((info->manfid == MANFID_OSITECH) &&
|
||||
(resource_size(link->resource[0]) == 0x40)) {
|
||||
port = link->resource[0]->start + 0x28;
|
||||
info->slave = 1;
|
||||
}
|
||||
if (info->slave) {
|
||||
return setup_serial(link, info, port,
|
||||
link->irq);
|
||||
}
|
||||
}
|
||||
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
|
||||
link->resource[0]->end = 8;
|
||||
|
||||
/* First pass: look for a config entry that looks normal.
|
||||
* Two tries: without IO aliases, then with aliases */
|
||||
@ -491,8 +495,7 @@ static int simple_config(struct pcmcia_device *link)
|
||||
if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
|
||||
goto found_port;
|
||||
|
||||
printk(KERN_NOTICE
|
||||
"serial_cs: no usable port range found, giving up\n");
|
||||
dev_warn(&link->dev, "no usable port range found, giving up\n");
|
||||
return -1;
|
||||
|
||||
found_port:
|
||||
@ -558,6 +561,7 @@ static int multi_config(struct pcmcia_device *link)
|
||||
int i, base2 = 0;
|
||||
|
||||
/* First, look for a generic full-sized window */
|
||||
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
|
||||
link->resource[0]->end = info->multi * 8;
|
||||
if (pcmcia_loop_config(link, multi_config_check, &base2)) {
|
||||
/* If that didn't work, look for two windows */
|
||||
@ -565,15 +569,14 @@ static int multi_config(struct pcmcia_device *link)
|
||||
info->multi = 2;
|
||||
if (pcmcia_loop_config(link, multi_config_check_notpicky,
|
||||
&base2)) {
|
||||
printk(KERN_NOTICE "serial_cs: no usable port range"
|
||||
dev_warn(&link->dev, "no usable port range "
|
||||
"found, giving up\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
if (!link->irq)
|
||||
dev_warn(&link->dev,
|
||||
"serial_cs: no usable IRQ found, continuing...\n");
|
||||
dev_warn(&link->dev, "no usable IRQ found, continuing...\n");
|
||||
|
||||
/*
|
||||
* Apply any configuration quirks.
|
||||
@ -675,6 +678,7 @@ static int serial_config(struct pcmcia_device * link)
|
||||
multifunction cards that ask for appropriate IO port ranges */
|
||||
if ((info->multi == 0) &&
|
||||
(link->has_func_id) &&
|
||||
(link->socket->pcmcia_pfc == 0) &&
|
||||
((link->func_id == CISTPL_FUNCID_MULTI) ||
|
||||
(link->func_id == CISTPL_FUNCID_SERIAL)))
|
||||
pcmcia_loop_config(link, serial_check_for_multi, info);
|
||||
@ -685,7 +689,13 @@ static int serial_config(struct pcmcia_device * link)
|
||||
if (info->quirk && info->quirk->multi != -1)
|
||||
info->multi = info->quirk->multi;
|
||||
|
||||
if (info->multi > 1)
|
||||
dev_info(&link->dev,
|
||||
"trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n",
|
||||
link->manf_id, link->card_id,
|
||||
link->socket->pcmcia_pfc, info->multi, info->quirk);
|
||||
if (link->socket->pcmcia_pfc)
|
||||
i = pfc_config(link);
|
||||
else if (info->multi > 1)
|
||||
i = multi_config(link);
|
||||
else
|
||||
i = simple_config(link);
|
||||
@ -704,7 +714,7 @@ static int serial_config(struct pcmcia_device * link)
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
dev_warn(&link->dev, "serial_cs: failed to initialize\n");
|
||||
dev_warn(&link->dev, "failed to initialize\n");
|
||||
serial_remove(link);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user