[SCSI] qla4xxx: ql4_os.c bugfixes
[deliverable/linux.git] / drivers / scsi / scsi_transport_fc.c
CommitLineData
1da177e4
LT
1/*
2 * FiberChannel transport specific attributes exported to sysfs.
3 *
4 * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * ========
21 *
a53eb5e0 22 * Copyright (C) 2004-2007 James Smart, Emulex Corporation
1da177e4
LT
23 * Rewrite for host, target, device, and remote port attributes,
24 * statistics, and service functions...
25 *
26 */
27#include <linux/module.h>
28#include <linux/init.h>
29#include <scsi/scsi_device.h>
30#include <scsi/scsi_host.h>
31#include <scsi/scsi_transport.h>
32#include <scsi/scsi_transport_fc.h>
c829c394 33#include <scsi/scsi_cmnd.h>
84314fd4
JS
34#include <linux/netlink.h>
35#include <net/netlink.h>
36#include <scsi/scsi_netlink_fc.h>
1da177e4
LT
37#include "scsi_priv.h"
38
aedf3497
JS
39static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
40
a53eb5e0
JS
41/*
42 * This is a temporary carrier for creating a vport. It will eventually
43 * be replaced by a real message definition for sgio or netlink.
44 *
45 * fc_vport_identifiers: This set of data contains all elements
46 * to uniquely identify and instantiate a FC virtual port.
47 *
48 * Notes:
49 * symbolic_name: The driver is to append the symbolic_name string data
50 * to the symbolic_node_name data that it generates by default.
51 * the resulting combination should then be registered with the switch.
52 * It is expected that things like Xen may stuff a VM title into
53 * this field.
54 */
55struct fc_vport_identifiers {
56 u64 node_name;
57 u64 port_name;
58 u32 roles;
59 bool disable;
60 enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */
61 char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
62};
63
64static int fc_vport_create(struct Scsi_Host *shost, int channel,
65 struct device *pdev, struct fc_vport_identifiers *ids,
66 struct fc_vport **vport);
67
1da177e4
LT
68/*
69 * Redefine so that we can have same named attributes in the
70 * sdev/starget/host objects.
71 */
72#define FC_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
73struct class_device_attribute class_device_attr_##_prefix##_##_name = \
74 __ATTR(_name,_mode,_show,_store)
75
76#define fc_enum_name_search(title, table_type, table) \
77static const char *get_fc_##title##_name(enum table_type table_key) \
78{ \
79 int i; \
80 char *name = NULL; \
81 \
6391a113 82 for (i = 0; i < ARRAY_SIZE(table); i++) { \
1da177e4
LT
83 if (table[i].value == table_key) { \
84 name = table[i].name; \
85 break; \
86 } \
87 } \
88 return name; \
89}
90
91#define fc_enum_name_match(title, table_type, table) \
92static int get_fc_##title##_match(const char *table_key, \
93 enum table_type *value) \
94{ \
95 int i; \
96 \
6391a113 97 for (i = 0; i < ARRAY_SIZE(table); i++) { \
1da177e4
LT
98 if (strncmp(table_key, table[i].name, \
99 table[i].matchlen) == 0) { \
100 *value = table[i].value; \
101 return 0; /* success */ \
102 } \
103 } \
104 return 1; /* failure */ \
105}
106
107
108/* Convert fc_port_type values to ascii string name */
109static struct {
110 enum fc_port_type value;
111 char *name;
112} fc_port_type_names[] = {
113 { FC_PORTTYPE_UNKNOWN, "Unknown" },
114 { FC_PORTTYPE_OTHER, "Other" },
115 { FC_PORTTYPE_NOTPRESENT, "Not Present" },
116 { FC_PORTTYPE_NPORT, "NPort (fabric via point-to-point)" },
117 { FC_PORTTYPE_NLPORT, "NLPort (fabric via loop)" },
118 { FC_PORTTYPE_LPORT, "LPort (private loop)" },
119 { FC_PORTTYPE_PTP, "Point-To-Point (direct nport connection" },
a53eb5e0 120 { FC_PORTTYPE_NPIV, "NPIV VPORT" },
1da177e4
LT
121};
122fc_enum_name_search(port_type, fc_port_type, fc_port_type_names)
123#define FC_PORTTYPE_MAX_NAMELEN 50
124
a53eb5e0
JS
125/* Reuse fc_port_type enum function for vport_type */
126#define get_fc_vport_type_name get_fc_port_type_name
127
1da177e4 128
84314fd4
JS
129/* Convert fc_host_event_code values to ascii string name */
130static const struct {
131 enum fc_host_event_code value;
132 char *name;
133} fc_host_event_code_names[] = {
134 { FCH_EVT_LIP, "lip" },
135 { FCH_EVT_LINKUP, "link_up" },
136 { FCH_EVT_LINKDOWN, "link_down" },
137 { FCH_EVT_LIPRESET, "lip_reset" },
138 { FCH_EVT_RSCN, "rscn" },
139 { FCH_EVT_ADAPTER_CHANGE, "adapter_chg" },
140 { FCH_EVT_PORT_UNKNOWN, "port_unknown" },
141 { FCH_EVT_PORT_ONLINE, "port_online" },
142 { FCH_EVT_PORT_OFFLINE, "port_offline" },
143 { FCH_EVT_PORT_FABRIC, "port_fabric" },
144 { FCH_EVT_LINK_UNKNOWN, "link_unknown" },
145 { FCH_EVT_VENDOR_UNIQUE, "vendor_unique" },
146};
147fc_enum_name_search(host_event_code, fc_host_event_code,
148 fc_host_event_code_names)
149#define FC_HOST_EVENT_CODE_MAX_NAMELEN 30
150
151
1da177e4
LT
152/* Convert fc_port_state values to ascii string name */
153static struct {
154 enum fc_port_state value;
155 char *name;
156} fc_port_state_names[] = {
157 { FC_PORTSTATE_UNKNOWN, "Unknown" },
158 { FC_PORTSTATE_NOTPRESENT, "Not Present" },
159 { FC_PORTSTATE_ONLINE, "Online" },
160 { FC_PORTSTATE_OFFLINE, "Offline" },
161 { FC_PORTSTATE_BLOCKED, "Blocked" },
162 { FC_PORTSTATE_BYPASSED, "Bypassed" },
163 { FC_PORTSTATE_DIAGNOSTICS, "Diagnostics" },
164 { FC_PORTSTATE_LINKDOWN, "Linkdown" },
165 { FC_PORTSTATE_ERROR, "Error" },
166 { FC_PORTSTATE_LOOPBACK, "Loopback" },
42e33148 167 { FC_PORTSTATE_DELETED, "Deleted" },
1da177e4
LT
168};
169fc_enum_name_search(port_state, fc_port_state, fc_port_state_names)
170#define FC_PORTSTATE_MAX_NAMELEN 20
171
172
a53eb5e0
JS
173/* Convert fc_vport_state values to ascii string name */
174static struct {
175 enum fc_vport_state value;
176 char *name;
177} fc_vport_state_names[] = {
178 { FC_VPORT_UNKNOWN, "Unknown" },
179 { FC_VPORT_ACTIVE, "Active" },
180 { FC_VPORT_DISABLED, "Disabled" },
181 { FC_VPORT_LINKDOWN, "Linkdown" },
182 { FC_VPORT_INITIALIZING, "Initializing" },
183 { FC_VPORT_NO_FABRIC_SUPP, "No Fabric Support" },
184 { FC_VPORT_NO_FABRIC_RSCS, "No Fabric Resources" },
185 { FC_VPORT_FABRIC_LOGOUT, "Fabric Logout" },
186 { FC_VPORT_FABRIC_REJ_WWN, "Fabric Rejected WWN" },
187 { FC_VPORT_FAILED, "VPort Failed" },
188};
189fc_enum_name_search(vport_state, fc_vport_state, fc_vport_state_names)
190#define FC_VPORTSTATE_MAX_NAMELEN 24
191
192/* Reuse fc_vport_state enum function for vport_last_state */
193#define get_fc_vport_last_state_name get_fc_vport_state_name
194
195
1da177e4 196/* Convert fc_tgtid_binding_type values to ascii string name */
0ad78200 197static const struct {
1da177e4
LT
198 enum fc_tgtid_binding_type value;
199 char *name;
200 int matchlen;
201} fc_tgtid_binding_type_names[] = {
202 { FC_TGTID_BIND_NONE, "none", 4 },
203 { FC_TGTID_BIND_BY_WWPN, "wwpn (World Wide Port Name)", 4 },
204 { FC_TGTID_BIND_BY_WWNN, "wwnn (World Wide Node Name)", 4 },
205 { FC_TGTID_BIND_BY_ID, "port_id (FC Address)", 7 },
206};
207fc_enum_name_search(tgtid_bind_type, fc_tgtid_binding_type,
208 fc_tgtid_binding_type_names)
209fc_enum_name_match(tgtid_bind_type, fc_tgtid_binding_type,
210 fc_tgtid_binding_type_names)
211#define FC_BINDTYPE_MAX_NAMELEN 30
212
213
214#define fc_bitfield_name_search(title, table) \
215static ssize_t \
216get_fc_##title##_names(u32 table_key, char *buf) \
217{ \
218 char *prefix = ""; \
219 ssize_t len = 0; \
220 int i; \
221 \
6391a113 222 for (i = 0; i < ARRAY_SIZE(table); i++) { \
1da177e4
LT
223 if (table[i].value & table_key) { \
224 len += sprintf(buf + len, "%s%s", \
225 prefix, table[i].name); \
226 prefix = ", "; \
227 } \
228 } \
229 len += sprintf(buf + len, "\n"); \
230 return len; \
231}
232
233
234/* Convert FC_COS bit values to ascii string name */
0ad78200 235static const struct {
1da177e4
LT
236 u32 value;
237 char *name;
238} fc_cos_names[] = {
239 { FC_COS_CLASS1, "Class 1" },
240 { FC_COS_CLASS2, "Class 2" },
241 { FC_COS_CLASS3, "Class 3" },
242 { FC_COS_CLASS4, "Class 4" },
243 { FC_COS_CLASS6, "Class 6" },
244};
245fc_bitfield_name_search(cos, fc_cos_names)
246
247
248/* Convert FC_PORTSPEED bit values to ascii string name */
0ad78200 249static const struct {
1da177e4
LT
250 u32 value;
251 char *name;
252} fc_port_speed_names[] = {
253 { FC_PORTSPEED_1GBIT, "1 Gbit" },
254 { FC_PORTSPEED_2GBIT, "2 Gbit" },
255 { FC_PORTSPEED_4GBIT, "4 Gbit" },
256 { FC_PORTSPEED_10GBIT, "10 Gbit" },
c3d2350a
JS
257 { FC_PORTSPEED_8GBIT, "8 Gbit" },
258 { FC_PORTSPEED_16GBIT, "16 Gbit" },
1da177e4
LT
259 { FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" },
260};
261fc_bitfield_name_search(port_speed, fc_port_speed_names)
262
263
264static int
265show_fc_fc4s (char *buf, u8 *fc4_list)
266{
267 int i, len=0;
268
269 for (i = 0; i < FC_FC4_LIST_SIZE; i++, fc4_list++)
270 len += sprintf(buf + len , "0x%02x ", *fc4_list);
271 len += sprintf(buf + len, "\n");
272 return len;
273}
274
275
a53eb5e0 276/* Convert FC_PORT_ROLE bit values to ascii string name */
0ad78200 277static const struct {
1da177e4
LT
278 u32 value;
279 char *name;
a53eb5e0
JS
280} fc_port_role_names[] = {
281 { FC_PORT_ROLE_FCP_TARGET, "FCP Target" },
282 { FC_PORT_ROLE_FCP_INITIATOR, "FCP Initiator" },
283 { FC_PORT_ROLE_IP_PORT, "IP Port" },
1da177e4 284};
a53eb5e0 285fc_bitfield_name_search(port_roles, fc_port_role_names)
1da177e4
LT
286
287/*
288 * Define roles that are specific to port_id. Values are relative to ROLE_MASK.
289 */
290#define FC_WELLKNOWN_PORTID_MASK 0xfffff0
291#define FC_WELLKNOWN_ROLE_MASK 0x00000f
292#define FC_FPORT_PORTID 0x00000e
293#define FC_FABCTLR_PORTID 0x00000d
294#define FC_DIRSRVR_PORTID 0x00000c
295#define FC_TIMESRVR_PORTID 0x00000b
296#define FC_MGMTSRVR_PORTID 0x00000a
297
298
c4028958
DH
299static void fc_timeout_deleted_rport(struct work_struct *work);
300static void fc_timeout_fail_rport_io(struct work_struct *work);
301static void fc_scsi_scan_rport(struct work_struct *work);
1da177e4
LT
302
303/*
304 * Attribute counts pre object type...
305 * Increase these values if you add attributes
306 */
307#define FC_STARGET_NUM_ATTRS 3
0f29b966 308#define FC_RPORT_NUM_ATTRS 10
a53eb5e0
JS
309#define FC_VPORT_NUM_ATTRS 9
310#define FC_HOST_NUM_ATTRS 21
1da177e4
LT
311
312struct fc_internal {
313 struct scsi_transport_template t;
314 struct fc_function_template *f;
315
316 /*
317 * For attributes : each object has :
318 * An array of the actual attributes structures
319 * An array of null-terminated pointers to the attribute
320 * structures - used for mid-layer interaction.
321 *
322 * The attribute containers for the starget and host are are
323 * part of the midlayer. As the remote port is specific to the
324 * fc transport, we must provide the attribute container.
325 */
326 struct class_device_attribute private_starget_attrs[
327 FC_STARGET_NUM_ATTRS];
328 struct class_device_attribute *starget_attrs[FC_STARGET_NUM_ATTRS + 1];
329
330 struct class_device_attribute private_host_attrs[FC_HOST_NUM_ATTRS];
331 struct class_device_attribute *host_attrs[FC_HOST_NUM_ATTRS + 1];
332
333 struct transport_container rport_attr_cont;
334 struct class_device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS];
335 struct class_device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1];
a53eb5e0
JS
336
337 struct transport_container vport_attr_cont;
338 struct class_device_attribute private_vport_attrs[FC_VPORT_NUM_ATTRS];
339 struct class_device_attribute *vport_attrs[FC_VPORT_NUM_ATTRS + 1];
1da177e4
LT
340};
341
342#define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t)
343
d0a7e574
JB
344static int fc_target_setup(struct transport_container *tc, struct device *dev,
345 struct class_device *cdev)
1da177e4
LT
346{
347 struct scsi_target *starget = to_scsi_target(dev);
348 struct fc_rport *rport = starget_to_rport(starget);
349
350 /*
351 * if parent is remote port, use values from remote port.
352 * Otherwise, this host uses the fc_transport, but not the
353 * remote port interface. As such, initialize to known non-values.
354 */
355 if (rport) {
356 fc_starget_node_name(starget) = rport->node_name;
357 fc_starget_port_name(starget) = rport->port_name;
358 fc_starget_port_id(starget) = rport->port_id;
359 } else {
360 fc_starget_node_name(starget) = -1;
361 fc_starget_port_name(starget) = -1;
362 fc_starget_port_id(starget) = -1;
363 }
364
365 return 0;
366}
367
368static DECLARE_TRANSPORT_CLASS(fc_transport_class,
369 "fc_transport",
370 fc_target_setup,
371 NULL,
372 NULL);
373
d0a7e574
JB
374static int fc_host_setup(struct transport_container *tc, struct device *dev,
375 struct class_device *cdev)
1da177e4
LT
376{
377 struct Scsi_Host *shost = dev_to_shost(dev);
aedf3497 378 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
1da177e4
LT
379
380 /*
381 * Set default values easily detected by the midlayer as
382 * failure cases. The scsi lldd is responsible for initializing
383 * all transport attributes to valid values per host.
384 */
aedf3497
JS
385 fc_host->node_name = -1;
386 fc_host->port_name = -1;
387 fc_host->permanent_port_name = -1;
388 fc_host->supported_classes = FC_COS_UNSPECIFIED;
389 memset(fc_host->supported_fc4s, 0,
390 sizeof(fc_host->supported_fc4s));
aedf3497
JS
391 fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN;
392 fc_host->maxframe_size = -1;
a53eb5e0 393 fc_host->max_npiv_vports = 0;
aedf3497
JS
394 memset(fc_host->serial_number, 0,
395 sizeof(fc_host->serial_number));
396
397 fc_host->port_id = -1;
398 fc_host->port_type = FC_PORTTYPE_UNKNOWN;
399 fc_host->port_state = FC_PORTSTATE_UNKNOWN;
400 memset(fc_host->active_fc4s, 0,
401 sizeof(fc_host->active_fc4s));
402 fc_host->speed = FC_PORTSPEED_UNKNOWN;
403 fc_host->fabric_name = -1;
b8d08210
JS
404 memset(fc_host->symbolic_name, 0, sizeof(fc_host->symbolic_name));
405 memset(fc_host->system_hostname, 0, sizeof(fc_host->system_hostname));
aedf3497
JS
406
407 fc_host->tgtid_bind_type = FC_TGTID_BIND_BY_WWPN;
408
409 INIT_LIST_HEAD(&fc_host->rports);
410 INIT_LIST_HEAD(&fc_host->rport_bindings);
a53eb5e0 411 INIT_LIST_HEAD(&fc_host->vports);
aedf3497
JS
412 fc_host->next_rport_number = 0;
413 fc_host->next_target_id = 0;
a53eb5e0
JS
414 fc_host->next_vport_number = 0;
415 fc_host->npiv_vports_inuse = 0;
aedf3497
JS
416
417 snprintf(fc_host->work_q_name, KOBJ_NAME_LEN, "fc_wq_%d",
418 shost->host_no);
419 fc_host->work_q = create_singlethread_workqueue(
420 fc_host->work_q_name);
421 if (!fc_host->work_q)
422 return -ENOMEM;
423
424 snprintf(fc_host->devloss_work_q_name, KOBJ_NAME_LEN, "fc_dl_%d",
425 shost->host_no);
426 fc_host->devloss_work_q = create_singlethread_workqueue(
427 fc_host->devloss_work_q_name);
428 if (!fc_host->devloss_work_q) {
429 destroy_workqueue(fc_host->work_q);
430 fc_host->work_q = NULL;
431 return -ENOMEM;
432 }
433
1da177e4
LT
434 return 0;
435}
436
437static DECLARE_TRANSPORT_CLASS(fc_host_class,
438 "fc_host",
439 fc_host_setup,
440 NULL,
441 NULL);
442
443/*
444 * Setup and Remove actions for remote ports are handled
445 * in the service functions below.
446 */
447static DECLARE_TRANSPORT_CLASS(fc_rport_class,
448 "fc_remote_ports",
449 NULL,
450 NULL,
451 NULL);
452
a53eb5e0
JS
453/*
454 * Setup and Remove actions for virtual ports are handled
455 * in the service functions below.
456 */
457static DECLARE_TRANSPORT_CLASS(fc_vport_class,
458 "fc_vports",
459 NULL,
460 NULL,
461 NULL);
462
1da177e4
LT
463/*
464 * Module Parameters
465 */
466
467/*
468 * dev_loss_tmo: the default number of seconds that the FC transport
469 * should insulate the loss of a remote port.
470 * The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.
471 */
1c9e16e4 472static unsigned int fc_dev_loss_tmo = 60; /* seconds */
1da177e4
LT
473
474module_param_named(dev_loss_tmo, fc_dev_loss_tmo, int, S_IRUGO|S_IWUSR);
475MODULE_PARM_DESC(dev_loss_tmo,
476 "Maximum number of seconds that the FC transport should"
477 " insulate the loss of a remote port. Once this value is"
478 " exceeded, the scsi target is removed. Value should be"
479 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT.");
480
84314fd4
JS
481/**
482 * Netlink Infrastructure
483 **/
484
485static atomic_t fc_event_seq;
486
487/**
488 * fc_get_event_number - Obtain the next sequential FC event number
489 *
490 * Notes:
491 * We could have inline'd this, but it would have required fc_event_seq to
492 * be exposed. For now, live with the subroutine call.
493 * Atomic used to avoid lock/unlock...
494 **/
495u32
496fc_get_event_number(void)
497{
498 return atomic_add_return(1, &fc_event_seq);
499}
500EXPORT_SYMBOL(fc_get_event_number);
501
502
503/**
504 * fc_host_post_event - called to post an even on an fc_host.
505 *
506 * @shost: host the event occurred on
507 * @event_number: fc event number obtained from get_fc_event_number()
508 * @event_code: fc_host event being posted
509 * @event_data: 32bits of data for the event being posted
510 *
511 * Notes:
512 * This routine assumes no locks are held on entry.
513 **/
514void
515fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
516 enum fc_host_event_code event_code, u32 event_data)
517{
518 struct sk_buff *skb;
519 struct nlmsghdr *nlh;
520 struct fc_nl_event *event;
521 const char *name;
522 u32 len, skblen;
523 int err;
524
525 if (!scsi_nl_sock) {
526 err = -ENOENT;
527 goto send_fail;
528 }
529
530 len = FC_NL_MSGALIGN(sizeof(*event));
531 skblen = NLMSG_SPACE(len);
532
533 skb = alloc_skb(skblen, GFP_KERNEL);
534 if (!skb) {
535 err = -ENOBUFS;
536 goto send_fail;
537 }
538
539 nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
540 skblen - sizeof(*nlh), 0);
541 if (!nlh) {
542 err = -ENOBUFS;
543 goto send_fail_skb;
544 }
545 event = NLMSG_DATA(nlh);
546
547 INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC,
548 FC_NL_ASYNC_EVENT, len);
549 event->seconds = get_seconds();
550 event->vendor_id = 0;
551 event->host_no = shost->host_no;
552 event->event_datalen = sizeof(u32); /* bytes */
553 event->event_num = event_number;
554 event->event_code = event_code;
555 event->event_data = event_data;
556
1b73c4bb
JB
557 err = nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS,
558 GFP_KERNEL);
84314fd4
JS
559 if (err && (err != -ESRCH)) /* filter no recipient errors */
560 /* nlmsg_multicast already kfree_skb'd */
561 goto send_fail;
562
563 return;
564
565send_fail_skb:
566 kfree_skb(skb);
567send_fail:
568 name = get_fc_host_event_code_name(event_code);
569 printk(KERN_WARNING
570 "%s: Dropped Event : host %d %s data 0x%08x - err %d\n",
571 __FUNCTION__, shost->host_no,
572 (name) ? name : "<unknown>", event_data, err);
573 return;
574}
575EXPORT_SYMBOL(fc_host_post_event);
576
577
578/**
579 * fc_host_post_vendor_event - called to post a vendor unique event on
580 * a fc_host
581 *
582 * @shost: host the event occurred on
583 * @event_number: fc event number obtained from get_fc_event_number()
584 * @data_len: amount, in bytes, of vendor unique data
585 * @data_buf: pointer to vendor unique data
586 *
587 * Notes:
588 * This routine assumes no locks are held on entry.
589 **/
590void
591fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
f14e2e29 592 u32 data_len, char * data_buf, u64 vendor_id)
84314fd4
JS
593{
594 struct sk_buff *skb;
595 struct nlmsghdr *nlh;
596 struct fc_nl_event *event;
597 u32 len, skblen;
598 int err;
599
600 if (!scsi_nl_sock) {
601 err = -ENOENT;
602 goto send_vendor_fail;
603 }
604
605 len = FC_NL_MSGALIGN(sizeof(*event) + data_len);
606 skblen = NLMSG_SPACE(len);
607
608 skb = alloc_skb(skblen, GFP_KERNEL);
609 if (!skb) {
610 err = -ENOBUFS;
611 goto send_vendor_fail;
612 }
613
614 nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
615 skblen - sizeof(*nlh), 0);
616 if (!nlh) {
617 err = -ENOBUFS;
618 goto send_vendor_fail_skb;
619 }
620 event = NLMSG_DATA(nlh);
621
622 INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC,
623 FC_NL_ASYNC_EVENT, len);
624 event->seconds = get_seconds();
625 event->vendor_id = vendor_id;
626 event->host_no = shost->host_no;
627 event->event_datalen = data_len; /* bytes */
628 event->event_num = event_number;
629 event->event_code = FCH_EVT_VENDOR_UNIQUE;
630 memcpy(&event->event_data, data_buf, data_len);
631
1b73c4bb
JB
632 err = nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS,
633 GFP_KERNEL);
84314fd4
JS
634 if (err && (err != -ESRCH)) /* filter no recipient errors */
635 /* nlmsg_multicast already kfree_skb'd */
636 goto send_vendor_fail;
637
638 return;
639
640send_vendor_fail_skb:
641 kfree_skb(skb);
642send_vendor_fail:
643 printk(KERN_WARNING
644 "%s: Dropped Event : host %d vendor_unique - err %d\n",
645 __FUNCTION__, shost->host_no, err);
646 return;
647}
648EXPORT_SYMBOL(fc_host_post_vendor_event);
649
650
1da177e4
LT
651
652static __init int fc_transport_init(void)
653{
84314fd4
JS
654 int error;
655
656 atomic_set(&fc_event_seq, 0);
657
658 error = transport_class_register(&fc_host_class);
a53eb5e0
JS
659 if (error)
660 return error;
661 error = transport_class_register(&fc_vport_class);
1da177e4
LT
662 if (error)
663 return error;
664 error = transport_class_register(&fc_rport_class);
665 if (error)
666 return error;
667 return transport_class_register(&fc_transport_class);
668}
669
670static void __exit fc_transport_exit(void)
671{
672 transport_class_unregister(&fc_transport_class);
673 transport_class_unregister(&fc_rport_class);
674 transport_class_unregister(&fc_host_class);
a53eb5e0 675 transport_class_unregister(&fc_vport_class);
1da177e4
LT
676}
677
678/*
679 * FC Remote Port Attribute Management
680 */
681
682#define fc_rport_show_function(field, format_string, sz, cast) \
683static ssize_t \
684show_fc_rport_##field (struct class_device *cdev, char *buf) \
685{ \
686 struct fc_rport *rport = transport_class_to_rport(cdev); \
687 struct Scsi_Host *shost = rport_to_shost(rport); \
688 struct fc_internal *i = to_fc_internal(shost->transportt); \
19a7b4ae
JSEC
689 if ((i->f->get_rport_##field) && \
690 !((rport->port_state == FC_PORTSTATE_BLOCKED) || \
42e33148 691 (rport->port_state == FC_PORTSTATE_DELETED) || \
19a7b4ae 692 (rport->port_state == FC_PORTSTATE_NOTPRESENT))) \
1da177e4
LT
693 i->f->get_rport_##field(rport); \
694 return snprintf(buf, sz, format_string, cast rport->field); \
695}
696
697#define fc_rport_store_function(field) \
698static ssize_t \
699store_fc_rport_##field(struct class_device *cdev, const char *buf, \
700 size_t count) \
701{ \
702 int val; \
703 struct fc_rport *rport = transport_class_to_rport(cdev); \
704 struct Scsi_Host *shost = rport_to_shost(rport); \
705 struct fc_internal *i = to_fc_internal(shost->transportt); \
0f29b966 706 char *cp; \
19a7b4ae 707 if ((rport->port_state == FC_PORTSTATE_BLOCKED) || \
42e33148 708 (rport->port_state == FC_PORTSTATE_DELETED) || \
19a7b4ae
JSEC
709 (rport->port_state == FC_PORTSTATE_NOTPRESENT)) \
710 return -EBUSY; \
0f29b966
JS
711 val = simple_strtoul(buf, &cp, 0); \
712 if (*cp && (*cp != '\n')) \
713 return -EINVAL; \
1da177e4
LT
714 i->f->set_rport_##field(rport, val); \
715 return count; \
716}
717
718#define fc_rport_rd_attr(field, format_string, sz) \
719 fc_rport_show_function(field, format_string, sz, ) \
720static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \
721 show_fc_rport_##field, NULL)
722
723#define fc_rport_rd_attr_cast(field, format_string, sz, cast) \
724 fc_rport_show_function(field, format_string, sz, (cast)) \
725static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \
726 show_fc_rport_##field, NULL)
727
728#define fc_rport_rw_attr(field, format_string, sz) \
729 fc_rport_show_function(field, format_string, sz, ) \
730 fc_rport_store_function(field) \
731static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO | S_IWUSR, \
732 show_fc_rport_##field, \
733 store_fc_rport_##field)
734
735
736#define fc_private_rport_show_function(field, format_string, sz, cast) \
737static ssize_t \
738show_fc_rport_##field (struct class_device *cdev, char *buf) \
739{ \
740 struct fc_rport *rport = transport_class_to_rport(cdev); \
741 return snprintf(buf, sz, format_string, cast rport->field); \
742}
743
744#define fc_private_rport_rd_attr(field, format_string, sz) \
745 fc_private_rport_show_function(field, format_string, sz, ) \
746static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \
747 show_fc_rport_##field, NULL)
748
749#define fc_private_rport_rd_attr_cast(field, format_string, sz, cast) \
750 fc_private_rport_show_function(field, format_string, sz, (cast)) \
751static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \
752 show_fc_rport_##field, NULL)
753
754
755#define fc_private_rport_rd_enum_attr(title, maxlen) \
756static ssize_t \
757show_fc_rport_##title (struct class_device *cdev, char *buf) \
758{ \
759 struct fc_rport *rport = transport_class_to_rport(cdev); \
760 const char *name; \
761 name = get_fc_##title##_name(rport->title); \
762 if (!name) \
763 return -EINVAL; \
764 return snprintf(buf, maxlen, "%s\n", name); \
765} \
766static FC_CLASS_DEVICE_ATTR(rport, title, S_IRUGO, \
767 show_fc_rport_##title, NULL)
768
769
770#define SETUP_RPORT_ATTRIBUTE_RD(field) \
771 i->private_rport_attrs[count] = class_device_attr_rport_##field; \
772 i->private_rport_attrs[count].attr.mode = S_IRUGO; \
773 i->private_rport_attrs[count].store = NULL; \
774 i->rport_attrs[count] = &i->private_rport_attrs[count]; \
775 if (i->f->show_rport_##field) \
776 count++
777
778#define SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(field) \
779 i->private_rport_attrs[count] = class_device_attr_rport_##field; \
780 i->private_rport_attrs[count].attr.mode = S_IRUGO; \
781 i->private_rport_attrs[count].store = NULL; \
782 i->rport_attrs[count] = &i->private_rport_attrs[count]; \
783 count++
784
785#define SETUP_RPORT_ATTRIBUTE_RW(field) \
786 i->private_rport_attrs[count] = class_device_attr_rport_##field; \
787 if (!i->f->set_rport_##field) { \
788 i->private_rport_attrs[count].attr.mode = S_IRUGO; \
789 i->private_rport_attrs[count].store = NULL; \
790 } \
791 i->rport_attrs[count] = &i->private_rport_attrs[count]; \
792 if (i->f->show_rport_##field) \
793 count++
794
0f29b966
JS
795#define SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(field) \
796{ \
797 i->private_rport_attrs[count] = class_device_attr_rport_##field; \
798 i->rport_attrs[count] = &i->private_rport_attrs[count]; \
799 count++; \
800}
801
1da177e4
LT
802
803/* The FC Transport Remote Port Attributes: */
804
805/* Fixed Remote Port Attributes */
806
807fc_private_rport_rd_attr(maxframe_size, "%u bytes\n", 20);
808
809static ssize_t
810show_fc_rport_supported_classes (struct class_device *cdev, char *buf)
811{
812 struct fc_rport *rport = transport_class_to_rport(cdev);
813 if (rport->supported_classes == FC_COS_UNSPECIFIED)
814 return snprintf(buf, 20, "unspecified\n");
815 return get_fc_cos_names(rport->supported_classes, buf);
816}
817static FC_CLASS_DEVICE_ATTR(rport, supported_classes, S_IRUGO,
818 show_fc_rport_supported_classes, NULL);
819
820/* Dynamic Remote Port Attributes */
821
19a7b4ae
JSEC
822/*
823 * dev_loss_tmo attribute
824 */
825fc_rport_show_function(dev_loss_tmo, "%d\n", 20, )
826static ssize_t
827store_fc_rport_dev_loss_tmo(struct class_device *cdev, const char *buf,
828 size_t count)
829{
830 int val;
831 struct fc_rport *rport = transport_class_to_rport(cdev);
832 struct Scsi_Host *shost = rport_to_shost(rport);
833 struct fc_internal *i = to_fc_internal(shost->transportt);
0f29b966 834 char *cp;
19a7b4ae 835 if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
42e33148 836 (rport->port_state == FC_PORTSTATE_DELETED) ||
19a7b4ae
JSEC
837 (rport->port_state == FC_PORTSTATE_NOTPRESENT))
838 return -EBUSY;
0f29b966
JS
839 val = simple_strtoul(buf, &cp, 0);
840 if ((*cp && (*cp != '\n')) ||
841 (val < 0) || (val > SCSI_DEVICE_BLOCK_MAX_TIMEOUT))
19a7b4ae
JSEC
842 return -EINVAL;
843 i->f->set_rport_dev_loss_tmo(rport, val);
844 return count;
845}
846static FC_CLASS_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR,
847 show_fc_rport_dev_loss_tmo, store_fc_rport_dev_loss_tmo);
1da177e4
LT
848
849
850/* Private Remote Port Attributes */
851
852fc_private_rport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
853fc_private_rport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
854fc_private_rport_rd_attr(port_id, "0x%06x\n", 20);
855
856static ssize_t
857show_fc_rport_roles (struct class_device *cdev, char *buf)
858{
859 struct fc_rport *rport = transport_class_to_rport(cdev);
860
861 /* identify any roles that are port_id specific */
862 if ((rport->port_id != -1) &&
863 (rport->port_id & FC_WELLKNOWN_PORTID_MASK) ==
864 FC_WELLKNOWN_PORTID_MASK) {
865 switch (rport->port_id & FC_WELLKNOWN_ROLE_MASK) {
866 case FC_FPORT_PORTID:
867 return snprintf(buf, 30, "Fabric Port\n");
868 case FC_FABCTLR_PORTID:
869 return snprintf(buf, 30, "Fabric Controller\n");
870 case FC_DIRSRVR_PORTID:
871 return snprintf(buf, 30, "Directory Server\n");
872 case FC_TIMESRVR_PORTID:
873 return snprintf(buf, 30, "Time Server\n");
874 case FC_MGMTSRVR_PORTID:
875 return snprintf(buf, 30, "Management Server\n");
876 default:
877 return snprintf(buf, 30, "Unknown Fabric Entity\n");
878 }
879 } else {
a53eb5e0 880 if (rport->roles == FC_PORT_ROLE_UNKNOWN)
1da177e4 881 return snprintf(buf, 20, "unknown\n");
a53eb5e0 882 return get_fc_port_roles_names(rport->roles, buf);
1da177e4
LT
883 }
884}
885static FC_CLASS_DEVICE_ATTR(rport, roles, S_IRUGO,
886 show_fc_rport_roles, NULL);
887
888fc_private_rport_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN);
889fc_private_rport_rd_attr(scsi_target_id, "%d\n", 20);
890
0f29b966
JS
891/*
892 * fast_io_fail_tmo attribute
893 */
894static ssize_t
895show_fc_rport_fast_io_fail_tmo (struct class_device *cdev, char *buf)
896{
897 struct fc_rport *rport = transport_class_to_rport(cdev);
898
899 if (rport->fast_io_fail_tmo == -1)
900 return snprintf(buf, 5, "off\n");
901 return snprintf(buf, 20, "%d\n", rport->fast_io_fail_tmo);
902}
903
904static ssize_t
905store_fc_rport_fast_io_fail_tmo(struct class_device *cdev, const char *buf,
906 size_t count)
907{
908 int val;
909 char *cp;
910 struct fc_rport *rport = transport_class_to_rport(cdev);
911
912 if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
913 (rport->port_state == FC_PORTSTATE_DELETED) ||
914 (rport->port_state == FC_PORTSTATE_NOTPRESENT))
915 return -EBUSY;
916 if (strncmp(buf, "off", 3) == 0)
917 rport->fast_io_fail_tmo = -1;
918 else {
919 val = simple_strtoul(buf, &cp, 0);
920 if ((*cp && (*cp != '\n')) ||
921 (val < 0) || (val >= rport->dev_loss_tmo))
922 return -EINVAL;
923 rport->fast_io_fail_tmo = val;
924 }
925 return count;
926}
927static FC_CLASS_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
928 show_fc_rport_fast_io_fail_tmo, store_fc_rport_fast_io_fail_tmo);
1da177e4
LT
929
930
931/*
932 * FC SCSI Target Attribute Management
933 */
934
935/*
936 * Note: in the target show function we recognize when the remote
a53eb5e0 937 * port is in the heirarchy and do not allow the driver to get
1da177e4
LT
938 * involved in sysfs functions. The driver only gets involved if
939 * it's the "old" style that doesn't use rports.
940 */
941#define fc_starget_show_function(field, format_string, sz, cast) \
942static ssize_t \
943show_fc_starget_##field (struct class_device *cdev, char *buf) \
944{ \
945 struct scsi_target *starget = transport_class_to_starget(cdev); \
946 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
947 struct fc_internal *i = to_fc_internal(shost->transportt); \
948 struct fc_rport *rport = starget_to_rport(starget); \
949 if (rport) \
950 fc_starget_##field(starget) = rport->field; \
951 else if (i->f->get_starget_##field) \
952 i->f->get_starget_##field(starget); \
953 return snprintf(buf, sz, format_string, \
954 cast fc_starget_##field(starget)); \
955}
956
957#define fc_starget_rd_attr(field, format_string, sz) \
958 fc_starget_show_function(field, format_string, sz, ) \
959static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO, \
960 show_fc_starget_##field, NULL)
961
962#define fc_starget_rd_attr_cast(field, format_string, sz, cast) \
963 fc_starget_show_function(field, format_string, sz, (cast)) \
964static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO, \
965 show_fc_starget_##field, NULL)
966
967#define SETUP_STARGET_ATTRIBUTE_RD(field) \
968 i->private_starget_attrs[count] = class_device_attr_starget_##field; \
969 i->private_starget_attrs[count].attr.mode = S_IRUGO; \
970 i->private_starget_attrs[count].store = NULL; \
971 i->starget_attrs[count] = &i->private_starget_attrs[count]; \
972 if (i->f->show_starget_##field) \
973 count++
974
975#define SETUP_STARGET_ATTRIBUTE_RW(field) \
976 i->private_starget_attrs[count] = class_device_attr_starget_##field; \
977 if (!i->f->set_starget_##field) { \
978 i->private_starget_attrs[count].attr.mode = S_IRUGO; \
979 i->private_starget_attrs[count].store = NULL; \
980 } \
981 i->starget_attrs[count] = &i->private_starget_attrs[count]; \
982 if (i->f->show_starget_##field) \
983 count++
984
985/* The FC Transport SCSI Target Attributes: */
986fc_starget_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
987fc_starget_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
988fc_starget_rd_attr(port_id, "0x%06x\n", 20);
989
990
a53eb5e0
JS
991/*
992 * FC Virtual Port Attribute Management
993 */
994
995#define fc_vport_show_function(field, format_string, sz, cast) \
996static ssize_t \
997show_fc_vport_##field (struct class_device *cdev, char *buf) \
998{ \
999 struct fc_vport *vport = transport_class_to_vport(cdev); \
1000 struct Scsi_Host *shost = vport_to_shost(vport); \
1001 struct fc_internal *i = to_fc_internal(shost->transportt); \
1002 if ((i->f->get_vport_##field) && \
1003 !(vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))) \
1004 i->f->get_vport_##field(vport); \
1005 return snprintf(buf, sz, format_string, cast vport->field); \
1006}
1007
1008#define fc_vport_store_function(field) \
1009static ssize_t \
1010store_fc_vport_##field(struct class_device *cdev, const char *buf, \
1011 size_t count) \
1012{ \
1013 int val; \
1014 struct fc_vport *vport = transport_class_to_vport(cdev); \
1015 struct Scsi_Host *shost = vport_to_shost(vport); \
1016 struct fc_internal *i = to_fc_internal(shost->transportt); \
1017 char *cp; \
1018 if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) \
1019 return -EBUSY; \
1020 val = simple_strtoul(buf, &cp, 0); \
1021 if (*cp && (*cp != '\n')) \
1022 return -EINVAL; \
1023 i->f->set_vport_##field(vport, val); \
1024 return count; \
1025}
1026
1027#define fc_vport_store_str_function(field, slen) \
1028static ssize_t \
1029store_fc_vport_##field(struct class_device *cdev, const char *buf, \
1030 size_t count) \
1031{ \
1032 struct fc_vport *vport = transport_class_to_vport(cdev); \
1033 struct Scsi_Host *shost = vport_to_shost(vport); \
1034 struct fc_internal *i = to_fc_internal(shost->transportt); \
1035 unsigned int cnt=count; \
1036 \
1037 /* count may include a LF at end of string */ \
1038 if (buf[cnt-1] == '\n') \
1039 cnt--; \
1040 if (cnt > ((slen) - 1)) \
1041 return -EINVAL; \
1042 memcpy(vport->field, buf, cnt); \
1043 i->f->set_vport_##field(vport); \
1044 return count; \
1045}
1046
1047#define fc_vport_rd_attr(field, format_string, sz) \
1048 fc_vport_show_function(field, format_string, sz, ) \
1049static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO, \
1050 show_fc_vport_##field, NULL)
1051
1052#define fc_vport_rd_attr_cast(field, format_string, sz, cast) \
1053 fc_vport_show_function(field, format_string, sz, (cast)) \
1054static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO, \
1055 show_fc_vport_##field, NULL)
1056
1057#define fc_vport_rw_attr(field, format_string, sz) \
1058 fc_vport_show_function(field, format_string, sz, ) \
1059 fc_vport_store_function(field) \
1060static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR, \
1061 show_fc_vport_##field, \
1062 store_fc_vport_##field)
1063
1064#define fc_private_vport_show_function(field, format_string, sz, cast) \
1065static ssize_t \
1066show_fc_vport_##field (struct class_device *cdev, char *buf) \
1067{ \
1068 struct fc_vport *vport = transport_class_to_vport(cdev); \
1069 return snprintf(buf, sz, format_string, cast vport->field); \
1070}
1071
1072#define fc_private_vport_store_u32_function(field) \
1073static ssize_t \
1074store_fc_vport_##field(struct class_device *cdev, const char *buf, \
1075 size_t count) \
1076{ \
1077 u32 val; \
1078 struct fc_vport *vport = transport_class_to_vport(cdev); \
1079 char *cp; \
1080 if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) \
1081 return -EBUSY; \
1082 val = simple_strtoul(buf, &cp, 0); \
1083 if (*cp && (*cp != '\n')) \
1084 return -EINVAL; \
1085 vport->field = val; \
1086 return count; \
1087}
1088
1089
1090#define fc_private_vport_rd_attr(field, format_string, sz) \
1091 fc_private_vport_show_function(field, format_string, sz, ) \
1092static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO, \
1093 show_fc_vport_##field, NULL)
1094
1095#define fc_private_vport_rd_attr_cast(field, format_string, sz, cast) \
1096 fc_private_vport_show_function(field, format_string, sz, (cast)) \
1097static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO, \
1098 show_fc_vport_##field, NULL)
1099
1100#define fc_private_vport_rw_u32_attr(field, format_string, sz) \
1101 fc_private_vport_show_function(field, format_string, sz, ) \
1102 fc_private_vport_store_u32_function(field) \
1103static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR, \
1104 show_fc_vport_##field, \
1105 store_fc_vport_##field)
1106
1107
1108#define fc_private_vport_rd_enum_attr(title, maxlen) \
1109static ssize_t \
1110show_fc_vport_##title (struct class_device *cdev, char *buf) \
1111{ \
1112 struct fc_vport *vport = transport_class_to_vport(cdev); \
1113 const char *name; \
1114 name = get_fc_##title##_name(vport->title); \
1115 if (!name) \
1116 return -EINVAL; \
1117 return snprintf(buf, maxlen, "%s\n", name); \
1118} \
1119static FC_CLASS_DEVICE_ATTR(vport, title, S_IRUGO, \
1120 show_fc_vport_##title, NULL)
1121
1122
1123#define SETUP_VPORT_ATTRIBUTE_RD(field) \
1124 i->private_vport_attrs[count] = class_device_attr_vport_##field; \
1125 i->private_vport_attrs[count].attr.mode = S_IRUGO; \
1126 i->private_vport_attrs[count].store = NULL; \
1127 i->vport_attrs[count] = &i->private_vport_attrs[count]; \
1128 if (i->f->get_##field) \
1129 count++
1130 /* NOTE: Above MACRO differs: checks function not show bit */
1131
1132#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(field) \
1133 i->private_vport_attrs[count] = class_device_attr_vport_##field; \
1134 i->private_vport_attrs[count].attr.mode = S_IRUGO; \
1135 i->private_vport_attrs[count].store = NULL; \
1136 i->vport_attrs[count] = &i->private_vport_attrs[count]; \
1137 count++
1138
1139#define SETUP_VPORT_ATTRIBUTE_WR(field) \
1140 i->private_vport_attrs[count] = class_device_attr_vport_##field; \
1141 i->vport_attrs[count] = &i->private_vport_attrs[count]; \
1142 if (i->f->field) \
1143 count++
1144 /* NOTE: Above MACRO differs: checks function */
1145
1146#define SETUP_VPORT_ATTRIBUTE_RW(field) \
1147 i->private_vport_attrs[count] = class_device_attr_vport_##field; \
1148 if (!i->f->set_vport_##field) { \
1149 i->private_vport_attrs[count].attr.mode = S_IRUGO; \
1150 i->private_vport_attrs[count].store = NULL; \
1151 } \
1152 i->vport_attrs[count] = &i->private_vport_attrs[count]; \
1153 count++
1154 /* NOTE: Above MACRO differs: does not check show bit */
1155
1156#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RW(field) \
1157{ \
1158 i->private_vport_attrs[count] = class_device_attr_vport_##field; \
1159 i->vport_attrs[count] = &i->private_vport_attrs[count]; \
1160 count++; \
1161}
1162
1163
1164/* The FC Transport Virtual Port Attributes: */
1165
1166/* Fixed Virtual Port Attributes */
1167
1168/* Dynamic Virtual Port Attributes */
1169
1170/* Private Virtual Port Attributes */
1171
1172fc_private_vport_rd_enum_attr(vport_state, FC_VPORTSTATE_MAX_NAMELEN);
1173fc_private_vport_rd_enum_attr(vport_last_state, FC_VPORTSTATE_MAX_NAMELEN);
1174fc_private_vport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
1175fc_private_vport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
1176
1177static ssize_t
1178show_fc_vport_roles (struct class_device *cdev, char *buf)
1179{
1180 struct fc_vport *vport = transport_class_to_vport(cdev);
1181
1182 if (vport->roles == FC_PORT_ROLE_UNKNOWN)
1183 return snprintf(buf, 20, "unknown\n");
1184 return get_fc_port_roles_names(vport->roles, buf);
1185}
1186static FC_CLASS_DEVICE_ATTR(vport, roles, S_IRUGO, show_fc_vport_roles, NULL);
1187
1188fc_private_vport_rd_enum_attr(vport_type, FC_PORTTYPE_MAX_NAMELEN);
1189
1190fc_private_vport_show_function(symbolic_name, "%s\n",
1191 FC_VPORT_SYMBOLIC_NAMELEN + 1, )
1192fc_vport_store_str_function(symbolic_name, FC_VPORT_SYMBOLIC_NAMELEN)
1193static FC_CLASS_DEVICE_ATTR(vport, symbolic_name, S_IRUGO | S_IWUSR,
1194 show_fc_vport_symbolic_name, store_fc_vport_symbolic_name);
1195
1196static ssize_t
1197store_fc_vport_delete(struct class_device *cdev, const char *buf,
1198 size_t count)
1199{
1200 struct fc_vport *vport = transport_class_to_vport(cdev);
1201 int stat;
1202
1203 stat = fc_vport_terminate(vport);
1204 if (stat)
1205 return stat;
1206
1207 return count;
1208}
1209static FC_CLASS_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
1210 NULL, store_fc_vport_delete);
1211
1212
1213/*
1214 * Enable/Disable vport
1215 * Write "1" to disable, write "0" to enable
1216 */
1217static ssize_t
1218store_fc_vport_disable(struct class_device *cdev, const char *buf,
1219 size_t count)
1220{
1221 struct fc_vport *vport = transport_class_to_vport(cdev);
1222 struct Scsi_Host *shost = vport_to_shost(vport);
1223 struct fc_internal *i = to_fc_internal(shost->transportt);
1224 int stat;
1225
1226 if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))
1227 return -EBUSY;
1228
1229 if (*buf == '0') {
1230 if (vport->vport_state != FC_VPORT_DISABLED)
1231 return -EALREADY;
1232 } else if (*buf == '1') {
1233 if (vport->vport_state == FC_VPORT_DISABLED)
1234 return -EALREADY;
1235 } else
1236 return -EINVAL;
1237
1238 stat = i->f->vport_disable(vport, ((*buf == '0') ? false : true));
1239 return stat ? stat : count;
1240}
1241static FC_CLASS_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
1242 NULL, store_fc_vport_disable);
1243
1244
1da177e4
LT
1245/*
1246 * Host Attribute Management
1247 */
1248
1249#define fc_host_show_function(field, format_string, sz, cast) \
1250static ssize_t \
1251show_fc_host_##field (struct class_device *cdev, char *buf) \
1252{ \
1253 struct Scsi_Host *shost = transport_class_to_shost(cdev); \
1254 struct fc_internal *i = to_fc_internal(shost->transportt); \
1255 if (i->f->get_host_##field) \
1256 i->f->get_host_##field(shost); \
1257 return snprintf(buf, sz, format_string, cast fc_host_##field(shost)); \
1258}
1259
1260#define fc_host_store_function(field) \
1261static ssize_t \
1262store_fc_host_##field(struct class_device *cdev, const char *buf, \
1263 size_t count) \
1264{ \
1265 int val; \
1266 struct Scsi_Host *shost = transport_class_to_shost(cdev); \
1267 struct fc_internal *i = to_fc_internal(shost->transportt); \
0f29b966 1268 char *cp; \
1da177e4 1269 \
0f29b966
JS
1270 val = simple_strtoul(buf, &cp, 0); \
1271 if (*cp && (*cp != '\n')) \
1272 return -EINVAL; \
1da177e4
LT
1273 i->f->set_host_##field(shost, val); \
1274 return count; \
1275}
1276
b8d08210
JS
1277#define fc_host_store_str_function(field, slen) \
1278static ssize_t \
1279store_fc_host_##field(struct class_device *cdev, const char *buf, \
1280 size_t count) \
1281{ \
1282 struct Scsi_Host *shost = transport_class_to_shost(cdev); \
1283 struct fc_internal *i = to_fc_internal(shost->transportt); \
1284 unsigned int cnt=count; \
1285 \
1286 /* count may include a LF at end of string */ \
1287 if (buf[cnt-1] == '\n') \
1288 cnt--; \
1289 if (cnt > ((slen) - 1)) \
1290 return -EINVAL; \
1291 memcpy(fc_host_##field(shost), buf, cnt); \
1292 i->f->set_host_##field(shost); \
1293 return count; \
1294}
1295
1da177e4
LT
1296#define fc_host_rd_attr(field, format_string, sz) \
1297 fc_host_show_function(field, format_string, sz, ) \
1298static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \
1299 show_fc_host_##field, NULL)
1300
1301#define fc_host_rd_attr_cast(field, format_string, sz, cast) \
1302 fc_host_show_function(field, format_string, sz, (cast)) \
1303static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \
1304 show_fc_host_##field, NULL)
1305
1306#define fc_host_rw_attr(field, format_string, sz) \
1307 fc_host_show_function(field, format_string, sz, ) \
1308 fc_host_store_function(field) \
1309static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO | S_IWUSR, \
1310 show_fc_host_##field, \
1311 store_fc_host_##field)
1312
1313#define fc_host_rd_enum_attr(title, maxlen) \
1314static ssize_t \
1315show_fc_host_##title (struct class_device *cdev, char *buf) \
1316{ \
1317 struct Scsi_Host *shost = transport_class_to_shost(cdev); \
1318 struct fc_internal *i = to_fc_internal(shost->transportt); \
1319 const char *name; \
1320 if (i->f->get_host_##title) \
1321 i->f->get_host_##title(shost); \
1322 name = get_fc_##title##_name(fc_host_##title(shost)); \
1323 if (!name) \
1324 return -EINVAL; \
1325 return snprintf(buf, maxlen, "%s\n", name); \
1326} \
1327static FC_CLASS_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL)
1328
1329#define SETUP_HOST_ATTRIBUTE_RD(field) \
1330 i->private_host_attrs[count] = class_device_attr_host_##field; \
1331 i->private_host_attrs[count].attr.mode = S_IRUGO; \
1332 i->private_host_attrs[count].store = NULL; \
1333 i->host_attrs[count] = &i->private_host_attrs[count]; \
1334 if (i->f->show_host_##field) \
1335 count++
1336
a53eb5e0
JS
1337#define SETUP_HOST_ATTRIBUTE_RD_NS(field) \
1338 i->private_host_attrs[count] = class_device_attr_host_##field; \
1339 i->private_host_attrs[count].attr.mode = S_IRUGO; \
1340 i->private_host_attrs[count].store = NULL; \
1341 i->host_attrs[count] = &i->private_host_attrs[count]; \
1342 count++
1343
1da177e4
LT
1344#define SETUP_HOST_ATTRIBUTE_RW(field) \
1345 i->private_host_attrs[count] = class_device_attr_host_##field; \
1346 if (!i->f->set_host_##field) { \
1347 i->private_host_attrs[count].attr.mode = S_IRUGO; \
1348 i->private_host_attrs[count].store = NULL; \
1349 } \
1350 i->host_attrs[count] = &i->private_host_attrs[count]; \
1351 if (i->f->show_host_##field) \
1352 count++
1353
1354
1355#define fc_private_host_show_function(field, format_string, sz, cast) \
1356static ssize_t \
1357show_fc_host_##field (struct class_device *cdev, char *buf) \
1358{ \
1359 struct Scsi_Host *shost = transport_class_to_shost(cdev); \
1360 return snprintf(buf, sz, format_string, cast fc_host_##field(shost)); \
1361}
1362
1363#define fc_private_host_rd_attr(field, format_string, sz) \
1364 fc_private_host_show_function(field, format_string, sz, ) \
1365static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \
1366 show_fc_host_##field, NULL)
1367
1368#define fc_private_host_rd_attr_cast(field, format_string, sz, cast) \
1369 fc_private_host_show_function(field, format_string, sz, (cast)) \
1370static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \
1371 show_fc_host_##field, NULL)
1372
1373#define SETUP_PRIVATE_HOST_ATTRIBUTE_RD(field) \
1374 i->private_host_attrs[count] = class_device_attr_host_##field; \
1375 i->private_host_attrs[count].attr.mode = S_IRUGO; \
1376 i->private_host_attrs[count].store = NULL; \
1377 i->host_attrs[count] = &i->private_host_attrs[count]; \
1378 count++
1379
1380#define SETUP_PRIVATE_HOST_ATTRIBUTE_RW(field) \
91ca7b01 1381{ \
1da177e4
LT
1382 i->private_host_attrs[count] = class_device_attr_host_##field; \
1383 i->host_attrs[count] = &i->private_host_attrs[count]; \
91ca7b01
AV
1384 count++; \
1385}
1da177e4
LT
1386
1387
1388/* Fixed Host Attributes */
1389
1390static ssize_t
1391show_fc_host_supported_classes (struct class_device *cdev, char *buf)
1392{
1393 struct Scsi_Host *shost = transport_class_to_shost(cdev);
1394
1395 if (fc_host_supported_classes(shost) == FC_COS_UNSPECIFIED)
1396 return snprintf(buf, 20, "unspecified\n");
1397
1398 return get_fc_cos_names(fc_host_supported_classes(shost), buf);
1399}
1400static FC_CLASS_DEVICE_ATTR(host, supported_classes, S_IRUGO,
1401 show_fc_host_supported_classes, NULL);
1402
1403static ssize_t
1404show_fc_host_supported_fc4s (struct class_device *cdev, char *buf)
1405{
1406 struct Scsi_Host *shost = transport_class_to_shost(cdev);
1407 return (ssize_t)show_fc_fc4s(buf, fc_host_supported_fc4s(shost));
1408}
1409static FC_CLASS_DEVICE_ATTR(host, supported_fc4s, S_IRUGO,
1410 show_fc_host_supported_fc4s, NULL);
1411
1412static ssize_t
1413show_fc_host_supported_speeds (struct class_device *cdev, char *buf)
1414{
1415 struct Scsi_Host *shost = transport_class_to_shost(cdev);
1416
1417 if (fc_host_supported_speeds(shost) == FC_PORTSPEED_UNKNOWN)
1418 return snprintf(buf, 20, "unknown\n");
1419
1420 return get_fc_port_speed_names(fc_host_supported_speeds(shost), buf);
1421}
1422static FC_CLASS_DEVICE_ATTR(host, supported_speeds, S_IRUGO,
1423 show_fc_host_supported_speeds, NULL);
1424
1425
1426fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
1427fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
6b7281d0
AH
1428fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20,
1429 unsigned long long);
1da177e4 1430fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
a53eb5e0 1431fc_private_host_rd_attr(max_npiv_vports, "%u\n", 20);
1da177e4
LT
1432fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
1433
1434
1435/* Dynamic Host Attributes */
1436
1437static ssize_t
1438show_fc_host_active_fc4s (struct class_device *cdev, char *buf)
1439{
1440 struct Scsi_Host *shost = transport_class_to_shost(cdev);
1441 struct fc_internal *i = to_fc_internal(shost->transportt);
1442
1443 if (i->f->get_host_active_fc4s)
1444 i->f->get_host_active_fc4s(shost);
1445
1446 return (ssize_t)show_fc_fc4s(buf, fc_host_active_fc4s(shost));
1447}
1448static FC_CLASS_DEVICE_ATTR(host, active_fc4s, S_IRUGO,
1449 show_fc_host_active_fc4s, NULL);
1450
1451static ssize_t
1452show_fc_host_speed (struct class_device *cdev, char *buf)
1453{
1454 struct Scsi_Host *shost = transport_class_to_shost(cdev);
1455 struct fc_internal *i = to_fc_internal(shost->transportt);
1456
1457 if (i->f->get_host_speed)
1458 i->f->get_host_speed(shost);
1459
1460 if (fc_host_speed(shost) == FC_PORTSPEED_UNKNOWN)
1461 return snprintf(buf, 20, "unknown\n");
1462
1463 return get_fc_port_speed_names(fc_host_speed(shost), buf);
1464}
1465static FC_CLASS_DEVICE_ATTR(host, speed, S_IRUGO,
1466 show_fc_host_speed, NULL);
1467
1468
1469fc_host_rd_attr(port_id, "0x%06x\n", 20);
1470fc_host_rd_enum_attr(port_type, FC_PORTTYPE_MAX_NAMELEN);
1471fc_host_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN);
1472fc_host_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long);
016131b8 1473fc_host_rd_attr(symbolic_name, "%s\n", FC_SYMBOLIC_NAME_SIZE + 1);
1da177e4 1474
b8d08210
JS
1475fc_private_host_show_function(system_hostname, "%s\n",
1476 FC_SYMBOLIC_NAME_SIZE + 1, )
1477fc_host_store_str_function(system_hostname, FC_SYMBOLIC_NAME_SIZE)
1478static FC_CLASS_DEVICE_ATTR(host, system_hostname, S_IRUGO | S_IWUSR,
1479 show_fc_host_system_hostname, store_fc_host_system_hostname);
1480
1da177e4
LT
1481
1482/* Private Host Attributes */
1483
1484static ssize_t
1485show_fc_private_host_tgtid_bind_type(struct class_device *cdev, char *buf)
1486{
1487 struct Scsi_Host *shost = transport_class_to_shost(cdev);
1488 const char *name;
1489
1490 name = get_fc_tgtid_bind_type_name(fc_host_tgtid_bind_type(shost));
1491 if (!name)
1492 return -EINVAL;
1493 return snprintf(buf, FC_BINDTYPE_MAX_NAMELEN, "%s\n", name);
1494}
1495
d16794f6
JSEC
1496#define get_list_head_entry(pos, head, member) \
1497 pos = list_entry((head)->next, typeof(*pos), member)
1498
1da177e4
LT
1499static ssize_t
1500store_fc_private_host_tgtid_bind_type(struct class_device *cdev,
1501 const char *buf, size_t count)
1502{
1503 struct Scsi_Host *shost = transport_class_to_shost(cdev);
d16794f6 1504 struct fc_rport *rport;
1da177e4
LT
1505 enum fc_tgtid_binding_type val;
1506 unsigned long flags;
1507
1508 if (get_fc_tgtid_bind_type_match(buf, &val))
1509 return -EINVAL;
1510
1511 /* if changing bind type, purge all unused consistent bindings */
1512 if (val != fc_host_tgtid_bind_type(shost)) {
1513 spin_lock_irqsave(shost->host_lock, flags);
d16794f6
JSEC
1514 while (!list_empty(&fc_host_rport_bindings(shost))) {
1515 get_list_head_entry(rport,
1516 &fc_host_rport_bindings(shost), peers);
aedf3497
JS
1517 list_del(&rport->peers);
1518 rport->port_state = FC_PORTSTATE_DELETED;
1519 fc_queue_work(shost, &rport->rport_delete_work);
d16794f6 1520 }
1da177e4
LT
1521 spin_unlock_irqrestore(shost->host_lock, flags);
1522 }
1523
1524 fc_host_tgtid_bind_type(shost) = val;
1525 return count;
1526}
1527
1528static FC_CLASS_DEVICE_ATTR(host, tgtid_bind_type, S_IRUGO | S_IWUSR,
1529 show_fc_private_host_tgtid_bind_type,
1530 store_fc_private_host_tgtid_bind_type);
1531
91ca7b01
AV
1532static ssize_t
1533store_fc_private_host_issue_lip(struct class_device *cdev,
1534 const char *buf, size_t count)
1535{
1536 struct Scsi_Host *shost = transport_class_to_shost(cdev);
1537 struct fc_internal *i = to_fc_internal(shost->transportt);
1538 int ret;
1539
1540 /* ignore any data value written to the attribute */
1541 if (i->f->issue_fc_host_lip) {
1542 ret = i->f->issue_fc_host_lip(shost);
1543 return ret ? ret: count;
1544 }
1545
1546 return -ENOENT;
1547}
1548
1549static FC_CLASS_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
1550 store_fc_private_host_issue_lip);
1551
a53eb5e0
JS
1552fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
1553
1554
1da177e4
LT
1555/*
1556 * Host Statistics Management
1557 */
1558
1559/* Show a given an attribute in the statistics group */
1560static ssize_t
1561fc_stat_show(const struct class_device *cdev, char *buf, unsigned long offset)
1562{
1563 struct Scsi_Host *shost = transport_class_to_shost(cdev);
1564 struct fc_internal *i = to_fc_internal(shost->transportt);
1565 struct fc_host_statistics *stats;
1566 ssize_t ret = -ENOENT;
1567
1568 if (offset > sizeof(struct fc_host_statistics) ||
1569 offset % sizeof(u64) != 0)
1570 WARN_ON(1);
1571
1572 if (i->f->get_fc_host_stats) {
1573 stats = (i->f->get_fc_host_stats)(shost);
1574 if (stats)
1575 ret = snprintf(buf, 20, "0x%llx\n",
1576 (unsigned long long)*(u64 *)(((u8 *) stats) + offset));
1577 }
1578 return ret;
1579}
1580
1581
1582/* generate a read-only statistics attribute */
1583#define fc_host_statistic(name) \
1584static ssize_t show_fcstat_##name(struct class_device *cd, char *buf) \
1585{ \
1586 return fc_stat_show(cd, buf, \
1587 offsetof(struct fc_host_statistics, name)); \
1588} \
1589static FC_CLASS_DEVICE_ATTR(host, name, S_IRUGO, show_fcstat_##name, NULL)
1590
1591fc_host_statistic(seconds_since_last_reset);
1592fc_host_statistic(tx_frames);
1593fc_host_statistic(tx_words);
1594fc_host_statistic(rx_frames);
1595fc_host_statistic(rx_words);
1596fc_host_statistic(lip_count);
1597fc_host_statistic(nos_count);
1598fc_host_statistic(error_frames);
1599fc_host_statistic(dumped_frames);
1600fc_host_statistic(link_failure_count);
1601fc_host_statistic(loss_of_sync_count);
1602fc_host_statistic(loss_of_signal_count);
1603fc_host_statistic(prim_seq_protocol_err_count);
1604fc_host_statistic(invalid_tx_word_count);
1605fc_host_statistic(invalid_crc_count);
1606fc_host_statistic(fcp_input_requests);
1607fc_host_statistic(fcp_output_requests);
1608fc_host_statistic(fcp_control_requests);
1609fc_host_statistic(fcp_input_megabytes);
1610fc_host_statistic(fcp_output_megabytes);
1611
1612static ssize_t
1613fc_reset_statistics(struct class_device *cdev, const char *buf,
1614 size_t count)
1615{
1616 struct Scsi_Host *shost = transport_class_to_shost(cdev);
1617 struct fc_internal *i = to_fc_internal(shost->transportt);
1618
1619 /* ignore any data value written to the attribute */
1620 if (i->f->reset_fc_host_stats) {
1621 i->f->reset_fc_host_stats(shost);
1622 return count;
1623 }
1624
1625 return -ENOENT;
1626}
1627static FC_CLASS_DEVICE_ATTR(host, reset_statistics, S_IWUSR, NULL,
1628 fc_reset_statistics);
1629
1da177e4
LT
1630static struct attribute *fc_statistics_attrs[] = {
1631 &class_device_attr_host_seconds_since_last_reset.attr,
1632 &class_device_attr_host_tx_frames.attr,
1633 &class_device_attr_host_tx_words.attr,
1634 &class_device_attr_host_rx_frames.attr,
1635 &class_device_attr_host_rx_words.attr,
1636 &class_device_attr_host_lip_count.attr,
1637 &class_device_attr_host_nos_count.attr,
1638 &class_device_attr_host_error_frames.attr,
1639 &class_device_attr_host_dumped_frames.attr,
1640 &class_device_attr_host_link_failure_count.attr,
1641 &class_device_attr_host_loss_of_sync_count.attr,
1642 &class_device_attr_host_loss_of_signal_count.attr,
1643 &class_device_attr_host_prim_seq_protocol_err_count.attr,
1644 &class_device_attr_host_invalid_tx_word_count.attr,
1645 &class_device_attr_host_invalid_crc_count.attr,
1646 &class_device_attr_host_fcp_input_requests.attr,
1647 &class_device_attr_host_fcp_output_requests.attr,
1648 &class_device_attr_host_fcp_control_requests.attr,
1649 &class_device_attr_host_fcp_input_megabytes.attr,
1650 &class_device_attr_host_fcp_output_megabytes.attr,
1651 &class_device_attr_host_reset_statistics.attr,
1652 NULL
1653};
1654
1655static struct attribute_group fc_statistics_group = {
1656 .name = "statistics",
1657 .attrs = fc_statistics_attrs,
1658};
1659
a53eb5e0
JS
1660
1661/* Host Vport Attributes */
1662
1663static int
1664fc_parse_wwn(const char *ns, u64 *nm)
1665{
1666 unsigned int i, j;
1667 u8 wwn[8];
1668
1669 memset(wwn, 0, sizeof(wwn));
1670
1671 /* Validate and store the new name */
1672 for (i=0, j=0; i < 16; i++) {
1673 if ((*ns >= 'a') && (*ns <= 'f'))
1674 j = ((j << 4) | ((*ns++ -'a') + 10));
1675 else if ((*ns >= 'A') && (*ns <= 'F'))
1676 j = ((j << 4) | ((*ns++ -'A') + 10));
1677 else if ((*ns >= '0') && (*ns <= '9'))
1678 j = ((j << 4) | (*ns++ -'0'));
1679 else
1680 return -EINVAL;
1681 if (i % 2) {
1682 wwn[i/2] = j & 0xff;
1683 j = 0;
1684 }
1685 }
1686
1687 *nm = wwn_to_u64(wwn);
1688
1689 return 0;
1690}
1691
1692
1693/*
1694 * "Short-cut" sysfs variable to create a new vport on a FC Host.
1695 * Input is a string of the form "<WWPN>:<WWNN>". Other attributes
1696 * will default to a NPIV-based FCP_Initiator; The WWNs are specified
1697 * as hex characters, and may *not* contain any prefixes (e.g. 0x, x, etc)
1698 */
1699static ssize_t
1700store_fc_host_vport_create(struct class_device *cdev, const char *buf,
1701 size_t count)
1702{
1703 struct Scsi_Host *shost = transport_class_to_shost(cdev);
1704 struct fc_vport_identifiers vid;
1705 struct fc_vport *vport;
1706 unsigned int cnt=count;
1707 int stat;
1708
1709 memset(&vid, 0, sizeof(vid));
1710
1711 /* count may include a LF at end of string */
1712 if (buf[cnt-1] == '\n')
1713 cnt--;
1714
1715 /* validate we have enough characters for WWPN */
1716 if ((cnt != (16+1+16)) || (buf[16] != ':'))
1717 return -EINVAL;
1718
1719 stat = fc_parse_wwn(&buf[0], &vid.port_name);
1720 if (stat)
1721 return stat;
1722
1723 stat = fc_parse_wwn(&buf[17], &vid.node_name);
1724 if (stat)
1725 return stat;
1726
1727 vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
1728 vid.vport_type = FC_PORTTYPE_NPIV;
1729 /* vid.symbolic_name is already zero/NULL's */
1730 vid.disable = false; /* always enabled */
1731
1732 /* we only allow support on Channel 0 !!! */
1733 stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport);
1734 return stat ? stat : count;
1735}
1736static FC_CLASS_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
1737 store_fc_host_vport_create);
1738
1739
1740/*
1741 * "Short-cut" sysfs variable to delete a vport on a FC Host.
1742 * Vport is identified by a string containing "<WWPN>:<WWNN>".
1743 * The WWNs are specified as hex characters, and may *not* contain
1744 * any prefixes (e.g. 0x, x, etc)
1745 */
1746static ssize_t
1747store_fc_host_vport_delete(struct class_device *cdev, const char *buf,
1748 size_t count)
1749{
1750 struct Scsi_Host *shost = transport_class_to_shost(cdev);
1751 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
1752 struct fc_vport *vport;
1753 u64 wwpn, wwnn;
1754 unsigned long flags;
1755 unsigned int cnt=count;
1756 int stat, match;
1757
1758 /* count may include a LF at end of string */
1759 if (buf[cnt-1] == '\n')
1760 cnt--;
1761
1762 /* validate we have enough characters for WWPN */
1763 if ((cnt != (16+1+16)) || (buf[16] != ':'))
1764 return -EINVAL;
1765
1766 stat = fc_parse_wwn(&buf[0], &wwpn);
1767 if (stat)
1768 return stat;
1769
1770 stat = fc_parse_wwn(&buf[17], &wwnn);
1771 if (stat)
1772 return stat;
1773
1774 spin_lock_irqsave(shost->host_lock, flags);
1775 match = 0;
1776 /* we only allow support on Channel 0 !!! */
1777 list_for_each_entry(vport, &fc_host->vports, peers) {
1778 if ((vport->channel == 0) &&
1779 (vport->port_name == wwpn) && (vport->node_name == wwnn)) {
1780 match = 1;
1781 break;
1782 }
1783 }
1784 spin_unlock_irqrestore(shost->host_lock, flags);
1785
1786 if (!match)
1787 return -ENODEV;
1788
1789 stat = fc_vport_terminate(vport);
1790 return stat ? stat : count;
1791}
1792static FC_CLASS_DEVICE_ATTR(host, vport_delete, S_IWUSR, NULL,
1793 store_fc_host_vport_delete);
1794
1795
1da177e4
LT
1796static int fc_host_match(struct attribute_container *cont,
1797 struct device *dev)
1798{
1799 struct Scsi_Host *shost;
1800 struct fc_internal *i;
1801
1802 if (!scsi_is_host_device(dev))
1803 return 0;
1804
1805 shost = dev_to_shost(dev);
1806 if (!shost->transportt || shost->transportt->host_attrs.ac.class
1807 != &fc_host_class.class)
1808 return 0;
1809
1810 i = to_fc_internal(shost->transportt);
1811
1812 return &i->t.host_attrs.ac == cont;
1813}
1814
1815static int fc_target_match(struct attribute_container *cont,
1816 struct device *dev)
1817{
1818 struct Scsi_Host *shost;
1819 struct fc_internal *i;
1820
1821 if (!scsi_is_target_device(dev))
1822 return 0;
1823
1824 shost = dev_to_shost(dev->parent);
1825 if (!shost->transportt || shost->transportt->host_attrs.ac.class
1826 != &fc_host_class.class)
1827 return 0;
1828
1829 i = to_fc_internal(shost->transportt);
1830
1831 return &i->t.target_attrs.ac == cont;
1832}
1833
1834static void fc_rport_dev_release(struct device *dev)
1835{
1836 struct fc_rport *rport = dev_to_rport(dev);
1837 put_device(dev->parent);
1838 kfree(rport);
1839}
1840
1841int scsi_is_fc_rport(const struct device *dev)
1842{
1843 return dev->release == fc_rport_dev_release;
1844}
1845EXPORT_SYMBOL(scsi_is_fc_rport);
1846
1847static int fc_rport_match(struct attribute_container *cont,
1848 struct device *dev)
1849{
1850 struct Scsi_Host *shost;
1851 struct fc_internal *i;
1852
1853 if (!scsi_is_fc_rport(dev))
1854 return 0;
1855
1856 shost = dev_to_shost(dev->parent);
1857 if (!shost->transportt || shost->transportt->host_attrs.ac.class
1858 != &fc_host_class.class)
1859 return 0;
1860
1861 i = to_fc_internal(shost->transportt);
1862
1863 return &i->rport_attr_cont.ac == cont;
1864}
1865
5c44cd2a 1866
a53eb5e0
JS
1867static void fc_vport_dev_release(struct device *dev)
1868{
1869 struct fc_vport *vport = dev_to_vport(dev);
1870 put_device(dev->parent); /* release kobj parent */
1871 kfree(vport);
1872}
1873
1874int scsi_is_fc_vport(const struct device *dev)
1875{
1876 return dev->release == fc_vport_dev_release;
1877}
1878EXPORT_SYMBOL(scsi_is_fc_vport);
1879
1880static int fc_vport_match(struct attribute_container *cont,
1881 struct device *dev)
1882{
1883 struct fc_vport *vport;
1884 struct Scsi_Host *shost;
1885 struct fc_internal *i;
1886
1887 if (!scsi_is_fc_vport(dev))
1888 return 0;
1889 vport = dev_to_vport(dev);
1890
1891 shost = vport_to_shost(vport);
1892 if (!shost->transportt || shost->transportt->host_attrs.ac.class
1893 != &fc_host_class.class)
1894 return 0;
1895
1896 i = to_fc_internal(shost->transportt);
1897 return &i->vport_attr_cont.ac == cont;
1898}
1899
1900
c829c394
JS
1901/**
1902 * fc_timed_out - FC Transport I/O timeout intercept handler
1903 *
1904 * @scmd: The SCSI command which timed out
1905 *
1906 * This routine protects against error handlers getting invoked while a
1907 * rport is in a blocked state, typically due to a temporarily loss of
1908 * connectivity. If the error handlers are allowed to proceed, requests
1909 * to abort i/o, reset the target, etc will likely fail as there is no way
1910 * to communicate with the device to perform the requested function. These
1911 * failures may result in the midlayer taking the device offline, requiring
1912 * manual intervention to restore operation.
1913 *
1914 * This routine, called whenever an i/o times out, validates the state of
1915 * the underlying rport. If the rport is blocked, it returns
1916 * EH_RESET_TIMER, which will continue to reschedule the timeout.
1917 * Eventually, either the device will return, or devloss_tmo will fire,
1918 * and when the timeout then fires, it will be handled normally.
1919 * If the rport is not blocked, normal error handling continues.
1920 *
1921 * Notes:
1922 * This routine assumes no locks are held on entry.
1923 **/
1924static enum scsi_eh_timer_return
1925fc_timed_out(struct scsi_cmnd *scmd)
1926{
1927 struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device));
1928
1929 if (rport->port_state == FC_PORTSTATE_BLOCKED)
1930 return EH_RESET_TIMER;
1931
1932 return EH_NOT_HANDLED;
1933}
1934
5c44cd2a
JSEC
1935/*
1936 * Must be called with shost->host_lock held
1937 */
e02f3f59
CH
1938static int fc_user_scan(struct Scsi_Host *shost, uint channel,
1939 uint id, uint lun)
5c44cd2a
JSEC
1940{
1941 struct fc_rport *rport;
1942
e02f3f59
CH
1943 list_for_each_entry(rport, &fc_host_rports(shost), peers) {
1944 if (rport->scsi_target_id == -1)
1945 continue;
5c44cd2a 1946
e02f3f59
CH
1947 if ((channel == SCAN_WILD_CARD || channel == rport->channel) &&
1948 (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) {
1949 scsi_scan_target(&rport->dev, rport->channel,
1950 rport->scsi_target_id, lun, 1);
1951 }
1952 }
1953
1954 return 0;
5c44cd2a
JSEC
1955}
1956
1da177e4
LT
1957struct scsi_transport_template *
1958fc_attach_transport(struct fc_function_template *ft)
1959{
1da177e4 1960 int count;
24669f75
JS
1961 struct fc_internal *i = kzalloc(sizeof(struct fc_internal),
1962 GFP_KERNEL);
1da177e4
LT
1963
1964 if (unlikely(!i))
1965 return NULL;
1966
1da177e4
LT
1967 i->t.target_attrs.ac.attrs = &i->starget_attrs[0];
1968 i->t.target_attrs.ac.class = &fc_transport_class.class;
1969 i->t.target_attrs.ac.match = fc_target_match;
1970 i->t.target_size = sizeof(struct fc_starget_attrs);
1971 transport_container_register(&i->t.target_attrs);
1972
1973 i->t.host_attrs.ac.attrs = &i->host_attrs[0];
1974 i->t.host_attrs.ac.class = &fc_host_class.class;
1975 i->t.host_attrs.ac.match = fc_host_match;
1976 i->t.host_size = sizeof(struct fc_host_attrs);
1977 if (ft->get_fc_host_stats)
1978 i->t.host_attrs.statistics = &fc_statistics_group;
1979 transport_container_register(&i->t.host_attrs);
1980
1981 i->rport_attr_cont.ac.attrs = &i->rport_attrs[0];
1982 i->rport_attr_cont.ac.class = &fc_rport_class.class;
1983 i->rport_attr_cont.ac.match = fc_rport_match;
1984 transport_container_register(&i->rport_attr_cont);
1985
a53eb5e0
JS
1986 i->vport_attr_cont.ac.attrs = &i->vport_attrs[0];
1987 i->vport_attr_cont.ac.class = &fc_vport_class.class;
1988 i->vport_attr_cont.ac.match = fc_vport_match;
1989 transport_container_register(&i->vport_attr_cont);
1990
1da177e4
LT
1991 i->f = ft;
1992
1993 /* Transport uses the shost workq for scsi scanning */
1994 i->t.create_work_queue = 1;
5c44cd2a 1995
c829c394
JS
1996 i->t.eh_timed_out = fc_timed_out;
1997
e02f3f59 1998 i->t.user_scan = fc_user_scan;
1da177e4
LT
1999
2000 /*
2001 * Setup SCSI Target Attributes.
2002 */
2003 count = 0;
2004 SETUP_STARGET_ATTRIBUTE_RD(node_name);
2005 SETUP_STARGET_ATTRIBUTE_RD(port_name);
2006 SETUP_STARGET_ATTRIBUTE_RD(port_id);
2007
2008 BUG_ON(count > FC_STARGET_NUM_ATTRS);
2009
2010 i->starget_attrs[count] = NULL;
2011
2012
2013 /*
2014 * Setup SCSI Host Attributes.
2015 */
2016 count=0;
2017 SETUP_HOST_ATTRIBUTE_RD(node_name);
2018 SETUP_HOST_ATTRIBUTE_RD(port_name);
6b7281d0 2019 SETUP_HOST_ATTRIBUTE_RD(permanent_port_name);
1da177e4
LT
2020 SETUP_HOST_ATTRIBUTE_RD(supported_classes);
2021 SETUP_HOST_ATTRIBUTE_RD(supported_fc4s);
1da177e4
LT
2022 SETUP_HOST_ATTRIBUTE_RD(supported_speeds);
2023 SETUP_HOST_ATTRIBUTE_RD(maxframe_size);
a53eb5e0
JS
2024 if (ft->vport_create) {
2025 SETUP_HOST_ATTRIBUTE_RD_NS(max_npiv_vports);
2026 SETUP_HOST_ATTRIBUTE_RD_NS(npiv_vports_inuse);
2027 }
1da177e4
LT
2028 SETUP_HOST_ATTRIBUTE_RD(serial_number);
2029
2030 SETUP_HOST_ATTRIBUTE_RD(port_id);
2031 SETUP_HOST_ATTRIBUTE_RD(port_type);
2032 SETUP_HOST_ATTRIBUTE_RD(port_state);
2033 SETUP_HOST_ATTRIBUTE_RD(active_fc4s);
2034 SETUP_HOST_ATTRIBUTE_RD(speed);
2035 SETUP_HOST_ATTRIBUTE_RD(fabric_name);
016131b8 2036 SETUP_HOST_ATTRIBUTE_RD(symbolic_name);
b8d08210 2037 SETUP_HOST_ATTRIBUTE_RW(system_hostname);
1da177e4
LT
2038
2039 /* Transport-managed attributes */
2040 SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type);
91ca7b01
AV
2041 if (ft->issue_fc_host_lip)
2042 SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip);
a53eb5e0
JS
2043 if (ft->vport_create)
2044 SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_create);
2045 if (ft->vport_delete)
2046 SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_delete);
1da177e4
LT
2047
2048 BUG_ON(count > FC_HOST_NUM_ATTRS);
2049
2050 i->host_attrs[count] = NULL;
2051
2052 /*
2053 * Setup Remote Port Attributes.
2054 */
2055 count=0;
2056 SETUP_RPORT_ATTRIBUTE_RD(maxframe_size);
2057 SETUP_RPORT_ATTRIBUTE_RD(supported_classes);
2058 SETUP_RPORT_ATTRIBUTE_RW(dev_loss_tmo);
2059 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(node_name);
2060 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_name);
2061 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_id);
2062 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(roles);
2063 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_state);
2064 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(scsi_target_id);
0f29b966
JS
2065 if (ft->terminate_rport_io)
2066 SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(fast_io_fail_tmo);
1da177e4
LT
2067
2068 BUG_ON(count > FC_RPORT_NUM_ATTRS);
2069
2070 i->rport_attrs[count] = NULL;
2071
a53eb5e0
JS
2072 /*
2073 * Setup Virtual Port Attributes.
2074 */
2075 count=0;
2076 SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_state);
2077 SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_last_state);
2078 SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(node_name);
2079 SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(port_name);
2080 SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(roles);
2081 SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_type);
2082 SETUP_VPORT_ATTRIBUTE_RW(symbolic_name);
2083 SETUP_VPORT_ATTRIBUTE_WR(vport_delete);
2084 SETUP_VPORT_ATTRIBUTE_WR(vport_disable);
2085
2086 BUG_ON(count > FC_VPORT_NUM_ATTRS);
2087
2088 i->vport_attrs[count] = NULL;
2089
1da177e4
LT
2090 return &i->t;
2091}
2092EXPORT_SYMBOL(fc_attach_transport);
2093
2094void fc_release_transport(struct scsi_transport_template *t)
2095{
2096 struct fc_internal *i = to_fc_internal(t);
2097
2098 transport_container_unregister(&i->t.target_attrs);
2099 transport_container_unregister(&i->t.host_attrs);
2100 transport_container_unregister(&i->rport_attr_cont);
a53eb5e0 2101 transport_container_unregister(&i->vport_attr_cont);
1da177e4
LT
2102
2103 kfree(i);
2104}
2105EXPORT_SYMBOL(fc_release_transport);
2106
aedf3497
JS
2107/**
2108 * fc_queue_work - Queue work to the fc_host workqueue.
2109 * @shost: Pointer to Scsi_Host bound to fc_host.
2110 * @work: Work to queue for execution.
2111 *
2112 * Return value:
a0785edf
JS
2113 * 1 - work queued for execution
2114 * 0 - work is already queued
2115 * -EINVAL - work queue doesn't exist
aedf3497
JS
2116 **/
2117static int
2118fc_queue_work(struct Scsi_Host *shost, struct work_struct *work)
2119{
2120 if (unlikely(!fc_host_work_q(shost))) {
2121 printk(KERN_ERR
2122 "ERROR: FC host '%s' attempted to queue work, "
2123 "when no workqueue created.\n", shost->hostt->name);
2124 dump_stack();
2125
2126 return -EINVAL;
2127 }
2128
2129 return queue_work(fc_host_work_q(shost), work);
2130}
2131
2132/**
2133 * fc_flush_work - Flush a fc_host's workqueue.
2134 * @shost: Pointer to Scsi_Host bound to fc_host.
2135 **/
2136static void
2137fc_flush_work(struct Scsi_Host *shost)
2138{
2139 if (!fc_host_work_q(shost)) {
2140 printk(KERN_ERR
2141 "ERROR: FC host '%s' attempted to flush work, "
2142 "when no workqueue created.\n", shost->hostt->name);
2143 dump_stack();
2144 return;
2145 }
2146
2147 flush_workqueue(fc_host_work_q(shost));
2148}
2149
2150/**
2151 * fc_queue_devloss_work - Schedule work for the fc_host devloss workqueue.
2152 * @shost: Pointer to Scsi_Host bound to fc_host.
2153 * @work: Work to queue for execution.
2154 * @delay: jiffies to delay the work queuing
2155 *
2156 * Return value:
0f29b966 2157 * 1 on success / 0 already queued / < 0 for error
aedf3497
JS
2158 **/
2159static int
c4028958 2160fc_queue_devloss_work(struct Scsi_Host *shost, struct delayed_work *work,
aedf3497
JS
2161 unsigned long delay)
2162{
2163 if (unlikely(!fc_host_devloss_work_q(shost))) {
2164 printk(KERN_ERR
2165 "ERROR: FC host '%s' attempted to queue work, "
2166 "when no workqueue created.\n", shost->hostt->name);
2167 dump_stack();
2168
2169 return -EINVAL;
2170 }
2171
2172 return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay);
2173}
2174
2175/**
2176 * fc_flush_devloss - Flush a fc_host's devloss workqueue.
2177 * @shost: Pointer to Scsi_Host bound to fc_host.
2178 **/
2179static void
2180fc_flush_devloss(struct Scsi_Host *shost)
2181{
2182 if (!fc_host_devloss_work_q(shost)) {
2183 printk(KERN_ERR
2184 "ERROR: FC host '%s' attempted to flush work, "
2185 "when no workqueue created.\n", shost->hostt->name);
2186 dump_stack();
2187 return;
2188 }
2189
2190 flush_workqueue(fc_host_devloss_work_q(shost));
2191}
2192
1da177e4
LT
2193
2194/**
2195 * fc_remove_host - called to terminate any fc_transport-related elements
2196 * for a scsi host.
2197 * @rport: remote port to be unblocked.
2198 *
2199 * This routine is expected to be called immediately preceeding the
2200 * a driver's call to scsi_remove_host().
2201 *
2202 * WARNING: A driver utilizing the fc_transport, which fails to call
2203 * this routine prior to scsi_remote_host(), will leave dangling
2204 * objects in /sys/class/fc_remote_ports. Access to any of these
2205 * objects can result in a system crash !!!
2206 *
2207 * Notes:
2208 * This routine assumes no locks are held on entry.
2209 **/
2210void
2211fc_remove_host(struct Scsi_Host *shost)
2212{
a53eb5e0
JS
2213 struct fc_vport *vport = NULL, *next_vport = NULL;
2214 struct fc_rport *rport = NULL, *next_rport = NULL;
aedf3497
JS
2215 struct workqueue_struct *work_q;
2216 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
a53eb5e0
JS
2217 unsigned long flags;
2218 int stat;
2219
2220 spin_lock_irqsave(shost->host_lock, flags);
2221
2222 /* Remove any vports */
2223 list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers) {
2224 spin_unlock_irqrestore(shost->host_lock, flags);
2225 /* this must be called synchronously */
2226 stat = fc_vport_terminate(vport);
2227 spin_lock_irqsave(shost->host_lock, flags);
2228 if (stat)
2229 dev_printk(KERN_ERR, vport->dev.parent,
2230 "%s: %s could not be deleted created via "
2231 "shost%d channel %d\n", __FUNCTION__,
2232 vport->dev.bus_id, vport->shost->host_no,
2233 vport->channel);
2234 }
1da177e4
LT
2235
2236 /* Remove any remote ports */
2237 list_for_each_entry_safe(rport, next_rport,
aedf3497
JS
2238 &fc_host->rports, peers) {
2239 list_del(&rport->peers);
2240 rport->port_state = FC_PORTSTATE_DELETED;
2241 fc_queue_work(shost, &rport->rport_delete_work);
2242 }
2243
1da177e4 2244 list_for_each_entry_safe(rport, next_rport,
aedf3497
JS
2245 &fc_host->rport_bindings, peers) {
2246 list_del(&rport->peers);
2247 rport->port_state = FC_PORTSTATE_DELETED;
2248 fc_queue_work(shost, &rport->rport_delete_work);
2249 }
2250
a53eb5e0
JS
2251 spin_unlock_irqrestore(shost->host_lock, flags);
2252
aedf3497
JS
2253 /* flush all scan work items */
2254 scsi_flush_work(shost);
2255
2256 /* flush all stgt delete, and rport delete work items, then kill it */
2257 if (fc_host->work_q) {
2258 work_q = fc_host->work_q;
2259 fc_host->work_q = NULL;
2260 destroy_workqueue(work_q);
2261 }
2262
2263 /* flush all devloss work items, then kill it */
2264 if (fc_host->devloss_work_q) {
2265 work_q = fc_host->devloss_work_q;
2266 fc_host->devloss_work_q = NULL;
2267 destroy_workqueue(work_q);
2268 }
1da177e4
LT
2269}
2270EXPORT_SYMBOL(fc_remove_host);
2271
aedf3497
JS
2272
2273/**
2274 * fc_starget_delete - called to delete the scsi decendents of an rport
2275 * (target and all sdevs)
2276 *
c4028958 2277 * @work: remote port to be operated on.
aedf3497 2278 **/
19a7b4ae 2279static void
c4028958 2280fc_starget_delete(struct work_struct *work)
19a7b4ae 2281{
c4028958
DH
2282 struct fc_rport *rport =
2283 container_of(work, struct fc_rport, stgt_delete_work);
19a7b4ae 2284 struct Scsi_Host *shost = rport_to_shost(rport);
0f29b966
JS
2285 struct fc_internal *i = to_fc_internal(shost->transportt);
2286
92740b24
JS
2287 /* Involve the LLDD if possible to terminate all io on the rport. */
2288 if (i->f->terminate_rport_io)
0f29b966 2289 i->f->terminate_rport_io(rport);
19a7b4ae 2290
19a7b4ae
JSEC
2291 scsi_remove_target(&rport->dev);
2292}
2293
aedf3497
JS
2294
2295/**
2296 * fc_rport_final_delete - finish rport termination and delete it.
2297 *
c4028958 2298 * @work: remote port to be deleted.
aedf3497
JS
2299 **/
2300static void
c4028958 2301fc_rport_final_delete(struct work_struct *work)
aedf3497 2302{
c4028958
DH
2303 struct fc_rport *rport =
2304 container_of(work, struct fc_rport, rport_delete_work);
aedf3497
JS
2305 struct device *dev = &rport->dev;
2306 struct Scsi_Host *shost = rport_to_shost(rport);
0f29b966 2307 struct fc_internal *i = to_fc_internal(shost->transportt);
92740b24 2308 unsigned long flags;
aedf3497
JS
2309
2310 /*
2311 * if a scan is pending, flush the SCSI Host work_q so that
2312 * that we can reclaim the rport scan work element.
2313 */
2314 if (rport->flags & FC_RPORT_SCAN_PENDING)
2315 scsi_flush_work(shost);
2316
92740b24
JS
2317 /* involve the LLDD to terminate all pending i/o */
2318 if (i->f->terminate_rport_io)
2319 i->f->terminate_rport_io(rport);
2320
2321 /*
2322 * Cancel any outstanding timers. These should really exist
2323 * only when rmmod'ing the LLDD and we're asking for
2324 * immediate termination of the rports
2325 */
2326 spin_lock_irqsave(shost->host_lock, flags);
2327 if (rport->flags & FC_RPORT_DEVLOSS_PENDING) {
2328 spin_unlock_irqrestore(shost->host_lock, flags);
2329 if (!cancel_delayed_work(&rport->fail_io_work))
2330 fc_flush_devloss(shost);
2331 if (!cancel_delayed_work(&rport->dev_loss_work))
2332 fc_flush_devloss(shost);
2333 spin_lock_irqsave(shost->host_lock, flags);
2334 rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
2335 }
2336 spin_unlock_irqrestore(shost->host_lock, flags);
2337
0f29b966
JS
2338 /* Delete SCSI target and sdevs */
2339 if (rport->scsi_target_id != -1)
c4028958 2340 fc_starget_delete(&rport->stgt_delete_work);
92740b24
JS
2341
2342 /*
2343 * Notify the driver that the rport is now dead. The LLDD will
2344 * also guarantee that any communication to the rport is terminated
2345 */
2346 if (i->f->dev_loss_tmo_callbk)
0f29b966 2347 i->f->dev_loss_tmo_callbk(rport);
0f29b966 2348
aedf3497
JS
2349 transport_remove_device(dev);
2350 device_del(dev);
2351 transport_destroy_device(dev);
3bdad7bd
JS
2352 put_device(&shost->shost_gendev); /* for fc_host->rport list */
2353 put_device(dev); /* for self-reference */
aedf3497
JS
2354}
2355
2356
1da177e4
LT
2357/**
2358 * fc_rport_create - allocates and creates a remote FC port.
2359 * @shost: scsi host the remote port is connected to.
2360 * @channel: Channel on shost port connected to.
2361 * @ids: The world wide names, fc address, and FC4 port
2362 * roles for the remote port.
2363 *
2364 * Allocates and creates the remoter port structure, including the
2365 * class and sysfs creation.
2366 *
2367 * Notes:
2368 * This routine assumes no locks are held on entry.
2369 **/
2370struct fc_rport *
2371fc_rport_create(struct Scsi_Host *shost, int channel,
2372 struct fc_rport_identifiers *ids)
2373{
aedf3497 2374 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
1da177e4
LT
2375 struct fc_internal *fci = to_fc_internal(shost->transportt);
2376 struct fc_rport *rport;
2377 struct device *dev;
2378 unsigned long flags;
2379 int error;
2380 size_t size;
2381
2382 size = (sizeof(struct fc_rport) + fci->f->dd_fcrport_size);
24669f75 2383 rport = kzalloc(size, GFP_KERNEL);
1da177e4
LT
2384 if (unlikely(!rport)) {
2385 printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
2386 return NULL;
2387 }
1da177e4
LT
2388
2389 rport->maxframe_size = -1;
2390 rport->supported_classes = FC_COS_UNSPECIFIED;
2391 rport->dev_loss_tmo = fc_dev_loss_tmo;
2392 memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name));
2393 memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name));
2394 rport->port_id = ids->port_id;
2395 rport->roles = ids->roles;
2396 rport->port_state = FC_PORTSTATE_ONLINE;
2397 if (fci->f->dd_fcrport_size)
2398 rport->dd_data = &rport[1];
2399 rport->channel = channel;
0f29b966 2400 rport->fast_io_fail_tmo = -1;
1da177e4 2401
c4028958
DH
2402 INIT_DELAYED_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport);
2403 INIT_DELAYED_WORK(&rport->fail_io_work, fc_timeout_fail_rport_io);
2404 INIT_WORK(&rport->scan_work, fc_scsi_scan_rport);
2405 INIT_WORK(&rport->stgt_delete_work, fc_starget_delete);
2406 INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete);
1da177e4
LT
2407
2408 spin_lock_irqsave(shost->host_lock, flags);
2409
2410 rport->number = fc_host->next_rport_number++;
a53eb5e0 2411 if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
1da177e4
LT
2412 rport->scsi_target_id = fc_host->next_target_id++;
2413 else
2414 rport->scsi_target_id = -1;
aedf3497 2415 list_add_tail(&rport->peers, &fc_host->rports);
3bdad7bd 2416 get_device(&shost->shost_gendev); /* for fc_host->rport list */
1da177e4
LT
2417
2418 spin_unlock_irqrestore(shost->host_lock, flags);
2419
2420 dev = &rport->dev;
3bdad7bd
JS
2421 device_initialize(dev); /* takes self reference */
2422 dev->parent = get_device(&shost->shost_gendev); /* parent reference */
1da177e4
LT
2423 dev->release = fc_rport_dev_release;
2424 sprintf(dev->bus_id, "rport-%d:%d-%d",
2425 shost->host_no, channel, rport->number);
2426 transport_setup_device(dev);
2427
2428 error = device_add(dev);
2429 if (error) {
2430 printk(KERN_ERR "FC Remote Port device_add failed\n");
2431 goto delete_rport;
2432 }
2433 transport_add_device(dev);
2434 transport_configure_device(dev);
2435
a53eb5e0 2436 if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
1da177e4 2437 /* initiate a scan of the target */
aedf3497 2438 rport->flags |= FC_RPORT_SCAN_PENDING;
1da177e4 2439 scsi_queue_work(shost, &rport->scan_work);
aedf3497 2440 }
1da177e4
LT
2441
2442 return rport;
2443
2444delete_rport:
2445 transport_destroy_device(dev);
1da177e4
LT
2446 spin_lock_irqsave(shost->host_lock, flags);
2447 list_del(&rport->peers);
3bdad7bd 2448 put_device(&shost->shost_gendev); /* for fc_host->rport list */
1da177e4
LT
2449 spin_unlock_irqrestore(shost->host_lock, flags);
2450 put_device(dev->parent);
2451 kfree(rport);
2452 return NULL;
2453}
2454
2455/**
2456 * fc_remote_port_add - notifies the fc transport of the existence
2457 * of a remote FC port.
2458 * @shost: scsi host the remote port is connected to.
2459 * @channel: Channel on shost port connected to.
2460 * @ids: The world wide names, fc address, and FC4 port
2461 * roles for the remote port.
2462 *
2463 * The LLDD calls this routine to notify the transport of the existence
2464 * of a remote port. The LLDD provides the unique identifiers (wwpn,wwn)
2465 * of the port, it's FC address (port_id), and the FC4 roles that are
2466 * active for the port.
2467 *
2468 * For ports that are FCP targets (aka scsi targets), the FC transport
2469 * maintains consistent target id bindings on behalf of the LLDD.
2470 * A consistent target id binding is an assignment of a target id to
2471 * a remote port identifier, which persists while the scsi host is
2472 * attached. The remote port can disappear, then later reappear, and
2473 * it's target id assignment remains the same. This allows for shifts
2474 * in FC addressing (if binding by wwpn or wwnn) with no apparent
2475 * changes to the scsi subsystem which is based on scsi host number and
2476 * target id values. Bindings are only valid during the attachment of
2477 * the scsi host. If the host detaches, then later re-attaches, target
2478 * id bindings may change.
2479 *
2480 * This routine is responsible for returning a remote port structure.
2481 * The routine will search the list of remote ports it maintains
2482 * internally on behalf of consistent target id mappings. If found, the
2483 * remote port structure will be reused. Otherwise, a new remote port
2484 * structure will be allocated.
2485 *
2486 * Whenever a remote port is allocated, a new fc_remote_port class
2487 * device is created.
2488 *
2489 * Should not be called from interrupt context.
2490 *
2491 * Notes:
2492 * This routine assumes no locks are held on entry.
2493 **/
2494struct fc_rport *
2495fc_remote_port_add(struct Scsi_Host *shost, int channel,
2496 struct fc_rport_identifiers *ids)
2497{
19a7b4ae 2498 struct fc_internal *fci = to_fc_internal(shost->transportt);
aedf3497 2499 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
1da177e4
LT
2500 struct fc_rport *rport;
2501 unsigned long flags;
2502 int match = 0;
2503
aedf3497
JS
2504 /* ensure any stgt delete functions are done */
2505 fc_flush_work(shost);
2506
19a7b4ae
JSEC
2507 /*
2508 * Search the list of "active" rports, for an rport that has been
2509 * deleted, but we've held off the real delete while the target
2510 * is in a "blocked" state.
2511 */
2512 spin_lock_irqsave(shost->host_lock, flags);
2513
aedf3497 2514 list_for_each_entry(rport, &fc_host->rports, peers) {
19a7b4ae
JSEC
2515
2516 if ((rport->port_state == FC_PORTSTATE_BLOCKED) &&
2517 (rport->channel == channel)) {
2518
aedf3497 2519 switch (fc_host->tgtid_bind_type) {
19a7b4ae
JSEC
2520 case FC_TGTID_BIND_BY_WWPN:
2521 case FC_TGTID_BIND_NONE:
2522 if (rport->port_name == ids->port_name)
2523 match = 1;
2524 break;
2525 case FC_TGTID_BIND_BY_WWNN:
2526 if (rport->node_name == ids->node_name)
2527 match = 1;
2528 break;
2529 case FC_TGTID_BIND_BY_ID:
2530 if (rport->port_id == ids->port_id)
2531 match = 1;
2532 break;
2533 }
2534
2535 if (match) {
19a7b4ae
JSEC
2536
2537 memcpy(&rport->node_name, &ids->node_name,
2538 sizeof(rport->node_name));
2539 memcpy(&rport->port_name, &ids->port_name,
2540 sizeof(rport->port_name));
2541 rport->port_id = ids->port_id;
2542
2543 rport->port_state = FC_PORTSTATE_ONLINE;
2544 rport->roles = ids->roles;
2545
2546 spin_unlock_irqrestore(shost->host_lock, flags);
2547
2548 if (fci->f->dd_fcrport_size)
2549 memset(rport->dd_data, 0,
2550 fci->f->dd_fcrport_size);
2551
2552 /*
92740b24
JS
2553 * If we were not a target, cancel the
2554 * io terminate and rport timers, and
2555 * we're done.
2556 *
2557 * If we were a target, but our new role
2558 * doesn't indicate a target, leave the
2559 * timers running expecting the role to
2560 * change as the target fully logs in. If
2561 * it doesn't, the target will be torn down.
2562 *
2563 * If we were a target, and our role shows
2564 * we're still a target, cancel the timers
2565 * and kick off a scan.
19a7b4ae 2566 */
19a7b4ae 2567
92740b24
JS
2568 /* was a target, not in roles */
2569 if ((rport->scsi_target_id != -1) &&
a53eb5e0 2570 (!(ids->roles & FC_PORT_ROLE_FCP_TARGET)))
92740b24 2571 return rport;
19a7b4ae
JSEC
2572
2573 /*
92740b24
JS
2574 * Stop the fail io and dev_loss timers.
2575 * If they flush, the port_state will
2576 * be checked and will NOOP the function.
19a7b4ae 2577 */
0f29b966
JS
2578 if (!cancel_delayed_work(&rport->fail_io_work))
2579 fc_flush_devloss(shost);
92740b24 2580 if (!cancel_delayed_work(&rport->dev_loss_work))
aedf3497
JS
2581 fc_flush_devloss(shost);
2582
2583 spin_lock_irqsave(shost->host_lock, flags);
2584
2585 rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
19a7b4ae 2586
92740b24
JS
2587 /* if target, initiate a scan */
2588 if (rport->scsi_target_id != -1) {
2589 rport->flags |= FC_RPORT_SCAN_PENDING;
2590 scsi_queue_work(shost,
2591 &rport->scan_work);
2592 spin_unlock_irqrestore(shost->host_lock,
2593 flags);
2594 scsi_target_unblock(&rport->dev);
2595 } else
2596 spin_unlock_irqrestore(shost->host_lock,
2597 flags);
a0785edf 2598
19a7b4ae
JSEC
2599 return rport;
2600 }
2601 }
2602 }
2603
92740b24
JS
2604 /*
2605 * Search the bindings array
2606 * Note: if never a FCP target, you won't be on this list
2607 */
aedf3497 2608 if (fc_host->tgtid_bind_type != FC_TGTID_BIND_NONE) {
1da177e4
LT
2609
2610 /* search for a matching consistent binding */
2611
aedf3497 2612 list_for_each_entry(rport, &fc_host->rport_bindings,
1da177e4
LT
2613 peers) {
2614 if (rport->channel != channel)
2615 continue;
2616
aedf3497 2617 switch (fc_host->tgtid_bind_type) {
1da177e4
LT
2618 case FC_TGTID_BIND_BY_WWPN:
2619 if (rport->port_name == ids->port_name)
2620 match = 1;
2621 break;
2622 case FC_TGTID_BIND_BY_WWNN:
2623 if (rport->node_name == ids->node_name)
2624 match = 1;
2625 break;
2626 case FC_TGTID_BIND_BY_ID:
2627 if (rport->port_id == ids->port_id)
2628 match = 1;
2629 break;
2630 case FC_TGTID_BIND_NONE: /* to keep compiler happy */
2631 break;
2632 }
2633
2634 if (match) {
aedf3497 2635 list_move_tail(&rport->peers, &fc_host->rports);
1da177e4
LT
2636 break;
2637 }
2638 }
2639
1da177e4
LT
2640 if (match) {
2641 memcpy(&rport->node_name, &ids->node_name,
2642 sizeof(rport->node_name));
2643 memcpy(&rport->port_name, &ids->port_name,
2644 sizeof(rport->port_name));
2645 rport->port_id = ids->port_id;
2646 rport->roles = ids->roles;
2647 rport->port_state = FC_PORTSTATE_ONLINE;
2648
19a7b4ae
JSEC
2649 if (fci->f->dd_fcrport_size)
2650 memset(rport->dd_data, 0,
2651 fci->f->dd_fcrport_size);
2652
a53eb5e0 2653 if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
1da177e4 2654 /* initiate a scan of the target */
aedf3497 2655 rport->flags |= FC_RPORT_SCAN_PENDING;
1da177e4 2656 scsi_queue_work(shost, &rport->scan_work);
a0785edf
JS
2657 spin_unlock_irqrestore(shost->host_lock, flags);
2658 scsi_target_unblock(&rport->dev);
2659 } else
2660 spin_unlock_irqrestore(shost->host_lock, flags);
1da177e4
LT
2661
2662 return rport;
2663 }
2664 }
2665
19a7b4ae
JSEC
2666 spin_unlock_irqrestore(shost->host_lock, flags);
2667
1da177e4
LT
2668 /* No consistent binding found - create new remote port entry */
2669 rport = fc_rport_create(shost, channel, ids);
2670
2671 return rport;
2672}
2673EXPORT_SYMBOL(fc_remote_port_add);
2674
1da177e4
LT
2675
2676/**
2677 * fc_remote_port_delete - notifies the fc transport that a remote
2678 * port is no longer in existence.
2679 * @rport: The remote port that no longer exists
2680 *
2681 * The LLDD calls this routine to notify the transport that a remote
2682 * port is no longer part of the topology. Note: Although a port
2683 * may no longer be part of the topology, it may persist in the remote
19a7b4ae
JSEC
2684 * ports displayed by the fc_host. We do this under 2 conditions:
2685 * - If the port was a scsi target, we delay its deletion by "blocking" it.
2686 * This allows the port to temporarily disappear, then reappear without
2687 * disrupting the SCSI device tree attached to it. During the "blocked"
2688 * period the port will still exist.
2689 * - If the port was a scsi target and disappears for longer than we
2690 * expect, we'll delete the port and the tear down the SCSI device tree
2691 * attached to it. However, we want to semi-persist the target id assigned
2692 * to that port if it eventually does exist. The port structure will
2693 * remain (although with minimal information) so that the target id
2694 * bindings remails.
1da177e4
LT
2695 *
2696 * If the remote port is not an FCP Target, it will be fully torn down
2697 * and deallocated, including the fc_remote_port class device.
2698 *
19a7b4ae
JSEC
2699 * If the remote port is an FCP Target, the port will be placed in a
2700 * temporary blocked state. From the LLDD's perspective, the rport no
2701 * longer exists. From the SCSI midlayer's perspective, the SCSI target
2702 * exists, but all sdevs on it are blocked from further I/O. The following
2703 * is then expected:
2704 * If the remote port does not return (signaled by a LLDD call to
2705 * fc_remote_port_add()) within the dev_loss_tmo timeout, then the
2706 * scsi target is removed - killing all outstanding i/o and removing the
2707 * scsi devices attached ot it. The port structure will be marked Not
2708 * Present and be partially cleared, leaving only enough information to
2709 * recognize the remote port relative to the scsi target id binding if
2710 * it later appears. The port will remain as long as there is a valid
2711 * binding (e.g. until the user changes the binding type or unloads the
2712 * scsi host with the binding).
1da177e4 2713 *
19a7b4ae
JSEC
2714 * If the remote port returns within the dev_loss_tmo value (and matches
2715 * according to the target id binding type), the port structure will be
2716 * reused. If it is no longer a SCSI target, the target will be torn
2717 * down. If it continues to be a SCSI target, then the target will be
2718 * unblocked (allowing i/o to be resumed), and a scan will be activated
2719 * to ensure that all luns are detected.
2720 *
2721 * Called from normal process context only - cannot be called from interrupt.
1da177e4
LT
2722 *
2723 * Notes:
2724 * This routine assumes no locks are held on entry.
2725 **/
2726void
2727fc_remote_port_delete(struct fc_rport *rport)
2728{
aedf3497 2729 struct Scsi_Host *shost = rport_to_shost(rport);
0f29b966 2730 struct fc_internal *i = to_fc_internal(shost->transportt);
19a7b4ae 2731 int timeout = rport->dev_loss_tmo;
aedf3497
JS
2732 unsigned long flags;
2733
2734 /*
2735 * No need to flush the fc_host work_q's, as all adds are synchronous.
2736 *
2737 * We do need to reclaim the rport scan work element, so eventually
2738 * (in fc_rport_final_delete()) we'll flush the scsi host work_q if
2739 * there's still a scan pending.
2740 */
2741
2742 spin_lock_irqsave(shost->host_lock, flags);
1da177e4 2743
92740b24 2744 if (rport->port_state != FC_PORTSTATE_ONLINE) {
aedf3497 2745 spin_unlock_irqrestore(shost->host_lock, flags);
1da177e4
LT
2746 return;
2747 }
2748
92740b24
JS
2749 /*
2750 * In the past, we if this was not an FCP-Target, we would
2751 * unconditionally just jump to deleting the rport.
2752 * However, rports can be used as node containers by the LLDD,
2753 * and its not appropriate to just terminate the rport at the
2754 * first sign of a loss in connectivity. The LLDD may want to
2755 * send ELS traffic to re-validate the login. If the rport is
2756 * immediately deleted, it makes it inappropriate for a node
2757 * container.
2758 * So... we now unconditionally wait dev_loss_tmo before
2759 * destroying an rport.
2760 */
2761
aedf3497
JS
2762 rport->port_state = FC_PORTSTATE_BLOCKED;
2763
2764 rport->flags |= FC_RPORT_DEVLOSS_PENDING;
2765
2766 spin_unlock_irqrestore(shost->host_lock, flags);
2767
19a7b4ae 2768 scsi_target_block(&rport->dev);
1da177e4 2769
0f29b966
JS
2770 /* see if we need to kill io faster than waiting for device loss */
2771 if ((rport->fast_io_fail_tmo != -1) &&
2772 (rport->fast_io_fail_tmo < timeout) && (i->f->terminate_rport_io))
2773 fc_queue_devloss_work(shost, &rport->fail_io_work,
2774 rport->fast_io_fail_tmo * HZ);
2775
19a7b4ae 2776 /* cap the length the devices can be blocked until they are deleted */
aedf3497 2777 fc_queue_devloss_work(shost, &rport->dev_loss_work, timeout * HZ);
1da177e4
LT
2778}
2779EXPORT_SYMBOL(fc_remote_port_delete);
2780
2781/**
2782 * fc_remote_port_rolechg - notifies the fc transport that the roles
2783 * on a remote may have changed.
2784 * @rport: The remote port that changed.
2785 *
2786 * The LLDD calls this routine to notify the transport that the roles
2787 * on a remote port may have changed. The largest effect of this is
2788 * if a port now becomes a FCP Target, it must be allocated a
2789 * scsi target id. If the port is no longer a FCP target, any
2790 * scsi target id value assigned to it will persist in case the
2791 * role changes back to include FCP Target. No changes in the scsi
2792 * midlayer will be invoked if the role changes (in the expectation
2793 * that the role will be resumed. If it doesn't normal error processing
2794 * will take place).
2795 *
2796 * Should not be called from interrupt context.
2797 *
2798 * Notes:
2799 * This routine assumes no locks are held on entry.
2800 **/
2801void
2802fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
2803{
2804 struct Scsi_Host *shost = rport_to_shost(rport);
aedf3497 2805 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
1da177e4
LT
2806 unsigned long flags;
2807 int create = 0;
2808
1da177e4 2809 spin_lock_irqsave(shost->host_lock, flags);
a53eb5e0 2810 if (roles & FC_PORT_ROLE_FCP_TARGET) {
19a7b4ae
JSEC
2811 if (rport->scsi_target_id == -1) {
2812 rport->scsi_target_id = fc_host->next_target_id++;
2813 create = 1;
a53eb5e0 2814 } else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET))
19a7b4ae 2815 create = 1;
1da177e4 2816 }
1da177e4 2817
19a7b4ae
JSEC
2818 rport->roles = roles;
2819
aedf3497
JS
2820 spin_unlock_irqrestore(shost->host_lock, flags);
2821
19a7b4ae
JSEC
2822 if (create) {
2823 /*
2824 * There may have been a delete timer running on the
2825 * port. Ensure that it is cancelled as we now know
2826 * the port is an FCP Target.
2827 * Note: we know the rport is exists and in an online
2828 * state as the LLDD would not have had an rport
2829 * reference to pass us.
2830 *
2831 * Take no action on the del_timer failure as the state
2832 * machine state change will validate the
2833 * transaction.
2834 */
0f29b966
JS
2835 if (!cancel_delayed_work(&rport->fail_io_work))
2836 fc_flush_devloss(shost);
19a7b4ae 2837 if (!cancel_delayed_work(&rport->dev_loss_work))
aedf3497
JS
2838 fc_flush_devloss(shost);
2839
2840 spin_lock_irqsave(shost->host_lock, flags);
2841 rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
2842 spin_unlock_irqrestore(shost->host_lock, flags);
2843
2844 /* ensure any stgt delete functions are done */
2845 fc_flush_work(shost);
19a7b4ae 2846
1da177e4 2847 /* initiate a scan of the target */
aedf3497
JS
2848 spin_lock_irqsave(shost->host_lock, flags);
2849 rport->flags |= FC_RPORT_SCAN_PENDING;
1da177e4 2850 scsi_queue_work(shost, &rport->scan_work);
aedf3497 2851 spin_unlock_irqrestore(shost->host_lock, flags);
a0785edf 2852 scsi_target_unblock(&rport->dev);
19a7b4ae 2853 }
1da177e4
LT
2854}
2855EXPORT_SYMBOL(fc_remote_port_rolechg);
2856
2857/**
92740b24
JS
2858 * fc_timeout_deleted_rport - Timeout handler for a deleted remote port,
2859 * which we blocked, and has now failed to return
2860 * in the allotted time.
19a7b4ae 2861 *
92740b24 2862 * @work: rport target that failed to reappear in the allotted time.
1da177e4
LT
2863 **/
2864static void
c4028958 2865fc_timeout_deleted_rport(struct work_struct *work)
1da177e4 2866{
c4028958
DH
2867 struct fc_rport *rport =
2868 container_of(work, struct fc_rport, dev_loss_work.work);
19a7b4ae 2869 struct Scsi_Host *shost = rport_to_shost(rport);
aedf3497 2870 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
19a7b4ae 2871 unsigned long flags;
1da177e4 2872
19a7b4ae 2873 spin_lock_irqsave(shost->host_lock, flags);
1da177e4 2874
aedf3497
JS
2875 rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
2876
1da177e4 2877 /*
92740b24
JS
2878 * If the port is ONLINE, then it came back. If it was a SCSI
2879 * target, validate it still is. If not, tear down the
2880 * scsi_target on it.
1da177e4 2881 */
aedf3497 2882 if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
92740b24 2883 (rport->scsi_target_id != -1) &&
a53eb5e0 2884 !(rport->roles & FC_PORT_ROLE_FCP_TARGET)) {
19a7b4ae 2885 dev_printk(KERN_ERR, &rport->dev,
aedf3497
JS
2886 "blocked FC remote port time out: no longer"
2887 " a FCP target, removing starget\n");
aedf3497 2888 spin_unlock_irqrestore(shost->host_lock, flags);
a0785edf
JS
2889 scsi_target_unblock(&rport->dev);
2890 fc_queue_work(shost, &rport->stgt_delete_work);
19a7b4ae
JSEC
2891 return;
2892 }
1da177e4 2893
92740b24 2894 /* NOOP state - we're flushing workq's */
19a7b4ae
JSEC
2895 if (rport->port_state != FC_PORTSTATE_BLOCKED) {
2896 spin_unlock_irqrestore(shost->host_lock, flags);
2897 dev_printk(KERN_ERR, &rport->dev,
92740b24
JS
2898 "blocked FC remote port time out: leaving"
2899 " rport%s alone\n",
2900 (rport->scsi_target_id != -1) ? " and starget" : "");
19a7b4ae
JSEC
2901 return;
2902 }
1da177e4 2903
92740b24
JS
2904 if ((fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE) ||
2905 (rport->scsi_target_id == -1)) {
aedf3497
JS
2906 list_del(&rport->peers);
2907 rport->port_state = FC_PORTSTATE_DELETED;
19a7b4ae 2908 dev_printk(KERN_ERR, &rport->dev,
92740b24
JS
2909 "blocked FC remote port time out: removing"
2910 " rport%s\n",
2911 (rport->scsi_target_id != -1) ? " and starget" : "");
aedf3497
JS
2912 fc_queue_work(shost, &rport->rport_delete_work);
2913 spin_unlock_irqrestore(shost->host_lock, flags);
19a7b4ae
JSEC
2914 return;
2915 }
1da177e4 2916
19a7b4ae
JSEC
2917 dev_printk(KERN_ERR, &rport->dev,
2918 "blocked FC remote port time out: removing target and "
2919 "saving binding\n");
2920
aedf3497 2921 list_move_tail(&rport->peers, &fc_host->rport_bindings);
1da177e4
LT
2922
2923 /*
19a7b4ae
JSEC
2924 * Note: We do not remove or clear the hostdata area. This allows
2925 * host-specific target data to persist along with the
2926 * scsi_target_id. It's up to the host to manage it's hostdata area.
1da177e4 2927 */
1da177e4 2928
19a7b4ae
JSEC
2929 /*
2930 * Reinitialize port attributes that may change if the port comes back.
2931 */
2932 rport->maxframe_size = -1;
2933 rport->supported_classes = FC_COS_UNSPECIFIED;
a53eb5e0 2934 rport->roles = FC_PORT_ROLE_UNKNOWN;
aedf3497 2935 rport->port_state = FC_PORTSTATE_NOTPRESENT;
1da177e4 2936
19a7b4ae 2937 /* remove the identifiers that aren't used in the consisting binding */
aedf3497 2938 switch (fc_host->tgtid_bind_type) {
19a7b4ae
JSEC
2939 case FC_TGTID_BIND_BY_WWPN:
2940 rport->node_name = -1;
2941 rport->port_id = -1;
2942 break;
2943 case FC_TGTID_BIND_BY_WWNN:
2944 rport->port_name = -1;
2945 rport->port_id = -1;
2946 break;
2947 case FC_TGTID_BIND_BY_ID:
2948 rport->node_name = -1;
2949 rport->port_name = -1;
2950 break;
2951 case FC_TGTID_BIND_NONE: /* to keep compiler happy */
2952 break;
2953 }
2954
19a7b4ae
JSEC
2955 /*
2956 * As this only occurs if the remote port (scsi target)
2957 * went away and didn't come back - we'll remove
2958 * all attached scsi devices.
2959 */
42e33148 2960 spin_unlock_irqrestore(shost->host_lock, flags);
a0785edf
JS
2961
2962 scsi_target_unblock(&rport->dev);
2963 fc_queue_work(shost, &rport->stgt_delete_work);
1da177e4 2964}
1da177e4 2965
0f29b966
JS
2966/**
2967 * fc_timeout_fail_rport_io - Timeout handler for a fast io failing on a
2968 * disconnected SCSI target.
2969 *
c4028958 2970 * @work: rport to terminate io on.
0f29b966
JS
2971 *
2972 * Notes: Only requests the failure of the io, not that all are flushed
2973 * prior to returning.
2974 **/
2975static void
c4028958 2976fc_timeout_fail_rport_io(struct work_struct *work)
0f29b966 2977{
c4028958
DH
2978 struct fc_rport *rport =
2979 container_of(work, struct fc_rport, fail_io_work.work);
0f29b966
JS
2980 struct Scsi_Host *shost = rport_to_shost(rport);
2981 struct fc_internal *i = to_fc_internal(shost->transportt);
2982
2983 if (rport->port_state != FC_PORTSTATE_BLOCKED)
2984 return;
2985
2986 i->f->terminate_rport_io(rport);
2987}
2988
1da177e4
LT
2989/**
2990 * fc_scsi_scan_rport - called to perform a scsi scan on a remote port.
19a7b4ae 2991 *
c4028958 2992 * @work: remote port to be scanned.
1da177e4
LT
2993 **/
2994static void
c4028958 2995fc_scsi_scan_rport(struct work_struct *work)
1da177e4 2996{
c4028958
DH
2997 struct fc_rport *rport =
2998 container_of(work, struct fc_rport, scan_work);
aedf3497 2999 struct Scsi_Host *shost = rport_to_shost(rport);
42e33148
JSEC
3000 unsigned long flags;
3001
aedf3497 3002 if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
a53eb5e0 3003 (rport->roles & FC_PORT_ROLE_FCP_TARGET)) {
aedf3497
JS
3004 scsi_scan_target(&rport->dev, rport->channel,
3005 rport->scsi_target_id, SCAN_WILD_CARD, 1);
42e33148 3006 }
aedf3497
JS
3007
3008 spin_lock_irqsave(shost->host_lock, flags);
3009 rport->flags &= ~FC_RPORT_SCAN_PENDING;
42e33148
JSEC
3010 spin_unlock_irqrestore(shost->host_lock, flags);
3011}
3012
3013
a53eb5e0
JS
3014/**
3015 * fc_vport_create - allocates and creates a FC virtual port.
3016 * @shost: scsi host the virtual port is connected to.
3017 * @channel: Channel on shost port connected to.
3018 * @pdev: parent device for vport
3019 * @ids: The world wide names, FC4 port roles, etc for
3020 * the virtual port.
3021 * @ret_vport: The pointer to the created vport.
3022 *
3023 * Allocates and creates the vport structure, calls the parent host
3024 * to instantiate the vport, the completes w/ class and sysfs creation.
3025 *
3026 * Notes:
3027 * This routine assumes no locks are held on entry.
3028 **/
3029static int
3030fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev,
3031 struct fc_vport_identifiers *ids, struct fc_vport **ret_vport)
3032{
3033 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
3034 struct fc_internal *fci = to_fc_internal(shost->transportt);
3035 struct fc_vport *vport;
3036 struct device *dev;
3037 unsigned long flags;
3038 size_t size;
3039 int error;
3040
3041 *ret_vport = NULL;
3042
3043 if ( ! fci->f->vport_create)
3044 return -ENOENT;
3045
3046 size = (sizeof(struct fc_vport) + fci->f->dd_fcvport_size);
3047 vport = kzalloc(size, GFP_KERNEL);
3048 if (unlikely(!vport)) {
3049 printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
3050 return -ENOMEM;
3051 }
3052
3053 vport->vport_state = FC_VPORT_UNKNOWN;
3054 vport->vport_last_state = FC_VPORT_UNKNOWN;
3055 vport->node_name = ids->node_name;
3056 vport->port_name = ids->port_name;
3057 vport->roles = ids->roles;
3058 vport->vport_type = ids->vport_type;
3059 if (fci->f->dd_fcvport_size)
3060 vport->dd_data = &vport[1];
3061 vport->shost = shost;
3062 vport->channel = channel;
3063 vport->flags = FC_VPORT_CREATING;
3064
3065 spin_lock_irqsave(shost->host_lock, flags);
3066
3067 if (fc_host->npiv_vports_inuse >= fc_host->max_npiv_vports) {
3068 spin_unlock_irqrestore(shost->host_lock, flags);
3069 kfree(vport);
3070 return -ENOSPC;
3071 }
3072 fc_host->npiv_vports_inuse++;
3073 vport->number = fc_host->next_vport_number++;
3074 list_add_tail(&vport->peers, &fc_host->vports);
3075 get_device(&shost->shost_gendev); /* for fc_host->vport list */
3076
3077 spin_unlock_irqrestore(shost->host_lock, flags);
3078
3079 dev = &vport->dev;
3080 device_initialize(dev); /* takes self reference */
3081 dev->parent = get_device(pdev); /* takes parent reference */
3082 dev->release = fc_vport_dev_release;
3083 sprintf(dev->bus_id, "vport-%d:%d-%d",
3084 shost->host_no, channel, vport->number);
3085 transport_setup_device(dev);
3086
3087 error = device_add(dev);
3088 if (error) {
3089 printk(KERN_ERR "FC Virtual Port device_add failed\n");
3090 goto delete_vport;
3091 }
3092 transport_add_device(dev);
3093 transport_configure_device(dev);
3094
3095 error = fci->f->vport_create(vport, ids->disable);
3096 if (error) {
3097 printk(KERN_ERR "FC Virtual Port LLDD Create failed\n");
3098 goto delete_vport_all;
3099 }
3100
3101 /*
3102 * if the parent isn't the physical adapter's Scsi_Host, ensure
3103 * the Scsi_Host at least contains ia symlink to the vport.
3104 */
3105 if (pdev != &shost->shost_gendev) {
3106 error = sysfs_create_link(&shost->shost_gendev.kobj,
3107 &dev->kobj, dev->bus_id);
3108 if (error)
3109 printk(KERN_ERR
3110 "%s: Cannot create vport symlinks for "
3111 "%s, err=%d\n",
3112 __FUNCTION__, dev->bus_id, error);
3113 }
3114 spin_lock_irqsave(shost->host_lock, flags);
3115 vport->flags &= ~FC_VPORT_CREATING;
3116 spin_unlock_irqrestore(shost->host_lock, flags);
3117
3118 dev_printk(KERN_NOTICE, pdev,
3119 "%s created via shost%d channel %d\n", dev->bus_id,
3120 shost->host_no, channel);
3121
3122 *ret_vport = vport;
3123
3124 return 0;
3125
3126delete_vport_all:
3127 transport_remove_device(dev);
3128 device_del(dev);
3129delete_vport:
3130 transport_destroy_device(dev);
3131 spin_lock_irqsave(shost->host_lock, flags);
3132 list_del(&vport->peers);
3133 put_device(&shost->shost_gendev); /* for fc_host->vport list */
3134 fc_host->npiv_vports_inuse--;
3135 spin_unlock_irqrestore(shost->host_lock, flags);
3136 put_device(dev->parent);
3137 kfree(vport);
3138
3139 return error;
3140}
3141
3142
3143/**
3144 * fc_vport_terminate - Admin App or LLDD requests termination of a vport
3145 * @vport: fc_vport to be terminated
3146 *
3147 * Calls the LLDD vport_delete() function, then deallocates and removes
3148 * the vport from the shost and object tree.
3149 *
3150 * Notes:
3151 * This routine assumes no locks are held on entry.
3152 **/
3153int
3154fc_vport_terminate(struct fc_vport *vport)
3155{
3156 struct Scsi_Host *shost = vport_to_shost(vport);
3157 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
3158 struct fc_internal *i = to_fc_internal(shost->transportt);
3159 struct device *dev = &vport->dev;
3160 unsigned long flags;
3161 int stat;
3162
3163 spin_lock_irqsave(shost->host_lock, flags);
3164 if (vport->flags & FC_VPORT_CREATING) {
3165 spin_unlock_irqrestore(shost->host_lock, flags);
3166 return -EBUSY;
3167 }
3168 if (vport->flags & (FC_VPORT_DEL)) {
3169 spin_unlock_irqrestore(shost->host_lock, flags);
3170 return -EALREADY;
3171 }
3172 vport->flags |= FC_VPORT_DELETING;
3173 spin_unlock_irqrestore(shost->host_lock, flags);
3174
3175 if (i->f->vport_delete)
3176 stat = i->f->vport_delete(vport);
3177 else
3178 stat = -ENOENT;
3179
3180 spin_lock_irqsave(shost->host_lock, flags);
3181 vport->flags &= ~FC_VPORT_DELETING;
3182 if (!stat) {
3183 vport->flags |= FC_VPORT_DELETED;
3184 list_del(&vport->peers);
3185 fc_host->npiv_vports_inuse--;
3186 put_device(&shost->shost_gendev); /* for fc_host->vport list */
3187 }
3188 spin_unlock_irqrestore(shost->host_lock, flags);
3189
3190 if (stat)
3191 return stat;
3192
3193 if (dev->parent != &shost->shost_gendev)
3194 sysfs_remove_link(&shost->shost_gendev.kobj, dev->bus_id);
3195 transport_remove_device(dev);
3196 device_del(dev);
3197 transport_destroy_device(dev);
3198
3199 /*
3200 * Removing our self-reference should mean our
3201 * release function gets called, which will drop the remaining
3202 * parent reference and free the data structure.
3203 */
3204 put_device(dev); /* for self-reference */
3205
3206 return 0; /* SUCCESS */
3207}
3208EXPORT_SYMBOL(fc_vport_terminate);
3209
3210
1da177e4
LT
3211MODULE_AUTHOR("Martin Hicks");
3212MODULE_DESCRIPTION("FC Transport Attributes");
3213MODULE_LICENSE("GPL");
3214
3215module_init(fc_transport_init);
3216module_exit(fc_transport_exit);
This page took 0.35196 seconds and 5 git commands to generate.