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