linux/drivers/scsi/fcoe/fcoe_sysfs.c
<<
>>
Prefs
   1/*
   2 * Copyright(c) 2011 - 2012 Intel Corporation. All rights reserved.
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms and conditions of the GNU General Public License,
   6 * version 2, as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope it will be useful, but WITHOUT
   9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  11 * more details.
  12 *
  13 * You should have received a copy of the GNU General Public License along with
  14 * this program; if not, write to the Free Software Foundation, Inc.,
  15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  16 *
  17 * Maintained at www.Open-FCoE.org
  18 */
  19
  20#include <linux/module.h>
  21#include <linux/types.h>
  22#include <linux/kernel.h>
  23#include <linux/etherdevice.h>
  24#include <linux/ctype.h>
  25
  26#include <scsi/fcoe_sysfs.h>
  27#include <scsi/libfcoe.h>
  28
  29/*
  30 * OK to include local libfcoe.h for debug_logging, but cannot include
  31 * <scsi/libfcoe.h> otherwise non-netdev based fcoe solutions would have
  32 * have to include more than fcoe_sysfs.h.
  33 */
  34#include "libfcoe.h"
  35
  36static atomic_t ctlr_num;
  37static atomic_t fcf_num;
  38
  39/*
  40 * fcoe_fcf_dev_loss_tmo: the default number of seconds that fcoe sysfs
  41 * should insulate the loss of a fcf.
  42 */
  43static unsigned int fcoe_fcf_dev_loss_tmo = 1800;  /* seconds */
  44
  45module_param_named(fcf_dev_loss_tmo, fcoe_fcf_dev_loss_tmo,
  46                   uint, S_IRUGO|S_IWUSR);
  47MODULE_PARM_DESC(fcf_dev_loss_tmo,
  48                 "Maximum number of seconds that libfcoe should"
  49                 " insulate the loss of a fcf. Once this value is"
  50                 " exceeded, the fcf is removed.");
  51
  52/*
  53 * These are used by the fcoe_*_show_function routines, they
  54 * are intentionally placed in the .c file as they're not intended
  55 * for use throughout the code.
  56 */
  57#define fcoe_ctlr_id(x)                         \
  58        ((x)->id)
  59#define fcoe_ctlr_work_q_name(x)                \
  60        ((x)->work_q_name)
  61#define fcoe_ctlr_work_q(x)                     \
  62        ((x)->work_q)
  63#define fcoe_ctlr_devloss_work_q_name(x)        \
  64        ((x)->devloss_work_q_name)
  65#define fcoe_ctlr_devloss_work_q(x)             \
  66        ((x)->devloss_work_q)
  67#define fcoe_ctlr_mode(x)                       \
  68        ((x)->mode)
  69#define fcoe_ctlr_fcf_dev_loss_tmo(x)           \
  70        ((x)->fcf_dev_loss_tmo)
  71#define fcoe_ctlr_link_fail(x)                  \
  72        ((x)->lesb.lesb_link_fail)
  73#define fcoe_ctlr_vlink_fail(x)                 \
  74        ((x)->lesb.lesb_vlink_fail)
  75#define fcoe_ctlr_miss_fka(x)                   \
  76        ((x)->lesb.lesb_miss_fka)
  77#define fcoe_ctlr_symb_err(x)                   \
  78        ((x)->lesb.lesb_symb_err)
  79#define fcoe_ctlr_err_block(x)                  \
  80        ((x)->lesb.lesb_err_block)
  81#define fcoe_ctlr_fcs_error(x)                  \
  82        ((x)->lesb.lesb_fcs_error)
  83#define fcoe_ctlr_enabled(x)                    \
  84        ((x)->enabled)
  85#define fcoe_fcf_state(x)                       \
  86        ((x)->state)
  87#define fcoe_fcf_fabric_name(x)                 \
  88        ((x)->fabric_name)
  89#define fcoe_fcf_switch_name(x)                 \
  90        ((x)->switch_name)
  91#define fcoe_fcf_fc_map(x)                      \
  92        ((x)->fc_map)
  93#define fcoe_fcf_vfid(x)                        \
  94        ((x)->vfid)
  95#define fcoe_fcf_mac(x)                         \
  96        ((x)->mac)
  97#define fcoe_fcf_priority(x)                    \
  98        ((x)->priority)
  99#define fcoe_fcf_fka_period(x)                  \
 100        ((x)->fka_period)
 101#define fcoe_fcf_dev_loss_tmo(x)                \
 102        ((x)->dev_loss_tmo)
 103#define fcoe_fcf_selected(x)                    \
 104        ((x)->selected)
 105#define fcoe_fcf_vlan_id(x)                     \
 106        ((x)->vlan_id)
 107
 108/*
 109 * dev_loss_tmo attribute
 110 */
 111static int fcoe_str_to_dev_loss(const char *buf, unsigned long *val)
 112{
 113        int ret;
 114
 115        ret = kstrtoul(buf, 0, val);
 116        if (ret)
 117                return -EINVAL;
 118        /*
 119         * Check for overflow; dev_loss_tmo is u32
 120         */
 121        if (*val > UINT_MAX)
 122                return -EINVAL;
 123
 124        return 0;
 125}
 126
 127static int fcoe_fcf_set_dev_loss_tmo(struct fcoe_fcf_device *fcf,
 128                                     unsigned long val)
 129{
 130        if ((fcf->state == FCOE_FCF_STATE_UNKNOWN) ||
 131            (fcf->state == FCOE_FCF_STATE_DISCONNECTED) ||
 132            (fcf->state == FCOE_FCF_STATE_DELETED))
 133                return -EBUSY;
 134        /*
 135         * Check for overflow; dev_loss_tmo is u32
 136         */
 137        if (val > UINT_MAX)
 138                return -EINVAL;
 139
 140        fcoe_fcf_dev_loss_tmo(fcf) = val;
 141        return 0;
 142}
 143
 144#define FCOE_DEVICE_ATTR(_prefix, _name, _mode, _show, _store)  \
 145struct device_attribute device_attr_fcoe_##_prefix##_##_name =  \
 146        __ATTR(_name, _mode, _show, _store)
 147
 148#define fcoe_ctlr_show_function(field, format_string, sz, cast) \
 149static ssize_t show_fcoe_ctlr_device_##field(struct device *dev, \
 150                                            struct device_attribute *attr, \
 151                                            char *buf)                  \
 152{                                                                       \
 153        struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);               \
 154        if (ctlr->f->get_fcoe_ctlr_##field)                             \
 155                ctlr->f->get_fcoe_ctlr_##field(ctlr);                   \
 156        return snprintf(buf, sz, format_string,                         \
 157                        cast fcoe_ctlr_##field(ctlr));                  \
 158}
 159
 160#define fcoe_fcf_show_function(field, format_string, sz, cast)  \
 161static ssize_t show_fcoe_fcf_device_##field(struct device *dev, \
 162                                           struct device_attribute *attr, \
 163                                           char *buf)                   \
 164{                                                                       \
 165        struct fcoe_fcf_device *fcf = dev_to_fcf(dev);                  \
 166        struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf);  \
 167        if (ctlr->f->get_fcoe_fcf_##field)                              \
 168                ctlr->f->get_fcoe_fcf_##field(fcf);                     \
 169        return snprintf(buf, sz, format_string,                         \
 170                        cast fcoe_fcf_##field(fcf));                    \
 171}
 172
 173#define fcoe_ctlr_private_show_function(field, format_string, sz, cast) \
 174static ssize_t show_fcoe_ctlr_device_##field(struct device *dev, \
 175                                            struct device_attribute *attr, \
 176                                            char *buf)                  \
 177{                                                                       \
 178        struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);               \
 179        return snprintf(buf, sz, format_string, cast fcoe_ctlr_##field(ctlr)); \
 180}
 181
 182#define fcoe_fcf_private_show_function(field, format_string, sz, cast)  \
 183static ssize_t show_fcoe_fcf_device_##field(struct device *dev, \
 184                                           struct device_attribute *attr, \
 185                                           char *buf)                   \
 186{                                                               \
 187        struct fcoe_fcf_device *fcf = dev_to_fcf(dev);                  \
 188        return snprintf(buf, sz, format_string, cast fcoe_fcf_##field(fcf)); \
 189}
 190
 191#define fcoe_ctlr_private_rd_attr(field, format_string, sz)             \
 192        fcoe_ctlr_private_show_function(field, format_string, sz, )     \
 193        static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO,                   \
 194                                show_fcoe_ctlr_device_##field, NULL)
 195
 196#define fcoe_ctlr_rd_attr(field, format_string, sz)                     \
 197        fcoe_ctlr_show_function(field, format_string, sz, )             \
 198        static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO,                   \
 199                                show_fcoe_ctlr_device_##field, NULL)
 200
 201#define fcoe_fcf_rd_attr(field, format_string, sz)                      \
 202        fcoe_fcf_show_function(field, format_string, sz, )              \
 203        static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO,                    \
 204                                show_fcoe_fcf_device_##field, NULL)
 205
 206#define fcoe_fcf_private_rd_attr(field, format_string, sz)              \
 207        fcoe_fcf_private_show_function(field, format_string, sz, )      \
 208        static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO,                    \
 209                                show_fcoe_fcf_device_##field, NULL)
 210
 211#define fcoe_ctlr_private_rd_attr_cast(field, format_string, sz, cast)  \
 212        fcoe_ctlr_private_show_function(field, format_string, sz, (cast)) \
 213        static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO,                   \
 214                                show_fcoe_ctlr_device_##field, NULL)
 215
 216#define fcoe_fcf_private_rd_attr_cast(field, format_string, sz, cast)   \
 217        fcoe_fcf_private_show_function(field, format_string, sz, (cast)) \
 218        static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO,                    \
 219                                show_fcoe_fcf_device_##field, NULL)
 220
 221#define fcoe_enum_name_search(title, table_type, table)                 \
 222static const char *get_fcoe_##title##_name(enum table_type table_key)   \
 223{                                                                       \
 224        if (table_key < 0 || table_key >= ARRAY_SIZE(table))            \
 225                return NULL;                                            \
 226        return table[table_key];                                        \
 227}
 228
 229static char *fip_conn_type_names[] = {
 230        [ FIP_CONN_TYPE_UNKNOWN ] = "Unknown",
 231        [ FIP_CONN_TYPE_FABRIC ]  = "Fabric",
 232        [ FIP_CONN_TYPE_VN2VN ]   = "VN2VN",
 233};
 234fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names)
 235
 236static enum fip_conn_type fcoe_parse_mode(const char *buf)
 237{
 238        int i;
 239
 240        for (i = 0; i < ARRAY_SIZE(fip_conn_type_names); i++) {
 241                if (strcasecmp(buf, fip_conn_type_names[i]) == 0)
 242                        return i;
 243        }
 244
 245        return FIP_CONN_TYPE_UNKNOWN;
 246}
 247
 248static char *fcf_state_names[] = {
 249        [ FCOE_FCF_STATE_UNKNOWN ]      = "Unknown",
 250        [ FCOE_FCF_STATE_DISCONNECTED ] = "Disconnected",
 251        [ FCOE_FCF_STATE_CONNECTED ]    = "Connected",
 252};
 253fcoe_enum_name_search(fcf_state, fcf_state, fcf_state_names)
 254#define FCOE_FCF_STATE_MAX_NAMELEN 50
 255
 256static ssize_t show_fcf_state(struct device *dev,
 257                              struct device_attribute *attr,
 258                              char *buf)
 259{
 260        struct fcoe_fcf_device *fcf = dev_to_fcf(dev);
 261        const char *name;
 262        name = get_fcoe_fcf_state_name(fcf->state);
 263        if (!name)
 264                return -EINVAL;
 265        return snprintf(buf, FCOE_FCF_STATE_MAX_NAMELEN, "%s\n", name);
 266}
 267static FCOE_DEVICE_ATTR(fcf, state, S_IRUGO, show_fcf_state, NULL);
 268
 269#define FCOE_MAX_MODENAME_LEN 20
 270static ssize_t show_ctlr_mode(struct device *dev,
 271                              struct device_attribute *attr,
 272                              char *buf)
 273{
 274        struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
 275        const char *name;
 276
 277        name = get_fcoe_ctlr_mode_name(ctlr->mode);
 278        if (!name)
 279                return -EINVAL;
 280        return snprintf(buf, FCOE_MAX_MODENAME_LEN,
 281                        "%s\n", name);
 282}
 283
 284static ssize_t store_ctlr_mode(struct device *dev,
 285                               struct device_attribute *attr,
 286                               const char *buf, size_t count)
 287{
 288        struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
 289        char mode[FCOE_MAX_MODENAME_LEN + 1];
 290
 291        if (count > FCOE_MAX_MODENAME_LEN)
 292                return -EINVAL;
 293
 294        strncpy(mode, buf, count);
 295
 296        if (mode[count - 1] == '\n')
 297                mode[count - 1] = '\0';
 298        else
 299                mode[count] = '\0';
 300
 301        switch (ctlr->enabled) {
 302        case FCOE_CTLR_ENABLED:
 303                LIBFCOE_SYSFS_DBG(ctlr, "Cannot change mode when enabled.\n");
 304                return -EBUSY;
 305        case FCOE_CTLR_DISABLED:
 306                if (!ctlr->f->set_fcoe_ctlr_mode) {
 307                        LIBFCOE_SYSFS_DBG(ctlr,
 308                                          "Mode change not supported by LLD.\n");
 309                        return -ENOTSUPP;
 310                }
 311
 312                ctlr->mode = fcoe_parse_mode(mode);
 313                if (ctlr->mode == FIP_CONN_TYPE_UNKNOWN) {
 314                        LIBFCOE_SYSFS_DBG(ctlr, "Unknown mode %s provided.\n",
 315                                          buf);
 316                        return -EINVAL;
 317                }
 318
 319                ctlr->f->set_fcoe_ctlr_mode(ctlr);
 320                LIBFCOE_SYSFS_DBG(ctlr, "Mode changed to %s.\n", buf);
 321
 322                return count;
 323        case FCOE_CTLR_UNUSED:
 324        default:
 325                LIBFCOE_SYSFS_DBG(ctlr, "Mode change not supported.\n");
 326                return -ENOTSUPP;
 327        };
 328}
 329
 330static FCOE_DEVICE_ATTR(ctlr, mode, S_IRUGO | S_IWUSR,
 331                        show_ctlr_mode, store_ctlr_mode);
 332
 333static ssize_t store_ctlr_enabled(struct device *dev,
 334                                  struct device_attribute *attr,
 335                                  const char *buf, size_t count)
 336{
 337        struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
 338        bool enabled;
 339        int rc;
 340
 341        if (*buf == '1')
 342                enabled = true;
 343        else if (*buf == '0')
 344                enabled = false;
 345        else
 346                return -EINVAL;
 347
 348        switch (ctlr->enabled) {
 349        case FCOE_CTLR_ENABLED:
 350                if (enabled)
 351                        return count;
 352                ctlr->enabled = FCOE_CTLR_DISABLED;
 353                break;
 354        case FCOE_CTLR_DISABLED:
 355                if (!enabled)
 356                        return count;
 357                ctlr->enabled = FCOE_CTLR_ENABLED;
 358                break;
 359        case FCOE_CTLR_UNUSED:
 360                return -ENOTSUPP;
 361        };
 362
 363        rc = ctlr->f->set_fcoe_ctlr_enabled(ctlr);
 364        if (rc)
 365                return rc;
 366
 367        return count;
 368}
 369
 370static char *ctlr_enabled_state_names[] = {
 371        [ FCOE_CTLR_ENABLED ]  = "1",
 372        [ FCOE_CTLR_DISABLED ] = "0",
 373};
 374fcoe_enum_name_search(ctlr_enabled_state, ctlr_enabled_state,
 375                      ctlr_enabled_state_names)
 376#define FCOE_CTLR_ENABLED_MAX_NAMELEN 50
 377
 378static ssize_t show_ctlr_enabled_state(struct device *dev,
 379                                       struct device_attribute *attr,
 380                                       char *buf)
 381{
 382        struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
 383        const char *name;
 384
 385        name = get_fcoe_ctlr_enabled_state_name(ctlr->enabled);
 386        if (!name)
 387                return -EINVAL;
 388        return snprintf(buf, FCOE_CTLR_ENABLED_MAX_NAMELEN,
 389                        "%s\n", name);
 390}
 391
 392static FCOE_DEVICE_ATTR(ctlr, enabled, S_IRUGO | S_IWUSR,
 393                        show_ctlr_enabled_state,
 394                        store_ctlr_enabled);
 395
 396static ssize_t store_ctlr_fip_resp(struct device *dev,
 397                              struct device_attribute *attr,
 398                              const char *buf, size_t count)
 399{
 400        struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
 401        struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr);
 402
 403        mutex_lock(&fip->ctlr_mutex);
 404        if ((buf[1] == '\0') || ((buf[1] == '\n') && (buf[2] == '\0'))) {
 405                if (buf[0] == '1') {
 406                        fip->fip_resp = 1;
 407                        mutex_unlock(&fip->ctlr_mutex);
 408                        return count;
 409                }
 410                if (buf[0] == '0') {
 411                        fip->fip_resp = 0;
 412                        mutex_unlock(&fip->ctlr_mutex);
 413                        return count;
 414                }
 415        }
 416        mutex_unlock(&fip->ctlr_mutex);
 417        return -EINVAL;
 418}
 419
 420static ssize_t show_ctlr_fip_resp(struct device *dev,
 421                                  struct device_attribute *attr,
 422                                  char *buf)
 423{
 424        struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
 425        struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr);
 426
 427        return sprintf(buf, "%d\n", fip->fip_resp ? 1 : 0);
 428}
 429
 430static FCOE_DEVICE_ATTR(ctlr, fip_vlan_responder, S_IRUGO | S_IWUSR,
 431                        show_ctlr_fip_resp,
 432                        store_ctlr_fip_resp);
 433
 434static ssize_t
 435fcoe_ctlr_var_store(u32 *var, const char *buf, size_t count)
 436{
 437        int err;
 438        unsigned long v;
 439
 440        err = kstrtoul(buf, 10, &v);
 441        if (err || v > UINT_MAX)
 442                return -EINVAL;
 443
 444        *var = v;
 445
 446        return count;
 447}
 448
 449static ssize_t store_ctlr_r_a_tov(struct device *dev,
 450                                  struct device_attribute *attr,
 451                                  const char *buf, size_t count)
 452{
 453        struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
 454        struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
 455
 456        if (ctlr_dev->enabled == FCOE_CTLR_ENABLED)
 457                return -EBUSY;
 458        if (ctlr_dev->enabled == FCOE_CTLR_DISABLED)
 459                return fcoe_ctlr_var_store(&ctlr->lp->r_a_tov, buf, count);
 460        return -ENOTSUPP;
 461}
 462
 463static ssize_t show_ctlr_r_a_tov(struct device *dev,
 464                                 struct device_attribute *attr,
 465                                 char *buf)
 466{
 467        struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
 468        struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
 469
 470        return sprintf(buf, "%d\n", ctlr->lp->r_a_tov);
 471}
 472
 473static FCOE_DEVICE_ATTR(ctlr, r_a_tov, S_IRUGO | S_IWUSR,
 474                        show_ctlr_r_a_tov, store_ctlr_r_a_tov);
 475
 476static ssize_t store_ctlr_e_d_tov(struct device *dev,
 477                                  struct device_attribute *attr,
 478                                  const char *buf, size_t count)
 479{
 480        struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
 481        struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
 482
 483        if (ctlr_dev->enabled == FCOE_CTLR_ENABLED)
 484                return -EBUSY;
 485        if (ctlr_dev->enabled == FCOE_CTLR_DISABLED)
 486                return fcoe_ctlr_var_store(&ctlr->lp->e_d_tov, buf, count);
 487        return -ENOTSUPP;
 488}
 489
 490static ssize_t show_ctlr_e_d_tov(struct device *dev,
 491                                 struct device_attribute *attr,
 492                                 char *buf)
 493{
 494        struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
 495        struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
 496
 497        return sprintf(buf, "%d\n", ctlr->lp->e_d_tov);
 498}
 499
 500static FCOE_DEVICE_ATTR(ctlr, e_d_tov, S_IRUGO | S_IWUSR,
 501                        show_ctlr_e_d_tov, store_ctlr_e_d_tov);
 502
 503static ssize_t
 504store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev,
 505                                         struct device_attribute *attr,
 506                                         const char *buf, size_t count)
 507{
 508        struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
 509        struct fcoe_fcf_device *fcf;
 510        unsigned long val;
 511        int rc;
 512
 513        rc = fcoe_str_to_dev_loss(buf, &val);
 514        if (rc)
 515                return rc;
 516
 517        fcoe_ctlr_fcf_dev_loss_tmo(ctlr) = val;
 518        mutex_lock(&ctlr->lock);
 519        list_for_each_entry(fcf, &ctlr->fcfs, peers)
 520                fcoe_fcf_set_dev_loss_tmo(fcf, val);
 521        mutex_unlock(&ctlr->lock);
 522        return count;
 523}
 524fcoe_ctlr_private_show_function(fcf_dev_loss_tmo, "%d\n", 20, );
 525static FCOE_DEVICE_ATTR(ctlr, fcf_dev_loss_tmo, S_IRUGO | S_IWUSR,
 526                        show_fcoe_ctlr_device_fcf_dev_loss_tmo,
 527                        store_private_fcoe_ctlr_fcf_dev_loss_tmo);
 528
 529/* Link Error Status Block (LESB) */
 530fcoe_ctlr_rd_attr(link_fail, "%u\n", 20);
 531fcoe_ctlr_rd_attr(vlink_fail, "%u\n", 20);
 532fcoe_ctlr_rd_attr(miss_fka, "%u\n", 20);
 533fcoe_ctlr_rd_attr(symb_err, "%u\n", 20);
 534fcoe_ctlr_rd_attr(err_block, "%u\n", 20);
 535fcoe_ctlr_rd_attr(fcs_error, "%u\n", 20);
 536
 537fcoe_fcf_private_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long);
 538fcoe_fcf_private_rd_attr_cast(switch_name, "0x%llx\n", 20, unsigned long long);
 539fcoe_fcf_private_rd_attr(priority, "%u\n", 20);
 540fcoe_fcf_private_rd_attr(fc_map, "0x%x\n", 20);
 541fcoe_fcf_private_rd_attr(vfid, "%u\n", 20);
 542fcoe_fcf_private_rd_attr(mac, "%pM\n", 20);
 543fcoe_fcf_private_rd_attr(fka_period, "%u\n", 20);
 544fcoe_fcf_rd_attr(selected, "%u\n", 20);
 545fcoe_fcf_rd_attr(vlan_id, "%u\n", 20);
 546
 547fcoe_fcf_private_show_function(dev_loss_tmo, "%d\n", 20, )
 548static ssize_t
 549store_fcoe_fcf_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
 550                            const char *buf, size_t count)
 551{
 552        struct fcoe_fcf_device *fcf = dev_to_fcf(dev);
 553        unsigned long val;
 554        int rc;
 555
 556        rc = fcoe_str_to_dev_loss(buf, &val);
 557        if (rc)
 558                return rc;
 559
 560        rc = fcoe_fcf_set_dev_loss_tmo(fcf, val);
 561        if (rc)
 562                return rc;
 563        return count;
 564}
 565static FCOE_DEVICE_ATTR(fcf, dev_loss_tmo, S_IRUGO | S_IWUSR,
 566                        show_fcoe_fcf_device_dev_loss_tmo,
 567                        store_fcoe_fcf_dev_loss_tmo);
 568
 569static struct attribute *fcoe_ctlr_lesb_attrs[] = {
 570        &device_attr_fcoe_ctlr_link_fail.attr,
 571        &device_attr_fcoe_ctlr_vlink_fail.attr,
 572        &device_attr_fcoe_ctlr_miss_fka.attr,
 573        &device_attr_fcoe_ctlr_symb_err.attr,
 574        &device_attr_fcoe_ctlr_err_block.attr,
 575        &device_attr_fcoe_ctlr_fcs_error.attr,
 576        NULL,
 577};
 578
 579static struct attribute_group fcoe_ctlr_lesb_attr_group = {
 580        .name = "lesb",
 581        .attrs = fcoe_ctlr_lesb_attrs,
 582};
 583
 584static struct attribute *fcoe_ctlr_attrs[] = {
 585        &device_attr_fcoe_ctlr_fip_vlan_responder.attr,
 586        &device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr,
 587        &device_attr_fcoe_ctlr_r_a_tov.attr,
 588        &device_attr_fcoe_ctlr_e_d_tov.attr,
 589        &device_attr_fcoe_ctlr_enabled.attr,
 590        &device_attr_fcoe_ctlr_mode.attr,
 591        NULL,
 592};
 593
 594static struct attribute_group fcoe_ctlr_attr_group = {
 595        .attrs = fcoe_ctlr_attrs,
 596};
 597
 598static const struct attribute_group *fcoe_ctlr_attr_groups[] = {
 599        &fcoe_ctlr_attr_group,
 600        &fcoe_ctlr_lesb_attr_group,
 601        NULL,
 602};
 603
 604static struct attribute *fcoe_fcf_attrs[] = {
 605        &device_attr_fcoe_fcf_fabric_name.attr,
 606        &device_attr_fcoe_fcf_switch_name.attr,
 607        &device_attr_fcoe_fcf_dev_loss_tmo.attr,
 608        &device_attr_fcoe_fcf_fc_map.attr,
 609        &device_attr_fcoe_fcf_vfid.attr,
 610        &device_attr_fcoe_fcf_mac.attr,
 611        &device_attr_fcoe_fcf_priority.attr,
 612        &device_attr_fcoe_fcf_fka_period.attr,
 613        &device_attr_fcoe_fcf_state.attr,
 614        &device_attr_fcoe_fcf_selected.attr,
 615        &device_attr_fcoe_fcf_vlan_id.attr,
 616        NULL
 617};
 618
 619static struct attribute_group fcoe_fcf_attr_group = {
 620        .attrs = fcoe_fcf_attrs,
 621};
 622
 623static const struct attribute_group *fcoe_fcf_attr_groups[] = {
 624        &fcoe_fcf_attr_group,
 625        NULL,
 626};
 627
 628static struct bus_type fcoe_bus_type;
 629
 630static int fcoe_bus_match(struct device *dev,
 631                          struct device_driver *drv)
 632{
 633        if (dev->bus == &fcoe_bus_type)
 634                return 1;
 635        return 0;
 636}
 637
 638/**
 639 * fcoe_ctlr_device_release() - Release the FIP ctlr memory
 640 * @dev: Pointer to the FIP ctlr's embedded device
 641 *
 642 * Called when the last FIP ctlr reference is released.
 643 */
 644static void fcoe_ctlr_device_release(struct device *dev)
 645{
 646        struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
 647        kfree(ctlr);
 648}
 649
 650/**
 651 * fcoe_fcf_device_release() - Release the FIP fcf memory
 652 * @dev: Pointer to the fcf's embedded device
 653 *
 654 * Called when the last FIP fcf reference is released.
 655 */
 656static void fcoe_fcf_device_release(struct device *dev)
 657{
 658        struct fcoe_fcf_device *fcf = dev_to_fcf(dev);
 659        kfree(fcf);
 660}
 661
 662static const struct device_type fcoe_ctlr_device_type = {
 663        .name = "fcoe_ctlr",
 664        .groups = fcoe_ctlr_attr_groups,
 665        .release = fcoe_ctlr_device_release,
 666};
 667
 668static const struct device_type fcoe_fcf_device_type = {
 669        .name = "fcoe_fcf",
 670        .groups = fcoe_fcf_attr_groups,
 671        .release = fcoe_fcf_device_release,
 672};
 673
 674static BUS_ATTR(ctlr_create, S_IWUSR, NULL, fcoe_ctlr_create_store);
 675static BUS_ATTR(ctlr_destroy, S_IWUSR, NULL, fcoe_ctlr_destroy_store);
 676
 677static struct attribute *fcoe_bus_attrs[] = {
 678        &bus_attr_ctlr_create.attr,
 679        &bus_attr_ctlr_destroy.attr,
 680        NULL,
 681};
 682ATTRIBUTE_GROUPS(fcoe_bus);
 683
 684static struct bus_type fcoe_bus_type = {
 685        .name = "fcoe",
 686        .match = &fcoe_bus_match,
 687        .bus_groups = fcoe_bus_groups,
 688};
 689
 690/**
 691 * fcoe_ctlr_device_flush_work() - Flush a FIP ctlr's workqueue
 692 * @ctlr: Pointer to the FIP ctlr whose workqueue is to be flushed
 693 */
 694static void fcoe_ctlr_device_flush_work(struct fcoe_ctlr_device *ctlr)
 695{
 696        if (!fcoe_ctlr_work_q(ctlr)) {
 697                printk(KERN_ERR
 698                       "ERROR: FIP Ctlr '%d' attempted to flush work, "
 699                       "when no workqueue created.\n", ctlr->id);
 700                dump_stack();
 701                return;
 702        }
 703
 704        flush_workqueue(fcoe_ctlr_work_q(ctlr));
 705}
 706
 707/**
 708 * fcoe_ctlr_device_queue_work() - Schedule work for a FIP ctlr's workqueue
 709 * @ctlr: Pointer to the FIP ctlr who owns the devloss workqueue
 710 * @work:   Work to queue for execution
 711 *
 712 * Return value:
 713 *      1 on success / 0 already queued / < 0 for error
 714 */
 715static int fcoe_ctlr_device_queue_work(struct fcoe_ctlr_device *ctlr,
 716                                       struct work_struct *work)
 717{
 718        if (unlikely(!fcoe_ctlr_work_q(ctlr))) {
 719                printk(KERN_ERR
 720                       "ERROR: FIP Ctlr '%d' attempted to queue work, "
 721                       "when no workqueue created.\n", ctlr->id);
 722                dump_stack();
 723
 724                return -EINVAL;
 725        }
 726
 727        return queue_work(fcoe_ctlr_work_q(ctlr), work);
 728}
 729
 730/**
 731 * fcoe_ctlr_device_flush_devloss() - Flush a FIP ctlr's devloss workqueue
 732 * @ctlr: Pointer to FIP ctlr whose workqueue is to be flushed
 733 */
 734static void fcoe_ctlr_device_flush_devloss(struct fcoe_ctlr_device *ctlr)
 735{
 736        if (!fcoe_ctlr_devloss_work_q(ctlr)) {
 737                printk(KERN_ERR
 738                       "ERROR: FIP Ctlr '%d' attempted to flush work, "
 739                       "when no workqueue created.\n", ctlr->id);
 740                dump_stack();
 741                return;
 742        }
 743
 744        flush_workqueue(fcoe_ctlr_devloss_work_q(ctlr));
 745}
 746
 747/**
 748 * fcoe_ctlr_device_queue_devloss_work() - Schedule work for a FIP ctlr's devloss workqueue
 749 * @ctlr: Pointer to the FIP ctlr who owns the devloss workqueue
 750 * @work:   Work to queue for execution
 751 * @delay:  jiffies to delay the work queuing
 752 *
 753 * Return value:
 754 *      1 on success / 0 already queued / < 0 for error
 755 */
 756static int fcoe_ctlr_device_queue_devloss_work(struct fcoe_ctlr_device *ctlr,
 757                                               struct delayed_work *work,
 758                                               unsigned long delay)
 759{
 760        if (unlikely(!fcoe_ctlr_devloss_work_q(ctlr))) {
 761                printk(KERN_ERR
 762                       "ERROR: FIP Ctlr '%d' attempted to queue work, "
 763                       "when no workqueue created.\n", ctlr->id);
 764                dump_stack();
 765
 766                return -EINVAL;
 767        }
 768
 769        return queue_delayed_work(fcoe_ctlr_devloss_work_q(ctlr), work, delay);
 770}
 771
 772static int fcoe_fcf_device_match(struct fcoe_fcf_device *new,
 773                                 struct fcoe_fcf_device *old)
 774{
 775        if (new->switch_name == old->switch_name &&
 776            new->fabric_name == old->fabric_name &&
 777            new->fc_map == old->fc_map &&
 778            ether_addr_equal(new->mac, old->mac))
 779                return 1;
 780        return 0;
 781}
 782
 783/**
 784 * fcoe_ctlr_device_add() - Add a FIP ctlr to sysfs
 785 * @parent:    The parent device to which the fcoe_ctlr instance
 786 *             should be attached
 787 * @f:         The LLD's FCoE sysfs function template pointer
 788 * @priv_size: Size to be allocated with the fcoe_ctlr_device for the LLD
 789 *
 790 * This routine allocates a FIP ctlr object with some additional memory
 791 * for the LLD. The FIP ctlr is initialized, added to sysfs and then
 792 * attributes are added to it.
 793 */
 794struct fcoe_ctlr_device *fcoe_ctlr_device_add(struct device *parent,
 795                                    struct fcoe_sysfs_function_template *f,
 796                                    int priv_size)
 797{
 798        struct fcoe_ctlr_device *ctlr;
 799        int error = 0;
 800
 801        ctlr = kzalloc(sizeof(struct fcoe_ctlr_device) + priv_size,
 802                       GFP_KERNEL);
 803        if (!ctlr)
 804                goto out;
 805
 806        ctlr->id = atomic_inc_return(&ctlr_num) - 1;
 807        ctlr->f = f;
 808        ctlr->mode = FIP_CONN_TYPE_FABRIC;
 809        INIT_LIST_HEAD(&ctlr->fcfs);
 810        mutex_init(&ctlr->lock);
 811        ctlr->dev.parent = parent;
 812        ctlr->dev.bus = &fcoe_bus_type;
 813        ctlr->dev.type = &fcoe_ctlr_device_type;
 814
 815        ctlr->fcf_dev_loss_tmo = fcoe_fcf_dev_loss_tmo;
 816
 817        snprintf(ctlr->work_q_name, sizeof(ctlr->work_q_name),
 818                 "ctlr_wq_%d", ctlr->id);
 819        ctlr->work_q = create_singlethread_workqueue(
 820                ctlr->work_q_name);
 821        if (!ctlr->work_q)
 822                goto out_del;
 823
 824        snprintf(ctlr->devloss_work_q_name,
 825                 sizeof(ctlr->devloss_work_q_name),
 826                 "ctlr_dl_wq_%d", ctlr->id);
 827        ctlr->devloss_work_q = create_singlethread_workqueue(
 828                ctlr->devloss_work_q_name);
 829        if (!ctlr->devloss_work_q)
 830                goto out_del_q;
 831
 832        dev_set_name(&ctlr->dev, "ctlr_%d", ctlr->id);
 833        error = device_register(&ctlr->dev);
 834        if (error)
 835                goto out_del_q2;
 836
 837        return ctlr;
 838
 839out_del_q2:
 840        destroy_workqueue(ctlr->devloss_work_q);
 841        ctlr->devloss_work_q = NULL;
 842out_del_q:
 843        destroy_workqueue(ctlr->work_q);
 844        ctlr->work_q = NULL;
 845out_del:
 846        kfree(ctlr);
 847out:
 848        return NULL;
 849}
 850EXPORT_SYMBOL_GPL(fcoe_ctlr_device_add);
 851
 852/**
 853 * fcoe_ctlr_device_delete() - Delete a FIP ctlr and its subtree from sysfs
 854 * @ctlr: A pointer to the ctlr to be deleted
 855 *
 856 * Deletes a FIP ctlr and any fcfs attached
 857 * to it. Deleting fcfs will cause their childen
 858 * to be deleted as well.
 859 *
 860 * The ctlr is detached from sysfs and it's resources
 861 * are freed (work q), but the memory is not freed
 862 * until its last reference is released.
 863 *
 864 * This routine expects no locks to be held before
 865 * calling.
 866 *
 867 * TODO: Currently there are no callbacks to clean up LLD data
 868 * for a fcoe_fcf_device. LLDs must keep this in mind as they need
 869 * to clean up each of their LLD data for all fcoe_fcf_device before
 870 * calling fcoe_ctlr_device_delete.
 871 */
 872void fcoe_ctlr_device_delete(struct fcoe_ctlr_device *ctlr)
 873{
 874        struct fcoe_fcf_device *fcf, *next;
 875        /* Remove any attached fcfs */
 876        mutex_lock(&ctlr->lock);
 877        list_for_each_entry_safe(fcf, next,
 878                                 &ctlr->fcfs, peers) {
 879                list_del(&fcf->peers);
 880                fcf->state = FCOE_FCF_STATE_DELETED;
 881                fcoe_ctlr_device_queue_work(ctlr, &fcf->delete_work);
 882        }
 883        mutex_unlock(&ctlr->lock);
 884
 885        fcoe_ctlr_device_flush_work(ctlr);
 886
 887        destroy_workqueue(ctlr->devloss_work_q);
 888        ctlr->devloss_work_q = NULL;
 889        destroy_workqueue(ctlr->work_q);
 890        ctlr->work_q = NULL;
 891
 892        device_unregister(&ctlr->dev);
 893}
 894EXPORT_SYMBOL_GPL(fcoe_ctlr_device_delete);
 895
 896/**
 897 * fcoe_fcf_device_final_delete() - Final delete routine
 898 * @work: The FIP fcf's embedded work struct
 899 *
 900 * It is expected that the fcf has been removed from
 901 * the FIP ctlr's list before calling this routine.
 902 */
 903static void fcoe_fcf_device_final_delete(struct work_struct *work)
 904{
 905        struct fcoe_fcf_device *fcf =
 906                container_of(work, struct fcoe_fcf_device, delete_work);
 907        struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf);
 908
 909        /*
 910         * Cancel any outstanding timers. These should really exist
 911         * only when rmmod'ing the LLDD and we're asking for
 912         * immediate termination of the rports
 913         */
 914        if (!cancel_delayed_work(&fcf->dev_loss_work))
 915                fcoe_ctlr_device_flush_devloss(ctlr);
 916
 917        device_unregister(&fcf->dev);
 918}
 919
 920/**
 921 * fip_timeout_deleted_fcf() - Delete a fcf when the devloss timer fires
 922 * @work: The FIP fcf's embedded work struct
 923 *
 924 * Removes the fcf from the FIP ctlr's list of fcfs and
 925 * queues the final deletion.
 926 */
 927static void fip_timeout_deleted_fcf(struct work_struct *work)
 928{
 929        struct fcoe_fcf_device *fcf =
 930                container_of(work, struct fcoe_fcf_device, dev_loss_work.work);
 931        struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf);
 932
 933        mutex_lock(&ctlr->lock);
 934
 935        /*
 936         * If the fcf is deleted or reconnected before the timer
 937         * fires the devloss queue will be flushed, but the state will
 938         * either be CONNECTED or DELETED. If that is the case we
 939         * cancel deleting the fcf.
 940         */
 941        if (fcf->state != FCOE_FCF_STATE_DISCONNECTED)
 942                goto out;
 943
 944        dev_printk(KERN_ERR, &fcf->dev,
 945                   "FIP fcf connection time out: removing fcf\n");
 946
 947        list_del(&fcf->peers);
 948        fcf->state = FCOE_FCF_STATE_DELETED;
 949        fcoe_ctlr_device_queue_work(ctlr, &fcf->delete_work);
 950
 951out:
 952        mutex_unlock(&ctlr->lock);
 953}
 954
 955/**
 956 * fcoe_fcf_device_delete() - Delete a FIP fcf
 957 * @fcf: Pointer to the fcf which is to be deleted
 958 *
 959 * Queues the FIP fcf on the devloss workqueue
 960 *
 961 * Expects the ctlr_attrs mutex to be held for fcf
 962 * state change.
 963 */
 964void fcoe_fcf_device_delete(struct fcoe_fcf_device *fcf)
 965{
 966        struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf);
 967        int timeout = fcf->dev_loss_tmo;
 968
 969        if (fcf->state != FCOE_FCF_STATE_CONNECTED)
 970                return;
 971
 972        fcf->state = FCOE_FCF_STATE_DISCONNECTED;
 973
 974        /*
 975         * FCF will only be re-connected by the LLD calling
 976         * fcoe_fcf_device_add, and it should be setting up
 977         * priv then.
 978         */
 979        fcf->priv = NULL;
 980
 981        fcoe_ctlr_device_queue_devloss_work(ctlr, &fcf->dev_loss_work,
 982                                           timeout * HZ);
 983}
 984EXPORT_SYMBOL_GPL(fcoe_fcf_device_delete);
 985
 986/**
 987 * fcoe_fcf_device_add() - Add a FCoE sysfs fcoe_fcf_device to the system
 988 * @ctlr:    The fcoe_ctlr_device that will be the fcoe_fcf_device parent
 989 * @new_fcf: A temporary FCF used for lookups on the current list of fcfs
 990 *
 991 * Expects to be called with the ctlr->lock held
 992 */
 993struct fcoe_fcf_device *fcoe_fcf_device_add(struct fcoe_ctlr_device *ctlr,
 994                                            struct fcoe_fcf_device *new_fcf)
 995{
 996        struct fcoe_fcf_device *fcf;
 997        int error = 0;
 998
 999        list_for_each_entry(fcf, &ctlr->fcfs, peers) {
1000                if (fcoe_fcf_device_match(new_fcf, fcf)) {
1001                        if (fcf->state == FCOE_FCF_STATE_CONNECTED)
1002                                return fcf;
1003
1004                        fcf->state = FCOE_FCF_STATE_CONNECTED;
1005
1006                        if (!cancel_delayed_work(&fcf->dev_loss_work))
1007                                fcoe_ctlr_device_flush_devloss(ctlr);
1008
1009                        return fcf;
1010                }
1011        }
1012
1013        fcf = kzalloc(sizeof(struct fcoe_fcf_device), GFP_ATOMIC);
1014        if (unlikely(!fcf))
1015                goto out;
1016
1017        INIT_WORK(&fcf->delete_work, fcoe_fcf_device_final_delete);
1018        INIT_DELAYED_WORK(&fcf->dev_loss_work, fip_timeout_deleted_fcf);
1019
1020        fcf->dev.parent = &ctlr->dev;
1021        fcf->dev.bus = &fcoe_bus_type;
1022        fcf->dev.type = &fcoe_fcf_device_type;
1023        fcf->id = atomic_inc_return(&fcf_num) - 1;
1024        fcf->state = FCOE_FCF_STATE_UNKNOWN;
1025
1026        fcf->dev_loss_tmo = ctlr->fcf_dev_loss_tmo;
1027
1028        dev_set_name(&fcf->dev, "fcf_%d", fcf->id);
1029
1030        fcf->fabric_name = new_fcf->fabric_name;
1031        fcf->switch_name = new_fcf->switch_name;
1032        fcf->fc_map = new_fcf->fc_map;
1033        fcf->vfid = new_fcf->vfid;
1034        memcpy(fcf->mac, new_fcf->mac, ETH_ALEN);
1035        fcf->priority = new_fcf->priority;
1036        fcf->fka_period = new_fcf->fka_period;
1037        fcf->selected = new_fcf->selected;
1038
1039        error = device_register(&fcf->dev);
1040        if (error)
1041                goto out_del;
1042
1043        fcf->state = FCOE_FCF_STATE_CONNECTED;
1044        list_add_tail(&fcf->peers, &ctlr->fcfs);
1045
1046        return fcf;
1047
1048out_del:
1049        kfree(fcf);
1050out:
1051        return NULL;
1052}
1053EXPORT_SYMBOL_GPL(fcoe_fcf_device_add);
1054
1055int __init fcoe_sysfs_setup(void)
1056{
1057        int error;
1058
1059        atomic_set(&ctlr_num, 0);
1060        atomic_set(&fcf_num, 0);
1061
1062        error = bus_register(&fcoe_bus_type);
1063        if (error)
1064                return error;
1065
1066        return 0;
1067}
1068
1069void __exit fcoe_sysfs_teardown(void)
1070{
1071        bus_unregister(&fcoe_bus_type);
1072}
1073