static int pcmcia_device_query()

in ds.c [398:476]


static int pcmcia_device_query(struct pcmcia_device *p_dev)
{
	cistpl_manfid_t manf_id;
	cistpl_funcid_t func_id;
	cistpl_vers_1_t	*vers1;
	unsigned int i;

	vers1 = kmalloc(sizeof(*vers1), GFP_KERNEL);
	if (!vers1)
		return -ENOMEM;

	if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL,
			       CISTPL_MANFID, &manf_id)) {
		mutex_lock(&p_dev->socket->ops_mutex);
		p_dev->manf_id = manf_id.manf;
		p_dev->card_id = manf_id.card;
		p_dev->has_manf_id = 1;
		p_dev->has_card_id = 1;
		mutex_unlock(&p_dev->socket->ops_mutex);
	}

	if (!pccard_read_tuple(p_dev->socket, p_dev->func,
			       CISTPL_FUNCID, &func_id)) {
		mutex_lock(&p_dev->socket->ops_mutex);
		p_dev->func_id = func_id.func;
		p_dev->has_func_id = 1;
		mutex_unlock(&p_dev->socket->ops_mutex);
	} else {
		/* rule of thumb: cards with no FUNCID, but with
		 * common memory device geometry information, are
		 * probably memory cards (from pcmcia-cs) */
		cistpl_device_geo_t *devgeo;

		devgeo = kmalloc(sizeof(*devgeo), GFP_KERNEL);
		if (!devgeo) {
			kfree(vers1);
			return -ENOMEM;
		}
		if (!pccard_read_tuple(p_dev->socket, p_dev->func,
				      CISTPL_DEVICE_GEO, devgeo)) {
			dev_dbg(&p_dev->dev,
				   "mem device geometry probably means "
				   "FUNCID_MEMORY\n");
			mutex_lock(&p_dev->socket->ops_mutex);
			p_dev->func_id = CISTPL_FUNCID_MEMORY;
			p_dev->has_func_id = 1;
			mutex_unlock(&p_dev->socket->ops_mutex);
		}
		kfree(devgeo);
	}

	if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL, CISTPL_VERS_1,
			       vers1)) {
		mutex_lock(&p_dev->socket->ops_mutex);
		for (i = 0; i < min_t(unsigned int, 4, vers1->ns); i++) {
			char *tmp;
			unsigned int length;
			char *new;

			tmp = vers1->str + vers1->ofs[i];

			length = strlen(tmp) + 1;
			if ((length < 2) || (length > 255))
				continue;

			new = kstrdup(tmp, GFP_KERNEL);
			if (!new)
				continue;

			tmp = p_dev->prod_id[i];
			p_dev->prod_id[i] = new;
			kfree(tmp);
		}
		mutex_unlock(&p_dev->socket->ops_mutex);
	}

	kfree(vers1);
	return 0;
}