]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/scsi/scsi_transport_iscsi.c
[SCSI] lpfc 8.2.7 : Update version to 8.2.7
[net-next-2.6.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>
0896b752 25#include <net/tcp.h>
1da177e4
LT
26#include <scsi/scsi.h>
27#include <scsi/scsi_host.h>
28#include <scsi/scsi_device.h>
29#include <scsi/scsi_transport.h>
30#include <scsi/scsi_transport_iscsi.h>
0896b752 31#include <scsi/iscsi_if.h>
1da177e4 32
88dfd340 33#define ISCSI_SESSION_ATTRS 21
c238c3bb 34#define ISCSI_CONN_ATTRS 13
d8196ed2 35#define ISCSI_HOST_ATTRS 4
d82ff9be 36
31ed0bf4 37#define ISCSI_TRANSPORT_VERSION "2.0-869"
1da177e4
LT
38
39struct iscsi_internal {
790f39a2 40 int daemon_pid;
1da177e4 41 struct scsi_transport_template t;
0896b752
AA
42 struct iscsi_transport *iscsi_transport;
43 struct list_head list;
ee959b00 44 struct device dev;
30a6c652 45
ee959b00 46 struct device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
0896b752 47 struct transport_container conn_cont;
ee959b00 48 struct device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
0896b752 49 struct transport_container session_cont;
ee959b00 50 struct device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
1da177e4
LT
51};
52
41be1444 53static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
d8bf541e 54static struct workqueue_struct *iscsi_eh_timer_workq;
b5c7a12d 55
0896b752
AA
56/*
57 * list of registered transports and lock that must
58 * be held while accessing list. The iscsi_transport_lock must
0b950672 59 * be acquired after the rx_queue_mutex.
0896b752
AA
60 */
61static LIST_HEAD(iscsi_transports);
62static DEFINE_SPINLOCK(iscsi_transport_lock);
63
64#define to_iscsi_internal(tmpl) \
65 container_of(tmpl, struct iscsi_internal, t)
66
ee959b00
TJ
67#define dev_to_iscsi_internal(_dev) \
68 container_of(_dev, struct iscsi_internal, dev)
0896b752 69
ee959b00 70static void iscsi_transport_release(struct device *dev)
0896b752 71{
ee959b00 72 struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
0896b752
AA
73 kfree(priv);
74}
1da177e4 75
0896b752
AA
76/*
77 * iscsi_transport_class represents the iscsi_transports that are
78 * registered.
79 */
80static struct class iscsi_transport_class = {
81 .name = "iscsi_transport",
ee959b00 82 .dev_release = iscsi_transport_release,
0896b752
AA
83};
84
85static ssize_t
ee959b00
TJ
86show_transport_handle(struct device *dev, struct device_attribute *attr,
87 char *buf)
0896b752 88{
ee959b00 89 struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
762e2bfa 90 return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport));
0896b752 91}
ee959b00 92static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
0896b752
AA
93
94#define show_transport_attr(name, format) \
95static ssize_t \
ee959b00
TJ
96show_transport_##name(struct device *dev, \
97 struct device_attribute *attr,char *buf) \
0896b752 98{ \
ee959b00 99 struct iscsi_internal *priv = dev_to_iscsi_internal(dev); \
0896b752
AA
100 return sprintf(buf, format"\n", priv->iscsi_transport->name); \
101} \
ee959b00 102static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
0896b752
AA
103
104show_transport_attr(caps, "0x%x");
0896b752
AA
105
106static struct attribute *iscsi_transport_attrs[] = {
ee959b00
TJ
107 &dev_attr_handle.attr,
108 &dev_attr_caps.attr,
0896b752
AA
109 NULL,
110};
111
112static struct attribute_group iscsi_transport_group = {
113 .attrs = iscsi_transport_attrs,
114};
115
d82ff9be
MC
116/*
117 * iSCSI endpoint attrs
118 */
119#define iscsi_dev_to_endpoint(_dev) \
120 container_of(_dev, struct iscsi_endpoint, dev)
121
122#define ISCSI_ATTR(_prefix,_name,_mode,_show,_store) \
123struct device_attribute dev_attr_##_prefix##_##_name = \
124 __ATTR(_name,_mode,_show,_store)
125
126static void iscsi_endpoint_release(struct device *dev)
127{
128 struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
129 kfree(ep);
130}
131
132static struct class iscsi_endpoint_class = {
133 .name = "iscsi_endpoint",
134 .dev_release = iscsi_endpoint_release,
135};
136
137static ssize_t
138show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
139{
140 struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
141 return sprintf(buf, "%u\n", ep->id);
142}
143static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
144
145static struct attribute *iscsi_endpoint_attrs[] = {
146 &dev_attr_ep_handle.attr,
147 NULL,
148};
149
150static struct attribute_group iscsi_endpoint_group = {
151 .attrs = iscsi_endpoint_attrs,
152};
153
154#define ISCSI_MAX_EPID -1
155
156static int iscsi_match_epid(struct device *dev, void *data)
157{
158 struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
159 unsigned int *epid = (unsigned int *) data;
160
161 return *epid == ep->id;
162}
163
164struct iscsi_endpoint *
165iscsi_create_endpoint(int dd_size)
166{
167 struct device *dev;
168 struct iscsi_endpoint *ep;
169 unsigned int id;
170 int err;
171
172 for (id = 1; id < ISCSI_MAX_EPID; id++) {
173 dev = class_find_device(&iscsi_endpoint_class, &id,
174 iscsi_match_epid);
175 if (!dev)
176 break;
177 }
178 if (id == ISCSI_MAX_EPID) {
179 printk(KERN_ERR "Too many connections. Max supported %u\n",
180 ISCSI_MAX_EPID - 1);
181 return NULL;
182 }
183
184 ep = kzalloc(sizeof(*ep) + dd_size, GFP_KERNEL);
185 if (!ep)
186 return NULL;
187
188 ep->id = id;
189 ep->dev.class = &iscsi_endpoint_class;
190 snprintf(ep->dev.bus_id, BUS_ID_SIZE, "ep-%u", id);
191 err = device_register(&ep->dev);
192 if (err)
193 goto free_ep;
194
195 err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group);
196 if (err)
197 goto unregister_dev;
198
199 if (dd_size)
200 ep->dd_data = &ep[1];
201 return ep;
202
203unregister_dev:
204 device_unregister(&ep->dev);
205 return NULL;
206
207free_ep:
208 kfree(ep);
209 return NULL;
210}
211EXPORT_SYMBOL_GPL(iscsi_create_endpoint);
212
213void iscsi_destroy_endpoint(struct iscsi_endpoint *ep)
214{
215 sysfs_remove_group(&ep->dev.kobj, &iscsi_endpoint_group);
216 device_unregister(&ep->dev);
217}
218EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
219
220struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
221{
222 struct device *dev;
223
224 dev = class_find_device(&iscsi_endpoint_class, &handle,
225 iscsi_match_epid);
226 if (!dev)
227 return NULL;
228
229 return iscsi_dev_to_endpoint(dev);
230}
231EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
232
30a6c652 233static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
ee959b00 234 struct device *cdev)
30a6c652
MC
235{
236 struct Scsi_Host *shost = dev_to_shost(dev);
32c6e1b9 237 struct iscsi_cls_host *ihost = shost->shost_data;
30a6c652
MC
238
239 memset(ihost, 0, sizeof(*ihost));
8aae18ad 240 atomic_set(&ihost->nr_scans, 0);
7970634b 241 mutex_init(&ihost->mutex);
26974789 242
bd976f62 243 snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d",
26974789 244 shost->host_no);
bd976f62
MC
245 ihost->scan_workq = create_singlethread_workqueue(
246 ihost->scan_workq_name);
247 if (!ihost->scan_workq)
26974789
MC
248 return -ENOMEM;
249 return 0;
250}
251
252static int iscsi_remove_host(struct transport_container *tc, struct device *dev,
ee959b00 253 struct device *cdev)
26974789
MC
254{
255 struct Scsi_Host *shost = dev_to_shost(dev);
32c6e1b9 256 struct iscsi_cls_host *ihost = shost->shost_data;
26974789 257
bd976f62 258 destroy_workqueue(ihost->scan_workq);
30a6c652
MC
259 return 0;
260}
261
262static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
263 "iscsi_host",
264 iscsi_setup_host,
26974789 265 iscsi_remove_host,
30a6c652
MC
266 NULL);
267
0896b752
AA
268static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
269 "iscsi_session",
1da177e4
LT
270 NULL,
271 NULL,
272 NULL);
273
0896b752
AA
274static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
275 "iscsi_connection",
1da177e4
LT
276 NULL,
277 NULL,
278 NULL);
0896b752
AA
279
280static struct sock *nls;
0b950672 281static DEFINE_MUTEX(rx_queue_mutex);
0896b752 282
7b7232f3
MC
283static LIST_HEAD(sesslist);
284static DEFINE_SPINLOCK(sesslock);
7b8631b5
MC
285static LIST_HEAD(connlist);
286static DEFINE_SPINLOCK(connlock);
0896b752 287
b5c7a12d
MC
288static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
289{
290 struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent);
291 return sess->sid;
292}
293
294/*
295 * Returns the matching session to a given sid
296 */
297static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid)
7b7232f3
MC
298{
299 unsigned long flags;
300 struct iscsi_cls_session *sess;
301
302 spin_lock_irqsave(&sesslock, flags);
303 list_for_each_entry(sess, &sesslist, sess_list) {
b5c7a12d 304 if (sess->sid == sid) {
7b7232f3
MC
305 spin_unlock_irqrestore(&sesslock, flags);
306 return sess;
307 }
308 }
309 spin_unlock_irqrestore(&sesslock, flags);
310 return NULL;
311}
312
b5c7a12d
MC
313/*
314 * Returns the matching connection to a given sid / cid tuple
315 */
316static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
7b7232f3
MC
317{
318 unsigned long flags;
319 struct iscsi_cls_conn *conn;
320
321 spin_lock_irqsave(&connlock, flags);
322 list_for_each_entry(conn, &connlist, conn_list) {
b5c7a12d 323 if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) {
7b7232f3
MC
324 spin_unlock_irqrestore(&connlock, flags);
325 return conn;
326 }
327 }
328 spin_unlock_irqrestore(&connlock, flags);
329 return NULL;
330}
331
7b8631b5
MC
332/*
333 * The following functions can be used by LLDs that allocate
334 * their own scsi_hosts or by software iscsi LLDs
335 */
6eabafbe
MC
336static struct {
337 int value;
338 char *name;
339} iscsi_session_state_names[] = {
340 { ISCSI_SESSION_LOGGED_IN, "LOGGED_IN" },
341 { ISCSI_SESSION_FAILED, "FAILED" },
342 { ISCSI_SESSION_FREE, "FREE" },
343};
344
3b0f208a 345static const char *iscsi_session_state_name(int state)
6eabafbe
MC
346{
347 int i;
348 char *name = NULL;
349
350 for (i = 0; i < ARRAY_SIZE(iscsi_session_state_names); i++) {
351 if (iscsi_session_state_names[i].value == state) {
352 name = iscsi_session_state_names[i].name;
353 break;
354 }
355 }
356 return name;
357}
358
359int iscsi_session_chkready(struct iscsi_cls_session *session)
360{
361 unsigned long flags;
362 int err;
363
364 spin_lock_irqsave(&session->lock, flags);
365 switch (session->state) {
366 case ISCSI_SESSION_LOGGED_IN:
367 err = 0;
368 break;
369 case ISCSI_SESSION_FAILED:
370 err = DID_IMM_RETRY << 16;
371 break;
372 case ISCSI_SESSION_FREE:
373 err = DID_NO_CONNECT << 16;
374 break;
375 default:
376 err = DID_NO_CONNECT << 16;
377 break;
378 }
379 spin_unlock_irqrestore(&session->lock, flags);
380 return err;
381}
382EXPORT_SYMBOL_GPL(iscsi_session_chkready);
383
7b8631b5
MC
384static void iscsi_session_release(struct device *dev)
385{
386 struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
7b8631b5 387 struct Scsi_Host *shost;
0896b752 388
7b8631b5
MC
389 shost = iscsi_session_to_shost(session);
390 scsi_host_put(shost);
391 kfree(session);
7b8631b5 392}
0896b752 393
7b8631b5
MC
394static int iscsi_is_session_dev(const struct device *dev)
395{
396 return dev->release == iscsi_session_release;
397}
0896b752 398
a4804cd6
MC
399static int iscsi_iter_session_fn(struct device *dev, void *data)
400{
401 void (* fn) (struct iscsi_cls_session *) = data;
402
403 if (!iscsi_is_session_dev(dev))
404 return 0;
405 fn(iscsi_dev_to_session(dev));
406 return 0;
407}
408
409void iscsi_host_for_each_session(struct Scsi_Host *shost,
410 void (*fn)(struct iscsi_cls_session *))
411{
412 device_for_each_child(&shost->shost_gendev, fn,
413 iscsi_iter_session_fn);
414}
415EXPORT_SYMBOL_GPL(iscsi_host_for_each_session);
416
8aae18ad
MC
417/**
418 * iscsi_scan_finished - helper to report when running scans are done
419 * @shost: scsi host
420 * @time: scan run time
421 *
422 * This function can be used by drives like qla4xxx to report to the scsi
423 * layer when the scans it kicked off at module load time are done.
424 */
425int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time)
426{
32c6e1b9 427 struct iscsi_cls_host *ihost = shost->shost_data;
8aae18ad
MC
428 /*
429 * qla4xxx will have kicked off some session unblocks before calling
430 * scsi_scan_host, so just wait for them to complete.
431 */
432 return !atomic_read(&ihost->nr_scans);
433}
434EXPORT_SYMBOL_GPL(iscsi_scan_finished);
435
7970634b
MC
436struct iscsi_scan_data {
437 unsigned int channel;
438 unsigned int id;
439 unsigned int lun;
440};
441
442static int iscsi_user_scan_session(struct device *dev, void *data)
30a6c652 443{
7970634b 444 struct iscsi_scan_data *scan_data = data;
30a6c652 445 struct iscsi_cls_session *session;
7970634b
MC
446 struct Scsi_Host *shost;
447 struct iscsi_cls_host *ihost;
448 unsigned long flags;
449 unsigned int id;
450
451 if (!iscsi_is_session_dev(dev))
452 return 0;
453
454 session = iscsi_dev_to_session(dev);
455 shost = iscsi_session_to_shost(session);
456 ihost = shost->shost_data;
30a6c652
MC
457
458 mutex_lock(&ihost->mutex);
7970634b
MC
459 spin_lock_irqsave(&session->lock, flags);
460 if (session->state != ISCSI_SESSION_LOGGED_IN) {
461 spin_unlock_irqrestore(&session->lock, flags);
462 mutex_unlock(&ihost->mutex);
463 return 0;
30a6c652 464 }
7970634b
MC
465 id = session->target_id;
466 spin_unlock_irqrestore(&session->lock, flags);
30a6c652 467
7970634b
MC
468 if (id != ISCSI_MAX_TARGET) {
469 if ((scan_data->channel == SCAN_WILD_CARD ||
470 scan_data->channel == 0) &&
471 (scan_data->id == SCAN_WILD_CARD ||
472 scan_data->id == id))
473 scsi_scan_target(&session->dev, 0, id,
474 scan_data->lun, 1);
475 }
476 mutex_unlock(&ihost->mutex);
30a6c652
MC
477 return 0;
478}
479
7970634b
MC
480static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
481 uint id, uint lun)
482{
483 struct iscsi_scan_data scan_data;
484
485 scan_data.channel = channel;
486 scan_data.id = id;
487 scan_data.lun = lun;
488
489 return device_for_each_child(&shost->shost_gendev, &scan_data,
490 iscsi_user_scan_session);
491}
492
bd976f62
MC
493static void iscsi_scan_session(struct work_struct *work)
494{
495 struct iscsi_cls_session *session =
496 container_of(work, struct iscsi_cls_session, scan_work);
8aae18ad 497 struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9 498 struct iscsi_cls_host *ihost = shost->shost_data;
7970634b 499 struct iscsi_scan_data scan_data;
bd976f62 500
7970634b
MC
501 scan_data.channel = 0;
502 scan_data.id = SCAN_WILD_CARD;
503 scan_data.lun = SCAN_WILD_CARD;
bd976f62 504
7970634b 505 iscsi_user_scan_session(&session->dev, &scan_data);
8aae18ad 506 atomic_dec(&ihost->nr_scans);
bd976f62
MC
507}
508
c4028958 509static void session_recovery_timedout(struct work_struct *work)
30a6c652 510{
c4028958
DH
511 struct iscsi_cls_session *session =
512 container_of(work, struct iscsi_cls_session,
513 recovery_work.work);
6eabafbe 514 unsigned long flags;
30a6c652 515
322d739d
MC
516 iscsi_cls_session_printk(KERN_INFO, session,
517 "session recovery timed out after %d secs\n",
518 session->recovery_tmo);
30a6c652 519
6eabafbe
MC
520 spin_lock_irqsave(&session->lock, flags);
521 switch (session->state) {
522 case ISCSI_SESSION_FAILED:
523 session->state = ISCSI_SESSION_FREE;
524 break;
525 case ISCSI_SESSION_LOGGED_IN:
526 case ISCSI_SESSION_FREE:
527 /* we raced with the unblock's flush */
528 spin_unlock_irqrestore(&session->lock, flags);
529 return;
530 }
531 spin_unlock_irqrestore(&session->lock, flags);
532
30a6c652
MC
533 if (session->transport->session_recovery_timedout)
534 session->transport->session_recovery_timedout(session);
535
536 scsi_target_unblock(&session->dev);
537}
538
45ab33b6 539static void __iscsi_unblock_session(struct work_struct *work)
6eabafbe 540{
45ab33b6
MC
541 struct iscsi_cls_session *session =
542 container_of(work, struct iscsi_cls_session,
543 unblock_work);
bd976f62 544 struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9 545 struct iscsi_cls_host *ihost = shost->shost_data;
6eabafbe
MC
546 unsigned long flags;
547
45ab33b6
MC
548 /*
549 * The recovery and unblock work get run from the same workqueue,
550 * so try to cancel it if it was going to run after this unblock.
551 */
552 cancel_delayed_work(&session->recovery_work);
6eabafbe
MC
553 spin_lock_irqsave(&session->lock, flags);
554 session->state = ISCSI_SESSION_LOGGED_IN;
555 spin_unlock_irqrestore(&session->lock, flags);
45ab33b6
MC
556 /* start IO */
557 scsi_target_unblock(&session->dev);
8aae18ad
MC
558 /*
559 * Only do kernel scanning if the driver is properly hooked into
560 * the async scanning code (drivers like iscsi_tcp do login and
561 * scanning from userspace).
562 */
563 if (shost->hostt->scan_finished) {
564 if (queue_work(ihost->scan_workq, &session->scan_work))
565 atomic_inc(&ihost->nr_scans);
566 }
6eabafbe 567}
45ab33b6
MC
568
569/**
570 * iscsi_unblock_session - set a session as logged in and start IO.
571 * @session: iscsi session
572 *
573 * Mark a session as ready to accept IO.
574 */
575void iscsi_unblock_session(struct iscsi_cls_session *session)
576{
577 queue_work(iscsi_eh_timer_workq, &session->unblock_work);
578 /*
579 * make sure all the events have completed before tell the driver
580 * it is safe
581 */
582 flush_workqueue(iscsi_eh_timer_workq);
583}
30a6c652
MC
584EXPORT_SYMBOL_GPL(iscsi_unblock_session);
585
45ab33b6 586static void __iscsi_block_session(struct work_struct *work)
30a6c652 587{
45ab33b6
MC
588 struct iscsi_cls_session *session =
589 container_of(work, struct iscsi_cls_session,
590 block_work);
6eabafbe
MC
591 unsigned long flags;
592
593 spin_lock_irqsave(&session->lock, flags);
594 session->state = ISCSI_SESSION_FAILED;
595 spin_unlock_irqrestore(&session->lock, flags);
30a6c652 596 scsi_target_block(&session->dev);
d8bf541e
MC
597 queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work,
598 session->recovery_tmo * HZ);
30a6c652 599}
45ab33b6
MC
600
601void iscsi_block_session(struct iscsi_cls_session *session)
602{
603 queue_work(iscsi_eh_timer_workq, &session->block_work);
604}
30a6c652
MC
605EXPORT_SYMBOL_GPL(iscsi_block_session);
606
26974789
MC
607static void __iscsi_unbind_session(struct work_struct *work)
608{
609 struct iscsi_cls_session *session =
610 container_of(work, struct iscsi_cls_session,
611 unbind_work);
612 struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9 613 struct iscsi_cls_host *ihost = shost->shost_data;
7970634b 614 unsigned long flags;
26974789
MC
615
616 /* Prevent new scans and make sure scanning is not in progress */
617 mutex_lock(&ihost->mutex);
7970634b
MC
618 spin_lock_irqsave(&session->lock, flags);
619 if (session->target_id == ISCSI_MAX_TARGET) {
620 spin_unlock_irqrestore(&session->lock, flags);
26974789
MC
621 mutex_unlock(&ihost->mutex);
622 return;
623 }
7970634b
MC
624 session->target_id = ISCSI_MAX_TARGET;
625 spin_unlock_irqrestore(&session->lock, flags);
26974789
MC
626 mutex_unlock(&ihost->mutex);
627
628 scsi_remove_target(&session->dev);
629 iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
630}
631
632static int iscsi_unbind_session(struct iscsi_cls_session *session)
633{
634 struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9 635 struct iscsi_cls_host *ihost = shost->shost_data;
26974789 636
bd976f62 637 return queue_work(ihost->scan_workq, &session->unbind_work);
26974789
MC
638}
639
7b8631b5 640struct iscsi_cls_session *
5d91e209
MC
641iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
642 int dd_size)
7b8631b5
MC
643{
644 struct iscsi_cls_session *session;
7b8631b5 645
5d91e209 646 session = kzalloc(sizeof(*session) + dd_size,
b5c7a12d 647 GFP_KERNEL);
7b8631b5 648 if (!session)
f53a88da
MC
649 return NULL;
650
7b8631b5 651 session->transport = transport;
30a6c652 652 session->recovery_tmo = 120;
6eabafbe 653 session->state = ISCSI_SESSION_FREE;
c4028958 654 INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
30a6c652 655 INIT_LIST_HEAD(&session->sess_list);
45ab33b6
MC
656 INIT_WORK(&session->unblock_work, __iscsi_unblock_session);
657 INIT_WORK(&session->block_work, __iscsi_block_session);
26974789 658 INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
bd976f62 659 INIT_WORK(&session->scan_work, iscsi_scan_session);
6eabafbe 660 spin_lock_init(&session->lock);
7b8631b5 661
6a8a0d36
MC
662 /* this is released in the dev's release function */
663 scsi_host_get(shost);
8434aa8b
MC
664 session->dev.parent = &shost->shost_gendev;
665 session->dev.release = iscsi_session_release;
666 device_initialize(&session->dev);
5d91e209 667 if (dd_size)
b5c7a12d 668 session->dd_data = &session[1];
8434aa8b
MC
669 return session;
670}
671EXPORT_SYMBOL_GPL(iscsi_alloc_session);
672
7970634b
MC
673static int iscsi_get_next_target_id(struct device *dev, void *data)
674{
675 struct iscsi_cls_session *session;
676 unsigned long flags;
677 int err = 0;
678
679 if (!iscsi_is_session_dev(dev))
680 return 0;
681
682 session = iscsi_dev_to_session(dev);
683 spin_lock_irqsave(&session->lock, flags);
684 if (*((unsigned int *) data) == session->target_id)
685 err = -EEXIST;
686 spin_unlock_irqrestore(&session->lock, flags);
687 return err;
688}
689
6a8a0d36 690int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
8434aa8b
MC
691{
692 struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9 693 struct iscsi_cls_host *ihost;
26974789 694 unsigned long flags;
7970634b 695 unsigned int id = target_id;
8434aa8b 696 int err;
b5c7a12d 697
30a6c652 698 ihost = shost->shost_data;
41be1444 699 session->sid = atomic_add_return(1, &iscsi_session_nr);
7970634b
MC
700
701 if (id == ISCSI_MAX_TARGET) {
702 for (id = 0; id < ISCSI_MAX_TARGET; id++) {
703 err = device_for_each_child(&shost->shost_gendev, &id,
704 iscsi_get_next_target_id);
705 if (!err)
706 break;
707 }
708
709 if (id == ISCSI_MAX_TARGET) {
710 iscsi_cls_session_printk(KERN_ERR, session,
711 "Too many iscsi targets. Max "
712 "number of targets is %d.\n",
713 ISCSI_MAX_TARGET - 1);
714 goto release_host;
715 }
716 }
717 session->target_id = id;
30a6c652 718
b5c7a12d
MC
719 snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
720 session->sid);
8434aa8b 721 err = device_add(&session->dev);
7b8631b5 722 if (err) {
322d739d
MC
723 iscsi_cls_session_printk(KERN_ERR, session,
724 "could not register session's dev\n");
8434aa8b 725 goto release_host;
7b8631b5
MC
726 }
727 transport_register_device(&session->dev);
728
26974789
MC
729 spin_lock_irqsave(&sesslock, flags);
730 list_add(&session->sess_list, &sesslist);
731 spin_unlock_irqrestore(&sesslock, flags);
732
26974789 733 iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION);
8434aa8b 734 return 0;
30a6c652 735
8434aa8b
MC
736release_host:
737 scsi_host_put(shost);
738 return err;
7b8631b5 739}
8434aa8b 740EXPORT_SYMBOL_GPL(iscsi_add_session);
7b8631b5
MC
741
742/**
8434aa8b
MC
743 * iscsi_create_session - create iscsi class session
744 * @shost: scsi host
745 * @transport: iscsi transport
5d91e209 746 * @dd_size: private driver data size
eb44820c 747 * @target_id: which target
7b8631b5 748 *
8434aa8b 749 * This can be called from a LLD or iscsi_transport.
eb44820c 750 */
8434aa8b 751struct iscsi_cls_session *
5d91e209
MC
752iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
753 int dd_size, unsigned int target_id)
8434aa8b
MC
754{
755 struct iscsi_cls_session *session;
756
5d91e209 757 session = iscsi_alloc_session(shost, transport, dd_size);
8434aa8b
MC
758 if (!session)
759 return NULL;
760
6a8a0d36 761 if (iscsi_add_session(session, target_id)) {
8434aa8b
MC
762 iscsi_free_session(session);
763 return NULL;
764 }
765 return session;
766}
767EXPORT_SYMBOL_GPL(iscsi_create_session);
768
26974789
MC
769static void iscsi_conn_release(struct device *dev)
770{
771 struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
772 struct device *parent = conn->dev.parent;
773
774 kfree(conn);
775 put_device(parent);
776}
777
778static int iscsi_is_conn_dev(const struct device *dev)
779{
780 return dev->release == iscsi_conn_release;
781}
782
783static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)
784{
785 if (!iscsi_is_conn_dev(dev))
786 return 0;
787 return iscsi_destroy_conn(iscsi_dev_to_conn(dev));
788}
789
8434aa8b 790void iscsi_remove_session(struct iscsi_cls_session *session)
7b8631b5 791{
30a6c652 792 struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9 793 struct iscsi_cls_host *ihost = shost->shost_data;
26974789
MC
794 unsigned long flags;
795 int err;
796
797 spin_lock_irqsave(&sesslock, flags);
798 list_del(&session->sess_list);
799 spin_unlock_irqrestore(&sesslock, flags);
30a6c652 800
45ab33b6
MC
801 /* make sure there are no blocks/unblocks queued */
802 flush_workqueue(iscsi_eh_timer_workq);
803 /* make sure the timedout callout is not running */
804 if (!cancel_delayed_work(&session->recovery_work))
805 flush_workqueue(iscsi_eh_timer_workq);
26974789
MC
806 /*
807 * If we are blocked let commands flow again. The lld or iscsi
808 * layer should set up the queuecommand to fail commands.
45ab33b6
MC
809 * We assume that LLD will not be calling block/unblock while
810 * removing the session.
26974789 811 */
6eabafbe
MC
812 spin_lock_irqsave(&session->lock, flags);
813 session->state = ISCSI_SESSION_FREE;
814 spin_unlock_irqrestore(&session->lock, flags);
bd976f62 815
45ab33b6
MC
816 scsi_target_unblock(&session->dev);
817 /* flush running scans then delete devices */
bd976f62 818 flush_workqueue(ihost->scan_workq);
45ab33b6 819 __iscsi_unbind_session(&session->unbind_work);
30a6c652 820
26974789
MC
821 /* hw iscsi may not have removed all connections from session */
822 err = device_for_each_child(&session->dev, NULL,
823 iscsi_iter_destroy_conn_fn);
824 if (err)
322d739d
MC
825 iscsi_cls_session_printk(KERN_ERR, session,
826 "Could not delete all connections "
827 "for session. Error %d.\n", err);
8434aa8b 828
7b8631b5 829 transport_unregister_device(&session->dev);
8434aa8b
MC
830 device_del(&session->dev);
831}
832EXPORT_SYMBOL_GPL(iscsi_remove_session);
833
834void iscsi_free_session(struct iscsi_cls_session *session)
835{
26974789 836 iscsi_session_event(session, ISCSI_KEVENT_DESTROY_SESSION);
8434aa8b 837 put_device(&session->dev);
7b8631b5 838}
8434aa8b
MC
839EXPORT_SYMBOL_GPL(iscsi_free_session);
840
841/**
842 * iscsi_destroy_session - destroy iscsi session
843 * @session: iscsi_session
844 *
845 * Can be called by a LLD or iscsi_transport. There must not be
846 * any running connections.
eb44820c 847 */
8434aa8b
MC
848int iscsi_destroy_session(struct iscsi_cls_session *session)
849{
850 iscsi_remove_session(session);
851 iscsi_free_session(session);
852 return 0;
853}
7b8631b5
MC
854EXPORT_SYMBOL_GPL(iscsi_destroy_session);
855
7b8631b5
MC
856/**
857 * iscsi_create_conn - create iscsi class connection
858 * @session: iscsi cls session
5d91e209 859 * @dd_size: private driver data size
7b8631b5
MC
860 * @cid: connection id
861 *
862 * This can be called from a LLD or iscsi_transport. The connection
863 * is child of the session so cid must be unique for all connections
864 * on the session.
b5c7a12d
MC
865 *
866 * Since we do not support MCS, cid will normally be zero. In some cases
867 * for software iscsi we could be trying to preallocate a connection struct
868 * in which case there could be two connection structs and cid would be
869 * non-zero.
eb44820c 870 */
7b8631b5 871struct iscsi_cls_conn *
5d91e209 872iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
7b8631b5
MC
873{
874 struct iscsi_transport *transport = session->transport;
7b8631b5 875 struct iscsi_cls_conn *conn;
26974789 876 unsigned long flags;
7b8631b5
MC
877 int err;
878
5d91e209 879 conn = kzalloc(sizeof(*conn) + dd_size, GFP_KERNEL);
7b8631b5
MC
880 if (!conn)
881 return NULL;
5d91e209 882 if (dd_size)
7b8631b5
MC
883 conn->dd_data = &conn[1];
884
885 INIT_LIST_HEAD(&conn->conn_list);
886 conn->transport = transport;
b5c7a12d 887 conn->cid = cid;
7b8631b5
MC
888
889 /* this is released in the dev's release function */
890 if (!get_device(&session->dev))
43a145a3 891 goto free_conn;
b5c7a12d 892
7b8631b5 893 snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
b5c7a12d 894 session->sid, cid);
7b8631b5
MC
895 conn->dev.parent = &session->dev;
896 conn->dev.release = iscsi_conn_release;
897 err = device_register(&conn->dev);
898 if (err) {
322d739d
MC
899 iscsi_cls_session_printk(KERN_ERR, session, "could not "
900 "register connection's dev\n");
7b8631b5
MC
901 goto release_parent_ref;
902 }
903 transport_register_device(&conn->dev);
26974789
MC
904
905 spin_lock_irqsave(&connlock, flags);
906 list_add(&conn->conn_list, &connlist);
907 conn->active = 1;
908 spin_unlock_irqrestore(&connlock, flags);
7b8631b5
MC
909 return conn;
910
911release_parent_ref:
912 put_device(&session->dev);
913free_conn:
914 kfree(conn);
915 return NULL;
916}
917
918EXPORT_SYMBOL_GPL(iscsi_create_conn);
919
920/**
921 * iscsi_destroy_conn - destroy iscsi class connection
eb44820c 922 * @conn: iscsi cls session
7b8631b5 923 *
26974789 924 * This can be called from a LLD or iscsi_transport.
eb44820c 925 */
7b8631b5
MC
926int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
927{
26974789
MC
928 unsigned long flags;
929
930 spin_lock_irqsave(&connlock, flags);
931 conn->active = 0;
932 list_del(&conn->conn_list);
933 spin_unlock_irqrestore(&connlock, flags);
934
7b8631b5
MC
935 transport_unregister_device(&conn->dev);
936 device_unregister(&conn->dev);
937 return 0;
938}
7b8631b5
MC
939EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
940
7b8631b5
MC
941/*
942 * iscsi interface functions
943 */
0896b752
AA
944static struct iscsi_internal *
945iscsi_if_transport_lookup(struct iscsi_transport *tt)
946{
947 struct iscsi_internal *priv;
948 unsigned long flags;
949
950 spin_lock_irqsave(&iscsi_transport_lock, flags);
951 list_for_each_entry(priv, &iscsi_transports, list) {
952 if (tt == priv->iscsi_transport) {
953 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
954 return priv;
955 }
956 }
957 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
958 return NULL;
959}
1da177e4 960
53cb8a1f 961static int
43a145a3 962iscsi_broadcast_skb(struct sk_buff *skb, gfp_t gfp)
53cb8a1f 963{
53cb8a1f
MC
964 int rc;
965
9aaa2b46 966 rc = netlink_broadcast(nls, skb, 0, 1, gfp);
53cb8a1f 967 if (rc < 0) {
53cb8a1f
MC
968 printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc);
969 return rc;
970 }
971
53cb8a1f
MC
972 return 0;
973}
974
0896b752 975static int
43a145a3 976iscsi_unicast_skb(struct sk_buff *skb, int pid)
0896b752 977{
0896b752 978 int rc;
1da177e4 979
790f39a2 980 rc = netlink_unicast(nls, skb, pid, MSG_DONTWAIT);
0896b752 981 if (rc < 0) {
0896b752
AA
982 printk(KERN_ERR "iscsi: can not unicast skb (%d)\n", rc);
983 return rc;
984 }
985
0896b752 986 return 0;
1da177e4 987}
1da177e4 988
7b7232f3 989int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
0896b752 990 char *data, uint32_t data_size)
1da177e4 991{
0896b752
AA
992 struct nlmsghdr *nlh;
993 struct sk_buff *skb;
994 struct iscsi_uevent *ev;
0896b752 995 char *pdu;
790f39a2 996 struct iscsi_internal *priv;
0896b752
AA
997 int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
998 data_size);
999
790f39a2
MC
1000 priv = iscsi_if_transport_lookup(conn->transport);
1001 if (!priv)
1002 return -EINVAL;
1003
43a145a3 1004 skb = alloc_skb(len, GFP_ATOMIC);
0896b752 1005 if (!skb) {
7b7232f3 1006 iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED);
322d739d
MC
1007 iscsi_cls_conn_printk(KERN_ERR, conn, "can not deliver "
1008 "control PDU: OOM\n");
0896b752
AA
1009 return -ENOMEM;
1010 }
1da177e4 1011
790f39a2 1012 nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
0896b752
AA
1013 ev = NLMSG_DATA(nlh);
1014 memset(ev, 0, sizeof(*ev));
1015 ev->transport_handle = iscsi_handle(conn->transport);
1016 ev->type = ISCSI_KEVENT_RECV_PDU;
b5c7a12d
MC
1017 ev->r.recv_req.cid = conn->cid;
1018 ev->r.recv_req.sid = iscsi_conn_get_sid(conn);
0896b752
AA
1019 pdu = (char*)ev + sizeof(*ev);
1020 memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
1021 memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
1da177e4 1022
43a145a3 1023 return iscsi_unicast_skb(skb, priv->daemon_pid);
1da177e4 1024}
0896b752 1025EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
1da177e4 1026
7b7232f3 1027void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
1da177e4 1028{
0896b752
AA
1029 struct nlmsghdr *nlh;
1030 struct sk_buff *skb;
1031 struct iscsi_uevent *ev;
790f39a2 1032 struct iscsi_internal *priv;
0896b752
AA
1033 int len = NLMSG_SPACE(sizeof(*ev));
1034
790f39a2
MC
1035 priv = iscsi_if_transport_lookup(conn->transport);
1036 if (!priv)
1037 return;
1038
43a145a3 1039 skb = alloc_skb(len, GFP_ATOMIC);
0896b752 1040 if (!skb) {
322d739d
MC
1041 iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
1042 "conn error (%d)\n", error);
0896b752
AA
1043 return;
1044 }
1045
790f39a2 1046 nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
0896b752
AA
1047 ev = NLMSG_DATA(nlh);
1048 ev->transport_handle = iscsi_handle(conn->transport);
1049 ev->type = ISCSI_KEVENT_CONN_ERROR;
0896b752 1050 ev->r.connerror.error = error;
b5c7a12d
MC
1051 ev->r.connerror.cid = conn->cid;
1052 ev->r.connerror.sid = iscsi_conn_get_sid(conn);
1da177e4 1053
43a145a3 1054 iscsi_broadcast_skb(skb, GFP_ATOMIC);
1da177e4 1055
322d739d
MC
1056 iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)\n",
1057 error);
0896b752
AA
1058}
1059EXPORT_SYMBOL_GPL(iscsi_conn_error);
1060
1061static int
1062iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
1063 void *payload, int size)
1064{
1065 struct sk_buff *skb;
1066 struct nlmsghdr *nlh;
1067 int len = NLMSG_SPACE(size);
1068 int flags = multi ? NLM_F_MULTI : 0;
1069 int t = done ? NLMSG_DONE : type;
1070
43a145a3 1071 skb = alloc_skb(len, GFP_ATOMIC);
239a7dc2
MC
1072 if (!skb) {
1073 printk(KERN_ERR "Could not allocate skb to send reply.\n");
1074 return -ENOMEM;
1075 }
0896b752
AA
1076
1077 nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
1078 nlh->nlmsg_flags = flags;
1079 memcpy(NLMSG_DATA(nlh), payload, size);
43a145a3 1080 return iscsi_unicast_skb(skb, pid);
1da177e4 1081}
1da177e4 1082
7b8631b5 1083static int
5b940adf 1084iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
7b8631b5
MC
1085{
1086 struct iscsi_uevent *ev = NLMSG_DATA(nlh);
1087 struct iscsi_stats *stats;
1088 struct sk_buff *skbstat;
1089 struct iscsi_cls_conn *conn;
1090 struct nlmsghdr *nlhstat;
1091 struct iscsi_uevent *evstat;
790f39a2 1092 struct iscsi_internal *priv;
7b8631b5
MC
1093 int len = NLMSG_SPACE(sizeof(*ev) +
1094 sizeof(struct iscsi_stats) +
1095 sizeof(struct iscsi_stats_custom) *
1096 ISCSI_STATS_CUSTOM_MAX);
1097 int err = 0;
0896b752 1098
790f39a2
MC
1099 priv = iscsi_if_transport_lookup(transport);
1100 if (!priv)
1101 return -EINVAL;
1102
b5c7a12d 1103 conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid);
7b8631b5
MC
1104 if (!conn)
1105 return -EEXIST;
0896b752 1106
7b8631b5
MC
1107 do {
1108 int actual_size;
0896b752 1109
43a145a3 1110 skbstat = alloc_skb(len, GFP_ATOMIC);
7b8631b5 1111 if (!skbstat) {
322d739d
MC
1112 iscsi_cls_conn_printk(KERN_ERR, conn, "can not "
1113 "deliver stats: OOM\n");
7b8631b5
MC
1114 return -ENOMEM;
1115 }
1116
790f39a2 1117 nlhstat = __nlmsg_put(skbstat, priv->daemon_pid, 0, 0,
7b8631b5
MC
1118 (len - sizeof(*nlhstat)), 0);
1119 evstat = NLMSG_DATA(nlhstat);
1120 memset(evstat, 0, sizeof(*evstat));
1121 evstat->transport_handle = iscsi_handle(conn->transport);
1122 evstat->type = nlh->nlmsg_type;
b5c7a12d
MC
1123 evstat->u.get_stats.cid =
1124 ev->u.get_stats.cid;
1125 evstat->u.get_stats.sid =
1126 ev->u.get_stats.sid;
7b8631b5
MC
1127 stats = (struct iscsi_stats *)
1128 ((char*)evstat + sizeof(*evstat));
1129 memset(stats, 0, sizeof(*stats));
1130
7b7232f3 1131 transport->get_stats(conn, stats);
7b8631b5
MC
1132 actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
1133 sizeof(struct iscsi_stats) +
1134 sizeof(struct iscsi_stats_custom) *
1135 stats->custom_length);
1136 actual_size -= sizeof(*nlhstat);
1137 actual_size = NLMSG_LENGTH(actual_size);
5b940adf 1138 skb_trim(skbstat, NLMSG_ALIGN(actual_size));
7b8631b5
MC
1139 nlhstat->nlmsg_len = actual_size;
1140
43a145a3 1141 err = iscsi_unicast_skb(skbstat, priv->daemon_pid);
7b8631b5
MC
1142 } while (err < 0 && err != -ECONNREFUSED);
1143
1144 return err;
0896b752
AA
1145}
1146
53cb8a1f 1147/**
26974789
MC
1148 * iscsi_session_event - send session destr. completion event
1149 * @session: iscsi class session
1150 * @event: type of event
eb44820c 1151 */
26974789
MC
1152int iscsi_session_event(struct iscsi_cls_session *session,
1153 enum iscsi_uevent_e event)
53cb8a1f
MC
1154{
1155 struct iscsi_internal *priv;
53cb8a1f
MC
1156 struct Scsi_Host *shost;
1157 struct iscsi_uevent *ev;
1158 struct sk_buff *skb;
1159 struct nlmsghdr *nlh;
53cb8a1f
MC
1160 int rc, len = NLMSG_SPACE(sizeof(*ev));
1161
26974789 1162 priv = iscsi_if_transport_lookup(session->transport);
53cb8a1f
MC
1163 if (!priv)
1164 return -EINVAL;
53cb8a1f
MC
1165 shost = iscsi_session_to_shost(session);
1166
43a145a3 1167 skb = alloc_skb(len, GFP_KERNEL);
53cb8a1f 1168 if (!skb) {
322d739d
MC
1169 iscsi_cls_session_printk(KERN_ERR, session,
1170 "Cannot notify userspace of session "
1171 "event %u\n", event);
53cb8a1f
MC
1172 return -ENOMEM;
1173 }
1174
1175 nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
1176 ev = NLMSG_DATA(nlh);
26974789 1177 ev->transport_handle = iscsi_handle(session->transport);
53cb8a1f 1178
26974789
MC
1179 ev->type = event;
1180 switch (event) {
1181 case ISCSI_KEVENT_DESTROY_SESSION:
1182 ev->r.d_session.host_no = shost->host_no;
1183 ev->r.d_session.sid = session->sid;
1184 break;
1185 case ISCSI_KEVENT_CREATE_SESSION:
1186 ev->r.c_session_ret.host_no = shost->host_no;
1187 ev->r.c_session_ret.sid = session->sid;
1188 break;
1189 case ISCSI_KEVENT_UNBIND_SESSION:
1190 ev->r.unbind_session.host_no = shost->host_no;
1191 ev->r.unbind_session.sid = session->sid;
1192 break;
1193 default:
322d739d
MC
1194 iscsi_cls_session_printk(KERN_ERR, session, "Invalid event "
1195 "%u.\n", event);
26974789 1196 kfree_skb(skb);
53cb8a1f 1197 return -EINVAL;
53cb8a1f
MC
1198 }
1199
53cb8a1f
MC
1200 /*
1201 * this will occur if the daemon is not up, so we just warn
1202 * the user and when the daemon is restarted it will handle it
1203 */
43a145a3 1204 rc = iscsi_broadcast_skb(skb, GFP_KERNEL);
53cb8a1f 1205 if (rc < 0)
322d739d
MC
1206 iscsi_cls_session_printk(KERN_ERR, session,
1207 "Cannot notify userspace of session "
1208 "event %u. Check iscsi daemon\n",
1209 event);
53cb8a1f
MC
1210 return rc;
1211}
26974789 1212EXPORT_SYMBOL_GPL(iscsi_session_event);
53cb8a1f 1213
0896b752 1214static int
d82ff9be
MC
1215iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep,
1216 struct iscsi_uevent *ev, uint32_t initial_cmdsn,
40753caa 1217 uint16_t cmds_max, uint16_t queue_depth)
0896b752
AA
1218{
1219 struct iscsi_transport *transport = priv->iscsi_transport;
7b7232f3 1220 struct iscsi_cls_session *session;
d82ff9be 1221 uint32_t host_no;
0896b752 1222
d82ff9be 1223 session = transport->create_session(ep, cmds_max, queue_depth,
40753caa 1224 initial_cmdsn, &host_no);
7b7232f3 1225 if (!session)
7b8631b5 1226 return -ENOMEM;
0896b752 1227
40753caa 1228 ev->r.c_session_ret.host_no = host_no;
b5c7a12d 1229 ev->r.c_session_ret.sid = session->sid;
0896b752 1230 return 0;
0896b752
AA
1231}
1232
1233static int
7b7232f3 1234iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
0896b752 1235{
7b8631b5 1236 struct iscsi_cls_conn *conn;
7b7232f3 1237 struct iscsi_cls_session *session;
7b8631b5 1238
b5c7a12d
MC
1239 session = iscsi_session_lookup(ev->u.c_conn.sid);
1240 if (!session) {
322d739d 1241 printk(KERN_ERR "iscsi: invalid session %d.\n",
b5c7a12d 1242 ev->u.c_conn.sid);
7b8631b5 1243 return -EINVAL;
b5c7a12d 1244 }
0896b752 1245
7b7232f3 1246 conn = transport->create_conn(session, ev->u.c_conn.cid);
b5c7a12d 1247 if (!conn) {
322d739d
MC
1248 iscsi_cls_session_printk(KERN_ERR, session,
1249 "couldn't create a new connection.");
7b7232f3 1250 return -ENOMEM;
b5c7a12d 1251 }
0896b752 1252
b5c7a12d
MC
1253 ev->r.c_conn_ret.sid = session->sid;
1254 ev->r.c_conn_ret.cid = conn->cid;
0896b752 1255 return 0;
1da177e4
LT
1256}
1257
0896b752
AA
1258static int
1259iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
1260{
7b8631b5 1261 struct iscsi_cls_conn *conn;
0896b752 1262
b5c7a12d 1263 conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
0896b752 1264 if (!conn)
7b8631b5 1265 return -EINVAL;
0896b752 1266
7b8631b5
MC
1267 if (transport->destroy_conn)
1268 transport->destroy_conn(conn);
7b8631b5 1269 return 0;
0896b752
AA
1270}
1271
fd7255f5
MC
1272static int
1273iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
1274{
1275 char *data = (char*)ev + sizeof(*ev);
1276 struct iscsi_cls_conn *conn;
1277 struct iscsi_cls_session *session;
a54a52ca 1278 int err = 0, value = 0;
fd7255f5
MC
1279
1280 session = iscsi_session_lookup(ev->u.set_param.sid);
1281 conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
1282 if (!conn || !session)
1283 return -EINVAL;
1284
1285 switch (ev->u.set_param.param) {
30a6c652 1286 case ISCSI_PARAM_SESS_RECOVERY_TMO:
a54a52ca 1287 sscanf(data, "%d", &value);
30a6c652
MC
1288 if (value != 0)
1289 session->recovery_tmo = value;
1290 break;
fd7255f5 1291 default:
a54a52ca
MC
1292 err = transport->set_param(conn, ev->u.set_param.param,
1293 data, ev->u.set_param.len);
fd7255f5
MC
1294 }
1295
1296 return err;
1297}
1298
264faaaa
OG
1299static int
1300iscsi_if_transport_ep(struct iscsi_transport *transport,
1301 struct iscsi_uevent *ev, int msg_type)
1302{
d82ff9be 1303 struct iscsi_endpoint *ep;
264faaaa
OG
1304 struct sockaddr *dst_addr;
1305 int rc = 0;
1306
1307 switch (msg_type) {
1308 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
1309 if (!transport->ep_connect)
1310 return -EINVAL;
1311
1312 dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
d82ff9be
MC
1313 ep = transport->ep_connect(dst_addr,
1314 ev->u.ep_connect.non_blocking);
1315 if (IS_ERR(ep))
1316 return PTR_ERR(ep);
1317
1318 ev->r.ep_connect_ret.handle = ep->id;
264faaaa
OG
1319 break;
1320 case ISCSI_UEVENT_TRANSPORT_EP_POLL:
1321 if (!transport->ep_poll)
1322 return -EINVAL;
1323
d82ff9be
MC
1324 ep = iscsi_lookup_endpoint(ev->u.ep_poll.ep_handle);
1325 if (!ep)
1326 return -EINVAL;
1327
1328 ev->r.retcode = transport->ep_poll(ep,
264faaaa
OG
1329 ev->u.ep_poll.timeout_ms);
1330 break;
1331 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
1332 if (!transport->ep_disconnect)
1333 return -EINVAL;
1334
d82ff9be
MC
1335 ep = iscsi_lookup_endpoint(ev->u.ep_disconnect.ep_handle);
1336 if (!ep)
1337 return -EINVAL;
1338
1339 transport->ep_disconnect(ep);
264faaaa
OG
1340 break;
1341 }
1342 return rc;
1343}
1344
01cb225d
MC
1345static int
1346iscsi_tgt_dscvr(struct iscsi_transport *transport,
1347 struct iscsi_uevent *ev)
1348{
2174a04e 1349 struct Scsi_Host *shost;
01cb225d 1350 struct sockaddr *dst_addr;
2174a04e 1351 int err;
01cb225d
MC
1352
1353 if (!transport->tgt_dscvr)
1354 return -EINVAL;
1355
2174a04e
MC
1356 shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no);
1357 if (IS_ERR(shost)) {
1358 printk(KERN_ERR "target discovery could not find host no %u\n",
1359 ev->u.tgt_dscvr.host_no);
1360 return -ENODEV;
1361 }
1362
1363
01cb225d 1364 dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
2174a04e
MC
1365 err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type,
1366 ev->u.tgt_dscvr.enable, dst_addr);
1367 scsi_host_put(shost);
1368 return err;
01cb225d
MC
1369}
1370
1d9bf13a
MC
1371static int
1372iscsi_set_host_param(struct iscsi_transport *transport,
1373 struct iscsi_uevent *ev)
1374{
1375 char *data = (char*)ev + sizeof(*ev);
1376 struct Scsi_Host *shost;
1377 int err;
1378
1379 if (!transport->set_host_param)
1380 return -ENOSYS;
1381
1382 shost = scsi_host_lookup(ev->u.set_host_param.host_no);
1383 if (IS_ERR(shost)) {
1384 printk(KERN_ERR "set_host_param could not find host no %u\n",
1385 ev->u.set_host_param.host_no);
1386 return -ENODEV;
1387 }
1388
1389 err = transport->set_host_param(shost, ev->u.set_host_param.param,
1390 data, ev->u.set_host_param.len);
1391 scsi_host_put(shost);
1392 return err;
1393}
1394
0896b752
AA
1395static int
1396iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1397{
1398 int err = 0;
1399 struct iscsi_uevent *ev = NLMSG_DATA(nlh);
1400 struct iscsi_transport *transport = NULL;
1401 struct iscsi_internal *priv;
7b7232f3
MC
1402 struct iscsi_cls_session *session;
1403 struct iscsi_cls_conn *conn;
d82ff9be 1404 struct iscsi_endpoint *ep = NULL;
0896b752 1405
0896b752
AA
1406 priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
1407 if (!priv)
1408 return -EINVAL;
1409 transport = priv->iscsi_transport;
1410
7b7232f3
MC
1411 if (!try_module_get(transport->owner))
1412 return -EINVAL;
1413
790f39a2
MC
1414 priv->daemon_pid = NETLINK_CREDS(skb)->pid;
1415
0896b752
AA
1416 switch (nlh->nlmsg_type) {
1417 case ISCSI_UEVENT_CREATE_SESSION:
d82ff9be 1418 err = iscsi_if_create_session(priv, ep, ev,
40753caa
MC
1419 ev->u.c_session.initial_cmdsn,
1420 ev->u.c_session.cmds_max,
1421 ev->u.c_session.queue_depth);
1422 break;
1423 case ISCSI_UEVENT_CREATE_BOUND_SESSION:
d82ff9be
MC
1424 ep = iscsi_lookup_endpoint(ev->u.c_bound_session.ep_handle);
1425 if (!ep)
1426 return -EINVAL;
1427
1428 err = iscsi_if_create_session(priv, ep, ev,
40753caa
MC
1429 ev->u.c_bound_session.initial_cmdsn,
1430 ev->u.c_bound_session.cmds_max,
1431 ev->u.c_bound_session.queue_depth);
0896b752
AA
1432 break;
1433 case ISCSI_UEVENT_DESTROY_SESSION:
b5c7a12d 1434 session = iscsi_session_lookup(ev->u.d_session.sid);
26974789 1435 if (session)
7b7232f3 1436 transport->destroy_session(session);
26974789
MC
1437 else
1438 err = -EINVAL;
1439 break;
1440 case ISCSI_UEVENT_UNBIND_SESSION:
1441 session = iscsi_session_lookup(ev->u.d_session.sid);
1442 if (session)
1443 iscsi_unbind_session(session);
1444 else
7b7232f3 1445 err = -EINVAL;
0896b752
AA
1446 break;
1447 case ISCSI_UEVENT_CREATE_CONN:
1448 err = iscsi_if_create_conn(transport, ev);
1449 break;
1450 case ISCSI_UEVENT_DESTROY_CONN:
1451 err = iscsi_if_destroy_conn(transport, ev);
1452 break;
1453 case ISCSI_UEVENT_BIND_CONN:
b5c7a12d
MC
1454 session = iscsi_session_lookup(ev->u.b_conn.sid);
1455 conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
7b7232f3
MC
1456
1457 if (session && conn)
1458 ev->r.retcode = transport->bind_conn(session, conn,
264faaaa 1459 ev->u.b_conn.transport_eph,
7b7232f3
MC
1460 ev->u.b_conn.is_leading);
1461 else
1462 err = -EINVAL;
0896b752
AA
1463 break;
1464 case ISCSI_UEVENT_SET_PARAM:
fd7255f5 1465 err = iscsi_set_param(transport, ev);
0896b752
AA
1466 break;
1467 case ISCSI_UEVENT_START_CONN:
b5c7a12d 1468 conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
7b7232f3
MC
1469 if (conn)
1470 ev->r.retcode = transport->start_conn(conn);
1471 else
1472 err = -EINVAL;
0896b752
AA
1473 break;
1474 case ISCSI_UEVENT_STOP_CONN:
b5c7a12d 1475 conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
7b7232f3
MC
1476 if (conn)
1477 transport->stop_conn(conn, ev->u.stop_conn.flag);
1478 else
1479 err = -EINVAL;
0896b752
AA
1480 break;
1481 case ISCSI_UEVENT_SEND_PDU:
b5c7a12d 1482 conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
7b7232f3
MC
1483 if (conn)
1484 ev->r.retcode = transport->send_pdu(conn,
1485 (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
1486 (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
1487 ev->u.send_pdu.data_size);
1488 else
1489 err = -EINVAL;
0896b752
AA
1490 break;
1491 case ISCSI_UEVENT_GET_STATS:
5b940adf 1492 err = iscsi_if_get_stats(transport, nlh);
0896b752 1493 break;
264faaaa
OG
1494 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
1495 case ISCSI_UEVENT_TRANSPORT_EP_POLL:
1496 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
1497 err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
1498 break;
01cb225d
MC
1499 case ISCSI_UEVENT_TGT_DSCVR:
1500 err = iscsi_tgt_dscvr(transport, ev);
1501 break;
1d9bf13a
MC
1502 case ISCSI_UEVENT_SET_HOST_PARAM:
1503 err = iscsi_set_host_param(transport, ev);
1504 break;
0896b752 1505 default:
1d9bf13a 1506 err = -ENOSYS;
0896b752
AA
1507 break;
1508 }
1509
7b7232f3 1510 module_put(transport->owner);
0896b752
AA
1511 return err;
1512}
1513
b5c7a12d 1514/*
cd40b7d3
DL
1515 * Get message from skb. Each message is processed by iscsi_if_recv_msg.
1516 * Malformed skbs with wrong lengths or invalid creds are not processed.
b5c7a12d 1517 */
0896b752 1518static void
cd40b7d3 1519iscsi_if_rx(struct sk_buff *skb)
0896b752 1520{
0b950672 1521 mutex_lock(&rx_queue_mutex);
cd40b7d3
DL
1522 while (skb->len >= NLMSG_SPACE(0)) {
1523 int err;
1524 uint32_t rlen;
1525 struct nlmsghdr *nlh;
1526 struct iscsi_uevent *ev;
1527
1528 nlh = nlmsg_hdr(skb);
1529 if (nlh->nlmsg_len < sizeof(*nlh) ||
1530 skb->len < nlh->nlmsg_len) {
1531 break;
ee7f8e40 1532 }
ee7f8e40 1533
cd40b7d3
DL
1534 ev = NLMSG_DATA(nlh);
1535 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
1536 if (rlen > skb->len)
1537 rlen = skb->len;
0896b752 1538
cd40b7d3
DL
1539 err = iscsi_if_recv_msg(skb, nlh);
1540 if (err) {
1541 ev->type = ISCSI_KEVENT_IF_ERROR;
1542 ev->iferror = err;
0896b752 1543 }
cd40b7d3
DL
1544 do {
1545 /*
1546 * special case for GET_STATS:
1547 * on success - sending reply and stats from
1548 * inside of if_recv_msg(),
1549 * on error - fall through.
1550 */
1551 if (ev->type == ISCSI_UEVENT_GET_STATS && !err)
1552 break;
1553 err = iscsi_if_send_reply(
1554 NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
1555 nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
1556 } while (err < 0 && err != -ECONNREFUSED);
1557 skb_pull(skb, rlen);
0896b752 1558 }
0b950672 1559 mutex_unlock(&rx_queue_mutex);
0896b752 1560}
1da177e4 1561
fd7255f5 1562#define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store) \
ee959b00 1563struct device_attribute dev_attr_##_prefix##_##_name = \
fd7255f5
MC
1564 __ATTR(_name,_mode,_show,_store)
1565
1da177e4 1566/*
0896b752 1567 * iSCSI connection attrs
1da177e4 1568 */
a54a52ca 1569#define iscsi_conn_attr_show(param) \
0896b752 1570static ssize_t \
ee959b00
TJ
1571show_conn_param_##param(struct device *dev, \
1572 struct device_attribute *attr, char *buf) \
0896b752 1573{ \
ee959b00 1574 struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent); \
7b8631b5 1575 struct iscsi_transport *t = conn->transport; \
a54a52ca 1576 return t->get_conn_param(conn, param, buf); \
0896b752
AA
1577}
1578
a54a52ca
MC
1579#define iscsi_conn_attr(field, param) \
1580 iscsi_conn_attr_show(param) \
1581static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_param_##param, \
fd7255f5 1582 NULL);
0896b752 1583
a54a52ca
MC
1584iscsi_conn_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH);
1585iscsi_conn_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH);
1586iscsi_conn_attr(header_digest, ISCSI_PARAM_HDRDGST_EN);
1587iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN);
1588iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN);
1589iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN);
1590iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT);
1591iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT);
1592iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
1593iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
1594iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
f6d5180c
MC
1595iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
1596iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
1da177e4
LT
1597
1598/*
0896b752 1599 * iSCSI session attrs
1da177e4 1600 */
b2c64167 1601#define iscsi_session_attr_show(param, perm) \
fd7255f5 1602static ssize_t \
ee959b00
TJ
1603show_session_param_##param(struct device *dev, \
1604 struct device_attribute *attr, char *buf) \
fd7255f5 1605{ \
ee959b00
TJ
1606 struct iscsi_cls_session *session = \
1607 iscsi_dev_to_session(dev->parent); \
fd7255f5 1608 struct iscsi_transport *t = session->transport; \
b2c64167
MC
1609 \
1610 if (perm && !capable(CAP_SYS_ADMIN)) \
1611 return -EACCES; \
a54a52ca 1612 return t->get_session_param(session, param, buf); \
fd7255f5
MC
1613}
1614
b2c64167
MC
1615#define iscsi_session_attr(field, param, perm) \
1616 iscsi_session_attr_show(param, perm) \
a54a52ca 1617static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
fd7255f5
MC
1618 NULL);
1619
b2c64167
MC
1620iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
1621iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
1622iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
1623iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, 0);
1624iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, 0);
1625iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, 0);
1626iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, 0);
1627iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, 0);
1628iscsi_session_attr(erl, ISCSI_PARAM_ERL, 0);
1629iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT, 0);
1630iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
1631iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
1632iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
1633iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
4cd49ea1
MC
1634iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);
1635iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
1636iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
88dfd340
MC
1637iscsi_session_attr(ifacename, ISCSI_PARAM_IFACE_NAME, 0);
1638iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0)
1da177e4 1639
6eabafbe 1640static ssize_t
ee959b00
TJ
1641show_priv_session_state(struct device *dev, struct device_attribute *attr,
1642 char *buf)
6eabafbe 1643{
ee959b00 1644 struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
6eabafbe
MC
1645 return sprintf(buf, "%s\n", iscsi_session_state_name(session->state));
1646}
1647static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
1648 NULL);
1649
fd7255f5
MC
1650#define iscsi_priv_session_attr_show(field, format) \
1651static ssize_t \
ee959b00
TJ
1652show_priv_session_##field(struct device *dev, \
1653 struct device_attribute *attr, char *buf) \
fd7255f5 1654{ \
ee959b00
TJ
1655 struct iscsi_cls_session *session = \
1656 iscsi_dev_to_session(dev->parent); \
fd7255f5
MC
1657 return sprintf(buf, format"\n", session->field); \
1658}
1659
1660#define iscsi_priv_session_attr(field, format) \
1661 iscsi_priv_session_attr_show(field, format) \
1662static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \
1663 NULL)
30a6c652 1664iscsi_priv_session_attr(recovery_tmo, "%d");
fd7255f5 1665
1819dc81
MC
1666/*
1667 * iSCSI host attrs
1668 */
1669#define iscsi_host_attr_show(param) \
1670static ssize_t \
ee959b00
TJ
1671show_host_param_##param(struct device *dev, \
1672 struct device_attribute *attr, char *buf) \
1819dc81 1673{ \
ee959b00 1674 struct Scsi_Host *shost = transport_class_to_shost(dev); \
1819dc81
MC
1675 struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
1676 return priv->iscsi_transport->get_host_param(shost, param, buf); \
1677}
1678
1679#define iscsi_host_attr(field, param) \
1680 iscsi_host_attr_show(param) \
1681static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param, \
1682 NULL);
1683
d8196ed2 1684iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME);
1819dc81 1685iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
d8196ed2 1686iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
8ad5781a 1687iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
1819dc81 1688
fd7255f5
MC
1689#define SETUP_PRIV_SESSION_RD_ATTR(field) \
1690do { \
ee959b00 1691 priv->session_attrs[count] = &dev_attr_priv_sess_##field; \
fd7255f5
MC
1692 count++; \
1693} while (0)
1694
a54a52ca 1695
fd7255f5
MC
1696#define SETUP_SESSION_RD_ATTR(field, param_flag) \
1697do { \
1698 if (tt->param_mask & param_flag) { \
ee959b00 1699 priv->session_attrs[count] = &dev_attr_sess_##field; \
1da177e4 1700 count++; \
fd7255f5
MC
1701 } \
1702} while (0)
1703
fd7255f5
MC
1704#define SETUP_CONN_RD_ATTR(field, param_flag) \
1705do { \
1706 if (tt->param_mask & param_flag) { \
ee959b00 1707 priv->conn_attrs[count] = &dev_attr_conn_##field; \
fd7255f5
MC
1708 count++; \
1709 } \
1710} while (0)
1da177e4 1711
1819dc81
MC
1712#define SETUP_HOST_RD_ATTR(field, param_flag) \
1713do { \
1714 if (tt->host_param_mask & param_flag) { \
ee959b00 1715 priv->host_attrs[count] = &dev_attr_host_##field; \
1819dc81
MC
1716 count++; \
1717 } \
1718} while (0)
1719
0896b752
AA
1720static int iscsi_session_match(struct attribute_container *cont,
1721 struct device *dev)
1da177e4 1722{
7b8631b5 1723 struct iscsi_cls_session *session;
1da177e4 1724 struct Scsi_Host *shost;
0896b752
AA
1725 struct iscsi_internal *priv;
1726
1727 if (!iscsi_is_session_dev(dev))
1728 return 0;
1da177e4 1729
7b8631b5
MC
1730 session = iscsi_dev_to_session(dev);
1731 shost = iscsi_session_to_shost(session);
0896b752 1732 if (!shost->transportt)
1da177e4
LT
1733 return 0;
1734
0896b752
AA
1735 priv = to_iscsi_internal(shost->transportt);
1736 if (priv->session_cont.ac.class != &iscsi_session_class.class)
1da177e4
LT
1737 return 0;
1738
0896b752 1739 return &priv->session_cont.ac == cont;
1da177e4
LT
1740}
1741
0896b752
AA
1742static int iscsi_conn_match(struct attribute_container *cont,
1743 struct device *dev)
1744{
7b8631b5
MC
1745 struct iscsi_cls_session *session;
1746 struct iscsi_cls_conn *conn;
1da177e4 1747 struct Scsi_Host *shost;
0896b752 1748 struct iscsi_internal *priv;
1da177e4 1749
0896b752 1750 if (!iscsi_is_conn_dev(dev))
1da177e4
LT
1751 return 0;
1752
7b8631b5
MC
1753 conn = iscsi_dev_to_conn(dev);
1754 session = iscsi_dev_to_session(conn->dev.parent);
1755 shost = iscsi_session_to_shost(session);
1756
0896b752 1757 if (!shost->transportt)
1da177e4
LT
1758 return 0;
1759
0896b752
AA
1760 priv = to_iscsi_internal(shost->transportt);
1761 if (priv->conn_cont.ac.class != &iscsi_connection_class.class)
1762 return 0;
1da177e4 1763
0896b752
AA
1764 return &priv->conn_cont.ac == cont;
1765}
1766
30a6c652
MC
1767static int iscsi_host_match(struct attribute_container *cont,
1768 struct device *dev)
1769{
1770 struct Scsi_Host *shost;
1771 struct iscsi_internal *priv;
1772
1773 if (!scsi_is_host_device(dev))
1774 return 0;
1775
1776 shost = dev_to_shost(dev);
1777 if (!shost->transportt ||
1778 shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
1779 return 0;
1780
1781 priv = to_iscsi_internal(shost->transportt);
1782 return &priv->t.host_attrs.ac == cont;
1783}
1784
7b8631b5
MC
1785struct scsi_transport_template *
1786iscsi_register_transport(struct iscsi_transport *tt)
0896b752
AA
1787{
1788 struct iscsi_internal *priv;
1789 unsigned long flags;
1790 int count = 0, err;
1791
1792 BUG_ON(!tt);
1793
1794 priv = iscsi_if_transport_lookup(tt);
1795 if (priv)
7b8631b5 1796 return NULL;
0896b752 1797
24669f75 1798 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0896b752 1799 if (!priv)
7b8631b5 1800 return NULL;
0896b752 1801 INIT_LIST_HEAD(&priv->list);
53cb8a1f 1802 priv->daemon_pid = -1;
0896b752 1803 priv->iscsi_transport = tt;
30a6c652 1804 priv->t.user_scan = iscsi_user_scan;
a4804cd6
MC
1805 if (!(tt->caps & CAP_DATA_PATH_OFFLOAD))
1806 priv->t.create_work_queue = 1;
0896b752 1807
ee959b00
TJ
1808 priv->dev.class = &iscsi_transport_class;
1809 snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name);
1810 err = device_register(&priv->dev);
0896b752
AA
1811 if (err)
1812 goto free_priv;
1813
ee959b00 1814 err = sysfs_create_group(&priv->dev.kobj, &iscsi_transport_group);
0896b752 1815 if (err)
ee959b00 1816 goto unregister_dev;
0896b752 1817
30a6c652
MC
1818 /* host parameters */
1819 priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
1820 priv->t.host_attrs.ac.class = &iscsi_host_class.class;
1821 priv->t.host_attrs.ac.match = iscsi_host_match;
32c6e1b9 1822 priv->t.host_size = sizeof(struct iscsi_cls_host);
30a6c652
MC
1823 transport_container_register(&priv->t.host_attrs);
1824
d8196ed2 1825 SETUP_HOST_RD_ATTR(netdev, ISCSI_HOST_NETDEV_NAME);
22236961 1826 SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS);
1819dc81 1827 SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS);
8ad5781a 1828 SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME);
1819dc81
MC
1829 BUG_ON(count > ISCSI_HOST_ATTRS);
1830 priv->host_attrs[count] = NULL;
1831 count = 0;
1832
0896b752
AA
1833 /* connection parameters */
1834 priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
1835 priv->conn_cont.ac.class = &iscsi_connection_class.class;
1836 priv->conn_cont.ac.match = iscsi_conn_match;
1837 transport_container_register(&priv->conn_cont);
1da177e4 1838
fd7255f5
MC
1839 SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_MAX_RECV_DLENGTH);
1840 SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_MAX_XMIT_DLENGTH);
1841 SETUP_CONN_RD_ATTR(header_digest, ISCSI_HDRDGST_EN);
1842 SETUP_CONN_RD_ATTR(data_digest, ISCSI_DATADGST_EN);
1843 SETUP_CONN_RD_ATTR(ifmarker, ISCSI_IFMARKER_EN);
1844 SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN);
1845 SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS);
1846 SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT);
8d2860b3 1847 SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN);
a54a52ca
MC
1848 SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
1849 SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
f6d5180c
MC
1850 SETUP_CONN_RD_ATTR(ping_tmo, ISCSI_PING_TMO);
1851 SETUP_CONN_RD_ATTR(recv_tmo, ISCSI_RECV_TMO);
0896b752
AA
1852
1853 BUG_ON(count > ISCSI_CONN_ATTRS);
1854 priv->conn_attrs[count] = NULL;
1da177e4 1855 count = 0;
1da177e4 1856
0896b752
AA
1857 /* session parameters */
1858 priv->session_cont.ac.attrs = &priv->session_attrs[0];
1859 priv->session_cont.ac.class = &iscsi_session_class.class;
1860 priv->session_cont.ac.match = iscsi_session_match;
1861 transport_container_register(&priv->session_cont);
1862
fd7255f5
MC
1863 SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_INITIAL_R2T_EN);
1864 SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_MAX_R2T);
1865 SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_IMM_DATA_EN);
1866 SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_FIRST_BURST);
1867 SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_MAX_BURST);
1868 SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN);
1869 SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN);
1870 SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
a54a52ca
MC
1871 SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
1872 SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
b2c64167
MC
1873 SETUP_SESSION_RD_ATTR(password, ISCSI_USERNAME);
1874 SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN);
1875 SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD);
1876 SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN);
843c0a8a 1877 SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT);
4cd49ea1
MC
1878 SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO);
1879 SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO);
88dfd340
MC
1880 SETUP_SESSION_RD_ATTR(ifacename, ISCSI_IFACE_NAME);
1881 SETUP_SESSION_RD_ATTR(initiatorname, ISCSI_INITIATOR_NAME);
30a6c652 1882 SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
6eabafbe 1883 SETUP_PRIV_SESSION_RD_ATTR(state);
fd7255f5 1884
0896b752
AA
1885 BUG_ON(count > ISCSI_SESSION_ATTRS);
1886 priv->session_attrs[count] = NULL;
1887
1888 spin_lock_irqsave(&iscsi_transport_lock, flags);
1889 list_add(&priv->list, &iscsi_transports);
1890 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
1891
1892 printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
7b8631b5 1893 return &priv->t;
1da177e4 1894
ee959b00
TJ
1895unregister_dev:
1896 device_unregister(&priv->dev);
d82ff9be 1897 return NULL;
0896b752
AA
1898free_priv:
1899 kfree(priv);
7b8631b5 1900 return NULL;
1da177e4 1901}
0896b752
AA
1902EXPORT_SYMBOL_GPL(iscsi_register_transport);
1903
1904int iscsi_unregister_transport(struct iscsi_transport *tt)
1905{
1906 struct iscsi_internal *priv;
1907 unsigned long flags;
1908
1909 BUG_ON(!tt);
1910
0b950672 1911 mutex_lock(&rx_queue_mutex);
0896b752
AA
1912
1913 priv = iscsi_if_transport_lookup(tt);
1914 BUG_ON (!priv);
1915
0896b752
AA
1916 spin_lock_irqsave(&iscsi_transport_lock, flags);
1917 list_del(&priv->list);
1918 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
1919
1920 transport_container_unregister(&priv->conn_cont);
1921 transport_container_unregister(&priv->session_cont);
30a6c652 1922 transport_container_unregister(&priv->t.host_attrs);
0896b752 1923
ee959b00
TJ
1924 sysfs_remove_group(&priv->dev.kobj, &iscsi_transport_group);
1925 device_unregister(&priv->dev);
0b950672 1926 mutex_unlock(&rx_queue_mutex);
1da177e4 1927
0896b752
AA
1928 return 0;
1929}
1930EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
1da177e4 1931
1da177e4
LT
1932static __init int iscsi_transport_init(void)
1933{
0896b752 1934 int err;
1da177e4 1935
09492605 1936 printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
f4246b33
MC
1937 ISCSI_TRANSPORT_VERSION);
1938
41be1444
MC
1939 atomic_set(&iscsi_session_nr, 0);
1940
0896b752 1941 err = class_register(&iscsi_transport_class);
1da177e4
LT
1942 if (err)
1943 return err;
0896b752 1944
d82ff9be 1945 err = class_register(&iscsi_endpoint_class);
0896b752
AA
1946 if (err)
1947 goto unregister_transport_class;
1948
d82ff9be
MC
1949 err = transport_class_register(&iscsi_host_class);
1950 if (err)
1951 goto unregister_endpoint_class;
1952
30a6c652
MC
1953 err = transport_class_register(&iscsi_connection_class);
1954 if (err)
1955 goto unregister_host_class;
1956
0896b752
AA
1957 err = transport_class_register(&iscsi_session_class);
1958 if (err)
1959 goto unregister_conn_class;
1960
d82ff9be
MC
1961 nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx,
1962 NULL, THIS_MODULE);
0896b752
AA
1963 if (!nls) {
1964 err = -ENOBUFS;
43a145a3 1965 goto unregister_session_class;
0896b752
AA
1966 }
1967
d8bf541e
MC
1968 iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
1969 if (!iscsi_eh_timer_workq)
1970 goto release_nls;
1971
43a145a3 1972 return 0;
0896b752 1973
d8bf541e 1974release_nls:
b7c6ba6e 1975 netlink_kernel_release(nls);
0896b752
AA
1976unregister_session_class:
1977 transport_class_unregister(&iscsi_session_class);
1978unregister_conn_class:
1979 transport_class_unregister(&iscsi_connection_class);
30a6c652
MC
1980unregister_host_class:
1981 transport_class_unregister(&iscsi_host_class);
d82ff9be
MC
1982unregister_endpoint_class:
1983 class_unregister(&iscsi_endpoint_class);
0896b752
AA
1984unregister_transport_class:
1985 class_unregister(&iscsi_transport_class);
1986 return err;
1da177e4
LT
1987}
1988
1989static void __exit iscsi_transport_exit(void)
1990{
d8bf541e 1991 destroy_workqueue(iscsi_eh_timer_workq);
b7c6ba6e 1992 netlink_kernel_release(nls);
0896b752
AA
1993 transport_class_unregister(&iscsi_connection_class);
1994 transport_class_unregister(&iscsi_session_class);
30a6c652 1995 transport_class_unregister(&iscsi_host_class);
d82ff9be 1996 class_unregister(&iscsi_endpoint_class);
0896b752 1997 class_unregister(&iscsi_transport_class);
1da177e4
LT
1998}
1999
2000module_init(iscsi_transport_init);
2001module_exit(iscsi_transport_exit);
2002
0896b752
AA
2003MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
2004 "Dmitry Yusupov <dmitry_yus@yahoo.com>, "
2005 "Alex Aizman <itn780@yahoo.com>");
2006MODULE_DESCRIPTION("iSCSI Transport Interface");
1da177e4 2007MODULE_LICENSE("GPL");
f4246b33 2008MODULE_VERSION(ISCSI_TRANSPORT_VERSION);