]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/scsi/scsi_transport_iscsi.c
[SCSI] be2iscsi: remove host and session casts
[mirror_ubuntu-bionic-kernel.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>
0896b752 26#include <net/tcp.h>
1da177e4
LT
27#include <scsi/scsi.h>
28#include <scsi/scsi_host.h>
29#include <scsi/scsi_device.h>
30#include <scsi/scsi_transport.h>
31#include <scsi/scsi_transport_iscsi.h>
0896b752 32#include <scsi/iscsi_if.h>
c01be6dc 33#include <scsi/scsi_cmnd.h>
1da177e4 34
4c2133c8 35#define ISCSI_TRANSPORT_VERSION "2.0-870"
1da177e4 36
632248aa
MC
37static int dbg_session;
38module_param_named(debug_session, dbg_session, int,
39 S_IRUGO | S_IWUSR);
40MODULE_PARM_DESC(debug_session,
41 "Turn on debugging for sessions in scsi_transport_iscsi "
42 "module. Set to 1 to turn on, and zero to turn off. Default "
43 "is off.");
44
45static int dbg_conn;
46module_param_named(debug_conn, dbg_conn, int,
47 S_IRUGO | S_IWUSR);
48MODULE_PARM_DESC(debug_conn,
49 "Turn on debugging for connections in scsi_transport_iscsi "
50 "module. Set to 1 to turn on, and zero to turn off. Default "
51 "is off.");
52
53#define ISCSI_DBG_TRANS_SESSION(_session, dbg_fmt, arg...) \
54 do { \
55 if (dbg_session) \
56 iscsi_cls_session_printk(KERN_INFO, _session, \
57 "%s: " dbg_fmt, \
58 __func__, ##arg); \
59 } while (0);
60
61#define ISCSI_DBG_TRANS_CONN(_conn, dbg_fmt, arg...) \
62 do { \
63 if (dbg_conn) \
64 iscsi_cls_conn_printk(KERN_INFO, _conn, \
65 "%s: " dbg_fmt, \
66 __func__, ##arg); \
67 } while (0);
68
1da177e4
LT
69struct iscsi_internal {
70 struct scsi_transport_template t;
0896b752
AA
71 struct iscsi_transport *iscsi_transport;
72 struct list_head list;
ee959b00 73 struct device dev;
30a6c652 74
0896b752 75 struct transport_container conn_cont;
0896b752 76 struct transport_container session_cont;
1da177e4
LT
77};
78
41be1444 79static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
d8bf541e 80static struct workqueue_struct *iscsi_eh_timer_workq;
b5c7a12d 81
0896b752
AA
82/*
83 * list of registered transports and lock that must
84 * be held while accessing list. The iscsi_transport_lock must
0b950672 85 * be acquired after the rx_queue_mutex.
0896b752
AA
86 */
87static LIST_HEAD(iscsi_transports);
88static DEFINE_SPINLOCK(iscsi_transport_lock);
89
90#define to_iscsi_internal(tmpl) \
91 container_of(tmpl, struct iscsi_internal, t)
92
ee959b00
TJ
93#define dev_to_iscsi_internal(_dev) \
94 container_of(_dev, struct iscsi_internal, dev)
0896b752 95
ee959b00 96static void iscsi_transport_release(struct device *dev)
0896b752 97{
ee959b00 98 struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
0896b752
AA
99 kfree(priv);
100}
1da177e4 101
0896b752
AA
102/*
103 * iscsi_transport_class represents the iscsi_transports that are
104 * registered.
105 */
106static struct class iscsi_transport_class = {
107 .name = "iscsi_transport",
ee959b00 108 .dev_release = iscsi_transport_release,
0896b752
AA
109};
110
111static ssize_t
ee959b00
TJ
112show_transport_handle(struct device *dev, struct device_attribute *attr,
113 char *buf)
0896b752 114{
ee959b00 115 struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
762e2bfa 116 return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport));
0896b752 117}
ee959b00 118static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
0896b752
AA
119
120#define show_transport_attr(name, format) \
121static ssize_t \
ee959b00
TJ
122show_transport_##name(struct device *dev, \
123 struct device_attribute *attr,char *buf) \
0896b752 124{ \
ee959b00 125 struct iscsi_internal *priv = dev_to_iscsi_internal(dev); \
0896b752
AA
126 return sprintf(buf, format"\n", priv->iscsi_transport->name); \
127} \
ee959b00 128static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
0896b752
AA
129
130show_transport_attr(caps, "0x%x");
0896b752
AA
131
132static struct attribute *iscsi_transport_attrs[] = {
ee959b00
TJ
133 &dev_attr_handle.attr,
134 &dev_attr_caps.attr,
0896b752
AA
135 NULL,
136};
137
138static struct attribute_group iscsi_transport_group = {
139 .attrs = iscsi_transport_attrs,
140};
141
d82ff9be
MC
142/*
143 * iSCSI endpoint attrs
144 */
145#define iscsi_dev_to_endpoint(_dev) \
146 container_of(_dev, struct iscsi_endpoint, dev)
147
148#define ISCSI_ATTR(_prefix,_name,_mode,_show,_store) \
149struct device_attribute dev_attr_##_prefix##_##_name = \
150 __ATTR(_name,_mode,_show,_store)
151
152static void iscsi_endpoint_release(struct device *dev)
153{
154 struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
155 kfree(ep);
156}
157
158static struct class iscsi_endpoint_class = {
159 .name = "iscsi_endpoint",
160 .dev_release = iscsi_endpoint_release,
161};
162
163static ssize_t
164show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
165{
166 struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
21536062 167 return sprintf(buf, "%llu\n", (unsigned long long) ep->id);
d82ff9be
MC
168}
169static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
170
171static struct attribute *iscsi_endpoint_attrs[] = {
172 &dev_attr_ep_handle.attr,
173 NULL,
174};
175
176static struct attribute_group iscsi_endpoint_group = {
177 .attrs = iscsi_endpoint_attrs,
178};
179
180#define ISCSI_MAX_EPID -1
181
182static int iscsi_match_epid(struct device *dev, void *data)
183{
184 struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
21536062 185 uint64_t *epid = (uint64_t *) data;
d82ff9be
MC
186
187 return *epid == ep->id;
188}
189
190struct iscsi_endpoint *
191iscsi_create_endpoint(int dd_size)
192{
193 struct device *dev;
194 struct iscsi_endpoint *ep;
21536062 195 uint64_t id;
d82ff9be
MC
196 int err;
197
198 for (id = 1; id < ISCSI_MAX_EPID; id++) {
695794ae 199 dev = class_find_device(&iscsi_endpoint_class, NULL, &id,
d82ff9be
MC
200 iscsi_match_epid);
201 if (!dev)
202 break;
203 }
204 if (id == ISCSI_MAX_EPID) {
205 printk(KERN_ERR "Too many connections. Max supported %u\n",
206 ISCSI_MAX_EPID - 1);
207 return NULL;
208 }
209
210 ep = kzalloc(sizeof(*ep) + dd_size, GFP_KERNEL);
211 if (!ep)
212 return NULL;
213
214 ep->id = id;
215 ep->dev.class = &iscsi_endpoint_class;
71610f55 216 dev_set_name(&ep->dev, "ep-%llu", (unsigned long long) id);
d82ff9be
MC
217 err = device_register(&ep->dev);
218 if (err)
219 goto free_ep;
220
221 err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group);
222 if (err)
223 goto unregister_dev;
224
225 if (dd_size)
226 ep->dd_data = &ep[1];
227 return ep;
228
229unregister_dev:
230 device_unregister(&ep->dev);
231 return NULL;
232
233free_ep:
234 kfree(ep);
235 return NULL;
236}
237EXPORT_SYMBOL_GPL(iscsi_create_endpoint);
238
239void iscsi_destroy_endpoint(struct iscsi_endpoint *ep)
240{
241 sysfs_remove_group(&ep->dev.kobj, &iscsi_endpoint_group);
242 device_unregister(&ep->dev);
243}
244EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
245
246struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
247{
f80f868e 248 struct iscsi_endpoint *ep;
d82ff9be
MC
249 struct device *dev;
250
695794ae 251 dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
d82ff9be
MC
252 iscsi_match_epid);
253 if (!dev)
254 return NULL;
255
f80f868e
MC
256 ep = iscsi_dev_to_endpoint(dev);
257 /*
258 * we can drop this now because the interface will prevent
259 * removals and lookups from racing.
260 */
261 put_device(dev);
262 return ep;
d82ff9be
MC
263}
264EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
265
8d07913d
MC
266/*
267 * Interface to display network param to sysfs
268 */
269
270static void iscsi_iface_release(struct device *dev)
271{
272 struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
273 struct device *parent = iface->dev.parent;
274
275 kfree(iface);
276 put_device(parent);
277}
278
279
280static struct class iscsi_iface_class = {
281 .name = "iscsi_iface",
282 .dev_release = iscsi_iface_release,
283};
284
285#define ISCSI_IFACE_ATTR(_prefix, _name, _mode, _show, _store) \
286struct device_attribute dev_attr_##_prefix##_##_name = \
287 __ATTR(_name, _mode, _show, _store)
288
289/* iface attrs show */
290#define iscsi_iface_attr_show(type, name, param_type, param) \
291static ssize_t \
292show_##type##_##name(struct device *dev, struct device_attribute *attr, \
293 char *buf) \
294{ \
295 struct iscsi_iface *iface = iscsi_dev_to_iface(dev); \
296 struct iscsi_transport *t = iface->transport; \
297 return t->get_iface_param(iface, param_type, param, buf); \
298} \
299
300#define iscsi_iface_net_attr(type, name, param) \
301 iscsi_iface_attr_show(type, name, ISCSI_NET_PARAM, param) \
302static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL);
303
304/* generic read only ipvi4 attribute */
305iscsi_iface_net_attr(ipv4_iface, ipaddress, ISCSI_NET_PARAM_IPV4_ADDR);
306iscsi_iface_net_attr(ipv4_iface, gateway, ISCSI_NET_PARAM_IPV4_GW);
307iscsi_iface_net_attr(ipv4_iface, subnet, ISCSI_NET_PARAM_IPV4_SUBNET);
308iscsi_iface_net_attr(ipv4_iface, bootproto, ISCSI_NET_PARAM_IPV4_BOOTPROTO);
309
310/* generic read only ipv6 attribute */
311iscsi_iface_net_attr(ipv6_iface, ipaddress, ISCSI_NET_PARAM_IPV6_ADDR);
312iscsi_iface_net_attr(ipv6_iface, link_local_addr, ISCSI_NET_PARAM_IPV6_LINKLOCAL);
313iscsi_iface_net_attr(ipv6_iface, router_addr, ISCSI_NET_PARAM_IPV6_ROUTER);
314iscsi_iface_net_attr(ipv6_iface, ipaddr_autocfg,
315 ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG);
316iscsi_iface_net_attr(ipv6_iface, linklocal_autocfg,
317 ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG);
318
319/* common read only iface attribute */
320iscsi_iface_net_attr(iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLE);
321iscsi_iface_net_attr(iface, vlan, ISCSI_NET_PARAM_VLAN_ID);
322
323static mode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
324 struct attribute *attr, int i)
325{
326 struct device *dev = container_of(kobj, struct device, kobj);
327 struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
328 struct iscsi_transport *t = iface->transport;
b78dbba0 329 int param;
8d07913d
MC
330
331 if (attr == &dev_attr_iface_enabled.attr)
b78dbba0 332 param = ISCSI_NET_PARAM_IFACE_ENABLE;
8d07913d 333 else if (attr == &dev_attr_iface_vlan.attr)
b78dbba0
MC
334 param = ISCSI_NET_PARAM_VLAN_ID;
335 else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {
8d07913d 336 if (attr == &dev_attr_ipv4_iface_ipaddress.attr)
b78dbba0 337 param = ISCSI_NET_PARAM_IPV4_ADDR;
8d07913d 338 else if (attr == &dev_attr_ipv4_iface_gateway.attr)
b78dbba0 339 param = ISCSI_NET_PARAM_IPV4_GW;
8d07913d 340 else if (attr == &dev_attr_ipv4_iface_subnet.attr)
b78dbba0 341 param = ISCSI_NET_PARAM_IPV4_SUBNET;
8d07913d 342 else if (attr == &dev_attr_ipv4_iface_bootproto.attr)
b78dbba0
MC
343 param = ISCSI_NET_PARAM_IPV4_BOOTPROTO;
344 else
345 return 0;
8d07913d
MC
346 } else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) {
347 if (attr == &dev_attr_ipv6_iface_ipaddress.attr)
b78dbba0 348 param = ISCSI_NET_PARAM_IPV6_ADDR;
8d07913d 349 else if (attr == &dev_attr_ipv6_iface_link_local_addr.attr)
b78dbba0 350 param = ISCSI_NET_PARAM_IPV6_LINKLOCAL;
8d07913d 351 else if (attr == &dev_attr_ipv6_iface_router_addr.attr)
b78dbba0 352 param = ISCSI_NET_PARAM_IPV6_ROUTER;
8d07913d 353 else if (attr == &dev_attr_ipv6_iface_ipaddr_autocfg.attr)
b78dbba0 354 param = ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG;
8d07913d 355 else if (attr == &dev_attr_ipv6_iface_linklocal_autocfg.attr)
b78dbba0
MC
356 param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG;
357 else
358 return 0;
359 } else {
360 WARN_ONCE(1, "Invalid iface attr");
361 return 0;
8d07913d
MC
362 }
363
b78dbba0 364 return t->attr_is_visible(ISCSI_NET_PARAM, param);
8d07913d
MC
365}
366
367static struct attribute *iscsi_iface_attrs[] = {
368 &dev_attr_iface_enabled.attr,
369 &dev_attr_iface_vlan.attr,
370 &dev_attr_ipv4_iface_ipaddress.attr,
371 &dev_attr_ipv4_iface_gateway.attr,
372 &dev_attr_ipv4_iface_subnet.attr,
373 &dev_attr_ipv4_iface_bootproto.attr,
374 &dev_attr_ipv6_iface_ipaddress.attr,
375 &dev_attr_ipv6_iface_link_local_addr.attr,
376 &dev_attr_ipv6_iface_router_addr.attr,
377 &dev_attr_ipv6_iface_ipaddr_autocfg.attr,
378 &dev_attr_ipv6_iface_linklocal_autocfg.attr,
379 NULL,
380};
381
382static struct attribute_group iscsi_iface_group = {
383 .attrs = iscsi_iface_attrs,
384 .is_visible = iscsi_iface_attr_is_visible,
385};
386
387struct iscsi_iface *
388iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport,
389 uint32_t iface_type, uint32_t iface_num, int dd_size)
390{
391 struct iscsi_iface *iface;
392 int err;
393
394 iface = kzalloc(sizeof(*iface) + dd_size, GFP_KERNEL);
395 if (!iface)
396 return NULL;
397
398 iface->transport = transport;
399 iface->iface_type = iface_type;
400 iface->iface_num = iface_num;
401 iface->dev.release = iscsi_iface_release;
402 iface->dev.class = &iscsi_iface_class;
403 /* parent reference released in iscsi_iface_release */
404 iface->dev.parent = get_device(&shost->shost_gendev);
405 if (iface_type == ISCSI_IFACE_TYPE_IPV4)
406 dev_set_name(&iface->dev, "ipv4-iface-%u-%u", shost->host_no,
407 iface_num);
408 else
409 dev_set_name(&iface->dev, "ipv6-iface-%u-%u", shost->host_no,
410 iface_num);
411
412 err = device_register(&iface->dev);
413 if (err)
414 goto free_iface;
415
416 err = sysfs_create_group(&iface->dev.kobj, &iscsi_iface_group);
417 if (err)
418 goto unreg_iface;
419
420 if (dd_size)
421 iface->dd_data = &iface[1];
422 return iface;
423
424unreg_iface:
425 device_unregister(&iface->dev);
426 return NULL;
427
428free_iface:
429 put_device(iface->dev.parent);
430 kfree(iface);
431 return NULL;
432}
433EXPORT_SYMBOL_GPL(iscsi_create_iface);
434
435void iscsi_destroy_iface(struct iscsi_iface *iface)
436{
437 sysfs_remove_group(&iface->dev.kobj, &iscsi_iface_group);
438 device_unregister(&iface->dev);
439}
440EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
441
30a6c652 442static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
ee959b00 443 struct device *cdev)
30a6c652
MC
444{
445 struct Scsi_Host *shost = dev_to_shost(dev);
32c6e1b9 446 struct iscsi_cls_host *ihost = shost->shost_data;
30a6c652
MC
447
448 memset(ihost, 0, sizeof(*ihost));
8aae18ad 449 atomic_set(&ihost->nr_scans, 0);
7970634b 450 mutex_init(&ihost->mutex);
30a6c652
MC
451 return 0;
452}
453
454static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
455 "iscsi_host",
456 iscsi_setup_host,
06d25af4 457 NULL,
30a6c652
MC
458 NULL);
459
0896b752
AA
460static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
461 "iscsi_session",
1da177e4
LT
462 NULL,
463 NULL,
464 NULL);
465
0896b752
AA
466static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
467 "iscsi_connection",
1da177e4
LT
468 NULL,
469 NULL,
470 NULL);
0896b752
AA
471
472static struct sock *nls;
0b950672 473static DEFINE_MUTEX(rx_queue_mutex);
0896b752 474
7b7232f3
MC
475static LIST_HEAD(sesslist);
476static DEFINE_SPINLOCK(sesslock);
7b8631b5
MC
477static LIST_HEAD(connlist);
478static DEFINE_SPINLOCK(connlock);
0896b752 479
b5c7a12d
MC
480static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
481{
482 struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent);
483 return sess->sid;
484}
485
486/*
487 * Returns the matching session to a given sid
488 */
489static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid)
7b7232f3
MC
490{
491 unsigned long flags;
492 struct iscsi_cls_session *sess;
493
494 spin_lock_irqsave(&sesslock, flags);
495 list_for_each_entry(sess, &sesslist, sess_list) {
b5c7a12d 496 if (sess->sid == sid) {
7b7232f3
MC
497 spin_unlock_irqrestore(&sesslock, flags);
498 return sess;
499 }
500 }
501 spin_unlock_irqrestore(&sesslock, flags);
502 return NULL;
503}
504
b5c7a12d
MC
505/*
506 * Returns the matching connection to a given sid / cid tuple
507 */
508static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
7b7232f3
MC
509{
510 unsigned long flags;
511 struct iscsi_cls_conn *conn;
512
513 spin_lock_irqsave(&connlock, flags);
514 list_for_each_entry(conn, &connlist, conn_list) {
b5c7a12d 515 if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) {
7b7232f3
MC
516 spin_unlock_irqrestore(&connlock, flags);
517 return conn;
518 }
519 }
520 spin_unlock_irqrestore(&connlock, flags);
521 return NULL;
522}
523
7b8631b5
MC
524/*
525 * The following functions can be used by LLDs that allocate
526 * their own scsi_hosts or by software iscsi LLDs
527 */
6eabafbe
MC
528static struct {
529 int value;
530 char *name;
531} iscsi_session_state_names[] = {
532 { ISCSI_SESSION_LOGGED_IN, "LOGGED_IN" },
533 { ISCSI_SESSION_FAILED, "FAILED" },
534 { ISCSI_SESSION_FREE, "FREE" },
535};
536
3b0f208a 537static const char *iscsi_session_state_name(int state)
6eabafbe
MC
538{
539 int i;
540 char *name = NULL;
541
542 for (i = 0; i < ARRAY_SIZE(iscsi_session_state_names); i++) {
543 if (iscsi_session_state_names[i].value == state) {
544 name = iscsi_session_state_names[i].name;
545 break;
546 }
547 }
548 return name;
549}
550
551int iscsi_session_chkready(struct iscsi_cls_session *session)
552{
553 unsigned long flags;
554 int err;
555
556 spin_lock_irqsave(&session->lock, flags);
557 switch (session->state) {
558 case ISCSI_SESSION_LOGGED_IN:
559 err = 0;
560 break;
561 case ISCSI_SESSION_FAILED:
9a1a69a1 562 err = DID_IMM_RETRY << 16;
6eabafbe
MC
563 break;
564 case ISCSI_SESSION_FREE:
56d7fcfa 565 err = DID_TRANSPORT_FAILFAST << 16;
6eabafbe
MC
566 break;
567 default:
568 err = DID_NO_CONNECT << 16;
569 break;
570 }
571 spin_unlock_irqrestore(&session->lock, flags);
572 return err;
573}
574EXPORT_SYMBOL_GPL(iscsi_session_chkready);
575
7b8631b5
MC
576static void iscsi_session_release(struct device *dev)
577{
578 struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
7b8631b5 579 struct Scsi_Host *shost;
0896b752 580
7b8631b5
MC
581 shost = iscsi_session_to_shost(session);
582 scsi_host_put(shost);
632248aa 583 ISCSI_DBG_TRANS_SESSION(session, "Completing session release\n");
7b8631b5 584 kfree(session);
7b8631b5 585}
0896b752 586
7b8631b5
MC
587static int iscsi_is_session_dev(const struct device *dev)
588{
589 return dev->release == iscsi_session_release;
590}
0896b752 591
a4804cd6
MC
592static int iscsi_iter_session_fn(struct device *dev, void *data)
593{
594 void (* fn) (struct iscsi_cls_session *) = data;
595
596 if (!iscsi_is_session_dev(dev))
597 return 0;
598 fn(iscsi_dev_to_session(dev));
599 return 0;
600}
601
602void iscsi_host_for_each_session(struct Scsi_Host *shost,
603 void (*fn)(struct iscsi_cls_session *))
604{
605 device_for_each_child(&shost->shost_gendev, fn,
606 iscsi_iter_session_fn);
607}
608EXPORT_SYMBOL_GPL(iscsi_host_for_each_session);
609
8aae18ad
MC
610/**
611 * iscsi_scan_finished - helper to report when running scans are done
612 * @shost: scsi host
613 * @time: scan run time
614 *
615 * This function can be used by drives like qla4xxx to report to the scsi
616 * layer when the scans it kicked off at module load time are done.
617 */
618int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time)
619{
32c6e1b9 620 struct iscsi_cls_host *ihost = shost->shost_data;
8aae18ad
MC
621 /*
622 * qla4xxx will have kicked off some session unblocks before calling
623 * scsi_scan_host, so just wait for them to complete.
624 */
625 return !atomic_read(&ihost->nr_scans);
626}
627EXPORT_SYMBOL_GPL(iscsi_scan_finished);
628
7970634b
MC
629struct iscsi_scan_data {
630 unsigned int channel;
631 unsigned int id;
632 unsigned int lun;
633};
634
635static int iscsi_user_scan_session(struct device *dev, void *data)
30a6c652 636{
7970634b 637 struct iscsi_scan_data *scan_data = data;
30a6c652 638 struct iscsi_cls_session *session;
7970634b
MC
639 struct Scsi_Host *shost;
640 struct iscsi_cls_host *ihost;
641 unsigned long flags;
642 unsigned int id;
643
644 if (!iscsi_is_session_dev(dev))
645 return 0;
646
647 session = iscsi_dev_to_session(dev);
632248aa
MC
648
649 ISCSI_DBG_TRANS_SESSION(session, "Scanning session\n");
650
7970634b
MC
651 shost = iscsi_session_to_shost(session);
652 ihost = shost->shost_data;
30a6c652
MC
653
654 mutex_lock(&ihost->mutex);
7970634b
MC
655 spin_lock_irqsave(&session->lock, flags);
656 if (session->state != ISCSI_SESSION_LOGGED_IN) {
657 spin_unlock_irqrestore(&session->lock, flags);
632248aa 658 goto user_scan_exit;
30a6c652 659 }
7970634b
MC
660 id = session->target_id;
661 spin_unlock_irqrestore(&session->lock, flags);
30a6c652 662
7970634b
MC
663 if (id != ISCSI_MAX_TARGET) {
664 if ((scan_data->channel == SCAN_WILD_CARD ||
665 scan_data->channel == 0) &&
666 (scan_data->id == SCAN_WILD_CARD ||
667 scan_data->id == id))
668 scsi_scan_target(&session->dev, 0, id,
669 scan_data->lun, 1);
670 }
632248aa
MC
671
672user_scan_exit:
7970634b 673 mutex_unlock(&ihost->mutex);
632248aa 674 ISCSI_DBG_TRANS_SESSION(session, "Completed session scan\n");
30a6c652
MC
675 return 0;
676}
677
7970634b
MC
678static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
679 uint id, uint lun)
680{
681 struct iscsi_scan_data scan_data;
682
683 scan_data.channel = channel;
684 scan_data.id = id;
685 scan_data.lun = lun;
686
687 return device_for_each_child(&shost->shost_gendev, &scan_data,
688 iscsi_user_scan_session);
689}
690
bd976f62
MC
691static void iscsi_scan_session(struct work_struct *work)
692{
693 struct iscsi_cls_session *session =
694 container_of(work, struct iscsi_cls_session, scan_work);
8aae18ad 695 struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9 696 struct iscsi_cls_host *ihost = shost->shost_data;
7970634b 697 struct iscsi_scan_data scan_data;
bd976f62 698
7970634b
MC
699 scan_data.channel = 0;
700 scan_data.id = SCAN_WILD_CARD;
701 scan_data.lun = SCAN_WILD_CARD;
bd976f62 702
7970634b 703 iscsi_user_scan_session(&session->dev, &scan_data);
8aae18ad 704 atomic_dec(&ihost->nr_scans);
bd976f62
MC
705}
706
c01be6dc
MC
707/**
708 * iscsi_block_scsi_eh - block scsi eh until session state has transistioned
e6d4ef45 709 * @cmd: scsi cmd passed to scsi eh handler
c01be6dc
MC
710 *
711 * If the session is down this function will wait for the recovery
712 * timer to fire or for the session to be logged back in. If the
713 * recovery timer fires then FAST_IO_FAIL is returned. The caller
714 * should pass this error value to the scsi eh.
715 */
716int iscsi_block_scsi_eh(struct scsi_cmnd *cmd)
717{
718 struct iscsi_cls_session *session =
719 starget_to_session(scsi_target(cmd->device));
720 unsigned long flags;
721 int ret = 0;
722
723 spin_lock_irqsave(&session->lock, flags);
724 while (session->state != ISCSI_SESSION_LOGGED_IN) {
725 if (session->state == ISCSI_SESSION_FREE) {
726 ret = FAST_IO_FAIL;
727 break;
728 }
729 spin_unlock_irqrestore(&session->lock, flags);
730 msleep(1000);
731 spin_lock_irqsave(&session->lock, flags);
732 }
733 spin_unlock_irqrestore(&session->lock, flags);
734 return ret;
735}
736EXPORT_SYMBOL_GPL(iscsi_block_scsi_eh);
737
c4028958 738static void session_recovery_timedout(struct work_struct *work)
30a6c652 739{
c4028958
DH
740 struct iscsi_cls_session *session =
741 container_of(work, struct iscsi_cls_session,
742 recovery_work.work);
6eabafbe 743 unsigned long flags;
30a6c652 744
322d739d
MC
745 iscsi_cls_session_printk(KERN_INFO, session,
746 "session recovery timed out after %d secs\n",
747 session->recovery_tmo);
30a6c652 748
6eabafbe
MC
749 spin_lock_irqsave(&session->lock, flags);
750 switch (session->state) {
751 case ISCSI_SESSION_FAILED:
752 session->state = ISCSI_SESSION_FREE;
753 break;
754 case ISCSI_SESSION_LOGGED_IN:
755 case ISCSI_SESSION_FREE:
756 /* we raced with the unblock's flush */
757 spin_unlock_irqrestore(&session->lock, flags);
758 return;
759 }
760 spin_unlock_irqrestore(&session->lock, flags);
761
30a6c652
MC
762 if (session->transport->session_recovery_timedout)
763 session->transport->session_recovery_timedout(session);
764
632248aa 765 ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n");
30a6c652 766 scsi_target_unblock(&session->dev);
632248aa 767 ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n");
30a6c652
MC
768}
769
45ab33b6 770static void __iscsi_unblock_session(struct work_struct *work)
6eabafbe 771{
45ab33b6
MC
772 struct iscsi_cls_session *session =
773 container_of(work, struct iscsi_cls_session,
774 unblock_work);
bd976f62 775 struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9 776 struct iscsi_cls_host *ihost = shost->shost_data;
6eabafbe
MC
777 unsigned long flags;
778
632248aa 779 ISCSI_DBG_TRANS_SESSION(session, "Unblocking session\n");
45ab33b6
MC
780 /*
781 * The recovery and unblock work get run from the same workqueue,
782 * so try to cancel it if it was going to run after this unblock.
783 */
784 cancel_delayed_work(&session->recovery_work);
6eabafbe
MC
785 spin_lock_irqsave(&session->lock, flags);
786 session->state = ISCSI_SESSION_LOGGED_IN;
787 spin_unlock_irqrestore(&session->lock, flags);
45ab33b6
MC
788 /* start IO */
789 scsi_target_unblock(&session->dev);
8aae18ad
MC
790 /*
791 * Only do kernel scanning if the driver is properly hooked into
792 * the async scanning code (drivers like iscsi_tcp do login and
793 * scanning from userspace).
794 */
795 if (shost->hostt->scan_finished) {
06d25af4 796 if (scsi_queue_work(shost, &session->scan_work))
8aae18ad
MC
797 atomic_inc(&ihost->nr_scans);
798 }
632248aa 799 ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking session\n");
6eabafbe 800}
45ab33b6
MC
801
802/**
803 * iscsi_unblock_session - set a session as logged in and start IO.
804 * @session: iscsi session
805 *
806 * Mark a session as ready to accept IO.
807 */
808void iscsi_unblock_session(struct iscsi_cls_session *session)
809{
810 queue_work(iscsi_eh_timer_workq, &session->unblock_work);
811 /*
812 * make sure all the events have completed before tell the driver
813 * it is safe
814 */
815 flush_workqueue(iscsi_eh_timer_workq);
816}
30a6c652
MC
817EXPORT_SYMBOL_GPL(iscsi_unblock_session);
818
45ab33b6 819static void __iscsi_block_session(struct work_struct *work)
30a6c652 820{
45ab33b6
MC
821 struct iscsi_cls_session *session =
822 container_of(work, struct iscsi_cls_session,
823 block_work);
6eabafbe
MC
824 unsigned long flags;
825
632248aa 826 ISCSI_DBG_TRANS_SESSION(session, "Blocking session\n");
6eabafbe
MC
827 spin_lock_irqsave(&session->lock, flags);
828 session->state = ISCSI_SESSION_FAILED;
829 spin_unlock_irqrestore(&session->lock, flags);
30a6c652 830 scsi_target_block(&session->dev);
632248aa 831 ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking\n");
fdd46dcb
MC
832 if (session->recovery_tmo >= 0)
833 queue_delayed_work(iscsi_eh_timer_workq,
834 &session->recovery_work,
835 session->recovery_tmo * HZ);
30a6c652 836}
45ab33b6
MC
837
838void iscsi_block_session(struct iscsi_cls_session *session)
839{
840 queue_work(iscsi_eh_timer_workq, &session->block_work);
841}
30a6c652
MC
842EXPORT_SYMBOL_GPL(iscsi_block_session);
843
26974789
MC
844static void __iscsi_unbind_session(struct work_struct *work)
845{
846 struct iscsi_cls_session *session =
847 container_of(work, struct iscsi_cls_session,
848 unbind_work);
849 struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9 850 struct iscsi_cls_host *ihost = shost->shost_data;
7970634b 851 unsigned long flags;
26974789 852
632248aa
MC
853 ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n");
854
26974789
MC
855 /* Prevent new scans and make sure scanning is not in progress */
856 mutex_lock(&ihost->mutex);
7970634b
MC
857 spin_lock_irqsave(&session->lock, flags);
858 if (session->target_id == ISCSI_MAX_TARGET) {
859 spin_unlock_irqrestore(&session->lock, flags);
26974789
MC
860 mutex_unlock(&ihost->mutex);
861 return;
862 }
7970634b
MC
863 session->target_id = ISCSI_MAX_TARGET;
864 spin_unlock_irqrestore(&session->lock, flags);
26974789
MC
865 mutex_unlock(&ihost->mutex);
866
867 scsi_remove_target(&session->dev);
868 iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
632248aa 869 ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
26974789
MC
870}
871
7b8631b5 872struct iscsi_cls_session *
5d91e209
MC
873iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
874 int dd_size)
7b8631b5
MC
875{
876 struct iscsi_cls_session *session;
7b8631b5 877
5d91e209 878 session = kzalloc(sizeof(*session) + dd_size,
b5c7a12d 879 GFP_KERNEL);
7b8631b5 880 if (!session)
f53a88da
MC
881 return NULL;
882
7b8631b5 883 session->transport = transport;
30a6c652 884 session->recovery_tmo = 120;
6eabafbe 885 session->state = ISCSI_SESSION_FREE;
c4028958 886 INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
30a6c652 887 INIT_LIST_HEAD(&session->sess_list);
45ab33b6
MC
888 INIT_WORK(&session->unblock_work, __iscsi_unblock_session);
889 INIT_WORK(&session->block_work, __iscsi_block_session);
26974789 890 INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
bd976f62 891 INIT_WORK(&session->scan_work, iscsi_scan_session);
6eabafbe 892 spin_lock_init(&session->lock);
7b8631b5 893
6a8a0d36
MC
894 /* this is released in the dev's release function */
895 scsi_host_get(shost);
8434aa8b
MC
896 session->dev.parent = &shost->shost_gendev;
897 session->dev.release = iscsi_session_release;
898 device_initialize(&session->dev);
5d91e209 899 if (dd_size)
b5c7a12d 900 session->dd_data = &session[1];
632248aa
MC
901
902 ISCSI_DBG_TRANS_SESSION(session, "Completed session allocation\n");
8434aa8b
MC
903 return session;
904}
905EXPORT_SYMBOL_GPL(iscsi_alloc_session);
906
7970634b
MC
907static int iscsi_get_next_target_id(struct device *dev, void *data)
908{
909 struct iscsi_cls_session *session;
910 unsigned long flags;
911 int err = 0;
912
913 if (!iscsi_is_session_dev(dev))
914 return 0;
915
916 session = iscsi_dev_to_session(dev);
917 spin_lock_irqsave(&session->lock, flags);
918 if (*((unsigned int *) data) == session->target_id)
919 err = -EEXIST;
920 spin_unlock_irqrestore(&session->lock, flags);
921 return err;
922}
923
6a8a0d36 924int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
8434aa8b
MC
925{
926 struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9 927 struct iscsi_cls_host *ihost;
26974789 928 unsigned long flags;
7970634b 929 unsigned int id = target_id;
8434aa8b 930 int err;
b5c7a12d 931
30a6c652 932 ihost = shost->shost_data;
41be1444 933 session->sid = atomic_add_return(1, &iscsi_session_nr);
7970634b
MC
934
935 if (id == ISCSI_MAX_TARGET) {
936 for (id = 0; id < ISCSI_MAX_TARGET; id++) {
937 err = device_for_each_child(&shost->shost_gendev, &id,
938 iscsi_get_next_target_id);
939 if (!err)
940 break;
941 }
942
943 if (id == ISCSI_MAX_TARGET) {
944 iscsi_cls_session_printk(KERN_ERR, session,
945 "Too many iscsi targets. Max "
946 "number of targets is %d.\n",
947 ISCSI_MAX_TARGET - 1);
24add1c4 948 err = -EOVERFLOW;
7970634b
MC
949 goto release_host;
950 }
951 }
952 session->target_id = id;
30a6c652 953
71610f55 954 dev_set_name(&session->dev, "session%u", session->sid);
8434aa8b 955 err = device_add(&session->dev);
7b8631b5 956 if (err) {
322d739d
MC
957 iscsi_cls_session_printk(KERN_ERR, session,
958 "could not register session's dev\n");
8434aa8b 959 goto release_host;
7b8631b5
MC
960 }
961 transport_register_device(&session->dev);
962
26974789
MC
963 spin_lock_irqsave(&sesslock, flags);
964 list_add(&session->sess_list, &sesslist);
965 spin_unlock_irqrestore(&sesslock, flags);
966
26974789 967 iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION);
632248aa 968 ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
8434aa8b 969 return 0;
30a6c652 970
8434aa8b
MC
971release_host:
972 scsi_host_put(shost);
973 return err;
7b8631b5 974}
8434aa8b 975EXPORT_SYMBOL_GPL(iscsi_add_session);
7b8631b5
MC
976
977/**
8434aa8b
MC
978 * iscsi_create_session - create iscsi class session
979 * @shost: scsi host
980 * @transport: iscsi transport
5d91e209 981 * @dd_size: private driver data size
eb44820c 982 * @target_id: which target
7b8631b5 983 *
8434aa8b 984 * This can be called from a LLD or iscsi_transport.
eb44820c 985 */
8434aa8b 986struct iscsi_cls_session *
5d91e209
MC
987iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
988 int dd_size, unsigned int target_id)
8434aa8b
MC
989{
990 struct iscsi_cls_session *session;
991
5d91e209 992 session = iscsi_alloc_session(shost, transport, dd_size);
8434aa8b
MC
993 if (!session)
994 return NULL;
995
6a8a0d36 996 if (iscsi_add_session(session, target_id)) {
8434aa8b
MC
997 iscsi_free_session(session);
998 return NULL;
999 }
1000 return session;
1001}
1002EXPORT_SYMBOL_GPL(iscsi_create_session);
1003
26974789
MC
1004static void iscsi_conn_release(struct device *dev)
1005{
1006 struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
1007 struct device *parent = conn->dev.parent;
1008
632248aa 1009 ISCSI_DBG_TRANS_CONN(conn, "Releasing conn\n");
26974789
MC
1010 kfree(conn);
1011 put_device(parent);
1012}
1013
1014static int iscsi_is_conn_dev(const struct device *dev)
1015{
1016 return dev->release == iscsi_conn_release;
1017}
1018
1019static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)
1020{
1021 if (!iscsi_is_conn_dev(dev))
1022 return 0;
1023 return iscsi_destroy_conn(iscsi_dev_to_conn(dev));
1024}
1025
8434aa8b 1026void iscsi_remove_session(struct iscsi_cls_session *session)
7b8631b5 1027{
30a6c652 1028 struct Scsi_Host *shost = iscsi_session_to_shost(session);
26974789
MC
1029 unsigned long flags;
1030 int err;
1031
632248aa
MC
1032 ISCSI_DBG_TRANS_SESSION(session, "Removing session\n");
1033
26974789
MC
1034 spin_lock_irqsave(&sesslock, flags);
1035 list_del(&session->sess_list);
1036 spin_unlock_irqrestore(&sesslock, flags);
30a6c652 1037
45ab33b6
MC
1038 /* make sure there are no blocks/unblocks queued */
1039 flush_workqueue(iscsi_eh_timer_workq);
1040 /* make sure the timedout callout is not running */
1041 if (!cancel_delayed_work(&session->recovery_work))
1042 flush_workqueue(iscsi_eh_timer_workq);
26974789
MC
1043 /*
1044 * If we are blocked let commands flow again. The lld or iscsi
1045 * layer should set up the queuecommand to fail commands.
45ab33b6
MC
1046 * We assume that LLD will not be calling block/unblock while
1047 * removing the session.
26974789 1048 */
6eabafbe
MC
1049 spin_lock_irqsave(&session->lock, flags);
1050 session->state = ISCSI_SESSION_FREE;
1051 spin_unlock_irqrestore(&session->lock, flags);
bd976f62 1052
45ab33b6
MC
1053 scsi_target_unblock(&session->dev);
1054 /* flush running scans then delete devices */
06d25af4 1055 scsi_flush_work(shost);
45ab33b6 1056 __iscsi_unbind_session(&session->unbind_work);
30a6c652 1057
26974789
MC
1058 /* hw iscsi may not have removed all connections from session */
1059 err = device_for_each_child(&session->dev, NULL,
1060 iscsi_iter_destroy_conn_fn);
1061 if (err)
322d739d
MC
1062 iscsi_cls_session_printk(KERN_ERR, session,
1063 "Could not delete all connections "
1064 "for session. Error %d.\n", err);
8434aa8b 1065
7b8631b5 1066 transport_unregister_device(&session->dev);
632248aa
MC
1067
1068 ISCSI_DBG_TRANS_SESSION(session, "Completing session removal\n");
8434aa8b
MC
1069 device_del(&session->dev);
1070}
1071EXPORT_SYMBOL_GPL(iscsi_remove_session);
1072
1073void iscsi_free_session(struct iscsi_cls_session *session)
1074{
632248aa 1075 ISCSI_DBG_TRANS_SESSION(session, "Freeing session\n");
26974789 1076 iscsi_session_event(session, ISCSI_KEVENT_DESTROY_SESSION);
8434aa8b 1077 put_device(&session->dev);
7b8631b5 1078}
8434aa8b
MC
1079EXPORT_SYMBOL_GPL(iscsi_free_session);
1080
1081/**
1082 * iscsi_destroy_session - destroy iscsi session
1083 * @session: iscsi_session
1084 *
1085 * Can be called by a LLD or iscsi_transport. There must not be
1086 * any running connections.
eb44820c 1087 */
8434aa8b
MC
1088int iscsi_destroy_session(struct iscsi_cls_session *session)
1089{
1090 iscsi_remove_session(session);
632248aa 1091 ISCSI_DBG_TRANS_SESSION(session, "Completing session destruction\n");
8434aa8b
MC
1092 iscsi_free_session(session);
1093 return 0;
1094}
7b8631b5
MC
1095EXPORT_SYMBOL_GPL(iscsi_destroy_session);
1096
7b8631b5
MC
1097/**
1098 * iscsi_create_conn - create iscsi class connection
1099 * @session: iscsi cls session
5d91e209 1100 * @dd_size: private driver data size
7b8631b5
MC
1101 * @cid: connection id
1102 *
1103 * This can be called from a LLD or iscsi_transport. The connection
1104 * is child of the session so cid must be unique for all connections
1105 * on the session.
b5c7a12d
MC
1106 *
1107 * Since we do not support MCS, cid will normally be zero. In some cases
1108 * for software iscsi we could be trying to preallocate a connection struct
1109 * in which case there could be two connection structs and cid would be
1110 * non-zero.
eb44820c 1111 */
7b8631b5 1112struct iscsi_cls_conn *
5d91e209 1113iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
7b8631b5
MC
1114{
1115 struct iscsi_transport *transport = session->transport;
7b8631b5 1116 struct iscsi_cls_conn *conn;
26974789 1117 unsigned long flags;
7b8631b5
MC
1118 int err;
1119
5d91e209 1120 conn = kzalloc(sizeof(*conn) + dd_size, GFP_KERNEL);
7b8631b5
MC
1121 if (!conn)
1122 return NULL;
5d91e209 1123 if (dd_size)
7b8631b5
MC
1124 conn->dd_data = &conn[1];
1125
22a39fbb 1126 mutex_init(&conn->ep_mutex);
7b8631b5
MC
1127 INIT_LIST_HEAD(&conn->conn_list);
1128 conn->transport = transport;
b5c7a12d 1129 conn->cid = cid;
7b8631b5
MC
1130
1131 /* this is released in the dev's release function */
1132 if (!get_device(&session->dev))
43a145a3 1133 goto free_conn;
b5c7a12d 1134
71610f55 1135 dev_set_name(&conn->dev, "connection%d:%u", session->sid, cid);
7b8631b5
MC
1136 conn->dev.parent = &session->dev;
1137 conn->dev.release = iscsi_conn_release;
1138 err = device_register(&conn->dev);
1139 if (err) {
322d739d
MC
1140 iscsi_cls_session_printk(KERN_ERR, session, "could not "
1141 "register connection's dev\n");
7b8631b5
MC
1142 goto release_parent_ref;
1143 }
1144 transport_register_device(&conn->dev);
26974789
MC
1145
1146 spin_lock_irqsave(&connlock, flags);
1147 list_add(&conn->conn_list, &connlist);
26974789 1148 spin_unlock_irqrestore(&connlock, flags);
632248aa
MC
1149
1150 ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n");
7b8631b5
MC
1151 return conn;
1152
1153release_parent_ref:
1154 put_device(&session->dev);
1155free_conn:
1156 kfree(conn);
1157 return NULL;
1158}
1159
1160EXPORT_SYMBOL_GPL(iscsi_create_conn);
1161
1162/**
1163 * iscsi_destroy_conn - destroy iscsi class connection
eb44820c 1164 * @conn: iscsi cls session
7b8631b5 1165 *
26974789 1166 * This can be called from a LLD or iscsi_transport.
eb44820c 1167 */
7b8631b5
MC
1168int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
1169{
26974789
MC
1170 unsigned long flags;
1171
1172 spin_lock_irqsave(&connlock, flags);
26974789
MC
1173 list_del(&conn->conn_list);
1174 spin_unlock_irqrestore(&connlock, flags);
1175
7b8631b5 1176 transport_unregister_device(&conn->dev);
632248aa 1177 ISCSI_DBG_TRANS_CONN(conn, "Completing conn destruction\n");
7b8631b5
MC
1178 device_unregister(&conn->dev);
1179 return 0;
1180}
7b8631b5
MC
1181EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
1182
7b8631b5
MC
1183/*
1184 * iscsi interface functions
1185 */
0896b752
AA
1186static struct iscsi_internal *
1187iscsi_if_transport_lookup(struct iscsi_transport *tt)
1188{
1189 struct iscsi_internal *priv;
1190 unsigned long flags;
1191
1192 spin_lock_irqsave(&iscsi_transport_lock, flags);
1193 list_for_each_entry(priv, &iscsi_transports, list) {
1194 if (tt == priv->iscsi_transport) {
1195 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
1196 return priv;
1197 }
1198 }
1199 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
1200 return NULL;
1201}
1da177e4 1202
53cb8a1f 1203static int
43514774 1204iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp)
53cb8a1f 1205{
43514774 1206 return nlmsg_multicast(nls, skb, 0, group, gfp);
1da177e4 1207}
1da177e4 1208
7b7232f3 1209int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
0896b752 1210 char *data, uint32_t data_size)
1da177e4 1211{
0896b752
AA
1212 struct nlmsghdr *nlh;
1213 struct sk_buff *skb;
1214 struct iscsi_uevent *ev;
0896b752 1215 char *pdu;
790f39a2 1216 struct iscsi_internal *priv;
0896b752
AA
1217 int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
1218 data_size);
1219
790f39a2
MC
1220 priv = iscsi_if_transport_lookup(conn->transport);
1221 if (!priv)
1222 return -EINVAL;
1223
43a145a3 1224 skb = alloc_skb(len, GFP_ATOMIC);
0896b752 1225 if (!skb) {
e5bd7b54 1226 iscsi_conn_error_event(conn, ISCSI_ERR_CONN_FAILED);
322d739d
MC
1227 iscsi_cls_conn_printk(KERN_ERR, conn, "can not deliver "
1228 "control PDU: OOM\n");
0896b752
AA
1229 return -ENOMEM;
1230 }
1da177e4 1231
43514774 1232 nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
0896b752
AA
1233 ev = NLMSG_DATA(nlh);
1234 memset(ev, 0, sizeof(*ev));
1235 ev->transport_handle = iscsi_handle(conn->transport);
1236 ev->type = ISCSI_KEVENT_RECV_PDU;
b5c7a12d
MC
1237 ev->r.recv_req.cid = conn->cid;
1238 ev->r.recv_req.sid = iscsi_conn_get_sid(conn);
0896b752
AA
1239 pdu = (char*)ev + sizeof(*ev);
1240 memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
1241 memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
1da177e4 1242
43514774 1243 return iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
1da177e4 1244}
0896b752 1245EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
1da177e4 1246
43514774
MC
1247int iscsi_offload_mesg(struct Scsi_Host *shost,
1248 struct iscsi_transport *transport, uint32_t type,
1249 char *data, uint16_t data_size)
1250{
1251 struct nlmsghdr *nlh;
1252 struct sk_buff *skb;
1253 struct iscsi_uevent *ev;
1254 int len = NLMSG_SPACE(sizeof(*ev) + data_size);
1255
a541f840 1256 skb = alloc_skb(len, GFP_ATOMIC);
43514774
MC
1257 if (!skb) {
1258 printk(KERN_ERR "can not deliver iscsi offload message:OOM\n");
1259 return -ENOMEM;
1260 }
1261
1262 nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
1263 ev = NLMSG_DATA(nlh);
1264 memset(ev, 0, sizeof(*ev));
1265 ev->type = type;
1266 ev->transport_handle = iscsi_handle(transport);
1267 switch (type) {
1268 case ISCSI_KEVENT_PATH_REQ:
1269 ev->r.req_path.host_no = shost->host_no;
1270 break;
1271 case ISCSI_KEVENT_IF_DOWN:
1272 ev->r.notify_if_down.host_no = shost->host_no;
1273 break;
1274 }
1275
1276 memcpy((char *)ev + sizeof(*ev), data, data_size);
1277
a541f840 1278 return iscsi_multicast_skb(skb, ISCSI_NL_GRP_UIP, GFP_ATOMIC);
43514774
MC
1279}
1280EXPORT_SYMBOL_GPL(iscsi_offload_mesg);
1281
e5bd7b54 1282void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
1da177e4 1283{
0896b752
AA
1284 struct nlmsghdr *nlh;
1285 struct sk_buff *skb;
1286 struct iscsi_uevent *ev;
790f39a2 1287 struct iscsi_internal *priv;
0896b752
AA
1288 int len = NLMSG_SPACE(sizeof(*ev));
1289
790f39a2
MC
1290 priv = iscsi_if_transport_lookup(conn->transport);
1291 if (!priv)
1292 return;
1293
43a145a3 1294 skb = alloc_skb(len, GFP_ATOMIC);
0896b752 1295 if (!skb) {
322d739d
MC
1296 iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
1297 "conn error (%d)\n", error);
0896b752
AA
1298 return;
1299 }
1300
43514774 1301 nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
0896b752
AA
1302 ev = NLMSG_DATA(nlh);
1303 ev->transport_handle = iscsi_handle(conn->transport);
1304 ev->type = ISCSI_KEVENT_CONN_ERROR;
0896b752 1305 ev->r.connerror.error = error;
b5c7a12d
MC
1306 ev->r.connerror.cid = conn->cid;
1307 ev->r.connerror.sid = iscsi_conn_get_sid(conn);
1da177e4 1308
43514774 1309 iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
1da177e4 1310
322d739d
MC
1311 iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)\n",
1312 error);
0896b752 1313}
e5bd7b54 1314EXPORT_SYMBOL_GPL(iscsi_conn_error_event);
0896b752
AA
1315
1316static int
43514774
MC
1317iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi,
1318 void *payload, int size)
0896b752
AA
1319{
1320 struct sk_buff *skb;
1321 struct nlmsghdr *nlh;
1322 int len = NLMSG_SPACE(size);
1323 int flags = multi ? NLM_F_MULTI : 0;
1324 int t = done ? NLMSG_DONE : type;
1325
43a145a3 1326 skb = alloc_skb(len, GFP_ATOMIC);
239a7dc2
MC
1327 if (!skb) {
1328 printk(KERN_ERR "Could not allocate skb to send reply.\n");
1329 return -ENOMEM;
1330 }
0896b752 1331
43514774 1332 nlh = __nlmsg_put(skb, 0, 0, t, (len - sizeof(*nlh)), 0);
0896b752
AA
1333 nlh->nlmsg_flags = flags;
1334 memcpy(NLMSG_DATA(nlh), payload, size);
43514774 1335 return iscsi_multicast_skb(skb, group, GFP_ATOMIC);
1da177e4 1336}
1da177e4 1337
7b8631b5 1338static int
5b940adf 1339iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
7b8631b5
MC
1340{
1341 struct iscsi_uevent *ev = NLMSG_DATA(nlh);
1342 struct iscsi_stats *stats;
1343 struct sk_buff *skbstat;
1344 struct iscsi_cls_conn *conn;
1345 struct nlmsghdr *nlhstat;
1346 struct iscsi_uevent *evstat;
790f39a2 1347 struct iscsi_internal *priv;
7b8631b5
MC
1348 int len = NLMSG_SPACE(sizeof(*ev) +
1349 sizeof(struct iscsi_stats) +
1350 sizeof(struct iscsi_stats_custom) *
1351 ISCSI_STATS_CUSTOM_MAX);
1352 int err = 0;
0896b752 1353
790f39a2
MC
1354 priv = iscsi_if_transport_lookup(transport);
1355 if (!priv)
1356 return -EINVAL;
1357
b5c7a12d 1358 conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid);
7b8631b5
MC
1359 if (!conn)
1360 return -EEXIST;
0896b752 1361
7b8631b5
MC
1362 do {
1363 int actual_size;
0896b752 1364
43a145a3 1365 skbstat = alloc_skb(len, GFP_ATOMIC);
7b8631b5 1366 if (!skbstat) {
322d739d
MC
1367 iscsi_cls_conn_printk(KERN_ERR, conn, "can not "
1368 "deliver stats: OOM\n");
7b8631b5
MC
1369 return -ENOMEM;
1370 }
1371
43514774 1372 nlhstat = __nlmsg_put(skbstat, 0, 0, 0,
7b8631b5
MC
1373 (len - sizeof(*nlhstat)), 0);
1374 evstat = NLMSG_DATA(nlhstat);
1375 memset(evstat, 0, sizeof(*evstat));
1376 evstat->transport_handle = iscsi_handle(conn->transport);
1377 evstat->type = nlh->nlmsg_type;
b5c7a12d
MC
1378 evstat->u.get_stats.cid =
1379 ev->u.get_stats.cid;
1380 evstat->u.get_stats.sid =
1381 ev->u.get_stats.sid;
7b8631b5
MC
1382 stats = (struct iscsi_stats *)
1383 ((char*)evstat + sizeof(*evstat));
1384 memset(stats, 0, sizeof(*stats));
1385
7b7232f3 1386 transport->get_stats(conn, stats);
7b8631b5
MC
1387 actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
1388 sizeof(struct iscsi_stats) +
1389 sizeof(struct iscsi_stats_custom) *
1390 stats->custom_length);
1391 actual_size -= sizeof(*nlhstat);
1392 actual_size = NLMSG_LENGTH(actual_size);
5b940adf 1393 skb_trim(skbstat, NLMSG_ALIGN(actual_size));
7b8631b5
MC
1394 nlhstat->nlmsg_len = actual_size;
1395
43514774
MC
1396 err = iscsi_multicast_skb(skbstat, ISCSI_NL_GRP_ISCSID,
1397 GFP_ATOMIC);
7b8631b5
MC
1398 } while (err < 0 && err != -ECONNREFUSED);
1399
1400 return err;
0896b752
AA
1401}
1402
53cb8a1f 1403/**
26974789
MC
1404 * iscsi_session_event - send session destr. completion event
1405 * @session: iscsi class session
1406 * @event: type of event
eb44820c 1407 */
26974789
MC
1408int iscsi_session_event(struct iscsi_cls_session *session,
1409 enum iscsi_uevent_e event)
53cb8a1f
MC
1410{
1411 struct iscsi_internal *priv;
53cb8a1f
MC
1412 struct Scsi_Host *shost;
1413 struct iscsi_uevent *ev;
1414 struct sk_buff *skb;
1415 struct nlmsghdr *nlh;
53cb8a1f
MC
1416 int rc, len = NLMSG_SPACE(sizeof(*ev));
1417
26974789 1418 priv = iscsi_if_transport_lookup(session->transport);
53cb8a1f
MC
1419 if (!priv)
1420 return -EINVAL;
53cb8a1f
MC
1421 shost = iscsi_session_to_shost(session);
1422
43a145a3 1423 skb = alloc_skb(len, GFP_KERNEL);
53cb8a1f 1424 if (!skb) {
322d739d
MC
1425 iscsi_cls_session_printk(KERN_ERR, session,
1426 "Cannot notify userspace of session "
1427 "event %u\n", event);
53cb8a1f
MC
1428 return -ENOMEM;
1429 }
1430
43514774 1431 nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
53cb8a1f 1432 ev = NLMSG_DATA(nlh);
26974789 1433 ev->transport_handle = iscsi_handle(session->transport);
53cb8a1f 1434
26974789
MC
1435 ev->type = event;
1436 switch (event) {
1437 case ISCSI_KEVENT_DESTROY_SESSION:
1438 ev->r.d_session.host_no = shost->host_no;
1439 ev->r.d_session.sid = session->sid;
1440 break;
1441 case ISCSI_KEVENT_CREATE_SESSION:
1442 ev->r.c_session_ret.host_no = shost->host_no;
1443 ev->r.c_session_ret.sid = session->sid;
1444 break;
1445 case ISCSI_KEVENT_UNBIND_SESSION:
1446 ev->r.unbind_session.host_no = shost->host_no;
1447 ev->r.unbind_session.sid = session->sid;
1448 break;
1449 default:
322d739d
MC
1450 iscsi_cls_session_printk(KERN_ERR, session, "Invalid event "
1451 "%u.\n", event);
26974789 1452 kfree_skb(skb);
53cb8a1f 1453 return -EINVAL;
53cb8a1f
MC
1454 }
1455
53cb8a1f
MC
1456 /*
1457 * this will occur if the daemon is not up, so we just warn
1458 * the user and when the daemon is restarted it will handle it
1459 */
43514774 1460 rc = iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_KERNEL);
ff491a73 1461 if (rc == -ESRCH)
322d739d
MC
1462 iscsi_cls_session_printk(KERN_ERR, session,
1463 "Cannot notify userspace of session "
1464 "event %u. Check iscsi daemon\n",
1465 event);
632248aa
MC
1466
1467 ISCSI_DBG_TRANS_SESSION(session, "Completed handling event %d rc %d\n",
1468 event, rc);
53cb8a1f
MC
1469 return rc;
1470}
26974789 1471EXPORT_SYMBOL_GPL(iscsi_session_event);
53cb8a1f 1472
0896b752 1473static int
d82ff9be
MC
1474iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep,
1475 struct iscsi_uevent *ev, uint32_t initial_cmdsn,
40753caa 1476 uint16_t cmds_max, uint16_t queue_depth)
0896b752
AA
1477{
1478 struct iscsi_transport *transport = priv->iscsi_transport;
7b7232f3 1479 struct iscsi_cls_session *session;
5e7facb7 1480 struct Scsi_Host *shost;
0896b752 1481
d82ff9be 1482 session = transport->create_session(ep, cmds_max, queue_depth,
5e7facb7 1483 initial_cmdsn);
7b7232f3 1484 if (!session)
7b8631b5 1485 return -ENOMEM;
0896b752 1486
5e7facb7
MC
1487 shost = iscsi_session_to_shost(session);
1488 ev->r.c_session_ret.host_no = shost->host_no;
b5c7a12d 1489 ev->r.c_session_ret.sid = session->sid;
632248aa
MC
1490 ISCSI_DBG_TRANS_SESSION(session,
1491 "Completed creating transport session\n");
0896b752 1492 return 0;
0896b752
AA
1493}
1494
1495static int
7b7232f3 1496iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
0896b752 1497{
7b8631b5 1498 struct iscsi_cls_conn *conn;
7b7232f3 1499 struct iscsi_cls_session *session;
7b8631b5 1500
b5c7a12d
MC
1501 session = iscsi_session_lookup(ev->u.c_conn.sid);
1502 if (!session) {
322d739d 1503 printk(KERN_ERR "iscsi: invalid session %d.\n",
b5c7a12d 1504 ev->u.c_conn.sid);
7b8631b5 1505 return -EINVAL;
b5c7a12d 1506 }
0896b752 1507
7b7232f3 1508 conn = transport->create_conn(session, ev->u.c_conn.cid);
b5c7a12d 1509 if (!conn) {
322d739d
MC
1510 iscsi_cls_session_printk(KERN_ERR, session,
1511 "couldn't create a new connection.");
7b7232f3 1512 return -ENOMEM;
b5c7a12d 1513 }
0896b752 1514
b5c7a12d
MC
1515 ev->r.c_conn_ret.sid = session->sid;
1516 ev->r.c_conn_ret.cid = conn->cid;
632248aa
MC
1517
1518 ISCSI_DBG_TRANS_CONN(conn, "Completed creating transport conn\n");
0896b752 1519 return 0;
1da177e4
LT
1520}
1521
0896b752
AA
1522static int
1523iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
1524{
7b8631b5 1525 struct iscsi_cls_conn *conn;
0896b752 1526
b5c7a12d 1527 conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
0896b752 1528 if (!conn)
7b8631b5 1529 return -EINVAL;
0896b752 1530
632248aa 1531 ISCSI_DBG_TRANS_CONN(conn, "Destroying transport conn\n");
7b8631b5
MC
1532 if (transport->destroy_conn)
1533 transport->destroy_conn(conn);
632248aa 1534
7b8631b5 1535 return 0;
0896b752
AA
1536}
1537
fd7255f5
MC
1538static int
1539iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
1540{
1541 char *data = (char*)ev + sizeof(*ev);
1542 struct iscsi_cls_conn *conn;
1543 struct iscsi_cls_session *session;
a54a52ca 1544 int err = 0, value = 0;
fd7255f5
MC
1545
1546 session = iscsi_session_lookup(ev->u.set_param.sid);
1547 conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
1548 if (!conn || !session)
1549 return -EINVAL;
1550
1551 switch (ev->u.set_param.param) {
30a6c652 1552 case ISCSI_PARAM_SESS_RECOVERY_TMO:
a54a52ca 1553 sscanf(data, "%d", &value);
fdd46dcb 1554 session->recovery_tmo = value;
30a6c652 1555 break;
fd7255f5 1556 default:
a54a52ca
MC
1557 err = transport->set_param(conn, ev->u.set_param.param,
1558 data, ev->u.set_param.len);
fd7255f5
MC
1559 }
1560
1561 return err;
1562}
1563
10eb0f01
MC
1564static int iscsi_if_ep_connect(struct iscsi_transport *transport,
1565 struct iscsi_uevent *ev, int msg_type)
1566{
1567 struct iscsi_endpoint *ep;
1568 struct sockaddr *dst_addr;
1569 struct Scsi_Host *shost = NULL;
1570 int non_blocking, err = 0;
1571
1572 if (!transport->ep_connect)
1573 return -EINVAL;
1574
1575 if (msg_type == ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST) {
1576 shost = scsi_host_lookup(ev->u.ep_connect_through_host.host_no);
1577 if (!shost) {
1578 printk(KERN_ERR "ep connect failed. Could not find "
1579 "host no %u\n",
1580 ev->u.ep_connect_through_host.host_no);
1581 return -ENODEV;
1582 }
1583 non_blocking = ev->u.ep_connect_through_host.non_blocking;
1584 } else
1585 non_blocking = ev->u.ep_connect.non_blocking;
1586
1587 dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
1588 ep = transport->ep_connect(shost, dst_addr, non_blocking);
1589 if (IS_ERR(ep)) {
1590 err = PTR_ERR(ep);
1591 goto release_host;
1592 }
1593
1594 ev->r.ep_connect_ret.handle = ep->id;
1595release_host:
1596 if (shost)
1597 scsi_host_put(shost);
1598 return err;
1599}
1600
22a39fbb
MC
1601static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
1602 u64 ep_handle)
1603{
1604 struct iscsi_cls_conn *conn;
1605 struct iscsi_endpoint *ep;
1606
1607 if (!transport->ep_disconnect)
1608 return -EINVAL;
1609
1610 ep = iscsi_lookup_endpoint(ep_handle);
1611 if (!ep)
1612 return -EINVAL;
1613 conn = ep->conn;
1614 if (conn) {
1615 mutex_lock(&conn->ep_mutex);
1616 conn->ep = NULL;
1617 mutex_unlock(&conn->ep_mutex);
1618 }
1619
1620 transport->ep_disconnect(ep);
1621 return 0;
1622}
1623
264faaaa
OG
1624static int
1625iscsi_if_transport_ep(struct iscsi_transport *transport,
1626 struct iscsi_uevent *ev, int msg_type)
1627{
d82ff9be 1628 struct iscsi_endpoint *ep;
264faaaa
OG
1629 int rc = 0;
1630
1631 switch (msg_type) {
10eb0f01 1632 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
264faaaa 1633 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
10eb0f01 1634 rc = iscsi_if_ep_connect(transport, ev, msg_type);
264faaaa
OG
1635 break;
1636 case ISCSI_UEVENT_TRANSPORT_EP_POLL:
1637 if (!transport->ep_poll)
1638 return -EINVAL;
1639
d82ff9be
MC
1640 ep = iscsi_lookup_endpoint(ev->u.ep_poll.ep_handle);
1641 if (!ep)
1642 return -EINVAL;
1643
1644 ev->r.retcode = transport->ep_poll(ep,
264faaaa
OG
1645 ev->u.ep_poll.timeout_ms);
1646 break;
1647 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
22a39fbb
MC
1648 rc = iscsi_if_ep_disconnect(transport,
1649 ev->u.ep_disconnect.ep_handle);
264faaaa
OG
1650 break;
1651 }
1652 return rc;
1653}
1654
01cb225d
MC
1655static int
1656iscsi_tgt_dscvr(struct iscsi_transport *transport,
1657 struct iscsi_uevent *ev)
1658{
2174a04e 1659 struct Scsi_Host *shost;
01cb225d 1660 struct sockaddr *dst_addr;
2174a04e 1661 int err;
01cb225d
MC
1662
1663 if (!transport->tgt_dscvr)
1664 return -EINVAL;
1665
2174a04e 1666 shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no);
315cb0ad 1667 if (!shost) {
2174a04e
MC
1668 printk(KERN_ERR "target discovery could not find host no %u\n",
1669 ev->u.tgt_dscvr.host_no);
1670 return -ENODEV;
1671 }
1672
1673
01cb225d 1674 dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
2174a04e
MC
1675 err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type,
1676 ev->u.tgt_dscvr.enable, dst_addr);
1677 scsi_host_put(shost);
1678 return err;
01cb225d
MC
1679}
1680
1d9bf13a
MC
1681static int
1682iscsi_set_host_param(struct iscsi_transport *transport,
1683 struct iscsi_uevent *ev)
1684{
1685 char *data = (char*)ev + sizeof(*ev);
1686 struct Scsi_Host *shost;
1687 int err;
1688
1689 if (!transport->set_host_param)
1690 return -ENOSYS;
1691
1692 shost = scsi_host_lookup(ev->u.set_host_param.host_no);
315cb0ad 1693 if (!shost) {
1d9bf13a
MC
1694 printk(KERN_ERR "set_host_param could not find host no %u\n",
1695 ev->u.set_host_param.host_no);
1696 return -ENODEV;
1697 }
1698
1699 err = transport->set_host_param(shost, ev->u.set_host_param.param,
1700 data, ev->u.set_host_param.len);
1701 scsi_host_put(shost);
1702 return err;
1703}
1704
0896b752 1705static int
43514774
MC
1706iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
1707{
1708 struct Scsi_Host *shost;
1709 struct iscsi_path *params;
1710 int err;
1711
1712 if (!transport->set_path)
1713 return -ENOSYS;
1714
1715 shost = scsi_host_lookup(ev->u.set_path.host_no);
1716 if (!shost) {
1717 printk(KERN_ERR "set path could not find host no %u\n",
1718 ev->u.set_path.host_no);
1719 return -ENODEV;
1720 }
1721
1722 params = (struct iscsi_path *)((char *)ev + sizeof(*ev));
1723 err = transport->set_path(shost, params);
1724
1725 scsi_host_put(shost);
1726 return err;
1727}
1728
56c155b5
MC
1729static int
1730iscsi_set_iface_params(struct iscsi_transport *transport,
1731 struct iscsi_uevent *ev)
1732{
1733 char *data = (char *)ev + sizeof(*ev);
1734 struct Scsi_Host *shost;
1735 int err;
1736
1737 if (!transport->set_iface_param)
1738 return -ENOSYS;
1739
1740 shost = scsi_host_lookup(ev->u.set_iface_params.host_no);
1741 if (!shost) {
1742 printk(KERN_ERR "set_iface_params could not find host no %u\n",
1743 ev->u.set_iface_params.host_no);
1744 return -ENODEV;
1745 }
1746
1747 err = transport->set_iface_param(shost, data,
1748 ev->u.set_iface_params.count);
1749 scsi_host_put(shost);
1750 return err;
1751}
1752
43514774
MC
1753static int
1754iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
0896b752
AA
1755{
1756 int err = 0;
1757 struct iscsi_uevent *ev = NLMSG_DATA(nlh);
1758 struct iscsi_transport *transport = NULL;
1759 struct iscsi_internal *priv;
7b7232f3
MC
1760 struct iscsi_cls_session *session;
1761 struct iscsi_cls_conn *conn;
d82ff9be 1762 struct iscsi_endpoint *ep = NULL;
0896b752 1763
43514774
MC
1764 if (nlh->nlmsg_type == ISCSI_UEVENT_PATH_UPDATE)
1765 *group = ISCSI_NL_GRP_UIP;
1766 else
1767 *group = ISCSI_NL_GRP_ISCSID;
1768
0896b752
AA
1769 priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
1770 if (!priv)
1771 return -EINVAL;
1772 transport = priv->iscsi_transport;
1773
7b7232f3
MC
1774 if (!try_module_get(transport->owner))
1775 return -EINVAL;
1776
0896b752
AA
1777 switch (nlh->nlmsg_type) {
1778 case ISCSI_UEVENT_CREATE_SESSION:
d82ff9be 1779 err = iscsi_if_create_session(priv, ep, ev,
40753caa
MC
1780 ev->u.c_session.initial_cmdsn,
1781 ev->u.c_session.cmds_max,
1782 ev->u.c_session.queue_depth);
1783 break;
1784 case ISCSI_UEVENT_CREATE_BOUND_SESSION:
d82ff9be 1785 ep = iscsi_lookup_endpoint(ev->u.c_bound_session.ep_handle);
c95fddc7
MC
1786 if (!ep) {
1787 err = -EINVAL;
1788 break;
1789 }
d82ff9be
MC
1790
1791 err = iscsi_if_create_session(priv, ep, ev,
40753caa
MC
1792 ev->u.c_bound_session.initial_cmdsn,
1793 ev->u.c_bound_session.cmds_max,
1794 ev->u.c_bound_session.queue_depth);
0896b752
AA
1795 break;
1796 case ISCSI_UEVENT_DESTROY_SESSION:
b5c7a12d 1797 session = iscsi_session_lookup(ev->u.d_session.sid);
26974789 1798 if (session)
7b7232f3 1799 transport->destroy_session(session);
26974789
MC
1800 else
1801 err = -EINVAL;
1802 break;
1803 case ISCSI_UEVENT_UNBIND_SESSION:
1804 session = iscsi_session_lookup(ev->u.d_session.sid);
1805 if (session)
06d25af4
MC
1806 scsi_queue_work(iscsi_session_to_shost(session),
1807 &session->unbind_work);
26974789 1808 else
7b7232f3 1809 err = -EINVAL;
0896b752
AA
1810 break;
1811 case ISCSI_UEVENT_CREATE_CONN:
1812 err = iscsi_if_create_conn(transport, ev);
1813 break;
1814 case ISCSI_UEVENT_DESTROY_CONN:
1815 err = iscsi_if_destroy_conn(transport, ev);
1816 break;
1817 case ISCSI_UEVENT_BIND_CONN:
b5c7a12d
MC
1818 session = iscsi_session_lookup(ev->u.b_conn.sid);
1819 conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
7b7232f3 1820
22a39fbb
MC
1821 if (conn && conn->ep)
1822 iscsi_if_ep_disconnect(transport, conn->ep->id);
1823
1824 if (!session || !conn) {
7b7232f3 1825 err = -EINVAL;
22a39fbb
MC
1826 break;
1827 }
1828
1829 ev->r.retcode = transport->bind_conn(session, conn,
1830 ev->u.b_conn.transport_eph,
1831 ev->u.b_conn.is_leading);
1832 if (ev->r.retcode || !transport->ep_connect)
1833 break;
1834
1835 ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
1836 if (ep) {
1837 ep->conn = conn;
1838
1839 mutex_lock(&conn->ep_mutex);
1840 conn->ep = ep;
1841 mutex_unlock(&conn->ep_mutex);
1842 } else
1843 iscsi_cls_conn_printk(KERN_ERR, conn,
1844 "Could not set ep conn "
1845 "binding\n");
0896b752
AA
1846 break;
1847 case ISCSI_UEVENT_SET_PARAM:
fd7255f5 1848 err = iscsi_set_param(transport, ev);
0896b752
AA
1849 break;
1850 case ISCSI_UEVENT_START_CONN:
b5c7a12d 1851 conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
7b7232f3
MC
1852 if (conn)
1853 ev->r.retcode = transport->start_conn(conn);
1854 else
1855 err = -EINVAL;
0896b752
AA
1856 break;
1857 case ISCSI_UEVENT_STOP_CONN:
b5c7a12d 1858 conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
7b7232f3
MC
1859 if (conn)
1860 transport->stop_conn(conn, ev->u.stop_conn.flag);
1861 else
1862 err = -EINVAL;
0896b752
AA
1863 break;
1864 case ISCSI_UEVENT_SEND_PDU:
b5c7a12d 1865 conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
7b7232f3
MC
1866 if (conn)
1867 ev->r.retcode = transport->send_pdu(conn,
1868 (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
1869 (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
1870 ev->u.send_pdu.data_size);
1871 else
1872 err = -EINVAL;
0896b752
AA
1873 break;
1874 case ISCSI_UEVENT_GET_STATS:
5b940adf 1875 err = iscsi_if_get_stats(transport, nlh);
0896b752 1876 break;
264faaaa
OG
1877 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
1878 case ISCSI_UEVENT_TRANSPORT_EP_POLL:
1879 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
10eb0f01 1880 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
264faaaa
OG
1881 err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
1882 break;
01cb225d
MC
1883 case ISCSI_UEVENT_TGT_DSCVR:
1884 err = iscsi_tgt_dscvr(transport, ev);
1885 break;
1d9bf13a
MC
1886 case ISCSI_UEVENT_SET_HOST_PARAM:
1887 err = iscsi_set_host_param(transport, ev);
1888 break;
43514774
MC
1889 case ISCSI_UEVENT_PATH_UPDATE:
1890 err = iscsi_set_path(transport, ev);
1891 break;
56c155b5
MC
1892 case ISCSI_UEVENT_SET_IFACE_PARAMS:
1893 err = iscsi_set_iface_params(transport, ev);
1894 break;
0896b752 1895 default:
1d9bf13a 1896 err = -ENOSYS;
0896b752
AA
1897 break;
1898 }
1899
7b7232f3 1900 module_put(transport->owner);
0896b752
AA
1901 return err;
1902}
1903
b5c7a12d 1904/*
cd40b7d3
DL
1905 * Get message from skb. Each message is processed by iscsi_if_recv_msg.
1906 * Malformed skbs with wrong lengths or invalid creds are not processed.
b5c7a12d 1907 */
0896b752 1908static void
cd40b7d3 1909iscsi_if_rx(struct sk_buff *skb)
0896b752 1910{
0b950672 1911 mutex_lock(&rx_queue_mutex);
cd40b7d3
DL
1912 while (skb->len >= NLMSG_SPACE(0)) {
1913 int err;
1914 uint32_t rlen;
1915 struct nlmsghdr *nlh;
1916 struct iscsi_uevent *ev;
43514774 1917 uint32_t group;
cd40b7d3
DL
1918
1919 nlh = nlmsg_hdr(skb);
1920 if (nlh->nlmsg_len < sizeof(*nlh) ||
1921 skb->len < nlh->nlmsg_len) {
1922 break;
ee7f8e40 1923 }
ee7f8e40 1924
cd40b7d3
DL
1925 ev = NLMSG_DATA(nlh);
1926 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
1927 if (rlen > skb->len)
1928 rlen = skb->len;
0896b752 1929
43514774 1930 err = iscsi_if_recv_msg(skb, nlh, &group);
cd40b7d3
DL
1931 if (err) {
1932 ev->type = ISCSI_KEVENT_IF_ERROR;
1933 ev->iferror = err;
0896b752 1934 }
cd40b7d3
DL
1935 do {
1936 /*
1937 * special case for GET_STATS:
1938 * on success - sending reply and stats from
1939 * inside of if_recv_msg(),
1940 * on error - fall through.
1941 */
1942 if (ev->type == ISCSI_UEVENT_GET_STATS && !err)
1943 break;
43514774 1944 err = iscsi_if_send_reply(group, nlh->nlmsg_seq,
cd40b7d3
DL
1945 nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
1946 } while (err < 0 && err != -ECONNREFUSED);
1947 skb_pull(skb, rlen);
0896b752 1948 }
0b950672 1949 mutex_unlock(&rx_queue_mutex);
0896b752 1950}
1da177e4 1951
fd7255f5 1952#define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store) \
ee959b00 1953struct device_attribute dev_attr_##_prefix##_##_name = \
fd7255f5
MC
1954 __ATTR(_name,_mode,_show,_store)
1955
1da177e4 1956/*
0896b752 1957 * iSCSI connection attrs
1da177e4 1958 */
a54a52ca 1959#define iscsi_conn_attr_show(param) \
0896b752 1960static ssize_t \
ee959b00
TJ
1961show_conn_param_##param(struct device *dev, \
1962 struct device_attribute *attr, char *buf) \
0896b752 1963{ \
ee959b00 1964 struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent); \
7b8631b5 1965 struct iscsi_transport *t = conn->transport; \
a54a52ca 1966 return t->get_conn_param(conn, param, buf); \
0896b752
AA
1967}
1968
a54a52ca
MC
1969#define iscsi_conn_attr(field, param) \
1970 iscsi_conn_attr_show(param) \
1971static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_param_##param, \
fd7255f5 1972 NULL);
0896b752 1973
a54a52ca
MC
1974iscsi_conn_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH);
1975iscsi_conn_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH);
1976iscsi_conn_attr(header_digest, ISCSI_PARAM_HDRDGST_EN);
1977iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN);
1978iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN);
1979iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN);
1980iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT);
a54a52ca
MC
1981iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
1982iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
f6d5180c
MC
1983iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
1984iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
1da177e4 1985
289324b0
MC
1986#define iscsi_conn_ep_attr_show(param) \
1987static ssize_t show_conn_ep_param_##param(struct device *dev, \
1988 struct device_attribute *attr,\
1989 char *buf) \
1990{ \
1991 struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent); \
1992 struct iscsi_transport *t = conn->transport; \
1993 struct iscsi_endpoint *ep; \
1994 ssize_t rc; \
1995 \
1996 /* \
1997 * Need to make sure ep_disconnect does not free the LLD's \
1998 * interconnect resources while we are trying to read them. \
1999 */ \
2000 mutex_lock(&conn->ep_mutex); \
2001 ep = conn->ep; \
2002 if (!ep && t->ep_connect) { \
2003 mutex_unlock(&conn->ep_mutex); \
2004 return -ENOTCONN; \
2005 } \
2006 \
2007 if (ep) \
2008 rc = t->get_ep_param(ep, param, buf); \
2009 else \
2010 rc = t->get_conn_param(conn, param, buf); \
2011 mutex_unlock(&conn->ep_mutex); \
2012 return rc; \
2013}
2014
2015#define iscsi_conn_ep_attr(field, param) \
2016 iscsi_conn_ep_attr_show(param) \
2017static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, \
2018 show_conn_ep_param_##param, NULL);
2019
2020iscsi_conn_ep_attr(address, ISCSI_PARAM_CONN_ADDRESS);
2021iscsi_conn_ep_attr(port, ISCSI_PARAM_CONN_PORT);
2022
3128c6c7
MC
2023static struct attribute *iscsi_conn_attrs[] = {
2024 &dev_attr_conn_max_recv_dlength.attr,
2025 &dev_attr_conn_max_xmit_dlength.attr,
2026 &dev_attr_conn_header_digest.attr,
2027 &dev_attr_conn_data_digest.attr,
2028 &dev_attr_conn_ifmarker.attr,
2029 &dev_attr_conn_ofmarker.attr,
2030 &dev_attr_conn_address.attr,
2031 &dev_attr_conn_port.attr,
2032 &dev_attr_conn_exp_statsn.attr,
2033 &dev_attr_conn_persistent_address.attr,
2034 &dev_attr_conn_persistent_port.attr,
2035 &dev_attr_conn_ping_tmo.attr,
2036 &dev_attr_conn_recv_tmo.attr,
2037 NULL,
2038};
2039
2040static mode_t iscsi_conn_attr_is_visible(struct kobject *kobj,
2041 struct attribute *attr, int i)
2042{
2043 struct device *cdev = container_of(kobj, struct device, kobj);
2044 struct iscsi_cls_conn *conn = transport_class_to_conn(cdev);
2045 struct iscsi_transport *t = conn->transport;
2046 int param;
2047
2048 if (attr == &dev_attr_conn_max_recv_dlength.attr)
2049 param = ISCSI_PARAM_MAX_RECV_DLENGTH;
2050 else if (attr == &dev_attr_conn_max_xmit_dlength.attr)
2051 param = ISCSI_PARAM_MAX_XMIT_DLENGTH;
2052 else if (attr == &dev_attr_conn_header_digest.attr)
2053 param = ISCSI_PARAM_HDRDGST_EN;
2054 else if (attr == &dev_attr_conn_data_digest.attr)
2055 param = ISCSI_PARAM_DATADGST_EN;
2056 else if (attr == &dev_attr_conn_ifmarker.attr)
2057 param = ISCSI_PARAM_IFMARKER_EN;
2058 else if (attr == &dev_attr_conn_ofmarker.attr)
2059 param = ISCSI_PARAM_OFMARKER_EN;
2060 else if (attr == &dev_attr_conn_address.attr)
2061 param = ISCSI_PARAM_CONN_ADDRESS;
2062 else if (attr == &dev_attr_conn_port.attr)
2063 param = ISCSI_PARAM_CONN_PORT;
2064 else if (attr == &dev_attr_conn_exp_statsn.attr)
2065 param = ISCSI_PARAM_EXP_STATSN;
2066 else if (attr == &dev_attr_conn_persistent_address.attr)
2067 param = ISCSI_PARAM_PERSISTENT_ADDRESS;
2068 else if (attr == &dev_attr_conn_persistent_port.attr)
2069 param = ISCSI_PARAM_PERSISTENT_PORT;
2070 else if (attr == &dev_attr_conn_ping_tmo.attr)
2071 param = ISCSI_PARAM_PING_TMO;
2072 else if (attr == &dev_attr_conn_recv_tmo.attr)
2073 param = ISCSI_PARAM_RECV_TMO;
2074 else {
2075 WARN_ONCE(1, "Invalid conn attr");
2076 return 0;
2077 }
2078
2079 return t->attr_is_visible(ISCSI_PARAM, param);
2080}
2081
2082static struct attribute_group iscsi_conn_group = {
2083 .attrs = iscsi_conn_attrs,
2084 .is_visible = iscsi_conn_attr_is_visible,
2085};
2086
1da177e4 2087/*
0896b752 2088 * iSCSI session attrs
1da177e4 2089 */
b2c64167 2090#define iscsi_session_attr_show(param, perm) \
fd7255f5 2091static ssize_t \
ee959b00
TJ
2092show_session_param_##param(struct device *dev, \
2093 struct device_attribute *attr, char *buf) \
fd7255f5 2094{ \
ee959b00
TJ
2095 struct iscsi_cls_session *session = \
2096 iscsi_dev_to_session(dev->parent); \
fd7255f5 2097 struct iscsi_transport *t = session->transport; \
b2c64167
MC
2098 \
2099 if (perm && !capable(CAP_SYS_ADMIN)) \
2100 return -EACCES; \
a54a52ca 2101 return t->get_session_param(session, param, buf); \
fd7255f5
MC
2102}
2103
b2c64167
MC
2104#define iscsi_session_attr(field, param, perm) \
2105 iscsi_session_attr_show(param, perm) \
a54a52ca 2106static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
fd7255f5 2107 NULL);
b2c64167
MC
2108iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
2109iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
2110iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
2111iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, 0);
2112iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, 0);
2113iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, 0);
2114iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, 0);
2115iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, 0);
2116iscsi_session_attr(erl, ISCSI_PARAM_ERL, 0);
2117iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT, 0);
2118iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
2119iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
2120iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
2121iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
4cd49ea1
MC
2122iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);
2123iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
2124iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
3fe5ae8b 2125iscsi_session_attr(tgt_reset_tmo, ISCSI_PARAM_TGT_RESET_TMO, 0);
88dfd340 2126iscsi_session_attr(ifacename, ISCSI_PARAM_IFACE_NAME, 0);
3b2bef1f
VC
2127iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0);
2128iscsi_session_attr(targetalias, ISCSI_PARAM_TARGET_ALIAS, 0);
1da177e4 2129
6eabafbe 2130static ssize_t
ee959b00
TJ
2131show_priv_session_state(struct device *dev, struct device_attribute *attr,
2132 char *buf)
6eabafbe 2133{
ee959b00 2134 struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
6eabafbe
MC
2135 return sprintf(buf, "%s\n", iscsi_session_state_name(session->state));
2136}
2137static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
2138 NULL);
2139
fd7255f5
MC
2140#define iscsi_priv_session_attr_show(field, format) \
2141static ssize_t \
ee959b00
TJ
2142show_priv_session_##field(struct device *dev, \
2143 struct device_attribute *attr, char *buf) \
fd7255f5 2144{ \
ee959b00
TJ
2145 struct iscsi_cls_session *session = \
2146 iscsi_dev_to_session(dev->parent); \
fe4f0bde
VC
2147 if (session->field == -1) \
2148 return sprintf(buf, "off\n"); \
fd7255f5
MC
2149 return sprintf(buf, format"\n", session->field); \
2150}
2151
fe4f0bde
VC
2152#define iscsi_priv_session_attr_store(field) \
2153static ssize_t \
2154store_priv_session_##field(struct device *dev, \
2155 struct device_attribute *attr, \
2156 const char *buf, size_t count) \
2157{ \
2158 int val; \
2159 char *cp; \
2160 struct iscsi_cls_session *session = \
2161 iscsi_dev_to_session(dev->parent); \
2162 if ((session->state == ISCSI_SESSION_FREE) || \
2163 (session->state == ISCSI_SESSION_FAILED)) \
2164 return -EBUSY; \
2165 if (strncmp(buf, "off", 3) == 0) \
2166 session->field = -1; \
2167 else { \
2168 val = simple_strtoul(buf, &cp, 0); \
2169 if (*cp != '\0' && *cp != '\n') \
2170 return -EINVAL; \
2171 session->field = val; \
2172 } \
2173 return count; \
2174}
2175
2176#define iscsi_priv_session_rw_attr(field, format) \
fd7255f5 2177 iscsi_priv_session_attr_show(field, format) \
fe4f0bde 2178 iscsi_priv_session_attr_store(field) \
523f3c80 2179static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUSR, \
fe4f0bde
VC
2180 show_priv_session_##field, \
2181 store_priv_session_##field)
2182iscsi_priv_session_rw_attr(recovery_tmo, "%d");
fd7255f5 2183
1d063c17
MC
2184static struct attribute *iscsi_session_attrs[] = {
2185 &dev_attr_sess_initial_r2t.attr,
2186 &dev_attr_sess_max_outstanding_r2t.attr,
2187 &dev_attr_sess_immediate_data.attr,
2188 &dev_attr_sess_first_burst_len.attr,
2189 &dev_attr_sess_max_burst_len.attr,
2190 &dev_attr_sess_data_pdu_in_order.attr,
2191 &dev_attr_sess_data_seq_in_order.attr,
2192 &dev_attr_sess_erl.attr,
2193 &dev_attr_sess_targetname.attr,
2194 &dev_attr_sess_tpgt.attr,
2195 &dev_attr_sess_password.attr,
2196 &dev_attr_sess_password_in.attr,
2197 &dev_attr_sess_username.attr,
2198 &dev_attr_sess_username_in.attr,
2199 &dev_attr_sess_fast_abort.attr,
2200 &dev_attr_sess_abort_tmo.attr,
2201 &dev_attr_sess_lu_reset_tmo.attr,
2202 &dev_attr_sess_tgt_reset_tmo.attr,
2203 &dev_attr_sess_ifacename.attr,
2204 &dev_attr_sess_initiatorname.attr,
2205 &dev_attr_sess_targetalias.attr,
2206 &dev_attr_priv_sess_recovery_tmo.attr,
2207 &dev_attr_priv_sess_state.attr,
2208 NULL,
2209};
2210
2211static mode_t iscsi_session_attr_is_visible(struct kobject *kobj,
2212 struct attribute *attr, int i)
2213{
2214 struct device *cdev = container_of(kobj, struct device, kobj);
2215 struct iscsi_cls_session *session = transport_class_to_session(cdev);
2216 struct iscsi_transport *t = session->transport;
2217 int param;
2218
2219 if (attr == &dev_attr_sess_initial_r2t.attr)
2220 param = ISCSI_PARAM_INITIAL_R2T_EN;
2221 else if (attr == &dev_attr_sess_max_outstanding_r2t.attr)
2222 param = ISCSI_PARAM_MAX_R2T;
2223 else if (attr == &dev_attr_sess_immediate_data.attr)
2224 param = ISCSI_PARAM_IMM_DATA_EN;
2225 else if (attr == &dev_attr_sess_first_burst_len.attr)
2226 param = ISCSI_PARAM_FIRST_BURST;
2227 else if (attr == &dev_attr_sess_max_burst_len.attr)
2228 param = ISCSI_PARAM_MAX_BURST;
2229 else if (attr == &dev_attr_sess_data_pdu_in_order.attr)
2230 param = ISCSI_PARAM_PDU_INORDER_EN;
2231 else if (attr == &dev_attr_sess_data_seq_in_order.attr)
2232 param = ISCSI_PARAM_DATASEQ_INORDER_EN;
2233 else if (attr == &dev_attr_sess_erl.attr)
2234 param = ISCSI_PARAM_ERL;
2235 else if (attr == &dev_attr_sess_targetname.attr)
2236 param = ISCSI_PARAM_TARGET_NAME;
2237 else if (attr == &dev_attr_sess_tpgt.attr)
2238 param = ISCSI_PARAM_TPGT;
2239 else if (attr == &dev_attr_sess_password.attr)
2240 param = ISCSI_PARAM_USERNAME;
2241 else if (attr == &dev_attr_sess_password_in.attr)
2242 param = ISCSI_PARAM_USERNAME_IN;
2243 else if (attr == &dev_attr_sess_username.attr)
2244 param = ISCSI_PARAM_PASSWORD;
2245 else if (attr == &dev_attr_sess_username_in.attr)
2246 param = ISCSI_PARAM_PASSWORD_IN;
2247 else if (attr == &dev_attr_sess_fast_abort.attr)
2248 param = ISCSI_PARAM_FAST_ABORT;
2249 else if (attr == &dev_attr_sess_abort_tmo.attr)
2250 param = ISCSI_PARAM_ABORT_TMO;
2251 else if (attr == &dev_attr_sess_lu_reset_tmo.attr)
2252 param = ISCSI_PARAM_LU_RESET_TMO;
2253 else if (attr == &dev_attr_sess_tgt_reset_tmo.attr)
2254 param = ISCSI_PARAM_TGT_RESET_TMO;
2255 else if (attr == &dev_attr_sess_ifacename.attr)
2256 param = ISCSI_PARAM_IFACE_NAME;
2257 else if (attr == &dev_attr_sess_initiatorname.attr)
2258 param = ISCSI_PARAM_INITIATOR_NAME;
2259 else if (attr == &dev_attr_sess_targetalias.attr)
2260 param = ISCSI_PARAM_TARGET_ALIAS;
2261 else if (attr == &dev_attr_priv_sess_recovery_tmo.attr)
2262 return S_IRUGO | S_IWUSR;
2263 else if (attr == &dev_attr_priv_sess_state.attr)
2264 return S_IRUGO;
2265 else {
2266 WARN_ONCE(1, "Invalid session attr");
2267 return 0;
2268 }
2269
2270 return t->attr_is_visible(ISCSI_PARAM, param);
2271}
2272
2273static struct attribute_group iscsi_session_group = {
2274 .attrs = iscsi_session_attrs,
2275 .is_visible = iscsi_session_attr_is_visible,
2276};
2277
1819dc81
MC
2278/*
2279 * iSCSI host attrs
2280 */
2281#define iscsi_host_attr_show(param) \
2282static ssize_t \
ee959b00
TJ
2283show_host_param_##param(struct device *dev, \
2284 struct device_attribute *attr, char *buf) \
1819dc81 2285{ \
ee959b00 2286 struct Scsi_Host *shost = transport_class_to_shost(dev); \
1819dc81
MC
2287 struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
2288 return priv->iscsi_transport->get_host_param(shost, param, buf); \
2289}
2290
2291#define iscsi_host_attr(field, param) \
2292 iscsi_host_attr_show(param) \
2293static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param, \
2294 NULL);
2295
d8196ed2 2296iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME);
1819dc81 2297iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
d8196ed2 2298iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
8ad5781a 2299iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
1819dc81 2300
f27fb2ef
MC
2301static struct attribute *iscsi_host_attrs[] = {
2302 &dev_attr_host_netdev.attr,
2303 &dev_attr_host_hwaddress.attr,
2304 &dev_attr_host_ipaddress.attr,
2305 &dev_attr_host_initiatorname.attr,
2306 NULL,
2307};
2308
2309static mode_t iscsi_host_attr_is_visible(struct kobject *kobj,
2310 struct attribute *attr, int i)
2311{
2312 struct device *cdev = container_of(kobj, struct device, kobj);
2313 struct Scsi_Host *shost = transport_class_to_shost(cdev);
2314 struct iscsi_internal *priv = to_iscsi_internal(shost->transportt);
2315 int param;
2316
2317 if (attr == &dev_attr_host_netdev.attr)
2318 param = ISCSI_HOST_PARAM_NETDEV_NAME;
2319 else if (attr == &dev_attr_host_hwaddress.attr)
2320 param = ISCSI_HOST_PARAM_HWADDRESS;
2321 else if (attr == &dev_attr_host_ipaddress.attr)
2322 param = ISCSI_HOST_PARAM_IPADDRESS;
2323 else if (attr == &dev_attr_host_initiatorname.attr)
2324 param = ISCSI_HOST_PARAM_INITIATOR_NAME;
2325 else {
2326 WARN_ONCE(1, "Invalid host attr");
2327 return 0;
2328 }
2329
2330 return priv->iscsi_transport->attr_is_visible(ISCSI_HOST_PARAM, param);
2331}
2332
2333static struct attribute_group iscsi_host_group = {
2334 .attrs = iscsi_host_attrs,
2335 .is_visible = iscsi_host_attr_is_visible,
2336};
1819dc81 2337
0896b752
AA
2338static int iscsi_session_match(struct attribute_container *cont,
2339 struct device *dev)
1da177e4 2340{
7b8631b5 2341 struct iscsi_cls_session *session;
1da177e4 2342 struct Scsi_Host *shost;
0896b752
AA
2343 struct iscsi_internal *priv;
2344
2345 if (!iscsi_is_session_dev(dev))
2346 return 0;
1da177e4 2347
7b8631b5
MC
2348 session = iscsi_dev_to_session(dev);
2349 shost = iscsi_session_to_shost(session);
0896b752 2350 if (!shost->transportt)
1da177e4
LT
2351 return 0;
2352
0896b752
AA
2353 priv = to_iscsi_internal(shost->transportt);
2354 if (priv->session_cont.ac.class != &iscsi_session_class.class)
1da177e4
LT
2355 return 0;
2356
0896b752 2357 return &priv->session_cont.ac == cont;
1da177e4
LT
2358}
2359
0896b752
AA
2360static int iscsi_conn_match(struct attribute_container *cont,
2361 struct device *dev)
2362{
7b8631b5
MC
2363 struct iscsi_cls_session *session;
2364 struct iscsi_cls_conn *conn;
1da177e4 2365 struct Scsi_Host *shost;
0896b752 2366 struct iscsi_internal *priv;
1da177e4 2367
0896b752 2368 if (!iscsi_is_conn_dev(dev))
1da177e4
LT
2369 return 0;
2370
7b8631b5
MC
2371 conn = iscsi_dev_to_conn(dev);
2372 session = iscsi_dev_to_session(conn->dev.parent);
2373 shost = iscsi_session_to_shost(session);
2374
0896b752 2375 if (!shost->transportt)
1da177e4
LT
2376 return 0;
2377
0896b752
AA
2378 priv = to_iscsi_internal(shost->transportt);
2379 if (priv->conn_cont.ac.class != &iscsi_connection_class.class)
2380 return 0;
1da177e4 2381
0896b752
AA
2382 return &priv->conn_cont.ac == cont;
2383}
2384
30a6c652
MC
2385static int iscsi_host_match(struct attribute_container *cont,
2386 struct device *dev)
2387{
2388 struct Scsi_Host *shost;
2389 struct iscsi_internal *priv;
2390
2391 if (!scsi_is_host_device(dev))
2392 return 0;
2393
2394 shost = dev_to_shost(dev);
2395 if (!shost->transportt ||
2396 shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
2397 return 0;
2398
2399 priv = to_iscsi_internal(shost->transportt);
2400 return &priv->t.host_attrs.ac == cont;
2401}
2402
7b8631b5
MC
2403struct scsi_transport_template *
2404iscsi_register_transport(struct iscsi_transport *tt)
0896b752
AA
2405{
2406 struct iscsi_internal *priv;
2407 unsigned long flags;
f27fb2ef 2408 int err;
0896b752
AA
2409
2410 BUG_ON(!tt);
2411
2412 priv = iscsi_if_transport_lookup(tt);
2413 if (priv)
7b8631b5 2414 return NULL;
0896b752 2415
24669f75 2416 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0896b752 2417 if (!priv)
7b8631b5 2418 return NULL;
0896b752 2419 INIT_LIST_HEAD(&priv->list);
0896b752 2420 priv->iscsi_transport = tt;
30a6c652 2421 priv->t.user_scan = iscsi_user_scan;
06d25af4 2422 priv->t.create_work_queue = 1;
0896b752 2423
ee959b00 2424 priv->dev.class = &iscsi_transport_class;
71610f55 2425 dev_set_name(&priv->dev, "%s", tt->name);
ee959b00 2426 err = device_register(&priv->dev);
0896b752
AA
2427 if (err)
2428 goto free_priv;
2429
ee959b00 2430 err = sysfs_create_group(&priv->dev.kobj, &iscsi_transport_group);
0896b752 2431 if (err)
ee959b00 2432 goto unregister_dev;
0896b752 2433
30a6c652 2434 /* host parameters */
30a6c652
MC
2435 priv->t.host_attrs.ac.class = &iscsi_host_class.class;
2436 priv->t.host_attrs.ac.match = iscsi_host_match;
f27fb2ef 2437 priv->t.host_attrs.ac.grp = &iscsi_host_group;
32c6e1b9 2438 priv->t.host_size = sizeof(struct iscsi_cls_host);
30a6c652
MC
2439 transport_container_register(&priv->t.host_attrs);
2440
0896b752 2441 /* connection parameters */
0896b752
AA
2442 priv->conn_cont.ac.class = &iscsi_connection_class.class;
2443 priv->conn_cont.ac.match = iscsi_conn_match;
3128c6c7 2444 priv->conn_cont.ac.grp = &iscsi_conn_group;
0896b752 2445 transport_container_register(&priv->conn_cont);
1da177e4 2446
0896b752 2447 /* session parameters */
0896b752
AA
2448 priv->session_cont.ac.class = &iscsi_session_class.class;
2449 priv->session_cont.ac.match = iscsi_session_match;
1d063c17 2450 priv->session_cont.ac.grp = &iscsi_session_group;
0896b752
AA
2451 transport_container_register(&priv->session_cont);
2452
0896b752
AA
2453 spin_lock_irqsave(&iscsi_transport_lock, flags);
2454 list_add(&priv->list, &iscsi_transports);
2455 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
2456
2457 printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
7b8631b5 2458 return &priv->t;
1da177e4 2459
ee959b00
TJ
2460unregister_dev:
2461 device_unregister(&priv->dev);
d82ff9be 2462 return NULL;
0896b752
AA
2463free_priv:
2464 kfree(priv);
7b8631b5 2465 return NULL;
1da177e4 2466}
0896b752
AA
2467EXPORT_SYMBOL_GPL(iscsi_register_transport);
2468
2469int iscsi_unregister_transport(struct iscsi_transport *tt)
2470{
2471 struct iscsi_internal *priv;
2472 unsigned long flags;
2473
2474 BUG_ON(!tt);
2475
0b950672 2476 mutex_lock(&rx_queue_mutex);
0896b752
AA
2477
2478 priv = iscsi_if_transport_lookup(tt);
2479 BUG_ON (!priv);
2480
0896b752
AA
2481 spin_lock_irqsave(&iscsi_transport_lock, flags);
2482 list_del(&priv->list);
2483 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
2484
2485 transport_container_unregister(&priv->conn_cont);
2486 transport_container_unregister(&priv->session_cont);
30a6c652 2487 transport_container_unregister(&priv->t.host_attrs);
0896b752 2488
ee959b00
TJ
2489 sysfs_remove_group(&priv->dev.kobj, &iscsi_transport_group);
2490 device_unregister(&priv->dev);
0b950672 2491 mutex_unlock(&rx_queue_mutex);
1da177e4 2492
0896b752
AA
2493 return 0;
2494}
2495EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
1da177e4 2496
1da177e4
LT
2497static __init int iscsi_transport_init(void)
2498{
0896b752 2499 int err;
1da177e4 2500
09492605 2501 printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
f4246b33
MC
2502 ISCSI_TRANSPORT_VERSION);
2503
41be1444
MC
2504 atomic_set(&iscsi_session_nr, 0);
2505
0896b752 2506 err = class_register(&iscsi_transport_class);
1da177e4
LT
2507 if (err)
2508 return err;
0896b752 2509
d82ff9be 2510 err = class_register(&iscsi_endpoint_class);
0896b752
AA
2511 if (err)
2512 goto unregister_transport_class;
2513
8d07913d 2514 err = class_register(&iscsi_iface_class);
d82ff9be
MC
2515 if (err)
2516 goto unregister_endpoint_class;
2517
8d07913d
MC
2518 err = transport_class_register(&iscsi_host_class);
2519 if (err)
2520 goto unregister_iface_class;
2521
30a6c652
MC
2522 err = transport_class_register(&iscsi_connection_class);
2523 if (err)
2524 goto unregister_host_class;
2525
0896b752
AA
2526 err = transport_class_register(&iscsi_session_class);
2527 if (err)
2528 goto unregister_conn_class;
2529
d82ff9be
MC
2530 nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx,
2531 NULL, THIS_MODULE);
0896b752
AA
2532 if (!nls) {
2533 err = -ENOBUFS;
43a145a3 2534 goto unregister_session_class;
0896b752
AA
2535 }
2536
d8bf541e
MC
2537 iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
2538 if (!iscsi_eh_timer_workq)
2539 goto release_nls;
2540
43a145a3 2541 return 0;
0896b752 2542
d8bf541e 2543release_nls:
b7c6ba6e 2544 netlink_kernel_release(nls);
0896b752
AA
2545unregister_session_class:
2546 transport_class_unregister(&iscsi_session_class);
2547unregister_conn_class:
2548 transport_class_unregister(&iscsi_connection_class);
30a6c652
MC
2549unregister_host_class:
2550 transport_class_unregister(&iscsi_host_class);
8d07913d
MC
2551unregister_iface_class:
2552 class_unregister(&iscsi_iface_class);
d82ff9be
MC
2553unregister_endpoint_class:
2554 class_unregister(&iscsi_endpoint_class);
0896b752
AA
2555unregister_transport_class:
2556 class_unregister(&iscsi_transport_class);
2557 return err;
1da177e4
LT
2558}
2559
2560static void __exit iscsi_transport_exit(void)
2561{
d8bf541e 2562 destroy_workqueue(iscsi_eh_timer_workq);
b7c6ba6e 2563 netlink_kernel_release(nls);
0896b752
AA
2564 transport_class_unregister(&iscsi_connection_class);
2565 transport_class_unregister(&iscsi_session_class);
30a6c652 2566 transport_class_unregister(&iscsi_host_class);
d82ff9be 2567 class_unregister(&iscsi_endpoint_class);
8d07913d 2568 class_unregister(&iscsi_iface_class);
0896b752 2569 class_unregister(&iscsi_transport_class);
1da177e4
LT
2570}
2571
2572module_init(iscsi_transport_init);
2573module_exit(iscsi_transport_exit);
2574
0896b752
AA
2575MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
2576 "Dmitry Yusupov <dmitry_yus@yahoo.com>, "
2577 "Alex Aizman <itn780@yahoo.com>");
2578MODULE_DESCRIPTION("iSCSI Transport Interface");
1da177e4 2579MODULE_LICENSE("GPL");
f4246b33 2580MODULE_VERSION(ISCSI_TRANSPORT_VERSION);
058548ae 2581MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_ISCSI);