Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * iSCSI transport class definitions
4 : : *
5 : : * Copyright (C) IBM Corporation, 2004
6 : : * Copyright (C) Mike Christie, 2004 - 2005
7 : : * Copyright (C) Dmitry Yusupov, 2004 - 2005
8 : : * Copyright (C) Alex Aizman, 2004 - 2005
9 : : */
10 : : #include <linux/module.h>
11 : : #include <linux/mutex.h>
12 : : #include <linux/slab.h>
13 : : #include <linux/bsg-lib.h>
14 : : #include <linux/idr.h>
15 : : #include <net/tcp.h>
16 : : #include <scsi/scsi.h>
17 : : #include <scsi/scsi_host.h>
18 : : #include <scsi/scsi_device.h>
19 : : #include <scsi/scsi_transport.h>
20 : : #include <scsi/scsi_transport_iscsi.h>
21 : : #include <scsi/iscsi_if.h>
22 : : #include <scsi/scsi_cmnd.h>
23 : : #include <scsi/scsi_bsg_iscsi.h>
24 : :
25 : : #define ISCSI_TRANSPORT_VERSION "2.0-870"
26 : :
27 : : #define ISCSI_SEND_MAX_ALLOWED 10
28 : :
29 : : #define CREATE_TRACE_POINTS
30 : : #include <trace/events/iscsi.h>
31 : :
32 : : /*
33 : : * Export tracepoint symbols to be used by other modules.
34 : : */
35 : : EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_conn);
36 : : EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_eh);
37 : : EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_session);
38 : : EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_tcp);
39 : : EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_sw_tcp);
40 : :
41 : : static int dbg_session;
42 : : module_param_named(debug_session, dbg_session, int,
43 : : S_IRUGO | S_IWUSR);
44 : : MODULE_PARM_DESC(debug_session,
45 : : "Turn on debugging for sessions in scsi_transport_iscsi "
46 : : "module. Set to 1 to turn on, and zero to turn off. Default "
47 : : "is off.");
48 : :
49 : : static int dbg_conn;
50 : : module_param_named(debug_conn, dbg_conn, int,
51 : : S_IRUGO | S_IWUSR);
52 : : MODULE_PARM_DESC(debug_conn,
53 : : "Turn on debugging for connections in scsi_transport_iscsi "
54 : : "module. Set to 1 to turn on, and zero to turn off. Default "
55 : : "is off.");
56 : :
57 : : #define ISCSI_DBG_TRANS_SESSION(_session, dbg_fmt, arg...) \
58 : : do { \
59 : : if (dbg_session) \
60 : : iscsi_cls_session_printk(KERN_INFO, _session, \
61 : : "%s: " dbg_fmt, \
62 : : __func__, ##arg); \
63 : : iscsi_dbg_trace(trace_iscsi_dbg_trans_session, \
64 : : &(_session)->dev, \
65 : : "%s " dbg_fmt, __func__, ##arg); \
66 : : } while (0);
67 : :
68 : : #define ISCSI_DBG_TRANS_CONN(_conn, dbg_fmt, arg...) \
69 : : do { \
70 : : if (dbg_conn) \
71 : : iscsi_cls_conn_printk(KERN_INFO, _conn, \
72 : : "%s: " dbg_fmt, \
73 : : __func__, ##arg); \
74 : : iscsi_dbg_trace(trace_iscsi_dbg_trans_conn, \
75 : : &(_conn)->dev, \
76 : : "%s " dbg_fmt, __func__, ##arg); \
77 : : } while (0);
78 : :
79 : : struct iscsi_internal {
80 : : struct scsi_transport_template t;
81 : : struct iscsi_transport *iscsi_transport;
82 : : struct list_head list;
83 : : struct device dev;
84 : :
85 : : struct transport_container conn_cont;
86 : : struct transport_container session_cont;
87 : : };
88 : :
89 : : static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
90 : : static struct workqueue_struct *iscsi_eh_timer_workq;
91 : :
92 : : static DEFINE_IDA(iscsi_sess_ida);
93 : : /*
94 : : * list of registered transports and lock that must
95 : : * be held while accessing list. The iscsi_transport_lock must
96 : : * be acquired after the rx_queue_mutex.
97 : : */
98 : : static LIST_HEAD(iscsi_transports);
99 : : static DEFINE_SPINLOCK(iscsi_transport_lock);
100 : :
101 : : #define to_iscsi_internal(tmpl) \
102 : : container_of(tmpl, struct iscsi_internal, t)
103 : :
104 : : #define dev_to_iscsi_internal(_dev) \
105 : : container_of(_dev, struct iscsi_internal, dev)
106 : :
107 : 0 : static void iscsi_transport_release(struct device *dev)
108 : : {
109 : 0 : struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
110 : 0 : kfree(priv);
111 : 0 : }
112 : :
113 : : /*
114 : : * iscsi_transport_class represents the iscsi_transports that are
115 : : * registered.
116 : : */
117 : : static struct class iscsi_transport_class = {
118 : : .name = "iscsi_transport",
119 : : .dev_release = iscsi_transport_release,
120 : : };
121 : :
122 : : static ssize_t
123 : 0 : show_transport_handle(struct device *dev, struct device_attribute *attr,
124 : : char *buf)
125 : : {
126 : : struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
127 : 0 : return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport));
128 : : }
129 : : static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
130 : :
131 : : #define show_transport_attr(name, format) \
132 : : static ssize_t \
133 : : show_transport_##name(struct device *dev, \
134 : : struct device_attribute *attr,char *buf) \
135 : : { \
136 : : struct iscsi_internal *priv = dev_to_iscsi_internal(dev); \
137 : : return sprintf(buf, format"\n", priv->iscsi_transport->name); \
138 : : } \
139 : : static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
140 : :
141 : 0 : show_transport_attr(caps, "0x%x");
142 : :
143 : : static struct attribute *iscsi_transport_attrs[] = {
144 : : &dev_attr_handle.attr,
145 : : &dev_attr_caps.attr,
146 : : NULL,
147 : : };
148 : :
149 : : static struct attribute_group iscsi_transport_group = {
150 : : .attrs = iscsi_transport_attrs,
151 : : };
152 : :
153 : : /*
154 : : * iSCSI endpoint attrs
155 : : */
156 : : #define iscsi_dev_to_endpoint(_dev) \
157 : : container_of(_dev, struct iscsi_endpoint, dev)
158 : :
159 : : #define ISCSI_ATTR(_prefix,_name,_mode,_show,_store) \
160 : : struct device_attribute dev_attr_##_prefix##_##_name = \
161 : : __ATTR(_name,_mode,_show,_store)
162 : :
163 : 0 : static void iscsi_endpoint_release(struct device *dev)
164 : : {
165 : 0 : struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
166 : 0 : kfree(ep);
167 : 0 : }
168 : :
169 : : static struct class iscsi_endpoint_class = {
170 : : .name = "iscsi_endpoint",
171 : : .dev_release = iscsi_endpoint_release,
172 : : };
173 : :
174 : : static ssize_t
175 : 0 : show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
176 : : {
177 : : struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
178 : 0 : return sprintf(buf, "%llu\n", (unsigned long long) ep->id);
179 : : }
180 : : static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
181 : :
182 : : static struct attribute *iscsi_endpoint_attrs[] = {
183 : : &dev_attr_ep_handle.attr,
184 : : NULL,
185 : : };
186 : :
187 : : static struct attribute_group iscsi_endpoint_group = {
188 : : .attrs = iscsi_endpoint_attrs,
189 : : };
190 : :
191 : : #define ISCSI_MAX_EPID -1
192 : :
193 : 0 : static int iscsi_match_epid(struct device *dev, const void *data)
194 : : {
195 : : struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
196 : : const uint64_t *epid = data;
197 : :
198 : 0 : return *epid == ep->id;
199 : : }
200 : :
201 : : struct iscsi_endpoint *
202 : 0 : iscsi_create_endpoint(int dd_size)
203 : : {
204 : : struct device *dev;
205 : : struct iscsi_endpoint *ep;
206 : : uint64_t id;
207 : : int err;
208 : :
209 : 0 : for (id = 1; id < ISCSI_MAX_EPID; id++) {
210 : 0 : dev = class_find_device(&iscsi_endpoint_class, NULL, &id,
211 : : iscsi_match_epid);
212 : 0 : if (!dev)
213 : : break;
214 : : else
215 : 0 : put_device(dev);
216 : : }
217 : 0 : if (id == ISCSI_MAX_EPID) {
218 : 0 : printk(KERN_ERR "Too many connections. Max supported %u\n",
219 : : ISCSI_MAX_EPID - 1);
220 : 0 : return NULL;
221 : : }
222 : :
223 : 0 : ep = kzalloc(sizeof(*ep) + dd_size, GFP_KERNEL);
224 : 0 : if (!ep)
225 : : return NULL;
226 : :
227 : 0 : ep->id = id;
228 : 0 : ep->dev.class = &iscsi_endpoint_class;
229 : 0 : dev_set_name(&ep->dev, "ep-%llu", (unsigned long long) id);
230 : 0 : err = device_register(&ep->dev);
231 : 0 : if (err)
232 : : goto free_ep;
233 : :
234 : 0 : err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group);
235 : 0 : if (err)
236 : : goto unregister_dev;
237 : :
238 : 0 : if (dd_size)
239 : 0 : ep->dd_data = &ep[1];
240 : 0 : return ep;
241 : :
242 : : unregister_dev:
243 : 0 : device_unregister(&ep->dev);
244 : 0 : return NULL;
245 : :
246 : : free_ep:
247 : 0 : kfree(ep);
248 : 0 : return NULL;
249 : : }
250 : : EXPORT_SYMBOL_GPL(iscsi_create_endpoint);
251 : :
252 : 0 : void iscsi_destroy_endpoint(struct iscsi_endpoint *ep)
253 : : {
254 : 0 : sysfs_remove_group(&ep->dev.kobj, &iscsi_endpoint_group);
255 : 0 : device_unregister(&ep->dev);
256 : 0 : }
257 : : EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
258 : :
259 : 0 : struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
260 : : {
261 : : struct iscsi_endpoint *ep;
262 : : struct device *dev;
263 : :
264 : 0 : dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
265 : : iscsi_match_epid);
266 : 0 : if (!dev)
267 : : return NULL;
268 : :
269 : 0 : ep = iscsi_dev_to_endpoint(dev);
270 : : /*
271 : : * we can drop this now because the interface will prevent
272 : : * removals and lookups from racing.
273 : : */
274 : 0 : put_device(dev);
275 : 0 : return ep;
276 : : }
277 : : EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
278 : :
279 : : /*
280 : : * Interface to display network param to sysfs
281 : : */
282 : :
283 : 0 : static void iscsi_iface_release(struct device *dev)
284 : : {
285 : : struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
286 : 0 : struct device *parent = iface->dev.parent;
287 : :
288 : 0 : kfree(iface);
289 : 0 : put_device(parent);
290 : 0 : }
291 : :
292 : :
293 : : static struct class iscsi_iface_class = {
294 : : .name = "iscsi_iface",
295 : : .dev_release = iscsi_iface_release,
296 : : };
297 : :
298 : : #define ISCSI_IFACE_ATTR(_prefix, _name, _mode, _show, _store) \
299 : : struct device_attribute dev_attr_##_prefix##_##_name = \
300 : : __ATTR(_name, _mode, _show, _store)
301 : :
302 : : /* iface attrs show */
303 : : #define iscsi_iface_attr_show(type, name, param_type, param) \
304 : : static ssize_t \
305 : : show_##type##_##name(struct device *dev, struct device_attribute *attr, \
306 : : char *buf) \
307 : : { \
308 : : struct iscsi_iface *iface = iscsi_dev_to_iface(dev); \
309 : : struct iscsi_transport *t = iface->transport; \
310 : : return t->get_iface_param(iface, param_type, param, buf); \
311 : : } \
312 : :
313 : : #define iscsi_iface_net_attr(type, name, param) \
314 : : iscsi_iface_attr_show(type, name, ISCSI_NET_PARAM, param) \
315 : : static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL);
316 : :
317 : : #define iscsi_iface_attr(type, name, param) \
318 : : iscsi_iface_attr_show(type, name, ISCSI_IFACE_PARAM, param) \
319 : : static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL);
320 : :
321 : : /* generic read only ipv4 attribute */
322 : 0 : iscsi_iface_net_attr(ipv4_iface, ipaddress, ISCSI_NET_PARAM_IPV4_ADDR);
323 : 0 : iscsi_iface_net_attr(ipv4_iface, gateway, ISCSI_NET_PARAM_IPV4_GW);
324 : 0 : iscsi_iface_net_attr(ipv4_iface, subnet, ISCSI_NET_PARAM_IPV4_SUBNET);
325 : 0 : iscsi_iface_net_attr(ipv4_iface, bootproto, ISCSI_NET_PARAM_IPV4_BOOTPROTO);
326 : 0 : iscsi_iface_net_attr(ipv4_iface, dhcp_dns_address_en,
327 : : ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN);
328 : 0 : iscsi_iface_net_attr(ipv4_iface, dhcp_slp_da_info_en,
329 : : ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN);
330 : 0 : iscsi_iface_net_attr(ipv4_iface, tos_en, ISCSI_NET_PARAM_IPV4_TOS_EN);
331 : 0 : iscsi_iface_net_attr(ipv4_iface, tos, ISCSI_NET_PARAM_IPV4_TOS);
332 : 0 : iscsi_iface_net_attr(ipv4_iface, grat_arp_en,
333 : : ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN);
334 : 0 : iscsi_iface_net_attr(ipv4_iface, dhcp_alt_client_id_en,
335 : : ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN);
336 : 0 : iscsi_iface_net_attr(ipv4_iface, dhcp_alt_client_id,
337 : : ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID);
338 : 0 : iscsi_iface_net_attr(ipv4_iface, dhcp_req_vendor_id_en,
339 : : ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN);
340 : 0 : iscsi_iface_net_attr(ipv4_iface, dhcp_use_vendor_id_en,
341 : : ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN);
342 : 0 : iscsi_iface_net_attr(ipv4_iface, dhcp_vendor_id,
343 : : ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID);
344 : 0 : iscsi_iface_net_attr(ipv4_iface, dhcp_learn_iqn_en,
345 : : ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN);
346 : 0 : iscsi_iface_net_attr(ipv4_iface, fragment_disable,
347 : : ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE);
348 : 0 : iscsi_iface_net_attr(ipv4_iface, incoming_forwarding_en,
349 : : ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN);
350 : 0 : iscsi_iface_net_attr(ipv4_iface, ttl, ISCSI_NET_PARAM_IPV4_TTL);
351 : :
352 : : /* generic read only ipv6 attribute */
353 : 0 : iscsi_iface_net_attr(ipv6_iface, ipaddress, ISCSI_NET_PARAM_IPV6_ADDR);
354 : 0 : iscsi_iface_net_attr(ipv6_iface, link_local_addr,
355 : : ISCSI_NET_PARAM_IPV6_LINKLOCAL);
356 : 0 : iscsi_iface_net_attr(ipv6_iface, router_addr, ISCSI_NET_PARAM_IPV6_ROUTER);
357 : 0 : iscsi_iface_net_attr(ipv6_iface, ipaddr_autocfg,
358 : : ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG);
359 : 0 : iscsi_iface_net_attr(ipv6_iface, link_local_autocfg,
360 : : ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG);
361 : 0 : iscsi_iface_net_attr(ipv6_iface, link_local_state,
362 : : ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE);
363 : 0 : iscsi_iface_net_attr(ipv6_iface, router_state,
364 : : ISCSI_NET_PARAM_IPV6_ROUTER_STATE);
365 : 0 : iscsi_iface_net_attr(ipv6_iface, grat_neighbor_adv_en,
366 : : ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN);
367 : 0 : iscsi_iface_net_attr(ipv6_iface, mld_en, ISCSI_NET_PARAM_IPV6_MLD_EN);
368 : 0 : iscsi_iface_net_attr(ipv6_iface, flow_label, ISCSI_NET_PARAM_IPV6_FLOW_LABEL);
369 : 0 : iscsi_iface_net_attr(ipv6_iface, traffic_class,
370 : : ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS);
371 : 0 : iscsi_iface_net_attr(ipv6_iface, hop_limit, ISCSI_NET_PARAM_IPV6_HOP_LIMIT);
372 : 0 : iscsi_iface_net_attr(ipv6_iface, nd_reachable_tmo,
373 : : ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO);
374 : 0 : iscsi_iface_net_attr(ipv6_iface, nd_rexmit_time,
375 : : ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME);
376 : 0 : iscsi_iface_net_attr(ipv6_iface, nd_stale_tmo,
377 : : ISCSI_NET_PARAM_IPV6_ND_STALE_TMO);
378 : 0 : iscsi_iface_net_attr(ipv6_iface, dup_addr_detect_cnt,
379 : : ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT);
380 : 0 : iscsi_iface_net_attr(ipv6_iface, router_adv_link_mtu,
381 : : ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU);
382 : :
383 : : /* common read only iface attribute */
384 : 0 : iscsi_iface_net_attr(iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLE);
385 : 0 : iscsi_iface_net_attr(iface, vlan_id, ISCSI_NET_PARAM_VLAN_ID);
386 : 0 : iscsi_iface_net_attr(iface, vlan_priority, ISCSI_NET_PARAM_VLAN_PRIORITY);
387 : 0 : iscsi_iface_net_attr(iface, vlan_enabled, ISCSI_NET_PARAM_VLAN_ENABLED);
388 : 0 : iscsi_iface_net_attr(iface, mtu, ISCSI_NET_PARAM_MTU);
389 : 0 : iscsi_iface_net_attr(iface, port, ISCSI_NET_PARAM_PORT);
390 : 0 : iscsi_iface_net_attr(iface, ipaddress_state, ISCSI_NET_PARAM_IPADDR_STATE);
391 : 0 : iscsi_iface_net_attr(iface, delayed_ack_en, ISCSI_NET_PARAM_DELAYED_ACK_EN);
392 : 0 : iscsi_iface_net_attr(iface, tcp_nagle_disable,
393 : : ISCSI_NET_PARAM_TCP_NAGLE_DISABLE);
394 : 0 : iscsi_iface_net_attr(iface, tcp_wsf_disable, ISCSI_NET_PARAM_TCP_WSF_DISABLE);
395 : 0 : iscsi_iface_net_attr(iface, tcp_wsf, ISCSI_NET_PARAM_TCP_WSF);
396 : 0 : iscsi_iface_net_attr(iface, tcp_timer_scale, ISCSI_NET_PARAM_TCP_TIMER_SCALE);
397 : 0 : iscsi_iface_net_attr(iface, tcp_timestamp_en, ISCSI_NET_PARAM_TCP_TIMESTAMP_EN);
398 : 0 : iscsi_iface_net_attr(iface, cache_id, ISCSI_NET_PARAM_CACHE_ID);
399 : 0 : iscsi_iface_net_attr(iface, redirect_en, ISCSI_NET_PARAM_REDIRECT_EN);
400 : :
401 : : /* common iscsi specific settings attributes */
402 : 0 : iscsi_iface_attr(iface, def_taskmgmt_tmo, ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO);
403 : 0 : iscsi_iface_attr(iface, header_digest, ISCSI_IFACE_PARAM_HDRDGST_EN);
404 : 0 : iscsi_iface_attr(iface, data_digest, ISCSI_IFACE_PARAM_DATADGST_EN);
405 : 0 : iscsi_iface_attr(iface, immediate_data, ISCSI_IFACE_PARAM_IMM_DATA_EN);
406 : 0 : iscsi_iface_attr(iface, initial_r2t, ISCSI_IFACE_PARAM_INITIAL_R2T_EN);
407 : 0 : iscsi_iface_attr(iface, data_seq_in_order,
408 : : ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN);
409 : 0 : iscsi_iface_attr(iface, data_pdu_in_order, ISCSI_IFACE_PARAM_PDU_INORDER_EN);
410 : 0 : iscsi_iface_attr(iface, erl, ISCSI_IFACE_PARAM_ERL);
411 : 0 : iscsi_iface_attr(iface, max_recv_dlength, ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH);
412 : 0 : iscsi_iface_attr(iface, first_burst_len, ISCSI_IFACE_PARAM_FIRST_BURST);
413 : 0 : iscsi_iface_attr(iface, max_outstanding_r2t, ISCSI_IFACE_PARAM_MAX_R2T);
414 : 0 : iscsi_iface_attr(iface, max_burst_len, ISCSI_IFACE_PARAM_MAX_BURST);
415 : 0 : iscsi_iface_attr(iface, chap_auth, ISCSI_IFACE_PARAM_CHAP_AUTH_EN);
416 : 0 : iscsi_iface_attr(iface, bidi_chap, ISCSI_IFACE_PARAM_BIDI_CHAP_EN);
417 : 0 : iscsi_iface_attr(iface, discovery_auth_optional,
418 : : ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL);
419 : 0 : iscsi_iface_attr(iface, discovery_logout,
420 : : ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN);
421 : 0 : iscsi_iface_attr(iface, strict_login_comp_en,
422 : : ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN);
423 : 0 : iscsi_iface_attr(iface, initiator_name, ISCSI_IFACE_PARAM_INITIATOR_NAME);
424 : :
425 : 0 : static umode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
426 : : struct attribute *attr, int i)
427 : : {
428 : : struct device *dev = container_of(kobj, struct device, kobj);
429 : : struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
430 : 0 : struct iscsi_transport *t = iface->transport;
431 : : int param;
432 : : int param_type;
433 : :
434 : 0 : if (attr == &dev_attr_iface_enabled.attr)
435 : : param = ISCSI_NET_PARAM_IFACE_ENABLE;
436 : 0 : else if (attr == &dev_attr_iface_vlan_id.attr)
437 : : param = ISCSI_NET_PARAM_VLAN_ID;
438 : 0 : else if (attr == &dev_attr_iface_vlan_priority.attr)
439 : : param = ISCSI_NET_PARAM_VLAN_PRIORITY;
440 : 0 : else if (attr == &dev_attr_iface_vlan_enabled.attr)
441 : : param = ISCSI_NET_PARAM_VLAN_ENABLED;
442 : 0 : else if (attr == &dev_attr_iface_mtu.attr)
443 : : param = ISCSI_NET_PARAM_MTU;
444 : 0 : else if (attr == &dev_attr_iface_port.attr)
445 : : param = ISCSI_NET_PARAM_PORT;
446 : 0 : else if (attr == &dev_attr_iface_ipaddress_state.attr)
447 : : param = ISCSI_NET_PARAM_IPADDR_STATE;
448 : 0 : else if (attr == &dev_attr_iface_delayed_ack_en.attr)
449 : : param = ISCSI_NET_PARAM_DELAYED_ACK_EN;
450 : 0 : else if (attr == &dev_attr_iface_tcp_nagle_disable.attr)
451 : : param = ISCSI_NET_PARAM_TCP_NAGLE_DISABLE;
452 : 0 : else if (attr == &dev_attr_iface_tcp_wsf_disable.attr)
453 : : param = ISCSI_NET_PARAM_TCP_WSF_DISABLE;
454 : 0 : else if (attr == &dev_attr_iface_tcp_wsf.attr)
455 : : param = ISCSI_NET_PARAM_TCP_WSF;
456 : 0 : else if (attr == &dev_attr_iface_tcp_timer_scale.attr)
457 : : param = ISCSI_NET_PARAM_TCP_TIMER_SCALE;
458 : 0 : else if (attr == &dev_attr_iface_tcp_timestamp_en.attr)
459 : : param = ISCSI_NET_PARAM_TCP_TIMESTAMP_EN;
460 : 0 : else if (attr == &dev_attr_iface_cache_id.attr)
461 : : param = ISCSI_NET_PARAM_CACHE_ID;
462 : 0 : else if (attr == &dev_attr_iface_redirect_en.attr)
463 : : param = ISCSI_NET_PARAM_REDIRECT_EN;
464 : 0 : else if (attr == &dev_attr_iface_def_taskmgmt_tmo.attr)
465 : : param = ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO;
466 : 0 : else if (attr == &dev_attr_iface_header_digest.attr)
467 : : param = ISCSI_IFACE_PARAM_HDRDGST_EN;
468 : 0 : else if (attr == &dev_attr_iface_data_digest.attr)
469 : : param = ISCSI_IFACE_PARAM_DATADGST_EN;
470 : 0 : else if (attr == &dev_attr_iface_immediate_data.attr)
471 : : param = ISCSI_IFACE_PARAM_IMM_DATA_EN;
472 : 0 : else if (attr == &dev_attr_iface_initial_r2t.attr)
473 : : param = ISCSI_IFACE_PARAM_INITIAL_R2T_EN;
474 : 0 : else if (attr == &dev_attr_iface_data_seq_in_order.attr)
475 : : param = ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN;
476 : 0 : else if (attr == &dev_attr_iface_data_pdu_in_order.attr)
477 : : param = ISCSI_IFACE_PARAM_PDU_INORDER_EN;
478 : 0 : else if (attr == &dev_attr_iface_erl.attr)
479 : : param = ISCSI_IFACE_PARAM_ERL;
480 : 0 : else if (attr == &dev_attr_iface_max_recv_dlength.attr)
481 : : param = ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH;
482 : 0 : else if (attr == &dev_attr_iface_first_burst_len.attr)
483 : : param = ISCSI_IFACE_PARAM_FIRST_BURST;
484 : 0 : else if (attr == &dev_attr_iface_max_outstanding_r2t.attr)
485 : : param = ISCSI_IFACE_PARAM_MAX_R2T;
486 : 0 : else if (attr == &dev_attr_iface_max_burst_len.attr)
487 : : param = ISCSI_IFACE_PARAM_MAX_BURST;
488 : 0 : else if (attr == &dev_attr_iface_chap_auth.attr)
489 : : param = ISCSI_IFACE_PARAM_CHAP_AUTH_EN;
490 : 0 : else if (attr == &dev_attr_iface_bidi_chap.attr)
491 : : param = ISCSI_IFACE_PARAM_BIDI_CHAP_EN;
492 : 0 : else if (attr == &dev_attr_iface_discovery_auth_optional.attr)
493 : : param = ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL;
494 : 0 : else if (attr == &dev_attr_iface_discovery_logout.attr)
495 : : param = ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN;
496 : 0 : else if (attr == &dev_attr_iface_strict_login_comp_en.attr)
497 : : param = ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN;
498 : 0 : else if (attr == &dev_attr_iface_initiator_name.attr)
499 : : param = ISCSI_IFACE_PARAM_INITIATOR_NAME;
500 : 0 : else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {
501 : 0 : if (attr == &dev_attr_ipv4_iface_ipaddress.attr)
502 : : param = ISCSI_NET_PARAM_IPV4_ADDR;
503 : 0 : else if (attr == &dev_attr_ipv4_iface_gateway.attr)
504 : : param = ISCSI_NET_PARAM_IPV4_GW;
505 : 0 : else if (attr == &dev_attr_ipv4_iface_subnet.attr)
506 : : param = ISCSI_NET_PARAM_IPV4_SUBNET;
507 : 0 : else if (attr == &dev_attr_ipv4_iface_bootproto.attr)
508 : : param = ISCSI_NET_PARAM_IPV4_BOOTPROTO;
509 : 0 : else if (attr ==
510 : : &dev_attr_ipv4_iface_dhcp_dns_address_en.attr)
511 : : param = ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN;
512 : 0 : else if (attr ==
513 : : &dev_attr_ipv4_iface_dhcp_slp_da_info_en.attr)
514 : : param = ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN;
515 : 0 : else if (attr == &dev_attr_ipv4_iface_tos_en.attr)
516 : : param = ISCSI_NET_PARAM_IPV4_TOS_EN;
517 : 0 : else if (attr == &dev_attr_ipv4_iface_tos.attr)
518 : : param = ISCSI_NET_PARAM_IPV4_TOS;
519 : 0 : else if (attr == &dev_attr_ipv4_iface_grat_arp_en.attr)
520 : : param = ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN;
521 : 0 : else if (attr ==
522 : : &dev_attr_ipv4_iface_dhcp_alt_client_id_en.attr)
523 : : param = ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN;
524 : 0 : else if (attr == &dev_attr_ipv4_iface_dhcp_alt_client_id.attr)
525 : : param = ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID;
526 : 0 : else if (attr ==
527 : : &dev_attr_ipv4_iface_dhcp_req_vendor_id_en.attr)
528 : : param = ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN;
529 : 0 : else if (attr ==
530 : : &dev_attr_ipv4_iface_dhcp_use_vendor_id_en.attr)
531 : : param = ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN;
532 : 0 : else if (attr == &dev_attr_ipv4_iface_dhcp_vendor_id.attr)
533 : : param = ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID;
534 : 0 : else if (attr ==
535 : : &dev_attr_ipv4_iface_dhcp_learn_iqn_en.attr)
536 : : param = ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN;
537 : 0 : else if (attr ==
538 : : &dev_attr_ipv4_iface_fragment_disable.attr)
539 : : param = ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE;
540 : 0 : else if (attr ==
541 : : &dev_attr_ipv4_iface_incoming_forwarding_en.attr)
542 : : param = ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN;
543 : 0 : else if (attr == &dev_attr_ipv4_iface_ttl.attr)
544 : : param = ISCSI_NET_PARAM_IPV4_TTL;
545 : : else
546 : : return 0;
547 : 0 : } else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) {
548 : 0 : if (attr == &dev_attr_ipv6_iface_ipaddress.attr)
549 : : param = ISCSI_NET_PARAM_IPV6_ADDR;
550 : 0 : else if (attr == &dev_attr_ipv6_iface_link_local_addr.attr)
551 : : param = ISCSI_NET_PARAM_IPV6_LINKLOCAL;
552 : 0 : else if (attr == &dev_attr_ipv6_iface_router_addr.attr)
553 : : param = ISCSI_NET_PARAM_IPV6_ROUTER;
554 : 0 : else if (attr == &dev_attr_ipv6_iface_ipaddr_autocfg.attr)
555 : : param = ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG;
556 : 0 : else if (attr == &dev_attr_ipv6_iface_link_local_autocfg.attr)
557 : : param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG;
558 : 0 : else if (attr == &dev_attr_ipv6_iface_link_local_state.attr)
559 : : param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE;
560 : 0 : else if (attr == &dev_attr_ipv6_iface_router_state.attr)
561 : : param = ISCSI_NET_PARAM_IPV6_ROUTER_STATE;
562 : 0 : else if (attr ==
563 : : &dev_attr_ipv6_iface_grat_neighbor_adv_en.attr)
564 : : param = ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN;
565 : 0 : else if (attr == &dev_attr_ipv6_iface_mld_en.attr)
566 : : param = ISCSI_NET_PARAM_IPV6_MLD_EN;
567 : 0 : else if (attr == &dev_attr_ipv6_iface_flow_label.attr)
568 : : param = ISCSI_NET_PARAM_IPV6_FLOW_LABEL;
569 : 0 : else if (attr == &dev_attr_ipv6_iface_traffic_class.attr)
570 : : param = ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS;
571 : 0 : else if (attr == &dev_attr_ipv6_iface_hop_limit.attr)
572 : : param = ISCSI_NET_PARAM_IPV6_HOP_LIMIT;
573 : 0 : else if (attr == &dev_attr_ipv6_iface_nd_reachable_tmo.attr)
574 : : param = ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO;
575 : 0 : else if (attr == &dev_attr_ipv6_iface_nd_rexmit_time.attr)
576 : : param = ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME;
577 : 0 : else if (attr == &dev_attr_ipv6_iface_nd_stale_tmo.attr)
578 : : param = ISCSI_NET_PARAM_IPV6_ND_STALE_TMO;
579 : 0 : else if (attr == &dev_attr_ipv6_iface_dup_addr_detect_cnt.attr)
580 : : param = ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT;
581 : 0 : else if (attr == &dev_attr_ipv6_iface_router_adv_link_mtu.attr)
582 : : param = ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU;
583 : : else
584 : : return 0;
585 : : } else {
586 : 0 : WARN_ONCE(1, "Invalid iface attr");
587 : : return 0;
588 : : }
589 : :
590 : 0 : switch (param) {
591 : : case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO:
592 : : case ISCSI_IFACE_PARAM_HDRDGST_EN:
593 : : case ISCSI_IFACE_PARAM_DATADGST_EN:
594 : : case ISCSI_IFACE_PARAM_IMM_DATA_EN:
595 : : case ISCSI_IFACE_PARAM_INITIAL_R2T_EN:
596 : : case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN:
597 : : case ISCSI_IFACE_PARAM_PDU_INORDER_EN:
598 : : case ISCSI_IFACE_PARAM_ERL:
599 : : case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH:
600 : : case ISCSI_IFACE_PARAM_FIRST_BURST:
601 : : case ISCSI_IFACE_PARAM_MAX_R2T:
602 : : case ISCSI_IFACE_PARAM_MAX_BURST:
603 : : case ISCSI_IFACE_PARAM_CHAP_AUTH_EN:
604 : : case ISCSI_IFACE_PARAM_BIDI_CHAP_EN:
605 : : case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL:
606 : : case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN:
607 : : case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN:
608 : : case ISCSI_IFACE_PARAM_INITIATOR_NAME:
609 : : param_type = ISCSI_IFACE_PARAM;
610 : : break;
611 : : default:
612 : : param_type = ISCSI_NET_PARAM;
613 : : }
614 : :
615 : 0 : return t->attr_is_visible(param_type, param);
616 : : }
617 : :
618 : : static struct attribute *iscsi_iface_attrs[] = {
619 : : &dev_attr_iface_enabled.attr,
620 : : &dev_attr_iface_vlan_id.attr,
621 : : &dev_attr_iface_vlan_priority.attr,
622 : : &dev_attr_iface_vlan_enabled.attr,
623 : : &dev_attr_ipv4_iface_ipaddress.attr,
624 : : &dev_attr_ipv4_iface_gateway.attr,
625 : : &dev_attr_ipv4_iface_subnet.attr,
626 : : &dev_attr_ipv4_iface_bootproto.attr,
627 : : &dev_attr_ipv6_iface_ipaddress.attr,
628 : : &dev_attr_ipv6_iface_link_local_addr.attr,
629 : : &dev_attr_ipv6_iface_router_addr.attr,
630 : : &dev_attr_ipv6_iface_ipaddr_autocfg.attr,
631 : : &dev_attr_ipv6_iface_link_local_autocfg.attr,
632 : : &dev_attr_iface_mtu.attr,
633 : : &dev_attr_iface_port.attr,
634 : : &dev_attr_iface_ipaddress_state.attr,
635 : : &dev_attr_iface_delayed_ack_en.attr,
636 : : &dev_attr_iface_tcp_nagle_disable.attr,
637 : : &dev_attr_iface_tcp_wsf_disable.attr,
638 : : &dev_attr_iface_tcp_wsf.attr,
639 : : &dev_attr_iface_tcp_timer_scale.attr,
640 : : &dev_attr_iface_tcp_timestamp_en.attr,
641 : : &dev_attr_iface_cache_id.attr,
642 : : &dev_attr_iface_redirect_en.attr,
643 : : &dev_attr_iface_def_taskmgmt_tmo.attr,
644 : : &dev_attr_iface_header_digest.attr,
645 : : &dev_attr_iface_data_digest.attr,
646 : : &dev_attr_iface_immediate_data.attr,
647 : : &dev_attr_iface_initial_r2t.attr,
648 : : &dev_attr_iface_data_seq_in_order.attr,
649 : : &dev_attr_iface_data_pdu_in_order.attr,
650 : : &dev_attr_iface_erl.attr,
651 : : &dev_attr_iface_max_recv_dlength.attr,
652 : : &dev_attr_iface_first_burst_len.attr,
653 : : &dev_attr_iface_max_outstanding_r2t.attr,
654 : : &dev_attr_iface_max_burst_len.attr,
655 : : &dev_attr_iface_chap_auth.attr,
656 : : &dev_attr_iface_bidi_chap.attr,
657 : : &dev_attr_iface_discovery_auth_optional.attr,
658 : : &dev_attr_iface_discovery_logout.attr,
659 : : &dev_attr_iface_strict_login_comp_en.attr,
660 : : &dev_attr_iface_initiator_name.attr,
661 : : &dev_attr_ipv4_iface_dhcp_dns_address_en.attr,
662 : : &dev_attr_ipv4_iface_dhcp_slp_da_info_en.attr,
663 : : &dev_attr_ipv4_iface_tos_en.attr,
664 : : &dev_attr_ipv4_iface_tos.attr,
665 : : &dev_attr_ipv4_iface_grat_arp_en.attr,
666 : : &dev_attr_ipv4_iface_dhcp_alt_client_id_en.attr,
667 : : &dev_attr_ipv4_iface_dhcp_alt_client_id.attr,
668 : : &dev_attr_ipv4_iface_dhcp_req_vendor_id_en.attr,
669 : : &dev_attr_ipv4_iface_dhcp_use_vendor_id_en.attr,
670 : : &dev_attr_ipv4_iface_dhcp_vendor_id.attr,
671 : : &dev_attr_ipv4_iface_dhcp_learn_iqn_en.attr,
672 : : &dev_attr_ipv4_iface_fragment_disable.attr,
673 : : &dev_attr_ipv4_iface_incoming_forwarding_en.attr,
674 : : &dev_attr_ipv4_iface_ttl.attr,
675 : : &dev_attr_ipv6_iface_link_local_state.attr,
676 : : &dev_attr_ipv6_iface_router_state.attr,
677 : : &dev_attr_ipv6_iface_grat_neighbor_adv_en.attr,
678 : : &dev_attr_ipv6_iface_mld_en.attr,
679 : : &dev_attr_ipv6_iface_flow_label.attr,
680 : : &dev_attr_ipv6_iface_traffic_class.attr,
681 : : &dev_attr_ipv6_iface_hop_limit.attr,
682 : : &dev_attr_ipv6_iface_nd_reachable_tmo.attr,
683 : : &dev_attr_ipv6_iface_nd_rexmit_time.attr,
684 : : &dev_attr_ipv6_iface_nd_stale_tmo.attr,
685 : : &dev_attr_ipv6_iface_dup_addr_detect_cnt.attr,
686 : : &dev_attr_ipv6_iface_router_adv_link_mtu.attr,
687 : : NULL,
688 : : };
689 : :
690 : : static struct attribute_group iscsi_iface_group = {
691 : : .attrs = iscsi_iface_attrs,
692 : : .is_visible = iscsi_iface_attr_is_visible,
693 : : };
694 : :
695 : : /* convert iscsi_ipaddress_state values to ascii string name */
696 : : static const struct {
697 : : enum iscsi_ipaddress_state value;
698 : : char *name;
699 : : } iscsi_ipaddress_state_names[] = {
700 : : {ISCSI_IPDDRESS_STATE_UNCONFIGURED, "Unconfigured" },
701 : : {ISCSI_IPDDRESS_STATE_ACQUIRING, "Acquiring" },
702 : : {ISCSI_IPDDRESS_STATE_TENTATIVE, "Tentative" },
703 : : {ISCSI_IPDDRESS_STATE_VALID, "Valid" },
704 : : {ISCSI_IPDDRESS_STATE_DISABLING, "Disabling" },
705 : : {ISCSI_IPDDRESS_STATE_INVALID, "Invalid" },
706 : : {ISCSI_IPDDRESS_STATE_DEPRECATED, "Deprecated" },
707 : : };
708 : :
709 : 0 : char *iscsi_get_ipaddress_state_name(enum iscsi_ipaddress_state port_state)
710 : : {
711 : : int i;
712 : : char *state = NULL;
713 : :
714 : 0 : for (i = 0; i < ARRAY_SIZE(iscsi_ipaddress_state_names); i++) {
715 : 0 : if (iscsi_ipaddress_state_names[i].value == port_state) {
716 : 0 : state = iscsi_ipaddress_state_names[i].name;
717 : 0 : break;
718 : : }
719 : : }
720 : 0 : return state;
721 : : }
722 : : EXPORT_SYMBOL_GPL(iscsi_get_ipaddress_state_name);
723 : :
724 : : /* convert iscsi_router_state values to ascii string name */
725 : : static const struct {
726 : : enum iscsi_router_state value;
727 : : char *name;
728 : : } iscsi_router_state_names[] = {
729 : : {ISCSI_ROUTER_STATE_UNKNOWN, "Unknown" },
730 : : {ISCSI_ROUTER_STATE_ADVERTISED, "Advertised" },
731 : : {ISCSI_ROUTER_STATE_MANUAL, "Manual" },
732 : : {ISCSI_ROUTER_STATE_STALE, "Stale" },
733 : : };
734 : :
735 : 0 : char *iscsi_get_router_state_name(enum iscsi_router_state router_state)
736 : : {
737 : : int i;
738 : : char *state = NULL;
739 : :
740 : 0 : for (i = 0; i < ARRAY_SIZE(iscsi_router_state_names); i++) {
741 : 0 : if (iscsi_router_state_names[i].value == router_state) {
742 : 0 : state = iscsi_router_state_names[i].name;
743 : 0 : break;
744 : : }
745 : : }
746 : 0 : return state;
747 : : }
748 : : EXPORT_SYMBOL_GPL(iscsi_get_router_state_name);
749 : :
750 : : struct iscsi_iface *
751 : 0 : iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport,
752 : : uint32_t iface_type, uint32_t iface_num, int dd_size)
753 : : {
754 : : struct iscsi_iface *iface;
755 : : int err;
756 : :
757 : 0 : iface = kzalloc(sizeof(*iface) + dd_size, GFP_KERNEL);
758 : 0 : if (!iface)
759 : : return NULL;
760 : :
761 : 0 : iface->transport = transport;
762 : 0 : iface->iface_type = iface_type;
763 : 0 : iface->iface_num = iface_num;
764 : 0 : iface->dev.release = iscsi_iface_release;
765 : 0 : iface->dev.class = &iscsi_iface_class;
766 : : /* parent reference released in iscsi_iface_release */
767 : 0 : iface->dev.parent = get_device(&shost->shost_gendev);
768 : 0 : if (iface_type == ISCSI_IFACE_TYPE_IPV4)
769 : 0 : dev_set_name(&iface->dev, "ipv4-iface-%u-%u", shost->host_no,
770 : : iface_num);
771 : : else
772 : 0 : dev_set_name(&iface->dev, "ipv6-iface-%u-%u", shost->host_no,
773 : : iface_num);
774 : :
775 : 0 : err = device_register(&iface->dev);
776 : 0 : if (err)
777 : : goto free_iface;
778 : :
779 : 0 : err = sysfs_create_group(&iface->dev.kobj, &iscsi_iface_group);
780 : 0 : if (err)
781 : : goto unreg_iface;
782 : :
783 : 0 : if (dd_size)
784 : 0 : iface->dd_data = &iface[1];
785 : 0 : return iface;
786 : :
787 : : unreg_iface:
788 : 0 : device_unregister(&iface->dev);
789 : 0 : return NULL;
790 : :
791 : : free_iface:
792 : 0 : put_device(iface->dev.parent);
793 : 0 : kfree(iface);
794 : 0 : return NULL;
795 : : }
796 : : EXPORT_SYMBOL_GPL(iscsi_create_iface);
797 : :
798 : 0 : void iscsi_destroy_iface(struct iscsi_iface *iface)
799 : : {
800 : 0 : sysfs_remove_group(&iface->dev.kobj, &iscsi_iface_group);
801 : 0 : device_unregister(&iface->dev);
802 : 0 : }
803 : : EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
804 : :
805 : : /*
806 : : * Interface to display flash node params to sysfs
807 : : */
808 : :
809 : : #define ISCSI_FLASHNODE_ATTR(_prefix, _name, _mode, _show, _store) \
810 : : struct device_attribute dev_attr_##_prefix##_##_name = \
811 : : __ATTR(_name, _mode, _show, _store)
812 : :
813 : : /* flash node session attrs show */
814 : : #define iscsi_flashnode_sess_attr_show(type, name, param) \
815 : : static ssize_t \
816 : : show_##type##_##name(struct device *dev, struct device_attribute *attr, \
817 : : char *buf) \
818 : : { \
819 : : struct iscsi_bus_flash_session *fnode_sess = \
820 : : iscsi_dev_to_flash_session(dev);\
821 : : struct iscsi_transport *t = fnode_sess->transport; \
822 : : return t->get_flashnode_param(fnode_sess, param, buf); \
823 : : } \
824 : :
825 : :
826 : : #define iscsi_flashnode_sess_attr(type, name, param) \
827 : : iscsi_flashnode_sess_attr_show(type, name, param) \
828 : : static ISCSI_FLASHNODE_ATTR(type, name, S_IRUGO, \
829 : : show_##type##_##name, NULL);
830 : :
831 : : /* Flash node session attributes */
832 : :
833 : 0 : iscsi_flashnode_sess_attr(fnode, auto_snd_tgt_disable,
834 : : ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE);
835 : 0 : iscsi_flashnode_sess_attr(fnode, discovery_session,
836 : : ISCSI_FLASHNODE_DISCOVERY_SESS);
837 : 0 : iscsi_flashnode_sess_attr(fnode, portal_type, ISCSI_FLASHNODE_PORTAL_TYPE);
838 : 0 : iscsi_flashnode_sess_attr(fnode, entry_enable, ISCSI_FLASHNODE_ENTRY_EN);
839 : 0 : iscsi_flashnode_sess_attr(fnode, immediate_data, ISCSI_FLASHNODE_IMM_DATA_EN);
840 : 0 : iscsi_flashnode_sess_attr(fnode, initial_r2t, ISCSI_FLASHNODE_INITIAL_R2T_EN);
841 : 0 : iscsi_flashnode_sess_attr(fnode, data_seq_in_order,
842 : : ISCSI_FLASHNODE_DATASEQ_INORDER);
843 : 0 : iscsi_flashnode_sess_attr(fnode, data_pdu_in_order,
844 : : ISCSI_FLASHNODE_PDU_INORDER);
845 : 0 : iscsi_flashnode_sess_attr(fnode, chap_auth, ISCSI_FLASHNODE_CHAP_AUTH_EN);
846 : 0 : iscsi_flashnode_sess_attr(fnode, discovery_logout,
847 : : ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN);
848 : 0 : iscsi_flashnode_sess_attr(fnode, bidi_chap, ISCSI_FLASHNODE_BIDI_CHAP_EN);
849 : 0 : iscsi_flashnode_sess_attr(fnode, discovery_auth_optional,
850 : : ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL);
851 : 0 : iscsi_flashnode_sess_attr(fnode, erl, ISCSI_FLASHNODE_ERL);
852 : 0 : iscsi_flashnode_sess_attr(fnode, first_burst_len, ISCSI_FLASHNODE_FIRST_BURST);
853 : 0 : iscsi_flashnode_sess_attr(fnode, def_time2wait, ISCSI_FLASHNODE_DEF_TIME2WAIT);
854 : 0 : iscsi_flashnode_sess_attr(fnode, def_time2retain,
855 : : ISCSI_FLASHNODE_DEF_TIME2RETAIN);
856 : 0 : iscsi_flashnode_sess_attr(fnode, max_outstanding_r2t, ISCSI_FLASHNODE_MAX_R2T);
857 : 0 : iscsi_flashnode_sess_attr(fnode, isid, ISCSI_FLASHNODE_ISID);
858 : 0 : iscsi_flashnode_sess_attr(fnode, tsid, ISCSI_FLASHNODE_TSID);
859 : 0 : iscsi_flashnode_sess_attr(fnode, max_burst_len, ISCSI_FLASHNODE_MAX_BURST);
860 : 0 : iscsi_flashnode_sess_attr(fnode, def_taskmgmt_tmo,
861 : : ISCSI_FLASHNODE_DEF_TASKMGMT_TMO);
862 : 0 : iscsi_flashnode_sess_attr(fnode, targetalias, ISCSI_FLASHNODE_ALIAS);
863 : 0 : iscsi_flashnode_sess_attr(fnode, targetname, ISCSI_FLASHNODE_NAME);
864 : 0 : iscsi_flashnode_sess_attr(fnode, tpgt, ISCSI_FLASHNODE_TPGT);
865 : 0 : iscsi_flashnode_sess_attr(fnode, discovery_parent_idx,
866 : : ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX);
867 : 0 : iscsi_flashnode_sess_attr(fnode, discovery_parent_type,
868 : : ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE);
869 : 0 : iscsi_flashnode_sess_attr(fnode, chap_in_idx, ISCSI_FLASHNODE_CHAP_IN_IDX);
870 : 0 : iscsi_flashnode_sess_attr(fnode, chap_out_idx, ISCSI_FLASHNODE_CHAP_OUT_IDX);
871 : 0 : iscsi_flashnode_sess_attr(fnode, username, ISCSI_FLASHNODE_USERNAME);
872 : 0 : iscsi_flashnode_sess_attr(fnode, username_in, ISCSI_FLASHNODE_USERNAME_IN);
873 : 0 : iscsi_flashnode_sess_attr(fnode, password, ISCSI_FLASHNODE_PASSWORD);
874 : 0 : iscsi_flashnode_sess_attr(fnode, password_in, ISCSI_FLASHNODE_PASSWORD_IN);
875 : 0 : iscsi_flashnode_sess_attr(fnode, is_boot_target, ISCSI_FLASHNODE_IS_BOOT_TGT);
876 : :
877 : : static struct attribute *iscsi_flashnode_sess_attrs[] = {
878 : : &dev_attr_fnode_auto_snd_tgt_disable.attr,
879 : : &dev_attr_fnode_discovery_session.attr,
880 : : &dev_attr_fnode_portal_type.attr,
881 : : &dev_attr_fnode_entry_enable.attr,
882 : : &dev_attr_fnode_immediate_data.attr,
883 : : &dev_attr_fnode_initial_r2t.attr,
884 : : &dev_attr_fnode_data_seq_in_order.attr,
885 : : &dev_attr_fnode_data_pdu_in_order.attr,
886 : : &dev_attr_fnode_chap_auth.attr,
887 : : &dev_attr_fnode_discovery_logout.attr,
888 : : &dev_attr_fnode_bidi_chap.attr,
889 : : &dev_attr_fnode_discovery_auth_optional.attr,
890 : : &dev_attr_fnode_erl.attr,
891 : : &dev_attr_fnode_first_burst_len.attr,
892 : : &dev_attr_fnode_def_time2wait.attr,
893 : : &dev_attr_fnode_def_time2retain.attr,
894 : : &dev_attr_fnode_max_outstanding_r2t.attr,
895 : : &dev_attr_fnode_isid.attr,
896 : : &dev_attr_fnode_tsid.attr,
897 : : &dev_attr_fnode_max_burst_len.attr,
898 : : &dev_attr_fnode_def_taskmgmt_tmo.attr,
899 : : &dev_attr_fnode_targetalias.attr,
900 : : &dev_attr_fnode_targetname.attr,
901 : : &dev_attr_fnode_tpgt.attr,
902 : : &dev_attr_fnode_discovery_parent_idx.attr,
903 : : &dev_attr_fnode_discovery_parent_type.attr,
904 : : &dev_attr_fnode_chap_in_idx.attr,
905 : : &dev_attr_fnode_chap_out_idx.attr,
906 : : &dev_attr_fnode_username.attr,
907 : : &dev_attr_fnode_username_in.attr,
908 : : &dev_attr_fnode_password.attr,
909 : : &dev_attr_fnode_password_in.attr,
910 : : &dev_attr_fnode_is_boot_target.attr,
911 : : NULL,
912 : : };
913 : :
914 : 0 : static umode_t iscsi_flashnode_sess_attr_is_visible(struct kobject *kobj,
915 : : struct attribute *attr,
916 : : int i)
917 : : {
918 : : struct device *dev = container_of(kobj, struct device, kobj);
919 : : struct iscsi_bus_flash_session *fnode_sess =
920 : : iscsi_dev_to_flash_session(dev);
921 : 0 : struct iscsi_transport *t = fnode_sess->transport;
922 : : int param;
923 : :
924 : 0 : if (attr == &dev_attr_fnode_auto_snd_tgt_disable.attr) {
925 : : param = ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE;
926 : 0 : } else if (attr == &dev_attr_fnode_discovery_session.attr) {
927 : : param = ISCSI_FLASHNODE_DISCOVERY_SESS;
928 : 0 : } else if (attr == &dev_attr_fnode_portal_type.attr) {
929 : : param = ISCSI_FLASHNODE_PORTAL_TYPE;
930 : 0 : } else if (attr == &dev_attr_fnode_entry_enable.attr) {
931 : : param = ISCSI_FLASHNODE_ENTRY_EN;
932 : 0 : } else if (attr == &dev_attr_fnode_immediate_data.attr) {
933 : : param = ISCSI_FLASHNODE_IMM_DATA_EN;
934 : 0 : } else if (attr == &dev_attr_fnode_initial_r2t.attr) {
935 : : param = ISCSI_FLASHNODE_INITIAL_R2T_EN;
936 : 0 : } else if (attr == &dev_attr_fnode_data_seq_in_order.attr) {
937 : : param = ISCSI_FLASHNODE_DATASEQ_INORDER;
938 : 0 : } else if (attr == &dev_attr_fnode_data_pdu_in_order.attr) {
939 : : param = ISCSI_FLASHNODE_PDU_INORDER;
940 : 0 : } else if (attr == &dev_attr_fnode_chap_auth.attr) {
941 : : param = ISCSI_FLASHNODE_CHAP_AUTH_EN;
942 : 0 : } else if (attr == &dev_attr_fnode_discovery_logout.attr) {
943 : : param = ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN;
944 : 0 : } else if (attr == &dev_attr_fnode_bidi_chap.attr) {
945 : : param = ISCSI_FLASHNODE_BIDI_CHAP_EN;
946 : 0 : } else if (attr == &dev_attr_fnode_discovery_auth_optional.attr) {
947 : : param = ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL;
948 : 0 : } else if (attr == &dev_attr_fnode_erl.attr) {
949 : : param = ISCSI_FLASHNODE_ERL;
950 : 0 : } else if (attr == &dev_attr_fnode_first_burst_len.attr) {
951 : : param = ISCSI_FLASHNODE_FIRST_BURST;
952 : 0 : } else if (attr == &dev_attr_fnode_def_time2wait.attr) {
953 : : param = ISCSI_FLASHNODE_DEF_TIME2WAIT;
954 : 0 : } else if (attr == &dev_attr_fnode_def_time2retain.attr) {
955 : : param = ISCSI_FLASHNODE_DEF_TIME2RETAIN;
956 : 0 : } else if (attr == &dev_attr_fnode_max_outstanding_r2t.attr) {
957 : : param = ISCSI_FLASHNODE_MAX_R2T;
958 : 0 : } else if (attr == &dev_attr_fnode_isid.attr) {
959 : : param = ISCSI_FLASHNODE_ISID;
960 : 0 : } else if (attr == &dev_attr_fnode_tsid.attr) {
961 : : param = ISCSI_FLASHNODE_TSID;
962 : 0 : } else if (attr == &dev_attr_fnode_max_burst_len.attr) {
963 : : param = ISCSI_FLASHNODE_MAX_BURST;
964 : 0 : } else if (attr == &dev_attr_fnode_def_taskmgmt_tmo.attr) {
965 : : param = ISCSI_FLASHNODE_DEF_TASKMGMT_TMO;
966 : 0 : } else if (attr == &dev_attr_fnode_targetalias.attr) {
967 : : param = ISCSI_FLASHNODE_ALIAS;
968 : 0 : } else if (attr == &dev_attr_fnode_targetname.attr) {
969 : : param = ISCSI_FLASHNODE_NAME;
970 : 0 : } else if (attr == &dev_attr_fnode_tpgt.attr) {
971 : : param = ISCSI_FLASHNODE_TPGT;
972 : 0 : } else if (attr == &dev_attr_fnode_discovery_parent_idx.attr) {
973 : : param = ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX;
974 : 0 : } else if (attr == &dev_attr_fnode_discovery_parent_type.attr) {
975 : : param = ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE;
976 : 0 : } else if (attr == &dev_attr_fnode_chap_in_idx.attr) {
977 : : param = ISCSI_FLASHNODE_CHAP_IN_IDX;
978 : 0 : } else if (attr == &dev_attr_fnode_chap_out_idx.attr) {
979 : : param = ISCSI_FLASHNODE_CHAP_OUT_IDX;
980 : 0 : } else if (attr == &dev_attr_fnode_username.attr) {
981 : : param = ISCSI_FLASHNODE_USERNAME;
982 : 0 : } else if (attr == &dev_attr_fnode_username_in.attr) {
983 : : param = ISCSI_FLASHNODE_USERNAME_IN;
984 : 0 : } else if (attr == &dev_attr_fnode_password.attr) {
985 : : param = ISCSI_FLASHNODE_PASSWORD;
986 : 0 : } else if (attr == &dev_attr_fnode_password_in.attr) {
987 : : param = ISCSI_FLASHNODE_PASSWORD_IN;
988 : 0 : } else if (attr == &dev_attr_fnode_is_boot_target.attr) {
989 : : param = ISCSI_FLASHNODE_IS_BOOT_TGT;
990 : : } else {
991 : 0 : WARN_ONCE(1, "Invalid flashnode session attr");
992 : : return 0;
993 : : }
994 : :
995 : 0 : return t->attr_is_visible(ISCSI_FLASHNODE_PARAM, param);
996 : : }
997 : :
998 : : static struct attribute_group iscsi_flashnode_sess_attr_group = {
999 : : .attrs = iscsi_flashnode_sess_attrs,
1000 : : .is_visible = iscsi_flashnode_sess_attr_is_visible,
1001 : : };
1002 : :
1003 : : static const struct attribute_group *iscsi_flashnode_sess_attr_groups[] = {
1004 : : &iscsi_flashnode_sess_attr_group,
1005 : : NULL,
1006 : : };
1007 : :
1008 : 0 : static void iscsi_flashnode_sess_release(struct device *dev)
1009 : : {
1010 : : struct iscsi_bus_flash_session *fnode_sess =
1011 : 0 : iscsi_dev_to_flash_session(dev);
1012 : :
1013 : 0 : kfree(fnode_sess->targetname);
1014 : 0 : kfree(fnode_sess->targetalias);
1015 : 0 : kfree(fnode_sess->portal_type);
1016 : 0 : kfree(fnode_sess);
1017 : 0 : }
1018 : :
1019 : : static const struct device_type iscsi_flashnode_sess_dev_type = {
1020 : : .name = "iscsi_flashnode_sess_dev_type",
1021 : : .groups = iscsi_flashnode_sess_attr_groups,
1022 : : .release = iscsi_flashnode_sess_release,
1023 : : };
1024 : :
1025 : : /* flash node connection attrs show */
1026 : : #define iscsi_flashnode_conn_attr_show(type, name, param) \
1027 : : static ssize_t \
1028 : : show_##type##_##name(struct device *dev, struct device_attribute *attr, \
1029 : : char *buf) \
1030 : : { \
1031 : : struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);\
1032 : : struct iscsi_bus_flash_session *fnode_sess = \
1033 : : iscsi_flash_conn_to_flash_session(fnode_conn);\
1034 : : struct iscsi_transport *t = fnode_conn->transport; \
1035 : : return t->get_flashnode_param(fnode_sess, param, buf); \
1036 : : } \
1037 : :
1038 : :
1039 : : #define iscsi_flashnode_conn_attr(type, name, param) \
1040 : : iscsi_flashnode_conn_attr_show(type, name, param) \
1041 : : static ISCSI_FLASHNODE_ATTR(type, name, S_IRUGO, \
1042 : : show_##type##_##name, NULL);
1043 : :
1044 : : /* Flash node connection attributes */
1045 : :
1046 : 0 : iscsi_flashnode_conn_attr(fnode, is_fw_assigned_ipv6,
1047 : : ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6);
1048 : 0 : iscsi_flashnode_conn_attr(fnode, header_digest, ISCSI_FLASHNODE_HDR_DGST_EN);
1049 : 0 : iscsi_flashnode_conn_attr(fnode, data_digest, ISCSI_FLASHNODE_DATA_DGST_EN);
1050 : 0 : iscsi_flashnode_conn_attr(fnode, snack_req, ISCSI_FLASHNODE_SNACK_REQ_EN);
1051 : 0 : iscsi_flashnode_conn_attr(fnode, tcp_timestamp_stat,
1052 : : ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT);
1053 : 0 : iscsi_flashnode_conn_attr(fnode, tcp_nagle_disable,
1054 : : ISCSI_FLASHNODE_TCP_NAGLE_DISABLE);
1055 : 0 : iscsi_flashnode_conn_attr(fnode, tcp_wsf_disable,
1056 : : ISCSI_FLASHNODE_TCP_WSF_DISABLE);
1057 : 0 : iscsi_flashnode_conn_attr(fnode, tcp_timer_scale,
1058 : : ISCSI_FLASHNODE_TCP_TIMER_SCALE);
1059 : 0 : iscsi_flashnode_conn_attr(fnode, tcp_timestamp_enable,
1060 : : ISCSI_FLASHNODE_TCP_TIMESTAMP_EN);
1061 : 0 : iscsi_flashnode_conn_attr(fnode, fragment_disable,
1062 : : ISCSI_FLASHNODE_IP_FRAG_DISABLE);
1063 : 0 : iscsi_flashnode_conn_attr(fnode, keepalive_tmo, ISCSI_FLASHNODE_KEEPALIVE_TMO);
1064 : 0 : iscsi_flashnode_conn_attr(fnode, port, ISCSI_FLASHNODE_PORT);
1065 : 0 : iscsi_flashnode_conn_attr(fnode, ipaddress, ISCSI_FLASHNODE_IPADDR);
1066 : 0 : iscsi_flashnode_conn_attr(fnode, max_recv_dlength,
1067 : : ISCSI_FLASHNODE_MAX_RECV_DLENGTH);
1068 : 0 : iscsi_flashnode_conn_attr(fnode, max_xmit_dlength,
1069 : : ISCSI_FLASHNODE_MAX_XMIT_DLENGTH);
1070 : 0 : iscsi_flashnode_conn_attr(fnode, local_port, ISCSI_FLASHNODE_LOCAL_PORT);
1071 : 0 : iscsi_flashnode_conn_attr(fnode, ipv4_tos, ISCSI_FLASHNODE_IPV4_TOS);
1072 : 0 : iscsi_flashnode_conn_attr(fnode, ipv6_traffic_class, ISCSI_FLASHNODE_IPV6_TC);
1073 : 0 : iscsi_flashnode_conn_attr(fnode, ipv6_flow_label,
1074 : : ISCSI_FLASHNODE_IPV6_FLOW_LABEL);
1075 : 0 : iscsi_flashnode_conn_attr(fnode, redirect_ipaddr,
1076 : : ISCSI_FLASHNODE_REDIRECT_IPADDR);
1077 : 0 : iscsi_flashnode_conn_attr(fnode, max_segment_size,
1078 : : ISCSI_FLASHNODE_MAX_SEGMENT_SIZE);
1079 : 0 : iscsi_flashnode_conn_attr(fnode, link_local_ipv6,
1080 : : ISCSI_FLASHNODE_LINK_LOCAL_IPV6);
1081 : 0 : iscsi_flashnode_conn_attr(fnode, tcp_xmit_wsf, ISCSI_FLASHNODE_TCP_XMIT_WSF);
1082 : 0 : iscsi_flashnode_conn_attr(fnode, tcp_recv_wsf, ISCSI_FLASHNODE_TCP_RECV_WSF);
1083 : 0 : iscsi_flashnode_conn_attr(fnode, statsn, ISCSI_FLASHNODE_STATSN);
1084 : 0 : iscsi_flashnode_conn_attr(fnode, exp_statsn, ISCSI_FLASHNODE_EXP_STATSN);
1085 : :
1086 : : static struct attribute *iscsi_flashnode_conn_attrs[] = {
1087 : : &dev_attr_fnode_is_fw_assigned_ipv6.attr,
1088 : : &dev_attr_fnode_header_digest.attr,
1089 : : &dev_attr_fnode_data_digest.attr,
1090 : : &dev_attr_fnode_snack_req.attr,
1091 : : &dev_attr_fnode_tcp_timestamp_stat.attr,
1092 : : &dev_attr_fnode_tcp_nagle_disable.attr,
1093 : : &dev_attr_fnode_tcp_wsf_disable.attr,
1094 : : &dev_attr_fnode_tcp_timer_scale.attr,
1095 : : &dev_attr_fnode_tcp_timestamp_enable.attr,
1096 : : &dev_attr_fnode_fragment_disable.attr,
1097 : : &dev_attr_fnode_max_recv_dlength.attr,
1098 : : &dev_attr_fnode_max_xmit_dlength.attr,
1099 : : &dev_attr_fnode_keepalive_tmo.attr,
1100 : : &dev_attr_fnode_port.attr,
1101 : : &dev_attr_fnode_ipaddress.attr,
1102 : : &dev_attr_fnode_redirect_ipaddr.attr,
1103 : : &dev_attr_fnode_max_segment_size.attr,
1104 : : &dev_attr_fnode_local_port.attr,
1105 : : &dev_attr_fnode_ipv4_tos.attr,
1106 : : &dev_attr_fnode_ipv6_traffic_class.attr,
1107 : : &dev_attr_fnode_ipv6_flow_label.attr,
1108 : : &dev_attr_fnode_link_local_ipv6.attr,
1109 : : &dev_attr_fnode_tcp_xmit_wsf.attr,
1110 : : &dev_attr_fnode_tcp_recv_wsf.attr,
1111 : : &dev_attr_fnode_statsn.attr,
1112 : : &dev_attr_fnode_exp_statsn.attr,
1113 : : NULL,
1114 : : };
1115 : :
1116 : 0 : static umode_t iscsi_flashnode_conn_attr_is_visible(struct kobject *kobj,
1117 : : struct attribute *attr,
1118 : : int i)
1119 : : {
1120 : : struct device *dev = container_of(kobj, struct device, kobj);
1121 : : struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);
1122 : 0 : struct iscsi_transport *t = fnode_conn->transport;
1123 : : int param;
1124 : :
1125 : 0 : if (attr == &dev_attr_fnode_is_fw_assigned_ipv6.attr) {
1126 : : param = ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6;
1127 : 0 : } else if (attr == &dev_attr_fnode_header_digest.attr) {
1128 : : param = ISCSI_FLASHNODE_HDR_DGST_EN;
1129 : 0 : } else if (attr == &dev_attr_fnode_data_digest.attr) {
1130 : : param = ISCSI_FLASHNODE_DATA_DGST_EN;
1131 : 0 : } else if (attr == &dev_attr_fnode_snack_req.attr) {
1132 : : param = ISCSI_FLASHNODE_SNACK_REQ_EN;
1133 : 0 : } else if (attr == &dev_attr_fnode_tcp_timestamp_stat.attr) {
1134 : : param = ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT;
1135 : 0 : } else if (attr == &dev_attr_fnode_tcp_nagle_disable.attr) {
1136 : : param = ISCSI_FLASHNODE_TCP_NAGLE_DISABLE;
1137 : 0 : } else if (attr == &dev_attr_fnode_tcp_wsf_disable.attr) {
1138 : : param = ISCSI_FLASHNODE_TCP_WSF_DISABLE;
1139 : 0 : } else if (attr == &dev_attr_fnode_tcp_timer_scale.attr) {
1140 : : param = ISCSI_FLASHNODE_TCP_TIMER_SCALE;
1141 : 0 : } else if (attr == &dev_attr_fnode_tcp_timestamp_enable.attr) {
1142 : : param = ISCSI_FLASHNODE_TCP_TIMESTAMP_EN;
1143 : 0 : } else if (attr == &dev_attr_fnode_fragment_disable.attr) {
1144 : : param = ISCSI_FLASHNODE_IP_FRAG_DISABLE;
1145 : 0 : } else if (attr == &dev_attr_fnode_max_recv_dlength.attr) {
1146 : : param = ISCSI_FLASHNODE_MAX_RECV_DLENGTH;
1147 : 0 : } else if (attr == &dev_attr_fnode_max_xmit_dlength.attr) {
1148 : : param = ISCSI_FLASHNODE_MAX_XMIT_DLENGTH;
1149 : 0 : } else if (attr == &dev_attr_fnode_keepalive_tmo.attr) {
1150 : : param = ISCSI_FLASHNODE_KEEPALIVE_TMO;
1151 : 0 : } else if (attr == &dev_attr_fnode_port.attr) {
1152 : : param = ISCSI_FLASHNODE_PORT;
1153 : 0 : } else if (attr == &dev_attr_fnode_ipaddress.attr) {
1154 : : param = ISCSI_FLASHNODE_IPADDR;
1155 : 0 : } else if (attr == &dev_attr_fnode_redirect_ipaddr.attr) {
1156 : : param = ISCSI_FLASHNODE_REDIRECT_IPADDR;
1157 : 0 : } else if (attr == &dev_attr_fnode_max_segment_size.attr) {
1158 : : param = ISCSI_FLASHNODE_MAX_SEGMENT_SIZE;
1159 : 0 : } else if (attr == &dev_attr_fnode_local_port.attr) {
1160 : : param = ISCSI_FLASHNODE_LOCAL_PORT;
1161 : 0 : } else if (attr == &dev_attr_fnode_ipv4_tos.attr) {
1162 : : param = ISCSI_FLASHNODE_IPV4_TOS;
1163 : 0 : } else if (attr == &dev_attr_fnode_ipv6_traffic_class.attr) {
1164 : : param = ISCSI_FLASHNODE_IPV6_TC;
1165 : 0 : } else if (attr == &dev_attr_fnode_ipv6_flow_label.attr) {
1166 : : param = ISCSI_FLASHNODE_IPV6_FLOW_LABEL;
1167 : 0 : } else if (attr == &dev_attr_fnode_link_local_ipv6.attr) {
1168 : : param = ISCSI_FLASHNODE_LINK_LOCAL_IPV6;
1169 : 0 : } else if (attr == &dev_attr_fnode_tcp_xmit_wsf.attr) {
1170 : : param = ISCSI_FLASHNODE_TCP_XMIT_WSF;
1171 : 0 : } else if (attr == &dev_attr_fnode_tcp_recv_wsf.attr) {
1172 : : param = ISCSI_FLASHNODE_TCP_RECV_WSF;
1173 : 0 : } else if (attr == &dev_attr_fnode_statsn.attr) {
1174 : : param = ISCSI_FLASHNODE_STATSN;
1175 : 0 : } else if (attr == &dev_attr_fnode_exp_statsn.attr) {
1176 : : param = ISCSI_FLASHNODE_EXP_STATSN;
1177 : : } else {
1178 : 0 : WARN_ONCE(1, "Invalid flashnode connection attr");
1179 : : return 0;
1180 : : }
1181 : :
1182 : 0 : return t->attr_is_visible(ISCSI_FLASHNODE_PARAM, param);
1183 : : }
1184 : :
1185 : : static struct attribute_group iscsi_flashnode_conn_attr_group = {
1186 : : .attrs = iscsi_flashnode_conn_attrs,
1187 : : .is_visible = iscsi_flashnode_conn_attr_is_visible,
1188 : : };
1189 : :
1190 : : static const struct attribute_group *iscsi_flashnode_conn_attr_groups[] = {
1191 : : &iscsi_flashnode_conn_attr_group,
1192 : : NULL,
1193 : : };
1194 : :
1195 : 0 : static void iscsi_flashnode_conn_release(struct device *dev)
1196 : : {
1197 : 0 : struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);
1198 : :
1199 : 0 : kfree(fnode_conn->ipaddress);
1200 : 0 : kfree(fnode_conn->redirect_ipaddr);
1201 : 0 : kfree(fnode_conn->link_local_ipv6_addr);
1202 : 0 : kfree(fnode_conn);
1203 : 0 : }
1204 : :
1205 : : static const struct device_type iscsi_flashnode_conn_dev_type = {
1206 : : .name = "iscsi_flashnode_conn_dev_type",
1207 : : .groups = iscsi_flashnode_conn_attr_groups,
1208 : : .release = iscsi_flashnode_conn_release,
1209 : : };
1210 : :
1211 : : static struct bus_type iscsi_flashnode_bus;
1212 : :
1213 : 0 : int iscsi_flashnode_bus_match(struct device *dev,
1214 : : struct device_driver *drv)
1215 : : {
1216 : 0 : if (dev->bus == &iscsi_flashnode_bus)
1217 : : return 1;
1218 : 0 : return 0;
1219 : : }
1220 : : EXPORT_SYMBOL_GPL(iscsi_flashnode_bus_match);
1221 : :
1222 : : static struct bus_type iscsi_flashnode_bus = {
1223 : : .name = "iscsi_flashnode",
1224 : : .match = &iscsi_flashnode_bus_match,
1225 : : };
1226 : :
1227 : : /**
1228 : : * iscsi_create_flashnode_sess - Add flashnode session entry in sysfs
1229 : : * @shost: pointer to host data
1230 : : * @index: index of flashnode to add in sysfs
1231 : : * @transport: pointer to transport data
1232 : : * @dd_size: total size to allocate
1233 : : *
1234 : : * Adds a sysfs entry for the flashnode session attributes
1235 : : *
1236 : : * Returns:
1237 : : * pointer to allocated flashnode sess on success
1238 : : * %NULL on failure
1239 : : */
1240 : : struct iscsi_bus_flash_session *
1241 : 0 : iscsi_create_flashnode_sess(struct Scsi_Host *shost, int index,
1242 : : struct iscsi_transport *transport,
1243 : : int dd_size)
1244 : : {
1245 : : struct iscsi_bus_flash_session *fnode_sess;
1246 : : int err;
1247 : :
1248 : 0 : fnode_sess = kzalloc(sizeof(*fnode_sess) + dd_size, GFP_KERNEL);
1249 : 0 : if (!fnode_sess)
1250 : : return NULL;
1251 : :
1252 : 0 : fnode_sess->transport = transport;
1253 : 0 : fnode_sess->target_id = index;
1254 : 0 : fnode_sess->dev.type = &iscsi_flashnode_sess_dev_type;
1255 : 0 : fnode_sess->dev.bus = &iscsi_flashnode_bus;
1256 : 0 : fnode_sess->dev.parent = &shost->shost_gendev;
1257 : 0 : dev_set_name(&fnode_sess->dev, "flashnode_sess-%u:%u",
1258 : : shost->host_no, index);
1259 : :
1260 : 0 : err = device_register(&fnode_sess->dev);
1261 : 0 : if (err)
1262 : : goto free_fnode_sess;
1263 : :
1264 : 0 : if (dd_size)
1265 : 0 : fnode_sess->dd_data = &fnode_sess[1];
1266 : :
1267 : 0 : return fnode_sess;
1268 : :
1269 : : free_fnode_sess:
1270 : 0 : kfree(fnode_sess);
1271 : 0 : return NULL;
1272 : : }
1273 : : EXPORT_SYMBOL_GPL(iscsi_create_flashnode_sess);
1274 : :
1275 : : /**
1276 : : * iscsi_create_flashnode_conn - Add flashnode conn entry in sysfs
1277 : : * @shost: pointer to host data
1278 : : * @fnode_sess: pointer to the parent flashnode session entry
1279 : : * @transport: pointer to transport data
1280 : : * @dd_size: total size to allocate
1281 : : *
1282 : : * Adds a sysfs entry for the flashnode connection attributes
1283 : : *
1284 : : * Returns:
1285 : : * pointer to allocated flashnode conn on success
1286 : : * %NULL on failure
1287 : : */
1288 : : struct iscsi_bus_flash_conn *
1289 : 0 : iscsi_create_flashnode_conn(struct Scsi_Host *shost,
1290 : : struct iscsi_bus_flash_session *fnode_sess,
1291 : : struct iscsi_transport *transport,
1292 : : int dd_size)
1293 : : {
1294 : : struct iscsi_bus_flash_conn *fnode_conn;
1295 : : int err;
1296 : :
1297 : 0 : fnode_conn = kzalloc(sizeof(*fnode_conn) + dd_size, GFP_KERNEL);
1298 : 0 : if (!fnode_conn)
1299 : : return NULL;
1300 : :
1301 : 0 : fnode_conn->transport = transport;
1302 : 0 : fnode_conn->dev.type = &iscsi_flashnode_conn_dev_type;
1303 : 0 : fnode_conn->dev.bus = &iscsi_flashnode_bus;
1304 : 0 : fnode_conn->dev.parent = &fnode_sess->dev;
1305 : 0 : dev_set_name(&fnode_conn->dev, "flashnode_conn-%u:%u:0",
1306 : : shost->host_no, fnode_sess->target_id);
1307 : :
1308 : 0 : err = device_register(&fnode_conn->dev);
1309 : 0 : if (err)
1310 : : goto free_fnode_conn;
1311 : :
1312 : 0 : if (dd_size)
1313 : 0 : fnode_conn->dd_data = &fnode_conn[1];
1314 : :
1315 : 0 : return fnode_conn;
1316 : :
1317 : : free_fnode_conn:
1318 : 0 : kfree(fnode_conn);
1319 : 0 : return NULL;
1320 : : }
1321 : : EXPORT_SYMBOL_GPL(iscsi_create_flashnode_conn);
1322 : :
1323 : : /**
1324 : : * iscsi_is_flashnode_conn_dev - verify passed device is to be flashnode conn
1325 : : * @dev: device to verify
1326 : : * @data: pointer to data containing value to use for verification
1327 : : *
1328 : : * Verifies if the passed device is flashnode conn device
1329 : : *
1330 : : * Returns:
1331 : : * 1 on success
1332 : : * 0 on failure
1333 : : */
1334 : 0 : static int iscsi_is_flashnode_conn_dev(struct device *dev, void *data)
1335 : : {
1336 : 0 : return dev->bus == &iscsi_flashnode_bus;
1337 : : }
1338 : :
1339 : : static int iscsi_destroy_flashnode_conn(struct iscsi_bus_flash_conn *fnode_conn)
1340 : : {
1341 : 0 : device_unregister(&fnode_conn->dev);
1342 : : return 0;
1343 : : }
1344 : :
1345 : 0 : static int flashnode_match_index(struct device *dev, void *data)
1346 : : {
1347 : : struct iscsi_bus_flash_session *fnode_sess = NULL;
1348 : : int ret = 0;
1349 : :
1350 : 0 : if (!iscsi_flashnode_bus_match(dev, NULL))
1351 : : goto exit_match_index;
1352 : :
1353 : : fnode_sess = iscsi_dev_to_flash_session(dev);
1354 : 0 : ret = (fnode_sess->target_id == *((int *)data)) ? 1 : 0;
1355 : :
1356 : : exit_match_index:
1357 : 0 : return ret;
1358 : : }
1359 : :
1360 : : /**
1361 : : * iscsi_get_flashnode_by_index -finds flashnode session entry by index
1362 : : * @shost: pointer to host data
1363 : : * @idx: index to match
1364 : : *
1365 : : * Finds the flashnode session object for the passed index
1366 : : *
1367 : : * Returns:
1368 : : * pointer to found flashnode session object on success
1369 : : * %NULL on failure
1370 : : */
1371 : : static struct iscsi_bus_flash_session *
1372 : : iscsi_get_flashnode_by_index(struct Scsi_Host *shost, uint32_t idx)
1373 : : {
1374 : : struct iscsi_bus_flash_session *fnode_sess = NULL;
1375 : : struct device *dev;
1376 : :
1377 : 0 : dev = device_find_child(&shost->shost_gendev, &idx,
1378 : : flashnode_match_index);
1379 : 0 : if (dev)
1380 : 0 : fnode_sess = iscsi_dev_to_flash_session(dev);
1381 : :
1382 : : return fnode_sess;
1383 : : }
1384 : :
1385 : : /**
1386 : : * iscsi_find_flashnode_sess - finds flashnode session entry
1387 : : * @shost: pointer to host data
1388 : : * @data: pointer to data containing value to use for comparison
1389 : : * @fn: function pointer that does actual comparison
1390 : : *
1391 : : * Finds the flashnode session object comparing the data passed using logic
1392 : : * defined in passed function pointer
1393 : : *
1394 : : * Returns:
1395 : : * pointer to found flashnode session device object on success
1396 : : * %NULL on failure
1397 : : */
1398 : : struct device *
1399 : 0 : iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
1400 : : int (*fn)(struct device *dev, void *data))
1401 : : {
1402 : 0 : return device_find_child(&shost->shost_gendev, data, fn);
1403 : : }
1404 : : EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
1405 : :
1406 : : /**
1407 : : * iscsi_find_flashnode_conn - finds flashnode connection entry
1408 : : * @fnode_sess: pointer to parent flashnode session entry
1409 : : *
1410 : : * Finds the flashnode connection object comparing the data passed using logic
1411 : : * defined in passed function pointer
1412 : : *
1413 : : * Returns:
1414 : : * pointer to found flashnode connection device object on success
1415 : : * %NULL on failure
1416 : : */
1417 : : struct device *
1418 : 0 : iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess)
1419 : : {
1420 : 0 : return device_find_child(&fnode_sess->dev, NULL,
1421 : : iscsi_is_flashnode_conn_dev);
1422 : : }
1423 : : EXPORT_SYMBOL_GPL(iscsi_find_flashnode_conn);
1424 : :
1425 : 0 : static int iscsi_iter_destroy_flashnode_conn_fn(struct device *dev, void *data)
1426 : : {
1427 : 0 : if (!iscsi_is_flashnode_conn_dev(dev, NULL))
1428 : : return 0;
1429 : :
1430 : 0 : return iscsi_destroy_flashnode_conn(iscsi_dev_to_flash_conn(dev));
1431 : : }
1432 : :
1433 : : /**
1434 : : * iscsi_destroy_flashnode_sess - destroy flashnode session entry
1435 : : * @fnode_sess: pointer to flashnode session entry to be destroyed
1436 : : *
1437 : : * Deletes the flashnode session entry and all children flashnode connection
1438 : : * entries from sysfs
1439 : : */
1440 : 0 : void iscsi_destroy_flashnode_sess(struct iscsi_bus_flash_session *fnode_sess)
1441 : : {
1442 : : int err;
1443 : :
1444 : 0 : err = device_for_each_child(&fnode_sess->dev, NULL,
1445 : : iscsi_iter_destroy_flashnode_conn_fn);
1446 : 0 : if (err)
1447 : 0 : pr_err("Could not delete all connections for %s. Error %d.\n",
1448 : : fnode_sess->dev.kobj.name, err);
1449 : :
1450 : 0 : device_unregister(&fnode_sess->dev);
1451 : 0 : }
1452 : : EXPORT_SYMBOL_GPL(iscsi_destroy_flashnode_sess);
1453 : :
1454 : 0 : static int iscsi_iter_destroy_flashnode_fn(struct device *dev, void *data)
1455 : : {
1456 : 0 : if (!iscsi_flashnode_bus_match(dev, NULL))
1457 : : return 0;
1458 : :
1459 : 0 : iscsi_destroy_flashnode_sess(iscsi_dev_to_flash_session(dev));
1460 : 0 : return 0;
1461 : : }
1462 : :
1463 : : /**
1464 : : * iscsi_destroy_all_flashnode - destroy all flashnode session entries
1465 : : * @shost: pointer to host data
1466 : : *
1467 : : * Destroys all the flashnode session entries and all corresponding children
1468 : : * flashnode connection entries from sysfs
1469 : : */
1470 : 0 : void iscsi_destroy_all_flashnode(struct Scsi_Host *shost)
1471 : : {
1472 : 0 : device_for_each_child(&shost->shost_gendev, NULL,
1473 : : iscsi_iter_destroy_flashnode_fn);
1474 : 0 : }
1475 : : EXPORT_SYMBOL_GPL(iscsi_destroy_all_flashnode);
1476 : :
1477 : : /*
1478 : : * BSG support
1479 : : */
1480 : : /**
1481 : : * iscsi_bsg_host_dispatch - Dispatch command to LLD.
1482 : : * @job: bsg job to be processed
1483 : : */
1484 : 0 : static int iscsi_bsg_host_dispatch(struct bsg_job *job)
1485 : : {
1486 : 0 : struct Scsi_Host *shost = iscsi_job_to_shost(job);
1487 : 0 : struct iscsi_bsg_request *req = job->request;
1488 : 0 : struct iscsi_bsg_reply *reply = job->reply;
1489 : 0 : struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
1490 : : int cmdlen = sizeof(uint32_t); /* start with length of msgcode */
1491 : : int ret;
1492 : :
1493 : : /* check if we have the msgcode value at least */
1494 : 0 : if (job->request_len < sizeof(uint32_t)) {
1495 : : ret = -ENOMSG;
1496 : : goto fail_host_msg;
1497 : : }
1498 : :
1499 : : /* Validate the host command */
1500 : 0 : switch (req->msgcode) {
1501 : : case ISCSI_BSG_HST_VENDOR:
1502 : : cmdlen += sizeof(struct iscsi_bsg_host_vendor);
1503 : 0 : if ((shost->hostt->vendor_id == 0L) ||
1504 : 0 : (req->rqst_data.h_vendor.vendor_id !=
1505 : : shost->hostt->vendor_id)) {
1506 : : ret = -ESRCH;
1507 : : goto fail_host_msg;
1508 : : }
1509 : : break;
1510 : : default:
1511 : : ret = -EBADR;
1512 : : goto fail_host_msg;
1513 : : }
1514 : :
1515 : : /* check if we really have all the request data needed */
1516 : 0 : if (job->request_len < cmdlen) {
1517 : : ret = -ENOMSG;
1518 : : goto fail_host_msg;
1519 : : }
1520 : :
1521 : 0 : ret = i->iscsi_transport->bsg_request(job);
1522 : 0 : if (!ret)
1523 : : return 0;
1524 : :
1525 : : fail_host_msg:
1526 : : /* return the errno failure code as the only status */
1527 : 0 : BUG_ON(job->reply_len < sizeof(uint32_t));
1528 : 0 : reply->reply_payload_rcv_len = 0;
1529 : 0 : reply->result = ret;
1530 : 0 : job->reply_len = sizeof(uint32_t);
1531 : 0 : bsg_job_done(job, ret, 0);
1532 : 0 : return 0;
1533 : : }
1534 : :
1535 : : /**
1536 : : * iscsi_bsg_host_add - Create and add the bsg hooks to receive requests
1537 : : * @shost: shost for iscsi_host
1538 : : * @ihost: iscsi_cls_host adding the structures to
1539 : : */
1540 : : static int
1541 : 0 : iscsi_bsg_host_add(struct Scsi_Host *shost, struct iscsi_cls_host *ihost)
1542 : : {
1543 : 0 : struct device *dev = &shost->shost_gendev;
1544 : 0 : struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
1545 : : struct request_queue *q;
1546 : : char bsg_name[20];
1547 : :
1548 : 0 : if (!i->iscsi_transport->bsg_request)
1549 : : return -ENOTSUPP;
1550 : :
1551 : 0 : snprintf(bsg_name, sizeof(bsg_name), "iscsi_host%d", shost->host_no);
1552 : 0 : q = bsg_setup_queue(dev, bsg_name, iscsi_bsg_host_dispatch, NULL, 0);
1553 : 0 : if (IS_ERR(q)) {
1554 : 0 : shost_printk(KERN_ERR, shost, "bsg interface failed to "
1555 : : "initialize - no request queue\n");
1556 : 0 : return PTR_ERR(q);
1557 : : }
1558 : 0 : __scsi_init_queue(shost, q);
1559 : :
1560 : 0 : ihost->bsg_q = q;
1561 : 0 : return 0;
1562 : : }
1563 : :
1564 : 0 : static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
1565 : : struct device *cdev)
1566 : : {
1567 : 0 : struct Scsi_Host *shost = dev_to_shost(dev);
1568 : 0 : struct iscsi_cls_host *ihost = shost->shost_data;
1569 : :
1570 : 0 : memset(ihost, 0, sizeof(*ihost));
1571 : : atomic_set(&ihost->nr_scans, 0);
1572 : 0 : mutex_init(&ihost->mutex);
1573 : :
1574 : 0 : iscsi_bsg_host_add(shost, ihost);
1575 : : /* ignore any bsg add error - we just can't do sgio */
1576 : :
1577 : 0 : return 0;
1578 : : }
1579 : :
1580 : 0 : static int iscsi_remove_host(struct transport_container *tc,
1581 : : struct device *dev, struct device *cdev)
1582 : : {
1583 : 0 : struct Scsi_Host *shost = dev_to_shost(dev);
1584 : 0 : struct iscsi_cls_host *ihost = shost->shost_data;
1585 : :
1586 : 0 : bsg_remove_queue(ihost->bsg_q);
1587 : 0 : return 0;
1588 : : }
1589 : :
1590 : : static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
1591 : : "iscsi_host",
1592 : : iscsi_setup_host,
1593 : : iscsi_remove_host,
1594 : : NULL);
1595 : :
1596 : : static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
1597 : : "iscsi_session",
1598 : : NULL,
1599 : : NULL,
1600 : : NULL);
1601 : :
1602 : : static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
1603 : : "iscsi_connection",
1604 : : NULL,
1605 : : NULL,
1606 : : NULL);
1607 : :
1608 : : static struct sock *nls;
1609 : : static DEFINE_MUTEX(rx_queue_mutex);
1610 : :
1611 : : static LIST_HEAD(sesslist);
1612 : : static DEFINE_SPINLOCK(sesslock);
1613 : : static LIST_HEAD(connlist);
1614 : : static DEFINE_SPINLOCK(connlock);
1615 : :
1616 : : static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
1617 : : {
1618 : 0 : struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent);
1619 : 0 : return sess->sid;
1620 : : }
1621 : :
1622 : : /*
1623 : : * Returns the matching session to a given sid
1624 : : */
1625 : 0 : static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid)
1626 : : {
1627 : : unsigned long flags;
1628 : : struct iscsi_cls_session *sess;
1629 : :
1630 : 0 : spin_lock_irqsave(&sesslock, flags);
1631 : 0 : list_for_each_entry(sess, &sesslist, sess_list) {
1632 : 0 : if (sess->sid == sid) {
1633 : : spin_unlock_irqrestore(&sesslock, flags);
1634 : 0 : return sess;
1635 : : }
1636 : : }
1637 : : spin_unlock_irqrestore(&sesslock, flags);
1638 : 0 : return NULL;
1639 : : }
1640 : :
1641 : : /*
1642 : : * Returns the matching connection to a given sid / cid tuple
1643 : : */
1644 : 0 : static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
1645 : : {
1646 : : unsigned long flags;
1647 : : struct iscsi_cls_conn *conn;
1648 : :
1649 : 0 : spin_lock_irqsave(&connlock, flags);
1650 : 0 : list_for_each_entry(conn, &connlist, conn_list) {
1651 : 0 : if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) {
1652 : : spin_unlock_irqrestore(&connlock, flags);
1653 : 0 : return conn;
1654 : : }
1655 : : }
1656 : : spin_unlock_irqrestore(&connlock, flags);
1657 : 0 : return NULL;
1658 : : }
1659 : :
1660 : : /*
1661 : : * The following functions can be used by LLDs that allocate
1662 : : * their own scsi_hosts or by software iscsi LLDs
1663 : : */
1664 : : static struct {
1665 : : int value;
1666 : : char *name;
1667 : : } iscsi_session_state_names[] = {
1668 : : { ISCSI_SESSION_LOGGED_IN, "LOGGED_IN" },
1669 : : { ISCSI_SESSION_FAILED, "FAILED" },
1670 : : { ISCSI_SESSION_FREE, "FREE" },
1671 : : };
1672 : :
1673 : : static const char *iscsi_session_state_name(int state)
1674 : : {
1675 : : int i;
1676 : : char *name = NULL;
1677 : :
1678 : 0 : for (i = 0; i < ARRAY_SIZE(iscsi_session_state_names); i++) {
1679 : 0 : if (iscsi_session_state_names[i].value == state) {
1680 : 0 : name = iscsi_session_state_names[i].name;
1681 : : break;
1682 : : }
1683 : : }
1684 : : return name;
1685 : : }
1686 : :
1687 : 0 : int iscsi_session_chkready(struct iscsi_cls_session *session)
1688 : : {
1689 : : unsigned long flags;
1690 : : int err;
1691 : :
1692 : 0 : spin_lock_irqsave(&session->lock, flags);
1693 : 0 : switch (session->state) {
1694 : : case ISCSI_SESSION_LOGGED_IN:
1695 : : err = 0;
1696 : : break;
1697 : : case ISCSI_SESSION_FAILED:
1698 : : err = DID_IMM_RETRY << 16;
1699 : : break;
1700 : : case ISCSI_SESSION_FREE:
1701 : : err = DID_TRANSPORT_FAILFAST << 16;
1702 : : break;
1703 : : default:
1704 : : err = DID_NO_CONNECT << 16;
1705 : : break;
1706 : : }
1707 : : spin_unlock_irqrestore(&session->lock, flags);
1708 : 0 : return err;
1709 : : }
1710 : : EXPORT_SYMBOL_GPL(iscsi_session_chkready);
1711 : :
1712 : 0 : int iscsi_is_session_online(struct iscsi_cls_session *session)
1713 : : {
1714 : : unsigned long flags;
1715 : : int ret = 0;
1716 : :
1717 : 0 : spin_lock_irqsave(&session->lock, flags);
1718 : 0 : if (session->state == ISCSI_SESSION_LOGGED_IN)
1719 : : ret = 1;
1720 : : spin_unlock_irqrestore(&session->lock, flags);
1721 : 0 : return ret;
1722 : : }
1723 : : EXPORT_SYMBOL_GPL(iscsi_is_session_online);
1724 : :
1725 : 0 : static void iscsi_session_release(struct device *dev)
1726 : : {
1727 : 0 : struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
1728 : : struct Scsi_Host *shost;
1729 : :
1730 : 0 : shost = iscsi_session_to_shost(session);
1731 : 0 : scsi_host_put(shost);
1732 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Completing session release\n");
1733 : 0 : kfree(session);
1734 : 0 : }
1735 : :
1736 : 0 : int iscsi_is_session_dev(const struct device *dev)
1737 : : {
1738 : 0 : return dev->release == iscsi_session_release;
1739 : : }
1740 : : EXPORT_SYMBOL_GPL(iscsi_is_session_dev);
1741 : :
1742 : 0 : static int iscsi_iter_session_fn(struct device *dev, void *data)
1743 : : {
1744 : 0 : void (* fn) (struct iscsi_cls_session *) = data;
1745 : :
1746 : 0 : if (!iscsi_is_session_dev(dev))
1747 : : return 0;
1748 : 0 : fn(iscsi_dev_to_session(dev));
1749 : 0 : return 0;
1750 : : }
1751 : :
1752 : 0 : void iscsi_host_for_each_session(struct Scsi_Host *shost,
1753 : : void (*fn)(struct iscsi_cls_session *))
1754 : : {
1755 : 0 : device_for_each_child(&shost->shost_gendev, fn,
1756 : : iscsi_iter_session_fn);
1757 : 0 : }
1758 : : EXPORT_SYMBOL_GPL(iscsi_host_for_each_session);
1759 : :
1760 : : /**
1761 : : * iscsi_scan_finished - helper to report when running scans are done
1762 : : * @shost: scsi host
1763 : : * @time: scan run time
1764 : : *
1765 : : * This function can be used by drives like qla4xxx to report to the scsi
1766 : : * layer when the scans it kicked off at module load time are done.
1767 : : */
1768 : 0 : int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time)
1769 : : {
1770 : 0 : struct iscsi_cls_host *ihost = shost->shost_data;
1771 : : /*
1772 : : * qla4xxx will have kicked off some session unblocks before calling
1773 : : * scsi_scan_host, so just wait for them to complete.
1774 : : */
1775 : 0 : return !atomic_read(&ihost->nr_scans);
1776 : : }
1777 : : EXPORT_SYMBOL_GPL(iscsi_scan_finished);
1778 : :
1779 : : struct iscsi_scan_data {
1780 : : unsigned int channel;
1781 : : unsigned int id;
1782 : : u64 lun;
1783 : : enum scsi_scan_mode rescan;
1784 : : };
1785 : :
1786 : 0 : static int iscsi_user_scan_session(struct device *dev, void *data)
1787 : : {
1788 : : struct iscsi_scan_data *scan_data = data;
1789 : : struct iscsi_cls_session *session;
1790 : : struct Scsi_Host *shost;
1791 : : struct iscsi_cls_host *ihost;
1792 : : unsigned long flags;
1793 : : unsigned int id;
1794 : :
1795 : 0 : if (!iscsi_is_session_dev(dev))
1796 : : return 0;
1797 : :
1798 : : session = iscsi_dev_to_session(dev);
1799 : :
1800 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Scanning session\n");
1801 : :
1802 : 0 : shost = iscsi_session_to_shost(session);
1803 : 0 : ihost = shost->shost_data;
1804 : :
1805 : 0 : mutex_lock(&ihost->mutex);
1806 : 0 : spin_lock_irqsave(&session->lock, flags);
1807 : 0 : if (session->state != ISCSI_SESSION_LOGGED_IN) {
1808 : : spin_unlock_irqrestore(&session->lock, flags);
1809 : : goto user_scan_exit;
1810 : : }
1811 : 0 : id = session->target_id;
1812 : : spin_unlock_irqrestore(&session->lock, flags);
1813 : :
1814 : 0 : if (id != ISCSI_MAX_TARGET) {
1815 : 0 : if ((scan_data->channel == SCAN_WILD_CARD ||
1816 : 0 : scan_data->channel == 0) &&
1817 : 0 : (scan_data->id == SCAN_WILD_CARD ||
1818 : : scan_data->id == id))
1819 : 0 : scsi_scan_target(&session->dev, 0, id,
1820 : : scan_data->lun, scan_data->rescan);
1821 : : }
1822 : :
1823 : : user_scan_exit:
1824 : 0 : mutex_unlock(&ihost->mutex);
1825 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Completed session scan\n");
1826 : 0 : return 0;
1827 : : }
1828 : :
1829 : 0 : static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
1830 : : uint id, u64 lun)
1831 : : {
1832 : : struct iscsi_scan_data scan_data;
1833 : :
1834 : 0 : scan_data.channel = channel;
1835 : 0 : scan_data.id = id;
1836 : 0 : scan_data.lun = lun;
1837 : 0 : scan_data.rescan = SCSI_SCAN_MANUAL;
1838 : :
1839 : 0 : return device_for_each_child(&shost->shost_gendev, &scan_data,
1840 : : iscsi_user_scan_session);
1841 : : }
1842 : :
1843 : 0 : static void iscsi_scan_session(struct work_struct *work)
1844 : : {
1845 : : struct iscsi_cls_session *session =
1846 : : container_of(work, struct iscsi_cls_session, scan_work);
1847 : 0 : struct Scsi_Host *shost = iscsi_session_to_shost(session);
1848 : 0 : struct iscsi_cls_host *ihost = shost->shost_data;
1849 : : struct iscsi_scan_data scan_data;
1850 : :
1851 : 0 : scan_data.channel = 0;
1852 : 0 : scan_data.id = SCAN_WILD_CARD;
1853 : 0 : scan_data.lun = SCAN_WILD_CARD;
1854 : 0 : scan_data.rescan = SCSI_SCAN_RESCAN;
1855 : :
1856 : 0 : iscsi_user_scan_session(&session->dev, &scan_data);
1857 : 0 : atomic_dec(&ihost->nr_scans);
1858 : 0 : }
1859 : :
1860 : : /**
1861 : : * iscsi_block_scsi_eh - block scsi eh until session state has transistioned
1862 : : * @cmd: scsi cmd passed to scsi eh handler
1863 : : *
1864 : : * If the session is down this function will wait for the recovery
1865 : : * timer to fire or for the session to be logged back in. If the
1866 : : * recovery timer fires then FAST_IO_FAIL is returned. The caller
1867 : : * should pass this error value to the scsi eh.
1868 : : */
1869 : 0 : int iscsi_block_scsi_eh(struct scsi_cmnd *cmd)
1870 : : {
1871 : : struct iscsi_cls_session *session =
1872 : 0 : starget_to_session(scsi_target(cmd->device));
1873 : : unsigned long flags;
1874 : : int ret = 0;
1875 : :
1876 : 0 : spin_lock_irqsave(&session->lock, flags);
1877 : 0 : while (session->state != ISCSI_SESSION_LOGGED_IN) {
1878 : 0 : if (session->state == ISCSI_SESSION_FREE) {
1879 : : ret = FAST_IO_FAIL;
1880 : : break;
1881 : : }
1882 : : spin_unlock_irqrestore(&session->lock, flags);
1883 : 0 : msleep(1000);
1884 : 0 : spin_lock_irqsave(&session->lock, flags);
1885 : : }
1886 : : spin_unlock_irqrestore(&session->lock, flags);
1887 : 0 : return ret;
1888 : : }
1889 : : EXPORT_SYMBOL_GPL(iscsi_block_scsi_eh);
1890 : :
1891 : 0 : static void session_recovery_timedout(struct work_struct *work)
1892 : : {
1893 : : struct iscsi_cls_session *session =
1894 : 0 : container_of(work, struct iscsi_cls_session,
1895 : : recovery_work.work);
1896 : : unsigned long flags;
1897 : :
1898 : 0 : iscsi_cls_session_printk(KERN_INFO, session,
1899 : : "session recovery timed out after %d secs\n",
1900 : : session->recovery_tmo);
1901 : :
1902 : 0 : spin_lock_irqsave(&session->lock, flags);
1903 : 0 : switch (session->state) {
1904 : : case ISCSI_SESSION_FAILED:
1905 : 0 : session->state = ISCSI_SESSION_FREE;
1906 : 0 : break;
1907 : : case ISCSI_SESSION_LOGGED_IN:
1908 : : case ISCSI_SESSION_FREE:
1909 : : /* we raced with the unblock's flush */
1910 : : spin_unlock_irqrestore(&session->lock, flags);
1911 : 0 : return;
1912 : : }
1913 : : spin_unlock_irqrestore(&session->lock, flags);
1914 : :
1915 : 0 : if (session->transport->session_recovery_timedout)
1916 : 0 : session->transport->session_recovery_timedout(session);
1917 : :
1918 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n");
1919 : 0 : scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
1920 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n");
1921 : : }
1922 : :
1923 : 0 : static void __iscsi_unblock_session(struct work_struct *work)
1924 : : {
1925 : : struct iscsi_cls_session *session =
1926 : : container_of(work, struct iscsi_cls_session,
1927 : : unblock_work);
1928 : 0 : struct Scsi_Host *shost = iscsi_session_to_shost(session);
1929 : 0 : struct iscsi_cls_host *ihost = shost->shost_data;
1930 : : unsigned long flags;
1931 : :
1932 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Unblocking session\n");
1933 : : /*
1934 : : * The recovery and unblock work get run from the same workqueue,
1935 : : * so try to cancel it if it was going to run after this unblock.
1936 : : */
1937 : 0 : cancel_delayed_work(&session->recovery_work);
1938 : 0 : spin_lock_irqsave(&session->lock, flags);
1939 : 0 : session->state = ISCSI_SESSION_LOGGED_IN;
1940 : : spin_unlock_irqrestore(&session->lock, flags);
1941 : : /* start IO */
1942 : 0 : scsi_target_unblock(&session->dev, SDEV_RUNNING);
1943 : : /*
1944 : : * Only do kernel scanning if the driver is properly hooked into
1945 : : * the async scanning code (drivers like iscsi_tcp do login and
1946 : : * scanning from userspace).
1947 : : */
1948 : 0 : if (shost->hostt->scan_finished) {
1949 : 0 : if (scsi_queue_work(shost, &session->scan_work))
1950 : 0 : atomic_inc(&ihost->nr_scans);
1951 : : }
1952 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking session\n");
1953 : 0 : }
1954 : :
1955 : : /**
1956 : : * iscsi_unblock_session - set a session as logged in and start IO.
1957 : : * @session: iscsi session
1958 : : *
1959 : : * Mark a session as ready to accept IO.
1960 : : */
1961 : 0 : void iscsi_unblock_session(struct iscsi_cls_session *session)
1962 : : {
1963 : 0 : queue_work(iscsi_eh_timer_workq, &session->unblock_work);
1964 : : /*
1965 : : * make sure all the events have completed before tell the driver
1966 : : * it is safe
1967 : : */
1968 : 0 : flush_workqueue(iscsi_eh_timer_workq);
1969 : 0 : }
1970 : : EXPORT_SYMBOL_GPL(iscsi_unblock_session);
1971 : :
1972 : 0 : static void __iscsi_block_session(struct work_struct *work)
1973 : : {
1974 : : struct iscsi_cls_session *session =
1975 : : container_of(work, struct iscsi_cls_session,
1976 : : block_work);
1977 : : unsigned long flags;
1978 : :
1979 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Blocking session\n");
1980 : 0 : spin_lock_irqsave(&session->lock, flags);
1981 : 0 : session->state = ISCSI_SESSION_FAILED;
1982 : : spin_unlock_irqrestore(&session->lock, flags);
1983 : 0 : scsi_target_block(&session->dev);
1984 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking\n");
1985 : 0 : if (session->recovery_tmo >= 0)
1986 : 0 : queue_delayed_work(iscsi_eh_timer_workq,
1987 : : &session->recovery_work,
1988 : 0 : session->recovery_tmo * HZ);
1989 : 0 : }
1990 : :
1991 : 0 : void iscsi_block_session(struct iscsi_cls_session *session)
1992 : : {
1993 : 0 : queue_work(iscsi_eh_timer_workq, &session->block_work);
1994 : 0 : }
1995 : : EXPORT_SYMBOL_GPL(iscsi_block_session);
1996 : :
1997 : 0 : static void __iscsi_unbind_session(struct work_struct *work)
1998 : : {
1999 : : struct iscsi_cls_session *session =
2000 : 0 : container_of(work, struct iscsi_cls_session,
2001 : : unbind_work);
2002 : 0 : struct Scsi_Host *shost = iscsi_session_to_shost(session);
2003 : 0 : struct iscsi_cls_host *ihost = shost->shost_data;
2004 : : unsigned long flags;
2005 : : unsigned int target_id;
2006 : :
2007 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n");
2008 : :
2009 : : /* Prevent new scans and make sure scanning is not in progress */
2010 : 0 : mutex_lock(&ihost->mutex);
2011 : 0 : spin_lock_irqsave(&session->lock, flags);
2012 : 0 : if (session->target_id == ISCSI_MAX_TARGET) {
2013 : : spin_unlock_irqrestore(&session->lock, flags);
2014 : 0 : mutex_unlock(&ihost->mutex);
2015 : 0 : goto unbind_session_exit;
2016 : : }
2017 : :
2018 : : target_id = session->target_id;
2019 : 0 : session->target_id = ISCSI_MAX_TARGET;
2020 : : spin_unlock_irqrestore(&session->lock, flags);
2021 : 0 : mutex_unlock(&ihost->mutex);
2022 : :
2023 : 0 : if (session->ida_used)
2024 : 0 : ida_simple_remove(&iscsi_sess_ida, target_id);
2025 : :
2026 : 0 : scsi_remove_target(&session->dev);
2027 : :
2028 : : unbind_session_exit:
2029 : 0 : iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
2030 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
2031 : 0 : }
2032 : :
2033 : : struct iscsi_cls_session *
2034 : 0 : iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
2035 : : int dd_size)
2036 : : {
2037 : : struct iscsi_cls_session *session;
2038 : :
2039 : 0 : session = kzalloc(sizeof(*session) + dd_size,
2040 : : GFP_KERNEL);
2041 : 0 : if (!session)
2042 : : return NULL;
2043 : :
2044 : 0 : session->transport = transport;
2045 : 0 : session->creator = -1;
2046 : 0 : session->recovery_tmo = 120;
2047 : 0 : session->recovery_tmo_sysfs_override = false;
2048 : 0 : session->state = ISCSI_SESSION_FREE;
2049 : 0 : INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
2050 : 0 : INIT_LIST_HEAD(&session->sess_list);
2051 : 0 : INIT_WORK(&session->unblock_work, __iscsi_unblock_session);
2052 : 0 : INIT_WORK(&session->block_work, __iscsi_block_session);
2053 : 0 : INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
2054 : 0 : INIT_WORK(&session->scan_work, iscsi_scan_session);
2055 : 0 : spin_lock_init(&session->lock);
2056 : :
2057 : : /* this is released in the dev's release function */
2058 : 0 : scsi_host_get(shost);
2059 : 0 : session->dev.parent = &shost->shost_gendev;
2060 : 0 : session->dev.release = iscsi_session_release;
2061 : 0 : device_initialize(&session->dev);
2062 : 0 : if (dd_size)
2063 : 0 : session->dd_data = &session[1];
2064 : :
2065 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Completed session allocation\n");
2066 : 0 : return session;
2067 : : }
2068 : : EXPORT_SYMBOL_GPL(iscsi_alloc_session);
2069 : :
2070 : 0 : int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
2071 : : {
2072 : : unsigned long flags;
2073 : : int id = 0;
2074 : : int err;
2075 : :
2076 : 0 : session->sid = atomic_add_return(1, &iscsi_session_nr);
2077 : :
2078 : 0 : if (target_id == ISCSI_MAX_TARGET) {
2079 : 0 : id = ida_simple_get(&iscsi_sess_ida, 0, 0, GFP_KERNEL);
2080 : :
2081 : 0 : if (id < 0) {
2082 : 0 : iscsi_cls_session_printk(KERN_ERR, session,
2083 : : "Failure in Target ID Allocation\n");
2084 : 0 : return id;
2085 : : }
2086 : 0 : session->target_id = (unsigned int)id;
2087 : 0 : session->ida_used = true;
2088 : : } else
2089 : 0 : session->target_id = target_id;
2090 : :
2091 : 0 : dev_set_name(&session->dev, "session%u", session->sid);
2092 : 0 : err = device_add(&session->dev);
2093 : 0 : if (err) {
2094 : 0 : iscsi_cls_session_printk(KERN_ERR, session,
2095 : : "could not register session's dev\n");
2096 : : goto release_ida;
2097 : : }
2098 : : transport_register_device(&session->dev);
2099 : :
2100 : 0 : spin_lock_irqsave(&sesslock, flags);
2101 : 0 : list_add(&session->sess_list, &sesslist);
2102 : : spin_unlock_irqrestore(&sesslock, flags);
2103 : :
2104 : 0 : iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION);
2105 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
2106 : 0 : return 0;
2107 : :
2108 : : release_ida:
2109 : 0 : if (session->ida_used)
2110 : 0 : ida_simple_remove(&iscsi_sess_ida, session->target_id);
2111 : :
2112 : 0 : return err;
2113 : : }
2114 : : EXPORT_SYMBOL_GPL(iscsi_add_session);
2115 : :
2116 : : /**
2117 : : * iscsi_create_session - create iscsi class session
2118 : : * @shost: scsi host
2119 : : * @transport: iscsi transport
2120 : : * @dd_size: private driver data size
2121 : : * @target_id: which target
2122 : : *
2123 : : * This can be called from a LLD or iscsi_transport.
2124 : : */
2125 : : struct iscsi_cls_session *
2126 : 0 : iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
2127 : : int dd_size, unsigned int target_id)
2128 : : {
2129 : : struct iscsi_cls_session *session;
2130 : :
2131 : 0 : session = iscsi_alloc_session(shost, transport, dd_size);
2132 : 0 : if (!session)
2133 : : return NULL;
2134 : :
2135 : 0 : if (iscsi_add_session(session, target_id)) {
2136 : 0 : iscsi_free_session(session);
2137 : 0 : return NULL;
2138 : : }
2139 : : return session;
2140 : : }
2141 : : EXPORT_SYMBOL_GPL(iscsi_create_session);
2142 : :
2143 : 0 : static void iscsi_conn_release(struct device *dev)
2144 : : {
2145 : 0 : struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
2146 : 0 : struct device *parent = conn->dev.parent;
2147 : :
2148 : 0 : ISCSI_DBG_TRANS_CONN(conn, "Releasing conn\n");
2149 : 0 : kfree(conn);
2150 : 0 : put_device(parent);
2151 : 0 : }
2152 : :
2153 : : static int iscsi_is_conn_dev(const struct device *dev)
2154 : : {
2155 : 0 : return dev->release == iscsi_conn_release;
2156 : : }
2157 : :
2158 : 0 : static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)
2159 : : {
2160 : 0 : if (!iscsi_is_conn_dev(dev))
2161 : : return 0;
2162 : 0 : return iscsi_destroy_conn(iscsi_dev_to_conn(dev));
2163 : : }
2164 : :
2165 : 0 : void iscsi_remove_session(struct iscsi_cls_session *session)
2166 : : {
2167 : : unsigned long flags;
2168 : : int err;
2169 : :
2170 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Removing session\n");
2171 : :
2172 : 0 : spin_lock_irqsave(&sesslock, flags);
2173 : : list_del(&session->sess_list);
2174 : : spin_unlock_irqrestore(&sesslock, flags);
2175 : :
2176 : : /* make sure there are no blocks/unblocks queued */
2177 : 0 : flush_workqueue(iscsi_eh_timer_workq);
2178 : : /* make sure the timedout callout is not running */
2179 : 0 : if (!cancel_delayed_work(&session->recovery_work))
2180 : 0 : flush_workqueue(iscsi_eh_timer_workq);
2181 : : /*
2182 : : * If we are blocked let commands flow again. The lld or iscsi
2183 : : * layer should set up the queuecommand to fail commands.
2184 : : * We assume that LLD will not be calling block/unblock while
2185 : : * removing the session.
2186 : : */
2187 : 0 : spin_lock_irqsave(&session->lock, flags);
2188 : 0 : session->state = ISCSI_SESSION_FREE;
2189 : : spin_unlock_irqrestore(&session->lock, flags);
2190 : :
2191 : 0 : scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
2192 : : /* flush running scans then delete devices */
2193 : 0 : flush_work(&session->scan_work);
2194 : : /* flush running unbind operations */
2195 : 0 : flush_work(&session->unbind_work);
2196 : 0 : __iscsi_unbind_session(&session->unbind_work);
2197 : :
2198 : : /* hw iscsi may not have removed all connections from session */
2199 : 0 : err = device_for_each_child(&session->dev, NULL,
2200 : : iscsi_iter_destroy_conn_fn);
2201 : 0 : if (err)
2202 : 0 : iscsi_cls_session_printk(KERN_ERR, session,
2203 : : "Could not delete all connections "
2204 : : "for session. Error %d.\n", err);
2205 : :
2206 : : transport_unregister_device(&session->dev);
2207 : :
2208 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Completing session removal\n");
2209 : 0 : device_del(&session->dev);
2210 : 0 : }
2211 : : EXPORT_SYMBOL_GPL(iscsi_remove_session);
2212 : :
2213 : 0 : void iscsi_free_session(struct iscsi_cls_session *session)
2214 : : {
2215 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Freeing session\n");
2216 : 0 : iscsi_session_event(session, ISCSI_KEVENT_DESTROY_SESSION);
2217 : 0 : put_device(&session->dev);
2218 : 0 : }
2219 : : EXPORT_SYMBOL_GPL(iscsi_free_session);
2220 : :
2221 : : /**
2222 : : * iscsi_create_conn - create iscsi class connection
2223 : : * @session: iscsi cls session
2224 : : * @dd_size: private driver data size
2225 : : * @cid: connection id
2226 : : *
2227 : : * This can be called from a LLD or iscsi_transport. The connection
2228 : : * is child of the session so cid must be unique for all connections
2229 : : * on the session.
2230 : : *
2231 : : * Since we do not support MCS, cid will normally be zero. In some cases
2232 : : * for software iscsi we could be trying to preallocate a connection struct
2233 : : * in which case there could be two connection structs and cid would be
2234 : : * non-zero.
2235 : : */
2236 : : struct iscsi_cls_conn *
2237 : 0 : iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
2238 : : {
2239 : 0 : struct iscsi_transport *transport = session->transport;
2240 : : struct iscsi_cls_conn *conn;
2241 : : unsigned long flags;
2242 : : int err;
2243 : :
2244 : 0 : conn = kzalloc(sizeof(*conn) + dd_size, GFP_KERNEL);
2245 : 0 : if (!conn)
2246 : : return NULL;
2247 : 0 : if (dd_size)
2248 : 0 : conn->dd_data = &conn[1];
2249 : :
2250 : 0 : mutex_init(&conn->ep_mutex);
2251 : 0 : INIT_LIST_HEAD(&conn->conn_list);
2252 : 0 : conn->transport = transport;
2253 : 0 : conn->cid = cid;
2254 : :
2255 : : /* this is released in the dev's release function */
2256 : 0 : if (!get_device(&session->dev))
2257 : : goto free_conn;
2258 : :
2259 : 0 : dev_set_name(&conn->dev, "connection%d:%u", session->sid, cid);
2260 : 0 : conn->dev.parent = &session->dev;
2261 : 0 : conn->dev.release = iscsi_conn_release;
2262 : 0 : err = device_register(&conn->dev);
2263 : 0 : if (err) {
2264 : 0 : iscsi_cls_session_printk(KERN_ERR, session, "could not "
2265 : : "register connection's dev\n");
2266 : : goto release_parent_ref;
2267 : : }
2268 : : transport_register_device(&conn->dev);
2269 : :
2270 : 0 : spin_lock_irqsave(&connlock, flags);
2271 : : list_add(&conn->conn_list, &connlist);
2272 : : spin_unlock_irqrestore(&connlock, flags);
2273 : :
2274 : 0 : ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n");
2275 : 0 : return conn;
2276 : :
2277 : : release_parent_ref:
2278 : 0 : put_device(&session->dev);
2279 : : free_conn:
2280 : 0 : kfree(conn);
2281 : 0 : return NULL;
2282 : : }
2283 : :
2284 : : EXPORT_SYMBOL_GPL(iscsi_create_conn);
2285 : :
2286 : : /**
2287 : : * iscsi_destroy_conn - destroy iscsi class connection
2288 : : * @conn: iscsi cls session
2289 : : *
2290 : : * This can be called from a LLD or iscsi_transport.
2291 : : */
2292 : 0 : int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
2293 : : {
2294 : : unsigned long flags;
2295 : :
2296 : 0 : spin_lock_irqsave(&connlock, flags);
2297 : : list_del(&conn->conn_list);
2298 : : spin_unlock_irqrestore(&connlock, flags);
2299 : :
2300 : 0 : transport_unregister_device(&conn->dev);
2301 : 0 : ISCSI_DBG_TRANS_CONN(conn, "Completing conn destruction\n");
2302 : 0 : device_unregister(&conn->dev);
2303 : 0 : return 0;
2304 : : }
2305 : : EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
2306 : :
2307 : : /*
2308 : : * iscsi interface functions
2309 : : */
2310 : : static struct iscsi_internal *
2311 : 0 : iscsi_if_transport_lookup(struct iscsi_transport *tt)
2312 : : {
2313 : : struct iscsi_internal *priv;
2314 : : unsigned long flags;
2315 : :
2316 : 0 : spin_lock_irqsave(&iscsi_transport_lock, flags);
2317 : 0 : list_for_each_entry(priv, &iscsi_transports, list) {
2318 : 0 : if (tt == priv->iscsi_transport) {
2319 : : spin_unlock_irqrestore(&iscsi_transport_lock, flags);
2320 : 0 : return priv;
2321 : : }
2322 : : }
2323 : : spin_unlock_irqrestore(&iscsi_transport_lock, flags);
2324 : 0 : return NULL;
2325 : : }
2326 : :
2327 : : static int
2328 : 0 : iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp)
2329 : : {
2330 : 0 : return nlmsg_multicast(nls, skb, 0, group, gfp);
2331 : : }
2332 : :
2333 : : static int
2334 : : iscsi_unicast_skb(struct sk_buff *skb, u32 portid)
2335 : : {
2336 : 0 : return nlmsg_unicast(nls, skb, portid);
2337 : : }
2338 : :
2339 : 0 : int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
2340 : : char *data, uint32_t data_size)
2341 : : {
2342 : : struct nlmsghdr *nlh;
2343 : : struct sk_buff *skb;
2344 : : struct iscsi_uevent *ev;
2345 : : char *pdu;
2346 : : struct iscsi_internal *priv;
2347 : 0 : int len = nlmsg_total_size(sizeof(*ev) + sizeof(struct iscsi_hdr) +
2348 : : data_size);
2349 : :
2350 : 0 : priv = iscsi_if_transport_lookup(conn->transport);
2351 : 0 : if (!priv)
2352 : : return -EINVAL;
2353 : :
2354 : 0 : skb = alloc_skb(len, GFP_ATOMIC);
2355 : 0 : if (!skb) {
2356 : 0 : iscsi_conn_error_event(conn, ISCSI_ERR_CONN_FAILED);
2357 : 0 : iscsi_cls_conn_printk(KERN_ERR, conn, "can not deliver "
2358 : : "control PDU: OOM\n");
2359 : 0 : return -ENOMEM;
2360 : : }
2361 : :
2362 : 0 : nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2363 : : ev = nlmsg_data(nlh);
2364 : 0 : memset(ev, 0, sizeof(*ev));
2365 : 0 : ev->transport_handle = iscsi_handle(conn->transport);
2366 : 0 : ev->type = ISCSI_KEVENT_RECV_PDU;
2367 : 0 : ev->r.recv_req.cid = conn->cid;
2368 : 0 : ev->r.recv_req.sid = iscsi_conn_get_sid(conn);
2369 : 0 : pdu = (char*)ev + sizeof(*ev);
2370 : 0 : memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
2371 : 0 : memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
2372 : :
2373 : 0 : return iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
2374 : : }
2375 : : EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
2376 : :
2377 : 0 : int iscsi_offload_mesg(struct Scsi_Host *shost,
2378 : : struct iscsi_transport *transport, uint32_t type,
2379 : : char *data, uint16_t data_size)
2380 : : {
2381 : : struct nlmsghdr *nlh;
2382 : : struct sk_buff *skb;
2383 : : struct iscsi_uevent *ev;
2384 : 0 : int len = nlmsg_total_size(sizeof(*ev) + data_size);
2385 : :
2386 : 0 : skb = alloc_skb(len, GFP_ATOMIC);
2387 : 0 : if (!skb) {
2388 : 0 : printk(KERN_ERR "can not deliver iscsi offload message:OOM\n");
2389 : 0 : return -ENOMEM;
2390 : : }
2391 : :
2392 : 0 : nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2393 : : ev = nlmsg_data(nlh);
2394 : 0 : memset(ev, 0, sizeof(*ev));
2395 : 0 : ev->type = type;
2396 : 0 : ev->transport_handle = iscsi_handle(transport);
2397 : 0 : switch (type) {
2398 : : case ISCSI_KEVENT_PATH_REQ:
2399 : 0 : ev->r.req_path.host_no = shost->host_no;
2400 : 0 : break;
2401 : : case ISCSI_KEVENT_IF_DOWN:
2402 : 0 : ev->r.notify_if_down.host_no = shost->host_no;
2403 : 0 : break;
2404 : : }
2405 : :
2406 : 0 : memcpy((char *)ev + sizeof(*ev), data, data_size);
2407 : :
2408 : 0 : return iscsi_multicast_skb(skb, ISCSI_NL_GRP_UIP, GFP_ATOMIC);
2409 : : }
2410 : : EXPORT_SYMBOL_GPL(iscsi_offload_mesg);
2411 : :
2412 : 0 : void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
2413 : : {
2414 : : struct nlmsghdr *nlh;
2415 : : struct sk_buff *skb;
2416 : : struct iscsi_uevent *ev;
2417 : : struct iscsi_internal *priv;
2418 : : int len = nlmsg_total_size(sizeof(*ev));
2419 : :
2420 : 0 : priv = iscsi_if_transport_lookup(conn->transport);
2421 : 0 : if (!priv)
2422 : : return;
2423 : :
2424 : : skb = alloc_skb(len, GFP_ATOMIC);
2425 : 0 : if (!skb) {
2426 : 0 : iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
2427 : : "conn error (%d)\n", error);
2428 : 0 : return;
2429 : : }
2430 : :
2431 : 0 : nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2432 : : ev = nlmsg_data(nlh);
2433 : 0 : ev->transport_handle = iscsi_handle(conn->transport);
2434 : 0 : ev->type = ISCSI_KEVENT_CONN_ERROR;
2435 : 0 : ev->r.connerror.error = error;
2436 : 0 : ev->r.connerror.cid = conn->cid;
2437 : 0 : ev->r.connerror.sid = iscsi_conn_get_sid(conn);
2438 : :
2439 : 0 : iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
2440 : :
2441 : 0 : iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)\n",
2442 : : error);
2443 : : }
2444 : : EXPORT_SYMBOL_GPL(iscsi_conn_error_event);
2445 : :
2446 : 0 : void iscsi_conn_login_event(struct iscsi_cls_conn *conn,
2447 : : enum iscsi_conn_state state)
2448 : : {
2449 : : struct nlmsghdr *nlh;
2450 : : struct sk_buff *skb;
2451 : : struct iscsi_uevent *ev;
2452 : : struct iscsi_internal *priv;
2453 : : int len = nlmsg_total_size(sizeof(*ev));
2454 : :
2455 : 0 : priv = iscsi_if_transport_lookup(conn->transport);
2456 : 0 : if (!priv)
2457 : : return;
2458 : :
2459 : : skb = alloc_skb(len, GFP_ATOMIC);
2460 : 0 : if (!skb) {
2461 : 0 : iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
2462 : : "conn login (%d)\n", state);
2463 : 0 : return;
2464 : : }
2465 : :
2466 : 0 : nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2467 : : ev = nlmsg_data(nlh);
2468 : 0 : ev->transport_handle = iscsi_handle(conn->transport);
2469 : 0 : ev->type = ISCSI_KEVENT_CONN_LOGIN_STATE;
2470 : 0 : ev->r.conn_login.state = state;
2471 : 0 : ev->r.conn_login.cid = conn->cid;
2472 : 0 : ev->r.conn_login.sid = iscsi_conn_get_sid(conn);
2473 : 0 : iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
2474 : :
2475 : 0 : iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn login (%d)\n",
2476 : : state);
2477 : : }
2478 : : EXPORT_SYMBOL_GPL(iscsi_conn_login_event);
2479 : :
2480 : 0 : void iscsi_post_host_event(uint32_t host_no, struct iscsi_transport *transport,
2481 : : enum iscsi_host_event_code code, uint32_t data_size,
2482 : : uint8_t *data)
2483 : : {
2484 : : struct nlmsghdr *nlh;
2485 : : struct sk_buff *skb;
2486 : : struct iscsi_uevent *ev;
2487 : 0 : int len = nlmsg_total_size(sizeof(*ev) + data_size);
2488 : :
2489 : 0 : skb = alloc_skb(len, GFP_NOIO);
2490 : 0 : if (!skb) {
2491 : 0 : printk(KERN_ERR "gracefully ignored host event (%d):%d OOM\n",
2492 : : host_no, code);
2493 : 0 : return;
2494 : : }
2495 : :
2496 : 0 : nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2497 : : ev = nlmsg_data(nlh);
2498 : 0 : ev->transport_handle = iscsi_handle(transport);
2499 : 0 : ev->type = ISCSI_KEVENT_HOST_EVENT;
2500 : 0 : ev->r.host_event.host_no = host_no;
2501 : 0 : ev->r.host_event.code = code;
2502 : 0 : ev->r.host_event.data_size = data_size;
2503 : :
2504 : 0 : if (data_size)
2505 : 0 : memcpy((char *)ev + sizeof(*ev), data, data_size);
2506 : :
2507 : 0 : iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_NOIO);
2508 : : }
2509 : : EXPORT_SYMBOL_GPL(iscsi_post_host_event);
2510 : :
2511 : 0 : void iscsi_ping_comp_event(uint32_t host_no, struct iscsi_transport *transport,
2512 : : uint32_t status, uint32_t pid, uint32_t data_size,
2513 : : uint8_t *data)
2514 : : {
2515 : : struct nlmsghdr *nlh;
2516 : : struct sk_buff *skb;
2517 : : struct iscsi_uevent *ev;
2518 : 0 : int len = nlmsg_total_size(sizeof(*ev) + data_size);
2519 : :
2520 : 0 : skb = alloc_skb(len, GFP_NOIO);
2521 : 0 : if (!skb) {
2522 : 0 : printk(KERN_ERR "gracefully ignored ping comp: OOM\n");
2523 : 0 : return;
2524 : : }
2525 : :
2526 : 0 : nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2527 : : ev = nlmsg_data(nlh);
2528 : 0 : ev->transport_handle = iscsi_handle(transport);
2529 : 0 : ev->type = ISCSI_KEVENT_PING_COMP;
2530 : 0 : ev->r.ping_comp.host_no = host_no;
2531 : 0 : ev->r.ping_comp.status = status;
2532 : 0 : ev->r.ping_comp.pid = pid;
2533 : 0 : ev->r.ping_comp.data_size = data_size;
2534 : 0 : memcpy((char *)ev + sizeof(*ev), data, data_size);
2535 : :
2536 : 0 : iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_NOIO);
2537 : : }
2538 : : EXPORT_SYMBOL_GPL(iscsi_ping_comp_event);
2539 : :
2540 : : static int
2541 : 0 : iscsi_if_send_reply(u32 portid, int type, void *payload, int size)
2542 : : {
2543 : : struct sk_buff *skb;
2544 : : struct nlmsghdr *nlh;
2545 : : int len = nlmsg_total_size(size);
2546 : :
2547 : 0 : skb = alloc_skb(len, GFP_ATOMIC);
2548 : 0 : if (!skb) {
2549 : 0 : printk(KERN_ERR "Could not allocate skb to send reply.\n");
2550 : 0 : return -ENOMEM;
2551 : : }
2552 : :
2553 : 0 : nlh = __nlmsg_put(skb, 0, 0, type, (len - sizeof(*nlh)), 0);
2554 : 0 : memcpy(nlmsg_data(nlh), payload, size);
2555 : 0 : return iscsi_unicast_skb(skb, portid);
2556 : : }
2557 : :
2558 : : static int
2559 : 0 : iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
2560 : : {
2561 : : struct iscsi_uevent *ev = nlmsg_data(nlh);
2562 : : struct iscsi_stats *stats;
2563 : : struct sk_buff *skbstat;
2564 : : struct iscsi_cls_conn *conn;
2565 : : struct nlmsghdr *nlhstat;
2566 : : struct iscsi_uevent *evstat;
2567 : : struct iscsi_internal *priv;
2568 : : int len = nlmsg_total_size(sizeof(*ev) +
2569 : : sizeof(struct iscsi_stats) +
2570 : : sizeof(struct iscsi_stats_custom) *
2571 : : ISCSI_STATS_CUSTOM_MAX);
2572 : : int err = 0;
2573 : :
2574 : 0 : priv = iscsi_if_transport_lookup(transport);
2575 : 0 : if (!priv)
2576 : : return -EINVAL;
2577 : :
2578 : 0 : conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid);
2579 : 0 : if (!conn)
2580 : : return -EEXIST;
2581 : :
2582 : : do {
2583 : : int actual_size;
2584 : :
2585 : : skbstat = alloc_skb(len, GFP_ATOMIC);
2586 : 0 : if (!skbstat) {
2587 : 0 : iscsi_cls_conn_printk(KERN_ERR, conn, "can not "
2588 : : "deliver stats: OOM\n");
2589 : 0 : return -ENOMEM;
2590 : : }
2591 : :
2592 : 0 : nlhstat = __nlmsg_put(skbstat, 0, 0, 0,
2593 : : (len - sizeof(*nlhstat)), 0);
2594 : : evstat = nlmsg_data(nlhstat);
2595 : 0 : memset(evstat, 0, sizeof(*evstat));
2596 : 0 : evstat->transport_handle = iscsi_handle(conn->transport);
2597 : 0 : evstat->type = nlh->nlmsg_type;
2598 : 0 : evstat->u.get_stats.cid =
2599 : 0 : ev->u.get_stats.cid;
2600 : 0 : evstat->u.get_stats.sid =
2601 : 0 : ev->u.get_stats.sid;
2602 : 0 : stats = (struct iscsi_stats *)
2603 : : ((char*)evstat + sizeof(*evstat));
2604 : 0 : memset(stats, 0, sizeof(*stats));
2605 : :
2606 : 0 : transport->get_stats(conn, stats);
2607 : 0 : actual_size = nlmsg_total_size(sizeof(struct iscsi_uevent) +
2608 : 0 : sizeof(struct iscsi_stats) +
2609 : 0 : sizeof(struct iscsi_stats_custom) *
2610 : 0 : stats->custom_length);
2611 : 0 : actual_size -= sizeof(*nlhstat);
2612 : : actual_size = nlmsg_msg_size(actual_size);
2613 : 0 : skb_trim(skbstat, NLMSG_ALIGN(actual_size));
2614 : 0 : nlhstat->nlmsg_len = actual_size;
2615 : :
2616 : 0 : err = iscsi_multicast_skb(skbstat, ISCSI_NL_GRP_ISCSID,
2617 : : GFP_ATOMIC);
2618 : 0 : } while (err < 0 && err != -ECONNREFUSED);
2619 : :
2620 : 0 : return err;
2621 : : }
2622 : :
2623 : : /**
2624 : : * iscsi_session_event - send session destr. completion event
2625 : : * @session: iscsi class session
2626 : : * @event: type of event
2627 : : */
2628 : 0 : int iscsi_session_event(struct iscsi_cls_session *session,
2629 : : enum iscsi_uevent_e event)
2630 : : {
2631 : : struct iscsi_internal *priv;
2632 : : struct Scsi_Host *shost;
2633 : : struct iscsi_uevent *ev;
2634 : : struct sk_buff *skb;
2635 : : struct nlmsghdr *nlh;
2636 : : int rc, len = nlmsg_total_size(sizeof(*ev));
2637 : :
2638 : 0 : priv = iscsi_if_transport_lookup(session->transport);
2639 : 0 : if (!priv)
2640 : : return -EINVAL;
2641 : 0 : shost = iscsi_session_to_shost(session);
2642 : :
2643 : : skb = alloc_skb(len, GFP_KERNEL);
2644 : 0 : if (!skb) {
2645 : 0 : iscsi_cls_session_printk(KERN_ERR, session,
2646 : : "Cannot notify userspace of session "
2647 : : "event %u\n", event);
2648 : 0 : return -ENOMEM;
2649 : : }
2650 : :
2651 : 0 : nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2652 : : ev = nlmsg_data(nlh);
2653 : 0 : ev->transport_handle = iscsi_handle(session->transport);
2654 : :
2655 : 0 : ev->type = event;
2656 : 0 : switch (event) {
2657 : : case ISCSI_KEVENT_DESTROY_SESSION:
2658 : 0 : ev->r.d_session.host_no = shost->host_no;
2659 : 0 : ev->r.d_session.sid = session->sid;
2660 : 0 : break;
2661 : : case ISCSI_KEVENT_CREATE_SESSION:
2662 : 0 : ev->r.c_session_ret.host_no = shost->host_no;
2663 : 0 : ev->r.c_session_ret.sid = session->sid;
2664 : 0 : break;
2665 : : case ISCSI_KEVENT_UNBIND_SESSION:
2666 : 0 : ev->r.unbind_session.host_no = shost->host_no;
2667 : 0 : ev->r.unbind_session.sid = session->sid;
2668 : 0 : break;
2669 : : default:
2670 : 0 : iscsi_cls_session_printk(KERN_ERR, session, "Invalid event "
2671 : : "%u.\n", event);
2672 : 0 : kfree_skb(skb);
2673 : 0 : return -EINVAL;
2674 : : }
2675 : :
2676 : : /*
2677 : : * this will occur if the daemon is not up, so we just warn
2678 : : * the user and when the daemon is restarted it will handle it
2679 : : */
2680 : 0 : rc = iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_KERNEL);
2681 : 0 : if (rc == -ESRCH)
2682 : 0 : iscsi_cls_session_printk(KERN_ERR, session,
2683 : : "Cannot notify userspace of session "
2684 : : "event %u. Check iscsi daemon\n",
2685 : : event);
2686 : :
2687 : 0 : ISCSI_DBG_TRANS_SESSION(session, "Completed handling event %d rc %d\n",
2688 : : event, rc);
2689 : 0 : return rc;
2690 : : }
2691 : : EXPORT_SYMBOL_GPL(iscsi_session_event);
2692 : :
2693 : : static int
2694 : 0 : iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep,
2695 : : struct iscsi_uevent *ev, pid_t pid,
2696 : : uint32_t initial_cmdsn, uint16_t cmds_max,
2697 : : uint16_t queue_depth)
2698 : : {
2699 : 0 : struct iscsi_transport *transport = priv->iscsi_transport;
2700 : : struct iscsi_cls_session *session;
2701 : : struct Scsi_Host *shost;
2702 : :
2703 : 0 : session = transport->create_session(ep, cmds_max, queue_depth,
2704 : : initial_cmdsn);
2705 : 0 : if (!session)
2706 : : return -ENOMEM;
2707 : :
2708 : 0 : session->creator = pid;
2709 : 0 : shost = iscsi_session_to_shost(session);
2710 : 0 : ev->r.c_session_ret.host_no = shost->host_no;
2711 : 0 : ev->r.c_session_ret.sid = session->sid;
2712 : 0 : ISCSI_DBG_TRANS_SESSION(session,
2713 : : "Completed creating transport session\n");
2714 : 0 : return 0;
2715 : : }
2716 : :
2717 : : static int
2718 : 0 : iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
2719 : : {
2720 : : struct iscsi_cls_conn *conn;
2721 : : struct iscsi_cls_session *session;
2722 : :
2723 : 0 : session = iscsi_session_lookup(ev->u.c_conn.sid);
2724 : 0 : if (!session) {
2725 : 0 : printk(KERN_ERR "iscsi: invalid session %d.\n",
2726 : : ev->u.c_conn.sid);
2727 : 0 : return -EINVAL;
2728 : : }
2729 : :
2730 : 0 : conn = transport->create_conn(session, ev->u.c_conn.cid);
2731 : 0 : if (!conn) {
2732 : 0 : iscsi_cls_session_printk(KERN_ERR, session,
2733 : : "couldn't create a new connection.");
2734 : 0 : return -ENOMEM;
2735 : : }
2736 : :
2737 : 0 : ev->r.c_conn_ret.sid = session->sid;
2738 : 0 : ev->r.c_conn_ret.cid = conn->cid;
2739 : :
2740 : 0 : ISCSI_DBG_TRANS_CONN(conn, "Completed creating transport conn\n");
2741 : 0 : return 0;
2742 : : }
2743 : :
2744 : : static int
2745 : 0 : iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
2746 : : {
2747 : : struct iscsi_cls_conn *conn;
2748 : :
2749 : 0 : conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
2750 : 0 : if (!conn)
2751 : : return -EINVAL;
2752 : :
2753 : 0 : ISCSI_DBG_TRANS_CONN(conn, "Destroying transport conn\n");
2754 : 0 : if (transport->destroy_conn)
2755 : 0 : transport->destroy_conn(conn);
2756 : :
2757 : : return 0;
2758 : : }
2759 : :
2760 : : static int
2761 : 0 : iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
2762 : : {
2763 : 0 : char *data = (char*)ev + sizeof(*ev);
2764 : : struct iscsi_cls_conn *conn;
2765 : : struct iscsi_cls_session *session;
2766 : 0 : int err = 0, value = 0;
2767 : :
2768 : 0 : session = iscsi_session_lookup(ev->u.set_param.sid);
2769 : 0 : conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
2770 : 0 : if (!conn || !session)
2771 : : return -EINVAL;
2772 : :
2773 : 0 : switch (ev->u.set_param.param) {
2774 : : case ISCSI_PARAM_SESS_RECOVERY_TMO:
2775 : 0 : sscanf(data, "%d", &value);
2776 : 0 : if (!session->recovery_tmo_sysfs_override)
2777 : 0 : session->recovery_tmo = value;
2778 : : break;
2779 : : default:
2780 : 0 : err = transport->set_param(conn, ev->u.set_param.param,
2781 : 0 : data, ev->u.set_param.len);
2782 : : }
2783 : :
2784 : 0 : return err;
2785 : : }
2786 : :
2787 : 0 : static int iscsi_if_ep_connect(struct iscsi_transport *transport,
2788 : : struct iscsi_uevent *ev, int msg_type)
2789 : : {
2790 : : struct iscsi_endpoint *ep;
2791 : : struct sockaddr *dst_addr;
2792 : : struct Scsi_Host *shost = NULL;
2793 : : int non_blocking, err = 0;
2794 : :
2795 : 0 : if (!transport->ep_connect)
2796 : : return -EINVAL;
2797 : :
2798 : 0 : if (msg_type == ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST) {
2799 : 0 : shost = scsi_host_lookup(ev->u.ep_connect_through_host.host_no);
2800 : 0 : if (!shost) {
2801 : 0 : printk(KERN_ERR "ep connect failed. Could not find "
2802 : : "host no %u\n",
2803 : : ev->u.ep_connect_through_host.host_no);
2804 : 0 : return -ENODEV;
2805 : : }
2806 : 0 : non_blocking = ev->u.ep_connect_through_host.non_blocking;
2807 : : } else
2808 : 0 : non_blocking = ev->u.ep_connect.non_blocking;
2809 : :
2810 : 0 : dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
2811 : 0 : ep = transport->ep_connect(shost, dst_addr, non_blocking);
2812 : 0 : if (IS_ERR(ep)) {
2813 : : err = PTR_ERR(ep);
2814 : 0 : goto release_host;
2815 : : }
2816 : :
2817 : 0 : ev->r.ep_connect_ret.handle = ep->id;
2818 : : release_host:
2819 : 0 : if (shost)
2820 : 0 : scsi_host_put(shost);
2821 : 0 : return err;
2822 : : }
2823 : :
2824 : 0 : static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
2825 : : u64 ep_handle)
2826 : : {
2827 : : struct iscsi_cls_conn *conn;
2828 : : struct iscsi_endpoint *ep;
2829 : :
2830 : 0 : if (!transport->ep_disconnect)
2831 : : return -EINVAL;
2832 : :
2833 : 0 : ep = iscsi_lookup_endpoint(ep_handle);
2834 : 0 : if (!ep)
2835 : : return -EINVAL;
2836 : 0 : conn = ep->conn;
2837 : 0 : if (conn) {
2838 : 0 : mutex_lock(&conn->ep_mutex);
2839 : 0 : conn->ep = NULL;
2840 : 0 : mutex_unlock(&conn->ep_mutex);
2841 : : }
2842 : :
2843 : 0 : transport->ep_disconnect(ep);
2844 : 0 : return 0;
2845 : : }
2846 : :
2847 : : static int
2848 : 0 : iscsi_if_transport_ep(struct iscsi_transport *transport,
2849 : : struct iscsi_uevent *ev, int msg_type)
2850 : : {
2851 : : struct iscsi_endpoint *ep;
2852 : : int rc = 0;
2853 : :
2854 : 0 : switch (msg_type) {
2855 : : case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
2856 : : case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
2857 : 0 : rc = iscsi_if_ep_connect(transport, ev, msg_type);
2858 : 0 : break;
2859 : : case ISCSI_UEVENT_TRANSPORT_EP_POLL:
2860 : 0 : if (!transport->ep_poll)
2861 : : return -EINVAL;
2862 : :
2863 : 0 : ep = iscsi_lookup_endpoint(ev->u.ep_poll.ep_handle);
2864 : 0 : if (!ep)
2865 : : return -EINVAL;
2866 : :
2867 : 0 : ev->r.retcode = transport->ep_poll(ep,
2868 : 0 : ev->u.ep_poll.timeout_ms);
2869 : 0 : break;
2870 : : case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
2871 : 0 : rc = iscsi_if_ep_disconnect(transport,
2872 : : ev->u.ep_disconnect.ep_handle);
2873 : 0 : break;
2874 : : }
2875 : 0 : return rc;
2876 : : }
2877 : :
2878 : : static int
2879 : 0 : iscsi_tgt_dscvr(struct iscsi_transport *transport,
2880 : : struct iscsi_uevent *ev)
2881 : : {
2882 : : struct Scsi_Host *shost;
2883 : : struct sockaddr *dst_addr;
2884 : : int err;
2885 : :
2886 : 0 : if (!transport->tgt_dscvr)
2887 : : return -EINVAL;
2888 : :
2889 : 0 : shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no);
2890 : 0 : if (!shost) {
2891 : 0 : printk(KERN_ERR "target discovery could not find host no %u\n",
2892 : : ev->u.tgt_dscvr.host_no);
2893 : 0 : return -ENODEV;
2894 : : }
2895 : :
2896 : :
2897 : 0 : dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
2898 : 0 : err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type,
2899 : : ev->u.tgt_dscvr.enable, dst_addr);
2900 : 0 : scsi_host_put(shost);
2901 : 0 : return err;
2902 : : }
2903 : :
2904 : : static int
2905 : 0 : iscsi_set_host_param(struct iscsi_transport *transport,
2906 : : struct iscsi_uevent *ev)
2907 : : {
2908 : 0 : char *data = (char*)ev + sizeof(*ev);
2909 : : struct Scsi_Host *shost;
2910 : : int err;
2911 : :
2912 : 0 : if (!transport->set_host_param)
2913 : : return -ENOSYS;
2914 : :
2915 : 0 : shost = scsi_host_lookup(ev->u.set_host_param.host_no);
2916 : 0 : if (!shost) {
2917 : 0 : printk(KERN_ERR "set_host_param could not find host no %u\n",
2918 : : ev->u.set_host_param.host_no);
2919 : 0 : return -ENODEV;
2920 : : }
2921 : :
2922 : 0 : err = transport->set_host_param(shost, ev->u.set_host_param.param,
2923 : 0 : data, ev->u.set_host_param.len);
2924 : 0 : scsi_host_put(shost);
2925 : 0 : return err;
2926 : : }
2927 : :
2928 : : static int
2929 : 0 : iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
2930 : : {
2931 : : struct Scsi_Host *shost;
2932 : : struct iscsi_path *params;
2933 : : int err;
2934 : :
2935 : 0 : if (!transport->set_path)
2936 : : return -ENOSYS;
2937 : :
2938 : 0 : shost = scsi_host_lookup(ev->u.set_path.host_no);
2939 : 0 : if (!shost) {
2940 : 0 : printk(KERN_ERR "set path could not find host no %u\n",
2941 : : ev->u.set_path.host_no);
2942 : 0 : return -ENODEV;
2943 : : }
2944 : :
2945 : 0 : params = (struct iscsi_path *)((char *)ev + sizeof(*ev));
2946 : 0 : err = transport->set_path(shost, params);
2947 : :
2948 : 0 : scsi_host_put(shost);
2949 : 0 : return err;
2950 : : }
2951 : :
2952 : 0 : static int iscsi_session_has_conns(int sid)
2953 : : {
2954 : : struct iscsi_cls_conn *conn;
2955 : : unsigned long flags;
2956 : : int found = 0;
2957 : :
2958 : 0 : spin_lock_irqsave(&connlock, flags);
2959 : 0 : list_for_each_entry(conn, &connlist, conn_list) {
2960 : 0 : if (iscsi_conn_get_sid(conn) == sid) {
2961 : : found = 1;
2962 : : break;
2963 : : }
2964 : : }
2965 : : spin_unlock_irqrestore(&connlock, flags);
2966 : :
2967 : 0 : return found;
2968 : : }
2969 : :
2970 : : static int
2971 : 0 : iscsi_set_iface_params(struct iscsi_transport *transport,
2972 : : struct iscsi_uevent *ev, uint32_t len)
2973 : : {
2974 : 0 : char *data = (char *)ev + sizeof(*ev);
2975 : : struct Scsi_Host *shost;
2976 : : int err;
2977 : :
2978 : 0 : if (!transport->set_iface_param)
2979 : : return -ENOSYS;
2980 : :
2981 : 0 : shost = scsi_host_lookup(ev->u.set_iface_params.host_no);
2982 : 0 : if (!shost) {
2983 : 0 : printk(KERN_ERR "set_iface_params could not find host no %u\n",
2984 : : ev->u.set_iface_params.host_no);
2985 : 0 : return -ENODEV;
2986 : : }
2987 : :
2988 : 0 : err = transport->set_iface_param(shost, data, len);
2989 : 0 : scsi_host_put(shost);
2990 : 0 : return err;
2991 : : }
2992 : :
2993 : : static int
2994 : 0 : iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev)
2995 : : {
2996 : : struct Scsi_Host *shost;
2997 : : struct sockaddr *dst_addr;
2998 : : int err;
2999 : :
3000 : 0 : if (!transport->send_ping)
3001 : : return -ENOSYS;
3002 : :
3003 : 0 : shost = scsi_host_lookup(ev->u.iscsi_ping.host_no);
3004 : 0 : if (!shost) {
3005 : 0 : printk(KERN_ERR "iscsi_ping could not find host no %u\n",
3006 : : ev->u.iscsi_ping.host_no);
3007 : 0 : return -ENODEV;
3008 : : }
3009 : :
3010 : 0 : dst_addr = (struct sockaddr *)((char *)ev + sizeof(*ev));
3011 : 0 : err = transport->send_ping(shost, ev->u.iscsi_ping.iface_num,
3012 : : ev->u.iscsi_ping.iface_type,
3013 : : ev->u.iscsi_ping.payload_size,
3014 : : ev->u.iscsi_ping.pid,
3015 : : dst_addr);
3016 : 0 : scsi_host_put(shost);
3017 : 0 : return err;
3018 : : }
3019 : :
3020 : : static int
3021 : 0 : iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
3022 : : {
3023 : : struct iscsi_uevent *ev = nlmsg_data(nlh);
3024 : : struct Scsi_Host *shost = NULL;
3025 : : struct iscsi_chap_rec *chap_rec;
3026 : : struct iscsi_internal *priv;
3027 : : struct sk_buff *skbchap;
3028 : : struct nlmsghdr *nlhchap;
3029 : : struct iscsi_uevent *evchap;
3030 : : uint32_t chap_buf_size;
3031 : : int len, err = 0;
3032 : : char *buf;
3033 : :
3034 : 0 : if (!transport->get_chap)
3035 : : return -EINVAL;
3036 : :
3037 : 0 : priv = iscsi_if_transport_lookup(transport);
3038 : 0 : if (!priv)
3039 : : return -EINVAL;
3040 : :
3041 : 0 : chap_buf_size = (ev->u.get_chap.num_entries * sizeof(*chap_rec));
3042 : 0 : len = nlmsg_total_size(sizeof(*ev) + chap_buf_size);
3043 : :
3044 : 0 : shost = scsi_host_lookup(ev->u.get_chap.host_no);
3045 : 0 : if (!shost) {
3046 : 0 : printk(KERN_ERR "%s: failed. Could not find host no %u\n",
3047 : : __func__, ev->u.get_chap.host_no);
3048 : 0 : return -ENODEV;
3049 : : }
3050 : :
3051 : : do {
3052 : : int actual_size;
3053 : :
3054 : 0 : skbchap = alloc_skb(len, GFP_KERNEL);
3055 : 0 : if (!skbchap) {
3056 : 0 : printk(KERN_ERR "can not deliver chap: OOM\n");
3057 : : err = -ENOMEM;
3058 : 0 : goto exit_get_chap;
3059 : : }
3060 : :
3061 : 0 : nlhchap = __nlmsg_put(skbchap, 0, 0, 0,
3062 : 0 : (len - sizeof(*nlhchap)), 0);
3063 : : evchap = nlmsg_data(nlhchap);
3064 : 0 : memset(evchap, 0, sizeof(*evchap));
3065 : 0 : evchap->transport_handle = iscsi_handle(transport);
3066 : 0 : evchap->type = nlh->nlmsg_type;
3067 : 0 : evchap->u.get_chap.host_no = ev->u.get_chap.host_no;
3068 : 0 : evchap->u.get_chap.chap_tbl_idx = ev->u.get_chap.chap_tbl_idx;
3069 : 0 : evchap->u.get_chap.num_entries = ev->u.get_chap.num_entries;
3070 : 0 : buf = (char *)evchap + sizeof(*evchap);
3071 : 0 : memset(buf, 0, chap_buf_size);
3072 : :
3073 : 0 : err = transport->get_chap(shost, ev->u.get_chap.chap_tbl_idx,
3074 : : &evchap->u.get_chap.num_entries, buf);
3075 : :
3076 : : actual_size = nlmsg_total_size(sizeof(*ev) + chap_buf_size);
3077 : 0 : skb_trim(skbchap, NLMSG_ALIGN(actual_size));
3078 : 0 : nlhchap->nlmsg_len = actual_size;
3079 : :
3080 : 0 : err = iscsi_multicast_skb(skbchap, ISCSI_NL_GRP_ISCSID,
3081 : : GFP_KERNEL);
3082 : 0 : } while (err < 0 && err != -ECONNREFUSED);
3083 : :
3084 : : exit_get_chap:
3085 : 0 : scsi_host_put(shost);
3086 : 0 : return err;
3087 : : }
3088 : :
3089 : 0 : static int iscsi_set_chap(struct iscsi_transport *transport,
3090 : : struct iscsi_uevent *ev, uint32_t len)
3091 : : {
3092 : 0 : char *data = (char *)ev + sizeof(*ev);
3093 : : struct Scsi_Host *shost;
3094 : : int err = 0;
3095 : :
3096 : 0 : if (!transport->set_chap)
3097 : : return -ENOSYS;
3098 : :
3099 : 0 : shost = scsi_host_lookup(ev->u.set_path.host_no);
3100 : 0 : if (!shost) {
3101 : 0 : pr_err("%s could not find host no %u\n",
3102 : : __func__, ev->u.set_path.host_no);
3103 : 0 : return -ENODEV;
3104 : : }
3105 : :
3106 : 0 : err = transport->set_chap(shost, data, len);
3107 : 0 : scsi_host_put(shost);
3108 : 0 : return err;
3109 : : }
3110 : :
3111 : 0 : static int iscsi_delete_chap(struct iscsi_transport *transport,
3112 : : struct iscsi_uevent *ev)
3113 : : {
3114 : : struct Scsi_Host *shost;
3115 : : int err = 0;
3116 : :
3117 : 0 : if (!transport->delete_chap)
3118 : : return -ENOSYS;
3119 : :
3120 : 0 : shost = scsi_host_lookup(ev->u.delete_chap.host_no);
3121 : 0 : if (!shost) {
3122 : 0 : printk(KERN_ERR "%s could not find host no %u\n",
3123 : : __func__, ev->u.delete_chap.host_no);
3124 : 0 : return -ENODEV;
3125 : : }
3126 : :
3127 : 0 : err = transport->delete_chap(shost, ev->u.delete_chap.chap_tbl_idx);
3128 : 0 : scsi_host_put(shost);
3129 : 0 : return err;
3130 : : }
3131 : :
3132 : : static const struct {
3133 : : enum iscsi_discovery_parent_type value;
3134 : : char *name;
3135 : : } iscsi_discovery_parent_names[] = {
3136 : : {ISCSI_DISC_PARENT_UNKNOWN, "Unknown" },
3137 : : {ISCSI_DISC_PARENT_SENDTGT, "Sendtarget" },
3138 : : {ISCSI_DISC_PARENT_ISNS, "isns" },
3139 : : };
3140 : :
3141 : 0 : char *iscsi_get_discovery_parent_name(int parent_type)
3142 : : {
3143 : : int i;
3144 : : char *state = "Unknown!";
3145 : :
3146 : 0 : for (i = 0; i < ARRAY_SIZE(iscsi_discovery_parent_names); i++) {
3147 : 0 : if (iscsi_discovery_parent_names[i].value & parent_type) {
3148 : 0 : state = iscsi_discovery_parent_names[i].name;
3149 : 0 : break;
3150 : : }
3151 : : }
3152 : 0 : return state;
3153 : : }
3154 : : EXPORT_SYMBOL_GPL(iscsi_get_discovery_parent_name);
3155 : :
3156 : 0 : static int iscsi_set_flashnode_param(struct iscsi_transport *transport,
3157 : : struct iscsi_uevent *ev, uint32_t len)
3158 : : {
3159 : 0 : char *data = (char *)ev + sizeof(*ev);
3160 : : struct Scsi_Host *shost;
3161 : : struct iscsi_bus_flash_session *fnode_sess;
3162 : : struct iscsi_bus_flash_conn *fnode_conn;
3163 : : struct device *dev;
3164 : : uint32_t idx;
3165 : : int err = 0;
3166 : :
3167 : 0 : if (!transport->set_flashnode_param) {
3168 : : err = -ENOSYS;
3169 : : goto exit_set_fnode;
3170 : : }
3171 : :
3172 : 0 : shost = scsi_host_lookup(ev->u.set_flashnode.host_no);
3173 : 0 : if (!shost) {
3174 : 0 : pr_err("%s could not find host no %u\n",
3175 : : __func__, ev->u.set_flashnode.host_no);
3176 : : err = -ENODEV;
3177 : 0 : goto put_host;
3178 : : }
3179 : :
3180 : 0 : idx = ev->u.set_flashnode.flashnode_idx;
3181 : : fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
3182 : 0 : if (!fnode_sess) {
3183 : 0 : pr_err("%s could not find flashnode %u for host no %u\n",
3184 : : __func__, idx, ev->u.set_flashnode.host_no);
3185 : : err = -ENODEV;
3186 : 0 : goto put_host;
3187 : : }
3188 : :
3189 : : dev = iscsi_find_flashnode_conn(fnode_sess);
3190 : 0 : if (!dev) {
3191 : : err = -ENODEV;
3192 : : goto put_sess;
3193 : : }
3194 : :
3195 : 0 : fnode_conn = iscsi_dev_to_flash_conn(dev);
3196 : 0 : err = transport->set_flashnode_param(fnode_sess, fnode_conn, data, len);
3197 : 0 : put_device(dev);
3198 : :
3199 : : put_sess:
3200 : 0 : put_device(&fnode_sess->dev);
3201 : :
3202 : : put_host:
3203 : 0 : scsi_host_put(shost);
3204 : :
3205 : : exit_set_fnode:
3206 : 0 : return err;
3207 : : }
3208 : :
3209 : 0 : static int iscsi_new_flashnode(struct iscsi_transport *transport,
3210 : : struct iscsi_uevent *ev, uint32_t len)
3211 : : {
3212 : 0 : char *data = (char *)ev + sizeof(*ev);
3213 : : struct Scsi_Host *shost;
3214 : : int index;
3215 : : int err = 0;
3216 : :
3217 : 0 : if (!transport->new_flashnode) {
3218 : : err = -ENOSYS;
3219 : : goto exit_new_fnode;
3220 : : }
3221 : :
3222 : 0 : shost = scsi_host_lookup(ev->u.new_flashnode.host_no);
3223 : 0 : if (!shost) {
3224 : 0 : pr_err("%s could not find host no %u\n",
3225 : : __func__, ev->u.new_flashnode.host_no);
3226 : : err = -ENODEV;
3227 : 0 : goto put_host;
3228 : : }
3229 : :
3230 : 0 : index = transport->new_flashnode(shost, data, len);
3231 : :
3232 : 0 : if (index >= 0)
3233 : 0 : ev->r.new_flashnode_ret.flashnode_idx = index;
3234 : : else
3235 : : err = -EIO;
3236 : :
3237 : : put_host:
3238 : 0 : scsi_host_put(shost);
3239 : :
3240 : : exit_new_fnode:
3241 : 0 : return err;
3242 : : }
3243 : :
3244 : 0 : static int iscsi_del_flashnode(struct iscsi_transport *transport,
3245 : : struct iscsi_uevent *ev)
3246 : : {
3247 : : struct Scsi_Host *shost;
3248 : : struct iscsi_bus_flash_session *fnode_sess;
3249 : : uint32_t idx;
3250 : : int err = 0;
3251 : :
3252 : 0 : if (!transport->del_flashnode) {
3253 : : err = -ENOSYS;
3254 : : goto exit_del_fnode;
3255 : : }
3256 : :
3257 : 0 : shost = scsi_host_lookup(ev->u.del_flashnode.host_no);
3258 : 0 : if (!shost) {
3259 : 0 : pr_err("%s could not find host no %u\n",
3260 : : __func__, ev->u.del_flashnode.host_no);
3261 : : err = -ENODEV;
3262 : 0 : goto put_host;
3263 : : }
3264 : :
3265 : 0 : idx = ev->u.del_flashnode.flashnode_idx;
3266 : : fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
3267 : 0 : if (!fnode_sess) {
3268 : 0 : pr_err("%s could not find flashnode %u for host no %u\n",
3269 : : __func__, idx, ev->u.del_flashnode.host_no);
3270 : : err = -ENODEV;
3271 : 0 : goto put_host;
3272 : : }
3273 : :
3274 : 0 : err = transport->del_flashnode(fnode_sess);
3275 : 0 : put_device(&fnode_sess->dev);
3276 : :
3277 : : put_host:
3278 : 0 : scsi_host_put(shost);
3279 : :
3280 : : exit_del_fnode:
3281 : 0 : return err;
3282 : : }
3283 : :
3284 : 0 : static int iscsi_login_flashnode(struct iscsi_transport *transport,
3285 : : struct iscsi_uevent *ev)
3286 : : {
3287 : : struct Scsi_Host *shost;
3288 : : struct iscsi_bus_flash_session *fnode_sess;
3289 : : struct iscsi_bus_flash_conn *fnode_conn;
3290 : : struct device *dev;
3291 : : uint32_t idx;
3292 : : int err = 0;
3293 : :
3294 : 0 : if (!transport->login_flashnode) {
3295 : : err = -ENOSYS;
3296 : : goto exit_login_fnode;
3297 : : }
3298 : :
3299 : 0 : shost = scsi_host_lookup(ev->u.login_flashnode.host_no);
3300 : 0 : if (!shost) {
3301 : 0 : pr_err("%s could not find host no %u\n",
3302 : : __func__, ev->u.login_flashnode.host_no);
3303 : : err = -ENODEV;
3304 : 0 : goto put_host;
3305 : : }
3306 : :
3307 : 0 : idx = ev->u.login_flashnode.flashnode_idx;
3308 : : fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
3309 : 0 : if (!fnode_sess) {
3310 : 0 : pr_err("%s could not find flashnode %u for host no %u\n",
3311 : : __func__, idx, ev->u.login_flashnode.host_no);
3312 : : err = -ENODEV;
3313 : 0 : goto put_host;
3314 : : }
3315 : :
3316 : : dev = iscsi_find_flashnode_conn(fnode_sess);
3317 : 0 : if (!dev) {
3318 : : err = -ENODEV;
3319 : : goto put_sess;
3320 : : }
3321 : :
3322 : 0 : fnode_conn = iscsi_dev_to_flash_conn(dev);
3323 : 0 : err = transport->login_flashnode(fnode_sess, fnode_conn);
3324 : 0 : put_device(dev);
3325 : :
3326 : : put_sess:
3327 : 0 : put_device(&fnode_sess->dev);
3328 : :
3329 : : put_host:
3330 : 0 : scsi_host_put(shost);
3331 : :
3332 : : exit_login_fnode:
3333 : 0 : return err;
3334 : : }
3335 : :
3336 : 0 : static int iscsi_logout_flashnode(struct iscsi_transport *transport,
3337 : : struct iscsi_uevent *ev)
3338 : : {
3339 : : struct Scsi_Host *shost;
3340 : : struct iscsi_bus_flash_session *fnode_sess;
3341 : : struct iscsi_bus_flash_conn *fnode_conn;
3342 : : struct device *dev;
3343 : : uint32_t idx;
3344 : : int err = 0;
3345 : :
3346 : 0 : if (!transport->logout_flashnode) {
3347 : : err = -ENOSYS;
3348 : : goto exit_logout_fnode;
3349 : : }
3350 : :
3351 : 0 : shost = scsi_host_lookup(ev->u.logout_flashnode.host_no);
3352 : 0 : if (!shost) {
3353 : 0 : pr_err("%s could not find host no %u\n",
3354 : : __func__, ev->u.logout_flashnode.host_no);
3355 : : err = -ENODEV;
3356 : 0 : goto put_host;
3357 : : }
3358 : :
3359 : 0 : idx = ev->u.logout_flashnode.flashnode_idx;
3360 : : fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
3361 : 0 : if (!fnode_sess) {
3362 : 0 : pr_err("%s could not find flashnode %u for host no %u\n",
3363 : : __func__, idx, ev->u.logout_flashnode.host_no);
3364 : : err = -ENODEV;
3365 : 0 : goto put_host;
3366 : : }
3367 : :
3368 : : dev = iscsi_find_flashnode_conn(fnode_sess);
3369 : 0 : if (!dev) {
3370 : : err = -ENODEV;
3371 : : goto put_sess;
3372 : : }
3373 : :
3374 : 0 : fnode_conn = iscsi_dev_to_flash_conn(dev);
3375 : :
3376 : 0 : err = transport->logout_flashnode(fnode_sess, fnode_conn);
3377 : 0 : put_device(dev);
3378 : :
3379 : : put_sess:
3380 : 0 : put_device(&fnode_sess->dev);
3381 : :
3382 : : put_host:
3383 : 0 : scsi_host_put(shost);
3384 : :
3385 : : exit_logout_fnode:
3386 : 0 : return err;
3387 : : }
3388 : :
3389 : 0 : static int iscsi_logout_flashnode_sid(struct iscsi_transport *transport,
3390 : : struct iscsi_uevent *ev)
3391 : : {
3392 : : struct Scsi_Host *shost;
3393 : : struct iscsi_cls_session *session;
3394 : : int err = 0;
3395 : :
3396 : 0 : if (!transport->logout_flashnode_sid) {
3397 : : err = -ENOSYS;
3398 : : goto exit_logout_sid;
3399 : : }
3400 : :
3401 : 0 : shost = scsi_host_lookup(ev->u.logout_flashnode_sid.host_no);
3402 : 0 : if (!shost) {
3403 : 0 : pr_err("%s could not find host no %u\n",
3404 : : __func__, ev->u.logout_flashnode.host_no);
3405 : : err = -ENODEV;
3406 : 0 : goto put_host;
3407 : : }
3408 : :
3409 : 0 : session = iscsi_session_lookup(ev->u.logout_flashnode_sid.sid);
3410 : 0 : if (!session) {
3411 : 0 : pr_err("%s could not find session id %u\n",
3412 : : __func__, ev->u.logout_flashnode_sid.sid);
3413 : : err = -EINVAL;
3414 : 0 : goto put_host;
3415 : : }
3416 : :
3417 : 0 : err = transport->logout_flashnode_sid(session);
3418 : :
3419 : : put_host:
3420 : 0 : scsi_host_put(shost);
3421 : :
3422 : : exit_logout_sid:
3423 : 0 : return err;
3424 : : }
3425 : :
3426 : : static int
3427 : 0 : iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
3428 : : {
3429 : : struct iscsi_uevent *ev = nlmsg_data(nlh);
3430 : : struct Scsi_Host *shost = NULL;
3431 : : struct iscsi_internal *priv;
3432 : : struct sk_buff *skbhost_stats;
3433 : : struct nlmsghdr *nlhhost_stats;
3434 : : struct iscsi_uevent *evhost_stats;
3435 : : int host_stats_size = 0;
3436 : : int len, err = 0;
3437 : : char *buf;
3438 : :
3439 : 0 : if (!transport->get_host_stats)
3440 : : return -ENOSYS;
3441 : :
3442 : 0 : priv = iscsi_if_transport_lookup(transport);
3443 : 0 : if (!priv)
3444 : : return -EINVAL;
3445 : :
3446 : : host_stats_size = sizeof(struct iscsi_offload_host_stats);
3447 : : len = nlmsg_total_size(sizeof(*ev) + host_stats_size);
3448 : :
3449 : 0 : shost = scsi_host_lookup(ev->u.get_host_stats.host_no);
3450 : 0 : if (!shost) {
3451 : 0 : pr_err("%s: failed. Could not find host no %u\n",
3452 : : __func__, ev->u.get_host_stats.host_no);
3453 : 0 : return -ENODEV;
3454 : : }
3455 : :
3456 : : do {
3457 : : int actual_size;
3458 : :
3459 : : skbhost_stats = alloc_skb(len, GFP_KERNEL);
3460 : 0 : if (!skbhost_stats) {
3461 : 0 : pr_err("cannot deliver host stats: OOM\n");
3462 : : err = -ENOMEM;
3463 : 0 : goto exit_host_stats;
3464 : : }
3465 : :
3466 : 0 : nlhhost_stats = __nlmsg_put(skbhost_stats, 0, 0, 0,
3467 : : (len - sizeof(*nlhhost_stats)), 0);
3468 : : evhost_stats = nlmsg_data(nlhhost_stats);
3469 : 0 : memset(evhost_stats, 0, sizeof(*evhost_stats));
3470 : 0 : evhost_stats->transport_handle = iscsi_handle(transport);
3471 : 0 : evhost_stats->type = nlh->nlmsg_type;
3472 : 0 : evhost_stats->u.get_host_stats.host_no =
3473 : 0 : ev->u.get_host_stats.host_no;
3474 : 0 : buf = (char *)evhost_stats + sizeof(*evhost_stats);
3475 : 0 : memset(buf, 0, host_stats_size);
3476 : :
3477 : 0 : err = transport->get_host_stats(shost, buf, host_stats_size);
3478 : 0 : if (err) {
3479 : 0 : kfree_skb(skbhost_stats);
3480 : 0 : goto exit_host_stats;
3481 : : }
3482 : :
3483 : : actual_size = nlmsg_total_size(sizeof(*ev) + host_stats_size);
3484 : 0 : skb_trim(skbhost_stats, NLMSG_ALIGN(actual_size));
3485 : 0 : nlhhost_stats->nlmsg_len = actual_size;
3486 : :
3487 : 0 : err = iscsi_multicast_skb(skbhost_stats, ISCSI_NL_GRP_ISCSID,
3488 : : GFP_KERNEL);
3489 : 0 : } while (err < 0 && err != -ECONNREFUSED);
3490 : :
3491 : : exit_host_stats:
3492 : 0 : scsi_host_put(shost);
3493 : 0 : return err;
3494 : : }
3495 : :
3496 : :
3497 : : static int
3498 : 0 : iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
3499 : : {
3500 : : int err = 0;
3501 : : u32 portid;
3502 : : struct iscsi_uevent *ev = nlmsg_data(nlh);
3503 : : struct iscsi_transport *transport = NULL;
3504 : : struct iscsi_internal *priv;
3505 : : struct iscsi_cls_session *session;
3506 : : struct iscsi_cls_conn *conn;
3507 : : struct iscsi_endpoint *ep = NULL;
3508 : :
3509 : 0 : if (nlh->nlmsg_type == ISCSI_UEVENT_PATH_UPDATE)
3510 : 0 : *group = ISCSI_NL_GRP_UIP;
3511 : : else
3512 : 0 : *group = ISCSI_NL_GRP_ISCSID;
3513 : :
3514 : 0 : priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
3515 : 0 : if (!priv)
3516 : : return -EINVAL;
3517 : 0 : transport = priv->iscsi_transport;
3518 : :
3519 : 0 : if (!try_module_get(transport->owner))
3520 : : return -EINVAL;
3521 : :
3522 : 0 : portid = NETLINK_CB(skb).portid;
3523 : :
3524 : 0 : switch (nlh->nlmsg_type) {
3525 : : case ISCSI_UEVENT_CREATE_SESSION:
3526 : 0 : err = iscsi_if_create_session(priv, ep, ev,
3527 : : portid,
3528 : : ev->u.c_session.initial_cmdsn,
3529 : : ev->u.c_session.cmds_max,
3530 : : ev->u.c_session.queue_depth);
3531 : 0 : break;
3532 : : case ISCSI_UEVENT_CREATE_BOUND_SESSION:
3533 : 0 : ep = iscsi_lookup_endpoint(ev->u.c_bound_session.ep_handle);
3534 : 0 : if (!ep) {
3535 : : err = -EINVAL;
3536 : : break;
3537 : : }
3538 : :
3539 : 0 : err = iscsi_if_create_session(priv, ep, ev,
3540 : : portid,
3541 : : ev->u.c_bound_session.initial_cmdsn,
3542 : : ev->u.c_bound_session.cmds_max,
3543 : : ev->u.c_bound_session.queue_depth);
3544 : 0 : break;
3545 : : case ISCSI_UEVENT_DESTROY_SESSION:
3546 : 0 : session = iscsi_session_lookup(ev->u.d_session.sid);
3547 : 0 : if (!session)
3548 : : err = -EINVAL;
3549 : 0 : else if (iscsi_session_has_conns(ev->u.d_session.sid))
3550 : : err = -EBUSY;
3551 : : else
3552 : 0 : transport->destroy_session(session);
3553 : : break;
3554 : : case ISCSI_UEVENT_UNBIND_SESSION:
3555 : 0 : session = iscsi_session_lookup(ev->u.d_session.sid);
3556 : 0 : if (session)
3557 : 0 : scsi_queue_work(iscsi_session_to_shost(session),
3558 : : &session->unbind_work);
3559 : : else
3560 : : err = -EINVAL;
3561 : : break;
3562 : : case ISCSI_UEVENT_CREATE_CONN:
3563 : 0 : err = iscsi_if_create_conn(transport, ev);
3564 : 0 : break;
3565 : : case ISCSI_UEVENT_DESTROY_CONN:
3566 : 0 : err = iscsi_if_destroy_conn(transport, ev);
3567 : 0 : break;
3568 : : case ISCSI_UEVENT_BIND_CONN:
3569 : 0 : session = iscsi_session_lookup(ev->u.b_conn.sid);
3570 : 0 : conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
3571 : :
3572 : 0 : if (conn && conn->ep)
3573 : 0 : iscsi_if_ep_disconnect(transport, conn->ep->id);
3574 : :
3575 : 0 : if (!session || !conn) {
3576 : : err = -EINVAL;
3577 : : break;
3578 : : }
3579 : :
3580 : 0 : ev->r.retcode = transport->bind_conn(session, conn,
3581 : : ev->u.b_conn.transport_eph,
3582 : 0 : ev->u.b_conn.is_leading);
3583 : 0 : if (ev->r.retcode || !transport->ep_connect)
3584 : : break;
3585 : :
3586 : 0 : ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
3587 : 0 : if (ep) {
3588 : 0 : ep->conn = conn;
3589 : :
3590 : 0 : mutex_lock(&conn->ep_mutex);
3591 : 0 : conn->ep = ep;
3592 : 0 : mutex_unlock(&conn->ep_mutex);
3593 : : } else
3594 : 0 : iscsi_cls_conn_printk(KERN_ERR, conn,
3595 : : "Could not set ep conn "
3596 : : "binding\n");
3597 : : break;
3598 : : case ISCSI_UEVENT_SET_PARAM:
3599 : 0 : err = iscsi_set_param(transport, ev);
3600 : 0 : break;
3601 : : case ISCSI_UEVENT_START_CONN:
3602 : 0 : conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
3603 : 0 : if (conn)
3604 : 0 : ev->r.retcode = transport->start_conn(conn);
3605 : : else
3606 : : err = -EINVAL;
3607 : : break;
3608 : : case ISCSI_UEVENT_STOP_CONN:
3609 : 0 : conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
3610 : 0 : if (conn)
3611 : 0 : transport->stop_conn(conn, ev->u.stop_conn.flag);
3612 : : else
3613 : : err = -EINVAL;
3614 : : break;
3615 : : case ISCSI_UEVENT_SEND_PDU:
3616 : 0 : conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
3617 : 0 : if (conn)
3618 : 0 : ev->r.retcode = transport->send_pdu(conn,
3619 : : (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
3620 : 0 : (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
3621 : : ev->u.send_pdu.data_size);
3622 : : else
3623 : : err = -EINVAL;
3624 : : break;
3625 : : case ISCSI_UEVENT_GET_STATS:
3626 : 0 : err = iscsi_if_get_stats(transport, nlh);
3627 : 0 : break;
3628 : : case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
3629 : : case ISCSI_UEVENT_TRANSPORT_EP_POLL:
3630 : : case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
3631 : : case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
3632 : 0 : err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
3633 : 0 : break;
3634 : : case ISCSI_UEVENT_TGT_DSCVR:
3635 : 0 : err = iscsi_tgt_dscvr(transport, ev);
3636 : 0 : break;
3637 : : case ISCSI_UEVENT_SET_HOST_PARAM:
3638 : 0 : err = iscsi_set_host_param(transport, ev);
3639 : 0 : break;
3640 : : case ISCSI_UEVENT_PATH_UPDATE:
3641 : 0 : err = iscsi_set_path(transport, ev);
3642 : 0 : break;
3643 : : case ISCSI_UEVENT_SET_IFACE_PARAMS:
3644 : 0 : err = iscsi_set_iface_params(transport, ev,
3645 : : nlmsg_attrlen(nlh, sizeof(*ev)));
3646 : 0 : break;
3647 : : case ISCSI_UEVENT_PING:
3648 : 0 : err = iscsi_send_ping(transport, ev);
3649 : 0 : break;
3650 : : case ISCSI_UEVENT_GET_CHAP:
3651 : 0 : err = iscsi_get_chap(transport, nlh);
3652 : 0 : break;
3653 : : case ISCSI_UEVENT_DELETE_CHAP:
3654 : 0 : err = iscsi_delete_chap(transport, ev);
3655 : 0 : break;
3656 : : case ISCSI_UEVENT_SET_FLASHNODE_PARAMS:
3657 : 0 : err = iscsi_set_flashnode_param(transport, ev,
3658 : : nlmsg_attrlen(nlh,
3659 : : sizeof(*ev)));
3660 : 0 : break;
3661 : : case ISCSI_UEVENT_NEW_FLASHNODE:
3662 : 0 : err = iscsi_new_flashnode(transport, ev,
3663 : : nlmsg_attrlen(nlh, sizeof(*ev)));
3664 : 0 : break;
3665 : : case ISCSI_UEVENT_DEL_FLASHNODE:
3666 : 0 : err = iscsi_del_flashnode(transport, ev);
3667 : 0 : break;
3668 : : case ISCSI_UEVENT_LOGIN_FLASHNODE:
3669 : 0 : err = iscsi_login_flashnode(transport, ev);
3670 : 0 : break;
3671 : : case ISCSI_UEVENT_LOGOUT_FLASHNODE:
3672 : 0 : err = iscsi_logout_flashnode(transport, ev);
3673 : 0 : break;
3674 : : case ISCSI_UEVENT_LOGOUT_FLASHNODE_SID:
3675 : 0 : err = iscsi_logout_flashnode_sid(transport, ev);
3676 : 0 : break;
3677 : : case ISCSI_UEVENT_SET_CHAP:
3678 : 0 : err = iscsi_set_chap(transport, ev,
3679 : : nlmsg_attrlen(nlh, sizeof(*ev)));
3680 : 0 : break;
3681 : : case ISCSI_UEVENT_GET_HOST_STATS:
3682 : 0 : err = iscsi_get_host_stats(transport, nlh);
3683 : 0 : break;
3684 : : default:
3685 : : err = -ENOSYS;
3686 : : break;
3687 : : }
3688 : :
3689 : 0 : module_put(transport->owner);
3690 : 0 : return err;
3691 : : }
3692 : :
3693 : : /*
3694 : : * Get message from skb. Each message is processed by iscsi_if_recv_msg.
3695 : : * Malformed skbs with wrong lengths or invalid creds are not processed.
3696 : : */
3697 : : static void
3698 : 0 : iscsi_if_rx(struct sk_buff *skb)
3699 : : {
3700 : 0 : u32 portid = NETLINK_CB(skb).portid;
3701 : :
3702 : 0 : mutex_lock(&rx_queue_mutex);
3703 : 0 : while (skb->len >= NLMSG_HDRLEN) {
3704 : : int err;
3705 : : uint32_t rlen;
3706 : : struct nlmsghdr *nlh;
3707 : : struct iscsi_uevent *ev;
3708 : : uint32_t group;
3709 : : int retries = ISCSI_SEND_MAX_ALLOWED;
3710 : :
3711 : : nlh = nlmsg_hdr(skb);
3712 : 0 : if (nlh->nlmsg_len < sizeof(*nlh) + sizeof(*ev) ||
3713 : : skb->len < nlh->nlmsg_len) {
3714 : : break;
3715 : : }
3716 : :
3717 : : ev = nlmsg_data(nlh);
3718 : 0 : rlen = NLMSG_ALIGN(nlh->nlmsg_len);
3719 : 0 : if (rlen > skb->len)
3720 : : rlen = skb->len;
3721 : :
3722 : 0 : err = iscsi_if_recv_msg(skb, nlh, &group);
3723 : 0 : if (err) {
3724 : 0 : ev->type = ISCSI_KEVENT_IF_ERROR;
3725 : 0 : ev->iferror = err;
3726 : : }
3727 : : do {
3728 : : /*
3729 : : * special case for GET_STATS:
3730 : : * on success - sending reply and stats from
3731 : : * inside of if_recv_msg(),
3732 : : * on error - fall through.
3733 : : */
3734 : 0 : if (ev->type == ISCSI_UEVENT_GET_STATS && !err)
3735 : : break;
3736 : 0 : if (ev->type == ISCSI_UEVENT_GET_CHAP && !err)
3737 : : break;
3738 : 0 : err = iscsi_if_send_reply(portid, nlh->nlmsg_type,
3739 : : ev, sizeof(*ev));
3740 : 0 : if (err == -EAGAIN && --retries < 0) {
3741 : 0 : printk(KERN_WARNING "Send reply failed, error %d\n", err);
3742 : 0 : break;
3743 : : }
3744 : 0 : } while (err < 0 && err != -ECONNREFUSED && err != -ESRCH);
3745 : 0 : skb_pull(skb, rlen);
3746 : : }
3747 : 0 : mutex_unlock(&rx_queue_mutex);
3748 : 0 : }
3749 : :
3750 : : #define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store) \
3751 : : struct device_attribute dev_attr_##_prefix##_##_name = \
3752 : : __ATTR(_name,_mode,_show,_store)
3753 : :
3754 : : /*
3755 : : * iSCSI connection attrs
3756 : : */
3757 : : #define iscsi_conn_attr_show(param) \
3758 : : static ssize_t \
3759 : : show_conn_param_##param(struct device *dev, \
3760 : : struct device_attribute *attr, char *buf) \
3761 : : { \
3762 : : struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent); \
3763 : : struct iscsi_transport *t = conn->transport; \
3764 : : return t->get_conn_param(conn, param, buf); \
3765 : : }
3766 : :
3767 : : #define iscsi_conn_attr(field, param) \
3768 : : iscsi_conn_attr_show(param) \
3769 : : static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_param_##param, \
3770 : : NULL);
3771 : :
3772 : 0 : iscsi_conn_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH);
3773 : 0 : iscsi_conn_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH);
3774 : 0 : iscsi_conn_attr(header_digest, ISCSI_PARAM_HDRDGST_EN);
3775 : 0 : iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN);
3776 : 0 : iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN);
3777 : 0 : iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN);
3778 : 0 : iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT);
3779 : 0 : iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
3780 : 0 : iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
3781 : 0 : iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
3782 : 0 : iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
3783 : 0 : iscsi_conn_attr(local_port, ISCSI_PARAM_LOCAL_PORT);
3784 : 0 : iscsi_conn_attr(statsn, ISCSI_PARAM_STATSN);
3785 : 0 : iscsi_conn_attr(keepalive_tmo, ISCSI_PARAM_KEEPALIVE_TMO);
3786 : 0 : iscsi_conn_attr(max_segment_size, ISCSI_PARAM_MAX_SEGMENT_SIZE);
3787 : 0 : iscsi_conn_attr(tcp_timestamp_stat, ISCSI_PARAM_TCP_TIMESTAMP_STAT);
3788 : 0 : iscsi_conn_attr(tcp_wsf_disable, ISCSI_PARAM_TCP_WSF_DISABLE);
3789 : 0 : iscsi_conn_attr(tcp_nagle_disable, ISCSI_PARAM_TCP_NAGLE_DISABLE);
3790 : 0 : iscsi_conn_attr(tcp_timer_scale, ISCSI_PARAM_TCP_TIMER_SCALE);
3791 : 0 : iscsi_conn_attr(tcp_timestamp_enable, ISCSI_PARAM_TCP_TIMESTAMP_EN);
3792 : 0 : iscsi_conn_attr(fragment_disable, ISCSI_PARAM_IP_FRAGMENT_DISABLE);
3793 : 0 : iscsi_conn_attr(ipv4_tos, ISCSI_PARAM_IPV4_TOS);
3794 : 0 : iscsi_conn_attr(ipv6_traffic_class, ISCSI_PARAM_IPV6_TC);
3795 : 0 : iscsi_conn_attr(ipv6_flow_label, ISCSI_PARAM_IPV6_FLOW_LABEL);
3796 : 0 : iscsi_conn_attr(is_fw_assigned_ipv6, ISCSI_PARAM_IS_FW_ASSIGNED_IPV6);
3797 : 0 : iscsi_conn_attr(tcp_xmit_wsf, ISCSI_PARAM_TCP_XMIT_WSF);
3798 : 0 : iscsi_conn_attr(tcp_recv_wsf, ISCSI_PARAM_TCP_RECV_WSF);
3799 : 0 : iscsi_conn_attr(local_ipaddr, ISCSI_PARAM_LOCAL_IPADDR);
3800 : :
3801 : :
3802 : : #define iscsi_conn_ep_attr_show(param) \
3803 : : static ssize_t show_conn_ep_param_##param(struct device *dev, \
3804 : : struct device_attribute *attr,\
3805 : : char *buf) \
3806 : : { \
3807 : : struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent); \
3808 : : struct iscsi_transport *t = conn->transport; \
3809 : : struct iscsi_endpoint *ep; \
3810 : : ssize_t rc; \
3811 : : \
3812 : : /* \
3813 : : * Need to make sure ep_disconnect does not free the LLD's \
3814 : : * interconnect resources while we are trying to read them. \
3815 : : */ \
3816 : : mutex_lock(&conn->ep_mutex); \
3817 : : ep = conn->ep; \
3818 : : if (!ep && t->ep_connect) { \
3819 : : mutex_unlock(&conn->ep_mutex); \
3820 : : return -ENOTCONN; \
3821 : : } \
3822 : : \
3823 : : if (ep) \
3824 : : rc = t->get_ep_param(ep, param, buf); \
3825 : : else \
3826 : : rc = t->get_conn_param(conn, param, buf); \
3827 : : mutex_unlock(&conn->ep_mutex); \
3828 : : return rc; \
3829 : : }
3830 : :
3831 : : #define iscsi_conn_ep_attr(field, param) \
3832 : : iscsi_conn_ep_attr_show(param) \
3833 : : static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, \
3834 : : show_conn_ep_param_##param, NULL);
3835 : :
3836 : 0 : iscsi_conn_ep_attr(address, ISCSI_PARAM_CONN_ADDRESS);
3837 : 0 : iscsi_conn_ep_attr(port, ISCSI_PARAM_CONN_PORT);
3838 : :
3839 : : static struct attribute *iscsi_conn_attrs[] = {
3840 : : &dev_attr_conn_max_recv_dlength.attr,
3841 : : &dev_attr_conn_max_xmit_dlength.attr,
3842 : : &dev_attr_conn_header_digest.attr,
3843 : : &dev_attr_conn_data_digest.attr,
3844 : : &dev_attr_conn_ifmarker.attr,
3845 : : &dev_attr_conn_ofmarker.attr,
3846 : : &dev_attr_conn_address.attr,
3847 : : &dev_attr_conn_port.attr,
3848 : : &dev_attr_conn_exp_statsn.attr,
3849 : : &dev_attr_conn_persistent_address.attr,
3850 : : &dev_attr_conn_persistent_port.attr,
3851 : : &dev_attr_conn_ping_tmo.attr,
3852 : : &dev_attr_conn_recv_tmo.attr,
3853 : : &dev_attr_conn_local_port.attr,
3854 : : &dev_attr_conn_statsn.attr,
3855 : : &dev_attr_conn_keepalive_tmo.attr,
3856 : : &dev_attr_conn_max_segment_size.attr,
3857 : : &dev_attr_conn_tcp_timestamp_stat.attr,
3858 : : &dev_attr_conn_tcp_wsf_disable.attr,
3859 : : &dev_attr_conn_tcp_nagle_disable.attr,
3860 : : &dev_attr_conn_tcp_timer_scale.attr,
3861 : : &dev_attr_conn_tcp_timestamp_enable.attr,
3862 : : &dev_attr_conn_fragment_disable.attr,
3863 : : &dev_attr_conn_ipv4_tos.attr,
3864 : : &dev_attr_conn_ipv6_traffic_class.attr,
3865 : : &dev_attr_conn_ipv6_flow_label.attr,
3866 : : &dev_attr_conn_is_fw_assigned_ipv6.attr,
3867 : : &dev_attr_conn_tcp_xmit_wsf.attr,
3868 : : &dev_attr_conn_tcp_recv_wsf.attr,
3869 : : &dev_attr_conn_local_ipaddr.attr,
3870 : : NULL,
3871 : : };
3872 : :
3873 : 0 : static umode_t iscsi_conn_attr_is_visible(struct kobject *kobj,
3874 : : struct attribute *attr, int i)
3875 : : {
3876 : : struct device *cdev = container_of(kobj, struct device, kobj);
3877 : 0 : struct iscsi_cls_conn *conn = transport_class_to_conn(cdev);
3878 : 0 : struct iscsi_transport *t = conn->transport;
3879 : : int param;
3880 : :
3881 : 0 : if (attr == &dev_attr_conn_max_recv_dlength.attr)
3882 : : param = ISCSI_PARAM_MAX_RECV_DLENGTH;
3883 : 0 : else if (attr == &dev_attr_conn_max_xmit_dlength.attr)
3884 : : param = ISCSI_PARAM_MAX_XMIT_DLENGTH;
3885 : 0 : else if (attr == &dev_attr_conn_header_digest.attr)
3886 : : param = ISCSI_PARAM_HDRDGST_EN;
3887 : 0 : else if (attr == &dev_attr_conn_data_digest.attr)
3888 : : param = ISCSI_PARAM_DATADGST_EN;
3889 : 0 : else if (attr == &dev_attr_conn_ifmarker.attr)
3890 : : param = ISCSI_PARAM_IFMARKER_EN;
3891 : 0 : else if (attr == &dev_attr_conn_ofmarker.attr)
3892 : : param = ISCSI_PARAM_OFMARKER_EN;
3893 : 0 : else if (attr == &dev_attr_conn_address.attr)
3894 : : param = ISCSI_PARAM_CONN_ADDRESS;
3895 : 0 : else if (attr == &dev_attr_conn_port.attr)
3896 : : param = ISCSI_PARAM_CONN_PORT;
3897 : 0 : else if (attr == &dev_attr_conn_exp_statsn.attr)
3898 : : param = ISCSI_PARAM_EXP_STATSN;
3899 : 0 : else if (attr == &dev_attr_conn_persistent_address.attr)
3900 : : param = ISCSI_PARAM_PERSISTENT_ADDRESS;
3901 : 0 : else if (attr == &dev_attr_conn_persistent_port.attr)
3902 : : param = ISCSI_PARAM_PERSISTENT_PORT;
3903 : 0 : else if (attr == &dev_attr_conn_ping_tmo.attr)
3904 : : param = ISCSI_PARAM_PING_TMO;
3905 : 0 : else if (attr == &dev_attr_conn_recv_tmo.attr)
3906 : : param = ISCSI_PARAM_RECV_TMO;
3907 : 0 : else if (attr == &dev_attr_conn_local_port.attr)
3908 : : param = ISCSI_PARAM_LOCAL_PORT;
3909 : 0 : else if (attr == &dev_attr_conn_statsn.attr)
3910 : : param = ISCSI_PARAM_STATSN;
3911 : 0 : else if (attr == &dev_attr_conn_keepalive_tmo.attr)
3912 : : param = ISCSI_PARAM_KEEPALIVE_TMO;
3913 : 0 : else if (attr == &dev_attr_conn_max_segment_size.attr)
3914 : : param = ISCSI_PARAM_MAX_SEGMENT_SIZE;
3915 : 0 : else if (attr == &dev_attr_conn_tcp_timestamp_stat.attr)
3916 : : param = ISCSI_PARAM_TCP_TIMESTAMP_STAT;
3917 : 0 : else if (attr == &dev_attr_conn_tcp_wsf_disable.attr)
3918 : : param = ISCSI_PARAM_TCP_WSF_DISABLE;
3919 : 0 : else if (attr == &dev_attr_conn_tcp_nagle_disable.attr)
3920 : : param = ISCSI_PARAM_TCP_NAGLE_DISABLE;
3921 : 0 : else if (attr == &dev_attr_conn_tcp_timer_scale.attr)
3922 : : param = ISCSI_PARAM_TCP_TIMER_SCALE;
3923 : 0 : else if (attr == &dev_attr_conn_tcp_timestamp_enable.attr)
3924 : : param = ISCSI_PARAM_TCP_TIMESTAMP_EN;
3925 : 0 : else if (attr == &dev_attr_conn_fragment_disable.attr)
3926 : : param = ISCSI_PARAM_IP_FRAGMENT_DISABLE;
3927 : 0 : else if (attr == &dev_attr_conn_ipv4_tos.attr)
3928 : : param = ISCSI_PARAM_IPV4_TOS;
3929 : 0 : else if (attr == &dev_attr_conn_ipv6_traffic_class.attr)
3930 : : param = ISCSI_PARAM_IPV6_TC;
3931 : 0 : else if (attr == &dev_attr_conn_ipv6_flow_label.attr)
3932 : : param = ISCSI_PARAM_IPV6_FLOW_LABEL;
3933 : 0 : else if (attr == &dev_attr_conn_is_fw_assigned_ipv6.attr)
3934 : : param = ISCSI_PARAM_IS_FW_ASSIGNED_IPV6;
3935 : 0 : else if (attr == &dev_attr_conn_tcp_xmit_wsf.attr)
3936 : : param = ISCSI_PARAM_TCP_XMIT_WSF;
3937 : 0 : else if (attr == &dev_attr_conn_tcp_recv_wsf.attr)
3938 : : param = ISCSI_PARAM_TCP_RECV_WSF;
3939 : 0 : else if (attr == &dev_attr_conn_local_ipaddr.attr)
3940 : : param = ISCSI_PARAM_LOCAL_IPADDR;
3941 : : else {
3942 : 0 : WARN_ONCE(1, "Invalid conn attr");
3943 : : return 0;
3944 : : }
3945 : :
3946 : 0 : return t->attr_is_visible(ISCSI_PARAM, param);
3947 : : }
3948 : :
3949 : : static struct attribute_group iscsi_conn_group = {
3950 : : .attrs = iscsi_conn_attrs,
3951 : : .is_visible = iscsi_conn_attr_is_visible,
3952 : : };
3953 : :
3954 : : /*
3955 : : * iSCSI session attrs
3956 : : */
3957 : : #define iscsi_session_attr_show(param, perm) \
3958 : : static ssize_t \
3959 : : show_session_param_##param(struct device *dev, \
3960 : : struct device_attribute *attr, char *buf) \
3961 : : { \
3962 : : struct iscsi_cls_session *session = \
3963 : : iscsi_dev_to_session(dev->parent); \
3964 : : struct iscsi_transport *t = session->transport; \
3965 : : \
3966 : : if (perm && !capable(CAP_SYS_ADMIN)) \
3967 : : return -EACCES; \
3968 : : return t->get_session_param(session, param, buf); \
3969 : : }
3970 : :
3971 : : #define iscsi_session_attr(field, param, perm) \
3972 : : iscsi_session_attr_show(param, perm) \
3973 : : static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
3974 : : NULL);
3975 : 0 : iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
3976 : 0 : iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
3977 : 0 : iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
3978 : 0 : iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, 0);
3979 : 0 : iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, 0);
3980 : 0 : iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, 0);
3981 : 0 : iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, 0);
3982 : 0 : iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, 0);
3983 : 0 : iscsi_session_attr(erl, ISCSI_PARAM_ERL, 0);
3984 : 0 : iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT, 0);
3985 : 0 : iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
3986 : 0 : iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
3987 : 0 : iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
3988 : 0 : iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
3989 : 0 : iscsi_session_attr(chap_out_idx, ISCSI_PARAM_CHAP_OUT_IDX, 1);
3990 : 0 : iscsi_session_attr(chap_in_idx, ISCSI_PARAM_CHAP_IN_IDX, 1);
3991 : 0 : iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);
3992 : 0 : iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
3993 : 0 : iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
3994 : 0 : iscsi_session_attr(tgt_reset_tmo, ISCSI_PARAM_TGT_RESET_TMO, 0);
3995 : 0 : iscsi_session_attr(ifacename, ISCSI_PARAM_IFACE_NAME, 0);
3996 : 0 : iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0);
3997 : 0 : iscsi_session_attr(targetalias, ISCSI_PARAM_TARGET_ALIAS, 0);
3998 : 0 : iscsi_session_attr(boot_root, ISCSI_PARAM_BOOT_ROOT, 0);
3999 : 0 : iscsi_session_attr(boot_nic, ISCSI_PARAM_BOOT_NIC, 0);
4000 : 0 : iscsi_session_attr(boot_target, ISCSI_PARAM_BOOT_TARGET, 0);
4001 : 0 : iscsi_session_attr(auto_snd_tgt_disable, ISCSI_PARAM_AUTO_SND_TGT_DISABLE, 0);
4002 : 0 : iscsi_session_attr(discovery_session, ISCSI_PARAM_DISCOVERY_SESS, 0);
4003 : 0 : iscsi_session_attr(portal_type, ISCSI_PARAM_PORTAL_TYPE, 0);
4004 : 0 : iscsi_session_attr(chap_auth, ISCSI_PARAM_CHAP_AUTH_EN, 0);
4005 : 0 : iscsi_session_attr(discovery_logout, ISCSI_PARAM_DISCOVERY_LOGOUT_EN, 0);
4006 : 0 : iscsi_session_attr(bidi_chap, ISCSI_PARAM_BIDI_CHAP_EN, 0);
4007 : 0 : iscsi_session_attr(discovery_auth_optional,
4008 : : ISCSI_PARAM_DISCOVERY_AUTH_OPTIONAL, 0);
4009 : 0 : iscsi_session_attr(def_time2wait, ISCSI_PARAM_DEF_TIME2WAIT, 0);
4010 : 0 : iscsi_session_attr(def_time2retain, ISCSI_PARAM_DEF_TIME2RETAIN, 0);
4011 : 0 : iscsi_session_attr(isid, ISCSI_PARAM_ISID, 0);
4012 : 0 : iscsi_session_attr(tsid, ISCSI_PARAM_TSID, 0);
4013 : 0 : iscsi_session_attr(def_taskmgmt_tmo, ISCSI_PARAM_DEF_TASKMGMT_TMO, 0);
4014 : 0 : iscsi_session_attr(discovery_parent_idx, ISCSI_PARAM_DISCOVERY_PARENT_IDX, 0);
4015 : 0 : iscsi_session_attr(discovery_parent_type, ISCSI_PARAM_DISCOVERY_PARENT_TYPE, 0);
4016 : :
4017 : : static ssize_t
4018 : 0 : show_priv_session_state(struct device *dev, struct device_attribute *attr,
4019 : : char *buf)
4020 : : {
4021 : 0 : struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
4022 : 0 : return sprintf(buf, "%s\n", iscsi_session_state_name(session->state));
4023 : : }
4024 : : static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
4025 : : NULL);
4026 : : static ssize_t
4027 : 0 : show_priv_session_creator(struct device *dev, struct device_attribute *attr,
4028 : : char *buf)
4029 : : {
4030 : 0 : struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
4031 : 0 : return sprintf(buf, "%d\n", session->creator);
4032 : : }
4033 : : static ISCSI_CLASS_ATTR(priv_sess, creator, S_IRUGO, show_priv_session_creator,
4034 : : NULL);
4035 : : static ssize_t
4036 : 0 : show_priv_session_target_id(struct device *dev, struct device_attribute *attr,
4037 : : char *buf)
4038 : : {
4039 : 0 : struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
4040 : 0 : return sprintf(buf, "%d\n", session->target_id);
4041 : : }
4042 : : static ISCSI_CLASS_ATTR(priv_sess, target_id, S_IRUGO,
4043 : : show_priv_session_target_id, NULL);
4044 : :
4045 : : #define iscsi_priv_session_attr_show(field, format) \
4046 : : static ssize_t \
4047 : : show_priv_session_##field(struct device *dev, \
4048 : : struct device_attribute *attr, char *buf) \
4049 : : { \
4050 : : struct iscsi_cls_session *session = \
4051 : : iscsi_dev_to_session(dev->parent); \
4052 : : if (session->field == -1) \
4053 : : return sprintf(buf, "off\n"); \
4054 : : return sprintf(buf, format"\n", session->field); \
4055 : : }
4056 : :
4057 : : #define iscsi_priv_session_attr_store(field) \
4058 : : static ssize_t \
4059 : : store_priv_session_##field(struct device *dev, \
4060 : : struct device_attribute *attr, \
4061 : : const char *buf, size_t count) \
4062 : : { \
4063 : : int val; \
4064 : : char *cp; \
4065 : : struct iscsi_cls_session *session = \
4066 : : iscsi_dev_to_session(dev->parent); \
4067 : : if ((session->state == ISCSI_SESSION_FREE) || \
4068 : : (session->state == ISCSI_SESSION_FAILED)) \
4069 : : return -EBUSY; \
4070 : : if (strncmp(buf, "off", 3) == 0) { \
4071 : : session->field = -1; \
4072 : : session->field##_sysfs_override = true; \
4073 : : } else { \
4074 : : val = simple_strtoul(buf, &cp, 0); \
4075 : : if (*cp != '\0' && *cp != '\n') \
4076 : : return -EINVAL; \
4077 : : session->field = val; \
4078 : : session->field##_sysfs_override = true; \
4079 : : } \
4080 : : return count; \
4081 : : }
4082 : :
4083 : : #define iscsi_priv_session_rw_attr(field, format) \
4084 : : iscsi_priv_session_attr_show(field, format) \
4085 : : iscsi_priv_session_attr_store(field) \
4086 : : static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUSR, \
4087 : : show_priv_session_##field, \
4088 : : store_priv_session_##field)
4089 : :
4090 : 0 : iscsi_priv_session_rw_attr(recovery_tmo, "%d");
4091 : :
4092 : : static struct attribute *iscsi_session_attrs[] = {
4093 : : &dev_attr_sess_initial_r2t.attr,
4094 : : &dev_attr_sess_max_outstanding_r2t.attr,
4095 : : &dev_attr_sess_immediate_data.attr,
4096 : : &dev_attr_sess_first_burst_len.attr,
4097 : : &dev_attr_sess_max_burst_len.attr,
4098 : : &dev_attr_sess_data_pdu_in_order.attr,
4099 : : &dev_attr_sess_data_seq_in_order.attr,
4100 : : &dev_attr_sess_erl.attr,
4101 : : &dev_attr_sess_targetname.attr,
4102 : : &dev_attr_sess_tpgt.attr,
4103 : : &dev_attr_sess_password.attr,
4104 : : &dev_attr_sess_password_in.attr,
4105 : : &dev_attr_sess_username.attr,
4106 : : &dev_attr_sess_username_in.attr,
4107 : : &dev_attr_sess_fast_abort.attr,
4108 : : &dev_attr_sess_abort_tmo.attr,
4109 : : &dev_attr_sess_lu_reset_tmo.attr,
4110 : : &dev_attr_sess_tgt_reset_tmo.attr,
4111 : : &dev_attr_sess_ifacename.attr,
4112 : : &dev_attr_sess_initiatorname.attr,
4113 : : &dev_attr_sess_targetalias.attr,
4114 : : &dev_attr_sess_boot_root.attr,
4115 : : &dev_attr_sess_boot_nic.attr,
4116 : : &dev_attr_sess_boot_target.attr,
4117 : : &dev_attr_priv_sess_recovery_tmo.attr,
4118 : : &dev_attr_priv_sess_state.attr,
4119 : : &dev_attr_priv_sess_creator.attr,
4120 : : &dev_attr_sess_chap_out_idx.attr,
4121 : : &dev_attr_sess_chap_in_idx.attr,
4122 : : &dev_attr_priv_sess_target_id.attr,
4123 : : &dev_attr_sess_auto_snd_tgt_disable.attr,
4124 : : &dev_attr_sess_discovery_session.attr,
4125 : : &dev_attr_sess_portal_type.attr,
4126 : : &dev_attr_sess_chap_auth.attr,
4127 : : &dev_attr_sess_discovery_logout.attr,
4128 : : &dev_attr_sess_bidi_chap.attr,
4129 : : &dev_attr_sess_discovery_auth_optional.attr,
4130 : : &dev_attr_sess_def_time2wait.attr,
4131 : : &dev_attr_sess_def_time2retain.attr,
4132 : : &dev_attr_sess_isid.attr,
4133 : : &dev_attr_sess_tsid.attr,
4134 : : &dev_attr_sess_def_taskmgmt_tmo.attr,
4135 : : &dev_attr_sess_discovery_parent_idx.attr,
4136 : : &dev_attr_sess_discovery_parent_type.attr,
4137 : : NULL,
4138 : : };
4139 : :
4140 : 0 : static umode_t iscsi_session_attr_is_visible(struct kobject *kobj,
4141 : : struct attribute *attr, int i)
4142 : : {
4143 : : struct device *cdev = container_of(kobj, struct device, kobj);
4144 : 0 : struct iscsi_cls_session *session = transport_class_to_session(cdev);
4145 : 0 : struct iscsi_transport *t = session->transport;
4146 : : int param;
4147 : :
4148 : 0 : if (attr == &dev_attr_sess_initial_r2t.attr)
4149 : : param = ISCSI_PARAM_INITIAL_R2T_EN;
4150 : 0 : else if (attr == &dev_attr_sess_max_outstanding_r2t.attr)
4151 : : param = ISCSI_PARAM_MAX_R2T;
4152 : 0 : else if (attr == &dev_attr_sess_immediate_data.attr)
4153 : : param = ISCSI_PARAM_IMM_DATA_EN;
4154 : 0 : else if (attr == &dev_attr_sess_first_burst_len.attr)
4155 : : param = ISCSI_PARAM_FIRST_BURST;
4156 : 0 : else if (attr == &dev_attr_sess_max_burst_len.attr)
4157 : : param = ISCSI_PARAM_MAX_BURST;
4158 : 0 : else if (attr == &dev_attr_sess_data_pdu_in_order.attr)
4159 : : param = ISCSI_PARAM_PDU_INORDER_EN;
4160 : 0 : else if (attr == &dev_attr_sess_data_seq_in_order.attr)
4161 : : param = ISCSI_PARAM_DATASEQ_INORDER_EN;
4162 : 0 : else if (attr == &dev_attr_sess_erl.attr)
4163 : : param = ISCSI_PARAM_ERL;
4164 : 0 : else if (attr == &dev_attr_sess_targetname.attr)
4165 : : param = ISCSI_PARAM_TARGET_NAME;
4166 : 0 : else if (attr == &dev_attr_sess_tpgt.attr)
4167 : : param = ISCSI_PARAM_TPGT;
4168 : 0 : else if (attr == &dev_attr_sess_chap_in_idx.attr)
4169 : : param = ISCSI_PARAM_CHAP_IN_IDX;
4170 : 0 : else if (attr == &dev_attr_sess_chap_out_idx.attr)
4171 : : param = ISCSI_PARAM_CHAP_OUT_IDX;
4172 : 0 : else if (attr == &dev_attr_sess_password.attr)
4173 : : param = ISCSI_PARAM_USERNAME;
4174 : 0 : else if (attr == &dev_attr_sess_password_in.attr)
4175 : : param = ISCSI_PARAM_USERNAME_IN;
4176 : 0 : else if (attr == &dev_attr_sess_username.attr)
4177 : : param = ISCSI_PARAM_PASSWORD;
4178 : 0 : else if (attr == &dev_attr_sess_username_in.attr)
4179 : : param = ISCSI_PARAM_PASSWORD_IN;
4180 : 0 : else if (attr == &dev_attr_sess_fast_abort.attr)
4181 : : param = ISCSI_PARAM_FAST_ABORT;
4182 : 0 : else if (attr == &dev_attr_sess_abort_tmo.attr)
4183 : : param = ISCSI_PARAM_ABORT_TMO;
4184 : 0 : else if (attr == &dev_attr_sess_lu_reset_tmo.attr)
4185 : : param = ISCSI_PARAM_LU_RESET_TMO;
4186 : 0 : else if (attr == &dev_attr_sess_tgt_reset_tmo.attr)
4187 : : param = ISCSI_PARAM_TGT_RESET_TMO;
4188 : 0 : else if (attr == &dev_attr_sess_ifacename.attr)
4189 : : param = ISCSI_PARAM_IFACE_NAME;
4190 : 0 : else if (attr == &dev_attr_sess_initiatorname.attr)
4191 : : param = ISCSI_PARAM_INITIATOR_NAME;
4192 : 0 : else if (attr == &dev_attr_sess_targetalias.attr)
4193 : : param = ISCSI_PARAM_TARGET_ALIAS;
4194 : 0 : else if (attr == &dev_attr_sess_boot_root.attr)
4195 : : param = ISCSI_PARAM_BOOT_ROOT;
4196 : 0 : else if (attr == &dev_attr_sess_boot_nic.attr)
4197 : : param = ISCSI_PARAM_BOOT_NIC;
4198 : 0 : else if (attr == &dev_attr_sess_boot_target.attr)
4199 : : param = ISCSI_PARAM_BOOT_TARGET;
4200 : 0 : else if (attr == &dev_attr_sess_auto_snd_tgt_disable.attr)
4201 : : param = ISCSI_PARAM_AUTO_SND_TGT_DISABLE;
4202 : 0 : else if (attr == &dev_attr_sess_discovery_session.attr)
4203 : : param = ISCSI_PARAM_DISCOVERY_SESS;
4204 : 0 : else if (attr == &dev_attr_sess_portal_type.attr)
4205 : : param = ISCSI_PARAM_PORTAL_TYPE;
4206 : 0 : else if (attr == &dev_attr_sess_chap_auth.attr)
4207 : : param = ISCSI_PARAM_CHAP_AUTH_EN;
4208 : 0 : else if (attr == &dev_attr_sess_discovery_logout.attr)
4209 : : param = ISCSI_PARAM_DISCOVERY_LOGOUT_EN;
4210 : 0 : else if (attr == &dev_attr_sess_bidi_chap.attr)
4211 : : param = ISCSI_PARAM_BIDI_CHAP_EN;
4212 : 0 : else if (attr == &dev_attr_sess_discovery_auth_optional.attr)
4213 : : param = ISCSI_PARAM_DISCOVERY_AUTH_OPTIONAL;
4214 : 0 : else if (attr == &dev_attr_sess_def_time2wait.attr)
4215 : : param = ISCSI_PARAM_DEF_TIME2WAIT;
4216 : 0 : else if (attr == &dev_attr_sess_def_time2retain.attr)
4217 : : param = ISCSI_PARAM_DEF_TIME2RETAIN;
4218 : 0 : else if (attr == &dev_attr_sess_isid.attr)
4219 : : param = ISCSI_PARAM_ISID;
4220 : 0 : else if (attr == &dev_attr_sess_tsid.attr)
4221 : : param = ISCSI_PARAM_TSID;
4222 : 0 : else if (attr == &dev_attr_sess_def_taskmgmt_tmo.attr)
4223 : : param = ISCSI_PARAM_DEF_TASKMGMT_TMO;
4224 : 0 : else if (attr == &dev_attr_sess_discovery_parent_idx.attr)
4225 : : param = ISCSI_PARAM_DISCOVERY_PARENT_IDX;
4226 : 0 : else if (attr == &dev_attr_sess_discovery_parent_type.attr)
4227 : : param = ISCSI_PARAM_DISCOVERY_PARENT_TYPE;
4228 : 0 : else if (attr == &dev_attr_priv_sess_recovery_tmo.attr)
4229 : : return S_IRUGO | S_IWUSR;
4230 : 0 : else if (attr == &dev_attr_priv_sess_state.attr)
4231 : : return S_IRUGO;
4232 : 0 : else if (attr == &dev_attr_priv_sess_creator.attr)
4233 : : return S_IRUGO;
4234 : 0 : else if (attr == &dev_attr_priv_sess_target_id.attr)
4235 : : return S_IRUGO;
4236 : : else {
4237 : 0 : WARN_ONCE(1, "Invalid session attr");
4238 : : return 0;
4239 : : }
4240 : :
4241 : 0 : return t->attr_is_visible(ISCSI_PARAM, param);
4242 : : }
4243 : :
4244 : : static struct attribute_group iscsi_session_group = {
4245 : : .attrs = iscsi_session_attrs,
4246 : : .is_visible = iscsi_session_attr_is_visible,
4247 : : };
4248 : :
4249 : : /*
4250 : : * iSCSI host attrs
4251 : : */
4252 : : #define iscsi_host_attr_show(param) \
4253 : : static ssize_t \
4254 : : show_host_param_##param(struct device *dev, \
4255 : : struct device_attribute *attr, char *buf) \
4256 : : { \
4257 : : struct Scsi_Host *shost = transport_class_to_shost(dev); \
4258 : : struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
4259 : : return priv->iscsi_transport->get_host_param(shost, param, buf); \
4260 : : }
4261 : :
4262 : : #define iscsi_host_attr(field, param) \
4263 : : iscsi_host_attr_show(param) \
4264 : : static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param, \
4265 : : NULL);
4266 : :
4267 : 0 : iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME);
4268 : 0 : iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
4269 : 0 : iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
4270 : 0 : iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
4271 : 0 : iscsi_host_attr(port_state, ISCSI_HOST_PARAM_PORT_STATE);
4272 : 0 : iscsi_host_attr(port_speed, ISCSI_HOST_PARAM_PORT_SPEED);
4273 : :
4274 : : static struct attribute *iscsi_host_attrs[] = {
4275 : : &dev_attr_host_netdev.attr,
4276 : : &dev_attr_host_hwaddress.attr,
4277 : : &dev_attr_host_ipaddress.attr,
4278 : : &dev_attr_host_initiatorname.attr,
4279 : : &dev_attr_host_port_state.attr,
4280 : : &dev_attr_host_port_speed.attr,
4281 : : NULL,
4282 : : };
4283 : :
4284 : 0 : static umode_t iscsi_host_attr_is_visible(struct kobject *kobj,
4285 : : struct attribute *attr, int i)
4286 : : {
4287 : : struct device *cdev = container_of(kobj, struct device, kobj);
4288 : 0 : struct Scsi_Host *shost = transport_class_to_shost(cdev);
4289 : 0 : struct iscsi_internal *priv = to_iscsi_internal(shost->transportt);
4290 : : int param;
4291 : :
4292 : 0 : if (attr == &dev_attr_host_netdev.attr)
4293 : : param = ISCSI_HOST_PARAM_NETDEV_NAME;
4294 : 0 : else if (attr == &dev_attr_host_hwaddress.attr)
4295 : : param = ISCSI_HOST_PARAM_HWADDRESS;
4296 : 0 : else if (attr == &dev_attr_host_ipaddress.attr)
4297 : : param = ISCSI_HOST_PARAM_IPADDRESS;
4298 : 0 : else if (attr == &dev_attr_host_initiatorname.attr)
4299 : : param = ISCSI_HOST_PARAM_INITIATOR_NAME;
4300 : 0 : else if (attr == &dev_attr_host_port_state.attr)
4301 : : param = ISCSI_HOST_PARAM_PORT_STATE;
4302 : 0 : else if (attr == &dev_attr_host_port_speed.attr)
4303 : : param = ISCSI_HOST_PARAM_PORT_SPEED;
4304 : : else {
4305 : 0 : WARN_ONCE(1, "Invalid host attr");
4306 : : return 0;
4307 : : }
4308 : :
4309 : 0 : return priv->iscsi_transport->attr_is_visible(ISCSI_HOST_PARAM, param);
4310 : : }
4311 : :
4312 : : static struct attribute_group iscsi_host_group = {
4313 : : .attrs = iscsi_host_attrs,
4314 : : .is_visible = iscsi_host_attr_is_visible,
4315 : : };
4316 : :
4317 : : /* convert iscsi_port_speed values to ascii string name */
4318 : : static const struct {
4319 : : enum iscsi_port_speed value;
4320 : : char *name;
4321 : : } iscsi_port_speed_names[] = {
4322 : : {ISCSI_PORT_SPEED_UNKNOWN, "Unknown" },
4323 : : {ISCSI_PORT_SPEED_10MBPS, "10 Mbps" },
4324 : : {ISCSI_PORT_SPEED_100MBPS, "100 Mbps" },
4325 : : {ISCSI_PORT_SPEED_1GBPS, "1 Gbps" },
4326 : : {ISCSI_PORT_SPEED_10GBPS, "10 Gbps" },
4327 : : {ISCSI_PORT_SPEED_25GBPS, "25 Gbps" },
4328 : : {ISCSI_PORT_SPEED_40GBPS, "40 Gbps" },
4329 : : };
4330 : :
4331 : 0 : char *iscsi_get_port_speed_name(struct Scsi_Host *shost)
4332 : : {
4333 : : int i;
4334 : : char *speed = "Unknown!";
4335 : 0 : struct iscsi_cls_host *ihost = shost->shost_data;
4336 : 0 : uint32_t port_speed = ihost->port_speed;
4337 : :
4338 : 0 : for (i = 0; i < ARRAY_SIZE(iscsi_port_speed_names); i++) {
4339 : 0 : if (iscsi_port_speed_names[i].value & port_speed) {
4340 : 0 : speed = iscsi_port_speed_names[i].name;
4341 : 0 : break;
4342 : : }
4343 : : }
4344 : 0 : return speed;
4345 : : }
4346 : : EXPORT_SYMBOL_GPL(iscsi_get_port_speed_name);
4347 : :
4348 : : /* convert iscsi_port_state values to ascii string name */
4349 : : static const struct {
4350 : : enum iscsi_port_state value;
4351 : : char *name;
4352 : : } iscsi_port_state_names[] = {
4353 : : {ISCSI_PORT_STATE_DOWN, "LINK DOWN" },
4354 : : {ISCSI_PORT_STATE_UP, "LINK UP" },
4355 : : };
4356 : :
4357 : 0 : char *iscsi_get_port_state_name(struct Scsi_Host *shost)
4358 : : {
4359 : : int i;
4360 : : char *state = "Unknown!";
4361 : 0 : struct iscsi_cls_host *ihost = shost->shost_data;
4362 : 0 : uint32_t port_state = ihost->port_state;
4363 : :
4364 : 0 : for (i = 0; i < ARRAY_SIZE(iscsi_port_state_names); i++) {
4365 : 0 : if (iscsi_port_state_names[i].value & port_state) {
4366 : 0 : state = iscsi_port_state_names[i].name;
4367 : 0 : break;
4368 : : }
4369 : : }
4370 : 0 : return state;
4371 : : }
4372 : : EXPORT_SYMBOL_GPL(iscsi_get_port_state_name);
4373 : :
4374 : 0 : static int iscsi_session_match(struct attribute_container *cont,
4375 : : struct device *dev)
4376 : : {
4377 : : struct iscsi_cls_session *session;
4378 : : struct Scsi_Host *shost;
4379 : : struct iscsi_internal *priv;
4380 : :
4381 : 0 : if (!iscsi_is_session_dev(dev))
4382 : : return 0;
4383 : :
4384 : : session = iscsi_dev_to_session(dev);
4385 : 0 : shost = iscsi_session_to_shost(session);
4386 : 0 : if (!shost->transportt)
4387 : : return 0;
4388 : :
4389 : : priv = to_iscsi_internal(shost->transportt);
4390 : 0 : if (priv->session_cont.ac.class != &iscsi_session_class.class)
4391 : : return 0;
4392 : :
4393 : 0 : return &priv->session_cont.ac == cont;
4394 : : }
4395 : :
4396 : 0 : static int iscsi_conn_match(struct attribute_container *cont,
4397 : : struct device *dev)
4398 : : {
4399 : : struct iscsi_cls_session *session;
4400 : : struct iscsi_cls_conn *conn;
4401 : : struct Scsi_Host *shost;
4402 : : struct iscsi_internal *priv;
4403 : :
4404 : 0 : if (!iscsi_is_conn_dev(dev))
4405 : : return 0;
4406 : :
4407 : : conn = iscsi_dev_to_conn(dev);
4408 : 0 : session = iscsi_dev_to_session(conn->dev.parent);
4409 : 0 : shost = iscsi_session_to_shost(session);
4410 : :
4411 : 0 : if (!shost->transportt)
4412 : : return 0;
4413 : :
4414 : : priv = to_iscsi_internal(shost->transportt);
4415 : 0 : if (priv->conn_cont.ac.class != &iscsi_connection_class.class)
4416 : : return 0;
4417 : :
4418 : 0 : return &priv->conn_cont.ac == cont;
4419 : : }
4420 : :
4421 : 0 : static int iscsi_host_match(struct attribute_container *cont,
4422 : : struct device *dev)
4423 : : {
4424 : : struct Scsi_Host *shost;
4425 : : struct iscsi_internal *priv;
4426 : :
4427 : 0 : if (!scsi_is_host_device(dev))
4428 : : return 0;
4429 : :
4430 : 0 : shost = dev_to_shost(dev);
4431 : 0 : if (!shost->transportt ||
4432 : 0 : shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
4433 : : return 0;
4434 : :
4435 : : priv = to_iscsi_internal(shost->transportt);
4436 : 0 : return &priv->t.host_attrs.ac == cont;
4437 : : }
4438 : :
4439 : : struct scsi_transport_template *
4440 : 0 : iscsi_register_transport(struct iscsi_transport *tt)
4441 : : {
4442 : : struct iscsi_internal *priv;
4443 : : unsigned long flags;
4444 : : int err;
4445 : :
4446 : 0 : BUG_ON(!tt);
4447 : :
4448 : 0 : priv = iscsi_if_transport_lookup(tt);
4449 : 0 : if (priv)
4450 : : return NULL;
4451 : :
4452 : 0 : priv = kzalloc(sizeof(*priv), GFP_KERNEL);
4453 : 0 : if (!priv)
4454 : : return NULL;
4455 : 0 : INIT_LIST_HEAD(&priv->list);
4456 : 0 : priv->iscsi_transport = tt;
4457 : 0 : priv->t.user_scan = iscsi_user_scan;
4458 : 0 : priv->t.create_work_queue = 1;
4459 : :
4460 : 0 : priv->dev.class = &iscsi_transport_class;
4461 : 0 : dev_set_name(&priv->dev, "%s", tt->name);
4462 : 0 : err = device_register(&priv->dev);
4463 : 0 : if (err)
4464 : : goto free_priv;
4465 : :
4466 : 0 : err = sysfs_create_group(&priv->dev.kobj, &iscsi_transport_group);
4467 : 0 : if (err)
4468 : : goto unregister_dev;
4469 : :
4470 : : /* host parameters */
4471 : 0 : priv->t.host_attrs.ac.class = &iscsi_host_class.class;
4472 : 0 : priv->t.host_attrs.ac.match = iscsi_host_match;
4473 : 0 : priv->t.host_attrs.ac.grp = &iscsi_host_group;
4474 : 0 : priv->t.host_size = sizeof(struct iscsi_cls_host);
4475 : : transport_container_register(&priv->t.host_attrs);
4476 : :
4477 : : /* connection parameters */
4478 : 0 : priv->conn_cont.ac.class = &iscsi_connection_class.class;
4479 : 0 : priv->conn_cont.ac.match = iscsi_conn_match;
4480 : 0 : priv->conn_cont.ac.grp = &iscsi_conn_group;
4481 : : transport_container_register(&priv->conn_cont);
4482 : :
4483 : : /* session parameters */
4484 : 0 : priv->session_cont.ac.class = &iscsi_session_class.class;
4485 : 0 : priv->session_cont.ac.match = iscsi_session_match;
4486 : 0 : priv->session_cont.ac.grp = &iscsi_session_group;
4487 : : transport_container_register(&priv->session_cont);
4488 : :
4489 : 0 : spin_lock_irqsave(&iscsi_transport_lock, flags);
4490 : : list_add(&priv->list, &iscsi_transports);
4491 : : spin_unlock_irqrestore(&iscsi_transport_lock, flags);
4492 : :
4493 : 0 : printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
4494 : 0 : return &priv->t;
4495 : :
4496 : : unregister_dev:
4497 : 0 : device_unregister(&priv->dev);
4498 : 0 : return NULL;
4499 : : free_priv:
4500 : 0 : kfree(priv);
4501 : 0 : return NULL;
4502 : : }
4503 : : EXPORT_SYMBOL_GPL(iscsi_register_transport);
4504 : :
4505 : 0 : int iscsi_unregister_transport(struct iscsi_transport *tt)
4506 : : {
4507 : : struct iscsi_internal *priv;
4508 : : unsigned long flags;
4509 : :
4510 : 0 : BUG_ON(!tt);
4511 : :
4512 : 0 : mutex_lock(&rx_queue_mutex);
4513 : :
4514 : 0 : priv = iscsi_if_transport_lookup(tt);
4515 : 0 : BUG_ON (!priv);
4516 : :
4517 : 0 : spin_lock_irqsave(&iscsi_transport_lock, flags);
4518 : : list_del(&priv->list);
4519 : : spin_unlock_irqrestore(&iscsi_transport_lock, flags);
4520 : :
4521 : 0 : transport_container_unregister(&priv->conn_cont);
4522 : 0 : transport_container_unregister(&priv->session_cont);
4523 : 0 : transport_container_unregister(&priv->t.host_attrs);
4524 : :
4525 : 0 : sysfs_remove_group(&priv->dev.kobj, &iscsi_transport_group);
4526 : 0 : device_unregister(&priv->dev);
4527 : 0 : mutex_unlock(&rx_queue_mutex);
4528 : :
4529 : 0 : return 0;
4530 : : }
4531 : : EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
4532 : :
4533 : 0 : void iscsi_dbg_trace(void (*trace)(struct device *dev, struct va_format *),
4534 : : struct device *dev, const char *fmt, ...)
4535 : : {
4536 : : struct va_format vaf;
4537 : : va_list args;
4538 : :
4539 : 0 : va_start(args, fmt);
4540 : 0 : vaf.fmt = fmt;
4541 : 0 : vaf.va = &args;
4542 : 0 : trace(dev, &vaf);
4543 : 0 : va_end(args);
4544 : 0 : }
4545 : : EXPORT_SYMBOL_GPL(iscsi_dbg_trace);
4546 : :
4547 : 3 : static __init int iscsi_transport_init(void)
4548 : : {
4549 : : int err;
4550 : 3 : struct netlink_kernel_cfg cfg = {
4551 : : .groups = 1,
4552 : : .input = iscsi_if_rx,
4553 : : };
4554 : 3 : printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
4555 : : ISCSI_TRANSPORT_VERSION);
4556 : :
4557 : : atomic_set(&iscsi_session_nr, 0);
4558 : :
4559 : 3 : err = class_register(&iscsi_transport_class);
4560 : 3 : if (err)
4561 : : return err;
4562 : :
4563 : 3 : err = class_register(&iscsi_endpoint_class);
4564 : 3 : if (err)
4565 : : goto unregister_transport_class;
4566 : :
4567 : 3 : err = class_register(&iscsi_iface_class);
4568 : 3 : if (err)
4569 : : goto unregister_endpoint_class;
4570 : :
4571 : 3 : err = transport_class_register(&iscsi_host_class);
4572 : 3 : if (err)
4573 : : goto unregister_iface_class;
4574 : :
4575 : 3 : err = transport_class_register(&iscsi_connection_class);
4576 : 3 : if (err)
4577 : : goto unregister_host_class;
4578 : :
4579 : 3 : err = transport_class_register(&iscsi_session_class);
4580 : 3 : if (err)
4581 : : goto unregister_conn_class;
4582 : :
4583 : 3 : err = bus_register(&iscsi_flashnode_bus);
4584 : 3 : if (err)
4585 : : goto unregister_session_class;
4586 : :
4587 : 3 : nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, &cfg);
4588 : 3 : if (!nls) {
4589 : : err = -ENOBUFS;
4590 : : goto unregister_flashnode_bus;
4591 : : }
4592 : :
4593 : 3 : iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
4594 : 3 : if (!iscsi_eh_timer_workq) {
4595 : : err = -ENOMEM;
4596 : : goto release_nls;
4597 : : }
4598 : :
4599 : : return 0;
4600 : :
4601 : : release_nls:
4602 : 0 : netlink_kernel_release(nls);
4603 : : unregister_flashnode_bus:
4604 : 0 : bus_unregister(&iscsi_flashnode_bus);
4605 : : unregister_session_class:
4606 : 0 : transport_class_unregister(&iscsi_session_class);
4607 : : unregister_conn_class:
4608 : 0 : transport_class_unregister(&iscsi_connection_class);
4609 : : unregister_host_class:
4610 : 0 : transport_class_unregister(&iscsi_host_class);
4611 : : unregister_iface_class:
4612 : 0 : class_unregister(&iscsi_iface_class);
4613 : : unregister_endpoint_class:
4614 : 0 : class_unregister(&iscsi_endpoint_class);
4615 : : unregister_transport_class:
4616 : 0 : class_unregister(&iscsi_transport_class);
4617 : 0 : return err;
4618 : : }
4619 : :
4620 : 0 : static void __exit iscsi_transport_exit(void)
4621 : : {
4622 : 0 : destroy_workqueue(iscsi_eh_timer_workq);
4623 : 0 : netlink_kernel_release(nls);
4624 : 0 : bus_unregister(&iscsi_flashnode_bus);
4625 : 0 : transport_class_unregister(&iscsi_connection_class);
4626 : 0 : transport_class_unregister(&iscsi_session_class);
4627 : 0 : transport_class_unregister(&iscsi_host_class);
4628 : 0 : class_unregister(&iscsi_endpoint_class);
4629 : 0 : class_unregister(&iscsi_iface_class);
4630 : 0 : class_unregister(&iscsi_transport_class);
4631 : 0 : }
4632 : :
4633 : : module_init(iscsi_transport_init);
4634 : : module_exit(iscsi_transport_exit);
4635 : :
4636 : : MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
4637 : : "Dmitry Yusupov <dmitry_yus@yahoo.com>, "
4638 : : "Alex Aizman <itn780@yahoo.com>");
4639 : : MODULE_DESCRIPTION("iSCSI Transport Interface");
4640 : : MODULE_LICENSE("GPL");
4641 : : MODULE_VERSION(ISCSI_TRANSPORT_VERSION);
4642 : : MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_ISCSI);
|