Skip to content

Commit

Permalink
Merge branch 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/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
  • Loading branch information
Linus Torvalds committed Sep 16, 2010
2 parents de109c9 + b76dc05 commit bd12e5c
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 106 deletions.
139 changes: 83 additions & 56 deletions drivers/net/pcmcia/pcnet_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -525,77 +526,103 @@ 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;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
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 hw_info_t *pcnet_try_config(struct pcmcia_device *link,
int *has_shmem, int try)
{
struct net_device *dev = link->priv;
hw_info_t *local_hw_info;
pcnet_dev_t *info = PRIV(dev);
int priv = try;
int ret;

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)
return NULL;

if (resource_size(link->resource[1]) == 8) {
link->conf.Attributes |= CONF_ENABLE_SPKR;
link->conf.Status = CCSR_AUDIO_ENA;
}
if ((link->manf_id == MANFID_IBM) &&
(link->card_id == PRODID_IBM_HOME_AND_AWAY))
link->conf.ConfigIndex |= 0x10;

ret = pcmcia_request_configuration(link, &link->conf);
if (ret)
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
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)) {
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)
local_hw_info = get_prom(link);
if (!local_hw_info)
local_hw_info = get_dl10019(link);
if (!local_hw_info)
local_hw_info = get_ax88190(link);
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 ret, start_pg, stop_pg, cm_offset;
int start_pg, stop_pg, cm_offset;
int has_shmem = 0;
hw_info_t *local_hw_info;

dev_dbg(&link->dev, "pcnet_config\n");

ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem);
if (ret)
goto failed;

if (!link->irq)
goto failed;

if (resource_size(link->resource[1]) == 8) {
link->conf.Attributes |= CONF_ENABLE_SPKR;
link->conf.Status = CCSR_AUDIO_ENA;
}
if ((link->manf_id == MANFID_IBM) &&
(link->card_id == PRODID_IBM_HOME_AND_AWAY))
link->conf.ConfigIndex |= 0x10;

ret = pcmcia_request_configuration(link, &link->conf);
if (ret)
goto failed;
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->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;
}

local_hw_info = get_hwinfo(link);
if (local_hw_info == NULL)
local_hw_info = get_prom(link);
if (local_hw_info == NULL)
local_hw_info = get_dl10019(link);
if (local_hw_info == NULL)
local_hw_info = get_ax88190(link);
if (local_hw_info == NULL)
local_hw_info = get_hwired(link);

if (local_hw_info == NULL) {
printk(KERN_NOTICE "pcnet_cs: unable to read hardware net"
" address for io base %#3lx\n", dev->base_addr);
goto failed;
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) {
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;
Expand Down
51 changes: 27 additions & 24 deletions drivers/pcmcia/pcmcia_resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 */
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -439,23 +441,23 @@ 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;
}

mutex_lock(&s->ops_mutex);
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;
}

/* Do power control. We don't allow changes in Vcc. */
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;
}
Expand Down Expand Up @@ -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;
}

Expand All @@ -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);
Expand Down Expand Up @@ -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;
}

Expand All @@ -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)
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
Expand Down
Loading

0 comments on commit bd12e5c

Please sign in to comment.