1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <scsi/libfc.h>
25
26
27
28
29
30
31
32struct fc_lport *libfc_vport_create(struct fc_vport *vport, int privsize)
33{
34 struct Scsi_Host *shost = vport_to_shost(vport);
35 struct fc_lport *n_port = shost_priv(shost);
36 struct fc_lport *vn_port;
37
38 vn_port = libfc_host_alloc(shost->hostt, privsize);
39 if (!vn_port)
40 goto err_out;
41 if (fc_exch_mgr_list_clone(n_port, vn_port))
42 goto err_put;
43
44 vn_port->vport = vport;
45 vport->dd_data = vn_port;
46
47 mutex_lock(&n_port->lp_mutex);
48 list_add_tail(&vn_port->list, &n_port->vports);
49 mutex_unlock(&n_port->lp_mutex);
50
51 return vn_port;
52
53err_put:
54 scsi_host_put(vn_port->host);
55err_out:
56 return NULL;
57}
58EXPORT_SYMBOL(libfc_vport_create);
59
60
61
62
63
64
65
66
67struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id)
68{
69 struct fc_lport *lport = NULL;
70 struct fc_lport *vn_port;
71
72 if (n_port->port_id == port_id)
73 return n_port;
74
75 if (port_id == FC_FID_FLOGI)
76 return n_port;
77
78 mutex_lock(&n_port->lp_mutex);
79 list_for_each_entry(vn_port, &n_port->vports, list) {
80 if (vn_port->port_id == port_id) {
81 lport = vn_port;
82 break;
83 }
84 }
85 mutex_unlock(&n_port->lp_mutex);
86
87 return lport;
88}
89
90
91
92
93
94
95
96enum libfc_lport_mutex_class {
97 LPORT_MUTEX_NORMAL = 0,
98 LPORT_MUTEX_VN_PORT = 1,
99};
100
101
102
103
104
105
106
107
108static void __fc_vport_setlink(struct fc_lport *n_port,
109 struct fc_lport *vn_port)
110{
111 struct fc_vport *vport = vn_port->vport;
112
113 if (vn_port->state == LPORT_ST_DISABLED)
114 return;
115
116 if (n_port->state == LPORT_ST_READY) {
117 if (n_port->npiv_enabled) {
118 fc_vport_set_state(vport, FC_VPORT_INITIALIZING);
119 __fc_linkup(vn_port);
120 } else {
121 fc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
122 __fc_linkdown(vn_port);
123 }
124 } else {
125 fc_vport_set_state(vport, FC_VPORT_LINKDOWN);
126 __fc_linkdown(vn_port);
127 }
128}
129
130
131
132
133
134void fc_vport_setlink(struct fc_lport *vn_port)
135{
136 struct fc_vport *vport = vn_port->vport;
137 struct Scsi_Host *shost = vport_to_shost(vport);
138 struct fc_lport *n_port = shost_priv(shost);
139
140 mutex_lock(&n_port->lp_mutex);
141 mutex_lock_nested(&vn_port->lp_mutex, LPORT_MUTEX_VN_PORT);
142 __fc_vport_setlink(n_port, vn_port);
143 mutex_unlock(&vn_port->lp_mutex);
144 mutex_unlock(&n_port->lp_mutex);
145}
146EXPORT_SYMBOL(fc_vport_setlink);
147
148
149
150
151
152
153
154void fc_vports_linkchange(struct fc_lport *n_port)
155{
156 struct fc_lport *vn_port;
157
158 list_for_each_entry(vn_port, &n_port->vports, list) {
159 mutex_lock_nested(&vn_port->lp_mutex, LPORT_MUTEX_VN_PORT);
160 __fc_vport_setlink(n_port, vn_port);
161 mutex_unlock(&vn_port->lp_mutex);
162 }
163}
164
165