root/drivers/mmc/core/sdio_cis.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cistpl_vers_1
  2. cistpl_manfid
  3. cis_tpl_parse
  4. cistpl_funce_common
  5. cistpl_funce_func
  6. cistpl_funce
  7. sdio_read_cis
  8. sdio_read_common_cis
  9. sdio_free_common_cis
  10. sdio_read_func_cis
  11. sdio_free_func_cis

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

/* [<][>][^][v][top][bottom][index][help] */