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