cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sdio_cis.c (9728B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * linux/drivers/mmc/core/sdio_cis.c
      4 *
      5 * Author:	Nicolas Pitre
      6 * Created:	June 11, 2007
      7 * Copyright:	MontaVista Software Inc.
      8 *
      9 * Copyright 2007 Pierre Ossman
     10 */
     11
     12#include <linux/kernel.h>
     13#include <linux/slab.h>
     14
     15#include <linux/mmc/host.h>
     16#include <linux/mmc/card.h>
     17#include <linux/mmc/sdio.h>
     18#include <linux/mmc/sdio_func.h>
     19
     20#include "sdio_cis.h"
     21#include "sdio_ops.h"
     22
     23#define SDIO_READ_CIS_TIMEOUT_MS  (10 * 1000) /* 10s */
     24
     25static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func,
     26			 const unsigned char *buf, unsigned size)
     27{
     28	u8 major_rev, minor_rev;
     29	unsigned i, nr_strings;
     30	char **buffer, *string;
     31
     32	if (size < 2)
     33		return 0;
     34
     35	major_rev = buf[0];
     36	minor_rev = buf[1];
     37
     38	/* Find all null-terminated (including zero length) strings in
     39	   the TPLLV1_INFO field. Trailing garbage is ignored. */
     40	buf += 2;
     41	size -= 2;
     42
     43	nr_strings = 0;
     44	for (i = 0; i < size; i++) {
     45		if (buf[i] == 0xff)
     46			break;
     47		if (buf[i] == 0)
     48			nr_strings++;
     49	}
     50	if (nr_strings == 0)
     51		return 0;
     52
     53	size = i;
     54
     55	buffer = kzalloc(sizeof(char*) * nr_strings + size, GFP_KERNEL);
     56	if (!buffer)
     57		return -ENOMEM;
     58
     59	string = (char*)(buffer + nr_strings);
     60
     61	for (i = 0; i < nr_strings; i++) {
     62		buffer[i] = string;
     63		strcpy(string, buf);
     64		string += strlen(string) + 1;
     65		buf += strlen(buf) + 1;
     66	}
     67
     68	if (func) {
     69		func->major_rev = major_rev;
     70		func->minor_rev = minor_rev;
     71		func->num_info = nr_strings;
     72		func->info = (const char**)buffer;
     73	} else {
     74		card->major_rev = major_rev;
     75		card->minor_rev = minor_rev;
     76		card->num_info = nr_strings;
     77		card->info = (const char**)buffer;
     78	}
     79
     80	return 0;
     81}
     82
     83static int cistpl_manfid(struct mmc_card *card, struct sdio_func *func,
     84			 const unsigned char *buf, unsigned size)
     85{
     86	unsigned int vendor, device;
     87
     88	/* TPLMID_MANF */
     89	vendor = buf[0] | (buf[1] << 8);
     90
     91	/* TPLMID_CARD */
     92	device = buf[2] | (buf[3] << 8);
     93
     94	if (func) {
     95		func->vendor = vendor;
     96		func->device = device;
     97	} else {
     98		card->cis.vendor = vendor;
     99		card->cis.device = device;
    100	}
    101
    102	return 0;
    103}
    104
    105static const unsigned char speed_val[16] =
    106	{ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 };
    107static const unsigned int speed_unit[8] =
    108	{ 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 };
    109
    110
    111typedef int (tpl_parse_t)(struct mmc_card *, struct sdio_func *,
    112			   const unsigned char *, unsigned);
    113
    114struct cis_tpl {
    115	unsigned char code;
    116	unsigned char min_size;
    117	tpl_parse_t *parse;
    118};
    119
    120static int cis_tpl_parse(struct mmc_card *card, struct sdio_func *func,
    121			 const char *tpl_descr,
    122			 const struct cis_tpl *tpl, int tpl_count,
    123			 unsigned char code,
    124			 const unsigned char *buf, unsigned size)
    125{
    126	int i, ret;
    127
    128	/* look for a matching code in the table */
    129	for (i = 0; i < tpl_count; i++, tpl++) {
    130		if (tpl->code == code)
    131			break;
    132	}
    133	if (i < tpl_count) {
    134		if (size >= tpl->min_size) {
    135			if (tpl->parse)
    136				ret = tpl->parse(card, func, buf, size);
    137			else
    138				ret = -EILSEQ;	/* known tuple, not parsed */
    139		} else {
    140			/* invalid tuple */
    141			ret = -EINVAL;
    142		}
    143		if (ret && ret != -EILSEQ && ret != -ENOENT) {
    144			pr_err("%s: bad %s tuple 0x%02x (%u bytes)\n",
    145			       mmc_hostname(card->host), tpl_descr, code, size);
    146		}
    147	} else {
    148		/* unknown tuple */
    149		ret = -ENOENT;
    150	}
    151
    152	return ret;
    153}
    154
    155static int cistpl_funce_common(struct mmc_card *card, struct sdio_func *func,
    156			       const unsigned char *buf, unsigned size)
    157{
    158	/* Only valid for the common CIS (function 0) */
    159	if (func)
    160		return -EINVAL;
    161
    162	/* TPLFE_FN0_BLK_SIZE */
    163	card->cis.blksize = buf[1] | (buf[2] << 8);
    164
    165	/* TPLFE_MAX_TRAN_SPEED */
    166	card->cis.max_dtr = speed_val[(buf[3] >> 3) & 15] *
    167			    speed_unit[buf[3] & 7];
    168
    169	return 0;
    170}
    171
    172static int cistpl_funce_func(struct mmc_card *card, struct sdio_func *func,
    173			     const unsigned char *buf, unsigned size)
    174{
    175	unsigned vsn;
    176	unsigned min_size;
    177
    178	/* Only valid for the individual function's CIS (1-7) */
    179	if (!func)
    180		return -EINVAL;
    181
    182	/*
    183	 * This tuple has a different length depending on the SDIO spec
    184	 * version.
    185	 */
    186	vsn = func->card->cccr.sdio_vsn;
    187	min_size = (vsn == SDIO_SDIO_REV_1_00) ? 28 : 42;
    188
    189	if (size == 28 && vsn == SDIO_SDIO_REV_1_10) {
    190		pr_warn("%s: card has broken SDIO 1.1 CIS, forcing SDIO 1.0\n",
    191			mmc_hostname(card->host));
    192		vsn = SDIO_SDIO_REV_1_00;
    193	} else if (size < min_size) {
    194		return -EINVAL;
    195	}
    196
    197	/* TPLFE_MAX_BLK_SIZE */
    198	func->max_blksize = buf[12] | (buf[13] << 8);
    199
    200	/* TPLFE_ENABLE_TIMEOUT_VAL, present in ver 1.1 and above */
    201	if (vsn > SDIO_SDIO_REV_1_00)
    202		func->enable_timeout = (buf[28] | (buf[29] << 8)) * 10;
    203	else
    204		func->enable_timeout = jiffies_to_msecs(HZ);
    205
    206	return 0;
    207}
    208
    209/*
    210 * Known TPLFE_TYPEs table for CISTPL_FUNCE tuples.
    211 *
    212 * Note that, unlike PCMCIA, CISTPL_FUNCE tuples are not parsed depending
    213 * on the TPLFID_FUNCTION value of the previous CISTPL_FUNCID as on SDIO
    214 * TPLFID_FUNCTION is always hardcoded to 0x0C.
    215 */
    216static const struct cis_tpl cis_tpl_funce_list[] = {
    217	{	0x00,	4,	cistpl_funce_common		},
    218	{	0x01,	0,	cistpl_funce_func		},
    219	{	0x04,	1+1+6,	/* CISTPL_FUNCE_LAN_NODE_ID */	},
    220};
    221
    222static int cistpl_funce(struct mmc_card *card, struct sdio_func *func,
    223			const unsigned char *buf, unsigned size)
    224{
    225	if (size < 1)
    226		return -EINVAL;
    227
    228	return cis_tpl_parse(card, func, "CISTPL_FUNCE",
    229			     cis_tpl_funce_list,
    230			     ARRAY_SIZE(cis_tpl_funce_list),
    231			     buf[0], buf, size);
    232}
    233
    234/* Known TPL_CODEs table for CIS tuples */
    235static const struct cis_tpl cis_tpl_list[] = {
    236	{	0x15,	3,	cistpl_vers_1		},
    237	{	0x20,	4,	cistpl_manfid		},
    238	{	0x21,	2,	/* cistpl_funcid */	},
    239	{	0x22,	0,	cistpl_funce		},
    240	{	0x91,	2,	/* cistpl_sdio_std */	},
    241};
    242
    243static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
    244{
    245	int ret;
    246	struct sdio_func_tuple *this, **prev;
    247	unsigned i, ptr = 0;
    248
    249	/*
    250	 * Note that this works for the common CIS (function number 0) as
    251	 * well as a function's CIS * since SDIO_CCCR_CIS and SDIO_FBR_CIS
    252	 * have the same offset.
    253	 */
    254	for (i = 0; i < 3; i++) {
    255		unsigned char x, fn;
    256
    257		if (func)
    258			fn = func->num;
    259		else
    260			fn = 0;
    261
    262		ret = mmc_io_rw_direct(card, 0, 0,
    263			SDIO_FBR_BASE(fn) + SDIO_FBR_CIS + i, 0, &x);
    264		if (ret)
    265			return ret;
    266		ptr |= x << (i * 8);
    267	}
    268
    269	if (func)
    270		prev = &func->tuples;
    271	else
    272		prev = &card->tuples;
    273
    274	if (*prev)
    275		return -EINVAL;
    276
    277	do {
    278		unsigned char tpl_code, tpl_link;
    279		unsigned long timeout = jiffies +
    280			msecs_to_jiffies(SDIO_READ_CIS_TIMEOUT_MS);
    281
    282		ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_code);
    283		if (ret)
    284			break;
    285
    286		/* 0xff means we're done */
    287		if (tpl_code == 0xff)
    288			break;
    289
    290		/* null entries have no link field or data */
    291		if (tpl_code == 0x00)
    292			continue;
    293
    294		ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_link);
    295		if (ret)
    296			break;
    297
    298		/* a size of 0xff also means we're done */
    299		if (tpl_link == 0xff)
    300			break;
    301
    302		this = kmalloc(sizeof(*this) + tpl_link, GFP_KERNEL);
    303		if (!this)
    304			return -ENOMEM;
    305
    306		for (i = 0; i < tpl_link; i++) {
    307			ret = mmc_io_rw_direct(card, 0, 0,
    308					       ptr + i, 0, &this->data[i]);
    309			if (ret)
    310				break;
    311		}
    312		if (ret) {
    313			kfree(this);
    314			break;
    315		}
    316
    317		/* Try to parse the CIS tuple */
    318		ret = cis_tpl_parse(card, func, "CIS",
    319				    cis_tpl_list, ARRAY_SIZE(cis_tpl_list),
    320				    tpl_code, this->data, tpl_link);
    321		if (ret == -EILSEQ || ret == -ENOENT) {
    322			/*
    323			 * The tuple is unknown or known but not parsed.
    324			 * Queue the tuple for the function driver.
    325			 */
    326			this->next = NULL;
    327			this->code = tpl_code;
    328			this->size = tpl_link;
    329			*prev = this;
    330			prev = &this->next;
    331
    332			if (ret == -ENOENT) {
    333
    334				if (time_after(jiffies, timeout))
    335					break;
    336
    337#define FMT(type) "%s: queuing " type " CIS tuple 0x%02x [%*ph] (%u bytes)\n"
    338				/*
    339				 * Tuples in this range are reserved for
    340				 * vendors, so don't warn about them
    341				 */
    342				if (tpl_code >= 0x80 && tpl_code <= 0x8f)
    343					pr_debug_ratelimited(FMT("vendor"),
    344						mmc_hostname(card->host),
    345						tpl_code, tpl_link, this->data,
    346						tpl_link);
    347				else
    348					pr_warn_ratelimited(FMT("unknown"),
    349						mmc_hostname(card->host),
    350						tpl_code, tpl_link, this->data,
    351						tpl_link);
    352			}
    353
    354			/* keep on analyzing tuples */
    355			ret = 0;
    356		} else {
    357			/*
    358			 * We don't need the tuple anymore if it was
    359			 * successfully parsed by the SDIO core or if it is
    360			 * not going to be queued for a driver.
    361			 */
    362			kfree(this);
    363		}
    364
    365		ptr += tpl_link;
    366	} while (!ret);
    367
    368	/*
    369	 * Link in all unknown tuples found in the common CIS so that
    370	 * drivers don't have to go digging in two places.
    371	 */
    372	if (func)
    373		*prev = card->tuples;
    374
    375	return ret;
    376}
    377
    378int sdio_read_common_cis(struct mmc_card *card)
    379{
    380	return sdio_read_cis(card, NULL);
    381}
    382
    383void sdio_free_common_cis(struct mmc_card *card)
    384{
    385	struct sdio_func_tuple *tuple, *victim;
    386
    387	tuple = card->tuples;
    388
    389	while (tuple) {
    390		victim = tuple;
    391		tuple = tuple->next;
    392		kfree(victim);
    393	}
    394
    395	card->tuples = NULL;
    396}
    397
    398int sdio_read_func_cis(struct sdio_func *func)
    399{
    400	int ret;
    401
    402	ret = sdio_read_cis(func->card, func);
    403	if (ret)
    404		return ret;
    405
    406	/*
    407	 * Since we've linked to tuples in the card structure,
    408	 * we must make sure we have a reference to it.
    409	 */
    410	get_device(&func->card->dev);
    411
    412	/*
    413	 * Vendor/device id is optional for function CIS, so
    414	 * copy it from the card structure as needed.
    415	 */
    416	if (func->vendor == 0) {
    417		func->vendor = func->card->cis.vendor;
    418		func->device = func->card->cis.device;
    419	}
    420
    421	return 0;
    422}
    423
    424void sdio_free_func_cis(struct sdio_func *func)
    425{
    426	struct sdio_func_tuple *tuple, *victim;
    427
    428	tuple = func->tuples;
    429
    430	while (tuple && tuple != func->card->tuples) {
    431		victim = tuple;
    432		tuple = tuple->next;
    433		kfree(victim);
    434	}
    435
    436	func->tuples = NULL;
    437
    438	/*
    439	 * We have now removed the link to the tuples in the
    440	 * card structure, so remove the reference.
    441	 */
    442	put_device(&func->card->dev);
    443}
    444