Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd12e5c3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
parents de109c98 b76dc054
Loading
Loading
Loading
Loading
+83 −56
Original line number Diff line number Diff line
@@ -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 */
+27 −24
Original line number Diff line number Diff line
@@ -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;
+36 −26
Original line number Diff line number Diff line
@@ -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;
}