]> err.no Git - linux-2.6/blob - drivers/scsi/scsi_transport_iscsi.c
[SCSI] iscsi class: Use our own workq instead of common system one.
[linux-2.6] / drivers / scsi / scsi_transport_iscsi.c
1 /*
2  * iSCSI transport class definitions
3  *
4  * Copyright (C) IBM Corporation, 2004
5  * Copyright (C) Mike Christie, 2004 - 2005
6  * Copyright (C) Dmitry Yusupov, 2004 - 2005
7  * Copyright (C) Alex Aizman, 2004 - 2005
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>
24 #include <linux/mutex.h>
25 #include <net/tcp.h>
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>
31 #include <scsi/iscsi_if.h>
32
33 #define ISCSI_SESSION_ATTRS 16
34 #define ISCSI_CONN_ATTRS 11
35 #define ISCSI_HOST_ATTRS 4
36 #define ISCSI_TRANSPORT_VERSION "2.0-724"
37
38 struct iscsi_internal {
39         int daemon_pid;
40         struct scsi_transport_template t;
41         struct iscsi_transport *iscsi_transport;
42         struct list_head list;
43         struct class_device cdev;
44
45         struct class_device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
46         struct transport_container conn_cont;
47         struct class_device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
48         struct transport_container session_cont;
49         struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
50 };
51
52 static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
53 static struct workqueue_struct *iscsi_eh_timer_workq;
54
55 /*
56  * list of registered transports and lock that must
57  * be held while accessing list. The iscsi_transport_lock must
58  * be acquired after the rx_queue_mutex.
59  */
60 static LIST_HEAD(iscsi_transports);
61 static DEFINE_SPINLOCK(iscsi_transport_lock);
62
63 #define to_iscsi_internal(tmpl) \
64         container_of(tmpl, struct iscsi_internal, t)
65
66 #define cdev_to_iscsi_internal(_cdev) \
67         container_of(_cdev, struct iscsi_internal, cdev)
68
69 static void iscsi_transport_release(struct class_device *cdev)
70 {
71         struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
72         kfree(priv);
73 }
74
75 /*
76  * iscsi_transport_class represents the iscsi_transports that are
77  * registered.
78  */
79 static struct class iscsi_transport_class = {
80         .name = "iscsi_transport",
81         .release = iscsi_transport_release,
82 };
83
84 static ssize_t
85 show_transport_handle(struct class_device *cdev, char *buf)
86 {
87         struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
88         return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport));
89 }
90 static CLASS_DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
91
92 #define show_transport_attr(name, format)                               \
93 static ssize_t                                                          \
94 show_transport_##name(struct class_device *cdev, char *buf)             \
95 {                                                                       \
96         struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);     \
97         return sprintf(buf, format"\n", priv->iscsi_transport->name);   \
98 }                                                                       \
99 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
100
101 show_transport_attr(caps, "0x%x");
102 show_transport_attr(max_lun, "%d");
103 show_transport_attr(max_conn, "%d");
104 show_transport_attr(max_cmd_len, "%d");
105
106 static struct attribute *iscsi_transport_attrs[] = {
107         &class_device_attr_handle.attr,
108         &class_device_attr_caps.attr,
109         &class_device_attr_max_lun.attr,
110         &class_device_attr_max_conn.attr,
111         &class_device_attr_max_cmd_len.attr,
112         NULL,
113 };
114
115 static struct attribute_group iscsi_transport_group = {
116         .attrs = iscsi_transport_attrs,
117 };
118
119 static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
120                             struct class_device *cdev)
121 {
122         struct Scsi_Host *shost = dev_to_shost(dev);
123         struct iscsi_host *ihost = shost->shost_data;
124
125         memset(ihost, 0, sizeof(*ihost));
126         INIT_LIST_HEAD(&ihost->sessions);
127         mutex_init(&ihost->mutex);
128         return 0;
129 }
130
131 static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
132                                "iscsi_host",
133                                iscsi_setup_host,
134                                NULL,
135                                NULL);
136
137 static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
138                                "iscsi_session",
139                                NULL,
140                                NULL,
141                                NULL);
142
143 static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
144                                "iscsi_connection",
145                                NULL,
146                                NULL,
147                                NULL);
148
149 static struct sock *nls;
150 static DEFINE_MUTEX(rx_queue_mutex);
151
152 static LIST_HEAD(sesslist);
153 static DEFINE_SPINLOCK(sesslock);
154 static LIST_HEAD(connlist);
155 static DEFINE_SPINLOCK(connlock);
156
157 static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
158 {
159         struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent);
160         return sess->sid;
161 }
162
163 /*
164  * Returns the matching session to a given sid
165  */
166 static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid)
167 {
168         unsigned long flags;
169         struct iscsi_cls_session *sess;
170
171         spin_lock_irqsave(&sesslock, flags);
172         list_for_each_entry(sess, &sesslist, sess_list) {
173                 if (sess->sid == sid) {
174                         spin_unlock_irqrestore(&sesslock, flags);
175                         return sess;
176                 }
177         }
178         spin_unlock_irqrestore(&sesslock, flags);
179         return NULL;
180 }
181
182 /*
183  * Returns the matching connection to a given sid / cid tuple
184  */
185 static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
186 {
187         unsigned long flags;
188         struct iscsi_cls_conn *conn;
189
190         spin_lock_irqsave(&connlock, flags);
191         list_for_each_entry(conn, &connlist, conn_list) {
192                 if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) {
193                         spin_unlock_irqrestore(&connlock, flags);
194                         return conn;
195                 }
196         }
197         spin_unlock_irqrestore(&connlock, flags);
198         return NULL;
199 }
200
201 /*
202  * The following functions can be used by LLDs that allocate
203  * their own scsi_hosts or by software iscsi LLDs
204  */
205 static void iscsi_session_release(struct device *dev)
206 {
207         struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
208         struct Scsi_Host *shost;
209
210         shost = iscsi_session_to_shost(session);
211         scsi_host_put(shost);
212         kfree(session);
213 }
214
215 static int iscsi_is_session_dev(const struct device *dev)
216 {
217         return dev->release == iscsi_session_release;
218 }
219
220 static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
221                            uint id, uint lun)
222 {
223         struct iscsi_host *ihost = shost->shost_data;
224         struct iscsi_cls_session *session;
225
226         mutex_lock(&ihost->mutex);
227         list_for_each_entry(session, &ihost->sessions, host_list) {
228                 if ((channel == SCAN_WILD_CARD || channel == 0) &&
229                     (id == SCAN_WILD_CARD || id == session->target_id))
230                         scsi_scan_target(&session->dev, 0,
231                                          session->target_id, lun, 1);
232         }
233         mutex_unlock(&ihost->mutex);
234
235         return 0;
236 }
237
238 static void session_recovery_timedout(struct work_struct *work)
239 {
240         struct iscsi_cls_session *session =
241                 container_of(work, struct iscsi_cls_session,
242                              recovery_work.work);
243
244         dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed "
245                   "out after %d secs\n", session->recovery_tmo);
246
247         if (session->transport->session_recovery_timedout)
248                 session->transport->session_recovery_timedout(session);
249
250         scsi_target_unblock(&session->dev);
251 }
252
253 void iscsi_unblock_session(struct iscsi_cls_session *session)
254 {
255         if (!cancel_delayed_work(&session->recovery_work))
256                 flush_workqueue(iscsi_eh_timer_workq);
257         scsi_target_unblock(&session->dev);
258 }
259 EXPORT_SYMBOL_GPL(iscsi_unblock_session);
260
261 void iscsi_block_session(struct iscsi_cls_session *session)
262 {
263         scsi_target_block(&session->dev);
264         queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work,
265                            session->recovery_tmo * HZ);
266 }
267 EXPORT_SYMBOL_GPL(iscsi_block_session);
268
269 struct iscsi_cls_session *
270 iscsi_alloc_session(struct Scsi_Host *shost,
271                     struct iscsi_transport *transport)
272 {
273         struct iscsi_cls_session *session;
274
275         session = kzalloc(sizeof(*session) + transport->sessiondata_size,
276                           GFP_KERNEL);
277         if (!session)
278                 return NULL;
279
280         session->transport = transport;
281         session->recovery_tmo = 120;
282         INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
283         INIT_LIST_HEAD(&session->host_list);
284         INIT_LIST_HEAD(&session->sess_list);
285
286         /* this is released in the dev's release function */
287         scsi_host_get(shost);
288         session->dev.parent = &shost->shost_gendev;
289         session->dev.release = iscsi_session_release;
290         device_initialize(&session->dev);
291         if (transport->sessiondata_size)
292                 session->dd_data = &session[1];
293         return session;
294 }
295 EXPORT_SYMBOL_GPL(iscsi_alloc_session);
296
297 int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
298 {
299         struct Scsi_Host *shost = iscsi_session_to_shost(session);
300         struct iscsi_host *ihost;
301         int err;
302
303         ihost = shost->shost_data;
304         session->sid = atomic_add_return(1, &iscsi_session_nr);
305         session->target_id = target_id;
306
307         snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
308                  session->sid);
309         err = device_add(&session->dev);
310         if (err) {
311                 dev_printk(KERN_ERR, &session->dev, "iscsi: could not "
312                            "register session's dev\n");
313                 goto release_host;
314         }
315         transport_register_device(&session->dev);
316
317         mutex_lock(&ihost->mutex);
318         list_add(&session->host_list, &ihost->sessions);
319         mutex_unlock(&ihost->mutex);
320         return 0;
321
322 release_host:
323         scsi_host_put(shost);
324         return err;
325 }
326 EXPORT_SYMBOL_GPL(iscsi_add_session);
327
328 /**
329  * iscsi_create_session - create iscsi class session
330  * @shost: scsi host
331  * @transport: iscsi transport
332  * @target_id: which target
333  *
334  * This can be called from a LLD or iscsi_transport.
335  */
336 struct iscsi_cls_session *
337 iscsi_create_session(struct Scsi_Host *shost,
338                      struct iscsi_transport *transport,
339                      unsigned int target_id)
340 {
341         struct iscsi_cls_session *session;
342
343         session = iscsi_alloc_session(shost, transport);
344         if (!session)
345                 return NULL;
346
347         if (iscsi_add_session(session, target_id)) {
348                 iscsi_free_session(session);
349                 return NULL;
350         }
351         return session;
352 }
353 EXPORT_SYMBOL_GPL(iscsi_create_session);
354
355 void iscsi_remove_session(struct iscsi_cls_session *session)
356 {
357         struct Scsi_Host *shost = iscsi_session_to_shost(session);
358         struct iscsi_host *ihost = shost->shost_data;
359
360         if (!cancel_delayed_work(&session->recovery_work))
361                 flush_workqueue(iscsi_eh_timer_workq);
362
363         mutex_lock(&ihost->mutex);
364         list_del(&session->host_list);
365         mutex_unlock(&ihost->mutex);
366
367         scsi_remove_target(&session->dev);
368
369         transport_unregister_device(&session->dev);
370         device_del(&session->dev);
371 }
372 EXPORT_SYMBOL_GPL(iscsi_remove_session);
373
374 void iscsi_free_session(struct iscsi_cls_session *session)
375 {
376         put_device(&session->dev);
377 }
378
379 EXPORT_SYMBOL_GPL(iscsi_free_session);
380
381 /**
382  * iscsi_destroy_session - destroy iscsi session
383  * @session: iscsi_session
384  *
385  * Can be called by a LLD or iscsi_transport. There must not be
386  * any running connections.
387  */
388 int iscsi_destroy_session(struct iscsi_cls_session *session)
389 {
390         iscsi_remove_session(session);
391         iscsi_free_session(session);
392         return 0;
393 }
394 EXPORT_SYMBOL_GPL(iscsi_destroy_session);
395
396 static void iscsi_conn_release(struct device *dev)
397 {
398         struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
399         struct device *parent = conn->dev.parent;
400
401         kfree(conn);
402         put_device(parent);
403 }
404
405 static int iscsi_is_conn_dev(const struct device *dev)
406 {
407         return dev->release == iscsi_conn_release;
408 }
409
410 /**
411  * iscsi_create_conn - create iscsi class connection
412  * @session: iscsi cls session
413  * @cid: connection id
414  *
415  * This can be called from a LLD or iscsi_transport. The connection
416  * is child of the session so cid must be unique for all connections
417  * on the session.
418  *
419  * Since we do not support MCS, cid will normally be zero. In some cases
420  * for software iscsi we could be trying to preallocate a connection struct
421  * in which case there could be two connection structs and cid would be
422  * non-zero.
423  */
424 struct iscsi_cls_conn *
425 iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
426 {
427         struct iscsi_transport *transport = session->transport;
428         struct iscsi_cls_conn *conn;
429         int err;
430
431         conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL);
432         if (!conn)
433                 return NULL;
434
435         if (transport->conndata_size)
436                 conn->dd_data = &conn[1];
437
438         INIT_LIST_HEAD(&conn->conn_list);
439         conn->transport = transport;
440         conn->cid = cid;
441
442         /* this is released in the dev's release function */
443         if (!get_device(&session->dev))
444                 goto free_conn;
445
446         snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
447                  session->sid, cid);
448         conn->dev.parent = &session->dev;
449         conn->dev.release = iscsi_conn_release;
450         err = device_register(&conn->dev);
451         if (err) {
452                 dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register "
453                            "connection's dev\n");
454                 goto release_parent_ref;
455         }
456         transport_register_device(&conn->dev);
457         return conn;
458
459 release_parent_ref:
460         put_device(&session->dev);
461 free_conn:
462         kfree(conn);
463         return NULL;
464 }
465
466 EXPORT_SYMBOL_GPL(iscsi_create_conn);
467
468 /**
469  * iscsi_destroy_conn - destroy iscsi class connection
470  * @conn: iscsi cls session
471  *
472  * This can be called from an LLD or iscsi_transport.
473  */
474 int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
475 {
476         transport_unregister_device(&conn->dev);
477         device_unregister(&conn->dev);
478         return 0;
479 }
480
481 EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
482
483 /*
484  * iscsi interface functions
485  */
486 static struct iscsi_internal *
487 iscsi_if_transport_lookup(struct iscsi_transport *tt)
488 {
489         struct iscsi_internal *priv;
490         unsigned long flags;
491
492         spin_lock_irqsave(&iscsi_transport_lock, flags);
493         list_for_each_entry(priv, &iscsi_transports, list) {
494                 if (tt == priv->iscsi_transport) {
495                         spin_unlock_irqrestore(&iscsi_transport_lock, flags);
496                         return priv;
497                 }
498         }
499         spin_unlock_irqrestore(&iscsi_transport_lock, flags);
500         return NULL;
501 }
502
503 static int
504 iscsi_broadcast_skb(struct sk_buff *skb, gfp_t gfp)
505 {
506         int rc;
507
508         rc = netlink_broadcast(nls, skb, 0, 1, gfp);
509         if (rc < 0) {
510                 printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc);
511                 return rc;
512         }
513
514         return 0;
515 }
516
517 static int
518 iscsi_unicast_skb(struct sk_buff *skb, int pid)
519 {
520         int rc;
521
522         rc = netlink_unicast(nls, skb, pid, MSG_DONTWAIT);
523         if (rc < 0) {
524                 printk(KERN_ERR "iscsi: can not unicast skb (%d)\n", rc);
525                 return rc;
526         }
527
528         return 0;
529 }
530
531 int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
532                    char *data, uint32_t data_size)
533 {
534         struct nlmsghdr *nlh;
535         struct sk_buff *skb;
536         struct iscsi_uevent *ev;
537         char *pdu;
538         struct iscsi_internal *priv;
539         int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
540                               data_size);
541
542         priv = iscsi_if_transport_lookup(conn->transport);
543         if (!priv)
544                 return -EINVAL;
545
546         skb = alloc_skb(len, GFP_ATOMIC);
547         if (!skb) {
548                 iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED);
549                 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
550                            "control PDU: OOM\n");
551                 return -ENOMEM;
552         }
553
554         nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
555         ev = NLMSG_DATA(nlh);
556         memset(ev, 0, sizeof(*ev));
557         ev->transport_handle = iscsi_handle(conn->transport);
558         ev->type = ISCSI_KEVENT_RECV_PDU;
559         ev->r.recv_req.cid = conn->cid;
560         ev->r.recv_req.sid = iscsi_conn_get_sid(conn);
561         pdu = (char*)ev + sizeof(*ev);
562         memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
563         memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
564
565         return iscsi_unicast_skb(skb, priv->daemon_pid);
566 }
567 EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
568
569 void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
570 {
571         struct nlmsghdr *nlh;
572         struct sk_buff  *skb;
573         struct iscsi_uevent *ev;
574         struct iscsi_internal *priv;
575         int len = NLMSG_SPACE(sizeof(*ev));
576
577         priv = iscsi_if_transport_lookup(conn->transport);
578         if (!priv)
579                 return;
580
581         skb = alloc_skb(len, GFP_ATOMIC);
582         if (!skb) {
583                 dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored "
584                           "conn error (%d)\n", error);
585                 return;
586         }
587
588         nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
589         ev = NLMSG_DATA(nlh);
590         ev->transport_handle = iscsi_handle(conn->transport);
591         ev->type = ISCSI_KEVENT_CONN_ERROR;
592         ev->r.connerror.error = error;
593         ev->r.connerror.cid = conn->cid;
594         ev->r.connerror.sid = iscsi_conn_get_sid(conn);
595
596         iscsi_broadcast_skb(skb, GFP_ATOMIC);
597
598         dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
599                    error);
600 }
601 EXPORT_SYMBOL_GPL(iscsi_conn_error);
602
603 static int
604 iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
605                       void *payload, int size)
606 {
607         struct sk_buff  *skb;
608         struct nlmsghdr *nlh;
609         int len = NLMSG_SPACE(size);
610         int flags = multi ? NLM_F_MULTI : 0;
611         int t = done ? NLMSG_DONE : type;
612
613         skb = alloc_skb(len, GFP_ATOMIC);
614         if (!skb) {
615                 printk(KERN_ERR "Could not allocate skb to send reply.\n");
616                 return -ENOMEM;
617         }
618
619         nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
620         nlh->nlmsg_flags = flags;
621         memcpy(NLMSG_DATA(nlh), payload, size);
622         return iscsi_unicast_skb(skb, pid);
623 }
624
625 static int
626 iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
627 {
628         struct iscsi_uevent *ev = NLMSG_DATA(nlh);
629         struct iscsi_stats *stats;
630         struct sk_buff *skbstat;
631         struct iscsi_cls_conn *conn;
632         struct nlmsghdr *nlhstat;
633         struct iscsi_uevent *evstat;
634         struct iscsi_internal *priv;
635         int len = NLMSG_SPACE(sizeof(*ev) +
636                               sizeof(struct iscsi_stats) +
637                               sizeof(struct iscsi_stats_custom) *
638                               ISCSI_STATS_CUSTOM_MAX);
639         int err = 0;
640
641         priv = iscsi_if_transport_lookup(transport);
642         if (!priv)
643                 return -EINVAL;
644
645         conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid);
646         if (!conn)
647                 return -EEXIST;
648
649         do {
650                 int actual_size;
651
652                 skbstat = alloc_skb(len, GFP_ATOMIC);
653                 if (!skbstat) {
654                         dev_printk(KERN_ERR, &conn->dev, "iscsi: can not "
655                                    "deliver stats: OOM\n");
656                         return -ENOMEM;
657                 }
658
659                 nlhstat = __nlmsg_put(skbstat, priv->daemon_pid, 0, 0,
660                                       (len - sizeof(*nlhstat)), 0);
661                 evstat = NLMSG_DATA(nlhstat);
662                 memset(evstat, 0, sizeof(*evstat));
663                 evstat->transport_handle = iscsi_handle(conn->transport);
664                 evstat->type = nlh->nlmsg_type;
665                 evstat->u.get_stats.cid =
666                         ev->u.get_stats.cid;
667                 evstat->u.get_stats.sid =
668                         ev->u.get_stats.sid;
669                 stats = (struct iscsi_stats *)
670                         ((char*)evstat + sizeof(*evstat));
671                 memset(stats, 0, sizeof(*stats));
672
673                 transport->get_stats(conn, stats);
674                 actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
675                                           sizeof(struct iscsi_stats) +
676                                           sizeof(struct iscsi_stats_custom) *
677                                           stats->custom_length);
678                 actual_size -= sizeof(*nlhstat);
679                 actual_size = NLMSG_LENGTH(actual_size);
680                 skb_trim(skbstat, NLMSG_ALIGN(actual_size));
681                 nlhstat->nlmsg_len = actual_size;
682
683                 err = iscsi_unicast_skb(skbstat, priv->daemon_pid);
684         } while (err < 0 && err != -ECONNREFUSED);
685
686         return err;
687 }
688
689 /**
690  * iscsi_if_destroy_session_done - send session destr. completion event
691  * @conn: last connection for session
692  *
693  * This is called by HW iscsi LLDs to notify userpsace that its HW has
694  * removed a session.
695  */
696 int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn)
697 {
698         struct iscsi_internal *priv;
699         struct iscsi_cls_session *session;
700         struct Scsi_Host *shost;
701         struct iscsi_uevent *ev;
702         struct sk_buff  *skb;
703         struct nlmsghdr *nlh;
704         unsigned long flags;
705         int rc, len = NLMSG_SPACE(sizeof(*ev));
706
707         priv = iscsi_if_transport_lookup(conn->transport);
708         if (!priv)
709                 return -EINVAL;
710
711         session = iscsi_dev_to_session(conn->dev.parent);
712         shost = iscsi_session_to_shost(session);
713
714         skb = alloc_skb(len, GFP_KERNEL);
715         if (!skb) {
716                 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
717                           "session creation event\n");
718                 return -ENOMEM;
719         }
720
721         nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
722         ev = NLMSG_DATA(nlh);
723         ev->transport_handle = iscsi_handle(conn->transport);
724         ev->type = ISCSI_KEVENT_DESTROY_SESSION;
725         ev->r.d_session.host_no = shost->host_no;
726         ev->r.d_session.sid = session->sid;
727
728         /*
729          * this will occur if the daemon is not up, so we just warn
730          * the user and when the daemon is restarted it will handle it
731          */
732         rc = iscsi_broadcast_skb(skb, GFP_KERNEL);
733         if (rc < 0)
734                 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
735                           "session destruction event. Check iscsi daemon\n");
736
737         spin_lock_irqsave(&sesslock, flags);
738         list_del(&session->sess_list);
739         spin_unlock_irqrestore(&sesslock, flags);
740
741         spin_lock_irqsave(&connlock, flags);
742         conn->active = 0;
743         list_del(&conn->conn_list);
744         spin_unlock_irqrestore(&connlock, flags);
745
746         return rc;
747 }
748 EXPORT_SYMBOL_GPL(iscsi_if_destroy_session_done);
749
750 /**
751  * iscsi_if_create_session_done - send session creation completion event
752  * @conn: leading connection for session
753  *
754  * This is called by HW iscsi LLDs to notify userpsace that its HW has
755  * created a session or a existing session is back in the logged in state.
756  */
757 int iscsi_if_create_session_done(struct iscsi_cls_conn *conn)
758 {
759         struct iscsi_internal *priv;
760         struct iscsi_cls_session *session;
761         struct Scsi_Host *shost;
762         struct iscsi_uevent *ev;
763         struct sk_buff  *skb;
764         struct nlmsghdr *nlh;
765         unsigned long flags;
766         int rc, len = NLMSG_SPACE(sizeof(*ev));
767
768         priv = iscsi_if_transport_lookup(conn->transport);
769         if (!priv)
770                 return -EINVAL;
771
772         session = iscsi_dev_to_session(conn->dev.parent);
773         shost = iscsi_session_to_shost(session);
774
775         skb = alloc_skb(len, GFP_KERNEL);
776         if (!skb) {
777                 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
778                           "session creation event\n");
779                 return -ENOMEM;
780         }
781
782         nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
783         ev = NLMSG_DATA(nlh);
784         ev->transport_handle = iscsi_handle(conn->transport);
785         ev->type = ISCSI_UEVENT_CREATE_SESSION;
786         ev->r.c_session_ret.host_no = shost->host_no;
787         ev->r.c_session_ret.sid = session->sid;
788
789         /*
790          * this will occur if the daemon is not up, so we just warn
791          * the user and when the daemon is restarted it will handle it
792          */
793         rc = iscsi_broadcast_skb(skb, GFP_KERNEL);
794         if (rc < 0)
795                 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
796                           "session creation event. Check iscsi daemon\n");
797
798         spin_lock_irqsave(&sesslock, flags);
799         list_add(&session->sess_list, &sesslist);
800         spin_unlock_irqrestore(&sesslock, flags);
801
802         spin_lock_irqsave(&connlock, flags);
803         list_add(&conn->conn_list, &connlist);
804         conn->active = 1;
805         spin_unlock_irqrestore(&connlock, flags);
806         return rc;
807 }
808 EXPORT_SYMBOL_GPL(iscsi_if_create_session_done);
809
810 static int
811 iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
812 {
813         struct iscsi_transport *transport = priv->iscsi_transport;
814         struct iscsi_cls_session *session;
815         unsigned long flags;
816         uint32_t hostno;
817
818         session = transport->create_session(transport, &priv->t,
819                                             ev->u.c_session.cmds_max,
820                                             ev->u.c_session.queue_depth,
821                                             ev->u.c_session.initial_cmdsn,
822                                             &hostno);
823         if (!session)
824                 return -ENOMEM;
825
826         spin_lock_irqsave(&sesslock, flags);
827         list_add(&session->sess_list, &sesslist);
828         spin_unlock_irqrestore(&sesslock, flags);
829
830         ev->r.c_session_ret.host_no = hostno;
831         ev->r.c_session_ret.sid = session->sid;
832         return 0;
833 }
834
835 static int
836 iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
837 {
838         struct iscsi_cls_conn *conn;
839         struct iscsi_cls_session *session;
840         unsigned long flags;
841
842         session = iscsi_session_lookup(ev->u.c_conn.sid);
843         if (!session) {
844                 printk(KERN_ERR "iscsi: invalid session %d\n",
845                        ev->u.c_conn.sid);
846                 return -EINVAL;
847         }
848
849         conn = transport->create_conn(session, ev->u.c_conn.cid);
850         if (!conn) {
851                 printk(KERN_ERR "iscsi: couldn't create a new "
852                            "connection for session %d\n",
853                            session->sid);
854                 return -ENOMEM;
855         }
856
857         ev->r.c_conn_ret.sid = session->sid;
858         ev->r.c_conn_ret.cid = conn->cid;
859
860         spin_lock_irqsave(&connlock, flags);
861         list_add(&conn->conn_list, &connlist);
862         conn->active = 1;
863         spin_unlock_irqrestore(&connlock, flags);
864
865         return 0;
866 }
867
868 static int
869 iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
870 {
871         unsigned long flags;
872         struct iscsi_cls_conn *conn;
873
874         conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
875         if (!conn)
876                 return -EINVAL;
877         spin_lock_irqsave(&connlock, flags);
878         conn->active = 0;
879         list_del(&conn->conn_list);
880         spin_unlock_irqrestore(&connlock, flags);
881
882         if (transport->destroy_conn)
883                 transport->destroy_conn(conn);
884         return 0;
885 }
886
887 static int
888 iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
889 {
890         char *data = (char*)ev + sizeof(*ev);
891         struct iscsi_cls_conn *conn;
892         struct iscsi_cls_session *session;
893         int err = 0, value = 0;
894
895         session = iscsi_session_lookup(ev->u.set_param.sid);
896         conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
897         if (!conn || !session)
898                 return -EINVAL;
899
900         switch (ev->u.set_param.param) {
901         case ISCSI_PARAM_SESS_RECOVERY_TMO:
902                 sscanf(data, "%d", &value);
903                 if (value != 0)
904                         session->recovery_tmo = value;
905                 break;
906         default:
907                 err = transport->set_param(conn, ev->u.set_param.param,
908                                            data, ev->u.set_param.len);
909         }
910
911         return err;
912 }
913
914 static int
915 iscsi_if_transport_ep(struct iscsi_transport *transport,
916                       struct iscsi_uevent *ev, int msg_type)
917 {
918         struct sockaddr *dst_addr;
919         int rc = 0;
920
921         switch (msg_type) {
922         case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
923                 if (!transport->ep_connect)
924                         return -EINVAL;
925
926                 dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
927                 rc = transport->ep_connect(dst_addr,
928                                            ev->u.ep_connect.non_blocking,
929                                            &ev->r.ep_connect_ret.handle);
930                 break;
931         case ISCSI_UEVENT_TRANSPORT_EP_POLL:
932                 if (!transport->ep_poll)
933                         return -EINVAL;
934
935                 ev->r.retcode = transport->ep_poll(ev->u.ep_poll.ep_handle,
936                                                    ev->u.ep_poll.timeout_ms);
937                 break;
938         case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
939                 if (!transport->ep_disconnect)
940                         return -EINVAL;
941
942                 transport->ep_disconnect(ev->u.ep_disconnect.ep_handle);
943                 break;
944         }
945         return rc;
946 }
947
948 static int
949 iscsi_tgt_dscvr(struct iscsi_transport *transport,
950                 struct iscsi_uevent *ev)
951 {
952         struct Scsi_Host *shost;
953         struct sockaddr *dst_addr;
954         int err;
955
956         if (!transport->tgt_dscvr)
957                 return -EINVAL;
958
959         shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no);
960         if (IS_ERR(shost)) {
961                 printk(KERN_ERR "target discovery could not find host no %u\n",
962                        ev->u.tgt_dscvr.host_no);
963                 return -ENODEV;
964         }
965
966
967         dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
968         err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type,
969                                    ev->u.tgt_dscvr.enable, dst_addr);
970         scsi_host_put(shost);
971         return err;
972 }
973
974 static int
975 iscsi_set_host_param(struct iscsi_transport *transport,
976                      struct iscsi_uevent *ev)
977 {
978         char *data = (char*)ev + sizeof(*ev);
979         struct Scsi_Host *shost;
980         int err;
981
982         if (!transport->set_host_param)
983                 return -ENOSYS;
984
985         shost = scsi_host_lookup(ev->u.set_host_param.host_no);
986         if (IS_ERR(shost)) {
987                 printk(KERN_ERR "set_host_param could not find host no %u\n",
988                        ev->u.set_host_param.host_no);
989                 return -ENODEV;
990         }
991
992         err = transport->set_host_param(shost, ev->u.set_host_param.param,
993                                         data, ev->u.set_host_param.len);
994         scsi_host_put(shost);
995         return err;
996 }
997
998 static int
999 iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1000 {
1001         int err = 0;
1002         struct iscsi_uevent *ev = NLMSG_DATA(nlh);
1003         struct iscsi_transport *transport = NULL;
1004         struct iscsi_internal *priv;
1005         struct iscsi_cls_session *session;
1006         struct iscsi_cls_conn *conn;
1007         unsigned long flags;
1008
1009         priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
1010         if (!priv)
1011                 return -EINVAL;
1012         transport = priv->iscsi_transport;
1013
1014         if (!try_module_get(transport->owner))
1015                 return -EINVAL;
1016
1017         priv->daemon_pid = NETLINK_CREDS(skb)->pid;
1018
1019         switch (nlh->nlmsg_type) {
1020         case ISCSI_UEVENT_CREATE_SESSION:
1021                 err = iscsi_if_create_session(priv, ev);
1022                 break;
1023         case ISCSI_UEVENT_DESTROY_SESSION:
1024                 session = iscsi_session_lookup(ev->u.d_session.sid);
1025                 if (session) {
1026                         spin_lock_irqsave(&sesslock, flags);
1027                         list_del(&session->sess_list);
1028                         spin_unlock_irqrestore(&sesslock, flags);
1029
1030                         transport->destroy_session(session);
1031                 } else
1032                         err = -EINVAL;
1033                 break;
1034         case ISCSI_UEVENT_CREATE_CONN:
1035                 err = iscsi_if_create_conn(transport, ev);
1036                 break;
1037         case ISCSI_UEVENT_DESTROY_CONN:
1038                 err = iscsi_if_destroy_conn(transport, ev);
1039                 break;
1040         case ISCSI_UEVENT_BIND_CONN:
1041                 session = iscsi_session_lookup(ev->u.b_conn.sid);
1042                 conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
1043
1044                 if (session && conn)
1045                         ev->r.retcode = transport->bind_conn(session, conn,
1046                                         ev->u.b_conn.transport_eph,
1047                                         ev->u.b_conn.is_leading);
1048                 else
1049                         err = -EINVAL;
1050                 break;
1051         case ISCSI_UEVENT_SET_PARAM:
1052                 err = iscsi_set_param(transport, ev);
1053                 break;
1054         case ISCSI_UEVENT_START_CONN:
1055                 conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
1056                 if (conn)
1057                         ev->r.retcode = transport->start_conn(conn);
1058                 else
1059                         err = -EINVAL;
1060                 break;
1061         case ISCSI_UEVENT_STOP_CONN:
1062                 conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
1063                 if (conn)
1064                         transport->stop_conn(conn, ev->u.stop_conn.flag);
1065                 else
1066                         err = -EINVAL;
1067                 break;
1068         case ISCSI_UEVENT_SEND_PDU:
1069                 conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
1070                 if (conn)
1071                         ev->r.retcode = transport->send_pdu(conn,
1072                                 (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
1073                                 (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
1074                                 ev->u.send_pdu.data_size);
1075                 else
1076                         err = -EINVAL;
1077                 break;
1078         case ISCSI_UEVENT_GET_STATS:
1079                 err = iscsi_if_get_stats(transport, nlh);
1080                 break;
1081         case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
1082         case ISCSI_UEVENT_TRANSPORT_EP_POLL:
1083         case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
1084                 err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
1085                 break;
1086         case ISCSI_UEVENT_TGT_DSCVR:
1087                 err = iscsi_tgt_dscvr(transport, ev);
1088                 break;
1089         case ISCSI_UEVENT_SET_HOST_PARAM:
1090                 err = iscsi_set_host_param(transport, ev);
1091                 break;
1092         default:
1093                 err = -ENOSYS;
1094                 break;
1095         }
1096
1097         module_put(transport->owner);
1098         return err;
1099 }
1100
1101 /*
1102  * Get message from skb.  Each message is processed by iscsi_if_recv_msg.
1103  * Malformed skbs with wrong lengths or invalid creds are not processed.
1104  */
1105 static void
1106 iscsi_if_rx(struct sk_buff *skb)
1107 {
1108         mutex_lock(&rx_queue_mutex);
1109         while (skb->len >= NLMSG_SPACE(0)) {
1110                 int err;
1111                 uint32_t rlen;
1112                 struct nlmsghdr *nlh;
1113                 struct iscsi_uevent *ev;
1114
1115                 nlh = nlmsg_hdr(skb);
1116                 if (nlh->nlmsg_len < sizeof(*nlh) ||
1117                     skb->len < nlh->nlmsg_len) {
1118                         break;
1119                 }
1120
1121                 ev = NLMSG_DATA(nlh);
1122                 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
1123                 if (rlen > skb->len)
1124                         rlen = skb->len;
1125
1126                 err = iscsi_if_recv_msg(skb, nlh);
1127                 if (err) {
1128                         ev->type = ISCSI_KEVENT_IF_ERROR;
1129                         ev->iferror = err;
1130                 }
1131                 do {
1132                         /*
1133                          * special case for GET_STATS:
1134                          * on success - sending reply and stats from
1135                          * inside of if_recv_msg(),
1136                          * on error - fall through.
1137                          */
1138                         if (ev->type == ISCSI_UEVENT_GET_STATS && !err)
1139                                 break;
1140                         err = iscsi_if_send_reply(
1141                                 NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
1142                                 nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
1143                 } while (err < 0 && err != -ECONNREFUSED);
1144                 skb_pull(skb, rlen);
1145         }
1146         mutex_unlock(&rx_queue_mutex);
1147 }
1148
1149 #define iscsi_cdev_to_conn(_cdev) \
1150         iscsi_dev_to_conn(_cdev->dev)
1151
1152 #define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store)              \
1153 struct class_device_attribute class_device_attr_##_prefix##_##_name =   \
1154         __ATTR(_name,_mode,_show,_store)
1155
1156 /*
1157  * iSCSI connection attrs
1158  */
1159 #define iscsi_conn_attr_show(param)                                     \
1160 static ssize_t                                                          \
1161 show_conn_param_##param(struct class_device *cdev, char *buf)           \
1162 {                                                                       \
1163         struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);         \
1164         struct iscsi_transport *t = conn->transport;                    \
1165         return t->get_conn_param(conn, param, buf);                     \
1166 }
1167
1168 #define iscsi_conn_attr(field, param)                                   \
1169         iscsi_conn_attr_show(param)                                     \
1170 static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_param_##param,  \
1171                         NULL);
1172
1173 iscsi_conn_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH);
1174 iscsi_conn_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH);
1175 iscsi_conn_attr(header_digest, ISCSI_PARAM_HDRDGST_EN);
1176 iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN);
1177 iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN);
1178 iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN);
1179 iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT);
1180 iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT);
1181 iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
1182 iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
1183 iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
1184
1185 #define iscsi_cdev_to_session(_cdev) \
1186         iscsi_dev_to_session(_cdev->dev)
1187
1188 /*
1189  * iSCSI session attrs
1190  */
1191 #define iscsi_session_attr_show(param, perm)                            \
1192 static ssize_t                                                          \
1193 show_session_param_##param(struct class_device *cdev, char *buf)        \
1194 {                                                                       \
1195         struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
1196         struct iscsi_transport *t = session->transport;                 \
1197                                                                         \
1198         if (perm && !capable(CAP_SYS_ADMIN))                            \
1199                 return -EACCES;                                         \
1200         return t->get_session_param(session, param, buf);               \
1201 }
1202
1203 #define iscsi_session_attr(field, param, perm)                          \
1204         iscsi_session_attr_show(param, perm)                            \
1205 static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
1206                         NULL);
1207
1208 iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
1209 iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
1210 iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
1211 iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, 0);
1212 iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, 0);
1213 iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, 0);
1214 iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, 0);
1215 iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, 0);
1216 iscsi_session_attr(erl, ISCSI_PARAM_ERL, 0);
1217 iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT, 0);
1218 iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
1219 iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
1220 iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
1221 iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
1222 iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 1);
1223
1224 #define iscsi_priv_session_attr_show(field, format)                     \
1225 static ssize_t                                                          \
1226 show_priv_session_##field(struct class_device *cdev, char *buf)         \
1227 {                                                                       \
1228         struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);\
1229         return sprintf(buf, format"\n", session->field);                \
1230 }
1231
1232 #define iscsi_priv_session_attr(field, format)                          \
1233         iscsi_priv_session_attr_show(field, format)                     \
1234 static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \
1235                         NULL)
1236 iscsi_priv_session_attr(recovery_tmo, "%d");
1237
1238 /*
1239  * iSCSI host attrs
1240  */
1241 #define iscsi_host_attr_show(param)                                     \
1242 static ssize_t                                                          \
1243 show_host_param_##param(struct class_device *cdev, char *buf)           \
1244 {                                                                       \
1245         struct Scsi_Host *shost = transport_class_to_shost(cdev);       \
1246         struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
1247         return priv->iscsi_transport->get_host_param(shost, param, buf); \
1248 }
1249
1250 #define iscsi_host_attr(field, param)                                   \
1251         iscsi_host_attr_show(param)                                     \
1252 static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param,  \
1253                         NULL);
1254
1255 iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME);
1256 iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
1257 iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
1258 iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
1259
1260 #define SETUP_PRIV_SESSION_RD_ATTR(field)                               \
1261 do {                                                                    \
1262         priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \
1263         count++;                                                        \
1264 } while (0)
1265
1266
1267 #define SETUP_SESSION_RD_ATTR(field, param_flag)                        \
1268 do {                                                                    \
1269         if (tt->param_mask & param_flag) {                              \
1270                 priv->session_attrs[count] = &class_device_attr_sess_##field; \
1271                 count++;                                                \
1272         }                                                               \
1273 } while (0)
1274
1275 #define SETUP_CONN_RD_ATTR(field, param_flag)                           \
1276 do {                                                                    \
1277         if (tt->param_mask & param_flag) {                              \
1278                 priv->conn_attrs[count] = &class_device_attr_conn_##field; \
1279                 count++;                                                \
1280         }                                                               \
1281 } while (0)
1282
1283 #define SETUP_HOST_RD_ATTR(field, param_flag)                           \
1284 do {                                                                    \
1285         if (tt->host_param_mask & param_flag) {                         \
1286                 priv->host_attrs[count] = &class_device_attr_host_##field; \
1287                 count++;                                                \
1288         }                                                               \
1289 } while (0)
1290
1291 static int iscsi_session_match(struct attribute_container *cont,
1292                            struct device *dev)
1293 {
1294         struct iscsi_cls_session *session;
1295         struct Scsi_Host *shost;
1296         struct iscsi_internal *priv;
1297
1298         if (!iscsi_is_session_dev(dev))
1299                 return 0;
1300
1301         session = iscsi_dev_to_session(dev);
1302         shost = iscsi_session_to_shost(session);
1303         if (!shost->transportt)
1304                 return 0;
1305
1306         priv = to_iscsi_internal(shost->transportt);
1307         if (priv->session_cont.ac.class != &iscsi_session_class.class)
1308                 return 0;
1309
1310         return &priv->session_cont.ac == cont;
1311 }
1312
1313 static int iscsi_conn_match(struct attribute_container *cont,
1314                            struct device *dev)
1315 {
1316         struct iscsi_cls_session *session;
1317         struct iscsi_cls_conn *conn;
1318         struct Scsi_Host *shost;
1319         struct iscsi_internal *priv;
1320
1321         if (!iscsi_is_conn_dev(dev))
1322                 return 0;
1323
1324         conn = iscsi_dev_to_conn(dev);
1325         session = iscsi_dev_to_session(conn->dev.parent);
1326         shost = iscsi_session_to_shost(session);
1327
1328         if (!shost->transportt)
1329                 return 0;
1330
1331         priv = to_iscsi_internal(shost->transportt);
1332         if (priv->conn_cont.ac.class != &iscsi_connection_class.class)
1333                 return 0;
1334
1335         return &priv->conn_cont.ac == cont;
1336 }
1337
1338 static int iscsi_host_match(struct attribute_container *cont,
1339                             struct device *dev)
1340 {
1341         struct Scsi_Host *shost;
1342         struct iscsi_internal *priv;
1343
1344         if (!scsi_is_host_device(dev))
1345                 return 0;
1346
1347         shost = dev_to_shost(dev);
1348         if (!shost->transportt  ||
1349             shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
1350                 return 0;
1351
1352         priv = to_iscsi_internal(shost->transportt);
1353         return &priv->t.host_attrs.ac == cont;
1354 }
1355
1356 struct scsi_transport_template *
1357 iscsi_register_transport(struct iscsi_transport *tt)
1358 {
1359         struct iscsi_internal *priv;
1360         unsigned long flags;
1361         int count = 0, err;
1362
1363         BUG_ON(!tt);
1364
1365         priv = iscsi_if_transport_lookup(tt);
1366         if (priv)
1367                 return NULL;
1368
1369         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
1370         if (!priv)
1371                 return NULL;
1372         INIT_LIST_HEAD(&priv->list);
1373         priv->daemon_pid = -1;
1374         priv->iscsi_transport = tt;
1375         priv->t.user_scan = iscsi_user_scan;
1376
1377         priv->cdev.class = &iscsi_transport_class;
1378         snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
1379         err = class_device_register(&priv->cdev);
1380         if (err)
1381                 goto free_priv;
1382
1383         err = sysfs_create_group(&priv->cdev.kobj, &iscsi_transport_group);
1384         if (err)
1385                 goto unregister_cdev;
1386
1387         /* host parameters */
1388         priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
1389         priv->t.host_attrs.ac.class = &iscsi_host_class.class;
1390         priv->t.host_attrs.ac.match = iscsi_host_match;
1391         priv->t.host_size = sizeof(struct iscsi_host);
1392         transport_container_register(&priv->t.host_attrs);
1393
1394         SETUP_HOST_RD_ATTR(netdev, ISCSI_HOST_NETDEV_NAME);
1395         SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS);
1396         SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS);
1397         SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME);
1398         BUG_ON(count > ISCSI_HOST_ATTRS);
1399         priv->host_attrs[count] = NULL;
1400         count = 0;
1401
1402         /* connection parameters */
1403         priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
1404         priv->conn_cont.ac.class = &iscsi_connection_class.class;
1405         priv->conn_cont.ac.match = iscsi_conn_match;
1406         transport_container_register(&priv->conn_cont);
1407
1408         SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_MAX_RECV_DLENGTH);
1409         SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_MAX_XMIT_DLENGTH);
1410         SETUP_CONN_RD_ATTR(header_digest, ISCSI_HDRDGST_EN);
1411         SETUP_CONN_RD_ATTR(data_digest, ISCSI_DATADGST_EN);
1412         SETUP_CONN_RD_ATTR(ifmarker, ISCSI_IFMARKER_EN);
1413         SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN);
1414         SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS);
1415         SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT);
1416         SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN);
1417         SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
1418         SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
1419
1420         BUG_ON(count > ISCSI_CONN_ATTRS);
1421         priv->conn_attrs[count] = NULL;
1422         count = 0;
1423
1424         /* session parameters */
1425         priv->session_cont.ac.attrs = &priv->session_attrs[0];
1426         priv->session_cont.ac.class = &iscsi_session_class.class;
1427         priv->session_cont.ac.match = iscsi_session_match;
1428         transport_container_register(&priv->session_cont);
1429
1430         SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_INITIAL_R2T_EN);
1431         SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_MAX_R2T);
1432         SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_IMM_DATA_EN);
1433         SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_FIRST_BURST);
1434         SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_MAX_BURST);
1435         SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN);
1436         SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN);
1437         SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
1438         SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
1439         SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
1440         SETUP_SESSION_RD_ATTR(password, ISCSI_USERNAME);
1441         SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN);
1442         SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD);
1443         SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN);
1444         SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT);
1445         SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
1446
1447         BUG_ON(count > ISCSI_SESSION_ATTRS);
1448         priv->session_attrs[count] = NULL;
1449
1450         spin_lock_irqsave(&iscsi_transport_lock, flags);
1451         list_add(&priv->list, &iscsi_transports);
1452         spin_unlock_irqrestore(&iscsi_transport_lock, flags);
1453
1454         printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
1455         return &priv->t;
1456
1457 unregister_cdev:
1458         class_device_unregister(&priv->cdev);
1459 free_priv:
1460         kfree(priv);
1461         return NULL;
1462 }
1463 EXPORT_SYMBOL_GPL(iscsi_register_transport);
1464
1465 int iscsi_unregister_transport(struct iscsi_transport *tt)
1466 {
1467         struct iscsi_internal *priv;
1468         unsigned long flags;
1469
1470         BUG_ON(!tt);
1471
1472         mutex_lock(&rx_queue_mutex);
1473
1474         priv = iscsi_if_transport_lookup(tt);
1475         BUG_ON (!priv);
1476
1477         spin_lock_irqsave(&iscsi_transport_lock, flags);
1478         list_del(&priv->list);
1479         spin_unlock_irqrestore(&iscsi_transport_lock, flags);
1480
1481         transport_container_unregister(&priv->conn_cont);
1482         transport_container_unregister(&priv->session_cont);
1483         transport_container_unregister(&priv->t.host_attrs);
1484
1485         sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
1486         class_device_unregister(&priv->cdev);
1487         mutex_unlock(&rx_queue_mutex);
1488
1489         return 0;
1490 }
1491 EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
1492
1493 static __init int iscsi_transport_init(void)
1494 {
1495         int err;
1496
1497         printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
1498                 ISCSI_TRANSPORT_VERSION);
1499
1500         atomic_set(&iscsi_session_nr, 0);
1501
1502         err = class_register(&iscsi_transport_class);
1503         if (err)
1504                 return err;
1505
1506         err = transport_class_register(&iscsi_host_class);
1507         if (err)
1508                 goto unregister_transport_class;
1509
1510         err = transport_class_register(&iscsi_connection_class);
1511         if (err)
1512                 goto unregister_host_class;
1513
1514         err = transport_class_register(&iscsi_session_class);
1515         if (err)
1516                 goto unregister_conn_class;
1517
1518         nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx, NULL,
1519                         THIS_MODULE);
1520         if (!nls) {
1521                 err = -ENOBUFS;
1522                 goto unregister_session_class;
1523         }
1524
1525         iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
1526         if (!iscsi_eh_timer_workq)
1527                 goto release_nls;
1528
1529         return 0;
1530
1531 release_nls:
1532         sock_release(nls->sk_socket);
1533 unregister_session_class:
1534         transport_class_unregister(&iscsi_session_class);
1535 unregister_conn_class:
1536         transport_class_unregister(&iscsi_connection_class);
1537 unregister_host_class:
1538         transport_class_unregister(&iscsi_host_class);
1539 unregister_transport_class:
1540         class_unregister(&iscsi_transport_class);
1541         return err;
1542 }
1543
1544 static void __exit iscsi_transport_exit(void)
1545 {
1546         destroy_workqueue(iscsi_eh_timer_workq);
1547         sock_release(nls->sk_socket);
1548         transport_class_unregister(&iscsi_connection_class);
1549         transport_class_unregister(&iscsi_session_class);
1550         transport_class_unregister(&iscsi_host_class);
1551         class_unregister(&iscsi_transport_class);
1552 }
1553
1554 module_init(iscsi_transport_init);
1555 module_exit(iscsi_transport_exit);
1556
1557 MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
1558               "Dmitry Yusupov <dmitry_yus@yahoo.com>, "
1559               "Alex Aizman <itn780@yahoo.com>");
1560 MODULE_DESCRIPTION("iSCSI Transport Interface");
1561 MODULE_LICENSE("GPL");
1562 MODULE_VERSION(ISCSI_TRANSPORT_VERSION);