0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/types.h>
0010 #include <linux/kernel.h>
0011 #include <linux/etherdevice.h>
0012 #include <linux/ctype.h>
0013
0014 #include <scsi/fcoe_sysfs.h>
0015 #include <scsi/libfcoe.h>
0016
0017
0018
0019
0020
0021
0022 #include "libfcoe.h"
0023
0024 static atomic_t ctlr_num;
0025 static atomic_t fcf_num;
0026
0027
0028
0029
0030
0031 static unsigned int fcoe_fcf_dev_loss_tmo = 1800;
0032
0033 module_param_named(fcf_dev_loss_tmo, fcoe_fcf_dev_loss_tmo,
0034 uint, S_IRUGO|S_IWUSR);
0035 MODULE_PARM_DESC(fcf_dev_loss_tmo,
0036 "Maximum number of seconds that libfcoe should"
0037 " insulate the loss of a fcf. Once this value is"
0038 " exceeded, the fcf is removed.");
0039
0040
0041
0042
0043
0044
0045 #define fcoe_ctlr_id(x) \
0046 ((x)->id)
0047 #define fcoe_ctlr_work_q_name(x) \
0048 ((x)->work_q_name)
0049 #define fcoe_ctlr_work_q(x) \
0050 ((x)->work_q)
0051 #define fcoe_ctlr_devloss_work_q_name(x) \
0052 ((x)->devloss_work_q_name)
0053 #define fcoe_ctlr_devloss_work_q(x) \
0054 ((x)->devloss_work_q)
0055 #define fcoe_ctlr_mode(x) \
0056 ((x)->mode)
0057 #define fcoe_ctlr_fcf_dev_loss_tmo(x) \
0058 ((x)->fcf_dev_loss_tmo)
0059 #define fcoe_ctlr_link_fail(x) \
0060 ((x)->lesb.lesb_link_fail)
0061 #define fcoe_ctlr_vlink_fail(x) \
0062 ((x)->lesb.lesb_vlink_fail)
0063 #define fcoe_ctlr_miss_fka(x) \
0064 ((x)->lesb.lesb_miss_fka)
0065 #define fcoe_ctlr_symb_err(x) \
0066 ((x)->lesb.lesb_symb_err)
0067 #define fcoe_ctlr_err_block(x) \
0068 ((x)->lesb.lesb_err_block)
0069 #define fcoe_ctlr_fcs_error(x) \
0070 ((x)->lesb.lesb_fcs_error)
0071 #define fcoe_ctlr_enabled(x) \
0072 ((x)->enabled)
0073 #define fcoe_fcf_state(x) \
0074 ((x)->state)
0075 #define fcoe_fcf_fabric_name(x) \
0076 ((x)->fabric_name)
0077 #define fcoe_fcf_switch_name(x) \
0078 ((x)->switch_name)
0079 #define fcoe_fcf_fc_map(x) \
0080 ((x)->fc_map)
0081 #define fcoe_fcf_vfid(x) \
0082 ((x)->vfid)
0083 #define fcoe_fcf_mac(x) \
0084 ((x)->mac)
0085 #define fcoe_fcf_priority(x) \
0086 ((x)->priority)
0087 #define fcoe_fcf_fka_period(x) \
0088 ((x)->fka_period)
0089 #define fcoe_fcf_dev_loss_tmo(x) \
0090 ((x)->dev_loss_tmo)
0091 #define fcoe_fcf_selected(x) \
0092 ((x)->selected)
0093 #define fcoe_fcf_vlan_id(x) \
0094 ((x)->vlan_id)
0095
0096
0097
0098
0099 static int fcoe_str_to_dev_loss(const char *buf, unsigned long *val)
0100 {
0101 int ret;
0102
0103 ret = kstrtoul(buf, 0, val);
0104 if (ret)
0105 return -EINVAL;
0106
0107
0108
0109 if (*val > UINT_MAX)
0110 return -EINVAL;
0111
0112 return 0;
0113 }
0114
0115 static int fcoe_fcf_set_dev_loss_tmo(struct fcoe_fcf_device *fcf,
0116 unsigned long val)
0117 {
0118 if ((fcf->state == FCOE_FCF_STATE_UNKNOWN) ||
0119 (fcf->state == FCOE_FCF_STATE_DISCONNECTED) ||
0120 (fcf->state == FCOE_FCF_STATE_DELETED))
0121 return -EBUSY;
0122
0123
0124
0125 if (val > UINT_MAX)
0126 return -EINVAL;
0127
0128 fcoe_fcf_dev_loss_tmo(fcf) = val;
0129 return 0;
0130 }
0131
0132 #define FCOE_DEVICE_ATTR(_prefix, _name, _mode, _show, _store) \
0133 struct device_attribute device_attr_fcoe_##_prefix##_##_name = \
0134 __ATTR(_name, _mode, _show, _store)
0135
0136 #define fcoe_ctlr_show_function(field, format_string, sz, cast) \
0137 static ssize_t show_fcoe_ctlr_device_##field(struct device *dev, \
0138 struct device_attribute *attr, \
0139 char *buf) \
0140 { \
0141 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); \
0142 if (ctlr->f->get_fcoe_ctlr_##field) \
0143 ctlr->f->get_fcoe_ctlr_##field(ctlr); \
0144 return snprintf(buf, sz, format_string, \
0145 cast fcoe_ctlr_##field(ctlr)); \
0146 }
0147
0148 #define fcoe_fcf_show_function(field, format_string, sz, cast) \
0149 static ssize_t show_fcoe_fcf_device_##field(struct device *dev, \
0150 struct device_attribute *attr, \
0151 char *buf) \
0152 { \
0153 struct fcoe_fcf_device *fcf = dev_to_fcf(dev); \
0154 struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf); \
0155 if (ctlr->f->get_fcoe_fcf_##field) \
0156 ctlr->f->get_fcoe_fcf_##field(fcf); \
0157 return snprintf(buf, sz, format_string, \
0158 cast fcoe_fcf_##field(fcf)); \
0159 }
0160
0161 #define fcoe_ctlr_private_show_function(field, format_string, sz, cast) \
0162 static ssize_t show_fcoe_ctlr_device_##field(struct device *dev, \
0163 struct device_attribute *attr, \
0164 char *buf) \
0165 { \
0166 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); \
0167 return snprintf(buf, sz, format_string, cast fcoe_ctlr_##field(ctlr)); \
0168 }
0169
0170 #define fcoe_fcf_private_show_function(field, format_string, sz, cast) \
0171 static ssize_t show_fcoe_fcf_device_##field(struct device *dev, \
0172 struct device_attribute *attr, \
0173 char *buf) \
0174 { \
0175 struct fcoe_fcf_device *fcf = dev_to_fcf(dev); \
0176 return snprintf(buf, sz, format_string, cast fcoe_fcf_##field(fcf)); \
0177 }
0178
0179 #define fcoe_ctlr_private_rd_attr(field, format_string, sz) \
0180 fcoe_ctlr_private_show_function(field, format_string, sz, ) \
0181 static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO, \
0182 show_fcoe_ctlr_device_##field, NULL)
0183
0184 #define fcoe_ctlr_rd_attr(field, format_string, sz) \
0185 fcoe_ctlr_show_function(field, format_string, sz, ) \
0186 static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO, \
0187 show_fcoe_ctlr_device_##field, NULL)
0188
0189 #define fcoe_fcf_rd_attr(field, format_string, sz) \
0190 fcoe_fcf_show_function(field, format_string, sz, ) \
0191 static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO, \
0192 show_fcoe_fcf_device_##field, NULL)
0193
0194 #define fcoe_fcf_private_rd_attr(field, format_string, sz) \
0195 fcoe_fcf_private_show_function(field, format_string, sz, ) \
0196 static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO, \
0197 show_fcoe_fcf_device_##field, NULL)
0198
0199 #define fcoe_ctlr_private_rd_attr_cast(field, format_string, sz, cast) \
0200 fcoe_ctlr_private_show_function(field, format_string, sz, (cast)) \
0201 static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO, \
0202 show_fcoe_ctlr_device_##field, NULL)
0203
0204 #define fcoe_fcf_private_rd_attr_cast(field, format_string, sz, cast) \
0205 fcoe_fcf_private_show_function(field, format_string, sz, (cast)) \
0206 static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO, \
0207 show_fcoe_fcf_device_##field, NULL)
0208
0209 #define fcoe_enum_name_search(title, table_type, table) \
0210 static const char *get_fcoe_##title##_name(enum table_type table_key) \
0211 { \
0212 if (table_key < 0 || table_key >= ARRAY_SIZE(table)) \
0213 return NULL; \
0214 return table[table_key]; \
0215 }
0216
0217 static char *fip_conn_type_names[] = {
0218 [ FIP_CONN_TYPE_UNKNOWN ] = "Unknown",
0219 [ FIP_CONN_TYPE_FABRIC ] = "Fabric",
0220 [ FIP_CONN_TYPE_VN2VN ] = "VN2VN",
0221 };
0222 fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names)
0223
0224 static enum fip_conn_type fcoe_parse_mode(const char *buf)
0225 {
0226 int i;
0227
0228 for (i = 0; i < ARRAY_SIZE(fip_conn_type_names); i++) {
0229 if (strcasecmp(buf, fip_conn_type_names[i]) == 0)
0230 return i;
0231 }
0232
0233 return FIP_CONN_TYPE_UNKNOWN;
0234 }
0235
0236 static char *fcf_state_names[] = {
0237 [ FCOE_FCF_STATE_UNKNOWN ] = "Unknown",
0238 [ FCOE_FCF_STATE_DISCONNECTED ] = "Disconnected",
0239 [ FCOE_FCF_STATE_CONNECTED ] = "Connected",
0240 };
0241 fcoe_enum_name_search(fcf_state, fcf_state, fcf_state_names)
0242 #define FCOE_FCF_STATE_MAX_NAMELEN 50
0243
0244 static ssize_t show_fcf_state(struct device *dev,
0245 struct device_attribute *attr,
0246 char *buf)
0247 {
0248 struct fcoe_fcf_device *fcf = dev_to_fcf(dev);
0249 const char *name;
0250 name = get_fcoe_fcf_state_name(fcf->state);
0251 if (!name)
0252 return -EINVAL;
0253 return snprintf(buf, FCOE_FCF_STATE_MAX_NAMELEN, "%s\n", name);
0254 }
0255 static FCOE_DEVICE_ATTR(fcf, state, S_IRUGO, show_fcf_state, NULL);
0256
0257 #define FCOE_MAX_MODENAME_LEN 20
0258 static ssize_t show_ctlr_mode(struct device *dev,
0259 struct device_attribute *attr,
0260 char *buf)
0261 {
0262 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
0263 const char *name;
0264
0265 name = get_fcoe_ctlr_mode_name(ctlr->mode);
0266 if (!name)
0267 return -EINVAL;
0268 return snprintf(buf, FCOE_MAX_MODENAME_LEN,
0269 "%s\n", name);
0270 }
0271
0272 static ssize_t store_ctlr_mode(struct device *dev,
0273 struct device_attribute *attr,
0274 const char *buf, size_t count)
0275 {
0276 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
0277 char mode[FCOE_MAX_MODENAME_LEN + 1];
0278
0279 if (count > FCOE_MAX_MODENAME_LEN)
0280 return -EINVAL;
0281
0282 strncpy(mode, buf, count);
0283
0284 if (mode[count - 1] == '\n')
0285 mode[count - 1] = '\0';
0286 else
0287 mode[count] = '\0';
0288
0289 switch (ctlr->enabled) {
0290 case FCOE_CTLR_ENABLED:
0291 LIBFCOE_SYSFS_DBG(ctlr, "Cannot change mode when enabled.\n");
0292 return -EBUSY;
0293 case FCOE_CTLR_DISABLED:
0294 if (!ctlr->f->set_fcoe_ctlr_mode) {
0295 LIBFCOE_SYSFS_DBG(ctlr,
0296 "Mode change not supported by LLD.\n");
0297 return -ENOTSUPP;
0298 }
0299
0300 ctlr->mode = fcoe_parse_mode(mode);
0301 if (ctlr->mode == FIP_CONN_TYPE_UNKNOWN) {
0302 LIBFCOE_SYSFS_DBG(ctlr, "Unknown mode %s provided.\n",
0303 buf);
0304 return -EINVAL;
0305 }
0306
0307 ctlr->f->set_fcoe_ctlr_mode(ctlr);
0308 LIBFCOE_SYSFS_DBG(ctlr, "Mode changed to %s.\n", buf);
0309
0310 return count;
0311 case FCOE_CTLR_UNUSED:
0312 default:
0313 LIBFCOE_SYSFS_DBG(ctlr, "Mode change not supported.\n");
0314 return -ENOTSUPP;
0315 }
0316 }
0317
0318 static FCOE_DEVICE_ATTR(ctlr, mode, S_IRUGO | S_IWUSR,
0319 show_ctlr_mode, store_ctlr_mode);
0320
0321 static ssize_t store_ctlr_enabled(struct device *dev,
0322 struct device_attribute *attr,
0323 const char *buf, size_t count)
0324 {
0325 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
0326 bool enabled;
0327 int rc;
0328
0329 if (*buf == '1')
0330 enabled = true;
0331 else if (*buf == '0')
0332 enabled = false;
0333 else
0334 return -EINVAL;
0335
0336 switch (ctlr->enabled) {
0337 case FCOE_CTLR_ENABLED:
0338 if (enabled)
0339 return count;
0340 ctlr->enabled = FCOE_CTLR_DISABLED;
0341 break;
0342 case FCOE_CTLR_DISABLED:
0343 if (!enabled)
0344 return count;
0345 ctlr->enabled = FCOE_CTLR_ENABLED;
0346 break;
0347 case FCOE_CTLR_UNUSED:
0348 return -ENOTSUPP;
0349 }
0350
0351 rc = ctlr->f->set_fcoe_ctlr_enabled(ctlr);
0352 if (rc)
0353 return rc;
0354
0355 return count;
0356 }
0357
0358 static char *ctlr_enabled_state_names[] = {
0359 [ FCOE_CTLR_ENABLED ] = "1",
0360 [ FCOE_CTLR_DISABLED ] = "0",
0361 };
0362 fcoe_enum_name_search(ctlr_enabled_state, ctlr_enabled_state,
0363 ctlr_enabled_state_names)
0364 #define FCOE_CTLR_ENABLED_MAX_NAMELEN 50
0365
0366 static ssize_t show_ctlr_enabled_state(struct device *dev,
0367 struct device_attribute *attr,
0368 char *buf)
0369 {
0370 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
0371 const char *name;
0372
0373 name = get_fcoe_ctlr_enabled_state_name(ctlr->enabled);
0374 if (!name)
0375 return -EINVAL;
0376 return snprintf(buf, FCOE_CTLR_ENABLED_MAX_NAMELEN,
0377 "%s\n", name);
0378 }
0379
0380 static FCOE_DEVICE_ATTR(ctlr, enabled, S_IRUGO | S_IWUSR,
0381 show_ctlr_enabled_state,
0382 store_ctlr_enabled);
0383
0384 static ssize_t store_ctlr_fip_resp(struct device *dev,
0385 struct device_attribute *attr,
0386 const char *buf, size_t count)
0387 {
0388 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
0389 struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr);
0390
0391 mutex_lock(&fip->ctlr_mutex);
0392 if ((buf[1] == '\0') || ((buf[1] == '\n') && (buf[2] == '\0'))) {
0393 if (buf[0] == '1') {
0394 fip->fip_resp = 1;
0395 mutex_unlock(&fip->ctlr_mutex);
0396 return count;
0397 }
0398 if (buf[0] == '0') {
0399 fip->fip_resp = 0;
0400 mutex_unlock(&fip->ctlr_mutex);
0401 return count;
0402 }
0403 }
0404 mutex_unlock(&fip->ctlr_mutex);
0405 return -EINVAL;
0406 }
0407
0408 static ssize_t show_ctlr_fip_resp(struct device *dev,
0409 struct device_attribute *attr,
0410 char *buf)
0411 {
0412 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
0413 struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr);
0414
0415 return sprintf(buf, "%d\n", fip->fip_resp ? 1 : 0);
0416 }
0417
0418 static FCOE_DEVICE_ATTR(ctlr, fip_vlan_responder, S_IRUGO | S_IWUSR,
0419 show_ctlr_fip_resp,
0420 store_ctlr_fip_resp);
0421
0422 static ssize_t
0423 fcoe_ctlr_var_store(u32 *var, const char *buf, size_t count)
0424 {
0425 int err;
0426 unsigned long v;
0427
0428 err = kstrtoul(buf, 10, &v);
0429 if (err || v > UINT_MAX)
0430 return -EINVAL;
0431
0432 *var = v;
0433
0434 return count;
0435 }
0436
0437 static ssize_t store_ctlr_r_a_tov(struct device *dev,
0438 struct device_attribute *attr,
0439 const char *buf, size_t count)
0440 {
0441 struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
0442 struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
0443
0444 if (ctlr_dev->enabled == FCOE_CTLR_ENABLED)
0445 return -EBUSY;
0446 if (ctlr_dev->enabled == FCOE_CTLR_DISABLED)
0447 return fcoe_ctlr_var_store(&ctlr->lp->r_a_tov, buf, count);
0448 return -ENOTSUPP;
0449 }
0450
0451 static ssize_t show_ctlr_r_a_tov(struct device *dev,
0452 struct device_attribute *attr,
0453 char *buf)
0454 {
0455 struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
0456 struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
0457
0458 return sprintf(buf, "%d\n", ctlr->lp->r_a_tov);
0459 }
0460
0461 static FCOE_DEVICE_ATTR(ctlr, r_a_tov, S_IRUGO | S_IWUSR,
0462 show_ctlr_r_a_tov, store_ctlr_r_a_tov);
0463
0464 static ssize_t store_ctlr_e_d_tov(struct device *dev,
0465 struct device_attribute *attr,
0466 const char *buf, size_t count)
0467 {
0468 struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
0469 struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
0470
0471 if (ctlr_dev->enabled == FCOE_CTLR_ENABLED)
0472 return -EBUSY;
0473 if (ctlr_dev->enabled == FCOE_CTLR_DISABLED)
0474 return fcoe_ctlr_var_store(&ctlr->lp->e_d_tov, buf, count);
0475 return -ENOTSUPP;
0476 }
0477
0478 static ssize_t show_ctlr_e_d_tov(struct device *dev,
0479 struct device_attribute *attr,
0480 char *buf)
0481 {
0482 struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
0483 struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
0484
0485 return sprintf(buf, "%d\n", ctlr->lp->e_d_tov);
0486 }
0487
0488 static FCOE_DEVICE_ATTR(ctlr, e_d_tov, S_IRUGO | S_IWUSR,
0489 show_ctlr_e_d_tov, store_ctlr_e_d_tov);
0490
0491 static ssize_t
0492 store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev,
0493 struct device_attribute *attr,
0494 const char *buf, size_t count)
0495 {
0496 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
0497 struct fcoe_fcf_device *fcf;
0498 unsigned long val;
0499 int rc;
0500
0501 rc = fcoe_str_to_dev_loss(buf, &val);
0502 if (rc)
0503 return rc;
0504
0505 fcoe_ctlr_fcf_dev_loss_tmo(ctlr) = val;
0506 mutex_lock(&ctlr->lock);
0507 list_for_each_entry(fcf, &ctlr->fcfs, peers)
0508 fcoe_fcf_set_dev_loss_tmo(fcf, val);
0509 mutex_unlock(&ctlr->lock);
0510 return count;
0511 }
0512 fcoe_ctlr_private_show_function(fcf_dev_loss_tmo, "%d\n", 20, );
0513 static FCOE_DEVICE_ATTR(ctlr, fcf_dev_loss_tmo, S_IRUGO | S_IWUSR,
0514 show_fcoe_ctlr_device_fcf_dev_loss_tmo,
0515 store_private_fcoe_ctlr_fcf_dev_loss_tmo);
0516
0517
0518 fcoe_ctlr_rd_attr(link_fail, "%u\n", 20);
0519 fcoe_ctlr_rd_attr(vlink_fail, "%u\n", 20);
0520 fcoe_ctlr_rd_attr(miss_fka, "%u\n", 20);
0521 fcoe_ctlr_rd_attr(symb_err, "%u\n", 20);
0522 fcoe_ctlr_rd_attr(err_block, "%u\n", 20);
0523 fcoe_ctlr_rd_attr(fcs_error, "%u\n", 20);
0524
0525 fcoe_fcf_private_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long);
0526 fcoe_fcf_private_rd_attr_cast(switch_name, "0x%llx\n", 20, unsigned long long);
0527 fcoe_fcf_private_rd_attr(priority, "%u\n", 20);
0528 fcoe_fcf_private_rd_attr(fc_map, "0x%x\n", 20);
0529 fcoe_fcf_private_rd_attr(vfid, "%u\n", 20);
0530 fcoe_fcf_private_rd_attr(mac, "%pM\n", 20);
0531 fcoe_fcf_private_rd_attr(fka_period, "%u\n", 20);
0532 fcoe_fcf_rd_attr(selected, "%u\n", 20);
0533 fcoe_fcf_rd_attr(vlan_id, "%u\n", 20);
0534
0535 fcoe_fcf_private_show_function(dev_loss_tmo, "%d\n", 20, )
0536 static ssize_t
0537 store_fcoe_fcf_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
0538 const char *buf, size_t count)
0539 {
0540 struct fcoe_fcf_device *fcf = dev_to_fcf(dev);
0541 unsigned long val;
0542 int rc;
0543
0544 rc = fcoe_str_to_dev_loss(buf, &val);
0545 if (rc)
0546 return rc;
0547
0548 rc = fcoe_fcf_set_dev_loss_tmo(fcf, val);
0549 if (rc)
0550 return rc;
0551 return count;
0552 }
0553 static FCOE_DEVICE_ATTR(fcf, dev_loss_tmo, S_IRUGO | S_IWUSR,
0554 show_fcoe_fcf_device_dev_loss_tmo,
0555 store_fcoe_fcf_dev_loss_tmo);
0556
0557 static struct attribute *fcoe_ctlr_lesb_attrs[] = {
0558 &device_attr_fcoe_ctlr_link_fail.attr,
0559 &device_attr_fcoe_ctlr_vlink_fail.attr,
0560 &device_attr_fcoe_ctlr_miss_fka.attr,
0561 &device_attr_fcoe_ctlr_symb_err.attr,
0562 &device_attr_fcoe_ctlr_err_block.attr,
0563 &device_attr_fcoe_ctlr_fcs_error.attr,
0564 NULL,
0565 };
0566
0567 static struct attribute_group fcoe_ctlr_lesb_attr_group = {
0568 .name = "lesb",
0569 .attrs = fcoe_ctlr_lesb_attrs,
0570 };
0571
0572 static struct attribute *fcoe_ctlr_attrs[] = {
0573 &device_attr_fcoe_ctlr_fip_vlan_responder.attr,
0574 &device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr,
0575 &device_attr_fcoe_ctlr_r_a_tov.attr,
0576 &device_attr_fcoe_ctlr_e_d_tov.attr,
0577 &device_attr_fcoe_ctlr_enabled.attr,
0578 &device_attr_fcoe_ctlr_mode.attr,
0579 NULL,
0580 };
0581
0582 static struct attribute_group fcoe_ctlr_attr_group = {
0583 .attrs = fcoe_ctlr_attrs,
0584 };
0585
0586 static const struct attribute_group *fcoe_ctlr_attr_groups[] = {
0587 &fcoe_ctlr_attr_group,
0588 &fcoe_ctlr_lesb_attr_group,
0589 NULL,
0590 };
0591
0592 static struct attribute *fcoe_fcf_attrs[] = {
0593 &device_attr_fcoe_fcf_fabric_name.attr,
0594 &device_attr_fcoe_fcf_switch_name.attr,
0595 &device_attr_fcoe_fcf_dev_loss_tmo.attr,
0596 &device_attr_fcoe_fcf_fc_map.attr,
0597 &device_attr_fcoe_fcf_vfid.attr,
0598 &device_attr_fcoe_fcf_mac.attr,
0599 &device_attr_fcoe_fcf_priority.attr,
0600 &device_attr_fcoe_fcf_fka_period.attr,
0601 &device_attr_fcoe_fcf_state.attr,
0602 &device_attr_fcoe_fcf_selected.attr,
0603 &device_attr_fcoe_fcf_vlan_id.attr,
0604 NULL
0605 };
0606
0607 static struct attribute_group fcoe_fcf_attr_group = {
0608 .attrs = fcoe_fcf_attrs,
0609 };
0610
0611 static const struct attribute_group *fcoe_fcf_attr_groups[] = {
0612 &fcoe_fcf_attr_group,
0613 NULL,
0614 };
0615
0616 static struct bus_type fcoe_bus_type;
0617
0618 static int fcoe_bus_match(struct device *dev,
0619 struct device_driver *drv)
0620 {
0621 if (dev->bus == &fcoe_bus_type)
0622 return 1;
0623 return 0;
0624 }
0625
0626
0627
0628
0629
0630
0631
0632 static void fcoe_ctlr_device_release(struct device *dev)
0633 {
0634 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
0635 kfree(ctlr);
0636 }
0637
0638
0639
0640
0641
0642
0643
0644 static void fcoe_fcf_device_release(struct device *dev)
0645 {
0646 struct fcoe_fcf_device *fcf = dev_to_fcf(dev);
0647 kfree(fcf);
0648 }
0649
0650 static const struct device_type fcoe_ctlr_device_type = {
0651 .name = "fcoe_ctlr",
0652 .groups = fcoe_ctlr_attr_groups,
0653 .release = fcoe_ctlr_device_release,
0654 };
0655
0656 static const struct device_type fcoe_fcf_device_type = {
0657 .name = "fcoe_fcf",
0658 .groups = fcoe_fcf_attr_groups,
0659 .release = fcoe_fcf_device_release,
0660 };
0661
0662 static ssize_t ctlr_create_store(struct bus_type *bus, const char *buf,
0663 size_t count)
0664 {
0665 return fcoe_ctlr_create_store(bus, buf, count);
0666 }
0667 static BUS_ATTR_WO(ctlr_create);
0668
0669 static ssize_t ctlr_destroy_store(struct bus_type *bus, const char *buf,
0670 size_t count)
0671 {
0672 return fcoe_ctlr_destroy_store(bus, buf, count);
0673 }
0674 static BUS_ATTR_WO(ctlr_destroy);
0675
0676 static struct attribute *fcoe_bus_attrs[] = {
0677 &bus_attr_ctlr_create.attr,
0678 &bus_attr_ctlr_destroy.attr,
0679 NULL,
0680 };
0681 ATTRIBUTE_GROUPS(fcoe_bus);
0682
0683 static struct bus_type fcoe_bus_type = {
0684 .name = "fcoe",
0685 .match = &fcoe_bus_match,
0686 .bus_groups = fcoe_bus_groups,
0687 };
0688
0689
0690
0691
0692
0693 static void fcoe_ctlr_device_flush_work(struct fcoe_ctlr_device *ctlr)
0694 {
0695 if (!fcoe_ctlr_work_q(ctlr)) {
0696 printk(KERN_ERR
0697 "ERROR: FIP Ctlr '%d' attempted to flush work, "
0698 "when no workqueue created.\n", ctlr->id);
0699 dump_stack();
0700 return;
0701 }
0702
0703 flush_workqueue(fcoe_ctlr_work_q(ctlr));
0704 }
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714 static int fcoe_ctlr_device_queue_work(struct fcoe_ctlr_device *ctlr,
0715 struct work_struct *work)
0716 {
0717 if (unlikely(!fcoe_ctlr_work_q(ctlr))) {
0718 printk(KERN_ERR
0719 "ERROR: FIP Ctlr '%d' attempted to queue work, "
0720 "when no workqueue created.\n", ctlr->id);
0721 dump_stack();
0722
0723 return -EINVAL;
0724 }
0725
0726 return queue_work(fcoe_ctlr_work_q(ctlr), work);
0727 }
0728
0729
0730
0731
0732
0733 static void fcoe_ctlr_device_flush_devloss(struct fcoe_ctlr_device *ctlr)
0734 {
0735 if (!fcoe_ctlr_devloss_work_q(ctlr)) {
0736 printk(KERN_ERR
0737 "ERROR: FIP Ctlr '%d' attempted to flush work, "
0738 "when no workqueue created.\n", ctlr->id);
0739 dump_stack();
0740 return;
0741 }
0742
0743 flush_workqueue(fcoe_ctlr_devloss_work_q(ctlr));
0744 }
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754
0755 static int fcoe_ctlr_device_queue_devloss_work(struct fcoe_ctlr_device *ctlr,
0756 struct delayed_work *work,
0757 unsigned long delay)
0758 {
0759 if (unlikely(!fcoe_ctlr_devloss_work_q(ctlr))) {
0760 printk(KERN_ERR
0761 "ERROR: FIP Ctlr '%d' attempted to queue work, "
0762 "when no workqueue created.\n", ctlr->id);
0763 dump_stack();
0764
0765 return -EINVAL;
0766 }
0767
0768 return queue_delayed_work(fcoe_ctlr_devloss_work_q(ctlr), work, delay);
0769 }
0770
0771 static int fcoe_fcf_device_match(struct fcoe_fcf_device *new,
0772 struct fcoe_fcf_device *old)
0773 {
0774 if (new->switch_name == old->switch_name &&
0775 new->fabric_name == old->fabric_name &&
0776 new->fc_map == old->fc_map &&
0777 ether_addr_equal(new->mac, old->mac))
0778 return 1;
0779 return 0;
0780 }
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790
0791
0792
0793 struct fcoe_ctlr_device *fcoe_ctlr_device_add(struct device *parent,
0794 struct fcoe_sysfs_function_template *f,
0795 int priv_size)
0796 {
0797 struct fcoe_ctlr_device *ctlr;
0798 int error = 0;
0799
0800 ctlr = kzalloc(sizeof(struct fcoe_ctlr_device) + priv_size,
0801 GFP_KERNEL);
0802 if (!ctlr)
0803 goto out;
0804
0805 ctlr->id = atomic_inc_return(&ctlr_num) - 1;
0806 ctlr->f = f;
0807 ctlr->mode = FIP_CONN_TYPE_FABRIC;
0808 INIT_LIST_HEAD(&ctlr->fcfs);
0809 mutex_init(&ctlr->lock);
0810 ctlr->dev.parent = parent;
0811 ctlr->dev.bus = &fcoe_bus_type;
0812 ctlr->dev.type = &fcoe_ctlr_device_type;
0813
0814 ctlr->fcf_dev_loss_tmo = fcoe_fcf_dev_loss_tmo;
0815
0816 snprintf(ctlr->work_q_name, sizeof(ctlr->work_q_name),
0817 "ctlr_wq_%d", ctlr->id);
0818 ctlr->work_q = create_singlethread_workqueue(
0819 ctlr->work_q_name);
0820 if (!ctlr->work_q)
0821 goto out_del;
0822
0823 snprintf(ctlr->devloss_work_q_name,
0824 sizeof(ctlr->devloss_work_q_name),
0825 "ctlr_dl_wq_%d", ctlr->id);
0826 ctlr->devloss_work_q = create_singlethread_workqueue(
0827 ctlr->devloss_work_q_name);
0828 if (!ctlr->devloss_work_q)
0829 goto out_del_q;
0830
0831 dev_set_name(&ctlr->dev, "ctlr_%d", ctlr->id);
0832 error = device_register(&ctlr->dev);
0833 if (error)
0834 goto out_del_q2;
0835
0836 return ctlr;
0837
0838 out_del_q2:
0839 destroy_workqueue(ctlr->devloss_work_q);
0840 ctlr->devloss_work_q = NULL;
0841 out_del_q:
0842 destroy_workqueue(ctlr->work_q);
0843 ctlr->work_q = NULL;
0844 out_del:
0845 kfree(ctlr);
0846 out:
0847 return NULL;
0848 }
0849 EXPORT_SYMBOL_GPL(fcoe_ctlr_device_add);
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871 void fcoe_ctlr_device_delete(struct fcoe_ctlr_device *ctlr)
0872 {
0873 struct fcoe_fcf_device *fcf, *next;
0874
0875 mutex_lock(&ctlr->lock);
0876 list_for_each_entry_safe(fcf, next,
0877 &ctlr->fcfs, peers) {
0878 list_del(&fcf->peers);
0879 fcf->state = FCOE_FCF_STATE_DELETED;
0880 fcoe_ctlr_device_queue_work(ctlr, &fcf->delete_work);
0881 }
0882 mutex_unlock(&ctlr->lock);
0883
0884 fcoe_ctlr_device_flush_work(ctlr);
0885
0886 destroy_workqueue(ctlr->devloss_work_q);
0887 ctlr->devloss_work_q = NULL;
0888 destroy_workqueue(ctlr->work_q);
0889 ctlr->work_q = NULL;
0890
0891 device_unregister(&ctlr->dev);
0892 }
0893 EXPORT_SYMBOL_GPL(fcoe_ctlr_device_delete);
0894
0895
0896
0897
0898
0899
0900
0901
0902 static void fcoe_fcf_device_final_delete(struct work_struct *work)
0903 {
0904 struct fcoe_fcf_device *fcf =
0905 container_of(work, struct fcoe_fcf_device, delete_work);
0906 struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf);
0907
0908
0909
0910
0911
0912
0913 if (!cancel_delayed_work(&fcf->dev_loss_work))
0914 fcoe_ctlr_device_flush_devloss(ctlr);
0915
0916 device_unregister(&fcf->dev);
0917 }
0918
0919
0920
0921
0922
0923
0924
0925
0926 static void fip_timeout_deleted_fcf(struct work_struct *work)
0927 {
0928 struct fcoe_fcf_device *fcf =
0929 container_of(work, struct fcoe_fcf_device, dev_loss_work.work);
0930 struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf);
0931
0932 mutex_lock(&ctlr->lock);
0933
0934
0935
0936
0937
0938
0939
0940 if (fcf->state != FCOE_FCF_STATE_DISCONNECTED)
0941 goto out;
0942
0943 dev_printk(KERN_ERR, &fcf->dev,
0944 "FIP fcf connection time out: removing fcf\n");
0945
0946 list_del(&fcf->peers);
0947 fcf->state = FCOE_FCF_STATE_DELETED;
0948 fcoe_ctlr_device_queue_work(ctlr, &fcf->delete_work);
0949
0950 out:
0951 mutex_unlock(&ctlr->lock);
0952 }
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962
0963 void fcoe_fcf_device_delete(struct fcoe_fcf_device *fcf)
0964 {
0965 struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf);
0966 int timeout = fcf->dev_loss_tmo;
0967
0968 if (fcf->state != FCOE_FCF_STATE_CONNECTED)
0969 return;
0970
0971 fcf->state = FCOE_FCF_STATE_DISCONNECTED;
0972
0973
0974
0975
0976
0977
0978 fcf->priv = NULL;
0979
0980 fcoe_ctlr_device_queue_devloss_work(ctlr, &fcf->dev_loss_work,
0981 timeout * HZ);
0982 }
0983 EXPORT_SYMBOL_GPL(fcoe_fcf_device_delete);
0984
0985
0986
0987
0988
0989
0990
0991
0992 struct fcoe_fcf_device *fcoe_fcf_device_add(struct fcoe_ctlr_device *ctlr,
0993 struct fcoe_fcf_device *new_fcf)
0994 {
0995 struct fcoe_fcf_device *fcf;
0996 int error = 0;
0997
0998 list_for_each_entry(fcf, &ctlr->fcfs, peers) {
0999 if (fcoe_fcf_device_match(new_fcf, fcf)) {
1000 if (fcf->state == FCOE_FCF_STATE_CONNECTED)
1001 return fcf;
1002
1003 fcf->state = FCOE_FCF_STATE_CONNECTED;
1004
1005 if (!cancel_delayed_work(&fcf->dev_loss_work))
1006 fcoe_ctlr_device_flush_devloss(ctlr);
1007
1008 return fcf;
1009 }
1010 }
1011
1012 fcf = kzalloc(sizeof(struct fcoe_fcf_device), GFP_ATOMIC);
1013 if (unlikely(!fcf))
1014 goto out;
1015
1016 INIT_WORK(&fcf->delete_work, fcoe_fcf_device_final_delete);
1017 INIT_DELAYED_WORK(&fcf->dev_loss_work, fip_timeout_deleted_fcf);
1018
1019 fcf->dev.parent = &ctlr->dev;
1020 fcf->dev.bus = &fcoe_bus_type;
1021 fcf->dev.type = &fcoe_fcf_device_type;
1022 fcf->id = atomic_inc_return(&fcf_num) - 1;
1023 fcf->state = FCOE_FCF_STATE_UNKNOWN;
1024
1025 fcf->dev_loss_tmo = ctlr->fcf_dev_loss_tmo;
1026
1027 dev_set_name(&fcf->dev, "fcf_%d", fcf->id);
1028
1029 fcf->fabric_name = new_fcf->fabric_name;
1030 fcf->switch_name = new_fcf->switch_name;
1031 fcf->fc_map = new_fcf->fc_map;
1032 fcf->vfid = new_fcf->vfid;
1033 memcpy(fcf->mac, new_fcf->mac, ETH_ALEN);
1034 fcf->priority = new_fcf->priority;
1035 fcf->fka_period = new_fcf->fka_period;
1036 fcf->selected = new_fcf->selected;
1037
1038 error = device_register(&fcf->dev);
1039 if (error)
1040 goto out_del;
1041
1042 fcf->state = FCOE_FCF_STATE_CONNECTED;
1043 list_add_tail(&fcf->peers, &ctlr->fcfs);
1044
1045 return fcf;
1046
1047 out_del:
1048 kfree(fcf);
1049 out:
1050 return NULL;
1051 }
1052 EXPORT_SYMBOL_GPL(fcoe_fcf_device_add);
1053
1054 int __init fcoe_sysfs_setup(void)
1055 {
1056 atomic_set(&ctlr_num, 0);
1057 atomic_set(&fcf_num, 0);
1058
1059 return bus_register(&fcoe_bus_type);
1060 }
1061
1062 void __exit fcoe_sysfs_teardown(void)
1063 {
1064 bus_unregister(&fcoe_bus_type);
1065 }