aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/fcoe_sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/fcoe/fcoe_sysfs.c')
-rw-r--r--drivers/scsi/fcoe/fcoe_sysfs.c186
1 files changed, 152 insertions, 34 deletions
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index 5e751689a089..8c05ae017f5b 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -21,8 +21,17 @@
21#include <linux/types.h> 21#include <linux/types.h>
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/etherdevice.h> 23#include <linux/etherdevice.h>
24#include <linux/ctype.h>
24 25
25#include <scsi/fcoe_sysfs.h> 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"
26 35
27static atomic_t ctlr_num; 36static atomic_t ctlr_num;
28static atomic_t fcf_num; 37static atomic_t fcf_num;
@@ -71,6 +80,8 @@ MODULE_PARM_DESC(fcf_dev_loss_tmo,
71 ((x)->lesb.lesb_err_block) 80 ((x)->lesb.lesb_err_block)
72#define fcoe_ctlr_fcs_error(x) \ 81#define fcoe_ctlr_fcs_error(x) \
73 ((x)->lesb.lesb_fcs_error) 82 ((x)->lesb.lesb_fcs_error)
83#define fcoe_ctlr_enabled(x) \
84 ((x)->enabled)
74#define fcoe_fcf_state(x) \ 85#define fcoe_fcf_state(x) \
75 ((x)->state) 86 ((x)->state)
76#define fcoe_fcf_fabric_name(x) \ 87#define fcoe_fcf_fabric_name(x) \
@@ -210,25 +221,34 @@ static ssize_t show_fcoe_fcf_device_##field(struct device *dev, \
210#define fcoe_enum_name_search(title, table_type, table) \ 221#define fcoe_enum_name_search(title, table_type, table) \
211static const char *get_fcoe_##title##_name(enum table_type table_key) \ 222static const char *get_fcoe_##title##_name(enum table_type table_key) \
212{ \ 223{ \
213 int i; \ 224 if (table_key < 0 || table_key >= ARRAY_SIZE(table)) \
214 char *name = NULL; \ 225 return NULL; \
215 \ 226 return table[table_key]; \
216 for (i = 0; i < ARRAY_SIZE(table); i++) { \ 227}
217 if (table[i].value == table_key) { \ 228
218 name = table[i].name; \ 229static char *fip_conn_type_names[] = {
219 break; \ 230 [ FIP_CONN_TYPE_UNKNOWN ] = "Unknown",
220 } \ 231 [ FIP_CONN_TYPE_FABRIC ] = "Fabric",
221 } \ 232 [ FIP_CONN_TYPE_VN2VN ] = "VN2VN",
222 return name; \ 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;
223} 246}
224 247
225static struct { 248static char *fcf_state_names[] = {
226 enum fcf_state value; 249 [ FCOE_FCF_STATE_UNKNOWN ] = "Unknown",
227 char *name; 250 [ FCOE_FCF_STATE_DISCONNECTED ] = "Disconnected",
228} fcf_state_names[] = { 251 [ FCOE_FCF_STATE_CONNECTED ] = "Connected",
229 { FCOE_FCF_STATE_UNKNOWN, "Unknown" },
230 { FCOE_FCF_STATE_DISCONNECTED, "Disconnected" },
231 { FCOE_FCF_STATE_CONNECTED, "Connected" },
232}; 252};
233fcoe_enum_name_search(fcf_state, fcf_state, fcf_state_names) 253fcoe_enum_name_search(fcf_state, fcf_state, fcf_state_names)
234#define FCOE_FCF_STATE_MAX_NAMELEN 50 254#define FCOE_FCF_STATE_MAX_NAMELEN 50
@@ -246,17 +266,7 @@ static ssize_t show_fcf_state(struct device *dev,
246} 266}
247static FCOE_DEVICE_ATTR(fcf, state, S_IRUGO, show_fcf_state, NULL); 267static FCOE_DEVICE_ATTR(fcf, state, S_IRUGO, show_fcf_state, NULL);
248 268
249static struct { 269#define FCOE_MAX_MODENAME_LEN 20
250 enum fip_conn_type value;
251 char *name;
252} fip_conn_type_names[] = {
253 { FIP_CONN_TYPE_UNKNOWN, "Unknown" },
254 { FIP_CONN_TYPE_FABRIC, "Fabric" },
255 { FIP_CONN_TYPE_VN2VN, "VN2VN" },
256};
257fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names)
258#define FCOE_CTLR_MODE_MAX_NAMELEN 50
259
260static ssize_t show_ctlr_mode(struct device *dev, 270static ssize_t show_ctlr_mode(struct device *dev,
261 struct device_attribute *attr, 271 struct device_attribute *attr,
262 char *buf) 272 char *buf)
@@ -264,17 +274,116 @@ static ssize_t show_ctlr_mode(struct device *dev,
264 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); 274 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
265 const char *name; 275 const char *name;
266 276
267 if (ctlr->f->get_fcoe_ctlr_mode)
268 ctlr->f->get_fcoe_ctlr_mode(ctlr);
269
270 name = get_fcoe_ctlr_mode_name(ctlr->mode); 277 name = get_fcoe_ctlr_mode_name(ctlr->mode);
271 if (!name) 278 if (!name)
272 return -EINVAL; 279 return -EINVAL;
273 return snprintf(buf, FCOE_CTLR_MODE_MAX_NAMELEN, 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.");
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.");
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,
315 "Unknown mode %s provided.", buf);
316 return -EINVAL;
317 }
318
319 ctlr->f->set_fcoe_ctlr_mode(ctlr);
320 LIBFCOE_SYSFS_DBG(ctlr, "Mode changed to %s.", buf);
321
322 return count;
323 case FCOE_CTLR_UNUSED:
324 default:
325 LIBFCOE_SYSFS_DBG(ctlr, "Mode change not supported.");
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 int rc;
339
340 switch (ctlr->enabled) {
341 case FCOE_CTLR_ENABLED:
342 if (*buf == '1')
343 return count;
344 ctlr->enabled = FCOE_CTLR_DISABLED;
345 break;
346 case FCOE_CTLR_DISABLED:
347 if (*buf == '0')
348 return count;
349 ctlr->enabled = FCOE_CTLR_ENABLED;
350 break;
351 case FCOE_CTLR_UNUSED:
352 return -ENOTSUPP;
353 };
354
355 rc = ctlr->f->set_fcoe_ctlr_enabled(ctlr);
356 if (rc)
357 return rc;
358
359 return count;
360}
361
362static char *ctlr_enabled_state_names[] = {
363 [ FCOE_CTLR_ENABLED ] = "1",
364 [ FCOE_CTLR_DISABLED ] = "0",
365};
366fcoe_enum_name_search(ctlr_enabled_state, ctlr_enabled_state,
367 ctlr_enabled_state_names)
368#define FCOE_CTLR_ENABLED_MAX_NAMELEN 50
369
370static ssize_t show_ctlr_enabled_state(struct device *dev,
371 struct device_attribute *attr,
372 char *buf)
373{
374 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
375 const char *name;
376
377 name = get_fcoe_ctlr_enabled_state_name(ctlr->enabled);
378 if (!name)
379 return -EINVAL;
380 return snprintf(buf, FCOE_CTLR_ENABLED_MAX_NAMELEN,
274 "%s\n", name); 381 "%s\n", name);
275} 382}
276static FCOE_DEVICE_ATTR(ctlr, mode, S_IRUGO, 383
277 show_ctlr_mode, NULL); 384static FCOE_DEVICE_ATTR(ctlr, enabled, S_IRUGO | S_IWUSR,
385 show_ctlr_enabled_state,
386 store_ctlr_enabled);
278 387
279static ssize_t 388static ssize_t
280store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev, 389store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev,
@@ -359,6 +468,7 @@ static struct attribute_group fcoe_ctlr_lesb_attr_group = {
359 468
360static struct attribute *fcoe_ctlr_attrs[] = { 469static struct attribute *fcoe_ctlr_attrs[] = {
361 &device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr, 470 &device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr,
471 &device_attr_fcoe_ctlr_enabled.attr,
362 &device_attr_fcoe_ctlr_mode.attr, 472 &device_attr_fcoe_ctlr_mode.attr,
363 NULL, 473 NULL,
364}; 474};
@@ -443,9 +553,16 @@ struct device_type fcoe_fcf_device_type = {
443 .release = fcoe_fcf_device_release, 553 .release = fcoe_fcf_device_release,
444}; 554};
445 555
556struct bus_attribute fcoe_bus_attr_group[] = {
557 __ATTR(ctlr_create, S_IWUSR, NULL, fcoe_ctlr_create_store),
558 __ATTR(ctlr_destroy, S_IWUSR, NULL, fcoe_ctlr_destroy_store),
559 __ATTR_NULL
560};
561
446struct bus_type fcoe_bus_type = { 562struct bus_type fcoe_bus_type = {
447 .name = "fcoe", 563 .name = "fcoe",
448 .match = &fcoe_bus_match, 564 .match = &fcoe_bus_match,
565 .bus_attrs = fcoe_bus_attr_group,
449}; 566};
450 567
451/** 568/**
@@ -566,6 +683,7 @@ struct fcoe_ctlr_device *fcoe_ctlr_device_add(struct device *parent,
566 683
567 ctlr->id = atomic_inc_return(&ctlr_num) - 1; 684 ctlr->id = atomic_inc_return(&ctlr_num) - 1;
568 ctlr->f = f; 685 ctlr->f = f;
686 ctlr->mode = FIP_CONN_TYPE_FABRIC;
569 INIT_LIST_HEAD(&ctlr->fcfs); 687 INIT_LIST_HEAD(&ctlr->fcfs);
570 mutex_init(&ctlr->lock); 688 mutex_init(&ctlr->lock);
571 ctlr->dev.parent = parent; 689 ctlr->dev.parent = parent;